aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/omap_hwmod.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/omap_hwmod.c')
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.c404
1 files changed, 350 insertions, 54 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 293fa6cd50e1..84cc0bdda3ae 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -2,6 +2,7 @@
2 * omap_hwmod implementation for OMAP2/3/4 2 * omap_hwmod implementation for OMAP2/3/4
3 * 3 *
4 * Copyright (C) 2009-2011 Nokia Corporation 4 * Copyright (C) 2009-2011 Nokia Corporation
5 * Copyright (C) 2011 Texas Instruments, Inc.
5 * 6 *
6 * Paul Walmsley, Benoît Cousson, Kevin Hilman 7 * Paul Walmsley, Benoît Cousson, Kevin Hilman
7 * 8 *
@@ -145,9 +146,10 @@
145#include <plat/prcm.h> 146#include <plat/prcm.h>
146 147
147#include "cm2xxx_3xxx.h" 148#include "cm2xxx_3xxx.h"
148#include "cm44xx.h" 149#include "cminst44xx.h"
149#include "prm2xxx_3xxx.h" 150#include "prm2xxx_3xxx.h"
150#include "prm44xx.h" 151#include "prm44xx.h"
152#include "prminst44xx.h"
151#include "mux.h" 153#include "mux.h"
152 154
153/* Maximum microseconds to wait for OMAP module to softreset */ 155/* Maximum microseconds to wait for OMAP module to softreset */
@@ -387,11 +389,10 @@ static int _set_module_autoidle(struct omap_hwmod *oh, u8 autoidle,
387 */ 389 */
388static int _enable_wakeup(struct omap_hwmod *oh, u32 *v) 390static int _enable_wakeup(struct omap_hwmod *oh, u32 *v)
389{ 391{
390 u32 wakeup_mask;
391
392 if (!oh->class->sysc || 392 if (!oh->class->sysc ||
393 !((oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP) || 393 !((oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP) ||
394 (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP))) 394 (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP) ||
395 (oh->class->sysc->idlemodes & MSTANDBY_SMART_WKUP)))
395 return -EINVAL; 396 return -EINVAL;
396 397
397 if (!oh->class->sysc->sysc_fields) { 398 if (!oh->class->sysc->sysc_fields) {
@@ -399,12 +400,13 @@ static int _enable_wakeup(struct omap_hwmod *oh, u32 *v)
399 return -EINVAL; 400 return -EINVAL;
400 } 401 }
401 402
402 wakeup_mask = (0x1 << oh->class->sysc->sysc_fields->enwkup_shift); 403 if (oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP)
403 404 *v |= 0x1 << oh->class->sysc->sysc_fields->enwkup_shift;
404 *v |= wakeup_mask;
405 405
406 if (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP) 406 if (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP)
407 _set_slave_idlemode(oh, HWMOD_IDLEMODE_SMART_WKUP, v); 407 _set_slave_idlemode(oh, HWMOD_IDLEMODE_SMART_WKUP, v);
408 if (oh->class->sysc->idlemodes & MSTANDBY_SMART_WKUP)
409 _set_master_standbymode(oh, HWMOD_IDLEMODE_SMART_WKUP, v);
408 410
409 /* XXX test pwrdm_get_wken for this hwmod's subsystem */ 411 /* XXX test pwrdm_get_wken for this hwmod's subsystem */
410 412
@@ -422,11 +424,10 @@ static int _enable_wakeup(struct omap_hwmod *oh, u32 *v)
422 */ 424 */
423static int _disable_wakeup(struct omap_hwmod *oh, u32 *v) 425static int _disable_wakeup(struct omap_hwmod *oh, u32 *v)
424{ 426{
425 u32 wakeup_mask;
426
427 if (!oh->class->sysc || 427 if (!oh->class->sysc ||
428 !((oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP) || 428 !((oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP) ||
429 (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP))) 429 (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP) ||
430 (oh->class->sysc->idlemodes & MSTANDBY_SMART_WKUP)))
430 return -EINVAL; 431 return -EINVAL;
431 432
432 if (!oh->class->sysc->sysc_fields) { 433 if (!oh->class->sysc->sysc_fields) {
@@ -434,12 +435,13 @@ static int _disable_wakeup(struct omap_hwmod *oh, u32 *v)
434 return -EINVAL; 435 return -EINVAL;
435 } 436 }
436 437
437 wakeup_mask = (0x1 << oh->class->sysc->sysc_fields->enwkup_shift); 438 if (oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP)
438 439 *v &= ~(0x1 << oh->class->sysc->sysc_fields->enwkup_shift);
439 *v &= ~wakeup_mask;
440 440
441 if (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP) 441 if (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP)
442 _set_slave_idlemode(oh, HWMOD_IDLEMODE_SMART, v); 442 _set_slave_idlemode(oh, HWMOD_IDLEMODE_SMART, v);
443 if (oh->class->sysc->idlemodes & MSTANDBY_SMART_WKUP)
444 _set_master_standbymode(oh, HWMOD_IDLEMODE_SMART_WKUP, v);
443 445
444 /* XXX test pwrdm_get_wken for this hwmod's subsystem */ 446 /* XXX test pwrdm_get_wken for this hwmod's subsystem */
445 447
@@ -678,6 +680,125 @@ static void _disable_optional_clocks(struct omap_hwmod *oh)
678} 680}
679 681
680/** 682/**
683 * _enable_module - enable CLKCTRL modulemode on OMAP4
684 * @oh: struct omap_hwmod *
685 *
686 * Enables the PRCM module mode related to the hwmod @oh.
687 * No return value.
688 */
689static void _enable_module(struct omap_hwmod *oh)
690{
691 /* The module mode does not exist prior OMAP4 */
692 if (cpu_is_omap24xx() || cpu_is_omap34xx())
693 return;
694
695 if (!oh->clkdm || !oh->prcm.omap4.modulemode)
696 return;
697
698 pr_debug("omap_hwmod: %s: _enable_module: %d\n",
699 oh->name, oh->prcm.omap4.modulemode);
700
701 omap4_cminst_module_enable(oh->prcm.omap4.modulemode,
702 oh->clkdm->prcm_partition,
703 oh->clkdm->cm_inst,
704 oh->clkdm->clkdm_offs,
705 oh->prcm.omap4.clkctrl_offs);
706}
707
708/**
709 * _disable_module - enable CLKCTRL modulemode on OMAP4
710 * @oh: struct omap_hwmod *
711 *
712 * Disable the PRCM module mode related to the hwmod @oh.
713 * No return value.
714 */
715static void _disable_module(struct omap_hwmod *oh)
716{
717 /* The module mode does not exist prior OMAP4 */
718 if (cpu_is_omap24xx() || cpu_is_omap34xx())
719 return;
720
721 if (!oh->clkdm || !oh->prcm.omap4.modulemode)
722 return;
723
724 pr_debug("omap_hwmod: %s: _disable_module\n", oh->name);
725
726 omap4_cminst_module_disable(oh->clkdm->prcm_partition,
727 oh->clkdm->cm_inst,
728 oh->clkdm->clkdm_offs,
729 oh->prcm.omap4.clkctrl_offs);
730}
731
732/**
733 * _count_mpu_irqs - count the number of MPU IRQ lines associated with @oh
734 * @oh: struct omap_hwmod *oh
735 *
736 * Count and return the number of MPU IRQs associated with the hwmod
737 * @oh. Used to allocate struct resource data. Returns 0 if @oh is
738 * NULL.
739 */
740static int _count_mpu_irqs(struct omap_hwmod *oh)
741{
742 struct omap_hwmod_irq_info *ohii;
743 int i = 0;
744
745 if (!oh || !oh->mpu_irqs)
746 return 0;
747
748 do {
749 ohii = &oh->mpu_irqs[i++];
750 } while (ohii->irq != -1);
751
752 return i;
753}
754
755/**
756 * _count_sdma_reqs - count the number of SDMA request lines associated with @oh
757 * @oh: struct omap_hwmod *oh
758 *
759 * Count and return the number of SDMA request lines associated with
760 * the hwmod @oh. Used to allocate struct resource data. Returns 0
761 * if @oh is NULL.
762 */
763static int _count_sdma_reqs(struct omap_hwmod *oh)
764{
765 struct omap_hwmod_dma_info *ohdi;
766 int i = 0;
767
768 if (!oh || !oh->sdma_reqs)
769 return 0;
770
771 do {
772 ohdi = &oh->sdma_reqs[i++];
773 } while (ohdi->dma_req != -1);
774
775 return i;
776}
777
778/**
779 * _count_ocp_if_addr_spaces - count the number of address space entries for @oh
780 * @oh: struct omap_hwmod *oh
781 *
782 * Count and return the number of address space ranges associated with
783 * the hwmod @oh. Used to allocate struct resource data. Returns 0
784 * if @oh is NULL.
785 */
786static int _count_ocp_if_addr_spaces(struct omap_hwmod_ocp_if *os)
787{
788 struct omap_hwmod_addr_space *mem;
789 int i = 0;
790
791 if (!os || !os->addr)
792 return 0;
793
794 do {
795 mem = &os->addr[i++];
796 } while (mem->pa_start != mem->pa_end);
797
798 return i;
799}
800
801/**
681 * _find_mpu_port_index - find hwmod OCP slave port ID intended for MPU use 802 * _find_mpu_port_index - find hwmod OCP slave port ID intended for MPU use
682 * @oh: struct omap_hwmod * 803 * @oh: struct omap_hwmod *
683 * 804 *
@@ -722,8 +843,7 @@ static void __iomem * __init _find_mpu_rt_base(struct omap_hwmod *oh, u8 index)
722{ 843{
723 struct omap_hwmod_ocp_if *os; 844 struct omap_hwmod_ocp_if *os;
724 struct omap_hwmod_addr_space *mem; 845 struct omap_hwmod_addr_space *mem;
725 int i; 846 int i = 0, found = 0;
726 int found = 0;
727 void __iomem *va_start; 847 void __iomem *va_start;
728 848
729 if (!oh || oh->slaves_cnt == 0) 849 if (!oh || oh->slaves_cnt == 0)
@@ -731,12 +851,14 @@ static void __iomem * __init _find_mpu_rt_base(struct omap_hwmod *oh, u8 index)
731 851
732 os = oh->slaves[index]; 852 os = oh->slaves[index];
733 853
734 for (i = 0, mem = os->addr; i < os->addr_cnt; i++, mem++) { 854 if (!os->addr)
735 if (mem->flags & ADDR_TYPE_RT) { 855 return NULL;
856
857 do {
858 mem = &os->addr[i++];
859 if (mem->flags & ADDR_TYPE_RT)
736 found = 1; 860 found = 1;
737 break; 861 } while (!found && mem->pa_start != mem->pa_end);
738 }
739 }
740 862
741 if (found) { 863 if (found) {
742 va_start = ioremap(mem->pa_start, mem->pa_end - mem->pa_start); 864 va_start = ioremap(mem->pa_start, mem->pa_end - mem->pa_start);
@@ -781,8 +903,16 @@ static void _enable_sysc(struct omap_hwmod *oh)
781 } 903 }
782 904
783 if (sf & SYSC_HAS_MIDLEMODE) { 905 if (sf & SYSC_HAS_MIDLEMODE) {
784 idlemode = (oh->flags & HWMOD_SWSUP_MSTANDBY) ? 906 if (oh->flags & HWMOD_SWSUP_MSTANDBY) {
785 HWMOD_IDLEMODE_NO : HWMOD_IDLEMODE_SMART; 907 idlemode = HWMOD_IDLEMODE_NO;
908 } else {
909 if (sf & SYSC_HAS_ENAWAKEUP)
910 _enable_wakeup(oh, &v);
911 if (oh->class->sysc->idlemodes & MSTANDBY_SMART_WKUP)
912 idlemode = HWMOD_IDLEMODE_SMART_WKUP;
913 else
914 idlemode = HWMOD_IDLEMODE_SMART;
915 }
786 _set_master_standbymode(oh, idlemode, &v); 916 _set_master_standbymode(oh, idlemode, &v);
787 } 917 }
788 918
@@ -840,8 +970,16 @@ static void _idle_sysc(struct omap_hwmod *oh)
840 } 970 }
841 971
842 if (sf & SYSC_HAS_MIDLEMODE) { 972 if (sf & SYSC_HAS_MIDLEMODE) {
843 idlemode = (oh->flags & HWMOD_SWSUP_MSTANDBY) ? 973 if (oh->flags & HWMOD_SWSUP_MSTANDBY) {
844 HWMOD_IDLEMODE_FORCE : HWMOD_IDLEMODE_SMART; 974 idlemode = HWMOD_IDLEMODE_FORCE;
975 } else {
976 if (sf & SYSC_HAS_ENAWAKEUP)
977 _enable_wakeup(oh, &v);
978 if (oh->class->sysc->idlemodes & MSTANDBY_SMART_WKUP)
979 idlemode = HWMOD_IDLEMODE_SMART_WKUP;
980 else
981 idlemode = HWMOD_IDLEMODE_SMART;
982 }
845 _set_master_standbymode(oh, idlemode, &v); 983 _set_master_standbymode(oh, idlemode, &v);
846 } 984 }
847 985
@@ -903,9 +1041,40 @@ static struct omap_hwmod *_lookup(const char *name)
903 1041
904 return oh; 1042 return oh;
905} 1043}
1044/**
1045 * _init_clkdm - look up a clockdomain name, store pointer in omap_hwmod
1046 * @oh: struct omap_hwmod *
1047 *
1048 * Convert a clockdomain name stored in a struct omap_hwmod into a
1049 * clockdomain pointer, and save it into the struct omap_hwmod.
1050 * return -EINVAL if clkdm_name does not exist or if the lookup failed.
1051 */
1052static int _init_clkdm(struct omap_hwmod *oh)
1053{
1054 if (cpu_is_omap24xx() || cpu_is_omap34xx())
1055 return 0;
1056
1057 if (!oh->clkdm_name) {
1058 pr_warning("omap_hwmod: %s: no clkdm_name\n", oh->name);
1059 return -EINVAL;
1060 }
1061
1062 oh->clkdm = clkdm_lookup(oh->clkdm_name);
1063 if (!oh->clkdm) {
1064 pr_warning("omap_hwmod: %s: could not associate to clkdm %s\n",
1065 oh->name, oh->clkdm_name);
1066 return -EINVAL;
1067 }
1068
1069 pr_debug("omap_hwmod: %s: associated to clkdm %s\n",
1070 oh->name, oh->clkdm_name);
1071
1072 return 0;
1073}
906 1074
907/** 1075/**
908 * _init_clocks - clk_get() all clocks associated with this hwmod 1076 * _init_clocks - clk_get() all clocks associated with this hwmod. Retrieve as
1077 * well the clockdomain.
909 * @oh: struct omap_hwmod * 1078 * @oh: struct omap_hwmod *
910 * @data: not used; pass NULL 1079 * @data: not used; pass NULL
911 * 1080 *
@@ -925,9 +1094,12 @@ static int _init_clocks(struct omap_hwmod *oh, void *data)
925 ret |= _init_main_clk(oh); 1094 ret |= _init_main_clk(oh);
926 ret |= _init_interface_clks(oh); 1095 ret |= _init_interface_clks(oh);
927 ret |= _init_opt_clks(oh); 1096 ret |= _init_opt_clks(oh);
1097 ret |= _init_clkdm(oh);
928 1098
929 if (!ret) 1099 if (!ret)
930 oh->_state = _HWMOD_STATE_CLKS_INITED; 1100 oh->_state = _HWMOD_STATE_CLKS_INITED;
1101 else
1102 pr_warning("omap_hwmod: %s: cannot _init_clocks\n", oh->name);
931 1103
932 return ret; 1104 return ret;
933} 1105}
@@ -939,7 +1111,7 @@ static int _init_clocks(struct omap_hwmod *oh, void *data)
939 * Wait for a module @oh to leave slave idle. Returns 0 if the module 1111 * Wait for a module @oh to leave slave idle. Returns 0 if the module
940 * does not have an IDLEST bit or if the module successfully leaves 1112 * does not have an IDLEST bit or if the module successfully leaves
941 * slave idle; otherwise, pass along the return value of the 1113 * slave idle; otherwise, pass along the return value of the
942 * appropriate *_cm_wait_module_ready() function. 1114 * appropriate *_cm*_wait_module_ready() function.
943 */ 1115 */
944static int _wait_target_ready(struct omap_hwmod *oh) 1116static int _wait_target_ready(struct omap_hwmod *oh)
945{ 1117{
@@ -966,7 +1138,13 @@ static int _wait_target_ready(struct omap_hwmod *oh)
966 oh->prcm.omap2.idlest_reg_id, 1138 oh->prcm.omap2.idlest_reg_id,
967 oh->prcm.omap2.idlest_idle_bit); 1139 oh->prcm.omap2.idlest_idle_bit);
968 } else if (cpu_is_omap44xx()) { 1140 } else if (cpu_is_omap44xx()) {
969 ret = omap4_cm_wait_module_ready(oh->prcm.omap4.clkctrl_reg); 1141 if (!oh->clkdm)
1142 return -EINVAL;
1143
1144 ret = omap4_cminst_wait_module_ready(oh->clkdm->prcm_partition,
1145 oh->clkdm->cm_inst,
1146 oh->clkdm->clkdm_offs,
1147 oh->prcm.omap4.clkctrl_offs);
970 } else { 1148 } else {
971 BUG(); 1149 BUG();
972 }; 1150 };
@@ -975,6 +1153,36 @@ static int _wait_target_ready(struct omap_hwmod *oh)
975} 1153}
976 1154
977/** 1155/**
1156 * _wait_target_disable - wait for a module to be disabled
1157 * @oh: struct omap_hwmod *
1158 *
1159 * Wait for a module @oh to enter slave idle. Returns 0 if the module
1160 * does not have an IDLEST bit or if the module successfully enters
1161 * slave idle; otherwise, pass along the return value of the
1162 * appropriate *_cm*_wait_module_idle() function.
1163 */
1164static int _wait_target_disable(struct omap_hwmod *oh)
1165{
1166 /* TODO: For now just handle OMAP4+ */
1167 if (cpu_is_omap24xx() || cpu_is_omap34xx())
1168 return 0;
1169
1170 if (!oh)
1171 return -EINVAL;
1172
1173 if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
1174 return 0;
1175
1176 if (oh->flags & HWMOD_NO_IDLEST)
1177 return 0;
1178
1179 return omap4_cminst_wait_module_idle(oh->clkdm->prcm_partition,
1180 oh->clkdm->cm_inst,
1181 oh->clkdm->clkdm_offs,
1182 oh->prcm.omap4.clkctrl_offs);
1183}
1184
1185/**
978 * _lookup_hardreset - fill register bit info for this hwmod/reset line 1186 * _lookup_hardreset - fill register bit info for this hwmod/reset line
979 * @oh: struct omap_hwmod * 1187 * @oh: struct omap_hwmod *
980 * @name: name of the reset line in the context of this hwmod 1188 * @name: name of the reset line in the context of this hwmod
@@ -1030,8 +1238,10 @@ static int _assert_hardreset(struct omap_hwmod *oh, const char *name)
1030 return omap2_prm_assert_hardreset(oh->prcm.omap2.module_offs, 1238 return omap2_prm_assert_hardreset(oh->prcm.omap2.module_offs,
1031 ohri.rst_shift); 1239 ohri.rst_shift);
1032 else if (cpu_is_omap44xx()) 1240 else if (cpu_is_omap44xx())
1033 return omap4_prm_assert_hardreset(oh->prcm.omap4.rstctrl_reg, 1241 return omap4_prminst_assert_hardreset(ohri.rst_shift,
1034 ohri.rst_shift); 1242 oh->clkdm->pwrdm.ptr->prcm_partition,
1243 oh->clkdm->pwrdm.ptr->prcm_offs,
1244 oh->prcm.omap4.rstctrl_offs);
1035 else 1245 else
1036 return -EINVAL; 1246 return -EINVAL;
1037} 1247}
@@ -1066,8 +1276,10 @@ static int _deassert_hardreset(struct omap_hwmod *oh, const char *name)
1066 if (ohri.st_shift) 1276 if (ohri.st_shift)
1067 pr_err("omap_hwmod: %s: %s: hwmod data error: OMAP4 does not support st_shift\n", 1277 pr_err("omap_hwmod: %s: %s: hwmod data error: OMAP4 does not support st_shift\n",
1068 oh->name, name); 1278 oh->name, name);
1069 ret = omap4_prm_deassert_hardreset(oh->prcm.omap4.rstctrl_reg, 1279 ret = omap4_prminst_deassert_hardreset(ohri.rst_shift,
1070 ohri.rst_shift); 1280 oh->clkdm->pwrdm.ptr->prcm_partition,
1281 oh->clkdm->pwrdm.ptr->prcm_offs,
1282 oh->prcm.omap4.rstctrl_offs);
1071 } else { 1283 } else {
1072 return -EINVAL; 1284 return -EINVAL;
1073 } 1285 }
@@ -1102,8 +1314,10 @@ static int _read_hardreset(struct omap_hwmod *oh, const char *name)
1102 return omap2_prm_is_hardreset_asserted(oh->prcm.omap2.module_offs, 1314 return omap2_prm_is_hardreset_asserted(oh->prcm.omap2.module_offs,
1103 ohri.st_shift); 1315 ohri.st_shift);
1104 } else if (cpu_is_omap44xx()) { 1316 } else if (cpu_is_omap44xx()) {
1105 return omap4_prm_is_hardreset_asserted(oh->prcm.omap4.rstctrl_reg, 1317 return omap4_prminst_is_hardreset_asserted(ohri.rst_shift,
1106 ohri.rst_shift); 1318 oh->clkdm->pwrdm.ptr->prcm_partition,
1319 oh->clkdm->pwrdm.ptr->prcm_offs,
1320 oh->prcm.omap4.rstctrl_offs);
1107 } else { 1321 } else {
1108 return -EINVAL; 1322 return -EINVAL;
1109 } 1323 }
@@ -1223,6 +1437,9 @@ static int _reset(struct omap_hwmod *oh)
1223static int _enable(struct omap_hwmod *oh) 1437static int _enable(struct omap_hwmod *oh)
1224{ 1438{
1225 int r; 1439 int r;
1440 int hwsup = 0;
1441
1442 pr_debug("omap_hwmod: %s: enabling\n", oh->name);
1226 1443
1227 if (oh->_state != _HWMOD_STATE_INITIALIZED && 1444 if (oh->_state != _HWMOD_STATE_INITIALIZED &&
1228 oh->_state != _HWMOD_STATE_IDLE && 1445 oh->_state != _HWMOD_STATE_IDLE &&
@@ -1232,11 +1449,10 @@ static int _enable(struct omap_hwmod *oh)
1232 return -EINVAL; 1449 return -EINVAL;
1233 } 1450 }
1234 1451
1235 pr_debug("omap_hwmod: %s: enabling\n", oh->name);
1236 1452
1237 /* 1453 /*
1238 * If an IP contains only one HW reset line, then de-assert it in order 1454 * If an IP contains only one HW reset line, then de-assert it in order
1239 * to allow to enable the clocks. Otherwise the PRCM will return 1455 * to allow the module state transition. Otherwise the PRCM will return
1240 * Intransition status, and the init will failed. 1456 * Intransition status, and the init will failed.
1241 */ 1457 */
1242 if ((oh->_state == _HWMOD_STATE_INITIALIZED || 1458 if ((oh->_state == _HWMOD_STATE_INITIALIZED ||
@@ -1250,10 +1466,34 @@ static int _enable(struct omap_hwmod *oh)
1250 omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED); 1466 omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED);
1251 1467
1252 _add_initiator_dep(oh, mpu_oh); 1468 _add_initiator_dep(oh, mpu_oh);
1469
1470 if (oh->clkdm) {
1471 /*
1472 * A clockdomain must be in SW_SUP before enabling
1473 * completely the module. The clockdomain can be set
1474 * in HW_AUTO only when the module become ready.
1475 */
1476 hwsup = clkdm_in_hwsup(oh->clkdm);
1477 r = clkdm_hwmod_enable(oh->clkdm, oh);
1478 if (r) {
1479 WARN(1, "omap_hwmod: %s: could not enable clockdomain %s: %d\n",
1480 oh->name, oh->clkdm->name, r);
1481 return r;
1482 }
1483 }
1484
1253 _enable_clocks(oh); 1485 _enable_clocks(oh);
1486 _enable_module(oh);
1254 1487
1255 r = _wait_target_ready(oh); 1488 r = _wait_target_ready(oh);
1256 if (!r) { 1489 if (!r) {
1490 /*
1491 * Set the clockdomain to HW_AUTO only if the target is ready,
1492 * assuming that the previous state was HW_AUTO
1493 */
1494 if (oh->clkdm && hwsup)
1495 clkdm_allow_idle(oh->clkdm);
1496
1257 oh->_state = _HWMOD_STATE_ENABLED; 1497 oh->_state = _HWMOD_STATE_ENABLED;
1258 1498
1259 /* Access the sysconfig only if the target is ready */ 1499 /* Access the sysconfig only if the target is ready */
@@ -1266,6 +1506,9 @@ static int _enable(struct omap_hwmod *oh)
1266 _disable_clocks(oh); 1506 _disable_clocks(oh);
1267 pr_debug("omap_hwmod: %s: _wait_target_ready: %d\n", 1507 pr_debug("omap_hwmod: %s: _wait_target_ready: %d\n",
1268 oh->name, r); 1508 oh->name, r);
1509
1510 if (oh->clkdm)
1511 clkdm_hwmod_disable(oh->clkdm, oh);
1269 } 1512 }
1270 1513
1271 return r; 1514 return r;
@@ -1281,18 +1524,33 @@ static int _enable(struct omap_hwmod *oh)
1281 */ 1524 */
1282static int _idle(struct omap_hwmod *oh) 1525static int _idle(struct omap_hwmod *oh)
1283{ 1526{
1527 int ret;
1528
1529 pr_debug("omap_hwmod: %s: idling\n", oh->name);
1530
1284 if (oh->_state != _HWMOD_STATE_ENABLED) { 1531 if (oh->_state != _HWMOD_STATE_ENABLED) {
1285 WARN(1, "omap_hwmod: %s: idle state can only be entered from " 1532 WARN(1, "omap_hwmod: %s: idle state can only be entered from "
1286 "enabled state\n", oh->name); 1533 "enabled state\n", oh->name);
1287 return -EINVAL; 1534 return -EINVAL;
1288 } 1535 }
1289 1536
1290 pr_debug("omap_hwmod: %s: idling\n", oh->name);
1291
1292 if (oh->class->sysc) 1537 if (oh->class->sysc)
1293 _idle_sysc(oh); 1538 _idle_sysc(oh);
1294 _del_initiator_dep(oh, mpu_oh); 1539 _del_initiator_dep(oh, mpu_oh);
1540 _disable_module(oh);
1541 ret = _wait_target_disable(oh);
1542 if (ret)
1543 pr_warn("omap_hwmod: %s: _wait_target_disable failed\n",
1544 oh->name);
1545 /*
1546 * The module must be in idle mode before disabling any parents
1547 * clocks. Otherwise, the parent clock might be disabled before
1548 * the module transition is done, and thus will prevent the
1549 * transition to complete properly.
1550 */
1295 _disable_clocks(oh); 1551 _disable_clocks(oh);
1552 if (oh->clkdm)
1553 clkdm_hwmod_disable(oh->clkdm, oh);
1296 1554
1297 /* Mux pins for device idle if populated */ 1555 /* Mux pins for device idle if populated */
1298 if (oh->mux && oh->mux->pads_dynamic) 1556 if (oh->mux && oh->mux->pads_dynamic)
@@ -1374,24 +1632,34 @@ static int _shutdown(struct omap_hwmod *oh)
1374 } 1632 }
1375 } 1633 }
1376 1634
1377 if (oh->class->sysc) 1635 if (oh->class->sysc) {
1636 if (oh->_state == _HWMOD_STATE_IDLE)
1637 _enable(oh);
1378 _shutdown_sysc(oh); 1638 _shutdown_sysc(oh);
1379 1639 }
1380 /*
1381 * If an IP contains only one HW reset line, then assert it
1382 * before disabling the clocks and shutting down the IP.
1383 */
1384 if (oh->rst_lines_cnt == 1)
1385 _assert_hardreset(oh, oh->rst_lines[0].name);
1386 1640
1387 /* clocks and deps are already disabled in idle */ 1641 /* clocks and deps are already disabled in idle */
1388 if (oh->_state == _HWMOD_STATE_ENABLED) { 1642 if (oh->_state == _HWMOD_STATE_ENABLED) {
1389 _del_initiator_dep(oh, mpu_oh); 1643 _del_initiator_dep(oh, mpu_oh);
1390 /* XXX what about the other system initiators here? dma, dsp */ 1644 /* XXX what about the other system initiators here? dma, dsp */
1645 _disable_module(oh);
1646 ret = _wait_target_disable(oh);
1647 if (ret)
1648 pr_warn("omap_hwmod: %s: _wait_target_disable failed\n",
1649 oh->name);
1391 _disable_clocks(oh); 1650 _disable_clocks(oh);
1651 if (oh->clkdm)
1652 clkdm_hwmod_disable(oh->clkdm, oh);
1392 } 1653 }
1393 /* XXX Should this code also force-disable the optional clocks? */ 1654 /* XXX Should this code also force-disable the optional clocks? */
1394 1655
1656 /*
1657 * If an IP contains only one HW reset line, then assert it
1658 * after disabling the clocks and before shutting down the IP.
1659 */
1660 if (oh->rst_lines_cnt == 1)
1661 _assert_hardreset(oh, oh->rst_lines[0].name);
1662
1395 /* Mux pins to safe mode or use populated off mode values */ 1663 /* Mux pins to safe mode or use populated off mode values */
1396 if (oh->mux) 1664 if (oh->mux)
1397 omap_hwmod_mux(oh->mux, _HWMOD_STATE_DISABLED); 1665 omap_hwmod_mux(oh->mux, _HWMOD_STATE_DISABLED);
@@ -1562,6 +1830,33 @@ void omap_hwmod_write(u32 v, struct omap_hwmod *oh, u16 reg_offs)
1562} 1830}
1563 1831
1564/** 1832/**
1833 * omap_hwmod_softreset - reset a module via SYSCONFIG.SOFTRESET bit
1834 * @oh: struct omap_hwmod *
1835 *
1836 * This is a public function exposed to drivers. Some drivers may need to do
1837 * some settings before and after resetting the device. Those drivers after
1838 * doing the necessary settings could use this function to start a reset by
1839 * setting the SYSCONFIG.SOFTRESET bit.
1840 */
1841int omap_hwmod_softreset(struct omap_hwmod *oh)
1842{
1843 u32 v;
1844 int ret;
1845
1846 if (!oh || !(oh->_sysc_cache))
1847 return -EINVAL;
1848
1849 v = oh->_sysc_cache;
1850 ret = _set_softreset(oh, &v);
1851 if (ret)
1852 goto error;
1853 _write_sysconfig(v, oh);
1854
1855error:
1856 return ret;
1857}
1858
1859/**
1565 * omap_hwmod_set_slave_idlemode - set the hwmod's OCP slave idlemode 1860 * omap_hwmod_set_slave_idlemode - set the hwmod's OCP slave idlemode
1566 * @oh: struct omap_hwmod * 1861 * @oh: struct omap_hwmod *
1567 * @idlemode: SIDLEMODE field bits (shifted to bit 0) 1862 * @idlemode: SIDLEMODE field bits (shifted to bit 0)
@@ -1685,9 +1980,6 @@ static int __init _populate_mpu_rt_base(struct omap_hwmod *oh, void *data)
1685 return 0; 1980 return 0;
1686 1981
1687 oh->_mpu_rt_va = _find_mpu_rt_base(oh, oh->_mpu_port_index); 1982 oh->_mpu_rt_va = _find_mpu_rt_base(oh, oh->_mpu_port_index);
1688 if (!oh->_mpu_rt_va)
1689 pr_warning("omap_hwmod: %s found no _mpu_rt_va for %s\n",
1690 __func__, oh->name);
1691 1983
1692 return 0; 1984 return 0;
1693} 1985}
@@ -1939,10 +2231,10 @@ int omap_hwmod_count_resources(struct omap_hwmod *oh)
1939{ 2231{
1940 int ret, i; 2232 int ret, i;
1941 2233
1942 ret = oh->mpu_irqs_cnt + oh->sdma_reqs_cnt; 2234 ret = _count_mpu_irqs(oh) + _count_sdma_reqs(oh);
1943 2235
1944 for (i = 0; i < oh->slaves_cnt; i++) 2236 for (i = 0; i < oh->slaves_cnt; i++)
1945 ret += oh->slaves[i]->addr_cnt; 2237 ret += _count_ocp_if_addr_spaces(oh->slaves[i]);
1946 2238
1947 return ret; 2239 return ret;
1948} 2240}
@@ -1959,12 +2251,13 @@ int omap_hwmod_count_resources(struct omap_hwmod *oh)
1959 */ 2251 */
1960int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res) 2252int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res)
1961{ 2253{
1962 int i, j; 2254 int i, j, mpu_irqs_cnt, sdma_reqs_cnt;
1963 int r = 0; 2255 int r = 0;
1964 2256
1965 /* For each IRQ, DMA, memory area, fill in array.*/ 2257 /* For each IRQ, DMA, memory area, fill in array.*/
1966 2258
1967 for (i = 0; i < oh->mpu_irqs_cnt; i++) { 2259 mpu_irqs_cnt = _count_mpu_irqs(oh);
2260 for (i = 0; i < mpu_irqs_cnt; i++) {
1968 (res + r)->name = (oh->mpu_irqs + i)->name; 2261 (res + r)->name = (oh->mpu_irqs + i)->name;
1969 (res + r)->start = (oh->mpu_irqs + i)->irq; 2262 (res + r)->start = (oh->mpu_irqs + i)->irq;
1970 (res + r)->end = (oh->mpu_irqs + i)->irq; 2263 (res + r)->end = (oh->mpu_irqs + i)->irq;
@@ -1972,7 +2265,8 @@ int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res)
1972 r++; 2265 r++;
1973 } 2266 }
1974 2267
1975 for (i = 0; i < oh->sdma_reqs_cnt; i++) { 2268 sdma_reqs_cnt = _count_sdma_reqs(oh);
2269 for (i = 0; i < sdma_reqs_cnt; i++) {
1976 (res + r)->name = (oh->sdma_reqs + i)->name; 2270 (res + r)->name = (oh->sdma_reqs + i)->name;
1977 (res + r)->start = (oh->sdma_reqs + i)->dma_req; 2271 (res + r)->start = (oh->sdma_reqs + i)->dma_req;
1978 (res + r)->end = (oh->sdma_reqs + i)->dma_req; 2272 (res + r)->end = (oh->sdma_reqs + i)->dma_req;
@@ -1982,10 +2276,12 @@ int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res)
1982 2276
1983 for (i = 0; i < oh->slaves_cnt; i++) { 2277 for (i = 0; i < oh->slaves_cnt; i++) {
1984 struct omap_hwmod_ocp_if *os; 2278 struct omap_hwmod_ocp_if *os;
2279 int addr_cnt;
1985 2280
1986 os = oh->slaves[i]; 2281 os = oh->slaves[i];
2282 addr_cnt = _count_ocp_if_addr_spaces(os);
1987 2283
1988 for (j = 0; j < os->addr_cnt; j++) { 2284 for (j = 0; j < addr_cnt; j++) {
1989 (res + r)->name = (os->addr + j)->name; 2285 (res + r)->name = (os->addr + j)->name;
1990 (res + r)->start = (os->addr + j)->pa_start; 2286 (res + r)->start = (os->addr + j)->pa_start;
1991 (res + r)->end = (os->addr + j)->pa_end; 2287 (res + r)->end = (os->addr + j)->pa_end;