Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/arm/mach-kirkwood/cpuidle.c
10819 views
1
/*
2
* arch/arm/mach-kirkwood/cpuidle.c
3
*
4
* CPU idle Marvell Kirkwood SoCs
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 DDR self refresh in order
11
* to implement two idle states -
12
* #1 wait-for-interrupt
13
* #2 wait-for-interrupt and DDR 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 <linux/io.h>
21
#include <asm/proc-fns.h>
22
#include <mach/kirkwood.h>
23
24
#define KIRKWOOD_MAX_STATES 2
25
26
static struct cpuidle_driver kirkwood_idle_driver = {
27
.name = "kirkwood_idle",
28
.owner = THIS_MODULE,
29
};
30
31
static DEFINE_PER_CPU(struct cpuidle_device, kirkwood_cpuidle_device);
32
33
/* Actual code that puts the SoC in different idle states */
34
static int kirkwood_enter_idle(struct cpuidle_device *dev,
35
struct cpuidle_state *state)
36
{
37
struct timeval before, after;
38
int idle_time;
39
40
local_irq_disable();
41
do_gettimeofday(&before);
42
if (state == &dev->states[0])
43
/* Wait for interrupt state */
44
cpu_do_idle();
45
else if (state == &dev->states[1]) {
46
/*
47
* Following write will put DDR in self refresh.
48
* Note that we have 256 cycles before DDR puts it
49
* self in self-refresh, so the wait-for-interrupt
50
* call afterwards won't get the DDR from self refresh
51
* mode.
52
*/
53
writel(0x7, DDR_OPERATION_BASE);
54
cpu_do_idle();
55
}
56
do_gettimeofday(&after);
57
local_irq_enable();
58
idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
59
(after.tv_usec - before.tv_usec);
60
return idle_time;
61
}
62
63
/* Initialize CPU idle by registering the idle states */
64
static int kirkwood_init_cpuidle(void)
65
{
66
struct cpuidle_device *device;
67
68
cpuidle_register_driver(&kirkwood_idle_driver);
69
70
device = &per_cpu(kirkwood_cpuidle_device, smp_processor_id());
71
device->state_count = KIRKWOOD_MAX_STATES;
72
73
/* Wait for interrupt state */
74
device->states[0].enter = kirkwood_enter_idle;
75
device->states[0].exit_latency = 1;
76
device->states[0].target_residency = 10000;
77
device->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
78
strcpy(device->states[0].name, "WFI");
79
strcpy(device->states[0].desc, "Wait for interrupt");
80
81
/* Wait for interrupt and DDR self refresh state */
82
device->states[1].enter = kirkwood_enter_idle;
83
device->states[1].exit_latency = 10;
84
device->states[1].target_residency = 10000;
85
device->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
86
strcpy(device->states[1].name, "DDR SR");
87
strcpy(device->states[1].desc, "WFI and DDR Self Refresh");
88
89
if (cpuidle_register_device(device)) {
90
printk(KERN_ERR "kirkwood_init_cpuidle: Failed registering\n");
91
return -EIO;
92
}
93
return 0;
94
}
95
96
device_initcall(kirkwood_init_cpuidle);
97
98