Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

serial: quatech: add the other serial identifiers and preliminary control code

Jonathan Woithe posted an out of tree enabler/control module for these
cards. Lift the relevant identifiers and put them in the 8250_pci driver
along with code used to control custom registers on these cards.

Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Jonathan Woithe <jwoithe@just42.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Alan Cox and committed by
Greg Kroah-Hartman
55c7c0fd 9931faca

+324
+309
drivers/tty/serial/8250/8250_pci.c
··· 1040 1040 return pci_default_setup(priv, board, port, idx); 1041 1041 } 1042 1042 1043 + /* Quatech devices have their own extra interface features */ 1044 + 1045 + struct 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 + 1066 + static 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 + 1089 + static 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 + 1101 + static 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 + 1113 + static 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 + 1125 + static 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 + 1141 + static 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 + 1155 + static 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 + 1173 + static 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 + 1198 + static 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 + 1237 + out: 1238 + pci_quatech_wqopr(port, qopr); 1239 + return clock; 1240 + } 1241 + 1242 + static 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 + 1257 + static 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 + 1272 + static 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 + 1286 + static void __devexit pci_quatech_exit(struct pci_dev *dev) 1287 + { 1288 + } 1289 + 1043 1290 static int pci_default_setup(struct serial_private *priv, 1044 1291 const struct pciserial_board *board, 1045 1292 struct uart_8250_port *port, int idx) ··· 1774 1527 .init = pci_ni8430_init, 1775 1528 .setup = pci_ni8430_setup, 1776 1529 .exit = pci_ni8430_exit, 1530 + }, 1531 + /* Quatech */ 1532 + { 1533 + .vendor = PCI_VENDOR_ID_QUATECH, 1534 + .device = PCI_ANY_ID, 1535 + .subvendor = PCI_ANY_ID, 1536 + .subdevice = PCI_ANY_ID, 1537 + .init = pci_quatech_init, 1538 + .setup = pci_quatech_setup, 1539 + .exit = __devexit_p(pci_quatech_exit), 1777 1540 }, 1778 1541 /* 1779 1542 * Panacom ··· 3732 3475 { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_ROMULUS, 3733 3476 0x10b5, 0x106a, 0, 0, 3734 3477 pbn_plx_romulus }, 3478 + /* 3479 + * Quatech cards. These actually have configurable clocks but for 3480 + * now we just use the default. 3481 + * 3482 + * 100 series are RS232, 200 series RS422, 3483 + */ 3735 3484 { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSC100, 3736 3485 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3737 3486 pbn_b1_4_115200 }, 3738 3487 { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSC100, 3739 3488 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3740 3489 pbn_b1_2_115200 }, 3490 + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSC100E, 3491 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3492 + pbn_b2_2_115200 }, 3493 + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSC200, 3494 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3495 + pbn_b1_2_115200 }, 3496 + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSC200E, 3497 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3498 + pbn_b2_2_115200 }, 3499 + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSC200, 3500 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3501 + pbn_b1_4_115200 }, 3741 3502 { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100D, 3742 3503 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3743 3504 pbn_b1_8_115200 }, 3744 3505 { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100M, 3745 3506 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3746 3507 pbn_b1_8_115200 }, 3508 + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSCP100, 3509 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3510 + pbn_b1_4_115200 }, 3511 + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSCP100, 3512 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3513 + pbn_b1_2_115200 }, 3514 + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSCP200, 3515 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3516 + pbn_b1_4_115200 }, 3517 + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSCP200, 3518 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3519 + pbn_b1_2_115200 }, 3520 + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSCLP100, 3521 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3522 + pbn_b2_4_115200 }, 3523 + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSCLP100, 3524 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3525 + pbn_b2_2_115200 }, 3526 + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_SSCLP100, 3527 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3528 + pbn_b2_1_115200 }, 3529 + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSCLP200, 3530 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3531 + pbn_b2_4_115200 }, 3532 + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSCLP200, 3533 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3534 + pbn_b2_2_115200 }, 3535 + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_SSCLP200, 3536 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3537 + pbn_b2_1_115200 }, 3538 + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESCLP100, 3539 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3540 + pbn_b0_8_115200 }, 3541 + 3747 3542 { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_OXSEMI_16PCI954, 3748 3543 PCI_VENDOR_ID_SPECIALIX, PCI_SUBDEVICE_ID_SPECIALIX_SPEED4, 3749 3544 0, 0,
+15
include/linux/pci_ids.h
··· 1868 1868 #define PCI_VENDOR_ID_QUATECH 0x135C 1869 1869 #define PCI_DEVICE_ID_QUATECH_QSC100 0x0010 1870 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 1873 #define PCI_DEVICE_ID_QUATECH_ESC100D 0x0050 1872 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 1888 #define PCI_DEVICE_ID_QUATECH_SPPXP_100 0x0278 1874 1889 1875 1890 #define PCI_VENDOR_ID_SEALEVEL 0x135e