| 
									
										
										
										
											2009-11-03 15:14:13 +05:30
										 |  |  | /*
 | 
					
						
							|  |  |  |  * CPU idle for DaVinci SoCs | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (C) 2009 Texas Instruments Incorporated. http://www.ti.com/
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Derived from Marvell Kirkwood CPU idle code | 
					
						
							|  |  |  |  * (arch/arm/mach-kirkwood/cpuidle.c) | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or modify | 
					
						
							|  |  |  |  * it under the terms of the GNU General Public License version 2 as | 
					
						
							|  |  |  |  * published by the Free Software Foundation. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <linux/kernel.h>
 | 
					
						
							|  |  |  | #include <linux/init.h>
 | 
					
						
							|  |  |  | #include <linux/platform_device.h>
 | 
					
						
							|  |  |  | #include <linux/cpuidle.h>
 | 
					
						
							|  |  |  | #include <linux/io.h>
 | 
					
						
							| 
									
										
										
										
											2011-07-31 16:17:29 -04:00
										 |  |  | #include <linux/export.h>
 | 
					
						
							| 
									
										
										
										
											2012-03-20 15:22:45 -05:00
										 |  |  | #include <asm/cpuidle.h>
 | 
					
						
							| 
									
										
										
										
											2009-11-03 15:14:13 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  | #include <mach/cpuidle.h>
 | 
					
						
							| 
									
										
										
										
											2011-07-05 22:52:57 -04:00
										 |  |  | #include <mach/ddr2.h>
 | 
					
						
							| 
									
										
										
										
											2009-11-03 15:14:13 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  | #define DAVINCI_CPUIDLE_MAX_STATES	2
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void __iomem *ddr2_reg_base; | 
					
						
							| 
									
										
										
										
											2013-02-04 12:01:41 +00:00
										 |  |  | static bool ddr2_pdown; | 
					
						
							| 
									
										
										
										
											2009-11-03 15:14:13 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  | static void davinci_save_ddr_power(int enter, bool pdown) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	u32 val; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	val = __raw_readl(ddr2_reg_base + DDR2_SDRCR_OFFSET); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (enter) { | 
					
						
							|  |  |  | 		if (pdown) | 
					
						
							|  |  |  | 			val |= DDR2_SRPD_BIT; | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			val &= ~DDR2_SRPD_BIT; | 
					
						
							|  |  |  | 		val |= DDR2_LPMODEN_BIT; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		val &= ~(DDR2_SRPD_BIT | DDR2_LPMODEN_BIT); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	__raw_writel(val, ddr2_reg_base + DDR2_SDRCR_OFFSET); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-04 12:01:42 +00:00
										 |  |  | /* Actual code that puts the SoC in different idle states */ | 
					
						
							|  |  |  | static int davinci_enter_idle(struct cpuidle_device *dev, | 
					
						
							| 
									
										
										
										
											2013-04-03 12:15:19 +00:00
										 |  |  | 			      struct cpuidle_driver *drv, int index) | 
					
						
							| 
									
										
										
										
											2013-02-04 12:01:42 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-02-04 12:01:43 +00:00
										 |  |  | 	davinci_save_ddr_power(1, ddr2_pdown); | 
					
						
							| 
									
										
										
										
											2013-04-03 12:15:19 +00:00
										 |  |  | 	cpu_do_idle(); | 
					
						
							| 
									
										
										
										
											2013-02-04 12:01:43 +00:00
										 |  |  | 	davinci_save_ddr_power(0, ddr2_pdown); | 
					
						
							| 
									
										
										
										
											2013-02-04 12:01:42 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return index; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct cpuidle_driver davinci_idle_driver = { | 
					
						
							|  |  |  | 	.name			= "cpuidle-davinci", | 
					
						
							|  |  |  | 	.owner			= THIS_MODULE, | 
					
						
							|  |  |  | 	.states[0]		= ARM_CPUIDLE_WFI_STATE, | 
					
						
							|  |  |  | 	.states[1]		= { | 
					
						
							|  |  |  | 		.enter			= davinci_enter_idle, | 
					
						
							|  |  |  | 		.exit_latency		= 10, | 
					
						
							| 
									
										
										
										
											2013-06-28 12:09:09 +02:00
										 |  |  | 		.target_residency	= 10000, | 
					
						
							| 
									
										
										
										
											2013-02-04 12:01:42 +00:00
										 |  |  | 		.name			= "DDR SR", | 
					
						
							|  |  |  | 		.desc			= "WFI and DDR Self Refresh", | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 	.state_count = DAVINCI_CPUIDLE_MAX_STATES, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-03 15:14:13 +05:30
										 |  |  | static int __init davinci_cpuidle_probe(struct platform_device *pdev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct davinci_cpuidle_config *pdata = pdev->dev.platform_data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!pdata) { | 
					
						
							|  |  |  | 		dev_err(&pdev->dev, "cannot get platform data\n"); | 
					
						
							|  |  |  | 		return -ENOENT; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-16 17:21:37 +05:30
										 |  |  | 	ddr2_reg_base = pdata->ddr2_ctlr_base; | 
					
						
							| 
									
										
										
										
											2009-11-03 15:14:13 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-04 12:01:41 +00:00
										 |  |  | 	ddr2_pdown = pdata->ddr2_pdown; | 
					
						
							| 
									
										
										
										
											2009-11-03 15:14:13 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-23 08:54:44 +00:00
										 |  |  | 	return cpuidle_register(&davinci_idle_driver, NULL); | 
					
						
							| 
									
										
										
										
											2009-11-03 15:14:13 +05:30
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct platform_driver davinci_cpuidle_driver = { | 
					
						
							|  |  |  | 	.driver = { | 
					
						
							|  |  |  | 		.name	= "cpuidle-davinci", | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int __init davinci_cpuidle_init(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return platform_driver_probe(&davinci_cpuidle_driver, | 
					
						
							|  |  |  | 						davinci_cpuidle_probe); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | device_initcall(davinci_cpuidle_init); | 
					
						
							|  |  |  | 
 |