[U-Boot] [PATCH 09/10] dm: imx: serial: Support driver model in the MXC serial driver

Simon Glass sjg at chromium.org
Mon Sep 15 14:57:44 CEST 2014


Add driver model support with this driver. Boards which use this driver
should define platform data in their board files.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

 drivers/serial/serial_mxc.c | 170 +++++++++++++++++++++++++++++++++++++-------
 include/serial_mxc.h        |  14 ++++
 2 files changed, 159 insertions(+), 25 deletions(-)
 create mode 100644 include/serial_mxc.h

diff --git a/drivers/serial/serial_mxc.c b/drivers/serial/serial_mxc.c
index 313d560..9ce24f9 100644
--- a/drivers/serial/serial_mxc.c
+++ b/drivers/serial/serial_mxc.c
@@ -5,37 +5,15 @@
  */
 
 #include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <serial_mxc.h>
 #include <watchdog.h>
 #include <asm/arch/imx-regs.h>
 #include <asm/arch/clock.h>
 #include <serial.h>
 #include <linux/compiler.h>
 
-#define __REG(x)     (*((volatile u32 *)(x)))
-
-#ifndef CONFIG_MXC_UART_BASE
-#error "define CONFIG_MXC_UART_BASE to use the MXC UART driver"
-#endif
-
-#define UART_PHYS	CONFIG_MXC_UART_BASE
-
-/* Register definitions */
-#define URXD  0x0  /* Receiver Register */
-#define UTXD  0x40 /* Transmitter Register */
-#define UCR1  0x80 /* Control Register 1 */
-#define UCR2  0x84 /* Control Register 2 */
-#define UCR3  0x88 /* Control Register 3 */
-#define UCR4  0x8c /* Control Register 4 */
-#define UFCR  0x90 /* FIFO Control Register */
-#define USR1  0x94 /* Status Register 1 */
-#define USR2  0x98 /* Status Register 2 */
-#define UESC  0x9c /* Escape Character Register */
-#define UTIM  0xa0 /* Escape Timer Register */
-#define UBIR  0xa4 /* BRM Incremental Register */
-#define UBMR  0xa8 /* BRM Modulator Register */
-#define UBRC  0xac /* Baud Rate Count Register */
-#define UTS   0xb4 /* UART Test Register (mx31) */
-
 /* UART Control Register Bit Fields.*/
 #define  URXD_CHARRDY    (1<<15)
 #define  URXD_ERR        (1<<14)
@@ -128,6 +106,33 @@
 #define  UTS_RXFULL	 (1<<3)	 /* RxFIFO full */
 #define  UTS_SOFTRST	 (1<<0)	 /* Software reset */
 
+#ifndef CONFIG_DM_SERIAL
+
+#ifndef CONFIG_MXC_UART_BASE
+#error "define CONFIG_MXC_UART_BASE to use the MXC UART driver"
+#endif
+
+#define UART_PHYS	CONFIG_MXC_UART_BASE
+
+#define __REG(x)     (*((volatile u32 *)(x)))
+
+/* Register definitions */
+#define URXD  0x0  /* Receiver Register */
+#define UTXD  0x40 /* Transmitter Register */
+#define UCR1  0x80 /* Control Register 1 */
+#define UCR2  0x84 /* Control Register 2 */
+#define UCR3  0x88 /* Control Register 3 */
+#define UCR4  0x8c /* Control Register 4 */
+#define UFCR  0x90 /* FIFO Control Register */
+#define USR1  0x94 /* Status Register 1 */
+#define USR2  0x98 /* Status Register 2 */
+#define UESC  0x9c /* Escape Character Register */
+#define UTIM  0xa0 /* Escape Timer Register */
+#define UBIR  0xa4 /* BRM Incremental Register */
+#define UBMR  0xa8 /* BRM Modulator Register */
+#define UBRC  0xac /* Baud Rate Count Register */
+#define UTS   0xb4 /* UART Test Register (mx31) */
+
 DECLARE_GLOBAL_DATA_PTR;
 
 static void mxc_serial_setbrg(void)
@@ -222,3 +227,118 @@ __weak struct serial_device *default_serial_console(void)
 {
 	return &mxc_serial_drv;
 }
+#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
diff --git a/include/serial_mxc.h b/include/serial_mxc.h
new file mode 100644
index 0000000..7d3ace2
--- /dev/null
+++ b/include/serial_mxc.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __serial_mxc_h
+#define __serial_mxc_h
+
+/* Information about a serial port */
+struct mxc_serial_platdata {
+	struct mxc_uart *reg;  /* address of registers in physical memory */
+};
+
+#endif
-- 
2.1.0.rc2.206.gedb03e5



More information about the U-Boot mailing list