diff options
Diffstat (limited to 'drivers/iio/temperature')
-rw-r--r-- | drivers/iio/temperature/ltc2983.c | 6 | ||||
-rw-r--r-- | drivers/iio/temperature/max31856.c | 134 | ||||
-rw-r--r-- | drivers/iio/temperature/maxim_thermocouple.c | 44 |
3 files changed, 178 insertions, 6 deletions
diff --git a/drivers/iio/temperature/ltc2983.c b/drivers/iio/temperature/ltc2983.c index ddf47023364b..d39c0d6b77f1 100644 --- a/drivers/iio/temperature/ltc2983.c +++ b/drivers/iio/temperature/ltc2983.c @@ -444,8 +444,10 @@ static struct ltc2983_custom_sensor *__ltc2983_custom_sensor_new( else temp = __convert_to_raw(temp, resolution); } else { - of_property_read_u32_index(np, propname, index, - (u32 *)&temp); + u32 t32; + + of_property_read_u32_index(np, propname, index, &t32); + temp = t32; } for (j = 0; j < n_size; j++) diff --git a/drivers/iio/temperature/max31856.c b/drivers/iio/temperature/max31856.c index 73ed550e3fc9..b4cb21ab2e85 100644 --- a/drivers/iio/temperature/max31856.c +++ b/drivers/iio/temperature/max31856.c @@ -6,12 +6,14 @@ * Copyright (C) 2018-2019 Rockwell Collins */ +#include <linux/ctype.h> #include <linux/module.h> #include <linux/init.h> #include <linux/err.h> #include <linux/spi/spi.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> +#include <linux/util_macros.h> #include <dt-bindings/iio/temperature/thermocouple.h> /* * The MSB of the register value determines whether the following byte will @@ -23,6 +25,9 @@ #define MAX31856_CR0_1SHOT BIT(6) #define MAX31856_CR0_OCFAULT BIT(4) #define MAX31856_CR0_OCFAULT_MASK GENMASK(5, 4) +#define MAX31856_CR0_FILTER_50HZ BIT(0) +#define MAX31856_AVERAGING_MASK GENMASK(6, 4) +#define MAX31856_AVERAGING_SHIFT 4 #define MAX31856_TC_TYPE_MASK GENMASK(3, 0) #define MAX31856_FAULT_OVUV BIT(1) #define MAX31856_FAULT_OPEN BIT(0) @@ -49,7 +54,10 @@ static const struct iio_chan_spec max31856_channels[] = { { /* Thermocouple Temperature */ .type = IIO_TEMP, .info_mask_separate = - BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_THERMOCOUPLE_TYPE), + .info_mask_shared_by_type = + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) }, { /* Cold Junction Temperature */ .type = IIO_TEMP, @@ -57,12 +65,20 @@ static const struct iio_chan_spec max31856_channels[] = { .modified = 1, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_type = + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) }, }; struct max31856_data { struct spi_device *spi; u32 thermocouple_type; + bool filter_50hz; + int averaging; +}; + +static const char max31856_tc_types[] = { + 'B', 'E', 'J', 'K', 'N', 'R', 'S', 'T' }; static int max31856_read(struct max31856_data *data, u8 reg, @@ -107,6 +123,10 @@ static int max31856_init(struct max31856_data *data) reg_cr1_val &= ~MAX31856_TC_TYPE_MASK; reg_cr1_val |= data->thermocouple_type; + + reg_cr1_val &= ~MAX31856_AVERAGING_MASK; + reg_cr1_val |= data->averaging << MAX31856_AVERAGING_SHIFT; + ret = max31856_write(data, MAX31856_CR1_REG, reg_cr1_val); if (ret) return ret; @@ -123,6 +143,11 @@ static int max31856_init(struct max31856_data *data) reg_cr0_val &= ~MAX31856_CR0_1SHOT; reg_cr0_val |= MAX31856_CR0_AUTOCONVERT; + if (data->filter_50hz) + reg_cr0_val |= MAX31856_CR0_FILTER_50HZ; + else + reg_cr0_val &= ~MAX31856_CR0_FILTER_50HZ; + return max31856_write(data, MAX31856_CR0_REG, reg_cr0_val); } @@ -210,6 +235,12 @@ static int max31856_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT_PLUS_MICRO; } break; + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + *val = 1 << data->averaging; + return IIO_VAL_INT; + case IIO_CHAN_INFO_THERMOCOUPLE_TYPE: + *val = max31856_tc_types[data->thermocouple_type]; + return IIO_VAL_CHAR; default: ret = -EINVAL; break; @@ -218,6 +249,62 @@ static int max31856_read_raw(struct iio_dev *indio_dev, return ret; } +static int max31856_write_raw_get_fmt(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_THERMOCOUPLE_TYPE: + return IIO_VAL_CHAR; + default: + return IIO_VAL_INT; + } +} + +static int max31856_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct max31856_data *data = iio_priv(indio_dev); + int msb; + + switch (mask) { + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + if (val > 16 || val < 1) + return -EINVAL; + msb = fls(val) - 1; + /* Round up to next 2pow if needed */ + if (BIT(msb) < val) + msb++; + + data->averaging = msb; + max31856_init(data); + break; + case IIO_CHAN_INFO_THERMOCOUPLE_TYPE: + { + int tc_type = -1; + int i; + + for (i = 0; i < ARRAY_SIZE(max31856_tc_types); i++) { + if (max31856_tc_types[i] == toupper(val)) { + tc_type = i; + break; + } + } + if (tc_type < 0) + return -EINVAL; + + data->thermocouple_type = tc_type; + max31856_init(data); + break; + } + default: + return -EINVAL; + } + + return 0; +} + static ssize_t show_fault(struct device *dev, u8 faultbit, char *buf) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); @@ -249,12 +336,54 @@ static ssize_t show_fault_oc(struct device *dev, return show_fault(dev, MAX31856_FAULT_OPEN, buf); } +static ssize_t show_filter(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct max31856_data *data = iio_priv(indio_dev); + + return sprintf(buf, "%d\n", data->filter_50hz ? 50 : 60); +} + +static ssize_t set_filter(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct max31856_data *data = iio_priv(indio_dev); + unsigned int freq; + int ret; + + ret = kstrtouint(buf, 10, &freq); + if (ret) + return ret; + + switch (freq) { + case 50: + data->filter_50hz = true; + break; + case 60: + data->filter_50hz = false; + break; + default: + return -EINVAL; + } + + max31856_init(data); + return len; +} + static IIO_DEVICE_ATTR(fault_ovuv, 0444, show_fault_ovuv, NULL, 0); static IIO_DEVICE_ATTR(fault_oc, 0444, show_fault_oc, NULL, 0); +static IIO_DEVICE_ATTR(in_temp_filter_notch_center_frequency, 0644, + show_filter, set_filter, 0); static struct attribute *max31856_attributes[] = { &iio_dev_attr_fault_ovuv.dev_attr.attr, &iio_dev_attr_fault_oc.dev_attr.attr, + &iio_dev_attr_in_temp_filter_notch_center_frequency.dev_attr.attr, NULL, }; @@ -264,6 +393,8 @@ static const struct attribute_group max31856_group = { static const struct iio_info max31856_info = { .read_raw = max31856_read_raw, + .write_raw = max31856_write_raw, + .write_raw_get_fmt = max31856_write_raw_get_fmt, .attrs = &max31856_group, }; @@ -280,6 +411,7 @@ static int max31856_probe(struct spi_device *spi) data = iio_priv(indio_dev); data->spi = spi; + data->filter_50hz = false; spi_set_drvdata(spi, indio_dev); diff --git a/drivers/iio/temperature/maxim_thermocouple.c b/drivers/iio/temperature/maxim_thermocouple.c index d1360605209c..8d21116c7a22 100644 --- a/drivers/iio/temperature/maxim_thermocouple.c +++ b/drivers/iio/temperature/maxim_thermocouple.c @@ -14,6 +14,7 @@ #include <linux/of_device.h> #include <linux/spi/spi.h> #include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> #include <linux/iio/trigger.h> #include <linux/iio/buffer.h> #include <linux/iio/triggered_buffer.h> @@ -24,13 +25,25 @@ enum { MAX6675, MAX31855, + MAX31855K, + MAX31855J, + MAX31855N, + MAX31855S, + MAX31855T, + MAX31855E, + MAX31855R, +}; + +static const char maxim_tc_types[] = { + 'K', '?', 'K', 'J', 'N', 'S', 'T', 'E', 'R' }; static const struct iio_chan_spec max6675_channels[] = { { /* thermocouple temperature */ .type = IIO_TEMP, .info_mask_separate = - BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_THERMOCOUPLE_TYPE), .scan_index = 0, .scan_type = { .sign = 's', @@ -48,7 +61,8 @@ static const struct iio_chan_spec max31855_channels[] = { .type = IIO_TEMP, .address = 2, .info_mask_separate = - BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_THERMOCOUPLE_TYPE), .scan_index = 0, .scan_type = { .sign = 's', @@ -110,6 +124,7 @@ struct maxim_thermocouple_data { const struct maxim_thermocouple_chip *chip; u8 buffer[16] ____cacheline_aligned; + char tc_type; }; static int maxim_thermocouple_read(struct maxim_thermocouple_data *data, @@ -196,6 +211,10 @@ static int maxim_thermocouple_read_raw(struct iio_dev *indio_dev, ret = IIO_VAL_INT; } break; + case IIO_CHAN_INFO_THERMOCOUPLE_TYPE: + *val = data->tc_type; + ret = IIO_VAL_CHAR; + break; } return ret; @@ -210,8 +229,9 @@ static int maxim_thermocouple_probe(struct spi_device *spi) const struct spi_device_id *id = spi_get_device_id(spi); struct iio_dev *indio_dev; struct maxim_thermocouple_data *data; + const int chip_type = (id->driver_data == MAX6675) ? MAX6675 : MAX31855; const struct maxim_thermocouple_chip *chip = - &maxim_thermocouple_chips[id->driver_data]; + &maxim_thermocouple_chips[chip_type]; int ret; indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*data)); @@ -229,6 +249,7 @@ static int maxim_thermocouple_probe(struct spi_device *spi) data = iio_priv(indio_dev); data->spi = spi; data->chip = chip; + data->tc_type = maxim_tc_types[id->driver_data]; ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, NULL, @@ -236,12 +257,22 @@ static int maxim_thermocouple_probe(struct spi_device *spi) if (ret) return ret; + if (id->driver_data == MAX31855) + dev_warn(&spi->dev, "generic max31855 ID is deprecated\nplease use more specific part type"); + return devm_iio_device_register(&spi->dev, indio_dev); } static const struct spi_device_id maxim_thermocouple_id[] = { {"max6675", MAX6675}, {"max31855", MAX31855}, + {"max31855k", MAX31855K}, + {"max31855j", MAX31855J}, + {"max31855n", MAX31855N}, + {"max31855s", MAX31855S}, + {"max31855t", MAX31855T}, + {"max31855e", MAX31855E}, + {"max31855r", MAX31855R}, {}, }; MODULE_DEVICE_TABLE(spi, maxim_thermocouple_id); @@ -249,6 +280,13 @@ MODULE_DEVICE_TABLE(spi, maxim_thermocouple_id); static const struct of_device_id maxim_thermocouple_of_match[] = { { .compatible = "maxim,max6675" }, { .compatible = "maxim,max31855" }, + { .compatible = "maxim,max31855k" }, + { .compatible = "maxim,max31855j" }, + { .compatible = "maxim,max31855n" }, + { .compatible = "maxim,max31855s" }, + { .compatible = "maxim,max31855t" }, + { .compatible = "maxim,max31855e" }, + { .compatible = "maxim,max31855r" }, { }, }; MODULE_DEVICE_TABLE(of, maxim_thermocouple_of_match); |