xref: /OK3568_Linux_fs/kernel/drivers/tty/serial/8250/8250_pnp.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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