18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * based on arch/arm/mach-kirkwood/cpuidle.c
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * CPU idle support for AT91 SoC
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * This file is licensed under the terms of the GNU General Public
78c2ecf20Sopenharmony_ci * License version 2.  This program is licensed "as is" without any
88c2ecf20Sopenharmony_ci * warranty of any kind, whether express or implied.
98c2ecf20Sopenharmony_ci *
108c2ecf20Sopenharmony_ci * The cpu idle uses wait-for-interrupt and RAM self refresh in order
118c2ecf20Sopenharmony_ci * to implement two idle states -
128c2ecf20Sopenharmony_ci * #1 wait-for-interrupt
138c2ecf20Sopenharmony_ci * #2 wait-for-interrupt and RAM self refresh
148c2ecf20Sopenharmony_ci */
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#include <linux/kernel.h>
178c2ecf20Sopenharmony_ci#include <linux/init.h>
188c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
198c2ecf20Sopenharmony_ci#include <linux/cpuidle.h>
208c2ecf20Sopenharmony_ci#include <linux/io.h>
218c2ecf20Sopenharmony_ci#include <linux/export.h>
228c2ecf20Sopenharmony_ci#include <asm/cpuidle.h>
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci#define AT91_MAX_STATES	2
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_cistatic void (*at91_standby)(void);
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci/* Actual code that puts the SoC in different idle states */
298c2ecf20Sopenharmony_cistatic int at91_enter_idle(struct cpuidle_device *dev,
308c2ecf20Sopenharmony_ci			struct cpuidle_driver *drv,
318c2ecf20Sopenharmony_ci			       int index)
328c2ecf20Sopenharmony_ci{
338c2ecf20Sopenharmony_ci	at91_standby();
348c2ecf20Sopenharmony_ci	return index;
358c2ecf20Sopenharmony_ci}
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_cistatic struct cpuidle_driver at91_idle_driver = {
388c2ecf20Sopenharmony_ci	.name			= "at91_idle",
398c2ecf20Sopenharmony_ci	.owner			= THIS_MODULE,
408c2ecf20Sopenharmony_ci	.states[0]		= ARM_CPUIDLE_WFI_STATE,
418c2ecf20Sopenharmony_ci	.states[1]		= {
428c2ecf20Sopenharmony_ci		.enter			= at91_enter_idle,
438c2ecf20Sopenharmony_ci		.exit_latency		= 10,
448c2ecf20Sopenharmony_ci		.target_residency	= 10000,
458c2ecf20Sopenharmony_ci		.name			= "RAM_SR",
468c2ecf20Sopenharmony_ci		.desc			= "WFI and DDR Self Refresh",
478c2ecf20Sopenharmony_ci	},
488c2ecf20Sopenharmony_ci	.state_count = AT91_MAX_STATES,
498c2ecf20Sopenharmony_ci};
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci/* Initialize CPU idle by registering the idle states */
528c2ecf20Sopenharmony_cistatic int at91_cpuidle_probe(struct platform_device *dev)
538c2ecf20Sopenharmony_ci{
548c2ecf20Sopenharmony_ci	at91_standby = (void *)(dev->dev.platform_data);
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci	return cpuidle_register(&at91_idle_driver, NULL);
578c2ecf20Sopenharmony_ci}
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_cistatic struct platform_driver at91_cpuidle_driver = {
608c2ecf20Sopenharmony_ci	.driver = {
618c2ecf20Sopenharmony_ci		.name = "cpuidle-at91",
628c2ecf20Sopenharmony_ci	},
638c2ecf20Sopenharmony_ci	.probe = at91_cpuidle_probe,
648c2ecf20Sopenharmony_ci};
658c2ecf20Sopenharmony_cibuiltin_platform_driver(at91_cpuidle_driver);
66