aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/tty/serial/8250/8250_pci.c309
-rw-r--r--include/linux/pci_ids.h15
2 files changed, 324 insertions, 0 deletions
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 26b9dc012ed0..89060ffb6b00 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -1040,6 +1040,253 @@ static int pci_asix_setup(struct serial_private *priv,
1040 return pci_default_setup(priv, board, port, idx); 1040 return pci_default_setup(priv, board, port, idx);
1041} 1041}
1042 1042
1043/* Quatech devices have their own extra interface features */
1044
1045struct quatech_feature {
1046 u16 devid;
1047 bool amcc;
1048};
1049
1050#define QPCR_TEST_FOR1 0x3F
1051#define QPCR_TEST_GET1 0x00
1052#define QPCR_TEST_FOR2 0x40
1053#define QPCR_TEST_GET2 0x40
1054#define QPCR_TEST_FOR3 0x80
1055#define QPCR_TEST_GET3 0x40
1056#define QPCR_TEST_FOR4 0xC0
1057#define QPCR_TEST_GET4 0x80
1058
1059#define QOPR_CLOCK_X1 0x0000
1060#define QOPR_CLOCK_X2 0x0001
1061#define QOPR_CLOCK_X4 0x0002
1062#define QOPR_CLOCK_X8 0x0003
1063#define QOPR_CLOCK_RATE_MASK 0x0003
1064
1065
1066static struct quatech_feature quatech_cards[] = {
1067 { PCI_DEVICE_ID_QUATECH_QSC100, 1 },
1068 { PCI_DEVICE_ID_QUATECH_DSC100, 1 },
1069 { PCI_DEVICE_ID_QUATECH_DSC100E, 0 },
1070 { PCI_DEVICE_ID_QUATECH_DSC200, 1 },
1071 { PCI_DEVICE_ID_QUATECH_DSC200E, 0 },
1072 { PCI_DEVICE_ID_QUATECH_ESC100D, 1 },
1073 { PCI_DEVICE_ID_QUATECH_ESC100M, 1 },
1074 { PCI_DEVICE_ID_QUATECH_QSCP100, 1 },
1075 { PCI_DEVICE_ID_QUATECH_DSCP100, 1 },
1076 { PCI_DEVICE_ID_QUATECH_QSCP200, 1 },
1077 { PCI_DEVICE_ID_QUATECH_DSCP200, 1 },
1078 { PCI_DEVICE_ID_QUATECH_ESCLP100, 0 },
1079 { PCI_DEVICE_ID_QUATECH_QSCLP100, 0 },
1080 { PCI_DEVICE_ID_QUATECH_DSCLP100, 0 },
1081 { PCI_DEVICE_ID_QUATECH_SSCLP100, 0 },
1082 { PCI_DEVICE_ID_QUATECH_QSCLP200, 0 },
1083 { PCI_DEVICE_ID_QUATECH_DSCLP200, 0 },
1084 { PCI_DEVICE_ID_QUATECH_SSCLP200, 0 },
1085 { PCI_DEVICE_ID_QUATECH_SPPXP_100, 0 },
1086 { 0, }
1087};
1088
1089static int pci_quatech_amcc(u16 devid)
1090{
1091 struct quatech_feature *qf = &quatech_cards[0];
1092 while (qf->devid) {
1093 if (qf->devid == devid)
1094 return qf->amcc;
1095 qf++;
1096 }
1097 pr_err("quatech: unknown port type '0x%04X'.\n", devid);
1098 return 0;
1099};
1100
1101static int pci_quatech_rqopr(struct uart_8250_port *port)
1102{
1103 unsigned long base = port->port.iobase;
1104 u8 LCR, val;
1105
1106 LCR = inb(base + UART_LCR);
1107 outb(0xBF, base + UART_LCR);
1108 val = inb(base + UART_SCR);
1109 outb(LCR, base + UART_LCR);
1110 return val;
1111}
1112
1113static void pci_quatech_wqopr(struct uart_8250_port *port, u8 qopr)
1114{
1115 unsigned long base = port->port.iobase;
1116 u8 LCR, val;
1117
1118 LCR = inb(base + UART_LCR);
1119 outb(0xBF, base + UART_LCR);
1120 val = inb(base + UART_SCR);
1121 outb(qopr, base + UART_SCR);
1122 outb(LCR, base + UART_LCR);
1123}
1124
1125static int pci_quatech_rqmcr(struct uart_8250_port *port)
1126{
1127 unsigned long base = port->port.iobase;
1128 u8 LCR, val, qmcr;
1129
1130 LCR = inb(base + UART_LCR);
1131 outb(0xBF, base + UART_LCR);
1132 val = inb(base + UART_SCR);
1133 outb(val | 0x10, base + UART_SCR);
1134 qmcr = inb(base + UART_MCR);
1135 outb(val, base + UART_SCR);
1136 outb(LCR, base + UART_LCR);
1137
1138 return qmcr;
1139}
1140
1141static void pci_quatech_wqmcr(struct uart_8250_port *port, u8 qmcr)
1142{
1143 unsigned long base = port->port.iobase;
1144 u8 LCR, val;
1145
1146 LCR = inb(base + UART_LCR);
1147 outb(0xBF, base + UART_LCR);
1148 val = inb(base + UART_SCR);
1149 outb(val | 0x10, base + UART_SCR);
1150 outb(qmcr, base + UART_MCR);
1151 outb(val, base + UART_SCR);
1152 outb(LCR, base + UART_LCR);
1153}
1154
1155static int pci_quatech_has_qmcr(struct uart_8250_port *port)
1156{
1157 unsigned long base = port->port.iobase;
1158 u8 LCR, val;
1159
1160 LCR = inb(base + UART_LCR);
1161 outb(0xBF, base + UART_LCR);
1162 val = inb(base + UART_SCR);
1163 if (val & 0x20) {
1164 outb(0x80, UART_LCR);
1165 if (!(inb(UART_SCR) & 0x20)) {
1166 outb(LCR, base + UART_LCR);
1167 return 1;
1168 }
1169 }
1170 return 0;
1171}
1172
1173static int pci_quatech_test(struct uart_8250_port *port)
1174{
1175 u8 reg;
1176 u8 qopr = pci_quatech_rqopr(port);
1177 pci_quatech_wqopr(port, qopr & QPCR_TEST_FOR1);
1178 reg = pci_quatech_rqopr(port) & 0xC0;
1179 if (reg != QPCR_TEST_GET1)
1180 return -EINVAL;
1181 pci_quatech_wqopr(port, (qopr & QPCR_TEST_FOR1)|QPCR_TEST_FOR2);
1182 reg = pci_quatech_rqopr(port) & 0xC0;
1183 if (reg != QPCR_TEST_GET2)
1184 return -EINVAL;
1185 pci_quatech_wqopr(port, (qopr & QPCR_TEST_FOR1)|QPCR_TEST_FOR3);
1186 reg = pci_quatech_rqopr(port) & 0xC0;
1187 if (reg != QPCR_TEST_GET3)
1188 return -EINVAL;
1189 pci_quatech_wqopr(port, (qopr & QPCR_TEST_FOR1)|QPCR_TEST_FOR4);
1190 reg = pci_quatech_rqopr(port) & 0xC0;
1191 if (reg != QPCR_TEST_GET4)
1192 return -EINVAL;
1193
1194 pci_quatech_wqopr(port, qopr);
1195 return 0;
1196}
1197
1198static int pci_quatech_clock(struct uart_8250_port *port)
1199{
1200 u8 qopr, reg, set;
1201 unsigned long clock;
1202
1203 if (pci_quatech_test(port) < 0)
1204 return 1843200;
1205
1206 qopr = pci_quatech_rqopr(port);
1207
1208 pci_quatech_wqopr(port, qopr & ~QOPR_CLOCK_X8);
1209 reg = pci_quatech_rqopr(port);
1210 if (reg & QOPR_CLOCK_X8) {
1211 clock = 1843200;
1212 goto out;
1213 }
1214 pci_quatech_wqopr(port, qopr | QOPR_CLOCK_X8);
1215 reg = pci_quatech_rqopr(port);
1216 if (!(reg & QOPR_CLOCK_X8)) {
1217 clock = 1843200;
1218 goto out;
1219 }
1220 reg &= QOPR_CLOCK_X8;
1221 if (reg == QOPR_CLOCK_X2) {
1222 clock = 3685400;
1223 set = QOPR_CLOCK_X2;
1224 } else if (reg == QOPR_CLOCK_X4) {
1225 clock = 7372800;
1226 set = QOPR_CLOCK_X4;
1227 } else if (reg == QOPR_CLOCK_X8) {
1228 clock = 14745600;
1229 set = QOPR_CLOCK_X8;
1230 } else {
1231 clock = 1843200;
1232 set = QOPR_CLOCK_X1;
1233 }
1234 qopr &= ~QOPR_CLOCK_RATE_MASK;
1235 qopr |= set;
1236
1237out:
1238 pci_quatech_wqopr(port, qopr);
1239 return clock;
1240}
1241
1242static int pci_quatech_rs422(struct uart_8250_port *port)
1243{
1244 u8 qmcr;
1245 int rs422 = 0;
1246
1247 if (!pci_quatech_has_qmcr(port))
1248 return 0;
1249 qmcr = pci_quatech_rqmcr(port);
1250 pci_quatech_wqmcr(port, 0xFF);
1251 if (pci_quatech_rqmcr(port))
1252 rs422 = 1;
1253 pci_quatech_wqmcr(port, qmcr);
1254 return rs422;
1255}
1256
1257static int pci_quatech_init(struct pci_dev *dev)
1258{
1259 if (pci_quatech_amcc(dev->device)) {
1260 unsigned long base = pci_resource_start(dev, 0);
1261 if (base) {
1262 u32 tmp;
1263 outl(inl(base + 0x38), base + 0x38);
1264 tmp = inl(base + 0x3c);
1265 outl(tmp | 0x01000000, base + 0x3c);
1266 outl(tmp, base + 0x3c);
1267 }
1268 }
1269 return 0;
1270}
1271
1272static int pci_quatech_setup(struct serial_private *priv,
1273 const struct pciserial_board *board,
1274 struct uart_8250_port *port, int idx)
1275{
1276 /* Needed by pci_quatech calls below */
1277 port->port.iobase = pci_resource_start(priv->dev, FL_GET_BASE(board->flags));
1278 /* Set up the clocking */
1279 port->port.uartclk = pci_quatech_clock(port);
1280 /* For now just warn about RS422 */
1281 if (pci_quatech_rs422(port))
1282 pr_warn("quatech: software control of RS422 features not currently supported.\n");
1283 return pci_default_setup(priv, board, port, idx);
1284}
1285
1286static void __devexit pci_quatech_exit(struct pci_dev *dev)
1287{
1288}
1289
1043static int pci_default_setup(struct serial_private *priv, 1290static int pci_default_setup(struct serial_private *priv,
1044 const struct pciserial_board *board, 1291 const struct pciserial_board *board,
1045 struct uart_8250_port *port, int idx) 1292 struct uart_8250_port *port, int idx)
@@ -1528,6 +1775,16 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
1528 .setup = pci_ni8430_setup, 1775 .setup = pci_ni8430_setup,
1529 .exit = pci_ni8430_exit, 1776 .exit = pci_ni8430_exit,
1530 }, 1777 },
1778 /* Quatech */
1779 {
1780 .vendor = PCI_VENDOR_ID_QUATECH,
1781 .device = PCI_ANY_ID,
1782 .subvendor = PCI_ANY_ID,
1783 .subdevice = PCI_ANY_ID,
1784 .init = pci_quatech_init,
1785 .setup = pci_quatech_setup,
1786 .exit = __devexit_p(pci_quatech_exit),
1787 },
1531 /* 1788 /*
1532 * Panacom 1789 * Panacom
1533 */ 1790 */
@@ -3475,18 +3732,70 @@ static struct pci_device_id serial_pci_tbl[] = {
3475 { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_ROMULUS, 3732 { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_ROMULUS,
3476 0x10b5, 0x106a, 0, 0, 3733 0x10b5, 0x106a, 0, 0,
3477 pbn_plx_romulus }, 3734 pbn_plx_romulus },
3735 /*
3736 * Quatech cards. These actually have configurable clocks but for
3737 * now we just use the default.
3738 *
3739 * 100 series are RS232, 200 series RS422,
3740 */
3478 { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSC100, 3741 { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSC100,
3479 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3742 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
3480 pbn_b1_4_115200 }, 3743 pbn_b1_4_115200 },
3481 { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSC100, 3744 { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSC100,
3482 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3745 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
3483 pbn_b1_2_115200 }, 3746 pbn_b1_2_115200 },
3747 { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSC100E,
3748 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
3749 pbn_b2_2_115200 },
3750 { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSC200,
3751 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
3752 pbn_b1_2_115200 },
3753 { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSC200E,
3754 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
3755 pbn_b2_2_115200 },
3756 { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSC200,
3757 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
3758 pbn_b1_4_115200 },
3484 { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100D, 3759 { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100D,
3485 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3760 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
3486 pbn_b1_8_115200 }, 3761 pbn_b1_8_115200 },
3487 { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100M, 3762 { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100M,
3488 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3763 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
3489 pbn_b1_8_115200 }, 3764 pbn_b1_8_115200 },
3765 { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSCP100,
3766 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
3767 pbn_b1_4_115200 },
3768 { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSCP100,
3769 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
3770 pbn_b1_2_115200 },
3771 { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSCP200,
3772 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
3773 pbn_b1_4_115200 },
3774 { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSCP200,
3775 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
3776 pbn_b1_2_115200 },
3777 { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSCLP100,
3778 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
3779 pbn_b2_4_115200 },
3780 { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSCLP100,
3781 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
3782 pbn_b2_2_115200 },
3783 { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_SSCLP100,
3784 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
3785 pbn_b2_1_115200 },
3786 { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSCLP200,
3787 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
3788 pbn_b2_4_115200 },
3789 { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSCLP200,
3790 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
3791 pbn_b2_2_115200 },
3792 { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_SSCLP200,
3793 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
3794 pbn_b2_1_115200 },
3795 { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESCLP100,
3796 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
3797 pbn_b0_8_115200 },
3798
3490 { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_OXSEMI_16PCI954, 3799 { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_OXSEMI_16PCI954,
3491 PCI_VENDOR_ID_SPECIALIX, PCI_SUBDEVICE_ID_SPECIALIX_SPEED4, 3800 PCI_VENDOR_ID_SPECIALIX, PCI_SUBDEVICE_ID_SPECIALIX_SPEED4,
3492 0, 0, 3801 0, 0,
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 0eb65796bcb9..19e8d7a42b34 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1868,8 +1868,23 @@
1868#define PCI_VENDOR_ID_QUATECH 0x135C 1868#define PCI_VENDOR_ID_QUATECH 0x135C
1869#define PCI_DEVICE_ID_QUATECH_QSC100 0x0010 1869#define PCI_DEVICE_ID_QUATECH_QSC100 0x0010
1870#define PCI_DEVICE_ID_QUATECH_DSC100 0x0020 1870#define PCI_DEVICE_ID_QUATECH_DSC100 0x0020
1871#define PCI_DEVICE_ID_QUATECH_DSC200 0x0030
1872#define PCI_DEVICE_ID_QUATECH_QSC200 0x0040
1871#define PCI_DEVICE_ID_QUATECH_ESC100D 0x0050 1873#define PCI_DEVICE_ID_QUATECH_ESC100D 0x0050
1872#define PCI_DEVICE_ID_QUATECH_ESC100M 0x0060 1874#define PCI_DEVICE_ID_QUATECH_ESC100M 0x0060
1875#define PCI_DEVICE_ID_QUATECH_QSCP100 0x0120
1876#define PCI_DEVICE_ID_QUATECH_DSCP100 0x0130
1877#define PCI_DEVICE_ID_QUATECH_QSCP200 0x0140
1878#define PCI_DEVICE_ID_QUATECH_DSCP200 0x0150
1879#define PCI_DEVICE_ID_QUATECH_QSCLP100 0x0170
1880#define PCI_DEVICE_ID_QUATECH_DSCLP100 0x0180
1881#define PCI_DEVICE_ID_QUATECH_DSC100E 0x0181
1882#define PCI_DEVICE_ID_QUATECH_SSCLP100 0x0190
1883#define PCI_DEVICE_ID_QUATECH_QSCLP200 0x01A0
1884#define PCI_DEVICE_ID_QUATECH_DSCLP200 0x01B0
1885#define PCI_DEVICE_ID_QUATECH_DSC200E 0x01B1
1886#define PCI_DEVICE_ID_QUATECH_SSCLP200 0x01C0
1887#define PCI_DEVICE_ID_QUATECH_ESCLP100 0x01E0
1873#define PCI_DEVICE_ID_QUATECH_SPPXP_100 0x0278 1888#define PCI_DEVICE_ID_QUATECH_SPPXP_100 0x0278
1874 1889
1875#define PCI_VENDOR_ID_SEALEVEL 0x135e 1890#define PCI_VENDOR_ID_SEALEVEL 0x135e