f075ef33834f8708b799bdeb93e43586c75139f5
[pandora-kernel.git] / drivers / usb / chipidea / 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/platform_device.h>
14 #include <linux/module.h>
15 #include <linux/pci.h>
16 #include <linux/interrupt.h>
17 #include <linux/usb/gadget.h>
18
19 #include "ci13xxx_udc.h"
20
21 /* driver name */
22 #define UDC_DRIVER_NAME   "ci13xxx_pci"
23
24 /******************************************************************************
25  * PCI block
26  *****************************************************************************/
27 struct ci13xxx_udc_driver pci_driver = {
28         .name           = UDC_DRIVER_NAME,
29         .capoffset      = DEF_CAPOFFSET,
30 };
31
32 struct ci13xxx_udc_driver langwell_pci_driver = {
33         .name           = UDC_DRIVER_NAME,
34         .capoffset      = 0,
35 };
36
37 /**
38  * ci13xxx_pci_probe: PCI probe
39  * @pdev: USB device controller being probed
40  * @id:   PCI hotplug ID connecting controller to UDC framework
41  *
42  * This function returns an error code
43  * Allocates basic PCI resources for this USB device controller, and then
44  * invokes the udc_probe() method to start the UDC associated with it
45  */
46 static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev,
47                                        const struct pci_device_id *id)
48 {
49         struct ci13xxx_udc_driver *driver = (void *)id->driver_data;
50         struct platform_device *plat_ci;
51         struct resource res[3];
52         int retval = 0, nres = 2;
53
54         if (!driver) {
55                 dev_err(&pdev->dev, "device doesn't provide driver data\n");
56                 return -ENODEV;
57         }
58
59         retval = pci_enable_device(pdev);
60         if (retval)
61                 goto done;
62
63         if (!pdev->irq) {
64                 dev_err(&pdev->dev, "No IRQ, check BIOS/PCI setup!");
65                 retval = -ENODEV;
66                 goto disable_device;
67         }
68
69         pci_set_power_state(pdev, PCI_D0);
70         pci_set_master(pdev);
71         pci_try_set_mwi(pdev);
72
73         plat_ci = platform_device_alloc("ci_udc", -1);
74         if (!plat_ci) {
75                 dev_err(&pdev->dev, "can't allocate ci_udc platform device\n");
76                 retval = -ENOMEM;
77                 goto disable_device;
78         }
79
80         memset(res, 0, sizeof(res));
81         res[0].start    = pci_resource_start(pdev, 0);
82         res[0].end      = pci_resource_end(pdev, 0);
83         res[0].flags    = IORESOURCE_MEM;
84         res[1].start    = pdev->irq;
85         res[1].flags    = IORESOURCE_IRQ;
86
87         retval = platform_device_add_resources(plat_ci, res, nres);
88         if (retval) {
89                 dev_err(&pdev->dev, "can't add resources to platform device\n");
90                 goto put_platform;
91         }
92
93         retval = platform_device_add_data(plat_ci, driver, sizeof(*driver));
94         if (retval)
95                 goto put_platform;
96
97         dma_set_coherent_mask(&plat_ci->dev, pdev->dev.coherent_dma_mask);
98         plat_ci->dev.dma_mask = pdev->dev.dma_mask;
99         plat_ci->dev.dma_parms = pdev->dev.dma_parms;
100         plat_ci->dev.parent = &pdev->dev;
101
102         pci_set_drvdata(pdev, plat_ci);
103
104         retval = platform_device_add(plat_ci);
105         if (retval)
106                 goto put_platform;
107
108         return 0;
109
110  put_platform:
111         pci_set_drvdata(pdev, NULL);
112         platform_device_put(plat_ci);
113  disable_device:
114         pci_disable_device(pdev);
115  done:
116         return retval;
117 }
118
119 /**
120  * ci13xxx_pci_remove: PCI remove
121  * @pdev: USB Device Controller being removed
122  *
123  * Reverses the effect of ci13xxx_pci_probe(),
124  * first invoking the udc_remove() and then releases
125  * all PCI resources allocated for this USB device controller
126  */
127 static void __devexit ci13xxx_pci_remove(struct pci_dev *pdev)
128 {
129         struct platform_device *plat_ci = pci_get_drvdata(pdev);
130
131         platform_device_unregister(plat_ci);
132         pci_set_drvdata(pdev, NULL);
133         pci_disable_device(pdev);
134 }
135
136 /**
137  * PCI device table
138  * PCI device structure
139  *
140  * Check "pci.h" for details
141  */
142 static DEFINE_PCI_DEVICE_TABLE(ci13xxx_pci_id_table) = {
143         {
144                 PCI_DEVICE(0x153F, 0x1004),
145                 .driver_data = (kernel_ulong_t)&pci_driver,
146         },
147         {
148                 PCI_DEVICE(0x153F, 0x1006),
149                 .driver_data = (kernel_ulong_t)&pci_driver,
150         },
151         {
152                 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0811),
153                 .driver_data = (kernel_ulong_t)&langwell_pci_driver,
154         },
155         {
156                 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0829),
157                 .driver_data = (kernel_ulong_t)&langwell_pci_driver,
158         },
159         { 0, 0, 0, 0, 0, 0, 0 /* end: all zeroes */ }
160 };
161 MODULE_DEVICE_TABLE(pci, ci13xxx_pci_id_table);
162
163 static struct pci_driver ci13xxx_pci_driver = {
164         .name         = UDC_DRIVER_NAME,
165         .id_table     = ci13xxx_pci_id_table,
166         .probe        = ci13xxx_pci_probe,
167         .remove       = __devexit_p(ci13xxx_pci_remove),
168 };
169
170 module_pci_driver(ci13xxx_pci_driver);
171
172 MODULE_AUTHOR("MIPS - David Lopo <dlopo@chipidea.mips.com>");
173 MODULE_DESCRIPTION("MIPS CI13XXX USB Peripheral Controller");
174 MODULE_LICENSE("GPL");
175 MODULE_VERSION("June 2008");