0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/device.h>
0011 #include <linux/err.h>
0012 #include <linux/mutex.h>
0013 #include <linux/gfp.h>
0014 #include <linux/kernel.h>
0015 #include <linux/workqueue.h>
0016 #include <linux/thermal.h>
0017 #include <linux/cpufreq.h>
0018 #include <linux/cpumask.h>
0019 #include <linux/cpu_cooling.h>
0020 #include <linux/of.h>
0021
0022 #include "ti-thermal.h"
0023 #include "ti-bandgap.h"
0024 #include "../thermal_hwmon.h"
0025
0026
0027 struct ti_thermal_data {
0028 struct cpufreq_policy *policy;
0029 struct thermal_zone_device *ti_thermal;
0030 struct thermal_zone_device *pcb_tz;
0031 struct thermal_cooling_device *cool_dev;
0032 struct ti_bandgap *bgp;
0033 enum thermal_device_mode mode;
0034 struct work_struct thermal_wq;
0035 int sensor_id;
0036 bool our_zone;
0037 };
0038
0039 static void ti_thermal_work(struct work_struct *work)
0040 {
0041 struct ti_thermal_data *data = container_of(work,
0042 struct ti_thermal_data, thermal_wq);
0043
0044 thermal_zone_device_update(data->ti_thermal, THERMAL_EVENT_UNSPECIFIED);
0045
0046 dev_dbg(&data->ti_thermal->device, "updated thermal zone %s\n",
0047 data->ti_thermal->type);
0048 }
0049
0050
0051
0052
0053
0054
0055
0056 static inline int ti_thermal_hotspot_temperature(int t, int s, int c)
0057 {
0058 int delta = t * s / 1000 + c;
0059
0060 if (delta < 0)
0061 delta = 0;
0062
0063 return t + delta;
0064 }
0065
0066
0067
0068 static inline int __ti_thermal_get_temp(void *devdata, int *temp)
0069 {
0070 struct thermal_zone_device *pcb_tz = NULL;
0071 struct ti_thermal_data *data = devdata;
0072 struct ti_bandgap *bgp;
0073 const struct ti_temp_sensor *s;
0074 int ret, tmp, slope, constant;
0075 int pcb_temp;
0076
0077 if (!data)
0078 return 0;
0079
0080 bgp = data->bgp;
0081 s = &bgp->conf->sensors[data->sensor_id];
0082
0083 ret = ti_bandgap_read_temperature(bgp, data->sensor_id, &tmp);
0084 if (ret)
0085 return ret;
0086
0087
0088 slope = thermal_zone_get_slope(data->ti_thermal);
0089 constant = thermal_zone_get_offset(data->ti_thermal);
0090
0091 pcb_tz = data->pcb_tz;
0092
0093 if (!IS_ERR(pcb_tz)) {
0094 ret = thermal_zone_get_temp(pcb_tz, &pcb_temp);
0095 if (!ret) {
0096 tmp -= pcb_temp;
0097 slope = s->slope_pcb;
0098 constant = s->constant_pcb;
0099 } else {
0100 dev_err(bgp->dev,
0101 "Failed to read PCB state. Using defaults\n");
0102 ret = 0;
0103 }
0104 }
0105 *temp = ti_thermal_hotspot_temperature(tmp, slope, constant);
0106
0107 return ret;
0108 }
0109
0110 static int __ti_thermal_get_trend(void *p, int trip, enum thermal_trend *trend)
0111 {
0112 struct ti_thermal_data *data = p;
0113 struct ti_bandgap *bgp;
0114 int id, tr, ret = 0;
0115
0116 bgp = data->bgp;
0117 id = data->sensor_id;
0118
0119 ret = ti_bandgap_get_trend(bgp, id, &tr);
0120 if (ret)
0121 return ret;
0122
0123 if (tr > 0)
0124 *trend = THERMAL_TREND_RAISING;
0125 else if (tr < 0)
0126 *trend = THERMAL_TREND_DROPPING;
0127 else
0128 *trend = THERMAL_TREND_STABLE;
0129
0130 return 0;
0131 }
0132
0133 static const struct thermal_zone_of_device_ops ti_of_thermal_ops = {
0134 .get_temp = __ti_thermal_get_temp,
0135 .get_trend = __ti_thermal_get_trend,
0136 };
0137
0138 static struct ti_thermal_data
0139 *ti_thermal_build_data(struct ti_bandgap *bgp, int id)
0140 {
0141 struct ti_thermal_data *data;
0142
0143 data = devm_kzalloc(bgp->dev, sizeof(*data), GFP_KERNEL);
0144 if (!data) {
0145 dev_err(bgp->dev, "kzalloc fail\n");
0146 return NULL;
0147 }
0148 data->sensor_id = id;
0149 data->bgp = bgp;
0150 data->mode = THERMAL_DEVICE_ENABLED;
0151
0152 data->pcb_tz = thermal_zone_get_zone_by_name("pcb");
0153 INIT_WORK(&data->thermal_wq, ti_thermal_work);
0154
0155 return data;
0156 }
0157
0158 int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id,
0159 char *domain)
0160 {
0161 struct ti_thermal_data *data;
0162 int interval;
0163
0164 data = ti_bandgap_get_sensor_data(bgp, id);
0165
0166 if (IS_ERR_OR_NULL(data))
0167 data = ti_thermal_build_data(bgp, id);
0168
0169 if (!data)
0170 return -EINVAL;
0171
0172
0173 data->ti_thermal = devm_thermal_zone_of_sensor_register(bgp->dev, id,
0174 data, &ti_of_thermal_ops);
0175 if (IS_ERR(data->ti_thermal)) {
0176 dev_err(bgp->dev, "thermal zone device is NULL\n");
0177 return PTR_ERR(data->ti_thermal);
0178 }
0179
0180 interval = jiffies_to_msecs(data->ti_thermal->polling_delay_jiffies);
0181
0182 ti_bandgap_set_sensor_data(bgp, id, data);
0183 ti_bandgap_write_update_interval(bgp, data->sensor_id, interval);
0184
0185 if (devm_thermal_add_hwmon_sysfs(data->ti_thermal))
0186 dev_warn(bgp->dev, "failed to add hwmon sysfs attributes\n");
0187
0188 return 0;
0189 }
0190
0191 int ti_thermal_remove_sensor(struct ti_bandgap *bgp, int id)
0192 {
0193 struct ti_thermal_data *data;
0194
0195 data = ti_bandgap_get_sensor_data(bgp, id);
0196
0197 if (!IS_ERR_OR_NULL(data) && data->ti_thermal) {
0198 if (data->our_zone)
0199 thermal_zone_device_unregister(data->ti_thermal);
0200 }
0201
0202 return 0;
0203 }
0204
0205 int ti_thermal_report_sensor_temperature(struct ti_bandgap *bgp, int id)
0206 {
0207 struct ti_thermal_data *data;
0208
0209 data = ti_bandgap_get_sensor_data(bgp, id);
0210
0211 schedule_work(&data->thermal_wq);
0212
0213 return 0;
0214 }
0215
0216 int ti_thermal_register_cpu_cooling(struct ti_bandgap *bgp, int id)
0217 {
0218 struct ti_thermal_data *data;
0219 struct device_node *np = bgp->dev->of_node;
0220
0221
0222
0223
0224
0225
0226 if (of_find_property(np, "#thermal-sensor-cells", NULL))
0227 return 0;
0228
0229 data = ti_bandgap_get_sensor_data(bgp, id);
0230 if (!data || IS_ERR(data))
0231 data = ti_thermal_build_data(bgp, id);
0232
0233 if (!data)
0234 return -EINVAL;
0235
0236 data->policy = cpufreq_cpu_get(0);
0237 if (!data->policy) {
0238 pr_debug("%s: CPUFreq policy not found\n", __func__);
0239 return -EPROBE_DEFER;
0240 }
0241
0242
0243 data->cool_dev = cpufreq_cooling_register(data->policy);
0244 if (IS_ERR(data->cool_dev)) {
0245 int ret = PTR_ERR(data->cool_dev);
0246 dev_err(bgp->dev, "Failed to register cpu cooling device %d\n",
0247 ret);
0248 cpufreq_cpu_put(data->policy);
0249
0250 return ret;
0251 }
0252 ti_bandgap_set_sensor_data(bgp, id, data);
0253
0254 return 0;
0255 }
0256
0257 int ti_thermal_unregister_cpu_cooling(struct ti_bandgap *bgp, int id)
0258 {
0259 struct ti_thermal_data *data;
0260
0261 data = ti_bandgap_get_sensor_data(bgp, id);
0262
0263 if (!IS_ERR_OR_NULL(data)) {
0264 cpufreq_cooling_unregister(data->cool_dev);
0265 if (data->policy)
0266 cpufreq_cpu_put(data->policy);
0267 }
0268
0269 return 0;
0270 }