aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNishanth Menon <nm@ti.com>2014-06-06 02:04:20 -0400
committerNishanth Menon <nm@ti.com>2014-09-08 12:22:41 -0400
commitbd002d7bdafc695decf7d4aeba285097356938f1 (patch)
treea9a5b81e89b4ae351d52d2f87fbc995233e90674
parent13bbffd4ebca57dfae59a3f13ff98dc417f89b23 (diff)
ARM: OMAP2+: powerdomain: introduce logic for finding valid power domain
powerdomain configuration in OMAP is done using PWRSTCTRL register for each power domain. However, PRCM lets us write any value we'd like to the logic and power domain target states, however the SoC integration tends to actually function only at a few discrete states. These valid states are already in our powerdomains_xxx_data.c file. So, provide a function to easily query valid low power state that the power domain is allowed to go to. Based on work originally done by Jean Pihet <j-pihet@ti.com> https://patchwork.kernel.org/patch/1325091/ . There is no attempt to create a new powerdomain solution here, except fixing issues seen attempting invalid programming attempts. Future consolidation to the generic powerdomain framework should consider this requirement as well. Similar solutions have been done in product kernels in the past such as: https://android.googlesource.com/kernel/omap.git/+blame/android-omap-panda-3.0/arch/arm/mach-omap2/pm44xx.c Signed-off-by: Nishanth Menon <nm@ti.com> Reviewed-by: Kevin Hilman <khilman@linaro.org> Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
-rw-r--r--arch/arm/mach-omap2/powerdomain.c76
-rw-r--r--arch/arm/mach-omap2/powerdomain.h3
2 files changed, 79 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index f391948c76b9..7fb033eca0a5 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -1081,6 +1081,82 @@ int pwrdm_post_transition(struct powerdomain *pwrdm)
1081} 1081}
1082 1082
1083/** 1083/**
1084 * pwrdm_get_valid_lp_state() - Find best match deep power state
1085 * @pwrdm: power domain for which we want to find best match
1086 * @is_logic_state: Are we looking for logic state match here? Should
1087 * be one of PWRDM_xxx macro values
1088 * @req_state: requested power state
1089 *
1090 * Returns: closest match for requested power state. default fallback
1091 * is RET for logic state and ON for power state.
1092 *
1093 * This does a search from the power domain data looking for the
1094 * closest valid power domain state that the hardware can achieve.
1095 * PRCM definitions for PWRSTCTRL allows us to program whatever
1096 * configuration we'd like, and PRCM will actually attempt such
1097 * a transition, however if the powerdomain does not actually support it,
1098 * we endup with a hung system. The valid power domain states are already
1099 * available in our powerdomain data files. So this function tries to do
1100 * the following:
1101 * a) find if we have an exact match to the request - no issues.
1102 * b) else find if a deeper power state is possible.
1103 * c) failing which, it tries to find closest higher power state for the
1104 * request.
1105 */
1106u8 pwrdm_get_valid_lp_state(struct powerdomain *pwrdm,
1107 bool is_logic_state, u8 req_state)
1108{
1109 u8 pwrdm_states = is_logic_state ? pwrdm->pwrsts_logic_ret :
1110 pwrdm->pwrsts;
1111 /* For logic, ret is highest and others, ON is highest */
1112 u8 default_pwrst = is_logic_state ? PWRDM_POWER_RET : PWRDM_POWER_ON;
1113 u8 new_pwrst;
1114 bool found;
1115
1116 /* If it is already supported, nothing to search */
1117 if (pwrdm_states & BIT(req_state))
1118 return req_state;
1119
1120 if (!req_state)
1121 goto up_search;
1122
1123 /*
1124 * So, we dont have a exact match
1125 * Can we get a deeper power state match?
1126 */
1127 new_pwrst = req_state - 1;
1128 found = true;
1129 while (!(pwrdm_states & BIT(new_pwrst))) {
1130 /* No match even at OFF? Not available */
1131 if (new_pwrst == PWRDM_POWER_OFF) {
1132 found = false;
1133 break;
1134 }
1135 new_pwrst--;
1136 }
1137
1138 if (found)
1139 goto done;
1140
1141up_search:
1142 /* OK, no deeper ones, can we get a higher match? */
1143 new_pwrst = req_state + 1;
1144 while (!(pwrdm_states & BIT(new_pwrst))) {
1145 if (new_pwrst > PWRDM_POWER_ON) {
1146 WARN(1, "powerdomain: %s: Fix max powerstate to ON\n",
1147 pwrdm->name);
1148 return PWRDM_POWER_ON;
1149 }
1150
1151 if (new_pwrst == default_pwrst)
1152 break;
1153 new_pwrst++;
1154 }
1155done:
1156 return new_pwrst;
1157}
1158
1159/**
1084 * omap_set_pwrdm_state - change a powerdomain's current power state 1160 * omap_set_pwrdm_state - change a powerdomain's current power state
1085 * @pwrdm: struct powerdomain * to change the power state of 1161 * @pwrdm: struct powerdomain * to change the power state of
1086 * @pwrst: power state to change to 1162 * @pwrst: power state to change to
diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
index a754c828aa51..11bd4dd7d8d6 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -220,6 +220,9 @@ struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm);
220 220
221int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm); 221int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
222 222
223u8 pwrdm_get_valid_lp_state(struct powerdomain *pwrdm,
224 bool is_logic_state, u8 req_state);
225
223int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst); 226int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst);
224int pwrdm_read_next_pwrst(struct powerdomain *pwrdm); 227int pwrdm_read_next_pwrst(struct powerdomain *pwrdm);
225int pwrdm_read_pwrst(struct powerdomain *pwrdm); 228int pwrdm_read_pwrst(struct powerdomain *pwrdm);