diff --git a/Documentation/devicetree/bindings/iio/adc/lltc,ltc2497.yaml b/Documentation/devicetree/bindings/iio/adc/lltc,ltc2497.yaml index 5cc6a968407784..5f68214f2949d9 100644 --- a/Documentation/devicetree/bindings/iio/adc/lltc,ltc2497.yaml +++ b/Documentation/devicetree/bindings/iio/adc/lltc,ltc2497.yaml @@ -4,7 +4,7 @@ $id: http://devicetree.org/schemas/iio/adc/lltc,ltc2497.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Linear Technology / Analog Devices LTC2497 and LTC2309 ADC +title: Linear Technology / Analog Devices LTC2497, LTC2499 and LTC2309 ADC maintainers: - Michael Hennerich @@ -22,6 +22,10 @@ description: | 16bit ADC supporting up to 16 single ended or 8 differential inputs. I2C interface. + The LTC2499 additionally provides an internal temperature sensor. Its + scale and offset are derived from the reference voltage, so an accurate + vref-supply is required for the temperature channel to report correctly. + https://www.analog.com/media/en/technical-documentation/data-sheets/2497fb.pdf https://www.analog.com/media/en/technical-documentation/data-sheets/2499fe.pdf diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile index 9ef5468849ebd1..e7570050a57098 100644 --- a/arch/arm/boot/dts/overlays/Makefile +++ b/arch/arm/boot/dts/overlays/Makefile @@ -320,6 +320,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ rpi-hmc425a.dtbo \ rpi-lm75.dtbo \ rpi-ltc2497.dtbo \ + rpi-ltc2499.dtbo \ rpi-ltc2664.dtbo \ rpi-ltc2672.dtbo \ rpi-ltc2688.dtbo \ diff --git a/arch/arm/boot/dts/overlays/rpi-ltc2499-overlay.dts b/arch/arm/boot/dts/overlays/rpi-ltc2499-overlay.dts new file mode 100644 index 00000000000000..161ddd92933e0e --- /dev/null +++ b/arch/arm/boot/dts/overlays/rpi-ltc2499-overlay.dts @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * rpi-ltc2499-overlay.dts - Raspberry Pi overlay for the LTC2499 ADC + * + * Instantiates an LTC2499 on the Raspberry Pi I2C1 bus (40-pin header) and + * wires its ADC reference to the board's existing 3.3 V fixed regulator via + * + * vref-supply = <&vdd_3v3_reg>; + * + * so that regulator_get_voltage() returns 3300000 and the LTC2499 temperature + * channel (in_temp_scale / in_temp_offset) reports correctly without relying on + * any driver-side fallback. + * + * Note: this overlay targets a Raspberry Pi wired with a 3.3 V VREF. Other + * boards must supply their own Device Tree node describing the actual VREF + * regulator (2.5 V, 3.3 V, 4.096 V, etc.); the 3.3 V value here is not a + * universal hardware assumption. + */ +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2835"; + + fragment@0 { + target = <&i2c1>; + __overlay__ { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + ltc2499: ltc2499@76 { + compatible = "lltc,ltc2499"; + reg = <0x76>; + /* Board's own 3.3 V rail - see arch DT __symbols__ */ + vref-supply = <&vdd_3v3_reg>; + #io-channel-cells = <1>; + status = "okay"; + }; + }; + }; + + __overrides__ { + addr = <<c2499>,"reg:0"; + }; +}; diff --git a/drivers/iio/adc/ltc2497-core.c b/drivers/iio/adc/ltc2497-core.c index 996f6cbbed3ce1..8f70a54382e1f8 100644 --- a/drivers/iio/adc/ltc2497-core.c +++ b/drivers/iio/adc/ltc2497-core.c @@ -7,11 +7,14 @@ */ #include +#include #include #include +#include #include #include #include +#include #include "ltc2497.h" @@ -19,24 +22,57 @@ #define LTC2497_DIFF 0 #define LTC2497_SIGN BIT(3) -static int ltc2497core_wait_conv(struct ltc2497core_driverdata *ddata) +/* + * Output-rate modes, indexed by ltc2497core_driverdata.sped_2x + * (0 = 1x, the power-on default; 1 = 2x, LTC2499 only). The advertised + * sampling_frequency and the conversion-time budget are two views of the same + * mode, so they are kept in lock-step here and can never drift apart. Only the + * two simultaneous 50/60Hz rejection rates are reachable today; adding FA/FB + * rejection selection later turns this into a [rejection][speed] lookup without + * changing any caller. + */ +static const int ltc2497core_samp_freq_avail[] = { + 6, 800000, /* 1x: ~6.8 Hz (1 / t_CONV_1 typ 146.9ms) */ + 13, 600000, /* 2x: ~13.6 Hz (1 / t_CONV_2 typ 73.6ms) */ +}; + +static const unsigned int ltc2497core_conv_time_ms_tbl[] = { + LTC2497_CONV_TIME_1X_MS, /* 1x */ + LTC2499_CONV_TIME_2X_MS, /* 2x */ +}; + +static unsigned int ltc2497core_conv_time_ms(struct ltc2497core_driverdata *ddata, + u8 address) +{ + /* + * SPD is ignored by the part during a temperature measurement: it + * always converts at 1x, so budget the 1x time regardless of the + * selected voltage-channel mode. + */ + if (address == LTC2497_TEMP_ADDR) + return ltc2497core_conv_time_ms_tbl[0]; + + return ltc2497core_conv_time_ms_tbl[ddata->sped_2x]; +} + +static int ltc2497core_wait_conv(struct ltc2497core_driverdata *ddata, + unsigned int conv_time_ms) { s64 time_elapsed; time_elapsed = ktime_ms_delta(ktime_get(), ddata->time_prev); - if (time_elapsed < LTC2497_CONVERSION_TIME_MS) { + if (time_elapsed < conv_time_ms) { /* delay if conversion time not passed * since last read or write */ - if (msleep_interruptible( - LTC2497_CONVERSION_TIME_MS - time_elapsed)) + if (msleep_interruptible(conv_time_ms - time_elapsed)) return -ERESTARTSYS; return 0; } - if (time_elapsed - LTC2497_CONVERSION_TIME_MS <= 0) { + if (time_elapsed - conv_time_ms <= 0) { /* We're in automatic mode - * so the last reading is still not outdated */ @@ -48,9 +84,18 @@ static int ltc2497core_wait_conv(struct ltc2497core_driverdata *ddata) static int ltc2497core_read(struct ltc2497core_driverdata *ddata, u8 address, int *val) { + unsigned int conv_time_ms = ltc2497core_conv_time_ms(ddata, address); int ret; - ret = ltc2497core_wait_conv(ddata); + /* + * Wait for the conversion currently in flight, whose duration was fixed + * by the mode active when it was started (ddata->conv_time_prev). This + * can be longer than the freshly selected mode's time - e.g. a 1x + * conversion is still running when the first 2x read arrives after a + * sampling_frequency change - and reprogramming the device before it + * finishes would be NACKed (-EIO). + */ + ret = ltc2497core_wait_conv(ddata, ddata->conv_time_prev); if (ret < 0) return ret; @@ -60,7 +105,9 @@ static int ltc2497core_read(struct ltc2497core_driverdata *ddata, u8 address, in return ret; ddata->addr_prev = address; - if (msleep_interruptible(LTC2497_CONVERSION_TIME_MS)) + /* The reprogram above starts a conversion in the new mode. */ + ddata->conv_time_prev = conv_time_ms; + if (msleep_interruptible(conv_time_ms)) return -ERESTARTSYS; } @@ -69,6 +116,8 @@ static int ltc2497core_read(struct ltc2497core_driverdata *ddata, u8 address, in return ret; ddata->time_prev = ktime_get(); + /* The read above auto-starts the next conversion in the current mode. */ + ddata->conv_time_prev = conv_time_ms; return ret; } @@ -95,11 +144,115 @@ static int ltc2497core_read_raw(struct iio_dev *indio_dev, if (ret < 0) return ret; + if (chan->type == IIO_TEMP) { + /* + * raw is normalised to 2^(resolution + 1), i.e. + * raw = 2 * DATAOUT24, so the PTAT scale (datasheet + * Vref / 1570 per kelvin) doubles its denominator and, + * in m°C, becomes Vref_uV / 3140000. + */ + *val = ret; + *val2 = 3140000; + return IIO_VAL_FRACTIONAL; + } + *val = ret / 1000; *val2 = ddata->chip_info->resolution + 1; return IIO_VAL_FRACTIONAL_LOG2; + case IIO_CHAN_INFO_OFFSET: + if (chan->type == IIO_TEMP) { + ret = regulator_get_voltage(ddata->ref); + if (ret < 0) + return ret; + /* + * 0 °C == 273.15 K must map to raw + offset such that + * (raw + offset) * scale == 0 m°C, i.e. + * offset = -273150 / scale + * = -273150 * 3140000 / Vref_uV + * Computed in 64-bit to avoid overflow. + */ + *val = (int)div_s64(-273150LL * 3140000LL, ret); + return IIO_VAL_INT; + } + return -EINVAL; + + case IIO_CHAN_INFO_SAMP_FREQ: + /* + * Only advertised on the voltage channels of parts with a speed + * mode; the sampling frequency is a property of the selected 1x/2x + * mode, not of an individual conversion. + */ + mutex_lock(&ddata->lock); + *val = ltc2497core_samp_freq_avail[ddata->sped_2x * 2]; + *val2 = ltc2497core_samp_freq_avail[ddata->sped_2x * 2 + 1]; + mutex_unlock(&ddata->lock); + + return IIO_VAL_INT_PLUS_MICRO; + + default: + return -EINVAL; + } +} + +static int ltc2497core_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, + long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + *vals = ltc2497core_samp_freq_avail; + *type = IIO_VAL_INT_PLUS_MICRO; + *length = ARRAY_SIZE(ltc2497core_samp_freq_avail); + return IIO_AVAIL_LIST; + + default: + return -EINVAL; + } +} + +static int ltc2497core_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct ltc2497core_driverdata *ddata = iio_priv(indio_dev); + bool sped_2x; + int i; + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + /* Match the (val, val2) pair against the advertised rates. */ + for (i = 0; i < ARRAY_SIZE(ltc2497core_samp_freq_avail); i += 2) { + if (val == ltc2497core_samp_freq_avail[i] && + val2 == ltc2497core_samp_freq_avail[i + 1]) + break; + } + if (i >= ARRAY_SIZE(ltc2497core_samp_freq_avail)) + return -EINVAL; + + sped_2x = i / 2; + + mutex_lock(&ddata->lock); + ddata->sped_2x = sped_2x; + /* + * The new speed only takes effect once the second command byte + * is reprogrammed, so force the next read to reprogram rather + * than reuse the value already latched for this address. + * LTC2497_CONFIG_DEFAULT is not a valid channel/temperature + * address, so it is a safe re-arm sentinel (as used at probe). + * + * A conversion started under the old speed may still be in + * flight; its own duration (conv_time_prev), not the new mode's, + * still gates the next reprogram, so the timing state is left + * untouched here. + */ + ddata->addr_prev = LTC2497_CONFIG_DEFAULT; + mutex_unlock(&ddata->lock); + + return 0; + default: return -EINVAL; } @@ -126,6 +279,15 @@ static int ltc2497core_read_raw(struct iio_dev *indio_dev, .differential = 1, \ } +#define LTC2497_TEMP_CHANNEL { \ + .type = IIO_TEMP, \ + .address = LTC2497_TEMP_ADDR, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_OFFSET), \ + .datasheet_name = "TEMP", \ +} + static const struct iio_chan_spec ltc2497core_channel[] = { LTC2497_CHAN(0, LTC2497_SGL, "CH0"), LTC2497_CHAN(1, LTC2497_SGL, "CH1"), @@ -159,10 +321,13 @@ static const struct iio_chan_spec ltc2497core_channel[] = { LTC2497_CHAN_DIFF(5, LTC2497_DIFF | LTC2497_SIGN), LTC2497_CHAN_DIFF(6, LTC2497_DIFF | LTC2497_SIGN), LTC2497_CHAN_DIFF(7, LTC2497_DIFF | LTC2497_SIGN), + LTC2497_TEMP_CHANNEL, }; static const struct iio_info ltc2497core_info = { .read_raw = ltc2497core_read_raw, + .read_avail = ltc2497core_read_avail, + .write_raw = ltc2497core_write_raw, }; int ltc2497core_probe(struct device *dev, struct iio_dev *indio_dev) @@ -183,6 +348,37 @@ int ltc2497core_probe(struct device *dev, struct iio_dev *indio_dev) indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = ltc2497core_channel; indio_dev->num_channels = ARRAY_SIZE(ltc2497core_channel); + /* Only the ltc2499 has a temperature channel; it is the last entry. */ + if (!ddata->chip_info->has_temp) + indio_dev->num_channels--; + + /* + * Parts with a speed mode expose in_voltage_sampling_frequency / + * _available on the voltage channels only. SPD is ignored during a + * temperature measurement, so the temperature channel deliberately + * carries no SAMP_FREQ attribute. Patch a private copy of the shared + * channel array so parts without a speed mode stay untouched. + */ + if (ddata->chip_info->has_speed_mode) { + struct iio_chan_spec *channels; + unsigned int i; + + channels = devm_kmemdup(dev, ltc2497core_channel, + sizeof(ltc2497core_channel), GFP_KERNEL); + if (!channels) + return -ENOMEM; + + for (i = 0; i < indio_dev->num_channels; i++) { + if (channels[i].type != IIO_VOLTAGE) + continue; + channels[i].info_mask_shared_by_type |= + BIT(IIO_CHAN_INFO_SAMP_FREQ); + channels[i].info_mask_shared_by_type_available |= + BIT(IIO_CHAN_INFO_SAMP_FREQ); + } + + indio_dev->channels = channels; + } ret = ddata->result_and_measure(ddata, LTC2497_CONFIG_DEFAULT, NULL); if (ret < 0) @@ -214,6 +410,8 @@ int ltc2497core_probe(struct device *dev, struct iio_dev *indio_dev) ddata->addr_prev = LTC2497_CONFIG_DEFAULT; ddata->time_prev = ktime_get(); + /* Power-on default mode is 1x; a conversion is already in flight. */ + ddata->conv_time_prev = LTC2497_CONV_TIME_1X_MS; mutex_init(&ddata->lock); diff --git a/drivers/iio/adc/ltc2497.c b/drivers/iio/adc/ltc2497.c index eb9d521e86e54d..f663aed8ecc241 100644 --- a/drivers/iio/adc/ltc2497.c +++ b/drivers/iio/adc/ltc2497.c @@ -85,6 +85,40 @@ static int ltc2497_result_and_measure(struct ltc2497core_driverdata *ddata, return 0; } + /* + * Parts with a second config byte (LTC2499: internal PTAT sensor and/or + * the 2x speed mode) latch their converter configuration from that byte + * and only re-evaluate it when EN2 is set; a single byte, or a second + * byte with EN2 = 0, means "keep previous". A one-byte channel select + * therefore cannot pull the device back out of temperature mode, so a + * voltage read after a temperature read would keep returning the PTAT + * result. Always drive the second byte with EN2 set on these parts: + * - temperature read: IM = 1 (SPD is ignored by the part in + * temperature mode and is left 0 here); + * - voltage read: IM = 0 (external input), plus SPD when 2x is + * selected. + */ + if (ddata->chip_info->has_temp || ddata->chip_info->has_speed_mode) { + u8 cmd[2]; + + if (address == LTC2497_TEMP_ADDR) { + cmd[0] = LTC2497_ENABLE | LTC2497_CONFIG_DEFAULT; + cmd[1] = LTC2499_EN2 | LTC2499_IM; + } else { + cmd[0] = LTC2497_ENABLE | address; + cmd[1] = LTC2499_EN2 | + (ddata->sped_2x ? LTC2499_SPD : 0); + } + + ret = i2c_master_send(st->client, cmd, sizeof(cmd)); + if (ret < 0) { + dev_err(&st->client->dev, "i2c transfer failed: %pe\n", + ERR_PTR(ret)); + return ret; + } + return 0; + } + ret = i2c_smbus_write_byte(st->client, LTC2497_ENABLE | address); if (ret) @@ -134,10 +168,13 @@ static const struct ltc2497_chip_info ltc2497_info[] = { [TYPE_LTC2497] = { .resolution = 16, .name = NULL, + .has_temp = false, }, [TYPE_LTC2499] = { .resolution = 24, .name = "ltc2499", + .has_temp = true, + .has_speed_mode = true, }, }; diff --git a/drivers/iio/adc/ltc2497.h b/drivers/iio/adc/ltc2497.h index 781519b5247562..36980486faf27e 100644 --- a/drivers/iio/adc/ltc2497.h +++ b/drivers/iio/adc/ltc2497.h @@ -2,11 +2,37 @@ #define LTC2497_ENABLE 0xA0 #define LTC2497_CONFIG_DEFAULT LTC2497_ENABLE -#define LTC2497_CONVERSION_TIME_MS 150ULL + +/* + * Worst-case conversion times (datasheet t_CONV max). The driver only ever + * programs simultaneous 50/60Hz rejection (FA/FB selection is not implemented), + * so only those two rates are listed. The 1x value also covers the + * LTC2496/LTC2497, which have no speed mode. + * + * The 2x mode (LTC2499_SPD, LTC2499 only) disables the offset auto-calibration + * to roughly double the output rate; adding the 2x wait time is what makes the + * SPD control actually faster. + */ +#define LTC2497_CONV_TIME_1X_MS 150ULL /* t_CONV_1 simult. max 149.9 */ +#define LTC2499_CONV_TIME_2X_MS 76ULL /* t_CONV_2 simult. max 75.1 */ + +/* + * Sentinel passed as `address` to result_and_measure() to request a + * temperature conversion instead of a voltage channel. Valid channel + * addresses fit in 5 bits (0x00–0x1F), so 0xFF is unambiguous. + */ +#define LTC2497_TEMP_ADDR 0xFF + +/* Second config-byte bits (LTC2499 / LTC2493 only) */ +#define LTC2499_EN2 BIT(7) /* enable second config byte */ +#define LTC2499_IM BIT(6) /* 1 = measure internal temp sensor */ +#define LTC2499_SPD BIT(3) /* 1 = 2x output rate (offset cal off) */ struct ltc2497_chip_info { u32 resolution; const char *name; + bool has_temp; + bool has_speed_mode; /* SPD bit in the 2nd config byte (LTC2499/LTC2493) */ }; struct ltc2497core_driverdata { @@ -16,6 +42,14 @@ struct ltc2497core_driverdata { struct mutex lock; const struct ltc2497_chip_info *chip_info; u8 addr_prev; + bool sped_2x; /* SPD: false = 1x (default), true = 2x */ + /* + * Conversion time (ms) of the conversion currently in flight. It is + * fixed by the mode active when that conversion was started, which + * differs from the newly selected mode for the first read after a + * sampling_frequency change. + */ + unsigned int conv_time_prev; int (*result_and_measure)(struct ltc2497core_driverdata *ddata, u8 address, int *val); };