diff options
Diffstat (limited to 'arch/arm/mach-omap2/clock.c')
| -rw-r--r-- | arch/arm/mach-omap2/clock.c | 57 |
1 files changed, 53 insertions, 4 deletions
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 9205ea7d8dde..e381d991092c 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c | |||
| @@ -26,17 +26,24 @@ | |||
| 26 | 26 | ||
| 27 | #include <asm/cpu.h> | 27 | #include <asm/cpu.h> |
| 28 | 28 | ||
| 29 | #include <plat/prcm.h> | ||
| 30 | 29 | ||
| 31 | #include <trace/events/power.h> | 30 | #include <trace/events/power.h> |
| 32 | 31 | ||
| 33 | #include "soc.h" | 32 | #include "soc.h" |
| 34 | #include "clockdomain.h" | 33 | #include "clockdomain.h" |
| 35 | #include "clock.h" | 34 | #include "clock.h" |
| 35 | #include "cm.h" | ||
| 36 | #include "cm2xxx.h" | 36 | #include "cm2xxx.h" |
| 37 | #include "cm3xxx.h" | 37 | #include "cm3xxx.h" |
| 38 | #include "cm-regbits-24xx.h" | 38 | #include "cm-regbits-24xx.h" |
| 39 | #include "cm-regbits-34xx.h" | 39 | #include "cm-regbits-34xx.h" |
| 40 | #include "common.h" | ||
| 41 | |||
| 42 | /* | ||
| 43 | * MAX_MODULE_ENABLE_WAIT: maximum of number of microseconds to wait | ||
| 44 | * for a module to indicate that it is no longer in idle | ||
| 45 | */ | ||
| 46 | #define MAX_MODULE_ENABLE_WAIT 100000 | ||
| 40 | 47 | ||
| 41 | u16 cpu_mask; | 48 | u16 cpu_mask; |
| 42 | 49 | ||
| @@ -58,6 +65,40 @@ static DEFINE_SPINLOCK(clockfw_lock); | |||
| 58 | 65 | ||
| 59 | /* Private functions */ | 66 | /* Private functions */ |
| 60 | 67 | ||
| 68 | |||
| 69 | /** | ||
| 70 | * _wait_idlest_generic - wait for a module to leave the idle state | ||
| 71 | * @reg: virtual address of module IDLEST register | ||
| 72 | * @mask: value to mask against to determine if the module is active | ||
| 73 | * @idlest: idle state indicator (0 or 1) for the clock | ||
| 74 | * @name: name of the clock (for printk) | ||
| 75 | * | ||
| 76 | * Wait for a module to leave idle, where its idle-status register is | ||
| 77 | * not inside the CM module. Returns 1 if the module left idle | ||
| 78 | * promptly, or 0 if the module did not leave idle before the timeout | ||
| 79 | * elapsed. XXX Deprecated - should be moved into drivers for the | ||
| 80 | * individual IP block that the IDLEST register exists in. | ||
| 81 | */ | ||
| 82 | static int _wait_idlest_generic(void __iomem *reg, u32 mask, u8 idlest, | ||
| 83 | const char *name) | ||
| 84 | { | ||
| 85 | int i = 0, ena = 0; | ||
| 86 | |||
| 87 | ena = (idlest) ? 0 : mask; | ||
| 88 | |||
| 89 | omap_test_timeout(((__raw_readl(reg) & mask) == ena), | ||
| 90 | MAX_MODULE_ENABLE_WAIT, i); | ||
| 91 | |||
| 92 | if (i < MAX_MODULE_ENABLE_WAIT) | ||
| 93 | pr_debug("omap clock: module associated with clock %s ready after %d loops\n", | ||
| 94 | name, i); | ||
| 95 | else | ||
| 96 | pr_err("omap clock: module associated with clock %s didn't enable in %d tries\n", | ||
| 97 | name, MAX_MODULE_ENABLE_WAIT); | ||
| 98 | |||
| 99 | return (i < MAX_MODULE_ENABLE_WAIT) ? 1 : 0; | ||
| 100 | }; | ||
| 101 | |||
| 61 | /** | 102 | /** |
| 62 | * _omap2_module_wait_ready - wait for an OMAP module to leave IDLE | 103 | * _omap2_module_wait_ready - wait for an OMAP module to leave IDLE |
| 63 | * @clk: struct clk * belonging to the module | 104 | * @clk: struct clk * belonging to the module |
| @@ -71,7 +112,9 @@ static DEFINE_SPINLOCK(clockfw_lock); | |||
| 71 | static void _omap2_module_wait_ready(struct clk *clk) | 112 | static void _omap2_module_wait_ready(struct clk *clk) |
| 72 | { | 113 | { |
| 73 | void __iomem *companion_reg, *idlest_reg; | 114 | void __iomem *companion_reg, *idlest_reg; |
| 74 | u8 other_bit, idlest_bit, idlest_val; | 115 | u8 other_bit, idlest_bit, idlest_val, idlest_reg_id; |
| 116 | s16 prcm_mod; | ||
| 117 | int r; | ||
| 75 | 118 | ||
| 76 | /* Not all modules have multiple clocks that their IDLEST depends on */ | 119 | /* Not all modules have multiple clocks that their IDLEST depends on */ |
| 77 | if (clk->ops->find_companion) { | 120 | if (clk->ops->find_companion) { |
| @@ -82,8 +125,14 @@ static void _omap2_module_wait_ready(struct clk *clk) | |||
| 82 | 125 | ||
| 83 | clk->ops->find_idlest(clk, &idlest_reg, &idlest_bit, &idlest_val); | 126 | clk->ops->find_idlest(clk, &idlest_reg, &idlest_bit, &idlest_val); |
| 84 | 127 | ||
| 85 | omap2_cm_wait_idlest(idlest_reg, (1 << idlest_bit), idlest_val, | 128 | r = cm_split_idlest_reg(idlest_reg, &prcm_mod, &idlest_reg_id); |
| 86 | __clk_get_name(clk)); | 129 | if (r) { |
| 130 | /* IDLEST register not in the CM module */ | ||
| 131 | _wait_idlest_generic(idlest_reg, (1 << idlest_bit), idlest_val, | ||
| 132 | clk->name); | ||
| 133 | } else { | ||
| 134 | cm_wait_module_ready(prcm_mod, idlest_reg_id, idlest_bit); | ||
| 135 | }; | ||
| 87 | } | 136 | } |
| 88 | 137 | ||
| 89 | /* Public functions */ | 138 | /* Public functions */ |
