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 = thermal_zone_device_priv(th); 112 unsigned int temp; 113 unsigned int overflow; 114 int ret; 115 116 ret = regmap_field_read(sensor->overflow, &overflow); 117 if (ret) 118 return ret; 119 if (overflow) 120 return -EIO; 121 122 ret = regmap_field_read(sensor->temp_data, &temp); 123 if (ret) 124 return ret; 125 126 temp += sensor->cdata->temp_adjust_val; 127 temp = mcelsius(temp); 128 129 *temperature = temp; 130 131 return 0; 132 } 133 134 static struct thermal_zone_device_ops st_tz_ops = { 135 .get_temp = st_thermal_get_temp, 136 }; 137 138 static struct thermal_trip trip; 139 140 int st_thermal_register(struct platform_device *pdev, 141 const struct of_device_id *st_thermal_of_match) 142 { 143 struct st_thermal_sensor *sensor; 144 struct device *dev = &pdev->dev; 145 struct device_node *np = dev->of_node; 146 const struct of_device_id *match; 147 148 int polling_delay; 149 int ret; 150 151 if (!np) { 152 dev_err(dev, "device tree node not found\n"); 153 return -EINVAL; 154 } 155 156 sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL); 157 if (!sensor) 158 return -ENOMEM; 159 160 sensor->dev = dev; 161 162 match = of_match_device(st_thermal_of_match, dev); 163 if (!(match && match->data)) 164 return -EINVAL; 165 166 sensor->cdata = match->data; 167 if (!sensor->cdata->ops) 168 return -EINVAL; 169 170 sensor->ops = sensor->cdata->ops; 171 172 ret = (sensor->ops->regmap_init)(sensor); 173 if (ret) 174 return ret; 175 176 ret = st_thermal_alloc_regfields(sensor); 177 if (ret) 178 return ret; 179 180 sensor->clk = devm_clk_get(dev, "thermal"); 181 if (IS_ERR(sensor->clk)) { 182 dev_err(dev, "failed to fetch clock\n"); 183 return PTR_ERR(sensor->clk); 184 } 185 186 if (sensor->ops->register_enable_irq) { 187 ret = sensor->ops->register_enable_irq(sensor); 188 if (ret) 189 return ret; 190 } 191 192 ret = st_thermal_sensor_on(sensor); 193 if (ret) 194 return ret; 195 196 ret = st_thermal_calibration(sensor); 197 if (ret) 198 goto sensor_off; 199 200 polling_delay = sensor->ops->register_enable_irq ? 0 : 1000; 201 202 trip.temperature = sensor->cdata->crit_temp; 203 trip.type = THERMAL_TRIP_CRITICAL; 204 205 sensor->thermal_dev = 206 thermal_zone_device_register_with_trips(dev_name(dev), &trip, 1, sensor, 207 &st_tz_ops, NULL, 0, polling_delay); 208 if (IS_ERR(sensor->thermal_dev)) { 209 dev_err(dev, "failed to register thermal zone device\n"); 210 ret = PTR_ERR(sensor->thermal_dev); 211 goto sensor_off; 212 } 213 ret = thermal_zone_device_enable(sensor->thermal_dev); 214 if (ret) 215 goto tzd_unregister; 216 217 platform_set_drvdata(pdev, sensor); 218 219 return 0; 220 221 tzd_unregister: 222 thermal_zone_device_unregister(sensor->thermal_dev); 223 sensor_off: 224 st_thermal_sensor_off(sensor); 225 226 return ret; 227 } 228 EXPORT_SYMBOL_GPL(st_thermal_register); 229 230 void st_thermal_unregister(struct platform_device *pdev) 231 { 232 struct st_thermal_sensor *sensor = platform_get_drvdata(pdev); 233 234 st_thermal_sensor_off(sensor); 235 thermal_zone_device_unregister(sensor->thermal_dev); 236 } 237 EXPORT_SYMBOL_GPL(st_thermal_unregister); 238 239 #ifdef CONFIG_PM_SLEEP 240 static int st_thermal_suspend(struct device *dev) 241 { 242 struct st_thermal_sensor *sensor = dev_get_drvdata(dev); 243 244 return st_thermal_sensor_off(sensor); 245 } 246 247 static int st_thermal_resume(struct device *dev) 248 { 249 int ret; 250 struct st_thermal_sensor *sensor = dev_get_drvdata(dev); 251 252 ret = st_thermal_sensor_on(sensor); 253 if (ret) 254 return ret; 255 256 ret = st_thermal_calibration(sensor); 257 if (ret) 258 return ret; 259 260 if (sensor->ops->enable_irq) { 261 ret = sensor->ops->enable_irq(sensor); 262 if (ret) 263 return ret; 264 } 265 266 return 0; 267 } 268 #endif 269 270 SIMPLE_DEV_PM_OPS(st_thermal_pm_ops, st_thermal_suspend, st_thermal_resume); 271 EXPORT_SYMBOL_GPL(st_thermal_pm_ops); 272 273 MODULE_AUTHOR("STMicroelectronics (R&D) Limited <ajitpal.singh@st.com>"); 274 MODULE_DESCRIPTION("STMicroelectronics STi SoC Thermal Sensor Driver"); 275 MODULE_LICENSE("GPL v2"); 276