Path: blob/master/arch/arm/mach-kirkwood/cpuidle.c
10819 views
/*1* arch/arm/mach-kirkwood/cpuidle.c2*3* CPU idle Marvell Kirkwood SoCs4*5* This file is licensed under the terms of the GNU General Public6* License version 2. This program is licensed "as is" without any7* warranty of any kind, whether express or implied.8*9* The cpu idle uses wait-for-interrupt and DDR self refresh in order10* to implement two idle states -11* #1 wait-for-interrupt12* #2 wait-for-interrupt and DDR self refresh13*/1415#include <linux/kernel.h>16#include <linux/init.h>17#include <linux/platform_device.h>18#include <linux/cpuidle.h>19#include <linux/io.h>20#include <asm/proc-fns.h>21#include <mach/kirkwood.h>2223#define KIRKWOOD_MAX_STATES 22425static struct cpuidle_driver kirkwood_idle_driver = {26.name = "kirkwood_idle",27.owner = THIS_MODULE,28};2930static DEFINE_PER_CPU(struct cpuidle_device, kirkwood_cpuidle_device);3132/* Actual code that puts the SoC in different idle states */33static int kirkwood_enter_idle(struct cpuidle_device *dev,34struct cpuidle_state *state)35{36struct timeval before, after;37int idle_time;3839local_irq_disable();40do_gettimeofday(&before);41if (state == &dev->states[0])42/* Wait for interrupt state */43cpu_do_idle();44else if (state == &dev->states[1]) {45/*46* Following write will put DDR in self refresh.47* Note that we have 256 cycles before DDR puts it48* self in self-refresh, so the wait-for-interrupt49* call afterwards won't get the DDR from self refresh50* mode.51*/52writel(0x7, DDR_OPERATION_BASE);53cpu_do_idle();54}55do_gettimeofday(&after);56local_irq_enable();57idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +58(after.tv_usec - before.tv_usec);59return idle_time;60}6162/* Initialize CPU idle by registering the idle states */63static int kirkwood_init_cpuidle(void)64{65struct cpuidle_device *device;6667cpuidle_register_driver(&kirkwood_idle_driver);6869device = &per_cpu(kirkwood_cpuidle_device, smp_processor_id());70device->state_count = KIRKWOOD_MAX_STATES;7172/* Wait for interrupt state */73device->states[0].enter = kirkwood_enter_idle;74device->states[0].exit_latency = 1;75device->states[0].target_residency = 10000;76device->states[0].flags = CPUIDLE_FLAG_TIME_VALID;77strcpy(device->states[0].name, "WFI");78strcpy(device->states[0].desc, "Wait for interrupt");7980/* Wait for interrupt and DDR self refresh state */81device->states[1].enter = kirkwood_enter_idle;82device->states[1].exit_latency = 10;83device->states[1].target_residency = 10000;84device->states[1].flags = CPUIDLE_FLAG_TIME_VALID;85strcpy(device->states[1].name, "DDR SR");86strcpy(device->states[1].desc, "WFI and DDR Self Refresh");8788if (cpuidle_register_device(device)) {89printk(KERN_ERR "kirkwood_init_cpuidle: Failed registering\n");90return -EIO;91}92return 0;93}9495device_initcall(kirkwood_init_cpuidle);969798