diff options
author | 2015-08-28 09:58:54 +0800 | |
---|---|---|
committer | 2015-09-01 12:44:00 +0800 | |
commit | e44e3482bdb4d0ebde2d8b41830ac2cdb07948fb (patch) | |
tree | 66b09f592c55df2878107a468a91d21506104d3f /qemu/roms/u-boot/drivers/serial/atmel_usart.c | |
parent | 9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00 (diff) |
Add qemu 2.4.0
Change-Id: Ic99cbad4b61f8b127b7dc74d04576c0bcbaaf4f5
Signed-off-by: Yang Zhang <yang.z.zhang@intel.com>
Diffstat (limited to 'qemu/roms/u-boot/drivers/serial/atmel_usart.c')
-rw-r--r-- | qemu/roms/u-boot/drivers/serial/atmel_usart.c | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/qemu/roms/u-boot/drivers/serial/atmel_usart.c b/qemu/roms/u-boot/drivers/serial/atmel_usart.c new file mode 100644 index 000000000..8f0e3489a --- /dev/null +++ b/qemu/roms/u-boot/drivers/serial/atmel_usart.c @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2004-2006 Atmel Corporation + * + * Modified to support C structur SoC access by + * Andreas Bießmann <biessmann@corscience.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <watchdog.h> +#include <serial.h> +#include <linux/compiler.h> + +#include <asm/io.h> +#include <asm/arch/clk.h> +#include <asm/arch/hardware.h> + +#include "atmel_usart.h" + +DECLARE_GLOBAL_DATA_PTR; + +static void atmel_serial_setbrg(void) +{ + atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE; + unsigned long divisor; + unsigned long usart_hz; + + /* + * Master Clock + * Baud Rate = -------------- + * 16 * CD + */ + usart_hz = get_usart_clk_rate(CONFIG_USART_ID); + divisor = (usart_hz / 16 + gd->baudrate / 2) / gd->baudrate; + writel(USART3_BF(CD, divisor), &usart->brgr); +} + +static int atmel_serial_init(void) +{ + atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE; + + /* + * Just in case: drain transmitter register + * 1000us is enough for baudrate >= 9600 + */ + if (!(readl(&usart->csr) & USART3_BIT(TXEMPTY))) + __udelay(1000); + + writel(USART3_BIT(RSTRX) | USART3_BIT(RSTTX), &usart->cr); + + serial_setbrg(); + + writel((USART3_BF(USART_MODE, USART3_USART_MODE_NORMAL) + | USART3_BF(USCLKS, USART3_USCLKS_MCK) + | USART3_BF(CHRL, USART3_CHRL_8) + | USART3_BF(PAR, USART3_PAR_NONE) + | USART3_BF(NBSTOP, USART3_NBSTOP_1)), + &usart->mr); + writel(USART3_BIT(RXEN) | USART3_BIT(TXEN), &usart->cr); + /* 100us is enough for the new settings to be settled */ + __udelay(100); + + return 0; +} + +static void atmel_serial_putc(char c) +{ + atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE; + + if (c == '\n') + serial_putc('\r'); + + while (!(readl(&usart->csr) & USART3_BIT(TXRDY))); + writel(c, &usart->thr); +} + +static int atmel_serial_getc(void) +{ + atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE; + + while (!(readl(&usart->csr) & USART3_BIT(RXRDY))) + WATCHDOG_RESET(); + return readl(&usart->rhr); +} + +static int atmel_serial_tstc(void) +{ + atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE; + return (readl(&usart->csr) & USART3_BIT(RXRDY)) != 0; +} + +static struct serial_device atmel_serial_drv = { + .name = "atmel_serial", + .start = atmel_serial_init, + .stop = NULL, + .setbrg = atmel_serial_setbrg, + .putc = atmel_serial_putc, + .puts = default_serial_puts, + .getc = atmel_serial_getc, + .tstc = atmel_serial_tstc, +}; + +void atmel_serial_initialize(void) +{ + serial_register(&atmel_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ + return &atmel_serial_drv; +} |