Linux Audio

Check our new training course

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