+#endif
+
+#ifdef CONFIG_DM_SERIAL
+
+struct mxc_uart {
+ u32 rxd;
+ u32 spare0[15];
+
+ u32 txd;
+ u32 spare1[15];
+
+ u32 cr1;
+ u32 cr2;
+ u32 cr3;
+ u32 cr4;
+
+ u32 fcr;
+ u32 sr1;
+ u32 sr2;
+ u32 esc;
+
+ u32 tim;
+ u32 bir;
+ u32 bmr;
+ u32 brc;
+
+ u32 onems;
+ u32 ts;
+};
+
+int mxc_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ struct mxc_serial_platdata *plat = dev->platdata;
+ struct mxc_uart *const uart = plat->reg;
+ u32 clk = imx_get_uartclk();
+
+ writel(4 << 7, &uart->fcr); /* divide input clock by 2 */
+ writel(0xf, &uart->bir);
+ writel(clk / (2 * baudrate), &uart->bmr);
+
+ writel(UCR2_WS | UCR2_IRTS | UCR2_RXEN | UCR2_TXEN | UCR2_SRST,
+ &uart->cr2);
+ writel(UCR1_UARTEN, &uart->cr1);
+
+ return 0;
+}
+
+static int mxc_serial_probe(struct udevice *dev)
+{
+ struct mxc_serial_platdata *plat = dev->platdata;
+ struct mxc_uart *const uart = plat->reg;
+
+ writel(0, &uart->cr1);
+ writel(0, &uart->cr2);
+ while (!(readl(&uart->cr2) & UCR2_SRST));
+ writel(0x704 | UCR3_ADNIMP, &uart->cr3);
+ writel(0x8000, &uart->cr4);
+ writel(0x2b, &uart->esc);
+ writel(0, &uart->tim);
+ writel(0, &uart->ts);
+
+ return 0;
+}
+
+static int mxc_serial_getc(struct udevice *dev)
+{
+ struct mxc_serial_platdata *plat = dev->platdata;
+ struct mxc_uart *const uart = plat->reg;
+
+ if (readl(&uart->ts) & UTS_RXEMPTY)
+ return -EAGAIN;
+
+ return readl(&uart->rxd) & URXD_RX_DATA;
+}
+
+static int mxc_serial_putc(struct udevice *dev, const char ch)
+{
+ struct mxc_serial_platdata *plat = dev->platdata;
+ struct mxc_uart *const uart = plat->reg;
+
+ if (!(readl(&uart->ts) & UTS_TXEMPTY))
+ return -EAGAIN;
+
+ writel(ch, &uart->txd);
+
+ return 0;
+}
+
+static int mxc_serial_pending(struct udevice *dev, bool input)
+{
+ struct mxc_serial_platdata *plat = dev->platdata;
+ struct mxc_uart *const uart = plat->reg;
+ uint32_t sr2 = readl(&uart->sr2);
+
+ if (input)
+ return sr2 & USR2_RDR ? 1 : 0;
+ else
+ return sr2 & USR2_TXDC ? 0 : 1;
+}
+
+static const struct dm_serial_ops mxc_serial_ops = {
+ .putc = mxc_serial_putc,
+ .pending = mxc_serial_pending,
+ .getc = mxc_serial_getc,
+ .setbrg = mxc_serial_setbrg,
+};
+
+U_BOOT_DRIVER(serial_mxc) = {
+ .name = "serial_mxc",
+ .id = UCLASS_SERIAL,
+ .probe = mxc_serial_probe,
+ .ops = &mxc_serial_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
+#endif