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-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Copyright 2012 Linaro Ltd.
^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/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <asm/cpuidle.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) extern struct of_cpuidle_method __cpuidle_method_of_table[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) static const struct of_cpuidle_method __cpuidle_method_of_table_sentinel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 	__used __section("__cpuidle_method_of_table_end");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) static struct cpuidle_ops cpuidle_ops[NR_CPUS] __ro_after_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  * arm_cpuidle_simple_enter() - a wrapper to cpu_do_idle()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  * @dev: not used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)  * @drv: not used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  * @index: not used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)  * A trivial wrapper to allow the cpu_do_idle function to be assigned as a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)  * cpuidle callback by matching the function signature.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)  * Returns the index passed as parameter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) int arm_cpuidle_simple_enter(struct cpuidle_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 		struct cpuidle_driver *drv, int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	cpu_do_idle();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	return index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38)  * arm_cpuidle_suspend() - function to enter low power idle states
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39)  * @index: an integer used as an identifier for the low level PM callbacks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41)  * This function calls the underlying arch specific low level PM code as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42)  * registered at the init time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44)  * Returns the result of the suspend callback.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) int arm_cpuidle_suspend(int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	int cpu = smp_processor_id();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	return cpuidle_ops[cpu].suspend(index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54)  * arm_cpuidle_get_ops() - find a registered cpuidle_ops by name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55)  * @method: the method name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57)  * Search in the __cpuidle_method_of_table array the cpuidle ops matching the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58)  * method name.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60)  * Returns a struct cpuidle_ops pointer, NULL if not found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) static const struct cpuidle_ops *__init arm_cpuidle_get_ops(const char *method)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	struct of_cpuidle_method *m = __cpuidle_method_of_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	for (; m->method; m++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 		if (!strcmp(m->method, method))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 			return m->ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74)  * arm_cpuidle_read_ops() - Initialize the cpuidle ops with the device tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75)  * @dn: a pointer to a struct device node corresponding to a cpu node
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76)  * @cpu: the cpu identifier
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78)  * Get the method name defined in the 'enable-method' property, retrieve the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79)  * associated cpuidle_ops and do a struct copy. This copy is needed because all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80)  * cpuidle_ops are tagged __initconst and will be unloaded after the init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81)  * process.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83)  * Return 0 on sucess, -ENOENT if no 'enable-method' is defined, -EOPNOTSUPP if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84)  * no cpuidle_ops is registered for the 'enable-method', or if either init or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85)  * suspend callback isn't defined.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) static int __init arm_cpuidle_read_ops(struct device_node *dn, int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	const char *enable_method;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	const struct cpuidle_ops *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	enable_method = of_get_property(dn, "enable-method", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	if (!enable_method)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 		return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	ops = arm_cpuidle_get_ops(enable_method);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	if (!ops) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 		pr_warn("%pOF: unsupported enable-method property: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 			dn, enable_method);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 		return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	if (!ops->init || !ops->suspend) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 		pr_warn("cpuidle_ops '%s': no init or suspend callback\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 			enable_method);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 		return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	cpuidle_ops[cpu] = *ops; /* structure copy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	pr_notice("cpuidle: enable-method property '%s'"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 		  " found operations\n", enable_method);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)  * arm_cpuidle_init() - Initialize cpuidle_ops for a specific cpu
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)  * @cpu: the cpu to be initialized
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)  * Initialize the cpuidle ops with the device for the cpu and then call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)  * the cpu's idle initialization callback. This may fail if the underlying HW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)  * is not operational.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)  * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)  *  0 on success,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)  *  -ENODEV if it fails to find the cpu node in the device tree,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)  *  -EOPNOTSUPP if it does not find a registered and valid cpuidle_ops for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)  *  this cpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)  *  -ENOENT if it fails to find an 'enable-method' property,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)  *  -ENXIO if the HW reports a failure or a misconfiguration,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)  *  -ENOMEM if the HW report an memory allocation failure 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) int __init arm_cpuidle_init(int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	struct device_node *cpu_node = of_cpu_device_node_get(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	if (!cpu_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	ret = arm_cpuidle_read_ops(cpu_node, cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 		ret = cpuidle_ops[cpu].init(cpu_node, cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	of_node_put(cpu_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }