1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * ST Thermal Sensor Driver core routines 4 * Author: Ajit Pal Singh <ajitpal.singh@st.com> 5 * 6 * Copyright (C) 2003-2014 STMicroelectronics (R&D) Limited 7 */ 8 9 #include <linux/clk.h> 10 #include <linux/module.h> 11 #include <linux/of.h> 12 #include <linux/of_device.h> 13 14 #include "st_thermal.h" 15 16 /* The Thermal Framework expects millidegrees */ 17 #define mcelsius(temp) ((temp) * 1000) 18 19 /* 20 * Function to allocate regfields which are common 21 * between syscfg and memory mapped based sensors 22 */ 23 static int st_thermal_alloc_regfields(struct st_thermal_sensor *sensor) 24 { 25 struct device *dev = sensor->dev; 26 struct regmap *regmap = sensor->regmap; 27 const struct reg_field *reg_fields = sensor->cdata->reg_fields; 28 29 sensor->dcorrect = devm_regmap_field_alloc(dev, regmap, 30 reg_fields[DCORRECT]); 31 32 sensor->overflow = devm_regmap_field_alloc(dev, regmap, 33 reg_fields[OVERFLOW]); 34 35 sensor->temp_data = devm_regmap_field_alloc(dev, regmap, 36 reg_fields[DATA]); 37 38 if (IS_ERR(sensor->dcorrect) || 39 IS_ERR(sensor->overflow) || 40 IS_ERR(sensor->temp_data)) { 41 dev_err(dev, "failed to allocate common regfields\n"); 42 return -EINVAL; 43 } 44 45 return sensor->ops->alloc_regfields(sensor); 46 } 47 48 static int st_thermal_sensor_on(struct st_thermal_sensor *sensor) 49 { 50 int ret; 51 struct device *dev = sensor->dev; 52 53 ret = clk_prepare_enable(sensor->clk); 54 if (ret) { 55 dev_err(dev, "failed to enable clk\n"); 56 return ret; 57 } 58 59 ret = sensor->ops->power_ctrl(sensor, POWER_ON); 60 if (ret) { 61 dev_err(dev, "failed to power on sensor\n"); 62 clk_disable_unprepare(sensor->clk); 63 } 64 65 return ret; 66 } 67 68 static int st_thermal_sensor_off(struct st_thermal_sensor *sensor) 69 { 70 int ret; 71 72 ret = sensor->ops->power_ctrl(sensor, POWER_OFF); 73 if (ret) 74 return ret; 75 76 clk_disable_unprepare(sensor->clk); 77 78 return 0; 79 } 80 81 static int st_thermal_calibration(struct st_thermal_sensor *sensor) 82 { 83 int ret; 84 unsigned int val; 85 struct device *dev = sensor->dev; 86 87 /* Check if sensor calibration data is already written */ 88 ret = regmap_field_read(sensor->dcorrect, &val); 89 if (ret) { 90 dev_err(dev, "failed to read calibration data\n"); 91 return ret; 92 } 93 94 if (!val) { 95 /* 96 * Sensor calibration value not set by bootloader, 97 * default calibration data to be used 98 */ 99 ret = regmap_field_write(sensor->dcorrect, 100 sensor->cdata->calibration_val); 101 if (ret) 102 dev_err(dev, "failed to set calibration data\n"); 103 } 104 105 return ret; 106 } 107 108 /* Callback to get temperature from HW*/ 109 static int st_thermal_get_temp(struct thermal_zone_device *th, int *temperature) 110 { 111 struct st_thermal_sensor *sensor = th->devdata; 112 struct device *dev = sensor->dev; 113 unsigned int temp; 114 unsigned int overflow; 115 int ret; 116 117 ret = regmap_field_read(sensor->overflow, &overflow); 118 if (ret) 119 return ret; 120 if (overflow) 121 return -EIO; 122 123 ret = regmap_field_read(sensor->temp_data, &temp); 124 if (ret) 125 return ret; 126 127 temp += sensor->cdata->temp_adjust_val; 128 temp = mcelsius(temp); 129 130 dev_dbg(dev, "temperature: %d\n", temp); 131 132 *temperature = temp; 133 134 return 0; 135 } 136 137 static struct thermal_zone_device_ops st_tz_ops = { 138 .get_temp = st_thermal_get_temp, 139 }; 140 141 static struct thermal_trip trip; 142 143 int st_thermal_register(struct platform_device *pdev, 144 const struct of_device_id *st_thermal_of_match) 145 { 146 struct st_thermal_sensor *sensor; 147 struct device *dev = &pdev->dev; 148 struct device_node *np = dev->of_node; 149 const struct of_device_id *match; 150 151 int polling_delay; 152 int ret; 153 154 if (!np) { 155 dev_err(dev, "device tree node not found\n"); 156 return -EINVAL; 157 } 158 159 sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL); 160 if (!sensor) 161 return -ENOMEM; 162 163 sensor->dev = dev; 164 165 match = of_match_device(st_thermal_of_match, dev); 166 if (!(match && match->data)) 167 return -EINVAL; 168 169 sensor->cdata = match->data; 170 if (!sensor->cdata->ops) 171 return -EINVAL; 172 173 sensor->ops = sensor->cdata->ops; 174 175 ret = (sensor->ops->regmap_init)(sensor); 176 if (ret) 177 return ret; 178 179 ret = st_thermal_alloc_regfields(sensor); 180 if (ret) 181 return ret; 182 183 sensor->clk = devm_clk_get(dev, "thermal"); 184 if (IS_ERR(sensor->clk)) { 185 dev_err(dev, "failed to fetch clock\n"); 186 return PTR_ERR(sensor->clk); 187 } 188 189 if (sensor->ops->register_enable_irq) { 190 ret = sensor->ops->register_enable_irq(sensor); 191 if (ret) 192 return ret; 193 } 194 195 ret = st_thermal_sensor_on(sensor); 196 if (ret) 197 return ret; 198 199 ret = st_thermal_calibration(sensor); 200 if (ret) 201 goto sensor_off; 202 203 polling_delay = sensor->ops->register_enable_irq ? 0 : 1000; 204 205 trip.temperature = sensor->cdata->crit_temp; 206 trip.type = THERMAL_TRIP_CRITICAL; 207 208 sensor->thermal_dev = 209 thermal_zone_device_register_with_trips(dev_name(dev), &trip, 1, 0, sensor, 210 &st_tz_ops, NULL, 0, polling_delay); 211 if (IS_ERR(sensor->thermal_dev)) { 212 dev_err(dev, "failed to register thermal zone device\n"); 213 ret = PTR_ERR(sensor->thermal_dev); 214 goto sensor_off; 215 } 216 ret = thermal_zone_device_enable(sensor->thermal_dev); 217 if (ret) 218 goto tzd_unregister; 219 220 platform_set_drvdata(pdev, sensor); 221 222 return 0; 223 224 tzd_unregister: 225 thermal_zone_device_unregister(sensor->thermal_dev); 226 sensor_off: 227 st_thermal_sensor_off(sensor); 228 229 return ret; 230 } 231 EXPORT_SYMBOL_GPL(st_thermal_register); 232 233 int st_thermal_unregister(struct platform_device *pdev) 234 { 235 struct st_thermal_sensor *sensor = platform_get_drvdata(pdev); 236 237 st_thermal_sensor_off(sensor); 238 thermal_zone_device_unregister(sensor->thermal_dev); 239 240 return 0; 241 } 242 EXPORT_SYMBOL_GPL(st_thermal_unregister); 243 244 #ifdef CONFIG_PM_SLEEP 245 static int st_thermal_suspend(struct device *dev) 246 { 247 struct st_thermal_sensor *sensor = dev_get_drvdata(dev); 248 249 return st_thermal_sensor_off(sensor); 250 } 251 252 static int st_thermal_resume(struct device *dev) 253 { 254 int ret; 255 struct st_thermal_sensor *sensor = dev_get_drvdata(dev); 256 257 ret = st_thermal_sensor_on(sensor); 258 if (ret) 259 return ret; 260 261 ret = st_thermal_calibration(sensor); 262 if (ret) 263 return ret; 264 265 if (sensor->ops->enable_irq) { 266 ret = sensor->ops->enable_irq(sensor); 267 if (ret) 268 return ret; 269 } 270 271 return 0; 272 } 273 #endif 274 275 SIMPLE_DEV_PM_OPS(st_thermal_pm_ops, st_thermal_suspend, st_thermal_resume); 276 EXPORT_SYMBOL_GPL(st_thermal_pm_ops); 277 278 MODULE_AUTHOR("STMicroelectronics (R&D) Limited <ajitpal.singh@st.com>"); 279 MODULE_DESCRIPTION("STMicroelectronics STi SoC Thermal Sensor Driver"); 280 MODULE_LICENSE("GPL v2"); 281