Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[deliverable/linux.git] / drivers / usb / chipidea / ci_hdrc_pci.c
CommitLineData
409a15da 1/*
8e22978c 2 * ci_hdrc_pci.c - MIPS USB IP core family device controller
409a15da
PK
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
62bb84ed 13#include <linux/platform_device.h>
409a15da
PK
14#include <linux/module.h>
15#include <linux/pci.h>
62bb84ed
AS
16#include <linux/interrupt.h>
17#include <linux/usb/gadget.h>
e443b333 18#include <linux/usb/chipidea.h>
ba1aff67 19#include <linux/usb/usb_phy_generic.h>
409a15da
PK
20
21/* driver name */
8e22978c 22#define UDC_DRIVER_NAME "ci_hdrc_pci"
409a15da 23
ba1aff67
AS
24struct ci_hdrc_pci {
25 struct platform_device *ci;
26 struct platform_device *phy;
27};
28
409a15da
PK
29/******************************************************************************
30 * PCI block
31 *****************************************************************************/
8e22978c 32static struct ci_hdrc_platform_data pci_platdata = {
62bb84ed
AS
33 .name = UDC_DRIVER_NAME,
34 .capoffset = DEF_CAPOFFSET,
35};
409a15da 36
8e22978c 37static struct ci_hdrc_platform_data langwell_pci_platdata = {
f01ef574 38 .name = UDC_DRIVER_NAME,
62bb84ed 39 .capoffset = 0,
f01ef574
PK
40};
41
8e22978c 42static struct ci_hdrc_platform_data penwell_pci_platdata = {
bd841986
AS
43 .name = UDC_DRIVER_NAME,
44 .capoffset = 0,
45 .power_budget = 200,
46};
47
409a15da 48/**
8e22978c 49 * ci_hdrc_pci_probe: PCI probe
409a15da
PK
50 * @pdev: USB device controller being probed
51 * @id: PCI hotplug ID connecting controller to UDC framework
52 *
53 * This function returns an error code
54 * Allocates basic PCI resources for this USB device controller, and then
55 * invokes the udc_probe() method to start the UDC associated with it
56 */
8e22978c 57static int ci_hdrc_pci_probe(struct pci_dev *pdev,
409a15da
PK
58 const struct pci_device_id *id)
59{
8e22978c 60 struct ci_hdrc_platform_data *platdata = (void *)id->driver_data;
ba1aff67 61 struct ci_hdrc_pci *ci;
62bb84ed
AS
62 struct resource res[3];
63 int retval = 0, nres = 2;
409a15da 64
77c4400f 65 if (!platdata) {
1989b5ce
AS
66 dev_err(&pdev->dev, "device doesn't provide driver data\n");
67 return -ENODEV;
68 }
69
ba1aff67
AS
70 ci = devm_kzalloc(&pdev->dev, sizeof(*ci), GFP_KERNEL);
71 if (!ci)
72 return -ENOMEM;
73
8b2379b4 74 retval = pcim_enable_device(pdev);
409a15da 75 if (retval)
8b2379b4 76 return retval;
409a15da
PK
77
78 if (!pdev->irq) {
79 dev_err(&pdev->dev, "No IRQ, check BIOS/PCI setup!");
8b2379b4 80 return -ENODEV;
409a15da
PK
81 }
82
409a15da
PK
83 pci_set_master(pdev);
84 pci_try_set_mwi(pdev);
85
ba1aff67
AS
86 /* register a nop PHY */
87 ci->phy = usb_phy_generic_register();
8c0614ca
WY
88 if (IS_ERR(ci->phy))
89 return PTR_ERR(ci->phy);
ba1aff67 90
62bb84ed
AS
91 memset(res, 0, sizeof(res));
92 res[0].start = pci_resource_start(pdev, 0);
93 res[0].end = pci_resource_end(pdev, 0);
94 res[0].flags = IORESOURCE_MEM;
95 res[1].start = pdev->irq;
96 res[1].flags = IORESOURCE_IRQ;
97
ba1aff67
AS
98 ci->ci = ci_hdrc_add_device(&pdev->dev, res, nres, platdata);
99 if (IS_ERR(ci->ci)) {
8e22978c 100 dev_err(&pdev->dev, "ci_hdrc_add_device failed!\n");
ba1aff67
AS
101 usb_phy_generic_unregister(ci->phy);
102 return PTR_ERR(ci->ci);
62bb84ed
AS
103 }
104
ba1aff67 105 pci_set_drvdata(pdev, ci);
62bb84ed 106
409a15da 107 return 0;
409a15da
PK
108}
109
110/**
8e22978c 111 * ci_hdrc_pci_remove: PCI remove
409a15da
PK
112 * @pdev: USB Device Controller being removed
113 *
8e22978c 114 * Reverses the effect of ci_hdrc_pci_probe(),
409a15da
PK
115 * first invoking the udc_remove() and then releases
116 * all PCI resources allocated for this USB device controller
117 */
8e22978c 118static void ci_hdrc_pci_remove(struct pci_dev *pdev)
409a15da 119{
ba1aff67 120 struct ci_hdrc_pci *ci = pci_get_drvdata(pdev);
62bb84ed 121
ba1aff67
AS
122 ci_hdrc_remove_device(ci->ci);
123 usb_phy_generic_unregister(ci->phy);
409a15da
PK
124}
125
126/**
127 * PCI device table
128 * PCI device structure
129 *
130 * Check "pci.h" for details
518ca8d9
AS
131 *
132 * Note: ehci-pci driver may try to probe the device first. You have to add an
133 * ID to the bypass_pci_id_table in ehci-pci driver to prevent this.
409a15da 134 */
4e065b8b 135static const struct pci_device_id ci_hdrc_pci_id_table[] = {
62bb84ed
AS
136 {
137 PCI_DEVICE(0x153F, 0x1004),
77c4400f 138 .driver_data = (kernel_ulong_t)&pci_platdata,
62bb84ed
AS
139 },
140 {
141 PCI_DEVICE(0x153F, 0x1006),
77c4400f 142 .driver_data = (kernel_ulong_t)&pci_platdata,
62bb84ed
AS
143 },
144 {
46b95a1d 145 PCI_VDEVICE(INTEL, 0x0811),
77c4400f 146 .driver_data = (kernel_ulong_t)&langwell_pci_platdata,
62bb84ed
AS
147 },
148 {
46b95a1d 149 PCI_VDEVICE(INTEL, 0x0829),
77c4400f 150 .driver_data = (kernel_ulong_t)&penwell_pci_platdata,
62bb84ed 151 },
a214339d
DC
152 {
153 /* Intel Clovertrail */
46b95a1d 154 PCI_VDEVICE(INTEL, 0xe006),
a214339d
DC
155 .driver_data = (kernel_ulong_t)&penwell_pci_platdata,
156 },
157 { 0 } /* end: all zeroes */
409a15da 158};
8e22978c 159MODULE_DEVICE_TABLE(pci, ci_hdrc_pci_id_table);
409a15da 160
8e22978c 161static struct pci_driver ci_hdrc_pci_driver = {
409a15da 162 .name = UDC_DRIVER_NAME,
8e22978c
AS
163 .id_table = ci_hdrc_pci_id_table,
164 .probe = ci_hdrc_pci_probe,
165 .remove = ci_hdrc_pci_remove,
409a15da
PK
166};
167
8e22978c 168module_pci_driver(ci_hdrc_pci_driver);
409a15da
PK
169
170MODULE_AUTHOR("MIPS - David Lopo <dlopo@chipidea.mips.com>");
171MODULE_DESCRIPTION("MIPS CI13XXX USB Peripheral Controller");
172MODULE_LICENSE("GPL");
173MODULE_VERSION("June 2008");
8e22978c 174MODULE_ALIAS("platform:ci13xxx_pci");
This page took 0.327881 seconds and 5 git commands to generate.