diff options
-rw-r--r-- | arch/arm/configs/kirkwood_defconfig | 4 | ||||
-rw-r--r-- | arch/arm/mach-kirkwood/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/mach-kirkwood/cpuidle.c | 96 | ||||
-rw-r--r-- | arch/arm/mach-kirkwood/include/mach/kirkwood.h | 1 |
4 files changed, 102 insertions, 1 deletions
diff --git a/arch/arm/configs/kirkwood_defconfig b/arch/arm/configs/kirkwood_defconfig index dcf8153a947d..bde56f406688 100644 --- a/arch/arm/configs/kirkwood_defconfig +++ b/arch/arm/configs/kirkwood_defconfig | |||
@@ -270,7 +270,9 @@ CONFIG_CMDLINE="" | |||
270 | # | 270 | # |
271 | # CPU Power Management | 271 | # CPU Power Management |
272 | # | 272 | # |
273 | # CONFIG_CPU_IDLE is not set | 273 | CONFIG_CPU_IDLE=y |
274 | CONFIG_CPU_IDLE_GOV_LADDER=y | ||
275 | CONFIG_CPU_IDLE_GOV_MENU=y | ||
274 | 276 | ||
275 | # | 277 | # |
276 | # Floating point emulation | 278 | # Floating point emulation |
diff --git a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile index 8f03c9b9bdd9..f21f35d8386b 100644 --- a/arch/arm/mach-kirkwood/Makefile +++ b/arch/arm/mach-kirkwood/Makefile | |||
@@ -5,3 +5,5 @@ obj-$(CONFIG_MACH_RD88F6192_NAS) += rd88f6192-nas-setup.o | |||
5 | obj-$(CONFIG_MACH_RD88F6281) += rd88f6281-setup.o | 5 | obj-$(CONFIG_MACH_RD88F6281) += rd88f6281-setup.o |
6 | obj-$(CONFIG_MACH_SHEEVAPLUG) += sheevaplug-setup.o | 6 | obj-$(CONFIG_MACH_SHEEVAPLUG) += sheevaplug-setup.o |
7 | obj-$(CONFIG_MACH_TS219) += ts219-setup.o | 7 | obj-$(CONFIG_MACH_TS219) += ts219-setup.o |
8 | |||
9 | obj-$(CONFIG_CPU_IDLE) += cpuidle.o | ||
diff --git a/arch/arm/mach-kirkwood/cpuidle.c b/arch/arm/mach-kirkwood/cpuidle.c new file mode 100644 index 000000000000..f68d33f1f396 --- /dev/null +++ b/arch/arm/mach-kirkwood/cpuidle.c | |||
@@ -0,0 +1,96 @@ | |||
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); | ||
diff --git a/arch/arm/mach-kirkwood/include/mach/kirkwood.h b/arch/arm/mach-kirkwood/include/mach/kirkwood.h index b3e13958821d..f20ff6460485 100644 --- a/arch/arm/mach-kirkwood/include/mach/kirkwood.h +++ b/arch/arm/mach-kirkwood/include/mach/kirkwood.h | |||
@@ -48,6 +48,7 @@ | |||
48 | */ | 48 | */ |
49 | #define DDR_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE | 0x00000) | 49 | #define DDR_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE | 0x00000) |
50 | #define DDR_WINDOW_CPU_BASE (DDR_VIRT_BASE | 0x1500) | 50 | #define DDR_WINDOW_CPU_BASE (DDR_VIRT_BASE | 0x1500) |
51 | #define DDR_OPERATION_BASE (DDR_VIRT_BASE | 0x1418) | ||
51 | 52 | ||
52 | #define DEV_BUS_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE | 0x10000) | 53 | #define DEV_BUS_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE | 0x10000) |
53 | #define DEV_BUS_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE | 0x10000) | 54 | #define DEV_BUS_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE | 0x10000) |