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) 2012 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/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  8) #include <asm/cpuidle.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  9) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <soc/imx/cpuidle.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "cpuidle.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "hardware.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) static int num_idle_cpus = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) static DEFINE_RAW_SPINLOCK(cpuidle_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) static int imx6q_enter_wait(struct cpuidle_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) 			    struct cpuidle_driver *drv, int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) 	raw_spin_lock(&cpuidle_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) 	if (++num_idle_cpus == num_online_cpus())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) 		imx6_set_lpm(WAIT_UNCLOCKED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) 	raw_spin_unlock(&cpuidle_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) 	rcu_idle_enter();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) 	cpu_do_idle();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) 	rcu_idle_exit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) 	raw_spin_lock(&cpuidle_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) 	if (num_idle_cpus-- == num_online_cpus())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) 		imx6_set_lpm(WAIT_CLOCKED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) 	raw_spin_unlock(&cpuidle_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) 	return index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static struct cpuidle_driver imx6q_cpuidle_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) 	.name = "imx6q_cpuidle",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) 	.owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) 	.states = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) 		/* WFI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) 		ARM_CPUIDLE_WFI_STATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) 		/* WAIT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) 		{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) 			.exit_latency = 50,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) 			.target_residency = 75,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) 			.flags = CPUIDLE_FLAG_TIMER_STOP | CPUIDLE_FLAG_RCU_IDLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) 			.enter = imx6q_enter_wait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) 			.name = "WAIT",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) 			.desc = "Clock off",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) 		},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) 	.state_count = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) 	.safe_state_index = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)  * i.MX6 Q/DL has an erratum (ERR006687) that prevents the FEC from waking the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)  * CPUs when they are in wait(unclocked) state. As the hardware workaround isn't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)  * applicable to all boards, disable the deeper idle state when the workaround
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)  * isn't present and the FEC is in use.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) void imx6q_cpuidle_fec_irqs_used(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) 	cpuidle_driver_state_disabled(&imx6q_cpuidle_driver, 1, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) EXPORT_SYMBOL_GPL(imx6q_cpuidle_fec_irqs_used);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) void imx6q_cpuidle_fec_irqs_unused(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) 	cpuidle_driver_state_disabled(&imx6q_cpuidle_driver, 1, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) EXPORT_SYMBOL_GPL(imx6q_cpuidle_fec_irqs_unused);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) int __init imx6q_cpuidle_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) 	/* Set INT_MEM_CLK_LPM bit to get a reliable WAIT mode support */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) 	imx6_set_int_mem_clk_lpm(true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) 	return cpuidle_register(&imx6q_cpuidle_driver, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }