1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* |
3 | * Actions Semi Owl family serial console |
4 | * |
5 | * Copyright 2013 Actions Semi Inc. |
6 | * Author: Actions Semi, Inc. |
7 | * |
8 | * Copyright (c) 2016-2017 Andreas Färber |
9 | */ |
10 | |
11 | #include <linux/clk.h> |
12 | #include <linux/console.h> |
13 | #include <linux/delay.h> |
14 | #include <linux/io.h> |
15 | #include <linux/iopoll.h> |
16 | #include <linux/module.h> |
17 | #include <linux/of.h> |
18 | #include <linux/platform_device.h> |
19 | #include <linux/serial.h> |
20 | #include <linux/serial_core.h> |
21 | #include <linux/tty.h> |
22 | #include <linux/tty_flip.h> |
23 | |
24 | #define OWL_UART_PORT_NUM 7 |
25 | #define OWL_UART_DEV_NAME "ttyOWL" |
26 | |
27 | #define OWL_UART_CTL 0x000 |
28 | #define OWL_UART_RXDAT 0x004 |
29 | #define OWL_UART_TXDAT 0x008 |
30 | #define OWL_UART_STAT 0x00c |
31 | |
32 | #define OWL_UART_CTL_DWLS_MASK GENMASK(1, 0) |
33 | #define OWL_UART_CTL_DWLS_5BITS (0x0 << 0) |
34 | #define OWL_UART_CTL_DWLS_6BITS (0x1 << 0) |
35 | #define OWL_UART_CTL_DWLS_7BITS (0x2 << 0) |
36 | #define OWL_UART_CTL_DWLS_8BITS (0x3 << 0) |
37 | #define OWL_UART_CTL_STPS_2BITS BIT(2) |
38 | #define OWL_UART_CTL_PRS_MASK GENMASK(6, 4) |
39 | #define OWL_UART_CTL_PRS_NONE (0x0 << 4) |
40 | #define OWL_UART_CTL_PRS_ODD (0x4 << 4) |
41 | #define OWL_UART_CTL_PRS_MARK (0x5 << 4) |
42 | #define OWL_UART_CTL_PRS_EVEN (0x6 << 4) |
43 | #define OWL_UART_CTL_PRS_SPACE (0x7 << 4) |
44 | #define OWL_UART_CTL_AFE BIT(12) |
45 | #define OWL_UART_CTL_TRFS_TX BIT(14) |
46 | #define OWL_UART_CTL_EN BIT(15) |
47 | #define OWL_UART_CTL_RXDE BIT(16) |
48 | #define OWL_UART_CTL_TXDE BIT(17) |
49 | #define OWL_UART_CTL_RXIE BIT(18) |
50 | #define OWL_UART_CTL_TXIE BIT(19) |
51 | #define OWL_UART_CTL_LBEN BIT(20) |
52 | |
53 | #define OWL_UART_STAT_RIP BIT(0) |
54 | #define OWL_UART_STAT_TIP BIT(1) |
55 | #define OWL_UART_STAT_RXER BIT(2) |
56 | #define OWL_UART_STAT_TFER BIT(3) |
57 | #define OWL_UART_STAT_RXST BIT(4) |
58 | #define OWL_UART_STAT_RFEM BIT(5) |
59 | #define OWL_UART_STAT_TFFU BIT(6) |
60 | #define OWL_UART_STAT_CTSS BIT(7) |
61 | #define OWL_UART_STAT_RTSS BIT(8) |
62 | #define OWL_UART_STAT_TFES BIT(10) |
63 | #define OWL_UART_STAT_TRFL_MASK GENMASK(16, 11) |
64 | #define OWL_UART_STAT_UTBB BIT(17) |
65 | |
66 | #define OWL_UART_POLL_USEC 5 |
67 | #define OWL_UART_TIMEOUT_USEC 10000 |
68 | |
69 | static struct uart_driver owl_uart_driver; |
70 | |
71 | struct owl_uart_info { |
72 | unsigned int tx_fifosize; |
73 | }; |
74 | |
75 | struct owl_uart_port { |
76 | struct uart_port port; |
77 | struct clk *clk; |
78 | }; |
79 | |
80 | #define to_owl_uart_port(prt) container_of(prt, struct owl_uart_port, prt) |
81 | |
82 | static struct owl_uart_port *owl_uart_ports[OWL_UART_PORT_NUM]; |
83 | |
84 | static inline void owl_uart_write(struct uart_port *port, u32 val, unsigned int off) |
85 | { |
86 | writel(val, addr: port->membase + off); |
87 | } |
88 | |
89 | static inline u32 owl_uart_read(struct uart_port *port, unsigned int off) |
90 | { |
91 | return readl(addr: port->membase + off); |
92 | } |
93 | |
94 | static void owl_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) |
95 | { |
96 | u32 ctl; |
97 | |
98 | ctl = owl_uart_read(port, OWL_UART_CTL); |
99 | |
100 | if (mctrl & TIOCM_LOOP) |
101 | ctl |= OWL_UART_CTL_LBEN; |
102 | else |
103 | ctl &= ~OWL_UART_CTL_LBEN; |
104 | |
105 | owl_uart_write(port, val: ctl, OWL_UART_CTL); |
106 | } |
107 | |
108 | static unsigned int owl_uart_get_mctrl(struct uart_port *port) |
109 | { |
110 | unsigned int mctrl = TIOCM_CAR | TIOCM_DSR; |
111 | u32 stat, ctl; |
112 | |
113 | ctl = owl_uart_read(port, OWL_UART_CTL); |
114 | stat = owl_uart_read(port, OWL_UART_STAT); |
115 | if (stat & OWL_UART_STAT_RTSS) |
116 | mctrl |= TIOCM_RTS; |
117 | if ((stat & OWL_UART_STAT_CTSS) || !(ctl & OWL_UART_CTL_AFE)) |
118 | mctrl |= TIOCM_CTS; |
119 | return mctrl; |
120 | } |
121 | |
122 | static unsigned int owl_uart_tx_empty(struct uart_port *port) |
123 | { |
124 | unsigned long flags; |
125 | u32 val; |
126 | unsigned int ret; |
127 | |
128 | uart_port_lock_irqsave(up: port, flags: &flags); |
129 | |
130 | val = owl_uart_read(port, OWL_UART_STAT); |
131 | ret = (val & OWL_UART_STAT_TFES) ? TIOCSER_TEMT : 0; |
132 | |
133 | uart_port_unlock_irqrestore(up: port, flags); |
134 | |
135 | return ret; |
136 | } |
137 | |
138 | static void owl_uart_stop_rx(struct uart_port *port) |
139 | { |
140 | u32 val; |
141 | |
142 | val = owl_uart_read(port, OWL_UART_CTL); |
143 | val &= ~(OWL_UART_CTL_RXIE | OWL_UART_CTL_RXDE); |
144 | owl_uart_write(port, val, OWL_UART_CTL); |
145 | |
146 | val = owl_uart_read(port, OWL_UART_STAT); |
147 | val |= OWL_UART_STAT_RIP; |
148 | owl_uart_write(port, val, OWL_UART_STAT); |
149 | } |
150 | |
151 | static void owl_uart_stop_tx(struct uart_port *port) |
152 | { |
153 | u32 val; |
154 | |
155 | val = owl_uart_read(port, OWL_UART_CTL); |
156 | val &= ~(OWL_UART_CTL_TXIE | OWL_UART_CTL_TXDE); |
157 | owl_uart_write(port, val, OWL_UART_CTL); |
158 | |
159 | val = owl_uart_read(port, OWL_UART_STAT); |
160 | val |= OWL_UART_STAT_TIP; |
161 | owl_uart_write(port, val, OWL_UART_STAT); |
162 | } |
163 | |
164 | static void owl_uart_start_tx(struct uart_port *port) |
165 | { |
166 | u32 val; |
167 | |
168 | if (uart_tx_stopped(port)) { |
169 | owl_uart_stop_tx(port); |
170 | return; |
171 | } |
172 | |
173 | val = owl_uart_read(port, OWL_UART_STAT); |
174 | val |= OWL_UART_STAT_TIP; |
175 | owl_uart_write(port, val, OWL_UART_STAT); |
176 | |
177 | val = owl_uart_read(port, OWL_UART_CTL); |
178 | val |= OWL_UART_CTL_TXIE; |
179 | owl_uart_write(port, val, OWL_UART_CTL); |
180 | } |
181 | |
182 | static void owl_uart_send_chars(struct uart_port *port) |
183 | { |
184 | u8 ch; |
185 | |
186 | uart_port_tx(port, ch, |
187 | !(owl_uart_read(port, OWL_UART_STAT) & OWL_UART_STAT_TFFU), |
188 | owl_uart_write(port, ch, OWL_UART_TXDAT)); |
189 | } |
190 | |
191 | static void owl_uart_receive_chars(struct uart_port *port) |
192 | { |
193 | u32 stat, val; |
194 | |
195 | val = owl_uart_read(port, OWL_UART_CTL); |
196 | val &= ~OWL_UART_CTL_TRFS_TX; |
197 | owl_uart_write(port, val, OWL_UART_CTL); |
198 | |
199 | stat = owl_uart_read(port, OWL_UART_STAT); |
200 | while (!(stat & OWL_UART_STAT_RFEM)) { |
201 | char flag = TTY_NORMAL; |
202 | |
203 | if (stat & OWL_UART_STAT_RXER) |
204 | port->icount.overrun++; |
205 | |
206 | if (stat & OWL_UART_STAT_RXST) { |
207 | /* We are not able to distinguish the error type. */ |
208 | port->icount.brk++; |
209 | port->icount.frame++; |
210 | |
211 | stat &= port->read_status_mask; |
212 | if (stat & OWL_UART_STAT_RXST) |
213 | flag = TTY_PARITY; |
214 | } else |
215 | port->icount.rx++; |
216 | |
217 | val = owl_uart_read(port, OWL_UART_RXDAT); |
218 | val &= 0xff; |
219 | |
220 | if ((stat & port->ignore_status_mask) == 0) |
221 | tty_insert_flip_char(port: &port->state->port, ch: val, flag); |
222 | |
223 | stat = owl_uart_read(port, OWL_UART_STAT); |
224 | } |
225 | |
226 | tty_flip_buffer_push(port: &port->state->port); |
227 | } |
228 | |
229 | static irqreturn_t owl_uart_irq(int irq, void *dev_id) |
230 | { |
231 | struct uart_port *port = dev_id; |
232 | unsigned long flags; |
233 | u32 stat; |
234 | |
235 | uart_port_lock_irqsave(up: port, flags: &flags); |
236 | |
237 | stat = owl_uart_read(port, OWL_UART_STAT); |
238 | |
239 | if (stat & OWL_UART_STAT_RIP) |
240 | owl_uart_receive_chars(port); |
241 | |
242 | if (stat & OWL_UART_STAT_TIP) |
243 | owl_uart_send_chars(port); |
244 | |
245 | stat = owl_uart_read(port, OWL_UART_STAT); |
246 | stat |= OWL_UART_STAT_RIP | OWL_UART_STAT_TIP; |
247 | owl_uart_write(port, val: stat, OWL_UART_STAT); |
248 | |
249 | uart_port_unlock_irqrestore(up: port, flags); |
250 | |
251 | return IRQ_HANDLED; |
252 | } |
253 | |
254 | static void owl_uart_shutdown(struct uart_port *port) |
255 | { |
256 | u32 val; |
257 | unsigned long flags; |
258 | |
259 | uart_port_lock_irqsave(up: port, flags: &flags); |
260 | |
261 | val = owl_uart_read(port, OWL_UART_CTL); |
262 | val &= ~(OWL_UART_CTL_TXIE | OWL_UART_CTL_RXIE |
263 | | OWL_UART_CTL_TXDE | OWL_UART_CTL_RXDE | OWL_UART_CTL_EN); |
264 | owl_uart_write(port, val, OWL_UART_CTL); |
265 | |
266 | uart_port_unlock_irqrestore(up: port, flags); |
267 | |
268 | free_irq(port->irq, port); |
269 | } |
270 | |
271 | static int owl_uart_startup(struct uart_port *port) |
272 | { |
273 | u32 val; |
274 | unsigned long flags; |
275 | int ret; |
276 | |
277 | ret = request_irq(irq: port->irq, handler: owl_uart_irq, IRQF_TRIGGER_HIGH, |
278 | name: "owl-uart" , dev: port); |
279 | if (ret) |
280 | return ret; |
281 | |
282 | uart_port_lock_irqsave(up: port, flags: &flags); |
283 | |
284 | val = owl_uart_read(port, OWL_UART_STAT); |
285 | val |= OWL_UART_STAT_RIP | OWL_UART_STAT_TIP |
286 | | OWL_UART_STAT_RXER | OWL_UART_STAT_TFER | OWL_UART_STAT_RXST; |
287 | owl_uart_write(port, val, OWL_UART_STAT); |
288 | |
289 | val = owl_uart_read(port, OWL_UART_CTL); |
290 | val |= OWL_UART_CTL_RXIE | OWL_UART_CTL_TXIE; |
291 | val |= OWL_UART_CTL_EN; |
292 | owl_uart_write(port, val, OWL_UART_CTL); |
293 | |
294 | uart_port_unlock_irqrestore(up: port, flags); |
295 | |
296 | return 0; |
297 | } |
298 | |
299 | static void owl_uart_change_baudrate(struct owl_uart_port *owl_port, |
300 | unsigned long baud) |
301 | { |
302 | clk_set_rate(clk: owl_port->clk, rate: baud * 8); |
303 | } |
304 | |
305 | static void owl_uart_set_termios(struct uart_port *port, |
306 | struct ktermios *termios, |
307 | const struct ktermios *old) |
308 | { |
309 | struct owl_uart_port *owl_port = to_owl_uart_port(port); |
310 | unsigned int baud; |
311 | u32 ctl; |
312 | unsigned long flags; |
313 | |
314 | uart_port_lock_irqsave(up: port, flags: &flags); |
315 | |
316 | ctl = owl_uart_read(port, OWL_UART_CTL); |
317 | |
318 | ctl &= ~OWL_UART_CTL_DWLS_MASK; |
319 | switch (termios->c_cflag & CSIZE) { |
320 | case CS5: |
321 | ctl |= OWL_UART_CTL_DWLS_5BITS; |
322 | break; |
323 | case CS6: |
324 | ctl |= OWL_UART_CTL_DWLS_6BITS; |
325 | break; |
326 | case CS7: |
327 | ctl |= OWL_UART_CTL_DWLS_7BITS; |
328 | break; |
329 | case CS8: |
330 | default: |
331 | ctl |= OWL_UART_CTL_DWLS_8BITS; |
332 | break; |
333 | } |
334 | |
335 | if (termios->c_cflag & CSTOPB) |
336 | ctl |= OWL_UART_CTL_STPS_2BITS; |
337 | else |
338 | ctl &= ~OWL_UART_CTL_STPS_2BITS; |
339 | |
340 | ctl &= ~OWL_UART_CTL_PRS_MASK; |
341 | if (termios->c_cflag & PARENB) { |
342 | if (termios->c_cflag & CMSPAR) { |
343 | if (termios->c_cflag & PARODD) |
344 | ctl |= OWL_UART_CTL_PRS_MARK; |
345 | else |
346 | ctl |= OWL_UART_CTL_PRS_SPACE; |
347 | } else if (termios->c_cflag & PARODD) |
348 | ctl |= OWL_UART_CTL_PRS_ODD; |
349 | else |
350 | ctl |= OWL_UART_CTL_PRS_EVEN; |
351 | } else |
352 | ctl |= OWL_UART_CTL_PRS_NONE; |
353 | |
354 | if (termios->c_cflag & CRTSCTS) |
355 | ctl |= OWL_UART_CTL_AFE; |
356 | else |
357 | ctl &= ~OWL_UART_CTL_AFE; |
358 | |
359 | owl_uart_write(port, val: ctl, OWL_UART_CTL); |
360 | |
361 | baud = uart_get_baud_rate(port, termios, old, min: 9600, max: 3200000); |
362 | owl_uart_change_baudrate(owl_port, baud); |
363 | |
364 | /* Don't rewrite B0 */ |
365 | if (tty_termios_baud_rate(termios)) |
366 | tty_termios_encode_baud_rate(termios, ibaud: baud, obaud: baud); |
367 | |
368 | port->read_status_mask |= OWL_UART_STAT_RXER; |
369 | if (termios->c_iflag & INPCK) |
370 | port->read_status_mask |= OWL_UART_STAT_RXST; |
371 | |
372 | uart_update_timeout(port, cflag: termios->c_cflag, baud); |
373 | |
374 | uart_port_unlock_irqrestore(up: port, flags); |
375 | } |
376 | |
377 | static void owl_uart_release_port(struct uart_port *port) |
378 | { |
379 | struct platform_device *pdev = to_platform_device(port->dev); |
380 | struct resource *res; |
381 | |
382 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
383 | if (!res) |
384 | return; |
385 | |
386 | if (port->flags & UPF_IOREMAP) { |
387 | devm_release_mem_region(port->dev, port->mapbase, |
388 | resource_size(res)); |
389 | devm_iounmap(dev: port->dev, addr: port->membase); |
390 | port->membase = NULL; |
391 | } |
392 | } |
393 | |
394 | static int owl_uart_request_port(struct uart_port *port) |
395 | { |
396 | struct platform_device *pdev = to_platform_device(port->dev); |
397 | struct resource *res; |
398 | |
399 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
400 | if (!res) |
401 | return -ENXIO; |
402 | |
403 | if (!devm_request_mem_region(port->dev, port->mapbase, |
404 | resource_size(res), dev_name(port->dev))) |
405 | return -EBUSY; |
406 | |
407 | if (port->flags & UPF_IOREMAP) { |
408 | port->membase = devm_ioremap(dev: port->dev, offset: port->mapbase, |
409 | size: resource_size(res)); |
410 | if (!port->membase) |
411 | return -EBUSY; |
412 | } |
413 | |
414 | return 0; |
415 | } |
416 | |
417 | static const char *owl_uart_type(struct uart_port *port) |
418 | { |
419 | return (port->type == PORT_OWL) ? "owl-uart" : NULL; |
420 | } |
421 | |
422 | static int owl_uart_verify_port(struct uart_port *port, |
423 | struct serial_struct *ser) |
424 | { |
425 | if (port->type != PORT_OWL) |
426 | return -EINVAL; |
427 | |
428 | if (port->irq != ser->irq) |
429 | return -EINVAL; |
430 | |
431 | return 0; |
432 | } |
433 | |
434 | static void owl_uart_config_port(struct uart_port *port, int flags) |
435 | { |
436 | if (flags & UART_CONFIG_TYPE) { |
437 | port->type = PORT_OWL; |
438 | owl_uart_request_port(port); |
439 | } |
440 | } |
441 | |
442 | #ifdef CONFIG_CONSOLE_POLL |
443 | |
444 | static int owl_uart_poll_get_char(struct uart_port *port) |
445 | { |
446 | if (owl_uart_read(port, OWL_UART_STAT) & OWL_UART_STAT_RFEM) |
447 | return NO_POLL_CHAR; |
448 | |
449 | return owl_uart_read(port, OWL_UART_RXDAT); |
450 | } |
451 | |
452 | static void owl_uart_poll_put_char(struct uart_port *port, unsigned char ch) |
453 | { |
454 | u32 reg; |
455 | int ret; |
456 | |
457 | /* Wait while FIFO is full or timeout */ |
458 | ret = readl_poll_timeout_atomic(port->membase + OWL_UART_STAT, reg, |
459 | !(reg & OWL_UART_STAT_TFFU), |
460 | OWL_UART_POLL_USEC, |
461 | OWL_UART_TIMEOUT_USEC); |
462 | if (ret == -ETIMEDOUT) { |
463 | dev_err(port->dev, "Timeout waiting while UART TX FULL\n" ); |
464 | return; |
465 | } |
466 | |
467 | owl_uart_write(port, val: ch, OWL_UART_TXDAT); |
468 | } |
469 | |
470 | #endif /* CONFIG_CONSOLE_POLL */ |
471 | |
472 | static const struct uart_ops owl_uart_ops = { |
473 | .set_mctrl = owl_uart_set_mctrl, |
474 | .get_mctrl = owl_uart_get_mctrl, |
475 | .tx_empty = owl_uart_tx_empty, |
476 | .start_tx = owl_uart_start_tx, |
477 | .stop_rx = owl_uart_stop_rx, |
478 | .stop_tx = owl_uart_stop_tx, |
479 | .startup = owl_uart_startup, |
480 | .shutdown = owl_uart_shutdown, |
481 | .set_termios = owl_uart_set_termios, |
482 | .type = owl_uart_type, |
483 | .config_port = owl_uart_config_port, |
484 | .request_port = owl_uart_request_port, |
485 | .release_port = owl_uart_release_port, |
486 | .verify_port = owl_uart_verify_port, |
487 | #ifdef CONFIG_CONSOLE_POLL |
488 | .poll_get_char = owl_uart_poll_get_char, |
489 | .poll_put_char = owl_uart_poll_put_char, |
490 | #endif |
491 | }; |
492 | |
493 | #ifdef CONFIG_SERIAL_OWL_CONSOLE |
494 | |
495 | static void owl_console_putchar(struct uart_port *port, unsigned char ch) |
496 | { |
497 | if (!port->membase) |
498 | return; |
499 | |
500 | while (owl_uart_read(port, OWL_UART_STAT) & OWL_UART_STAT_TFFU) |
501 | cpu_relax(); |
502 | |
503 | owl_uart_write(port, val: ch, OWL_UART_TXDAT); |
504 | } |
505 | |
506 | static void owl_uart_port_write(struct uart_port *port, const char *s, |
507 | u_int count) |
508 | { |
509 | u32 old_ctl, val; |
510 | unsigned long flags; |
511 | int locked; |
512 | |
513 | local_irq_save(flags); |
514 | |
515 | if (port->sysrq) |
516 | locked = 0; |
517 | else if (oops_in_progress) |
518 | locked = uart_port_trylock(up: port); |
519 | else { |
520 | uart_port_lock(up: port); |
521 | locked = 1; |
522 | } |
523 | |
524 | old_ctl = owl_uart_read(port, OWL_UART_CTL); |
525 | val = old_ctl | OWL_UART_CTL_TRFS_TX; |
526 | /* disable IRQ */ |
527 | val &= ~(OWL_UART_CTL_RXIE | OWL_UART_CTL_TXIE); |
528 | owl_uart_write(port, val, OWL_UART_CTL); |
529 | |
530 | uart_console_write(port, s, count, putchar: owl_console_putchar); |
531 | |
532 | /* wait until all contents have been sent out */ |
533 | while (owl_uart_read(port, OWL_UART_STAT) & OWL_UART_STAT_TRFL_MASK) |
534 | cpu_relax(); |
535 | |
536 | /* clear IRQ pending */ |
537 | val = owl_uart_read(port, OWL_UART_STAT); |
538 | val |= OWL_UART_STAT_TIP | OWL_UART_STAT_RIP; |
539 | owl_uart_write(port, val, OWL_UART_STAT); |
540 | |
541 | owl_uart_write(port, val: old_ctl, OWL_UART_CTL); |
542 | |
543 | if (locked) |
544 | uart_port_unlock(up: port); |
545 | |
546 | local_irq_restore(flags); |
547 | } |
548 | |
549 | static void owl_uart_console_write(struct console *co, const char *s, |
550 | u_int count) |
551 | { |
552 | struct owl_uart_port *owl_port; |
553 | |
554 | owl_port = owl_uart_ports[co->index]; |
555 | if (!owl_port) |
556 | return; |
557 | |
558 | owl_uart_port_write(port: &owl_port->port, s, count); |
559 | } |
560 | |
561 | static int owl_uart_console_setup(struct console *co, char *options) |
562 | { |
563 | struct owl_uart_port *owl_port; |
564 | int baud = 115200; |
565 | int bits = 8; |
566 | int parity = 'n'; |
567 | int flow = 'n'; |
568 | |
569 | if (co->index < 0 || co->index >= OWL_UART_PORT_NUM) |
570 | return -EINVAL; |
571 | |
572 | owl_port = owl_uart_ports[co->index]; |
573 | if (!owl_port || !owl_port->port.membase) |
574 | return -ENODEV; |
575 | |
576 | if (options) |
577 | uart_parse_options(options, baud: &baud, parity: &parity, bits: &bits, flow: &flow); |
578 | |
579 | return uart_set_options(port: &owl_port->port, co, baud, parity, bits, flow); |
580 | } |
581 | |
582 | static struct console owl_uart_console = { |
583 | .name = OWL_UART_DEV_NAME, |
584 | .write = owl_uart_console_write, |
585 | .device = uart_console_device, |
586 | .setup = owl_uart_console_setup, |
587 | .flags = CON_PRINTBUFFER, |
588 | .index = -1, |
589 | .data = &owl_uart_driver, |
590 | }; |
591 | |
592 | static int __init owl_uart_console_init(void) |
593 | { |
594 | register_console(&owl_uart_console); |
595 | |
596 | return 0; |
597 | } |
598 | console_initcall(owl_uart_console_init); |
599 | |
600 | static void owl_uart_early_console_write(struct console *co, |
601 | const char *s, |
602 | u_int count) |
603 | { |
604 | struct earlycon_device *dev = co->data; |
605 | |
606 | owl_uart_port_write(port: &dev->port, s, count); |
607 | } |
608 | |
609 | static int __init |
610 | owl_uart_early_console_setup(struct earlycon_device *device, const char *opt) |
611 | { |
612 | if (!device->port.membase) |
613 | return -ENODEV; |
614 | |
615 | device->con->write = owl_uart_early_console_write; |
616 | |
617 | return 0; |
618 | } |
619 | OF_EARLYCON_DECLARE(owl, "actions,owl-uart" , |
620 | owl_uart_early_console_setup); |
621 | |
622 | #define OWL_UART_CONSOLE (&owl_uart_console) |
623 | #else |
624 | #define OWL_UART_CONSOLE NULL |
625 | #endif |
626 | |
627 | static struct uart_driver owl_uart_driver = { |
628 | .owner = THIS_MODULE, |
629 | .driver_name = "owl-uart" , |
630 | .dev_name = OWL_UART_DEV_NAME, |
631 | .nr = OWL_UART_PORT_NUM, |
632 | .cons = OWL_UART_CONSOLE, |
633 | }; |
634 | |
635 | static const struct owl_uart_info owl_s500_info = { |
636 | .tx_fifosize = 16, |
637 | }; |
638 | |
639 | static const struct owl_uart_info owl_s900_info = { |
640 | .tx_fifosize = 32, |
641 | }; |
642 | |
643 | static const struct of_device_id owl_uart_dt_matches[] = { |
644 | { .compatible = "actions,s500-uart" , .data = &owl_s500_info }, |
645 | { .compatible = "actions,s900-uart" , .data = &owl_s900_info }, |
646 | { } |
647 | }; |
648 | MODULE_DEVICE_TABLE(of, owl_uart_dt_matches); |
649 | |
650 | static int owl_uart_probe(struct platform_device *pdev) |
651 | { |
652 | const struct of_device_id *match; |
653 | const struct owl_uart_info *info = NULL; |
654 | struct resource *res_mem; |
655 | struct owl_uart_port *owl_port; |
656 | int ret, irq; |
657 | |
658 | if (pdev->dev.of_node) { |
659 | pdev->id = of_alias_get_id(np: pdev->dev.of_node, stem: "serial" ); |
660 | match = of_match_node(matches: owl_uart_dt_matches, node: pdev->dev.of_node); |
661 | if (match) |
662 | info = match->data; |
663 | } |
664 | |
665 | if (pdev->id < 0 || pdev->id >= OWL_UART_PORT_NUM) { |
666 | dev_err(&pdev->dev, "id %d out of range\n" , pdev->id); |
667 | return -EINVAL; |
668 | } |
669 | |
670 | res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
671 | if (!res_mem) { |
672 | dev_err(&pdev->dev, "could not get mem\n" ); |
673 | return -ENODEV; |
674 | } |
675 | |
676 | irq = platform_get_irq(pdev, 0); |
677 | if (irq < 0) |
678 | return irq; |
679 | |
680 | if (owl_uart_ports[pdev->id]) { |
681 | dev_err(&pdev->dev, "port %d already allocated\n" , pdev->id); |
682 | return -EBUSY; |
683 | } |
684 | |
685 | owl_port = devm_kzalloc(dev: &pdev->dev, size: sizeof(*owl_port), GFP_KERNEL); |
686 | if (!owl_port) |
687 | return -ENOMEM; |
688 | |
689 | owl_port->clk = devm_clk_get(dev: &pdev->dev, NULL); |
690 | if (IS_ERR(ptr: owl_port->clk)) { |
691 | dev_err(&pdev->dev, "could not get clk\n" ); |
692 | return PTR_ERR(ptr: owl_port->clk); |
693 | } |
694 | |
695 | ret = clk_prepare_enable(clk: owl_port->clk); |
696 | if (ret) { |
697 | dev_err(&pdev->dev, "could not enable clk\n" ); |
698 | return ret; |
699 | } |
700 | |
701 | owl_port->port.dev = &pdev->dev; |
702 | owl_port->port.line = pdev->id; |
703 | owl_port->port.type = PORT_OWL; |
704 | owl_port->port.iotype = UPIO_MEM; |
705 | owl_port->port.mapbase = res_mem->start; |
706 | owl_port->port.irq = irq; |
707 | owl_port->port.uartclk = clk_get_rate(clk: owl_port->clk); |
708 | if (owl_port->port.uartclk == 0) { |
709 | dev_err(&pdev->dev, "clock rate is zero\n" ); |
710 | clk_disable_unprepare(clk: owl_port->clk); |
711 | return -EINVAL; |
712 | } |
713 | owl_port->port.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_LOW_LATENCY; |
714 | owl_port->port.x_char = 0; |
715 | owl_port->port.fifosize = (info) ? info->tx_fifosize : 16; |
716 | owl_port->port.ops = &owl_uart_ops; |
717 | |
718 | owl_uart_ports[pdev->id] = owl_port; |
719 | platform_set_drvdata(pdev, data: owl_port); |
720 | |
721 | ret = uart_add_one_port(reg: &owl_uart_driver, port: &owl_port->port); |
722 | if (ret) |
723 | owl_uart_ports[pdev->id] = NULL; |
724 | |
725 | return ret; |
726 | } |
727 | |
728 | static int owl_uart_remove(struct platform_device *pdev) |
729 | { |
730 | struct owl_uart_port *owl_port = platform_get_drvdata(pdev); |
731 | |
732 | uart_remove_one_port(reg: &owl_uart_driver, port: &owl_port->port); |
733 | owl_uart_ports[pdev->id] = NULL; |
734 | clk_disable_unprepare(clk: owl_port->clk); |
735 | |
736 | return 0; |
737 | } |
738 | |
739 | static struct platform_driver owl_uart_platform_driver = { |
740 | .probe = owl_uart_probe, |
741 | .remove = owl_uart_remove, |
742 | .driver = { |
743 | .name = "owl-uart" , |
744 | .of_match_table = owl_uart_dt_matches, |
745 | }, |
746 | }; |
747 | |
748 | static int __init owl_uart_init(void) |
749 | { |
750 | int ret; |
751 | |
752 | ret = uart_register_driver(uart: &owl_uart_driver); |
753 | if (ret) |
754 | return ret; |
755 | |
756 | ret = platform_driver_register(&owl_uart_platform_driver); |
757 | if (ret) |
758 | uart_unregister_driver(uart: &owl_uart_driver); |
759 | |
760 | return ret; |
761 | } |
762 | |
763 | static void __exit owl_uart_exit(void) |
764 | { |
765 | platform_driver_unregister(&owl_uart_platform_driver); |
766 | uart_unregister_driver(uart: &owl_uart_driver); |
767 | } |
768 | |
769 | module_init(owl_uart_init); |
770 | module_exit(owl_uart_exit); |
771 | |
772 | MODULE_LICENSE("GPL" ); |
773 | |