Re: [PATCH v2 2/3] iio: adc: ltc2497: add LTC2499 internal temperature channel
Jonathan Cameron <[email protected]>
| Newsgroups | org.kernel.vger.linux-iio,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <20260815231513.3a72146a@jic23-huawei> |
On Thu, 13 Aug 2026 19:01:36 +0300 Andrei Stancovici <[email protected]> wrote: > The LTC2499 has an internal PTAT (proportional to absolute temperature) > sensor that is activated by a second I2C configuration byte (EN2 | IM). > Expose it as an IIO_TEMP channel providing raw, scale and offset so the > standard IIO formula > > T[m°C] = (raw + offset) * scale > > reconstructs the temperature. > > The PTAT sensor yields the absolute temperature as > > T(K) = DATAOUT24 * Vref / 1570 (Vref in volts) > > The raw value exported here is sign-extended and normalised to > 2^(resolution + 1) == 2^25, i.e. raw = 2 * DATAOUT24, so on the IIO > milli-degree-Celsius convention > > scale[m°C/LSB] = Vref_uV / 3140000 > offset = -273150 * 3140000 / Vref_uV > > The scale and offset are derived from the reference voltage returned by > regulator_get_voltage(); its error is propagated as before, so a board > that fails to describe vref-supply gets a clear read error instead of a > silently wrong temperature. No board-specific reference value is assumed > in the driver. > > The single temperature channel is appended as the last entry of the > shared channel array and excluded via num_channels for parts without an > internal sensor, so the existing LTC2497 channel layout and device name > are unchanged. > > The LTC2499 latches its converter configuration from the second command > byte and only re-evaluates it when that byte has EN2 set. EN2 | IM > selects the internal temperature sensor. Because a single-byte command, > or a second byte with EN2 = 0, means "keep previous", a one-byte channel > select cannot pull the device back out of temperature mode: after a > temperature read every subsequent voltage read would keep returning the > PTAT result instead of the selected input. Temperature support is > therefore only correct if the voltage path also emits a second command > byte that re-selects an external input. > > Send two-byte commands for all conversions on parts that have the sensor > (has_temp): > > temperature: EN2 | IM > voltage: EN2 (IM = 0 -> external input) > > The LTC2497 and LTC2496, which lack the second-byte mechanism, keep using > the original single-byte channel select and are unchanged. > > Signed-off-by: Andrei Stancovici <[email protected]> Hi Andrei A question inline on why this needs a DMA safe buffer given i2c still bounced everything unless we opt in. Thanks, Jonathan > diff --git a/drivers/iio/adc/ltc2497.c b/drivers/iio/adc/ltc2497.c > index c1668b5a351e..57a5406977ed 100644 > --- a/drivers/iio/adc/ltc2497.c > +++ b/drivers/iio/adc/ltc2497.c > @@ -84,6 +84,40 @@ static int ltc2497_result_and_measure(struct ltc2497core_driverdata *ddata, > return 0; > } > > + /* > + * Parts with the internal PTAT sensor (LTC2499) latch their converter > + * configuration via a second command byte and only re-evaluate it when > + * that byte has EN2 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: IM = 1 for a temperature read, > + * EN2 alone (IM = 0) to (re)select an external input. FA = FB = 0 keeps > + * the power-on simultaneous 50/60Hz rejection, whose worst-case > + * conversion time the driver's wait already covers. > + * > + * The two bytes are assembled in the DMA-safe st->data buffer rather than > + * on the stack, so the pointer handed to i2c_master_send() stays valid on > + * adapters that DMA the transfer (e.g. with CONFIG_VMAP_STACK). I'm confused by this (as is sashiko ;) You aren't using i2c_master_send_dmasafe() so the i2c core will bounce the data anyway. Generally I2C is too slow to care about copying a few bytes so we tend not to use that infrastructure unless the copy that would be needed is much bigger. In the wider set of devices supported, the ltc2496 uses SPI and there we do need something to ensure we have dma safe buffers. > + */ > + if (ddata->chip_info->has_temp) { > + if (address == LTC2497_TEMP_ADDR) { > + st->data.d8[0] = LTC2497_ENABLE | LTC2497_CONFIG_DEFAULT; > + st->data.d8[1] = LTC2499_EN2 | LTC2499_IM; > + } else { > + st->data.d8[0] = LTC2497_ENABLE | address; > + st->data.d8[1] = LTC2499_EN2; > + } > + > + ret = i2c_master_send(st->client, (char *)st->data.d8, 2); > + if (ret < 0) { > + dev_err(&st->client->dev, "i2c transfer failed: %pe\n", > + ERR_PTR(ret)); > + return ret; > + } > + return 0; > + } > +