dm: imx: serial: Support driver model in the MXC serial driver

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@chromium.org>
This commit is contained in:
Simon Glass 2014-10-01 19:57:27 -06:00
parent 441d0cfff1
commit a8ba569cba
2 changed files with 159 additions and 25 deletions

View file

@ -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

14
include/serial_mxc.h Normal file
View file

@ -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