1/* 2 * based on arch/arm/mach-kirkwood/cpuidle.c 3 * 4 * CPU idle support for AT91 SoC 5 * 6 * This file is licensed under the terms of the GNU General Public 7 * License version 2. This program is licensed "as is" without any 8 * warranty of any kind, whether express or implied. 9 * 10 * The cpu idle uses wait-for-interrupt and RAM self refresh in order 11 * to implement two idle states - 12 * #1 wait-for-interrupt 13 * #2 wait-for-interrupt and RAM self refresh 14 */ 15 16#include <linux/kernel.h> 17#include <linux/init.h> 18#include <linux/platform_device.h> 19#include <linux/cpuidle.h> 20#include <asm/proc-fns.h> 21#include <linux/io.h> 22 23#include "pm.h" 24 25#define AT91_MAX_STATES 2 26 27static DEFINE_PER_CPU(struct cpuidle_device, at91_cpuidle_device); 28 29static struct cpuidle_driver at91_idle_driver = { 30 .name = "at91_idle", 31 .owner = THIS_MODULE, 32}; 33 34/* Actual code that puts the SoC in different idle states */ 35static int at91_enter_idle(struct cpuidle_device *dev, 36 struct cpuidle_state *state) 37{ 38 struct timeval before, after; 39 int idle_time; 40 u32 saved_lpr; 41 42 local_irq_disable(); 43 do_gettimeofday(&before); 44 if (state == &dev->states[0]) 45 /* Wait for interrupt state */ 46 cpu_do_idle(); 47 else if (state == &dev->states[1]) { 48 asm("b 1f; .align 5; 1:"); 49 asm("mcr p15, 0, r0, c7, c10, 4"); /* drain write buffer */ 50 saved_lpr = sdram_selfrefresh_enable(); 51 cpu_do_idle(); 52 sdram_selfrefresh_disable(saved_lpr); 53 } 54 do_gettimeofday(&after); 55 local_irq_enable(); 56 idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC + 57 (after.tv_usec - before.tv_usec); 58 return idle_time; 59} 60 61/* Initialize CPU idle by registering the idle states */ 62static int at91_init_cpuidle(void) 63{ 64 struct cpuidle_device *device; 65 66 cpuidle_register_driver(&at91_idle_driver); 67 68 device = &per_cpu(at91_cpuidle_device, smp_processor_id()); 69 device->state_count = AT91_MAX_STATES; 70 71 /* Wait for interrupt state */ 72 device->states[0].enter = at91_enter_idle; 73 device->states[0].exit_latency = 1; 74 device->states[0].target_residency = 10000; 75 device->states[0].flags = CPUIDLE_FLAG_TIME_VALID; 76 strcpy(device->states[0].name, "WFI"); 77 strcpy(device->states[0].desc, "Wait for interrupt"); 78 79 /* Wait for interrupt and RAM self refresh state */ 80 device->states[1].enter = at91_enter_idle; 81 device->states[1].exit_latency = 10; 82 device->states[1].target_residency = 10000; 83 device->states[1].flags = CPUIDLE_FLAG_TIME_VALID; 84 strcpy(device->states[1].name, "RAM_SR"); 85 strcpy(device->states[1].desc, "WFI and RAM Self Refresh"); 86 87 if (cpuidle_register_device(device)) { 88 printk(KERN_ERR "at91_init_cpuidle: Failed registering\n"); 89 return -EIO; 90 } 91 return 0; 92} 93 94device_initcall(at91_init_cpuidle); 95