linux/drivers/hwmon/tmp108.c
<<
>>
Prefs
   1/* Texas Instruments TMP108 SMBus temperature sensor driver
   2 *
   3 * Copyright (C) 2016 John Muir <john@jmuir.com>
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License as published by
   7 * the Free Software Foundation; either version 2 of the License, or
   8 * (at your option) any later version.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 */
  15
  16#include <linux/delay.h>
  17#include <linux/device.h>
  18#include <linux/err.h>
  19#include <linux/hwmon.h>
  20#include <linux/hwmon-sysfs.h>
  21#include <linux/module.h>
  22#include <linux/mutex.h>
  23#include <linux/of.h>
  24#include <linux/i2c.h>
  25#include <linux/init.h>
  26#include <linux/jiffies.h>
  27#include <linux/regmap.h>
  28#include <linux/slab.h>
  29
  30#define DRIVER_NAME "tmp108"
  31
  32#define TMP108_REG_TEMP         0x00
  33#define TMP108_REG_CONF         0x01
  34#define TMP108_REG_TLOW         0x02
  35#define TMP108_REG_THIGH        0x03
  36
  37#define TMP108_TEMP_MIN_MC      -50000 /* Minimum millicelcius. */
  38#define TMP108_TEMP_MAX_MC      127937 /* Maximum millicelcius. */
  39
  40/* Configuration register bits.
  41 * Note: these bit definitions are byte swapped.
  42 */
  43#define TMP108_CONF_M0          0x0100 /* Sensor mode. */
  44#define TMP108_CONF_M1          0x0200
  45#define TMP108_CONF_TM          0x0400 /* Thermostat mode. */
  46#define TMP108_CONF_FL          0x0800 /* Watchdog flag - TLOW */
  47#define TMP108_CONF_FH          0x1000 /* Watchdog flag - THIGH */
  48#define TMP108_CONF_CR0         0x2000 /* Conversion rate. */
  49#define TMP108_CONF_CR1         0x4000
  50#define TMP108_CONF_ID          0x8000
  51#define TMP108_CONF_HYS0        0x0010 /* Hysteresis. */
  52#define TMP108_CONF_HYS1        0x0020
  53#define TMP108_CONF_POL         0x0080 /* Polarity of alert. */
  54
  55/* Defaults set by the hardware upon reset. */
  56#define TMP108_CONF_DEFAULTS            (TMP108_CONF_CR0 | TMP108_CONF_TM |\
  57                                         TMP108_CONF_HYS0 | TMP108_CONF_M1)
  58/* These bits are read-only. */
  59#define TMP108_CONF_READ_ONLY           (TMP108_CONF_FL | TMP108_CONF_FH |\
  60                                         TMP108_CONF_ID)
  61
  62#define TMP108_CONF_MODE_MASK           (TMP108_CONF_M0|TMP108_CONF_M1)
  63#define TMP108_MODE_SHUTDOWN            0x0000
  64#define TMP108_MODE_ONE_SHOT            TMP108_CONF_M0
  65#define TMP108_MODE_CONTINUOUS          TMP108_CONF_M1          /* Default */
  66                                        /* When M1 is set, M0 is ignored. */
  67
  68#define TMP108_CONF_CONVRATE_MASK       (TMP108_CONF_CR0|TMP108_CONF_CR1)
  69#define TMP108_CONVRATE_0P25HZ          0x0000
  70#define TMP108_CONVRATE_1HZ             TMP108_CONF_CR0         /* Default */
  71#define TMP108_CONVRATE_4HZ             TMP108_CONF_CR1
  72#define TMP108_CONVRATE_16HZ            (TMP108_CONF_CR0|TMP108_CONF_CR1)
  73
  74#define TMP108_CONF_HYSTERESIS_MASK     (TMP108_CONF_HYS0|TMP108_CONF_HYS1)
  75#define TMP108_HYSTERESIS_0C            0x0000
  76#define TMP108_HYSTERESIS_1C            TMP108_CONF_HYS0        /* Default */
  77#define TMP108_HYSTERESIS_2C            TMP108_CONF_HYS1
  78#define TMP108_HYSTERESIS_4C            (TMP108_CONF_HYS0|TMP108_CONF_HYS1)
  79
  80#define TMP108_CONVERSION_TIME_MS       30      /* in milli-seconds */
  81
  82struct tmp108 {
  83        struct regmap *regmap;
  84        u16 orig_config;
  85        unsigned long ready_time;
  86};
  87
  88/* convert 12-bit TMP108 register value to milliCelsius */
  89static inline int tmp108_temp_reg_to_mC(s16 val)
  90{
  91        return (val & ~0x0f) * 1000 / 256;
  92}
  93
  94/* convert milliCelsius to left adjusted 12-bit TMP108 register value */
  95static inline u16 tmp108_mC_to_temp_reg(int val)
  96{
  97        return (val * 256) / 1000;
  98}
  99
 100static int tmp108_read(struct device *dev, enum hwmon_sensor_types type,
 101                       u32 attr, int channel, long *temp)
 102{
 103        struct tmp108 *tmp108 = dev_get_drvdata(dev);
 104        unsigned int regval;
 105        int err, hyst;
 106
 107        if (type == hwmon_chip) {
 108                if (attr == hwmon_chip_update_interval) {
 109                        err = regmap_read(tmp108->regmap, TMP108_REG_CONF,
 110                                          &regval);
 111                        if (err < 0)
 112                                return err;
 113                        switch (regval & TMP108_CONF_CONVRATE_MASK) {
 114                        case TMP108_CONVRATE_0P25HZ:
 115                        default:
 116                                *temp = 4000;
 117                                break;
 118                        case TMP108_CONVRATE_1HZ:
 119                                *temp = 1000;
 120                                break;
 121                        case TMP108_CONVRATE_4HZ:
 122                                *temp = 250;
 123                                break;
 124                        case TMP108_CONVRATE_16HZ:
 125                                *temp = 63;
 126                                break;
 127                        }
 128                        return 0;
 129                }
 130                return -EOPNOTSUPP;
 131        }
 132
 133        switch (attr) {
 134        case hwmon_temp_input:
 135                /* Is it too early to return a conversion ? */
 136                if (time_before(jiffies, tmp108->ready_time)) {
 137                        dev_dbg(dev, "%s: Conversion not ready yet..\n",
 138                                __func__);
 139                        return -EAGAIN;
 140                }
 141                err = regmap_read(tmp108->regmap, TMP108_REG_TEMP, &regval);
 142                if (err < 0)
 143                        return err;
 144                *temp = tmp108_temp_reg_to_mC(regval);
 145                break;
 146        case hwmon_temp_min:
 147        case hwmon_temp_max:
 148                err = regmap_read(tmp108->regmap, attr == hwmon_temp_min ?
 149                                  TMP108_REG_TLOW : TMP108_REG_THIGH, &regval);
 150                if (err < 0)
 151                        return err;
 152                *temp = tmp108_temp_reg_to_mC(regval);
 153                break;
 154        case hwmon_temp_min_alarm:
 155        case hwmon_temp_max_alarm:
 156                err = regmap_read(tmp108->regmap, TMP108_REG_CONF, &regval);
 157                if (err < 0)
 158                        return err;
 159                *temp = !!(regval & (attr == hwmon_temp_min_alarm ?
 160                                     TMP108_CONF_FL : TMP108_CONF_FH));
 161                break;
 162        case hwmon_temp_min_hyst:
 163        case hwmon_temp_max_hyst:
 164                err = regmap_read(tmp108->regmap, TMP108_REG_CONF, &regval);
 165                if (err < 0)
 166                        return err;
 167                switch (regval & TMP108_CONF_HYSTERESIS_MASK) {
 168                case TMP108_HYSTERESIS_0C:
 169                default:
 170                        hyst = 0;
 171                        break;
 172                case TMP108_HYSTERESIS_1C:
 173                        hyst = 1000;
 174                        break;
 175                case TMP108_HYSTERESIS_2C:
 176                        hyst = 2000;
 177                        break;
 178                case TMP108_HYSTERESIS_4C:
 179                        hyst = 4000;
 180                        break;
 181                }
 182                err = regmap_read(tmp108->regmap, attr == hwmon_temp_min_hyst ?
 183                                  TMP108_REG_TLOW : TMP108_REG_THIGH, &regval);
 184                if (err < 0)
 185                        return err;
 186                *temp = tmp108_temp_reg_to_mC(regval);
 187                if (attr == hwmon_temp_min_hyst)
 188                        *temp += hyst;
 189                else
 190                        *temp -= hyst;
 191                break;
 192        default:
 193                return -EOPNOTSUPP;
 194        }
 195
 196        return 0;
 197}
 198
 199static int tmp108_write(struct device *dev, enum hwmon_sensor_types type,
 200                        u32 attr, int channel, long temp)
 201{
 202        struct tmp108 *tmp108 = dev_get_drvdata(dev);
 203        u32 regval, mask;
 204        int err;
 205
 206        if (type == hwmon_chip) {
 207                if (attr == hwmon_chip_update_interval) {
 208                        if (temp < 156)
 209                                mask = TMP108_CONVRATE_16HZ;
 210                        else if (temp < 625)
 211                                mask = TMP108_CONVRATE_4HZ;
 212                        else if (temp < 2500)
 213                                mask = TMP108_CONVRATE_1HZ;
 214                        else
 215                                mask = TMP108_CONVRATE_0P25HZ;
 216                        return regmap_update_bits(tmp108->regmap,
 217                                                  TMP108_REG_CONF,
 218                                                  TMP108_CONF_CONVRATE_MASK,
 219                                                  mask);
 220                }
 221                return -EOPNOTSUPP;
 222        }
 223
 224        switch (attr) {
 225        case hwmon_temp_min:
 226        case hwmon_temp_max:
 227                temp = clamp_val(temp, TMP108_TEMP_MIN_MC, TMP108_TEMP_MAX_MC);
 228                return regmap_write(tmp108->regmap,
 229                                    attr == hwmon_temp_min ?
 230                                        TMP108_REG_TLOW : TMP108_REG_THIGH,
 231                                    tmp108_mC_to_temp_reg(temp));
 232        case hwmon_temp_min_hyst:
 233        case hwmon_temp_max_hyst:
 234                temp = clamp_val(temp, TMP108_TEMP_MIN_MC, TMP108_TEMP_MAX_MC);
 235                err = regmap_read(tmp108->regmap,
 236                                  attr == hwmon_temp_min_hyst ?
 237                                        TMP108_REG_TLOW : TMP108_REG_THIGH,
 238                                  &regval);
 239                if (err < 0)
 240                        return err;
 241                if (attr == hwmon_temp_min_hyst)
 242                        temp -= tmp108_temp_reg_to_mC(regval);
 243                else
 244                        temp = tmp108_temp_reg_to_mC(regval) - temp;
 245                if (temp < 500)
 246                        mask = TMP108_HYSTERESIS_0C;
 247                else if (temp < 1500)
 248                        mask = TMP108_HYSTERESIS_1C;
 249                else if (temp < 3000)
 250                        mask = TMP108_HYSTERESIS_2C;
 251                else
 252                        mask = TMP108_HYSTERESIS_4C;
 253                return regmap_update_bits(tmp108->regmap, TMP108_REG_CONF,
 254                                          TMP108_CONF_HYSTERESIS_MASK, mask);
 255        default:
 256                return -EOPNOTSUPP;
 257        }
 258}
 259
 260static umode_t tmp108_is_visible(const void *data, enum hwmon_sensor_types type,
 261                                 u32 attr, int channel)
 262{
 263        if (type == hwmon_chip && attr == hwmon_chip_update_interval)
 264                return 0644;
 265
 266        if (type != hwmon_temp)
 267                return 0;
 268
 269        switch (attr) {
 270        case hwmon_temp_input:
 271        case hwmon_temp_min_alarm:
 272        case hwmon_temp_max_alarm:
 273                return 0444;
 274        case hwmon_temp_min:
 275        case hwmon_temp_max:
 276        case hwmon_temp_min_hyst:
 277        case hwmon_temp_max_hyst:
 278                return 0644;
 279        default:
 280                return 0;
 281        }
 282}
 283
 284static u32 tmp108_chip_config[] = {
 285        HWMON_C_REGISTER_TZ | HWMON_C_UPDATE_INTERVAL,
 286        0
 287};
 288
 289static const struct hwmon_channel_info tmp108_chip = {
 290        .type = hwmon_chip,
 291        .config = tmp108_chip_config,
 292};
 293
 294static u32 tmp108_temp_config[] = {
 295        HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MIN | HWMON_T_MIN_HYST
 296                | HWMON_T_MAX_HYST | HWMON_T_MIN_ALARM | HWMON_T_MAX_ALARM,
 297        0
 298};
 299
 300static const struct hwmon_channel_info tmp108_temp = {
 301        .type = hwmon_temp,
 302        .config = tmp108_temp_config,
 303};
 304
 305static const struct hwmon_channel_info *tmp108_info[] = {
 306        &tmp108_chip,
 307        &tmp108_temp,
 308        NULL
 309};
 310
 311static const struct hwmon_ops tmp108_hwmon_ops = {
 312        .is_visible = tmp108_is_visible,
 313        .read = tmp108_read,
 314        .write = tmp108_write,
 315};
 316
 317static const struct hwmon_chip_info tmp108_chip_info = {
 318        .ops = &tmp108_hwmon_ops,
 319        .info = tmp108_info,
 320};
 321
 322static void tmp108_restore_config(void *data)
 323{
 324        struct tmp108 *tmp108 = data;
 325
 326        regmap_write(tmp108->regmap, TMP108_REG_CONF, tmp108->orig_config);
 327}
 328
 329static bool tmp108_is_writeable_reg(struct device *dev, unsigned int reg)
 330{
 331        return reg != TMP108_REG_TEMP;
 332}
 333
 334static bool tmp108_is_volatile_reg(struct device *dev, unsigned int reg)
 335{
 336        /* Configuration register must be volatile to enable FL and FH. */
 337        return reg == TMP108_REG_TEMP || reg == TMP108_REG_CONF;
 338}
 339
 340static const struct regmap_config tmp108_regmap_config = {
 341        .reg_bits = 8,
 342        .val_bits = 16,
 343        .max_register = TMP108_REG_THIGH,
 344        .writeable_reg = tmp108_is_writeable_reg,
 345        .volatile_reg = tmp108_is_volatile_reg,
 346        .val_format_endian = REGMAP_ENDIAN_BIG,
 347        .cache_type = REGCACHE_RBTREE,
 348        .use_single_rw = true,
 349};
 350
 351static int tmp108_probe(struct i2c_client *client,
 352                        const struct i2c_device_id *id)
 353{
 354        struct device *dev = &client->dev;
 355        struct device *hwmon_dev;
 356        struct tmp108 *tmp108;
 357        int err;
 358        u32 config;
 359
 360        if (!i2c_check_functionality(client->adapter,
 361                                     I2C_FUNC_SMBUS_WORD_DATA)) {
 362                dev_err(dev,
 363                        "adapter doesn't support SMBus word transactions\n");
 364                return -ENODEV;
 365        }
 366
 367        tmp108 = devm_kzalloc(dev, sizeof(*tmp108), GFP_KERNEL);
 368        if (!tmp108)
 369                return -ENOMEM;
 370
 371        dev_set_drvdata(dev, tmp108);
 372
 373        tmp108->regmap = devm_regmap_init_i2c(client, &tmp108_regmap_config);
 374        if (IS_ERR(tmp108->regmap)) {
 375                err = PTR_ERR(tmp108->regmap);
 376                dev_err(dev, "regmap init failed: %d", err);
 377                return err;
 378        }
 379
 380        err = regmap_read(tmp108->regmap, TMP108_REG_CONF, &config);
 381        if (err < 0) {
 382                dev_err(dev, "error reading config register: %d", err);
 383                return err;
 384        }
 385        tmp108->orig_config = config;
 386
 387        /* Only continuous mode is supported. */
 388        config &= ~TMP108_CONF_MODE_MASK;
 389        config |= TMP108_MODE_CONTINUOUS;
 390
 391        /* Only comparator mode is supported. */
 392        config &= ~TMP108_CONF_TM;
 393
 394        err = regmap_write(tmp108->regmap, TMP108_REG_CONF, config);
 395        if (err < 0) {
 396                dev_err(dev, "error writing config register: %d", err);
 397                return err;
 398        }
 399
 400        tmp108->ready_time = jiffies;
 401        if ((tmp108->orig_config & TMP108_CONF_MODE_MASK) ==
 402            TMP108_MODE_SHUTDOWN)
 403                tmp108->ready_time +=
 404                        msecs_to_jiffies(TMP108_CONVERSION_TIME_MS);
 405
 406        err = devm_add_action_or_reset(dev, tmp108_restore_config, tmp108);
 407        if (err) {
 408                dev_err(dev, "add action or reset failed: %d", err);
 409                return err;
 410        }
 411
 412        hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,
 413                                                         tmp108,
 414                                                         &tmp108_chip_info,
 415                                                         NULL);
 416        return PTR_ERR_OR_ZERO(hwmon_dev);
 417}
 418
 419static int __maybe_unused tmp108_suspend(struct device *dev)
 420{
 421        struct tmp108 *tmp108 = dev_get_drvdata(dev);
 422
 423        return regmap_update_bits(tmp108->regmap, TMP108_REG_CONF,
 424                                  TMP108_CONF_MODE_MASK, TMP108_MODE_SHUTDOWN);
 425}
 426
 427static int __maybe_unused tmp108_resume(struct device *dev)
 428{
 429        struct tmp108 *tmp108 = dev_get_drvdata(dev);
 430        int err;
 431
 432        err = regmap_update_bits(tmp108->regmap, TMP108_REG_CONF,
 433                                 TMP108_CONF_MODE_MASK, TMP108_MODE_CONTINUOUS);
 434        tmp108->ready_time = jiffies +
 435                             msecs_to_jiffies(TMP108_CONVERSION_TIME_MS);
 436        return err;
 437}
 438
 439static SIMPLE_DEV_PM_OPS(tmp108_dev_pm_ops, tmp108_suspend, tmp108_resume);
 440
 441static const struct i2c_device_id tmp108_i2c_ids[] = {
 442        { "tmp108", 0 },
 443        { }
 444};
 445MODULE_DEVICE_TABLE(i2c, tmp108_i2c_ids);
 446
 447#ifdef CONFIG_OF
 448static const struct of_device_id tmp108_of_ids[] = {
 449        { .compatible = "ti,tmp108", },
 450        {}
 451};
 452MODULE_DEVICE_TABLE(of, tmp108_of_ids);
 453#endif
 454
 455static struct i2c_driver tmp108_driver = {
 456        .driver = {
 457                .name   = DRIVER_NAME,
 458                .pm     = &tmp108_dev_pm_ops,
 459                .of_match_table = of_match_ptr(tmp108_of_ids),
 460        },
 461        .probe          = tmp108_probe,
 462        .id_table       = tmp108_i2c_ids,
 463};
 464
 465module_i2c_driver(tmp108_driver);
 466
 467MODULE_AUTHOR("John Muir <john@jmuir.com>");
 468MODULE_DESCRIPTION("Texas Instruments TMP108 temperature sensor driver");
 469MODULE_LICENSE("GPL");
 470