root/arch/arm/mach-imx/cpuidle-imx6sx.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. imx6sx_idle_finish
  2. imx6sx_enter_wait
  3. imx6sx_cpuidle_init

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (C) 2014 Freescale Semiconductor, Inc.
   4  */
   5 
   6 #include <linux/cpuidle.h>
   7 #include <linux/cpu_pm.h>
   8 #include <linux/module.h>
   9 #include <asm/cacheflush.h>
  10 #include <asm/cpuidle.h>
  11 #include <asm/suspend.h>
  12 
  13 #include "common.h"
  14 #include "cpuidle.h"
  15 #include "hardware.h"
  16 
  17 static int imx6sx_idle_finish(unsigned long val)
  18 {
  19         /*
  20          * for Cortex-A7 which has an internal L2
  21          * cache, need to flush it before powering
  22          * down ARM platform, since flushing L1 cache
  23          * here again has very small overhead, compared
  24          * to adding conditional code for L2 cache type,
  25          * just call flush_cache_all() is fine.
  26          */
  27         flush_cache_all();
  28         cpu_do_idle();
  29 
  30         return 0;
  31 }
  32 
  33 static int imx6sx_enter_wait(struct cpuidle_device *dev,
  34                             struct cpuidle_driver *drv, int index)
  35 {
  36         imx6_set_lpm(WAIT_UNCLOCKED);
  37 
  38         switch (index) {
  39         case 1:
  40                 cpu_do_idle();
  41                 break;
  42         case 2:
  43                 imx6_enable_rbc(true);
  44                 imx_gpc_set_arm_power_in_lpm(true);
  45                 imx_set_cpu_jump(0, v7_cpu_resume);
  46                 /* Need to notify there is a cpu pm operation. */
  47                 cpu_pm_enter();
  48                 cpu_cluster_pm_enter();
  49 
  50                 cpu_suspend(0, imx6sx_idle_finish);
  51 
  52                 cpu_cluster_pm_exit();
  53                 cpu_pm_exit();
  54                 imx_gpc_set_arm_power_in_lpm(false);
  55                 imx6_enable_rbc(false);
  56                 break;
  57         default:
  58                 break;
  59         }
  60 
  61         imx6_set_lpm(WAIT_CLOCKED);
  62 
  63         return index;
  64 }
  65 
  66 static struct cpuidle_driver imx6sx_cpuidle_driver = {
  67         .name = "imx6sx_cpuidle",
  68         .owner = THIS_MODULE,
  69         .states = {
  70                 /* WFI */
  71                 ARM_CPUIDLE_WFI_STATE,
  72                 /* WAIT */
  73                 {
  74                         .exit_latency = 50,
  75                         .target_residency = 75,
  76                         .flags = CPUIDLE_FLAG_TIMER_STOP,
  77                         .enter = imx6sx_enter_wait,
  78                         .name = "WAIT",
  79                         .desc = "Clock off",
  80                 },
  81                 /* WAIT + ARM power off  */
  82                 {
  83                         /*
  84                          * ARM gating 31us * 5 + RBC clear 65us
  85                          * and some margin for SW execution, here set it
  86                          * to 300us.
  87                          */
  88                         .exit_latency = 300,
  89                         .target_residency = 500,
  90                         .flags = CPUIDLE_FLAG_TIMER_STOP,
  91                         .enter = imx6sx_enter_wait,
  92                         .name = "LOW-POWER-IDLE",
  93                         .desc = "ARM power off",
  94                 },
  95         },
  96         .state_count = 3,
  97         .safe_state_index = 0,
  98 };
  99 
 100 int __init imx6sx_cpuidle_init(void)
 101 {
 102         imx6_set_int_mem_clk_lpm(true);
 103         imx6_enable_rbc(false);
 104         imx_gpc_set_l2_mem_power_in_lpm(false);
 105         /*
 106          * set ARM power up/down timing to the fastest,
 107          * sw2iso and sw can be set to one 32K cycle = 31us
 108          * except for power up sw2iso which need to be
 109          * larger than LDO ramp up time.
 110          */
 111         imx_gpc_set_arm_power_up_timing(cpu_is_imx6sx() ? 0xf : 0x2, 1);
 112         imx_gpc_set_arm_power_down_timing(1, 1);
 113 
 114         return cpuidle_register(&imx6sx_cpuidle_driver, NULL);
 115 }

/* [<][>][^][v][top][bottom][index][help] */