~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/arm/mach-imx/cpuidle-imx6sx.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 __cpuidle 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                 ct_cpuidle_enter();
 51                 cpu_suspend(0, imx6sx_idle_finish);
 52                 ct_cpuidle_exit();
 53 
 54                 cpu_cluster_pm_exit();
 55                 cpu_pm_exit();
 56                 imx_gpc_set_arm_power_in_lpm(false);
 57                 imx6_enable_rbc(false);
 58                 break;
 59         default:
 60                 break;
 61         }
 62 
 63         imx6_set_lpm(WAIT_CLOCKED);
 64 
 65         return index;
 66 }
 67 
 68 static struct cpuidle_driver imx6sx_cpuidle_driver = {
 69         .name = "imx6sx_cpuidle",
 70         .owner = THIS_MODULE,
 71         .states = {
 72                 /* WFI */
 73                 ARM_CPUIDLE_WFI_STATE,
 74                 /* WAIT */
 75                 {
 76                         .exit_latency = 50,
 77                         .target_residency = 75,
 78                         .flags = CPUIDLE_FLAG_TIMER_STOP,
 79                         .enter = imx6sx_enter_wait,
 80                         .name = "WAIT",
 81                         .desc = "Clock off",
 82                 },
 83                 /* WAIT + ARM power off  */
 84                 {
 85                         /*
 86                          * ARM gating 31us * 5 + RBC clear 65us
 87                          * and some margin for SW execution, here set it
 88                          * to 300us.
 89                          */
 90                         .exit_latency = 300,
 91                         .target_residency = 500,
 92                         .flags = CPUIDLE_FLAG_TIMER_STOP |
 93                                  CPUIDLE_FLAG_RCU_IDLE,
 94                         .enter = imx6sx_enter_wait,
 95                         .name = "LOW-POWER-IDLE",
 96                         .desc = "ARM power off",
 97                 },
 98         },
 99         .state_count = 3,
100         .safe_state_index = 0,
101 };
102 
103 int __init imx6sx_cpuidle_init(void)
104 {
105         imx6_set_int_mem_clk_lpm(true);
106         imx6_enable_rbc(false);
107         imx_gpc_set_l2_mem_power_in_lpm(false);
108         /*
109          * set ARM power up/down timing to the fastest,
110          * sw2iso and sw can be set to one 32K cycle = 31us
111          * except for power up sw2iso which need to be
112          * larger than LDO ramp up time.
113          */
114         imx_gpc_set_arm_power_up_timing(cpu_is_imx6sx() ? 0xf : 0x2, 1);
115         imx_gpc_set_arm_power_down_timing(1, 1);
116 
117         return cpuidle_register(&imx6sx_cpuidle_driver, NULL);
118 }
119 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php