aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/parport/parport_serial.c66
-rw-r--r--drivers/tty/serial/8250_pci.c104
-rw-r--r--include/linux/pci_ids.h4
3 files changed, 157 insertions, 17 deletions
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index f01e26440f1..342a3de6c67 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))
diff --git a/drivers/tty/serial/8250_pci.c b/drivers/tty/serial/8250_pci.c
index 4b4968a294b..0b255cef57e 100644
--- a/drivers/tty/serial/8250_pci.c
+++ b/drivers/tty/serial/8250_pci.c
@@ -56,6 +56,9 @@ struct serial_private {
56 int line[0]; 56 int line[0];
57}; 57};
58 58
59static int pci_default_setup(struct serial_private*,
60 const struct pciserial_board*, struct uart_port*, int);
61
59static void moan_device(const char *str, struct pci_dev *dev) 62static void moan_device(const char *str, struct pci_dev *dev)
60{ 63{
61 printk(KERN_WARNING 64 printk(KERN_WARNING
@@ -752,6 +755,62 @@ pci_ni8430_setup(struct serial_private *priv,
752 return setup_port(priv, port, bar, offset, board->reg_shift); 755 return setup_port(priv, port, bar, offset, board->reg_shift);
753} 756}
754 757
758static int pci_netmos_9900_setup(struct serial_private *priv,
759 const struct pciserial_board *board,
760 struct uart_port *port, int idx)
761{
762 unsigned int bar;
763
764 if ((priv->dev->subsystem_device & 0xff00) == 0x3000) {
765 /* netmos apparently orders BARs by datasheet layout, so serial
766 * ports get BARs 0 and 3 (or 1 and 4 for memmapped)
767 */
768 bar = 3 * idx;
769
770 return setup_port(priv, port, bar, 0, board->reg_shift);
771 } else {
772 return pci_default_setup(priv, board, port, idx);
773 }
774}
775
776/* the 99xx series comes with a range of device IDs and a variety
777 * of capabilities:
778 *
779 * 9900 has varying capabilities and can cascade to sub-controllers
780 * (cascading should be purely internal)
781 * 9904 is hardwired with 4 serial ports
782 * 9912 and 9922 are hardwired with 2 serial ports
783 */
784static int pci_netmos_9900_numports(struct pci_dev *dev)
785{
786 unsigned int c = dev->class;
787 unsigned int pi;
788 unsigned short sub_serports;
789
790 pi = (c & 0xff);
791
792 if (pi == 2) {
793 return 1;
794 } else if ((pi == 0) &&
795 (dev->device == PCI_DEVICE_ID_NETMOS_9900)) {
796 /* two possibilities: 0x30ps encodes number of parallel and
797 * serial ports, or 0x1000 indicates *something*. This is not
798 * immediately obvious, since the 2s1p+4s configuration seems
799 * to offer all functionality on functions 0..2, while still
800 * advertising the same function 3 as the 4s+2s1p config.
801 */
802 sub_serports = dev->subsystem_device & 0xf;
803 if (sub_serports > 0) {
804 return sub_serports;
805 } else {
806 printk(KERN_NOTICE "NetMos/Mostech serial driver ignoring port on ambiguous config.\n");
807 return 0;
808 }
809 }
810
811 moan_device("unknown NetMos/Mostech program interface", dev);
812 return 0;
813}
755 814
756static int pci_netmos_init(struct pci_dev *dev) 815static int pci_netmos_init(struct pci_dev *dev)
757{ 816{
@@ -761,12 +820,28 @@ static int pci_netmos_init(struct pci_dev *dev)
761 if ((dev->device == PCI_DEVICE_ID_NETMOS_9901) || 820 if ((dev->device == PCI_DEVICE_ID_NETMOS_9901) ||
762 (dev->device == PCI_DEVICE_ID_NETMOS_9865)) 821 (dev->device == PCI_DEVICE_ID_NETMOS_9865))
763 return 0; 822 return 0;
823
764 if (dev->subsystem_vendor == PCI_VENDOR_ID_IBM && 824 if (dev->subsystem_vendor == PCI_VENDOR_ID_IBM &&
765 dev->subsystem_device == 0x0299) 825 dev->subsystem_device == 0x0299)
766 return 0; 826 return 0;
767 827
828 switch (dev->device) { /* FALLTHROUGH on all */
829 case PCI_DEVICE_ID_NETMOS_9904:
830 case PCI_DEVICE_ID_NETMOS_9912:
831 case PCI_DEVICE_ID_NETMOS_9922:
832 case PCI_DEVICE_ID_NETMOS_9900:
833 num_serial = pci_netmos_9900_numports(dev);
834 break;
835
836 default:
837 if (num_serial == 0 ) {
838 moan_device("unknown NetMos/Mostech device", dev);
839 }
840 }
841
768 if (num_serial == 0) 842 if (num_serial == 0)
769 return -ENODEV; 843 return -ENODEV;
844
770 return num_serial; 845 return num_serial;
771} 846}
772 847
@@ -1417,7 +1492,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
1417 .subvendor = PCI_ANY_ID, 1492 .subvendor = PCI_ANY_ID,
1418 .subdevice = PCI_ANY_ID, 1493 .subdevice = PCI_ANY_ID,
1419 .init = pci_netmos_init, 1494 .init = pci_netmos_init,
1420 .setup = pci_default_setup, 1495 .setup = pci_netmos_9900_setup,
1421 }, 1496 },
1422 /* 1497 /*
1423 * For Oxford Semiconductor Tornado based devices 1498 * For Oxford Semiconductor Tornado based devices
@@ -1644,6 +1719,7 @@ enum pci_board_num_t {
1644 pbn_ADDIDATA_PCIe_8_3906250, 1719 pbn_ADDIDATA_PCIe_8_3906250,
1645 pbn_ce4100_1_115200, 1720 pbn_ce4100_1_115200,
1646 pbn_omegapci, 1721 pbn_omegapci,
1722 pbn_NETMOS9900_2s_115200,
1647}; 1723};
1648 1724
1649/* 1725/*
@@ -2345,6 +2421,11 @@ static struct pciserial_board pci_boards[] __devinitdata = {
2345 .base_baud = 115200, 2421 .base_baud = 115200,
2346 .uart_offset = 0x200, 2422 .uart_offset = 0x200,
2347 }, 2423 },
2424 [pbn_NETMOS9900_2s_115200] = {
2425 .flags = FL_BASE0,
2426 .num_ports = 2,
2427 .base_baud = 115200,
2428 },
2348}; 2429};
2349 2430
2350static const struct pci_device_id softmodem_blacklist[] = { 2431static const struct pci_device_id softmodem_blacklist[] = {
@@ -3826,6 +3907,27 @@ static struct pci_device_id serial_pci_tbl[] = {
3826 0xA000, 0x1000, 3907 0xA000, 0x1000,
3827 0, 0, pbn_b0_1_115200 }, 3908 0, 0, pbn_b0_1_115200 },
3828 3909
3910 /* the 9901 is a rebranded 9912 */
3911 { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9912,
3912 0xA000, 0x1000,
3913 0, 0, pbn_b0_1_115200 },
3914
3915 { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9922,
3916 0xA000, 0x1000,
3917 0, 0, pbn_b0_1_115200 },
3918
3919 { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9904,
3920 0xA000, 0x1000,
3921 0, 0, pbn_b0_1_115200 },
3922
3923 { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
3924 0xA000, 0x1000,
3925 0, 0, pbn_b0_1_115200 },
3926
3927 { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
3928 0xA000, 0x3002,
3929 0, 0, pbn_NETMOS9900_2s_115200 },
3930
3829 /* 3931 /*
3830 * Best Connectivity PCI Multi I/O cards 3932 * Best Connectivity PCI Multi I/O cards
3831 */ 3933 */
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index a311008af5e..034ebb4451c 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -2821,7 +2821,11 @@
2821#define PCI_DEVICE_ID_NETMOS_9845 0x9845 2821#define PCI_DEVICE_ID_NETMOS_9845 0x9845
2822#define PCI_DEVICE_ID_NETMOS_9855 0x9855 2822#define PCI_DEVICE_ID_NETMOS_9855 0x9855
2823#define PCI_DEVICE_ID_NETMOS_9865 0x9865 2823#define PCI_DEVICE_ID_NETMOS_9865 0x9865
2824#define PCI_DEVICE_ID_NETMOS_9900 0x9900
2824#define PCI_DEVICE_ID_NETMOS_9901 0x9901 2825#define PCI_DEVICE_ID_NETMOS_9901 0x9901
2826#define PCI_DEVICE_ID_NETMOS_9904 0x9904
2827#define PCI_DEVICE_ID_NETMOS_9912 0x9912
2828#define PCI_DEVICE_ID_NETMOS_9922 0x9922
2825 2829
2826#define PCI_VENDOR_ID_3COM_2 0xa727 2830#define PCI_VENDOR_ID_3COM_2 0xa727
2827 2831