linux/drivers/iio/temperature/max31865.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2
   3/*
   4 * Copyright (c) Linumiz 2021
   5 *
   6 * max31865.c - Maxim MAX31865 RTD-to-Digital Converter sensor driver
   7 *
   8 * Author: Navin Sankar Velliangiri <navin@linumiz.com>
   9 */
  10
  11#include <linux/ctype.h>
  12#include <linux/delay.h>
  13#include <linux/err.h>
  14#include <linux/init.h>
  15#include <linux/mod_devicetable.h>
  16#include <linux/module.h>
  17#include <linux/iio/iio.h>
  18#include <linux/iio/sysfs.h>
  19#include <linux/property.h>
  20#include <linux/spi/spi.h>
  21#include <asm/unaligned.h>
  22
  23/*
  24 * The MSB of the register value determines whether the following byte will
  25 * be written or read. If it is 0, read will follow and if it is 1, write
  26 * will follow.
  27 */
  28#define MAX31865_RD_WR_BIT                      BIT(7)
  29
  30#define MAX31865_CFG_VBIAS                      BIT(7)
  31#define MAX31865_CFG_1SHOT                      BIT(5)
  32#define MAX31865_3WIRE_RTD                      BIT(4)
  33#define MAX31865_FAULT_STATUS_CLEAR             BIT(1)
  34#define MAX31865_FILTER_50HZ                    BIT(0)
  35
  36/* The MAX31865 registers */
  37#define MAX31865_CFG_REG                        0x00
  38#define MAX31865_RTD_MSB                        0x01
  39#define MAX31865_FAULT_STATUS                   0x07
  40
  41#define MAX31865_FAULT_OVUV                     BIT(2)
  42
  43static const char max31865_show_samp_freq[] = "50 60";
  44
  45static const struct iio_chan_spec max31865_channels[] = {
  46        {       /* RTD Temperature */
  47                .type = IIO_TEMP,
  48                .info_mask_separate =
  49                        BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE)
  50        },
  51};
  52
  53struct max31865_data {
  54        struct spi_device *spi;
  55        struct mutex lock;
  56        bool filter_50hz;
  57        bool three_wire;
  58        u8 buf[2] ____cacheline_aligned;
  59};
  60
  61static int max31865_read(struct max31865_data *data, u8 reg,
  62                         unsigned int read_size)
  63{
  64        return spi_write_then_read(data->spi, &reg, 1, data->buf, read_size);
  65}
  66
  67static int max31865_write(struct max31865_data *data, size_t len)
  68{
  69        return spi_write(data->spi, data->buf, len);
  70}
  71
  72static int enable_bias(struct max31865_data *data)
  73{
  74        u8 cfg;
  75        int ret;
  76
  77        ret = max31865_read(data, MAX31865_CFG_REG, 1);
  78        if (ret)
  79                return ret;
  80
  81        cfg = data->buf[0];
  82
  83        data->buf[0] = MAX31865_CFG_REG | MAX31865_RD_WR_BIT;
  84        data->buf[1] = cfg | MAX31865_CFG_VBIAS;
  85
  86        return max31865_write(data, 2);
  87}
  88
  89static int disable_bias(struct max31865_data *data)
  90{
  91        u8 cfg;
  92        int ret;
  93
  94        ret = max31865_read(data, MAX31865_CFG_REG, 1);
  95        if (ret)
  96                return ret;
  97
  98        cfg = data->buf[0];
  99        cfg &= ~MAX31865_CFG_VBIAS;
 100
 101        data->buf[0] = MAX31865_CFG_REG | MAX31865_RD_WR_BIT;
 102        data->buf[1] = cfg;
 103
 104        return max31865_write(data, 2);
 105}
 106
 107static int max31865_rtd_read(struct max31865_data *data, int *val)
 108{
 109        u8 reg;
 110        int ret;
 111
 112        /* Enable BIAS to start the conversion */
 113        ret = enable_bias(data);
 114        if (ret)
 115                return ret;
 116
 117        /* wait 10.5ms before initiating the conversion */
 118        msleep(11);
 119
 120        ret = max31865_read(data, MAX31865_CFG_REG, 1);
 121        if (ret)
 122                return ret;
 123
 124        reg = data->buf[0];
 125        reg |= MAX31865_CFG_1SHOT | MAX31865_FAULT_STATUS_CLEAR;
 126        data->buf[0] = MAX31865_CFG_REG | MAX31865_RD_WR_BIT;
 127        data->buf[1] = reg;
 128
 129        ret = max31865_write(data, 2);
 130        if (ret)
 131                return ret;
 132
 133        if (data->filter_50hz) {
 134                /* 50Hz filter mode requires 62.5ms to complete */
 135                msleep(63);
 136        } else {
 137                /* 60Hz filter mode requires 52ms to complete */
 138                msleep(52);
 139        }
 140
 141        ret = max31865_read(data, MAX31865_RTD_MSB, 2);
 142        if (ret)
 143                return ret;
 144
 145        *val = get_unaligned_be16(&data->buf) >> 1;
 146
 147        return disable_bias(data);
 148}
 149
 150static int max31865_read_raw(struct iio_dev *indio_dev,
 151                             struct iio_chan_spec const *chan,
 152                             int *val, int *val2, long mask)
 153{
 154        struct max31865_data *data = iio_priv(indio_dev);
 155        int ret;
 156
 157        switch (mask) {
 158        case IIO_CHAN_INFO_RAW:
 159                mutex_lock(&data->lock);
 160                ret = max31865_rtd_read(data, val);
 161                mutex_unlock(&data->lock);
 162                if (ret)
 163                        return ret;
 164                return IIO_VAL_INT;
 165        case IIO_CHAN_INFO_SCALE:
 166                /* Temp. Data resolution is 0.03125 degree centigrade */
 167                *val = 31;
 168                *val2 = 250000; /* 1000 * 0.03125 */
 169                return IIO_VAL_INT_PLUS_MICRO;
 170        default:
 171                return -EINVAL;
 172        }
 173}
 174
 175static int max31865_init(struct max31865_data *data)
 176{
 177        u8 cfg;
 178        int ret;
 179
 180        ret = max31865_read(data, MAX31865_CFG_REG, 1);
 181        if (ret)
 182                return ret;
 183
 184        cfg = data->buf[0];
 185
 186        if (data->three_wire)
 187                /* 3-wire RTD connection */
 188                cfg |= MAX31865_3WIRE_RTD;
 189
 190        if (data->filter_50hz)
 191                /* 50Hz noise rejection filter */
 192                cfg |= MAX31865_FILTER_50HZ;
 193
 194        data->buf[0] = MAX31865_CFG_REG | MAX31865_RD_WR_BIT;
 195        data->buf[1] = cfg;
 196
 197        return max31865_write(data, 2);
 198}
 199
 200static ssize_t show_fault(struct device *dev, u8 faultbit, char *buf)
 201{
 202        int ret;
 203        bool fault;
 204        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 205        struct max31865_data *data = iio_priv(indio_dev);
 206
 207        ret = max31865_read(data, MAX31865_FAULT_STATUS, 1);
 208        if (ret)
 209                return ret;
 210
 211        fault = data->buf[0] & faultbit;
 212
 213        return sysfs_emit(buf, "%d\n", fault);
 214}
 215
 216static ssize_t show_fault_ovuv(struct device *dev,
 217                              struct device_attribute *attr,
 218                              char *buf)
 219{
 220        return show_fault(dev, MAX31865_FAULT_OVUV, buf);
 221}
 222
 223static ssize_t show_filter(struct device *dev,
 224                           struct device_attribute *attr,
 225                           char *buf)
 226{
 227        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 228        struct max31865_data *data = iio_priv(indio_dev);
 229
 230        return sysfs_emit(buf, "%d\n", data->filter_50hz ? 50 : 60);
 231}
 232
 233static ssize_t set_filter(struct device *dev,
 234                          struct device_attribute *attr,
 235                          const char *buf,
 236                          size_t len)
 237{
 238        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 239        struct max31865_data *data = iio_priv(indio_dev);
 240        unsigned int freq;
 241        int ret;
 242
 243        ret = kstrtouint(buf, 10, &freq);
 244        if (ret)
 245                return ret;
 246
 247        switch (freq) {
 248        case 50:
 249                data->filter_50hz = true;
 250                break;
 251        case 60:
 252                data->filter_50hz = false;
 253                break;
 254        default:
 255                return -EINVAL;
 256        }
 257
 258        mutex_lock(&data->lock);
 259        ret = max31865_init(data);
 260        mutex_unlock(&data->lock);
 261        if (ret)
 262                return ret;
 263
 264        return len;
 265}
 266
 267static IIO_CONST_ATTR_SAMP_FREQ_AVAIL(max31865_show_samp_freq);
 268static IIO_DEVICE_ATTR(fault_ovuv, 0444, show_fault_ovuv, NULL, 0);
 269static IIO_DEVICE_ATTR(in_filter_notch_center_frequency, 0644,
 270                    show_filter, set_filter, 0);
 271
 272static struct attribute *max31865_attributes[] = {
 273        &iio_dev_attr_fault_ovuv.dev_attr.attr,
 274        &iio_const_attr_sampling_frequency_available.dev_attr.attr,
 275        &iio_dev_attr_in_filter_notch_center_frequency.dev_attr.attr,
 276        NULL,
 277};
 278
 279static const struct attribute_group max31865_group = {
 280        .attrs = max31865_attributes,
 281};
 282
 283static const struct iio_info max31865_info = {
 284        .read_raw = max31865_read_raw,
 285        .attrs = &max31865_group,
 286};
 287
 288static int max31865_probe(struct spi_device *spi)
 289{
 290        const struct spi_device_id *id = spi_get_device_id(spi);
 291        struct iio_dev *indio_dev;
 292        struct max31865_data *data;
 293        int ret;
 294
 295        indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*data));
 296        if (!indio_dev)
 297                return -ENOMEM;
 298
 299        data = iio_priv(indio_dev);
 300        data->spi = spi;
 301        data->filter_50hz = false;
 302        mutex_init(&data->lock);
 303
 304        indio_dev->info = &max31865_info;
 305        indio_dev->name = id->name;
 306        indio_dev->modes = INDIO_DIRECT_MODE;
 307        indio_dev->channels = max31865_channels;
 308        indio_dev->num_channels = ARRAY_SIZE(max31865_channels);
 309
 310        if (device_property_read_bool(&spi->dev, "maxim,3-wire")) {
 311                /* select 3 wire */
 312                data->three_wire = 1;
 313        } else {
 314                /* select 2 or 4 wire */
 315                data->three_wire = 0;
 316        }
 317
 318        ret = max31865_init(data);
 319        if (ret) {
 320                dev_err(&spi->dev, "error: Failed to configure max31865\n");
 321                return ret;
 322        }
 323
 324        return devm_iio_device_register(&spi->dev, indio_dev);
 325}
 326
 327static const struct spi_device_id max31865_id[] = {
 328        { "max31865", 0 },
 329        { }
 330};
 331MODULE_DEVICE_TABLE(spi, max31865_id);
 332
 333static const struct of_device_id max31865_of_match[] = {
 334        { .compatible = "maxim,max31865" },
 335        { }
 336};
 337MODULE_DEVICE_TABLE(of, max31865_of_match);
 338
 339static struct spi_driver max31865_driver = {
 340        .driver = {
 341                .name   = "max31865",
 342                .of_match_table = max31865_of_match,
 343        },
 344        .probe = max31865_probe,
 345        .id_table = max31865_id,
 346};
 347module_spi_driver(max31865_driver);
 348
 349MODULE_AUTHOR("Navin Sankar Velliangiri <navin@linumiz.com>");
 350MODULE_DESCRIPTION("Maxim MAX31865 RTD-to-Digital Converter sensor driver");
 351MODULE_LICENSE("GPL v2");
 352