aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/parport/parport_serial.c339
-rw-r--r--drivers/serial/8250_pci.c21
-rw-r--r--include/linux/8250_pci.h3
-rw-r--r--include/linux/serialP.h40
4 files changed, 167 insertions, 236 deletions
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index 00498e2f1205..d3dad0aac7cb 100644
--- a/drivers/parport/parport_serial.c
+++ b/drivers/parport/parport_serial.c
@@ -23,13 +23,8 @@
23#include <linux/pci.h> 23#include <linux/pci.h>
24#include <linux/parport.h> 24#include <linux/parport.h>
25#include <linux/parport_pc.h> 25#include <linux/parport_pc.h>
26#include <linux/serial.h>
27#include <linux/serialP.h>
28#include <linux/list.h>
29#include <linux/8250_pci.h> 26#include <linux/8250_pci.h>
30 27
31#include <asm/serial.h>
32
33enum parport_pc_pci_cards { 28enum parport_pc_pci_cards {
34 titan_110l = 0, 29 titan_110l = 0,
35 titan_210l, 30 titan_210l,
@@ -168,182 +163,147 @@ static struct pci_device_id parport_serial_pci_tbl[] = {
168}; 163};
169MODULE_DEVICE_TABLE(pci,parport_serial_pci_tbl); 164MODULE_DEVICE_TABLE(pci,parport_serial_pci_tbl);
170 165
171struct pci_board_no_ids { 166/*
172 int flags; 167 * This table describes the serial "geometry" of these boards. Any
173 int num_ports; 168 * quirks for these can be found in drivers/serial/8250_pci.c
174 int base_baud; 169 *
175 int uart_offset; 170 * Cards not tested are marked n/t
176 int reg_shift; 171 * If you have one of these cards and it works for you, please tell me..
177 int (*init_fn)(struct pci_dev *dev, struct pci_board_no_ids *board, 172 */
178 int enable); 173static struct pciserial_board pci_parport_serial_boards[] __devinitdata = {
179 int first_uart_offset; 174 [titan_110l] = {
180}; 175 .flags = FL_BASE1 | FL_BASE_BARS,
181 176 .num_ports = 1,
182static int __devinit siig10x_init_fn(struct pci_dev *dev, struct pci_board_no_ids *board, int enable) 177 .base_baud = 921600,
183{ 178 .uart_offset = 8,
184 return pci_siig10x_fn(dev, enable); 179 },
185} 180 [titan_210l] = {
186 181 .flags = FL_BASE1 | FL_BASE_BARS,
187static int __devinit siig20x_init_fn(struct pci_dev *dev, struct pci_board_no_ids *board, int enable) 182 .num_ports = 2,
188{ 183 .base_baud = 921600,
189 return pci_siig20x_fn(dev, enable); 184 .uart_offset = 8,
190} 185 },
191 186 [netmos_9xx5_combo] = {
192static int __devinit netmos_serial_init(struct pci_dev *dev, struct pci_board_no_ids *board, int enable) 187 .flags = FL_BASE0 | FL_BASE_BARS,
193{ 188 .num_ports = 1,
194 board->num_ports = dev->subsystem_device & 0xf; 189 .base_baud = 115200,
195 return 0; 190 .uart_offset = 8,
196} 191 },
197 192 [netmos_9855] = {
198static struct pci_board_no_ids pci_boards[] __devinitdata = { 193 .flags = FL_BASE2 | FL_BASE_BARS,
199 /* 194 .num_ports = 1,
200 * PCI Flags, Number of Ports, Base (Maximum) Baud Rate, 195 .base_baud = 115200,
201 * Offset to get to next UART's registers, 196 .uart_offset = 8,
202 * Register shift to use for memory-mapped I/O, 197 },
203 * Initialization function, first UART offset 198 [avlab_1s1p] = { /* n/t */
204 */ 199 .flags = FL_BASE0 | FL_BASE_BARS,
205 200 .num_ports = 1,
206// Cards not tested are marked n/t 201 .base_baud = 115200,
207// If you have one of these cards and it works for you, please tell me.. 202 .uart_offset = 8,
208 203 },
209/* titan_110l */ { SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 1, 921600 }, 204 [avlab_1s1p_650] = { /* nt */
210/* titan_210l */ { SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 2, 921600 }, 205 .flags = FL_BASE0 | FL_BASE_BARS,
211/* netmos_9xx5_combo */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200, 0, 0, netmos_serial_init }, 206 .num_ports = 1,
212/* netmos_9855 */ { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 1, 115200, 0, 0, netmos_serial_init }, 207 .base_baud = 115200,
213/* avlab_1s1p (n/t) */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 }, 208 .uart_offset = 8,
214/* avlab_1s1p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 }, 209 },
215/* avlab_1s1p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 }, 210 [avlab_1s1p_850] = { /* nt */
216/* avlab_1s2p (n/t) */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 }, 211 .flags = FL_BASE0 | FL_BASE_BARS,
217/* avlab_1s2p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 }, 212 .num_ports = 1,
218/* avlab_1s2p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 }, 213 .base_baud = 115200,
219/* avlab_2s1p (n/t) */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 }, 214 .uart_offset = 8,
220/* avlab_2s1p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 }, 215 },
221/* avlab_2s1p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 }, 216 [avlab_1s2p] = { /* n/t */
222/* siig_1s1p_10x */ { SPCI_FL_BASE2, 1, 460800, 0, 0, siig10x_init_fn }, 217 .flags = FL_BASE0 | FL_BASE_BARS,
223/* siig_2s1p_10x */ { SPCI_FL_BASE2, 1, 921600, 0, 0, siig10x_init_fn }, 218 .num_ports = 1,
224/* siig_2p1s_20x */ { SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn }, 219 .base_baud = 115200,
225/* siig_1s1p_20x */ { SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn }, 220 .uart_offset = 8,
226/* siig_2s1p_20x */ { SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn }, 221 },
222 [avlab_1s2p_650] = { /* nt */
223 .flags = FL_BASE0 | FL_BASE_BARS,
224 .num_ports = 1,
225 .base_baud = 115200,
226 .uart_offset = 8,
227 },
228 [avlab_1s2p_850] = { /* nt */
229 .flags = FL_BASE0 | FL_BASE_BARS,
230 .num_ports = 1,
231 .base_baud = 115200,
232 .uart_offset = 8,
233 },
234 [avlab_2s1p] = { /* n/t */
235 .flags = FL_BASE0 | FL_BASE_BARS,
236 .num_ports = 2,
237 .base_baud = 115200,
238 .uart_offset = 8,
239 },
240 [avlab_2s1p_650] = { /* nt */
241 .flags = FL_BASE0 | FL_BASE_BARS,
242 .num_ports = 2,
243 .base_baud = 115200,
244 .uart_offset = 8,
245 },
246 [avlab_2s1p_850] = { /* nt */
247 .flags = FL_BASE0 | FL_BASE_BARS,
248 .num_ports = 2,
249 .base_baud = 115200,
250 .uart_offset = 8,
251 },
252 [siig_1s1p_10x] = {
253 .flags = FL_BASE2,
254 .num_ports = 1,
255 .base_baud = 460800,
256 .uart_offset = 8,
257 },
258 [siig_2s1p_10x] = {
259 .flags = FL_BASE2,
260 .num_ports = 1,
261 .base_baud = 921600,
262 .uart_offset = 8,
263 },
264 [siig_2p1s_20x] = {
265 .flags = FL_BASE0,
266 .num_ports = 1,
267 .base_baud = 921600,
268 .uart_offset = 8,
269 },
270 [siig_1s1p_20x] = {
271 .flags = FL_BASE0,
272 .num_ports = 1,
273 .base_baud = 921600,
274 .uart_offset = 8,
275 },
276 [siig_2s1p_20x] = {
277 .flags = FL_BASE0,
278 .num_ports = 1,
279 .base_baud = 921600,
280 .uart_offset = 8,
281 },
227}; 282};
228 283
229struct parport_serial_private { 284struct parport_serial_private {
230 int num_ser; 285 struct serial_private *serial;
231 int line[20];
232 struct pci_board_no_ids ser;
233 int num_par; 286 int num_par;
234 struct parport *port[PARPORT_MAX]; 287 struct parport *port[PARPORT_MAX];
235 struct parport_pc_pci par; 288 struct parport_pc_pci par;
236}; 289};
237 290
238static int __devinit get_pci_port (struct pci_dev *dev,
239 struct pci_board_no_ids *board,
240 struct serial_struct *req,
241 int idx)
242{
243 unsigned long port;
244 int base_idx;
245 int max_port;
246 int offset;
247
248 base_idx = SPCI_FL_GET_BASE(board->flags);
249 if (board->flags & SPCI_FL_BASE_TABLE)
250 base_idx += idx;
251
252 if (board->flags & SPCI_FL_REGION_SZ_CAP) {
253 max_port = pci_resource_len(dev, base_idx) / 8;
254 if (idx >= max_port)
255 return 1;
256 }
257
258 offset = board->first_uart_offset;
259
260 /* Timedia/SUNIX uses a mixture of BARs and offsets */
261 /* Ugh, this is ugly as all hell --- TYT */
262 if(dev->vendor == PCI_VENDOR_ID_TIMEDIA ) /* 0x1409 */
263 switch(idx) {
264 case 0: base_idx=0;
265 break;
266 case 1: base_idx=0; offset=8;
267 break;
268 case 2: base_idx=1;
269 break;
270 case 3: base_idx=1; offset=8;
271 break;
272 case 4: /* BAR 2*/
273 case 5: /* BAR 3 */
274 case 6: /* BAR 4*/
275 case 7: base_idx=idx-2; /* BAR 5*/
276 }
277
278 port = pci_resource_start(dev, base_idx) + offset;
279
280 if ((board->flags & SPCI_FL_BASE_TABLE) == 0)
281 port += idx * (board->uart_offset ? board->uart_offset : 8);
282
283 if (pci_resource_flags (dev, base_idx) & IORESOURCE_IO) {
284 int high_bits_offset = ((sizeof(long)-sizeof(int))*8);
285 req->port = port;
286 if (high_bits_offset)
287 req->port_high = port >> high_bits_offset;
288 else
289 req->port_high = 0;
290 return 0;
291 }
292 req->io_type = SERIAL_IO_MEM;
293 req->iomem_base = ioremap(port, board->uart_offset);
294 req->iomem_reg_shift = board->reg_shift;
295 req->port = 0;
296 return req->iomem_base ? 0 : 1;
297}
298
299/* Register the serial port(s) of a PCI card. */ 291/* Register the serial port(s) of a PCI card. */
300static int __devinit serial_register (struct pci_dev *dev, 292static int __devinit serial_register (struct pci_dev *dev,
301 const struct pci_device_id *id) 293 const struct pci_device_id *id)
302{ 294{
303 struct pci_board_no_ids *board;
304 struct parport_serial_private *priv = pci_get_drvdata (dev); 295 struct parport_serial_private *priv = pci_get_drvdata (dev);
305 struct serial_struct serial_req; 296 struct pciserial_board *board;
306 int base_baud; 297 struct serial_private *serial;
307 int k;
308 int success = 0;
309
310 priv->ser = pci_boards[id->driver_data];
311 board = &priv->ser;
312 if (board->init_fn && ((board->init_fn) (dev, board, 1) != 0))
313 return 1;
314
315 base_baud = board->base_baud;
316 if (!base_baud)
317 base_baud = BASE_BAUD;
318 memset (&serial_req, 0, sizeof (serial_req));
319
320 for (k = 0; k < board->num_ports; k++) {
321 int line;
322 298
323 if (priv->num_ser == ARRAY_SIZE (priv->line)) { 299 board = &pci_parport_serial_boards[id->driver_data];
324 printk (KERN_WARNING 300 serial = pciserial_init_ports(dev, board);
325 "parport_serial: %s: only %u serial lines "
326 "supported (%d reported)\n", pci_name (dev),
327 ARRAY_SIZE (priv->line), board->num_ports);
328 break;
329 }
330 301
331 serial_req.irq = dev->irq; 302 if (IS_ERR(serial))
332 if (get_pci_port (dev, board, &serial_req, k)) 303 return PTR_ERR(serial);
333 break;
334 serial_req.flags = ASYNC_SKIP_TEST | ASYNC_AUTOPROBE;
335 serial_req.baud_base = base_baud;
336 line = register_serial (&serial_req);
337 if (line < 0) {
338 printk (KERN_DEBUG
339 "parport_serial: register_serial failed\n");
340 continue;
341 }
342 priv->line[priv->num_ser++] = line;
343 success = 1;
344 }
345 304
346 return success ? 0 : 1; 305 priv->serial = serial;
306 return 0;
347} 307}
348 308
349/* Register the parallel port(s) of a PCI card. */ 309/* Register the parallel port(s) of a PCI card. */
@@ -411,7 +371,7 @@ static int __devinit parport_serial_pci_probe (struct pci_dev *dev,
411 priv = kmalloc (sizeof *priv, GFP_KERNEL); 371 priv = kmalloc (sizeof *priv, GFP_KERNEL);
412 if (!priv) 372 if (!priv)
413 return -ENOMEM; 373 return -ENOMEM;
414 priv->num_ser = priv->num_par = 0; 374 memset(priv, 0, sizeof(struct parport_serial_private));
415 pci_set_drvdata (dev, priv); 375 pci_set_drvdata (dev, priv);
416 376
417 err = pci_enable_device (dev); 377 err = pci_enable_device (dev);
@@ -444,15 +404,12 @@ static void __devexit parport_serial_pci_remove (struct pci_dev *dev)
444 struct parport_serial_private *priv = pci_get_drvdata (dev); 404 struct parport_serial_private *priv = pci_get_drvdata (dev);
445 int i; 405 int i;
446 406
407 pci_set_drvdata(dev, NULL);
408
447 // Serial ports 409 // Serial ports
448 for (i = 0; i < priv->num_ser; i++) { 410 if (priv->serial)
449 unregister_serial (priv->line[i]); 411 pciserial_remove_ports(priv->serial);
450 412
451 if (priv->ser.init_fn)
452 (priv->ser.init_fn) (dev, &priv->ser, 0);
453 }
454 pci_set_drvdata (dev, NULL);
455
456 // Parallel ports 413 // Parallel ports
457 for (i = 0; i < priv->num_par; i++) 414 for (i = 0; i < priv->num_par; i++)
458 parport_pc_unregister_port (priv->port[i]); 415 parport_pc_unregister_port (priv->port[i]);
@@ -461,11 +418,47 @@ static void __devexit parport_serial_pci_remove (struct pci_dev *dev)
461 return; 418 return;
462} 419}
463 420
421static int parport_serial_pci_suspend(struct pci_dev *dev, pm_message_t state)
422{
423 struct parport_serial_private *priv = pci_get_drvdata(dev);
424
425 if (priv->serial)
426 pciserial_suspend_ports(priv->serial);
427
428 /* FIXME: What about parport? */
429
430 pci_save_state(dev);
431 pci_set_power_state(dev, pci_choose_state(dev, state));
432 return 0;
433}
434
435static int parport_serial_pci_resume(struct pci_dev *dev)
436{
437 struct parport_serial_private *priv = pci_get_drvdata(dev);
438
439 pci_set_power_state(dev, PCI_D0);
440 pci_restore_state(dev);
441
442 /*
443 * The device may have been disabled. Re-enable it.
444 */
445 pci_enable_device(dev);
446
447 if (priv->serial)
448 pciserial_resume_ports(priv->serial);
449
450 /* FIXME: What about parport? */
451
452 return 0;
453}
454
464static struct pci_driver parport_serial_pci_driver = { 455static struct pci_driver parport_serial_pci_driver = {
465 .name = "parport_serial", 456 .name = "parport_serial",
466 .id_table = parport_serial_pci_tbl, 457 .id_table = parport_serial_pci_tbl,
467 .probe = parport_serial_pci_probe, 458 .probe = parport_serial_pci_probe,
468 .remove = __devexit_p(parport_serial_pci_remove), 459 .remove = __devexit_p(parport_serial_pci_remove),
460 .suspend = parport_serial_pci_suspend,
461 .resume = parport_serial_pci_resume,
469}; 462};
470 463
471 464
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index 4e9084edfc7e..52b0a0558ed4 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -46,7 +46,7 @@ struct pci_serial_quirk {
46 u32 subdevice; 46 u32 subdevice;
47 int (*init)(struct pci_dev *dev); 47 int (*init)(struct pci_dev *dev);
48 int (*setup)(struct serial_private *, struct pciserial_board *, 48 int (*setup)(struct serial_private *, struct pciserial_board *,
49 struct uart_port *port, int idx); 49 struct uart_port *, int);
50 void (*exit)(struct pci_dev *dev); 50 void (*exit)(struct pci_dev *dev);
51}; 51};
52 52
@@ -436,25 +436,6 @@ static int pci_siig_init(struct pci_dev *dev)
436 return -ENODEV; 436 return -ENODEV;
437} 437}
438 438
439int pci_siig10x_fn(struct pci_dev *dev, int enable)
440{
441 int ret = 0;
442 if (enable)
443 ret = pci_siig10x_init(dev);
444 return ret;
445}
446
447int pci_siig20x_fn(struct pci_dev *dev, int enable)
448{
449 int ret = 0;
450 if (enable)
451 ret = pci_siig20x_init(dev);
452 return ret;
453}
454
455EXPORT_SYMBOL(pci_siig10x_fn);
456EXPORT_SYMBOL(pci_siig20x_fn);
457
458/* 439/*
459 * Timedia has an explosion of boards, and to avoid the PCI table from 440 * Timedia has an explosion of boards, and to avoid the PCI table from
460 * growing *huge*, we use this function to collapse some 70 entries 441 * growing *huge*, we use this function to collapse some 70 entries
diff --git a/include/linux/8250_pci.h b/include/linux/8250_pci.h
index 192c0ff7a774..3209dd46ea7d 100644
--- a/include/linux/8250_pci.h
+++ b/include/linux/8250_pci.h
@@ -35,6 +35,3 @@ pciserial_init_ports(struct pci_dev *dev, struct pciserial_board *board);
35void pciserial_remove_ports(struct serial_private *priv); 35void pciserial_remove_ports(struct serial_private *priv);
36void pciserial_suspend_ports(struct serial_private *priv); 36void pciserial_suspend_ports(struct serial_private *priv);
37void pciserial_resume_ports(struct serial_private *priv); 37void pciserial_resume_ports(struct serial_private *priv);
38
39int pci_siig10x_fn(struct pci_dev *dev, int enable);
40int pci_siig20x_fn(struct pci_dev *dev, int enable);
diff --git a/include/linux/serialP.h b/include/linux/serialP.h
index 2b2f35a64d75..2b9e6b9554d5 100644
--- a/include/linux/serialP.h
+++ b/include/linux/serialP.h
@@ -140,44 +140,4 @@ struct rs_multiport_struct {
140#define ALPHA_KLUDGE_MCR 0 140#define ALPHA_KLUDGE_MCR 0
141#endif 141#endif
142 142
143/*
144 * Definitions for PCI support.
145 */
146#define SPCI_FL_BASE_MASK 0x0007
147#define SPCI_FL_BASE0 0x0000
148#define SPCI_FL_BASE1 0x0001
149#define SPCI_FL_BASE2 0x0002
150#define SPCI_FL_BASE3 0x0003
151#define SPCI_FL_BASE4 0x0004
152#define SPCI_FL_GET_BASE(x) (x & SPCI_FL_BASE_MASK)
153
154#define SPCI_FL_IRQ_MASK (0x0007 << 4)
155#define SPCI_FL_IRQBASE0 (0x0000 << 4)
156#define SPCI_FL_IRQBASE1 (0x0001 << 4)
157#define SPCI_FL_IRQBASE2 (0x0002 << 4)
158#define SPCI_FL_IRQBASE3 (0x0003 << 4)
159#define SPCI_FL_IRQBASE4 (0x0004 << 4)
160#define SPCI_FL_GET_IRQBASE(x) ((x & SPCI_FL_IRQ_MASK) >> 4)
161
162/* Use successive BARs (PCI base address registers),
163 else use offset into some specified BAR */
164#define SPCI_FL_BASE_TABLE 0x0100
165
166/* Use successive entries in the irq resource table */
167#define SPCI_FL_IRQ_TABLE 0x0200
168
169/* Use the irq resource table instead of dev->irq */
170#define SPCI_FL_IRQRESOURCE 0x0400
171
172/* Use the Base address register size to cap number of ports */
173#define SPCI_FL_REGION_SZ_CAP 0x0800
174
175/* Do not use irq sharing for this device */
176#define SPCI_FL_NO_SHIRQ 0x1000
177
178/* This is a PNP device */
179#define SPCI_FL_ISPNP 0x2000
180
181#define SPCI_FL_PNPDEFAULT (SPCI_FL_IRQRESOURCE|SPCI_FL_ISPNP)
182
183#endif /* _LINUX_SERIAL_H */ 143#endif /* _LINUX_SERIAL_H */