summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2019-08-13 03:25:00 -0400
committerTony Luck <tony.luck@intel.com>2019-08-16 14:33:57 -0400
commitf7bc6e42bf12487182fc442a08eca25d968dc543 (patch)
treeb0cd73d052383791201ad06e0e15c491a08cc5e4
parentc9fa9c327b5228c516f4a8c54b91b711526e3e96 (diff)
drivers: remove the SGI SN2 IOC4 base support
The IOC4 is a multi-function chip seen on SGI SN2 and some SGI MIPS systems. This removes the base driver, which while not having an SN2 Kconfig dependency was only for sub-drivers that had one. Signed-off-by: Christoph Hellwig <hch@lst.de> Link: https://lkml.kernel.org/r/20190813072514.23299-15-hch@lst.de Signed-off-by: Tony Luck <tony.luck@intel.com>
-rw-r--r--Documentation/driver-api/sgi-ioc4.rst49
-rw-r--r--arch/ia64/configs/generic_defconfig1
-rw-r--r--arch/ia64/configs/gensparse_defconfig1
-rw-r--r--arch/mips/configs/bigsur_defconfig1
-rw-r--r--arch/mips/configs/ip32_defconfig1
-rw-r--r--arch/mips/configs/markeins_defconfig1
-rw-r--r--arch/mips/configs/rm200_defconfig1
-rw-r--r--arch/mips/configs/sb1250_swarm_defconfig1
-rw-r--r--drivers/misc/Kconfig12
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/ioc4.c498
-rw-r--r--include/linux/ioc4.h184
-rw-r--r--include/linux/pci_ids.h1
13 files changed, 0 insertions, 752 deletions
diff --git a/Documentation/driver-api/sgi-ioc4.rst b/Documentation/driver-api/sgi-ioc4.rst
deleted file mode 100644
index 72709222d3c0..000000000000
--- a/Documentation/driver-api/sgi-ioc4.rst
+++ /dev/null
@@ -1,49 +0,0 @@
1====================================
2SGI IOC4 PCI (multi function) device
3====================================
4
5The SGI IOC4 PCI device is a bit of a strange beast, so some notes on
6it are in order.
7
8First, even though the IOC4 performs multiple functions, such as an
9IDE controller, a serial controller, a PS/2 keyboard/mouse controller,
10and an external interrupt mechanism, it's not implemented as a
11multifunction device. The consequence of this from a software
12standpoint is that all these functions share a single IRQ, and
13they can't all register to own the same PCI device ID. To make
14matters a bit worse, some of the register blocks (and even registers
15themselves) present in IOC4 are mixed-purpose between these several
16functions, meaning that there's no clear "owning" device driver.
17
18The solution is to organize the IOC4 driver into several independent
19drivers, "ioc4", "sgiioc4", and "ioc4_serial". Note that there is no
20PS/2 controller driver as this functionality has never been wired up
21on a shipping IO card.
22
23ioc4
24====
25This is the core (or shim) driver for IOC4. It is responsible for
26initializing the basic functionality of the chip, and allocating
27the PCI resources that are shared between the IOC4 functions.
28
29This driver also provides registration functions that the other
30IOC4 drivers can call to make their presence known. Each driver
31needs to provide a probe and remove function, which are invoked
32by the core driver at appropriate times. The interface of these
33IOC4 function probe and remove operations isn't precisely the same
34as PCI device probe and remove operations, but is logically the
35same operation.
36
37sgiioc4
38=======
39This is the IDE driver for IOC4. Its name isn't very descriptive
40simply for historical reasons (it used to be the only IOC4 driver
41component). There's not much to say about it other than it hooks
42up to the ioc4 driver via the appropriate registration, probe, and
43remove functions.
44
45ioc4_serial
46===========
47This is the serial driver for IOC4. There's not much to say about it
48other than it hooks up to the ioc4 driver via the appropriate registration,
49probe, and remove functions.
diff --git a/arch/ia64/configs/generic_defconfig b/arch/ia64/configs/generic_defconfig
index 8dd921dce4b5..661d90b3e148 100644
--- a/arch/ia64/configs/generic_defconfig
+++ b/arch/ia64/configs/generic_defconfig
@@ -44,7 +44,6 @@ CONFIG_BLK_DEV_LOOP=m
44CONFIG_BLK_DEV_CRYPTOLOOP=m 44CONFIG_BLK_DEV_CRYPTOLOOP=m
45CONFIG_BLK_DEV_NBD=m 45CONFIG_BLK_DEV_NBD=m
46CONFIG_BLK_DEV_RAM=y 46CONFIG_BLK_DEV_RAM=y
47CONFIG_SGI_IOC4=y
48CONFIG_SGI_XP=m 47CONFIG_SGI_XP=m
49CONFIG_IDE=y 48CONFIG_IDE=y
50CONFIG_BLK_DEV_IDECD=y 49CONFIG_BLK_DEV_IDECD=y
diff --git a/arch/ia64/configs/gensparse_defconfig b/arch/ia64/configs/gensparse_defconfig
index 5d5ea744f7e6..7844e6a956a4 100644
--- a/arch/ia64/configs/gensparse_defconfig
+++ b/arch/ia64/configs/gensparse_defconfig
@@ -36,7 +36,6 @@ CONFIG_BLK_DEV_LOOP=m
36CONFIG_BLK_DEV_CRYPTOLOOP=m 36CONFIG_BLK_DEV_CRYPTOLOOP=m
37CONFIG_BLK_DEV_NBD=m 37CONFIG_BLK_DEV_NBD=m
38CONFIG_BLK_DEV_RAM=y 38CONFIG_BLK_DEV_RAM=y
39CONFIG_SGI_IOC4=y
40CONFIG_IDE=y 39CONFIG_IDE=y
41CONFIG_BLK_DEV_IDECD=y 40CONFIG_BLK_DEV_IDECD=y
42CONFIG_IDE_GENERIC=y 41CONFIG_IDE_GENERIC=y
diff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfig
index 66566026409d..f14ad0538f4e 100644
--- a/arch/mips/configs/bigsur_defconfig
+++ b/arch/mips/configs/bigsur_defconfig
@@ -103,7 +103,6 @@ CONFIG_FW_LOADER=m
103CONFIG_BLK_DEV_LOOP=m 103CONFIG_BLK_DEV_LOOP=m
104CONFIG_BLK_DEV_CRYPTOLOOP=m 104CONFIG_BLK_DEV_CRYPTOLOOP=m
105CONFIG_BLK_DEV_NBD=m 105CONFIG_BLK_DEV_NBD=m
106CONFIG_SGI_IOC4=m
107CONFIG_EEPROM_LEGACY=y 106CONFIG_EEPROM_LEGACY=y
108CONFIG_EEPROM_MAX6875=y 107CONFIG_EEPROM_MAX6875=y
109CONFIG_IDE=y 108CONFIG_IDE=y
diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig
index 572cab91670c..370884018aad 100644
--- a/arch/mips/configs/ip32_defconfig
+++ b/arch/mips/configs/ip32_defconfig
@@ -46,7 +46,6 @@ CONFIG_CONNECTOR=y
46CONFIG_BLK_DEV_LOOP=m 46CONFIG_BLK_DEV_LOOP=m
47CONFIG_BLK_DEV_CRYPTOLOOP=m 47CONFIG_BLK_DEV_CRYPTOLOOP=m
48CONFIG_BLK_DEV_NBD=m 48CONFIG_BLK_DEV_NBD=m
49CONFIG_SGI_IOC4=y
50CONFIG_RAID_ATTRS=y 49CONFIG_RAID_ATTRS=y
51CONFIG_SCSI=y 50CONFIG_SCSI=y
52CONFIG_BLK_DEV_SD=y 51CONFIG_BLK_DEV_SD=y
diff --git a/arch/mips/configs/markeins_defconfig b/arch/mips/configs/markeins_defconfig
index ae93a94f8c71..507ad91b21e7 100644
--- a/arch/mips/configs/markeins_defconfig
+++ b/arch/mips/configs/markeins_defconfig
@@ -117,7 +117,6 @@ CONFIG_MTD_CFI_AMDSTD=y
117CONFIG_MTD_PHYSMAP=y 117CONFIG_MTD_PHYSMAP=y
118CONFIG_BLK_DEV_LOOP=m 118CONFIG_BLK_DEV_LOOP=m
119CONFIG_BLK_DEV_CRYPTOLOOP=m 119CONFIG_BLK_DEV_CRYPTOLOOP=m
120CONFIG_SGI_IOC4=m
121CONFIG_SCSI=m 120CONFIG_SCSI=m
122# CONFIG_SCSI_PROC_FS is not set 121# CONFIG_SCSI_PROC_FS is not set
123CONFIG_BLK_DEV_SD=m 122CONFIG_BLK_DEV_SD=m
diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig
index 0f4b09f8a0ee..8762e75f5d5f 100644
--- a/arch/mips/configs/rm200_defconfig
+++ b/arch/mips/configs/rm200_defconfig
@@ -198,7 +198,6 @@ CONFIG_BLK_DEV_SX8=m
198CONFIG_BLK_DEV_RAM=m 198CONFIG_BLK_DEV_RAM=m
199CONFIG_CDROM_PKTCDVD=m 199CONFIG_CDROM_PKTCDVD=m
200CONFIG_ATA_OVER_ETH=m 200CONFIG_ATA_OVER_ETH=m
201CONFIG_SGI_IOC4=m
202CONFIG_RAID_ATTRS=m 201CONFIG_RAID_ATTRS=m
203CONFIG_SCSI=y 202CONFIG_SCSI=y
204CONFIG_BLK_DEV_SD=y 203CONFIG_BLK_DEV_SD=y
diff --git a/arch/mips/configs/sb1250_swarm_defconfig b/arch/mips/configs/sb1250_swarm_defconfig
index 6883ea4477d4..bb0b1b22ebe1 100644
--- a/arch/mips/configs/sb1250_swarm_defconfig
+++ b/arch/mips/configs/sb1250_swarm_defconfig
@@ -49,7 +49,6 @@ CONFIG_BLK_DEV_RAM=y
49CONFIG_BLK_DEV_RAM_SIZE=9220 49CONFIG_BLK_DEV_RAM_SIZE=9220
50CONFIG_CDROM_PKTCDVD=m 50CONFIG_CDROM_PKTCDVD=m
51CONFIG_ATA_OVER_ETH=m 51CONFIG_ATA_OVER_ETH=m
52CONFIG_SGI_IOC4=m
53CONFIG_IDE=y 52CONFIG_IDE=y
54CONFIG_BLK_DEV_IDECD=y 53CONFIG_BLK_DEV_IDECD=y
55CONFIG_BLK_DEV_IDETAPE=y 54CONFIG_BLK_DEV_IDETAPE=y
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 299032693934..423d2d26d8f7 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -126,18 +126,6 @@ config INTEL_MID_PTI
126 an Intel Atom (non-netbook) mobile device containing a MIPI 126 an Intel Atom (non-netbook) mobile device containing a MIPI
127 P1149.7 standard implementation. 127 P1149.7 standard implementation.
128 128
129config SGI_IOC4
130 tristate "SGI IOC4 Base IO support"
131 depends on PCI
132 ---help---
133 This option enables basic support for the IOC4 chip on certain
134 SGI IO controller cards (IO9, IO10, and PCI-RT). This option
135 does not enable any specific functions on such a card, but provides
136 necessary infrastructure for other drivers to utilize.
137
138 If you have an SGI Altix with an IOC4-based card say Y.
139 Otherwise say N.
140
141config TIFM_CORE 129config TIFM_CORE
142 tristate "TI Flash Media interface support" 130 tristate "TI Flash Media interface support"
143 depends on PCI 131 depends on PCI
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index abd8ae249746..8dae0a976200 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -21,7 +21,6 @@ obj-$(CONFIG_QCOM_COINCELL) += qcom-coincell.o
21obj-$(CONFIG_QCOM_FASTRPC) += fastrpc.o 21obj-$(CONFIG_QCOM_FASTRPC) += fastrpc.o
22obj-$(CONFIG_SENSORS_BH1770) += bh1770glc.o 22obj-$(CONFIG_SENSORS_BH1770) += bh1770glc.o
23obj-$(CONFIG_SENSORS_APDS990X) += apds990x.o 23obj-$(CONFIG_SENSORS_APDS990X) += apds990x.o
24obj-$(CONFIG_SGI_IOC4) += ioc4.o
25obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o 24obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o
26obj-$(CONFIG_KGDB_TESTS) += kgdbts.o 25obj-$(CONFIG_KGDB_TESTS) += kgdbts.o
27obj-$(CONFIG_SGI_XP) += sgi-xp/ 26obj-$(CONFIG_SGI_XP) += sgi-xp/
diff --git a/drivers/misc/ioc4.c b/drivers/misc/ioc4.c
deleted file mode 100644
index 9d0445a567db..000000000000
--- a/drivers/misc/ioc4.c
+++ /dev/null
@@ -1,498 +0,0 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2005-2006 Silicon Graphics, Inc. All Rights Reserved.
7 */
8
9/* This file contains the master driver module for use by SGI IOC4 subdrivers.
10 *
11 * It allocates any resources shared between multiple subdevices, and
12 * provides accessor functions (where needed) and the like for those
13 * resources. It also provides a mechanism for the subdevice modules
14 * to support loading and unloading.
15 *
16 * Non-shared resources (e.g. external interrupt A_INT_OUT register page
17 * alias, serial port and UART registers) are handled by the subdevice
18 * modules themselves.
19 *
20 * This is all necessary because IOC4 is not implemented as a multi-function
21 * PCI device, but an amalgamation of disparate registers for several
22 * types of device (ATA, serial, external interrupts). The normal
23 * resource management in the kernel doesn't have quite the right interfaces
24 * to handle this situation (e.g. multiple modules can't claim the same
25 * PCI ID), thus this IOC4 master module.
26 */
27
28#include <linux/errno.h>
29#include <linux/module.h>
30#include <linux/pci.h>
31#include <linux/ioc4.h>
32#include <linux/ktime.h>
33#include <linux/slab.h>
34#include <linux/mutex.h>
35#include <linux/time.h>
36#include <asm/io.h>
37
38/***************
39 * Definitions *
40 ***************/
41
42/* Tweakable values */
43
44/* PCI bus speed detection/calibration */
45#define IOC4_CALIBRATE_COUNT 63 /* Calibration cycle period */
46#define IOC4_CALIBRATE_CYCLES 256 /* Average over this many cycles */
47#define IOC4_CALIBRATE_DISCARD 2 /* Discard first few cycles */
48#define IOC4_CALIBRATE_LOW_MHZ 25 /* Lower bound on bus speed sanity */
49#define IOC4_CALIBRATE_HIGH_MHZ 75 /* Upper bound on bus speed sanity */
50#define IOC4_CALIBRATE_DEFAULT_MHZ 66 /* Assumed if sanity check fails */
51
52/************************
53 * Submodule management *
54 ************************/
55
56static DEFINE_MUTEX(ioc4_mutex);
57
58static LIST_HEAD(ioc4_devices);
59static LIST_HEAD(ioc4_submodules);
60
61/* Register an IOC4 submodule */
62int
63ioc4_register_submodule(struct ioc4_submodule *is)
64{
65 struct ioc4_driver_data *idd;
66
67 mutex_lock(&ioc4_mutex);
68 list_add(&is->is_list, &ioc4_submodules);
69
70 /* Initialize submodule for each IOC4 */
71 if (!is->is_probe)
72 goto out;
73
74 list_for_each_entry(idd, &ioc4_devices, idd_list) {
75 if (is->is_probe(idd)) {
76 printk(KERN_WARNING
77 "%s: IOC4 submodule %s probe failed "
78 "for pci_dev %s",
79 __func__, module_name(is->is_owner),
80 pci_name(idd->idd_pdev));
81 }
82 }
83 out:
84 mutex_unlock(&ioc4_mutex);
85 return 0;
86}
87
88/* Unregister an IOC4 submodule */
89void
90ioc4_unregister_submodule(struct ioc4_submodule *is)
91{
92 struct ioc4_driver_data *idd;
93
94 mutex_lock(&ioc4_mutex);
95 list_del(&is->is_list);
96
97 /* Remove submodule for each IOC4 */
98 if (!is->is_remove)
99 goto out;
100
101 list_for_each_entry(idd, &ioc4_devices, idd_list) {
102 if (is->is_remove(idd)) {
103 printk(KERN_WARNING
104 "%s: IOC4 submodule %s remove failed "
105 "for pci_dev %s.\n",
106 __func__, module_name(is->is_owner),
107 pci_name(idd->idd_pdev));
108 }
109 }
110 out:
111 mutex_unlock(&ioc4_mutex);
112}
113
114/*********************
115 * Device management *
116 *********************/
117
118#define IOC4_CALIBRATE_LOW_LIMIT \
119 (1000*IOC4_EXTINT_COUNT_DIVISOR/IOC4_CALIBRATE_LOW_MHZ)
120#define IOC4_CALIBRATE_HIGH_LIMIT \
121 (1000*IOC4_EXTINT_COUNT_DIVISOR/IOC4_CALIBRATE_HIGH_MHZ)
122#define IOC4_CALIBRATE_DEFAULT \
123 (1000*IOC4_EXTINT_COUNT_DIVISOR/IOC4_CALIBRATE_DEFAULT_MHZ)
124
125#define IOC4_CALIBRATE_END \
126 (IOC4_CALIBRATE_CYCLES + IOC4_CALIBRATE_DISCARD)
127
128#define IOC4_INT_OUT_MODE_TOGGLE 0x7 /* Toggle INT_OUT every COUNT+1 ticks */
129
130/* Determines external interrupt output clock period of the PCI bus an
131 * IOC4 is attached to. This value can be used to determine the PCI
132 * bus speed.
133 *
134 * IOC4 has a design feature that various internal timers are derived from
135 * the PCI bus clock. This causes IOC4 device drivers to need to take the
136 * bus speed into account when setting various register values (e.g. INT_OUT
137 * register COUNT field, UART divisors, etc). Since this information is
138 * needed by several subdrivers, it is determined by the main IOC4 driver,
139 * even though the following code utilizes external interrupt registers
140 * to perform the speed calculation.
141 */
142static void
143ioc4_clock_calibrate(struct ioc4_driver_data *idd)
144{
145 union ioc4_int_out int_out;
146 union ioc4_gpcr gpcr;
147 unsigned int state, last_state;
148 uint64_t start, end, period;
149 unsigned int count;
150
151 /* Enable output */
152 gpcr.raw = 0;
153 gpcr.fields.dir = IOC4_GPCR_DIR_0;
154 gpcr.fields.int_out_en = 1;
155 writel(gpcr.raw, &idd->idd_misc_regs->gpcr_s.raw);
156
157 /* Reset to power-on state */
158 writel(0, &idd->idd_misc_regs->int_out.raw);
159
160 /* Set up square wave */
161 int_out.raw = 0;
162 int_out.fields.count = IOC4_CALIBRATE_COUNT;
163 int_out.fields.mode = IOC4_INT_OUT_MODE_TOGGLE;
164 int_out.fields.diag = 0;
165 writel(int_out.raw, &idd->idd_misc_regs->int_out.raw);
166
167 /* Check square wave period averaged over some number of cycles */
168 start = ktime_get_ns();
169 state = 1; /* make sure the first read isn't a rising edge */
170 for (count = 0; count <= IOC4_CALIBRATE_END; count++) {
171 do { /* wait for a rising edge */
172 last_state = state;
173 int_out.raw = readl(&idd->idd_misc_regs->int_out.raw);
174 state = int_out.fields.int_out;
175 } while (last_state || !state);
176
177 /* discard the first few cycles */
178 if (count == IOC4_CALIBRATE_DISCARD)
179 start = ktime_get_ns();
180 }
181 end = ktime_get_ns();
182
183 /* Calculation rearranged to preserve intermediate precision.
184 * Logically:
185 * 1. "end - start" gives us the measurement period over all
186 * the square wave cycles.
187 * 2. Divide by number of square wave cycles to get the period
188 * of a square wave cycle.
189 * 3. Divide by 2*(int_out.fields.count+1), which is the formula
190 * by which the IOC4 generates the square wave, to get the
191 * period of an IOC4 INT_OUT count.
192 */
193 period = (end - start) /
194 (IOC4_CALIBRATE_CYCLES * 2 * (IOC4_CALIBRATE_COUNT + 1));
195
196 /* Bounds check the result. */
197 if (period > IOC4_CALIBRATE_LOW_LIMIT ||
198 period < IOC4_CALIBRATE_HIGH_LIMIT) {
199 printk(KERN_INFO
200 "IOC4 %s: Clock calibration failed. Assuming"
201 "PCI clock is %d ns.\n",
202 pci_name(idd->idd_pdev),
203 IOC4_CALIBRATE_DEFAULT / IOC4_EXTINT_COUNT_DIVISOR);
204 period = IOC4_CALIBRATE_DEFAULT;
205 } else {
206 u64 ns = period;
207
208 do_div(ns, IOC4_EXTINT_COUNT_DIVISOR);
209 printk(KERN_DEBUG
210 "IOC4 %s: PCI clock is %llu ns.\n",
211 pci_name(idd->idd_pdev), (unsigned long long)ns);
212 }
213
214 /* Remember results. We store the extint clock period rather
215 * than the PCI clock period so that greater precision is
216 * retained. Divide by IOC4_EXTINT_COUNT_DIVISOR to get
217 * PCI clock period.
218 */
219 idd->count_period = period;
220}
221
222/* There are three variants of IOC4 cards: IO9, IO10, and PCI-RT.
223 * Each brings out different combinations of IOC4 signals, thus.
224 * the IOC4 subdrivers need to know to which we're attached.
225 *
226 * We look for the presence of a SCSI (IO9) or SATA (IO10) controller
227 * on the same PCI bus at slot number 3 to differentiate IO9 from IO10.
228 * If neither is present, it's a PCI-RT.
229 */
230static unsigned int
231ioc4_variant(struct ioc4_driver_data *idd)
232{
233 struct pci_dev *pdev = NULL;
234 int found = 0;
235
236 /* IO9: Look for a QLogic ISP 12160 at the same bus and slot 3. */
237 do {
238 pdev = pci_get_device(PCI_VENDOR_ID_QLOGIC,
239 PCI_DEVICE_ID_QLOGIC_ISP12160, pdev);
240 if (pdev &&
241 idd->idd_pdev->bus->number == pdev->bus->number &&
242 3 == PCI_SLOT(pdev->devfn))
243 found = 1;
244 } while (pdev && !found);
245 if (NULL != pdev) {
246 pci_dev_put(pdev);
247 return IOC4_VARIANT_IO9;
248 }
249
250 /* IO10: Look for a Vitesse VSC 7174 at the same bus and slot 3. */
251 pdev = NULL;
252 do {
253 pdev = pci_get_device(PCI_VENDOR_ID_VITESSE,
254 PCI_DEVICE_ID_VITESSE_VSC7174, pdev);
255 if (pdev &&
256 idd->idd_pdev->bus->number == pdev->bus->number &&
257 3 == PCI_SLOT(pdev->devfn))
258 found = 1;
259 } while (pdev && !found);
260 if (NULL != pdev) {
261 pci_dev_put(pdev);
262 return IOC4_VARIANT_IO10;
263 }
264
265 /* PCI-RT: No SCSI/SATA controller will be present */
266 return IOC4_VARIANT_PCI_RT;
267}
268
269static void
270ioc4_load_modules(struct work_struct *work)
271{
272 request_module("sgiioc4");
273}
274
275static DECLARE_WORK(ioc4_load_modules_work, ioc4_load_modules);
276
277/* Adds a new instance of an IOC4 card */
278static int
279ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
280{
281 struct ioc4_driver_data *idd;
282 struct ioc4_submodule *is;
283 uint32_t pcmd;
284 int ret;
285
286 /* Enable IOC4 and take ownership of it */
287 if ((ret = pci_enable_device(pdev))) {
288 printk(KERN_WARNING
289 "%s: Failed to enable IOC4 device for pci_dev %s.\n",
290 __func__, pci_name(pdev));
291 goto out;
292 }
293 pci_set_master(pdev);
294
295 /* Set up per-IOC4 data */
296 idd = kmalloc(sizeof(struct ioc4_driver_data), GFP_KERNEL);
297 if (!idd) {
298 printk(KERN_WARNING
299 "%s: Failed to allocate IOC4 data for pci_dev %s.\n",
300 __func__, pci_name(pdev));
301 ret = -ENODEV;
302 goto out_idd;
303 }
304 idd->idd_pdev = pdev;
305 idd->idd_pci_id = pci_id;
306
307 /* Map IOC4 misc registers. These are shared between subdevices
308 * so the main IOC4 module manages them.
309 */
310 idd->idd_bar0 = pci_resource_start(idd->idd_pdev, 0);
311 if (!idd->idd_bar0) {
312 printk(KERN_WARNING
313 "%s: Unable to find IOC4 misc resource "
314 "for pci_dev %s.\n",
315 __func__, pci_name(idd->idd_pdev));
316 ret = -ENODEV;
317 goto out_pci;
318 }
319 if (!request_mem_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs),
320 "ioc4_misc")) {
321 printk(KERN_WARNING
322 "%s: Unable to request IOC4 misc region "
323 "for pci_dev %s.\n",
324 __func__, pci_name(idd->idd_pdev));
325 ret = -ENODEV;
326 goto out_pci;
327 }
328 idd->idd_misc_regs = ioremap(idd->idd_bar0,
329 sizeof(struct ioc4_misc_regs));
330 if (!idd->idd_misc_regs) {
331 printk(KERN_WARNING
332 "%s: Unable to remap IOC4 misc region "
333 "for pci_dev %s.\n",
334 __func__, pci_name(idd->idd_pdev));
335 ret = -ENODEV;
336 goto out_misc_region;
337 }
338
339 /* Failsafe portion of per-IOC4 initialization */
340
341 /* Detect card variant */
342 idd->idd_variant = ioc4_variant(idd);
343 printk(KERN_INFO "IOC4 %s: %s card detected.\n", pci_name(pdev),
344 idd->idd_variant == IOC4_VARIANT_IO9 ? "IO9" :
345 idd->idd_variant == IOC4_VARIANT_PCI_RT ? "PCI-RT" :
346 idd->idd_variant == IOC4_VARIANT_IO10 ? "IO10" : "unknown");
347
348 /* Initialize IOC4 */
349 pci_read_config_dword(idd->idd_pdev, PCI_COMMAND, &pcmd);
350 pci_write_config_dword(idd->idd_pdev, PCI_COMMAND,
351 pcmd | PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
352
353 /* Determine PCI clock */
354 ioc4_clock_calibrate(idd);
355
356 /* Disable/clear all interrupts. Need to do this here lest
357 * one submodule request the shared IOC4 IRQ, but interrupt
358 * is generated by a different subdevice.
359 */
360 /* Disable */
361 writel(~0, &idd->idd_misc_regs->other_iec.raw);
362 writel(~0, &idd->idd_misc_regs->sio_iec);
363 /* Clear (i.e. acknowledge) */
364 writel(~0, &idd->idd_misc_regs->other_ir.raw);
365 writel(~0, &idd->idd_misc_regs->sio_ir);
366
367 /* Track PCI-device specific data */
368 idd->idd_serial_data = NULL;
369 pci_set_drvdata(idd->idd_pdev, idd);
370
371 mutex_lock(&ioc4_mutex);
372 list_add_tail(&idd->idd_list, &ioc4_devices);
373
374 /* Add this IOC4 to all submodules */
375 list_for_each_entry(is, &ioc4_submodules, is_list) {
376 if (is->is_probe && is->is_probe(idd)) {
377 printk(KERN_WARNING
378 "%s: IOC4 submodule 0x%s probe failed "
379 "for pci_dev %s.\n",
380 __func__, module_name(is->is_owner),
381 pci_name(idd->idd_pdev));
382 }
383 }
384 mutex_unlock(&ioc4_mutex);
385
386 /* Request sgiioc4 IDE driver on boards that bring that functionality
387 * off of IOC4. The root filesystem may be hosted on a drive connected
388 * to IOC4, so we need to make sure the sgiioc4 driver is loaded as it
389 * won't be picked up by modprobes due to the ioc4 module owning the
390 * PCI device.
391 */
392 if (idd->idd_variant != IOC4_VARIANT_PCI_RT) {
393 /* Request the module from a work procedure as the modprobe
394 * goes out to a userland helper and that will hang if done
395 * directly from ioc4_probe().
396 */
397 printk(KERN_INFO "IOC4 loading sgiioc4 submodule\n");
398 schedule_work(&ioc4_load_modules_work);
399 }
400
401 return 0;
402
403out_misc_region:
404 release_mem_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs));
405out_pci:
406 kfree(idd);
407out_idd:
408 pci_disable_device(pdev);
409out:
410 return ret;
411}
412
413/* Removes a particular instance of an IOC4 card. */
414static void
415ioc4_remove(struct pci_dev *pdev)
416{
417 struct ioc4_submodule *is;
418 struct ioc4_driver_data *idd;
419
420 idd = pci_get_drvdata(pdev);
421
422 /* Remove this IOC4 from all submodules */
423 mutex_lock(&ioc4_mutex);
424 list_for_each_entry(is, &ioc4_submodules, is_list) {
425 if (is->is_remove && is->is_remove(idd)) {
426 printk(KERN_WARNING
427 "%s: IOC4 submodule 0x%s remove failed "
428 "for pci_dev %s.\n",
429 __func__, module_name(is->is_owner),
430 pci_name(idd->idd_pdev));
431 }
432 }
433 mutex_unlock(&ioc4_mutex);
434
435 /* Release resources */
436 iounmap(idd->idd_misc_regs);
437 if (!idd->idd_bar0) {
438 printk(KERN_WARNING
439 "%s: Unable to get IOC4 misc mapping for pci_dev %s. "
440 "Device removal may be incomplete.\n",
441 __func__, pci_name(idd->idd_pdev));
442 }
443 release_mem_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs));
444
445 /* Disable IOC4 and relinquish */
446 pci_disable_device(pdev);
447
448 /* Remove and free driver data */
449 mutex_lock(&ioc4_mutex);
450 list_del(&idd->idd_list);
451 mutex_unlock(&ioc4_mutex);
452 kfree(idd);
453}
454
455static const struct pci_device_id ioc4_id_table[] = {
456 {PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC4, PCI_ANY_ID,
457 PCI_ANY_ID, 0x0b4000, 0xFFFFFF},
458 {0}
459};
460
461static struct pci_driver ioc4_driver = {
462 .name = "IOC4",
463 .id_table = ioc4_id_table,
464 .probe = ioc4_probe,
465 .remove = ioc4_remove,
466};
467
468MODULE_DEVICE_TABLE(pci, ioc4_id_table);
469
470/*********************
471 * Module management *
472 *********************/
473
474/* Module load */
475static int __init
476ioc4_init(void)
477{
478 return pci_register_driver(&ioc4_driver);
479}
480
481/* Module unload */
482static void __exit
483ioc4_exit(void)
484{
485 /* Ensure ioc4_load_modules() has completed before exiting */
486 flush_work(&ioc4_load_modules_work);
487 pci_unregister_driver(&ioc4_driver);
488}
489
490module_init(ioc4_init);
491module_exit(ioc4_exit);
492
493MODULE_AUTHOR("Brent Casavant - Silicon Graphics, Inc. <bcasavan@sgi.com>");
494MODULE_DESCRIPTION("PCI driver master module for SGI IOC4 Base-IO Card");
495MODULE_LICENSE("GPL");
496
497EXPORT_SYMBOL(ioc4_register_submodule);
498EXPORT_SYMBOL(ioc4_unregister_submodule);
diff --git a/include/linux/ioc4.h b/include/linux/ioc4.h
deleted file mode 100644
index 51e2b9fb6372..000000000000
--- a/include/linux/ioc4.h
+++ /dev/null
@@ -1,184 +0,0 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (c) 2005 Silicon Graphics, Inc. All Rights Reserved.
7 */
8
9#ifndef _LINUX_IOC4_H
10#define _LINUX_IOC4_H
11
12#include <linux/interrupt.h>
13
14/***************
15 * Definitions *
16 ***************/
17
18/* Miscellaneous values inherent to hardware */
19
20#define IOC4_EXTINT_COUNT_DIVISOR 520 /* PCI clocks per COUNT tick */
21
22/***********************************
23 * Structures needed by subdrivers *
24 ***********************************/
25
26/* This structure fully describes the IOC4 miscellaneous registers which
27 * appear at bar[0]+0x00000 through bar[0]+0x0005c. The corresponding
28 * PCI resource is managed by the main IOC4 driver because it contains
29 * registers of interest to many different IOC4 subdrivers.
30 */
31struct ioc4_misc_regs {
32 /* Miscellaneous IOC4 registers */
33 union ioc4_pci_err_addr_l {
34 uint32_t raw;
35 struct {
36 uint32_t valid:1; /* Address captured */
37 uint32_t master_id:4; /* Unit causing error
38 * 0/1: Serial port 0 TX/RX
39 * 2/3: Serial port 1 TX/RX
40 * 4/5: Serial port 2 TX/RX
41 * 6/7: Serial port 3 TX/RX
42 * 8: ATA/ATAPI
43 * 9-15: Undefined
44 */
45 uint32_t mul_err:1; /* Multiple errors occurred */
46 uint32_t addr:26; /* Bits 31-6 of error addr */
47 } fields;
48 } pci_err_addr_l;
49 uint32_t pci_err_addr_h; /* Bits 63-32 of error addr */
50 union ioc4_sio_int {
51 uint32_t raw;
52 struct {
53 uint8_t tx_mt:1; /* TX ring buffer empty */
54 uint8_t rx_full:1; /* RX ring buffer full */
55 uint8_t rx_high:1; /* RX high-water exceeded */
56 uint8_t rx_timer:1; /* RX timer has triggered */
57 uint8_t delta_dcd:1; /* DELTA_DCD seen */
58 uint8_t delta_cts:1; /* DELTA_CTS seen */
59 uint8_t intr_pass:1; /* Interrupt pass-through */
60 uint8_t tx_explicit:1; /* TX, MCW, or delay complete */
61 } fields[4];
62 } sio_ir; /* Serial interrupt state */
63 union ioc4_other_int {
64 uint32_t raw;
65 struct {
66 uint32_t ata_int:1; /* ATA port passthru */
67 uint32_t ata_memerr:1; /* ATA halted by mem error */
68 uint32_t memerr:4; /* Serial halted by mem err */
69 uint32_t kbd_int:1; /* kbd/mouse intr asserted */
70 uint32_t reserved:16; /* zero */
71 uint32_t rt_int:1; /* INT_OUT section latch */
72 uint32_t gen_int:8; /* Intr. from generic pins */
73 } fields;
74 } other_ir; /* Other interrupt state */
75 union ioc4_sio_int sio_ies; /* Serial interrupt enable set */
76 union ioc4_other_int other_ies; /* Other interrupt enable set */
77 union ioc4_sio_int sio_iec; /* Serial interrupt enable clear */
78 union ioc4_other_int other_iec; /* Other interrupt enable clear */
79 union ioc4_sio_cr {
80 uint32_t raw;
81 struct {
82 uint32_t cmd_pulse:4; /* Bytebus strobe width */
83 uint32_t arb_diag:3; /* PCI bus requester */
84 uint32_t sio_diag_idle:1; /* Active ser req? */
85 uint32_t ata_diag_idle:1; /* Active ATA req? */
86 uint32_t ata_diag_active:1; /* ATA req is winner */
87 uint32_t reserved:22; /* zero */
88 } fields;
89 } sio_cr;
90 uint32_t unused1;
91 union ioc4_int_out {
92 uint32_t raw;
93 struct {
94 uint32_t count:16; /* Period control */
95 uint32_t mode:3; /* Output signal shape */
96 uint32_t reserved:11; /* zero */
97 uint32_t diag:1; /* Timebase control */
98 uint32_t int_out:1; /* Current value */
99 } fields;
100 } int_out; /* External interrupt output control */
101 uint32_t unused2;
102 union ioc4_gpcr {
103 uint32_t raw;
104 struct {
105 uint32_t dir:8; /* Pin direction */
106 uint32_t edge:8; /* Edge/level mode */
107 uint32_t reserved1:4; /* zero */
108 uint32_t int_out_en:1; /* INT_OUT enable */
109 uint32_t reserved2:11; /* zero */
110 } fields;
111 } gpcr_s; /* Generic PIO control set */
112 union ioc4_gpcr gpcr_c; /* Generic PIO control clear */
113 union ioc4_gpdr {
114 uint32_t raw;
115 struct {
116 uint32_t gen_pin:8; /* State of pins */
117 uint32_t reserved:24;
118 } fields;
119 } gpdr; /* Generic PIO data */
120 uint32_t unused3;
121 union ioc4_gppr {
122 uint32_t raw;
123 struct {
124 uint32_t gen_pin:1; /* Single pin state */
125 uint32_t reserved:31;
126 } fields;
127 } gppr[8]; /* Generic PIO pins */
128};
129
130/* Masks for GPCR DIR pins */
131#define IOC4_GPCR_DIR_0 0x01 /* External interrupt output */
132#define IOC4_GPCR_DIR_1 0x02 /* External interrupt input */
133#define IOC4_GPCR_DIR_2 0x04
134#define IOC4_GPCR_DIR_3 0x08 /* Keyboard/mouse presence */
135#define IOC4_GPCR_DIR_4 0x10 /* Ser. port 0 xcvr select (0=232, 1=422) */
136#define IOC4_GPCR_DIR_5 0x20 /* Ser. port 1 xcvr select (0=232, 1=422) */
137#define IOC4_GPCR_DIR_6 0x40 /* Ser. port 2 xcvr select (0=232, 1=422) */
138#define IOC4_GPCR_DIR_7 0x80 /* Ser. port 3 xcvr select (0=232, 1=422) */
139
140/* Masks for GPCR EDGE pins */
141#define IOC4_GPCR_EDGE_0 0x01
142#define IOC4_GPCR_EDGE_1 0x02 /* External interrupt input */
143#define IOC4_GPCR_EDGE_2 0x04
144#define IOC4_GPCR_EDGE_3 0x08
145#define IOC4_GPCR_EDGE_4 0x10
146#define IOC4_GPCR_EDGE_5 0x20
147#define IOC4_GPCR_EDGE_6 0x40
148#define IOC4_GPCR_EDGE_7 0x80
149
150#define IOC4_VARIANT_IO9 0x0900
151#define IOC4_VARIANT_PCI_RT 0x0901
152#define IOC4_VARIANT_IO10 0x1000
153
154/* One of these per IOC4 */
155struct ioc4_driver_data {
156 struct list_head idd_list;
157 unsigned long idd_bar0;
158 struct pci_dev *idd_pdev;
159 const struct pci_device_id *idd_pci_id;
160 struct ioc4_misc_regs __iomem *idd_misc_regs;
161 unsigned long count_period;
162 void *idd_serial_data;
163 unsigned int idd_variant;
164};
165
166/* One per submodule */
167struct ioc4_submodule {
168 struct list_head is_list;
169 char *is_name;
170 struct module *is_owner;
171 int (*is_probe) (struct ioc4_driver_data *);
172 int (*is_remove) (struct ioc4_driver_data *);
173};
174
175#define IOC4_NUM_CARDS 8 /* max cards per partition */
176
177/**********************************
178 * Functions needed by submodules *
179 **********************************/
180
181extern int ioc4_register_submodule(struct ioc4_submodule *);
182extern void ioc4_unregister_submodule(struct ioc4_submodule *);
183
184#endif /* _LINUX_IOC4_H */
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index c842735a4f45..85e2ca611d42 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1070,7 +1070,6 @@
1070#define PCI_VENDOR_ID_SGI 0x10a9 1070#define PCI_VENDOR_ID_SGI 0x10a9
1071#define PCI_DEVICE_ID_SGI_IOC3 0x0003 1071#define PCI_DEVICE_ID_SGI_IOC3 0x0003
1072#define PCI_DEVICE_ID_SGI_LITHIUM 0x1002 1072#define PCI_DEVICE_ID_SGI_LITHIUM 0x1002
1073#define PCI_DEVICE_ID_SGI_IOC4 0x100a
1074 1073
1075#define PCI_VENDOR_ID_WINBOND 0x10ad 1074#define PCI_VENDOR_ID_WINBOND 0x10ad
1076#define PCI_DEVICE_ID_WINBOND_82C105 0x0105 1075#define PCI_DEVICE_ID_WINBOND_82C105 0x0105