root/drivers/thermal/qcom/tsens-common.c

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

DEFINITIONS

This source file includes following definitions.
  1. qfprom_read
  2. compute_intercept_slope
  3. code_to_degc
  4. get_temp_tsens_valid
  5. get_temp_common
  6. init_common

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Copyright (c) 2015, The Linux Foundation. All rights reserved.
   4  */
   5 
   6 #include <linux/err.h>
   7 #include <linux/io.h>
   8 #include <linux/nvmem-consumer.h>
   9 #include <linux/of_address.h>
  10 #include <linux/of_platform.h>
  11 #include <linux/platform_device.h>
  12 #include <linux/regmap.h>
  13 #include "tsens.h"
  14 
  15 char *qfprom_read(struct device *dev, const char *cname)
  16 {
  17         struct nvmem_cell *cell;
  18         ssize_t data;
  19         char *ret;
  20 
  21         cell = nvmem_cell_get(dev, cname);
  22         if (IS_ERR(cell))
  23                 return ERR_CAST(cell);
  24 
  25         ret = nvmem_cell_read(cell, &data);
  26         nvmem_cell_put(cell);
  27 
  28         return ret;
  29 }
  30 
  31 /*
  32  * Use this function on devices where slope and offset calculations
  33  * depend on calibration data read from qfprom. On others the slope
  34  * and offset values are derived from tz->tzp->slope and tz->tzp->offset
  35  * resp.
  36  */
  37 void compute_intercept_slope(struct tsens_priv *priv, u32 *p1,
  38                              u32 *p2, u32 mode)
  39 {
  40         int i;
  41         int num, den;
  42 
  43         for (i = 0; i < priv->num_sensors; i++) {
  44                 dev_dbg(priv->dev,
  45                         "sensor%d - data_point1:%#x data_point2:%#x\n",
  46                         i, p1[i], p2[i]);
  47 
  48                 priv->sensor[i].slope = SLOPE_DEFAULT;
  49                 if (mode == TWO_PT_CALIB) {
  50                         /*
  51                          * slope (m) = adc_code2 - adc_code1 (y2 - y1)/
  52                          *      temp_120_degc - temp_30_degc (x2 - x1)
  53                          */
  54                         num = p2[i] - p1[i];
  55                         num *= SLOPE_FACTOR;
  56                         den = CAL_DEGC_PT2 - CAL_DEGC_PT1;
  57                         priv->sensor[i].slope = num / den;
  58                 }
  59 
  60                 priv->sensor[i].offset = (p1[i] * SLOPE_FACTOR) -
  61                                 (CAL_DEGC_PT1 *
  62                                 priv->sensor[i].slope);
  63                 dev_dbg(priv->dev, "offset:%d\n", priv->sensor[i].offset);
  64         }
  65 }
  66 
  67 static inline int code_to_degc(u32 adc_code, const struct tsens_sensor *s)
  68 {
  69         int degc, num, den;
  70 
  71         num = (adc_code * SLOPE_FACTOR) - s->offset;
  72         den = s->slope;
  73 
  74         if (num > 0)
  75                 degc = num + (den / 2);
  76         else if (num < 0)
  77                 degc = num - (den / 2);
  78         else
  79                 degc = num;
  80 
  81         degc /= den;
  82 
  83         return degc;
  84 }
  85 
  86 int get_temp_tsens_valid(struct tsens_priv *priv, int i, int *temp)
  87 {
  88         struct tsens_sensor *s = &priv->sensor[i];
  89         u32 temp_idx = LAST_TEMP_0 + s->hw_id;
  90         u32 valid_idx = VALID_0 + s->hw_id;
  91         u32 last_temp = 0, valid, mask;
  92         int ret;
  93 
  94         ret = regmap_field_read(priv->rf[valid_idx], &valid);
  95         if (ret)
  96                 return ret;
  97         while (!valid) {
  98                 /* Valid bit is 0 for 6 AHB clock cycles.
  99                  * At 19.2MHz, 1 AHB clock is ~60ns.
 100                  * We should enter this loop very, very rarely.
 101                  */
 102                 ndelay(400);
 103                 ret = regmap_field_read(priv->rf[valid_idx], &valid);
 104                 if (ret)
 105                         return ret;
 106         }
 107 
 108         /* Valid bit is set, OK to read the temperature */
 109         ret = regmap_field_read(priv->rf[temp_idx], &last_temp);
 110         if (ret)
 111                 return ret;
 112 
 113         if (priv->feat->adc) {
 114                 /* Convert temperature from ADC code to milliCelsius */
 115                 *temp = code_to_degc(last_temp, s) * 1000;
 116         } else {
 117                 mask = GENMASK(priv->fields[LAST_TEMP_0].msb,
 118                                priv->fields[LAST_TEMP_0].lsb);
 119                 /* Convert temperature from deciCelsius to milliCelsius */
 120                 *temp = sign_extend32(last_temp, fls(mask) - 1) * 100;
 121         }
 122 
 123         return 0;
 124 }
 125 
 126 int get_temp_common(struct tsens_priv *priv, int i, int *temp)
 127 {
 128         struct tsens_sensor *s = &priv->sensor[i];
 129         int last_temp = 0, ret;
 130 
 131         ret = regmap_field_read(priv->rf[LAST_TEMP_0 + s->hw_id], &last_temp);
 132         if (ret)
 133                 return ret;
 134 
 135         *temp = code_to_degc(last_temp, s) * 1000;
 136 
 137         return 0;
 138 }
 139 
 140 static const struct regmap_config tsens_config = {
 141         .name           = "tm",
 142         .reg_bits       = 32,
 143         .val_bits       = 32,
 144         .reg_stride     = 4,
 145 };
 146 
 147 static const struct regmap_config tsens_srot_config = {
 148         .name           = "srot",
 149         .reg_bits       = 32,
 150         .val_bits       = 32,
 151         .reg_stride     = 4,
 152 };
 153 
 154 int __init init_common(struct tsens_priv *priv)
 155 {
 156         void __iomem *tm_base, *srot_base;
 157         struct device *dev = priv->dev;
 158         struct resource *res;
 159         u32 enabled;
 160         int ret, i, j;
 161         struct platform_device *op = of_find_device_by_node(priv->dev->of_node);
 162 
 163         if (!op)
 164                 return -EINVAL;
 165 
 166         if (op->num_resources > 1) {
 167                 /* DT with separate SROT and TM address space */
 168                 priv->tm_offset = 0;
 169                 res = platform_get_resource(op, IORESOURCE_MEM, 1);
 170                 srot_base = devm_ioremap_resource(&op->dev, res);
 171                 if (IS_ERR(srot_base)) {
 172                         ret = PTR_ERR(srot_base);
 173                         goto err_put_device;
 174                 }
 175 
 176                 priv->srot_map = devm_regmap_init_mmio(dev, srot_base,
 177                                                         &tsens_srot_config);
 178                 if (IS_ERR(priv->srot_map)) {
 179                         ret = PTR_ERR(priv->srot_map);
 180                         goto err_put_device;
 181                 }
 182         } else {
 183                 /* old DTs where SROT and TM were in a contiguous 2K block */
 184                 priv->tm_offset = 0x1000;
 185         }
 186 
 187         res = platform_get_resource(op, IORESOURCE_MEM, 0);
 188         tm_base = devm_ioremap_resource(&op->dev, res);
 189         if (IS_ERR(tm_base)) {
 190                 ret = PTR_ERR(tm_base);
 191                 goto err_put_device;
 192         }
 193 
 194         priv->tm_map = devm_regmap_init_mmio(dev, tm_base, &tsens_config);
 195         if (IS_ERR(priv->tm_map)) {
 196                 ret = PTR_ERR(priv->tm_map);
 197                 goto err_put_device;
 198         }
 199 
 200         priv->rf[TSENS_EN] = devm_regmap_field_alloc(dev, priv->srot_map,
 201                                                      priv->fields[TSENS_EN]);
 202         if (IS_ERR(priv->rf[TSENS_EN])) {
 203                 ret = PTR_ERR(priv->rf[TSENS_EN]);
 204                 goto err_put_device;
 205         }
 206         ret = regmap_field_read(priv->rf[TSENS_EN], &enabled);
 207         if (ret)
 208                 goto err_put_device;
 209         if (!enabled) {
 210                 dev_err(dev, "tsens device is not enabled\n");
 211                 ret = -ENODEV;
 212                 goto err_put_device;
 213         }
 214 
 215         priv->rf[SENSOR_EN] = devm_regmap_field_alloc(dev, priv->srot_map,
 216                                                       priv->fields[SENSOR_EN]);
 217         if (IS_ERR(priv->rf[SENSOR_EN])) {
 218                 ret = PTR_ERR(priv->rf[SENSOR_EN]);
 219                 goto err_put_device;
 220         }
 221         /* now alloc regmap_fields in tm_map */
 222         for (i = 0, j = LAST_TEMP_0; i < priv->feat->max_sensors; i++, j++) {
 223                 priv->rf[j] = devm_regmap_field_alloc(dev, priv->tm_map,
 224                                                       priv->fields[j]);
 225                 if (IS_ERR(priv->rf[j])) {
 226                         ret = PTR_ERR(priv->rf[j]);
 227                         goto err_put_device;
 228                 }
 229         }
 230         for (i = 0, j = VALID_0; i < priv->feat->max_sensors; i++, j++) {
 231                 priv->rf[j] = devm_regmap_field_alloc(dev, priv->tm_map,
 232                                                       priv->fields[j]);
 233                 if (IS_ERR(priv->rf[j])) {
 234                         ret = PTR_ERR(priv->rf[j]);
 235                         goto err_put_device;
 236                 }
 237         }
 238 
 239         return 0;
 240 
 241 err_put_device:
 242         put_device(&op->dev);
 243         return ret;
 244 }

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