aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2014-09-08 18:04:24 -0400
committerTony Lindgren <tony@atomide.com>2014-09-08 18:04:24 -0400
commitd7eb67f7fef9c046f27a975118da2324de65a90c (patch)
treed6ddda513ae56e6a4d56b087b10c7f1faa11ecb0
parent9a15fff05b702c3ea29ae64db0d3ff0355431eab (diff)
parent3e6a1c945950140926dd6e2cc667893de0a7fe3b (diff)
Merge branch 'pull/v3.18/powerdomain-fixes' of https://github.com/nmenon/linux-2.6-playground into omap-for-v3.18/fixes-not-urgent
-rw-r--r--arch/arm/mach-omap2/omap-mpuss-lowpower.c4
-rw-r--r--arch/arm/mach-omap2/pm44xx.c9
-rw-r--r--arch/arm/mach-omap2/powerdomain.c79
-rw-r--r--arch/arm/mach-omap2/powerdomain.h4
-rw-r--r--arch/arm/mach-omap2/powerdomains54xx_data.c12
-rw-r--r--arch/arm/mach-omap2/powerdomains7xx_data.c14
6 files changed, 106 insertions, 16 deletions
diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
index 4001325f90fb..e9cdacfe1923 100644
--- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c
+++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
@@ -298,6 +298,10 @@ int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
298 if (omap_rev() == OMAP4430_REV_ES1_0) 298 if (omap_rev() == OMAP4430_REV_ES1_0)
299 return -ENXIO; 299 return -ENXIO;
300 300
301 /* Use the achievable power state for the domain */
302 power_state = pwrdm_get_valid_lp_state(pm_info->pwrdm,
303 false, power_state);
304
301 if (power_state == PWRDM_POWER_OFF) 305 if (power_state == PWRDM_POWER_OFF)
302 cpu_state = 1; 306 cpu_state = 1;
303 307
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index 0dda6cf8b855..0bfce38a744a 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -29,6 +29,7 @@ u16 pm44xx_errata;
29struct power_state { 29struct power_state {
30 struct powerdomain *pwrdm; 30 struct powerdomain *pwrdm;
31 u32 next_state; 31 u32 next_state;
32 u32 next_logic_state;
32#ifdef CONFIG_SUSPEND 33#ifdef CONFIG_SUSPEND
33 u32 saved_state; 34 u32 saved_state;
34 u32 saved_logic_state; 35 u32 saved_logic_state;
@@ -54,7 +55,7 @@ static int omap4_pm_suspend(void)
54 /* Set targeted power domain states by suspend */ 55 /* Set targeted power domain states by suspend */
55 list_for_each_entry(pwrst, &pwrst_list, node) { 56 list_for_each_entry(pwrst, &pwrst_list, node) {
56 omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state); 57 omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
57 pwrdm_set_logic_retst(pwrst->pwrdm, PWRDM_POWER_OFF); 58 pwrdm_set_logic_retst(pwrst->pwrdm, pwrst->next_logic_state);
58 } 59 }
59 60
60 /* 61 /*
@@ -120,7 +121,11 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
120 return -ENOMEM; 121 return -ENOMEM;
121 122
122 pwrst->pwrdm = pwrdm; 123 pwrst->pwrdm = pwrdm;
123 pwrst->next_state = PWRDM_POWER_RET; 124 pwrst->next_state = pwrdm_get_valid_lp_state(pwrdm, false,
125 PWRDM_POWER_RET);
126 pwrst->next_logic_state = pwrdm_get_valid_lp_state(pwrdm, true,
127 PWRDM_POWER_OFF);
128
124 list_add(&pwrst->node, &pwrst_list); 129 list_add(&pwrst->node, &pwrst_list);
125 130
126 return omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state); 131 return omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index faebd5f076af..7fb033eca0a5 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -546,7 +546,8 @@ int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
546 return -EINVAL; 546 return -EINVAL;
547 547
548 for (i = 0; i < PWRDM_MAX_CLKDMS && !ret; i++) 548 for (i = 0; i < PWRDM_MAX_CLKDMS && !ret; i++)
549 ret = (*fn)(pwrdm, pwrdm->pwrdm_clkdms[i]); 549 if (pwrdm->pwrdm_clkdms[i])
550 ret = (*fn)(pwrdm, pwrdm->pwrdm_clkdms[i]);
550 551
551 return ret; 552 return ret;
552} 553}
@@ -1080,6 +1081,82 @@ int pwrdm_post_transition(struct powerdomain *pwrdm)
1080} 1081}
1081 1082
1082/** 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/**
1083 * omap_set_pwrdm_state - change a powerdomain's current power state 1160 * omap_set_pwrdm_state - change a powerdomain's current power state
1084 * @pwrdm: struct powerdomain * to change the power state of 1161 * @pwrdm: struct powerdomain * to change the power state of
1085 * @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 f4727117f6cc..11bd4dd7d8d6 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -39,6 +39,7 @@
39#define PWRSTS_OFF_RET (PWRSTS_OFF | PWRSTS_RET) 39#define PWRSTS_OFF_RET (PWRSTS_OFF | PWRSTS_RET)
40#define PWRSTS_RET_ON (PWRSTS_RET | PWRSTS_ON) 40#define PWRSTS_RET_ON (PWRSTS_RET | PWRSTS_ON)
41#define PWRSTS_OFF_RET_ON (PWRSTS_OFF_RET | PWRSTS_ON) 41#define PWRSTS_OFF_RET_ON (PWRSTS_OFF_RET | PWRSTS_ON)
42#define PWRSTS_INA_ON (PWRSTS_INACTIVE | PWRSTS_ON)
42 43
43 44
44/* 45/*
@@ -219,6 +220,9 @@ struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm);
219 220
220int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm); 221int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
221 222
223u8 pwrdm_get_valid_lp_state(struct powerdomain *pwrdm,
224 bool is_logic_state, u8 req_state);
225
222int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst); 226int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst);
223int pwrdm_read_next_pwrst(struct powerdomain *pwrdm); 227int pwrdm_read_next_pwrst(struct powerdomain *pwrdm);
224int pwrdm_read_pwrst(struct powerdomain *pwrdm); 228int pwrdm_read_pwrst(struct powerdomain *pwrdm);
diff --git a/arch/arm/mach-omap2/powerdomains54xx_data.c b/arch/arm/mach-omap2/powerdomains54xx_data.c
index ce1d752af991..60d7ed8ef8ca 100644
--- a/arch/arm/mach-omap2/powerdomains54xx_data.c
+++ b/arch/arm/mach-omap2/powerdomains54xx_data.c
@@ -35,7 +35,7 @@ static struct powerdomain core_54xx_pwrdm = {
35 .prcm_offs = OMAP54XX_PRM_CORE_INST, 35 .prcm_offs = OMAP54XX_PRM_CORE_INST,
36 .prcm_partition = OMAP54XX_PRM_PARTITION, 36 .prcm_partition = OMAP54XX_PRM_PARTITION,
37 .pwrsts = PWRSTS_RET_ON, 37 .pwrsts = PWRSTS_RET_ON,
38 .pwrsts_logic_ret = PWRSTS_OFF_RET, 38 .pwrsts_logic_ret = PWRSTS_RET,
39 .banks = 5, 39 .banks = 5,
40 .pwrsts_mem_ret = { 40 .pwrsts_mem_ret = {
41 [0] = PWRSTS_OFF_RET, /* core_nret_bank */ 41 [0] = PWRSTS_OFF_RET, /* core_nret_bank */
@@ -107,8 +107,8 @@ static struct powerdomain cpu0_54xx_pwrdm = {
107 .voltdm = { .name = "mpu" }, 107 .voltdm = { .name = "mpu" },
108 .prcm_offs = OMAP54XX_PRCM_MPU_PRM_C0_INST, 108 .prcm_offs = OMAP54XX_PRCM_MPU_PRM_C0_INST,
109 .prcm_partition = OMAP54XX_PRCM_MPU_PARTITION, 109 .prcm_partition = OMAP54XX_PRCM_MPU_PARTITION,
110 .pwrsts = PWRSTS_OFF_RET_ON, 110 .pwrsts = PWRSTS_RET_ON,
111 .pwrsts_logic_ret = PWRSTS_OFF_RET, 111 .pwrsts_logic_ret = PWRSTS_RET,
112 .banks = 1, 112 .banks = 1,
113 .pwrsts_mem_ret = { 113 .pwrsts_mem_ret = {
114 [0] = PWRSTS_OFF_RET, /* cpu0_l1 */ 114 [0] = PWRSTS_OFF_RET, /* cpu0_l1 */
@@ -124,8 +124,8 @@ static struct powerdomain cpu1_54xx_pwrdm = {
124 .voltdm = { .name = "mpu" }, 124 .voltdm = { .name = "mpu" },
125 .prcm_offs = OMAP54XX_PRCM_MPU_PRM_C1_INST, 125 .prcm_offs = OMAP54XX_PRCM_MPU_PRM_C1_INST,
126 .prcm_partition = OMAP54XX_PRCM_MPU_PARTITION, 126 .prcm_partition = OMAP54XX_PRCM_MPU_PARTITION,
127 .pwrsts = PWRSTS_OFF_RET_ON, 127 .pwrsts = PWRSTS_RET_ON,
128 .pwrsts_logic_ret = PWRSTS_OFF_RET, 128 .pwrsts_logic_ret = PWRSTS_RET,
129 .banks = 1, 129 .banks = 1,
130 .pwrsts_mem_ret = { 130 .pwrsts_mem_ret = {
131 [0] = PWRSTS_OFF_RET, /* cpu1_l1 */ 131 [0] = PWRSTS_OFF_RET, /* cpu1_l1 */
@@ -158,7 +158,7 @@ static struct powerdomain mpu_54xx_pwrdm = {
158 .prcm_offs = OMAP54XX_PRM_MPU_INST, 158 .prcm_offs = OMAP54XX_PRM_MPU_INST,
159 .prcm_partition = OMAP54XX_PRM_PARTITION, 159 .prcm_partition = OMAP54XX_PRM_PARTITION,
160 .pwrsts = PWRSTS_RET_ON, 160 .pwrsts = PWRSTS_RET_ON,
161 .pwrsts_logic_ret = PWRSTS_OFF_RET, 161 .pwrsts_logic_ret = PWRSTS_RET,
162 .banks = 2, 162 .banks = 2,
163 .pwrsts_mem_ret = { 163 .pwrsts_mem_ret = {
164 [0] = PWRSTS_OFF_RET, /* mpu_l2 */ 164 [0] = PWRSTS_OFF_RET, /* mpu_l2 */
diff --git a/arch/arm/mach-omap2/powerdomains7xx_data.c b/arch/arm/mach-omap2/powerdomains7xx_data.c
index 48151d1cfde0..287a2037aa16 100644
--- a/arch/arm/mach-omap2/powerdomains7xx_data.c
+++ b/arch/arm/mach-omap2/powerdomains7xx_data.c
@@ -160,8 +160,8 @@ static struct powerdomain core_7xx_pwrdm = {
160 .name = "core_pwrdm", 160 .name = "core_pwrdm",
161 .prcm_offs = DRA7XX_PRM_CORE_INST, 161 .prcm_offs = DRA7XX_PRM_CORE_INST,
162 .prcm_partition = DRA7XX_PRM_PARTITION, 162 .prcm_partition = DRA7XX_PRM_PARTITION,
163 .pwrsts = PWRSTS_RET_ON, 163 .pwrsts = PWRSTS_INA_ON,
164 .pwrsts_logic_ret = PWRSTS_OFF_RET, 164 .pwrsts_logic_ret = PWRSTS_RET,
165 .banks = 5, 165 .banks = 5,
166 .pwrsts_mem_ret = { 166 .pwrsts_mem_ret = {
167 [0] = PWRSTS_OFF_RET, /* core_nret_bank */ 167 [0] = PWRSTS_OFF_RET, /* core_nret_bank */
@@ -193,8 +193,8 @@ static struct powerdomain cpu0_7xx_pwrdm = {
193 .name = "cpu0_pwrdm", 193 .name = "cpu0_pwrdm",
194 .prcm_offs = DRA7XX_MPU_PRCM_PRM_C0_INST, 194 .prcm_offs = DRA7XX_MPU_PRCM_PRM_C0_INST,
195 .prcm_partition = DRA7XX_MPU_PRCM_PARTITION, 195 .prcm_partition = DRA7XX_MPU_PRCM_PARTITION,
196 .pwrsts = PWRSTS_OFF_RET_ON, 196 .pwrsts = PWRSTS_RET_ON,
197 .pwrsts_logic_ret = PWRSTS_OFF_RET, 197 .pwrsts_logic_ret = PWRSTS_RET,
198 .banks = 1, 198 .banks = 1,
199 .pwrsts_mem_ret = { 199 .pwrsts_mem_ret = {
200 [0] = PWRSTS_OFF_RET, /* cpu0_l1 */ 200 [0] = PWRSTS_OFF_RET, /* cpu0_l1 */
@@ -209,8 +209,8 @@ static struct powerdomain cpu1_7xx_pwrdm = {
209 .name = "cpu1_pwrdm", 209 .name = "cpu1_pwrdm",
210 .prcm_offs = DRA7XX_MPU_PRCM_PRM_C1_INST, 210 .prcm_offs = DRA7XX_MPU_PRCM_PRM_C1_INST,
211 .prcm_partition = DRA7XX_MPU_PRCM_PARTITION, 211 .prcm_partition = DRA7XX_MPU_PRCM_PARTITION,
212 .pwrsts = PWRSTS_OFF_RET_ON, 212 .pwrsts = PWRSTS_RET_ON,
213 .pwrsts_logic_ret = PWRSTS_OFF_RET, 213 .pwrsts_logic_ret = PWRSTS_RET,
214 .banks = 1, 214 .banks = 1,
215 .pwrsts_mem_ret = { 215 .pwrsts_mem_ret = {
216 [0] = PWRSTS_OFF_RET, /* cpu1_l1 */ 216 [0] = PWRSTS_OFF_RET, /* cpu1_l1 */
@@ -243,7 +243,7 @@ static struct powerdomain mpu_7xx_pwrdm = {
243 .prcm_offs = DRA7XX_PRM_MPU_INST, 243 .prcm_offs = DRA7XX_PRM_MPU_INST,
244 .prcm_partition = DRA7XX_PRM_PARTITION, 244 .prcm_partition = DRA7XX_PRM_PARTITION,
245 .pwrsts = PWRSTS_RET_ON, 245 .pwrsts = PWRSTS_RET_ON,
246 .pwrsts_logic_ret = PWRSTS_OFF_RET, 246 .pwrsts_logic_ret = PWRSTS_RET,
247 .banks = 2, 247 .banks = 2,
248 .pwrsts_mem_ret = { 248 .pwrsts_mem_ret = {
249 [0] = PWRSTS_OFF_RET, /* mpu_l2 */ 249 [0] = PWRSTS_OFF_RET, /* mpu_l2 */