diff options
| -rw-r--r-- | arch/arm/mach-omap2/board-3430sdp.c | 20 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/board-rx51.c | 44 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/cpuidle34xx.c | 226 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/pm.h | 20 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/pm34xx.c | 4 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/sleep34xx.S | 59 | ||||
| -rw-r--r-- | arch/arm/plat-omap/Kconfig | 17 |
7 files changed, 352 insertions, 38 deletions
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c index a10e96f48aea..f312b1513753 100644 --- a/arch/arm/mach-omap2/board-3430sdp.c +++ b/arch/arm/mach-omap2/board-3430sdp.c | |||
| @@ -46,6 +46,7 @@ | |||
| 46 | #include "mux.h" | 46 | #include "mux.h" |
| 47 | #include "sdram-qimonda-hyb18m512160af-6.h" | 47 | #include "sdram-qimonda-hyb18m512160af-6.h" |
| 48 | #include "hsmmc.h" | 48 | #include "hsmmc.h" |
| 49 | #include "pm.h" | ||
| 49 | 50 | ||
| 50 | #define CONFIG_DISABLE_HFCLK 1 | 51 | #define CONFIG_DISABLE_HFCLK 1 |
| 51 | 52 | ||
| @@ -57,6 +58,24 @@ | |||
| 57 | 58 | ||
| 58 | #define TWL4030_MSECURE_GPIO 22 | 59 | #define TWL4030_MSECURE_GPIO 22 |
| 59 | 60 | ||
| 61 | /* FIXME: These values need to be updated based on more profiling on 3430sdp*/ | ||
| 62 | static struct cpuidle_params omap3_cpuidle_params_table[] = { | ||
| 63 | /* C1 */ | ||
| 64 | {1, 2, 2, 5}, | ||
| 65 | /* C2 */ | ||
| 66 | {1, 10, 10, 30}, | ||
| 67 | /* C3 */ | ||
| 68 | {1, 50, 50, 300}, | ||
| 69 | /* C4 */ | ||
| 70 | {1, 1500, 1800, 4000}, | ||
| 71 | /* C5 */ | ||
| 72 | {1, 2500, 7500, 12000}, | ||
| 73 | /* C6 */ | ||
| 74 | {1, 3000, 8500, 15000}, | ||
| 75 | /* C7 */ | ||
| 76 | {1, 10000, 30000, 300000}, | ||
| 77 | }; | ||
| 78 | |||
| 60 | static int board_keymap[] = { | 79 | static int board_keymap[] = { |
| 61 | KEY(0, 0, KEY_LEFT), | 80 | KEY(0, 0, KEY_LEFT), |
| 62 | KEY(0, 1, KEY_RIGHT), | 81 | KEY(0, 1, KEY_RIGHT), |
| @@ -307,6 +326,7 @@ static void __init omap_3430sdp_init_irq(void) | |||
| 307 | { | 326 | { |
| 308 | omap_board_config = sdp3430_config; | 327 | omap_board_config = sdp3430_config; |
| 309 | omap_board_config_size = ARRAY_SIZE(sdp3430_config); | 328 | omap_board_config_size = ARRAY_SIZE(sdp3430_config); |
| 329 | omap3_pm_init_cpuidle(omap3_cpuidle_params_table); | ||
| 310 | omap2_init_common_hw(hyb18m512160af6_sdrc_params, NULL); | 330 | omap2_init_common_hw(hyb18m512160af6_sdrc_params, NULL); |
| 311 | omap_init_irq(); | 331 | omap_init_irq(); |
| 312 | omap_gpio_init(); | 332 | omap_gpio_init(); |
diff --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c index 0ccb8b46d157..b155c366c650 100644 --- a/arch/arm/mach-omap2/board-rx51.c +++ b/arch/arm/mach-omap2/board-rx51.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/clk.h> | 16 | #include <linux/clk.h> |
| 17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
| 18 | #include <linux/gpio.h> | 18 | #include <linux/gpio.h> |
| 19 | #include <linux/leds.h> | ||
| 19 | 20 | ||
| 20 | #include <mach/hardware.h> | 21 | #include <mach/hardware.h> |
| 21 | #include <asm/mach-types.h> | 22 | #include <asm/mach-types.h> |
| @@ -30,9 +31,49 @@ | |||
| 30 | #include <plat/usb.h> | 31 | #include <plat/usb.h> |
| 31 | 32 | ||
| 32 | #include "mux.h" | 33 | #include "mux.h" |
| 34 | #include "pm.h" | ||
| 35 | |||
| 36 | #define RX51_GPIO_SLEEP_IND 162 | ||
| 33 | 37 | ||
| 34 | struct omap_sdrc_params *rx51_get_sdram_timings(void); | 38 | struct omap_sdrc_params *rx51_get_sdram_timings(void); |
| 35 | 39 | ||
| 40 | static struct gpio_led gpio_leds[] = { | ||
| 41 | { | ||
| 42 | .name = "sleep_ind", | ||
| 43 | .gpio = RX51_GPIO_SLEEP_IND, | ||
| 44 | }, | ||
| 45 | }; | ||
| 46 | |||
| 47 | static struct gpio_led_platform_data gpio_led_info = { | ||
| 48 | .leds = gpio_leds, | ||
| 49 | .num_leds = ARRAY_SIZE(gpio_leds), | ||
| 50 | }; | ||
| 51 | |||
| 52 | static struct platform_device leds_gpio = { | ||
| 53 | .name = "leds-gpio", | ||
| 54 | .id = -1, | ||
| 55 | .dev = { | ||
| 56 | .platform_data = &gpio_led_info, | ||
| 57 | }, | ||
| 58 | }; | ||
| 59 | |||
| 60 | static struct cpuidle_params rx51_cpuidle_params[] = { | ||
| 61 | /* C1 */ | ||
| 62 | {1, 110, 162, 5}, | ||
| 63 | /* C2 */ | ||
| 64 | {1, 106, 180, 309}, | ||
| 65 | /* C3 */ | ||
| 66 | {0, 107, 410, 46057}, | ||
| 67 | /* C4 */ | ||
| 68 | {0, 121, 3374, 46057}, | ||
| 69 | /* C5 */ | ||
| 70 | {1, 855, 1146, 46057}, | ||
| 71 | /* C6 */ | ||
| 72 | {0, 7580, 4134, 484329}, | ||
| 73 | /* C7 */ | ||
| 74 | {1, 7505, 15274, 484329}, | ||
| 75 | }; | ||
| 76 | |||
| 36 | static struct omap_lcd_config rx51_lcd_config = { | 77 | static struct omap_lcd_config rx51_lcd_config = { |
| 37 | .ctrl_name = "internal", | 78 | .ctrl_name = "internal", |
| 38 | }; | 79 | }; |
| @@ -62,6 +103,7 @@ static void __init rx51_init_irq(void) | |||
| 62 | 103 | ||
| 63 | omap_board_config = rx51_config; | 104 | omap_board_config = rx51_config; |
| 64 | omap_board_config_size = ARRAY_SIZE(rx51_config); | 105 | omap_board_config_size = ARRAY_SIZE(rx51_config); |
| 106 | omap3_pm_init_cpuidle(rx51_cpuidle_params); | ||
| 65 | sdrc_params = rx51_get_sdram_timings(); | 107 | sdrc_params = rx51_get_sdram_timings(); |
| 66 | omap2_init_common_hw(sdrc_params, sdrc_params); | 108 | omap2_init_common_hw(sdrc_params, sdrc_params); |
| 67 | omap_init_irq(); | 109 | omap_init_irq(); |
| @@ -94,6 +136,8 @@ static void __init rx51_init(void) | |||
| 94 | /* Ensure SDRC pins are mux'd for self-refresh */ | 136 | /* Ensure SDRC pins are mux'd for self-refresh */ |
| 95 | omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT); | 137 | omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT); |
| 96 | omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT); | 138 | omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT); |
| 139 | |||
| 140 | platform_device_register(&leds_gpio); | ||
| 97 | } | 141 | } |
| 98 | 142 | ||
| 99 | static void __init rx51_map_io(void) | 143 | static void __init rx51_map_io(void) |
diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c index 12f0cbfc2894..3d3d035db9af 100644 --- a/arch/arm/mach-omap2/cpuidle34xx.c +++ b/arch/arm/mach-omap2/cpuidle34xx.c | |||
| @@ -45,6 +45,8 @@ | |||
| 45 | #define OMAP3_STATE_C6 5 /* C6 - MPU OFF + Core RET */ | 45 | #define OMAP3_STATE_C6 5 /* C6 - MPU OFF + Core RET */ |
| 46 | #define OMAP3_STATE_C7 6 /* C7 - MPU OFF + Core OFF */ | 46 | #define OMAP3_STATE_C7 6 /* C7 - MPU OFF + Core OFF */ |
| 47 | 47 | ||
| 48 | #define OMAP3_STATE_MAX OMAP3_STATE_C7 | ||
| 49 | |||
| 48 | struct omap3_processor_cx { | 50 | struct omap3_processor_cx { |
| 49 | u8 valid; | 51 | u8 valid; |
| 50 | u8 type; | 52 | u8 type; |
| @@ -60,6 +62,30 @@ struct omap3_processor_cx omap3_power_states[OMAP3_MAX_STATES]; | |||
| 60 | struct omap3_processor_cx current_cx_state; | 62 | struct omap3_processor_cx current_cx_state; |
| 61 | struct powerdomain *mpu_pd, *core_pd; | 63 | struct powerdomain *mpu_pd, *core_pd; |
| 62 | 64 | ||
| 65 | /* | ||
| 66 | * The latencies/thresholds for various C states have | ||
| 67 | * to be configured from the respective board files. | ||
| 68 | * These are some default values (which might not provide | ||
| 69 | * the best power savings) used on boards which do not | ||
| 70 | * pass these details from the board file. | ||
| 71 | */ | ||
| 72 | static struct cpuidle_params cpuidle_params_table[] = { | ||
| 73 | /* C1 */ | ||
| 74 | {1, 2, 2, 5}, | ||
| 75 | /* C2 */ | ||
| 76 | {1, 10, 10, 30}, | ||
| 77 | /* C3 */ | ||
| 78 | {1, 50, 50, 300}, | ||
| 79 | /* C4 */ | ||
| 80 | {1, 1500, 1800, 4000}, | ||
| 81 | /* C5 */ | ||
| 82 | {1, 2500, 7500, 12000}, | ||
| 83 | /* C6 */ | ||
| 84 | {1, 3000, 8500, 15000}, | ||
| 85 | /* C7 */ | ||
| 86 | {1, 10000, 30000, 300000}, | ||
| 87 | }; | ||
| 88 | |||
| 63 | static int omap3_idle_bm_check(void) | 89 | static int omap3_idle_bm_check(void) |
| 64 | { | 90 | { |
| 65 | if (!omap3_can_sleep()) | 91 | if (!omap3_can_sleep()) |
| @@ -104,13 +130,6 @@ static int omap3_enter_idle(struct cpuidle_device *dev, | |||
| 104 | local_irq_disable(); | 130 | local_irq_disable(); |
| 105 | local_fiq_disable(); | 131 | local_fiq_disable(); |
| 106 | 132 | ||
| 107 | if (!enable_off_mode) { | ||
| 108 | if (mpu_state < PWRDM_POWER_RET) | ||
| 109 | mpu_state = PWRDM_POWER_RET; | ||
| 110 | if (core_state < PWRDM_POWER_RET) | ||
| 111 | core_state = PWRDM_POWER_RET; | ||
| 112 | } | ||
| 113 | |||
| 114 | pwrdm_set_next_pwrst(mpu_pd, mpu_state); | 133 | pwrdm_set_next_pwrst(mpu_pd, mpu_state); |
| 115 | pwrdm_set_next_pwrst(core_pd, core_state); | 134 | pwrdm_set_next_pwrst(core_pd, core_state); |
| 116 | 135 | ||
| @@ -141,6 +160,67 @@ return_sleep_time: | |||
| 141 | } | 160 | } |
| 142 | 161 | ||
| 143 | /** | 162 | /** |
| 163 | * next_valid_state - Find next valid c-state | ||
| 164 | * @dev: cpuidle device | ||
| 165 | * @state: Currently selected c-state | ||
| 166 | * | ||
| 167 | * If the current state is valid, it is returned back to the caller. | ||
| 168 | * Else, this function searches for a lower c-state which is still | ||
| 169 | * valid (as defined in omap3_power_states[]). | ||
| 170 | */ | ||
| 171 | static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev, | ||
| 172 | struct cpuidle_state *curr) | ||
| 173 | { | ||
| 174 | struct cpuidle_state *next = NULL; | ||
| 175 | struct omap3_processor_cx *cx; | ||
| 176 | |||
| 177 | cx = (struct omap3_processor_cx *)cpuidle_get_statedata(curr); | ||
| 178 | |||
| 179 | /* Check if current state is valid */ | ||
| 180 | if (cx->valid) { | ||
| 181 | return curr; | ||
| 182 | } else { | ||
| 183 | u8 idx = OMAP3_STATE_MAX; | ||
| 184 | |||
| 185 | /* | ||
| 186 | * Reach the current state starting at highest C-state | ||
| 187 | */ | ||
| 188 | for (; idx >= OMAP3_STATE_C1; idx--) { | ||
| 189 | if (&dev->states[idx] == curr) { | ||
| 190 | next = &dev->states[idx]; | ||
| 191 | break; | ||
| 192 | } | ||
| 193 | } | ||
| 194 | |||
| 195 | /* | ||
| 196 | * Should never hit this condition. | ||
| 197 | */ | ||
| 198 | WARN_ON(next == NULL); | ||
| 199 | |||
| 200 | /* | ||
| 201 | * Drop to next valid state. | ||
| 202 | * Start search from the next (lower) state. | ||
| 203 | */ | ||
| 204 | idx--; | ||
| 205 | for (; idx >= OMAP3_STATE_C1; idx--) { | ||
| 206 | struct omap3_processor_cx *cx; | ||
| 207 | |||
| 208 | cx = cpuidle_get_statedata(&dev->states[idx]); | ||
| 209 | if (cx->valid) { | ||
| 210 | next = &dev->states[idx]; | ||
| 211 | break; | ||
| 212 | } | ||
| 213 | } | ||
| 214 | /* | ||
| 215 | * C1 and C2 are always valid. | ||
| 216 | * So, no need to check for 'next==NULL' outside this loop. | ||
| 217 | */ | ||
| 218 | } | ||
| 219 | |||
| 220 | return next; | ||
| 221 | } | ||
| 222 | |||
| 223 | /** | ||
| 144 | * omap3_enter_idle_bm - Checks for any bus activity | 224 | * omap3_enter_idle_bm - Checks for any bus activity |
| 145 | * @dev: cpuidle device | 225 | * @dev: cpuidle device |
| 146 | * @state: The target state to be programmed | 226 | * @state: The target state to be programmed |
| @@ -152,7 +232,7 @@ return_sleep_time: | |||
| 152 | static int omap3_enter_idle_bm(struct cpuidle_device *dev, | 232 | static int omap3_enter_idle_bm(struct cpuidle_device *dev, |
| 153 | struct cpuidle_state *state) | 233 | struct cpuidle_state *state) |
| 154 | { | 234 | { |
| 155 | struct cpuidle_state *new_state = state; | 235 | struct cpuidle_state *new_state = next_valid_state(dev, state); |
| 156 | 236 | ||
| 157 | if ((state->flags & CPUIDLE_FLAG_CHECK_BM) && omap3_idle_bm_check()) { | 237 | if ((state->flags & CPUIDLE_FLAG_CHECK_BM) && omap3_idle_bm_check()) { |
| 158 | BUG_ON(!dev->safe_state); | 238 | BUG_ON(!dev->safe_state); |
| @@ -165,6 +245,50 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev, | |||
| 165 | 245 | ||
| 166 | DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev); | 246 | DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev); |
| 167 | 247 | ||
| 248 | /** | ||
| 249 | * omap3_cpuidle_update_states - Update the cpuidle states. | ||
| 250 | * | ||
| 251 | * Currently, this function toggles the validity of idle states based upon | ||
| 252 | * the flag 'enable_off_mode'. When the flag is set all states are valid. | ||
| 253 | * Else, states leading to OFF state set to be invalid. | ||
| 254 | */ | ||
| 255 | void omap3_cpuidle_update_states(void) | ||
| 256 | { | ||
| 257 | int i; | ||
| 258 | |||
| 259 | for (i = OMAP3_STATE_C1; i < OMAP3_MAX_STATES; i++) { | ||
| 260 | struct omap3_processor_cx *cx = &omap3_power_states[i]; | ||
| 261 | |||
| 262 | if (enable_off_mode) { | ||
| 263 | cx->valid = 1; | ||
| 264 | } else { | ||
| 265 | if ((cx->mpu_state == PWRDM_POWER_OFF) || | ||
| 266 | (cx->core_state == PWRDM_POWER_OFF)) | ||
| 267 | cx->valid = 0; | ||
| 268 | } | ||
| 269 | } | ||
| 270 | } | ||
| 271 | |||
| 272 | void omap3_pm_init_cpuidle(struct cpuidle_params *cpuidle_board_params) | ||
| 273 | { | ||
| 274 | int i; | ||
| 275 | |||
| 276 | if (!cpuidle_board_params) | ||
| 277 | return; | ||
| 278 | |||
| 279 | for (i = OMAP3_STATE_C1; i < OMAP3_MAX_STATES; i++) { | ||
| 280 | cpuidle_params_table[i].valid = | ||
| 281 | cpuidle_board_params[i].valid; | ||
| 282 | cpuidle_params_table[i].sleep_latency = | ||
| 283 | cpuidle_board_params[i].sleep_latency; | ||
| 284 | cpuidle_params_table[i].wake_latency = | ||
| 285 | cpuidle_board_params[i].wake_latency; | ||
| 286 | cpuidle_params_table[i].threshold = | ||
| 287 | cpuidle_board_params[i].threshold; | ||
| 288 | } | ||
| 289 | return; | ||
| 290 | } | ||
| 291 | |||
| 168 | /* omap3_init_power_states - Initialises the OMAP3 specific C states. | 292 | /* omap3_init_power_states - Initialises the OMAP3 specific C states. |
| 169 | * | 293 | * |
| 170 | * Below is the desciption of each C state. | 294 | * Below is the desciption of each C state. |
| @@ -179,75 +303,103 @@ DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev); | |||
| 179 | void omap_init_power_states(void) | 303 | void omap_init_power_states(void) |
| 180 | { | 304 | { |
| 181 | /* C1 . MPU WFI + Core active */ | 305 | /* C1 . MPU WFI + Core active */ |
| 182 | omap3_power_states[OMAP3_STATE_C1].valid = 1; | 306 | omap3_power_states[OMAP3_STATE_C1].valid = |
| 307 | cpuidle_params_table[OMAP3_STATE_C1].valid; | ||
| 183 | omap3_power_states[OMAP3_STATE_C1].type = OMAP3_STATE_C1; | 308 | omap3_power_states[OMAP3_STATE_C1].type = OMAP3_STATE_C1; |
| 184 | omap3_power_states[OMAP3_STATE_C1].sleep_latency = 2; | 309 | omap3_power_states[OMAP3_STATE_C1].sleep_latency = |
| 185 | omap3_power_states[OMAP3_STATE_C1].wakeup_latency = 2; | 310 | cpuidle_params_table[OMAP3_STATE_C1].sleep_latency; |
| 186 | omap3_power_states[OMAP3_STATE_C1].threshold = 5; | 311 | omap3_power_states[OMAP3_STATE_C1].wakeup_latency = |
| 312 | cpuidle_params_table[OMAP3_STATE_C1].wake_latency; | ||
| 313 | omap3_power_states[OMAP3_STATE_C1].threshold = | ||
| 314 | cpuidle_params_table[OMAP3_STATE_C1].threshold; | ||
| 187 | omap3_power_states[OMAP3_STATE_C1].mpu_state = PWRDM_POWER_ON; | 315 | omap3_power_states[OMAP3_STATE_C1].mpu_state = PWRDM_POWER_ON; |
| 188 | omap3_power_states[OMAP3_STATE_C1].core_state = PWRDM_POWER_ON; | 316 | omap3_power_states[OMAP3_STATE_C1].core_state = PWRDM_POWER_ON; |
| 189 | omap3_power_states[OMAP3_STATE_C1].flags = CPUIDLE_FLAG_TIME_VALID; | 317 | omap3_power_states[OMAP3_STATE_C1].flags = CPUIDLE_FLAG_TIME_VALID; |
| 190 | 318 | ||
| 191 | /* C2 . MPU WFI + Core inactive */ | 319 | /* C2 . MPU WFI + Core inactive */ |
| 192 | omap3_power_states[OMAP3_STATE_C2].valid = 1; | 320 | omap3_power_states[OMAP3_STATE_C2].valid = |
| 321 | cpuidle_params_table[OMAP3_STATE_C2].valid; | ||
| 193 | omap3_power_states[OMAP3_STATE_C2].type = OMAP3_STATE_C2; | 322 | omap3_power_states[OMAP3_STATE_C2].type = OMAP3_STATE_C2; |
| 194 | omap3_power_states[OMAP3_STATE_C2].sleep_latency = 10; | 323 | omap3_power_states[OMAP3_STATE_C2].sleep_latency = |
| 195 | omap3_power_states[OMAP3_STATE_C2].wakeup_latency = 10; | 324 | cpuidle_params_table[OMAP3_STATE_C2].sleep_latency; |
| 196 | omap3_power_states[OMAP3_STATE_C2].threshold = 30; | 325 | omap3_power_states[OMAP3_STATE_C2].wakeup_latency = |
| 326 | cpuidle_params_table[OMAP3_STATE_C2].wake_latency; | ||
| 327 | omap3_power_states[OMAP3_STATE_C2].threshold = | ||
| 328 | cpuidle_params_table[OMAP3_STATE_C2].threshold; | ||
| 197 | omap3_power_states[OMAP3_STATE_C2].mpu_state = PWRDM_POWER_ON; | 329 | omap3_power_states[OMAP3_STATE_C2].mpu_state = PWRDM_POWER_ON; |
| 198 | omap3_power_states[OMAP3_STATE_C2].core_state = PWRDM_POWER_ON; | 330 | omap3_power_states[OMAP3_STATE_C2].core_state = PWRDM_POWER_ON; |
| 199 | omap3_power_states[OMAP3_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID; | 331 | omap3_power_states[OMAP3_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID; |
| 200 | 332 | ||
| 201 | /* C3 . MPU CSWR + Core inactive */ | 333 | /* C3 . MPU CSWR + Core inactive */ |
| 202 | omap3_power_states[OMAP3_STATE_C3].valid = 1; | 334 | omap3_power_states[OMAP3_STATE_C3].valid = |
| 335 | cpuidle_params_table[OMAP3_STATE_C3].valid; | ||
| 203 | omap3_power_states[OMAP3_STATE_C3].type = OMAP3_STATE_C3; | 336 | omap3_power_states[OMAP3_STATE_C3].type = OMAP3_STATE_C3; |
| 204 | omap3_power_states[OMAP3_STATE_C3].sleep_latency = 50; | 337 | omap3_power_states[OMAP3_STATE_C3].sleep_latency = |
| 205 | omap3_power_states[OMAP3_STATE_C3].wakeup_latency = 50; | 338 | cpuidle_params_table[OMAP3_STATE_C3].sleep_latency; |
| 206 | omap3_power_states[OMAP3_STATE_C3].threshold = 300; | 339 | omap3_power_states[OMAP3_STATE_C3].wakeup_latency = |
| 340 | cpuidle_params_table[OMAP3_STATE_C3].wake_latency; | ||
| 341 | omap3_power_states[OMAP3_STATE_C3].threshold = | ||
| 342 | cpuidle_params_table[OMAP3_STATE_C3].threshold; | ||
| 207 | omap3_power_states[OMAP3_STATE_C3].mpu_state = PWRDM_POWER_RET; | 343 | omap3_power_states[OMAP3_STATE_C3].mpu_state = PWRDM_POWER_RET; |
| 208 | omap3_power_states[OMAP3_STATE_C3].core_state = PWRDM_POWER_ON; | 344 | omap3_power_states[OMAP3_STATE_C3].core_state = PWRDM_POWER_ON; |
| 209 | omap3_power_states[OMAP3_STATE_C3].flags = CPUIDLE_FLAG_TIME_VALID | | 345 | omap3_power_states[OMAP3_STATE_C3].flags = CPUIDLE_FLAG_TIME_VALID | |
| 210 | CPUIDLE_FLAG_CHECK_BM; | 346 | CPUIDLE_FLAG_CHECK_BM; |
| 211 | 347 | ||
| 212 | /* C4 . MPU OFF + Core inactive */ | 348 | /* C4 . MPU OFF + Core inactive */ |
| 213 | omap3_power_states[OMAP3_STATE_C4].valid = 1; | 349 | omap3_power_states[OMAP3_STATE_C4].valid = |
| 350 | cpuidle_params_table[OMAP3_STATE_C4].valid; | ||
| 214 | omap3_power_states[OMAP3_STATE_C4].type = OMAP3_STATE_C4; | 351 | omap3_power_states[OMAP3_STATE_C4].type = OMAP3_STATE_C4; |
| 215 | omap3_power_states[OMAP3_STATE_C4].sleep_latency = 1500; | 352 | omap3_power_states[OMAP3_STATE_C4].sleep_latency = |
| 216 | omap3_power_states[OMAP3_STATE_C4].wakeup_latency = 1800; | 353 | cpuidle_params_table[OMAP3_STATE_C4].sleep_latency; |
| 217 | omap3_power_states[OMAP3_STATE_C4].threshold = 4000; | 354 | omap3_power_states[OMAP3_STATE_C4].wakeup_latency = |
| 355 | cpuidle_params_table[OMAP3_STATE_C4].wake_latency; | ||
| 356 | omap3_power_states[OMAP3_STATE_C4].threshold = | ||
| 357 | cpuidle_params_table[OMAP3_STATE_C4].threshold; | ||
| 218 | omap3_power_states[OMAP3_STATE_C4].mpu_state = PWRDM_POWER_OFF; | 358 | omap3_power_states[OMAP3_STATE_C4].mpu_state = PWRDM_POWER_OFF; |
| 219 | omap3_power_states[OMAP3_STATE_C4].core_state = PWRDM_POWER_ON; | 359 | omap3_power_states[OMAP3_STATE_C4].core_state = PWRDM_POWER_ON; |
| 220 | omap3_power_states[OMAP3_STATE_C4].flags = CPUIDLE_FLAG_TIME_VALID | | 360 | omap3_power_states[OMAP3_STATE_C4].flags = CPUIDLE_FLAG_TIME_VALID | |
| 221 | CPUIDLE_FLAG_CHECK_BM; | 361 | CPUIDLE_FLAG_CHECK_BM; |
| 222 | 362 | ||
| 223 | /* C5 . MPU CSWR + Core CSWR*/ | 363 | /* C5 . MPU CSWR + Core CSWR*/ |
| 224 | omap3_power_states[OMAP3_STATE_C5].valid = 1; | 364 | omap3_power_states[OMAP3_STATE_C5].valid = |
| 365 | cpuidle_params_table[OMAP3_STATE_C5].valid; | ||
| 225 | omap3_power_states[OMAP3_STATE_C5].type = OMAP3_STATE_C5; | 366 | omap3_power_states[OMAP3_STATE_C5].type = OMAP3_STATE_C5; |
| 226 | omap3_power_states[OMAP3_STATE_C5].sleep_latency = 2500; | 367 | omap3_power_states[OMAP3_STATE_C5].sleep_latency = |
| 227 | omap3_power_states[OMAP3_STATE_C5].wakeup_latency = 7500; | 368 | cpuidle_params_table[OMAP3_STATE_C5].sleep_latency; |
| 228 | omap3_power_states[OMAP3_STATE_C5].threshold = 12000; | 369 | omap3_power_states[OMAP3_STATE_C5].wakeup_latency = |
| 370 | cpuidle_params_table[OMAP3_STATE_C5].wake_latency; | ||
| 371 | omap3_power_states[OMAP3_STATE_C5].threshold = | ||
| 372 | cpuidle_params_table[OMAP3_STATE_C5].threshold; | ||
| 229 | omap3_power_states[OMAP3_STATE_C5].mpu_state = PWRDM_POWER_RET; | 373 | omap3_power_states[OMAP3_STATE_C5].mpu_state = PWRDM_POWER_RET; |
| 230 | omap3_power_states[OMAP3_STATE_C5].core_state = PWRDM_POWER_RET; | 374 | omap3_power_states[OMAP3_STATE_C5].core_state = PWRDM_POWER_RET; |
| 231 | omap3_power_states[OMAP3_STATE_C5].flags = CPUIDLE_FLAG_TIME_VALID | | 375 | omap3_power_states[OMAP3_STATE_C5].flags = CPUIDLE_FLAG_TIME_VALID | |
| 232 | CPUIDLE_FLAG_CHECK_BM; | 376 | CPUIDLE_FLAG_CHECK_BM; |
| 233 | 377 | ||
| 234 | /* C6 . MPU OFF + Core CSWR */ | 378 | /* C6 . MPU OFF + Core CSWR */ |
| 235 | omap3_power_states[OMAP3_STATE_C6].valid = 1; | 379 | omap3_power_states[OMAP3_STATE_C6].valid = |
| 380 | cpuidle_params_table[OMAP3_STATE_C6].valid; | ||
| 236 | omap3_power_states[OMAP3_STATE_C6].type = OMAP3_STATE_C6; | 381 | omap3_power_states[OMAP3_STATE_C6].type = OMAP3_STATE_C6; |
| 237 | omap3_power_states[OMAP3_STATE_C6].sleep_latency = 3000; | 382 | omap3_power_states[OMAP3_STATE_C6].sleep_latency = |
| 238 | omap3_power_states[OMAP3_STATE_C6].wakeup_latency = 8500; | 383 | cpuidle_params_table[OMAP3_STATE_C6].sleep_latency; |
| 239 | omap3_power_states[OMAP3_STATE_C6].threshold = 15000; | 384 | omap3_power_states[OMAP3_STATE_C6].wakeup_latency = |
| 385 | cpuidle_params_table[OMAP3_STATE_C6].wake_latency; | ||
| 386 | omap3_power_states[OMAP3_STATE_C6].threshold = | ||
| 387 | cpuidle_params_table[OMAP3_STATE_C6].threshold; | ||
| 240 | omap3_power_states[OMAP3_STATE_C6].mpu_state = PWRDM_POWER_OFF; | 388 | omap3_power_states[OMAP3_STATE_C6].mpu_state = PWRDM_POWER_OFF; |
| 241 | omap3_power_states[OMAP3_STATE_C6].core_state = PWRDM_POWER_RET; | 389 | omap3_power_states[OMAP3_STATE_C6].core_state = PWRDM_POWER_RET; |
| 242 | omap3_power_states[OMAP3_STATE_C6].flags = CPUIDLE_FLAG_TIME_VALID | | 390 | omap3_power_states[OMAP3_STATE_C6].flags = CPUIDLE_FLAG_TIME_VALID | |
| 243 | CPUIDLE_FLAG_CHECK_BM; | 391 | CPUIDLE_FLAG_CHECK_BM; |
| 244 | 392 | ||
| 245 | /* C7 . MPU OFF + Core OFF */ | 393 | /* C7 . MPU OFF + Core OFF */ |
| 246 | omap3_power_states[OMAP3_STATE_C7].valid = 1; | 394 | omap3_power_states[OMAP3_STATE_C7].valid = |
| 395 | cpuidle_params_table[OMAP3_STATE_C7].valid; | ||
| 247 | omap3_power_states[OMAP3_STATE_C7].type = OMAP3_STATE_C7; | 396 | omap3_power_states[OMAP3_STATE_C7].type = OMAP3_STATE_C7; |
| 248 | omap3_power_states[OMAP3_STATE_C7].sleep_latency = 10000; | 397 | omap3_power_states[OMAP3_STATE_C7].sleep_latency = |
| 249 | omap3_power_states[OMAP3_STATE_C7].wakeup_latency = 30000; | 398 | cpuidle_params_table[OMAP3_STATE_C7].sleep_latency; |
| 250 | omap3_power_states[OMAP3_STATE_C7].threshold = 300000; | 399 | omap3_power_states[OMAP3_STATE_C7].wakeup_latency = |
| 400 | cpuidle_params_table[OMAP3_STATE_C7].wake_latency; | ||
| 401 | omap3_power_states[OMAP3_STATE_C7].threshold = | ||
| 402 | cpuidle_params_table[OMAP3_STATE_C7].threshold; | ||
| 251 | omap3_power_states[OMAP3_STATE_C7].mpu_state = PWRDM_POWER_OFF; | 403 | omap3_power_states[OMAP3_STATE_C7].mpu_state = PWRDM_POWER_OFF; |
| 252 | omap3_power_states[OMAP3_STATE_C7].core_state = PWRDM_POWER_OFF; | 404 | omap3_power_states[OMAP3_STATE_C7].core_state = PWRDM_POWER_OFF; |
| 253 | omap3_power_states[OMAP3_STATE_C7].flags = CPUIDLE_FLAG_TIME_VALID | | 405 | omap3_power_states[OMAP3_STATE_C7].flags = CPUIDLE_FLAG_TIME_VALID | |
| @@ -302,6 +454,8 @@ int __init omap3_idle_init(void) | |||
| 302 | return -EINVAL; | 454 | return -EINVAL; |
| 303 | dev->state_count = count; | 455 | dev->state_count = count; |
| 304 | 456 | ||
| 457 | omap3_cpuidle_update_states(); | ||
| 458 | |||
| 305 | if (cpuidle_register_device(dev)) { | 459 | if (cpuidle_register_device(dev)) { |
| 306 | printk(KERN_ERR "%s: CPUidle register device failed\n", | 460 | printk(KERN_ERR "%s: CPUidle register device failed\n", |
| 307 | __func__); | 461 | __func__); |
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h index 7a9c2d004511..bd6466a2b039 100644 --- a/arch/arm/mach-omap2/pm.h +++ b/arch/arm/mach-omap2/pm.h | |||
| @@ -23,6 +23,22 @@ extern int omap3_can_sleep(void); | |||
| 23 | extern int set_pwrdm_state(struct powerdomain *pwrdm, u32 state); | 23 | extern int set_pwrdm_state(struct powerdomain *pwrdm, u32 state); |
| 24 | extern int omap3_idle_init(void); | 24 | extern int omap3_idle_init(void); |
| 25 | 25 | ||
| 26 | struct cpuidle_params { | ||
| 27 | u8 valid; | ||
| 28 | u32 sleep_latency; | ||
| 29 | u32 wake_latency; | ||
| 30 | u32 threshold; | ||
| 31 | }; | ||
| 32 | |||
| 33 | #if defined(CONFIG_PM) && defined(CONFIG_CPU_IDLE) | ||
| 34 | extern void omap3_pm_init_cpuidle(struct cpuidle_params *cpuidle_board_params); | ||
| 35 | #else | ||
| 36 | static | ||
| 37 | inline void omap3_pm_init_cpuidle(struct cpuidle_params *cpuidle_board_params) | ||
| 38 | { | ||
| 39 | } | ||
| 40 | #endif | ||
| 41 | |||
| 26 | extern int omap3_pm_get_suspend_state(struct powerdomain *pwrdm); | 42 | extern int omap3_pm_get_suspend_state(struct powerdomain *pwrdm); |
| 27 | extern int omap3_pm_set_suspend_state(struct powerdomain *pwrdm, int state); | 43 | extern int omap3_pm_set_suspend_state(struct powerdomain *pwrdm, int state); |
| 28 | 44 | ||
| @@ -37,6 +53,10 @@ extern int omap2_pm_debug; | |||
| 37 | #define omap2_pm_debug 0 | 53 | #define omap2_pm_debug 0 |
| 38 | #endif | 54 | #endif |
| 39 | 55 | ||
| 56 | #if defined(CONFIG_CPU_IDLE) | ||
| 57 | extern void omap3_cpuidle_update_states(void); | ||
| 58 | #endif | ||
| 59 | |||
| 40 | #if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) | 60 | #if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) |
| 41 | extern void pm_dbg_update_time(struct powerdomain *pwrdm, int prev); | 61 | extern void pm_dbg_update_time(struct powerdomain *pwrdm, int prev); |
| 42 | extern int pm_dbg_regset_save(int reg_set); | 62 | extern int pm_dbg_regset_save(int reg_set); |
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 5087b153b093..5320229926e4 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c | |||
| @@ -941,6 +941,10 @@ void omap3_pm_off_mode_enable(int enable) | |||
| 941 | else | 941 | else |
| 942 | state = PWRDM_POWER_RET; | 942 | state = PWRDM_POWER_RET; |
| 943 | 943 | ||
| 944 | #ifdef CONFIG_CPU_IDLE | ||
| 945 | omap3_cpuidle_update_states(); | ||
| 946 | #endif | ||
| 947 | |||
| 944 | list_for_each_entry(pwrst, &pwrst_list, node) { | 948 | list_for_each_entry(pwrst, &pwrst_list, node) { |
| 945 | pwrst->next_state = state; | 949 | pwrst->next_state = state; |
| 946 | set_pwrdm_state(pwrst->pwrdm, state); | 950 | set_pwrdm_state(pwrst->pwrdm, state); |
diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S index 22fcc14e63be..d522cd70bf53 100644 --- a/arch/arm/mach-omap2/sleep34xx.S +++ b/arch/arm/mach-omap2/sleep34xx.S | |||
| @@ -33,6 +33,8 @@ | |||
| 33 | #include "prm.h" | 33 | #include "prm.h" |
| 34 | #include "sdrc.h" | 34 | #include "sdrc.h" |
| 35 | 35 | ||
| 36 | #define SDRC_SCRATCHPAD_SEM_V 0xfa00291c | ||
| 37 | |||
| 36 | #define PM_PREPWSTST_CORE_V OMAP34XX_PRM_REGADDR(CORE_MOD, \ | 38 | #define PM_PREPWSTST_CORE_V OMAP34XX_PRM_REGADDR(CORE_MOD, \ |
| 37 | OMAP3430_PM_PREPWSTST) | 39 | OMAP3430_PM_PREPWSTST) |
| 38 | #define PM_PREPWSTST_CORE_P 0x48306AE8 | 40 | #define PM_PREPWSTST_CORE_P 0x48306AE8 |
| @@ -57,6 +59,37 @@ | |||
| 57 | #define SDRC_DLLA_STATUS_V OMAP34XX_SDRC_REGADDR(SDRC_DLLA_STATUS) | 59 | #define SDRC_DLLA_STATUS_V OMAP34XX_SDRC_REGADDR(SDRC_DLLA_STATUS) |
| 58 | #define SDRC_DLLA_CTRL_V OMAP34XX_SDRC_REGADDR(SDRC_DLLA_CTRL) | 60 | #define SDRC_DLLA_CTRL_V OMAP34XX_SDRC_REGADDR(SDRC_DLLA_CTRL) |
| 59 | 61 | ||
| 62 | .text | ||
| 63 | /* Function to aquire the semaphore in scratchpad */ | ||
| 64 | ENTRY(lock_scratchpad_sem) | ||
| 65 | stmfd sp!, {lr} @ save registers on stack | ||
| 66 | wait_sem: | ||
| 67 | mov r0,#1 | ||
| 68 | ldr r1, sdrc_scratchpad_sem | ||
| 69 | wait_loop: | ||
| 70 | ldr r2, [r1] @ load the lock value | ||
| 71 | cmp r2, r0 @ is the lock free ? | ||
| 72 | beq wait_loop @ not free... | ||
| 73 | swp r2, r0, [r1] @ semaphore free so lock it and proceed | ||
| 74 | cmp r2, r0 @ did we succeed ? | ||
| 75 | beq wait_sem @ no - try again | ||
| 76 | ldmfd sp!, {pc} @ restore regs and return | ||
| 77 | sdrc_scratchpad_sem: | ||
| 78 | .word SDRC_SCRATCHPAD_SEM_V | ||
| 79 | ENTRY(lock_scratchpad_sem_sz) | ||
| 80 | .word . - lock_scratchpad_sem | ||
| 81 | |||
| 82 | .text | ||
| 83 | /* Function to release the scratchpad semaphore */ | ||
| 84 | ENTRY(unlock_scratchpad_sem) | ||
| 85 | stmfd sp!, {lr} @ save registers on stack | ||
| 86 | ldr r3, sdrc_scratchpad_sem | ||
| 87 | mov r2,#0 | ||
| 88 | str r2,[r3] | ||
| 89 | ldmfd sp!, {pc} @ restore regs and return | ||
| 90 | ENTRY(unlock_scratchpad_sem_sz) | ||
| 91 | .word . - unlock_scratchpad_sem | ||
| 92 | |||
| 60 | .text | 93 | .text |
| 61 | /* Function call to get the restore pointer for resume from OFF */ | 94 | /* Function call to get the restore pointer for resume from OFF */ |
| 62 | ENTRY(get_restore_pointer) | 95 | ENTRY(get_restore_pointer) |
| @@ -251,6 +284,21 @@ restore: | |||
| 251 | mcr p15, 0, r0, c7, c10, 5 @ data memory barrier | 284 | mcr p15, 0, r0, c7, c10, 5 @ data memory barrier |
| 252 | .word 0xE1600071 @ call SMI monitor (smi #1) | 285 | .word 0xE1600071 @ call SMI monitor (smi #1) |
| 253 | 286 | ||
| 287 | #ifdef CONFIG_OMAP3_L2_AUX_SECURE_SAVE_RESTORE | ||
| 288 | /* Restore L2 aux control register */ | ||
| 289 | @ set service ID for PPA | ||
| 290 | mov r0, #CONFIG_OMAP3_L2_AUX_SECURE_SERVICE_SET_ID | ||
| 291 | mov r12, r0 @ copy service ID in r12 | ||
| 292 | mov r1, #0 @ set task ID for ROM code in r1 | ||
| 293 | mov r2, #4 @ set some flags in r2, r6 | ||
| 294 | mov r6, #0xff | ||
| 295 | ldr r4, scratchpad_base | ||
| 296 | ldr r3, [r4, #0xBC] | ||
| 297 | adds r3, r3, #8 @ r3 points to parameters | ||
| 298 | mcr p15, 0, r0, c7, c10, 4 @ data write barrier | ||
| 299 | mcr p15, 0, r0, c7, c10, 5 @ data memory barrier | ||
| 300 | .word 0xE1600071 @ call SMI monitor (smi #1) | ||
| 301 | #endif | ||
| 254 | b logic_l1_restore | 302 | b logic_l1_restore |
| 255 | l2_inv_api_params: | 303 | l2_inv_api_params: |
| 256 | .word 0x1, 0x00 | 304 | .word 0x1, 0x00 |
| @@ -264,6 +312,11 @@ smi: .word 0xE1600070 @ Call SMI monitor (smieq) | |||
| 264 | ldr r0, [r3,#4] | 312 | ldr r0, [r3,#4] |
| 265 | mov r12, #0x3 | 313 | mov r12, #0x3 |
| 266 | .word 0xE1600070 @ Call SMI monitor (smieq) | 314 | .word 0xE1600070 @ Call SMI monitor (smieq) |
| 315 | ldr r4, scratchpad_base | ||
| 316 | ldr r3, [r4,#0xBC] | ||
| 317 | ldr r0, [r3,#12] | ||
| 318 | mov r12, #0x2 | ||
| 319 | .word 0xE1600070 @ Call SMI monitor (smieq) | ||
| 267 | logic_l1_restore: | 320 | logic_l1_restore: |
| 268 | mov r1, #0 | 321 | mov r1, #0 |
| 269 | /* Invalidate all instruction caches to PoU | 322 | /* Invalidate all instruction caches to PoU |
| @@ -272,7 +325,7 @@ logic_l1_restore: | |||
| 272 | 325 | ||
| 273 | ldr r4, scratchpad_base | 326 | ldr r4, scratchpad_base |
| 274 | ldr r3, [r4,#0xBC] | 327 | ldr r3, [r4,#0xBC] |
| 275 | adds r3, r3, #8 | 328 | adds r3, r3, #16 |
| 276 | ldmia r3!, {r4-r6} | 329 | ldmia r3!, {r4-r6} |
| 277 | mov sp, r4 | 330 | mov sp, r4 |
| 278 | msr spsr_cxsf, r5 | 331 | msr spsr_cxsf, r5 |
| @@ -391,7 +444,9 @@ save_context_wfi: | |||
| 391 | mov r8, r0 /* Store SDRAM address in r8 */ | 444 | mov r8, r0 /* Store SDRAM address in r8 */ |
| 392 | mrc p15, 0, r5, c1, c0, 1 @ Read Auxiliary Control Register | 445 | mrc p15, 0, r5, c1, c0, 1 @ Read Auxiliary Control Register |
| 393 | mov r4, #0x1 @ Number of parameters for restore call | 446 | mov r4, #0x1 @ Number of parameters for restore call |
| 394 | stmia r8!, {r4-r5} | 447 | stmia r8!, {r4-r5} @ Push parameters for restore call |
| 448 | mrc p15, 1, r5, c9, c0, 2 @ Read L2 AUX ctrl register | ||
| 449 | stmia r8!, {r4-r5} @ Push parameters for restore call | ||
| 395 | /* Check what that target sleep state is:stored in r1*/ | 450 | /* Check what that target sleep state is:stored in r1*/ |
| 396 | /* 1 - Only L1 and logic lost */ | 451 | /* 1 - Only L1 and logic lost */ |
| 397 | /* 2 - Only L2 lost */ | 452 | /* 2 - Only L2 lost */ |
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index 97d0c79ffd2b..be9484a28b12 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig | |||
| @@ -135,6 +135,23 @@ config OMAP_32K_TIMER | |||
| 135 | 135 | ||
| 136 | endchoice | 136 | endchoice |
| 137 | 137 | ||
| 138 | config OMAP3_L2_AUX_SECURE_SAVE_RESTORE | ||
| 139 | bool "OMAP3 HS/EMU save and restore for L2 AUX control register" | ||
| 140 | depends on ARCH_OMAP3 && PM | ||
| 141 | default n | ||
| 142 | help | ||
| 143 | Without this option, L2 Auxiliary control register contents are | ||
| 144 | lost during off-mode entry on HS/EMU devices. This feature | ||
| 145 | requires support from PPA / boot-loader in HS/EMU devices, which | ||
| 146 | currently does not exist by default. | ||
| 147 | |||
| 148 | config OMAP3_L2_AUX_SECURE_SERVICE_SET_ID | ||
| 149 | int "Service ID for the support routine to set L2 AUX control" | ||
| 150 | depends on OMAP3_L2_AUX_SECURE_SAVE_RESTORE | ||
| 151 | default 43 | ||
| 152 | help | ||
| 153 | PPA routine service ID for setting L2 auxiliary control register. | ||
| 154 | |||
| 138 | config OMAP_32K_TIMER_HZ | 155 | config OMAP_32K_TIMER_HZ |
| 139 | int "Kernel internal timer frequency for 32KHz timer" | 156 | int "Kernel internal timer frequency for 32KHz timer" |
| 140 | range 32 1024 | 157 | range 32 1024 |
