diff options
Diffstat (limited to 'drivers/tty/serial')
60 files changed, 3896 insertions, 11326 deletions
diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index ebfb0bd5bef5..33ad9d6de532 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -11,6 +11,8 @@ #include <linux/serial_reg.h> #include <linux/dmaengine.h> +#include "../serial_mctrl_gpio.h" + struct uart_8250_dma { int (*tx_dma)(struct uart_8250_port *p); int (*rx_dma)(struct uart_8250_port *p); @@ -128,6 +130,24 @@ static inline void serial_dl_write(struct uart_8250_port *up, int value) up->dl_write(up, value); } +static inline bool serial8250_set_THRI(struct uart_8250_port *up) +{ + if (up->ier & UART_IER_THRI) + return false; + up->ier |= UART_IER_THRI; + serial_out(up, UART_IER, up->ier); + return true; +} + +static inline bool serial8250_clear_THRI(struct uart_8250_port *up) +{ + if (!(up->ier & UART_IER_THRI)) + return false; + up->ier &= ~UART_IER_THRI; + serial_out(up, UART_IER, up->ier); + return true; +} + struct uart_8250_port *serial8250_get_port(int line); void serial8250_rpm_get(struct uart_8250_port *p); @@ -139,14 +159,82 @@ void serial8250_rpm_put_tx(struct uart_8250_port *p); int serial8250_em485_init(struct uart_8250_port *p); void serial8250_em485_destroy(struct uart_8250_port *p); +/* MCR <-> TIOCM conversion */ +static inline int serial8250_TIOCM_to_MCR(int tiocm) +{ + int mcr = 0; + + if (tiocm & TIOCM_RTS) + mcr |= UART_MCR_RTS; + if (tiocm & TIOCM_DTR) + mcr |= UART_MCR_DTR; + if (tiocm & TIOCM_OUT1) + mcr |= UART_MCR_OUT1; + if (tiocm & TIOCM_OUT2) + mcr |= UART_MCR_OUT2; + if (tiocm & TIOCM_LOOP) + mcr |= UART_MCR_LOOP; + + return mcr; +} + +static inline int serial8250_MCR_to_TIOCM(int mcr) +{ + int tiocm = 0; + + if (mcr & UART_MCR_RTS) + tiocm |= TIOCM_RTS; + if (mcr & UART_MCR_DTR) + tiocm |= TIOCM_DTR; + if (mcr & UART_MCR_OUT1) + tiocm |= TIOCM_OUT1; + if (mcr & UART_MCR_OUT2) + tiocm |= TIOCM_OUT2; + if (mcr & UART_MCR_LOOP) + tiocm |= TIOCM_LOOP; + + return tiocm; +} + +/* MSR <-> TIOCM conversion */ +static inline int serial8250_MSR_to_TIOCM(int msr) +{ + int tiocm = 0; + + if (msr & UART_MSR_DCD) + tiocm |= TIOCM_CAR; + if (msr & UART_MSR_RI) + tiocm |= TIOCM_RNG; + if (msr & UART_MSR_DSR) + tiocm |= TIOCM_DSR; + if (msr & UART_MSR_CTS) + tiocm |= TIOCM_CTS; + + return tiocm; +} + static inline void serial8250_out_MCR(struct uart_8250_port *up, int value) { serial_out(up, UART_MCR, value); + + if (up->gpios) + mctrl_gpio_set(up->gpios, serial8250_MCR_to_TIOCM(value)); } static inline int serial8250_in_MCR(struct uart_8250_port *up) { - return serial_in(up, UART_MCR); + int mctrl; + + mctrl = serial_in(up, UART_MCR); + + if (up->gpios) { + unsigned int mctrl_gpio = 0; + + mctrl_gpio = mctrl_gpio_get_outputs(up->gpios, &mctrl_gpio); + mctrl |= serial8250_TIOCM_to_MCR(mctrl_gpio); + } + + return mctrl; } #if defined(__alpha__) && !defined(CONFIG_PCI) diff --git a/drivers/tty/serial/8250/8250_bcm2835aux.c b/drivers/tty/serial/8250/8250_bcm2835aux.c index bd53661103eb..8ce700c1a7fc 100644 --- a/drivers/tty/serial/8250/8250_bcm2835aux.c +++ b/drivers/tty/serial/8250/8250_bcm2835aux.c @@ -56,10 +56,8 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev) /* get the interrupt */ ret = platform_get_irq(pdev, 0); - if (ret < 0) { - dev_err(&pdev->dev, "irq not found - %i", ret); + if (ret < 0) return ret; - } data->uart.port.irq = ret; /* map the main registers */ diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index e441221e04b9..e682390ce0de 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -14,6 +14,7 @@ * serial8250_register_8250_port() ports */ +#include <linux/acpi.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/ioport.h> @@ -982,6 +983,8 @@ int serial8250_register_8250_port(struct uart_8250_port *up) uart = serial8250_find_match_or_unused(&up->port); if (uart && uart->port.type != PORT_8250_CIR) { + struct mctrl_gpios *gpios; + if (uart->port.dev) uart_remove_one_port(&serial8250_reg, &uart->port); @@ -1016,6 +1019,20 @@ int serial8250_register_8250_port(struct uart_8250_port *up) if (up->port.flags & UPF_FIXED_TYPE) uart->port.type = up->port.type; + /* + * 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 out_unlock; + } else { + uart->gpios = gpios; + } + } + serial8250_set_defaults(uart); /* Possibly override default I/O functions. */ @@ -1082,6 +1099,7 @@ int serial8250_register_8250_port(struct uart_8250_port *up) } } +out_unlock: mutex_unlock(&serial_mutex); return ret; diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c index bfa1a857f3ff..890fa7ddaa7f 100644 --- a/drivers/tty/serial/8250/8250_dma.c +++ b/drivers/tty/serial/8250/8250_dma.c @@ -34,10 +34,8 @@ static void __dma_tx_complete(void *param) uart_write_wakeup(&p->port); ret = serial8250_tx_dma(p); - if (ret) { - p->ier |= UART_IER_THRI; - serial_port_out(&p->port, UART_IER, p->ier); - } + if (ret) + serial8250_set_THRI(p); spin_unlock_irqrestore(&p->port.lock, flags); } @@ -100,10 +98,7 @@ int serial8250_tx_dma(struct uart_8250_port *p) dma_async_issue_pending(dma->txchan); if (dma->tx_err) { dma->tx_err = 0; - if (p->ier & UART_IER_THRI) { - p->ier &= ~UART_IER_THRI; - serial_out(p, UART_IER, p->ier); - } + serial8250_clear_THRI(p); } return 0; err: diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 284e8d052fc3..1c72fdc2dd37 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -27,66 +27,36 @@ #include <asm/byteorder.h> -#include "8250.h" +#include "8250_dwlib.h" /* Offsets for the DesignWare specific registers */ #define DW_UART_USR 0x1f /* UART Status Register */ -#define DW_UART_DLF 0xc0 /* Divisor Latch Fraction Register */ -#define DW_UART_CPR 0xf4 /* Component Parameter Register */ -#define DW_UART_UCV 0xf8 /* UART Component Version */ - -/* Component Parameter Register bits */ -#define DW_UART_CPR_ABP_DATA_WIDTH (3 << 0) -#define DW_UART_CPR_AFCE_MODE (1 << 4) -#define DW_UART_CPR_THRE_MODE (1 << 5) -#define DW_UART_CPR_SIR_MODE (1 << 6) -#define DW_UART_CPR_SIR_LP_MODE (1 << 7) -#define DW_UART_CPR_ADDITIONAL_FEATURES (1 << 8) -#define DW_UART_CPR_FIFO_ACCESS (1 << 9) -#define DW_UART_CPR_FIFO_STAT (1 << 10) -#define DW_UART_CPR_SHADOW (1 << 11) -#define DW_UART_CPR_ENCODED_PARMS (1 << 12) -#define DW_UART_CPR_DMA_EXTRA (1 << 13) -#define DW_UART_CPR_FIFO_MODE (0xff << 16) -/* Helper for fifo size calculation */ -#define DW_UART_CPR_FIFO_SIZE(a) (((a >> 16) & 0xff) * 16) /* DesignWare specific register fields */ #define DW_UART_MCR_SIRE BIT(6) struct dw8250_data { + struct dw8250_port_data data; + u8 usr_reg; - u8 dlf_size; - int line; int msr_mask_on; int msr_mask_off; struct clk *clk; struct clk *pclk; struct reset_control *rst; - struct uart_8250_dma dma; unsigned int skip_autocfg:1; unsigned int uart_16550_compatible:1; }; -static inline u32 dw8250_readl_ext(struct uart_port *p, int offset) +static inline struct dw8250_data *to_dw8250_data(struct dw8250_port_data *data) { - if (p->iotype == UPIO_MEM32BE) - return ioread32be(p->membase + offset); - return readl(p->membase + offset); -} - -static inline void dw8250_writel_ext(struct uart_port *p, int offset, u32 reg) -{ - if (p->iotype == UPIO_MEM32BE) - iowrite32be(reg, p->membase + offset); - else - writel(reg, p->membase + offset); + return container_of(data, struct dw8250_data, data); } static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value) { - struct dw8250_data *d = p->private_data; + struct dw8250_data *d = to_dw8250_data(p->private_data); /* Override any modem control signals if needed */ if (offset == UART_MSR) { @@ -160,7 +130,7 @@ static void dw8250_tx_wait_empty(struct uart_port *p) static void dw8250_serial_out38x(struct uart_port *p, int offset, int value) { - struct dw8250_data *d = p->private_data; + struct dw8250_data *d = to_dw8250_data(p->private_data); /* Allow the TX to drain before we reconfigure */ if (offset == UART_LCR) @@ -175,7 +145,7 @@ static void dw8250_serial_out38x(struct uart_port *p, int offset, int value) static void dw8250_serial_out(struct uart_port *p, int offset, int value) { - struct dw8250_data *d = p->private_data; + struct dw8250_data *d = to_dw8250_data(p->private_data); writeb(value, p->membase + (offset << p->regshift)); @@ -202,7 +172,7 @@ static unsigned int dw8250_serial_inq(struct uart_port *p, int offset) static void dw8250_serial_outq(struct uart_port *p, int offset, int value) { - struct dw8250_data *d = p->private_data; + struct dw8250_data *d = to_dw8250_data(p->private_data); value &= 0xff; __raw_writeq(value, p->membase + (offset << p->regshift)); @@ -216,7 +186,7 @@ static void dw8250_serial_outq(struct uart_port *p, int offset, int value) static void dw8250_serial_out32(struct uart_port *p, int offset, int value) { - struct dw8250_data *d = p->private_data; + struct dw8250_data *d = to_dw8250_data(p->private_data); writel(value, p->membase + (offset << p->regshift)); @@ -233,7 +203,7 @@ static unsigned int dw8250_serial_in32(struct uart_port *p, int offset) static void dw8250_serial_out32be(struct uart_port *p, int offset, int value) { - struct dw8250_data *d = p->private_data; + struct dw8250_data *d = to_dw8250_data(p->private_data); iowrite32be(value, p->membase + (offset << p->regshift)); @@ -252,7 +222,7 @@ static unsigned int dw8250_serial_in32be(struct uart_port *p, int offset) static int dw8250_handle_irq(struct uart_port *p) { struct uart_8250_port *up = up_to_u8250p(p); - struct dw8250_data *d = p->private_data; + struct dw8250_data *d = to_dw8250_data(p->private_data); unsigned int iir = p->serial_in(p, UART_IIR); unsigned int status; unsigned long flags; @@ -306,7 +276,7 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios, struct ktermios *old) { unsigned int baud = tty_termios_baud_rate(termios); - struct dw8250_data *d = p->private_data; + struct dw8250_data *d = to_dw8250_data(p->private_data); long rate; int ret; @@ -368,37 +338,6 @@ static bool dw8250_idma_filter(struct dma_chan *chan, void *param) return param == chan->device->dev; } -/* - * divisor = div(I) + div(F) - * "I" means integer, "F" means fractional - * quot = div(I) = clk / (16 * baud) - * frac = div(F) * 2^dlf_size - * - * let rem = clk % (16 * baud) - * we have: div(F) * (16 * baud) = rem - * so frac = 2^dlf_size * rem / (16 * baud) = (rem << dlf_size) / (16 * baud) - */ -static unsigned int dw8250_get_divisor(struct uart_port *p, - unsigned int baud, - unsigned int *frac) -{ - unsigned int quot, rem, base_baud = baud * 16; - struct dw8250_data *d = p->private_data; - - quot = p->uartclk / base_baud; - rem = p->uartclk % base_baud; - *frac = DIV_ROUND_CLOSEST(rem << d->dlf_size, base_baud); - - return quot; -} - -static void dw8250_set_divisor(struct uart_port *p, unsigned int baud, - unsigned int quot, unsigned int quot_frac) -{ - dw8250_writel_ext(p, DW_UART_DLF, quot_frac); - serial8250_do_set_divisor(p, baud, quot, quot_frac); -} - static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data) { if (p->dev->of_node) { @@ -437,65 +376,18 @@ static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data) /* Platforms with iDMA 64-bit */ if (platform_get_resource_byname(to_platform_device(p->dev), IORESOURCE_MEM, "lpss_priv")) { - 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. - */ - reg = dw8250_readl_ext(p, DW_UART_UCV); - if (!reg) - return; - - dev_dbg(p->dev, "Designware UART version %c.%c%c\n", - (reg >> 24) & 0xff, (reg >> 16) & 0xff, (reg >> 8) & 0xff); - - dw8250_writel_ext(p, DW_UART_DLF, ~0U); - reg = dw8250_readl_ext(p, DW_UART_DLF); - dw8250_writel_ext(p, DW_UART_DLF, 0); - - if (reg) { - struct dw8250_data *d = p->private_data; - - d->dlf_size = fls(reg); - p->get_divisor = dw8250_get_divisor; - p->set_divisor = dw8250_set_divisor; - } - - reg = dw8250_readl_ext(p, DW_UART_CPR); - if (!reg) - return; - - /* Select the type based on fifo */ - if (reg & DW_UART_CPR_FIFO_MODE) { - p->type = PORT_16550A; - p->flags |= UPF_FIXED_TYPE; - p->fifosize = DW_UART_CPR_FIFO_SIZE(reg); - up->capabilities = UART_CAP_FIFO; + data->data.dma.rx_param = p->dev->parent; + data->data.dma.tx_param = p->dev->parent; + data->data.dma.fn = dw8250_idma_filter; } - - if (reg & DW_UART_CPR_AFCE_MODE) - up->capabilities |= UART_CAP_AFE; - - if (reg & DW_UART_CPR_SIR_MODE) - up->capabilities |= UART_CAP_IRDA; } static int dw8250_probe(struct platform_device *pdev) { - struct uart_8250_port uart = {}; + struct uart_8250_port uart = {}, *up = &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 uart_port *p = &up->port; struct device *dev = &pdev->dev; struct dw8250_data *data; int err; @@ -534,9 +426,9 @@ static int dw8250_probe(struct platform_device *pdev) if (!data) return -ENOMEM; - data->dma.fn = dw8250_fallback_dma_filter; + data->data.dma.fn = dw8250_fallback_dma_filter; data->usr_reg = DW_UART_USR; - p->private_data = data; + p->private_data = &data->data; data->uart_16550_compatible = device_property_read_bool(dev, "snps,uart-16550-compatible"); @@ -632,14 +524,14 @@ static int dw8250_probe(struct platform_device *pdev) /* 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->data.dma.rxconf.src_maxburst = p->fifosize / 4; + data->data.dma.txconf.dst_maxburst = p->fifosize / 4; + up->dma = &data->data.dma; } - data->line = serial8250_register_8250_port(&uart); - if (data->line < 0) { - err = data->line; + data->data.line = serial8250_register_8250_port(up); + if (data->data.line < 0) { + err = data->data.line; goto err_reset; } @@ -667,10 +559,11 @@ err_clk: static int dw8250_remove(struct platform_device *pdev) { struct dw8250_data *data = platform_get_drvdata(pdev); + struct device *dev = &pdev->dev; - pm_runtime_get_sync(&pdev->dev); + pm_runtime_get_sync(dev); - serial8250_unregister_port(data->line); + serial8250_unregister_port(data->data.line); reset_control_assert(data->rst); @@ -680,8 +573,8 @@ static int dw8250_remove(struct platform_device *pdev) if (!IS_ERR(data->clk)) clk_disable_unprepare(data->clk); - pm_runtime_disable(&pdev->dev); - pm_runtime_put_noidle(&pdev->dev); + pm_runtime_disable(dev); + pm_runtime_put_noidle(dev); return 0; } @@ -691,7 +584,7 @@ static int dw8250_suspend(struct device *dev) { struct dw8250_data *data = dev_get_drvdata(dev); - serial8250_suspend_port(data->line); + serial8250_suspend_port(data->data.line); return 0; } @@ -700,7 +593,7 @@ static int dw8250_resume(struct device *dev) { struct dw8250_data *data = dev_get_drvdata(dev); - serial8250_resume_port(data->line); + serial8250_resume_port(data->data.line); return 0; } diff --git a/drivers/tty/serial/8250/8250_dwlib.c b/drivers/tty/serial/8250/8250_dwlib.c new file mode 100644 index 000000000000..6d6a78eead3e --- /dev/null +++ b/drivers/tty/serial/8250/8250_dwlib.c @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* Synopsys DesignWare 8250 library. */ + +#include <linux/bitops.h> +#include <linux/device.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/serial_8250.h> +#include <linux/serial_core.h> + +#include "8250_dwlib.h" + +/* Offsets for the DesignWare specific registers */ +#define DW_UART_DLF 0xc0 /* Divisor Latch Fraction Register */ +#define DW_UART_CPR 0xf4 /* Component Parameter Register */ +#define DW_UART_UCV 0xf8 /* UART Component Version */ + +/* Component Parameter Register bits */ +#define DW_UART_CPR_ABP_DATA_WIDTH (3 << 0) +#define DW_UART_CPR_AFCE_MODE (1 << 4) +#define DW_UART_CPR_THRE_MODE (1 << 5) +#define DW_UART_CPR_SIR_MODE (1 << 6) +#define DW_UART_CPR_SIR_LP_MODE (1 << 7) +#define DW_UART_CPR_ADDITIONAL_FEATURES (1 << 8) +#define DW_UART_CPR_FIFO_ACCESS (1 << 9) +#define DW_UART_CPR_FIFO_STAT (1 << 10) +#define DW_UART_CPR_SHADOW (1 << 11) +#define DW_UART_CPR_ENCODED_PARMS (1 << 12) +#define DW_UART_CPR_DMA_EXTRA (1 << 13) +#define DW_UART_CPR_FIFO_MODE (0xff << 16) + +/* Helper for FIFO size calculation */ +#define DW_UART_CPR_FIFO_SIZE(a) (((a >> 16) & 0xff) * 16) + +static inline u32 dw8250_readl_ext(struct uart_port *p, int offset) +{ + if (p->iotype == UPIO_MEM32BE) + return ioread32be(p->membase + offset); + return readl(p->membase + offset); +} + +static inline void dw8250_writel_ext(struct uart_port *p, int offset, u32 reg) +{ + if (p->iotype == UPIO_MEM32BE) + iowrite32be(reg, p->membase + offset); + else + writel(reg, p->membase + offset); +} + +/* + * divisor = div(I) + div(F) + * "I" means integer, "F" means fractional + * quot = div(I) = clk / (16 * baud) + * frac = div(F) * 2^dlf_size + * + * let rem = clk % (16 * baud) + * we have: div(F) * (16 * baud) = rem + * so frac = 2^dlf_size * rem / (16 * baud) = (rem << dlf_size) / (16 * baud) + */ +static unsigned int dw8250_get_divisor(struct uart_port *p, unsigned int baud, + unsigned int *frac) +{ + unsigned int quot, rem, base_baud = baud * 16; + struct dw8250_port_data *d = p->private_data; + + quot = p->uartclk / base_baud; + rem = p->uartclk % base_baud; + *frac = DIV_ROUND_CLOSEST(rem << d->dlf_size, base_baud); + + return quot; +} + +static void dw8250_set_divisor(struct uart_port *p, unsigned int baud, + unsigned int quot, unsigned int quot_frac) +{ + dw8250_writel_ext(p, DW_UART_DLF, quot_frac); + serial8250_do_set_divisor(p, baud, quot, quot_frac); +} + +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. + */ + reg = dw8250_readl_ext(p, DW_UART_UCV); + if (!reg) + return; + + dev_dbg(p->dev, "Designware UART version %c.%c%c\n", + (reg >> 24) & 0xff, (reg >> 16) & 0xff, (reg >> 8) & 0xff); + + dw8250_writel_ext(p, DW_UART_DLF, ~0U); + reg = dw8250_readl_ext(p, DW_UART_DLF); + dw8250_writel_ext(p, DW_UART_DLF, 0); + + if (reg) { + struct dw8250_port_data *d = p->private_data; + + d->dlf_size = fls(reg); + p->get_divisor = dw8250_get_divisor; + p->set_divisor = dw8250_set_divisor; + } + + reg = dw8250_readl_ext(p, DW_UART_CPR); + if (!reg) + return; + + /* Select the type based on FIFO */ + if (reg & DW_UART_CPR_FIFO_MODE) { + p->type = PORT_16550A; + p->flags |= UPF_FIXED_TYPE; + p->fifosize = DW_UART_CPR_FIFO_SIZE(reg); + up->capabilities = UART_CAP_FIFO; + } + + if (reg & DW_UART_CPR_AFCE_MODE) + up->capabilities |= UART_CAP_AFE; + + if (reg & DW_UART_CPR_SIR_MODE) + up->capabilities |= UART_CAP_IRDA; +} +EXPORT_SYMBOL_GPL(dw8250_setup_port); diff --git a/drivers/tty/serial/8250/8250_dwlib.h b/drivers/tty/serial/8250/8250_dwlib.h new file mode 100644 index 000000000000..87a4db2a8aba --- /dev/null +++ b/drivers/tty/serial/8250/8250_dwlib.h @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* Synopsys DesignWare 8250 library header file. */ + +#include <linux/types.h> + +#include "8250.h" + +struct dw8250_port_data { + /* Port properties */ + int line; + + /* DMA operations */ + struct uart_8250_dma dma; + + /* Hardware configuration */ + u8 dlf_size; +}; + +void dw8250_setup_port(struct uart_port *p); diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c index edd6dfe055bf..597eb9d16f21 100644 --- a/drivers/tty/serial/8250/8250_exar.c +++ b/drivers/tty/serial/8250/8250_exar.c @@ -19,6 +19,7 @@ #include <linux/string.h> #include <linux/tty.h> #include <linux/8250_pci.h> +#include <linux/delay.h> #include <asm/byteorder.h> @@ -36,6 +37,8 @@ #define UART_EXAR_INT0 0x80 #define UART_EXAR_8XMODE 0x88 /* 8X sampling rate select */ +#define UART_EXAR_SLEEP 0x8b /* Sleep mode */ +#define UART_EXAR_DVID 0x8d /* Device identification */ #define UART_EXAR_FCTR 0x08 /* Feature Control Register */ #define UART_FCTR_EXAR_IRDA 0x10 /* IrDa data encode select */ @@ -127,18 +130,95 @@ struct exar8250 { int line[0]; }; +static void exar_pm(struct uart_port *port, unsigned int state, unsigned int old) +{ + /* + * 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. + */ + serial_port_out(port, UART_EXAR_SLEEP, state ? 0xff : 0); +} + +/* + * 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_port *p, unsigned int baud, + unsigned int *frac) +{ + unsigned int quot_16; + + quot_16 = DIV_ROUND_CLOSEST(p->uartclk, baud); + *frac = quot_16 & 0x0f; + + return quot_16 >> 4; +} + +static void xr17v35x_set_divisor(struct uart_port *p, unsigned int baud, + unsigned int quot, unsigned int quot_frac) +{ + serial8250_do_set_divisor(p, baud, quot, quot_frac); + + /* Preserve bits not related to baudrate; DLD[7:4]. */ + quot_frac |= serial_port_in(p, 0x2) & 0xf0; + serial_port_out(p, 0x2, quot_frac); +} + +static void exar_shutdown(struct uart_port *port) +{ + unsigned char lsr; + bool tx_complete = 0; + struct uart_8250_port *up = up_to_u8250p(port); + struct circ_buf *xmit = &port->state->xmit; + int i = 0; + + do { + lsr = serial_in(up, UART_LSR); + if (lsr & (UART_LSR_TEMT | UART_LSR_THRE)) + tx_complete = 1; + else + tx_complete = 0; + usleep_range(1000, 1100); + } while (!uart_circ_empty(xmit) && !tx_complete && i++ < 1000); + + serial8250_do_shutdown(port); +} + static int default_setup(struct exar8250 *priv, struct pci_dev *pcidev, int idx, unsigned int offset, struct uart_8250_port *port) { const struct exar8250_board *board = priv->board; unsigned int bar = 0; + unsigned char status; port->port.iotype = UPIO_MEM; port->port.mapbase = pci_resource_start(pcidev, bar) + offset; port->port.membase = priv->virt + offset; port->port.regshift = board->reg_shift; + /* + * 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. + */ + status = readb(port->port.membase + UART_EXAR_DVID); + if (status == 0x82 || status == 0x84 || status == 0x88) { + port->port.type = PORT_XR17V35X; + + port->port.get_divisor = xr17v35x_get_divisor; + port->port.set_divisor = xr17v35x_set_divisor; + } else { + port->port.type = PORT_XR17D15X; + } + + port->port.pm = exar_pm; + port->port.shutdown = exar_shutdown; + return 0; } @@ -434,6 +514,16 @@ static void pci_xr17v35x_exit(struct pci_dev *pcidev) port->port.private_data = NULL; } +static inline void exar_misc_clear(struct exar8250 *priv) +{ + /* Clear all PCI interrupts by reading INT0. No effect on IIR */ + readb(priv->virt + UART_EXAR_INT0); + + /* Clear INT0 for Expansion Interface slave ports, too */ + if (priv->board->num_ports > 8) + readb(priv->virt + 0x2000 + UART_EXAR_INT0); +} + /* * These Exar UARTs have an extra interrupt indicator that could fire for a * few interrupts that are not presented/cleared through IIR. One of which is @@ -445,14 +535,7 @@ static void pci_xr17v35x_exit(struct pci_dev *pcidev) */ static irqreturn_t exar_misc_handler(int irq, void *data) { - struct exar8250 *priv = data; - - /* Clear all PCI interrupts by reading INT0. No effect on IIR */ - readb(priv->virt + UART_EXAR_INT0); - - /* Clear INT0 for Expansion Interface slave ports, too */ - if (priv->board->num_ports > 8) - readb(priv->virt + 0x2000 + UART_EXAR_INT0); + exar_misc_clear(data); return IRQ_HANDLED; } @@ -478,9 +561,7 @@ exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent) nr_ports = board->num_ports ? board->num_ports : pcidev->device & 0x0f; - priv = devm_kzalloc(&pcidev->dev, sizeof(*priv) + - sizeof(unsigned int) * nr_ports, - GFP_KERNEL); + priv = devm_kzalloc(&pcidev->dev, struct_size(priv, line, nr_ports), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -496,8 +577,7 @@ exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent) return rc; memset(&uart, 0, sizeof(uart)); - uart.port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ - | UPF_EXAR_EFR; + uart.port.flags = UPF_SHARE_IRQ | UPF_EXAR_EFR | UPF_FIXED_TYPE | UPF_FIXED_PORT; uart.port.irq = pci_irq_vector(pcidev, 0); uart.port.dev = &pcidev->dev; @@ -506,6 +586,9 @@ exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent) if (rc) return rc; + /* Clear interrupts */ + exar_misc_clear(priv); + for (i = 0; i < nr_ports && i < maxnr; i++) { rc = board->setup(priv, pcidev, &uart, i); if (rc) { @@ -561,10 +644,11 @@ static int __maybe_unused exar_suspend(struct device *dev) static int __maybe_unused exar_resume(struct device *dev) { - struct pci_dev *pcidev = to_pci_dev(dev); - struct exar8250 *priv = pci_get_drvdata(pcidev); + struct exar8250 *priv = dev_get_drvdata(dev); unsigned int i; + exar_misc_clear(priv); + for (i = 0; i < priv->nr; i++) if (priv->line[i] >= 0) serial8250_resume_port(priv->line[i]); diff --git a/drivers/tty/serial/8250/8250_lpc18xx.c b/drivers/tty/serial/8250/8250_lpc18xx.c index eddf119374e1..570e25d6f37e 100644 --- a/drivers/tty/serial/8250/8250_lpc18xx.c +++ b/drivers/tty/serial/8250/8250_lpc18xx.c @@ -106,10 +106,8 @@ static int lpc18xx_serial_probe(struct platform_device *pdev) int irq, ret; irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "irq not found"); + if (irq < 0) return irq; - } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { diff --git a/drivers/tty/serial/8250/8250_lpss.c b/drivers/tty/serial/8250/8250_lpss.c index 53ca9ba6ab4b..5f72ef3ea574 100644 --- a/drivers/tty/serial/8250/8250_lpss.c +++ b/drivers/tty/serial/8250/8250_lpss.c @@ -14,7 +14,7 @@ #include <linux/dmaengine.h> #include <linux/dma/dw.h> -#include "8250.h" +#include "8250_dwlib.h" #define PCI_DEVICE_ID_INTEL_QRK_UARTx 0x0936 @@ -24,6 +24,13 @@ #define PCI_DEVICE_ID_INTEL_BSW_UART1 0x228a #define PCI_DEVICE_ID_INTEL_BSW_UART2 0x228c +#define PCI_DEVICE_ID_INTEL_EHL_UART0 0x4b96 +#define PCI_DEVICE_ID_INTEL_EHL_UART1 0x4b97 +#define PCI_DEVICE_ID_INTEL_EHL_UART2 0x4b98 +#define PCI_DEVICE_ID_INTEL_EHL_UART3 0x4b99 +#define PCI_DEVICE_ID_INTEL_EHL_UART4 0x4b9a +#define PCI_DEVICE_ID_INTEL_EHL_UART5 0x4b9b + #define PCI_DEVICE_ID_INTEL_BDW_UART1 0x9ce3 #define PCI_DEVICE_ID_INTEL_BDW_UART2 0x9ce4 @@ -48,21 +55,25 @@ struct lpss8250_board { }; struct lpss8250 { - int line; + struct dw8250_port_data data; struct lpss8250_board *board; /* DMA parameters */ - struct uart_8250_dma dma; struct dw_dma_chip dma_chip; struct dw_dma_slave dma_param; u8 dma_maxburst; }; +static inline struct lpss8250 *to_lpss8250(struct dw8250_port_data *data) +{ + return container_of(data, struct lpss8250, data); +} + static void byt_set_termios(struct uart_port *p, struct ktermios *termios, struct ktermios *old) { unsigned int baud = tty_termios_baud_rate(termios); - struct lpss8250 *lpss = p->private_data; + struct lpss8250 *lpss = to_lpss8250(p->private_data); unsigned long fref = lpss->board->freq, fuart = baud * 16; unsigned long w = BIT(15) - 1; unsigned long m, n; @@ -109,7 +120,6 @@ static unsigned int byt_get_mctrl(struct uart_port *port) static int byt_serial_setup(struct lpss8250 *lpss, struct uart_port *port) { struct dw_dma_slave *param = &lpss->dma_param; - struct uart_8250_port *up = up_to_u8250p(port); struct pci_dev *pdev = to_pci_dev(port->dev); unsigned int dma_devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0); struct pci_dev *dma_dev = pci_get_slot(pdev->bus, dma_devfn); @@ -135,10 +145,6 @@ static int byt_serial_setup(struct lpss8250 *lpss, struct uart_port *port) param->m_master = 0; param->p_master = 1; - /* TODO: Detect FIFO size automaticaly for DesignWare 8250 */ - port->fifosize = 64; - up->tx_loadsz = 64; - lpss->dma_maxburst = 16; port->set_termios = byt_set_termios; @@ -163,16 +169,19 @@ static const struct dw_dma_platform_data qrk_serial_dma_pdata = { static void qrk_serial_setup_dma(struct lpss8250 *lpss, struct uart_port *port) { - struct uart_8250_dma *dma = &lpss->dma; + struct uart_8250_dma *dma = &lpss->data.dma; struct dw_dma_chip *chip = &lpss->dma_chip; struct dw_dma_slave *param = &lpss->dma_param; struct pci_dev *pdev = to_pci_dev(port->dev); int ret; + chip->pdata = &qrk_serial_dma_pdata; chip->dev = &pdev->dev; + chip->id = pdev->devfn; chip->irq = pci_irq_vector(pdev, 0); chip->regs = pci_ioremap_bar(pdev, 1); - chip->pdata = &qrk_serial_dma_pdata; + if (!chip->regs) + return; /* Falling back to PIO mode if DMA probing fails */ ret = dw_dma_probe(chip); @@ -195,11 +204,15 @@ static void qrk_serial_setup_dma(struct lpss8250 *lpss, struct uart_port *port) static void qrk_serial_exit_dma(struct lpss8250 *lpss) { + struct dw_dma_chip *chip = &lpss->dma_chip; struct dw_dma_slave *param = &lpss->dma_param; if (!param->dma_dev) return; - dw_dma_remove(&lpss->dma_chip); + + dw_dma_remove(chip); + + pci_iounmap(to_pci_dev(chip->dev), chip->regs); } #else /* CONFIG_SERIAL_8250_DMA */ static void qrk_serial_setup_dma(struct lpss8250 *lpss, struct uart_port *port) {} @@ -241,7 +254,7 @@ static bool lpss8250_dma_filter(struct dma_chan *chan, void *param) static int lpss8250_dma_setup(struct lpss8250 *lpss, struct uart_8250_port *port) { - struct uart_8250_dma *dma = &lpss->dma; + struct uart_8250_dma *dma = &lpss->data.dma; struct dw_dma_slave *rx_param, *tx_param; struct device *dev = port->port.dev; @@ -290,7 +303,7 @@ static int lpss8250_probe(struct pci_dev *pdev, const struct pci_device_id *id) uart.port.dev = &pdev->dev; uart.port.irq = pdev->irq; - uart.port.private_data = lpss; + uart.port.private_data = &lpss->data; uart.port.type = PORT_16550A; uart.port.iotype = UPIO_MEM; uart.port.regshift = 2; @@ -306,6 +319,8 @@ static int lpss8250_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (ret) return ret; + dw8250_setup_port(&uart.port); + ret = lpss8250_dma_setup(lpss, &uart); if (ret) goto err_exit; @@ -314,7 +329,7 @@ static int lpss8250_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (ret < 0) goto err_exit; - lpss->line = ret; + lpss->data.line = ret; pci_set_drvdata(pdev, lpss); return 0; @@ -329,7 +344,7 @@ static void lpss8250_remove(struct pci_dev *pdev) { struct lpss8250 *lpss = pci_get_drvdata(pdev); - serial8250_unregister_port(lpss->line); + serial8250_unregister_port(lpss->data.line); if (lpss->board->exit) lpss->board->exit(lpss); @@ -341,6 +356,11 @@ static const struct lpss8250_board byt_board = { .setup = byt_serial_setup, }; +static const struct lpss8250_board ehl_board = { + .freq = 200000000, + .base_baud = 12500000, +}; + static const struct lpss8250_board qrk_board = { .freq = 44236800, .base_baud = 2764800, @@ -348,17 +368,21 @@ static const struct lpss8250_board qrk_board = { .exit = qrk_serial_exit, }; -#define LPSS_DEVICE(id, board) { PCI_VDEVICE(INTEL, id), (kernel_ulong_t)&board } - static const struct pci_device_id pci_ids[] = { - LPSS_DEVICE(PCI_DEVICE_ID_INTEL_QRK_UARTx, qrk_board), - LPSS_DEVICE(PCI_DEVICE_ID_INTEL_BYT_UART1, byt_board), - LPSS_DEVICE(PCI_DEVICE_ID_INTEL_BYT_UART2, byt_board), - LPSS_DEVICE(PCI_DEVICE_ID_INTEL_BSW_UART1, byt_board), - LPSS_DEVICE(PCI_DEVICE_ID_INTEL_BSW_UART2, byt_board), - LPSS_DEVICE(PCI_DEVICE_ID_INTEL_BDW_UART1, byt_board), - LPSS_DEVICE(PCI_DEVICE_ID_INTEL_BDW_UART2, byt_board), - { }, + { PCI_DEVICE_DATA(INTEL, QRK_UARTx, &qrk_board) }, + { PCI_DEVICE_DATA(INTEL, EHL_UART0, &ehl_board) }, + { PCI_DEVICE_DATA(INTEL, EHL_UART1, &ehl_board) }, + { PCI_DEVICE_DATA(INTEL, EHL_UART2, &ehl_board) }, + { PCI_DEVICE_DATA(INTEL, EHL_UART3, &ehl_board) }, + { PCI_DEVICE_DATA(INTEL, EHL_UART4, &ehl_board) }, + { PCI_DEVICE_DATA(INTEL, EHL_UART5, &ehl_board) }, + { PCI_DEVICE_DATA(INTEL, BYT_UART1, &byt_board) }, + { PCI_DEVICE_DATA(INTEL, BYT_UART2, &byt_board) }, + { PCI_DEVICE_DATA(INTEL, BSW_UART1, &byt_board) }, + { PCI_DEVICE_DATA(INTEL, BSW_UART2, &byt_board) }, + { PCI_DEVICE_DATA(INTEL, BDW_UART1, &byt_board) }, + { PCI_DEVICE_DATA(INTEL, BDW_UART2, &byt_board) }, + { } }; MODULE_DEVICE_TABLE(pci, pci_ids); diff --git a/drivers/tty/serial/8250/8250_moxa.c b/drivers/tty/serial/8250/8250_moxa.c deleted file mode 100644 index 1ee4cd94d4fa..000000000000 --- a/drivers/tty/serial/8250/8250_moxa.c +++ /dev/null @@ -1,155 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * 8250_moxa.c - MOXA Smartio/Industio MUE multiport serial driver. - * - * Author: Mathieu OTHACEHE <m.othacehe@gmail.com> - */ - -#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; - brd->num_ports = nr_ports; - - 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 417c7c810df9..b411ba4eb5e9 100644 --- a/drivers/tty/serial/8250/8250_mtk.c +++ b/drivers/tty/serial/8250/8250_mtk.c @@ -10,6 +10,7 @@ #include <linux/module.h> #include <linux/of_irq.h> #include <linux/of_platform.h> +#include <linux/pinctrl/consumer.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/serial_8250.h> @@ -47,7 +48,6 @@ #define MTK_UART_DMA_EN_RX 0x5 #define MTK_UART_ESCAPE_CHAR 0x77 /* Escape char added under sw fc */ -#define MTK_UART_TX_SIZE UART_XMIT_SIZE #define MTK_UART_RX_SIZE 0x8000 #define MTK_UART_TX_TRIGGER 1 #define MTK_UART_RX_TRIGGER MTK_UART_RX_SIZE @@ -70,6 +70,7 @@ struct mtk8250_data { #ifdef CONFIG_SERIAL_8250_DMA enum dma_rx_status rx_status; #endif + int rx_wakeup_irq; }; /* flow control mode */ @@ -89,28 +90,30 @@ static void mtk8250_dma_rx_complete(void *param) struct mtk8250_data *data = up->port.private_data; struct tty_port *tty_port = &up->port.state->port; struct dma_tx_state state; + int copied, total, cnt; unsigned char *ptr; - int copied; - dma_sync_single_for_cpu(dma->rxchan->device->dev, dma->rx_addr, - dma->rx_size, DMA_FROM_DEVICE); + if (data->rx_status == DMA_RX_SHUTDOWN) + return; dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state); + total = dma->rx_size - state.residue; + cnt = total; - if (data->rx_status == DMA_RX_SHUTDOWN) - return; + if ((data->rx_pos + cnt) > dma->rx_size) + cnt = dma->rx_size - data->rx_pos; - if ((data->rx_pos + state.residue) <= dma->rx_size) { - ptr = (unsigned char *)(data->rx_pos + dma->rx_buf); - copied = tty_insert_flip_string(tty_port, ptr, state.residue); - } else { - ptr = (unsigned char *)(data->rx_pos + dma->rx_buf); - copied = tty_insert_flip_string(tty_port, ptr, - dma->rx_size - data->rx_pos); + ptr = (unsigned char *)(data->rx_pos + dma->rx_buf); + copied = tty_insert_flip_string(tty_port, ptr, cnt); + data->rx_pos += cnt; + + if (total > cnt) { ptr = (unsigned char *)(dma->rx_buf); - copied += tty_insert_flip_string(tty_port, ptr, - data->rx_pos + state.residue - dma->rx_size); + cnt = total - cnt; + copied += tty_insert_flip_string(tty_port, ptr, cnt); + data->rx_pos = cnt; } + up->port.icount.rx += copied; tty_flip_buffer_push(tty_port); @@ -121,9 +124,7 @@ static void mtk8250_dma_rx_complete(void *param) static void mtk8250_rx_dma(struct uart_8250_port *up) { struct uart_8250_dma *dma = up->dma; - struct mtk8250_data *data = up->port.private_data; struct dma_async_tx_descriptor *desc; - struct dma_tx_state state; desc = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr, dma->rx_size, DMA_DEV_TO_MEM, @@ -138,12 +139,6 @@ static void mtk8250_rx_dma(struct uart_8250_port *up) dma->rx_cookie = dmaengine_submit(desc); - dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state); - data->rx_pos = state.residue; - - dma_sync_single_for_device(dma->rxchan->device->dev, dma->rx_addr, - dma->rx_size, DMA_FROM_DEVICE); - dma_async_issue_pending(dma->rxchan); } @@ -156,13 +151,11 @@ static void mtk8250_dma_enable(struct uart_8250_port *up) if (data->rx_status != DMA_RX_START) return; - dma->rxconf.direction = DMA_DEV_TO_MEM; - dma->rxconf.src_addr_width = dma->rx_size / 1024; - dma->rxconf.src_addr = dma->rx_addr; + dma->rxconf.src_port_window_size = dma->rx_size; + dma->rxconf.src_addr = dma->rx_addr; - dma->txconf.direction = DMA_MEM_TO_DEV; - dma->txconf.dst_addr_width = MTK_UART_TX_SIZE / 1024; - dma->txconf.dst_addr = dma->tx_addr; + dma->txconf.dst_port_window_size = UART_XMIT_SIZE; + dma->txconf.dst_addr = dma->tx_addr; serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); @@ -551,6 +544,8 @@ static int mtk8250_probe(struct platform_device *pdev) pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); + data->rx_wakeup_irq = platform_get_irq(pdev, 1); + return 0; } @@ -572,15 +567,35 @@ static int mtk8250_remove(struct platform_device *pdev) static int __maybe_unused mtk8250_suspend(struct device *dev) { struct mtk8250_data *data = dev_get_drvdata(dev); + int irq = data->rx_wakeup_irq; + int err; serial8250_suspend_port(data->line); + pinctrl_pm_select_sleep_state(dev); + if (irq >= 0) { + err = enable_irq_wake(irq); + if (err) { + dev_err(dev, + "failed to enable irq wake on IRQ %d: %d\n", + irq, err); + pinctrl_pm_select_default_state(dev); + serial8250_resume_port(data->line); + return err; + } + } + return 0; } static int __maybe_unused mtk8250_resume(struct device *dev) { struct mtk8250_data *data = dev_get_drvdata(dev); + int irq = data->rx_wakeup_irq; + + if (irq >= 0) + disable_irq_wake(irq); + pinctrl_pm_select_default_state(dev); serial8250_resume_port(data->line); diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c index 0277479c87e9..0826cfdbd406 100644 --- a/drivers/tty/serial/8250/8250_of.c +++ b/drivers/tty/serial/8250/8250_of.c @@ -70,9 +70,10 @@ static int of_platform_serial_setup(struct platform_device *ofdev, /* 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"); ret = PTR_ERR(info->clk); + if (ret != -EPROBE_DEFER) + dev_warn(&ofdev->dev, + "failed to get clock: %d\n", ret); goto err_pmruntime; } @@ -205,18 +206,16 @@ err_pmruntime: /* * 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_8250_port port8250; + unsigned int port_type; u32 tx_threshold; - int port_type; int ret; - match = of_match_device(of_platform_serial_table, &ofdev->dev); - if (!match) + port_type = (unsigned long)of_device_get_match_data(&ofdev->dev); + if (port_type == PORT_UNKNOWN) return -EINVAL; if (of_property_read_bool(ofdev->dev.of_node, "used-by-rtas")) @@ -226,7 +225,6 @@ static int of_platform_serial_probe(struct platform_device *ofdev) if (info == NULL) return -ENOMEM; - port_type = (unsigned long)match->data; memset(&port8250, 0, sizeof(port8250)); ret = of_platform_serial_setup(ofdev, port_type, &port8250.port, info); if (ret) diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index 0a8316632d75..c68e2b3a1634 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -141,18 +141,20 @@ static void omap8250_set_mctrl(struct uart_port *port, unsigned int mctrl) serial8250_do_set_mctrl(port, mctrl); - /* - * Turn off autoRTS if RTS is lowered and restore autoRTS setting - * if RTS is raised - */ - lcr = serial_in(up, UART_LCR); - serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); - if ((mctrl & TIOCM_RTS) && (port->status & UPSTAT_AUTORTS)) - priv->efr |= UART_EFR_RTS; - else - priv->efr &= ~UART_EFR_RTS; - serial_out(up, UART_EFR, priv->efr); - serial_out(up, UART_LCR, lcr); + if (!up->gpios) { + /* + * Turn off autoRTS if RTS is lowered and restore autoRTS + * setting if RTS is raised + */ + lcr = serial_in(up, UART_LCR); + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); + if ((mctrl & TIOCM_RTS) && (port->status & UPSTAT_AUTORTS)) + priv->efr |= UART_EFR_RTS; + else + priv->efr &= ~UART_EFR_RTS; + serial_out(up, UART_EFR, priv->efr); + serial_out(up, UART_LCR, lcr); + } } /* @@ -453,7 +455,8 @@ static void omap_8250_set_termios(struct uart_port *port, priv->efr = 0; up->port.status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS | UPSTAT_AUTOXOFF); - if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW) { + if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW && + !up->gpios) { /* Enable AUTOCTS (autoRTS is enabled when RTS is raised) */ up->port.status |= UPSTAT_AUTOCTS | UPSTAT_AUTORTS; priv->efr |= UART_EFR_CTS; @@ -923,15 +926,13 @@ static void omap_8250_dma_tx_complete(void *param) ret = omap_8250_tx_dma(p); if (ret) en_thri = true; - } else if (p->capabilities & UART_CAP_RPM) { en_thri = true; } if (en_thri) { dma->tx_err = 1; - p->ier |= UART_IER_THRI; - serial_port_out(&p->port, UART_IER, p->ier); + serial8250_set_THRI(p); } spin_unlock_irqrestore(&p->port.lock, flags); @@ -959,10 +960,7 @@ static int omap_8250_tx_dma(struct uart_8250_port *p) ret = -EBUSY; goto err; } - if (p->ier & UART_IER_THRI) { - p->ier &= ~UART_IER_THRI; - serial_out(p, UART_IER, p->ier); - } + serial8250_clear_THRI(p); return 0; } @@ -1020,10 +1018,7 @@ static int omap_8250_tx_dma(struct uart_8250_port *p) if (dma->tx_err) dma->tx_err = 0; - if (p->ier & UART_IER_THRI) { - p->ier &= ~UART_IER_THRI; - serial_out(p, UART_IER, p->ier); - } + serial8250_clear_THRI(p); if (skip_byte) serial_out(p, UART_TX, xmit->buf[xmit->tail]); return 0; @@ -1239,7 +1234,16 @@ static int omap8250_probe(struct platform_device *pdev) device_init_wakeup(&pdev->dev, true); pm_runtime_use_autosuspend(&pdev->dev); - pm_runtime_set_autosuspend_delay(&pdev->dev, -1); + + /* + * Disable runtime PM until autosuspend delay unless specifically + * enabled by the user via sysfs. This is the historic way to + * prevent an unsafe default policy with lossy characters on wake-up. + * For serdev devices this is not needed, the policy can be managed by + * the serdev driver. + */ + if (!of_get_available_child_count(pdev->dev.of_node)) + pm_runtime_set_autosuspend_delay(&pdev->dev, -1); pm_runtime_irq_safe(&pdev->dev); pm_runtime_enable(&pdev->dev); diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index df41397de478..6adbadd6a56a 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -43,6 +43,11 @@ struct pci_serial_quirk { void (*exit)(struct pci_dev *dev); }; +struct f815xxa_data { + spinlock_t lock; + int idx; +}; + #define PCI_NUM_BAR_RESOURCES 6 struct serial_private { @@ -53,6 +58,16 @@ struct serial_private { int line[0]; }; +static const struct pci_device_id pci_use_msi[] = { + { PCI_DEVICE_SUB(PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900, + 0xA000, 0x1000) }, + { PCI_DEVICE_SUB(PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9912, + 0xA000, 0x1000) }, + { PCI_DEVICE_SUB(PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9922, + 0xA000, 0x1000) }, + { } +}; + static int pci_default_setup(struct serial_private*, const struct pciserial_board*, struct uart_8250_port *, int); @@ -730,8 +745,16 @@ static int pci_ni8430_init(struct pci_dev *dev) } /* UART Port Control Register */ -#define NI8430_PORTCON 0x0f -#define NI8430_PORTCON_TXVR_ENABLE (1 << 3) +#define NI16550_PCR_OFFSET 0x0f +#define NI16550_PCR_RS422 0x00 +#define NI16550_PCR_ECHO_RS485 0x01 +#define NI16550_PCR_DTR_RS485 0x02 +#define NI16550_PCR_AUTO_RS485 0x03 +#define NI16550_PCR_WIRE_MODE_MASK 0x03 +#define NI16550_PCR_TXVR_ENABLE_BIT BIT(3) +#define NI16550_PCR_RS485_TERMINATION_BIT BIT(6) +#define NI16550_ACR_DTR_AUTO_DTR (0x2 << 3) +#define NI16550_ACR_DTR_MANUAL_DTR (0x0 << 3) static int pci_ni8430_setup(struct serial_private *priv, @@ -753,14 +776,117 @@ pci_ni8430_setup(struct serial_private *priv, return -ENOMEM; /* enable the transceiver */ - writeb(readb(p + offset + NI8430_PORTCON) | NI8430_PORTCON_TXVR_ENABLE, - p + offset + NI8430_PORTCON); + writeb(readb(p + offset + NI16550_PCR_OFFSET) | NI16550_PCR_TXVR_ENABLE_BIT, + p + offset + NI16550_PCR_OFFSET); iounmap(p); return setup_port(priv, port, bar, offset, board->reg_shift); } +static int pci_ni8431_config_rs485(struct uart_port *port, + struct serial_rs485 *rs485) +{ + u8 pcr, acr; + struct uart_8250_port *up; + + up = container_of(port, struct uart_8250_port, port); + acr = up->acr; + pcr = port->serial_in(port, NI16550_PCR_OFFSET); + pcr &= ~NI16550_PCR_WIRE_MODE_MASK; + + if (rs485->flags & SER_RS485_ENABLED) { + /* RS-485 */ + if ((rs485->flags & SER_RS485_RX_DURING_TX) && + (rs485->flags & SER_RS485_RTS_ON_SEND)) { + dev_dbg(port->dev, "Invalid 2-wire mode\n"); + return -EINVAL; + } + + if (rs485->flags & SER_RS485_RX_DURING_TX) { + /* Echo */ + dev_vdbg(port->dev, "2-wire DTR with echo\n"); + pcr |= NI16550_PCR_ECHO_RS485; + acr |= NI16550_ACR_DTR_MANUAL_DTR; + } else { + /* Auto or DTR */ + if (rs485->flags & SER_RS485_RTS_ON_SEND) { + /* Auto */ + dev_vdbg(port->dev, "2-wire Auto\n"); + pcr |= NI16550_PCR_AUTO_RS485; + acr |= NI16550_ACR_DTR_AUTO_DTR; + } else { + /* DTR-controlled */ + /* No Echo */ + dev_vdbg(port->dev, "2-wire DTR no echo\n"); + pcr |= NI16550_PCR_DTR_RS485; + acr |= NI16550_ACR_DTR_MANUAL_DTR; + } + } + } else { + /* RS-422 */ + dev_vdbg(port->dev, "4-wire\n"); + pcr |= NI16550_PCR_RS422; + acr |= NI16550_ACR_DTR_MANUAL_DTR; + } + + dev_dbg(port->dev, "write pcr: 0x%08x\n", pcr); + port->serial_out(port, NI16550_PCR_OFFSET, pcr); + + up->acr = acr; + port->serial_out(port, UART_SCR, UART_ACR); + port->serial_out(port, UART_ICR, up->acr); + + /* Update the cache. */ + port->rs485 = *rs485; + + return 0; +} + +static int pci_ni8431_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *uart, int idx) +{ + u8 pcr, acr; + struct pci_dev *dev = priv->dev; + void __iomem *addr; + unsigned int bar, offset = board->first_offset; + + if (idx >= board->num_ports) + return 1; + + bar = FL_GET_BASE(board->flags); + offset += idx * board->uart_offset; + + addr = pci_ioremap_bar(dev, bar); + if (!addr) + return -ENOMEM; + + /* enable the transceiver */ + writeb(readb(addr + NI16550_PCR_OFFSET) | NI16550_PCR_TXVR_ENABLE_BIT, + addr + NI16550_PCR_OFFSET); + + pcr = readb(addr + NI16550_PCR_OFFSET); + pcr &= ~NI16550_PCR_WIRE_MODE_MASK; + + /* set wire mode to default RS-422 */ + pcr |= NI16550_PCR_RS422; + acr = NI16550_ACR_DTR_MANUAL_DTR; + + /* write port configuration to register */ + writeb(pcr, addr + NI16550_PCR_OFFSET); + + /* access and write to UART acr register */ + writeb(UART_ACR, addr + UART_SCR); + writeb(acr, addr + UART_ICR); + + uart->port.rs485_config = &pci_ni8431_config_rs485; + + iounmap(addr); + + return setup_port(priv, uart, bar, offset, board->reg_shift); +} + static int pci_netmos_9900_setup(struct serial_private *priv, const struct pciserial_board *board, struct uart_8250_port *port, int idx) @@ -1326,7 +1452,36 @@ static int pci_default_setup(struct serial_private *priv, return setup_port(priv, port, bar, offset, board->reg_shift); } - +static void +pericom_do_set_divisor(struct uart_port *port, unsigned int baud, + unsigned int quot, unsigned int quot_frac) +{ + int scr; + int lcr; + int actual_baud; + int tolerance; + + for (scr = 5 ; scr <= 15 ; scr++) { + actual_baud = 921600 * 16 / scr; + tolerance = actual_baud / 50; + + if ((baud < actual_baud + tolerance) && + (baud > actual_baud - tolerance)) { + + lcr = serial_port_in(port, UART_LCR); + serial_port_out(port, UART_LCR, lcr | 0x80); + + serial_port_out(port, UART_DLL, 1); + serial_port_out(port, UART_DLM, 0); + serial_port_out(port, 2, 16 - scr); + serial_port_out(port, UART_LCR, lcr); + return; + } else if (baud > actual_baud) { + break; + } + } + serial8250_do_set_divisor(port, baud, quot, quot_frac); +} static int pci_pericom_setup(struct serial_private *priv, const struct pciserial_board *board, struct uart_8250_port *port, int idx) @@ -1339,6 +1494,30 @@ static int pci_pericom_setup(struct serial_private *priv, 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.set_divisor = pericom_do_set_divisor; + + return setup_port(priv, port, bar, offset, board->reg_shift); +} + +static int pci_pericom_setup_four_at_eight(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; + if (idx==3) offset = 0x38; @@ -1348,6 +1527,8 @@ static int pci_pericom_setup(struct serial_private *priv, if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr) return 1; + port->port.set_divisor = pericom_do_set_divisor; + return setup_port(priv, port, bar, offset, board->reg_shift); } @@ -1541,6 +1722,77 @@ 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) +{ + struct f815xxa_data *data = p->private_data; + unsigned long flags; + + spin_lock_irqsave(&data->lock, flags); + writeb(value, p->membase + offset); + readb(p->membase + UART_SCR); /* Dummy read for flush pcie tx queue */ + spin_unlock_irqrestore(&data->lock, flags); +} + +static int pci_fintek_f815xxa_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + struct pci_dev *pdev = priv->dev; + struct f815xxa_data *data; + + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->idx = idx; + spin_lock_init(&data->lock); + + port->port.private_data = data; + port->port.iotype = UPIO_MEM; + port->port.flags |= UPF_IOREMAP; + port->port.mapbase = pci_resource_start(pdev, 0) + 8 * idx; + port->port.serial_out = f815xxa_mem_serial_out; + + return 0; +} + +static int pci_fintek_f815xxa_init(struct pci_dev *dev) +{ + u32 max_port, i; + int config_base; + + if (!(pci_resource_flags(dev, 0) & IORESOURCE_MEM)) + return -ENODEV; + + switch (dev->device) { + case 0x1204: /* 4 ports */ + case 0x1208: /* 8 ports */ + max_port = dev->device & 0xff; + break; + case 0x1212: /* 12 ports */ + max_port = 12; + break; + default: + return -EINVAL; + } + + /* Set to mmio decode */ + pci_write_config_byte(dev, 0x209, 0x40); + + for (i = 0; i < max_port; ++i) { + /* UART0 configuration offset start from 0x2A0 */ + config_base = 0x2A0 + 0x08 * i; + + /* Select 128-byte FIFO and 8x FIFO threshold */ + pci_write_config_byte(dev, config_base + 0x01, 0x33); + + /* Enable UART I/O port */ + pci_write_config_byte(dev, config_base + 0, 0x01); + } + + return max_port; +} + static int skip_tx_en_setup(struct serial_private *priv, const struct pciserial_board *board, struct uart_8250_port *port, int idx) @@ -1637,6 +1889,46 @@ pci_wch_ch38x_setup(struct serial_private *priv, return pci_default_setup(priv, board, port, idx); } +static int +pci_sunix_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + int bar; + int offset; + + port->port.flags |= UPF_FIXED_TYPE; + port->port.type = PORT_SUNIX; + + if (idx < 4) { + bar = 0; + offset = idx * board->uart_offset; + } else { + bar = 1; + idx -= 4; + idx = div_s64_rem(idx, 4, &offset); + offset = idx * 64 + offset * board->uart_offset; + } + + return setup_port(priv, port, bar, offset, 0); +} + +static int +pci_moxa_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + unsigned int bar = FL_GET_BASE(board->flags); + int offset; + + if (board->num_ports == 4 && idx == 3) + offset = 7 * board->uart_offset; + else + offset = idx * board->uart_offset; + + return setup_port(priv, port, bar, offset, 0); +} + #define PCI_VENDOR_ID_SBSMODULARIO 0x124B #define PCI_SUBVENDOR_ID_SBSMODULARIO 0x124B #define PCI_DEVICE_ID_OCTPRO 0x0001 @@ -1731,7 +2023,28 @@ pci_wch_ch38x_setup(struct serial_private *priv, #define PCI_DEVICE_ID_ACCESIO_PCIE_COM_8SM 0x10E9 #define PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4SM 0x11D8 - +#define PCIE_DEVICE_ID_NI_PXIE8430_2328 0x74C2 +#define PCIE_DEVICE_ID_NI_PXIE8430_23216 0x74C1 +#define PCI_DEVICE_ID_NI_PXI8431_4852 0x7081 +#define PCI_DEVICE_ID_NI_PXI8431_4854 0x70DE +#define PCI_DEVICE_ID_NI_PXI8431_4858 0x70E3 +#define PCI_DEVICE_ID_NI_PXI8433_4852 0x70E9 +#define PCI_DEVICE_ID_NI_PXI8433_4854 0x70ED +#define PCIE_DEVICE_ID_NI_PXIE8431_4858 0x74C4 +#define PCIE_DEVICE_ID_NI_PXIE8431_48516 0x74C3 + +#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 /* Unknown vendors/cards - this should not be in linux/pci_ids.h */ #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584 @@ -1956,6 +2269,87 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { .setup = pci_ni8430_setup, .exit = pci_ni8430_exit, }, + { + .vendor = PCI_VENDOR_ID_NI, + .device = PCIE_DEVICE_ID_NI_PXIE8430_2328, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_ni8430_init, + .setup = pci_ni8430_setup, + .exit = pci_ni8430_exit, + }, + { + .vendor = PCI_VENDOR_ID_NI, + .device = PCIE_DEVICE_ID_NI_PXIE8430_23216, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_ni8430_init, + .setup = pci_ni8430_setup, + .exit = pci_ni8430_exit, + }, + { + .vendor = PCI_VENDOR_ID_NI, + .device = PCI_DEVICE_ID_NI_PXI8431_4852, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_ni8430_init, + .setup = pci_ni8431_setup, + .exit = pci_ni8430_exit, + }, + { + .vendor = PCI_VENDOR_ID_NI, + .device = PCI_DEVICE_ID_NI_PXI8431_4854, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_ni8430_init, + .setup = pci_ni8431_setup, + .exit = pci_ni8430_exit, + }, + { + .vendor = PCI_VENDOR_ID_NI, + .device = PCI_DEVICE_ID_NI_PXI8431_4858, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_ni8430_init, + .setup = pci_ni8431_setup, + .exit = pci_ni8430_exit, + }, + { + .vendor = PCI_VENDOR_ID_NI, + .device = PCI_DEVICE_ID_NI_PXI8433_4852, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_ni8430_init, + .setup = pci_ni8431_setup, + .exit = pci_ni8430_exit, + }, + { + .vendor = PCI_VENDOR_ID_NI, + .device = PCI_DEVICE_ID_NI_PXI8433_4854, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_ni8430_init, + .setup = pci_ni8431_setup, + .exit = pci_ni8430_exit, + }, + { + .vendor = PCI_VENDOR_ID_NI, + .device = PCIE_DEVICE_ID_NI_PXIE8431_4858, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_ni8430_init, + .setup = pci_ni8431_setup, + .exit = pci_ni8430_exit, + }, + { + .vendor = PCI_VENDOR_ID_NI, + .device = PCIE_DEVICE_ID_NI_PXIE8431_48516, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_ni8430_init, + .setup = pci_ni8431_setup, + .exit = pci_ni8430_exit, + }, /* Quatech */ { .vendor = PCI_VENDOR_ID_QUATECH, @@ -1995,7 +2389,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { .device = PCI_DEVICE_ID_PERICOM_PI7C9X7954, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup, + .setup = pci_pericom_setup_four_at_eight, }, /* * PLX @@ -2032,107 +2426,113 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SDB, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup, + .setup = pci_pericom_setup_four_at_eight, }, { .vendor = PCI_VENDOR_ID_ACCESIO, .device = PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4S, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup, + .setup = pci_pericom_setup_four_at_eight, }, { .vendor = PCI_VENDOR_ID_ACCESIO, .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4DB, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup, + .setup = pci_pericom_setup_four_at_eight, }, { .vendor = PCI_VENDOR_ID_ACCESIO, .device = PCI_DEVICE_ID_ACCESIO_MPCIE_COM232_4, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup, + .setup = pci_pericom_setup_four_at_eight, }, { .vendor = PCI_VENDOR_ID_ACCESIO, .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SMDB, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup, + .setup = pci_pericom_setup_four_at_eight, }, { .vendor = PCI_VENDOR_ID_ACCESIO, .device = PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4SM, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup, + .setup = pci_pericom_setup_four_at_eight, }, { .vendor = PCI_VENDOR_ID_ACCESIO, .device = PCI_DEVICE_ID_ACCESIO_MPCIE_ICM422_4, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup, + .setup = pci_pericom_setup_four_at_eight, }, { .vendor = PCI_VENDOR_ID_ACCESIO, .device = PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_4, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup, + .setup = pci_pericom_setup_four_at_eight, }, { .vendor = PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4S, .device = PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_4, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup, + .setup = pci_pericom_setup_four_at_eight, }, { .vendor = PCI_VENDOR_ID_ACCESIO, .device = PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_4, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup, + .setup = pci_pericom_setup_four_at_eight, }, { .vendor = PCI_VENDOR_ID_ACCESIO, .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM422_4, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup, + .setup = pci_pericom_setup_four_at_eight, }, { .vendor = PCI_VENDOR_ID_ACCESIO, .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM485_4, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup, + .setup = pci_pericom_setup_four_at_eight, }, { .vendor = PCI_VENDOR_ID_ACCESIO, .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup, + .setup = pci_pericom_setup_four_at_eight, }, { .vendor = PCI_VENDOR_ID_ACCESIO, .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SM, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup, + .setup = pci_pericom_setup_four_at_eight, }, { .vendor = PCI_VENDOR_ID_ACCESIO, .device = PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4SM, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup, + .setup = pci_pericom_setup_four_at_eight, }, - /* + { + .vendor = PCI_VENDOR_ID_ACCESIO, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_pericom_setup, + }, /* * SBS Technologies, Inc., PMC-OCTALPRO 232 */ { @@ -2228,21 +2628,14 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { .setup = pci_timedia_setup, }, /* - * SUNIX (Timedia) cards - * Do not "probe" for these cards as there is at least one combination - * card that should be handled by parport_pc that doesn't match the - * rule in pci_timedia_probe. - * It is part number is MIO5079A but its subdevice ID is 0x0102. - * There are some boards with part number SER5037AL that report - * subdevice ID 0x0002. + * Sunix PCI serial boards */ { .vendor = PCI_VENDOR_ID_SUNIX, .device = PCI_DEVICE_ID_SUNIX_1999, .subvendor = PCI_VENDOR_ID_SUNIX, .subdevice = PCI_ANY_ID, - .init = pci_timedia_init, - .setup = pci_timedia_setup, + .setup = pci_sunix_setup, }, /* * Xircom cards @@ -2502,6 +2895,40 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { .setup = pci_fintek_setup, .init = pci_fintek_init, }, + /* + * MOXA + */ + { + .vendor = PCI_VENDOR_ID_MOXA, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_moxa_setup, + }, + { + .vendor = 0x1c29, + .device = 0x1204, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_fintek_f815xxa_setup, + .init = pci_fintek_f815xxa_init, + }, + { + .vendor = 0x1c29, + .device = 0x1208, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_fintek_f815xxa_setup, + .init = pci_fintek_f815xxa_init, + }, + { + .vendor = 0x1c29, + .device = 0x1212, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_fintek_f815xxa_setup, + .init = pci_fintek_f815xxa_init, + }, /* * Default "match everything" terminator entry @@ -2679,6 +3106,13 @@ enum pci_board_num_t { pbn_ni8430_4, pbn_ni8430_8, pbn_ni8430_16, + pbn_ni8430_pxie_8, + pbn_ni8430_pxie_16, + pbn_ni8431_2, + pbn_ni8431_4, + pbn_ni8431_8, + pbn_ni8431_pxie_8, + pbn_ni8431_pxie_16, pbn_ADDIDATA_PCIe_1_3906250, pbn_ADDIDATA_PCIe_2_3906250, pbn_ADDIDATA_PCIe_4_3906250, @@ -2690,12 +3124,23 @@ enum pci_board_num_t { pbn_fintek_4, pbn_fintek_8, pbn_fintek_12, + pbn_fintek_F81504A, + pbn_fintek_F81508A, + pbn_fintek_F81512A, pbn_wch382_2, pbn_wch384_4, pbn_pericom_PI7C9X7951, pbn_pericom_PI7C9X7952, pbn_pericom_PI7C9X7954, pbn_pericom_PI7C9X7958, + pbn_sunix_pci_1s, + pbn_sunix_pci_2s, + pbn_sunix_pci_4s, + pbn_sunix_pci_8s, + pbn_sunix_pci_16s, + pbn_moxa8250_2p, + pbn_moxa8250_4p, + pbn_moxa8250_8p, }; /* @@ -3320,6 +3765,55 @@ static struct pciserial_board pci_boards[] = { .uart_offset = 0x10, .first_offset = 0x800, }, + [pbn_ni8430_pxie_16] = { + .flags = FL_BASE0, + .num_ports = 16, + .base_baud = 3125000, + .uart_offset = 0x10, + .first_offset = 0x800, + }, + [pbn_ni8430_pxie_8] = { + .flags = FL_BASE0, + .num_ports = 8, + .base_baud = 3125000, + .uart_offset = 0x10, + .first_offset = 0x800, + }, + [pbn_ni8431_8] = { + .flags = FL_BASE0, + .num_ports = 8, + .base_baud = 3686400, + .uart_offset = 0x10, + .first_offset = 0x800, + }, + [pbn_ni8431_4] = { + .flags = FL_BASE0, + .num_ports = 4, + .base_baud = 3686400, + .uart_offset = 0x10, + .first_offset = 0x800, + }, + [pbn_ni8431_2] = { + .flags = FL_BASE0, + .num_ports = 2, + .base_baud = 3686400, + .uart_offset = 0x10, + .first_offset = 0x800, + }, + [pbn_ni8431_pxie_16] = { + .flags = FL_BASE0, + .num_ports = 16, + .base_baud = 3125000, + .uart_offset = 0x10, + .first_offset = 0x800, + }, + [pbn_ni8431_pxie_8] = { + .flags = FL_BASE0, + .num_ports = 8, + .base_baud = 3125000, + .uart_offset = 0x10, + .first_offset = 0x800, + }, /* * ADDI-DATA GmbH PCI-Express communication cards <info@addi-data.com> */ @@ -3392,6 +3886,21 @@ static struct pciserial_board pci_boards[] = { .base_baud = 115200, .first_offset = 0x40, }, + [pbn_fintek_F81504A] = { + .num_ports = 4, + .uart_offset = 8, + .base_baud = 115200, + }, + [pbn_fintek_F81508A] = { + .num_ports = 8, + .uart_offset = 8, + .base_baud = 115200, + }, + [pbn_fintek_F81512A] = { + .num_ports = 12, + .uart_offset = 8, + .base_baud = 115200, + }, [pbn_wch382_2] = { .flags = FL_BASE0, .num_ports = 2, @@ -3433,6 +3942,49 @@ static struct pciserial_board pci_boards[] = { .base_baud = 921600, .uart_offset = 0x8, }, + [pbn_sunix_pci_1s] = { + .num_ports = 1, + .base_baud = 921600, + .uart_offset = 0x8, + }, + [pbn_sunix_pci_2s] = { + .num_ports = 2, + .base_baud = 921600, + .uart_offset = 0x8, + }, + [pbn_sunix_pci_4s] = { + .num_ports = 4, + .base_baud = 921600, + .uart_offset = 0x8, + }, + [pbn_sunix_pci_8s] = { + .num_ports = 8, + .base_baud = 921600, + .uart_offset = 0x8, + }, + [pbn_sunix_pci_16s] = { + .num_ports = 16, + .base_baud = 921600, + .uart_offset = 0x8, + }, + [pbn_moxa8250_2p] = { + .flags = FL_BASE1, + .num_ports = 2, + .base_baud = 921600, + .uart_offset = 0x200, + }, + [pbn_moxa8250_4p] = { + .flags = FL_BASE1, + .num_ports = 4, + .base_baud = 921600, + .uart_offset = 0x200, + }, + [pbn_moxa8250_8p] = { + .flags = FL_BASE1, + .num_ports = 8, + .base_baud = 921600, + .uart_offset = 0x200, + }, }; static const struct pci_device_id blacklist[] = { @@ -3446,20 +3998,6 @@ static const struct pci_device_id blacklist[] = { { PCI_DEVICE(0x4348, 0x5053), }, /* WCH CH353 1S1P */ { PCI_DEVICE(0x1c00, 0x3250), }, /* WCH CH382 2S1P */ - /* 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), }, @@ -3627,7 +4165,22 @@ pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board) memset(&uart, 0, sizeof(uart)); uart.port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ; uart.port.uartclk = board->base_baud * 16; - uart.port.irq = get_pci_irq(dev, board); + + if (pci_match_id(pci_use_msi, dev)) { + dev_dbg(&dev->dev, "Using MSI(-X) interrupts\n"); + pci_set_master(dev); + rc = pci_alloc_irq_vectors(dev, 1, 1, PCI_IRQ_ALL_TYPES); + } else { + dev_dbg(&dev->dev, "Using legacy interrupts\n"); + rc = pci_alloc_irq_vectors(dev, 1, 1, PCI_IRQ_LEGACY); + } + if (rc < 0) { + kfree(priv); + priv = ERR_PTR(rc); + goto err_deinit; + } + + uart.port.irq = pci_irq_vector(dev, 0); uart.port.dev = &dev->dev; for (i = 0; i < nr_ports; i++) { @@ -3798,8 +4351,7 @@ static void pciserial_remove_one(struct pci_dev *dev) #ifdef CONFIG_PM_SLEEP static int pciserial_suspend_one(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct serial_private *priv = pci_get_drvdata(pdev); + struct serial_private *priv = dev_get_drvdata(dev); if (priv) pciserial_suspend_ports(priv); @@ -4471,17 +5023,29 @@ static const struct pci_device_id serial_pci_tbl[] = { pbn_b0_bt_1_921600 }, /* - * SUNIX (TIMEDIA) + * Sunix PCI serial boards */ { PCI_VENDOR_ID_SUNIX, PCI_DEVICE_ID_SUNIX_1999, - PCI_VENDOR_ID_SUNIX, PCI_ANY_ID, - PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xffff00, - pbn_b0_bt_1_921600 }, - + PCI_VENDOR_ID_SUNIX, 0x0001, 0, 0, + pbn_sunix_pci_1s }, { PCI_VENDOR_ID_SUNIX, PCI_DEVICE_ID_SUNIX_1999, - PCI_VENDOR_ID_SUNIX, PCI_ANY_ID, - PCI_CLASS_COMMUNICATION_MULTISERIAL << 8, 0xffff00, - pbn_b0_bt_1_921600 }, + PCI_VENDOR_ID_SUNIX, 0x0002, 0, 0, + pbn_sunix_pci_2s }, + { PCI_VENDOR_ID_SUNIX, PCI_DEVICE_ID_SUNIX_1999, + PCI_VENDOR_ID_SUNIX, 0x0004, 0, 0, + pbn_sunix_pci_4s }, + { PCI_VENDOR_ID_SUNIX, PCI_DEVICE_ID_SUNIX_1999, + PCI_VENDOR_ID_SUNIX, 0x0084, 0, 0, + pbn_sunix_pci_4s }, + { PCI_VENDOR_ID_SUNIX, PCI_DEVICE_ID_SUNIX_1999, + PCI_VENDOR_ID_SUNIX, 0x0008, 0, 0, + pbn_sunix_pci_8s }, + { PCI_VENDOR_ID_SUNIX, PCI_DEVICE_ID_SUNIX_1999, + PCI_VENDOR_ID_SUNIX, 0x0088, 0, 0, + pbn_sunix_pci_8s }, + { PCI_VENDOR_ID_SUNIX, PCI_DEVICE_ID_SUNIX_1999, + PCI_VENDOR_ID_SUNIX, 0x0010, 0, 0, + pbn_sunix_pci_16s }, /* * AFAVLAB serial card, from Harald Welte <laforge@gnumonks.org> @@ -5003,6 +5567,73 @@ static const struct pci_device_id serial_pci_tbl[] = { { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8432_2324, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_ni8430_4 }, + { PCI_VENDOR_ID_NI, PCIE_DEVICE_ID_NI_PXIE8430_2328, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_ni8430_pxie_8 }, + { PCI_VENDOR_ID_NI, PCIE_DEVICE_ID_NI_PXIE8430_23216, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_ni8430_pxie_16 }, + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8431_4852, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_ni8431_2 }, + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8431_4854, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_ni8431_4 }, + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8431_4858, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_ni8431_8 }, + { PCI_VENDOR_ID_NI, PCIE_DEVICE_ID_NI_PXIE8431_4858, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_ni8431_pxie_8 }, + { PCI_VENDOR_ID_NI, PCIE_DEVICE_ID_NI_PXIE8431_48516, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_ni8431_pxie_16 }, + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8433_4852, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_ni8431_2 }, + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8433_4854, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_ni8431_4 }, + + /* + * MOXA + */ + { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP102E, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_moxa8250_2p }, + { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP102EL, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_moxa8250_2p }, + { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP104EL_A, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_moxa8250_4p }, + { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP114EL, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_moxa8250_4p }, + { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP116E_A_A, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_moxa8250_8p }, + { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP116E_A_B, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_moxa8250_8p }, + { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP118EL_A, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_moxa8250_8p }, + { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP118E_A_I, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_moxa8250_8p }, + { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP132EL, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_moxa8250_2p }, + { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP134EL_A, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_moxa8250_4p }, + { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP138E_A, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_moxa8250_8p }, + { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP168EL_A, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_moxa8250_8p }, /* * ADDI-DATA GmbH communication cards <info@addi-data.com> @@ -5231,6 +5862,9 @@ static const struct pci_device_id serial_pci_tbl[] = { { PCI_DEVICE(0x1c29, 0x1104), .driver_data = pbn_fintek_4 }, { PCI_DEVICE(0x1c29, 0x1108), .driver_data = pbn_fintek_8 }, { PCI_DEVICE(0x1c29, 0x1112), .driver_data = pbn_fintek_12 }, + { PCI_DEVICE(0x1c29, 0x1204), .driver_data = pbn_fintek_F81504A }, + { PCI_DEVICE(0x1c29, 0x1208), .driver_data = pbn_fintek_F81508A }, + { PCI_DEVICE(0x1c29, 0x1212), .driver_data = pbn_fintek_F81512A }, /* MKS Tenta SCOM-080x serial cards */ { PCI_DEVICE(0x1601, 0x0800), .driver_data = pbn_b0_4_1250000 }, diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c index 431e69a5a6a0..de90d681b64c 100644 --- a/drivers/tty/serial/8250/8250_pnp.c +++ b/drivers/tty/serial/8250/8250_pnp.c @@ -462,8 +462,8 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) return -ENODEV; dev_dbg(&dev->dev, - "Setup PNP port: port %lx, mem %pa, irq %d, type %d\n", - uart.port.iobase, &uart.port.mapbase, + "Setup PNP port: port %#lx, mem %#llx, irq %u, type %u\n", + uart.port.iobase, (unsigned long long)uart.port.mapbase, uart.port.irq, uart.port.iotype); if (flags & CIR_PORT) { @@ -498,10 +498,9 @@ static void serial_pnp_remove(struct pnp_dev *dev) serial8250_unregister_port(line - 1); } -#ifdef CONFIG_PM -static int serial_pnp_suspend(struct pnp_dev *dev, pm_message_t state) +static int __maybe_unused serial_pnp_suspend(struct device *dev) { - long line = (long)pnp_get_drvdata(dev); + long line = (long)dev_get_drvdata(dev); if (!line) return -ENODEV; @@ -509,26 +508,25 @@ static int serial_pnp_suspend(struct pnp_dev *dev, pm_message_t state) return 0; } -static int serial_pnp_resume(struct pnp_dev *dev) +static int __maybe_unused serial_pnp_resume(struct device *dev) { - long line = (long)pnp_get_drvdata(dev); + long line = (long)dev_get_drvdata(dev); if (!line) return -ENODEV; serial8250_resume_port(line - 1); return 0; } -#else -#define serial_pnp_suspend NULL -#define serial_pnp_resume NULL -#endif /* CONFIG_PM */ + +static SIMPLE_DEV_PM_OPS(serial_pnp_pm_ops, serial_pnp_suspend, serial_pnp_resume); static struct pnp_driver serial_pnp_driver = { .name = "serial", .probe = serial_pnp_probe, .remove = serial_pnp_remove, - .suspend = serial_pnp_suspend, - .resume = serial_pnp_resume, + .driver = { + .pm = &serial_pnp_pm_ops, + }, .id_table = pnp_dev_table, }; diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index d2f3310abe54..8407166610ce 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -40,13 +40,6 @@ #include "8250.h" -/* - * These are definitions for the Exar XR17V35X and XR17(C|D)15X - */ -#define UART_EXAR_INT0 0x80 -#define UART_EXAR_SLEEP 0x8b /* Sleep mode */ -#define UART_EXAR_DVID 0x8d /* Device identification */ - /* Nuvoton NPCM timeout register */ #define UART_NPCM_TOR 7 #define UART_NPCM_TOIE BIT(7) /* Timeout Interrupt Enable */ @@ -308,6 +301,14 @@ static const struct serial8250_config uart_config[] = { .rxtrig_bytes = {1, 4, 8, 14}, .flags = UART_CAP_FIFO, }, + [PORT_SUNIX] = { + .name = "Sunix", + .fifo_size = 128, + .tx_loadsz = 128, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, + .rxtrig_bytes = {1, 32, 64, 112}, + .flags = UART_CAP_FIFO | UART_CAP_SLEEP, + }, }; /* Uart divisor latch read */ @@ -709,19 +710,8 @@ EXPORT_SYMBOL_GPL(serial8250_rpm_put_tx); 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) { @@ -738,7 +728,7 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep) serial_out(p, UART_LCR, lcr); } } -out: + serial8250_rpm_put(p); } @@ -1012,27 +1002,6 @@ static void autoconfig_16550a(struct uart_8250_port *up) 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. */ @@ -1171,18 +1140,6 @@ static void autoconfig_16550a(struct uart_8250_port *up) 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. */ @@ -1502,11 +1459,8 @@ static void __stop_tx_rs485(struct uart_8250_port *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); + if (serial8250_clear_THRI(p)) serial8250_rpm_put_tx(p); - } } static inline void __stop_tx(struct uart_8250_port *p) @@ -1555,10 +1509,7 @@ static inline void __start_tx(struct uart_port *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 (serial8250_set_THRI(up)) { if (up->bugs & UART_BUG_TXEN) { unsigned char lsr; @@ -1662,6 +1613,8 @@ static void serial8250_disable_ms(struct uart_port *port) if (up->bugs & UART_BUG_NOMSR) return; + mctrl_gpio_disable_ms(up->gpios); + up->ier &= ~UART_IER_MSI; serial_port_out(port, UART_IER, up->ier); } @@ -1674,6 +1627,8 @@ static void serial8250_enable_ms(struct uart_port *port) if (up->bugs & UART_BUG_NOMSR) return; + mctrl_gpio_enable_ms(up->gpios); + up->ier |= UART_IER_MSI; serial8250_rpm_get(up); @@ -1869,13 +1824,13 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir) status = serial_port_in(port, UART_LSR); - if (status & (UART_LSR_DR | UART_LSR_BI) && - iir & UART_IIR_RDI) { + 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)) + if ((!up->dma || up->dma->tx_err) && (status & UART_LSR_THRE) && + (up->ier & UART_IER_THRI)) serial8250_tx_chars(up); uart_unlock_and_check_sysrq(port, flags); @@ -1944,22 +1899,17 @@ 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; + unsigned int val; 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; + val = serial8250_MSR_to_TIOCM(status); + if (up->gpios) + return mctrl_gpio_get(up->gpios, &val); + + return val; } EXPORT_SYMBOL_GPL(serial8250_do_get_mctrl); @@ -1973,18 +1923,9 @@ static unsigned int serial8250_get_mctrl(struct uart_port *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; + unsigned char mcr; - 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 = serial8250_TIOCM_to_MCR(mctrl); mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr; @@ -2200,8 +2141,6 @@ int serial8250_do_startup(struct uart_port *port) serial_port_in(port, UART_RX); serial_port_in(port, UART_IIR); serial_port_in(port, UART_MSR); - if ((port->type == PORT_XR17V35X) || (port->type == PORT_XR17D15X)) - serial_port_in(port, UART_EXAR_INT0); /* * At this point, there's no way the LSR could still be 0xff; @@ -2359,8 +2298,6 @@ dont_test_tx_en: serial_port_in(port, UART_RX); serial_port_in(port, UART_IIR); serial_port_in(port, UART_MSR); - if ((port->type == PORT_XR17V35X) || (port->type == PORT_XR17D15X)) - serial_port_in(port, UART_EXAR_INT0); up->lsr_saved_flags = 0; up->msr_saved_flags = 0; @@ -2469,23 +2406,6 @@ static void serial8250_shutdown(struct uart_port *port) 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; -} - /* Nuvoton NPCM UARTs have a custom divisor calculation */ static unsigned int npcm_get_divisor(struct uart_8250_port *up, unsigned int baud) @@ -2513,8 +2433,6 @@ static unsigned int serial8250_do_get_divisor(struct uart_port *port, 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 if (up->port.type == PORT_NPCM) quot = npcm_get_divisor(up, baud); else @@ -2601,13 +2519,6 @@ void serial8250_do_set_divisor(struct uart_port *port, unsigned int baud, 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) { - /* Preserve bits not related to baudrate; DLD[7:4]. */ - quot_frac |= serial_port_in(port, 0x2) & 0xf0; - serial_port_out(port, 0x2, quot_frac); - } } EXPORT_SYMBOL_GPL(serial8250_do_set_divisor); diff --git a/drivers/tty/serial/8250/8250_uniphier.c b/drivers/tty/serial/8250/8250_uniphier.c index 164ba133437a..e0b73a5402db 100644 --- a/drivers/tty/serial/8250/8250_uniphier.c +++ b/drivers/tty/serial/8250/8250_uniphier.c @@ -176,10 +176,8 @@ static int uniphier_uart_probe(struct platform_device *pdev) return -ENOMEM; irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(dev, "failed to get IRQ number\n"); + if (irq < 0) return irq; - } priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index 296115f6a4d8..7ef60f8b6e2c 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -8,6 +8,7 @@ config SERIAL_8250 tristate "8250/16550 and compatible serial support" depends on !S390 select SERIAL_CORE + select SERIAL_MCTRL_GPIO if GPIOLIB ---help--- This selects whether you want to include the driver for the standard serial ports. The standard answer is Y. People who might say N @@ -313,6 +314,9 @@ config SERIAL_8250_RSA If you don't have such card, or if unsure, say N. +config SERIAL_8250_DWLIB + bool + config SERIAL_8250_ACORN tristate "Acorn expansion card serial port support" depends on ARCH_ACORN && SERIAL_8250 @@ -353,6 +357,7 @@ config SERIAL_8250_FSL config SERIAL_8250_DW tristate "Support for Synopsys DesignWare 8250 quirks" depends on SERIAL_8250 + select SERIAL_8250_DWLIB help Selecting this option will enable handling of the extra features present in the Synopsys DesignWare APB UART. @@ -439,6 +444,7 @@ config SERIAL_8250_LPSS default SERIAL_8250 depends on SERIAL_8250 && PCI depends on X86 || COMPILE_TEST + select SERIAL_8250_DWLIB select DW_DMAC_CORE if SERIAL_8250_DMA select DW_DMAC_PCI if (SERIAL_8250_DMA && X86_INTEL_LPSS) select RATIONAL @@ -462,16 +468,6 @@ config SERIAL_8250_MID 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_8250_PXA tristate "PXA serial port support" depends on SERIAL_8250 diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile index 18751bc63a84..08c1d8117506 100644 --- a/drivers/tty/serial/8250/Makefile +++ b/drivers/tty/serial/8250/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_SERIAL_8250) += 8250.o 8250_base.o 8250-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o 8250_base-y := 8250_port.o 8250_base-$(CONFIG_SERIAL_8250_DMA) += 8250_dma.o +8250_base-$(CONFIG_SERIAL_8250_DWLIB) += 8250_dwlib.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 @@ -34,7 +35,6 @@ obj-$(CONFIG_SERIAL_8250_UNIPHIER) += 8250_uniphier.o obj-$(CONFIG_SERIAL_8250_INGENIC) += 8250_ingenic.o obj-$(CONFIG_SERIAL_8250_LPSS) += 8250_lpss.o obj-$(CONFIG_SERIAL_8250_MID) += 8250_mid.o -obj-$(CONFIG_SERIAL_8250_MOXA) += 8250_moxa.o obj-$(CONFIG_SERIAL_8250_PXA) += 8250_pxa.o obj-$(CONFIG_SERIAL_OF_PLATFORM) += 8250_of.o diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 0d31251e04cc..4789b5d62f63 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -197,23 +197,6 @@ config SERIAL_KGDB_NMI If unsure, say N. -config SERIAL_KS8695 - bool "Micrel KS8695 (Centaur) serial port support" - depends on ARCH_KS8695 - select SERIAL_CORE - help - This selects the Micrel Centaur KS8695 UART. Say Y here. - -config SERIAL_KS8695_CONSOLE - bool "Support for console on KS8695 (Centaur) serial port" - depends on SERIAL_KS8695=y - select SERIAL_CORE_CONSOLE - help - Say Y here if you wish to use a KS8695 (Centaur) UART as the - system console (the system console is the device which - receives all kernel messages and warnings and which allows - logins in single user mode). - config SERIAL_MESON tristate "Meson serial port support" depends on ARCH_MESON @@ -457,20 +440,6 @@ config SERIAL_21285_CONSOLE your boot loader (lilo or loadlin) about how to pass options to the kernel at boot time.) -config SERIAL_MPSC - bool "Marvell MPSC serial port support" - depends on MV64X60 - select SERIAL_CORE - help - Say Y here if you want to use the Marvell MPSC serial controller. - -config SERIAL_MPSC_CONSOLE - bool "Support for console on Marvell MPSC serial port" - depends on SERIAL_MPSC - select SERIAL_CORE_CONSOLE - help - Say Y here if you want to support a serial console on a Marvell MPSC. - config SERIAL_PXA bool "PXA serial port support (DEPRECATED)" depends on ARCH_PXA || ARCH_MMP @@ -511,10 +480,11 @@ config SERIAL_SA1100 bool "SA1100 serial port support" depends on ARCH_SA1100 select SERIAL_CORE + select SERIAL_MCTRL_GPIO if GPIOLIB help If you have a machine based on a SA1100/SA1110 StrongARM(R) CPU you can enable its onboard serial port by enabling this option. - Please read <file:Documentation/arm/SA1100/serial_UART> for further + Please read <file:Documentation/arm/sa1100/serial_uart.rst> for further info. config SERIAL_SA1100_CONSOLE @@ -752,7 +722,8 @@ config SERIAL_PNX8XXX_CONSOLE config SERIAL_HS_LPC32XX tristate "LPC32XX high speed serial port support" - depends on ARCH_LPC32XX && OF + depends on ARCH_LPC32XX || COMPILE_TEST + depends on OF select SERIAL_CORE help Support for the LPC32XX high speed serial ports (up to 900kbps). @@ -868,16 +839,6 @@ config SERIAL_CPM_CONSOLE your boot loader (lilo or loadlin) about how to pass options to the kernel at boot time.) -config SERIAL_SGI_L1_CONSOLE - bool "SGI Altix L1 serial console support" - depends on IA64_GENERIC || IA64_SGI_SN2 - select SERIAL_CORE - select SERIAL_CORE_CONSOLE - help - If you have an SGI Altix and you would like to use the system - controller serial port as your console (you want this!), - say Y. Otherwise, say N. - config SERIAL_PIC32 tristate "Microchip PIC32 serial support" depends on MACH_PIC32 @@ -995,23 +956,6 @@ config SERIAL_JSM To compile this driver as a module, choose M here: the module will be called jsm. -config SERIAL_SGI_IOC4 - tristate "SGI IOC4 controller serial support" - depends on (IA64_GENERIC || IA64_SGI_SN2) && SGI_IOC4 - select SERIAL_CORE - help - If you have an SGI Altix with an IOC4 based Base IO card - and wish to use the serial ports on this card, say Y. - Otherwise, say N. - -config SERIAL_SGI_IOC3 - tristate "SGI Altix IOC3 serial support" - depends on (IA64_GENERIC || IA64_SGI_SN2) && SGI_IOC3 - select SERIAL_CORE - help - If you have an SGI Altix with an IOC3 serial card, - say Y or M. Otherwise, say N. - config SERIAL_MSM tristate "MSM on-chip serial port support" depends on ARCH_QCOM @@ -1048,25 +992,6 @@ config SERIAL_VT8500_CONSOLE depends on SERIAL_VT8500=y select SERIAL_CORE_CONSOLE -config SERIAL_NETX - tristate "NetX serial port support" - depends on ARCH_NETX - select SERIAL_CORE - help - If you have a machine based on a Hilscher NetX SoC you - can enable its onboard serial port by enabling this option. - - To compile this driver as a module, choose M here: the - module will be called netx-serial. - -config SERIAL_NETX_CONSOLE - bool "Console on NetX serial port" - depends on SERIAL_NETX=y - select SERIAL_CORE_CONSOLE - help - If you have enabled the serial port on the Hilscher NetX SoC - you can make it the console by answering Y to this option. - config SERIAL_OMAP tristate "OMAP serial port support" depends on ARCH_OMAP2PLUS @@ -1465,6 +1390,22 @@ config SERIAL_FSL_LPUART_CONSOLE If you have enabled the lpuart serial port on the Freescale SoCs, you can make it the console by answering Y to this option. +config SERIAL_FSL_LINFLEXUART + tristate "Freescale linflexuart serial port support" + depends on PRINTK + select SERIAL_CORE + help + Support for the on-chip linflexuart on some Freescale SOCs. + +config SERIAL_FSL_LINFLEXUART_CONSOLE + bool "Console on Freescale linflexuart serial port" + depends on SERIAL_FSL_LINFLEXUART=y + select SERIAL_CORE_CONSOLE + select SERIAL_EARLYCON + help + If you have enabled the linflexuart serial port on the Freescale + SoCs, you can make it the console by answering Y to this option. + config SERIAL_CONEXANT_DIGICOLOR tristate "Conexant Digicolor CX92xxx USART serial port support" depends on OF diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index 79c3d513db7e..863f47056539 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile @@ -41,12 +41,10 @@ obj-$(CONFIG_SERIAL_HS_LPC32XX) += lpc32xx_hs.o obj-$(CONFIG_SERIAL_DZ) += dz.o obj-$(CONFIG_SERIAL_ZS) += zs.o obj-$(CONFIG_SERIAL_SH_SCI) += sh-sci.o -obj-$(CONFIG_SERIAL_SGI_L1_CONSOLE) += sn_console.o obj-$(CONFIG_SERIAL_CPM) += cpm_uart/ obj-$(CONFIG_SERIAL_IMX) += imx.o obj-$(CONFIG_SERIAL_MPC52xx) += mpc52xx_uart.o obj-$(CONFIG_SERIAL_ICOM) += icom.o -obj-$(CONFIG_SERIAL_MPSC) += mpsc.o obj-$(CONFIG_SERIAL_MESON) += meson_uart.o obj-$(CONFIG_SERIAL_SB1250_DUART) += sb1250-duart.o obj-$(CONFIG_SERIAL_SCCNXP) += sccnxp.o @@ -54,14 +52,10 @@ obj-$(CONFIG_SERIAL_SC16IS7XX_CORE) += sc16is7xx.o obj-$(CONFIG_SERIAL_JSM) += jsm/ obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o -obj-$(CONFIG_SERIAL_SGI_IOC4) += ioc4_serial.o -obj-$(CONFIG_SERIAL_SGI_IOC3) += ioc3_serial.o obj-$(CONFIG_SERIAL_ATMEL) += atmel_serial.o obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o obj-$(CONFIG_SERIAL_MSM) += msm_serial.o obj-$(CONFIG_SERIAL_QCOM_GENI) += qcom_geni_serial.o -obj-$(CONFIG_SERIAL_NETX) += netx-serial.o -obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o obj-$(CONFIG_SERIAL_ST_ASC) += st-asc.o @@ -83,6 +77,7 @@ obj-$(CONFIG_SERIAL_EFM32_UART) += efm32-uart.o obj-$(CONFIG_SERIAL_ARC) += arc_uart.o obj-$(CONFIG_SERIAL_RP2) += rp2.o obj-$(CONFIG_SERIAL_FSL_LPUART) += fsl_lpuart.o +obj-$(CONFIG_SERIAL_FSL_LINFLEXUART) += fsl_linflexuart.o obj-$(CONFIG_SERIAL_CONEXANT_DIGICOLOR) += digicolor-usart.o obj-$(CONFIG_SERIAL_MEN_Z135) += men_z135_uart.o obj-$(CONFIG_SERIAL_SPRD) += sprd_serial.o diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 89ade213a1a9..3a7d1a66f79c 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -1717,7 +1717,7 @@ static int pl011_allocate_irq(struct uart_amba_port *uap) { pl011_write(uap->im, uap, REG_IMSC); - return request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap); + return request_irq(uap->port.irq, pl011_int, IRQF_SHARED, "uart-pl011", uap); } /* @@ -2718,11 +2718,8 @@ static int sbsa_uart_probe(struct platform_device *pdev) return -ENOMEM; ret = platform_get_irq(pdev, 0); - if (ret < 0) { - if (ret != -EPROBE_DEFER) - dev_err(&pdev->dev, "cannot obtain irq\n"); + if (ret < 0) return ret; - } uap->port.irq = ret; #ifdef CONFIG_ACPI_SPCR_TABLE diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 0b4f36905321..a8dc8af83f39 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -294,50 +294,6 @@ static void atmel_tasklet_schedule(struct atmel_uart_port *atmel_port, tasklet_schedule(t); } -static unsigned int atmel_get_lines_status(struct uart_port *port) -{ - struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); - unsigned int status, ret = 0; - - status = atmel_uart_readl(port, ATMEL_US_CSR); - - mctrl_gpio_get(atmel_port->gpios, &ret); - - if (!IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(atmel_port->gpios, - UART_GPIO_CTS))) { - if (ret & TIOCM_CTS) - status &= ~ATMEL_US_CTS; - else - status |= ATMEL_US_CTS; - } - - if (!IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(atmel_port->gpios, - UART_GPIO_DSR))) { - if (ret & TIOCM_DSR) - status &= ~ATMEL_US_DSR; - else - status |= ATMEL_US_DSR; - } - - if (!IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(atmel_port->gpios, - UART_GPIO_RI))) { - if (ret & TIOCM_RI) - status &= ~ATMEL_US_RI; - else - status |= ATMEL_US_RI; - } - - if (!IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(atmel_port->gpios, - UART_GPIO_DCD))) { - if (ret & TIOCM_CD) - status &= ~ATMEL_US_DCD; - else - status |= ATMEL_US_DCD; - } - - return status; -} - /* Enable or disable the rs485 support */ static int atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf) @@ -1400,7 +1356,6 @@ atmel_handle_transmit(struct uart_port *port, unsigned int pending) atmel_port->hd_start_rx = false; atmel_start_rx(port); - return; } atmel_tasklet_schedule(atmel_port, &atmel_port->tasklet_tx); @@ -1454,7 +1409,7 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id) spin_lock(&atmel_port->lock_suspended); do { - status = atmel_get_lines_status(port); + status = atmel_uart_readl(port, ATMEL_US_CSR); mask = atmel_uart_readl(port, ATMEL_US_IMR); pending = status & mask; if (!pending) @@ -2003,7 +1958,7 @@ static int atmel_startup(struct uart_port *port) } /* Save current CSR for comparison in atmel_tasklet_func() */ - atmel_port->irq_status_prev = atmel_get_lines_status(port); + atmel_port->irq_status_prev = atmel_uart_readl(port, ATMEL_US_CSR); /* * Finally, enable the serial port @@ -2888,7 +2843,7 @@ static int atmel_serial_probe(struct platform_device *pdev) struct atmel_uart_port *atmel_port; struct device_node *np = pdev->dev.parent->of_node; void *data; - int ret = -ENODEV; + int ret; bool rs485_enabled; BUILD_BUG_ON(ATMEL_SERIAL_RINGSIZE & (ATMEL_SERIAL_RINGSIZE - 1)); diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_core.c b/drivers/tty/serial/cpm_uart/cpm_uart_core.c index b929c7ae3a27..de6d02f7abe2 100644 --- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/tty/serial/cpm_uart/cpm_uart_core.c @@ -407,7 +407,16 @@ static int cpm_uart_startup(struct uart_port *port) clrbits16(&pinfo->sccp->scc_sccm, UART_SCCM_RX); } cpm_uart_initbd(pinfo); - cpm_line_cr_cmd(pinfo, CPM_CR_INIT_TRX); + if (IS_SMC(pinfo)) { + out_be32(&pinfo->smcup->smc_rstate, 0); + out_be32(&pinfo->smcup->smc_tstate, 0); + out_be16(&pinfo->smcup->smc_rbptr, + in_be16(&pinfo->smcup->smc_rbase)); + out_be16(&pinfo->smcup->smc_tbptr, + in_be16(&pinfo->smcup->smc_tbase)); + } else { + cpm_line_cr_cmd(pinfo, CPM_CR_INIT_TRX); + } } /* Install interrupt handler. */ retval = request_irq(port->irq, cpm_uart_int, 0, "cpm_uart", port); @@ -567,8 +576,6 @@ static void cpm_uart_set_termios(struct uart_port *port, /* * Set up parity check flag */ -#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) - port->read_status_mask = (BD_SC_EMPTY | BD_SC_OV); if (termios->c_iflag & INPCK) port->read_status_mask |= BD_SC_FR | BD_SC_PR; @@ -861,16 +868,14 @@ static void cpm_uart_init_smc(struct uart_cpm_port *pinfo) (u8 __iomem *)pinfo->tx_bd_base - DPRAM_BASE); /* - * In case SMC1 is being relocated... + * In case SMC is being relocated... */ -#if defined (CONFIG_I2C_SPI_SMC1_UCODE_PATCH) out_be16(&up->smc_rbptr, in_be16(&pinfo->smcup->smc_rbase)); out_be16(&up->smc_tbptr, in_be16(&pinfo->smcup->smc_tbase)); out_be32(&up->smc_rstate, 0); out_be32(&up->smc_tstate, 0); out_be16(&up->smc_brkcr, 1); /* number of break chars */ out_be16(&up->smc_brkec, 0); -#endif /* Set up the uart parameters in the * parameter ram. @@ -884,8 +889,6 @@ static void cpm_uart_init_smc(struct uart_cpm_port *pinfo) out_be16(&up->smc_brkec, 0); out_be16(&up->smc_brkcr, 1); - cpm_line_cr_cmd(pinfo, CPM_CR_INIT_TRX); - /* Set UART mode, 8 bit, no parity, one stop. * Enable receive and transmit. */ diff --git a/drivers/tty/serial/digicolor-usart.c b/drivers/tty/serial/digicolor-usart.c index f460cca139e2..13ac36e2da4f 100644 --- a/drivers/tty/serial/digicolor-usart.c +++ b/drivers/tty/serial/digicolor-usart.c @@ -541,7 +541,11 @@ static int __init digicolor_uart_init(void) if (ret) return ret; - return platform_driver_register(&digicolor_uart_platform); + ret = platform_driver_register(&digicolor_uart_platform); + if (ret) + uart_unregister_driver(&digicolor_uart); + + return ret; } module_init(digicolor_uart_init); diff --git a/drivers/tty/serial/fsl_linflexuart.c b/drivers/tty/serial/fsl_linflexuart.c new file mode 100644 index 000000000000..68d74f2b5106 --- /dev/null +++ b/drivers/tty/serial/fsl_linflexuart.c @@ -0,0 +1,937 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Freescale linflexuart serial port driver + * + * Copyright 2012-2016 Freescale Semiconductor, Inc. + * Copyright 2017-2018 NXP + */ + +#if defined(CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE) && \ + defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + +#include <linux/console.h> +#include <linux/io.h> +#include <linux/irq.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/serial_core.h> +#include <linux/slab.h> +#include <linux/tty_flip.h> +#include <linux/delay.h> + +/* All registers are 32-bit width */ + +#define LINCR1 0x0000 /* LIN control register */ +#define LINIER 0x0004 /* LIN interrupt enable register */ +#define LINSR 0x0008 /* LIN status register */ +#define LINESR 0x000C /* LIN error status register */ +#define UARTCR 0x0010 /* UART mode control register */ +#define UARTSR 0x0014 /* UART mode status register */ +#define LINTCSR 0x0018 /* LIN timeout control status register */ +#define LINOCR 0x001C /* LIN output compare register */ +#define LINTOCR 0x0020 /* LIN timeout control register */ +#define LINFBRR 0x0024 /* LIN fractional baud rate register */ +#define LINIBRR 0x0028 /* LIN integer baud rate register */ +#define LINCFR 0x002C /* LIN checksum field register */ +#define LINCR2 0x0030 /* LIN control register 2 */ +#define BIDR 0x0034 /* Buffer identifier register */ +#define BDRL 0x0038 /* Buffer data register least significant */ +#define BDRM 0x003C /* Buffer data register most significant */ +#define IFER 0x0040 /* Identifier filter enable register */ +#define IFMI 0x0044 /* Identifier filter match index */ +#define IFMR 0x0048 /* Identifier filter mode register */ +#define GCR 0x004C /* Global control register */ +#define UARTPTO 0x0050 /* UART preset timeout register */ +#define UARTCTO 0x0054 /* UART current timeout register */ + +/* + * Register field definitions + */ + +#define LINFLEXD_LINCR1_INIT BIT(0) +#define LINFLEXD_LINCR1_MME BIT(4) +#define LINFLEXD_LINCR1_BF BIT(7) + +#define LINFLEXD_LINSR_LINS_INITMODE BIT(12) +#define LINFLEXD_LINSR_LINS_MASK (0xF << 12) + +#define LINFLEXD_LINIER_SZIE BIT(15) +#define LINFLEXD_LINIER_OCIE BIT(14) +#define LINFLEXD_LINIER_BEIE BIT(13) +#define LINFLEXD_LINIER_CEIE BIT(12) +#define LINFLEXD_LINIER_HEIE BIT(11) +#define LINFLEXD_LINIER_FEIE BIT(8) +#define LINFLEXD_LINIER_BOIE BIT(7) +#define LINFLEXD_LINIER_LSIE BIT(6) +#define LINFLEXD_LINIER_WUIE BIT(5) +#define LINFLEXD_LINIER_DBFIE BIT(4) +#define LINFLEXD_LINIER_DBEIETOIE BIT(3) +#define LINFLEXD_LINIER_DRIE BIT(2) +#define LINFLEXD_LINIER_DTIE BIT(1) +#define LINFLEXD_LINIER_HRIE BIT(0) + +#define LINFLEXD_UARTCR_OSR_MASK (0xF << 24) +#define LINFLEXD_UARTCR_OSR(uartcr) (((uartcr) \ + & LINFLEXD_UARTCR_OSR_MASK) >> 24) + +#define LINFLEXD_UARTCR_ROSE BIT(23) + +#define LINFLEXD_UARTCR_RFBM BIT(9) +#define LINFLEXD_UARTCR_TFBM BIT(8) +#define LINFLEXD_UARTCR_WL1 BIT(7) +#define LINFLEXD_UARTCR_PC1 BIT(6) + +#define LINFLEXD_UARTCR_RXEN BIT(5) +#define LINFLEXD_UARTCR_TXEN BIT(4) +#define LINFLEXD_UARTCR_PC0 BIT(3) + +#define LINFLEXD_UARTCR_PCE BIT(2) +#define LINFLEXD_UARTCR_WL0 BIT(1) +#define LINFLEXD_UARTCR_UART BIT(0) + +#define LINFLEXD_UARTSR_SZF BIT(15) +#define LINFLEXD_UARTSR_OCF BIT(14) +#define LINFLEXD_UARTSR_PE3 BIT(13) +#define LINFLEXD_UARTSR_PE2 BIT(12) +#define LINFLEXD_UARTSR_PE1 BIT(11) +#define LINFLEXD_UARTSR_PE0 BIT(10) +#define LINFLEXD_UARTSR_RMB BIT(9) +#define LINFLEXD_UARTSR_FEF BIT(8) +#define LINFLEXD_UARTSR_BOF BIT(7) +#define LINFLEXD_UARTSR_RPS BIT(6) +#define LINFLEXD_UARTSR_WUF BIT(5) +#define LINFLEXD_UARTSR_4 BIT(4) + +#define LINFLEXD_UARTSR_TO BIT(3) + +#define LINFLEXD_UARTSR_DRFRFE BIT(2) +#define LINFLEXD_UARTSR_DTFTFF BIT(1) +#define LINFLEXD_UARTSR_NF BIT(0) +#define LINFLEXD_UARTSR_PE (LINFLEXD_UARTSR_PE0 |\ + LINFLEXD_UARTSR_PE1 |\ + LINFLEXD_UARTSR_PE2 |\ + LINFLEXD_UARTSR_PE3) + +#define LINFLEX_LDIV_MULTIPLIER (16) + +#define DRIVER_NAME "fsl-linflexuart" +#define DEV_NAME "ttyLF" +#define UART_NR 4 + +#define EARLYCON_BUFFER_INITIAL_CAP 8 + +#define PREINIT_DELAY 2000 /* us */ + +static const struct of_device_id linflex_dt_ids[] = { + { + .compatible = "fsl,s32v234-linflexuart", + }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, linflex_dt_ids); + +#ifdef CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE +static struct uart_port *earlycon_port; +static bool linflex_earlycon_same_instance; +static DEFINE_SPINLOCK(init_lock); +static bool during_init; + +static struct { + char *content; + unsigned int len, cap; +} earlycon_buf; +#endif + +static void linflex_stop_tx(struct uart_port *port) +{ + unsigned long ier; + + ier = readl(port->membase + LINIER); + ier &= ~(LINFLEXD_LINIER_DTIE); + writel(ier, port->membase + LINIER); +} + +static void linflex_stop_rx(struct uart_port *port) +{ + unsigned long ier; + + ier = readl(port->membase + LINIER); + writel(ier & ~LINFLEXD_LINIER_DRIE, port->membase + LINIER); +} + +static inline void linflex_transmit_buffer(struct uart_port *sport) +{ + struct circ_buf *xmit = &sport->state->xmit; + unsigned char c; + unsigned long status; + + while (!uart_circ_empty(xmit)) { + c = xmit->buf[xmit->tail]; + writeb(c, sport->membase + BDRL); + + /* Waiting for data transmission completed. */ + while (((status = readl(sport->membase + UARTSR)) & + LINFLEXD_UARTSR_DTFTFF) != + LINFLEXD_UARTSR_DTFTFF) + ; + + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + sport->icount.tx++; + + writel(status | LINFLEXD_UARTSR_DTFTFF, + sport->membase + UARTSR); + } + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(sport); + + if (uart_circ_empty(xmit)) + linflex_stop_tx(sport); +} + +static void linflex_start_tx(struct uart_port *port) +{ + unsigned long ier; + + linflex_transmit_buffer(port); + ier = readl(port->membase + LINIER); + writel(ier | LINFLEXD_LINIER_DTIE, port->membase + LINIER); +} + +static irqreturn_t linflex_txint(int irq, void *dev_id) +{ + struct uart_port *sport = dev_id; + struct circ_buf *xmit = &sport->state->xmit; + unsigned long flags; + unsigned long status; + + spin_lock_irqsave(&sport->lock, flags); + + if (sport->x_char) { + writeb(sport->x_char, sport->membase + BDRL); + + /* waiting for data transmission completed */ + while (((status = readl(sport->membase + UARTSR)) & + LINFLEXD_UARTSR_DTFTFF) != LINFLEXD_UARTSR_DTFTFF) + ; + + writel(status | LINFLEXD_UARTSR_DTFTFF, + sport->membase + UARTSR); + + goto out; + } + + if (uart_circ_empty(xmit) || uart_tx_stopped(sport)) { + linflex_stop_tx(sport); + goto out; + } + + linflex_transmit_buffer(sport); + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(sport); + +out: + spin_unlock_irqrestore(&sport->lock, flags); + return IRQ_HANDLED; +} + +static irqreturn_t linflex_rxint(int irq, void *dev_id) +{ + struct uart_port *sport = dev_id; + unsigned int flg; + struct tty_port *port = &sport->state->port; + unsigned long flags, status; + unsigned char rx; + + spin_lock_irqsave(&sport->lock, flags); + + status = readl(sport->membase + UARTSR); + while (status & LINFLEXD_UARTSR_RMB) { + rx = readb(sport->membase + BDRM); + flg = TTY_NORMAL; + sport->icount.rx++; + + if (status & (LINFLEXD_UARTSR_BOF | LINFLEXD_UARTSR_SZF | + LINFLEXD_UARTSR_FEF | LINFLEXD_UARTSR_PE)) { + if (status & LINFLEXD_UARTSR_SZF) + status |= LINFLEXD_UARTSR_SZF; + if (status & LINFLEXD_UARTSR_BOF) + status |= LINFLEXD_UARTSR_BOF; + if (status & LINFLEXD_UARTSR_FEF) + status |= LINFLEXD_UARTSR_FEF; + if (status & LINFLEXD_UARTSR_PE) + status |= LINFLEXD_UARTSR_PE; + } + + writel(status | LINFLEXD_UARTSR_RMB | LINFLEXD_UARTSR_DRFRFE, + sport->membase + UARTSR); + status = readl(sport->membase + UARTSR); + + if (uart_handle_sysrq_char(sport, (unsigned char)rx)) + continue; + +#ifdef SUPPORT_SYSRQ + sport->sysrq = 0; +#endif + tty_insert_flip_char(port, rx, flg); + } + + spin_unlock_irqrestore(&sport->lock, flags); + + tty_flip_buffer_push(port); + + return IRQ_HANDLED; +} + +static irqreturn_t linflex_int(int irq, void *dev_id) +{ + struct uart_port *sport = dev_id; + unsigned long status; + + status = readl(sport->membase + UARTSR); + + if (status & LINFLEXD_UARTSR_DRFRFE) + linflex_rxint(irq, dev_id); + if (status & LINFLEXD_UARTSR_DTFTFF) + linflex_txint(irq, dev_id); + + return IRQ_HANDLED; +} + +/* return TIOCSER_TEMT when transmitter is not busy */ +static unsigned int linflex_tx_empty(struct uart_port *port) +{ + unsigned long status; + + status = readl(port->membase + UARTSR) & LINFLEXD_UARTSR_DTFTFF; + + return status ? TIOCSER_TEMT : 0; +} + +static unsigned int linflex_get_mctrl(struct uart_port *port) +{ + return 0; +} + +static void linflex_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ +} + +static void linflex_break_ctl(struct uart_port *port, int break_state) +{ +} + +static void linflex_setup_watermark(struct uart_port *sport) +{ + unsigned long cr, ier, cr1; + + /* Disable transmission/reception */ + ier = readl(sport->membase + LINIER); + ier &= ~(LINFLEXD_LINIER_DRIE | LINFLEXD_LINIER_DTIE); + writel(ier, sport->membase + LINIER); + + cr = readl(sport->membase + UARTCR); + cr &= ~(LINFLEXD_UARTCR_RXEN | LINFLEXD_UARTCR_TXEN); + writel(cr, sport->membase + UARTCR); + + /* Enter initialization mode by setting INIT bit */ + + /* set the Linflex in master mode and activate by-pass filter */ + cr1 = LINFLEXD_LINCR1_BF | LINFLEXD_LINCR1_MME + | LINFLEXD_LINCR1_INIT; + writel(cr1, sport->membase + LINCR1); + + /* wait for init mode entry */ + while ((readl(sport->membase + LINSR) + & LINFLEXD_LINSR_LINS_MASK) + != LINFLEXD_LINSR_LINS_INITMODE) + ; + + /* + * UART = 0x1; - Linflex working in UART mode + * TXEN = 0x1; - Enable transmission of data now + * RXEn = 0x1; - Receiver enabled + * WL0 = 0x1; - 8 bit data + * PCE = 0x0; - No parity + */ + + /* set UART bit to allow writing other bits */ + writel(LINFLEXD_UARTCR_UART, sport->membase + UARTCR); + + cr = (LINFLEXD_UARTCR_RXEN | LINFLEXD_UARTCR_TXEN | + LINFLEXD_UARTCR_WL0 | LINFLEXD_UARTCR_UART); + + writel(cr, sport->membase + UARTCR); + + cr1 &= ~(LINFLEXD_LINCR1_INIT); + + writel(cr1, sport->membase + LINCR1); + + ier = readl(sport->membase + LINIER); + ier |= LINFLEXD_LINIER_DRIE; + ier |= LINFLEXD_LINIER_DTIE; + + writel(ier, sport->membase + LINIER); +} + +static int linflex_startup(struct uart_port *port) +{ + int ret = 0; + unsigned long flags; + + spin_lock_irqsave(&port->lock, flags); + + linflex_setup_watermark(port); + + spin_unlock_irqrestore(&port->lock, flags); + + ret = devm_request_irq(port->dev, port->irq, linflex_int, 0, + DRIVER_NAME, port); + + return ret; +} + +static void linflex_shutdown(struct uart_port *port) +{ + unsigned long ier; + unsigned long flags; + + spin_lock_irqsave(&port->lock, flags); + + /* disable interrupts */ + ier = readl(port->membase + LINIER); + ier &= ~(LINFLEXD_LINIER_DRIE | LINFLEXD_LINIER_DTIE); + writel(ier, port->membase + LINIER); + + spin_unlock_irqrestore(&port->lock, flags); + + devm_free_irq(port->dev, port->irq, port); +} + +static void +linflex_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) +{ + unsigned long flags; + unsigned long cr, old_cr, cr1; + unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8; + + cr = readl(port->membase + UARTCR); + old_cr = cr; + + /* Enter initialization mode by setting INIT bit */ + cr1 = readl(port->membase + LINCR1); + cr1 |= LINFLEXD_LINCR1_INIT; + writel(cr1, port->membase + LINCR1); + + /* wait for init mode entry */ + while ((readl(port->membase + LINSR) + & LINFLEXD_LINSR_LINS_MASK) + != LINFLEXD_LINSR_LINS_INITMODE) + ; + + /* + * only support CS8 and CS7, and for CS7 must enable PE. + * supported mode: + * - (7,e/o,1) + * - (8,n,1) + * - (8,e/o,1) + */ + /* enter the UART into configuration mode */ + + while ((termios->c_cflag & CSIZE) != CS8 && + (termios->c_cflag & CSIZE) != CS7) { + termios->c_cflag &= ~CSIZE; + termios->c_cflag |= old_csize; + old_csize = CS8; + } + + if ((termios->c_cflag & CSIZE) == CS7) { + /* Word length: WL1WL0:00 */ + cr = old_cr & ~LINFLEXD_UARTCR_WL1 & ~LINFLEXD_UARTCR_WL0; + } + + if ((termios->c_cflag & CSIZE) == CS8) { + /* Word length: WL1WL0:01 */ + cr = (old_cr | LINFLEXD_UARTCR_WL0) & ~LINFLEXD_UARTCR_WL1; + } + + if (termios->c_cflag & CMSPAR) { + if ((termios->c_cflag & CSIZE) != CS8) { + termios->c_cflag &= ~CSIZE; + termios->c_cflag |= CS8; + } + /* has a space/sticky bit */ + cr |= LINFLEXD_UARTCR_WL0; + } + + if (termios->c_cflag & CSTOPB) + termios->c_cflag &= ~CSTOPB; + + /* parity must be enabled when CS7 to match 8-bits format */ + if ((termios->c_cflag & CSIZE) == CS7) + termios->c_cflag |= PARENB; + + if ((termios->c_cflag & PARENB)) { + cr |= LINFLEXD_UARTCR_PCE; + if (termios->c_cflag & PARODD) + cr = (cr | LINFLEXD_UARTCR_PC0) & + (~LINFLEXD_UARTCR_PC1); + else + cr = cr & (~LINFLEXD_UARTCR_PC1 & + ~LINFLEXD_UARTCR_PC0); + } else { + cr &= ~LINFLEXD_UARTCR_PCE; + } + + spin_lock_irqsave(&port->lock, flags); + + port->read_status_mask = 0; + + if (termios->c_iflag & INPCK) + port->read_status_mask |= (LINFLEXD_UARTSR_FEF | + LINFLEXD_UARTSR_PE0 | + LINFLEXD_UARTSR_PE1 | + LINFLEXD_UARTSR_PE2 | + LINFLEXD_UARTSR_PE3); + if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK)) + port->read_status_mask |= LINFLEXD_UARTSR_FEF; + + /* characters to ignore */ + port->ignore_status_mask = 0; + if (termios->c_iflag & IGNPAR) + port->ignore_status_mask |= LINFLEXD_UARTSR_PE; + if (termios->c_iflag & IGNBRK) { + port->ignore_status_mask |= LINFLEXD_UARTSR_PE; + /* + * if we're ignoring parity and break indicators, + * ignore overruns too (for real raw support). + */ + if (termios->c_iflag & IGNPAR) + port->ignore_status_mask |= LINFLEXD_UARTSR_BOF; + } + + writel(cr, port->membase + UARTCR); + + cr1 &= ~(LINFLEXD_LINCR1_INIT); + + writel(cr1, port->membase + LINCR1); + + spin_unlock_irqrestore(&port->lock, flags); +} + +static const char *linflex_type(struct uart_port *port) +{ + return "FSL_LINFLEX"; +} + +static void linflex_release_port(struct uart_port *port) +{ + /* nothing to do */ +} + +static int linflex_request_port(struct uart_port *port) +{ + return 0; +} + +/* configure/auto-configure the port */ +static void linflex_config_port(struct uart_port *port, int flags) +{ + if (flags & UART_CONFIG_TYPE) + port->type = PORT_LINFLEXUART; +} + +static const struct uart_ops linflex_pops = { + .tx_empty = linflex_tx_empty, + .set_mctrl = linflex_set_mctrl, + .get_mctrl = linflex_get_mctrl, + .stop_tx = linflex_stop_tx, + .start_tx = linflex_start_tx, + .stop_rx = linflex_stop_rx, + .break_ctl = linflex_break_ctl, + .startup = linflex_startup, + .shutdown = linflex_shutdown, + .set_termios = linflex_set_termios, + .type = linflex_type, + .request_port = linflex_request_port, + .release_port = linflex_release_port, + .config_port = linflex_config_port, +}; + +static struct uart_port *linflex_ports[UART_NR]; + +#ifdef CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE +static void linflex_console_putchar(struct uart_port *port, int ch) +{ + unsigned long cr; + + cr = readl(port->membase + UARTCR); + + writeb(ch, port->membase + BDRL); + + if (!(cr & LINFLEXD_UARTCR_TFBM)) + while ((readl(port->membase + UARTSR) & + LINFLEXD_UARTSR_DTFTFF) + != LINFLEXD_UARTSR_DTFTFF) + ; + else + while (readl(port->membase + UARTSR) & + LINFLEXD_UARTSR_DTFTFF) + ; + + if (!(cr & LINFLEXD_UARTCR_TFBM)) { + writel((readl(port->membase + UARTSR) | + LINFLEXD_UARTSR_DTFTFF), + port->membase + UARTSR); + } +} + +static void linflex_earlycon_putchar(struct uart_port *port, int ch) +{ + unsigned long flags; + char *ret; + + if (!linflex_earlycon_same_instance) { + linflex_console_putchar(port, ch); + return; + } + + spin_lock_irqsave(&init_lock, flags); + if (!during_init) + goto outside_init; + + if (earlycon_buf.len >= 1 << CONFIG_LOG_BUF_SHIFT) + goto init_release; + + if (!earlycon_buf.cap) { + earlycon_buf.content = kmalloc(EARLYCON_BUFFER_INITIAL_CAP, + GFP_ATOMIC); + earlycon_buf.cap = earlycon_buf.content ? + EARLYCON_BUFFER_INITIAL_CAP : 0; + } else if (earlycon_buf.len == earlycon_buf.cap) { + ret = krealloc(earlycon_buf.content, earlycon_buf.cap << 1, + GFP_ATOMIC); + if (ret) { + earlycon_buf.content = ret; + earlycon_buf.cap <<= 1; + } + } + + if (earlycon_buf.len < earlycon_buf.cap) + earlycon_buf.content[earlycon_buf.len++] = ch; + + goto init_release; + +outside_init: + linflex_console_putchar(port, ch); +init_release: + spin_unlock_irqrestore(&init_lock, flags); +} + +static void linflex_string_write(struct uart_port *sport, const char *s, + unsigned int count) +{ + unsigned long cr, ier = 0; + + ier = readl(sport->membase + LINIER); + linflex_stop_tx(sport); + + cr = readl(sport->membase + UARTCR); + cr |= (LINFLEXD_UARTCR_TXEN); + writel(cr, sport->membase + UARTCR); + + uart_console_write(sport, s, count, linflex_console_putchar); + + writel(ier, sport->membase + LINIER); +} + +static void +linflex_console_write(struct console *co, const char *s, unsigned int count) +{ + struct uart_port *sport = linflex_ports[co->index]; + unsigned long flags; + int locked = 1; + + if (sport->sysrq) + locked = 0; + else if (oops_in_progress) + locked = spin_trylock_irqsave(&sport->lock, flags); + else + spin_lock_irqsave(&sport->lock, flags); + + linflex_string_write(sport, s, count); + + if (locked) + spin_unlock_irqrestore(&sport->lock, flags); +} + +/* + * if the port was already initialised (eg, by a boot loader), + * try to determine the current setup. + */ +static void __init +linflex_console_get_options(struct uart_port *sport, int *parity, int *bits) +{ + unsigned long cr; + + cr = readl(sport->membase + UARTCR); + cr &= LINFLEXD_UARTCR_RXEN | LINFLEXD_UARTCR_TXEN; + + if (!cr) + return; + + /* ok, the port was enabled */ + + *parity = 'n'; + if (cr & LINFLEXD_UARTCR_PCE) { + if (cr & LINFLEXD_UARTCR_PC0) + *parity = 'o'; + else + *parity = 'e'; + } + + if ((cr & LINFLEXD_UARTCR_WL0) && ((cr & LINFLEXD_UARTCR_WL1) == 0)) { + if (cr & LINFLEXD_UARTCR_PCE) + *bits = 9; + else + *bits = 8; + } +} + +static int __init linflex_console_setup(struct console *co, char *options) +{ + struct uart_port *sport; + int baud = 115200; + int bits = 8; + int parity = 'n'; + int flow = 'n'; + int ret; + int i; + unsigned long flags; + /* + * check whether an invalid uart number has been specified, and + * if so, search for the first available port that does have + * console support. + */ + if (co->index == -1 || co->index >= ARRAY_SIZE(linflex_ports)) + co->index = 0; + + sport = linflex_ports[co->index]; + if (!sport) + return -ENODEV; + + if (options) + uart_parse_options(options, &baud, &parity, &bits, &flow); + else + linflex_console_get_options(sport, &parity, &bits); + + if (earlycon_port && sport->mapbase == earlycon_port->mapbase) { + linflex_earlycon_same_instance = true; + + spin_lock_irqsave(&init_lock, flags); + during_init = true; + spin_unlock_irqrestore(&init_lock, flags); + + /* Workaround for character loss or output of many invalid + * characters, when INIT mode is entered shortly after a + * character has just been printed. + */ + udelay(PREINIT_DELAY); + } + + linflex_setup_watermark(sport); + + ret = uart_set_options(sport, co, baud, parity, bits, flow); + + if (!linflex_earlycon_same_instance) + goto done; + + spin_lock_irqsave(&init_lock, flags); + + /* Emptying buffer */ + if (earlycon_buf.len) { + for (i = 0; i < earlycon_buf.len; i++) + linflex_console_putchar(earlycon_port, + earlycon_buf.content[i]); + + kfree(earlycon_buf.content); + earlycon_buf.len = 0; + } + + during_init = false; + spin_unlock_irqrestore(&init_lock, flags); + +done: + return ret; +} + +static struct uart_driver linflex_reg; +static struct console linflex_console = { + .name = DEV_NAME, + .write = linflex_console_write, + .device = uart_console_device, + .setup = linflex_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, + .data = &linflex_reg, +}; + +static void linflex_earlycon_write(struct console *con, const char *s, + unsigned int n) +{ + struct earlycon_device *dev = con->data; + + uart_console_write(&dev->port, s, n, linflex_earlycon_putchar); +} + +static int __init linflex_early_console_setup(struct earlycon_device *device, + const char *options) +{ + if (!device->port.membase) + return -ENODEV; + + device->con->write = linflex_earlycon_write; + earlycon_port = &device->port; + + return 0; +} + +OF_EARLYCON_DECLARE(linflex, "fsl,s32v234-linflexuart", + linflex_early_console_setup); + +#define LINFLEX_CONSOLE (&linflex_console) +#else +#define LINFLEX_CONSOLE NULL +#endif + +static struct uart_driver linflex_reg = { + .owner = THIS_MODULE, + .driver_name = DRIVER_NAME, + .dev_name = DEV_NAME, + .nr = ARRAY_SIZE(linflex_ports), + .cons = LINFLEX_CONSOLE, +}; + +static int linflex_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct uart_port *sport; + struct resource *res; + int ret; + + sport = devm_kzalloc(&pdev->dev, sizeof(*sport), GFP_KERNEL); + if (!sport) + return -ENOMEM; + + ret = of_alias_get_id(np, "serial"); + if (ret < 0) { + dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret); + return ret; + } + if (ret >= UART_NR) { + dev_err(&pdev->dev, "driver limited to %d serial ports\n", + UART_NR); + return -ENOMEM; + } + + sport->line = ret; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + + sport->mapbase = res->start; + sport->membase = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(sport->membase)) + return PTR_ERR(sport->membase); + + sport->dev = &pdev->dev; + sport->type = PORT_LINFLEXUART; + sport->iotype = UPIO_MEM; + sport->irq = platform_get_irq(pdev, 0); + sport->ops = &linflex_pops; + sport->flags = UPF_BOOT_AUTOCONF; + + linflex_ports[sport->line] = sport; + + platform_set_drvdata(pdev, sport); + + ret = uart_add_one_port(&linflex_reg, sport); + if (ret) + return ret; + + return 0; +} + +static int linflex_remove(struct platform_device *pdev) +{ + struct uart_port *sport = platform_get_drvdata(pdev); + + uart_remove_one_port(&linflex_reg, sport); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int linflex_suspend(struct device *dev) +{ + struct uart_port *sport = dev_get_drvdata(dev); + + uart_suspend_port(&linflex_reg, sport); + + return 0; +} + +static int linflex_resume(struct device *dev) +{ + struct uart_port *sport = dev_get_drvdata(dev); + + uart_resume_port(&linflex_reg, sport); + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(linflex_pm_ops, linflex_suspend, linflex_resume); + +static struct platform_driver linflex_driver = { + .probe = linflex_probe, + .remove = linflex_remove, + .driver = { + .name = DRIVER_NAME, + .of_match_table = linflex_dt_ids, + .pm = &linflex_pm_ops, + }, +}; + +static int __init linflex_serial_init(void) +{ + int ret; + + ret = uart_register_driver(&linflex_reg); + if (ret) + return ret; + + ret = platform_driver_register(&linflex_driver); + if (ret) + uart_unregister_driver(&linflex_reg); + + return ret; +} + +static void __exit linflex_serial_exit(void) +{ + platform_driver_unregister(&linflex_driver); + uart_unregister_driver(&linflex_reg); +} + +module_init(linflex_serial_init); +module_exit(linflex_serial_exit); + +MODULE_DESCRIPTION("Freescale linflex serial port driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index ea1c85e3b432..3e17bb8a0b16 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -214,6 +214,7 @@ #define UARTFIFO_TXSIZE_OFF 4 #define UARTFIFO_RXFE 0x00000008 #define UARTFIFO_RXSIZE_OFF 0 +#define UARTFIFO_DEPTH(x) (0x1 << ((x) ? ((x) + 1) : 0)) #define UARTWATER_COUNT_MASK 0xff #define UARTWATER_TXCNT_OFF 8 @@ -234,9 +235,18 @@ static DEFINE_IDA(fsl_lpuart_ida); +enum lpuart_type { + VF610_LPUART, + LS1021A_LPUART, + IMX7ULP_LPUART, + IMX8QXP_LPUART, +}; + struct lpuart_port { struct uart_port port; - struct clk *clk; + enum lpuart_type devtype; + struct clk *ipg_clk; + struct clk *baud_clk; unsigned int txfifo_size; unsigned int rxfifo_size; @@ -261,19 +271,29 @@ struct lpuart_port { }; struct lpuart_soc_data { - char iotype; - u8 reg_off; + enum lpuart_type devtype; + char iotype; + u8 reg_off; }; static const struct lpuart_soc_data vf_data = { + .devtype = VF610_LPUART, .iotype = UPIO_MEM, }; static const struct lpuart_soc_data ls_data = { + .devtype = LS1021A_LPUART, .iotype = UPIO_MEM32BE, }; -static struct lpuart_soc_data imx_data = { +static struct lpuart_soc_data imx7ulp_data = { + .devtype = IMX7ULP_LPUART, + .iotype = UPIO_MEM32, + .reg_off = IMX_REG_OFF, +}; + +static struct lpuart_soc_data imx8qxp_data = { + .devtype = IMX8QXP_LPUART, .iotype = UPIO_MEM32, .reg_off = IMX_REG_OFF, }; @@ -281,7 +301,8 @@ static struct lpuart_soc_data imx_data = { static const struct of_device_id lpuart_dt_ids[] = { { .compatible = "fsl,vf610-lpuart", .data = &vf_data, }, { .compatible = "fsl,ls1021a-lpuart", .data = &ls_data, }, - { .compatible = "fsl,imx7ulp-lpuart", .data = &imx_data, }, + { .compatible = "fsl,imx7ulp-lpuart", .data = &imx7ulp_data, }, + { .compatible = "fsl,imx8qxp-lpuart", .data = &imx8qxp_data, }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, lpuart_dt_ids); @@ -289,6 +310,11 @@ MODULE_DEVICE_TABLE(of, lpuart_dt_ids); /* Forward declare this for the dma callbacks*/ static void lpuart_dma_tx_complete(void *arg); +static inline bool is_imx8qxp_lpuart(struct lpuart_port *sport) +{ + return sport->devtype == IMX8QXP_LPUART; +} + static inline u32 lpuart32_read(struct uart_port *port, u32 off) { switch (port->iotype) { @@ -314,6 +340,39 @@ static inline void lpuart32_write(struct uart_port *port, u32 val, } } +static int __lpuart_enable_clks(struct lpuart_port *sport, bool is_en) +{ + int ret = 0; + + if (is_en) { + ret = clk_prepare_enable(sport->ipg_clk); + if (ret) + return ret; + + ret = clk_prepare_enable(sport->baud_clk); + if (ret) { + clk_disable_unprepare(sport->ipg_clk); + return ret; + } + } else { + clk_disable_unprepare(sport->baud_clk); + clk_disable_unprepare(sport->ipg_clk); + } + + return 0; +} + +static unsigned int lpuart_get_baud_clk_rate(struct lpuart_port *sport) +{ + if (is_imx8qxp_lpuart(sport)) + return clk_get_rate(sport->baud_clk); + + return clk_get_rate(sport->ipg_clk); +} + +#define lpuart_enable_clks(x) __lpuart_enable_clks(x, true) +#define lpuart_disable_clks(x) __lpuart_enable_clks(x, false) + static void lpuart_stop_tx(struct uart_port *port) { unsigned char temp; @@ -393,6 +452,11 @@ static void lpuart_dma_tx(struct lpuart_port *sport) dma_async_issue_pending(sport->dma_tx_chan); } +static bool lpuart_stopped_or_empty(struct uart_port *port) +{ + return uart_circ_empty(&port->state->xmit) || uart_tx_stopped(port); +} + static void lpuart_dma_tx_complete(void *arg) { struct lpuart_port *sport = arg; @@ -420,7 +484,7 @@ static void lpuart_dma_tx_complete(void *arg) spin_lock_irqsave(&sport->port.lock, flags); - if (!uart_circ_empty(xmit) && !uart_tx_stopped(&sport->port)) + if (!lpuart_stopped_or_empty(&sport->port)) lpuart_dma_tx(sport); spin_unlock_irqrestore(&sport->port.lock, flags); @@ -459,9 +523,16 @@ static int lpuart_dma_tx_request(struct uart_port *port) return 0; } +static bool lpuart_is_32(struct lpuart_port *sport) +{ + return sport->port.iotype == UPIO_MEM32 || + sport->port.iotype == UPIO_MEM32BE; +} + static void lpuart_flush_buffer(struct uart_port *port) { struct lpuart_port *sport = container_of(port, struct lpuart_port, port); + u32 val; if (sport->lpuart_dma_tx_use) { if (sport->dma_tx_in_progress) { @@ -471,6 +542,30 @@ static void lpuart_flush_buffer(struct uart_port *port) } dmaengine_terminate_all(sport->dma_tx_chan); } + + if (lpuart_is_32(sport)) { + val = lpuart32_read(&sport->port, UARTFIFO); + val |= UARTFIFO_TXFLUSH | UARTFIFO_RXFLUSH; + lpuart32_write(&sport->port, val, UARTFIFO); + } else { + val = readb(sport->port.membase + UARTPFIFO); + val |= UARTCFIFO_TXFLUSH | UARTCFIFO_RXFLUSH; + writeb(val, sport->port.membase + UARTCFIFO); + } +} + +static void lpuart_wait_bit_set(struct uart_port *port, unsigned int offset, + u8 bit) +{ + while (!(readb(port->membase + offset) & bit)) + cpu_relax(); +} + +static void lpuart32_wait_bit_set(struct uart_port *port, unsigned int offset, + u32 bit) +{ + while (!(lpuart32_read(port, offset) & bit)) + cpu_relax(); } #if defined(CONFIG_CONSOLE_POLL) @@ -516,9 +611,7 @@ static int lpuart_poll_init(struct uart_port *port) static void lpuart_poll_put_char(struct uart_port *port, unsigned char c) { /* drain */ - while (!(readb(port->membase + UARTSR1) & UARTSR1_TDRE)) - barrier(); - + lpuart_wait_bit_set(port, UARTSR1, UARTSR1_TDRE); writeb(c, port->membase + UARTDR); } @@ -541,26 +634,26 @@ static int lpuart32_poll_init(struct uart_port *port) spin_lock_irqsave(&sport->port.lock, flags); /* Disable Rx & Tx */ - writel(0, sport->port.membase + UARTCTRL); + lpuart32_write(&sport->port, UARTCTRL, 0); - temp = readl(sport->port.membase + UARTFIFO); + temp = lpuart32_read(&sport->port, UARTFIFO); /* Enable Rx and Tx FIFO */ - writel(temp | UARTFIFO_RXFE | UARTFIFO_TXFE, - sport->port.membase + UARTFIFO); + lpuart32_write(&sport->port, UARTFIFO, + temp | UARTFIFO_RXFE | UARTFIFO_TXFE); /* flush Tx and Rx FIFO */ - writel(UARTFIFO_TXFLUSH | UARTFIFO_RXFLUSH, - sport->port.membase + UARTFIFO); + lpuart32_write(&sport->port, UARTFIFO, + UARTFIFO_TXFLUSH | UARTFIFO_RXFLUSH); /* explicitly clear RDRF */ - if (readl(sport->port.membase + UARTSTAT) & UARTSTAT_RDRF) { - readl(sport->port.membase + UARTDATA); - writel(UARTFIFO_RXUF, sport->port.membase + UARTFIFO); + if (lpuart32_read(&sport->port, UARTSTAT) & UARTSTAT_RDRF) { + lpuart32_read(&sport->port, UARTDATA); + lpuart32_write(&sport->port, UARTFIFO, UARTFIFO_RXUF); } /* Enable Rx and Tx */ - writel(UARTCTRL_RE | UARTCTRL_TE, sport->port.membase + UARTCTRL); + lpuart32_write(&sport->port, UARTCTRL, UARTCTRL_RE | UARTCTRL_TE); spin_unlock_irqrestore(&sport->port.lock, flags); return 0; @@ -568,18 +661,16 @@ static int lpuart32_poll_init(struct uart_port *port) static void lpuart32_poll_put_char(struct uart_port *port, unsigned char c) { - while (!(readl(port->membase + UARTSTAT) & UARTSTAT_TDRE)) - barrier(); - - writel(c, port->membase + UARTDATA); + lpuart32_wait_bit_set(port, UARTSTAT, UARTSTAT_TDRE); + lpuart32_write(port, UARTDATA, c); } static int lpuart32_poll_get_char(struct uart_port *port) { - if (!(readl(port->membase + UARTSTAT) & UARTSTAT_RDRF)) + if (!(lpuart32_read(port, UARTSTAT) & UARTSTAT_RDRF)) return NO_POLL_CHAR; - return readl(port->membase + UARTDATA); + return lpuart32_read(port, UARTDATA); } #endif @@ -587,6 +678,18 @@ static inline void lpuart_transmit_buffer(struct lpuart_port *sport) { struct circ_buf *xmit = &sport->port.state->xmit; + if (sport->port.x_char) { + writeb(sport->port.x_char, sport->port.membase + UARTDR); + sport->port.icount.tx++; + sport->port.x_char = 0; + return; + } + + if (lpuart_stopped_or_empty(&sport->port)) { + lpuart_stop_tx(&sport->port); + return; + } + while (!uart_circ_empty(xmit) && (readb(sport->port.membase + UARTTCFIFO) < sport->txfifo_size)) { writeb(xmit->buf[xmit->tail], sport->port.membase + UARTDR); @@ -606,6 +709,18 @@ static inline void lpuart32_transmit_buffer(struct lpuart_port *sport) struct circ_buf *xmit = &sport->port.state->xmit; unsigned long txcnt; + if (sport->port.x_char) { + lpuart32_write(&sport->port, sport->port.x_char, UARTDATA); + sport->port.icount.tx++; + sport->port.x_char = 0; + return; + } + + if (lpuart_stopped_or_empty(&sport->port)) { + lpuart32_stop_tx(&sport->port); + return; + } + txcnt = lpuart32_read(&sport->port, UARTWATER); txcnt = txcnt >> UARTWATER_TXCNT_OFF; txcnt &= UARTWATER_COUNT_MASK; @@ -629,14 +744,13 @@ static void lpuart_start_tx(struct uart_port *port) { struct lpuart_port *sport = container_of(port, struct lpuart_port, port); - struct circ_buf *xmit = &sport->port.state->xmit; unsigned char temp; temp = readb(port->membase + UARTCR2); writeb(temp | UARTCR2_TIE, port->membase + UARTCR2); if (sport->lpuart_dma_tx_use) { - if (!uart_circ_empty(xmit) && !uart_tx_stopped(port)) + if (!lpuart_stopped_or_empty(port)) lpuart_dma_tx(sport); } else { if (readb(port->membase + UARTSR1) & UARTSR1_TDRE) @@ -647,11 +761,10 @@ static void lpuart_start_tx(struct uart_port *port) static void lpuart32_start_tx(struct uart_port *port) { struct lpuart_port *sport = container_of(port, struct lpuart_port, port); - struct circ_buf *xmit = &sport->port.state->xmit; unsigned long temp; if (sport->lpuart_dma_tx_use) { - if (!uart_circ_empty(xmit) && !uart_tx_stopped(port)) + if (!lpuart_stopped_or_empty(port)) lpuart_dma_tx(sport); } else { temp = lpuart32_read(port, UARTCTRL); @@ -695,52 +808,18 @@ static unsigned int lpuart32_tx_empty(struct uart_port *port) return 0; } -static bool lpuart_is_32(struct lpuart_port *sport) -{ - return sport->port.iotype == UPIO_MEM32 || - sport->port.iotype == UPIO_MEM32BE; -} - -static irqreturn_t lpuart_txint(int irq, void *dev_id) +static void lpuart_txint(struct lpuart_port *sport) { - struct lpuart_port *sport = dev_id; - struct circ_buf *xmit = &sport->port.state->xmit; unsigned long flags; spin_lock_irqsave(&sport->port.lock, flags); - if (sport->port.x_char) { - if (lpuart_is_32(sport)) - lpuart32_write(&sport->port, sport->port.x_char, UARTDATA); - else - writeb(sport->port.x_char, sport->port.membase + UARTDR); - goto out; - } - - if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) { - if (lpuart_is_32(sport)) - lpuart32_stop_tx(&sport->port); - else - lpuart_stop_tx(&sport->port); - goto out; - } - - if (lpuart_is_32(sport)) - lpuart32_transmit_buffer(sport); - else - lpuart_transmit_buffer(sport); - - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(&sport->port); - -out: + lpuart_transmit_buffer(sport); spin_unlock_irqrestore(&sport->port.lock, flags); - return IRQ_HANDLED; } -static irqreturn_t lpuart_rxint(int irq, void *dev_id) +static void lpuart_rxint(struct lpuart_port *sport) { - struct lpuart_port *sport = dev_id; - unsigned int flg, ignored = 0; + unsigned int flg, ignored = 0, overrun = 0; struct tty_port *port = &sport->port.state->port; unsigned long flags; unsigned char rx, sr; @@ -767,7 +846,7 @@ static irqreturn_t lpuart_rxint(int irq, void *dev_id) sport->port.icount.frame++; if (sr & UARTSR1_OR) - sport->port.icount.overrun++; + overrun++; if (sr & sport->port.ignore_status_mask) { if (++ignored > 100) @@ -794,15 +873,33 @@ static irqreturn_t lpuart_rxint(int irq, void *dev_id) } out: + if (overrun) { + sport->port.icount.overrun += overrun; + + /* + * Overruns cause FIFO pointers to become missaligned. + * Flushing the receive FIFO reinitializes the pointers. + */ + writeb(UARTCFIFO_RXFLUSH, sport->port.membase + UARTCFIFO); + writeb(UARTSFIFO_RXOF, sport->port.membase + UARTSFIFO); + } + spin_unlock_irqrestore(&sport->port.lock, flags); tty_flip_buffer_push(port); - return IRQ_HANDLED; } -static irqreturn_t lpuart32_rxint(int irq, void *dev_id) +static void lpuart32_txint(struct lpuart_port *sport) +{ + unsigned long flags; + + spin_lock_irqsave(&sport->port.lock, flags); + lpuart32_transmit_buffer(sport); + spin_unlock_irqrestore(&sport->port.lock, flags); +} + +static void lpuart32_rxint(struct lpuart_port *sport) { - struct lpuart_port *sport = dev_id; unsigned int flg, ignored = 0; struct tty_port *port = &sport->port.state->port; unsigned long flags; @@ -861,7 +958,6 @@ out: spin_unlock_irqrestore(&sport->port.lock, flags); tty_flip_buffer_push(port); - return IRQ_HANDLED; } static irqreturn_t lpuart_int(int irq, void *dev_id) @@ -871,11 +967,11 @@ static irqreturn_t lpuart_int(int irq, void *dev_id) sts = readb(sport->port.membase + UARTSR1); - if (sts & UARTSR1_RDRF) - lpuart_rxint(irq, dev_id); + if (sts & UARTSR1_RDRF && !sport->lpuart_dma_rx_use) + lpuart_rxint(sport); - if (sts & UARTSR1_TDRE) - lpuart_txint(irq, dev_id); + if (sts & UARTSR1_TDRE && !sport->lpuart_dma_tx_use) + lpuart_txint(sport); return IRQ_HANDLED; } @@ -890,10 +986,10 @@ static irqreturn_t lpuart32_int(int irq, void *dev_id) rxcount = rxcount >> UARTWATER_RXCNT_OFF; if ((sts & UARTSTAT_RDRF || rxcount > 0) && !sport->lpuart_dma_rx_use) - lpuart32_rxint(irq, dev_id); + lpuart32_rxint(sport); if ((sts & UARTSTAT_TDRE) && !sport->lpuart_dma_tx_use) - lpuart_txint(irq, dev_id); + lpuart32_txint(sport); lpuart32_write(&sport->port, sts, UARTSTAT); return IRQ_HANDLED; @@ -924,6 +1020,13 @@ static void lpuart_copy_rx_to_tty(struct lpuart_port *sport) unsigned char sr = readb(sport->port.membase + UARTSR1); if (sr & (UARTSR1_PE | UARTSR1_FE)) { + unsigned char cr2; + + /* Disable receiver during this operation... */ + cr2 = readb(sport->port.membase + UARTCR2); + cr2 &= ~UARTCR2_RE; + writeb(cr2, sport->port.membase + UARTCR2); + /* Read DR to clear the error flags */ readb(sport->port.membase + UARTDR); @@ -931,6 +1034,25 @@ static void lpuart_copy_rx_to_tty(struct lpuart_port *sport) sport->port.icount.parity++; else if (sr & UARTSR1_FE) sport->port.icount.frame++; + /* + * At this point parity/framing error is + * cleared However, since the DMA already read + * the data register and we had to read it + * again after reading the status register to + * properly clear the flags, the FIFO actually + * underflowed... This requires a clearing of + * the FIFO... + */ + if (readb(sport->port.membase + UARTSFIFO) & + UARTSFIFO_RXUF) { + writeb(UARTSFIFO_RXUF, + sport->port.membase + UARTSFIFO); + writeb(UARTCFIFO_RXFLUSH, + sport->port.membase + UARTCFIFO); + } + + cr2 |= UARTCR2_RE; + writeb(cr2, sport->port.membase + UARTCR2); } } @@ -1039,14 +1161,11 @@ static inline int lpuart_start_rx_dma(struct lpuart_port *sport) if (sport->rx_dma_rng_buf_len < 16) sport->rx_dma_rng_buf_len = 16; - ring->buf = kmalloc(sport->rx_dma_rng_buf_len, GFP_ATOMIC); - if (!ring->buf) { - dev_err(sport->port.dev, "Ring buf alloc failed\n"); + ring->buf = kzalloc(sport->rx_dma_rng_buf_len, GFP_ATOMIC); + if (!ring->buf) return -ENOMEM; - } sg_init_one(&sport->rx_sgl, ring->buf, sport->rx_dma_rng_buf_len); - sg_set_buf(&sport->rx_sgl, ring->buf, sport->rx_dma_rng_buf_len); nent = dma_map_sg(sport->port.dev, &sport->rx_sgl, 1, DMA_FROM_DEVICE); if (!nent) { @@ -1284,6 +1403,17 @@ static void lpuart_setup_watermark(struct lpuart_port *sport) writeb(cr2_saved, sport->port.membase + UARTCR2); } +static void lpuart_setup_watermark_enable(struct lpuart_port *sport) +{ + unsigned char cr2; + + lpuart_setup_watermark(sport); + + cr2 = readb(sport->port.membase + UARTCR2); + cr2 |= UARTCR2_RIE | UARTCR2_RE | UARTCR2_TE; + writeb(cr2, sport->port.membase + UARTCR2); +} + static void lpuart32_setup_watermark(struct lpuart_port *sport) { unsigned long val, ctrl; @@ -1309,109 +1439,90 @@ static void lpuart32_setup_watermark(struct lpuart_port *sport) lpuart32_write(&sport->port, ctrl_saved, UARTCTRL); } -static void rx_dma_timer_init(struct lpuart_port *sport) -{ - timer_setup(&sport->lpuart_timer, lpuart_timer_func, 0); - sport->lpuart_timer.expires = jiffies + sport->dma_rx_timeout; - add_timer(&sport->lpuart_timer); -} - -static int lpuart_startup(struct uart_port *port) +static void lpuart32_setup_watermark_enable(struct lpuart_port *sport) { - struct lpuart_port *sport = container_of(port, struct lpuart_port, port); - unsigned long flags; - unsigned char temp; - - /* determine FIFO size and enable FIFO mode */ - temp = readb(sport->port.membase + UARTPFIFO); - - sport->txfifo_size = 0x1 << (((temp >> UARTPFIFO_TXSIZE_OFF) & - UARTPFIFO_FIFOSIZE_MASK) + 1); + u32 temp; - sport->port.fifosize = sport->txfifo_size; + lpuart32_setup_watermark(sport); - sport->rxfifo_size = 0x1 << (((temp >> UARTPFIFO_RXSIZE_OFF) & - UARTPFIFO_FIFOSIZE_MASK) + 1); + temp = lpuart32_read(&sport->port, UARTCTRL); + temp |= UARTCTRL_RE | UARTCTRL_TE | UARTCTRL_ILIE; + lpuart32_write(&sport->port, temp, UARTCTRL); +} - spin_lock_irqsave(&sport->port.lock, flags); +static void rx_dma_timer_init(struct lpuart_port *sport) +{ + timer_setup(&sport->lpuart_timer, lpuart_timer_func, 0); + sport->lpuart_timer.expires = jiffies + sport->dma_rx_timeout; + add_timer(&sport->lpuart_timer); +} - lpuart_setup_watermark(sport); +static void lpuart_tx_dma_startup(struct lpuart_port *sport) +{ + u32 uartbaud; - temp = readb(sport->port.membase + UARTCR2); - temp |= (UARTCR2_RIE | UARTCR2_TIE | UARTCR2_RE | UARTCR2_TE); - writeb(temp, sport->port.membase + UARTCR2); + if (sport->dma_tx_chan && !lpuart_dma_tx_request(&sport->port)) { + init_waitqueue_head(&sport->dma_wait); + sport->lpuart_dma_tx_use = true; + if (lpuart_is_32(sport)) { + uartbaud = lpuart32_read(&sport->port, UARTBAUD); + lpuart32_write(&sport->port, + uartbaud | UARTBAUD_TDMAE, UARTBAUD); + } else { + writeb(readb(sport->port.membase + UARTCR5) | + UARTCR5_TDMAS, sport->port.membase + UARTCR5); + } + } else { + sport->lpuart_dma_tx_use = false; + } +} +static void lpuart_rx_dma_startup(struct lpuart_port *sport) +{ if (sport->dma_rx_chan && !lpuart_start_rx_dma(sport)) { /* set Rx DMA timeout */ sport->dma_rx_timeout = msecs_to_jiffies(DMA_RX_TIMEOUT); if (!sport->dma_rx_timeout) - sport->dma_rx_timeout = 1; + sport->dma_rx_timeout = 1; sport->lpuart_dma_rx_use = true; rx_dma_timer_init(sport); } else { sport->lpuart_dma_rx_use = false; } - - if (sport->dma_tx_chan && !lpuart_dma_tx_request(port)) { - init_waitqueue_head(&sport->dma_wait); - sport->lpuart_dma_tx_use = true; - temp = readb(port->membase + UARTCR5); - writeb(temp | UARTCR5_TDMAS, port->membase + UARTCR5); - } else { - sport->lpuart_dma_tx_use = false; - } - - spin_unlock_irqrestore(&sport->port.lock, flags); - - return 0; } -static int lpuart32_startup(struct uart_port *port) +static int lpuart_startup(struct uart_port *port) { struct lpuart_port *sport = container_of(port, struct lpuart_port, port); unsigned long flags; - unsigned long temp; - - /* determine FIFO size */ - temp = lpuart32_read(&sport->port, UARTFIFO); + unsigned char temp; - sport->txfifo_size = 0x1 << (((temp >> UARTFIFO_TXSIZE_OFF) & - UARTFIFO_FIFOSIZE_MASK) - 1); + /* determine FIFO size and enable FIFO mode */ + temp = readb(sport->port.membase + UARTPFIFO); + sport->txfifo_size = UARTFIFO_DEPTH((temp >> UARTPFIFO_TXSIZE_OFF) & + UARTPFIFO_FIFOSIZE_MASK); sport->port.fifosize = sport->txfifo_size; - sport->rxfifo_size = 0x1 << (((temp >> UARTFIFO_RXSIZE_OFF) & - UARTFIFO_FIFOSIZE_MASK) - 1); + sport->rxfifo_size = UARTFIFO_DEPTH((temp >> UARTPFIFO_RXSIZE_OFF) & + UARTPFIFO_FIFOSIZE_MASK); spin_lock_irqsave(&sport->port.lock, flags); - lpuart32_setup_watermark(sport); + lpuart_setup_watermark_enable(sport); - temp = lpuart32_read(&sport->port, UARTCTRL); - temp |= UARTCTRL_RE | UARTCTRL_TE | UARTCTRL_ILIE; - lpuart32_write(&sport->port, temp, UARTCTRL); + lpuart_rx_dma_startup(sport); + lpuart_tx_dma_startup(sport); - if (sport->dma_rx_chan && !lpuart_start_rx_dma(sport)) { - /* set Rx DMA timeout */ - sport->dma_rx_timeout = msecs_to_jiffies(DMA_RX_TIMEOUT); - if (!sport->dma_rx_timeout) - sport->dma_rx_timeout = 1; + spin_unlock_irqrestore(&sport->port.lock, flags); - sport->lpuart_dma_rx_use = true; - rx_dma_timer_init(sport); - } else { - sport->lpuart_dma_rx_use = false; - } + return 0; +} - if (sport->dma_tx_chan && !lpuart_dma_tx_request(port)) { - init_waitqueue_head(&sport->dma_wait); - sport->lpuart_dma_tx_use = true; - temp = lpuart32_read(&sport->port, UARTBAUD); - lpuart32_write(&sport->port, temp | UARTBAUD_TDMAE, UARTBAUD); - } else { - sport->lpuart_dma_tx_use = false; - } +static void lpuart32_configure(struct lpuart_port *sport) +{ + unsigned long temp; if (sport->lpuart_dma_rx_use) { /* RXWATER must be 0 */ @@ -1425,27 +1536,40 @@ static int lpuart32_startup(struct uart_port *port) if (!sport->lpuart_dma_tx_use) temp |= UARTCTRL_TIE; lpuart32_write(&sport->port, temp, UARTCTRL); - - spin_unlock_irqrestore(&sport->port.lock, flags); - return 0; } -static void lpuart_shutdown(struct uart_port *port) +static int lpuart32_startup(struct uart_port *port) { struct lpuart_port *sport = container_of(port, struct lpuart_port, port); - unsigned char temp; unsigned long flags; + unsigned long temp; - spin_lock_irqsave(&port->lock, flags); + /* determine FIFO size */ + temp = lpuart32_read(&sport->port, UARTFIFO); - /* disable Rx/Tx and interrupts */ - temp = readb(port->membase + UARTCR2); - temp &= ~(UARTCR2_TE | UARTCR2_RE | - UARTCR2_TIE | UARTCR2_TCIE | UARTCR2_RIE); - writeb(temp, port->membase + UARTCR2); + sport->txfifo_size = UARTFIFO_DEPTH((temp >> UARTFIFO_TXSIZE_OFF) & + UARTFIFO_FIFOSIZE_MASK); + sport->port.fifosize = sport->txfifo_size; + + sport->rxfifo_size = UARTFIFO_DEPTH((temp >> UARTFIFO_RXSIZE_OFF) & + UARTFIFO_FIFOSIZE_MASK); + + spin_lock_irqsave(&sport->port.lock, flags); + + lpuart32_setup_watermark_enable(sport); - spin_unlock_irqrestore(&port->lock, flags); + lpuart_rx_dma_startup(sport); + lpuart_tx_dma_startup(sport); + + lpuart32_configure(sport); + + spin_unlock_irqrestore(&sport->port.lock, flags); + return 0; +} + +static void lpuart_dma_shutdown(struct lpuart_port *sport) +{ if (sport->lpuart_dma_rx_use) { del_timer_sync(&sport->lpuart_timer); lpuart_dma_rx_free(&sport->port); @@ -1457,11 +1581,28 @@ static void lpuart_shutdown(struct uart_port *port) sport->dma_tx_in_progress = false; dmaengine_terminate_all(sport->dma_tx_chan); } - - lpuart_stop_tx(port); } } +static void lpuart_shutdown(struct uart_port *port) +{ + struct lpuart_port *sport = container_of(port, struct lpuart_port, port); + unsigned char temp; + unsigned long flags; + + spin_lock_irqsave(&port->lock, flags); + + /* disable Rx/Tx and interrupts */ + temp = readb(port->membase + UARTCR2); + temp &= ~(UARTCR2_TE | UARTCR2_RE | + UARTCR2_TIE | UARTCR2_TCIE | UARTCR2_RIE); + writeb(temp, port->membase + UARTCR2); + + spin_unlock_irqrestore(&port->lock, flags); + + lpuart_dma_shutdown(sport); +} + static void lpuart32_shutdown(struct uart_port *port) { struct lpuart_port *sport = @@ -1479,20 +1620,7 @@ static void lpuart32_shutdown(struct uart_port *port) spin_unlock_irqrestore(&port->lock, flags); - if (sport->lpuart_dma_rx_use) { - del_timer_sync(&sport->lpuart_timer); - lpuart_dma_rx_free(&sport->port); - } - - if (sport->lpuart_dma_tx_use) { - if (wait_event_interruptible(sport->dma_wait, - !sport->dma_tx_in_progress)) { - sport->dma_tx_in_progress = false; - dmaengine_terminate_all(sport->dma_tx_chan); - } - - lpuart32_stop_tx(port); - } + lpuart_dma_shutdown(sport); } static void @@ -1546,21 +1674,18 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios, if (sport->port.rs485.flags & SER_RS485_ENABLED) termios->c_cflag &= ~CRTSCTS; - if (termios->c_cflag & CRTSCTS) { - modem |= (UARTMODEM_RXRTSE | UARTMODEM_TXCTSE); - } else { - termios->c_cflag &= ~CRTSCTS; + if (termios->c_cflag & CRTSCTS) + modem |= UARTMODEM_RXRTSE | UARTMODEM_TXCTSE; + else modem &= ~(UARTMODEM_RXRTSE | UARTMODEM_TXCTSE); - } - if (termios->c_cflag & CSTOPB) - termios->c_cflag &= ~CSTOPB; + termios->c_cflag &= ~CSTOPB; /* parity must be enabled when CS7 to match 8-bits format */ if ((termios->c_cflag & CSIZE) == CS7) termios->c_cflag |= PARENB; - if ((termios->c_cflag & PARENB)) { + if (termios->c_cflag & PARENB) { if (termios->c_cflag & CMSPAR) { cr1 &= ~UARTCR1_PE; if (termios->c_cflag & PARODD) @@ -1599,7 +1724,7 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios, sport->port.read_status_mask = 0; if (termios->c_iflag & INPCK) - sport->port.read_status_mask |= (UARTSR1_FE | UARTSR1_PE); + sport->port.read_status_mask |= UARTSR1_FE | UARTSR1_PE; if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK)) sport->port.read_status_mask |= UARTSR1_FE; @@ -1621,8 +1746,7 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios, uart_update_timeout(port, termios->c_cflag, baud); /* wait transmit engin complete */ - while (!(readb(sport->port.membase + UARTSR1) & UARTSR1_TC)) - barrier(); + lpuart_wait_bit_set(&sport->port, UARTSR1, UARTSR1_TC); /* disable transmit and receive */ writeb(old_cr2 & ~(UARTCR2_TE | UARTCR2_RE), @@ -1713,7 +1837,7 @@ lpuart32_serial_setbrg(struct lpuart_port *sport, unsigned int baudrate) tmp |= UARTBAUD_BOTHEDGE; tmp &= ~(UARTBAUD_OSR_MASK << UARTBAUD_OSR_SHIFT); - tmp |= (((osr-1) & UARTBAUD_OSR_MASK) << UARTBAUD_OSR_SHIFT); + tmp |= ((osr-1) & UARTBAUD_OSR_MASK) << UARTBAUD_OSR_SHIFT; tmp &= ~UARTBAUD_SBR_MASK; tmp |= sbr & UARTBAUD_SBR_MASK; @@ -1766,7 +1890,7 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios, } if (termios->c_cflag & CRTSCTS) { - modem |= (UARTMODEM_RXRTSE | UARTMODEM_TXCTSE); + modem |= UARTMODEM_RXRTSE | UARTMODEM_TXCTSE; } else { termios->c_cflag &= ~CRTSCTS; modem &= ~(UARTMODEM_RXRTSE | UARTMODEM_TXCTSE); @@ -1815,7 +1939,7 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios, sport->port.read_status_mask = 0; if (termios->c_iflag & INPCK) - sport->port.read_status_mask |= (UARTSTAT_FE | UARTSTAT_PE); + sport->port.read_status_mask |= UARTSTAT_FE | UARTSTAT_PE; if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK)) sport->port.read_status_mask |= UARTSTAT_FE; @@ -1837,8 +1961,7 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios, uart_update_timeout(port, termios->c_cflag, baud); /* wait transmit engin complete */ - while (!(lpuart32_read(&sport->port, UARTSTAT) & UARTSTAT_TC)) - barrier(); + lpuart32_wait_bit_set(&sport->port, UARTSTAT, UARTSTAT_TC); /* disable transmit and receive */ lpuart32_write(&sport->port, old_ctrl & ~(UARTCTRL_TE | UARTCTRL_RE), @@ -1953,17 +2076,13 @@ static struct lpuart_port *lpuart_ports[UART_NR]; #ifdef CONFIG_SERIAL_FSL_LPUART_CONSOLE static void lpuart_console_putchar(struct uart_port *port, int ch) { - while (!(readb(port->membase + UARTSR1) & UARTSR1_TDRE)) - barrier(); - + lpuart_wait_bit_set(port, UARTSR1, UARTSR1_TDRE); writeb(ch, port->membase + UARTDR); } static void lpuart32_console_putchar(struct uart_port *port, int ch) { - while (!(lpuart32_read(port, UARTSTAT) & UARTSTAT_TDRE)) - barrier(); - + lpuart32_wait_bit_set(port, UARTSTAT, UARTSTAT_TDRE); lpuart32_write(port, ch, UARTDATA); } @@ -1982,15 +2101,14 @@ lpuart_console_write(struct console *co, const char *s, unsigned int count) /* first save CR2 and then disable interrupts */ cr2 = old_cr2 = readb(sport->port.membase + UARTCR2); - cr2 |= (UARTCR2_TE | UARTCR2_RE); + cr2 |= UARTCR2_TE | UARTCR2_RE; cr2 &= ~(UARTCR2_TIE | UARTCR2_TCIE | UARTCR2_RIE); writeb(cr2, sport->port.membase + UARTCR2); uart_console_write(&sport->port, s, count, lpuart_console_putchar); /* wait for transmitter finish complete and restore CR2 */ - while (!(readb(sport->port.membase + UARTSR1) & UARTSR1_TC)) - barrier(); + lpuart_wait_bit_set(&sport->port, UARTSR1, UARTSR1_TC); writeb(old_cr2, sport->port.membase + UARTCR2); @@ -2013,15 +2131,14 @@ lpuart32_console_write(struct console *co, const char *s, unsigned int count) /* first save CR2 and then disable interrupts */ cr = old_cr = lpuart32_read(&sport->port, UARTCTRL); - cr |= (UARTCTRL_TE | UARTCTRL_RE); + cr |= UARTCTRL_TE | UARTCTRL_RE; cr &= ~(UARTCTRL_TIE | UARTCTRL_TCIE | UARTCTRL_RIE); lpuart32_write(&sport->port, cr, UARTCTRL); uart_console_write(&sport->port, s, count, lpuart32_console_putchar); /* wait for transmitter finish complete and restore CR2 */ - while (!(lpuart32_read(&sport->port, UARTSTAT) & UARTSTAT_TC)) - barrier(); + lpuart32_wait_bit_set(&sport->port, UARTSTAT, UARTSTAT_TC); lpuart32_write(&sport->port, old_cr, UARTCTRL); @@ -2071,14 +2188,14 @@ lpuart_console_get_options(struct lpuart_port *sport, int *baud, brfa = readb(sport->port.membase + UARTCR4); brfa &= UARTCR4_BRFA_MASK; - uartclk = clk_get_rate(sport->clk); + uartclk = lpuart_get_baud_clk_rate(sport); /* * baud = mod_clk/(16*(sbr[13]+(brfa)/32) */ baud_raw = uartclk / (16 * (sbr + brfa / 32)); if (*baud != baud_raw) - printk(KERN_INFO "Serial: Console lpuart rounded baud rate" + dev_info(sport->port.dev, "Serial: Console lpuart rounded baud rate" "from %d to %d\n", baud_raw, *baud); } @@ -2114,14 +2231,14 @@ lpuart32_console_get_options(struct lpuart_port *sport, int *baud, bd = lpuart32_read(&sport->port, UARTBAUD); bd &= UARTBAUD_SBR_MASK; sbr = bd; - uartclk = clk_get_rate(sport->clk); + uartclk = lpuart_get_baud_clk_rate(sport); /* * baud = mod_clk/(16*(sbr[13]+(brfa)/32) */ baud_raw = uartclk / (16 * sbr); if (*baud != baud_raw) - printk(KERN_INFO "Serial: Console lpuart rounded baud rate" + dev_info(sport->port.dev, "Serial: Console lpuart rounded baud rate" "from %d to %d\n", baud_raw, *baud); } @@ -2232,6 +2349,7 @@ static int __init lpuart32_imx_early_console_setup(struct earlycon_device *devic OF_EARLYCON_DECLARE(lpuart, "fsl,vf610-lpuart", lpuart_early_console_setup); OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1021a-lpuart", lpuart32_early_console_setup); OF_EARLYCON_DECLARE(lpuart32, "fsl,imx7ulp-lpuart", lpuart32_imx_early_console_setup); +OF_EARLYCON_DECLARE(lpuart32, "fsl,imx8qxp-lpuart", lpuart32_imx_early_console_setup); EARLYCON_DECLARE(lpuart, lpuart_early_console_setup); EARLYCON_DECLARE(lpuart32, lpuart32_early_console_setup); @@ -2264,8 +2382,6 @@ static int lpuart_probe(struct platform_device *pdev) if (!sport) return -ENOMEM; - pdev->dev.coherent_dma_mask = 0; - ret = of_alias_get_id(np, "serial"); if (ret < 0) { ret = ida_simple_get(&fsl_lpuart_ida, 0, UART_NR, GFP_KERNEL); @@ -2288,11 +2404,10 @@ static int lpuart_probe(struct platform_device *pdev) sport->port.mapbase = res->start; sport->port.dev = &pdev->dev; sport->port.type = PORT_LPUART; + sport->devtype = sdata->devtype; ret = platform_get_irq(pdev, 0); - if (ret < 0) { - dev_err(&pdev->dev, "cannot obtain irq\n"); + if (ret < 0) return ret; - } sport->port.irq = ret; sport->port.iotype = sdata->iotype; if (lpuart_is_32(sport)) @@ -2303,20 +2418,27 @@ static int lpuart_probe(struct platform_device *pdev) sport->port.rs485_config = lpuart_config_rs485; - sport->clk = devm_clk_get(&pdev->dev, "ipg"); - if (IS_ERR(sport->clk)) { - ret = PTR_ERR(sport->clk); - dev_err(&pdev->dev, "failed to get uart clk: %d\n", ret); + sport->ipg_clk = devm_clk_get(&pdev->dev, "ipg"); + if (IS_ERR(sport->ipg_clk)) { + ret = PTR_ERR(sport->ipg_clk); + dev_err(&pdev->dev, "failed to get uart ipg clk: %d\n", ret); return ret; } - ret = clk_prepare_enable(sport->clk); - if (ret) { - dev_err(&pdev->dev, "failed to enable uart clk: %d\n", ret); - return ret; + sport->baud_clk = NULL; + if (is_imx8qxp_lpuart(sport)) { + sport->baud_clk = devm_clk_get(&pdev->dev, "baud"); + if (IS_ERR(sport->baud_clk)) { + ret = PTR_ERR(sport->baud_clk); + dev_err(&pdev->dev, "failed to get uart baud clk: %d\n", ret); + return ret; + } } - sport->port.uartclk = clk_get_rate(sport->clk); + ret = lpuart_enable_clks(sport); + if (ret) + return ret; + sport->port.uartclk = lpuart_get_baud_clk_rate(sport); lpuart_ports[sport->port.line] = sport; @@ -2364,7 +2486,7 @@ static int lpuart_probe(struct platform_device *pdev) failed_attach_port: failed_irq_request: - clk_disable_unprepare(sport->clk); + lpuart_disable_clks(sport); return ret; } @@ -2376,7 +2498,7 @@ static int lpuart_remove(struct platform_device *pdev) ida_simple_remove(&fsl_lpuart_ida, sport->port.line); - clk_disable_unprepare(sport->clk); + lpuart_disable_clks(sport); if (sport->dma_tx_chan) dma_release_channel(sport->dma_tx_chan); @@ -2441,7 +2563,7 @@ static int lpuart_suspend(struct device *dev) } if (sport->port.suspended && !irq_wake) - clk_disable_unprepare(sport->clk); + lpuart_disable_clks(sport); return 0; } @@ -2450,22 +2572,14 @@ static int lpuart_resume(struct device *dev) { struct lpuart_port *sport = dev_get_drvdata(dev); bool irq_wake = irqd_is_wakeup_set(irq_get_irq_data(sport->port.irq)); - unsigned long temp; if (sport->port.suspended && !irq_wake) - clk_prepare_enable(sport->clk); + lpuart_enable_clks(sport); - if (lpuart_is_32(sport)) { - lpuart32_setup_watermark(sport); - temp = lpuart32_read(&sport->port, UARTCTRL); - temp |= UARTCTRL_RE | UARTCTRL_TE | UARTCTRL_ILIE; - lpuart32_write(&sport->port, temp, UARTCTRL); - } else { - lpuart_setup_watermark(sport); - temp = readb(sport->port.membase + UARTCR2); - temp |= (UARTCR2_RIE | UARTCR2_TIE | UARTCR2_RE | UARTCR2_TE); - writeb(temp, sport->port.membase + UARTCR2); - } + if (lpuart_is_32(sport)) + lpuart32_setup_watermark_enable(sport); + else + lpuart_setup_watermark_enable(sport); if (sport->lpuart_dma_rx_use) { if (irq_wake) { @@ -2476,36 +2590,10 @@ static int lpuart_resume(struct device *dev) } } - if (sport->dma_tx_chan && !lpuart_dma_tx_request(&sport->port)) { - init_waitqueue_head(&sport->dma_wait); - sport->lpuart_dma_tx_use = true; - if (lpuart_is_32(sport)) { - temp = lpuart32_read(&sport->port, UARTBAUD); - lpuart32_write(&sport->port, - temp | UARTBAUD_TDMAE, UARTBAUD); - } else { - writeb(readb(sport->port.membase + UARTCR5) | - UARTCR5_TDMAS, sport->port.membase + UARTCR5); - } - } else { - sport->lpuart_dma_tx_use = false; - } + lpuart_tx_dma_startup(sport); - if (lpuart_is_32(sport)) { - if (sport->lpuart_dma_rx_use) { - /* RXWATER must be 0 */ - temp = lpuart32_read(&sport->port, UARTWATER); - temp &= ~(UARTWATER_WATER_MASK << - UARTWATER_RXWATER_OFF); - lpuart32_write(&sport->port, temp, UARTWATER); - } - temp = lpuart32_read(&sport->port, UARTCTRL); - if (!sport->lpuart_dma_rx_use) - temp |= UARTCTRL_RIE; - if (!sport->lpuart_dma_tx_use) - temp |= UARTCTRL_TIE; - lpuart32_write(&sport->port, temp, UARTCTRL); - } + if (lpuart_is_32(sport)) + lpuart32_configure(sport); uart_resume_port(&lpuart_reg, &sport->port); diff --git a/drivers/tty/serial/icom.c b/drivers/tty/serial/icom.c index ad374f7c476d..624f3d541c68 100644 --- a/drivers/tty/serial/icom.c +++ b/drivers/tty/serial/icom.c @@ -207,8 +207,6 @@ static int get_port_memory(struct icom_port *icom_port) return -ENOMEM; } - memset(icom_port->statStg, 0, 4096); - /* FODs: Frame Out Descriptor Queue, this is a FIFO queue that indicates that frames are to be transmitted */ diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 8b752e895053..87c58f9f6390 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -383,6 +383,7 @@ static void imx_uart_ucrs_restore(struct imx_port *sport, } #endif +/* called with port.lock taken and irqs caller dependent */ static void imx_uart_rts_active(struct imx_port *sport, u32 *ucr2) { *ucr2 &= ~(UCR2_CTSC | UCR2_CTS); @@ -391,6 +392,7 @@ static void imx_uart_rts_active(struct imx_port *sport, u32 *ucr2) mctrl_gpio_set(sport->gpios, sport->port.mctrl); } +/* called with port.lock taken and irqs caller dependent */ static void imx_uart_rts_inactive(struct imx_port *sport, u32 *ucr2) { *ucr2 &= ~UCR2_CTSC; @@ -400,11 +402,6 @@ static void imx_uart_rts_inactive(struct imx_port *sport, u32 *ucr2) mctrl_gpio_set(sport->gpios, sport->port.mctrl); } -static void imx_uart_rts_auto(struct imx_port *sport, u32 *ucr2) -{ - *ucr2 |= UCR2_CTSC; -} - /* called with port.lock taken and irqs off */ static void imx_uart_start_rx(struct uart_port *port) { @@ -442,7 +439,7 @@ static void imx_uart_stop_tx(struct uart_port *port) return; ucr1 = imx_uart_readl(sport, UCR1); - imx_uart_writel(sport, ucr1 & ~UCR1_TXMPTYEN, UCR1); + imx_uart_writel(sport, ucr1 & ~UCR1_TRDYEN, UCR1); /* in rs485 mode disable transmitter if shifter is empty */ if (port->rs485.flags & SER_RS485_ENABLED && @@ -520,7 +517,7 @@ static inline void imx_uart_transmit_buffer(struct imx_port *sport) * and the TX IRQ is disabled. **/ ucr1 = imx_uart_readl(sport, UCR1); - ucr1 &= ~UCR1_TXMPTYEN; + ucr1 &= ~UCR1_TRDYEN; if (sport->dma_is_txing) { ucr1 |= UCR1_TXDMAEN; imx_uart_writel(sport, ucr1, UCR1); @@ -682,7 +679,7 @@ static void imx_uart_start_tx(struct uart_port *port) if (!sport->dma_is_enabled) { ucr1 = imx_uart_readl(sport, UCR1); - imx_uart_writel(sport, ucr1 | UCR1_TXMPTYEN, UCR1); + imx_uart_writel(sport, ucr1 | UCR1_TRDYEN, UCR1); } if (sport->dma_is_enabled) { @@ -691,7 +688,7 @@ static void imx_uart_start_tx(struct uart_port *port) * disable TX DMA to let TX interrupt to send X-char */ ucr1 = imx_uart_readl(sport, UCR1); ucr1 &= ~UCR1_TXDMAEN; - ucr1 |= UCR1_TXMPTYEN; + ucr1 |= UCR1_TRDYEN; imx_uart_writel(sport, ucr1, UCR1); return; } @@ -877,7 +874,7 @@ static irqreturn_t imx_uart_int(int irq, void *dev_id) usr1 &= ~USR1_RRDY; if ((ucr2 & UCR2_ATEN) == 0) usr1 &= ~USR1_AGTIM; - if ((ucr1 & UCR1_TXMPTYEN) == 0) + if ((ucr1 & UCR1_TRDYEN) == 0) usr1 &= ~USR1_TRDY; if ((ucr4 & UCR4_TCEN) == 0) usr2 &= ~USR2_TXDC; @@ -966,10 +963,22 @@ static void imx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) if (!(port->rs485.flags & SER_RS485_ENABLED)) { u32 ucr2; + /* + * Turn off autoRTS if RTS is lowered and restore autoRTS + * setting if RTS is raised. + */ ucr2 = imx_uart_readl(sport, UCR2); ucr2 &= ~(UCR2_CTS | UCR2_CTSC); - if (mctrl & TIOCM_RTS) - ucr2 |= UCR2_CTS | UCR2_CTSC; + if (mctrl & TIOCM_RTS) { + ucr2 |= UCR2_CTS; + /* + * UCR2_IRTS is unset if and only if the port is + * configured for CRTSCTS, so we use inverted UCR2_IRTS + * to get the state to restore to. + */ + if (!(ucr2 & UCR2_IRTS)) + ucr2 |= UCR2_CTSC; + } imx_uart_writel(sport, ucr2, UCR2); } @@ -1465,7 +1474,7 @@ static void imx_uart_shutdown(struct uart_port *port) spin_lock_irqsave(&sport->port.lock, flags); ucr1 = imx_uart_readl(sport, UCR1); - ucr1 &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN | UCR1_RXDMAEN | UCR1_ATDMAEN); + ucr1 &= ~(UCR1_TRDYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN | UCR1_RXDMAEN | UCR1_ATDMAEN); imx_uart_writel(sport, ucr1, UCR1); spin_unlock_irqrestore(&sport->port.lock, flags); @@ -1532,11 +1541,11 @@ imx_uart_set_termios(struct uart_port *port, struct ktermios *termios, { struct imx_port *sport = (struct imx_port *)port; unsigned long flags; - u32 ucr2, old_ucr1, old_ucr2, ufcr; + u32 ucr2, old_ucr2, ufcr; unsigned int baud, quot; unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8; unsigned long div; - unsigned long num, denom; + unsigned long num, denom, old_ubir, old_ubmr; uint64_t tdiv64; /* @@ -1549,40 +1558,52 @@ imx_uart_set_termios(struct uart_port *port, struct ktermios *termios, old_csize = CS8; } + del_timer_sync(&sport->timer); + + /* + * Ask the core to calculate the divisor for us. + */ + baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 16); + quot = uart_get_divisor(port, baud); + + spin_lock_irqsave(&sport->port.lock, flags); + + /* + * Read current UCR2 and save it for future use, then clear all the bits + * except those we will or may need to preserve. + */ + old_ucr2 = imx_uart_readl(sport, UCR2); + ucr2 = old_ucr2 & (UCR2_TXEN | UCR2_RXEN | UCR2_ATEN | UCR2_CTS); + + ucr2 |= UCR2_SRST | UCR2_IRTS; if ((termios->c_cflag & CSIZE) == CS8) - ucr2 = UCR2_WS | UCR2_SRST | UCR2_IRTS; - else - ucr2 = UCR2_SRST | UCR2_IRTS; - - if (termios->c_cflag & CRTSCTS) { - if (sport->have_rtscts) { - ucr2 &= ~UCR2_IRTS; - - if (port->rs485.flags & SER_RS485_ENABLED) { - /* - * RTS is mandatory for rs485 operation, so keep - * it under manual control and keep transmitter - * disabled. - */ - if (port->rs485.flags & - SER_RS485_RTS_AFTER_SEND) - imx_uart_rts_active(sport, &ucr2); - else - imx_uart_rts_inactive(sport, &ucr2); - } else { - imx_uart_rts_auto(sport, &ucr2); - } - } else { - termios->c_cflag &= ~CRTSCTS; - } - } else if (port->rs485.flags & SER_RS485_ENABLED) { - /* disable transmitter */ + ucr2 |= UCR2_WS; + + if (!sport->have_rtscts) + termios->c_cflag &= ~CRTSCTS; + + if (port->rs485.flags & SER_RS485_ENABLED) { + /* + * RTS is mandatory for rs485 operation, so keep + * it under manual control and keep transmitter + * disabled. + */ if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND) imx_uart_rts_active(sport, &ucr2); else imx_uart_rts_inactive(sport, &ucr2); + + } else if (termios->c_cflag & CRTSCTS) { + /* + * Only let receiver control RTS output if we were not requested + * to have RTS inactive (which then should take precedence). + */ + if (ucr2 & UCR2_CTS) + ucr2 |= UCR2_CTSC; } + if (termios->c_cflag & CRTSCTS) + ucr2 &= ~UCR2_IRTS; if (termios->c_cflag & CSTOPB) ucr2 |= UCR2_STPB; @@ -1592,16 +1613,6 @@ imx_uart_set_termios(struct uart_port *port, struct ktermios *termios, ucr2 |= UCR2_PROE; } - del_timer_sync(&sport->timer); - - /* - * Ask the core to calculate the divisor for us. - */ - baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 16); - quot = uart_get_divisor(port, baud); - - spin_lock_irqsave(&sport->port.lock, flags); - sport->port.read_status_mask = 0; if (termios->c_iflag & INPCK) sport->port.read_status_mask |= (URXD_FRMERR | URXD_PRERR); @@ -1632,23 +1643,6 @@ imx_uart_set_termios(struct uart_port *port, struct ktermios *termios, */ uart_update_timeout(port, termios->c_cflag, baud); - /* - * disable interrupts and drain transmitter - */ - old_ucr1 = imx_uart_readl(sport, UCR1); - imx_uart_writel(sport, - old_ucr1 & ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN), - UCR1); - old_ucr2 = imx_uart_readl(sport, UCR2); - imx_uart_writel(sport, old_ucr2 & ~UCR2_ATEN, UCR2); - - while (!(imx_uart_readl(sport, USR2) & USR2_TXDC)) - barrier(); - - /* then, disable everything */ - imx_uart_writel(sport, old_ucr2 & ~(UCR2_TXEN | UCR2_RXEN | UCR2_ATEN), UCR2); - old_ucr2 &= (UCR2_TXEN | UCR2_RXEN | UCR2_ATEN); - /* custom-baudrate handling */ div = sport->port.uartclk / (baud * 16); if (baud == 38400 && quot != div) @@ -1676,17 +1670,27 @@ imx_uart_set_termios(struct uart_port *port, struct ktermios *termios, ufcr = (ufcr & (~UFCR_RFDIV)) | UFCR_RFDIV_REG(div); imx_uart_writel(sport, ufcr, UFCR); - imx_uart_writel(sport, num, UBIR); - imx_uart_writel(sport, denom, UBMR); + /* + * Two registers below should always be written both and in this + * particular order. One consequence is that we need to check if any of + * them changes and then update both. We do need the check for change + * as even writing the same values seem to "restart" + * transmission/receiving logic in the hardware, that leads to data + * breakage even when rate doesn't in fact change. E.g., user switches + * RTS/CTS handshake and suddenly gets broken bytes. + */ + old_ubir = imx_uart_readl(sport, UBIR); + old_ubmr = imx_uart_readl(sport, UBMR); + if (old_ubir != num || old_ubmr != denom) { + imx_uart_writel(sport, num, UBIR); + imx_uart_writel(sport, denom, UBMR); + } if (!imx_uart_is_imx1(sport)) imx_uart_writel(sport, sport->port.uartclk / div / 1000, IMX21_ONEMS); - imx_uart_writel(sport, old_ucr1, UCR1); - - /* set the parity, stop bits and data size */ - imx_uart_writel(sport, ucr2 | old_ucr2, UCR2); + imx_uart_writel(sport, ucr2, UCR2); if (UART_ENABLE_MS(&sport->port, termios->c_cflag)) imx_uart_enable_ms(&sport->port); @@ -1774,7 +1778,7 @@ static int imx_uart_poll_init(struct uart_port *port) ucr1 |= IMX1_UCR1_UARTCLKEN; ucr1 |= UCR1_UARTEN; - ucr1 &= ~(UCR1_TXMPTYEN | UCR1_RTSDEN | UCR1_RRDYEN); + ucr1 &= ~(UCR1_TRDYEN | UCR1_RTSDEN | UCR1_RRDYEN); ucr2 |= UCR2_RXEN; ucr2 &= ~UCR2_ATEN; @@ -1934,7 +1938,7 @@ imx_uart_console_write(struct console *co, const char *s, unsigned int count) if (imx_uart_is_imx1(sport)) ucr1 |= IMX1_UCR1_UARTCLKEN; ucr1 |= UCR1_UARTEN; - ucr1 &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN); + ucr1 &= ~(UCR1_TRDYEN | UCR1_RRDYEN | UCR1_RTSDEN); imx_uart_writel(sport, ucr1, UCR1); @@ -2015,7 +2019,7 @@ imx_uart_console_get_options(struct imx_port *sport, int *baud, } if (*baud != baud_raw) - pr_info("Console IMX rounded baud rate from %d to %d\n", + dev_info(sport->port.dev, "Console IMX rounded baud rate from %d to %d\n", baud_raw, *baud); } } @@ -2290,7 +2294,7 @@ static int imx_uart_probe(struct platform_device *pdev) /* Disable interrupts before requesting them */ ucr1 = imx_uart_readl(sport, UCR1); ucr1 &= ~(UCR1_ADEN | UCR1_TRDYEN | UCR1_IDEN | UCR1_RRDYEN | - UCR1_TXMPTYEN | UCR1_RTSDEN); + UCR1_TRDYEN | UCR1_RTSDEN); imx_uart_writel(sport, ucr1, UCR1); if (!imx_uart_is_imx1(sport) && sport->dte_mode) { diff --git a/drivers/tty/serial/ioc3_serial.c b/drivers/tty/serial/ioc3_serial.c deleted file mode 100644 index d8a1cdd6a53d..000000000000 --- a/drivers/tty/serial/ioc3_serial.c +++ /dev/null @@ -1,2195 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2005 Silicon Graphics, Inc. All Rights Reserved. - */ - -/* - * This file contains a module version of the ioc3 serial driver. This - * includes all the support functions needed (support functions, etc.) - * and the serial driver itself. - */ -#include <linux/errno.h> -#include <linux/tty.h> -#include <linux/tty_flip.h> -#include <linux/serial.h> -#include <linux/circ_buf.h> -#include <linux/serial_reg.h> -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/serial_core.h> -#include <linux/ioc3.h> -#include <linux/slab.h> - -/* - * Interesting things about the ioc3 - */ - -#define LOGICAL_PORTS 2 /* rs232(0) and rs422(1) */ -#define PORTS_PER_CARD 2 -#define LOGICAL_PORTS_PER_CARD (PORTS_PER_CARD * LOGICAL_PORTS) -#define MAX_CARDS 8 -#define MAX_LOGICAL_PORTS (LOGICAL_PORTS_PER_CARD * MAX_CARDS) - -/* determine given the sio_ir what port it applies to */ -#define GET_PORT_FROM_SIO_IR(_x) (_x & SIO_IR_SA) ? 0 : 1 - - -/* - * we have 2 logical ports (rs232, rs422) for each physical port - * evens are rs232, odds are rs422 - */ -#define GET_PHYSICAL_PORT(_x) ((_x) >> 1) -#define GET_LOGICAL_PORT(_x) ((_x) & 1) -#define IS_PHYSICAL_PORT(_x) !((_x) & 1) -#define IS_RS232(_x) !((_x) & 1) - -static unsigned int Num_of_ioc3_cards; -static unsigned int Submodule_slot; - -/* defining this will get you LOTS of great debug info */ -//#define DEBUG_INTERRUPTS -#define DPRINT_CONFIG(_x...) ; -//#define DPRINT_CONFIG(_x...) printk _x -#define NOT_PROGRESS() ; -//#define NOT_PROGRESS() printk("%s : fails %d\n", __func__, __LINE__) - -/* number of characters we want to transmit to the lower level at a time */ -#define MAX_CHARS 256 -#define FIFO_SIZE (MAX_CHARS-1) /* it's a uchar */ - -/* Device name we're using */ -#define DEVICE_NAME "ttySIOC" -#define DEVICE_MAJOR 204 -#define DEVICE_MINOR 116 - -/* flags for next_char_state */ -#define NCS_BREAK 0x1 -#define NCS_PARITY 0x2 -#define NCS_FRAMING 0x4 -#define NCS_OVERRUN 0x8 - -/* cause we need SOME parameters ... */ -#define MIN_BAUD_SUPPORTED 1200 -#define MAX_BAUD_SUPPORTED 115200 - -/* protocol types supported */ -#define PROTO_RS232 0 -#define PROTO_RS422 1 - -/* Notification types */ -#define N_DATA_READY 0x01 -#define N_OUTPUT_LOWAT 0x02 -#define N_BREAK 0x04 -#define N_PARITY_ERROR 0x08 -#define N_FRAMING_ERROR 0x10 -#define N_OVERRUN_ERROR 0x20 -#define N_DDCD 0x40 -#define N_DCTS 0x80 - -#define N_ALL_INPUT (N_DATA_READY | N_BREAK \ - | N_PARITY_ERROR | N_FRAMING_ERROR \ - | N_OVERRUN_ERROR | N_DDCD | N_DCTS) - -#define N_ALL_OUTPUT N_OUTPUT_LOWAT - -#define N_ALL_ERRORS (N_PARITY_ERROR | N_FRAMING_ERROR \ - | N_OVERRUN_ERROR) - -#define N_ALL (N_DATA_READY | N_OUTPUT_LOWAT | N_BREAK \ - | N_PARITY_ERROR | N_FRAMING_ERROR \ - | N_OVERRUN_ERROR | N_DDCD | N_DCTS) - -#define SER_CLK_SPEED(prediv) ((22000000 << 1) / prediv) -#define SER_DIVISOR(x, clk) (((clk) + (x) * 8) / ((x) * 16)) -#define DIVISOR_TO_BAUD(div, clk) ((clk) / 16 / (div)) - -/* Some masks */ -#define LCR_MASK_BITS_CHAR (UART_LCR_WLEN5 | UART_LCR_WLEN6 \ - | UART_LCR_WLEN7 | UART_LCR_WLEN8) -#define LCR_MASK_STOP_BITS (UART_LCR_STOP) - -#define PENDING(_a, _p) (readl(&(_p)->vma->sio_ir) & (_a)->ic_enable) - -#define RING_BUF_SIZE 4096 -#define BUF_SIZE_BIT SBBR_L_SIZE -#define PROD_CONS_MASK PROD_CONS_PTR_4K - -#define TOTAL_RING_BUF_SIZE (RING_BUF_SIZE * 4) - -/* driver specific - one per card */ -struct ioc3_card { - struct { - /* uart ports are allocated here */ - struct uart_port icp_uart_port[LOGICAL_PORTS]; - /* the ioc3_port used for this port */ - struct ioc3_port *icp_port; - } ic_port[PORTS_PER_CARD]; - /* currently enabled interrupts */ - uint32_t ic_enable; -}; - -/* Local port info for each IOC3 serial port */ -struct ioc3_port { - /* handy reference material */ - struct uart_port *ip_port; - struct ioc3_card *ip_card; - struct ioc3_driver_data *ip_idd; - struct ioc3_submodule *ip_is; - - /* pci mem addresses for this port */ - struct ioc3_serialregs __iomem *ip_serial_regs; - struct ioc3_uartregs __iomem *ip_uart_regs; - - /* Ring buffer page for this port */ - dma_addr_t ip_dma_ringbuf; - /* vaddr of ring buffer */ - struct ring_buffer *ip_cpu_ringbuf; - - /* Rings for this port */ - struct ring *ip_inring; - struct ring *ip_outring; - - /* Hook to port specific values */ - struct port_hooks *ip_hooks; - - spinlock_t ip_lock; - - /* Various rx/tx parameters */ - int ip_baud; - int ip_tx_lowat; - int ip_rx_timeout; - - /* Copy of notification bits */ - int ip_notify; - - /* Shadow copies of various registers so we don't need to PIO - * read them constantly - */ - uint32_t ip_sscr; - uint32_t ip_tx_prod; - uint32_t ip_rx_cons; - unsigned char ip_flags; -}; - -/* tx low water mark. We need to notify the driver whenever tx is getting - * close to empty so it can refill the tx buffer and keep things going. - * Let's assume that if we interrupt 1 ms before the tx goes idle, we'll - * have no trouble getting in more chars in time (I certainly hope so). - */ -#define TX_LOWAT_LATENCY 1000 -#define TX_LOWAT_HZ (1000000 / TX_LOWAT_LATENCY) -#define TX_LOWAT_CHARS(baud) (baud / 10 / TX_LOWAT_HZ) - -/* Flags per port */ -#define INPUT_HIGH 0x01 - /* used to signify that we have turned off the rx_high - * temporarily - we need to drain the fifo and don't - * want to get blasted with interrupts. - */ -#define DCD_ON 0x02 - /* DCD state is on */ -#define LOWAT_WRITTEN 0x04 -#define READ_ABORTED 0x08 - /* the read was aborted - used to avaoid infinate looping - * in the interrupt handler - */ -#define INPUT_ENABLE 0x10 - -/* Since each port has different register offsets and bitmasks - * for everything, we'll store those that we need in tables so we - * don't have to be constantly checking the port we are dealing with. - */ -struct port_hooks { - uint32_t intr_delta_dcd; - uint32_t intr_delta_cts; - uint32_t intr_tx_mt; - uint32_t intr_rx_timer; - uint32_t intr_rx_high; - uint32_t intr_tx_explicit; - uint32_t intr_clear; - uint32_t intr_all; - char rs422_select_pin; -}; - -static struct port_hooks hooks_array[PORTS_PER_CARD] = { - /* values for port A */ - { - .intr_delta_dcd = SIO_IR_SA_DELTA_DCD, - .intr_delta_cts = SIO_IR_SA_DELTA_CTS, - .intr_tx_mt = SIO_IR_SA_TX_MT, - .intr_rx_timer = SIO_IR_SA_RX_TIMER, - .intr_rx_high = SIO_IR_SA_RX_HIGH, - .intr_tx_explicit = SIO_IR_SA_TX_EXPLICIT, - .intr_clear = (SIO_IR_SA_TX_MT | SIO_IR_SA_RX_FULL - | SIO_IR_SA_RX_HIGH - | SIO_IR_SA_RX_TIMER - | SIO_IR_SA_DELTA_DCD - | SIO_IR_SA_DELTA_CTS - | SIO_IR_SA_INT - | SIO_IR_SA_TX_EXPLICIT - | SIO_IR_SA_MEMERR), - .intr_all = SIO_IR_SA, - .rs422_select_pin = GPPR_UARTA_MODESEL_PIN, - }, - - /* values for port B */ - { - .intr_delta_dcd = SIO_IR_SB_DELTA_DCD, - .intr_delta_cts = SIO_IR_SB_DELTA_CTS, - .intr_tx_mt = SIO_IR_SB_TX_MT, - .intr_rx_timer = SIO_IR_SB_RX_TIMER, - .intr_rx_high = SIO_IR_SB_RX_HIGH, - .intr_tx_explicit = SIO_IR_SB_TX_EXPLICIT, - .intr_clear = (SIO_IR_SB_TX_MT | SIO_IR_SB_RX_FULL - | SIO_IR_SB_RX_HIGH - | SIO_IR_SB_RX_TIMER - | SIO_IR_SB_DELTA_DCD - | SIO_IR_SB_DELTA_CTS - | SIO_IR_SB_INT - | SIO_IR_SB_TX_EXPLICIT - | SIO_IR_SB_MEMERR), - .intr_all = SIO_IR_SB, - .rs422_select_pin = GPPR_UARTB_MODESEL_PIN, - } -}; - -struct ring_entry { - union { - struct { - uint32_t alldata; - uint32_t allsc; - } all; - struct { - char data[4]; /* data bytes */ - char sc[4]; /* status/control */ - } s; - } u; -}; - -/* Test the valid bits in any of the 4 sc chars using "allsc" member */ -#define RING_ANY_VALID \ - ((uint32_t)(RXSB_MODEM_VALID | RXSB_DATA_VALID) * 0x01010101) - -#define ring_sc u.s.sc -#define ring_data u.s.data -#define ring_allsc u.all.allsc - -/* Number of entries per ring buffer. */ -#define ENTRIES_PER_RING (RING_BUF_SIZE / (int) sizeof(struct ring_entry)) - -/* An individual ring */ -struct ring { - struct ring_entry entries[ENTRIES_PER_RING]; -}; - -/* The whole enchilada */ -struct ring_buffer { - struct ring TX_A; - struct ring RX_A; - struct ring TX_B; - struct ring RX_B; -}; - -/* Get a ring from a port struct */ -#define RING(_p, _wh) &(((struct ring_buffer *)((_p)->ip_cpu_ringbuf))->_wh) - -/* for Infinite loop detection */ -#define MAXITER 10000000 - - -/** - * set_baud - Baud rate setting code - * @port: port to set - * @baud: baud rate to use - */ -static int set_baud(struct ioc3_port *port, int baud) -{ - int divisor; - int actual_baud; - int diff; - int lcr, prediv; - struct ioc3_uartregs __iomem *uart; - - for (prediv = 6; prediv < 64; prediv++) { - divisor = SER_DIVISOR(baud, SER_CLK_SPEED(prediv)); - if (!divisor) - continue; /* invalid divisor */ - actual_baud = DIVISOR_TO_BAUD(divisor, SER_CLK_SPEED(prediv)); - - diff = actual_baud - baud; - if (diff < 0) - diff = -diff; - - /* if we're within 1% we've found a match */ - if (diff * 100 <= actual_baud) - break; - } - - /* if the above loop completed, we didn't match - * the baud rate. give up. - */ - if (prediv == 64) { - NOT_PROGRESS(); - return 1; - } - - uart = port->ip_uart_regs; - lcr = readb(&uart->iu_lcr); - - writeb(lcr | UART_LCR_DLAB, &uart->iu_lcr); - writeb((unsigned char)divisor, &uart->iu_dll); - writeb((unsigned char)(divisor >> 8), &uart->iu_dlm); - writeb((unsigned char)prediv, &uart->iu_scr); - writeb((unsigned char)lcr, &uart->iu_lcr); - - return 0; -} - -/** - * get_ioc3_port - given a uart port, return the control structure - * @the_port: uart port to find - */ -static struct ioc3_port *get_ioc3_port(struct uart_port *the_port) -{ - struct ioc3_driver_data *idd = dev_get_drvdata(the_port->dev); - struct ioc3_card *card_ptr = idd->data[Submodule_slot]; - int ii, jj; - - if (!card_ptr) { - NOT_PROGRESS(); - return NULL; - } - for (ii = 0; ii < PORTS_PER_CARD; ii++) { - for (jj = 0; jj < LOGICAL_PORTS; jj++) { - if (the_port == &card_ptr->ic_port[ii].icp_uart_port[jj]) - return card_ptr->ic_port[ii].icp_port; - } - } - NOT_PROGRESS(); - return NULL; -} - -/** - * port_init - Initialize the sio and ioc3 hardware for a given port - * called per port from attach... - * @port: port to initialize - */ -static inline int port_init(struct ioc3_port *port) -{ - uint32_t sio_cr; - struct port_hooks *hooks = port->ip_hooks; - struct ioc3_uartregs __iomem *uart; - int reset_loop_counter = 0xfffff; - struct ioc3_driver_data *idd = port->ip_idd; - - /* Idle the IOC3 serial interface */ - writel(SSCR_RESET, &port->ip_serial_regs->sscr); - - /* Wait until any pending bus activity for this port has ceased */ - do { - sio_cr = readl(&idd->vma->sio_cr); - if (reset_loop_counter-- <= 0) { - printk(KERN_WARNING - "IOC3 unable to come out of reset" - " scr 0x%x\n", sio_cr); - return -1; - } - } while (!(sio_cr & SIO_CR_ARB_DIAG_IDLE) && - (((sio_cr &= SIO_CR_ARB_DIAG) == SIO_CR_ARB_DIAG_TXA) - || sio_cr == SIO_CR_ARB_DIAG_TXB - || sio_cr == SIO_CR_ARB_DIAG_RXA - || sio_cr == SIO_CR_ARB_DIAG_RXB)); - - /* Finish reset sequence */ - writel(0, &port->ip_serial_regs->sscr); - - /* Once RESET is done, reload cached tx_prod and rx_cons values - * and set rings to empty by making prod == cons - */ - port->ip_tx_prod = readl(&port->ip_serial_regs->stcir) & PROD_CONS_MASK; - writel(port->ip_tx_prod, &port->ip_serial_regs->stpir); - port->ip_rx_cons = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK; - writel(port->ip_rx_cons | SRCIR_ARM, &port->ip_serial_regs->srcir); - - /* Disable interrupts for this 16550 */ - uart = port->ip_uart_regs; - writeb(0, &uart->iu_lcr); - writeb(0, &uart->iu_ier); - - /* Set the default baud */ - set_baud(port, port->ip_baud); - - /* Set line control to 8 bits no parity */ - writeb(UART_LCR_WLEN8 | 0, &uart->iu_lcr); - /* UART_LCR_STOP == 1 stop */ - - /* Enable the FIFOs */ - writeb(UART_FCR_ENABLE_FIFO, &uart->iu_fcr); - /* then reset 16550 FIFOs */ - writeb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT, - &uart->iu_fcr); - - /* Clear modem control register */ - writeb(0, &uart->iu_mcr); - - /* Clear deltas in modem status register */ - writel(0, &port->ip_serial_regs->shadow); - - /* Only do this once per port pair */ - if (port->ip_hooks == &hooks_array[0]) { - unsigned long ring_pci_addr; - uint32_t __iomem *sbbr_l, *sbbr_h; - - sbbr_l = &idd->vma->sbbr_l; - sbbr_h = &idd->vma->sbbr_h; - ring_pci_addr = (unsigned long __iomem)port->ip_dma_ringbuf; - DPRINT_CONFIG(("%s: ring_pci_addr 0x%p\n", - __func__, (void *)ring_pci_addr)); - - writel((unsigned int)((uint64_t) ring_pci_addr >> 32), sbbr_h); - writel((unsigned int)ring_pci_addr | BUF_SIZE_BIT, sbbr_l); - } - - /* Set the receive timeout value to 10 msec */ - writel(SRTR_HZ / 100, &port->ip_serial_regs->srtr); - - /* Set rx threshold, enable DMA */ - /* Set high water mark at 3/4 of full ring */ - port->ip_sscr = (ENTRIES_PER_RING * 3 / 4); - - /* uart experiences pauses at high baud rate reducing actual - * throughput by 10% or so unless we enable high speed polling - * XXX when this hardware bug is resolved we should revert to - * normal polling speed - */ - port->ip_sscr |= SSCR_HIGH_SPD; - - writel(port->ip_sscr, &port->ip_serial_regs->sscr); - - /* Disable and clear all serial related interrupt bits */ - port->ip_card->ic_enable &= ~hooks->intr_clear; - ioc3_disable(port->ip_is, idd, hooks->intr_clear); - ioc3_ack(port->ip_is, idd, hooks->intr_clear); - return 0; -} - -/** - * enable_intrs - enable interrupts - * @port: port to enable - * @mask: mask to use - */ -static void enable_intrs(struct ioc3_port *port, uint32_t mask) -{ - if ((port->ip_card->ic_enable & mask) != mask) { - port->ip_card->ic_enable |= mask; - ioc3_enable(port->ip_is, port->ip_idd, mask); - } -} - -/** - * local_open - local open a port - * @port: port to open - */ -static inline int local_open(struct ioc3_port *port) -{ - int spiniter = 0; - - port->ip_flags = INPUT_ENABLE; - - /* Pause the DMA interface if necessary */ - if (port->ip_sscr & SSCR_DMA_EN) { - writel(port->ip_sscr | SSCR_DMA_PAUSE, - &port->ip_serial_regs->sscr); - while ((readl(&port->ip_serial_regs->sscr) - & SSCR_PAUSE_STATE) == 0) { - spiniter++; - if (spiniter > MAXITER) { - NOT_PROGRESS(); - return -1; - } - } - } - - /* Reset the input fifo. If the uart received chars while the port - * was closed and DMA is not enabled, the uart may have a bunch of - * chars hanging around in its rx fifo which will not be discarded - * by rclr in the upper layer. We must get rid of them here. - */ - writeb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR, - &port->ip_uart_regs->iu_fcr); - - writeb(UART_LCR_WLEN8, &port->ip_uart_regs->iu_lcr); - /* UART_LCR_STOP == 1 stop */ - - /* Re-enable DMA, set default threshold to intr whenever there is - * data available. - */ - port->ip_sscr &= ~SSCR_RX_THRESHOLD; - port->ip_sscr |= 1; /* default threshold */ - - /* Plug in the new sscr. This implicitly clears the DMA_PAUSE - * flag if it was set above - */ - writel(port->ip_sscr, &port->ip_serial_regs->sscr); - port->ip_tx_lowat = 1; - return 0; -} - -/** - * set_rx_timeout - Set rx timeout and threshold values. - * @port: port to use - * @timeout: timeout value in ticks - */ -static inline int set_rx_timeout(struct ioc3_port *port, int timeout) -{ - int threshold; - - port->ip_rx_timeout = timeout; - - /* Timeout is in ticks. Let's figure out how many chars we - * can receive at the current baud rate in that interval - * and set the rx threshold to that amount. There are 4 chars - * per ring entry, so we'll divide the number of chars that will - * arrive in timeout by 4. - * So .... timeout * baud / 10 / HZ / 4, with HZ = 100. - */ - threshold = timeout * port->ip_baud / 4000; - if (threshold == 0) - threshold = 1; /* otherwise we'll intr all the time! */ - - if ((unsigned)threshold > (unsigned)SSCR_RX_THRESHOLD) - return 1; - - port->ip_sscr &= ~SSCR_RX_THRESHOLD; - port->ip_sscr |= threshold; - writel(port->ip_sscr, &port->ip_serial_regs->sscr); - - /* Now set the rx timeout to the given value - * again timeout * SRTR_HZ / HZ - */ - timeout = timeout * SRTR_HZ / 100; - if (timeout > SRTR_CNT) - timeout = SRTR_CNT; - writel(timeout, &port->ip_serial_regs->srtr); - return 0; -} - -/** - * config_port - config the hardware - * @port: port to config - * @baud: baud rate for the port - * @byte_size: data size - * @stop_bits: number of stop bits - * @parenb: parity enable ? - * @parodd: odd parity ? - */ -static inline int -config_port(struct ioc3_port *port, - int baud, int byte_size, int stop_bits, int parenb, int parodd) -{ - char lcr, sizebits; - int spiniter = 0; - - DPRINT_CONFIG(("%s: line %d baud %d byte_size %d stop %d parenb %d " - "parodd %d\n", - __func__, ((struct uart_port *)port->ip_port)->line, - baud, byte_size, stop_bits, parenb, parodd)); - - if (set_baud(port, baud)) - return 1; - - switch (byte_size) { - case 5: - sizebits = UART_LCR_WLEN5; - break; - case 6: - sizebits = UART_LCR_WLEN6; - break; - case 7: - sizebits = UART_LCR_WLEN7; - break; - case 8: - sizebits = UART_LCR_WLEN8; - break; - default: - return 1; - } - - /* Pause the DMA interface if necessary */ - if (port->ip_sscr & SSCR_DMA_EN) { - writel(port->ip_sscr | SSCR_DMA_PAUSE, - &port->ip_serial_regs->sscr); - while ((readl(&port->ip_serial_regs->sscr) - & SSCR_PAUSE_STATE) == 0) { - spiniter++; - if (spiniter > MAXITER) - return -1; - } - } - - /* Clear relevant fields in lcr */ - lcr = readb(&port->ip_uart_regs->iu_lcr); - lcr &= ~(LCR_MASK_BITS_CHAR | UART_LCR_EPAR | - UART_LCR_PARITY | LCR_MASK_STOP_BITS); - - /* Set byte size in lcr */ - lcr |= sizebits; - - /* Set parity */ - if (parenb) { - lcr |= UART_LCR_PARITY; - if (!parodd) - lcr |= UART_LCR_EPAR; - } - - /* Set stop bits */ - if (stop_bits) - lcr |= UART_LCR_STOP /* 2 stop bits */ ; - - writeb(lcr, &port->ip_uart_regs->iu_lcr); - - /* Re-enable the DMA interface if necessary */ - if (port->ip_sscr & SSCR_DMA_EN) { - writel(port->ip_sscr, &port->ip_serial_regs->sscr); - } - port->ip_baud = baud; - - /* When we get within this number of ring entries of filling the - * entire ring on tx, place an EXPLICIT intr to generate a lowat - * notification when output has drained. - */ - port->ip_tx_lowat = (TX_LOWAT_CHARS(baud) + 3) / 4; - if (port->ip_tx_lowat == 0) - port->ip_tx_lowat = 1; - - set_rx_timeout(port, 2); - return 0; -} - -/** - * do_write - Write bytes to the port. Returns the number of bytes - * actually written. Called from transmit_chars - * @port: port to use - * @buf: the stuff to write - * @len: how many bytes in 'buf' - */ -static inline int do_write(struct ioc3_port *port, char *buf, int len) -{ - int prod_ptr, cons_ptr, total = 0; - struct ring *outring; - struct ring_entry *entry; - struct port_hooks *hooks = port->ip_hooks; - - BUG_ON(!(len >= 0)); - - prod_ptr = port->ip_tx_prod; - cons_ptr = readl(&port->ip_serial_regs->stcir) & PROD_CONS_MASK; - outring = port->ip_outring; - - /* Maintain a 1-entry red-zone. The ring buffer is full when - * (cons - prod) % ring_size is 1. Rather than do this subtraction - * in the body of the loop, I'll do it now. - */ - cons_ptr = (cons_ptr - (int)sizeof(struct ring_entry)) & PROD_CONS_MASK; - - /* Stuff the bytes into the output */ - while ((prod_ptr != cons_ptr) && (len > 0)) { - int xx; - - /* Get 4 bytes (one ring entry) at a time */ - entry = (struct ring_entry *)((caddr_t) outring + prod_ptr); - - /* Invalidate all entries */ - entry->ring_allsc = 0; - - /* Copy in some bytes */ - for (xx = 0; (xx < 4) && (len > 0); xx++) { - entry->ring_data[xx] = *buf++; - entry->ring_sc[xx] = TXCB_VALID; - len--; - total++; - } - - /* If we are within some small threshold of filling up the - * entire ring buffer, we must place an EXPLICIT intr here - * to generate a lowat interrupt in case we subsequently - * really do fill up the ring and the caller goes to sleep. - * No need to place more than one though. - */ - if (!(port->ip_flags & LOWAT_WRITTEN) && - ((cons_ptr - prod_ptr) & PROD_CONS_MASK) - <= port->ip_tx_lowat * (int)sizeof(struct ring_entry)) { - port->ip_flags |= LOWAT_WRITTEN; - entry->ring_sc[0] |= TXCB_INT_WHEN_DONE; - } - - /* Go on to next entry */ - prod_ptr += sizeof(struct ring_entry); - prod_ptr &= PROD_CONS_MASK; - } - - /* If we sent something, start DMA if necessary */ - if (total > 0 && !(port->ip_sscr & SSCR_DMA_EN)) { - port->ip_sscr |= SSCR_DMA_EN; - writel(port->ip_sscr, &port->ip_serial_regs->sscr); - } - - /* Store the new producer pointer. If tx is disabled, we stuff the - * data into the ring buffer, but we don't actually start tx. - */ - if (!uart_tx_stopped(port->ip_port)) { - writel(prod_ptr, &port->ip_serial_regs->stpir); - - /* If we are now transmitting, enable tx_mt interrupt so we - * can disable DMA if necessary when the tx finishes. - */ - if (total > 0) - enable_intrs(port, hooks->intr_tx_mt); - } - port->ip_tx_prod = prod_ptr; - - return total; -} - -/** - * disable_intrs - disable interrupts - * @port: port to enable - * @mask: mask to use - */ -static inline void disable_intrs(struct ioc3_port *port, uint32_t mask) -{ - if (port->ip_card->ic_enable & mask) { - ioc3_disable(port->ip_is, port->ip_idd, mask); - port->ip_card->ic_enable &= ~mask; - } -} - -/** - * set_notification - Modify event notification - * @port: port to use - * @mask: events mask - * @set_on: set ? - */ -static int set_notification(struct ioc3_port *port, int mask, int set_on) -{ - struct port_hooks *hooks = port->ip_hooks; - uint32_t intrbits, sscrbits; - - BUG_ON(!mask); - - intrbits = sscrbits = 0; - - if (mask & N_DATA_READY) - intrbits |= (hooks->intr_rx_timer | hooks->intr_rx_high); - if (mask & N_OUTPUT_LOWAT) - intrbits |= hooks->intr_tx_explicit; - if (mask & N_DDCD) { - intrbits |= hooks->intr_delta_dcd; - sscrbits |= SSCR_RX_RING_DCD; - } - if (mask & N_DCTS) - intrbits |= hooks->intr_delta_cts; - - if (set_on) { - enable_intrs(port, intrbits); - port->ip_notify |= mask; - port->ip_sscr |= sscrbits; - } else { - disable_intrs(port, intrbits); - port->ip_notify &= ~mask; - port->ip_sscr &= ~sscrbits; - } - - /* We require DMA if either DATA_READY or DDCD notification is - * currently requested. If neither of these is requested and - * there is currently no tx in progress, DMA may be disabled. - */ - if (port->ip_notify & (N_DATA_READY | N_DDCD)) - port->ip_sscr |= SSCR_DMA_EN; - else if (!(port->ip_card->ic_enable & hooks->intr_tx_mt)) - port->ip_sscr &= ~SSCR_DMA_EN; - - writel(port->ip_sscr, &port->ip_serial_regs->sscr); - return 0; -} - -/** - * set_mcr - set the master control reg - * @the_port: port to use - * @mask1: mcr mask - * @mask2: shadow mask - */ -static inline int set_mcr(struct uart_port *the_port, - int mask1, int mask2) -{ - struct ioc3_port *port = get_ioc3_port(the_port); - uint32_t shadow; - int spiniter = 0; - char mcr; - - if (!port) - return -1; - - /* Pause the DMA interface if necessary */ - if (port->ip_sscr & SSCR_DMA_EN) { - writel(port->ip_sscr | SSCR_DMA_PAUSE, - &port->ip_serial_regs->sscr); - while ((readl(&port->ip_serial_regs->sscr) - & SSCR_PAUSE_STATE) == 0) { - spiniter++; - if (spiniter > MAXITER) - return -1; - } - } - shadow = readl(&port->ip_serial_regs->shadow); - mcr = (shadow & 0xff000000) >> 24; - - /* Set new value */ - mcr |= mask1; - shadow |= mask2; - writeb(mcr, &port->ip_uart_regs->iu_mcr); - writel(shadow, &port->ip_serial_regs->shadow); - - /* Re-enable the DMA interface if necessary */ - if (port->ip_sscr & SSCR_DMA_EN) { - writel(port->ip_sscr, &port->ip_serial_regs->sscr); - } - return 0; -} - -/** - * ioc3_set_proto - set the protocol for the port - * @port: port to use - * @proto: protocol to use - */ -static int ioc3_set_proto(struct ioc3_port *port, int proto) -{ - struct port_hooks *hooks = port->ip_hooks; - - switch (proto) { - default: - case PROTO_RS232: - /* Clear the appropriate GIO pin */ - DPRINT_CONFIG(("%s: rs232\n", __func__)); - writel(0, (&port->ip_idd->vma->gppr[0] - + hooks->rs422_select_pin)); - break; - - case PROTO_RS422: - /* Set the appropriate GIO pin */ - DPRINT_CONFIG(("%s: rs422\n", __func__)); - writel(1, (&port->ip_idd->vma->gppr[0] - + hooks->rs422_select_pin)); - break; - } - return 0; -} - -/** - * transmit_chars - upper level write, called with the_port->lock - * @the_port: port to write - */ -static void transmit_chars(struct uart_port *the_port) -{ - int xmit_count, tail, head; - int result; - char *start; - struct tty_struct *tty; - struct ioc3_port *port = get_ioc3_port(the_port); - struct uart_state *state; - - if (!the_port) - return; - if (!port) - return; - - state = the_port->state; - tty = state->port.tty; - - if (uart_circ_empty(&state->xmit) || uart_tx_stopped(the_port)) { - /* Nothing to do or hw stopped */ - set_notification(port, N_ALL_OUTPUT, 0); - return; - } - - head = state->xmit.head; - tail = state->xmit.tail; - start = (char *)&state->xmit.buf[tail]; - - /* write out all the data or until the end of the buffer */ - xmit_count = (head < tail) ? (UART_XMIT_SIZE - tail) : (head - tail); - if (xmit_count > 0) { - result = do_write(port, start, xmit_count); - if (result > 0) { - /* booking */ - xmit_count -= result; - the_port->icount.tx += result; - /* advance the pointers */ - tail += result; - tail &= UART_XMIT_SIZE - 1; - state->xmit.tail = tail; - start = (char *)&state->xmit.buf[tail]; - } - } - if (uart_circ_chars_pending(&state->xmit) < WAKEUP_CHARS) - uart_write_wakeup(the_port); - - if (uart_circ_empty(&state->xmit)) { - set_notification(port, N_OUTPUT_LOWAT, 0); - } else { - set_notification(port, N_OUTPUT_LOWAT, 1); - } -} - -/** - * ioc3_change_speed - change the speed of the port - * @the_port: port to change - * @new_termios: new termios settings - * @old_termios: old termios settings - */ -static void -ioc3_change_speed(struct uart_port *the_port, - struct ktermios *new_termios, struct ktermios *old_termios) -{ - struct ioc3_port *port = get_ioc3_port(the_port); - unsigned int cflag, iflag; - int baud; - int new_parity = 0, new_parity_enable = 0, new_stop = 0, new_data = 8; - struct uart_state *state = the_port->state; - - cflag = new_termios->c_cflag; - iflag = new_termios->c_iflag; - - switch (cflag & CSIZE) { - case CS5: - new_data = 5; - break; - case CS6: - new_data = 6; - break; - case CS7: - new_data = 7; - break; - case CS8: - new_data = 8; - break; - default: - /* cuz we always need a default ... */ - new_data = 5; - break; - } - if (cflag & CSTOPB) { - new_stop = 1; - } - if (cflag & PARENB) { - new_parity_enable = 1; - if (cflag & PARODD) - new_parity = 1; - } - baud = uart_get_baud_rate(the_port, new_termios, old_termios, - MIN_BAUD_SUPPORTED, MAX_BAUD_SUPPORTED); - DPRINT_CONFIG(("%s: returned baud %d for line %d\n", __func__, baud, - the_port->line)); - - if (!the_port->fifosize) - the_port->fifosize = FIFO_SIZE; - uart_update_timeout(the_port, cflag, baud); - - the_port->ignore_status_mask = N_ALL_INPUT; - - state->port.low_latency = 1; - - if (iflag & IGNPAR) - the_port->ignore_status_mask &= ~(N_PARITY_ERROR - | N_FRAMING_ERROR); - if (iflag & IGNBRK) { - the_port->ignore_status_mask &= ~N_BREAK; - if (iflag & IGNPAR) - the_port->ignore_status_mask &= ~N_OVERRUN_ERROR; - } - if (!(cflag & CREAD)) { - /* ignore everything */ - the_port->ignore_status_mask &= ~N_DATA_READY; - } - - if (cflag & CRTSCTS) { - /* enable hardware flow control */ - port->ip_sscr |= SSCR_HFC_EN; - } - else { - /* disable hardware flow control */ - port->ip_sscr &= ~SSCR_HFC_EN; - } - writel(port->ip_sscr, &port->ip_serial_regs->sscr); - - /* Set the configuration and proper notification call */ - DPRINT_CONFIG(("%s : port 0x%p line %d cflag 0%o " - "config_port(baud %d data %d stop %d penable %d " - " parity %d), notification 0x%x\n", - __func__, (void *)port, the_port->line, cflag, baud, - new_data, new_stop, new_parity_enable, new_parity, - the_port->ignore_status_mask)); - - if ((config_port(port, baud, /* baud */ - new_data, /* byte size */ - new_stop, /* stop bits */ - new_parity_enable, /* set parity */ - new_parity)) >= 0) { /* parity 1==odd */ - set_notification(port, the_port->ignore_status_mask, 1); - } -} - -/** - * ic3_startup_local - Start up the serial port - returns >= 0 if no errors - * @the_port: Port to operate on - */ -static inline int ic3_startup_local(struct uart_port *the_port) -{ - struct ioc3_port *port; - - if (!the_port) { - NOT_PROGRESS(); - return -1; - } - - port = get_ioc3_port(the_port); - if (!port) { - NOT_PROGRESS(); - return -1; - } - - local_open(port); - - /* set the protocol */ - ioc3_set_proto(port, IS_RS232(the_port->line) ? PROTO_RS232 : - PROTO_RS422); - return 0; -} - -/* - * ioc3_cb_output_lowat - called when the output low water mark is hit - * @port: port to output - */ -static void ioc3_cb_output_lowat(struct ioc3_port *port) -{ - unsigned long pflags; - - /* the_port->lock is set on the call here */ - if (port->ip_port) { - spin_lock_irqsave(&port->ip_port->lock, pflags); - transmit_chars(port->ip_port); - spin_unlock_irqrestore(&port->ip_port->lock, pflags); - } -} - -/* - * ioc3_cb_post_ncs - called for some basic errors - * @port: port to use - * @ncs: event - */ -static void ioc3_cb_post_ncs(struct uart_port *the_port, int ncs) -{ - struct uart_icount *icount; - - icount = &the_port->icount; - - if (ncs & NCS_BREAK) - icount->brk++; - if (ncs & NCS_FRAMING) - icount->frame++; - if (ncs & NCS_OVERRUN) - icount->overrun++; - if (ncs & NCS_PARITY) - icount->parity++; -} - -/** - * do_read - Read in bytes from the port. Return the number of bytes - * actually read. - * @the_port: port to use - * @buf: place to put the stuff we read - * @len: how big 'buf' is - */ - -static inline int do_read(struct uart_port *the_port, char *buf, int len) -{ - int prod_ptr, cons_ptr, total; - struct ioc3_port *port = get_ioc3_port(the_port); - struct ring *inring; - struct ring_entry *entry; - struct port_hooks *hooks; - int byte_num; - char *sc; - int loop_counter; - - BUG_ON(!(len >= 0)); - BUG_ON(!port); - hooks = port->ip_hooks; - - /* There is a nasty timing issue in the IOC3. When the rx_timer - * expires or the rx_high condition arises, we take an interrupt. - * At some point while servicing the interrupt, we read bytes from - * the ring buffer and re-arm the rx_timer. However the rx_timer is - * not started until the first byte is received *after* it is armed, - * and any bytes pending in the rx construction buffers are not drained - * to memory until either there are 4 bytes available or the rx_timer - * expires. This leads to a potential situation where data is left - * in the construction buffers forever - 1 to 3 bytes were received - * after the interrupt was generated but before the rx_timer was - * re-armed. At that point as long as no subsequent bytes are received - * the timer will never be started and the bytes will remain in the - * construction buffer forever. The solution is to execute a DRAIN - * command after rearming the timer. This way any bytes received before - * the DRAIN will be drained to memory, and any bytes received after - * the DRAIN will start the TIMER and be drained when it expires. - * Luckily, this only needs to be done when the DMA buffer is empty - * since there is no requirement that this function return all - * available data as long as it returns some. - */ - /* Re-arm the timer */ - - writel(port->ip_rx_cons | SRCIR_ARM, &port->ip_serial_regs->srcir); - - prod_ptr = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK; - cons_ptr = port->ip_rx_cons; - - if (prod_ptr == cons_ptr) { - int reset_dma = 0; - - /* Input buffer appears empty, do a flush. */ - - /* DMA must be enabled for this to work. */ - if (!(port->ip_sscr & SSCR_DMA_EN)) { - port->ip_sscr |= SSCR_DMA_EN; - reset_dma = 1; - } - - /* Potential race condition: we must reload the srpir after - * issuing the drain command, otherwise we could think the rx - * buffer is empty, then take a very long interrupt, and when - * we come back it's full and we wait forever for the drain to - * complete. - */ - writel(port->ip_sscr | SSCR_RX_DRAIN, - &port->ip_serial_regs->sscr); - prod_ptr = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK; - - /* We must not wait for the DRAIN to complete unless there are - * at least 8 bytes (2 ring entries) available to receive the - * data otherwise the DRAIN will never complete and we'll - * deadlock here. - * In fact, to make things easier, I'll just ignore the flush if - * there is any data at all now available. - */ - if (prod_ptr == cons_ptr) { - loop_counter = 0; - while (readl(&port->ip_serial_regs->sscr) & - SSCR_RX_DRAIN) { - loop_counter++; - if (loop_counter > MAXITER) - return -1; - } - - /* SIGH. We have to reload the prod_ptr *again* since - * the drain may have caused it to change - */ - prod_ptr = readl(&port->ip_serial_regs->srpir) - & PROD_CONS_MASK; - } - if (reset_dma) { - port->ip_sscr &= ~SSCR_DMA_EN; - writel(port->ip_sscr, &port->ip_serial_regs->sscr); - } - } - inring = port->ip_inring; - port->ip_flags &= ~READ_ABORTED; - - total = 0; - loop_counter = 0xfffff; /* to avoid hangs */ - - /* Grab bytes from the hardware */ - while ((prod_ptr != cons_ptr) && (len > 0)) { - entry = (struct ring_entry *)((caddr_t) inring + cons_ptr); - - if (loop_counter-- <= 0) { - printk(KERN_WARNING "IOC3 serial: " - "possible hang condition/" - "port stuck on read (line %d).\n", - the_port->line); - break; - } - - /* According to the producer pointer, this ring entry - * must contain some data. But if the PIO happened faster - * than the DMA, the data may not be available yet, so let's - * wait until it arrives. - */ - if ((entry->ring_allsc & RING_ANY_VALID) == 0) { - /* Indicate the read is aborted so we don't disable - * the interrupt thinking that the consumer is - * congested. - */ - port->ip_flags |= READ_ABORTED; - len = 0; - break; - } - - /* Load the bytes/status out of the ring entry */ - for (byte_num = 0; byte_num < 4 && len > 0; byte_num++) { - sc = &(entry->ring_sc[byte_num]); - - /* Check for change in modem state or overrun */ - if ((*sc & RXSB_MODEM_VALID) - && (port->ip_notify & N_DDCD)) { - /* Notify upper layer if DCD dropped */ - if ((port->ip_flags & DCD_ON) - && !(*sc & RXSB_DCD)) { - /* If we have already copied some data, - * return it. We'll pick up the carrier - * drop on the next pass. That way we - * don't throw away the data that has - * already been copied back to - * the caller's buffer. - */ - if (total > 0) { - len = 0; - break; - } - port->ip_flags &= ~DCD_ON; - - /* Turn off this notification so the - * carrier drop protocol won't see it - * again when it does a read. - */ - *sc &= ~RXSB_MODEM_VALID; - - /* To keep things consistent, we need - * to update the consumer pointer so - * the next reader won't come in and - * try to read the same ring entries - * again. This must be done here before - * the dcd change. - */ - - if ((entry->ring_allsc & RING_ANY_VALID) - == 0) { - cons_ptr += (int)sizeof - (struct ring_entry); - cons_ptr &= PROD_CONS_MASK; - } - writel(cons_ptr, - &port->ip_serial_regs->srcir); - port->ip_rx_cons = cons_ptr; - - /* Notify upper layer of carrier drop */ - if ((port->ip_notify & N_DDCD) - && port->ip_port) { - uart_handle_dcd_change - (port->ip_port, 0); - wake_up_interruptible - (&the_port->state-> - port.delta_msr_wait); - } - - /* If we had any data to return, we - * would have returned it above. - */ - return 0; - } - } - if (*sc & RXSB_MODEM_VALID) { - /* Notify that an input overrun occurred */ - if ((*sc & RXSB_OVERRUN) - && (port->ip_notify & N_OVERRUN_ERROR)) { - ioc3_cb_post_ncs(the_port, NCS_OVERRUN); - } - /* Don't look at this byte again */ - *sc &= ~RXSB_MODEM_VALID; - } - - /* Check for valid data or RX errors */ - if ((*sc & RXSB_DATA_VALID) && - ((*sc & (RXSB_PAR_ERR - | RXSB_FRAME_ERR | RXSB_BREAK)) - && (port->ip_notify & (N_PARITY_ERROR - | N_FRAMING_ERROR - | N_BREAK)))) { - /* There is an error condition on the next byte. - * If we have already transferred some bytes, - * we'll stop here. Otherwise if this is the - * first byte to be read, we'll just transfer - * it alone after notifying the - * upper layer of its status. - */ - if (total > 0) { - len = 0; - break; - } else { - if ((*sc & RXSB_PAR_ERR) && - (port-> - ip_notify & N_PARITY_ERROR)) { - ioc3_cb_post_ncs(the_port, - NCS_PARITY); - } - if ((*sc & RXSB_FRAME_ERR) && - (port-> - ip_notify & N_FRAMING_ERROR)) { - ioc3_cb_post_ncs(the_port, - NCS_FRAMING); - } - if ((*sc & RXSB_BREAK) - && (port->ip_notify & N_BREAK)) { - ioc3_cb_post_ncs - (the_port, NCS_BREAK); - } - len = 1; - } - } - if (*sc & RXSB_DATA_VALID) { - *sc &= ~RXSB_DATA_VALID; - *buf = entry->ring_data[byte_num]; - buf++; - len--; - total++; - } - } - - /* If we used up this entry entirely, go on to the next one, - * otherwise we must have run out of buffer space, so - * leave the consumer pointer here for the next read in case - * there are still unread bytes in this entry. - */ - if ((entry->ring_allsc & RING_ANY_VALID) == 0) { - cons_ptr += (int)sizeof(struct ring_entry); - cons_ptr &= PROD_CONS_MASK; - } - } - - /* Update consumer pointer and re-arm rx timer interrupt */ - writel(cons_ptr, &port->ip_serial_regs->srcir); - port->ip_rx_cons = cons_ptr; - - /* If we have now dipped below the rx high water mark and we have - * rx_high interrupt turned off, we can now turn it back on again. - */ - if ((port->ip_flags & INPUT_HIGH) && (((prod_ptr - cons_ptr) - & PROD_CONS_MASK) < - ((port-> - ip_sscr & - SSCR_RX_THRESHOLD) - << PROD_CONS_PTR_OFF))) { - port->ip_flags &= ~INPUT_HIGH; - enable_intrs(port, hooks->intr_rx_high); - } - return total; -} - -/** - * receive_chars - upper level read. - * @the_port: port to read from - */ -static int receive_chars(struct uart_port *the_port) -{ - unsigned char ch[MAX_CHARS]; - int read_count = 0, read_room, flip = 0; - struct uart_state *state = the_port->state; - struct ioc3_port *port = get_ioc3_port(the_port); - unsigned long pflags; - - /* Make sure all the pointers are "good" ones */ - if (!state) - return 0; - - if (!(port->ip_flags & INPUT_ENABLE)) - return 0; - - spin_lock_irqsave(&the_port->lock, pflags); - - read_count = do_read(the_port, ch, MAX_CHARS); - if (read_count > 0) { - flip = 1; - read_room = tty_insert_flip_string(&state->port, ch, - read_count); - the_port->icount.rx += read_count; - } - spin_unlock_irqrestore(&the_port->lock, pflags); - - if (flip) - tty_flip_buffer_push(&state->port); - - return read_count; -} - -/** - * ioc3uart_intr_one - lowest level (per port) interrupt handler. - * @is : submodule - * @idd: driver data - * @pending: interrupts to handle - */ - -static inline int -ioc3uart_intr_one(struct ioc3_submodule *is, - struct ioc3_driver_data *idd, - unsigned int pending) -{ - int port_num = GET_PORT_FROM_SIO_IR(pending); - struct port_hooks *hooks; - unsigned int rx_high_rd_aborted = 0; - unsigned long flags; - struct uart_port *the_port; - struct ioc3_port *port; - int loop_counter; - struct ioc3_card *card_ptr; - unsigned int sio_ir; - - card_ptr = idd->data[is->id]; - port = card_ptr->ic_port[port_num].icp_port; - hooks = port->ip_hooks; - - /* Possible race condition here: The tx_mt interrupt bit may be - * cleared without the intervention of the interrupt handler, - * e.g. by a write. If the top level interrupt handler reads a - * tx_mt, then some other processor does a write, starting up - * output, then we come in here, see the tx_mt and stop DMA, the - * output started by the other processor will hang. Thus we can - * only rely on tx_mt being legitimate if it is read while the - * port lock is held. Therefore this bit must be ignored in the - * passed in interrupt mask which was read by the top level - * interrupt handler since the port lock was not held at the time - * it was read. We can only rely on this bit being accurate if it - * is read while the port lock is held. So we'll clear it for now, - * and reload it later once we have the port lock. - */ - - sio_ir = pending & ~(hooks->intr_tx_mt); - spin_lock_irqsave(&port->ip_lock, flags); - - loop_counter = MAXITER; /* to avoid hangs */ - - do { - uint32_t shadow; - - if (loop_counter-- <= 0) { - printk(KERN_WARNING "IOC3 serial: " - "possible hang condition/" - "port stuck on interrupt (line %d).\n", - ((struct uart_port *)port->ip_port)->line); - break; - } - /* Handle a DCD change */ - if (sio_ir & hooks->intr_delta_dcd) { - ioc3_ack(is, idd, hooks->intr_delta_dcd); - shadow = readl(&port->ip_serial_regs->shadow); - - if ((port->ip_notify & N_DDCD) - && (shadow & SHADOW_DCD) - && (port->ip_port)) { - the_port = port->ip_port; - uart_handle_dcd_change(the_port, - shadow & SHADOW_DCD); - wake_up_interruptible - (&the_port->state->port.delta_msr_wait); - } else if ((port->ip_notify & N_DDCD) - && !(shadow & SHADOW_DCD)) { - /* Flag delta DCD/no DCD */ - uart_handle_dcd_change(port->ip_port, - shadow & SHADOW_DCD); - port->ip_flags |= DCD_ON; - } - } - - /* Handle a CTS change */ - if (sio_ir & hooks->intr_delta_cts) { - ioc3_ack(is, idd, hooks->intr_delta_cts); - shadow = readl(&port->ip_serial_regs->shadow); - - if ((port->ip_notify & N_DCTS) && (port->ip_port)) { - the_port = port->ip_port; - uart_handle_cts_change(the_port, shadow - & SHADOW_CTS); - wake_up_interruptible - (&the_port->state->port.delta_msr_wait); - } - } - - /* rx timeout interrupt. Must be some data available. Put this - * before the check for rx_high since servicing this condition - * may cause that condition to clear. - */ - if (sio_ir & hooks->intr_rx_timer) { - ioc3_ack(is, idd, hooks->intr_rx_timer); - if ((port->ip_notify & N_DATA_READY) - && (port->ip_port)) { - receive_chars(port->ip_port); - } - } - - /* rx high interrupt. Must be after rx_timer. */ - else if (sio_ir & hooks->intr_rx_high) { - /* Data available, notify upper layer */ - if ((port->ip_notify & N_DATA_READY) && port->ip_port) { - receive_chars(port->ip_port); - } - - /* We can't ACK this interrupt. If receive_chars didn't - * cause the condition to clear, we'll have to disable - * the interrupt until the data is drained. - * If the read was aborted, don't disable the interrupt - * as this may cause us to hang indefinitely. An - * aborted read generally means that this interrupt - * hasn't been delivered to the cpu yet anyway, even - * though we see it as asserted when we read the sio_ir. - */ - if ((sio_ir = PENDING(card_ptr, idd)) - & hooks->intr_rx_high) { - if (port->ip_flags & READ_ABORTED) { - rx_high_rd_aborted++; - } - else { - card_ptr->ic_enable &= ~hooks->intr_rx_high; - port->ip_flags |= INPUT_HIGH; - } - } - } - - /* We got a low water interrupt: notify upper layer to - * send more data. Must come before tx_mt since servicing - * this condition may cause that condition to clear. - */ - if (sio_ir & hooks->intr_tx_explicit) { - port->ip_flags &= ~LOWAT_WRITTEN; - ioc3_ack(is, idd, hooks->intr_tx_explicit); - if (port->ip_notify & N_OUTPUT_LOWAT) - ioc3_cb_output_lowat(port); - } - - /* Handle tx_mt. Must come after tx_explicit. */ - else if (sio_ir & hooks->intr_tx_mt) { - /* If we are expecting a lowat notification - * and we get to this point it probably means that for - * some reason the tx_explicit didn't work as expected - * (that can legitimately happen if the output buffer is - * filled up in just the right way). - * So send the notification now. - */ - if (port->ip_notify & N_OUTPUT_LOWAT) { - ioc3_cb_output_lowat(port); - - /* We need to reload the sio_ir since the lowat - * call may have caused another write to occur, - * clearing the tx_mt condition. - */ - sio_ir = PENDING(card_ptr, idd); - } - - /* If the tx_mt condition still persists even after the - * lowat call, we've got some work to do. - */ - if (sio_ir & hooks->intr_tx_mt) { - /* If we are not currently expecting DMA input, - * and the transmitter has just gone idle, - * there is no longer any reason for DMA, so - * disable it. - */ - if (!(port->ip_notify - & (N_DATA_READY | N_DDCD))) { - BUG_ON(!(port->ip_sscr - & SSCR_DMA_EN)); - port->ip_sscr &= ~SSCR_DMA_EN; - writel(port->ip_sscr, - &port->ip_serial_regs->sscr); - } - /* Prevent infinite tx_mt interrupt */ - card_ptr->ic_enable &= ~hooks->intr_tx_mt; - } - } - sio_ir = PENDING(card_ptr, idd); - - /* if the read was aborted and only hooks->intr_rx_high, - * clear hooks->intr_rx_high, so we do not loop forever. - */ - - if (rx_high_rd_aborted && (sio_ir == hooks->intr_rx_high)) { - sio_ir &= ~hooks->intr_rx_high; - } - } while (sio_ir & hooks->intr_all); - - spin_unlock_irqrestore(&port->ip_lock, flags); - ioc3_enable(is, idd, card_ptr->ic_enable); - return 0; -} - -/** - * ioc3uart_intr - field all serial interrupts - * @is : submodule - * @idd: driver data - * @pending: interrupts to handle - * - */ - -static int ioc3uart_intr(struct ioc3_submodule *is, - struct ioc3_driver_data *idd, - unsigned int pending) -{ - int ret = 0; - - /* - * The upper level interrupt handler sends interrupts for both ports - * here. So we need to call for each port with its interrupts. - */ - - if (pending & SIO_IR_SA) - ret |= ioc3uart_intr_one(is, idd, pending & SIO_IR_SA); - if (pending & SIO_IR_SB) - ret |= ioc3uart_intr_one(is, idd, pending & SIO_IR_SB); - - return ret; -} - -/** - * ic3_type - * @port: Port to operate with (we ignore since we only have one port) - * - */ -static const char *ic3_type(struct uart_port *the_port) -{ - if (IS_RS232(the_port->line)) - return "SGI IOC3 Serial [rs232]"; - else - return "SGI IOC3 Serial [rs422]"; -} - -/** - * ic3_tx_empty - Is the transmitter empty? - * @port: Port to operate on - * - */ -static unsigned int ic3_tx_empty(struct uart_port *the_port) -{ - unsigned int ret = 0; - struct ioc3_port *port = get_ioc3_port(the_port); - - if (readl(&port->ip_serial_regs->shadow) & SHADOW_TEMT) - ret = TIOCSER_TEMT; - return ret; -} - -/** - * ic3_stop_tx - stop the transmitter - * @port: Port to operate on - * - */ -static void ic3_stop_tx(struct uart_port *the_port) -{ - struct ioc3_port *port = get_ioc3_port(the_port); - - if (port) - set_notification(port, N_OUTPUT_LOWAT, 0); -} - -/** - * ic3_stop_rx - stop the receiver - * @port: Port to operate on - * - */ -static void ic3_stop_rx(struct uart_port *the_port) -{ - struct ioc3_port *port = get_ioc3_port(the_port); - - if (port) - port->ip_flags &= ~INPUT_ENABLE; -} - -/** - * null_void_function - * @port: Port to operate on - * - */ -static void null_void_function(struct uart_port *the_port) -{ -} - -/** - * ic3_shutdown - shut down the port - free irq and disable - * @port: port to shut down - * - */ -static void ic3_shutdown(struct uart_port *the_port) -{ - unsigned long port_flags; - struct ioc3_port *port; - struct uart_state *state; - - port = get_ioc3_port(the_port); - if (!port) - return; - - state = the_port->state; - wake_up_interruptible(&state->port.delta_msr_wait); - - spin_lock_irqsave(&the_port->lock, port_flags); - set_notification(port, N_ALL, 0); - spin_unlock_irqrestore(&the_port->lock, port_flags); -} - -/** - * ic3_set_mctrl - set control lines (dtr, rts, etc) - * @port: Port to operate on - * @mctrl: Lines to set/unset - * - */ -static void ic3_set_mctrl(struct uart_port *the_port, unsigned int mctrl) -{ - 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; - - set_mcr(the_port, mcr, SHADOW_DTR); -} - -/** - * ic3_get_mctrl - get control line info - * @port: port to operate on - * - */ -static unsigned int ic3_get_mctrl(struct uart_port *the_port) -{ - struct ioc3_port *port = get_ioc3_port(the_port); - uint32_t shadow; - unsigned int ret = 0; - - if (!port) - return 0; - - shadow = readl(&port->ip_serial_regs->shadow); - if (shadow & SHADOW_DCD) - ret |= TIOCM_CD; - if (shadow & SHADOW_DR) - ret |= TIOCM_DSR; - if (shadow & SHADOW_CTS) - ret |= TIOCM_CTS; - return ret; -} - -/** - * ic3_start_tx - Start transmitter. Called with the_port->lock - * @port: Port to operate on - * - */ -static void ic3_start_tx(struct uart_port *the_port) -{ - struct ioc3_port *port = get_ioc3_port(the_port); - - if (port) { - set_notification(port, N_OUTPUT_LOWAT, 1); - enable_intrs(port, port->ip_hooks->intr_tx_mt); - } -} - -/** - * ic3_break_ctl - handle breaks - * @port: Port to operate on - * @break_state: Break state - * - */ -static void ic3_break_ctl(struct uart_port *the_port, int break_state) -{ -} - -/** - * ic3_startup - Start up the serial port - always return 0 (We're always on) - * @port: Port to operate on - * - */ -static int ic3_startup(struct uart_port *the_port) -{ - int retval; - struct ioc3_port *port; - struct ioc3_card *card_ptr; - unsigned long port_flags; - - if (!the_port) { - NOT_PROGRESS(); - return -ENODEV; - } - port = get_ioc3_port(the_port); - if (!port) { - NOT_PROGRESS(); - return -ENODEV; - } - card_ptr = port->ip_card; - port->ip_port = the_port; - - if (!card_ptr) { - NOT_PROGRESS(); - return -ENODEV; - } - - /* Start up the serial port */ - spin_lock_irqsave(&the_port->lock, port_flags); - retval = ic3_startup_local(the_port); - spin_unlock_irqrestore(&the_port->lock, port_flags); - return retval; -} - -/** - * ic3_set_termios - set termios stuff - * @port: port to operate on - * @termios: New settings - * @termios: Old - * - */ -static void -ic3_set_termios(struct uart_port *the_port, - struct ktermios *termios, struct ktermios *old_termios) -{ - unsigned long port_flags; - - spin_lock_irqsave(&the_port->lock, port_flags); - ioc3_change_speed(the_port, termios, old_termios); - spin_unlock_irqrestore(&the_port->lock, port_flags); -} - -/** - * ic3_request_port - allocate resources for port - no op.... - * @port: port to operate on - * - */ -static int ic3_request_port(struct uart_port *port) -{ - return 0; -} - -/* Associate the uart functions above - given to serial core */ -static const struct uart_ops ioc3_ops = { - .tx_empty = ic3_tx_empty, - .set_mctrl = ic3_set_mctrl, - .get_mctrl = ic3_get_mctrl, - .stop_tx = ic3_stop_tx, - .start_tx = ic3_start_tx, - .stop_rx = ic3_stop_rx, - .break_ctl = ic3_break_ctl, - .startup = ic3_startup, - .shutdown = ic3_shutdown, - .set_termios = ic3_set_termios, - .type = ic3_type, - .release_port = null_void_function, - .request_port = ic3_request_port, -}; - -/* - * Boot-time initialization code - */ - -static struct uart_driver ioc3_uart = { - .owner = THIS_MODULE, - .driver_name = "ioc3_serial", - .dev_name = DEVICE_NAME, - .major = DEVICE_MAJOR, - .minor = DEVICE_MINOR, - .nr = MAX_LOGICAL_PORTS -}; - -/** - * ioc3_serial_core_attach - register with serial core - * This is done during pci probing - * @is: submodule struct for this - * @idd: handle for this card - */ -static inline int ioc3_serial_core_attach( struct ioc3_submodule *is, - struct ioc3_driver_data *idd) -{ - struct ioc3_port *port; - struct uart_port *the_port; - struct ioc3_card *card_ptr = idd->data[is->id]; - int ii, phys_port; - struct pci_dev *pdev = idd->pdev; - - DPRINT_CONFIG(("%s: attach pdev 0x%p - card_ptr 0x%p\n", - __func__, pdev, (void *)card_ptr)); - - if (!card_ptr) - return -ENODEV; - - /* once around for each logical port on this card */ - for (ii = 0; ii < LOGICAL_PORTS_PER_CARD; ii++) { - phys_port = GET_PHYSICAL_PORT(ii); - the_port = &card_ptr->ic_port[phys_port]. - icp_uart_port[GET_LOGICAL_PORT(ii)]; - port = card_ptr->ic_port[phys_port].icp_port; - port->ip_port = the_port; - - DPRINT_CONFIG(("%s: attach the_port 0x%p / port 0x%p [%d/%d]\n", - __func__, (void *)the_port, (void *)port, - phys_port, ii)); - - /* membase, iobase and mapbase just need to be non-0 */ - the_port->membase = (unsigned char __iomem *)1; - the_port->iobase = (pdev->bus->number << 16) | ii; - the_port->line = (Num_of_ioc3_cards << 2) | ii; - the_port->mapbase = 1; - the_port->type = PORT_16550A; - the_port->fifosize = FIFO_SIZE; - the_port->ops = &ioc3_ops; - the_port->irq = idd->irq_io; - the_port->dev = &pdev->dev; - - if (uart_add_one_port(&ioc3_uart, the_port) < 0) { - printk(KERN_WARNING - "%s: unable to add port %d bus %d\n", - __func__, the_port->line, pdev->bus->number); - } else { - DPRINT_CONFIG(("IOC3 serial port %d irq %d bus %d\n", - the_port->line, the_port->irq, pdev->bus->number)); - } - - /* all ports are rs232 for now */ - if (IS_PHYSICAL_PORT(ii)) - ioc3_set_proto(port, PROTO_RS232); - } - return 0; -} - -/** - * ioc3uart_remove - register detach function - * @is: submodule struct for this submodule - * @idd: ioc3 driver data for this submodule - */ - -static int ioc3uart_remove(struct ioc3_submodule *is, - struct ioc3_driver_data *idd) -{ - struct ioc3_card *card_ptr = idd->data[is->id]; - struct uart_port *the_port; - struct ioc3_port *port; - int ii; - - if (card_ptr) { - for (ii = 0; ii < LOGICAL_PORTS_PER_CARD; ii++) { - the_port = &card_ptr->ic_port[GET_PHYSICAL_PORT(ii)]. - icp_uart_port[GET_LOGICAL_PORT(ii)]; - if (the_port) - uart_remove_one_port(&ioc3_uart, the_port); - port = card_ptr->ic_port[GET_PHYSICAL_PORT(ii)].icp_port; - if (port && IS_PHYSICAL_PORT(ii) - && (GET_PHYSICAL_PORT(ii) == 0)) { - pci_free_consistent(port->ip_idd->pdev, - TOTAL_RING_BUF_SIZE, - (void *)port->ip_cpu_ringbuf, - port->ip_dma_ringbuf); - kfree(port); - card_ptr->ic_port[GET_PHYSICAL_PORT(ii)]. - icp_port = NULL; - } - } - kfree(card_ptr); - idd->data[is->id] = NULL; - } - return 0; -} - -/** - * ioc3uart_probe - card probe function called from shim driver - * @is: submodule struct for this submodule - * @idd: ioc3 driver data for this card - */ - -static int -ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd) -{ - struct pci_dev *pdev = idd->pdev; - struct ioc3_card *card_ptr; - int ret = 0; - struct ioc3_port *port; - struct ioc3_port *ports[PORTS_PER_CARD]; - int phys_port; - int cnt; - - DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __func__, is, idd)); - - card_ptr = kzalloc(sizeof(struct ioc3_card), GFP_KERNEL); - if (!card_ptr) { - printk(KERN_WARNING "ioc3_attach_one" - ": unable to get memory for the IOC3\n"); - return -ENOMEM; - } - idd->data[is->id] = card_ptr; - Submodule_slot = is->id; - - writel(((UARTA_BASE >> 3) << SIO_CR_SER_A_BASE_SHIFT) | - ((UARTB_BASE >> 3) << SIO_CR_SER_B_BASE_SHIFT) | - (0xf << SIO_CR_CMD_PULSE_SHIFT), &idd->vma->sio_cr); - - pci_write_config_dword(pdev, PCI_LAT, 0xff00); - - /* Enable serial port mode select generic PIO pins as outputs */ - ioc3_gpcr_set(idd, GPCR_UARTA_MODESEL | GPCR_UARTB_MODESEL); - - /* Create port structures for each port */ - for (phys_port = 0; phys_port < PORTS_PER_CARD; phys_port++) { - port = kzalloc(sizeof(struct ioc3_port), GFP_KERNEL); - if (!port) { - printk(KERN_WARNING - "IOC3 serial memory not available for port\n"); - ret = -ENOMEM; - goto out4; - } - spin_lock_init(&port->ip_lock); - - /* we need to remember the previous ones, to point back to - * them farther down - setting up the ring buffers. - */ - ports[phys_port] = port; - - /* init to something useful */ - card_ptr->ic_port[phys_port].icp_port = port; - port->ip_is = is; - port->ip_idd = idd; - port->ip_baud = 9600; - port->ip_card = card_ptr; - port->ip_hooks = &hooks_array[phys_port]; - - /* Setup each port */ - if (phys_port == 0) { - port->ip_serial_regs = &idd->vma->port_a; - port->ip_uart_regs = &idd->vma->sregs.uarta; - - DPRINT_CONFIG(("%s : Port A ip_serial_regs 0x%p " - "ip_uart_regs 0x%p\n", - __func__, - (void *)port->ip_serial_regs, - (void *)port->ip_uart_regs)); - - /* setup ring buffers */ - port->ip_cpu_ringbuf = pci_alloc_consistent(pdev, - TOTAL_RING_BUF_SIZE, &port->ip_dma_ringbuf); - - BUG_ON(!((((int64_t) port->ip_dma_ringbuf) & - (TOTAL_RING_BUF_SIZE - 1)) == 0)); - port->ip_inring = RING(port, RX_A); - port->ip_outring = RING(port, TX_A); - DPRINT_CONFIG(("%s : Port A ip_cpu_ringbuf 0x%p " - "ip_dma_ringbuf 0x%p, ip_inring 0x%p " - "ip_outring 0x%p\n", - __func__, - (void *)port->ip_cpu_ringbuf, - (void *)port->ip_dma_ringbuf, - (void *)port->ip_inring, - (void *)port->ip_outring)); - } - else { - port->ip_serial_regs = &idd->vma->port_b; - port->ip_uart_regs = &idd->vma->sregs.uartb; - - DPRINT_CONFIG(("%s : Port B ip_serial_regs 0x%p " - "ip_uart_regs 0x%p\n", - __func__, - (void *)port->ip_serial_regs, - (void *)port->ip_uart_regs)); - - /* share the ring buffers */ - port->ip_dma_ringbuf = - ports[phys_port - 1]->ip_dma_ringbuf; - port->ip_cpu_ringbuf = - ports[phys_port - 1]->ip_cpu_ringbuf; - port->ip_inring = RING(port, RX_B); - port->ip_outring = RING(port, TX_B); - DPRINT_CONFIG(("%s : Port B ip_cpu_ringbuf 0x%p " - "ip_dma_ringbuf 0x%p, ip_inring 0x%p " - "ip_outring 0x%p\n", - __func__, - (void *)port->ip_cpu_ringbuf, - (void *)port->ip_dma_ringbuf, - (void *)port->ip_inring, - (void *)port->ip_outring)); - } - - DPRINT_CONFIG(("%s : port %d [addr 0x%p] card_ptr 0x%p", - __func__, - phys_port, (void *)port, (void *)card_ptr)); - DPRINT_CONFIG((" ip_serial_regs 0x%p ip_uart_regs 0x%p\n", - (void *)port->ip_serial_regs, - (void *)port->ip_uart_regs)); - - /* Initialize the hardware for IOC3 */ - port_init(port); - - DPRINT_CONFIG(("%s: phys_port %d port 0x%p inring 0x%p " - "outring 0x%p\n", - __func__, - phys_port, (void *)port, - (void *)port->ip_inring, - (void *)port->ip_outring)); - - } - - /* register port with the serial core */ - - ret = ioc3_serial_core_attach(is, idd); - if (ret) - goto out4; - - Num_of_ioc3_cards++; - - return ret; - - /* error exits that give back resources */ -out4: - for (cnt = 0; cnt < phys_port; cnt++) - kfree(ports[cnt]); - - kfree(card_ptr); - return ret; -} - -static struct ioc3_submodule ioc3uart_ops = { - .name = "IOC3uart", - .probe = ioc3uart_probe, - .remove = ioc3uart_remove, - /* call .intr for both ports initially */ - .irq_mask = SIO_IR_SA | SIO_IR_SB, - .intr = ioc3uart_intr, - .owner = THIS_MODULE, -}; - -/** - * ioc3_detect - module init called, - */ -static int __init ioc3uart_init(void) -{ - int ret; - - /* register with serial core */ - if ((ret = uart_register_driver(&ioc3_uart)) < 0) { - printk(KERN_WARNING - "%s: Couldn't register IOC3 uart serial driver\n", - __func__); - return ret; - } - ret = ioc3_register_submodule(&ioc3uart_ops); - if (ret) - uart_unregister_driver(&ioc3_uart); - return ret; -} - -static void __exit ioc3uart_exit(void) -{ - ioc3_unregister_submodule(&ioc3uart_ops); - uart_unregister_driver(&ioc3_uart); -} - -module_init(ioc3uart_init); -module_exit(ioc3uart_exit); - -MODULE_AUTHOR("Pat Gefre - Silicon Graphics Inc. (SGI) <pfg@sgi.com>"); -MODULE_DESCRIPTION("Serial PCI driver module for SGI IOC3 card"); -MODULE_LICENSE("GPL"); diff --git a/drivers/tty/serial/ioc4_serial.c b/drivers/tty/serial/ioc4_serial.c deleted file mode 100644 index db5b979e5a0c..000000000000 --- a/drivers/tty/serial/ioc4_serial.c +++ /dev/null @@ -1,2955 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2003-2006 Silicon Graphics, Inc. All Rights Reserved. - */ - - -/* - * This file contains a module version of the ioc4 serial driver. This - * includes all the support functions needed (support functions, etc.) - * and the serial driver itself. - */ -#include <linux/errno.h> -#include <linux/tty.h> -#include <linux/tty_flip.h> -#include <linux/serial.h> -#include <linux/circ_buf.h> -#include <linux/serial_reg.h> -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/ioc4.h> -#include <linux/serial_core.h> -#include <linux/slab.h> - -/* - * interesting things about the ioc4 - */ - -#define IOC4_NUM_SERIAL_PORTS 4 /* max ports per card */ -#define IOC4_NUM_CARDS 8 /* max cards per partition */ - -#define GET_SIO_IR(_n) (_n == 0) ? (IOC4_SIO_IR_S0) : \ - (_n == 1) ? (IOC4_SIO_IR_S1) : \ - (_n == 2) ? (IOC4_SIO_IR_S2) : \ - (IOC4_SIO_IR_S3) - -#define GET_OTHER_IR(_n) (_n == 0) ? (IOC4_OTHER_IR_S0_MEMERR) : \ - (_n == 1) ? (IOC4_OTHER_IR_S1_MEMERR) : \ - (_n == 2) ? (IOC4_OTHER_IR_S2_MEMERR) : \ - (IOC4_OTHER_IR_S3_MEMERR) - - -/* - * All IOC4 registers are 32 bits wide. - */ - -/* - * PCI Memory Space Map - */ -#define IOC4_PCI_ERR_ADDR_L 0x000 /* Low Error Address */ -#define IOC4_PCI_ERR_ADDR_VLD (0x1 << 0) -#define IOC4_PCI_ERR_ADDR_MST_ID_MSK (0xf << 1) -#define IOC4_PCI_ERR_ADDR_MST_NUM_MSK (0xe << 1) -#define IOC4_PCI_ERR_ADDR_MST_TYP_MSK (0x1 << 1) -#define IOC4_PCI_ERR_ADDR_MUL_ERR (0x1 << 5) -#define IOC4_PCI_ERR_ADDR_ADDR_MSK (0x3ffffff << 6) - -/* Interrupt types */ -#define IOC4_SIO_INTR_TYPE 0 -#define IOC4_OTHER_INTR_TYPE 1 -#define IOC4_NUM_INTR_TYPES 2 - -/* Bitmasks for IOC4_SIO_IR, IOC4_SIO_IEC, and IOC4_SIO_IES */ -#define IOC4_SIO_IR_S0_TX_MT 0x00000001 /* Serial port 0 TX empty */ -#define IOC4_SIO_IR_S0_RX_FULL 0x00000002 /* Port 0 RX buf full */ -#define IOC4_SIO_IR_S0_RX_HIGH 0x00000004 /* Port 0 RX hiwat */ -#define IOC4_SIO_IR_S0_RX_TIMER 0x00000008 /* Port 0 RX timeout */ -#define IOC4_SIO_IR_S0_DELTA_DCD 0x00000010 /* Port 0 delta DCD */ -#define IOC4_SIO_IR_S0_DELTA_CTS 0x00000020 /* Port 0 delta CTS */ -#define IOC4_SIO_IR_S0_INT 0x00000040 /* Port 0 pass-thru intr */ -#define IOC4_SIO_IR_S0_TX_EXPLICIT 0x00000080 /* Port 0 explicit TX thru */ -#define IOC4_SIO_IR_S1_TX_MT 0x00000100 /* Serial port 1 */ -#define IOC4_SIO_IR_S1_RX_FULL 0x00000200 /* */ -#define IOC4_SIO_IR_S1_RX_HIGH 0x00000400 /* */ -#define IOC4_SIO_IR_S1_RX_TIMER 0x00000800 /* */ -#define IOC4_SIO_IR_S1_DELTA_DCD 0x00001000 /* */ -#define IOC4_SIO_IR_S1_DELTA_CTS 0x00002000 /* */ -#define IOC4_SIO_IR_S1_INT 0x00004000 /* */ -#define IOC4_SIO_IR_S1_TX_EXPLICIT 0x00008000 /* */ -#define IOC4_SIO_IR_S2_TX_MT 0x00010000 /* Serial port 2 */ -#define IOC4_SIO_IR_S2_RX_FULL 0x00020000 /* */ -#define IOC4_SIO_IR_S2_RX_HIGH 0x00040000 /* */ -#define IOC4_SIO_IR_S2_RX_TIMER 0x00080000 /* */ -#define IOC4_SIO_IR_S2_DELTA_DCD 0x00100000 /* */ -#define IOC4_SIO_IR_S2_DELTA_CTS 0x00200000 /* */ -#define IOC4_SIO_IR_S2_INT 0x00400000 /* */ -#define IOC4_SIO_IR_S2_TX_EXPLICIT 0x00800000 /* */ -#define IOC4_SIO_IR_S3_TX_MT 0x01000000 /* Serial port 3 */ -#define IOC4_SIO_IR_S3_RX_FULL 0x02000000 /* */ -#define IOC4_SIO_IR_S3_RX_HIGH 0x04000000 /* */ -#define IOC4_SIO_IR_S3_RX_TIMER 0x08000000 /* */ -#define IOC4_SIO_IR_S3_DELTA_DCD 0x10000000 /* */ -#define IOC4_SIO_IR_S3_DELTA_CTS 0x20000000 /* */ -#define IOC4_SIO_IR_S3_INT 0x40000000 /* */ -#define IOC4_SIO_IR_S3_TX_EXPLICIT 0x80000000 /* */ - -/* Per device interrupt masks */ -#define IOC4_SIO_IR_S0 (IOC4_SIO_IR_S0_TX_MT | \ - IOC4_SIO_IR_S0_RX_FULL | \ - IOC4_SIO_IR_S0_RX_HIGH | \ - IOC4_SIO_IR_S0_RX_TIMER | \ - IOC4_SIO_IR_S0_DELTA_DCD | \ - IOC4_SIO_IR_S0_DELTA_CTS | \ - IOC4_SIO_IR_S0_INT | \ - IOC4_SIO_IR_S0_TX_EXPLICIT) -#define IOC4_SIO_IR_S1 (IOC4_SIO_IR_S1_TX_MT | \ - IOC4_SIO_IR_S1_RX_FULL | \ - IOC4_SIO_IR_S1_RX_HIGH | \ - IOC4_SIO_IR_S1_RX_TIMER | \ - IOC4_SIO_IR_S1_DELTA_DCD | \ - IOC4_SIO_IR_S1_DELTA_CTS | \ - IOC4_SIO_IR_S1_INT | \ - IOC4_SIO_IR_S1_TX_EXPLICIT) -#define IOC4_SIO_IR_S2 (IOC4_SIO_IR_S2_TX_MT | \ - IOC4_SIO_IR_S2_RX_FULL | \ - IOC4_SIO_IR_S2_RX_HIGH | \ - IOC4_SIO_IR_S2_RX_TIMER | \ - IOC4_SIO_IR_S2_DELTA_DCD | \ - IOC4_SIO_IR_S2_DELTA_CTS | \ - IOC4_SIO_IR_S2_INT | \ - IOC4_SIO_IR_S2_TX_EXPLICIT) -#define IOC4_SIO_IR_S3 (IOC4_SIO_IR_S3_TX_MT | \ - IOC4_SIO_IR_S3_RX_FULL | \ - IOC4_SIO_IR_S3_RX_HIGH | \ - IOC4_SIO_IR_S3_RX_TIMER | \ - IOC4_SIO_IR_S3_DELTA_DCD | \ - IOC4_SIO_IR_S3_DELTA_CTS | \ - IOC4_SIO_IR_S3_INT | \ - IOC4_SIO_IR_S3_TX_EXPLICIT) - -/* Bitmasks for IOC4_OTHER_IR, IOC4_OTHER_IEC, and IOC4_OTHER_IES */ -#define IOC4_OTHER_IR_ATA_INT 0x00000001 /* ATAPI intr pass-thru */ -#define IOC4_OTHER_IR_ATA_MEMERR 0x00000002 /* ATAPI DMA PCI error */ -#define IOC4_OTHER_IR_S0_MEMERR 0x00000004 /* Port 0 PCI error */ -#define IOC4_OTHER_IR_S1_MEMERR 0x00000008 /* Port 1 PCI error */ -#define IOC4_OTHER_IR_S2_MEMERR 0x00000010 /* Port 2 PCI error */ -#define IOC4_OTHER_IR_S3_MEMERR 0x00000020 /* Port 3 PCI error */ -#define IOC4_OTHER_IR_KBD_INT 0x00000040 /* Keyboard/mouse */ -#define IOC4_OTHER_IR_RESERVED 0x007fff80 /* Reserved */ -#define IOC4_OTHER_IR_RT_INT 0x00800000 /* INT_OUT section output */ -#define IOC4_OTHER_IR_GEN_INT 0xff000000 /* Generic pins */ - -#define IOC4_OTHER_IR_SER_MEMERR (IOC4_OTHER_IR_S0_MEMERR | IOC4_OTHER_IR_S1_MEMERR | \ - IOC4_OTHER_IR_S2_MEMERR | IOC4_OTHER_IR_S3_MEMERR) - -/* Bitmasks for IOC4_SIO_CR */ -#define IOC4_SIO_CR_CMD_PULSE_SHIFT 0 /* byte bus strobe shift */ -#define IOC4_SIO_CR_ARB_DIAG_TX0 0x00000000 -#define IOC4_SIO_CR_ARB_DIAG_RX0 0x00000010 -#define IOC4_SIO_CR_ARB_DIAG_TX1 0x00000020 -#define IOC4_SIO_CR_ARB_DIAG_RX1 0x00000030 -#define IOC4_SIO_CR_ARB_DIAG_TX2 0x00000040 -#define IOC4_SIO_CR_ARB_DIAG_RX2 0x00000050 -#define IOC4_SIO_CR_ARB_DIAG_TX3 0x00000060 -#define IOC4_SIO_CR_ARB_DIAG_RX3 0x00000070 -#define IOC4_SIO_CR_SIO_DIAG_IDLE 0x00000080 /* 0 -> active request among - serial ports (ro) */ -/* Defs for some of the generic I/O pins */ -#define IOC4_GPCR_UART0_MODESEL 0x10 /* Pin is output to port 0 - mode sel */ -#define IOC4_GPCR_UART1_MODESEL 0x20 /* Pin is output to port 1 - mode sel */ -#define IOC4_GPCR_UART2_MODESEL 0x40 /* Pin is output to port 2 - mode sel */ -#define IOC4_GPCR_UART3_MODESEL 0x80 /* Pin is output to port 3 - mode sel */ - -#define IOC4_GPPR_UART0_MODESEL_PIN 4 /* GIO pin controlling - uart 0 mode select */ -#define IOC4_GPPR_UART1_MODESEL_PIN 5 /* GIO pin controlling - uart 1 mode select */ -#define IOC4_GPPR_UART2_MODESEL_PIN 6 /* GIO pin controlling - uart 2 mode select */ -#define IOC4_GPPR_UART3_MODESEL_PIN 7 /* GIO pin controlling - uart 3 mode select */ - -/* Bitmasks for serial RX status byte */ -#define IOC4_RXSB_OVERRUN 0x01 /* Char(s) lost */ -#define IOC4_RXSB_PAR_ERR 0x02 /* Parity error */ -#define IOC4_RXSB_FRAME_ERR 0x04 /* Framing error */ -#define IOC4_RXSB_BREAK 0x08 /* Break character */ -#define IOC4_RXSB_CTS 0x10 /* State of CTS */ -#define IOC4_RXSB_DCD 0x20 /* State of DCD */ -#define IOC4_RXSB_MODEM_VALID 0x40 /* DCD, CTS, and OVERRUN are valid */ -#define IOC4_RXSB_DATA_VALID 0x80 /* Data byte, FRAME_ERR PAR_ERR - * & BREAK valid */ - -/* Bitmasks for serial TX control byte */ -#define IOC4_TXCB_INT_WHEN_DONE 0x20 /* Interrupt after this byte is sent */ -#define IOC4_TXCB_INVALID 0x00 /* Byte is invalid */ -#define IOC4_TXCB_VALID 0x40 /* Byte is valid */ -#define IOC4_TXCB_MCR 0x80 /* Data<7:0> to modem control reg */ -#define IOC4_TXCB_DELAY 0xc0 /* Delay data<7:0> mSec */ - -/* Bitmasks for IOC4_SBBR_L */ -#define IOC4_SBBR_L_SIZE 0x00000001 /* 0 == 1KB rings, 1 == 4KB rings */ - -/* Bitmasks for IOC4_SSCR_<3:0> */ -#define IOC4_SSCR_RX_THRESHOLD 0x000001ff /* Hiwater mark */ -#define IOC4_SSCR_TX_TIMER_BUSY 0x00010000 /* TX timer in progress */ -#define IOC4_SSCR_HFC_EN 0x00020000 /* Hardware flow control enabled */ -#define IOC4_SSCR_RX_RING_DCD 0x00040000 /* Post RX record on delta-DCD */ -#define IOC4_SSCR_RX_RING_CTS 0x00080000 /* Post RX record on delta-CTS */ -#define IOC4_SSCR_DIAG 0x00200000 /* Bypass clock divider for sim */ -#define IOC4_SSCR_RX_DRAIN 0x08000000 /* Drain RX buffer to memory */ -#define IOC4_SSCR_DMA_EN 0x10000000 /* Enable ring buffer DMA */ -#define IOC4_SSCR_DMA_PAUSE 0x20000000 /* Pause DMA */ -#define IOC4_SSCR_PAUSE_STATE 0x40000000 /* Sets when PAUSE takes effect */ -#define IOC4_SSCR_RESET 0x80000000 /* Reset DMA channels */ - -/* All producer/consumer pointers are the same bitfield */ -#define IOC4_PROD_CONS_PTR_4K 0x00000ff8 /* For 4K buffers */ -#define IOC4_PROD_CONS_PTR_1K 0x000003f8 /* For 1K buffers */ -#define IOC4_PROD_CONS_PTR_OFF 3 - -/* Bitmasks for IOC4_SRCIR_<3:0> */ -#define IOC4_SRCIR_ARM 0x80000000 /* Arm RX timer */ - -/* Bitmasks for IOC4_SHADOW_<3:0> */ -#define IOC4_SHADOW_DR 0x00000001 /* Data ready */ -#define IOC4_SHADOW_OE 0x00000002 /* Overrun error */ -#define IOC4_SHADOW_PE 0x00000004 /* Parity error */ -#define IOC4_SHADOW_FE 0x00000008 /* Framing error */ -#define IOC4_SHADOW_BI 0x00000010 /* Break interrupt */ -#define IOC4_SHADOW_THRE 0x00000020 /* Xmit holding register empty */ -#define IOC4_SHADOW_TEMT 0x00000040 /* Xmit shift register empty */ -#define IOC4_SHADOW_RFCE 0x00000080 /* Char in RX fifo has an error */ -#define IOC4_SHADOW_DCTS 0x00010000 /* Delta clear to send */ -#define IOC4_SHADOW_DDCD 0x00080000 /* Delta data carrier detect */ -#define IOC4_SHADOW_CTS 0x00100000 /* Clear to send */ -#define IOC4_SHADOW_DCD 0x00800000 /* Data carrier detect */ -#define IOC4_SHADOW_DTR 0x01000000 /* Data terminal ready */ -#define IOC4_SHADOW_RTS 0x02000000 /* Request to send */ -#define IOC4_SHADOW_OUT1 0x04000000 /* 16550 OUT1 bit */ -#define IOC4_SHADOW_OUT2 0x08000000 /* 16550 OUT2 bit */ -#define IOC4_SHADOW_LOOP 0x10000000 /* Loopback enabled */ - -/* Bitmasks for IOC4_SRTR_<3:0> */ -#define IOC4_SRTR_CNT 0x00000fff /* Reload value for RX timer */ -#define IOC4_SRTR_CNT_VAL 0x0fff0000 /* Current value of RX timer */ -#define IOC4_SRTR_CNT_VAL_SHIFT 16 -#define IOC4_SRTR_HZ 16000 /* SRTR clock frequency */ - -/* Serial port register map used for DMA and PIO serial I/O */ -struct ioc4_serialregs { - uint32_t sscr; - uint32_t stpir; - uint32_t stcir; - uint32_t srpir; - uint32_t srcir; - uint32_t srtr; - uint32_t shadow; -}; - -/* IOC4 UART register map */ -struct ioc4_uartregs { - char i4u_lcr; - union { - char iir; /* read only */ - char fcr; /* write only */ - } u3; - union { - char ier; /* DLAB == 0 */ - char dlm; /* DLAB == 1 */ - } u2; - union { - char rbr; /* read only, DLAB == 0 */ - char thr; /* write only, DLAB == 0 */ - char dll; /* DLAB == 1 */ - } u1; - char i4u_scr; - char i4u_msr; - char i4u_lsr; - char i4u_mcr; -}; - -/* short names */ -#define i4u_dll u1.dll -#define i4u_ier u2.ier -#define i4u_dlm u2.dlm -#define i4u_fcr u3.fcr - -/* Serial port registers used for DMA serial I/O */ -struct ioc4_serial { - uint32_t sbbr01_l; - uint32_t sbbr01_h; - uint32_t sbbr23_l; - uint32_t sbbr23_h; - - struct ioc4_serialregs port_0; - struct ioc4_serialregs port_1; - struct ioc4_serialregs port_2; - struct ioc4_serialregs port_3; - struct ioc4_uartregs uart_0; - struct ioc4_uartregs uart_1; - struct ioc4_uartregs uart_2; - struct ioc4_uartregs uart_3; -}; - -/* UART clock speed */ -#define IOC4_SER_XIN_CLK_66 66666667 -#define IOC4_SER_XIN_CLK_33 33333333 - -#define IOC4_W_IES 0 -#define IOC4_W_IEC 1 - -typedef void ioc4_intr_func_f(void *, uint32_t); -typedef ioc4_intr_func_f *ioc4_intr_func_t; - -static unsigned int Num_of_ioc4_cards; - -/* defining this will get you LOTS of great debug info */ -//#define DEBUG_INTERRUPTS -#define DPRINT_CONFIG(_x...) ; -//#define DPRINT_CONFIG(_x...) printk _x - -/* number of characters left in xmit buffer before we ask for more */ -#define WAKEUP_CHARS 256 - -/* number of characters we want to transmit to the lower level at a time */ -#define IOC4_MAX_CHARS 256 -#define IOC4_FIFO_CHARS 255 - -/* Device name we're using */ -#define DEVICE_NAME_RS232 "ttyIOC" -#define DEVICE_NAME_RS422 "ttyAIOC" -#define DEVICE_MAJOR 204 -#define DEVICE_MINOR_RS232 50 -#define DEVICE_MINOR_RS422 84 - - -/* register offsets */ -#define IOC4_SERIAL_OFFSET 0x300 - -/* flags for next_char_state */ -#define NCS_BREAK 0x1 -#define NCS_PARITY 0x2 -#define NCS_FRAMING 0x4 -#define NCS_OVERRUN 0x8 - -/* cause we need SOME parameters ... */ -#define MIN_BAUD_SUPPORTED 1200 -#define MAX_BAUD_SUPPORTED 115200 - -/* protocol types supported */ -#define PROTO_RS232 3 -#define PROTO_RS422 7 - -/* Notification types */ -#define N_DATA_READY 0x01 -#define N_OUTPUT_LOWAT 0x02 -#define N_BREAK 0x04 -#define N_PARITY_ERROR 0x08 -#define N_FRAMING_ERROR 0x10 -#define N_OVERRUN_ERROR 0x20 -#define N_DDCD 0x40 -#define N_DCTS 0x80 - -#define N_ALL_INPUT (N_DATA_READY | N_BREAK | \ - N_PARITY_ERROR | N_FRAMING_ERROR | \ - N_OVERRUN_ERROR | N_DDCD | N_DCTS) - -#define N_ALL_OUTPUT N_OUTPUT_LOWAT - -#define N_ALL_ERRORS (N_PARITY_ERROR | N_FRAMING_ERROR | N_OVERRUN_ERROR) - -#define N_ALL (N_DATA_READY | N_OUTPUT_LOWAT | N_BREAK | \ - N_PARITY_ERROR | N_FRAMING_ERROR | \ - N_OVERRUN_ERROR | N_DDCD | N_DCTS) - -#define SER_DIVISOR(_x, clk) (((clk) + (_x) * 8) / ((_x) * 16)) -#define DIVISOR_TO_BAUD(div, clk) ((clk) / 16 / (div)) - -/* Some masks */ -#define LCR_MASK_BITS_CHAR (UART_LCR_WLEN5 | UART_LCR_WLEN6 \ - | UART_LCR_WLEN7 | UART_LCR_WLEN8) -#define LCR_MASK_STOP_BITS (UART_LCR_STOP) - -#define PENDING(_p) (readl(&(_p)->ip_mem->sio_ir.raw) & _p->ip_ienb) -#define READ_SIO_IR(_p) readl(&(_p)->ip_mem->sio_ir.raw) - -/* Default to 4k buffers */ -#ifdef IOC4_1K_BUFFERS -#define RING_BUF_SIZE 1024 -#define IOC4_BUF_SIZE_BIT 0 -#define PROD_CONS_MASK IOC4_PROD_CONS_PTR_1K -#else -#define RING_BUF_SIZE 4096 -#define IOC4_BUF_SIZE_BIT IOC4_SBBR_L_SIZE -#define PROD_CONS_MASK IOC4_PROD_CONS_PTR_4K -#endif - -#define TOTAL_RING_BUF_SIZE (RING_BUF_SIZE * 4) - -/* - * This is the entry saved by the driver - one per card - */ - -#define UART_PORT_MIN 0 -#define UART_PORT_RS232 UART_PORT_MIN -#define UART_PORT_RS422 1 -#define UART_PORT_COUNT 2 /* one for each mode */ - -struct ioc4_control { - int ic_irq; - struct { - /* uart ports are allocated here - 1 for rs232, 1 for rs422 */ - struct uart_port icp_uart_port[UART_PORT_COUNT]; - /* Handy reference material */ - struct ioc4_port *icp_port; - } ic_port[IOC4_NUM_SERIAL_PORTS]; - struct ioc4_soft *ic_soft; -}; - -/* - * per-IOC4 data structure - */ -#define MAX_IOC4_INTR_ENTS (8 * sizeof(uint32_t)) -struct ioc4_soft { - struct ioc4_misc_regs __iomem *is_ioc4_misc_addr; - struct ioc4_serial __iomem *is_ioc4_serial_addr; - - /* Each interrupt type has an entry in the array */ - struct ioc4_intr_type { - - /* - * Each in-use entry in this array contains at least - * one nonzero bit in sd_bits; no two entries in this - * array have overlapping sd_bits values. - */ - struct ioc4_intr_info { - uint32_t sd_bits; - ioc4_intr_func_f *sd_intr; - void *sd_info; - } is_intr_info[MAX_IOC4_INTR_ENTS]; - - /* Number of entries active in the above array */ - atomic_t is_num_intrs; - } is_intr_type[IOC4_NUM_INTR_TYPES]; - - /* is_ir_lock must be held while - * modifying sio_ie values, so - * we can be sure that sio_ie is - * not changing when we read it - * along with sio_ir. - */ - spinlock_t is_ir_lock; /* SIO_IE[SC] mod lock */ -}; - -/* Local port info for each IOC4 serial ports */ -struct ioc4_port { - struct uart_port *ip_port; /* current active port ptr */ - /* Ptrs for all ports */ - struct uart_port *ip_all_ports[UART_PORT_COUNT]; - /* Back ptrs for this port */ - struct ioc4_control *ip_control; - struct pci_dev *ip_pdev; - struct ioc4_soft *ip_ioc4_soft; - - /* pci mem addresses */ - struct ioc4_misc_regs __iomem *ip_mem; - struct ioc4_serial __iomem *ip_serial; - struct ioc4_serialregs __iomem *ip_serial_regs; - struct ioc4_uartregs __iomem *ip_uart_regs; - - /* Ring buffer page for this port */ - dma_addr_t ip_dma_ringbuf; - /* vaddr of ring buffer */ - struct ring_buffer *ip_cpu_ringbuf; - - /* Rings for this port */ - struct ring *ip_inring; - struct ring *ip_outring; - - /* Hook to port specific values */ - struct hooks *ip_hooks; - - spinlock_t ip_lock; - - /* Various rx/tx parameters */ - int ip_baud; - int ip_tx_lowat; - int ip_rx_timeout; - - /* Copy of notification bits */ - int ip_notify; - - /* Shadow copies of various registers so we don't need to PIO - * read them constantly - */ - uint32_t ip_ienb; /* Enabled interrupts */ - uint32_t ip_sscr; - uint32_t ip_tx_prod; - uint32_t ip_rx_cons; - int ip_pci_bus_speed; - unsigned char ip_flags; -}; - -/* tx low water mark. We need to notify the driver whenever tx is getting - * close to empty so it can refill the tx buffer and keep things going. - * Let's assume that if we interrupt 1 ms before the tx goes idle, we'll - * have no trouble getting in more chars in time (I certainly hope so). - */ -#define TX_LOWAT_LATENCY 1000 -#define TX_LOWAT_HZ (1000000 / TX_LOWAT_LATENCY) -#define TX_LOWAT_CHARS(baud) (baud / 10 / TX_LOWAT_HZ) - -/* Flags per port */ -#define INPUT_HIGH 0x01 -#define DCD_ON 0x02 -#define LOWAT_WRITTEN 0x04 -#define READ_ABORTED 0x08 -#define PORT_ACTIVE 0x10 -#define PORT_INACTIVE 0 /* This is the value when "off" */ - - -/* Since each port has different register offsets and bitmasks - * for everything, we'll store those that we need in tables so we - * don't have to be constantly checking the port we are dealing with. - */ -struct hooks { - uint32_t intr_delta_dcd; - uint32_t intr_delta_cts; - uint32_t intr_tx_mt; - uint32_t intr_rx_timer; - uint32_t intr_rx_high; - uint32_t intr_tx_explicit; - uint32_t intr_dma_error; - uint32_t intr_clear; - uint32_t intr_all; - int rs422_select_pin; -}; - -static struct hooks hooks_array[IOC4_NUM_SERIAL_PORTS] = { - /* Values for port 0 */ - { - IOC4_SIO_IR_S0_DELTA_DCD, IOC4_SIO_IR_S0_DELTA_CTS, - IOC4_SIO_IR_S0_TX_MT, IOC4_SIO_IR_S0_RX_TIMER, - IOC4_SIO_IR_S0_RX_HIGH, IOC4_SIO_IR_S0_TX_EXPLICIT, - IOC4_OTHER_IR_S0_MEMERR, - (IOC4_SIO_IR_S0_TX_MT | IOC4_SIO_IR_S0_RX_FULL | - IOC4_SIO_IR_S0_RX_HIGH | IOC4_SIO_IR_S0_RX_TIMER | - IOC4_SIO_IR_S0_DELTA_DCD | IOC4_SIO_IR_S0_DELTA_CTS | - IOC4_SIO_IR_S0_INT | IOC4_SIO_IR_S0_TX_EXPLICIT), - IOC4_SIO_IR_S0, IOC4_GPPR_UART0_MODESEL_PIN, - }, - - /* Values for port 1 */ - { - IOC4_SIO_IR_S1_DELTA_DCD, IOC4_SIO_IR_S1_DELTA_CTS, - IOC4_SIO_IR_S1_TX_MT, IOC4_SIO_IR_S1_RX_TIMER, - IOC4_SIO_IR_S1_RX_HIGH, IOC4_SIO_IR_S1_TX_EXPLICIT, - IOC4_OTHER_IR_S1_MEMERR, - (IOC4_SIO_IR_S1_TX_MT | IOC4_SIO_IR_S1_RX_FULL | - IOC4_SIO_IR_S1_RX_HIGH | IOC4_SIO_IR_S1_RX_TIMER | - IOC4_SIO_IR_S1_DELTA_DCD | IOC4_SIO_IR_S1_DELTA_CTS | - IOC4_SIO_IR_S1_INT | IOC4_SIO_IR_S1_TX_EXPLICIT), - IOC4_SIO_IR_S1, IOC4_GPPR_UART1_MODESEL_PIN, - }, - - /* Values for port 2 */ - { - IOC4_SIO_IR_S2_DELTA_DCD, IOC4_SIO_IR_S2_DELTA_CTS, - IOC4_SIO_IR_S2_TX_MT, IOC4_SIO_IR_S2_RX_TIMER, - IOC4_SIO_IR_S2_RX_HIGH, IOC4_SIO_IR_S2_TX_EXPLICIT, - IOC4_OTHER_IR_S2_MEMERR, - (IOC4_SIO_IR_S2_TX_MT | IOC4_SIO_IR_S2_RX_FULL | - IOC4_SIO_IR_S2_RX_HIGH | IOC4_SIO_IR_S2_RX_TIMER | - IOC4_SIO_IR_S2_DELTA_DCD | IOC4_SIO_IR_S2_DELTA_CTS | - IOC4_SIO_IR_S2_INT | IOC4_SIO_IR_S2_TX_EXPLICIT), - IOC4_SIO_IR_S2, IOC4_GPPR_UART2_MODESEL_PIN, - }, - - /* Values for port 3 */ - { - IOC4_SIO_IR_S3_DELTA_DCD, IOC4_SIO_IR_S3_DELTA_CTS, - IOC4_SIO_IR_S3_TX_MT, IOC4_SIO_IR_S3_RX_TIMER, - IOC4_SIO_IR_S3_RX_HIGH, IOC4_SIO_IR_S3_TX_EXPLICIT, - IOC4_OTHER_IR_S3_MEMERR, - (IOC4_SIO_IR_S3_TX_MT | IOC4_SIO_IR_S3_RX_FULL | - IOC4_SIO_IR_S3_RX_HIGH | IOC4_SIO_IR_S3_RX_TIMER | - IOC4_SIO_IR_S3_DELTA_DCD | IOC4_SIO_IR_S3_DELTA_CTS | - IOC4_SIO_IR_S3_INT | IOC4_SIO_IR_S3_TX_EXPLICIT), - IOC4_SIO_IR_S3, IOC4_GPPR_UART3_MODESEL_PIN, - } -}; - -/* A ring buffer entry */ -struct ring_entry { - union { - struct { - uint32_t alldata; - uint32_t allsc; - } all; - struct { - char data[4]; /* data bytes */ - char sc[4]; /* status/control */ - } s; - } u; -}; - -/* Test the valid bits in any of the 4 sc chars using "allsc" member */ -#define RING_ANY_VALID \ - ((uint32_t)(IOC4_RXSB_MODEM_VALID | IOC4_RXSB_DATA_VALID) * 0x01010101) - -#define ring_sc u.s.sc -#define ring_data u.s.data -#define ring_allsc u.all.allsc - -/* Number of entries per ring buffer. */ -#define ENTRIES_PER_RING (RING_BUF_SIZE / (int) sizeof(struct ring_entry)) - -/* An individual ring */ -struct ring { - struct ring_entry entries[ENTRIES_PER_RING]; -}; - -/* The whole enchilada */ -struct ring_buffer { - struct ring TX_0_OR_2; - struct ring RX_0_OR_2; - struct ring TX_1_OR_3; - struct ring RX_1_OR_3; -}; - -/* Get a ring from a port struct */ -#define RING(_p, _wh) &(((struct ring_buffer *)((_p)->ip_cpu_ringbuf))->_wh) - -/* Infinite loop detection. - */ -#define MAXITER 10000000 - -/* Prototypes */ -static void receive_chars(struct uart_port *); -static void handle_intr(void *arg, uint32_t sio_ir); - -/* - * port_is_active - determines if this port is currently active - * @port: ptr to soft struct for this port - * @uart_port: uart port to test for - */ -static inline int port_is_active(struct ioc4_port *port, - struct uart_port *uart_port) -{ - if (port) { - if ((port->ip_flags & PORT_ACTIVE) - && (port->ip_port == uart_port)) - return 1; - } - return 0; -} - - -/** - * write_ireg - write the interrupt regs - * @ioc4_soft: ptr to soft struct for this port - * @val: value to write - * @which: which register - * @type: which ireg set - */ -static inline void -write_ireg(struct ioc4_soft *ioc4_soft, uint32_t val, int which, int type) -{ - struct ioc4_misc_regs __iomem *mem = ioc4_soft->is_ioc4_misc_addr; - unsigned long flags; - - spin_lock_irqsave(&ioc4_soft->is_ir_lock, flags); - - switch (type) { - case IOC4_SIO_INTR_TYPE: - switch (which) { - case IOC4_W_IES: - writel(val, &mem->sio_ies.raw); - break; - - case IOC4_W_IEC: - writel(val, &mem->sio_iec.raw); - break; - } - break; - - case IOC4_OTHER_INTR_TYPE: - switch (which) { - case IOC4_W_IES: - writel(val, &mem->other_ies.raw); - break; - - case IOC4_W_IEC: - writel(val, &mem->other_iec.raw); - break; - } - break; - - default: - break; - } - spin_unlock_irqrestore(&ioc4_soft->is_ir_lock, flags); -} - -/** - * set_baud - Baud rate setting code - * @port: port to set - * @baud: baud rate to use - */ -static int set_baud(struct ioc4_port *port, int baud) -{ - int actual_baud; - int diff; - int lcr; - unsigned short divisor; - struct ioc4_uartregs __iomem *uart; - - divisor = SER_DIVISOR(baud, port->ip_pci_bus_speed); - if (!divisor) - return 1; - actual_baud = DIVISOR_TO_BAUD(divisor, port->ip_pci_bus_speed); - - diff = actual_baud - baud; - if (diff < 0) - diff = -diff; - - /* If we're within 1%, we've found a match */ - if (diff * 100 > actual_baud) - return 1; - - uart = port->ip_uart_regs; - lcr = readb(&uart->i4u_lcr); - writeb(lcr | UART_LCR_DLAB, &uart->i4u_lcr); - writeb((unsigned char)divisor, &uart->i4u_dll); - writeb((unsigned char)(divisor >> 8), &uart->i4u_dlm); - writeb(lcr, &uart->i4u_lcr); - return 0; -} - - -/** - * get_ioc4_port - given a uart port, return the control structure - * @port: uart port - * @set: set this port as current - */ -static struct ioc4_port *get_ioc4_port(struct uart_port *the_port, int set) -{ - struct ioc4_driver_data *idd = dev_get_drvdata(the_port->dev); - struct ioc4_control *control = idd->idd_serial_data; - struct ioc4_port *port; - int port_num, port_type; - - if (control) { - for ( port_num = 0; port_num < IOC4_NUM_SERIAL_PORTS; - port_num++ ) { - port = control->ic_port[port_num].icp_port; - if (!port) - continue; - for (port_type = UART_PORT_MIN; - port_type < UART_PORT_COUNT; - port_type++) { - if (the_port == port->ip_all_ports - [port_type]) { - /* set local copy */ - if (set) { - port->ip_port = the_port; - } - return port; - } - } - } - } - return NULL; -} - -/* The IOC4 hardware provides no atomic way to determine if interrupts - * are pending since two reads are required to do so. The handler must - * read the SIO_IR and the SIO_IES, and take the logical and of the - * two. When this value is zero, all interrupts have been serviced and - * the handler may return. - * - * This has the unfortunate "hole" that, if some other CPU or - * some other thread or some higher level interrupt manages to - * modify SIO_IE between our reads of SIO_IR and SIO_IE, we may - * think we have observed SIO_IR&SIO_IE==0 when in fact this - * condition never really occurred. - * - * To solve this, we use a simple spinlock that must be held - * whenever modifying SIO_IE; holding this lock while observing - * both SIO_IR and SIO_IE guarantees that we do not falsely - * conclude that no enabled interrupts are pending. - */ - -static inline uint32_t -pending_intrs(struct ioc4_soft *soft, int type) -{ - struct ioc4_misc_regs __iomem *mem = soft->is_ioc4_misc_addr; - unsigned long flag; - uint32_t intrs = 0; - - BUG_ON(!((type == IOC4_SIO_INTR_TYPE) - || (type == IOC4_OTHER_INTR_TYPE))); - - spin_lock_irqsave(&soft->is_ir_lock, flag); - - switch (type) { - case IOC4_SIO_INTR_TYPE: - intrs = readl(&mem->sio_ir.raw) & readl(&mem->sio_ies.raw); - break; - - case IOC4_OTHER_INTR_TYPE: - intrs = readl(&mem->other_ir.raw) & readl(&mem->other_ies.raw); - - /* Don't process any ATA interrupte */ - intrs &= ~(IOC4_OTHER_IR_ATA_INT | IOC4_OTHER_IR_ATA_MEMERR); - break; - - default: - break; - } - spin_unlock_irqrestore(&soft->is_ir_lock, flag); - return intrs; -} - -/** - * port_init - Initialize the sio and ioc4 hardware for a given port - * called per port from attach... - * @port: port to initialize - */ -static inline int port_init(struct ioc4_port *port) -{ - uint32_t sio_cr; - struct hooks *hooks = port->ip_hooks; - struct ioc4_uartregs __iomem *uart; - - /* Idle the IOC4 serial interface */ - writel(IOC4_SSCR_RESET, &port->ip_serial_regs->sscr); - - /* Wait until any pending bus activity for this port has ceased */ - do - sio_cr = readl(&port->ip_mem->sio_cr.raw); - while (!(sio_cr & IOC4_SIO_CR_SIO_DIAG_IDLE)); - - /* Finish reset sequence */ - writel(0, &port->ip_serial_regs->sscr); - - /* Once RESET is done, reload cached tx_prod and rx_cons values - * and set rings to empty by making prod == cons - */ - port->ip_tx_prod = readl(&port->ip_serial_regs->stcir) & PROD_CONS_MASK; - writel(port->ip_tx_prod, &port->ip_serial_regs->stpir); - port->ip_rx_cons = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK; - writel(port->ip_rx_cons | IOC4_SRCIR_ARM, &port->ip_serial_regs->srcir); - - /* Disable interrupts for this 16550 */ - uart = port->ip_uart_regs; - writeb(0, &uart->i4u_lcr); - writeb(0, &uart->i4u_ier); - - /* Set the default baud */ - set_baud(port, port->ip_baud); - - /* Set line control to 8 bits no parity */ - writeb(UART_LCR_WLEN8 | 0, &uart->i4u_lcr); - /* UART_LCR_STOP == 1 stop */ - - /* Enable the FIFOs */ - writeb(UART_FCR_ENABLE_FIFO, &uart->i4u_fcr); - /* then reset 16550 FIFOs */ - writeb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT, - &uart->i4u_fcr); - - /* Clear modem control register */ - writeb(0, &uart->i4u_mcr); - - /* Clear deltas in modem status register */ - readb(&uart->i4u_msr); - - /* Only do this once per port pair */ - if (port->ip_hooks == &hooks_array[0] - || port->ip_hooks == &hooks_array[2]) { - unsigned long ring_pci_addr; - uint32_t __iomem *sbbr_l; - uint32_t __iomem *sbbr_h; - - if (port->ip_hooks == &hooks_array[0]) { - sbbr_l = &port->ip_serial->sbbr01_l; - sbbr_h = &port->ip_serial->sbbr01_h; - } else { - sbbr_l = &port->ip_serial->sbbr23_l; - sbbr_h = &port->ip_serial->sbbr23_h; - } - - ring_pci_addr = (unsigned long __iomem)port->ip_dma_ringbuf; - DPRINT_CONFIG(("%s: ring_pci_addr 0x%lx\n", - __func__, ring_pci_addr)); - - writel((unsigned int)((uint64_t)ring_pci_addr >> 32), sbbr_h); - writel((unsigned int)ring_pci_addr | IOC4_BUF_SIZE_BIT, sbbr_l); - } - - /* Set the receive timeout value to 10 msec */ - writel(IOC4_SRTR_HZ / 100, &port->ip_serial_regs->srtr); - - /* Set rx threshold, enable DMA */ - /* Set high water mark at 3/4 of full ring */ - port->ip_sscr = (ENTRIES_PER_RING * 3 / 4); - writel(port->ip_sscr, &port->ip_serial_regs->sscr); - - /* Disable and clear all serial related interrupt bits */ - write_ireg(port->ip_ioc4_soft, hooks->intr_clear, - IOC4_W_IEC, IOC4_SIO_INTR_TYPE); - port->ip_ienb &= ~hooks->intr_clear; - writel(hooks->intr_clear, &port->ip_mem->sio_ir.raw); - return 0; -} - -/** - * handle_dma_error_intr - service any pending DMA error interrupts for the - * given port - 2nd level called via sd_intr - * @arg: handler arg - * @other_ir: ioc4regs - */ -static void handle_dma_error_intr(void *arg, uint32_t other_ir) -{ - struct ioc4_port *port = (struct ioc4_port *)arg; - struct hooks *hooks = port->ip_hooks; - unsigned long flags; - - spin_lock_irqsave(&port->ip_lock, flags); - - /* ACK the interrupt */ - writel(hooks->intr_dma_error, &port->ip_mem->other_ir.raw); - - if (readl(&port->ip_mem->pci_err_addr_l.raw) & IOC4_PCI_ERR_ADDR_VLD) { - printk(KERN_ERR - "PCI error address is 0x%llx, " - "master is serial port %c %s\n", - (((uint64_t)readl(&port->ip_mem->pci_err_addr_h) - << 32) - | readl(&port->ip_mem->pci_err_addr_l.raw)) - & IOC4_PCI_ERR_ADDR_ADDR_MSK, '1' + - ((char)(readl(&port->ip_mem->pci_err_addr_l.raw) & - IOC4_PCI_ERR_ADDR_MST_NUM_MSK) >> 1), - (readl(&port->ip_mem->pci_err_addr_l.raw) - & IOC4_PCI_ERR_ADDR_MST_TYP_MSK) - ? "RX" : "TX"); - - if (readl(&port->ip_mem->pci_err_addr_l.raw) - & IOC4_PCI_ERR_ADDR_MUL_ERR) { - printk(KERN_ERR - "Multiple errors occurred\n"); - } - } - spin_unlock_irqrestore(&port->ip_lock, flags); - - /* Re-enable DMA error interrupts */ - write_ireg(port->ip_ioc4_soft, hooks->intr_dma_error, IOC4_W_IES, - IOC4_OTHER_INTR_TYPE); -} - -/** - * intr_connect - interrupt connect function - * @soft: soft struct for this card - * @type: interrupt type - * @intrbits: bit pattern to set - * @intr: handler function - * @info: handler arg - */ -static void -intr_connect(struct ioc4_soft *soft, int type, - uint32_t intrbits, ioc4_intr_func_f * intr, void *info) -{ - int i; - struct ioc4_intr_info *intr_ptr; - - BUG_ON(!((type == IOC4_SIO_INTR_TYPE) - || (type == IOC4_OTHER_INTR_TYPE))); - - i = atomic_inc_return(&soft-> is_intr_type[type].is_num_intrs) - 1; - BUG_ON(!(i < MAX_IOC4_INTR_ENTS || (printk("i %d\n", i), 0))); - - /* Save off the lower level interrupt handler */ - intr_ptr = &soft->is_intr_type[type].is_intr_info[i]; - intr_ptr->sd_bits = intrbits; - intr_ptr->sd_intr = intr; - intr_ptr->sd_info = info; -} - -/** - * ioc4_intr - Top level IOC4 interrupt handler. - * @irq: irq value - * @arg: handler arg - */ - -static irqreturn_t ioc4_intr(int irq, void *arg) -{ - struct ioc4_soft *soft; - uint32_t this_ir, this_mir; - int xx, num_intrs = 0; - int intr_type; - int handled = 0; - struct ioc4_intr_info *intr_info; - - soft = arg; - for (intr_type = 0; intr_type < IOC4_NUM_INTR_TYPES; intr_type++) { - num_intrs = (int)atomic_read( - &soft->is_intr_type[intr_type].is_num_intrs); - - this_mir = this_ir = pending_intrs(soft, intr_type); - - /* Farm out the interrupt to the various drivers depending on - * which interrupt bits are set. - */ - for (xx = 0; xx < num_intrs; xx++) { - intr_info = &soft->is_intr_type[intr_type].is_intr_info[xx]; - this_mir = this_ir & intr_info->sd_bits; - if (this_mir) { - /* Disable owned interrupts, call handler */ - handled++; - write_ireg(soft, intr_info->sd_bits, IOC4_W_IEC, - intr_type); - intr_info->sd_intr(intr_info->sd_info, this_mir); - this_ir &= ~this_mir; - } - } - } -#ifdef DEBUG_INTERRUPTS - { - struct ioc4_misc_regs __iomem *mem = soft->is_ioc4_misc_addr; - unsigned long flag; - - spin_lock_irqsave(&soft->is_ir_lock, flag); - printk ("%s : %d : mem 0x%p sio_ir 0x%x sio_ies 0x%x " - "other_ir 0x%x other_ies 0x%x mask 0x%x\n", - __func__, __LINE__, - (void *)mem, readl(&mem->sio_ir.raw), - readl(&mem->sio_ies.raw), - readl(&mem->other_ir.raw), - readl(&mem->other_ies.raw), - IOC4_OTHER_IR_ATA_INT | IOC4_OTHER_IR_ATA_MEMERR); - spin_unlock_irqrestore(&soft->is_ir_lock, flag); - } -#endif - return handled ? IRQ_HANDLED : IRQ_NONE; -} - -/** - * ioc4_attach_local - Device initialization. - * Called at *_attach() time for each - * IOC4 with serial ports in the system. - * @idd: Master module data for this IOC4 - */ -static inline int ioc4_attach_local(struct ioc4_driver_data *idd) -{ - struct ioc4_port *port; - struct ioc4_port *ports[IOC4_NUM_SERIAL_PORTS]; - int port_number; - uint16_t ioc4_revid_min = 62; - uint16_t ioc4_revid; - struct pci_dev *pdev = idd->idd_pdev; - struct ioc4_control* control = idd->idd_serial_data; - struct ioc4_soft *soft = control->ic_soft; - void __iomem *ioc4_misc = idd->idd_misc_regs; - void __iomem *ioc4_serial = soft->is_ioc4_serial_addr; - - /* IOC4 firmware must be at least rev 62 */ - pci_read_config_word(pdev, PCI_COMMAND_SPECIAL, &ioc4_revid); - - printk(KERN_INFO "IOC4 firmware revision %d\n", ioc4_revid); - if (ioc4_revid < ioc4_revid_min) { - printk(KERN_WARNING - "IOC4 serial not supported on firmware rev %d, " - "please upgrade to rev %d or higher\n", - ioc4_revid, ioc4_revid_min); - return -EPERM; - } - BUG_ON(ioc4_misc == NULL); - BUG_ON(ioc4_serial == NULL); - - /* Create port structures for each port */ - for (port_number = 0; port_number < IOC4_NUM_SERIAL_PORTS; - port_number++) { - port = kzalloc(sizeof(struct ioc4_port), GFP_KERNEL); - if (!port) { - printk(KERN_WARNING - "IOC4 serial memory not available for port\n"); - goto free; - } - spin_lock_init(&port->ip_lock); - - /* we need to remember the previous ones, to point back to - * them farther down - setting up the ring buffers. - */ - ports[port_number] = port; - - /* Allocate buffers and jumpstart the hardware. */ - control->ic_port[port_number].icp_port = port; - port->ip_ioc4_soft = soft; - port->ip_pdev = pdev; - port->ip_ienb = 0; - /* Use baud rate calculations based on detected PCI - * bus speed. Simply test whether the PCI clock is - * running closer to 66MHz or 33MHz. - */ - if (idd->count_period/IOC4_EXTINT_COUNT_DIVISOR < 20) { - port->ip_pci_bus_speed = IOC4_SER_XIN_CLK_66; - } else { - port->ip_pci_bus_speed = IOC4_SER_XIN_CLK_33; - } - port->ip_baud = 9600; - port->ip_control = control; - port->ip_mem = ioc4_misc; - port->ip_serial = ioc4_serial; - - /* point to the right hook */ - port->ip_hooks = &hooks_array[port_number]; - - /* Get direct hooks to the serial regs and uart regs - * for this port - */ - switch (port_number) { - case 0: - port->ip_serial_regs = &(port->ip_serial->port_0); - port->ip_uart_regs = &(port->ip_serial->uart_0); - break; - case 1: - port->ip_serial_regs = &(port->ip_serial->port_1); - port->ip_uart_regs = &(port->ip_serial->uart_1); - break; - case 2: - port->ip_serial_regs = &(port->ip_serial->port_2); - port->ip_uart_regs = &(port->ip_serial->uart_2); - break; - default: - case 3: - port->ip_serial_regs = &(port->ip_serial->port_3); - port->ip_uart_regs = &(port->ip_serial->uart_3); - break; - } - - /* ring buffers are 1 to a pair of ports */ - if (port_number && (port_number & 1)) { - /* odd use the evens buffer */ - port->ip_dma_ringbuf = - ports[port_number - 1]->ip_dma_ringbuf; - port->ip_cpu_ringbuf = - ports[port_number - 1]->ip_cpu_ringbuf; - port->ip_inring = RING(port, RX_1_OR_3); - port->ip_outring = RING(port, TX_1_OR_3); - - } else { - if (port->ip_dma_ringbuf == 0) { - port->ip_cpu_ringbuf = pci_alloc_consistent - (pdev, TOTAL_RING_BUF_SIZE, - &port->ip_dma_ringbuf); - - } - BUG_ON(!((((int64_t)port->ip_dma_ringbuf) & - (TOTAL_RING_BUF_SIZE - 1)) == 0)); - DPRINT_CONFIG(("%s : ip_cpu_ringbuf 0x%p " - "ip_dma_ringbuf 0x%p\n", - __func__, - (void *)port->ip_cpu_ringbuf, - (void *)port->ip_dma_ringbuf)); - port->ip_inring = RING(port, RX_0_OR_2); - port->ip_outring = RING(port, TX_0_OR_2); - } - DPRINT_CONFIG(("%s : port %d [addr 0x%p] control 0x%p", - __func__, - port_number, (void *)port, (void *)control)); - DPRINT_CONFIG((" ip_serial_regs 0x%p ip_uart_regs 0x%p\n", - (void *)port->ip_serial_regs, - (void *)port->ip_uart_regs)); - - /* Initialize the hardware for IOC4 */ - port_init(port); - - DPRINT_CONFIG(("%s: port_number %d port 0x%p inring 0x%p " - "outring 0x%p\n", - __func__, - port_number, (void *)port, - (void *)port->ip_inring, - (void *)port->ip_outring)); - - /* Attach interrupt handlers */ - intr_connect(soft, IOC4_SIO_INTR_TYPE, - GET_SIO_IR(port_number), - handle_intr, port); - - intr_connect(soft, IOC4_OTHER_INTR_TYPE, - GET_OTHER_IR(port_number), - handle_dma_error_intr, port); - } - return 0; - -free: - while (port_number) - kfree(ports[--port_number]); - return -ENOMEM; -} - -/** - * enable_intrs - enable interrupts - * @port: port to enable - * @mask: mask to use - */ -static void enable_intrs(struct ioc4_port *port, uint32_t mask) -{ - struct hooks *hooks = port->ip_hooks; - - if ((port->ip_ienb & mask) != mask) { - write_ireg(port->ip_ioc4_soft, mask, IOC4_W_IES, - IOC4_SIO_INTR_TYPE); - port->ip_ienb |= mask; - } - - if (port->ip_ienb) - write_ireg(port->ip_ioc4_soft, hooks->intr_dma_error, - IOC4_W_IES, IOC4_OTHER_INTR_TYPE); -} - -/** - * local_open - local open a port - * @port: port to open - */ -static inline int local_open(struct ioc4_port *port) -{ - int spiniter = 0; - - port->ip_flags = PORT_ACTIVE; - - /* Pause the DMA interface if necessary */ - if (port->ip_sscr & IOC4_SSCR_DMA_EN) { - writel(port->ip_sscr | IOC4_SSCR_DMA_PAUSE, - &port->ip_serial_regs->sscr); - while((readl(&port->ip_serial_regs-> sscr) - & IOC4_SSCR_PAUSE_STATE) == 0) { - spiniter++; - if (spiniter > MAXITER) { - port->ip_flags = PORT_INACTIVE; - return -1; - } - } - } - - /* Reset the input fifo. If the uart received chars while the port - * was closed and DMA is not enabled, the uart may have a bunch of - * chars hanging around in its rx fifo which will not be discarded - * by rclr in the upper layer. We must get rid of them here. - */ - writeb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR, - &port->ip_uart_regs->i4u_fcr); - - writeb(UART_LCR_WLEN8, &port->ip_uart_regs->i4u_lcr); - /* UART_LCR_STOP == 1 stop */ - - /* Re-enable DMA, set default threshold to intr whenever there is - * data available. - */ - port->ip_sscr &= ~IOC4_SSCR_RX_THRESHOLD; - port->ip_sscr |= 1; /* default threshold */ - - /* Plug in the new sscr. This implicitly clears the DMA_PAUSE - * flag if it was set above - */ - writel(port->ip_sscr, &port->ip_serial_regs->sscr); - port->ip_tx_lowat = 1; - return 0; -} - -/** - * set_rx_timeout - Set rx timeout and threshold values. - * @port: port to use - * @timeout: timeout value in ticks - */ -static inline int set_rx_timeout(struct ioc4_port *port, int timeout) -{ - int threshold; - - port->ip_rx_timeout = timeout; - - /* Timeout is in ticks. Let's figure out how many chars we - * can receive at the current baud rate in that interval - * and set the rx threshold to that amount. There are 4 chars - * per ring entry, so we'll divide the number of chars that will - * arrive in timeout by 4. - * So .... timeout * baud / 10 / HZ / 4, with HZ = 100. - */ - threshold = timeout * port->ip_baud / 4000; - if (threshold == 0) - threshold = 1; /* otherwise we'll intr all the time! */ - - if ((unsigned)threshold > (unsigned)IOC4_SSCR_RX_THRESHOLD) - return 1; - - port->ip_sscr &= ~IOC4_SSCR_RX_THRESHOLD; - port->ip_sscr |= threshold; - - writel(port->ip_sscr, &port->ip_serial_regs->sscr); - - /* Now set the rx timeout to the given value - * again timeout * IOC4_SRTR_HZ / HZ - */ - timeout = timeout * IOC4_SRTR_HZ / 100; - if (timeout > IOC4_SRTR_CNT) - timeout = IOC4_SRTR_CNT; - - writel(timeout, &port->ip_serial_regs->srtr); - return 0; -} - -/** - * config_port - config the hardware - * @port: port to config - * @baud: baud rate for the port - * @byte_size: data size - * @stop_bits: number of stop bits - * @parenb: parity enable ? - * @parodd: odd parity ? - */ -static inline int -config_port(struct ioc4_port *port, - int baud, int byte_size, int stop_bits, int parenb, int parodd) -{ - char lcr, sizebits; - int spiniter = 0; - - DPRINT_CONFIG(("%s: baud %d byte_size %d stop %d parenb %d parodd %d\n", - __func__, baud, byte_size, stop_bits, parenb, parodd)); - - if (set_baud(port, baud)) - return 1; - - switch (byte_size) { - case 5: - sizebits = UART_LCR_WLEN5; - break; - case 6: - sizebits = UART_LCR_WLEN6; - break; - case 7: - sizebits = UART_LCR_WLEN7; - break; - case 8: - sizebits = UART_LCR_WLEN8; - break; - default: - return 1; - } - - /* Pause the DMA interface if necessary */ - if (port->ip_sscr & IOC4_SSCR_DMA_EN) { - writel(port->ip_sscr | IOC4_SSCR_DMA_PAUSE, - &port->ip_serial_regs->sscr); - while((readl(&port->ip_serial_regs->sscr) - & IOC4_SSCR_PAUSE_STATE) == 0) { - spiniter++; - if (spiniter > MAXITER) - return -1; - } - } - - /* Clear relevant fields in lcr */ - lcr = readb(&port->ip_uart_regs->i4u_lcr); - lcr &= ~(LCR_MASK_BITS_CHAR | UART_LCR_EPAR | - UART_LCR_PARITY | LCR_MASK_STOP_BITS); - - /* Set byte size in lcr */ - lcr |= sizebits; - - /* Set parity */ - if (parenb) { - lcr |= UART_LCR_PARITY; - if (!parodd) - lcr |= UART_LCR_EPAR; - } - - /* Set stop bits */ - if (stop_bits) - lcr |= UART_LCR_STOP /* 2 stop bits */ ; - - writeb(lcr, &port->ip_uart_regs->i4u_lcr); - - /* Re-enable the DMA interface if necessary */ - if (port->ip_sscr & IOC4_SSCR_DMA_EN) { - writel(port->ip_sscr, &port->ip_serial_regs->sscr); - } - port->ip_baud = baud; - - /* When we get within this number of ring entries of filling the - * entire ring on tx, place an EXPLICIT intr to generate a lowat - * notification when output has drained. - */ - port->ip_tx_lowat = (TX_LOWAT_CHARS(baud) + 3) / 4; - if (port->ip_tx_lowat == 0) - port->ip_tx_lowat = 1; - - set_rx_timeout(port, 2); - - return 0; -} - -/** - * do_write - Write bytes to the port. Returns the number of bytes - * actually written. Called from transmit_chars - * @port: port to use - * @buf: the stuff to write - * @len: how many bytes in 'buf' - */ -static inline int do_write(struct ioc4_port *port, char *buf, int len) -{ - int prod_ptr, cons_ptr, total = 0; - struct ring *outring; - struct ring_entry *entry; - struct hooks *hooks = port->ip_hooks; - - BUG_ON(!(len >= 0)); - - prod_ptr = port->ip_tx_prod; - cons_ptr = readl(&port->ip_serial_regs->stcir) & PROD_CONS_MASK; - outring = port->ip_outring; - - /* Maintain a 1-entry red-zone. The ring buffer is full when - * (cons - prod) % ring_size is 1. Rather than do this subtraction - * in the body of the loop, I'll do it now. - */ - cons_ptr = (cons_ptr - (int)sizeof(struct ring_entry)) & PROD_CONS_MASK; - - /* Stuff the bytes into the output */ - while ((prod_ptr != cons_ptr) && (len > 0)) { - int xx; - - /* Get 4 bytes (one ring entry) at a time */ - entry = (struct ring_entry *)((caddr_t) outring + prod_ptr); - - /* Invalidate all entries */ - entry->ring_allsc = 0; - - /* Copy in some bytes */ - for (xx = 0; (xx < 4) && (len > 0); xx++) { - entry->ring_data[xx] = *buf++; - entry->ring_sc[xx] = IOC4_TXCB_VALID; - len--; - total++; - } - - /* If we are within some small threshold of filling up the - * entire ring buffer, we must place an EXPLICIT intr here - * to generate a lowat interrupt in case we subsequently - * really do fill up the ring and the caller goes to sleep. - * No need to place more than one though. - */ - if (!(port->ip_flags & LOWAT_WRITTEN) && - ((cons_ptr - prod_ptr) & PROD_CONS_MASK) - <= port->ip_tx_lowat - * (int)sizeof(struct ring_entry)) { - port->ip_flags |= LOWAT_WRITTEN; - entry->ring_sc[0] |= IOC4_TXCB_INT_WHEN_DONE; - } - - /* Go on to next entry */ - prod_ptr += sizeof(struct ring_entry); - prod_ptr &= PROD_CONS_MASK; - } - - /* If we sent something, start DMA if necessary */ - if (total > 0 && !(port->ip_sscr & IOC4_SSCR_DMA_EN)) { - port->ip_sscr |= IOC4_SSCR_DMA_EN; - writel(port->ip_sscr, &port->ip_serial_regs->sscr); - } - - /* Store the new producer pointer. If tx is disabled, we stuff the - * data into the ring buffer, but we don't actually start tx. - */ - if (!uart_tx_stopped(port->ip_port)) { - writel(prod_ptr, &port->ip_serial_regs->stpir); - - /* If we are now transmitting, enable tx_mt interrupt so we - * can disable DMA if necessary when the tx finishes. - */ - if (total > 0) - enable_intrs(port, hooks->intr_tx_mt); - } - port->ip_tx_prod = prod_ptr; - return total; -} - -/** - * disable_intrs - disable interrupts - * @port: port to enable - * @mask: mask to use - */ -static void disable_intrs(struct ioc4_port *port, uint32_t mask) -{ - struct hooks *hooks = port->ip_hooks; - - if (port->ip_ienb & mask) { - write_ireg(port->ip_ioc4_soft, mask, IOC4_W_IEC, - IOC4_SIO_INTR_TYPE); - port->ip_ienb &= ~mask; - } - - if (!port->ip_ienb) - write_ireg(port->ip_ioc4_soft, hooks->intr_dma_error, - IOC4_W_IEC, IOC4_OTHER_INTR_TYPE); -} - -/** - * set_notification - Modify event notification - * @port: port to use - * @mask: events mask - * @set_on: set ? - */ -static int set_notification(struct ioc4_port *port, int mask, int set_on) -{ - struct hooks *hooks = port->ip_hooks; - uint32_t intrbits, sscrbits; - - BUG_ON(!mask); - - intrbits = sscrbits = 0; - - if (mask & N_DATA_READY) - intrbits |= (hooks->intr_rx_timer | hooks->intr_rx_high); - if (mask & N_OUTPUT_LOWAT) - intrbits |= hooks->intr_tx_explicit; - if (mask & N_DDCD) { - intrbits |= hooks->intr_delta_dcd; - sscrbits |= IOC4_SSCR_RX_RING_DCD; - } - if (mask & N_DCTS) - intrbits |= hooks->intr_delta_cts; - - if (set_on) { - enable_intrs(port, intrbits); - port->ip_notify |= mask; - port->ip_sscr |= sscrbits; - } else { - disable_intrs(port, intrbits); - port->ip_notify &= ~mask; - port->ip_sscr &= ~sscrbits; - } - - /* We require DMA if either DATA_READY or DDCD notification is - * currently requested. If neither of these is requested and - * there is currently no tx in progress, DMA may be disabled. - */ - if (port->ip_notify & (N_DATA_READY | N_DDCD)) - port->ip_sscr |= IOC4_SSCR_DMA_EN; - else if (!(port->ip_ienb & hooks->intr_tx_mt)) - port->ip_sscr &= ~IOC4_SSCR_DMA_EN; - - writel(port->ip_sscr, &port->ip_serial_regs->sscr); - return 0; -} - -/** - * set_mcr - set the master control reg - * @the_port: port to use - * @mask1: mcr mask - * @mask2: shadow mask - */ -static inline int set_mcr(struct uart_port *the_port, - int mask1, int mask2) -{ - struct ioc4_port *port = get_ioc4_port(the_port, 0); - uint32_t shadow; - int spiniter = 0; - char mcr; - - if (!port) - return -1; - - /* Pause the DMA interface if necessary */ - if (port->ip_sscr & IOC4_SSCR_DMA_EN) { - writel(port->ip_sscr | IOC4_SSCR_DMA_PAUSE, - &port->ip_serial_regs->sscr); - while ((readl(&port->ip_serial_regs->sscr) - & IOC4_SSCR_PAUSE_STATE) == 0) { - spiniter++; - if (spiniter > MAXITER) - return -1; - } - } - shadow = readl(&port->ip_serial_regs->shadow); - mcr = (shadow & 0xff000000) >> 24; - - /* Set new value */ - mcr |= mask1; - shadow |= mask2; - - writeb(mcr, &port->ip_uart_regs->i4u_mcr); - writel(shadow, &port->ip_serial_regs->shadow); - - /* Re-enable the DMA interface if necessary */ - if (port->ip_sscr & IOC4_SSCR_DMA_EN) { - writel(port->ip_sscr, &port->ip_serial_regs->sscr); - } - return 0; -} - -/** - * ioc4_set_proto - set the protocol for the port - * @port: port to use - * @proto: protocol to use - */ -static int ioc4_set_proto(struct ioc4_port *port, int proto) -{ - struct hooks *hooks = port->ip_hooks; - - switch (proto) { - case PROTO_RS232: - /* Clear the appropriate GIO pin */ - writel(0, (&port->ip_mem->gppr[hooks->rs422_select_pin].raw)); - break; - - case PROTO_RS422: - /* Set the appropriate GIO pin */ - writel(1, (&port->ip_mem->gppr[hooks->rs422_select_pin].raw)); - break; - - default: - return 1; - } - return 0; -} - -/** - * transmit_chars - upper level write, called with ip_lock - * @the_port: port to write - */ -static void transmit_chars(struct uart_port *the_port) -{ - int xmit_count, tail, head; - int result; - char *start; - struct tty_struct *tty; - struct ioc4_port *port = get_ioc4_port(the_port, 0); - struct uart_state *state; - - if (!the_port) - return; - if (!port) - return; - - state = the_port->state; - tty = state->port.tty; - - if (uart_circ_empty(&state->xmit) || uart_tx_stopped(the_port)) { - /* Nothing to do or hw stopped */ - set_notification(port, N_ALL_OUTPUT, 0); - return; - } - - head = state->xmit.head; - tail = state->xmit.tail; - start = (char *)&state->xmit.buf[tail]; - - /* write out all the data or until the end of the buffer */ - xmit_count = (head < tail) ? (UART_XMIT_SIZE - tail) : (head - tail); - if (xmit_count > 0) { - result = do_write(port, start, xmit_count); - if (result > 0) { - /* booking */ - xmit_count -= result; - the_port->icount.tx += result; - /* advance the pointers */ - tail += result; - tail &= UART_XMIT_SIZE - 1; - state->xmit.tail = tail; - start = (char *)&state->xmit.buf[tail]; - } - } - if (uart_circ_chars_pending(&state->xmit) < WAKEUP_CHARS) - uart_write_wakeup(the_port); - - if (uart_circ_empty(&state->xmit)) { - set_notification(port, N_OUTPUT_LOWAT, 0); - } else { - set_notification(port, N_OUTPUT_LOWAT, 1); - } -} - -/** - * ioc4_change_speed - change the speed of the port - * @the_port: port to change - * @new_termios: new termios settings - * @old_termios: old termios settings - */ -static void -ioc4_change_speed(struct uart_port *the_port, - struct ktermios *new_termios, struct ktermios *old_termios) -{ - struct ioc4_port *port = get_ioc4_port(the_port, 0); - int baud, bits; - unsigned cflag, iflag; - int new_parity = 0, new_parity_enable = 0, new_stop = 0, new_data = 8; - struct uart_state *state = the_port->state; - - cflag = new_termios->c_cflag; - iflag = new_termios->c_iflag; - - switch (cflag & CSIZE) { - case CS5: - new_data = 5; - bits = 7; - break; - case CS6: - new_data = 6; - bits = 8; - break; - case CS7: - new_data = 7; - bits = 9; - break; - case CS8: - new_data = 8; - bits = 10; - break; - default: - /* cuz we always need a default ... */ - new_data = 5; - bits = 7; - break; - } - if (cflag & CSTOPB) { - bits++; - new_stop = 1; - } - if (cflag & PARENB) { - bits++; - new_parity_enable = 1; - if (cflag & PARODD) - new_parity = 1; - } - baud = uart_get_baud_rate(the_port, new_termios, old_termios, - MIN_BAUD_SUPPORTED, MAX_BAUD_SUPPORTED); - DPRINT_CONFIG(("%s: returned baud %d\n", __func__, baud)); - - /* default is 9600 */ - if (!baud) - baud = 9600; - - if (!the_port->fifosize) - the_port->fifosize = IOC4_FIFO_CHARS; - the_port->timeout = ((the_port->fifosize * HZ * bits) / (baud / 10)); - the_port->timeout += HZ / 50; /* Add .02 seconds of slop */ - - the_port->ignore_status_mask = N_ALL_INPUT; - - state->port.low_latency = 1; - - if (iflag & IGNPAR) - the_port->ignore_status_mask &= ~(N_PARITY_ERROR - | N_FRAMING_ERROR); - if (iflag & IGNBRK) { - the_port->ignore_status_mask &= ~N_BREAK; - if (iflag & IGNPAR) - the_port->ignore_status_mask &= ~N_OVERRUN_ERROR; - } - if (!(cflag & CREAD)) { - /* ignore everything */ - the_port->ignore_status_mask &= ~N_DATA_READY; - } - - if (cflag & CRTSCTS) { - port->ip_sscr |= IOC4_SSCR_HFC_EN; - } - else { - port->ip_sscr &= ~IOC4_SSCR_HFC_EN; - } - writel(port->ip_sscr, &port->ip_serial_regs->sscr); - - /* Set the configuration and proper notification call */ - DPRINT_CONFIG(("%s : port 0x%p cflag 0%o " - "config_port(baud %d data %d stop %d p enable %d parity %d)," - " notification 0x%x\n", - __func__, (void *)port, cflag, baud, new_data, new_stop, - new_parity_enable, new_parity, the_port->ignore_status_mask)); - - if ((config_port(port, baud, /* baud */ - new_data, /* byte size */ - new_stop, /* stop bits */ - new_parity_enable, /* set parity */ - new_parity)) >= 0) { /* parity 1==odd */ - set_notification(port, the_port->ignore_status_mask, 1); - } -} - -/** - * ic4_startup_local - Start up the serial port - returns >= 0 if no errors - * @the_port: Port to operate on - */ -static inline int ic4_startup_local(struct uart_port *the_port) -{ - struct ioc4_port *port; - struct uart_state *state; - - if (!the_port) - return -1; - - port = get_ioc4_port(the_port, 0); - if (!port) - return -1; - - state = the_port->state; - - local_open(port); - - /* set the protocol - mapbase has the port type */ - ioc4_set_proto(port, the_port->mapbase); - - /* set the speed of the serial port */ - ioc4_change_speed(the_port, &state->port.tty->termios, - (struct ktermios *)0); - - return 0; -} - -/* - * ioc4_cb_output_lowat - called when the output low water mark is hit - * @the_port: port to output - */ -static void ioc4_cb_output_lowat(struct uart_port *the_port) -{ - unsigned long pflags; - - /* ip_lock is set on the call here */ - if (the_port) { - spin_lock_irqsave(&the_port->lock, pflags); - transmit_chars(the_port); - spin_unlock_irqrestore(&the_port->lock, pflags); - } -} - -/** - * handle_intr - service any interrupts for the given port - 2nd level - * called via sd_intr - * @arg: handler arg - * @sio_ir: ioc4regs - */ -static void handle_intr(void *arg, uint32_t sio_ir) -{ - struct ioc4_port *port = (struct ioc4_port *)arg; - struct hooks *hooks = port->ip_hooks; - unsigned int rx_high_rd_aborted = 0; - unsigned long flags; - struct uart_port *the_port; - int loop_counter; - - /* Possible race condition here: The tx_mt interrupt bit may be - * cleared without the intervention of the interrupt handler, - * e.g. by a write. If the top level interrupt handler reads a - * tx_mt, then some other processor does a write, starting up - * output, then we come in here, see the tx_mt and stop DMA, the - * output started by the other processor will hang. Thus we can - * only rely on tx_mt being legitimate if it is read while the - * port lock is held. Therefore this bit must be ignored in the - * passed in interrupt mask which was read by the top level - * interrupt handler since the port lock was not held at the time - * it was read. We can only rely on this bit being accurate if it - * is read while the port lock is held. So we'll clear it for now, - * and reload it later once we have the port lock. - */ - sio_ir &= ~(hooks->intr_tx_mt); - - spin_lock_irqsave(&port->ip_lock, flags); - - loop_counter = MAXITER; /* to avoid hangs */ - - do { - uint32_t shadow; - - if ( loop_counter-- <= 0 ) { - printk(KERN_WARNING "IOC4 serial: " - "possible hang condition/" - "port stuck on interrupt.\n"); - break; - } - - /* Handle a DCD change */ - if (sio_ir & hooks->intr_delta_dcd) { - /* ACK the interrupt */ - writel(hooks->intr_delta_dcd, - &port->ip_mem->sio_ir.raw); - - shadow = readl(&port->ip_serial_regs->shadow); - - if ((port->ip_notify & N_DDCD) - && (shadow & IOC4_SHADOW_DCD) - && (port->ip_port)) { - the_port = port->ip_port; - the_port->icount.dcd = 1; - wake_up_interruptible - (&the_port->state->port.delta_msr_wait); - } else if ((port->ip_notify & N_DDCD) - && !(shadow & IOC4_SHADOW_DCD)) { - /* Flag delta DCD/no DCD */ - port->ip_flags |= DCD_ON; - } - } - - /* Handle a CTS change */ - if (sio_ir & hooks->intr_delta_cts) { - /* ACK the interrupt */ - writel(hooks->intr_delta_cts, - &port->ip_mem->sio_ir.raw); - - shadow = readl(&port->ip_serial_regs->shadow); - - if ((port->ip_notify & N_DCTS) - && (port->ip_port)) { - the_port = port->ip_port; - the_port->icount.cts = - (shadow & IOC4_SHADOW_CTS) ? 1 : 0; - wake_up_interruptible - (&the_port->state->port.delta_msr_wait); - } - } - - /* rx timeout interrupt. Must be some data available. Put this - * before the check for rx_high since servicing this condition - * may cause that condition to clear. - */ - if (sio_ir & hooks->intr_rx_timer) { - /* ACK the interrupt */ - writel(hooks->intr_rx_timer, - &port->ip_mem->sio_ir.raw); - - if ((port->ip_notify & N_DATA_READY) - && (port->ip_port)) { - /* ip_lock is set on call here */ - receive_chars(port->ip_port); - } - } - - /* rx high interrupt. Must be after rx_timer. */ - else if (sio_ir & hooks->intr_rx_high) { - /* Data available, notify upper layer */ - if ((port->ip_notify & N_DATA_READY) - && port->ip_port) { - /* ip_lock is set on call here */ - receive_chars(port->ip_port); - } - - /* We can't ACK this interrupt. If receive_chars didn't - * cause the condition to clear, we'll have to disable - * the interrupt until the data is drained. - * If the read was aborted, don't disable the interrupt - * as this may cause us to hang indefinitely. An - * aborted read generally means that this interrupt - * hasn't been delivered to the cpu yet anyway, even - * though we see it as asserted when we read the sio_ir. - */ - if ((sio_ir = PENDING(port)) & hooks->intr_rx_high) { - if ((port->ip_flags & READ_ABORTED) == 0) { - port->ip_ienb &= ~hooks->intr_rx_high; - port->ip_flags |= INPUT_HIGH; - } else { - rx_high_rd_aborted++; - } - } - } - - /* We got a low water interrupt: notify upper layer to - * send more data. Must come before tx_mt since servicing - * this condition may cause that condition to clear. - */ - if (sio_ir & hooks->intr_tx_explicit) { - port->ip_flags &= ~LOWAT_WRITTEN; - - /* ACK the interrupt */ - writel(hooks->intr_tx_explicit, - &port->ip_mem->sio_ir.raw); - - if (port->ip_notify & N_OUTPUT_LOWAT) - ioc4_cb_output_lowat(port->ip_port); - } - - /* Handle tx_mt. Must come after tx_explicit. */ - else if (sio_ir & hooks->intr_tx_mt) { - /* If we are expecting a lowat notification - * and we get to this point it probably means that for - * some reason the tx_explicit didn't work as expected - * (that can legitimately happen if the output buffer is - * filled up in just the right way). - * So send the notification now. - */ - if (port->ip_notify & N_OUTPUT_LOWAT) { - ioc4_cb_output_lowat(port->ip_port); - - /* We need to reload the sio_ir since the lowat - * call may have caused another write to occur, - * clearing the tx_mt condition. - */ - sio_ir = PENDING(port); - } - - /* If the tx_mt condition still persists even after the - * lowat call, we've got some work to do. - */ - if (sio_ir & hooks->intr_tx_mt) { - - /* If we are not currently expecting DMA input, - * and the transmitter has just gone idle, - * there is no longer any reason for DMA, so - * disable it. - */ - if (!(port->ip_notify - & (N_DATA_READY | N_DDCD))) { - BUG_ON(!(port->ip_sscr - & IOC4_SSCR_DMA_EN)); - port->ip_sscr &= ~IOC4_SSCR_DMA_EN; - writel(port->ip_sscr, - &port->ip_serial_regs->sscr); - } - - /* Prevent infinite tx_mt interrupt */ - port->ip_ienb &= ~hooks->intr_tx_mt; - } - } - sio_ir = PENDING(port); - - /* if the read was aborted and only hooks->intr_rx_high, - * clear hooks->intr_rx_high, so we do not loop forever. - */ - - if (rx_high_rd_aborted && (sio_ir == hooks->intr_rx_high)) { - sio_ir &= ~hooks->intr_rx_high; - } - } while (sio_ir & hooks->intr_all); - - spin_unlock_irqrestore(&port->ip_lock, flags); - - /* Re-enable interrupts before returning from interrupt handler. - * Getting interrupted here is okay. It'll just v() our semaphore, and - * we'll come through the loop again. - */ - - write_ireg(port->ip_ioc4_soft, port->ip_ienb, IOC4_W_IES, - IOC4_SIO_INTR_TYPE); -} - -/* - * ioc4_cb_post_ncs - called for some basic errors - * @port: port to use - * @ncs: event - */ -static void ioc4_cb_post_ncs(struct uart_port *the_port, int ncs) -{ - struct uart_icount *icount; - - icount = &the_port->icount; - - if (ncs & NCS_BREAK) - icount->brk++; - if (ncs & NCS_FRAMING) - icount->frame++; - if (ncs & NCS_OVERRUN) - icount->overrun++; - if (ncs & NCS_PARITY) - icount->parity++; -} - -/** - * do_read - Read in bytes from the port. Return the number of bytes - * actually read. - * @the_port: port to use - * @buf: place to put the stuff we read - * @len: how big 'buf' is - */ - -static inline int do_read(struct uart_port *the_port, unsigned char *buf, - int len) -{ - int prod_ptr, cons_ptr, total; - struct ioc4_port *port = get_ioc4_port(the_port, 0); - struct ring *inring; - struct ring_entry *entry; - struct hooks *hooks; - int byte_num; - char *sc; - int loop_counter; - - BUG_ON(!(len >= 0)); - BUG_ON(!port); - hooks = port->ip_hooks; - - /* There is a nasty timing issue in the IOC4. When the rx_timer - * expires or the rx_high condition arises, we take an interrupt. - * At some point while servicing the interrupt, we read bytes from - * the ring buffer and re-arm the rx_timer. However the rx_timer is - * not started until the first byte is received *after* it is armed, - * and any bytes pending in the rx construction buffers are not drained - * to memory until either there are 4 bytes available or the rx_timer - * expires. This leads to a potential situation where data is left - * in the construction buffers forever - 1 to 3 bytes were received - * after the interrupt was generated but before the rx_timer was - * re-armed. At that point as long as no subsequent bytes are received - * the timer will never be started and the bytes will remain in the - * construction buffer forever. The solution is to execute a DRAIN - * command after rearming the timer. This way any bytes received before - * the DRAIN will be drained to memory, and any bytes received after - * the DRAIN will start the TIMER and be drained when it expires. - * Luckily, this only needs to be done when the DMA buffer is empty - * since there is no requirement that this function return all - * available data as long as it returns some. - */ - /* Re-arm the timer */ - writel(port->ip_rx_cons | IOC4_SRCIR_ARM, &port->ip_serial_regs->srcir); - - prod_ptr = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK; - cons_ptr = port->ip_rx_cons; - - if (prod_ptr == cons_ptr) { - int reset_dma = 0; - - /* Input buffer appears empty, do a flush. */ - - /* DMA must be enabled for this to work. */ - if (!(port->ip_sscr & IOC4_SSCR_DMA_EN)) { - port->ip_sscr |= IOC4_SSCR_DMA_EN; - reset_dma = 1; - } - - /* Potential race condition: we must reload the srpir after - * issuing the drain command, otherwise we could think the rx - * buffer is empty, then take a very long interrupt, and when - * we come back it's full and we wait forever for the drain to - * complete. - */ - writel(port->ip_sscr | IOC4_SSCR_RX_DRAIN, - &port->ip_serial_regs->sscr); - prod_ptr = readl(&port->ip_serial_regs->srpir) - & PROD_CONS_MASK; - - /* We must not wait for the DRAIN to complete unless there are - * at least 8 bytes (2 ring entries) available to receive the - * data otherwise the DRAIN will never complete and we'll - * deadlock here. - * In fact, to make things easier, I'll just ignore the flush if - * there is any data at all now available. - */ - if (prod_ptr == cons_ptr) { - loop_counter = 0; - while (readl(&port->ip_serial_regs->sscr) & - IOC4_SSCR_RX_DRAIN) { - loop_counter++; - if (loop_counter > MAXITER) - return -1; - } - - /* SIGH. We have to reload the prod_ptr *again* since - * the drain may have caused it to change - */ - prod_ptr = readl(&port->ip_serial_regs->srpir) - & PROD_CONS_MASK; - } - if (reset_dma) { - port->ip_sscr &= ~IOC4_SSCR_DMA_EN; - writel(port->ip_sscr, &port->ip_serial_regs->sscr); - } - } - inring = port->ip_inring; - port->ip_flags &= ~READ_ABORTED; - - total = 0; - loop_counter = 0xfffff; /* to avoid hangs */ - - /* Grab bytes from the hardware */ - while ((prod_ptr != cons_ptr) && (len > 0)) { - entry = (struct ring_entry *)((caddr_t)inring + cons_ptr); - - if ( loop_counter-- <= 0 ) { - printk(KERN_WARNING "IOC4 serial: " - "possible hang condition/" - "port stuck on read.\n"); - break; - } - - /* According to the producer pointer, this ring entry - * must contain some data. But if the PIO happened faster - * than the DMA, the data may not be available yet, so let's - * wait until it arrives. - */ - if ((entry->ring_allsc & RING_ANY_VALID) == 0) { - /* Indicate the read is aborted so we don't disable - * the interrupt thinking that the consumer is - * congested. - */ - port->ip_flags |= READ_ABORTED; - len = 0; - break; - } - - /* Load the bytes/status out of the ring entry */ - for (byte_num = 0; byte_num < 4 && len > 0; byte_num++) { - sc = &(entry->ring_sc[byte_num]); - - /* Check for change in modem state or overrun */ - if ((*sc & IOC4_RXSB_MODEM_VALID) - && (port->ip_notify & N_DDCD)) { - /* Notify upper layer if DCD dropped */ - - if ((port->ip_flags & DCD_ON) - && !(*sc & IOC4_RXSB_DCD)) { - - /* If we have already copied some data, - * return it. We'll pick up the carrier - * drop on the next pass. That way we - * don't throw away the data that has - * already been copied back to - * the caller's buffer. - */ - if (total > 0) { - len = 0; - break; - } - port->ip_flags &= ~DCD_ON; - - /* Turn off this notification so the - * carrier drop protocol won't see it - * again when it does a read. - */ - *sc &= ~IOC4_RXSB_MODEM_VALID; - - /* To keep things consistent, we need - * to update the consumer pointer so - * the next reader won't come in and - * try to read the same ring entries - * again. This must be done here before - * the dcd change. - */ - - if ((entry->ring_allsc & RING_ANY_VALID) - == 0) { - cons_ptr += (int)sizeof - (struct ring_entry); - cons_ptr &= PROD_CONS_MASK; - } - writel(cons_ptr, - &port->ip_serial_regs->srcir); - port->ip_rx_cons = cons_ptr; - - /* Notify upper layer of carrier drop */ - if ((port->ip_notify & N_DDCD) - && port->ip_port) { - the_port->icount.dcd = 0; - wake_up_interruptible - (&the_port->state-> - port.delta_msr_wait); - } - - /* If we had any data to return, we - * would have returned it above. - */ - return 0; - } - } - if (*sc & IOC4_RXSB_MODEM_VALID) { - /* Notify that an input overrun occurred */ - if ((*sc & IOC4_RXSB_OVERRUN) - && (port->ip_notify & N_OVERRUN_ERROR)) { - ioc4_cb_post_ncs(the_port, NCS_OVERRUN); - } - /* Don't look at this byte again */ - *sc &= ~IOC4_RXSB_MODEM_VALID; - } - - /* Check for valid data or RX errors */ - if ((*sc & IOC4_RXSB_DATA_VALID) && - ((*sc & (IOC4_RXSB_PAR_ERR - | IOC4_RXSB_FRAME_ERR - | IOC4_RXSB_BREAK)) - && (port->ip_notify & (N_PARITY_ERROR - | N_FRAMING_ERROR - | N_BREAK)))) { - /* There is an error condition on the next byte. - * If we have already transferred some bytes, - * we'll stop here. Otherwise if this is the - * first byte to be read, we'll just transfer - * it alone after notifying the - * upper layer of its status. - */ - if (total > 0) { - len = 0; - break; - } else { - if ((*sc & IOC4_RXSB_PAR_ERR) && - (port->ip_notify & N_PARITY_ERROR)) { - ioc4_cb_post_ncs(the_port, - NCS_PARITY); - } - if ((*sc & IOC4_RXSB_FRAME_ERR) && - (port->ip_notify & N_FRAMING_ERROR)){ - ioc4_cb_post_ncs(the_port, - NCS_FRAMING); - } - if ((*sc & IOC4_RXSB_BREAK) - && (port->ip_notify & N_BREAK)) { - ioc4_cb_post_ncs - (the_port, - NCS_BREAK); - } - len = 1; - } - } - if (*sc & IOC4_RXSB_DATA_VALID) { - *sc &= ~IOC4_RXSB_DATA_VALID; - *buf = entry->ring_data[byte_num]; - buf++; - len--; - total++; - } - } - - /* If we used up this entry entirely, go on to the next one, - * otherwise we must have run out of buffer space, so - * leave the consumer pointer here for the next read in case - * there are still unread bytes in this entry. - */ - if ((entry->ring_allsc & RING_ANY_VALID) == 0) { - cons_ptr += (int)sizeof(struct ring_entry); - cons_ptr &= PROD_CONS_MASK; - } - } - - /* Update consumer pointer and re-arm rx timer interrupt */ - writel(cons_ptr, &port->ip_serial_regs->srcir); - port->ip_rx_cons = cons_ptr; - - /* If we have now dipped below the rx high water mark and we have - * rx_high interrupt turned off, we can now turn it back on again. - */ - if ((port->ip_flags & INPUT_HIGH) && (((prod_ptr - cons_ptr) - & PROD_CONS_MASK) < ((port->ip_sscr & - IOC4_SSCR_RX_THRESHOLD) - << IOC4_PROD_CONS_PTR_OFF))) { - port->ip_flags &= ~INPUT_HIGH; - enable_intrs(port, hooks->intr_rx_high); - } - return total; -} - -/** - * receive_chars - upper level read. Called with ip_lock. - * @the_port: port to read from - */ -static void receive_chars(struct uart_port *the_port) -{ - unsigned char ch[IOC4_MAX_CHARS]; - int read_count, request_count = IOC4_MAX_CHARS; - struct uart_icount *icount; - struct uart_state *state = the_port->state; - unsigned long pflags; - - /* Make sure all the pointers are "good" ones */ - if (!state) - return; - - spin_lock_irqsave(&the_port->lock, pflags); - - request_count = tty_buffer_request_room(&state->port, IOC4_MAX_CHARS); - - if (request_count > 0) { - icount = &the_port->icount; - read_count = do_read(the_port, ch, request_count); - if (read_count > 0) { - tty_insert_flip_string(&state->port, ch, read_count); - icount->rx += read_count; - } - } - - spin_unlock_irqrestore(&the_port->lock, pflags); - - tty_flip_buffer_push(&state->port); -} - -/** - * ic4_type - What type of console are we? - * @port: Port to operate with (we ignore since we only have one port) - * - */ -static const char *ic4_type(struct uart_port *the_port) -{ - if (the_port->mapbase == PROTO_RS232) - return "SGI IOC4 Serial [rs232]"; - else - return "SGI IOC4 Serial [rs422]"; -} - -/** - * ic4_tx_empty - Is the transmitter empty? - * @port: Port to operate on - * - */ -static unsigned int ic4_tx_empty(struct uart_port *the_port) -{ - struct ioc4_port *port = get_ioc4_port(the_port, 0); - unsigned int ret = 0; - - if (port_is_active(port, the_port)) { - if (readl(&port->ip_serial_regs->shadow) & IOC4_SHADOW_TEMT) - ret = TIOCSER_TEMT; - } - return ret; -} - -/** - * ic4_stop_tx - stop the transmitter - * @port: Port to operate on - * - */ -static void ic4_stop_tx(struct uart_port *the_port) -{ - struct ioc4_port *port = get_ioc4_port(the_port, 0); - - if (port_is_active(port, the_port)) - set_notification(port, N_OUTPUT_LOWAT, 0); -} - -/** - * null_void_function - - * @port: Port to operate on - * - */ -static void null_void_function(struct uart_port *the_port) -{ -} - -/** - * ic4_shutdown - shut down the port - free irq and disable - * @port: Port to shut down - * - */ -static void ic4_shutdown(struct uart_port *the_port) -{ - unsigned long port_flags; - struct ioc4_port *port; - struct uart_state *state; - - port = get_ioc4_port(the_port, 0); - if (!port) - return; - - state = the_port->state; - port->ip_port = NULL; - - wake_up_interruptible(&state->port.delta_msr_wait); - - if (state->port.tty) - set_bit(TTY_IO_ERROR, &state->port.tty->flags); - - spin_lock_irqsave(&the_port->lock, port_flags); - set_notification(port, N_ALL, 0); - port->ip_flags = PORT_INACTIVE; - spin_unlock_irqrestore(&the_port->lock, port_flags); -} - -/** - * ic4_set_mctrl - set control lines (dtr, rts, etc) - * @port: Port to operate on - * @mctrl: Lines to set/unset - * - */ -static void ic4_set_mctrl(struct uart_port *the_port, unsigned int mctrl) -{ - unsigned char mcr = 0; - struct ioc4_port *port; - - port = get_ioc4_port(the_port, 0); - if (!port_is_active(port, the_port)) - return; - - 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; - - set_mcr(the_port, mcr, IOC4_SHADOW_DTR); -} - -/** - * ic4_get_mctrl - get control line info - * @port: port to operate on - * - */ -static unsigned int ic4_get_mctrl(struct uart_port *the_port) -{ - struct ioc4_port *port = get_ioc4_port(the_port, 0); - uint32_t shadow; - unsigned int ret = 0; - - if (!port_is_active(port, the_port)) - return 0; - - shadow = readl(&port->ip_serial_regs->shadow); - if (shadow & IOC4_SHADOW_DCD) - ret |= TIOCM_CAR; - if (shadow & IOC4_SHADOW_DR) - ret |= TIOCM_DSR; - if (shadow & IOC4_SHADOW_CTS) - ret |= TIOCM_CTS; - return ret; -} - -/** - * ic4_start_tx - Start transmitter, flush any output - * @port: Port to operate on - * - */ -static void ic4_start_tx(struct uart_port *the_port) -{ - struct ioc4_port *port = get_ioc4_port(the_port, 0); - - if (port_is_active(port, the_port)) { - set_notification(port, N_OUTPUT_LOWAT, 1); - enable_intrs(port, port->ip_hooks->intr_tx_mt); - } -} - -/** - * ic4_break_ctl - handle breaks - * @port: Port to operate on - * @break_state: Break state - * - */ -static void ic4_break_ctl(struct uart_port *the_port, int break_state) -{ -} - -/** - * ic4_startup - Start up the serial port - * @port: Port to operate on - * - */ -static int ic4_startup(struct uart_port *the_port) -{ - int retval; - struct ioc4_port *port; - struct ioc4_control *control; - struct uart_state *state; - unsigned long port_flags; - - if (!the_port) - return -ENODEV; - port = get_ioc4_port(the_port, 1); - if (!port) - return -ENODEV; - state = the_port->state; - - control = port->ip_control; - if (!control) { - port->ip_port = NULL; - return -ENODEV; - } - - /* Start up the serial port */ - spin_lock_irqsave(&the_port->lock, port_flags); - retval = ic4_startup_local(the_port); - spin_unlock_irqrestore(&the_port->lock, port_flags); - return retval; -} - -/** - * ic4_set_termios - set termios stuff - * @port: port to operate on - * @termios: New settings - * @termios: Old - * - */ -static void -ic4_set_termios(struct uart_port *the_port, - struct ktermios *termios, struct ktermios *old_termios) -{ - unsigned long port_flags; - - spin_lock_irqsave(&the_port->lock, port_flags); - ioc4_change_speed(the_port, termios, old_termios); - spin_unlock_irqrestore(&the_port->lock, port_flags); -} - -/** - * ic4_request_port - allocate resources for port - no op.... - * @port: port to operate on - * - */ -static int ic4_request_port(struct uart_port *port) -{ - return 0; -} - -/* Associate the uart functions above - given to serial core */ - -static const struct uart_ops ioc4_ops = { - .tx_empty = ic4_tx_empty, - .set_mctrl = ic4_set_mctrl, - .get_mctrl = ic4_get_mctrl, - .stop_tx = ic4_stop_tx, - .start_tx = ic4_start_tx, - .stop_rx = null_void_function, - .break_ctl = ic4_break_ctl, - .startup = ic4_startup, - .shutdown = ic4_shutdown, - .set_termios = ic4_set_termios, - .type = ic4_type, - .release_port = null_void_function, - .request_port = ic4_request_port, -}; - -/* - * Boot-time initialization code - */ - -static struct uart_driver ioc4_uart_rs232 = { - .owner = THIS_MODULE, - .driver_name = "ioc4_serial_rs232", - .dev_name = DEVICE_NAME_RS232, - .major = DEVICE_MAJOR, - .minor = DEVICE_MINOR_RS232, - .nr = IOC4_NUM_CARDS * IOC4_NUM_SERIAL_PORTS, -}; - -static struct uart_driver ioc4_uart_rs422 = { - .owner = THIS_MODULE, - .driver_name = "ioc4_serial_rs422", - .dev_name = DEVICE_NAME_RS422, - .major = DEVICE_MAJOR, - .minor = DEVICE_MINOR_RS422, - .nr = IOC4_NUM_CARDS * IOC4_NUM_SERIAL_PORTS, -}; - - -/** - * ioc4_serial_remove_one - detach function - * - * @idd: IOC4 master module data for this IOC4 - */ - -static int ioc4_serial_remove_one(struct ioc4_driver_data *idd) -{ - int port_num, port_type; - struct ioc4_control *control; - struct uart_port *the_port; - struct ioc4_port *port; - struct ioc4_soft *soft; - - /* If serial driver did not attach, don't try to detach */ - control = idd->idd_serial_data; - if (!control) - return 0; - - for (port_num = 0; port_num < IOC4_NUM_SERIAL_PORTS; port_num++) { - for (port_type = UART_PORT_MIN; - port_type < UART_PORT_COUNT; - port_type++) { - the_port = &control->ic_port[port_num].icp_uart_port - [port_type]; - if (the_port) { - switch (port_type) { - case UART_PORT_RS422: - uart_remove_one_port(&ioc4_uart_rs422, - the_port); - break; - default: - case UART_PORT_RS232: - uart_remove_one_port(&ioc4_uart_rs232, - the_port); - break; - } - } - } - port = control->ic_port[port_num].icp_port; - /* we allocate in pairs */ - if (!(port_num & 1) && port) { - pci_free_consistent(port->ip_pdev, - TOTAL_RING_BUF_SIZE, - port->ip_cpu_ringbuf, - port->ip_dma_ringbuf); - kfree(port); - } - } - soft = control->ic_soft; - if (soft) { - free_irq(control->ic_irq, soft); - if (soft->is_ioc4_serial_addr) { - iounmap(soft->is_ioc4_serial_addr); - release_mem_region((unsigned long) - soft->is_ioc4_serial_addr, - sizeof(struct ioc4_serial)); - } - kfree(soft); - } - kfree(control); - idd->idd_serial_data = NULL; - - return 0; -} - - -/** - * ioc4_serial_core_attach_rs232 - register with serial core - * This is done during pci probing - * @pdev: handle for this card - */ -static inline int -ioc4_serial_core_attach(struct pci_dev *pdev, int port_type) -{ - struct ioc4_port *port; - struct uart_port *the_port; - struct ioc4_driver_data *idd = pci_get_drvdata(pdev); - struct ioc4_control *control = idd->idd_serial_data; - int port_num; - int port_type_idx; - struct uart_driver *u_driver; - - - DPRINT_CONFIG(("%s: attach pdev 0x%p - control 0x%p\n", - __func__, pdev, (void *)control)); - - if (!control) - return -ENODEV; - - port_type_idx = (port_type == PROTO_RS232) ? UART_PORT_RS232 - : UART_PORT_RS422; - - u_driver = (port_type == PROTO_RS232) ? &ioc4_uart_rs232 - : &ioc4_uart_rs422; - - /* once around for each port on this card */ - for (port_num = 0; port_num < IOC4_NUM_SERIAL_PORTS; port_num++) { - the_port = &control->ic_port[port_num].icp_uart_port - [port_type_idx]; - port = control->ic_port[port_num].icp_port; - port->ip_all_ports[port_type_idx] = the_port; - - DPRINT_CONFIG(("%s: attach the_port 0x%p / port 0x%p : type %s\n", - __func__, (void *)the_port, - (void *)port, - port_type == PROTO_RS232 ? "rs232" : "rs422")); - - /* membase, iobase and mapbase just need to be non-0 */ - the_port->membase = (unsigned char __iomem *)1; - the_port->iobase = (pdev->bus->number << 16) | port_num; - the_port->line = (Num_of_ioc4_cards << 2) | port_num; - the_port->mapbase = port_type; - the_port->type = PORT_16550A; - the_port->fifosize = IOC4_FIFO_CHARS; - the_port->ops = &ioc4_ops; - the_port->irq = control->ic_irq; - the_port->dev = &pdev->dev; - spin_lock_init(&the_port->lock); - if (uart_add_one_port(u_driver, the_port) < 0) { - printk(KERN_WARNING - "%s: unable to add port %d bus %d\n", - __func__, the_port->line, pdev->bus->number); - } else { - DPRINT_CONFIG( - ("IOC4 serial port %d irq = %d, bus %d\n", - the_port->line, the_port->irq, pdev->bus->number)); - } - } - return 0; -} - -/** - * ioc4_serial_attach_one - register attach function - * called per card found from IOC4 master module. - * @idd: Master module data for this IOC4 - */ -static int -ioc4_serial_attach_one(struct ioc4_driver_data *idd) -{ - unsigned long tmp_addr1; - struct ioc4_serial __iomem *serial; - struct ioc4_soft *soft; - struct ioc4_control *control; - int ret = 0; - - - DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __func__, idd->idd_pdev, - idd->idd_pci_id)); - - /* PCI-RT does not bring out serial connections. - * Do not attach to this particular IOC4. - */ - if (idd->idd_variant == IOC4_VARIANT_PCI_RT) - return 0; - - /* request serial registers */ - tmp_addr1 = idd->idd_bar0 + IOC4_SERIAL_OFFSET; - - if (!request_mem_region(tmp_addr1, sizeof(struct ioc4_serial), - "sioc4_uart")) { - printk(KERN_WARNING - "ioc4 (%p): unable to get request region for " - "uart space\n", (void *)idd->idd_pdev); - ret = -ENODEV; - goto out1; - } - serial = ioremap(tmp_addr1, sizeof(struct ioc4_serial)); - if (!serial) { - printk(KERN_WARNING - "ioc4 (%p) : unable to remap ioc4 serial register\n", - (void *)idd->idd_pdev); - ret = -ENODEV; - goto out2; - } - DPRINT_CONFIG(("%s : mem 0x%p, serial 0x%p\n", - __func__, (void *)idd->idd_misc_regs, - (void *)serial)); - - /* Get memory for the new card */ - control = kzalloc(sizeof(struct ioc4_control), GFP_KERNEL); - - if (!control) { - printk(KERN_WARNING "ioc4_attach_one" - ": unable to get memory for the IOC4\n"); - ret = -ENOMEM; - goto out2; - } - idd->idd_serial_data = control; - - /* Allocate the soft structure */ - soft = kzalloc(sizeof(struct ioc4_soft), GFP_KERNEL); - if (!soft) { - printk(KERN_WARNING - "ioc4 (%p): unable to get memory for the soft struct\n", - (void *)idd->idd_pdev); - ret = -ENOMEM; - goto out3; - } - - spin_lock_init(&soft->is_ir_lock); - soft->is_ioc4_misc_addr = idd->idd_misc_regs; - soft->is_ioc4_serial_addr = serial; - - /* Init the IOC4 */ - writel(0xf << IOC4_SIO_CR_CMD_PULSE_SHIFT, - &idd->idd_misc_regs->sio_cr.raw); - - /* Enable serial port mode select generic PIO pins as outputs */ - writel(IOC4_GPCR_UART0_MODESEL | IOC4_GPCR_UART1_MODESEL - | IOC4_GPCR_UART2_MODESEL | IOC4_GPCR_UART3_MODESEL, - &idd->idd_misc_regs->gpcr_s.raw); - - /* Clear and disable all serial interrupts */ - write_ireg(soft, ~0, IOC4_W_IEC, IOC4_SIO_INTR_TYPE); - writel(~0, &idd->idd_misc_regs->sio_ir.raw); - write_ireg(soft, IOC4_OTHER_IR_SER_MEMERR, IOC4_W_IEC, - IOC4_OTHER_INTR_TYPE); - writel(IOC4_OTHER_IR_SER_MEMERR, &idd->idd_misc_regs->other_ir.raw); - control->ic_soft = soft; - - /* Hook up interrupt handler */ - if (!request_irq(idd->idd_pdev->irq, ioc4_intr, IRQF_SHARED, - "sgi-ioc4serial", soft)) { - control->ic_irq = idd->idd_pdev->irq; - } else { - printk(KERN_WARNING - "%s : request_irq fails for IRQ 0x%x\n ", - __func__, idd->idd_pdev->irq); - } - ret = ioc4_attach_local(idd); - if (ret) - goto out4; - - /* register port with the serial core - 1 rs232, 1 rs422 */ - - ret = ioc4_serial_core_attach(idd->idd_pdev, PROTO_RS232); - if (ret) - goto out4; - - ret = ioc4_serial_core_attach(idd->idd_pdev, PROTO_RS422); - if (ret) - goto out5; - - Num_of_ioc4_cards++; - - return ret; - - /* error exits that give back resources */ -out5: - ioc4_serial_remove_one(idd); - return ret; -out4: - kfree(soft); -out3: - kfree(control); -out2: - if (serial) - iounmap(serial); - release_mem_region(tmp_addr1, sizeof(struct ioc4_serial)); -out1: - - return ret; -} - - -static struct ioc4_submodule ioc4_serial_submodule = { - .is_name = "IOC4_serial", - .is_owner = THIS_MODULE, - .is_probe = ioc4_serial_attach_one, - .is_remove = ioc4_serial_remove_one, -}; - -/** - * ioc4_serial_init - module init - */ -static int __init ioc4_serial_init(void) -{ - int ret; - - /* register with serial core */ - if ((ret = uart_register_driver(&ioc4_uart_rs232)) < 0) { - printk(KERN_WARNING - "%s: Couldn't register rs232 IOC4 serial driver\n", - __func__); - goto out; - } - if ((ret = uart_register_driver(&ioc4_uart_rs422)) < 0) { - printk(KERN_WARNING - "%s: Couldn't register rs422 IOC4 serial driver\n", - __func__); - goto out_uart_rs232; - } - - /* register with IOC4 main module */ - ret = ioc4_register_submodule(&ioc4_serial_submodule); - if (ret) - goto out_uart_rs422; - return 0; - -out_uart_rs422: - uart_unregister_driver(&ioc4_uart_rs422); -out_uart_rs232: - uart_unregister_driver(&ioc4_uart_rs232); -out: - return ret; -} - -static void __exit ioc4_serial_exit(void) -{ - ioc4_unregister_submodule(&ioc4_serial_submodule); - uart_unregister_driver(&ioc4_uart_rs232); - uart_unregister_driver(&ioc4_uart_rs422); -} - -late_initcall(ioc4_serial_init); /* Call only after tty init is done */ -module_exit(ioc4_serial_exit); - -MODULE_AUTHOR("Pat Gefre - Silicon Graphics Inc. (SGI) <pfg@sgi.com>"); -MODULE_DESCRIPTION("Serial PCI driver module for SGI IOC4 Base-IO Card"); -MODULE_LICENSE("GPL"); diff --git a/drivers/tty/serial/kgdboc.c b/drivers/tty/serial/kgdboc.c index bfe5e9e034ec..c7d51b51898f 100644 --- a/drivers/tty/serial/kgdboc.c +++ b/drivers/tty/serial/kgdboc.c @@ -277,10 +277,14 @@ static void kgdboc_pre_exp_handler(void) /* Increment the module count when the debugger is active */ if (!kgdb_connected) try_module_get(THIS_MODULE); + + atomic_inc(&ignore_console_lock_warning); } static void kgdboc_post_exp_handler(void) { + atomic_dec(&ignore_console_lock_warning); + /* decrement the module count when the debugger detaches */ if (!kgdb_connected) module_put(THIS_MODULE); diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c index 9de9f0f239a1..fcbea43dc334 100644 --- a/drivers/tty/serial/lantiq.c +++ b/drivers/tty/serial/lantiq.c @@ -57,6 +57,7 @@ #define ASC_IRNCR_TIR 0x1 #define ASC_IRNCR_RIR 0x2 #define ASC_IRNCR_EIR 0x4 +#define ASC_IRNCR_MASK GENMASK(2, 0) #define ASCOPT_CSIZE 0x3 #define TXFIFO_FL 1 @@ -99,7 +100,12 @@ static void lqasc_tx_chars(struct uart_port *port); static struct ltq_uart_port *lqasc_port[MAXPORTS]; static struct uart_driver lqasc_reg; -static DEFINE_SPINLOCK(ltq_asc_lock); + +struct ltq_soc_data { + int (*fetch_irq)(struct device *dev, struct ltq_uart_port *ltq_port); + int (*request_irq)(struct uart_port *port); + void (*free_irq)(struct uart_port *port); +}; struct ltq_uart_port { struct uart_port port; @@ -110,6 +116,10 @@ struct ltq_uart_port { unsigned int tx_irq; unsigned int rx_irq; unsigned int err_irq; + unsigned int common_irq; + spinlock_t lock; /* exclusive access for multi core */ + + const struct ltq_soc_data *soc; }; static inline void asc_update_bits(u32 clear, u32 set, void __iomem *reg) @@ -135,9 +145,11 @@ static void lqasc_start_tx(struct uart_port *port) { unsigned long flags; - spin_lock_irqsave(<q_asc_lock, flags); + struct ltq_uart_port *ltq_port = to_ltq_uart_port(port); + + spin_lock_irqsave(<q_port->lock, flags); lqasc_tx_chars(port); - spin_unlock_irqrestore(<q_asc_lock, flags); + spin_unlock_irqrestore(<q_port->lock, flags); return; } @@ -245,9 +257,11 @@ lqasc_tx_int(int irq, void *_port) { unsigned long flags; struct uart_port *port = (struct uart_port *)_port; - spin_lock_irqsave(<q_asc_lock, flags); + struct ltq_uart_port *ltq_port = to_ltq_uart_port(port); + + spin_lock_irqsave(<q_port->lock, flags); __raw_writel(ASC_IRNCR_TIR, port->membase + LTQ_ASC_IRNCR); - spin_unlock_irqrestore(<q_asc_lock, flags); + spin_unlock_irqrestore(<q_port->lock, flags); lqasc_start_tx(port); return IRQ_HANDLED; } @@ -257,11 +271,13 @@ lqasc_err_int(int irq, void *_port) { unsigned long flags; struct uart_port *port = (struct uart_port *)_port; - spin_lock_irqsave(<q_asc_lock, flags); + struct ltq_uart_port *ltq_port = to_ltq_uart_port(port); + + spin_lock_irqsave(<q_port->lock, flags); /* clear any pending interrupts */ asc_update_bits(0, ASCWHBSTATE_CLRPE | ASCWHBSTATE_CLRFE | ASCWHBSTATE_CLRROE, port->membase + LTQ_ASC_WHBSTATE); - spin_unlock_irqrestore(<q_asc_lock, flags); + spin_unlock_irqrestore(<q_port->lock, flags); return IRQ_HANDLED; } @@ -270,10 +286,37 @@ lqasc_rx_int(int irq, void *_port) { unsigned long flags; struct uart_port *port = (struct uart_port *)_port; - spin_lock_irqsave(<q_asc_lock, flags); + struct ltq_uart_port *ltq_port = to_ltq_uart_port(port); + + spin_lock_irqsave(<q_port->lock, flags); __raw_writel(ASC_IRNCR_RIR, port->membase + LTQ_ASC_IRNCR); lqasc_rx_chars(port); - spin_unlock_irqrestore(<q_asc_lock, flags); + spin_unlock_irqrestore(<q_port->lock, flags); + return IRQ_HANDLED; +} + +static irqreturn_t lqasc_irq(int irq, void *p) +{ + unsigned long flags; + u32 stat; + struct uart_port *port = p; + struct ltq_uart_port *ltq_port = to_ltq_uart_port(port); + + spin_lock_irqsave(<q_port->lock, flags); + stat = readl(port->membase + LTQ_ASC_IRNCR); + spin_unlock_irqrestore(<q_port->lock, flags); + if (!(stat & ASC_IRNCR_MASK)) + return IRQ_NONE; + + if (stat & ASC_IRNCR_TIR) + lqasc_tx_int(irq, p); + + if (stat & ASC_IRNCR_RIR) + lqasc_rx_int(irq, p); + + if (stat & ASC_IRNCR_EIR) + lqasc_err_int(irq, p); + return IRQ_HANDLED; } @@ -307,11 +350,13 @@ lqasc_startup(struct uart_port *port) { struct ltq_uart_port *ltq_port = to_ltq_uart_port(port); int retval; + unsigned long flags; if (!IS_ERR(ltq_port->clk)) clk_prepare_enable(ltq_port->clk); port->uartclk = clk_get_rate(ltq_port->freqclk); + spin_lock_irqsave(<q_port->lock, flags); asc_update_bits(ASCCLC_DISS | ASCCLC_RMCMASK, (1 << ASCCLC_RMCOFFSET), port->membase + LTQ_ASC_CLC); @@ -331,35 +376,14 @@ lqasc_startup(struct uart_port *port) asc_update_bits(0, ASCCON_M_8ASYNC | ASCCON_FEN | ASCCON_TOEN | ASCCON_ROEN, port->membase + LTQ_ASC_CON); - retval = request_irq(ltq_port->tx_irq, lqasc_tx_int, - 0, "asc_tx", port); - if (retval) { - pr_err("failed to request lqasc_tx_int\n"); - return retval; - } - - retval = request_irq(ltq_port->rx_irq, lqasc_rx_int, - 0, "asc_rx", port); - if (retval) { - pr_err("failed to request lqasc_rx_int\n"); - goto err1; - } + spin_unlock_irqrestore(<q_port->lock, flags); - retval = request_irq(ltq_port->err_irq, lqasc_err_int, - 0, "asc_err", port); - if (retval) { - pr_err("failed to request lqasc_err_int\n"); - goto err2; - } + retval = ltq_port->soc->request_irq(port); + if (retval) + return retval; __raw_writel(ASC_IRNREN_RX | ASC_IRNREN_ERR | ASC_IRNREN_TX, port->membase + LTQ_ASC_IRNREN); - return 0; - -err2: - free_irq(ltq_port->rx_irq, port); -err1: - free_irq(ltq_port->tx_irq, port); return retval; } @@ -367,15 +391,17 @@ static void lqasc_shutdown(struct uart_port *port) { struct ltq_uart_port *ltq_port = to_ltq_uart_port(port); - free_irq(ltq_port->tx_irq, port); - free_irq(ltq_port->rx_irq, port); - free_irq(ltq_port->err_irq, port); + unsigned long flags; + + ltq_port->soc->free_irq(port); + spin_lock_irqsave(<q_port->lock, flags); __raw_writel(0, port->membase + LTQ_ASC_CON); asc_update_bits(ASCRXFCON_RXFEN, ASCRXFCON_RXFFLU, port->membase + LTQ_ASC_RXFCON); asc_update_bits(ASCTXFCON_TXFEN, ASCTXFCON_TXFFLU, port->membase + LTQ_ASC_TXFCON); + spin_unlock_irqrestore(<q_port->lock, flags); if (!IS_ERR(ltq_port->clk)) clk_disable_unprepare(ltq_port->clk); } @@ -390,6 +416,7 @@ lqasc_set_termios(struct uart_port *port, unsigned int baud; unsigned int con = 0; unsigned long flags; + struct ltq_uart_port *ltq_port = to_ltq_uart_port(port); cflag = new->c_cflag; iflag = new->c_iflag; @@ -443,7 +470,7 @@ lqasc_set_termios(struct uart_port *port, /* set error signals - framing, parity and overrun, enable receiver */ con |= ASCCON_FEN | ASCCON_TOEN | ASCCON_ROEN; - spin_lock_irqsave(<q_asc_lock, flags); + spin_lock_irqsave(<q_port->lock, flags); /* set up CON */ asc_update_bits(0, con, port->membase + LTQ_ASC_CON); @@ -471,7 +498,7 @@ lqasc_set_termios(struct uart_port *port, /* enable rx */ __raw_writel(ASCWHBSTATE_SETREN, port->membase + LTQ_ASC_WHBSTATE); - spin_unlock_irqrestore(<q_asc_lock, flags); + spin_unlock_irqrestore(<q_port->lock, flags); /* Don't rewrite B0 */ if (tty_termios_baud_rate(new)) @@ -589,17 +616,14 @@ lqasc_console_putchar(struct uart_port *port, int ch) static void lqasc_serial_port_write(struct uart_port *port, const char *s, u_int count) { - unsigned long flags; - - spin_lock_irqsave(<q_asc_lock, flags); uart_console_write(port, s, count, lqasc_console_putchar); - spin_unlock_irqrestore(<q_asc_lock, flags); } static void lqasc_console_write(struct console *co, const char *s, u_int count) { struct ltq_uart_port *ltq_port; + unsigned long flags; if (co->index >= MAXPORTS) return; @@ -608,7 +632,9 @@ lqasc_console_write(struct console *co, const char *s, u_int count) if (!ltq_port) return; + spin_lock_irqsave(<q_port->lock, flags); lqasc_serial_port_write(<q_port->port, s, count); + spin_unlock_irqrestore(<q_port->lock, flags); } static int __init @@ -677,7 +703,8 @@ lqasc_serial_early_console_setup(struct earlycon_device *device, device->con->write = lqasc_serial_early_console_write; return 0; } -OF_EARLYCON_DECLARE(lantiq, DRVNAME, lqasc_serial_early_console_setup); +OF_EARLYCON_DECLARE(lantiq, "lantiq,asc", lqasc_serial_early_console_setup); +OF_EARLYCON_DECLARE(lantiq, "intel,lgm-asc", lqasc_serial_early_console_setup); static struct uart_driver lqasc_reg = { .owner = THIS_MODULE, @@ -689,24 +716,134 @@ static struct uart_driver lqasc_reg = { .cons = &lqasc_console, }; +static int fetch_irq_lantiq(struct device *dev, struct ltq_uart_port *ltq_port) +{ + struct uart_port *port = <q_port->port; + struct resource irqres[3]; + int ret; + + ret = of_irq_to_resource_table(dev->of_node, irqres, 3); + if (ret != 3) { + dev_err(dev, + "failed to get IRQs for serial port\n"); + return -ENODEV; + } + ltq_port->tx_irq = irqres[0].start; + ltq_port->rx_irq = irqres[1].start; + ltq_port->err_irq = irqres[2].start; + port->irq = irqres[0].start; + + return 0; +} + +static int request_irq_lantiq(struct uart_port *port) +{ + struct ltq_uart_port *ltq_port = to_ltq_uart_port(port); + int retval; + + retval = request_irq(ltq_port->tx_irq, lqasc_tx_int, + 0, "asc_tx", port); + if (retval) { + dev_err(port->dev, "failed to request asc_tx\n"); + return retval; + } + + retval = request_irq(ltq_port->rx_irq, lqasc_rx_int, + 0, "asc_rx", port); + if (retval) { + dev_err(port->dev, "failed to request asc_rx\n"); + goto err1; + } + + retval = request_irq(ltq_port->err_irq, lqasc_err_int, + 0, "asc_err", port); + if (retval) { + dev_err(port->dev, "failed to request asc_err\n"); + goto err2; + } + return 0; + +err2: + free_irq(ltq_port->rx_irq, port); +err1: + free_irq(ltq_port->tx_irq, port); + return retval; +} + +static void free_irq_lantiq(struct uart_port *port) +{ + struct ltq_uart_port *ltq_port = to_ltq_uart_port(port); + + free_irq(ltq_port->tx_irq, port); + free_irq(ltq_port->rx_irq, port); + free_irq(ltq_port->err_irq, port); +} + +static int fetch_irq_intel(struct device *dev, struct ltq_uart_port *ltq_port) +{ + struct uart_port *port = <q_port->port; + int ret; + + ret = of_irq_get(dev->of_node, 0); + if (ret < 0) { + dev_err(dev, "failed to fetch IRQ for serial port\n"); + return ret; + } + ltq_port->common_irq = ret; + port->irq = ret; + + return 0; +} + +static int request_irq_intel(struct uart_port *port) +{ + struct ltq_uart_port *ltq_port = to_ltq_uart_port(port); + int retval; + + retval = request_irq(ltq_port->common_irq, lqasc_irq, 0, + "asc_irq", port); + if (retval) + dev_err(port->dev, "failed to request asc_irq\n"); + + return retval; +} + +static void free_irq_intel(struct uart_port *port) +{ + struct ltq_uart_port *ltq_port = to_ltq_uart_port(port); + + free_irq(ltq_port->common_irq, port); +} + static int __init lqasc_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; struct ltq_uart_port *ltq_port; struct uart_port *port; - struct resource *mmres, irqres[3]; + struct resource *mmres; int line; int ret; mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0); - ret = of_irq_to_resource_table(node, irqres, 3); - if (!mmres || (ret != 3)) { + if (!mmres) { dev_err(&pdev->dev, - "failed to get memory/irq for serial port\n"); + "failed to get memory for serial port\n"); return -ENODEV; } + ltq_port = devm_kzalloc(&pdev->dev, sizeof(struct ltq_uart_port), + GFP_KERNEL); + if (!ltq_port) + return -ENOMEM; + + port = <q_port->port; + + ltq_port->soc = of_device_get_match_data(&pdev->dev); + ret = ltq_port->soc->fetch_irq(&pdev->dev, ltq_port); + if (ret) + return ret; + /* get serial id */ line = of_alias_get_id(node, "serial"); if (line < 0) { @@ -727,13 +864,6 @@ lqasc_probe(struct platform_device *pdev) return -EBUSY; } - ltq_port = devm_kzalloc(&pdev->dev, sizeof(struct ltq_uart_port), - GFP_KERNEL); - if (!ltq_port) - return -ENOMEM; - - port = <q_port->port; - port->iotype = SERIAL_IO_MEM; port->flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP; port->ops = &lqasc_pops; @@ -742,7 +872,6 @@ lqasc_probe(struct platform_device *pdev) port->line = line; port->dev = &pdev->dev; /* unused, just to be backward-compatible */ - port->irq = irqres[0].start; port->mapbase = mmres->start; if (IS_ENABLED(CONFIG_LANTIQ) && !IS_ENABLED(CONFIG_COMMON_CLK)) @@ -762,10 +891,7 @@ lqasc_probe(struct platform_device *pdev) else ltq_port->clk = devm_clk_get(&pdev->dev, "asc"); - ltq_port->tx_irq = irqres[0].start; - ltq_port->rx_irq = irqres[1].start; - ltq_port->err_irq = irqres[2].start; - + spin_lock_init(<q_port->lock); lqasc_port[line] = ltq_port; platform_set_drvdata(pdev, ltq_port); @@ -774,8 +900,21 @@ lqasc_probe(struct platform_device *pdev) return ret; } +static const struct ltq_soc_data soc_data_lantiq = { + .fetch_irq = fetch_irq_lantiq, + .request_irq = request_irq_lantiq, + .free_irq = free_irq_lantiq, +}; + +static const struct ltq_soc_data soc_data_intel = { + .fetch_irq = fetch_irq_intel, + .request_irq = request_irq_intel, + .free_irq = free_irq_intel, +}; + static const struct of_device_id ltq_asc_match[] = { - { .compatible = DRVNAME }, + { .compatible = "lantiq,asc", .data = &soc_data_lantiq }, + { .compatible = "intel,lgm-asc", .data = &soc_data_intel }, {}, }; diff --git a/drivers/tty/serial/lpc32xx_hs.c b/drivers/tty/serial/lpc32xx_hs.c index f4e27d0ad947..9a836dcac157 100644 --- a/drivers/tty/serial/lpc32xx_hs.c +++ b/drivers/tty/serial/lpc32xx_hs.c @@ -25,8 +25,8 @@ #include <linux/irq.h> #include <linux/gpio.h> #include <linux/of.h> -#include <mach/platform.h> -#include <mach/hardware.h> +#include <linux/sizes.h> +#include <linux/soc/nxp/lpc32xx-misc.h> /* * High Speed UART register offsets @@ -81,6 +81,8 @@ #define LPC32XX_HSU_TX_TL8B (0x2 << 0) #define LPC32XX_HSU_TX_TL16B (0x3 << 0) +#define LPC32XX_MAIN_OSC_FREQ 13000000 + #define MODNAME "lpc32xx_hsuart" struct lpc32xx_hsuart_port { @@ -151,8 +153,6 @@ static void lpc32xx_hsuart_console_write(struct console *co, const char *s, local_irq_restore(flags); } -static void lpc32xx_loopback_set(resource_size_t mapbase, int state); - static int __init lpc32xx_hsuart_console_setup(struct console *co, char *options) { @@ -439,35 +439,6 @@ static void serial_lpc32xx_break_ctl(struct uart_port *port, spin_unlock_irqrestore(&port->lock, flags); } -/* LPC3250 Errata HSUART.1: Hang workaround via loopback mode on inactivity */ -static void lpc32xx_loopback_set(resource_size_t mapbase, int state) -{ - int bit; - u32 tmp; - - switch (mapbase) { - case LPC32XX_HS_UART1_BASE: - bit = 0; - break; - case LPC32XX_HS_UART2_BASE: - bit = 1; - break; - case LPC32XX_HS_UART7_BASE: - bit = 6; - break; - default: - WARN(1, "lpc32xx_hs: Warning: Unknown port at %08x\n", mapbase); - return; - } - - tmp = readl(LPC32XX_UARTCTL_CLOOP); - if (state) - tmp |= (1 << bit); - else - tmp &= ~(1 << bit); - writel(tmp, LPC32XX_UARTCTL_CLOOP); -} - /* port->lock is not held. */ static int serial_lpc32xx_startup(struct uart_port *port) { @@ -687,11 +658,8 @@ static int serial_hs_lpc32xx_probe(struct platform_device *pdev) p->port.membase = NULL; ret = platform_get_irq(pdev, 0); - if (ret < 0) { - dev_err(&pdev->dev, "Error getting irq for HS UART port %d\n", - uarts_registered); + if (ret < 0) return ret; - } p->port.irq = ret; p->port.iotype = UPIO_MEM32; diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index e5aebbf5f302..8434bd5a8ec7 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -258,12 +258,17 @@ struct max310x_one { struct work_struct tx_work; struct work_struct md_work; struct work_struct rs_work; + + u8 wr_header; + u8 rd_header; + u8 rx_buf[MAX310X_FIFO_SIZE]; }; +#define to_max310x_port(_port) \ + container_of(_port, struct max310x_one, port) struct max310x_port { struct max310x_devtype *devtype; struct regmap *regmap; - struct mutex mutex; struct clk *clk; #ifdef CONFIG_GPIOLIB struct gpio_chip gpio; @@ -496,37 +501,48 @@ static bool max310x_reg_precious(struct device *dev, unsigned int reg) static int max310x_set_baud(struct uart_port *port, int baud) { - unsigned int mode = 0, clk = port->uartclk, div = clk / baud; - - /* Check for minimal value for divider */ - if (div < 16) - div = 16; + unsigned int mode = 0, div = 0, frac = 0, c = 0, F = 0; - if (clk % baud && (div / 16) < 0x8000) { + /* + * Calculate the integer divisor first. Select a proper mode + * in case if the requested baud is too high for the pre-defined + * clocks frequency. + */ + div = port->uartclk / baud; + if (div < 8) { + /* Mode x4 */ + c = 4; + mode = MAX310X_BRGCFG_4XMODE_BIT; + } else if (div < 16) { /* Mode x2 */ + c = 8; mode = MAX310X_BRGCFG_2XMODE_BIT; - clk = port->uartclk * 2; - div = clk / baud; - - if (clk % baud && (div / 16) < 0x8000) { - /* Mode x4 */ - mode = MAX310X_BRGCFG_4XMODE_BIT; - clk = port->uartclk * 4; - div = clk / baud; - } + } else { + c = 16; } - max310x_port_write(port, MAX310X_BRGDIVMSB_REG, (div / 16) >> 8); - max310x_port_write(port, MAX310X_BRGDIVLSB_REG, div / 16); - max310x_port_write(port, MAX310X_BRGCFG_REG, (div % 16) | mode); + /* Calculate the divisor in accordance with the fraction coefficient */ + div /= c; + F = c*baud; + + /* Calculate the baud rate fraction */ + if (div > 0) + frac = (16*(port->uartclk % F)) / F; + else + div = 1; - return DIV_ROUND_CLOSEST(clk, div); + max310x_port_write(port, MAX310X_BRGDIVMSB_REG, div >> 8); + max310x_port_write(port, MAX310X_BRGDIVLSB_REG, div); + max310x_port_write(port, MAX310X_BRGCFG_REG, frac | mode); + + /* Return the actual baud rate we just programmed */ + return (16*port->uartclk) / (c*(16*div + frac)); } static int max310x_update_best_err(unsigned long f, long *besterr) { /* Use baudrate 115200 for calculate error */ - long err = f % (115200 * 16); + long err = f % (460800 * 16); if ((*besterr < 0) || (*besterr > err)) { *besterr = err; @@ -607,11 +623,11 @@ static int max310x_set_ref_clk(struct device *dev, struct max310x_port *s, static void max310x_batch_write(struct uart_port *port, u8 *txbuf, unsigned int len) { - u8 header[] = { (port->iobase + MAX310X_THR_REG) | MAX310X_WRITE_BIT }; + struct max310x_one *one = to_max310x_port(port); struct spi_transfer xfer[] = { { - .tx_buf = &header, - .len = sizeof(header), + .tx_buf = &one->wr_header, + .len = sizeof(one->wr_header), }, { .tx_buf = txbuf, .len = len, @@ -622,11 +638,11 @@ static void max310x_batch_write(struct uart_port *port, u8 *txbuf, unsigned int static void max310x_batch_read(struct uart_port *port, u8 *rxbuf, unsigned int len) { - u8 header[] = { port->iobase + MAX310X_RHR_REG }; + struct max310x_one *one = to_max310x_port(port); struct spi_transfer xfer[] = { { - .tx_buf = &header, - .len = sizeof(header), + .tx_buf = &one->rd_header, + .len = sizeof(one->rd_header), }, { .rx_buf = rxbuf, .len = len, @@ -637,8 +653,8 @@ static void max310x_batch_read(struct uart_port *port, u8 *rxbuf, unsigned int l static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen) { + struct max310x_one *one = to_max310x_port(port); unsigned int sts, ch, flag, i; - u8 buf[MAX310X_FIFO_SIZE]; if (port->read_status_mask == MAX310X_LSR_RXOVR_BIT) { /* We are just reading, happily ignoring any error conditions. @@ -653,7 +669,7 @@ static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen) * */ sts = max310x_port_read(port, MAX310X_LSR_IRQSTS_REG); - max310x_batch_read(port, buf, rxlen); + max310x_batch_read(port, one->rx_buf, rxlen); port->icount.rx += rxlen; flag = TTY_NORMAL; @@ -664,9 +680,16 @@ static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen) port->icount.overrun++; } - for (i = 0; i < rxlen; ++i) { - uart_insert_char(port, sts, MAX310X_LSR_RXOVR_BIT, buf[i], flag); - } + for (i = 0; i < (rxlen - 1); ++i) + uart_insert_char(port, sts, 0, one->rx_buf[i], flag); + + /* + * Handle the overrun case for the last character only, since + * the RxFIFO overflow happens after it is pushed to the FIFO + * tail. + */ + uart_insert_char(port, sts, MAX310X_LSR_RXOVR_BIT, + one->rx_buf[rxlen-1], flag); } else { if (unlikely(rxlen >= port->fifosize)) { @@ -766,10 +789,9 @@ static void max310x_handle_tx(struct uart_port *port) static void max310x_start_tx(struct uart_port *port) { - struct max310x_one *one = container_of(port, struct max310x_one, port); + struct max310x_one *one = to_max310x_port(port); - if (!work_pending(&one->tx_work)) - schedule_work(&one->tx_work); + schedule_work(&one->tx_work); } static irqreturn_t max310x_port_irq(struct max310x_port *s, int portno) @@ -826,14 +848,11 @@ static irqreturn_t max310x_ist(int irq, void *dev_id) return IRQ_RETVAL(handled); } -static void max310x_wq_proc(struct work_struct *ws) +static void max310x_tx_proc(struct work_struct *ws) { struct max310x_one *one = container_of(ws, struct max310x_one, tx_work); - struct max310x_port *s = dev_get_drvdata(one->port.dev); - mutex_lock(&s->mutex); max310x_handle_tx(&one->port); - mutex_unlock(&s->mutex); } static unsigned int max310x_tx_empty(struct uart_port *port) @@ -863,7 +882,7 @@ static void max310x_md_proc(struct work_struct *ws) static void max310x_set_mctrl(struct uart_port *port, unsigned int mctrl) { - struct max310x_one *one = container_of(port, struct max310x_one, port); + struct max310x_one *one = to_max310x_port(port); schedule_work(&one->md_work); } @@ -936,17 +955,43 @@ static void max310x_set_termios(struct uart_port *port, /* Configure flow control */ max310x_port_write(port, MAX310X_XON1_REG, termios->c_cc[VSTART]); max310x_port_write(port, MAX310X_XOFF1_REG, termios->c_cc[VSTOP]); - if (termios->c_cflag & CRTSCTS) + + /* Disable transmitter before enabling AutoCTS or auto transmitter + * flow control + */ + if (termios->c_cflag & CRTSCTS || termios->c_iflag & IXOFF) { + max310x_port_update(port, MAX310X_MODE1_REG, + MAX310X_MODE1_TXDIS_BIT, + MAX310X_MODE1_TXDIS_BIT); + } + + port->status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS | UPSTAT_AUTOXOFF); + + if (termios->c_cflag & CRTSCTS) { + /* Enable AUTORTS and AUTOCTS */ + port->status |= UPSTAT_AUTOCTS | UPSTAT_AUTORTS; flow |= MAX310X_FLOWCTRL_AUTOCTS_BIT | MAX310X_FLOWCTRL_AUTORTS_BIT; + } if (termios->c_iflag & IXON) flow |= MAX310X_FLOWCTRL_SWFLOW3_BIT | MAX310X_FLOWCTRL_SWFLOWEN_BIT; - if (termios->c_iflag & IXOFF) + if (termios->c_iflag & IXOFF) { + port->status |= UPSTAT_AUTOXOFF; flow |= MAX310X_FLOWCTRL_SWFLOW1_BIT | MAX310X_FLOWCTRL_SWFLOWEN_BIT; + } max310x_port_write(port, MAX310X_FLOWCTRL_REG, flow); + /* Enable transmitter after disabling AutoCTS and auto transmitter + * flow control + */ + if (!(termios->c_cflag & CRTSCTS) && !(termios->c_iflag & IXOFF)) { + max310x_port_update(port, MAX310X_MODE1_REG, + MAX310X_MODE1_TXDIS_BIT, + 0); + } + /* Get baud rate generator configuration */ baud = uart_get_baud_rate(port, termios, old, port->uartclk / 16 / 0xffff, @@ -962,37 +1007,36 @@ static void max310x_set_termios(struct uart_port *port, static void max310x_rs_proc(struct work_struct *ws) { struct max310x_one *one = container_of(ws, struct max310x_one, rs_work); - unsigned int val; + unsigned int delay, mode1 = 0, mode2 = 0; - val = (one->port.rs485.delay_rts_before_send << 4) | + delay = (one->port.rs485.delay_rts_before_send << 4) | one->port.rs485.delay_rts_after_send; - max310x_port_write(&one->port, MAX310X_HDPIXDELAY_REG, val); + max310x_port_write(&one->port, MAX310X_HDPIXDELAY_REG, delay); if (one->port.rs485.flags & SER_RS485_ENABLED) { - max310x_port_update(&one->port, MAX310X_MODE1_REG, - MAX310X_MODE1_TRNSCVCTRL_BIT, - MAX310X_MODE1_TRNSCVCTRL_BIT); - max310x_port_update(&one->port, MAX310X_MODE2_REG, - MAX310X_MODE2_ECHOSUPR_BIT, - MAX310X_MODE2_ECHOSUPR_BIT); - } else { - max310x_port_update(&one->port, MAX310X_MODE1_REG, - MAX310X_MODE1_TRNSCVCTRL_BIT, 0); - max310x_port_update(&one->port, MAX310X_MODE2_REG, - MAX310X_MODE2_ECHOSUPR_BIT, 0); + mode1 = MAX310X_MODE1_TRNSCVCTRL_BIT; + + if (!(one->port.rs485.flags & SER_RS485_RX_DURING_TX)) + mode2 = MAX310X_MODE2_ECHOSUPR_BIT; } + + max310x_port_update(&one->port, MAX310X_MODE1_REG, + MAX310X_MODE1_TRNSCVCTRL_BIT, mode1); + max310x_port_update(&one->port, MAX310X_MODE2_REG, + MAX310X_MODE2_ECHOSUPR_BIT, mode2); } static int max310x_rs485_config(struct uart_port *port, struct serial_rs485 *rs485) { - struct max310x_one *one = container_of(port, struct max310x_one, port); + struct max310x_one *one = to_max310x_port(port); if ((rs485->delay_rts_before_send > 0x0f) || (rs485->delay_rts_after_send > 0x0f)) return -ERANGE; - rs485->flags &= SER_RS485_RTS_ON_SEND | SER_RS485_ENABLED; + rs485->flags &= SER_RS485_RTS_ON_SEND | SER_RS485_RX_DURING_TX | + SER_RS485_ENABLED; memset(rs485->padding, 0, sizeof(rs485->padding)); port->rs485 = *rs485; @@ -1018,6 +1062,22 @@ static int max310x_startup(struct uart_port *port) max310x_port_update(port, MAX310X_MODE2_REG, MAX310X_MODE2_FIFORST_BIT, 0); + /* Configure mode1/mode2 to have rs485/rs232 enabled at startup */ + val = (clamp(port->rs485.delay_rts_before_send, 0U, 15U) << 4) | + clamp(port->rs485.delay_rts_after_send, 0U, 15U); + max310x_port_write(port, MAX310X_HDPIXDELAY_REG, val); + + if (port->rs485.flags & SER_RS485_ENABLED) { + max310x_port_update(port, MAX310X_MODE1_REG, + MAX310X_MODE1_TRNSCVCTRL_BIT, + MAX310X_MODE1_TRNSCVCTRL_BIT); + + if (!(port->rs485.flags & SER_RS485_RX_DURING_TX)) + max310x_port_update(port, MAX310X_MODE2_REG, + MAX310X_MODE2_ECHOSUPR_BIT, + MAX310X_MODE2_ECHOSUPR_BIT); + } + /* Configure flow control levels */ /* Flow control halt level 96, resume level 48 */ max310x_port_write(port, MAX310X_FLOWLVL_REG, @@ -1269,8 +1329,6 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype, uartclk = max310x_set_ref_clk(dev, s, freq, xtal); dev_dbg(dev, "Reference clock set to %i Hz\n", uartclk); - mutex_init(&s->mutex); - for (i = 0; i < devtype->nr; i++) { unsigned int line; @@ -1298,11 +1356,15 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype, /* Clear IRQ status register */ max310x_port_read(&s->p[i].port, MAX310X_IRQSTS_REG); /* Initialize queue for start TX */ - INIT_WORK(&s->p[i].tx_work, max310x_wq_proc); + INIT_WORK(&s->p[i].tx_work, max310x_tx_proc); /* Initialize queue for changing LOOPBACK mode */ INIT_WORK(&s->p[i].md_work, max310x_md_proc); /* Initialize queue for changing RS485 mode */ INIT_WORK(&s->p[i].rs_work, max310x_rs_proc); + /* Initialize SPI-transfer buffers */ + s->p[i].wr_header = (s->p[i].port.iobase + MAX310X_THR_REG) | + MAX310X_WRITE_BIT; + s->p[i].rd_header = (s->p[i].port.iobase + MAX310X_RHR_REG); /* Register port */ ret = uart_add_one_port(&max310x_uart, &s->p[i].port); @@ -1350,8 +1412,6 @@ out_uart: } } - mutex_destroy(&s->mutex); - out_clk: clk_disable_unprepare(s->clk); @@ -1372,7 +1432,6 @@ static int max310x_remove(struct device *dev) s->devtype->power(&s->p[i].port, 0); } - mutex_destroy(&s->mutex); clk_disable_unprepare(s->clk); return 0; diff --git a/drivers/tty/serial/mpsc.c b/drivers/tty/serial/mpsc.c deleted file mode 100644 index 1f60d6fe4ff2..000000000000 --- a/drivers/tty/serial/mpsc.c +++ /dev/null @@ -1,2138 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Generic driver for the MPSC (UART mode) on Marvell parts (e.g., GT64240, - * GT64260, MV64340, MV64360, GT96100, ... ). - * - * Author: Mark A. Greer <mgreer@mvista.com> - * - * Based on an old MPSC driver that was in the linuxppc tree. It appears to - * have been created by Chris Zankel (formerly of MontaVista) but there - * is no proper Copyright so I'm not sure. Apparently, parts were also - * taken from PPCBoot (now U-Boot). Also based on drivers/serial/8250.c - * by Russell King. - * - * 2004 (c) MontaVista, Software, Inc. - */ -/* - * The MPSC interface is much like a typical network controller's interface. - * That is, you set up separate rings of descriptors for transmitting and - * receiving data. There is also a pool of buffers with (one buffer per - * descriptor) that incoming data are dma'd into or outgoing data are dma'd - * out of. - * - * The MPSC requires two other controllers to be able to work. The Baud Rate - * Generator (BRG) provides a clock at programmable frequencies which determines - * the baud rate. The Serial DMA Controller (SDMA) takes incoming data from the - * MPSC and DMA's it into memory or DMA's outgoing data and passes it to the - * MPSC. It is actually the SDMA interrupt that the driver uses to keep the - * transmit and receive "engines" going (i.e., indicate data has been - * transmitted or received). - * - * NOTES: - * - * 1) Some chips have an erratum where several regs cannot be - * read. To work around that, we keep a local copy of those regs in - * 'mpsc_port_info'. - * - * 2) Some chips have an erratum where the ctlr will hang when the SDMA ctlr - * accesses system mem with coherency enabled. For that reason, the driver - * assumes that coherency for that ctlr has been disabled. This means - * that when in a cache coherent system, the driver has to manually manage - * the data cache on the areas that it touches because the dma_* macro are - * basically no-ops. - * - * 3) There is an erratum (on PPC) where you can't use the instruction to do - * a DMA_TO_DEVICE/cache clean so DMA_BIDIRECTIONAL/flushes are used in places - * where a DMA_TO_DEVICE/clean would have [otherwise] sufficed. - * - * 4) AFAICT, hardware flow control isn't supported by the controller --MAG. - */ - - -#if defined(CONFIG_SERIAL_MPSC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - -#include <linux/tty.h> -#include <linux/tty_flip.h> -#include <linux/ioport.h> -#include <linux/init.h> -#include <linux/console.h> -#include <linux/sysrq.h> -#include <linux/serial.h> -#include <linux/serial_core.h> -#include <linux/delay.h> -#include <linux/device.h> -#include <linux/dma-mapping.h> -#include <linux/mv643xx.h> -#include <linux/platform_device.h> -#include <linux/gfp.h> - -#include <asm/io.h> -#include <asm/irq.h> - -#define MPSC_NUM_CTLRS 2 - -/* - * Descriptors and buffers must be cache line aligned. - * Buffers lengths must be multiple of cache line size. - * Number of Tx & Rx descriptors must be powers of 2. - */ -#define MPSC_RXR_ENTRIES 32 -#define MPSC_RXRE_SIZE dma_get_cache_alignment() -#define MPSC_RXR_SIZE (MPSC_RXR_ENTRIES * MPSC_RXRE_SIZE) -#define MPSC_RXBE_SIZE dma_get_cache_alignment() -#define MPSC_RXB_SIZE (MPSC_RXR_ENTRIES * MPSC_RXBE_SIZE) - -#define MPSC_TXR_ENTRIES 32 -#define MPSC_TXRE_SIZE dma_get_cache_alignment() -#define MPSC_TXR_SIZE (MPSC_TXR_ENTRIES * MPSC_TXRE_SIZE) -#define MPSC_TXBE_SIZE dma_get_cache_alignment() -#define MPSC_TXB_SIZE (MPSC_TXR_ENTRIES * MPSC_TXBE_SIZE) - -#define MPSC_DMA_ALLOC_SIZE (MPSC_RXR_SIZE + MPSC_RXB_SIZE + MPSC_TXR_SIZE \ - + MPSC_TXB_SIZE + dma_get_cache_alignment() /* for alignment */) - -/* Rx and Tx Ring entry descriptors -- assume entry size is <= cacheline size */ -struct mpsc_rx_desc { - u16 bufsize; - u16 bytecnt; - u32 cmdstat; - u32 link; - u32 buf_ptr; -} __attribute((packed)); - -struct mpsc_tx_desc { - u16 bytecnt; - u16 shadow; - u32 cmdstat; - u32 link; - u32 buf_ptr; -} __attribute((packed)); - -/* - * Some regs that have the erratum that you can't read them are are shared - * between the two MPSC controllers. This struct contains those shared regs. - */ -struct mpsc_shared_regs { - phys_addr_t mpsc_routing_base_p; - phys_addr_t sdma_intr_base_p; - - void __iomem *mpsc_routing_base; - void __iomem *sdma_intr_base; - - u32 MPSC_MRR_m; - u32 MPSC_RCRR_m; - u32 MPSC_TCRR_m; - u32 SDMA_INTR_CAUSE_m; - u32 SDMA_INTR_MASK_m; -}; - -/* The main driver data structure */ -struct mpsc_port_info { - struct uart_port port; /* Overlay uart_port structure */ - - /* Internal driver state for this ctlr */ - u8 ready; - u8 rcv_data; - - /* Info passed in from platform */ - u8 mirror_regs; /* Need to mirror regs? */ - u8 cache_mgmt; /* Need manual cache mgmt? */ - u8 brg_can_tune; /* BRG has baud tuning? */ - u32 brg_clk_src; - u16 mpsc_max_idle; - int default_baud; - int default_bits; - int default_parity; - int default_flow; - - /* Physical addresses of various blocks of registers (from platform) */ - phys_addr_t mpsc_base_p; - phys_addr_t sdma_base_p; - phys_addr_t brg_base_p; - - /* Virtual addresses of various blocks of registers (from platform) */ - void __iomem *mpsc_base; - void __iomem *sdma_base; - void __iomem *brg_base; - - /* Descriptor ring and buffer allocations */ - void *dma_region; - dma_addr_t dma_region_p; - - dma_addr_t rxr; /* Rx descriptor ring */ - dma_addr_t rxr_p; /* Phys addr of rxr */ - u8 *rxb; /* Rx Ring I/O buf */ - u8 *rxb_p; /* Phys addr of rxb */ - u32 rxr_posn; /* First desc w/ Rx data */ - - dma_addr_t txr; /* Tx descriptor ring */ - dma_addr_t txr_p; /* Phys addr of txr */ - u8 *txb; /* Tx Ring I/O buf */ - u8 *txb_p; /* Phys addr of txb */ - int txr_head; /* Where new data goes */ - int txr_tail; /* Where sent data comes off */ - spinlock_t tx_lock; /* transmit lock */ - - /* Mirrored values of regs we can't read (if 'mirror_regs' set) */ - u32 MPSC_MPCR_m; - u32 MPSC_CHR_1_m; - u32 MPSC_CHR_2_m; - u32 MPSC_CHR_10_m; - u32 BRG_BCR_m; - struct mpsc_shared_regs *shared_regs; -}; - -/* Hooks to platform-specific code */ -int mpsc_platform_register_driver(void); -void mpsc_platform_unregister_driver(void); - -/* Hooks back in to mpsc common to be called by platform-specific code */ -struct mpsc_port_info *mpsc_device_probe(int index); -struct mpsc_port_info *mpsc_device_remove(int index); - -/* Main MPSC Configuration Register Offsets */ -#define MPSC_MMCRL 0x0000 -#define MPSC_MMCRH 0x0004 -#define MPSC_MPCR 0x0008 -#define MPSC_CHR_1 0x000c -#define MPSC_CHR_2 0x0010 -#define MPSC_CHR_3 0x0014 -#define MPSC_CHR_4 0x0018 -#define MPSC_CHR_5 0x001c -#define MPSC_CHR_6 0x0020 -#define MPSC_CHR_7 0x0024 -#define MPSC_CHR_8 0x0028 -#define MPSC_CHR_9 0x002c -#define MPSC_CHR_10 0x0030 -#define MPSC_CHR_11 0x0034 - -#define MPSC_MPCR_FRZ (1 << 9) -#define MPSC_MPCR_CL_5 0 -#define MPSC_MPCR_CL_6 1 -#define MPSC_MPCR_CL_7 2 -#define MPSC_MPCR_CL_8 3 -#define MPSC_MPCR_SBL_1 0 -#define MPSC_MPCR_SBL_2 1 - -#define MPSC_CHR_2_TEV (1<<1) -#define MPSC_CHR_2_TA (1<<7) -#define MPSC_CHR_2_TTCS (1<<9) -#define MPSC_CHR_2_REV (1<<17) -#define MPSC_CHR_2_RA (1<<23) -#define MPSC_CHR_2_CRD (1<<25) -#define MPSC_CHR_2_EH (1<<31) -#define MPSC_CHR_2_PAR_ODD 0 -#define MPSC_CHR_2_PAR_SPACE 1 -#define MPSC_CHR_2_PAR_EVEN 2 -#define MPSC_CHR_2_PAR_MARK 3 - -/* MPSC Signal Routing */ -#define MPSC_MRR 0x0000 -#define MPSC_RCRR 0x0004 -#define MPSC_TCRR 0x0008 - -/* Serial DMA Controller Interface Registers */ -#define SDMA_SDC 0x0000 -#define SDMA_SDCM 0x0008 -#define SDMA_RX_DESC 0x0800 -#define SDMA_RX_BUF_PTR 0x0808 -#define SDMA_SCRDP 0x0810 -#define SDMA_TX_DESC 0x0c00 -#define SDMA_SCTDP 0x0c10 -#define SDMA_SFTDP 0x0c14 - -#define SDMA_DESC_CMDSTAT_PE (1<<0) -#define SDMA_DESC_CMDSTAT_CDL (1<<1) -#define SDMA_DESC_CMDSTAT_FR (1<<3) -#define SDMA_DESC_CMDSTAT_OR (1<<6) -#define SDMA_DESC_CMDSTAT_BR (1<<9) -#define SDMA_DESC_CMDSTAT_MI (1<<10) -#define SDMA_DESC_CMDSTAT_A (1<<11) -#define SDMA_DESC_CMDSTAT_AM (1<<12) -#define SDMA_DESC_CMDSTAT_CT (1<<13) -#define SDMA_DESC_CMDSTAT_C (1<<14) -#define SDMA_DESC_CMDSTAT_ES (1<<15) -#define SDMA_DESC_CMDSTAT_L (1<<16) -#define SDMA_DESC_CMDSTAT_F (1<<17) -#define SDMA_DESC_CMDSTAT_P (1<<18) -#define SDMA_DESC_CMDSTAT_EI (1<<23) -#define SDMA_DESC_CMDSTAT_O (1<<31) - -#define SDMA_DESC_DFLT (SDMA_DESC_CMDSTAT_O \ - | SDMA_DESC_CMDSTAT_EI) - -#define SDMA_SDC_RFT (1<<0) -#define SDMA_SDC_SFM (1<<1) -#define SDMA_SDC_BLMR (1<<6) -#define SDMA_SDC_BLMT (1<<7) -#define SDMA_SDC_POVR (1<<8) -#define SDMA_SDC_RIFB (1<<9) - -#define SDMA_SDCM_ERD (1<<7) -#define SDMA_SDCM_AR (1<<15) -#define SDMA_SDCM_STD (1<<16) -#define SDMA_SDCM_TXD (1<<23) -#define SDMA_SDCM_AT (1<<31) - -#define SDMA_0_CAUSE_RXBUF (1<<0) -#define SDMA_0_CAUSE_RXERR (1<<1) -#define SDMA_0_CAUSE_TXBUF (1<<2) -#define SDMA_0_CAUSE_TXEND (1<<3) -#define SDMA_1_CAUSE_RXBUF (1<<8) -#define SDMA_1_CAUSE_RXERR (1<<9) -#define SDMA_1_CAUSE_TXBUF (1<<10) -#define SDMA_1_CAUSE_TXEND (1<<11) - -#define SDMA_CAUSE_RX_MASK (SDMA_0_CAUSE_RXBUF | SDMA_0_CAUSE_RXERR \ - | SDMA_1_CAUSE_RXBUF | SDMA_1_CAUSE_RXERR) -#define SDMA_CAUSE_TX_MASK (SDMA_0_CAUSE_TXBUF | SDMA_0_CAUSE_TXEND \ - | SDMA_1_CAUSE_TXBUF | SDMA_1_CAUSE_TXEND) - -/* SDMA Interrupt registers */ -#define SDMA_INTR_CAUSE 0x0000 -#define SDMA_INTR_MASK 0x0080 - -/* Baud Rate Generator Interface Registers */ -#define BRG_BCR 0x0000 -#define BRG_BTR 0x0004 - -/* - * Define how this driver is known to the outside (we've been assigned a - * range on the "Low-density serial ports" major). - */ -#define MPSC_MAJOR 204 -#define MPSC_MINOR_START 44 -#define MPSC_DRIVER_NAME "MPSC" -#define MPSC_DEV_NAME "ttyMM" -#define MPSC_VERSION "1.00" - -static struct mpsc_port_info mpsc_ports[MPSC_NUM_CTLRS]; -static struct mpsc_shared_regs mpsc_shared_regs; -static struct uart_driver mpsc_reg; - -static void mpsc_start_rx(struct mpsc_port_info *pi); -static void mpsc_free_ring_mem(struct mpsc_port_info *pi); -static void mpsc_release_port(struct uart_port *port); -/* - ****************************************************************************** - * - * Baud Rate Generator Routines (BRG) - * - ****************************************************************************** - */ -static void mpsc_brg_init(struct mpsc_port_info *pi, u32 clk_src) -{ - u32 v; - - v = (pi->mirror_regs) ? pi->BRG_BCR_m : readl(pi->brg_base + BRG_BCR); - v = (v & ~(0xf << 18)) | ((clk_src & 0xf) << 18); - - if (pi->brg_can_tune) - v &= ~(1 << 25); - - if (pi->mirror_regs) - pi->BRG_BCR_m = v; - writel(v, pi->brg_base + BRG_BCR); - - writel(readl(pi->brg_base + BRG_BTR) & 0xffff0000, - pi->brg_base + BRG_BTR); -} - -static void mpsc_brg_enable(struct mpsc_port_info *pi) -{ - u32 v; - - v = (pi->mirror_regs) ? pi->BRG_BCR_m : readl(pi->brg_base + BRG_BCR); - v |= (1 << 16); - - if (pi->mirror_regs) - pi->BRG_BCR_m = v; - writel(v, pi->brg_base + BRG_BCR); -} - -static void mpsc_brg_disable(struct mpsc_port_info *pi) -{ - u32 v; - - v = (pi->mirror_regs) ? pi->BRG_BCR_m : readl(pi->brg_base + BRG_BCR); - v &= ~(1 << 16); - - if (pi->mirror_regs) - pi->BRG_BCR_m = v; - writel(v, pi->brg_base + BRG_BCR); -} - -/* - * To set the baud, we adjust the CDV field in the BRG_BCR reg. - * From manual: Baud = clk / ((CDV+1)*2) ==> CDV = (clk / (baud*2)) - 1. - * However, the input clock is divided by 16 in the MPSC b/c of how - * 'MPSC_MMCRH' was set up so we have to divide the 'clk' used in our - * calculation by 16 to account for that. So the real calculation - * that accounts for the way the mpsc is set up is: - * CDV = (clk / (baud*2*16)) - 1 ==> CDV = (clk / (baud << 5)) - 1. - */ -static void mpsc_set_baudrate(struct mpsc_port_info *pi, u32 baud) -{ - u32 cdv = (pi->port.uartclk / (baud << 5)) - 1; - u32 v; - - mpsc_brg_disable(pi); - v = (pi->mirror_regs) ? pi->BRG_BCR_m : readl(pi->brg_base + BRG_BCR); - v = (v & 0xffff0000) | (cdv & 0xffff); - - if (pi->mirror_regs) - pi->BRG_BCR_m = v; - writel(v, pi->brg_base + BRG_BCR); - mpsc_brg_enable(pi); -} - -/* - ****************************************************************************** - * - * Serial DMA Routines (SDMA) - * - ****************************************************************************** - */ - -static void mpsc_sdma_burstsize(struct mpsc_port_info *pi, u32 burst_size) -{ - u32 v; - - pr_debug("mpsc_sdma_burstsize[%d]: burst_size: %d\n", - pi->port.line, burst_size); - - burst_size >>= 3; /* Divide by 8 b/c reg values are 8-byte chunks */ - - if (burst_size < 2) - v = 0x0; /* 1 64-bit word */ - else if (burst_size < 4) - v = 0x1; /* 2 64-bit words */ - else if (burst_size < 8) - v = 0x2; /* 4 64-bit words */ - else - v = 0x3; /* 8 64-bit words */ - - writel((readl(pi->sdma_base + SDMA_SDC) & (0x3 << 12)) | (v << 12), - pi->sdma_base + SDMA_SDC); -} - -static void mpsc_sdma_init(struct mpsc_port_info *pi, u32 burst_size) -{ - pr_debug("mpsc_sdma_init[%d]: burst_size: %d\n", pi->port.line, - burst_size); - - writel((readl(pi->sdma_base + SDMA_SDC) & 0x3ff) | 0x03f, - pi->sdma_base + SDMA_SDC); - mpsc_sdma_burstsize(pi, burst_size); -} - -static u32 mpsc_sdma_intr_mask(struct mpsc_port_info *pi, u32 mask) -{ - u32 old, v; - - pr_debug("mpsc_sdma_intr_mask[%d]: mask: 0x%x\n", pi->port.line, mask); - - old = v = (pi->mirror_regs) ? pi->shared_regs->SDMA_INTR_MASK_m : - readl(pi->shared_regs->sdma_intr_base + SDMA_INTR_MASK); - - mask &= 0xf; - if (pi->port.line) - mask <<= 8; - v &= ~mask; - - if (pi->mirror_regs) - pi->shared_regs->SDMA_INTR_MASK_m = v; - writel(v, pi->shared_regs->sdma_intr_base + SDMA_INTR_MASK); - - if (pi->port.line) - old >>= 8; - return old & 0xf; -} - -static void mpsc_sdma_intr_unmask(struct mpsc_port_info *pi, u32 mask) -{ - u32 v; - - pr_debug("mpsc_sdma_intr_unmask[%d]: mask: 0x%x\n", pi->port.line,mask); - - v = (pi->mirror_regs) ? pi->shared_regs->SDMA_INTR_MASK_m - : readl(pi->shared_regs->sdma_intr_base + SDMA_INTR_MASK); - - mask &= 0xf; - if (pi->port.line) - mask <<= 8; - v |= mask; - - if (pi->mirror_regs) - pi->shared_regs->SDMA_INTR_MASK_m = v; - writel(v, pi->shared_regs->sdma_intr_base + SDMA_INTR_MASK); -} - -static void mpsc_sdma_intr_ack(struct mpsc_port_info *pi) -{ - pr_debug("mpsc_sdma_intr_ack[%d]: Acknowledging IRQ\n", pi->port.line); - - if (pi->mirror_regs) - pi->shared_regs->SDMA_INTR_CAUSE_m = 0; - writeb(0x00, pi->shared_regs->sdma_intr_base + SDMA_INTR_CAUSE - + pi->port.line); -} - -static void mpsc_sdma_set_rx_ring(struct mpsc_port_info *pi, - struct mpsc_rx_desc *rxre_p) -{ - pr_debug("mpsc_sdma_set_rx_ring[%d]: rxre_p: 0x%x\n", - pi->port.line, (u32)rxre_p); - - writel((u32)rxre_p, pi->sdma_base + SDMA_SCRDP); -} - -static void mpsc_sdma_set_tx_ring(struct mpsc_port_info *pi, - struct mpsc_tx_desc *txre_p) -{ - writel((u32)txre_p, pi->sdma_base + SDMA_SFTDP); - writel((u32)txre_p, pi->sdma_base + SDMA_SCTDP); -} - -static void mpsc_sdma_cmd(struct mpsc_port_info *pi, u32 val) -{ - u32 v; - - v = readl(pi->sdma_base + SDMA_SDCM); - if (val) - v |= val; - else - v = 0; - wmb(); - writel(v, pi->sdma_base + SDMA_SDCM); - wmb(); -} - -static uint mpsc_sdma_tx_active(struct mpsc_port_info *pi) -{ - return readl(pi->sdma_base + SDMA_SDCM) & SDMA_SDCM_TXD; -} - -static void mpsc_sdma_start_tx(struct mpsc_port_info *pi) -{ - struct mpsc_tx_desc *txre, *txre_p; - - /* If tx isn't running & there's a desc ready to go, start it */ - if (!mpsc_sdma_tx_active(pi)) { - txre = (struct mpsc_tx_desc *)(pi->txr - + (pi->txr_tail * MPSC_TXRE_SIZE)); - dma_cache_sync(pi->port.dev, (void *)txre, MPSC_TXRE_SIZE, - DMA_FROM_DEVICE); -#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) - if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ - invalidate_dcache_range((ulong)txre, - (ulong)txre + MPSC_TXRE_SIZE); -#endif - - if (be32_to_cpu(txre->cmdstat) & SDMA_DESC_CMDSTAT_O) { - txre_p = (struct mpsc_tx_desc *) - (pi->txr_p + (pi->txr_tail * MPSC_TXRE_SIZE)); - - mpsc_sdma_set_tx_ring(pi, txre_p); - mpsc_sdma_cmd(pi, SDMA_SDCM_STD | SDMA_SDCM_TXD); - } - } -} - -static void mpsc_sdma_stop(struct mpsc_port_info *pi) -{ - pr_debug("mpsc_sdma_stop[%d]: Stopping SDMA\n", pi->port.line); - - /* Abort any SDMA transfers */ - mpsc_sdma_cmd(pi, 0); - mpsc_sdma_cmd(pi, SDMA_SDCM_AR | SDMA_SDCM_AT); - - /* Clear the SDMA current and first TX and RX pointers */ - mpsc_sdma_set_tx_ring(pi, NULL); - mpsc_sdma_set_rx_ring(pi, NULL); - - /* Disable interrupts */ - mpsc_sdma_intr_mask(pi, 0xf); - mpsc_sdma_intr_ack(pi); -} - -/* - ****************************************************************************** - * - * Multi-Protocol Serial Controller Routines (MPSC) - * - ****************************************************************************** - */ - -static void mpsc_hw_init(struct mpsc_port_info *pi) -{ - u32 v; - - pr_debug("mpsc_hw_init[%d]: Initializing hardware\n", pi->port.line); - - /* Set up clock routing */ - if (pi->mirror_regs) { - v = pi->shared_regs->MPSC_MRR_m; - v &= ~0x1c7; - pi->shared_regs->MPSC_MRR_m = v; - writel(v, pi->shared_regs->mpsc_routing_base + MPSC_MRR); - - v = pi->shared_regs->MPSC_RCRR_m; - v = (v & ~0xf0f) | 0x100; - pi->shared_regs->MPSC_RCRR_m = v; - writel(v, pi->shared_regs->mpsc_routing_base + MPSC_RCRR); - - v = pi->shared_regs->MPSC_TCRR_m; - v = (v & ~0xf0f) | 0x100; - pi->shared_regs->MPSC_TCRR_m = v; - writel(v, pi->shared_regs->mpsc_routing_base + MPSC_TCRR); - } else { - v = readl(pi->shared_regs->mpsc_routing_base + MPSC_MRR); - v &= ~0x1c7; - writel(v, pi->shared_regs->mpsc_routing_base + MPSC_MRR); - - v = readl(pi->shared_regs->mpsc_routing_base + MPSC_RCRR); - v = (v & ~0xf0f) | 0x100; - writel(v, pi->shared_regs->mpsc_routing_base + MPSC_RCRR); - - v = readl(pi->shared_regs->mpsc_routing_base + MPSC_TCRR); - v = (v & ~0xf0f) | 0x100; - writel(v, pi->shared_regs->mpsc_routing_base + MPSC_TCRR); - } - - /* Put MPSC in UART mode & enabel Tx/Rx egines */ - writel(0x000004c4, pi->mpsc_base + MPSC_MMCRL); - - /* No preamble, 16x divider, low-latency, */ - writel(0x04400400, pi->mpsc_base + MPSC_MMCRH); - mpsc_set_baudrate(pi, pi->default_baud); - - if (pi->mirror_regs) { - pi->MPSC_CHR_1_m = 0; - pi->MPSC_CHR_2_m = 0; - } - writel(0, pi->mpsc_base + MPSC_CHR_1); - writel(0, pi->mpsc_base + MPSC_CHR_2); - writel(pi->mpsc_max_idle, pi->mpsc_base + MPSC_CHR_3); - writel(0, pi->mpsc_base + MPSC_CHR_4); - writel(0, pi->mpsc_base + MPSC_CHR_5); - writel(0, pi->mpsc_base + MPSC_CHR_6); - writel(0, pi->mpsc_base + MPSC_CHR_7); - writel(0, pi->mpsc_base + MPSC_CHR_8); - writel(0, pi->mpsc_base + MPSC_CHR_9); - writel(0, pi->mpsc_base + MPSC_CHR_10); -} - -static void mpsc_enter_hunt(struct mpsc_port_info *pi) -{ - pr_debug("mpsc_enter_hunt[%d]: Hunting...\n", pi->port.line); - - if (pi->mirror_regs) { - writel(pi->MPSC_CHR_2_m | MPSC_CHR_2_EH, - pi->mpsc_base + MPSC_CHR_2); - /* Erratum prevents reading CHR_2 so just delay for a while */ - udelay(100); - } else { - writel(readl(pi->mpsc_base + MPSC_CHR_2) | MPSC_CHR_2_EH, - pi->mpsc_base + MPSC_CHR_2); - - while (readl(pi->mpsc_base + MPSC_CHR_2) & MPSC_CHR_2_EH) - udelay(10); - } -} - -static void mpsc_freeze(struct mpsc_port_info *pi) -{ - u32 v; - - pr_debug("mpsc_freeze[%d]: Freezing\n", pi->port.line); - - v = (pi->mirror_regs) ? pi->MPSC_MPCR_m : - readl(pi->mpsc_base + MPSC_MPCR); - v |= MPSC_MPCR_FRZ; - - if (pi->mirror_regs) - pi->MPSC_MPCR_m = v; - writel(v, pi->mpsc_base + MPSC_MPCR); -} - -static void mpsc_unfreeze(struct mpsc_port_info *pi) -{ - u32 v; - - v = (pi->mirror_regs) ? pi->MPSC_MPCR_m : - readl(pi->mpsc_base + MPSC_MPCR); - v &= ~MPSC_MPCR_FRZ; - - if (pi->mirror_regs) - pi->MPSC_MPCR_m = v; - writel(v, pi->mpsc_base + MPSC_MPCR); - - pr_debug("mpsc_unfreeze[%d]: Unfrozen\n", pi->port.line); -} - -static void mpsc_set_char_length(struct mpsc_port_info *pi, u32 len) -{ - u32 v; - - pr_debug("mpsc_set_char_length[%d]: char len: %d\n", pi->port.line,len); - - v = (pi->mirror_regs) ? pi->MPSC_MPCR_m : - readl(pi->mpsc_base + MPSC_MPCR); - v = (v & ~(0x3 << 12)) | ((len & 0x3) << 12); - - if (pi->mirror_regs) - pi->MPSC_MPCR_m = v; - writel(v, pi->mpsc_base + MPSC_MPCR); -} - -static void mpsc_set_stop_bit_length(struct mpsc_port_info *pi, u32 len) -{ - u32 v; - - pr_debug("mpsc_set_stop_bit_length[%d]: stop bits: %d\n", - pi->port.line, len); - - v = (pi->mirror_regs) ? pi->MPSC_MPCR_m : - readl(pi->mpsc_base + MPSC_MPCR); - - v = (v & ~(1 << 14)) | ((len & 0x1) << 14); - - if (pi->mirror_regs) - pi->MPSC_MPCR_m = v; - writel(v, pi->mpsc_base + MPSC_MPCR); -} - -static void mpsc_set_parity(struct mpsc_port_info *pi, u32 p) -{ - u32 v; - - pr_debug("mpsc_set_parity[%d]: parity bits: 0x%x\n", pi->port.line, p); - - v = (pi->mirror_regs) ? pi->MPSC_CHR_2_m : - readl(pi->mpsc_base + MPSC_CHR_2); - - p &= 0x3; - v = (v & ~0xc000c) | (p << 18) | (p << 2); - - if (pi->mirror_regs) - pi->MPSC_CHR_2_m = v; - writel(v, pi->mpsc_base + MPSC_CHR_2); -} - -/* - ****************************************************************************** - * - * Driver Init Routines - * - ****************************************************************************** - */ - -static void mpsc_init_hw(struct mpsc_port_info *pi) -{ - pr_debug("mpsc_init_hw[%d]: Initializing\n", pi->port.line); - - mpsc_brg_init(pi, pi->brg_clk_src); - mpsc_brg_enable(pi); - mpsc_sdma_init(pi, dma_get_cache_alignment()); /* burst a cacheline */ - mpsc_sdma_stop(pi); - mpsc_hw_init(pi); -} - -static int mpsc_alloc_ring_mem(struct mpsc_port_info *pi) -{ - int rc = 0; - - pr_debug("mpsc_alloc_ring_mem[%d]: Allocating ring mem\n", - pi->port.line); - - if (!pi->dma_region) { - if (!dma_set_mask(pi->port.dev, 0xffffffff)) { - printk(KERN_ERR "MPSC: Inadequate DMA support\n"); - rc = -ENXIO; - } else if ((pi->dma_region = dma_alloc_attrs(pi->port.dev, - MPSC_DMA_ALLOC_SIZE, - &pi->dma_region_p, GFP_KERNEL, - DMA_ATTR_NON_CONSISTENT)) - == NULL) { - printk(KERN_ERR "MPSC: Can't alloc Desc region\n"); - rc = -ENOMEM; - } - } - - return rc; -} - -static void mpsc_free_ring_mem(struct mpsc_port_info *pi) -{ - pr_debug("mpsc_free_ring_mem[%d]: Freeing ring mem\n", pi->port.line); - - if (pi->dma_region) { - dma_free_attrs(pi->port.dev, MPSC_DMA_ALLOC_SIZE, - pi->dma_region, pi->dma_region_p, - DMA_ATTR_NON_CONSISTENT); - pi->dma_region = NULL; - pi->dma_region_p = (dma_addr_t)NULL; - } -} - -static void mpsc_init_rings(struct mpsc_port_info *pi) -{ - struct mpsc_rx_desc *rxre; - struct mpsc_tx_desc *txre; - dma_addr_t dp, dp_p; - u8 *bp, *bp_p; - int i; - - pr_debug("mpsc_init_rings[%d]: Initializing rings\n", pi->port.line); - - BUG_ON(pi->dma_region == NULL); - - memset(pi->dma_region, 0, MPSC_DMA_ALLOC_SIZE); - - /* - * Descriptors & buffers are multiples of cacheline size and must be - * cacheline aligned. - */ - dp = ALIGN((u32)pi->dma_region, dma_get_cache_alignment()); - dp_p = ALIGN((u32)pi->dma_region_p, dma_get_cache_alignment()); - - /* - * Partition dma region into rx ring descriptor, rx buffers, - * tx ring descriptors, and tx buffers. - */ - pi->rxr = dp; - pi->rxr_p = dp_p; - dp += MPSC_RXR_SIZE; - dp_p += MPSC_RXR_SIZE; - - pi->rxb = (u8 *)dp; - pi->rxb_p = (u8 *)dp_p; - dp += MPSC_RXB_SIZE; - dp_p += MPSC_RXB_SIZE; - - pi->rxr_posn = 0; - - pi->txr = dp; - pi->txr_p = dp_p; - dp += MPSC_TXR_SIZE; - dp_p += MPSC_TXR_SIZE; - - pi->txb = (u8 *)dp; - pi->txb_p = (u8 *)dp_p; - - pi->txr_head = 0; - pi->txr_tail = 0; - - /* Init rx ring descriptors */ - dp = pi->rxr; - dp_p = pi->rxr_p; - bp = pi->rxb; - bp_p = pi->rxb_p; - - for (i = 0; i < MPSC_RXR_ENTRIES; i++) { - rxre = (struct mpsc_rx_desc *)dp; - - rxre->bufsize = cpu_to_be16(MPSC_RXBE_SIZE); - rxre->bytecnt = cpu_to_be16(0); - rxre->cmdstat = cpu_to_be32(SDMA_DESC_CMDSTAT_O - | SDMA_DESC_CMDSTAT_EI | SDMA_DESC_CMDSTAT_F - | SDMA_DESC_CMDSTAT_L); - rxre->link = cpu_to_be32(dp_p + MPSC_RXRE_SIZE); - rxre->buf_ptr = cpu_to_be32(bp_p); - - dp += MPSC_RXRE_SIZE; - dp_p += MPSC_RXRE_SIZE; - bp += MPSC_RXBE_SIZE; - bp_p += MPSC_RXBE_SIZE; - } - rxre->link = cpu_to_be32(pi->rxr_p); /* Wrap last back to first */ - - /* Init tx ring descriptors */ - dp = pi->txr; - dp_p = pi->txr_p; - bp = pi->txb; - bp_p = pi->txb_p; - - for (i = 0; i < MPSC_TXR_ENTRIES; i++) { - txre = (struct mpsc_tx_desc *)dp; - - txre->link = cpu_to_be32(dp_p + MPSC_TXRE_SIZE); - txre->buf_ptr = cpu_to_be32(bp_p); - - dp += MPSC_TXRE_SIZE; - dp_p += MPSC_TXRE_SIZE; - bp += MPSC_TXBE_SIZE; - bp_p += MPSC_TXBE_SIZE; - } - txre->link = cpu_to_be32(pi->txr_p); /* Wrap last back to first */ - - dma_cache_sync(pi->port.dev, (void *)pi->dma_region, - MPSC_DMA_ALLOC_SIZE, DMA_BIDIRECTIONAL); -#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) - if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ - flush_dcache_range((ulong)pi->dma_region, - (ulong)pi->dma_region - + MPSC_DMA_ALLOC_SIZE); -#endif - - return; -} - -static void mpsc_uninit_rings(struct mpsc_port_info *pi) -{ - pr_debug("mpsc_uninit_rings[%d]: Uninitializing rings\n",pi->port.line); - - BUG_ON(pi->dma_region == NULL); - - pi->rxr = 0; - pi->rxr_p = 0; - pi->rxb = NULL; - pi->rxb_p = NULL; - pi->rxr_posn = 0; - - pi->txr = 0; - pi->txr_p = 0; - pi->txb = NULL; - pi->txb_p = NULL; - pi->txr_head = 0; - pi->txr_tail = 0; -} - -static int mpsc_make_ready(struct mpsc_port_info *pi) -{ - int rc; - - pr_debug("mpsc_make_ready[%d]: Making cltr ready\n", pi->port.line); - - if (!pi->ready) { - mpsc_init_hw(pi); - rc = mpsc_alloc_ring_mem(pi); - if (rc) - return rc; - mpsc_init_rings(pi); - pi->ready = 1; - } - - return 0; -} - -#ifdef CONFIG_CONSOLE_POLL -static int serial_polled; -#endif - -/* - ****************************************************************************** - * - * Interrupt Handling Routines - * - ****************************************************************************** - */ - -static int mpsc_rx_intr(struct mpsc_port_info *pi, unsigned long *flags) -{ - struct mpsc_rx_desc *rxre; - struct tty_port *port = &pi->port.state->port; - u32 cmdstat, bytes_in, i; - int rc = 0; - u8 *bp; - char flag = TTY_NORMAL; - - pr_debug("mpsc_rx_intr[%d]: Handling Rx intr\n", pi->port.line); - - rxre = (struct mpsc_rx_desc *)(pi->rxr + (pi->rxr_posn*MPSC_RXRE_SIZE)); - - dma_cache_sync(pi->port.dev, (void *)rxre, MPSC_RXRE_SIZE, - DMA_FROM_DEVICE); -#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) - if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ - invalidate_dcache_range((ulong)rxre, - (ulong)rxre + MPSC_RXRE_SIZE); -#endif - - /* - * Loop through Rx descriptors handling ones that have been completed. - */ - while (!((cmdstat = be32_to_cpu(rxre->cmdstat)) - & SDMA_DESC_CMDSTAT_O)) { - bytes_in = be16_to_cpu(rxre->bytecnt); -#ifdef CONFIG_CONSOLE_POLL - if (unlikely(serial_polled)) { - serial_polled = 0; - return 0; - } -#endif - /* Following use of tty struct directly is deprecated */ - if (tty_buffer_request_room(port, bytes_in) < bytes_in) { - if (port->low_latency) { - spin_unlock_irqrestore(&pi->port.lock, *flags); - tty_flip_buffer_push(port); - spin_lock_irqsave(&pi->port.lock, *flags); - } - /* - * If this failed then we will throw away the bytes - * but must do so to clear interrupts. - */ - } - - bp = pi->rxb + (pi->rxr_posn * MPSC_RXBE_SIZE); - dma_cache_sync(pi->port.dev, (void *)bp, MPSC_RXBE_SIZE, - DMA_FROM_DEVICE); -#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) - if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ - invalidate_dcache_range((ulong)bp, - (ulong)bp + MPSC_RXBE_SIZE); -#endif - - /* - * Other than for parity error, the manual provides little - * info on what data will be in a frame flagged by any of - * these errors. For parity error, it is the last byte in - * the buffer that had the error. As for the rest, I guess - * we'll assume there is no data in the buffer. - * If there is...it gets lost. - */ - if (unlikely(cmdstat & (SDMA_DESC_CMDSTAT_BR - | SDMA_DESC_CMDSTAT_FR - | SDMA_DESC_CMDSTAT_OR))) { - - pi->port.icount.rx++; - - if (cmdstat & SDMA_DESC_CMDSTAT_BR) { /* Break */ - pi->port.icount.brk++; - - if (uart_handle_break(&pi->port)) - goto next_frame; - } else if (cmdstat & SDMA_DESC_CMDSTAT_FR) { - pi->port.icount.frame++; - } else if (cmdstat & SDMA_DESC_CMDSTAT_OR) { - pi->port.icount.overrun++; - } - - cmdstat &= pi->port.read_status_mask; - - if (cmdstat & SDMA_DESC_CMDSTAT_BR) - flag = TTY_BREAK; - else if (cmdstat & SDMA_DESC_CMDSTAT_FR) - flag = TTY_FRAME; - else if (cmdstat & SDMA_DESC_CMDSTAT_OR) - flag = TTY_OVERRUN; - else if (cmdstat & SDMA_DESC_CMDSTAT_PE) - flag = TTY_PARITY; - } - - if (uart_handle_sysrq_char(&pi->port, *bp)) { - bp++; - bytes_in--; -#ifdef CONFIG_CONSOLE_POLL - if (unlikely(serial_polled)) { - serial_polled = 0; - return 0; - } -#endif - goto next_frame; - } - - if ((unlikely(cmdstat & (SDMA_DESC_CMDSTAT_BR - | SDMA_DESC_CMDSTAT_FR - | SDMA_DESC_CMDSTAT_OR))) - && !(cmdstat & pi->port.ignore_status_mask)) { - tty_insert_flip_char(port, *bp, flag); - } else { - for (i=0; i<bytes_in; i++) - tty_insert_flip_char(port, *bp++, TTY_NORMAL); - - pi->port.icount.rx += bytes_in; - } - -next_frame: - rxre->bytecnt = cpu_to_be16(0); - wmb(); - rxre->cmdstat = cpu_to_be32(SDMA_DESC_CMDSTAT_O - | SDMA_DESC_CMDSTAT_EI | SDMA_DESC_CMDSTAT_F - | SDMA_DESC_CMDSTAT_L); - wmb(); - dma_cache_sync(pi->port.dev, (void *)rxre, MPSC_RXRE_SIZE, - DMA_BIDIRECTIONAL); -#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) - if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ - flush_dcache_range((ulong)rxre, - (ulong)rxre + MPSC_RXRE_SIZE); -#endif - - /* Advance to next descriptor */ - pi->rxr_posn = (pi->rxr_posn + 1) & (MPSC_RXR_ENTRIES - 1); - rxre = (struct mpsc_rx_desc *) - (pi->rxr + (pi->rxr_posn * MPSC_RXRE_SIZE)); - dma_cache_sync(pi->port.dev, (void *)rxre, MPSC_RXRE_SIZE, - DMA_FROM_DEVICE); -#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) - if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ - invalidate_dcache_range((ulong)rxre, - (ulong)rxre + MPSC_RXRE_SIZE); -#endif - rc = 1; - } - - /* Restart rx engine, if its stopped */ - if ((readl(pi->sdma_base + SDMA_SDCM) & SDMA_SDCM_ERD) == 0) - mpsc_start_rx(pi); - - spin_unlock_irqrestore(&pi->port.lock, *flags); - tty_flip_buffer_push(port); - spin_lock_irqsave(&pi->port.lock, *flags); - return rc; -} - -static void mpsc_setup_tx_desc(struct mpsc_port_info *pi, u32 count, u32 intr) -{ - struct mpsc_tx_desc *txre; - - txre = (struct mpsc_tx_desc *)(pi->txr - + (pi->txr_head * MPSC_TXRE_SIZE)); - - txre->bytecnt = cpu_to_be16(count); - txre->shadow = txre->bytecnt; - wmb(); /* ensure cmdstat is last field updated */ - txre->cmdstat = cpu_to_be32(SDMA_DESC_CMDSTAT_O | SDMA_DESC_CMDSTAT_F - | SDMA_DESC_CMDSTAT_L - | ((intr) ? SDMA_DESC_CMDSTAT_EI : 0)); - wmb(); - dma_cache_sync(pi->port.dev, (void *)txre, MPSC_TXRE_SIZE, - DMA_BIDIRECTIONAL); -#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) - if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ - flush_dcache_range((ulong)txre, - (ulong)txre + MPSC_TXRE_SIZE); -#endif -} - -static void mpsc_copy_tx_data(struct mpsc_port_info *pi) -{ - struct circ_buf *xmit = &pi->port.state->xmit; - u8 *bp; - u32 i; - - /* Make sure the desc ring isn't full */ - while (CIRC_CNT(pi->txr_head, pi->txr_tail, MPSC_TXR_ENTRIES) - < (MPSC_TXR_ENTRIES - 1)) { - if (pi->port.x_char) { - /* - * Ideally, we should use the TCS field in - * CHR_1 to put the x_char out immediately but - * errata prevents us from being able to read - * CHR_2 to know that its safe to write to - * CHR_1. Instead, just put it in-band with - * all the other Tx data. - */ - bp = pi->txb + (pi->txr_head * MPSC_TXBE_SIZE); - *bp = pi->port.x_char; - pi->port.x_char = 0; - i = 1; - } else if (!uart_circ_empty(xmit) - && !uart_tx_stopped(&pi->port)) { - i = min((u32)MPSC_TXBE_SIZE, - (u32)uart_circ_chars_pending(xmit)); - i = min(i, (u32)CIRC_CNT_TO_END(xmit->head, xmit->tail, - UART_XMIT_SIZE)); - bp = pi->txb + (pi->txr_head * MPSC_TXBE_SIZE); - memcpy(bp, &xmit->buf[xmit->tail], i); - xmit->tail = (xmit->tail + i) & (UART_XMIT_SIZE - 1); - - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(&pi->port); - } else { /* All tx data copied into ring bufs */ - return; - } - - dma_cache_sync(pi->port.dev, (void *)bp, MPSC_TXBE_SIZE, - DMA_BIDIRECTIONAL); -#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) - if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ - flush_dcache_range((ulong)bp, - (ulong)bp + MPSC_TXBE_SIZE); -#endif - mpsc_setup_tx_desc(pi, i, 1); - - /* Advance to next descriptor */ - pi->txr_head = (pi->txr_head + 1) & (MPSC_TXR_ENTRIES - 1); - } -} - -static int mpsc_tx_intr(struct mpsc_port_info *pi) -{ - struct mpsc_tx_desc *txre; - int rc = 0; - unsigned long iflags; - - spin_lock_irqsave(&pi->tx_lock, iflags); - - if (!mpsc_sdma_tx_active(pi)) { - txre = (struct mpsc_tx_desc *)(pi->txr - + (pi->txr_tail * MPSC_TXRE_SIZE)); - - dma_cache_sync(pi->port.dev, (void *)txre, MPSC_TXRE_SIZE, - DMA_FROM_DEVICE); -#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) - if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ - invalidate_dcache_range((ulong)txre, - (ulong)txre + MPSC_TXRE_SIZE); -#endif - - while (!(be32_to_cpu(txre->cmdstat) & SDMA_DESC_CMDSTAT_O)) { - rc = 1; - pi->port.icount.tx += be16_to_cpu(txre->bytecnt); - pi->txr_tail = (pi->txr_tail+1) & (MPSC_TXR_ENTRIES-1); - - /* If no more data to tx, fall out of loop */ - if (pi->txr_head == pi->txr_tail) - break; - - txre = (struct mpsc_tx_desc *)(pi->txr - + (pi->txr_tail * MPSC_TXRE_SIZE)); - dma_cache_sync(pi->port.dev, (void *)txre, - MPSC_TXRE_SIZE, DMA_FROM_DEVICE); -#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) - if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ - invalidate_dcache_range((ulong)txre, - (ulong)txre + MPSC_TXRE_SIZE); -#endif - } - - mpsc_copy_tx_data(pi); - mpsc_sdma_start_tx(pi); /* start next desc if ready */ - } - - spin_unlock_irqrestore(&pi->tx_lock, iflags); - return rc; -} - -/* - * This is the driver's interrupt handler. To avoid a race, we first clear - * the interrupt, then handle any completed Rx/Tx descriptors. When done - * handling those descriptors, we restart the Rx/Tx engines if they're stopped. - */ -static irqreturn_t mpsc_sdma_intr(int irq, void *dev_id) -{ - struct mpsc_port_info *pi = dev_id; - ulong iflags; - int rc = IRQ_NONE; - - pr_debug("mpsc_sdma_intr[%d]: SDMA Interrupt Received\n",pi->port.line); - - spin_lock_irqsave(&pi->port.lock, iflags); - mpsc_sdma_intr_ack(pi); - if (mpsc_rx_intr(pi, &iflags)) - rc = IRQ_HANDLED; - if (mpsc_tx_intr(pi)) - rc = IRQ_HANDLED; - spin_unlock_irqrestore(&pi->port.lock, iflags); - - pr_debug("mpsc_sdma_intr[%d]: SDMA Interrupt Handled\n", pi->port.line); - return rc; -} - -/* - ****************************************************************************** - * - * serial_core.c Interface routines - * - ****************************************************************************** - */ -static uint mpsc_tx_empty(struct uart_port *port) -{ - struct mpsc_port_info *pi = - container_of(port, struct mpsc_port_info, port); - ulong iflags; - uint rc; - - spin_lock_irqsave(&pi->port.lock, iflags); - rc = mpsc_sdma_tx_active(pi) ? 0 : TIOCSER_TEMT; - spin_unlock_irqrestore(&pi->port.lock, iflags); - - return rc; -} - -static void mpsc_set_mctrl(struct uart_port *port, uint mctrl) -{ - /* Have no way to set modem control lines AFAICT */ -} - -static uint mpsc_get_mctrl(struct uart_port *port) -{ - struct mpsc_port_info *pi = - container_of(port, struct mpsc_port_info, port); - u32 mflags, status; - - status = (pi->mirror_regs) ? pi->MPSC_CHR_10_m - : readl(pi->mpsc_base + MPSC_CHR_10); - - mflags = 0; - if (status & 0x1) - mflags |= TIOCM_CTS; - if (status & 0x2) - mflags |= TIOCM_CAR; - - return mflags | TIOCM_DSR; /* No way to tell if DSR asserted */ -} - -static void mpsc_stop_tx(struct uart_port *port) -{ - struct mpsc_port_info *pi = - container_of(port, struct mpsc_port_info, port); - - pr_debug("mpsc_stop_tx[%d]\n", port->line); - - mpsc_freeze(pi); -} - -static void mpsc_start_tx(struct uart_port *port) -{ - struct mpsc_port_info *pi = - container_of(port, struct mpsc_port_info, port); - unsigned long iflags; - - spin_lock_irqsave(&pi->tx_lock, iflags); - - mpsc_unfreeze(pi); - mpsc_copy_tx_data(pi); - mpsc_sdma_start_tx(pi); - - spin_unlock_irqrestore(&pi->tx_lock, iflags); - - pr_debug("mpsc_start_tx[%d]\n", port->line); -} - -static void mpsc_start_rx(struct mpsc_port_info *pi) -{ - pr_debug("mpsc_start_rx[%d]: Starting...\n", pi->port.line); - - if (pi->rcv_data) { - mpsc_enter_hunt(pi); - mpsc_sdma_cmd(pi, SDMA_SDCM_ERD); - } -} - -static void mpsc_stop_rx(struct uart_port *port) -{ - struct mpsc_port_info *pi = - container_of(port, struct mpsc_port_info, port); - - pr_debug("mpsc_stop_rx[%d]: Stopping...\n", port->line); - - if (pi->mirror_regs) { - writel(pi->MPSC_CHR_2_m | MPSC_CHR_2_RA, - pi->mpsc_base + MPSC_CHR_2); - /* Erratum prevents reading CHR_2 so just delay for a while */ - udelay(100); - } else { - writel(readl(pi->mpsc_base + MPSC_CHR_2) | MPSC_CHR_2_RA, - pi->mpsc_base + MPSC_CHR_2); - - while (readl(pi->mpsc_base + MPSC_CHR_2) & MPSC_CHR_2_RA) - udelay(10); - } - - mpsc_sdma_cmd(pi, SDMA_SDCM_AR); -} - -static void mpsc_break_ctl(struct uart_port *port, int ctl) -{ - struct mpsc_port_info *pi = - container_of(port, struct mpsc_port_info, port); - ulong flags; - u32 v; - - v = ctl ? 0x00ff0000 : 0; - - spin_lock_irqsave(&pi->port.lock, flags); - if (pi->mirror_regs) - pi->MPSC_CHR_1_m = v; - writel(v, pi->mpsc_base + MPSC_CHR_1); - spin_unlock_irqrestore(&pi->port.lock, flags); -} - -static int mpsc_startup(struct uart_port *port) -{ - struct mpsc_port_info *pi = - container_of(port, struct mpsc_port_info, port); - u32 flag = 0; - int rc; - - pr_debug("mpsc_startup[%d]: Starting up MPSC, irq: %d\n", - port->line, pi->port.irq); - - if ((rc = mpsc_make_ready(pi)) == 0) { - /* Setup IRQ handler */ - mpsc_sdma_intr_ack(pi); - - /* If irq's are shared, need to set flag */ - if (mpsc_ports[0].port.irq == mpsc_ports[1].port.irq) - flag = IRQF_SHARED; - - if (request_irq(pi->port.irq, mpsc_sdma_intr, flag, - "mpsc-sdma", pi)) - printk(KERN_ERR "MPSC: Can't get SDMA IRQ %d\n", - pi->port.irq); - - mpsc_sdma_intr_unmask(pi, 0xf); - mpsc_sdma_set_rx_ring(pi, (struct mpsc_rx_desc *)(pi->rxr_p - + (pi->rxr_posn * MPSC_RXRE_SIZE))); - } - - return rc; -} - -static void mpsc_shutdown(struct uart_port *port) -{ - struct mpsc_port_info *pi = - container_of(port, struct mpsc_port_info, port); - - pr_debug("mpsc_shutdown[%d]: Shutting down MPSC\n", port->line); - - mpsc_sdma_stop(pi); - free_irq(pi->port.irq, pi); -} - -static void mpsc_set_termios(struct uart_port *port, struct ktermios *termios, - struct ktermios *old) -{ - struct mpsc_port_info *pi = - container_of(port, struct mpsc_port_info, port); - u32 baud; - ulong flags; - u32 chr_bits, stop_bits, par; - - switch (termios->c_cflag & CSIZE) { - case CS5: - chr_bits = MPSC_MPCR_CL_5; - break; - case CS6: - chr_bits = MPSC_MPCR_CL_6; - break; - case CS7: - chr_bits = MPSC_MPCR_CL_7; - break; - case CS8: - default: - chr_bits = MPSC_MPCR_CL_8; - break; - } - - if (termios->c_cflag & CSTOPB) - stop_bits = MPSC_MPCR_SBL_2; - else - stop_bits = MPSC_MPCR_SBL_1; - - par = MPSC_CHR_2_PAR_EVEN; - if (termios->c_cflag & PARENB) - if (termios->c_cflag & PARODD) - par = MPSC_CHR_2_PAR_ODD; -#ifdef CMSPAR - if (termios->c_cflag & CMSPAR) { - if (termios->c_cflag & PARODD) - par = MPSC_CHR_2_PAR_MARK; - else - par = MPSC_CHR_2_PAR_SPACE; - } -#endif - - baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk); - - spin_lock_irqsave(&pi->port.lock, flags); - - uart_update_timeout(port, termios->c_cflag, baud); - - mpsc_set_char_length(pi, chr_bits); - mpsc_set_stop_bit_length(pi, stop_bits); - mpsc_set_parity(pi, par); - mpsc_set_baudrate(pi, baud); - - /* Characters/events to read */ - pi->port.read_status_mask = SDMA_DESC_CMDSTAT_OR; - - if (termios->c_iflag & INPCK) - pi->port.read_status_mask |= SDMA_DESC_CMDSTAT_PE - | SDMA_DESC_CMDSTAT_FR; - - if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK)) - pi->port.read_status_mask |= SDMA_DESC_CMDSTAT_BR; - - /* Characters/events to ignore */ - pi->port.ignore_status_mask = 0; - - if (termios->c_iflag & IGNPAR) - pi->port.ignore_status_mask |= SDMA_DESC_CMDSTAT_PE - | SDMA_DESC_CMDSTAT_FR; - - if (termios->c_iflag & IGNBRK) { - pi->port.ignore_status_mask |= SDMA_DESC_CMDSTAT_BR; - - if (termios->c_iflag & IGNPAR) - pi->port.ignore_status_mask |= SDMA_DESC_CMDSTAT_OR; - } - - if ((termios->c_cflag & CREAD)) { - if (!pi->rcv_data) { - pi->rcv_data = 1; - mpsc_start_rx(pi); - } - } else if (pi->rcv_data) { - mpsc_stop_rx(port); - pi->rcv_data = 0; - } - - spin_unlock_irqrestore(&pi->port.lock, flags); -} - -static const char *mpsc_type(struct uart_port *port) -{ - pr_debug("mpsc_type[%d]: port type: %s\n", port->line,MPSC_DRIVER_NAME); - return MPSC_DRIVER_NAME; -} - -static int mpsc_request_port(struct uart_port *port) -{ - /* Should make chip/platform specific call */ - return 0; -} - -static void mpsc_release_port(struct uart_port *port) -{ - struct mpsc_port_info *pi = - container_of(port, struct mpsc_port_info, port); - - if (pi->ready) { - mpsc_uninit_rings(pi); - mpsc_free_ring_mem(pi); - pi->ready = 0; - } -} - -static void mpsc_config_port(struct uart_port *port, int flags) -{ -} - -static int mpsc_verify_port(struct uart_port *port, struct serial_struct *ser) -{ - struct mpsc_port_info *pi = - container_of(port, struct mpsc_port_info, port); - int rc = 0; - - pr_debug("mpsc_verify_port[%d]: Verifying port data\n", pi->port.line); - - if (ser->type != PORT_UNKNOWN && ser->type != PORT_MPSC) - rc = -EINVAL; - else if (pi->port.irq != ser->irq) - rc = -EINVAL; - else if (ser->io_type != SERIAL_IO_MEM) - rc = -EINVAL; - else if (pi->port.uartclk / 16 != ser->baud_base) /* Not sure */ - rc = -EINVAL; - else if ((void *)pi->port.mapbase != ser->iomem_base) - rc = -EINVAL; - else if (pi->port.iobase != ser->port) - rc = -EINVAL; - else if (ser->hub6 != 0) - rc = -EINVAL; - - return rc; -} -#ifdef CONFIG_CONSOLE_POLL -/* Serial polling routines for writing and reading from the uart while - * in an interrupt or debug context. - */ - -static char poll_buf[2048]; -static int poll_ptr; -static int poll_cnt; -static void mpsc_put_poll_char(struct uart_port *port, - unsigned char c); - -static int mpsc_get_poll_char(struct uart_port *port) -{ - struct mpsc_port_info *pi = - container_of(port, struct mpsc_port_info, port); - struct mpsc_rx_desc *rxre; - u32 cmdstat, bytes_in, i; - u8 *bp; - - if (!serial_polled) - serial_polled = 1; - - pr_debug("mpsc_rx_intr[%d]: Handling Rx intr\n", pi->port.line); - - if (poll_cnt) { - poll_cnt--; - return poll_buf[poll_ptr++]; - } - poll_ptr = 0; - poll_cnt = 0; - - while (poll_cnt == 0) { - rxre = (struct mpsc_rx_desc *)(pi->rxr + - (pi->rxr_posn*MPSC_RXRE_SIZE)); - dma_cache_sync(pi->port.dev, (void *)rxre, - MPSC_RXRE_SIZE, DMA_FROM_DEVICE); -#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) - if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ - invalidate_dcache_range((ulong)rxre, - (ulong)rxre + MPSC_RXRE_SIZE); -#endif - /* - * Loop through Rx descriptors handling ones that have - * been completed. - */ - while (poll_cnt == 0 && - !((cmdstat = be32_to_cpu(rxre->cmdstat)) & - SDMA_DESC_CMDSTAT_O)){ - bytes_in = be16_to_cpu(rxre->bytecnt); - bp = pi->rxb + (pi->rxr_posn * MPSC_RXBE_SIZE); - dma_cache_sync(pi->port.dev, (void *) bp, - MPSC_RXBE_SIZE, DMA_FROM_DEVICE); -#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) - if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ - invalidate_dcache_range((ulong)bp, - (ulong)bp + MPSC_RXBE_SIZE); -#endif - if ((unlikely(cmdstat & (SDMA_DESC_CMDSTAT_BR | - SDMA_DESC_CMDSTAT_FR | SDMA_DESC_CMDSTAT_OR))) && - !(cmdstat & pi->port.ignore_status_mask)) { - poll_buf[poll_cnt] = *bp; - poll_cnt++; - } else { - for (i = 0; i < bytes_in; i++) { - poll_buf[poll_cnt] = *bp++; - poll_cnt++; - } - pi->port.icount.rx += bytes_in; - } - rxre->bytecnt = cpu_to_be16(0); - wmb(); - rxre->cmdstat = cpu_to_be32(SDMA_DESC_CMDSTAT_O | - SDMA_DESC_CMDSTAT_EI | - SDMA_DESC_CMDSTAT_F | - SDMA_DESC_CMDSTAT_L); - wmb(); - dma_cache_sync(pi->port.dev, (void *)rxre, - MPSC_RXRE_SIZE, DMA_BIDIRECTIONAL); -#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) - if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ - flush_dcache_range((ulong)rxre, - (ulong)rxre + MPSC_RXRE_SIZE); -#endif - - /* Advance to next descriptor */ - pi->rxr_posn = (pi->rxr_posn + 1) & - (MPSC_RXR_ENTRIES - 1); - rxre = (struct mpsc_rx_desc *)(pi->rxr + - (pi->rxr_posn * MPSC_RXRE_SIZE)); - dma_cache_sync(pi->port.dev, (void *)rxre, - MPSC_RXRE_SIZE, DMA_FROM_DEVICE); -#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) - if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ - invalidate_dcache_range((ulong)rxre, - (ulong)rxre + MPSC_RXRE_SIZE); -#endif - } - - /* Restart rx engine, if its stopped */ - if ((readl(pi->sdma_base + SDMA_SDCM) & SDMA_SDCM_ERD) == 0) - mpsc_start_rx(pi); - } - if (poll_cnt) { - poll_cnt--; - return poll_buf[poll_ptr++]; - } - - return 0; -} - - -static void mpsc_put_poll_char(struct uart_port *port, - unsigned char c) -{ - struct mpsc_port_info *pi = - container_of(port, struct mpsc_port_info, port); - u32 data; - - data = readl(pi->mpsc_base + MPSC_MPCR); - writeb(c, pi->mpsc_base + MPSC_CHR_1); - mb(); - data = readl(pi->mpsc_base + MPSC_CHR_2); - data |= MPSC_CHR_2_TTCS; - writel(data, pi->mpsc_base + MPSC_CHR_2); - mb(); - - while (readl(pi->mpsc_base + MPSC_CHR_2) & MPSC_CHR_2_TTCS); -} -#endif - -static const struct uart_ops mpsc_pops = { - .tx_empty = mpsc_tx_empty, - .set_mctrl = mpsc_set_mctrl, - .get_mctrl = mpsc_get_mctrl, - .stop_tx = mpsc_stop_tx, - .start_tx = mpsc_start_tx, - .stop_rx = mpsc_stop_rx, - .break_ctl = mpsc_break_ctl, - .startup = mpsc_startup, - .shutdown = mpsc_shutdown, - .set_termios = mpsc_set_termios, - .type = mpsc_type, - .release_port = mpsc_release_port, - .request_port = mpsc_request_port, - .config_port = mpsc_config_port, - .verify_port = mpsc_verify_port, -#ifdef CONFIG_CONSOLE_POLL - .poll_get_char = mpsc_get_poll_char, - .poll_put_char = mpsc_put_poll_char, -#endif -}; - -/* - ****************************************************************************** - * - * Console Interface Routines - * - ****************************************************************************** - */ - -#ifdef CONFIG_SERIAL_MPSC_CONSOLE -static void mpsc_console_write(struct console *co, const char *s, uint count) -{ - struct mpsc_port_info *pi = &mpsc_ports[co->index]; - u8 *bp, *dp, add_cr = 0; - int i; - unsigned long iflags; - - spin_lock_irqsave(&pi->tx_lock, iflags); - - while (pi->txr_head != pi->txr_tail) { - while (mpsc_sdma_tx_active(pi)) - udelay(100); - mpsc_sdma_intr_ack(pi); - mpsc_tx_intr(pi); - } - - while (mpsc_sdma_tx_active(pi)) - udelay(100); - - while (count > 0) { - bp = dp = pi->txb + (pi->txr_head * MPSC_TXBE_SIZE); - - for (i = 0; i < MPSC_TXBE_SIZE; i++) { - if (count == 0) - break; - - if (add_cr) { - *(dp++) = '\r'; - add_cr = 0; - } else { - *(dp++) = *s; - - if (*(s++) == '\n') { /* add '\r' after '\n' */ - add_cr = 1; - count++; - } - } - - count--; - } - - dma_cache_sync(pi->port.dev, (void *)bp, MPSC_TXBE_SIZE, - DMA_BIDIRECTIONAL); -#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) - if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ - flush_dcache_range((ulong)bp, - (ulong)bp + MPSC_TXBE_SIZE); -#endif - mpsc_setup_tx_desc(pi, i, 0); - pi->txr_head = (pi->txr_head + 1) & (MPSC_TXR_ENTRIES - 1); - mpsc_sdma_start_tx(pi); - - while (mpsc_sdma_tx_active(pi)) - udelay(100); - - pi->txr_tail = (pi->txr_tail + 1) & (MPSC_TXR_ENTRIES - 1); - } - - spin_unlock_irqrestore(&pi->tx_lock, iflags); -} - -static int __init mpsc_console_setup(struct console *co, char *options) -{ - struct mpsc_port_info *pi; - int baud, bits, parity, flow; - - pr_debug("mpsc_console_setup[%d]: options: %s\n", co->index, options); - - if (co->index >= MPSC_NUM_CTLRS) - co->index = 0; - - pi = &mpsc_ports[co->index]; - - baud = pi->default_baud; - bits = pi->default_bits; - parity = pi->default_parity; - flow = pi->default_flow; - - if (!pi->port.ops) - return -ENODEV; - - spin_lock_init(&pi->port.lock); /* Temporary fix--copied from 8250.c */ - - if (options) - uart_parse_options(options, &baud, &parity, &bits, &flow); - - return uart_set_options(&pi->port, co, baud, parity, bits, flow); -} - -static struct console mpsc_console = { - .name = MPSC_DEV_NAME, - .write = mpsc_console_write, - .device = uart_console_device, - .setup = mpsc_console_setup, - .flags = CON_PRINTBUFFER, - .index = -1, - .data = &mpsc_reg, -}; - -static int __init mpsc_late_console_init(void) -{ - pr_debug("mpsc_late_console_init: Enter\n"); - - if (!(mpsc_console.flags & CON_ENABLED)) - register_console(&mpsc_console); - return 0; -} - -late_initcall(mpsc_late_console_init); - -#define MPSC_CONSOLE &mpsc_console -#else -#define MPSC_CONSOLE NULL -#endif -/* - ****************************************************************************** - * - * Dummy Platform Driver to extract & map shared register regions - * - ****************************************************************************** - */ -static void mpsc_resource_err(char *s) -{ - printk(KERN_WARNING "MPSC: Platform device resource error in %s\n", s); -} - -static int mpsc_shared_map_regs(struct platform_device *pd) -{ - struct resource *r; - - if ((r = platform_get_resource(pd, IORESOURCE_MEM, - MPSC_ROUTING_BASE_ORDER)) - && request_mem_region(r->start, - MPSC_ROUTING_REG_BLOCK_SIZE, - "mpsc_routing_regs")) { - mpsc_shared_regs.mpsc_routing_base = ioremap(r->start, - MPSC_ROUTING_REG_BLOCK_SIZE); - mpsc_shared_regs.mpsc_routing_base_p = r->start; - } else { - mpsc_resource_err("MPSC routing base"); - return -ENOMEM; - } - - if ((r = platform_get_resource(pd, IORESOURCE_MEM, - MPSC_SDMA_INTR_BASE_ORDER)) - && request_mem_region(r->start, - MPSC_SDMA_INTR_REG_BLOCK_SIZE, - "sdma_intr_regs")) { - mpsc_shared_regs.sdma_intr_base = ioremap(r->start, - MPSC_SDMA_INTR_REG_BLOCK_SIZE); - mpsc_shared_regs.sdma_intr_base_p = r->start; - } else { - iounmap(mpsc_shared_regs.mpsc_routing_base); - release_mem_region(mpsc_shared_regs.mpsc_routing_base_p, - MPSC_ROUTING_REG_BLOCK_SIZE); - mpsc_resource_err("SDMA intr base"); - return -ENOMEM; - } - - return 0; -} - -static void mpsc_shared_unmap_regs(void) -{ - if (mpsc_shared_regs.mpsc_routing_base) { - iounmap(mpsc_shared_regs.mpsc_routing_base); - release_mem_region(mpsc_shared_regs.mpsc_routing_base_p, - MPSC_ROUTING_REG_BLOCK_SIZE); - } - if (mpsc_shared_regs.sdma_intr_base) { - iounmap(mpsc_shared_regs.sdma_intr_base); - release_mem_region(mpsc_shared_regs.sdma_intr_base_p, - MPSC_SDMA_INTR_REG_BLOCK_SIZE); - } - - mpsc_shared_regs.mpsc_routing_base = NULL; - mpsc_shared_regs.sdma_intr_base = NULL; - - mpsc_shared_regs.mpsc_routing_base_p = 0; - mpsc_shared_regs.sdma_intr_base_p = 0; -} - -static int mpsc_shared_drv_probe(struct platform_device *dev) -{ - struct mpsc_shared_pdata *pdata; - int rc; - - if (dev->id != 0) - return -ENODEV; - - rc = mpsc_shared_map_regs(dev); - if (rc) - return rc; - - pdata = dev_get_platdata(&dev->dev); - - mpsc_shared_regs.MPSC_MRR_m = pdata->mrr_val; - mpsc_shared_regs.MPSC_RCRR_m= pdata->rcrr_val; - mpsc_shared_regs.MPSC_TCRR_m= pdata->tcrr_val; - mpsc_shared_regs.SDMA_INTR_CAUSE_m = pdata->intr_cause_val; - mpsc_shared_regs.SDMA_INTR_MASK_m = pdata->intr_mask_val; - - return 0; -} - -static int mpsc_shared_drv_remove(struct platform_device *dev) -{ - if (dev->id != 0) - return -ENODEV; - - mpsc_shared_unmap_regs(); - mpsc_shared_regs.MPSC_MRR_m = 0; - mpsc_shared_regs.MPSC_RCRR_m = 0; - mpsc_shared_regs.MPSC_TCRR_m = 0; - mpsc_shared_regs.SDMA_INTR_CAUSE_m = 0; - mpsc_shared_regs.SDMA_INTR_MASK_m = 0; - - return 0; -} - -static struct platform_driver mpsc_shared_driver = { - .probe = mpsc_shared_drv_probe, - .remove = mpsc_shared_drv_remove, - .driver = { - .name = MPSC_SHARED_NAME, - }, -}; - -/* - ****************************************************************************** - * - * Driver Interface Routines - * - ****************************************************************************** - */ -static struct uart_driver mpsc_reg = { - .owner = THIS_MODULE, - .driver_name = MPSC_DRIVER_NAME, - .dev_name = MPSC_DEV_NAME, - .major = MPSC_MAJOR, - .minor = MPSC_MINOR_START, - .nr = MPSC_NUM_CTLRS, - .cons = MPSC_CONSOLE, -}; - -static int mpsc_drv_map_regs(struct mpsc_port_info *pi, - struct platform_device *pd) -{ - struct resource *r; - - if ((r = platform_get_resource(pd, IORESOURCE_MEM, MPSC_BASE_ORDER)) - && request_mem_region(r->start, MPSC_REG_BLOCK_SIZE, - "mpsc_regs")) { - pi->mpsc_base = ioremap(r->start, MPSC_REG_BLOCK_SIZE); - pi->mpsc_base_p = r->start; - } else { - mpsc_resource_err("MPSC base"); - goto err; - } - - if ((r = platform_get_resource(pd, IORESOURCE_MEM, - MPSC_SDMA_BASE_ORDER)) - && request_mem_region(r->start, - MPSC_SDMA_REG_BLOCK_SIZE, "sdma_regs")) { - pi->sdma_base = ioremap(r->start,MPSC_SDMA_REG_BLOCK_SIZE); - pi->sdma_base_p = r->start; - } else { - mpsc_resource_err("SDMA base"); - goto err; - } - - if ((r = platform_get_resource(pd,IORESOURCE_MEM,MPSC_BRG_BASE_ORDER)) - && request_mem_region(r->start, - MPSC_BRG_REG_BLOCK_SIZE, "brg_regs")) { - pi->brg_base = ioremap(r->start, MPSC_BRG_REG_BLOCK_SIZE); - pi->brg_base_p = r->start; - } else { - mpsc_resource_err("BRG base"); - goto err; - } - return 0; - -err: - if (pi->sdma_base) { - iounmap(pi->sdma_base); - pi->sdma_base = NULL; - } - if (pi->mpsc_base) { - iounmap(pi->mpsc_base); - pi->mpsc_base = NULL; - } - return -ENOMEM; -} - -static void mpsc_drv_unmap_regs(struct mpsc_port_info *pi) -{ - if (pi->mpsc_base) { - iounmap(pi->mpsc_base); - release_mem_region(pi->mpsc_base_p, MPSC_REG_BLOCK_SIZE); - } - if (pi->sdma_base) { - iounmap(pi->sdma_base); - release_mem_region(pi->sdma_base_p, MPSC_SDMA_REG_BLOCK_SIZE); - } - if (pi->brg_base) { - iounmap(pi->brg_base); - release_mem_region(pi->brg_base_p, MPSC_BRG_REG_BLOCK_SIZE); - } - - pi->mpsc_base = NULL; - pi->sdma_base = NULL; - pi->brg_base = NULL; - - pi->mpsc_base_p = 0; - pi->sdma_base_p = 0; - pi->brg_base_p = 0; -} - -static void mpsc_drv_get_platform_data(struct mpsc_port_info *pi, - struct platform_device *pd, int num) -{ - struct mpsc_pdata *pdata; - - pdata = dev_get_platdata(&pd->dev); - - pi->port.uartclk = pdata->brg_clk_freq; - pi->port.iotype = UPIO_MEM; - pi->port.line = num; - pi->port.type = PORT_MPSC; - pi->port.fifosize = MPSC_TXBE_SIZE; - pi->port.membase = pi->mpsc_base; - pi->port.mapbase = (ulong)pi->mpsc_base; - pi->port.ops = &mpsc_pops; - - pi->mirror_regs = pdata->mirror_regs; - pi->cache_mgmt = pdata->cache_mgmt; - pi->brg_can_tune = pdata->brg_can_tune; - pi->brg_clk_src = pdata->brg_clk_src; - pi->mpsc_max_idle = pdata->max_idle; - pi->default_baud = pdata->default_baud; - pi->default_bits = pdata->default_bits; - pi->default_parity = pdata->default_parity; - pi->default_flow = pdata->default_flow; - - /* Initial values of mirrored regs */ - pi->MPSC_CHR_1_m = pdata->chr_1_val; - pi->MPSC_CHR_2_m = pdata->chr_2_val; - pi->MPSC_CHR_10_m = pdata->chr_10_val; - pi->MPSC_MPCR_m = pdata->mpcr_val; - pi->BRG_BCR_m = pdata->bcr_val; - - pi->shared_regs = &mpsc_shared_regs; - - pi->port.irq = platform_get_irq(pd, 0); -} - -static int mpsc_drv_probe(struct platform_device *dev) -{ - struct mpsc_port_info *pi; - int rc; - - dev_dbg(&dev->dev, "mpsc_drv_probe: Adding MPSC %d\n", dev->id); - - if (dev->id >= MPSC_NUM_CTLRS) - return -ENODEV; - - pi = &mpsc_ports[dev->id]; - - rc = mpsc_drv_map_regs(pi, dev); - if (rc) - return rc; - - mpsc_drv_get_platform_data(pi, dev, dev->id); - pi->port.dev = &dev->dev; - - rc = mpsc_make_ready(pi); - if (rc) - goto err_unmap; - - spin_lock_init(&pi->tx_lock); - rc = uart_add_one_port(&mpsc_reg, &pi->port); - if (rc) - goto err_relport; - - return 0; -err_relport: - mpsc_release_port(&pi->port); -err_unmap: - mpsc_drv_unmap_regs(pi); - return rc; -} - -static struct platform_driver mpsc_driver = { - .probe = mpsc_drv_probe, - .driver = { - .name = MPSC_CTLR_NAME, - .suppress_bind_attrs = true, - }, -}; - -static int __init mpsc_drv_init(void) -{ - int rc; - - printk(KERN_INFO "Serial: MPSC driver\n"); - - memset(mpsc_ports, 0, sizeof(mpsc_ports)); - memset(&mpsc_shared_regs, 0, sizeof(mpsc_shared_regs)); - - rc = uart_register_driver(&mpsc_reg); - if (rc) - return rc; - - rc = platform_driver_register(&mpsc_shared_driver); - if (rc) - goto err_unreg_uart; - - rc = platform_driver_register(&mpsc_driver); - if (rc) - goto err_unreg_plat; - - return 0; -err_unreg_plat: - platform_driver_unregister(&mpsc_shared_driver); -err_unreg_uart: - uart_unregister_driver(&mpsc_reg); - return rc; -} -device_initcall(mpsc_drv_init); - -/* -MODULE_AUTHOR("Mark A. Greer <mgreer@mvista.com>"); -MODULE_DESCRIPTION("Generic Marvell MPSC serial/UART driver"); -MODULE_LICENSE("GPL"); -*/ diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c index 23833ad952ba..3657a24913fc 100644 --- a/drivers/tty/serial/msm_serial.c +++ b/drivers/tty/serial/msm_serial.c @@ -383,10 +383,14 @@ no_rx: static inline void msm_wait_for_xmitr(struct uart_port *port) { + unsigned int timeout = 500000; + while (!(msm_read(port, UART_SR) & UART_SR_TX_EMPTY)) { if (msm_read(port, UART_ISR) & UART_ISR_TX_READY) break; udelay(1); + if (!timeout--) + break; } msm_write(port, UART_CR_CMD_RESET_TX_READY, UART_CR); } diff --git a/drivers/tty/serial/mvebu-uart.c b/drivers/tty/serial/mvebu-uart.c index 7e7b1559fa36..c12a12556339 100644 --- a/drivers/tty/serial/mvebu-uart.c +++ b/drivers/tty/serial/mvebu-uart.c @@ -884,10 +884,8 @@ static int mvebu_uart_probe(struct platform_device *pdev) if (platform_irq_count(pdev) == 1) { /* Old bindings: no name on the single unamed UART0 IRQ */ irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "unable to get UART IRQ\n"); + if (irq < 0) return irq; - } mvuart->irq[UART_IRQ_SUM] = irq; } else { @@ -897,18 +895,14 @@ static int mvebu_uart_probe(struct platform_device *pdev) * uart-sum of UART0 port. */ irq = platform_get_irq_byname(pdev, "uart-rx"); - if (irq < 0) { - dev_err(&pdev->dev, "unable to get 'uart-rx' IRQ\n"); + if (irq < 0) return irq; - } mvuart->irq[UART_RX_IRQ] = irq; irq = platform_get_irq_byname(pdev, "uart-tx"); - if (irq < 0) { - dev_err(&pdev->dev, "unable to get 'uart-tx' IRQ\n"); + if (irq < 0) return irq; - } mvuart->irq[UART_TX_IRQ] = irq; } diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c index 4c188f4079b3..e34525970682 100644 --- a/drivers/tty/serial/mxs-auart.c +++ b/drivers/tty/serial/mxs-auart.c @@ -969,10 +969,8 @@ err_out: } -#define RTS_AT_AUART() IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(s->gpios, \ - UART_GPIO_RTS)) -#define CTS_AT_AUART() IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(s->gpios, \ - UART_GPIO_CTS)) +#define RTS_AT_AUART() !mctrl_gpio_to_gpiod(s->gpios, UART_GPIO_RTS) +#define CTS_AT_AUART() !mctrl_gpio_to_gpiod(s->gpios, UART_GPIO_CTS) static void mxs_auart_settermios(struct uart_port *u, struct ktermios *termios, struct ktermios *old) diff --git a/drivers/tty/serial/netx-serial.c b/drivers/tty/serial/netx-serial.c deleted file mode 100644 index b3556863491f..000000000000 --- a/drivers/tty/serial/netx-serial.c +++ /dev/null @@ -1,733 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix - */ - -#if defined(CONFIG_SERIAL_NETX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - -#include <linux/device.h> -#include <linux/module.h> -#include <linux/ioport.h> -#include <linux/init.h> -#include <linux/console.h> -#include <linux/sysrq.h> -#include <linux/platform_device.h> -#include <linux/tty.h> -#include <linux/tty_flip.h> -#include <linux/serial_core.h> -#include <linux/serial.h> - -#include <asm/io.h> -#include <asm/irq.h> -#include <mach/hardware.h> -#include <mach/netx-regs.h> - -/* We've been assigned a range on the "Low-density serial ports" major */ -#define SERIAL_NX_MAJOR 204 -#define MINOR_START 170 - -enum uart_regs { - UART_DR = 0x00, - UART_SR = 0x04, - UART_LINE_CR = 0x08, - UART_BAUDDIV_MSB = 0x0c, - UART_BAUDDIV_LSB = 0x10, - UART_CR = 0x14, - UART_FR = 0x18, - UART_IIR = 0x1c, - UART_ILPR = 0x20, - UART_RTS_CR = 0x24, - UART_RTS_LEAD = 0x28, - UART_RTS_TRAIL = 0x2c, - UART_DRV_ENABLE = 0x30, - UART_BRM_CR = 0x34, - UART_RXFIFO_IRQLEVEL = 0x38, - UART_TXFIFO_IRQLEVEL = 0x3c, -}; - -#define SR_FE (1<<0) -#define SR_PE (1<<1) -#define SR_BE (1<<2) -#define SR_OE (1<<3) - -#define LINE_CR_BRK (1<<0) -#define LINE_CR_PEN (1<<1) -#define LINE_CR_EPS (1<<2) -#define LINE_CR_STP2 (1<<3) -#define LINE_CR_FEN (1<<4) -#define LINE_CR_5BIT (0<<5) -#define LINE_CR_6BIT (1<<5) -#define LINE_CR_7BIT (2<<5) -#define LINE_CR_8BIT (3<<5) -#define LINE_CR_BITS_MASK (3<<5) - -#define CR_UART_EN (1<<0) -#define CR_SIREN (1<<1) -#define CR_SIRLP (1<<2) -#define CR_MSIE (1<<3) -#define CR_RIE (1<<4) -#define CR_TIE (1<<5) -#define CR_RTIE (1<<6) -#define CR_LBE (1<<7) - -#define FR_CTS (1<<0) -#define FR_DSR (1<<1) -#define FR_DCD (1<<2) -#define FR_BUSY (1<<3) -#define FR_RXFE (1<<4) -#define FR_TXFF (1<<5) -#define FR_RXFF (1<<6) -#define FR_TXFE (1<<7) - -#define IIR_MIS (1<<0) -#define IIR_RIS (1<<1) -#define IIR_TIS (1<<2) -#define IIR_RTIS (1<<3) -#define IIR_MASK 0xf - -#define RTS_CR_AUTO (1<<0) -#define RTS_CR_RTS (1<<1) -#define RTS_CR_COUNT (1<<2) -#define RTS_CR_MOD2 (1<<3) -#define RTS_CR_RTS_POL (1<<4) -#define RTS_CR_CTS_CTR (1<<5) -#define RTS_CR_CTS_POL (1<<6) -#define RTS_CR_STICK (1<<7) - -#define UART_PORT_SIZE 0x40 -#define DRIVER_NAME "netx-uart" - -struct netx_port { - struct uart_port port; -}; - -static void netx_stop_tx(struct uart_port *port) -{ - unsigned int val; - val = readl(port->membase + UART_CR); - writel(val & ~CR_TIE, port->membase + UART_CR); -} - -static void netx_stop_rx(struct uart_port *port) -{ - unsigned int val; - val = readl(port->membase + UART_CR); - writel(val & ~CR_RIE, port->membase + UART_CR); -} - -static void netx_enable_ms(struct uart_port *port) -{ - unsigned int val; - val = readl(port->membase + UART_CR); - writel(val | CR_MSIE, port->membase + UART_CR); -} - -static inline void netx_transmit_buffer(struct uart_port *port) -{ - struct circ_buf *xmit = &port->state->xmit; - - if (port->x_char) { - writel(port->x_char, port->membase + UART_DR); - port->icount.tx++; - port->x_char = 0; - return; - } - - if (uart_tx_stopped(port) || uart_circ_empty(xmit)) { - netx_stop_tx(port); - return; - } - - do { - /* send xmit->buf[xmit->tail] - * out the port here */ - writel(xmit->buf[xmit->tail], port->membase + UART_DR); - xmit->tail = (xmit->tail + 1) & - (UART_XMIT_SIZE - 1); - port->icount.tx++; - if (uart_circ_empty(xmit)) - break; - } while (!(readl(port->membase + UART_FR) & FR_TXFF)); - - if (uart_circ_empty(xmit)) - netx_stop_tx(port); -} - -static void netx_start_tx(struct uart_port *port) -{ - writel( - readl(port->membase + UART_CR) | CR_TIE, port->membase + UART_CR); - - if (!(readl(port->membase + UART_FR) & FR_TXFF)) - netx_transmit_buffer(port); -} - -static unsigned int netx_tx_empty(struct uart_port *port) -{ - return readl(port->membase + UART_FR) & FR_BUSY ? 0 : TIOCSER_TEMT; -} - -static void netx_txint(struct uart_port *port) -{ - struct circ_buf *xmit = &port->state->xmit; - - if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { - netx_stop_tx(port); - return; - } - - netx_transmit_buffer(port); - - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(port); -} - -static void netx_rxint(struct uart_port *port, unsigned long *flags) -{ - unsigned char rx, flg, status; - - while (!(readl(port->membase + UART_FR) & FR_RXFE)) { - rx = readl(port->membase + UART_DR); - flg = TTY_NORMAL; - port->icount.rx++; - status = readl(port->membase + UART_SR); - if (status & SR_BE) { - writel(0, port->membase + UART_SR); - if (uart_handle_break(port)) - continue; - } - - if (unlikely(status & (SR_FE | SR_PE | SR_OE))) { - - if (status & SR_PE) - port->icount.parity++; - else if (status & SR_FE) - port->icount.frame++; - if (status & SR_OE) - port->icount.overrun++; - - status &= port->read_status_mask; - - if (status & SR_BE) - flg = TTY_BREAK; - else if (status & SR_PE) - flg = TTY_PARITY; - else if (status & SR_FE) - flg = TTY_FRAME; - } - - if (uart_handle_sysrq_char(port, rx)) - continue; - - uart_insert_char(port, status, SR_OE, rx, flg); - } - - spin_unlock_irqrestore(&port->lock, *flags); - tty_flip_buffer_push(&port->state->port); - spin_lock_irqsave(&port->lock, *flags); -} - -static irqreturn_t netx_int(int irq, void *dev_id) -{ - struct uart_port *port = dev_id; - unsigned long flags; - unsigned char status; - - spin_lock_irqsave(&port->lock,flags); - - status = readl(port->membase + UART_IIR) & IIR_MASK; - while (status) { - if (status & IIR_RIS) - netx_rxint(port, &flags); - if (status & IIR_TIS) - netx_txint(port); - if (status & IIR_MIS) { - if (readl(port->membase + UART_FR) & FR_CTS) - uart_handle_cts_change(port, 1); - else - uart_handle_cts_change(port, 0); - } - writel(0, port->membase + UART_IIR); - status = readl(port->membase + UART_IIR) & IIR_MASK; - } - - spin_unlock_irqrestore(&port->lock,flags); - return IRQ_HANDLED; -} - -static unsigned int netx_get_mctrl(struct uart_port *port) -{ - unsigned int ret = TIOCM_DSR | TIOCM_CAR; - - if (readl(port->membase + UART_FR) & FR_CTS) - ret |= TIOCM_CTS; - - return ret; -} - -static void netx_set_mctrl(struct uart_port *port, unsigned int mctrl) -{ - unsigned int val; - - /* FIXME: Locking needed ? */ - if (mctrl & TIOCM_RTS) { - val = readl(port->membase + UART_RTS_CR); - writel(val | RTS_CR_RTS, port->membase + UART_RTS_CR); - } -} - -static void netx_break_ctl(struct uart_port *port, int break_state) -{ - unsigned int line_cr; - spin_lock_irq(&port->lock); - - line_cr = readl(port->membase + UART_LINE_CR); - if (break_state != 0) - line_cr |= LINE_CR_BRK; - else - line_cr &= ~LINE_CR_BRK; - writel(line_cr, port->membase + UART_LINE_CR); - - spin_unlock_irq(&port->lock); -} - -static int netx_startup(struct uart_port *port) -{ - int ret; - - ret = request_irq(port->irq, netx_int, 0, - DRIVER_NAME, port); - if (ret) { - dev_err(port->dev, "unable to grab irq%d\n",port->irq); - goto exit; - } - - writel(readl(port->membase + UART_LINE_CR) | LINE_CR_FEN, - port->membase + UART_LINE_CR); - - writel(CR_MSIE | CR_RIE | CR_TIE | CR_RTIE | CR_UART_EN, - port->membase + UART_CR); - -exit: - return ret; -} - -static void netx_shutdown(struct uart_port *port) -{ - writel(0, port->membase + UART_CR) ; - - free_irq(port->irq, port); -} - -static void -netx_set_termios(struct uart_port *port, struct ktermios *termios, - struct ktermios *old) -{ - unsigned int baud, quot; - unsigned char old_cr; - unsigned char line_cr = LINE_CR_FEN; - unsigned char rts_cr = 0; - - switch (termios->c_cflag & CSIZE) { - case CS5: - line_cr |= LINE_CR_5BIT; - break; - case CS6: - line_cr |= LINE_CR_6BIT; - break; - case CS7: - line_cr |= LINE_CR_7BIT; - break; - case CS8: - line_cr |= LINE_CR_8BIT; - break; - } - - if (termios->c_cflag & CSTOPB) - line_cr |= LINE_CR_STP2; - - if (termios->c_cflag & PARENB) { - line_cr |= LINE_CR_PEN; - if (!(termios->c_cflag & PARODD)) - line_cr |= LINE_CR_EPS; - } - - if (termios->c_cflag & CRTSCTS) - rts_cr = RTS_CR_AUTO | RTS_CR_CTS_CTR | RTS_CR_RTS_POL; - - baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); - quot = baud * 4096; - quot /= 1000; - quot *= 256; - quot /= 100000; - - spin_lock_irq(&port->lock); - - uart_update_timeout(port, termios->c_cflag, baud); - - old_cr = readl(port->membase + UART_CR); - - /* disable interrupts */ - writel(old_cr & ~(CR_MSIE | CR_RIE | CR_TIE | CR_RTIE), - port->membase + UART_CR); - - /* drain transmitter */ - while (readl(port->membase + UART_FR) & FR_BUSY); - - /* disable UART */ - writel(old_cr & ~CR_UART_EN, port->membase + UART_CR); - - /* modem status interrupts */ - old_cr &= ~CR_MSIE; - if (UART_ENABLE_MS(port, termios->c_cflag)) - old_cr |= CR_MSIE; - - writel((quot>>8) & 0xff, port->membase + UART_BAUDDIV_MSB); - writel(quot & 0xff, port->membase + UART_BAUDDIV_LSB); - writel(line_cr, port->membase + UART_LINE_CR); - - writel(rts_cr, port->membase + UART_RTS_CR); - - /* - * Characters to ignore - */ - port->ignore_status_mask = 0; - if (termios->c_iflag & IGNPAR) - port->ignore_status_mask |= SR_PE; - if (termios->c_iflag & IGNBRK) { - port->ignore_status_mask |= SR_BE; - /* - * If we're ignoring parity and break indicators, - * ignore overruns too (for real raw support). - */ - if (termios->c_iflag & IGNPAR) - port->ignore_status_mask |= SR_PE; - } - - port->read_status_mask = 0; - if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK)) - port->read_status_mask |= SR_BE; - if (termios->c_iflag & INPCK) - port->read_status_mask |= SR_PE | SR_FE; - - writel(old_cr, port->membase + UART_CR); - - spin_unlock_irq(&port->lock); -} - -static const char *netx_type(struct uart_port *port) -{ - return port->type == PORT_NETX ? "NETX" : NULL; -} - -static void netx_release_port(struct uart_port *port) -{ - release_mem_region(port->mapbase, UART_PORT_SIZE); -} - -static int netx_request_port(struct uart_port *port) -{ - return request_mem_region(port->mapbase, UART_PORT_SIZE, - DRIVER_NAME) != NULL ? 0 : -EBUSY; -} - -static void netx_config_port(struct uart_port *port, int flags) -{ - if (flags & UART_CONFIG_TYPE && netx_request_port(port) == 0) - port->type = PORT_NETX; -} - -static int -netx_verify_port(struct uart_port *port, struct serial_struct *ser) -{ - int ret = 0; - - if (ser->type != PORT_UNKNOWN && ser->type != PORT_NETX) - ret = -EINVAL; - - return ret; -} - -static struct uart_ops netx_pops = { - .tx_empty = netx_tx_empty, - .set_mctrl = netx_set_mctrl, - .get_mctrl = netx_get_mctrl, - .stop_tx = netx_stop_tx, - .start_tx = netx_start_tx, - .stop_rx = netx_stop_rx, - .enable_ms = netx_enable_ms, - .break_ctl = netx_break_ctl, - .startup = netx_startup, - .shutdown = netx_shutdown, - .set_termios = netx_set_termios, - .type = netx_type, - .release_port = netx_release_port, - .request_port = netx_request_port, - .config_port = netx_config_port, - .verify_port = netx_verify_port, -}; - -static struct netx_port netx_ports[] = { - { - .port = { - .type = PORT_NETX, - .iotype = UPIO_MEM, - .membase = (char __iomem *)io_p2v(NETX_PA_UART0), - .mapbase = NETX_PA_UART0, - .irq = NETX_IRQ_UART0, - .uartclk = 100000000, - .fifosize = 16, - .flags = UPF_BOOT_AUTOCONF, - .ops = &netx_pops, - .line = 0, - }, - }, { - .port = { - .type = PORT_NETX, - .iotype = UPIO_MEM, - .membase = (char __iomem *)io_p2v(NETX_PA_UART1), - .mapbase = NETX_PA_UART1, - .irq = NETX_IRQ_UART1, - .uartclk = 100000000, - .fifosize = 16, - .flags = UPF_BOOT_AUTOCONF, - .ops = &netx_pops, - .line = 1, - }, - }, { - .port = { - .type = PORT_NETX, - .iotype = UPIO_MEM, - .membase = (char __iomem *)io_p2v(NETX_PA_UART2), - .mapbase = NETX_PA_UART2, - .irq = NETX_IRQ_UART2, - .uartclk = 100000000, - .fifosize = 16, - .flags = UPF_BOOT_AUTOCONF, - .ops = &netx_pops, - .line = 2, - }, - } -}; - -#ifdef CONFIG_SERIAL_NETX_CONSOLE - -static void netx_console_putchar(struct uart_port *port, int ch) -{ - while (readl(port->membase + UART_FR) & FR_BUSY); - writel(ch, port->membase + UART_DR); -} - -static void -netx_console_write(struct console *co, const char *s, unsigned int count) -{ - struct uart_port *port = &netx_ports[co->index].port; - unsigned char cr_save; - - cr_save = readl(port->membase + UART_CR); - writel(cr_save | CR_UART_EN, port->membase + UART_CR); - - uart_console_write(port, s, count, netx_console_putchar); - - while (readl(port->membase + UART_FR) & FR_BUSY); - writel(cr_save, port->membase + UART_CR); -} - -static void __init -netx_console_get_options(struct uart_port *port, int *baud, - int *parity, int *bits, int *flow) -{ - unsigned char line_cr; - - *baud = (readl(port->membase + UART_BAUDDIV_MSB) << 8) | - readl(port->membase + UART_BAUDDIV_LSB); - *baud *= 1000; - *baud /= 4096; - *baud *= 1000; - *baud /= 256; - *baud *= 100; - - line_cr = readl(port->membase + UART_LINE_CR); - *parity = 'n'; - if (line_cr & LINE_CR_PEN) { - if (line_cr & LINE_CR_EPS) - *parity = 'e'; - else - *parity = 'o'; - } - - switch (line_cr & LINE_CR_BITS_MASK) { - case LINE_CR_8BIT: - *bits = 8; - break; - case LINE_CR_7BIT: - *bits = 7; - break; - case LINE_CR_6BIT: - *bits = 6; - break; - case LINE_CR_5BIT: - *bits = 5; - break; - } - - if (readl(port->membase + UART_RTS_CR) & RTS_CR_AUTO) - *flow = 'r'; -} - -static int __init -netx_console_setup(struct console *co, char *options) -{ - struct netx_port *sport; - int baud = 9600; - int bits = 8; - int parity = 'n'; - int flow = 'n'; - - /* - * Check whether an invalid uart number has been specified, and - * if so, search for the first available port that does have - * console support. - */ - if (co->index == -1 || co->index >= ARRAY_SIZE(netx_ports)) - co->index = 0; - sport = &netx_ports[co->index]; - - if (options) { - uart_parse_options(options, &baud, &parity, &bits, &flow); - } else { - /* if the UART is enabled, assume it has been correctly setup - * by the bootloader and get the options - */ - if (readl(sport->port.membase + UART_CR) & CR_UART_EN) { - netx_console_get_options(&sport->port, &baud, - &parity, &bits, &flow); - } - - } - - return uart_set_options(&sport->port, co, baud, parity, bits, flow); -} - -static struct uart_driver netx_reg; -static struct console netx_console = { - .name = "ttyNX", - .write = netx_console_write, - .device = uart_console_device, - .setup = netx_console_setup, - .flags = CON_PRINTBUFFER, - .index = -1, - .data = &netx_reg, -}; - -static int __init netx_console_init(void) -{ - register_console(&netx_console); - return 0; -} -console_initcall(netx_console_init); - -#define NETX_CONSOLE &netx_console -#else -#define NETX_CONSOLE NULL -#endif - -static struct uart_driver netx_reg = { - .owner = THIS_MODULE, - .driver_name = DRIVER_NAME, - .dev_name = "ttyNX", - .major = SERIAL_NX_MAJOR, - .minor = MINOR_START, - .nr = ARRAY_SIZE(netx_ports), - .cons = NETX_CONSOLE, -}; - -static int serial_netx_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct netx_port *sport = platform_get_drvdata(pdev); - - if (sport) - uart_suspend_port(&netx_reg, &sport->port); - - return 0; -} - -static int serial_netx_resume(struct platform_device *pdev) -{ - struct netx_port *sport = platform_get_drvdata(pdev); - - if (sport) - uart_resume_port(&netx_reg, &sport->port); - - return 0; -} - -static int serial_netx_probe(struct platform_device *pdev) -{ - struct uart_port *port = &netx_ports[pdev->id].port; - - dev_info(&pdev->dev, "initialising\n"); - - port->dev = &pdev->dev; - - writel(1, port->membase + UART_RXFIFO_IRQLEVEL); - uart_add_one_port(&netx_reg, &netx_ports[pdev->id].port); - platform_set_drvdata(pdev, &netx_ports[pdev->id]); - - return 0; -} - -static int serial_netx_remove(struct platform_device *pdev) -{ - struct netx_port *sport = platform_get_drvdata(pdev); - - if (sport) - uart_remove_one_port(&netx_reg, &sport->port); - - return 0; -} - -static struct platform_driver serial_netx_driver = { - .probe = serial_netx_probe, - .remove = serial_netx_remove, - - .suspend = serial_netx_suspend, - .resume = serial_netx_resume, - - .driver = { - .name = DRIVER_NAME, - }, -}; - -static int __init netx_serial_init(void) -{ - int ret; - - printk(KERN_INFO "Serial: NetX driver\n"); - - ret = uart_register_driver(&netx_reg); - if (ret) - return ret; - - ret = platform_driver_register(&serial_netx_driver); - if (ret != 0) - uart_unregister_driver(&netx_reg); - - return 0; -} - -static void __exit netx_serial_exit(void) -{ - platform_driver_unregister(&serial_netx_driver); - uart_unregister_driver(&netx_reg); -} - -module_init(netx_serial_init); -module_exit(netx_serial_exit); - -MODULE_AUTHOR("Sascha Hauer"); -MODULE_DESCRIPTION("NetX serial port driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:" DRIVER_NAME); diff --git a/drivers/tty/serial/owl-uart.c b/drivers/tty/serial/owl-uart.c index 29a6dc6a8d23..03963af77b15 100644 --- a/drivers/tty/serial/owl-uart.c +++ b/drivers/tty/serial/owl-uart.c @@ -662,10 +662,8 @@ static int owl_uart_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "could not get irq\n"); + if (irq < 0) return irq; - } if (owl_uart_ports[pdev->id]) { dev_err(&pdev->dev, "port %d already allocated\n", pdev->id); diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c index 35e5f9c5d5be..14c6306bc462 100644 --- a/drivers/tty/serial/qcom_geni_serial.c +++ b/drivers/tty/serial/qcom_geni_serial.c @@ -198,10 +198,8 @@ static int qcom_geni_serial_request_port(struct uart_port *uport) { struct platform_device *pdev = to_platform_device(uport->dev); struct qcom_geni_serial_port *port = to_dev_port(uport, uport); - struct resource *res; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - uport->membase = devm_ioremap_resource(&pdev->dev, res); + uport->membase = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(uport->membase)) return PTR_ERR(uport->membase); port->se.base = uport->membase; @@ -920,12 +918,13 @@ static unsigned long get_clk_cfg(unsigned long clk_freq) return 0; } -static unsigned long get_clk_div_rate(unsigned int baud, unsigned int *clk_div) +static unsigned long get_clk_div_rate(unsigned int baud, + unsigned int sampling_rate, unsigned int *clk_div) { unsigned long ser_clk; unsigned long desired_clk; - desired_clk = baud * UART_OVERSAMPLING; + desired_clk = baud * sampling_rate; ser_clk = get_clk_cfg(desired_clk); if (!ser_clk) { pr_err("%s: Can't find matching DFS entry for baud %d\n", @@ -951,12 +950,20 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport, u32 ser_clk_cfg; struct qcom_geni_serial_port *port = to_dev_port(uport, uport); unsigned long clk_rate; + u32 ver, sampling_rate; qcom_geni_serial_stop_rx(uport); /* baud rate */ baud = uart_get_baud_rate(uport, termios, old, 300, 4000000); port->baud = baud; - clk_rate = get_clk_div_rate(baud, &clk_div); + + sampling_rate = UART_OVERSAMPLING; + /* Sampling rate is halved for IP versions >= 2.5 */ + ver = geni_se_get_qup_hw_version(&port->se); + if (GENI_SE_VERSION_MAJOR(ver) >= 2 && GENI_SE_VERSION_MINOR(ver) >= 5) + sampling_rate /= 2; + + clk_rate = get_clk_div_rate(baud, sampling_rate, &clk_div); if (!clk_rate) goto out_restart_rx; @@ -1291,10 +1298,8 @@ static int qcom_geni_serial_probe(struct platform_device *pdev) port->tx_fifo_width = DEF_FIFO_WIDTH_BITS; irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "Failed to get IRQ %d\n", irq); + if (irq < 0) return irq; - } uport->irq = irq; uport->private_data = drv; diff --git a/drivers/tty/serial/rda-uart.c b/drivers/tty/serial/rda-uart.c index 284623eefaeb..c1b0d7662ef9 100644 --- a/drivers/tty/serial/rda-uart.c +++ b/drivers/tty/serial/rda-uart.c @@ -735,10 +735,8 @@ static int rda_uart_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "could not get irq\n"); + if (irq < 0) return irq; - } if (rda_uart_ports[pdev->id]) { dev_err(&pdev->dev, "port %d already allocated\n", pdev->id); diff --git a/drivers/tty/serial/sa1100.c b/drivers/tty/serial/sa1100.c index a399772be3fc..8e618129e65c 100644 --- a/drivers/tty/serial/sa1100.c +++ b/drivers/tty/serial/sa1100.c @@ -28,6 +28,8 @@ #include <mach/hardware.h> #include <mach/irqs.h> +#include "serial_mctrl_gpio.h" + /* We've been assigned a range on the "Low-density serial ports" major */ #define SERIAL_SA1100_MAJOR 204 #define MINOR_START 5 @@ -77,6 +79,7 @@ struct sa1100_port { struct uart_port port; struct timer_list timer; unsigned int old_status; + struct mctrl_gpios *gpios; }; /* @@ -174,6 +177,8 @@ static void sa1100_enable_ms(struct uart_port *port) container_of(port, struct sa1100_port, port); mod_timer(&sport->timer, jiffies); + + mctrl_gpio_enable_ms(sport->gpios); } static void @@ -322,11 +327,21 @@ static unsigned int sa1100_tx_empty(struct uart_port *port) static unsigned int sa1100_get_mctrl(struct uart_port *port) { - return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; + struct sa1100_port *sport = + container_of(port, struct sa1100_port, port); + int ret = TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; + + mctrl_gpio_get(sport->gpios, &ret); + + return ret; } static void sa1100_set_mctrl(struct uart_port *port, unsigned int mctrl) { + struct sa1100_port *sport = + container_of(port, struct sa1100_port, port); + + mctrl_gpio_set(sport->gpios, mctrl); } /* @@ -842,6 +857,31 @@ static int sa1100_serial_resume(struct platform_device *dev) return 0; } +static int sa1100_serial_add_one_port(struct sa1100_port *sport, struct platform_device *dev) +{ + sport->port.dev = &dev->dev; + + // mctrl_gpio_init() requires that the GPIO driver supports interrupts, + // but we need to support GPIO drivers for hardware that has no such + // interrupts. Use mctrl_gpio_init_noauto() instead. + sport->gpios = mctrl_gpio_init_noauto(sport->port.dev, 0); + if (IS_ERR(sport->gpios)) { + int err = PTR_ERR(sport->gpios); + + dev_err(sport->port.dev, "failed to get mctrl gpios: %d\n", + err); + + if (err == -EPROBE_DEFER) + return err; + + sport->gpios = NULL; + } + + platform_set_drvdata(dev, sport); + + return uart_add_one_port(&sa1100_reg, &sport->port); +} + static int sa1100_serial_probe(struct platform_device *dev) { struct resource *res = dev->resource; @@ -856,9 +896,7 @@ static int sa1100_serial_probe(struct platform_device *dev) if (sa1100_ports[i].port.mapbase != res->start) continue; - sa1100_ports[i].port.dev = &dev->dev; - uart_add_one_port(&sa1100_reg, &sa1100_ports[i].port); - platform_set_drvdata(dev, &sa1100_ports[i]); + sa1100_serial_add_one_port(&sa1100_ports[i], dev); break; } } diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c index 68a24a14f6b7..d2b77aae42ae 100644 --- a/drivers/tty/serial/sccnxp.c +++ b/drivers/tty/serial/sccnxp.c @@ -961,7 +961,6 @@ static int sccnxp_probe(struct platform_device *pdev) if (!s->poll) { s->irq = platform_get_irq(pdev, 0); if (s->irq < 0) { - dev_err(&pdev->dev, "Missing irq resource data\n"); ret = -ENXIO; goto err_out; } diff --git a/drivers/tty/serial/serial-tegra.c b/drivers/tty/serial/serial-tegra.c index d5269aaaf9b2..2f599515c133 100644 --- a/drivers/tty/serial/serial-tegra.c +++ b/drivers/tty/serial/serial-tegra.c @@ -4,7 +4,7 @@ * * High-speed serial driver for NVIDIA Tegra SoCs * - * Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2012-2019, NVIDIA CORPORATION. All rights reserved. * * Author: Laxman Dewangan <ldewangan@nvidia.com> */ @@ -62,7 +62,7 @@ #define TEGRA_UART_TX_TRIG_4B 0x20 #define TEGRA_UART_TX_TRIG_1B 0x30 -#define TEGRA_UART_MAXIMUM 5 +#define TEGRA_UART_MAXIMUM 8 /* Default UART setting when started: 115200 no parity, stop, 8 data bits */ #define TEGRA_UART_DEFAULT_BAUD 115200 @@ -72,6 +72,8 @@ #define TEGRA_TX_PIO 1 #define TEGRA_TX_DMA 2 +#define TEGRA_UART_FCR_IIR_FIFO_EN 0x40 + /** * tegra_uart_chip_data: SOC specific data. * @@ -84,6 +86,17 @@ struct tegra_uart_chip_data { bool tx_fifo_full_status; bool allow_txfifo_reset_fifo_mode; bool support_clk_src_div; + bool fifo_mode_enable_status; + int uart_max_port; + int max_dma_burst_bytes; + int error_tolerance_low_range; + int error_tolerance_high_range; +}; + +struct tegra_baud_tolerance { + u32 lower_range_baud; + u32 upper_range_baud; + s32 tolerance; }; struct tegra_uart_port { @@ -122,10 +135,18 @@ struct tegra_uart_port { dma_cookie_t rx_cookie; unsigned int tx_bytes_requested; unsigned int rx_bytes_requested; + struct tegra_baud_tolerance *baud_tolerance; + int n_adjustable_baud_rates; + int required_rate; + int configured_rate; + bool use_rx_pio; + bool use_tx_pio; }; static void tegra_uart_start_next_tx(struct tegra_uart_port *tup); static int tegra_uart_start_rx_dma(struct tegra_uart_port *tup); +static void tegra_uart_dma_channel_free(struct tegra_uart_port *tup, + bool dma_to_memory); static inline unsigned long tegra_uart_read(struct tegra_uart_port *tup, unsigned long reg) @@ -192,16 +213,34 @@ static void set_dtr(struct tegra_uart_port *tup, bool active) } } +static void set_loopbk(struct tegra_uart_port *tup, bool active) +{ + unsigned long mcr = tup->mcr_shadow; + + if (active) + mcr |= UART_MCR_LOOP; + else + mcr &= ~UART_MCR_LOOP; + + if (mcr != tup->mcr_shadow) { + tegra_uart_write(tup, mcr, UART_MCR); + tup->mcr_shadow = mcr; + } +} + static void tegra_uart_set_mctrl(struct uart_port *u, unsigned int mctrl) { struct tegra_uart_port *tup = to_tegra_uport(u); - int dtr_enable; + int enable; tup->rts_active = !!(mctrl & TIOCM_RTS); set_rts(tup, tup->rts_active); - dtr_enable = !!(mctrl & TIOCM_DTR); - set_dtr(tup, dtr_enable); + enable = !!(mctrl & TIOCM_DTR); + set_dtr(tup, enable); + + enable = !!(mctrl & TIOCM_LOOP); + set_loopbk(tup, enable); } static void tegra_uart_break_ctl(struct uart_port *u, int break_ctl) @@ -243,9 +282,28 @@ static void tegra_uart_wait_sym_time(struct tegra_uart_port *tup, tup->current_baud)); } +static int tegra_uart_wait_fifo_mode_enabled(struct tegra_uart_port *tup) +{ + unsigned long iir; + unsigned int tmout = 100; + + do { + iir = tegra_uart_read(tup, UART_IIR); + if (iir & TEGRA_UART_FCR_IIR_FIFO_EN) + return 0; + udelay(1); + } while (--tmout); + + return -ETIMEDOUT; +} + static void tegra_uart_fifo_reset(struct tegra_uart_port *tup, u8 fcr_bits) { unsigned long fcr = tup->fcr_shadow; + unsigned int lsr, tmout = 10000; + + if (tup->rts_active) + set_rts(tup, false); if (tup->cdata->allow_txfifo_reset_fifo_mode) { fcr |= fcr_bits & (UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); @@ -258,6 +316,8 @@ static void tegra_uart_fifo_reset(struct tegra_uart_port *tup, u8 fcr_bits) tegra_uart_write(tup, fcr, UART_FCR); fcr |= UART_FCR_ENABLE_FIFO; tegra_uart_write(tup, fcr, UART_FCR); + if (tup->cdata->fifo_mode_enable_status) + tegra_uart_wait_fifo_mode_enabled(tup); } /* Dummy read to ensure the write is posted */ @@ -269,6 +329,47 @@ static void tegra_uart_fifo_reset(struct tegra_uart_port *tup, u8 fcr_bits) * to propagate, otherwise data could be lost. */ tegra_uart_wait_cycle_time(tup, 32); + + do { + lsr = tegra_uart_read(tup, UART_LSR); + if ((lsr | UART_LSR_TEMT) && !(lsr & UART_LSR_DR)) + break; + udelay(1); + } while (--tmout); + + if (tup->rts_active) + set_rts(tup, true); +} + +static long tegra_get_tolerance_rate(struct tegra_uart_port *tup, + unsigned int baud, long rate) +{ + int i; + + for (i = 0; i < tup->n_adjustable_baud_rates; ++i) { + if (baud >= tup->baud_tolerance[i].lower_range_baud && + baud <= tup->baud_tolerance[i].upper_range_baud) + return (rate + (rate * + tup->baud_tolerance[i].tolerance) / 10000); + } + + return rate; +} + +static int tegra_check_rate_in_range(struct tegra_uart_port *tup) +{ + long diff; + + diff = ((long)(tup->configured_rate - tup->required_rate) * 10000) + / tup->required_rate; + if (diff < (tup->cdata->error_tolerance_low_range * 100) || + diff > (tup->cdata->error_tolerance_high_range * 100)) { + dev_err(tup->uport.dev, + "configured baud rate is out of range by %ld", diff); + return -EIO; + } + + return 0; } static int tegra_set_baudrate(struct tegra_uart_port *tup, unsigned int baud) @@ -276,6 +377,7 @@ static int tegra_set_baudrate(struct tegra_uart_port *tup, unsigned int baud) unsigned long rate; unsigned int divisor; unsigned long lcr; + unsigned long flags; int ret; if (tup->current_baud == baud) @@ -283,18 +385,28 @@ static int tegra_set_baudrate(struct tegra_uart_port *tup, unsigned int baud) if (tup->cdata->support_clk_src_div) { rate = baud * 16; + tup->required_rate = rate; + + if (tup->n_adjustable_baud_rates) + rate = tegra_get_tolerance_rate(tup, baud, rate); + ret = clk_set_rate(tup->uart_clk, rate); if (ret < 0) { dev_err(tup->uport.dev, "clk_set_rate() failed for rate %lu\n", rate); return ret; } + tup->configured_rate = clk_get_rate(tup->uart_clk); divisor = 1; + ret = tegra_check_rate_in_range(tup); + if (ret < 0) + return ret; } else { rate = clk_get_rate(tup->uart_clk); divisor = DIV_ROUND_CLOSEST(rate, baud * 16); } + spin_lock_irqsave(&tup->uport.lock, flags); lcr = tup->lcr_shadow; lcr |= UART_LCR_DLAB; tegra_uart_write(tup, lcr, UART_LCR); @@ -307,6 +419,7 @@ static int tegra_set_baudrate(struct tegra_uart_port *tup, unsigned int baud) /* Dummy read to ensure the write is posted */ tegra_uart_read(tup, UART_SCR); + spin_unlock_irqrestore(&tup->uport.lock, flags); tup->current_baud = baud; @@ -336,13 +449,21 @@ static char tegra_uart_decode_rx_error(struct tegra_uart_port *tup, tup->uport.icount.frame++; dev_err(tup->uport.dev, "Got frame errors\n"); } else if (lsr & UART_LSR_BI) { - dev_err(tup->uport.dev, "Got Break\n"); - tup->uport.icount.brk++; - /* If FIFO read error without any data, reset Rx FIFO */ + /* + * Break error + * If FIFO read error without any data, reset Rx FIFO + */ if (!(lsr & UART_LSR_DR) && (lsr & UART_LSR_FIFOE)) tegra_uart_fifo_reset(tup, UART_FCR_CLEAR_RCVR); + if (tup->uport.ignore_status_mask & UART_LSR_BI) + return TTY_BREAK; + flag = TTY_BREAK; + tup->uport.icount.brk++; + dev_dbg(tup->uport.dev, "Got Break\n"); } + uart_insert_char(&tup->uport, lsr, UART_LSR_OE, 0, flag); } + return flag; } @@ -440,12 +561,15 @@ static void tegra_uart_start_next_tx(struct tegra_uart_port *tup) unsigned long count; struct circ_buf *xmit = &tup->uport.state->xmit; + if (!tup->current_baud) + return; + tail = (unsigned long)&xmit->buf[xmit->tail]; count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); if (!count) return; - if (count < TEGRA_UART_MIN_DMA) + if (tup->use_tx_pio || count < TEGRA_UART_MIN_DMA) tegra_uart_start_pio_tx(tup, count); else if (BYTES_TO_ALIGN(tail) > 0) tegra_uart_start_pio_tx(tup, BYTES_TO_ALIGN(tail)); @@ -521,11 +645,17 @@ static void tegra_uart_handle_rx_pio(struct tegra_uart_port *tup, break; flag = tegra_uart_decode_rx_error(tup, lsr); + if (flag != TTY_NORMAL) + continue; + ch = (unsigned char) tegra_uart_read(tup, UART_RX); tup->uport.icount.rx++; if (!uart_handle_sysrq_char(&tup->uport, ch) && tty) tty_insert_flip_char(tty, ch, flag); + + if (tup->uport.ignore_status_mask & UART_LSR_DR) + continue; } while (1); } @@ -544,6 +674,10 @@ static void tegra_uart_copy_rx_to_tty(struct tegra_uart_port *tup, dev_err(tup->uport.dev, "No tty port\n"); return; } + + if (tup->uport.ignore_status_mask & UART_LSR_DR) + return; + dma_sync_single_for_cpu(tup->uport.dev, tup->rx_dma_buf_phys, TEGRA_UART_RX_DMA_BUFFER_SIZE, DMA_FROM_DEVICE); copied = tty_insert_flip_string(tty, @@ -668,6 +802,18 @@ static void tegra_uart_handle_modem_signal_change(struct uart_port *u) uart_handle_cts_change(&tup->uport, msr & UART_MSR_CTS); } +static void do_handle_rx_pio(struct tegra_uart_port *tup) +{ + struct tty_struct *tty = tty_port_tty_get(&tup->uport.state->port); + struct tty_port *port = &tup->uport.state->port; + + tegra_uart_handle_rx_pio(tup, port); + if (tty) { + tty_flip_buffer_push(port); + tty_kref_put(tty); + } +} + static irqreturn_t tegra_uart_isr(int irq, void *data) { struct tegra_uart_port *tup = data; @@ -681,7 +827,7 @@ static irqreturn_t tegra_uart_isr(int irq, void *data) while (1) { iir = tegra_uart_read(tup, UART_IIR); if (iir & UART_IIR_NO_INT) { - if (is_rx_int) { + if (!tup->use_rx_pio && is_rx_int) { tegra_uart_handle_rx_dma(tup); if (tup->rx_in_progress) { ier = tup->ier_shadow; @@ -709,7 +855,7 @@ static irqreturn_t tegra_uart_isr(int irq, void *data) case 4: /* End of data */ case 6: /* Rx timeout */ case 2: /* Receive */ - if (!is_rx_int) { + if (!tup->use_rx_pio && !is_rx_int) { is_rx_int = true; /* Disable Rx interrupts */ ier = tup->ier_shadow; @@ -719,6 +865,8 @@ static irqreturn_t tegra_uart_isr(int irq, void *data) UART_IER_RTOIE | TEGRA_UART_IER_EORD); tup->ier_shadow = ier; tegra_uart_write(tup, ier, UART_IER); + } else { + do_handle_rx_pio(tup); } break; @@ -737,6 +885,7 @@ static irqreturn_t tegra_uart_isr(int irq, void *data) static void tegra_uart_stop_rx(struct uart_port *u) { struct tegra_uart_port *tup = to_tegra_uport(u); + struct tty_port *port = &tup->uport.state->port; struct dma_tx_state state; unsigned long ier; @@ -754,9 +903,13 @@ static void tegra_uart_stop_rx(struct uart_port *u) tup->ier_shadow = ier; tegra_uart_write(tup, ier, UART_IER); tup->rx_in_progress = 0; - dmaengine_terminate_all(tup->rx_dma_chan); - dmaengine_tx_status(tup->rx_dma_chan, tup->rx_cookie, &state); - tegra_uart_rx_buffer_push(tup, state.residue); + if (tup->rx_dma_chan && !tup->use_rx_pio) { + dmaengine_terminate_all(tup->rx_dma_chan); + dmaengine_tx_status(tup->rx_dma_chan, tup->rx_cookie, &state); + tegra_uart_rx_buffer_push(tup, state.residue); + } else { + tegra_uart_handle_rx_pio(tup, port); + } } static void tegra_uart_hw_deinit(struct tegra_uart_port *tup) @@ -804,6 +957,14 @@ static void tegra_uart_hw_deinit(struct tegra_uart_port *tup) tup->current_baud = 0; spin_unlock_irqrestore(&tup->uport.lock, flags); + tup->rx_in_progress = 0; + tup->tx_in_progress = 0; + + if (!tup->use_rx_pio) + tegra_uart_dma_channel_free(tup, true); + if (!tup->use_tx_pio) + tegra_uart_dma_channel_free(tup, false); + clk_disable_unprepare(tup->uart_clk); } @@ -846,35 +1007,60 @@ static int tegra_uart_hw_init(struct tegra_uart_port *tup) * programmed in the DMA registers. */ tup->fcr_shadow = UART_FCR_ENABLE_FIFO; - tup->fcr_shadow |= UART_FCR_R_TRIG_01; + + if (tup->use_rx_pio) { + tup->fcr_shadow |= UART_FCR_R_TRIG_11; + } else { + if (tup->cdata->max_dma_burst_bytes == 8) + tup->fcr_shadow |= UART_FCR_R_TRIG_10; + else + tup->fcr_shadow |= UART_FCR_R_TRIG_01; + } + tup->fcr_shadow |= TEGRA_UART_TX_TRIG_16B; tegra_uart_write(tup, tup->fcr_shadow, UART_FCR); /* Dummy read to ensure the write is posted */ tegra_uart_read(tup, UART_SCR); - /* - * For all tegra devices (up to t210), there is a hardware issue that - * requires software to wait for 3 UART clock periods after enabling - * the TX fifo, otherwise data could be lost. - */ - tegra_uart_wait_cycle_time(tup, 3); + if (tup->cdata->fifo_mode_enable_status) { + ret = tegra_uart_wait_fifo_mode_enabled(tup); + dev_err(tup->uport.dev, "FIFO mode not enabled\n"); + if (ret < 0) + return ret; + } else { + /* + * For all tegra devices (up to t210), there is a hardware + * issue that requires software to wait for 3 UART clock + * periods after enabling the TX fifo, otherwise data could + * be lost. + */ + tegra_uart_wait_cycle_time(tup, 3); + } /* * Initialize the UART with default configuration * (115200, N, 8, 1) so that the receive DMA buffer may be * enqueued */ - tup->lcr_shadow = TEGRA_UART_DEFAULT_LSR; - tegra_set_baudrate(tup, TEGRA_UART_DEFAULT_BAUD); - tup->fcr_shadow |= UART_FCR_DMA_SELECT; - tegra_uart_write(tup, tup->fcr_shadow, UART_FCR); - - ret = tegra_uart_start_rx_dma(tup); + ret = tegra_set_baudrate(tup, TEGRA_UART_DEFAULT_BAUD); if (ret < 0) { - dev_err(tup->uport.dev, "Not able to start Rx DMA\n"); + dev_err(tup->uport.dev, "Failed to set baud rate\n"); return ret; } + if (!tup->use_rx_pio) { + tup->lcr_shadow = TEGRA_UART_DEFAULT_LSR; + tup->fcr_shadow |= UART_FCR_DMA_SELECT; + tegra_uart_write(tup, tup->fcr_shadow, UART_FCR); + + ret = tegra_uart_start_rx_dma(tup); + if (ret < 0) { + dev_err(tup->uport.dev, "Not able to start Rx DMA\n"); + return ret; + } + } else { + tegra_uart_write(tup, tup->fcr_shadow, UART_FCR); + } tup->rx_in_progress = 1; /* @@ -895,7 +1081,12 @@ static int tegra_uart_hw_init(struct tegra_uart_port *tup) * both the EORD as well as RX_TIMEOUT - SW sees RX_TIMEOUT first * then the EORD. */ - tup->ier_shadow = UART_IER_RLSI | UART_IER_RTOIE | TEGRA_UART_IER_EORD; + if (!tup->use_rx_pio) + tup->ier_shadow = UART_IER_RLSI | UART_IER_RTOIE | + TEGRA_UART_IER_EORD; + else + tup->ier_shadow = UART_IER_RLSI | UART_IER_RTOIE | UART_IER_RDI; + tegra_uart_write(tup, tup->ier_shadow, UART_IER); return 0; } @@ -952,7 +1143,7 @@ static int tegra_uart_dma_channel_allocate(struct tegra_uart_port *tup, } dma_sconfig.src_addr = tup->uport.mapbase; dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; - dma_sconfig.src_maxburst = 4; + dma_sconfig.src_maxburst = tup->cdata->max_dma_burst_bytes; tup->rx_dma_chan = dma_chan; tup->rx_dma_buf_virt = dma_buf; tup->rx_dma_buf_phys = dma_phys; @@ -990,16 +1181,22 @@ static int tegra_uart_startup(struct uart_port *u) struct tegra_uart_port *tup = to_tegra_uport(u); int ret; - ret = tegra_uart_dma_channel_allocate(tup, false); - if (ret < 0) { - dev_err(u->dev, "Tx Dma allocation failed, err = %d\n", ret); - return ret; + if (!tup->use_tx_pio) { + ret = tegra_uart_dma_channel_allocate(tup, false); + if (ret < 0) { + dev_err(u->dev, "Tx Dma allocation failed, err = %d\n", + ret); + return ret; + } } - ret = tegra_uart_dma_channel_allocate(tup, true); - if (ret < 0) { - dev_err(u->dev, "Rx Dma allocation failed, err = %d\n", ret); - goto fail_rx_dma; + if (!tup->use_rx_pio) { + ret = tegra_uart_dma_channel_allocate(tup, true); + if (ret < 0) { + dev_err(u->dev, "Rx Dma allocation failed, err = %d\n", + ret); + goto fail_rx_dma; + } } ret = tegra_uart_hw_init(tup); @@ -1017,9 +1214,11 @@ static int tegra_uart_startup(struct uart_port *u) return 0; fail_hw_init: - tegra_uart_dma_channel_free(tup, true); + if (!tup->use_rx_pio) + tegra_uart_dma_channel_free(tup, true); fail_rx_dma: - tegra_uart_dma_channel_free(tup, false); + if (!tup->use_tx_pio) + tegra_uart_dma_channel_free(tup, false); return ret; } @@ -1041,12 +1240,6 @@ static void tegra_uart_shutdown(struct uart_port *u) struct tegra_uart_port *tup = to_tegra_uport(u); tegra_uart_hw_deinit(tup); - - tup->rx_in_progress = 0; - tup->tx_in_progress = 0; - - tegra_uart_dma_channel_free(tup, true); - tegra_uart_dma_channel_free(tup, false); free_irq(u->irq, tup); } @@ -1071,6 +1264,7 @@ static void tegra_uart_set_termios(struct uart_port *u, struct clk *parent_clk = clk_get_parent(tup->uart_clk); unsigned long parent_clk_rate = clk_get_rate(parent_clk); int max_divider = (tup->cdata->support_clk_src_div) ? 0x7FFF : 0xFFFF; + int ret; max_divider *= 16; spin_lock_irqsave(&u->lock, flags); @@ -1143,7 +1337,11 @@ static void tegra_uart_set_termios(struct uart_port *u, parent_clk_rate/max_divider, parent_clk_rate/16); spin_unlock_irqrestore(&u->lock, flags); - tegra_set_baudrate(tup, baud); + ret = tegra_set_baudrate(tup, baud); + if (ret < 0) { + dev_err(tup->uport.dev, "Failed to set baud rate\n"); + return; + } if (tty_termios_baud_rate(termios)) tty_termios_encode_baud_rate(termios, baud, baud); spin_lock_irqsave(&u->lock, flags); @@ -1172,6 +1370,13 @@ static void tegra_uart_set_termios(struct uart_port *u, tegra_uart_write(tup, tup->ier_shadow, UART_IER); tegra_uart_read(tup, UART_IER); + tup->uport.ignore_status_mask = 0; + /* Ignore all characters if CREAD is not set */ + if ((termios->c_cflag & CREAD) == 0) + tup->uport.ignore_status_mask |= UART_LSR_DR; + if (termios->c_iflag & IGNBRK) + tup->uport.ignore_status_mask |= UART_LSR_BI; + spin_unlock_irqrestore(&u->lock, flags); } @@ -1211,6 +1416,11 @@ static int tegra_uart_parse_dt(struct platform_device *pdev, { struct device_node *np = pdev->dev.of_node; int port; + int ret; + int index; + u32 pval; + int count; + int n_entries; port = of_alias_get_id(np, "serial"); if (port < 0) { @@ -1221,6 +1431,54 @@ static int tegra_uart_parse_dt(struct platform_device *pdev, tup->enable_modem_interrupt = of_property_read_bool(np, "nvidia,enable-modem-interrupt"); + + index = of_property_match_string(np, "dma-names", "rx"); + if (index < 0) { + tup->use_rx_pio = true; + dev_info(&pdev->dev, "RX in PIO mode\n"); + } + index = of_property_match_string(np, "dma-names", "tx"); + if (index < 0) { + tup->use_tx_pio = true; + dev_info(&pdev->dev, "TX in PIO mode\n"); + } + + n_entries = of_property_count_u32_elems(np, "nvidia,adjust-baud-rates"); + if (n_entries > 0) { + tup->n_adjustable_baud_rates = n_entries / 3; + tup->baud_tolerance = + devm_kzalloc(&pdev->dev, (tup->n_adjustable_baud_rates) * + sizeof(*tup->baud_tolerance), GFP_KERNEL); + if (!tup->baud_tolerance) + return -ENOMEM; + for (count = 0, index = 0; count < n_entries; count += 3, + index++) { + ret = + of_property_read_u32_index(np, + "nvidia,adjust-baud-rates", + count, &pval); + if (!ret) + tup->baud_tolerance[index].lower_range_baud = + pval; + ret = + of_property_read_u32_index(np, + "nvidia,adjust-baud-rates", + count + 1, &pval); + if (!ret) + tup->baud_tolerance[index].upper_range_baud = + pval; + ret = + of_property_read_u32_index(np, + "nvidia,adjust-baud-rates", + count + 2, &pval); + if (!ret) + tup->baud_tolerance[index].tolerance = + (s32)pval; + } + } else { + tup->n_adjustable_baud_rates = 0; + } + return 0; } @@ -1228,12 +1486,44 @@ static struct tegra_uart_chip_data tegra20_uart_chip_data = { .tx_fifo_full_status = false, .allow_txfifo_reset_fifo_mode = true, .support_clk_src_div = false, + .fifo_mode_enable_status = false, + .uart_max_port = 5, + .max_dma_burst_bytes = 4, + .error_tolerance_low_range = 0, + .error_tolerance_high_range = 4, }; static struct tegra_uart_chip_data tegra30_uart_chip_data = { .tx_fifo_full_status = true, .allow_txfifo_reset_fifo_mode = false, .support_clk_src_div = true, + .fifo_mode_enable_status = false, + .uart_max_port = 5, + .max_dma_burst_bytes = 4, + .error_tolerance_low_range = 0, + .error_tolerance_high_range = 4, +}; + +static struct tegra_uart_chip_data tegra186_uart_chip_data = { + .tx_fifo_full_status = true, + .allow_txfifo_reset_fifo_mode = false, + .support_clk_src_div = true, + .fifo_mode_enable_status = true, + .uart_max_port = 8, + .max_dma_burst_bytes = 8, + .error_tolerance_low_range = 0, + .error_tolerance_high_range = 4, +}; + +static struct tegra_uart_chip_data tegra194_uart_chip_data = { + .tx_fifo_full_status = true, + .allow_txfifo_reset_fifo_mode = false, + .support_clk_src_div = true, + .fifo_mode_enable_status = true, + .uart_max_port = 8, + .max_dma_burst_bytes = 8, + .error_tolerance_low_range = -2, + .error_tolerance_high_range = 2, }; static const struct of_device_id tegra_uart_of_match[] = { @@ -1244,6 +1534,12 @@ static const struct of_device_id tegra_uart_of_match[] = { .compatible = "nvidia,tegra20-hsuart", .data = &tegra20_uart_chip_data, }, { + .compatible = "nvidia,tegra186-hsuart", + .data = &tegra186_uart_chip_data, + }, { + .compatible = "nvidia,tegra194-hsuart", + .data = &tegra194_uart_chip_data, + }, { }, }; MODULE_DEVICE_TABLE(of, tegra_uart_of_match); @@ -1307,10 +1603,8 @@ static int tegra_uart_probe(struct platform_device *pdev) u->iotype = UPIO_MEM32; ret = platform_get_irq(pdev, 0); - if (ret < 0) { - dev_err(&pdev->dev, "Couldn't get IRQ\n"); + if (ret < 0) return ret; - } u->irq = ret; u->regshift = 2; ret = uart_add_one_port(&tegra_uart_driver, u); @@ -1365,11 +1659,22 @@ static struct platform_driver tegra_uart_platform_driver = { static int __init tegra_uart_init(void) { int ret; + struct device_node *node; + const struct of_device_id *match = NULL; + const struct tegra_uart_chip_data *cdata = NULL; + + node = of_find_matching_node(NULL, tegra_uart_of_match); + if (node) + match = of_match_node(tegra_uart_of_match, node); + if (match) + cdata = match->data; + if (cdata) + tegra_uart_driver.nr = cdata->uart_max_port; ret = uart_register_driver(&tegra_uart_driver); if (ret < 0) { pr_err("Could not register %s driver\n", - tegra_uart_driver.driver_name); + tegra_uart_driver.driver_name); return ret; } diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index bbad407557b9..6e713be1d4e9 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1782,6 +1782,7 @@ static int uart_port_activate(struct tty_port *port, struct tty_struct *tty) { struct uart_state *state = container_of(port, struct uart_state, port); struct uart_port *uport; + int ret; uport = uart_port_check(state); if (!uport || uport->flags & UPF_DEAD) @@ -1792,7 +1793,11 @@ static int uart_port_activate(struct tty_port *port, struct tty_struct *tty) /* * Start up the serial port. */ - return uart_startup(tty, state, 0); + ret = uart_startup(tty, state, 0); + if (ret > 0) + tty_port_set_active(port, 1); + + return ret; } static const char *uart_type(struct uart_port *port) diff --git a/drivers/tty/serial/serial_ks8695.c b/drivers/tty/serial/serial_ks8695.c deleted file mode 100644 index b461d791188c..000000000000 --- a/drivers/tty/serial/serial_ks8695.c +++ /dev/null @@ -1,698 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Driver for KS8695 serial ports - * - * Based on drivers/serial/serial_amba.c, by Kam Lee. - * - * Copyright 2002-2005 Micrel Inc. - */ -#include <linux/module.h> -#include <linux/tty.h> -#include <linux/tty_flip.h> -#include <linux/ioport.h> -#include <linux/init.h> -#include <linux/serial.h> -#include <linux/console.h> -#include <linux/sysrq.h> -#include <linux/device.h> - -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/mach/irq.h> - -#include <mach/regs-uart.h> -#include <mach/regs-irq.h> - -#if defined(CONFIG_SERIAL_KS8695_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - -#include <linux/serial_core.h> - - -#define SERIAL_KS8695_MAJOR 204 -#define SERIAL_KS8695_MINOR 16 -#define SERIAL_KS8695_DEVNAME "ttyAM" - -#define SERIAL_KS8695_NR 1 - -/* - * Access macros for the KS8695 UART - */ -#define UART_GET_CHAR(p) (__raw_readl((p)->membase + KS8695_URRB) & 0xFF) -#define UART_PUT_CHAR(p, c) __raw_writel((c), (p)->membase + KS8695_URTH) -#define UART_GET_FCR(p) __raw_readl((p)->membase + KS8695_URFC) -#define UART_PUT_FCR(p, c) __raw_writel((c), (p)->membase + KS8695_URFC) -#define UART_GET_MSR(p) __raw_readl((p)->membase + KS8695_URMS) -#define UART_GET_LSR(p) __raw_readl((p)->membase + KS8695_URLS) -#define UART_GET_LCR(p) __raw_readl((p)->membase + KS8695_URLC) -#define UART_PUT_LCR(p, c) __raw_writel((c), (p)->membase + KS8695_URLC) -#define UART_GET_MCR(p) __raw_readl((p)->membase + KS8695_URMC) -#define UART_PUT_MCR(p, c) __raw_writel((c), (p)->membase + KS8695_URMC) -#define UART_GET_BRDR(p) __raw_readl((p)->membase + KS8695_URBD) -#define UART_PUT_BRDR(p, c) __raw_writel((c), (p)->membase + KS8695_URBD) - -#define KS8695_CLR_TX_INT() __raw_writel(1 << KS8695_IRQ_UART_TX, KS8695_IRQ_VA + KS8695_INTST) - -#define UART_DUMMY_LSR_RX 0x100 -#define UART_PORT_SIZE (KS8695_USR - KS8695_URRB + 4) - -static inline int tx_enabled(struct uart_port *port) -{ - return port->unused[0] & 1; -} - -static inline int rx_enabled(struct uart_port *port) -{ - return port->unused[0] & 2; -} - -static inline int ms_enabled(struct uart_port *port) -{ - return port->unused[0] & 4; -} - -static inline void ms_enable(struct uart_port *port, int enabled) -{ - if(enabled) - port->unused[0] |= 4; - else - port->unused[0] &= ~4; -} - -static inline void rx_enable(struct uart_port *port, int enabled) -{ - if(enabled) - port->unused[0] |= 2; - else - port->unused[0] &= ~2; -} - -static inline void tx_enable(struct uart_port *port, int enabled) -{ - if(enabled) - port->unused[0] |= 1; - else - port->unused[0] &= ~1; -} - - -#ifdef SUPPORT_SYSRQ -static struct console ks8695_console; -#endif - -static void ks8695uart_stop_tx(struct uart_port *port) -{ - if (tx_enabled(port)) { - /* use disable_irq_nosync() and not disable_irq() to avoid self - * imposed deadlock by not waiting for irq handler to end, - * since this ks8695uart_stop_tx() is called from interrupt context. - */ - disable_irq_nosync(KS8695_IRQ_UART_TX); - tx_enable(port, 0); - } -} - -static void ks8695uart_start_tx(struct uart_port *port) -{ - if (!tx_enabled(port)) { - enable_irq(KS8695_IRQ_UART_TX); - tx_enable(port, 1); - } -} - -static void ks8695uart_stop_rx(struct uart_port *port) -{ - if (rx_enabled(port)) { - disable_irq(KS8695_IRQ_UART_RX); - rx_enable(port, 0); - } -} - -static void ks8695uart_enable_ms(struct uart_port *port) -{ - if (!ms_enabled(port)) { - enable_irq(KS8695_IRQ_UART_MODEM_STATUS); - ms_enable(port,1); - } -} - -static void ks8695uart_disable_ms(struct uart_port *port) -{ - if (ms_enabled(port)) { - disable_irq(KS8695_IRQ_UART_MODEM_STATUS); - ms_enable(port,0); - } -} - -static irqreturn_t ks8695uart_rx_chars(int irq, void *dev_id) -{ - struct uart_port *port = dev_id; - unsigned int status, ch, lsr, flg, max_count = 256; - - status = UART_GET_LSR(port); /* clears pending LSR interrupts */ - while ((status & URLS_URDR) && max_count--) { - ch = UART_GET_CHAR(port); - flg = TTY_NORMAL; - - port->icount.rx++; - - /* - * Note that the error handling code is - * out of the main execution path - */ - lsr = UART_GET_LSR(port) | UART_DUMMY_LSR_RX; - if (unlikely(lsr & (URLS_URBI | URLS_URPE | URLS_URFE | URLS_URROE))) { - if (lsr & URLS_URBI) { - lsr &= ~(URLS_URFE | URLS_URPE); - port->icount.brk++; - if (uart_handle_break(port)) - goto ignore_char; - } - if (lsr & URLS_URPE) - port->icount.parity++; - if (lsr & URLS_URFE) - port->icount.frame++; - if (lsr & URLS_URROE) - port->icount.overrun++; - - lsr &= port->read_status_mask; - - if (lsr & URLS_URBI) - flg = TTY_BREAK; - else if (lsr & URLS_URPE) - flg = TTY_PARITY; - else if (lsr & URLS_URFE) - flg = TTY_FRAME; - } - - if (uart_handle_sysrq_char(port, ch)) - goto ignore_char; - - uart_insert_char(port, lsr, URLS_URROE, ch, flg); - -ignore_char: - status = UART_GET_LSR(port); - } - tty_flip_buffer_push(&port->state->port); - - return IRQ_HANDLED; -} - - -static irqreturn_t ks8695uart_tx_chars(int irq, void *dev_id) -{ - struct uart_port *port = dev_id; - struct circ_buf *xmit = &port->state->xmit; - unsigned int count; - - if (port->x_char) { - KS8695_CLR_TX_INT(); - UART_PUT_CHAR(port, port->x_char); - port->icount.tx++; - port->x_char = 0; - return IRQ_HANDLED; - } - - if (uart_tx_stopped(port) || uart_circ_empty(xmit)) { - ks8695uart_stop_tx(port); - return IRQ_HANDLED; - } - - count = 16; /* fifo size */ - while (!uart_circ_empty(xmit) && (count-- > 0)) { - KS8695_CLR_TX_INT(); - UART_PUT_CHAR(port, xmit->buf[xmit->tail]); - - xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); - port->icount.tx++; - } - - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(port); - - if (uart_circ_empty(xmit)) - ks8695uart_stop_tx(port); - - return IRQ_HANDLED; -} - -static irqreturn_t ks8695uart_modem_status(int irq, void *dev_id) -{ - struct uart_port *port = dev_id; - unsigned int status; - - /* - * clear modem interrupt by reading MSR - */ - status = UART_GET_MSR(port); - - if (status & URMS_URDDCD) - uart_handle_dcd_change(port, status & URMS_URDDCD); - - if (status & URMS_URDDST) - port->icount.dsr++; - - if (status & URMS_URDCTS) - uart_handle_cts_change(port, status & URMS_URDCTS); - - if (status & URMS_URTERI) - port->icount.rng++; - - wake_up_interruptible(&port->state->port.delta_msr_wait); - - return IRQ_HANDLED; -} - -static unsigned int ks8695uart_tx_empty(struct uart_port *port) -{ - return (UART_GET_LSR(port) & URLS_URTE) ? TIOCSER_TEMT : 0; -} - -static unsigned int ks8695uart_get_mctrl(struct uart_port *port) -{ - unsigned int result = 0; - unsigned int status; - - status = UART_GET_MSR(port); - if (status & URMS_URDCD) - result |= TIOCM_CAR; - if (status & URMS_URDSR) - result |= TIOCM_DSR; - if (status & URMS_URCTS) - result |= TIOCM_CTS; - if (status & URMS_URRI) - result |= TIOCM_RI; - - return result; -} - -static void ks8695uart_set_mctrl(struct uart_port *port, u_int mctrl) -{ - unsigned int mcr; - - mcr = UART_GET_MCR(port); - if (mctrl & TIOCM_RTS) - mcr |= URMC_URRTS; - else - mcr &= ~URMC_URRTS; - - if (mctrl & TIOCM_DTR) - mcr |= URMC_URDTR; - else - mcr &= ~URMC_URDTR; - - UART_PUT_MCR(port, mcr); -} - -static void ks8695uart_break_ctl(struct uart_port *port, int break_state) -{ - unsigned int lcr; - - lcr = UART_GET_LCR(port); - - if (break_state == -1) - lcr |= URLC_URSBC; - else - lcr &= ~URLC_URSBC; - - UART_PUT_LCR(port, lcr); -} - -static int ks8695uart_startup(struct uart_port *port) -{ - int retval; - - irq_modify_status(KS8695_IRQ_UART_TX, IRQ_NOREQUEST, IRQ_NOAUTOEN); - tx_enable(port, 0); - rx_enable(port, 1); - ms_enable(port, 1); - - /* - * Allocate the IRQ - */ - retval = request_irq(KS8695_IRQ_UART_TX, ks8695uart_tx_chars, 0, "UART TX", port); - if (retval) - goto err_tx; - - retval = request_irq(KS8695_IRQ_UART_RX, ks8695uart_rx_chars, 0, "UART RX", port); - if (retval) - goto err_rx; - - retval = request_irq(KS8695_IRQ_UART_LINE_STATUS, ks8695uart_rx_chars, 0, "UART LineStatus", port); - if (retval) - goto err_ls; - - retval = request_irq(KS8695_IRQ_UART_MODEM_STATUS, ks8695uart_modem_status, 0, "UART ModemStatus", port); - if (retval) - goto err_ms; - - return 0; - -err_ms: - free_irq(KS8695_IRQ_UART_LINE_STATUS, port); -err_ls: - free_irq(KS8695_IRQ_UART_RX, port); -err_rx: - free_irq(KS8695_IRQ_UART_TX, port); -err_tx: - return retval; -} - -static void ks8695uart_shutdown(struct uart_port *port) -{ - /* - * Free the interrupt - */ - free_irq(KS8695_IRQ_UART_RX, port); - free_irq(KS8695_IRQ_UART_TX, port); - free_irq(KS8695_IRQ_UART_MODEM_STATUS, port); - free_irq(KS8695_IRQ_UART_LINE_STATUS, port); - - /* disable break condition and fifos */ - UART_PUT_LCR(port, UART_GET_LCR(port) & ~URLC_URSBC); - UART_PUT_FCR(port, UART_GET_FCR(port) & ~URFC_URFE); -} - -static void ks8695uart_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) -{ - unsigned int lcr, fcr = 0; - unsigned long flags; - unsigned int baud, quot; - - /* - * Ask the core to calculate the divisor for us. - */ - baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); - quot = uart_get_divisor(port, baud); - - switch (termios->c_cflag & CSIZE) { - case CS5: - lcr = URCL_5; - break; - case CS6: - lcr = URCL_6; - break; - case CS7: - lcr = URCL_7; - break; - default: - lcr = URCL_8; - break; - } - - /* stop bits */ - if (termios->c_cflag & CSTOPB) - lcr |= URLC_URSB; - - /* parity */ - if (termios->c_cflag & PARENB) { - if (termios->c_cflag & CMSPAR) { /* Mark or Space parity */ - if (termios->c_cflag & PARODD) - lcr |= URPE_MARK; - else - lcr |= URPE_SPACE; - } - else if (termios->c_cflag & PARODD) - lcr |= URPE_ODD; - else - lcr |= URPE_EVEN; - } - - if (port->fifosize > 1) - fcr = URFC_URFRT_8 | URFC_URTFR | URFC_URRFR | URFC_URFE; - - spin_lock_irqsave(&port->lock, flags); - - /* - * Update the per-port timeout. - */ - uart_update_timeout(port, termios->c_cflag, baud); - - port->read_status_mask = URLS_URROE; - if (termios->c_iflag & INPCK) - port->read_status_mask |= (URLS_URFE | URLS_URPE); - if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK)) - port->read_status_mask |= URLS_URBI; - - /* - * Characters to ignore - */ - port->ignore_status_mask = 0; - if (termios->c_iflag & IGNPAR) - port->ignore_status_mask |= (URLS_URFE | URLS_URPE); - if (termios->c_iflag & IGNBRK) { - port->ignore_status_mask |= URLS_URBI; - /* - * If we're ignoring parity and break indicators, - * ignore overruns too (for real raw support). - */ - if (termios->c_iflag & IGNPAR) - port->ignore_status_mask |= URLS_URROE; - } - - /* - * Ignore all characters if CREAD is not set. - */ - if ((termios->c_cflag & CREAD) == 0) - port->ignore_status_mask |= UART_DUMMY_LSR_RX; - - /* first, disable everything */ - if (UART_ENABLE_MS(port, termios->c_cflag)) - ks8695uart_enable_ms(port); - else - ks8695uart_disable_ms(port); - - /* Set baud rate */ - UART_PUT_BRDR(port, quot); - - UART_PUT_LCR(port, lcr); - UART_PUT_FCR(port, fcr); - - spin_unlock_irqrestore(&port->lock, flags); -} - -static const char *ks8695uart_type(struct uart_port *port) -{ - return port->type == PORT_KS8695 ? "KS8695" : NULL; -} - -/* - * Release the memory region(s) being used by 'port' - */ -static void ks8695uart_release_port(struct uart_port *port) -{ - release_mem_region(port->mapbase, UART_PORT_SIZE); -} - -/* - * Request the memory region(s) being used by 'port' - */ -static int ks8695uart_request_port(struct uart_port *port) -{ - return request_mem_region(port->mapbase, UART_PORT_SIZE, - "serial_ks8695") != NULL ? 0 : -EBUSY; -} - -/* - * Configure/autoconfigure the port. - */ -static void ks8695uart_config_port(struct uart_port *port, int flags) -{ - if (flags & UART_CONFIG_TYPE) { - port->type = PORT_KS8695; - ks8695uart_request_port(port); - } -} - -/* - * verify the new serial_struct (for TIOCSSERIAL). - */ -static int ks8695uart_verify_port(struct uart_port *port, struct serial_struct *ser) -{ - int ret = 0; - - if (ser->type != PORT_UNKNOWN && ser->type != PORT_KS8695) - ret = -EINVAL; - if (ser->irq != port->irq) - ret = -EINVAL; - if (ser->baud_base < 9600) - ret = -EINVAL; - return ret; -} - -static struct uart_ops ks8695uart_pops = { - .tx_empty = ks8695uart_tx_empty, - .set_mctrl = ks8695uart_set_mctrl, - .get_mctrl = ks8695uart_get_mctrl, - .stop_tx = ks8695uart_stop_tx, - .start_tx = ks8695uart_start_tx, - .stop_rx = ks8695uart_stop_rx, - .enable_ms = ks8695uart_enable_ms, - .break_ctl = ks8695uart_break_ctl, - .startup = ks8695uart_startup, - .shutdown = ks8695uart_shutdown, - .set_termios = ks8695uart_set_termios, - .type = ks8695uart_type, - .release_port = ks8695uart_release_port, - .request_port = ks8695uart_request_port, - .config_port = ks8695uart_config_port, - .verify_port = ks8695uart_verify_port, -}; - -static struct uart_port ks8695uart_ports[SERIAL_KS8695_NR] = { - { - .membase = KS8695_UART_VA, - .mapbase = KS8695_UART_PA, - .iotype = SERIAL_IO_MEM, - .irq = KS8695_IRQ_UART_TX, - .uartclk = KS8695_CLOCK_RATE * 16, - .fifosize = 16, - .ops = &ks8695uart_pops, - .flags = UPF_BOOT_AUTOCONF, - .line = 0, - } -}; - -#ifdef CONFIG_SERIAL_KS8695_CONSOLE -static void ks8695_console_putchar(struct uart_port *port, int ch) -{ - while (!(UART_GET_LSR(port) & URLS_URTHRE)) - barrier(); - - UART_PUT_CHAR(port, ch); -} - -static void ks8695_console_write(struct console *co, const char *s, u_int count) -{ - struct uart_port *port = ks8695uart_ports + co->index; - - uart_console_write(port, s, count, ks8695_console_putchar); -} - -static void __init ks8695_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits) -{ - unsigned int lcr; - - lcr = UART_GET_LCR(port); - - switch (lcr & URLC_PARITY) { - case URPE_ODD: - *parity = 'o'; - break; - case URPE_EVEN: - *parity = 'e'; - break; - default: - *parity = 'n'; - } - - switch (lcr & URLC_URCL) { - case URCL_5: - *bits = 5; - break; - case URCL_6: - *bits = 6; - break; - case URCL_7: - *bits = 7; - break; - default: - *bits = 8; - } - - *baud = port->uartclk / (UART_GET_BRDR(port) & 0x0FFF); - *baud /= 16; - *baud &= 0xFFFFFFF0; -} - -static int __init ks8695_console_setup(struct console *co, char *options) -{ - struct uart_port *port; - int baud = 115200; - int bits = 8; - int parity = 'n'; - int flow = 'n'; - - /* - * Check whether an invalid uart number has been specified, and - * if so, search for the first available port that does have - * console support. - */ - port = uart_get_console(ks8695uart_ports, SERIAL_KS8695_NR, co); - - if (options) - uart_parse_options(options, &baud, &parity, &bits, &flow); - else - ks8695_console_get_options(port, &baud, &parity, &bits); - - return uart_set_options(port, co, baud, parity, bits, flow); -} - -static struct uart_driver ks8695_reg; - -static struct console ks8695_console = { - .name = SERIAL_KS8695_DEVNAME, - .write = ks8695_console_write, - .device = uart_console_device, - .setup = ks8695_console_setup, - .flags = CON_PRINTBUFFER, - .index = -1, - .data = &ks8695_reg, -}; - -static int __init ks8695_console_init(void) -{ - add_preferred_console(SERIAL_KS8695_DEVNAME, 0, NULL); - register_console(&ks8695_console); - return 0; -} - -console_initcall(ks8695_console_init); - -#define KS8695_CONSOLE &ks8695_console -#else -#define KS8695_CONSOLE NULL -#endif - -static struct uart_driver ks8695_reg = { - .owner = THIS_MODULE, - .driver_name = "serial_ks8695", - .dev_name = SERIAL_KS8695_DEVNAME, - .major = SERIAL_KS8695_MAJOR, - .minor = SERIAL_KS8695_MINOR, - .nr = SERIAL_KS8695_NR, - .cons = KS8695_CONSOLE, -}; - -static int __init ks8695uart_init(void) -{ - int i, ret; - - printk(KERN_INFO "Serial: Micrel KS8695 UART driver\n"); - - ret = uart_register_driver(&ks8695_reg); - if (ret) - return ret; - - for (i = 0; i < SERIAL_KS8695_NR; i++) - uart_add_one_port(&ks8695_reg, &ks8695uart_ports[0]); - - return 0; -} - -static void __exit ks8695uart_exit(void) -{ - int i; - - for (i = 0; i < SERIAL_KS8695_NR; i++) - uart_remove_one_port(&ks8695_reg, &ks8695uart_ports[0]); - uart_unregister_driver(&ks8695_reg); -} - -module_init(ks8695uart_init); -module_exit(ks8695uart_exit); - -MODULE_DESCRIPTION("KS8695 serial port driver"); -MODULE_AUTHOR("Micrel Inc."); -MODULE_LICENSE("GPL"); diff --git a/drivers/tty/serial/serial_mctrl_gpio.c b/drivers/tty/serial/serial_mctrl_gpio.c index 39ed56214cd3..d9074303c88e 100644 --- a/drivers/tty/serial/serial_mctrl_gpio.c +++ b/drivers/tty/serial/serial_mctrl_gpio.c @@ -12,6 +12,7 @@ #include <linux/termios.h> #include <linux/serial_core.h> #include <linux/module.h> +#include <linux/property.h> #include "serial_mctrl_gpio.h" @@ -26,16 +27,21 @@ struct mctrl_gpios { static const struct { const char *name; unsigned int mctrl; - bool dir_out; + enum gpiod_flags flags; } mctrl_gpios_desc[UART_GPIO_MAX] = { - { "cts", TIOCM_CTS, false, }, - { "dsr", TIOCM_DSR, false, }, - { "dcd", TIOCM_CD, false, }, - { "rng", TIOCM_RNG, false, }, - { "rts", TIOCM_RTS, true, }, - { "dtr", TIOCM_DTR, true, }, + { "cts", TIOCM_CTS, GPIOD_IN, }, + { "dsr", TIOCM_DSR, GPIOD_IN, }, + { "dcd", TIOCM_CD, GPIOD_IN, }, + { "rng", TIOCM_RNG, GPIOD_IN, }, + { "rts", TIOCM_RTS, GPIOD_OUT_LOW, }, + { "dtr", TIOCM_DTR, GPIOD_OUT_LOW, }, }; +static bool mctrl_gpio_flags_is_dir_out(unsigned int idx) +{ + return mctrl_gpios_desc[idx].flags & GPIOD_FLAGS_BIT_DIR_OUT; +} + void mctrl_gpio_set(struct mctrl_gpios *gpios, unsigned int mctrl) { enum mctrl_gpio_idx i; @@ -47,7 +53,7 @@ void mctrl_gpio_set(struct mctrl_gpios *gpios, unsigned int mctrl) return; for (i = 0; i < UART_GPIO_MAX; i++) - if (gpios->gpio[i] && mctrl_gpios_desc[i].dir_out) { + if (gpios->gpio[i] && mctrl_gpio_flags_is_dir_out(i)) { desc_array[count] = gpios->gpio[i]; __assign_bit(count, values, mctrl & mctrl_gpios_desc[i].mctrl); @@ -72,7 +78,7 @@ unsigned int mctrl_gpio_get(struct mctrl_gpios *gpios, unsigned int *mctrl) return *mctrl; for (i = 0; i < UART_GPIO_MAX; i++) { - if (gpios->gpio[i] && !mctrl_gpios_desc[i].dir_out) { + if (gpios->gpio[i] && !mctrl_gpio_flags_is_dir_out(i)) { if (gpiod_get_value(gpios->gpio[i])) *mctrl |= mctrl_gpios_desc[i].mctrl; else @@ -93,7 +99,7 @@ mctrl_gpio_get_outputs(struct mctrl_gpios *gpios, unsigned int *mctrl) return *mctrl; for (i = 0; i < UART_GPIO_MAX; i++) { - if (gpios->gpio[i] && mctrl_gpios_desc[i].dir_out) { + if (gpios->gpio[i] && mctrl_gpio_flags_is_dir_out(i)) { if (gpiod_get_value(gpios->gpio[i])) *mctrl |= mctrl_gpios_desc[i].mctrl; else @@ -115,17 +121,25 @@ struct mctrl_gpios *mctrl_gpio_init_noauto(struct device *dev, unsigned int idx) return ERR_PTR(-ENOMEM); for (i = 0; i < UART_GPIO_MAX; i++) { - enum gpiod_flags flags; + char *gpio_str; + bool present; - if (mctrl_gpios_desc[i].dir_out) - flags = GPIOD_OUT_LOW; - else - flags = GPIOD_IN; + /* Check if GPIO property exists and continue if not */ + gpio_str = kasprintf(GFP_KERNEL, "%s-gpios", + mctrl_gpios_desc[i].name); + if (!gpio_str) + continue; + + present = device_property_present(dev, gpio_str); + kfree(gpio_str); + if (!present) + continue; gpios->gpio[i] = devm_gpiod_get_index_optional(dev, mctrl_gpios_desc[i].name, - idx, flags); + idx, + mctrl_gpios_desc[i].flags); if (IS_ERR(gpios->gpio[i])) return ERR_CAST(gpios->gpio[i]); @@ -186,7 +200,7 @@ struct mctrl_gpios *mctrl_gpio_init(struct uart_port *port, unsigned int idx) for (i = 0; i < UART_GPIO_MAX; ++i) { int ret; - if (!gpios->gpio[i] || mctrl_gpios_desc[i].dir_out) + if (!gpios->gpio[i] || mctrl_gpio_flags_is_dir_out(i)) continue; ret = gpiod_to_irq(gpios->gpio[i]); diff --git a/drivers/tty/serial/serial_mctrl_gpio.h b/drivers/tty/serial/serial_mctrl_gpio.h index b7d3cca48ede..1b2ff503b2c2 100644 --- a/drivers/tty/serial/serial_mctrl_gpio.h +++ b/drivers/tty/serial/serial_mctrl_gpio.h @@ -114,19 +114,19 @@ static inline struct gpio_desc *mctrl_gpio_to_gpiod(struct mctrl_gpios *gpios, enum mctrl_gpio_idx gidx) { - return ERR_PTR(-ENOSYS); + return NULL; } static inline struct mctrl_gpios *mctrl_gpio_init(struct uart_port *port, unsigned int idx) { - return ERR_PTR(-ENOSYS); + return NULL; } static inline struct mctrl_gpios *mctrl_gpio_init_noauto(struct device *dev, unsigned int idx) { - return ERR_PTR(-ENOSYS); + return NULL; } static inline diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index abc705716aa0..4e754a4850e6 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1092,9 +1092,8 @@ static void rx_fifo_timer_fn(struct timer_list *t) scif_set_rtrg(port, 1); } -static ssize_t rx_trigger_show(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t rx_fifo_trigger_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct uart_port *port = dev_get_drvdata(dev); struct sci_port *sci = to_sci_port(port); @@ -1102,10 +1101,9 @@ static ssize_t rx_trigger_show(struct device *dev, return sprintf(buf, "%d\n", sci->rx_trigger); } -static ssize_t rx_trigger_store(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) +static ssize_t rx_fifo_trigger_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { struct uart_port *port = dev_get_drvdata(dev); struct sci_port *sci = to_sci_port(port); @@ -1123,7 +1121,7 @@ static ssize_t rx_trigger_store(struct device *dev, return count; } -static DEVICE_ATTR(rx_fifo_trigger, 0644, rx_trigger_show, rx_trigger_store); +static DEVICE_ATTR_RW(rx_fifo_trigger); static ssize_t rx_fifo_timeout_show(struct device *dev, struct device_attribute *attr, @@ -1398,6 +1396,7 @@ static void sci_dma_tx_work_fn(struct work_struct *work) struct circ_buf *xmit = &port->state->xmit; unsigned long flags; dma_addr_t buf; + int head, tail; /* * DMA is idle now. @@ -1407,16 +1406,23 @@ static void sci_dma_tx_work_fn(struct work_struct *work) * consistent xmit buffer state. */ spin_lock_irq(&port->lock); - buf = s->tx_dma_addr + (xmit->tail & (UART_XMIT_SIZE - 1)); + head = xmit->head; + tail = xmit->tail; + buf = s->tx_dma_addr + (tail & (UART_XMIT_SIZE - 1)); s->tx_dma_len = min_t(unsigned int, - CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE), - CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE)); - spin_unlock_irq(&port->lock); + CIRC_CNT(head, tail, UART_XMIT_SIZE), + CIRC_CNT_TO_END(head, tail, UART_XMIT_SIZE)); + if (!s->tx_dma_len) { + /* Transmit buffer has been flushed */ + spin_unlock_irq(&port->lock); + return; + } desc = dmaengine_prep_slave_single(chan, buf, s->tx_dma_len, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) { + spin_unlock_irq(&port->lock); dev_warn(port->dev, "Failed preparing Tx DMA descriptor\n"); goto switch_to_pio; } @@ -1424,18 +1430,18 @@ static void sci_dma_tx_work_fn(struct work_struct *work) dma_sync_single_for_device(chan->device->dev, buf, s->tx_dma_len, DMA_TO_DEVICE); - spin_lock_irq(&port->lock); desc->callback = sci_dma_tx_complete; desc->callback_param = s; - spin_unlock_irq(&port->lock); s->cookie_tx = dmaengine_submit(desc); if (dma_submit_error(s->cookie_tx)) { + spin_unlock_irq(&port->lock); dev_warn(port->dev, "Failed submitting Tx DMA descriptor\n"); goto switch_to_pio; } + spin_unlock_irq(&port->lock); dev_dbg(port->dev, "%s: %p: %d...%d, cookie %d\n", - __func__, xmit->buf, xmit->tail, xmit->head, s->cookie_tx); + __func__, xmit->buf, tail, head, s->cookie_tx); dma_async_issue_pending(chan); return; @@ -1648,11 +1654,18 @@ static void sci_free_dma(struct uart_port *port) static void sci_flush_buffer(struct uart_port *port) { + struct sci_port *s = to_sci_port(port); + /* * In uart_flush_buffer(), the xmit circular buffer has just been - * cleared, so we have to reset tx_dma_len accordingly. + * cleared, so we have to reset tx_dma_len accordingly, and stop any + * pending transfers */ - to_sci_port(port)->tx_dma_len = 0; + s->tx_dma_len = 0; + if (s->chan_tx) { + dmaengine_terminate_async(s->chan_tx); + s->cookie_tx = -EINVAL; + } } #else /* !CONFIG_SERIAL_SH_SCI_DMA */ static inline void sci_request_dma(struct uart_port *port) @@ -2086,12 +2099,12 @@ static unsigned int sci_get_mctrl(struct uart_port *port) if (s->autorts) { if (sci_get_cts(port)) mctrl |= TIOCM_CTS; - } else if (IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(gpios, UART_GPIO_CTS))) { + } else if (!mctrl_gpio_to_gpiod(gpios, UART_GPIO_CTS)) { mctrl |= TIOCM_CTS; } - if (IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(gpios, UART_GPIO_DSR))) + if (!mctrl_gpio_to_gpiod(gpios, UART_GPIO_DSR)) mctrl |= TIOCM_DSR; - if (IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(gpios, UART_GPIO_DCD))) + if (!mctrl_gpio_to_gpiod(gpios, UART_GPIO_DCD)) mctrl |= TIOCM_CAR; return mctrl; @@ -3137,14 +3150,10 @@ static int sci_remove(struct platform_device *dev) sci_cleanup_single(port); - if (port->port.fifosize > 1) { - sysfs_remove_file(&dev->dev.kobj, - &dev_attr_rx_fifo_trigger.attr); - } - if (type == PORT_SCIFA || type == PORT_SCIFB || type == PORT_HSCIF) { - sysfs_remove_file(&dev->dev.kobj, - &dev_attr_rx_fifo_timeout.attr); - } + if (port->port.fifosize > 1) + device_remove_file(&dev->dev, &dev_attr_rx_fifo_trigger); + if (type == PORT_SCIFA || type == PORT_SCIFB || type == PORT_HSCIF) + device_remove_file(&dev->dev, &dev_attr_rx_fifo_timeout); return 0; } @@ -3272,14 +3281,12 @@ static int sci_probe_single(struct platform_device *dev, return ret; sciport->gpios = mctrl_gpio_init(&sciport->port, 0); - if (IS_ERR(sciport->gpios) && PTR_ERR(sciport->gpios) != -ENOSYS) + if (IS_ERR(sciport->gpios)) return PTR_ERR(sciport->gpios); if (sciport->has_rtscts) { - if (!IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(sciport->gpios, - UART_GPIO_CTS)) || - !IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(sciport->gpios, - UART_GPIO_RTS))) { + if (mctrl_gpio_to_gpiod(sciport->gpios, UART_GPIO_CTS) || + mctrl_gpio_to_gpiod(sciport->gpios, UART_GPIO_RTS)) { dev_err(&dev->dev, "Conflicting RTS/CTS config\n"); return -EINVAL; } @@ -3332,19 +3339,17 @@ static int sci_probe(struct platform_device *dev) return ret; if (sp->port.fifosize > 1) { - ret = sysfs_create_file(&dev->dev.kobj, - &dev_attr_rx_fifo_trigger.attr); + ret = device_create_file(&dev->dev, &dev_attr_rx_fifo_trigger); if (ret) return ret; } if (sp->port.type == PORT_SCIFA || sp->port.type == PORT_SCIFB || sp->port.type == PORT_HSCIF) { - ret = sysfs_create_file(&dev->dev.kobj, - &dev_attr_rx_fifo_timeout.attr); + ret = device_create_file(&dev->dev, &dev_attr_rx_fifo_timeout); if (ret) { if (sp->port.fifosize > 1) { - sysfs_remove_file(&dev->dev.kobj, - &dev_attr_rx_fifo_trigger.attr); + device_remove_file(&dev->dev, + &dev_attr_rx_fifo_trigger); } return ret; } diff --git a/drivers/tty/serial/sifive.c b/drivers/tty/serial/sifive.c index be4687814353..d5f81b98e4d7 100644 --- a/drivers/tty/serial/sifive.c +++ b/drivers/tty/serial/sifive.c @@ -896,10 +896,8 @@ static int sifive_serial_probe(struct platform_device *pdev) int irq, id, r; irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "could not acquire interrupt\n"); + if (irq < 0) return -EPROBE_DEFER; - } mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_ioremap_resource(&pdev->dev, mem); diff --git a/drivers/tty/serial/sn_console.c b/drivers/tty/serial/sn_console.c deleted file mode 100644 index 283493358a62..000000000000 --- a/drivers/tty/serial/sn_console.c +++ /dev/null @@ -1,1036 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * C-Brick Serial Port (and console) driver for SGI Altix machines. - * - * This driver is NOT suitable for talking to the l1-controller for - * anything other than 'console activities' --- please use the l1 - * driver for that. - * - * - * Copyright (c) 2004-2006 Silicon Graphics, Inc. All Rights Reserved. - * - * Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/NoticeExplan - */ - -#include <linux/interrupt.h> -#include <linux/tty.h> -#include <linux/tty_flip.h> -#include <linux/serial.h> -#include <linux/console.h> -#include <linux/init.h> -#include <linux/sysrq.h> -#include <linux/circ_buf.h> -#include <linux/serial_reg.h> -#include <linux/delay.h> /* for mdelay */ -#include <linux/miscdevice.h> -#include <linux/serial_core.h> - -#include <asm/io.h> -#include <asm/sn/simulator.h> -#include <asm/sn/sn_sal.h> - -/* number of characters we can transmit to the SAL console at a time */ -#define SN_SAL_MAX_CHARS 120 - -/* 64K, when we're asynch, it must be at least printk's LOG_BUF_LEN to - * avoid losing chars, (always has to be a power of 2) */ -#define SN_SAL_BUFFER_SIZE (64 * (1 << 10)) - -#define SN_SAL_UART_FIFO_DEPTH 16 -#define SN_SAL_UART_FIFO_SPEED_CPS (9600/10) - -/* sn_transmit_chars() calling args */ -#define TRANSMIT_BUFFERED 0 -#define TRANSMIT_RAW 1 - -/* To use dynamic numbers only and not use the assigned major and minor, - * define the following.. */ - /* #define USE_DYNAMIC_MINOR 1 *//* use dynamic minor number */ -#define USE_DYNAMIC_MINOR 0 /* Don't rely on misc_register dynamic minor */ - -/* Device name we're using */ -#define DEVICE_NAME "ttySG" -#define DEVICE_NAME_DYNAMIC "ttySG0" /* need full name for misc_register */ -/* The major/minor we are using, ignored for USE_DYNAMIC_MINOR */ -#define DEVICE_MAJOR 204 -#define DEVICE_MINOR 40 - -#ifdef CONFIG_MAGIC_SYSRQ -static char sysrq_serial_str[] = "\eSYS"; -static char *sysrq_serial_ptr = sysrq_serial_str; -static unsigned long sysrq_requested; -#endif /* CONFIG_MAGIC_SYSRQ */ - -/* - * Port definition - this kinda drives it all - */ -struct sn_cons_port { - struct timer_list sc_timer; - struct uart_port sc_port; - struct sn_sal_ops { - int (*sal_puts_raw) (const char *s, int len); - int (*sal_puts) (const char *s, int len); - int (*sal_getc) (void); - int (*sal_input_pending) (void); - void (*sal_wakeup_transmit) (struct sn_cons_port *, int); - } *sc_ops; - unsigned long sc_interrupt_timeout; - int sc_is_asynch; -}; - -static struct sn_cons_port sal_console_port; -static int sn_process_input; - -/* Only used if USE_DYNAMIC_MINOR is set to 1 */ -static struct miscdevice misc; /* used with misc_register for dynamic */ - -extern void early_sn_setup(void); - -#undef DEBUG -#ifdef DEBUG -static int sn_debug_printf(const char *fmt, ...); -#define DPRINTF(x...) sn_debug_printf(x) -#else -#define DPRINTF(x...) do { } while (0) -#endif - -/* Prototypes */ -static int snt_hw_puts_raw(const char *, int); -static int snt_hw_puts_buffered(const char *, int); -static int snt_poll_getc(void); -static int snt_poll_input_pending(void); -static int snt_intr_getc(void); -static int snt_intr_input_pending(void); -static void sn_transmit_chars(struct sn_cons_port *, int); - -/* A table for polling: - */ -static struct sn_sal_ops poll_ops = { - .sal_puts_raw = snt_hw_puts_raw, - .sal_puts = snt_hw_puts_raw, - .sal_getc = snt_poll_getc, - .sal_input_pending = snt_poll_input_pending -}; - -/* A table for interrupts enabled */ -static struct sn_sal_ops intr_ops = { - .sal_puts_raw = snt_hw_puts_raw, - .sal_puts = snt_hw_puts_buffered, - .sal_getc = snt_intr_getc, - .sal_input_pending = snt_intr_input_pending, - .sal_wakeup_transmit = sn_transmit_chars -}; - -/* the console does output in two distinctly different ways: - * synchronous (raw) and asynchronous (buffered). initially, early_printk - * does synchronous output. any data written goes directly to the SAL - * to be output (incidentally, it is internally buffered by the SAL) - * after interrupts and timers are initialized and available for use, - * the console init code switches to asynchronous output. this is - * also the earliest opportunity to begin polling for console input. - * after console initialization, console output and tty (serial port) - * output is buffered and sent to the SAL asynchronously (either by - * timer callback or by UART interrupt) */ - -/* routines for running the console in polling mode */ - -/** - * snt_poll_getc - Get a character from the console in polling mode - * - */ -static int snt_poll_getc(void) -{ - int ch; - - ia64_sn_console_getc(&ch); - return ch; -} - -/** - * snt_poll_input_pending - Check if any input is waiting - polling mode. - * - */ -static int snt_poll_input_pending(void) -{ - int status, input; - - status = ia64_sn_console_check(&input); - return !status && input; -} - -/* routines for an interrupt driven console (normal) */ - -/** - * snt_intr_getc - Get a character from the console, interrupt mode - * - */ -static int snt_intr_getc(void) -{ - return ia64_sn_console_readc(); -} - -/** - * snt_intr_input_pending - Check if input is pending, interrupt mode - * - */ -static int snt_intr_input_pending(void) -{ - return ia64_sn_console_intr_status() & SAL_CONSOLE_INTR_RECV; -} - -/* these functions are polled and interrupt */ - -/** - * snt_hw_puts_raw - Send raw string to the console, polled or interrupt mode - * @s: String - * @len: Length - * - */ -static int snt_hw_puts_raw(const char *s, int len) -{ - /* this will call the PROM and not return until this is done */ - return ia64_sn_console_putb(s, len); -} - -/** - * snt_hw_puts_buffered - Send string to console, polled or interrupt mode - * @s: String - * @len: Length - * - */ -static int snt_hw_puts_buffered(const char *s, int len) -{ - /* queue data to the PROM */ - return ia64_sn_console_xmit_chars((char *)s, len); -} - -/* uart interface structs - * These functions are associated with the uart_port that the serial core - * infrastructure calls. - * - * Note: Due to how the console works, many routines are no-ops. - */ - -/** - * snp_type - What type of console are we? - * @port: Port to operate with (we ignore since we only have one port) - * - */ -static const char *snp_type(struct uart_port *port) -{ - return ("SGI SN L1"); -} - -/** - * snp_tx_empty - Is the transmitter empty? We pretend we're always empty - * @port: Port to operate on (we ignore since we only have one port) - * - */ -static unsigned int snp_tx_empty(struct uart_port *port) -{ - return 1; -} - -/** - * snp_stop_tx - stop the transmitter - no-op for us - * @port: Port to operat eon - we ignore - no-op function - * - */ -static void snp_stop_tx(struct uart_port *port) -{ -} - -/** - * snp_release_port - Free i/o and resources for port - no-op for us - * @port: Port to operate on - we ignore - no-op function - * - */ -static void snp_release_port(struct uart_port *port) -{ -} - -/** - * snp_shutdown - shut down the port - free irq and disable - no-op for us - * @port: Port to shut down - we ignore - * - */ -static void snp_shutdown(struct uart_port *port) -{ -} - -/** - * snp_set_mctrl - set control lines (dtr, rts, etc) - no-op for our console - * @port: Port to operate on - we ignore - * @mctrl: Lines to set/unset - we ignore - * - */ -static void snp_set_mctrl(struct uart_port *port, unsigned int mctrl) -{ -} - -/** - * snp_get_mctrl - get contorl line info, we just return a static value - * @port: port to operate on - we only have one port so we ignore this - * - */ -static unsigned int snp_get_mctrl(struct uart_port *port) -{ - return TIOCM_CAR | TIOCM_RNG | TIOCM_DSR | TIOCM_CTS; -} - -/** - * snp_stop_rx - Stop the receiver - we ignor ethis - * @port: Port to operate on - we ignore - * - */ -static void snp_stop_rx(struct uart_port *port) -{ -} - -/** - * snp_start_tx - Start transmitter - * @port: Port to operate on - * - */ -static void snp_start_tx(struct uart_port *port) -{ - if (sal_console_port.sc_ops->sal_wakeup_transmit) - sal_console_port.sc_ops->sal_wakeup_transmit(&sal_console_port, - TRANSMIT_BUFFERED); - -} - -/** - * snp_break_ctl - handle breaks - ignored by us - * @port: Port to operate on - * @break_state: Break state - * - */ -static void snp_break_ctl(struct uart_port *port, int break_state) -{ -} - -/** - * snp_startup - Start up the serial port - always return 0 (We're always on) - * @port: Port to operate on - * - */ -static int snp_startup(struct uart_port *port) -{ - return 0; -} - -/** - * snp_set_termios - set termios stuff - we ignore these - * @port: port to operate on - * @termios: New settings - * @termios: Old - * - */ -static void -snp_set_termios(struct uart_port *port, struct ktermios *termios, - struct ktermios *old) -{ -} - -/** - * snp_request_port - allocate resources for port - ignored by us - * @port: port to operate on - * - */ -static int snp_request_port(struct uart_port *port) -{ - return 0; -} - -/** - * snp_config_port - allocate resources, set up - we ignore, we're always on - * @port: Port to operate on - * @flags: flags used for port setup - * - */ -static void snp_config_port(struct uart_port *port, int flags) -{ -} - -/* Associate the uart functions above - given to serial core */ - -static const struct uart_ops sn_console_ops = { - .tx_empty = snp_tx_empty, - .set_mctrl = snp_set_mctrl, - .get_mctrl = snp_get_mctrl, - .stop_tx = snp_stop_tx, - .start_tx = snp_start_tx, - .stop_rx = snp_stop_rx, - .break_ctl = snp_break_ctl, - .startup = snp_startup, - .shutdown = snp_shutdown, - .set_termios = snp_set_termios, - .pm = NULL, - .type = snp_type, - .release_port = snp_release_port, - .request_port = snp_request_port, - .config_port = snp_config_port, - .verify_port = NULL, -}; - -/* End of uart struct functions and defines */ - -#ifdef DEBUG - -/** - * sn_debug_printf - close to hardware debugging printf - * @fmt: printf format - * - * This is as "close to the metal" as we can get, used when the driver - * itself may be broken. - * - */ -static int sn_debug_printf(const char *fmt, ...) -{ - static char printk_buf[1024]; - int printed_len; - va_list args; - - va_start(args, fmt); - printed_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args); - - if (!sal_console_port.sc_ops) { - sal_console_port.sc_ops = &poll_ops; - early_sn_setup(); - } - sal_console_port.sc_ops->sal_puts_raw(printk_buf, printed_len); - - va_end(args); - return printed_len; -} -#endif /* DEBUG */ - -/* - * Interrupt handling routines. - */ - -/** - * sn_receive_chars - Grab characters, pass them to tty layer - * @port: Port to operate on - * @flags: irq flags - * - * Note: If we're not registered with the serial core infrastructure yet, - * we don't try to send characters to it... - * - */ -static void -sn_receive_chars(struct sn_cons_port *port, unsigned long flags) -{ - struct tty_port *tport = NULL; - int ch; - - if (!port) { - printk(KERN_ERR "sn_receive_chars - port NULL so can't receive\n"); - return; - } - - if (!port->sc_ops) { - printk(KERN_ERR "sn_receive_chars - port->sc_ops NULL so can't receive\n"); - return; - } - - if (port->sc_port.state) { - /* The serial_core stuffs are initialized, use them */ - tport = &port->sc_port.state->port; - } - - while (port->sc_ops->sal_input_pending()) { - ch = port->sc_ops->sal_getc(); - if (ch < 0) { - printk(KERN_ERR "sn_console: An error occurred while " - "obtaining data from the console (0x%0x)\n", ch); - break; - } -#ifdef CONFIG_MAGIC_SYSRQ - if (sysrq_requested) { - unsigned long sysrq_timeout = sysrq_requested + HZ*5; - - sysrq_requested = 0; - if (ch && time_before(jiffies, sysrq_timeout)) { - spin_unlock_irqrestore(&port->sc_port.lock, flags); - handle_sysrq(ch); - spin_lock_irqsave(&port->sc_port.lock, flags); - /* ignore actual sysrq command char */ - continue; - } - } - if (ch == *sysrq_serial_ptr) { - if (!(*++sysrq_serial_ptr)) { - sysrq_requested = jiffies; - sysrq_serial_ptr = sysrq_serial_str; - } - /* - * ignore the whole sysrq string except for the - * leading escape - */ - if (ch != '\e') - continue; - } - else - sysrq_serial_ptr = sysrq_serial_str; -#endif /* CONFIG_MAGIC_SYSRQ */ - - /* record the character to pass up to the tty layer */ - if (tport) { - if (tty_insert_flip_char(tport, ch, TTY_NORMAL) == 0) - break; - } - port->sc_port.icount.rx++; - } - - if (tport) - tty_flip_buffer_push(tport); -} - -/** - * sn_transmit_chars - grab characters from serial core, send off - * @port: Port to operate on - * @raw: Transmit raw or buffered - * - * Note: If we're early, before we're registered with serial core, the - * writes are going through sn_sal_console_write because that's how - * register_console has been set up. We currently could have asynch - * polls calling this function due to sn_sal_switch_to_asynch but we can - * ignore them until we register with the serial core stuffs. - * - */ -static void sn_transmit_chars(struct sn_cons_port *port, int raw) -{ - int xmit_count, tail, head, loops, ii; - int result; - char *start; - struct circ_buf *xmit; - - if (!port) - return; - - BUG_ON(!port->sc_is_asynch); - - if (port->sc_port.state) { - /* We're initialized, using serial core infrastructure */ - xmit = &port->sc_port.state->xmit; - } else { - /* Probably sn_sal_switch_to_asynch has been run but serial core isn't - * initialized yet. Just return. Writes are going through - * sn_sal_console_write (due to register_console) at this time. - */ - return; - } - - if (uart_circ_empty(xmit) || uart_tx_stopped(&port->sc_port)) { - /* Nothing to do. */ - ia64_sn_console_intr_disable(SAL_CONSOLE_INTR_XMIT); - return; - } - - head = xmit->head; - tail = xmit->tail; - start = &xmit->buf[tail]; - - /* twice around gets the tail to the end of the buffer and - * then to the head, if needed */ - loops = (head < tail) ? 2 : 1; - - for (ii = 0; ii < loops; ii++) { - xmit_count = (head < tail) ? - (UART_XMIT_SIZE - tail) : (head - tail); - - if (xmit_count > 0) { - if (raw == TRANSMIT_RAW) - result = - port->sc_ops->sal_puts_raw(start, - xmit_count); - else - result = - port->sc_ops->sal_puts(start, xmit_count); -#ifdef DEBUG - if (!result) - DPRINTF("`"); -#endif - if (result > 0) { - xmit_count -= result; - port->sc_port.icount.tx += result; - tail += result; - tail &= UART_XMIT_SIZE - 1; - xmit->tail = tail; - start = &xmit->buf[tail]; - } - } - } - - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(&port->sc_port); - - if (uart_circ_empty(xmit)) - snp_stop_tx(&port->sc_port); /* no-op for us */ -} - -/** - * sn_sal_interrupt - Handle console interrupts - * @irq: irq #, useful for debug statements - * @dev_id: our pointer to our port (sn_cons_port which contains the uart port) - * - */ -static irqreturn_t sn_sal_interrupt(int irq, void *dev_id) -{ - struct sn_cons_port *port = (struct sn_cons_port *)dev_id; - unsigned long flags; - int status = ia64_sn_console_intr_status(); - - if (!port) - return IRQ_NONE; - - spin_lock_irqsave(&port->sc_port.lock, flags); - if (status & SAL_CONSOLE_INTR_RECV) { - sn_receive_chars(port, flags); - } - if (status & SAL_CONSOLE_INTR_XMIT) { - sn_transmit_chars(port, TRANSMIT_BUFFERED); - } - spin_unlock_irqrestore(&port->sc_port.lock, flags); - return IRQ_HANDLED; -} - -/** - * sn_sal_timer_poll - this function handles polled console mode - * @data: A pointer to our sn_cons_port (which contains the uart port) - * - * data is the pointer that init_timer will store for us. This function is - * associated with init_timer to see if there is any console traffic. - * Obviously not used in interrupt mode - * - */ -static void sn_sal_timer_poll(struct timer_list *t) -{ - struct sn_cons_port *port = from_timer(port, t, sc_timer); - unsigned long flags; - - if (!port) - return; - - if (!port->sc_port.irq) { - spin_lock_irqsave(&port->sc_port.lock, flags); - if (sn_process_input) - sn_receive_chars(port, flags); - sn_transmit_chars(port, TRANSMIT_RAW); - spin_unlock_irqrestore(&port->sc_port.lock, flags); - mod_timer(&port->sc_timer, - jiffies + port->sc_interrupt_timeout); - } -} - -/* - * Boot-time initialization code - */ - -/** - * sn_sal_switch_to_asynch - Switch to async mode (as opposed to synch) - * @port: Our sn_cons_port (which contains the uart port) - * - * So this is used by sn_sal_serial_console_init (early on, before we're - * registered with serial core). It's also used by sn_sal_init - * right after we've registered with serial core. The later only happens - * if we didn't already come through here via sn_sal_serial_console_init. - * - */ -static void __init sn_sal_switch_to_asynch(struct sn_cons_port *port) -{ - unsigned long flags; - - if (!port) - return; - - DPRINTF("sn_console: about to switch to asynchronous console\n"); - - /* without early_printk, we may be invoked late enough to race - * with other cpus doing console IO at this point, however - * console interrupts will never be enabled */ - spin_lock_irqsave(&port->sc_port.lock, flags); - - /* early_printk invocation may have done this for us */ - if (!port->sc_ops) - port->sc_ops = &poll_ops; - - /* we can't turn on the console interrupt (as request_irq - * calls kmalloc, which isn't set up yet), so we rely on a - * timer to poll for input and push data from the console - * buffer. - */ - timer_setup(&port->sc_timer, sn_sal_timer_poll, 0); - - if (IS_RUNNING_ON_SIMULATOR()) - port->sc_interrupt_timeout = 6; - else { - /* 960cps / 16 char FIFO = 60HZ - * HZ / (SN_SAL_FIFO_SPEED_CPS / SN_SAL_FIFO_DEPTH) */ - port->sc_interrupt_timeout = - HZ * SN_SAL_UART_FIFO_DEPTH / SN_SAL_UART_FIFO_SPEED_CPS; - } - mod_timer(&port->sc_timer, jiffies + port->sc_interrupt_timeout); - - port->sc_is_asynch = 1; - spin_unlock_irqrestore(&port->sc_port.lock, flags); -} - -/** - * sn_sal_switch_to_interrupts - Switch to interrupt driven mode - * @port: Our sn_cons_port (which contains the uart port) - * - * In sn_sal_init, after we're registered with serial core and - * the port is added, this function is called to switch us to interrupt - * mode. We were previously in asynch/polling mode (using init_timer). - * - * We attempt to switch to interrupt mode here by calling - * request_irq. If that works out, we enable receive interrupts. - */ -static void __init sn_sal_switch_to_interrupts(struct sn_cons_port *port) -{ - unsigned long flags; - - if (port) { - DPRINTF("sn_console: switching to interrupt driven console\n"); - - if (request_irq(SGI_UART_VECTOR, sn_sal_interrupt, - IRQF_SHARED, - "SAL console driver", port) >= 0) { - spin_lock_irqsave(&port->sc_port.lock, flags); - port->sc_port.irq = SGI_UART_VECTOR; - port->sc_ops = &intr_ops; - irq_set_handler(port->sc_port.irq, handle_level_irq); - - /* turn on receive interrupts */ - ia64_sn_console_intr_enable(SAL_CONSOLE_INTR_RECV); - spin_unlock_irqrestore(&port->sc_port.lock, flags); - } - else { - printk(KERN_INFO - "sn_console: console proceeding in polled mode\n"); - } - } -} - -/* - * Kernel console definitions - */ - -static void sn_sal_console_write(struct console *, const char *, unsigned); -static int sn_sal_console_setup(struct console *, char *); -static struct uart_driver sal_console_uart; -extern struct tty_driver *uart_console_device(struct console *, int *); - -static struct console sal_console = { - .name = DEVICE_NAME, - .write = sn_sal_console_write, - .device = uart_console_device, - .setup = sn_sal_console_setup, - .index = -1, /* unspecified */ - .data = &sal_console_uart, -}; - -#define SAL_CONSOLE &sal_console - -static struct uart_driver sal_console_uart = { - .owner = THIS_MODULE, - .driver_name = "sn_console", - .dev_name = DEVICE_NAME, - .major = 0, /* major/minor set at registration time per USE_DYNAMIC_MINOR */ - .minor = 0, - .nr = 1, /* one port */ - .cons = SAL_CONSOLE, -}; - -/** - * sn_sal_init - When the kernel loads us, get us rolling w/ serial core - * - * Before this is called, we've been printing kernel messages in a special - * early mode not making use of the serial core infrastructure. When our - * driver is loaded for real, we register the driver and port with serial - * core and try to enable interrupt driven mode. - * - */ -static int __init sn_sal_init(void) -{ - int retval; - - if (!ia64_platform_is("sn2")) - return 0; - - printk(KERN_INFO "sn_console: Console driver init\n"); - - if (USE_DYNAMIC_MINOR == 1) { - misc.minor = MISC_DYNAMIC_MINOR; - misc.name = DEVICE_NAME_DYNAMIC; - retval = misc_register(&misc); - if (retval != 0) { - printk(KERN_WARNING "Failed to register console " - "device using misc_register.\n"); - return -ENODEV; - } - sal_console_uart.major = MISC_MAJOR; - sal_console_uart.minor = misc.minor; - } else { - sal_console_uart.major = DEVICE_MAJOR; - sal_console_uart.minor = DEVICE_MINOR; - } - - /* We register the driver and the port before switching to interrupts - * or async above so the proper uart structures are populated */ - - if (uart_register_driver(&sal_console_uart) < 0) { - printk - ("ERROR sn_sal_init failed uart_register_driver, line %d\n", - __LINE__); - return -ENODEV; - } - - spin_lock_init(&sal_console_port.sc_port.lock); - - /* Setup the port struct with the minimum needed */ - sal_console_port.sc_port.membase = (char *)1; /* just needs to be non-zero */ - sal_console_port.sc_port.type = PORT_16550A; - sal_console_port.sc_port.fifosize = SN_SAL_MAX_CHARS; - sal_console_port.sc_port.ops = &sn_console_ops; - sal_console_port.sc_port.line = 0; - - if (uart_add_one_port(&sal_console_uart, &sal_console_port.sc_port) < 0) { - /* error - not sure what I'd do - so I'll do nothing */ - printk(KERN_ERR "%s: unable to add port\n", __func__); - } - - /* when this driver is compiled in, the console initialization - * will have already switched us into asynchronous operation - * before we get here through the initcalls */ - if (!sal_console_port.sc_is_asynch) { - sn_sal_switch_to_asynch(&sal_console_port); - } - - /* at this point (device_init) we can try to turn on interrupts */ - if (!IS_RUNNING_ON_SIMULATOR()) { - sn_sal_switch_to_interrupts(&sal_console_port); - } - sn_process_input = 1; - return 0; -} -device_initcall(sn_sal_init); - -/** - * puts_raw_fixed - sn_sal_console_write helper for adding \r's as required - * @puts_raw : puts function to do the writing - * @s: input string - * @count: length - * - * We need a \r ahead of every \n for direct writes through - * ia64_sn_console_putb (what sal_puts_raw below actually does). - * - */ - -static void puts_raw_fixed(int (*puts_raw) (const char *s, int len), - const char *s, int count) -{ - const char *s1; - - /* Output '\r' before each '\n' */ - while ((s1 = memchr(s, '\n', count)) != NULL) { - puts_raw(s, s1 - s); - puts_raw("\r\n", 2); - count -= s1 + 1 - s; - s = s1 + 1; - } - puts_raw(s, count); -} - -/** - * sn_sal_console_write - Print statements before serial core available - * @console: Console to operate on - we ignore since we have just one - * @s: String to send - * @count: length - * - * This is referenced in the console struct. It is used for early - * console printing before we register with serial core and for things - * such as kdb. The console_lock must be held when we get here. - * - * This function has some code for trying to print output even if the lock - * is held. We try to cover the case where a lock holder could have died. - * We don't use this special case code if we're not registered with serial - * core yet. After we're registered with serial core, the only time this - * function would be used is for high level kernel output like magic sys req, - * kdb, and printk's. - */ -static void -sn_sal_console_write(struct console *co, const char *s, unsigned count) -{ - unsigned long flags = 0; - struct sn_cons_port *port = &sal_console_port; - static int stole_lock = 0; - - BUG_ON(!port->sc_is_asynch); - - /* We can't look at the xmit buffer if we're not registered with serial core - * yet. So only do the fancy recovery after registering - */ - if (!port->sc_port.state) { - /* Not yet registered with serial core - simple case */ - puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count); - return; - } - - /* somebody really wants this output, might be an - * oops, kdb, panic, etc. make sure they get it. */ - if (!spin_trylock_irqsave(&port->sc_port.lock, flags)) { - int lhead = port->sc_port.state->xmit.head; - int ltail = port->sc_port.state->xmit.tail; - int counter, got_lock = 0; - - /* - * We attempt to determine if someone has died with the - * lock. We wait ~20 secs after the head and tail ptrs - * stop moving and assume the lock holder is not functional - * and plow ahead. If the lock is freed within the time out - * period we re-get the lock and go ahead normally. We also - * remember if we have plowed ahead so that we don't have - * to wait out the time out period again - the asumption - * is that we will time out again. - */ - - for (counter = 0; counter < 150; mdelay(125), counter++) { - if (stole_lock) - break; - - if (spin_trylock_irqsave(&port->sc_port.lock, flags)) { - got_lock = 1; - break; - } else { - /* still locked */ - if ((lhead != port->sc_port.state->xmit.head) - || (ltail != - port->sc_port.state->xmit.tail)) { - lhead = - port->sc_port.state->xmit.head; - ltail = - port->sc_port.state->xmit.tail; - counter = 0; - } - } - } - /* flush anything in the serial core xmit buffer, raw */ - sn_transmit_chars(port, 1); - if (got_lock) { - spin_unlock_irqrestore(&port->sc_port.lock, flags); - stole_lock = 0; - } else { - /* fell thru */ - stole_lock = 1; - } - puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count); - } else { - stole_lock = 0; - sn_transmit_chars(port, 1); - spin_unlock_irqrestore(&port->sc_port.lock, flags); - - puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count); - } -} - - -/** - * sn_sal_console_setup - Set up console for early printing - * @co: Console to work with - * @options: Options to set - * - * Altix console doesn't do anything with baud rates, etc, anyway. - * - * This isn't required since not providing the setup function in the - * console struct is ok. However, other patches like KDB plop something - * here so providing it is easier. - * - */ -static int sn_sal_console_setup(struct console *co, char *options) -{ - return 0; -} - -/** - * sn_sal_console_write_early - simple early output routine - * @co - console struct - * @s - string to print - * @count - count - * - * Simple function to provide early output, before even - * sn_sal_serial_console_init is called. Referenced in the - * console struct registerd in sn_serial_console_early_setup. - * - */ -static void __init -sn_sal_console_write_early(struct console *co, const char *s, unsigned count) -{ - puts_raw_fixed(sal_console_port.sc_ops->sal_puts_raw, s, count); -} - -/* Used for very early console printing - again, before - * sn_sal_serial_console_init is run */ -static struct console sal_console_early __initdata = { - .name = "sn_sal", - .write = sn_sal_console_write_early, - .flags = CON_PRINTBUFFER, - .index = -1, -}; - -/** - * sn_serial_console_early_setup - Sets up early console output support - * - * Register a console early on... This is for output before even - * sn_sal_serial_cosnole_init is called. This function is called from - * setup.c. This allows us to do really early polled writes. When - * sn_sal_serial_console_init is called, this console is unregistered - * and a new one registered. - */ -int __init sn_serial_console_early_setup(void) -{ - if (!ia64_platform_is("sn2")) - return -1; - - sal_console_port.sc_ops = &poll_ops; - spin_lock_init(&sal_console_port.sc_port.lock); - early_sn_setup(); /* Find SAL entry points */ - register_console(&sal_console_early); - - return 0; -} - -/** - * sn_sal_serial_console_init - Early console output - set up for register - * - * This function is called when regular console init happens. Because we - * support even earlier console output with sn_serial_console_early_setup - * (called from setup.c directly), this function unregisters the really - * early console. - * - * Note: Even if setup.c doesn't register sal_console_early, unregistering - * it here doesn't hurt anything. - * - */ -static int __init sn_sal_serial_console_init(void) -{ - if (ia64_platform_is("sn2")) { - sn_sal_switch_to_asynch(&sal_console_port); - DPRINTF("sn_sal_serial_console_init : register console\n"); - register_console(&sal_console); - unregister_console(&sal_console_early); - } - return 0; -} - -console_initcall(sn_sal_serial_console_init); diff --git a/drivers/tty/serial/sprd_serial.c b/drivers/tty/serial/sprd_serial.c index 73d71a4e6c0c..771d11196523 100644 --- a/drivers/tty/serial/sprd_serial.c +++ b/drivers/tty/serial/sprd_serial.c @@ -79,6 +79,7 @@ /* control register 1 */ #define SPRD_CTL1 0x001C #define SPRD_DMA_EN BIT(15) +#define SPRD_LOOPBACK_EN BIT(14) #define RX_HW_FLOW_CTL_THLD BIT(6) #define RX_HW_FLOW_CTL_EN BIT(7) #define TX_HW_FLOW_CTL_EN BIT(8) @@ -164,7 +165,14 @@ static unsigned int sprd_get_mctrl(struct uart_port *port) static void sprd_set_mctrl(struct uart_port *port, unsigned int mctrl) { - /* nothing to do */ + u32 val = serial_in(port, SPRD_CTL1); + + if (mctrl & TIOCM_LOOP) + val |= SPRD_LOOPBACK_EN; + else + val &= ~SPRD_LOOPBACK_EN; + + serial_out(port, SPRD_CTL1, val); } static void sprd_stop_rx(struct uart_port *port) @@ -609,7 +617,7 @@ static inline void sprd_rx(struct uart_port *port) if (lsr & (SPRD_LSR_BI | SPRD_LSR_PE | SPRD_LSR_FE | SPRD_LSR_OE)) - if (handle_lsr_errors(port, &lsr, &flag)) + if (handle_lsr_errors(port, &flag, &lsr)) continue; if (uart_handle_sysrq_char(port, ch)) continue; @@ -975,7 +983,7 @@ static void sprd_console_write(struct console *co, const char *s, static int __init sprd_console_setup(struct console *co, char *options) { - struct uart_port *port; + struct sprd_uart_port *sprd_uart_port; int baud = 115200; int bits = 8; int parity = 'n'; @@ -984,15 +992,17 @@ static int __init sprd_console_setup(struct console *co, char *options) if (co->index >= UART_NR_MAX || co->index < 0) co->index = 0; - port = &sprd_port[co->index]->port; - if (port == NULL) { + sprd_uart_port = sprd_port[co->index]; + if (!sprd_uart_port || !sprd_uart_port->port.membase) { pr_info("serial port %d not yet initialized\n", co->index); return -ENODEV; } + if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); - return uart_set_options(port, co, baud, parity, bits, flow); + return uart_set_options(&sprd_uart_port->port, co, baud, + parity, bits, flow); } static struct uart_driver sprd_uart_driver; @@ -1006,6 +1016,13 @@ static struct console sprd_console = { .data = &sprd_uart_driver, }; +static int __init sprd_serial_console_init(void) +{ + register_console(&sprd_console); + return 0; +} +console_initcall(sprd_serial_console_init); + #define SPRD_CONSOLE (&sprd_console) /* Support for earlycon */ @@ -1094,6 +1111,16 @@ static int sprd_remove(struct platform_device *dev) return 0; } +static bool sprd_uart_is_console(struct uart_port *uport) +{ + struct console *cons = sprd_uart_driver.cons; + + if (cons && cons->index >= 0 && cons->index == uport->line) + return true; + + return false; +} + static int sprd_clk_init(struct uart_port *uport) { struct clk *clk_uart, *clk_parent; @@ -1120,10 +1147,17 @@ static int sprd_clk_init(struct uart_port *uport) u->clk = devm_clk_get(uport->dev, "enable"); if (IS_ERR(u->clk)) { - if (PTR_ERR(u->clk) != -EPROBE_DEFER) - dev_err(uport->dev, "uart%d can't get enable clock\n", - uport->line); - return PTR_ERR(u->clk); + if (PTR_ERR(u->clk) == -EPROBE_DEFER) + return -EPROBE_DEFER; + + dev_warn(uport->dev, "uart%d can't get enable clock\n", + uport->line); + + /* To keep console alive even if the error occurred */ + if (!sprd_uart_is_console(uport)) + return PTR_ERR(u->clk); + + u->clk = NULL; } return 0; @@ -1173,10 +1207,8 @@ static int sprd_probe(struct platform_device *pdev) up->mapbase = res->start; irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "not provide irq resource: %d\n", irq); + if (irq < 0) return irq; - } up->irq = irq; /* diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index e8d7a7bb4339..df90747ee3a8 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -24,6 +24,7 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/of_platform.h> +#include <linux/pinctrl/consumer.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/pm_wakeirq.h> @@ -105,9 +106,7 @@ static int stm32_config_rs485(struct uart_port *port, struct stm32_usart_config *cfg = &stm32_port->info->cfg; u32 usartdiv, baud, cr1, cr3; bool over8; - unsigned long flags; - spin_lock_irqsave(&port->lock, flags); stm32_clr_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit)); port->rs485 = *rs485conf; @@ -147,7 +146,6 @@ static int stm32_config_rs485(struct uart_port *port, } stm32_set_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit)); - spin_unlock_irqrestore(&port->lock, flags); return 0; } @@ -194,8 +192,8 @@ static int stm32_pending_rx(struct uart_port *port, u32 *sr, int *last_res, return 0; } -static unsigned long -stm32_get_char(struct uart_port *port, u32 *sr, int *last_res) +static unsigned long stm32_get_char(struct uart_port *port, u32 *sr, + int *last_res) { struct stm32_port *stm32_port = to_stm32_port(port); struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; @@ -205,10 +203,13 @@ stm32_get_char(struct uart_port *port, u32 *sr, int *last_res) c = stm32_port->rx_buf[RX_BUF_L - (*last_res)--]; if ((*last_res) == 0) *last_res = RX_BUF_L; - return c; } else { - return readl_relaxed(port->membase + ofs->rdr); + c = readl_relaxed(port->membase + ofs->rdr); + /* apply RDR data mask */ + c &= stm32_port->rdr_mask; } + + return c; } static void stm32_receive_chars(struct uart_port *port, bool threaded) @@ -225,35 +226,51 @@ static void stm32_receive_chars(struct uart_port *port, bool threaded) while (stm32_pending_rx(port, &sr, &stm32_port->last_res, threaded)) { sr |= USART_SR_DUMMY_RX; - c = stm32_get_char(port, &sr, &stm32_port->last_res); flag = TTY_NORMAL; - port->icount.rx++; + /* + * Status bits has to be cleared before reading the RDR: + * In FIFO mode, reading the RDR will pop the next data + * (if any) along with its status bits into the SR. + * Not doing so leads to misalignement between RDR and SR, + * and clear status bits of the next rx data. + * + * Clear errors flags for stm32f7 and stm32h7 compatible + * devices. On stm32f4 compatible devices, the error bit is + * cleared by the sequence [read SR - read DR]. + */ + if ((sr & USART_SR_ERR_MASK) && ofs->icr != UNDEF_REG) + stm32_clr_bits(port, ofs->icr, USART_ICR_ORECF | + USART_ICR_PECF | USART_ICR_FECF); + + c = stm32_get_char(port, &sr, &stm32_port->last_res); + port->icount.rx++; if (sr & USART_SR_ERR_MASK) { - if (sr & USART_SR_LBD) { - port->icount.brk++; - if (uart_handle_break(port)) - continue; - } else if (sr & USART_SR_ORE) { - if (ofs->icr != UNDEF_REG) - writel_relaxed(USART_ICR_ORECF, - port->membase + - ofs->icr); + if (sr & USART_SR_ORE) { port->icount.overrun++; } else if (sr & USART_SR_PE) { port->icount.parity++; } else if (sr & USART_SR_FE) { - port->icount.frame++; + /* Break detection if character is null */ + if (!c) { + port->icount.brk++; + if (uart_handle_break(port)) + continue; + } else { + port->icount.frame++; + } } sr &= port->read_status_mask; - if (sr & USART_SR_LBD) - flag = TTY_BREAK; - else if (sr & USART_SR_PE) + if (sr & USART_SR_PE) { flag = TTY_PARITY; - else if (sr & USART_SR_FE) - flag = TTY_FRAME; + } else if (sr & USART_SR_FE) { + if (!c) + flag = TTY_BREAK; + else + flag = TTY_FRAME; + } } if (uart_handle_sysrq_char(port, c)) @@ -271,21 +288,6 @@ static void stm32_tx_dma_complete(void *arg) struct uart_port *port = arg; struct stm32_port *stm32port = to_stm32_port(port); struct stm32_usart_offsets *ofs = &stm32port->info->ofs; - unsigned int isr; - int ret; - - ret = readl_relaxed_poll_timeout_atomic(port->membase + ofs->isr, - isr, - (isr & USART_SR_TC), - 10, 100000); - - if (ret) - dev_err(port->dev, "terminal count not set\n"); - - if (ofs->icr == UNDEF_REG) - stm32_clr_bits(port, ofs->isr, USART_SR_TC); - else - stm32_set_bits(port, ofs->icr, USART_CR_TC); stm32_clr_bits(port, ofs->cr3, USART_CR3_DMAT); stm32port->tx_dma_busy = false; @@ -294,32 +296,57 @@ static void stm32_tx_dma_complete(void *arg) stm32_transmit_chars(port); } +static void stm32_tx_interrupt_enable(struct uart_port *port) +{ + struct stm32_port *stm32_port = to_stm32_port(port); + struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; + + /* + * Enables TX FIFO threashold irq when FIFO is enabled, + * or TX empty irq when FIFO is disabled + */ + if (stm32_port->fifoen) + stm32_set_bits(port, ofs->cr3, USART_CR3_TXFTIE); + else + stm32_set_bits(port, ofs->cr1, USART_CR1_TXEIE); +} + +static void stm32_tx_interrupt_disable(struct uart_port *port) +{ + struct stm32_port *stm32_port = to_stm32_port(port); + struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; + + if (stm32_port->fifoen) + stm32_clr_bits(port, ofs->cr3, USART_CR3_TXFTIE); + else + stm32_clr_bits(port, ofs->cr1, USART_CR1_TXEIE); +} + static void stm32_transmit_chars_pio(struct uart_port *port) { struct stm32_port *stm32_port = to_stm32_port(port); struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; struct circ_buf *xmit = &port->state->xmit; - unsigned int isr; - int ret; if (stm32_port->tx_dma_busy) { stm32_clr_bits(port, ofs->cr3, USART_CR3_DMAT); stm32_port->tx_dma_busy = false; } - ret = readl_relaxed_poll_timeout_atomic(port->membase + ofs->isr, - isr, - (isr & USART_SR_TXE), - 10, 100000); - - if (ret) - dev_err(port->dev, "tx empty not set\n"); - - stm32_set_bits(port, ofs->cr1, USART_CR1_TXEIE); + while (!uart_circ_empty(xmit)) { + /* Check that TDR is empty before filling FIFO */ + if (!(readl_relaxed(port->membase + ofs->isr) & USART_SR_TXE)) + break; + writel_relaxed(xmit->buf[xmit->tail], port->membase + ofs->tdr); + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + port->icount.tx++; + } - writel_relaxed(xmit->buf[xmit->tail], port->membase + ofs->tdr); - xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); - port->icount.tx++; + /* rely on TXE irq (mask or unmask) for sending remaining data */ + if (uart_circ_empty(xmit)) + stm32_tx_interrupt_disable(port); + else + stm32_tx_interrupt_enable(port); } static void stm32_transmit_chars_dma(struct uart_port *port) @@ -377,7 +404,6 @@ static void stm32_transmit_chars_dma(struct uart_port *port) /* Issue pending DMA TX requests */ dma_async_issue_pending(stm32port->tx_ch); - stm32_clr_bits(port, ofs->isr, USART_SR_TC); stm32_set_bits(port, ofs->cr3, USART_CR3_DMAT); xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1); @@ -401,15 +427,15 @@ static void stm32_transmit_chars(struct uart_port *port) return; } - if (uart_tx_stopped(port)) { - stm32_stop_tx(port); + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { + stm32_tx_interrupt_disable(port); return; } - if (uart_circ_empty(xmit)) { - stm32_stop_tx(port); - return; - } + if (ofs->icr == UNDEF_REG) + stm32_clr_bits(port, ofs->isr, USART_SR_TC); + else + stm32_set_bits(port, ofs->icr, USART_ICR_TCCF); if (stm32_port->tx_ch) stm32_transmit_chars_dma(port); @@ -420,7 +446,7 @@ static void stm32_transmit_chars(struct uart_port *port) uart_write_wakeup(port); if (uart_circ_empty(xmit)) - stm32_stop_tx(port); + stm32_tx_interrupt_disable(port); } static irqreturn_t stm32_interrupt(int irq, void *ptr) @@ -434,6 +460,10 @@ static irqreturn_t stm32_interrupt(int irq, void *ptr) sr = readl_relaxed(port->membase + ofs->isr); + if ((sr & USART_SR_RTOF) && ofs->icr != UNDEF_REG) + writel_relaxed(USART_ICR_RTOCF, + port->membase + ofs->icr); + if ((sr & USART_SR_WUF) && (ofs->icr != UNDEF_REG)) writel_relaxed(USART_ICR_WUCF, port->membase + ofs->icr); @@ -495,10 +525,7 @@ static unsigned int stm32_get_mctrl(struct uart_port *port) /* Transmit stop */ static void stm32_stop_tx(struct uart_port *port) { - struct stm32_port *stm32_port = to_stm32_port(port); - struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; - - stm32_clr_bits(port, ofs->cr1, USART_CR1_TXEIE); + stm32_tx_interrupt_disable(port); } /* There are probably characters waiting to be transmitted. */ @@ -520,7 +547,10 @@ static void stm32_throttle(struct uart_port *port) unsigned long flags; spin_lock_irqsave(&port->lock, flags); - stm32_clr_bits(port, ofs->cr1, USART_CR1_RXNEIE); + stm32_clr_bits(port, ofs->cr1, stm32_port->cr1_irq); + if (stm32_port->cr3_irq) + stm32_clr_bits(port, ofs->cr3, stm32_port->cr3_irq); + spin_unlock_irqrestore(&port->lock, flags); } @@ -532,7 +562,10 @@ static void stm32_unthrottle(struct uart_port *port) unsigned long flags; spin_lock_irqsave(&port->lock, flags); - stm32_set_bits(port, ofs->cr1, USART_CR1_RXNEIE); + stm32_set_bits(port, ofs->cr1, stm32_port->cr1_irq); + if (stm32_port->cr3_irq) + stm32_set_bits(port, ofs->cr3, stm32_port->cr3_irq); + spin_unlock_irqrestore(&port->lock, flags); } @@ -542,7 +575,10 @@ static void stm32_stop_rx(struct uart_port *port) struct stm32_port *stm32_port = to_stm32_port(port); struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; - stm32_clr_bits(port, ofs->cr1, USART_CR1_RXNEIE); + stm32_clr_bits(port, ofs->cr1, stm32_port->cr1_irq); + if (stm32_port->cr3_irq) + stm32_clr_bits(port, ofs->cr3, stm32_port->cr3_irq); + } /* Handle breaks - ignored by us */ @@ -554,7 +590,6 @@ static int stm32_startup(struct uart_port *port) { struct stm32_port *stm32_port = to_stm32_port(port); struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; - struct stm32_usart_config *cfg = &stm32_port->info->cfg; const char *name = to_platform_device(port->dev)->name; u32 val; int ret; @@ -565,16 +600,21 @@ static int stm32_startup(struct uart_port *port) if (ret) return ret; - if (cfg->has_wakeup && stm32_port->wakeirq >= 0) { - ret = dev_pm_set_dedicated_wake_irq(port->dev, - stm32_port->wakeirq); - if (ret) { - free_irq(port->irq, port); - return ret; - } + /* RX FIFO Flush */ + if (ofs->rqr != UNDEF_REG) + stm32_set_bits(port, ofs->rqr, USART_RQR_RXFRQ); + + /* Tx and RX FIFO configuration */ + if (stm32_port->fifoen) { + val = readl_relaxed(port->membase + ofs->cr3); + val &= ~(USART_CR3_TXFTCFG_MASK | USART_CR3_RXFTCFG_MASK); + val |= USART_CR3_TXFTCFG_HALF << USART_CR3_TXFTCFG_SHIFT; + val |= USART_CR3_RXFTCFG_HALF << USART_CR3_RXFTCFG_SHIFT; + writel_relaxed(val, port->membase + ofs->cr3); } - val = USART_CR1_RXNEIE | USART_CR1_TE | USART_CR1_RE; + /* RX FIFO enabling */ + val = stm32_port->cr1_irq | USART_CR1_RE; if (stm32_port->fifoen) val |= USART_CR1_FIFOEN; stm32_set_bits(port, ofs->cr1, val); @@ -587,18 +627,57 @@ static void stm32_shutdown(struct uart_port *port) struct stm32_port *stm32_port = to_stm32_port(port); struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; struct stm32_usart_config *cfg = &stm32_port->info->cfg; - u32 val; + u32 val, isr; + int ret; - val = USART_CR1_TXEIE | USART_CR1_RXNEIE | USART_CR1_TE | USART_CR1_RE; + val = USART_CR1_TXEIE | USART_CR1_TE; + val |= stm32_port->cr1_irq | USART_CR1_RE; val |= BIT(cfg->uart_enable_bit); if (stm32_port->fifoen) val |= USART_CR1_FIFOEN; + + ret = readl_relaxed_poll_timeout(port->membase + ofs->isr, + isr, (isr & USART_SR_TC), + 10, 100000); + + if (ret) + dev_err(port->dev, "transmission complete not set\n"); + stm32_clr_bits(port, ofs->cr1, val); - dev_pm_clear_wake_irq(port->dev); free_irq(port->irq, port); } +static unsigned int stm32_get_databits(struct ktermios *termios) +{ + unsigned int bits; + + tcflag_t cflag = termios->c_cflag; + + switch (cflag & CSIZE) { + /* + * CSIZE settings are not necessarily supported in hardware. + * CSIZE unsupported configurations are handled here to set word length + * to 8 bits word as default configuration and to print debug message. + */ + case CS5: + bits = 5; + break; + case CS6: + bits = 6; + break; + case CS7: + bits = 7; + break; + /* default including CS8 */ + default: + bits = 8; + break; + } + + return bits; +} + static void stm32_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { @@ -606,7 +685,7 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios, struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; struct stm32_usart_config *cfg = &stm32_port->info->cfg; struct serial_rs485 *rs485conf = &port->rs485; - unsigned int baud; + unsigned int baud, bits; u32 usartdiv, mantissa, fraction, oversampling; tcflag_t cflag = termios->c_cflag; u32 cr1, cr2, cr3; @@ -622,26 +701,64 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios, /* Stop serial port and reset value */ writel_relaxed(0, port->membase + ofs->cr1); - cr1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_RXNEIE; + /* flush RX & TX FIFO */ + if (ofs->rqr != UNDEF_REG) + stm32_set_bits(port, ofs->rqr, + USART_RQR_TXFRQ | USART_RQR_RXFRQ); + cr1 = USART_CR1_TE | USART_CR1_RE; if (stm32_port->fifoen) cr1 |= USART_CR1_FIFOEN; cr2 = 0; - cr3 = 0; + cr3 = readl_relaxed(port->membase + ofs->cr3); + cr3 &= USART_CR3_TXFTIE | USART_CR3_RXFTCFG_MASK | USART_CR3_RXFTIE + | USART_CR3_TXFTCFG_MASK; if (cflag & CSTOPB) cr2 |= USART_CR2_STOP_2B; + bits = stm32_get_databits(termios); + stm32_port->rdr_mask = (BIT(bits) - 1); + if (cflag & PARENB) { + bits++; cr1 |= USART_CR1_PCE; - if ((cflag & CSIZE) == CS8) { - if (cfg->has_7bits_data) - cr1 |= USART_CR1_M0; - else - cr1 |= USART_CR1_M; - } } + /* + * Word length configuration: + * CS8 + parity, 9 bits word aka [M1:M0] = 0b01 + * CS7 or (CS6 + parity), 7 bits word aka [M1:M0] = 0b10 + * CS8 or (CS7 + parity), 8 bits word aka [M1:M0] = 0b00 + * M0 and M1 already cleared by cr1 initialization. + */ + if (bits == 9) + cr1 |= USART_CR1_M0; + else if ((bits == 7) && cfg->has_7bits_data) + cr1 |= USART_CR1_M1; + else if (bits != 8) + dev_dbg(port->dev, "Unsupported data bits config: %u bits\n" + , bits); + + if (ofs->rtor != UNDEF_REG && (stm32_port->rx_ch || + stm32_port->fifoen)) { + if (cflag & CSTOPB) + bits = bits + 3; /* 1 start bit + 2 stop bits */ + else + bits = bits + 2; /* 1 start bit + 1 stop bit */ + + /* RX timeout irq to occur after last stop bit + bits */ + stm32_port->cr1_irq = USART_CR1_RTOIE; + writel_relaxed(bits, port->membase + ofs->rtor); + cr2 |= USART_CR2_RTOEN; + /* Not using dma, enable fifo threshold irq */ + if (!stm32_port->rx_ch) + stm32_port->cr3_irq = USART_CR3_RXFTIE; + } + + cr1 |= stm32_port->cr1_irq; + cr3 |= stm32_port->cr3_irq; + if (cflag & PARODD) cr1 |= USART_CR1_PS; @@ -679,14 +796,14 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios, if (termios->c_iflag & INPCK) port->read_status_mask |= USART_SR_PE | USART_SR_FE; if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK)) - port->read_status_mask |= USART_SR_LBD; + port->read_status_mask |= USART_SR_FE; /* Characters to ignore */ port->ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) port->ignore_status_mask = USART_SR_PE | USART_SR_FE; if (termios->c_iflag & IGNBRK) { - port->ignore_status_mask |= USART_SR_LBD; + port->ignore_status_mask |= USART_SR_FE; /* * If we're ignoring parity and break indicators, * ignore overruns too (for real raw support). @@ -765,13 +882,13 @@ static void stm32_pm(struct uart_port *port, unsigned int state, switch (state) { case UART_PM_STATE_ON: - clk_prepare_enable(stm32port->clk); + pm_runtime_get_sync(port->dev); break; case UART_PM_STATE_OFF: spin_lock_irqsave(&port->lock, flags); stm32_clr_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit)); spin_unlock_irqrestore(&port->lock, flags); - clk_disable_unprepare(stm32port->clk); + pm_runtime_put_sync(port->dev); break; } } @@ -808,12 +925,23 @@ static int stm32_init_port(struct stm32_port *stm32port, port->flags = UPF_BOOT_AUTOCONF; port->ops = &stm32_uart_ops; port->dev = &pdev->dev; - port->irq = platform_get_irq(pdev, 0); + port->fifosize = stm32port->info->cfg.fifosize; + + ret = platform_get_irq(pdev, 0); + if (ret <= 0) + return ret ? : -ENODEV; + port->irq = ret; + port->rs485_config = stm32_config_rs485; stm32_init_rs485(port, pdev); - stm32port->wakeirq = platform_get_irq(pdev, 1); + if (stm32port->info->cfg.has_wakeup) { + stm32port->wakeirq = platform_get_irq(pdev, 1); + if (stm32port->wakeirq <= 0 && stm32port->wakeirq != -ENXIO) + return stm32port->wakeirq ? : -ENODEV; + } + stm32port->fifoen = stm32port->info->cfg.has_fifo; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -862,6 +990,8 @@ static struct stm32_port *stm32_of_get_stm32_port(struct platform_device *pdev) stm32_ports[id].hw_flow_control = of_property_read_bool(np, "st,hw-flow-ctrl"); stm32_ports[id].port.line = id; + stm32_ports[id].cr1_irq = USART_CR1_RXNEIE; + stm32_ports[id].cr3_irq = 0; stm32_ports[id].last_res = RX_BUF_L; return &stm32_ports[id]; } @@ -1020,15 +1150,22 @@ static int stm32_serial_probe(struct platform_device *pdev) if (ret) return ret; - if (stm32port->info->cfg.has_wakeup && stm32port->wakeirq >= 0) { + if (stm32port->wakeirq > 0) { ret = device_init_wakeup(&pdev->dev, true); if (ret) goto err_uninit; + + ret = dev_pm_set_dedicated_wake_irq(&pdev->dev, + stm32port->wakeirq); + if (ret) + goto err_nowup; + + device_set_wakeup_enable(&pdev->dev, false); } ret = uart_add_one_port(&stm32_usart_driver, &stm32port->port); if (ret) - goto err_nowup; + goto err_wirq; ret = stm32_of_dma_rx_probe(stm32port, pdev); if (ret) @@ -1040,10 +1177,19 @@ static int stm32_serial_probe(struct platform_device *pdev) platform_set_drvdata(pdev, &stm32port->port); + pm_runtime_get_noresume(&pdev->dev); + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); + pm_runtime_put_sync(&pdev->dev); + return 0; +err_wirq: + if (stm32port->wakeirq > 0) + dev_pm_clear_wake_irq(&pdev->dev); + err_nowup: - if (stm32port->info->cfg.has_wakeup && stm32port->wakeirq >= 0) + if (stm32port->wakeirq > 0) device_init_wakeup(&pdev->dev, false); err_uninit: @@ -1057,7 +1203,9 @@ static int stm32_serial_remove(struct platform_device *pdev) struct uart_port *port = platform_get_drvdata(pdev); struct stm32_port *stm32_port = to_stm32_port(port); struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; - struct stm32_usart_config *cfg = &stm32_port->info->cfg; + int err; + + pm_runtime_get_sync(&pdev->dev); stm32_clr_bits(port, ofs->cr3, USART_CR3_DMAR); @@ -1079,12 +1227,19 @@ static int stm32_serial_remove(struct platform_device *pdev) TX_BUF_L, stm32_port->tx_buf, stm32_port->tx_dma_buf); - if (cfg->has_wakeup && stm32_port->wakeirq >= 0) + if (stm32_port->wakeirq > 0) { + dev_pm_clear_wake_irq(&pdev->dev); device_init_wakeup(&pdev->dev, false); + } clk_disable_unprepare(stm32_port->clk); - return uart_remove_one_port(&stm32_usart_driver, port); + err = uart_remove_one_port(&stm32_usart_driver, port); + + pm_runtime_disable(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); + + return err; } @@ -1187,15 +1342,15 @@ static struct uart_driver stm32_usart_driver = { .cons = STM32_SERIAL_CONSOLE, }; -#ifdef CONFIG_PM_SLEEP -static void stm32_serial_enable_wakeup(struct uart_port *port, bool enable) +static void __maybe_unused stm32_serial_enable_wakeup(struct uart_port *port, + bool enable) { struct stm32_port *stm32_port = to_stm32_port(port); struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; struct stm32_usart_config *cfg = &stm32_port->info->cfg; u32 val; - if (!cfg->has_wakeup || stm32_port->wakeirq < 0) + if (stm32_port->wakeirq <= 0) return; if (enable) { @@ -1212,7 +1367,7 @@ static void stm32_serial_enable_wakeup(struct uart_port *port, bool enable) } } -static int stm32_serial_suspend(struct device *dev) +static int __maybe_unused stm32_serial_suspend(struct device *dev) { struct uart_port *port = dev_get_drvdata(dev); @@ -1223,21 +1378,46 @@ static int stm32_serial_suspend(struct device *dev) else stm32_serial_enable_wakeup(port, false); + pinctrl_pm_select_sleep_state(dev); + return 0; } -static int stm32_serial_resume(struct device *dev) +static int __maybe_unused stm32_serial_resume(struct device *dev) { struct uart_port *port = dev_get_drvdata(dev); + pinctrl_pm_select_default_state(dev); + if (device_may_wakeup(dev)) stm32_serial_enable_wakeup(port, false); return uart_resume_port(&stm32_usart_driver, port); } -#endif /* CONFIG_PM_SLEEP */ + +static int __maybe_unused stm32_serial_runtime_suspend(struct device *dev) +{ + struct uart_port *port = dev_get_drvdata(dev); + struct stm32_port *stm32port = container_of(port, + struct stm32_port, port); + + clk_disable_unprepare(stm32port->clk); + + return 0; +} + +static int __maybe_unused stm32_serial_runtime_resume(struct device *dev) +{ + struct uart_port *port = dev_get_drvdata(dev); + struct stm32_port *stm32port = container_of(port, + struct stm32_port, port); + + return clk_prepare_enable(stm32port->clk); +} static const struct dev_pm_ops stm32_serial_pm_ops = { + SET_RUNTIME_PM_OPS(stm32_serial_runtime_suspend, + stm32_serial_runtime_resume, NULL) SET_SYSTEM_SLEEP_PM_OPS(stm32_serial_suspend, stm32_serial_resume) }; diff --git a/drivers/tty/serial/stm32-usart.h b/drivers/tty/serial/stm32-usart.h index 6f294e280ea3..a175c1094dc8 100644 --- a/drivers/tty/serial/stm32-usart.h +++ b/drivers/tty/serial/stm32-usart.h @@ -27,6 +27,7 @@ struct stm32_usart_config { bool has_7bits_data; bool has_wakeup; bool has_fifo; + int fifosize; }; struct stm32_usart_info { @@ -54,6 +55,7 @@ struct stm32_usart_info stm32f4_info = { .cfg = { .uart_enable_bit = 13, .has_7bits_data = false, + .fifosize = 1, } }; @@ -74,6 +76,7 @@ struct stm32_usart_info stm32f7_info = { .cfg = { .uart_enable_bit = 0, .has_7bits_data = true, + .fifosize = 1, } }; @@ -96,6 +99,7 @@ struct stm32_usart_info stm32h7_info = { .has_7bits_data = true, .has_wakeup = true, .has_fifo = true, + .fifosize = 16, } }; @@ -108,7 +112,6 @@ struct stm32_usart_info stm32h7_info = { #define USART_SR_RXNE BIT(5) #define USART_SR_TC BIT(6) #define USART_SR_TXE BIT(7) -#define USART_SR_LBD BIT(8) #define USART_SR_CTSIF BIT(9) #define USART_SR_CTS BIT(10) /* F7 */ #define USART_SR_RTOF BIT(11) /* F7 */ @@ -120,8 +123,7 @@ struct stm32_usart_info stm32h7_info = { #define USART_SR_SBKF BIT(18) /* F7 */ #define USART_SR_WUF BIT(20) /* H7 */ #define USART_SR_TEACK BIT(21) /* F7 */ -#define USART_SR_ERR_MASK (USART_SR_LBD | USART_SR_ORE | \ - USART_SR_FE | USART_SR_PE) +#define USART_SR_ERR_MASK (USART_SR_ORE | USART_SR_FE | USART_SR_PE) /* Dummy bits */ #define USART_SR_DUMMY_RX BIT(16) @@ -151,8 +153,7 @@ struct stm32_usart_info stm32h7_info = { #define USART_CR1_PS BIT(9) #define USART_CR1_PCE BIT(10) #define USART_CR1_WAKE BIT(11) -#define USART_CR1_M BIT(12) -#define USART_CR1_M0 BIT(12) /* F7 */ +#define USART_CR1_M0 BIT(12) /* F7 (CR1_M for F4) */ #define USART_CR1_MME BIT(13) /* F7 */ #define USART_CR1_CMIE BIT(14) /* F7 */ #define USART_CR1_OVER8 BIT(15) @@ -169,8 +170,6 @@ struct stm32_usart_info stm32h7_info = { /* USART_CR2 */ #define USART_CR2_ADD_MASK GENMASK(3, 0) /* F4 */ #define USART_CR2_ADDM7 BIT(4) /* F7 */ -#define USART_CR2_LBDL BIT(5) -#define USART_CR2_LBDIE BIT(6) #define USART_CR2_LBCL BIT(8) #define USART_CR2_CPHA BIT(9) #define USART_CR2_CPOL BIT(10) @@ -209,6 +208,19 @@ struct stm32_usart_info stm32h7_info = { #define USART_CR3_WUS_MASK GENMASK(21, 20) /* H7 */ #define USART_CR3_WUS_START_BIT BIT(21) /* H7 */ #define USART_CR3_WUFIE BIT(22) /* H7 */ +#define USART_CR3_TXFTIE BIT(23) /* H7 */ +#define USART_CR3_TCBGTIE BIT(24) /* H7 */ +#define USART_CR3_RXFTCFG_MASK GENMASK(27, 25) /* H7 */ +#define USART_CR3_RXFTCFG_SHIFT 25 /* H7 */ +#define USART_CR3_RXFTIE BIT(28) /* H7 */ +#define USART_CR3_TXFTCFG_MASK GENMASK(31, 29) /* H7 */ +#define USART_CR3_TXFTCFG_SHIFT 29 /* H7 */ + +/* TX FIFO threashold set to half of its depth */ +#define USART_CR3_TXFTCFG_HALF 0x2 + +/* RX FIFO threashold set to half of its depth */ +#define USART_CR3_RXFTCFG_HALF 0x2 /* USART_GTPR */ #define USART_GTPR_PSC_MASK GENMASK(7, 0) @@ -227,12 +239,10 @@ struct stm32_usart_info stm32h7_info = { /* USART_ICR */ #define USART_ICR_PECF BIT(0) /* F7 */ -#define USART_ICR_FFECF BIT(1) /* F7 */ -#define USART_ICR_NCF BIT(2) /* F7 */ +#define USART_ICR_FECF BIT(1) /* F7 */ #define USART_ICR_ORECF BIT(3) /* F7 */ #define USART_ICR_IDLECF BIT(4) /* F7 */ #define USART_ICR_TCCF BIT(6) /* F7 */ -#define USART_ICR_LBDCF BIT(8) /* F7 */ #define USART_ICR_CTSCF BIT(9) /* F7 */ #define USART_ICR_RTOCF BIT(11) /* F7 */ #define USART_ICR_EOBCF BIT(12) /* F7 */ @@ -256,11 +266,14 @@ struct stm32_port { struct dma_chan *tx_ch; /* dma tx channel */ dma_addr_t tx_dma_buf; /* dma tx buffer bus address */ unsigned char *tx_buf; /* dma tx buffer cpu address */ + u32 cr1_irq; /* USART_CR1_RXNEIE or RTOIE */ + u32 cr3_irq; /* USART_CR3_RXFTIE */ int last_res; bool tx_dma_busy; /* dma tx busy */ bool hw_flow_control; bool fifoen; int wakeirq; + int rdr_mask; /* receive data register mask */ }; static struct stm32_port stm32_ports[STM32_MAX_PORTS]; diff --git a/drivers/tty/serial/sunhv.c b/drivers/tty/serial/sunhv.c index 63e34d868de8..f8503f8fc44e 100644 --- a/drivers/tty/serial/sunhv.c +++ b/drivers/tty/serial/sunhv.c @@ -397,7 +397,7 @@ static const struct uart_ops sunhv_pops = { static struct uart_driver sunhv_reg = { .owner = THIS_MODULE, .driver_name = "sunhv", - .dev_name = "ttyS", + .dev_name = "ttyHV", .major = TTY_MAJOR, }; diff --git a/drivers/tty/serial/ucc_uart.c b/drivers/tty/serial/ucc_uart.c index 6e3c66ab0e62..a0555ae2b1ef 100644 --- a/drivers/tty/serial/ucc_uart.c +++ b/drivers/tty/serial/ucc_uart.c @@ -1081,7 +1081,7 @@ static int qe_uart_verify_port(struct uart_port *port, } /* UART operations * - * Details on these functions can be found in Documentation/serial/driver.rst + * Details on these functions can be found in Documentation/driver-api/serial/driver.rst */ static const struct uart_ops qe_uart_pops = { .tx_empty = qe_uart_tx_empty, diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 605354fd60b1..da4563aaaf5c 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -26,21 +26,23 @@ #include <linux/of.h> #include <linux/module.h> #include <linux/pm_runtime.h> +#include <linux/iopoll.h> #define CDNS_UART_TTY_NAME "ttyPS" #define CDNS_UART_NAME "xuartps" -#define CDNS_UART_MAJOR 0 /* use dynamic node allocation */ #define CDNS_UART_FIFO_SIZE 64 /* FIFO size */ #define CDNS_UART_REGISTER_SPACE 0x1000 +#define TX_TIMEOUT 500000 /* Rx Trigger level */ static int rx_trigger_level = 56; -module_param(rx_trigger_level, uint, S_IRUGO); +static int uartps_major; +module_param(rx_trigger_level, uint, 0444); MODULE_PARM_DESC(rx_trigger_level, "Rx trigger level, 1-63 bytes"); /* Rx Timeout */ static int rx_timeout = 10; -module_param(rx_timeout, uint, S_IRUGO); +module_param(rx_timeout, uint, 0444); MODULE_PARM_DESC(rx_timeout, "Rx timeout, 1-255"); /* Register offsets for the UART. */ @@ -199,7 +201,7 @@ struct cdns_platform_data { u32 quirks; }; #define to_cdns_uart(_nb) container_of(_nb, struct cdns_uart, \ - clk_rate_change_nb); + clk_rate_change_nb) /** * cdns_uart_handle_rx - Handle the received bytes along with Rx errors. @@ -312,15 +314,16 @@ static void cdns_uart_handle_tx(void *dev_id) } else { numbytes = port->fifosize; while (numbytes && !uart_circ_empty(&port->state->xmit) && - !(readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_TXFULL)) { + !(readl(port->membase + CDNS_UART_SR) & + CDNS_UART_SR_TXFULL)) { /* * Get the data from the UART circular buffer * and write it to the cdns_uart's TX_FIFO * register. */ writel( - port->state->xmit.buf[port->state->xmit. - tail], port->membase + CDNS_UART_FIFO); + port->state->xmit.buf[port->state->xmit.tail], + port->membase + CDNS_UART_FIFO); port->icount.tx++; @@ -684,18 +687,21 @@ static void cdns_uart_set_termios(struct uart_port *port, unsigned int cval = 0; unsigned int baud, minbaud, maxbaud; unsigned long flags; - unsigned int ctrl_reg, mode_reg; - - spin_lock_irqsave(&port->lock, flags); + unsigned int ctrl_reg, mode_reg, val; + int err; /* Wait for the transmit FIFO to empty before making changes */ if (!(readl(port->membase + CDNS_UART_CR) & CDNS_UART_CR_TX_DIS)) { - while (!(readl(port->membase + CDNS_UART_SR) & - CDNS_UART_SR_TXEMPTY)) { - cpu_relax(); + err = readl_poll_timeout(port->membase + CDNS_UART_SR, + val, (val & CDNS_UART_SR_TXEMPTY), + 1000, TX_TIMEOUT); + if (err) { + dev_err(port->dev, "timed out waiting for tx empty"); + return; } } + spin_lock_irqsave(&port->lock, flags); /* Disable the TX and RX to set baud rate */ ctrl_reg = readl(port->membase + CDNS_UART_CR); @@ -1073,8 +1079,6 @@ static void cdns_uart_poll_put_char(struct uart_port *port, unsigned char c) cpu_relax(); spin_unlock_irqrestore(&port->lock, flags); - - return; } #endif @@ -1190,7 +1194,7 @@ static void cdns_uart_console_write(struct console *co, const char *s, unsigned int count) { struct uart_port *port = console_port; - unsigned long flags; + unsigned long flags = 0; unsigned int imr, ctrl; int locked = 1; @@ -1517,7 +1521,7 @@ static int cdns_uart_probe(struct platform_device *pdev) cdns_uart_uart_driver->owner = THIS_MODULE; cdns_uart_uart_driver->driver_name = driver_name; cdns_uart_uart_driver->dev_name = CDNS_UART_TTY_NAME; - cdns_uart_uart_driver->major = CDNS_UART_MAJOR; + cdns_uart_uart_driver->major = uartps_major; cdns_uart_uart_driver->minor = cdns_uart_data->id; cdns_uart_uart_driver->nr = 1; @@ -1546,6 +1550,7 @@ static int cdns_uart_probe(struct platform_device *pdev) goto err_out_id; } + uartps_major = cdns_uart_uart_driver->tty_driver->major; cdns_uart_data->cdns_uart_driver = cdns_uart_uart_driver; /* |