]>
Commit | Line | Data |
---|---|---|
f93ae788 WD |
1 | /* |
2 | * Copyright (C) 2004-2006 Atmel Corporation | |
3 | * | |
125637c5 AB |
4 | * Modified to support C structur SoC access by |
5 | * Andreas Bießmann <[email protected]> | |
6 | * | |
1a459660 | 7 | * SPDX-License-Identifier: GPL-2.0+ |
f93ae788 WD |
8 | */ |
9 | #include <common.h> | |
843a2654 | 10 | #include <watchdog.h> |
cfba4573 MV |
11 | #include <serial.h> |
12 | #include <linux/compiler.h> | |
f93ae788 | 13 | |
f93ae788 | 14 | #include <asm/io.h> |
df548d3c | 15 | #include <asm/arch/clk.h> |
329f0f52 | 16 | #include <asm/arch/hardware.h> |
f93ae788 WD |
17 | |
18 | #include "atmel_usart.h" | |
19 | ||
20 | DECLARE_GLOBAL_DATA_PTR; | |
21 | ||
cfba4573 | 22 | static void atmel_serial_setbrg(void) |
f93ae788 | 23 | { |
329f0f52 | 24 | atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE; |
f93ae788 WD |
25 | unsigned long divisor; |
26 | unsigned long usart_hz; | |
27 | ||
28 | /* | |
29 | * Master Clock | |
30 | * Baud Rate = -------------- | |
31 | * 16 * CD | |
32 | */ | |
329f0f52 | 33 | usart_hz = get_usart_clk_rate(CONFIG_USART_ID); |
f93ae788 | 34 | divisor = (usart_hz / 16 + gd->baudrate / 2) / gd->baudrate; |
125637c5 | 35 | writel(USART3_BF(CD, divisor), &usart->brgr); |
f93ae788 WD |
36 | } |
37 | ||
cfba4573 | 38 | static int atmel_serial_init(void) |
f93ae788 | 39 | { |
329f0f52 | 40 | atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE; |
125637c5 | 41 | |
1f4faedd XH |
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 | ||
125637c5 | 49 | writel(USART3_BIT(RSTRX) | USART3_BIT(RSTTX), &usart->cr); |
f93ae788 WD |
50 | |
51 | serial_setbrg(); | |
52 | ||
125637c5 | 53 | writel((USART3_BF(USART_MODE, USART3_USART_MODE_NORMAL) |
df548d3c HS |
54 | | USART3_BF(USCLKS, USART3_USCLKS_MCK) |
55 | | USART3_BF(CHRL, USART3_CHRL_8) | |
56 | | USART3_BF(PAR, USART3_PAR_NONE) | |
125637c5 AB |
57 | | USART3_BF(NBSTOP, USART3_NBSTOP_1)), |
58 | &usart->mr); | |
1f4faedd XH |
59 | writel(USART3_BIT(RXEN) | USART3_BIT(TXEN), &usart->cr); |
60 | /* 100us is enough for the new settings to be settled */ | |
61 | __udelay(100); | |
f93ae788 WD |
62 | |
63 | return 0; | |
64 | } | |
65 | ||
cfba4573 | 66 | static void atmel_serial_putc(char c) |
f93ae788 | 67 | { |
329f0f52 | 68 | atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE; |
125637c5 | 69 | |
f93ae788 WD |
70 | if (c == '\n') |
71 | serial_putc('\r'); | |
72 | ||
125637c5 AB |
73 | while (!(readl(&usart->csr) & USART3_BIT(TXRDY))); |
74 | writel(c, &usart->thr); | |
f93ae788 WD |
75 | } |
76 | ||
cfba4573 | 77 | static int atmel_serial_getc(void) |
f93ae788 | 78 | { |
329f0f52 | 79 | atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE; |
125637c5 AB |
80 | |
81 | while (!(readl(&usart->csr) & USART3_BIT(RXRDY))) | |
843a2654 | 82 | WATCHDOG_RESET(); |
125637c5 | 83 | return readl(&usart->rhr); |
f93ae788 WD |
84 | } |
85 | ||
cfba4573 | 86 | static int atmel_serial_tstc(void) |
f93ae788 | 87 | { |
329f0f52 | 88 | atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE; |
125637c5 | 89 | return (readl(&usart->csr) & USART3_BIT(RXRDY)) != 0; |
f93ae788 | 90 | } |
cfba4573 | 91 | |
cfba4573 MV |
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, | |
ec3fd689 | 98 | .puts = default_serial_puts, |
cfba4573 MV |
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 | } |