• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/arch/arm/mach-at91/
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