diff options
author | Manuel Lauss <manuel.lauss@gmail.com> | 2014-07-23 10:36:50 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2014-07-30 08:09:21 -0400 |
commit | 3feae78416ae2c30f12c0a4bbe2e5dddf029510d (patch) | |
tree | 8c4c9394e1a58526815c05f17ff09d34c770eb7d /arch | |
parent | 5a2fb71e7329dbcefbd08db8e44055c72ed52e90 (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.c | 47 |
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 | ||
390 | static inline void au1000_usb_init(unsigned long rb, int reg) | 391 | static 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 | } |
453 | out: | ||
454 | clk_put(c); | ||
427 | } | 455 | } |
428 | 456 | ||
429 | static inline int au1000_usb_control(int block, int enable, unsigned long rb, | 457 | static 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 | ||
570 | static int __init alchemy_usb_init(void) | 598 | static 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 | } |
593 | arch_initcall(alchemy_usb_init); | 626 | arch_initcall(alchemy_usb_init); |