root/drivers/thermal/st/st_thermal.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. st_thermal_alloc_regfields
  2. st_thermal_sensor_on
  3. st_thermal_sensor_off
  4. st_thermal_calibration
  5. st_thermal_get_temp
  6. st_thermal_get_trip_type
  7. st_thermal_get_trip_temp
  8. st_thermal_register
  9. st_thermal_unregister
  10. st_thermal_suspend
  11. st_thermal_resume

   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 int st_thermal_get_trip_type(struct thermal_zone_device *th,
 138                                 int trip, enum thermal_trip_type *type)
 139 {
 140         struct st_thermal_sensor *sensor = th->devdata;
 141         struct device *dev = sensor->dev;
 142 
 143         switch (trip) {
 144         case 0:
 145                 *type = THERMAL_TRIP_CRITICAL;
 146                 break;
 147         default:
 148                 dev_err(dev, "invalid trip point\n");
 149                 return -EINVAL;
 150         }
 151 
 152         return 0;
 153 }
 154 
 155 static int st_thermal_get_trip_temp(struct thermal_zone_device *th,
 156                                     int trip, int *temp)
 157 {
 158         struct st_thermal_sensor *sensor = th->devdata;
 159         struct device *dev = sensor->dev;
 160 
 161         switch (trip) {
 162         case 0:
 163                 *temp = mcelsius(sensor->cdata->crit_temp);
 164                 break;
 165         default:
 166                 dev_err(dev, "Invalid trip point\n");
 167                 return -EINVAL;
 168         }
 169 
 170         return 0;
 171 }
 172 
 173 static struct thermal_zone_device_ops st_tz_ops = {
 174         .get_temp       = st_thermal_get_temp,
 175         .get_trip_type  = st_thermal_get_trip_type,
 176         .get_trip_temp  = st_thermal_get_trip_temp,
 177 };
 178 
 179 int st_thermal_register(struct platform_device *pdev,
 180                         const struct of_device_id *st_thermal_of_match)
 181 {
 182         struct st_thermal_sensor *sensor;
 183         struct device *dev = &pdev->dev;
 184         struct device_node *np = dev->of_node;
 185         const struct of_device_id *match;
 186 
 187         int polling_delay;
 188         int ret;
 189 
 190         if (!np) {
 191                 dev_err(dev, "device tree node not found\n");
 192                 return -EINVAL;
 193         }
 194 
 195         sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL);
 196         if (!sensor)
 197                 return -ENOMEM;
 198 
 199         sensor->dev = dev;
 200 
 201         match = of_match_device(st_thermal_of_match, dev);
 202         if (!(match && match->data))
 203                 return -EINVAL;
 204 
 205         sensor->cdata = match->data;
 206         if (!sensor->cdata->ops)
 207                 return -EINVAL;
 208 
 209         sensor->ops = sensor->cdata->ops;
 210 
 211         ret = (sensor->ops->regmap_init)(sensor);
 212         if (ret)
 213                 return ret;
 214 
 215         ret = st_thermal_alloc_regfields(sensor);
 216         if (ret)
 217                 return ret;
 218 
 219         sensor->clk = devm_clk_get(dev, "thermal");
 220         if (IS_ERR(sensor->clk)) {
 221                 dev_err(dev, "failed to fetch clock\n");
 222                 return PTR_ERR(sensor->clk);
 223         }
 224 
 225         if (sensor->ops->register_enable_irq) {
 226                 ret = sensor->ops->register_enable_irq(sensor);
 227                 if (ret)
 228                         return ret;
 229         }
 230 
 231         ret = st_thermal_sensor_on(sensor);
 232         if (ret)
 233                 return ret;
 234 
 235         ret = st_thermal_calibration(sensor);
 236         if (ret)
 237                 goto sensor_off;
 238 
 239         polling_delay = sensor->ops->register_enable_irq ? 0 : 1000;
 240 
 241         sensor->thermal_dev =
 242                 thermal_zone_device_register(dev_name(dev), 1, 0, sensor,
 243                                              &st_tz_ops, NULL, 0, polling_delay);
 244         if (IS_ERR(sensor->thermal_dev)) {
 245                 dev_err(dev, "failed to register thermal zone device\n");
 246                 ret = PTR_ERR(sensor->thermal_dev);
 247                 goto sensor_off;
 248         }
 249 
 250         platform_set_drvdata(pdev, sensor);
 251 
 252         return 0;
 253 
 254 sensor_off:
 255         st_thermal_sensor_off(sensor);
 256 
 257         return ret;
 258 }
 259 EXPORT_SYMBOL_GPL(st_thermal_register);
 260 
 261 int st_thermal_unregister(struct platform_device *pdev)
 262 {
 263         struct st_thermal_sensor *sensor = platform_get_drvdata(pdev);
 264 
 265         st_thermal_sensor_off(sensor);
 266         thermal_zone_device_unregister(sensor->thermal_dev);
 267 
 268         return 0;
 269 }
 270 EXPORT_SYMBOL_GPL(st_thermal_unregister);
 271 
 272 #ifdef CONFIG_PM_SLEEP
 273 static int st_thermal_suspend(struct device *dev)
 274 {
 275         struct st_thermal_sensor *sensor = dev_get_drvdata(dev);
 276 
 277         return st_thermal_sensor_off(sensor);
 278 }
 279 
 280 static int st_thermal_resume(struct device *dev)
 281 {
 282         int ret;
 283         struct st_thermal_sensor *sensor = dev_get_drvdata(dev);
 284 
 285         ret = st_thermal_sensor_on(sensor);
 286         if (ret)
 287                 return ret;
 288 
 289         ret = st_thermal_calibration(sensor);
 290         if (ret)
 291                 return ret;
 292 
 293         if (sensor->ops->enable_irq) {
 294                 ret = sensor->ops->enable_irq(sensor);
 295                 if (ret)
 296                         return ret;
 297         }
 298 
 299         return 0;
 300 }
 301 #endif
 302 
 303 SIMPLE_DEV_PM_OPS(st_thermal_pm_ops, st_thermal_suspend, st_thermal_resume);
 304 EXPORT_SYMBOL_GPL(st_thermal_pm_ops);
 305 
 306 MODULE_AUTHOR("STMicroelectronics (R&D) Limited <ajitpal.singh@st.com>");
 307 MODULE_DESCRIPTION("STMicroelectronics STi SoC Thermal Sensor Driver");
 308 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */