M: Richard Genoud <richard.genoud@gmail.com>
S: Maintained
F: drivers/tty/serial/atmel_serial.c
-F: include/linux/atmel_serial.h
+F: drivers/tty/serial/atmel_serial.h
MICROCHIP / ATMEL DMA DRIVER
M: Ludovic Desroches <ludovic.desroches@microchip.com>
*/
rc = driver_create_file(&(hvcs_vio_driver.driver), &driver_attr_rescan);
if (rc)
- pr_warning("HVCS: Failed to create rescan file (err %d)\n", rc);
+ pr_warn("HVCS: Failed to create rescan file (err %d)\n", rc);
return 0;
}
/**
* struct gsm_mux_net - network interface
* @struct gsm_dlci* dlci
- * @struct net_device_stats stats;
*
* Created when net interface is initialized.
**/
struct gsm_mux_net {
struct kref ref;
struct gsm_dlci *dlci;
- struct net_device_stats stats;
};
-#define STATS(net) (((struct gsm_mux_net *)netdev_priv(net))->stats)
-
/*
* Each block of data we have queued to go out is in the form of
* a gsm_msg which holds everything we need in a link layer independent
return 0;
}
-static struct net_device_stats *gsm_mux_net_get_stats(struct net_device *net)
-{
- return &((struct gsm_mux_net *)netdev_priv(net))->stats;
-}
static void dlci_net_free(struct gsm_dlci *dlci)
{
if (!dlci->net) {
muxnet_get(mux_net);
skb_queue_head(&dlci->skb_list, skb);
- STATS(net).tx_packets++;
- STATS(net).tx_bytes += skb->len;
+ net->stats.tx_packets++;
+ net->stats.tx_bytes += skb->len;
gsm_dlci_data_kick(dlci);
/* And tell the kernel when the last transmit started. */
netif_trans_update(net);
dev_dbg(&net->dev, "Tx timed out.\n");
/* Update statistics */
- STATS(net).tx_errors++;
+ net->stats.tx_errors++;
}
static void gsm_mux_rx_netchar(struct gsm_dlci *dlci,
skb = dev_alloc_skb(size + NET_IP_ALIGN);
if (!skb) {
/* We got no receive buffer. */
- STATS(net).rx_dropped++;
+ net->stats.rx_dropped++;
muxnet_put(mux_net);
return;
}
netif_rx(skb);
/* update out statistics */
- STATS(net).rx_packets++;
- STATS(net).rx_bytes += size;
+ net->stats.rx_packets++;
+ net->stats.rx_bytes += size;
muxnet_put(mux_net);
return;
}
.ndo_stop = gsm_mux_net_close,
.ndo_start_xmit = gsm_mux_net_start_xmit,
.ndo_tx_timeout = gsm_mux_net_tx_timeout,
- .ndo_get_stats = gsm_mux_net_get_stats,
};
net->netdev_ops = &gsm_netdev_ops;
static void pty_flush_buffer(struct tty_struct *tty)
{
struct tty_struct *to = tty->link;
- struct tty_ldisc *ld;
if (!to)
return;
- ld = tty_ldisc_ref(to);
- tty_buffer_flush(to, ld);
- if (ld)
- tty_ldisc_deref(ld);
-
+ tty_buffer_flush(to, NULL);
if (to->packet) {
spin_lock_irq(&tty->ctrl_lock);
tty->ctrl_status |= TIOCPKT_FLUSHWRITE;
spin_unlock_irq(&i->lock);
irq_flags |= up->port.irqflags;
ret = request_irq(up->port.irq, serial8250_interrupt,
- irq_flags, "serial", i);
+ irq_flags, dev_name(up->port.dev), i);
if (ret < 0)
serial_do_unlink(i, up);
}
}
data->rst = devm_reset_control_get_optional(dev, NULL);
- if (IS_ERR(data->rst) && PTR_ERR(data->rst) == -EPROBE_DEFER) {
- err = -EPROBE_DEFER;
+ if (IS_ERR(data->rst)) {
+ err = PTR_ERR(data->rst);
goto err_pclk;
}
- if (!IS_ERR(data->rst))
- reset_control_deassert(data->rst);
+ reset_control_deassert(data->rst);
dw8250_quirks(p, data);
return 0;
err_reset:
- if (!IS_ERR(data->rst))
- reset_control_assert(data->rst);
+ reset_control_assert(data->rst);
err_pclk:
if (!IS_ERR(data->pclk))
serial8250_unregister_port(data->line);
- if (!IS_ERR(data->rst))
- reset_control_assert(data->rst);
+ reset_control_assert(data->rst);
if (!IS_ERR(data->pclk))
clk_disable_unprepare(data->pclk);
module_pci_driver(exar_pci_driver);
MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Exar Serial Dricer");
+MODULE_DESCRIPTION("Exar Serial Driver");
MODULE_AUTHOR("Sudip Mukherjee <sudip.mukherjee@codethink.co.uk>");
* The IRQ setting mode of F81866 is not the same with F81216 series.
* Level/Low: IRQ_MODE0:0, IRQ_MODE1:0
* Edge/High: IRQ_MODE0:1, IRQ_MODE1:0
+ *
+ * Clock speeds for UART (register F2h)
+ * 00: 1.8432MHz.
+ * 01: 18.432MHz.
+ * 10: 24MHz.
+ * 11: 14.769MHz.
*/
#define F81866_IRQ_MODE 0xf0
#define F81866_IRQ_SHARE BIT(0)
#define F81866_LDN_LOW 0x10
#define F81866_LDN_HIGH 0x16
+#define F81866_UART_CLK 0xF2
+#define F81866_UART_CLK_MASK (BIT(1) | BIT(0))
+#define F81866_UART_CLK_1_8432MHZ 0
+#define F81866_UART_CLK_14_769MHZ (BIT(1) | BIT(0))
+#define F81866_UART_CLK_18_432MHZ BIT(0)
+#define F81866_UART_CLK_24MHZ BIT(1)
+
struct fintek_8250 {
u16 pid;
u16 base_port;
}
}
-static int probe_setup_port(struct fintek_8250 *pdata, u16 io_address,
- unsigned int irq)
+static void fintek_8250_goto_highspeed(struct uart_8250_port *uart,
+ struct fintek_8250 *pdata)
+{
+ sio_write_reg(pdata, LDN, pdata->index);
+
+ switch (pdata->pid) {
+ case CHIP_ID_F81866: /* set uart clock for high speed serial mode */
+ sio_write_mask_reg(pdata, F81866_UART_CLK,
+ F81866_UART_CLK_MASK,
+ F81866_UART_CLK_14_769MHZ);
+
+ uart->port.uartclk = 921600 * 16;
+ break;
+ default: /* leave clock speed untouched */
+ break;
+ }
+}
+
+static int probe_setup_port(struct fintek_8250 *pdata,
+ struct uart_8250_port *uart)
{
static const u16 addr[] = {0x4e, 0x2e};
static const u8 keys[] = {0x77, 0xa0, 0x87, 0x67};
sio_write_reg(pdata, LDN, k);
aux = sio_read_reg(pdata, IO_ADDR1);
aux |= sio_read_reg(pdata, IO_ADDR2) << 8;
- if (aux != io_address)
+ if (aux != uart->port.iobase)
continue;
pdata->index = k;
- irq_data = irq_get_irq_data(irq);
+ irq_data = irq_get_irq_data(uart->port.irq);
if (irq_data)
level_mode =
irqd_is_level_type(irq_data);
fintek_8250_set_irq_mode(pdata, level_mode);
fintek_8250_set_max_fifo(pdata);
+ fintek_8250_goto_highspeed(uart, pdata);
+
fintek_8250_exit_key(addr[i]);
return 0;
struct fintek_8250 *pdata;
struct fintek_8250 probe_data;
- if (probe_setup_port(&probe_data, uart->port.iobase, uart->port.irq))
+ if (probe_setup_port(&probe_data, uart))
return -ENODEV;
pdata = devm_kzalloc(uart->port.dev, sizeof(*pdata), GFP_KERNEL);
console (the system console is the device which receives all kernel
messages and warnings and which allows logins in single user mode).
+config SERIAL_UARTLITE_NR_UARTS
+ int "Maximum number of uartlite serial ports"
+ depends on SERIAL_UARTLITE
+ range 1 256
+ default 1
+ help
+ Set this to the number of uartlites in your system, or the number
+ you think you might implement.
+
config SERIAL_SUNCORE
bool
depends on SPARC
bool "Altera JTAG UART console support"
depends on SERIAL_ALTERA_JTAGUART=y
select SERIAL_CORE_CONSOLE
+ select SERIAL_EARLYCON
help
Enable a Altera JTAG UART port to be the system console.
#define ALTERA_JTAGUART_CONSOLE (&altera_jtaguart_console)
+static void altera_jtaguart_earlycon_write(struct console *co, const char *s,
+ unsigned int count)
+{
+ struct earlycon_device *dev = co->data;
+
+ uart_console_write(&dev->port, s, count, altera_jtaguart_console_putc);
+}
+
+static int __init altera_jtaguart_earlycon_setup(struct earlycon_device *dev,
+ const char *options)
+{
+ if (!dev->port.membase)
+ return -ENODEV;
+
+ dev->con->write = altera_jtaguart_earlycon_write;
+ return 0;
+}
+
+OF_EARLYCON_DECLARE(juart, "altr,juart-1.0", altera_jtaguart_earlycon_setup);
+
#else
#define ALTERA_JTAGUART_CONSOLE NULL
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/atmel_pdc.h>
-#include <linux/atmel_serial.h>
#include <linux/uaccess.h>
#include <linux/platform_data/atmel.h>
#include <linux/timer.h>
#include <linux/serial_core.h>
#include "serial_mctrl_gpio.h"
+#include "atmel_serial.h"
static void atmel_start_rx(struct uart_port *port);
static void atmel_stop_rx(struct uart_port *port);
/*
* at91: 6 USARTs and one DBGU port (SAM9260)
* avr32: 4
+ * samx7: 3 USARTs and 5 UARTs
*/
-#define ATMEL_MAX_UART 7
+#define ATMEL_MAX_UART 8
/*
* We wrap our port structure around the generic uart_port.
unsigned int pending_status;
spinlock_t lock_suspended;
+#ifdef CONFIG_PM
struct {
u32 cr;
u32 mr;
u32 fmr;
u32 fimr;
} cache;
+#endif
int (*prepare_rx)(struct uart_port *port);
int (*prepare_tx)(struct uart_port *port);
#include <linux/tty_flip.h>
#include <linux/types.h>
-#include <linux/atomic.h>
+#include <linux/refcount.h>
#include <asm/io.h>
#include <asm/war.h>
struct sbd_duart {
struct sbd_port sport[2];
unsigned long mapctrl;
- atomic_t map_guard;
+ refcount_t map_guard;
};
#define to_sport(uport) container_of(uport, struct sbd_port, port)
{
struct sbd_port *sport = to_sport(uport);
struct sbd_duart *duart = sport->duart;
- int map_guard;
iounmap(sport->memctrl);
sport->memctrl = NULL;
iounmap(uport->membase);
uport->membase = NULL;
- map_guard = atomic_add_return(-1, &duart->map_guard);
- if (!map_guard)
+ if(refcount_dec_and_test(&duart->map_guard))
release_mem_region(duart->mapctrl, DUART_CHANREG_SPACING);
release_mem_region(uport->mapbase, DUART_CHANREG_SPACING);
}
{
const char *err = KERN_ERR "sbd: Unable to reserve MMIO resource\n";
struct sbd_duart *duart = to_sport(uport)->duart;
- int map_guard;
int ret = 0;
if (!request_mem_region(uport->mapbase, DUART_CHANREG_SPACING,
printk(err);
return -EBUSY;
}
- map_guard = atomic_add_return(1, &duart->map_guard);
- if (map_guard == 1) {
+ refcount_inc(&duart->map_guard);
+ if (refcount_read(&duart->map_guard) == 1) {
if (!request_mem_region(duart->mapctrl, DUART_CHANREG_SPACING,
"sb1250-duart")) {
- atomic_add(-1, &duart->map_guard);
+ refcount_dec(&duart->map_guard);
printk(err);
ret = -EBUSY;
}
if (!ret) {
ret = sbd_map_port(uport);
if (ret) {
- map_guard = atomic_add_return(-1, &duart->map_guard);
- if (!map_guard)
+ if (refcount_dec_and_test(&duart->map_guard))
release_mem_region(duart->mapctrl,
DUART_CHANREG_SPACING);
}
int flow = 'n';
int ret = 0;
- if (!state)
- return -1;
-
tport = &state->port;
mutex_lock(&tport->mutex);
struct uart_port *port;
int ret = -1;
- if (state) {
- port = uart_port_ref(state);
- if (port) {
- ret = port->ops->poll_get_char(port);
- uart_port_deref(port);
- }
+ port = uart_port_ref(state);
+ if (port) {
+ ret = port->ops->poll_get_char(port);
+ uart_port_deref(port);
}
+
return ret;
}
struct uart_state *state = drv->state + line;
struct uart_port *port;
- if (!state)
- return;
-
port = uart_port_ref(state);
if (!port)
return;
dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
+ sci_request_dma(port);
+
ret = sci_request_irq(s);
- if (unlikely(ret < 0))
+ if (unlikely(ret < 0)) {
+ sci_free_dma(port);
return ret;
-
- sci_request_dma(port);
+ }
return 0;
}
}
#endif
- sci_free_dma(port);
sci_free_irq(s);
+ sci_free_dma(port);
}
static int sci_sck_calc(struct sci_port *s, unsigned int bps,
#define ULITE_NAME "ttyUL"
#define ULITE_MAJOR 204
#define ULITE_MINOR 187
-#define ULITE_NR_UARTS 16
+#define ULITE_NR_UARTS CONFIG_SERIAL_UARTLITE_NR_UARTS
/* ---------------------------------------------------------------------
* Register definitions
#include <linux/io.h>
#include <linux/of.h>
#include <linux/module.h>
+#include <linux/pm_runtime.h>
#define CDNS_UART_TTY_NAME "ttyPS"
#define CDNS_UART_NAME "xuartps"
#define CDNS_UART_BDIV_MIN 4
#define CDNS_UART_BDIV_MAX 255
#define CDNS_UART_CD_MAX 65535
+#define UART_AUTOSUSPEND_TIMEOUT 3000
/**
* struct cdns_uart - device data
static void cdns_uart_pm(struct uart_port *port, unsigned int state,
unsigned int oldstate)
{
- struct cdns_uart *cdns_uart = port->private_data;
-
switch (state) {
case UART_PM_STATE_OFF:
- clk_disable(cdns_uart->uartclk);
- clk_disable(cdns_uart->pclk);
+ pm_runtime_mark_last_busy(port->dev);
+ pm_runtime_put_autosuspend(port->dev);
break;
default:
- clk_enable(cdns_uart->pclk);
- clk_enable(cdns_uart->uartclk);
+ pm_runtime_get_sync(port->dev);
break;
}
}
* the suspend.
*/
uart_suspend_port(&cdns_uart_uart_driver, port);
- if (console_suspend_enabled && !may_wake) {
- struct cdns_uart *cdns_uart = port->private_data;
-
- clk_disable(cdns_uart->uartclk);
- clk_disable(cdns_uart->pclk);
- } else {
+ if (!(console_suspend_enabled && !may_wake)) {
unsigned long flags = 0;
spin_lock_irqsave(&port->lock, flags);
ctrl_reg |= CDNS_UART_CR_TX_EN | CDNS_UART_CR_RX_EN;
writel(ctrl_reg, port->membase + CDNS_UART_CR);
+ clk_disable(cdns_uart->uartclk);
+ clk_disable(cdns_uart->pclk);
spin_unlock_irqrestore(&port->lock, flags);
} else {
spin_lock_irqsave(&port->lock, flags);
return uart_resume_port(&cdns_uart_uart_driver, port);
}
#endif /* ! CONFIG_PM_SLEEP */
+static int __maybe_unused cdns_runtime_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct uart_port *port = platform_get_drvdata(pdev);
+ struct cdns_uart *cdns_uart = port->private_data;
+
+ clk_disable(cdns_uart->uartclk);
+ clk_disable(cdns_uart->pclk);
+ return 0;
+};
+
+static int __maybe_unused cdns_runtime_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct uart_port *port = platform_get_drvdata(pdev);
+ struct cdns_uart *cdns_uart = port->private_data;
-static SIMPLE_DEV_PM_OPS(cdns_uart_dev_pm_ops, cdns_uart_suspend,
- cdns_uart_resume);
+ clk_enable(cdns_uart->pclk);
+ clk_enable(cdns_uart->uartclk);
+ return 0;
+};
+
+static const struct dev_pm_ops cdns_uart_dev_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(cdns_uart_suspend, cdns_uart_resume)
+ SET_RUNTIME_PM_OPS(cdns_runtime_suspend,
+ cdns_runtime_resume, NULL)
+};
static const struct cdns_platform_data zynqmp_uart_def = {
.quirks = CDNS_UART_RXBS_SUPPORT, };
cdns_uart_data->port = port;
platform_set_drvdata(pdev, port);
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(&pdev->dev, UART_AUTOSUSPEND_TIMEOUT);
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_set_active(&pdev->dev);
+
rc = uart_add_one_port(&cdns_uart_uart_driver, port);
if (rc) {
dev_err(&pdev->dev,
&cdns_uart_data->clk_rate_change_nb);
#endif
err_out_clk_disable:
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_dont_use_autosuspend(&pdev->dev);
clk_unprepare(cdns_uart_data->uartclk);
err_out_clk_dis_pclk:
clk_unprepare(cdns_uart_data->pclk);
port->mapbase = 0;
clk_unprepare(cdns_uart_data->uartclk);
clk_unprepare(cdns_uart_data->pclk);
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_dont_use_autosuspend(&pdev->dev);
return rc;
}
flags &= ASYNC_DEPRECATED;
if (flags && __ratelimit(&depr_flags))
- pr_warning("%s: '%s' is using deprecated serial flags (with no effect): %.8x\n",
- __func__, get_task_comm(comm, current), flags);
+ pr_warn("%s: '%s' is using deprecated serial flags (with no effect): %.8x\n",
+ __func__, get_task_comm(comm, current), flags);
}
/*
if (!serdev || !serdev->ops->write_wakeup)
return;
- serdev->ops->write_wakeup(ctrl->serdev);
+ serdev->ops->write_wakeup(serdev);
}
static inline int serdev_controller_receive_buf(struct serdev_controller *ctrl,
if (!serdev || !serdev->ops->receive_buf)
return -EINVAL;
- return serdev->ops->receive_buf(ctrl->serdev, data, count);
+ return serdev->ops->receive_buf(serdev, data, count);
}
#if IS_ENABLED(CONFIG_SERIAL_DEV_BUS)