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