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