linux/arch/arm/mach-davinci/cpuidle.c
<<
>>
Prefs
   1/*
   2 * CPU idle for DaVinci SoCs
   3 *
   4 * Copyright (C) 2009 Texas Instruments Incorporated. http://www.ti.com/
   5 *
   6 * Derived from Marvell Kirkwood CPU idle code
   7 * (arch/arm/mach-kirkwood/cpuidle.c)
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License version 2 as
  11 * published by the Free Software Foundation.
  12 */
  13
  14#include <linux/kernel.h>
  15#include <linux/init.h>
  16#include <linux/platform_device.h>
  17#include <linux/cpuidle.h>
  18#include <linux/io.h>
  19#include <linux/export.h>
  20#include <asm/proc-fns.h>
  21#include <asm/cpuidle.h>
  22
  23#include <mach/cpuidle.h>
  24#include <mach/ddr2.h>
  25
  26#define DAVINCI_CPUIDLE_MAX_STATES      2
  27
  28static void __iomem *ddr2_reg_base;
  29static bool ddr2_pdown;
  30
  31static void davinci_save_ddr_power(int enter, bool pdown)
  32{
  33        u32 val;
  34
  35        val = __raw_readl(ddr2_reg_base + DDR2_SDRCR_OFFSET);
  36
  37        if (enter) {
  38                if (pdown)
  39                        val |= DDR2_SRPD_BIT;
  40                else
  41                        val &= ~DDR2_SRPD_BIT;
  42                val |= DDR2_LPMODEN_BIT;
  43        } else {
  44                val &= ~(DDR2_SRPD_BIT | DDR2_LPMODEN_BIT);
  45        }
  46
  47        __raw_writel(val, ddr2_reg_base + DDR2_SDRCR_OFFSET);
  48}
  49
  50/* Actual code that puts the SoC in different idle states */
  51static int davinci_enter_idle(struct cpuidle_device *dev,
  52                              struct cpuidle_driver *drv, int index)
  53{
  54        davinci_save_ddr_power(1, ddr2_pdown);
  55        cpu_do_idle();
  56        davinci_save_ddr_power(0, ddr2_pdown);
  57
  58        return index;
  59}
  60
  61static struct cpuidle_driver davinci_idle_driver = {
  62        .name                   = "cpuidle-davinci",
  63        .owner                  = THIS_MODULE,
  64        .states[0]              = ARM_CPUIDLE_WFI_STATE,
  65        .states[1]              = {
  66                .enter                  = davinci_enter_idle,
  67                .exit_latency           = 10,
  68                .target_residency       = 100000,
  69                .flags                  = CPUIDLE_FLAG_TIME_VALID,
  70                .name                   = "DDR SR",
  71                .desc                   = "WFI and DDR Self Refresh",
  72        },
  73        .state_count = DAVINCI_CPUIDLE_MAX_STATES,
  74};
  75
  76static int __init davinci_cpuidle_probe(struct platform_device *pdev)
  77{
  78        struct davinci_cpuidle_config *pdata = pdev->dev.platform_data;
  79
  80        if (!pdata) {
  81                dev_err(&pdev->dev, "cannot get platform data\n");
  82                return -ENOENT;
  83        }
  84
  85        ddr2_reg_base = pdata->ddr2_ctlr_base;
  86
  87        ddr2_pdown = pdata->ddr2_pdown;
  88
  89        return cpuidle_register(&davinci_idle_driver, NULL);
  90}
  91
  92static struct platform_driver davinci_cpuidle_driver = {
  93        .driver = {
  94                .name   = "cpuidle-davinci",
  95                .owner  = THIS_MODULE,
  96        },
  97};
  98
  99static int __init davinci_cpuidle_init(void)
 100{
 101        return platform_driver_probe(&davinci_cpuidle_driver,
 102                                                davinci_cpuidle_probe);
 103}
 104device_initcall(davinci_cpuidle_init);
 105
 106