On Sat, 29 May 2021 20:59:13 -0400 Liam Beguin <liambeguin@xxxxxxxxx> wrote: > From: Liam Beguin <lvb@xxxxxxxxxx> > > Add support for various linear temperature sensors. > > temperature-sense-rtd is used when the measured temperature is a > function of the sensor's resistance (like RTD sensors). > > temperature-sense-current is used when the measured temperature is a > function of the sensor's output current (like the AD590) > > temperature-sense-amplifier is used when the measured temperature is a > function of the sensor's voltage (like the LTC2997) > > Signed-off-by: Liam Beguin <lvb@xxxxxxxxxx> Hi Liam, Comments in here follow through from the bindings. Jonathan > --- > drivers/iio/afe/iio-rescale.c | 141 ++++++++++++++++++++++++++++++++++ > 1 file changed, 141 insertions(+) > > diff --git a/drivers/iio/afe/iio-rescale.c b/drivers/iio/afe/iio-rescale.c > index 3bd1f11f21db..eb53d833bf7c 100644 > --- a/drivers/iio/afe/iio-rescale.c > +++ b/drivers/iio/afe/iio-rescale.c > @@ -222,10 +222,133 @@ static int rescale_voltage_divider_props(struct device *dev, > return 0; > } > > +static int rescale_temp_sense_rtd_props(struct device *dev, > + struct rescale *rescale) > +{ > + u32 factor; > + u32 alpha; > + u32 iexc; > + u32 tmp; > + int ret; > + u32 r0; > + > + ret = device_property_read_u32(dev, "excitation-current-microamp", > + &iexc); > + if (ret) { > + dev_err(dev, "failed to read excitation-current-microamp: %d\n", > + ret); > + return ret; > + } > + > + ret = device_property_read_u32(dev, "alpha-micro-ohms-per-ohm-celsius", > + &alpha); > + if (ret) { > + dev_err(dev, "failed to read alpha-micro-ohms-per-celsius: %d\n", > + ret); > + return ret; > + } > + > + ret = device_property_read_u32(dev, "r-naught-ohms", &r0); > + if (ret) { > + dev_err(dev, "failed to read r-naught-ohms: %d\n", ret); > + return ret; > + } > + > + /* > + * The transfer function: > + * > + * - V(T) = R(T) * iexc > + * - R(T) = r0 * (1 + alpha * T) > + * > + * T = 1 / (alpha * r0 * iexc) * (V - r0 * iexc) > + */ > + tmp = r0 * iexc * alpha / 1000000; > + factor = gcd(tmp, 1000000); > + rescale->numerator = 1000000 / factor; > + rescale->denominator = tmp / factor; > + > + rescale->offset = -1 * ((r0 * iexc) / 1000); > + > + return 0; > +} > + > +static int rescale_temp_sense_current_props(struct device *dev, > + struct rescale *rescale) > +{ > + u32 alpha; > + u32 sense; > + int ret; > + > + ret = device_property_read_u32(dev, "sense-resistor-ohms", &sense); > + if (ret) { > + dev_err(dev, "failed to read the sense resistance: %d\n", ret); > + return ret; > + } > + > + ret = device_property_read_u32(dev, "alpha-micro-amps-per-degree", > + &alpha); > + if (ret) { > + dev_err(dev, "failed to read alpha-micro-amps-per-degree: %d\n", > + ret); > + return ret; > + } > + > + /* > + * The transfer function: > + * > + * - V(K) = Rsense * Isense(K) > + * - K = Isense(K) / alpha > + * - C = K - 273.15 > + * > + * C = 1 / (Rsense * alpha) * (V - 273.15 * Rsense * alpha) > + */ > + rescale->numerator = 1000000; > + rescale->denominator = alpha * sense; > + > + if (device_property_read_bool(dev, "use-kelvin-scale")) > + rescale->offset = -1 * ((27315 * alpha * sense) / 100000); As below. Generic offset, not this specific one please ;) > + > + return 0; > +} > + > +static int rescale_temp_sense_amplifier_props(struct device *dev, > + struct rescale *rescale) > +{ > + u32 alpha; > + int ret; > + > + ret = device_property_read_u32(dev, "alpha-micro-volts-per-degree", > + &alpha); > + if (ret) { > + dev_err(dev, "failed to read alpha-micro-volts-per-degree: %d\n", > + ret); > + return ret; > + } > + > + /* > + * The transfer function: > + * > + * - K = V(K) / alpha > + * - C = K - 273.15 > + * > + * C = 1 / (alpha) * (V - 273.15 * alpha) > + */ > + rescale->numerator = 1000000; > + rescale->denominator = alpha; > + > + if (device_property_read_bool(dev, "use-kelvin-scale")) As mentioned later, stick to celcius + an explicit offset. There will be devices that have their own offset which doesn't happen to be -273.15 > + rescale->offset = -1 * ((27315 * alpha) / 100000); > + > + return 0; > +} > + > enum rescale_variant { > CURRENT_SENSE_AMPLIFIER, > CURRENT_SENSE_SHUNT, > VOLTAGE_DIVIDER, > + TEMP_SENSE_RTD, > + TEMP_SENSE_CURRENT, > + TEMP_SENSE_AMPLIFIER, > }; > > static const struct rescale_cfg rescale_cfg[] = { > @@ -241,6 +364,18 @@ static const struct rescale_cfg rescale_cfg[] = { > .type = IIO_VOLTAGE, > .props = rescale_voltage_divider_props, > }, > + [TEMP_SENSE_RTD] = { > + .type = IIO_TEMP, > + .props = rescale_temp_sense_rtd_props, > + }, > + [TEMP_SENSE_CURRENT] = { > + .type = IIO_TEMP, > + .props = rescale_temp_sense_current_props, > + }, > + [TEMP_SENSE_AMPLIFIER] = { > + .type = IIO_TEMP, > + .props = rescale_temp_sense_amplifier_props, > + }, > }; > > static const struct of_device_id rescale_match[] = { > @@ -250,6 +385,12 @@ static const struct of_device_id rescale_match[] = { > .data = &rescale_cfg[CURRENT_SENSE_SHUNT], }, > { .compatible = "voltage-divider", > .data = &rescale_cfg[VOLTAGE_DIVIDER], }, > + { .compatible = "temperature-sense-rtd", > + .data = &rescale_cfg[TEMP_SENSE_RTD], }, > + { .compatible = "temperature-sense-current", > + .data = &rescale_cfg[TEMP_SENSE_CURRENT], }, > + { .compatible = "temperature-sense-amplifier", > + .data = &rescale_cfg[TEMP_SENSE_AMPLIFIER], }, > { /* sentinel */ } > }; > MODULE_DEVICE_TABLE(of, rescale_match);