1 /*
2  *  Serial Port driver for a NWP uart device
3  *
4  *    Copyright (C) 2008 IBM Corp., Benjamin Krill <ben@codiert.org>
5  *
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.
10  *
11  */
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>
25 #include <asm/prom.h>
26 #include <asm/dcr.h>
27 
28 #define NWPSERIAL_NR               2
29 
30 #define NWPSERIAL_STATUS_RXVALID 0x1
31 #define NWPSERIAL_STATUS_TXFULL  0x2
32 
33 struct nwpserial_port {
34 	struct uart_port port;
35 	dcr_host_t dcr_host;
36 	unsigned int ier;
37 	unsigned int mcr;
38 };
39 
40 static DEFINE_MUTEX(nwpserial_mutex);
41 static struct nwpserial_port nwpserial_ports[NWPSERIAL_NR];
42 
wait_for_bits(struct nwpserial_port * up,int bits)43 static void wait_for_bits(struct nwpserial_port *up, int bits)
44 {
45 	unsigned int status, tmout = 10000;
46 
47 	/* Wait up to 10ms for the character(s) to be sent. */
48 	do {
49 		status = dcr_read(up->dcr_host, UART_LSR);
50 
51 		if (--tmout == 0)
52 			break;
53 		udelay(1);
54 	} while ((status & bits) != bits);
55 }
56 
57 #ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE
nwpserial_console_putchar(struct uart_port * port,int c)58 static void nwpserial_console_putchar(struct uart_port *port, int c)
59 {
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);
65 	up->port.icount.tx++;
66 }
67 
68 static void
nwpserial_console_write(struct console * co,const char * s,unsigned int count)69 nwpserial_console_write(struct console *co, const char *s, unsigned int count)
70 {
71 	struct nwpserial_port *up = &nwpserial_ports[co->index];
72 	unsigned long flags;
73 	int locked = 1;
74 
75 	if (oops_in_progress)
76 		locked = spin_trylock_irqsave(&up->port.lock, flags);
77 	else
78 		spin_lock_irqsave(&up->port.lock, flags);
79 
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);
83 
84 	uart_console_write(&up->port, s, count, nwpserial_console_putchar);
85 
86 	/* wait for transmitter to become empty */
87 	while ((dcr_read(up->dcr_host, UART_LSR) & UART_LSR_THRE) == 0)
88 		cpu_relax();
89 
90 	/* restore interrupt state */
91 	dcr_write(up->dcr_host, UART_IER, up->ier);
92 
93 	if (locked)
94 		spin_unlock_irqrestore(&up->port.lock, flags);
95 }
96 
97 static struct uart_driver nwpserial_reg;
98 static struct console nwpserial_console = {
99 	.name		= "ttySQ",
100 	.write		= nwpserial_console_write,
101 	.device		= uart_console_device,
102 	.flags		= CON_PRINTBUFFER,
103 	.index		= -1,
104 	.data		= &nwpserial_reg,
105 };
106 #define NWPSERIAL_CONSOLE	(&nwpserial_console)
107 #else
108 #define NWPSERIAL_CONSOLE	NULL
109 #endif /* CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE */
110 
111 /**************************************************************************/
112 
nwpserial_request_port(struct uart_port * port)113 static int nwpserial_request_port(struct uart_port *port)
114 {
115 	return 0;
116 }
117 
nwpserial_release_port(struct uart_port * port)118 static void nwpserial_release_port(struct uart_port *port)
119 {
120 	/* N/A */
121 }
122 
nwpserial_config_port(struct uart_port * port,int flags)123 static void nwpserial_config_port(struct uart_port *port, int flags)
124 {
125 	port->type = PORT_NWPSERIAL;
126 }
127 
nwpserial_interrupt(int irq,void * dev_id)128 static irqreturn_t nwpserial_interrupt(int irq, void *dev_id)
129 {
130 	struct nwpserial_port *up = dev_id;
131 	struct tty_struct *tty = up->port.state->port.tty;
132 	irqreturn_t ret;
133 	unsigned int iir;
134 	unsigned char ch;
135 
136 	spin_lock(&up->port.lock);
137 
138 	/* check if the uart was the interrupt source. */
139 	iir = dcr_read(up->dcr_host, UART_IIR);
140 	if (!iir) {
141 		ret = IRQ_NONE;
142 		goto out;
143 	}
144 
145 	do {
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(tty, ch, TTY_NORMAL);
150 	} while (dcr_read(up->dcr_host, UART_LSR) & UART_LSR_DR);
151 
152 	tty_flip_buffer_push(tty);
153 	ret = IRQ_HANDLED;
154 
155 	/* clear interrupt */
156 	dcr_write(up->dcr_host, UART_IIR, 1);
157 out:
158 	spin_unlock(&up->port.lock);
159 	return ret;
160 }
161 
nwpserial_startup(struct uart_port * port)162 static int nwpserial_startup(struct uart_port *port)
163 {
164 	struct nwpserial_port *up;
165 	int err;
166 
167 	up = container_of(port, struct nwpserial_port, port);
168 
169 	/* disable flow control by default */
170 	up->mcr = dcr_read(up->dcr_host, UART_MCR) & ~UART_MCR_AFE;
171 	dcr_write(up->dcr_host, UART_MCR, up->mcr);
172 
173 	/* register interrupt handler */
174 	err = request_irq(up->port.irq, nwpserial_interrupt,
175 			IRQF_SHARED, "nwpserial", up);
176 	if (err)
177 		return err;
178 
179 	/* enable interrupts */
180 	up->ier = UART_IER_RDI;
181 	dcr_write(up->dcr_host, UART_IER, up->ier);
182 
183 	/* enable receiving */
184 	up->port.ignore_status_mask &= ~NWPSERIAL_STATUS_RXVALID;
185 
186 	return 0;
187 }
188 
nwpserial_shutdown(struct uart_port * port)189 static void nwpserial_shutdown(struct uart_port *port)
190 {
191 	struct nwpserial_port *up;
192 	up = container_of(port, struct nwpserial_port, port);
193 
194 	/* disable receiving */
195 	up->port.ignore_status_mask |= NWPSERIAL_STATUS_RXVALID;
196 
197 	/* disable interrupts from this port */
198 	up->ier = 0;
199 	dcr_write(up->dcr_host, UART_IER, up->ier);
200 
201 	/* free irq */
202 	free_irq(up->port.irq, port);
203 }
204 
nwpserial_verify_port(struct uart_port * port,struct serial_struct * ser)205 static int nwpserial_verify_port(struct uart_port *port,
206 			struct serial_struct *ser)
207 {
208 	return -EINVAL;
209 }
210 
nwpserial_type(struct uart_port * port)211 static const char *nwpserial_type(struct uart_port *port)
212 {
213 	return port->type == PORT_NWPSERIAL ? "nwpserial" : NULL;
214 }
215 
nwpserial_set_termios(struct uart_port * port,struct ktermios * termios,struct ktermios * old)216 static void nwpserial_set_termios(struct uart_port *port,
217 			struct ktermios *termios, struct ktermios *old)
218 {
219 	struct nwpserial_port *up;
220 	up = container_of(port, struct nwpserial_port, port);
221 
222 	up->port.read_status_mask = NWPSERIAL_STATUS_RXVALID
223 				| NWPSERIAL_STATUS_TXFULL;
224 
225 	up->port.ignore_status_mask = 0;
226 	/* ignore all characters if CREAD is not set */
227 	if ((termios->c_cflag & CREAD) == 0)
228 		up->port.ignore_status_mask |= NWPSERIAL_STATUS_RXVALID;
229 
230 	/* Copy back the old hardware settings */
231 	if (old)
232 		tty_termios_copy_hw(termios, old);
233 }
234 
nwpserial_break_ctl(struct uart_port * port,int ctl)235 static void nwpserial_break_ctl(struct uart_port *port, int ctl)
236 {
237 	/* N/A */
238 }
239 
nwpserial_enable_ms(struct uart_port * port)240 static void nwpserial_enable_ms(struct uart_port *port)
241 {
242 	/* N/A */
243 }
244 
nwpserial_stop_rx(struct uart_port * port)245 static void nwpserial_stop_rx(struct uart_port *port)
246 {
247 	struct nwpserial_port *up;
248 	up = container_of(port, struct nwpserial_port, port);
249 	/* don't forward any more data (like !CREAD) */
250 	up->port.ignore_status_mask = NWPSERIAL_STATUS_RXVALID;
251 }
252 
nwpserial_putchar(struct nwpserial_port * up,unsigned char c)253 static void nwpserial_putchar(struct nwpserial_port *up, unsigned char c)
254 {
255 	/* check if tx buffer is full */
256 	wait_for_bits(up, UART_LSR_THRE);
257 	dcr_write(up->dcr_host, UART_TX, c);
258 	up->port.icount.tx++;
259 }
260 
nwpserial_start_tx(struct uart_port * port)261 static void nwpserial_start_tx(struct uart_port *port)
262 {
263 	struct nwpserial_port *up;
264 	struct circ_buf *xmit;
265 	up = container_of(port, struct nwpserial_port, port);
266 	xmit  = &up->port.state->xmit;
267 
268 	if (port->x_char) {
269 		nwpserial_putchar(up, up->port.x_char);
270 		port->x_char = 0;
271 	}
272 
273 	while (!(uart_circ_empty(xmit) || uart_tx_stopped(&up->port))) {
274 		nwpserial_putchar(up, xmit->buf[xmit->tail]);
275 		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1);
276 	}
277 }
278 
nwpserial_get_mctrl(struct uart_port * port)279 static unsigned int nwpserial_get_mctrl(struct uart_port *port)
280 {
281 	return 0;
282 }
283 
nwpserial_set_mctrl(struct uart_port * port,unsigned int mctrl)284 static void nwpserial_set_mctrl(struct uart_port *port, unsigned int mctrl)
285 {
286 	/* N/A */
287 }
288 
nwpserial_stop_tx(struct uart_port * port)289 static void nwpserial_stop_tx(struct uart_port *port)
290 {
291 	/* N/A */
292 }
293 
nwpserial_tx_empty(struct uart_port * port)294 static unsigned int nwpserial_tx_empty(struct uart_port *port)
295 {
296 	struct nwpserial_port *up;
297 	unsigned long flags;
298 	int ret;
299 	up = container_of(port, struct nwpserial_port, port);
300 
301 	spin_lock_irqsave(&up->port.lock, flags);
302 	ret = dcr_read(up->dcr_host, UART_LSR);
303 	spin_unlock_irqrestore(&up->port.lock, flags);
304 
305 	return ret & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
306 }
307 
308 static struct uart_ops nwpserial_pops = {
309 	.tx_empty     = nwpserial_tx_empty,
310 	.set_mctrl    = nwpserial_set_mctrl,
311 	.get_mctrl    = nwpserial_get_mctrl,
312 	.stop_tx      = nwpserial_stop_tx,
313 	.start_tx     = nwpserial_start_tx,
314 	.stop_rx      = nwpserial_stop_rx,
315 	.enable_ms    = nwpserial_enable_ms,
316 	.break_ctl    = nwpserial_break_ctl,
317 	.startup      = nwpserial_startup,
318 	.shutdown     = nwpserial_shutdown,
319 	.set_termios  = nwpserial_set_termios,
320 	.type         = nwpserial_type,
321 	.release_port = nwpserial_release_port,
322 	.request_port = nwpserial_request_port,
323 	.config_port  = nwpserial_config_port,
324 	.verify_port  = nwpserial_verify_port,
325 };
326 
327 static struct uart_driver nwpserial_reg = {
328 	.owner       = THIS_MODULE,
329 	.driver_name = "nwpserial",
330 	.dev_name    = "ttySQ",
331 	.major       = TTY_MAJOR,
332 	.minor       = 68,
333 	.nr          = NWPSERIAL_NR,
334 	.cons        = NWPSERIAL_CONSOLE,
335 };
336 
nwpserial_register_port(struct uart_port * port)337 int nwpserial_register_port(struct uart_port *port)
338 {
339 	struct nwpserial_port *up = NULL;
340 	int ret = -1;
341 	int i;
342 	static int first = 1;
343 	int dcr_len;
344 	int dcr_base;
345 	struct device_node *dn;
346 
347 	mutex_lock(&nwpserial_mutex);
348 
349 	dn = port->dev->of_node;
350 	if (dn == NULL)
351 		goto out;
352 
353 	/* get dcr base. */
354 	dcr_base = dcr_resource_start(dn, 0);
355 
356 	/* find matching entry */
357 	for (i = 0; i < NWPSERIAL_NR; i++)
358 		if (nwpserial_ports[i].port.iobase == dcr_base) {
359 			up = &nwpserial_ports[i];
360 			break;
361 		}
362 
363 	/* we didn't find a mtching entry, search for a free port */
364 	if (up == NULL)
365 		for (i = 0; i < NWPSERIAL_NR; i++)
366 			if (nwpserial_ports[i].port.type == PORT_UNKNOWN &&
367 				nwpserial_ports[i].port.iobase == 0) {
368 				up = &nwpserial_ports[i];
369 				break;
370 			}
371 
372 	if (up == NULL) {
373 		ret = -EBUSY;
374 		goto out;
375 	}
376 
377 	if (first)
378 		uart_register_driver(&nwpserial_reg);
379 	first = 0;
380 
381 	up->port.membase      = port->membase;
382 	up->port.irq          = port->irq;
383 	up->port.uartclk      = port->uartclk;
384 	up->port.fifosize     = port->fifosize;
385 	up->port.regshift     = port->regshift;
386 	up->port.iotype       = port->iotype;
387 	up->port.flags        = port->flags;
388 	up->port.mapbase      = port->mapbase;
389 	up->port.private_data = port->private_data;
390 
391 	if (port->dev)
392 		up->port.dev = port->dev;
393 
394 	if (up->port.iobase != dcr_base) {
395 		up->port.ops          = &nwpserial_pops;
396 		up->port.fifosize     = 16;
397 
398 		spin_lock_init(&up->port.lock);
399 
400 		up->port.iobase = dcr_base;
401 		dcr_len = dcr_resource_len(dn, 0);
402 
403 		up->dcr_host = dcr_map(dn, dcr_base, dcr_len);
404 		if (!DCR_MAP_OK(up->dcr_host)) {
405 			printk(KERN_ERR "Cannot map DCR resources for NWPSERIAL");
406 			goto out;
407 		}
408 	}
409 
410 	ret = uart_add_one_port(&nwpserial_reg, &up->port);
411 	if (ret == 0)
412 		ret = up->port.line;
413 
414 out:
415 	mutex_unlock(&nwpserial_mutex);
416 
417 	return ret;
418 }
419 EXPORT_SYMBOL(nwpserial_register_port);
420 
nwpserial_unregister_port(int line)421 void nwpserial_unregister_port(int line)
422 {
423 	struct nwpserial_port *up = &nwpserial_ports[line];
424 	mutex_lock(&nwpserial_mutex);
425 	uart_remove_one_port(&nwpserial_reg, &up->port);
426 
427 	up->port.type = PORT_UNKNOWN;
428 
429 	mutex_unlock(&nwpserial_mutex);
430 }
431 EXPORT_SYMBOL(nwpserial_unregister_port);
432 
433 #ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE
nwpserial_console_init(void)434 static int __init nwpserial_console_init(void)
435 {
436 	struct nwpserial_port *up = NULL;
437 	struct device_node *dn;
438 	const char *name;
439 	int dcr_base;
440 	int dcr_len;
441 	int i;
442 
443 	/* search for a free port */
444 	for (i = 0; i < NWPSERIAL_NR; i++)
445 		if (nwpserial_ports[i].port.type == PORT_UNKNOWN) {
446 			up = &nwpserial_ports[i];
447 			break;
448 		}
449 
450 	if (up == NULL)
451 		return -1;
452 
453 	name = of_get_property(of_chosen, "linux,stdout-path", NULL);
454 	if (name == NULL)
455 		return -1;
456 
457 	dn = of_find_node_by_path(name);
458 	if (!dn)
459 		return -1;
460 
461 	spin_lock_init(&up->port.lock);
462 	up->port.ops = &nwpserial_pops;
463 	up->port.type = PORT_NWPSERIAL;
464 	up->port.fifosize = 16;
465 
466 	dcr_base = dcr_resource_start(dn, 0);
467 	dcr_len = dcr_resource_len(dn, 0);
468 	up->port.iobase = dcr_base;
469 
470 	up->dcr_host = dcr_map(dn, dcr_base, dcr_len);
471 	if (!DCR_MAP_OK(up->dcr_host)) {
472 		printk("Cannot map DCR resources for SERIAL");
473 		return -1;
474 	}
475 	register_console(&nwpserial_console);
476 	return 0;
477 }
478 console_initcall(nwpserial_console_init);
479 #endif /* CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE */
480