USB: ftdi_sio: add Basic Micro ATOM Nano USB2Serial PID
[pandora-kernel.git] / drivers / usb / gadget / ci13xxx_pci.c
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  */
32 static 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
41 static 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  */
54 static 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  */
122 static 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  */
137 static 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 };
142 MODULE_DEVICE_TABLE(pci, ci13xxx_pci_id_table);
143
144 static 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  */
156 static int __init ci13xxx_pci_init(void)
157 {
158         return pci_register_driver(&ci13xxx_pci_driver);
159 }
160 module_init(ci13xxx_pci_init);
161
162 /**
163  * ci13xxx_pci_exit: module exit
164  *
165  * Driver unload
166  */
167 static void __exit ci13xxx_pci_exit(void)
168 {
169         pci_unregister_driver(&ci13xxx_pci_driver);
170 }
171 module_exit(ci13xxx_pci_exit);
172
173 MODULE_AUTHOR("MIPS - David Lopo <dlopo@chipidea.mips.com>");
174 MODULE_DESCRIPTION("MIPS CI13XXX USB Peripheral Controller");
175 MODULE_LICENSE("GPL");
176 MODULE_VERSION("June 2008");