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