#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)
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 */ }
{
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;
}
/* 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);
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;
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;
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);
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);
}
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);
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)