2 * Serial Port driver for a NWP uart device
4 * Copyright (C) 2008 IBM Corp., Benjamin Krill <ben@codiert.org>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
12 #include <linux/init.h>
13 #include <linux/export.h>
14 #include <linux/console.h>
15 #include <linux/serial.h>
16 #include <linux/serial_reg.h>
17 #include <linux/serial_core.h>
18 #include <linux/tty.h>
19 #include <linux/tty_flip.h>
20 #include <linux/irqreturn.h>
21 #include <linux/mutex.h>
22 #include <linux/of_platform.h>
23 #include <linux/of_device.h>
24 #include <linux/nwpserial.h>
28 #define NWPSERIAL_NR 2
30 #define NWPSERIAL_STATUS_RXVALID 0x1
31 #define NWPSERIAL_STATUS_TXFULL 0x2
33 struct nwpserial_port
{
34 struct uart_port port
;
40 static DEFINE_MUTEX(nwpserial_mutex
);
41 static struct nwpserial_port nwpserial_ports
[NWPSERIAL_NR
];
43 static void wait_for_bits(struct nwpserial_port
*up
, int bits
)
45 unsigned int status
, tmout
= 10000;
47 /* Wait up to 10ms for the character(s) to be sent. */
49 status
= dcr_read(up
->dcr_host
, UART_LSR
);
54 } while ((status
& bits
) != bits
);
57 #ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE
58 static void nwpserial_console_putchar(struct uart_port
*port
, int c
)
60 struct nwpserial_port
*up
;
61 up
= container_of(port
, struct nwpserial_port
, port
);
62 /* check if tx buffer is full */
63 wait_for_bits(up
, UART_LSR_THRE
);
64 dcr_write(up
->dcr_host
, UART_TX
, c
);
69 nwpserial_console_write(struct console
*co
, const char *s
, unsigned int count
)
71 struct nwpserial_port
*up
= &nwpserial_ports
[co
->index
];
76 locked
= spin_trylock_irqsave(&up
->port
.lock
, flags
);
78 spin_lock_irqsave(&up
->port
.lock
, flags
);
80 /* save and disable interrupt */
81 up
->ier
= dcr_read(up
->dcr_host
, UART_IER
);
82 dcr_write(up
->dcr_host
, UART_IER
, up
->ier
& ~UART_IER_RDI
);
84 uart_console_write(&up
->port
, s
, count
, nwpserial_console_putchar
);
86 /* wait for transmitter to become empty */
87 while ((dcr_read(up
->dcr_host
, UART_LSR
) & UART_LSR_THRE
) == 0)
90 /* restore interrupt state */
91 dcr_write(up
->dcr_host
, UART_IER
, up
->ier
);
94 spin_unlock_irqrestore(&up
->port
.lock
, flags
);
97 static struct uart_driver nwpserial_reg
;
98 static struct console nwpserial_console
= {
100 .write
= nwpserial_console_write
,
101 .device
= uart_console_device
,
102 .flags
= CON_PRINTBUFFER
,
104 .data
= &nwpserial_reg
,
106 #define NWPSERIAL_CONSOLE (&nwpserial_console)
108 #define NWPSERIAL_CONSOLE NULL
109 #endif /* CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE */
111 /**************************************************************************/
113 static int nwpserial_request_port(struct uart_port
*port
)
118 static void nwpserial_release_port(struct uart_port
*port
)
123 static void nwpserial_config_port(struct uart_port
*port
, int flags
)
125 port
->type
= PORT_NWPSERIAL
;
128 static irqreturn_t
nwpserial_interrupt(int irq
, void *dev_id
)
130 struct nwpserial_port
*up
= dev_id
;
131 struct tty_port
*port
= &up
->port
.state
->port
;
136 spin_lock(&up
->port
.lock
);
138 /* check if the uart was the interrupt source. */
139 iir
= dcr_read(up
->dcr_host
, UART_IIR
);
146 up
->port
.icount
.rx
++;
147 ch
= dcr_read(up
->dcr_host
, UART_RX
);
148 if (up
->port
.ignore_status_mask
!= NWPSERIAL_STATUS_RXVALID
)
149 tty_insert_flip_char(port
, ch
, TTY_NORMAL
);
150 } while (dcr_read(up
->dcr_host
, UART_LSR
) & UART_LSR_DR
);
152 spin_unlock(&up
->port
.lock
);
153 tty_flip_buffer_push(port
);
154 spin_lock(&up
->port
.lock
);
158 /* clear interrupt */
159 dcr_write(up
->dcr_host
, UART_IIR
, 1);
161 spin_unlock(&up
->port
.lock
);
165 static int nwpserial_startup(struct uart_port
*port
)
167 struct nwpserial_port
*up
;
170 up
= container_of(port
, struct nwpserial_port
, port
);
172 /* disable flow control by default */
173 up
->mcr
= dcr_read(up
->dcr_host
, UART_MCR
) & ~UART_MCR_AFE
;
174 dcr_write(up
->dcr_host
, UART_MCR
, up
->mcr
);
176 /* register interrupt handler */
177 err
= request_irq(up
->port
.irq
, nwpserial_interrupt
,
178 IRQF_SHARED
, "nwpserial", up
);
182 /* enable interrupts */
183 up
->ier
= UART_IER_RDI
;
184 dcr_write(up
->dcr_host
, UART_IER
, up
->ier
);
186 /* enable receiving */
187 up
->port
.ignore_status_mask
&= ~NWPSERIAL_STATUS_RXVALID
;
192 static void nwpserial_shutdown(struct uart_port
*port
)
194 struct nwpserial_port
*up
;
195 up
= container_of(port
, struct nwpserial_port
, port
);
197 /* disable receiving */
198 up
->port
.ignore_status_mask
|= NWPSERIAL_STATUS_RXVALID
;
200 /* disable interrupts from this port */
202 dcr_write(up
->dcr_host
, UART_IER
, up
->ier
);
205 free_irq(up
->port
.irq
, up
);
208 static int nwpserial_verify_port(struct uart_port
*port
,
209 struct serial_struct
*ser
)
214 static const char *nwpserial_type(struct uart_port
*port
)
216 return port
->type
== PORT_NWPSERIAL
? "nwpserial" : NULL
;
219 static void nwpserial_set_termios(struct uart_port
*port
,
220 struct ktermios
*termios
, struct ktermios
*old
)
222 struct nwpserial_port
*up
;
223 up
= container_of(port
, struct nwpserial_port
, port
);
225 up
->port
.read_status_mask
= NWPSERIAL_STATUS_RXVALID
226 | NWPSERIAL_STATUS_TXFULL
;
228 up
->port
.ignore_status_mask
= 0;
229 /* ignore all characters if CREAD is not set */
230 if ((termios
->c_cflag
& CREAD
) == 0)
231 up
->port
.ignore_status_mask
|= NWPSERIAL_STATUS_RXVALID
;
233 /* Copy back the old hardware settings */
235 tty_termios_copy_hw(termios
, old
);
238 static void nwpserial_break_ctl(struct uart_port
*port
, int ctl
)
243 static void nwpserial_enable_ms(struct uart_port
*port
)
248 static void nwpserial_stop_rx(struct uart_port
*port
)
250 struct nwpserial_port
*up
;
251 up
= container_of(port
, struct nwpserial_port
, port
);
252 /* don't forward any more data (like !CREAD) */
253 up
->port
.ignore_status_mask
= NWPSERIAL_STATUS_RXVALID
;
256 static void nwpserial_putchar(struct nwpserial_port
*up
, unsigned char c
)
258 /* check if tx buffer is full */
259 wait_for_bits(up
, UART_LSR_THRE
);
260 dcr_write(up
->dcr_host
, UART_TX
, c
);
261 up
->port
.icount
.tx
++;
264 static void nwpserial_start_tx(struct uart_port
*port
)
266 struct nwpserial_port
*up
;
267 struct circ_buf
*xmit
;
268 up
= container_of(port
, struct nwpserial_port
, port
);
269 xmit
= &up
->port
.state
->xmit
;
272 nwpserial_putchar(up
, up
->port
.x_char
);
276 while (!(uart_circ_empty(xmit
) || uart_tx_stopped(&up
->port
))) {
277 nwpserial_putchar(up
, xmit
->buf
[xmit
->tail
]);
278 xmit
->tail
= (xmit
->tail
+ 1) & (UART_XMIT_SIZE
-1);
282 static unsigned int nwpserial_get_mctrl(struct uart_port
*port
)
287 static void nwpserial_set_mctrl(struct uart_port
*port
, unsigned int mctrl
)
292 static void nwpserial_stop_tx(struct uart_port
*port
)
297 static unsigned int nwpserial_tx_empty(struct uart_port
*port
)
299 struct nwpserial_port
*up
;
302 up
= container_of(port
, struct nwpserial_port
, port
);
304 spin_lock_irqsave(&up
->port
.lock
, flags
);
305 ret
= dcr_read(up
->dcr_host
, UART_LSR
);
306 spin_unlock_irqrestore(&up
->port
.lock
, flags
);
308 return ret
& UART_LSR_TEMT
? TIOCSER_TEMT
: 0;
311 static struct uart_ops nwpserial_pops
= {
312 .tx_empty
= nwpserial_tx_empty
,
313 .set_mctrl
= nwpserial_set_mctrl
,
314 .get_mctrl
= nwpserial_get_mctrl
,
315 .stop_tx
= nwpserial_stop_tx
,
316 .start_tx
= nwpserial_start_tx
,
317 .stop_rx
= nwpserial_stop_rx
,
318 .enable_ms
= nwpserial_enable_ms
,
319 .break_ctl
= nwpserial_break_ctl
,
320 .startup
= nwpserial_startup
,
321 .shutdown
= nwpserial_shutdown
,
322 .set_termios
= nwpserial_set_termios
,
323 .type
= nwpserial_type
,
324 .release_port
= nwpserial_release_port
,
325 .request_port
= nwpserial_request_port
,
326 .config_port
= nwpserial_config_port
,
327 .verify_port
= nwpserial_verify_port
,
330 static struct uart_driver nwpserial_reg
= {
331 .owner
= THIS_MODULE
,
332 .driver_name
= "nwpserial",
337 .cons
= NWPSERIAL_CONSOLE
,
340 int nwpserial_register_port(struct uart_port
*port
)
342 struct nwpserial_port
*up
= NULL
;
345 static int first
= 1;
348 struct device_node
*dn
;
350 mutex_lock(&nwpserial_mutex
);
352 dn
= port
->dev
->of_node
;
357 dcr_base
= dcr_resource_start(dn
, 0);
359 /* find matching entry */
360 for (i
= 0; i
< NWPSERIAL_NR
; i
++)
361 if (nwpserial_ports
[i
].port
.iobase
== dcr_base
) {
362 up
= &nwpserial_ports
[i
];
366 /* we didn't find a mtching entry, search for a free port */
368 for (i
= 0; i
< NWPSERIAL_NR
; i
++)
369 if (nwpserial_ports
[i
].port
.type
== PORT_UNKNOWN
&&
370 nwpserial_ports
[i
].port
.iobase
== 0) {
371 up
= &nwpserial_ports
[i
];
381 uart_register_driver(&nwpserial_reg
);
384 up
->port
.membase
= port
->membase
;
385 up
->port
.irq
= port
->irq
;
386 up
->port
.uartclk
= port
->uartclk
;
387 up
->port
.fifosize
= port
->fifosize
;
388 up
->port
.regshift
= port
->regshift
;
389 up
->port
.iotype
= port
->iotype
;
390 up
->port
.flags
= port
->flags
;
391 up
->port
.mapbase
= port
->mapbase
;
392 up
->port
.private_data
= port
->private_data
;
395 up
->port
.dev
= port
->dev
;
397 if (up
->port
.iobase
!= dcr_base
) {
398 up
->port
.ops
= &nwpserial_pops
;
399 up
->port
.fifosize
= 16;
401 spin_lock_init(&up
->port
.lock
);
403 up
->port
.iobase
= dcr_base
;
404 dcr_len
= dcr_resource_len(dn
, 0);
406 up
->dcr_host
= dcr_map(dn
, dcr_base
, dcr_len
);
407 if (!DCR_MAP_OK(up
->dcr_host
)) {
408 printk(KERN_ERR
"Cannot map DCR resources for NWPSERIAL");
413 ret
= uart_add_one_port(&nwpserial_reg
, &up
->port
);
418 mutex_unlock(&nwpserial_mutex
);
422 EXPORT_SYMBOL(nwpserial_register_port
);
424 void nwpserial_unregister_port(int line
)
426 struct nwpserial_port
*up
= &nwpserial_ports
[line
];
427 mutex_lock(&nwpserial_mutex
);
428 uart_remove_one_port(&nwpserial_reg
, &up
->port
);
430 up
->port
.type
= PORT_UNKNOWN
;
432 mutex_unlock(&nwpserial_mutex
);
434 EXPORT_SYMBOL(nwpserial_unregister_port
);
436 #ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE
437 static int __init
nwpserial_console_init(void)
439 struct nwpserial_port
*up
= NULL
;
440 struct device_node
*dn
;
446 /* search for a free port */
447 for (i
= 0; i
< NWPSERIAL_NR
; i
++)
448 if (nwpserial_ports
[i
].port
.type
== PORT_UNKNOWN
) {
449 up
= &nwpserial_ports
[i
];
456 name
= of_get_property(of_chosen
, "linux,stdout-path", NULL
);
460 dn
= of_find_node_by_path(name
);
464 spin_lock_init(&up
->port
.lock
);
465 up
->port
.ops
= &nwpserial_pops
;
466 up
->port
.type
= PORT_NWPSERIAL
;
467 up
->port
.fifosize
= 16;
469 dcr_base
= dcr_resource_start(dn
, 0);
470 dcr_len
= dcr_resource_len(dn
, 0);
471 up
->port
.iobase
= dcr_base
;
473 up
->dcr_host
= dcr_map(dn
, dcr_base
, dcr_len
);
474 if (!DCR_MAP_OK(up
->dcr_host
)) {
475 printk("Cannot map DCR resources for SERIAL");
478 register_console(&nwpserial_console
);
481 console_initcall(nwpserial_console_init
);
482 #endif /* CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE */