1
2
3
4
5#include <linux/clk.h>
6#include <linux/delay.h>
7#include <linux/dma-mapping.h>
8#include <linux/init.h>
9#include <linux/mfd/da8xx-cfgchip.h>
10#include <linux/phy/phy.h>
11#include <linux/platform_data/phy-da8xx-usb.h>
12#include <linux/platform_data/usb-davinci.h>
13#include <linux/platform_device.h>
14#include <linux/usb/musb.h>
15
16#include <mach/clock.h>
17#include <mach/common.h>
18#include <mach/cputype.h>
19#include <mach/da8xx.h>
20#include <mach/irqs.h>
21
22#include "clock.h"
23
24#define DA8XX_USB0_BASE 0x01e00000
25#define DA8XX_USB1_BASE 0x01e25000
26
27static struct clk *usb20_clk;
28
29static struct da8xx_usb_phy_platform_data da8xx_usb_phy_pdata;
30
31static struct platform_device da8xx_usb_phy = {
32 .name = "da8xx-usb-phy",
33 .id = -1,
34 .dev = {
35
36
37
38
39
40 .init_name = "da8xx-usb-phy",
41 .platform_data = &da8xx_usb_phy_pdata,
42 },
43};
44
45int __init da8xx_register_usb_phy(void)
46{
47 da8xx_usb_phy_pdata.cfgchip = da8xx_get_cfgchip();
48
49 return platform_device_register(&da8xx_usb_phy);
50}
51
52static struct musb_hdrc_config musb_config = {
53 .multipoint = true,
54 .num_eps = 5,
55 .ram_bits = 10,
56};
57
58static struct musb_hdrc_platform_data usb_data = {
59
60 .mode = MUSB_OTG,
61 .clock = "usb20",
62 .config = &musb_config,
63};
64
65static struct resource da8xx_usb20_resources[] = {
66 {
67 .start = DA8XX_USB0_BASE,
68 .end = DA8XX_USB0_BASE + SZ_64K - 1,
69 .flags = IORESOURCE_MEM,
70 },
71 {
72 .start = IRQ_DA8XX_USB_INT,
73 .flags = IORESOURCE_IRQ,
74 .name = "mc",
75 },
76};
77
78static u64 usb_dmamask = DMA_BIT_MASK(32);
79
80static struct platform_device da8xx_usb20_dev = {
81 .name = "musb-da8xx",
82 .id = -1,
83 .dev = {
84
85
86
87
88 .init_name = "musb-da8xx",
89 .platform_data = &usb_data,
90 .dma_mask = &usb_dmamask,
91 .coherent_dma_mask = DMA_BIT_MASK(32),
92 },
93 .resource = da8xx_usb20_resources,
94 .num_resources = ARRAY_SIZE(da8xx_usb20_resources),
95};
96
97int __init da8xx_register_usb20(unsigned int mA, unsigned int potpgt)
98{
99 usb_data.power = mA > 510 ? 255 : mA / 2;
100 usb_data.potpgt = (potpgt + 1) / 2;
101
102 return platform_device_register(&da8xx_usb20_dev);
103}
104
105static struct resource da8xx_usb11_resources[] = {
106 [0] = {
107 .start = DA8XX_USB1_BASE,
108 .end = DA8XX_USB1_BASE + SZ_4K - 1,
109 .flags = IORESOURCE_MEM,
110 },
111 [1] = {
112 .start = IRQ_DA8XX_IRQN,
113 .end = IRQ_DA8XX_IRQN,
114 .flags = IORESOURCE_IRQ,
115 },
116};
117
118static u64 da8xx_usb11_dma_mask = DMA_BIT_MASK(32);
119
120static struct platform_device da8xx_usb11_device = {
121 .name = "ohci-da8xx",
122 .id = -1,
123 .dev = {
124 .dma_mask = &da8xx_usb11_dma_mask,
125 .coherent_dma_mask = DMA_BIT_MASK(32),
126 },
127 .num_resources = ARRAY_SIZE(da8xx_usb11_resources),
128 .resource = da8xx_usb11_resources,
129};
130
131int __init da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata)
132{
133 da8xx_usb11_device.dev.platform_data = pdata;
134 return platform_device_register(&da8xx_usb11_device);
135}
136
137static struct clk usb_refclkin = {
138 .name = "usb_refclkin",
139 .set_rate = davinci_simple_set_rate,
140};
141
142static struct clk_lookup usb_refclkin_lookup =
143 CLK(NULL, "usb_refclkin", &usb_refclkin);
144
145
146
147
148
149
150
151
152
153
154int __init da8xx_register_usb_refclkin(int rate)
155{
156 int ret;
157
158 usb_refclkin.rate = rate;
159 ret = clk_register(&usb_refclkin);
160 if (ret)
161 return ret;
162
163 clkdev_add(&usb_refclkin_lookup);
164
165 return 0;
166}
167
168static void usb20_phy_clk_enable(struct clk *clk)
169{
170 u32 val;
171 u32 timeout = 500000;
172
173 val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
174
175
176 davinci_clk_enable(usb20_clk);
177
178
179
180
181
182 val &= ~(CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN);
183 val |= CFGCHIP2_PHY_PLLON;
184
185 writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
186
187 while (--timeout) {
188 val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
189 if (val & CFGCHIP2_PHYCLKGD)
190 goto done;
191 udelay(1);
192 }
193
194 pr_err("Timeout waiting for USB 2.0 PHY clock good\n");
195done:
196 davinci_clk_disable(usb20_clk);
197}
198
199static void usb20_phy_clk_disable(struct clk *clk)
200{
201 u32 val;
202
203 val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
204 val |= CFGCHIP2_PHYPWRDN;
205 writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
206}
207
208static int usb20_phy_clk_set_parent(struct clk *clk, struct clk *parent)
209{
210 u32 val;
211
212 val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
213
214
215 if (parent == &usb_refclkin) {
216 val &= ~CFGCHIP2_USB2PHYCLKMUX;
217 } else if (strcmp(parent->name, "pll0_aux_clk") == 0) {
218 val |= CFGCHIP2_USB2PHYCLKMUX;
219 } else {
220 pr_err("Bad parent on USB 2.0 PHY clock\n");
221 return -EINVAL;
222 }
223
224
225 val &= ~CFGCHIP2_REFFREQ_MASK;
226 switch (clk_get_rate(parent)) {
227 case 12000000:
228 val |= CFGCHIP2_REFFREQ_12MHZ;
229 break;
230 case 13000000:
231 val |= CFGCHIP2_REFFREQ_13MHZ;
232 break;
233 case 19200000:
234 val |= CFGCHIP2_REFFREQ_19_2MHZ;
235 break;
236 case 20000000:
237 val |= CFGCHIP2_REFFREQ_20MHZ;
238 break;
239 case 24000000:
240 val |= CFGCHIP2_REFFREQ_24MHZ;
241 break;
242 case 26000000:
243 val |= CFGCHIP2_REFFREQ_26MHZ;
244 break;
245 case 38400000:
246 val |= CFGCHIP2_REFFREQ_38_4MHZ;
247 break;
248 case 40000000:
249 val |= CFGCHIP2_REFFREQ_40MHZ;
250 break;
251 case 48000000:
252 val |= CFGCHIP2_REFFREQ_48MHZ;
253 break;
254 default:
255 pr_err("Bad parent clock rate on USB 2.0 PHY clock\n");
256 return -EINVAL;
257 }
258
259 writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
260
261 return 0;
262}
263
264static struct clk usb20_phy_clk = {
265 .name = "usb0_clk48",
266 .clk_enable = usb20_phy_clk_enable,
267 .clk_disable = usb20_phy_clk_disable,
268 .set_parent = usb20_phy_clk_set_parent,
269};
270
271static struct clk_lookup usb20_phy_clk_lookup =
272 CLK("da8xx-usb-phy", "usb0_clk48", &usb20_phy_clk);
273
274
275
276
277
278
279
280int __init da8xx_register_usb20_phy_clk(bool use_usb_refclkin)
281{
282 struct clk *parent;
283 int ret;
284
285 usb20_clk = clk_get(&da8xx_usb20_dev.dev, "usb20");
286 ret = PTR_ERR_OR_ZERO(usb20_clk);
287 if (ret)
288 return ret;
289
290 parent = clk_get(NULL, use_usb_refclkin ? "usb_refclkin" : "pll0_aux");
291 ret = PTR_ERR_OR_ZERO(parent);
292 if (ret) {
293 clk_put(usb20_clk);
294 return ret;
295 }
296
297 usb20_phy_clk.parent = parent;
298 ret = clk_register(&usb20_phy_clk);
299 if (!ret)
300 clkdev_add(&usb20_phy_clk_lookup);
301
302 clk_put(parent);
303
304 return ret;
305}
306
307static int usb11_phy_clk_set_parent(struct clk *clk, struct clk *parent)
308{
309 u32 val;
310
311 val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
312
313
314 if (parent == &usb20_phy_clk) {
315 val &= ~CFGCHIP2_USB1PHYCLKMUX;
316 } else if (parent == &usb_refclkin) {
317 val |= CFGCHIP2_USB1PHYCLKMUX;
318 } else {
319 pr_err("Bad parent on USB 1.1 PHY clock\n");
320 return -EINVAL;
321 }
322
323 writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
324
325 return 0;
326}
327
328static struct clk usb11_phy_clk = {
329 .name = "usb1_clk48",
330 .set_parent = usb11_phy_clk_set_parent,
331};
332
333static struct clk_lookup usb11_phy_clk_lookup =
334 CLK("da8xx-usb-phy", "usb1_clk48", &usb11_phy_clk);
335
336
337
338
339
340
341
342int __init da8xx_register_usb11_phy_clk(bool use_usb_refclkin)
343{
344 struct clk *parent;
345 int ret = 0;
346
347 if (use_usb_refclkin)
348 parent = clk_get(NULL, "usb_refclkin");
349 else
350 parent = clk_get(&da8xx_usb_phy.dev, "usb0_clk48");
351 if (IS_ERR(parent))
352 return PTR_ERR(parent);
353
354 usb11_phy_clk.parent = parent;
355 ret = clk_register(&usb11_phy_clk);
356 if (!ret)
357 clkdev_add(&usb11_phy_clk_lookup);
358
359 clk_put(parent);
360
361 return ret;
362}
363