0001
0002
0003
0004
0005
0006 #include <linux/cpuidle.h>
0007 #include <linux/of.h>
0008 #include <linux/of_device.h>
0009 #include <asm/cpuidle.h>
0010
0011 extern struct of_cpuidle_method __cpuidle_method_of_table[];
0012
0013 static const struct of_cpuidle_method __cpuidle_method_of_table_sentinel
0014 __used __section("__cpuidle_method_of_table_end");
0015
0016 static struct cpuidle_ops cpuidle_ops[NR_CPUS] __ro_after_init;
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029 int arm_cpuidle_simple_enter(struct cpuidle_device *dev,
0030 struct cpuidle_driver *drv, int index)
0031 {
0032 cpu_do_idle();
0033
0034 return index;
0035 }
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046 int arm_cpuidle_suspend(int index)
0047 {
0048 int cpu = smp_processor_id();
0049
0050 return cpuidle_ops[cpu].suspend(index);
0051 }
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062 static const struct cpuidle_ops *__init arm_cpuidle_get_ops(const char *method)
0063 {
0064 struct of_cpuidle_method *m = __cpuidle_method_of_table;
0065
0066 for (; m->method; m++)
0067 if (!strcmp(m->method, method))
0068 return m->ops;
0069
0070 return NULL;
0071 }
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087 static int __init arm_cpuidle_read_ops(struct device_node *dn, int cpu)
0088 {
0089 const char *enable_method;
0090 const struct cpuidle_ops *ops;
0091
0092 enable_method = of_get_property(dn, "enable-method", NULL);
0093 if (!enable_method)
0094 return -ENOENT;
0095
0096 ops = arm_cpuidle_get_ops(enable_method);
0097 if (!ops) {
0098 pr_warn("%pOF: unsupported enable-method property: %s\n",
0099 dn, enable_method);
0100 return -EOPNOTSUPP;
0101 }
0102
0103 if (!ops->init || !ops->suspend) {
0104 pr_warn("cpuidle_ops '%s': no init or suspend callback\n",
0105 enable_method);
0106 return -EOPNOTSUPP;
0107 }
0108
0109 cpuidle_ops[cpu] = *ops;
0110
0111 pr_notice("cpuidle: enable-method property '%s'"
0112 " found operations\n", enable_method);
0113
0114 return 0;
0115 }
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134 int __init arm_cpuidle_init(int cpu)
0135 {
0136 struct device_node *cpu_node = of_cpu_device_node_get(cpu);
0137 int ret;
0138
0139 if (!cpu_node)
0140 return -ENODEV;
0141
0142 ret = arm_cpuidle_read_ops(cpu_node, cpu);
0143 if (!ret)
0144 ret = cpuidle_ops[cpu].init(cpu_node, cpu);
0145
0146 of_node_put(cpu_node);
0147
0148 return ret;
0149 }