diff options
author | José Pekkarinen <jose.pekkarinen@nokia.com> | 2016-04-11 10:41:07 +0300 |
---|---|---|
committer | José Pekkarinen <jose.pekkarinen@nokia.com> | 2016-04-13 08:17:18 +0300 |
commit | e09b41010ba33a20a87472ee821fa407a5b8da36 (patch) | |
tree | d10dc367189862e7ca5c592f033dc3726e1df4e3 /kernel/drivers/tty/serial/mxs-auart.c | |
parent | f93b97fd65072de626c074dbe099a1fff05ce060 (diff) |
These changes are the raw update to linux-4.4.6-rt14. Kernel sources
are taken from kernel.org, and rt patch from the rt wiki download page.
During the rebasing, the following patch collided:
Force tick interrupt and get rid of softirq magic(I70131fb85).
Collisions have been removed because its logic was found on the
source already.
Change-Id: I7f57a4081d9deaa0d9ccfc41a6c8daccdee3b769
Signed-off-by: José Pekkarinen <jose.pekkarinen@nokia.com>
Diffstat (limited to 'kernel/drivers/tty/serial/mxs-auart.c')
-rw-r--r-- | kernel/drivers/tty/serial/mxs-auart.c | 62 |
1 files changed, 49 insertions, 13 deletions
diff --git a/kernel/drivers/tty/serial/mxs-auart.c b/kernel/drivers/tty/serial/mxs-auart.c index f7e5825b5..cd0414bbe 100644 --- a/kernel/drivers/tty/serial/mxs-auart.c +++ b/kernel/drivers/tty/serial/mxs-auart.c @@ -100,6 +100,8 @@ #define AUART_CTRL2_TXE (1 << 8) #define AUART_CTRL2_UARTEN (1 << 0) +#define AUART_LINECTRL_BAUD_DIV_MAX 0x003fffc0 +#define AUART_LINECTRL_BAUD_DIV_MIN 0x000000ec #define AUART_LINECTRL_BAUD_DIVINT_SHIFT 16 #define AUART_LINECTRL_BAUD_DIVINT_MASK 0xffff0000 #define AUART_LINECTRL_BAUD_DIVINT(v) (((v) & 0xffff) << 16) @@ -169,7 +171,7 @@ struct mxs_auart_port { bool ms_irq_enabled; }; -static struct platform_device_id mxs_auart_devtype[] = { +static const struct platform_device_id mxs_auart_devtype[] = { { .name = "mxs-auart-imx23", .driver_data = IMX23_AUART }, { .name = "mxs-auart-imx28", .driver_data = IMX28_AUART }, { /* sentinel */ } @@ -659,7 +661,7 @@ static void mxs_auart_settermios(struct uart_port *u, { struct mxs_auart_port *s = to_auart_port(u); u32 bm, ctrl, ctrl2, div; - unsigned int cflag, baud; + unsigned int cflag, baud, baud_min, baud_max; cflag = termios->c_cflag; @@ -752,7 +754,9 @@ static void mxs_auart_settermios(struct uart_port *u, } /* set baud rate */ - baud = uart_get_baud_rate(u, termios, old, 0, u->uartclk); + baud_min = DIV_ROUND_UP(u->uartclk * 32, AUART_LINECTRL_BAUD_DIV_MAX); + baud_max = u->uartclk * 32 / AUART_LINECTRL_BAUD_DIV_MIN; + baud = uart_get_baud_rate(u, termios, old, baud_min, baud_max); div = u->uartclk * 32 / baud; ctrl |= AUART_LINECTRL_BAUD_DIVFRAC(div & 0x3F); ctrl |= AUART_LINECTRL_BAUD_DIVINT(div >> 6); @@ -842,7 +846,7 @@ static irqreturn_t mxs_auart_irq_handle(int irq, void *context) return IRQ_HANDLED; } -static void mxs_auart_reset(struct uart_port *u) +static void mxs_auart_reset_deassert(struct uart_port *u) { int i; unsigned int reg; @@ -858,6 +862,30 @@ static void mxs_auart_reset(struct uart_port *u) writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR); } +static void mxs_auart_reset_assert(struct uart_port *u) +{ + int i; + u32 reg; + + reg = readl(u->membase + AUART_CTRL0); + /* if already in reset state, keep it untouched */ + if (reg & AUART_CTRL0_SFTRST) + return; + + writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR); + writel(AUART_CTRL0_SFTRST, u->membase + AUART_CTRL0_SET); + + for (i = 0; i < 1000; i++) { + reg = readl(u->membase + AUART_CTRL0); + /* reset is finished when the clock is gated */ + if (reg & AUART_CTRL0_CLKGATE) + return; + udelay(10); + } + + dev_err(u->dev, "Failed to reset the unit."); +} + static int mxs_auart_startup(struct uart_port *u) { int ret; @@ -867,7 +895,13 @@ static int mxs_auart_startup(struct uart_port *u) if (ret) return ret; - writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR); + if (uart_console(u)) { + writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR); + } else { + /* reset the unit to a well known state */ + mxs_auart_reset_assert(u); + mxs_auart_reset_deassert(u); + } writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_SET); @@ -899,12 +933,14 @@ static void mxs_auart_shutdown(struct uart_port *u) if (auart_dma_enabled(s)) mxs_auart_dma_exit(s); - writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_CLR); - - writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN, - u->membase + AUART_INTR_CLR); - - writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_SET); + if (uart_console(u)) { + writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_CLR); + writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN, + u->membase + AUART_INTR_CLR); + writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_SET); + } else { + mxs_auart_reset_assert(u); + } clk_disable_unprepare(s->clk); } @@ -1160,7 +1196,7 @@ static int mxs_auart_init_gpios(struct mxs_auart_port *s, struct device *dev) enum mctrl_gpio_idx i; struct gpio_desc *gpiod; - s->gpios = mctrl_gpio_init(dev, 0); + s->gpios = mctrl_gpio_init_noauto(dev, 0); if (IS_ERR(s->gpios)) return PTR_ERR(s->gpios); @@ -1291,7 +1327,7 @@ static int mxs_auart_probe(struct platform_device *pdev) auart_port[s->port.line] = s; - mxs_auart_reset(&s->port); + mxs_auart_reset_deassert(&s->port); ret = uart_add_one_port(&auart_driver, &s->port); if (ret) |