Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

iio: adc: xilinx-xadc: Correct temperature offset/scale for UltraScale

The driver was previously using offset and scale values for the
temperature sensor readings which were only valid for 7-series devices.
Add per-device-type values for offset and scale and set them appropriately
for each device type.

Note that the values used for the UltraScale family are for UltraScale+
(i.e. the SYSMONE4 primitive) using the internal reference, as that seems
to be the most common configuration and the device tree values Xilinx's
device tree generator produces don't seem to give us anything to tell us
which configuration is used. However, the differences within the UltraScale
family seem fairly minor and it's closer than using the 7-series values
instead in any case.

Fixes: c2b7720a7905 ("iio: xilinx-xadc: Add basic support for Ultrascale System Monitor")
Signed-off-by: Robert Hancock <robert.hancock@calian.com>
Acked-by: O'Griofa, Conall <conall.ogriofa@amd.com>
Tested-by: O'Griofa, Conall <conall.ogriofa@amd.com>
Link: https://lore.kernel.org/r/20230915001019.2862964-3-robert.hancock@calian.com
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Robert Hancock and committed by
Jonathan Cameron
e2bd8c28 8d6b3ea4

+16 -3
+14 -3
drivers/iio/adc/xilinx-xadc-core.c
··· 456 456 .interrupt_handler = xadc_zynq_interrupt_handler, 457 457 .update_alarm = xadc_zynq_update_alarm, 458 458 .type = XADC_TYPE_S7, 459 + /* Temp in C = (val * 503.975) / 2**bits - 273.15 */ 460 + .temp_scale = 503975, 461 + .temp_offset = 273150, 459 462 }; 460 463 461 464 static const unsigned int xadc_axi_reg_offsets[] = { ··· 569 566 .interrupt_handler = xadc_axi_interrupt_handler, 570 567 .flags = XADC_FLAGS_BUFFERED | XADC_FLAGS_IRQ_OPTIONAL, 571 568 .type = XADC_TYPE_S7, 569 + /* Temp in C = (val * 503.975) / 2**bits - 273.15 */ 570 + .temp_scale = 503975, 571 + .temp_offset = 273150, 572 572 }; 573 573 574 574 static const struct xadc_ops xadc_us_axi_ops = { ··· 583 577 .interrupt_handler = xadc_axi_interrupt_handler, 584 578 .flags = XADC_FLAGS_BUFFERED | XADC_FLAGS_IRQ_OPTIONAL, 585 579 .type = XADC_TYPE_US, 580 + /** 581 + * Values below are for UltraScale+ (SYSMONE4) using internal reference. 582 + * See https://docs.xilinx.com/v/u/en-US/ug580-ultrascale-sysmon 583 + */ 584 + .temp_scale = 509314, 585 + .temp_offset = 280231, 586 586 }; 587 587 588 588 static int _xadc_update_adc_reg(struct xadc *xadc, unsigned int reg, ··· 957 945 *val2 = bits; 958 946 return IIO_VAL_FRACTIONAL_LOG2; 959 947 case IIO_TEMP: 960 - /* Temp in C = (val * 503.975) / 2**bits - 273.15 */ 961 - *val = 503975; 948 + *val = xadc->ops->temp_scale; 962 949 *val2 = bits; 963 950 return IIO_VAL_FRACTIONAL_LOG2; 964 951 default: ··· 965 954 } 966 955 case IIO_CHAN_INFO_OFFSET: 967 956 /* Only the temperature channel has an offset */ 968 - *val = -((273150 << bits) / 503975); 957 + *val = -((xadc->ops->temp_offset << bits) / xadc->ops->temp_scale); 969 958 return IIO_VAL_INT; 970 959 case IIO_CHAN_INFO_SAMP_FREQ: 971 960 ret = xadc_read_samplerate(xadc);
+2
drivers/iio/adc/xilinx-xadc.h
··· 85 85 86 86 unsigned int flags; 87 87 enum xadc_type type; 88 + int temp_scale; 89 + int temp_offset; 88 90 }; 89 91 90 92 static inline int _xadc_read_adc_reg(struct xadc *xadc, unsigned int reg,