linux/drivers/iio/temperature/maxim_thermocouple.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * maxim_thermocouple.c  - Support for Maxim thermocouple chips
   4 *
   5 * Copyright (C) 2016-2018 Matt Ranostay
   6 * Author: <matt.ranostay@konsulko.com>
   7 */
   8
   9#include <linux/module.h>
  10#include <linux/init.h>
  11#include <linux/mutex.h>
  12#include <linux/err.h>
  13#include <linux/of.h>
  14#include <linux/of_device.h>
  15#include <linux/spi/spi.h>
  16#include <linux/iio/iio.h>
  17#include <linux/iio/sysfs.h>
  18#include <linux/iio/trigger.h>
  19#include <linux/iio/buffer.h>
  20#include <linux/iio/triggered_buffer.h>
  21#include <linux/iio/trigger_consumer.h>
  22
  23#define MAXIM_THERMOCOUPLE_DRV_NAME     "maxim_thermocouple"
  24
  25enum {
  26        MAX6675,
  27        MAX31855,
  28        MAX31855K,
  29        MAX31855J,
  30        MAX31855N,
  31        MAX31855S,
  32        MAX31855T,
  33        MAX31855E,
  34        MAX31855R,
  35};
  36
  37static const char maxim_tc_types[] = {
  38        'K', '?', 'K', 'J', 'N', 'S', 'T', 'E', 'R'
  39};
  40
  41static const struct iio_chan_spec max6675_channels[] = {
  42        {       /* thermocouple temperature */
  43                .type = IIO_TEMP,
  44                .info_mask_separate =
  45                        BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE) |
  46                        BIT(IIO_CHAN_INFO_THERMOCOUPLE_TYPE),
  47                .scan_index = 0,
  48                .scan_type = {
  49                        .sign = 's',
  50                        .realbits = 13,
  51                        .storagebits = 16,
  52                        .shift = 3,
  53                        .endianness = IIO_BE,
  54                },
  55        },
  56        IIO_CHAN_SOFT_TIMESTAMP(1),
  57};
  58
  59static const struct iio_chan_spec max31855_channels[] = {
  60        {       /* thermocouple temperature */
  61                .type = IIO_TEMP,
  62                .address = 2,
  63                .info_mask_separate =
  64                        BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE) |
  65                        BIT(IIO_CHAN_INFO_THERMOCOUPLE_TYPE),
  66                .scan_index = 0,
  67                .scan_type = {
  68                        .sign = 's',
  69                        .realbits = 14,
  70                        .storagebits = 16,
  71                        .shift = 2,
  72                        .endianness = IIO_BE,
  73                },
  74        },
  75        {       /* cold junction temperature */
  76                .type = IIO_TEMP,
  77                .address = 0,
  78                .channel2 = IIO_MOD_TEMP_AMBIENT,
  79                .modified = 1,
  80                .info_mask_separate =
  81                        BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
  82                .scan_index = 1,
  83                .scan_type = {
  84                        .sign = 's',
  85                        .realbits = 12,
  86                        .storagebits = 16,
  87                        .shift = 4,
  88                        .endianness = IIO_BE,
  89                },
  90        },
  91        IIO_CHAN_SOFT_TIMESTAMP(2),
  92};
  93
  94static const unsigned long max31855_scan_masks[] = {0x3, 0};
  95
  96struct maxim_thermocouple_chip {
  97        const struct iio_chan_spec *channels;
  98        const unsigned long *scan_masks;
  99        u8 num_channels;
 100        u8 read_size;
 101
 102        /* bit-check for valid input */
 103        u32 status_bit;
 104};
 105
 106static const struct maxim_thermocouple_chip maxim_thermocouple_chips[] = {
 107        [MAX6675] = {
 108                        .channels = max6675_channels,
 109                        .num_channels = ARRAY_SIZE(max6675_channels),
 110                        .read_size = 2,
 111                        .status_bit = BIT(2),
 112                },
 113        [MAX31855] = {
 114                        .channels = max31855_channels,
 115                        .num_channels = ARRAY_SIZE(max31855_channels),
 116                        .read_size = 4,
 117                        .scan_masks = max31855_scan_masks,
 118                        .status_bit = BIT(16),
 119                },
 120};
 121
 122struct maxim_thermocouple_data {
 123        struct spi_device *spi;
 124        const struct maxim_thermocouple_chip *chip;
 125
 126        u8 buffer[16] ____cacheline_aligned;
 127        char tc_type;
 128};
 129
 130static int maxim_thermocouple_read(struct maxim_thermocouple_data *data,
 131                                   struct iio_chan_spec const *chan, int *val)
 132{
 133        unsigned int storage_bytes = data->chip->read_size;
 134        unsigned int shift = chan->scan_type.shift + (chan->address * 8);
 135        __be16 buf16;
 136        __be32 buf32;
 137        int ret;
 138
 139        switch (storage_bytes) {
 140        case 2:
 141                ret = spi_read(data->spi, (void *)&buf16, storage_bytes);
 142                *val = be16_to_cpu(buf16);
 143                break;
 144        case 4:
 145                ret = spi_read(data->spi, (void *)&buf32, storage_bytes);
 146                *val = be32_to_cpu(buf32);
 147                break;
 148        default:
 149                ret = -EINVAL;
 150        }
 151
 152        if (ret)
 153                return ret;
 154
 155        /* check to be sure this is a valid reading */
 156        if (*val & data->chip->status_bit)
 157                return -EINVAL;
 158
 159        *val = sign_extend32(*val >> shift, chan->scan_type.realbits - 1);
 160
 161        return 0;
 162}
 163
 164static irqreturn_t maxim_thermocouple_trigger_handler(int irq, void *private)
 165{
 166        struct iio_poll_func *pf = private;
 167        struct iio_dev *indio_dev = pf->indio_dev;
 168        struct maxim_thermocouple_data *data = iio_priv(indio_dev);
 169        int ret;
 170
 171        ret = spi_read(data->spi, data->buffer, data->chip->read_size);
 172        if (!ret) {
 173                iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
 174                                                   iio_get_time_ns(indio_dev));
 175        }
 176
 177        iio_trigger_notify_done(indio_dev->trig);
 178
 179        return IRQ_HANDLED;
 180}
 181
 182static int maxim_thermocouple_read_raw(struct iio_dev *indio_dev,
 183                                       struct iio_chan_spec const *chan,
 184                                       int *val, int *val2, long mask)
 185{
 186        struct maxim_thermocouple_data *data = iio_priv(indio_dev);
 187        int ret = -EINVAL;
 188
 189        switch (mask) {
 190        case IIO_CHAN_INFO_RAW:
 191                ret = iio_device_claim_direct_mode(indio_dev);
 192                if (ret)
 193                        return ret;
 194
 195                ret = maxim_thermocouple_read(data, chan, val);
 196                iio_device_release_direct_mode(indio_dev);
 197
 198                if (!ret)
 199                        return IIO_VAL_INT;
 200
 201                break;
 202        case IIO_CHAN_INFO_SCALE:
 203                switch (chan->channel2) {
 204                case IIO_MOD_TEMP_AMBIENT:
 205                        *val = 62;
 206                        *val2 = 500000; /* 1000 * 0.0625 */
 207                        ret = IIO_VAL_INT_PLUS_MICRO;
 208                        break;
 209                default:
 210                        *val = 250; /* 1000 * 0.25 */
 211                        ret = IIO_VAL_INT;
 212                }
 213                break;
 214        case IIO_CHAN_INFO_THERMOCOUPLE_TYPE:
 215                *val = data->tc_type;
 216                ret = IIO_VAL_CHAR;
 217                break;
 218        }
 219
 220        return ret;
 221}
 222
 223static const struct iio_info maxim_thermocouple_info = {
 224        .read_raw = maxim_thermocouple_read_raw,
 225};
 226
 227static int maxim_thermocouple_probe(struct spi_device *spi)
 228{
 229        const struct spi_device_id *id = spi_get_device_id(spi);
 230        struct iio_dev *indio_dev;
 231        struct maxim_thermocouple_data *data;
 232        const int chip_type = (id->driver_data == MAX6675) ? MAX6675 : MAX31855;
 233        const struct maxim_thermocouple_chip *chip =
 234                &maxim_thermocouple_chips[chip_type];
 235        int ret;
 236
 237        indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*data));
 238        if (!indio_dev)
 239                return -ENOMEM;
 240
 241        indio_dev->info = &maxim_thermocouple_info;
 242        indio_dev->name = MAXIM_THERMOCOUPLE_DRV_NAME;
 243        indio_dev->channels = chip->channels;
 244        indio_dev->available_scan_masks = chip->scan_masks;
 245        indio_dev->num_channels = chip->num_channels;
 246        indio_dev->modes = INDIO_DIRECT_MODE;
 247
 248        data = iio_priv(indio_dev);
 249        data->spi = spi;
 250        data->chip = chip;
 251        data->tc_type = maxim_tc_types[id->driver_data];
 252
 253        ret = devm_iio_triggered_buffer_setup(&spi->dev,
 254                                indio_dev, NULL,
 255                                maxim_thermocouple_trigger_handler, NULL);
 256        if (ret)
 257                return ret;
 258
 259        if (id->driver_data == MAX31855)
 260                dev_warn(&spi->dev, "generic max31855 ID is deprecated\nplease use more specific part type");
 261
 262        return devm_iio_device_register(&spi->dev, indio_dev);
 263}
 264
 265static const struct spi_device_id maxim_thermocouple_id[] = {
 266        {"max6675", MAX6675},
 267        {"max31855", MAX31855},
 268        {"max31855k", MAX31855K},
 269        {"max31855j", MAX31855J},
 270        {"max31855n", MAX31855N},
 271        {"max31855s", MAX31855S},
 272        {"max31855t", MAX31855T},
 273        {"max31855e", MAX31855E},
 274        {"max31855r", MAX31855R},
 275        {},
 276};
 277MODULE_DEVICE_TABLE(spi, maxim_thermocouple_id);
 278
 279static const struct of_device_id maxim_thermocouple_of_match[] = {
 280        { .compatible = "maxim,max6675" },
 281        { .compatible = "maxim,max31855" },
 282        { .compatible = "maxim,max31855k" },
 283        { .compatible = "maxim,max31855j" },
 284        { .compatible = "maxim,max31855n" },
 285        { .compatible = "maxim,max31855s" },
 286        { .compatible = "maxim,max31855t" },
 287        { .compatible = "maxim,max31855e" },
 288        { .compatible = "maxim,max31855r" },
 289        { },
 290};
 291MODULE_DEVICE_TABLE(of, maxim_thermocouple_of_match);
 292
 293static struct spi_driver maxim_thermocouple_driver = {
 294        .driver = {
 295                .name   = MAXIM_THERMOCOUPLE_DRV_NAME,
 296                .of_match_table = maxim_thermocouple_of_match,
 297        },
 298        .probe          = maxim_thermocouple_probe,
 299        .id_table       = maxim_thermocouple_id,
 300};
 301module_spi_driver(maxim_thermocouple_driver);
 302
 303MODULE_AUTHOR("Matt Ranostay <matt.ranostay@konsulko.com>");
 304MODULE_DESCRIPTION("Maxim thermocouple sensors");
 305MODULE_LICENSE("GPL");
 306