blob: 50445f0e98def51ac1e261d03746fb36ab8628fe [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001// SPDX-License-Identifier: GPL-2.0
David Lechner86cad162016-03-24 18:51:28 -05002/*
3 * DA8xx USB
4 */
David Lechner0004b022016-10-31 15:47:20 -05005#include <linux/clk.h>
6#include <linux/delay.h>
David Lechner86cad162016-03-24 18:51:28 -05007#include <linux/dma-mapping.h>
8#include <linux/init.h>
David Lechner0004b022016-10-31 15:47:20 -05009#include <linux/mfd/da8xx-cfgchip.h>
David Lechner9b504752016-10-26 19:18:15 -050010#include <linux/phy/phy.h>
David Lechnerbdec5a62018-02-17 21:22:24 -060011#include <linux/platform_data/phy-da8xx-usb.h>
David Lechner86cad162016-03-24 18:51:28 -050012#include <linux/platform_data/usb-davinci.h>
13#include <linux/platform_device.h>
14#include <linux/usb/musb.h>
15
David Lechner0004b022016-10-31 15:47:20 -050016#include <mach/clock.h>
David Lechner86cad162016-03-24 18:51:28 -050017#include <mach/common.h>
18#include <mach/cputype.h>
19#include <mach/da8xx.h>
20#include <mach/irqs.h>
21
David Lechner0004b022016-10-31 15:47:20 -050022#include "clock.h"
23
David Lechner86cad162016-03-24 18:51:28 -050024#define DA8XX_USB0_BASE 0x01e00000
25#define DA8XX_USB1_BASE 0x01e25000
26
Alexandre Bailond1df1e02016-12-09 17:59:33 +010027static struct clk *usb20_clk;
28
David Lechner3424a512018-03-15 14:17:20 -050029static struct da8xx_usb_phy_platform_data da8xx_usb_phy_pdata;
30
David Lechner9b504752016-10-26 19:18:15 -050031static struct platform_device da8xx_usb_phy = {
32 .name = "da8xx-usb-phy",
33 .id = -1,
David Lechner0004b022016-10-31 15:47:20 -050034 .dev = {
35 /*
36 * Setting init_name so that clock lookup will work in
37 * da8xx_register_usb11_phy_clk() even if this device is not
38 * registered yet.
39 */
40 .init_name = "da8xx-usb-phy",
David Lechner3424a512018-03-15 14:17:20 -050041 .platform_data = &da8xx_usb_phy_pdata,
David Lechner0004b022016-10-31 15:47:20 -050042 },
David Lechner9b504752016-10-26 19:18:15 -050043};
44
45int __init da8xx_register_usb_phy(void)
46{
David Lechner3424a512018-03-15 14:17:20 -050047 da8xx_usb_phy_pdata.cfgchip = da8xx_get_cfgchip();
David Lechnerbdec5a62018-02-17 21:22:24 -060048
David Lechner9b504752016-10-26 19:18:15 -050049 return platform_device_register(&da8xx_usb_phy);
50}
51
David Lechner86cad162016-03-24 18:51:28 -050052static 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 /* OTG requires a Mini-AB connector */
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
David Lechner0004b022016-10-31 15:47:20 -050080static struct platform_device da8xx_usb20_dev = {
David Lechner86cad162016-03-24 18:51:28 -050081 .name = "musb-da8xx",
82 .id = -1,
83 .dev = {
David Lechner0004b022016-10-31 15:47:20 -050084 /*
85 * Setting init_name so that clock lookup will work in
86 * usb20_phy_clk_enable() even if this device is not registered.
87 */
88 .init_name = "musb-da8xx",
David Lechner86cad162016-03-24 18:51:28 -050089 .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
David Lechner0004b022016-10-31 15:47:20 -0500102 return platform_device_register(&da8xx_usb20_dev);
David Lechner86cad162016-03-24 18:51:28 -0500103}
104
David Lechner86cad162016-03-24 18:51:28 -0500105static 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 = {
Axel Haslam8439a1d2016-11-03 17:03:06 +0100121 .name = "ohci-da8xx",
122 .id = -1,
David Lechner86cad162016-03-24 18:51:28 -0500123 .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}
David Lechner0004b022016-10-31 15:47:20 -0500136
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 * da8xx_register_usb_refclkin - register USB_REFCLKIN clock
147 *
148 * @rate: The clock rate in Hz
149 *
150 * This clock is only needed if the board provides an external USB_REFCLKIN
151 * signal, in which case it will be used as the parent of usb20_phy_clk and/or
152 * usb11_phy_clk.
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{
David Lechner0004b022016-10-31 15:47:20 -0500170 u32 val;
171 u32 timeout = 500000; /* 500 msec */
172
173 val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
174
David Lechner0004b022016-10-31 15:47:20 -0500175 /* The USB 2.O PLL requires that the USB 2.O PSC is enabled as well. */
Alexandre Bailond1df1e02016-12-09 17:59:33 +0100176 davinci_clk_enable(usb20_clk);
David Lechner0004b022016-10-31 15:47:20 -0500177
178 /*
179 * Turn on the USB 2.0 PHY, but just the PLL, and not OTG. The USB 1.1
180 * host may use the PLL clock without USB 2.0 OTG being used.
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:
Alexandre Bailond1df1e02016-12-09 17:59:33 +0100196 davinci_clk_disable(usb20_clk);
David Lechner0004b022016-10-31 15:47:20 -0500197}
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 /* Set the mux depending on the parent clock. */
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 /* reference frequency also comes from parent clock */
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 = {
David Lechnere98bbbf2018-01-23 12:14:43 -0600265 .name = "usb0_clk48",
David Lechner0004b022016-10-31 15:47:20 -0500266 .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 =
David Lechnere98bbbf2018-01-23 12:14:43 -0600272 CLK("da8xx-usb-phy", "usb0_clk48", &usb20_phy_clk);
David Lechner0004b022016-10-31 15:47:20 -0500273
274/**
275 * da8xx_register_usb20_phy_clk - register USB0PHYCLKMUX clock
276 *
277 * @use_usb_refclkin: Selects the parent clock - either "usb_refclkin" if true
278 * or "pll0_aux" if false.
279 */
280int __init da8xx_register_usb20_phy_clk(bool use_usb_refclkin)
281{
282 struct clk *parent;
Alexandre Bailond1df1e02016-12-09 17:59:33 +0100283 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;
David Lechner0004b022016-10-31 15:47:20 -0500289
290 parent = clk_get(NULL, use_usb_refclkin ? "usb_refclkin" : "pll0_aux");
Alexandre Bailond1df1e02016-12-09 17:59:33 +0100291 ret = PTR_ERR_OR_ZERO(parent);
292 if (ret) {
293 clk_put(usb20_clk);
294 return ret;
295 }
David Lechner0004b022016-10-31 15:47:20 -0500296
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 /* Set the USB 1.1 PHY clock mux based on the parent clock. */
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 = {
David Lechnere98bbbf2018-01-23 12:14:43 -0600329 .name = "usb1_clk48",
David Lechner0004b022016-10-31 15:47:20 -0500330 .set_parent = usb11_phy_clk_set_parent,
331};
332
333static struct clk_lookup usb11_phy_clk_lookup =
David Lechnere98bbbf2018-01-23 12:14:43 -0600334 CLK("da8xx-usb-phy", "usb1_clk48", &usb11_phy_clk);
David Lechner0004b022016-10-31 15:47:20 -0500335
336/**
337 * da8xx_register_usb11_phy_clk - register USB1PHYCLKMUX clock
338 *
339 * @use_usb_refclkin: Selects the parent clock - either "usb_refclkin" if true
David Lechnere98bbbf2018-01-23 12:14:43 -0600340 * or "usb0_clk48" if false.
David Lechner0004b022016-10-31 15:47:20 -0500341 */
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
David Lechnere98bbbf2018-01-23 12:14:43 -0600350 parent = clk_get(&da8xx_usb_phy.dev, "usb0_clk48");
David Lechner0004b022016-10-31 15:47:20 -0500351 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}