blob: f4440d3293106a9d7930fe3b9a55e10e755dbb78 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * drivers/serial/serial_txx9.c
3 *
4 * Derived from many drivers using generic_serial interface,
5 * especially serial_tx3912.c by Steven J. Hill and r39xx_serial.c
6 * (was in Linux/VR tree) by Jim Pick.
7 *
8 * Copyright (C) 1999 Harald Koerfgen
9 * Copyright (C) 2000 Jim Pick <jim@jimpick.com>
10 * Copyright (C) 2001 Steven J. Hill (sjhill@realitydiluted.com)
11 * Copyright (C) 2000-2002 Toshiba Corporation
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
16 *
17 * Serial driver for TX3927/TX4927/TX4925/TX4938 internal SIO controller
18 *
19 * Revision History:
20 * 0.30 Initial revision. (Renamed from serial_txx927.c)
21 * 0.31 Use save_flags instead of local_irq_save.
22 * 0.32 Support SCLK.
23 * 0.33 Switch TXX9_TTY_NAME by CONFIG_SERIAL_TXX9_STDSERIAL.
24 * Support TIOCSERGETLSR.
25 * 0.34 Support slow baudrate.
26 * 0.40 Merge codes from mainstream kernel (2.4.22).
27 * 0.41 Fix console checking in rs_shutdown_port().
28 * Disable flow-control in serial_console_write().
29 * 0.42 Fix minor compiler warning.
30 * 1.00 Kernel 2.6. Converted to new serial core (based on 8250.c).
31 * 1.01 Set fifosize to make tx_empry called properly.
32 * Use standard uart_get_divisor.
33 * 1.02 Cleanup. (import 8250.c changes)
Ralf Baechlef5ee56c2005-09-09 13:01:32 -070034 * 1.03 Fix low-latency mode. (import 8250.c changes)
35 * 1.04 Remove usage of deprecated functions, cleanup.
Atsushi Nemoto83485f82006-03-22 00:07:45 -080036 * 1.05 More strict check in verify_port. Cleanup.
37 * 1.06 Do not insert a char caused previous overrun.
38 * Fix some spin_locks.
39 * Do not call uart_add_one_port for absent ports.
Atsushi Nemoto138c5d22007-02-10 01:45:05 -080040 * 1.07 Use CONFIG_SERIAL_TXX9_NR_UARTS. Cleanup.
Linus Torvalds1da177e2005-04-16 15:20:36 -070041 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070042
43#if defined(CONFIG_SERIAL_TXX9_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
44#define SUPPORT_SYSRQ
45#endif
46
47#include <linux/module.h>
48#include <linux/ioport.h>
49#include <linux/init.h>
50#include <linux/console.h>
51#include <linux/sysrq.h>
52#include <linux/delay.h>
53#include <linux/device.h>
54#include <linux/pci.h>
55#include <linux/tty.h>
56#include <linux/tty_flip.h>
57#include <linux/serial_core.h>
58#include <linux/serial.h>
Arjan van de Venf392ecf2006-01-12 18:44:32 +000059#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070060
61#include <asm/io.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
Atsushi Nemoto138c5d22007-02-10 01:45:05 -080063static char *serial_version = "1.07";
Linus Torvalds1da177e2005-04-16 15:20:36 -070064static char *serial_name = "TX39/49 Serial driver";
65
66#define PASS_LIMIT 256
67
68#if !defined(CONFIG_SERIAL_TXX9_STDSERIAL)
69/* "ttyS" is used for standard serial driver */
70#define TXX9_TTY_NAME "ttyTX"
Linus Torvalds1da177e2005-04-16 15:20:36 -070071#define TXX9_TTY_MINOR_START (64 + 64) /* ttyTX0(128), ttyTX1(129) */
72#else
73/* acts like standard serial driver */
74#define TXX9_TTY_NAME "ttyS"
Linus Torvalds1da177e2005-04-16 15:20:36 -070075#define TXX9_TTY_MINOR_START 64
76#endif
77#define TXX9_TTY_MAJOR TTY_MAJOR
78
79/* flag aliases */
80#define UPF_TXX9_HAVE_CTS_LINE UPF_BUGGY_UART
81#define UPF_TXX9_USE_SCLK UPF_MAGIC_MULTIPLIER
82
83#ifdef CONFIG_PCI
84/* support for Toshiba TC86C001 SIO */
85#define ENABLE_SERIAL_TXX9_PCI
86#endif
87
88/*
89 * Number of serial ports
90 */
Atsushi Nemoto138c5d22007-02-10 01:45:05 -080091#define UART_NR CONFIG_SERIAL_TXX9_NR_UARTS
Linus Torvalds1da177e2005-04-16 15:20:36 -070092
Atsushi Nemoto83485f82006-03-22 00:07:45 -080093#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
94
Linus Torvalds1da177e2005-04-16 15:20:36 -070095struct uart_txx9_port {
96 struct uart_port port;
97
98 /*
99 * We provide a per-port pm hook.
100 */
101 void (*pm)(struct uart_port *port,
102 unsigned int state, unsigned int old);
103};
104
105#define TXX9_REGION_SIZE 0x24
106
107/* TXX9 Serial Registers */
108#define TXX9_SILCR 0x00
109#define TXX9_SIDICR 0x04
110#define TXX9_SIDISR 0x08
111#define TXX9_SICISR 0x0c
112#define TXX9_SIFCR 0x10
113#define TXX9_SIFLCR 0x14
114#define TXX9_SIBGR 0x18
115#define TXX9_SITFIFO 0x1c
116#define TXX9_SIRFIFO 0x20
117
118/* SILCR : Line Control */
119#define TXX9_SILCR_SCS_MASK 0x00000060
120#define TXX9_SILCR_SCS_IMCLK 0x00000000
121#define TXX9_SILCR_SCS_IMCLK_BG 0x00000020
122#define TXX9_SILCR_SCS_SCLK 0x00000040
123#define TXX9_SILCR_SCS_SCLK_BG 0x00000060
124#define TXX9_SILCR_UEPS 0x00000010
125#define TXX9_SILCR_UPEN 0x00000008
126#define TXX9_SILCR_USBL_MASK 0x00000004
127#define TXX9_SILCR_USBL_1BIT 0x00000000
128#define TXX9_SILCR_USBL_2BIT 0x00000004
129#define TXX9_SILCR_UMODE_MASK 0x00000003
130#define TXX9_SILCR_UMODE_8BIT 0x00000000
131#define TXX9_SILCR_UMODE_7BIT 0x00000001
132
133/* SIDICR : DMA/Int. Control */
134#define TXX9_SIDICR_TDE 0x00008000
135#define TXX9_SIDICR_RDE 0x00004000
136#define TXX9_SIDICR_TIE 0x00002000
137#define TXX9_SIDICR_RIE 0x00001000
138#define TXX9_SIDICR_SPIE 0x00000800
139#define TXX9_SIDICR_CTSAC 0x00000600
140#define TXX9_SIDICR_STIE_MASK 0x0000003f
141#define TXX9_SIDICR_STIE_OERS 0x00000020
142#define TXX9_SIDICR_STIE_CTSS 0x00000010
143#define TXX9_SIDICR_STIE_RBRKD 0x00000008
144#define TXX9_SIDICR_STIE_TRDY 0x00000004
145#define TXX9_SIDICR_STIE_TXALS 0x00000002
146#define TXX9_SIDICR_STIE_UBRKD 0x00000001
147
148/* SIDISR : DMA/Int. Status */
149#define TXX9_SIDISR_UBRK 0x00008000
150#define TXX9_SIDISR_UVALID 0x00004000
151#define TXX9_SIDISR_UFER 0x00002000
152#define TXX9_SIDISR_UPER 0x00001000
153#define TXX9_SIDISR_UOER 0x00000800
154#define TXX9_SIDISR_ERI 0x00000400
155#define TXX9_SIDISR_TOUT 0x00000200
156#define TXX9_SIDISR_TDIS 0x00000100
157#define TXX9_SIDISR_RDIS 0x00000080
158#define TXX9_SIDISR_STIS 0x00000040
159#define TXX9_SIDISR_RFDN_MASK 0x0000001f
160
161/* SICISR : Change Int. Status */
162#define TXX9_SICISR_OERS 0x00000020
163#define TXX9_SICISR_CTSS 0x00000010
164#define TXX9_SICISR_RBRKD 0x00000008
165#define TXX9_SICISR_TRDY 0x00000004
166#define TXX9_SICISR_TXALS 0x00000002
167#define TXX9_SICISR_UBRKD 0x00000001
168
169/* SIFCR : FIFO Control */
170#define TXX9_SIFCR_SWRST 0x00008000
171#define TXX9_SIFCR_RDIL_MASK 0x00000180
172#define TXX9_SIFCR_RDIL_1 0x00000000
173#define TXX9_SIFCR_RDIL_4 0x00000080
174#define TXX9_SIFCR_RDIL_8 0x00000100
175#define TXX9_SIFCR_RDIL_12 0x00000180
176#define TXX9_SIFCR_RDIL_MAX 0x00000180
177#define TXX9_SIFCR_TDIL_MASK 0x00000018
178#define TXX9_SIFCR_TDIL_MASK 0x00000018
179#define TXX9_SIFCR_TDIL_1 0x00000000
180#define TXX9_SIFCR_TDIL_4 0x00000001
181#define TXX9_SIFCR_TDIL_8 0x00000010
182#define TXX9_SIFCR_TDIL_MAX 0x00000010
183#define TXX9_SIFCR_TFRST 0x00000004
184#define TXX9_SIFCR_RFRST 0x00000002
185#define TXX9_SIFCR_FRSTE 0x00000001
186#define TXX9_SIO_TX_FIFO 8
187#define TXX9_SIO_RX_FIFO 16
188
189/* SIFLCR : Flow Control */
190#define TXX9_SIFLCR_RCS 0x00001000
191#define TXX9_SIFLCR_TES 0x00000800
192#define TXX9_SIFLCR_RTSSC 0x00000200
193#define TXX9_SIFLCR_RSDE 0x00000100
194#define TXX9_SIFLCR_TSDE 0x00000080
195#define TXX9_SIFLCR_RTSTL_MASK 0x0000001e
196#define TXX9_SIFLCR_RTSTL_MAX 0x0000001e
197#define TXX9_SIFLCR_TBRK 0x00000001
198
199/* SIBGR : Baudrate Control */
200#define TXX9_SIBGR_BCLK_MASK 0x00000300
201#define TXX9_SIBGR_BCLK_T0 0x00000000
202#define TXX9_SIBGR_BCLK_T2 0x00000100
203#define TXX9_SIBGR_BCLK_T4 0x00000200
204#define TXX9_SIBGR_BCLK_T6 0x00000300
205#define TXX9_SIBGR_BRD_MASK 0x000000ff
206
207static inline unsigned int sio_in(struct uart_txx9_port *up, int offset)
208{
209 switch (up->port.iotype) {
210 default:
Atsushi Nemoto83485f82006-03-22 00:07:45 -0800211 return __raw_readl(up->port.membase + offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 case UPIO_PORT:
213 return inl(up->port.iobase + offset);
214 }
215}
216
217static inline void
218sio_out(struct uart_txx9_port *up, int offset, int value)
219{
220 switch (up->port.iotype) {
221 default:
Atsushi Nemoto83485f82006-03-22 00:07:45 -0800222 __raw_writel(value, up->port.membase + offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223 break;
224 case UPIO_PORT:
225 outl(value, up->port.iobase + offset);
226 break;
227 }
228}
229
230static inline void
231sio_mask(struct uart_txx9_port *up, int offset, unsigned int value)
232{
233 sio_out(up, offset, sio_in(up, offset) & ~value);
234}
235static inline void
236sio_set(struct uart_txx9_port *up, int offset, unsigned int value)
237{
238 sio_out(up, offset, sio_in(up, offset) | value);
239}
240
241static inline void
242sio_quot_set(struct uart_txx9_port *up, int quot)
243{
244 quot >>= 1;
245 if (quot < 256)
246 sio_out(up, TXX9_SIBGR, quot | TXX9_SIBGR_BCLK_T0);
247 else if (quot < (256 << 2))
248 sio_out(up, TXX9_SIBGR, (quot >> 2) | TXX9_SIBGR_BCLK_T2);
249 else if (quot < (256 << 4))
250 sio_out(up, TXX9_SIBGR, (quot >> 4) | TXX9_SIBGR_BCLK_T4);
251 else if (quot < (256 << 6))
252 sio_out(up, TXX9_SIBGR, (quot >> 6) | TXX9_SIBGR_BCLK_T6);
253 else
254 sio_out(up, TXX9_SIBGR, 0xff | TXX9_SIBGR_BCLK_T6);
255}
256
Russell Kingb129a8c2005-08-31 10:12:14 +0100257static void serial_txx9_stop_tx(struct uart_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258{
259 struct uart_txx9_port *up = (struct uart_txx9_port *)port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260 sio_mask(up, TXX9_SIDICR, TXX9_SIDICR_TIE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261}
262
Russell Kingb129a8c2005-08-31 10:12:14 +0100263static void serial_txx9_start_tx(struct uart_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264{
265 struct uart_txx9_port *up = (struct uart_txx9_port *)port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 sio_set(up, TXX9_SIDICR, TXX9_SIDICR_TIE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267}
268
269static void serial_txx9_stop_rx(struct uart_port *port)
270{
271 struct uart_txx9_port *up = (struct uart_txx9_port *)port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 up->port.read_status_mask &= ~TXX9_SIDISR_RDIS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273}
274
275static void serial_txx9_enable_ms(struct uart_port *port)
276{
277 /* TXX9-SIO can not control DTR... */
278}
279
280static inline void
David Howells7d12e782006-10-05 14:55:46 +0100281receive_chars(struct uart_txx9_port *up, unsigned int *status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282{
283 struct tty_struct *tty = up->port.info->tty;
284 unsigned char ch;
285 unsigned int disr = *status;
286 int max_count = 256;
287 char flag;
Atsushi Nemoto83485f82006-03-22 00:07:45 -0800288 unsigned int next_ignore_status_mask;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289
290 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 ch = sio_in(up, TXX9_SIRFIFO);
292 flag = TTY_NORMAL;
293 up->port.icount.rx++;
294
Atsushi Nemoto83485f82006-03-22 00:07:45 -0800295 /* mask out RFDN_MASK bit added by previous overrun */
296 next_ignore_status_mask =
297 up->port.ignore_status_mask & ~TXX9_SIDISR_RFDN_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298 if (unlikely(disr & (TXX9_SIDISR_UBRK | TXX9_SIDISR_UPER |
299 TXX9_SIDISR_UFER | TXX9_SIDISR_UOER))) {
300 /*
301 * For statistics only
302 */
303 if (disr & TXX9_SIDISR_UBRK) {
304 disr &= ~(TXX9_SIDISR_UFER | TXX9_SIDISR_UPER);
305 up->port.icount.brk++;
306 /*
307 * We do the SysRQ and SAK checking
308 * here because otherwise the break
309 * may get masked by ignore_status_mask
310 * or read_status_mask.
311 */
312 if (uart_handle_break(&up->port))
313 goto ignore_char;
314 } else if (disr & TXX9_SIDISR_UPER)
315 up->port.icount.parity++;
316 else if (disr & TXX9_SIDISR_UFER)
317 up->port.icount.frame++;
Atsushi Nemoto83485f82006-03-22 00:07:45 -0800318 if (disr & TXX9_SIDISR_UOER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319 up->port.icount.overrun++;
Atsushi Nemoto83485f82006-03-22 00:07:45 -0800320 /*
321 * The receiver read buffer still hold
322 * a char which caused overrun.
323 * Ignore next char by adding RFDN_MASK
324 * to ignore_status_mask temporarily.
325 */
326 next_ignore_status_mask |=
327 TXX9_SIDISR_RFDN_MASK;
328 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329
330 /*
331 * Mask off conditions which should be ingored.
332 */
333 disr &= up->port.read_status_mask;
334
335 if (disr & TXX9_SIDISR_UBRK) {
336 flag = TTY_BREAK;
337 } else if (disr & TXX9_SIDISR_UPER)
338 flag = TTY_PARITY;
339 else if (disr & TXX9_SIDISR_UFER)
340 flag = TTY_FRAME;
341 }
David Howells7d12e782006-10-05 14:55:46 +0100342 if (uart_handle_sysrq_char(&up->port, ch))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343 goto ignore_char;
Russell King05ab3012005-05-09 23:21:59 +0100344
345 uart_insert_char(&up->port, disr, TXX9_SIDISR_UOER, ch, flag);
346
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347 ignore_char:
Atsushi Nemoto83485f82006-03-22 00:07:45 -0800348 up->port.ignore_status_mask = next_ignore_status_mask;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349 disr = sio_in(up, TXX9_SIDISR);
350 } while (!(disr & TXX9_SIDISR_UVALID) && (max_count-- > 0));
Ralf Baechlef5ee56c2005-09-09 13:01:32 -0700351 spin_unlock(&up->port.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 tty_flip_buffer_push(tty);
Ralf Baechlef5ee56c2005-09-09 13:01:32 -0700353 spin_lock(&up->port.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354 *status = disr;
355}
356
357static inline void transmit_chars(struct uart_txx9_port *up)
358{
359 struct circ_buf *xmit = &up->port.info->xmit;
360 int count;
361
362 if (up->port.x_char) {
363 sio_out(up, TXX9_SITFIFO, up->port.x_char);
364 up->port.icount.tx++;
365 up->port.x_char = 0;
366 return;
367 }
368 if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
Russell Kingb129a8c2005-08-31 10:12:14 +0100369 serial_txx9_stop_tx(&up->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 return;
371 }
372
373 count = TXX9_SIO_TX_FIFO;
374 do {
375 sio_out(up, TXX9_SITFIFO, xmit->buf[xmit->tail]);
376 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
377 up->port.icount.tx++;
378 if (uart_circ_empty(xmit))
379 break;
380 } while (--count > 0);
381
382 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
383 uart_write_wakeup(&up->port);
384
385 if (uart_circ_empty(xmit))
Russell Kingb129a8c2005-08-31 10:12:14 +0100386 serial_txx9_stop_tx(&up->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387}
388
David Howells7d12e782006-10-05 14:55:46 +0100389static irqreturn_t serial_txx9_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390{
391 int pass_counter = 0;
392 struct uart_txx9_port *up = dev_id;
393 unsigned int status;
394
395 while (1) {
396 spin_lock(&up->port.lock);
397 status = sio_in(up, TXX9_SIDISR);
398 if (!(sio_in(up, TXX9_SIDICR) & TXX9_SIDICR_TIE))
399 status &= ~TXX9_SIDISR_TDIS;
400 if (!(status & (TXX9_SIDISR_TDIS | TXX9_SIDISR_RDIS |
401 TXX9_SIDISR_TOUT))) {
402 spin_unlock(&up->port.lock);
403 break;
404 }
405
406 if (status & TXX9_SIDISR_RDIS)
David Howells7d12e782006-10-05 14:55:46 +0100407 receive_chars(up, &status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408 if (status & TXX9_SIDISR_TDIS)
409 transmit_chars(up);
410 /* Clear TX/RX Int. Status */
411 sio_mask(up, TXX9_SIDISR,
412 TXX9_SIDISR_TDIS | TXX9_SIDISR_RDIS |
413 TXX9_SIDISR_TOUT);
414 spin_unlock(&up->port.lock);
415
416 if (pass_counter++ > PASS_LIMIT)
417 break;
418 }
419
420 return pass_counter ? IRQ_HANDLED : IRQ_NONE;
421}
422
423static unsigned int serial_txx9_tx_empty(struct uart_port *port)
424{
425 struct uart_txx9_port *up = (struct uart_txx9_port *)port;
426 unsigned long flags;
427 unsigned int ret;
428
429 spin_lock_irqsave(&up->port.lock, flags);
430 ret = (sio_in(up, TXX9_SICISR) & TXX9_SICISR_TXALS) ? TIOCSER_TEMT : 0;
431 spin_unlock_irqrestore(&up->port.lock, flags);
432
433 return ret;
434}
435
436static unsigned int serial_txx9_get_mctrl(struct uart_port *port)
437{
438 struct uart_txx9_port *up = (struct uart_txx9_port *)port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439 unsigned int ret;
440
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 ret = ((sio_in(up, TXX9_SIFLCR) & TXX9_SIFLCR_RTSSC) ? 0 : TIOCM_RTS)
442 | ((sio_in(up, TXX9_SICISR) & TXX9_SICISR_CTSS) ? 0 : TIOCM_CTS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443
444 return ret;
445}
446
447static void serial_txx9_set_mctrl(struct uart_port *port, unsigned int mctrl)
448{
449 struct uart_txx9_port *up = (struct uart_txx9_port *)port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 if (mctrl & TIOCM_RTS)
452 sio_mask(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSSC);
453 else
454 sio_set(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSSC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455}
456
457static void serial_txx9_break_ctl(struct uart_port *port, int break_state)
458{
459 struct uart_txx9_port *up = (struct uart_txx9_port *)port;
460 unsigned long flags;
461
462 spin_lock_irqsave(&up->port.lock, flags);
463 if (break_state == -1)
464 sio_set(up, TXX9_SIFLCR, TXX9_SIFLCR_TBRK);
465 else
466 sio_mask(up, TXX9_SIFLCR, TXX9_SIFLCR_TBRK);
467 spin_unlock_irqrestore(&up->port.lock, flags);
468}
469
470static int serial_txx9_startup(struct uart_port *port)
471{
472 struct uart_txx9_port *up = (struct uart_txx9_port *)port;
473 unsigned long flags;
474 int retval;
475
476 /*
477 * Clear the FIFO buffers and disable them.
Alexey Dobriyan7f927fc2006-03-28 01:56:53 -0800478 * (they will be reenabled in set_termios())
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479 */
480 sio_set(up, TXX9_SIFCR,
481 TXX9_SIFCR_TFRST | TXX9_SIFCR_RFRST | TXX9_SIFCR_FRSTE);
482 /* clear reset */
483 sio_mask(up, TXX9_SIFCR,
484 TXX9_SIFCR_TFRST | TXX9_SIFCR_RFRST | TXX9_SIFCR_FRSTE);
485 sio_out(up, TXX9_SIDICR, 0);
486
487 /*
488 * Clear the interrupt registers.
489 */
490 sio_out(up, TXX9_SIDISR, 0);
491
492 retval = request_irq(up->port.irq, serial_txx9_interrupt,
Thomas Gleixner40663cc2006-07-01 19:29:43 -0700493 IRQF_SHARED, "serial_txx9", up);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494 if (retval)
495 return retval;
496
497 /*
498 * Now, initialize the UART
499 */
500 spin_lock_irqsave(&up->port.lock, flags);
501 serial_txx9_set_mctrl(&up->port, up->port.mctrl);
502 spin_unlock_irqrestore(&up->port.lock, flags);
503
504 /* Enable RX/TX */
505 sio_mask(up, TXX9_SIFLCR, TXX9_SIFLCR_RSDE | TXX9_SIFLCR_TSDE);
506
507 /*
508 * Finally, enable interrupts.
509 */
510 sio_set(up, TXX9_SIDICR, TXX9_SIDICR_RIE);
511
512 return 0;
513}
514
515static void serial_txx9_shutdown(struct uart_port *port)
516{
517 struct uart_txx9_port *up = (struct uart_txx9_port *)port;
518 unsigned long flags;
519
520 /*
521 * Disable interrupts from this port
522 */
523 sio_out(up, TXX9_SIDICR, 0); /* disable all intrs */
524
525 spin_lock_irqsave(&up->port.lock, flags);
526 serial_txx9_set_mctrl(&up->port, up->port.mctrl);
527 spin_unlock_irqrestore(&up->port.lock, flags);
528
529 /*
530 * Disable break condition
531 */
532 sio_mask(up, TXX9_SIFLCR, TXX9_SIFLCR_TBRK);
533
534#ifdef CONFIG_SERIAL_TXX9_CONSOLE
535 if (up->port.cons && up->port.line == up->port.cons->index) {
536 free_irq(up->port.irq, up);
537 return;
538 }
539#endif
540 /* reset FIFOs */
541 sio_set(up, TXX9_SIFCR,
542 TXX9_SIFCR_TFRST | TXX9_SIFCR_RFRST | TXX9_SIFCR_FRSTE);
543 /* clear reset */
544 sio_mask(up, TXX9_SIFCR,
545 TXX9_SIFCR_TFRST | TXX9_SIFCR_RFRST | TXX9_SIFCR_FRSTE);
546
547 /* Disable RX/TX */
548 sio_set(up, TXX9_SIFLCR, TXX9_SIFLCR_RSDE | TXX9_SIFLCR_TSDE);
549
550 free_irq(up->port.irq, up);
551}
552
553static void
Alan Cox606d0992006-12-08 02:38:45 -0800554serial_txx9_set_termios(struct uart_port *port, struct ktermios *termios,
555 struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556{
557 struct uart_txx9_port *up = (struct uart_txx9_port *)port;
558 unsigned int cval, fcr = 0;
559 unsigned long flags;
560 unsigned int baud, quot;
561
562 cval = sio_in(up, TXX9_SILCR);
563 /* byte size and parity */
564 cval &= ~TXX9_SILCR_UMODE_MASK;
565 switch (termios->c_cflag & CSIZE) {
566 case CS7:
567 cval |= TXX9_SILCR_UMODE_7BIT;
568 break;
569 default:
570 case CS5: /* not supported */
571 case CS6: /* not supported */
572 case CS8:
573 cval |= TXX9_SILCR_UMODE_8BIT;
574 break;
575 }
576
577 cval &= ~TXX9_SILCR_USBL_MASK;
578 if (termios->c_cflag & CSTOPB)
579 cval |= TXX9_SILCR_USBL_2BIT;
580 else
581 cval |= TXX9_SILCR_USBL_1BIT;
582 cval &= ~(TXX9_SILCR_UPEN | TXX9_SILCR_UEPS);
583 if (termios->c_cflag & PARENB)
584 cval |= TXX9_SILCR_UPEN;
585 if (!(termios->c_cflag & PARODD))
586 cval |= TXX9_SILCR_UEPS;
587
588 /*
589 * Ask the core to calculate the divisor for us.
590 */
591 baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16/2);
592 quot = uart_get_divisor(port, baud);
593
594 /* Set up FIFOs */
595 /* TX Int by FIFO Empty, RX Int by Receiving 1 char. */
596 fcr = TXX9_SIFCR_TDIL_MAX | TXX9_SIFCR_RDIL_1;
597
598 /*
599 * Ok, we're now changing the port state. Do it with
600 * interrupts disabled.
601 */
602 spin_lock_irqsave(&up->port.lock, flags);
603
604 /*
605 * Update the per-port timeout.
606 */
607 uart_update_timeout(port, termios->c_cflag, baud);
608
609 up->port.read_status_mask = TXX9_SIDISR_UOER |
610 TXX9_SIDISR_TDIS | TXX9_SIDISR_RDIS;
611 if (termios->c_iflag & INPCK)
612 up->port.read_status_mask |= TXX9_SIDISR_UFER | TXX9_SIDISR_UPER;
613 if (termios->c_iflag & (BRKINT | PARMRK))
614 up->port.read_status_mask |= TXX9_SIDISR_UBRK;
615
616 /*
617 * Characteres to ignore
618 */
619 up->port.ignore_status_mask = 0;
620 if (termios->c_iflag & IGNPAR)
621 up->port.ignore_status_mask |= TXX9_SIDISR_UPER | TXX9_SIDISR_UFER;
622 if (termios->c_iflag & IGNBRK) {
623 up->port.ignore_status_mask |= TXX9_SIDISR_UBRK;
624 /*
625 * If we're ignoring parity and break indicators,
626 * ignore overruns too (for real raw support).
627 */
628 if (termios->c_iflag & IGNPAR)
629 up->port.ignore_status_mask |= TXX9_SIDISR_UOER;
630 }
631
632 /*
633 * ignore all characters if CREAD is not set
634 */
635 if ((termios->c_cflag & CREAD) == 0)
636 up->port.ignore_status_mask |= TXX9_SIDISR_RDIS;
637
638 /* CTS flow control flag */
639 if ((termios->c_cflag & CRTSCTS) &&
640 (up->port.flags & UPF_TXX9_HAVE_CTS_LINE)) {
641 sio_set(up, TXX9_SIFLCR,
642 TXX9_SIFLCR_RCS | TXX9_SIFLCR_TES);
643 } else {
644 sio_mask(up, TXX9_SIFLCR,
645 TXX9_SIFLCR_RCS | TXX9_SIFLCR_TES);
646 }
647
648 sio_out(up, TXX9_SILCR, cval);
649 sio_quot_set(up, quot);
650 sio_out(up, TXX9_SIFCR, fcr);
651
652 serial_txx9_set_mctrl(&up->port, up->port.mctrl);
653 spin_unlock_irqrestore(&up->port.lock, flags);
654}
655
656static void
657serial_txx9_pm(struct uart_port *port, unsigned int state,
658 unsigned int oldstate)
659{
660 struct uart_txx9_port *up = (struct uart_txx9_port *)port;
Ralf Baechlef5ee56c2005-09-09 13:01:32 -0700661 if (up->pm)
662 up->pm(port, state, oldstate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663}
664
665static int serial_txx9_request_resource(struct uart_txx9_port *up)
666{
667 unsigned int size = TXX9_REGION_SIZE;
668 int ret = 0;
669
670 switch (up->port.iotype) {
671 default:
672 if (!up->port.mapbase)
673 break;
674
675 if (!request_mem_region(up->port.mapbase, size, "serial_txx9")) {
676 ret = -EBUSY;
677 break;
678 }
679
680 if (up->port.flags & UPF_IOREMAP) {
681 up->port.membase = ioremap(up->port.mapbase, size);
682 if (!up->port.membase) {
683 release_mem_region(up->port.mapbase, size);
684 ret = -ENOMEM;
685 }
686 }
687 break;
688
689 case UPIO_PORT:
690 if (!request_region(up->port.iobase, size, "serial_txx9"))
691 ret = -EBUSY;
692 break;
693 }
694 return ret;
695}
696
697static void serial_txx9_release_resource(struct uart_txx9_port *up)
698{
699 unsigned int size = TXX9_REGION_SIZE;
700
701 switch (up->port.iotype) {
702 default:
703 if (!up->port.mapbase)
704 break;
705
706 if (up->port.flags & UPF_IOREMAP) {
707 iounmap(up->port.membase);
708 up->port.membase = NULL;
709 }
710
711 release_mem_region(up->port.mapbase, size);
712 break;
713
714 case UPIO_PORT:
715 release_region(up->port.iobase, size);
716 break;
717 }
718}
719
720static void serial_txx9_release_port(struct uart_port *port)
721{
722 struct uart_txx9_port *up = (struct uart_txx9_port *)port;
723 serial_txx9_release_resource(up);
724}
725
726static int serial_txx9_request_port(struct uart_port *port)
727{
728 struct uart_txx9_port *up = (struct uart_txx9_port *)port;
729 return serial_txx9_request_resource(up);
730}
731
732static void serial_txx9_config_port(struct uart_port *port, int uflags)
733{
734 struct uart_txx9_port *up = (struct uart_txx9_port *)port;
735 unsigned long flags;
736 int ret;
737
738 /*
739 * Find the region that we can probe for. This in turn
740 * tells us whether we can probe for the type of port.
741 */
742 ret = serial_txx9_request_resource(up);
743 if (ret < 0)
744 return;
745 port->type = PORT_TXX9;
746 up->port.fifosize = TXX9_SIO_TX_FIFO;
747
748#ifdef CONFIG_SERIAL_TXX9_CONSOLE
749 if (up->port.line == up->port.cons->index)
750 return;
751#endif
752 spin_lock_irqsave(&up->port.lock, flags);
753 /*
754 * Reset the UART.
755 */
756 sio_out(up, TXX9_SIFCR, TXX9_SIFCR_SWRST);
757#ifdef CONFIG_CPU_TX49XX
758 /* TX4925 BUG WORKAROUND. Accessing SIOC register
759 * immediately after soft reset causes bus error. */
760 iob();
761 udelay(1);
762#endif
763 while (sio_in(up, TXX9_SIFCR) & TXX9_SIFCR_SWRST)
764 ;
765 /* TX Int by FIFO Empty, RX Int by Receiving 1 char. */
766 sio_set(up, TXX9_SIFCR,
767 TXX9_SIFCR_TDIL_MAX | TXX9_SIFCR_RDIL_1);
768 /* initial settings */
769 sio_out(up, TXX9_SILCR,
770 TXX9_SILCR_UMODE_8BIT | TXX9_SILCR_USBL_1BIT |
771 ((up->port.flags & UPF_TXX9_USE_SCLK) ?
772 TXX9_SILCR_SCS_SCLK_BG : TXX9_SILCR_SCS_IMCLK_BG));
773 sio_quot_set(up, uart_get_divisor(port, 9600));
774 sio_out(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSTL_MAX /* 15 */);
775 spin_unlock_irqrestore(&up->port.lock, flags);
776}
777
778static int
779serial_txx9_verify_port(struct uart_port *port, struct serial_struct *ser)
780{
Atsushi Nemoto83485f82006-03-22 00:07:45 -0800781 unsigned long new_port = ser->port;
782 if (HIGH_BITS_OFFSET)
783 new_port += (unsigned long)ser->port_high << HIGH_BITS_OFFSET;
784 if (ser->type != port->type ||
785 ser->irq != port->irq ||
786 ser->io_type != port->iotype ||
787 new_port != port->iobase ||
788 (unsigned long)ser->iomem_base != port->mapbase)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 return -EINVAL;
790 return 0;
791}
792
793static const char *
794serial_txx9_type(struct uart_port *port)
795{
796 return "txx9";
797}
798
799static struct uart_ops serial_txx9_pops = {
800 .tx_empty = serial_txx9_tx_empty,
801 .set_mctrl = serial_txx9_set_mctrl,
802 .get_mctrl = serial_txx9_get_mctrl,
803 .stop_tx = serial_txx9_stop_tx,
804 .start_tx = serial_txx9_start_tx,
805 .stop_rx = serial_txx9_stop_rx,
806 .enable_ms = serial_txx9_enable_ms,
807 .break_ctl = serial_txx9_break_ctl,
808 .startup = serial_txx9_startup,
809 .shutdown = serial_txx9_shutdown,
810 .set_termios = serial_txx9_set_termios,
811 .pm = serial_txx9_pm,
812 .type = serial_txx9_type,
813 .release_port = serial_txx9_release_port,
814 .request_port = serial_txx9_request_port,
815 .config_port = serial_txx9_config_port,
816 .verify_port = serial_txx9_verify_port,
817};
818
819static struct uart_txx9_port serial_txx9_ports[UART_NR];
820
821static void __init serial_txx9_register_ports(struct uart_driver *drv)
822{
823 int i;
824
825 for (i = 0; i < UART_NR; i++) {
826 struct uart_txx9_port *up = &serial_txx9_ports[i];
827
828 up->port.line = i;
829 up->port.ops = &serial_txx9_pops;
Atsushi Nemoto83485f82006-03-22 00:07:45 -0800830 if (up->port.iobase || up->port.mapbase)
831 uart_add_one_port(drv, &up->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 }
833}
834
835#ifdef CONFIG_SERIAL_TXX9_CONSOLE
836
837/*
838 * Wait for transmitter & holding register to empty
839 */
840static inline void wait_for_xmitr(struct uart_txx9_port *up)
841{
842 unsigned int tmout = 10000;
843
844 /* Wait up to 10ms for the character(s) to be sent. */
845 while (--tmout &&
846 !(sio_in(up, TXX9_SICISR) & TXX9_SICISR_TXALS))
847 udelay(1);
848
849 /* Wait up to 1s for flow control if necessary */
850 if (up->port.flags & UPF_CONS_FLOW) {
851 tmout = 1000000;
852 while (--tmout &&
853 (sio_in(up, TXX9_SICISR) & TXX9_SICISR_CTSS))
854 udelay(1);
855 }
856}
857
Russell Kingd3587882006-03-20 20:00:09 +0000858static void serial_txx9_console_putchar(struct uart_port *port, int ch)
859{
860 struct uart_txx9_port *up = (struct uart_txx9_port *)port;
861
862 wait_for_xmitr(up);
863 sio_out(up, TXX9_SITFIFO, ch);
864}
865
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866/*
867 * Print a string to the serial port trying not to disturb
868 * any possible real use of the port...
869 *
870 * The console_lock must be held when we get here.
871 */
872static void
873serial_txx9_console_write(struct console *co, const char *s, unsigned int count)
874{
875 struct uart_txx9_port *up = &serial_txx9_ports[co->index];
876 unsigned int ier, flcr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877
878 /*
879 * First save the UER then disable the interrupts
880 */
881 ier = sio_in(up, TXX9_SIDICR);
882 sio_out(up, TXX9_SIDICR, 0);
883 /*
884 * Disable flow-control if enabled (and unnecessary)
885 */
886 flcr = sio_in(up, TXX9_SIFLCR);
887 if (!(up->port.flags & UPF_CONS_FLOW) && (flcr & TXX9_SIFLCR_TES))
888 sio_out(up, TXX9_SIFLCR, flcr & ~TXX9_SIFLCR_TES);
889
Russell Kingd3587882006-03-20 20:00:09 +0000890 uart_console_write(&up->port, s, count, serial_txx9_console_putchar);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891
892 /*
893 * Finally, wait for transmitter to become empty
894 * and restore the IER
895 */
896 wait_for_xmitr(up);
897 sio_out(up, TXX9_SIFLCR, flcr);
898 sio_out(up, TXX9_SIDICR, ier);
899}
900
901static int serial_txx9_console_setup(struct console *co, char *options)
902{
903 struct uart_port *port;
904 struct uart_txx9_port *up;
905 int baud = 9600;
906 int bits = 8;
907 int parity = 'n';
908 int flow = 'n';
909
910 /*
911 * Check whether an invalid uart number has been specified, and
912 * if so, search for the first available port that does have
913 * console support.
914 */
915 if (co->index >= UART_NR)
916 co->index = 0;
917 up = &serial_txx9_ports[co->index];
918 port = &up->port;
919 if (!port->ops)
920 return -ENODEV;
921
922 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923 * Disable UART interrupts, set DTR and RTS high
924 * and set speed.
925 */
926 sio_out(up, TXX9_SIDICR, 0);
927 /* initial settings */
928 sio_out(up, TXX9_SILCR,
929 TXX9_SILCR_UMODE_8BIT | TXX9_SILCR_USBL_1BIT |
930 ((port->flags & UPF_TXX9_USE_SCLK) ?
931 TXX9_SILCR_SCS_SCLK_BG : TXX9_SILCR_SCS_IMCLK_BG));
932 sio_out(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSTL_MAX /* 15 */);
933
934 if (options)
935 uart_parse_options(options, &baud, &parity, &bits, &flow);
936
937 return uart_set_options(port, co, baud, parity, bits, flow);
938}
939
940static struct uart_driver serial_txx9_reg;
941static struct console serial_txx9_console = {
942 .name = TXX9_TTY_NAME,
943 .write = serial_txx9_console_write,
944 .device = uart_console_device,
945 .setup = serial_txx9_console_setup,
946 .flags = CON_PRINTBUFFER,
947 .index = -1,
948 .data = &serial_txx9_reg,
949};
950
951static int __init serial_txx9_console_init(void)
952{
953 register_console(&serial_txx9_console);
954 return 0;
955}
956console_initcall(serial_txx9_console_init);
957
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958#define SERIAL_TXX9_CONSOLE &serial_txx9_console
959#else
960#define SERIAL_TXX9_CONSOLE NULL
961#endif
962
963static struct uart_driver serial_txx9_reg = {
964 .owner = THIS_MODULE,
965 .driver_name = "serial_txx9",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966 .dev_name = TXX9_TTY_NAME,
967 .major = TXX9_TTY_MAJOR,
968 .minor = TXX9_TTY_MINOR_START,
969 .nr = UART_NR,
970 .cons = SERIAL_TXX9_CONSOLE,
971};
972
973int __init early_serial_txx9_setup(struct uart_port *port)
974{
975 if (port->line >= ARRAY_SIZE(serial_txx9_ports))
976 return -ENODEV;
977
978 serial_txx9_ports[port->line].port = *port;
979 serial_txx9_ports[port->line].port.ops = &serial_txx9_pops;
980 serial_txx9_ports[port->line].port.flags |= UPF_BOOT_AUTOCONF;
981 return 0;
982}
983
984#ifdef ENABLE_SERIAL_TXX9_PCI
Atsushi Nemoto138c5d22007-02-10 01:45:05 -0800985#ifdef CONFIG_PM
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986/**
987 * serial_txx9_suspend_port - suspend one serial port
988 * @line: serial line number
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 *
990 * Suspend one serial port.
991 */
992static void serial_txx9_suspend_port(int line)
993{
994 uart_suspend_port(&serial_txx9_reg, &serial_txx9_ports[line].port);
995}
996
997/**
998 * serial_txx9_resume_port - resume one serial port
999 * @line: serial line number
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 *
1001 * Resume one serial port.
1002 */
1003static void serial_txx9_resume_port(int line)
1004{
1005 uart_resume_port(&serial_txx9_reg, &serial_txx9_ports[line].port);
1006}
Atsushi Nemoto138c5d22007-02-10 01:45:05 -08001007#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008
Arjan van de Venf392ecf2006-01-12 18:44:32 +00001009static DEFINE_MUTEX(serial_txx9_mutex);
Ralf Baechlef5ee56c2005-09-09 13:01:32 -07001010
1011/**
1012 * serial_txx9_register_port - register a serial port
1013 * @port: serial port template
1014 *
1015 * Configure the serial port specified by the request.
1016 *
1017 * The port is then probed and if necessary the IRQ is autodetected
1018 * If this fails an error is returned.
1019 *
1020 * On success the port is ready to use and the line number is returned.
1021 */
1022static int __devinit serial_txx9_register_port(struct uart_port *port)
1023{
1024 int i;
1025 struct uart_txx9_port *uart;
1026 int ret = -ENOSPC;
1027
Arjan van de Venf392ecf2006-01-12 18:44:32 +00001028 mutex_lock(&serial_txx9_mutex);
Ralf Baechlef5ee56c2005-09-09 13:01:32 -07001029 for (i = 0; i < UART_NR; i++) {
1030 uart = &serial_txx9_ports[i];
Atsushi Nemoto83485f82006-03-22 00:07:45 -08001031 if (!(uart->port.iobase || uart->port.mapbase))
Ralf Baechlef5ee56c2005-09-09 13:01:32 -07001032 break;
1033 }
1034 if (i < UART_NR) {
Ralf Baechlef5ee56c2005-09-09 13:01:32 -07001035 uart->port.iobase = port->iobase;
1036 uart->port.membase = port->membase;
1037 uart->port.irq = port->irq;
1038 uart->port.uartclk = port->uartclk;
1039 uart->port.iotype = port->iotype;
1040 uart->port.flags = port->flags | UPF_BOOT_AUTOCONF;
1041 uart->port.mapbase = port->mapbase;
1042 if (port->dev)
1043 uart->port.dev = port->dev;
1044 ret = uart_add_one_port(&serial_txx9_reg, &uart->port);
1045 if (ret == 0)
1046 ret = uart->port.line;
1047 }
Arjan van de Venf392ecf2006-01-12 18:44:32 +00001048 mutex_unlock(&serial_txx9_mutex);
Ralf Baechlef5ee56c2005-09-09 13:01:32 -07001049 return ret;
1050}
1051
1052/**
1053 * serial_txx9_unregister_port - remove a txx9 serial port at runtime
1054 * @line: serial line number
1055 *
1056 * Remove one serial port. This may not be called from interrupt
1057 * context. We hand the port back to the our control.
1058 */
1059static void __devexit serial_txx9_unregister_port(int line)
1060{
1061 struct uart_txx9_port *uart = &serial_txx9_ports[line];
1062
Arjan van de Venf392ecf2006-01-12 18:44:32 +00001063 mutex_lock(&serial_txx9_mutex);
Ralf Baechlef5ee56c2005-09-09 13:01:32 -07001064 uart_remove_one_port(&serial_txx9_reg, &uart->port);
1065 uart->port.flags = 0;
1066 uart->port.type = PORT_UNKNOWN;
1067 uart->port.iobase = 0;
1068 uart->port.mapbase = 0;
Atsushi Nemoto83485f82006-03-22 00:07:45 -08001069 uart->port.membase = NULL;
Ralf Baechlef5ee56c2005-09-09 13:01:32 -07001070 uart->port.dev = NULL;
Arjan van de Venf392ecf2006-01-12 18:44:32 +00001071 mutex_unlock(&serial_txx9_mutex);
Ralf Baechlef5ee56c2005-09-09 13:01:32 -07001072}
1073
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074/*
1075 * Probe one serial board. Unfortunately, there is no rhyme nor reason
1076 * to the arrangement of serial ports on a PCI card.
1077 */
1078static int __devinit
1079pciserial_txx9_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
1080{
1081 struct uart_port port;
1082 int line;
1083 int rc;
1084
1085 rc = pci_enable_device(dev);
1086 if (rc)
1087 return rc;
1088
1089 memset(&port, 0, sizeof(port));
1090 port.ops = &serial_txx9_pops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091 port.flags |= UPF_TXX9_HAVE_CTS_LINE;
1092 port.uartclk = 66670000;
1093 port.irq = dev->irq;
1094 port.iotype = UPIO_PORT;
1095 port.iobase = pci_resource_start(dev, 1);
Ralf Baechlef5ee56c2005-09-09 13:01:32 -07001096 port.dev = &dev->dev;
1097 line = serial_txx9_register_port(&port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098 if (line < 0) {
1099 printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), line);
1100 }
1101 pci_set_drvdata(dev, (void *)(long)line);
1102
1103 return 0;
1104}
1105
1106static void __devexit pciserial_txx9_remove_one(struct pci_dev *dev)
1107{
1108 int line = (int)(long)pci_get_drvdata(dev);
1109
1110 pci_set_drvdata(dev, NULL);
1111
1112 if (line) {
Ralf Baechlef5ee56c2005-09-09 13:01:32 -07001113 serial_txx9_unregister_port(line);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114 pci_disable_device(dev);
1115 }
1116}
1117
Atsushi Nemoto138c5d22007-02-10 01:45:05 -08001118#ifdef CONFIG_PM
Pavel Machek0370aff2005-04-16 15:25:35 -07001119static int pciserial_txx9_suspend_one(struct pci_dev *dev, pm_message_t state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120{
1121 int line = (int)(long)pci_get_drvdata(dev);
1122
1123 if (line)
1124 serial_txx9_suspend_port(line);
Ralf Baechlef5ee56c2005-09-09 13:01:32 -07001125 pci_save_state(dev);
1126 pci_set_power_state(dev, pci_choose_state(dev, state));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 return 0;
1128}
1129
1130static int pciserial_txx9_resume_one(struct pci_dev *dev)
1131{
1132 int line = (int)(long)pci_get_drvdata(dev);
1133
Ralf Baechlef5ee56c2005-09-09 13:01:32 -07001134 pci_set_power_state(dev, PCI_D0);
1135 pci_restore_state(dev);
1136
1137 if (line) {
1138 pci_enable_device(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139 serial_txx9_resume_port(line);
Ralf Baechlef5ee56c2005-09-09 13:01:32 -07001140 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141 return 0;
1142}
Atsushi Nemoto138c5d22007-02-10 01:45:05 -08001143#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144
Atsushi Nemoto138c5d22007-02-10 01:45:05 -08001145static const struct pci_device_id serial_txx9_pci_tbl[] = {
1146 { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC86C001_MISC) },
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 { 0, }
1148};
1149
1150static struct pci_driver serial_txx9_pci_driver = {
1151 .name = "serial_txx9",
1152 .probe = pciserial_txx9_init_one,
1153 .remove = __devexit_p(pciserial_txx9_remove_one),
Atsushi Nemoto138c5d22007-02-10 01:45:05 -08001154#ifdef CONFIG_PM
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155 .suspend = pciserial_txx9_suspend_one,
1156 .resume = pciserial_txx9_resume_one,
Atsushi Nemoto138c5d22007-02-10 01:45:05 -08001157#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158 .id_table = serial_txx9_pci_tbl,
1159};
1160
1161MODULE_DEVICE_TABLE(pci, serial_txx9_pci_tbl);
1162#endif /* ENABLE_SERIAL_TXX9_PCI */
1163
1164static int __init serial_txx9_init(void)
1165{
1166 int ret;
1167
1168 printk(KERN_INFO "%s version %s\n", serial_name, serial_version);
1169
1170 ret = uart_register_driver(&serial_txx9_reg);
1171 if (ret >= 0) {
1172 serial_txx9_register_ports(&serial_txx9_reg);
1173
1174#ifdef ENABLE_SERIAL_TXX9_PCI
Richard Knutsson93b47682005-11-30 01:00:35 +01001175 ret = pci_register_driver(&serial_txx9_pci_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176#endif
1177 }
1178 return ret;
1179}
1180
1181static void __exit serial_txx9_exit(void)
1182{
1183 int i;
1184
1185#ifdef ENABLE_SERIAL_TXX9_PCI
1186 pci_unregister_driver(&serial_txx9_pci_driver);
1187#endif
Atsushi Nemoto83485f82006-03-22 00:07:45 -08001188 for (i = 0; i < UART_NR; i++) {
1189 struct uart_txx9_port *up = &serial_txx9_ports[i];
1190 if (up->port.iobase || up->port.mapbase)
1191 uart_remove_one_port(&serial_txx9_reg, &up->port);
1192 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193
1194 uart_unregister_driver(&serial_txx9_reg);
1195}
1196
1197module_init(serial_txx9_init);
1198module_exit(serial_txx9_exit);
1199
1200MODULE_LICENSE("GPL");
1201MODULE_DESCRIPTION("TX39/49 serial driver");
1202
1203MODULE_ALIAS_CHARDEV_MAJOR(TXX9_TTY_MAJOR);