cpuidle-kirkwood.c revision dc28094b905a872f8884f1f1c48ca86b3b78583a
1e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury/* 2e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury * arch/arm/mach-kirkwood/cpuidle.c 3e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury * 4e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury * CPU idle Marvell Kirkwood SoCs 5e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury * 6e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury * This file is licensed under the terms of the GNU General Public 7e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury * License version 2. This program is licensed "as is" without any 8e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury * warranty of any kind, whether express or implied. 9e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury * 10e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury * The cpu idle uses wait-for-interrupt and DDR self refresh in order 11e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury * to implement two idle states - 12e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury * #1 wait-for-interrupt 13e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury * #2 wait-for-interrupt and DDR self refresh 14e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury */ 15e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury 16e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury#include <linux/kernel.h> 17e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury#include <linux/init.h> 18e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury#include <linux/platform_device.h> 19e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury#include <linux/cpuidle.h> 20e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury#include <linux/io.h> 21dc28094b905a872f8884f1f1c48ca86b3b78583aPaul Gortmaker#include <linux/export.h> 22e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury#include <asm/proc-fns.h> 23e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury#include <mach/kirkwood.h> 24e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury 25e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury#define KIRKWOOD_MAX_STATES 2 26e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury 27e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khourystatic struct cpuidle_driver kirkwood_idle_driver = { 28e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury .name = "kirkwood_idle", 29e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury .owner = THIS_MODULE, 30e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury}; 31e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury 32e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khourystatic DEFINE_PER_CPU(struct cpuidle_device, kirkwood_cpuidle_device); 33e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury 34e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury/* Actual code that puts the SoC in different idle states */ 35e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khourystatic int kirkwood_enter_idle(struct cpuidle_device *dev, 36e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury struct cpuidle_state *state) 37e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury{ 38e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury struct timeval before, after; 39e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury int idle_time; 40e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury 41e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury local_irq_disable(); 42e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury do_gettimeofday(&before); 43e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury if (state == &dev->states[0]) 44e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury /* Wait for interrupt state */ 45e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury cpu_do_idle(); 46e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury else if (state == &dev->states[1]) { 47e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury /* 48e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury * Following write will put DDR in self refresh. 49e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury * Note that we have 256 cycles before DDR puts it 50e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury * self in self-refresh, so the wait-for-interrupt 51e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury * call afterwards won't get the DDR from self refresh 52e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury * mode. 53e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury */ 54e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury writel(0x7, DDR_OPERATION_BASE); 55e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury cpu_do_idle(); 56e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury } 57e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury do_gettimeofday(&after); 58e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury local_irq_enable(); 59e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC + 60e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury (after.tv_usec - before.tv_usec); 61e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury return idle_time; 62e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury} 63e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury 64e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury/* Initialize CPU idle by registering the idle states */ 65e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khourystatic int kirkwood_init_cpuidle(void) 66e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury{ 67e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury struct cpuidle_device *device; 68e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury 69e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury cpuidle_register_driver(&kirkwood_idle_driver); 70e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury 71e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury device = &per_cpu(kirkwood_cpuidle_device, smp_processor_id()); 72e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury device->state_count = KIRKWOOD_MAX_STATES; 73e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury 74e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury /* Wait for interrupt state */ 75e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury device->states[0].enter = kirkwood_enter_idle; 76e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury device->states[0].exit_latency = 1; 77e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury device->states[0].target_residency = 10000; 78e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury device->states[0].flags = CPUIDLE_FLAG_TIME_VALID; 79e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury strcpy(device->states[0].name, "WFI"); 80e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury strcpy(device->states[0].desc, "Wait for interrupt"); 81e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury 82e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury /* Wait for interrupt and DDR self refresh state */ 83e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury device->states[1].enter = kirkwood_enter_idle; 84e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury device->states[1].exit_latency = 10; 85e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury device->states[1].target_residency = 10000; 86e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury device->states[1].flags = CPUIDLE_FLAG_TIME_VALID; 87e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury strcpy(device->states[1].name, "DDR SR"); 88e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury strcpy(device->states[1].desc, "WFI and DDR Self Refresh"); 89e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury 90e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury if (cpuidle_register_device(device)) { 91e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury printk(KERN_ERR "kirkwood_init_cpuidle: Failed registering\n"); 92e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury return -EIO; 93e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury } 94e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury return 0; 95e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury} 96e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury 97e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khourydevice_initcall(kirkwood_init_cpuidle); 98