0001
0002
0003
0004
0005
0006
0007
0008 #define pr_fmt(fmt) "cpuidle cooling: " fmt
0009
0010 #include <linux/cpu_cooling.h>
0011 #include <linux/cpuidle.h>
0012 #include <linux/device.h>
0013 #include <linux/err.h>
0014 #include <linux/idle_inject.h>
0015 #include <linux/of_device.h>
0016 #include <linux/slab.h>
0017 #include <linux/thermal.h>
0018
0019
0020
0021
0022
0023
0024 struct cpuidle_cooling_device {
0025 struct idle_inject_device *ii_dev;
0026 unsigned long state;
0027 };
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053 static unsigned int cpuidle_cooling_runtime(unsigned int idle_duration_us,
0054 unsigned long state)
0055 {
0056 if (!state)
0057 return 0;
0058
0059 return ((idle_duration_us * 100) / state) - idle_duration_us;
0060 }
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072 static int cpuidle_cooling_get_max_state(struct thermal_cooling_device *cdev,
0073 unsigned long *state)
0074 {
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086 *state = 100;
0087
0088 return 0;
0089 }
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101 static int cpuidle_cooling_get_cur_state(struct thermal_cooling_device *cdev,
0102 unsigned long *state)
0103 {
0104 struct cpuidle_cooling_device *idle_cdev = cdev->devdata;
0105
0106 *state = idle_cdev->state;
0107
0108 return 0;
0109 }
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123 static int cpuidle_cooling_set_cur_state(struct thermal_cooling_device *cdev,
0124 unsigned long state)
0125 {
0126 struct cpuidle_cooling_device *idle_cdev = cdev->devdata;
0127 struct idle_inject_device *ii_dev = idle_cdev->ii_dev;
0128 unsigned long current_state = idle_cdev->state;
0129 unsigned int runtime_us, idle_duration_us;
0130
0131 idle_cdev->state = state;
0132
0133 idle_inject_get_duration(ii_dev, &runtime_us, &idle_duration_us);
0134
0135 runtime_us = cpuidle_cooling_runtime(idle_duration_us, state);
0136
0137 idle_inject_set_duration(ii_dev, runtime_us, idle_duration_us);
0138
0139 if (current_state == 0 && state > 0) {
0140 idle_inject_start(ii_dev);
0141 } else if (current_state > 0 && !state) {
0142 idle_inject_stop(ii_dev);
0143 }
0144
0145 return 0;
0146 }
0147
0148
0149
0150
0151 static struct thermal_cooling_device_ops cpuidle_cooling_ops = {
0152 .get_max_state = cpuidle_cooling_get_max_state,
0153 .get_cur_state = cpuidle_cooling_get_cur_state,
0154 .set_cur_state = cpuidle_cooling_set_cur_state,
0155 };
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169 static int __cpuidle_cooling_register(struct device_node *np,
0170 struct cpuidle_driver *drv)
0171 {
0172 struct idle_inject_device *ii_dev;
0173 struct cpuidle_cooling_device *idle_cdev;
0174 struct thermal_cooling_device *cdev;
0175 struct device *dev;
0176 unsigned int idle_duration_us = TICK_USEC;
0177 unsigned int latency_us = UINT_MAX;
0178 char *name;
0179 int ret;
0180
0181 idle_cdev = kzalloc(sizeof(*idle_cdev), GFP_KERNEL);
0182 if (!idle_cdev) {
0183 ret = -ENOMEM;
0184 goto out;
0185 }
0186
0187 ii_dev = idle_inject_register(drv->cpumask);
0188 if (!ii_dev) {
0189 ret = -EINVAL;
0190 goto out_kfree;
0191 }
0192
0193 of_property_read_u32(np, "duration-us", &idle_duration_us);
0194 of_property_read_u32(np, "exit-latency-us", &latency_us);
0195
0196 idle_inject_set_duration(ii_dev, TICK_USEC, idle_duration_us);
0197 idle_inject_set_latency(ii_dev, latency_us);
0198
0199 idle_cdev->ii_dev = ii_dev;
0200
0201 dev = get_cpu_device(cpumask_first(drv->cpumask));
0202
0203 name = kasprintf(GFP_KERNEL, "idle-%s", dev_name(dev));
0204 if (!name) {
0205 ret = -ENOMEM;
0206 goto out_unregister;
0207 }
0208
0209 cdev = thermal_of_cooling_device_register(np, name, idle_cdev,
0210 &cpuidle_cooling_ops);
0211 if (IS_ERR(cdev)) {
0212 ret = PTR_ERR(cdev);
0213 goto out_kfree_name;
0214 }
0215
0216 pr_debug("%s: Idle injection set with idle duration=%u, latency=%u\n",
0217 name, idle_duration_us, latency_us);
0218
0219 kfree(name);
0220
0221 return 0;
0222
0223 out_kfree_name:
0224 kfree(name);
0225 out_unregister:
0226 idle_inject_unregister(ii_dev);
0227 out_kfree:
0228 kfree(idle_cdev);
0229 out:
0230 return ret;
0231 }
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243 void cpuidle_cooling_register(struct cpuidle_driver *drv)
0244 {
0245 struct device_node *cooling_node;
0246 struct device_node *cpu_node;
0247 int cpu, ret;
0248
0249 for_each_cpu(cpu, drv->cpumask) {
0250
0251 cpu_node = of_cpu_device_node_get(cpu);
0252
0253 cooling_node = of_get_child_by_name(cpu_node, "thermal-idle");
0254
0255 of_node_put(cpu_node);
0256
0257 if (!cooling_node) {
0258 pr_debug("'thermal-idle' node not found for cpu%d\n", cpu);
0259 continue;
0260 }
0261
0262 ret = __cpuidle_cooling_register(cooling_node, drv);
0263
0264 of_node_put(cooling_node);
0265
0266 if (ret) {
0267 pr_err("Failed to register the cpuidle cooling device" \
0268 "for cpu%d: %d\n", cpu, ret);
0269 break;
0270 }
0271 }
0272 }