linux/drivers/cpuidle/cpuidle-zynq.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2012-2013 Xilinx
   3 *
   4 * CPU idle support for Xilinx Zynq
   5 *
   6 * based on arch/arm/mach-at91/cpuidle.c
   7 *
   8 * This program is free software; you can redistribute it and/or modify it
   9 * under the terms and conditions of the GNU General Public License,
  10 * version 2, as published by the Free Software Foundation.
  11 *
  12 * This program is distributed in the hope it will be useful, but WITHOUT
  13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  15 * more details.
  16 *
  17 * You should have received a copy of the GNU General Public License along with
  18 * this program.  If not, see <http://www.gnu.org/licenses/>.
  19 *
  20 * The cpu idle uses wait-for-interrupt and RAM self refresh in order
  21 * to implement two idle states -
  22 * #1 wait-for-interrupt
  23 * #2 wait-for-interrupt and RAM self refresh
  24 *
  25 * Maintainer: Michal Simek <michal.simek@xilinx.com>
  26 */
  27
  28#include <linux/init.h>
  29#include <linux/cpu_pm.h>
  30#include <linux/cpuidle.h>
  31#include <linux/of.h>
  32#include <asm/proc-fns.h>
  33#include <asm/cpuidle.h>
  34
  35#define ZYNQ_MAX_STATES         2
  36
  37/* Actual code that puts the SoC in different idle states */
  38static int zynq_enter_idle(struct cpuidle_device *dev,
  39                           struct cpuidle_driver *drv, int index)
  40{
  41        /* Devices must be stopped here */
  42        cpu_pm_enter();
  43
  44        /* Add code for DDR self refresh start */
  45        cpu_do_idle();
  46
  47        /* Add code for DDR self refresh stop */
  48        cpu_pm_exit();
  49
  50        return index;
  51}
  52
  53static struct cpuidle_driver zynq_idle_driver = {
  54        .name = "zynq_idle",
  55        .owner = THIS_MODULE,
  56        .states = {
  57                ARM_CPUIDLE_WFI_STATE,
  58                {
  59                        .enter                  = zynq_enter_idle,
  60                        .exit_latency           = 10,
  61                        .target_residency       = 10000,
  62                        .flags                  = CPUIDLE_FLAG_TIME_VALID |
  63                                                  CPUIDLE_FLAG_TIMER_STOP,
  64                        .name                   = "RAM_SR",
  65                        .desc                   = "WFI and RAM Self Refresh",
  66                },
  67        },
  68        .safe_state_index = 0,
  69        .state_count = ZYNQ_MAX_STATES,
  70};
  71
  72/* Initialize CPU idle by registering the idle states */
  73static int __init zynq_cpuidle_init(void)
  74{
  75        if (!of_machine_is_compatible("xlnx,zynq-7000"))
  76                return -ENODEV;
  77
  78        pr_info("Xilinx Zynq CpuIdle Driver started\n");
  79
  80        return cpuidle_register(&zynq_idle_driver, NULL);
  81}
  82
  83device_initcall(zynq_cpuidle_init);
  84