diff options
Diffstat (limited to 'arch/arm/mach-omap2/omap_hwmod.c')
-rw-r--r-- | arch/arm/mach-omap2/omap_hwmod.c | 271 |
1 files changed, 209 insertions, 62 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index b969ab1d258b..4653efb87a27 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c | |||
@@ -130,7 +130,7 @@ | |||
130 | #include <linux/kernel.h> | 130 | #include <linux/kernel.h> |
131 | #include <linux/errno.h> | 131 | #include <linux/errno.h> |
132 | #include <linux/io.h> | 132 | #include <linux/io.h> |
133 | #include <linux/clk.h> | 133 | #include <linux/clk-provider.h> |
134 | #include <linux/delay.h> | 134 | #include <linux/delay.h> |
135 | #include <linux/err.h> | 135 | #include <linux/err.h> |
136 | #include <linux/list.h> | 136 | #include <linux/list.h> |
@@ -139,27 +139,25 @@ | |||
139 | #include <linux/slab.h> | 139 | #include <linux/slab.h> |
140 | #include <linux/bootmem.h> | 140 | #include <linux/bootmem.h> |
141 | 141 | ||
142 | #include <plat/clock.h> | 142 | #include "clock.h" |
143 | #include <plat/omap_hwmod.h> | 143 | #include "omap_hwmod.h" |
144 | #include <plat/prcm.h> | ||
145 | 144 | ||
146 | #include "soc.h" | 145 | #include "soc.h" |
147 | #include "common.h" | 146 | #include "common.h" |
148 | #include "clockdomain.h" | 147 | #include "clockdomain.h" |
149 | #include "powerdomain.h" | 148 | #include "powerdomain.h" |
150 | #include "cm2xxx_3xxx.h" | 149 | #include "cm2xxx.h" |
150 | #include "cm3xxx.h" | ||
151 | #include "cminst44xx.h" | 151 | #include "cminst44xx.h" |
152 | #include "cm33xx.h" | 152 | #include "cm33xx.h" |
153 | #include "prm2xxx_3xxx.h" | 153 | #include "prm.h" |
154 | #include "prm3xxx.h" | ||
154 | #include "prm44xx.h" | 155 | #include "prm44xx.h" |
155 | #include "prm33xx.h" | 156 | #include "prm33xx.h" |
156 | #include "prminst44xx.h" | 157 | #include "prminst44xx.h" |
157 | #include "mux.h" | 158 | #include "mux.h" |
158 | #include "pm.h" | 159 | #include "pm.h" |
159 | 160 | ||
160 | /* Maximum microseconds to wait for OMAP module to softreset */ | ||
161 | #define MAX_MODULE_SOFTRESET_WAIT 10000 | ||
162 | |||
163 | /* Name of the OMAP hwmod for the MPU */ | 161 | /* Name of the OMAP hwmod for the MPU */ |
164 | #define MPU_INITIATOR_NAME "mpu" | 162 | #define MPU_INITIATOR_NAME "mpu" |
165 | 163 | ||
@@ -189,6 +187,8 @@ struct omap_hwmod_soc_ops { | |||
189 | int (*is_hardreset_asserted)(struct omap_hwmod *oh, | 187 | int (*is_hardreset_asserted)(struct omap_hwmod *oh, |
190 | struct omap_hwmod_rst_info *ohri); | 188 | struct omap_hwmod_rst_info *ohri); |
191 | int (*init_clkdm)(struct omap_hwmod *oh); | 189 | int (*init_clkdm)(struct omap_hwmod *oh); |
190 | void (*update_context_lost)(struct omap_hwmod *oh); | ||
191 | int (*get_context_lost)(struct omap_hwmod *oh); | ||
192 | }; | 192 | }; |
193 | 193 | ||
194 | /* soc_ops: adapts the omap_hwmod code to the currently-booted SoC */ | 194 | /* soc_ops: adapts the omap_hwmod code to the currently-booted SoC */ |
@@ -422,6 +422,38 @@ static int _set_softreset(struct omap_hwmod *oh, u32 *v) | |||
422 | } | 422 | } |
423 | 423 | ||
424 | /** | 424 | /** |
425 | * _wait_softreset_complete - wait for an OCP softreset to complete | ||
426 | * @oh: struct omap_hwmod * to wait on | ||
427 | * | ||
428 | * Wait until the IP block represented by @oh reports that its OCP | ||
429 | * softreset is complete. This can be triggered by software (see | ||
430 | * _ocp_softreset()) or by hardware upon returning from off-mode (one | ||
431 | * example is HSMMC). Waits for up to MAX_MODULE_SOFTRESET_WAIT | ||
432 | * microseconds. Returns the number of microseconds waited. | ||
433 | */ | ||
434 | static int _wait_softreset_complete(struct omap_hwmod *oh) | ||
435 | { | ||
436 | struct omap_hwmod_class_sysconfig *sysc; | ||
437 | u32 softrst_mask; | ||
438 | int c = 0; | ||
439 | |||
440 | sysc = oh->class->sysc; | ||
441 | |||
442 | if (sysc->sysc_flags & SYSS_HAS_RESET_STATUS) | ||
443 | omap_test_timeout((omap_hwmod_read(oh, sysc->syss_offs) | ||
444 | & SYSS_RESETDONE_MASK), | ||
445 | MAX_MODULE_SOFTRESET_WAIT, c); | ||
446 | else if (sysc->sysc_flags & SYSC_HAS_RESET_STATUS) { | ||
447 | softrst_mask = (0x1 << sysc->sysc_fields->srst_shift); | ||
448 | omap_test_timeout(!(omap_hwmod_read(oh, sysc->sysc_offs) | ||
449 | & softrst_mask), | ||
450 | MAX_MODULE_SOFTRESET_WAIT, c); | ||
451 | } | ||
452 | |||
453 | return c; | ||
454 | } | ||
455 | |||
456 | /** | ||
425 | * _set_dmadisable: set OCP_SYSCONFIG.DMADISABLE bit in @v | 457 | * _set_dmadisable: set OCP_SYSCONFIG.DMADISABLE bit in @v |
426 | * @oh: struct omap_hwmod * | 458 | * @oh: struct omap_hwmod * |
427 | * | 459 | * |
@@ -616,6 +648,19 @@ static int _disable_wakeup(struct omap_hwmod *oh, u32 *v) | |||
616 | return 0; | 648 | return 0; |
617 | } | 649 | } |
618 | 650 | ||
651 | static struct clockdomain *_get_clkdm(struct omap_hwmod *oh) | ||
652 | { | ||
653 | struct clk_hw_omap *clk; | ||
654 | |||
655 | if (oh->clkdm) { | ||
656 | return oh->clkdm; | ||
657 | } else if (oh->_clk) { | ||
658 | clk = to_clk_hw_omap(__clk_get_hw(oh->_clk)); | ||
659 | return clk->clkdm; | ||
660 | } | ||
661 | return NULL; | ||
662 | } | ||
663 | |||
619 | /** | 664 | /** |
620 | * _add_initiator_dep: prevent @oh from smart-idling while @init_oh is active | 665 | * _add_initiator_dep: prevent @oh from smart-idling while @init_oh is active |
621 | * @oh: struct omap_hwmod * | 666 | * @oh: struct omap_hwmod * |
@@ -631,13 +676,18 @@ static int _disable_wakeup(struct omap_hwmod *oh, u32 *v) | |||
631 | */ | 676 | */ |
632 | static int _add_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh) | 677 | static int _add_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh) |
633 | { | 678 | { |
634 | if (!oh->_clk) | 679 | struct clockdomain *clkdm, *init_clkdm; |
680 | |||
681 | clkdm = _get_clkdm(oh); | ||
682 | init_clkdm = _get_clkdm(init_oh); | ||
683 | |||
684 | if (!clkdm || !init_clkdm) | ||
635 | return -EINVAL; | 685 | return -EINVAL; |
636 | 686 | ||
637 | if (oh->_clk->clkdm && oh->_clk->clkdm->flags & CLKDM_NO_AUTODEPS) | 687 | if (clkdm && clkdm->flags & CLKDM_NO_AUTODEPS) |
638 | return 0; | 688 | return 0; |
639 | 689 | ||
640 | return clkdm_add_sleepdep(oh->_clk->clkdm, init_oh->_clk->clkdm); | 690 | return clkdm_add_sleepdep(clkdm, init_clkdm); |
641 | } | 691 | } |
642 | 692 | ||
643 | /** | 693 | /** |
@@ -655,13 +705,18 @@ static int _add_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh) | |||
655 | */ | 705 | */ |
656 | static int _del_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh) | 706 | static int _del_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh) |
657 | { | 707 | { |
658 | if (!oh->_clk) | 708 | struct clockdomain *clkdm, *init_clkdm; |
709 | |||
710 | clkdm = _get_clkdm(oh); | ||
711 | init_clkdm = _get_clkdm(init_oh); | ||
712 | |||
713 | if (!clkdm || !init_clkdm) | ||
659 | return -EINVAL; | 714 | return -EINVAL; |
660 | 715 | ||
661 | if (oh->_clk->clkdm && oh->_clk->clkdm->flags & CLKDM_NO_AUTODEPS) | 716 | if (clkdm && clkdm->flags & CLKDM_NO_AUTODEPS) |
662 | return 0; | 717 | return 0; |
663 | 718 | ||
664 | return clkdm_del_sleepdep(oh->_clk->clkdm, init_oh->_clk->clkdm); | 719 | return clkdm_del_sleepdep(clkdm, init_clkdm); |
665 | } | 720 | } |
666 | 721 | ||
667 | /** | 722 | /** |
@@ -695,7 +750,7 @@ static int _init_main_clk(struct omap_hwmod *oh) | |||
695 | */ | 750 | */ |
696 | clk_prepare(oh->_clk); | 751 | clk_prepare(oh->_clk); |
697 | 752 | ||
698 | if (!oh->_clk->clkdm) | 753 | if (!_get_clkdm(oh)) |
699 | pr_debug("omap_hwmod: %s: missing clockdomain for %s.\n", | 754 | pr_debug("omap_hwmod: %s: missing clockdomain for %s.\n", |
700 | oh->name, oh->main_clk); | 755 | oh->name, oh->main_clk); |
701 | 756 | ||
@@ -1278,18 +1333,29 @@ static void _enable_sysc(struct omap_hwmod *oh) | |||
1278 | u8 idlemode, sf; | 1333 | u8 idlemode, sf; |
1279 | u32 v; | 1334 | u32 v; |
1280 | bool clkdm_act; | 1335 | bool clkdm_act; |
1336 | struct clockdomain *clkdm; | ||
1281 | 1337 | ||
1282 | if (!oh->class->sysc) | 1338 | if (!oh->class->sysc) |
1283 | return; | 1339 | return; |
1284 | 1340 | ||
1341 | /* | ||
1342 | * Wait until reset has completed, this is needed as the IP | ||
1343 | * block is reset automatically by hardware in some cases | ||
1344 | * (off-mode for example), and the drivers require the | ||
1345 | * IP to be ready when they access it | ||
1346 | */ | ||
1347 | if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET) | ||
1348 | _enable_optional_clocks(oh); | ||
1349 | _wait_softreset_complete(oh); | ||
1350 | if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET) | ||
1351 | _disable_optional_clocks(oh); | ||
1352 | |||
1285 | v = oh->_sysc_cache; | 1353 | v = oh->_sysc_cache; |
1286 | sf = oh->class->sysc->sysc_flags; | 1354 | sf = oh->class->sysc->sysc_flags; |
1287 | 1355 | ||
1356 | clkdm = _get_clkdm(oh); | ||
1288 | if (sf & SYSC_HAS_SIDLEMODE) { | 1357 | if (sf & SYSC_HAS_SIDLEMODE) { |
1289 | clkdm_act = ((oh->clkdm && | 1358 | clkdm_act = (clkdm && clkdm->flags & CLKDM_ACTIVE_WITH_MPU); |
1290 | oh->clkdm->flags & CLKDM_ACTIVE_WITH_MPU) || | ||
1291 | (oh->_clk && oh->_clk->clkdm && | ||
1292 | oh->_clk->clkdm->flags & CLKDM_ACTIVE_WITH_MPU)); | ||
1293 | if (clkdm_act && !(oh->class->sysc->idlemodes & | 1359 | if (clkdm_act && !(oh->class->sysc->idlemodes & |
1294 | (SIDLE_SMART | SIDLE_SMART_WKUP))) | 1360 | (SIDLE_SMART | SIDLE_SMART_WKUP))) |
1295 | idlemode = HWMOD_IDLEMODE_FORCE; | 1361 | idlemode = HWMOD_IDLEMODE_FORCE; |
@@ -1491,11 +1557,12 @@ static int _init_clocks(struct omap_hwmod *oh, void *data) | |||
1491 | 1557 | ||
1492 | pr_debug("omap_hwmod: %s: looking up clocks\n", oh->name); | 1558 | pr_debug("omap_hwmod: %s: looking up clocks\n", oh->name); |
1493 | 1559 | ||
1560 | if (soc_ops.init_clkdm) | ||
1561 | ret |= soc_ops.init_clkdm(oh); | ||
1562 | |||
1494 | ret |= _init_main_clk(oh); | 1563 | ret |= _init_main_clk(oh); |
1495 | ret |= _init_interface_clks(oh); | 1564 | ret |= _init_interface_clks(oh); |
1496 | ret |= _init_opt_clks(oh); | 1565 | ret |= _init_opt_clks(oh); |
1497 | if (soc_ops.init_clkdm) | ||
1498 | ret |= soc_ops.init_clkdm(oh); | ||
1499 | 1566 | ||
1500 | if (!ret) | 1567 | if (!ret) |
1501 | oh->_state = _HWMOD_STATE_CLKS_INITED; | 1568 | oh->_state = _HWMOD_STATE_CLKS_INITED; |
@@ -1804,7 +1871,7 @@ static int _am33xx_disable_module(struct omap_hwmod *oh) | |||
1804 | */ | 1871 | */ |
1805 | static int _ocp_softreset(struct omap_hwmod *oh) | 1872 | static int _ocp_softreset(struct omap_hwmod *oh) |
1806 | { | 1873 | { |
1807 | u32 v, softrst_mask; | 1874 | u32 v; |
1808 | int c = 0; | 1875 | int c = 0; |
1809 | int ret = 0; | 1876 | int ret = 0; |
1810 | 1877 | ||
@@ -1834,19 +1901,7 @@ static int _ocp_softreset(struct omap_hwmod *oh) | |||
1834 | if (oh->class->sysc->srst_udelay) | 1901 | if (oh->class->sysc->srst_udelay) |
1835 | udelay(oh->class->sysc->srst_udelay); | 1902 | udelay(oh->class->sysc->srst_udelay); |
1836 | 1903 | ||
1837 | if (oh->class->sysc->sysc_flags & SYSS_HAS_RESET_STATUS) | 1904 | c = _wait_softreset_complete(oh); |
1838 | omap_test_timeout((omap_hwmod_read(oh, | ||
1839 | oh->class->sysc->syss_offs) | ||
1840 | & SYSS_RESETDONE_MASK), | ||
1841 | MAX_MODULE_SOFTRESET_WAIT, c); | ||
1842 | else if (oh->class->sysc->sysc_flags & SYSC_HAS_RESET_STATUS) { | ||
1843 | softrst_mask = (0x1 << oh->class->sysc->sysc_fields->srst_shift); | ||
1844 | omap_test_timeout(!(omap_hwmod_read(oh, | ||
1845 | oh->class->sysc->sysc_offs) | ||
1846 | & softrst_mask), | ||
1847 | MAX_MODULE_SOFTRESET_WAIT, c); | ||
1848 | } | ||
1849 | |||
1850 | if (c == MAX_MODULE_SOFTRESET_WAIT) | 1905 | if (c == MAX_MODULE_SOFTRESET_WAIT) |
1851 | pr_warning("omap_hwmod: %s: softreset failed (waited %d usec)\n", | 1906 | pr_warning("omap_hwmod: %s: softreset failed (waited %d usec)\n", |
1852 | oh->name, MAX_MODULE_SOFTRESET_WAIT); | 1907 | oh->name, MAX_MODULE_SOFTRESET_WAIT); |
@@ -1962,6 +2017,42 @@ static void _reconfigure_io_chain(void) | |||
1962 | } | 2017 | } |
1963 | 2018 | ||
1964 | /** | 2019 | /** |
2020 | * _omap4_update_context_lost - increment hwmod context loss counter if | ||
2021 | * hwmod context was lost, and clear hardware context loss reg | ||
2022 | * @oh: hwmod to check for context loss | ||
2023 | * | ||
2024 | * If the PRCM indicates that the hwmod @oh lost context, increment | ||
2025 | * our in-memory context loss counter, and clear the RM_*_CONTEXT | ||
2026 | * bits. No return value. | ||
2027 | */ | ||
2028 | static void _omap4_update_context_lost(struct omap_hwmod *oh) | ||
2029 | { | ||
2030 | if (oh->prcm.omap4.flags & HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT) | ||
2031 | return; | ||
2032 | |||
2033 | if (!prm_was_any_context_lost_old(oh->clkdm->pwrdm.ptr->prcm_partition, | ||
2034 | oh->clkdm->pwrdm.ptr->prcm_offs, | ||
2035 | oh->prcm.omap4.context_offs)) | ||
2036 | return; | ||
2037 | |||
2038 | oh->prcm.omap4.context_lost_counter++; | ||
2039 | prm_clear_context_loss_flags_old(oh->clkdm->pwrdm.ptr->prcm_partition, | ||
2040 | oh->clkdm->pwrdm.ptr->prcm_offs, | ||
2041 | oh->prcm.omap4.context_offs); | ||
2042 | } | ||
2043 | |||
2044 | /** | ||
2045 | * _omap4_get_context_lost - get context loss counter for a hwmod | ||
2046 | * @oh: hwmod to get context loss counter for | ||
2047 | * | ||
2048 | * Returns the in-memory context loss counter for a hwmod. | ||
2049 | */ | ||
2050 | static int _omap4_get_context_lost(struct omap_hwmod *oh) | ||
2051 | { | ||
2052 | return oh->prcm.omap4.context_lost_counter; | ||
2053 | } | ||
2054 | |||
2055 | /** | ||
1965 | * _enable - enable an omap_hwmod | 2056 | * _enable - enable an omap_hwmod |
1966 | * @oh: struct omap_hwmod * | 2057 | * @oh: struct omap_hwmod * |
1967 | * | 2058 | * |
@@ -2044,6 +2135,9 @@ static int _enable(struct omap_hwmod *oh) | |||
2044 | if (soc_ops.enable_module) | 2135 | if (soc_ops.enable_module) |
2045 | soc_ops.enable_module(oh); | 2136 | soc_ops.enable_module(oh); |
2046 | 2137 | ||
2138 | if (soc_ops.update_context_lost) | ||
2139 | soc_ops.update_context_lost(oh); | ||
2140 | |||
2047 | r = (soc_ops.wait_target_ready) ? soc_ops.wait_target_ready(oh) : | 2141 | r = (soc_ops.wait_target_ready) ? soc_ops.wait_target_ready(oh) : |
2048 | -EINVAL; | 2142 | -EINVAL; |
2049 | if (!r) { | 2143 | if (!r) { |
@@ -2063,7 +2157,8 @@ static int _enable(struct omap_hwmod *oh) | |||
2063 | _enable_sysc(oh); | 2157 | _enable_sysc(oh); |
2064 | } | 2158 | } |
2065 | } else { | 2159 | } else { |
2066 | _omap4_disable_module(oh); | 2160 | if (soc_ops.disable_module) |
2161 | soc_ops.disable_module(oh); | ||
2067 | _disable_clocks(oh); | 2162 | _disable_clocks(oh); |
2068 | pr_debug("omap_hwmod: %s: _wait_target_ready: %d\n", | 2163 | pr_debug("omap_hwmod: %s: _wait_target_ready: %d\n", |
2069 | oh->name, r); | 2164 | oh->name, r); |
@@ -2352,6 +2447,9 @@ static int __init _setup_reset(struct omap_hwmod *oh) | |||
2352 | if (oh->_state != _HWMOD_STATE_INITIALIZED) | 2447 | if (oh->_state != _HWMOD_STATE_INITIALIZED) |
2353 | return -EINVAL; | 2448 | return -EINVAL; |
2354 | 2449 | ||
2450 | if (oh->flags & HWMOD_EXT_OPT_MAIN_CLK) | ||
2451 | return -EPERM; | ||
2452 | |||
2355 | if (oh->rst_lines_cnt == 0) { | 2453 | if (oh->rst_lines_cnt == 0) { |
2356 | r = _enable(oh); | 2454 | r = _enable(oh); |
2357 | if (r) { | 2455 | if (r) { |
@@ -2668,7 +2766,7 @@ static int __init _alloc_linkspace(struct omap_hwmod_ocp_if **ois) | |||
2668 | /* Static functions intended only for use in soc_ops field function pointers */ | 2766 | /* Static functions intended only for use in soc_ops field function pointers */ |
2669 | 2767 | ||
2670 | /** | 2768 | /** |
2671 | * _omap2_wait_target_ready - wait for a module to leave slave idle | 2769 | * _omap2xxx_wait_target_ready - wait for a module to leave slave idle |
2672 | * @oh: struct omap_hwmod * | 2770 | * @oh: struct omap_hwmod * |
2673 | * | 2771 | * |
2674 | * Wait for a module @oh to leave slave idle. Returns 0 if the module | 2772 | * Wait for a module @oh to leave slave idle. Returns 0 if the module |
@@ -2676,7 +2774,7 @@ static int __init _alloc_linkspace(struct omap_hwmod_ocp_if **ois) | |||
2676 | * slave idle; otherwise, pass along the return value of the | 2774 | * slave idle; otherwise, pass along the return value of the |
2677 | * appropriate *_cm*_wait_module_ready() function. | 2775 | * appropriate *_cm*_wait_module_ready() function. |
2678 | */ | 2776 | */ |
2679 | static int _omap2_wait_target_ready(struct omap_hwmod *oh) | 2777 | static int _omap2xxx_wait_target_ready(struct omap_hwmod *oh) |
2680 | { | 2778 | { |
2681 | if (!oh) | 2779 | if (!oh) |
2682 | return -EINVAL; | 2780 | return -EINVAL; |
@@ -2689,9 +2787,36 @@ static int _omap2_wait_target_ready(struct omap_hwmod *oh) | |||
2689 | 2787 | ||
2690 | /* XXX check module SIDLEMODE, hardreset status, enabled clocks */ | 2788 | /* XXX check module SIDLEMODE, hardreset status, enabled clocks */ |
2691 | 2789 | ||
2692 | return omap2_cm_wait_module_ready(oh->prcm.omap2.module_offs, | 2790 | return omap2xxx_cm_wait_module_ready(oh->prcm.omap2.module_offs, |
2693 | oh->prcm.omap2.idlest_reg_id, | 2791 | oh->prcm.omap2.idlest_reg_id, |
2694 | oh->prcm.omap2.idlest_idle_bit); | 2792 | oh->prcm.omap2.idlest_idle_bit); |
2793 | } | ||
2794 | |||
2795 | /** | ||
2796 | * _omap3xxx_wait_target_ready - wait for a module to leave slave idle | ||
2797 | * @oh: struct omap_hwmod * | ||
2798 | * | ||
2799 | * Wait for a module @oh to leave slave idle. Returns 0 if the module | ||
2800 | * does not have an IDLEST bit or if the module successfully leaves | ||
2801 | * slave idle; otherwise, pass along the return value of the | ||
2802 | * appropriate *_cm*_wait_module_ready() function. | ||
2803 | */ | ||
2804 | static int _omap3xxx_wait_target_ready(struct omap_hwmod *oh) | ||
2805 | { | ||
2806 | if (!oh) | ||
2807 | return -EINVAL; | ||
2808 | |||
2809 | if (oh->flags & HWMOD_NO_IDLEST) | ||
2810 | return 0; | ||
2811 | |||
2812 | if (!_find_mpu_rt_port(oh)) | ||
2813 | return 0; | ||
2814 | |||
2815 | /* XXX check module SIDLEMODE, hardreset status, enabled clocks */ | ||
2816 | |||
2817 | return omap3xxx_cm_wait_module_ready(oh->prcm.omap2.module_offs, | ||
2818 | oh->prcm.omap2.idlest_reg_id, | ||
2819 | oh->prcm.omap2.idlest_idle_bit); | ||
2695 | } | 2820 | } |
2696 | 2821 | ||
2697 | /** | 2822 | /** |
@@ -3337,7 +3462,7 @@ int omap_hwmod_reset(struct omap_hwmod *oh) | |||
3337 | /** | 3462 | /** |
3338 | * omap_hwmod_count_resources - count number of struct resources needed by hwmod | 3463 | * omap_hwmod_count_resources - count number of struct resources needed by hwmod |
3339 | * @oh: struct omap_hwmod * | 3464 | * @oh: struct omap_hwmod * |
3340 | * @res: pointer to the first element of an array of struct resource to fill | 3465 | * @flags: Type of resources to include when counting (IRQ/DMA/MEM) |
3341 | * | 3466 | * |
3342 | * Count the number of struct resource array elements necessary to | 3467 | * Count the number of struct resource array elements necessary to |
3343 | * contain omap_hwmod @oh resources. Intended to be called by code | 3468 | * contain omap_hwmod @oh resources. Intended to be called by code |
@@ -3350,20 +3475,25 @@ int omap_hwmod_reset(struct omap_hwmod *oh) | |||
3350 | * resource IDs. | 3475 | * resource IDs. |
3351 | * | 3476 | * |
3352 | */ | 3477 | */ |
3353 | int omap_hwmod_count_resources(struct omap_hwmod *oh) | 3478 | int omap_hwmod_count_resources(struct omap_hwmod *oh, unsigned long flags) |
3354 | { | 3479 | { |
3355 | struct omap_hwmod_ocp_if *os; | 3480 | int ret = 0; |
3356 | struct list_head *p; | ||
3357 | int ret; | ||
3358 | int i = 0; | ||
3359 | 3481 | ||
3360 | ret = _count_mpu_irqs(oh) + _count_sdma_reqs(oh); | 3482 | if (flags & IORESOURCE_IRQ) |
3483 | ret += _count_mpu_irqs(oh); | ||
3361 | 3484 | ||
3362 | p = oh->slave_ports.next; | 3485 | if (flags & IORESOURCE_DMA) |
3486 | ret += _count_sdma_reqs(oh); | ||
3363 | 3487 | ||
3364 | while (i < oh->slaves_cnt) { | 3488 | if (flags & IORESOURCE_MEM) { |
3365 | os = _fetch_next_ocp_if(&p, &i); | 3489 | int i = 0; |
3366 | ret += _count_ocp_if_addr_spaces(os); | 3490 | struct omap_hwmod_ocp_if *os; |
3491 | struct list_head *p = oh->slave_ports.next; | ||
3492 | |||
3493 | while (i < oh->slaves_cnt) { | ||
3494 | os = _fetch_next_ocp_if(&p, &i); | ||
3495 | ret += _count_ocp_if_addr_spaces(os); | ||
3496 | } | ||
3367 | } | 3497 | } |
3368 | 3498 | ||
3369 | return ret; | 3499 | return ret; |
@@ -3530,10 +3660,15 @@ struct powerdomain *omap_hwmod_get_pwrdm(struct omap_hwmod *oh) | |||
3530 | { | 3660 | { |
3531 | struct clk *c; | 3661 | struct clk *c; |
3532 | struct omap_hwmod_ocp_if *oi; | 3662 | struct omap_hwmod_ocp_if *oi; |
3663 | struct clockdomain *clkdm; | ||
3664 | struct clk_hw_omap *clk; | ||
3533 | 3665 | ||
3534 | if (!oh) | 3666 | if (!oh) |
3535 | return NULL; | 3667 | return NULL; |
3536 | 3668 | ||
3669 | if (oh->clkdm) | ||
3670 | return oh->clkdm->pwrdm.ptr; | ||
3671 | |||
3537 | if (oh->_clk) { | 3672 | if (oh->_clk) { |
3538 | c = oh->_clk; | 3673 | c = oh->_clk; |
3539 | } else { | 3674 | } else { |
@@ -3543,11 +3678,12 @@ struct powerdomain *omap_hwmod_get_pwrdm(struct omap_hwmod *oh) | |||
3543 | c = oi->_clk; | 3678 | c = oi->_clk; |
3544 | } | 3679 | } |
3545 | 3680 | ||
3546 | if (!c->clkdm) | 3681 | clk = to_clk_hw_omap(__clk_get_hw(c)); |
3682 | clkdm = clk->clkdm; | ||
3683 | if (!clkdm) | ||
3547 | return NULL; | 3684 | return NULL; |
3548 | 3685 | ||
3549 | return c->clkdm->pwrdm.ptr; | 3686 | return clkdm->pwrdm.ptr; |
3550 | |||
3551 | } | 3687 | } |
3552 | 3688 | ||
3553 | /** | 3689 | /** |
@@ -3852,17 +3988,21 @@ ohsps_unlock: | |||
3852 | * omap_hwmod_get_context_loss_count - get lost context count | 3988 | * omap_hwmod_get_context_loss_count - get lost context count |
3853 | * @oh: struct omap_hwmod * | 3989 | * @oh: struct omap_hwmod * |
3854 | * | 3990 | * |
3855 | * Query the powerdomain of of @oh to get the context loss | 3991 | * Returns the context loss count of associated @oh |
3856 | * count for this device. | 3992 | * upon success, or zero if no context loss data is available. |
3857 | * | 3993 | * |
3858 | * Returns the context loss count of the powerdomain assocated with @oh | 3994 | * On OMAP4, this queries the per-hwmod context loss register, |
3859 | * upon success, or zero if no powerdomain exists for @oh. | 3995 | * assuming one exists. If not, or on OMAP2/3, this queries the |
3996 | * enclosing powerdomain context loss count. | ||
3860 | */ | 3997 | */ |
3861 | int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh) | 3998 | int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh) |
3862 | { | 3999 | { |
3863 | struct powerdomain *pwrdm; | 4000 | struct powerdomain *pwrdm; |
3864 | int ret = 0; | 4001 | int ret = 0; |
3865 | 4002 | ||
4003 | if (soc_ops.get_context_lost) | ||
4004 | return soc_ops.get_context_lost(oh); | ||
4005 | |||
3866 | pwrdm = omap_hwmod_get_pwrdm(oh); | 4006 | pwrdm = omap_hwmod_get_pwrdm(oh); |
3867 | if (pwrdm) | 4007 | if (pwrdm) |
3868 | ret = pwrdm_get_context_loss_count(pwrdm); | 4008 | ret = pwrdm_get_context_loss_count(pwrdm); |
@@ -3959,8 +4099,13 @@ int omap_hwmod_pad_route_irq(struct omap_hwmod *oh, int pad_idx, int irq_idx) | |||
3959 | */ | 4099 | */ |
3960 | void __init omap_hwmod_init(void) | 4100 | void __init omap_hwmod_init(void) |
3961 | { | 4101 | { |
3962 | if (cpu_is_omap24xx() || cpu_is_omap34xx()) { | 4102 | if (cpu_is_omap24xx()) { |
3963 | soc_ops.wait_target_ready = _omap2_wait_target_ready; | 4103 | soc_ops.wait_target_ready = _omap2xxx_wait_target_ready; |
4104 | soc_ops.assert_hardreset = _omap2_assert_hardreset; | ||
4105 | soc_ops.deassert_hardreset = _omap2_deassert_hardreset; | ||
4106 | soc_ops.is_hardreset_asserted = _omap2_is_hardreset_asserted; | ||
4107 | } else if (cpu_is_omap34xx()) { | ||
4108 | soc_ops.wait_target_ready = _omap3xxx_wait_target_ready; | ||
3964 | soc_ops.assert_hardreset = _omap2_assert_hardreset; | 4109 | soc_ops.assert_hardreset = _omap2_assert_hardreset; |
3965 | soc_ops.deassert_hardreset = _omap2_deassert_hardreset; | 4110 | soc_ops.deassert_hardreset = _omap2_deassert_hardreset; |
3966 | soc_ops.is_hardreset_asserted = _omap2_is_hardreset_asserted; | 4111 | soc_ops.is_hardreset_asserted = _omap2_is_hardreset_asserted; |
@@ -3972,6 +4117,8 @@ void __init omap_hwmod_init(void) | |||
3972 | soc_ops.deassert_hardreset = _omap4_deassert_hardreset; | 4117 | soc_ops.deassert_hardreset = _omap4_deassert_hardreset; |
3973 | soc_ops.is_hardreset_asserted = _omap4_is_hardreset_asserted; | 4118 | soc_ops.is_hardreset_asserted = _omap4_is_hardreset_asserted; |
3974 | soc_ops.init_clkdm = _init_clkdm; | 4119 | soc_ops.init_clkdm = _init_clkdm; |
4120 | soc_ops.update_context_lost = _omap4_update_context_lost; | ||
4121 | soc_ops.get_context_lost = _omap4_get_context_lost; | ||
3975 | } else if (soc_is_am33xx()) { | 4122 | } else if (soc_is_am33xx()) { |
3976 | soc_ops.enable_module = _am33xx_enable_module; | 4123 | soc_ops.enable_module = _am33xx_enable_module; |
3977 | soc_ops.disable_module = _am33xx_disable_module; | 4124 | soc_ops.disable_module = _am33xx_disable_module; |