blob: 9a6af0bd5dc340690bbe794b972b0aeb529faeff [file] [log] [blame]
David Lechner86cad162016-03-24 18:51:28 -05001/*
2 * DA8xx USB
3 */
David Lechner0004b022016-10-31 15:47:20 -05004#include <linux/clk.h>
5#include <linux/delay.h>
David Lechner86cad162016-03-24 18:51:28 -05006#include <linux/dma-mapping.h>
7#include <linux/init.h>
David Lechner0004b022016-10-31 15:47:20 -05008#include <linux/mfd/da8xx-cfgchip.h>
David Lechner9b504752016-10-26 19:18:15 -05009#include <linux/phy/phy.h>
David Lechner86cad162016-03-24 18:51:28 -050010#include <linux/platform_data/usb-davinci.h>
11#include <linux/platform_device.h>
12#include <linux/usb/musb.h>
13
David Lechner0004b022016-10-31 15:47:20 -050014#include <mach/clock.h>
David Lechner86cad162016-03-24 18:51:28 -050015#include <mach/common.h>
16#include <mach/cputype.h>
17#include <mach/da8xx.h>
18#include <mach/irqs.h>
19
David Lechner0004b022016-10-31 15:47:20 -050020#include "clock.h"
21
David Lechner86cad162016-03-24 18:51:28 -050022#define DA8XX_USB0_BASE 0x01e00000
23#define DA8XX_USB1_BASE 0x01e25000
24
Alexandre Bailond1df1e02016-12-09 17:59:33 +010025static struct clk *usb20_clk;
26
David Lechner9b504752016-10-26 19:18:15 -050027static struct platform_device da8xx_usb_phy = {
28 .name = "da8xx-usb-phy",
29 .id = -1,
David Lechner0004b022016-10-31 15:47:20 -050030 .dev = {
31 /*
32 * Setting init_name so that clock lookup will work in
33 * da8xx_register_usb11_phy_clk() even if this device is not
34 * registered yet.
35 */
36 .init_name = "da8xx-usb-phy",
37 },
David Lechner9b504752016-10-26 19:18:15 -050038};
39
40int __init da8xx_register_usb_phy(void)
41{
42 return platform_device_register(&da8xx_usb_phy);
43}
44
David Lechner86cad162016-03-24 18:51:28 -050045static struct musb_hdrc_config musb_config = {
46 .multipoint = true,
47 .num_eps = 5,
48 .ram_bits = 10,
49};
50
51static struct musb_hdrc_platform_data usb_data = {
52 /* OTG requires a Mini-AB connector */
53 .mode = MUSB_OTG,
54 .clock = "usb20",
55 .config = &musb_config,
56};
57
58static struct resource da8xx_usb20_resources[] = {
59 {
60 .start = DA8XX_USB0_BASE,
61 .end = DA8XX_USB0_BASE + SZ_64K - 1,
62 .flags = IORESOURCE_MEM,
63 },
64 {
65 .start = IRQ_DA8XX_USB_INT,
66 .flags = IORESOURCE_IRQ,
67 .name = "mc",
68 },
69};
70
71static u64 usb_dmamask = DMA_BIT_MASK(32);
72
David Lechner0004b022016-10-31 15:47:20 -050073static struct platform_device da8xx_usb20_dev = {
David Lechner86cad162016-03-24 18:51:28 -050074 .name = "musb-da8xx",
75 .id = -1,
76 .dev = {
David Lechner0004b022016-10-31 15:47:20 -050077 /*
78 * Setting init_name so that clock lookup will work in
79 * usb20_phy_clk_enable() even if this device is not registered.
80 */
81 .init_name = "musb-da8xx",
David Lechner86cad162016-03-24 18:51:28 -050082 .platform_data = &usb_data,
83 .dma_mask = &usb_dmamask,
84 .coherent_dma_mask = DMA_BIT_MASK(32),
85 },
86 .resource = da8xx_usb20_resources,
87 .num_resources = ARRAY_SIZE(da8xx_usb20_resources),
88};
89
90int __init da8xx_register_usb20(unsigned int mA, unsigned int potpgt)
91{
92 usb_data.power = mA > 510 ? 255 : mA / 2;
93 usb_data.potpgt = (potpgt + 1) / 2;
94
David Lechner0004b022016-10-31 15:47:20 -050095 return platform_device_register(&da8xx_usb20_dev);
David Lechner86cad162016-03-24 18:51:28 -050096}
97
David Lechner86cad162016-03-24 18:51:28 -050098static struct resource da8xx_usb11_resources[] = {
99 [0] = {
100 .start = DA8XX_USB1_BASE,
101 .end = DA8XX_USB1_BASE + SZ_4K - 1,
102 .flags = IORESOURCE_MEM,
103 },
104 [1] = {
105 .start = IRQ_DA8XX_IRQN,
106 .end = IRQ_DA8XX_IRQN,
107 .flags = IORESOURCE_IRQ,
108 },
109};
110
111static u64 da8xx_usb11_dma_mask = DMA_BIT_MASK(32);
112
113static struct platform_device da8xx_usb11_device = {
Axel Haslam8439a1d2016-11-03 17:03:06 +0100114 .name = "ohci-da8xx",
115 .id = -1,
David Lechner86cad162016-03-24 18:51:28 -0500116 .dev = {
117 .dma_mask = &da8xx_usb11_dma_mask,
118 .coherent_dma_mask = DMA_BIT_MASK(32),
119 },
120 .num_resources = ARRAY_SIZE(da8xx_usb11_resources),
121 .resource = da8xx_usb11_resources,
122};
123
124int __init da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata)
125{
126 da8xx_usb11_device.dev.platform_data = pdata;
127 return platform_device_register(&da8xx_usb11_device);
128}
David Lechner0004b022016-10-31 15:47:20 -0500129
130static struct clk usb_refclkin = {
131 .name = "usb_refclkin",
132 .set_rate = davinci_simple_set_rate,
133};
134
135static struct clk_lookup usb_refclkin_lookup =
136 CLK(NULL, "usb_refclkin", &usb_refclkin);
137
138/**
139 * da8xx_register_usb_refclkin - register USB_REFCLKIN clock
140 *
141 * @rate: The clock rate in Hz
142 *
143 * This clock is only needed if the board provides an external USB_REFCLKIN
144 * signal, in which case it will be used as the parent of usb20_phy_clk and/or
145 * usb11_phy_clk.
146 */
147int __init da8xx_register_usb_refclkin(int rate)
148{
149 int ret;
150
151 usb_refclkin.rate = rate;
152 ret = clk_register(&usb_refclkin);
153 if (ret)
154 return ret;
155
156 clkdev_add(&usb_refclkin_lookup);
157
158 return 0;
159}
160
161static void usb20_phy_clk_enable(struct clk *clk)
162{
David Lechner0004b022016-10-31 15:47:20 -0500163 u32 val;
164 u32 timeout = 500000; /* 500 msec */
165
166 val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
167
David Lechner0004b022016-10-31 15:47:20 -0500168 /* The USB 2.O PLL requires that the USB 2.O PSC is enabled as well. */
Alexandre Bailond1df1e02016-12-09 17:59:33 +0100169 davinci_clk_enable(usb20_clk);
David Lechner0004b022016-10-31 15:47:20 -0500170
171 /*
172 * Turn on the USB 2.0 PHY, but just the PLL, and not OTG. The USB 1.1
173 * host may use the PLL clock without USB 2.0 OTG being used.
174 */
175 val &= ~(CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN);
176 val |= CFGCHIP2_PHY_PLLON;
177
178 writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
179
180 while (--timeout) {
181 val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
182 if (val & CFGCHIP2_PHYCLKGD)
183 goto done;
184 udelay(1);
185 }
186
187 pr_err("Timeout waiting for USB 2.0 PHY clock good\n");
188done:
Alexandre Bailond1df1e02016-12-09 17:59:33 +0100189 davinci_clk_disable(usb20_clk);
David Lechner0004b022016-10-31 15:47:20 -0500190}
191
192static void usb20_phy_clk_disable(struct clk *clk)
193{
194 u32 val;
195
196 val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
197 val |= CFGCHIP2_PHYPWRDN;
198 writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
199}
200
201static int usb20_phy_clk_set_parent(struct clk *clk, struct clk *parent)
202{
203 u32 val;
204
205 val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
206
207 /* Set the mux depending on the parent clock. */
208 if (parent == &usb_refclkin) {
209 val &= ~CFGCHIP2_USB2PHYCLKMUX;
210 } else if (strcmp(parent->name, "pll0_aux_clk") == 0) {
211 val |= CFGCHIP2_USB2PHYCLKMUX;
212 } else {
213 pr_err("Bad parent on USB 2.0 PHY clock\n");
214 return -EINVAL;
215 }
216
217 /* reference frequency also comes from parent clock */
218 val &= ~CFGCHIP2_REFFREQ_MASK;
219 switch (clk_get_rate(parent)) {
220 case 12000000:
221 val |= CFGCHIP2_REFFREQ_12MHZ;
222 break;
223 case 13000000:
224 val |= CFGCHIP2_REFFREQ_13MHZ;
225 break;
226 case 19200000:
227 val |= CFGCHIP2_REFFREQ_19_2MHZ;
228 break;
229 case 20000000:
230 val |= CFGCHIP2_REFFREQ_20MHZ;
231 break;
232 case 24000000:
233 val |= CFGCHIP2_REFFREQ_24MHZ;
234 break;
235 case 26000000:
236 val |= CFGCHIP2_REFFREQ_26MHZ;
237 break;
238 case 38400000:
239 val |= CFGCHIP2_REFFREQ_38_4MHZ;
240 break;
241 case 40000000:
242 val |= CFGCHIP2_REFFREQ_40MHZ;
243 break;
244 case 48000000:
245 val |= CFGCHIP2_REFFREQ_48MHZ;
246 break;
247 default:
248 pr_err("Bad parent clock rate on USB 2.0 PHY clock\n");
249 return -EINVAL;
250 }
251
252 writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
253
254 return 0;
255}
256
257static struct clk usb20_phy_clk = {
258 .name = "usb20_phy",
259 .clk_enable = usb20_phy_clk_enable,
260 .clk_disable = usb20_phy_clk_disable,
261 .set_parent = usb20_phy_clk_set_parent,
262};
263
264static struct clk_lookup usb20_phy_clk_lookup =
265 CLK("da8xx-usb-phy", "usb20_phy", &usb20_phy_clk);
266
267/**
268 * da8xx_register_usb20_phy_clk - register USB0PHYCLKMUX clock
269 *
270 * @use_usb_refclkin: Selects the parent clock - either "usb_refclkin" if true
271 * or "pll0_aux" if false.
272 */
273int __init da8xx_register_usb20_phy_clk(bool use_usb_refclkin)
274{
275 struct clk *parent;
Alexandre Bailond1df1e02016-12-09 17:59:33 +0100276 int ret;
277
278 usb20_clk = clk_get(&da8xx_usb20_dev.dev, "usb20");
279 ret = PTR_ERR_OR_ZERO(usb20_clk);
280 if (ret)
281 return ret;
David Lechner0004b022016-10-31 15:47:20 -0500282
283 parent = clk_get(NULL, use_usb_refclkin ? "usb_refclkin" : "pll0_aux");
Alexandre Bailond1df1e02016-12-09 17:59:33 +0100284 ret = PTR_ERR_OR_ZERO(parent);
285 if (ret) {
286 clk_put(usb20_clk);
287 return ret;
288 }
David Lechner0004b022016-10-31 15:47:20 -0500289
290 usb20_phy_clk.parent = parent;
291 ret = clk_register(&usb20_phy_clk);
292 if (!ret)
293 clkdev_add(&usb20_phy_clk_lookup);
294
295 clk_put(parent);
296
297 return ret;
298}
299
300static int usb11_phy_clk_set_parent(struct clk *clk, struct clk *parent)
301{
302 u32 val;
303
304 val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
305
306 /* Set the USB 1.1 PHY clock mux based on the parent clock. */
307 if (parent == &usb20_phy_clk) {
308 val &= ~CFGCHIP2_USB1PHYCLKMUX;
309 } else if (parent == &usb_refclkin) {
310 val |= CFGCHIP2_USB1PHYCLKMUX;
311 } else {
312 pr_err("Bad parent on USB 1.1 PHY clock\n");
313 return -EINVAL;
314 }
315
316 writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
317
318 return 0;
319}
320
321static struct clk usb11_phy_clk = {
322 .name = "usb11_phy",
323 .set_parent = usb11_phy_clk_set_parent,
324};
325
326static struct clk_lookup usb11_phy_clk_lookup =
327 CLK("da8xx-usb-phy", "usb11_phy", &usb11_phy_clk);
328
329/**
330 * da8xx_register_usb11_phy_clk - register USB1PHYCLKMUX clock
331 *
332 * @use_usb_refclkin: Selects the parent clock - either "usb_refclkin" if true
333 * or "usb20_phy" if false.
334 */
335int __init da8xx_register_usb11_phy_clk(bool use_usb_refclkin)
336{
337 struct clk *parent;
338 int ret = 0;
339
340 if (use_usb_refclkin)
341 parent = clk_get(NULL, "usb_refclkin");
342 else
343 parent = clk_get(&da8xx_usb_phy.dev, "usb20_phy");
344 if (IS_ERR(parent))
345 return PTR_ERR(parent);
346
347 usb11_phy_clk.parent = parent;
348 ret = clk_register(&usb11_phy_clk);
349 if (!ret)
350 clkdev_add(&usb11_phy_clk_lookup);
351
352 clk_put(parent);
353
354 return ret;
355}