[go: nahoru, domu]

cpuidle-kirkwood.c revision 488540bf41ce8ccfe8b54c646c3ea67a7196edcd
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>
179cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew Lunn#include <linux/module.h>
18e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury#include <linux/init.h>
19e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury#include <linux/platform_device.h>
20e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury#include <linux/cpuidle.h>
21e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury#include <linux/io.h>
22dc28094b905a872f8884f1f1c48ca86b3b78583aPaul Gortmaker#include <linux/export.h>
23e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury#include <asm/proc-fns.h>
24b334648db0ff2d07b00d81cf033c6eddff277680Robert Lee#include <asm/cpuidle.h>
25e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury
26e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury#define KIRKWOOD_MAX_STATES	2
27e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury
289cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew Lunnstatic void __iomem *ddr_operation_base;
299cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew Lunn
30e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury/* Actual code that puts the SoC in different idle states */
31e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khourystatic int kirkwood_enter_idle(struct cpuidle_device *dev,
329cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew Lunn			       struct cpuidle_driver *drv,
33e978aa7d7d57d04eb5f88a7507c4fb98577def77Deepthi Dharwar			       int index)
34e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury{
359cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew Lunn	writel(0x7, ddr_operation_base);
36b334648db0ff2d07b00d81cf033c6eddff277680Robert Lee	cpu_do_idle();
37e978aa7d7d57d04eb5f88a7507c4fb98577def77Deepthi Dharwar
38e978aa7d7d57d04eb5f88a7507c4fb98577def77Deepthi Dharwar	return index;
39e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury}
40e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury
41b334648db0ff2d07b00d81cf033c6eddff277680Robert Leestatic struct cpuidle_driver kirkwood_idle_driver = {
42b334648db0ff2d07b00d81cf033c6eddff277680Robert Lee	.name			= "kirkwood_idle",
43b334648db0ff2d07b00d81cf033c6eddff277680Robert Lee	.owner			= THIS_MODULE,
44b334648db0ff2d07b00d81cf033c6eddff277680Robert Lee	.en_core_tk_irqen	= 1,
45b334648db0ff2d07b00d81cf033c6eddff277680Robert Lee	.states[0]		= ARM_CPUIDLE_WFI_STATE,
46b334648db0ff2d07b00d81cf033c6eddff277680Robert Lee	.states[1]		= {
47b334648db0ff2d07b00d81cf033c6eddff277680Robert Lee		.enter			= kirkwood_enter_idle,
48b334648db0ff2d07b00d81cf033c6eddff277680Robert Lee		.exit_latency		= 10,
49b334648db0ff2d07b00d81cf033c6eddff277680Robert Lee		.target_residency	= 100000,
50b334648db0ff2d07b00d81cf033c6eddff277680Robert Lee		.flags			= CPUIDLE_FLAG_TIME_VALID,
51b334648db0ff2d07b00d81cf033c6eddff277680Robert Lee		.name			= "DDR SR",
52b334648db0ff2d07b00d81cf033c6eddff277680Robert Lee		.desc			= "WFI and DDR Self Refresh",
53b334648db0ff2d07b00d81cf033c6eddff277680Robert Lee	},
54b334648db0ff2d07b00d81cf033c6eddff277680Robert Lee	.state_count = KIRKWOOD_MAX_STATES,
55b334648db0ff2d07b00d81cf033c6eddff277680Robert Lee};
569cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew Lunnstatic struct cpuidle_device *device;
57b334648db0ff2d07b00d81cf033c6eddff277680Robert Lee
58b334648db0ff2d07b00d81cf033c6eddff277680Robert Leestatic DEFINE_PER_CPU(struct cpuidle_device, kirkwood_cpuidle_device);
59b334648db0ff2d07b00d81cf033c6eddff277680Robert Lee
60e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury/* Initialize CPU idle by registering the idle states */
619cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew Lunnstatic int kirkwood_cpuidle_probe(struct platform_device *pdev)
62e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury{
639cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew Lunn	struct resource *res;
649cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew Lunn
659cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew Lunn	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
669cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew Lunn	if (res == NULL)
679cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew Lunn		return -EINVAL;
689cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew Lunn
69488540bf41ce8ccfe8b54c646c3ea67a7196edcdSilviu-Mihai Popescu	ddr_operation_base = devm_ioremap_resource(&pdev->dev, res);
70488540bf41ce8ccfe8b54c646c3ea67a7196edcdSilviu-Mihai Popescu	if (IS_ERR(ddr_operation_base))
71488540bf41ce8ccfe8b54c646c3ea67a7196edcdSilviu-Mihai Popescu		return PTR_ERR(ddr_operation_base);
72e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury
73e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury	device = &per_cpu(kirkwood_cpuidle_device, smp_processor_id());
74e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury	device->state_count = KIRKWOOD_MAX_STATES;
75e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury
7646bcfad7a819bd17ac4e831b04405152d59784abDeepthi Dharwar	cpuidle_register_driver(&kirkwood_idle_driver);
77e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury	if (cpuidle_register_device(device)) {
7898adf932c0adc5e57257fe4230d89bda306a4037Andrew Lunn		pr_err("kirkwood_init_cpuidle: Failed registering\n");
79e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury		return -EIO;
80e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury	}
81e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury	return 0;
82e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury}
83e50b6befae9ea91c2d190fb78ff1e06a0b950addRabeeh Khoury
849cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew Lunnint kirkwood_cpuidle_remove(struct platform_device *pdev)
859cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew Lunn{
869cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew Lunn	cpuidle_unregister_device(device);
879cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew Lunn	cpuidle_unregister_driver(&kirkwood_idle_driver);
889cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew Lunn
899cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew Lunn	return 0;
909cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew Lunn}
919cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew Lunn
929cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew Lunnstatic struct platform_driver kirkwood_cpuidle_driver = {
939cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew Lunn	.probe = kirkwood_cpuidle_probe,
949cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew Lunn	.remove = kirkwood_cpuidle_remove,
959cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew Lunn	.driver = {
969cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew Lunn		   .name = "kirkwood_cpuidle",
979cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew Lunn		   .owner = THIS_MODULE,
989cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew Lunn		   },
999cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew Lunn};
1009cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew Lunn
1019cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew Lunnmodule_platform_driver(kirkwood_cpuidle_driver);
1029cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew Lunn
1039cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew LunnMODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch>");
1049cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew LunnMODULE_DESCRIPTION("Kirkwood cpu idle driver");
1059cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew LunnMODULE_LICENSE("GPL v2");
1069cfc94eb0f4843af5d1141a37d7b7ca5d3b27220Andrew LunnMODULE_ALIAS("platform:kirkwood-cpuidle");
107