1// SPDX-License-Identifier: GPL-2.0
2/*
3 * UART driver for PNX8XXX SoCs
4 *
5 * Author: Per Hallsmark per.hallsmark@mvista.com
6 * Ported to 2.6 kernel by EmbeddedAlley
7 * Reworked by Vitaly Wool <vitalywool@gmail.com>
8 *
9 * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
10 * Copyright (C) 2000 Deep Blue Solutions Ltd.
11 */
12
13#include <linux/module.h>
14#include <linux/ioport.h>
15#include <linux/init.h>
16#include <linux/console.h>
17#include <linux/sysrq.h>
18#include <linux/device.h>
19#include <linux/platform_device.h>
20#include <linux/tty.h>
21#include <linux/tty_flip.h>
22#include <linux/serial_core.h>
23#include <linux/serial.h>
24#include <linux/serial_pnx8xxx.h>
25
26#include <asm/io.h>
27#include <asm/irq.h>
28
29/* We'll be using StrongARM sa1100 serial port major/minor */
30#define SERIAL_PNX8XXX_MAJOR	204
31#define MINOR_START		5
32
33#define NR_PORTS		2
34
35#define PNX8XXX_ISR_PASS_LIMIT	256
36
37/*
38 * Convert from ignore_status_mask or read_status_mask to FIFO
39 * and interrupt status bits
40 */
41#define SM_TO_FIFO(x)	((x) >> 10)
42#define SM_TO_ISTAT(x)	((x) & 0x000001ff)
43#define FIFO_TO_SM(x)	((x) << 10)
44#define ISTAT_TO_SM(x)	((x) & 0x000001ff)
45
46/*
47 * This is the size of our serial port register set.
48 */
49#define UART_PORT_SIZE	0x1000
50
51/*
52 * This determines how often we check the modem status signals
53 * for any change.  They generally aren't connected to an IRQ
54 * so we have to poll them.  We also check immediately before
55 * filling the TX fifo incase CTS has been dropped.
56 */
57#define MCTRL_TIMEOUT	(250*HZ/1000)
58
59extern struct pnx8xxx_port pnx8xxx_ports[];
60
61static inline int serial_in(struct pnx8xxx_port *sport, int offset)
62{
63	return (__raw_readl(sport->port.membase + offset));
64}
65
66static inline void serial_out(struct pnx8xxx_port *sport, int offset, int value)
67{
68	__raw_writel(value, sport->port.membase + offset);
69}
70
71/*
72 * Handle any change of modem status signal since we were last called.
73 */
74static void pnx8xxx_mctrl_check(struct pnx8xxx_port *sport)
75{
76	unsigned int status, changed;
77
78	status = sport->port.ops->get_mctrl(&sport->port);
79	changed = status ^ sport->old_status;
80
81	if (changed == 0)
82		return;
83
84	sport->old_status = status;
85
86	if (changed & TIOCM_RI)
87		sport->port.icount.rng++;
88	if (changed & TIOCM_DSR)
89		sport->port.icount.dsr++;
90	if (changed & TIOCM_CAR)
91		uart_handle_dcd_change(&sport->port, status & TIOCM_CAR);
92	if (changed & TIOCM_CTS)
93		uart_handle_cts_change(&sport->port, status & TIOCM_CTS);
94
95	wake_up_interruptible(&sport->port.state->port.delta_msr_wait);
96}
97
98/*
99 * This is our per-port timeout handler, for checking the
100 * modem status signals.
101 */
102static void pnx8xxx_timeout(struct timer_list *t)
103{
104	struct pnx8xxx_port *sport = from_timer(sport, t, timer);
105	unsigned long flags;
106
107	if (sport->port.state) {
108		spin_lock_irqsave(&sport->port.lock, flags);
109		pnx8xxx_mctrl_check(sport);
110		spin_unlock_irqrestore(&sport->port.lock, flags);
111
112		mod_timer(&sport->timer, jiffies + MCTRL_TIMEOUT);
113	}
114}
115
116/*
117 * interrupts disabled on entry
118 */
119static void pnx8xxx_stop_tx(struct uart_port *port)
120{
121	struct pnx8xxx_port *sport =
122		container_of(port, struct pnx8xxx_port, port);
123	u32 ien;
124
125	/* Disable TX intr */
126	ien = serial_in(sport, PNX8XXX_IEN);
127	serial_out(sport, PNX8XXX_IEN, ien & ~PNX8XXX_UART_INT_ALLTX);
128
129	/* Clear all pending TX intr */
130	serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_ALLTX);
131}
132
133/*
134 * interrupts may not be disabled on entry
135 */
136static void pnx8xxx_start_tx(struct uart_port *port)
137{
138	struct pnx8xxx_port *sport =
139		container_of(port, struct pnx8xxx_port, port);
140	u32 ien;
141
142	/* Clear all pending TX intr */
143	serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_ALLTX);
144
145	/* Enable TX intr */
146	ien = serial_in(sport, PNX8XXX_IEN);
147	serial_out(sport, PNX8XXX_IEN, ien | PNX8XXX_UART_INT_ALLTX);
148}
149
150/*
151 * Interrupts enabled
152 */
153static void pnx8xxx_stop_rx(struct uart_port *port)
154{
155	struct pnx8xxx_port *sport =
156		container_of(port, struct pnx8xxx_port, port);
157	u32 ien;
158
159	/* Disable RX intr */
160	ien = serial_in(sport, PNX8XXX_IEN);
161	serial_out(sport, PNX8XXX_IEN, ien & ~PNX8XXX_UART_INT_ALLRX);
162
163	/* Clear all pending RX intr */
164	serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_ALLRX);
165}
166
167/*
168 * Set the modem control timer to fire immediately.
169 */
170static void pnx8xxx_enable_ms(struct uart_port *port)
171{
172	struct pnx8xxx_port *sport =
173		container_of(port, struct pnx8xxx_port, port);
174
175	mod_timer(&sport->timer, jiffies);
176}
177
178static void pnx8xxx_rx_chars(struct pnx8xxx_port *sport)
179{
180	unsigned int status, ch, flg;
181
182	status = FIFO_TO_SM(serial_in(sport, PNX8XXX_FIFO)) |
183		 ISTAT_TO_SM(serial_in(sport, PNX8XXX_ISTAT));
184	while (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFIFO)) {
185		ch = serial_in(sport, PNX8XXX_FIFO) & 0xff;
186
187		sport->port.icount.rx++;
188
189		flg = TTY_NORMAL;
190
191		/*
192		 * note that the error handling code is
193		 * out of the main execution path
194		 */
195		if (status & (FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE |
196					PNX8XXX_UART_FIFO_RXPAR |
197					PNX8XXX_UART_FIFO_RXBRK) |
198			      ISTAT_TO_SM(PNX8XXX_UART_INT_RXOVRN))) {
199			if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXBRK)) {
200				status &= ~(FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE) |
201					FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR));
202				sport->port.icount.brk++;
203				if (uart_handle_break(&sport->port))
204					goto ignore_char;
205			} else if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR))
206				sport->port.icount.parity++;
207			else if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE))
208				sport->port.icount.frame++;
209			if (status & ISTAT_TO_SM(PNX8XXX_UART_INT_RXOVRN))
210				sport->port.icount.overrun++;
211
212			status &= sport->port.read_status_mask;
213
214			if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR))
215				flg = TTY_PARITY;
216			else if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE))
217				flg = TTY_FRAME;
218
219			sport->port.sysrq = 0;
220		}
221
222		if (uart_handle_sysrq_char(&sport->port, ch))
223			goto ignore_char;
224
225		uart_insert_char(&sport->port, status,
226				ISTAT_TO_SM(PNX8XXX_UART_INT_RXOVRN), ch, flg);
227
228	ignore_char:
229		serial_out(sport, PNX8XXX_LCR, serial_in(sport, PNX8XXX_LCR) |
230				PNX8XXX_UART_LCR_RX_NEXT);
231		status = FIFO_TO_SM(serial_in(sport, PNX8XXX_FIFO)) |
232			 ISTAT_TO_SM(serial_in(sport, PNX8XXX_ISTAT));
233	}
234
235	spin_unlock(&sport->port.lock);
236	tty_flip_buffer_push(&sport->port.state->port);
237	spin_lock(&sport->port.lock);
238}
239
240static void pnx8xxx_tx_chars(struct pnx8xxx_port *sport)
241{
242	struct circ_buf *xmit = &sport->port.state->xmit;
243
244	if (sport->port.x_char) {
245		serial_out(sport, PNX8XXX_FIFO, sport->port.x_char);
246		sport->port.icount.tx++;
247		sport->port.x_char = 0;
248		return;
249	}
250
251	/*
252	 * Check the modem control lines before
253	 * transmitting anything.
254	 */
255	pnx8xxx_mctrl_check(sport);
256
257	if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
258		pnx8xxx_stop_tx(&sport->port);
259		return;
260	}
261
262	/*
263	 * TX while bytes available
264	 */
265	while (((serial_in(sport, PNX8XXX_FIFO) &
266					PNX8XXX_UART_FIFO_TXFIFO) >> 16) < 16) {
267		serial_out(sport, PNX8XXX_FIFO, xmit->buf[xmit->tail]);
268		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
269		sport->port.icount.tx++;
270		if (uart_circ_empty(xmit))
271			break;
272	}
273
274	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
275		uart_write_wakeup(&sport->port);
276
277	if (uart_circ_empty(xmit))
278		pnx8xxx_stop_tx(&sport->port);
279}
280
281static irqreturn_t pnx8xxx_int(int irq, void *dev_id)
282{
283	struct pnx8xxx_port *sport = dev_id;
284	unsigned int status;
285
286	spin_lock(&sport->port.lock);
287	/* Get the interrupts */
288	status  = serial_in(sport, PNX8XXX_ISTAT) & serial_in(sport, PNX8XXX_IEN);
289
290	/* Byte or break signal received */
291	if (status & (PNX8XXX_UART_INT_RX | PNX8XXX_UART_INT_BREAK))
292		pnx8xxx_rx_chars(sport);
293
294	/* TX holding register empty - transmit a byte */
295	if (status & PNX8XXX_UART_INT_TX)
296		pnx8xxx_tx_chars(sport);
297
298	/* Clear the ISTAT register */
299	serial_out(sport, PNX8XXX_ICLR, status);
300
301	spin_unlock(&sport->port.lock);
302	return IRQ_HANDLED;
303}
304
305/*
306 * Return TIOCSER_TEMT when transmitter is not busy.
307 */
308static unsigned int pnx8xxx_tx_empty(struct uart_port *port)
309{
310	struct pnx8xxx_port *sport =
311		container_of(port, struct pnx8xxx_port, port);
312
313	return serial_in(sport, PNX8XXX_FIFO) & PNX8XXX_UART_FIFO_TXFIFO_STA ? 0 : TIOCSER_TEMT;
314}
315
316static unsigned int pnx8xxx_get_mctrl(struct uart_port *port)
317{
318	struct pnx8xxx_port *sport =
319		container_of(port, struct pnx8xxx_port, port);
320	unsigned int mctrl = TIOCM_DSR;
321	unsigned int msr;
322
323	/* REVISIT */
324
325	msr = serial_in(sport, PNX8XXX_MCR);
326
327	mctrl |= msr & PNX8XXX_UART_MCR_CTS ? TIOCM_CTS : 0;
328	mctrl |= msr & PNX8XXX_UART_MCR_DCD ? TIOCM_CAR : 0;
329
330	return mctrl;
331}
332
333static void pnx8xxx_set_mctrl(struct uart_port *port, unsigned int mctrl)
334{
335#if	0	/* FIXME */
336	struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
337	unsigned int msr;
338#endif
339}
340
341/*
342 * Interrupts always disabled.
343 */
344static void pnx8xxx_break_ctl(struct uart_port *port, int break_state)
345{
346	struct pnx8xxx_port *sport =
347		container_of(port, struct pnx8xxx_port, port);
348	unsigned long flags;
349	unsigned int lcr;
350
351	spin_lock_irqsave(&sport->port.lock, flags);
352	lcr = serial_in(sport, PNX8XXX_LCR);
353	if (break_state == -1)
354		lcr |= PNX8XXX_UART_LCR_TXBREAK;
355	else
356		lcr &= ~PNX8XXX_UART_LCR_TXBREAK;
357	serial_out(sport, PNX8XXX_LCR, lcr);
358	spin_unlock_irqrestore(&sport->port.lock, flags);
359}
360
361static int pnx8xxx_startup(struct uart_port *port)
362{
363	struct pnx8xxx_port *sport =
364		container_of(port, struct pnx8xxx_port, port);
365	int retval;
366
367	/*
368	 * Allocate the IRQ
369	 */
370	retval = request_irq(sport->port.irq, pnx8xxx_int, 0,
371			     "pnx8xxx-uart", sport);
372	if (retval)
373		return retval;
374
375	/*
376	 * Finally, clear and enable interrupts
377	 */
378
379	serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_ALLRX |
380			     PNX8XXX_UART_INT_ALLTX);
381
382	serial_out(sport, PNX8XXX_IEN, serial_in(sport, PNX8XXX_IEN) |
383			    PNX8XXX_UART_INT_ALLRX |
384			    PNX8XXX_UART_INT_ALLTX);
385
386	/*
387	 * Enable modem status interrupts
388	 */
389	spin_lock_irq(&sport->port.lock);
390	pnx8xxx_enable_ms(&sport->port);
391	spin_unlock_irq(&sport->port.lock);
392
393	return 0;
394}
395
396static void pnx8xxx_shutdown(struct uart_port *port)
397{
398	struct pnx8xxx_port *sport =
399		container_of(port, struct pnx8xxx_port, port);
400	int lcr;
401
402	/*
403	 * Stop our timer.
404	 */
405	del_timer_sync(&sport->timer);
406
407	/*
408	 * Disable all interrupts
409	 */
410	serial_out(sport, PNX8XXX_IEN, 0);
411
412	/*
413	 * Reset the Tx and Rx FIFOS, disable the break condition
414	 */
415	lcr = serial_in(sport, PNX8XXX_LCR);
416	lcr &= ~PNX8XXX_UART_LCR_TXBREAK;
417	lcr |= PNX8XXX_UART_LCR_TX_RST | PNX8XXX_UART_LCR_RX_RST;
418	serial_out(sport, PNX8XXX_LCR, lcr);
419
420	/*
421	 * Clear all interrupts
422	 */
423	serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_ALLRX |
424			     PNX8XXX_UART_INT_ALLTX);
425
426	/*
427	 * Free the interrupt
428	 */
429	free_irq(sport->port.irq, sport);
430}
431
432static void
433pnx8xxx_set_termios(struct uart_port *port, struct ktermios *termios,
434		   struct ktermios *old)
435{
436	struct pnx8xxx_port *sport =
437		container_of(port, struct pnx8xxx_port, port);
438	unsigned long flags;
439	unsigned int lcr_fcr, old_ien, baud, quot;
440	unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
441
442	/*
443	 * We only support CS7 and CS8.
444	 */
445	while ((termios->c_cflag & CSIZE) != CS7 &&
446	       (termios->c_cflag & CSIZE) != CS8) {
447		termios->c_cflag &= ~CSIZE;
448		termios->c_cflag |= old_csize;
449		old_csize = CS8;
450	}
451
452	if ((termios->c_cflag & CSIZE) == CS8)
453		lcr_fcr = PNX8XXX_UART_LCR_8BIT;
454	else
455		lcr_fcr = 0;
456
457	if (termios->c_cflag & CSTOPB)
458		lcr_fcr |= PNX8XXX_UART_LCR_2STOPB;
459	if (termios->c_cflag & PARENB) {
460		lcr_fcr |= PNX8XXX_UART_LCR_PAREN;
461		if (!(termios->c_cflag & PARODD))
462			lcr_fcr |= PNX8XXX_UART_LCR_PAREVN;
463	}
464
465	/*
466	 * Ask the core to calculate the divisor for us.
467	 */
468	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
469	quot = uart_get_divisor(port, baud);
470
471	spin_lock_irqsave(&sport->port.lock, flags);
472
473	sport->port.read_status_mask = ISTAT_TO_SM(PNX8XXX_UART_INT_RXOVRN) |
474				ISTAT_TO_SM(PNX8XXX_UART_INT_EMPTY) |
475				ISTAT_TO_SM(PNX8XXX_UART_INT_RX);
476	if (termios->c_iflag & INPCK)
477		sport->port.read_status_mask |=
478			FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE) |
479			FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR);
480	if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
481		sport->port.read_status_mask |=
482			ISTAT_TO_SM(PNX8XXX_UART_INT_BREAK);
483
484	/*
485	 * Characters to ignore
486	 */
487	sport->port.ignore_status_mask = 0;
488	if (termios->c_iflag & IGNPAR)
489		sport->port.ignore_status_mask |=
490			FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE) |
491			FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR);
492	if (termios->c_iflag & IGNBRK) {
493		sport->port.ignore_status_mask |=
494			ISTAT_TO_SM(PNX8XXX_UART_INT_BREAK);
495		/*
496		 * If we're ignoring parity and break indicators,
497		 * ignore overruns too (for real raw support).
498		 */
499		if (termios->c_iflag & IGNPAR)
500			sport->port.ignore_status_mask |=
501				ISTAT_TO_SM(PNX8XXX_UART_INT_RXOVRN);
502	}
503
504	/*
505	 * ignore all characters if CREAD is not set
506	 */
507	if ((termios->c_cflag & CREAD) == 0)
508		sport->port.ignore_status_mask |=
509			ISTAT_TO_SM(PNX8XXX_UART_INT_RX);
510
511	del_timer_sync(&sport->timer);
512
513	/*
514	 * Update the per-port timeout.
515	 */
516	uart_update_timeout(port, termios->c_cflag, baud);
517
518	/*
519	 * disable interrupts and drain transmitter
520	 */
521	old_ien = serial_in(sport, PNX8XXX_IEN);
522	serial_out(sport, PNX8XXX_IEN, old_ien & ~(PNX8XXX_UART_INT_ALLTX |
523					PNX8XXX_UART_INT_ALLRX));
524
525	while (serial_in(sport, PNX8XXX_FIFO) & PNX8XXX_UART_FIFO_TXFIFO_STA)
526		barrier();
527
528	/* then, disable everything */
529	serial_out(sport, PNX8XXX_IEN, 0);
530
531	/* Reset the Rx and Tx FIFOs too */
532	lcr_fcr |= PNX8XXX_UART_LCR_TX_RST;
533	lcr_fcr |= PNX8XXX_UART_LCR_RX_RST;
534
535	/* set the parity, stop bits and data size */
536	serial_out(sport, PNX8XXX_LCR, lcr_fcr);
537
538	/* set the baud rate */
539	quot -= 1;
540	serial_out(sport, PNX8XXX_BAUD, quot);
541
542	serial_out(sport, PNX8XXX_ICLR, -1);
543
544	serial_out(sport, PNX8XXX_IEN, old_ien);
545
546	if (UART_ENABLE_MS(&sport->port, termios->c_cflag))
547		pnx8xxx_enable_ms(&sport->port);
548
549	spin_unlock_irqrestore(&sport->port.lock, flags);
550}
551
552static const char *pnx8xxx_type(struct uart_port *port)
553{
554	struct pnx8xxx_port *sport =
555		container_of(port, struct pnx8xxx_port, port);
556
557	return sport->port.type == PORT_PNX8XXX ? "PNX8XXX" : NULL;
558}
559
560/*
561 * Release the memory region(s) being used by 'port'.
562 */
563static void pnx8xxx_release_port(struct uart_port *port)
564{
565	struct pnx8xxx_port *sport =
566		container_of(port, struct pnx8xxx_port, port);
567
568	release_mem_region(sport->port.mapbase, UART_PORT_SIZE);
569}
570
571/*
572 * Request the memory region(s) being used by 'port'.
573 */
574static int pnx8xxx_request_port(struct uart_port *port)
575{
576	struct pnx8xxx_port *sport =
577		container_of(port, struct pnx8xxx_port, port);
578	return request_mem_region(sport->port.mapbase, UART_PORT_SIZE,
579			"pnx8xxx-uart") != NULL ? 0 : -EBUSY;
580}
581
582/*
583 * Configure/autoconfigure the port.
584 */
585static void pnx8xxx_config_port(struct uart_port *port, int flags)
586{
587	struct pnx8xxx_port *sport =
588		container_of(port, struct pnx8xxx_port, port);
589
590	if (flags & UART_CONFIG_TYPE &&
591	    pnx8xxx_request_port(&sport->port) == 0)
592		sport->port.type = PORT_PNX8XXX;
593}
594
595/*
596 * Verify the new serial_struct (for TIOCSSERIAL).
597 * The only change we allow are to the flags and type, and
598 * even then only between PORT_PNX8XXX and PORT_UNKNOWN
599 */
600static int
601pnx8xxx_verify_port(struct uart_port *port, struct serial_struct *ser)
602{
603	struct pnx8xxx_port *sport =
604		container_of(port, struct pnx8xxx_port,	port);
605	int ret = 0;
606
607	if (ser->type != PORT_UNKNOWN && ser->type != PORT_PNX8XXX)
608		ret = -EINVAL;
609	if (sport->port.irq != ser->irq)
610		ret = -EINVAL;
611	if (ser->io_type != SERIAL_IO_MEM)
612		ret = -EINVAL;
613	if (sport->port.uartclk / 16 != ser->baud_base)
614		ret = -EINVAL;
615	if ((void *)sport->port.mapbase != ser->iomem_base)
616		ret = -EINVAL;
617	if (sport->port.iobase != ser->port)
618		ret = -EINVAL;
619	if (ser->hub6 != 0)
620		ret = -EINVAL;
621	return ret;
622}
623
624static const struct uart_ops pnx8xxx_pops = {
625	.tx_empty	= pnx8xxx_tx_empty,
626	.set_mctrl	= pnx8xxx_set_mctrl,
627	.get_mctrl	= pnx8xxx_get_mctrl,
628	.stop_tx	= pnx8xxx_stop_tx,
629	.start_tx	= pnx8xxx_start_tx,
630	.stop_rx	= pnx8xxx_stop_rx,
631	.enable_ms	= pnx8xxx_enable_ms,
632	.break_ctl	= pnx8xxx_break_ctl,
633	.startup	= pnx8xxx_startup,
634	.shutdown	= pnx8xxx_shutdown,
635	.set_termios	= pnx8xxx_set_termios,
636	.type		= pnx8xxx_type,
637	.release_port	= pnx8xxx_release_port,
638	.request_port	= pnx8xxx_request_port,
639	.config_port	= pnx8xxx_config_port,
640	.verify_port	= pnx8xxx_verify_port,
641};
642
643
644/*
645 * Setup the PNX8XXX serial ports.
646 *
647 * Note also that we support "console=ttySx" where "x" is either 0 or 1.
648 */
649static void __init pnx8xxx_init_ports(void)
650{
651	static int first = 1;
652	int i;
653
654	if (!first)
655		return;
656	first = 0;
657
658	for (i = 0; i < NR_PORTS; i++) {
659		timer_setup(&pnx8xxx_ports[i].timer, pnx8xxx_timeout, 0);
660		pnx8xxx_ports[i].port.ops = &pnx8xxx_pops;
661	}
662}
663
664#ifdef CONFIG_SERIAL_PNX8XXX_CONSOLE
665
666static void pnx8xxx_console_putchar(struct uart_port *port, int ch)
667{
668	struct pnx8xxx_port *sport =
669		container_of(port, struct pnx8xxx_port, port);
670	int status;
671
672	do {
673		/* Wait for UART_TX register to empty */
674		status = serial_in(sport, PNX8XXX_FIFO);
675	} while (status & PNX8XXX_UART_FIFO_TXFIFO);
676	serial_out(sport, PNX8XXX_FIFO, ch);
677}
678
679/*
680 * Interrupts are disabled on entering
681 */static void
682pnx8xxx_console_write(struct console *co, const char *s, unsigned int count)
683{
684	struct pnx8xxx_port *sport = &pnx8xxx_ports[co->index];
685	unsigned int old_ien, status;
686
687	/*
688	 *	First, save IEN and then disable interrupts
689	 */
690	old_ien = serial_in(sport, PNX8XXX_IEN);
691	serial_out(sport, PNX8XXX_IEN, old_ien & ~(PNX8XXX_UART_INT_ALLTX |
692					PNX8XXX_UART_INT_ALLRX));
693
694	uart_console_write(&sport->port, s, count, pnx8xxx_console_putchar);
695
696	/*
697	 *	Finally, wait for transmitter to become empty
698	 *	and restore IEN
699	 */
700	do {
701		/* Wait for UART_TX register to empty */
702		status = serial_in(sport, PNX8XXX_FIFO);
703	} while (status & PNX8XXX_UART_FIFO_TXFIFO);
704
705	/* Clear TX and EMPTY interrupt */
706	serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_TX |
707			     PNX8XXX_UART_INT_EMPTY);
708
709	serial_out(sport, PNX8XXX_IEN, old_ien);
710}
711
712static int __init
713pnx8xxx_console_setup(struct console *co, char *options)
714{
715	struct pnx8xxx_port *sport;
716	int baud = 38400;
717	int bits = 8;
718	int parity = 'n';
719	int flow = 'n';
720
721	/*
722	 * Check whether an invalid uart number has been specified, and
723	 * if so, search for the first available port that does have
724	 * console support.
725	 */
726	if (co->index == -1 || co->index >= NR_PORTS)
727		co->index = 0;
728	sport = &pnx8xxx_ports[co->index];
729
730	if (options)
731		uart_parse_options(options, &baud, &parity, &bits, &flow);
732
733	return uart_set_options(&sport->port, co, baud, parity, bits, flow);
734}
735
736static struct uart_driver pnx8xxx_reg;
737static struct console pnx8xxx_console = {
738	.name		= "ttyS",
739	.write		= pnx8xxx_console_write,
740	.device		= uart_console_device,
741	.setup		= pnx8xxx_console_setup,
742	.flags		= CON_PRINTBUFFER,
743	.index		= -1,
744	.data		= &pnx8xxx_reg,
745};
746
747static int __init pnx8xxx_rs_console_init(void)
748{
749	pnx8xxx_init_ports();
750	register_console(&pnx8xxx_console);
751	return 0;
752}
753console_initcall(pnx8xxx_rs_console_init);
754
755#define PNX8XXX_CONSOLE	&pnx8xxx_console
756#else
757#define PNX8XXX_CONSOLE	NULL
758#endif
759
760static struct uart_driver pnx8xxx_reg = {
761	.owner			= THIS_MODULE,
762	.driver_name		= "ttyS",
763	.dev_name		= "ttyS",
764	.major			= SERIAL_PNX8XXX_MAJOR,
765	.minor			= MINOR_START,
766	.nr			= NR_PORTS,
767	.cons			= PNX8XXX_CONSOLE,
768};
769
770static int pnx8xxx_serial_suspend(struct platform_device *pdev, pm_message_t state)
771{
772	struct pnx8xxx_port *sport = platform_get_drvdata(pdev);
773
774	return uart_suspend_port(&pnx8xxx_reg, &sport->port);
775}
776
777static int pnx8xxx_serial_resume(struct platform_device *pdev)
778{
779	struct pnx8xxx_port *sport = platform_get_drvdata(pdev);
780
781	return uart_resume_port(&pnx8xxx_reg, &sport->port);
782}
783
784static int pnx8xxx_serial_probe(struct platform_device *pdev)
785{
786	struct resource *res = pdev->resource;
787	int i;
788
789	for (i = 0; i < pdev->num_resources; i++, res++) {
790		if (!(res->flags & IORESOURCE_MEM))
791			continue;
792
793		for (i = 0; i < NR_PORTS; i++) {
794			if (pnx8xxx_ports[i].port.mapbase != res->start)
795				continue;
796
797			pnx8xxx_ports[i].port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_PNX8XXX_CONSOLE);
798			pnx8xxx_ports[i].port.dev = &pdev->dev;
799			uart_add_one_port(&pnx8xxx_reg, &pnx8xxx_ports[i].port);
800			platform_set_drvdata(pdev, &pnx8xxx_ports[i]);
801			break;
802		}
803	}
804
805	return 0;
806}
807
808static int pnx8xxx_serial_remove(struct platform_device *pdev)
809{
810	struct pnx8xxx_port *sport = platform_get_drvdata(pdev);
811
812	if (sport)
813		uart_remove_one_port(&pnx8xxx_reg, &sport->port);
814
815	return 0;
816}
817
818static struct platform_driver pnx8xxx_serial_driver = {
819	.driver		= {
820		.name	= "pnx8xxx-uart",
821	},
822	.probe		= pnx8xxx_serial_probe,
823	.remove		= pnx8xxx_serial_remove,
824	.suspend	= pnx8xxx_serial_suspend,
825	.resume		= pnx8xxx_serial_resume,
826};
827
828static int __init pnx8xxx_serial_init(void)
829{
830	int ret;
831
832	printk(KERN_INFO "Serial: PNX8XXX driver\n");
833
834	pnx8xxx_init_ports();
835
836	ret = uart_register_driver(&pnx8xxx_reg);
837	if (ret == 0) {
838		ret = platform_driver_register(&pnx8xxx_serial_driver);
839		if (ret)
840			uart_unregister_driver(&pnx8xxx_reg);
841	}
842	return ret;
843}
844
845static void __exit pnx8xxx_serial_exit(void)
846{
847	platform_driver_unregister(&pnx8xxx_serial_driver);
848	uart_unregister_driver(&pnx8xxx_reg);
849}
850
851module_init(pnx8xxx_serial_init);
852module_exit(pnx8xxx_serial_exit);
853
854MODULE_AUTHOR("Embedded Alley Solutions, Inc.");
855MODULE_DESCRIPTION("PNX8XXX SoCs serial port driver");
856MODULE_LICENSE("GPL");
857MODULE_ALIAS_CHARDEV_MAJOR(SERIAL_PNX8XXX_MAJOR);
858MODULE_ALIAS("platform:pnx8xxx-uart");
859