Commit | Line | Data |
---|---|---|
2ac4ad2a VG |
1 | /* |
2 | * ARC On-Chip(fpga) UART Driver | |
3 | * | |
4 | * Copyright (C) 2010-2012 Synopsys, Inc. (www.synopsys.com) | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License version 2 as | |
8 | * published by the Free Software Foundation. | |
9 | * | |
10 | * vineetg: July 10th 2012 | |
11 | * -Decoupled the driver from arch/arc | |
12 | * +Using platform_get_resource() for irq/membase (thx to bfin_uart.c) | |
13 | * +Using early_platform_xxx() for early console (thx to mach-shmobile/xxx) | |
14 | * | |
15 | * Vineetg: Aug 21st 2010 | |
16 | * -Is uart_tx_stopped() not done in tty write path as it has already been | |
17 | * taken care of, in serial core | |
18 | * | |
19 | * Vineetg: Aug 18th 2010 | |
20 | * -New Serial Core based ARC UART driver | |
21 | * -Derived largely from blackfin driver albiet with some major tweaks | |
22 | * | |
23 | * TODO: | |
24 | * -check if sysreq works | |
25 | */ | |
26 | ||
27 | #if defined(CONFIG_SERIAL_ARC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) | |
28 | #define SUPPORT_SYSRQ | |
29 | #endif | |
30 | ||
31 | #include <linux/module.h> | |
32 | #include <linux/serial.h> | |
33 | #include <linux/console.h> | |
34 | #include <linux/sysrq.h> | |
35 | #include <linux/platform_device.h> | |
36 | #include <linux/tty.h> | |
37 | #include <linux/tty_flip.h> | |
38 | #include <linux/serial_core.h> | |
39 | #include <linux/io.h> | |
40 | ||
41 | /************************************* | |
42 | * ARC UART Hardware Specs | |
43 | ************************************/ | |
44 | #define ARC_UART_TX_FIFO_SIZE 1 | |
45 | ||
46 | /* | |
47 | * UART Register set (this is not a Standards Compliant IP) | |
48 | * Also each reg is Word aligned, but only 8 bits wide | |
49 | */ | |
50 | #define R_ID0 0 | |
51 | #define R_ID1 4 | |
52 | #define R_ID2 8 | |
53 | #define R_ID3 12 | |
54 | #define R_DATA 16 | |
55 | #define R_STS 20 | |
56 | #define R_BAUDL 24 | |
57 | #define R_BAUDH 28 | |
58 | ||
59 | /* Bits for UART Status Reg (R/W) */ | |
60 | #define RXIENB 0x04 /* Receive Interrupt Enable */ | |
61 | #define TXIENB 0x40 /* Transmit Interrupt Enable */ | |
62 | ||
63 | #define RXEMPTY 0x20 /* Receive FIFO Empty: No char receivede */ | |
64 | #define TXEMPTY 0x80 /* Transmit FIFO Empty, thus char can be written into */ | |
65 | ||
66 | #define RXFULL 0x08 /* Receive FIFO full */ | |
67 | #define RXFULL1 0x10 /* Receive FIFO has space for 1 char (tot space=4) */ | |
68 | ||
69 | #define RXFERR 0x01 /* Frame Error: Stop Bit not detected */ | |
70 | #define RXOERR 0x02 /* OverFlow Err: Char recv but RXFULL still set */ | |
71 | ||
72 | /* Uart bit fiddling helpers: lowest level */ | |
73 | #define RBASE(uart, reg) (uart->port.membase + reg) | |
74 | #define UART_REG_SET(u, r, v) writeb((v), RBASE(u, r)) | |
75 | #define UART_REG_GET(u, r) readb(RBASE(u, r)) | |
76 | ||
77 | #define UART_REG_OR(u, r, v) UART_REG_SET(u, r, UART_REG_GET(u, r) | (v)) | |
78 | #define UART_REG_CLR(u, r, v) UART_REG_SET(u, r, UART_REG_GET(u, r) & ~(v)) | |
79 | ||
80 | /* Uart bit fiddling helpers: API level */ | |
81 | #define UART_SET_DATA(uart, val) UART_REG_SET(uart, R_DATA, val) | |
82 | #define UART_GET_DATA(uart) UART_REG_GET(uart, R_DATA) | |
83 | ||
84 | #define UART_SET_BAUDH(uart, val) UART_REG_SET(uart, R_BAUDH, val) | |
85 | #define UART_SET_BAUDL(uart, val) UART_REG_SET(uart, R_BAUDL, val) | |
86 | ||
87 | #define UART_CLR_STATUS(uart, val) UART_REG_CLR(uart, R_STS, val) | |
88 | #define UART_GET_STATUS(uart) UART_REG_GET(uart, R_STS) | |
89 | ||
90 | #define UART_ALL_IRQ_DISABLE(uart) UART_REG_CLR(uart, R_STS, RXIENB|TXIENB) | |
91 | #define UART_RX_IRQ_DISABLE(uart) UART_REG_CLR(uart, R_STS, RXIENB) | |
92 | #define UART_TX_IRQ_DISABLE(uart) UART_REG_CLR(uart, R_STS, TXIENB) | |
93 | ||
94 | #define UART_ALL_IRQ_ENABLE(uart) UART_REG_OR(uart, R_STS, RXIENB|TXIENB) | |
95 | #define UART_RX_IRQ_ENABLE(uart) UART_REG_OR(uart, R_STS, RXIENB) | |
96 | #define UART_TX_IRQ_ENABLE(uart) UART_REG_OR(uart, R_STS, TXIENB) | |
97 | ||
98 | #define ARC_SERIAL_DEV_NAME "ttyARC" | |
99 | ||
100 | struct arc_uart_port { | |
101 | struct uart_port port; | |
102 | unsigned long baud; | |
103 | int is_emulated; /* H/w vs. Instruction Set Simulator */ | |
104 | }; | |
105 | ||
106 | #define to_arc_port(uport) container_of(uport, struct arc_uart_port, port) | |
107 | ||
108 | static struct arc_uart_port arc_uart_ports[CONFIG_SERIAL_ARC_NR_PORTS]; | |
109 | ||
110 | #ifdef CONFIG_SERIAL_ARC_CONSOLE | |
111 | static struct console arc_console; | |
112 | #endif | |
113 | ||
114 | #define DRIVER_NAME "arc-uart" | |
115 | ||
116 | static struct uart_driver arc_uart_driver = { | |
117 | .owner = THIS_MODULE, | |
118 | .driver_name = DRIVER_NAME, | |
119 | .dev_name = ARC_SERIAL_DEV_NAME, | |
120 | .major = 0, | |
121 | .minor = 0, | |
122 | .nr = CONFIG_SERIAL_ARC_NR_PORTS, | |
123 | #ifdef CONFIG_SERIAL_ARC_CONSOLE | |
124 | .cons = &arc_console, | |
125 | #endif | |
126 | }; | |
127 | ||
128 | static void arc_serial_stop_rx(struct uart_port *port) | |
129 | { | |
130 | struct arc_uart_port *uart = to_arc_port(port); | |
131 | ||
132 | UART_RX_IRQ_DISABLE(uart); | |
133 | } | |
134 | ||
135 | static void arc_serial_stop_tx(struct uart_port *port) | |
136 | { | |
137 | struct arc_uart_port *uart = to_arc_port(port); | |
138 | ||
139 | while (!(UART_GET_STATUS(uart) & TXEMPTY)) | |
140 | cpu_relax(); | |
141 | ||
142 | UART_TX_IRQ_DISABLE(uart); | |
143 | } | |
144 | ||
145 | /* | |
146 | * Return TIOCSER_TEMT when transmitter is not busy. | |
147 | */ | |
148 | static unsigned int arc_serial_tx_empty(struct uart_port *port) | |
149 | { | |
150 | struct arc_uart_port *uart = to_arc_port(port); | |
151 | unsigned int stat; | |
152 | ||
153 | stat = UART_GET_STATUS(uart); | |
154 | if (stat & TXEMPTY) | |
155 | return TIOCSER_TEMT; | |
156 | ||
157 | return 0; | |
158 | } | |
159 | ||
160 | /* | |
161 | * Driver internal routine, used by both tty(serial core) as well as tx-isr | |
162 | * -Called under spinlock in either cases | |
163 | * -also tty->stopped / tty->hw_stopped has already been checked | |
164 | * = by uart_start( ) before calling us | |
165 | * = tx_ist checks that too before calling | |
166 | */ | |
167 | static void arc_serial_tx_chars(struct arc_uart_port *uart) | |
168 | { | |
169 | struct circ_buf *xmit = &uart->port.state->xmit; | |
170 | int sent = 0; | |
171 | unsigned char ch; | |
172 | ||
173 | if (unlikely(uart->port.x_char)) { | |
174 | UART_SET_DATA(uart, uart->port.x_char); | |
175 | uart->port.icount.tx++; | |
176 | uart->port.x_char = 0; | |
177 | sent = 1; | |
178 | } else if (xmit->tail != xmit->head) { /* TODO: uart_circ_empty */ | |
179 | ch = xmit->buf[xmit->tail]; | |
180 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | |
181 | uart->port.icount.tx++; | |
182 | while (!(UART_GET_STATUS(uart) & TXEMPTY)) | |
183 | cpu_relax(); | |
184 | UART_SET_DATA(uart, ch); | |
185 | sent = 1; | |
186 | } | |
187 | ||
188 | /* | |
189 | * If num chars in xmit buffer are too few, ask tty layer for more. | |
190 | * By Hard ISR to schedule processing in software interrupt part | |
191 | */ | |
192 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | |
193 | uart_write_wakeup(&uart->port); | |
194 | ||
195 | if (sent) | |
196 | UART_TX_IRQ_ENABLE(uart); | |
197 | } | |
198 | ||
199 | /* | |
200 | * port is locked and interrupts are disabled | |
201 | * uart_start( ) calls us under the port spinlock irqsave | |
202 | */ | |
203 | static void arc_serial_start_tx(struct uart_port *port) | |
204 | { | |
205 | struct arc_uart_port *uart = to_arc_port(port); | |
206 | ||
207 | arc_serial_tx_chars(uart); | |
208 | } | |
209 | ||
210 | static void arc_serial_rx_chars(struct arc_uart_port *uart) | |
211 | { | |
212 | struct tty_struct *tty = tty_port_tty_get(&uart->port.state->port); | |
213 | unsigned int status, ch, flg = 0; | |
214 | ||
215 | if (!tty) | |
216 | return; | |
217 | ||
218 | /* | |
219 | * UART has 4 deep RX-FIFO. Driver's recongnition of this fact | |
220 | * is very subtle. Here's how ... | |
221 | * Upon getting a RX-Intr, such that RX-EMPTY=0, meaning data available, | |
222 | * driver reads the DATA Reg and keeps doing that in a loop, until | |
223 | * RX-EMPTY=1. Multiple chars being avail, with a single Interrupt, | |
224 | * before RX-EMPTY=0, implies some sort of buffering going on in the | |
225 | * controller, which is indeed the Rx-FIFO. | |
226 | */ | |
227 | while (!((status = UART_GET_STATUS(uart)) & RXEMPTY)) { | |
228 | ||
229 | ch = UART_GET_DATA(uart); | |
230 | uart->port.icount.rx++; | |
231 | ||
232 | if (unlikely(status & (RXOERR | RXFERR))) { | |
233 | if (status & RXOERR) { | |
234 | uart->port.icount.overrun++; | |
235 | flg = TTY_OVERRUN; | |
236 | UART_CLR_STATUS(uart, RXOERR); | |
237 | } | |
238 | ||
239 | if (status & RXFERR) { | |
240 | uart->port.icount.frame++; | |
241 | flg = TTY_FRAME; | |
242 | UART_CLR_STATUS(uart, RXFERR); | |
243 | } | |
244 | } else | |
245 | flg = TTY_NORMAL; | |
246 | ||
247 | if (unlikely(uart_handle_sysrq_char(&uart->port, ch))) | |
248 | goto done; | |
249 | ||
250 | uart_insert_char(&uart->port, status, RXOERR, ch, flg); | |
251 | ||
252 | done: | |
253 | tty_flip_buffer_push(tty); | |
254 | } | |
255 | ||
256 | tty_kref_put(tty); | |
257 | } | |
258 | ||
259 | /* | |
260 | * A note on the Interrupt handling state machine of this driver | |
261 | * | |
262 | * kernel printk writes funnel thru the console driver framework and in order | |
263 | * to keep things simple as well as efficient, it writes to UART in polled | |
264 | * mode, in one shot, and exits. | |
265 | * | |
266 | * OTOH, Userland output (via tty layer), uses interrupt based writes as there | |
267 | * can be undeterministic delay between char writes. | |
268 | * | |
269 | * Thus Rx-interrupts are always enabled, while tx-interrupts are by default | |
270 | * disabled. | |
271 | * | |
272 | * When tty has some data to send out, serial core calls driver's start_tx | |
273 | * which | |
274 | * -checks-if-tty-buffer-has-char-to-send | |
275 | * -writes-data-to-uart | |
276 | * -enable-tx-intr | |
277 | * | |
278 | * Once data bits are pushed out, controller raises the Tx-room-avail-Interrupt. | |
279 | * The first thing Tx ISR does is disable further Tx interrupts (as this could | |
280 | * be the last char to send, before settling down into the quiet polled mode). | |
281 | * It then calls the exact routine used by tty layer write to send out any | |
282 | * more char in tty buffer. In case of sending, it re-enables Tx-intr. In case | |
283 | * of no data, it remains disabled. | |
284 | * This is how the transmit state machine is dynamically switched on/off | |
285 | */ | |
286 | ||
287 | static irqreturn_t arc_serial_isr(int irq, void *dev_id) | |
288 | { | |
289 | struct arc_uart_port *uart = dev_id; | |
290 | unsigned int status; | |
291 | ||
292 | status = UART_GET_STATUS(uart); | |
293 | ||
294 | /* | |
295 | * Single IRQ for both Rx (data available) Tx (room available) Interrupt | |
296 | * notifications from the UART Controller. | |
297 | * To demultiplex between the two, we check the relevant bits | |
298 | */ | |
299 | if ((status & RXIENB) && !(status & RXEMPTY)) { | |
300 | ||
301 | /* already in ISR, no need of xx_irqsave */ | |
302 | spin_lock(&uart->port.lock); | |
303 | arc_serial_rx_chars(uart); | |
304 | spin_unlock(&uart->port.lock); | |
305 | } | |
306 | ||
307 | if ((status & TXIENB) && (status & TXEMPTY)) { | |
308 | ||
309 | /* Unconditionally disable further Tx-Interrupts. | |
310 | * will be enabled by tx_chars() if needed. | |
311 | */ | |
312 | UART_TX_IRQ_DISABLE(uart); | |
313 | ||
314 | spin_lock(&uart->port.lock); | |
315 | ||
316 | if (!uart_tx_stopped(&uart->port)) | |
317 | arc_serial_tx_chars(uart); | |
318 | ||
319 | spin_unlock(&uart->port.lock); | |
320 | } | |
321 | ||
322 | return IRQ_HANDLED; | |
323 | } | |
324 | ||
325 | static unsigned int arc_serial_get_mctrl(struct uart_port *port) | |
326 | { | |
327 | /* | |
328 | * Pretend we have a Modem status reg and following bits are | |
329 | * always set, to satify the serial core state machine | |
330 | * (DSR) Data Set Ready | |
331 | * (CTS) Clear To Send | |
332 | * (CAR) Carrier Detect | |
333 | */ | |
334 | return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; | |
335 | } | |
336 | ||
337 | static void arc_serial_set_mctrl(struct uart_port *port, unsigned int mctrl) | |
338 | { | |
339 | /* MCR not present */ | |
340 | } | |
341 | ||
342 | /* Enable Modem Status Interrupts */ | |
343 | ||
344 | static void arc_serial_enable_ms(struct uart_port *port) | |
345 | { | |
346 | /* MSR not present */ | |
347 | } | |
348 | ||
349 | static void arc_serial_break_ctl(struct uart_port *port, int break_state) | |
350 | { | |
351 | /* ARC UART doesn't support sending Break signal */ | |
352 | } | |
353 | ||
354 | static int arc_serial_startup(struct uart_port *port) | |
355 | { | |
356 | struct arc_uart_port *uart = to_arc_port(port); | |
357 | ||
358 | /* Before we hook up the ISR, Disable all UART Interrupts */ | |
359 | UART_ALL_IRQ_DISABLE(uart); | |
360 | ||
361 | if (request_irq(uart->port.irq, arc_serial_isr, 0, "arc uart rx-tx", | |
362 | uart)) { | |
363 | dev_warn(uart->port.dev, "Unable to attach ARC UART intr\n"); | |
364 | return -EBUSY; | |
365 | } | |
366 | ||
367 | UART_RX_IRQ_ENABLE(uart); /* Only Rx IRQ enabled to begin with */ | |
368 | ||
369 | return 0; | |
370 | } | |
371 | ||
372 | /* This is not really needed */ | |
373 | static void arc_serial_shutdown(struct uart_port *port) | |
374 | { | |
375 | struct arc_uart_port *uart = to_arc_port(port); | |
376 | free_irq(uart->port.irq, uart); | |
377 | } | |
378 | ||
379 | static void | |
380 | arc_serial_set_termios(struct uart_port *port, struct ktermios *new, | |
381 | struct ktermios *old) | |
382 | { | |
383 | struct arc_uart_port *uart = to_arc_port(port); | |
384 | unsigned int baud, uartl, uarth, hw_val; | |
385 | unsigned long flags; | |
386 | ||
387 | /* | |
388 | * Use the generic handler so that any specially encoded baud rates | |
389 | * such as SPD_xx flags or "%B0" can be handled | |
390 | * Max Baud I suppose will not be more than current 115K * 4 | |
391 | * Formula for ARC UART is: hw-val = ((CLK/(BAUD*4)) -1) | |
392 | * spread over two 8-bit registers | |
393 | */ | |
394 | baud = uart_get_baud_rate(port, new, old, 0, 460800); | |
395 | ||
396 | hw_val = port->uartclk / (uart->baud * 4) - 1; | |
397 | uartl = hw_val & 0xFF; | |
398 | uarth = (hw_val >> 8) & 0xFF; | |
399 | ||
400 | /* | |
401 | * UART ISS(Instruction Set simulator) emulation has a subtle bug: | |
402 | * A existing value of Baudh = 0 is used as a indication to startup | |
403 | * it's internal state machine. | |
404 | * Thus if baudh is set to 0, 2 times, it chokes. | |
405 | * This happens with BAUD=115200 and the formaula above | |
406 | * Until that is fixed, when running on ISS, we will set baudh to !0 | |
407 | */ | |
408 | if (uart->is_emulated) | |
409 | uarth = 1; | |
410 | ||
411 | spin_lock_irqsave(&port->lock, flags); | |
412 | ||
413 | UART_ALL_IRQ_DISABLE(uart); | |
414 | ||
415 | UART_SET_BAUDL(uart, uartl); | |
416 | UART_SET_BAUDH(uart, uarth); | |
417 | ||
418 | UART_RX_IRQ_ENABLE(uart); | |
419 | ||
420 | /* | |
421 | * UART doesn't support Parity/Hardware Flow Control; | |
422 | * Only supports 8N1 character size | |
423 | */ | |
424 | new->c_cflag &= ~(CMSPAR|CRTSCTS|CSIZE); | |
425 | new->c_cflag |= CS8; | |
426 | ||
427 | if (old) | |
428 | tty_termios_copy_hw(new, old); | |
429 | ||
430 | /* Don't rewrite B0 */ | |
431 | if (tty_termios_baud_rate(new)) | |
432 | tty_termios_encode_baud_rate(new, baud, baud); | |
433 | ||
434 | uart_update_timeout(port, new->c_cflag, baud); | |
435 | ||
436 | spin_unlock_irqrestore(&port->lock, flags); | |
437 | } | |
438 | ||
439 | static const char *arc_serial_type(struct uart_port *port) | |
440 | { | |
441 | struct arc_uart_port *uart = to_arc_port(port); | |
442 | ||
443 | return uart->port.type == PORT_ARC ? DRIVER_NAME : NULL; | |
444 | } | |
445 | ||
446 | static void arc_serial_release_port(struct uart_port *port) | |
447 | { | |
448 | } | |
449 | ||
450 | static int arc_serial_request_port(struct uart_port *port) | |
451 | { | |
452 | return 0; | |
453 | } | |
454 | ||
455 | /* | |
456 | * Verify the new serial_struct (for TIOCSSERIAL). | |
457 | */ | |
458 | static int | |
459 | arc_serial_verify_port(struct uart_port *port, struct serial_struct *ser) | |
460 | { | |
461 | if (port->type != PORT_UNKNOWN && ser->type != PORT_ARC) | |
462 | return -EINVAL; | |
463 | ||
464 | return 0; | |
465 | } | |
466 | ||
467 | /* | |
468 | * Configure/autoconfigure the port. | |
469 | */ | |
470 | static void arc_serial_config_port(struct uart_port *port, int flags) | |
471 | { | |
472 | struct arc_uart_port *uart = to_arc_port(port); | |
473 | ||
474 | if (flags & UART_CONFIG_TYPE) | |
475 | uart->port.type = PORT_ARC; | |
476 | } | |
477 | ||
478 | #if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_ARC_CONSOLE) | |
479 | ||
480 | static void arc_serial_poll_putchar(struct uart_port *port, unsigned char chr) | |
481 | { | |
482 | struct arc_uart_port *uart = to_arc_port(port); | |
483 | ||
484 | while (!(UART_GET_STATUS(uart) & TXEMPTY)) | |
485 | cpu_relax(); | |
486 | ||
487 | UART_SET_DATA(uart, chr); | |
488 | } | |
489 | #endif | |
490 | ||
491 | #ifdef CONFIG_CONSOLE_POLL | |
492 | static int arc_serial_poll_getchar(struct uart_port *port) | |
493 | { | |
494 | struct arc_uart_port *uart = to_arc_port(port); | |
495 | unsigned char chr; | |
496 | ||
497 | while (!(UART_GET_STATUS(uart) & RXEMPTY)) | |
498 | cpu_relax(); | |
499 | ||
500 | chr = UART_GET_DATA(uart); | |
501 | return chr; | |
502 | } | |
503 | #endif | |
504 | ||
505 | static struct uart_ops arc_serial_pops = { | |
506 | .tx_empty = arc_serial_tx_empty, | |
507 | .set_mctrl = arc_serial_set_mctrl, | |
508 | .get_mctrl = arc_serial_get_mctrl, | |
509 | .stop_tx = arc_serial_stop_tx, | |
510 | .start_tx = arc_serial_start_tx, | |
511 | .stop_rx = arc_serial_stop_rx, | |
512 | .enable_ms = arc_serial_enable_ms, | |
513 | .break_ctl = arc_serial_break_ctl, | |
514 | .startup = arc_serial_startup, | |
515 | .shutdown = arc_serial_shutdown, | |
516 | .set_termios = arc_serial_set_termios, | |
517 | .type = arc_serial_type, | |
518 | .release_port = arc_serial_release_port, | |
519 | .request_port = arc_serial_request_port, | |
520 | .config_port = arc_serial_config_port, | |
521 | .verify_port = arc_serial_verify_port, | |
522 | #ifdef CONFIG_CONSOLE_POLL | |
523 | .poll_put_char = arc_serial_poll_putchar, | |
524 | .poll_get_char = arc_serial_poll_getchar, | |
525 | #endif | |
526 | }; | |
527 | ||
528 | static int __devinit | |
529 | arc_uart_init_one(struct platform_device *pdev, struct arc_uart_port *uart) | |
530 | { | |
531 | struct resource *res, *res2; | |
532 | unsigned long *plat_data; | |
533 | ||
534 | if (pdev->id < 0 || pdev->id >= CONFIG_SERIAL_ARC_NR_PORTS) { | |
535 | dev_err(&pdev->dev, "Wrong uart platform device id.\n"); | |
536 | return -ENOENT; | |
537 | } | |
538 | ||
539 | plat_data = ((unsigned long *)(pdev->dev.platform_data)); | |
540 | uart->baud = plat_data[0]; | |
541 | ||
542 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
543 | if (!res) | |
544 | return -ENODEV; | |
545 | ||
546 | res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | |
547 | if (!res2) | |
548 | return -ENODEV; | |
549 | ||
550 | uart->port.mapbase = res->start; | |
551 | uart->port.membase = ioremap_nocache(res->start, resource_size(res)); | |
552 | if (!uart->port.membase) | |
553 | /* No point of dev_err since UART itself is hosed here */ | |
554 | return -ENXIO; | |
555 | ||
556 | uart->port.irq = res2->start; | |
557 | uart->port.dev = &pdev->dev; | |
558 | uart->port.iotype = UPIO_MEM; | |
559 | uart->port.flags = UPF_BOOT_AUTOCONF; | |
560 | uart->port.line = pdev->id; | |
561 | uart->port.ops = &arc_serial_pops; | |
562 | ||
563 | uart->port.uartclk = plat_data[1]; | |
564 | uart->port.fifosize = ARC_UART_TX_FIFO_SIZE; | |
565 | ||
566 | /* | |
567 | * uart_insert_char( ) uses it in decideding whether to ignore a | |
568 | * char or not. Explicitly setting it here, removes the subtelty | |
569 | */ | |
570 | uart->port.ignore_status_mask = 0; | |
571 | ||
572 | /* Real Hardware vs. emulated to work around a bug */ | |
573 | uart->is_emulated = !!plat_data[2]; | |
574 | ||
575 | return 0; | |
576 | } | |
577 | ||
578 | #ifdef CONFIG_SERIAL_ARC_CONSOLE | |
579 | ||
580 | static int __devinit arc_serial_console_setup(struct console *co, char *options) | |
581 | { | |
582 | struct uart_port *port; | |
583 | int baud = 115200; | |
584 | int bits = 8; | |
585 | int parity = 'n'; | |
586 | int flow = 'n'; | |
587 | ||
588 | if (co->index < 0 || co->index >= CONFIG_SERIAL_ARC_NR_PORTS) | |
589 | return -ENODEV; | |
590 | ||
591 | /* | |
592 | * The uart port backing the console (e.g. ttyARC1) might not have been | |
593 | * init yet. If so, defer the console setup to after the port. | |
594 | */ | |
595 | port = &arc_uart_ports[co->index].port; | |
596 | if (!port->membase) | |
597 | return -ENODEV; | |
598 | ||
599 | if (options) | |
600 | uart_parse_options(options, &baud, &parity, &bits, &flow); | |
601 | ||
602 | /* | |
603 | * Serial core will call port->ops->set_termios( ) | |
604 | * which will set the baud reg | |
605 | */ | |
606 | return uart_set_options(port, co, baud, parity, bits, flow); | |
607 | } | |
608 | ||
609 | static void arc_serial_console_putchar(struct uart_port *port, int ch) | |
610 | { | |
611 | arc_serial_poll_putchar(port, (unsigned char)ch); | |
612 | } | |
613 | ||
614 | /* | |
615 | * Interrupts are disabled on entering | |
616 | */ | |
617 | static void arc_serial_console_write(struct console *co, const char *s, | |
618 | unsigned int count) | |
619 | { | |
620 | struct uart_port *port = &arc_uart_ports[co->index].port; | |
621 | unsigned long flags; | |
622 | ||
623 | spin_lock_irqsave(&port->lock, flags); | |
624 | uart_console_write(port, s, count, arc_serial_console_putchar); | |
625 | spin_unlock_irqrestore(&port->lock, flags); | |
626 | } | |
627 | ||
628 | static struct console arc_console = { | |
629 | .name = ARC_SERIAL_DEV_NAME, | |
630 | .write = arc_serial_console_write, | |
631 | .device = uart_console_device, | |
632 | .setup = arc_serial_console_setup, | |
633 | .flags = CON_PRINTBUFFER, | |
634 | .index = -1, | |
635 | .data = &arc_uart_driver | |
636 | }; | |
637 | ||
638 | static __init void early_serial_write(struct console *con, const char *s, | |
639 | unsigned int n) | |
640 | { | |
641 | struct uart_port *port = &arc_uart_ports[con->index].port; | |
642 | unsigned int i; | |
643 | ||
644 | for (i = 0; i < n; i++, s++) { | |
645 | if (*s == '\n') | |
646 | arc_serial_poll_putchar(port, '\r'); | |
647 | arc_serial_poll_putchar(port, *s); | |
648 | } | |
649 | } | |
650 | ||
651 | static struct __initdata console arc_early_serial_console = { | |
652 | .name = "early_ARCuart", | |
653 | .write = early_serial_write, | |
654 | .flags = CON_PRINTBUFFER | CON_BOOT, | |
655 | .index = -1 | |
656 | }; | |
657 | ||
658 | static int __devinit arc_serial_probe_earlyprintk(struct platform_device *pdev) | |
659 | { | |
660 | arc_early_serial_console.index = pdev->id; | |
661 | ||
662 | arc_uart_init_one(pdev, &arc_uart_ports[pdev->id]); | |
663 | ||
664 | arc_serial_console_setup(&arc_early_serial_console, NULL); | |
665 | ||
666 | register_console(&arc_early_serial_console); | |
667 | return 0; | |
668 | } | |
669 | #else | |
670 | static int __devinit arc_serial_probe_earlyprintk(struct platform_device *pdev) | |
671 | { | |
672 | return -ENODEV; | |
673 | } | |
674 | #endif /* CONFIG_SERIAL_ARC_CONSOLE */ | |
675 | ||
676 | static int __devinit arc_serial_probe(struct platform_device *pdev) | |
677 | { | |
678 | struct arc_uart_port *uart; | |
679 | int rc; | |
680 | ||
681 | if (is_early_platform_device(pdev)) | |
682 | return arc_serial_probe_earlyprintk(pdev); | |
683 | ||
684 | uart = &arc_uart_ports[pdev->id]; | |
685 | rc = arc_uart_init_one(pdev, uart); | |
686 | if (rc) | |
687 | return rc; | |
688 | ||
689 | return uart_add_one_port(&arc_uart_driver, &uart->port); | |
690 | } | |
691 | ||
692 | static int __devexit arc_serial_remove(struct platform_device *pdev) | |
693 | { | |
694 | /* This will never be called */ | |
695 | return 0; | |
696 | } | |
697 | ||
698 | static struct platform_driver arc_platform_driver = { | |
699 | .probe = arc_serial_probe, | |
700 | .remove = __devexit_p(arc_serial_remove), | |
701 | .driver = { | |
702 | .name = DRIVER_NAME, | |
703 | .owner = THIS_MODULE, | |
704 | }, | |
705 | }; | |
706 | ||
707 | #ifdef CONFIG_SERIAL_ARC_CONSOLE | |
708 | /* | |
709 | * Register an early platform driver of "earlyprintk" class. | |
710 | * ARCH platform code installs the driver and probes the early devices | |
711 | * The installation could rely on user specifying earlyprintk=xyx in cmd line | |
712 | * or it could be done independently, for all "earlyprintk" class drivers. | |
713 | * [see arch/arc/plat-arcfpga/platform.c] | |
714 | */ | |
715 | early_platform_init("earlyprintk", &arc_platform_driver); | |
716 | ||
717 | #endif /* CONFIG_SERIAL_ARC_CONSOLE */ | |
718 | ||
719 | static int __init arc_serial_init(void) | |
720 | { | |
721 | int ret; | |
722 | ||
723 | ret = uart_register_driver(&arc_uart_driver); | |
724 | if (ret) | |
725 | return ret; | |
726 | ||
727 | ret = platform_driver_register(&arc_platform_driver); | |
728 | if (ret) | |
729 | uart_unregister_driver(&arc_uart_driver); | |
730 | ||
731 | return ret; | |
732 | } | |
733 | ||
734 | static void __exit arc_serial_exit(void) | |
735 | { | |
736 | platform_driver_unregister(&arc_platform_driver); | |
737 | uart_unregister_driver(&arc_uart_driver); | |
738 | } | |
739 | ||
740 | module_init(arc_serial_init); | |
741 | module_exit(arc_serial_exit); | |
742 | ||
743 | MODULE_LICENSE("GPL"); | |
744 | MODULE_ALIAS("plat-arcfpga/uart"); | |
745 | MODULE_AUTHOR("Vineet Gupta"); | |
746 | MODULE_DESCRIPTION("ARC(Synopsys) On-Chip(fpga) serial driver"); |