aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Youn <John.Youn@synopsys.com>2015-03-03 20:17:49 -0500
committerFelipe Balbi <balbi@ti.com>2015-03-11 16:08:17 -0400
commit9024c495f35be735a917571406fab30a789c27d1 (patch)
treea4d16aa96cb6f763689601bb6d0286f96b67dca0
parent005a64307d5d3ef895e7821df4cad7739bab392e (diff)
usb: dwc2: pci: Add device mode to the dwc2-pci driver
The pci driver now registers a platform driver, like in dwc3, and lets its probe function do all the initialization. This allows it to account for changes to the platform driver that were not added to the pci driver. Also future changes to the probe function don't have to be duplicated. This also has the effect of adding device and DRD mode to the pci driver. Tested on the Synopsys HAPS PCIe platform. Signed-off-by: John Youn <johnyoun@synopsys.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
-rw-r--r--drivers/usb/dwc2/Kconfig7
-rw-r--r--drivers/usb/dwc2/pci.c159
2 files changed, 76 insertions, 90 deletions
diff --git a/drivers/usb/dwc2/Kconfig b/drivers/usb/dwc2/Kconfig
index 76b9ba4dc925..3db204f21ff9 100644
--- a/drivers/usb/dwc2/Kconfig
+++ b/drivers/usb/dwc2/Kconfig
@@ -59,11 +59,12 @@ config USB_DWC2_PLATFORM
59 59
60config USB_DWC2_PCI 60config USB_DWC2_PCI
61 tristate "DWC2 PCI" 61 tristate "DWC2 PCI"
62 depends on USB_DWC2_HOST && PCI 62 depends on PCI
63 default USB_DWC2_HOST 63 default n
64 select USB_DWC2_PLATFORM
64 help 65 help
65 The Designware USB2.0 PCI interface module for controllers 66 The Designware USB2.0 PCI interface module for controllers
66 connected to a PCI bus. This is only used for host mode. 67 connected to a PCI bus.
67 68
68config USB_DWC2_DEBUG 69config USB_DWC2_DEBUG
69 bool "Enable Debugging Messages" 70 bool "Enable Debugging Messages"
diff --git a/drivers/usb/dwc2/pci.c b/drivers/usb/dwc2/pci.c
index 6646adb1fb17..ae419615a176 100644
--- a/drivers/usb/dwc2/pci.c
+++ b/drivers/usb/dwc2/pci.c
@@ -50,112 +50,97 @@
50 50
51#include <linux/usb/hcd.h> 51#include <linux/usb/hcd.h>
52#include <linux/usb/ch11.h> 52#include <linux/usb/ch11.h>
53 53#include <linux/platform_device.h>
54#include "core.h" 54#include <linux/usb/usb_phy_generic.h>
55#include "hcd.h"
56 55
57#define PCI_PRODUCT_ID_HAPS_HSOTG 0xabc0 56#define PCI_PRODUCT_ID_HAPS_HSOTG 0xabc0
58 57
59static const char dwc2_driver_name[] = "dwc2"; 58static const char dwc2_driver_name[] = "dwc2-pci";
60 59
61static const struct dwc2_core_params dwc2_module_params = { 60struct dwc2_pci_glue {
62 .otg_cap = -1, 61 struct platform_device *dwc2;
63 .otg_ver = -1, 62 struct platform_device *phy;
64 .dma_enable = -1,
65 .dma_desc_enable = 0,
66 .speed = -1,
67 .enable_dynamic_fifo = -1,
68 .en_multiple_tx_fifo = -1,
69 .host_rx_fifo_size = 1024,
70 .host_nperio_tx_fifo_size = 256,
71 .host_perio_tx_fifo_size = 1024,
72 .max_transfer_size = 65535,
73 .max_packet_count = 511,
74 .host_channels = -1,
75 .phy_type = -1,
76 .phy_utmi_width = -1,
77 .phy_ulpi_ddr = -1,
78 .phy_ulpi_ext_vbus = -1,
79 .i2c_enable = -1,
80 .ulpi_fs_ls = -1,
81 .host_support_fs_ls_low_power = -1,
82 .host_ls_low_power_phy_clk = -1,
83 .ts_dline = -1,
84 .reload_ctl = -1,
85 .ahbcfg = -1,
86 .uframe_sched = -1,
87}; 63};
88 64
89/** 65static void dwc2_pci_remove(struct pci_dev *pci)
90 * dwc2_driver_remove() - Called when the DWC_otg core is unregistered with the
91 * DWC_otg driver
92 *
93 * @dev: Bus device
94 *
95 * This routine is called, for example, when the rmmod command is executed. The
96 * device may or may not be electrically present. If it is present, the driver
97 * stops device processing. Any resources used on behalf of this device are
98 * freed.
99 */
100static void dwc2_driver_remove(struct pci_dev *dev)
101{ 66{
102 struct dwc2_hsotg *hsotg = pci_get_drvdata(dev); 67 struct dwc2_pci_glue *glue = pci_get_drvdata(pci);
103 68
104 dwc2_hcd_remove(hsotg); 69 platform_device_unregister(glue->dwc2);
105 pci_disable_device(dev); 70 usb_phy_generic_unregister(glue->phy);
71 kfree(glue);
72 pci_set_drvdata(pci, NULL);
106} 73}
107 74
108/** 75static int dwc2_pci_probe(struct pci_dev *pci,
109 * dwc2_driver_probe() - Called when the DWC_otg core is bound to the DWC_otg 76 const struct pci_device_id *id)
110 * driver
111 *
112 * @dev: Bus device
113 *
114 * This routine creates the driver components required to control the device
115 * (core, HCD, and PCD) and initializes the device. The driver components are
116 * stored in a dwc2_hsotg structure. A reference to the dwc2_hsotg is saved
117 * in the device private data. This allows the driver to access the dwc2_hsotg
118 * structure on subsequent calls to driver methods for this device.
119 */
120static int dwc2_driver_probe(struct pci_dev *dev,
121 const struct pci_device_id *id)
122{ 77{
123 struct dwc2_hsotg *hsotg; 78 struct resource res[2];
124 int retval; 79 struct platform_device *dwc2;
80 struct platform_device *phy;
81 int ret;
82 struct device *dev = &pci->dev;
83 struct dwc2_pci_glue *glue;
84
85 ret = pcim_enable_device(pci);
86 if (ret) {
87 dev_err(dev, "failed to enable pci device\n");
88 return -ENODEV;
89 }
90
91 pci_set_master(pci);
125 92
126 hsotg = devm_kzalloc(&dev->dev, sizeof(*hsotg), GFP_KERNEL); 93 dwc2 = platform_device_alloc("dwc2", PLATFORM_DEVID_AUTO);
127 if (!hsotg) 94 if (!dwc2) {
95 dev_err(dev, "couldn't allocate dwc2 device\n");
128 return -ENOMEM; 96 return -ENOMEM;
97 }
129 98
130 hsotg->dev = &dev->dev; 99 memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res));
131 hsotg->regs = devm_ioremap_resource(&dev->dev, &dev->resource[0]);
132 if (IS_ERR(hsotg->regs))
133 return PTR_ERR(hsotg->regs);
134 100
135 dev_dbg(&dev->dev, "mapped PA %08lx to VA %p\n", 101 res[0].start = pci_resource_start(pci, 0);
136 (unsigned long)pci_resource_start(dev, 0), hsotg->regs); 102 res[0].end = pci_resource_end(pci, 0);
103 res[0].name = "dwc2";
104 res[0].flags = IORESOURCE_MEM;
137 105
138 if (pci_enable_device(dev) < 0) 106 res[1].start = pci->irq;
139 return -ENODEV; 107 res[1].name = "dwc2";
108 res[1].flags = IORESOURCE_IRQ;
140 109
141 pci_set_master(dev); 110 ret = platform_device_add_resources(dwc2, res, ARRAY_SIZE(res));
111 if (ret) {
112 dev_err(dev, "couldn't add resources to dwc2 device\n");
113 return ret;
114 }
142 115
143 retval = devm_request_irq(hsotg->dev, dev->irq, 116 dwc2->dev.parent = dev;
144 dwc2_handle_common_intr, IRQF_SHARED,
145 dev_name(hsotg->dev), hsotg);
146 if (retval)
147 return retval;
148 117
149 spin_lock_init(&hsotg->lock); 118 phy = usb_phy_generic_register();
150 retval = dwc2_hcd_init(hsotg, dev->irq, &dwc2_module_params); 119 if (IS_ERR(phy)) {
151 if (retval) { 120 dev_err(dev, "error registering generic PHY (%ld)\n",
152 pci_disable_device(dev); 121 PTR_ERR(phy));
153 return retval; 122 return PTR_ERR(phy);
154 } 123 }
155 124
156 pci_set_drvdata(dev, hsotg); 125 ret = platform_device_add(dwc2);
126 if (ret) {
127 dev_err(dev, "failed to register dwc2 device\n");
128 goto err;
129 }
130
131 glue = kzalloc(sizeof(*glue), GFP_KERNEL);
132 if (!glue)
133 return -ENOMEM;
134
135 glue->phy = phy;
136 glue->dwc2 = dwc2;
137 pci_set_drvdata(pci, glue);
157 138
158 return retval; 139 return 0;
140err:
141 usb_phy_generic_unregister(phy);
142 platform_device_put(dwc2);
143 return ret;
159} 144}
160 145
161static const struct pci_device_id dwc2_pci_ids[] = { 146static const struct pci_device_id dwc2_pci_ids[] = {
@@ -173,8 +158,8 @@ MODULE_DEVICE_TABLE(pci, dwc2_pci_ids);
173static struct pci_driver dwc2_pci_driver = { 158static struct pci_driver dwc2_pci_driver = {
174 .name = dwc2_driver_name, 159 .name = dwc2_driver_name,
175 .id_table = dwc2_pci_ids, 160 .id_table = dwc2_pci_ids,
176 .probe = dwc2_driver_probe, 161 .probe = dwc2_pci_probe,
177 .remove = dwc2_driver_remove, 162 .remove = dwc2_pci_remove,
178}; 163};
179 164
180module_pci_driver(dwc2_pci_driver); 165module_pci_driver(dwc2_pci_driver);