]>
Commit | Line | Data |
---|---|---|
c609719b | 1 | /* |
237ce0fe MV |
2 | * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> |
3 | * | |
c609719b WD |
4 | * (C) Copyright 2002 |
5 | * Wolfgang Denk, DENX Software Engineering, <wd@denx.de> | |
6 | * | |
7 | * (C) Copyright 2002 | |
8 | * Sysgo Real-Time Solutions, GmbH <www.elinos.com> | |
9 | * Marius Groeger <mgroeger@sysgo.de> | |
10 | * | |
11 | * (C) Copyright 2002 | |
12 | * Sysgo Real-Time Solutions, GmbH <www.elinos.com> | |
13 | * Alex Zuepke <azu@sysgo.de> | |
14 | * | |
15 | * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) | |
16 | * | |
1a459660 | 17 | * SPDX-License-Identifier: GPL-2.0+ |
c609719b WD |
18 | */ |
19 | ||
20 | #include <common.h> | |
21 | #include <asm/arch/pxa-regs.h> | |
237ce0fe | 22 | #include <asm/arch/regs-uart.h> |
3ba8bf7c | 23 | #include <asm/io.h> |
407e6a28 | 24 | #include <linux/compiler.h> |
8648b235 MZ |
25 | #include <serial.h> |
26 | #include <watchdog.h> | |
c609719b | 27 | |
d87080b7 WD |
28 | DECLARE_GLOBAL_DATA_PTR; |
29 | ||
237ce0fe MV |
30 | /* |
31 | * The numbering scheme differs here for PXA25x, PXA27x and PXA3xx so we can | |
32 | * easily handle enabling of clock. | |
33 | */ | |
34 | #ifdef CONFIG_CPU_MONAHANS | |
35 | #define UART_CLK_BASE CKENA_21_BTUART | |
36 | #define UART_CLK_REG CKENA | |
37 | #define BTUART_INDEX 0 | |
38 | #define FFUART_INDEX 1 | |
39 | #define STUART_INDEX 2 | |
abc20aba | 40 | #elif CONFIG_CPU_PXA25X |
237ce0fe MV |
41 | #define UART_CLK_BASE (1 << 4) /* HWUART */ |
42 | #define UART_CLK_REG CKEN | |
43 | #define HWUART_INDEX 0 | |
44 | #define STUART_INDEX 1 | |
45 | #define FFUART_INDEX 2 | |
46 | #define BTUART_INDEX 3 | |
47 | #else /* PXA27x */ | |
48 | #define UART_CLK_BASE CKEN5_STUART | |
49 | #define UART_CLK_REG CKEN | |
50 | #define STUART_INDEX 0 | |
51 | #define FFUART_INDEX 1 | |
52 | #define BTUART_INDEX 2 | |
53 | #endif | |
54 | ||
55 | /* | |
56 | * Only PXA250 has HWUART, to avoid poluting the code with more macros, | |
57 | * artificially introduce this. | |
58 | */ | |
abc20aba | 59 | #ifndef CONFIG_CPU_PXA25X |
237ce0fe MV |
60 | #define HWUART_INDEX 0xff |
61 | #endif | |
80172c61 | 62 | |
4808f106 | 63 | static uint32_t pxa_uart_get_baud_divider(void) |
c609719b | 64 | { |
c609719b | 65 | if (gd->baudrate == 1200) |
237ce0fe | 66 | return 768; |
c609719b | 67 | else if (gd->baudrate == 9600) |
237ce0fe | 68 | return 96; |
c609719b | 69 | else if (gd->baudrate == 19200) |
237ce0fe | 70 | return 48; |
c609719b | 71 | else if (gd->baudrate == 38400) |
237ce0fe | 72 | return 24; |
c609719b | 73 | else if (gd->baudrate == 57600) |
237ce0fe | 74 | return 16; |
c609719b | 75 | else if (gd->baudrate == 115200) |
237ce0fe MV |
76 | return 8; |
77 | else /* Unsupported baudrate */ | |
78 | return 0; | |
79 | } | |
c609719b | 80 | |
4808f106 | 81 | static struct pxa_uart_regs *pxa_uart_index_to_regs(uint32_t uart_index) |
237ce0fe | 82 | { |
80172c61 | 83 | switch (uart_index) { |
237ce0fe MV |
84 | case FFUART_INDEX: return (struct pxa_uart_regs *)FFUART_BASE; |
85 | case BTUART_INDEX: return (struct pxa_uart_regs *)BTUART_BASE; | |
86 | case STUART_INDEX: return (struct pxa_uart_regs *)STUART_BASE; | |
87 | case HWUART_INDEX: return (struct pxa_uart_regs *)HWUART_BASE; | |
88 | default: | |
89 | return NULL; | |
90 | } | |
91 | } | |
c609719b | 92 | |
4808f106 | 93 | static void pxa_uart_toggle_clock(uint32_t uart_index, int enable) |
237ce0fe MV |
94 | { |
95 | uint32_t clk_reg, clk_offset, reg; | |
c609719b | 96 | |
237ce0fe MV |
97 | clk_reg = UART_CLK_REG; |
98 | clk_offset = UART_CLK_BASE << uart_index; | |
c609719b | 99 | |
237ce0fe | 100 | reg = readl(clk_reg); |
3e38691e | 101 | |
237ce0fe MV |
102 | if (enable) |
103 | reg |= clk_offset; | |
104 | else | |
105 | reg &= ~clk_offset; | |
3e38691e | 106 | |
237ce0fe MV |
107 | writel(reg, clk_reg); |
108 | } | |
3e38691e | 109 | |
237ce0fe MV |
110 | /* |
111 | * Enable clock and set baud rate, parity etc. | |
112 | */ | |
113 | void pxa_setbrg_dev(uint32_t uart_index) | |
114 | { | |
115 | uint32_t divider = 0; | |
116 | struct pxa_uart_regs *uart_regs; | |
3e38691e | 117 | |
237ce0fe MV |
118 | divider = pxa_uart_get_baud_divider(); |
119 | if (!divider) | |
120 | hang(); | |
80172c61 | 121 | |
237ce0fe MV |
122 | uart_regs = pxa_uart_index_to_regs(uart_index); |
123 | if (!uart_regs) | |
124 | hang(); | |
5f535fe1 | 125 | |
237ce0fe | 126 | pxa_uart_toggle_clock(uart_index, 1); |
5f535fe1 | 127 | |
237ce0fe MV |
128 | /* Disable interrupts and FIFOs */ |
129 | writel(0, &uart_regs->ier); | |
130 | writel(0, &uart_regs->fcr); | |
5f535fe1 | 131 | |
237ce0fe MV |
132 | /* Set baud rate */ |
133 | writel(LCR_WLS0 | LCR_WLS1 | LCR_DLAB, &uart_regs->lcr); | |
134 | writel(divider & 0xff, &uart_regs->dll); | |
135 | writel(divider >> 8, &uart_regs->dlh); | |
136 | writel(LCR_WLS0 | LCR_WLS1, &uart_regs->lcr); | |
5f535fe1 | 137 | |
237ce0fe MV |
138 | /* Enable UART */ |
139 | writel(IER_UUE, &uart_regs->ier); | |
c609719b WD |
140 | } |
141 | ||
c609719b WD |
142 | /* |
143 | * Initialise the serial port with the given baudrate. The settings | |
144 | * are always 8 data bits, no parity, 1 stop bit, no start bits. | |
c609719b | 145 | */ |
237ce0fe | 146 | int pxa_init_dev(unsigned int uart_index) |
c609719b | 147 | { |
80172c61 | 148 | pxa_setbrg_dev (uart_index); |
237ce0fe | 149 | return 0; |
c609719b WD |
150 | } |
151 | ||
c609719b WD |
152 | /* |
153 | * Output a single byte to the serial port. | |
154 | */ | |
237ce0fe | 155 | void pxa_putc_dev(unsigned int uart_index, const char c) |
80172c61 | 156 | { |
237ce0fe MV |
157 | struct pxa_uart_regs *uart_regs; |
158 | ||
055457ef AW |
159 | /* If \n, also do \r */ |
160 | if (c == '\n') | |
161 | pxa_putc_dev(uart_index, '\r'); | |
162 | ||
237ce0fe MV |
163 | uart_regs = pxa_uart_index_to_regs(uart_index); |
164 | if (!uart_regs) | |
165 | hang(); | |
166 | ||
167 | while (!(readl(&uart_regs->lsr) & LSR_TEMT)) | |
168 | WATCHDOG_RESET(); | |
169 | writel(c, &uart_regs->thr); | |
c609719b WD |
170 | } |
171 | ||
172 | /* | |
173 | * Read a single byte from the serial port. Returns 1 on success, 0 | |
174 | * otherwise. When the function is succesfull, the character read is | |
175 | * written into its argument c. | |
176 | */ | |
237ce0fe | 177 | int pxa_tstc_dev(unsigned int uart_index) |
80172c61 | 178 | { |
237ce0fe MV |
179 | struct pxa_uart_regs *uart_regs; |
180 | ||
181 | uart_regs = pxa_uart_index_to_regs(uart_index); | |
182 | if (!uart_regs) | |
183 | return -1; | |
184 | ||
185 | return readl(&uart_regs->lsr) & LSR_DR; | |
c609719b WD |
186 | } |
187 | ||
188 | /* | |
189 | * Read a single byte from the serial port. Returns 1 on success, 0 | |
190 | * otherwise. When the function is succesfull, the character read is | |
191 | * written into its argument c. | |
192 | */ | |
237ce0fe | 193 | int pxa_getc_dev(unsigned int uart_index) |
80172c61 | 194 | { |
237ce0fe | 195 | struct pxa_uart_regs *uart_regs; |
c609719b | 196 | |
237ce0fe MV |
197 | uart_regs = pxa_uart_index_to_regs(uart_index); |
198 | if (!uart_regs) | |
199 | return -1; | |
80172c61 | 200 | |
237ce0fe MV |
201 | while (!(readl(&uart_regs->lsr) & LSR_DR)) |
202 | WATCHDOG_RESET(); | |
203 | return readl(&uart_regs->rbr) & 0xff; | |
80172c61 SB |
204 | } |
205 | ||
237ce0fe | 206 | void pxa_puts_dev(unsigned int uart_index, const char *s) |
80172c61 | 207 | { |
237ce0fe MV |
208 | while (*s) |
209 | pxa_putc_dev(uart_index, *s++); | |
80172c61 SB |
210 | } |
211 | ||
237ce0fe MV |
212 | #define pxa_uart(uart, UART) \ |
213 | int uart##_init(void) \ | |
214 | { \ | |
215 | return pxa_init_dev(UART##_INDEX); \ | |
216 | } \ | |
217 | \ | |
218 | void uart##_setbrg(void) \ | |
219 | { \ | |
220 | return pxa_setbrg_dev(UART##_INDEX); \ | |
221 | } \ | |
222 | \ | |
223 | void uart##_putc(const char c) \ | |
224 | { \ | |
225 | return pxa_putc_dev(UART##_INDEX, c); \ | |
226 | } \ | |
227 | \ | |
228 | void uart##_puts(const char *s) \ | |
229 | { \ | |
230 | return pxa_puts_dev(UART##_INDEX, s); \ | |
231 | } \ | |
232 | \ | |
233 | int uart##_getc(void) \ | |
234 | { \ | |
235 | return pxa_getc_dev(UART##_INDEX); \ | |
236 | } \ | |
237 | \ | |
238 | int uart##_tstc(void) \ | |
239 | { \ | |
240 | return pxa_tstc_dev(UART##_INDEX); \ | |
241 | } \ | |
242 | ||
243 | #define pxa_uart_desc(uart) \ | |
244 | struct serial_device serial_##uart##_device = \ | |
245 | { \ | |
90bad891 MV |
246 | .name = "serial_"#uart, \ |
247 | .start = uart##_init, \ | |
248 | .stop = NULL, \ | |
249 | .setbrg = uart##_setbrg, \ | |
250 | .getc = uart##_getc, \ | |
251 | .tstc = uart##_tstc, \ | |
252 | .putc = uart##_putc, \ | |
253 | .puts = uart##_puts, \ | |
237ce0fe MV |
254 | }; |
255 | ||
256 | #define pxa_uart_multi(uart, UART) \ | |
257 | pxa_uart(uart, UART) \ | |
258 | pxa_uart_desc(uart) | |
259 | ||
260 | #if defined(CONFIG_HWUART) | |
261 | pxa_uart_multi(hwuart, HWUART) | |
80172c61 | 262 | #endif |
237ce0fe MV |
263 | #if defined(CONFIG_STUART) |
264 | pxa_uart_multi(stuart, STUART) | |
80172c61 | 265 | #endif |
237ce0fe MV |
266 | #if defined(CONFIG_FFUART) |
267 | pxa_uart_multi(ffuart, FFUART) | |
268 | #endif | |
269 | #if defined(CONFIG_BTUART) | |
270 | pxa_uart_multi(btuart, BTUART) | |
80172c61 SB |
271 | #endif |
272 | ||
407e6a28 MV |
273 | __weak struct serial_device *default_serial_console(void) |
274 | { | |
275 | #if CONFIG_CONS_INDEX == 1 | |
276 | return &serial_hwuart_device; | |
277 | #elif CONFIG_CONS_INDEX == 2 | |
278 | return &serial_stuart_device; | |
279 | #elif CONFIG_CONS_INDEX == 3 | |
280 | return &serial_ffuart_device; | |
281 | #elif CONFIG_CONS_INDEX == 4 | |
282 | return &serial_btuart_device; | |
283 | #else | |
284 | #error "Bad CONFIG_CONS_INDEX." | |
285 | #endif | |
286 | } | |
1fe5c110 MV |
287 | |
288 | void pxa_serial_initialize(void) | |
289 | { | |
290 | #if defined(CONFIG_FFUART) | |
291 | serial_register(&serial_ffuart_device); | |
292 | #endif | |
293 | #if defined(CONFIG_BTUART) | |
294 | serial_register(&serial_btuart_device); | |
295 | #endif | |
296 | #if defined(CONFIG_STUART) | |
297 | serial_register(&serial_stuart_device); | |
298 | #endif | |
299 | } |