linux/drivers/usb/gadget/ci13xxx_pci.c
<<
>>
Prefs
   1/*
   2 * ci13xxx_pci.c - MIPS USB IP core family device controller
   3 *
   4 * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved.
   5 *
   6 * Author: David Lopo
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License version 2 as
  10 * published by the Free Software Foundation.
  11 */
  12
  13#include <linux/module.h>
  14#include <linux/pci.h>
  15
  16#include "ci13xxx_udc.c"
  17
  18/* driver name */
  19#define UDC_DRIVER_NAME   "ci13xxx_pci"
  20
  21/******************************************************************************
  22 * PCI block
  23 *****************************************************************************/
  24/**
  25 * ci13xxx_pci_irq: interrut handler
  26 * @irq:  irq number
  27 * @pdev: USB Device Controller interrupt source
  28 *
  29 * This function returns IRQ_HANDLED if the IRQ has been handled
  30 * This is an ISR don't trace, use attribute interface instead
  31 */
  32static irqreturn_t ci13xxx_pci_irq(int irq, void *pdev)
  33{
  34        if (irq == 0) {
  35                dev_err(&((struct pci_dev *)pdev)->dev, "Invalid IRQ0 usage!");
  36                return IRQ_HANDLED;
  37        }
  38        return udc_irq();
  39}
  40
  41static struct ci13xxx_udc_driver ci13xxx_pci_udc_driver = {
  42        .name           = UDC_DRIVER_NAME,
  43};
  44
  45/**
  46 * ci13xxx_pci_probe: PCI probe
  47 * @pdev: USB device controller being probed
  48 * @id:   PCI hotplug ID connecting controller to UDC framework
  49 *
  50 * This function returns an error code
  51 * Allocates basic PCI resources for this USB device controller, and then
  52 * invokes the udc_probe() method to start the UDC associated with it
  53 */
  54static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev,
  55                                       const struct pci_device_id *id)
  56{
  57        void __iomem *regs = NULL;
  58        int retval = 0;
  59
  60        if (id == NULL)
  61                return -EINVAL;
  62
  63        retval = pci_enable_device(pdev);
  64        if (retval)
  65                goto done;
  66
  67        if (!pdev->irq) {
  68                dev_err(&pdev->dev, "No IRQ, check BIOS/PCI setup!");
  69                retval = -ENODEV;
  70                goto disable_device;
  71        }
  72
  73        retval = pci_request_regions(pdev, UDC_DRIVER_NAME);
  74        if (retval)
  75                goto disable_device;
  76
  77        /* BAR 0 holds all the registers */
  78        regs = pci_iomap(pdev, 0, 0);
  79        if (!regs) {
  80                dev_err(&pdev->dev, "Error mapping memory!");
  81                retval = -EFAULT;
  82                goto release_regions;
  83        }
  84        pci_set_drvdata(pdev, (__force void *)regs);
  85
  86        pci_set_master(pdev);
  87        pci_try_set_mwi(pdev);
  88
  89        retval = udc_probe(&ci13xxx_pci_udc_driver, &pdev->dev, regs);
  90        if (retval)
  91                goto iounmap;
  92
  93        /* our device does not have MSI capability */
  94
  95        retval = request_irq(pdev->irq, ci13xxx_pci_irq, IRQF_SHARED,
  96                             UDC_DRIVER_NAME, pdev);
  97        if (retval)
  98                goto gadget_remove;
  99
 100        return 0;
 101
 102 gadget_remove:
 103        udc_remove();
 104 iounmap:
 105        pci_iounmap(pdev, regs);
 106 release_regions:
 107        pci_release_regions(pdev);
 108 disable_device:
 109        pci_disable_device(pdev);
 110 done:
 111        return retval;
 112}
 113
 114/**
 115 * ci13xxx_pci_remove: PCI remove
 116 * @pdev: USB Device Controller being removed
 117 *
 118 * Reverses the effect of ci13xxx_pci_probe(),
 119 * first invoking the udc_remove() and then releases
 120 * all PCI resources allocated for this USB device controller
 121 */
 122static void __devexit ci13xxx_pci_remove(struct pci_dev *pdev)
 123{
 124        free_irq(pdev->irq, pdev);
 125        udc_remove();
 126        pci_iounmap(pdev, (__force void __iomem *)pci_get_drvdata(pdev));
 127        pci_release_regions(pdev);
 128        pci_disable_device(pdev);
 129}
 130
 131/**
 132 * PCI device table
 133 * PCI device structure
 134 *
 135 * Check "pci.h" for details
 136 */
 137static DEFINE_PCI_DEVICE_TABLE(ci13xxx_pci_id_table) = {
 138        { PCI_DEVICE(0x153F, 0x1004) },
 139        { PCI_DEVICE(0x153F, 0x1006) },
 140        { 0, 0, 0, 0, 0, 0, 0 /* end: all zeroes */ }
 141};
 142MODULE_DEVICE_TABLE(pci, ci13xxx_pci_id_table);
 143
 144static struct pci_driver ci13xxx_pci_driver = {
 145        .name         = UDC_DRIVER_NAME,
 146        .id_table     = ci13xxx_pci_id_table,
 147        .probe        = ci13xxx_pci_probe,
 148        .remove       = __devexit_p(ci13xxx_pci_remove),
 149};
 150
 151/**
 152 * ci13xxx_pci_init: module init
 153 *
 154 * Driver load
 155 */
 156static int __init ci13xxx_pci_init(void)
 157{
 158        return pci_register_driver(&ci13xxx_pci_driver);
 159}
 160module_init(ci13xxx_pci_init);
 161
 162/**
 163 * ci13xxx_pci_exit: module exit
 164 *
 165 * Driver unload
 166 */
 167static void __exit ci13xxx_pci_exit(void)
 168{
 169        pci_unregister_driver(&ci13xxx_pci_driver);
 170}
 171module_exit(ci13xxx_pci_exit);
 172
 173MODULE_AUTHOR("MIPS - David Lopo <dlopo@chipidea.mips.com>");
 174MODULE_DESCRIPTION("MIPS CI13XXX USB Peripheral Controller");
 175MODULE_LICENSE("GPL");
 176MODULE_VERSION("June 2008");
 177