linux/drivers/uio/uio_netx.c
<<
>>
Prefs
   1/*
   2 * UIO driver for Hilscher NetX based fieldbus cards (cifX, comX).
   3 * See http://www.hilscher.com for details.
   4 *
   5 * (C) 2007 Hans J. Koch <hjk@hansjkoch.de>
   6 * (C) 2008 Manuel Traut <manut@linutronix.de>
   7 *
   8 * Licensed under GPL version 2 only.
   9 *
  10 */
  11
  12#include <linux/device.h>
  13#include <linux/io.h>
  14#include <linux/module.h>
  15#include <linux/pci.h>
  16#include <linux/slab.h>
  17#include <linux/uio_driver.h>
  18
  19#define PCI_VENDOR_ID_HILSCHER          0x15CF
  20#define PCI_DEVICE_ID_HILSCHER_NETX     0x0000
  21#define PCI_DEVICE_ID_HILSCHER_NETPLC   0x0010
  22#define PCI_SUBDEVICE_ID_NETPLC_RAM     0x0000
  23#define PCI_SUBDEVICE_ID_NETPLC_FLASH   0x0001
  24#define PCI_SUBDEVICE_ID_NXSB_PCA       0x3235
  25#define PCI_SUBDEVICE_ID_NXPCA          0x3335
  26
  27#define DPM_HOST_INT_EN0        0xfff0
  28#define DPM_HOST_INT_STAT0      0xffe0
  29
  30#define DPM_HOST_INT_MASK       0xe600ffff
  31#define DPM_HOST_INT_GLOBAL_EN  0x80000000
  32
  33static irqreturn_t netx_handler(int irq, struct uio_info *dev_info)
  34{
  35        void __iomem *int_enable_reg = dev_info->mem[0].internal_addr
  36                                        + DPM_HOST_INT_EN0;
  37        void __iomem *int_status_reg = dev_info->mem[0].internal_addr
  38                                        + DPM_HOST_INT_STAT0;
  39
  40        /* Is one of our interrupts enabled and active ? */
  41        if (!(ioread32(int_enable_reg) & ioread32(int_status_reg)
  42                & DPM_HOST_INT_MASK))
  43                return IRQ_NONE;
  44
  45        /* Disable interrupt */
  46        iowrite32(ioread32(int_enable_reg) & ~DPM_HOST_INT_GLOBAL_EN,
  47                int_enable_reg);
  48        return IRQ_HANDLED;
  49}
  50
  51static int netx_pci_probe(struct pci_dev *dev,
  52                                        const struct pci_device_id *id)
  53{
  54        struct uio_info *info;
  55        int bar;
  56
  57        info = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
  58        if (!info)
  59                return -ENOMEM;
  60
  61        if (pci_enable_device(dev))
  62                goto out_free;
  63
  64        if (pci_request_regions(dev, "netx"))
  65                goto out_disable;
  66
  67        switch (id->device) {
  68        case PCI_DEVICE_ID_HILSCHER_NETX:
  69                bar = 0;
  70                info->name = "netx";
  71                break;
  72        case PCI_DEVICE_ID_HILSCHER_NETPLC:
  73                bar = 0;
  74                info->name = "netplc";
  75                break;
  76        default:
  77                bar = 2;
  78                info->name = "netx_plx";
  79        }
  80
  81        /* BAR0 or 2 points to the card's dual port memory */
  82        info->mem[0].addr = pci_resource_start(dev, bar);
  83        if (!info->mem[0].addr)
  84                goto out_release;
  85        info->mem[0].internal_addr = ioremap(pci_resource_start(dev, bar),
  86                                                pci_resource_len(dev, bar));
  87
  88        if (!info->mem[0].internal_addr)
  89                        goto out_release;
  90
  91        info->mem[0].size = pci_resource_len(dev, bar);
  92        info->mem[0].memtype = UIO_MEM_PHYS;
  93        info->irq = dev->irq;
  94        info->irq_flags = IRQF_SHARED;
  95        info->handler = netx_handler;
  96        info->version = "0.0.1";
  97
  98        /* Make sure all interrupts are disabled */
  99        iowrite32(0, info->mem[0].internal_addr + DPM_HOST_INT_EN0);
 100
 101        if (uio_register_device(&dev->dev, info))
 102                goto out_unmap;
 103
 104        pci_set_drvdata(dev, info);
 105        dev_info(&dev->dev, "Found %s card, registered UIO device.\n",
 106                                info->name);
 107
 108        return 0;
 109
 110out_unmap:
 111        iounmap(info->mem[0].internal_addr);
 112out_release:
 113        pci_release_regions(dev);
 114out_disable:
 115        pci_disable_device(dev);
 116out_free:
 117        kfree(info);
 118        return -ENODEV;
 119}
 120
 121static void netx_pci_remove(struct pci_dev *dev)
 122{
 123        struct uio_info *info = pci_get_drvdata(dev);
 124
 125        /* Disable all interrupts */
 126        iowrite32(0, info->mem[0].internal_addr + DPM_HOST_INT_EN0);
 127        uio_unregister_device(info);
 128        pci_release_regions(dev);
 129        pci_disable_device(dev);
 130        pci_set_drvdata(dev, NULL);
 131        iounmap(info->mem[0].internal_addr);
 132
 133        kfree(info);
 134}
 135
 136static struct pci_device_id netx_pci_ids[] = {
 137        {
 138                .vendor =       PCI_VENDOR_ID_HILSCHER,
 139                .device =       PCI_DEVICE_ID_HILSCHER_NETX,
 140                .subvendor =    0,
 141                .subdevice =    0,
 142        },
 143        {
 144                .vendor =       PCI_VENDOR_ID_HILSCHER,
 145                .device =       PCI_DEVICE_ID_HILSCHER_NETPLC,
 146                .subvendor =    PCI_VENDOR_ID_HILSCHER,
 147                .subdevice =    PCI_SUBDEVICE_ID_NETPLC_RAM,
 148        },
 149        {
 150                .vendor =       PCI_VENDOR_ID_HILSCHER,
 151                .device =       PCI_DEVICE_ID_HILSCHER_NETPLC,
 152                .subvendor =    PCI_VENDOR_ID_HILSCHER,
 153                .subdevice =    PCI_SUBDEVICE_ID_NETPLC_FLASH,
 154        },
 155        {
 156                .vendor =       PCI_VENDOR_ID_PLX,
 157                .device =       PCI_DEVICE_ID_PLX_9030,
 158                .subvendor =    PCI_VENDOR_ID_PLX,
 159                .subdevice =    PCI_SUBDEVICE_ID_NXSB_PCA,
 160        },
 161        {
 162                .vendor =       PCI_VENDOR_ID_PLX,
 163                .device =       PCI_DEVICE_ID_PLX_9030,
 164                .subvendor =    PCI_VENDOR_ID_PLX,
 165                .subdevice =    PCI_SUBDEVICE_ID_NXPCA,
 166        },
 167        { 0, }
 168};
 169
 170static struct pci_driver netx_pci_driver = {
 171        .name = "netx",
 172        .id_table = netx_pci_ids,
 173        .probe = netx_pci_probe,
 174        .remove = netx_pci_remove,
 175};
 176
 177static int __init netx_init_module(void)
 178{
 179        return pci_register_driver(&netx_pci_driver);
 180}
 181
 182static void __exit netx_exit_module(void)
 183{
 184        pci_unregister_driver(&netx_pci_driver);
 185}
 186
 187module_init(netx_init_module);
 188module_exit(netx_exit_module);
 189
 190MODULE_DEVICE_TABLE(pci, netx_pci_ids);
 191MODULE_LICENSE("GPL v2");
 192MODULE_AUTHOR("Hans J. Koch, Manuel Traut");
 193
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.