Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dwc3-exynos.c
Go to the documentation of this file.
1 
15 #include <linux/module.h>
16 #include <linux/kernel.h>
17 #include <linux/slab.h>
18 #include <linux/platform_device.h>
20 #include <linux/dma-mapping.h>
21 #include <linux/clk.h>
22 #include <linux/usb/otg.h>
24 
25 #include "core.h"
26 
27 struct dwc3_exynos {
31  struct device *dev;
32 
33  struct clk *clk;
34 };
35 
36 static int __devinit dwc3_exynos_register_phys(struct dwc3_exynos *exynos)
37 {
38  struct nop_usb_xceiv_platform_data pdata;
39  struct platform_device *pdev;
40  int ret;
41 
42  memset(&pdata, 0x00, sizeof(pdata));
43 
44  pdev = platform_device_alloc("nop_usb_xceiv", 0);
45  if (!pdev)
46  return -ENOMEM;
47 
48  exynos->usb2_phy = pdev;
49  pdata.type = USB_PHY_TYPE_USB2;
50 
51  ret = platform_device_add_data(exynos->usb2_phy, &pdata, sizeof(pdata));
52  if (ret)
53  goto err1;
54 
55  pdev = platform_device_alloc("nop_usb_xceiv", 1);
56  if (!pdev) {
57  ret = -ENOMEM;
58  goto err1;
59  }
60 
61  exynos->usb3_phy = pdev;
62  pdata.type = USB_PHY_TYPE_USB3;
63 
64  ret = platform_device_add_data(exynos->usb3_phy, &pdata, sizeof(pdata));
65  if (ret)
66  goto err2;
67 
68  ret = platform_device_add(exynos->usb2_phy);
69  if (ret)
70  goto err2;
71 
72  ret = platform_device_add(exynos->usb3_phy);
73  if (ret)
74  goto err3;
75 
76  return 0;
77 
78 err3:
80 
81 err2:
83 
84 err1:
86 
87  return ret;
88 }
89 
90 static int __devinit dwc3_exynos_probe(struct platform_device *pdev)
91 {
92  struct dwc3_exynos_data *pdata = pdev->dev.platform_data;
93  struct platform_device *dwc3;
94  struct dwc3_exynos *exynos;
95  struct clk *clk;
96 
97  int devid;
98  int ret = -ENOMEM;
99 
100  exynos = kzalloc(sizeof(*exynos), GFP_KERNEL);
101  if (!exynos) {
102  dev_err(&pdev->dev, "not enough memory\n");
103  goto err0;
104  }
105 
106  platform_set_drvdata(pdev, exynos);
107 
108  devid = dwc3_get_device_id();
109  if (devid < 0)
110  goto err1;
111 
112  ret = dwc3_exynos_register_phys(exynos);
113  if (ret) {
114  dev_err(&pdev->dev, "couldn't register PHYs\n");
115  goto err1;
116  }
117 
118  dwc3 = platform_device_alloc("dwc3", devid);
119  if (!dwc3) {
120  dev_err(&pdev->dev, "couldn't allocate dwc3 device\n");
121  goto err2;
122  }
123 
124  clk = clk_get(&pdev->dev, "usbdrd30");
125  if (IS_ERR(clk)) {
126  dev_err(&pdev->dev, "couldn't get clock\n");
127  ret = -EINVAL;
128  goto err3;
129  }
130 
131  dma_set_coherent_mask(&dwc3->dev, pdev->dev.coherent_dma_mask);
132 
133  dwc3->dev.parent = &pdev->dev;
134  dwc3->dev.dma_mask = pdev->dev.dma_mask;
135  dwc3->dev.dma_parms = pdev->dev.dma_parms;
136  exynos->dwc3 = dwc3;
137  exynos->dev = &pdev->dev;
138  exynos->clk = clk;
139 
140  clk_enable(exynos->clk);
141 
142  /* PHY initialization */
143  if (!pdata) {
144  dev_dbg(&pdev->dev, "missing platform data\n");
145  } else {
146  if (pdata->phy_init)
147  pdata->phy_init(pdev, pdata->phy_type);
148  }
149 
150  ret = platform_device_add_resources(dwc3, pdev->resource,
151  pdev->num_resources);
152  if (ret) {
153  dev_err(&pdev->dev, "couldn't add resources to dwc3 device\n");
154  goto err4;
155  }
156 
157  ret = platform_device_add(dwc3);
158  if (ret) {
159  dev_err(&pdev->dev, "failed to register dwc3 device\n");
160  goto err4;
161  }
162 
163  return 0;
164 
165 err4:
166  if (pdata && pdata->phy_exit)
167  pdata->phy_exit(pdev, pdata->phy_type);
168 
169  clk_disable(clk);
170  clk_put(clk);
171 err3:
172  platform_device_put(dwc3);
173 err2:
174  dwc3_put_device_id(devid);
175 err1:
176  kfree(exynos);
177 err0:
178  return ret;
179 }
180 
181 static int __devexit dwc3_exynos_remove(struct platform_device *pdev)
182 {
183  struct dwc3_exynos *exynos = platform_get_drvdata(pdev);
184  struct dwc3_exynos_data *pdata = pdev->dev.platform_data;
185 
189 
190  dwc3_put_device_id(exynos->dwc3->id);
191 
192  if (pdata && pdata->phy_exit)
193  pdata->phy_exit(pdev, pdata->phy_type);
194 
195  clk_disable(exynos->clk);
196  clk_put(exynos->clk);
197 
198  kfree(exynos);
199 
200  return 0;
201 }
202 
203 static struct platform_driver dwc3_exynos_driver = {
204  .probe = dwc3_exynos_probe,
205  .remove = __devexit_p(dwc3_exynos_remove),
206  .driver = {
207  .name = "exynos-dwc3",
208  },
209 };
210 
211 module_platform_driver(dwc3_exynos_driver);
212 
213 MODULE_ALIAS("platform:exynos-dwc3");
214 MODULE_AUTHOR("Anton Tikhomirov <[email protected]>");
215 MODULE_LICENSE("GPL");
216 MODULE_DESCRIPTION("DesignWare USB3 EXYNOS Glue Layer");