162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *  Probe for 8250/16550-type ISAPNP serial ports.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci *  Copyright (C) 2001 Russell King, All Rights Reserved.
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci *  Ported to the Linux PnP Layer - (C) Adam Belay.
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci#include <linux/module.h>
1262306a36Sopenharmony_ci#include <linux/pci.h>
1362306a36Sopenharmony_ci#include <linux/pnp.h>
1462306a36Sopenharmony_ci#include <linux/string.h>
1562306a36Sopenharmony_ci#include <linux/kernel.h>
1662306a36Sopenharmony_ci#include <linux/property.h>
1762306a36Sopenharmony_ci#include <linux/serial_core.h>
1862306a36Sopenharmony_ci#include <linux/bitops.h>
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci#include <asm/byteorder.h>
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#include "8250.h"
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci#define UNKNOWN_DEV 0x3000
2562306a36Sopenharmony_ci#define CIR_PORT	0x0800
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_cistatic const struct pnp_device_id pnp_dev_table[] = {
2862306a36Sopenharmony_ci	/* Archtek America Corp. */
2962306a36Sopenharmony_ci	/* Archtek SmartLink Modem 3334BT Plug & Play */
3062306a36Sopenharmony_ci	{	"AAC000F",		0	},
3162306a36Sopenharmony_ci	/* Anchor Datacomm BV */
3262306a36Sopenharmony_ci	/* SXPro 144 External Data Fax Modem Plug & Play */
3362306a36Sopenharmony_ci	{	"ADC0001",		0	},
3462306a36Sopenharmony_ci	/* SXPro 288 External Data Fax Modem Plug & Play */
3562306a36Sopenharmony_ci	{	"ADC0002",		0	},
3662306a36Sopenharmony_ci	/* PROLiNK 1456VH ISA PnP K56flex Fax Modem */
3762306a36Sopenharmony_ci	{	"AEI0250",		0	},
3862306a36Sopenharmony_ci	/* Actiontec ISA PNP 56K X2 Fax Modem */
3962306a36Sopenharmony_ci	{	"AEI1240",		0	},
4062306a36Sopenharmony_ci	/* Rockwell 56K ACF II Fax+Data+Voice Modem */
4162306a36Sopenharmony_ci	{	"AKY1021",		0 /*SPCI_FL_NO_SHIRQ*/	},
4262306a36Sopenharmony_ci	/*
4362306a36Sopenharmony_ci	 * ALi Fast Infrared Controller
4462306a36Sopenharmony_ci	 * Native driver (ali-ircc) is broken so at least
4562306a36Sopenharmony_ci	 * it can be used with irtty-sir.
4662306a36Sopenharmony_ci	 */
4762306a36Sopenharmony_ci	{	"ALI5123",		0	},
4862306a36Sopenharmony_ci	/* AZT3005 PnP SOUND DEVICE */
4962306a36Sopenharmony_ci	{	"AZT4001",		0	},
5062306a36Sopenharmony_ci	/* Best Data Products Inc. Smart One 336F PnP Modem */
5162306a36Sopenharmony_ci	{	"BDP3336",		0	},
5262306a36Sopenharmony_ci	/*  Boca Research */
5362306a36Sopenharmony_ci	/* Boca Complete Ofc Communicator 14.4 Data-FAX */
5462306a36Sopenharmony_ci	{	"BRI0A49",		0	},
5562306a36Sopenharmony_ci	/* Boca Research 33,600 ACF Modem */
5662306a36Sopenharmony_ci	{	"BRI1400",		0	},
5762306a36Sopenharmony_ci	/* Boca 33.6 Kbps Internal FD34FSVD */
5862306a36Sopenharmony_ci	{	"BRI3400",		0	},
5962306a36Sopenharmony_ci	/* Computer Peripherals Inc */
6062306a36Sopenharmony_ci	/* EuroViVa CommCenter-33.6 SP PnP */
6162306a36Sopenharmony_ci	{	"CPI4050",		0	},
6262306a36Sopenharmony_ci	/* Creative Labs */
6362306a36Sopenharmony_ci	/* Creative Labs Phone Blaster 28.8 DSVD PnP Voice */
6462306a36Sopenharmony_ci	{	"CTL3001",		0	},
6562306a36Sopenharmony_ci	/* Creative Labs Modem Blaster 28.8 DSVD PnP Voice */
6662306a36Sopenharmony_ci	{	"CTL3011",		0	},
6762306a36Sopenharmony_ci	/* Davicom ISA 33.6K Modem */
6862306a36Sopenharmony_ci	{	"DAV0336",		0	},
6962306a36Sopenharmony_ci	/* Creative */
7062306a36Sopenharmony_ci	/* Creative Modem Blaster Flash56 DI5601-1 */
7162306a36Sopenharmony_ci	{	"DMB1032",		0	},
7262306a36Sopenharmony_ci	/* Creative Modem Blaster V.90 DI5660 */
7362306a36Sopenharmony_ci	{	"DMB2001",		0	},
7462306a36Sopenharmony_ci	/* E-Tech */
7562306a36Sopenharmony_ci	/* E-Tech CyberBULLET PC56RVP */
7662306a36Sopenharmony_ci	{	"ETT0002",		0	},
7762306a36Sopenharmony_ci	/* FUJITSU */
7862306a36Sopenharmony_ci	/* Fujitsu 33600 PnP-I2 R Plug & Play */
7962306a36Sopenharmony_ci	{	"FUJ0202",		0	},
8062306a36Sopenharmony_ci	/* Fujitsu FMV-FX431 Plug & Play */
8162306a36Sopenharmony_ci	{	"FUJ0205",		0	},
8262306a36Sopenharmony_ci	/* Fujitsu 33600 PnP-I4 R Plug & Play */
8362306a36Sopenharmony_ci	{	"FUJ0206",		0	},
8462306a36Sopenharmony_ci	/* Fujitsu Fax Voice 33600 PNP-I5 R Plug & Play */
8562306a36Sopenharmony_ci	{	"FUJ0209",		0	},
8662306a36Sopenharmony_ci	/* Archtek America Corp. */
8762306a36Sopenharmony_ci	/* Archtek SmartLink Modem 3334BT Plug & Play */
8862306a36Sopenharmony_ci	{	"GVC000F",		0	},
8962306a36Sopenharmony_ci	/* Archtek SmartLink Modem 3334BRV 33.6K Data Fax Voice */
9062306a36Sopenharmony_ci	{	"GVC0303",		0	},
9162306a36Sopenharmony_ci	/* Hayes */
9262306a36Sopenharmony_ci	/* Hayes Optima 288 V.34-V.FC + FAX + Voice Plug & Play */
9362306a36Sopenharmony_ci	{	"HAY0001",		0	},
9462306a36Sopenharmony_ci	/* Hayes Optima 336 V.34 + FAX + Voice PnP */
9562306a36Sopenharmony_ci	{	"HAY000C",		0	},
9662306a36Sopenharmony_ci	/* Hayes Optima 336B V.34 + FAX + Voice PnP */
9762306a36Sopenharmony_ci	{	"HAY000D",		0	},
9862306a36Sopenharmony_ci	/* Hayes Accura 56K Ext Fax Modem PnP */
9962306a36Sopenharmony_ci	{	"HAY5670",		0	},
10062306a36Sopenharmony_ci	/* Hayes Accura 56K Ext Fax Modem PnP */
10162306a36Sopenharmony_ci	{	"HAY5674",		0	},
10262306a36Sopenharmony_ci	/* Hayes Accura 56K Fax Modem PnP */
10362306a36Sopenharmony_ci	{	"HAY5675",		0	},
10462306a36Sopenharmony_ci	/* Hayes 288, V.34 + FAX */
10562306a36Sopenharmony_ci	{	"HAYF000",		0	},
10662306a36Sopenharmony_ci	/* Hayes Optima 288 V.34 + FAX + Voice, Plug & Play */
10762306a36Sopenharmony_ci	{	"HAYF001",		0	},
10862306a36Sopenharmony_ci	/* IBM */
10962306a36Sopenharmony_ci	/* IBM Thinkpad 701 Internal Modem Voice */
11062306a36Sopenharmony_ci	{	"IBM0033",		0	},
11162306a36Sopenharmony_ci	/* Intermec */
11262306a36Sopenharmony_ci	/* Intermec CV60 touchscreen port */
11362306a36Sopenharmony_ci	{	"PNP4972",		0	},
11462306a36Sopenharmony_ci	/* Intertex */
11562306a36Sopenharmony_ci	/* Intertex 28k8 33k6 Voice EXT PnP */
11662306a36Sopenharmony_ci	{	"IXDC801",		0	},
11762306a36Sopenharmony_ci	/* Intertex 33k6 56k Voice EXT PnP */
11862306a36Sopenharmony_ci	{	"IXDC901",		0	},
11962306a36Sopenharmony_ci	/* Intertex 28k8 33k6 Voice SP EXT PnP */
12062306a36Sopenharmony_ci	{	"IXDD801",		0	},
12162306a36Sopenharmony_ci	/* Intertex 33k6 56k Voice SP EXT PnP */
12262306a36Sopenharmony_ci	{	"IXDD901",		0	},
12362306a36Sopenharmony_ci	/* Intertex 28k8 33k6 Voice SP INT PnP */
12462306a36Sopenharmony_ci	{	"IXDF401",		0	},
12562306a36Sopenharmony_ci	/* Intertex 28k8 33k6 Voice SP EXT PnP */
12662306a36Sopenharmony_ci	{	"IXDF801",		0	},
12762306a36Sopenharmony_ci	/* Intertex 33k6 56k Voice SP EXT PnP */
12862306a36Sopenharmony_ci	{	"IXDF901",		0	},
12962306a36Sopenharmony_ci	/* Kortex International */
13062306a36Sopenharmony_ci	/* KORTEX 28800 Externe PnP */
13162306a36Sopenharmony_ci	{	"KOR4522",		0	},
13262306a36Sopenharmony_ci	/* KXPro 33.6 Vocal ASVD PnP */
13362306a36Sopenharmony_ci	{	"KORF661",		0	},
13462306a36Sopenharmony_ci	/* Lasat */
13562306a36Sopenharmony_ci	/* LASAT Internet 33600 PnP */
13662306a36Sopenharmony_ci	{	"LAS4040",		0	},
13762306a36Sopenharmony_ci	/* Lasat Safire 560 PnP */
13862306a36Sopenharmony_ci	{	"LAS4540",		0	},
13962306a36Sopenharmony_ci	/* Lasat Safire 336  PnP */
14062306a36Sopenharmony_ci	{	"LAS5440",		0	},
14162306a36Sopenharmony_ci	/* Microcom, Inc. */
14262306a36Sopenharmony_ci	/* Microcom TravelPorte FAST V.34 Plug & Play */
14362306a36Sopenharmony_ci	{	"MNP0281",		0	},
14462306a36Sopenharmony_ci	/* Microcom DeskPorte V.34 FAST or FAST+ Plug & Play */
14562306a36Sopenharmony_ci	{	"MNP0336",		0	},
14662306a36Sopenharmony_ci	/* Microcom DeskPorte FAST EP 28.8 Plug & Play */
14762306a36Sopenharmony_ci	{	"MNP0339",		0	},
14862306a36Sopenharmony_ci	/* Microcom DeskPorte 28.8P Plug & Play */
14962306a36Sopenharmony_ci	{	"MNP0342",		0	},
15062306a36Sopenharmony_ci	/* Microcom DeskPorte FAST ES 28.8 Plug & Play */
15162306a36Sopenharmony_ci	{	"MNP0500",		0	},
15262306a36Sopenharmony_ci	/* Microcom DeskPorte FAST ES 28.8 Plug & Play */
15362306a36Sopenharmony_ci	{	"MNP0501",		0	},
15462306a36Sopenharmony_ci	/* Microcom DeskPorte 28.8S Internal Plug & Play */
15562306a36Sopenharmony_ci	{	"MNP0502",		0	},
15662306a36Sopenharmony_ci	/* Motorola */
15762306a36Sopenharmony_ci	/* Motorola BitSURFR Plug & Play */
15862306a36Sopenharmony_ci	{	"MOT1105",		0	},
15962306a36Sopenharmony_ci	/* Motorola TA210 Plug & Play */
16062306a36Sopenharmony_ci	{	"MOT1111",		0	},
16162306a36Sopenharmony_ci	/* Motorola HMTA 200 (ISDN) Plug & Play */
16262306a36Sopenharmony_ci	{	"MOT1114",		0	},
16362306a36Sopenharmony_ci	/* Motorola BitSURFR Plug & Play */
16462306a36Sopenharmony_ci	{	"MOT1115",		0	},
16562306a36Sopenharmony_ci	/* Motorola Lifestyle 28.8 Internal */
16662306a36Sopenharmony_ci	{	"MOT1190",		0	},
16762306a36Sopenharmony_ci	/* Motorola V.3400 Plug & Play */
16862306a36Sopenharmony_ci	{	"MOT1501",		0	},
16962306a36Sopenharmony_ci	/* Motorola Lifestyle 28.8 V.34 Plug & Play */
17062306a36Sopenharmony_ci	{	"MOT1502",		0	},
17162306a36Sopenharmony_ci	/* Motorola Power 28.8 V.34 Plug & Play */
17262306a36Sopenharmony_ci	{	"MOT1505",		0	},
17362306a36Sopenharmony_ci	/* Motorola ModemSURFR External 28.8 Plug & Play */
17462306a36Sopenharmony_ci	{	"MOT1509",		0	},
17562306a36Sopenharmony_ci	/* Motorola Premier 33.6 Desktop Plug & Play */
17662306a36Sopenharmony_ci	{	"MOT150A",		0	},
17762306a36Sopenharmony_ci	/* Motorola VoiceSURFR 56K External PnP */
17862306a36Sopenharmony_ci	{	"MOT150F",		0	},
17962306a36Sopenharmony_ci	/* Motorola ModemSURFR 56K External PnP */
18062306a36Sopenharmony_ci	{	"MOT1510",		0	},
18162306a36Sopenharmony_ci	/* Motorola ModemSURFR 56K Internal PnP */
18262306a36Sopenharmony_ci	{	"MOT1550",		0	},
18362306a36Sopenharmony_ci	/* Motorola ModemSURFR Internal 28.8 Plug & Play */
18462306a36Sopenharmony_ci	{	"MOT1560",		0	},
18562306a36Sopenharmony_ci	/* Motorola Premier 33.6 Internal Plug & Play */
18662306a36Sopenharmony_ci	{	"MOT1580",		0	},
18762306a36Sopenharmony_ci	/* Motorola OnlineSURFR 28.8 Internal Plug & Play */
18862306a36Sopenharmony_ci	{	"MOT15B0",		0	},
18962306a36Sopenharmony_ci	/* Motorola VoiceSURFR 56K Internal PnP */
19062306a36Sopenharmony_ci	{	"MOT15F0",		0	},
19162306a36Sopenharmony_ci	/* Com 1 */
19262306a36Sopenharmony_ci	/*  Deskline K56 Phone System PnP */
19362306a36Sopenharmony_ci	{	"MVX00A1",		0	},
19462306a36Sopenharmony_ci	/* PC Rider K56 Phone System PnP */
19562306a36Sopenharmony_ci	{	"MVX00F2",		0	},
19662306a36Sopenharmony_ci	/* NEC 98NOTE SPEAKER PHONE FAX MODEM(33600bps) */
19762306a36Sopenharmony_ci	{	"nEC8241",		0	},
19862306a36Sopenharmony_ci	/* Pace 56 Voice Internal Plug & Play Modem */
19962306a36Sopenharmony_ci	{	"PMC2430",		0	},
20062306a36Sopenharmony_ci	/* Generic */
20162306a36Sopenharmony_ci	/* Generic standard PC COM port	 */
20262306a36Sopenharmony_ci	{	"PNP0500",		0	},
20362306a36Sopenharmony_ci	/* Generic 16550A-compatible COM port */
20462306a36Sopenharmony_ci	{	"PNP0501",		0	},
20562306a36Sopenharmony_ci	/* Compaq 14400 Modem */
20662306a36Sopenharmony_ci	{	"PNPC000",		0	},
20762306a36Sopenharmony_ci	/* Compaq 2400/9600 Modem */
20862306a36Sopenharmony_ci	{	"PNPC001",		0	},
20962306a36Sopenharmony_ci	/* Dial-Up Networking Serial Cable between 2 PCs */
21062306a36Sopenharmony_ci	{	"PNPC031",		0	},
21162306a36Sopenharmony_ci	/* Dial-Up Networking Parallel Cable between 2 PCs */
21262306a36Sopenharmony_ci	{	"PNPC032",		0	},
21362306a36Sopenharmony_ci	/* Standard 9600 bps Modem */
21462306a36Sopenharmony_ci	{	"PNPC100",		0	},
21562306a36Sopenharmony_ci	/* Standard 14400 bps Modem */
21662306a36Sopenharmony_ci	{	"PNPC101",		0	},
21762306a36Sopenharmony_ci	/*  Standard 28800 bps Modem*/
21862306a36Sopenharmony_ci	{	"PNPC102",		0	},
21962306a36Sopenharmony_ci	/*  Standard Modem*/
22062306a36Sopenharmony_ci	{	"PNPC103",		0	},
22162306a36Sopenharmony_ci	/*  Standard 9600 bps Modem*/
22262306a36Sopenharmony_ci	{	"PNPC104",		0	},
22362306a36Sopenharmony_ci	/*  Standard 14400 bps Modem*/
22462306a36Sopenharmony_ci	{	"PNPC105",		0	},
22562306a36Sopenharmony_ci	/*  Standard 28800 bps Modem*/
22662306a36Sopenharmony_ci	{	"PNPC106",		0	},
22762306a36Sopenharmony_ci	/*  Standard Modem */
22862306a36Sopenharmony_ci	{	"PNPC107",		0	},
22962306a36Sopenharmony_ci	/* Standard 9600 bps Modem */
23062306a36Sopenharmony_ci	{	"PNPC108",		0	},
23162306a36Sopenharmony_ci	/* Standard 14400 bps Modem */
23262306a36Sopenharmony_ci	{	"PNPC109",		0	},
23362306a36Sopenharmony_ci	/* Standard 28800 bps Modem */
23462306a36Sopenharmony_ci	{	"PNPC10A",		0	},
23562306a36Sopenharmony_ci	/* Standard Modem */
23662306a36Sopenharmony_ci	{	"PNPC10B",		0	},
23762306a36Sopenharmony_ci	/* Standard 9600 bps Modem */
23862306a36Sopenharmony_ci	{	"PNPC10C",		0	},
23962306a36Sopenharmony_ci	/* Standard 14400 bps Modem */
24062306a36Sopenharmony_ci	{	"PNPC10D",		0	},
24162306a36Sopenharmony_ci	/* Standard 28800 bps Modem */
24262306a36Sopenharmony_ci	{	"PNPC10E",		0	},
24362306a36Sopenharmony_ci	/* Standard Modem */
24462306a36Sopenharmony_ci	{	"PNPC10F",		0	},
24562306a36Sopenharmony_ci	/* Standard PCMCIA Card Modem */
24662306a36Sopenharmony_ci	{	"PNP2000",		0	},
24762306a36Sopenharmony_ci	/* Rockwell */
24862306a36Sopenharmony_ci	/* Modular Technology */
24962306a36Sopenharmony_ci	/* Rockwell 33.6 DPF Internal PnP */
25062306a36Sopenharmony_ci	/* Modular Technology 33.6 Internal PnP */
25162306a36Sopenharmony_ci	{	"ROK0030",		0	},
25262306a36Sopenharmony_ci	/* Kortex International */
25362306a36Sopenharmony_ci	/* KORTEX 14400 Externe PnP */
25462306a36Sopenharmony_ci	{	"ROK0100",		0	},
25562306a36Sopenharmony_ci	/* Rockwell 28.8 */
25662306a36Sopenharmony_ci	{	"ROK4120",		0	},
25762306a36Sopenharmony_ci	/* Viking Components, Inc */
25862306a36Sopenharmony_ci	/* Viking 28.8 INTERNAL Fax+Data+Voice PnP */
25962306a36Sopenharmony_ci	{	"ROK4920",		0	},
26062306a36Sopenharmony_ci	/* Rockwell */
26162306a36Sopenharmony_ci	/* British Telecom */
26262306a36Sopenharmony_ci	/* Modular Technology */
26362306a36Sopenharmony_ci	/* Rockwell 33.6 DPF External PnP */
26462306a36Sopenharmony_ci	/* BT Prologue 33.6 External PnP */
26562306a36Sopenharmony_ci	/* Modular Technology 33.6 External PnP */
26662306a36Sopenharmony_ci	{	"RSS00A0",		0	},
26762306a36Sopenharmony_ci	/* Viking 56K FAX INT */
26862306a36Sopenharmony_ci	{	"RSS0262",		0	},
26962306a36Sopenharmony_ci	/* K56 par,VV,Voice,Speakphone,AudioSpan,PnP */
27062306a36Sopenharmony_ci	{       "RSS0250",              0       },
27162306a36Sopenharmony_ci	/* SupraExpress 28.8 Data/Fax PnP modem */
27262306a36Sopenharmony_ci	{	"SUP1310",		0	},
27362306a36Sopenharmony_ci	/* SupraExpress 336i PnP Voice Modem */
27462306a36Sopenharmony_ci	{	"SUP1381",		0	},
27562306a36Sopenharmony_ci	/* SupraExpress 33.6 Data/Fax PnP modem */
27662306a36Sopenharmony_ci	{	"SUP1421",		0	},
27762306a36Sopenharmony_ci	/* SupraExpress 33.6 Data/Fax PnP modem */
27862306a36Sopenharmony_ci	{	"SUP1590",		0	},
27962306a36Sopenharmony_ci	/* SupraExpress 336i Sp ASVD */
28062306a36Sopenharmony_ci	{	"SUP1620",		0	},
28162306a36Sopenharmony_ci	/* SupraExpress 33.6 Data/Fax PnP modem */
28262306a36Sopenharmony_ci	{	"SUP1760",		0	},
28362306a36Sopenharmony_ci	/* SupraExpress 56i Sp Intl */
28462306a36Sopenharmony_ci	{	"SUP2171",		0	},
28562306a36Sopenharmony_ci	/* Phoebe Micro */
28662306a36Sopenharmony_ci	/* Phoebe Micro 33.6 Data Fax 1433VQH Plug & Play */
28762306a36Sopenharmony_ci	{	"TEX0011",		0	},
28862306a36Sopenharmony_ci	/* Archtek America Corp. */
28962306a36Sopenharmony_ci	/* Archtek SmartLink Modem 3334BT Plug & Play */
29062306a36Sopenharmony_ci	{	"UAC000F",		0	},
29162306a36Sopenharmony_ci	/* 3Com Corp. */
29262306a36Sopenharmony_ci	/* Gateway Telepath IIvi 33.6 */
29362306a36Sopenharmony_ci	{	"USR0000",		0	},
29462306a36Sopenharmony_ci	/* U.S. Robotics Sporster 33.6K Fax INT PnP */
29562306a36Sopenharmony_ci	{	"USR0002",		0	},
29662306a36Sopenharmony_ci	/*  Sportster Vi 14.4 PnP FAX Voicemail */
29762306a36Sopenharmony_ci	{	"USR0004",		0	},
29862306a36Sopenharmony_ci	/* U.S. Robotics 33.6K Voice INT PnP */
29962306a36Sopenharmony_ci	{	"USR0006",		0	},
30062306a36Sopenharmony_ci	/* U.S. Robotics 33.6K Voice EXT PnP */
30162306a36Sopenharmony_ci	{	"USR0007",		0	},
30262306a36Sopenharmony_ci	/* U.S. Robotics Courier V.Everything INT PnP */
30362306a36Sopenharmony_ci	{	"USR0009",		0	},
30462306a36Sopenharmony_ci	/* U.S. Robotics 33.6K Voice INT PnP */
30562306a36Sopenharmony_ci	{	"USR2002",		0	},
30662306a36Sopenharmony_ci	/* U.S. Robotics 56K Voice INT PnP */
30762306a36Sopenharmony_ci	{	"USR2070",		0	},
30862306a36Sopenharmony_ci	/* U.S. Robotics 56K Voice EXT PnP */
30962306a36Sopenharmony_ci	{	"USR2080",		0	},
31062306a36Sopenharmony_ci	/* U.S. Robotics 56K FAX INT */
31162306a36Sopenharmony_ci	{	"USR3031",		0	},
31262306a36Sopenharmony_ci	/* U.S. Robotics 56K FAX INT */
31362306a36Sopenharmony_ci	{	"USR3050",		0	},
31462306a36Sopenharmony_ci	/* U.S. Robotics 56K Voice INT PnP */
31562306a36Sopenharmony_ci	{	"USR3070",		0	},
31662306a36Sopenharmony_ci	/* U.S. Robotics 56K Voice EXT PnP */
31762306a36Sopenharmony_ci	{	"USR3080",		0	},
31862306a36Sopenharmony_ci	/* U.S. Robotics 56K Voice INT PnP */
31962306a36Sopenharmony_ci	{	"USR3090",		0	},
32062306a36Sopenharmony_ci	/* U.S. Robotics 56K Message  */
32162306a36Sopenharmony_ci	{	"USR9100",		0	},
32262306a36Sopenharmony_ci	/* U.S. Robotics 56K FAX EXT PnP*/
32362306a36Sopenharmony_ci	{	"USR9160",		0	},
32462306a36Sopenharmony_ci	/* U.S. Robotics 56K FAX INT PnP*/
32562306a36Sopenharmony_ci	{	"USR9170",		0	},
32662306a36Sopenharmony_ci	/* U.S. Robotics 56K Voice EXT PnP*/
32762306a36Sopenharmony_ci	{	"USR9180",		0	},
32862306a36Sopenharmony_ci	/* U.S. Robotics 56K Voice INT PnP*/
32962306a36Sopenharmony_ci	{	"USR9190",		0	},
33062306a36Sopenharmony_ci	/* Wacom tablets */
33162306a36Sopenharmony_ci	{	"WACFXXX",		0	},
33262306a36Sopenharmony_ci	/* Compaq touchscreen */
33362306a36Sopenharmony_ci	{       "FPI2002",              0 },
33462306a36Sopenharmony_ci	/* Fujitsu Stylistic touchscreens */
33562306a36Sopenharmony_ci	{       "FUJ02B2",              0 },
33662306a36Sopenharmony_ci	{       "FUJ02B3",              0 },
33762306a36Sopenharmony_ci	/* Fujitsu Stylistic LT touchscreens */
33862306a36Sopenharmony_ci	{       "FUJ02B4",              0 },
33962306a36Sopenharmony_ci	/* Passive Fujitsu Stylistic touchscreens */
34062306a36Sopenharmony_ci	{       "FUJ02B6",              0 },
34162306a36Sopenharmony_ci	{       "FUJ02B7",              0 },
34262306a36Sopenharmony_ci	{       "FUJ02B8",              0 },
34362306a36Sopenharmony_ci	{       "FUJ02B9",              0 },
34462306a36Sopenharmony_ci	{       "FUJ02BC",              0 },
34562306a36Sopenharmony_ci	/* Fujitsu Wacom Tablet PC device */
34662306a36Sopenharmony_ci	{	"FUJ02E5",		0	},
34762306a36Sopenharmony_ci	/* Fujitsu P-series tablet PC device */
34862306a36Sopenharmony_ci	{	"FUJ02E6",		0	},
34962306a36Sopenharmony_ci	/* Fujitsu Wacom 2FGT Tablet PC device */
35062306a36Sopenharmony_ci	{	"FUJ02E7",		0	},
35162306a36Sopenharmony_ci	/* Fujitsu Wacom 1FGT Tablet PC device */
35262306a36Sopenharmony_ci	{	"FUJ02E9",		0	},
35362306a36Sopenharmony_ci	/*
35462306a36Sopenharmony_ci	 * LG C1 EXPRESS DUAL (C1-PB11A3) touch screen (actually a FUJ02E6
35562306a36Sopenharmony_ci	 * in disguise).
35662306a36Sopenharmony_ci	 */
35762306a36Sopenharmony_ci	{	"LTS0001",		0       },
35862306a36Sopenharmony_ci	/* Rockwell's (PORALiNK) 33600 INT PNP */
35962306a36Sopenharmony_ci	{	"WCI0003",		0	},
36062306a36Sopenharmony_ci	/* Unknown PnP modems */
36162306a36Sopenharmony_ci	{	"PNPCXXX",		UNKNOWN_DEV	},
36262306a36Sopenharmony_ci	/* More unknown PnP modems */
36362306a36Sopenharmony_ci	{	"PNPDXXX",		UNKNOWN_DEV	},
36462306a36Sopenharmony_ci	/*
36562306a36Sopenharmony_ci	 * Winbond CIR port, should not be probed. We should keep track of
36662306a36Sopenharmony_ci	 * it to prevent the legacy serial driver from probing it.
36762306a36Sopenharmony_ci	 */
36862306a36Sopenharmony_ci	{	"WEC1022",		CIR_PORT	},
36962306a36Sopenharmony_ci	/*
37062306a36Sopenharmony_ci	 * SMSC IrCC SIR/FIR port, should not be probed by serial driver as
37162306a36Sopenharmony_ci	 * well so its own driver can bind to it.
37262306a36Sopenharmony_ci	 */
37362306a36Sopenharmony_ci	{	"SMCF010",		CIR_PORT	},
37462306a36Sopenharmony_ci	{	"",			0	}
37562306a36Sopenharmony_ci};
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ciMODULE_DEVICE_TABLE(pnp, pnp_dev_table);
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_cistatic const char *modem_names[] = {
38062306a36Sopenharmony_ci	"MODEM", "Modem", "modem", "FAX", "Fax", "fax",
38162306a36Sopenharmony_ci	"56K", "56k", "K56", "33.6", "28.8", "14.4",
38262306a36Sopenharmony_ci	"33,600", "28,800", "14,400", "33.600", "28.800", "14.400",
38362306a36Sopenharmony_ci	"33600", "28800", "14400", "V.90", "V.34", "V.32", NULL
38462306a36Sopenharmony_ci};
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_cistatic bool check_name(const char *name)
38762306a36Sopenharmony_ci{
38862306a36Sopenharmony_ci	const char **tmp;
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci	for (tmp = modem_names; *tmp; tmp++)
39162306a36Sopenharmony_ci		if (strstr(name, *tmp))
39262306a36Sopenharmony_ci			return true;
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	return false;
39562306a36Sopenharmony_ci}
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_cistatic bool check_resources(struct pnp_dev *dev)
39862306a36Sopenharmony_ci{
39962306a36Sopenharmony_ci	static const resource_size_t base[] = {0x2f8, 0x3f8, 0x2e8, 0x3e8};
40062306a36Sopenharmony_ci	unsigned int i;
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(base); i++) {
40362306a36Sopenharmony_ci		if (pnp_possible_config(dev, IORESOURCE_IO, base[i], 8))
40462306a36Sopenharmony_ci			return true;
40562306a36Sopenharmony_ci	}
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_ci	return false;
40862306a36Sopenharmony_ci}
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci/*
41162306a36Sopenharmony_ci * Given a complete unknown PnP device, try to use some heuristics to
41262306a36Sopenharmony_ci * detect modems. Currently use such heuristic set:
41362306a36Sopenharmony_ci *     - dev->name or dev->bus->name must contain "modem" substring;
41462306a36Sopenharmony_ci *     - device must have only one IO region (8 byte long) with base address
41562306a36Sopenharmony_ci *       0x2e8, 0x3e8, 0x2f8 or 0x3f8.
41662306a36Sopenharmony_ci *
41762306a36Sopenharmony_ci * Such detection looks very ugly, but can detect at least some of numerous
41862306a36Sopenharmony_ci * PnP modems, alternatively we must hardcode all modems in pnp_devices[]
41962306a36Sopenharmony_ci * table.
42062306a36Sopenharmony_ci */
42162306a36Sopenharmony_cistatic int serial_pnp_guess_board(struct pnp_dev *dev)
42262306a36Sopenharmony_ci{
42362306a36Sopenharmony_ci	if (!(check_name(pnp_dev_name(dev)) ||
42462306a36Sopenharmony_ci	    (dev->card && check_name(dev->card->name))))
42562306a36Sopenharmony_ci		return -ENODEV;
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_ci	if (check_resources(dev))
42862306a36Sopenharmony_ci		return 0;
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_ci	return -ENODEV;
43162306a36Sopenharmony_ci}
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_cistatic int
43462306a36Sopenharmony_ciserial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
43562306a36Sopenharmony_ci{
43662306a36Sopenharmony_ci	struct uart_8250_port uart, *port;
43762306a36Sopenharmony_ci	int ret, line, flags = dev_id->driver_data;
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci	if (flags & UNKNOWN_DEV) {
44062306a36Sopenharmony_ci		ret = serial_pnp_guess_board(dev);
44162306a36Sopenharmony_ci		if (ret < 0)
44262306a36Sopenharmony_ci			return ret;
44362306a36Sopenharmony_ci	}
44462306a36Sopenharmony_ci
44562306a36Sopenharmony_ci	memset(&uart, 0, sizeof(uart));
44662306a36Sopenharmony_ci	if (pnp_irq_valid(dev, 0))
44762306a36Sopenharmony_ci		uart.port.irq = pnp_irq(dev, 0);
44862306a36Sopenharmony_ci	if ((flags & CIR_PORT) && pnp_port_valid(dev, 2)) {
44962306a36Sopenharmony_ci		uart.port.iobase = pnp_port_start(dev, 2);
45062306a36Sopenharmony_ci		uart.port.iotype = UPIO_PORT;
45162306a36Sopenharmony_ci	} else if (pnp_port_valid(dev, 0)) {
45262306a36Sopenharmony_ci		uart.port.iobase = pnp_port_start(dev, 0);
45362306a36Sopenharmony_ci		uart.port.iotype = UPIO_PORT;
45462306a36Sopenharmony_ci	} else if (pnp_mem_valid(dev, 0)) {
45562306a36Sopenharmony_ci		uart.port.mapbase = pnp_mem_start(dev, 0);
45662306a36Sopenharmony_ci		uart.port.iotype = UPIO_MEM;
45762306a36Sopenharmony_ci		uart.port.flags = UPF_IOREMAP;
45862306a36Sopenharmony_ci	} else
45962306a36Sopenharmony_ci		return -ENODEV;
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_ci	dev_dbg(&dev->dev,
46262306a36Sopenharmony_ci		 "Setup PNP port: port %#lx, mem %#llx, irq %u, type %u\n",
46362306a36Sopenharmony_ci		 uart.port.iobase, (unsigned long long)uart.port.mapbase,
46462306a36Sopenharmony_ci		 uart.port.irq, uart.port.iotype);
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci	if (flags & CIR_PORT) {
46762306a36Sopenharmony_ci		uart.port.flags |= UPF_FIXED_PORT | UPF_FIXED_TYPE;
46862306a36Sopenharmony_ci		uart.port.type = PORT_8250_CIR;
46962306a36Sopenharmony_ci	}
47062306a36Sopenharmony_ci
47162306a36Sopenharmony_ci	uart.port.flags |= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
47262306a36Sopenharmony_ci	if (pnp_irq_flags(dev, 0) & IORESOURCE_IRQ_SHAREABLE)
47362306a36Sopenharmony_ci		uart.port.flags |= UPF_SHARE_IRQ;
47462306a36Sopenharmony_ci	uart.port.uartclk = 1843200;
47562306a36Sopenharmony_ci	device_property_read_u32(&dev->dev, "clock-frequency", &uart.port.uartclk);
47662306a36Sopenharmony_ci	uart.port.dev = &dev->dev;
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ci	line = serial8250_register_8250_port(&uart);
47962306a36Sopenharmony_ci	if (line < 0 || (flags & CIR_PORT))
48062306a36Sopenharmony_ci		return -ENODEV;
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci	port = serial8250_get_port(line);
48362306a36Sopenharmony_ci	if (uart_console(&port->port))
48462306a36Sopenharmony_ci		dev->capabilities |= PNP_CONSOLE;
48562306a36Sopenharmony_ci
48662306a36Sopenharmony_ci	pnp_set_drvdata(dev, (void *)((long)line + 1));
48762306a36Sopenharmony_ci	return 0;
48862306a36Sopenharmony_ci}
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_cistatic void serial_pnp_remove(struct pnp_dev *dev)
49162306a36Sopenharmony_ci{
49262306a36Sopenharmony_ci	long line = (long)pnp_get_drvdata(dev);
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_ci	dev->capabilities &= ~PNP_CONSOLE;
49562306a36Sopenharmony_ci	if (line)
49662306a36Sopenharmony_ci		serial8250_unregister_port(line - 1);
49762306a36Sopenharmony_ci}
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_cistatic int __maybe_unused serial_pnp_suspend(struct device *dev)
50062306a36Sopenharmony_ci{
50162306a36Sopenharmony_ci	long line = (long)dev_get_drvdata(dev);
50262306a36Sopenharmony_ci
50362306a36Sopenharmony_ci	if (!line)
50462306a36Sopenharmony_ci		return -ENODEV;
50562306a36Sopenharmony_ci	serial8250_suspend_port(line - 1);
50662306a36Sopenharmony_ci	return 0;
50762306a36Sopenharmony_ci}
50862306a36Sopenharmony_ci
50962306a36Sopenharmony_cistatic int __maybe_unused serial_pnp_resume(struct device *dev)
51062306a36Sopenharmony_ci{
51162306a36Sopenharmony_ci	long line = (long)dev_get_drvdata(dev);
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci	if (!line)
51462306a36Sopenharmony_ci		return -ENODEV;
51562306a36Sopenharmony_ci	serial8250_resume_port(line - 1);
51662306a36Sopenharmony_ci	return 0;
51762306a36Sopenharmony_ci}
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(serial_pnp_pm_ops, serial_pnp_suspend, serial_pnp_resume);
52062306a36Sopenharmony_ci
52162306a36Sopenharmony_cistatic struct pnp_driver serial_pnp_driver = {
52262306a36Sopenharmony_ci	.name		= "serial",
52362306a36Sopenharmony_ci	.probe		= serial_pnp_probe,
52462306a36Sopenharmony_ci	.remove		= serial_pnp_remove,
52562306a36Sopenharmony_ci	.driver         = {
52662306a36Sopenharmony_ci		.pm     = &serial_pnp_pm_ops,
52762306a36Sopenharmony_ci	},
52862306a36Sopenharmony_ci	.id_table	= pnp_dev_table,
52962306a36Sopenharmony_ci};
53062306a36Sopenharmony_ci
53162306a36Sopenharmony_ciint serial8250_pnp_init(void)
53262306a36Sopenharmony_ci{
53362306a36Sopenharmony_ci	return pnp_register_driver(&serial_pnp_driver);
53462306a36Sopenharmony_ci}
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_civoid serial8250_pnp_exit(void)
53762306a36Sopenharmony_ci{
53862306a36Sopenharmony_ci	pnp_unregister_driver(&serial_pnp_driver);
53962306a36Sopenharmony_ci}
54062306a36Sopenharmony_ci
541