diff options
Diffstat (limited to 'drivers/serial/serial_mxc.c')
-rw-r--r-- | drivers/serial/serial_mxc.c | 170 |
1 files changed, 145 insertions, 25 deletions
diff --git a/drivers/serial/serial_mxc.c b/drivers/serial/serial_mxc.c index 313d560afce..d6cf1d874a6 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 <watchdog.h> #include <asm/arch/imx-regs.h> #include <asm/arch/clock.h> +#include <dm/platform_data/serial_mxc.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 |