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 = 1;
 148        struct timespec start_ts, end_ts;
 149        uint64_t start, end, period;
 150        unsigned int count = 0;
 151
 152        /* Enable output */
 153        gpcr.raw = 0;
 154        gpcr.fields.dir = IOC4_GPCR_DIR_0;
 155        gpcr.fields.int_out_en = 1;
 156        writel(gpcr.raw, &idd->idd_misc_regs->gpcr_s.raw);
 157
 158        /* Reset to power-on state */
 159        writel(0, &idd->idd_misc_regs->int_out.raw);
 160        mmiowb();
 161
 162        /* Set up square wave */
 163        int_out.raw = 0;
 164        int_out.fields.count = IOC4_CALIBRATE_COUNT;
 165        int_out.fields.mode = IOC4_INT_OUT_MODE_TOGGLE;
 166        int_out.fields.diag = 0;
 167        writel(int_out.raw, &idd->idd_misc_regs->int_out.raw);
 168        mmiowb();
 169
 170        /* Check square wave period averaged over some number of cycles */
 171        do {
 172                int_out.raw = readl(&idd->idd_misc_regs->int_out.raw);
 173                state = int_out.fields.int_out;
 174                if (!last_state && state) {
 175                        count++;
 176                        if (count == IOC4_CALIBRATE_END) {
 177                                ktime_get_ts(&end_ts);
 178                                break;
 179                        } else if (count == IOC4_CALIBRATE_DISCARD)
 180                                ktime_get_ts(&start_ts);
 181                }
 182                last_state = state;
 183        } while (1);
 184
 185        /* Calculation rearranged to preserve intermediate precision.
 186         * Logically:
 187         * 1. "end - start" gives us the measurement period over all
 188         *    the square wave cycles.
 189         * 2. Divide by number of square wave cycles to get the period
 190         *    of a square wave cycle.
 191         * 3. Divide by 2*(int_out.fields.count+1), which is the formula
 192         *    by which the IOC4 generates the square wave, to get the
 193         *    period of an IOC4 INT_OUT count.
 194         */
 195        end = end_ts.tv_sec * NSEC_PER_SEC + end_ts.tv_nsec;
 196        start = start_ts.tv_sec * NSEC_PER_SEC + start_ts.tv_nsec;
 197        period = (end - start) /
 198                (IOC4_CALIBRATE_CYCLES * 2 * (IOC4_CALIBRATE_COUNT + 1));
 199
 200        /* Bounds check the result. */
 201        if (period > IOC4_CALIBRATE_LOW_LIMIT ||
 202            period < IOC4_CALIBRATE_HIGH_LIMIT) {
 203                printk(KERN_INFO
 204                       "IOC4 %s: Clock calibration failed.  Assuming"
 205                       "PCI clock is %d ns.\n",
 206                       pci_name(idd->idd_pdev),
 207                       IOC4_CALIBRATE_DEFAULT / IOC4_EXTINT_COUNT_DIVISOR);
 208                period = IOC4_CALIBRATE_DEFAULT;
 209        } else {
 210                u64 ns = period;
 211
 212                do_div(ns, IOC4_EXTINT_COUNT_DIVISOR);
 213                printk(KERN_DEBUG
 214                       "IOC4 %s: PCI clock is %llu ns.\n",
 215                       pci_name(idd->idd_pdev), (unsigned long long)ns);
 216        }
 217
 218        /* Remember results.  We store the extint clock period rather
 219         * than the PCI clock period so that greater precision is
 220         * retained.  Divide by IOC4_EXTINT_COUNT_DIVISOR to get
 221         * PCI clock period.
 222         */
 223        idd->count_period = period;
 224}
 225
 226/* There are three variants of IOC4 cards: IO9, IO10, and PCI-RT.
 227 * Each brings out different combinations of IOC4 signals, thus.
 228 * the IOC4 subdrivers need to know to which we're attached.
 229 *
 230 * We look for the presence of a SCSI (IO9) or SATA (IO10) controller
 231 * on the same PCI bus at slot number 3 to differentiate IO9 from IO10.
 232 * If neither is present, it's a PCI-RT.
 233 */
 234static unsigned int
 235ioc4_variant(struct ioc4_driver_data *idd)
 236{
 237        struct pci_dev *pdev = NULL;
 238        int found = 0;
 239
 240        /* IO9: Look for a QLogic ISP 12160 at the same bus and slot 3. */
 241        do {
 242                pdev = pci_get_device(PCI_VENDOR_ID_QLOGIC,
 243                                      PCI_DEVICE_ID_QLOGIC_ISP12160, pdev);
 244                if (pdev &&
 245                    idd->idd_pdev->bus->number == pdev->bus->number &&
 246                    3 == PCI_SLOT(pdev->devfn))
 247                        found = 1;
 248        } while (pdev && !found);
 249        if (NULL != pdev) {
 250                pci_dev_put(pdev);
 251                return IOC4_VARIANT_IO9;
 252        }
 253
 254        /* IO10: Look for a Vitesse VSC 7174 at the same bus and slot 3. */
 255        pdev = NULL;
 256        do {
 257                pdev = pci_get_device(PCI_VENDOR_ID_VITESSE,
 258                                      PCI_DEVICE_ID_VITESSE_VSC7174, pdev);
 259                if (pdev &&
 260                    idd->idd_pdev->bus->number == pdev->bus->number &&
 261                    3 == PCI_SLOT(pdev->devfn))
 262                        found = 1;
 263        } while (pdev && !found);
 264        if (NULL != pdev) {
 265                pci_dev_put(pdev);
 266                return IOC4_VARIANT_IO10;
 267        }
 268
 269        /* PCI-RT: No SCSI/SATA controller will be present */
 270        return IOC4_VARIANT_PCI_RT;
 271}
 272
 273static void
 274ioc4_load_modules(struct work_struct *work)
 275{
 276        request_module("sgiioc4");
 277}
 278
 279static DECLARE_WORK(ioc4_load_modules_work, ioc4_load_modules);
 280
 281/* Adds a new instance of an IOC4 card */
 282static int
 283ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
 284{
 285        struct ioc4_driver_data *idd;
 286        struct ioc4_submodule *is;
 287        uint32_t pcmd;
 288        int ret;
 289
 290        /* Enable IOC4 and take ownership of it */
 291        if ((ret = pci_enable_device(pdev))) {
 292                printk(KERN_WARNING
 293                       "%s: Failed to enable IOC4 device for pci_dev %s.\n",
 294                       __func__, pci_name(pdev));
 295                goto out;
 296        }
 297        pci_set_master(pdev);
 298
 299        /* Set up per-IOC4 data */
 300        idd = kmalloc(sizeof(struct ioc4_driver_data), GFP_KERNEL);
 301        if (!idd) {
 302                printk(KERN_WARNING
 303                       "%s: Failed to allocate IOC4 data for pci_dev %s.\n",
 304                       __func__, pci_name(pdev));
 305                ret = -ENODEV;
 306                goto out_idd;
 307        }
 308        idd->idd_pdev = pdev;
 309        idd->idd_pci_id = pci_id;
 310
 311        /* Map IOC4 misc registers.  These are shared between subdevices
 312         * so the main IOC4 module manages them.
 313         */
 314        idd->idd_bar0 = pci_resource_start(idd->idd_pdev, 0);
 315        if (!idd->idd_bar0) {
 316                printk(KERN_WARNING
 317                       "%s: Unable to find IOC4 misc resource "
 318                       "for pci_dev %s.\n",
 319                       __func__, pci_name(idd->idd_pdev));
 320                ret = -ENODEV;
 321                goto out_pci;
 322        }
 323        if (!request_mem_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs),
 324                            "ioc4_misc")) {
 325                printk(KERN_WARNING
 326                       "%s: Unable to request IOC4 misc region "
 327                       "for pci_dev %s.\n",
 328                       __func__, pci_name(idd->idd_pdev));
 329                ret = -ENODEV;
 330                goto out_pci;
 331        }
 332        idd->idd_misc_regs = ioremap(idd->idd_bar0,
 333                                     sizeof(struct ioc4_misc_regs));
 334        if (!idd->idd_misc_regs) {
 335                printk(KERN_WARNING
 336                       "%s: Unable to remap IOC4 misc region "
 337                       "for pci_dev %s.\n",
 338                       __func__, pci_name(idd->idd_pdev));
 339                ret = -ENODEV;
 340                goto out_misc_region;
 341        }
 342
 343        /* Failsafe portion of per-IOC4 initialization */
 344
 345        /* Detect card variant */
 346        idd->idd_variant = ioc4_variant(idd);
 347        printk(KERN_INFO "IOC4 %s: %s card detected.\n", pci_name(pdev),
 348               idd->idd_variant == IOC4_VARIANT_IO9 ? "IO9" :
 349               idd->idd_variant == IOC4_VARIANT_PCI_RT ? "PCI-RT" :
 350               idd->idd_variant == IOC4_VARIANT_IO10 ? "IO10" : "unknown");
 351
 352        /* Initialize IOC4 */
 353        pci_read_config_dword(idd->idd_pdev, PCI_COMMAND, &pcmd);
 354        pci_write_config_dword(idd->idd_pdev, PCI_COMMAND,
 355                               pcmd | PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
 356
 357        /* Determine PCI clock */
 358        ioc4_clock_calibrate(idd);
 359
 360        /* Disable/clear all interrupts.  Need to do this here lest
 361         * one submodule request the shared IOC4 IRQ, but interrupt
 362         * is generated by a different subdevice.
 363         */
 364        /* Disable */
 365        writel(~0, &idd->idd_misc_regs->other_iec.raw);
 366        writel(~0, &idd->idd_misc_regs->sio_iec);
 367        /* Clear (i.e. acknowledge) */
 368        writel(~0, &idd->idd_misc_regs->other_ir.raw);
 369        writel(~0, &idd->idd_misc_regs->sio_ir);
 370
 371        /* Track PCI-device specific data */
 372        idd->idd_serial_data = NULL;
 373        pci_set_drvdata(idd->idd_pdev, idd);
 374
 375        mutex_lock(&ioc4_mutex);
 376        list_add_tail(&idd->idd_list, &ioc4_devices);
 377
 378        /* Add this IOC4 to all submodules */
 379        list_for_each_entry(is, &ioc4_submodules, is_list) {
 380                if (is->is_probe && is->is_probe(idd)) {
 381                        printk(KERN_WARNING
 382                               "%s: IOC4 submodule 0x%s probe failed "
 383                               "for pci_dev %s.\n",
 384                               __func__, module_name(is->is_owner),
 385                               pci_name(idd->idd_pdev));
 386                }
 387        }
 388        mutex_unlock(&ioc4_mutex);
 389
 390        /* Request sgiioc4 IDE driver on boards that bring that functionality
 391         * off of IOC4.  The root filesystem may be hosted on a drive connected
 392         * to IOC4, so we need to make sure the sgiioc4 driver is loaded as it
 393         * won't be picked up by modprobes due to the ioc4 module owning the
 394         * PCI device.
 395         */
 396        if (idd->idd_variant != IOC4_VARIANT_PCI_RT) {
 397                /* Request the module from a work procedure as the modprobe
 398                 * goes out to a userland helper and that will hang if done
 399                 * directly from ioc4_probe().
 400                 */
 401                printk(KERN_INFO "IOC4 loading sgiioc4 submodule\n");
 402                schedule_work(&ioc4_load_modules_work);
 403        }
 404
 405        return 0;
 406
 407out_misc_region:
 408        release_mem_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs));
 409out_pci:
 410        kfree(idd);
 411out_idd:
 412        pci_disable_device(pdev);
 413out:
 414        return ret;
 415}
 416
 417/* Removes a particular instance of an IOC4 card. */
 418static void
 419ioc4_remove(struct pci_dev *pdev)
 420{
 421        struct ioc4_submodule *is;
 422        struct ioc4_driver_data *idd;
 423
 424        idd = pci_get_drvdata(pdev);
 425
 426        /* Remove this IOC4 from all submodules */
 427        mutex_lock(&ioc4_mutex);
 428        list_for_each_entry(is, &ioc4_submodules, is_list) {
 429                if (is->is_remove && is->is_remove(idd)) {
 430                        printk(KERN_WARNING
 431                               "%s: IOC4 submodule 0x%s remove failed "
 432                               "for pci_dev %s.\n",
 433                               __func__, module_name(is->is_owner),
 434                               pci_name(idd->idd_pdev));
 435                }
 436        }
 437        mutex_unlock(&ioc4_mutex);
 438
 439        /* Release resources */
 440        iounmap(idd->idd_misc_regs);
 441        if (!idd->idd_bar0) {
 442                printk(KERN_WARNING
 443                       "%s: Unable to get IOC4 misc mapping for pci_dev %s. "
 444                       "Device removal may be incomplete.\n",
 445                       __func__, pci_name(idd->idd_pdev));
 446        }
 447        release_mem_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs));
 448
 449        /* Disable IOC4 and relinquish */
 450        pci_disable_device(pdev);
 451
 452        /* Remove and free driver data */
 453        mutex_lock(&ioc4_mutex);
 454        list_del(&idd->idd_list);
 455        mutex_unlock(&ioc4_mutex);
 456        kfree(idd);
 457}
 458
 459static struct pci_device_id ioc4_id_table[] = {
 460        {PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC4, PCI_ANY_ID,
 461         PCI_ANY_ID, 0x0b4000, 0xFFFFFF},
 462        {0}
 463};
 464
 465static struct pci_driver ioc4_driver = {
 466        .name = "IOC4",
 467        .id_table = ioc4_id_table,
 468        .probe = ioc4_probe,
 469        .remove = ioc4_remove,
 470};
 471
 472MODULE_DEVICE_TABLE(pci, ioc4_id_table);
 473
 474/*********************
 475 * Module management *
 476 *********************/
 477
 478/* Module load */
 479static int __init
 480ioc4_init(void)
 481{
 482        return pci_register_driver(&ioc4_driver);
 483}
 484
 485/* Module unload */
 486static void __exit
 487ioc4_exit(void)
 488{
 489        /* Ensure ioc4_load_modules() has completed before exiting */
 490        flush_work(&ioc4_load_modules_work);
 491        pci_unregister_driver(&ioc4_driver);
 492}
 493
 494module_init(ioc4_init);
 495module_exit(ioc4_exit);
 496
 497MODULE_AUTHOR("Brent Casavant - Silicon Graphics, Inc. <bcasavan@sgi.com>");
 498MODULE_DESCRIPTION("PCI driver master module for SGI IOC4 Base-IO Card");
 499MODULE_LICENSE("GPL");
 500
 501EXPORT_SYMBOL(ioc4_register_submodule);
 502EXPORT_SYMBOL(ioc4_unregister_submodule);
 503