0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/kernel.h>
0012 #include <linux/init.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/cpuidle.h>
0015 #include <linux/io.h>
0016 #include <linux/export.h>
0017 #include <asm/cpuidle.h>
0018
0019 #include "cpuidle.h"
0020 #include "ddr2.h"
0021
0022 #define DAVINCI_CPUIDLE_MAX_STATES 2
0023
0024 static void __iomem *ddr2_reg_base;
0025 static bool ddr2_pdown;
0026
0027 static void davinci_save_ddr_power(int enter, bool pdown)
0028 {
0029 u32 val;
0030
0031 val = __raw_readl(ddr2_reg_base + DDR2_SDRCR_OFFSET);
0032
0033 if (enter) {
0034 if (pdown)
0035 val |= DDR2_SRPD_BIT;
0036 else
0037 val &= ~DDR2_SRPD_BIT;
0038 val |= DDR2_LPMODEN_BIT;
0039 } else {
0040 val &= ~(DDR2_SRPD_BIT | DDR2_LPMODEN_BIT);
0041 }
0042
0043 __raw_writel(val, ddr2_reg_base + DDR2_SDRCR_OFFSET);
0044 }
0045
0046
0047 static int davinci_enter_idle(struct cpuidle_device *dev,
0048 struct cpuidle_driver *drv, int index)
0049 {
0050 davinci_save_ddr_power(1, ddr2_pdown);
0051 cpu_do_idle();
0052 davinci_save_ddr_power(0, ddr2_pdown);
0053
0054 return index;
0055 }
0056
0057 static struct cpuidle_driver davinci_idle_driver = {
0058 .name = "cpuidle-davinci",
0059 .owner = THIS_MODULE,
0060 .states[0] = ARM_CPUIDLE_WFI_STATE,
0061 .states[1] = {
0062 .enter = davinci_enter_idle,
0063 .exit_latency = 10,
0064 .target_residency = 10000,
0065 .name = "DDR SR",
0066 .desc = "WFI and DDR Self Refresh",
0067 },
0068 .state_count = DAVINCI_CPUIDLE_MAX_STATES,
0069 };
0070
0071 static int __init davinci_cpuidle_probe(struct platform_device *pdev)
0072 {
0073 struct davinci_cpuidle_config *pdata = pdev->dev.platform_data;
0074
0075 if (!pdata) {
0076 dev_err(&pdev->dev, "cannot get platform data\n");
0077 return -ENOENT;
0078 }
0079
0080 ddr2_reg_base = pdata->ddr2_ctlr_base;
0081
0082 ddr2_pdown = pdata->ddr2_pdown;
0083
0084 return cpuidle_register(&davinci_idle_driver, NULL);
0085 }
0086
0087 static struct platform_driver davinci_cpuidle_driver = {
0088 .driver = {
0089 .name = "cpuidle-davinci",
0090 },
0091 };
0092
0093 static int __init davinci_cpuidle_init(void)
0094 {
0095 return platform_driver_probe(&davinci_cpuidle_driver,
0096 davinci_cpuidle_probe);
0097 }
0098 device_initcall(davinci_cpuidle_init);
0099