aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/parport/parport_serial.c
diff options
context:
space:
mode:
authorNicos Gollan <gtdev@spearhead.de>2011-05-05 15:00:37 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2011-06-07 12:35:21 -0400
commit7808edcd306f22aeb23775d34e70b7fa2f58b852 (patch)
treeb477dbde7a82a42940a2d5634571d3b1b8626a45 /drivers/parport/parport_serial.c
parent59c5f46fbe01a00eedf54a23789634438bb80603 (diff)
Basic support for Moschip 9900 family I/O chips
Add I/O based support for serial and parallel ports of the following chips: Vendor: Moschip (0x9710) Parts (device IDs) * 9900 (0x9900) * 9904 (0x9904 * 9901 (0x9912, also sold as 9912) * 9922 (0x9922) On all chips but the 9900, a single port is provided per PCI subdevice (subvendor-ID 0xA000, subdevice-IDs 0x1000 for serial, 0x2000 for parallel with proper class codes). In cascading configurations, the 9900 provides two devices per subdevice, with subvendor-ID 0xA000 and subdevice-IDs 0x30ps where p is the number of parallel ports and s the number of serial ports. Basic testing was only done on the serial part of a 9912 to the point where it can be used for a serial kernel console, and advanced features are completely untested. It is possible to reduce functionality of the chips by adding a configuration EEPROM, and the datasheet [1] is inconsistent w.r.t subdevices in the 4s+2s1p and 2s1p+4s configurations. The subdevice-ID 0x3012 should likely read 0x3011 with a serial port in function 3, which would be consistent with the BAR layouts. For now, the drivers ignore subdevices with ID 0x1000 and no class code. The parallel ports are integrated in parport_serial even for purely parallel parts to reduce the footprint of the patch. [1] http://www.moschip.com/data/products/MCS9900/MCS9900_Datasheet.pdf Signed-off-by: Nicos Gollan <gtdev@spearhead.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/parport/parport_serial.c')
-rw-r--r--drivers/parport/parport_serial.c66
1 files changed, 50 insertions, 16 deletions
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index f01e26440f11..342a3de6c674 100644
--- a/drivers/parport/parport_serial.c
+++ b/drivers/parport/parport_serial.c
@@ -33,6 +33,9 @@ enum parport_pc_pci_cards {
33 netmos_9xx5_combo, 33 netmos_9xx5_combo,
34 netmos_9855, 34 netmos_9855,
35 netmos_9855_2p, 35 netmos_9855_2p,
36 netmos_9900,
37 netmos_9900_2p,
38 netmos_99xx_1p,
36 avlab_1s1p, 39 avlab_1s1p,
37 avlab_1s2p, 40 avlab_1s2p,
38 avlab_2s1p, 41 avlab_2s1p,
@@ -72,22 +75,20 @@ static int __devinit netmos_parallel_init(struct pci_dev *dev, struct parport_pc
72 dev->subsystem_vendor == PCI_VENDOR_ID_IBM && 75 dev->subsystem_vendor == PCI_VENDOR_ID_IBM &&
73 dev->subsystem_device == 0x0299) 76 dev->subsystem_device == 0x0299)
74 return -ENODEV; 77 return -ENODEV;
75 /* 78
76 * Netmos uses the subdevice ID to indicate the number of parallel 79 if (dev->device == PCI_DEVICE_ID_NETMOS_9912) {
77 * and serial ports. The form is 0x00PS, where <P> is the number of 80 par->numports = 1;
78 * parallel ports and <S> is the number of serial ports. 81 } else {
79 */ 82 /*
80 par->numports = (dev->subsystem_device & 0xf0) >> 4; 83 * Netmos uses the subdevice ID to indicate the number of parallel
81 if (par->numports > ARRAY_SIZE(par->addr)) 84 * and serial ports. The form is 0x00PS, where <P> is the number of
82 par->numports = ARRAY_SIZE(par->addr); 85 * parallel ports and <S> is the number of serial ports.
83 /* 86 */
84 * This function is currently only called for cards with up to 87 par->numports = (dev->subsystem_device & 0xf0) >> 4;
85 * one parallel port. 88 if (par->numports > ARRAY_SIZE(par->addr))
86 * Parallel port BAR is either before or after serial ports BARS; 89 par->numports = ARRAY_SIZE(par->addr);
87 * hence, lo should be either 0 or equal to the number of serial ports. 90 }
88 */ 91
89 if (par->addr[0].lo != 0)
90 par->addr[0].lo = dev->subsystem_device & 0xf;
91 return 0; 92 return 0;
92} 93}
93 94
@@ -97,6 +98,9 @@ static struct parport_pc_pci cards[] __devinitdata = {
97 /* netmos_9xx5_combo */ { 1, { { 2, -1 }, }, netmos_parallel_init }, 98 /* netmos_9xx5_combo */ { 1, { { 2, -1 }, }, netmos_parallel_init },
98 /* netmos_9855 */ { 1, { { 0, -1 }, }, netmos_parallel_init }, 99 /* netmos_9855 */ { 1, { { 0, -1 }, }, netmos_parallel_init },
99 /* netmos_9855_2p */ { 2, { { 0, -1 }, { 2, -1 }, } }, 100 /* netmos_9855_2p */ { 2, { { 0, -1 }, { 2, -1 }, } },
101 /* netmos_9900 */ {1, { { 3, 4 }, }, netmos_parallel_init },
102 /* netmos_9900_2p */ {2, { { 0, 1 }, { 3, 4 }, } },
103 /* netmos_99xx_1p */ {1, { { 0, 1 }, } },
100 /* avlab_1s1p */ { 1, { { 1, 2}, } }, 104 /* avlab_1s1p */ { 1, { { 1, 2}, } },
101 /* avlab_1s2p */ { 2, { { 1, 2}, { 3, 4 },} }, 105 /* avlab_1s2p */ { 2, { { 1, 2}, { 3, 4 },} },
102 /* avlab_2s1p */ { 1, { { 2, 3}, } }, 106 /* avlab_2s1p */ { 1, { { 2, 3}, } },
@@ -127,6 +131,14 @@ static struct pci_device_id parport_serial_pci_tbl[] = {
127 0x1000, 0x0022, 0, 0, netmos_9855_2p }, 131 0x1000, 0x0022, 0, 0, netmos_9855_2p },
128 { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855, 132 { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855,
129 PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9855 }, 133 PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9855 },
134 { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
135 0xA000, 0x3011, 0, 0, netmos_9900 },
136 { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
137 0xA000, 0x3012, 0, 0, netmos_9900 },
138 { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
139 0xA000, 0x3020, 0, 0, netmos_9900_2p },
140 { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9912,
141 0xA000, 0x2000, 0, 0, netmos_99xx_1p },
130 /* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/ 142 /* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/
131 { PCI_VENDOR_ID_AFAVLAB, 0x2110, 143 { PCI_VENDOR_ID_AFAVLAB, 0x2110,
132 PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p }, 144 PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p },
@@ -219,6 +231,24 @@ static struct pciserial_board pci_parport_serial_boards[] __devinitdata = {
219 .base_baud = 115200, 231 .base_baud = 115200,
220 .uart_offset = 8, 232 .uart_offset = 8,
221 }, 233 },
234 [netmos_9900] = { /* n/t */
235 .flags = FL_BASE0 | FL_BASE_BARS,
236 .num_ports = 1,
237 .base_baud = 115200,
238 .uart_offset = 8,
239 },
240 [netmos_9900_2p] = { /* parallel only */ /* n/t */
241 .flags = FL_BASE0,
242 .num_ports = 0,
243 .base_baud = 115200,
244 .uart_offset = 8,
245 },
246 [netmos_99xx_1p] = { /* parallel only */ /* n/t */
247 .flags = FL_BASE0,
248 .num_ports = 0,
249 .base_baud = 115200,
250 .uart_offset = 8,
251 },
222 [avlab_1s1p] = { /* n/t */ 252 [avlab_1s1p] = { /* n/t */
223 .flags = FL_BASE0 | FL_BASE_BARS, 253 .flags = FL_BASE0 | FL_BASE_BARS,
224 .num_ports = 1, 254 .num_ports = 1,
@@ -285,6 +315,10 @@ static int __devinit serial_register (struct pci_dev *dev,
285 struct serial_private *serial; 315 struct serial_private *serial;
286 316
287 board = &pci_parport_serial_boards[id->driver_data]; 317 board = &pci_parport_serial_boards[id->driver_data];
318
319 if (board->num_ports == 0)
320 return 0;
321
288 serial = pciserial_init_ports(dev, board); 322 serial = pciserial_init_ports(dev, board);
289 323
290 if (IS_ERR(serial)) 324 if (IS_ERR(serial))