janz-cmodio.c revision 8102bad2c0c7492eedd86aeec97e99a866b64662
1bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder/* 2bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder * Janz CMOD-IO MODULbus Carrier Board PCI Driver 3bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder * 4bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder * Copyright (c) 2010 Ira W. Snyder <iws@ovro.caltech.edu> 5bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder * 6bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder * Lots of inspiration and code was copied from drivers/mfd/sm501.c 7bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder * 8bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder * This program is free software; you can redistribute it and/or modify it 9bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder * under the terms of the GNU General Public License as published by the 10bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder * Free Software Foundation; either version 2 of the License, or (at your 11bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder * option) any later version. 12bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder */ 13bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 14bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder#include <linux/kernel.h> 15bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder#include <linux/module.h> 16bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder#include <linux/init.h> 17bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder#include <linux/pci.h> 18bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder#include <linux/interrupt.h> 19bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder#include <linux/delay.h> 20bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder#include <linux/platform_device.h> 218102bad2c0c7492eedd86aeec97e99a866b64662David Miller#include <linux/slab.h> 22bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder#include <linux/mfd/core.h> 23bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 24bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder#include <linux/mfd/janz.h> 25bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 26bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder#define DRV_NAME "janz-cmodio" 27bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 28bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder/* Size of each MODULbus module in PCI BAR4 */ 29bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder#define CMODIO_MODULBUS_SIZE 0x200 30bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 31bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder/* Maximum number of MODULbus modules on a CMOD-IO carrier board */ 32bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder#define CMODIO_MAX_MODULES 4 33bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 34bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder/* Module Parameters */ 35bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyderstatic unsigned int num_modules = CMODIO_MAX_MODULES; 36bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyderstatic unsigned char *modules[CMODIO_MAX_MODULES] = { 37bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder "empty", "empty", "empty", "empty", 38bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder}; 39bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 40bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snydermodule_param_array(modules, charp, &num_modules, S_IRUGO); 41bd3581323cc02aefc79a21780a4ca8c578642892Ira W. SnyderMODULE_PARM_DESC(modules, "MODULbus modules attached to the carrier board"); 42bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 43bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder/* Unique Device Id */ 44bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyderstatic unsigned int cmodio_id; 45bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 46bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyderstruct cmodio_device { 47bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder /* Parent PCI device */ 48bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder struct pci_dev *pdev; 49bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 50bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder /* PLX control registers */ 51bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder struct janz_cmodio_onboard_regs __iomem *ctrl; 52bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 53bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder /* hex switch position */ 54bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder u8 hex; 55bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 56bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder /* mfd-core API */ 57bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder struct mfd_cell cells[CMODIO_MAX_MODULES]; 58bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder struct resource resources[3 * CMODIO_MAX_MODULES]; 59bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder struct janz_platform_data pdata[CMODIO_MAX_MODULES]; 60bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder}; 61bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 62bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder/* 63bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder * Subdevices using the mfd-core API 64bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder */ 65bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 66bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyderstatic int __devinit cmodio_setup_subdevice(struct cmodio_device *priv, 67bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder char *name, unsigned int devno, 68bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder unsigned int modno) 69bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder{ 70bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder struct janz_platform_data *pdata; 71bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder struct mfd_cell *cell; 72bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder struct resource *res; 73bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder struct pci_dev *pci; 74bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 75bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder pci = priv->pdev; 76bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder cell = &priv->cells[devno]; 77bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder res = &priv->resources[devno * 3]; 78bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder pdata = &priv->pdata[devno]; 79bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 80bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder cell->name = name; 81bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder cell->resources = res; 82bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder cell->num_resources = 3; 83bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 84bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder /* Setup the subdevice ID -- must be unique */ 85bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder cell->id = cmodio_id++; 86bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 87bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder /* Add platform data */ 88bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder pdata->modno = modno; 89bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder cell->platform_data = pdata; 90bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder cell->data_size = sizeof(*pdata); 91bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 92bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder /* MODULbus registers -- PCI BAR3 is big-endian MODULbus access */ 93bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder res->flags = IORESOURCE_MEM; 94bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder res->parent = &pci->resource[3]; 95bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder res->start = pci->resource[3].start + (CMODIO_MODULBUS_SIZE * modno); 96bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder res->end = res->start + CMODIO_MODULBUS_SIZE - 1; 97bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder res++; 98bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 99bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder /* PLX Control Registers -- PCI BAR4 is interrupt and other registers */ 100bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder res->flags = IORESOURCE_MEM; 101bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder res->parent = &pci->resource[4]; 102bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder res->start = pci->resource[4].start; 103bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder res->end = pci->resource[4].end; 104bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder res++; 105bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 106bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder /* 107bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder * IRQ 108bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder * 109bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder * The start and end fields are used as an offset to the irq_base 110bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder * parameter passed into the mfd_add_devices() function call. All 111bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder * devices share the same IRQ. 112bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder */ 113bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder res->flags = IORESOURCE_IRQ; 114bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder res->parent = NULL; 115bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder res->start = 0; 116bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder res->end = 0; 117bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder res++; 118bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 119bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder return 0; 120bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder} 121bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 122bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder/* Probe each submodule using kernel parameters */ 123bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyderstatic int __devinit cmodio_probe_submodules(struct cmodio_device *priv) 124bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder{ 125bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder struct pci_dev *pdev = priv->pdev; 126bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder unsigned int num_probed = 0; 127bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder char *name; 128bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder int i; 129bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 130bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder for (i = 0; i < num_modules; i++) { 131bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder name = modules[i]; 132bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder if (!strcmp(name, "") || !strcmp(name, "empty")) 133bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder continue; 134bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 135bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder dev_dbg(&priv->pdev->dev, "MODULbus %d: name %s\n", i, name); 136bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder cmodio_setup_subdevice(priv, name, num_probed, i); 137bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder num_probed++; 138bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder } 139bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 140bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder /* print an error message if no modules were probed */ 141bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder if (num_probed == 0) { 142bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder dev_err(&priv->pdev->dev, "no MODULbus modules specified, " 143bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder "please set the ``modules'' kernel " 144bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder "parameter according to your " 145bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder "hardware configuration\n"); 146bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder return -ENODEV; 147bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder } 148bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 149bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder return mfd_add_devices(&pdev->dev, 0, priv->cells, 150bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder num_probed, NULL, pdev->irq); 151bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder} 152bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 153bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder/* 154bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder * SYSFS Attributes 155bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder */ 156bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 157bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyderstatic ssize_t mbus_show(struct device *dev, struct device_attribute *attr, 158bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder char *buf) 159bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder{ 160bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder struct cmodio_device *priv = dev_get_drvdata(dev); 161bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 162bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder return snprintf(buf, PAGE_SIZE, "%x\n", priv->hex); 163bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder} 164bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 165bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyderstatic DEVICE_ATTR(modulbus_number, S_IRUGO, mbus_show, NULL); 166bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 167bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyderstatic struct attribute *cmodio_sysfs_attrs[] = { 168bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder &dev_attr_modulbus_number.attr, 169bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder NULL, 170bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder}; 171bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 172bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyderstatic const struct attribute_group cmodio_sysfs_attr_group = { 173bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder .attrs = cmodio_sysfs_attrs, 174bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder}; 175bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 176bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder/* 177bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder * PCI Driver 178bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder */ 179bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 180bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyderstatic int __devinit cmodio_pci_probe(struct pci_dev *dev, 181bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder const struct pci_device_id *id) 182bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder{ 183bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder struct cmodio_device *priv; 184bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder int ret; 185bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 186bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder priv = kzalloc(sizeof(*priv), GFP_KERNEL); 187bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder if (!priv) { 188bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder dev_err(&dev->dev, "unable to allocate private data\n"); 189bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder ret = -ENOMEM; 190bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder goto out_return; 191bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder } 192bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 193bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder pci_set_drvdata(dev, priv); 194bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder priv->pdev = dev; 195bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 196bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder /* Hardware Initialization */ 197bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder ret = pci_enable_device(dev); 198bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder if (ret) { 199bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder dev_err(&dev->dev, "unable to enable device\n"); 200bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder goto out_free_priv; 201bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder } 202bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 203bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder pci_set_master(dev); 204bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder ret = pci_request_regions(dev, DRV_NAME); 205bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder if (ret) { 206bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder dev_err(&dev->dev, "unable to request regions\n"); 207bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder goto out_pci_disable_device; 208bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder } 209bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 210bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder /* Onboard configuration registers */ 211bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder priv->ctrl = pci_ioremap_bar(dev, 4); 212bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder if (!priv->ctrl) { 213bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder dev_err(&dev->dev, "unable to remap onboard regs\n"); 214bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder ret = -ENOMEM; 215bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder goto out_pci_release_regions; 216bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder } 217bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 218bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder /* Read the hex switch on the carrier board */ 219bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder priv->hex = ioread8(&priv->ctrl->int_enable); 220bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 221bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder /* Add the MODULbus number (hex switch value) to the device's sysfs */ 222bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder ret = sysfs_create_group(&dev->dev.kobj, &cmodio_sysfs_attr_group); 223bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder if (ret) { 224bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder dev_err(&dev->dev, "unable to create sysfs attributes\n"); 225bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder goto out_unmap_ctrl; 226bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder } 227bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 228bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder /* 229bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder * Disable all interrupt lines, each submodule will enable its 230bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder * own interrupt line if needed 231bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder */ 232bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder iowrite8(0xf, &priv->ctrl->int_disable); 233bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 234bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder /* Register drivers for all submodules */ 235bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder ret = cmodio_probe_submodules(priv); 236bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder if (ret) { 237bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder dev_err(&dev->dev, "unable to probe submodules\n"); 238bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder goto out_sysfs_remove_group; 239bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder } 240bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 241bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder return 0; 242bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 243bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyderout_sysfs_remove_group: 244bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder sysfs_remove_group(&dev->dev.kobj, &cmodio_sysfs_attr_group); 245bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyderout_unmap_ctrl: 246bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder iounmap(priv->ctrl); 247bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyderout_pci_release_regions: 248bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder pci_release_regions(dev); 249bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyderout_pci_disable_device: 250bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder pci_disable_device(dev); 251bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyderout_free_priv: 252bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder kfree(priv); 253bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyderout_return: 254bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder return ret; 255bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder} 256bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 257bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyderstatic void __devexit cmodio_pci_remove(struct pci_dev *dev) 258bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder{ 259bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder struct cmodio_device *priv = pci_get_drvdata(dev); 260bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 261bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder mfd_remove_devices(&dev->dev); 262bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder sysfs_remove_group(&dev->dev.kobj, &cmodio_sysfs_attr_group); 263bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder iounmap(priv->ctrl); 264bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder pci_release_regions(dev); 265bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder pci_disable_device(dev); 266bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder kfree(priv); 267bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder} 268bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 269bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder#define PCI_VENDOR_ID_JANZ 0x13c3 270bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 271bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder/* The list of devices that this module will support */ 272bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyderstatic DEFINE_PCI_DEVICE_TABLE(cmodio_pci_ids) = { 273bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030, PCI_VENDOR_ID_JANZ, 0x0101 }, 274bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_JANZ, 0x0100 }, 275bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder { 0, } 276bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder}; 277bd3581323cc02aefc79a21780a4ca8c578642892Ira W. SnyderMODULE_DEVICE_TABLE(pci, cmodio_pci_ids); 278bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 279bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyderstatic struct pci_driver cmodio_pci_driver = { 280bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder .name = DRV_NAME, 281bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder .id_table = cmodio_pci_ids, 282bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder .probe = cmodio_pci_probe, 283bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder .remove = __devexit_p(cmodio_pci_remove), 284bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder}; 285bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 286bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder/* 287bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder * Module Init / Exit 288bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder */ 289bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 290bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyderstatic int __init cmodio_init(void) 291bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder{ 292bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder return pci_register_driver(&cmodio_pci_driver); 293bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder} 294bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 295bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyderstatic void __exit cmodio_exit(void) 296bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder{ 297bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder pci_unregister_driver(&cmodio_pci_driver); 298bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder} 299bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 300bd3581323cc02aefc79a21780a4ca8c578642892Ira W. SnyderMODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>"); 301bd3581323cc02aefc79a21780a4ca8c578642892Ira W. SnyderMODULE_DESCRIPTION("Janz CMOD-IO PCI MODULbus Carrier Board Driver"); 302bd3581323cc02aefc79a21780a4ca8c578642892Ira W. SnyderMODULE_LICENSE("GPL"); 303bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snyder 304bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snydermodule_init(cmodio_init); 305bd3581323cc02aefc79a21780a4ca8c578642892Ira W. Snydermodule_exit(cmodio_exit); 306