diff options
Diffstat (limited to 'drivers/tty/serial/8250')
-rw-r--r-- | drivers/tty/serial/8250/8250.h | 8 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_ce4100.c | 93 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_core.c | 318 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_dw.c | 36 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_em.c | 4 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_ingenic.c | 8 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_ioc3.c | 4 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_lpc18xx.c | 2 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_ni.c | 56 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_omap.c | 53 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_pci.c | 6 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_port.c | 774 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_rsa.c | 96 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_rt288x.c | 4 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_uniphier.c | 4 | ||||
-rw-r--r-- | drivers/tty/serial/8250/Makefile | 3 |
16 files changed, 810 insertions, 659 deletions
diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index 18530c31a598..cfe6ba286b45 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -318,8 +318,16 @@ static inline void serial8250_pnp_exit(void) { } #ifdef CONFIG_SERIAL_8250_RSA void univ8250_rsa_support(struct uart_ops *ops); +void rsa_enable(struct uart_8250_port *up); +void rsa_disable(struct uart_8250_port *up); +void rsa_autoconfig(struct uart_8250_port *up); +void rsa_reset(struct uart_8250_port *up); #else static inline void univ8250_rsa_support(struct uart_ops *ops) { } +static inline void rsa_enable(struct uart_8250_port *up) {} +static inline void rsa_disable(struct uart_8250_port *up) {} +static inline void rsa_autoconfig(struct uart_8250_port *up) {} +static inline void rsa_reset(struct uart_8250_port *up) {} #endif #ifdef CONFIG_SERIAL_8250_FINTEK diff --git a/drivers/tty/serial/8250/8250_ce4100.c b/drivers/tty/serial/8250/8250_ce4100.c new file mode 100644 index 000000000000..81dfb2adbabd --- /dev/null +++ b/drivers/tty/serial/8250/8250_ce4100.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Intel CE4100 platform specific setup code + * + * (C) Copyright 2010 Intel Corporation + */ + +#include <linux/init.h> +#include <linux/io.h> +#include <linux/types.h> + +#include <asm/ce4100.h> +#include <asm/fixmap.h> +#include <asm/page.h> + +#include <linux/serial_reg.h> +#include <linux/serial_8250.h> + +static unsigned int mem_serial_in(struct uart_port *p, int offset) +{ + offset = offset << p->regshift; + return readl(p->membase + offset); +} + +/* + * The UART Tx interrupts are not set under some conditions and therefore serial + * transmission hangs. This is a silicon issue and has not been root caused. The + * workaround for this silicon issue checks UART_LSR_THRE bit and UART_LSR_TEMT + * bit of LSR register in interrupt handler to see whether at least one of these + * two bits is set, if so then process the transmit request. If this workaround + * is not applied, then the serial transmission may hang. This workaround is for + * errata number 9 in Errata - B step. +*/ +static u32 ce4100_mem_serial_in(struct uart_port *p, unsigned int offset) +{ + u32 ret, ier, lsr; + + ret = mem_serial_in(p, offset); + if (offset != UART_IIR || !(ret & UART_IIR_NO_INT)) + return ret; + + /* see if the TX interrupt should have really set */ + ier = mem_serial_in(p, UART_IER); + /* see if the UART's XMIT interrupt is enabled */ + if (!(ier & UART_IER_THRI)) + return ret; + + lsr = mem_serial_in(p, UART_LSR); + /* now check to see if the UART should be generating an interrupt (but isn't) */ + if (lsr & (UART_LSR_THRE | UART_LSR_TEMT)) + ret &= ~UART_IIR_NO_INT; + + return ret; +} + +static void ce4100_mem_serial_out(struct uart_port *p, unsigned int offset, u32 value) +{ + offset <<= p->regshift; + writel(value, p->membase + offset); +} + +static void ce4100_serial_fixup(int port, struct uart_port *up, u32 *capabilities) +{ +#ifdef CONFIG_EARLY_PRINTK + /* + * Override the legacy port configuration that comes from + * asm/serial.h. Using the ioport driver then switching to the + * PCI memmaped driver hangs the IOAPIC. + */ + if (up->iotype != UPIO_MEM32) { + up->uartclk = 14745600; + up->mapbase = 0xdffe0200; + set_fixmap_nocache(FIX_EARLYCON_MEM_BASE, up->mapbase & PAGE_MASK); + up->membase = (void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE); + up->membase += up->mapbase & ~PAGE_MASK; + up->mapbase += port * 0x100; + up->membase += port * 0x100; + up->iotype = UPIO_MEM32; + up->regshift = 2; + up->irq = 4; + } +#endif + up->iobase = 0; + up->serial_in = ce4100_mem_serial_in; + up->serial_out = ce4100_mem_serial_out; + + *capabilities |= (1 << 12); +} + +void __init sdv_serial_fixup(void) +{ + serial8250_set_isa_configurator(ce4100_serial_fixup); +} diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 7a6050f1c094..feb920c5b2e8 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -13,6 +13,7 @@ */ #include <linux/acpi.h> +#include <linux/hashtable.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/ioport.h> @@ -47,8 +48,8 @@ struct irq_info { struct list_head *head; }; -#define NR_IRQ_HASH 32 /* Can be adjusted later */ -static struct hlist_head irq_lists[NR_IRQ_HASH]; +#define IRQ_HASH_BITS 5 /* Can be adjusted later */ +static DEFINE_HASHTABLE(irq_lists, IRQ_HASH_BITS); static DEFINE_MUTEX(hash_mutex); /* Used to walk the hash */ /* @@ -71,17 +72,12 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id) struct list_head *l, *end = NULL; int pass_counter = 0, handled = 0; - pr_debug("%s(%d): start\n", __func__, irq); - spin_lock(&i->lock); l = i->head; do { - struct uart_8250_port *up; - struct uart_port *port; - - up = list_entry(l, struct uart_8250_port, list); - port = &up->port; + struct uart_8250_port *up = list_entry(l, struct uart_8250_port, list); + struct uart_port *port = &up->port; if (port->handle_irq(port)) { handled = 1; @@ -97,8 +93,6 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id) spin_unlock(&i->lock); - pr_debug("%s(%d): end\n", __func__, irq); - return IRQ_RETVAL(handled); } @@ -129,32 +123,44 @@ static void serial_do_unlink(struct irq_info *i, struct uart_8250_port *up) } } -static int serial_link_irq_chain(struct uart_8250_port *up) +/* + * Either: + * - find the corresponding info in the hashtable and return it, or + * - allocate a new one, add it to the hashtable and return it. + */ +static struct irq_info *serial_get_or_create_irq_info(const struct uart_8250_port *up) { - struct hlist_head *h; struct irq_info *i; - int ret; mutex_lock(&hash_mutex); - h = &irq_lists[up->port.irq % NR_IRQ_HASH]; - - hlist_for_each_entry(i, h, node) + hash_for_each_possible(irq_lists, i, node, up->port.irq) if (i->irq == up->port.irq) - break; + goto unlock; + i = kzalloc(sizeof(*i), GFP_KERNEL); if (i == NULL) { - i = kzalloc(sizeof(struct irq_info), GFP_KERNEL); - if (i == NULL) { - mutex_unlock(&hash_mutex); - return -ENOMEM; - } - spin_lock_init(&i->lock); - i->irq = up->port.irq; - hlist_add_head(&i->node, h); + i = ERR_PTR(-ENOMEM); + goto unlock; } + spin_lock_init(&i->lock); + i->irq = up->port.irq; + hash_add(irq_lists, &i->node, i->irq); +unlock: mutex_unlock(&hash_mutex); + return i; +} + +static int serial_link_irq_chain(struct uart_8250_port *up) +{ + struct irq_info *i; + int ret; + + i = serial_get_or_create_irq_info(up); + if (IS_ERR(i)) + return PTR_ERR(i); + spin_lock_irq(&i->lock); if (i->head) { @@ -178,13 +184,10 @@ static int serial_link_irq_chain(struct uart_8250_port *up) static void serial_unlink_irq_chain(struct uart_8250_port *up) { struct irq_info *i; - struct hlist_head *h; mutex_lock(&hash_mutex); - h = &irq_lists[up->port.irq % NR_IRQ_HASH]; - - hlist_for_each_entry(i, h, node) + hash_for_each_possible(irq_lists, i, node, up->port.irq) if (i->irq == up->port.irq) break; @@ -714,139 +717,142 @@ int serial8250_register_8250_port(const struct uart_8250_port *up) nr_uarts++; } - if (uart->port.type != PORT_8250_CIR) { - struct mctrl_gpios *gpios; - - if (uart->port.dev) - uart_remove_one_port(&serial8250_reg, &uart->port); - - uart->port.ctrl_id = up->port.ctrl_id; - uart->port.port_id = up->port.port_id; - uart->port.iobase = up->port.iobase; - uart->port.membase = up->port.membase; - uart->port.irq = up->port.irq; - uart->port.irqflags = up->port.irqflags; - uart->port.uartclk = up->port.uartclk; - uart->port.fifosize = up->port.fifosize; - uart->port.regshift = up->port.regshift; - uart->port.iotype = up->port.iotype; - uart->port.flags = up->port.flags | UPF_BOOT_AUTOCONF; - uart->bugs = up->bugs; - uart->port.mapbase = up->port.mapbase; - uart->port.mapsize = up->port.mapsize; - uart->port.private_data = up->port.private_data; - uart->tx_loadsz = up->tx_loadsz; - uart->capabilities = up->capabilities; - uart->port.throttle = up->port.throttle; - uart->port.unthrottle = up->port.unthrottle; - uart->port.rs485_config = up->port.rs485_config; - uart->port.rs485_supported = up->port.rs485_supported; - uart->port.rs485 = up->port.rs485; - uart->rs485_start_tx = up->rs485_start_tx; - uart->rs485_stop_tx = up->rs485_stop_tx; - uart->lsr_save_mask = up->lsr_save_mask; - uart->dma = up->dma; - - /* Take tx_loadsz from fifosize if it wasn't set separately */ - if (uart->port.fifosize && !uart->tx_loadsz) - uart->tx_loadsz = uart->port.fifosize; - - if (up->port.dev) { - uart->port.dev = up->port.dev; - ret = uart_get_rs485_mode(&uart->port); - if (ret) - goto err; - } + /* Check if it is CIR already. We check this below again, see there why. */ + if (uart->port.type == PORT_8250_CIR) { + ret = -ENODEV; + goto unlock; + } - if (up->port.flags & UPF_FIXED_TYPE) - uart->port.type = up->port.type; + if (uart->port.dev) + uart_remove_one_port(&serial8250_reg, &uart->port); + + uart->port.ctrl_id = up->port.ctrl_id; + uart->port.port_id = up->port.port_id; + uart->port.iobase = up->port.iobase; + uart->port.membase = up->port.membase; + uart->port.irq = up->port.irq; + uart->port.irqflags = up->port.irqflags; + uart->port.uartclk = up->port.uartclk; + uart->port.fifosize = up->port.fifosize; + uart->port.regshift = up->port.regshift; + uart->port.iotype = up->port.iotype; + uart->port.flags = up->port.flags | UPF_BOOT_AUTOCONF; + uart->bugs = up->bugs; + uart->port.mapbase = up->port.mapbase; + uart->port.mapsize = up->port.mapsize; + uart->port.private_data = up->port.private_data; + uart->tx_loadsz = up->tx_loadsz; + uart->capabilities = up->capabilities; + uart->port.throttle = up->port.throttle; + uart->port.unthrottle = up->port.unthrottle; + uart->port.rs485_config = up->port.rs485_config; + uart->port.rs485_supported = up->port.rs485_supported; + uart->port.rs485 = up->port.rs485; + uart->rs485_start_tx = up->rs485_start_tx; + uart->rs485_stop_tx = up->rs485_stop_tx; + uart->lsr_save_mask = up->lsr_save_mask; + uart->dma = up->dma; + + /* Take tx_loadsz from fifosize if it wasn't set separately */ + if (uart->port.fifosize && !uart->tx_loadsz) + uart->tx_loadsz = uart->port.fifosize; + + if (up->port.dev) { + uart->port.dev = up->port.dev; + ret = uart_get_rs485_mode(&uart->port); + if (ret) + goto err; + } - /* - * Only call mctrl_gpio_init(), if the device has no ACPI - * companion device - */ - if (!has_acpi_companion(uart->port.dev)) { - gpios = mctrl_gpio_init(&uart->port, 0); - if (IS_ERR(gpios)) { - ret = PTR_ERR(gpios); - goto err; - } else { - uart->gpios = gpios; - } - } + if (up->port.flags & UPF_FIXED_TYPE) + uart->port.type = up->port.type; - serial8250_set_defaults(uart); - - /* Possibly override default I/O functions. */ - if (up->port.serial_in) - uart->port.serial_in = up->port.serial_in; - if (up->port.serial_out) - uart->port.serial_out = up->port.serial_out; - if (up->port.handle_irq) - uart->port.handle_irq = up->port.handle_irq; - /* Possibly override set_termios call */ - if (up->port.set_termios) - uart->port.set_termios = up->port.set_termios; - if (up->port.set_ldisc) - uart->port.set_ldisc = up->port.set_ldisc; - 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.get_divisor) - uart->port.get_divisor = up->port.get_divisor; - if (up->port.set_divisor) - uart->port.set_divisor = up->port.set_divisor; - if (up->port.startup) - uart->port.startup = up->port.startup; - if (up->port.shutdown) - uart->port.shutdown = up->port.shutdown; - if (up->port.pm) - uart->port.pm = up->port.pm; - if (up->port.handle_break) - uart->port.handle_break = up->port.handle_break; - if (up->dl_read) - uart->dl_read = up->dl_read; - if (up->dl_write) - uart->dl_write = up->dl_write; - - if (uart->port.type != PORT_8250_CIR) { - if (uart_console_registered(&uart->port)) - pm_runtime_get_sync(uart->port.dev); - - if (serial8250_isa_config != NULL) - serial8250_isa_config(0, &uart->port, - &uart->capabilities); - - serial8250_apply_quirks(uart); - ret = uart_add_one_port(&serial8250_reg, - &uart->port); - if (ret) - goto err; - - ret = uart->port.line; + /* + * Only call mctrl_gpio_init(), if the device has no ACPI + * companion device + */ + if (!has_acpi_companion(uart->port.dev)) { + struct mctrl_gpios *gpios = mctrl_gpio_init(&uart->port, 0); + if (IS_ERR(gpios)) { + ret = PTR_ERR(gpios); + goto err; } 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 = 0; + uart->gpios = gpios; } + } - if (!uart->lsr_save_mask) - uart->lsr_save_mask = LSR_SAVE_FLAGS; /* Use default LSR mask */ + serial8250_set_defaults(uart); + + /* Possibly override default I/O functions. */ + if (up->port.serial_in) + uart->port.serial_in = up->port.serial_in; + if (up->port.serial_out) + uart->port.serial_out = up->port.serial_out; + if (up->port.handle_irq) + uart->port.handle_irq = up->port.handle_irq; + /* Possibly override set_termios call */ + if (up->port.set_termios) + uart->port.set_termios = up->port.set_termios; + if (up->port.set_ldisc) + uart->port.set_ldisc = up->port.set_ldisc; + 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.get_divisor) + uart->port.get_divisor = up->port.get_divisor; + if (up->port.set_divisor) + uart->port.set_divisor = up->port.set_divisor; + if (up->port.startup) + uart->port.startup = up->port.startup; + if (up->port.shutdown) + uart->port.shutdown = up->port.shutdown; + if (up->port.pm) + uart->port.pm = up->port.pm; + if (up->port.handle_break) + uart->port.handle_break = up->port.handle_break; + if (up->dl_read) + uart->dl_read = up->dl_read; + if (up->dl_write) + uart->dl_write = up->dl_write; + + /* Check the type (again)! It might have changed by the port.type assignment above. */ + if (uart->port.type != PORT_8250_CIR) { + if (uart_console_registered(&uart->port)) + pm_runtime_get_sync(uart->port.dev); - /* Initialise interrupt backoff work if required */ - if (up->overrun_backoff_time_ms > 0) { - uart->overrun_backoff_time_ms = - up->overrun_backoff_time_ms; - INIT_DELAYED_WORK(&uart->overrun_backoff, - serial_8250_overrun_backoff_work); - } else { - uart->overrun_backoff_time_ms = 0; - } + if (serial8250_isa_config != NULL) + serial8250_isa_config(0, &uart->port, + &uart->capabilities); + + serial8250_apply_quirks(uart); + ret = uart_add_one_port(&serial8250_reg, + &uart->port); + if (ret) + goto err; + + 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 = 0; + } + + if (!uart->lsr_save_mask) + uart->lsr_save_mask = LSR_SAVE_FLAGS; /* Use default LSR mask */ + + /* Initialise interrupt backoff work if required */ + if (up->overrun_backoff_time_ms > 0) { + uart->overrun_backoff_time_ms = + up->overrun_backoff_time_ms; + INIT_DELAYED_WORK(&uart->overrun_backoff, + serial_8250_overrun_backoff_work); + } else { + uart->overrun_backoff_time_ms = 0; } unlock: diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 1902f29444a1..a53ba04d9770 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -67,8 +67,8 @@ struct dw8250_data { struct dw8250_port_data data; const struct dw8250_platform_data *pdata; - int msr_mask_on; - int msr_mask_off; + u32 msr_mask_on; + u32 msr_mask_off; struct clk *clk; struct clk *pclk; struct notifier_block clk_notifier; @@ -94,7 +94,7 @@ static inline struct dw8250_data *work_to_dw8250_data(struct work_struct *work) return container_of(work, struct dw8250_data, clk_work); } -static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value) +static inline u32 dw8250_modify_msr(struct uart_port *p, unsigned int offset, u32 value) { struct dw8250_data *d = to_dw8250_data(p->private_data); @@ -145,7 +145,7 @@ static void dw8250_force_idle(struct uart_port *p) * routine. Hence, it must not call serial_port_out() or serial_out() * against the modified registers here, i.e. LCR. */ -static void dw8250_check_lcr(struct uart_port *p, int offset, int value) +static void dw8250_check_lcr(struct uart_port *p, unsigned int offset, u32 value) { struct dw8250_data *d = to_dw8250_data(p->private_data); void __iomem *addr = p->membase + (offset << p->regshift); @@ -156,7 +156,7 @@ static void dw8250_check_lcr(struct uart_port *p, int offset, int value) /* Make sure LCR write wasn't ignored */ while (tries--) { - unsigned int lcr = serial_port_in(p, offset); + u32 lcr = serial_port_in(p, offset); if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR)) return; @@ -205,13 +205,13 @@ static void dw8250_tx_wait_empty(struct uart_port *p) } } -static void dw8250_serial_out(struct uart_port *p, int offset, int value) +static void dw8250_serial_out(struct uart_port *p, unsigned int offset, u32 value) { writeb(value, p->membase + (offset << p->regshift)); dw8250_check_lcr(p, offset, value); } -static void dw8250_serial_out38x(struct uart_port *p, int offset, int value) +static void dw8250_serial_out38x(struct uart_port *p, unsigned int offset, u32 value) { /* Allow the TX to drain before we reconfigure */ if (offset == UART_LCR) @@ -220,22 +220,22 @@ static void dw8250_serial_out38x(struct uart_port *p, int offset, int value) dw8250_serial_out(p, offset, value); } -static unsigned int dw8250_serial_in(struct uart_port *p, int offset) +static u32 dw8250_serial_in(struct uart_port *p, unsigned int offset) { - unsigned int value = readb(p->membase + (offset << p->regshift)); + u32 value = readb(p->membase + (offset << p->regshift)); return dw8250_modify_msr(p, offset, value); } #ifdef CONFIG_64BIT -static unsigned int dw8250_serial_inq(struct uart_port *p, int offset) +static u32 dw8250_serial_inq(struct uart_port *p, unsigned int offset) { u8 value = __raw_readq(p->membase + (offset << p->regshift)); return dw8250_modify_msr(p, offset, value); } -static void dw8250_serial_outq(struct uart_port *p, int offset, int value) +static void dw8250_serial_outq(struct uart_port *p, unsigned int offset, u32 value) { value &= 0xff; __raw_writeq(value, p->membase + (offset << p->regshift)); @@ -246,28 +246,28 @@ static void dw8250_serial_outq(struct uart_port *p, int offset, int value) } #endif /* CONFIG_64BIT */ -static void dw8250_serial_out32(struct uart_port *p, int offset, int value) +static void dw8250_serial_out32(struct uart_port *p, unsigned int offset, u32 value) { writel(value, p->membase + (offset << p->regshift)); dw8250_check_lcr(p, offset, value); } -static unsigned int dw8250_serial_in32(struct uart_port *p, int offset) +static u32 dw8250_serial_in32(struct uart_port *p, unsigned int offset) { - unsigned int value = readl(p->membase + (offset << p->regshift)); + u32 value = readl(p->membase + (offset << p->regshift)); return dw8250_modify_msr(p, offset, value); } -static void dw8250_serial_out32be(struct uart_port *p, int offset, int value) +static void dw8250_serial_out32be(struct uart_port *p, unsigned int offset, u32 value) { iowrite32be(value, p->membase + (offset << p->regshift)); dw8250_check_lcr(p, offset, value); } -static unsigned int dw8250_serial_in32be(struct uart_port *p, int offset) +static u32 dw8250_serial_in32be(struct uart_port *p, unsigned int offset) { - unsigned int value = ioread32be(p->membase + (offset << p->regshift)); + u32 value = ioread32be(p->membase + (offset << p->regshift)); return dw8250_modify_msr(p, offset, value); } @@ -392,7 +392,7 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios, rate = clk_round_rate(d->clk, newrate); if (rate > 0) { /* - * Note that any clock-notifer worker will block in + * Note that any clock-notifier worker will block in * serial8250_update_uartclk() until we are done. */ ret = clk_set_rate(d->clk, newrate); diff --git a/drivers/tty/serial/8250/8250_em.c b/drivers/tty/serial/8250/8250_em.c index 35094f884492..e90c71494944 100644 --- a/drivers/tty/serial/8250/8250_em.c +++ b/drivers/tty/serial/8250/8250_em.c @@ -59,7 +59,7 @@ static void serial8250_em_serial_out_helper(struct uart_port *p, int offset, } } -static unsigned int serial8250_em_serial_in(struct uart_port *p, int offset) +static u32 serial8250_em_serial_in(struct uart_port *p, unsigned int offset) { switch (offset) { case UART_RX: /* RX @ 0x00 */ @@ -119,7 +119,7 @@ static void serial8250_em_reg_update(struct uart_port *p, int off, int value) serial8250_em_serial_out_helper(p, UART_HCR0_EM, hcr0); } -static void serial8250_em_serial_out(struct uart_port *p, int offset, int value) +static void serial8250_em_serial_out(struct uart_port *p, unsigned int offset, u32 value) { switch (offset) { case UART_TX: diff --git a/drivers/tty/serial/8250/8250_ingenic.c b/drivers/tty/serial/8250/8250_ingenic.c index a73dd3773640..94542fc143c2 100644 --- a/drivers/tty/serial/8250/8250_ingenic.c +++ b/drivers/tty/serial/8250/8250_ingenic.c @@ -168,9 +168,9 @@ OF_EARLYCON_DECLARE(jz4780_uart, "ingenic,jz4780-uart", OF_EARLYCON_DECLARE(x1000_uart, "ingenic,x1000-uart", ingenic_early_console_setup); -static void ingenic_uart_serial_out(struct uart_port *p, int offset, int value) +static void ingenic_uart_serial_out(struct uart_port *p, unsigned int offset, u32 value) { - int ier; + u32 ier; switch (offset) { case UART_FCR: @@ -206,9 +206,9 @@ static void ingenic_uart_serial_out(struct uart_port *p, int offset, int value) writeb(value, p->membase + (offset << p->regshift)); } -static unsigned int ingenic_uart_serial_in(struct uart_port *p, int offset) +static u32 ingenic_uart_serial_in(struct uart_port *p, unsigned int offset) { - unsigned int value; + u8 value; value = readb(p->membase + (offset << p->regshift)); diff --git a/drivers/tty/serial/8250/8250_ioc3.c b/drivers/tty/serial/8250/8250_ioc3.c index 499e80aa4cf9..3ebda9a5d07d 100644 --- a/drivers/tty/serial/8250/8250_ioc3.c +++ b/drivers/tty/serial/8250/8250_ioc3.c @@ -21,12 +21,12 @@ struct ioc3_8250_data { int line; }; -static unsigned int ioc3_serial_in(struct uart_port *p, int offset) +static u32 ioc3_serial_in(struct uart_port *p, unsigned int offset) { return readb(p->membase + (offset ^ 3)); } -static void ioc3_serial_out(struct uart_port *p, int offset, int value) +static void ioc3_serial_out(struct uart_port *p, unsigned int offset, u32 value) { writeb(value, p->membase + (offset ^ 3)); } diff --git a/drivers/tty/serial/8250/8250_lpc18xx.c b/drivers/tty/serial/8250/8250_lpc18xx.c index d52445948da0..6c0489c9c253 100644 --- a/drivers/tty/serial/8250/8250_lpc18xx.c +++ b/drivers/tty/serial/8250/8250_lpc18xx.c @@ -67,7 +67,7 @@ static int lpc18xx_rs485_config(struct uart_port *port, struct ktermios *termios return 0; } -static void lpc18xx_uart_serial_out(struct uart_port *p, int offset, int value) +static void lpc18xx_uart_serial_out(struct uart_port *p, unsigned int offset, u32 value) { /* * For DMA mode one must ensure that the UART_FCR_DMA_SELECT diff --git a/drivers/tty/serial/8250/8250_ni.c b/drivers/tty/serial/8250/8250_ni.c index b0e44fb00b3a..cb5b42b3609c 100644 --- a/drivers/tty/serial/8250/8250_ni.c +++ b/drivers/tty/serial/8250/8250_ni.c @@ -275,76 +275,80 @@ static void ni16550_set_mctrl(struct uart_port *port, unsigned int mctrl) static int ni16550_probe(struct platform_device *pdev) { + struct uart_8250_port *uart __free(kfree) = NULL; const struct ni16550_device_info *info; struct device *dev = &pdev->dev; - struct uart_8250_port uart = {}; unsigned int txfifosz, rxfifosz; - unsigned int prescaler; struct ni16550_data *data; + unsigned int prescaler; const char *portmode; bool rs232_property; int ret; + uart = kzalloc(sizeof(*uart), GFP_KERNEL); + if (!uart) + return -ENOMEM; + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; - spin_lock_init(&uart.port.lock); + spin_lock_init(&uart->port.lock); - ret = ni16550_get_regs(pdev, &uart.port); + ret = ni16550_get_regs(pdev, &uart->port); if (ret < 0) return ret; /* early setup so that serial_in()/serial_out() work */ - serial8250_set_defaults(&uart); + serial8250_set_defaults(uart); info = device_get_match_data(dev); - uart.port.dev = dev; - uart.port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_FIXED_TYPE; - uart.port.startup = ni16550_port_startup; - uart.port.shutdown = ni16550_port_shutdown; + uart->port.dev = dev; + uart->port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_FIXED_TYPE; + uart->port.startup = ni16550_port_startup; + uart->port.shutdown = ni16550_port_shutdown; /* * Hardware instantiation of FIFO sizes are held in registers. */ - txfifosz = ni16550_read_fifo_size(&uart, NI16550_TFS_OFFSET); - rxfifosz = ni16550_read_fifo_size(&uart, NI16550_RFS_OFFSET); + txfifosz = ni16550_read_fifo_size(uart, NI16550_TFS_OFFSET); + rxfifosz = ni16550_read_fifo_size(uart, NI16550_RFS_OFFSET); dev_dbg(dev, "NI 16550 has TX FIFO size %u, RX FIFO size %u\n", txfifosz, rxfifosz); - uart.port.type = PORT_16550A; - uart.port.fifosize = txfifosz; - uart.tx_loadsz = txfifosz; - uart.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10; - uart.capabilities = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR; + uart->port.type = PORT_16550A; + uart->port.fifosize = txfifosz; + uart->tx_loadsz = txfifosz; + uart->fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10; + uart->capabilities = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR; /* * Declaration of the base clock frequency can come from one of: * - static declaration in this driver (for older ACPI IDs) * - a "clock-frequency" ACPI */ - uart.port.uartclk = info->uartclk; + uart->port.uartclk = info->uartclk; - ret = uart_read_port_properties(&uart.port); + ret = uart_read_port_properties(&uart->port); if (ret) return ret; - if (!uart.port.uartclk) { + if (!uart->port.uartclk) { data->clk = devm_clk_get_enabled(dev, NULL); if (!IS_ERR(data->clk)) - uart.port.uartclk = clk_get_rate(data->clk); + uart->port.uartclk = clk_get_rate(data->clk); } - if (!uart.port.uartclk) + if (!uart->port.uartclk) return dev_err_probe(dev, -ENODEV, "unable to determine clock frequency!\n"); prescaler = info->prescaler; device_property_read_u32(dev, "clock-prescaler", &prescaler); if (prescaler) { - uart.port.set_mctrl = ni16550_set_mctrl; - ni16550_config_prescaler(&uart, (u8)prescaler); + uart->port.set_mctrl = ni16550_set_mctrl; + ni16550_config_prescaler(uart, (u8)prescaler); } /* @@ -362,7 +366,7 @@ static int ni16550_probe(struct platform_device *pdev) dev_dbg(dev, "port is in %s mode (via device property)\n", rs232_property ? "RS-232" : "RS-485"); } else if (info->flags & NI_HAS_PMR) { - rs232_property = is_pmr_rs232_mode(&uart); + rs232_property = is_pmr_rs232_mode(uart); dev_dbg(dev, "port is in %s mode (via PMR)\n", rs232_property ? "RS-232" : "RS-485"); @@ -377,10 +381,10 @@ static int ni16550_probe(struct platform_device *pdev) * Neither the 'transceiver' property nor the PMR indicate * that this is an RS-232 port, so it must be an RS-485 one. */ - ni16550_rs485_setup(&uart.port); + ni16550_rs485_setup(&uart->port); } - ret = serial8250_register_8250_port(&uart); + ret = serial8250_register_8250_port(uart); if (ret < 0) return ret; data->line = ret; diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index 72ae08d6204f..6707f55bdbe7 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -176,7 +176,7 @@ static u32 uart_read(struct omap8250_priv *priv, u32 reg) static void __omap8250_set_mctrl(struct uart_port *port, unsigned int mctrl) { struct uart_8250_port *up = up_to_u8250p(port); - struct omap8250_priv *priv = up->port.private_data; + struct omap8250_priv *priv = port->private_data; u8 lcr; serial8250_do_set_mctrl(port, mctrl); @@ -303,12 +303,13 @@ static void omap8250_update_mdr1(struct uart_8250_port *up, static void omap8250_restore_regs(struct uart_8250_port *up) { - struct omap8250_priv *priv = up->port.private_data; + struct uart_port *port = &up->port; + struct omap8250_priv *priv = port->private_data; struct uart_8250_dma *dma = up->dma; u8 mcr = serial8250_in_MCR(up); /* Port locked to synchronize UART_IER access against the console. */ - lockdep_assert_held_once(&up->port.lock); + lockdep_assert_held_once(&port->lock); if (dma && dma->tx_running) { /* @@ -359,12 +360,12 @@ static void omap8250_restore_regs(struct uart_8250_port *up) omap8250_update_mdr1(up, priv); - __omap8250_set_mctrl(&up->port, up->port.mctrl); + __omap8250_set_mctrl(port, port->mctrl); serial_out(up, UART_OMAP_MDR3, priv->mdr3); - if (up->port.rs485.flags & SER_RS485_ENABLED && - up->port.rs485_config == serial8250_em485_config) + if (port->rs485.flags & SER_RS485_ENABLED && + port->rs485_config == serial8250_em485_config) serial8250_em485_stop_tx(up, true); } @@ -377,7 +378,7 @@ static void omap_8250_set_termios(struct uart_port *port, const struct ktermios *old) { struct uart_8250_port *up = up_to_u8250p(port); - struct omap8250_priv *priv = up->port.private_data; + struct omap8250_priv *priv = port->private_data; unsigned char cval = 0; unsigned int baud; @@ -418,39 +419,39 @@ static void omap_8250_set_termios(struct uart_port *port, * ignoring of characters only occurs if the bit is set * in @ignore_status_mask as well. */ - up->port.read_status_mask = UART_LSR_OE | UART_LSR_DR; + port->read_status_mask = UART_LSR_OE | UART_LSR_DR; if (termios->c_iflag & INPCK) - up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE; + port->read_status_mask |= UART_LSR_FE | UART_LSR_PE; if (termios->c_iflag & (IGNBRK | PARMRK)) - up->port.read_status_mask |= UART_LSR_BI; + port->read_status_mask |= UART_LSR_BI; /* * Characters to ignore */ - up->port.ignore_status_mask = 0; + port->ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) - up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; + port->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; if (termios->c_iflag & IGNBRK) { - up->port.ignore_status_mask |= UART_LSR_BI; + 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) - up->port.ignore_status_mask |= UART_LSR_OE; + port->ignore_status_mask |= UART_LSR_OE; } /* * ignore all characters if CREAD is not set */ if ((termios->c_cflag & CREAD) == 0) - up->port.ignore_status_mask |= UART_LSR_DR; + port->ignore_status_mask |= UART_LSR_DR; /* * Modem status interrupts */ up->ier &= ~UART_IER_MSI; - if (UART_ENABLE_MS(&up->port, termios->c_cflag)) + if (UART_ENABLE_MS(port, termios->c_cflag)) up->ier |= UART_IER_MSI; up->lcr = cval; @@ -488,15 +489,15 @@ static void omap_8250_set_termios(struct uart_port *port, priv->xoff = termios->c_cc[VSTOP]; priv->efr = 0; - up->port.status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS | UPSTAT_AUTOXOFF); + port->status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS | UPSTAT_AUTOXOFF); - if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW && + if (termios->c_cflag & CRTSCTS && port->flags & UPF_HARD_FLOW && !mctrl_gpio_to_gpiod(up->gpios, UART_GPIO_RTS) && !mctrl_gpio_to_gpiod(up->gpios, UART_GPIO_CTS)) { /* Enable AUTOCTS (autoRTS is enabled when RTS is raised) */ - up->port.status |= UPSTAT_AUTOCTS | UPSTAT_AUTORTS; + port->status |= UPSTAT_AUTOCTS | UPSTAT_AUTORTS; priv->efr |= UART_EFR_CTS; - } else if (up->port.flags & UPF_SOFT_FLOW) { + } else if (port->flags & UPF_SOFT_FLOW) { /* * OMAP rx s/w flow control is borked; the transmitter remains * stuck off even if rx flow control is subsequently disabled @@ -508,7 +509,7 @@ static void omap_8250_set_termios(struct uart_port *port, * Transmit XON1, XOFF1 */ if (termios->c_iflag & IXOFF) { - up->port.status |= UPSTAT_AUTOXOFF; + port->status |= UPSTAT_AUTOXOFF; priv->efr |= OMAP_UART_SW_TX; } } @@ -770,7 +771,7 @@ static int omap_8250_startup(struct uart_port *port) uart_port_unlock_irq(port); } - enable_irq(up->port.irq); + enable_irq(port->irq); pm_runtime_mark_last_busy(port->dev); pm_runtime_put_autosuspend(port->dev); @@ -797,7 +798,7 @@ static void omap_8250_shutdown(struct uart_port *port) up->ier = 0; serial_out(up, UART_IER, 0); uart_port_unlock_irq(port); - disable_irq_nosync(up->port.irq); + disable_irq_nosync(port->irq); dev_pm_clear_wake_irq(port->dev); serial8250_release_dma(up); @@ -1310,7 +1311,7 @@ static void am654_8250_handle_rx_dma(struct uart_8250_port *up, u8 iir, static int omap_8250_dma_handle_irq(struct uart_port *port) { struct uart_8250_port *up = up_to_u8250p(port); - struct omap8250_priv *priv = up->port.private_data; + struct omap8250_priv *priv = port->private_data; u16 status; u8 iir; @@ -1332,8 +1333,8 @@ static int omap_8250_dma_handle_irq(struct uart_port *port) serial8250_modem_status(up); if (status & UART_LSR_THRE && up->dma->tx_err) { - if (uart_tx_stopped(&up->port) || - kfifo_is_empty(&up->port.state->port.xmit_fifo)) { + if (uart_tx_stopped(port) || + kfifo_is_empty(&port->state->port.xmit_fifo)) { up->dma->tx_err = 0; serial8250_tx_chars(up); } else { diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 73c200127b08..152f914c599d 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1751,7 +1751,7 @@ static int pci_fintek_init(struct pci_dev *dev) return max_port; } -static void f815xxa_mem_serial_out(struct uart_port *p, int offset, int value) +static void f815xxa_mem_serial_out(struct uart_port *p, unsigned int offset, u32 value) { struct f815xxa_data *data = p->private_data; unsigned long flags; @@ -1846,10 +1846,10 @@ static void kt_handle_break(struct uart_port *p) serial8250_clear_and_reinit_fifos(up); } -static unsigned int kt_serial_in(struct uart_port *p, int offset) +static u32 kt_serial_in(struct uart_port *p, unsigned int offset) { struct uart_8250_port *up = up_to_u8250p(p); - unsigned int val; + u32 val; /* * When the Intel ME (management engine) gets reset its serial diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 6d7b8c4667c9..2da9db960d09 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -39,15 +39,6 @@ #include "8250.h" /* - * Debugging. - */ -#if 0 -#define DEBUG_AUTOCONF(fmt...) printk(fmt) -#else -#define DEBUG_AUTOCONF(fmt...) do { } while (0) -#endif - -/* * Here we define the default xmit fifo size used for each type of UART. */ static const struct serial8250_config uart_config[] = { @@ -339,14 +330,14 @@ static void default_serial_dl_write(struct uart_8250_port *up, u32 value) } #ifdef CONFIG_HAS_IOPORT -static unsigned int hub6_serial_in(struct uart_port *p, int offset) +static u32 hub6_serial_in(struct uart_port *p, unsigned 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) +static void hub6_serial_out(struct uart_port *p, unsigned int offset, u32 value) { offset = offset << p->regshift; outb(p->hub6 - 1 + offset, p->iobase); @@ -354,73 +345,73 @@ static void hub6_serial_out(struct uart_port *p, int offset, int value) } #endif /* CONFIG_HAS_IOPORT */ -static unsigned int mem_serial_in(struct uart_port *p, int offset) +static u32 mem_serial_in(struct uart_port *p, unsigned int offset) { offset = offset << p->regshift; return readb(p->membase + offset); } -static void mem_serial_out(struct uart_port *p, int offset, int value) +static void mem_serial_out(struct uart_port *p, unsigned int offset, u32 value) { offset = offset << p->regshift; writeb(value, p->membase + offset); } -static void mem16_serial_out(struct uart_port *p, int offset, int value) +static void mem16_serial_out(struct uart_port *p, unsigned int offset, u32 value) { offset = offset << p->regshift; writew(value, p->membase + offset); } -static unsigned int mem16_serial_in(struct uart_port *p, int offset) +static u32 mem16_serial_in(struct uart_port *p, unsigned int offset) { offset = offset << p->regshift; return readw(p->membase + offset); } -static void mem32_serial_out(struct uart_port *p, int offset, int value) +static void mem32_serial_out(struct uart_port *p, unsigned int offset, u32 value) { offset = offset << p->regshift; writel(value, p->membase + offset); } -static unsigned int mem32_serial_in(struct uart_port *p, int offset) +static u32 mem32_serial_in(struct uart_port *p, unsigned int offset) { offset = offset << p->regshift; return readl(p->membase + offset); } -static void mem32be_serial_out(struct uart_port *p, int offset, int value) +static void mem32be_serial_out(struct uart_port *p, unsigned int offset, u32 value) { offset = offset << p->regshift; iowrite32be(value, p->membase + offset); } -static unsigned int mem32be_serial_in(struct uart_port *p, int offset) +static u32 mem32be_serial_in(struct uart_port *p, unsigned int offset) { offset = offset << p->regshift; return ioread32be(p->membase + offset); } #ifdef CONFIG_HAS_IOPORT -static unsigned int io_serial_in(struct uart_port *p, int offset) +static u32 io_serial_in(struct uart_port *p, unsigned int offset) { offset = offset << p->regshift; return inb(p->iobase + offset); } -static void io_serial_out(struct uart_port *p, int offset, int value) +static void io_serial_out(struct uart_port *p, unsigned int offset, u32 value) { offset = offset << p->regshift; outb(value, p->iobase + offset); } #endif -static unsigned int no_serial_in(struct uart_port *p, int offset) +static u32 no_serial_in(struct uart_port *p, unsigned int offset) { - return (unsigned int)-1; + return ~0U; } -static void no_serial_out(struct uart_port *p, int offset, int value) +static void no_serial_out(struct uart_port *p, unsigned int offset, u32 value) { } @@ -705,6 +696,15 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep) serial8250_rpm_put(p); } +/* Clear the interrupt registers. */ +static void serial8250_clear_interrupts(struct uart_port *port) +{ + serial_port_in(port, UART_LSR); + serial_port_in(port, UART_RX); + serial_port_in(port, UART_IIR); + serial_port_in(port, UART_MSR); +} + static void serial8250_clear_IER(struct uart_8250_port *up) { if (up->capabilities & UART_CAP_UUE) @@ -713,75 +713,6 @@ static void serial8250_clear_IER(struct uart_8250_port *up) serial_out(up, UART_IER, 0); } -#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) { - uart_port_lock_irq(&up->port); - __enable_rsa(up); - uart_port_unlock_irq(&up->port); - } - 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) { - uart_port_lock_irq(&up->port); - - 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; - uart_port_unlock_irq(&up->port); - } -} -#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. @@ -885,8 +816,6 @@ static void autoconfig_has_efr(struct uart_8250_port *up) 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; @@ -910,7 +839,6 @@ static void autoconfig_has_efr(struct uart_8250_port *up) * 0x14 - XR16C854. */ id1 = autoconfig_read_divisor_id(up); - DEBUG_AUTOCONF("850id=%04x ", id1); id2 = id1 >> 8; if (id2 == 0x10 || id2 == 0x12 || id2 == 0x14) { @@ -997,7 +925,6 @@ static void autoconfig_16550a(struct uart_8250_port *up) 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 { @@ -1010,8 +937,6 @@ static void autoconfig_16550a(struct uart_8250_port *up) if (status1 == UART_IIR_FIFO_ENABLED_16750) up->port.type = PORT_16550A_FSL64; - else - DEBUG_AUTOCONF("Motorola 8xxx DUART "); } serial_out(up, UART_EFR, 0); return; @@ -1023,7 +948,6 @@ static void autoconfig_16550a(struct uart_8250_port *up) */ 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; } @@ -1086,8 +1010,6 @@ static void autoconfig_16550a(struct uart_8250_port *up) serial_out(up, UART_LCR, 0); - DEBUG_AUTOCONF("iir1=%d iir2=%d ", status1, status2); - if (status1 == UART_IIR_FIFO_ENABLED_16550A && status2 == UART_IIR_FIFO_ENABLED_16750) { up->port.type = PORT_16750; @@ -1116,17 +1038,10 @@ static void autoconfig_16550a(struct uart_8250_port *up) * 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); @@ -1158,9 +1073,6 @@ static void autoconfig(struct uart_8250_port *up) if (!port->iobase && !port->mapbase && !port->membase) return; - DEBUG_AUTOCONF("%s: autoconf (0x%04lx, 0x%p): ", - port->name, 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. @@ -1207,9 +1119,7 @@ static void autoconfig(struct uart_8250_port *up) * We failed; there's nothing here */ uart_port_unlock_irqrestore(port, flags); - DEBUG_AUTOCONF("IER test failed (%02x, %02x) ", - scratch2, scratch3); - goto out; + return; } } @@ -1231,9 +1141,7 @@ static void autoconfig(struct uart_8250_port *up) serial8250_out_MCR(up, save_mcr); if (status1 != (UART_MSR_DCD | UART_MSR_CTS)) { uart_port_unlock_irqrestore(port, flags); - DEBUG_AUTOCONF("LOOP test failed (%02x) ", - status1); - goto out; + return; } } @@ -1267,14 +1175,7 @@ static void autoconfig(struct uart_8250_port *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 + rsa_autoconfig(up); serial_out(up, UART_LCR, save_lcr); @@ -1283,22 +1184,17 @@ static void autoconfig(struct uart_8250_port *up) up->capabilities = uart_config[port->type].flags; up->tx_loadsz = uart_config[port->type].tx_loadsz; - if (port->type == PORT_UNKNOWN) - goto out_unlock; - - /* - * 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); - serial8250_clear_IER(up); + if (port->type != PORT_UNKNOWN) { + /* + * Reset the UART. + */ + rsa_reset(up); + serial8250_out_MCR(up, save_mcr); + serial8250_clear_fifos(up); + serial_in(up, UART_RX); + serial8250_clear_IER(up); + } -out_unlock: uart_port_unlock_irqrestore(port, flags); /* @@ -1311,9 +1207,6 @@ out_unlock: dev_warn(port->dev, "detected caps %08x should be %08x\n", 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) @@ -1354,10 +1247,7 @@ static void autoconfig_irq(struct uart_8250_port *up) uart_port_lock_irq(port); serial_out(up, UART_IER, UART_IER_ALL_INTR); uart_port_unlock_irq(port); - serial_in(up, UART_LSR); - serial_in(up, UART_RX); - serial_in(up, UART_IIR); - serial_in(up, UART_MSR); + serial8250_clear_interrupts(port); serial_out(up, UART_TX, 0xFF); udelay(20); irq = probe_irq_off(irqs); @@ -2190,27 +2080,13 @@ static void serial8250_put_poll_char(struct uart_port *port, #endif /* CONFIG_CONSOLE_POLL */ -int serial8250_do_startup(struct uart_port *port) +static void serial8250_startup_special(struct uart_port *port) { struct uart_8250_port *up = up_to_u8250p(port); unsigned long flags; - unsigned char iir; - int retval; - u16 lsr; - 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) { + switch (port->type) { + case PORT_16C950: /* * Wake up and initialize UART * @@ -2227,9 +2103,8 @@ int serial8250_do_startup(struct uart_port *port) serial_port_out(port, UART_EFR, UART_EFR_ECB); serial_port_out(port, UART_LCR, 0); uart_port_unlock_irqrestore(port, flags); - } - - if (port->type == PORT_DA830) { + break; + case PORT_DA830: /* * Reset the port * @@ -2246,193 +2121,224 @@ int serial8250_do_startup(struct uart_port *port) UART_DA830_PWREMU_MGMT_UTRST | UART_DA830_PWREMU_MGMT_URRST | UART_DA830_PWREMU_MGMT_FREE); + break; + case PORT_RSA: + rsa_enable(up); + break; } +} -#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)) { - dev_info_ratelimited(port->dev, "LSR safety check engaged!\n"); - retval = -ENODEV; - goto out; - } +static void serial8250_set_TRG_levels(struct uart_port *port) +{ + struct uart_8250_port *up = up_to_u8250p(port); - /* - * For a XR16C850, we need to set the trigger levels - */ - if (port->type == PORT_16850) { - unsigned char fctr; + switch (port->type) { + /* For a XR16C850, we need to set the trigger levels */ + case PORT_16850: { + u8 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); + fctr |= UART_FCTR_TRGD; + serial_port_out(port, UART_FCTR, fctr | 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_FCTR, fctr | UART_FCTR_TX); serial_port_out(port, UART_TRG, UART_TRG_96); serial_port_out(port, UART_LCR, 0); + break; } + /* For the Altera 16550 variants, set TX threshold trigger level. */ + case PORT_ALTR_16550_F32: + case PORT_ALTR_16550_F64: + case PORT_ALTR_16550_F128: + if (port->fifosize <= 1) + return; - /* - * For the Altera 16550 variants, set TX threshold trigger level. - */ - if (((port->type == PORT_ALTR_16550_F32) || - (port->type == PORT_ALTR_16550_F64) || - (port->type == PORT_ALTR_16550_F128)) && (port->fifosize > 1)) { /* Bounds checking of TX threshold (valid 0 to fifosize-2) */ - if ((up->tx_loadsz < 2) || (up->tx_loadsz > port->fifosize)) { + if (up->tx_loadsz < 2 || up->tx_loadsz > port->fifosize) { dev_err(port->dev, "TX FIFO Threshold errors, skipping\n"); - } else { - serial_port_out(port, UART_ALTR_AFR, - UART_ALTR_EN_TXFIFO_LW); - serial_port_out(port, UART_ALTR_TX_LOW, - port->fifosize - up->tx_loadsz); - port->handle_irq = serial8250_tx_threshold_handle_irq; + return; } + serial_port_out(port, UART_ALTR_AFR, UART_ALTR_EN_TXFIFO_LW); + serial_port_out(port, UART_ALTR_TX_LOW, port->fifosize - up->tx_loadsz); + port->handle_irq = serial8250_tx_threshold_handle_irq; + break; } +} - /* Check if we need to have shared IRQs */ - if (port->irq && (up->port.flags & UPF_SHARE_IRQ)) - up->port.irqflags |= IRQF_SHARED; - - retval = up->ops->setup_irq(up); - if (retval) - goto out; - - if (port->irq && !(up->port.flags & UPF_NO_THRE_TEST)) { - unsigned char iir1; +static void serial8250_THRE_test(struct uart_port *port) +{ + struct uart_8250_port *up = up_to_u8250p(port); + unsigned long flags; + bool iir_noint1, iir_noint2; - if (port->irqflags & IRQF_SHARED) - disable_irq_nosync(port->irq); + if (!port->irq) + return; - /* - * 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. - * - * Synchronize UART_IER access against the console. - */ - uart_port_lock_irqsave(port, &flags); + if (up->port.flags & UPF_NO_THRE_TEST) + return; - 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) + disable_irq_nosync(port->irq); - uart_port_unlock_irqrestore(port, flags); + /* + * 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. + * + * Synchronize UART_IER access against the console. + */ + uart_port_lock_irqsave(port, &flags); - if (port->irqflags & IRQF_SHARED) - enable_irq(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 */ + iir_noint1 = serial_port_in(port, UART_IIR) & UART_IIR_NO_INT; + 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_noint2 = serial_port_in(port, UART_IIR) & UART_IIR_NO_INT; + serial_port_out(port, UART_IER, 0); - /* - * 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; - } - } + uart_port_unlock_irqrestore(port, flags); - up->ops->setup_timer(up); + if (port->irqflags & IRQF_SHARED) + enable_irq(port->irq); /* - * Now, initialize the UART + * 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. */ - serial_port_out(port, UART_LCR, UART_LCR_WLEN8); + if ((!iir_noint1 && iir_noint2) || up->port.flags & UPF_BUG_THRE) + up->bugs |= UART_BUG_THRE; +} - uart_port_lock_irqsave(port, &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. - */ +static void serial8250_init_mctrl(struct uart_port *port) +{ + if (port->flags & UPF_FOURPORT) { + if (!port->irq) + port->mctrl |= TIOCM_OUT1; + } else { + /* Most PC uarts need OUT2 raised to enable interrupts. */ if (port->irq) - up->port.mctrl |= TIOCM_OUT2; + port->mctrl |= TIOCM_OUT2; + } serial8250_set_mctrl(port, port->mctrl); +} + +static void serial8250_iir_txen_test(struct uart_port *port) +{ + struct uart_8250_port *up = up_to_u8250p(port); + bool lsr_temt, iir_noint; + + if (port->quirks & UPQ_NO_TXEN_TEST) + return; + + /* 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_temt = serial_port_in(port, UART_LSR) & UART_LSR_TEMT; + iir_noint = serial_port_in(port, UART_IIR) & UART_IIR_NO_INT; + serial_port_out(port, UART_IER, 0); /* * 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.quirks & UPQ_NO_TXEN_TEST)) { - /* - * 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; - dev_dbg(port->dev, "enabling bad tx status workarounds\n"); - } - } else { - up->bugs &= ~UART_BUG_TXEN; + * 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, in case of UPQ_NO_TXEN_TEST, let's just don't test if we receive TX irq. + * This way, we'll never enable UART_BUG_TXEN. + */ + if (lsr_temt && iir_noint) { + if (!(up->bugs & UART_BUG_TXEN)) { + up->bugs |= UART_BUG_TXEN; + dev_dbg(port->dev, "enabling bad tx status workarounds\n"); } + return; } + /* FIXME: why is this needed? */ + up->bugs &= ~UART_BUG_TXEN; +} + +static void serial8250_initialize(struct uart_port *port) +{ + unsigned long flags; + + uart_port_lock_irqsave(port, &flags); + serial_port_out(port, UART_LCR, UART_LCR_WLEN8); + + serial8250_init_mctrl(port); + serial8250_iir_txen_test(port); uart_port_unlock_irqrestore(port, flags); +} + +int serial8250_do_startup(struct uart_port *port) +{ + struct uart_8250_port *up = up_to_u8250p(port); + 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); + + serial8250_startup_special(port); + + /* + * Clear the FIFO buffers and disable them. + * (they will be reenabled in set_termios()) + */ + serial8250_clear_fifos(up); + + serial8250_clear_interrupts(port); + + /* + * 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)) { + dev_info_ratelimited(port->dev, "LSR safety check engaged!\n"); + retval = -ENODEV; + goto out; + } + + serial8250_set_TRG_levels(port); + + /* Check if we need to have shared IRQs */ + if (port->irq && (up->port.flags & UPF_SHARE_IRQ)) + up->port.irqflags |= IRQF_SHARED; + + retval = up->ops->setup_irq(up); + if (retval) + goto out; + + serial8250_THRE_test(port); + + up->ops->setup_timer(up); + + serial8250_initialize(port); /* * 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); + serial8250_clear_interrupts(port); up->lsr_saved_flags = 0; up->msr_saved_flags = 0; @@ -2521,12 +2427,7 @@ void serial8250_do_shutdown(struct uart_port *port) 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 + rsa_disable(up); /* * Read data port to reset things, and then unlink from @@ -2555,9 +2456,7 @@ static void serial8250_flush_buffer(struct uart_port *port) serial8250_tx_dma_flush(up); } -static unsigned int serial8250_do_get_divisor(struct uart_port *port, - unsigned int baud, - unsigned int *frac) +static unsigned int serial8250_do_get_divisor(struct uart_port *port, unsigned int baud) { upf_t magic_multiplier = port->flags & UPF_MAGIC_MULTIPLIER; struct uart_8250_port *up = up_to_u8250p(port); @@ -2618,26 +2517,23 @@ static unsigned int serial8250_get_divisor(struct uart_port *port, if (port->get_divisor) return port->get_divisor(port, baud, frac); - return serial8250_do_get_divisor(port, baud, frac); + return serial8250_do_get_divisor(port, baud); } -static unsigned char serial8250_compute_lcr(struct uart_8250_port *up, - tcflag_t c_cflag) +static unsigned char serial8250_compute_lcr(struct uart_8250_port *up, tcflag_t c_cflag) { - unsigned char cval; - - cval = UART_LCR_WLEN(tty_get_char_size(c_cflag)); + u8 lcr = UART_LCR_WLEN(tty_get_char_size(c_cflag)); if (c_cflag & CSTOPB) - cval |= UART_LCR_STOP; + lcr |= UART_LCR_STOP; if (c_cflag & PARENB) - cval |= UART_LCR_PARITY; + lcr |= UART_LCR_PARITY; if (!(c_cflag & PARODD)) - cval |= UART_LCR_EPAR; + lcr |= UART_LCR_EPAR; if (c_cflag & CMSPAR) - cval |= UART_LCR_SPAR; + lcr |= UART_LCR_SPAR; - return cval; + return lcr; } void serial8250_do_set_divisor(struct uart_port *port, unsigned int baud, @@ -2744,65 +2640,62 @@ out_unlock: } EXPORT_SYMBOL_GPL(serial8250_update_uartclk); -void -serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, - const struct ktermios *old) +static void serial8250_set_mini(struct uart_port *port, struct ktermios *termios) { struct uart_8250_port *up = up_to_u8250p(port); - unsigned char cval; - unsigned long flags; - unsigned int baud, quot, frac = 0; - if (up->capabilities & UART_CAP_MINI) { - termios->c_cflag &= ~(CSTOPB | PARENB | PARODD | CMSPAR); - if ((termios->c_cflag & CSIZE) == CS5 || - (termios->c_cflag & CSIZE) == CS6) - termios->c_cflag = (termios->c_cflag & ~CSIZE) | CS7; + if (!(up->capabilities & UART_CAP_MINI)) + return; + + termios->c_cflag &= ~(CSTOPB | PARENB | PARODD | CMSPAR); + + tcflag_t csize = termios->c_cflag & CSIZE; + if (csize == CS5 || csize == CS6) { + termios->c_cflag &= ~CSIZE; + termios->c_cflag |= CS7; } - cval = serial8250_compute_lcr(up, termios->c_cflag); +} - baud = serial8250_get_baud_rate(port, termios, old); - quot = serial8250_get_divisor(port, baud, &frac); +static void serial8250_set_trigger_for_slow_speed(struct uart_port *port, struct ktermios *termios, + unsigned int baud) +{ + struct uart_8250_port *up = up_to_u8250p(port); - /* - * Ok, we're now changing the port state. Do it with - * interrupts disabled. - * - * Synchronize UART_IER access against the console. - */ - serial8250_rpm_get(up); - uart_port_lock_irqsave(port, &flags); + if (!(up->capabilities & UART_CAP_FIFO)) + return; + if (port->fifosize <= 1) + return; + if (baud >= 2400) + return; + if (up->dma) + return; - up->lcr = cval; /* Save computed LCR */ + up->fcr &= ~UART_FCR_TRIGGER_MASK; + up->fcr |= UART_FCR_TRIGGER_1; +} - if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) { - if (baud < 2400 && !up->dma) { - 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. + */ +static void serial8250_set_afe(struct uart_port *port, struct ktermios *termios) +{ + struct uart_8250_port *up = up_to_u8250p(port); - /* - * 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. - */ - if (up->capabilities & UART_CAP_AFE) { - up->mcr &= ~UART_MCR_AFE; - if (termios->c_cflag & CRTSCTS) - up->mcr |= UART_MCR_AFE; - } + if (!(up->capabilities & UART_CAP_AFE)) + return; - /* - * Update the per-port timeout. - */ - uart_update_timeout(port, termios->c_cflag, baud); + up->mcr &= ~UART_MCR_AFE; + if (termios->c_cflag & CRTSCTS) + up->mcr |= UART_MCR_AFE; +} +static void serial8250_set_errors_and_ignores(struct uart_port *port, struct ktermios *termios) +{ /* - * Specify which conditions may be considered for error - * handling and the ignoring of characters. The actual - * ignoring of characters only occurs if the bit is set - * in @ignore_status_mask as well. + * Specify which conditions may be considered for error handling and the ignoring of + * characters. The actual ignoring of characters only occurs if the bit is set in + * @ignore_status_mask as well. */ port->read_status_mask = UART_LSR_OE | UART_LSR_DR; if (termios->c_iflag & INPCK) @@ -2810,34 +2703,32 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK)) port->read_status_mask |= UART_LSR_BI; - /* - * Characters to ignore - */ + /* Characters 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 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 - */ + /* 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 - */ +static void serial8250_set_ier(struct uart_port *port, struct ktermios *termios) +{ + struct uart_8250_port *up = up_to_u8250p(port); + + /* 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)) + 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; @@ -2845,41 +2736,90 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, 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); - } +static void serial8250_set_efr(struct uart_port *port, struct ktermios *termios) +{ + struct uart_8250_port *up = up_to_u8250p(port); + u8 efr_reg = UART_EFR; + u8 efr = 0; - serial8250_set_divisor(port, baud, quot, frac); + if (!(up->capabilities & UART_CAP_EFR)) + return; /* - * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR - * is written without DLAB set, this mode will be disabled. + * 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 (port->type == PORT_16750) + if (termios->c_cflag & CRTSCTS) + efr |= UART_EFR_CTS; + + if (port->flags & UPF_EXAR_EFR) + efr_reg = UART_XR_EFR; + + serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B); + serial_port_out(port, efr_reg, efr); +} + +static void serial8250_set_fcr(struct uart_port *port, struct ktermios *termios) +{ + struct uart_8250_port *up = up_to_u8250p(port); + bool is_16750 = port->type == PORT_16750; + + if (is_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 */ - } + /* + * LCR DLAB must be reset to enable 64-byte FIFO mode. If the FCR is written without DLAB + * set, this mode will be disabled. + */ + serial_port_out(port, UART_LCR, up->lcr); + + if (is_16750) + return; + + /* 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); +} + +void +serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, + const struct ktermios *old) +{ + struct uart_8250_port *up = up_to_u8250p(port); + unsigned long flags; + unsigned int baud, quot, frac = 0; + u8 lcr; + + serial8250_set_mini(port, termios); + lcr = serial8250_compute_lcr(up, termios->c_cflag); + baud = serial8250_get_baud_rate(port, termios, old); + quot = serial8250_get_divisor(port, baud, &frac); + + /* + * Ok, we're now changing the port state. Do it with + * interrupts disabled. + * + * Synchronize UART_IER access against the console. + */ + serial8250_rpm_get(up); + uart_port_lock_irqsave(port, &flags); + + up->lcr = lcr; + serial8250_set_trigger_for_slow_speed(port, termios, baud); + serial8250_set_afe(port, termios); + uart_update_timeout(port, termios->c_cflag, baud); + serial8250_set_errors_and_ignores(port, termios); + serial8250_set_ier(port, termios); + serial8250_set_efr(port, termios); + serial8250_set_divisor(port, baud, quot, frac); + serial8250_set_fcr(port, termios); serial8250_set_mctrl(port, port->mctrl); + uart_port_unlock_irqrestore(port, flags); serial8250_rpm_put(up); diff --git a/drivers/tty/serial/8250/8250_rsa.c b/drivers/tty/serial/8250/8250_rsa.c index 4c8b9671bd41..d34093cc03ad 100644 --- a/drivers/tty/serial/8250/8250_rsa.c +++ b/drivers/tty/serial/8250/8250_rsa.c @@ -107,6 +107,102 @@ void univ8250_rsa_support(struct uart_ops *ops) module_param_hw_array(probe_rsa, ulong, ioport, &probe_rsa_count, 0444); MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA"); +/* + * Attempts to turn on the RSA FIFO. Returns zero on failure. + * We set the port uart clock rate if we succeed. + */ +static int __rsa_enable(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; +} + +/* + * If this is an RSA port, see if we can kick it up to the higher speed clock. + */ +void rsa_enable(struct uart_8250_port *up) +{ + if (up->port.type != PORT_RSA) + return; + + if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16) { + uart_port_lock_irq(&up->port); + __rsa_enable(up); + uart_port_unlock_irq(&up->port); + } + if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) + serial_out(up, UART_RSA_FRR, 0); +} +EXPORT_SYMBOL_GPL_FOR_MODULES(rsa_enable, "8250_base"); + +/* + * Attempts to turn off the RSA FIFO and resets the RSA board back to 115kbps compat mode. 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. + */ +void rsa_disable(struct uart_8250_port *up) +{ + unsigned char mode; + int result; + + if (up->port.type != PORT_RSA) + return; + + if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16) + return; + + uart_port_lock_irq(&up->port); + 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; + uart_port_unlock_irq(&up->port); +} +EXPORT_SYMBOL_GPL_FOR_MODULES(rsa_disable, "8250_base"); + +void rsa_autoconfig(struct uart_8250_port *up) +{ + /* Only probe for RSA ports if we got the region. */ + if (up->port.type != PORT_16550A) + return; + if (!(up->probe & UART_PROBE_RSA)) + return; + + if (__rsa_enable(up)) + up->port.type = PORT_RSA; +} +EXPORT_SYMBOL_GPL_FOR_MODULES(rsa_autoconfig, "8250_base"); + +void rsa_reset(struct uart_8250_port *up) +{ + if (up->port.type != PORT_RSA) + return; + + serial_out(up, UART_RSA_FRR, 0); +} +EXPORT_SYMBOL_GPL_FOR_MODULES(rsa_reset, "8250_base"); + #ifdef CONFIG_SERIAL_8250_DEPRECATED_OPTIONS #ifndef MODULE /* diff --git a/drivers/tty/serial/8250/8250_rt288x.c b/drivers/tty/serial/8250/8250_rt288x.c index 6415ca8d3adf..bf28b8a9a710 100644 --- a/drivers/tty/serial/8250/8250_rt288x.c +++ b/drivers/tty/serial/8250/8250_rt288x.c @@ -33,7 +33,7 @@ static const u8 au_io_out_map[5] = { [UART_MCR] = 6, }; -static unsigned int au_serial_in(struct uart_port *p, int offset) +static u32 au_serial_in(struct uart_port *p, unsigned int offset) { if (offset >= ARRAY_SIZE(au_io_in_map)) return UINT_MAX; @@ -42,7 +42,7 @@ static unsigned int au_serial_in(struct uart_port *p, int offset) return __raw_readl(p->membase + (offset << p->regshift)); } -static void au_serial_out(struct uart_port *p, int offset, int value) +static void au_serial_out(struct uart_port *p, unsigned int offset, u32 value) { if (offset >= ARRAY_SIZE(au_io_out_map)) return; diff --git a/drivers/tty/serial/8250/8250_uniphier.c b/drivers/tty/serial/8250/8250_uniphier.c index 4874a9632db3..e3db60bf50c9 100644 --- a/drivers/tty/serial/8250/8250_uniphier.c +++ b/drivers/tty/serial/8250/8250_uniphier.c @@ -63,7 +63,7 @@ OF_EARLYCON_DECLARE(uniphier, "socionext,uniphier-uart", * The register map is slightly different from that of 8250. * IO callbacks must be overridden for correct access to FCR, LCR, MCR and SCR. */ -static unsigned int uniphier_serial_in(struct uart_port *p, int offset) +static u32 uniphier_serial_in(struct uart_port *p, unsigned int offset) { unsigned int valshift = 0; @@ -92,7 +92,7 @@ static unsigned int uniphier_serial_in(struct uart_port *p, int offset) return (readl(p->membase + offset) >> valshift) & 0xff; } -static void uniphier_serial_out(struct uart_port *p, int offset, int value) +static void uniphier_serial_out(struct uart_port *p, unsigned int offset, u32 value) { unsigned int valshift = 0; bool normal = false; diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile index b04eeda03b23..513a0941c284 100644 --- a/drivers/tty/serial/8250/Makefile +++ b/drivers/tty/serial/8250/Makefile @@ -24,6 +24,9 @@ obj-$(CONFIG_SERIAL_8250_ASPEED_VUART) += 8250_aspeed_vuart.o obj-$(CONFIG_SERIAL_8250_BCM2835AUX) += 8250_bcm2835aux.o obj-$(CONFIG_SERIAL_8250_BCM7271) += 8250_bcm7271.o obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o +ifeq ($(CONFIG_SERIAL_8250),y) +obj-$(CONFIG_X86_INTEL_CE) += 8250_ce4100.o +endif obj-$(CONFIG_SERIAL_8250_DFL) += 8250_dfl.o obj-$(CONFIG_SERIAL_8250_DW) += 8250_dw.o obj-$(CONFIG_SERIAL_8250_EM) += 8250_em.o |