diff options
Diffstat (limited to 'drivers/tty/serial/8250')
30 files changed, 6620 insertions, 4031 deletions
diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index c43f74c53..1a16feac9 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -17,7 +17,7 @@ struct uart_8250_dma { int (*tx_dma)(struct uart_8250_port *p); - int (*rx_dma)(struct uart_8250_port *p, unsigned int iir); + int (*rx_dma)(struct uart_8250_port *p); /* Filter function */ dma_filter_fn fn; @@ -42,9 +42,9 @@ struct uart_8250_dma { size_t rx_size; size_t tx_size; - unsigned char tx_running:1; - unsigned char tx_err: 1; - unsigned char rx_running:1; + unsigned char tx_running; + unsigned char tx_err; + unsigned char rx_running; }; struct old_serial_port { @@ -53,11 +53,9 @@ struct old_serial_port { unsigned int port; unsigned int irq; upf_t flags; - unsigned char hub6; unsigned char io_type; unsigned char __iomem *iomem_base; unsigned short iomem_reg_shift; - unsigned long irqflags; }; struct serial8250_config { @@ -84,7 +82,6 @@ struct serial8250_config { #define UART_BUG_THRE (1 << 3) /* UART has buggy THRE reassertion */ #define UART_BUG_PARITY (1 << 4) /* UART mishandles parity if FIFO enabled */ -#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) #ifdef CONFIG_SERIAL_8250_SHARE_IRQ #define SERIAL8250_SHARE_IRQS 1 @@ -92,6 +89,18 @@ struct serial8250_config { #define SERIAL8250_SHARE_IRQS 0 #endif +#define SERIAL8250_PORT_FLAGS(_base, _irq, _flags) \ + { \ + .iobase = _base, \ + .irq = _irq, \ + .uartclk = 1843200, \ + .iotype = UPIO_PORT, \ + .flags = UPF_BOOT_AUTOCONF | (_flags), \ + } + +#define SERIAL8250_PORT(_base, _irq) SERIAL8250_PORT_FLAGS(_base, _irq, 0) + + static inline int serial_in(struct uart_8250_port *up, int offset) { return up->port.serial_in(&up->port, offset); @@ -117,6 +126,18 @@ static inline void serial_dl_write(struct uart_8250_port *up, int value) struct uart_8250_port *serial8250_get_port(int line); void serial8250_rpm_get(struct uart_8250_port *p); void serial8250_rpm_put(struct uart_8250_port *p); +int serial8250_em485_init(struct uart_8250_port *p); +void serial8250_em485_destroy(struct uart_8250_port *p); + +static inline void serial8250_out_MCR(struct uart_8250_port *up, int value) +{ + serial_out(up, UART_MCR, value); +} + +static inline int serial8250_in_MCR(struct uart_8250_port *up) +{ + return serial_in(up, UART_MCR); +} #if defined(__alpha__) && !defined(CONFIG_PCI) /* @@ -137,6 +158,12 @@ static inline int serial8250_pnp_init(void) { return 0; } static inline void serial8250_pnp_exit(void) { } #endif +#ifdef CONFIG_SERIAL_8250_FINTEK +int fintek_8250_probe(struct uart_8250_port *uart); +#else +static inline int fintek_8250_probe(struct uart_8250_port *uart) { return 0; } +#endif + #ifdef CONFIG_ARCH_OMAP1 static inline int is_omap1_8250(struct uart_8250_port *pt) { @@ -176,7 +203,8 @@ static inline int is_omap1510_8250(struct uart_8250_port *pt) #ifdef CONFIG_SERIAL_8250_DMA extern int serial8250_tx_dma(struct uart_8250_port *); -extern int serial8250_rx_dma(struct uart_8250_port *, unsigned int iir); +extern int serial8250_rx_dma(struct uart_8250_port *); +extern void serial8250_rx_dma_flush(struct uart_8250_port *); extern int serial8250_request_dma(struct uart_8250_port *); extern void serial8250_release_dma(struct uart_8250_port *); #else @@ -184,10 +212,11 @@ static inline int serial8250_tx_dma(struct uart_8250_port *p) { return -1; } -static inline int serial8250_rx_dma(struct uart_8250_port *p, unsigned int iir) +static inline int serial8250_rx_dma(struct uart_8250_port *p) { return -1; } +static inline void serial8250_rx_dma_flush(struct uart_8250_port *p) { } static inline int serial8250_request_dma(struct uart_8250_port *p) { return -1; @@ -211,3 +240,8 @@ static inline int ns16550a_goto_highspeed(struct uart_8250_port *up) } return 1; } + +static inline int serial_index(struct uart_port *port) +{ + return port->minor - 64; +} diff --git a/drivers/tty/serial/8250/8250_accent.c b/drivers/tty/serial/8250/8250_accent.c index 34b51c651..522aeae05 100644 --- a/drivers/tty/serial/8250/8250_accent.c +++ b/drivers/tty/serial/8250/8250_accent.c @@ -10,18 +10,11 @@ #include <linux/init.h> #include <linux/serial_8250.h> -#define PORT(_base,_irq) \ - { \ - .iobase = _base, \ - .irq = _irq, \ - .uartclk = 1843200, \ - .iotype = UPIO_PORT, \ - .flags = UPF_BOOT_AUTOCONF, \ - } +#include "8250.h" static struct plat_serial8250_port accent_data[] = { - PORT(0x330, 4), - PORT(0x338, 4), + SERIAL8250_PORT(0x330, 4), + SERIAL8250_PORT(0x338, 4), { }, }; diff --git a/drivers/tty/serial/8250/8250_acorn.c b/drivers/tty/serial/8250/8250_acorn.c index 549aa07c0..402dfdd49 100644 --- a/drivers/tty/serial/8250/8250_acorn.c +++ b/drivers/tty/serial/8250/8250_acorn.c @@ -70,7 +70,7 @@ serial_card_probe(struct expansion_card *ec, const struct ecard_id *id) uart.port.regshift = 2; uart.port.dev = &ec->dev; - for (i = 0; i < info->num_ports; i ++) { + for (i = 0; i < info->num_ports; i++) { uart.port.membase = info->vaddr + type->offset[i]; uart.port.mapbase = bus_addr + type->offset[i]; diff --git a/drivers/tty/serial/8250/8250_bcm2835aux.c b/drivers/tty/serial/8250/8250_bcm2835aux.c new file mode 100644 index 000000000..e10f12444 --- /dev/null +++ b/drivers/tty/serial/8250/8250_bcm2835aux.c @@ -0,0 +1,146 @@ +/* + * Serial port driver for BCM2835AUX UART + * + * Copyright (C) 2016 Martin Sperl <kernel@martin.sperl.org> + * + * Based on 8250_lpc18xx.c: + * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include <linux/clk.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> + +#include "8250.h" + +struct bcm2835aux_data { + struct uart_8250_port uart; + struct clk *clk; + int line; +}; + +static int bcm2835aux_serial_probe(struct platform_device *pdev) +{ + struct bcm2835aux_data *data; + struct resource *res; + int ret; + + /* allocate the custom structure */ + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + /* initialize data */ + spin_lock_init(&data->uart.port.lock); + data->uart.capabilities = UART_CAP_FIFO; + data->uart.port.dev = &pdev->dev; + data->uart.port.regshift = 2; + data->uart.port.type = PORT_16550; + data->uart.port.iotype = UPIO_MEM; + data->uart.port.fifosize = 8; + data->uart.port.flags = UPF_SHARE_IRQ | + UPF_FIXED_PORT | + UPF_FIXED_TYPE | + UPF_SKIP_TEST; + + /* get the clock - this also enables the HW */ + data->clk = devm_clk_get(&pdev->dev, NULL); + ret = PTR_ERR_OR_ZERO(data->clk); + if (ret) { + dev_err(&pdev->dev, "could not get clk: %d\n", ret); + return ret; + } + + /* get the interrupt */ + ret = platform_get_irq(pdev, 0); + if (ret < 0) { + dev_err(&pdev->dev, "irq not found - %i", ret); + return ret; + } + data->uart.port.irq = ret; + + /* map the main registers */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "memory resource not found"); + return -EINVAL; + } + data->uart.port.membase = devm_ioremap_resource(&pdev->dev, res); + ret = PTR_ERR_OR_ZERO(data->uart.port.membase); + if (ret) + return ret; + + /* Check for a fixed line number */ + ret = of_alias_get_id(pdev->dev.of_node, "serial"); + if (ret >= 0) + data->uart.port.line = ret; + + /* enable the clock as a last step */ + ret = clk_prepare_enable(data->clk); + if (ret) { + dev_err(&pdev->dev, "unable to enable uart clock - %d\n", + ret); + return ret; + } + + /* the HW-clock divider for bcm2835aux is 8, + * but 8250 expects a divider of 16, + * so we have to multiply the actual clock by 2 + * to get identical baudrates. + */ + data->uart.port.uartclk = clk_get_rate(data->clk) * 2; + + /* register the port */ + ret = serial8250_register_8250_port(&data->uart); + if (ret < 0) { + dev_err(&pdev->dev, "unable to register 8250 port - %d\n", + ret); + goto dis_clk; + } + data->line = ret; + + platform_set_drvdata(pdev, data); + + return 0; + +dis_clk: + clk_disable_unprepare(data->clk); + return ret; +} + +static int bcm2835aux_serial_remove(struct platform_device *pdev) +{ + struct bcm2835aux_data *data = platform_get_drvdata(pdev); + + serial8250_unregister_port(data->uart.port.line); + clk_disable_unprepare(data->clk); + + return 0; +} + +static const struct of_device_id bcm2835aux_serial_match[] = { + { .compatible = "brcm,bcm2835-aux-uart" }, + { }, +}; +MODULE_DEVICE_TABLE(of, bcm2835aux_serial_match); + +static struct platform_driver bcm2835aux_serial_driver = { + .driver = { + .name = "bcm2835-aux-uart", + .of_match_table = bcm2835aux_serial_match, + }, + .probe = bcm2835aux_serial_probe, + .remove = bcm2835aux_serial_remove, +}; +module_platform_driver(bcm2835aux_serial_driver); + +MODULE_DESCRIPTION("BCM2835 auxiliar UART driver"); +MODULE_AUTHOR("Martin Sperl <kernel@martin.sperl.org>"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/tty/serial/8250/8250_boca.c b/drivers/tty/serial/8250/8250_boca.c index d125dc107..a63b5998e 100644 --- a/drivers/tty/serial/8250/8250_boca.c +++ b/drivers/tty/serial/8250/8250_boca.c @@ -10,32 +10,25 @@ #include <linux/init.h> #include <linux/serial_8250.h> -#define PORT(_base,_irq) \ - { \ - .iobase = _base, \ - .irq = _irq, \ - .uartclk = 1843200, \ - .iotype = UPIO_PORT, \ - .flags = UPF_BOOT_AUTOCONF, \ - } +#include "8250.h" static struct plat_serial8250_port boca_data[] = { - PORT(0x100, 12), - PORT(0x108, 12), - PORT(0x110, 12), - PORT(0x118, 12), - PORT(0x120, 12), - PORT(0x128, 12), - PORT(0x130, 12), - PORT(0x138, 12), - PORT(0x140, 12), - PORT(0x148, 12), - PORT(0x150, 12), - PORT(0x158, 12), - PORT(0x160, 12), - PORT(0x168, 12), - PORT(0x170, 12), - PORT(0x178, 12), + SERIAL8250_PORT(0x100, 12), + SERIAL8250_PORT(0x108, 12), + SERIAL8250_PORT(0x110, 12), + SERIAL8250_PORT(0x118, 12), + SERIAL8250_PORT(0x120, 12), + SERIAL8250_PORT(0x128, 12), + SERIAL8250_PORT(0x130, 12), + SERIAL8250_PORT(0x138, 12), + SERIAL8250_PORT(0x140, 12), + SERIAL8250_PORT(0x148, 12), + SERIAL8250_PORT(0x150, 12), + SERIAL8250_PORT(0x158, 12), + SERIAL8250_PORT(0x160, 12), + SERIAL8250_PORT(0x168, 12), + SERIAL8250_PORT(0x170, 12), + SERIAL8250_PORT(0x178, 12), { }, }; diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 87e25a6f0..dcf43f664 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -1,25 +1,23 @@ /* - * Driver for 8250/16550-type serial ports + * Universal/legacy driver for 8250/16550-type serial ports * * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. * * Copyright (C) 2001 Russell King. * + * Supports: ISA-compatible 8250/16550 ports + * PNP 8250/16550 ports + * early_serial_setup() ports + * userspace-configurable "phantom" ports + * "serial8250" platform devices + * serial8250_register_8250_port() ports + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * - * A note about mapbase / membase - * - * mapbase is the physical address of the IO port. - * membase is an 'ioremapped' cookie. */ -#if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/ioport.h> @@ -38,11 +36,11 @@ #include <linux/slab.h> #include <linux/uaccess.h> #include <linux/pm_runtime.h> +#include <linux/io.h> #ifdef CONFIG_SPARC #include <linux/sunserialcore.h> #endif -#include <asm/io.h> #include <asm/irq.h> #include "8250.h" @@ -58,46 +56,10 @@ static unsigned int nr_uarts = CONFIG_SERIAL_8250_RUNTIME_UARTS; static struct uart_driver serial8250_reg; -static int serial_index(struct uart_port *port) -{ - return port->minor - 64; -} - static unsigned int skip_txen_test; /* force skip of txen test at init time */ -/* - * Debugging. - */ -#if 0 -#define DEBUG_AUTOCONF(fmt...) printk(fmt) -#else -#define DEBUG_AUTOCONF(fmt...) do { } while (0) -#endif - -#if 0 -#define DEBUG_INTR(fmt...) printk(fmt) -#else -#define DEBUG_INTR(fmt...) do { } while (0) -#endif - #define PASS_LIMIT 512 -#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) - - -#ifdef CONFIG_SERIAL_8250_DETECT_IRQ -#define CONFIG_SERIAL_DETECT_IRQ 1 -#endif -#ifdef CONFIG_SERIAL_8250_MANY_PORTS -#define CONFIG_SERIAL_MANY_PORTS 1 -#endif - -/* - * HUB6 is always on. This will be removed once the header - * files have been cleaned. - */ -#define CONFIG_HUB6 1 - #include <asm/serial.h> /* * SERIAL_PORT_DFNS tells us about built-in ports that have no @@ -133,1563 +95,6 @@ static struct hlist_head irq_lists[NR_IRQ_HASH]; static DEFINE_MUTEX(hash_mutex); /* Used to walk the hash */ /* - * Here we define the default xmit fifo size used for each type of UART. - */ -static const struct serial8250_config uart_config[] = { - [PORT_UNKNOWN] = { - .name = "unknown", - .fifo_size = 1, - .tx_loadsz = 1, - }, - [PORT_8250] = { - .name = "8250", - .fifo_size = 1, - .tx_loadsz = 1, - }, - [PORT_16450] = { - .name = "16450", - .fifo_size = 1, - .tx_loadsz = 1, - }, - [PORT_16550] = { - .name = "16550", - .fifo_size = 1, - .tx_loadsz = 1, - }, - [PORT_16550A] = { - .name = "16550A", - .fifo_size = 16, - .tx_loadsz = 16, - .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, - .rxtrig_bytes = {1, 4, 8, 14}, - .flags = UART_CAP_FIFO, - }, - [PORT_CIRRUS] = { - .name = "Cirrus", - .fifo_size = 1, - .tx_loadsz = 1, - }, - [PORT_16650] = { - .name = "ST16650", - .fifo_size = 1, - .tx_loadsz = 1, - .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP, - }, - [PORT_16650V2] = { - .name = "ST16650V2", - .fifo_size = 32, - .tx_loadsz = 16, - .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 | - UART_FCR_T_TRIG_00, - .rxtrig_bytes = {8, 16, 24, 28}, - .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP, - }, - [PORT_16750] = { - .name = "TI16750", - .fifo_size = 64, - .tx_loadsz = 64, - .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 | - UART_FCR7_64BYTE, - .rxtrig_bytes = {1, 16, 32, 56}, - .flags = UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_AFE, - }, - [PORT_STARTECH] = { - .name = "Startech", - .fifo_size = 1, - .tx_loadsz = 1, - }, - [PORT_16C950] = { - .name = "16C950/954", - .fifo_size = 128, - .tx_loadsz = 128, - .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, - /* UART_CAP_EFR breaks billionon CF bluetooth card. */ - .flags = UART_CAP_FIFO | UART_CAP_SLEEP, - }, - [PORT_16654] = { - .name = "ST16654", - .fifo_size = 64, - .tx_loadsz = 32, - .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 | - UART_FCR_T_TRIG_10, - .rxtrig_bytes = {8, 16, 56, 60}, - .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP, - }, - [PORT_16850] = { - .name = "XR16850", - .fifo_size = 128, - .tx_loadsz = 128, - .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, - .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP, - }, - [PORT_RSA] = { - .name = "RSA", - .fifo_size = 2048, - .tx_loadsz = 2048, - .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_11, - .flags = UART_CAP_FIFO, - }, - [PORT_NS16550A] = { - .name = "NS16550A", - .fifo_size = 16, - .tx_loadsz = 16, - .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, - .flags = UART_CAP_FIFO | UART_NATSEMI, - }, - [PORT_XSCALE] = { - .name = "XScale", - .fifo_size = 32, - .tx_loadsz = 32, - .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, - .flags = UART_CAP_FIFO | UART_CAP_UUE | UART_CAP_RTOIE, - }, - [PORT_OCTEON] = { - .name = "OCTEON", - .fifo_size = 64, - .tx_loadsz = 64, - .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, - .flags = UART_CAP_FIFO, - }, - [PORT_AR7] = { - .name = "AR7", - .fifo_size = 16, - .tx_loadsz = 16, - .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00, - .flags = UART_CAP_FIFO | UART_CAP_AFE, - }, - [PORT_U6_16550A] = { - .name = "U6_16550A", - .fifo_size = 64, - .tx_loadsz = 64, - .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, - .flags = UART_CAP_FIFO | UART_CAP_AFE, - }, - [PORT_TEGRA] = { - .name = "Tegra", - .fifo_size = 32, - .tx_loadsz = 8, - .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 | - UART_FCR_T_TRIG_01, - .rxtrig_bytes = {1, 4, 8, 14}, - .flags = UART_CAP_FIFO | UART_CAP_RTOIE, - }, - [PORT_XR17D15X] = { - .name = "XR17D15X", - .fifo_size = 64, - .tx_loadsz = 64, - .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, - .flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR | - UART_CAP_SLEEP, - }, - [PORT_XR17V35X] = { - .name = "XR17V35X", - .fifo_size = 256, - .tx_loadsz = 256, - .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_11 | - UART_FCR_T_TRIG_11, - .flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR | - UART_CAP_SLEEP, - }, - [PORT_LPC3220] = { - .name = "LPC3220", - .fifo_size = 64, - .tx_loadsz = 32, - .fcr = UART_FCR_DMA_SELECT | UART_FCR_ENABLE_FIFO | - UART_FCR_R_TRIG_00 | UART_FCR_T_TRIG_00, - .flags = UART_CAP_FIFO, - }, - [PORT_BRCM_TRUMANAGE] = { - .name = "TruManage", - .fifo_size = 1, - .tx_loadsz = 1024, - .flags = UART_CAP_HFIFO, - }, - [PORT_8250_CIR] = { - .name = "CIR port" - }, - [PORT_ALTR_16550_F32] = { - .name = "Altera 16550 FIFO32", - .fifo_size = 32, - .tx_loadsz = 32, - .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, - .flags = UART_CAP_FIFO | UART_CAP_AFE, - }, - [PORT_ALTR_16550_F64] = { - .name = "Altera 16550 FIFO64", - .fifo_size = 64, - .tx_loadsz = 64, - .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, - .flags = UART_CAP_FIFO | UART_CAP_AFE, - }, - [PORT_ALTR_16550_F128] = { - .name = "Altera 16550 FIFO128", - .fifo_size = 128, - .tx_loadsz = 128, - .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, - .flags = UART_CAP_FIFO | UART_CAP_AFE, - }, -/* tx_loadsz is set to 63-bytes instead of 64-bytes to implement -workaround of errata A-008006 which states that tx_loadsz should be -configured less than Maximum supported fifo bytes */ - [PORT_16550A_FSL64] = { - .name = "16550A_FSL64", - .fifo_size = 64, - .tx_loadsz = 63, - .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 | - UART_FCR7_64BYTE, - .flags = UART_CAP_FIFO, - }, -}; - -/* Uart divisor latch read */ -static int default_serial_dl_read(struct uart_8250_port *up) -{ - return serial_in(up, UART_DLL) | serial_in(up, UART_DLM) << 8; -} - -/* Uart divisor latch write */ -static void default_serial_dl_write(struct uart_8250_port *up, int value) -{ - serial_out(up, UART_DLL, value & 0xff); - serial_out(up, UART_DLM, value >> 8 & 0xff); -} - -#if defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_SERIAL_8250_RT288X) - -/* Au1x00/RT288x UART hardware has a weird register layout */ -static const s8 au_io_in_map[8] = { - 0, /* UART_RX */ - 2, /* UART_IER */ - 3, /* UART_IIR */ - 5, /* UART_LCR */ - 6, /* UART_MCR */ - 7, /* UART_LSR */ - 8, /* UART_MSR */ - -1, /* UART_SCR (unmapped) */ -}; - -static const s8 au_io_out_map[8] = { - 1, /* UART_TX */ - 2, /* UART_IER */ - 4, /* UART_FCR */ - 5, /* UART_LCR */ - 6, /* UART_MCR */ - -1, /* UART_LSR (unmapped) */ - -1, /* UART_MSR (unmapped) */ - -1, /* UART_SCR (unmapped) */ -}; - -static unsigned int au_serial_in(struct uart_port *p, int offset) -{ - if (offset >= ARRAY_SIZE(au_io_in_map)) - return UINT_MAX; - offset = au_io_in_map[offset]; - if (offset < 0) - return UINT_MAX; - return __raw_readl(p->membase + (offset << p->regshift)); -} - -static void au_serial_out(struct uart_port *p, int offset, int value) -{ - if (offset >= ARRAY_SIZE(au_io_out_map)) - return; - offset = au_io_out_map[offset]; - if (offset < 0) - return; - __raw_writel(value, p->membase + (offset << p->regshift)); -} - -/* Au1x00 haven't got a standard divisor latch */ -static int au_serial_dl_read(struct uart_8250_port *up) -{ - return __raw_readl(up->port.membase + 0x28); -} - -static void au_serial_dl_write(struct uart_8250_port *up, int value) -{ - __raw_writel(value, up->port.membase + 0x28); -} - -#endif - -static unsigned int hub6_serial_in(struct uart_port *p, int offset) -{ - offset = offset << p->regshift; - outb(p->hub6 - 1 + offset, p->iobase); - return inb(p->iobase + 1); -} - -static void hub6_serial_out(struct uart_port *p, int offset, int value) -{ - offset = offset << p->regshift; - outb(p->hub6 - 1 + offset, p->iobase); - outb(value, p->iobase + 1); -} - -static unsigned int mem_serial_in(struct uart_port *p, int offset) -{ - offset = offset << p->regshift; - return readb(p->membase + offset); -} - -static void mem_serial_out(struct uart_port *p, int offset, int value) -{ - offset = offset << p->regshift; - writeb(value, p->membase + offset); -} - -static void mem32_serial_out(struct uart_port *p, int offset, int value) -{ - offset = offset << p->regshift; - writel(value, p->membase + offset); -} - -static unsigned int mem32_serial_in(struct uart_port *p, int offset) -{ - offset = offset << p->regshift; - return readl(p->membase + offset); -} - -static void mem32be_serial_out(struct uart_port *p, int offset, int value) -{ - offset = offset << p->regshift; - iowrite32be(value, p->membase + offset); -} - -static unsigned int mem32be_serial_in(struct uart_port *p, int offset) -{ - offset = offset << p->regshift; - return ioread32be(p->membase + offset); -} - -static unsigned int io_serial_in(struct uart_port *p, int offset) -{ - offset = offset << p->regshift; - return inb(p->iobase + offset); -} - -static void io_serial_out(struct uart_port *p, int offset, int value) -{ - offset = offset << p->regshift; - outb(value, p->iobase + offset); -} - -static int serial8250_default_handle_irq(struct uart_port *port); -static int exar_handle_irq(struct uart_port *port); - -static void set_io_from_upio(struct uart_port *p) -{ - struct uart_8250_port *up = up_to_u8250p(p); - - up->dl_read = default_serial_dl_read; - up->dl_write = default_serial_dl_write; - - switch (p->iotype) { - case UPIO_HUB6: - p->serial_in = hub6_serial_in; - p->serial_out = hub6_serial_out; - break; - - case UPIO_MEM: - p->serial_in = mem_serial_in; - p->serial_out = mem_serial_out; - break; - - case UPIO_MEM32: - p->serial_in = mem32_serial_in; - p->serial_out = mem32_serial_out; - break; - - case UPIO_MEM32BE: - p->serial_in = mem32be_serial_in; - p->serial_out = mem32be_serial_out; - break; - -#if defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_SERIAL_8250_RT288X) - case UPIO_AU: - p->serial_in = au_serial_in; - p->serial_out = au_serial_out; - up->dl_read = au_serial_dl_read; - up->dl_write = au_serial_dl_write; - break; -#endif - - default: - p->serial_in = io_serial_in; - p->serial_out = io_serial_out; - break; - } - /* Remember loaded iotype */ - up->cur_iotype = p->iotype; - p->handle_irq = serial8250_default_handle_irq; -} - -static void -serial_port_out_sync(struct uart_port *p, int offset, int value) -{ - switch (p->iotype) { - case UPIO_MEM: - case UPIO_MEM32: - case UPIO_MEM32BE: - case UPIO_AU: - p->serial_out(p, offset, value); - p->serial_in(p, UART_LCR); /* safe, no side-effects */ - break; - default: - p->serial_out(p, offset, value); - } -} - -/* - * For the 16C950 - */ -static void serial_icr_write(struct uart_8250_port *up, int offset, int value) -{ - serial_out(up, UART_SCR, offset); - serial_out(up, UART_ICR, value); -} - -static unsigned int serial_icr_read(struct uart_8250_port *up, int offset) -{ - unsigned int value; - - serial_icr_write(up, UART_ACR, up->acr | UART_ACR_ICRRD); - serial_out(up, UART_SCR, offset); - value = serial_in(up, UART_ICR); - serial_icr_write(up, UART_ACR, up->acr); - - return value; -} - -/* - * FIFO support. - */ -static void serial8250_clear_fifos(struct uart_8250_port *p) -{ - if (p->capabilities & UART_CAP_FIFO) { - serial_out(p, UART_FCR, UART_FCR_ENABLE_FIFO); - serial_out(p, UART_FCR, UART_FCR_ENABLE_FIFO | - UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); - serial_out(p, UART_FCR, 0); - } -} - -void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p) -{ - serial8250_clear_fifos(p); - serial_out(p, UART_FCR, p->fcr); -} -EXPORT_SYMBOL_GPL(serial8250_clear_and_reinit_fifos); - -void serial8250_rpm_get(struct uart_8250_port *p) -{ - if (!(p->capabilities & UART_CAP_RPM)) - return; - pm_runtime_get_sync(p->port.dev); -} -EXPORT_SYMBOL_GPL(serial8250_rpm_get); - -void serial8250_rpm_put(struct uart_8250_port *p) -{ - if (!(p->capabilities & UART_CAP_RPM)) - return; - pm_runtime_mark_last_busy(p->port.dev); - pm_runtime_put_autosuspend(p->port.dev); -} -EXPORT_SYMBOL_GPL(serial8250_rpm_put); - -/* - * These two wrappers ensure that enable_runtime_pm_tx() can be called more than - * once and disable_runtime_pm_tx() will still disable RPM because the fifo is - * empty and the HW can idle again. - */ -static void serial8250_rpm_get_tx(struct uart_8250_port *p) -{ - unsigned char rpm_active; - - if (!(p->capabilities & UART_CAP_RPM)) - return; - - rpm_active = xchg(&p->rpm_tx_active, 1); - if (rpm_active) - return; - pm_runtime_get_sync(p->port.dev); -} - -static void serial8250_rpm_put_tx(struct uart_8250_port *p) -{ - unsigned char rpm_active; - - if (!(p->capabilities & UART_CAP_RPM)) - return; - - rpm_active = xchg(&p->rpm_tx_active, 0); - if (!rpm_active) - return; - pm_runtime_mark_last_busy(p->port.dev); - pm_runtime_put_autosuspend(p->port.dev); -} - -/* - * IER sleep support. UARTs which have EFRs need the "extended - * capability" bit enabled. Note that on XR16C850s, we need to - * reset LCR to write to IER. - */ -static void serial8250_set_sleep(struct uart_8250_port *p, int sleep) -{ - unsigned char lcr = 0, efr = 0; - /* - * Exar UARTs have a SLEEP register that enables or disables - * each UART to enter sleep mode separately. On the XR17V35x the - * register is accessible to each UART at the UART_EXAR_SLEEP - * offset but the UART channel may only write to the corresponding - * bit. - */ - serial8250_rpm_get(p); - if ((p->port.type == PORT_XR17V35X) || - (p->port.type == PORT_XR17D15X)) { - serial_out(p, UART_EXAR_SLEEP, sleep ? 0xff : 0); - goto out; - } - - if (p->capabilities & UART_CAP_SLEEP) { - if (p->capabilities & UART_CAP_EFR) { - lcr = serial_in(p, UART_LCR); - efr = serial_in(p, UART_EFR); - serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B); - serial_out(p, UART_EFR, UART_EFR_ECB); - serial_out(p, UART_LCR, 0); - } - serial_out(p, UART_IER, sleep ? UART_IERX_SLEEP : 0); - if (p->capabilities & UART_CAP_EFR) { - serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B); - serial_out(p, UART_EFR, efr); - serial_out(p, UART_LCR, lcr); - } - } -out: - serial8250_rpm_put(p); -} - -#ifdef CONFIG_SERIAL_8250_RSA -/* - * Attempts to turn on the RSA FIFO. Returns zero on failure. - * We set the port uart clock rate if we succeed. - */ -static int __enable_rsa(struct uart_8250_port *up) -{ - unsigned char mode; - int result; - - mode = serial_in(up, UART_RSA_MSR); - result = mode & UART_RSA_MSR_FIFO; - - if (!result) { - serial_out(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO); - mode = serial_in(up, UART_RSA_MSR); - result = mode & UART_RSA_MSR_FIFO; - } - - if (result) - up->port.uartclk = SERIAL_RSA_BAUD_BASE * 16; - - return result; -} - -static void enable_rsa(struct uart_8250_port *up) -{ - if (up->port.type == PORT_RSA) { - if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16) { - spin_lock_irq(&up->port.lock); - __enable_rsa(up); - spin_unlock_irq(&up->port.lock); - } - if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) - serial_out(up, UART_RSA_FRR, 0); - } -} - -/* - * Attempts to turn off the RSA FIFO. Returns zero on failure. - * It is unknown why interrupts were disabled in here. However, - * the caller is expected to preserve this behaviour by grabbing - * the spinlock before calling this function. - */ -static void disable_rsa(struct uart_8250_port *up) -{ - unsigned char mode; - int result; - - if (up->port.type == PORT_RSA && - up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) { - spin_lock_irq(&up->port.lock); - - mode = serial_in(up, UART_RSA_MSR); - result = !(mode & UART_RSA_MSR_FIFO); - - if (!result) { - serial_out(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO); - mode = serial_in(up, UART_RSA_MSR); - result = !(mode & UART_RSA_MSR_FIFO); - } - - if (result) - up->port.uartclk = SERIAL_RSA_BAUD_BASE_LO * 16; - spin_unlock_irq(&up->port.lock); - } -} -#endif /* CONFIG_SERIAL_8250_RSA */ - -/* - * This is a quickie test to see how big the FIFO is. - * It doesn't work at all the time, more's the pity. - */ -static int size_fifo(struct uart_8250_port *up) -{ - unsigned char old_fcr, old_mcr, old_lcr; - unsigned short old_dl; - int count; - - old_lcr = serial_in(up, UART_LCR); - serial_out(up, UART_LCR, 0); - old_fcr = serial_in(up, UART_FCR); - old_mcr = serial_in(up, UART_MCR); - serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | - UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); - serial_out(up, UART_MCR, UART_MCR_LOOP); - serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); - old_dl = serial_dl_read(up); - serial_dl_write(up, 0x0001); - serial_out(up, UART_LCR, 0x03); - for (count = 0; count < 256; count++) - serial_out(up, UART_TX, count); - mdelay(20);/* FIXME - schedule_timeout */ - for (count = 0; (serial_in(up, UART_LSR) & UART_LSR_DR) && - (count < 256); count++) - serial_in(up, UART_RX); - serial_out(up, UART_FCR, old_fcr); - serial_out(up, UART_MCR, old_mcr); - serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); - serial_dl_write(up, old_dl); - serial_out(up, UART_LCR, old_lcr); - - return count; -} - -/* - * Read UART ID using the divisor method - set DLL and DLM to zero - * and the revision will be in DLL and device type in DLM. We - * preserve the device state across this. - */ -static unsigned int autoconfig_read_divisor_id(struct uart_8250_port *p) -{ - unsigned char old_dll, old_dlm, old_lcr; - unsigned int id; - - old_lcr = serial_in(p, UART_LCR); - serial_out(p, UART_LCR, UART_LCR_CONF_MODE_A); - - old_dll = serial_in(p, UART_DLL); - old_dlm = serial_in(p, UART_DLM); - - serial_out(p, UART_DLL, 0); - serial_out(p, UART_DLM, 0); - - id = serial_in(p, UART_DLL) | serial_in(p, UART_DLM) << 8; - - serial_out(p, UART_DLL, old_dll); - serial_out(p, UART_DLM, old_dlm); - serial_out(p, UART_LCR, old_lcr); - - return id; -} - -/* - * This is a helper routine to autodetect StarTech/Exar/Oxsemi UART's. - * When this function is called we know it is at least a StarTech - * 16650 V2, but it might be one of several StarTech UARTs, or one of - * its clones. (We treat the broken original StarTech 16650 V1 as a - * 16550, and why not? Startech doesn't seem to even acknowledge its - * existence.) - * - * What evil have men's minds wrought... - */ -static void autoconfig_has_efr(struct uart_8250_port *up) -{ - unsigned int id1, id2, id3, rev; - - /* - * Everything with an EFR has SLEEP - */ - up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP; - - /* - * First we check to see if it's an Oxford Semiconductor UART. - * - * If we have to do this here because some non-National - * Semiconductor clone chips lock up if you try writing to the - * LSR register (which serial_icr_read does) - */ - - /* - * Check for Oxford Semiconductor 16C950. - * - * EFR [4] must be set else this test fails. - * - * This shouldn't be necessary, but Mike Hudson (Exoray@isys.ca) - * claims that it's needed for 952 dual UART's (which are not - * recommended for new designs). - */ - up->acr = 0; - serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); - serial_out(up, UART_EFR, UART_EFR_ECB); - serial_out(up, UART_LCR, 0x00); - id1 = serial_icr_read(up, UART_ID1); - id2 = serial_icr_read(up, UART_ID2); - id3 = serial_icr_read(up, UART_ID3); - rev = serial_icr_read(up, UART_REV); - - DEBUG_AUTOCONF("950id=%02x:%02x:%02x:%02x ", id1, id2, id3, rev); - - if (id1 == 0x16 && id2 == 0xC9 && - (id3 == 0x50 || id3 == 0x52 || id3 == 0x54)) { - up->port.type = PORT_16C950; - - /* - * Enable work around for the Oxford Semiconductor 952 rev B - * chip which causes it to seriously miscalculate baud rates - * when DLL is 0. - */ - if (id3 == 0x52 && rev == 0x01) - up->bugs |= UART_BUG_QUOT; - return; - } - - /* - * We check for a XR16C850 by setting DLL and DLM to 0, and then - * reading back DLL and DLM. The chip type depends on the DLM - * value read back: - * 0x10 - XR16C850 and the DLL contains the chip revision. - * 0x12 - XR16C2850. - * 0x14 - XR16C854. - */ - id1 = autoconfig_read_divisor_id(up); - DEBUG_AUTOCONF("850id=%04x ", id1); - - id2 = id1 >> 8; - if (id2 == 0x10 || id2 == 0x12 || id2 == 0x14) { - up->port.type = PORT_16850; - return; - } - - /* - * It wasn't an XR16C850. - * - * We distinguish between the '654 and the '650 by counting - * how many bytes are in the FIFO. I'm using this for now, - * since that's the technique that was sent to me in the - * serial driver update, but I'm not convinced this works. - * I've had problems doing this in the past. -TYT - */ - if (size_fifo(up) == 64) - up->port.type = PORT_16654; - else - up->port.type = PORT_16650V2; -} - -/* - * We detected a chip without a FIFO. Only two fall into - * this category - the original 8250 and the 16450. The - * 16450 has a scratch register (accessible with LCR=0) - */ -static void autoconfig_8250(struct uart_8250_port *up) -{ - unsigned char scratch, status1, status2; - - up->port.type = PORT_8250; - - scratch = serial_in(up, UART_SCR); - serial_out(up, UART_SCR, 0xa5); - status1 = serial_in(up, UART_SCR); - serial_out(up, UART_SCR, 0x5a); - status2 = serial_in(up, UART_SCR); - serial_out(up, UART_SCR, scratch); - - if (status1 == 0xa5 && status2 == 0x5a) - up->port.type = PORT_16450; -} - -static int broken_efr(struct uart_8250_port *up) -{ - /* - * Exar ST16C2550 "A2" devices incorrectly detect as - * having an EFR, and report an ID of 0x0201. See - * http://linux.derkeiler.com/Mailing-Lists/Kernel/2004-11/4812.html - */ - if (autoconfig_read_divisor_id(up) == 0x0201 && size_fifo(up) == 16) - return 1; - - return 0; -} - -/* - * We know that the chip has FIFOs. Does it have an EFR? The - * EFR is located in the same register position as the IIR and - * we know the top two bits of the IIR are currently set. The - * EFR should contain zero. Try to read the EFR. - */ -static void autoconfig_16550a(struct uart_8250_port *up) -{ - unsigned char status1, status2; - unsigned int iersave; - - up->port.type = PORT_16550A; - up->capabilities |= UART_CAP_FIFO; - - /* - * XR17V35x UARTs have an extra divisor register, DLD - * that gets enabled with when DLAB is set which will - * cause the device to incorrectly match and assign - * port type to PORT_16650. The EFR for this UART is - * found at offset 0x09. Instead check the Deice ID (DVID) - * register for a 2, 4 or 8 port UART. - */ - if (up->port.flags & UPF_EXAR_EFR) { - status1 = serial_in(up, UART_EXAR_DVID); - if (status1 == 0x82 || status1 == 0x84 || status1 == 0x88) { - DEBUG_AUTOCONF("Exar XR17V35x "); - up->port.type = PORT_XR17V35X; - up->capabilities |= UART_CAP_AFE | UART_CAP_EFR | - UART_CAP_SLEEP; - - return; - } - - } - - /* - * Check for presence of the EFR when DLAB is set. - * Only ST16C650V1 UARTs pass this test. - */ - serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); - if (serial_in(up, UART_EFR) == 0) { - serial_out(up, UART_EFR, 0xA8); - if (serial_in(up, UART_EFR) != 0) { - DEBUG_AUTOCONF("EFRv1 "); - up->port.type = PORT_16650; - up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP; - } else { - serial_out(up, UART_LCR, 0); - serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | - UART_FCR7_64BYTE); - status1 = serial_in(up, UART_IIR) >> 5; - serial_out(up, UART_FCR, 0); - serial_out(up, UART_LCR, 0); - - if (status1 == 7) - up->port.type = PORT_16550A_FSL64; - else - DEBUG_AUTOCONF("Motorola 8xxx DUART "); - } - serial_out(up, UART_EFR, 0); - return; - } - - /* - * Maybe it requires 0xbf to be written to the LCR. - * (other ST16C650V2 UARTs, TI16C752A, etc) - */ - serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); - if (serial_in(up, UART_EFR) == 0 && !broken_efr(up)) { - DEBUG_AUTOCONF("EFRv2 "); - autoconfig_has_efr(up); - return; - } - - /* - * Check for a National Semiconductor SuperIO chip. - * Attempt to switch to bank 2, read the value of the LOOP bit - * from EXCR1. Switch back to bank 0, change it in MCR. Then - * switch back to bank 2, read it from EXCR1 again and check - * it's changed. If so, set baud_base in EXCR2 to 921600. -- dwmw2 - */ - serial_out(up, UART_LCR, 0); - status1 = serial_in(up, UART_MCR); - serial_out(up, UART_LCR, 0xE0); - status2 = serial_in(up, 0x02); /* EXCR1 */ - - if (!((status2 ^ status1) & UART_MCR_LOOP)) { - serial_out(up, UART_LCR, 0); - serial_out(up, UART_MCR, status1 ^ UART_MCR_LOOP); - serial_out(up, UART_LCR, 0xE0); - status2 = serial_in(up, 0x02); /* EXCR1 */ - serial_out(up, UART_LCR, 0); - serial_out(up, UART_MCR, status1); - - if ((status2 ^ status1) & UART_MCR_LOOP) { - unsigned short quot; - - serial_out(up, UART_LCR, 0xE0); - - quot = serial_dl_read(up); - quot <<= 3; - - if (ns16550a_goto_highspeed(up)) - serial_dl_write(up, quot); - - serial_out(up, UART_LCR, 0); - - up->port.uartclk = 921600*16; - up->port.type = PORT_NS16550A; - up->capabilities |= UART_NATSEMI; - return; - } - } - - /* - * No EFR. Try to detect a TI16750, which only sets bit 5 of - * the IIR when 64 byte FIFO mode is enabled when DLAB is set. - * Try setting it with and without DLAB set. Cheap clones - * set bit 5 without DLAB set. - */ - serial_out(up, UART_LCR, 0); - serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE); - status1 = serial_in(up, UART_IIR) >> 5; - serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO); - serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); - serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE); - status2 = serial_in(up, UART_IIR) >> 5; - serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO); - serial_out(up, UART_LCR, 0); - - DEBUG_AUTOCONF("iir1=%d iir2=%d ", status1, status2); - - if (status1 == 6 && status2 == 7) { - up->port.type = PORT_16750; - up->capabilities |= UART_CAP_AFE | UART_CAP_SLEEP; - return; - } - - /* - * Try writing and reading the UART_IER_UUE bit (b6). - * If it works, this is probably one of the Xscale platform's - * internal UARTs. - * We're going to explicitly set the UUE bit to 0 before - * trying to write and read a 1 just to make sure it's not - * already a 1 and maybe locked there before we even start start. - */ - iersave = serial_in(up, UART_IER); - serial_out(up, UART_IER, iersave & ~UART_IER_UUE); - if (!(serial_in(up, UART_IER) & UART_IER_UUE)) { - /* - * OK it's in a known zero state, try writing and reading - * without disturbing the current state of the other bits. - */ - serial_out(up, UART_IER, iersave | UART_IER_UUE); - if (serial_in(up, UART_IER) & UART_IER_UUE) { - /* - * It's an Xscale. - * We'll leave the UART_IER_UUE bit set to 1 (enabled). - */ - DEBUG_AUTOCONF("Xscale "); - up->port.type = PORT_XSCALE; - up->capabilities |= UART_CAP_UUE | UART_CAP_RTOIE; - return; - } - } else { - /* - * If we got here we couldn't force the IER_UUE bit to 0. - * Log it and continue. - */ - DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 "); - } - serial_out(up, UART_IER, iersave); - - /* - * Exar uarts have EFR in a weird location - */ - if (up->port.flags & UPF_EXAR_EFR) { - DEBUG_AUTOCONF("Exar XR17D15x "); - up->port.type = PORT_XR17D15X; - up->capabilities |= UART_CAP_AFE | UART_CAP_EFR | - UART_CAP_SLEEP; - - return; - } - - /* - * We distinguish between 16550A and U6 16550A by counting - * how many bytes are in the FIFO. - */ - if (up->port.type == PORT_16550A && size_fifo(up) == 64) { - up->port.type = PORT_U6_16550A; - up->capabilities |= UART_CAP_AFE; - } -} - -/* - * This routine is called by rs_init() to initialize a specific serial - * port. It determines what type of UART chip this serial port is - * using: 8250, 16450, 16550, 16550A. The important question is - * whether or not this UART is a 16550A or not, since this will - * determine whether or not we can use its FIFO features or not. - */ -static void autoconfig(struct uart_8250_port *up) -{ - unsigned char status1, scratch, scratch2, scratch3; - unsigned char save_lcr, save_mcr; - struct uart_port *port = &up->port; - unsigned long flags; - unsigned int old_capabilities; - - if (!port->iobase && !port->mapbase && !port->membase) - return; - - DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04lx, 0x%p): ", - serial_index(port), port->iobase, port->membase); - - /* - * We really do need global IRQs disabled here - we're going to - * be frobbing the chips IRQ enable register to see if it exists. - */ - spin_lock_irqsave(&port->lock, flags); - - up->capabilities = 0; - up->bugs = 0; - - if (!(port->flags & UPF_BUGGY_UART)) { - /* - * Do a simple existence test first; if we fail this, - * there's no point trying anything else. - * - * 0x80 is used as a nonsense port to prevent against - * false positives due to ISA bus float. The - * assumption is that 0x80 is a non-existent port; - * which should be safe since include/asm/io.h also - * makes this assumption. - * - * Note: this is safe as long as MCR bit 4 is clear - * and the device is in "PC" mode. - */ - scratch = serial_in(up, UART_IER); - serial_out(up, UART_IER, 0); -#ifdef __i386__ - outb(0xff, 0x080); -#endif - /* - * Mask out IER[7:4] bits for test as some UARTs (e.g. TL - * 16C754B) allow only to modify them if an EFR bit is set. - */ - scratch2 = serial_in(up, UART_IER) & 0x0f; - serial_out(up, UART_IER, 0x0F); -#ifdef __i386__ - outb(0, 0x080); -#endif - scratch3 = serial_in(up, UART_IER) & 0x0f; - serial_out(up, UART_IER, scratch); - if (scratch2 != 0 || scratch3 != 0x0F) { - /* - * We failed; there's nothing here - */ - spin_unlock_irqrestore(&port->lock, flags); - DEBUG_AUTOCONF("IER test failed (%02x, %02x) ", - scratch2, scratch3); - goto out; - } - } - - save_mcr = serial_in(up, UART_MCR); - save_lcr = serial_in(up, UART_LCR); - - /* - * Check to see if a UART is really there. Certain broken - * internal modems based on the Rockwell chipset fail this - * test, because they apparently don't implement the loopback - * test mode. So this test is skipped on the COM 1 through - * COM 4 ports. This *should* be safe, since no board - * manufacturer would be stupid enough to design a board - * that conflicts with COM 1-4 --- we hope! - */ - if (!(port->flags & UPF_SKIP_TEST)) { - serial_out(up, UART_MCR, UART_MCR_LOOP | 0x0A); - status1 = serial_in(up, UART_MSR) & 0xF0; - serial_out(up, UART_MCR, save_mcr); - if (status1 != 0x90) { - spin_unlock_irqrestore(&port->lock, flags); - DEBUG_AUTOCONF("LOOP test failed (%02x) ", - status1); - goto out; - } - } - - /* - * We're pretty sure there's a port here. Lets find out what - * type of port it is. The IIR top two bits allows us to find - * out if it's 8250 or 16450, 16550, 16550A or later. This - * determines what we test for next. - * - * We also initialise the EFR (if any) to zero for later. The - * EFR occupies the same register location as the FCR and IIR. - */ - serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); - serial_out(up, UART_EFR, 0); - serial_out(up, UART_LCR, 0); - - serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO); - scratch = serial_in(up, UART_IIR) >> 6; - - switch (scratch) { - case 0: - autoconfig_8250(up); - break; - case 1: - port->type = PORT_UNKNOWN; - break; - case 2: - port->type = PORT_16550; - break; - case 3: - autoconfig_16550a(up); - break; - } - -#ifdef CONFIG_SERIAL_8250_RSA - /* - * Only probe for RSA ports if we got the region. - */ - if (port->type == PORT_16550A && up->probe & UART_PROBE_RSA && - __enable_rsa(up)) - port->type = PORT_RSA; -#endif - - serial_out(up, UART_LCR, save_lcr); - - port->fifosize = uart_config[up->port.type].fifo_size; - old_capabilities = up->capabilities; - up->capabilities = uart_config[port->type].flags; - up->tx_loadsz = uart_config[port->type].tx_loadsz; - - if (port->type == PORT_UNKNOWN) - goto out_lock; - - /* - * Reset the UART. - */ -#ifdef CONFIG_SERIAL_8250_RSA - if (port->type == PORT_RSA) - serial_out(up, UART_RSA_FRR, 0); -#endif - serial_out(up, UART_MCR, save_mcr); - serial8250_clear_fifos(up); - serial_in(up, UART_RX); - if (up->capabilities & UART_CAP_UUE) - serial_out(up, UART_IER, UART_IER_UUE); - else - serial_out(up, UART_IER, 0); - -out_lock: - spin_unlock_irqrestore(&port->lock, flags); - if (up->capabilities != old_capabilities) { - printk(KERN_WARNING - "ttyS%d: detected caps %08x should be %08x\n", - serial_index(port), old_capabilities, - up->capabilities); - } -out: - DEBUG_AUTOCONF("iir=%d ", scratch); - DEBUG_AUTOCONF("type=%s\n", uart_config[port->type].name); -} - -static void autoconfig_irq(struct uart_8250_port *up) -{ - struct uart_port *port = &up->port; - unsigned char save_mcr, save_ier; - unsigned char save_ICP = 0; - unsigned int ICP = 0; - unsigned long irqs; - int irq; - - if (port->flags & UPF_FOURPORT) { - ICP = (port->iobase & 0xfe0) | 0x1f; - save_ICP = inb_p(ICP); - outb_p(0x80, ICP); - inb_p(ICP); - } - - /* forget possible initially masked and pending IRQ */ - probe_irq_off(probe_irq_on()); - save_mcr = serial_in(up, UART_MCR); - save_ier = serial_in(up, UART_IER); - serial_out(up, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2); - - irqs = probe_irq_on(); - serial_out(up, UART_MCR, 0); - udelay(10); - if (port->flags & UPF_FOURPORT) { - serial_out(up, UART_MCR, - UART_MCR_DTR | UART_MCR_RTS); - } else { - serial_out(up, UART_MCR, - UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2); - } - serial_out(up, UART_IER, 0x0f); /* enable all intrs */ - serial_in(up, UART_LSR); - serial_in(up, UART_RX); - serial_in(up, UART_IIR); - serial_in(up, UART_MSR); - serial_out(up, UART_TX, 0xFF); - udelay(20); - irq = probe_irq_off(irqs); - - serial_out(up, UART_MCR, save_mcr); - serial_out(up, UART_IER, save_ier); - - if (port->flags & UPF_FOURPORT) - outb_p(save_ICP, ICP); - - port->irq = (irq > 0) ? irq : 0; -} - -static inline void __stop_tx(struct uart_8250_port *p) -{ - if (p->ier & UART_IER_THRI) { - p->ier &= ~UART_IER_THRI; - serial_out(p, UART_IER, p->ier); - serial8250_rpm_put_tx(p); - } -} - -static void serial8250_stop_tx(struct uart_port *port) -{ - struct uart_8250_port *up = up_to_u8250p(port); - - serial8250_rpm_get(up); - __stop_tx(up); - - /* - * We really want to stop the transmitter from sending. - */ - if (port->type == PORT_16C950) { - up->acr |= UART_ACR_TXDIS; - serial_icr_write(up, UART_ACR, up->acr); - } - serial8250_rpm_put(up); -} - -static void serial8250_start_tx(struct uart_port *port) -{ - struct uart_8250_port *up = up_to_u8250p(port); - - serial8250_rpm_get_tx(up); - - if (up->dma && !up->dma->tx_dma(up)) - return; - - if (!(up->ier & UART_IER_THRI)) { - up->ier |= UART_IER_THRI; - serial_port_out(port, UART_IER, up->ier); - - if (up->bugs & UART_BUG_TXEN) { - unsigned char lsr; - lsr = serial_in(up, UART_LSR); - up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; - if (lsr & UART_LSR_THRE) - serial8250_tx_chars(up); - } - } - - /* - * Re-enable the transmitter if we disabled it. - */ - if (port->type == PORT_16C950 && up->acr & UART_ACR_TXDIS) { - up->acr &= ~UART_ACR_TXDIS; - serial_icr_write(up, UART_ACR, up->acr); - } -} - -static void serial8250_throttle(struct uart_port *port) -{ - port->throttle(port); -} - -static void serial8250_unthrottle(struct uart_port *port) -{ - port->unthrottle(port); -} - -static void serial8250_stop_rx(struct uart_port *port) -{ - struct uart_8250_port *up = up_to_u8250p(port); - - serial8250_rpm_get(up); - - up->ier &= ~(UART_IER_RLSI | UART_IER_RDI); - up->port.read_status_mask &= ~UART_LSR_DR; - serial_port_out(port, UART_IER, up->ier); - - serial8250_rpm_put(up); -} - -static void serial8250_disable_ms(struct uart_port *port) -{ - struct uart_8250_port *up = - container_of(port, struct uart_8250_port, port); - - /* no MSR capabilities */ - if (up->bugs & UART_BUG_NOMSR) - return; - - up->ier &= ~UART_IER_MSI; - serial_port_out(port, UART_IER, up->ier); -} - -static void serial8250_enable_ms(struct uart_port *port) -{ - struct uart_8250_port *up = up_to_u8250p(port); - - /* no MSR capabilities */ - if (up->bugs & UART_BUG_NOMSR) - return; - - up->ier |= UART_IER_MSI; - - serial8250_rpm_get(up); - serial_port_out(port, UART_IER, up->ier); - serial8250_rpm_put(up); -} - -/* - * serial8250_rx_chars: processes according to the passed in LSR - * value, and returns the remaining LSR bits not handled - * by this Rx routine. - */ -unsigned char -serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr) -{ - struct uart_port *port = &up->port; - unsigned char ch; - int max_count = 256; - char flag; - - do { - if (likely(lsr & UART_LSR_DR)) - ch = serial_in(up, UART_RX); - else - /* - * Intel 82571 has a Serial Over Lan device that will - * set UART_LSR_BI without setting UART_LSR_DR when - * it receives a break. To avoid reading from the - * receive buffer without UART_LSR_DR bit set, we - * just force the read character to be 0 - */ - ch = 0; - - flag = TTY_NORMAL; - port->icount.rx++; - - lsr |= up->lsr_saved_flags; - up->lsr_saved_flags = 0; - - if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) { - if (lsr & UART_LSR_BI) { - lsr &= ~(UART_LSR_FE | UART_LSR_PE); - port->icount.brk++; - /* - * We do the SysRQ and SAK checking - * here because otherwise the break - * may get masked by ignore_status_mask - * or read_status_mask. - */ - if (uart_handle_break(port)) - goto ignore_char; - } else if (lsr & UART_LSR_PE) - port->icount.parity++; - else if (lsr & UART_LSR_FE) - port->icount.frame++; - if (lsr & UART_LSR_OE) - port->icount.overrun++; - - /* - * Mask off conditions which should be ignored. - */ - lsr &= port->read_status_mask; - - if (lsr & UART_LSR_BI) { - DEBUG_INTR("handling break...."); - flag = TTY_BREAK; - } else if (lsr & UART_LSR_PE) - flag = TTY_PARITY; - else if (lsr & UART_LSR_FE) - flag = TTY_FRAME; - } - if (uart_handle_sysrq_char(port, ch)) - goto ignore_char; - - uart_insert_char(port, lsr, UART_LSR_OE, ch, flag); - -ignore_char: - lsr = serial_in(up, UART_LSR); - } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (--max_count > 0)); - spin_unlock(&port->lock); - tty_flip_buffer_push(&port->state->port); - spin_lock(&port->lock); - return lsr; -} -EXPORT_SYMBOL_GPL(serial8250_rx_chars); - -void serial8250_tx_chars(struct uart_8250_port *up) -{ - struct uart_port *port = &up->port; - struct circ_buf *xmit = &port->state->xmit; - int count; - - if (port->x_char) { - serial_out(up, UART_TX, port->x_char); - port->icount.tx++; - port->x_char = 0; - return; - } - if (uart_tx_stopped(port)) { - serial8250_stop_tx(port); - return; - } - if (uart_circ_empty(xmit)) { - __stop_tx(up); - return; - } - - count = up->tx_loadsz; - do { - serial_out(up, UART_TX, xmit->buf[xmit->tail]); - xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); - port->icount.tx++; - if (uart_circ_empty(xmit)) - break; - if (up->capabilities & UART_CAP_HFIFO) { - if ((serial_port_in(port, UART_LSR) & BOTH_EMPTY) != - BOTH_EMPTY) - break; - } - } while (--count > 0); - - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(port); - - DEBUG_INTR("THRE..."); - - /* - * With RPM enabled, we have to wait until the FIFO is empty before the - * HW can go idle. So we get here once again with empty FIFO and disable - * the interrupt and RPM in __stop_tx() - */ - if (uart_circ_empty(xmit) && !(up->capabilities & UART_CAP_RPM)) - __stop_tx(up); -} -EXPORT_SYMBOL_GPL(serial8250_tx_chars); - -/* Caller holds uart port lock */ -unsigned int serial8250_modem_status(struct uart_8250_port *up) -{ - struct uart_port *port = &up->port; - unsigned int status = serial_in(up, UART_MSR); - - status |= up->msr_saved_flags; - up->msr_saved_flags = 0; - if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI && - port->state != NULL) { - if (status & UART_MSR_TERI) - port->icount.rng++; - if (status & UART_MSR_DDSR) - port->icount.dsr++; - if (status & UART_MSR_DDCD) - uart_handle_dcd_change(port, status & UART_MSR_DCD); - if (status & UART_MSR_DCTS) - uart_handle_cts_change(port, status & UART_MSR_CTS); - - wake_up_interruptible(&port->state->port.delta_msr_wait); - } - - return status; -} -EXPORT_SYMBOL_GPL(serial8250_modem_status); - -/* - * This handles the interrupt from one port. - */ -int serial8250_handle_irq(struct uart_port *port, unsigned int iir) -{ - unsigned char status; - unsigned long flags; - struct uart_8250_port *up = up_to_u8250p(port); - int dma_err = 0; - - if (iir & UART_IIR_NO_INT) - return 0; - - spin_lock_irqsave(&port->lock, flags); - - status = serial_port_in(port, UART_LSR); - - DEBUG_INTR("status = %x...", status); - - if (status & (UART_LSR_DR | UART_LSR_BI)) { - if (up->dma) - dma_err = up->dma->rx_dma(up, iir); - - if (!up->dma || dma_err) - status = serial8250_rx_chars(up, status); - } - serial8250_modem_status(up); - if ((!up->dma || (up->dma && up->dma->tx_err)) && - (status & UART_LSR_THRE)) - serial8250_tx_chars(up); - - spin_unlock_irqrestore(&port->lock, flags); - return 1; -} -EXPORT_SYMBOL_GPL(serial8250_handle_irq); - -static int serial8250_default_handle_irq(struct uart_port *port) -{ - struct uart_8250_port *up = up_to_u8250p(port); - unsigned int iir; - int ret; - - serial8250_rpm_get(up); - - iir = serial_port_in(port, UART_IIR); - ret = serial8250_handle_irq(port, iir); - - serial8250_rpm_put(up); - return ret; -} - -/* - * These Exar UARTs have an extra interrupt indicator that could - * fire for a few unimplemented interrupts. One of which is a - * wakeup event when coming out of sleep. Put this here just - * to be on the safe side that these interrupts don't go unhandled. - */ -static int exar_handle_irq(struct uart_port *port) -{ - unsigned char int0, int1, int2, int3; - unsigned int iir = serial_port_in(port, UART_IIR); - int ret; - - ret = serial8250_handle_irq(port, iir); - - if ((port->type == PORT_XR17V35X) || - (port->type == PORT_XR17D15X)) { - int0 = serial_port_in(port, 0x80); - int1 = serial_port_in(port, 0x81); - int2 = serial_port_in(port, 0x82); - int3 = serial_port_in(port, 0x83); - } - - return ret; -} - -/* * This is the serial driver's interrupt routine. * * Arjan thinks the old way was overly complex, so it got simplified. @@ -1709,7 +114,7 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id) struct list_head *l, *end = NULL; int pass_counter = 0, handled = 0; - DEBUG_INTR("serial8250_interrupt(%d)...", irq); + pr_debug("%s(%d): start\n", __func__, irq); spin_lock(&i->lock); @@ -1739,7 +144,7 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id) spin_unlock(&i->lock); - DEBUG_INTR("end.\n"); + pr_debug("%s(%d): end\n", __func__, irq); return IRQ_RETVAL(handled); } @@ -1954,875 +359,6 @@ static void univ8250_release_irq(struct uart_8250_port *up) serial_unlink_irq_chain(up); } -static unsigned int serial8250_tx_empty(struct uart_port *port) -{ - struct uart_8250_port *up = up_to_u8250p(port); - unsigned long flags; - unsigned int lsr; - - serial8250_rpm_get(up); - - spin_lock_irqsave(&port->lock, flags); - lsr = serial_port_in(port, UART_LSR); - up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; - spin_unlock_irqrestore(&port->lock, flags); - - serial8250_rpm_put(up); - - return (lsr & BOTH_EMPTY) == BOTH_EMPTY ? TIOCSER_TEMT : 0; -} - -static unsigned int serial8250_get_mctrl(struct uart_port *port) -{ - struct uart_8250_port *up = up_to_u8250p(port); - unsigned int status; - unsigned int ret; - - serial8250_rpm_get(up); - status = serial8250_modem_status(up); - serial8250_rpm_put(up); - - ret = 0; - if (status & UART_MSR_DCD) - ret |= TIOCM_CAR; - if (status & UART_MSR_RI) - ret |= TIOCM_RNG; - if (status & UART_MSR_DSR) - ret |= TIOCM_DSR; - if (status & UART_MSR_CTS) - ret |= TIOCM_CTS; - return ret; -} - -void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl) -{ - struct uart_8250_port *up = up_to_u8250p(port); - unsigned char mcr = 0; - - if (mctrl & TIOCM_RTS) - mcr |= UART_MCR_RTS; - if (mctrl & TIOCM_DTR) - mcr |= UART_MCR_DTR; - if (mctrl & TIOCM_OUT1) - mcr |= UART_MCR_OUT1; - if (mctrl & TIOCM_OUT2) - mcr |= UART_MCR_OUT2; - if (mctrl & TIOCM_LOOP) - mcr |= UART_MCR_LOOP; - - mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr; - - serial_port_out(port, UART_MCR, mcr); -} -EXPORT_SYMBOL_GPL(serial8250_do_set_mctrl); - -static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl) -{ - if (port->set_mctrl) - return port->set_mctrl(port, mctrl); - return serial8250_do_set_mctrl(port, mctrl); -} - -static void serial8250_break_ctl(struct uart_port *port, int break_state) -{ - struct uart_8250_port *up = up_to_u8250p(port); - unsigned long flags; - - serial8250_rpm_get(up); - spin_lock_irqsave(&port->lock, flags); - if (break_state == -1) - up->lcr |= UART_LCR_SBC; - else - up->lcr &= ~UART_LCR_SBC; - serial_port_out(port, UART_LCR, up->lcr); - spin_unlock_irqrestore(&port->lock, flags); - serial8250_rpm_put(up); -} - -/* - * Wait for transmitter & holding register to empty - */ -static void wait_for_xmitr(struct uart_8250_port *up, int bits) -{ - unsigned int status, tmout = 10000; - - /* Wait up to 10ms for the character(s) to be sent. */ - for (;;) { - status = serial_in(up, UART_LSR); - - up->lsr_saved_flags |= status & LSR_SAVE_FLAGS; - - if ((status & bits) == bits) - break; - if (--tmout == 0) - break; - udelay(1); - } - - /* Wait up to 1s for flow control if necessary */ - if (up->port.flags & UPF_CONS_FLOW) { - unsigned int tmout; - for (tmout = 1000000; tmout; tmout--) { - unsigned int msr = serial_in(up, UART_MSR); - up->msr_saved_flags |= msr & MSR_SAVE_FLAGS; - if (msr & UART_MSR_CTS) - break; - udelay(1); - touch_nmi_watchdog(); - } - } -} - -#ifdef CONFIG_CONSOLE_POLL -/* - * Console polling routines for writing and reading from the uart while - * in an interrupt or debug context. - */ - -static int serial8250_get_poll_char(struct uart_port *port) -{ - struct uart_8250_port *up = up_to_u8250p(port); - unsigned char lsr; - int status; - - serial8250_rpm_get(up); - - lsr = serial_port_in(port, UART_LSR); - - if (!(lsr & UART_LSR_DR)) { - status = NO_POLL_CHAR; - goto out; - } - - status = serial_port_in(port, UART_RX); -out: - serial8250_rpm_put(up); - return status; -} - - -static void serial8250_put_poll_char(struct uart_port *port, - unsigned char c) -{ - unsigned int ier; - struct uart_8250_port *up = up_to_u8250p(port); - - serial8250_rpm_get(up); - /* - * First save the IER then disable the interrupts - */ - ier = serial_port_in(port, UART_IER); - if (up->capabilities & UART_CAP_UUE) - serial_port_out(port, UART_IER, UART_IER_UUE); - else - serial_port_out(port, UART_IER, 0); - - wait_for_xmitr(up, BOTH_EMPTY); - /* - * Send the character out. - */ - serial_port_out(port, UART_TX, c); - - /* - * Finally, wait for transmitter to become empty - * and restore the IER - */ - wait_for_xmitr(up, BOTH_EMPTY); - serial_port_out(port, UART_IER, ier); - serial8250_rpm_put(up); -} - -#endif /* CONFIG_CONSOLE_POLL */ - -int serial8250_do_startup(struct uart_port *port) -{ - struct uart_8250_port *up = up_to_u8250p(port); - unsigned long flags; - unsigned char lsr, iir; - int retval; - - if (port->type == PORT_8250_CIR) - return -ENODEV; - - if (!port->fifosize) - port->fifosize = uart_config[port->type].fifo_size; - if (!up->tx_loadsz) - up->tx_loadsz = uart_config[port->type].tx_loadsz; - if (!up->capabilities) - up->capabilities = uart_config[port->type].flags; - up->mcr = 0; - - if (port->iotype != up->cur_iotype) - set_io_from_upio(port); - - serial8250_rpm_get(up); - if (port->type == PORT_16C950) { - /* Wake up and initialize UART */ - up->acr = 0; - serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B); - serial_port_out(port, UART_EFR, UART_EFR_ECB); - serial_port_out(port, UART_IER, 0); - serial_port_out(port, UART_LCR, 0); - serial_icr_write(up, UART_CSR, 0); /* Reset the UART */ - serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B); - serial_port_out(port, UART_EFR, UART_EFR_ECB); - serial_port_out(port, UART_LCR, 0); - } - -#ifdef CONFIG_SERIAL_8250_RSA - /* - * If this is an RSA port, see if we can kick it up to the - * higher speed clock. - */ - enable_rsa(up); -#endif - /* - * Clear the FIFO buffers and disable them. - * (they will be reenabled in set_termios()) - */ - serial8250_clear_fifos(up); - - /* - * Clear the interrupt registers. - */ - serial_port_in(port, UART_LSR); - serial_port_in(port, UART_RX); - serial_port_in(port, UART_IIR); - serial_port_in(port, UART_MSR); - - /* - * At this point, there's no way the LSR could still be 0xff; - * if it is, then bail out, because there's likely no UART - * here. - */ - if (!(port->flags & UPF_BUGGY_UART) && - (serial_port_in(port, UART_LSR) == 0xff)) { - printk_ratelimited(KERN_INFO "ttyS%d: LSR safety check engaged!\n", - serial_index(port)); - retval = -ENODEV; - goto out; - } - - /* - * For a XR16C850, we need to set the trigger levels - */ - if (port->type == PORT_16850) { - unsigned char fctr; - - serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); - - fctr = serial_in(up, UART_FCTR) & ~(UART_FCTR_RX|UART_FCTR_TX); - serial_port_out(port, UART_FCTR, - fctr | UART_FCTR_TRGD | UART_FCTR_RX); - serial_port_out(port, UART_TRG, UART_TRG_96); - serial_port_out(port, UART_FCTR, - fctr | UART_FCTR_TRGD | UART_FCTR_TX); - serial_port_out(port, UART_TRG, UART_TRG_96); - - serial_port_out(port, UART_LCR, 0); - } - - if (port->irq) { - unsigned char iir1; - /* - * Test for UARTs that do not reassert THRE when the - * transmitter is idle and the interrupt has already - * been cleared. Real 16550s should always reassert - * this interrupt whenever the transmitter is idle and - * the interrupt is enabled. Delays are necessary to - * allow register changes to become visible. - */ - spin_lock_irqsave(&port->lock, flags); - if (up->port.irqflags & IRQF_SHARED) - disable_irq_nosync(port->irq); - - wait_for_xmitr(up, UART_LSR_THRE); - serial_port_out_sync(port, UART_IER, UART_IER_THRI); - udelay(1); /* allow THRE to set */ - iir1 = serial_port_in(port, UART_IIR); - serial_port_out(port, UART_IER, 0); - serial_port_out_sync(port, UART_IER, UART_IER_THRI); - udelay(1); /* allow a working UART time to re-assert THRE */ - iir = serial_port_in(port, UART_IIR); - serial_port_out(port, UART_IER, 0); - - if (port->irqflags & IRQF_SHARED) - enable_irq(port->irq); - spin_unlock_irqrestore(&port->lock, flags); - - /* - * If the interrupt is not reasserted, or we otherwise - * don't trust the iir, setup a timer to kick the UART - * on a regular basis. - */ - if ((!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) || - up->port.flags & UPF_BUG_THRE) { - up->bugs |= UART_BUG_THRE; - } - } - - retval = up->ops->setup_irq(up); - if (retval) - goto out; - - /* - * Now, initialize the UART - */ - serial_port_out(port, UART_LCR, UART_LCR_WLEN8); - - spin_lock_irqsave(&port->lock, flags); - if (up->port.flags & UPF_FOURPORT) { - if (!up->port.irq) - up->port.mctrl |= TIOCM_OUT1; - } else - /* - * Most PC uarts need OUT2 raised to enable interrupts. - */ - if (port->irq) - up->port.mctrl |= TIOCM_OUT2; - - serial8250_set_mctrl(port, port->mctrl); - - /* Serial over Lan (SoL) hack: - Intel 8257x Gigabit ethernet chips have a - 16550 emulation, to be used for Serial Over Lan. - Those chips take a longer time than a normal - serial device to signalize that a transmission - data was queued. Due to that, the above test generally - fails. One solution would be to delay the reading of - iir. However, this is not reliable, since the timeout - is variable. So, let's just don't test if we receive - TX irq. This way, we'll never enable UART_BUG_TXEN. - */ - if (up->port.flags & UPF_NO_TXEN_TEST) - goto dont_test_tx_en; - - /* - * Do a quick test to see if we receive an - * interrupt when we enable the TX irq. - */ - serial_port_out(port, UART_IER, UART_IER_THRI); - lsr = serial_port_in(port, UART_LSR); - iir = serial_port_in(port, UART_IIR); - serial_port_out(port, UART_IER, 0); - - if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) { - if (!(up->bugs & UART_BUG_TXEN)) { - up->bugs |= UART_BUG_TXEN; - pr_debug("ttyS%d - enabling bad tx status workarounds\n", - serial_index(port)); - } - } else { - up->bugs &= ~UART_BUG_TXEN; - } - -dont_test_tx_en: - spin_unlock_irqrestore(&port->lock, flags); - - /* - * Clear the interrupt registers again for luck, and clear the - * saved flags to avoid getting false values from polling - * routines or the previous session. - */ - serial_port_in(port, UART_LSR); - serial_port_in(port, UART_RX); - serial_port_in(port, UART_IIR); - serial_port_in(port, UART_MSR); - up->lsr_saved_flags = 0; - up->msr_saved_flags = 0; - - /* - * Request DMA channels for both RX and TX. - */ - if (up->dma) { - retval = serial8250_request_dma(up); - if (retval) { - pr_warn_ratelimited("ttyS%d - failed to request DMA\n", - serial_index(port)); - up->dma = NULL; - } - } - - /* - * Finally, enable interrupts. Note: Modem status interrupts - * are set via set_termios(), which will be occurring imminently - * anyway, so we don't enable them here. - */ - up->ier = UART_IER_RLSI | UART_IER_RDI; - serial_port_out(port, UART_IER, up->ier); - - if (port->flags & UPF_FOURPORT) { - unsigned int icp; - /* - * Enable interrupts on the AST Fourport board - */ - icp = (port->iobase & 0xfe0) | 0x01f; - outb_p(0x80, icp); - inb_p(icp); - } - retval = 0; -out: - serial8250_rpm_put(up); - return retval; -} -EXPORT_SYMBOL_GPL(serial8250_do_startup); - -static int serial8250_startup(struct uart_port *port) -{ - if (port->startup) - return port->startup(port); - return serial8250_do_startup(port); -} - -void serial8250_do_shutdown(struct uart_port *port) -{ - struct uart_8250_port *up = up_to_u8250p(port); - unsigned long flags; - - serial8250_rpm_get(up); - /* - * Disable interrupts from this port - */ - up->ier = 0; - serial_port_out(port, UART_IER, 0); - - if (up->dma) - serial8250_release_dma(up); - - spin_lock_irqsave(&port->lock, flags); - if (port->flags & UPF_FOURPORT) { - /* reset interrupts on the AST Fourport board */ - inb((port->iobase & 0xfe0) | 0x1f); - port->mctrl |= TIOCM_OUT1; - } else - port->mctrl &= ~TIOCM_OUT2; - - serial8250_set_mctrl(port, port->mctrl); - spin_unlock_irqrestore(&port->lock, flags); - - /* - * Disable break condition and FIFOs - */ - serial_port_out(port, UART_LCR, - serial_port_in(port, UART_LCR) & ~UART_LCR_SBC); - serial8250_clear_fifos(up); - -#ifdef CONFIG_SERIAL_8250_RSA - /* - * Reset the RSA board back to 115kbps compat mode. - */ - disable_rsa(up); -#endif - - /* - * Read data port to reset things, and then unlink from - * the IRQ chain. - */ - serial_port_in(port, UART_RX); - serial8250_rpm_put(up); - - up->ops->release_irq(up); -} -EXPORT_SYMBOL_GPL(serial8250_do_shutdown); - -static void serial8250_shutdown(struct uart_port *port) -{ - if (port->shutdown) - port->shutdown(port); - else - serial8250_do_shutdown(port); -} - -/* - * XR17V35x UARTs have an extra fractional divisor register (DLD) - * Calculate divisor with extra 4-bit fractional portion - */ -static unsigned int xr17v35x_get_divisor(struct uart_8250_port *up, - unsigned int baud, - unsigned int *frac) -{ - struct uart_port *port = &up->port; - unsigned int quot_16; - - quot_16 = DIV_ROUND_CLOSEST(port->uartclk, baud); - *frac = quot_16 & 0x0f; - - return quot_16 >> 4; -} - -static unsigned int serial8250_get_divisor(struct uart_8250_port *up, - unsigned int baud, - unsigned int *frac) -{ - struct uart_port *port = &up->port; - unsigned int quot; - - /* - * Handle magic divisors for baud rates above baud_base on - * SMSC SuperIO chips. - * - */ - if ((port->flags & UPF_MAGIC_MULTIPLIER) && - baud == (port->uartclk/4)) - quot = 0x8001; - else if ((port->flags & UPF_MAGIC_MULTIPLIER) && - baud == (port->uartclk/8)) - quot = 0x8002; - else if (up->port.type == PORT_XR17V35X) - quot = xr17v35x_get_divisor(up, baud, frac); - else - quot = uart_get_divisor(port, baud); - - /* - * Oxford Semi 952 rev B workaround - */ - if (up->bugs & UART_BUG_QUOT && (quot & 0xff) == 0) - quot++; - - return quot; -} - -static unsigned char serial8250_compute_lcr(struct uart_8250_port *up, - tcflag_t c_cflag) -{ - unsigned char cval; - - switch (c_cflag & CSIZE) { - case CS5: - cval = UART_LCR_WLEN5; - break; - case CS6: - cval = UART_LCR_WLEN6; - break; - case CS7: - cval = UART_LCR_WLEN7; - break; - default: - case CS8: - cval = UART_LCR_WLEN8; - break; - } - - if (c_cflag & CSTOPB) - cval |= UART_LCR_STOP; - if (c_cflag & PARENB) { - cval |= UART_LCR_PARITY; - if (up->bugs & UART_BUG_PARITY) - up->fifo_bug = true; - } - if (!(c_cflag & PARODD)) - cval |= UART_LCR_EPAR; -#ifdef CMSPAR - if (c_cflag & CMSPAR) - cval |= UART_LCR_SPAR; -#endif - - return cval; -} - -static void serial8250_set_divisor(struct uart_port *port, unsigned int baud, - unsigned int quot, unsigned int quot_frac) -{ - struct uart_8250_port *up = up_to_u8250p(port); - - /* Workaround to enable 115200 baud on OMAP1510 internal ports */ - if (is_omap1510_8250(up)) { - if (baud == 115200) { - quot = 1; - serial_port_out(port, UART_OMAP_OSC_12M_SEL, 1); - } else - serial_port_out(port, UART_OMAP_OSC_12M_SEL, 0); - } - - /* - * For NatSemi, switch to bank 2 not bank 1, to avoid resetting EXCR2, - * otherwise just set DLAB - */ - if (up->capabilities & UART_NATSEMI) - serial_port_out(port, UART_LCR, 0xe0); - else - serial_port_out(port, UART_LCR, up->lcr | UART_LCR_DLAB); - - serial_dl_write(up, quot); - - /* XR17V35x UARTs have an extra fractional divisor register (DLD) */ - if (up->port.type == PORT_XR17V35X) - serial_port_out(port, 0x2, quot_frac); -} - -void -serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, - struct ktermios *old) -{ - struct uart_8250_port *up = up_to_u8250p(port); - unsigned char cval; - unsigned long flags; - unsigned int baud, quot, frac = 0; - - cval = serial8250_compute_lcr(up, termios->c_cflag); - - /* - * Ask the core to calculate the divisor for us. - */ - baud = uart_get_baud_rate(port, termios, old, - port->uartclk / 16 / 0xffff, - port->uartclk / 16); - quot = serial8250_get_divisor(up, baud, &frac); - - /* - * Ok, we're now changing the port state. Do it with - * interrupts disabled. - */ - serial8250_rpm_get(up); - spin_lock_irqsave(&port->lock, flags); - - up->lcr = cval; /* Save computed LCR */ - - if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) { - /* NOTE: If fifo_bug is not set, a user can set RX_trigger. */ - if ((baud < 2400 && !up->dma) || up->fifo_bug) { - up->fcr &= ~UART_FCR_TRIGGER_MASK; - up->fcr |= UART_FCR_TRIGGER_1; - } - } - - /* - * MCR-based auto flow control. When AFE is enabled, RTS will be - * deasserted when the receive FIFO contains more characters than - * the trigger, or the MCR RTS bit is cleared. In the case where - * the remote UART is not using CTS auto flow control, we must - * have sufficient FIFO entries for the latency of the remote - * UART to respond. IOW, at least 32 bytes of FIFO. - */ - if (up->capabilities & UART_CAP_AFE && port->fifosize >= 32) { - up->mcr &= ~UART_MCR_AFE; - if (termios->c_cflag & CRTSCTS) - up->mcr |= UART_MCR_AFE; - } - - /* - * Update the per-port timeout. - */ - uart_update_timeout(port, termios->c_cflag, baud); - - port->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; - if (termios->c_iflag & INPCK) - port->read_status_mask |= UART_LSR_FE | UART_LSR_PE; - if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK)) - port->read_status_mask |= UART_LSR_BI; - - /* - * Characteres to ignore - */ - port->ignore_status_mask = 0; - if (termios->c_iflag & IGNPAR) - port->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; - if (termios->c_iflag & IGNBRK) { - port->ignore_status_mask |= UART_LSR_BI; - /* - * If we're ignoring parity and break indicators, - * ignore overruns too (for real raw support). - */ - if (termios->c_iflag & IGNPAR) - port->ignore_status_mask |= UART_LSR_OE; - } - - /* - * ignore all characters if CREAD is not set - */ - if ((termios->c_cflag & CREAD) == 0) - port->ignore_status_mask |= UART_LSR_DR; - - /* - * CTS flow control flag and modem status interrupts - */ - up->ier &= ~UART_IER_MSI; - if (!(up->bugs & UART_BUG_NOMSR) && - UART_ENABLE_MS(&up->port, termios->c_cflag)) - up->ier |= UART_IER_MSI; - if (up->capabilities & UART_CAP_UUE) - up->ier |= UART_IER_UUE; - if (up->capabilities & UART_CAP_RTOIE) - up->ier |= UART_IER_RTOIE; - - serial_port_out(port, UART_IER, up->ier); - - if (up->capabilities & UART_CAP_EFR) { - unsigned char efr = 0; - /* - * TI16C752/Startech hardware flow control. FIXME: - * - TI16C752 requires control thresholds to be set. - * - UART_MCR_RTS is ineffective if auto-RTS mode is enabled. - */ - if (termios->c_cflag & CRTSCTS) - efr |= UART_EFR_CTS; - - serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B); - if (port->flags & UPF_EXAR_EFR) - serial_port_out(port, UART_XR_EFR, efr); - else - serial_port_out(port, UART_EFR, efr); - } - - serial8250_set_divisor(port, baud, quot, frac); - - /* - * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR - * is written without DLAB set, this mode will be disabled. - */ - if (port->type == PORT_16750) - serial_port_out(port, UART_FCR, up->fcr); - - serial_port_out(port, UART_LCR, up->lcr); /* reset DLAB */ - if (port->type != PORT_16750) { - /* emulated UARTs (Lucent Venus 167x) need two steps */ - if (up->fcr & UART_FCR_ENABLE_FIFO) - serial_port_out(port, UART_FCR, UART_FCR_ENABLE_FIFO); - serial_port_out(port, UART_FCR, up->fcr); /* set fcr */ - } - serial8250_set_mctrl(port, port->mctrl); - spin_unlock_irqrestore(&port->lock, flags); - serial8250_rpm_put(up); - - /* Don't rewrite B0 */ - if (tty_termios_baud_rate(termios)) - tty_termios_encode_baud_rate(termios, baud, baud); -} -EXPORT_SYMBOL(serial8250_do_set_termios); - -static void -serial8250_set_termios(struct uart_port *port, struct ktermios *termios, - struct ktermios *old) -{ - if (port->set_termios) - port->set_termios(port, termios, old); - else - serial8250_do_set_termios(port, termios, old); -} - -static void -serial8250_set_ldisc(struct uart_port *port, struct ktermios *termios) -{ - if (termios->c_line == N_PPS) { - port->flags |= UPF_HARDPPS_CD; - spin_lock_irq(&port->lock); - serial8250_enable_ms(port); - spin_unlock_irq(&port->lock); - } else { - port->flags &= ~UPF_HARDPPS_CD; - if (!UART_ENABLE_MS(port, termios->c_cflag)) { - spin_lock_irq(&port->lock); - serial8250_disable_ms(port); - spin_unlock_irq(&port->lock); - } - } -} - - -void serial8250_do_pm(struct uart_port *port, unsigned int state, - unsigned int oldstate) -{ - struct uart_8250_port *p = up_to_u8250p(port); - - serial8250_set_sleep(p, state != 0); -} -EXPORT_SYMBOL(serial8250_do_pm); - -static void -serial8250_pm(struct uart_port *port, unsigned int state, - unsigned int oldstate) -{ - if (port->pm) - port->pm(port, state, oldstate); - else - serial8250_do_pm(port, state, oldstate); -} - -static unsigned int serial8250_port_size(struct uart_8250_port *pt) -{ - if (pt->port.mapsize) - return pt->port.mapsize; - if (pt->port.iotype == UPIO_AU) { - if (pt->port.type == PORT_RT2880) - return 0x100; - return 0x1000; - } - if (is_omap1_8250(pt)) - return 0x16 << pt->port.regshift; - - return 8 << pt->port.regshift; -} - -/* - * Resource handling. - */ -static int serial8250_request_std_resource(struct uart_8250_port *up) -{ - unsigned int size = serial8250_port_size(up); - struct uart_port *port = &up->port; - int ret = 0; - - switch (port->iotype) { - case UPIO_AU: - case UPIO_TSI: - case UPIO_MEM32: - case UPIO_MEM32BE: - case UPIO_MEM: - if (!port->mapbase) - break; - - if (!request_mem_region(port->mapbase, size, "serial")) { - ret = -EBUSY; - break; - } - - if (port->flags & UPF_IOREMAP) { - port->membase = ioremap_nocache(port->mapbase, size); - if (!port->membase) { - release_mem_region(port->mapbase, size); - ret = -ENOMEM; - } - } - break; - - case UPIO_HUB6: - case UPIO_PORT: - if (!request_region(port->iobase, size, "serial")) - ret = -EBUSY; - break; - } - return ret; -} - -static void serial8250_release_std_resource(struct uart_8250_port *up) -{ - unsigned int size = serial8250_port_size(up); - struct uart_port *port = &up->port; - - switch (port->iotype) { - case UPIO_AU: - case UPIO_TSI: - case UPIO_MEM32: - case UPIO_MEM32BE: - case UPIO_MEM: - if (!port->mapbase) - break; - - if (port->flags & UPF_IOREMAP) { - iounmap(port->membase); - port->membase = NULL; - } - - release_mem_region(port->mapbase, size); - break; - - case UPIO_HUB6: - case UPIO_PORT: - release_region(port->iobase, size); - break; - } -} - #ifdef CONFIG_SERIAL_8250_RSA static int serial8250_request_rsa_resource(struct uart_8250_port *up) { @@ -2860,259 +396,6 @@ static void serial8250_release_rsa_resource(struct uart_8250_port *up) } #endif -static void serial8250_release_port(struct uart_port *port) -{ - struct uart_8250_port *up = up_to_u8250p(port); - - serial8250_release_std_resource(up); -} - -static int serial8250_request_port(struct uart_port *port) -{ - struct uart_8250_port *up = up_to_u8250p(port); - int ret; - - if (port->type == PORT_8250_CIR) - return -ENODEV; - - ret = serial8250_request_std_resource(up); - - return ret; -} - -static int fcr_get_rxtrig_bytes(struct uart_8250_port *up) -{ - const struct serial8250_config *conf_type = &uart_config[up->port.type]; - unsigned char bytes; - - bytes = conf_type->rxtrig_bytes[UART_FCR_R_TRIG_BITS(up->fcr)]; - - return bytes ? bytes : -EOPNOTSUPP; -} - -static int bytes_to_fcr_rxtrig(struct uart_8250_port *up, unsigned char bytes) -{ - const struct serial8250_config *conf_type = &uart_config[up->port.type]; - int i; - - if (!conf_type->rxtrig_bytes[UART_FCR_R_TRIG_BITS(UART_FCR_R_TRIG_00)]) - return -EOPNOTSUPP; - - for (i = 1; i < UART_FCR_R_TRIG_MAX_STATE; i++) { - if (bytes < conf_type->rxtrig_bytes[i]) - /* Use the nearest lower value */ - return (--i) << UART_FCR_R_TRIG_SHIFT; - } - - return UART_FCR_R_TRIG_11; -} - -static int do_get_rxtrig(struct tty_port *port) -{ - struct uart_state *state = container_of(port, struct uart_state, port); - struct uart_port *uport = state->uart_port; - struct uart_8250_port *up = - container_of(uport, struct uart_8250_port, port); - - if (!(up->capabilities & UART_CAP_FIFO) || uport->fifosize <= 1) - return -EINVAL; - - return fcr_get_rxtrig_bytes(up); -} - -static int do_serial8250_get_rxtrig(struct tty_port *port) -{ - int rxtrig_bytes; - - mutex_lock(&port->mutex); - rxtrig_bytes = do_get_rxtrig(port); - mutex_unlock(&port->mutex); - - return rxtrig_bytes; -} - -static ssize_t serial8250_get_attr_rx_trig_bytes(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct tty_port *port = dev_get_drvdata(dev); - int rxtrig_bytes; - - rxtrig_bytes = do_serial8250_get_rxtrig(port); - if (rxtrig_bytes < 0) - return rxtrig_bytes; - - return snprintf(buf, PAGE_SIZE, "%d\n", rxtrig_bytes); -} - -static int do_set_rxtrig(struct tty_port *port, unsigned char bytes) -{ - struct uart_state *state = container_of(port, struct uart_state, port); - struct uart_port *uport = state->uart_port; - struct uart_8250_port *up = - container_of(uport, struct uart_8250_port, port); - int rxtrig; - - if (!(up->capabilities & UART_CAP_FIFO) || uport->fifosize <= 1 || - up->fifo_bug) - return -EINVAL; - - rxtrig = bytes_to_fcr_rxtrig(up, bytes); - if (rxtrig < 0) - return rxtrig; - - serial8250_clear_fifos(up); - up->fcr &= ~UART_FCR_TRIGGER_MASK; - up->fcr |= (unsigned char)rxtrig; - serial_out(up, UART_FCR, up->fcr); - return 0; -} - -static int do_serial8250_set_rxtrig(struct tty_port *port, unsigned char bytes) -{ - int ret; - - mutex_lock(&port->mutex); - ret = do_set_rxtrig(port, bytes); - mutex_unlock(&port->mutex); - - return ret; -} - -static ssize_t serial8250_set_attr_rx_trig_bytes(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct tty_port *port = dev_get_drvdata(dev); - unsigned char bytes; - int ret; - - if (!count) - return -EINVAL; - - ret = kstrtou8(buf, 10, &bytes); - if (ret < 0) - return ret; - - ret = do_serial8250_set_rxtrig(port, bytes); - if (ret < 0) - return ret; - - return count; -} - -static DEVICE_ATTR(rx_trig_bytes, S_IRUSR | S_IWUSR | S_IRGRP, - serial8250_get_attr_rx_trig_bytes, - serial8250_set_attr_rx_trig_bytes); - -static struct attribute *serial8250_dev_attrs[] = { - &dev_attr_rx_trig_bytes.attr, - NULL, - }; - -static struct attribute_group serial8250_dev_attr_group = { - .attrs = serial8250_dev_attrs, - }; - -static void register_dev_spec_attr_grp(struct uart_8250_port *up) -{ - const struct serial8250_config *conf_type = &uart_config[up->port.type]; - - if (conf_type->rxtrig_bytes[0]) - up->port.attr_group = &serial8250_dev_attr_group; -} - -static void serial8250_config_port(struct uart_port *port, int flags) -{ - struct uart_8250_port *up = up_to_u8250p(port); - int ret; - - if (port->type == PORT_8250_CIR) - return; - - /* - * Find the region that we can probe for. This in turn - * tells us whether we can probe for the type of port. - */ - ret = serial8250_request_std_resource(up); - if (ret < 0) - return; - - if (port->iotype != up->cur_iotype) - set_io_from_upio(port); - - if (flags & UART_CONFIG_TYPE) - autoconfig(up); - - /* if access method is AU, it is a 16550 with a quirk */ - if (port->type == PORT_16550A && port->iotype == UPIO_AU) - up->bugs |= UART_BUG_NOMSR; - - /* HW bugs may trigger IRQ while IIR == NO_INT */ - if (port->type == PORT_TEGRA) - up->bugs |= UART_BUG_NOMSR; - - if (port->type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ) - autoconfig_irq(up); - - if (port->type == PORT_UNKNOWN) - serial8250_release_std_resource(up); - - /* Fixme: probably not the best place for this */ - if ((port->type == PORT_XR17V35X) || - (port->type == PORT_XR17D15X)) - port->handle_irq = exar_handle_irq; - - register_dev_spec_attr_grp(up); - up->fcr = uart_config[up->port.type].fcr; -} - -static int -serial8250_verify_port(struct uart_port *port, struct serial_struct *ser) -{ - if (ser->irq >= nr_irqs || ser->irq < 0 || - ser->baud_base < 9600 || ser->type < PORT_UNKNOWN || - ser->type >= ARRAY_SIZE(uart_config) || ser->type == PORT_CIRRUS || - ser->type == PORT_STARTECH) - return -EINVAL; - return 0; -} - -static const char * -serial8250_type(struct uart_port *port) -{ - int type = port->type; - - if (type >= ARRAY_SIZE(uart_config)) - type = 0; - return uart_config[type].name; -} - -static const struct uart_ops serial8250_pops = { - .tx_empty = serial8250_tx_empty, - .set_mctrl = serial8250_set_mctrl, - .get_mctrl = serial8250_get_mctrl, - .stop_tx = serial8250_stop_tx, - .start_tx = serial8250_start_tx, - .throttle = serial8250_throttle, - .unthrottle = serial8250_unthrottle, - .stop_rx = serial8250_stop_rx, - .enable_ms = serial8250_enable_ms, - .break_ctl = serial8250_break_ctl, - .startup = serial8250_startup, - .shutdown = serial8250_shutdown, - .set_termios = serial8250_set_termios, - .set_ldisc = serial8250_set_ldisc, - .pm = serial8250_pm, - .type = serial8250_type, - .release_port = serial8250_release_port, - .request_port = serial8250_request_port, - .config_port = serial8250_config_port, - .verify_port = serial8250_verify_port, -#ifdef CONFIG_CONSOLE_POLL - .poll_get_char = serial8250_get_poll_char, - .poll_put_char = serial8250_put_poll_char, -#endif -}; - static const struct uart_ops *base_ops; static struct uart_ops univ8250_port_ops; @@ -3151,42 +434,6 @@ void serial8250_set_isa_configurator( } EXPORT_SYMBOL(serial8250_set_isa_configurator); -static void serial8250_init_port(struct uart_8250_port *up) -{ - struct uart_port *port = &up->port; - - spin_lock_init(&port->lock); - port->ops = &serial8250_pops; - - up->cur_iotype = 0xFF; -} - -static void serial8250_set_defaults(struct uart_8250_port *up) -{ - struct uart_port *port = &up->port; - - if (up->port.flags & UPF_FIXED_TYPE) { - unsigned int type = up->port.type; - - if (!up->port.fifosize) - up->port.fifosize = uart_config[type].fifo_size; - if (!up->tx_loadsz) - up->tx_loadsz = uart_config[type].tx_loadsz; - if (!up->capabilities) - up->capabilities = uart_config[type].flags; - } - - set_io_from_upio(port); - - /* default dma handlers */ - if (up->dma) { - if (!up->dma->tx_dma) - up->dma->tx_dma = serial8250_tx_dma; - if (!up->dma->rx_dma) - up->dma->rx_dma = serial8250_rx_dma; - } -} - #ifdef CONFIG_SERIAL_8250_RSA static void univ8250_config_port(struct uart_port *port, int flags) @@ -3299,10 +546,10 @@ static void __init serial8250_isa_init_ports(void) port->iobase = old_serial_port[i].port; port->irq = irq_canonicalize(old_serial_port[i].irq); - port->irqflags = old_serial_port[i].irqflags; + port->irqflags = 0; port->uartclk = old_serial_port[i].baud_base * 16; port->flags = old_serial_port[i].flags; - port->hub6 = old_serial_port[i].hub6; + port->hub6 = 0; port->membase = old_serial_port[i].iomem_base; port->iotype = old_serial_port[i].io_type; port->regshift = old_serial_port[i].iomem_reg_shift; @@ -3322,6 +569,9 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev) for (i = 0; i < nr_uarts; i++) { struct uart_8250_port *up = &serial8250_ports[i]; + if (up->port.type == PORT_8250_CIR) + continue; + if (up->port.dev) continue; @@ -3336,138 +586,18 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev) #ifdef CONFIG_SERIAL_8250_CONSOLE -static void serial8250_console_putchar(struct uart_port *port, int ch) -{ - struct uart_8250_port *up = up_to_u8250p(port); - - wait_for_xmitr(up, UART_LSR_THRE); - serial_port_out(port, UART_TX, ch); -} - -/* - * Print a string to the serial port trying not to disturb - * any possible real use of the port... - * - * The console_lock must be held when we get here. - */ -static void serial8250_console_write(struct uart_8250_port *up, const char *s, - unsigned int count, unsigned int loglevel) -{ - struct uart_port *port = &up->port; - unsigned long flags; - unsigned int ier; - int locked = 1; - - touch_nmi_watchdog(); - - serial8250_rpm_get(up); - - if (port->sysrq) - locked = 0; - else if (oops_in_progress) - locked = spin_trylock_irqsave(&port->lock, flags); - else - spin_lock_irqsave(&port->lock, flags); - - /* - * First save the IER then disable the interrupts - */ - ier = serial_port_in(port, UART_IER); - - if (up->capabilities & UART_CAP_UUE) - serial_port_out(port, UART_IER, UART_IER_UUE); - else - serial_port_out(port, UART_IER, 0); - - /* check scratch reg to see if port powered off during system sleep */ - if (up->canary && (up->canary != serial_port_in(port, UART_SCR))) { - struct ktermios termios; - unsigned int baud, quot, frac = 0; - - termios.c_cflag = port->cons->cflag; - if (port->state->port.tty && termios.c_cflag == 0) - termios.c_cflag = port->state->port.tty->termios.c_cflag; - - baud = uart_get_baud_rate(port, &termios, NULL, - port->uartclk / 16 / 0xffff, - port->uartclk / 16); - quot = serial8250_get_divisor(up, baud, &frac); - - serial8250_set_divisor(port, baud, quot, frac); - serial_port_out(port, UART_LCR, up->lcr); - serial_port_out(port, UART_MCR, UART_MCR_DTR | UART_MCR_RTS); - - up->canary = 0; - } - - uart_console_write(port, s, count, serial8250_console_putchar); - - /* - * Finally, wait for transmitter to become empty - * and restore the IER - */ - wait_for_xmitr(up, BOTH_EMPTY); - serial_port_out(port, UART_IER, ier); - - /* - * The receive handling will happen properly because the - * receive ready bit will still be set; it is not cleared - * on read. However, modem control will not, we must - * call it if we have saved something in the saved flags - * while processing with interrupts off. - */ - if (up->msr_saved_flags) - serial8250_modem_status(up); - - if (locked) - spin_unlock_irqrestore(&port->lock, flags); - serial8250_rpm_put(up); -} - static void univ8250_console_write(struct console *co, const char *s, - unsigned int count, unsigned int loglevel) + unsigned int count) { struct uart_8250_port *up = &serial8250_ports[co->index]; - serial8250_console_write(up, s, count, loglevel); -} - -static unsigned int probe_baud(struct uart_port *port) -{ - unsigned char lcr, dll, dlm; - unsigned int quot; - - lcr = serial_port_in(port, UART_LCR); - serial_port_out(port, UART_LCR, lcr | UART_LCR_DLAB); - dll = serial_port_in(port, UART_DLL); - dlm = serial_port_in(port, UART_DLM); - serial_port_out(port, UART_LCR, lcr); - - quot = (dlm << 8) | dll; - return (port->uartclk / 16) / quot; -} - -static int serial8250_console_setup(struct uart_port *port, char *options, bool probe) -{ - int baud = 9600; - int bits = 8; - int parity = 'n'; - int flow = 'n'; - - if (!port->iobase && !port->membase) - return -ENODEV; - - if (options) - uart_parse_options(options, &baud, &parity, &bits, &flow); - else if (probe) - baud = probe_baud(port); - - return uart_set_options(port, port->cons, baud, parity, bits, flow); + serial8250_console_write(up, s, count); } static int univ8250_console_setup(struct console *co, char *options) { struct uart_port *port; + int retval; /* * Check whether an invalid uart number has been specified, and @@ -3480,7 +610,10 @@ static int univ8250_console_setup(struct console *co, char *options) /* link port to console */ port->cons = co; - return serial8250_console_setup(port, options, false); + retval = serial8250_console_setup(port, options, false); + if (retval != 0) + port->cons = NULL; + return retval; } /** @@ -3491,7 +624,7 @@ static int univ8250_console_setup(struct console *co, char *options) * @options: ptr to option string from console command line * * Only attempts to match console command lines of the form: - * console=uart[8250],io|mmio|mmio32,<addr>[,<options>] + * console=uart[8250],io|mmio|mmio16|mmio32,<addr>[,<options>] * console=uart[8250],0x<addr>[,<options>] * This form is used to register an initial earlycon boot console and * replace it with the serial8250_console at 8250 driver init. @@ -3521,8 +654,9 @@ static int univ8250_console_match(struct console *co, char *name, int idx, if (port->iotype != iotype) continue; - if ((iotype == UPIO_MEM || iotype == UPIO_MEM32) && - (port->mapbase != addr)) + if ((iotype == UPIO_MEM || iotype == UPIO_MEM16 || + iotype == UPIO_MEM32 || iotype == UPIO_MEM32BE) + && (port->mapbase != addr)) continue; if (iotype == UPIO_PORT && port->iobase != addr) continue; @@ -3541,20 +675,23 @@ static struct console univ8250_console = { .device = uart_console_device, .setup = univ8250_console_setup, .match = univ8250_console_match, - .flags = CON_PRINTBUFFER | CON_ANYTIME, + .flags = CON_PRINTBUFFER | CON_ANYTIME | CON_CONSDEV, .index = -1, .data = &serial8250_reg, }; static int __init univ8250_console_init(void) { + if (nr_uarts == 0) + return -ENODEV; + serial8250_isa_init_ports(); register_console(&univ8250_console); return 0; } console_initcall(univ8250_console_init); -#define SERIAL8250_CONSOLE &univ8250_console +#define SERIAL8250_CONSOLE (&univ8250_console) #else #define SERIAL8250_CONSOLE NULL #endif @@ -3578,7 +715,7 @@ int __init early_serial_setup(struct uart_port *port) { struct uart_port *p; - if (port->line >= ARRAY_SIZE(serial8250_ports)) + if (port->line >= ARRAY_SIZE(serial8250_ports) || nr_uarts == 0) return -ENODEV; serial8250_isa_init_ports(); @@ -3631,6 +768,7 @@ void serial8250_suspend_port(int line) uart_suspend_port(&serial8250_reg, port); } +EXPORT_SYMBOL(serial8250_suspend_port); /** * serial8250_resume_port - resume one serial port @@ -3656,6 +794,7 @@ void serial8250_resume_port(int line) } uart_resume_port(&serial8250_reg, port); } +EXPORT_SYMBOL(serial8250_resume_port); /* * Register a set of serial devices attached to a platform device. The @@ -3691,6 +830,7 @@ static int serial8250_probe(struct platform_device *dev) uart.port.handle_irq = p->handle_irq; uart.port.handle_break = p->handle_break; uart.port.set_termios = p->set_termios; + uart.port.get_mctrl = p->get_mctrl; uart.port.pm = p->pm; uart.port.dev = &dev->dev; uart.port.irqflags |= irqflag; @@ -3850,7 +990,6 @@ int serial8250_register_8250_port(struct uart_8250_port *up) uart->port.mapbase = up->port.mapbase; uart->port.mapsize = up->port.mapsize; uart->port.private_data = up->port.private_data; - uart->port.fifosize = up->port.fifosize; uart->tx_loadsz = up->tx_loadsz; uart->capabilities = up->capabilities; uart->port.throttle = up->port.throttle; @@ -3884,6 +1023,8 @@ int serial8250_register_8250_port(struct uart_8250_port *up) /* Possibly override set_termios call */ if (up->port.set_termios) uart->port.set_termios = up->port.set_termios; + if (up->port.get_mctrl) + uart->port.get_mctrl = up->port.get_mctrl; if (up->port.set_mctrl) uart->port.set_mctrl = up->port.set_mctrl; if (up->port.startup) @@ -3899,13 +1040,24 @@ int serial8250_register_8250_port(struct uart_8250_port *up) if (up->dl_write) uart->dl_write = up->dl_write; - if (serial8250_isa_config != NULL) - serial8250_isa_config(0, &uart->port, - &uart->capabilities); + if (uart->port.type != PORT_8250_CIR) { + if (serial8250_isa_config != NULL) + serial8250_isa_config(0, &uart->port, + &uart->capabilities); + + ret = uart_add_one_port(&serial8250_reg, + &uart->port); + if (ret == 0) + ret = uart->port.line; + } else { + dev_info(uart->port.dev, + "skipping CIR port at 0x%lx / 0x%llx, IRQ %d\n", + uart->port.iobase, + (unsigned long long)uart->port.mapbase, + uart->port.irq); - ret = uart_add_one_port(&serial8250_reg, &uart->port); - if (ret == 0) - ret = uart->port.line; + ret = 0; + } } mutex_unlock(&serial_mutex); @@ -3925,6 +1077,15 @@ void serial8250_unregister_port(int line) struct uart_8250_port *uart = &serial8250_ports[line]; mutex_lock(&serial_mutex); + + if (uart->em485) { + unsigned long flags; + + spin_lock_irqsave(&uart->port.lock, flags); + serial8250_em485_destroy(uart); + spin_unlock_irqrestore(&uart->port.lock, flags); + } + uart_remove_one_port(&serial8250_reg, &uart->port); if (serial8250_isa_devs) { uart->port.flags &= ~UPF_BOOT_AUTOCONF; @@ -3945,11 +1106,13 @@ static int __init serial8250_init(void) { int ret; + if (nr_uarts == 0) + return -ENODEV; + serial8250_isa_init_ports(); - printk(KERN_INFO "Serial: 8250/16550 driver, " - "%d ports, IRQ sharing %sabled\n", nr_uarts, - share_irqs ? "en" : "dis"); + pr_info("Serial: 8250/16550 driver, %d ports, IRQ sharing %sabled\n", + nr_uarts, share_irqs ? "en" : "dis"); #ifdef CONFIG_SPARC ret = sunserial_register_minors(&serial8250_reg, UART_NR); @@ -4022,15 +1185,11 @@ static void __exit serial8250_exit(void) module_init(serial8250_init); module_exit(serial8250_exit); -EXPORT_SYMBOL(serial8250_suspend_port); -EXPORT_SYMBOL(serial8250_resume_port); - MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Generic 8250/16x50 serial driver"); module_param(share_irqs, uint, 0644); -MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices" - " (unsafe)"); +MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices (unsafe)"); module_param(nr_uarts, uint, 0644); MODULE_PARM_DESC(nr_uarts, "Maximum number of UARTs supported. (1-" __MODULE_STRING(CONFIG_SERIAL_8250_NR_UARTS) ")"); diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c index 21d01a491..3590d0120 100644 --- a/drivers/tty/serial/8250/8250_dma.c +++ b/drivers/tty/serial/8250/8250_dma.c @@ -54,9 +54,6 @@ static void __dma_rx_complete(void *param) struct dma_tx_state state; int count; - dma_sync_single_for_cpu(dma->rxchan->device->dev, dma->rx_addr, - dma->rx_size, DMA_FROM_DEVICE); - dma->rx_running = 0; dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state); @@ -80,10 +77,6 @@ int serial8250_tx_dma(struct uart_8250_port *p) return 0; dma->tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); - if (dma->tx_size < p->port.fifosize) { - ret = -EINVAL; - goto err; - } desc = dmaengine_prep_slave_single(dma->txchan, dma->tx_addr + xmit->tail, @@ -117,30 +110,11 @@ err: return ret; } -int serial8250_rx_dma(struct uart_8250_port *p, unsigned int iir) +int serial8250_rx_dma(struct uart_8250_port *p) { struct uart_8250_dma *dma = p->dma; struct dma_async_tx_descriptor *desc; - switch (iir & 0x3f) { - case UART_IIR_RLSI: - /* 8250_core handles errors and break interrupts */ - return -EIO; - case UART_IIR_RX_TIMEOUT: - /* - * If RCVR FIFO trigger level was not reached, complete the - * transfer and let 8250_core copy the remaining data. - */ - if (dma->rx_running) { - dmaengine_pause(dma->rxchan); - __dma_rx_complete(p); - dmaengine_terminate_all(dma->rxchan); - } - return -ETIMEDOUT; - default: - break; - } - if (dma->rx_running) return 0; @@ -156,18 +130,29 @@ int serial8250_rx_dma(struct uart_8250_port *p, unsigned int iir) dma->rx_cookie = dmaengine_submit(desc); - dma_sync_single_for_device(dma->rxchan->device->dev, dma->rx_addr, - dma->rx_size, DMA_FROM_DEVICE); - dma_async_issue_pending(dma->rxchan); return 0; } +void serial8250_rx_dma_flush(struct uart_8250_port *p) +{ + struct uart_8250_dma *dma = p->dma; + + if (dma->rx_running) { + dmaengine_pause(dma->rxchan); + __dma_rx_complete(p); + dmaengine_terminate_all(dma->rxchan); + } +} +EXPORT_SYMBOL_GPL(serial8250_rx_dma_flush); + int serial8250_request_dma(struct uart_8250_port *p) { struct uart_8250_dma *dma = p->dma; dma_cap_mask_t mask; + struct dma_slave_caps caps; + int ret; /* Default slave configuration parameters */ dma->rxconf.direction = DMA_DEV_TO_MEM; @@ -188,6 +173,16 @@ int serial8250_request_dma(struct uart_8250_port *p) if (!dma->rxchan) return -ENODEV; + /* 8250 rx dma requires dmaengine driver to support pause/terminate */ + ret = dma_get_slave_caps(dma->rxchan, &caps); + if (ret) + goto release_rx; + if (!caps.cmd_pause || !caps.cmd_terminate || + caps.residue_granularity == DMA_RESIDUE_GRANULARITY_DESCRIPTOR) { + ret = -EINVAL; + goto release_rx; + } + dmaengine_slave_config(dma->rxchan, &dma->rxconf); /* Get a channel for TX */ @@ -195,8 +190,17 @@ int serial8250_request_dma(struct uart_8250_port *p) dma->fn, dma->tx_param, p->port.dev, "tx"); if (!dma->txchan) { - dma_release_channel(dma->rxchan); - return -ENODEV; + ret = -ENODEV; + goto release_rx; + } + + /* 8250 tx dma requires dmaengine driver to support terminate */ + ret = dma_get_slave_caps(dma->txchan, &caps); + if (ret) + goto err; + if (!caps.cmd_terminate) { + ret = -EINVAL; + goto err; } dmaengine_slave_config(dma->txchan, &dma->txconf); @@ -207,8 +211,10 @@ int serial8250_request_dma(struct uart_8250_port *p) dma->rx_buf = dma_alloc_coherent(dma->rxchan->device->dev, dma->rx_size, &dma->rx_addr, GFP_KERNEL); - if (!dma->rx_buf) + if (!dma->rx_buf) { + ret = -ENOMEM; goto err; + } /* TX buffer */ dma->tx_addr = dma_map_single(dma->txchan->device->dev, @@ -218,6 +224,7 @@ int serial8250_request_dma(struct uart_8250_port *p) if (dma_mapping_error(dma->txchan->device->dev, dma->tx_addr)) { dma_free_coherent(dma->rxchan->device->dev, dma->rx_size, dma->rx_buf, dma->rx_addr); + ret = -ENOMEM; goto err; } @@ -225,10 +232,10 @@ int serial8250_request_dma(struct uart_8250_port *p) return 0; err: - dma_release_channel(dma->rxchan); dma_release_channel(dma->txchan); - - return -ENOMEM; +release_rx: + dma_release_channel(dma->rxchan); + return ret; } EXPORT_SYMBOL_GPL(serial8250_request_dma); diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 176f18f2e..b022f5a01 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -56,7 +56,6 @@ struct dw8250_data { u8 usr_reg; - int last_mcr; int line; int msr_mask_on; int msr_mask_off; @@ -64,24 +63,15 @@ struct dw8250_data { struct clk *pclk; struct reset_control *rst; struct uart_8250_dma dma; -}; -#define BYT_PRV_CLK 0x800 -#define BYT_PRV_CLK_EN (1 << 0) -#define BYT_PRV_CLK_M_VAL_SHIFT 1 -#define BYT_PRV_CLK_N_VAL_SHIFT 16 -#define BYT_PRV_CLK_UPDATE (1 << 31) + unsigned int skip_autocfg:1; + unsigned int uart_16550_compatible:1; +}; static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value) { struct dw8250_data *d = p->private_data; - /* If reading MSR, report CTS asserted when auto-CTS/RTS enabled */ - if (offset == UART_MSR && d->last_mcr & UART_MCR_AFE) { - value |= UART_MSR_CTS; - value &= ~UART_MSR_DCTS; - } - /* Override any modem control signals if needed */ if (offset == UART_MSR) { value |= d->msr_mask_on; @@ -99,30 +89,46 @@ static void dw8250_force_idle(struct uart_port *p) (void)p->serial_in(p, UART_RX); } +static void dw8250_check_lcr(struct uart_port *p, int value) +{ + void __iomem *offset = p->membase + (UART_LCR << p->regshift); + int tries = 1000; + + /* Make sure LCR write wasn't ignored */ + while (tries--) { + unsigned int lcr = p->serial_in(p, UART_LCR); + + if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR)) + return; + + dw8250_force_idle(p); + +#ifdef CONFIG_64BIT + if (p->type == PORT_OCTEON) + __raw_writeq(value & 0xff, offset); + else +#endif + if (p->iotype == UPIO_MEM32) + writel(value, offset); + else if (p->iotype == UPIO_MEM32BE) + iowrite32be(value, offset); + else + writeb(value, offset); + } + /* + * FIXME: this deadlocks if port->lock is already held + * dev_err(p->dev, "Couldn't set LCR to %d\n", value); + */ +} + static void dw8250_serial_out(struct uart_port *p, int offset, int value) { struct dw8250_data *d = p->private_data; - if (offset == UART_MCR) - d->last_mcr = value; - writeb(value, p->membase + (offset << p->regshift)); - /* Make sure LCR write wasn't ignored */ - if (offset == UART_LCR) { - int tries = 1000; - while (tries--) { - unsigned int lcr = p->serial_in(p, UART_LCR); - if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR)) - return; - dw8250_force_idle(p); - writeb(value, p->membase + (UART_LCR << p->regshift)); - } - /* - * FIXME: this deadlocks if port->lock is already held - * dev_err(p->dev, "Couldn't set LCR to %d\n", value); - */ - } + if (offset == UART_LCR && !d->uart_16550_compatible) + dw8250_check_lcr(p, value); } static unsigned int dw8250_serial_in(struct uart_port *p, int offset) @@ -146,30 +152,13 @@ static void dw8250_serial_outq(struct uart_port *p, int offset, int value) { struct dw8250_data *d = p->private_data; - if (offset == UART_MCR) - d->last_mcr = value; - value &= 0xff; __raw_writeq(value, p->membase + (offset << p->regshift)); /* Read back to ensure register write ordering. */ __raw_readq(p->membase + (UART_LCR << p->regshift)); - /* Make sure LCR write wasn't ignored */ - if (offset == UART_LCR) { - int tries = 1000; - while (tries--) { - unsigned int lcr = p->serial_in(p, UART_LCR); - if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR)) - return; - dw8250_force_idle(p); - __raw_writeq(value & 0xff, - p->membase + (UART_LCR << p->regshift)); - } - /* - * FIXME: this deadlocks if port->lock is already held - * dev_err(p->dev, "Couldn't set LCR to %d\n", value); - */ - } + if (offset == UART_LCR && !d->uart_16550_compatible) + dw8250_check_lcr(p, value); } #endif /* CONFIG_64BIT */ @@ -177,26 +166,10 @@ static void dw8250_serial_out32(struct uart_port *p, int offset, int value) { struct dw8250_data *d = p->private_data; - if (offset == UART_MCR) - d->last_mcr = value; - writel(value, p->membase + (offset << p->regshift)); - /* Make sure LCR write wasn't ignored */ - if (offset == UART_LCR) { - int tries = 1000; - while (tries--) { - unsigned int lcr = p->serial_in(p, UART_LCR); - if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR)) - return; - dw8250_force_idle(p); - writel(value, p->membase + (UART_LCR << p->regshift)); - } - /* - * FIXME: this deadlocks if port->lock is already held - * dev_err(p->dev, "Couldn't set LCR to %d\n", value); - */ - } + if (offset == UART_LCR && !d->uart_16550_compatible) + dw8250_check_lcr(p, value); } static unsigned int dw8250_serial_in32(struct uart_port *p, int offset) @@ -206,14 +179,33 @@ static unsigned int dw8250_serial_in32(struct uart_port *p, int offset) return dw8250_modify_msr(p, offset, value); } +static void dw8250_serial_out32be(struct uart_port *p, int offset, int value) +{ + struct dw8250_data *d = p->private_data; + + iowrite32be(value, p->membase + (offset << p->regshift)); + + if (offset == UART_LCR && !d->uart_16550_compatible) + dw8250_check_lcr(p, value); +} + +static unsigned int dw8250_serial_in32be(struct uart_port *p, int offset) +{ + unsigned int value = ioread32be(p->membase + (offset << p->regshift)); + + return dw8250_modify_msr(p, offset, value); +} + + static int dw8250_handle_irq(struct uart_port *p) { struct dw8250_data *d = p->private_data; unsigned int iir = p->serial_in(p, UART_IIR); - if (serial8250_handle_irq(p, iir)) { + if (serial8250_handle_irq(p, iir)) return 1; - } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) { + + if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) { /* Clear the USR */ (void)p->serial_in(p, d->usr_reg); @@ -246,10 +238,6 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios, if (IS_ERR(d->clk) || !old) goto out; - /* Not requesting clock rates below 1.8432Mhz */ - if (baud < 115200) - baud = 115200; - clk_disable_unprepare(d->clk); rate = clk_round_rate(d->clk, baud * 16); ret = clk_set_rate(d->clk, rate); @@ -257,31 +245,100 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios, if (!ret) p->uartclk = rate; + + p->status &= ~UPSTAT_AUTOCTS; + if (termios->c_cflag & CRTSCTS) + p->status |= UPSTAT_AUTOCTS; + out: serial8250_do_set_termios(p, termios, old); } -static bool dw8250_dma_filter(struct dma_chan *chan, void *param) +/* + * dw8250_fallback_dma_filter will prevent the UART from getting just any free + * channel on platforms that have DMA engines, but don't have any channels + * assigned to the UART. + * + * REVISIT: This is a work around for limitation in the DMA Engine API. Once the + * core problem is fixed, this function is no longer needed. + */ +static bool dw8250_fallback_dma_filter(struct dma_chan *chan, void *param) { return false; } -static void dw8250_setup_port(struct uart_8250_port *up) +static bool dw8250_idma_filter(struct dma_chan *chan, void *param) +{ + return param == chan->device->dev->parent; +} + +static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data) { - struct uart_port *p = &up->port; - u32 reg = readl(p->membase + DW_UART_UCV); + if (p->dev->of_node) { + struct device_node *np = p->dev->of_node; + int id; + + /* get index of serial line, if found in DT aliases */ + id = of_alias_get_id(np, "serial"); + if (id >= 0) + p->line = id; +#ifdef CONFIG_64BIT + if (of_device_is_compatible(np, "cavium,octeon-3860-uart")) { + p->serial_in = dw8250_serial_inq; + p->serial_out = dw8250_serial_outq; + p->flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE; + p->type = PORT_OCTEON; + data->usr_reg = 0x27; + data->skip_autocfg = true; + } +#endif + if (of_device_is_big_endian(p->dev->of_node)) { + p->iotype = UPIO_MEM32BE; + p->serial_in = dw8250_serial_in32be; + p->serial_out = dw8250_serial_out32be; + } + } else if (has_acpi_companion(p->dev)) { + p->iotype = UPIO_MEM32; + p->regshift = 2; + p->serial_in = dw8250_serial_in32; + p->set_termios = dw8250_set_termios; + /* So far none of there implement the Busy Functionality */ + data->uart_16550_compatible = true; + } + + /* Platforms with iDMA */ + if (platform_get_resource_byname(to_platform_device(p->dev), + IORESOURCE_MEM, "lpss_priv")) { + p->set_termios = dw8250_set_termios; + data->dma.rx_param = p->dev->parent; + data->dma.tx_param = p->dev->parent; + data->dma.fn = dw8250_idma_filter; + } +} + +static void dw8250_setup_port(struct uart_port *p) +{ + struct uart_8250_port *up = up_to_u8250p(p); + u32 reg; /* * If the Component Version Register returns zero, we know that * ADDITIONAL_FEATURES are not enabled. No need to go any further. */ + if (p->iotype == UPIO_MEM32BE) + reg = ioread32be(p->membase + DW_UART_UCV); + else + reg = readl(p->membase + DW_UART_UCV); if (!reg) return; - dev_dbg_ratelimited(p->dev, "Designware UART version %c.%c%c\n", + dev_dbg(p->dev, "Designware UART version %c.%c%c\n", (reg >> 24) & 0xff, (reg >> 16) & 0xff, (reg >> 8) & 0xff); - reg = readl(p->membase + DW_UART_CPR); + if (p->iotype == UPIO_MEM32BE) + reg = ioread32be(p->membase + DW_UART_CPR); + else + reg = readl(p->membase + DW_UART_CPR); if (!reg) return; @@ -290,7 +347,6 @@ static void dw8250_setup_port(struct uart_8250_port *up) p->type = PORT_16550A; p->flags |= UPF_FIXED_TYPE; p->fifosize = DW_UART_CPR_FIFO_SIZE(reg); - up->tx_loadsz = p->fifosize; up->capabilities = UART_CAP_FIFO; } @@ -298,149 +354,91 @@ static void dw8250_setup_port(struct uart_8250_port *up) up->capabilities |= UART_CAP_AFE; } -static int dw8250_probe_of(struct uart_port *p, - struct dw8250_data *data) +static int dw8250_probe(struct platform_device *pdev) { - struct device_node *np = p->dev->of_node; - struct uart_8250_port *up = up_to_u8250p(p); - u32 val; - bool has_ucv = true; - int id; + struct uart_8250_port uart = {}; + struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); + int irq = platform_get_irq(pdev, 0); + struct uart_port *p = &uart.port; + struct dw8250_data *data; + int err; + u32 val; -#ifdef CONFIG_64BIT - if (of_device_is_compatible(np, "cavium,octeon-3860-uart")) { - p->serial_in = dw8250_serial_inq; - p->serial_out = dw8250_serial_outq; - p->flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE; - p->type = PORT_OCTEON; - data->usr_reg = 0x27; - has_ucv = false; - } else -#endif - if (!of_property_read_u32(np, "reg-io-width", &val)) { - switch (val) { - case 1: - break; - case 4: - p->iotype = UPIO_MEM32; - p->serial_in = dw8250_serial_in32; - p->serial_out = dw8250_serial_out32; - break; - default: - dev_err(p->dev, "unsupported reg-io-width (%u)\n", val); - return -EINVAL; - } + if (!regs) { + dev_err(&pdev->dev, "no registers defined\n"); + return -EINVAL; } - if (has_ucv) - dw8250_setup_port(up); - - /* if we have a valid fifosize, try hooking up DMA here */ - if (p->fifosize) { - up->dma = &data->dma; - up->dma->rxconf.src_maxburst = p->fifosize / 4; - up->dma->txconf.dst_maxburst = p->fifosize / 4; + if (irq < 0) { + if (irq != -EPROBE_DEFER) + dev_err(&pdev->dev, "cannot get irq\n"); + return irq; } - if (!of_property_read_u32(np, "reg-shift", &val)) + spin_lock_init(&p->lock); + p->mapbase = regs->start; + p->irq = irq; + p->handle_irq = dw8250_handle_irq; + p->pm = dw8250_do_pm; + p->type = PORT_8250; + p->flags = UPF_SHARE_IRQ | UPF_FIXED_PORT; + p->dev = &pdev->dev; + p->iotype = UPIO_MEM; + p->serial_in = dw8250_serial_in; + p->serial_out = dw8250_serial_out; + + p->membase = devm_ioremap(&pdev->dev, regs->start, resource_size(regs)); + if (!p->membase) + return -ENOMEM; + + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->dma.fn = dw8250_fallback_dma_filter; + data->usr_reg = DW_UART_USR; + p->private_data = data; + + data->uart_16550_compatible = device_property_read_bool(p->dev, + "snps,uart-16550-compatible"); + + err = device_property_read_u32(p->dev, "reg-shift", &val); + if (!err) p->regshift = val; - /* get index of serial line, if found in DT aliases */ - id = of_alias_get_id(np, "serial"); - if (id >= 0) - p->line = id; + err = device_property_read_u32(p->dev, "reg-io-width", &val); + if (!err && val == 4) { + p->iotype = UPIO_MEM32; + p->serial_in = dw8250_serial_in32; + p->serial_out = dw8250_serial_out32; + } - if (of_property_read_bool(np, "dcd-override")) { + if (device_property_read_bool(p->dev, "dcd-override")) { /* Always report DCD as active */ data->msr_mask_on |= UART_MSR_DCD; data->msr_mask_off |= UART_MSR_DDCD; } - if (of_property_read_bool(np, "dsr-override")) { + if (device_property_read_bool(p->dev, "dsr-override")) { /* Always report DSR as active */ data->msr_mask_on |= UART_MSR_DSR; data->msr_mask_off |= UART_MSR_DDSR; } - if (of_property_read_bool(np, "cts-override")) { + if (device_property_read_bool(p->dev, "cts-override")) { /* Always report CTS as active */ data->msr_mask_on |= UART_MSR_CTS; data->msr_mask_off |= UART_MSR_DCTS; } - if (of_property_read_bool(np, "ri-override")) { + if (device_property_read_bool(p->dev, "ri-override")) { /* Always report Ring indicator as inactive */ data->msr_mask_off |= UART_MSR_RI; data->msr_mask_off |= UART_MSR_TERI; } - return 0; -} - -static int dw8250_probe_acpi(struct uart_8250_port *up, - struct dw8250_data *data) -{ - struct uart_port *p = &up->port; - - dw8250_setup_port(up); - - p->iotype = UPIO_MEM32; - p->serial_in = dw8250_serial_in32; - p->serial_out = dw8250_serial_out32; - p->regshift = 2; - - up->dma = &data->dma; - - up->dma->rxconf.src_maxburst = p->fifosize / 4; - up->dma->txconf.dst_maxburst = p->fifosize / 4; - - up->port.set_termios = dw8250_set_termios; - - return 0; -} - -static int dw8250_probe(struct platform_device *pdev) -{ - struct uart_8250_port uart = {}; - struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - int irq = platform_get_irq(pdev, 0); - struct dw8250_data *data; - int err; - - if (!regs) { - dev_err(&pdev->dev, "no registers defined\n"); - return -EINVAL; - } - - if (irq < 0) { - if (irq != -EPROBE_DEFER) - dev_err(&pdev->dev, "cannot get irq\n"); - return irq; - } - - spin_lock_init(&uart.port.lock); - uart.port.mapbase = regs->start; - uart.port.irq = irq; - uart.port.handle_irq = dw8250_handle_irq; - uart.port.pm = dw8250_do_pm; - uart.port.type = PORT_8250; - uart.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_FIXED_PORT; - uart.port.dev = &pdev->dev; - - uart.port.membase = devm_ioremap(&pdev->dev, regs->start, - resource_size(regs)); - if (!uart.port.membase) - return -ENOMEM; - - data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - data->usr_reg = DW_UART_USR; - /* Always ask for fixed clock rate from a property. */ - device_property_read_u32(&pdev->dev, "clock-frequency", - &uart.port.uartclk); + device_property_read_u32(p->dev, "clock-frequency", &p->uartclk); /* If there is separate baudclk, get the rate from it. */ data->clk = devm_clk_get(&pdev->dev, "baudclk"); @@ -454,17 +452,17 @@ static int dw8250_probe(struct platform_device *pdev) dev_warn(&pdev->dev, "could not enable optional baudclk: %d\n", err); else - uart.port.uartclk = clk_get_rate(data->clk); + p->uartclk = clk_get_rate(data->clk); } /* If no clock rate is defined, fail. */ - if (!uart.port.uartclk) { + if (!p->uartclk) { dev_err(&pdev->dev, "clock rate not defined\n"); return -EINVAL; } data->pclk = devm_clk_get(&pdev->dev, "apb_pclk"); - if (IS_ERR(data->clk) && PTR_ERR(data->clk) == -EPROBE_DEFER) { + if (IS_ERR(data->pclk) && PTR_ERR(data->pclk) == -EPROBE_DEFER) { err = -EPROBE_DEFER; goto err_clk; } @@ -484,26 +482,20 @@ static int dw8250_probe(struct platform_device *pdev) if (!IS_ERR(data->rst)) reset_control_deassert(data->rst); - data->dma.rx_param = data; - data->dma.tx_param = data; - data->dma.fn = dw8250_dma_filter; + dw8250_quirks(p, data); - uart.port.iotype = UPIO_MEM; - uart.port.serial_in = dw8250_serial_in; - uart.port.serial_out = dw8250_serial_out; - uart.port.private_data = data; + /* If the Busy Functionality is not implemented, don't handle it */ + if (data->uart_16550_compatible) + p->handle_irq = NULL; - if (pdev->dev.of_node) { - err = dw8250_probe_of(&uart.port, data); - if (err) - goto err_reset; - } else if (ACPI_HANDLE(&pdev->dev)) { - err = dw8250_probe_acpi(&uart, data); - if (err) - goto err_reset; - } else { - err = -ENODEV; - goto err_reset; + if (!data->skip_autocfg) + dw8250_setup_port(p); + + /* If we have a valid fifosize, try hooking up DMA */ + if (p->fifosize) { + data->dma.rxconf.src_maxburst = p->fifosize / 4; + data->dma.txconf.dst_maxburst = p->fifosize / 4; + uart.dma = &data->dma; } data->line = serial8250_register_8250_port(&uart); @@ -626,6 +618,7 @@ static const struct acpi_device_id dw8250_acpi_match[] = { { "8086228A", 0 }, { "APMC0D08", 0}, { "AMD0020", 0 }, + { "AMDI0020", 0 }, { }, }; MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match); diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c index f8adaf2c9..85a12f032 100644 --- a/drivers/tty/serial/8250/8250_early.c +++ b/drivers/tty/serial/8250/8250_early.c @@ -29,21 +29,27 @@ #include <linux/tty.h> #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> #include <asm/io.h> #include <asm/serial.h> -unsigned int __weak __init serial8250_early_in(struct uart_port *port, int offset) +static unsigned int __init serial8250_early_in(struct uart_port *port, int offset) { + offset <<= port->regshift; + switch (port->iotype) { case UPIO_MEM: return readb(port->membase + offset); + case UPIO_MEM16: + return readw(port->membase + offset); case UPIO_MEM32: - return readl(port->membase + (offset << 2)); + return readl(port->membase + offset); case UPIO_MEM32BE: - return ioread32be(port->membase + (offset << 2)); + return ioread32be(port->membase + offset); case UPIO_PORT: return inb(port->iobase + offset); default: @@ -51,17 +57,22 @@ unsigned int __weak __init serial8250_early_in(struct uart_port *port, int offse } } -void __weak __init serial8250_early_out(struct uart_port *port, int offset, int value) +static void __init serial8250_early_out(struct uart_port *port, int offset, int value) { + offset <<= port->regshift; + switch (port->iotype) { case UPIO_MEM: writeb(value, port->membase + offset); break; + case UPIO_MEM16: + writew(value, port->membase + offset); + break; case UPIO_MEM32: - writel(value, port->membase + (offset << 2)); + writel(value, port->membase + offset); break; case UPIO_MEM32BE: - iowrite32be(value, port->membase + (offset << 2)); + iowrite32be(value, port->membase + offset); break; case UPIO_PORT: outb(value, port->iobase + offset); @@ -71,43 +82,27 @@ void __weak __init serial8250_early_out(struct uart_port *port, int offset, int #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) -static void __init wait_for_xmitr(struct uart_port *port) +static void __init serial_putc(struct uart_port *port, int c) { unsigned int status; + serial8250_early_out(port, UART_TX, c); + for (;;) { status = serial8250_early_in(port, UART_LSR); if ((status & BOTH_EMPTY) == BOTH_EMPTY) - return; + break; cpu_relax(); } } -static void __init serial_putc(struct uart_port *port, int c) -{ - wait_for_xmitr(port); - serial8250_early_out(port, UART_TX, c); -} - static void __init early_serial8250_write(struct console *console, - const char *s, unsigned int count, unsigned int loglevel) + const char *s, unsigned int count) { struct earlycon_device *device = console->data; struct uart_port *port = &device->port; - unsigned int ier; - - /* Save the IER and disable interrupts preserving the UUE bit */ - ier = serial8250_early_in(port, UART_IER); - if (ier) - serial8250_early_out(port, UART_IER, ier & UART_IER_UUE); uart_console_write(port, s, count, serial_putc); - - /* Wait for transmitter to become empty and restore the IER */ - wait_for_xmitr(port); - - if (ier) - serial8250_early_out(port, UART_IER, ier); } static void __init init_port(struct earlycon_device *device) @@ -131,7 +126,7 @@ static void __init init_port(struct earlycon_device *device) serial8250_early_out(port, UART_LCR, c & ~UART_LCR_DLAB); } -static int __init early_serial8250_setup(struct earlycon_device *device, +int __init early_serial8250_setup(struct earlycon_device *device, const char *options) { if (!(device->port.membase || device->port.iobase)) @@ -152,3 +147,28 @@ static int __init early_serial8250_setup(struct earlycon_device *device, } EARLYCON_DECLARE(uart8250, early_serial8250_setup); EARLYCON_DECLARE(uart, early_serial8250_setup); +OF_EARLYCON_DECLARE(ns16550, "ns16550", early_serial8250_setup); +OF_EARLYCON_DECLARE(ns16550a, "ns16550a", early_serial8250_setup); +OF_EARLYCON_DECLARE(uart, "nvidia,tegra20-uart", early_serial8250_setup); +OF_EARLYCON_DECLARE(uart, "snps,dw-apb-uart", early_serial8250_setup); + +#ifdef CONFIG_SERIAL_8250_OMAP + +static int __init early_omap8250_setup(struct earlycon_device *device, + const char *options) +{ + struct uart_port *port = &device->port; + + if (!(device->port.membase || device->port.iobase)) + return -ENODEV; + + port->regshift = 2; + device->con->write = early_serial8250_write; + return 0; +} + +OF_EARLYCON_DECLARE(omap8250, "ti,omap2-uart", early_omap8250_setup); +OF_EARLYCON_DECLARE(omap8250, "ti,omap3-uart", early_omap8250_setup); +OF_EARLYCON_DECLARE(omap8250, "ti,omap4-uart", early_omap8250_setup); + +#endif diff --git a/drivers/tty/serial/8250/8250_exar_st16c554.c b/drivers/tty/serial/8250/8250_exar_st16c554.c index bf53aabf9..3a7cb8262 100644 --- a/drivers/tty/serial/8250/8250_exar_st16c554.c +++ b/drivers/tty/serial/8250/8250_exar_st16c554.c @@ -13,20 +13,13 @@ #include <linux/init.h> #include <linux/serial_8250.h> -#define PORT(_base,_irq) \ - { \ - .iobase = _base, \ - .irq = _irq, \ - .uartclk = 1843200, \ - .iotype = UPIO_PORT, \ - .flags = UPF_BOOT_AUTOCONF, \ - } +#include "8250.h" static struct plat_serial8250_port exar_data[] = { - PORT(0x100, 5), - PORT(0x108, 5), - PORT(0x110, 5), - PORT(0x118, 5), + SERIAL8250_PORT(0x100, 5), + SERIAL8250_PORT(0x108, 5), + SERIAL8250_PORT(0x110, 5), + SERIAL8250_PORT(0x118, 5), { }, }; diff --git a/drivers/tty/serial/8250/8250_fintek.c b/drivers/tty/serial/8250/8250_fintek.c index 5815e81b5..0facc789f 100644 --- a/drivers/tty/serial/8250/8250_fintek.c +++ b/drivers/tty/serial/8250/8250_fintek.c @@ -1,9 +1,7 @@ /* * Probe for F81216A LPC to 4 UART * - * Based on drivers/tty/serial/8250_pnp.c, by Russell King, et al - * - * Copyright (C) 2014 Ricardo Ribalda, Qtechnology A/S + * Copyright (C) 2014-2016 Ricardo Ribalda, Qtechnology A/S * * * This program is free software; you can redistribute it and/or modify @@ -15,75 +13,77 @@ #include <linux/pnp.h> #include <linux/kernel.h> #include <linux/serial_core.h> +#include <linux/irq.h> #include "8250.h" -#define ADDR_PORT 0x4E -#define DATA_PORT 0x4F -#define ENTRY_KEY 0x77 +#define ADDR_PORT 0 +#define DATA_PORT 1 #define EXIT_KEY 0xAA #define CHIP_ID1 0x20 -#define CHIP_ID1_VAL 0x02 #define CHIP_ID2 0x21 -#define CHIP_ID2_VAL 0x16 +#define CHIP_ID_0 0x1602 +#define CHIP_ID_1 0x0501 #define VENDOR_ID1 0x23 #define VENDOR_ID1_VAL 0x19 #define VENDOR_ID2 0x24 #define VENDOR_ID2_VAL 0x34 +#define IO_ADDR1 0x61 +#define IO_ADDR2 0x60 #define LDN 0x7 +#define FINTEK_IRQ_MODE 0x70 +#define IRQ_SHARE BIT(4) +#define IRQ_MODE_MASK (BIT(6) | BIT(5)) +#define IRQ_LEVEL_LOW 0 +#define IRQ_EDGE_HIGH BIT(5) + #define RS485 0xF0 #define RTS_INVERT BIT(5) #define RS485_URA BIT(4) #define RXW4C_IRA BIT(3) #define TXW4C_IRA BIT(2) -#define DRIVER_NAME "8250_fintek" - -static int fintek_8250_enter_key(void){ +struct fintek_8250 { + u16 base_port; + u8 index; + u8 key; +}; - if (!request_muxed_region(ADDR_PORT, 2, DRIVER_NAME)) +static int fintek_8250_enter_key(u16 base_port, u8 key) +{ + if (!request_muxed_region(base_port, 2, "8250_fintek")) return -EBUSY; - outb(ENTRY_KEY, ADDR_PORT); - outb(ENTRY_KEY, ADDR_PORT); + outb(key, base_port + ADDR_PORT); + outb(key, base_port + ADDR_PORT); return 0; } -static void fintek_8250_exit_key(void){ - - outb(EXIT_KEY, ADDR_PORT); - release_region(ADDR_PORT, 2); -} - -static int fintek_8250_get_index(resource_size_t base_addr) +static void fintek_8250_exit_key(u16 base_port) { - resource_size_t base[] = {0x3f8, 0x2f8, 0x3e8, 0x2e8}; - int i; - - for (i = 0; i < ARRAY_SIZE(base); i++) - if (base_addr == base[i]) - return i; - return -ENODEV; + outb(EXIT_KEY, base_port + ADDR_PORT); + release_region(base_port + ADDR_PORT, 2); } -static int fintek_8250_check_id(void) +static int fintek_8250_check_id(u16 base_port) { + u16 chip; - outb(CHIP_ID1, ADDR_PORT); - if (inb(DATA_PORT) != CHIP_ID1_VAL) + outb(VENDOR_ID1, base_port + ADDR_PORT); + if (inb(base_port + DATA_PORT) != VENDOR_ID1_VAL) return -ENODEV; - outb(CHIP_ID2, ADDR_PORT); - if (inb(DATA_PORT) != CHIP_ID2_VAL) + outb(VENDOR_ID2, base_port + ADDR_PORT); + if (inb(base_port + DATA_PORT) != VENDOR_ID2_VAL) return -ENODEV; - outb(VENDOR_ID1, ADDR_PORT); - if (inb(DATA_PORT) != VENDOR_ID1_VAL) - return -ENODEV; + outb(CHIP_ID1, base_port + ADDR_PORT); + chip = inb(base_port + DATA_PORT); + outb(CHIP_ID2, base_port + ADDR_PORT); + chip |= inb(base_port + DATA_PORT) << 8; - outb(VENDOR_ID2, ADDR_PORT); - if (inb(DATA_PORT) != VENDOR_ID2_VAL) + if (chip != CHIP_ID_0 && chip != CHIP_ID_1) return -ENODEV; return 0; @@ -93,9 +93,9 @@ static int fintek_8250_rs485_config(struct uart_port *port, struct serial_rs485 *rs485) { uint8_t config = 0; - int index = fintek_8250_get_index(port->iobase); + struct fintek_8250 *pdata = port->private_data; - if (index < 0) + if (!pdata) return -EINVAL; if (rs485->flags & SER_RS485_ENABLED) @@ -125,116 +125,106 @@ static int fintek_8250_rs485_config(struct uart_port *port, if (rs485->flags & SER_RS485_RTS_ON_SEND) config |= RTS_INVERT; - if (fintek_8250_enter_key()) + if (fintek_8250_enter_key(pdata->base_port, pdata->key)) return -EBUSY; - outb(LDN, ADDR_PORT); - outb(index, DATA_PORT); - outb(RS485, ADDR_PORT); - outb(config, DATA_PORT); - fintek_8250_exit_key(); + outb(LDN, pdata->base_port + ADDR_PORT); + outb(pdata->index, pdata->base_port + DATA_PORT); + outb(RS485, pdata->base_port + ADDR_PORT); + outb(config, pdata->base_port + DATA_PORT); + fintek_8250_exit_key(pdata->base_port); port->rs485 = *rs485; return 0; } -static int -fintek_8250_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) +static int find_base_port(struct fintek_8250 *pdata, u16 io_address) { - int line; - struct uart_8250_port uart; - int ret; - - if (!pnp_port_valid(dev, 0)) - return -ENODEV; - - if (fintek_8250_get_index(pnp_port_start(dev, 0)) < 0) - return -ENODEV; - - /* Enable configuration registers*/ - if (fintek_8250_enter_key()) - return -EBUSY; - - /*Check ID*/ - ret = fintek_8250_check_id(); - fintek_8250_exit_key(); - if (ret) - return ret; - - memset(&uart, 0, sizeof(uart)); - if (!pnp_irq_valid(dev, 0)) - return -ENODEV; - uart.port.irq = pnp_irq(dev, 0); - uart.port.iobase = pnp_port_start(dev, 0); - uart.port.iotype = UPIO_PORT; - uart.port.rs485_config = fintek_8250_rs485_config; - - uart.port.flags |= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF; - if (pnp_irq_flags(dev, 0) & IORESOURCE_IRQ_SHAREABLE) - uart.port.flags |= UPF_SHARE_IRQ; - uart.port.uartclk = 1843200; - uart.port.dev = &dev->dev; - - line = serial8250_register_8250_port(&uart); - if (line < 0) - return -ENODEV; + static const u16 addr[] = {0x4e, 0x2e}; + static const u8 keys[] = {0x77, 0xa0, 0x87, 0x67}; + int i, j, k; + + for (i = 0; i < ARRAY_SIZE(addr); i++) { + for (j = 0; j < ARRAY_SIZE(keys); j++) { + + if (fintek_8250_enter_key(addr[i], keys[j])) + continue; + if (fintek_8250_check_id(addr[i])) { + fintek_8250_exit_key(addr[i]); + continue; + } + + for (k = 0; k < 4; k++) { + u16 aux; + + outb(LDN, addr[i] + ADDR_PORT); + outb(k, addr[i] + DATA_PORT); + + outb(IO_ADDR1, addr[i] + ADDR_PORT); + aux = inb(addr[i] + DATA_PORT); + outb(IO_ADDR2, addr[i] + ADDR_PORT); + aux |= inb(addr[i] + DATA_PORT) << 8; + if (aux != io_address) + continue; + + fintek_8250_exit_key(addr[i]); + pdata->key = keys[j]; + pdata->base_port = addr[i]; + pdata->index = k; + + return 0; + } + + fintek_8250_exit_key(addr[i]); + } + } - pnp_set_drvdata(dev, (void *)((long)line + 1)); - return 0; + return -ENODEV; } -static void fintek_8250_remove(struct pnp_dev *dev) +static int fintek_8250_set_irq_mode(struct fintek_8250 *pdata, bool level_mode) { - long line = (long)pnp_get_drvdata(dev); + int status; + u8 tmp; - if (line) - serial8250_unregister_port(line - 1); -} + status = fintek_8250_enter_key(pdata->base_port, pdata->key); + if (status) + return status; -#ifdef CONFIG_PM -static int fintek_8250_suspend(struct pnp_dev *dev, pm_message_t state) -{ - long line = (long)pnp_get_drvdata(dev); + outb(LDN, pdata->base_port + ADDR_PORT); + outb(pdata->index, pdata->base_port + DATA_PORT); - if (!line) - return -ENODEV; - serial8250_suspend_port(line - 1); + outb(FINTEK_IRQ_MODE, pdata->base_port + ADDR_PORT); + tmp = inb(pdata->base_port + DATA_PORT); + + tmp &= ~IRQ_MODE_MASK; + tmp |= IRQ_SHARE; + if (!level_mode) + tmp |= IRQ_EDGE_HIGH; + + outb(tmp, pdata->base_port + DATA_PORT); + fintek_8250_exit_key(pdata->base_port); return 0; } -static int fintek_8250_resume(struct pnp_dev *dev) +int fintek_8250_probe(struct uart_8250_port *uart) { - long line = (long)pnp_get_drvdata(dev); + struct fintek_8250 *pdata; + struct fintek_8250 probe_data; + struct irq_data *irq_data = irq_get_irq_data(uart->port.irq); + bool level_mode = irqd_is_level_type(irq_data); - if (!line) + if (find_base_port(&probe_data, uart->port.iobase)) return -ENODEV; - serial8250_resume_port(line - 1); - return 0; -} -#else -#define fintek_8250_suspend NULL -#define fintek_8250_resume NULL -#endif /* CONFIG_PM */ - -static const struct pnp_device_id fintek_dev_table[] = { - /* Qtechnology Panel PC / IO1000 */ - { "PNP0501"}, - {} -}; -MODULE_DEVICE_TABLE(pnp, fintek_dev_table); + pdata = devm_kzalloc(uart->port.dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; -static struct pnp_driver fintek_8250_driver = { - .name = DRIVER_NAME, - .probe = fintek_8250_probe, - .remove = fintek_8250_remove, - .suspend = fintek_8250_suspend, - .resume = fintek_8250_resume, - .id_table = fintek_dev_table, -}; + memcpy(pdata, &probe_data, sizeof(probe_data)); + uart->port.rs485_config = fintek_8250_rs485_config; + uart->port.private_data = pdata; -module_pnp_driver(fintek_8250_driver); -MODULE_DESCRIPTION("Fintek F812164 module"); -MODULE_AUTHOR("Ricardo Ribalda <ricardo.ribalda@gmail.com>"); -MODULE_LICENSE("GPL"); + return fintek_8250_set_irq_mode(pdata, level_mode); +} diff --git a/drivers/tty/serial/8250/8250_fourport.c b/drivers/tty/serial/8250/8250_fourport.c index be1582609..4045180a8 100644 --- a/drivers/tty/serial/8250/8250_fourport.c +++ b/drivers/tty/serial/8250/8250_fourport.c @@ -10,24 +10,20 @@ #include <linux/init.h> #include <linux/serial_8250.h> -#define PORT(_base,_irq) \ - { \ - .iobase = _base, \ - .irq = _irq, \ - .uartclk = 1843200, \ - .iotype = UPIO_PORT, \ - .flags = UPF_BOOT_AUTOCONF | UPF_FOURPORT, \ - } +#include "8250.h" + +#define SERIAL8250_FOURPORT(_base, _irq) \ + SERIAL8250_PORT_FLAGS(_base, _irq, UPF_FOURPORT) static struct plat_serial8250_port fourport_data[] = { - PORT(0x1a0, 9), - PORT(0x1a8, 9), - PORT(0x1b0, 9), - PORT(0x1b8, 9), - PORT(0x2a0, 5), - PORT(0x2a8, 5), - PORT(0x2b0, 5), - PORT(0x2b8, 5), + SERIAL8250_FOURPORT(0x1a0, 9), + SERIAL8250_FOURPORT(0x1a8, 9), + SERIAL8250_FOURPORT(0x1b0, 9), + SERIAL8250_FOURPORT(0x1b8, 9), + SERIAL8250_FOURPORT(0x2a0, 5), + SERIAL8250_FOURPORT(0x2a8, 5), + SERIAL8250_FOURPORT(0x2b0, 5), + SERIAL8250_FOURPORT(0x2b8, 5), { }, }; diff --git a/drivers/tty/serial/8250/8250_fsl.c b/drivers/tty/serial/8250/8250_fsl.c index c0533a57e..910bfee5a 100644 --- a/drivers/tty/serial/8250/8250_fsl.c +++ b/drivers/tty/serial/8250/8250_fsl.c @@ -60,3 +60,4 @@ int fsl8250_handle_irq(struct uart_port *port) spin_unlock_irqrestore(&up->port.lock, flags); return 1; } +EXPORT_SYMBOL_GPL(fsl8250_handle_irq); diff --git a/drivers/tty/serial/8250/8250_gsc.c b/drivers/tty/serial/8250/8250_gsc.c index 2e3ea1a70..b1e6ae9f1 100644 --- a/drivers/tty/serial/8250/8250_gsc.c +++ b/drivers/tty/serial/8250/8250_gsc.c @@ -42,7 +42,7 @@ static int __init serial_init_chip(struct parisc_device *dev) * the user what they're missing. */ if (parisc_parent(dev)->id.hw_type != HPHW_IOA) - printk(KERN_INFO + dev_info(&dev->dev, "Serial: device 0x%llx not configured.\n" "Enable support for Wax, Lasi, Asp or Dino.\n", (unsigned long long)dev->hpa.start); @@ -66,8 +66,9 @@ static int __init serial_init_chip(struct parisc_device *dev) err = serial8250_register_8250_port(&uart); if (err < 0) { - printk(KERN_WARNING - "serial8250_register_8250_port returned error %d\n", err); + dev_warn(&dev->dev, + "serial8250_register_8250_port returned error %d\n", + err); iounmap(uart.port.membase); return err; } diff --git a/drivers/tty/serial/8250/8250_hp300.c b/drivers/tty/serial/8250/8250_hp300.c index 2891958cd..38166db2b 100644 --- a/drivers/tty/serial/8250/8250_hp300.c +++ b/drivers/tty/serial/8250/8250_hp300.c @@ -24,8 +24,7 @@ #endif #ifdef CONFIG_HPAPCI -struct hp300_port -{ +struct hp300_port { struct hp300_port *next; /* next port */ int line; /* line (tty) number */ }; @@ -111,7 +110,7 @@ int __init hp300_setup_serial_console(void) /* Check for APCI console */ if (scode == 256) { #ifdef CONFIG_HPAPCI - printk(KERN_INFO "Serial console is HP APCI 1\n"); + pr_info("Serial console is HP APCI 1\n"); port.uartclk = HPAPCI_BAUD_BASE * 16; port.mapbase = (FRODO_BASE + FRODO_APCI_OFFSET(1)); @@ -119,7 +118,7 @@ int __init hp300_setup_serial_console(void) port.regshift = 2; add_preferred_console("ttyS", port.line, "9600n8"); #else - printk(KERN_WARNING "Serial console is APCI but support is disabled (CONFIG_HPAPCI)!\n"); + pr_warn("Serial console is APCI but support is disabled (CONFIG_HPAPCI)!\n"); return 0; #endif } else { @@ -128,7 +127,7 @@ int __init hp300_setup_serial_console(void) if (!pa) return 0; - printk(KERN_INFO "Serial console is HP DCA at select code %d\n", scode); + pr_info("Serial console is HP DCA at select code %d\n", scode); port.uartclk = HPDCA_BAUD_BASE * 16; port.mapbase = (pa + UART_OFFSET); @@ -142,13 +141,13 @@ int __init hp300_setup_serial_console(void) if (DIO_ID(pa + DIO_VIRADDRBASE) & 0x80) add_preferred_console("ttyS", port.line, "9600n8"); #else - printk(KERN_WARNING "Serial console is DCA but support is disabled (CONFIG_HPDCA)!\n"); + pr_warn("Serial console is DCA but support is disabled (CONFIG_HPDCA)!\n"); return 0; #endif } if (early_serial_setup(&port) < 0) - printk(KERN_WARNING "hp300_setup_serial_console(): early_serial_setup() failed.\n"); + pr_warn("%s: early_serial_setup() failed.\n", __func__); return 0; } #endif /* CONFIG_SERIAL_8250_CONSOLE */ @@ -180,8 +179,9 @@ static int hpdca_init_one(struct dio_dev *d, line = serial8250_register_8250_port(&uart); if (line < 0) { - printk(KERN_NOTICE "8250_hp300: register_serial() DCA scode %d" - " irq %d failed\n", d->scode, uart.port.irq); + dev_notice(&d->dev, + "8250_hp300: register_serial() DCA scode %d irq %d failed\n", + d->scode, uart.port.irq); return -ENOMEM; } @@ -249,8 +249,8 @@ static int __init hp300_8250_init(void) /* Memory mapped I/O */ uart.port.iotype = UPIO_MEM; - uart.port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ \ - | UPF_BOOT_AUTOCONF; + uart.port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ + | UPF_BOOT_AUTOCONF; /* XXX - no interrupt support yet */ uart.port.irq = 0; uart.port.uartclk = HPAPCI_BAUD_BASE * 16; @@ -261,8 +261,9 @@ static int __init hp300_8250_init(void) line = serial8250_register_8250_port(&uart); if (line < 0) { - printk(KERN_NOTICE "8250_hp300: register_serial() APCI" - " %d irq %d failed\n", i, uart.port.irq); + dev_notice(uart.port.dev, + "8250_hp300: register_serial() APCI %d irq %d failed\n", + i, uart.port.irq); kfree(port); continue; } diff --git a/drivers/tty/serial/8250/8250_hub6.c b/drivers/tty/serial/8250/8250_hub6.c index a5c778e83..27124e21e 100644 --- a/drivers/tty/serial/8250/8250_hub6.c +++ b/drivers/tty/serial/8250/8250_hub6.c @@ -10,7 +10,7 @@ #include <linux/init.h> #include <linux/serial_8250.h> -#define HUB6(card,port) \ +#define HUB6(card, port) \ { \ .iobase = 0x302, \ .irq = 3, \ diff --git a/drivers/tty/serial/8250/8250_ingenic.c b/drivers/tty/serial/8250/8250_ingenic.c new file mode 100644 index 000000000..4d9dc10e2 --- /dev/null +++ b/drivers/tty/serial/8250/8250_ingenic.c @@ -0,0 +1,349 @@ +/* + * Copyright (C) 2010 Lars-Peter Clausen <lars@metafoo.de> + * Copyright (C) 2015 Imagination Technologies + * + * Ingenic SoC UART support + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/clk.h> +#include <linux/console.h> +#include <linux/io.h> +#include <linux/libfdt.h> +#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> +#include <linux/serial_reg.h> + +#include "8250.h" + +/** ingenic_uart_config: SOC specific config data. */ +struct ingenic_uart_config { + int tx_loadsz; + int fifosize; +}; + +struct ingenic_uart_data { + struct clk *clk_module; + struct clk *clk_baud; + int line; +}; + +static const struct of_device_id of_match[]; + +#define UART_FCR_UME BIT(4) + +#define UART_MCR_MDCE BIT(7) +#define UART_MCR_FCM BIT(6) + +static struct earlycon_device *early_device; + +static uint8_t __init early_in(struct uart_port *port, int offset) +{ + return readl(port->membase + (offset << 2)); +} + +static void __init early_out(struct uart_port *port, int offset, uint8_t value) +{ + writel(value, port->membase + (offset << 2)); +} + +static void __init ingenic_early_console_putc(struct uart_port *port, int c) +{ + uint8_t lsr; + + do { + lsr = early_in(port, UART_LSR); + } while ((lsr & UART_LSR_TEMT) == 0); + + early_out(port, UART_TX, c); +} + +static void __init ingenic_early_console_write(struct console *console, + const char *s, unsigned int count) +{ + uart_console_write(&early_device->port, s, count, + ingenic_early_console_putc); +} + +static void __init ingenic_early_console_setup_clock(struct earlycon_device *dev) +{ + void *fdt = initial_boot_params; + const __be32 *prop; + int offset; + + offset = fdt_path_offset(fdt, "/ext"); + if (offset < 0) + return; + + prop = fdt_getprop(fdt, offset, "clock-frequency", NULL); + if (!prop) + return; + + dev->port.uartclk = be32_to_cpup(prop); +} + +static int __init ingenic_early_console_setup(struct earlycon_device *dev, + const char *opt) +{ + struct uart_port *port = &dev->port; + unsigned int baud, divisor; + + if (!dev->port.membase) + return -ENODEV; + + ingenic_early_console_setup_clock(dev); + + baud = dev->baud ?: 115200; + divisor = DIV_ROUND_CLOSEST(port->uartclk, 16 * baud); + + early_out(port, UART_IER, 0); + early_out(port, UART_LCR, UART_LCR_DLAB | UART_LCR_WLEN8); + early_out(port, UART_DLL, 0); + early_out(port, UART_DLM, 0); + early_out(port, UART_LCR, UART_LCR_WLEN8); + early_out(port, UART_FCR, UART_FCR_UME | UART_FCR_CLEAR_XMIT | + UART_FCR_CLEAR_RCVR | UART_FCR_ENABLE_FIFO); + early_out(port, UART_MCR, UART_MCR_RTS | UART_MCR_DTR); + + early_out(port, UART_LCR, UART_LCR_DLAB | UART_LCR_WLEN8); + early_out(port, UART_DLL, divisor & 0xff); + early_out(port, UART_DLM, (divisor >> 8) & 0xff); + early_out(port, UART_LCR, UART_LCR_WLEN8); + + early_device = dev; + dev->con->write = ingenic_early_console_write; + + return 0; +} + +EARLYCON_DECLARE(jz4740_uart, ingenic_early_console_setup); +OF_EARLYCON_DECLARE(jz4740_uart, "ingenic,jz4740-uart", + ingenic_early_console_setup); + +EARLYCON_DECLARE(jz4775_uart, ingenic_early_console_setup); +OF_EARLYCON_DECLARE(jz4775_uart, "ingenic,jz4775-uart", + ingenic_early_console_setup); + +EARLYCON_DECLARE(jz4780_uart, ingenic_early_console_setup); +OF_EARLYCON_DECLARE(jz4780_uart, "ingenic,jz4780-uart", + ingenic_early_console_setup); + +static void ingenic_uart_serial_out(struct uart_port *p, int offset, int value) +{ + int ier; + + switch (offset) { + case UART_FCR: + /* UART module enable */ + value |= UART_FCR_UME; + break; + + case UART_IER: + /* + * Enable receive timeout interrupt with the receive line + * status interrupt. + */ + value |= (value & 0x4) << 2; + break; + + case UART_MCR: + /* + * If we have enabled modem status IRQs we should enable + * modem mode. + */ + ier = p->serial_in(p, UART_IER); + + if (ier & UART_IER_MSI) + value |= UART_MCR_MDCE | UART_MCR_FCM; + else + value &= ~(UART_MCR_MDCE | UART_MCR_FCM); + break; + + default: + break; + } + + writeb(value, p->membase + (offset << p->regshift)); +} + +static unsigned int ingenic_uart_serial_in(struct uart_port *p, int offset) +{ + unsigned int value; + + value = readb(p->membase + (offset << p->regshift)); + + /* Hide non-16550 compliant bits from higher levels */ + switch (offset) { + case UART_FCR: + value &= ~UART_FCR_UME; + break; + + case UART_MCR: + value &= ~(UART_MCR_MDCE | UART_MCR_FCM); + break; + + default: + break; + } + return value; +} + +static int ingenic_uart_probe(struct platform_device *pdev) +{ + struct uart_8250_port uart = {}; + struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); + struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + struct ingenic_uart_data *data; + const struct ingenic_uart_config *cdata; + const struct of_device_id *match; + int err, line; + + match = of_match_device(of_match, &pdev->dev); + if (!match) { + dev_err(&pdev->dev, "Error: No device match found\n"); + return -ENODEV; + } + cdata = match->data; + + if (!regs || !irq) { + dev_err(&pdev->dev, "no registers/irq defined\n"); + return -EINVAL; + } + + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + spin_lock_init(&uart.port.lock); + uart.port.type = PORT_16550A; + uart.port.flags = UPF_SKIP_TEST | UPF_IOREMAP | UPF_FIXED_TYPE; + uart.port.iotype = UPIO_MEM; + uart.port.mapbase = regs->start; + uart.port.regshift = 2; + uart.port.serial_out = ingenic_uart_serial_out; + uart.port.serial_in = ingenic_uart_serial_in; + uart.port.irq = irq->start; + uart.port.dev = &pdev->dev; + uart.port.fifosize = cdata->fifosize; + uart.tx_loadsz = cdata->tx_loadsz; + uart.capabilities = UART_CAP_FIFO | UART_CAP_RTOIE; + + /* Check for a fixed line number */ + line = of_alias_get_id(pdev->dev.of_node, "serial"); + if (line >= 0) + uart.port.line = line; + + uart.port.membase = devm_ioremap(&pdev->dev, regs->start, + resource_size(regs)); + if (!uart.port.membase) + return -ENOMEM; + + data->clk_module = devm_clk_get(&pdev->dev, "module"); + if (IS_ERR(data->clk_module)) { + err = PTR_ERR(data->clk_module); + if (err != -EPROBE_DEFER) + dev_err(&pdev->dev, + "unable to get module clock: %d\n", err); + return err; + } + + data->clk_baud = devm_clk_get(&pdev->dev, "baud"); + if (IS_ERR(data->clk_baud)) { + err = PTR_ERR(data->clk_baud); + if (err != -EPROBE_DEFER) + dev_err(&pdev->dev, + "unable to get baud clock: %d\n", err); + return err; + } + + err = clk_prepare_enable(data->clk_module); + if (err) { + dev_err(&pdev->dev, "could not enable module clock: %d\n", err); + goto out; + } + + err = clk_prepare_enable(data->clk_baud); + if (err) { + dev_err(&pdev->dev, "could not enable baud clock: %d\n", err); + goto out_disable_moduleclk; + } + uart.port.uartclk = clk_get_rate(data->clk_baud); + + data->line = serial8250_register_8250_port(&uart); + if (data->line < 0) { + err = data->line; + goto out_disable_baudclk; + } + + platform_set_drvdata(pdev, data); + return 0; + +out_disable_baudclk: + clk_disable_unprepare(data->clk_baud); +out_disable_moduleclk: + clk_disable_unprepare(data->clk_module); +out: + return err; +} + +static int ingenic_uart_remove(struct platform_device *pdev) +{ + struct ingenic_uart_data *data = platform_get_drvdata(pdev); + + serial8250_unregister_port(data->line); + clk_disable_unprepare(data->clk_module); + clk_disable_unprepare(data->clk_baud); + return 0; +} + +static const struct ingenic_uart_config jz4740_uart_config = { + .tx_loadsz = 8, + .fifosize = 16, +}; + +static const struct ingenic_uart_config jz4760_uart_config = { + .tx_loadsz = 16, + .fifosize = 32, +}; + +static const struct ingenic_uart_config jz4780_uart_config = { + .tx_loadsz = 32, + .fifosize = 64, +}; + +static const struct of_device_id of_match[] = { + { .compatible = "ingenic,jz4740-uart", .data = &jz4740_uart_config }, + { .compatible = "ingenic,jz4760-uart", .data = &jz4760_uart_config }, + { .compatible = "ingenic,jz4775-uart", .data = &jz4760_uart_config }, + { .compatible = "ingenic,jz4780-uart", .data = &jz4780_uart_config }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, of_match); + +static struct platform_driver ingenic_uart_platform_driver = { + .driver = { + .name = "ingenic-uart", + .of_match_table = of_match, + }, + .probe = ingenic_uart_probe, + .remove = ingenic_uart_remove, +}; + +module_platform_driver(ingenic_uart_platform_driver); + +MODULE_AUTHOR("Paul Burton"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Ingenic SoC UART driver"); diff --git a/drivers/tty/serial/8250/8250_lpc18xx.c b/drivers/tty/serial/8250/8250_lpc18xx.c new file mode 100644 index 000000000..99cd47885 --- /dev/null +++ b/drivers/tty/serial/8250/8250_lpc18xx.c @@ -0,0 +1,230 @@ +/* + * Serial port driver for NXP LPC18xx/43xx UART + * + * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com> + * + * Based on 8250_mtk.c: + * Copyright (c) 2014 MundoReader S.L. + * Matthias Brugger <matthias.bgg@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include <linux/clk.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> + +#include "8250.h" + +/* Additional LPC18xx/43xx 8250 registers and bits */ +#define LPC18XX_UART_RS485CTRL (0x04c / sizeof(u32)) +#define LPC18XX_UART_RS485CTRL_NMMEN BIT(0) +#define LPC18XX_UART_RS485CTRL_DCTRL BIT(4) +#define LPC18XX_UART_RS485CTRL_OINV BIT(5) +#define LPC18XX_UART_RS485DLY (0x054 / sizeof(u32)) +#define LPC18XX_UART_RS485DLY_MAX 255 + +struct lpc18xx_uart_data { + struct uart_8250_dma dma; + struct clk *clk_uart; + struct clk *clk_reg; + int line; +}; + +static int lpc18xx_rs485_config(struct uart_port *port, + struct serial_rs485 *rs485) +{ + struct uart_8250_port *up = up_to_u8250p(port); + u32 rs485_ctrl_reg = 0; + u32 rs485_dly_reg = 0; + unsigned baud_clk; + + if (rs485->flags & SER_RS485_ENABLED) + memset(rs485->padding, 0, sizeof(rs485->padding)); + else + memset(rs485, 0, sizeof(*rs485)); + + rs485->flags &= SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND | + SER_RS485_RTS_AFTER_SEND; + + if (rs485->flags & SER_RS485_ENABLED) { + rs485_ctrl_reg |= LPC18XX_UART_RS485CTRL_NMMEN | + LPC18XX_UART_RS485CTRL_DCTRL; + + if (rs485->flags & SER_RS485_RTS_ON_SEND) { + rs485_ctrl_reg |= LPC18XX_UART_RS485CTRL_OINV; + rs485->flags &= ~SER_RS485_RTS_AFTER_SEND; + } else { + rs485->flags |= SER_RS485_RTS_AFTER_SEND; + } + } + + if (rs485->delay_rts_after_send) { + baud_clk = port->uartclk / up->dl_read(up); + rs485_dly_reg = DIV_ROUND_UP(rs485->delay_rts_after_send + * baud_clk, MSEC_PER_SEC); + + if (rs485_dly_reg > LPC18XX_UART_RS485DLY_MAX) + rs485_dly_reg = LPC18XX_UART_RS485DLY_MAX; + + /* Calculate the resulting delay in ms */ + rs485->delay_rts_after_send = (rs485_dly_reg * MSEC_PER_SEC) + / baud_clk; + } + + /* Delay RTS before send not supported */ + rs485->delay_rts_before_send = 0; + + serial_out(up, LPC18XX_UART_RS485CTRL, rs485_ctrl_reg); + serial_out(up, LPC18XX_UART_RS485DLY, rs485_dly_reg); + + port->rs485 = *rs485; + + return 0; +} + +static void lpc18xx_uart_serial_out(struct uart_port *p, int offset, int value) +{ + /* + * For DMA mode one must ensure that the UART_FCR_DMA_SELECT + * bit is set when FIFO is enabled. Even if DMA is not used + * setting this bit doesn't seem to affect anything. + */ + if (offset == UART_FCR && (value & UART_FCR_ENABLE_FIFO)) + value |= UART_FCR_DMA_SELECT; + + offset = offset << p->regshift; + writel(value, p->membase + offset); +} + +static int lpc18xx_serial_probe(struct platform_device *pdev) +{ + struct lpc18xx_uart_data *data; + struct uart_8250_port uart; + struct resource *res; + int irq, ret; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "irq not found"); + return irq; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "memory resource not found"); + return -EINVAL; + } + + memset(&uart, 0, sizeof(uart)); + + uart.port.membase = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (!uart.port.membase) + return -ENOMEM; + + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->clk_uart = devm_clk_get(&pdev->dev, "uartclk"); + if (IS_ERR(data->clk_uart)) { + dev_err(&pdev->dev, "uart clock not found\n"); + return PTR_ERR(data->clk_uart); + } + + data->clk_reg = devm_clk_get(&pdev->dev, "reg"); + if (IS_ERR(data->clk_reg)) { + dev_err(&pdev->dev, "reg clock not found\n"); + return PTR_ERR(data->clk_reg); + } + + ret = clk_prepare_enable(data->clk_reg); + if (ret) { + dev_err(&pdev->dev, "unable to enable reg clock\n"); + return ret; + } + + ret = clk_prepare_enable(data->clk_uart); + if (ret) { + dev_err(&pdev->dev, "unable to enable uart clock\n"); + goto dis_clk_reg; + } + + ret = of_alias_get_id(pdev->dev.of_node, "serial"); + if (ret >= 0) + uart.port.line = ret; + + data->dma.rx_param = data; + data->dma.tx_param = data; + + spin_lock_init(&uart.port.lock); + uart.port.dev = &pdev->dev; + uart.port.irq = irq; + uart.port.iotype = UPIO_MEM32; + uart.port.mapbase = res->start; + uart.port.regshift = 2; + uart.port.type = PORT_16550A; + uart.port.flags = UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_SKIP_TEST; + uart.port.uartclk = clk_get_rate(data->clk_uart); + uart.port.private_data = data; + uart.port.rs485_config = lpc18xx_rs485_config; + uart.port.serial_out = lpc18xx_uart_serial_out; + + uart.dma = &data->dma; + uart.dma->rxconf.src_maxburst = 1; + uart.dma->txconf.dst_maxburst = 1; + + ret = serial8250_register_8250_port(&uart); + if (ret < 0) { + dev_err(&pdev->dev, "unable to register 8250 port\n"); + goto dis_uart_clk; + } + + data->line = ret; + platform_set_drvdata(pdev, data); + + return 0; + +dis_uart_clk: + clk_disable_unprepare(data->clk_uart); +dis_clk_reg: + clk_disable_unprepare(data->clk_reg); + return ret; +} + +static int lpc18xx_serial_remove(struct platform_device *pdev) +{ + struct lpc18xx_uart_data *data = platform_get_drvdata(pdev); + + serial8250_unregister_port(data->line); + clk_disable_unprepare(data->clk_uart); + clk_disable_unprepare(data->clk_reg); + + return 0; +} + +static const struct of_device_id lpc18xx_serial_match[] = { + { .compatible = "nxp,lpc1850-uart" }, + { }, +}; +MODULE_DEVICE_TABLE(of, lpc18xx_serial_match); + +static struct platform_driver lpc18xx_serial_driver = { + .probe = lpc18xx_serial_probe, + .remove = lpc18xx_serial_remove, + .driver = { + .name = "lpc18xx-uart", + .of_match_table = lpc18xx_serial_match, + }, +}; +module_platform_driver(lpc18xx_serial_driver); + +MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>"); +MODULE_DESCRIPTION("Serial port driver NXP LPC18xx/43xx devices"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/tty/serial/8250/8250_mid.c b/drivers/tty/serial/8250/8250_mid.c new file mode 100644 index 000000000..20c5db2f4 --- /dev/null +++ b/drivers/tty/serial/8250/8250_mid.c @@ -0,0 +1,357 @@ +/* + * 8250_mid.c - Driver for UART on Intel Penwell and various other Intel SOCs + * + * Copyright (C) 2015 Intel Corporation + * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/bitops.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/rational.h> + +#include <linux/dma/hsu.h> +#include <linux/8250_pci.h> + +#include "8250.h" + +#define PCI_DEVICE_ID_INTEL_PNW_UART1 0x081b +#define PCI_DEVICE_ID_INTEL_PNW_UART2 0x081c +#define PCI_DEVICE_ID_INTEL_PNW_UART3 0x081d +#define PCI_DEVICE_ID_INTEL_TNG_UART 0x1191 +#define PCI_DEVICE_ID_INTEL_DNV_UART 0x19d8 + +/* Intel MID Specific registers */ +#define INTEL_MID_UART_DNV_FISR 0x08 +#define INTEL_MID_UART_PS 0x30 +#define INTEL_MID_UART_MUL 0x34 +#define INTEL_MID_UART_DIV 0x38 + +struct mid8250; + +struct mid8250_board { + unsigned int flags; + unsigned long freq; + unsigned int base_baud; + int (*setup)(struct mid8250 *, struct uart_port *p); + void (*exit)(struct mid8250 *); +}; + +struct mid8250 { + int line; + int dma_index; + struct pci_dev *dma_dev; + struct uart_8250_dma dma; + struct mid8250_board *board; + struct hsu_dma_chip dma_chip; +}; + +/*****************************************************************************/ + +static int pnw_setup(struct mid8250 *mid, struct uart_port *p) +{ + struct pci_dev *pdev = to_pci_dev(p->dev); + + switch (pdev->device) { + case PCI_DEVICE_ID_INTEL_PNW_UART1: + mid->dma_index = 0; + break; + case PCI_DEVICE_ID_INTEL_PNW_UART2: + mid->dma_index = 1; + break; + case PCI_DEVICE_ID_INTEL_PNW_UART3: + mid->dma_index = 2; + break; + default: + return -EINVAL; + } + + mid->dma_dev = pci_get_slot(pdev->bus, + PCI_DEVFN(PCI_SLOT(pdev->devfn), 3)); + return 0; +} + +static int tng_setup(struct mid8250 *mid, struct uart_port *p) +{ + struct pci_dev *pdev = to_pci_dev(p->dev); + int index = PCI_FUNC(pdev->devfn); + + /* + * Device 0000:00:04.0 is not a real HSU port. It provides a global + * register set for all HSU ports, although it has the same PCI ID. + * Skip it here. + */ + if (index-- == 0) + return -ENODEV; + + mid->dma_index = index; + mid->dma_dev = pci_get_slot(pdev->bus, PCI_DEVFN(5, 0)); + return 0; +} + +static int dnv_handle_irq(struct uart_port *p) +{ + struct mid8250 *mid = p->private_data; + struct uart_8250_port *up = up_to_u8250p(p); + unsigned int fisr = serial_port_in(p, INTEL_MID_UART_DNV_FISR); + u32 status; + int ret = IRQ_NONE; + int err; + + if (fisr & BIT(2)) { + err = hsu_dma_get_status(&mid->dma_chip, 1, &status); + if (err > 0) { + serial8250_rx_dma_flush(up); + ret |= IRQ_HANDLED; + } else if (err == 0) + ret |= hsu_dma_do_irq(&mid->dma_chip, 1, status); + } + if (fisr & BIT(1)) { + err = hsu_dma_get_status(&mid->dma_chip, 0, &status); + if (err > 0) + ret |= IRQ_HANDLED; + else if (err == 0) + ret |= hsu_dma_do_irq(&mid->dma_chip, 0, status); + } + if (fisr & BIT(0)) + ret |= serial8250_handle_irq(p, serial_port_in(p, UART_IIR)); + return ret; +} + +#define DNV_DMA_CHAN_OFFSET 0x80 + +static int dnv_setup(struct mid8250 *mid, struct uart_port *p) +{ + struct hsu_dma_chip *chip = &mid->dma_chip; + struct pci_dev *pdev = to_pci_dev(p->dev); + unsigned int bar = FL_GET_BASE(mid->board->flags); + int ret; + + chip->dev = &pdev->dev; + chip->irq = pdev->irq; + chip->regs = p->membase; + chip->length = pci_resource_len(pdev, bar); + chip->offset = DNV_DMA_CHAN_OFFSET; + + /* Falling back to PIO mode if DMA probing fails */ + ret = hsu_dma_probe(chip); + if (ret) + return 0; + + mid->dma_dev = pdev; + + p->handle_irq = dnv_handle_irq; + return 0; +} + +static void dnv_exit(struct mid8250 *mid) +{ + if (!mid->dma_dev) + return; + hsu_dma_remove(&mid->dma_chip); +} + +/*****************************************************************************/ + +static void mid8250_set_termios(struct uart_port *p, + struct ktermios *termios, + struct ktermios *old) +{ + unsigned int baud = tty_termios_baud_rate(termios); + struct mid8250 *mid = p->private_data; + unsigned short ps = 16; + unsigned long fuart = baud * ps; + unsigned long w = BIT(24) - 1; + unsigned long mul, div; + + /* Gracefully handle the B0 case: fall back to B9600 */ + fuart = fuart ? fuart : 9600 * 16; + + if (mid->board->freq < fuart) { + /* Find prescaler value that satisfies Fuart < Fref */ + if (mid->board->freq > baud) + ps = mid->board->freq / baud; /* baud rate too high */ + else + ps = 1; /* PLL case */ + fuart = baud * ps; + } else { + /* Get Fuart closer to Fref */ + fuart *= rounddown_pow_of_two(mid->board->freq / fuart); + } + + rational_best_approximation(fuart, mid->board->freq, w, w, &mul, &div); + p->uartclk = fuart * 16 / ps; /* core uses ps = 16 always */ + + writel(ps, p->membase + INTEL_MID_UART_PS); /* set PS */ + writel(mul, p->membase + INTEL_MID_UART_MUL); /* set MUL */ + writel(div, p->membase + INTEL_MID_UART_DIV); + + serial8250_do_set_termios(p, termios, old); +} + +static bool mid8250_dma_filter(struct dma_chan *chan, void *param) +{ + struct hsu_dma_slave *s = param; + + if (s->dma_dev != chan->device->dev || s->chan_id != chan->chan_id) + return false; + + chan->private = s; + return true; +} + +static int mid8250_dma_setup(struct mid8250 *mid, struct uart_8250_port *port) +{ + struct uart_8250_dma *dma = &mid->dma; + struct device *dev = port->port.dev; + struct hsu_dma_slave *rx_param; + struct hsu_dma_slave *tx_param; + + if (!mid->dma_dev) + return 0; + + rx_param = devm_kzalloc(dev, sizeof(*rx_param), GFP_KERNEL); + if (!rx_param) + return -ENOMEM; + + tx_param = devm_kzalloc(dev, sizeof(*tx_param), GFP_KERNEL); + if (!tx_param) + return -ENOMEM; + + rx_param->chan_id = mid->dma_index * 2 + 1; + tx_param->chan_id = mid->dma_index * 2; + + dma->rxconf.src_maxburst = 64; + dma->txconf.dst_maxburst = 64; + + rx_param->dma_dev = &mid->dma_dev->dev; + tx_param->dma_dev = &mid->dma_dev->dev; + + dma->fn = mid8250_dma_filter; + dma->rx_param = rx_param; + dma->tx_param = tx_param; + + port->dma = dma; + return 0; +} + +static int mid8250_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + struct uart_8250_port uart; + struct mid8250 *mid; + unsigned int bar; + int ret; + + ret = pcim_enable_device(pdev); + if (ret) + return ret; + + pci_set_master(pdev); + + mid = devm_kzalloc(&pdev->dev, sizeof(*mid), GFP_KERNEL); + if (!mid) + return -ENOMEM; + + mid->board = (struct mid8250_board *)id->driver_data; + bar = FL_GET_BASE(mid->board->flags); + + memset(&uart, 0, sizeof(struct uart_8250_port)); + + uart.port.dev = &pdev->dev; + uart.port.irq = pdev->irq; + uart.port.private_data = mid; + uart.port.type = PORT_16750; + uart.port.iotype = UPIO_MEM; + uart.port.uartclk = mid->board->base_baud * 16; + uart.port.flags = UPF_SHARE_IRQ | UPF_FIXED_PORT | UPF_FIXED_TYPE; + uart.port.set_termios = mid8250_set_termios; + + uart.port.mapbase = pci_resource_start(pdev, bar); + uart.port.membase = pcim_iomap(pdev, bar, 0); + if (!uart.port.membase) + return -ENOMEM; + + if (mid->board->setup) { + ret = mid->board->setup(mid, &uart.port); + if (ret) + return ret; + } + + ret = mid8250_dma_setup(mid, &uart); + if (ret) + goto err; + + ret = serial8250_register_8250_port(&uart); + if (ret < 0) + goto err; + + mid->line = ret; + + pci_set_drvdata(pdev, mid); + return 0; +err: + if (mid->board->exit) + mid->board->exit(mid); + return ret; +} + +static void mid8250_remove(struct pci_dev *pdev) +{ + struct mid8250 *mid = pci_get_drvdata(pdev); + + if (mid->board->exit) + mid->board->exit(mid); + + serial8250_unregister_port(mid->line); +} + +static const struct mid8250_board pnw_board = { + .flags = FL_BASE0, + .freq = 50000000, + .base_baud = 115200, + .setup = pnw_setup, +}; + +static const struct mid8250_board tng_board = { + .flags = FL_BASE0, + .freq = 38400000, + .base_baud = 1843200, + .setup = tng_setup, +}; + +static const struct mid8250_board dnv_board = { + .flags = FL_BASE1, + .freq = 133333333, + .base_baud = 115200, + .setup = dnv_setup, + .exit = dnv_exit, +}; + +#define MID_DEVICE(id, board) { PCI_VDEVICE(INTEL, id), (kernel_ulong_t)&board } + +static const struct pci_device_id pci_ids[] = { + MID_DEVICE(PCI_DEVICE_ID_INTEL_PNW_UART1, pnw_board), + MID_DEVICE(PCI_DEVICE_ID_INTEL_PNW_UART2, pnw_board), + MID_DEVICE(PCI_DEVICE_ID_INTEL_PNW_UART3, pnw_board), + MID_DEVICE(PCI_DEVICE_ID_INTEL_TNG_UART, tng_board), + MID_DEVICE(PCI_DEVICE_ID_INTEL_DNV_UART, dnv_board), + { }, +}; +MODULE_DEVICE_TABLE(pci, pci_ids); + +static struct pci_driver mid8250_pci_driver = { + .name = "8250_mid", + .id_table = pci_ids, + .probe = mid8250_probe, + .remove = mid8250_remove, +}; + +module_pci_driver(mid8250_pci_driver); + +MODULE_AUTHOR("Intel Corporation"); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Intel MID UART driver"); diff --git a/drivers/tty/serial/8250/8250_moxa.c b/drivers/tty/serial/8250/8250_moxa.c new file mode 100644 index 000000000..26eb5393a --- /dev/null +++ b/drivers/tty/serial/8250/8250_moxa.c @@ -0,0 +1,157 @@ +/* + * 8250_moxa.c - MOXA Smartio/Industio MUE multiport serial driver. + * + * Author: Mathieu OTHACEHE <m.othacehe@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/module.h> +#include <linux/pci.h> + +#include "8250.h" + +#define PCI_DEVICE_ID_MOXA_CP102E 0x1024 +#define PCI_DEVICE_ID_MOXA_CP102EL 0x1025 +#define PCI_DEVICE_ID_MOXA_CP104EL_A 0x1045 +#define PCI_DEVICE_ID_MOXA_CP114EL 0x1144 +#define PCI_DEVICE_ID_MOXA_CP116E_A_A 0x1160 +#define PCI_DEVICE_ID_MOXA_CP116E_A_B 0x1161 +#define PCI_DEVICE_ID_MOXA_CP118EL_A 0x1182 +#define PCI_DEVICE_ID_MOXA_CP118E_A_I 0x1183 +#define PCI_DEVICE_ID_MOXA_CP132EL 0x1322 +#define PCI_DEVICE_ID_MOXA_CP134EL_A 0x1342 +#define PCI_DEVICE_ID_MOXA_CP138E_A 0x1381 +#define PCI_DEVICE_ID_MOXA_CP168EL_A 0x1683 + +#define MOXA_BASE_BAUD 921600 +#define MOXA_UART_OFFSET 0x200 +#define MOXA_BASE_BAR 1 + +struct moxa8250_board { + unsigned int num_ports; + int line[0]; +}; + +enum { + moxa8250_2p = 0, + moxa8250_4p, + moxa8250_8p +}; + +static struct moxa8250_board moxa8250_boards[] = { + [moxa8250_2p] = { .num_ports = 2}, + [moxa8250_4p] = { .num_ports = 4}, + [moxa8250_8p] = { .num_ports = 8}, +}; + +static int moxa8250_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + struct uart_8250_port uart; + struct moxa8250_board *brd; + void __iomem *ioaddr; + resource_size_t baseaddr; + unsigned int i, nr_ports; + unsigned int offset; + int ret; + + brd = &moxa8250_boards[id->driver_data]; + nr_ports = brd->num_ports; + + ret = pcim_enable_device(pdev); + if (ret) + return ret; + + brd = devm_kzalloc(&pdev->dev, sizeof(struct moxa8250_board) + + sizeof(unsigned int) * nr_ports, GFP_KERNEL); + if (!brd) + return -ENOMEM; + + memset(&uart, 0, sizeof(struct uart_8250_port)); + + uart.port.dev = &pdev->dev; + uart.port.irq = pdev->irq; + uart.port.uartclk = MOXA_BASE_BAUD * 16; + uart.port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ; + + baseaddr = pci_resource_start(pdev, MOXA_BASE_BAR); + ioaddr = pcim_iomap(pdev, MOXA_BASE_BAR, 0); + if (!ioaddr) + return -ENOMEM; + + for (i = 0; i < nr_ports; i++) { + + /* + * MOXA Smartio MUE boards with 4 ports have + * a different offset for port #3 + */ + if (nr_ports == 4 && i == 3) + offset = 7 * MOXA_UART_OFFSET; + else + offset = i * MOXA_UART_OFFSET; + + uart.port.iotype = UPIO_MEM; + uart.port.iobase = 0; + uart.port.mapbase = baseaddr + offset; + uart.port.membase = ioaddr + offset; + uart.port.regshift = 0; + + dev_dbg(&pdev->dev, "Setup PCI port: port %lx, irq %d, type %d\n", + uart.port.iobase, uart.port.irq, uart.port.iotype); + + brd->line[i] = serial8250_register_8250_port(&uart); + if (brd->line[i] < 0) { + dev_err(&pdev->dev, + "Couldn't register serial port %lx, irq %d, type %d, error %d\n", + uart.port.iobase, uart.port.irq, + uart.port.iotype, brd->line[i]); + break; + } + } + + pci_set_drvdata(pdev, brd); + return 0; +} + +static void moxa8250_remove(struct pci_dev *pdev) +{ + struct moxa8250_board *brd = pci_get_drvdata(pdev); + unsigned int i; + + for (i = 0; i < brd->num_ports; i++) + serial8250_unregister_port(brd->line[i]); +} + +#define MOXA_DEVICE(id, data) { PCI_VDEVICE(MOXA, id), (kernel_ulong_t)data } + +static const struct pci_device_id pci_ids[] = { + MOXA_DEVICE(PCI_DEVICE_ID_MOXA_CP102E, moxa8250_2p), + MOXA_DEVICE(PCI_DEVICE_ID_MOXA_CP102EL, moxa8250_2p), + MOXA_DEVICE(PCI_DEVICE_ID_MOXA_CP104EL_A, moxa8250_4p), + MOXA_DEVICE(PCI_DEVICE_ID_MOXA_CP114EL, moxa8250_4p), + MOXA_DEVICE(PCI_DEVICE_ID_MOXA_CP116E_A_A, moxa8250_8p), + MOXA_DEVICE(PCI_DEVICE_ID_MOXA_CP116E_A_B, moxa8250_8p), + MOXA_DEVICE(PCI_DEVICE_ID_MOXA_CP118EL_A, moxa8250_8p), + MOXA_DEVICE(PCI_DEVICE_ID_MOXA_CP118E_A_I, moxa8250_8p), + MOXA_DEVICE(PCI_DEVICE_ID_MOXA_CP132EL, moxa8250_2p), + MOXA_DEVICE(PCI_DEVICE_ID_MOXA_CP134EL_A, moxa8250_4p), + MOXA_DEVICE(PCI_DEVICE_ID_MOXA_CP138E_A, moxa8250_8p), + MOXA_DEVICE(PCI_DEVICE_ID_MOXA_CP168EL_A, moxa8250_8p), + {0} +}; +MODULE_DEVICE_TABLE(pci, pci_ids); + +static struct pci_driver moxa8250_pci_driver = { + .name = "8250_moxa", + .id_table = pci_ids, + .probe = moxa8250_probe, + .remove = moxa8250_remove, +}; + +module_pci_driver(moxa8250_pci_driver); + +MODULE_AUTHOR("Mathieu OTHACEHE"); +MODULE_DESCRIPTION("MOXA SmartIO MUE driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c index 7a11fac77..3611ec9bb 100644 --- a/drivers/tty/serial/8250/8250_mtk.c +++ b/drivers/tty/serial/8250/8250_mtk.c @@ -34,18 +34,17 @@ struct mtk8250_data { int line; struct clk *uart_clk; + struct clk *bus_clk; }; static void mtk8250_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { + struct uart_8250_port *up = up_to_u8250p(port); unsigned long flags; unsigned int baud, quot; - struct uart_8250_port *up = - container_of(port, struct uart_8250_port, port); - serial8250_do_set_termios(port, termios, old); /* @@ -115,6 +114,36 @@ mtk8250_set_termios(struct uart_port *port, struct ktermios *termios, tty_termios_encode_baud_rate(termios, baud, baud); } +static int __maybe_unused mtk8250_runtime_suspend(struct device *dev) +{ + struct mtk8250_data *data = dev_get_drvdata(dev); + + clk_disable_unprepare(data->uart_clk); + clk_disable_unprepare(data->bus_clk); + + return 0; +} + +static int __maybe_unused mtk8250_runtime_resume(struct device *dev) +{ + struct mtk8250_data *data = dev_get_drvdata(dev); + int err; + + err = clk_prepare_enable(data->uart_clk); + if (err) { + dev_warn(dev, "Can't enable clock\n"); + return err; + } + + err = clk_prepare_enable(data->bus_clk); + if (err) { + dev_warn(dev, "Can't enable bus clock\n"); + return err; + } + + return 0; +} + static void mtk8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old) { @@ -130,22 +159,24 @@ mtk8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old) static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port *p, struct mtk8250_data *data) { - int err; - struct device_node *np = pdev->dev.of_node; - - data->uart_clk = of_clk_get(np, 0); + data->uart_clk = devm_clk_get(&pdev->dev, "baud"); if (IS_ERR(data->uart_clk)) { - dev_warn(&pdev->dev, "Can't get timer clock\n"); - return PTR_ERR(data->uart_clk); + /* + * For compatibility with older device trees try unnamed + * clk when no baud clk can be found. + */ + data->uart_clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(data->uart_clk)) { + dev_warn(&pdev->dev, "Can't get uart clock\n"); + return PTR_ERR(data->uart_clk); + } + + return 0; } - err = clk_prepare_enable(data->uart_clk); - if (err) { - dev_warn(&pdev->dev, "Can't prepare clock\n"); - clk_put(data->uart_clk); - return err; - } - p->uartclk = clk_get_rate(data->uart_clk); + data->bus_clk = devm_clk_get(&pdev->dev, "bus"); + if (IS_ERR(data->bus_clk)) + return PTR_ERR(data->bus_clk); return 0; } @@ -190,19 +221,24 @@ static int mtk8250_probe(struct platform_device *pdev) uart.port.regshift = 2; uart.port.private_data = data; uart.port.set_termios = mtk8250_set_termios; + uart.port.uartclk = clk_get_rate(data->uart_clk); /* Disable Rate Fix function */ writel(0x0, uart.port.membase + (MTK_UART_RATE_FIX << uart.port.regshift)); - data->line = serial8250_register_8250_port(&uart); - if (data->line < 0) - return data->line; - platform_set_drvdata(pdev, data); - pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); + if (!pm_runtime_enabled(&pdev->dev)) { + err = mtk8250_runtime_resume(&pdev->dev); + if (err) + return err; + } + + data->line = serial8250_register_8250_port(&uart); + if (data->line < 0) + return data->line; return 0; } @@ -214,57 +250,33 @@ static int mtk8250_remove(struct platform_device *pdev) pm_runtime_get_sync(&pdev->dev); serial8250_unregister_port(data->line); - if (!IS_ERR(data->uart_clk)) { - clk_disable_unprepare(data->uart_clk); - clk_put(data->uart_clk); - } pm_runtime_disable(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int mtk8250_suspend(struct device *dev) -{ - struct mtk8250_data *data = dev_get_drvdata(dev); - serial8250_suspend_port(data->line); + if (!pm_runtime_status_suspended(&pdev->dev)) + mtk8250_runtime_suspend(&pdev->dev); return 0; } -static int mtk8250_resume(struct device *dev) +static int __maybe_unused mtk8250_suspend(struct device *dev) { struct mtk8250_data *data = dev_get_drvdata(dev); - serial8250_resume_port(data->line); - - return 0; -} -#endif /* CONFIG_PM_SLEEP */ - -#ifdef CONFIG_PM -static int mtk8250_runtime_suspend(struct device *dev) -{ - struct mtk8250_data *data = dev_get_drvdata(dev); - - if (!IS_ERR(data->uart_clk)) - clk_disable_unprepare(data->uart_clk); + serial8250_suspend_port(data->line); return 0; } -static int mtk8250_runtime_resume(struct device *dev) +static int __maybe_unused mtk8250_resume(struct device *dev) { struct mtk8250_data *data = dev_get_drvdata(dev); - if (!IS_ERR(data->uart_clk)) - clk_prepare_enable(data->uart_clk); + serial8250_resume_port(data->line); return 0; } -#endif static const struct dev_pm_ops mtk8250_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(mtk8250_suspend, mtk8250_resume) @@ -289,6 +301,21 @@ static struct platform_driver mtk8250_platform_driver = { }; module_platform_driver(mtk8250_platform_driver); +#ifdef CONFIG_SERIAL_8250_CONSOLE +static int __init early_mtk8250_setup(struct earlycon_device *device, + const char *options) +{ + if (!device->port.membase) + return -ENODEV; + + device->port.iotype = UPIO_MEM32; + + return early_serial8250_setup(device, NULL); +} + +OF_EARLYCON_DECLARE(mtk8250, "mediatek,mt6577-uart", early_mtk8250_setup); +#endif + MODULE_AUTHOR("Matthias Brugger"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Mediatek 8250 serial port driver"); diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c new file mode 100644 index 000000000..38963d7bc --- /dev/null +++ b/drivers/tty/serial/8250/8250_of.c @@ -0,0 +1,348 @@ +/* + * Serial Port driver for Open Firmware platform devices + * + * Copyright (C) 2006 Arnd Bergmann <arnd@arndb.de>, IBM Corp. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ +#include <linux/console.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/serial_core.h> +#include <linux/serial_reg.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/of_platform.h> +#include <linux/clk.h> + +#include "8250.h" + +struct of_serial_info { + struct clk *clk; + int type; + int line; +}; + +#ifdef CONFIG_ARCH_TEGRA +static void tegra_serial_handle_break(struct uart_port *p) +{ + unsigned int status, tmout = 10000; + + do { + status = p->serial_in(p, UART_LSR); + if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS)) + status = p->serial_in(p, UART_RX); + else + break; + if (--tmout == 0) + break; + udelay(1); + } while (1); +} +#else +static inline void tegra_serial_handle_break(struct uart_port *port) +{ +} +#endif + +/* + * Fill a struct uart_port for a given device node + */ +static int of_platform_serial_setup(struct platform_device *ofdev, + int type, struct uart_port *port, + struct of_serial_info *info) +{ + struct resource resource; + struct device_node *np = ofdev->dev.of_node; + u32 clk, spd, prop; + int ret; + + memset(port, 0, sizeof *port); + if (of_property_read_u32(np, "clock-frequency", &clk)) { + + /* Get clk rate through clk driver if present */ + info->clk = devm_clk_get(&ofdev->dev, NULL); + if (IS_ERR(info->clk)) { + dev_warn(&ofdev->dev, + "clk or clock-frequency not defined\n"); + return PTR_ERR(info->clk); + } + + ret = clk_prepare_enable(info->clk); + if (ret < 0) + return ret; + + clk = clk_get_rate(info->clk); + } + /* If current-speed was set, then try not to change it. */ + if (of_property_read_u32(np, "current-speed", &spd) == 0) + port->custom_divisor = clk / (16 * spd); + + ret = of_address_to_resource(np, 0, &resource); + if (ret) { + dev_warn(&ofdev->dev, "invalid address\n"); + goto out; + } + + spin_lock_init(&port->lock); + port->mapbase = resource.start; + port->mapsize = resource_size(&resource); + + /* Check for shifted address mapping */ + if (of_property_read_u32(np, "reg-offset", &prop) == 0) + port->mapbase += prop; + + /* Check for registers offset within the devices address range */ + if (of_property_read_u32(np, "reg-shift", &prop) == 0) + port->regshift = prop; + + /* Check for fifo size */ + if (of_property_read_u32(np, "fifo-size", &prop) == 0) + port->fifosize = prop; + + /* Check for a fixed line number */ + ret = of_alias_get_id(np, "serial"); + if (ret >= 0) + port->line = ret; + + port->irq = irq_of_parse_and_map(np, 0); + port->iotype = UPIO_MEM; + if (of_property_read_u32(np, "reg-io-width", &prop) == 0) { + switch (prop) { + case 1: + port->iotype = UPIO_MEM; + break; + case 2: + port->iotype = UPIO_MEM16; + break; + case 4: + port->iotype = of_device_is_big_endian(np) ? + UPIO_MEM32BE : UPIO_MEM32; + break; + default: + dev_warn(&ofdev->dev, "unsupported reg-io-width (%d)\n", + prop); + ret = -EINVAL; + goto out; + } + } + + port->type = type; + port->uartclk = clk; + port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP + | UPF_FIXED_PORT | UPF_FIXED_TYPE; + + if (of_find_property(np, "no-loopback-test", NULL)) + port->flags |= UPF_SKIP_TEST; + + port->dev = &ofdev->dev; + + switch (type) { + case PORT_TEGRA: + port->handle_break = tegra_serial_handle_break; + break; + + case PORT_RT2880: + port->iotype = UPIO_AU; + break; + } + + if (IS_ENABLED(CONFIG_SERIAL_8250_FSL) && + (of_device_is_compatible(np, "fsl,ns16550") || + of_device_is_compatible(np, "fsl,16550-FIFO64"))) + port->handle_irq = fsl8250_handle_irq; + + return 0; +out: + if (info->clk) + clk_disable_unprepare(info->clk); + return ret; +} + +/* + * Try to register a serial port + */ +static const struct of_device_id of_platform_serial_table[]; +static int of_platform_serial_probe(struct platform_device *ofdev) +{ + const struct of_device_id *match; + struct of_serial_info *info; + struct uart_port port; + int port_type; + int ret; + + match = of_match_device(of_platform_serial_table, &ofdev->dev); + if (!match) + return -EINVAL; + + if (of_find_property(ofdev->dev.of_node, "used-by-rtas", NULL)) + return -EBUSY; + + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (info == NULL) + return -ENOMEM; + + port_type = (unsigned long)match->data; + ret = of_platform_serial_setup(ofdev, port_type, &port, info); + if (ret) + goto out; + + switch (port_type) { + case PORT_8250 ... PORT_MAX_8250: + { + struct uart_8250_port port8250; + memset(&port8250, 0, sizeof(port8250)); + port8250.port = port; + + if (port.fifosize) + port8250.capabilities = UART_CAP_FIFO; + + if (of_property_read_bool(ofdev->dev.of_node, + "auto-flow-control")) + port8250.capabilities |= UART_CAP_AFE; + + ret = serial8250_register_8250_port(&port8250); + break; + } + default: + /* need to add code for these */ + case PORT_UNKNOWN: + dev_info(&ofdev->dev, "Unknown serial port found, ignored\n"); + ret = -ENODEV; + break; + } + if (ret < 0) + goto out; + + info->type = port_type; + info->line = ret; + platform_set_drvdata(ofdev, info); + return 0; +out: + kfree(info); + irq_dispose_mapping(port.irq); + return ret; +} + +/* + * Release a line + */ +static int of_platform_serial_remove(struct platform_device *ofdev) +{ + struct of_serial_info *info = platform_get_drvdata(ofdev); + switch (info->type) { + case PORT_8250 ... PORT_MAX_8250: + serial8250_unregister_port(info->line); + break; + default: + /* need to add code for these */ + break; + } + + if (info->clk) + clk_disable_unprepare(info->clk); + kfree(info); + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static void of_serial_suspend_8250(struct of_serial_info *info) +{ + struct uart_8250_port *port8250 = serial8250_get_port(info->line); + struct uart_port *port = &port8250->port; + + serial8250_suspend_port(info->line); + if (info->clk && (!uart_console(port) || console_suspend_enabled)) + clk_disable_unprepare(info->clk); +} + +static void of_serial_resume_8250(struct of_serial_info *info) +{ + struct uart_8250_port *port8250 = serial8250_get_port(info->line); + struct uart_port *port = &port8250->port; + + if (info->clk && (!uart_console(port) || console_suspend_enabled)) + clk_prepare_enable(info->clk); + + serial8250_resume_port(info->line); +} + +static int of_serial_suspend(struct device *dev) +{ + struct of_serial_info *info = dev_get_drvdata(dev); + + switch (info->type) { + case PORT_8250 ... PORT_MAX_8250: + of_serial_suspend_8250(info); + break; + default: + break; + } + + return 0; +} + +static int of_serial_resume(struct device *dev) +{ + struct of_serial_info *info = dev_get_drvdata(dev); + + switch (info->type) { + case PORT_8250 ... PORT_MAX_8250: + of_serial_resume_8250(info); + break; + default: + break; + } + + return 0; +} +#endif +static SIMPLE_DEV_PM_OPS(of_serial_pm_ops, of_serial_suspend, of_serial_resume); + +/* + * A few common types, add more as needed. + */ +static const struct of_device_id of_platform_serial_table[] = { + { .compatible = "ns8250", .data = (void *)PORT_8250, }, + { .compatible = "ns16450", .data = (void *)PORT_16450, }, + { .compatible = "ns16550a", .data = (void *)PORT_16550A, }, + { .compatible = "ns16550", .data = (void *)PORT_16550, }, + { .compatible = "ns16750", .data = (void *)PORT_16750, }, + { .compatible = "ns16850", .data = (void *)PORT_16850, }, + { .compatible = "nvidia,tegra20-uart", .data = (void *)PORT_TEGRA, }, + { .compatible = "nxp,lpc3220-uart", .data = (void *)PORT_LPC3220, }, + { .compatible = "ralink,rt2880-uart", .data = (void *)PORT_RT2880, }, + { .compatible = "altr,16550-FIFO32", + .data = (void *)PORT_ALTR_16550_F32, }, + { .compatible = "altr,16550-FIFO64", + .data = (void *)PORT_ALTR_16550_F64, }, + { .compatible = "altr,16550-FIFO128", + .data = (void *)PORT_ALTR_16550_F128, }, + { .compatible = "mrvl,mmp-uart", + .data = (void *)PORT_XSCALE, }, + { .compatible = "mrvl,pxa-uart", + .data = (void *)PORT_XSCALE, }, + { /* end of list */ }, +}; +MODULE_DEVICE_TABLE(of, of_platform_serial_table); + +static struct platform_driver of_platform_serial_driver = { + .driver = { + .name = "of_serial", + .of_match_table = of_platform_serial_table, + .pm = &of_serial_pm_ops, + }, + .probe = of_platform_serial_probe, + .remove = of_platform_serial_remove, +}; + +module_platform_driver(of_platform_serial_driver); + +MODULE_AUTHOR("Arnd Bergmann <arnd@arndb.de>"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Serial Port driver for Open Firmware platform devices"); diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index dce1a2370..61ad6c3b2 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -16,12 +16,14 @@ #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> #include <linux/pm_runtime.h> #include <linux/console.h> #include <linux/pm_qos.h> +#include <linux/pm_wakeirq.h> #include <linux/dma-mapping.h> #include "8250.h" @@ -31,6 +33,11 @@ #define UART_ERRATA_i202_MDR1_ACCESS (1 << 0) #define OMAP_UART_WER_HAS_TX_WAKEUP (1 << 1) #define OMAP_DMA_TX_KICK (1 << 2) +/* + * See Advisory 21 in AM437x errata SPRZ408B, updated April 2015. + * The same errata is applicable to AM335x and DRA7x processors too. + */ +#define UART_ERRATA_CLOCK_DISABLE (1 << 3) #define OMAP_UART_FCR_RX_TRIG 6 #define OMAP_UART_FCR_TX_TRIG 4 @@ -52,6 +59,12 @@ #define OMAP_UART_MVR_MAJ_SHIFT 8 #define OMAP_UART_MVR_MIN_MASK 0x3f +/* SYSC register bitmasks */ +#define OMAP_UART_SYSC_SOFTRESET (1 << 1) + +/* SYSS register bitmasks */ +#define OMAP_UART_SYSS_RESETDONE (1 << 0) + #define UART_TI752_TLR_TX 0 #define UART_TI752_TLR_RX 4 @@ -98,8 +111,16 @@ struct omap8250_priv { struct pm_qos_request pm_qos_request; struct work_struct qos_work; struct uart_8250_dma omap8250_dma; + spinlock_t rx_dma_lock; + bool rx_dma_broken; }; +#ifdef CONFIG_SERIAL_8250_DMA +static void omap_8250_rx_dma_flush(struct uart_8250_port *p); +#else +static inline void omap_8250_rx_dma_flush(struct uart_8250_port *p) { } +#endif + static u32 uart_read(struct uart_8250_port *up, u32 reg) { return readl(up->port.membase + (reg << up->port.regshift)); @@ -230,6 +251,15 @@ static void omap8250_update_scr(struct uart_8250_port *up, serial_out(up, UART_OMAP_SCR, priv->scr); } +static void omap8250_update_mdr1(struct uart_8250_port *up, + struct omap8250_priv *priv) +{ + if (priv->habit & UART_ERRATA_i202_MDR1_ACCESS) + omap_8250_mdr1_errataset(up, priv); + else + serial_out(up, UART_OMAP_MDR1, priv->mdr1); +} + static void omap8250_restore_regs(struct uart_8250_port *up) { struct omap8250_priv *priv = up->port.private_data; @@ -250,7 +280,7 @@ static void omap8250_restore_regs(struct uart_8250_port *up) serial_out(up, UART_EFR, UART_EFR_ECB); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); - serial_out(up, UART_MCR, UART_MCR_TCRTLR); + serial8250_out_MCR(up, UART_MCR_TCRTLR); serial_out(up, UART_FCR, up->fcr); omap8250_update_scr(up, priv); @@ -266,7 +296,7 @@ static void omap8250_restore_regs(struct uart_8250_port *up) serial_out(up, UART_LCR, 0); /* drop TCR + TLR access, we setup XON/XOFF later */ - serial_out(up, UART_MCR, up->mcr); + serial8250_out_MCR(up, up->mcr); serial_out(up, UART_IER, up->ier); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); @@ -280,11 +310,9 @@ static void omap8250_restore_regs(struct uart_8250_port *up) serial_out(up, UART_XOFF1, priv->xoff); serial_out(up, UART_LCR, up->lcr); - /* need mode A for FCR */ - if (priv->habit & UART_ERRATA_i202_MDR1_ACCESS) - omap_8250_mdr1_errataset(up, priv); - else - serial_out(up, UART_OMAP_MDR1, priv->mdr1); + + omap8250_update_mdr1(up, priv); + up->port.ops->set_mctrl(&up->port, up->port.mctrl); } @@ -296,8 +324,7 @@ static void omap_8250_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { - struct uart_8250_port *up = - container_of(port, struct uart_8250_port, port); + struct uart_8250_port *up = up_to_u8250p(port); struct omap8250_priv *priv = up->port.private_data; unsigned char cval = 0; unsigned int baud; @@ -417,7 +444,6 @@ static void omap_8250_set_termios(struct uart_port *port, priv->xoff = termios->c_cc[VSTOP]; priv->efr = 0; - up->mcr &= ~(UART_MCR_RTS | UART_MCR_XONANY); up->port.status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS | UPSTAT_AUTOXOFF); if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW) { @@ -426,12 +452,9 @@ static void omap_8250_set_termios(struct uart_port *port, priv->efr |= UART_EFR_CTS; } else if (up->port.flags & UPF_SOFT_FLOW) { /* - * IXON Flag: - * Enable XON/XOFF flow control on input. - * Receiver compares XON1, XOFF1. + * OMAP rx s/w flow control is borked; the transmitter remains + * stuck off even if rx flow control is subsequently disabled */ - if (termios->c_iflag & IXON) - priv->efr |= OMAP_UART_SW_RX; /* * IXOFF Flag: @@ -442,15 +465,6 @@ static void omap_8250_set_termios(struct uart_port *port, up->port.status |= UPSTAT_AUTOXOFF; priv->efr |= OMAP_UART_SW_TX; } - - /* - * IXANY Flag: - * Enable any character to restart output. - * Operation resumes after receiving any - * character after recognition of the XOFF character - */ - if (termios->c_iflag & IXANY) - up->mcr |= UART_MCR_XONANY; } omap8250_restore_regs(up); @@ -528,14 +542,14 @@ static void omap_serial_fill_features_erratas(struct uart_8250_port *up, switch (revision) { case OMAP_UART_REV_46: - priv->habit = UART_ERRATA_i202_MDR1_ACCESS; + priv->habit |= UART_ERRATA_i202_MDR1_ACCESS; break; case OMAP_UART_REV_52: - priv->habit = UART_ERRATA_i202_MDR1_ACCESS | + priv->habit |= UART_ERRATA_i202_MDR1_ACCESS | OMAP_UART_WER_HAS_TX_WAKEUP; break; case OMAP_UART_REV_63: - priv->habit = UART_ERRATA_i202_MDR1_ACCESS | + priv->habit |= UART_ERRATA_i202_MDR1_ACCESS | OMAP_UART_WER_HAS_TX_WAKEUP; break; default: @@ -551,17 +565,6 @@ static void omap8250_uart_qos_work(struct work_struct *work) pm_qos_update_request(&priv->pm_qos_request, priv->latency); } -static irqreturn_t omap_wake_irq(int irq, void *dev_id) -{ - struct uart_port *port = dev_id; - int ret; - - ret = port->handle_irq(port); - if (ret) - return IRQ_HANDLED; - return IRQ_NONE; -} - #ifdef CONFIG_SERIAL_8250_DMA static int omap_8250_dma_handle_irq(struct uart_port *port); #endif @@ -595,11 +598,9 @@ static int omap_8250_startup(struct uart_port *port) int ret; if (priv->wakeirq) { - ret = request_irq(priv->wakeirq, omap_wake_irq, - port->irqflags, "uart wakeup irq", port); + ret = dev_pm_set_dedicated_wake_irq(port->dev, priv->wakeirq); if (ret) return ret; - disable_irq(priv->wakeirq); } pm_runtime_get_sync(port->dev); @@ -640,7 +641,7 @@ static int omap_8250_startup(struct uart_port *port) serial_out(up, UART_OMAP_WER, priv->wer); if (up->dma) - up->dma->rx_dma(up, 0); + up->dma->rx_dma(up); pm_runtime_mark_last_busy(port->dev); pm_runtime_put_autosuspend(port->dev); @@ -648,8 +649,7 @@ static int omap_8250_startup(struct uart_port *port) err: pm_runtime_mark_last_busy(port->dev); pm_runtime_put_autosuspend(port->dev); - if (priv->wakeirq) - free_irq(priv->wakeirq, port); + dev_pm_clear_wake_irq(port->dev); return ret; } @@ -660,7 +660,7 @@ static void omap_8250_shutdown(struct uart_port *port) flush_work(&priv->qos_work); if (up->dma) - up->dma->rx_dma(up, UART_IIR_RX_TIMEOUT); + omap_8250_rx_dma_flush(up); pm_runtime_get_sync(port->dev); @@ -681,17 +681,14 @@ static void omap_8250_shutdown(struct uart_port *port) pm_runtime_mark_last_busy(port->dev); pm_runtime_put_autosuspend(port->dev); - free_irq(port->irq, port); - if (priv->wakeirq) - free_irq(priv->wakeirq, port); + dev_pm_clear_wake_irq(port->dev); } static void omap_8250_throttle(struct uart_port *port) { + struct uart_8250_port *up = up_to_u8250p(port); unsigned long flags; - struct uart_8250_port *up = - container_of(port, struct uart_8250_port, port); pm_runtime_get_sync(port->dev); @@ -704,11 +701,40 @@ static void omap_8250_throttle(struct uart_port *port) pm_runtime_put_autosuspend(port->dev); } +static int omap_8250_rs485_config(struct uart_port *port, + struct serial_rs485 *rs485) +{ + struct uart_8250_port *up = up_to_u8250p(port); + + /* Clamp the delays to [0, 100ms] */ + rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U); + rs485->delay_rts_after_send = min(rs485->delay_rts_after_send, 100U); + + port->rs485 = *rs485; + + /* + * Both serial8250_em485_init and serial8250_em485_destroy + * are idempotent + */ + if (rs485->flags & SER_RS485_ENABLED) { + int ret = serial8250_em485_init(up); + + if (ret) { + rs485->flags &= ~SER_RS485_ENABLED; + port->rs485.flags &= ~SER_RS485_ENABLED; + } + return ret; + } + + serial8250_em485_destroy(up); + + return 0; +} + static void omap_8250_unthrottle(struct uart_port *port) { + struct uart_8250_port *up = up_to_u8250p(port); unsigned long flags; - struct uart_8250_port *up = - container_of(port, struct uart_8250_port, port); pm_runtime_get_sync(port->dev); @@ -722,88 +748,91 @@ static void omap_8250_unthrottle(struct uart_port *port) } #ifdef CONFIG_SERIAL_8250_DMA -static int omap_8250_rx_dma(struct uart_8250_port *p, unsigned int iir); +static int omap_8250_rx_dma(struct uart_8250_port *p); -static void __dma_rx_do_complete(struct uart_8250_port *p, bool error) +static void __dma_rx_do_complete(struct uart_8250_port *p) { + struct omap8250_priv *priv = p->port.private_data; struct uart_8250_dma *dma = p->dma; struct tty_port *tty_port = &p->port.state->port; struct dma_tx_state state; int count; + unsigned long flags; + int ret; + + spin_lock_irqsave(&priv->rx_dma_lock, flags); - dma_sync_single_for_cpu(dma->rxchan->device->dev, dma->rx_addr, - dma->rx_size, DMA_FROM_DEVICE); + if (!dma->rx_running) + goto unlock; dma->rx_running = 0; dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state); - dmaengine_terminate_all(dma->rxchan); count = dma->rx_size - state.residue; - tty_insert_flip_string(tty_port, dma->rx_buf, count); - p->port.icount.rx += count; - if (!error) - omap_8250_rx_dma(p, 0); + ret = tty_insert_flip_string(tty_port, dma->rx_buf, count); + + p->port.icount.rx += ret; + p->port.icount.buf_overrun += count - ret; +unlock: + spin_unlock_irqrestore(&priv->rx_dma_lock, flags); tty_flip_buffer_push(tty_port); } static void __dma_rx_complete(void *param) { - __dma_rx_do_complete(param, false); + __dma_rx_do_complete(param); + omap_8250_rx_dma(param); } -static int omap_8250_rx_dma(struct uart_8250_port *p, unsigned int iir) +static void omap_8250_rx_dma_flush(struct uart_8250_port *p) { + struct omap8250_priv *priv = p->port.private_data; + struct uart_8250_dma *dma = p->dma; + unsigned long flags; + int ret; + + spin_lock_irqsave(&priv->rx_dma_lock, flags); + + if (!dma->rx_running) { + spin_unlock_irqrestore(&priv->rx_dma_lock, flags); + return; + } + + ret = dmaengine_pause(dma->rxchan); + if (WARN_ON_ONCE(ret)) + priv->rx_dma_broken = true; + + spin_unlock_irqrestore(&priv->rx_dma_lock, flags); + + __dma_rx_do_complete(p); + dmaengine_terminate_all(dma->rxchan); +} + +static int omap_8250_rx_dma(struct uart_8250_port *p) +{ + struct omap8250_priv *priv = p->port.private_data; struct uart_8250_dma *dma = p->dma; + int err = 0; struct dma_async_tx_descriptor *desc; + unsigned long flags; - switch (iir & 0x3f) { - case UART_IIR_RLSI: - /* 8250_core handles errors and break interrupts */ - if (dma->rx_running) { - dmaengine_pause(dma->rxchan); - __dma_rx_do_complete(p, true); - } - return -EIO; - case UART_IIR_RX_TIMEOUT: - /* - * If RCVR FIFO trigger level was not reached, complete the - * transfer and let 8250_core copy the remaining data. - */ - if (dma->rx_running) { - dmaengine_pause(dma->rxchan); - __dma_rx_do_complete(p, true); - } - return -ETIMEDOUT; - case UART_IIR_RDI: - /* - * The OMAP UART is a special BEAST. If we receive RDI we _have_ - * a DMA transfer programmed but it didn't work. One reason is - * that we were too slow and there were too many bytes in the - * FIFO, the UART counted wrong and never kicked the DMA engine - * to do anything. That means once we receive RDI on OMAP then - * the DMA won't do anything soon so we have to cancel the DMA - * transfer and purge the FIFO manually. - */ - if (dma->rx_running) { - dmaengine_pause(dma->rxchan); - __dma_rx_do_complete(p, true); - } - return -ETIMEDOUT; + if (priv->rx_dma_broken) + return -EINVAL; - default: - break; - } + spin_lock_irqsave(&priv->rx_dma_lock, flags); if (dma->rx_running) - return 0; + goto out; desc = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr, dma->rx_size, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - if (!desc) - return -EBUSY; + if (!desc) { + err = -EBUSY; + goto out; + } dma->rx_running = 1; desc->callback = __dma_rx_complete; @@ -811,11 +840,10 @@ static int omap_8250_rx_dma(struct uart_8250_port *p, unsigned int iir) dma->rx_cookie = dmaengine_submit(desc); - dma_sync_single_for_device(dma->rxchan->device->dev, dma->rx_addr, - dma->rx_size, DMA_FROM_DEVICE); - dma_async_issue_pending(dma->rxchan); - return 0; +out: + spin_unlock_irqrestore(&priv->rx_dma_lock, flags); + return err; } static int omap_8250_tx_dma(struct uart_8250_port *p); @@ -963,6 +991,18 @@ err: return ret; } +static bool handle_rx_dma(struct uart_8250_port *up, unsigned int iir) +{ + switch (iir & 0x3f) { + case UART_IIR_RLSI: + case UART_IIR_RX_TIMEOUT: + case UART_IIR_RDI: + omap_8250_rx_dma_flush(up); + return true; + } + return omap_8250_rx_dma(up); +} + /* * This is mostly serial8250_handle_irq(). We have a slightly different DMA * hoook for RX/TX and need different logic for them in the ISR. Therefore we @@ -974,7 +1014,6 @@ static int omap_8250_dma_handle_irq(struct uart_port *port) unsigned char status; unsigned long flags; u8 iir; - int dma_err = 0; serial8250_rpm_get(up); @@ -989,11 +1028,9 @@ static int omap_8250_dma_handle_irq(struct uart_port *port) status = serial_port_in(port, UART_LSR); if (status & (UART_LSR_DR | UART_LSR_BI)) { - - dma_err = omap_8250_rx_dma(up, iir); - if (dma_err) { + if (handle_rx_dma(up, iir)) { status = serial8250_rx_chars(up, status); - omap_8250_rx_dma(up, 0); + omap_8250_rx_dma(up); } } serial8250_modem_status(up); @@ -1007,8 +1044,7 @@ static int omap_8250_dma_handle_irq(struct uart_port *port) * try again due to an earlier failer which * might have been resolved by now. */ - dma_err = omap_8250_tx_dma(up); - if (dma_err) + if (omap_8250_tx_dma(up)) serial8250_tx_chars(up); } } @@ -1025,7 +1061,7 @@ static bool the_no_dma_filter_fn(struct dma_chan *chan, void *param) #else -static inline int omap_8250_rx_dma(struct uart_8250_port *p, unsigned int iir) +static inline int omap_8250_rx_dma(struct uart_8250_port *p) { return -EINVAL; } @@ -1038,6 +1074,20 @@ static int omap8250_no_handle_irq(struct uart_port *port) return 0; } +static const u8 am3352_habit = OMAP_DMA_TX_KICK | UART_ERRATA_CLOCK_DISABLE; +static const u8 am4372_habit = UART_ERRATA_CLOCK_DISABLE; + +static const struct of_device_id omap8250_dt_ids[] = { + { .compatible = "ti,omap2-uart" }, + { .compatible = "ti,omap3-uart" }, + { .compatible = "ti,omap4-uart" }, + { .compatible = "ti,am3352-uart", .data = &am3352_habit, }, + { .compatible = "ti,am4372-uart", .data = &am4372_habit, }, + { .compatible = "ti,dra742-uart", .data = &am4372_habit, }, + {}, +}; +MODULE_DEVICE_TABLE(of, omap8250_dt_ids); + static int omap8250_probe(struct platform_device *pdev) { struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -1100,13 +1150,20 @@ static int omap8250_probe(struct platform_device *pdev) up.port.shutdown = omap_8250_shutdown; up.port.throttle = omap_8250_throttle; up.port.unthrottle = omap_8250_unthrottle; + up.port.rs485_config = omap_8250_rs485_config; if (pdev->dev.of_node) { + const struct of_device_id *id; + ret = of_alias_get_id(pdev->dev.of_node, "serial"); of_property_read_u32(pdev->dev.of_node, "clock-frequency", &up.port.uartclk); priv->wakeirq = irq_of_parse_and_map(pdev->dev.of_node, 1); + + id = of_match_device(of_match_ptr(omap8250_dt_ids), &pdev->dev); + if (id && id->data) + priv->habit |= *(u8 *)id->data; } else { ret = pdev->id; } @@ -1129,6 +1186,8 @@ static int omap8250_probe(struct platform_device *pdev) priv->latency); INIT_WORK(&priv->qos_work, omap8250_uart_qos_work); + spin_lock_init(&priv->rx_dma_lock); + device_init_wakeup(&pdev->dev, true); pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_set_autosuspend_delay(&pdev->dev, -1); @@ -1162,6 +1221,11 @@ static int omap8250_probe(struct platform_device *pdev) if (of_machine_is_compatible("ti,am33xx")) priv->habit |= OMAP_DMA_TX_KICK; + /* + * pause is currently not supported atleast on omap-sdma + * and edma on most earlier kernels. + */ + priv->rx_dma_broken = true; } } #endif @@ -1193,31 +1257,6 @@ static int omap8250_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM - -static inline void omap8250_enable_wakeirq(struct omap8250_priv *priv, - bool enable) -{ - if (!priv->wakeirq) - return; - - if (enable) - enable_irq(priv->wakeirq); - else - disable_irq_nosync(priv->wakeirq); -} - -static void omap8250_enable_wakeup(struct omap8250_priv *priv, - bool enable) -{ - if (enable == priv->wakeups_enabled) - return; - - omap8250_enable_wakeirq(priv, enable); - priv->wakeups_enabled = enable; -} -#endif - #ifdef CONFIG_PM_SLEEP static int omap8250_prepare(struct device *dev) { @@ -1244,11 +1283,6 @@ static int omap8250_suspend(struct device *dev) serial8250_suspend_port(priv->line); flush_work(&priv->qos_work); - - if (device_may_wakeup(dev)) - omap8250_enable_wakeup(priv, true); - else - omap8250_enable_wakeup(priv, false); return 0; } @@ -1256,9 +1290,6 @@ static int omap8250_resume(struct device *dev) { struct omap8250_priv *priv = dev_get_drvdata(dev); - if (device_may_wakeup(dev)) - omap8250_enable_wakeup(priv, false); - serial8250_resume_port(priv->line); return 0; } @@ -1272,17 +1303,46 @@ static int omap8250_lost_context(struct uart_8250_port *up) { u32 val; - val = serial_in(up, UART_OMAP_MDR1); + val = serial_in(up, UART_OMAP_SCR); /* - * If we lose context, then MDR1 is set to its reset value which is - * UART_OMAP_MDR1_DISABLE. After set_termios() we set it either to 13x - * or 16x but never to disable again. + * If we lose context, then SCR is set to its reset value of zero. + * After set_termios() we set bit 3 of SCR (TX_EMPTY_CTL_IT) to 1, + * among other bits, to never set the register back to zero again. */ - if (val == UART_OMAP_MDR1_DISABLE) + if (!val) return 1; return 0; } +/* TODO: in future, this should happen via API in drivers/reset/ */ +static int omap8250_soft_reset(struct device *dev) +{ + struct omap8250_priv *priv = dev_get_drvdata(dev); + struct uart_8250_port *up = serial8250_get_port(priv->line); + int timeout = 100; + int sysc; + int syss; + + sysc = serial_in(up, UART_OMAP_SYSC); + + /* softreset the UART */ + sysc |= OMAP_UART_SYSC_SOFTRESET; + serial_out(up, UART_OMAP_SYSC, sysc); + + /* By experiments, 1us enough for reset complete on AM335x */ + do { + udelay(1); + syss = serial_in(up, UART_OMAP_SYSS); + } while (--timeout && !(syss & OMAP_UART_SYSS_RESETDONE)); + + if (!timeout) { + dev_err(dev, "timed out waiting for reset done\n"); + return -ETIMEDOUT; + } + + return 0; +} + static int omap8250_runtime_suspend(struct device *dev) { struct omap8250_priv *priv = dev_get_drvdata(dev); @@ -1300,9 +1360,19 @@ static int omap8250_runtime_suspend(struct device *dev) return -EBUSY; } - omap8250_enable_wakeup(priv, true); - if (up->dma) - omap_8250_rx_dma(up, UART_IIR_RX_TIMEOUT); + if (priv->habit & UART_ERRATA_CLOCK_DISABLE) { + int ret; + + ret = omap8250_soft_reset(dev); + if (ret) + return ret; + + /* Restore to UART mode after reset (for wakeup) */ + omap8250_update_mdr1(up, priv); + } + + if (up->dma && up->dma->rxchan) + omap_8250_rx_dma_flush(up); priv->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE; schedule_work(&priv->qos_work); @@ -1314,21 +1384,18 @@ static int omap8250_runtime_resume(struct device *dev) { struct omap8250_priv *priv = dev_get_drvdata(dev); struct uart_8250_port *up; - int loss_cntx; /* In case runtime-pm tries this before we are setup */ if (!priv) return 0; up = serial8250_get_port(priv->line); - omap8250_enable_wakeup(priv, false); - loss_cntx = omap8250_lost_context(up); - if (loss_cntx) + if (omap8250_lost_context(up)) omap8250_restore_regs(up); - if (up->dma) - omap_8250_rx_dma(up, 0); + if (up->dma && up->dma->rxchan) + omap_8250_rx_dma(up); priv->latency = priv->calc_latency; schedule_work(&priv->qos_work); @@ -1384,14 +1451,6 @@ static const struct dev_pm_ops omap8250_dev_pm_ops = { .complete = omap8250_complete, }; -static const struct of_device_id omap8250_dt_ids[] = { - { .compatible = "ti,omap2-uart" }, - { .compatible = "ti,omap3-uart" }, - { .compatible = "ti,omap4-uart" }, - {}, -}; -MODULE_DEVICE_TABLE(of, omap8250_dt_ids); - static struct platform_driver omap8250_platform_driver = { .driver = { .name = "omap8250", diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 46bcebba5..bc51b32b2 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -28,7 +28,6 @@ #include <linux/dmaengine.h> #include <linux/platform_data/dma-dw.h> -#include <linux/platform_data/dma-hsu.h> #include "8250.h" @@ -56,7 +55,6 @@ struct pci_serial_quirk { struct serial_private { struct pci_dev *dev; unsigned int nr; - void __iomem *remapped_bar[PCI_NUM_BAR_RESOURCES]; struct pci_serial_quirk *quirk; int line[0]; }; @@ -86,15 +84,13 @@ setup_port(struct serial_private *priv, struct uart_8250_port *port, return -EINVAL; if (pci_resource_flags(dev, bar) & IORESOURCE_MEM) { - if (!priv->remapped_bar[bar]) - priv->remapped_bar[bar] = pci_ioremap_bar(dev, bar); - if (!priv->remapped_bar[bar]) + if (!pcim_iomap(dev, bar, 0) && !pcim_iomap_table(dev)) return -ENOMEM; port->port.iotype = UPIO_MEM; port->port.iobase = 0; port->port.mapbase = pci_resource_start(dev, bar) + offset; - port->port.membase = priv->remapped_bar[bar] + offset; + port->port.membase = pcim_iomap_table(dev)[bar] + offset; port->port.regshift = regshift; } else { port->port.iotype = UPIO_PORT; @@ -722,7 +718,7 @@ static int pci_ni8430_init(struct pci_dev *dev) */ pcibios_resource_to_bus(dev->bus, ®ion, &dev->resource[bar]); device_window = ((region.start + MITE_IOWBSR1_WIN_OFFSET) & 0xffffff00) - | MITE_IOWBSR1_WENAB | MITE_IOWBSR1_WSIZE; + | MITE_IOWBSR1_WENAB | MITE_IOWBSR1_WSIZE; writel(device_window, p + MITE_IOWBSR1); /* Set window access to go to RAMSEL IO address space */ @@ -804,12 +800,12 @@ static int pci_netmos_9900_numports(struct pci_dev *dev) unsigned int pi; unsigned short sub_serports; - pi = (c & 0xff); + pi = c & 0xff; - if (pi == 2) { + if (pi == 2) return 1; - } else if ((pi == 0) && - (dev->device == PCI_DEVICE_ID_NETMOS_9900)) { + + if ((pi == 0) && (dev->device == PCI_DEVICE_ID_NETMOS_9900)) { /* two possibilities: 0x30ps encodes number of parallel and * serial ports, or 0x1000 indicates *something*. This is not * immediately obvious, since the 2s1p+4s configuration seems @@ -817,12 +813,12 @@ static int pci_netmos_9900_numports(struct pci_dev *dev) * advertising the same function 3 as the 4s+2s1p config. */ sub_serports = dev->subsystem_device & 0xf; - if (sub_serports > 0) { + if (sub_serports > 0) return sub_serports; - } else { - dev_err(&dev->dev, "NetMos/Mostech serial driver ignoring port on ambiguous config.\n"); - return 0; - } + + dev_err(&dev->dev, + "NetMos/Mostech serial driver ignoring port on ambiguous config.\n"); + return 0; } moan_device("unknown NetMos/Mostech program interface", dev); @@ -843,21 +839,21 @@ static int pci_netmos_init(struct pci_dev *dev) return 0; switch (dev->device) { /* FALLTHROUGH on all */ - case PCI_DEVICE_ID_NETMOS_9904: - case PCI_DEVICE_ID_NETMOS_9912: - case PCI_DEVICE_ID_NETMOS_9922: - case PCI_DEVICE_ID_NETMOS_9900: - num_serial = pci_netmos_9900_numports(dev); - break; + case PCI_DEVICE_ID_NETMOS_9904: + case PCI_DEVICE_ID_NETMOS_9912: + case PCI_DEVICE_ID_NETMOS_9922: + case PCI_DEVICE_ID_NETMOS_9900: + num_serial = pci_netmos_9900_numports(dev); + break; - default: - if (num_serial == 0 ) { - moan_device("unknown NetMos/Mostech device", dev); - } + default: + break; } - if (num_serial == 0) + if (num_serial == 0) { + moan_device("unknown NetMos/Mostech device", dev); return -ENODEV; + } return num_serial; } @@ -1140,11 +1136,11 @@ static int pci_quatech_rqopr(struct uart_8250_port *port) static void pci_quatech_wqopr(struct uart_8250_port *port, u8 qopr) { unsigned long base = port->port.iobase; - u8 LCR, val; + u8 LCR; LCR = inb(base + UART_LCR); outb(0xBF, base + UART_LCR); - val = inb(base + UART_SCR); + inb(base + UART_SCR); outb(qopr, base + UART_SCR); outb(LCR, base + UART_LCR); } @@ -1199,8 +1195,9 @@ static int pci_quatech_has_qmcr(struct uart_8250_port *port) static int pci_quatech_test(struct uart_8250_port *port) { - u8 reg; - u8 qopr = pci_quatech_rqopr(port); + u8 reg, qopr; + + qopr = pci_quatech_rqopr(port); pci_quatech_wqopr(port, qopr & QPCR_TEST_FOR1); reg = pci_quatech_rqopr(port) & 0xC0; if (reg != QPCR_TEST_GET1) @@ -1287,6 +1284,7 @@ static int pci_quatech_init(struct pci_dev *dev) unsigned long base = pci_resource_start(dev, 0); if (base) { u32 tmp; + outl(inl(base + 0x38) | 0x00002000, base + 0x38); tmp = inl(base + 0x3c); outl(tmp | 0x01000000, base + 0x3c); @@ -1335,29 +1333,6 @@ static int pci_default_setup(struct serial_private *priv, return setup_port(priv, port, bar, offset, board->reg_shift); } -static int pci_pericom_setup(struct serial_private *priv, - const struct pciserial_board *board, - struct uart_8250_port *port, int idx) -{ - unsigned int bar, offset = board->first_offset, maxnr; - - bar = FL_GET_BASE(board->flags); - if (board->flags & FL_BASE_BARS) - bar += idx; - else - offset += idx * board->uart_offset; - - maxnr = (pci_resource_len(priv->dev, bar) - board->first_offset) >> - (board->reg_shift + 3); - - if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr) - return 1; - - port->port.uartclk = 14745600; - - return setup_port(priv, port, bar, offset, board->reg_shift); -} - static int ce4100_serial_setup(struct serial_private *priv, const struct pciserial_board *board, @@ -1380,6 +1355,9 @@ ce4100_serial_setup(struct serial_private *priv, #define PCI_DEVICE_ID_INTEL_BSW_UART1 0x228a #define PCI_DEVICE_ID_INTEL_BSW_UART2 0x228c +#define PCI_DEVICE_ID_INTEL_BDW_UART1 0x9ce3 +#define PCI_DEVICE_ID_INTEL_BDW_UART2 0x9ce4 + #define BYT_PRV_CLK 0x800 #define BYT_PRV_CLK_EN (1 << 0) #define BYT_PRV_CLK_M_VAL_SHIFT 1 @@ -1399,6 +1377,9 @@ byt_set_termios(struct uart_port *p, struct ktermios *termios, unsigned long m, n; u32 reg; + /* Gracefully handle the B0 case: fall back to B9600 */ + fuart = fuart ? fuart : 9600 * 16; + /* Get Fuart closer to Fref */ fuart *= rounddown_pow_of_two(fref / fuart); @@ -1417,6 +1398,10 @@ byt_set_termios(struct uart_port *p, struct ktermios *termios, reg |= BYT_PRV_CLK_EN | BYT_PRV_CLK_UPDATE; writel(reg, p->membase + BYT_PRV_CLK); + p->status &= ~UPSTAT_AUTOCTS; + if (termios->c_cflag & CRTSCTS) + p->status |= UPSTAT_AUTOCTS; + serial8250_do_set_termios(p, termios, old); } @@ -1431,6 +1416,17 @@ static bool byt_dma_filter(struct dma_chan *chan, void *param) return true; } +static unsigned int +byt_get_mctrl(struct uart_port *port) +{ + unsigned int ret = serial8250_do_get_mctrl(port); + + /* Force DCD and DSR signals to permanently be reported as active. */ + ret |= TIOCM_CAR | TIOCM_DSR; + + return ret; +} + static int byt_serial_setup(struct serial_private *priv, const struct pciserial_board *board, @@ -1458,11 +1454,13 @@ byt_serial_setup(struct serial_private *priv, switch (pdev->device) { case PCI_DEVICE_ID_INTEL_BYT_UART1: case PCI_DEVICE_ID_INTEL_BSW_UART1: + case PCI_DEVICE_ID_INTEL_BDW_UART1: rx_param->src_id = 3; tx_param->dst_id = 2; break; case PCI_DEVICE_ID_INTEL_BYT_UART2: case PCI_DEVICE_ID_INTEL_BSW_UART2: + case PCI_DEVICE_ID_INTEL_BDW_UART2: rx_param->src_id = 5; tx_param->dst_id = 4; break; @@ -1470,13 +1468,13 @@ byt_serial_setup(struct serial_private *priv, return -EINVAL; } - rx_param->src_master = 1; - rx_param->dst_master = 0; + rx_param->m_master = 0; + rx_param->p_master = 1; dma->rxconf.src_maxburst = 16; - tx_param->src_master = 1; - tx_param->dst_master = 0; + tx_param->m_master = 0; + tx_param->p_master = 1; dma->txconf.dst_maxburst = 16; @@ -1493,6 +1491,7 @@ byt_serial_setup(struct serial_private *priv, port->port.type = PORT_16550A; port->port.flags = (port->port.flags | UPF_FIXED_PORT | UPF_FIXED_TYPE); port->port.set_termios = byt_set_termios; + port->port.get_mctrl = byt_get_mctrl; port->port.fifosize = 64; port->tx_loadsz = 64; port->dma = dma; @@ -1504,185 +1503,76 @@ byt_serial_setup(struct serial_private *priv, return ret; } -#define INTEL_MID_UART_PS 0x30 -#define INTEL_MID_UART_MUL 0x34 -#define INTEL_MID_UART_DIV 0x38 - -static void intel_mid_set_termios(struct uart_port *p, - struct ktermios *termios, - struct ktermios *old, - unsigned long fref) +static int +pci_omegapci_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) { - unsigned int baud = tty_termios_baud_rate(termios); - unsigned short ps = 16; - unsigned long fuart = baud * ps; - unsigned long w = BIT(24) - 1; - unsigned long mul, div; - - if (fref < fuart) { - /* Find prescaler value that satisfies Fuart < Fref */ - if (fref > baud) - ps = fref / baud; /* baud rate too high */ - else - ps = 1; /* PLL case */ - fuart = baud * ps; - } else { - /* Get Fuart closer to Fref */ - fuart *= rounddown_pow_of_two(fref / fuart); - } - - rational_best_approximation(fuart, fref, w, w, &mul, &div); - p->uartclk = fuart * 16 / ps; /* core uses ps = 16 always */ - - writel(ps, p->membase + INTEL_MID_UART_PS); /* set PS */ - writel(mul, p->membase + INTEL_MID_UART_MUL); /* set MUL */ - writel(div, p->membase + INTEL_MID_UART_DIV); - - serial8250_do_set_termios(p, termios, old); + return setup_port(priv, port, 2, idx * 8, 0); } -static void intel_mid_set_termios_38_4M(struct uart_port *p, - struct ktermios *termios, - struct ktermios *old) +static int +pci_brcm_trumanage_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) { - intel_mid_set_termios(p, termios, old, 38400000); -} + int ret = pci_default_setup(priv, board, port, idx); -static void intel_mid_set_termios_50M(struct uart_port *p, - struct ktermios *termios, - struct ktermios *old) -{ - /* - * The uart clk is 50Mhz, and the baud rate come from: - * baud = 50M * MUL / (DIV * PS * DLAB) - */ - intel_mid_set_termios(p, termios, old, 50000000); + port->port.type = PORT_BRCM_TRUMANAGE; + port->port.flags = (port->port.flags | UPF_FIXED_PORT | UPF_FIXED_TYPE); + return ret; } -static bool intel_mid_dma_filter(struct dma_chan *chan, void *param) -{ - struct hsu_dma_slave *s = param; - - if (s->dma_dev != chan->device->dev || s->chan_id != chan->chan_id) - return false; +/* RTS will control by MCR if this bit is 0 */ +#define FINTEK_RTS_CONTROL_BY_HW BIT(4) +/* only worked with FINTEK_RTS_CONTROL_BY_HW on */ +#define FINTEK_RTS_INVERT BIT(5) - chan->private = s; - return true; -} - -static int intel_mid_serial_setup(struct serial_private *priv, - const struct pciserial_board *board, - struct uart_8250_port *port, int idx, - int index, struct pci_dev *dma_dev) +/* We should do proper H/W transceiver setting before change to RS485 mode */ +static int pci_fintek_rs485_config(struct uart_port *port, + struct serial_rs485 *rs485) { - struct device *dev = port->port.dev; - struct uart_8250_dma *dma; - struct hsu_dma_slave *tx_param, *rx_param; - - dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL); - if (!dma) - return -ENOMEM; - - tx_param = devm_kzalloc(dev, sizeof(*tx_param), GFP_KERNEL); - if (!tx_param) - return -ENOMEM; - - rx_param = devm_kzalloc(dev, sizeof(*rx_param), GFP_KERNEL); - if (!rx_param) - return -ENOMEM; - - rx_param->chan_id = index * 2 + 1; - tx_param->chan_id = index * 2; + struct pci_dev *pci_dev = to_pci_dev(port->dev); + u8 setting; + u8 *index = (u8 *) port->private_data; - dma->rxconf.src_maxburst = 64; - dma->txconf.dst_maxburst = 64; - - rx_param->dma_dev = &dma_dev->dev; - tx_param->dma_dev = &dma_dev->dev; - - dma->fn = intel_mid_dma_filter; - dma->rx_param = rx_param; - dma->tx_param = tx_param; + pci_read_config_byte(pci_dev, 0x40 + 8 * *index + 7, &setting); - port->port.type = PORT_16750; - port->port.flags |= UPF_FIXED_PORT | UPF_FIXED_TYPE; - port->dma = dma; + if (!rs485) + rs485 = &port->rs485; + else if (rs485->flags & SER_RS485_ENABLED) + memset(rs485->padding, 0, sizeof(rs485->padding)); + else + memset(rs485, 0, sizeof(*rs485)); - return pci_default_setup(priv, board, port, idx); -} + /* F81504/508/512 not support RTS delay before or after send */ + rs485->flags &= SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND; -#define PCI_DEVICE_ID_INTEL_PNW_UART1 0x081b -#define PCI_DEVICE_ID_INTEL_PNW_UART2 0x081c -#define PCI_DEVICE_ID_INTEL_PNW_UART3 0x081d + if (rs485->flags & SER_RS485_ENABLED) { + /* Enable RTS H/W control mode */ + setting |= FINTEK_RTS_CONTROL_BY_HW; -static int pnw_serial_setup(struct serial_private *priv, - const struct pciserial_board *board, - struct uart_8250_port *port, int idx) -{ - struct pci_dev *pdev = priv->dev; - struct pci_dev *dma_dev; - int index; + if (rs485->flags & SER_RS485_RTS_ON_SEND) { + /* RTS driving high on TX */ + setting &= ~FINTEK_RTS_INVERT; + } else { + /* RTS driving low on TX */ + setting |= FINTEK_RTS_INVERT; + } - switch (pdev->device) { - case PCI_DEVICE_ID_INTEL_PNW_UART1: - index = 0; - break; - case PCI_DEVICE_ID_INTEL_PNW_UART2: - index = 1; - break; - case PCI_DEVICE_ID_INTEL_PNW_UART3: - index = 2; - break; - default: - return -EINVAL; + rs485->delay_rts_after_send = 0; + rs485->delay_rts_before_send = 0; + } else { + /* Disable RTS H/W control mode */ + setting &= ~(FINTEK_RTS_CONTROL_BY_HW | FINTEK_RTS_INVERT); } - dma_dev = pci_get_slot(pdev->bus, PCI_DEVFN(PCI_SLOT(pdev->devfn), 3)); - - port->port.set_termios = intel_mid_set_termios_50M; - - return intel_mid_serial_setup(priv, board, port, idx, index, dma_dev); -} - -#define PCI_DEVICE_ID_INTEL_TNG_UART 0x1191 - -static int tng_serial_setup(struct serial_private *priv, - const struct pciserial_board *board, - struct uart_8250_port *port, int idx) -{ - struct pci_dev *pdev = priv->dev; - struct pci_dev *dma_dev; - int index = PCI_FUNC(pdev->devfn); - - /* Currently no support for HSU port0 */ - if (index-- == 0) - return -ENODEV; - - dma_dev = pci_get_slot(pdev->bus, PCI_DEVFN(5, 0)); + pci_write_config_byte(pci_dev, 0x40 + 8 * *index + 7, setting); - port->port.set_termios = intel_mid_set_termios_38_4M; + if (rs485 != &port->rs485) + port->rs485 = *rs485; - return intel_mid_serial_setup(priv, board, port, idx, index, dma_dev); -} - -static int -pci_omegapci_setup(struct serial_private *priv, - const struct pciserial_board *board, - struct uart_8250_port *port, int idx) -{ - return setup_port(priv, port, 2, idx * 8, 0); -} - -static int -pci_brcm_trumanage_setup(struct serial_private *priv, - const struct pciserial_board *board, - struct uart_8250_port *port, int idx) -{ - int ret = pci_default_setup(priv, board, port, idx); - - port->port.type = PORT_BRCM_TRUMANAGE; - port->port.flags = (port->port.flags | UPF_FIXED_PORT | UPF_FIXED_TYPE); - return ret; + return 0; } static int pci_fintek_setup(struct serial_private *priv, @@ -1690,6 +1580,7 @@ static int pci_fintek_setup(struct serial_private *priv, struct uart_8250_port *port, int idx) { struct pci_dev *pdev = priv->dev; + u8 *data; u8 config_base; u16 iobase; @@ -1702,6 +1593,15 @@ static int pci_fintek_setup(struct serial_private *priv, port->port.iotype = UPIO_PORT; port->port.iobase = iobase; + port->port.rs485_config = pci_fintek_rs485_config; + + data = devm_kzalloc(&pdev->dev, sizeof(u8), GFP_KERNEL); + if (!data) + return -ENOMEM; + + /* preserve index in PCI configuration space */ + *data = idx; + port->port.private_data = data; return 0; } @@ -1712,6 +1612,8 @@ static int pci_fintek_init(struct pci_dev *dev) u32 max_port, i; u32 bar_data[3]; u8 config_base; + struct serial_private *priv = pci_get_drvdata(dev); + struct uart_8250_port *port; switch (dev->device) { case 0x1104: /* 4 ports */ @@ -1752,6 +1654,19 @@ static int pci_fintek_init(struct pci_dev *dev) (u8)((iobase & 0xff00) >> 8)); pci_write_config_byte(dev, config_base + 0x06, dev->irq); + + if (priv) { + /* re-apply RS232/485 mode when + * pciserial_resume_ports() + */ + port = serial8250_get_port(priv->line[i]); + pci_fintek_rs485_config(&port->port, NULL); + } else { + /* First init without port data + * force init to RS232 Mode + */ + pci_write_config_byte(dev, config_base + 0x07, 0x01); + } } return max_port; @@ -1823,6 +1738,9 @@ static int pci_eg20t_init(struct pci_dev *dev) #endif } +#define PCI_DEVICE_ID_EXAR_XR17V4358 0x4358 +#define PCI_DEVICE_ID_EXAR_XR17V8358 0x8358 + static int pci_xr17c154_setup(struct serial_private *priv, const struct pciserial_board *board, @@ -1832,6 +1750,15 @@ pci_xr17c154_setup(struct serial_private *priv, return pci_default_setup(priv, board, port, idx); } +static inline int +xr17v35x_has_slave(struct serial_private *priv) +{ + const int dev_id = priv->dev->device; + + return ((dev_id == PCI_DEVICE_ID_EXAR_XR17V4358) || + (dev_id == PCI_DEVICE_ID_EXAR_XR17V8358)); +} + static int pci_xr17v35x_setup(struct serial_private *priv, const struct pciserial_board *board, @@ -1846,6 +1773,13 @@ pci_xr17v35x_setup(struct serial_private *priv, port->port.flags |= UPF_EXAR_EFR; /* + * Setup the uart clock for the devices on expansion slot to + * half the clock speed of the main chip (which is 125MHz) + */ + if (xr17v35x_has_slave(priv) && idx >= 8) + port->port.uartclk = (7812500 * 16 / 2); + + /* * Setup Multipurpose Input/Output pins. */ if (idx == 0) { @@ -1922,8 +1856,18 @@ pci_fastcom335_setup(struct serial_private *priv, static int pci_wch_ch353_setup(struct serial_private *priv, - const struct pciserial_board *board, - struct uart_8250_port *port, int idx) + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + port->port.flags |= UPF_FIXED_TYPE; + port->port.type = PORT_16550A; + return pci_default_setup(priv, board, port, idx); +} + +static int +pci_wch_ch355_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) { port->port.flags |= UPF_FIXED_TYPE; port->port.type = PORT_16550A; @@ -1932,8 +1876,8 @@ pci_wch_ch353_setup(struct serial_private *priv, static int pci_wch_ch38x_setup(struct serial_private *priv, - const struct pciserial_board *board, - struct uart_8250_port *port, int idx) + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) { port->port.flags |= UPF_FIXED_TYPE; port->port.type = PORT_16850; @@ -1981,6 +1925,7 @@ pci_wch_ch38x_setup(struct serial_private *priv, #define PCI_DEVICE_ID_WCH_CH353_2S1PF 0x5046 #define PCI_DEVICE_ID_WCH_CH353_1S1P 0x5053 #define PCI_DEVICE_ID_WCH_CH353_2S1P 0x7053 +#define PCI_DEVICE_ID_WCH_CH355_4S 0x7173 #define PCI_VENDOR_ID_AGESTAR 0x5372 #define PCI_DEVICE_ID_AGESTAR_9375 0x6872 #define PCI_VENDOR_ID_ASIX 0x9710 @@ -1997,8 +1942,50 @@ pci_wch_ch38x_setup(struct serial_private *priv, #define PCIE_VENDOR_ID_WCH 0x1c00 #define PCIE_DEVICE_ID_WCH_CH382_2S1P 0x3250 #define PCIE_DEVICE_ID_WCH_CH384_4S 0x3470 +#define PCIE_DEVICE_ID_WCH_CH382_2S 0x3253 + +#define PCI_VENDOR_ID_PERICOM 0x12D8 +#define PCI_DEVICE_ID_PERICOM_PI7C9X7951 0x7951 +#define PCI_DEVICE_ID_PERICOM_PI7C9X7952 0x7952 +#define PCI_DEVICE_ID_PERICOM_PI7C9X7954 0x7954 +#define PCI_DEVICE_ID_PERICOM_PI7C9X7958 0x7958 + +#define PCI_VENDOR_ID_ACCESIO 0x494f +#define PCI_DEVICE_ID_ACCESIO_PCIE_COM_2SDB 0x1051 +#define PCI_DEVICE_ID_ACCESIO_MPCIE_COM_2S 0x1053 +#define PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SDB 0x105C +#define PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4S 0x105E +#define PCI_DEVICE_ID_ACCESIO_PCIE_COM232_2DB 0x1091 +#define PCI_DEVICE_ID_ACCESIO_MPCIE_COM232_2 0x1093 +#define PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4DB 0x1099 +#define PCI_DEVICE_ID_ACCESIO_MPCIE_COM232_4 0x109B +#define PCI_DEVICE_ID_ACCESIO_PCIE_COM_2SMDB 0x10D1 +#define PCI_DEVICE_ID_ACCESIO_MPCIE_COM_2SM 0x10D3 +#define PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SMDB 0x10DA +#define PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4SM 0x10DC +#define PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_1 0x1108 +#define PCI_DEVICE_ID_ACCESIO_MPCIE_ICM422_2 0x1110 +#define PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_2 0x1111 +#define PCI_DEVICE_ID_ACCESIO_MPCIE_ICM422_4 0x1118 +#define PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_4 0x1119 +#define PCI_DEVICE_ID_ACCESIO_PCIE_ICM_2S 0x1152 +#define PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4S 0x115A +#define PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_2 0x1190 +#define PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_2 0x1191 +#define PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_4 0x1198 +#define PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_4 0x1199 +#define PCI_DEVICE_ID_ACCESIO_PCIE_ICM_2SM 0x11D0 +#define PCI_DEVICE_ID_ACCESIO_PCIE_COM422_4 0x105A +#define PCI_DEVICE_ID_ACCESIO_PCIE_COM485_4 0x105B +#define PCI_DEVICE_ID_ACCESIO_PCIE_COM422_8 0x106A +#define PCI_DEVICE_ID_ACCESIO_PCIE_COM485_8 0x106B +#define PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4 0x1098 +#define PCI_DEVICE_ID_ACCESIO_PCIE_COM232_8 0x10A9 +#define PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SM 0x10D9 +#define PCI_DEVICE_ID_ACCESIO_PCIE_COM_8SM 0x10E9 +#define PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4SM 0x11D8 + -#define PCI_DEVICE_ID_EXAR_XR17V8358 0x8358 /* Unknown vendors/cards - this should not be in linux/pci_ids.h */ #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584 @@ -2107,42 +2094,28 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { }, { .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_PNW_UART1, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pnw_serial_setup, - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_PNW_UART2, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pnw_serial_setup, - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_PNW_UART3, + .device = PCI_DEVICE_ID_INTEL_BSW_UART1, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .setup = pnw_serial_setup, + .setup = byt_serial_setup, }, { .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_TNG_UART, + .device = PCI_DEVICE_ID_INTEL_BSW_UART2, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .setup = tng_serial_setup, + .setup = byt_serial_setup, }, { .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_BSW_UART1, + .device = PCI_DEVICE_ID_INTEL_BDW_UART1, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, .setup = byt_serial_setup, }, { .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_BSW_UART2, + .device = PCI_DEVICE_ID_INTEL_BDW_UART2, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, .setup = byt_serial_setup, @@ -2311,31 +2284,6 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { .exit = pci_plx9050_exit, }, /* - * Pericom - */ - { - .vendor = 0x12d8, - .device = 0x7952, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup, - }, - { - .vendor = 0x12d8, - .device = 0x7954, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup, - }, - { - .vendor = 0x12d8, - .device = 0x7958, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup, - }, - - /* * PLX */ { @@ -2524,6 +2472,13 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { }, { .vendor = PCI_VENDOR_ID_EXAR, + .device = PCI_DEVICE_ID_EXAR_XR17V4358, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_xr17v35x_setup, + }, + { + .vendor = PCI_VENDOR_ID_EXAR, .device = PCI_DEVICE_ID_EXAR_XR17V8358, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, @@ -2711,6 +2666,22 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { .subdevice = PCI_ANY_ID, .setup = pci_wch_ch353_setup, }, + /* WCH CH355 4S card (16550 clone) */ + { + .vendor = PCI_VENDOR_ID_WCH, + .device = PCI_DEVICE_ID_WCH_CH355_4S, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_wch_ch355_setup, + }, + /* WCH CH382 2S card (16850 clone) */ + { + .vendor = PCIE_VENDOR_ID_WCH, + .device = PCIE_DEVICE_ID_WCH_CH382_2S, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_wch_ch38x_setup, + }, /* WCH CH382 2S1P card (16850 clone) */ { .vendor = PCIE_VENDOR_ID_WCH, @@ -3008,6 +2979,7 @@ enum pci_board_num_t { pbn_exar_XR17V352, pbn_exar_XR17V354, pbn_exar_XR17V358, + pbn_exar_XR17V4358, pbn_exar_XR17V8358, pbn_exar_ibm_saturn, pbn_pasemi_1682M, @@ -3021,8 +2993,6 @@ enum pci_board_num_t { pbn_ADDIDATA_PCIe_8_3906250, pbn_ce4100_1_115200, pbn_byt, - pbn_pnw, - pbn_tng, pbn_qrk, pbn_omegapci, pbn_NETMOS9900_2s_115200, @@ -3030,7 +3000,12 @@ enum pci_board_num_t { pbn_fintek_4, pbn_fintek_8, pbn_fintek_12, + pbn_wch382_2, pbn_wch384_4, + pbn_pericom_PI7C9X7951, + pbn_pericom_PI7C9X7952, + pbn_pericom_PI7C9X7954, + pbn_pericom_PI7C9X7958, }; /* @@ -3695,6 +3670,14 @@ static struct pciserial_board pci_boards[] = { .reg_shift = 0, .first_offset = 0, }, + [pbn_exar_XR17V4358] = { + .flags = FL_BASE0, + .num_ports = 12, + .base_baud = 7812500, + .uart_offset = 0x400, + .reg_shift = 0, + .first_offset = 0, + }, [pbn_exar_XR17V8358] = { .flags = FL_BASE0, .num_ports = 16, @@ -3786,27 +3769,12 @@ static struct pciserial_board pci_boards[] = { .base_baud = 921600, .reg_shift = 2, }, - /* - * Intel BayTrail HSUART reference clock is 44.2368 MHz at power-on, - * but is overridden by byt_set_termios. - */ [pbn_byt] = { .flags = FL_BASE0, .num_ports = 1, .base_baud = 2764800, - .uart_offset = 0x80, .reg_shift = 2, }, - [pbn_pnw] = { - .flags = FL_BASE0, - .num_ports = 1, - .base_baud = 115200, - }, - [pbn_tng] = { - .flags = FL_BASE0, - .num_ports = 1, - .base_baud = 1843200, - }, [pbn_qrk] = { .flags = FL_BASE0, .num_ports = 1, @@ -3848,7 +3816,13 @@ static struct pciserial_board pci_boards[] = { .base_baud = 115200, .first_offset = 0x40, }, - + [pbn_wch382_2] = { + .flags = FL_BASE0, + .num_ports = 2, + .base_baud = 115200, + .uart_offset = 8, + .first_offset = 0xC0, + }, [pbn_wch384_4] = { .flags = FL_BASE0, .num_ports = 4, @@ -3856,6 +3830,33 @@ static struct pciserial_board pci_boards[] = { .uart_offset = 8, .first_offset = 0xC0, }, + /* + * Pericom PI7C9X795[1248] Uno/Dual/Quad/Octal UART + */ + [pbn_pericom_PI7C9X7951] = { + .flags = FL_BASE0, + .num_ports = 1, + .base_baud = 921600, + .uart_offset = 0x8, + }, + [pbn_pericom_PI7C9X7952] = { + .flags = FL_BASE0, + .num_ports = 2, + .base_baud = 921600, + .uart_offset = 0x8, + }, + [pbn_pericom_PI7C9X7954] = { + .flags = FL_BASE0, + .num_ports = 4, + .base_baud = 921600, + .uart_offset = 0x8, + }, + [pbn_pericom_PI7C9X7958] = { + .flags = FL_BASE0, + .num_ports = 8, + .base_baud = 921600, + .uart_offset = 0x8, + }, }; static const struct pci_device_id blacklist[] = { @@ -3867,8 +3868,30 @@ static const struct pci_device_id blacklist[] = { /* multi-io cards handled by parport_serial */ { PCI_DEVICE(0x4348, 0x7053), }, /* WCH CH353 2S1P */ { PCI_DEVICE(0x4348, 0x5053), }, /* WCH CH353 1S1P */ + { PCI_DEVICE(0x4348, 0x7173), }, /* WCH CH355 4S */ { PCI_DEVICE(0x1c00, 0x3250), }, /* WCH CH382 2S1P */ { PCI_DEVICE(0x1c00, 0x3470), }, /* WCH CH384 4S */ + + /* Moxa Smartio MUE boards handled by 8250_moxa */ + { PCI_VDEVICE(MOXA, 0x1024), }, + { PCI_VDEVICE(MOXA, 0x1025), }, + { PCI_VDEVICE(MOXA, 0x1045), }, + { PCI_VDEVICE(MOXA, 0x1144), }, + { PCI_VDEVICE(MOXA, 0x1160), }, + { PCI_VDEVICE(MOXA, 0x1161), }, + { PCI_VDEVICE(MOXA, 0x1182), }, + { PCI_VDEVICE(MOXA, 0x1183), }, + { PCI_VDEVICE(MOXA, 0x1322), }, + { PCI_VDEVICE(MOXA, 0x1342), }, + { PCI_VDEVICE(MOXA, 0x1381), }, + { PCI_VDEVICE(MOXA, 0x1683), }, + + /* Intel platforms with MID UART */ + { PCI_VDEVICE(INTEL, 0x081b), }, + { PCI_VDEVICE(INTEL, 0x081c), }, + { PCI_VDEVICE(INTEL, 0x081d), }, + { PCI_VDEVICE(INTEL, 0x1191), }, + { PCI_VDEVICE(INTEL, 0x19d8), }, }; /* @@ -4050,12 +4073,6 @@ void pciserial_remove_ports(struct serial_private *priv) for (i = 0; i < priv->nr; i++) serial8250_unregister_port(priv->line[i]); - for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) { - if (priv->remapped_bar[i]) - iounmap(priv->remapped_bar[i]); - priv->remapped_bar[i] = NULL; - } - /* * Find the exit quirks. */ @@ -4127,7 +4144,7 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent) board = &pci_boards[ent->driver_data]; - rc = pci_enable_device(dev); + rc = pcim_enable_device(dev); pci_save_state(dev); if (rc) return rc; @@ -4146,7 +4163,7 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent) */ rc = serial_pci_guess_board(dev, &tmp); if (rc) - goto disable; + return rc; } else { /* * We matched an explicit entry. If we are able to @@ -4162,16 +4179,11 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent) } priv = pciserial_init_ports(dev, board); - if (!IS_ERR(priv)) { - pci_set_drvdata(dev, priv); - return 0; - } + if (IS_ERR(priv)) + return PTR_ERR(priv); - rc = PTR_ERR(priv); - - disable: - pci_disable_device(dev); - return rc; + pci_set_drvdata(dev, priv); + return 0; } static void pciserial_remove_one(struct pci_dev *dev) @@ -4179,8 +4191,6 @@ static void pciserial_remove_one(struct pci_dev *dev) struct serial_private *priv = pci_get_drvdata(dev); pciserial_remove_ports(priv); - - pci_disable_device(dev); } #ifdef CONFIG_PM_SLEEP @@ -4561,7 +4571,7 @@ static struct pci_device_id serial_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_bt_2_921600 }, { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI958, - PCI_ANY_ID , PCI_ANY_ID, 0, 0, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b2_8_1152000 }, /* @@ -5112,11 +5122,136 @@ static struct pci_device_id serial_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_exar_XR17V358 }, + { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V4358, + PCI_ANY_ID, PCI_ANY_ID, + 0, + 0, pbn_exar_XR17V4358 }, { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V8358, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_exar_XR17V8358 }, /* + * Pericom PI7C9X795[1248] Uno/Dual/Quad/Octal UART + */ + { PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7951, + PCI_ANY_ID, PCI_ANY_ID, + 0, + 0, pbn_pericom_PI7C9X7951 }, + { PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7952, + PCI_ANY_ID, PCI_ANY_ID, + 0, + 0, pbn_pericom_PI7C9X7952 }, + { PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7954, + PCI_ANY_ID, PCI_ANY_ID, + 0, + 0, pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7958, + PCI_ANY_ID, PCI_ANY_ID, + 0, + 0, pbn_pericom_PI7C9X7958 }, + /* + * ACCES I/O Products quad + */ + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_2SDB, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_COM_2S, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SDB, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4S, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM232_2DB, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_COM232_2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4DB, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_COM232_4, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_2SMDB, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_COM_2SM, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SMDB, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4SM, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_1, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM422_2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM422_4, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_4, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM_2S, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4S, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_4, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_4, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM_2SM, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM422_4, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7958 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM485_4, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7958 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM422_8, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7958 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM485_8, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7958 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7958 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM232_8, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7958 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SM, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7958 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_8SM, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7958 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4SM, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7958 }, + /* * Topic TP560 Data/Fax/Voice 56k modem (reported by Evan Clarke) */ { PCI_VENDOR_ID_TOPIC, PCI_DEVICE_ID_TOPIC_TP560, @@ -5542,25 +5677,15 @@ static struct pci_device_id serial_pci_tbl[] = { PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000, pbn_byt }, - /* - * Intel Penwell - */ - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PNW_UART1, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pnw}, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PNW_UART2, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pnw}, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PNW_UART3, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pnw}, - - /* - * Intel Tangier - */ - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TNG_UART, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_tng}, + /* Intel Broadwell */ + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BDW_UART1, + PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000, + pbn_byt }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BDW_UART2, + PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000, + pbn_byt }, /* * Intel Quark x1000 @@ -5601,6 +5726,14 @@ static struct pci_device_id serial_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_bt_2_115200 }, + { PCI_VENDOR_ID_WCH, PCI_DEVICE_ID_WCH_CH355_4S, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, pbn_b0_bt_4_115200 }, + + { PCIE_VENDOR_ID_WCH, PCIE_DEVICE_ID_WCH_CH382_2S, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, pbn_wch382_2 }, + { PCIE_VENDOR_ID_WCH, PCIE_DEVICE_ID_WCH_CH384_4S, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_wch384_4 }, diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c index 50a09cd76..34f05ed78 100644 --- a/drivers/tty/serial/8250/8250_pnp.c +++ b/drivers/tty/serial/8250/8250_pnp.c @@ -41,6 +41,12 @@ static const struct pnp_device_id pnp_dev_table[] = { { "AEI1240", 0 }, /* Rockwell 56K ACF II Fax+Data+Voice Modem */ { "AKY1021", 0 /*SPCI_FL_NO_SHIRQ*/ }, + /* + * ALi Fast Infrared Controller + * Native driver (ali-ircc) is broken so at least + * it can be used with irtty-sir. + */ + { "ALI5123", 0 }, /* AZT3005 PnP SOUND DEVICE */ { "AZT4001", 0 }, /* Best Data Products Inc. Smart One 336F PnP Modem */ @@ -351,8 +357,8 @@ static const struct pnp_device_id pnp_dev_table[] = { /* Fujitsu Wacom 1FGT Tablet PC device */ { "FUJ02E9", 0 }, /* - * LG C1 EXPRESS DUAL (C1-PB11A3) touch screen (actually a FUJ02E6 in - * disguise) + * LG C1 EXPRESS DUAL (C1-PB11A3) touch screen (actually a FUJ02E6 + * in disguise). */ { "LTS0001", 0 }, /* Rockwell's (PORALiNK) 33600 INT PNP */ @@ -361,43 +367,50 @@ static const struct pnp_device_id pnp_dev_table[] = { { "PNPCXXX", UNKNOWN_DEV }, /* More unknown PnP modems */ { "PNPDXXX", UNKNOWN_DEV }, - /* Winbond CIR port, should not be probed. We should keep track - of it to prevent the legacy serial driver from probing it */ + /* + * Winbond CIR port, should not be probed. We should keep track of + * it to prevent the legacy serial driver from probing it. + */ { "WEC1022", CIR_PORT }, + /* + * SMSC IrCC SIR/FIR port, should not be probed by serial driver as + * well so its own driver can bind to it. + */ + { "SMCF010", CIR_PORT }, { "", 0 } }; MODULE_DEVICE_TABLE(pnp, pnp_dev_table); -static char *modem_names[] = { +static const char *modem_names[] = { "MODEM", "Modem", "modem", "FAX", "Fax", "fax", "56K", "56k", "K56", "33.6", "28.8", "14.4", "33,600", "28,800", "14,400", "33.600", "28.800", "14.400", "33600", "28800", "14400", "V.90", "V.34", "V.32", NULL }; -static int check_name(char *name) +static bool check_name(const char *name) { - char **tmp; + const char **tmp; for (tmp = modem_names; *tmp; tmp++) if (strstr(name, *tmp)) - return 1; + return true; - return 0; + return false; } -static int check_resources(struct pnp_dev *dev) +static bool check_resources(struct pnp_dev *dev) { - resource_size_t base[] = {0x2f8, 0x3f8, 0x2e8, 0x3e8}; - int i; + static const resource_size_t base[] = {0x2f8, 0x3f8, 0x2e8, 0x3e8}; + unsigned int i; for (i = 0; i < ARRAY_SIZE(base); i++) { if (pnp_possible_config(dev, IORESOURCE_IO, base[i], 8)) - return 1; + return true; } - return 0; + return false; } /* @@ -414,8 +427,8 @@ static int check_resources(struct pnp_dev *dev) static int serial_pnp_guess_board(struct pnp_dev *dev) { if (!(check_name(pnp_dev_name(dev)) || - (dev->card && check_name(dev->card->name)))) - return -ENODEV; + (dev->card && check_name(dev->card->name)))) + return -ENODEV; if (check_resources(dev)) return 0; @@ -451,11 +464,11 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) } else return -ENODEV; -#ifdef SERIAL_DEBUG_PNP - printk(KERN_DEBUG - "Setup PNP port: port %x, mem 0x%lx, irq %d, type %d\n", - uart.port.iobase, uart.port.mapbase, uart.port.irq, uart.port.iotype); -#endif + dev_dbg(&dev->dev, + "Setup PNP port: port %lx, mem %pa, irq %d, type %d\n", + uart.port.iobase, &uart.port.mapbase, + uart.port.irq, uart.port.iotype); + if (flags & CIR_PORT) { uart.port.flags |= UPF_FIXED_PORT | UPF_FIXED_TYPE; uart.port.type = PORT_8250_CIR; diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c new file mode 100644 index 000000000..858a54633 --- /dev/null +++ b/drivers/tty/serial/8250/8250_port.c @@ -0,0 +1,3194 @@ +/* + * Base port operations for 8250/16550-type serial ports + * + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. + * Split from 8250_core.c, Copyright (C) 2001 Russell King. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * A note about mapbase / membase + * + * mapbase is the physical address of the IO port. + * membase is an 'ioremapped' cookie. + */ + +#if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/ioport.h> +#include <linux/init.h> +#include <linux/console.h> +#include <linux/sysrq.h> +#include <linux/delay.h> +#include <linux/platform_device.h> +#include <linux/tty.h> +#include <linux/ratelimit.h> +#include <linux/tty_flip.h> +#include <linux/serial.h> +#include <linux/serial_8250.h> +#include <linux/nmi.h> +#include <linux/mutex.h> +#include <linux/slab.h> +#include <linux/uaccess.h> +#include <linux/pm_runtime.h> +#include <linux/timer.h> + +#include <asm/io.h> +#include <asm/irq.h> + +#include "8250.h" + +/* + * Debugging. + */ +#if 0 +#define DEBUG_AUTOCONF(fmt...) printk(fmt) +#else +#define DEBUG_AUTOCONF(fmt...) do { } while (0) +#endif + +#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) + +/* + * Here we define the default xmit fifo size used for each type of UART. + */ +static const struct serial8250_config uart_config[] = { + [PORT_UNKNOWN] = { + .name = "unknown", + .fifo_size = 1, + .tx_loadsz = 1, + }, + [PORT_8250] = { + .name = "8250", + .fifo_size = 1, + .tx_loadsz = 1, + }, + [PORT_16450] = { + .name = "16450", + .fifo_size = 1, + .tx_loadsz = 1, + }, + [PORT_16550] = { + .name = "16550", + .fifo_size = 1, + .tx_loadsz = 1, + }, + [PORT_16550A] = { + .name = "16550A", + .fifo_size = 16, + .tx_loadsz = 16, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, + .rxtrig_bytes = {1, 4, 8, 14}, + .flags = UART_CAP_FIFO, + }, + [PORT_CIRRUS] = { + .name = "Cirrus", + .fifo_size = 1, + .tx_loadsz = 1, + }, + [PORT_16650] = { + .name = "ST16650", + .fifo_size = 1, + .tx_loadsz = 1, + .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP, + }, + [PORT_16650V2] = { + .name = "ST16650V2", + .fifo_size = 32, + .tx_loadsz = 16, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 | + UART_FCR_T_TRIG_00, + .rxtrig_bytes = {8, 16, 24, 28}, + .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP, + }, + [PORT_16750] = { + .name = "TI16750", + .fifo_size = 64, + .tx_loadsz = 64, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 | + UART_FCR7_64BYTE, + .rxtrig_bytes = {1, 16, 32, 56}, + .flags = UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_AFE, + }, + [PORT_STARTECH] = { + .name = "Startech", + .fifo_size = 1, + .tx_loadsz = 1, + }, + [PORT_16C950] = { + .name = "16C950/954", + .fifo_size = 128, + .tx_loadsz = 128, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, + /* UART_CAP_EFR breaks billionon CF bluetooth card. */ + .flags = UART_CAP_FIFO | UART_CAP_SLEEP, + }, + [PORT_16654] = { + .name = "ST16654", + .fifo_size = 64, + .tx_loadsz = 32, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 | + UART_FCR_T_TRIG_10, + .rxtrig_bytes = {8, 16, 56, 60}, + .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP, + }, + [PORT_16850] = { + .name = "XR16850", + .fifo_size = 128, + .tx_loadsz = 128, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, + .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP, + }, + [PORT_RSA] = { + .name = "RSA", + .fifo_size = 2048, + .tx_loadsz = 2048, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_11, + .flags = UART_CAP_FIFO, + }, + [PORT_NS16550A] = { + .name = "NS16550A", + .fifo_size = 16, + .tx_loadsz = 16, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, + .flags = UART_CAP_FIFO | UART_NATSEMI, + }, + [PORT_XSCALE] = { + .name = "XScale", + .fifo_size = 32, + .tx_loadsz = 32, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, + .flags = UART_CAP_FIFO | UART_CAP_UUE | UART_CAP_RTOIE, + }, + [PORT_OCTEON] = { + .name = "OCTEON", + .fifo_size = 64, + .tx_loadsz = 64, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, + .flags = UART_CAP_FIFO, + }, + [PORT_AR7] = { + .name = "AR7", + .fifo_size = 16, + .tx_loadsz = 16, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00, + .flags = UART_CAP_FIFO | UART_CAP_AFE, + }, + [PORT_U6_16550A] = { + .name = "U6_16550A", + .fifo_size = 64, + .tx_loadsz = 64, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, + .flags = UART_CAP_FIFO | UART_CAP_AFE, + }, + [PORT_TEGRA] = { + .name = "Tegra", + .fifo_size = 32, + .tx_loadsz = 8, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 | + UART_FCR_T_TRIG_01, + .rxtrig_bytes = {1, 4, 8, 14}, + .flags = UART_CAP_FIFO | UART_CAP_RTOIE, + }, + [PORT_XR17D15X] = { + .name = "XR17D15X", + .fifo_size = 64, + .tx_loadsz = 64, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, + .flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR | + UART_CAP_SLEEP, + }, + [PORT_XR17V35X] = { + .name = "XR17V35X", + .fifo_size = 256, + .tx_loadsz = 256, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_11 | + UART_FCR_T_TRIG_11, + .flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR | + UART_CAP_SLEEP, + }, + [PORT_LPC3220] = { + .name = "LPC3220", + .fifo_size = 64, + .tx_loadsz = 32, + .fcr = UART_FCR_DMA_SELECT | UART_FCR_ENABLE_FIFO | + UART_FCR_R_TRIG_00 | UART_FCR_T_TRIG_00, + .flags = UART_CAP_FIFO, + }, + [PORT_BRCM_TRUMANAGE] = { + .name = "TruManage", + .fifo_size = 1, + .tx_loadsz = 1024, + .flags = UART_CAP_HFIFO, + }, + [PORT_8250_CIR] = { + .name = "CIR port" + }, + [PORT_ALTR_16550_F32] = { + .name = "Altera 16550 FIFO32", + .fifo_size = 32, + .tx_loadsz = 32, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, + .flags = UART_CAP_FIFO | UART_CAP_AFE, + }, + [PORT_ALTR_16550_F64] = { + .name = "Altera 16550 FIFO64", + .fifo_size = 64, + .tx_loadsz = 64, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, + .flags = UART_CAP_FIFO | UART_CAP_AFE, + }, + [PORT_ALTR_16550_F128] = { + .name = "Altera 16550 FIFO128", + .fifo_size = 128, + .tx_loadsz = 128, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, + .flags = UART_CAP_FIFO | UART_CAP_AFE, + }, + /* + * tx_loadsz is set to 63-bytes instead of 64-bytes to implement + * workaround of errata A-008006 which states that tx_loadsz should + * be configured less than Maximum supported fifo bytes. + */ + [PORT_16550A_FSL64] = { + .name = "16550A_FSL64", + .fifo_size = 64, + .tx_loadsz = 63, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 | + UART_FCR7_64BYTE, + .flags = UART_CAP_FIFO, + }, + [PORT_RT2880] = { + .name = "Palmchip BK-3103", + .fifo_size = 16, + .tx_loadsz = 16, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, + .rxtrig_bytes = {1, 4, 8, 14}, + .flags = UART_CAP_FIFO, + }, +}; + +/* Uart divisor latch read */ +static int default_serial_dl_read(struct uart_8250_port *up) +{ + return serial_in(up, UART_DLL) | serial_in(up, UART_DLM) << 8; +} + +/* Uart divisor latch write */ +static void default_serial_dl_write(struct uart_8250_port *up, int value) +{ + serial_out(up, UART_DLL, value & 0xff); + serial_out(up, UART_DLM, value >> 8 & 0xff); +} + +#ifdef CONFIG_SERIAL_8250_RT288X + +/* Au1x00/RT288x UART hardware has a weird register layout */ +static const s8 au_io_in_map[8] = { + 0, /* UART_RX */ + 2, /* UART_IER */ + 3, /* UART_IIR */ + 5, /* UART_LCR */ + 6, /* UART_MCR */ + 7, /* UART_LSR */ + 8, /* UART_MSR */ + -1, /* UART_SCR (unmapped) */ +}; + +static const s8 au_io_out_map[8] = { + 1, /* UART_TX */ + 2, /* UART_IER */ + 4, /* UART_FCR */ + 5, /* UART_LCR */ + 6, /* UART_MCR */ + -1, /* UART_LSR (unmapped) */ + -1, /* UART_MSR (unmapped) */ + -1, /* UART_SCR (unmapped) */ +}; + +static unsigned int au_serial_in(struct uart_port *p, int offset) +{ + if (offset >= ARRAY_SIZE(au_io_in_map)) + return UINT_MAX; + offset = au_io_in_map[offset]; + if (offset < 0) + return UINT_MAX; + return __raw_readl(p->membase + (offset << p->regshift)); +} + +static void au_serial_out(struct uart_port *p, int offset, int value) +{ + if (offset >= ARRAY_SIZE(au_io_out_map)) + return; + offset = au_io_out_map[offset]; + if (offset < 0) + return; + __raw_writel(value, p->membase + (offset << p->regshift)); +} + +/* Au1x00 haven't got a standard divisor latch */ +static int au_serial_dl_read(struct uart_8250_port *up) +{ + return __raw_readl(up->port.membase + 0x28); +} + +static void au_serial_dl_write(struct uart_8250_port *up, int value) +{ + __raw_writel(value, up->port.membase + 0x28); +} + +#endif + +static unsigned int hub6_serial_in(struct uart_port *p, int offset) +{ + offset = offset << p->regshift; + outb(p->hub6 - 1 + offset, p->iobase); + return inb(p->iobase + 1); +} + +static void hub6_serial_out(struct uart_port *p, int offset, int value) +{ + offset = offset << p->regshift; + outb(p->hub6 - 1 + offset, p->iobase); + outb(value, p->iobase + 1); +} + +static unsigned int mem_serial_in(struct uart_port *p, int offset) +{ + offset = offset << p->regshift; + return readb(p->membase + offset); +} + +static void mem_serial_out(struct uart_port *p, int offset, int value) +{ + offset = offset << p->regshift; + writeb(value, p->membase + offset); +} + +static void mem16_serial_out(struct uart_port *p, int offset, int value) +{ + offset = offset << p->regshift; + writew(value, p->membase + offset); +} + +static unsigned int mem16_serial_in(struct uart_port *p, int offset) +{ + offset = offset << p->regshift; + return readw(p->membase + offset); +} + +static void mem32_serial_out(struct uart_port *p, int offset, int value) +{ + offset = offset << p->regshift; + writel(value, p->membase + offset); +} + +static unsigned int mem32_serial_in(struct uart_port *p, int offset) +{ + offset = offset << p->regshift; + return readl(p->membase + offset); +} + +static void mem32be_serial_out(struct uart_port *p, int offset, int value) +{ + offset = offset << p->regshift; + iowrite32be(value, p->membase + offset); +} + +static unsigned int mem32be_serial_in(struct uart_port *p, int offset) +{ + offset = offset << p->regshift; + return ioread32be(p->membase + offset); +} + +static unsigned int io_serial_in(struct uart_port *p, int offset) +{ + offset = offset << p->regshift; + return inb(p->iobase + offset); +} + +static void io_serial_out(struct uart_port *p, int offset, int value) +{ + offset = offset << p->regshift; + outb(value, p->iobase + offset); +} + +static int serial8250_default_handle_irq(struct uart_port *port); +static int exar_handle_irq(struct uart_port *port); + +static void set_io_from_upio(struct uart_port *p) +{ + struct uart_8250_port *up = up_to_u8250p(p); + + up->dl_read = default_serial_dl_read; + up->dl_write = default_serial_dl_write; + + switch (p->iotype) { + case UPIO_HUB6: + p->serial_in = hub6_serial_in; + p->serial_out = hub6_serial_out; + break; + + case UPIO_MEM: + p->serial_in = mem_serial_in; + p->serial_out = mem_serial_out; + break; + + case UPIO_MEM16: + p->serial_in = mem16_serial_in; + p->serial_out = mem16_serial_out; + break; + + case UPIO_MEM32: + p->serial_in = mem32_serial_in; + p->serial_out = mem32_serial_out; + break; + + case UPIO_MEM32BE: + p->serial_in = mem32be_serial_in; + p->serial_out = mem32be_serial_out; + break; + +#ifdef CONFIG_SERIAL_8250_RT288X + case UPIO_AU: + p->serial_in = au_serial_in; + p->serial_out = au_serial_out; + up->dl_read = au_serial_dl_read; + up->dl_write = au_serial_dl_write; + break; +#endif + + default: + p->serial_in = io_serial_in; + p->serial_out = io_serial_out; + break; + } + /* Remember loaded iotype */ + up->cur_iotype = p->iotype; + p->handle_irq = serial8250_default_handle_irq; +} + +static void +serial_port_out_sync(struct uart_port *p, int offset, int value) +{ + switch (p->iotype) { + case UPIO_MEM: + case UPIO_MEM16: + case UPIO_MEM32: + case UPIO_MEM32BE: + case UPIO_AU: + p->serial_out(p, offset, value); + p->serial_in(p, UART_LCR); /* safe, no side-effects */ + break; + default: + p->serial_out(p, offset, value); + } +} + +/* + * For the 16C950 + */ +static void serial_icr_write(struct uart_8250_port *up, int offset, int value) +{ + serial_out(up, UART_SCR, offset); + serial_out(up, UART_ICR, value); +} + +static unsigned int serial_icr_read(struct uart_8250_port *up, int offset) +{ + unsigned int value; + + serial_icr_write(up, UART_ACR, up->acr | UART_ACR_ICRRD); + serial_out(up, UART_SCR, offset); + value = serial_in(up, UART_ICR); + serial_icr_write(up, UART_ACR, up->acr); + + return value; +} + +/* + * FIFO support. + */ +static void serial8250_clear_fifos(struct uart_8250_port *p) +{ + if (p->capabilities & UART_CAP_FIFO) { + serial_out(p, UART_FCR, UART_FCR_ENABLE_FIFO); + serial_out(p, UART_FCR, UART_FCR_ENABLE_FIFO | + UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); + serial_out(p, UART_FCR, 0); + } +} + +static inline void serial8250_em485_rts_after_send(struct uart_8250_port *p) +{ + unsigned char mcr = serial8250_in_MCR(p); + + if (p->port.rs485.flags & SER_RS485_RTS_AFTER_SEND) + mcr |= UART_MCR_RTS; + else + mcr &= ~UART_MCR_RTS; + serial8250_out_MCR(p, mcr); +} + +static void serial8250_em485_handle_start_tx(unsigned long arg); +static void serial8250_em485_handle_stop_tx(unsigned long arg); + +void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p) +{ + serial8250_clear_fifos(p); + serial_out(p, UART_FCR, p->fcr); +} +EXPORT_SYMBOL_GPL(serial8250_clear_and_reinit_fifos); + +void serial8250_rpm_get(struct uart_8250_port *p) +{ + if (!(p->capabilities & UART_CAP_RPM)) + return; + pm_runtime_get_sync(p->port.dev); +} +EXPORT_SYMBOL_GPL(serial8250_rpm_get); + +void serial8250_rpm_put(struct uart_8250_port *p) +{ + if (!(p->capabilities & UART_CAP_RPM)) + return; + pm_runtime_mark_last_busy(p->port.dev); + pm_runtime_put_autosuspend(p->port.dev); +} +EXPORT_SYMBOL_GPL(serial8250_rpm_put); + +/** + * serial8250_em485_init() - put uart_8250_port into rs485 emulating + * @p: uart_8250_port port instance + * + * The function is used to start rs485 software emulating on the + * &struct uart_8250_port* @p. Namely, RTS is switched before/after + * transmission. The function is idempotent, so it is safe to call it + * multiple times. + * + * The caller MUST enable interrupt on empty shift register before + * calling serial8250_em485_init(). This interrupt is not a part of + * 8250 standard, but implementation defined. + * + * The function is supposed to be called from .rs485_config callback + * or from any other callback protected with p->port.lock spinlock. + * + * See also serial8250_em485_destroy() + * + * Return 0 - success, -errno - otherwise + */ +int serial8250_em485_init(struct uart_8250_port *p) +{ + if (p->em485 != NULL) + return 0; + + p->em485 = kmalloc(sizeof(struct uart_8250_em485), GFP_ATOMIC); + if (p->em485 == NULL) + return -ENOMEM; + + setup_timer(&p->em485->stop_tx_timer, + serial8250_em485_handle_stop_tx, (unsigned long)p); + setup_timer(&p->em485->start_tx_timer, + serial8250_em485_handle_start_tx, (unsigned long)p); + p->em485->active_timer = NULL; + + serial8250_em485_rts_after_send(p); + + return 0; +} +EXPORT_SYMBOL_GPL(serial8250_em485_init); + +/** + * serial8250_em485_destroy() - put uart_8250_port into normal state + * @p: uart_8250_port port instance + * + * The function is used to stop rs485 software emulating on the + * &struct uart_8250_port* @p. The function is idempotent, so it is safe to + * call it multiple times. + * + * The function is supposed to be called from .rs485_config callback + * or from any other callback protected with p->port.lock spinlock. + * + * See also serial8250_em485_init() + */ +void serial8250_em485_destroy(struct uart_8250_port *p) +{ + if (p->em485 == NULL) + return; + + del_timer(&p->em485->start_tx_timer); + del_timer(&p->em485->stop_tx_timer); + + kfree(p->em485); + p->em485 = NULL; +} +EXPORT_SYMBOL_GPL(serial8250_em485_destroy); + +/* + * These two wrappers ensure that enable_runtime_pm_tx() can be called more than + * once and disable_runtime_pm_tx() will still disable RPM because the fifo is + * empty and the HW can idle again. + */ +static void serial8250_rpm_get_tx(struct uart_8250_port *p) +{ + unsigned char rpm_active; + + if (!(p->capabilities & UART_CAP_RPM)) + return; + + rpm_active = xchg(&p->rpm_tx_active, 1); + if (rpm_active) + return; + pm_runtime_get_sync(p->port.dev); +} + +static void serial8250_rpm_put_tx(struct uart_8250_port *p) +{ + unsigned char rpm_active; + + if (!(p->capabilities & UART_CAP_RPM)) + return; + + rpm_active = xchg(&p->rpm_tx_active, 0); + if (!rpm_active) + return; + pm_runtime_mark_last_busy(p->port.dev); + pm_runtime_put_autosuspend(p->port.dev); +} + +/* + * IER sleep support. UARTs which have EFRs need the "extended + * capability" bit enabled. Note that on XR16C850s, we need to + * reset LCR to write to IER. + */ +static void serial8250_set_sleep(struct uart_8250_port *p, int sleep) +{ + unsigned char lcr = 0, efr = 0; + /* + * Exar UARTs have a SLEEP register that enables or disables + * each UART to enter sleep mode separately. On the XR17V35x the + * register is accessible to each UART at the UART_EXAR_SLEEP + * offset but the UART channel may only write to the corresponding + * bit. + */ + serial8250_rpm_get(p); + if ((p->port.type == PORT_XR17V35X) || + (p->port.type == PORT_XR17D15X)) { + serial_out(p, UART_EXAR_SLEEP, sleep ? 0xff : 0); + goto out; + } + + if (p->capabilities & UART_CAP_SLEEP) { + if (p->capabilities & UART_CAP_EFR) { + lcr = serial_in(p, UART_LCR); + efr = serial_in(p, UART_EFR); + serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B); + serial_out(p, UART_EFR, UART_EFR_ECB); + serial_out(p, UART_LCR, 0); + } + serial_out(p, UART_IER, sleep ? UART_IERX_SLEEP : 0); + if (p->capabilities & UART_CAP_EFR) { + serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B); + serial_out(p, UART_EFR, efr); + serial_out(p, UART_LCR, lcr); + } + } +out: + serial8250_rpm_put(p); +} + +#ifdef CONFIG_SERIAL_8250_RSA +/* + * Attempts to turn on the RSA FIFO. Returns zero on failure. + * We set the port uart clock rate if we succeed. + */ +static int __enable_rsa(struct uart_8250_port *up) +{ + unsigned char mode; + int result; + + mode = serial_in(up, UART_RSA_MSR); + result = mode & UART_RSA_MSR_FIFO; + + if (!result) { + serial_out(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO); + mode = serial_in(up, UART_RSA_MSR); + result = mode & UART_RSA_MSR_FIFO; + } + + if (result) + up->port.uartclk = SERIAL_RSA_BAUD_BASE * 16; + + return result; +} + +static void enable_rsa(struct uart_8250_port *up) +{ + if (up->port.type == PORT_RSA) { + if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16) { + spin_lock_irq(&up->port.lock); + __enable_rsa(up); + spin_unlock_irq(&up->port.lock); + } + if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) + serial_out(up, UART_RSA_FRR, 0); + } +} + +/* + * Attempts to turn off the RSA FIFO. Returns zero on failure. + * It is unknown why interrupts were disabled in here. However, + * the caller is expected to preserve this behaviour by grabbing + * the spinlock before calling this function. + */ +static void disable_rsa(struct uart_8250_port *up) +{ + unsigned char mode; + int result; + + if (up->port.type == PORT_RSA && + up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) { + spin_lock_irq(&up->port.lock); + + mode = serial_in(up, UART_RSA_MSR); + result = !(mode & UART_RSA_MSR_FIFO); + + if (!result) { + serial_out(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO); + mode = serial_in(up, UART_RSA_MSR); + result = !(mode & UART_RSA_MSR_FIFO); + } + + if (result) + up->port.uartclk = SERIAL_RSA_BAUD_BASE_LO * 16; + spin_unlock_irq(&up->port.lock); + } +} +#endif /* CONFIG_SERIAL_8250_RSA */ + +/* + * This is a quickie test to see how big the FIFO is. + * It doesn't work at all the time, more's the pity. + */ +static int size_fifo(struct uart_8250_port *up) +{ + unsigned char old_fcr, old_mcr, old_lcr; + unsigned short old_dl; + int count; + + old_lcr = serial_in(up, UART_LCR); + serial_out(up, UART_LCR, 0); + old_fcr = serial_in(up, UART_FCR); + old_mcr = serial8250_in_MCR(up); + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | + UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); + serial8250_out_MCR(up, UART_MCR_LOOP); + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); + old_dl = serial_dl_read(up); + serial_dl_write(up, 0x0001); + serial_out(up, UART_LCR, 0x03); + for (count = 0; count < 256; count++) + serial_out(up, UART_TX, count); + mdelay(20);/* FIXME - schedule_timeout */ + for (count = 0; (serial_in(up, UART_LSR) & UART_LSR_DR) && + (count < 256); count++) + serial_in(up, UART_RX); + serial_out(up, UART_FCR, old_fcr); + serial8250_out_MCR(up, old_mcr); + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); + serial_dl_write(up, old_dl); + serial_out(up, UART_LCR, old_lcr); + + return count; +} + +/* + * Read UART ID using the divisor method - set DLL and DLM to zero + * and the revision will be in DLL and device type in DLM. We + * preserve the device state across this. + */ +static unsigned int autoconfig_read_divisor_id(struct uart_8250_port *p) +{ + unsigned char old_lcr; + unsigned int id, old_dl; + + old_lcr = serial_in(p, UART_LCR); + serial_out(p, UART_LCR, UART_LCR_CONF_MODE_A); + old_dl = serial_dl_read(p); + serial_dl_write(p, 0); + id = serial_dl_read(p); + serial_dl_write(p, old_dl); + + serial_out(p, UART_LCR, old_lcr); + + return id; +} + +/* + * This is a helper routine to autodetect StarTech/Exar/Oxsemi UART's. + * When this function is called we know it is at least a StarTech + * 16650 V2, but it might be one of several StarTech UARTs, or one of + * its clones. (We treat the broken original StarTech 16650 V1 as a + * 16550, and why not? Startech doesn't seem to even acknowledge its + * existence.) + * + * What evil have men's minds wrought... + */ +static void autoconfig_has_efr(struct uart_8250_port *up) +{ + unsigned int id1, id2, id3, rev; + + /* + * Everything with an EFR has SLEEP + */ + up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP; + + /* + * First we check to see if it's an Oxford Semiconductor UART. + * + * If we have to do this here because some non-National + * Semiconductor clone chips lock up if you try writing to the + * LSR register (which serial_icr_read does) + */ + + /* + * Check for Oxford Semiconductor 16C950. + * + * EFR [4] must be set else this test fails. + * + * This shouldn't be necessary, but Mike Hudson (Exoray@isys.ca) + * claims that it's needed for 952 dual UART's (which are not + * recommended for new designs). + */ + up->acr = 0; + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); + serial_out(up, UART_EFR, UART_EFR_ECB); + serial_out(up, UART_LCR, 0x00); + id1 = serial_icr_read(up, UART_ID1); + id2 = serial_icr_read(up, UART_ID2); + id3 = serial_icr_read(up, UART_ID3); + rev = serial_icr_read(up, UART_REV); + + DEBUG_AUTOCONF("950id=%02x:%02x:%02x:%02x ", id1, id2, id3, rev); + + if (id1 == 0x16 && id2 == 0xC9 && + (id3 == 0x50 || id3 == 0x52 || id3 == 0x54)) { + up->port.type = PORT_16C950; + + /* + * Enable work around for the Oxford Semiconductor 952 rev B + * chip which causes it to seriously miscalculate baud rates + * when DLL is 0. + */ + if (id3 == 0x52 && rev == 0x01) + up->bugs |= UART_BUG_QUOT; + return; + } + + /* + * We check for a XR16C850 by setting DLL and DLM to 0, and then + * reading back DLL and DLM. The chip type depends on the DLM + * value read back: + * 0x10 - XR16C850 and the DLL contains the chip revision. + * 0x12 - XR16C2850. + * 0x14 - XR16C854. + */ + id1 = autoconfig_read_divisor_id(up); + DEBUG_AUTOCONF("850id=%04x ", id1); + + id2 = id1 >> 8; + if (id2 == 0x10 || id2 == 0x12 || id2 == 0x14) { + up->port.type = PORT_16850; + return; + } + + /* + * It wasn't an XR16C850. + * + * We distinguish between the '654 and the '650 by counting + * how many bytes are in the FIFO. I'm using this for now, + * since that's the technique that was sent to me in the + * serial driver update, but I'm not convinced this works. + * I've had problems doing this in the past. -TYT + */ + if (size_fifo(up) == 64) + up->port.type = PORT_16654; + else + up->port.type = PORT_16650V2; +} + +/* + * We detected a chip without a FIFO. Only two fall into + * this category - the original 8250 and the 16450. The + * 16450 has a scratch register (accessible with LCR=0) + */ +static void autoconfig_8250(struct uart_8250_port *up) +{ + unsigned char scratch, status1, status2; + + up->port.type = PORT_8250; + + scratch = serial_in(up, UART_SCR); + serial_out(up, UART_SCR, 0xa5); + status1 = serial_in(up, UART_SCR); + serial_out(up, UART_SCR, 0x5a); + status2 = serial_in(up, UART_SCR); + serial_out(up, UART_SCR, scratch); + + if (status1 == 0xa5 && status2 == 0x5a) + up->port.type = PORT_16450; +} + +static int broken_efr(struct uart_8250_port *up) +{ + /* + * Exar ST16C2550 "A2" devices incorrectly detect as + * having an EFR, and report an ID of 0x0201. See + * http://linux.derkeiler.com/Mailing-Lists/Kernel/2004-11/4812.html + */ + if (autoconfig_read_divisor_id(up) == 0x0201 && size_fifo(up) == 16) + return 1; + + return 0; +} + +/* + * We know that the chip has FIFOs. Does it have an EFR? The + * EFR is located in the same register position as the IIR and + * we know the top two bits of the IIR are currently set. The + * EFR should contain zero. Try to read the EFR. + */ +static void autoconfig_16550a(struct uart_8250_port *up) +{ + unsigned char status1, status2; + unsigned int iersave; + + up->port.type = PORT_16550A; + up->capabilities |= UART_CAP_FIFO; + + /* + * XR17V35x UARTs have an extra divisor register, DLD + * that gets enabled with when DLAB is set which will + * cause the device to incorrectly match and assign + * port type to PORT_16650. The EFR for this UART is + * found at offset 0x09. Instead check the Deice ID (DVID) + * register for a 2, 4 or 8 port UART. + */ + if (up->port.flags & UPF_EXAR_EFR) { + status1 = serial_in(up, UART_EXAR_DVID); + if (status1 == 0x82 || status1 == 0x84 || status1 == 0x88) { + DEBUG_AUTOCONF("Exar XR17V35x "); + up->port.type = PORT_XR17V35X; + up->capabilities |= UART_CAP_AFE | UART_CAP_EFR | + UART_CAP_SLEEP; + + return; + } + + } + + /* + * Check for presence of the EFR when DLAB is set. + * Only ST16C650V1 UARTs pass this test. + */ + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); + if (serial_in(up, UART_EFR) == 0) { + serial_out(up, UART_EFR, 0xA8); + if (serial_in(up, UART_EFR) != 0) { + DEBUG_AUTOCONF("EFRv1 "); + up->port.type = PORT_16650; + up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP; + } else { + serial_out(up, UART_LCR, 0); + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | + UART_FCR7_64BYTE); + status1 = serial_in(up, UART_IIR) >> 5; + serial_out(up, UART_FCR, 0); + serial_out(up, UART_LCR, 0); + + if (status1 == 7) + up->port.type = PORT_16550A_FSL64; + else + DEBUG_AUTOCONF("Motorola 8xxx DUART "); + } + serial_out(up, UART_EFR, 0); + return; + } + + /* + * Maybe it requires 0xbf to be written to the LCR. + * (other ST16C650V2 UARTs, TI16C752A, etc) + */ + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); + if (serial_in(up, UART_EFR) == 0 && !broken_efr(up)) { + DEBUG_AUTOCONF("EFRv2 "); + autoconfig_has_efr(up); + return; + } + + /* + * Check for a National Semiconductor SuperIO chip. + * Attempt to switch to bank 2, read the value of the LOOP bit + * from EXCR1. Switch back to bank 0, change it in MCR. Then + * switch back to bank 2, read it from EXCR1 again and check + * it's changed. If so, set baud_base in EXCR2 to 921600. -- dwmw2 + */ + serial_out(up, UART_LCR, 0); + status1 = serial8250_in_MCR(up); + serial_out(up, UART_LCR, 0xE0); + status2 = serial_in(up, 0x02); /* EXCR1 */ + + if (!((status2 ^ status1) & UART_MCR_LOOP)) { + serial_out(up, UART_LCR, 0); + serial8250_out_MCR(up, status1 ^ UART_MCR_LOOP); + serial_out(up, UART_LCR, 0xE0); + status2 = serial_in(up, 0x02); /* EXCR1 */ + serial_out(up, UART_LCR, 0); + serial8250_out_MCR(up, status1); + + if ((status2 ^ status1) & UART_MCR_LOOP) { + unsigned short quot; + + serial_out(up, UART_LCR, 0xE0); + + quot = serial_dl_read(up); + quot <<= 3; + + if (ns16550a_goto_highspeed(up)) + serial_dl_write(up, quot); + + serial_out(up, UART_LCR, 0); + + up->port.uartclk = 921600*16; + up->port.type = PORT_NS16550A; + up->capabilities |= UART_NATSEMI; + return; + } + } + + /* + * No EFR. Try to detect a TI16750, which only sets bit 5 of + * the IIR when 64 byte FIFO mode is enabled when DLAB is set. + * Try setting it with and without DLAB set. Cheap clones + * set bit 5 without DLAB set. + */ + serial_out(up, UART_LCR, 0); + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE); + status1 = serial_in(up, UART_IIR) >> 5; + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO); + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE); + status2 = serial_in(up, UART_IIR) >> 5; + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO); + serial_out(up, UART_LCR, 0); + + DEBUG_AUTOCONF("iir1=%d iir2=%d ", status1, status2); + + if (status1 == 6 && status2 == 7) { + up->port.type = PORT_16750; + up->capabilities |= UART_CAP_AFE | UART_CAP_SLEEP; + return; + } + + /* + * Try writing and reading the UART_IER_UUE bit (b6). + * If it works, this is probably one of the Xscale platform's + * internal UARTs. + * We're going to explicitly set the UUE bit to 0 before + * trying to write and read a 1 just to make sure it's not + * already a 1 and maybe locked there before we even start start. + */ + iersave = serial_in(up, UART_IER); + serial_out(up, UART_IER, iersave & ~UART_IER_UUE); + if (!(serial_in(up, UART_IER) & UART_IER_UUE)) { + /* + * OK it's in a known zero state, try writing and reading + * without disturbing the current state of the other bits. + */ + serial_out(up, UART_IER, iersave | UART_IER_UUE); + if (serial_in(up, UART_IER) & UART_IER_UUE) { + /* + * It's an Xscale. + * We'll leave the UART_IER_UUE bit set to 1 (enabled). + */ + DEBUG_AUTOCONF("Xscale "); + up->port.type = PORT_XSCALE; + up->capabilities |= UART_CAP_UUE | UART_CAP_RTOIE; + return; + } + } else { + /* + * If we got here we couldn't force the IER_UUE bit to 0. + * Log it and continue. + */ + DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 "); + } + serial_out(up, UART_IER, iersave); + + /* + * Exar uarts have EFR in a weird location + */ + if (up->port.flags & UPF_EXAR_EFR) { + DEBUG_AUTOCONF("Exar XR17D15x "); + up->port.type = PORT_XR17D15X; + up->capabilities |= UART_CAP_AFE | UART_CAP_EFR | + UART_CAP_SLEEP; + + return; + } + + /* + * We distinguish between 16550A and U6 16550A by counting + * how many bytes are in the FIFO. + */ + if (up->port.type == PORT_16550A && size_fifo(up) == 64) { + up->port.type = PORT_U6_16550A; + up->capabilities |= UART_CAP_AFE; + } +} + +/* + * This routine is called by rs_init() to initialize a specific serial + * port. It determines what type of UART chip this serial port is + * using: 8250, 16450, 16550, 16550A. The important question is + * whether or not this UART is a 16550A or not, since this will + * determine whether or not we can use its FIFO features or not. + */ +static void autoconfig(struct uart_8250_port *up) +{ + unsigned char status1, scratch, scratch2, scratch3; + unsigned char save_lcr, save_mcr; + struct uart_port *port = &up->port; + unsigned long flags; + unsigned int old_capabilities; + + if (!port->iobase && !port->mapbase && !port->membase) + return; + + DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04lx, 0x%p): ", + serial_index(port), port->iobase, port->membase); + + /* + * We really do need global IRQs disabled here - we're going to + * be frobbing the chips IRQ enable register to see if it exists. + */ + spin_lock_irqsave(&port->lock, flags); + + up->capabilities = 0; + up->bugs = 0; + + if (!(port->flags & UPF_BUGGY_UART)) { + /* + * Do a simple existence test first; if we fail this, + * there's no point trying anything else. + * + * 0x80 is used as a nonsense port to prevent against + * false positives due to ISA bus float. The + * assumption is that 0x80 is a non-existent port; + * which should be safe since include/asm/io.h also + * makes this assumption. + * + * Note: this is safe as long as MCR bit 4 is clear + * and the device is in "PC" mode. + */ + scratch = serial_in(up, UART_IER); + serial_out(up, UART_IER, 0); +#ifdef __i386__ + outb(0xff, 0x080); +#endif + /* + * Mask out IER[7:4] bits for test as some UARTs (e.g. TL + * 16C754B) allow only to modify them if an EFR bit is set. + */ + scratch2 = serial_in(up, UART_IER) & 0x0f; + serial_out(up, UART_IER, 0x0F); +#ifdef __i386__ + outb(0, 0x080); +#endif + scratch3 = serial_in(up, UART_IER) & 0x0f; + serial_out(up, UART_IER, scratch); + if (scratch2 != 0 || scratch3 != 0x0F) { + /* + * We failed; there's nothing here + */ + spin_unlock_irqrestore(&port->lock, flags); + DEBUG_AUTOCONF("IER test failed (%02x, %02x) ", + scratch2, scratch3); + goto out; + } + } + + save_mcr = serial8250_in_MCR(up); + save_lcr = serial_in(up, UART_LCR); + + /* + * Check to see if a UART is really there. Certain broken + * internal modems based on the Rockwell chipset fail this + * test, because they apparently don't implement the loopback + * test mode. So this test is skipped on the COM 1 through + * COM 4 ports. This *should* be safe, since no board + * manufacturer would be stupid enough to design a board + * that conflicts with COM 1-4 --- we hope! + */ + if (!(port->flags & UPF_SKIP_TEST)) { + serial8250_out_MCR(up, UART_MCR_LOOP | 0x0A); + status1 = serial_in(up, UART_MSR) & 0xF0; + serial8250_out_MCR(up, save_mcr); + if (status1 != 0x90) { + spin_unlock_irqrestore(&port->lock, flags); + DEBUG_AUTOCONF("LOOP test failed (%02x) ", + status1); + goto out; + } + } + + /* + * We're pretty sure there's a port here. Lets find out what + * type of port it is. The IIR top two bits allows us to find + * out if it's 8250 or 16450, 16550, 16550A or later. This + * determines what we test for next. + * + * We also initialise the EFR (if any) to zero for later. The + * EFR occupies the same register location as the FCR and IIR. + */ + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); + serial_out(up, UART_EFR, 0); + serial_out(up, UART_LCR, 0); + + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO); + scratch = serial_in(up, UART_IIR) >> 6; + + switch (scratch) { + case 0: + autoconfig_8250(up); + break; + case 1: + port->type = PORT_UNKNOWN; + break; + case 2: + port->type = PORT_16550; + break; + case 3: + autoconfig_16550a(up); + break; + } + +#ifdef CONFIG_SERIAL_8250_RSA + /* + * Only probe for RSA ports if we got the region. + */ + if (port->type == PORT_16550A && up->probe & UART_PROBE_RSA && + __enable_rsa(up)) + port->type = PORT_RSA; +#endif + + serial_out(up, UART_LCR, save_lcr); + + port->fifosize = uart_config[up->port.type].fifo_size; + old_capabilities = up->capabilities; + up->capabilities = uart_config[port->type].flags; + up->tx_loadsz = uart_config[port->type].tx_loadsz; + + if (port->type == PORT_UNKNOWN) + goto out_lock; + + /* + * Reset the UART. + */ +#ifdef CONFIG_SERIAL_8250_RSA + if (port->type == PORT_RSA) + serial_out(up, UART_RSA_FRR, 0); +#endif + serial8250_out_MCR(up, save_mcr); + serial8250_clear_fifos(up); + serial_in(up, UART_RX); + if (up->capabilities & UART_CAP_UUE) + serial_out(up, UART_IER, UART_IER_UUE); + else + serial_out(up, UART_IER, 0); + +out_lock: + spin_unlock_irqrestore(&port->lock, flags); + + /* + * Check if the device is a Fintek F81216A + */ + if (port->type == PORT_16550A) + fintek_8250_probe(up); + + if (up->capabilities != old_capabilities) { + pr_warn("ttyS%d: detected caps %08x should be %08x\n", + serial_index(port), old_capabilities, + up->capabilities); + } +out: + DEBUG_AUTOCONF("iir=%d ", scratch); + DEBUG_AUTOCONF("type=%s\n", uart_config[port->type].name); +} + +static void autoconfig_irq(struct uart_8250_port *up) +{ + struct uart_port *port = &up->port; + unsigned char save_mcr, save_ier; + unsigned char save_ICP = 0; + unsigned int ICP = 0; + unsigned long irqs; + int irq; + + if (port->flags & UPF_FOURPORT) { + ICP = (port->iobase & 0xfe0) | 0x1f; + save_ICP = inb_p(ICP); + outb_p(0x80, ICP); + inb_p(ICP); + } + + if (uart_console(port)) + console_lock(); + + /* forget possible initially masked and pending IRQ */ + probe_irq_off(probe_irq_on()); + save_mcr = serial8250_in_MCR(up); + save_ier = serial_in(up, UART_IER); + serial8250_out_MCR(up, UART_MCR_OUT1 | UART_MCR_OUT2); + + irqs = probe_irq_on(); + serial8250_out_MCR(up, 0); + udelay(10); + if (port->flags & UPF_FOURPORT) { + serial8250_out_MCR(up, UART_MCR_DTR | UART_MCR_RTS); + } else { + serial8250_out_MCR(up, + UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2); + } + serial_out(up, UART_IER, 0x0f); /* enable all intrs */ + serial_in(up, UART_LSR); + serial_in(up, UART_RX); + serial_in(up, UART_IIR); + serial_in(up, UART_MSR); + serial_out(up, UART_TX, 0xFF); + udelay(20); + irq = probe_irq_off(irqs); + + serial8250_out_MCR(up, save_mcr); + serial_out(up, UART_IER, save_ier); + + if (port->flags & UPF_FOURPORT) + outb_p(save_ICP, ICP); + + if (uart_console(port)) + console_unlock(); + + port->irq = (irq > 0) ? irq : 0; +} + +static void serial8250_stop_rx(struct uart_port *port) +{ + struct uart_8250_port *up = up_to_u8250p(port); + + serial8250_rpm_get(up); + + up->ier &= ~(UART_IER_RLSI | UART_IER_RDI); + up->port.read_status_mask &= ~UART_LSR_DR; + serial_port_out(port, UART_IER, up->ier); + + serial8250_rpm_put(up); +} + +static void __do_stop_tx_rs485(struct uart_8250_port *p) +{ + if (!p->em485) + return; + + serial8250_em485_rts_after_send(p); + /* + * Empty the RX FIFO, we are not interested in anything + * received during the half-duplex transmission. + * Enable previously disabled RX interrupts. + */ + if (!(p->port.rs485.flags & SER_RS485_RX_DURING_TX)) { + serial8250_clear_fifos(p); + + p->ier |= UART_IER_RLSI | UART_IER_RDI; + serial_port_out(&p->port, UART_IER, p->ier); + } +} + +static void serial8250_em485_handle_stop_tx(unsigned long arg) +{ + struct uart_8250_port *p = (struct uart_8250_port *)arg; + struct uart_8250_em485 *em485 = p->em485; + unsigned long flags; + + serial8250_rpm_get(p); + spin_lock_irqsave(&p->port.lock, flags); + if (em485 && + em485->active_timer == &em485->stop_tx_timer) { + __do_stop_tx_rs485(p); + em485->active_timer = NULL; + } + spin_unlock_irqrestore(&p->port.lock, flags); + serial8250_rpm_put(p); +} + +static void __stop_tx_rs485(struct uart_8250_port *p) +{ + struct uart_8250_em485 *em485 = p->em485; + + if (!em485) + return; + + /* + * __do_stop_tx_rs485 is going to set RTS according to config + * AND flush RX FIFO if required. + */ + if (p->port.rs485.delay_rts_after_send > 0) { + em485->active_timer = &em485->stop_tx_timer; + mod_timer(&em485->stop_tx_timer, jiffies + + p->port.rs485.delay_rts_after_send * HZ / 1000); + } else { + __do_stop_tx_rs485(p); + } +} + +static inline void __do_stop_tx(struct uart_8250_port *p) +{ + if (p->ier & UART_IER_THRI) { + p->ier &= ~UART_IER_THRI; + serial_out(p, UART_IER, p->ier); + serial8250_rpm_put_tx(p); + } +} + +static inline void __stop_tx(struct uart_8250_port *p) +{ + struct uart_8250_em485 *em485 = p->em485; + + if (em485) { + unsigned char lsr = serial_in(p, UART_LSR); + /* + * To provide required timeing and allow FIFO transfer, + * __stop_tx_rs485() must be called only when both FIFO and + * shift register are empty. It is for device driver to enable + * interrupt on TEMT. + */ + if ((lsr & BOTH_EMPTY) != BOTH_EMPTY) + return; + + del_timer(&em485->start_tx_timer); + em485->active_timer = NULL; + + __stop_tx_rs485(p); + } + __do_stop_tx(p); +} + +static void serial8250_stop_tx(struct uart_port *port) +{ + struct uart_8250_port *up = up_to_u8250p(port); + + serial8250_rpm_get(up); + __stop_tx(up); + + /* + * We really want to stop the transmitter from sending. + */ + if (port->type == PORT_16C950) { + up->acr |= UART_ACR_TXDIS; + serial_icr_write(up, UART_ACR, up->acr); + } + serial8250_rpm_put(up); +} + +static inline void __start_tx(struct uart_port *port) +{ + struct uart_8250_port *up = up_to_u8250p(port); + + if (up->dma && !up->dma->tx_dma(up)) + return; + + if (!(up->ier & UART_IER_THRI)) { + up->ier |= UART_IER_THRI; + serial_port_out(port, UART_IER, up->ier); + + if (up->bugs & UART_BUG_TXEN) { + unsigned char lsr; + + lsr = serial_in(up, UART_LSR); + up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; + if (lsr & UART_LSR_THRE) + serial8250_tx_chars(up); + } + } + + /* + * Re-enable the transmitter if we disabled it. + */ + if (port->type == PORT_16C950 && up->acr & UART_ACR_TXDIS) { + up->acr &= ~UART_ACR_TXDIS; + serial_icr_write(up, UART_ACR, up->acr); + } +} + +static inline void start_tx_rs485(struct uart_port *port) +{ + struct uart_8250_port *up = up_to_u8250p(port); + struct uart_8250_em485 *em485 = up->em485; + unsigned char mcr; + + if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX)) + serial8250_stop_rx(&up->port); + + del_timer(&em485->stop_tx_timer); + em485->active_timer = NULL; + + mcr = serial8250_in_MCR(up); + if (!!(up->port.rs485.flags & SER_RS485_RTS_ON_SEND) != + !!(mcr & UART_MCR_RTS)) { + if (up->port.rs485.flags & SER_RS485_RTS_ON_SEND) + mcr |= UART_MCR_RTS; + else + mcr &= ~UART_MCR_RTS; + serial8250_out_MCR(up, mcr); + + if (up->port.rs485.delay_rts_before_send > 0) { + em485->active_timer = &em485->start_tx_timer; + mod_timer(&em485->start_tx_timer, jiffies + + up->port.rs485.delay_rts_before_send * HZ / 1000); + return; + } + } + + __start_tx(port); +} + +static void serial8250_em485_handle_start_tx(unsigned long arg) +{ + struct uart_8250_port *p = (struct uart_8250_port *)arg; + struct uart_8250_em485 *em485 = p->em485; + unsigned long flags; + + spin_lock_irqsave(&p->port.lock, flags); + if (em485 && + em485->active_timer == &em485->start_tx_timer) { + __start_tx(&p->port); + em485->active_timer = NULL; + } + spin_unlock_irqrestore(&p->port.lock, flags); +} + +static void serial8250_start_tx(struct uart_port *port) +{ + struct uart_8250_port *up = up_to_u8250p(port); + struct uart_8250_em485 *em485 = up->em485; + + serial8250_rpm_get_tx(up); + + if (em485 && + em485->active_timer == &em485->start_tx_timer) + return; + + if (em485) + start_tx_rs485(port); + else + __start_tx(port); +} + +static void serial8250_throttle(struct uart_port *port) +{ + port->throttle(port); +} + +static void serial8250_unthrottle(struct uart_port *port) +{ + port->unthrottle(port); +} + +static void serial8250_disable_ms(struct uart_port *port) +{ + struct uart_8250_port *up = up_to_u8250p(port); + + /* no MSR capabilities */ + if (up->bugs & UART_BUG_NOMSR) + return; + + up->ier &= ~UART_IER_MSI; + serial_port_out(port, UART_IER, up->ier); +} + +static void serial8250_enable_ms(struct uart_port *port) +{ + struct uart_8250_port *up = up_to_u8250p(port); + + /* no MSR capabilities */ + if (up->bugs & UART_BUG_NOMSR) + return; + + up->ier |= UART_IER_MSI; + + serial8250_rpm_get(up); + serial_port_out(port, UART_IER, up->ier); + serial8250_rpm_put(up); +} + +static void serial8250_read_char(struct uart_8250_port *up, unsigned char lsr) +{ + struct uart_port *port = &up->port; + unsigned char ch; + char flag = TTY_NORMAL; + + if (likely(lsr & UART_LSR_DR)) + ch = serial_in(up, UART_RX); + else + /* + * Intel 82571 has a Serial Over Lan device that will + * set UART_LSR_BI without setting UART_LSR_DR when + * it receives a break. To avoid reading from the + * receive buffer without UART_LSR_DR bit set, we + * just force the read character to be 0 + */ + ch = 0; + + port->icount.rx++; + + lsr |= up->lsr_saved_flags; + up->lsr_saved_flags = 0; + + if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) { + if (lsr & UART_LSR_BI) { + lsr &= ~(UART_LSR_FE | UART_LSR_PE); + port->icount.brk++; + /* + * We do the SysRQ and SAK checking + * here because otherwise the break + * may get masked by ignore_status_mask + * or read_status_mask. + */ + if (uart_handle_break(port)) + return; + } else if (lsr & UART_LSR_PE) + port->icount.parity++; + else if (lsr & UART_LSR_FE) + port->icount.frame++; + if (lsr & UART_LSR_OE) + port->icount.overrun++; + + /* + * Mask off conditions which should be ignored. + */ + lsr &= port->read_status_mask; + + if (lsr & UART_LSR_BI) { + pr_debug("%s: handling break\n", __func__); + flag = TTY_BREAK; + } else if (lsr & UART_LSR_PE) + flag = TTY_PARITY; + else if (lsr & UART_LSR_FE) + flag = TTY_FRAME; + } + if (uart_handle_sysrq_char(port, ch)) + return; + + uart_insert_char(port, lsr, UART_LSR_OE, ch, flag); +} + +/* + * serial8250_rx_chars: processes according to the passed in LSR + * value, and returns the remaining LSR bits not handled + * by this Rx routine. + */ +unsigned char serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr) +{ + struct uart_port *port = &up->port; + int max_count = 256; + + do { + serial8250_read_char(up, lsr); + if (--max_count == 0) + break; + lsr = serial_in(up, UART_LSR); + } while (lsr & (UART_LSR_DR | UART_LSR_BI)); + + tty_flip_buffer_push(&port->state->port); + return lsr; +} +EXPORT_SYMBOL_GPL(serial8250_rx_chars); + +void serial8250_tx_chars(struct uart_8250_port *up) +{ + struct uart_port *port = &up->port; + struct circ_buf *xmit = &port->state->xmit; + int count; + + if (port->x_char) { + serial_out(up, UART_TX, port->x_char); + port->icount.tx++; + port->x_char = 0; + return; + } + if (uart_tx_stopped(port)) { + serial8250_stop_tx(port); + return; + } + if (uart_circ_empty(xmit)) { + __stop_tx(up); + return; + } + + count = up->tx_loadsz; + do { + serial_out(up, UART_TX, xmit->buf[xmit->tail]); + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + port->icount.tx++; + if (uart_circ_empty(xmit)) + break; + if ((up->capabilities & UART_CAP_HFIFO) && + (serial_in(up, UART_LSR) & BOTH_EMPTY) != BOTH_EMPTY) + break; + } while (--count > 0); + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(port); + + pr_debug("%s: THRE\n", __func__); + + /* + * With RPM enabled, we have to wait until the FIFO is empty before the + * HW can go idle. So we get here once again with empty FIFO and disable + * the interrupt and RPM in __stop_tx() + */ + if (uart_circ_empty(xmit) && !(up->capabilities & UART_CAP_RPM)) + __stop_tx(up); +} +EXPORT_SYMBOL_GPL(serial8250_tx_chars); + +/* Caller holds uart port lock */ +unsigned int serial8250_modem_status(struct uart_8250_port *up) +{ + struct uart_port *port = &up->port; + unsigned int status = serial_in(up, UART_MSR); + + status |= up->msr_saved_flags; + up->msr_saved_flags = 0; + if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI && + port->state != NULL) { + if (status & UART_MSR_TERI) + port->icount.rng++; + if (status & UART_MSR_DDSR) + port->icount.dsr++; + if (status & UART_MSR_DDCD) + uart_handle_dcd_change(port, status & UART_MSR_DCD); + if (status & UART_MSR_DCTS) + uart_handle_cts_change(port, status & UART_MSR_CTS); + + wake_up_interruptible(&port->state->port.delta_msr_wait); + } + + return status; +} +EXPORT_SYMBOL_GPL(serial8250_modem_status); + +static bool handle_rx_dma(struct uart_8250_port *up, unsigned int iir) +{ + switch (iir & 0x3f) { + case UART_IIR_RX_TIMEOUT: + serial8250_rx_dma_flush(up); + /* fall-through */ + case UART_IIR_RLSI: + return true; + } + return up->dma->rx_dma(up); +} + +/* + * This handles the interrupt from one port. + */ +int serial8250_handle_irq(struct uart_port *port, unsigned int iir) +{ + unsigned char status; + unsigned long flags; + struct uart_8250_port *up = up_to_u8250p(port); + + if (iir & UART_IIR_NO_INT) + return 0; + + spin_lock_irqsave(&port->lock, flags); + + status = serial_port_in(port, UART_LSR); + + pr_debug("%s: status = %x\n", __func__, status); + + if (status & (UART_LSR_DR | UART_LSR_BI)) { + if (!up->dma || handle_rx_dma(up, iir)) + status = serial8250_rx_chars(up, status); + } + serial8250_modem_status(up); + if ((!up->dma || up->dma->tx_err) && (status & UART_LSR_THRE)) + serial8250_tx_chars(up); + + spin_unlock_irqrestore(&port->lock, flags); + return 1; +} +EXPORT_SYMBOL_GPL(serial8250_handle_irq); + +static int serial8250_default_handle_irq(struct uart_port *port) +{ + struct uart_8250_port *up = up_to_u8250p(port); + unsigned int iir; + int ret; + + serial8250_rpm_get(up); + + iir = serial_port_in(port, UART_IIR); + ret = serial8250_handle_irq(port, iir); + + serial8250_rpm_put(up); + return ret; +} + +/* + * These Exar UARTs have an extra interrupt indicator that could + * fire for a few unimplemented interrupts. One of which is a + * wakeup event when coming out of sleep. Put this here just + * to be on the safe side that these interrupts don't go unhandled. + */ +static int exar_handle_irq(struct uart_port *port) +{ + unsigned int iir = serial_port_in(port, UART_IIR); + int ret; + + ret = serial8250_handle_irq(port, iir); + + if ((port->type == PORT_XR17V35X) || + (port->type == PORT_XR17D15X)) { + serial_port_in(port, 0x80); + serial_port_in(port, 0x81); + serial_port_in(port, 0x82); + serial_port_in(port, 0x83); + } + + return ret; +} + +static unsigned int serial8250_tx_empty(struct uart_port *port) +{ + struct uart_8250_port *up = up_to_u8250p(port); + unsigned long flags; + unsigned int lsr; + + serial8250_rpm_get(up); + + spin_lock_irqsave(&port->lock, flags); + lsr = serial_port_in(port, UART_LSR); + up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; + spin_unlock_irqrestore(&port->lock, flags); + + serial8250_rpm_put(up); + + return (lsr & BOTH_EMPTY) == BOTH_EMPTY ? TIOCSER_TEMT : 0; +} + +unsigned int serial8250_do_get_mctrl(struct uart_port *port) +{ + struct uart_8250_port *up = up_to_u8250p(port); + unsigned int status; + unsigned int ret; + + serial8250_rpm_get(up); + status = serial8250_modem_status(up); + serial8250_rpm_put(up); + + ret = 0; + if (status & UART_MSR_DCD) + ret |= TIOCM_CAR; + if (status & UART_MSR_RI) + ret |= TIOCM_RNG; + if (status & UART_MSR_DSR) + ret |= TIOCM_DSR; + if (status & UART_MSR_CTS) + ret |= TIOCM_CTS; + return ret; +} +EXPORT_SYMBOL_GPL(serial8250_do_get_mctrl); + +static unsigned int serial8250_get_mctrl(struct uart_port *port) +{ + if (port->get_mctrl) + return port->get_mctrl(port); + return serial8250_do_get_mctrl(port); +} + +void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ + struct uart_8250_port *up = up_to_u8250p(port); + unsigned char mcr = 0; + + if (mctrl & TIOCM_RTS) + mcr |= UART_MCR_RTS; + if (mctrl & TIOCM_DTR) + mcr |= UART_MCR_DTR; + if (mctrl & TIOCM_OUT1) + mcr |= UART_MCR_OUT1; + if (mctrl & TIOCM_OUT2) + mcr |= UART_MCR_OUT2; + if (mctrl & TIOCM_LOOP) + mcr |= UART_MCR_LOOP; + + mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr; + + serial8250_out_MCR(up, mcr); +} +EXPORT_SYMBOL_GPL(serial8250_do_set_mctrl); + +static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ + if (port->set_mctrl) + port->set_mctrl(port, mctrl); + else + serial8250_do_set_mctrl(port, mctrl); +} + +static void serial8250_break_ctl(struct uart_port *port, int break_state) +{ + struct uart_8250_port *up = up_to_u8250p(port); + unsigned long flags; + + serial8250_rpm_get(up); + spin_lock_irqsave(&port->lock, flags); + if (break_state == -1) + up->lcr |= UART_LCR_SBC; + else + up->lcr &= ~UART_LCR_SBC; + serial_port_out(port, UART_LCR, up->lcr); + spin_unlock_irqrestore(&port->lock, flags); + serial8250_rpm_put(up); +} + +/* + * Wait for transmitter & holding register to empty + */ +static void wait_for_xmitr(struct uart_8250_port *up, int bits) +{ + unsigned int status, tmout = 10000; + + /* Wait up to 10ms for the character(s) to be sent. */ + for (;;) { + status = serial_in(up, UART_LSR); + + up->lsr_saved_flags |= status & LSR_SAVE_FLAGS; + + if ((status & bits) == bits) + break; + if (--tmout == 0) + break; + udelay(1); + } + + /* Wait up to 1s for flow control if necessary */ + if (up->port.flags & UPF_CONS_FLOW) { + for (tmout = 1000000; tmout; tmout--) { + unsigned int msr = serial_in(up, UART_MSR); + up->msr_saved_flags |= msr & MSR_SAVE_FLAGS; + if (msr & UART_MSR_CTS) + break; + udelay(1); + touch_nmi_watchdog(); + } + } +} + +#ifdef CONFIG_CONSOLE_POLL +/* + * Console polling routines for writing and reading from the uart while + * in an interrupt or debug context. + */ + +static int serial8250_get_poll_char(struct uart_port *port) +{ + struct uart_8250_port *up = up_to_u8250p(port); + unsigned char lsr; + int status; + + serial8250_rpm_get(up); + + lsr = serial_port_in(port, UART_LSR); + + if (!(lsr & UART_LSR_DR)) { + status = NO_POLL_CHAR; + goto out; + } + + status = serial_port_in(port, UART_RX); +out: + serial8250_rpm_put(up); + return status; +} + + +static void serial8250_put_poll_char(struct uart_port *port, + unsigned char c) +{ + unsigned int ier; + struct uart_8250_port *up = up_to_u8250p(port); + + serial8250_rpm_get(up); + /* + * First save the IER then disable the interrupts + */ + ier = serial_port_in(port, UART_IER); + if (up->capabilities & UART_CAP_UUE) + serial_port_out(port, UART_IER, UART_IER_UUE); + else + serial_port_out(port, UART_IER, 0); + + wait_for_xmitr(up, BOTH_EMPTY); + /* + * Send the character out. + */ + serial_port_out(port, UART_TX, c); + + /* + * Finally, wait for transmitter to become empty + * and restore the IER + */ + wait_for_xmitr(up, BOTH_EMPTY); + serial_port_out(port, UART_IER, ier); + serial8250_rpm_put(up); +} + +#endif /* CONFIG_CONSOLE_POLL */ + +int serial8250_do_startup(struct uart_port *port) +{ + struct uart_8250_port *up = up_to_u8250p(port); + unsigned long flags; + unsigned char lsr, iir; + int retval; + + if (!port->fifosize) + port->fifosize = uart_config[port->type].fifo_size; + if (!up->tx_loadsz) + up->tx_loadsz = uart_config[port->type].tx_loadsz; + if (!up->capabilities) + up->capabilities = uart_config[port->type].flags; + up->mcr = 0; + + if (port->iotype != up->cur_iotype) + set_io_from_upio(port); + + serial8250_rpm_get(up); + if (port->type == PORT_16C950) { + /* Wake up and initialize UART */ + up->acr = 0; + serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B); + serial_port_out(port, UART_EFR, UART_EFR_ECB); + serial_port_out(port, UART_IER, 0); + serial_port_out(port, UART_LCR, 0); + serial_icr_write(up, UART_CSR, 0); /* Reset the UART */ + serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B); + serial_port_out(port, UART_EFR, UART_EFR_ECB); + serial_port_out(port, UART_LCR, 0); + } + +#ifdef CONFIG_SERIAL_8250_RSA + /* + * If this is an RSA port, see if we can kick it up to the + * higher speed clock. + */ + enable_rsa(up); +#endif + + if (port->type == PORT_XR17V35X) { + /* + * First enable access to IER [7:5], ISR [5:4], FCR [5:4], + * MCR [7:5] and MSR [7:0] + */ + serial_port_out(port, UART_XR_EFR, UART_EFR_ECB); + + /* + * Make sure all interrups are masked until initialization is + * complete and the FIFOs are cleared + */ + serial_port_out(port, UART_IER, 0); + } + + /* + * Clear the FIFO buffers and disable them. + * (they will be reenabled in set_termios()) + */ + serial8250_clear_fifos(up); + + /* + * Clear the interrupt registers. + */ + serial_port_in(port, UART_LSR); + serial_port_in(port, UART_RX); + serial_port_in(port, UART_IIR); + serial_port_in(port, UART_MSR); + + /* + * At this point, there's no way the LSR could still be 0xff; + * if it is, then bail out, because there's likely no UART + * here. + */ + if (!(port->flags & UPF_BUGGY_UART) && + (serial_port_in(port, UART_LSR) == 0xff)) { + printk_ratelimited(KERN_INFO "ttyS%d: LSR safety check engaged!\n", + serial_index(port)); + retval = -ENODEV; + goto out; + } + + /* + * For a XR16C850, we need to set the trigger levels + */ + if (port->type == PORT_16850) { + unsigned char fctr; + + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); + + fctr = serial_in(up, UART_FCTR) & ~(UART_FCTR_RX|UART_FCTR_TX); + serial_port_out(port, UART_FCTR, + fctr | UART_FCTR_TRGD | UART_FCTR_RX); + serial_port_out(port, UART_TRG, UART_TRG_96); + serial_port_out(port, UART_FCTR, + fctr | UART_FCTR_TRGD | UART_FCTR_TX); + serial_port_out(port, UART_TRG, UART_TRG_96); + + serial_port_out(port, UART_LCR, 0); + } + + if (port->irq) { + unsigned char iir1; + /* + * Test for UARTs that do not reassert THRE when the + * transmitter is idle and the interrupt has already + * been cleared. Real 16550s should always reassert + * this interrupt whenever the transmitter is idle and + * the interrupt is enabled. Delays are necessary to + * allow register changes to become visible. + */ + spin_lock_irqsave(&port->lock, flags); + if (up->port.irqflags & IRQF_SHARED) + disable_irq_nosync(port->irq); + + wait_for_xmitr(up, UART_LSR_THRE); + serial_port_out_sync(port, UART_IER, UART_IER_THRI); + udelay(1); /* allow THRE to set */ + iir1 = serial_port_in(port, UART_IIR); + serial_port_out(port, UART_IER, 0); + serial_port_out_sync(port, UART_IER, UART_IER_THRI); + udelay(1); /* allow a working UART time to re-assert THRE */ + iir = serial_port_in(port, UART_IIR); + serial_port_out(port, UART_IER, 0); + + if (port->irqflags & IRQF_SHARED) + enable_irq(port->irq); + spin_unlock_irqrestore(&port->lock, flags); + + /* + * If the interrupt is not reasserted, or we otherwise + * don't trust the iir, setup a timer to kick the UART + * on a regular basis. + */ + if ((!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) || + up->port.flags & UPF_BUG_THRE) { + up->bugs |= UART_BUG_THRE; + } + } + + retval = up->ops->setup_irq(up); + if (retval) + goto out; + + /* + * Now, initialize the UART + */ + serial_port_out(port, UART_LCR, UART_LCR_WLEN8); + + spin_lock_irqsave(&port->lock, flags); + if (up->port.flags & UPF_FOURPORT) { + if (!up->port.irq) + up->port.mctrl |= TIOCM_OUT1; + } else + /* + * Most PC uarts need OUT2 raised to enable interrupts. + */ + if (port->irq) + up->port.mctrl |= TIOCM_OUT2; + + serial8250_set_mctrl(port, port->mctrl); + + /* + * Serial over Lan (SoL) hack: + * Intel 8257x Gigabit ethernet chips have a 16550 emulation, to be + * used for Serial Over Lan. Those chips take a longer time than a + * normal serial device to signalize that a transmission data was + * queued. Due to that, the above test generally fails. One solution + * would be to delay the reading of iir. However, this is not + * reliable, since the timeout is variable. So, let's just don't + * test if we receive TX irq. This way, we'll never enable + * UART_BUG_TXEN. + */ + if (up->port.flags & UPF_NO_TXEN_TEST) + goto dont_test_tx_en; + + /* + * Do a quick test to see if we receive an interrupt when we enable + * the TX irq. + */ + serial_port_out(port, UART_IER, UART_IER_THRI); + lsr = serial_port_in(port, UART_LSR); + iir = serial_port_in(port, UART_IIR); + serial_port_out(port, UART_IER, 0); + + if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) { + if (!(up->bugs & UART_BUG_TXEN)) { + up->bugs |= UART_BUG_TXEN; + pr_debug("ttyS%d - enabling bad tx status workarounds\n", + serial_index(port)); + } + } else { + up->bugs &= ~UART_BUG_TXEN; + } + +dont_test_tx_en: + spin_unlock_irqrestore(&port->lock, flags); + + /* + * Clear the interrupt registers again for luck, and clear the + * saved flags to avoid getting false values from polling + * routines or the previous session. + */ + serial_port_in(port, UART_LSR); + serial_port_in(port, UART_RX); + serial_port_in(port, UART_IIR); + serial_port_in(port, UART_MSR); + up->lsr_saved_flags = 0; + up->msr_saved_flags = 0; + + /* + * Request DMA channels for both RX and TX. + */ + if (up->dma) { + retval = serial8250_request_dma(up); + if (retval) { + pr_warn_ratelimited("ttyS%d - failed to request DMA\n", + serial_index(port)); + up->dma = NULL; + } + } + + /* + * Set the IER shadow for rx interrupts but defer actual interrupt + * enable until after the FIFOs are enabled; otherwise, an already- + * active sender can swamp the interrupt handler with "too much work". + */ + up->ier = UART_IER_RLSI | UART_IER_RDI; + + if (port->flags & UPF_FOURPORT) { + unsigned int icp; + /* + * Enable interrupts on the AST Fourport board + */ + icp = (port->iobase & 0xfe0) | 0x01f; + outb_p(0x80, icp); + inb_p(icp); + } + retval = 0; +out: + serial8250_rpm_put(up); + return retval; +} +EXPORT_SYMBOL_GPL(serial8250_do_startup); + +static int serial8250_startup(struct uart_port *port) +{ + if (port->startup) + return port->startup(port); + return serial8250_do_startup(port); +} + +void serial8250_do_shutdown(struct uart_port *port) +{ + struct uart_8250_port *up = up_to_u8250p(port); + unsigned long flags; + + serial8250_rpm_get(up); + /* + * Disable interrupts from this port + */ + spin_lock_irqsave(&port->lock, flags); + up->ier = 0; + serial_port_out(port, UART_IER, 0); + spin_unlock_irqrestore(&port->lock, flags); + + synchronize_irq(port->irq); + + if (up->dma) + serial8250_release_dma(up); + + spin_lock_irqsave(&port->lock, flags); + if (port->flags & UPF_FOURPORT) { + /* reset interrupts on the AST Fourport board */ + inb((port->iobase & 0xfe0) | 0x1f); + port->mctrl |= TIOCM_OUT1; + } else + port->mctrl &= ~TIOCM_OUT2; + + serial8250_set_mctrl(port, port->mctrl); + spin_unlock_irqrestore(&port->lock, flags); + + /* + * Disable break condition and FIFOs + */ + serial_port_out(port, UART_LCR, + serial_port_in(port, UART_LCR) & ~UART_LCR_SBC); + serial8250_clear_fifos(up); + +#ifdef CONFIG_SERIAL_8250_RSA + /* + * Reset the RSA board back to 115kbps compat mode. + */ + disable_rsa(up); +#endif + + /* + * Read data port to reset things, and then unlink from + * the IRQ chain. + */ + serial_port_in(port, UART_RX); + serial8250_rpm_put(up); + + up->ops->release_irq(up); +} +EXPORT_SYMBOL_GPL(serial8250_do_shutdown); + +static void serial8250_shutdown(struct uart_port *port) +{ + if (port->shutdown) + port->shutdown(port); + else + serial8250_do_shutdown(port); +} + +/* + * XR17V35x UARTs have an extra fractional divisor register (DLD) + * Calculate divisor with extra 4-bit fractional portion + */ +static unsigned int xr17v35x_get_divisor(struct uart_8250_port *up, + unsigned int baud, + unsigned int *frac) +{ + struct uart_port *port = &up->port; + unsigned int quot_16; + + quot_16 = DIV_ROUND_CLOSEST(port->uartclk, baud); + *frac = quot_16 & 0x0f; + + return quot_16 >> 4; +} + +static unsigned int serial8250_get_divisor(struct uart_8250_port *up, + unsigned int baud, + unsigned int *frac) +{ + struct uart_port *port = &up->port; + unsigned int quot; + + /* + * Handle magic divisors for baud rates above baud_base on + * SMSC SuperIO chips. + * + */ + if ((port->flags & UPF_MAGIC_MULTIPLIER) && + baud == (port->uartclk/4)) + quot = 0x8001; + else if ((port->flags & UPF_MAGIC_MULTIPLIER) && + baud == (port->uartclk/8)) + quot = 0x8002; + else if (up->port.type == PORT_XR17V35X) + quot = xr17v35x_get_divisor(up, baud, frac); + else + quot = uart_get_divisor(port, baud); + + /* + * Oxford Semi 952 rev B workaround + */ + if (up->bugs & UART_BUG_QUOT && (quot & 0xff) == 0) + quot++; + + return quot; +} + +static unsigned char serial8250_compute_lcr(struct uart_8250_port *up, + tcflag_t c_cflag) +{ + unsigned char cval; + + switch (c_cflag & CSIZE) { + case CS5: + cval = UART_LCR_WLEN5; + break; + case CS6: + cval = UART_LCR_WLEN6; + break; + case CS7: + cval = UART_LCR_WLEN7; + break; + default: + case CS8: + cval = UART_LCR_WLEN8; + break; + } + + if (c_cflag & CSTOPB) + cval |= UART_LCR_STOP; + if (c_cflag & PARENB) { + cval |= UART_LCR_PARITY; + if (up->bugs & UART_BUG_PARITY) + up->fifo_bug = true; + } + if (!(c_cflag & PARODD)) + cval |= UART_LCR_EPAR; +#ifdef CMSPAR + if (c_cflag & CMSPAR) + cval |= UART_LCR_SPAR; +#endif + + return cval; +} + +static void serial8250_set_divisor(struct uart_port *port, unsigned int baud, + unsigned int quot, unsigned int quot_frac) +{ + struct uart_8250_port *up = up_to_u8250p(port); + + /* Workaround to enable 115200 baud on OMAP1510 internal ports */ + if (is_omap1510_8250(up)) { + if (baud == 115200) { + quot = 1; + serial_port_out(port, UART_OMAP_OSC_12M_SEL, 1); + } else + serial_port_out(port, UART_OMAP_OSC_12M_SEL, 0); + } + + /* + * For NatSemi, switch to bank 2 not bank 1, to avoid resetting EXCR2, + * otherwise just set DLAB + */ + if (up->capabilities & UART_NATSEMI) + serial_port_out(port, UART_LCR, 0xe0); + else + serial_port_out(port, UART_LCR, up->lcr | UART_LCR_DLAB); + + serial_dl_write(up, quot); + + /* XR17V35x UARTs have an extra fractional divisor register (DLD) */ + if (up->port.type == PORT_XR17V35X) + serial_port_out(port, 0x2, quot_frac); +} + +static unsigned int serial8250_get_baud_rate(struct uart_port *port, + struct ktermios *termios, + struct ktermios *old) +{ + unsigned int tolerance = port->uartclk / 100; + + /* + * Ask the core to calculate the divisor for us. + * Allow 1% tolerance at the upper limit so uart clks marginally + * slower than nominal still match standard baud rates without + * causing transmission errors. + */ + return uart_get_baud_rate(port, termios, old, + port->uartclk / 16 / 0xffff, + (port->uartclk + tolerance) / 16); +} + +void +serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) +{ + struct uart_8250_port *up = up_to_u8250p(port); + unsigned char cval; + unsigned long flags; + unsigned int baud, quot, frac = 0; + + cval = serial8250_compute_lcr(up, termios->c_cflag); + + baud = serial8250_get_baud_rate(port, termios, old); + quot = serial8250_get_divisor(up, baud, &frac); + + /* + * Ok, we're now changing the port state. Do it with + * interrupts disabled. + */ + serial8250_rpm_get(up); + spin_lock_irqsave(&port->lock, flags); + + up->lcr = cval; /* Save computed LCR */ + + if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) { + /* NOTE: If fifo_bug is not set, a user can set RX_trigger. */ + if ((baud < 2400 && !up->dma) || up->fifo_bug) { + up->fcr &= ~UART_FCR_TRIGGER_MASK; + up->fcr |= UART_FCR_TRIGGER_1; + } + } + + /* + * MCR-based auto flow control. When AFE is enabled, RTS will be + * deasserted when the receive FIFO contains more characters than + * the trigger, or the MCR RTS bit is cleared. In the case where + * the remote UART is not using CTS auto flow control, we must + * have sufficient FIFO entries for the latency of the remote + * UART to respond. IOW, at least 32 bytes of FIFO. + */ + if (up->capabilities & UART_CAP_AFE && port->fifosize >= 32) { + up->mcr &= ~UART_MCR_AFE; + if (termios->c_cflag & CRTSCTS) + up->mcr |= UART_MCR_AFE; + } + + /* + * Update the per-port timeout. + */ + uart_update_timeout(port, termios->c_cflag, baud); + + port->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; + if (termios->c_iflag & INPCK) + port->read_status_mask |= UART_LSR_FE | UART_LSR_PE; + if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK)) + port->read_status_mask |= UART_LSR_BI; + + /* + * Characteres to ignore + */ + port->ignore_status_mask = 0; + if (termios->c_iflag & IGNPAR) + port->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; + if (termios->c_iflag & IGNBRK) { + port->ignore_status_mask |= UART_LSR_BI; + /* + * If we're ignoring parity and break indicators, + * ignore overruns too (for real raw support). + */ + if (termios->c_iflag & IGNPAR) + port->ignore_status_mask |= UART_LSR_OE; + } + + /* + * ignore all characters if CREAD is not set + */ + if ((termios->c_cflag & CREAD) == 0) + port->ignore_status_mask |= UART_LSR_DR; + + /* + * CTS flow control flag and modem status interrupts + */ + up->ier &= ~UART_IER_MSI; + if (!(up->bugs & UART_BUG_NOMSR) && + UART_ENABLE_MS(&up->port, termios->c_cflag)) + up->ier |= UART_IER_MSI; + if (up->capabilities & UART_CAP_UUE) + up->ier |= UART_IER_UUE; + if (up->capabilities & UART_CAP_RTOIE) + up->ier |= UART_IER_RTOIE; + + serial_port_out(port, UART_IER, up->ier); + + if (up->capabilities & UART_CAP_EFR) { + unsigned char efr = 0; + /* + * TI16C752/Startech hardware flow control. FIXME: + * - TI16C752 requires control thresholds to be set. + * - UART_MCR_RTS is ineffective if auto-RTS mode is enabled. + */ + if (termios->c_cflag & CRTSCTS) + efr |= UART_EFR_CTS; + + serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B); + if (port->flags & UPF_EXAR_EFR) + serial_port_out(port, UART_XR_EFR, efr); + else + serial_port_out(port, UART_EFR, efr); + } + + serial8250_set_divisor(port, baud, quot, frac); + + /* + * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR + * is written without DLAB set, this mode will be disabled. + */ + if (port->type == PORT_16750) + serial_port_out(port, UART_FCR, up->fcr); + + serial_port_out(port, UART_LCR, up->lcr); /* reset DLAB */ + if (port->type != PORT_16750) { + /* emulated UARTs (Lucent Venus 167x) need two steps */ + if (up->fcr & UART_FCR_ENABLE_FIFO) + serial_port_out(port, UART_FCR, UART_FCR_ENABLE_FIFO); + serial_port_out(port, UART_FCR, up->fcr); /* set fcr */ + } + serial8250_set_mctrl(port, port->mctrl); + spin_unlock_irqrestore(&port->lock, flags); + serial8250_rpm_put(up); + + /* Don't rewrite B0 */ + if (tty_termios_baud_rate(termios)) + tty_termios_encode_baud_rate(termios, baud, baud); +} +EXPORT_SYMBOL(serial8250_do_set_termios); + +static void +serial8250_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) +{ + if (port->set_termios) + port->set_termios(port, termios, old); + else + serial8250_do_set_termios(port, termios, old); +} + +static void +serial8250_set_ldisc(struct uart_port *port, struct ktermios *termios) +{ + if (termios->c_line == N_PPS) { + port->flags |= UPF_HARDPPS_CD; + spin_lock_irq(&port->lock); + serial8250_enable_ms(port); + spin_unlock_irq(&port->lock); + } else { + port->flags &= ~UPF_HARDPPS_CD; + if (!UART_ENABLE_MS(port, termios->c_cflag)) { + spin_lock_irq(&port->lock); + serial8250_disable_ms(port); + spin_unlock_irq(&port->lock); + } + } +} + + +void serial8250_do_pm(struct uart_port *port, unsigned int state, + unsigned int oldstate) +{ + struct uart_8250_port *p = up_to_u8250p(port); + + serial8250_set_sleep(p, state != 0); +} +EXPORT_SYMBOL(serial8250_do_pm); + +static void +serial8250_pm(struct uart_port *port, unsigned int state, + unsigned int oldstate) +{ + if (port->pm) + port->pm(port, state, oldstate); + else + serial8250_do_pm(port, state, oldstate); +} + +static unsigned int serial8250_port_size(struct uart_8250_port *pt) +{ + if (pt->port.mapsize) + return pt->port.mapsize; + if (pt->port.iotype == UPIO_AU) { + if (pt->port.type == PORT_RT2880) + return 0x100; + return 0x1000; + } + if (is_omap1_8250(pt)) + return 0x16 << pt->port.regshift; + + return 8 << pt->port.regshift; +} + +/* + * Resource handling. + */ +static int serial8250_request_std_resource(struct uart_8250_port *up) +{ + unsigned int size = serial8250_port_size(up); + struct uart_port *port = &up->port; + int ret = 0; + + switch (port->iotype) { + case UPIO_AU: + case UPIO_TSI: + case UPIO_MEM32: + case UPIO_MEM32BE: + case UPIO_MEM16: + case UPIO_MEM: + if (!port->mapbase) + break; + + if (!request_mem_region(port->mapbase, size, "serial")) { + ret = -EBUSY; + break; + } + + if (port->flags & UPF_IOREMAP) { + port->membase = ioremap_nocache(port->mapbase, size); + if (!port->membase) { + release_mem_region(port->mapbase, size); + ret = -ENOMEM; + } + } + break; + + case UPIO_HUB6: + case UPIO_PORT: + if (!request_region(port->iobase, size, "serial")) + ret = -EBUSY; + break; + } + return ret; +} + +static void serial8250_release_std_resource(struct uart_8250_port *up) +{ + unsigned int size = serial8250_port_size(up); + struct uart_port *port = &up->port; + + switch (port->iotype) { + case UPIO_AU: + case UPIO_TSI: + case UPIO_MEM32: + case UPIO_MEM32BE: + case UPIO_MEM16: + case UPIO_MEM: + if (!port->mapbase) + break; + + if (port->flags & UPF_IOREMAP) { + iounmap(port->membase); + port->membase = NULL; + } + + release_mem_region(port->mapbase, size); + break; + + case UPIO_HUB6: + case UPIO_PORT: + release_region(port->iobase, size); + break; + } +} + +static void serial8250_release_port(struct uart_port *port) +{ + struct uart_8250_port *up = up_to_u8250p(port); + + serial8250_release_std_resource(up); +} + +static int serial8250_request_port(struct uart_port *port) +{ + struct uart_8250_port *up = up_to_u8250p(port); + + return serial8250_request_std_resource(up); +} + +static int fcr_get_rxtrig_bytes(struct uart_8250_port *up) +{ + const struct serial8250_config *conf_type = &uart_config[up->port.type]; + unsigned char bytes; + + bytes = conf_type->rxtrig_bytes[UART_FCR_R_TRIG_BITS(up->fcr)]; + + return bytes ? bytes : -EOPNOTSUPP; +} + +static int bytes_to_fcr_rxtrig(struct uart_8250_port *up, unsigned char bytes) +{ + const struct serial8250_config *conf_type = &uart_config[up->port.type]; + int i; + + if (!conf_type->rxtrig_bytes[UART_FCR_R_TRIG_BITS(UART_FCR_R_TRIG_00)]) + return -EOPNOTSUPP; + + for (i = 1; i < UART_FCR_R_TRIG_MAX_STATE; i++) { + if (bytes < conf_type->rxtrig_bytes[i]) + /* Use the nearest lower value */ + return (--i) << UART_FCR_R_TRIG_SHIFT; + } + + return UART_FCR_R_TRIG_11; +} + +static int do_get_rxtrig(struct tty_port *port) +{ + struct uart_state *state = container_of(port, struct uart_state, port); + struct uart_port *uport = state->uart_port; + struct uart_8250_port *up = up_to_u8250p(uport); + + if (!(up->capabilities & UART_CAP_FIFO) || uport->fifosize <= 1) + return -EINVAL; + + return fcr_get_rxtrig_bytes(up); +} + +static int do_serial8250_get_rxtrig(struct tty_port *port) +{ + int rxtrig_bytes; + + mutex_lock(&port->mutex); + rxtrig_bytes = do_get_rxtrig(port); + mutex_unlock(&port->mutex); + + return rxtrig_bytes; +} + +static ssize_t serial8250_get_attr_rx_trig_bytes(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct tty_port *port = dev_get_drvdata(dev); + int rxtrig_bytes; + + rxtrig_bytes = do_serial8250_get_rxtrig(port); + if (rxtrig_bytes < 0) + return rxtrig_bytes; + + return snprintf(buf, PAGE_SIZE, "%d\n", rxtrig_bytes); +} + +static int do_set_rxtrig(struct tty_port *port, unsigned char bytes) +{ + struct uart_state *state = container_of(port, struct uart_state, port); + struct uart_port *uport = state->uart_port; + struct uart_8250_port *up = up_to_u8250p(uport); + int rxtrig; + + if (!(up->capabilities & UART_CAP_FIFO) || uport->fifosize <= 1 || + up->fifo_bug) + return -EINVAL; + + rxtrig = bytes_to_fcr_rxtrig(up, bytes); + if (rxtrig < 0) + return rxtrig; + + serial8250_clear_fifos(up); + up->fcr &= ~UART_FCR_TRIGGER_MASK; + up->fcr |= (unsigned char)rxtrig; + serial_out(up, UART_FCR, up->fcr); + return 0; +} + +static int do_serial8250_set_rxtrig(struct tty_port *port, unsigned char bytes) +{ + int ret; + + mutex_lock(&port->mutex); + ret = do_set_rxtrig(port, bytes); + mutex_unlock(&port->mutex); + + return ret; +} + +static ssize_t serial8250_set_attr_rx_trig_bytes(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct tty_port *port = dev_get_drvdata(dev); + unsigned char bytes; + int ret; + + if (!count) + return -EINVAL; + + ret = kstrtou8(buf, 10, &bytes); + if (ret < 0) + return ret; + + ret = do_serial8250_set_rxtrig(port, bytes); + if (ret < 0) + return ret; + + return count; +} + +static DEVICE_ATTR(rx_trig_bytes, S_IRUSR | S_IWUSR | S_IRGRP, + serial8250_get_attr_rx_trig_bytes, + serial8250_set_attr_rx_trig_bytes); + +static struct attribute *serial8250_dev_attrs[] = { + &dev_attr_rx_trig_bytes.attr, + NULL, + }; + +static struct attribute_group serial8250_dev_attr_group = { + .attrs = serial8250_dev_attrs, + }; + +static void register_dev_spec_attr_grp(struct uart_8250_port *up) +{ + const struct serial8250_config *conf_type = &uart_config[up->port.type]; + + if (conf_type->rxtrig_bytes[0]) + up->port.attr_group = &serial8250_dev_attr_group; +} + +static void serial8250_config_port(struct uart_port *port, int flags) +{ + struct uart_8250_port *up = up_to_u8250p(port); + int ret; + + /* + * Find the region that we can probe for. This in turn + * tells us whether we can probe for the type of port. + */ + ret = serial8250_request_std_resource(up); + if (ret < 0) + return; + + if (port->iotype != up->cur_iotype) + set_io_from_upio(port); + + if (flags & UART_CONFIG_TYPE) + autoconfig(up); + + /* if access method is AU, it is a 16550 with a quirk */ + if (port->type == PORT_16550A && port->iotype == UPIO_AU) + up->bugs |= UART_BUG_NOMSR; + + /* HW bugs may trigger IRQ while IIR == NO_INT */ + if (port->type == PORT_TEGRA) + up->bugs |= UART_BUG_NOMSR; + + if (port->type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ) + autoconfig_irq(up); + + if (port->type == PORT_UNKNOWN) + serial8250_release_std_resource(up); + + /* Fixme: probably not the best place for this */ + if ((port->type == PORT_XR17V35X) || + (port->type == PORT_XR17D15X)) + port->handle_irq = exar_handle_irq; + + register_dev_spec_attr_grp(up); + up->fcr = uart_config[up->port.type].fcr; +} + +static int +serial8250_verify_port(struct uart_port *port, struct serial_struct *ser) +{ + if (ser->irq >= nr_irqs || ser->irq < 0 || + ser->baud_base < 9600 || ser->type < PORT_UNKNOWN || + ser->type >= ARRAY_SIZE(uart_config) || ser->type == PORT_CIRRUS || + ser->type == PORT_STARTECH) + return -EINVAL; + return 0; +} + +static const char *serial8250_type(struct uart_port *port) +{ + int type = port->type; + + if (type >= ARRAY_SIZE(uart_config)) + type = 0; + return uart_config[type].name; +} + +static const struct uart_ops serial8250_pops = { + .tx_empty = serial8250_tx_empty, + .set_mctrl = serial8250_set_mctrl, + .get_mctrl = serial8250_get_mctrl, + .stop_tx = serial8250_stop_tx, + .start_tx = serial8250_start_tx, + .throttle = serial8250_throttle, + .unthrottle = serial8250_unthrottle, + .stop_rx = serial8250_stop_rx, + .enable_ms = serial8250_enable_ms, + .break_ctl = serial8250_break_ctl, + .startup = serial8250_startup, + .shutdown = serial8250_shutdown, + .set_termios = serial8250_set_termios, + .set_ldisc = serial8250_set_ldisc, + .pm = serial8250_pm, + .type = serial8250_type, + .release_port = serial8250_release_port, + .request_port = serial8250_request_port, + .config_port = serial8250_config_port, + .verify_port = serial8250_verify_port, +#ifdef CONFIG_CONSOLE_POLL + .poll_get_char = serial8250_get_poll_char, + .poll_put_char = serial8250_put_poll_char, +#endif +}; + +void serial8250_init_port(struct uart_8250_port *up) +{ + struct uart_port *port = &up->port; + + spin_lock_init(&port->lock); + port->ops = &serial8250_pops; + + up->cur_iotype = 0xFF; +} +EXPORT_SYMBOL_GPL(serial8250_init_port); + +void serial8250_set_defaults(struct uart_8250_port *up) +{ + struct uart_port *port = &up->port; + + if (up->port.flags & UPF_FIXED_TYPE) { + unsigned int type = up->port.type; + + if (!up->port.fifosize) + up->port.fifosize = uart_config[type].fifo_size; + if (!up->tx_loadsz) + up->tx_loadsz = uart_config[type].tx_loadsz; + if (!up->capabilities) + up->capabilities = uart_config[type].flags; + } + + set_io_from_upio(port); + + /* default dma handlers */ + if (up->dma) { + if (!up->dma->tx_dma) + up->dma->tx_dma = serial8250_tx_dma; + if (!up->dma->rx_dma) + up->dma->rx_dma = serial8250_rx_dma; + } +} +EXPORT_SYMBOL_GPL(serial8250_set_defaults); + +#ifdef CONFIG_SERIAL_8250_CONSOLE + +static void serial8250_console_putchar(struct uart_port *port, int ch) +{ + struct uart_8250_port *up = up_to_u8250p(port); + + wait_for_xmitr(up, UART_LSR_THRE); + serial_port_out(port, UART_TX, ch); +} + +/* + * Restore serial console when h/w power-off detected + */ +static void serial8250_console_restore(struct uart_8250_port *up) +{ + struct uart_port *port = &up->port; + struct ktermios termios; + unsigned int baud, quot, frac = 0; + + termios.c_cflag = port->cons->cflag; + if (port->state->port.tty && termios.c_cflag == 0) + termios.c_cflag = port->state->port.tty->termios.c_cflag; + + baud = serial8250_get_baud_rate(port, &termios, NULL); + quot = serial8250_get_divisor(up, baud, &frac); + + serial8250_set_divisor(port, baud, quot, frac); + serial_port_out(port, UART_LCR, up->lcr); + serial8250_out_MCR(up, UART_MCR_DTR | UART_MCR_RTS); +} + +/* + * Print a string to the serial port trying not to disturb + * any possible real use of the port... + * + * The console_lock must be held when we get here. + */ +void serial8250_console_write(struct uart_8250_port *up, const char *s, + unsigned int count) +{ + struct uart_port *port = &up->port; + unsigned long flags; + unsigned int ier; + int locked = 1; + + touch_nmi_watchdog(); + + serial8250_rpm_get(up); + + if (port->sysrq) + locked = 0; + else if (oops_in_progress) + locked = spin_trylock_irqsave(&port->lock, flags); + else + spin_lock_irqsave(&port->lock, flags); + + /* + * First save the IER then disable the interrupts + */ + ier = serial_port_in(port, UART_IER); + + if (up->capabilities & UART_CAP_UUE) + serial_port_out(port, UART_IER, UART_IER_UUE); + else + serial_port_out(port, UART_IER, 0); + + /* check scratch reg to see if port powered off during system sleep */ + if (up->canary && (up->canary != serial_port_in(port, UART_SCR))) { + serial8250_console_restore(up); + up->canary = 0; + } + + uart_console_write(port, s, count, serial8250_console_putchar); + + /* + * Finally, wait for transmitter to become empty + * and restore the IER + */ + wait_for_xmitr(up, BOTH_EMPTY); + serial_port_out(port, UART_IER, ier); + + /* + * The receive handling will happen properly because the + * receive ready bit will still be set; it is not cleared + * on read. However, modem control will not, we must + * call it if we have saved something in the saved flags + * while processing with interrupts off. + */ + if (up->msr_saved_flags) + serial8250_modem_status(up); + + if (locked) + spin_unlock_irqrestore(&port->lock, flags); + serial8250_rpm_put(up); +} + +static unsigned int probe_baud(struct uart_port *port) +{ + unsigned char lcr, dll, dlm; + unsigned int quot; + + lcr = serial_port_in(port, UART_LCR); + serial_port_out(port, UART_LCR, lcr | UART_LCR_DLAB); + dll = serial_port_in(port, UART_DLL); + dlm = serial_port_in(port, UART_DLM); + serial_port_out(port, UART_LCR, lcr); + + quot = (dlm << 8) | dll; + return (port->uartclk / 16) / quot; +} + +int serial8250_console_setup(struct uart_port *port, char *options, bool probe) +{ + int baud = 9600; + int bits = 8; + int parity = 'n'; + int flow = 'n'; + + if (!port->iobase && !port->membase) + return -ENODEV; + + if (options) + uart_parse_options(options, &baud, &parity, &bits, &flow); + else if (probe) + baud = probe_baud(port); + + return uart_set_options(port, port->cons, baud, parity, bits, flow); +} + +#endif /* CONFIG_SERIAL_8250_CONSOLE */ + +MODULE_LICENSE("GPL"); diff --git a/drivers/tty/serial/8250/8250_uniphier.c b/drivers/tty/serial/8250/8250_uniphier.c new file mode 100644 index 000000000..b8d9c8c9d --- /dev/null +++ b/drivers/tty/serial/8250/8250_uniphier.c @@ -0,0 +1,286 @@ +/* + * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/clk.h> +#include <linux/console.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> + +#include "8250.h" + +/* Most (but not all) of UniPhier UART devices have 64-depth FIFO. */ +#define UNIPHIER_UART_DEFAULT_FIFO_SIZE 64 + +#define UNIPHIER_UART_CHAR_FCR 3 /* Character / FIFO Control Register */ +#define UNIPHIER_UART_LCR_MCR 4 /* Line/Modem Control Register */ +#define UNIPHIER_UART_LCR_SHIFT 8 +#define UNIPHIER_UART_DLR 9 /* Divisor Latch Register */ + +struct uniphier8250_priv { + int line; + struct clk *clk; + spinlock_t atomic_write_lock; +}; + +#ifdef CONFIG_SERIAL_8250_CONSOLE +static int __init uniphier_early_console_setup(struct earlycon_device *device, + const char *options) +{ + if (!device->port.membase) + return -ENODEV; + + /* This hardware always expects MMIO32 register interface. */ + device->port.iotype = UPIO_MEM32; + device->port.regshift = 2; + + /* + * Do not touch the divisor register in early_serial8250_setup(); + * we assume it has been initialized by a boot loader. + */ + device->baud = 0; + + return early_serial8250_setup(device, options); +} +OF_EARLYCON_DECLARE(uniphier, "socionext,uniphier-uart", + uniphier_early_console_setup); +#endif + +/* + * The register map is slightly different from that of 8250. + * IO callbacks must be overridden for correct access to FCR, LCR, and MCR. + */ +static unsigned int uniphier_serial_in(struct uart_port *p, int offset) +{ + unsigned int valshift = 0; + + switch (offset) { + case UART_LCR: + valshift = UNIPHIER_UART_LCR_SHIFT; + /* fall through */ + case UART_MCR: + offset = UNIPHIER_UART_LCR_MCR; + break; + default: + break; + } + + offset <<= p->regshift; + + /* + * The return value must be masked with 0xff because LCR and MCR reside + * in the same register that must be accessed by 32-bit write/read. + * 8 or 16 bit access to this hardware result in unexpected behavior. + */ + return (readl(p->membase + offset) >> valshift) & 0xff; +} + +static void uniphier_serial_out(struct uart_port *p, int offset, int value) +{ + unsigned int valshift = 0; + bool normal = false; + + switch (offset) { + case UART_FCR: + offset = UNIPHIER_UART_CHAR_FCR; + break; + case UART_LCR: + valshift = UNIPHIER_UART_LCR_SHIFT; + /* Divisor latch access bit does not exist. */ + value &= ~(UART_LCR_DLAB << valshift); + /* fall through */ + case UART_MCR: + offset = UNIPHIER_UART_LCR_MCR; + break; + default: + normal = true; + break; + } + + offset <<= p->regshift; + + if (normal) { + writel(value, p->membase + offset); + } else { + /* + * Special case: two registers share the same address that + * must be 32-bit accessed. As this is not longer atomic safe, + * take a lock just in case. + */ + struct uniphier8250_priv *priv = p->private_data; + unsigned long flags; + u32 tmp; + + spin_lock_irqsave(&priv->atomic_write_lock, flags); + tmp = readl(p->membase + offset); + tmp &= ~(0xff << valshift); + tmp |= value << valshift; + writel(tmp, p->membase + offset); + spin_unlock_irqrestore(&priv->atomic_write_lock, flags); + } +} + +/* + * This hardware does not have the divisor latch access bit. + * The divisor latch register exists at different address. + * Override dl_read/write callbacks. + */ +static int uniphier_serial_dl_read(struct uart_8250_port *up) +{ + int offset = UNIPHIER_UART_DLR << up->port.regshift; + + return readl(up->port.membase + offset); +} + +static void uniphier_serial_dl_write(struct uart_8250_port *up, int value) +{ + int offset = UNIPHIER_UART_DLR << up->port.regshift; + + writel(value, up->port.membase + offset); +} + +static int uniphier_of_serial_setup(struct device *dev, struct uart_port *port, + struct uniphier8250_priv *priv) +{ + int ret; + u32 prop; + struct device_node *np = dev->of_node; + + ret = of_alias_get_id(np, "serial"); + if (ret < 0) { + dev_err(dev, "failed to get alias id\n"); + return ret; + } + port->line = priv->line = ret; + + /* Get clk rate through clk driver */ + priv->clk = devm_clk_get(dev, NULL); + if (IS_ERR(priv->clk)) { + dev_err(dev, "failed to get clock\n"); + return PTR_ERR(priv->clk); + } + + ret = clk_prepare_enable(priv->clk); + if (ret < 0) + return ret; + + port->uartclk = clk_get_rate(priv->clk); + + /* Check for fifo size */ + if (of_property_read_u32(np, "fifo-size", &prop) == 0) + port->fifosize = prop; + else + port->fifosize = UNIPHIER_UART_DEFAULT_FIFO_SIZE; + + return 0; +} + +static int uniphier_uart_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct uart_8250_port up; + struct uniphier8250_priv *priv; + struct resource *regs; + void __iomem *membase; + int irq; + int ret; + + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!regs) { + dev_err(dev, "failed to get memory resource"); + return -EINVAL; + } + + membase = devm_ioremap(dev, regs->start, resource_size(regs)); + if (!membase) + return -ENOMEM; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(dev, "failed to get IRQ number\n"); + return irq; + } + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + memset(&up, 0, sizeof(up)); + + ret = uniphier_of_serial_setup(dev, &up.port, priv); + if (ret < 0) + return ret; + + spin_lock_init(&priv->atomic_write_lock); + + up.port.dev = dev; + up.port.private_data = priv; + up.port.mapbase = regs->start; + up.port.mapsize = resource_size(regs); + up.port.membase = membase; + up.port.irq = irq; + + up.port.type = PORT_16550A; + up.port.iotype = UPIO_MEM32; + up.port.regshift = 2; + up.port.flags = UPF_FIXED_PORT | UPF_FIXED_TYPE; + up.capabilities = UART_CAP_FIFO; + + up.port.serial_in = uniphier_serial_in; + up.port.serial_out = uniphier_serial_out; + up.dl_read = uniphier_serial_dl_read; + up.dl_write = uniphier_serial_dl_write; + + ret = serial8250_register_8250_port(&up); + if (ret < 0) { + dev_err(dev, "failed to register 8250 port\n"); + clk_disable_unprepare(priv->clk); + return ret; + } + + platform_set_drvdata(pdev, priv); + + return 0; +} + +static int uniphier_uart_remove(struct platform_device *pdev) +{ + struct uniphier8250_priv *priv = platform_get_drvdata(pdev); + + serial8250_unregister_port(priv->line); + clk_disable_unprepare(priv->clk); + + return 0; +} + +static const struct of_device_id uniphier_uart_match[] = { + { .compatible = "socionext,uniphier-uart" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, uniphier_uart_match); + +static struct platform_driver uniphier_uart_platform_driver = { + .probe = uniphier_uart_probe, + .remove = uniphier_uart_remove, + .driver = { + .name = "uniphier-uart", + .of_match_table = uniphier_uart_match, + }, +}; +module_platform_driver(uniphier_uart_platform_driver); + +MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro@socionext.com>"); +MODULE_DESCRIPTION("UniPhier UART driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index c35070356..7c6f7afca 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -57,6 +57,18 @@ config SERIAL_8250_PNP This builds standard PNP serial support. You may be able to disable this feature if you only need legacy serial support. +config SERIAL_8250_FINTEK + bool "Support for Fintek F81216A LPC to 4 UART RS485 API" + depends on SERIAL_8250 + ---help--- + Selecting this option will add support for the RS485 capabilities + of the Fintek F81216A LPC to 4 UART. + + If this option is not selected the device will be configured as a + standard 16550A serial port. + + If unsure, say N. + config SERIAL_8250_CONSOLE bool "Console on 8250/16550 and compatible serial port" depends on SERIAL_8250=y @@ -262,7 +274,12 @@ config SERIAL_8250_RSA bool "Support RSA serial ports" depends on SERIAL_8250_EXTENDED help - ::: To be written ::: + Say Y here if you have a IODATA RSA-DV II/S ISA card and + would like to use its >115kbps speeds. + You will need to provide module parameter "probe_rsa", or boot-time + parameter 8250.probe_rsa with I/O addresses of this card then. + + If you don't have such card, or if unsure, say N. config SERIAL_8250_ACORN tristate "Acorn expansion card serial port support" @@ -272,10 +289,34 @@ config SERIAL_8250_ACORN system, say Y to this option. The driver can handle 1, 2, or 3 port cards. If unsure, say N. +config SERIAL_8250_BCM2835AUX + tristate "BCM2835 auxiliar mini UART support" + depends on ARCH_BCM2835 || COMPILE_TEST + depends on SERIAL_8250 && SERIAL_8250_SHARE_IRQ + help + Support for the BCM2835 auxiliar mini UART. + + Features and limitations of the UART are + Registers are similar to 16650 registers, + set bits in the control registers that are unsupported + are ignored and read back as 0 + 7/8 bit operation with 1 start and 1 stop bit + 8 symbols deep fifo for rx and tx + SW controlled RTS and SW readable CTS + Clock rate derived from system clock + Uses 8 times oversampling (compared to 16 times for 16650) + Missing break detection (but break generation) + Missing framing error detection + Missing parity bit + Missing receive time-out interrupt + Missing DCD, DSR, DTR and RI signals + + If unsure, say N. + config SERIAL_8250_FSL bool - depends on SERIAL_8250_CONSOLE && PPC_UDBG_16550 - default PPC + depends on SERIAL_8250_CONSOLE + default PPC || ARM || ARM64 config SERIAL_8250_DW tristate "Support for Synopsys DesignWare 8250 quirks" @@ -294,11 +335,12 @@ config SERIAL_8250_EM config SERIAL_8250_RT288X bool "Ralink RT288x/RT305x/RT3662/RT3883 serial port support" - depends on SERIAL_8250 && (SOC_RT288X || SOC_RT305X || SOC_RT3883 || SOC_MT7620) + depends on SERIAL_8250 + default y if MIPS_ALCHEMY || SOC_RT288X || SOC_RT305X || SOC_RT3883 || SOC_MT7620 help - If you have a Ralink RT288x/RT305x SoC based board and want to use the - serial port, say Y to this option. The driver can handle up to 2 serial - ports. If unsure, say N. + Selecting this option will add support for the alternate register + layout used by Ralink RT288x/RT305x, Alchemy Au1xxx, and some others. + If unsure, say N. config SERIAL_8250_OMAP tristate "Support for OMAP internal UART (8250 based driver)" @@ -328,17 +370,66 @@ config SERIAL_8250_OMAP_TTYO_FIXUP not booting kernel because the serial console remains silent in case they forgot to update the command line. -config SERIAL_8250_FINTEK - tristate "Support for Fintek F81216A LPC to 4 UART" - depends on SERIAL_8250 && PNP +config SERIAL_8250_LPC18XX + tristate "NXP LPC18xx/43xx serial port support" + depends on SERIAL_8250 && OF && (ARCH_LPC18XX || COMPILE_TEST) + default ARCH_LPC18XX help - Selecting this option will add support for the Fintek F81216A - LPC to 4 UART. This device has some RS485 functionality not available - through the PNP driver. If unsure, say N. + If you have a LPC18xx/43xx based board and want to use the + serial port, say Y to this option. If unsure, say Y. config SERIAL_8250_MT6577 - bool "Mediatek serial port support" + tristate "Mediatek serial port support" depends on SERIAL_8250 && ARCH_MEDIATEK help If you have a Mediatek based board and want to use the serial port, say Y to this option. If unsure, say N. + +config SERIAL_8250_UNIPHIER + tristate "Support for UniPhier on-chip UART" + depends on SERIAL_8250 + depends on ARCH_UNIPHIER || COMPILE_TEST + help + If you have a UniPhier based board and want to use the on-chip + serial ports, say Y to this option. If unsure, say N. + +config SERIAL_8250_INGENIC + tristate "Support for Ingenic SoC serial ports" + depends on SERIAL_8250 + depends on OF_FLATTREE + depends on MIPS || COMPILE_TEST + help + If you have a system using an Ingenic SoC and wish to make use of + its UARTs, say Y to this option. If unsure, say N. + +config SERIAL_8250_MID + tristate "Support for serial ports on Intel MID platforms" if EXPERT + default SERIAL_8250 + depends on SERIAL_8250 && PCI + depends on X86 || COMPILE_TEST + select HSU_DMA if SERIAL_8250_DMA + select HSU_DMA_PCI if (HSU_DMA && X86_INTEL_MID) + select RATIONAL + help + Selecting this option will enable handling of the extra features + present on the UART found on Intel Medfield SOC and various other + Intel platforms. + +config SERIAL_8250_MOXA + tristate "MOXA SmartIO MUE support" + depends on SERIAL_8250 && PCI + help + Say Y here if you have a Moxa SmartIO MUE multiport serial card. + If unsure, say N. + + This driver can also be built as a module. The module will be called + 8250_moxa. If you want to do that, say M here. + +config SERIAL_OF_PLATFORM + tristate "Devicetree based probing for 8250 ports" + depends on SERIAL_8250 && OF + help + This option is used for all 8250 compatible serial ports that + are probed through devicetree, including Open Firmware based + PowerPC systems and embedded systems on architectures using the + flattened device tree format. diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile index 31e7cdc68..367d403d2 100644 --- a/drivers/tty/serial/8250/Makefile +++ b/drivers/tty/serial/8250/Makefile @@ -2,15 +2,18 @@ # Makefile for the 8250 serial device drivers. # -obj-$(CONFIG_SERIAL_8250) += 8250.o +obj-$(CONFIG_SERIAL_8250) += 8250.o 8250_base.o 8250-y := 8250_core.o 8250-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o -8250-$(CONFIG_SERIAL_8250_DMA) += 8250_dma.o +8250_base-y := 8250_port.o +8250_base-$(CONFIG_SERIAL_8250_DMA) += 8250_dma.o +8250_base-$(CONFIG_SERIAL_8250_FINTEK) += 8250_fintek.o obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o obj-$(CONFIG_SERIAL_8250_CS) += serial_cs.o obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o +obj-$(CONFIG_SERIAL_8250_BCM2835AUX) += 8250_bcm2835aux.o obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o obj-$(CONFIG_SERIAL_8250_FOURPORT) += 8250_fourport.o obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o @@ -21,5 +24,12 @@ obj-$(CONFIG_SERIAL_8250_FSL) += 8250_fsl.o obj-$(CONFIG_SERIAL_8250_DW) += 8250_dw.o obj-$(CONFIG_SERIAL_8250_EM) += 8250_em.o obj-$(CONFIG_SERIAL_8250_OMAP) += 8250_omap.o -obj-$(CONFIG_SERIAL_8250_FINTEK) += 8250_fintek.o +obj-$(CONFIG_SERIAL_8250_LPC18XX) += 8250_lpc18xx.o obj-$(CONFIG_SERIAL_8250_MT6577) += 8250_mtk.o +obj-$(CONFIG_SERIAL_8250_UNIPHIER) += 8250_uniphier.o +obj-$(CONFIG_SERIAL_8250_INGENIC) += 8250_ingenic.o +obj-$(CONFIG_SERIAL_8250_MID) += 8250_mid.o +obj-$(CONFIG_SERIAL_8250_MOXA) += 8250_moxa.o +obj-$(CONFIG_SERIAL_OF_PLATFORM) += 8250_of.o + +CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt diff --git a/drivers/tty/serial/8250/serial_cs.c b/drivers/tty/serial/8250/serial_cs.c index 4d180c942..933c2688d 100644 --- a/drivers/tty/serial/8250/serial_cs.c +++ b/drivers/tty/serial/8250/serial_cs.c @@ -28,7 +28,7 @@ and other provisions required by the GPL. If you do not delete the provisions above, a recipient may use your version of this file under either the MPL or the GPL. - + ======================================================================*/ #include <linux/module.h> @@ -257,7 +257,7 @@ static const struct serial_quirk quirks[] = { }; -static int serial_config(struct pcmcia_device * link); +static int serial_config(struct pcmcia_device *link); static void serial_remove(struct pcmcia_device *link) @@ -309,7 +309,7 @@ static int serial_probe(struct pcmcia_device *link) dev_dbg(&link->dev, "serial_attach()\n"); /* Create new serial device */ - info = kzalloc(sizeof (*info), GFP_KERNEL); + info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; info->p_dev = link; @@ -339,7 +339,7 @@ static void serial_detach(struct pcmcia_device *link) /*====================================================================*/ -static int setup_serial(struct pcmcia_device *handle, struct serial_info * info, +static int setup_serial(struct pcmcia_device *handle, struct serial_info *info, unsigned int iobase, int irq) { struct uart_8250_port uart; @@ -441,16 +441,20 @@ static int simple_config(struct pcmcia_device *link) struct serial_info *info = link->priv; int i = -ENODEV, try; - /* First pass: look for a config entry that looks normal. - * Two tries: without IO aliases, then with aliases */ + /* + * First pass: look for a config entry that looks normal. + * Two tries: without IO aliases, then with aliases. + */ link->config_flags |= CONF_AUTO_SET_VPP; for (try = 0; try < 4; try++) if (!pcmcia_loop_config(link, simple_config_check, &try)) goto found_port; - /* Second pass: try to find an entry that isn't picky about - its base address, then try to grab any standard serial port - address, and finally try to get any free port. */ + /* + * Second pass: try to find an entry that isn't picky about + * its base address, then try to grab any standard serial port + * address, and finally try to get any free port. + */ if (!pcmcia_loop_config(link, simple_config_check_notpicky, NULL)) goto found_port; @@ -480,8 +484,10 @@ static int multi_config_check(struct pcmcia_device *p_dev, void *priv_data) if (p_dev->resource[1]->end) return -EINVAL; - /* The quad port cards have bad CIS's, so just look for a - window larger than 8 ports and assume it will be right */ + /* + * The quad port cards have bad CIS's, so just look for a + * window larger than 8 ports and assume it will be right. + */ if (p_dev->resource[0]->end <= 8) return -EINVAL; @@ -527,8 +533,8 @@ static int multi_config(struct pcmcia_device *link) info->multi = 2; if (pcmcia_loop_config(link, multi_config_check_notpicky, &base2)) { - dev_warn(&link->dev, "no usable port range " - "found, giving up\n"); + dev_warn(&link->dev, + "no usable port range found, giving up\n"); return -ENODEV; } } @@ -600,7 +606,7 @@ static int serial_check_for_multi(struct pcmcia_device *p_dev, void *priv_data) } -static int serial_config(struct pcmcia_device * link) +static int serial_config(struct pcmcia_device *link) { struct serial_info *info = link->priv; int i; @@ -623,8 +629,10 @@ static int serial_config(struct pcmcia_device * link) break; } - /* Another check for dual-serial cards: look for either serial or - multifunction cards that ask for appropriate IO port ranges */ + /* + * Another check for dual-serial cards: look for either serial or + * multifunction cards that ask for appropriate IO port ranges. + */ if ((info->multi == 0) && (link->has_func_id) && (link->socket->pcmcia_pfc == 0) && @@ -701,7 +709,7 @@ static const struct pcmcia_device_id serial_ids[] = { PCMCIA_PFC_DEVICE_PROD_ID12(1, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58), PCMCIA_PFC_DEVICE_PROD_ID12(1, "MEGAHERTZ", "XJEM1144/CCEM1144", 0xf510db04, 0x52d21e1e), PCMCIA_PFC_DEVICE_PROD_ID12(1, "MICRO RESEARCH", "COMBO-L/M-336", 0xb2ced065, 0x3ced0555), - PCMCIA_PFC_DEVICE_PROD_ID12(1, "NEC", "PK-UG-J001" ,0x18df0ba0 ,0x831b1064), + PCMCIA_PFC_DEVICE_PROD_ID12(1, "NEC", "PK-UG-J001", 0x18df0ba0, 0x831b1064), PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Diamonds Modem+Ethernet", 0xc2f80cd, 0x656947b9), PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Hearts Modem+Ethernet", 0xc2f80cd, 0xdc9ba5ed), PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc), @@ -797,30 +805,30 @@ static const struct pcmcia_device_id serial_ids[] = { PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "cis/COMpad2.cis"), PCMCIA_DEVICE_CIS_PROD_ID2("RS-COM 2P", 0xad20b156, "cis/RS-COM-2P.cis"), PCMCIA_DEVICE_CIS_MANF_CARD(0x0013, 0x0000, "cis/GLOBETROTTER.cis"), - PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL100 1.00.",0x19ca78af,0xf964f42b), - PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL100",0x19ca78af,0x71d98e83), - PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL232 1.00.",0x19ca78af,0x69fb7490), - PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL232",0x19ca78af,0xb6bc0235), - PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c2000.","SERIAL CARD: CF232",0x63f2e0bd,0xb9e175d3), - PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c2000.","SERIAL CARD: CF232-5",0x63f2e0bd,0xfce33442), - PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF232",0x3beb8cf2,0x171e7190), - PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF232-5",0x3beb8cf2,0x20da4262), - PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF428",0x3beb8cf2,0xea5dd57d), - PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF500",0x3beb8cf2,0xd77255fa), - PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: IC232",0x3beb8cf2,0x6a709903), - PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: SL232",0x3beb8cf2,0x18430676), - PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: XL232",0x3beb8cf2,0x6f933767), - PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: CF332",0x3beb8cf2,0x16dc1ba7), - PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL332",0x3beb8cf2,0x19816c41), - PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL385",0x3beb8cf2,0x64112029), - PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4), - PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial+Parallel Port: SP230",0x3beb8cf2,0xdb9e58bc), - PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: CF332",0x3beb8cf2,0x16dc1ba7), - PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL332",0x3beb8cf2,0x19816c41), - PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL385",0x3beb8cf2,0x64112029), - PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4), - PCMCIA_MFC_DEVICE_PROD_ID12(2,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4), - PCMCIA_MFC_DEVICE_PROD_ID12(3,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4), + PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.", "SERIAL CARD: SL100 1.00.", 0x19ca78af, 0xf964f42b), + PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.", "SERIAL CARD: SL100", 0x19ca78af, 0x71d98e83), + PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.", "SERIAL CARD: SL232 1.00.", 0x19ca78af, 0x69fb7490), + PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.", "SERIAL CARD: SL232", 0x19ca78af, 0xb6bc0235), + PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c2000.", "SERIAL CARD: CF232", 0x63f2e0bd, 0xb9e175d3), + PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c2000.", "SERIAL CARD: CF232-5", 0x63f2e0bd, 0xfce33442), + PCMCIA_DEVICE_PROD_ID12("Elan", "Serial Port: CF232", 0x3beb8cf2, 0x171e7190), + PCMCIA_DEVICE_PROD_ID12("Elan", "Serial Port: CF232-5", 0x3beb8cf2, 0x20da4262), + PCMCIA_DEVICE_PROD_ID12("Elan", "Serial Port: CF428", 0x3beb8cf2, 0xea5dd57d), + PCMCIA_DEVICE_PROD_ID12("Elan", "Serial Port: CF500", 0x3beb8cf2, 0xd77255fa), + PCMCIA_DEVICE_PROD_ID12("Elan", "Serial Port: IC232", 0x3beb8cf2, 0x6a709903), + PCMCIA_DEVICE_PROD_ID12("Elan", "Serial Port: SL232", 0x3beb8cf2, 0x18430676), + PCMCIA_DEVICE_PROD_ID12("Elan", "Serial Port: XL232", 0x3beb8cf2, 0x6f933767), + PCMCIA_MFC_DEVICE_PROD_ID12(0, "Elan", "Serial Port: CF332", 0x3beb8cf2, 0x16dc1ba7), + PCMCIA_MFC_DEVICE_PROD_ID12(0, "Elan", "Serial Port: SL332", 0x3beb8cf2, 0x19816c41), + PCMCIA_MFC_DEVICE_PROD_ID12(0, "Elan", "Serial Port: SL385", 0x3beb8cf2, 0x64112029), + PCMCIA_MFC_DEVICE_PROD_ID12(0, "Elan", "Serial Port: SL432", 0x3beb8cf2, 0x1cce7ac4), + PCMCIA_MFC_DEVICE_PROD_ID12(0, "Elan", "Serial+Parallel Port: SP230", 0x3beb8cf2, 0xdb9e58bc), + PCMCIA_MFC_DEVICE_PROD_ID12(1, "Elan", "Serial Port: CF332", 0x3beb8cf2, 0x16dc1ba7), + PCMCIA_MFC_DEVICE_PROD_ID12(1, "Elan", "Serial Port: SL332", 0x3beb8cf2, 0x19816c41), + PCMCIA_MFC_DEVICE_PROD_ID12(1, "Elan", "Serial Port: SL385", 0x3beb8cf2, 0x64112029), + PCMCIA_MFC_DEVICE_PROD_ID12(1, "Elan", "Serial Port: SL432", 0x3beb8cf2, 0x1cce7ac4), + PCMCIA_MFC_DEVICE_PROD_ID12(2, "Elan", "Serial Port: SL432", 0x3beb8cf2, 0x1cce7ac4), + PCMCIA_MFC_DEVICE_PROD_ID12(3, "Elan", "Serial Port: SL432", 0x3beb8cf2, 0x1cce7ac4), PCMCIA_DEVICE_MANF_CARD(0x0279, 0x950b), /* too generic */ /* PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0160, 0x0002), */ |