linux/drivers/misc/ioc4.c
<<
>>
Prefs
   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);
 499