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

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

DEFINITIONS

This source file includes following definitions.
  1. suspend_8960
  2. resume_8960
  3. enable_8960
  4. disable_8960
  5. init_8960
  6. calibrate_8960
  7. code_to_mdegC
  8. get_temp_8960

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Copyright (c) 2015, The Linux Foundation. All rights reserved.
   4  */
   5 
   6 #include <linux/platform_device.h>
   7 #include <linux/delay.h>
   8 #include <linux/bitops.h>
   9 #include <linux/regmap.h>
  10 #include <linux/thermal.h>
  11 #include "tsens.h"
  12 
  13 #define CAL_MDEGC               30000
  14 
  15 #define CONFIG_ADDR             0x3640
  16 #define CONFIG_ADDR_8660        0x3620
  17 /* CONFIG_ADDR bitmasks */
  18 #define CONFIG                  0x9b
  19 #define CONFIG_MASK             0xf
  20 #define CONFIG_8660             1
  21 #define CONFIG_SHIFT_8660       28
  22 #define CONFIG_MASK_8660        (3 << CONFIG_SHIFT_8660)
  23 
  24 #define STATUS_CNTL_ADDR_8064   0x3660
  25 #define CNTL_ADDR               0x3620
  26 /* CNTL_ADDR bitmasks */
  27 #define EN                      BIT(0)
  28 #define SW_RST                  BIT(1)
  29 #define SENSOR0_EN              BIT(3)
  30 #define SLP_CLK_ENA             BIT(26)
  31 #define SLP_CLK_ENA_8660        BIT(24)
  32 #define MEASURE_PERIOD          1
  33 #define SENSOR0_SHIFT           3
  34 
  35 /* INT_STATUS_ADDR bitmasks */
  36 #define MIN_STATUS_MASK         BIT(0)
  37 #define LOWER_STATUS_CLR        BIT(1)
  38 #define UPPER_STATUS_CLR        BIT(2)
  39 #define MAX_STATUS_MASK         BIT(3)
  40 
  41 #define THRESHOLD_ADDR          0x3624
  42 /* THRESHOLD_ADDR bitmasks */
  43 #define THRESHOLD_MAX_LIMIT_SHIFT       24
  44 #define THRESHOLD_MIN_LIMIT_SHIFT       16
  45 #define THRESHOLD_UPPER_LIMIT_SHIFT     8
  46 #define THRESHOLD_LOWER_LIMIT_SHIFT     0
  47 
  48 /* Initial temperature threshold values */
  49 #define LOWER_LIMIT_TH          0x50
  50 #define UPPER_LIMIT_TH          0xdf
  51 #define MIN_LIMIT_TH            0x0
  52 #define MAX_LIMIT_TH            0xff
  53 
  54 #define S0_STATUS_ADDR          0x3628
  55 #define INT_STATUS_ADDR         0x363c
  56 #define TRDY_MASK               BIT(7)
  57 #define TIMEOUT_US              100
  58 
  59 static int suspend_8960(struct tsens_priv *priv)
  60 {
  61         int ret;
  62         unsigned int mask;
  63         struct regmap *map = priv->tm_map;
  64 
  65         ret = regmap_read(map, THRESHOLD_ADDR, &priv->ctx.threshold);
  66         if (ret)
  67                 return ret;
  68 
  69         ret = regmap_read(map, CNTL_ADDR, &priv->ctx.control);
  70         if (ret)
  71                 return ret;
  72 
  73         if (priv->num_sensors > 1)
  74                 mask = SLP_CLK_ENA | EN;
  75         else
  76                 mask = SLP_CLK_ENA_8660 | EN;
  77 
  78         ret = regmap_update_bits(map, CNTL_ADDR, mask, 0);
  79         if (ret)
  80                 return ret;
  81 
  82         return 0;
  83 }
  84 
  85 static int resume_8960(struct tsens_priv *priv)
  86 {
  87         int ret;
  88         struct regmap *map = priv->tm_map;
  89 
  90         ret = regmap_update_bits(map, CNTL_ADDR, SW_RST, SW_RST);
  91         if (ret)
  92                 return ret;
  93 
  94         /*
  95          * Separate CONFIG restore is not needed only for 8660 as
  96          * config is part of CTRL Addr and its restored as such
  97          */
  98         if (priv->num_sensors > 1) {
  99                 ret = regmap_update_bits(map, CONFIG_ADDR, CONFIG_MASK, CONFIG);
 100                 if (ret)
 101                         return ret;
 102         }
 103 
 104         ret = regmap_write(map, THRESHOLD_ADDR, priv->ctx.threshold);
 105         if (ret)
 106                 return ret;
 107 
 108         ret = regmap_write(map, CNTL_ADDR, priv->ctx.control);
 109         if (ret)
 110                 return ret;
 111 
 112         return 0;
 113 }
 114 
 115 static int enable_8960(struct tsens_priv *priv, int id)
 116 {
 117         int ret;
 118         u32 reg, mask;
 119 
 120         ret = regmap_read(priv->tm_map, CNTL_ADDR, &reg);
 121         if (ret)
 122                 return ret;
 123 
 124         mask = BIT(id + SENSOR0_SHIFT);
 125         ret = regmap_write(priv->tm_map, CNTL_ADDR, reg | SW_RST);
 126         if (ret)
 127                 return ret;
 128 
 129         if (priv->num_sensors > 1)
 130                 reg |= mask | SLP_CLK_ENA | EN;
 131         else
 132                 reg |= mask | SLP_CLK_ENA_8660 | EN;
 133 
 134         ret = regmap_write(priv->tm_map, CNTL_ADDR, reg);
 135         if (ret)
 136                 return ret;
 137 
 138         return 0;
 139 }
 140 
 141 static void disable_8960(struct tsens_priv *priv)
 142 {
 143         int ret;
 144         u32 reg_cntl;
 145         u32 mask;
 146 
 147         mask = GENMASK(priv->num_sensors - 1, 0);
 148         mask <<= SENSOR0_SHIFT;
 149         mask |= EN;
 150 
 151         ret = regmap_read(priv->tm_map, CNTL_ADDR, &reg_cntl);
 152         if (ret)
 153                 return;
 154 
 155         reg_cntl &= ~mask;
 156 
 157         if (priv->num_sensors > 1)
 158                 reg_cntl &= ~SLP_CLK_ENA;
 159         else
 160                 reg_cntl &= ~SLP_CLK_ENA_8660;
 161 
 162         regmap_write(priv->tm_map, CNTL_ADDR, reg_cntl);
 163 }
 164 
 165 static int init_8960(struct tsens_priv *priv)
 166 {
 167         int ret, i;
 168         u32 reg_cntl;
 169 
 170         priv->tm_map = dev_get_regmap(priv->dev, NULL);
 171         if (!priv->tm_map)
 172                 return -ENODEV;
 173 
 174         /*
 175          * The status registers for each sensor are discontiguous
 176          * because some SoCs have 5 sensors while others have more
 177          * but the control registers stay in the same place, i.e
 178          * directly after the first 5 status registers.
 179          */
 180         for (i = 0; i < priv->num_sensors; i++) {
 181                 if (i >= 5)
 182                         priv->sensor[i].status = S0_STATUS_ADDR + 40;
 183                 priv->sensor[i].status += i * 4;
 184         }
 185 
 186         reg_cntl = SW_RST;
 187         ret = regmap_update_bits(priv->tm_map, CNTL_ADDR, SW_RST, reg_cntl);
 188         if (ret)
 189                 return ret;
 190 
 191         if (priv->num_sensors > 1) {
 192                 reg_cntl |= SLP_CLK_ENA | (MEASURE_PERIOD << 18);
 193                 reg_cntl &= ~SW_RST;
 194                 ret = regmap_update_bits(priv->tm_map, CONFIG_ADDR,
 195                                          CONFIG_MASK, CONFIG);
 196         } else {
 197                 reg_cntl |= SLP_CLK_ENA_8660 | (MEASURE_PERIOD << 16);
 198                 reg_cntl &= ~CONFIG_MASK_8660;
 199                 reg_cntl |= CONFIG_8660 << CONFIG_SHIFT_8660;
 200         }
 201 
 202         reg_cntl |= GENMASK(priv->num_sensors - 1, 0) << SENSOR0_SHIFT;
 203         ret = regmap_write(priv->tm_map, CNTL_ADDR, reg_cntl);
 204         if (ret)
 205                 return ret;
 206 
 207         reg_cntl |= EN;
 208         ret = regmap_write(priv->tm_map, CNTL_ADDR, reg_cntl);
 209         if (ret)
 210                 return ret;
 211 
 212         return 0;
 213 }
 214 
 215 static int calibrate_8960(struct tsens_priv *priv)
 216 {
 217         int i;
 218         char *data;
 219 
 220         ssize_t num_read = priv->num_sensors;
 221         struct tsens_sensor *s = priv->sensor;
 222 
 223         data = qfprom_read(priv->dev, "calib");
 224         if (IS_ERR(data))
 225                 data = qfprom_read(priv->dev, "calib_backup");
 226         if (IS_ERR(data))
 227                 return PTR_ERR(data);
 228 
 229         for (i = 0; i < num_read; i++, s++)
 230                 s->offset = data[i];
 231 
 232         kfree(data);
 233 
 234         return 0;
 235 }
 236 
 237 /* Temperature on y axis and ADC-code on x-axis */
 238 static inline int code_to_mdegC(u32 adc_code, const struct tsens_sensor *s)
 239 {
 240         int slope, offset;
 241 
 242         slope = thermal_zone_get_slope(s->tzd);
 243         offset = CAL_MDEGC - slope * s->offset;
 244 
 245         return adc_code * slope + offset;
 246 }
 247 
 248 static int get_temp_8960(struct tsens_priv *priv, int id, int *temp)
 249 {
 250         int ret;
 251         u32 code, trdy;
 252         const struct tsens_sensor *s = &priv->sensor[id];
 253         unsigned long timeout;
 254 
 255         timeout = jiffies + usecs_to_jiffies(TIMEOUT_US);
 256         do {
 257                 ret = regmap_read(priv->tm_map, INT_STATUS_ADDR, &trdy);
 258                 if (ret)
 259                         return ret;
 260                 if (!(trdy & TRDY_MASK))
 261                         continue;
 262                 ret = regmap_read(priv->tm_map, s->status, &code);
 263                 if (ret)
 264                         return ret;
 265                 *temp = code_to_mdegC(code, s);
 266                 return 0;
 267         } while (time_before(jiffies, timeout));
 268 
 269         return -ETIMEDOUT;
 270 }
 271 
 272 static const struct tsens_ops ops_8960 = {
 273         .init           = init_8960,
 274         .calibrate      = calibrate_8960,
 275         .get_temp       = get_temp_8960,
 276         .enable         = enable_8960,
 277         .disable        = disable_8960,
 278         .suspend        = suspend_8960,
 279         .resume         = resume_8960,
 280 };
 281 
 282 const struct tsens_plat_data data_8960 = {
 283         .num_sensors    = 11,
 284         .ops            = &ops_8960,
 285 };

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