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/cpuidle.h>
  21
  22#include "cpuidle.h"
  23#include "ddr2.h"
  24
  25#define DAVINCI_CPUIDLE_MAX_STATES      2
  26
  27static void __iomem *ddr2_reg_base;
  28static bool ddr2_pdown;
  29
  30static void davinci_save_ddr_power(int enter, bool pdown)
  31{
  32        u32 val;
  33
  34        val = __raw_readl(ddr2_reg_base + DDR2_SDRCR_OFFSET);
  35
  36        if (enter) {
  37                if (pdown)
  38                        val |= DDR2_SRPD_BIT;
  39                else
  40                        val &= ~DDR2_SRPD_BIT;
  41                val |= DDR2_LPMODEN_BIT;
  42        } else {
  43                val &= ~(DDR2_SRPD_BIT | DDR2_LPMODEN_BIT);
  44        }
  45
  46        __raw_writel(val, ddr2_reg_base + DDR2_SDRCR_OFFSET);
  47}
  48
  49/* Actual code that puts the SoC in different idle states */
  50static int davinci_enter_idle(struct cpuidle_device *dev,
  51                              struct cpuidle_driver *drv, int index)
  52{
  53        davinci_save_ddr_power(1, ddr2_pdown);
  54        cpu_do_idle();
  55        davinci_save_ddr_power(0, ddr2_pdown);
  56
  57        return index;
  58}
  59
  60static struct cpuidle_driver davinci_idle_driver = {
  61        .name                   = "cpuidle-davinci",
  62        .owner                  = THIS_MODULE,
  63        .states[0]              = ARM_CPUIDLE_WFI_STATE,
  64        .states[1]              = {
  65                .enter                  = davinci_enter_idle,
  66                .exit_latency           = 10,
  67                .target_residency       = 10000,
  68                .name                   = "DDR SR",
  69                .desc                   = "WFI and DDR Self Refresh",
  70        },
  71        .state_count = DAVINCI_CPUIDLE_MAX_STATES,
  72};
  73
  74static int __init davinci_cpuidle_probe(struct platform_device *pdev)
  75{
  76        struct davinci_cpuidle_config *pdata = pdev->dev.platform_data;
  77
  78        if (!pdata) {
  79                dev_err(&pdev->dev, "cannot get platform data\n");
  80                return -ENOENT;
  81        }
  82
  83        ddr2_reg_base = pdata->ddr2_ctlr_base;
  84
  85        ddr2_pdown = pdata->ddr2_pdown;
  86
  87        return cpuidle_register(&davinci_idle_driver, NULL);
  88}
  89
  90static struct platform_driver davinci_cpuidle_driver = {
  91        .driver = {
  92                .name   = "cpuidle-davinci",
  93        },
  94};
  95
  96static int __init davinci_cpuidle_init(void)
  97{
  98        return platform_driver_probe(&davinci_cpuidle_driver,
  99                                                davinci_cpuidle_probe);
 100}
 101device_initcall(davinci_cpuidle_init);
 102
 103