]> git.sur5r.net Git - u-boot/blob - drivers/serial/atmel_usart.c
Merge branch 'iu-boot/master' into 'u-boot-arm/master'
[u-boot] / drivers / serial / atmel_usart.c
1 /*
2  * Copyright (C) 2004-2006 Atmel Corporation
3  *
4  * Modified to support C structur SoC access by
5  * Andreas Bießmann <biessmann@corscience.de>
6  *
7  * SPDX-License-Identifier:     GPL-2.0+
8  */
9 #include <common.h>
10 #include <watchdog.h>
11 #include <serial.h>
12 #include <linux/compiler.h>
13
14 #include <asm/io.h>
15 #include <asm/arch/clk.h>
16 #include <asm/arch/hardware.h>
17
18 #include "atmel_usart.h"
19
20 DECLARE_GLOBAL_DATA_PTR;
21
22 static void atmel_serial_setbrg(void)
23 {
24         atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE;
25         unsigned long divisor;
26         unsigned long usart_hz;
27
28         /*
29          *              Master Clock
30          * Baud Rate = --------------
31          *                16 * CD
32          */
33         usart_hz = get_usart_clk_rate(CONFIG_USART_ID);
34         divisor = (usart_hz / 16 + gd->baudrate / 2) / gd->baudrate;
35         writel(USART3_BF(CD, divisor), &usart->brgr);
36 }
37
38 static int atmel_serial_init(void)
39 {
40         atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE;
41
42         /*
43          * Just in case: drain transmitter register
44          * 1000us is enough for baudrate >= 9600
45          */
46         if (!(readl(&usart->csr) & USART3_BIT(TXEMPTY)))
47                 __udelay(1000);
48
49         writel(USART3_BIT(RSTRX) | USART3_BIT(RSTTX), &usart->cr);
50
51         serial_setbrg();
52
53         writel((USART3_BF(USART_MODE, USART3_USART_MODE_NORMAL)
54                            | USART3_BF(USCLKS, USART3_USCLKS_MCK)
55                            | USART3_BF(CHRL, USART3_CHRL_8)
56                            | USART3_BF(PAR, USART3_PAR_NONE)
57                            | USART3_BF(NBSTOP, USART3_NBSTOP_1)),
58                            &usart->mr);
59         writel(USART3_BIT(RXEN) | USART3_BIT(TXEN), &usart->cr);
60         /* 100us is enough for the new settings to be settled */
61         __udelay(100);
62
63         return 0;
64 }
65
66 static void atmel_serial_putc(char c)
67 {
68         atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE;
69
70         if (c == '\n')
71                 serial_putc('\r');
72
73         while (!(readl(&usart->csr) & USART3_BIT(TXRDY)));
74         writel(c, &usart->thr);
75 }
76
77 static int atmel_serial_getc(void)
78 {
79         atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE;
80
81         while (!(readl(&usart->csr) & USART3_BIT(RXRDY)))
82                  WATCHDOG_RESET();
83         return readl(&usart->rhr);
84 }
85
86 static int atmel_serial_tstc(void)
87 {
88         atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE;
89         return (readl(&usart->csr) & USART3_BIT(RXRDY)) != 0;
90 }
91
92 static struct serial_device atmel_serial_drv = {
93         .name   = "atmel_serial",
94         .start  = atmel_serial_init,
95         .stop   = NULL,
96         .setbrg = atmel_serial_setbrg,
97         .putc   = atmel_serial_putc,
98         .puts   = default_serial_puts,
99         .getc   = atmel_serial_getc,
100         .tstc   = atmel_serial_tstc,
101 };
102
103 void atmel_serial_initialize(void)
104 {
105         serial_register(&atmel_serial_drv);
106 }
107
108 __weak struct serial_device *default_serial_console(void)
109 {
110         return &atmel_serial_drv;
111 }