Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

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