diff options
Diffstat (limited to 'drivers/tty/serial')
77 files changed, 967 insertions, 926 deletions
diff --git a/drivers/tty/serial/21285.c b/drivers/tty/serial/21285.c index 185462fd959c..d756fcc884cb 100644 --- a/drivers/tty/serial/21285.c +++ b/drivers/tty/serial/21285.c @@ -117,7 +117,8 @@ static void serial21285_stop_rx(struct uart_port *port) static irqreturn_t serial21285_rx_chars(int irq, void *dev_id) { struct uart_port *port = dev_id; - unsigned int status, ch, flag, rxs, max_count = 256; + unsigned int status, rxs, max_count = 256; + u8 ch, flag; status = *CSR_UARTFLG; while (!(status & 0x10) && max_count--) { diff --git a/drivers/tty/serial/8250/8250_bcm7271.c b/drivers/tty/serial/8250/8250_bcm7271.c index d4b05d7ad9e8..aa5aff046756 100644 --- a/drivers/tty/serial/8250/8250_bcm7271.c +++ b/drivers/tty/serial/8250/8250_bcm7271.c @@ -1042,7 +1042,7 @@ static int brcmuart_probe(struct platform_device *pdev) dev_dbg(dev, "DMA is %senabled\n", priv->dma_enabled ? "" : "not "); memset(&up, 0, sizeof(up)); - up.port.type = PORT_16550A; + up.port.type = PORT_BCM7271; up.port.uartclk = clk_rate; up.port.dev = dev; up.port.mapbase = mapbase; @@ -1056,8 +1056,6 @@ static int brcmuart_probe(struct platform_device *pdev) | UPF_FIXED_PORT | UPF_FIXED_TYPE; up.port.dev = dev; up.port.private_data = priv; - up.capabilities = UART_CAP_FIFO | UART_CAP_AFE; - up.port.fifosize = 32; /* Check for a fixed line number */ ret = of_alias_get_id(np, "serial"); diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 7db51781289e..f4cafca1a7da 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -523,7 +523,10 @@ static int dw8250_probe(struct platform_device *pdev) if (!regs) return dev_err_probe(dev, -EINVAL, "no registers defined\n"); - irq = platform_get_irq(pdev, 0); + irq = platform_get_irq_optional(pdev, 0); + /* no interrupt -> fall back to polling */ + if (irq == -ENXIO) + irq = 0; if (irq < 0) return irq; diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c index 4299a8bd83d9..9837a27739fd 100644 --- a/drivers/tty/serial/8250/8250_early.c +++ b/drivers/tty/serial/8250/8250_early.c @@ -27,7 +27,6 @@ #include <linux/init.h> #include <linux/console.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/serial_reg.h> #include <linux/serial.h> #include <linux/serial_8250.h> diff --git a/drivers/tty/serial/8250/8250_ingenic.c b/drivers/tty/serial/8250/8250_ingenic.c index 617b8ce60d6b..4c4c4da73ad0 100644 --- a/drivers/tty/serial/8250/8250_ingenic.c +++ b/drivers/tty/serial/8250/8250_ingenic.c @@ -13,7 +13,6 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/of_fdt.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/serial_8250.h> #include <linux/serial_core.h> diff --git a/drivers/tty/serial/8250/8250_men_mcb.c b/drivers/tty/serial/8250/8250_men_mcb.c index f46ca13ff4aa..dc9e093b1cb3 100644 --- a/drivers/tty/serial/8250/8250_men_mcb.c +++ b/drivers/tty/serial/8250/8250_men_mcb.c @@ -12,11 +12,42 @@ #define MEN_UART_ID_Z057 0x39 #define MEN_UART_ID_Z125 0x7d -#define MEN_UART_MEM_SIZE 0x10 +/* + * IP Cores Z025 and Z057 can have up to 4 UART + * The UARTs available are stored in a global + * register saved in physical address + 0x40 + * Is saved as follows: + * + * 7 0 + * +------+-------+-------+-------+-------+-------+-------+-------+ + * |UART4 | UART3 | UART2 | UART1 | U4irq | U3irq | U2irq | U1irq | + * +------+-------+-------+-------+-------+-------+-------+-------+ + */ +#define MEN_UART1_MASK 0x01 +#define MEN_UART2_MASK 0x02 +#define MEN_UART3_MASK 0x04 +#define MEN_UART4_MASK 0x08 + +#define MEN_Z125_UARTS_AVAILABLE 0x01 + +#define MEN_Z025_MAX_UARTS 4 +#define MEN_UART_MEM_SIZE 0x10 +#define MEM_UART_REGISTER_SIZE 0x01 +#define MEN_Z025_REGISTER_OFFSET 0x40 + +#define MEN_UART1_OFFSET 0 +#define MEN_UART2_OFFSET (MEN_UART1_OFFSET + MEN_UART_MEM_SIZE) +#define MEN_UART3_OFFSET (MEN_UART2_OFFSET + MEN_UART_MEM_SIZE) +#define MEN_UART4_OFFSET (MEN_UART3_OFFSET + MEN_UART_MEM_SIZE) + +#define MEN_READ_REGISTER(addr) readb(addr) + +#define MAX_PORTS 4 struct serial_8250_men_mcb_data { - struct uart_8250_port uart; - int line; + int num_ports; + int line[MAX_PORTS]; + unsigned int offset[MAX_PORTS]; }; /* @@ -37,10 +68,10 @@ static u32 men_lookup_uartclk(struct mcb_device *mdev) clkval = 1041666; else if (strncmp(mdev->bus->name, "F216", 4) == 0) clkval = 1843200; - else if (strncmp(mdev->bus->name, "G215", 4) == 0) - clkval = 1843200; else if (strncmp(mdev->bus->name, "F210", 4) == 0) clkval = 115200; + else if (strstr(mdev->bus->name, "215")) + clkval = 1843200; else dev_info(&mdev->dev, "board not detected, using default uartclk\n"); @@ -50,16 +81,98 @@ static u32 men_lookup_uartclk(struct mcb_device *mdev) return clkval; } -static int get_num_ports(struct mcb_device *mdev, - void __iomem *membase) +static int read_uarts_available_from_register(struct resource *mem_res, + u8 *uarts_available) +{ + void __iomem *mem; + int reg_value; + + if (!request_mem_region(mem_res->start + MEN_Z025_REGISTER_OFFSET, + MEM_UART_REGISTER_SIZE, KBUILD_MODNAME)) { + return -EBUSY; + } + + mem = ioremap(mem_res->start + MEN_Z025_REGISTER_OFFSET, + MEM_UART_REGISTER_SIZE); + if (!mem) { + release_mem_region(mem_res->start + MEN_Z025_REGISTER_OFFSET, + MEM_UART_REGISTER_SIZE); + return -ENOMEM; + } + + reg_value = MEN_READ_REGISTER(mem); + + iounmap(mem); + + release_mem_region(mem_res->start + MEN_Z025_REGISTER_OFFSET, + MEM_UART_REGISTER_SIZE); + + *uarts_available = reg_value >> 4; + + return 0; +} + +static int read_serial_data(struct mcb_device *mdev, + struct resource *mem_res, + struct serial_8250_men_mcb_data *serial_data) +{ + u8 uarts_available; + int count = 0; + int mask; + int res; + int i; + + res = read_uarts_available_from_register(mem_res, &uarts_available); + if (res < 0) + return res; + + for (i = 0; i < MAX_PORTS; i++) { + mask = 0x1 << i; + switch (uarts_available & mask) { + case MEN_UART1_MASK: + serial_data->offset[count] = MEN_UART1_OFFSET; + count++; + break; + case MEN_UART2_MASK: + serial_data->offset[count] = MEN_UART2_OFFSET; + count++; + break; + case MEN_UART3_MASK: + serial_data->offset[count] = MEN_UART3_OFFSET; + count++; + break; + case MEN_UART4_MASK: + serial_data->offset[count] = MEN_UART4_OFFSET; + count++; + break; + default: + return -EINVAL; + } + } + + if (count <= 0 || count > MAX_PORTS) { + dev_err(&mdev->dev, "unexpected number of ports: %u\n", + count); + return -ENODEV; + } + + serial_data->num_ports = count; + + return 0; +} + +static int init_serial_data(struct mcb_device *mdev, + struct resource *mem_res, + struct serial_8250_men_mcb_data *serial_data) { switch (mdev->id) { case MEN_UART_ID_Z125: - return 1U; + serial_data->num_ports = 1; + serial_data->offset[0] = 0; + return 0; case MEN_UART_ID_Z025: - return readb(membase) >> 4; case MEN_UART_ID_Z057: - return 4U; + return read_serial_data(mdev, mem_res, serial_data); default: dev_err(&mdev->dev, "no supported device!\n"); return -ENODEV; @@ -69,62 +182,54 @@ static int get_num_ports(struct mcb_device *mdev, static int serial_8250_men_mcb_probe(struct mcb_device *mdev, const struct mcb_device_id *id) { + struct uart_8250_port uart; struct serial_8250_men_mcb_data *data; struct resource *mem; - int num_ports; int i; - void __iomem *membase; + int res; mem = mcb_get_resource(mdev, IORESOURCE_MEM); if (mem == NULL) return -ENXIO; - membase = devm_ioremap_resource(&mdev->dev, mem); - if (IS_ERR(membase)) - return PTR_ERR_OR_ZERO(membase); - - num_ports = get_num_ports(mdev, membase); - dev_dbg(&mdev->dev, "found a 16z%03u with %u ports\n", - mdev->id, num_ports); - - if (num_ports <= 0 || num_ports > 4) { - dev_err(&mdev->dev, "unexpected number of ports: %u\n", - num_ports); - return -ENODEV; - } - - data = devm_kcalloc(&mdev->dev, num_ports, + data = devm_kzalloc(&mdev->dev, sizeof(struct serial_8250_men_mcb_data), GFP_KERNEL); if (!data) return -ENOMEM; + res = init_serial_data(mdev, mem, data); + if (res < 0) + return res; + + dev_dbg(&mdev->dev, "found a 16z%03u with %u ports\n", + mdev->id, data->num_ports); + mcb_set_drvdata(mdev, data); - for (i = 0; i < num_ports; i++) { - data[i].uart.port.dev = mdev->dma_dev; - spin_lock_init(&data[i].uart.port.lock); - - data[i].uart.port.type = PORT_16550; - data[i].uart.port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ - | UPF_FIXED_TYPE; - data[i].uart.port.iotype = UPIO_MEM; - data[i].uart.port.uartclk = men_lookup_uartclk(mdev); - data[i].uart.port.regshift = 0; - data[i].uart.port.irq = mcb_get_irq(mdev); - data[i].uart.port.membase = membase; - data[i].uart.port.fifosize = 60; - data[i].uart.port.mapbase = (unsigned long) mem->start - + i * MEN_UART_MEM_SIZE; - data[i].uart.port.iobase = data[i].uart.port.mapbase; + for (i = 0; i < data->num_ports; i++) { + memset(&uart, 0, sizeof(struct uart_8250_port)); + spin_lock_init(&uart.port.lock); + + uart.port.flags = UPF_SKIP_TEST | + UPF_SHARE_IRQ | + UPF_BOOT_AUTOCONF | + UPF_IOREMAP; + uart.port.iotype = UPIO_MEM; + uart.port.uartclk = men_lookup_uartclk(mdev); + uart.port.irq = mcb_get_irq(mdev); + uart.port.mapbase = (unsigned long) mem->start + + data->offset[i]; /* ok, register the port */ - data[i].line = serial8250_register_8250_port(&data[i].uart); - if (data[i].line < 0) { + res = serial8250_register_8250_port(&uart); + if (res < 0) { dev_err(&mdev->dev, "unable to register UART port\n"); - return data[i].line; + return res; } - dev_info(&mdev->dev, "found MCB UART: ttyS%d\n", data[i].line); + + data->line[i] = res; + dev_info(&mdev->dev, "found MCB UART: ttyS%d\n", data->line[i]); } return 0; @@ -132,20 +237,14 @@ static int serial_8250_men_mcb_probe(struct mcb_device *mdev, static void serial_8250_men_mcb_remove(struct mcb_device *mdev) { - int num_ports, i; + int i; struct serial_8250_men_mcb_data *data = mcb_get_drvdata(mdev); if (!data) return; - num_ports = get_num_ports(mdev, data[0].uart.port.membase); - if (num_ports <= 0 || num_ports > 4) { - dev_err(&mdev->dev, "error retrieving number of ports!\n"); - return; - } - - for (i = 0; i < num_ports; i++) - serial8250_unregister_port(data[i].line); + for (i = 0; i < data->num_ports; i++) + serial8250_unregister_port(data->line[i]); } static const struct mcb_device_id serial_8250_men_mcb_ids[] = { @@ -159,7 +258,6 @@ MODULE_DEVICE_TABLE(mcb, serial_8250_men_mcb_ids); static struct mcb_driver mcb_driver = { .driver = { .name = "8250_men_mcb", - .owner = THIS_MODULE, }, .probe = serial_8250_men_mcb_probe, .remove = serial_8250_men_mcb_remove, diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index d48a82f1634e..26dd089d8e82 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -18,7 +18,6 @@ #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/of_gpio.h> #include <linux/of_irq.h> #include <linux/delay.h> diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index d2d547b5da95..62a9bd30b4db 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -67,6 +67,8 @@ static const struct pci_device_id pci_use_msi[] = { 0xA000, 0x1000) }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9922, 0xA000, 0x1000) }, + { PCI_DEVICE_SUB(PCI_VENDOR_ID_ASIX, PCI_DEVICE_ID_ASIX_AX99100, + 0xA000, 0x1000) }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_HP_3PAR, PCI_DEVICE_ID_HPE_PCI_SERIAL, PCI_ANY_ID, PCI_ANY_ID) }, { } @@ -5557,6 +5559,14 @@ static const struct pci_device_id serial_pci_tbl[] = { { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865, 0xA000, 0x3004, 0, 0, pbn_b0_bt_4_115200 }, + + /* + * ASIX AX99100 PCIe to Multi I/O Controller + */ + { PCI_VENDOR_ID_ASIX, PCI_DEVICE_ID_ASIX_AX99100, + 0xA000, 0x1000, + 0, 0, pbn_b0_1_115200 }, + /* Intel CE4100 */ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CE4100_UART, PCI_ANY_ID, PCI_ANY_ID, 0, 0, diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 483bb552cdc4..fb891b67968f 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -322,6 +322,14 @@ static const struct serial8250_config uart_config[] = { .rxtrig_bytes = {2, 66, 130, 194}, .flags = UART_CAP_FIFO, }, + [PORT_BCM7271] = { + .name = "Broadcom BCM7271 UART", + .fifo_size = 32, + .tx_loadsz = 32, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01, + .rxtrig_bytes = {1, 8, 16, 30}, + .flags = UART_CAP_FIFO | UART_CAP_AFE, + }, }; /* Uart divisor latch read */ @@ -1703,8 +1711,7 @@ static void serial8250_enable_ms(struct uart_port *port) void serial8250_read_char(struct uart_8250_port *up, u16 lsr) { struct uart_port *port = &up->port; - unsigned char ch; - char flag = TTY_NORMAL; + u8 ch, flag = TTY_NORMAL; if (likely(lsr & UART_LSR_DR)) ch = serial_in(up, UART_RX); diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c index 28b341f602c6..a5b3ea27fc90 100644 --- a/drivers/tty/serial/8250/8250_pxa.c +++ b/drivers/tty/serial/8250/8250_pxa.c @@ -183,6 +183,7 @@ static int __init early_serial_pxa_setup(struct earlycon_device *device, return early_serial8250_setup(device, NULL); } OF_EARLYCON_DECLARE(early_pxa, "mrvl,pxa-uart", early_serial_pxa_setup); +OF_EARLYCON_DECLARE(mmp, "mrvl,mmp-uart", early_serial_pxa_setup); #endif MODULE_AUTHOR("Sergei Ianovich"); diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index d4123469583d..138abbc89738 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile @@ -41,7 +41,7 @@ obj-$(CONFIG_SERIAL_HS_LPC32XX) += lpc32xx_hs.o obj-$(CONFIG_SERIAL_DZ) += dz.o obj-$(CONFIG_SERIAL_ZS) += zs.o obj-$(CONFIG_SERIAL_SH_SCI) += sh-sci.o -obj-$(CONFIG_SERIAL_CPM) += cpm_uart/ +obj-$(CONFIG_SERIAL_CPM) += cpm_uart.o obj-$(CONFIG_SERIAL_IMX) += imx.o obj-$(CONFIG_SERIAL_IMX_EARLYCON) += imx_earlycon.o obj-$(CONFIG_SERIAL_MPC52xx) += mpc52xx_uart.o diff --git a/drivers/tty/serial/altera_jtaguart.c b/drivers/tty/serial/altera_jtaguart.c index 9f843d1cee40..5fab4c978891 100644 --- a/drivers/tty/serial/altera_jtaguart.c +++ b/drivers/tty/serial/altera_jtaguart.c @@ -110,8 +110,8 @@ static void altera_jtaguart_set_termios(struct uart_port *port, static void altera_jtaguart_rx_chars(struct uart_port *port) { - unsigned char ch; - unsigned long status; + u32 status; + u8 ch; while ((status = readl(port->membase + ALTERA_JTAGUART_DATA_REG)) & ALTERA_JTAGUART_DATA_RVALID_MSK) { diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c index 9ce3d24af536..a9c41942190c 100644 --- a/drivers/tty/serial/altera_uart.c +++ b/drivers/tty/serial/altera_uart.c @@ -201,8 +201,8 @@ static void altera_uart_set_termios(struct uart_port *port, static void altera_uart_rx_chars(struct uart_port *port) { - unsigned char ch, flag; unsigned short status; + u8 ch, flag; while ((status = altera_uart_readl(port, ALTERA_UART_STATUS_REG)) & ALTERA_UART_STATUS_RRDY_MSK) { diff --git a/drivers/tty/serial/amba-pl010.c b/drivers/tty/serial/amba-pl010.c index a98fae2ca422..b5a7404cbacb 100644 --- a/drivers/tty/serial/amba-pl010.c +++ b/drivers/tty/serial/amba-pl010.c @@ -112,7 +112,8 @@ static void pl010_enable_ms(struct uart_port *port) static void pl010_rx_chars(struct uart_port *port) { - unsigned int status, ch, flag, rsr, max_count = 256; + unsigned int status, rsr, max_count = 256; + u8 ch, flag; status = readb(port->membase + UART01x_FR); while (UART_RX_DATA(status) && max_count--) { diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index c5c3f4674459..3dc9b0fcab1c 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -20,6 +20,7 @@ #include <linux/ioport.h> #include <linux/init.h> #include <linux/console.h> +#include <linux/platform_device.h> #include <linux/sysrq.h> #include <linux/device.h> #include <linux/tty.h> @@ -36,7 +37,6 @@ #include <linux/delay.h> #include <linux/types.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/pinctrl/consumer.h> #include <linux/sizes.h> #include <linux/io.h> @@ -307,9 +307,10 @@ static void pl011_write(unsigned int val, const struct uart_amba_port *uap, */ static int pl011_fifo_to_tty(struct uart_amba_port *uap) { - unsigned int ch, flag, fifotaken; + unsigned int ch, fifotaken; int sysrq; u16 status; + u8 flag; for (fifotaken = 0; fifotaken != 256; fifotaken++) { status = pl011_read(uap, REG_FR); diff --git a/drivers/tty/serial/apbuart.c b/drivers/tty/serial/apbuart.c index 915ee4b0d594..d7658f380838 100644 --- a/drivers/tty/serial/apbuart.c +++ b/drivers/tty/serial/apbuart.c @@ -22,9 +22,6 @@ #include <linux/kthread.h> #include <linux/device.h> #include <linux/of.h> -#include <linux/of_device.h> -#include <linux/of_platform.h> -#include <linux/of_irq.h> #include <linux/platform_device.h> #include <linux/io.h> #include <linux/serial_core.h> @@ -70,8 +67,9 @@ static void apbuart_stop_rx(struct uart_port *port) static void apbuart_rx_chars(struct uart_port *port) { - unsigned int status, ch, rsr, flag; + unsigned int status, rsr; unsigned int max_chars = port->fifosize; + u8 ch, flag; status = UART_GET_STATUS(port); diff --git a/drivers/tty/serial/ar933x_uart.c b/drivers/tty/serial/ar933x_uart.c index 4c3d04c6826a..924c1a89347c 100644 --- a/drivers/tty/serial/ar933x_uart.c +++ b/drivers/tty/serial/ar933x_uart.c @@ -749,8 +749,7 @@ static int ar933x_uart_probe(struct platform_device *pdev) port = &up->port; - mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - port->membase = devm_ioremap_resource(&pdev->dev, mem_res); + port->membase = devm_platform_get_and_ioremap_resource(pdev, 0, &mem_res); if (IS_ERR(port->membase)) return PTR_ERR(port->membase); diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c index 4b2512eef577..ad4ae19b6ce3 100644 --- a/drivers/tty/serial/arc_uart.c +++ b/drivers/tty/serial/arc_uart.c @@ -195,8 +195,6 @@ static void arc_serial_start_tx(struct uart_port *port) static void arc_serial_rx_chars(struct uart_port *port, unsigned int status) { - unsigned int ch, flg = 0; - /* * UART has 4 deep RX-FIFO. Driver's recongnition of this fact * is very subtle. Here's how ... @@ -207,24 +205,23 @@ static void arc_serial_rx_chars(struct uart_port *port, unsigned int status) * controller, which is indeed the Rx-FIFO. */ do { + u8 ch, flg = TTY_NORMAL; + /* * This could be an Rx Intr for err (no data), * so check err and clear that Intr first */ - if (unlikely(status & (RXOERR | RXFERR))) { - if (status & RXOERR) { - port->icount.overrun++; - flg = TTY_OVERRUN; - UART_CLR_STATUS(port, RXOERR); - } - - if (status & RXFERR) { - port->icount.frame++; - flg = TTY_FRAME; - UART_CLR_STATUS(port, RXFERR); - } - } else - flg = TTY_NORMAL; + if (status & RXOERR) { + port->icount.overrun++; + flg = TTY_OVERRUN; + UART_CLR_STATUS(port, RXOERR); + } + + if (status & RXFERR) { + port->icount.frame++; + flg = TTY_FRAME; + UART_CLR_STATUS(port, RXFERR); + } if (status & RXEMPTY) continue; diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 3467a875641a..88cdafa5ac54 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -21,7 +21,6 @@ #include <linux/tty_flip.h> #include <linux/platform_device.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/dma-mapping.h> #include <linux/dmaengine.h> #include <linux/atmel_pdc.h> @@ -1516,8 +1515,8 @@ static void atmel_rx_from_ring(struct uart_port *port) { struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); struct circ_buf *ring = &atmel_port->rx_ring; - unsigned int flg; unsigned int status; + u8 flg; while (ring->head != ring->tail) { struct atmel_uart_char c; diff --git a/drivers/tty/serial/bcm63xx_uart.c b/drivers/tty/serial/bcm63xx_uart.c index 55e82d0bf92d..0dd8cceb837c 100644 --- a/drivers/tty/serial/bcm63xx_uart.c +++ b/drivers/tty/serial/bcm63xx_uart.c @@ -832,14 +832,10 @@ static int bcm_uart_probe(struct platform_device *pdev) return -EBUSY; memset(port, 0, sizeof(*port)); - res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res_mem) - return -ENODEV; - - port->mapbase = res_mem->start; - port->membase = devm_ioremap_resource(&pdev->dev, res_mem); + port->membase = devm_platform_get_and_ioremap_resource(pdev, 0, &res_mem); if (IS_ERR(port->membase)) return PTR_ERR(port->membase); + port->mapbase = res_mem->start; ret = platform_get_irq(pdev, 0); if (ret < 0) diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c index e49bc4019b50..55d19937efbd 100644 --- a/drivers/tty/serial/clps711x.c +++ b/drivers/tty/serial/clps711x.c @@ -92,8 +92,9 @@ static irqreturn_t uart_clps711x_int_rx(int irq, void *dev_id) { struct uart_port *port = dev_id; struct clps711x_port *s = dev_get_drvdata(port->dev); - unsigned int status, flg; + unsigned int status; u16 ch; + u8 flg; for (;;) { u32 sysflg = 0; @@ -450,8 +451,7 @@ static int uart_clps711x_probe(struct platform_device *pdev) if (IS_ERR(uart_clk)) return PTR_ERR(uart_clk); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - s->port.membase = devm_ioremap_resource(&pdev->dev, res); + s->port.membase = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(s->port.membase)) return PTR_ERR(s->port.membase); diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_core.c b/drivers/tty/serial/cpm_uart.c index 66afa9bea6bf..626423022d62 100644 --- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/tty/serial/cpm_uart.c @@ -26,17 +26,17 @@ #include <linux/device.h> #include <linux/memblock.h> #include <linux/dma-mapping.h> -#include <linux/fs_uart_pd.h> #include <linux/of_address.h> #include <linux/of_irq.h> #include <linux/of_platform.h> #include <linux/gpio/consumer.h> #include <linux/clk.h> +#include <sysdev/fsl_soc.h> + #include <asm/io.h> #include <asm/irq.h> #include <asm/delay.h> -#include <asm/fs_pd.h> #include <asm/udbg.h> #include <linux/serial_core.h> @@ -48,14 +48,17 @@ /**************************************************************/ static int cpm_uart_tx_pump(struct uart_port *port); -static void cpm_uart_init_smc(struct uart_cpm_port *pinfo); -static void cpm_uart_init_scc(struct uart_cpm_port *pinfo); static void cpm_uart_initbd(struct uart_cpm_port *pinfo); /**************************************************************/ #define HW_BUF_SPD_THRESHOLD 2400 +static void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd) +{ + cpm_command(port->command, cmd); +} + /* * Check, if transmit buffers are processed */ @@ -605,7 +608,7 @@ static void cpm_uart_set_termios(struct uart_port *port, if (pinfo->clk) clk_set_rate(pinfo->clk, baud); else - cpm_set_brg(pinfo->brg - 1, baud); + cpm_setbrg(pinfo->brg - 1, baud); spin_unlock_irqrestore(&port->lock, flags); } @@ -771,7 +774,8 @@ static void cpm_uart_init_scc(struct uart_cpm_port *pinfo) * parameter ram. */ - cpm_set_scc_fcr(sup); + out_8(&sup->scc_genscc.scc_rfcr, CPMFCR_GBL | CPMFCR_EB); + out_8(&sup->scc_genscc.scc_tfcr, CPMFCR_GBL | CPMFCR_EB); out_be16(&sup->scc_genscc.scc_mrblr, pinfo->rx_fifosize); out_be16(&sup->scc_maxidl, 0x10); @@ -842,7 +846,8 @@ static void cpm_uart_init_smc(struct uart_cpm_port *pinfo) /* Set up the uart parameters in the * parameter ram. */ - cpm_set_smc_fcr(up); + out_8(&up->smc_rfcr, CPMFCR_GBL | CPMFCR_EB); + out_8(&up->smc_tfcr, CPMFCR_GBL | CPMFCR_EB); /* Using idle character time requires some additional tuning. */ out_be16(&up->smc_mrblr, pinfo->rx_fifosize); @@ -864,6 +869,78 @@ static void cpm_uart_init_smc(struct uart_cpm_port *pinfo) } /* + * Allocate DP-Ram and memory buffers. We need to allocate a transmit and + * receive buffer descriptors from dual port ram, and a character + * buffer area from host mem. If we are allocating for the console we need + * to do it from bootmem + */ +static int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con) +{ + int dpmemsz, memsz; + u8 __iomem *dp_mem; + unsigned long dp_offset; + u8 *mem_addr; + dma_addr_t dma_addr = 0; + + pr_debug("CPM uart[%d]:allocbuf\n", pinfo->port.line); + + dpmemsz = sizeof(cbd_t) * (pinfo->rx_nrfifos + pinfo->tx_nrfifos); + dp_offset = cpm_muram_alloc(dpmemsz, 8); + if (IS_ERR_VALUE(dp_offset)) { + pr_err("%s: could not allocate buffer descriptors\n", __func__); + return -ENOMEM; + } + + dp_mem = cpm_muram_addr(dp_offset); + + memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) + + L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize); + if (IS_ENABLED(CONFIG_CPM1) && is_con) { + /* was hostalloc but changed cause it blows away the */ + /* large tlb mapping when pinning the kernel area */ + mem_addr = (u8 __force *)cpm_muram_addr(cpm_muram_alloc(memsz, 8)); + dma_addr = cpm_muram_dma((void __iomem *)mem_addr); + } else if (is_con) { + mem_addr = kzalloc(memsz, GFP_NOWAIT); + dma_addr = virt_to_bus(mem_addr); + } else { + mem_addr = dma_alloc_coherent(pinfo->port.dev, memsz, &dma_addr, + GFP_KERNEL); + } + + if (!mem_addr) { + cpm_muram_free(dp_offset); + pr_err("%s: could not allocate coherent memory\n", __func__); + return -ENOMEM; + } + + pinfo->dp_addr = dp_offset; + pinfo->mem_addr = mem_addr; + pinfo->dma_addr = dma_addr; + pinfo->mem_size = memsz; + + pinfo->rx_buf = mem_addr; + pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos + * pinfo->rx_fifosize); + + pinfo->rx_bd_base = (cbd_t __iomem *)dp_mem; + pinfo->tx_bd_base = pinfo->rx_bd_base + pinfo->rx_nrfifos; + + return 0; +} + +static void cpm_uart_freebuf(struct uart_cpm_port *pinfo) +{ + dma_free_coherent(pinfo->port.dev, L1_CACHE_ALIGN(pinfo->rx_nrfifos * + pinfo->rx_fifosize) + + L1_CACHE_ALIGN(pinfo->tx_nrfifos * + pinfo->tx_fifosize), (void __force *)pinfo->mem_addr, + pinfo->dma_addr); + + cpm_muram_free(pinfo->dp_addr); +} + +/* * Initialize port. This is called from early_console stuff * so we have to be careful here ! */ @@ -1128,7 +1205,55 @@ static const struct uart_ops cpm_uart_pops = { #endif }; -struct uart_cpm_port cpm_uart_ports[UART_NR]; +static struct uart_cpm_port cpm_uart_ports[UART_NR]; + +static void __iomem *cpm_uart_map_pram(struct uart_cpm_port *port, + struct device_node *np) +{ + void __iomem *pram; + unsigned long offset; + struct resource res; + resource_size_t len; + + /* Don't remap parameter RAM if it has already been initialized + * during console setup. + */ + if (IS_SMC(port) && port->smcup) + return port->smcup; + else if (!IS_SMC(port) && port->sccup) + return port->sccup; + + if (of_address_to_resource(np, 1, &res)) + return NULL; + + len = resource_size(&res); + pram = ioremap(res.start, len); + if (!pram) + return NULL; + + if (!IS_ENABLED(CONFIG_CPM2) || !IS_SMC(port)) + return pram; + + if (len != 2) { + pr_warn("cpm_uart[%d]: device tree references " + "SMC pram, using boot loader/wrapper pram mapping. " + "Please fix your device tree to reference the pram " + "base register instead.\n", + port->port.line); + return pram; + } + + offset = cpm_muram_alloc(64, 64); + out_be16(pram, offset); + iounmap(pram); + return cpm_muram_addr(offset); +} + +static void cpm_uart_unmap_pram(struct uart_cpm_port *port, void __iomem *pram) +{ + if (!IS_ENABLED(CONFIG_CPM2) || !IS_SMC(port)) + iounmap(pram); +} static int cpm_uart_init_port(struct device_node *np, struct uart_cpm_port *pinfo) @@ -1255,19 +1380,14 @@ static void cpm_uart_console_write(struct console *co, const char *s, { struct uart_cpm_port *pinfo = &cpm_uart_ports[co->index]; unsigned long flags; - int nolock = oops_in_progress; - if (unlikely(nolock)) { + if (unlikely(oops_in_progress)) { local_irq_save(flags); - } else { - spin_lock_irqsave(&pinfo->port.lock, flags); - } - - cpm_uart_early_write(pinfo, s, count, true); - - if (unlikely(nolock)) { + cpm_uart_early_write(pinfo, s, count, true); local_irq_restore(flags); } else { + spin_lock_irqsave(&pinfo->port.lock, flags); + cpm_uart_early_write(pinfo, s, count, true); spin_unlock_irqrestore(&pinfo->port.lock, flags); } } @@ -1319,7 +1439,8 @@ static int __init cpm_uart_console_setup(struct console *co, char *options) if (options) { uart_parse_options(options, &baud, &parity, &bits, &flow); } else { - if ((baud = uart_baudrate()) == -1) + baud = get_baudrate(); + if (baud == -1) baud = 9600; } diff --git a/drivers/tty/serial/cpm_uart/cpm_uart.h b/drivers/tty/serial/cpm_uart.h index 46c03ed71c31..37bb6e976e03 100644 --- a/drivers/tty/serial/cpm_uart/cpm_uart.h +++ b/drivers/tty/serial/cpm_uart.h @@ -11,41 +11,31 @@ #define CPM_UART_H #include <linux/platform_device.h> -#include <linux/fs_uart_pd.h> struct gpio_desc; #if defined(CONFIG_CPM2) -#include "cpm_uart_cpm2.h" +#include "asm/cpm2.h" #elif defined(CONFIG_CPM1) -#include "cpm_uart_cpm1.h" +#include "asm/cpm1.h" #endif +#define DPRAM_BASE ((u8 __iomem *)cpm_muram_addr(0)) + #define SERIAL_CPM_MAJOR 204 #define SERIAL_CPM_MINOR 46 #define IS_SMC(pinfo) (pinfo->flags & FLAG_SMC) -#define IS_DISCARDING(pinfo) (pinfo->flags & FLAG_DISCARDING) -#define FLAG_DISCARDING 0x00000004 /* when set, don't discard */ #define FLAG_SMC 0x00000002 #define FLAG_CONSOLE 0x00000001 -#define UART_SMC1 fsid_smc1_uart -#define UART_SMC2 fsid_smc2_uart -#define UART_SCC1 fsid_scc1_uart -#define UART_SCC2 fsid_scc2_uart -#define UART_SCC3 fsid_scc3_uart -#define UART_SCC4 fsid_scc4_uart - -#define UART_NR fs_uart_nr +#define UART_NR 6 #define RX_NUM_FIFO 4 #define RX_BUF_SIZE 32 #define TX_NUM_FIFO 4 #define TX_BUF_SIZE 32 -#define SCC_WAIT_CLOSING 100 - #define GPIO_CTS 0 #define GPIO_RTS 1 #define GPIO_DCD 2 @@ -85,24 +75,6 @@ struct uart_cpm_port { struct gpio_desc *gpios[NUM_GPIOS]; }; -extern struct uart_cpm_port cpm_uart_ports[UART_NR]; - -/* these are located in their respective files */ -void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd); -void __iomem *cpm_uart_map_pram(struct uart_cpm_port *port, - struct device_node *np); -void cpm_uart_unmap_pram(struct uart_cpm_port *port, void __iomem *pram); -int cpm_uart_init_portdesc(void); -int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con); -void cpm_uart_freebuf(struct uart_cpm_port *pinfo); - -void smc1_lineif(struct uart_cpm_port *pinfo); -void smc2_lineif(struct uart_cpm_port *pinfo); -void scc1_lineif(struct uart_cpm_port *pinfo); -void scc2_lineif(struct uart_cpm_port *pinfo); -void scc3_lineif(struct uart_cpm_port *pinfo); -void scc4_lineif(struct uart_cpm_port *pinfo); - /* virtual to phys transtalion */ diff --git a/drivers/tty/serial/cpm_uart/Makefile b/drivers/tty/serial/cpm_uart/Makefile deleted file mode 100644 index 3f3a6ed02ed4..000000000000 --- a/drivers/tty/serial/cpm_uart/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# Makefile for the Motorola 8xx FEC ethernet controller -# - -obj-$(CONFIG_SERIAL_CPM) += cpm_uart.o - -# Select the correct platform objects. -cpm_uart-objs-$(CONFIG_CPM2) += cpm_uart_cpm2.o -cpm_uart-objs-$(CONFIG_CPM1) += cpm_uart_cpm1.o - -cpm_uart-objs := cpm_uart_core.o $(cpm_uart-objs-y) diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.c deleted file mode 100644 index 56fc527015cb..000000000000 --- a/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.c +++ /dev/null @@ -1,122 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Driver for CPM (SCC/SMC) serial ports; CPM1 definitions - * - * Maintainer: Kumar Gala (galak@kernel.crashing.org) (CPM2) - * Pantelis Antoniou (panto@intracom.gr) (CPM1) - * - * Copyright (C) 2004 Freescale Semiconductor, Inc. - * (C) 2004 Intracom, S.A. - * (C) 2006 MontaVista Software, Inc. - * Vitaly Bordug <vbordug@ru.mvista.com> - */ - -#include <linux/module.h> -#include <linux/tty.h> -#include <linux/gfp.h> -#include <linux/ioport.h> -#include <linux/serial.h> -#include <linux/console.h> -#include <linux/sysrq.h> -#include <linux/device.h> -#include <linux/memblock.h> -#include <linux/dma-mapping.h> - -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/fs_pd.h> - -#include <linux/serial_core.h> -#include <linux/kernel.h> - -#include <linux/of.h> -#include <linux/of_address.h> - -#include "cpm_uart.h" - -/**************************************************************/ - -void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd) -{ - cpm_command(port->command, cmd); -} - -void __iomem *cpm_uart_map_pram(struct uart_cpm_port *port, - struct device_node *np) -{ - return of_iomap(np, 1); -} - -void cpm_uart_unmap_pram(struct uart_cpm_port *port, void __iomem *pram) -{ - iounmap(pram); -} - -/* - * Allocate DP-Ram and memory buffers. We need to allocate a transmit and - * receive buffer descriptors from dual port ram, and a character - * buffer area from host mem. If we are allocating for the console we need - * to do it from bootmem - */ -int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con) -{ - int dpmemsz, memsz; - u8 *dp_mem; - unsigned long dp_offset; - u8 *mem_addr; - dma_addr_t dma_addr = 0; - - pr_debug("CPM uart[%d]:allocbuf\n", pinfo->port.line); - - dpmemsz = sizeof(cbd_t) * (pinfo->rx_nrfifos + pinfo->tx_nrfifos); - dp_offset = cpm_dpalloc(dpmemsz, 8); - if (IS_ERR_VALUE(dp_offset)) { - printk(KERN_ERR - "cpm_uart_cpm1.c: could not allocate buffer descriptors\n"); - return -ENOMEM; - } - dp_mem = cpm_dpram_addr(dp_offset); - - memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) + - L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize); - if (is_con) { - /* was hostalloc but changed cause it blows away the */ - /* large tlb mapping when pinning the kernel area */ - mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8)); - dma_addr = (u32)cpm_dpram_phys(mem_addr); - } else - mem_addr = dma_alloc_coherent(pinfo->port.dev, memsz, &dma_addr, - GFP_KERNEL); - - if (mem_addr == NULL) { - cpm_dpfree(dp_offset); - printk(KERN_ERR - "cpm_uart_cpm1.c: could not allocate coherent memory\n"); - return -ENOMEM; - } - - pinfo->dp_addr = dp_offset; - pinfo->mem_addr = mem_addr; /* virtual address*/ - pinfo->dma_addr = dma_addr; /* physical address*/ - pinfo->mem_size = memsz; - - pinfo->rx_buf = mem_addr; - pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos - * pinfo->rx_fifosize); - - pinfo->rx_bd_base = (cbd_t __iomem __force *)dp_mem; - pinfo->tx_bd_base = pinfo->rx_bd_base + pinfo->rx_nrfifos; - - return 0; -} - -void cpm_uart_freebuf(struct uart_cpm_port *pinfo) -{ - dma_free_coherent(pinfo->port.dev, L1_CACHE_ALIGN(pinfo->rx_nrfifos * - pinfo->rx_fifosize) + - L1_CACHE_ALIGN(pinfo->tx_nrfifos * - pinfo->tx_fifosize), pinfo->mem_addr, - pinfo->dma_addr); - - cpm_dpfree(pinfo->dp_addr); -} diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.h b/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.h deleted file mode 100644 index 18ec0849918a..000000000000 --- a/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.h +++ /dev/null @@ -1,33 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Driver for CPM (SCC/SMC) serial ports - * - * definitions for cpm1 - * - */ - -#ifndef CPM_UART_CPM1_H -#define CPM_UART_CPM1_H - -#include <asm/cpm1.h> - -static inline void cpm_set_brg(int brg, int baud) -{ - cpm_setbrg(brg, baud); -} - -static inline void cpm_set_scc_fcr(scc_uart_t __iomem * sup) -{ - out_8(&sup->scc_genscc.scc_rfcr, SMC_EB); - out_8(&sup->scc_genscc.scc_tfcr, SMC_EB); -} - -static inline void cpm_set_smc_fcr(smc_uart_t __iomem * up) -{ - out_8(&up->smc_rfcr, SMC_EB); - out_8(&up->smc_tfcr, SMC_EB); -} - -#define DPRAM_BASE ((u8 __iomem __force *)cpm_dpram_addr(0)) - -#endif diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.c deleted file mode 100644 index 108af254e8f3..000000000000 --- a/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.c +++ /dev/null @@ -1,156 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Driver for CPM (SCC/SMC) serial ports; CPM2 definitions - * - * Maintainer: Kumar Gala (galak@kernel.crashing.org) (CPM2) - * Pantelis Antoniou (panto@intracom.gr) (CPM1) - * - * Copyright (C) 2004 Freescale Semiconductor, Inc. - * (C) 2004 Intracom, S.A. - * (C) 2006 MontaVista Software, Inc. - * Vitaly Bordug <vbordug@ru.mvista.com> - */ - -#include <linux/module.h> -#include <linux/tty.h> -#include <linux/ioport.h> -#include <linux/slab.h> -#include <linux/serial.h> -#include <linux/console.h> -#include <linux/sysrq.h> -#include <linux/device.h> -#include <linux/memblock.h> -#include <linux/dma-mapping.h> - -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/fs_pd.h> - -#include <linux/serial_core.h> -#include <linux/kernel.h> - -#include "cpm_uart.h" - -/**************************************************************/ - -void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd) -{ - cpm_command(port->command, cmd); -} - -void __iomem *cpm_uart_map_pram(struct uart_cpm_port *port, - struct device_node *np) -{ - void __iomem *pram; - unsigned long offset; - struct resource res; - resource_size_t len; - - /* Don't remap parameter RAM if it has already been initialized - * during console setup. - */ - if (IS_SMC(port) && port->smcup) - return port->smcup; - else if (!IS_SMC(port) && port->sccup) - return port->sccup; - - if (of_address_to_resource(np, 1, &res)) - return NULL; - - len = resource_size(&res); - pram = ioremap(res.start, len); - if (!pram) - return NULL; - - if (!IS_SMC(port)) - return pram; - - if (len != 2) { - printk(KERN_WARNING "cpm_uart[%d]: device tree references " - "SMC pram, using boot loader/wrapper pram mapping. " - "Please fix your device tree to reference the pram " - "base register instead.\n", - port->port.line); - return pram; - } - - offset = cpm_dpalloc(PROFF_SMC_SIZE, 64); - out_be16(pram, offset); - iounmap(pram); - return cpm_muram_addr(offset); -} - -void cpm_uart_unmap_pram(struct uart_cpm_port *port, void __iomem *pram) -{ - if (!IS_SMC(port)) - iounmap(pram); -} - -/* - * Allocate DP-Ram and memory buffers. We need to allocate a transmit and - * receive buffer descriptors from dual port ram, and a character - * buffer area from host mem. If we are allocating for the console we need - * to do it from bootmem - */ -int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con) -{ - int dpmemsz, memsz; - u8 __iomem *dp_mem; - unsigned long dp_offset; - u8 *mem_addr; - dma_addr_t dma_addr = 0; - - pr_debug("CPM uart[%d]:allocbuf\n", pinfo->port.line); - - dpmemsz = sizeof(cbd_t) * (pinfo->rx_nrfifos + pinfo->tx_nrfifos); - dp_offset = cpm_dpalloc(dpmemsz, 8); - if (IS_ERR_VALUE(dp_offset)) { - printk(KERN_ERR - "cpm_uart_cpm.c: could not allocate buffer descriptors\n"); - return -ENOMEM; - } - - dp_mem = cpm_dpram_addr(dp_offset); - - memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) + - L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize); - if (is_con) { - mem_addr = kzalloc(memsz, GFP_NOWAIT); - dma_addr = virt_to_bus(mem_addr); - } - else - mem_addr = dma_alloc_coherent(pinfo->port.dev, memsz, &dma_addr, - GFP_KERNEL); - - if (mem_addr == NULL) { - cpm_dpfree(dp_offset); - printk(KERN_ERR - "cpm_uart_cpm.c: could not allocate coherent memory\n"); - return -ENOMEM; - } - - pinfo->dp_addr = dp_offset; - pinfo->mem_addr = mem_addr; - pinfo->dma_addr = dma_addr; - pinfo->mem_size = memsz; - - pinfo->rx_buf = mem_addr; - pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos - * pinfo->rx_fifosize); - - pinfo->rx_bd_base = (cbd_t __iomem *)dp_mem; - pinfo->tx_bd_base = pinfo->rx_bd_base + pinfo->rx_nrfifos; - - return 0; -} - -void cpm_uart_freebuf(struct uart_cpm_port *pinfo) -{ - dma_free_coherent(pinfo->port.dev, L1_CACHE_ALIGN(pinfo->rx_nrfifos * - pinfo->rx_fifosize) + - L1_CACHE_ALIGN(pinfo->tx_nrfifos * - pinfo->tx_fifosize), (void __force *)pinfo->mem_addr, - pinfo->dma_addr); - - cpm_dpfree(pinfo->dp_addr); -} diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.h b/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.h deleted file mode 100644 index 051a8509c3e5..000000000000 --- a/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.h +++ /dev/null @@ -1,33 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Driver for CPM (SCC/SMC) serial ports - * - * definitions for cpm2 - * - */ - -#ifndef CPM_UART_CPM2_H -#define CPM_UART_CPM2_H - -#include <asm/cpm2.h> - -static inline void cpm_set_brg(int brg, int baud) -{ - cpm_setbrg(brg, baud); -} - -static inline void cpm_set_scc_fcr(scc_uart_t __iomem *sup) -{ - out_8(&sup->scc_genscc.scc_rfcr, CPMFCR_GBL | CPMFCR_EB); - out_8(&sup->scc_genscc.scc_tfcr, CPMFCR_GBL | CPMFCR_EB); -} - -static inline void cpm_set_smc_fcr(smc_uart_t __iomem *up) -{ - out_8(&up->smc_rfcr, CPMFCR_GBL | CPMFCR_EB); - out_8(&up->smc_tfcr, CPMFCR_GBL | CPMFCR_EB); -} - -#define DPRAM_BASE ((u8 __iomem __force *)cpm_dpram_addr(0)) - -#endif diff --git a/drivers/tty/serial/digicolor-usart.c b/drivers/tty/serial/digicolor-usart.c index ed197705f7ee..128b5479e813 100644 --- a/drivers/tty/serial/digicolor-usart.c +++ b/drivers/tty/serial/digicolor-usart.c @@ -136,8 +136,7 @@ static void digicolor_uart_rx(struct uart_port *port) spin_lock_irqsave(&port->lock, flags); while (1) { - u8 status, ch; - unsigned int ch_flag; + u8 status, ch, ch_flag; if (digicolor_uart_rx_empty(port)) break; diff --git a/drivers/tty/serial/dz.c b/drivers/tty/serial/dz.c index 6b7ed7f2f3ca..667f52e83277 100644 --- a/drivers/tty/serial/dz.c +++ b/drivers/tty/serial/dz.c @@ -181,8 +181,8 @@ static inline void dz_receive_chars(struct dz_mux *mux) struct dz_port *dport = &mux->dport[0]; struct uart_icount *icount; int lines_rx[DZ_NB_PORT] = { [0 ... DZ_NB_PORT - 1] = 0 }; - unsigned char ch, flag; u16 status; + u8 ch, flag; int i; while ((status = dz_in(dport, DZ_RBUF)) & DZ_DVAL) { diff --git a/drivers/tty/serial/fsl_linflexuart.c b/drivers/tty/serial/fsl_linflexuart.c index 6fc21b6684e6..249cb380c3c6 100644 --- a/drivers/tty/serial/fsl_linflexuart.c +++ b/drivers/tty/serial/fsl_linflexuart.c @@ -11,7 +11,7 @@ #include <linux/irq.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> +#include <linux/platform_device.h> #include <linux/serial_core.h> #include <linux/slab.h> #include <linux/tty_flip.h> @@ -827,14 +827,10 @@ static int linflex_probe(struct platform_device *pdev) sport->line = ret; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENODEV; - - sport->mapbase = res->start; - sport->membase = devm_ioremap_resource(&pdev->dev, res); + sport->membase = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(sport->membase)) return PTR_ERR(sport->membase); + sport->mapbase = res->start; sport->dev = &pdev->dev; sport->type = PORT_LINFLEXUART; diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index c569a08b5b19..f72e1340b47d 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -18,9 +18,9 @@ #include <linux/irq.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/of_dma.h> #include <linux/pinctrl/consumer.h> +#include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/serial_core.h> #include <linux/slab.h> @@ -288,6 +288,7 @@ struct lpuart_port { wait_queue_head_t dma_wait; bool is_cs7; /* Set to true when character size is 7 */ /* and the parity is enabled */ + bool dma_idle_int; }; struct lpuart_soc_data { @@ -1064,26 +1065,6 @@ static irqreturn_t lpuart_int(int irq, void *dev_id) return IRQ_HANDLED; } -static irqreturn_t lpuart32_int(int irq, void *dev_id) -{ - struct lpuart_port *sport = dev_id; - unsigned long sts, rxcount; - - sts = lpuart32_read(&sport->port, UARTSTAT); - rxcount = lpuart32_read(&sport->port, UARTWATER); - rxcount = rxcount >> UARTWATER_RXCNT_OFF; - - if ((sts & UARTSTAT_RDRF || rxcount > 0) && !sport->lpuart_dma_rx_use) - lpuart32_rxint(sport); - - if ((sts & UARTSTAT_TDRE) && !sport->lpuart_dma_tx_use) - lpuart32_txint(sport); - - lpuart32_write(&sport->port, sts, UARTSTAT); - return IRQ_HANDLED; -} - - static inline void lpuart_handle_sysrq_chars(struct uart_port *port, unsigned char *p, int count) { @@ -1266,7 +1247,8 @@ exit: spin_unlock_irqrestore(&sport->port.lock, flags); tty_flip_buffer_push(port); - mod_timer(&sport->lpuart_timer, jiffies + sport->dma_rx_timeout); + if (!sport->dma_idle_int) + mod_timer(&sport->lpuart_timer, jiffies + sport->dma_rx_timeout); } static void lpuart_dma_rx_complete(void *arg) @@ -1276,6 +1258,50 @@ static void lpuart_dma_rx_complete(void *arg) lpuart_copy_rx_to_tty(sport); } +static void lpuart32_dma_idleint(struct lpuart_port *sport) +{ + enum dma_status dmastat; + struct dma_chan *chan = sport->dma_rx_chan; + struct circ_buf *ring = &sport->rx_ring; + struct dma_tx_state state; + int count = 0; + + dmastat = dmaengine_tx_status(chan, sport->dma_rx_cookie, &state); + if (dmastat == DMA_ERROR) { + dev_err(sport->port.dev, "Rx DMA transfer failed!\n"); + return; + } + + ring->head = sport->rx_sgl.length - state.residue; + count = CIRC_CNT(ring->head, ring->tail, sport->rx_sgl.length); + + /* Check if new data received before copying */ + if (count) + lpuart_copy_rx_to_tty(sport); +} + +static irqreturn_t lpuart32_int(int irq, void *dev_id) +{ + struct lpuart_port *sport = dev_id; + unsigned long sts, rxcount; + + sts = lpuart32_read(&sport->port, UARTSTAT); + rxcount = lpuart32_read(&sport->port, UARTWATER); + rxcount = rxcount >> UARTWATER_RXCNT_OFF; + + if ((sts & UARTSTAT_RDRF || rxcount > 0) && !sport->lpuart_dma_rx_use) + lpuart32_rxint(sport); + + if ((sts & UARTSTAT_TDRE) && !sport->lpuart_dma_tx_use) + lpuart32_txint(sport); + + if ((sts & UARTSTAT_IDLE) && sport->lpuart_dma_rx_use && sport->dma_idle_int) + lpuart32_dma_idleint(sport); + + lpuart32_write(&sport->port, sts, UARTSTAT); + return IRQ_HANDLED; +} + /* * Timer function to simulate the hardware EOP (End Of Package) event. * The timer callback is to check for new RX data and copy to TTY buffer. @@ -1392,6 +1418,12 @@ static inline int lpuart_start_rx_dma(struct lpuart_port *sport) unsigned long temp = lpuart32_read(&sport->port, UARTBAUD); lpuart32_write(&sport->port, temp | UARTBAUD_RDMAE, UARTBAUD); + + if (sport->dma_idle_int) { + unsigned long ctrl = lpuart32_read(&sport->port, UARTCTRL); + + lpuart32_write(&sport->port, ctrl | UARTCTRL_ILIE, UARTCTRL); + } } else { writeb(readb(sport->port.membase + UARTCR5) | UARTCR5_RDMAS, sport->port.membase + UARTCR5); @@ -1407,7 +1439,9 @@ static void lpuart_dma_rx_free(struct uart_port *port) struct dma_chan *chan = sport->dma_rx_chan; dmaengine_terminate_sync(chan); - del_timer_sync(&sport->lpuart_timer); + if (!sport->dma_idle_int) + del_timer_sync(&sport->lpuart_timer); + dma_unmap_sg(chan->device->dev, &sport->rx_sgl, 1, DMA_FROM_DEVICE); kfree(sport->rx_ring.buf); sport->rx_ring.tail = 0; @@ -1669,6 +1703,9 @@ static void lpuart32_setup_watermark_enable(struct lpuart_port *sport) static void rx_dma_timer_init(struct lpuart_port *sport) { + if (sport->dma_idle_int) + return; + timer_setup(&sport->lpuart_timer, lpuart_timer_func, 0); sport->lpuart_timer.expires = jiffies + sport->dma_rx_timeout; add_timer(&sport->lpuart_timer); @@ -2811,8 +2848,7 @@ static int lpuart_probe(struct platform_device *pdev) if (!sport) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - sport->port.membase = devm_ioremap_resource(&pdev->dev, res); + sport->port.membase = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(sport->port.membase)) return PTR_ERR(sport->port.membase); @@ -2822,6 +2858,8 @@ static int lpuart_probe(struct platform_device *pdev) sport->port.type = PORT_LPUART; sport->devtype = sdata->devtype; sport->rx_watermark = sdata->rx_watermark; + sport->dma_idle_int = is_imx7ulp_lpuart(sport) || is_imx8ulp_lpuart(sport) || + is_imx8qxp_lpuart(sport); ret = platform_get_irq(pdev, 0); if (ret < 0) return ret; diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 7341d060f85c..13cb78340709 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -25,7 +25,6 @@ #include <linux/rational.h> #include <linux/slab.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/io.h> #include <linux/dma-mapping.h> @@ -2276,8 +2275,7 @@ static int imx_uart_probe(struct platform_device *pdev) return -EINVAL; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, res); + base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(base)) return PTR_ERR(base); diff --git a/drivers/tty/serial/ip22zilog.c b/drivers/tty/serial/ip22zilog.c index b1f27e168135..845ff706bc59 100644 --- a/drivers/tty/serial/ip22zilog.c +++ b/drivers/tty/serial/ip22zilog.c @@ -248,8 +248,8 @@ static void ip22zilog_maybe_update_regs(struct uart_ip22zilog_port *up, static bool ip22zilog_receive_chars(struct uart_ip22zilog_port *up, struct zilog_channel *channel) { - unsigned char ch, flag; unsigned int r1; + u8 ch, flag; bool push = up->port.state != NULL; for (;;) { diff --git a/drivers/tty/serial/kgdb_nmi.c b/drivers/tty/serial/kgdb_nmi.c index 55c3c9db7462..e93850f6447a 100644 --- a/drivers/tty/serial/kgdb_nmi.c +++ b/drivers/tty/serial/kgdb_nmi.c @@ -304,7 +304,8 @@ static unsigned int kgdb_nmi_tty_write_room(struct tty_struct *tty) return 2048; } -static int kgdb_nmi_tty_write(struct tty_struct *tty, const unchar *buf, int c) +static ssize_t kgdb_nmi_tty_write(struct tty_struct *tty, const u8 *buf, + size_t c) { int i; diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c index bcaa479608d8..3adb60c683f7 100644 --- a/drivers/tty/serial/lantiq.c +++ b/drivers/tty/serial/lantiq.c @@ -17,7 +17,8 @@ #include <linux/ioport.h> #include <linux/lantiq.h> #include <linux/module.h> -#include <linux/of_platform.h> +#include <linux/of.h> +#include <linux/platform_device.h> #include <linux/serial.h> #include <linux/serial_core.h> #include <linux/slab.h> diff --git a/drivers/tty/serial/liteuart.c b/drivers/tty/serial/liteuart.c index 80de3a42b67b..d881cdd2a58f 100644 --- a/drivers/tty/serial/liteuart.c +++ b/drivers/tty/serial/liteuart.c @@ -11,8 +11,7 @@ #include <linux/litex.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_address.h> -#include <linux/of_platform.h> +#include <linux/platform_device.h> #include <linux/serial.h> #include <linux/serial_core.h> #include <linux/slab.h> diff --git a/drivers/tty/serial/ma35d1_serial.c b/drivers/tty/serial/ma35d1_serial.c index 2604b4d9fb78..465b1def9e11 100644 --- a/drivers/tty/serial/ma35d1_serial.c +++ b/drivers/tty/serial/ma35d1_serial.c @@ -8,7 +8,7 @@ #include <linux/clk.h> #include <linux/delay.h> #include <linux/of.h> -#include <linux/of_platform.h> +#include <linux/platform_device.h> #include <linux/iopoll.h> #include <linux/serial_core.h> #include <linux/slab.h> @@ -788,7 +788,6 @@ static struct platform_driver ma35d1serial_driver = { .resume = ma35d1serial_resume, .driver = { .name = "ma35d1-uart", - .owner = THIS_MODULE, .of_match_table = of_match_ptr(ma35d1_serial_of_match), }, }; diff --git a/drivers/tty/serial/max3100.c b/drivers/tty/serial/max3100.c index 86dcbff8faa3..5efb2b593be3 100644 --- a/drivers/tty/serial/max3100.c +++ b/drivers/tty/serial/max3100.c @@ -215,8 +215,9 @@ static int max3100_sr(struct max3100_port *s, u16 tx, u16 *rx) static int max3100_handlerx(struct max3100_port *s, u16 rx) { - unsigned int ch, flg, status = 0; + unsigned int status = 0; int ret = 0, cts; + u8 ch, flg; if (rx & MAX3100_R && s->rx_enabled) { dev_dbg(&s->spi->dev, "%s\n", __func__); diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index 997e39449766..db3204d2a305 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -669,7 +669,8 @@ static void max310x_batch_read(struct uart_port *port, u8 *rxbuf, unsigned int l static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen) { struct max310x_one *one = to_max310x_port(port); - unsigned int sts, ch, flag, i; + unsigned int sts, i; + u8 ch, flag; if (port->read_status_mask == MAX310X_LSR_RXOVR_BIT) { /* We are just reading, happily ignoring any error conditions. @@ -1368,6 +1369,11 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty s->p[i].port.flags = UPF_FIXED_TYPE | UPF_LOW_LATENCY; s->p[i].port.iotype = UPIO_PORT; s->p[i].port.iobase = i; + /* + * Use all ones as membase to make sure uart_configure_port() in + * serial_core.c does not abort for SPI/I2C devices where the + * membase address is not applicable. + */ s->p[i].port.membase = (void __iomem *)~0; s->p[i].port.uartclk = uartclk; s->p[i].port.rs485_config = max310x_rs485_config; @@ -1399,7 +1405,7 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty } #ifdef CONFIG_GPIOLIB - /* Setup GPIO cotroller */ + /* Setup GPIO controller */ s->gpio.owner = THIS_MODULE; s->gpio.parent = dev; s->gpio.label = devtype->name; diff --git a/drivers/tty/serial/mcf.c b/drivers/tty/serial/mcf.c index 3239babe12a4..1666ce012e5e 100644 --- a/drivers/tty/serial/mcf.c +++ b/drivers/tty/serial/mcf.c @@ -281,7 +281,7 @@ static void mcf_set_termios(struct uart_port *port, struct ktermios *termios, static void mcf_rx_chars(struct mcf_uart *pp) { struct uart_port *port = &pp->port; - unsigned char status, ch, flag; + u8 status, ch, flag; while ((status = readb(port->membase + MCFUART_USR)) & MCFUART_USR_RXREADY) { ch = readb(port->membase + MCFUART_URB); diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c index 2501db5a7aaf..790d910dafa5 100644 --- a/drivers/tty/serial/meson_uart.c +++ b/drivers/tty/serial/meson_uart.c @@ -72,16 +72,17 @@ #define AML_UART_PORT_NUM 12 #define AML_UART_PORT_OFFSET 6 -#define AML_UART_DEV_NAME "ttyAML" #define AML_UART_POLL_USEC 5 #define AML_UART_TIMEOUT_USEC 10000 -static struct uart_driver meson_uart_driver; +static struct uart_driver meson_uart_driver_ttyAML; +static struct uart_driver meson_uart_driver_ttyS; static struct uart_port *meson_ports[AML_UART_PORT_NUM]; struct meson_uart_data { + struct uart_driver *uart_driver; bool has_xtal_div2; }; @@ -611,21 +612,19 @@ static int meson_serial_console_setup(struct console *co, char *options) return uart_set_options(port, co, baud, parity, bits, flow); } -static struct console meson_serial_console = { - .name = AML_UART_DEV_NAME, - .write = meson_serial_console_write, - .device = uart_console_device, - .setup = meson_serial_console_setup, - .flags = CON_PRINTBUFFER, - .index = -1, - .data = &meson_uart_driver, -}; +#define MESON_SERIAL_CONSOLE(_devname) \ + static struct console meson_serial_console_##_devname = { \ + .name = __stringify(_devname), \ + .write = meson_serial_console_write, \ + .device = uart_console_device, \ + .setup = meson_serial_console_setup, \ + .flags = CON_PRINTBUFFER, \ + .index = -1, \ + .data = &meson_uart_driver_##_devname, \ + } -static int __init meson_serial_console_init(void) -{ - register_console(&meson_serial_console); - return 0; -} +MESON_SERIAL_CONSOLE(ttyAML); +MESON_SERIAL_CONSOLE(ttyS); static void meson_serial_early_console_write(struct console *co, const char *s, @@ -650,21 +649,22 @@ meson_serial_early_console_setup(struct earlycon_device *device, const char *opt OF_EARLYCON_DECLARE(meson, "amlogic,meson-ao-uart", meson_serial_early_console_setup); -#define MESON_SERIAL_CONSOLE (&meson_serial_console) +#define MESON_SERIAL_CONSOLE_PTR(_devname) (&meson_serial_console_##_devname) #else -static int __init meson_serial_console_init(void) { - return 0; -} -#define MESON_SERIAL_CONSOLE NULL +#define MESON_SERIAL_CONSOLE_PTR(_devname) (NULL) #endif -static struct uart_driver meson_uart_driver = { - .owner = THIS_MODULE, - .driver_name = "meson_uart", - .dev_name = AML_UART_DEV_NAME, - .nr = AML_UART_PORT_NUM, - .cons = MESON_SERIAL_CONSOLE, -}; +#define MESON_UART_DRIVER(_devname) \ + static struct uart_driver meson_uart_driver_##_devname = { \ + .owner = THIS_MODULE, \ + .driver_name = "meson_uart", \ + .dev_name = __stringify(_devname), \ + .nr = AML_UART_PORT_NUM, \ + .cons = MESON_SERIAL_CONSOLE_PTR(_devname), \ + } + +MESON_UART_DRIVER(ttyAML); +MESON_UART_DRIVER(ttyS); static int meson_uart_probe_clocks(struct platform_device *pdev, struct uart_port *port) @@ -690,8 +690,16 @@ static int meson_uart_probe_clocks(struct platform_device *pdev, return 0; } +static struct uart_driver *meson_uart_current(const struct meson_uart_data *pd) +{ + return (pd && pd->uart_driver) ? + pd->uart_driver : &meson_uart_driver_ttyAML; +} + static int meson_uart_probe(struct platform_device *pdev) { + const struct meson_uart_data *priv_data; + struct uart_driver *uart_driver; struct resource *res_mem; struct uart_port *port; u32 fifosize = 64; /* Default is 64, 128 for EE UART_0 */ @@ -726,8 +734,8 @@ static int meson_uart_probe(struct platform_device *pdev) of_property_read_u32(pdev->dev.of_node, "fifo-size", &fifosize); if (meson_ports[pdev->id]) { - dev_err(&pdev->dev, "port %d already allocated\n", pdev->id); - return -EBUSY; + return dev_err_probe(&pdev->dev, -EBUSY, + "port %d already allocated\n", pdev->id); } port = devm_kzalloc(&pdev->dev, sizeof(struct uart_port), GFP_KERNEL); @@ -738,6 +746,17 @@ static int meson_uart_probe(struct platform_device *pdev) if (ret) return ret; + priv_data = device_get_match_data(&pdev->dev); + + uart_driver = meson_uart_current(priv_data); + + if (!uart_driver->state) { + ret = uart_register_driver(uart_driver); + if (ret) + return dev_err_probe(&pdev->dev, ret, + "can't register uart driver\n"); + } + port->iotype = UPIO_MEM; port->mapbase = res_mem->start; port->mapsize = resource_size(res_mem); @@ -750,7 +769,7 @@ static int meson_uart_probe(struct platform_device *pdev) port->x_char = 0; port->ops = &meson_uart_ops; port->fifosize = fifosize; - port->private_data = (void *)device_get_match_data(&pdev->dev); + port->private_data = (void *)priv_data; meson_ports[pdev->id] = port; platform_set_drvdata(pdev, port); @@ -761,7 +780,7 @@ static int meson_uart_probe(struct platform_device *pdev) meson_uart_release_port(port); } - ret = uart_add_one_port(&meson_uart_driver, port); + ret = uart_add_one_port(uart_driver, port); if (ret) meson_ports[pdev->id] = NULL; @@ -770,12 +789,21 @@ static int meson_uart_probe(struct platform_device *pdev) static int meson_uart_remove(struct platform_device *pdev) { + struct uart_driver *uart_driver; struct uart_port *port; port = platform_get_drvdata(pdev); - uart_remove_one_port(&meson_uart_driver, port); + uart_driver = meson_uart_current(port->private_data); + uart_remove_one_port(uart_driver, port); meson_ports[pdev->id] = NULL; + for (int id = 0; id < AML_UART_PORT_NUM; id++) + if (meson_ports[id]) + return 0; + + /* No more available uart ports, unregister uart driver */ + uart_unregister_driver(uart_driver); + return 0; } @@ -783,6 +811,16 @@ static struct meson_uart_data meson_g12a_uart_data = { .has_xtal_div2 = true, }; +static struct meson_uart_data meson_a1_uart_data = { + .uart_driver = &meson_uart_driver_ttyS, + .has_xtal_div2 = false, +}; + +static struct meson_uart_data meson_s4_uart_data = { + .uart_driver = &meson_uart_driver_ttyS, + .has_xtal_div2 = true, +}; + static const struct of_device_id meson_uart_dt_match[] = { { .compatible = "amlogic,meson6-uart" }, { .compatible = "amlogic,meson8-uart" }, @@ -794,7 +832,11 @@ static const struct of_device_id meson_uart_dt_match[] = { }, { .compatible = "amlogic,meson-s4-uart", - .data = (void *)&meson_g12a_uart_data, + .data = (void *)&meson_s4_uart_data, + }, + { + .compatible = "amlogic,meson-a1-uart", + .data = (void *)&meson_a1_uart_data, }, { /* sentinel */ }, }; @@ -809,33 +851,7 @@ static struct platform_driver meson_uart_platform_driver = { }, }; -static int __init meson_uart_init(void) -{ - int ret; - - ret = meson_serial_console_init(); - if (ret) - return ret; - - ret = uart_register_driver(&meson_uart_driver); - if (ret) - return ret; - - ret = platform_driver_register(&meson_uart_platform_driver); - if (ret) - uart_unregister_driver(&meson_uart_driver); - - return ret; -} - -static void __exit meson_uart_exit(void) -{ - platform_driver_unregister(&meson_uart_platform_driver); - uart_unregister_driver(&meson_uart_driver); -} - -module_init(meson_uart_init); -module_exit(meson_uart_exit); +module_platform_driver(meson_uart_platform_driver); MODULE_AUTHOR("Carlo Caione <carlo@caione.org>"); MODULE_DESCRIPTION("Amlogic Meson serial port driver"); diff --git a/drivers/tty/serial/milbeaut_usio.c b/drivers/tty/serial/milbeaut_usio.c index 44988a2941b8..70a910085e93 100644 --- a/drivers/tty/serial/milbeaut_usio.c +++ b/drivers/tty/serial/milbeaut_usio.c @@ -148,8 +148,7 @@ static void mlb_usio_enable_ms(struct uart_port *port) static void mlb_usio_rx_chars(struct uart_port *port) { struct tty_port *ttyport = &port->state->port; - unsigned long flag = 0; - char ch = 0; + u8 flag = 0, ch = 0; u8 status; int max_count = 2; diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c index 384ca195e3d5..916507b8f31d 100644 --- a/drivers/tty/serial/mpc52xx_uart.c +++ b/drivers/tty/serial/mpc52xx_uart.c @@ -40,7 +40,7 @@ #include <linux/of.h> #include <linux/of_address.h> #include <linux/of_irq.h> -#include <linux/of_platform.h> +#include <linux/platform_device.h> #include <linux/clk.h> #include <asm/mpc52xx.h> diff --git a/drivers/tty/serial/mps2-uart.c b/drivers/tty/serial/mps2-uart.c index 860d161fa594..ea5a7911cb15 100644 --- a/drivers/tty/serial/mps2-uart.c +++ b/drivers/tty/serial/mps2-uart.c @@ -16,7 +16,6 @@ #include <linux/console.h> #include <linux/io.h> #include <linux/kernel.h> -#include <linux/of_device.h> #include <linux/of.h> #include <linux/platform_device.h> #include <linux/serial_core.h> @@ -539,8 +538,7 @@ static int mps2_init_port(struct platform_device *pdev, struct resource *res; int ret; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - mps_port->port.membase = devm_ioremap_resource(&pdev->dev, res); + mps_port->port.membase = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(mps_port->port.membase)) return PTR_ERR(mps_port->port.membase); diff --git a/drivers/tty/serial/mvebu-uart.c b/drivers/tty/serial/mvebu-uart.c index 31f739c7a08b..ea924e9b913b 100644 --- a/drivers/tty/serial/mvebu-uart.c +++ b/drivers/tty/serial/mvebu-uart.c @@ -876,18 +876,13 @@ static int uart_num_counter; static int mvebu_uart_probe(struct platform_device *pdev) { - struct resource *reg = platform_get_resource(pdev, IORESOURCE_MEM, 0); const struct of_device_id *match = of_match_device(mvebu_uart_of_match, &pdev->dev); struct uart_port *port; struct mvebu_uart *mvuart; + struct resource *reg; int id, irq; - if (!reg) { - dev_err(&pdev->dev, "no registers defined\n"); - return -EINVAL; - } - /* Assume that all UART ports have a DT alias or none has */ id = of_alias_get_id(pdev->dev.of_node, "serial"); if (!pdev->dev.of_node || id < 0) @@ -922,11 +917,11 @@ static int mvebu_uart_probe(struct platform_device *pdev) */ port->irq = 0; port->irqflags = 0; - port->mapbase = reg->start; - port->membase = devm_ioremap_resource(&pdev->dev, reg); + port->membase = devm_platform_get_and_ioremap_resource(pdev, 0, ®); if (IS_ERR(port->membase)) return PTR_ERR(port->membase); + port->mapbase = reg->start; mvuart = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_uart), GFP_KERNEL); diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c index a368f4293967..8eeecf8ad359 100644 --- a/drivers/tty/serial/mxs-auart.c +++ b/drivers/tty/serial/mxs-auart.c @@ -30,7 +30,7 @@ #include <linux/clk.h> #include <linux/delay.h> #include <linux/io.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/dma-mapping.h> #include <linux/dmaengine.h> @@ -616,9 +616,8 @@ static void mxs_auart_tx_chars(struct mxs_auart_port *s) static void mxs_auart_rx_char(struct mxs_auart_port *s) { - int flag; u32 stat; - u8 c; + u8 c, flag; c = mxs_read(s, REG_DATA); stat = mxs_read(s, REG_STAT); diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 82d35dbbfa6c..0ead88c5a19a 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -222,16 +222,11 @@ static inline int calculate_baud_abs_diff(struct uart_port *port, unsigned int baud, unsigned int mode) { unsigned int n = port->uartclk / (mode * baud); - int abs_diff; if (n == 0) n = 1; - abs_diff = baud - (port->uartclk / (mode * n)); - if (abs_diff < 0) - abs_diff = -abs_diff; - - return abs_diff; + return abs_diff(baud, port->uartclk / (mode * n)); } /* @@ -442,7 +437,7 @@ static unsigned int check_modem_status(struct uart_omap_port *up) static void serial_omap_rlsi(struct uart_omap_port *up, unsigned int lsr) { - unsigned int flag; + u8 flag; /* * Read one data character out to avoid stalling the receiver according @@ -498,8 +493,7 @@ static void serial_omap_rlsi(struct uart_omap_port *up, unsigned int lsr) static void serial_omap_rdi(struct uart_omap_port *up, unsigned int lsr) { - unsigned char ch = 0; - unsigned int flag; + u8 ch; if (!(lsr & UART_LSR_DR)) return; @@ -512,13 +506,12 @@ static void serial_omap_rdi(struct uart_omap_port *up, unsigned int lsr) return; } - flag = TTY_NORMAL; up->port.icount.rx++; if (uart_handle_sysrq_char(&up->port, ch)) return; - uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag); + uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, TTY_NORMAL); } /** @@ -1573,8 +1566,7 @@ static int serial_omap_probe(struct platform_device *pdev) if (!up) return -ENOMEM; - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, mem); + base = devm_platform_get_and_ioremap_resource(pdev, 0, &mem); if (IS_ERR(base)) return PTR_ERR(base); diff --git a/drivers/tty/serial/pic32_uart.c b/drivers/tty/serial/pic32_uart.c index 196a4e678451..e308d5022b3f 100644 --- a/drivers/tty/serial/pic32_uart.c +++ b/drivers/tty/serial/pic32_uart.c @@ -11,7 +11,6 @@ #include <linux/kernel.h> #include <linux/platform_device.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/of_irq.h> #include <linux/of_gpio.h> #include <linux/init.h> diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c index 444fa4b654ac..73c60f5ea027 100644 --- a/drivers/tty/serial/pxa.c +++ b/drivers/tty/serial/pxa.c @@ -90,7 +90,7 @@ static void serial_pxa_stop_rx(struct uart_port *port) static inline void receive_chars(struct uart_pxa_port *up, int *status) { - unsigned int ch, flag; + u8 ch, flag; int max_count = 256; do { diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c index daaf2a64e7f1..b8aa4c1293ba 100644 --- a/drivers/tty/serial/qcom_geni_serial.c +++ b/drivers/tty/serial/qcom_geni_serial.c @@ -11,7 +11,6 @@ #include <linux/irq.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/pm_opp.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> @@ -126,6 +125,7 @@ struct qcom_geni_serial_port { dma_addr_t rx_dma_addr; bool setup; unsigned int baud; + unsigned long clk_rate; void *rx_buf; u32 loopback; bool brk; @@ -591,7 +591,6 @@ static void qcom_geni_serial_stop_tx_dma(struct uart_port *uport) { struct qcom_geni_serial_port *port = to_dev_port(uport); bool done; - u32 m_irq_en; if (!qcom_geni_serial_main_active(uport)) return; @@ -603,12 +602,10 @@ static void qcom_geni_serial_stop_tx_dma(struct uart_port *uport) port->tx_remaining = 0; } - m_irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN); - writel(m_irq_en, uport->membase + SE_GENI_M_IRQ_EN); geni_se_cancel_m_cmd(&port->se); - done = qcom_geni_serial_poll_bit(uport, SE_GENI_S_IRQ_STATUS, - S_CMD_CANCEL_EN, true); + done = qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS, + M_CMD_CANCEL_EN, true); if (!done) { geni_se_abort_m_cmd(&port->se); done = qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS, @@ -1245,10 +1242,11 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport, goto out_restart_rx; } - dev_dbg(port->se.dev, "desired_rate-%u, clk_rate-%lu, clk_div-%u\n", + dev_dbg(port->se.dev, "desired_rate = %u, clk_rate = %lu, clk_div = %u\n", baud * sampling_rate, clk_rate, clk_div); uport->uartclk = clk_rate; + port->clk_rate = clk_rate; dev_pm_opp_set_rate(uport->dev, clk_rate); ser_clk_cfg = SER_CLK_EN; ser_clk_cfg |= clk_div << CLK_DIV_SHFT; @@ -1513,10 +1511,13 @@ static void qcom_geni_serial_pm(struct uart_port *uport, if (new_state == UART_PM_STATE_ON && old_state == UART_PM_STATE_OFF) { geni_icc_enable(&port->se); + if (port->clk_rate) + dev_pm_opp_set_rate(uport->dev, port->clk_rate); geni_se_resources_on(&port->se); } else if (new_state == UART_PM_STATE_OFF && old_state == UART_PM_STATE_ON) { geni_se_resources_off(&port->se); + dev_pm_opp_set_rate(uport->dev, 0); geni_icc_disable(&port->se); } } @@ -1750,7 +1751,7 @@ static int qcom_geni_serial_sys_hib_resume(struct device *dev) private_data = uport->private_data; if (uart_console(uport)) { - geni_icc_set_tag(&port->se, 0x7); + geni_icc_set_tag(&port->se, QCOM_ICC_TAG_ALWAYS); geni_icc_set_bw(&port->se); ret = uart_resume_port(private_data->drv, uport); /* diff --git a/drivers/tty/serial/rp2.c b/drivers/tty/serial/rp2.c index 749b873a5d99..de220ac8ca54 100644 --- a/drivers/tty/serial/rp2.c +++ b/drivers/tty/serial/rp2.c @@ -401,14 +401,14 @@ static void rp2_rx_chars(struct rp2_uart_port *up) for (; bytes != 0; bytes--) { u32 byte = readw(up->base + RP2_DATA_BYTE) | RP2_DUMMY_READ; - char ch = byte & 0xff; + u8 ch = byte & 0xff; if (likely(!(byte & RP2_DATA_BYTE_EXCEPTION_MASK))) { if (!uart_handle_sysrq_char(&up->port, ch)) uart_insert_char(&up->port, byte, 0, ch, TTY_NORMAL); } else { - char flag = TTY_NORMAL; + u8 flag = TTY_NORMAL; if (byte & RP2_DATA_BYTE_BREAK_m) flag = TTY_BREAK; diff --git a/drivers/tty/serial/sa1100.c b/drivers/tty/serial/sa1100.c index 55107bbc00ce..ad011f1e2f4d 100644 --- a/drivers/tty/serial/sa1100.c +++ b/drivers/tty/serial/sa1100.c @@ -180,7 +180,8 @@ static void sa1100_enable_ms(struct uart_port *port) static void sa1100_rx_chars(struct sa1100_port *sport) { - unsigned int status, ch, flg; + unsigned int status; + u8 ch, flg; status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) | UTSR0_TO_SM(UART_GET_UTSR0(sport)); diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c index b29e9dfd81a6..07fb8a9dac63 100644 --- a/drivers/tty/serial/samsung_tty.c +++ b/drivers/tty/serial/samsung_tty.c @@ -759,9 +759,10 @@ finish: static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport) { struct uart_port *port = &ourport->port; - unsigned int ufcon, ch, flag, ufstat, uerstat; + unsigned int ufcon, ufstat, uerstat; unsigned int fifocnt = 0; int max_count = port->fifosize; + u8 ch, flag; while (max_count-- > 0) { /* @@ -2273,9 +2274,8 @@ static int s3c24xx_serial_resume_noirq(struct device *dev) } static const struct dev_pm_ops s3c24xx_serial_pm_ops = { - .suspend = s3c24xx_serial_suspend, - .resume = s3c24xx_serial_resume, - .resume_noirq = s3c24xx_serial_resume_noirq, + SET_SYSTEM_SLEEP_PM_OPS(s3c24xx_serial_suspend, s3c24xx_serial_resume) + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(NULL, s3c24xx_serial_resume_noirq) }; #define SERIAL_SAMSUNG_PM_OPS (&s3c24xx_serial_pm_ops) diff --git a/drivers/tty/serial/sb1250-duart.c b/drivers/tty/serial/sb1250-duart.c index b6de0dc51f29..f3cd69346482 100644 --- a/drivers/tty/serial/sb1250-duart.c +++ b/drivers/tty/serial/sb1250-duart.c @@ -331,8 +331,9 @@ static void sbd_receive_chars(struct sbd_port *sport) { struct uart_port *uport = &sport->port; struct uart_icount *icount; - unsigned int status, ch, flag; + unsigned int status; int count; + u8 ch, flag; for (count = 16; count; count--) { status = read_sbdchn(sport, R_DUART_STATUS); diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index 2e7e7c409cf2..f61d98e09dc3 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -236,7 +236,8 @@ /* IOControl register bits (Only 750/760) */ #define SC16IS7XX_IOCONTROL_LATCH_BIT (1 << 0) /* Enable input latching */ -#define SC16IS7XX_IOCONTROL_MODEM_BIT (1 << 1) /* Enable GPIO[7:4] as modem pins */ +#define SC16IS7XX_IOCONTROL_MODEM_A_BIT (1 << 1) /* Enable GPIO[7:4] as modem A pins */ +#define SC16IS7XX_IOCONTROL_MODEM_B_BIT (1 << 2) /* Enable GPIO[3:0] as modem B pins */ #define SC16IS7XX_IOCONTROL_SRESET_BIT (1 << 3) /* Software Reset */ /* EFCR register bits */ @@ -301,12 +302,12 @@ /* Misc definitions */ #define SC16IS7XX_FIFO_SIZE (64) #define SC16IS7XX_REG_SHIFT 2 +#define SC16IS7XX_GPIOS_PER_BANK 4 struct sc16is7xx_devtype { char name[10]; int nr_gpio; int nr_uart; - int has_mctrl; }; #define SC16IS7XX_RECONF_MD (1 << 0) @@ -336,7 +337,9 @@ struct sc16is7xx_port { struct clk *clk; #ifdef CONFIG_GPIOLIB struct gpio_chip gpio; + unsigned long gpio_valid_mask; #endif + u8 mctrl_mask; unsigned char buf[SC16IS7XX_FIFO_SIZE]; struct kthread_worker kworker; struct task_struct *kworker_task; @@ -447,35 +450,30 @@ static const struct sc16is7xx_devtype sc16is74x_devtype = { .name = "SC16IS74X", .nr_gpio = 0, .nr_uart = 1, - .has_mctrl = 0, }; static const struct sc16is7xx_devtype sc16is750_devtype = { .name = "SC16IS750", - .nr_gpio = 4, + .nr_gpio = 8, .nr_uart = 1, - .has_mctrl = 1, }; static const struct sc16is7xx_devtype sc16is752_devtype = { .name = "SC16IS752", - .nr_gpio = 0, + .nr_gpio = 8, .nr_uart = 2, - .has_mctrl = 1, }; static const struct sc16is7xx_devtype sc16is760_devtype = { .name = "SC16IS760", - .nr_gpio = 4, + .nr_gpio = 8, .nr_uart = 1, - .has_mctrl = 1, }; static const struct sc16is7xx_devtype sc16is762_devtype = { .name = "SC16IS762", - .nr_gpio = 0, + .nr_gpio = 8, .nr_uart = 2, - .has_mctrl = 1, }; static bool sc16is7xx_regmap_volatile(struct device *dev, unsigned int reg) @@ -488,6 +486,7 @@ static bool sc16is7xx_regmap_volatile(struct device *dev, unsigned int reg) case SC16IS7XX_TXLVL_REG: case SC16IS7XX_RXLVL_REG: case SC16IS7XX_IOSTATE_REG: + case SC16IS7XX_IOCONTROL_REG: return true; default: break; @@ -578,8 +577,9 @@ static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen, unsigned int iir) { struct sc16is7xx_port *s = dev_get_drvdata(port->dev); - unsigned int lsr = 0, ch, flag, bytes_read, i; + unsigned int lsr = 0, bytes_read, i; bool read_lsr = (iir == SC16IS7XX_IIR_RLSE_SRC) ? true : false; + u8 ch, flag; if (unlikely(rxlen >= sizeof(s->buf))) { dev_warn_ratelimited(port->dev, @@ -1342,14 +1342,113 @@ static int sc16is7xx_gpio_direction_output(struct gpio_chip *chip, state |= BIT(offset); else state &= ~BIT(offset); - sc16is7xx_port_write(port, SC16IS7XX_IOSTATE_REG, state); + + /* + * If we write IOSTATE first, and then IODIR, the output value is not + * transferred to the corresponding I/O pin. + * The datasheet states that each register bit will be transferred to + * the corresponding I/O pin programmed as output when writing to + * IOSTATE. Therefore, configure direction first with IODIR, and then + * set value after with IOSTATE. + */ sc16is7xx_port_update(port, SC16IS7XX_IODIR_REG, BIT(offset), BIT(offset)); + sc16is7xx_port_write(port, SC16IS7XX_IOSTATE_REG, state); return 0; } + +static int sc16is7xx_gpio_init_valid_mask(struct gpio_chip *chip, + unsigned long *valid_mask, + unsigned int ngpios) +{ + struct sc16is7xx_port *s = gpiochip_get_data(chip); + + *valid_mask = s->gpio_valid_mask; + + return 0; +} + +static int sc16is7xx_setup_gpio_chip(struct sc16is7xx_port *s) +{ + struct device *dev = s->p[0].port.dev; + + if (!s->devtype->nr_gpio) + return 0; + + switch (s->mctrl_mask) { + case 0: + s->gpio_valid_mask = GENMASK(7, 0); + break; + case SC16IS7XX_IOCONTROL_MODEM_A_BIT: + s->gpio_valid_mask = GENMASK(3, 0); + break; + case SC16IS7XX_IOCONTROL_MODEM_B_BIT: + s->gpio_valid_mask = GENMASK(7, 4); + break; + default: + break; + } + + if (s->gpio_valid_mask == 0) + return 0; + + s->gpio.owner = THIS_MODULE; + s->gpio.parent = dev; + s->gpio.label = dev_name(dev); + s->gpio.init_valid_mask = sc16is7xx_gpio_init_valid_mask; + s->gpio.direction_input = sc16is7xx_gpio_direction_input; + s->gpio.get = sc16is7xx_gpio_get; + s->gpio.direction_output = sc16is7xx_gpio_direction_output; + s->gpio.set = sc16is7xx_gpio_set; + s->gpio.base = -1; + s->gpio.ngpio = s->devtype->nr_gpio; + s->gpio.can_sleep = 1; + + return gpiochip_add_data(&s->gpio, s); +} #endif +/* + * Configure ports designated to operate as modem control lines. + */ +static int sc16is7xx_setup_mctrl_ports(struct sc16is7xx_port *s) +{ + int i; + int ret; + int count; + u32 mctrl_port[2]; + struct device *dev = s->p[0].port.dev; + + count = device_property_count_u32(dev, "nxp,modem-control-line-ports"); + if (count < 0 || count > ARRAY_SIZE(mctrl_port)) + return 0; + + ret = device_property_read_u32_array(dev, "nxp,modem-control-line-ports", + mctrl_port, count); + if (ret) + return ret; + + s->mctrl_mask = 0; + + for (i = 0; i < count; i++) { + /* Use GPIO lines as modem control lines */ + if (mctrl_port[i] == 0) + s->mctrl_mask |= SC16IS7XX_IOCONTROL_MODEM_A_BIT; + else if (mctrl_port[i] == 1) + s->mctrl_mask |= SC16IS7XX_IOCONTROL_MODEM_B_BIT; + } + + if (s->mctrl_mask) + regmap_update_bits( + s->regmap, + SC16IS7XX_IOCONTROL_REG << SC16IS7XX_REG_SHIFT, + SC16IS7XX_IOCONTROL_MODEM_A_BIT | + SC16IS7XX_IOCONTROL_MODEM_B_BIT, s->mctrl_mask); + + return 0; +} + static const struct serial_rs485 sc16is7xx_rs485_supported = { .flags = SER_RS485_ENABLED | SER_RS485_RTS_AFTER_SEND, .delay_rts_before_send = 1, @@ -1436,6 +1535,12 @@ static int sc16is7xx_probe(struct device *dev, s->p[i].port.fifosize = SC16IS7XX_FIFO_SIZE; s->p[i].port.flags = UPF_FIXED_TYPE | UPF_LOW_LATENCY; s->p[i].port.iobase = i; + /* + * Use all ones as membase to make sure uart_configure_port() in + * serial_core.c does not abort for SPI/I2C devices where the + * membase address is not applicable. + */ + s->p[i].port.membase = (void __iomem *)~0; s->p[i].port.iotype = UPIO_PORT; s->p[i].port.uartclk = freq; s->p[i].port.rs485_config = sc16is7xx_config_rs485; @@ -1449,6 +1554,10 @@ static int sc16is7xx_probe(struct device *dev, goto out_ports; } + ret = uart_get_rs485_mode(&s->p[i].port); + if (ret) + goto out_ports; + /* Disable all interrupts */ sc16is7xx_port_write(&s->p[i].port, SC16IS7XX_IER_REG, 0); /* Disable TX/RX */ @@ -1456,12 +1565,6 @@ static int sc16is7xx_probe(struct device *dev, SC16IS7XX_EFCR_RXDISABLE_BIT | SC16IS7XX_EFCR_TXDISABLE_BIT); - /* Use GPIO lines as modem status registers */ - if (devtype->has_mctrl) - sc16is7xx_port_write(&s->p[i].port, - SC16IS7XX_IOCONTROL_REG, - SC16IS7XX_IOCONTROL_MODEM_BIT); - /* Initialize kthread work structs */ kthread_init_work(&s->p[i].tx_work, sc16is7xx_tx_proc); kthread_init_work(&s->p[i].reg_work, sc16is7xx_reg_proc); @@ -1499,23 +1602,14 @@ static int sc16is7xx_probe(struct device *dev, s->p[u].irda_mode = true; } + ret = sc16is7xx_setup_mctrl_ports(s); + if (ret) + goto out_ports; + #ifdef CONFIG_GPIOLIB - if (devtype->nr_gpio) { - /* Setup GPIO cotroller */ - s->gpio.owner = THIS_MODULE; - s->gpio.parent = dev; - s->gpio.label = dev_name(dev); - s->gpio.direction_input = sc16is7xx_gpio_direction_input; - s->gpio.get = sc16is7xx_gpio_get; - s->gpio.direction_output = sc16is7xx_gpio_direction_output; - s->gpio.set = sc16is7xx_gpio_set; - s->gpio.base = -1; - s->gpio.ngpio = devtype->nr_gpio; - s->gpio.can_sleep = 1; - ret = gpiochip_add_data(&s->gpio, s); - if (ret) - goto out_thread; - } + ret = sc16is7xx_setup_gpio_chip(s); + if (ret) + goto out_ports; #endif /* @@ -1538,10 +1632,8 @@ static int sc16is7xx_probe(struct device *dev, return 0; #ifdef CONFIG_GPIOLIB - if (devtype->nr_gpio) + if (s->gpio_valid_mask) gpiochip_remove(&s->gpio); - -out_thread: #endif out_ports: @@ -1564,7 +1656,7 @@ static void sc16is7xx_remove(struct device *dev) int i; #ifdef CONFIG_GPIOLIB - if (s->devtype->nr_gpio) + if (s->gpio_valid_mask) gpiochip_remove(&s->gpio); #endif diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c index 4f2fc5f7bb19..2be2c1098025 100644 --- a/drivers/tty/serial/sccnxp.c +++ b/drivers/tty/serial/sccnxp.c @@ -383,8 +383,7 @@ static void sccnxp_set_bit(struct uart_port *port, int sig, int state) static void sccnxp_handle_rx(struct uart_port *port) { - u8 sr; - unsigned int ch, flag; + u8 sr, ch, flag; for (;;) { sr = sccnxp_port_read(port, SCCNXP_SR_REG); @@ -880,14 +879,14 @@ MODULE_DEVICE_TABLE(platform, sccnxp_id_table); static int sccnxp_probe(struct platform_device *pdev) { - struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); struct sccnxp_pdata *pdata = dev_get_platdata(&pdev->dev); + struct resource *res; int i, ret, uartclk; struct sccnxp_port *s; void __iomem *membase; struct clk *clk; - membase = devm_ioremap_resource(&pdev->dev, res); + membase = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(membase)) return PTR_ERR(membase); diff --git a/drivers/tty/serial/serial-tegra.c b/drivers/tty/serial/serial-tegra.c index 1cf08b33456c..d4ec943cb8e9 100644 --- a/drivers/tty/serial/serial-tegra.c +++ b/drivers/tty/serial/serial-tegra.c @@ -20,7 +20,6 @@ #include <linux/irq.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/pagemap.h> #include <linux/platform_device.h> #include <linux/reset.h> @@ -434,10 +433,10 @@ static int tegra_set_baudrate(struct tegra_uart_port *tup, unsigned int baud) return 0; } -static char tegra_uart_decode_rx_error(struct tegra_uart_port *tup, +static u8 tegra_uart_decode_rx_error(struct tegra_uart_port *tup, unsigned long lsr) { - char flag = TTY_NORMAL; + u8 flag = TTY_NORMAL; if (unlikely(lsr & TEGRA_UART_LSR_ANY)) { if (lsr & UART_LSR_OE) { @@ -642,9 +641,8 @@ static void tegra_uart_handle_rx_pio(struct tegra_uart_port *tup, struct tty_port *port) { do { - char flag = TTY_NORMAL; unsigned long lsr = 0; - unsigned char ch; + u8 ch, flag = TTY_NORMAL; lsr = tegra_uart_read(tup, UART_LSR); if (!(lsr & UART_LSR_DR)) @@ -998,7 +996,11 @@ static int tegra_uart_hw_init(struct tegra_uart_port *tup) tup->ier_shadow = 0; tup->current_baud = 0; - clk_prepare_enable(tup->uart_clk); + ret = clk_prepare_enable(tup->uart_clk); + if (ret) { + dev_err(tup->uport.dev, "could not enable clk\n"); + return ret; + } /* Reset the UART controller to clear all previous status.*/ reset_control_assert(tup->rst); @@ -1579,22 +1581,15 @@ static int tegra_uart_probe(struct platform_device *pdev) tup->cdata = cdata; platform_set_drvdata(pdev, tup); - resource = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!resource) { - dev_err(&pdev->dev, "No IO memory resource\n"); - return -ENODEV; - } - u->mapbase = resource->start; - u->membase = devm_ioremap_resource(&pdev->dev, resource); + u->membase = devm_platform_get_and_ioremap_resource(pdev, 0, &resource); if (IS_ERR(u->membase)) return PTR_ERR(u->membase); + u->mapbase = resource->start; tup->uart_clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(tup->uart_clk)) { - dev_err(&pdev->dev, "Couldn't get the clock\n"); - return PTR_ERR(tup->uart_clk); - } + if (IS_ERR(tup->uart_clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(tup->uart_clk), "Couldn't get the clock"); tup->rst = devm_reset_control_get_exclusive(&pdev->dev, "serial"); if (IS_ERR(tup->rst)) { diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 831d033611e6..7bdc21d5e13b 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -133,9 +133,8 @@ static void uart_stop(struct tty_struct *tty) uart_port_unlock(port, flags); } -static void __uart_start(struct tty_struct *tty) +static void __uart_start(struct uart_state *state) { - struct uart_state *state = tty->driver_data; struct uart_port *port = state->uart_port; struct serial_port_device *port_dev; int err; @@ -170,7 +169,7 @@ static void uart_start(struct tty_struct *tty) unsigned long flags; port = uart_port_lock(state, flags); - __uart_start(tty); + __uart_start(state); uart_port_unlock(port, flags); } @@ -239,7 +238,7 @@ static void uart_change_line_settings(struct tty_struct *tty, struct uart_state if (!old_hw_stopped) uport->ops->stop_tx(uport); else - __uart_start(tty); + __uart_start(state); } spin_unlock_irq(&uport->lock); } @@ -552,7 +551,7 @@ uart_get_divisor(struct uart_port *port, unsigned int baud) } EXPORT_SYMBOL(uart_get_divisor); -static int uart_put_char(struct tty_struct *tty, unsigned char c) +static int uart_put_char(struct tty_struct *tty, u8 c) { struct uart_state *state = tty->driver_data; struct uart_port *port; @@ -581,8 +580,7 @@ static void uart_flush_chars(struct tty_struct *tty) uart_start(tty); } -static int uart_write(struct tty_struct *tty, - const unsigned char *buf, int count) +static ssize_t uart_write(struct tty_struct *tty, const u8 *buf, size_t count) { struct uart_state *state = tty->driver_data; struct uart_port *port; @@ -594,10 +592,8 @@ static int uart_write(struct tty_struct *tty, * This means you called this function _after_ the port was * closed. No cookie for you. */ - if (!state) { - WARN_ON(1); + if (WARN_ON(!state)) return -EL3HLT; - } port = uart_port_lock(state, flags); circ = &state->xmit; @@ -619,7 +615,7 @@ static int uart_write(struct tty_struct *tty, ret += c; } - __uart_start(tty); + __uart_start(state); uart_port_unlock(port, flags); return ret; } @@ -660,10 +656,8 @@ static void uart_flush_buffer(struct tty_struct *tty) * This means you called this function _after_ the port was * closed. No cookie for you. */ - if (!state) { - WARN_ON(1); + if (WARN_ON(!state)) return; - } pr_debug("uart_flush_buffer(%d) called\n", tty->index); @@ -3486,7 +3480,7 @@ EXPORT_SYMBOL_GPL(uart_handle_cts_change); * @flag: flag for the character (see TTY_NORMAL and friends) */ void uart_insert_char(struct uart_port *port, unsigned int status, - unsigned int overrun, unsigned int ch, unsigned int flag) + unsigned int overrun, u8 ch, u8 flag) { struct tty_port *tport = &port->state->port; @@ -3505,7 +3499,7 @@ void uart_insert_char(struct uart_port *port, unsigned int status, EXPORT_SYMBOL_GPL(uart_insert_char); #ifdef CONFIG_MAGIC_SYSRQ_SERIAL -static const char sysrq_toggle_seq[] = CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE; +static const u8 sysrq_toggle_seq[] = CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE; static void uart_sysrq_on(struct work_struct *w) { @@ -3528,7 +3522,7 @@ static DECLARE_WORK(sysrq_enable_work, uart_sysrq_on); * Returns: %false if @ch is out of enabling sequence and should be * handled some other way, %true if @ch was consumed. */ -bool uart_try_toggle_sysrq(struct uart_port *port, unsigned int ch) +bool uart_try_toggle_sysrq(struct uart_port *port, u8 ch) { int sysrq_toggle_seq_len = strlen(sysrq_toggle_seq); diff --git a/drivers/tty/serial/serial_txx9.c b/drivers/tty/serial/serial_txx9.c index eab387b01e36..be08fb6f749c 100644 --- a/drivers/tty/serial/serial_txx9.c +++ b/drivers/tty/serial/serial_txx9.c @@ -246,11 +246,10 @@ static void serial_txx9_initialize(struct uart_port *up) static inline void receive_chars(struct uart_port *up, unsigned int *status) { - unsigned char ch; unsigned int disr = *status; int max_count = 256; - char flag; unsigned int next_ignore_status_mask; + u8 ch, flag; do { ch = sio_in(up, TXX9_SIRFIFO); diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 8b7a42e05d6d..a560b729fa3b 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -35,7 +35,6 @@ #include <linux/module.h> #include <linux/mm.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/reset.h> diff --git a/drivers/tty/serial/sifive.c b/drivers/tty/serial/sifive.c index a19db49327e2..d195c5de52e7 100644 --- a/drivers/tty/serial/sifive.c +++ b/drivers/tty/serial/sifive.c @@ -402,9 +402,9 @@ static char __ssp_receive_char(struct sifive_serial_port *ssp, char *is_empty) */ static void __ssp_receive_chars(struct sifive_serial_port *ssp) { - unsigned char ch; char is_empty; int c; + u8 ch; for (c = SIFIVE_RX_FIFO_DEPTH; c > 0; --c) { ch = __ssp_receive_char(ssp, &is_empty); @@ -917,12 +917,9 @@ static int sifive_serial_probe(struct platform_device *pdev) if (irq < 0) return -EPROBE_DEFER; - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, mem); - if (IS_ERR(base)) { - dev_err(&pdev->dev, "could not acquire device memory\n"); + base = devm_platform_get_and_ioremap_resource(pdev, 0, &mem); + if (IS_ERR(base)) return PTR_ERR(base); - } clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(clk)) { @@ -1022,6 +1019,23 @@ static int sifive_serial_remove(struct platform_device *dev) return 0; } +static int sifive_serial_suspend(struct device *dev) +{ + struct sifive_serial_port *ssp = dev_get_drvdata(dev); + + return uart_suspend_port(&sifive_serial_uart_driver, &ssp->port); +} + +static int sifive_serial_resume(struct device *dev) +{ + struct sifive_serial_port *ssp = dev_get_drvdata(dev); + + return uart_resume_port(&sifive_serial_uart_driver, &ssp->port); +} + +DEFINE_SIMPLE_DEV_PM_OPS(sifive_uart_pm_ops, sifive_serial_suspend, + sifive_serial_resume); + static const struct of_device_id sifive_serial_of_match[] = { { .compatible = "sifive,fu540-c000-uart0" }, { .compatible = "sifive,uart0" }, @@ -1034,7 +1048,8 @@ static struct platform_driver sifive_serial_platform_driver = { .remove = sifive_serial_remove, .driver = { .name = SIFIVE_SERIAL_NAME, - .of_match_table = of_match_ptr(sifive_serial_of_match), + .pm = pm_sleep_ptr(&sifive_uart_pm_ops), + .of_match_table = sifive_serial_of_match, }, }; diff --git a/drivers/tty/serial/sprd_serial.c b/drivers/tty/serial/sprd_serial.c index b58f51296ace..f328fa57231f 100644 --- a/drivers/tty/serial/sprd_serial.c +++ b/drivers/tty/serial/sprd_serial.c @@ -364,7 +364,7 @@ static void sprd_rx_free_buf(struct sprd_uart_port *sp) if (sp->rx_dma.virt) dma_free_coherent(sp->port.dev, SPRD_UART_RX_SIZE, sp->rx_dma.virt, sp->rx_dma.phys_addr); - + sp->rx_dma.virt = NULL; } static int sprd_rx_dma_config(struct uart_port *port, u32 burst) @@ -558,7 +558,7 @@ static void sprd_break_ctl(struct uart_port *port, int break_state) } static int handle_lsr_errors(struct uart_port *port, - unsigned int *flag, + u8 *flag, unsigned int *lsr) { int ret = 0; @@ -594,7 +594,8 @@ static inline void sprd_rx(struct uart_port *port) struct sprd_uart_port *sp = container_of(port, struct sprd_uart_port, port); struct tty_port *tty = &port->state->port; - unsigned int ch, flag, lsr, max_count = SPRD_TIMEOUT; + unsigned int lsr, max_count = SPRD_TIMEOUT; + u8 ch, flag; if (sp->rx_dma.enable) { sprd_uart_dma_irq(port); @@ -1106,7 +1107,7 @@ static bool sprd_uart_is_console(struct uart_port *uport) static int sprd_clk_init(struct uart_port *uport) { struct clk *clk_uart, *clk_parent; - struct sprd_uart_port *u = sprd_port[uport->line]; + struct sprd_uart_port *u = container_of(uport, struct sprd_uart_port, port); clk_uart = devm_clk_get(uport->dev, "uart"); if (IS_ERR(clk_uart)) { @@ -1149,22 +1150,22 @@ static int sprd_probe(struct platform_device *pdev) { struct resource *res; struct uart_port *up; + struct sprd_uart_port *sport; int irq; int index; int ret; index = of_alias_get_id(pdev->dev.of_node, "serial"); - if (index < 0 || index >= ARRAY_SIZE(sprd_port)) { + if (index < 0 || index >= UART_NR_MAX) { dev_err(&pdev->dev, "got a wrong serial alias id %d\n", index); return -EINVAL; } - sprd_port[index] = devm_kzalloc(&pdev->dev, sizeof(*sprd_port[index]), - GFP_KERNEL); - if (!sprd_port[index]) + sport = devm_kzalloc(&pdev->dev, sizeof(*sport), GFP_KERNEL); + if (!sport) return -ENOMEM; - up = &sprd_port[index]->port; + up = &sport->port; up->dev = &pdev->dev; up->line = index; up->type = PORT_SPRD; @@ -1179,8 +1180,7 @@ static int sprd_probe(struct platform_device *pdev) if (ret) return ret; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - up->membase = devm_ioremap_resource(&pdev->dev, res); + up->membase = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(up->membase)) return PTR_ERR(up->membase); @@ -1195,7 +1195,7 @@ static int sprd_probe(struct platform_device *pdev) * Allocate one dma buffer to prepare for receive transfer, in case * memory allocation failure at runtime. */ - ret = sprd_rx_alloc_buf(sprd_port[index]); + ret = sprd_rx_alloc_buf(sport); if (ret) return ret; @@ -1203,17 +1203,27 @@ static int sprd_probe(struct platform_device *pdev) ret = uart_register_driver(&sprd_uart_driver); if (ret < 0) { pr_err("Failed to register SPRD-UART driver\n"); - return ret; + goto free_rx_buf; } } + sprd_ports_num++; + sprd_port[index] = sport; ret = uart_add_one_port(&sprd_uart_driver, up); if (ret) - sprd_remove(pdev); + goto clean_port; platform_set_drvdata(pdev, up); + return 0; + +clean_port: + sprd_port[index] = NULL; + if (--sprd_ports_num == 0) + uart_unregister_driver(&sprd_uart_driver); +free_rx_buf: + sprd_rx_free_buf(sport); return ret; } diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c index aa471c9c24d9..92b9f6894006 100644 --- a/drivers/tty/serial/st-asc.c +++ b/drivers/tty/serial/st-asc.c @@ -250,7 +250,7 @@ static void asc_receive_chars(struct uart_port *port) struct tty_port *tport = &port->state->port; unsigned long status, mode; unsigned long c = 0; - char flag; + u8 flag; bool ignore_pe = false; /* @@ -691,8 +691,7 @@ static int asc_init_port(struct asc_port *ascport, port->irq = platform_get_irq(pdev, 0); port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_ST_ASC_CONSOLE); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - port->membase = devm_ioremap_resource(&pdev->dev, res); + port->membase = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(port->membase)) return PTR_ERR(port->membase); port->mapbase = res->start; @@ -704,7 +703,9 @@ static int asc_init_port(struct asc_port *ascport, if (WARN_ON(IS_ERR(ascport->clk))) return -EINVAL; /* ensure that clk rate is correct by enabling the clk */ - clk_prepare_enable(ascport->clk); + ret = clk_prepare_enable(ascport->clk); + if (ret) + return ret; ascport->port.uartclk = clk_get_rate(ascport->clk); WARN_ON(ascport->port.uartclk == 0); clk_disable_unprepare(ascport->clk); diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index e9e11a259621..5e9cf0c48813 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -289,15 +289,57 @@ static int stm32_usart_init_rs485(struct uart_port *port, return uart_get_rs485_mode(port); } -static bool stm32_usart_rx_dma_enabled(struct uart_port *port) +static bool stm32_usart_rx_dma_started(struct stm32_port *stm32_port) { - struct stm32_port *stm32_port = to_stm32_port(port); - const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; + return stm32_port->rx_ch ? stm32_port->rx_dma_busy : false; +} + +static void stm32_usart_rx_dma_terminate(struct stm32_port *stm32_port) +{ + dmaengine_terminate_async(stm32_port->rx_ch); + stm32_port->rx_dma_busy = false; +} + +static int stm32_usart_dma_pause_resume(struct stm32_port *stm32_port, + struct dma_chan *chan, + enum dma_status expected_status, + int dmaengine_pause_or_resume(struct dma_chan *), + bool stm32_usart_xx_dma_started(struct stm32_port *), + void stm32_usart_xx_dma_terminate(struct stm32_port *)) +{ + struct uart_port *port = &stm32_port->port; + enum dma_status dma_status; + int ret; + + if (!stm32_usart_xx_dma_started(stm32_port)) + return -EPERM; + + dma_status = dmaengine_tx_status(chan, chan->cookie, NULL); + if (dma_status != expected_status) + return -EAGAIN; - if (!stm32_port->rx_ch) - return false; + ret = dmaengine_pause_or_resume(chan); + if (ret) { + dev_err(port->dev, "DMA failed with error code: %d\n", ret); + stm32_usart_xx_dma_terminate(stm32_port); + } + return ret; +} - return !!(readl_relaxed(port->membase + ofs->cr3) & USART_CR3_DMAR); +static int stm32_usart_rx_dma_pause(struct stm32_port *stm32_port) +{ + return stm32_usart_dma_pause_resume(stm32_port, stm32_port->rx_ch, + DMA_IN_PROGRESS, dmaengine_pause, + stm32_usart_rx_dma_started, + stm32_usart_rx_dma_terminate); +} + +static int stm32_usart_rx_dma_resume(struct stm32_port *stm32_port) +{ + return stm32_usart_dma_pause_resume(stm32_port, stm32_port->rx_ch, + DMA_PAUSED, dmaengine_resume, + stm32_usart_rx_dma_started, + stm32_usart_rx_dma_terminate); } /* Return true when data is pending (in pio mode), and false when no data is pending. */ @@ -310,7 +352,7 @@ static bool stm32_usart_pending_rx_pio(struct uart_port *port, u32 *sr) /* Get pending characters in RDR or FIFO */ if (*sr & USART_SR_RXNE) { /* Get all pending characters from the RDR or the FIFO when using interrupts */ - if (!stm32_usart_rx_dma_enabled(port)) + if (!stm32_usart_rx_dma_started(stm32_port)) return true; /* Handle only RX data errors when using DMA */ @@ -321,7 +363,7 @@ static bool stm32_usart_pending_rx_pio(struct uart_port *port, u32 *sr) return false; } -static unsigned long stm32_usart_get_char_pio(struct uart_port *port) +static u8 stm32_usart_get_char_pio(struct uart_port *port) { struct stm32_port *stm32_port = to_stm32_port(port); const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; @@ -338,10 +380,9 @@ static unsigned int stm32_usart_receive_chars_pio(struct uart_port *port) { struct stm32_port *stm32_port = to_stm32_port(port); const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; - unsigned long c; unsigned int size = 0; u32 sr; - char flag; + u8 c, flag; while (stm32_usart_pending_rx_pio(port, &sr)) { sr |= USART_SR_DUMMY_RX; @@ -456,11 +497,12 @@ static unsigned int stm32_usart_receive_chars(struct uart_port *port, bool force u32 sr; unsigned int size = 0; - if (stm32_usart_rx_dma_enabled(port) || force_dma_flush) { + if (stm32_usart_rx_dma_started(stm32_port) || force_dma_flush) { rx_dma_status = dmaengine_tx_status(stm32_port->rx_ch, stm32_port->rx_ch->cookie, &stm32_port->rx_dma_state); - if (rx_dma_status == DMA_IN_PROGRESS) { + if (rx_dma_status == DMA_IN_PROGRESS || + rx_dma_status == DMA_PAUSED) { /* Empty DMA buffer */ size = stm32_usart_receive_chars_dma(port); sr = readl_relaxed(port->membase + ofs->isr); @@ -476,8 +518,7 @@ static unsigned int stm32_usart_receive_chars(struct uart_port *port, bool force } } else { /* Disable RX DMA */ - dmaengine_terminate_async(stm32_port->rx_ch); - stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAR); + stm32_usart_rx_dma_terminate(stm32_port); /* Fall back to interrupt mode */ dev_dbg(port->dev, "DMA error, fallback to irq mode\n"); size = stm32_usart_receive_chars_pio(port); @@ -489,6 +530,76 @@ static unsigned int stm32_usart_receive_chars(struct uart_port *port, bool force return size; } +static void stm32_usart_rx_dma_complete(void *arg) +{ + struct uart_port *port = arg; + struct tty_port *tport = &port->state->port; + unsigned int size; + unsigned long flags; + + spin_lock_irqsave(&port->lock, flags); + size = stm32_usart_receive_chars(port, false); + uart_unlock_and_check_sysrq_irqrestore(port, flags); + if (size) + tty_flip_buffer_push(tport); +} + +static int stm32_usart_rx_dma_start_or_resume(struct uart_port *port) +{ + struct stm32_port *stm32_port = to_stm32_port(port); + struct dma_async_tx_descriptor *desc; + enum dma_status rx_dma_status; + int ret; + + if (stm32_port->throttled) + return 0; + + if (stm32_port->rx_dma_busy) { + rx_dma_status = dmaengine_tx_status(stm32_port->rx_ch, + stm32_port->rx_ch->cookie, + NULL); + if (rx_dma_status == DMA_IN_PROGRESS) + return 0; + + if (rx_dma_status == DMA_PAUSED && !stm32_usart_rx_dma_resume(stm32_port)) + return 0; + + dev_err(port->dev, "DMA failed : status error.\n"); + stm32_usart_rx_dma_terminate(stm32_port); + } + + stm32_port->rx_dma_busy = true; + + stm32_port->last_res = RX_BUF_L; + /* Prepare a DMA cyclic transaction */ + desc = dmaengine_prep_dma_cyclic(stm32_port->rx_ch, + stm32_port->rx_dma_buf, + RX_BUF_L, RX_BUF_P, + DMA_DEV_TO_MEM, + DMA_PREP_INTERRUPT); + if (!desc) { + dev_err(port->dev, "rx dma prep cyclic failed\n"); + stm32_port->rx_dma_busy = false; + return -ENODEV; + } + + desc->callback = stm32_usart_rx_dma_complete; + desc->callback_param = port; + + /* Push current DMA transaction in the pending queue */ + ret = dma_submit_error(dmaengine_submit(desc)); + if (ret) { + dmaengine_terminate_sync(stm32_port->rx_ch); + stm32_port->rx_dma_busy = false; + return ret; + } + + /* Issue pending DMA requests */ + dma_async_issue_pending(stm32_port->rx_ch); + + return 0; +} + static void stm32_usart_tx_dma_terminate(struct stm32_port *stm32_port) { dmaengine_terminate_async(stm32_port->tx_ch); @@ -507,21 +618,28 @@ static bool stm32_usart_tx_dma_started(struct stm32_port *stm32_port) return stm32_port->tx_dma_busy; } -static bool stm32_usart_tx_dma_enabled(struct stm32_port *stm32_port) +static int stm32_usart_tx_dma_pause(struct stm32_port *stm32_port) { - const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; + return stm32_usart_dma_pause_resume(stm32_port, stm32_port->tx_ch, + DMA_IN_PROGRESS, dmaengine_pause, + stm32_usart_tx_dma_started, + stm32_usart_tx_dma_terminate); +} - return !!(readl_relaxed(stm32_port->port.membase + ofs->cr3) & USART_CR3_DMAT); +static int stm32_usart_tx_dma_resume(struct stm32_port *stm32_port) +{ + return stm32_usart_dma_pause_resume(stm32_port, stm32_port->tx_ch, + DMA_PAUSED, dmaengine_resume, + stm32_usart_tx_dma_started, + stm32_usart_tx_dma_terminate); } static void stm32_usart_tx_dma_complete(void *arg) { struct uart_port *port = arg; struct stm32_port *stm32port = to_stm32_port(port); - const struct stm32_usart_offsets *ofs = &stm32port->info->ofs; unsigned long flags; - stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); stm32_usart_tx_dma_terminate(stm32port); /* Let's see if we have pending data to send */ @@ -553,20 +671,6 @@ static void stm32_usart_tc_interrupt_enable(struct uart_port *port) stm32_usart_set_bits(port, ofs->cr1, USART_CR1_TCIE); } -static void stm32_usart_rx_dma_complete(void *arg) -{ - struct uart_port *port = arg; - struct tty_port *tport = &port->state->port; - unsigned int size; - unsigned long flags; - - spin_lock_irqsave(&port->lock, flags); - size = stm32_usart_receive_chars(port, false); - uart_unlock_and_check_sysrq_irqrestore(port, flags); - if (size) - tty_flip_buffer_push(tport); -} - static void stm32_usart_tx_interrupt_disable(struct uart_port *port) { struct stm32_port *stm32_port = to_stm32_port(port); @@ -592,9 +696,6 @@ static void stm32_usart_transmit_chars_pio(struct uart_port *port) const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; struct circ_buf *xmit = &port->state->xmit; - if (stm32_usart_tx_dma_enabled(stm32_port)) - stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); - while (!uart_circ_empty(xmit)) { /* Check that TDR is empty before filling FIFO */ if (!(readl_relaxed(port->membase + ofs->isr) & USART_SR_TXE)) @@ -613,14 +714,15 @@ static void stm32_usart_transmit_chars_pio(struct uart_port *port) static void stm32_usart_transmit_chars_dma(struct uart_port *port) { struct stm32_port *stm32port = to_stm32_port(port); - const struct stm32_usart_offsets *ofs = &stm32port->info->ofs; struct circ_buf *xmit = &port->state->xmit; struct dma_async_tx_descriptor *desc = NULL; unsigned int count; + int ret; if (stm32_usart_tx_dma_started(stm32port)) { - if (!stm32_usart_tx_dma_enabled(stm32port)) - stm32_usart_set_bits(port, ofs->cr3, USART_CR3_DMAT); + ret = stm32_usart_tx_dma_resume(stm32port); + if (ret < 0 && ret != -EAGAIN) + goto fallback_err; return; } @@ -665,8 +767,10 @@ static void stm32_usart_transmit_chars_dma(struct uart_port *port) desc->callback_param = port; /* Push current DMA TX transaction in the pending queue */ - if (dma_submit_error(dmaengine_submit(desc))) { - /* dma no yet started, safe to free resources */ + /* DMA no yet started, safe to free resources */ + ret = dma_submit_error(dmaengine_submit(desc)); + if (ret) { + dev_err(port->dev, "DMA failed with error code: %d\n", ret); stm32_usart_tx_dma_terminate(stm32port); goto fallback_err; } @@ -674,8 +778,6 @@ static void stm32_usart_transmit_chars_dma(struct uart_port *port) /* Issue pending DMA TX requests */ dma_async_issue_pending(stm32port->tx_ch); - stm32_usart_set_bits(port, ofs->cr3, USART_CR3_DMAT); - uart_xmit_advance(port, count); return; @@ -701,9 +803,8 @@ static void stm32_usart_transmit_chars(struct uart_port *port) } if (port->x_char) { - if (stm32_usart_tx_dma_started(stm32_port) && - stm32_usart_tx_dma_enabled(stm32_port)) - stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); + /* dma terminate may have been called in case of dma pause failure */ + stm32_usart_tx_dma_pause(stm32_port); /* Check that TDR is empty before filling FIFO */ ret = @@ -717,8 +818,9 @@ static void stm32_usart_transmit_chars(struct uart_port *port) writel_relaxed(port->x_char, port->membase + ofs->tdr); port->x_char = 0; port->icount.tx++; - if (stm32_usart_tx_dma_started(stm32_port)) - stm32_usart_set_bits(port, ofs->cr3, USART_CR3_DMAT); + + /* dma terminate may have been called in case of dma resume failure */ + stm32_usart_tx_dma_resume(stm32_port); return; } @@ -785,8 +887,8 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr) * line has been masked by HW and rx data are stacking in FIFO. */ if (!stm32_port->throttled) { - if (((sr & USART_SR_RXNE) && !stm32_usart_rx_dma_enabled(port)) || - ((sr & USART_SR_ERR_MASK) && stm32_usart_rx_dma_enabled(port))) { + if (((sr & USART_SR_RXNE) && !stm32_usart_rx_dma_started(stm32_port)) || + ((sr & USART_SR_ERR_MASK) && stm32_usart_rx_dma_started(stm32_port))) { spin_lock(&port->lock); size = stm32_usart_receive_chars(port, false); uart_unlock_and_check_sysrq(port); @@ -802,7 +904,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr) } /* Receiver timeout irq for DMA RX */ - if (stm32_usart_rx_dma_enabled(port) && !stm32_port->throttled) { + if (stm32_usart_rx_dma_started(stm32_port) && !stm32_port->throttled) { spin_lock(&port->lock); size = stm32_usart_receive_chars(port, false); uart_unlock_and_check_sysrq(port); @@ -851,11 +953,11 @@ static void stm32_usart_disable_ms(struct uart_port *port) static void stm32_usart_stop_tx(struct uart_port *port) { struct stm32_port *stm32_port = to_stm32_port(port); - const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; stm32_usart_tx_interrupt_disable(port); - if (stm32_usart_tx_dma_started(stm32_port) && stm32_usart_tx_dma_enabled(stm32_port)) - stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); + + /* dma terminate may have been called in case of dma pause failure */ + stm32_usart_tx_dma_pause(stm32_port); stm32_usart_rs485_rts_disable(port); } @@ -879,12 +981,9 @@ static void stm32_usart_start_tx(struct uart_port *port) static void stm32_usart_flush_buffer(struct uart_port *port) { struct stm32_port *stm32_port = to_stm32_port(port); - const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; - if (stm32_port->tx_ch) { + if (stm32_port->tx_ch) stm32_usart_tx_dma_terminate(stm32_port); - stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); - } } /* Throttle the remote when input buffer is about to overflow. */ @@ -897,11 +996,10 @@ static void stm32_usart_throttle(struct uart_port *port) spin_lock_irqsave(&port->lock, flags); /* - * Disable DMA request line if enabled, so the RX data gets queued into the FIFO. + * Pause DMA transfer, so the RX data gets queued into the FIFO. * Hardware flow control is triggered when RX FIFO is full. */ - if (stm32_usart_rx_dma_enabled(port)) - stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAR); + stm32_usart_rx_dma_pause(stm32_port); stm32_usart_clr_bits(port, ofs->cr1, stm32_port->cr1_irq); if (stm32_port->cr3_irq) @@ -923,14 +1021,15 @@ static void stm32_usart_unthrottle(struct uart_port *port) if (stm32_port->cr3_irq) stm32_usart_set_bits(port, ofs->cr3, stm32_port->cr3_irq); + stm32_port->throttled = false; + /* - * Switch back to DMA mode (re-enable DMA request line). + * Switch back to DMA mode (resume DMA). * Hardware flow control is stopped when FIFO is not full any more. */ if (stm32_port->rx_ch) - stm32_usart_set_bits(port, ofs->cr3, USART_CR3_DMAR); + stm32_usart_rx_dma_start_or_resume(port); - stm32_port->throttled = false; spin_unlock_irqrestore(&port->lock, flags); } @@ -941,8 +1040,7 @@ static void stm32_usart_stop_rx(struct uart_port *port) const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; /* Disable DMA request line. */ - if (stm32_port->rx_ch) - stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAR); + stm32_usart_rx_dma_pause(stm32_port); stm32_usart_clr_bits(port, ofs->cr1, stm32_port->cr1_irq); if (stm32_port->cr3_irq) @@ -954,48 +1052,6 @@ static void stm32_usart_break_ctl(struct uart_port *port, int break_state) { } -static int stm32_usart_start_rx_dma_cyclic(struct uart_port *port) -{ - struct stm32_port *stm32_port = to_stm32_port(port); - const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; - struct dma_async_tx_descriptor *desc; - int ret; - - stm32_port->last_res = RX_BUF_L; - /* Prepare a DMA cyclic transaction */ - desc = dmaengine_prep_dma_cyclic(stm32_port->rx_ch, - stm32_port->rx_dma_buf, - RX_BUF_L, RX_BUF_P, - DMA_DEV_TO_MEM, - DMA_PREP_INTERRUPT); - if (!desc) { - dev_err(port->dev, "rx dma prep cyclic failed\n"); - return -ENODEV; - } - - desc->callback = stm32_usart_rx_dma_complete; - desc->callback_param = port; - - /* Push current DMA transaction in the pending queue */ - ret = dma_submit_error(dmaengine_submit(desc)); - if (ret) { - dmaengine_terminate_sync(stm32_port->rx_ch); - return ret; - } - - /* Issue pending DMA requests */ - dma_async_issue_pending(stm32_port->rx_ch); - - /* - * DMA request line not re-enabled at resume when port is throttled. - * It will be re-enabled by unthrottle ops. - */ - if (!stm32_port->throttled) - stm32_usart_set_bits(port, ofs->cr3, USART_CR3_DMAR); - - return 0; -} - static int stm32_usart_startup(struct uart_port *port) { struct stm32_port *stm32_port = to_stm32_port(port); @@ -1021,7 +1077,7 @@ static int stm32_usart_startup(struct uart_port *port) writel_relaxed(USART_RQR_RXFRQ, port->membase + ofs->rqr); if (stm32_port->rx_ch) { - ret = stm32_usart_start_rx_dma_cyclic(port); + ret = stm32_usart_rx_dma_start_or_resume(port); if (ret) { free_irq(port->irq, port); return ret; @@ -1043,12 +1099,12 @@ static void stm32_usart_shutdown(struct uart_port *port) u32 val, isr; int ret; - if (stm32_usart_tx_dma_enabled(stm32_port)) - stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); - if (stm32_usart_tx_dma_started(stm32_port)) stm32_usart_tx_dma_terminate(stm32_port); + if (stm32_port->tx_ch) + stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); + /* Disable modem control interrupts */ stm32_usart_disable_ms(port); @@ -1067,8 +1123,10 @@ static void stm32_usart_shutdown(struct uart_port *port) dev_err(port->dev, "Transmission is not complete\n"); /* Disable RX DMA. */ - if (stm32_port->rx_ch) - dmaengine_terminate_async(stm32_port->rx_ch); + if (stm32_port->rx_ch) { + stm32_usart_rx_dma_terminate(stm32_port); + dmaengine_synchronize(stm32_port->rx_ch); + } /* flush RX & TX FIFO */ if (ofs->rqr != UNDEF_REG) @@ -1259,6 +1317,9 @@ static void stm32_usart_set_termios(struct uart_port *port, cr3 |= USART_CR3_DDRE; } + if (stm32_port->tx_ch) + cr3 |= USART_CR3_DMAT; + if (rs485conf->flags & SER_RS485_ENABLED) { stm32_usart_config_reg_rs485(&cr1, &cr3, rs485conf->delay_rts_before_send, @@ -1765,11 +1826,6 @@ static int stm32_usart_serial_remove(struct platform_device *pdev) pm_runtime_put_noidle(&pdev->dev); stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_PEIE); - cr3 = readl_relaxed(port->membase + ofs->cr3); - cr3 &= ~USART_CR3_EIE; - cr3 &= ~USART_CR3_DMAR; - cr3 &= ~USART_CR3_DDRE; - writel_relaxed(cr3, port->membase + ofs->cr3); if (stm32_port->tx_ch) { stm32_usart_of_dma_tx_remove(stm32_port, pdev); @@ -1781,7 +1837,12 @@ static int stm32_usart_serial_remove(struct platform_device *pdev) dma_release_channel(stm32_port->rx_ch); } - stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); + cr3 = readl_relaxed(port->membase + ofs->cr3); + cr3 &= ~USART_CR3_EIE; + cr3 &= ~USART_CR3_DMAR; + cr3 &= ~USART_CR3_DMAT; + cr3 &= ~USART_CR3_DDRE; + writel_relaxed(cr3, port->membase + ofs->cr3); if (stm32_port->wakeup_src) { dev_pm_clear_wake_irq(&pdev->dev); @@ -1953,7 +2014,7 @@ static int __maybe_unused stm32_usart_serial_en_wakeup(struct uart_port *port, const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; struct tty_port *tport = &port->state->port; int ret; - unsigned int size; + unsigned int size = 0; unsigned long flags; if (!stm32_port->wakeup_src || !tty_port_initialized(tport)) @@ -1975,11 +2036,10 @@ static int __maybe_unused stm32_usart_serial_en_wakeup(struct uart_port *port, */ if (stm32_port->rx_ch) { spin_lock_irqsave(&port->lock, flags); - /* Avoid race with RX IRQ when DMAR is cleared */ - stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAR); /* Poll data from DMA RX buffer if any */ - size = stm32_usart_receive_chars(port, true); - dmaengine_terminate_async(stm32_port->rx_ch); + if (!stm32_usart_rx_dma_pause(stm32_port)) + size += stm32_usart_receive_chars(port, true); + stm32_usart_rx_dma_terminate(stm32_port); uart_unlock_and_check_sysrq_irqrestore(port, flags); if (size) tty_flip_buffer_push(tport); @@ -1989,7 +2049,7 @@ static int __maybe_unused stm32_usart_serial_en_wakeup(struct uart_port *port, stm32_usart_receive_chars(port, false); } else { if (stm32_port->rx_ch) { - ret = stm32_usart_start_rx_dma_cyclic(port); + ret = stm32_usart_rx_dma_start_or_resume(port); if (ret) return ret; } diff --git a/drivers/tty/serial/stm32-usart.h b/drivers/tty/serial/stm32-usart.h index 903285b5aea7..f59f831b2a10 100644 --- a/drivers/tty/serial/stm32-usart.h +++ b/drivers/tty/serial/stm32-usart.h @@ -199,6 +199,7 @@ struct stm32_port { u32 cr3_irq; /* USART_CR3_RXFTIE */ int last_res; bool tx_dma_busy; /* dma tx transaction in progress */ + bool rx_dma_busy; /* dma rx transaction in progress */ bool throttled; /* port throttled */ bool hw_flow_control; bool swap; /* swap RX & TX pins */ diff --git a/drivers/tty/serial/sunhv.c b/drivers/tty/serial/sunhv.c index 7d38c33ef506..c671d674bce4 100644 --- a/drivers/tty/serial/sunhv.c +++ b/drivers/tty/serial/sunhv.c @@ -17,11 +17,11 @@ #include <linux/slab.h> #include <linux/delay.h> #include <linux/init.h> -#include <linux/of_device.h> +#include <linux/of.h> +#include <linux/platform_device.h> #include <asm/hypervisor.h> #include <asm/spitfire.h> -#include <asm/prom.h> #include <asm/irq.h> #include <asm/setup.h> diff --git a/drivers/tty/serial/sunplus-uart.c b/drivers/tty/serial/sunplus-uart.c index 727942c43c45..3aacd5eb414c 100644 --- a/drivers/tty/serial/sunplus-uart.c +++ b/drivers/tty/serial/sunplus-uart.c @@ -231,7 +231,7 @@ static void transmit_chars(struct uart_port *port) static void receive_chars(struct uart_port *port) { unsigned int lsr = readl(port->membase + SUP_UART_LSR); - unsigned int ch, flag; + u8 ch, flag; do { ch = readl(port->membase + SUP_UART_DATA); diff --git a/drivers/tty/serial/sunsab.c b/drivers/tty/serial/sunsab.c index 48b39fdb0397..40eeaf835bba 100644 --- a/drivers/tty/serial/sunsab.c +++ b/drivers/tty/serial/sunsab.c @@ -33,7 +33,8 @@ #include <linux/slab.h> #include <linux/delay.h> #include <linux/init.h> -#include <linux/of_device.h> +#include <linux/of.h> +#include <linux/platform_device.h> #include <linux/io.h> #include <asm/irq.h> diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c index fed052a0b931..58a4342ad0f9 100644 --- a/drivers/tty/serial/sunsu.c +++ b/drivers/tty/serial/sunsu.c @@ -37,11 +37,11 @@ #include <linux/serial_reg.h> #include <linux/init.h> #include <linux/delay.h> -#include <linux/of_device.h> +#include <linux/of.h> +#include <linux/platform_device.h> #include <linux/io.h> #include <asm/irq.h> -#include <asm/prom.h> #include <asm/setup.h> #include <linux/serial_core.h> diff --git a/drivers/tty/serial/sunzilog.c b/drivers/tty/serial/sunzilog.c index 0fbeb3dbd843..c8c71c56264c 100644 --- a/drivers/tty/serial/sunzilog.c +++ b/drivers/tty/serial/sunzilog.c @@ -33,11 +33,11 @@ #include <linux/serio.h> #endif #include <linux/init.h> -#include <linux/of_device.h> +#include <linux/of.h> +#include <linux/platform_device.h> #include <linux/io.h> #include <asm/irq.h> -#include <asm/prom.h> #include <asm/setup.h> #include <linux/serial_core.h> diff --git a/drivers/tty/serial/tegra-tcu.c b/drivers/tty/serial/tegra-tcu.c index 23500b342da7..65069daf36ec 100644 --- a/drivers/tty/serial/tegra-tcu.c +++ b/drivers/tty/serial/tegra-tcu.c @@ -7,7 +7,6 @@ #include <linux/mailbox_client.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/serial.h> #include <linux/serial_core.h> diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c index 679574893ebe..b225a78f6175 100644 --- a/drivers/tty/serial/uartlite.c +++ b/drivers/tty/serial/uartlite.c @@ -20,9 +20,6 @@ #include <linux/io.h> #include <linux/iopoll.h> #include <linux/of.h> -#include <linux/of_address.h> -#include <linux/of_device.h> -#include <linux/of_platform.h> #include <linux/clk.h> #include <linux/pm_runtime.h> diff --git a/drivers/tty/serial/ucc_uart.c b/drivers/tty/serial/ucc_uart.c index 0a370b9ea70b..b06661b80f41 100644 --- a/drivers/tty/serial/ucc_uart.c +++ b/drivers/tty/serial/ucc_uart.c @@ -17,18 +17,18 @@ */ #include <linux/module.h> +#include <linux/platform_device.h> #include <linux/serial.h> #include <linux/serial_core.h> #include <linux/slab.h> #include <linux/tty.h> #include <linux/tty_flip.h> #include <linux/io.h> +#include <linux/of.h> #include <linux/of_address.h> #include <linux/of_irq.h> -#include <linux/of_platform.h> #include <linux/dma-mapping.h> -#include <linux/fs_uart_pd.h> #include <soc/fsl/qe/ucc_slow.h> #include <linux/firmware.h> diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c index cc9157df732f..c5d5c2765119 100644 --- a/drivers/tty/serial/vt8500_serial.c +++ b/drivers/tty/serial/vt8500_serial.c @@ -14,6 +14,7 @@ #include <linux/irq.h> #include <linux/init.h> #include <linux/console.h> +#include <linux/platform_device.h> #include <linux/tty.h> #include <linux/tty_flip.h> #include <linux/serial_core.h> @@ -21,7 +22,6 @@ #include <linux/slab.h> #include <linux/clk.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/err.h> /* @@ -611,10 +611,6 @@ static int vt8500_serial_probe(struct platform_device *pdev) if (!flags) return -EINVAL; - mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mmres) - return -ENODEV; - irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; @@ -647,7 +643,7 @@ static int vt8500_serial_probe(struct platform_device *pdev) if (!vt8500_port) return -ENOMEM; - vt8500_port->uart.membase = devm_ioremap_resource(&pdev->dev, mmres); + vt8500_port->uart.membase = devm_platform_get_and_ioremap_resource(pdev, 0, &mmres); if (IS_ERR(vt8500_port->uart.membase)) return PTR_ERR(vt8500_port->uart.membase); diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 20a751663ef9..2e5e86a00a77 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -1562,8 +1562,8 @@ static int cdns_uart_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq <= 0) { - rc = -ENXIO; + if (irq < 0) { + rc = irq; goto err_out_clk_disable; } diff --git a/drivers/tty/serial/zs.c b/drivers/tty/serial/zs.c index 730c648e32ff..65ca4da6e368 100644 --- a/drivers/tty/serial/zs.c +++ b/drivers/tty/serial/zs.c @@ -539,8 +539,9 @@ static void zs_receive_chars(struct zs_port *zport) struct uart_port *uport = &zport->port; struct zs_scc *scc = zport->scc; struct uart_icount *icount; - unsigned int avail, status, ch, flag; + unsigned int avail, status; int count; + u8 ch, flag; for (count = 16; count; count--) { spin_lock(&scc->zlock); |