Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dwc3-pci.c
Go to the documentation of this file.
1 
39 #include <linux/kernel.h>
40 #include <linux/module.h>
41 #include <linux/slab.h>
42 #include <linux/pci.h>
43 #include <linux/platform_device.h>
44 
45 #include <linux/usb/otg.h>
47 
48 #include "core.h"
49 
50 /* FIXME define these in <linux/pci_ids.h> */
51 #define PCI_VENDOR_ID_SYNOPSYS 0x16c3
52 #define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3 0xabcd
53 
54 struct dwc3_pci {
55  struct device *dev;
59 };
60 
61 static int __devinit dwc3_pci_register_phys(struct dwc3_pci *glue)
62 {
63  struct nop_usb_xceiv_platform_data pdata;
64  struct platform_device *pdev;
65  int ret;
66 
67  memset(&pdata, 0x00, sizeof(pdata));
68 
69  pdev = platform_device_alloc("nop_usb_xceiv", 0);
70  if (!pdev)
71  return -ENOMEM;
72 
73  glue->usb2_phy = pdev;
74  pdata.type = USB_PHY_TYPE_USB2;
75 
76  ret = platform_device_add_data(glue->usb2_phy, &pdata, sizeof(pdata));
77  if (ret)
78  goto err1;
79 
80  pdev = platform_device_alloc("nop_usb_xceiv", 1);
81  if (!pdev) {
82  ret = -ENOMEM;
83  goto err1;
84  }
85 
86  glue->usb3_phy = pdev;
87  pdata.type = USB_PHY_TYPE_USB3;
88 
89  ret = platform_device_add_data(glue->usb3_phy, &pdata, sizeof(pdata));
90  if (ret)
91  goto err2;
92 
93  ret = platform_device_add(glue->usb2_phy);
94  if (ret)
95  goto err2;
96 
97  ret = platform_device_add(glue->usb3_phy);
98  if (ret)
99  goto err3;
100 
101  return 0;
102 
103 err3:
105 
106 err2:
108 
109 err1:
111 
112  return ret;
113 }
114 
115 static int __devinit dwc3_pci_probe(struct pci_dev *pci,
116  const struct pci_device_id *id)
117 {
118  struct resource res[2];
119  struct platform_device *dwc3;
120  struct dwc3_pci *glue;
121  int ret = -ENOMEM;
122  int devid;
123  struct device *dev = &pci->dev;
124 
125  glue = devm_kzalloc(dev, sizeof(*glue), GFP_KERNEL);
126  if (!glue) {
127  dev_err(dev, "not enough memory\n");
128  return -ENOMEM;
129  }
130 
131  glue->dev = dev;
132 
133  ret = pci_enable_device(pci);
134  if (ret) {
135  dev_err(dev, "failed to enable pci device\n");
136  return -ENODEV;
137  }
138 
140  pci_set_master(pci);
141 
142  ret = dwc3_pci_register_phys(glue);
143  if (ret) {
144  dev_err(dev, "couldn't register PHYs\n");
145  return ret;
146  }
147 
148  devid = dwc3_get_device_id();
149  if (devid < 0) {
150  ret = -ENOMEM;
151  goto err1;
152  }
153 
154  dwc3 = platform_device_alloc("dwc3", devid);
155  if (!dwc3) {
156  dev_err(dev, "couldn't allocate dwc3 device\n");
157  ret = -ENOMEM;
158  goto err1;
159  }
160 
161  memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res));
162 
163  res[0].start = pci_resource_start(pci, 0);
164  res[0].end = pci_resource_end(pci, 0);
165  res[0].name = "dwc_usb3";
166  res[0].flags = IORESOURCE_MEM;
167 
168  res[1].start = pci->irq;
169  res[1].name = "dwc_usb3";
170  res[1].flags = IORESOURCE_IRQ;
171 
173  if (ret) {
174  dev_err(dev, "couldn't add resources to dwc3 device\n");
175  goto err2;
176  }
177 
178  pci_set_drvdata(pci, glue);
179 
181 
182  dwc3->dev.dma_mask = dev->dma_mask;
183  dwc3->dev.dma_parms = dev->dma_parms;
184  dwc3->dev.parent = dev;
185  glue->dwc3 = dwc3;
186 
187  ret = platform_device_add(dwc3);
188  if (ret) {
189  dev_err(dev, "failed to register dwc3 device\n");
190  goto err3;
191  }
192 
193  return 0;
194 
195 err3:
196  pci_set_drvdata(pci, NULL);
197  platform_device_put(dwc3);
198 
199 err2:
200  dwc3_put_device_id(devid);
201 
202 err1:
203  pci_disable_device(pci);
204 
205  return ret;
206 }
207 
208 static void __devexit dwc3_pci_remove(struct pci_dev *pci)
209 {
210  struct dwc3_pci *glue = pci_get_drvdata(pci);
211 
214  dwc3_put_device_id(glue->dwc3->id);
216  pci_set_drvdata(pci, NULL);
217  pci_disable_device(pci);
218 }
219 
220 static DEFINE_PCI_DEVICE_TABLE(dwc3_pci_id_table) = {
221  {
224  },
225  { } /* Terminating Entry */
226 };
227 MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table);
228 
229 static struct pci_driver dwc3_pci_driver = {
230  .name = "dwc3-pci",
231  .id_table = dwc3_pci_id_table,
232  .probe = dwc3_pci_probe,
233  .remove = __devexit_p(dwc3_pci_remove),
234 };
235 
236 MODULE_AUTHOR("Felipe Balbi <[email protected]>");
237 MODULE_LICENSE("Dual BSD/GPL");
238 MODULE_DESCRIPTION("DesignWare USB3 PCI Glue Layer");
239 
240 module_pci_driver(dwc3_pci_driver);