diff options
author | Andreas Herrmann <andreas.herrmann@caviumnetworks.com> | 2015-01-06 07:48:56 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-01-09 15:29:57 -0500 |
commit | a95cfa6b86a19a822877e75d5a73b2a95d249e70 (patch) | |
tree | 8cf3d3f205e173af62fb9754f5632b9693bd940a /arch/mips/cavium-octeon | |
parent | 314b41b16a71ee824f55e2791fcb92997672da37 (diff) |
USB: host: Remove hard-coded octeon platform information for ehci/ohci
Instead rely on device tree information for ehci and ohci.
This was suggested with
http://www.linux-mips.org/cgi-bin/mesg.cgi?a=linux-mips&i=1401358203-60225-4-git-send-email-alex.smith%40imgtec.com
"The device tree will *always* have correct ehci/ohci clock
configuration, so use it. This allows us to remove a big chunk of
platform configuration code from octeon-platform.c."
More or less I rebased that patch on Alan's work to remove ehci-octeon
and ohci-octeon drivers.
Cc: David Daney <david.daney@cavium.com>
Cc: Alex Smith <alex.smith@imgtec.com>
Cc: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Andreas Herrmann <andreas.herrmann@caviumnetworks.com>
Acked-by: Ralf Baechle <ralf@linux-mips.org>
Tested-by: Aaro Koskinen <aaro.koskinen@iki.fi>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'arch/mips/cavium-octeon')
-rw-r--r-- | arch/mips/cavium-octeon/octeon-platform.c | 148 |
1 files changed, 62 insertions, 86 deletions
diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c index b67ddf0f8bcd..eea60b6c927b 100644 --- a/arch/mips/cavium-octeon/octeon-platform.c +++ b/arch/mips/cavium-octeon/octeon-platform.c | |||
@@ -77,7 +77,7 @@ static DEFINE_MUTEX(octeon2_usb_clocks_mutex); | |||
77 | 77 | ||
78 | static int octeon2_usb_clock_start_cnt; | 78 | static int octeon2_usb_clock_start_cnt; |
79 | 79 | ||
80 | static void octeon2_usb_clocks_start(void) | 80 | static void octeon2_usb_clocks_start(struct device *dev) |
81 | { | 81 | { |
82 | u64 div; | 82 | u64 div; |
83 | union cvmx_uctlx_if_ena if_ena; | 83 | union cvmx_uctlx_if_ena if_ena; |
@@ -86,6 +86,8 @@ static void octeon2_usb_clocks_start(void) | |||
86 | union cvmx_uctlx_uphy_portx_ctl_status port_ctl_status; | 86 | union cvmx_uctlx_uphy_portx_ctl_status port_ctl_status; |
87 | int i; | 87 | int i; |
88 | unsigned long io_clk_64_to_ns; | 88 | unsigned long io_clk_64_to_ns; |
89 | u32 clock_rate = 12000000; | ||
90 | bool is_crystal_clock = false; | ||
89 | 91 | ||
90 | 92 | ||
91 | mutex_lock(&octeon2_usb_clocks_mutex); | 93 | mutex_lock(&octeon2_usb_clocks_mutex); |
@@ -96,6 +98,28 @@ static void octeon2_usb_clocks_start(void) | |||
96 | 98 | ||
97 | io_clk_64_to_ns = 64000000000ull / octeon_get_io_clock_rate(); | 99 | io_clk_64_to_ns = 64000000000ull / octeon_get_io_clock_rate(); |
98 | 100 | ||
101 | if (dev->of_node) { | ||
102 | struct device_node *uctl_node; | ||
103 | const char *clock_type; | ||
104 | |||
105 | uctl_node = of_get_parent(dev->of_node); | ||
106 | if (!uctl_node) { | ||
107 | dev_err(dev, "No UCTL device node\n"); | ||
108 | goto exit; | ||
109 | } | ||
110 | i = of_property_read_u32(uctl_node, | ||
111 | "refclk-frequency", &clock_rate); | ||
112 | if (i) { | ||
113 | dev_err(dev, "No UCTL \"refclk-frequency\"\n"); | ||
114 | goto exit; | ||
115 | } | ||
116 | i = of_property_read_string(uctl_node, | ||
117 | "refclk-type", &clock_type); | ||
118 | |||
119 | if (!i && strcmp("crystal", clock_type) == 0) | ||
120 | is_crystal_clock = true; | ||
121 | } | ||
122 | |||
99 | /* | 123 | /* |
100 | * Step 1: Wait for voltages stable. That surely happened | 124 | * Step 1: Wait for voltages stable. That surely happened |
101 | * before starting the kernel. | 125 | * before starting the kernel. |
@@ -126,9 +150,22 @@ static void octeon2_usb_clocks_start(void) | |||
126 | cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); | 150 | cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); |
127 | 151 | ||
128 | /* 3b */ | 152 | /* 3b */ |
129 | /* 12MHz crystal. */ | 153 | clk_rst_ctl.s.p_refclk_sel = is_crystal_clock ? 0 : 1; |
130 | clk_rst_ctl.s.p_refclk_sel = 0; | 154 | switch (clock_rate) { |
131 | clk_rst_ctl.s.p_refclk_div = 0; | 155 | default: |
156 | pr_err("Invalid UCTL clock rate of %u, using 12000000 instead\n", | ||
157 | clock_rate); | ||
158 | /* Fall through */ | ||
159 | case 12000000: | ||
160 | clk_rst_ctl.s.p_refclk_div = 0; | ||
161 | break; | ||
162 | case 24000000: | ||
163 | clk_rst_ctl.s.p_refclk_div = 1; | ||
164 | break; | ||
165 | case 48000000: | ||
166 | clk_rst_ctl.s.p_refclk_div = 2; | ||
167 | break; | ||
168 | } | ||
132 | cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); | 169 | cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); |
133 | 170 | ||
134 | /* 3c */ | 171 | /* 3c */ |
@@ -259,7 +296,7 @@ static void octeon2_usb_clocks_stop(void) | |||
259 | 296 | ||
260 | static int octeon_ehci_power_on(struct platform_device *pdev) | 297 | static int octeon_ehci_power_on(struct platform_device *pdev) |
261 | { | 298 | { |
262 | octeon2_usb_clocks_start(); | 299 | octeon2_usb_clocks_start(&pdev->dev); |
263 | return 0; | 300 | return 0; |
264 | } | 301 | } |
265 | 302 | ||
@@ -277,11 +314,11 @@ static struct usb_ehci_pdata octeon_ehci_pdata = { | |||
277 | .power_off = octeon_ehci_power_off, | 314 | .power_off = octeon_ehci_power_off, |
278 | }; | 315 | }; |
279 | 316 | ||
280 | static void __init octeon_ehci_hw_start(void) | 317 | static void __init octeon_ehci_hw_start(struct device *dev) |
281 | { | 318 | { |
282 | union cvmx_uctlx_ehci_ctl ehci_ctl; | 319 | union cvmx_uctlx_ehci_ctl ehci_ctl; |
283 | 320 | ||
284 | octeon2_usb_clocks_start(); | 321 | octeon2_usb_clocks_start(dev); |
285 | 322 | ||
286 | ehci_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_EHCI_CTL(0)); | 323 | ehci_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_EHCI_CTL(0)); |
287 | /* Use 64-bit addressing. */ | 324 | /* Use 64-bit addressing. */ |
@@ -299,59 +336,28 @@ static u64 octeon_ehci_dma_mask = DMA_BIT_MASK(64); | |||
299 | static int __init octeon_ehci_device_init(void) | 336 | static int __init octeon_ehci_device_init(void) |
300 | { | 337 | { |
301 | struct platform_device *pd; | 338 | struct platform_device *pd; |
339 | struct device_node *ehci_node; | ||
302 | int ret = 0; | 340 | int ret = 0; |
303 | 341 | ||
304 | struct resource usb_resources[] = { | 342 | ehci_node = of_find_node_by_name(NULL, "ehci"); |
305 | { | 343 | if (!ehci_node) |
306 | .flags = IORESOURCE_MEM, | ||
307 | }, { | ||
308 | .flags = IORESOURCE_IRQ, | ||
309 | } | ||
310 | }; | ||
311 | |||
312 | /* Only Octeon2 has ehci/ohci */ | ||
313 | if (!OCTEON_IS_MODEL(OCTEON_CN63XX)) | ||
314 | return 0; | 344 | return 0; |
315 | 345 | ||
316 | if (octeon_is_simulation() || usb_disabled()) | 346 | pd = of_find_device_by_node(ehci_node); |
317 | return 0; /* No USB in the simulator. */ | 347 | if (!pd) |
318 | 348 | return 0; | |
319 | pd = platform_device_alloc("ehci-platform", 0); | ||
320 | if (!pd) { | ||
321 | ret = -ENOMEM; | ||
322 | goto out; | ||
323 | } | ||
324 | |||
325 | usb_resources[0].start = 0x00016F0000000000ULL; | ||
326 | usb_resources[0].end = usb_resources[0].start + 0x100; | ||
327 | |||
328 | usb_resources[1].start = OCTEON_IRQ_USB0; | ||
329 | usb_resources[1].end = OCTEON_IRQ_USB0; | ||
330 | |||
331 | ret = platform_device_add_resources(pd, usb_resources, | ||
332 | ARRAY_SIZE(usb_resources)); | ||
333 | if (ret) | ||
334 | goto fail; | ||
335 | 349 | ||
336 | pd->dev.dma_mask = &octeon_ehci_dma_mask; | 350 | pd->dev.dma_mask = &octeon_ehci_dma_mask; |
337 | pd->dev.platform_data = &octeon_ehci_pdata; | 351 | pd->dev.platform_data = &octeon_ehci_pdata; |
338 | octeon_ehci_hw_start(); | 352 | octeon_ehci_hw_start(&pd->dev); |
339 | |||
340 | ret = platform_device_add(pd); | ||
341 | if (ret) | ||
342 | goto fail; | ||
343 | 353 | ||
344 | return ret; | 354 | return ret; |
345 | fail: | ||
346 | platform_device_put(pd); | ||
347 | out: | ||
348 | return ret; | ||
349 | } | 355 | } |
350 | device_initcall(octeon_ehci_device_init); | 356 | device_initcall(octeon_ehci_device_init); |
351 | 357 | ||
352 | static int octeon_ohci_power_on(struct platform_device *pdev) | 358 | static int octeon_ohci_power_on(struct platform_device *pdev) |
353 | { | 359 | { |
354 | octeon2_usb_clocks_start(); | 360 | octeon2_usb_clocks_start(&pdev->dev); |
355 | return 0; | 361 | return 0; |
356 | } | 362 | } |
357 | 363 | ||
@@ -369,11 +375,11 @@ static struct usb_ohci_pdata octeon_ohci_pdata = { | |||
369 | .power_off = octeon_ohci_power_off, | 375 | .power_off = octeon_ohci_power_off, |
370 | }; | 376 | }; |
371 | 377 | ||
372 | static void __init octeon_ohci_hw_start(void) | 378 | static void __init octeon_ohci_hw_start(struct device *dev) |
373 | { | 379 | { |
374 | union cvmx_uctlx_ohci_ctl ohci_ctl; | 380 | union cvmx_uctlx_ohci_ctl ohci_ctl; |
375 | 381 | ||
376 | octeon2_usb_clocks_start(); | 382 | octeon2_usb_clocks_start(dev); |
377 | 383 | ||
378 | ohci_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_OHCI_CTL(0)); | 384 | ohci_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_OHCI_CTL(0)); |
379 | ohci_ctl.s.l2c_addr_msb = 0; | 385 | ohci_ctl.s.l2c_addr_msb = 0; |
@@ -387,57 +393,27 @@ static void __init octeon_ohci_hw_start(void) | |||
387 | static int __init octeon_ohci_device_init(void) | 393 | static int __init octeon_ohci_device_init(void) |
388 | { | 394 | { |
389 | struct platform_device *pd; | 395 | struct platform_device *pd; |
396 | struct device_node *ohci_node; | ||
390 | int ret = 0; | 397 | int ret = 0; |
391 | 398 | ||
392 | struct resource usb_resources[] = { | 399 | ohci_node = of_find_node_by_name(NULL, "ohci"); |
393 | { | 400 | if (!ohci_node) |
394 | .flags = IORESOURCE_MEM, | ||
395 | }, { | ||
396 | .flags = IORESOURCE_IRQ, | ||
397 | } | ||
398 | }; | ||
399 | |||
400 | /* Only Octeon2 has ehci/ohci */ | ||
401 | if (!OCTEON_IS_MODEL(OCTEON_CN63XX)) | ||
402 | return 0; | 401 | return 0; |
403 | 402 | ||
404 | if (octeon_is_simulation() || usb_disabled()) | 403 | pd = of_find_device_by_node(ohci_node); |
405 | return 0; /* No USB in the simulator. */ | 404 | if (!pd) |
406 | 405 | return 0; | |
407 | pd = platform_device_alloc("ohci-platform", 0); | ||
408 | if (!pd) { | ||
409 | ret = -ENOMEM; | ||
410 | goto out; | ||
411 | } | ||
412 | |||
413 | usb_resources[0].start = 0x00016F0000000400ULL; | ||
414 | usb_resources[0].end = usb_resources[0].start + 0x100; | ||
415 | |||
416 | usb_resources[1].start = OCTEON_IRQ_USB0; | ||
417 | usb_resources[1].end = OCTEON_IRQ_USB0; | ||
418 | |||
419 | ret = platform_device_add_resources(pd, usb_resources, | ||
420 | ARRAY_SIZE(usb_resources)); | ||
421 | if (ret) | ||
422 | goto fail; | ||
423 | 406 | ||
424 | pd->dev.platform_data = &octeon_ohci_pdata; | 407 | pd->dev.platform_data = &octeon_ohci_pdata; |
425 | octeon_ohci_hw_start(); | 408 | octeon_ohci_hw_start(&pd->dev); |
426 | |||
427 | ret = platform_device_add(pd); | ||
428 | if (ret) | ||
429 | goto fail; | ||
430 | 409 | ||
431 | return ret; | 410 | return ret; |
432 | fail: | ||
433 | platform_device_put(pd); | ||
434 | out: | ||
435 | return ret; | ||
436 | } | 411 | } |
437 | device_initcall(octeon_ohci_device_init); | 412 | device_initcall(octeon_ohci_device_init); |
438 | 413 | ||
439 | #endif /* CONFIG_USB */ | 414 | #endif /* CONFIG_USB */ |
440 | 415 | ||
416 | |||
441 | static struct of_device_id __initdata octeon_ids[] = { | 417 | static struct of_device_id __initdata octeon_ids[] = { |
442 | { .compatible = "simple-bus", }, | 418 | { .compatible = "simple-bus", }, |
443 | { .compatible = "cavium,octeon-6335-uctl", }, | 419 | { .compatible = "cavium,octeon-6335-uctl", }, |