aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorManuel Lauss <manuel.lauss@gmail.com>2014-07-23 10:36:50 -0400
committerRalf Baechle <ralf@linux-mips.org>2014-07-30 08:09:21 -0400
commit3feae78416ae2c30f12c0a4bbe2e5dddf029510d (patch)
tree8c4c9394e1a58526815c05f17ff09d34c770eb7d /arch
parent5a2fb71e7329dbcefbd08db8e44055c72ed52e90 (diff)
MIPS: Alchemy: usb: use clk framework
Add use of the common clock framework to set and enable the 48MHz clock source for the onchip OHCI and UDC blocks. Tested on a DB1500. (Au1200 and Au1300 use an external 48MHz crystal). Signed-off-by: Manuel Lauss <manuel.lauss@gmail.com> Cc: Linux-MIPS <linux-mips@linux-mips.org> Patchwork: https://patchwork.linux-mips.org/patch/7467/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/mips/alchemy/common/usb.c47
1 files changed, 40 insertions, 7 deletions
diff --git a/arch/mips/alchemy/common/usb.c b/arch/mips/alchemy/common/usb.c
index d193dbea84a1..297805ade849 100644
--- a/arch/mips/alchemy/common/usb.c
+++ b/arch/mips/alchemy/common/usb.c
@@ -9,6 +9,7 @@
9 * 9 *
10 */ 10 */
11 11
12#include <linux/clk.h>
12#include <linux/init.h> 13#include <linux/init.h>
13#include <linux/io.h> 14#include <linux/io.h>
14#include <linux/module.h> 15#include <linux/module.h>
@@ -387,10 +388,25 @@ static inline void au1200_usb_init(void)
387 udelay(1000); 388 udelay(1000);
388} 389}
389 390
390static inline void au1000_usb_init(unsigned long rb, int reg) 391static inline int au1000_usb_init(unsigned long rb, int reg)
391{ 392{
392 void __iomem *base = (void __iomem *)KSEG1ADDR(rb + reg); 393 void __iomem *base = (void __iomem *)KSEG1ADDR(rb + reg);
393 unsigned long r = __raw_readl(base); 394 unsigned long r = __raw_readl(base);
395 struct clk *c;
396
397 /* 48MHz check. Don't init if no one can provide it */
398 c = clk_get(NULL, "usbh_clk");
399 if (IS_ERR(c))
400 return -ENODEV;
401 if (clk_round_rate(c, 48000000) != 48000000) {
402 clk_put(c);
403 return -ENODEV;
404 }
405 if (clk_set_rate(c, 48000000)) {
406 clk_put(c);
407 return -ENODEV;
408 }
409 clk_put(c);
394 410
395#if defined(__BIG_ENDIAN) 411#if defined(__BIG_ENDIAN)
396 r |= USBHEN_BE; 412 r |= USBHEN_BE;
@@ -400,6 +416,8 @@ static inline void au1000_usb_init(unsigned long rb, int reg)
400 __raw_writel(r, base); 416 __raw_writel(r, base);
401 wmb(); 417 wmb();
402 udelay(1000); 418 udelay(1000);
419
420 return 0;
403} 421}
404 422
405 423
@@ -407,8 +425,15 @@ static inline void __au1xx0_ohci_control(int enable, unsigned long rb, int creg)
407{ 425{
408 void __iomem *base = (void __iomem *)KSEG1ADDR(rb); 426 void __iomem *base = (void __iomem *)KSEG1ADDR(rb);
409 unsigned long r = __raw_readl(base + creg); 427 unsigned long r = __raw_readl(base + creg);
428 struct clk *c = clk_get(NULL, "usbh_clk");
429
430 if (IS_ERR(c))
431 return;
410 432
411 if (enable) { 433 if (enable) {
434 if (clk_prepare_enable(c))
435 goto out;
436
412 __raw_writel(r | USBHEN_CE, base + creg); 437 __raw_writel(r | USBHEN_CE, base + creg);
413 wmb(); 438 wmb();
414 udelay(1000); 439 udelay(1000);
@@ -423,7 +448,10 @@ static inline void __au1xx0_ohci_control(int enable, unsigned long rb, int creg)
423 } else { 448 } else {
424 __raw_writel(r & ~(USBHEN_CE | USBHEN_E), base + creg); 449 __raw_writel(r & ~(USBHEN_CE | USBHEN_E), base + creg);
425 wmb(); 450 wmb();
451 clk_disable_unprepare(c);
426 } 452 }
453out:
454 clk_put(c);
427} 455}
428 456
429static inline int au1000_usb_control(int block, int enable, unsigned long rb, 457static inline int au1000_usb_control(int block, int enable, unsigned long rb,
@@ -457,11 +485,11 @@ int alchemy_usb_control(int block, int enable)
457 case ALCHEMY_CPU_AU1500: 485 case ALCHEMY_CPU_AU1500:
458 case ALCHEMY_CPU_AU1100: 486 case ALCHEMY_CPU_AU1100:
459 ret = au1000_usb_control(block, enable, 487 ret = au1000_usb_control(block, enable,
460 AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG); 488 AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG);
461 break; 489 break;
462 case ALCHEMY_CPU_AU1550: 490 case ALCHEMY_CPU_AU1550:
463 ret = au1000_usb_control(block, enable, 491 ret = au1000_usb_control(block, enable,
464 AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG); 492 AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG);
465 break; 493 break;
466 case ALCHEMY_CPU_AU1200: 494 case ALCHEMY_CPU_AU1200:
467 ret = au1200_usb_control(block, enable); 495 ret = au1200_usb_control(block, enable);
@@ -569,14 +597,18 @@ static struct syscore_ops alchemy_usb_pm_ops = {
569 597
570static int __init alchemy_usb_init(void) 598static int __init alchemy_usb_init(void)
571{ 599{
600 int ret = 0;
601
572 switch (alchemy_get_cputype()) { 602 switch (alchemy_get_cputype()) {
573 case ALCHEMY_CPU_AU1000: 603 case ALCHEMY_CPU_AU1000:
574 case ALCHEMY_CPU_AU1500: 604 case ALCHEMY_CPU_AU1500:
575 case ALCHEMY_CPU_AU1100: 605 case ALCHEMY_CPU_AU1100:
576 au1000_usb_init(AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG); 606 ret = au1000_usb_init(AU1000_USB_OHCI_PHYS_ADDR,
607 AU1000_OHCICFG);
577 break; 608 break;
578 case ALCHEMY_CPU_AU1550: 609 case ALCHEMY_CPU_AU1550:
579 au1000_usb_init(AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG); 610 ret = au1000_usb_init(AU1550_USB_OHCI_PHYS_ADDR,
611 AU1550_OHCICFG);
580 break; 612 break;
581 case ALCHEMY_CPU_AU1200: 613 case ALCHEMY_CPU_AU1200:
582 au1200_usb_init(); 614 au1200_usb_init();
@@ -586,8 +618,9 @@ static int __init alchemy_usb_init(void)
586 break; 618 break;
587 } 619 }
588 620
589 register_syscore_ops(&alchemy_usb_pm_ops); 621 if (!ret)
622 register_syscore_ops(&alchemy_usb_pm_ops);
590 623
591 return 0; 624 return ret;
592} 625}
593arch_initcall(alchemy_usb_init); 626arch_initcall(alchemy_usb_init);