Commit | Line | Data |
---|---|---|
c4b05856 SK |
1 | /* |
2 | * st-asc.c: ST Asynchronous serial controller (ASC) driver | |
3 | * | |
4 | * Copyright (C) 2003-2013 STMicroelectronics (R&D) Limited | |
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 as published by | |
8 | * the Free Software Foundation; either version 2 of the License, or | |
9 | * (at your option) any later version. | |
10 | * | |
11 | */ | |
12 | ||
13 | #if defined(CONFIG_SERIAL_ST_ASC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) | |
14 | #define SUPPORT_SYSRQ | |
15 | #endif | |
16 | ||
17 | #include <linux/module.h> | |
18 | #include <linux/serial.h> | |
19 | #include <linux/console.h> | |
20 | #include <linux/sysrq.h> | |
21 | #include <linux/platform_device.h> | |
22 | #include <linux/io.h> | |
23 | #include <linux/irq.h> | |
24 | #include <linux/tty.h> | |
25 | #include <linux/tty_flip.h> | |
26 | #include <linux/delay.h> | |
27 | #include <linux/spinlock.h> | |
28 | #include <linux/pm_runtime.h> | |
29 | #include <linux/of.h> | |
30 | #include <linux/of_platform.h> | |
31 | #include <linux/serial_core.h> | |
32 | #include <linux/clk.h> | |
33 | ||
34 | #define DRIVER_NAME "st-asc" | |
35 | #define ASC_SERIAL_NAME "ttyAS" | |
36 | #define ASC_FIFO_SIZE 16 | |
37 | #define ASC_MAX_PORTS 8 | |
38 | ||
39 | struct asc_port { | |
40 | struct uart_port port; | |
41 | struct clk *clk; | |
42 | unsigned int hw_flow_control:1; | |
43 | unsigned int force_m1:1; | |
44 | }; | |
45 | ||
46 | static struct asc_port asc_ports[ASC_MAX_PORTS]; | |
47 | static struct uart_driver asc_uart_driver; | |
48 | ||
49 | /*---- UART Register definitions ------------------------------*/ | |
50 | ||
51 | /* Register offsets */ | |
52 | ||
53 | #define ASC_BAUDRATE 0x00 | |
54 | #define ASC_TXBUF 0x04 | |
55 | #define ASC_RXBUF 0x08 | |
56 | #define ASC_CTL 0x0C | |
57 | #define ASC_INTEN 0x10 | |
58 | #define ASC_STA 0x14 | |
59 | #define ASC_GUARDTIME 0x18 | |
60 | #define ASC_TIMEOUT 0x1C | |
61 | #define ASC_TXRESET 0x20 | |
62 | #define ASC_RXRESET 0x24 | |
63 | #define ASC_RETRIES 0x28 | |
64 | ||
65 | /* ASC_RXBUF */ | |
66 | #define ASC_RXBUF_PE 0x100 | |
67 | #define ASC_RXBUF_FE 0x200 | |
68 | /** | |
69 | * Some of status comes from higher bits of the character and some come from | |
70 | * the status register. Combining both of them in to single status using dummy | |
71 | * bits. | |
72 | */ | |
73 | #define ASC_RXBUF_DUMMY_RX 0x10000 | |
74 | #define ASC_RXBUF_DUMMY_BE 0x20000 | |
75 | #define ASC_RXBUF_DUMMY_OE 0x40000 | |
76 | ||
77 | /* ASC_CTL */ | |
78 | ||
79 | #define ASC_CTL_MODE_MSK 0x0007 | |
80 | #define ASC_CTL_MODE_8BIT 0x0001 | |
81 | #define ASC_CTL_MODE_7BIT_PAR 0x0003 | |
82 | #define ASC_CTL_MODE_9BIT 0x0004 | |
83 | #define ASC_CTL_MODE_8BIT_WKUP 0x0005 | |
84 | #define ASC_CTL_MODE_8BIT_PAR 0x0007 | |
85 | #define ASC_CTL_STOP_MSK 0x0018 | |
86 | #define ASC_CTL_STOP_HALFBIT 0x0000 | |
87 | #define ASC_CTL_STOP_1BIT 0x0008 | |
88 | #define ASC_CTL_STOP_1_HALFBIT 0x0010 | |
89 | #define ASC_CTL_STOP_2BIT 0x0018 | |
90 | #define ASC_CTL_PARITYODD 0x0020 | |
91 | #define ASC_CTL_LOOPBACK 0x0040 | |
92 | #define ASC_CTL_RUN 0x0080 | |
93 | #define ASC_CTL_RXENABLE 0x0100 | |
94 | #define ASC_CTL_SCENABLE 0x0200 | |
95 | #define ASC_CTL_FIFOENABLE 0x0400 | |
96 | #define ASC_CTL_CTSENABLE 0x0800 | |
97 | #define ASC_CTL_BAUDMODE 0x1000 | |
98 | ||
99 | /* ASC_GUARDTIME */ | |
100 | ||
101 | #define ASC_GUARDTIME_MSK 0x00FF | |
102 | ||
103 | /* ASC_INTEN */ | |
104 | ||
105 | #define ASC_INTEN_RBE 0x0001 | |
106 | #define ASC_INTEN_TE 0x0002 | |
107 | #define ASC_INTEN_THE 0x0004 | |
108 | #define ASC_INTEN_PE 0x0008 | |
109 | #define ASC_INTEN_FE 0x0010 | |
110 | #define ASC_INTEN_OE 0x0020 | |
111 | #define ASC_INTEN_TNE 0x0040 | |
112 | #define ASC_INTEN_TOI 0x0080 | |
113 | #define ASC_INTEN_RHF 0x0100 | |
114 | ||
115 | /* ASC_RETRIES */ | |
116 | ||
117 | #define ASC_RETRIES_MSK 0x00FF | |
118 | ||
119 | /* ASC_RXBUF */ | |
120 | ||
121 | #define ASC_RXBUF_MSK 0x03FF | |
122 | ||
123 | /* ASC_STA */ | |
124 | ||
125 | #define ASC_STA_RBF 0x0001 | |
126 | #define ASC_STA_TE 0x0002 | |
127 | #define ASC_STA_THE 0x0004 | |
128 | #define ASC_STA_PE 0x0008 | |
129 | #define ASC_STA_FE 0x0010 | |
130 | #define ASC_STA_OE 0x0020 | |
131 | #define ASC_STA_TNE 0x0040 | |
132 | #define ASC_STA_TOI 0x0080 | |
133 | #define ASC_STA_RHF 0x0100 | |
134 | #define ASC_STA_TF 0x0200 | |
135 | #define ASC_STA_NKD 0x0400 | |
136 | ||
137 | /* ASC_TIMEOUT */ | |
138 | ||
139 | #define ASC_TIMEOUT_MSK 0x00FF | |
140 | ||
141 | /* ASC_TXBUF */ | |
142 | ||
143 | #define ASC_TXBUF_MSK 0x01FF | |
144 | ||
145 | /*---- Inline function definitions ---------------------------*/ | |
146 | ||
147 | static inline struct asc_port *to_asc_port(struct uart_port *port) | |
148 | { | |
149 | return container_of(port, struct asc_port, port); | |
150 | } | |
151 | ||
152 | static inline u32 asc_in(struct uart_port *port, u32 offset) | |
153 | { | |
154 | return readl(port->membase + offset); | |
155 | } | |
156 | ||
157 | static inline void asc_out(struct uart_port *port, u32 offset, u32 value) | |
158 | { | |
159 | writel(value, port->membase + offset); | |
160 | } | |
161 | ||
162 | /* | |
163 | * Some simple utility functions to enable and disable interrupts. | |
164 | * Note that these need to be called with interrupts disabled. | |
165 | */ | |
166 | static inline void asc_disable_tx_interrupts(struct uart_port *port) | |
167 | { | |
168 | u32 intenable = asc_in(port, ASC_INTEN) & ~ASC_INTEN_THE; | |
169 | asc_out(port, ASC_INTEN, intenable); | |
170 | (void)asc_in(port, ASC_INTEN); /* Defeat bus write posting */ | |
171 | } | |
172 | ||
173 | static inline void asc_enable_tx_interrupts(struct uart_port *port) | |
174 | { | |
175 | u32 intenable = asc_in(port, ASC_INTEN) | ASC_INTEN_THE; | |
176 | asc_out(port, ASC_INTEN, intenable); | |
177 | } | |
178 | ||
179 | static inline void asc_disable_rx_interrupts(struct uart_port *port) | |
180 | { | |
181 | u32 intenable = asc_in(port, ASC_INTEN) & ~ASC_INTEN_RBE; | |
182 | asc_out(port, ASC_INTEN, intenable); | |
183 | (void)asc_in(port, ASC_INTEN); /* Defeat bus write posting */ | |
184 | } | |
185 | ||
186 | static inline void asc_enable_rx_interrupts(struct uart_port *port) | |
187 | { | |
188 | u32 intenable = asc_in(port, ASC_INTEN) | ASC_INTEN_RBE; | |
189 | asc_out(port, ASC_INTEN, intenable); | |
190 | } | |
191 | ||
192 | static inline u32 asc_txfifo_is_empty(struct uart_port *port) | |
193 | { | |
194 | return asc_in(port, ASC_STA) & ASC_STA_TE; | |
195 | } | |
196 | ||
1ffcd67d | 197 | static inline u32 asc_txfifo_is_half_empty(struct uart_port *port) |
c4b05856 | 198 | { |
1ffcd67d | 199 | return asc_in(port, ASC_STA) & ASC_STA_THE; |
c4b05856 SK |
200 | } |
201 | ||
202 | static inline const char *asc_port_name(struct uart_port *port) | |
203 | { | |
204 | return to_platform_device(port->dev)->name; | |
205 | } | |
206 | ||
207 | /*----------------------------------------------------------------------*/ | |
208 | ||
209 | /* | |
210 | * This section contains code to support the use of the ASC as a | |
211 | * generic serial port. | |
212 | */ | |
213 | ||
214 | static inline unsigned asc_hw_txroom(struct uart_port *port) | |
215 | { | |
216 | u32 status = asc_in(port, ASC_STA); | |
217 | ||
218 | if (status & ASC_STA_THE) | |
219 | return port->fifosize / 2; | |
220 | else if (!(status & ASC_STA_TF)) | |
221 | return 1; | |
222 | ||
223 | return 0; | |
224 | } | |
225 | ||
226 | /* | |
227 | * Start transmitting chars. | |
228 | * This is called from both interrupt and task level. | |
229 | * Either way interrupts are disabled. | |
230 | */ | |
231 | static void asc_transmit_chars(struct uart_port *port) | |
232 | { | |
233 | struct circ_buf *xmit = &port->state->xmit; | |
234 | int txroom; | |
235 | unsigned char c; | |
236 | ||
237 | txroom = asc_hw_txroom(port); | |
238 | ||
239 | if ((txroom != 0) && port->x_char) { | |
240 | c = port->x_char; | |
241 | port->x_char = 0; | |
242 | asc_out(port, ASC_TXBUF, c); | |
243 | port->icount.tx++; | |
244 | txroom = asc_hw_txroom(port); | |
245 | } | |
246 | ||
247 | if (uart_tx_stopped(port)) { | |
248 | /* | |
249 | * We should try and stop the hardware here, but I | |
250 | * don't think the ASC has any way to do that. | |
251 | */ | |
252 | asc_disable_tx_interrupts(port); | |
253 | return; | |
254 | } | |
255 | ||
256 | if (uart_circ_empty(xmit)) { | |
257 | asc_disable_tx_interrupts(port); | |
258 | return; | |
259 | } | |
260 | ||
261 | if (txroom == 0) | |
262 | return; | |
263 | ||
264 | do { | |
265 | c = xmit->buf[xmit->tail]; | |
266 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | |
267 | asc_out(port, ASC_TXBUF, c); | |
268 | port->icount.tx++; | |
269 | txroom--; | |
270 | } while ((txroom > 0) && (!uart_circ_empty(xmit))); | |
271 | ||
272 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | |
273 | uart_write_wakeup(port); | |
274 | ||
275 | if (uart_circ_empty(xmit)) | |
276 | asc_disable_tx_interrupts(port); | |
277 | } | |
278 | ||
279 | static void asc_receive_chars(struct uart_port *port) | |
280 | { | |
281 | struct tty_port *tport = &port->state->port; | |
282 | unsigned long status; | |
283 | unsigned long c = 0; | |
284 | char flag; | |
285 | ||
286 | if (port->irq_wake) | |
287 | pm_wakeup_event(tport->tty->dev, 0); | |
288 | ||
289 | while ((status = asc_in(port, ASC_STA)) & ASC_STA_RBF) { | |
290 | c = asc_in(port, ASC_RXBUF) | ASC_RXBUF_DUMMY_RX; | |
291 | flag = TTY_NORMAL; | |
292 | port->icount.rx++; | |
293 | ||
294 | if ((c & (ASC_RXBUF_FE | ASC_RXBUF_PE)) || | |
295 | status & ASC_STA_OE) { | |
296 | ||
297 | if (c & ASC_RXBUF_FE) { | |
c3c00b6f | 298 | if (c == (ASC_RXBUF_FE | ASC_RXBUF_DUMMY_RX)) { |
c4b05856 SK |
299 | port->icount.brk++; |
300 | if (uart_handle_break(port)) | |
301 | continue; | |
302 | c |= ASC_RXBUF_DUMMY_BE; | |
303 | } else { | |
304 | port->icount.frame++; | |
305 | } | |
306 | } else if (c & ASC_RXBUF_PE) { | |
307 | port->icount.parity++; | |
308 | } | |
309 | /* | |
310 | * Reading any data from the RX FIFO clears the | |
311 | * overflow error condition. | |
312 | */ | |
313 | if (status & ASC_STA_OE) { | |
314 | port->icount.overrun++; | |
315 | c |= ASC_RXBUF_DUMMY_OE; | |
316 | } | |
317 | ||
318 | c &= port->read_status_mask; | |
319 | ||
320 | if (c & ASC_RXBUF_DUMMY_BE) | |
321 | flag = TTY_BREAK; | |
322 | else if (c & ASC_RXBUF_PE) | |
323 | flag = TTY_PARITY; | |
324 | else if (c & ASC_RXBUF_FE) | |
325 | flag = TTY_FRAME; | |
326 | } | |
327 | ||
c3c00b6f | 328 | if (uart_handle_sysrq_char(port, c & 0xff)) |
c4b05856 SK |
329 | continue; |
330 | ||
331 | uart_insert_char(port, c, ASC_RXBUF_DUMMY_OE, c & 0xff, flag); | |
332 | } | |
333 | ||
334 | /* Tell the rest of the system the news. New characters! */ | |
335 | tty_flip_buffer_push(tport); | |
336 | } | |
337 | ||
338 | static irqreturn_t asc_interrupt(int irq, void *ptr) | |
339 | { | |
340 | struct uart_port *port = ptr; | |
341 | u32 status; | |
342 | ||
343 | spin_lock(&port->lock); | |
344 | ||
345 | status = asc_in(port, ASC_STA); | |
346 | ||
347 | if (status & ASC_STA_RBF) { | |
348 | /* Receive FIFO not empty */ | |
349 | asc_receive_chars(port); | |
350 | } | |
351 | ||
352 | if ((status & ASC_STA_THE) && | |
353 | (asc_in(port, ASC_INTEN) & ASC_INTEN_THE)) { | |
354 | /* Transmitter FIFO at least half empty */ | |
355 | asc_transmit_chars(port); | |
356 | } | |
357 | ||
358 | spin_unlock(&port->lock); | |
359 | ||
360 | return IRQ_HANDLED; | |
361 | } | |
362 | ||
363 | /*----------------------------------------------------------------------*/ | |
364 | ||
365 | /* | |
366 | * UART Functions | |
367 | */ | |
368 | ||
369 | static unsigned int asc_tx_empty(struct uart_port *port) | |
370 | { | |
371 | return asc_txfifo_is_empty(port) ? TIOCSER_TEMT : 0; | |
372 | } | |
373 | ||
374 | static void asc_set_mctrl(struct uart_port *port, unsigned int mctrl) | |
375 | { | |
376 | /* | |
377 | * This routine is used for seting signals of: DTR, DCD, CTS/RTS | |
378 | * We use ASC's hardware for CTS/RTS, so don't need any for that. | |
379 | * Some boards have DTR and DCD implemented using PIO pins, | |
380 | * code to do this should be hooked in here. | |
381 | */ | |
382 | } | |
383 | ||
384 | static unsigned int asc_get_mctrl(struct uart_port *port) | |
385 | { | |
386 | /* | |
387 | * This routine is used for geting signals of: DTR, DCD, DSR, RI, | |
388 | * and CTS/RTS | |
389 | */ | |
390 | return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS; | |
391 | } | |
392 | ||
393 | /* There are probably characters waiting to be transmitted. */ | |
394 | static void asc_start_tx(struct uart_port *port) | |
395 | { | |
396 | struct circ_buf *xmit = &port->state->xmit; | |
397 | ||
398 | if (!uart_circ_empty(xmit)) | |
399 | asc_enable_tx_interrupts(port); | |
400 | } | |
401 | ||
402 | /* Transmit stop */ | |
403 | static void asc_stop_tx(struct uart_port *port) | |
404 | { | |
405 | asc_disable_tx_interrupts(port); | |
406 | } | |
407 | ||
408 | /* Receive stop */ | |
409 | static void asc_stop_rx(struct uart_port *port) | |
410 | { | |
411 | asc_disable_rx_interrupts(port); | |
412 | } | |
413 | ||
414 | /* Force modem status interrupts on */ | |
415 | static void asc_enable_ms(struct uart_port *port) | |
416 | { | |
417 | /* Nothing here yet .. */ | |
418 | } | |
419 | ||
420 | /* Handle breaks - ignored by us */ | |
421 | static void asc_break_ctl(struct uart_port *port, int break_state) | |
422 | { | |
423 | /* Nothing here yet .. */ | |
424 | } | |
425 | ||
426 | /* | |
427 | * Enable port for reception. | |
428 | */ | |
429 | static int asc_startup(struct uart_port *port) | |
430 | { | |
431 | if (request_irq(port->irq, asc_interrupt, IRQF_NO_SUSPEND, | |
432 | asc_port_name(port), port)) { | |
433 | dev_err(port->dev, "cannot allocate irq.\n"); | |
434 | return -ENODEV; | |
435 | } | |
436 | ||
437 | asc_transmit_chars(port); | |
438 | asc_enable_rx_interrupts(port); | |
439 | ||
440 | return 0; | |
441 | } | |
442 | ||
443 | static void asc_shutdown(struct uart_port *port) | |
444 | { | |
445 | asc_disable_tx_interrupts(port); | |
446 | asc_disable_rx_interrupts(port); | |
447 | free_irq(port->irq, port); | |
448 | } | |
449 | ||
450 | static void asc_pm(struct uart_port *port, unsigned int state, | |
451 | unsigned int oldstate) | |
452 | { | |
453 | struct asc_port *ascport = to_asc_port(port); | |
454 | unsigned long flags = 0; | |
455 | u32 ctl; | |
456 | ||
457 | switch (state) { | |
458 | case UART_PM_STATE_ON: | |
459 | clk_prepare_enable(ascport->clk); | |
460 | break; | |
461 | case UART_PM_STATE_OFF: | |
462 | /* | |
463 | * Disable the ASC baud rate generator, which is as close as | |
464 | * we can come to turning it off. Note this is not called with | |
465 | * the port spinlock held. | |
466 | */ | |
467 | spin_lock_irqsave(&port->lock, flags); | |
468 | ctl = asc_in(port, ASC_CTL) & ~ASC_CTL_RUN; | |
469 | asc_out(port, ASC_CTL, ctl); | |
470 | spin_unlock_irqrestore(&port->lock, flags); | |
471 | clk_disable_unprepare(ascport->clk); | |
472 | break; | |
473 | } | |
474 | } | |
475 | ||
476 | static void asc_set_termios(struct uart_port *port, struct ktermios *termios, | |
477 | struct ktermios *old) | |
478 | { | |
479 | struct asc_port *ascport = to_asc_port(port); | |
480 | unsigned int baud; | |
481 | u32 ctrl_val; | |
482 | tcflag_t cflag; | |
483 | unsigned long flags; | |
484 | ||
485 | /* Update termios to reflect hardware capabilities */ | |
486 | termios->c_cflag &= ~(CMSPAR | | |
487 | (ascport->hw_flow_control ? 0 : CRTSCTS)); | |
488 | ||
489 | port->uartclk = clk_get_rate(ascport->clk); | |
490 | ||
491 | baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); | |
492 | cflag = termios->c_cflag; | |
493 | ||
494 | spin_lock_irqsave(&port->lock, flags); | |
495 | ||
496 | /* read control register */ | |
497 | ctrl_val = asc_in(port, ASC_CTL); | |
498 | ||
499 | /* stop serial port and reset value */ | |
500 | asc_out(port, ASC_CTL, (ctrl_val & ~ASC_CTL_RUN)); | |
501 | ctrl_val = ASC_CTL_RXENABLE | ASC_CTL_FIFOENABLE; | |
502 | ||
503 | /* reset fifo rx & tx */ | |
504 | asc_out(port, ASC_TXRESET, 1); | |
505 | asc_out(port, ASC_RXRESET, 1); | |
506 | ||
507 | /* set character length */ | |
508 | if ((cflag & CSIZE) == CS7) { | |
509 | ctrl_val |= ASC_CTL_MODE_7BIT_PAR; | |
510 | } else { | |
511 | ctrl_val |= (cflag & PARENB) ? ASC_CTL_MODE_8BIT_PAR : | |
512 | ASC_CTL_MODE_8BIT; | |
513 | } | |
514 | ||
515 | /* set stop bit */ | |
516 | ctrl_val |= (cflag & CSTOPB) ? ASC_CTL_STOP_2BIT : ASC_CTL_STOP_1BIT; | |
517 | ||
518 | /* odd parity */ | |
519 | if (cflag & PARODD) | |
520 | ctrl_val |= ASC_CTL_PARITYODD; | |
521 | ||
522 | /* hardware flow control */ | |
523 | if ((cflag & CRTSCTS)) | |
524 | ctrl_val |= ASC_CTL_CTSENABLE; | |
525 | ||
526 | if ((baud < 19200) && !ascport->force_m1) { | |
527 | asc_out(port, ASC_BAUDRATE, (port->uartclk / (16 * baud))); | |
528 | } else { | |
529 | /* | |
530 | * MODE 1: recommended for high bit rates (above 19.2K) | |
531 | * | |
532 | * baudrate * 16 * 2^16 | |
533 | * ASCBaudRate = ------------------------ | |
534 | * inputclock | |
535 | * | |
536 | * However to keep the maths inside 32bits we divide top and | |
537 | * bottom by 64. The +1 is to avoid a divide by zero if the | |
538 | * input clock rate is something unexpected. | |
539 | */ | |
540 | u32 counter = (baud * 16384) / ((port->uartclk / 64) + 1); | |
541 | asc_out(port, ASC_BAUDRATE, counter); | |
542 | ctrl_val |= ASC_CTL_BAUDMODE; | |
543 | } | |
544 | ||
545 | uart_update_timeout(port, cflag, baud); | |
546 | ||
547 | ascport->port.read_status_mask = ASC_RXBUF_DUMMY_OE; | |
548 | if (termios->c_iflag & INPCK) | |
549 | ascport->port.read_status_mask |= ASC_RXBUF_FE | ASC_RXBUF_PE; | |
ef8b9ddc | 550 | if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK)) |
c4b05856 SK |
551 | ascport->port.read_status_mask |= ASC_RXBUF_DUMMY_BE; |
552 | ||
553 | /* | |
554 | * Characters to ignore | |
555 | */ | |
556 | ascport->port.ignore_status_mask = 0; | |
557 | if (termios->c_iflag & IGNPAR) | |
558 | ascport->port.ignore_status_mask |= ASC_RXBUF_FE | ASC_RXBUF_PE; | |
559 | if (termios->c_iflag & IGNBRK) { | |
560 | ascport->port.ignore_status_mask |= ASC_RXBUF_DUMMY_BE; | |
561 | /* | |
562 | * If we're ignoring parity and break indicators, | |
563 | * ignore overruns too (for real raw support). | |
564 | */ | |
565 | if (termios->c_iflag & IGNPAR) | |
566 | ascport->port.ignore_status_mask |= ASC_RXBUF_DUMMY_OE; | |
567 | } | |
568 | ||
569 | /* | |
570 | * Ignore all characters if CREAD is not set. | |
571 | */ | |
572 | if (!(termios->c_cflag & CREAD)) | |
573 | ascport->port.ignore_status_mask |= ASC_RXBUF_DUMMY_RX; | |
574 | ||
575 | /* Set the timeout */ | |
576 | asc_out(port, ASC_TIMEOUT, 20); | |
577 | ||
578 | /* write final value and enable port */ | |
579 | asc_out(port, ASC_CTL, (ctrl_val | ASC_CTL_RUN)); | |
580 | ||
581 | spin_unlock_irqrestore(&port->lock, flags); | |
582 | } | |
583 | ||
584 | static const char *asc_type(struct uart_port *port) | |
585 | { | |
586 | return (port->type == PORT_ASC) ? DRIVER_NAME : NULL; | |
587 | } | |
588 | ||
589 | static void asc_release_port(struct uart_port *port) | |
590 | { | |
591 | } | |
592 | ||
593 | static int asc_request_port(struct uart_port *port) | |
594 | { | |
595 | return 0; | |
596 | } | |
597 | ||
598 | /* | |
599 | * Called when the port is opened, and UPF_BOOT_AUTOCONF flag is set | |
600 | * Set type field if successful | |
601 | */ | |
602 | static void asc_config_port(struct uart_port *port, int flags) | |
603 | { | |
604 | if ((flags & UART_CONFIG_TYPE)) | |
605 | port->type = PORT_ASC; | |
606 | } | |
607 | ||
608 | static int | |
609 | asc_verify_port(struct uart_port *port, struct serial_struct *ser) | |
610 | { | |
611 | /* No user changeable parameters */ | |
612 | return -EINVAL; | |
613 | } | |
614 | ||
615 | #ifdef CONFIG_CONSOLE_POLL | |
616 | /* | |
617 | * Console polling routines for writing and reading from the uart while | |
618 | * in an interrupt or debug context (i.e. kgdb). | |
619 | */ | |
620 | ||
621 | static int asc_get_poll_char(struct uart_port *port) | |
622 | { | |
623 | if (!(asc_in(port, ASC_STA) & ASC_STA_RBF)) | |
624 | return NO_POLL_CHAR; | |
625 | ||
626 | return asc_in(port, ASC_RXBUF); | |
627 | } | |
628 | ||
629 | static void asc_put_poll_char(struct uart_port *port, unsigned char c) | |
630 | { | |
1ffcd67d | 631 | while (!asc_txfifo_is_half_empty(port)) |
c4b05856 SK |
632 | cpu_relax(); |
633 | asc_out(port, ASC_TXBUF, c); | |
634 | } | |
635 | ||
636 | #endif /* CONFIG_CONSOLE_POLL */ | |
637 | ||
638 | /*---------------------------------------------------------------------*/ | |
639 | ||
640 | static struct uart_ops asc_uart_ops = { | |
641 | .tx_empty = asc_tx_empty, | |
642 | .set_mctrl = asc_set_mctrl, | |
643 | .get_mctrl = asc_get_mctrl, | |
644 | .start_tx = asc_start_tx, | |
645 | .stop_tx = asc_stop_tx, | |
646 | .stop_rx = asc_stop_rx, | |
647 | .enable_ms = asc_enable_ms, | |
648 | .break_ctl = asc_break_ctl, | |
649 | .startup = asc_startup, | |
650 | .shutdown = asc_shutdown, | |
651 | .set_termios = asc_set_termios, | |
652 | .type = asc_type, | |
653 | .release_port = asc_release_port, | |
654 | .request_port = asc_request_port, | |
655 | .config_port = asc_config_port, | |
656 | .verify_port = asc_verify_port, | |
657 | .pm = asc_pm, | |
658 | #ifdef CONFIG_CONSOLE_POLL | |
659 | .poll_get_char = asc_get_poll_char, | |
660 | .poll_put_char = asc_put_poll_char, | |
661 | #endif /* CONFIG_CONSOLE_POLL */ | |
662 | }; | |
663 | ||
664 | static int asc_init_port(struct asc_port *ascport, | |
665 | struct platform_device *pdev) | |
666 | { | |
667 | struct uart_port *port = &ascport->port; | |
3abeff77 | 668 | struct resource *res; |
c4b05856 SK |
669 | |
670 | port->iotype = UPIO_MEM; | |
671 | port->flags = UPF_BOOT_AUTOCONF; | |
672 | port->ops = &asc_uart_ops; | |
673 | port->fifosize = ASC_FIFO_SIZE; | |
674 | port->dev = &pdev->dev; | |
c4b05856 SK |
675 | port->irq = platform_get_irq(pdev, 0); |
676 | ||
3abeff77 JL |
677 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
678 | port->membase = devm_ioremap_resource(&pdev->dev, res); | |
679 | if (IS_ERR(port->membase)) | |
680 | return PTR_ERR(port->membase); | |
681 | port->mapbase = res->start; | |
c4b05856 SK |
682 | |
683 | spin_lock_init(&port->lock); | |
684 | ||
685 | ascport->clk = devm_clk_get(&pdev->dev, NULL); | |
686 | ||
687 | if (WARN_ON(IS_ERR(ascport->clk))) | |
688 | return -EINVAL; | |
689 | /* ensure that clk rate is correct by enabling the clk */ | |
690 | clk_prepare_enable(ascport->clk); | |
691 | ascport->port.uartclk = clk_get_rate(ascport->clk); | |
692 | WARN_ON(ascport->port.uartclk == 0); | |
693 | clk_disable_unprepare(ascport->clk); | |
694 | ||
695 | return 0; | |
696 | } | |
697 | ||
698 | static struct asc_port *asc_of_get_asc_port(struct platform_device *pdev) | |
699 | { | |
700 | struct device_node *np = pdev->dev.of_node; | |
701 | int id; | |
702 | ||
703 | if (!np) | |
704 | return NULL; | |
705 | ||
706 | id = of_alias_get_id(np, ASC_SERIAL_NAME); | |
707 | ||
708 | if (id < 0) | |
709 | id = 0; | |
710 | ||
711 | if (WARN_ON(id >= ASC_MAX_PORTS)) | |
712 | return NULL; | |
713 | ||
714 | asc_ports[id].hw_flow_control = of_property_read_bool(np, | |
715 | "st,hw-flow-control"); | |
716 | asc_ports[id].force_m1 = of_property_read_bool(np, "st,force_m1"); | |
717 | asc_ports[id].port.line = id; | |
718 | return &asc_ports[id]; | |
719 | } | |
720 | ||
a4f2dc9e | 721 | #ifdef CONFIG_OF |
c4b05856 SK |
722 | static struct of_device_id asc_match[] = { |
723 | { .compatible = "st,asc", }, | |
724 | {}, | |
725 | }; | |
726 | ||
727 | MODULE_DEVICE_TABLE(of, asc_match); | |
a4f2dc9e | 728 | #endif |
c4b05856 SK |
729 | |
730 | static int asc_serial_probe(struct platform_device *pdev) | |
731 | { | |
732 | int ret; | |
733 | struct asc_port *ascport; | |
734 | ||
735 | ascport = asc_of_get_asc_port(pdev); | |
736 | if (!ascport) | |
737 | return -ENODEV; | |
738 | ||
739 | ret = asc_init_port(ascport, pdev); | |
740 | if (ret) | |
741 | return ret; | |
742 | ||
743 | ret = uart_add_one_port(&asc_uart_driver, &ascport->port); | |
744 | if (ret) | |
745 | return ret; | |
746 | ||
747 | platform_set_drvdata(pdev, &ascport->port); | |
748 | ||
749 | return 0; | |
750 | } | |
751 | ||
752 | static int asc_serial_remove(struct platform_device *pdev) | |
753 | { | |
754 | struct uart_port *port = platform_get_drvdata(pdev); | |
755 | ||
c4b05856 SK |
756 | return uart_remove_one_port(&asc_uart_driver, port); |
757 | } | |
758 | ||
759 | #ifdef CONFIG_PM_SLEEP | |
760 | static int asc_serial_suspend(struct device *dev) | |
761 | { | |
762 | struct platform_device *pdev = to_platform_device(dev); | |
763 | struct uart_port *port = platform_get_drvdata(pdev); | |
764 | ||
765 | return uart_suspend_port(&asc_uart_driver, port); | |
766 | } | |
767 | ||
768 | static int asc_serial_resume(struct device *dev) | |
769 | { | |
770 | struct platform_device *pdev = to_platform_device(dev); | |
771 | struct uart_port *port = platform_get_drvdata(pdev); | |
772 | ||
773 | return uart_resume_port(&asc_uart_driver, port); | |
774 | } | |
775 | ||
776 | #endif /* CONFIG_PM_SLEEP */ | |
777 | ||
778 | /*----------------------------------------------------------------------*/ | |
779 | ||
780 | #ifdef CONFIG_SERIAL_ST_ASC_CONSOLE | |
781 | static void asc_console_putchar(struct uart_port *port, int ch) | |
782 | { | |
783 | unsigned int timeout = 1000000; | |
784 | ||
785 | /* Wait for upto 1 second in case flow control is stopping us. */ | |
1ffcd67d | 786 | while (--timeout && !asc_txfifo_is_half_empty(port)) |
c4b05856 SK |
787 | udelay(1); |
788 | ||
789 | asc_out(port, ASC_TXBUF, ch); | |
790 | } | |
791 | ||
792 | /* | |
793 | * Print a string to the serial port trying not to disturb | |
794 | * any possible real use of the port... | |
795 | */ | |
796 | ||
797 | static void asc_console_write(struct console *co, const char *s, unsigned count) | |
798 | { | |
799 | struct uart_port *port = &asc_ports[co->index].port; | |
800 | unsigned long flags; | |
801 | unsigned long timeout = 1000000; | |
802 | int locked = 1; | |
803 | u32 intenable; | |
804 | ||
805 | local_irq_save(flags); | |
806 | if (port->sysrq) | |
807 | locked = 0; /* asc_interrupt has already claimed the lock */ | |
808 | else if (oops_in_progress) | |
809 | locked = spin_trylock(&port->lock); | |
810 | else | |
811 | spin_lock(&port->lock); | |
812 | ||
813 | /* | |
814 | * Disable interrupts so we don't get the IRQ line bouncing | |
815 | * up and down while interrupts are disabled. | |
816 | */ | |
817 | intenable = asc_in(port, ASC_INTEN); | |
818 | asc_out(port, ASC_INTEN, 0); | |
819 | (void)asc_in(port, ASC_INTEN); /* Defeat bus write posting */ | |
820 | ||
821 | uart_console_write(port, s, count, asc_console_putchar); | |
822 | ||
823 | while (--timeout && !asc_txfifo_is_empty(port)) | |
824 | udelay(1); | |
825 | ||
826 | asc_out(port, ASC_INTEN, intenable); | |
827 | ||
828 | if (locked) | |
829 | spin_unlock(&port->lock); | |
830 | local_irq_restore(flags); | |
831 | } | |
832 | ||
833 | static int asc_console_setup(struct console *co, char *options) | |
834 | { | |
835 | struct asc_port *ascport; | |
836 | int baud = 9600; | |
837 | int bits = 8; | |
838 | int parity = 'n'; | |
839 | int flow = 'n'; | |
840 | ||
841 | if (co->index >= ASC_MAX_PORTS) | |
842 | return -ENODEV; | |
843 | ||
844 | ascport = &asc_ports[co->index]; | |
845 | ||
846 | /* | |
847 | * This driver does not support early console initialization | |
848 | * (use ARM early printk support instead), so we only expect | |
849 | * this to be called during the uart port registration when the | |
850 | * driver gets probed and the port should be mapped at that point. | |
851 | */ | |
852 | BUG_ON(ascport->port.mapbase == 0 || ascport->port.membase == NULL); | |
853 | ||
854 | if (options) | |
855 | uart_parse_options(options, &baud, &parity, &bits, &flow); | |
856 | ||
857 | return uart_set_options(&ascport->port, co, baud, parity, bits, flow); | |
858 | } | |
859 | ||
860 | static struct console asc_console = { | |
861 | .name = ASC_SERIAL_NAME, | |
862 | .device = uart_console_device, | |
863 | .write = asc_console_write, | |
864 | .setup = asc_console_setup, | |
865 | .flags = CON_PRINTBUFFER, | |
866 | .index = -1, | |
867 | .data = &asc_uart_driver, | |
868 | }; | |
869 | ||
870 | #define ASC_SERIAL_CONSOLE (&asc_console) | |
871 | ||
872 | #else | |
873 | #define ASC_SERIAL_CONSOLE NULL | |
874 | #endif /* CONFIG_SERIAL_ST_ASC_CONSOLE */ | |
875 | ||
876 | static struct uart_driver asc_uart_driver = { | |
877 | .owner = THIS_MODULE, | |
878 | .driver_name = DRIVER_NAME, | |
879 | .dev_name = ASC_SERIAL_NAME, | |
880 | .major = 0, | |
881 | .minor = 0, | |
882 | .nr = ASC_MAX_PORTS, | |
883 | .cons = ASC_SERIAL_CONSOLE, | |
884 | }; | |
885 | ||
886 | static const struct dev_pm_ops asc_serial_pm_ops = { | |
887 | SET_SYSTEM_SLEEP_PM_OPS(asc_serial_suspend, asc_serial_resume) | |
888 | }; | |
889 | ||
890 | static struct platform_driver asc_serial_driver = { | |
891 | .probe = asc_serial_probe, | |
892 | .remove = asc_serial_remove, | |
893 | .driver = { | |
894 | .name = DRIVER_NAME, | |
895 | .pm = &asc_serial_pm_ops, | |
896 | .owner = THIS_MODULE, | |
897 | .of_match_table = of_match_ptr(asc_match), | |
898 | }, | |
899 | }; | |
900 | ||
901 | static int __init asc_init(void) | |
902 | { | |
903 | int ret; | |
904 | static char banner[] __initdata = | |
905 | KERN_INFO "STMicroelectronics ASC driver initialized\n"; | |
906 | ||
907 | printk(banner); | |
908 | ||
909 | ret = uart_register_driver(&asc_uart_driver); | |
910 | if (ret) | |
911 | return ret; | |
912 | ||
913 | ret = platform_driver_register(&asc_serial_driver); | |
914 | if (ret) | |
915 | uart_unregister_driver(&asc_uart_driver); | |
916 | ||
917 | return ret; | |
918 | } | |
919 | ||
920 | static void __exit asc_exit(void) | |
921 | { | |
922 | platform_driver_unregister(&asc_serial_driver); | |
923 | uart_unregister_driver(&asc_uart_driver); | |
924 | } | |
925 | ||
926 | module_init(asc_init); | |
927 | module_exit(asc_exit); | |
928 | ||
929 | MODULE_ALIAS("platform:" DRIVER_NAME); | |
930 | MODULE_AUTHOR("STMicroelectronics (R&D) Limited"); | |
931 | MODULE_DESCRIPTION("STMicroelectronics ASC serial port driver"); | |
932 | MODULE_LICENSE("GPL"); |