aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Lechner <david@lechnology.com>2016-10-31 16:47:20 -0400
committerSekhar Nori <nsekhar@ti.com>2016-11-01 05:54:14 -0400
commit0004b02a6820e855788fc029b21d710b3c5fdfe0 (patch)
treea8c43a1bc66c1d85b38c5b75c05e9975d4d54d09
parent3b996e5f8f4057b76eacae493a309215f3fd8485 (diff)
ARM: davinci: da8xx: add usb phy clocks
Up to this point, the USB phy clock configuration was handled manually in the board files and in the usb drivers. This adds proper clocks so that the usb drivers can use clk_get and clk_enable and not have to worry about the details. Also, the related code is removed from the board files and replaced with the new clock registration functions. This also removes the #if IS_ENABLED(CONFIG_USB_MUSB_HDRC) around the musb declaration and renames the musb platform device so that we can reference it from the usb20 clock even if the musb device is not used. Signed-off-by: David Lechner <david@lechnology.com> Signed-off-by: Axel Haslam <ahaslam@baylibre.com> Signed-off-by: Sekhar Nori <nsekhar@ti.com>
-rw-r--r--arch/arm/mach-davinci/board-da830-evm.c31
-rw-r--r--arch/arm/mach-davinci/board-omapl138-hawk.c15
-rw-r--r--arch/arm/mach-davinci/include/mach/da8xx.h3
-rw-r--r--arch/arm/mach-davinci/usb-da8xx.c267
4 files changed, 274 insertions, 42 deletions
diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c
index 53172add5248..5db09014f55a 100644
--- a/arch/arm/mach-davinci/board-da830-evm.c
+++ b/arch/arm/mach-davinci/board-da830-evm.c
@@ -18,7 +18,6 @@
18#include <linux/i2c.h> 18#include <linux/i2c.h>
19#include <linux/i2c/pcf857x.h> 19#include <linux/i2c/pcf857x.h>
20#include <linux/platform_data/at24.h> 20#include <linux/platform_data/at24.h>
21#include <linux/mfd/da8xx-cfgchip.h>
22#include <linux/mtd/mtd.h> 21#include <linux/mtd/mtd.h>
23#include <linux/mtd/partitions.h> 22#include <linux/mtd/partitions.h>
24#include <linux/spi/spi.h> 23#include <linux/spi/spi.h>
@@ -108,30 +107,18 @@ static irqreturn_t da830_evm_usb_ocic_irq(int irq, void *dev_id)
108 107
109static __init void da830_evm_usb_init(void) 108static __init void da830_evm_usb_init(void)
110{ 109{
111 u32 cfgchip2;
112 int ret; 110 int ret;
113 111
114 /*
115 * Set up USB clock in the CFGCHIP2 register.
116 * FYI: CFGCHIP2 is 0x0000ef00 initially.
117 */
118 cfgchip2 = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
119
120 /* USB2.0 PHY reference clock is 24 MHz */
121 cfgchip2 &= ~CFGCHIP2_REFFREQ_MASK;
122 cfgchip2 |= CFGCHIP2_REFFREQ_24MHZ;
123
124 /*
125 * Select internal reference clock for USB 2.0 PHY
126 * and use it as a clock source for USB 1.1 PHY
127 * (this is the default setting anyway).
128 */
129 cfgchip2 &= ~CFGCHIP2_USB1PHYCLKMUX;
130 cfgchip2 |= CFGCHIP2_USB2PHYCLKMUX;
131
132 __raw_writel(cfgchip2, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
133
134 /* USB_REFCLKIN is not used. */ 112 /* USB_REFCLKIN is not used. */
113 ret = da8xx_register_usb20_phy_clk(false);
114 if (ret)
115 pr_warn("%s: USB 2.0 PHY CLK registration failed: %d\n",
116 __func__, ret);
117
118 ret = da8xx_register_usb11_phy_clk(false);
119 if (ret)
120 pr_warn("%s: USB 1.1 PHY CLK registration failed: %d\n",
121 __func__, ret);
135 122
136 ret = da8xx_register_usb_phy(); 123 ret = da8xx_register_usb_phy();
137 if (ret) 124 if (ret)
diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c
index 67477ca4f15a..a4e87264ebd7 100644
--- a/arch/arm/mach-davinci/board-omapl138-hawk.c
+++ b/arch/arm/mach-davinci/board-omapl138-hawk.c
@@ -13,7 +13,6 @@
13#include <linux/init.h> 13#include <linux/init.h>
14#include <linux/console.h> 14#include <linux/console.h>
15#include <linux/gpio.h> 15#include <linux/gpio.h>
16#include <linux/mfd/da8xx-cfgchip.h>
17#include <linux/platform_data/gpio-davinci.h> 16#include <linux/platform_data/gpio-davinci.h>
18#include <linux/regulator/machine.h> 17#include <linux/regulator/machine.h>
19 18
@@ -245,7 +244,6 @@ static irqreturn_t omapl138_hawk_usb_ocic_irq(int irq, void *dev_id)
245static __init void omapl138_hawk_usb_init(void) 244static __init void omapl138_hawk_usb_init(void)
246{ 245{
247 int ret; 246 int ret;
248 u32 cfgchip2;
249 247
250 ret = davinci_cfg_reg_list(da850_hawk_usb11_pins); 248 ret = davinci_cfg_reg_list(da850_hawk_usb11_pins);
251 if (ret) { 249 if (ret) {
@@ -253,12 +251,15 @@ static __init void omapl138_hawk_usb_init(void)
253 return; 251 return;
254 } 252 }
255 253
256 /* Setup the Ref. clock frequency for the HAWK at 24 MHz. */ 254 ret = da8xx_register_usb20_phy_clk(false);
255 if (ret)
256 pr_warn("%s: USB 2.0 PHY CLK registration failed: %d\n",
257 __func__, ret);
257 258
258 cfgchip2 = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG)); 259 ret = da8xx_register_usb11_phy_clk(false);
259 cfgchip2 &= ~CFGCHIP2_REFFREQ_MASK; 260 if (ret)
260 cfgchip2 |= CFGCHIP2_REFFREQ_24MHZ; 261 pr_warn("%s: USB 1.1 PHY CLK registration failed: %d\n",
261 __raw_writel(cfgchip2, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG)); 262 __func__, ret);
262 263
263 ret = da8xx_register_usb_phy(); 264 ret = da8xx_register_usb_phy();
264 if (ret) 265 if (ret)
diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h
index 5e07d06f60e4..43322be26bd5 100644
--- a/arch/arm/mach-davinci/include/mach/da8xx.h
+++ b/arch/arm/mach-davinci/include/mach/da8xx.h
@@ -92,6 +92,9 @@ int da8xx_register_watchdog(void);
92int da8xx_register_usb_phy(void); 92int da8xx_register_usb_phy(void);
93int da8xx_register_usb20(unsigned mA, unsigned potpgt); 93int da8xx_register_usb20(unsigned mA, unsigned potpgt);
94int da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata); 94int da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata);
95int da8xx_register_usb_refclkin(int rate);
96int da8xx_register_usb20_phy_clk(bool use_usb_refclkin);
97int da8xx_register_usb11_phy_clk(bool use_usb_refclkin);
95int da8xx_register_emac(void); 98int da8xx_register_emac(void);
96int da8xx_register_uio_pruss(void); 99int da8xx_register_uio_pruss(void);
97int da8xx_register_lcdc(struct da8xx_lcdc_platform_data *pdata); 100int da8xx_register_lcdc(struct da8xx_lcdc_platform_data *pdata);
diff --git a/arch/arm/mach-davinci/usb-da8xx.c b/arch/arm/mach-davinci/usb-da8xx.c
index 4bb190380060..b010e5f80c5f 100644
--- a/arch/arm/mach-davinci/usb-da8xx.c
+++ b/arch/arm/mach-davinci/usb-da8xx.c
@@ -1,24 +1,38 @@
1/* 1/*
2 * DA8xx USB 2 * DA8xx USB
3 */ 3 */
4#include <linux/clk.h>
5#include <linux/delay.h>
4#include <linux/dma-mapping.h> 6#include <linux/dma-mapping.h>
5#include <linux/init.h> 7#include <linux/init.h>
8#include <linux/mfd/da8xx-cfgchip.h>
6#include <linux/phy/phy.h> 9#include <linux/phy/phy.h>
7#include <linux/platform_data/usb-davinci.h> 10#include <linux/platform_data/usb-davinci.h>
8#include <linux/platform_device.h> 11#include <linux/platform_device.h>
9#include <linux/usb/musb.h> 12#include <linux/usb/musb.h>
10 13
14#include <mach/clock.h>
11#include <mach/common.h> 15#include <mach/common.h>
12#include <mach/cputype.h> 16#include <mach/cputype.h>
13#include <mach/da8xx.h> 17#include <mach/da8xx.h>
14#include <mach/irqs.h> 18#include <mach/irqs.h>
15 19
20#include "clock.h"
21
16#define DA8XX_USB0_BASE 0x01e00000 22#define DA8XX_USB0_BASE 0x01e00000
17#define DA8XX_USB1_BASE 0x01e25000 23#define DA8XX_USB1_BASE 0x01e25000
18 24
19static struct platform_device da8xx_usb_phy = { 25static struct platform_device da8xx_usb_phy = {
20 .name = "da8xx-usb-phy", 26 .name = "da8xx-usb-phy",
21 .id = -1, 27 .id = -1,
28 .dev = {
29 /*
30 * Setting init_name so that clock lookup will work in
31 * da8xx_register_usb11_phy_clk() even if this device is not
32 * registered yet.
33 */
34 .init_name = "da8xx-usb-phy",
35 },
22}; 36};
23 37
24int __init da8xx_register_usb_phy(void) 38int __init da8xx_register_usb_phy(void)
@@ -26,8 +40,6 @@ int __init da8xx_register_usb_phy(void)
26 return platform_device_register(&da8xx_usb_phy); 40 return platform_device_register(&da8xx_usb_phy);
27} 41}
28 42
29#if IS_ENABLED(CONFIG_USB_MUSB_HDRC)
30
31static struct musb_hdrc_config musb_config = { 43static struct musb_hdrc_config musb_config = {
32 .multipoint = true, 44 .multipoint = true,
33 .num_eps = 5, 45 .num_eps = 5,
@@ -56,10 +68,15 @@ static struct resource da8xx_usb20_resources[] = {
56 68
57static u64 usb_dmamask = DMA_BIT_MASK(32); 69static u64 usb_dmamask = DMA_BIT_MASK(32);
58 70
59static struct platform_device usb_dev = { 71static struct platform_device da8xx_usb20_dev = {
60 .name = "musb-da8xx", 72 .name = "musb-da8xx",
61 .id = -1, 73 .id = -1,
62 .dev = { 74 .dev = {
75 /*
76 * Setting init_name so that clock lookup will work in
77 * usb20_phy_clk_enable() even if this device is not registered.
78 */
79 .init_name = "musb-da8xx",
63 .platform_data = &usb_data, 80 .platform_data = &usb_data,
64 .dma_mask = &usb_dmamask, 81 .dma_mask = &usb_dmamask,
65 .coherent_dma_mask = DMA_BIT_MASK(32), 82 .coherent_dma_mask = DMA_BIT_MASK(32),
@@ -73,18 +90,9 @@ int __init da8xx_register_usb20(unsigned int mA, unsigned int potpgt)
73 usb_data.power = mA > 510 ? 255 : mA / 2; 90 usb_data.power = mA > 510 ? 255 : mA / 2;
74 usb_data.potpgt = (potpgt + 1) / 2; 91 usb_data.potpgt = (potpgt + 1) / 2;
75 92
76 return platform_device_register(&usb_dev); 93 return platform_device_register(&da8xx_usb20_dev);
77}
78
79#else
80
81int __init da8xx_register_usb20(unsigned int mA, unsigned int potpgt)
82{
83 return 0;
84} 94}
85 95
86#endif /* CONFIG_USB_MUSB_HDRC */
87
88static struct resource da8xx_usb11_resources[] = { 96static struct resource da8xx_usb11_resources[] = {
89 [0] = { 97 [0] = {
90 .start = DA8XX_USB1_BASE, 98 .start = DA8XX_USB1_BASE,
@@ -116,3 +124,236 @@ int __init da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata)
116 da8xx_usb11_device.dev.platform_data = pdata; 124 da8xx_usb11_device.dev.platform_data = pdata;
117 return platform_device_register(&da8xx_usb11_device); 125 return platform_device_register(&da8xx_usb11_device);
118} 126}
127
128static struct clk usb_refclkin = {
129 .name = "usb_refclkin",
130 .set_rate = davinci_simple_set_rate,
131};
132
133static struct clk_lookup usb_refclkin_lookup =
134 CLK(NULL, "usb_refclkin", &usb_refclkin);
135
136/**
137 * da8xx_register_usb_refclkin - register USB_REFCLKIN clock
138 *
139 * @rate: The clock rate in Hz
140 *
141 * This clock is only needed if the board provides an external USB_REFCLKIN
142 * signal, in which case it will be used as the parent of usb20_phy_clk and/or
143 * usb11_phy_clk.
144 */
145int __init da8xx_register_usb_refclkin(int rate)
146{
147 int ret;
148
149 usb_refclkin.rate = rate;
150 ret = clk_register(&usb_refclkin);
151 if (ret)
152 return ret;
153
154 clkdev_add(&usb_refclkin_lookup);
155
156 return 0;
157}
158
159static void usb20_phy_clk_enable(struct clk *clk)
160{
161 struct clk *usb20_clk;
162 int err;
163 u32 val;
164 u32 timeout = 500000; /* 500 msec */
165
166 val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
167
168 usb20_clk = clk_get(&da8xx_usb20_dev.dev, "usb20");
169 if (IS_ERR(usb20_clk)) {
170 pr_err("could not get usb20 clk: %ld\n", PTR_ERR(usb20_clk));
171 return;
172 }
173
174 /* The USB 2.O PLL requires that the USB 2.O PSC is enabled as well. */
175 err = clk_prepare_enable(usb20_clk);
176 if (err) {
177 pr_err("failed to enable usb20 clk: %d\n", err);
178 clk_put(usb20_clk);
179 return;
180 }
181
182 /*
183 * Turn on the USB 2.0 PHY, but just the PLL, and not OTG. The USB 1.1
184 * host may use the PLL clock without USB 2.0 OTG being used.
185 */
186 val &= ~(CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN);
187 val |= CFGCHIP2_PHY_PLLON;
188
189 writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
190
191 while (--timeout) {
192 val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
193 if (val & CFGCHIP2_PHYCLKGD)
194 goto done;
195 udelay(1);
196 }
197
198 pr_err("Timeout waiting for USB 2.0 PHY clock good\n");
199done:
200 clk_disable_unprepare(usb20_clk);
201 clk_put(usb20_clk);
202}
203
204static void usb20_phy_clk_disable(struct clk *clk)
205{
206 u32 val;
207
208 val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
209 val |= CFGCHIP2_PHYPWRDN;
210 writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
211}
212
213static int usb20_phy_clk_set_parent(struct clk *clk, struct clk *parent)
214{
215 u32 val;
216
217 val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
218
219 /* Set the mux depending on the parent clock. */
220 if (parent == &usb_refclkin) {
221 val &= ~CFGCHIP2_USB2PHYCLKMUX;
222 } else if (strcmp(parent->name, "pll0_aux_clk") == 0) {
223 val |= CFGCHIP2_USB2PHYCLKMUX;
224 } else {
225 pr_err("Bad parent on USB 2.0 PHY clock\n");
226 return -EINVAL;
227 }
228
229 /* reference frequency also comes from parent clock */
230 val &= ~CFGCHIP2_REFFREQ_MASK;
231 switch (clk_get_rate(parent)) {
232 case 12000000:
233 val |= CFGCHIP2_REFFREQ_12MHZ;
234 break;
235 case 13000000:
236 val |= CFGCHIP2_REFFREQ_13MHZ;
237 break;
238 case 19200000:
239 val |= CFGCHIP2_REFFREQ_19_2MHZ;
240 break;
241 case 20000000:
242 val |= CFGCHIP2_REFFREQ_20MHZ;
243 break;
244 case 24000000:
245 val |= CFGCHIP2_REFFREQ_24MHZ;
246 break;
247 case 26000000:
248 val |= CFGCHIP2_REFFREQ_26MHZ;
249 break;
250 case 38400000:
251 val |= CFGCHIP2_REFFREQ_38_4MHZ;
252 break;
253 case 40000000:
254 val |= CFGCHIP2_REFFREQ_40MHZ;
255 break;
256 case 48000000:
257 val |= CFGCHIP2_REFFREQ_48MHZ;
258 break;
259 default:
260 pr_err("Bad parent clock rate on USB 2.0 PHY clock\n");
261 return -EINVAL;
262 }
263
264 writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
265
266 return 0;
267}
268
269static struct clk usb20_phy_clk = {
270 .name = "usb20_phy",
271 .clk_enable = usb20_phy_clk_enable,
272 .clk_disable = usb20_phy_clk_disable,
273 .set_parent = usb20_phy_clk_set_parent,
274};
275
276static struct clk_lookup usb20_phy_clk_lookup =
277 CLK("da8xx-usb-phy", "usb20_phy", &usb20_phy_clk);
278
279/**
280 * da8xx_register_usb20_phy_clk - register USB0PHYCLKMUX clock
281 *
282 * @use_usb_refclkin: Selects the parent clock - either "usb_refclkin" if true
283 * or "pll0_aux" if false.
284 */
285int __init da8xx_register_usb20_phy_clk(bool use_usb_refclkin)
286{
287 struct clk *parent;
288 int ret = 0;
289
290 parent = clk_get(NULL, use_usb_refclkin ? "usb_refclkin" : "pll0_aux");
291 if (IS_ERR(parent))
292 return PTR_ERR(parent);
293
294 usb20_phy_clk.parent = parent;
295 ret = clk_register(&usb20_phy_clk);
296 if (!ret)
297 clkdev_add(&usb20_phy_clk_lookup);
298
299 clk_put(parent);
300
301 return ret;
302}
303
304static int usb11_phy_clk_set_parent(struct clk *clk, struct clk *parent)
305{
306 u32 val;
307
308 val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
309
310 /* Set the USB 1.1 PHY clock mux based on the parent clock. */
311 if (parent == &usb20_phy_clk) {
312 val &= ~CFGCHIP2_USB1PHYCLKMUX;
313 } else if (parent == &usb_refclkin) {
314 val |= CFGCHIP2_USB1PHYCLKMUX;
315 } else {
316 pr_err("Bad parent on USB 1.1 PHY clock\n");
317 return -EINVAL;
318 }
319
320 writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
321
322 return 0;
323}
324
325static struct clk usb11_phy_clk = {
326 .name = "usb11_phy",
327 .set_parent = usb11_phy_clk_set_parent,
328};
329
330static struct clk_lookup usb11_phy_clk_lookup =
331 CLK("da8xx-usb-phy", "usb11_phy", &usb11_phy_clk);
332
333/**
334 * da8xx_register_usb11_phy_clk - register USB1PHYCLKMUX clock
335 *
336 * @use_usb_refclkin: Selects the parent clock - either "usb_refclkin" if true
337 * or "usb20_phy" if false.
338 */
339int __init da8xx_register_usb11_phy_clk(bool use_usb_refclkin)
340{
341 struct clk *parent;
342 int ret = 0;
343
344 if (use_usb_refclkin)
345 parent = clk_get(NULL, "usb_refclkin");
346 else
347 parent = clk_get(&da8xx_usb_phy.dev, "usb20_phy");
348 if (IS_ERR(parent))
349 return PTR_ERR(parent);
350
351 usb11_phy_clk.parent = parent;
352 ret = clk_register(&usb11_phy_clk);
353 if (!ret)
354 clkdev_add(&usb11_phy_clk_lookup);
355
356 clk_put(parent);
357
358 return ret;
359}