aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/sccnxp.c
diff options
context:
space:
mode:
authorAlexander Shiyan <shc_work@mail.ru>2012-08-25 11:24:19 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-09-05 16:21:46 -0400
commit1d65c0b12656d9f3bc29bb19f2d7441832433f03 (patch)
treef808a7ac221715ec9471a9c9ec096dc840479213 /drivers/tty/serial/sccnxp.c
parent6971c635af27b1d18d409e337e70bae25d2fa8ec (diff)
serial: New serial driver SCCNXP
This driver is a replacement for a SC26XX driver with a lot of improvements and new features. The main differences from the SC26XX driver: - Removed dependency on MIPS. Driver can be used on any platform. - Added support for SCC2681, SCC2691, SCC2692, SC28L91, SC28L92, SC28L202, SCC68681 and SCC68692 ICs. - Using devm_-related functions. - Improved error handling of serial port, improved FIFO handling. - Ability to load multiple instances of drivers. To avoid the possibility of regression, driver SC26XX left in the system to confirm the stability of the driver on platforms where it is being used. Signed-off-by: Alexander Shiyan <shc_work@mail.ru> Acked-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/serial/sccnxp.c')
-rw-r--r--drivers/tty/serial/sccnxp.c985
1 files changed, 985 insertions, 0 deletions
diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c
new file mode 100644
index 000000000000..29dda9ba6f0f
--- /dev/null
+++ b/drivers/tty/serial/sccnxp.c
@@ -0,0 +1,985 @@
1/*
2 * NXP (Philips) SCC+++(SCN+++) serial driver
3 *
4 * Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru>
5 *
6 * Based on sc26xx.c, by Thomas Bogendörfer (tsbogend@alpha.franken.de)
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 */
13
14#if defined(CONFIG_SERIAL_SCCNXP_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
15#define SUPPORT_SYSRQ
16#endif
17
18#include <linux/module.h>
19#include <linux/device.h>
20#include <linux/serial_core.h>
21#include <linux/serial.h>
22#include <linux/io.h>
23#include <linux/tty.h>
24#include <linux/tty_flip.h>
25#include <linux/console.h>
26#include <linux/platform_device.h>
27#include <linux/platform_data/sccnxp.h>
28
29#define SCCNXP_NAME "uart-sccnxp"
30#define SCCNXP_MAJOR 204
31#define SCCNXP_MINOR 205
32
33#define SCCNXP_MR_REG (0x00)
34# define MR0_BAUD_NORMAL (0 << 0)
35# define MR0_BAUD_EXT1 (1 << 0)
36# define MR0_BAUD_EXT2 (5 << 0)
37# define MR0_FIFO (1 << 3)
38# define MR0_TXLVL (1 << 4)
39# define MR1_BITS_5 (0 << 0)
40# define MR1_BITS_6 (1 << 0)
41# define MR1_BITS_7 (2 << 0)
42# define MR1_BITS_8 (3 << 0)
43# define MR1_PAR_EVN (0 << 2)
44# define MR1_PAR_ODD (1 << 2)
45# define MR1_PAR_NO (4 << 2)
46# define MR2_STOP1 (7 << 0)
47# define MR2_STOP2 (0xf << 0)
48#define SCCNXP_SR_REG (0x01)
49#define SCCNXP_CSR_REG SCCNXP_SR_REG
50# define SR_RXRDY (1 << 0)
51# define SR_FULL (1 << 1)
52# define SR_TXRDY (1 << 2)
53# define SR_TXEMT (1 << 3)
54# define SR_OVR (1 << 4)
55# define SR_PE (1 << 5)
56# define SR_FE (1 << 6)
57# define SR_BRK (1 << 7)
58#define SCCNXP_CR_REG (0x02)
59# define CR_RX_ENABLE (1 << 0)
60# define CR_RX_DISABLE (1 << 1)
61# define CR_TX_ENABLE (1 << 2)
62# define CR_TX_DISABLE (1 << 3)
63# define CR_CMD_MRPTR1 (0x01 << 4)
64# define CR_CMD_RX_RESET (0x02 << 4)
65# define CR_CMD_TX_RESET (0x03 << 4)
66# define CR_CMD_STATUS_RESET (0x04 << 4)
67# define CR_CMD_BREAK_RESET (0x05 << 4)
68# define CR_CMD_START_BREAK (0x06 << 4)
69# define CR_CMD_STOP_BREAK (0x07 << 4)
70# define CR_CMD_MRPTR0 (0x0b << 4)
71#define SCCNXP_RHR_REG (0x03)
72#define SCCNXP_THR_REG SCCNXP_RHR_REG
73#define SCCNXP_IPCR_REG (0x04)
74#define SCCNXP_ACR_REG SCCNXP_IPCR_REG
75# define ACR_BAUD0 (0 << 7)
76# define ACR_BAUD1 (1 << 7)
77# define ACR_TIMER_MODE (6 << 4)
78#define SCCNXP_ISR_REG (0x05)
79#define SCCNXP_IMR_REG SCCNXP_ISR_REG
80# define IMR_TXRDY (1 << 0)
81# define IMR_RXRDY (1 << 1)
82# define ISR_TXRDY(x) (1 << ((x * 4) + 0))
83# define ISR_RXRDY(x) (1 << ((x * 4) + 1))
84#define SCCNXP_IPR_REG (0x0d)
85#define SCCNXP_OPCR_REG SCCNXP_IPR_REG
86#define SCCNXP_SOP_REG (0x0e)
87#define SCCNXP_ROP_REG (0x0f)
88
89/* Route helpers */
90#define MCTRL_MASK(sig) (0xf << (sig))
91#define MCTRL_IBIT(cfg, sig) ((((cfg) >> (sig)) & 0xf) - LINE_IP0)
92#define MCTRL_OBIT(cfg, sig) ((((cfg) >> (sig)) & 0xf) - LINE_OP0)
93
94/* Supported chip types */
95enum {
96 SCCNXP_TYPE_SC2681 = 2681,
97 SCCNXP_TYPE_SC2691 = 2691,
98 SCCNXP_TYPE_SC2692 = 2692,
99 SCCNXP_TYPE_SC2891 = 2891,
100 SCCNXP_TYPE_SC2892 = 2892,
101 SCCNXP_TYPE_SC28202 = 28202,
102 SCCNXP_TYPE_SC68681 = 68681,
103 SCCNXP_TYPE_SC68692 = 68692,
104};
105
106struct sccnxp_port {
107 struct uart_driver uart;
108 struct uart_port port[SCCNXP_MAX_UARTS];
109
110 const char *name;
111 int irq;
112
113 u8 imr;
114 u8 addr_mask;
115 int freq_std;
116
117 int flags;
118#define SCCNXP_HAVE_IO 0x00000001
119#define SCCNXP_HAVE_MR0 0x00000002
120
121#ifdef CONFIG_SERIAL_SCCNXP_CONSOLE
122 struct console console;
123#endif
124
125 struct mutex sccnxp_mutex;
126
127 struct sccnxp_pdata pdata;
128};
129
130static inline u8 sccnxp_raw_read(void __iomem *base, u8 reg, u8 shift)
131{
132 return readb(base + (reg << shift));
133}
134
135static inline void sccnxp_raw_write(void __iomem *base, u8 reg, u8 shift, u8 v)
136{
137 writeb(v, base + (reg << shift));
138}
139
140static inline u8 sccnxp_read(struct uart_port *port, u8 reg)
141{
142 struct sccnxp_port *s = dev_get_drvdata(port->dev);
143
144 return sccnxp_raw_read(port->membase, reg & s->addr_mask,
145 port->regshift);
146}
147
148static inline void sccnxp_write(struct uart_port *port, u8 reg, u8 v)
149{
150 struct sccnxp_port *s = dev_get_drvdata(port->dev);
151
152 sccnxp_raw_write(port->membase, reg & s->addr_mask, port->regshift, v);
153}
154
155static inline u8 sccnxp_port_read(struct uart_port *port, u8 reg)
156{
157 return sccnxp_read(port, (port->line << 3) + reg);
158}
159
160static inline void sccnxp_port_write(struct uart_port *port, u8 reg, u8 v)
161{
162 sccnxp_write(port, (port->line << 3) + reg, v);
163}
164
165static int sccnxp_update_best_err(int a, int b, int *besterr)
166{
167 int err = abs(a - b);
168
169 if ((*besterr < 0) || (*besterr > err)) {
170 *besterr = err;
171 return 0;
172 }
173
174 return 1;
175}
176
177struct baud_table {
178 u8 csr;
179 u8 acr;
180 u8 mr0;
181 int baud;
182};
183
184const struct baud_table baud_std[] = {
185 { 0, ACR_BAUD0, MR0_BAUD_NORMAL, 50, },
186 { 0, ACR_BAUD1, MR0_BAUD_NORMAL, 75, },
187 { 1, ACR_BAUD0, MR0_BAUD_NORMAL, 110, },
188 { 2, ACR_BAUD0, MR0_BAUD_NORMAL, 134, },
189 { 3, ACR_BAUD1, MR0_BAUD_NORMAL, 150, },
190 { 3, ACR_BAUD0, MR0_BAUD_NORMAL, 200, },
191 { 4, ACR_BAUD0, MR0_BAUD_NORMAL, 300, },
192 { 0, ACR_BAUD1, MR0_BAUD_EXT1, 450, },
193 { 1, ACR_BAUD0, MR0_BAUD_EXT2, 880, },
194 { 3, ACR_BAUD1, MR0_BAUD_EXT1, 900, },
195 { 5, ACR_BAUD0, MR0_BAUD_NORMAL, 600, },
196 { 7, ACR_BAUD0, MR0_BAUD_NORMAL, 1050, },
197 { 2, ACR_BAUD0, MR0_BAUD_EXT2, 1076, },
198 { 6, ACR_BAUD0, MR0_BAUD_NORMAL, 1200, },
199 { 10, ACR_BAUD1, MR0_BAUD_NORMAL, 1800, },
200 { 7, ACR_BAUD1, MR0_BAUD_NORMAL, 2000, },
201 { 8, ACR_BAUD0, MR0_BAUD_NORMAL, 2400, },
202 { 5, ACR_BAUD1, MR0_BAUD_EXT1, 3600, },
203 { 9, ACR_BAUD0, MR0_BAUD_NORMAL, 4800, },
204 { 10, ACR_BAUD0, MR0_BAUD_NORMAL, 7200, },
205 { 11, ACR_BAUD0, MR0_BAUD_NORMAL, 9600, },
206 { 8, ACR_BAUD0, MR0_BAUD_EXT1, 14400, },
207 { 12, ACR_BAUD1, MR0_BAUD_NORMAL, 19200, },
208 { 9, ACR_BAUD0, MR0_BAUD_EXT1, 28800, },
209 { 12, ACR_BAUD0, MR0_BAUD_NORMAL, 38400, },
210 { 11, ACR_BAUD0, MR0_BAUD_EXT1, 57600, },
211 { 12, ACR_BAUD1, MR0_BAUD_EXT1, 115200, },
212 { 12, ACR_BAUD0, MR0_BAUD_EXT1, 230400, },
213 { 0, 0, 0, 0 }
214};
215
216static void sccnxp_set_baud(struct uart_port *port, int baud)
217{
218 struct sccnxp_port *s = dev_get_drvdata(port->dev);
219 int div_std, tmp_baud, bestbaud = baud, besterr = -1;
220 u8 i, acr = 0, csr = 0, mr0 = 0;
221
222 /* Find best baud from table */
223 for (i = 0; baud_std[i].baud && besterr; i++) {
224 if (baud_std[i].mr0 && !(s->flags & SCCNXP_HAVE_MR0))
225 continue;
226 div_std = DIV_ROUND_CLOSEST(s->freq_std, baud_std[i].baud);
227 tmp_baud = DIV_ROUND_CLOSEST(port->uartclk, div_std);
228 if (!sccnxp_update_best_err(baud, tmp_baud, &besterr)) {
229 acr = baud_std[i].acr;
230 csr = baud_std[i].csr;
231 mr0 = baud_std[i].mr0;
232 bestbaud = tmp_baud;
233 }
234 }
235
236 if (s->flags & SCCNXP_HAVE_MR0) {
237 /* Enable FIFO, set half level for TX */
238 mr0 |= MR0_FIFO | MR0_TXLVL;
239 /* Update MR0 */
240 sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_MRPTR0);
241 sccnxp_port_write(port, SCCNXP_MR_REG, mr0);
242 }
243
244 sccnxp_port_write(port, SCCNXP_ACR_REG, acr | ACR_TIMER_MODE);
245 sccnxp_port_write(port, SCCNXP_CSR_REG, (csr << 4) | csr);
246
247 dev_dbg(port->dev, "Baudrate desired: %i, calculated: %i\n",
248 baud, bestbaud);
249}
250
251static void sccnxp_enable_irq(struct uart_port *port, int mask)
252{
253 struct sccnxp_port *s = dev_get_drvdata(port->dev);
254
255 s->imr |= mask << (port->line * 4);
256 sccnxp_write(port, SCCNXP_IMR_REG, s->imr);
257}
258
259static void sccnxp_disable_irq(struct uart_port *port, int mask)
260{
261 struct sccnxp_port *s = dev_get_drvdata(port->dev);
262
263 s->imr &= ~(mask << (port->line * 4));
264 sccnxp_write(port, SCCNXP_IMR_REG, s->imr);
265}
266
267static void sccnxp_set_bit(struct uart_port *port, int sig, int state)
268{
269 u8 bitmask;
270 struct sccnxp_port *s = dev_get_drvdata(port->dev);
271
272 if (s->pdata.mctrl_cfg[port->line] & MCTRL_MASK(sig)) {
273 bitmask = 1 << MCTRL_OBIT(s->pdata.mctrl_cfg[port->line], sig);
274 if (state)
275 sccnxp_write(port, SCCNXP_SOP_REG, bitmask);
276 else
277 sccnxp_write(port, SCCNXP_ROP_REG, bitmask);
278 }
279}
280
281static void sccnxp_handle_rx(struct uart_port *port)
282{
283 u8 sr;
284 unsigned int ch, flag;
285 struct tty_struct *tty = tty_port_tty_get(&port->state->port);
286
287 if (!tty)
288 return;
289
290 for (;;) {
291 sr = sccnxp_port_read(port, SCCNXP_SR_REG);
292 if (!(sr & SR_RXRDY))
293 break;
294 sr &= SR_PE | SR_FE | SR_OVR | SR_BRK;
295
296 ch = sccnxp_port_read(port, SCCNXP_RHR_REG);
297
298 port->icount.rx++;
299 flag = TTY_NORMAL;
300
301 if (unlikely(sr)) {
302 if (sr & SR_BRK) {
303 port->icount.brk++;
304 if (uart_handle_break(port))
305 continue;
306 } else if (sr & SR_PE)
307 port->icount.parity++;
308 else if (sr & SR_FE)
309 port->icount.frame++;
310 else if (sr & SR_OVR)
311 port->icount.overrun++;
312
313 sr &= port->read_status_mask;
314 if (sr & SR_BRK)
315 flag = TTY_BREAK;
316 else if (sr & SR_PE)
317 flag = TTY_PARITY;
318 else if (sr & SR_FE)
319 flag = TTY_FRAME;
320 else if (sr & SR_OVR)
321 flag = TTY_OVERRUN;
322 }
323
324 if (uart_handle_sysrq_char(port, ch))
325 continue;
326
327 if (sr & port->ignore_status_mask)
328 continue;
329
330 uart_insert_char(port, sr, SR_OVR, ch, flag);
331 }
332
333 tty_flip_buffer_push(tty);
334
335 tty_kref_put(tty);
336}
337
338static void sccnxp_handle_tx(struct uart_port *port)
339{
340 u8 sr;
341 struct circ_buf *xmit = &port->state->xmit;
342 struct sccnxp_port *s = dev_get_drvdata(port->dev);
343
344 if (unlikely(port->x_char)) {
345 sccnxp_port_write(port, SCCNXP_THR_REG, port->x_char);
346 port->icount.tx++;
347 port->x_char = 0;
348 return;
349 }
350
351 if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
352 /* Disable TX if FIFO is empty */
353 if (sccnxp_port_read(port, SCCNXP_SR_REG) & SR_TXEMT) {
354 sccnxp_disable_irq(port, IMR_TXRDY);
355
356 /* Set direction to input */
357 if (s->flags & SCCNXP_HAVE_IO)
358 sccnxp_set_bit(port, DIR_OP, 0);
359 }
360 return;
361 }
362
363 while (!uart_circ_empty(xmit)) {
364 sr = sccnxp_port_read(port, SCCNXP_SR_REG);
365 if (!(sr & SR_TXRDY))
366 break;
367
368 sccnxp_port_write(port, SCCNXP_THR_REG, xmit->buf[xmit->tail]);
369 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
370 port->icount.tx++;
371 }
372
373 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
374 uart_write_wakeup(port);
375}
376
377static irqreturn_t sccnxp_ist(int irq, void *dev_id)
378{
379 int i;
380 u8 isr;
381 struct sccnxp_port *s = (struct sccnxp_port *)dev_id;
382
383 mutex_lock(&s->sccnxp_mutex);
384
385 for (;;) {
386 isr = sccnxp_read(&s->port[0], SCCNXP_ISR_REG);
387 isr &= s->imr;
388 if (!isr)
389 break;
390
391 dev_dbg(s->port[0].dev, "IRQ status: 0x%02x\n", isr);
392
393 for (i = 0; i < s->uart.nr; i++) {
394 if (isr & ISR_RXRDY(i))
395 sccnxp_handle_rx(&s->port[i]);
396 if (isr & ISR_TXRDY(i))
397 sccnxp_handle_tx(&s->port[i]);
398 }
399 }
400
401 mutex_unlock(&s->sccnxp_mutex);
402
403 return IRQ_HANDLED;
404}
405
406static void sccnxp_start_tx(struct uart_port *port)
407{
408 struct sccnxp_port *s = dev_get_drvdata(port->dev);
409
410 mutex_lock(&s->sccnxp_mutex);
411
412 /* Set direction to output */
413 if (s->flags & SCCNXP_HAVE_IO)
414 sccnxp_set_bit(port, DIR_OP, 1);
415
416 sccnxp_enable_irq(port, IMR_TXRDY);
417
418 mutex_unlock(&s->sccnxp_mutex);
419}
420
421static void sccnxp_stop_tx(struct uart_port *port)
422{
423 /* Do nothing */
424}
425
426static void sccnxp_stop_rx(struct uart_port *port)
427{
428 struct sccnxp_port *s = dev_get_drvdata(port->dev);
429
430 mutex_lock(&s->sccnxp_mutex);
431 sccnxp_port_write(port, SCCNXP_CR_REG, CR_RX_DISABLE);
432 mutex_unlock(&s->sccnxp_mutex);
433}
434
435static unsigned int sccnxp_tx_empty(struct uart_port *port)
436{
437 u8 val;
438 struct sccnxp_port *s = dev_get_drvdata(port->dev);
439
440 mutex_lock(&s->sccnxp_mutex);
441 val = sccnxp_port_read(port, SCCNXP_SR_REG);
442 mutex_unlock(&s->sccnxp_mutex);
443
444 return (val & SR_TXEMT) ? TIOCSER_TEMT : 0;
445}
446
447static void sccnxp_enable_ms(struct uart_port *port)
448{
449 /* Do nothing */
450}
451
452static void sccnxp_set_mctrl(struct uart_port *port, unsigned int mctrl)
453{
454 struct sccnxp_port *s = dev_get_drvdata(port->dev);
455
456 if (!(s->flags & SCCNXP_HAVE_IO))
457 return;
458
459 mutex_lock(&s->sccnxp_mutex);
460
461 sccnxp_set_bit(port, DTR_OP, mctrl & TIOCM_DTR);
462 sccnxp_set_bit(port, RTS_OP, mctrl & TIOCM_RTS);
463
464 mutex_unlock(&s->sccnxp_mutex);
465}
466
467static unsigned int sccnxp_get_mctrl(struct uart_port *port)
468{
469 u8 bitmask, ipr;
470 struct sccnxp_port *s = dev_get_drvdata(port->dev);
471 unsigned int mctrl = TIOCM_DSR | TIOCM_CTS | TIOCM_CAR;
472
473 if (!(s->flags & SCCNXP_HAVE_IO))
474 return mctrl;
475
476 mutex_lock(&s->sccnxp_mutex);
477
478 ipr = ~sccnxp_read(port, SCCNXP_IPCR_REG);
479
480 if (s->pdata.mctrl_cfg[port->line] & MCTRL_MASK(DSR_IP)) {
481 bitmask = 1 << MCTRL_IBIT(s->pdata.mctrl_cfg[port->line],
482 DSR_IP);
483 mctrl &= ~TIOCM_DSR;
484 mctrl |= (ipr & bitmask) ? TIOCM_DSR : 0;
485 }
486 if (s->pdata.mctrl_cfg[port->line] & MCTRL_MASK(CTS_IP)) {
487 bitmask = 1 << MCTRL_IBIT(s->pdata.mctrl_cfg[port->line],
488 CTS_IP);
489 mctrl &= ~TIOCM_CTS;
490 mctrl |= (ipr & bitmask) ? TIOCM_CTS : 0;
491 }
492 if (s->pdata.mctrl_cfg[port->line] & MCTRL_MASK(DCD_IP)) {
493 bitmask = 1 << MCTRL_IBIT(s->pdata.mctrl_cfg[port->line],
494 DCD_IP);
495 mctrl &= ~TIOCM_CAR;
496 mctrl |= (ipr & bitmask) ? TIOCM_CAR : 0;
497 }
498 if (s->pdata.mctrl_cfg[port->line] & MCTRL_MASK(RNG_IP)) {
499 bitmask = 1 << MCTRL_IBIT(s->pdata.mctrl_cfg[port->line],
500 RNG_IP);
501 mctrl &= ~TIOCM_RNG;
502 mctrl |= (ipr & bitmask) ? TIOCM_RNG : 0;
503 }
504
505 mutex_unlock(&s->sccnxp_mutex);
506
507 return mctrl;
508}
509
510static void sccnxp_break_ctl(struct uart_port *port, int break_state)
511{
512 struct sccnxp_port *s = dev_get_drvdata(port->dev);
513
514 mutex_lock(&s->sccnxp_mutex);
515 sccnxp_port_write(port, SCCNXP_CR_REG, break_state ?
516 CR_CMD_START_BREAK : CR_CMD_STOP_BREAK);
517 mutex_unlock(&s->sccnxp_mutex);
518}
519
520static void sccnxp_set_termios(struct uart_port *port,
521 struct ktermios *termios, struct ktermios *old)
522{
523 struct sccnxp_port *s = dev_get_drvdata(port->dev);
524 u8 mr1, mr2;
525 int baud;
526
527 mutex_lock(&s->sccnxp_mutex);
528
529 /* Mask termios capabilities we don't support */
530 termios->c_cflag &= ~CMSPAR;
531 termios->c_iflag &= ~(IXON | IXOFF | IXANY);
532
533 /* Disable RX & TX, reset break condition, status and FIFOs */
534 sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_RX_RESET |
535 CR_RX_DISABLE | CR_TX_DISABLE);
536 sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_TX_RESET);
537 sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_STATUS_RESET);
538 sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_BREAK_RESET);
539
540 /* Word size */
541 switch (termios->c_cflag & CSIZE) {
542 case CS5:
543 mr1 = MR1_BITS_5;
544 break;
545 case CS6:
546 mr1 = MR1_BITS_6;
547 break;
548 case CS7:
549 mr1 = MR1_BITS_7;
550 break;
551 default:
552 case CS8:
553 mr1 = MR1_BITS_8;
554 break;
555 }
556
557 /* Parity */
558 if (termios->c_cflag & PARENB) {
559 if (termios->c_cflag & PARODD)
560 mr1 |= MR1_PAR_ODD;
561 } else
562 mr1 |= MR1_PAR_NO;
563
564 /* Stop bits */
565 mr2 = (termios->c_cflag & CSTOPB) ? MR2_STOP2 : MR2_STOP1;
566
567 /* Update desired format */
568 sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_MRPTR1);
569 sccnxp_port_write(port, SCCNXP_MR_REG, mr1);
570 sccnxp_port_write(port, SCCNXP_MR_REG, mr2);
571
572 /* Set read status mask */
573 port->read_status_mask = SR_OVR;
574 if (termios->c_iflag & INPCK)
575 port->read_status_mask |= SR_PE | SR_FE;
576 if (termios->c_iflag & (BRKINT | PARMRK))
577 port->read_status_mask |= SR_BRK;
578
579 /* Set status ignore mask */
580 port->ignore_status_mask = 0;
581 if (termios->c_iflag & IGNBRK)
582 port->ignore_status_mask |= SR_BRK;
583 if (!(termios->c_cflag & CREAD))
584 port->ignore_status_mask |= SR_PE | SR_OVR | SR_FE | SR_BRK;
585
586 /* Setup baudrate */
587 baud = uart_get_baud_rate(port, termios, old, 50,
588 (s->flags & SCCNXP_HAVE_MR0) ?
589 230400 : 38400);
590 sccnxp_set_baud(port, baud);
591
592 /* Update timeout according to new baud rate */
593 uart_update_timeout(port, termios->c_cflag, baud);
594
595 /* Enable RX & TX */
596 sccnxp_port_write(port, SCCNXP_CR_REG, CR_RX_ENABLE | CR_TX_ENABLE);
597
598 mutex_unlock(&s->sccnxp_mutex);
599}
600
601static int sccnxp_startup(struct uart_port *port)
602{
603 struct sccnxp_port *s = dev_get_drvdata(port->dev);
604
605 mutex_lock(&s->sccnxp_mutex);
606
607 if (s->flags & SCCNXP_HAVE_IO) {
608 /* Outputs are controlled manually */
609 sccnxp_write(port, SCCNXP_OPCR_REG, 0);
610 }
611
612 /* Reset break condition, status and FIFOs */
613 sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_RX_RESET);
614 sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_TX_RESET);
615 sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_STATUS_RESET);
616 sccnxp_port_write(port, SCCNXP_CR_REG, CR_CMD_BREAK_RESET);
617
618 /* Enable RX & TX */
619 sccnxp_port_write(port, SCCNXP_CR_REG, CR_RX_ENABLE | CR_TX_ENABLE);
620
621 /* Enable RX interrupt */
622 sccnxp_enable_irq(port, IMR_RXRDY);
623
624 mutex_unlock(&s->sccnxp_mutex);
625
626 return 0;
627}
628
629static void sccnxp_shutdown(struct uart_port *port)
630{
631 struct sccnxp_port *s = dev_get_drvdata(port->dev);
632
633 mutex_lock(&s->sccnxp_mutex);
634
635 /* Disable interrupts */
636 sccnxp_disable_irq(port, IMR_TXRDY | IMR_RXRDY);
637
638 /* Disable TX & RX */
639 sccnxp_port_write(port, SCCNXP_CR_REG, CR_RX_DISABLE | CR_TX_DISABLE);
640
641 /* Leave direction to input */
642 if (s->flags & SCCNXP_HAVE_IO)
643 sccnxp_set_bit(port, DIR_OP, 0);
644
645 mutex_unlock(&s->sccnxp_mutex);
646}
647
648static const char *sccnxp_type(struct uart_port *port)
649{
650 struct sccnxp_port *s = dev_get_drvdata(port->dev);
651
652 return (port->type == PORT_SC26XX) ? s->name : NULL;
653}
654
655static void sccnxp_release_port(struct uart_port *port)
656{
657 /* Do nothing */
658}
659
660static int sccnxp_request_port(struct uart_port *port)
661{
662 /* Do nothing */
663 return 0;
664}
665
666static void sccnxp_config_port(struct uart_port *port, int flags)
667{
668 if (flags & UART_CONFIG_TYPE)
669 port->type = PORT_SC26XX;
670}
671
672static int sccnxp_verify_port(struct uart_port *port, struct serial_struct *s)
673{
674 if ((s->type == PORT_UNKNOWN) || (s->type == PORT_SC26XX))
675 return 0;
676 if (s->irq == port->irq)
677 return 0;
678
679 return -EINVAL;
680}
681
682static const struct uart_ops sccnxp_ops = {
683 .tx_empty = sccnxp_tx_empty,
684 .set_mctrl = sccnxp_set_mctrl,
685 .get_mctrl = sccnxp_get_mctrl,
686 .stop_tx = sccnxp_stop_tx,
687 .start_tx = sccnxp_start_tx,
688 .stop_rx = sccnxp_stop_rx,
689 .enable_ms = sccnxp_enable_ms,
690 .break_ctl = sccnxp_break_ctl,
691 .startup = sccnxp_startup,
692 .shutdown = sccnxp_shutdown,
693 .set_termios = sccnxp_set_termios,
694 .type = sccnxp_type,
695 .release_port = sccnxp_release_port,
696 .request_port = sccnxp_request_port,
697 .config_port = sccnxp_config_port,
698 .verify_port = sccnxp_verify_port,
699};
700
701#ifdef CONFIG_SERIAL_SCCNXP_CONSOLE
702static void sccnxp_console_putchar(struct uart_port *port, int c)
703{
704 int tryes = 100000;
705
706 while (tryes--) {
707 if (sccnxp_port_read(port, SCCNXP_SR_REG) & SR_TXRDY) {
708 sccnxp_port_write(port, SCCNXP_THR_REG, c);
709 break;
710 }
711 barrier();
712 }
713}
714
715static void sccnxp_console_write(struct console *co, const char *c, unsigned n)
716{
717 struct sccnxp_port *s = (struct sccnxp_port *)co->data;
718 struct uart_port *port = &s->port[co->index];
719
720 mutex_lock(&s->sccnxp_mutex);
721 uart_console_write(port, c, n, sccnxp_console_putchar);
722 mutex_unlock(&s->sccnxp_mutex);
723}
724
725static int sccnxp_console_setup(struct console *co, char *options)
726{
727 struct sccnxp_port *s = (struct sccnxp_port *)co->data;
728 struct uart_port *port = &s->port[(co->index > 0) ? co->index : 0];
729 int baud = 9600, bits = 8, parity = 'n', flow = 'n';
730
731 if (options)
732 uart_parse_options(options, &baud, &parity, &bits, &flow);
733
734 return uart_set_options(port, co, baud, parity, bits, flow);
735}
736#endif
737
738static int __devinit sccnxp_probe(struct platform_device *pdev)
739{
740 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
741 int chiptype = pdev->id_entry->driver_data;
742 struct sccnxp_pdata *pdata = dev_get_platdata(&pdev->dev);
743 int i, ret, fifosize, freq_min, freq_max;
744 struct sccnxp_port *s;
745 void __iomem *membase;
746
747 if (!res) {
748 dev_err(&pdev->dev, "Missing memory resource data\n");
749 return -EADDRNOTAVAIL;
750 }
751
752 dev_set_name(&pdev->dev, SCCNXP_NAME);
753
754 s = devm_kzalloc(&pdev->dev, sizeof(struct sccnxp_port), GFP_KERNEL);
755 if (!s) {
756 dev_err(&pdev->dev, "Error allocating port structure\n");
757 return -ENOMEM;
758 }
759 platform_set_drvdata(pdev, s);
760
761 mutex_init(&s->sccnxp_mutex);
762
763 /* Individual chip settings */
764 switch (chiptype) {
765 case SCCNXP_TYPE_SC2681:
766 s->name = "SC2681";
767 s->uart.nr = 2;
768 s->freq_std = 3686400;
769 s->addr_mask = 0x0f;
770 s->flags = SCCNXP_HAVE_IO;
771 fifosize = 3;
772 freq_min = 1000000;
773 freq_max = 4000000;
774 break;
775 case SCCNXP_TYPE_SC2691:
776 s->name = "SC2691";
777 s->uart.nr = 1;
778 s->freq_std = 3686400;
779 s->addr_mask = 0x07;
780 s->flags = 0;
781 fifosize = 3;
782 freq_min = 1000000;
783 freq_max = 4000000;
784 break;
785 case SCCNXP_TYPE_SC2692:
786 s->name = "SC2692";
787 s->uart.nr = 2;
788 s->freq_std = 3686400;
789 s->addr_mask = 0x0f;
790 s->flags = SCCNXP_HAVE_IO;
791 fifosize = 3;
792 freq_min = 1000000;
793 freq_max = 4000000;
794 break;
795 case SCCNXP_TYPE_SC2891:
796 s->name = "SC2891";
797 s->uart.nr = 1;
798 s->freq_std = 3686400;
799 s->addr_mask = 0x0f;
800 s->flags = SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0;
801 fifosize = 16;
802 freq_min = 100000;
803 freq_max = 8000000;
804 break;
805 case SCCNXP_TYPE_SC2892:
806 s->name = "SC2892";
807 s->uart.nr = 2;
808 s->freq_std = 3686400;
809 s->addr_mask = 0x0f;
810 s->flags = SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0;
811 fifosize = 16;
812 freq_min = 100000;
813 freq_max = 8000000;
814 break;
815 case SCCNXP_TYPE_SC28202:
816 s->name = "SC28202";
817 s->uart.nr = 2;
818 s->freq_std = 14745600;
819 s->addr_mask = 0x7f;
820 s->flags = SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0;
821 fifosize = 256;
822 freq_min = 1000000;
823 freq_max = 50000000;
824 break;
825 case SCCNXP_TYPE_SC68681:
826 s->name = "SC68681";
827 s->uart.nr = 2;
828 s->freq_std = 3686400;
829 s->addr_mask = 0x0f;
830 s->flags = SCCNXP_HAVE_IO;
831 fifosize = 3;
832 freq_min = 1000000;
833 freq_max = 4000000;
834 break;
835 case SCCNXP_TYPE_SC68692:
836 s->name = "SC68692";
837 s->uart.nr = 2;
838 s->freq_std = 3686400;
839 s->addr_mask = 0x0f;
840 s->flags = SCCNXP_HAVE_IO;
841 fifosize = 3;
842 freq_min = 1000000;
843 freq_max = 4000000;
844 break;
845 default:
846 dev_err(&pdev->dev, "Unsupported chip type %i\n", chiptype);
847 ret = -ENOTSUPP;
848 goto err_out;
849 }
850
851 if (!pdata) {
852 dev_warn(&pdev->dev,
853 "No platform data supplied, using defaults\n");
854 s->pdata.frequency = s->freq_std;
855 } else
856 memcpy(&s->pdata, pdata, sizeof(struct sccnxp_pdata));
857
858 s->irq = platform_get_irq(pdev, 0);
859 if (s->irq <= 0) {
860 dev_err(&pdev->dev, "Missing irq resource data\n");
861 ret = -ENXIO;
862 goto err_out;
863 }
864
865 /* Check input frequency */
866 if ((s->pdata.frequency < freq_min) ||
867 (s->pdata.frequency > freq_max)) {
868 dev_err(&pdev->dev, "Frequency out of bounds\n");
869 ret = -EINVAL;
870 goto err_out;
871 }
872
873 membase = devm_request_and_ioremap(&pdev->dev, res);
874 if (!membase) {
875 dev_err(&pdev->dev, "Failed to ioremap\n");
876 ret = -EIO;
877 goto err_out;
878 }
879
880 s->uart.owner = THIS_MODULE;
881 s->uart.dev_name = "ttySC";
882 s->uart.major = SCCNXP_MAJOR;
883 s->uart.minor = SCCNXP_MINOR;
884#ifdef CONFIG_SERIAL_SCCNXP_CONSOLE
885 s->uart.cons = &s->console;
886 s->uart.cons->device = uart_console_device;
887 s->uart.cons->write = sccnxp_console_write;
888 s->uart.cons->setup = sccnxp_console_setup;
889 s->uart.cons->flags = CON_PRINTBUFFER;
890 s->uart.cons->index = -1;
891 s->uart.cons->data = s;
892 strcpy(s->uart.cons->name, "ttySC");
893#endif
894 ret = uart_register_driver(&s->uart);
895 if (ret) {
896 dev_err(&pdev->dev, "Registering UART driver failed\n");
897 goto err_out;
898 }
899
900 for (i = 0; i < s->uart.nr; i++) {
901 s->port[i].line = i;
902 s->port[i].dev = &pdev->dev;
903 s->port[i].irq = s->irq;
904 s->port[i].type = PORT_SC26XX;
905 s->port[i].fifosize = fifosize;
906 s->port[i].flags = UPF_SKIP_TEST | UPF_FIXED_TYPE;
907 s->port[i].iotype = UPIO_MEM;
908 s->port[i].mapbase = res->start;
909 s->port[i].membase = membase;
910 s->port[i].regshift = s->pdata.reg_shift;
911 s->port[i].uartclk = s->pdata.frequency;
912 s->port[i].ops = &sccnxp_ops;
913 uart_add_one_port(&s->uart, &s->port[i]);
914 /* Set direction to input */
915 if (s->flags & SCCNXP_HAVE_IO)
916 sccnxp_set_bit(&s->port[i], DIR_OP, 0);
917 }
918
919 /* Disable interrupts */
920 s->imr = 0;
921 sccnxp_write(&s->port[0], SCCNXP_IMR_REG, 0);
922
923 /* Board specific configure */
924 if (s->pdata.init)
925 s->pdata.init();
926
927 ret = devm_request_threaded_irq(&pdev->dev, s->irq, NULL, sccnxp_ist,
928 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
929 dev_name(&pdev->dev), s);
930 if (!ret)
931 return 0;
932
933 dev_err(&pdev->dev, "Unable to reguest IRQ %i\n", s->irq);
934
935err_out:
936 platform_set_drvdata(pdev, NULL);
937
938 return ret;
939}
940
941static int __devexit sccnxp_remove(struct platform_device *pdev)
942{
943 int i;
944 struct sccnxp_port *s = platform_get_drvdata(pdev);
945
946 devm_free_irq(&pdev->dev, s->irq, s);
947
948 for (i = 0; i < s->uart.nr; i++)
949 uart_remove_one_port(&s->uart, &s->port[i]);
950
951 uart_unregister_driver(&s->uart);
952 platform_set_drvdata(pdev, NULL);
953
954 if (s->pdata.exit)
955 s->pdata.exit();
956
957 return 0;
958}
959
960static const struct platform_device_id sccnxp_id_table[] = {
961 { "sc2681", SCCNXP_TYPE_SC2681 },
962 { "sc2691", SCCNXP_TYPE_SC2691 },
963 { "sc2692", SCCNXP_TYPE_SC2692 },
964 { "sc2891", SCCNXP_TYPE_SC2891 },
965 { "sc2892", SCCNXP_TYPE_SC2892 },
966 { "sc28202", SCCNXP_TYPE_SC28202 },
967 { "sc68681", SCCNXP_TYPE_SC68681 },
968 { "sc68692", SCCNXP_TYPE_SC68692 },
969};
970MODULE_DEVICE_TABLE(platform, sccnxp_id_table);
971
972static struct platform_driver sccnxp_uart_driver = {
973 .driver = {
974 .name = SCCNXP_NAME,
975 .owner = THIS_MODULE,
976 },
977 .probe = sccnxp_probe,
978 .remove = __devexit_p(sccnxp_remove),
979 .id_table = sccnxp_id_table,
980};
981module_platform_driver(sccnxp_uart_driver);
982
983MODULE_LICENSE("GPL v2");
984MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");
985MODULE_DESCRIPTION("SCCNXP serial driver");