Loading arch/arm/mach-at91/cpuidle.c +23 −18 Original line number Diff line number Diff line Loading @@ -33,7 +33,8 @@ static struct cpuidle_driver at91_idle_driver = { /* Actual code that puts the SoC in different idle states */ static int at91_enter_idle(struct cpuidle_device *dev, struct cpuidle_state *state) struct cpuidle_driver *drv, int index) { struct timeval before, after; int idle_time; Loading @@ -41,10 +42,10 @@ static int at91_enter_idle(struct cpuidle_device *dev, local_irq_disable(); do_gettimeofday(&before); if (state == &dev->states[0]) if (index == 0) /* Wait for interrupt state */ cpu_do_idle(); else if (state == &dev->states[1]) { else if (index == 1) { asm("b 1f; .align 5; 1:"); asm("mcr p15, 0, r0, c7, c10, 4"); /* drain write buffer */ saved_lpr = sdram_selfrefresh_enable(); Loading @@ -55,34 +56,38 @@ static int at91_enter_idle(struct cpuidle_device *dev, local_irq_enable(); idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC + (after.tv_usec - before.tv_usec); return idle_time; dev->last_residency = idle_time; return index; } /* Initialize CPU idle by registering the idle states */ static int at91_init_cpuidle(void) { struct cpuidle_device *device; cpuidle_register_driver(&at91_idle_driver); struct cpuidle_driver *driver = &at91_idle_driver; device = &per_cpu(at91_cpuidle_device, smp_processor_id()); device->state_count = AT91_MAX_STATES; driver->state_count = AT91_MAX_STATES; /* Wait for interrupt state */ device->states[0].enter = at91_enter_idle; device->states[0].exit_latency = 1; device->states[0].target_residency = 10000; device->states[0].flags = CPUIDLE_FLAG_TIME_VALID; strcpy(device->states[0].name, "WFI"); strcpy(device->states[0].desc, "Wait for interrupt"); driver->states[0].enter = at91_enter_idle; driver->states[0].exit_latency = 1; driver->states[0].target_residency = 10000; driver->states[0].flags = CPUIDLE_FLAG_TIME_VALID; strcpy(driver->states[0].name, "WFI"); strcpy(driver->states[0].desc, "Wait for interrupt"); /* Wait for interrupt and RAM self refresh state */ device->states[1].enter = at91_enter_idle; device->states[1].exit_latency = 10; device->states[1].target_residency = 10000; device->states[1].flags = CPUIDLE_FLAG_TIME_VALID; strcpy(device->states[1].name, "RAM_SR"); strcpy(device->states[1].desc, "WFI and RAM Self Refresh"); driver->states[1].enter = at91_enter_idle; driver->states[1].exit_latency = 10; driver->states[1].target_residency = 10000; driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID; strcpy(driver->states[1].name, "RAM_SR"); strcpy(driver->states[1].desc, "WFI and RAM Self Refresh"); cpuidle_register_driver(&at91_idle_driver); if (cpuidle_register_device(device)) { printk(KERN_ERR "at91_init_cpuidle: Failed registering\n"); Loading arch/arm/mach-davinci/cpuidle.c +29 −22 Original line number Diff line number Diff line Loading @@ -78,9 +78,11 @@ static struct davinci_ops davinci_states[DAVINCI_CPUIDLE_MAX_STATES] = { /* Actual code that puts the SoC in different idle states */ static int davinci_enter_idle(struct cpuidle_device *dev, struct cpuidle_state *state) struct cpuidle_driver *drv, int index) { struct davinci_ops *ops = cpuidle_get_statedata(state); struct cpuidle_state_usage *state_usage = &dev->states_usage[index]; struct davinci_ops *ops = cpuidle_get_statedata(state_usage); struct timeval before, after; int idle_time; Loading @@ -98,13 +100,17 @@ static int davinci_enter_idle(struct cpuidle_device *dev, local_irq_enable(); idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC + (after.tv_usec - before.tv_usec); return idle_time; dev->last_residency = idle_time; return index; } static int __init davinci_cpuidle_probe(struct platform_device *pdev) { int ret; struct cpuidle_device *device; struct cpuidle_driver *driver = &davinci_idle_driver; struct davinci_cpuidle_config *pdata = pdev->dev.platform_data; device = &per_cpu(davinci_cpuidle_device, smp_processor_id()); Loading @@ -116,32 +122,33 @@ static int __init davinci_cpuidle_probe(struct platform_device *pdev) ddr2_reg_base = pdata->ddr2_ctlr_base; ret = cpuidle_register_driver(&davinci_idle_driver); if (ret) { dev_err(&pdev->dev, "failed to register driver\n"); return ret; } /* Wait for interrupt state */ device->states[0].enter = davinci_enter_idle; device->states[0].exit_latency = 1; device->states[0].target_residency = 10000; device->states[0].flags = CPUIDLE_FLAG_TIME_VALID; strcpy(device->states[0].name, "WFI"); strcpy(device->states[0].desc, "Wait for interrupt"); driver->states[0].enter = davinci_enter_idle; driver->states[0].exit_latency = 1; driver->states[0].target_residency = 10000; driver->states[0].flags = CPUIDLE_FLAG_TIME_VALID; strcpy(driver->states[0].name, "WFI"); strcpy(driver->states[0].desc, "Wait for interrupt"); /* Wait for interrupt and DDR self refresh state */ device->states[1].enter = davinci_enter_idle; device->states[1].exit_latency = 10; device->states[1].target_residency = 10000; device->states[1].flags = CPUIDLE_FLAG_TIME_VALID; strcpy(device->states[1].name, "DDR SR"); strcpy(device->states[1].desc, "WFI and DDR Self Refresh"); driver->states[1].enter = davinci_enter_idle; driver->states[1].exit_latency = 10; driver->states[1].target_residency = 10000; driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID; strcpy(driver->states[1].name, "DDR SR"); strcpy(driver->states[1].desc, "WFI and DDR Self Refresh"); if (pdata->ddr2_pdown) davinci_states[1].flags |= DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN; cpuidle_set_statedata(&device->states[1], &davinci_states[1]); cpuidle_set_statedata(&device->states_usage[1], &davinci_states[1]); device->state_count = DAVINCI_CPUIDLE_MAX_STATES; driver->state_count = DAVINCI_CPUIDLE_MAX_STATES; ret = cpuidle_register_driver(&davinci_idle_driver); if (ret) { dev_err(&pdev->dev, "failed to register driver\n"); return ret; } ret = cpuidle_register_device(device); if (ret) { Loading arch/arm/mach-exynos4/cpuidle.c +17 −13 Original line number Diff line number Diff line Loading @@ -16,7 +16,8 @@ #include <asm/proc-fns.h> static int exynos4_enter_idle(struct cpuidle_device *dev, struct cpuidle_state *state); struct cpuidle_driver *drv, int index); static struct cpuidle_state exynos4_cpuidle_set[] = { [0] = { Loading @@ -37,7 +38,8 @@ static struct cpuidle_driver exynos4_idle_driver = { }; static int exynos4_enter_idle(struct cpuidle_device *dev, struct cpuidle_state *state) struct cpuidle_driver *drv, int index) { struct timeval before, after; int idle_time; Loading @@ -52,29 +54,31 @@ static int exynos4_enter_idle(struct cpuidle_device *dev, idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC + (after.tv_usec - before.tv_usec); return idle_time; dev->last_residency = idle_time; return index; } static int __init exynos4_init_cpuidle(void) { int i, max_cpuidle_state, cpu_id; struct cpuidle_device *device; struct cpuidle_driver *drv = &exynos4_idle_driver; /* Setup cpuidle driver */ drv->state_count = (sizeof(exynos4_cpuidle_set) / sizeof(struct cpuidle_state)); max_cpuidle_state = drv->state_count; for (i = 0; i < max_cpuidle_state; i++) { memcpy(&drv->states[i], &exynos4_cpuidle_set[i], sizeof(struct cpuidle_state)); } cpuidle_register_driver(&exynos4_idle_driver); for_each_cpu(cpu_id, cpu_online_mask) { device = &per_cpu(exynos4_cpuidle_device, cpu_id); device->cpu = cpu_id; device->state_count = (sizeof(exynos4_cpuidle_set) / sizeof(struct cpuidle_state)); max_cpuidle_state = device->state_count; for (i = 0; i < max_cpuidle_state; i++) { memcpy(&device->states[i], &exynos4_cpuidle_set[i], sizeof(struct cpuidle_state)); } device->state_count = drv->state_count; if (cpuidle_register_device(device)) { printk(KERN_ERR "CPUidle register device failed\n,"); Loading arch/arm/mach-kirkwood/cpuidle.c +24 −18 Original line number Diff line number Diff line Loading @@ -32,17 +32,18 @@ static DEFINE_PER_CPU(struct cpuidle_device, kirkwood_cpuidle_device); /* Actual code that puts the SoC in different idle states */ static int kirkwood_enter_idle(struct cpuidle_device *dev, struct cpuidle_state *state) struct cpuidle_driver *drv, int index) { struct timeval before, after; int idle_time; local_irq_disable(); do_gettimeofday(&before); if (state == &dev->states[0]) if (index == 0) /* Wait for interrupt state */ cpu_do_idle(); else if (state == &dev->states[1]) { else if (index == 1) { /* * Following write will put DDR in self refresh. * Note that we have 256 cycles before DDR puts it Loading @@ -57,35 +58,40 @@ static int kirkwood_enter_idle(struct cpuidle_device *dev, local_irq_enable(); idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC + (after.tv_usec - before.tv_usec); return idle_time; /* Update last residency */ dev->last_residency = idle_time; return index; } /* Initialize CPU idle by registering the idle states */ static int kirkwood_init_cpuidle(void) { struct cpuidle_device *device; cpuidle_register_driver(&kirkwood_idle_driver); struct cpuidle_driver *driver = &kirkwood_idle_driver; device = &per_cpu(kirkwood_cpuidle_device, smp_processor_id()); device->state_count = KIRKWOOD_MAX_STATES; driver->state_count = KIRKWOOD_MAX_STATES; /* Wait for interrupt state */ device->states[0].enter = kirkwood_enter_idle; device->states[0].exit_latency = 1; device->states[0].target_residency = 10000; device->states[0].flags = CPUIDLE_FLAG_TIME_VALID; strcpy(device->states[0].name, "WFI"); strcpy(device->states[0].desc, "Wait for interrupt"); driver->states[0].enter = kirkwood_enter_idle; driver->states[0].exit_latency = 1; driver->states[0].target_residency = 10000; driver->states[0].flags = CPUIDLE_FLAG_TIME_VALID; strcpy(driver->states[0].name, "WFI"); strcpy(driver->states[0].desc, "Wait for interrupt"); /* Wait for interrupt and DDR self refresh state */ device->states[1].enter = kirkwood_enter_idle; device->states[1].exit_latency = 10; device->states[1].target_residency = 10000; device->states[1].flags = CPUIDLE_FLAG_TIME_VALID; strcpy(device->states[1].name, "DDR SR"); strcpy(device->states[1].desc, "WFI and DDR Self Refresh"); driver->states[1].enter = kirkwood_enter_idle; driver->states[1].exit_latency = 10; driver->states[1].target_residency = 10000; driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID; strcpy(driver->states[1].name, "DDR SR"); strcpy(driver->states[1].desc, "WFI and DDR Self Refresh"); cpuidle_register_driver(&kirkwood_idle_driver); if (cpuidle_register_device(device)) { printk(KERN_ERR "kirkwood_init_cpuidle: Failed registering\n"); return -EIO; Loading arch/arm/mach-omap2/cpuidle34xx.c +85 −48 Original line number Diff line number Diff line Loading @@ -88,17 +88,21 @@ static int _cpuidle_deny_idle(struct powerdomain *pwrdm, /** * omap3_enter_idle - Programs OMAP3 to enter the specified state * @dev: cpuidle device * @state: The target state to be programmed * @drv: cpuidle driver * @index: the index of state to be entered * * Called from the CPUidle framework to program the device to the * specified target state selected by the governor. */ static int omap3_enter_idle(struct cpuidle_device *dev, struct cpuidle_state *state) struct cpuidle_driver *drv, int index) { struct omap3_idle_statedata *cx = cpuidle_get_statedata(state); struct omap3_idle_statedata *cx = cpuidle_get_statedata(&dev->states_usage[index]); struct timespec ts_preidle, ts_postidle, ts_idle; u32 mpu_state = cx->mpu_state, core_state = cx->core_state; int idle_time; /* Used to keep track of the total time in idle */ getnstimeofday(&ts_preidle); Loading @@ -113,7 +117,7 @@ static int omap3_enter_idle(struct cpuidle_device *dev, goto return_sleep_time; /* Deny idle for C1 */ if (state == &dev->states[0]) { if (index == 0) { pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle); pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle); } Loading @@ -122,7 +126,7 @@ static int omap3_enter_idle(struct cpuidle_device *dev, omap_sram_idle(); /* Re-allow idle for C1 */ if (state == &dev->states[0]) { if (index == 0) { pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle); pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle); } Loading @@ -134,28 +138,38 @@ static int omap3_enter_idle(struct cpuidle_device *dev, local_irq_enable(); local_fiq_enable(); return ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * USEC_PER_SEC; idle_time = ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * \ USEC_PER_SEC; /* Update cpuidle counters */ dev->last_residency = idle_time; return index; } /** * next_valid_state - Find next valid C-state * @dev: cpuidle device * @state: Currently selected C-state * @drv: cpuidle driver * @index: Index of currently selected c-state * * If the current state is valid, it is returned back to the caller. * Else, this function searches for a lower c-state which is still * valid. * If the state corresponding to index is valid, index is returned back * to the caller. Else, this function searches for a lower c-state which is * still valid (as defined in omap3_power_states[]) and returns its index. * * A state is valid if the 'valid' field is enabled and * if it satisfies the enable_off_mode condition. */ static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev, struct cpuidle_state *curr) static int next_valid_state(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) { struct cpuidle_state *next = NULL; struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr); struct cpuidle_state_usage *curr_usage = &dev->states_usage[index]; struct cpuidle_state *curr = &drv->states[index]; struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr_usage); u32 mpu_deepest_state = PWRDM_POWER_RET; u32 core_deepest_state = PWRDM_POWER_RET; int next_index = -1; if (enable_off_mode) { mpu_deepest_state = PWRDM_POWER_OFF; Loading @@ -172,20 +186,20 @@ static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev, if ((cx->valid) && (cx->mpu_state >= mpu_deepest_state) && (cx->core_state >= core_deepest_state)) { return curr; return index; } else { int idx = OMAP3_NUM_STATES - 1; /* Reach the current state starting at highest C-state */ for (; idx >= 0; idx--) { if (&dev->states[idx] == curr) { next = &dev->states[idx]; if (&drv->states[idx] == curr) { next_index = idx; break; } } /* Should never hit this condition */ WARN_ON(next == NULL); WARN_ON(next_index == -1); /* * Drop to next valid state. Loading @@ -193,41 +207,44 @@ static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev, */ idx--; for (; idx >= 0; idx--) { cx = cpuidle_get_statedata(&dev->states[idx]); cx = cpuidle_get_statedata(&dev->states_usage[idx]); if ((cx->valid) && (cx->mpu_state >= mpu_deepest_state) && (cx->core_state >= core_deepest_state)) { next = &dev->states[idx]; next_index = idx; break; } } /* * C1 is always valid. * So, no need to check for 'next==NULL' outside this loop. * So, no need to check for 'next_index == -1' outside * this loop. */ } return next; return next_index; } /** * omap3_enter_idle_bm - Checks for any bus activity * @dev: cpuidle device * @state: The target state to be programmed * @drv: cpuidle driver * @index: array index of target state to be programmed * * This function checks for any pending activity and then programs * the device to the specified or a safer state. */ static int omap3_enter_idle_bm(struct cpuidle_device *dev, struct cpuidle_state *state) struct cpuidle_driver *drv, int index) { struct cpuidle_state *new_state; int new_state_idx; u32 core_next_state, per_next_state = 0, per_saved_state = 0, cam_state; struct omap3_idle_statedata *cx; int ret; if (!omap3_can_sleep()) { new_state = dev->safe_state; new_state_idx = drv->safe_state_index; goto select_state; } Loading @@ -237,7 +254,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev, */ cam_state = pwrdm_read_pwrst(cam_pd); if (cam_state == PWRDM_POWER_ON) { new_state = dev->safe_state; new_state_idx = drv->safe_state_index; goto select_state; } Loading @@ -253,7 +270,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev, * Prevent PER off if CORE is not in retention or off as this * would disable PER wakeups completely. */ cx = cpuidle_get_statedata(state); cx = cpuidle_get_statedata(&dev->states_usage[index]); core_next_state = cx->core_state; per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd); if ((per_next_state == PWRDM_POWER_OFF) && Loading @@ -264,11 +281,10 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev, if (per_next_state != per_saved_state) pwrdm_set_next_pwrst(per_pd, per_next_state); new_state = next_valid_state(dev, state); new_state_idx = next_valid_state(dev, drv, index); select_state: dev->last_state = new_state; ret = omap3_enter_idle(dev, new_state); ret = omap3_enter_idle(dev, drv, new_state_idx); /* Restore original PER state if it was modified */ if (per_next_state != per_saved_state) Loading Loading @@ -301,22 +317,31 @@ struct cpuidle_driver omap3_idle_driver = { .owner = THIS_MODULE, }; /* Helper to fill the C-state common data and register the driver_data */ static inline struct omap3_idle_statedata *_fill_cstate( struct cpuidle_device *dev, /* Helper to fill the C-state common data*/ static inline void _fill_cstate(struct cpuidle_driver *drv, int idx, const char *descr) { struct omap3_idle_statedata *cx = &omap3_idle_data[idx]; struct cpuidle_state *state = &dev->states[idx]; struct cpuidle_state *state = &drv->states[idx]; state->exit_latency = cpuidle_params_table[idx].exit_latency; state->target_residency = cpuidle_params_table[idx].target_residency; state->flags = CPUIDLE_FLAG_TIME_VALID; state->enter = omap3_enter_idle_bm; cx->valid = cpuidle_params_table[idx].valid; sprintf(state->name, "C%d", idx + 1); strncpy(state->desc, descr, CPUIDLE_DESC_LEN); cpuidle_set_statedata(state, cx); } /* Helper to register the driver_data */ static inline struct omap3_idle_statedata *_fill_cstate_usage( struct cpuidle_device *dev, int idx) { struct omap3_idle_statedata *cx = &omap3_idle_data[idx]; struct cpuidle_state_usage *state_usage = &dev->states_usage[idx]; cx->valid = cpuidle_params_table[idx].valid; cpuidle_set_statedata(state_usage, cx); return cx; } Loading @@ -330,6 +355,7 @@ static inline struct omap3_idle_statedata *_fill_cstate( int __init omap3_idle_init(void) { struct cpuidle_device *dev; struct cpuidle_driver *drv = &omap3_idle_driver; struct omap3_idle_statedata *cx; mpu_pd = pwrdm_lookup("mpu_pwrdm"); Loading @@ -337,44 +363,52 @@ int __init omap3_idle_init(void) per_pd = pwrdm_lookup("per_pwrdm"); cam_pd = pwrdm_lookup("cam_pwrdm"); cpuidle_register_driver(&omap3_idle_driver); drv->safe_state_index = -1; dev = &per_cpu(omap3_idle_dev, smp_processor_id()); /* C1 . MPU WFI + Core active */ cx = _fill_cstate(dev, 0, "MPU ON + CORE ON"); (&dev->states[0])->enter = omap3_enter_idle; dev->safe_state = &dev->states[0]; _fill_cstate(drv, 0, "MPU ON + CORE ON"); (&drv->states[0])->enter = omap3_enter_idle; drv->safe_state_index = 0; cx = _fill_cstate_usage(dev, 0); cx->valid = 1; /* C1 is always valid */ cx->mpu_state = PWRDM_POWER_ON; cx->core_state = PWRDM_POWER_ON; /* C2 . MPU WFI + Core inactive */ cx = _fill_cstate(dev, 1, "MPU ON + CORE ON"); _fill_cstate(drv, 1, "MPU ON + CORE ON"); cx = _fill_cstate_usage(dev, 1); cx->mpu_state = PWRDM_POWER_ON; cx->core_state = PWRDM_POWER_ON; /* C3 . MPU CSWR + Core inactive */ cx = _fill_cstate(dev, 2, "MPU RET + CORE ON"); _fill_cstate(drv, 2, "MPU RET + CORE ON"); cx = _fill_cstate_usage(dev, 2); cx->mpu_state = PWRDM_POWER_RET; cx->core_state = PWRDM_POWER_ON; /* C4 . MPU OFF + Core inactive */ cx = _fill_cstate(dev, 3, "MPU OFF + CORE ON"); _fill_cstate(drv, 3, "MPU OFF + CORE ON"); cx = _fill_cstate_usage(dev, 3); cx->mpu_state = PWRDM_POWER_OFF; cx->core_state = PWRDM_POWER_ON; /* C5 . MPU RET + Core RET */ cx = _fill_cstate(dev, 4, "MPU RET + CORE RET"); _fill_cstate(drv, 4, "MPU RET + CORE RET"); cx = _fill_cstate_usage(dev, 4); cx->mpu_state = PWRDM_POWER_RET; cx->core_state = PWRDM_POWER_RET; /* C6 . MPU OFF + Core RET */ cx = _fill_cstate(dev, 5, "MPU OFF + CORE RET"); _fill_cstate(drv, 5, "MPU OFF + CORE RET"); cx = _fill_cstate_usage(dev, 5); cx->mpu_state = PWRDM_POWER_OFF; cx->core_state = PWRDM_POWER_RET; /* C7 . MPU OFF + Core OFF */ cx = _fill_cstate(dev, 6, "MPU OFF + CORE OFF"); _fill_cstate(drv, 6, "MPU OFF + CORE OFF"); cx = _fill_cstate_usage(dev, 6); /* * Erratum i583: implementation for ES rev < Es1.2 on 3630. We cannot * enable OFF mode in a stable form for previous revisions. Loading @@ -388,6 +422,9 @@ int __init omap3_idle_init(void) cx->mpu_state = PWRDM_POWER_OFF; cx->core_state = PWRDM_POWER_OFF; drv->state_count = OMAP3_NUM_STATES; cpuidle_register_driver(&omap3_idle_driver); dev->state_count = OMAP3_NUM_STATES; if (cpuidle_register_device(dev)) { printk(KERN_ERR "%s: CPUidle register device failed\n", Loading Loading
arch/arm/mach-at91/cpuidle.c +23 −18 Original line number Diff line number Diff line Loading @@ -33,7 +33,8 @@ static struct cpuidle_driver at91_idle_driver = { /* Actual code that puts the SoC in different idle states */ static int at91_enter_idle(struct cpuidle_device *dev, struct cpuidle_state *state) struct cpuidle_driver *drv, int index) { struct timeval before, after; int idle_time; Loading @@ -41,10 +42,10 @@ static int at91_enter_idle(struct cpuidle_device *dev, local_irq_disable(); do_gettimeofday(&before); if (state == &dev->states[0]) if (index == 0) /* Wait for interrupt state */ cpu_do_idle(); else if (state == &dev->states[1]) { else if (index == 1) { asm("b 1f; .align 5; 1:"); asm("mcr p15, 0, r0, c7, c10, 4"); /* drain write buffer */ saved_lpr = sdram_selfrefresh_enable(); Loading @@ -55,34 +56,38 @@ static int at91_enter_idle(struct cpuidle_device *dev, local_irq_enable(); idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC + (after.tv_usec - before.tv_usec); return idle_time; dev->last_residency = idle_time; return index; } /* Initialize CPU idle by registering the idle states */ static int at91_init_cpuidle(void) { struct cpuidle_device *device; cpuidle_register_driver(&at91_idle_driver); struct cpuidle_driver *driver = &at91_idle_driver; device = &per_cpu(at91_cpuidle_device, smp_processor_id()); device->state_count = AT91_MAX_STATES; driver->state_count = AT91_MAX_STATES; /* Wait for interrupt state */ device->states[0].enter = at91_enter_idle; device->states[0].exit_latency = 1; device->states[0].target_residency = 10000; device->states[0].flags = CPUIDLE_FLAG_TIME_VALID; strcpy(device->states[0].name, "WFI"); strcpy(device->states[0].desc, "Wait for interrupt"); driver->states[0].enter = at91_enter_idle; driver->states[0].exit_latency = 1; driver->states[0].target_residency = 10000; driver->states[0].flags = CPUIDLE_FLAG_TIME_VALID; strcpy(driver->states[0].name, "WFI"); strcpy(driver->states[0].desc, "Wait for interrupt"); /* Wait for interrupt and RAM self refresh state */ device->states[1].enter = at91_enter_idle; device->states[1].exit_latency = 10; device->states[1].target_residency = 10000; device->states[1].flags = CPUIDLE_FLAG_TIME_VALID; strcpy(device->states[1].name, "RAM_SR"); strcpy(device->states[1].desc, "WFI and RAM Self Refresh"); driver->states[1].enter = at91_enter_idle; driver->states[1].exit_latency = 10; driver->states[1].target_residency = 10000; driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID; strcpy(driver->states[1].name, "RAM_SR"); strcpy(driver->states[1].desc, "WFI and RAM Self Refresh"); cpuidle_register_driver(&at91_idle_driver); if (cpuidle_register_device(device)) { printk(KERN_ERR "at91_init_cpuidle: Failed registering\n"); Loading
arch/arm/mach-davinci/cpuidle.c +29 −22 Original line number Diff line number Diff line Loading @@ -78,9 +78,11 @@ static struct davinci_ops davinci_states[DAVINCI_CPUIDLE_MAX_STATES] = { /* Actual code that puts the SoC in different idle states */ static int davinci_enter_idle(struct cpuidle_device *dev, struct cpuidle_state *state) struct cpuidle_driver *drv, int index) { struct davinci_ops *ops = cpuidle_get_statedata(state); struct cpuidle_state_usage *state_usage = &dev->states_usage[index]; struct davinci_ops *ops = cpuidle_get_statedata(state_usage); struct timeval before, after; int idle_time; Loading @@ -98,13 +100,17 @@ static int davinci_enter_idle(struct cpuidle_device *dev, local_irq_enable(); idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC + (after.tv_usec - before.tv_usec); return idle_time; dev->last_residency = idle_time; return index; } static int __init davinci_cpuidle_probe(struct platform_device *pdev) { int ret; struct cpuidle_device *device; struct cpuidle_driver *driver = &davinci_idle_driver; struct davinci_cpuidle_config *pdata = pdev->dev.platform_data; device = &per_cpu(davinci_cpuidle_device, smp_processor_id()); Loading @@ -116,32 +122,33 @@ static int __init davinci_cpuidle_probe(struct platform_device *pdev) ddr2_reg_base = pdata->ddr2_ctlr_base; ret = cpuidle_register_driver(&davinci_idle_driver); if (ret) { dev_err(&pdev->dev, "failed to register driver\n"); return ret; } /* Wait for interrupt state */ device->states[0].enter = davinci_enter_idle; device->states[0].exit_latency = 1; device->states[0].target_residency = 10000; device->states[0].flags = CPUIDLE_FLAG_TIME_VALID; strcpy(device->states[0].name, "WFI"); strcpy(device->states[0].desc, "Wait for interrupt"); driver->states[0].enter = davinci_enter_idle; driver->states[0].exit_latency = 1; driver->states[0].target_residency = 10000; driver->states[0].flags = CPUIDLE_FLAG_TIME_VALID; strcpy(driver->states[0].name, "WFI"); strcpy(driver->states[0].desc, "Wait for interrupt"); /* Wait for interrupt and DDR self refresh state */ device->states[1].enter = davinci_enter_idle; device->states[1].exit_latency = 10; device->states[1].target_residency = 10000; device->states[1].flags = CPUIDLE_FLAG_TIME_VALID; strcpy(device->states[1].name, "DDR SR"); strcpy(device->states[1].desc, "WFI and DDR Self Refresh"); driver->states[1].enter = davinci_enter_idle; driver->states[1].exit_latency = 10; driver->states[1].target_residency = 10000; driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID; strcpy(driver->states[1].name, "DDR SR"); strcpy(driver->states[1].desc, "WFI and DDR Self Refresh"); if (pdata->ddr2_pdown) davinci_states[1].flags |= DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN; cpuidle_set_statedata(&device->states[1], &davinci_states[1]); cpuidle_set_statedata(&device->states_usage[1], &davinci_states[1]); device->state_count = DAVINCI_CPUIDLE_MAX_STATES; driver->state_count = DAVINCI_CPUIDLE_MAX_STATES; ret = cpuidle_register_driver(&davinci_idle_driver); if (ret) { dev_err(&pdev->dev, "failed to register driver\n"); return ret; } ret = cpuidle_register_device(device); if (ret) { Loading
arch/arm/mach-exynos4/cpuidle.c +17 −13 Original line number Diff line number Diff line Loading @@ -16,7 +16,8 @@ #include <asm/proc-fns.h> static int exynos4_enter_idle(struct cpuidle_device *dev, struct cpuidle_state *state); struct cpuidle_driver *drv, int index); static struct cpuidle_state exynos4_cpuidle_set[] = { [0] = { Loading @@ -37,7 +38,8 @@ static struct cpuidle_driver exynos4_idle_driver = { }; static int exynos4_enter_idle(struct cpuidle_device *dev, struct cpuidle_state *state) struct cpuidle_driver *drv, int index) { struct timeval before, after; int idle_time; Loading @@ -52,29 +54,31 @@ static int exynos4_enter_idle(struct cpuidle_device *dev, idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC + (after.tv_usec - before.tv_usec); return idle_time; dev->last_residency = idle_time; return index; } static int __init exynos4_init_cpuidle(void) { int i, max_cpuidle_state, cpu_id; struct cpuidle_device *device; struct cpuidle_driver *drv = &exynos4_idle_driver; /* Setup cpuidle driver */ drv->state_count = (sizeof(exynos4_cpuidle_set) / sizeof(struct cpuidle_state)); max_cpuidle_state = drv->state_count; for (i = 0; i < max_cpuidle_state; i++) { memcpy(&drv->states[i], &exynos4_cpuidle_set[i], sizeof(struct cpuidle_state)); } cpuidle_register_driver(&exynos4_idle_driver); for_each_cpu(cpu_id, cpu_online_mask) { device = &per_cpu(exynos4_cpuidle_device, cpu_id); device->cpu = cpu_id; device->state_count = (sizeof(exynos4_cpuidle_set) / sizeof(struct cpuidle_state)); max_cpuidle_state = device->state_count; for (i = 0; i < max_cpuidle_state; i++) { memcpy(&device->states[i], &exynos4_cpuidle_set[i], sizeof(struct cpuidle_state)); } device->state_count = drv->state_count; if (cpuidle_register_device(device)) { printk(KERN_ERR "CPUidle register device failed\n,"); Loading
arch/arm/mach-kirkwood/cpuidle.c +24 −18 Original line number Diff line number Diff line Loading @@ -32,17 +32,18 @@ static DEFINE_PER_CPU(struct cpuidle_device, kirkwood_cpuidle_device); /* Actual code that puts the SoC in different idle states */ static int kirkwood_enter_idle(struct cpuidle_device *dev, struct cpuidle_state *state) struct cpuidle_driver *drv, int index) { struct timeval before, after; int idle_time; local_irq_disable(); do_gettimeofday(&before); if (state == &dev->states[0]) if (index == 0) /* Wait for interrupt state */ cpu_do_idle(); else if (state == &dev->states[1]) { else if (index == 1) { /* * Following write will put DDR in self refresh. * Note that we have 256 cycles before DDR puts it Loading @@ -57,35 +58,40 @@ static int kirkwood_enter_idle(struct cpuidle_device *dev, local_irq_enable(); idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC + (after.tv_usec - before.tv_usec); return idle_time; /* Update last residency */ dev->last_residency = idle_time; return index; } /* Initialize CPU idle by registering the idle states */ static int kirkwood_init_cpuidle(void) { struct cpuidle_device *device; cpuidle_register_driver(&kirkwood_idle_driver); struct cpuidle_driver *driver = &kirkwood_idle_driver; device = &per_cpu(kirkwood_cpuidle_device, smp_processor_id()); device->state_count = KIRKWOOD_MAX_STATES; driver->state_count = KIRKWOOD_MAX_STATES; /* Wait for interrupt state */ device->states[0].enter = kirkwood_enter_idle; device->states[0].exit_latency = 1; device->states[0].target_residency = 10000; device->states[0].flags = CPUIDLE_FLAG_TIME_VALID; strcpy(device->states[0].name, "WFI"); strcpy(device->states[0].desc, "Wait for interrupt"); driver->states[0].enter = kirkwood_enter_idle; driver->states[0].exit_latency = 1; driver->states[0].target_residency = 10000; driver->states[0].flags = CPUIDLE_FLAG_TIME_VALID; strcpy(driver->states[0].name, "WFI"); strcpy(driver->states[0].desc, "Wait for interrupt"); /* Wait for interrupt and DDR self refresh state */ device->states[1].enter = kirkwood_enter_idle; device->states[1].exit_latency = 10; device->states[1].target_residency = 10000; device->states[1].flags = CPUIDLE_FLAG_TIME_VALID; strcpy(device->states[1].name, "DDR SR"); strcpy(device->states[1].desc, "WFI and DDR Self Refresh"); driver->states[1].enter = kirkwood_enter_idle; driver->states[1].exit_latency = 10; driver->states[1].target_residency = 10000; driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID; strcpy(driver->states[1].name, "DDR SR"); strcpy(driver->states[1].desc, "WFI and DDR Self Refresh"); cpuidle_register_driver(&kirkwood_idle_driver); if (cpuidle_register_device(device)) { printk(KERN_ERR "kirkwood_init_cpuidle: Failed registering\n"); return -EIO; Loading
arch/arm/mach-omap2/cpuidle34xx.c +85 −48 Original line number Diff line number Diff line Loading @@ -88,17 +88,21 @@ static int _cpuidle_deny_idle(struct powerdomain *pwrdm, /** * omap3_enter_idle - Programs OMAP3 to enter the specified state * @dev: cpuidle device * @state: The target state to be programmed * @drv: cpuidle driver * @index: the index of state to be entered * * Called from the CPUidle framework to program the device to the * specified target state selected by the governor. */ static int omap3_enter_idle(struct cpuidle_device *dev, struct cpuidle_state *state) struct cpuidle_driver *drv, int index) { struct omap3_idle_statedata *cx = cpuidle_get_statedata(state); struct omap3_idle_statedata *cx = cpuidle_get_statedata(&dev->states_usage[index]); struct timespec ts_preidle, ts_postidle, ts_idle; u32 mpu_state = cx->mpu_state, core_state = cx->core_state; int idle_time; /* Used to keep track of the total time in idle */ getnstimeofday(&ts_preidle); Loading @@ -113,7 +117,7 @@ static int omap3_enter_idle(struct cpuidle_device *dev, goto return_sleep_time; /* Deny idle for C1 */ if (state == &dev->states[0]) { if (index == 0) { pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle); pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle); } Loading @@ -122,7 +126,7 @@ static int omap3_enter_idle(struct cpuidle_device *dev, omap_sram_idle(); /* Re-allow idle for C1 */ if (state == &dev->states[0]) { if (index == 0) { pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle); pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle); } Loading @@ -134,28 +138,38 @@ static int omap3_enter_idle(struct cpuidle_device *dev, local_irq_enable(); local_fiq_enable(); return ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * USEC_PER_SEC; idle_time = ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * \ USEC_PER_SEC; /* Update cpuidle counters */ dev->last_residency = idle_time; return index; } /** * next_valid_state - Find next valid C-state * @dev: cpuidle device * @state: Currently selected C-state * @drv: cpuidle driver * @index: Index of currently selected c-state * * If the current state is valid, it is returned back to the caller. * Else, this function searches for a lower c-state which is still * valid. * If the state corresponding to index is valid, index is returned back * to the caller. Else, this function searches for a lower c-state which is * still valid (as defined in omap3_power_states[]) and returns its index. * * A state is valid if the 'valid' field is enabled and * if it satisfies the enable_off_mode condition. */ static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev, struct cpuidle_state *curr) static int next_valid_state(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) { struct cpuidle_state *next = NULL; struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr); struct cpuidle_state_usage *curr_usage = &dev->states_usage[index]; struct cpuidle_state *curr = &drv->states[index]; struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr_usage); u32 mpu_deepest_state = PWRDM_POWER_RET; u32 core_deepest_state = PWRDM_POWER_RET; int next_index = -1; if (enable_off_mode) { mpu_deepest_state = PWRDM_POWER_OFF; Loading @@ -172,20 +186,20 @@ static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev, if ((cx->valid) && (cx->mpu_state >= mpu_deepest_state) && (cx->core_state >= core_deepest_state)) { return curr; return index; } else { int idx = OMAP3_NUM_STATES - 1; /* Reach the current state starting at highest C-state */ for (; idx >= 0; idx--) { if (&dev->states[idx] == curr) { next = &dev->states[idx]; if (&drv->states[idx] == curr) { next_index = idx; break; } } /* Should never hit this condition */ WARN_ON(next == NULL); WARN_ON(next_index == -1); /* * Drop to next valid state. Loading @@ -193,41 +207,44 @@ static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev, */ idx--; for (; idx >= 0; idx--) { cx = cpuidle_get_statedata(&dev->states[idx]); cx = cpuidle_get_statedata(&dev->states_usage[idx]); if ((cx->valid) && (cx->mpu_state >= mpu_deepest_state) && (cx->core_state >= core_deepest_state)) { next = &dev->states[idx]; next_index = idx; break; } } /* * C1 is always valid. * So, no need to check for 'next==NULL' outside this loop. * So, no need to check for 'next_index == -1' outside * this loop. */ } return next; return next_index; } /** * omap3_enter_idle_bm - Checks for any bus activity * @dev: cpuidle device * @state: The target state to be programmed * @drv: cpuidle driver * @index: array index of target state to be programmed * * This function checks for any pending activity and then programs * the device to the specified or a safer state. */ static int omap3_enter_idle_bm(struct cpuidle_device *dev, struct cpuidle_state *state) struct cpuidle_driver *drv, int index) { struct cpuidle_state *new_state; int new_state_idx; u32 core_next_state, per_next_state = 0, per_saved_state = 0, cam_state; struct omap3_idle_statedata *cx; int ret; if (!omap3_can_sleep()) { new_state = dev->safe_state; new_state_idx = drv->safe_state_index; goto select_state; } Loading @@ -237,7 +254,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev, */ cam_state = pwrdm_read_pwrst(cam_pd); if (cam_state == PWRDM_POWER_ON) { new_state = dev->safe_state; new_state_idx = drv->safe_state_index; goto select_state; } Loading @@ -253,7 +270,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev, * Prevent PER off if CORE is not in retention or off as this * would disable PER wakeups completely. */ cx = cpuidle_get_statedata(state); cx = cpuidle_get_statedata(&dev->states_usage[index]); core_next_state = cx->core_state; per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd); if ((per_next_state == PWRDM_POWER_OFF) && Loading @@ -264,11 +281,10 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev, if (per_next_state != per_saved_state) pwrdm_set_next_pwrst(per_pd, per_next_state); new_state = next_valid_state(dev, state); new_state_idx = next_valid_state(dev, drv, index); select_state: dev->last_state = new_state; ret = omap3_enter_idle(dev, new_state); ret = omap3_enter_idle(dev, drv, new_state_idx); /* Restore original PER state if it was modified */ if (per_next_state != per_saved_state) Loading Loading @@ -301,22 +317,31 @@ struct cpuidle_driver omap3_idle_driver = { .owner = THIS_MODULE, }; /* Helper to fill the C-state common data and register the driver_data */ static inline struct omap3_idle_statedata *_fill_cstate( struct cpuidle_device *dev, /* Helper to fill the C-state common data*/ static inline void _fill_cstate(struct cpuidle_driver *drv, int idx, const char *descr) { struct omap3_idle_statedata *cx = &omap3_idle_data[idx]; struct cpuidle_state *state = &dev->states[idx]; struct cpuidle_state *state = &drv->states[idx]; state->exit_latency = cpuidle_params_table[idx].exit_latency; state->target_residency = cpuidle_params_table[idx].target_residency; state->flags = CPUIDLE_FLAG_TIME_VALID; state->enter = omap3_enter_idle_bm; cx->valid = cpuidle_params_table[idx].valid; sprintf(state->name, "C%d", idx + 1); strncpy(state->desc, descr, CPUIDLE_DESC_LEN); cpuidle_set_statedata(state, cx); } /* Helper to register the driver_data */ static inline struct omap3_idle_statedata *_fill_cstate_usage( struct cpuidle_device *dev, int idx) { struct omap3_idle_statedata *cx = &omap3_idle_data[idx]; struct cpuidle_state_usage *state_usage = &dev->states_usage[idx]; cx->valid = cpuidle_params_table[idx].valid; cpuidle_set_statedata(state_usage, cx); return cx; } Loading @@ -330,6 +355,7 @@ static inline struct omap3_idle_statedata *_fill_cstate( int __init omap3_idle_init(void) { struct cpuidle_device *dev; struct cpuidle_driver *drv = &omap3_idle_driver; struct omap3_idle_statedata *cx; mpu_pd = pwrdm_lookup("mpu_pwrdm"); Loading @@ -337,44 +363,52 @@ int __init omap3_idle_init(void) per_pd = pwrdm_lookup("per_pwrdm"); cam_pd = pwrdm_lookup("cam_pwrdm"); cpuidle_register_driver(&omap3_idle_driver); drv->safe_state_index = -1; dev = &per_cpu(omap3_idle_dev, smp_processor_id()); /* C1 . MPU WFI + Core active */ cx = _fill_cstate(dev, 0, "MPU ON + CORE ON"); (&dev->states[0])->enter = omap3_enter_idle; dev->safe_state = &dev->states[0]; _fill_cstate(drv, 0, "MPU ON + CORE ON"); (&drv->states[0])->enter = omap3_enter_idle; drv->safe_state_index = 0; cx = _fill_cstate_usage(dev, 0); cx->valid = 1; /* C1 is always valid */ cx->mpu_state = PWRDM_POWER_ON; cx->core_state = PWRDM_POWER_ON; /* C2 . MPU WFI + Core inactive */ cx = _fill_cstate(dev, 1, "MPU ON + CORE ON"); _fill_cstate(drv, 1, "MPU ON + CORE ON"); cx = _fill_cstate_usage(dev, 1); cx->mpu_state = PWRDM_POWER_ON; cx->core_state = PWRDM_POWER_ON; /* C3 . MPU CSWR + Core inactive */ cx = _fill_cstate(dev, 2, "MPU RET + CORE ON"); _fill_cstate(drv, 2, "MPU RET + CORE ON"); cx = _fill_cstate_usage(dev, 2); cx->mpu_state = PWRDM_POWER_RET; cx->core_state = PWRDM_POWER_ON; /* C4 . MPU OFF + Core inactive */ cx = _fill_cstate(dev, 3, "MPU OFF + CORE ON"); _fill_cstate(drv, 3, "MPU OFF + CORE ON"); cx = _fill_cstate_usage(dev, 3); cx->mpu_state = PWRDM_POWER_OFF; cx->core_state = PWRDM_POWER_ON; /* C5 . MPU RET + Core RET */ cx = _fill_cstate(dev, 4, "MPU RET + CORE RET"); _fill_cstate(drv, 4, "MPU RET + CORE RET"); cx = _fill_cstate_usage(dev, 4); cx->mpu_state = PWRDM_POWER_RET; cx->core_state = PWRDM_POWER_RET; /* C6 . MPU OFF + Core RET */ cx = _fill_cstate(dev, 5, "MPU OFF + CORE RET"); _fill_cstate(drv, 5, "MPU OFF + CORE RET"); cx = _fill_cstate_usage(dev, 5); cx->mpu_state = PWRDM_POWER_OFF; cx->core_state = PWRDM_POWER_RET; /* C7 . MPU OFF + Core OFF */ cx = _fill_cstate(dev, 6, "MPU OFF + CORE OFF"); _fill_cstate(drv, 6, "MPU OFF + CORE OFF"); cx = _fill_cstate_usage(dev, 6); /* * Erratum i583: implementation for ES rev < Es1.2 on 3630. We cannot * enable OFF mode in a stable form for previous revisions. Loading @@ -388,6 +422,9 @@ int __init omap3_idle_init(void) cx->mpu_state = PWRDM_POWER_OFF; cx->core_state = PWRDM_POWER_OFF; drv->state_count = OMAP3_NUM_STATES; cpuidle_register_driver(&omap3_idle_driver); dev->state_count = OMAP3_NUM_STATES; if (cpuidle_register_device(dev)) { printk(KERN_ERR "%s: CPUidle register device failed\n", Loading