Merge git://git.kernel.org/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog
[pandora-kernel.git] / drivers / misc / ioc4.c
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/mutex.h>
34 #include <linux/time.h>
35
36 /***************
37  * Definitions *
38  ***************/
39
40 /* Tweakable values */
41
42 /* PCI bus speed detection/calibration */
43 #define IOC4_CALIBRATE_COUNT 63         /* Calibration cycle period */
44 #define IOC4_CALIBRATE_CYCLES 256       /* Average over this many cycles */
45 #define IOC4_CALIBRATE_DISCARD 2        /* Discard first few cycles */
46 #define IOC4_CALIBRATE_LOW_MHZ 25       /* Lower bound on bus speed sanity */
47 #define IOC4_CALIBRATE_HIGH_MHZ 75      /* Upper bound on bus speed sanity */
48 #define IOC4_CALIBRATE_DEFAULT_MHZ 66   /* Assumed if sanity check fails */
49
50 /************************
51  * Submodule management *
52  ************************/
53
54 static DEFINE_MUTEX(ioc4_mutex);
55
56 static LIST_HEAD(ioc4_devices);
57 static LIST_HEAD(ioc4_submodules);
58
59 /* Register an IOC4 submodule */
60 int
61 ioc4_register_submodule(struct ioc4_submodule *is)
62 {
63         struct ioc4_driver_data *idd;
64
65         mutex_lock(&ioc4_mutex);
66         list_add(&is->is_list, &ioc4_submodules);
67
68         /* Initialize submodule for each IOC4 */
69         if (!is->is_probe)
70                 goto out;
71
72         list_for_each_entry(idd, &ioc4_devices, idd_list) {
73                 if (is->is_probe(idd)) {
74                         printk(KERN_WARNING
75                                "%s: IOC4 submodule %s probe failed "
76                                "for pci_dev %s",
77                                __FUNCTION__, module_name(is->is_owner),
78                                pci_name(idd->idd_pdev));
79                 }
80         }
81  out:
82         mutex_unlock(&ioc4_mutex);
83         return 0;
84 }
85
86 /* Unregister an IOC4 submodule */
87 void
88 ioc4_unregister_submodule(struct ioc4_submodule *is)
89 {
90         struct ioc4_driver_data *idd;
91
92         mutex_lock(&ioc4_mutex);
93         list_del(&is->is_list);
94
95         /* Remove submodule for each IOC4 */
96         if (!is->is_remove)
97                 goto out;
98
99         list_for_each_entry(idd, &ioc4_devices, idd_list) {
100                 if (is->is_remove(idd)) {
101                         printk(KERN_WARNING
102                                "%s: IOC4 submodule %s remove failed "
103                                "for pci_dev %s.\n",
104                                __FUNCTION__, module_name(is->is_owner),
105                                pci_name(idd->idd_pdev));
106                 }
107         }
108  out:
109         mutex_unlock(&ioc4_mutex);
110 }
111
112 /*********************
113  * Device management *
114  *********************/
115
116 #define IOC4_CALIBRATE_LOW_LIMIT \
117         (1000*IOC4_EXTINT_COUNT_DIVISOR/IOC4_CALIBRATE_LOW_MHZ)
118 #define IOC4_CALIBRATE_HIGH_LIMIT \
119         (1000*IOC4_EXTINT_COUNT_DIVISOR/IOC4_CALIBRATE_HIGH_MHZ)
120 #define IOC4_CALIBRATE_DEFAULT \
121         (1000*IOC4_EXTINT_COUNT_DIVISOR/IOC4_CALIBRATE_DEFAULT_MHZ)
122
123 #define IOC4_CALIBRATE_END \
124         (IOC4_CALIBRATE_CYCLES + IOC4_CALIBRATE_DISCARD)
125
126 #define IOC4_INT_OUT_MODE_TOGGLE 0x7    /* Toggle INT_OUT every COUNT+1 ticks */
127
128 /* Determines external interrupt output clock period of the PCI bus an
129  * IOC4 is attached to.  This value can be used to determine the PCI
130  * bus speed.
131  *
132  * IOC4 has a design feature that various internal timers are derived from
133  * the PCI bus clock.  This causes IOC4 device drivers to need to take the
134  * bus speed into account when setting various register values (e.g. INT_OUT
135  * register COUNT field, UART divisors, etc).  Since this information is
136  * needed by several subdrivers, it is determined by the main IOC4 driver,
137  * even though the following code utilizes external interrupt registers
138  * to perform the speed calculation.
139  */
140 static void
141 ioc4_clock_calibrate(struct ioc4_driver_data *idd)
142 {
143         union ioc4_int_out int_out;
144         union ioc4_gpcr gpcr;
145         unsigned int state, last_state = 1;
146         struct timespec start_ts, end_ts;
147         uint64_t start, end, period;
148         unsigned int count = 0;
149
150         /* Enable output */
151         gpcr.raw = 0;
152         gpcr.fields.dir = IOC4_GPCR_DIR_0;
153         gpcr.fields.int_out_en = 1;
154         writel(gpcr.raw, &idd->idd_misc_regs->gpcr_s.raw);
155
156         /* Reset to power-on state */
157         writel(0, &idd->idd_misc_regs->int_out.raw);
158         mmiowb();
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         mmiowb();
167
168         /* Check square wave period averaged over some number of cycles */
169         do {
170                 int_out.raw = readl(&idd->idd_misc_regs->int_out.raw);
171                 state = int_out.fields.int_out;
172                 if (!last_state && state) {
173                         count++;
174                         if (count == IOC4_CALIBRATE_END) {
175                                 ktime_get_ts(&end_ts);
176                                 break;
177                         } else if (count == IOC4_CALIBRATE_DISCARD)
178                                 ktime_get_ts(&start_ts);
179                 }
180                 last_state = state;
181         } while (1);
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         end = end_ts.tv_sec * NSEC_PER_SEC + end_ts.tv_nsec;
194         start = start_ts.tv_sec * NSEC_PER_SEC + start_ts.tv_nsec;
195         period = (end - start) /
196                 (IOC4_CALIBRATE_CYCLES * 2 * (IOC4_CALIBRATE_COUNT + 1));
197
198         /* Bounds check the result. */
199         if (period > IOC4_CALIBRATE_LOW_LIMIT ||
200             period < IOC4_CALIBRATE_HIGH_LIMIT) {
201                 printk(KERN_INFO
202                        "IOC4 %s: Clock calibration failed.  Assuming"
203                        "PCI clock is %d ns.\n",
204                        pci_name(idd->idd_pdev),
205                        IOC4_CALIBRATE_DEFAULT / IOC4_EXTINT_COUNT_DIVISOR);
206                 period = IOC4_CALIBRATE_DEFAULT;
207         } else {
208                 u64 ns = period;
209
210                 do_div(ns, IOC4_EXTINT_COUNT_DIVISOR);
211                 printk(KERN_DEBUG
212                        "IOC4 %s: PCI clock is %lld ns.\n",
213                        pci_name(idd->idd_pdev), ns);
214         }
215
216         /* Remember results.  We store the extint clock period rather
217          * than the PCI clock period so that greater precision is
218          * retained.  Divide by IOC4_EXTINT_COUNT_DIVISOR to get
219          * PCI clock period.
220          */
221         idd->count_period = period;
222 }
223
224 /* There are three variants of IOC4 cards: IO9, IO10, and PCI-RT.
225  * Each brings out different combinations of IOC4 signals, thus.
226  * the IOC4 subdrivers need to know to which we're attached.
227  *
228  * We look for the presence of a SCSI (IO9) or SATA (IO10) controller
229  * on the same PCI bus at slot number 3 to differentiate IO9 from IO10.
230  * If neither is present, it's a PCI-RT.
231  */
232 static unsigned int
233 ioc4_variant(struct ioc4_driver_data *idd)
234 {
235         struct pci_dev *pdev = NULL;
236         int found = 0;
237
238         /* IO9: Look for a QLogic ISP 12160 at the same bus and slot 3. */
239         do {
240                 pdev = pci_get_device(PCI_VENDOR_ID_QLOGIC,
241                                       PCI_DEVICE_ID_QLOGIC_ISP12160, pdev);
242                 if (pdev &&
243                     idd->idd_pdev->bus->number == pdev->bus->number &&
244                     3 == PCI_SLOT(pdev->devfn))
245                         found = 1;
246                 pci_dev_put(pdev);
247         } while (pdev && !found);
248         if (NULL != pdev)
249                 return IOC4_VARIANT_IO9;
250
251         /* IO10: Look for a Vitesse VSC 7174 at the same bus and slot 3. */
252         pdev = NULL;
253         do {
254                 pdev = pci_get_device(PCI_VENDOR_ID_VITESSE,
255                                       PCI_DEVICE_ID_VITESSE_VSC7174, pdev);
256                 if (pdev &&
257                     idd->idd_pdev->bus->number == pdev->bus->number &&
258                     3 == PCI_SLOT(pdev->devfn))
259                         found = 1;
260                 pci_dev_put(pdev);
261         } while (pdev && !found);
262         if (NULL != pdev)
263                 return IOC4_VARIANT_IO10;
264
265         /* PCI-RT: No SCSI/SATA controller will be present */
266         return IOC4_VARIANT_PCI_RT;
267 }
268
269 /* Adds a new instance of an IOC4 card */
270 static int
271 ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
272 {
273         struct ioc4_driver_data *idd;
274         struct ioc4_submodule *is;
275         uint32_t pcmd;
276         int ret;
277
278         /* Enable IOC4 and take ownership of it */
279         if ((ret = pci_enable_device(pdev))) {
280                 printk(KERN_WARNING
281                        "%s: Failed to enable IOC4 device for pci_dev %s.\n",
282                        __FUNCTION__, pci_name(pdev));
283                 goto out;
284         }
285         pci_set_master(pdev);
286
287         /* Set up per-IOC4 data */
288         idd = kmalloc(sizeof(struct ioc4_driver_data), GFP_KERNEL);
289         if (!idd) {
290                 printk(KERN_WARNING
291                        "%s: Failed to allocate IOC4 data for pci_dev %s.\n",
292                        __FUNCTION__, pci_name(pdev));
293                 ret = -ENODEV;
294                 goto out_idd;
295         }
296         idd->idd_pdev = pdev;
297         idd->idd_pci_id = pci_id;
298
299         /* Map IOC4 misc registers.  These are shared between subdevices
300          * so the main IOC4 module manages them.
301          */
302         idd->idd_bar0 = pci_resource_start(idd->idd_pdev, 0);
303         if (!idd->idd_bar0) {
304                 printk(KERN_WARNING
305                        "%s: Unable to find IOC4 misc resource "
306                        "for pci_dev %s.\n",
307                        __FUNCTION__, pci_name(idd->idd_pdev));
308                 ret = -ENODEV;
309                 goto out_pci;
310         }
311         if (!request_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs),
312                             "ioc4_misc")) {
313                 printk(KERN_WARNING
314                        "%s: Unable to request IOC4 misc region "
315                        "for pci_dev %s.\n",
316                        __FUNCTION__, pci_name(idd->idd_pdev));
317                 ret = -ENODEV;
318                 goto out_pci;
319         }
320         idd->idd_misc_regs = ioremap(idd->idd_bar0,
321                                      sizeof(struct ioc4_misc_regs));
322         if (!idd->idd_misc_regs) {
323                 printk(KERN_WARNING
324                        "%s: Unable to remap IOC4 misc region "
325                        "for pci_dev %s.\n",
326                        __FUNCTION__, pci_name(idd->idd_pdev));
327                 ret = -ENODEV;
328                 goto out_misc_region;
329         }
330
331         /* Failsafe portion of per-IOC4 initialization */
332
333         /* Detect card variant */
334         idd->idd_variant = ioc4_variant(idd);
335         printk(KERN_INFO "IOC4 %s: %s card detected.\n", pci_name(pdev),
336                idd->idd_variant == IOC4_VARIANT_IO9 ? "IO9" :
337                idd->idd_variant == IOC4_VARIANT_PCI_RT ? "PCI-RT" :
338                idd->idd_variant == IOC4_VARIANT_IO10 ? "IO10" : "unknown");
339
340         /* Initialize IOC4 */
341         pci_read_config_dword(idd->idd_pdev, PCI_COMMAND, &pcmd);
342         pci_write_config_dword(idd->idd_pdev, PCI_COMMAND,
343                                pcmd | PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
344
345         /* Determine PCI clock */
346         ioc4_clock_calibrate(idd);
347
348         /* Disable/clear all interrupts.  Need to do this here lest
349          * one submodule request the shared IOC4 IRQ, but interrupt
350          * is generated by a different subdevice.
351          */
352         /* Disable */
353         writel(~0, &idd->idd_misc_regs->other_iec.raw);
354         writel(~0, &idd->idd_misc_regs->sio_iec);
355         /* Clear (i.e. acknowledge) */
356         writel(~0, &idd->idd_misc_regs->other_ir.raw);
357         writel(~0, &idd->idd_misc_regs->sio_ir);
358
359         /* Track PCI-device specific data */
360         idd->idd_serial_data = NULL;
361         pci_set_drvdata(idd->idd_pdev, idd);
362
363         mutex_lock(&ioc4_mutex);
364         list_add_tail(&idd->idd_list, &ioc4_devices);
365
366         /* Add this IOC4 to all submodules */
367         list_for_each_entry(is, &ioc4_submodules, is_list) {
368                 if (is->is_probe && is->is_probe(idd)) {
369                         printk(KERN_WARNING
370                                "%s: IOC4 submodule 0x%s probe failed "
371                                "for pci_dev %s.\n",
372                                __FUNCTION__, module_name(is->is_owner),
373                                pci_name(idd->idd_pdev));
374                 }
375         }
376         mutex_unlock(&ioc4_mutex);
377
378         return 0;
379
380 out_misc_region:
381         release_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs));
382 out_pci:
383         kfree(idd);
384 out_idd:
385         pci_disable_device(pdev);
386 out:
387         return ret;
388 }
389
390 /* Removes a particular instance of an IOC4 card. */
391 static void
392 ioc4_remove(struct pci_dev *pdev)
393 {
394         struct ioc4_submodule *is;
395         struct ioc4_driver_data *idd;
396
397         idd = pci_get_drvdata(pdev);
398
399         /* Remove this IOC4 from all submodules */
400         mutex_lock(&ioc4_mutex);
401         list_for_each_entry(is, &ioc4_submodules, is_list) {
402                 if (is->is_remove && is->is_remove(idd)) {
403                         printk(KERN_WARNING
404                                "%s: IOC4 submodule 0x%s remove failed "
405                                "for pci_dev %s.\n",
406                                __FUNCTION__, module_name(is->is_owner),
407                                pci_name(idd->idd_pdev));
408                 }
409         }
410         mutex_unlock(&ioc4_mutex);
411
412         /* Release resources */
413         iounmap(idd->idd_misc_regs);
414         if (!idd->idd_bar0) {
415                 printk(KERN_WARNING
416                        "%s: Unable to get IOC4 misc mapping for pci_dev %s. "
417                        "Device removal may be incomplete.\n",
418                        __FUNCTION__, pci_name(idd->idd_pdev));
419         }
420         release_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs));
421
422         /* Disable IOC4 and relinquish */
423         pci_disable_device(pdev);
424
425         /* Remove and free driver data */
426         mutex_lock(&ioc4_mutex);
427         list_del(&idd->idd_list);
428         mutex_unlock(&ioc4_mutex);
429         kfree(idd);
430 }
431
432 static struct pci_device_id ioc4_id_table[] = {
433         {PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC4, PCI_ANY_ID,
434          PCI_ANY_ID, 0x0b4000, 0xFFFFFF},
435         {0}
436 };
437
438 static struct pci_driver ioc4_driver = {
439         .name = "IOC4",
440         .id_table = ioc4_id_table,
441         .probe = ioc4_probe,
442         .remove = ioc4_remove,
443 };
444
445 MODULE_DEVICE_TABLE(pci, ioc4_id_table);
446
447 /*********************
448  * Module management *
449  *********************/
450
451 /* Module load */
452 static int __devinit
453 ioc4_init(void)
454 {
455         return pci_register_driver(&ioc4_driver);
456 }
457
458 /* Module unload */
459 static void __devexit
460 ioc4_exit(void)
461 {
462         pci_unregister_driver(&ioc4_driver);
463 }
464
465 module_init(ioc4_init);
466 module_exit(ioc4_exit);
467
468 MODULE_AUTHOR("Brent Casavant - Silicon Graphics, Inc. <bcasavan@sgi.com>");
469 MODULE_DESCRIPTION("PCI driver master module for SGI IOC4 Base-IO Card");
470 MODULE_LICENSE("GPL");
471
472 EXPORT_SYMBOL(ioc4_register_submodule);
473 EXPORT_SYMBOL(ioc4_unregister_submodule);