1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Probe for 8250/16550-type ISAPNP serial ports.
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Copyright (C) 2001 Russell King, All Rights Reserved.
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * Ported to the Linux PnP Layer - (C) Adam Belay.
10*4882a593Smuzhiyun */
11*4882a593Smuzhiyun #include <linux/module.h>
12*4882a593Smuzhiyun #include <linux/pci.h>
13*4882a593Smuzhiyun #include <linux/pnp.h>
14*4882a593Smuzhiyun #include <linux/string.h>
15*4882a593Smuzhiyun #include <linux/kernel.h>
16*4882a593Smuzhiyun #include <linux/serial_core.h>
17*4882a593Smuzhiyun #include <linux/bitops.h>
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun #include <asm/byteorder.h>
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun #include "8250.h"
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun #define UNKNOWN_DEV 0x3000
24*4882a593Smuzhiyun #define CIR_PORT 0x0800
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun static const struct pnp_device_id pnp_dev_table[] = {
27*4882a593Smuzhiyun /* Archtek America Corp. */
28*4882a593Smuzhiyun /* Archtek SmartLink Modem 3334BT Plug & Play */
29*4882a593Smuzhiyun { "AAC000F", 0 },
30*4882a593Smuzhiyun /* Anchor Datacomm BV */
31*4882a593Smuzhiyun /* SXPro 144 External Data Fax Modem Plug & Play */
32*4882a593Smuzhiyun { "ADC0001", 0 },
33*4882a593Smuzhiyun /* SXPro 288 External Data Fax Modem Plug & Play */
34*4882a593Smuzhiyun { "ADC0002", 0 },
35*4882a593Smuzhiyun /* PROLiNK 1456VH ISA PnP K56flex Fax Modem */
36*4882a593Smuzhiyun { "AEI0250", 0 },
37*4882a593Smuzhiyun /* Actiontec ISA PNP 56K X2 Fax Modem */
38*4882a593Smuzhiyun { "AEI1240", 0 },
39*4882a593Smuzhiyun /* Rockwell 56K ACF II Fax+Data+Voice Modem */
40*4882a593Smuzhiyun { "AKY1021", 0 /*SPCI_FL_NO_SHIRQ*/ },
41*4882a593Smuzhiyun /*
42*4882a593Smuzhiyun * ALi Fast Infrared Controller
43*4882a593Smuzhiyun * Native driver (ali-ircc) is broken so at least
44*4882a593Smuzhiyun * it can be used with irtty-sir.
45*4882a593Smuzhiyun */
46*4882a593Smuzhiyun { "ALI5123", 0 },
47*4882a593Smuzhiyun /* AZT3005 PnP SOUND DEVICE */
48*4882a593Smuzhiyun { "AZT4001", 0 },
49*4882a593Smuzhiyun /* Best Data Products Inc. Smart One 336F PnP Modem */
50*4882a593Smuzhiyun { "BDP3336", 0 },
51*4882a593Smuzhiyun /* Boca Research */
52*4882a593Smuzhiyun /* Boca Complete Ofc Communicator 14.4 Data-FAX */
53*4882a593Smuzhiyun { "BRI0A49", 0 },
54*4882a593Smuzhiyun /* Boca Research 33,600 ACF Modem */
55*4882a593Smuzhiyun { "BRI1400", 0 },
56*4882a593Smuzhiyun /* Boca 33.6 Kbps Internal FD34FSVD */
57*4882a593Smuzhiyun { "BRI3400", 0 },
58*4882a593Smuzhiyun /* Boca 33.6 Kbps Internal FD34FSVD */
59*4882a593Smuzhiyun { "BRI0A49", 0 },
60*4882a593Smuzhiyun /* Best Data Products Inc. Smart One 336F PnP Modem */
61*4882a593Smuzhiyun { "BDP3336", 0 },
62*4882a593Smuzhiyun /* Computer Peripherals Inc */
63*4882a593Smuzhiyun /* EuroViVa CommCenter-33.6 SP PnP */
64*4882a593Smuzhiyun { "CPI4050", 0 },
65*4882a593Smuzhiyun /* Creative Labs */
66*4882a593Smuzhiyun /* Creative Labs Phone Blaster 28.8 DSVD PnP Voice */
67*4882a593Smuzhiyun { "CTL3001", 0 },
68*4882a593Smuzhiyun /* Creative Labs Modem Blaster 28.8 DSVD PnP Voice */
69*4882a593Smuzhiyun { "CTL3011", 0 },
70*4882a593Smuzhiyun /* Davicom ISA 33.6K Modem */
71*4882a593Smuzhiyun { "DAV0336", 0 },
72*4882a593Smuzhiyun /* Creative */
73*4882a593Smuzhiyun /* Creative Modem Blaster Flash56 DI5601-1 */
74*4882a593Smuzhiyun { "DMB1032", 0 },
75*4882a593Smuzhiyun /* Creative Modem Blaster V.90 DI5660 */
76*4882a593Smuzhiyun { "DMB2001", 0 },
77*4882a593Smuzhiyun /* E-Tech */
78*4882a593Smuzhiyun /* E-Tech CyberBULLET PC56RVP */
79*4882a593Smuzhiyun { "ETT0002", 0 },
80*4882a593Smuzhiyun /* FUJITSU */
81*4882a593Smuzhiyun /* Fujitsu 33600 PnP-I2 R Plug & Play */
82*4882a593Smuzhiyun { "FUJ0202", 0 },
83*4882a593Smuzhiyun /* Fujitsu FMV-FX431 Plug & Play */
84*4882a593Smuzhiyun { "FUJ0205", 0 },
85*4882a593Smuzhiyun /* Fujitsu 33600 PnP-I4 R Plug & Play */
86*4882a593Smuzhiyun { "FUJ0206", 0 },
87*4882a593Smuzhiyun /* Fujitsu Fax Voice 33600 PNP-I5 R Plug & Play */
88*4882a593Smuzhiyun { "FUJ0209", 0 },
89*4882a593Smuzhiyun /* Archtek America Corp. */
90*4882a593Smuzhiyun /* Archtek SmartLink Modem 3334BT Plug & Play */
91*4882a593Smuzhiyun { "GVC000F", 0 },
92*4882a593Smuzhiyun /* Archtek SmartLink Modem 3334BRV 33.6K Data Fax Voice */
93*4882a593Smuzhiyun { "GVC0303", 0 },
94*4882a593Smuzhiyun /* Hayes */
95*4882a593Smuzhiyun /* Hayes Optima 288 V.34-V.FC + FAX + Voice Plug & Play */
96*4882a593Smuzhiyun { "HAY0001", 0 },
97*4882a593Smuzhiyun /* Hayes Optima 336 V.34 + FAX + Voice PnP */
98*4882a593Smuzhiyun { "HAY000C", 0 },
99*4882a593Smuzhiyun /* Hayes Optima 336B V.34 + FAX + Voice PnP */
100*4882a593Smuzhiyun { "HAY000D", 0 },
101*4882a593Smuzhiyun /* Hayes Accura 56K Ext Fax Modem PnP */
102*4882a593Smuzhiyun { "HAY5670", 0 },
103*4882a593Smuzhiyun /* Hayes Accura 56K Ext Fax Modem PnP */
104*4882a593Smuzhiyun { "HAY5674", 0 },
105*4882a593Smuzhiyun /* Hayes Accura 56K Fax Modem PnP */
106*4882a593Smuzhiyun { "HAY5675", 0 },
107*4882a593Smuzhiyun /* Hayes 288, V.34 + FAX */
108*4882a593Smuzhiyun { "HAYF000", 0 },
109*4882a593Smuzhiyun /* Hayes Optima 288 V.34 + FAX + Voice, Plug & Play */
110*4882a593Smuzhiyun { "HAYF001", 0 },
111*4882a593Smuzhiyun /* IBM */
112*4882a593Smuzhiyun /* IBM Thinkpad 701 Internal Modem Voice */
113*4882a593Smuzhiyun { "IBM0033", 0 },
114*4882a593Smuzhiyun /* Intermec */
115*4882a593Smuzhiyun /* Intermec CV60 touchscreen port */
116*4882a593Smuzhiyun { "PNP4972", 0 },
117*4882a593Smuzhiyun /* Intertex */
118*4882a593Smuzhiyun /* Intertex 28k8 33k6 Voice EXT PnP */
119*4882a593Smuzhiyun { "IXDC801", 0 },
120*4882a593Smuzhiyun /* Intertex 33k6 56k Voice EXT PnP */
121*4882a593Smuzhiyun { "IXDC901", 0 },
122*4882a593Smuzhiyun /* Intertex 28k8 33k6 Voice SP EXT PnP */
123*4882a593Smuzhiyun { "IXDD801", 0 },
124*4882a593Smuzhiyun /* Intertex 33k6 56k Voice SP EXT PnP */
125*4882a593Smuzhiyun { "IXDD901", 0 },
126*4882a593Smuzhiyun /* Intertex 28k8 33k6 Voice SP INT PnP */
127*4882a593Smuzhiyun { "IXDF401", 0 },
128*4882a593Smuzhiyun /* Intertex 28k8 33k6 Voice SP EXT PnP */
129*4882a593Smuzhiyun { "IXDF801", 0 },
130*4882a593Smuzhiyun /* Intertex 33k6 56k Voice SP EXT PnP */
131*4882a593Smuzhiyun { "IXDF901", 0 },
132*4882a593Smuzhiyun /* Kortex International */
133*4882a593Smuzhiyun /* KORTEX 28800 Externe PnP */
134*4882a593Smuzhiyun { "KOR4522", 0 },
135*4882a593Smuzhiyun /* KXPro 33.6 Vocal ASVD PnP */
136*4882a593Smuzhiyun { "KORF661", 0 },
137*4882a593Smuzhiyun /* Lasat */
138*4882a593Smuzhiyun /* LASAT Internet 33600 PnP */
139*4882a593Smuzhiyun { "LAS4040", 0 },
140*4882a593Smuzhiyun /* Lasat Safire 560 PnP */
141*4882a593Smuzhiyun { "LAS4540", 0 },
142*4882a593Smuzhiyun /* Lasat Safire 336 PnP */
143*4882a593Smuzhiyun { "LAS5440", 0 },
144*4882a593Smuzhiyun /* Microcom, Inc. */
145*4882a593Smuzhiyun /* Microcom TravelPorte FAST V.34 Plug & Play */
146*4882a593Smuzhiyun { "MNP0281", 0 },
147*4882a593Smuzhiyun /* Microcom DeskPorte V.34 FAST or FAST+ Plug & Play */
148*4882a593Smuzhiyun { "MNP0336", 0 },
149*4882a593Smuzhiyun /* Microcom DeskPorte FAST EP 28.8 Plug & Play */
150*4882a593Smuzhiyun { "MNP0339", 0 },
151*4882a593Smuzhiyun /* Microcom DeskPorte 28.8P Plug & Play */
152*4882a593Smuzhiyun { "MNP0342", 0 },
153*4882a593Smuzhiyun /* Microcom DeskPorte FAST ES 28.8 Plug & Play */
154*4882a593Smuzhiyun { "MNP0500", 0 },
155*4882a593Smuzhiyun /* Microcom DeskPorte FAST ES 28.8 Plug & Play */
156*4882a593Smuzhiyun { "MNP0501", 0 },
157*4882a593Smuzhiyun /* Microcom DeskPorte 28.8S Internal Plug & Play */
158*4882a593Smuzhiyun { "MNP0502", 0 },
159*4882a593Smuzhiyun /* Motorola */
160*4882a593Smuzhiyun /* Motorola BitSURFR Plug & Play */
161*4882a593Smuzhiyun { "MOT1105", 0 },
162*4882a593Smuzhiyun /* Motorola TA210 Plug & Play */
163*4882a593Smuzhiyun { "MOT1111", 0 },
164*4882a593Smuzhiyun /* Motorola HMTA 200 (ISDN) Plug & Play */
165*4882a593Smuzhiyun { "MOT1114", 0 },
166*4882a593Smuzhiyun /* Motorola BitSURFR Plug & Play */
167*4882a593Smuzhiyun { "MOT1115", 0 },
168*4882a593Smuzhiyun /* Motorola Lifestyle 28.8 Internal */
169*4882a593Smuzhiyun { "MOT1190", 0 },
170*4882a593Smuzhiyun /* Motorola V.3400 Plug & Play */
171*4882a593Smuzhiyun { "MOT1501", 0 },
172*4882a593Smuzhiyun /* Motorola Lifestyle 28.8 V.34 Plug & Play */
173*4882a593Smuzhiyun { "MOT1502", 0 },
174*4882a593Smuzhiyun /* Motorola Power 28.8 V.34 Plug & Play */
175*4882a593Smuzhiyun { "MOT1505", 0 },
176*4882a593Smuzhiyun /* Motorola ModemSURFR External 28.8 Plug & Play */
177*4882a593Smuzhiyun { "MOT1509", 0 },
178*4882a593Smuzhiyun /* Motorola Premier 33.6 Desktop Plug & Play */
179*4882a593Smuzhiyun { "MOT150A", 0 },
180*4882a593Smuzhiyun /* Motorola VoiceSURFR 56K External PnP */
181*4882a593Smuzhiyun { "MOT150F", 0 },
182*4882a593Smuzhiyun /* Motorola ModemSURFR 56K External PnP */
183*4882a593Smuzhiyun { "MOT1510", 0 },
184*4882a593Smuzhiyun /* Motorola ModemSURFR 56K Internal PnP */
185*4882a593Smuzhiyun { "MOT1550", 0 },
186*4882a593Smuzhiyun /* Motorola ModemSURFR Internal 28.8 Plug & Play */
187*4882a593Smuzhiyun { "MOT1560", 0 },
188*4882a593Smuzhiyun /* Motorola Premier 33.6 Internal Plug & Play */
189*4882a593Smuzhiyun { "MOT1580", 0 },
190*4882a593Smuzhiyun /* Motorola OnlineSURFR 28.8 Internal Plug & Play */
191*4882a593Smuzhiyun { "MOT15B0", 0 },
192*4882a593Smuzhiyun /* Motorola VoiceSURFR 56K Internal PnP */
193*4882a593Smuzhiyun { "MOT15F0", 0 },
194*4882a593Smuzhiyun /* Com 1 */
195*4882a593Smuzhiyun /* Deskline K56 Phone System PnP */
196*4882a593Smuzhiyun { "MVX00A1", 0 },
197*4882a593Smuzhiyun /* PC Rider K56 Phone System PnP */
198*4882a593Smuzhiyun { "MVX00F2", 0 },
199*4882a593Smuzhiyun /* NEC 98NOTE SPEAKER PHONE FAX MODEM(33600bps) */
200*4882a593Smuzhiyun { "nEC8241", 0 },
201*4882a593Smuzhiyun /* Pace 56 Voice Internal Plug & Play Modem */
202*4882a593Smuzhiyun { "PMC2430", 0 },
203*4882a593Smuzhiyun /* Generic */
204*4882a593Smuzhiyun /* Generic standard PC COM port */
205*4882a593Smuzhiyun { "PNP0500", 0 },
206*4882a593Smuzhiyun /* Generic 16550A-compatible COM port */
207*4882a593Smuzhiyun { "PNP0501", 0 },
208*4882a593Smuzhiyun /* Compaq 14400 Modem */
209*4882a593Smuzhiyun { "PNPC000", 0 },
210*4882a593Smuzhiyun /* Compaq 2400/9600 Modem */
211*4882a593Smuzhiyun { "PNPC001", 0 },
212*4882a593Smuzhiyun /* Dial-Up Networking Serial Cable between 2 PCs */
213*4882a593Smuzhiyun { "PNPC031", 0 },
214*4882a593Smuzhiyun /* Dial-Up Networking Parallel Cable between 2 PCs */
215*4882a593Smuzhiyun { "PNPC032", 0 },
216*4882a593Smuzhiyun /* Standard 9600 bps Modem */
217*4882a593Smuzhiyun { "PNPC100", 0 },
218*4882a593Smuzhiyun /* Standard 14400 bps Modem */
219*4882a593Smuzhiyun { "PNPC101", 0 },
220*4882a593Smuzhiyun /* Standard 28800 bps Modem*/
221*4882a593Smuzhiyun { "PNPC102", 0 },
222*4882a593Smuzhiyun /* Standard Modem*/
223*4882a593Smuzhiyun { "PNPC103", 0 },
224*4882a593Smuzhiyun /* Standard 9600 bps Modem*/
225*4882a593Smuzhiyun { "PNPC104", 0 },
226*4882a593Smuzhiyun /* Standard 14400 bps Modem*/
227*4882a593Smuzhiyun { "PNPC105", 0 },
228*4882a593Smuzhiyun /* Standard 28800 bps Modem*/
229*4882a593Smuzhiyun { "PNPC106", 0 },
230*4882a593Smuzhiyun /* Standard Modem */
231*4882a593Smuzhiyun { "PNPC107", 0 },
232*4882a593Smuzhiyun /* Standard 9600 bps Modem */
233*4882a593Smuzhiyun { "PNPC108", 0 },
234*4882a593Smuzhiyun /* Standard 14400 bps Modem */
235*4882a593Smuzhiyun { "PNPC109", 0 },
236*4882a593Smuzhiyun /* Standard 28800 bps Modem */
237*4882a593Smuzhiyun { "PNPC10A", 0 },
238*4882a593Smuzhiyun /* Standard Modem */
239*4882a593Smuzhiyun { "PNPC10B", 0 },
240*4882a593Smuzhiyun /* Standard 9600 bps Modem */
241*4882a593Smuzhiyun { "PNPC10C", 0 },
242*4882a593Smuzhiyun /* Standard 14400 bps Modem */
243*4882a593Smuzhiyun { "PNPC10D", 0 },
244*4882a593Smuzhiyun /* Standard 28800 bps Modem */
245*4882a593Smuzhiyun { "PNPC10E", 0 },
246*4882a593Smuzhiyun /* Standard Modem */
247*4882a593Smuzhiyun { "PNPC10F", 0 },
248*4882a593Smuzhiyun /* Standard PCMCIA Card Modem */
249*4882a593Smuzhiyun { "PNP2000", 0 },
250*4882a593Smuzhiyun /* Rockwell */
251*4882a593Smuzhiyun /* Modular Technology */
252*4882a593Smuzhiyun /* Rockwell 33.6 DPF Internal PnP */
253*4882a593Smuzhiyun /* Modular Technology 33.6 Internal PnP */
254*4882a593Smuzhiyun { "ROK0030", 0 },
255*4882a593Smuzhiyun /* Kortex International */
256*4882a593Smuzhiyun /* KORTEX 14400 Externe PnP */
257*4882a593Smuzhiyun { "ROK0100", 0 },
258*4882a593Smuzhiyun /* Rockwell 28.8 */
259*4882a593Smuzhiyun { "ROK4120", 0 },
260*4882a593Smuzhiyun /* Viking Components, Inc */
261*4882a593Smuzhiyun /* Viking 28.8 INTERNAL Fax+Data+Voice PnP */
262*4882a593Smuzhiyun { "ROK4920", 0 },
263*4882a593Smuzhiyun /* Rockwell */
264*4882a593Smuzhiyun /* British Telecom */
265*4882a593Smuzhiyun /* Modular Technology */
266*4882a593Smuzhiyun /* Rockwell 33.6 DPF External PnP */
267*4882a593Smuzhiyun /* BT Prologue 33.6 External PnP */
268*4882a593Smuzhiyun /* Modular Technology 33.6 External PnP */
269*4882a593Smuzhiyun { "RSS00A0", 0 },
270*4882a593Smuzhiyun /* Viking 56K FAX INT */
271*4882a593Smuzhiyun { "RSS0262", 0 },
272*4882a593Smuzhiyun /* K56 par,VV,Voice,Speakphone,AudioSpan,PnP */
273*4882a593Smuzhiyun { "RSS0250", 0 },
274*4882a593Smuzhiyun /* SupraExpress 28.8 Data/Fax PnP modem */
275*4882a593Smuzhiyun { "SUP1310", 0 },
276*4882a593Smuzhiyun /* SupraExpress 336i PnP Voice Modem */
277*4882a593Smuzhiyun { "SUP1381", 0 },
278*4882a593Smuzhiyun /* SupraExpress 33.6 Data/Fax PnP modem */
279*4882a593Smuzhiyun { "SUP1421", 0 },
280*4882a593Smuzhiyun /* SupraExpress 33.6 Data/Fax PnP modem */
281*4882a593Smuzhiyun { "SUP1590", 0 },
282*4882a593Smuzhiyun /* SupraExpress 336i Sp ASVD */
283*4882a593Smuzhiyun { "SUP1620", 0 },
284*4882a593Smuzhiyun /* SupraExpress 33.6 Data/Fax PnP modem */
285*4882a593Smuzhiyun { "SUP1760", 0 },
286*4882a593Smuzhiyun /* SupraExpress 56i Sp Intl */
287*4882a593Smuzhiyun { "SUP2171", 0 },
288*4882a593Smuzhiyun /* Phoebe Micro */
289*4882a593Smuzhiyun /* Phoebe Micro 33.6 Data Fax 1433VQH Plug & Play */
290*4882a593Smuzhiyun { "TEX0011", 0 },
291*4882a593Smuzhiyun /* Archtek America Corp. */
292*4882a593Smuzhiyun /* Archtek SmartLink Modem 3334BT Plug & Play */
293*4882a593Smuzhiyun { "UAC000F", 0 },
294*4882a593Smuzhiyun /* 3Com Corp. */
295*4882a593Smuzhiyun /* Gateway Telepath IIvi 33.6 */
296*4882a593Smuzhiyun { "USR0000", 0 },
297*4882a593Smuzhiyun /* U.S. Robotics Sporster 33.6K Fax INT PnP */
298*4882a593Smuzhiyun { "USR0002", 0 },
299*4882a593Smuzhiyun /* Sportster Vi 14.4 PnP FAX Voicemail */
300*4882a593Smuzhiyun { "USR0004", 0 },
301*4882a593Smuzhiyun /* U.S. Robotics 33.6K Voice INT PnP */
302*4882a593Smuzhiyun { "USR0006", 0 },
303*4882a593Smuzhiyun /* U.S. Robotics 33.6K Voice EXT PnP */
304*4882a593Smuzhiyun { "USR0007", 0 },
305*4882a593Smuzhiyun /* U.S. Robotics Courier V.Everything INT PnP */
306*4882a593Smuzhiyun { "USR0009", 0 },
307*4882a593Smuzhiyun /* U.S. Robotics 33.6K Voice INT PnP */
308*4882a593Smuzhiyun { "USR2002", 0 },
309*4882a593Smuzhiyun /* U.S. Robotics 56K Voice INT PnP */
310*4882a593Smuzhiyun { "USR2070", 0 },
311*4882a593Smuzhiyun /* U.S. Robotics 56K Voice EXT PnP */
312*4882a593Smuzhiyun { "USR2080", 0 },
313*4882a593Smuzhiyun /* U.S. Robotics 56K FAX INT */
314*4882a593Smuzhiyun { "USR3031", 0 },
315*4882a593Smuzhiyun /* U.S. Robotics 56K FAX INT */
316*4882a593Smuzhiyun { "USR3050", 0 },
317*4882a593Smuzhiyun /* U.S. Robotics 56K Voice INT PnP */
318*4882a593Smuzhiyun { "USR3070", 0 },
319*4882a593Smuzhiyun /* U.S. Robotics 56K Voice EXT PnP */
320*4882a593Smuzhiyun { "USR3080", 0 },
321*4882a593Smuzhiyun /* U.S. Robotics 56K Voice INT PnP */
322*4882a593Smuzhiyun { "USR3090", 0 },
323*4882a593Smuzhiyun /* U.S. Robotics 56K Message */
324*4882a593Smuzhiyun { "USR9100", 0 },
325*4882a593Smuzhiyun /* U.S. Robotics 56K FAX EXT PnP*/
326*4882a593Smuzhiyun { "USR9160", 0 },
327*4882a593Smuzhiyun /* U.S. Robotics 56K FAX INT PnP*/
328*4882a593Smuzhiyun { "USR9170", 0 },
329*4882a593Smuzhiyun /* U.S. Robotics 56K Voice EXT PnP*/
330*4882a593Smuzhiyun { "USR9180", 0 },
331*4882a593Smuzhiyun /* U.S. Robotics 56K Voice INT PnP*/
332*4882a593Smuzhiyun { "USR9190", 0 },
333*4882a593Smuzhiyun /* Wacom tablets */
334*4882a593Smuzhiyun { "WACFXXX", 0 },
335*4882a593Smuzhiyun /* Compaq touchscreen */
336*4882a593Smuzhiyun { "FPI2002", 0 },
337*4882a593Smuzhiyun /* Fujitsu Stylistic touchscreens */
338*4882a593Smuzhiyun { "FUJ02B2", 0 },
339*4882a593Smuzhiyun { "FUJ02B3", 0 },
340*4882a593Smuzhiyun /* Fujitsu Stylistic LT touchscreens */
341*4882a593Smuzhiyun { "FUJ02B4", 0 },
342*4882a593Smuzhiyun /* Passive Fujitsu Stylistic touchscreens */
343*4882a593Smuzhiyun { "FUJ02B6", 0 },
344*4882a593Smuzhiyun { "FUJ02B7", 0 },
345*4882a593Smuzhiyun { "FUJ02B8", 0 },
346*4882a593Smuzhiyun { "FUJ02B9", 0 },
347*4882a593Smuzhiyun { "FUJ02BC", 0 },
348*4882a593Smuzhiyun /* Fujitsu Wacom Tablet PC device */
349*4882a593Smuzhiyun { "FUJ02E5", 0 },
350*4882a593Smuzhiyun /* Fujitsu P-series tablet PC device */
351*4882a593Smuzhiyun { "FUJ02E6", 0 },
352*4882a593Smuzhiyun /* Fujitsu Wacom 2FGT Tablet PC device */
353*4882a593Smuzhiyun { "FUJ02E7", 0 },
354*4882a593Smuzhiyun /* Fujitsu Wacom 1FGT Tablet PC device */
355*4882a593Smuzhiyun { "FUJ02E9", 0 },
356*4882a593Smuzhiyun /*
357*4882a593Smuzhiyun * LG C1 EXPRESS DUAL (C1-PB11A3) touch screen (actually a FUJ02E6
358*4882a593Smuzhiyun * in disguise).
359*4882a593Smuzhiyun */
360*4882a593Smuzhiyun { "LTS0001", 0 },
361*4882a593Smuzhiyun /* Rockwell's (PORALiNK) 33600 INT PNP */
362*4882a593Smuzhiyun { "WCI0003", 0 },
363*4882a593Smuzhiyun /* Unknown PnP modems */
364*4882a593Smuzhiyun { "PNPCXXX", UNKNOWN_DEV },
365*4882a593Smuzhiyun /* More unknown PnP modems */
366*4882a593Smuzhiyun { "PNPDXXX", UNKNOWN_DEV },
367*4882a593Smuzhiyun /*
368*4882a593Smuzhiyun * Winbond CIR port, should not be probed. We should keep track of
369*4882a593Smuzhiyun * it to prevent the legacy serial driver from probing it.
370*4882a593Smuzhiyun */
371*4882a593Smuzhiyun { "WEC1022", CIR_PORT },
372*4882a593Smuzhiyun /*
373*4882a593Smuzhiyun * SMSC IrCC SIR/FIR port, should not be probed by serial driver as
374*4882a593Smuzhiyun * well so its own driver can bind to it.
375*4882a593Smuzhiyun */
376*4882a593Smuzhiyun { "SMCF010", CIR_PORT },
377*4882a593Smuzhiyun { "", 0 }
378*4882a593Smuzhiyun };
379*4882a593Smuzhiyun
380*4882a593Smuzhiyun MODULE_DEVICE_TABLE(pnp, pnp_dev_table);
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun static const char *modem_names[] = {
383*4882a593Smuzhiyun "MODEM", "Modem", "modem", "FAX", "Fax", "fax",
384*4882a593Smuzhiyun "56K", "56k", "K56", "33.6", "28.8", "14.4",
385*4882a593Smuzhiyun "33,600", "28,800", "14,400", "33.600", "28.800", "14.400",
386*4882a593Smuzhiyun "33600", "28800", "14400", "V.90", "V.34", "V.32", NULL
387*4882a593Smuzhiyun };
388*4882a593Smuzhiyun
check_name(const char * name)389*4882a593Smuzhiyun static bool check_name(const char *name)
390*4882a593Smuzhiyun {
391*4882a593Smuzhiyun const char **tmp;
392*4882a593Smuzhiyun
393*4882a593Smuzhiyun for (tmp = modem_names; *tmp; tmp++)
394*4882a593Smuzhiyun if (strstr(name, *tmp))
395*4882a593Smuzhiyun return true;
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun return false;
398*4882a593Smuzhiyun }
399*4882a593Smuzhiyun
check_resources(struct pnp_dev * dev)400*4882a593Smuzhiyun static bool check_resources(struct pnp_dev *dev)
401*4882a593Smuzhiyun {
402*4882a593Smuzhiyun static const resource_size_t base[] = {0x2f8, 0x3f8, 0x2e8, 0x3e8};
403*4882a593Smuzhiyun unsigned int i;
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(base); i++) {
406*4882a593Smuzhiyun if (pnp_possible_config(dev, IORESOURCE_IO, base[i], 8))
407*4882a593Smuzhiyun return true;
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun return false;
411*4882a593Smuzhiyun }
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun /*
414*4882a593Smuzhiyun * Given a complete unknown PnP device, try to use some heuristics to
415*4882a593Smuzhiyun * detect modems. Currently use such heuristic set:
416*4882a593Smuzhiyun * - dev->name or dev->bus->name must contain "modem" substring;
417*4882a593Smuzhiyun * - device must have only one IO region (8 byte long) with base address
418*4882a593Smuzhiyun * 0x2e8, 0x3e8, 0x2f8 or 0x3f8.
419*4882a593Smuzhiyun *
420*4882a593Smuzhiyun * Such detection looks very ugly, but can detect at least some of numerous
421*4882a593Smuzhiyun * PnP modems, alternatively we must hardcode all modems in pnp_devices[]
422*4882a593Smuzhiyun * table.
423*4882a593Smuzhiyun */
serial_pnp_guess_board(struct pnp_dev * dev)424*4882a593Smuzhiyun static int serial_pnp_guess_board(struct pnp_dev *dev)
425*4882a593Smuzhiyun {
426*4882a593Smuzhiyun if (!(check_name(pnp_dev_name(dev)) ||
427*4882a593Smuzhiyun (dev->card && check_name(dev->card->name))))
428*4882a593Smuzhiyun return -ENODEV;
429*4882a593Smuzhiyun
430*4882a593Smuzhiyun if (check_resources(dev))
431*4882a593Smuzhiyun return 0;
432*4882a593Smuzhiyun
433*4882a593Smuzhiyun return -ENODEV;
434*4882a593Smuzhiyun }
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun static int
serial_pnp_probe(struct pnp_dev * dev,const struct pnp_device_id * dev_id)437*4882a593Smuzhiyun serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
438*4882a593Smuzhiyun {
439*4882a593Smuzhiyun struct uart_8250_port uart, *port;
440*4882a593Smuzhiyun int ret, line, flags = dev_id->driver_data;
441*4882a593Smuzhiyun
442*4882a593Smuzhiyun if (flags & UNKNOWN_DEV) {
443*4882a593Smuzhiyun ret = serial_pnp_guess_board(dev);
444*4882a593Smuzhiyun if (ret < 0)
445*4882a593Smuzhiyun return ret;
446*4882a593Smuzhiyun }
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun memset(&uart, 0, sizeof(uart));
449*4882a593Smuzhiyun if (pnp_irq_valid(dev, 0))
450*4882a593Smuzhiyun uart.port.irq = pnp_irq(dev, 0);
451*4882a593Smuzhiyun if ((flags & CIR_PORT) && pnp_port_valid(dev, 2)) {
452*4882a593Smuzhiyun uart.port.iobase = pnp_port_start(dev, 2);
453*4882a593Smuzhiyun uart.port.iotype = UPIO_PORT;
454*4882a593Smuzhiyun } else if (pnp_port_valid(dev, 0)) {
455*4882a593Smuzhiyun uart.port.iobase = pnp_port_start(dev, 0);
456*4882a593Smuzhiyun uart.port.iotype = UPIO_PORT;
457*4882a593Smuzhiyun } else if (pnp_mem_valid(dev, 0)) {
458*4882a593Smuzhiyun uart.port.mapbase = pnp_mem_start(dev, 0);
459*4882a593Smuzhiyun uart.port.iotype = UPIO_MEM;
460*4882a593Smuzhiyun uart.port.flags = UPF_IOREMAP;
461*4882a593Smuzhiyun } else
462*4882a593Smuzhiyun return -ENODEV;
463*4882a593Smuzhiyun
464*4882a593Smuzhiyun dev_dbg(&dev->dev,
465*4882a593Smuzhiyun "Setup PNP port: port %#lx, mem %#llx, irq %u, type %u\n",
466*4882a593Smuzhiyun uart.port.iobase, (unsigned long long)uart.port.mapbase,
467*4882a593Smuzhiyun uart.port.irq, uart.port.iotype);
468*4882a593Smuzhiyun
469*4882a593Smuzhiyun if (flags & CIR_PORT) {
470*4882a593Smuzhiyun uart.port.flags |= UPF_FIXED_PORT | UPF_FIXED_TYPE;
471*4882a593Smuzhiyun uart.port.type = PORT_8250_CIR;
472*4882a593Smuzhiyun }
473*4882a593Smuzhiyun
474*4882a593Smuzhiyun uart.port.flags |= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
475*4882a593Smuzhiyun if (pnp_irq_flags(dev, 0) & IORESOURCE_IRQ_SHAREABLE)
476*4882a593Smuzhiyun uart.port.flags |= UPF_SHARE_IRQ;
477*4882a593Smuzhiyun uart.port.uartclk = 1843200;
478*4882a593Smuzhiyun uart.port.dev = &dev->dev;
479*4882a593Smuzhiyun
480*4882a593Smuzhiyun line = serial8250_register_8250_port(&uart);
481*4882a593Smuzhiyun if (line < 0 || (flags & CIR_PORT))
482*4882a593Smuzhiyun return -ENODEV;
483*4882a593Smuzhiyun
484*4882a593Smuzhiyun port = serial8250_get_port(line);
485*4882a593Smuzhiyun if (uart_console(&port->port))
486*4882a593Smuzhiyun dev->capabilities |= PNP_CONSOLE;
487*4882a593Smuzhiyun
488*4882a593Smuzhiyun pnp_set_drvdata(dev, (void *)((long)line + 1));
489*4882a593Smuzhiyun return 0;
490*4882a593Smuzhiyun }
491*4882a593Smuzhiyun
serial_pnp_remove(struct pnp_dev * dev)492*4882a593Smuzhiyun static void serial_pnp_remove(struct pnp_dev *dev)
493*4882a593Smuzhiyun {
494*4882a593Smuzhiyun long line = (long)pnp_get_drvdata(dev);
495*4882a593Smuzhiyun
496*4882a593Smuzhiyun dev->capabilities &= ~PNP_CONSOLE;
497*4882a593Smuzhiyun if (line)
498*4882a593Smuzhiyun serial8250_unregister_port(line - 1);
499*4882a593Smuzhiyun }
500*4882a593Smuzhiyun
serial_pnp_suspend(struct device * dev)501*4882a593Smuzhiyun static int __maybe_unused serial_pnp_suspend(struct device *dev)
502*4882a593Smuzhiyun {
503*4882a593Smuzhiyun long line = (long)dev_get_drvdata(dev);
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun if (!line)
506*4882a593Smuzhiyun return -ENODEV;
507*4882a593Smuzhiyun serial8250_suspend_port(line - 1);
508*4882a593Smuzhiyun return 0;
509*4882a593Smuzhiyun }
510*4882a593Smuzhiyun
serial_pnp_resume(struct device * dev)511*4882a593Smuzhiyun static int __maybe_unused serial_pnp_resume(struct device *dev)
512*4882a593Smuzhiyun {
513*4882a593Smuzhiyun long line = (long)dev_get_drvdata(dev);
514*4882a593Smuzhiyun
515*4882a593Smuzhiyun if (!line)
516*4882a593Smuzhiyun return -ENODEV;
517*4882a593Smuzhiyun serial8250_resume_port(line - 1);
518*4882a593Smuzhiyun return 0;
519*4882a593Smuzhiyun }
520*4882a593Smuzhiyun
521*4882a593Smuzhiyun static SIMPLE_DEV_PM_OPS(serial_pnp_pm_ops, serial_pnp_suspend, serial_pnp_resume);
522*4882a593Smuzhiyun
523*4882a593Smuzhiyun static struct pnp_driver serial_pnp_driver = {
524*4882a593Smuzhiyun .name = "serial",
525*4882a593Smuzhiyun .probe = serial_pnp_probe,
526*4882a593Smuzhiyun .remove = serial_pnp_remove,
527*4882a593Smuzhiyun .driver = {
528*4882a593Smuzhiyun .pm = &serial_pnp_pm_ops,
529*4882a593Smuzhiyun },
530*4882a593Smuzhiyun .id_table = pnp_dev_table,
531*4882a593Smuzhiyun };
532*4882a593Smuzhiyun
serial8250_pnp_init(void)533*4882a593Smuzhiyun int serial8250_pnp_init(void)
534*4882a593Smuzhiyun {
535*4882a593Smuzhiyun return pnp_register_driver(&serial_pnp_driver);
536*4882a593Smuzhiyun }
537*4882a593Smuzhiyun
serial8250_pnp_exit(void)538*4882a593Smuzhiyun void serial8250_pnp_exit(void)
539*4882a593Smuzhiyun {
540*4882a593Smuzhiyun pnp_unregister_driver(&serial_pnp_driver);
541*4882a593Smuzhiyun }
542*4882a593Smuzhiyun
543