diff options
Diffstat (limited to 'u-boot/drivers/serial/atmel_usart.c')
-rw-r--r-- | u-boot/drivers/serial/atmel_usart.c | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/u-boot/drivers/serial/atmel_usart.c b/u-boot/drivers/serial/atmel_usart.c new file mode 100644 index 0000000..bfa1f3a --- /dev/null +++ b/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> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <common.h> +#include <watchdog.h> + +#include <asm/io.h> +#include <asm/arch/clk.h> +#include <asm/arch/memory-map.h> + +#if defined(CONFIG_USART0) +# define USART_ID 0 +# define USART_BASE USART0_BASE +#elif defined(CONFIG_USART1) +# define USART_ID 1 +# define USART_BASE USART1_BASE +#elif defined(CONFIG_USART2) +# define USART_ID 2 +# define USART_BASE USART2_BASE +#elif defined(CONFIG_USART3) +# define USART_ID 3 +# define USART_BASE USART3_BASE +#endif + +#include "atmel_usart.h" + +DECLARE_GLOBAL_DATA_PTR; + +void serial_setbrg(void) +{ + atmel_usart3_t *usart = (atmel_usart3_t*)USART_BASE; + unsigned long divisor; + unsigned long usart_hz; + + /* + * Master Clock + * Baud Rate = -------------- + * 16 * CD + */ + usart_hz = get_usart_clk_rate(USART_ID); + divisor = (usart_hz / 16 + gd->baudrate / 2) / gd->baudrate; + writel(USART3_BF(CD, divisor), &usart->brgr); +} + +int serial_init(void) +{ + atmel_usart3_t *usart = (atmel_usart3_t*)USART_BASE; + + writel(USART3_BIT(RSTRX) | USART3_BIT(RSTTX), &usart->cr); + + serial_setbrg(); + + writel(USART3_BIT(RXEN) | USART3_BIT(TXEN), &usart->cr); + 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); + + return 0; +} + +void serial_putc(char c) +{ + atmel_usart3_t *usart = (atmel_usart3_t*)USART_BASE; + + if (c == '\n') + serial_putc('\r'); + + while (!(readl(&usart->csr) & USART3_BIT(TXRDY))); + writel(c, &usart->thr); +} + +void serial_puts(const char *s) +{ + while (*s) + serial_putc(*s++); +} + +int serial_getc(void) +{ + atmel_usart3_t *usart = (atmel_usart3_t*)USART_BASE; + + while (!(readl(&usart->csr) & USART3_BIT(RXRDY))) + WATCHDOG_RESET(); + return readl(&usart->rhr); +} + +int serial_tstc(void) +{ + atmel_usart3_t *usart = (atmel_usart3_t*)USART_BASE; + return (readl(&usart->csr) & USART3_BIT(RXRDY)) != 0; +} |