blob: 7a0f153e33c04841684479a9aab065f36ad3921a [file] [log] [blame]
Pavankumar Kondeti409a15d2010-12-07 17:53:59 +05301/*
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
41/**
42 * ci13xxx_pci_probe: PCI probe
43 * @pdev: USB device controller being probed
44 * @id: PCI hotplug ID connecting controller to UDC framework
45 *
46 * This function returns an error code
47 * Allocates basic PCI resources for this USB device controller, and then
48 * invokes the udc_probe() method to start the UDC associated with it
49 */
50static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev,
51 const struct pci_device_id *id)
52{
53 void __iomem *regs = NULL;
54 int retval = 0;
55
56 if (id == NULL)
57 return -EINVAL;
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 retval = pci_request_regions(pdev, UDC_DRIVER_NAME);
70 if (retval)
71 goto disable_device;
72
73 /* BAR 0 holds all the registers */
74 regs = pci_iomap(pdev, 0, 0);
75 if (!regs) {
76 dev_err(&pdev->dev, "Error mapping memory!");
77 retval = -EFAULT;
78 goto release_regions;
79 }
80 pci_set_drvdata(pdev, (__force void *)regs);
81
82 pci_set_master(pdev);
83 pci_try_set_mwi(pdev);
84
85 retval = udc_probe(&pdev->dev, regs, UDC_DRIVER_NAME);
86 if (retval)
87 goto iounmap;
88
89 /* our device does not have MSI capability */
90
91 retval = request_irq(pdev->irq, ci13xxx_pci_irq, IRQF_SHARED,
92 UDC_DRIVER_NAME, pdev);
93 if (retval)
94 goto gadget_remove;
95
96 return 0;
97
98 gadget_remove:
99 udc_remove();
100 iounmap:
101 pci_iounmap(pdev, regs);
102 release_regions:
103 pci_release_regions(pdev);
104 disable_device:
105 pci_disable_device(pdev);
106 done:
107 return retval;
108}
109
110/**
111 * ci13xxx_pci_remove: PCI remove
112 * @pdev: USB Device Controller being removed
113 *
114 * Reverses the effect of ci13xxx_pci_probe(),
115 * first invoking the udc_remove() and then releases
116 * all PCI resources allocated for this USB device controller
117 */
118static void __devexit ci13xxx_pci_remove(struct pci_dev *pdev)
119{
120 free_irq(pdev->irq, pdev);
121 udc_remove();
122 pci_iounmap(pdev, (__force void __iomem *)pci_get_drvdata(pdev));
123 pci_release_regions(pdev);
124 pci_disable_device(pdev);
125}
126
127/**
128 * PCI device table
129 * PCI device structure
130 *
131 * Check "pci.h" for details
132 */
133static DEFINE_PCI_DEVICE_TABLE(ci13xxx_pci_id_table) = {
134 { PCI_DEVICE(0x153F, 0x1004) },
135 { PCI_DEVICE(0x153F, 0x1006) },
136 { 0, 0, 0, 0, 0, 0, 0 /* end: all zeroes */ }
137};
138MODULE_DEVICE_TABLE(pci, ci13xxx_pci_id_table);
139
140static struct pci_driver ci13xxx_pci_driver = {
141 .name = UDC_DRIVER_NAME,
142 .id_table = ci13xxx_pci_id_table,
143 .probe = ci13xxx_pci_probe,
144 .remove = __devexit_p(ci13xxx_pci_remove),
145};
146
147/**
148 * ci13xxx_pci_init: module init
149 *
150 * Driver load
151 */
152static int __init ci13xxx_pci_init(void)
153{
154 return pci_register_driver(&ci13xxx_pci_driver);
155}
156module_init(ci13xxx_pci_init);
157
158/**
159 * ci13xxx_pci_exit: module exit
160 *
161 * Driver unload
162 */
163static void __exit ci13xxx_pci_exit(void)
164{
165 pci_unregister_driver(&ci13xxx_pci_driver);
166}
167module_exit(ci13xxx_pci_exit);
168
169MODULE_AUTHOR("MIPS - David Lopo <dlopo@chipidea.mips.com>");
170MODULE_DESCRIPTION("MIPS CI13XXX USB Peripheral Controller");
171MODULE_LICENSE("GPL");
172MODULE_VERSION("June 2008");