diff options
author | Nicos Gollan <gtdev@spearhead.de> | 2011-05-05 15:00:37 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-06-07 12:35:21 -0400 |
commit | 7808edcd306f22aeb23775d34e70b7fa2f58b852 (patch) | |
tree | b477dbde7a82a42940a2d5634571d3b1b8626a45 /drivers/parport/parport_serial.c | |
parent | 59c5f46fbe01a00eedf54a23789634438bb80603 (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.c | 66 |
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)) |