iio: adc: xilinx-xadc: Correct temperature offset/scale for UltraScale
[platform/kernel/linux-starfive.git] / drivers / iio / adc / xilinx-xadc-core.c
index d4d0d18..564c0ca 100644 (file)
@@ -456,6 +456,9 @@ static const struct xadc_ops xadc_zynq_ops = {
        .interrupt_handler = xadc_zynq_interrupt_handler,
        .update_alarm = xadc_zynq_update_alarm,
        .type = XADC_TYPE_S7,
+       /* Temp in C = (val * 503.975) / 2**bits - 273.15 */
+       .temp_scale = 503975,
+       .temp_offset = 273150,
 };
 
 static const unsigned int xadc_axi_reg_offsets[] = {
@@ -566,6 +569,9 @@ static const struct xadc_ops xadc_7s_axi_ops = {
        .interrupt_handler = xadc_axi_interrupt_handler,
        .flags = XADC_FLAGS_BUFFERED | XADC_FLAGS_IRQ_OPTIONAL,
        .type = XADC_TYPE_S7,
+       /* Temp in C = (val * 503.975) / 2**bits - 273.15 */
+       .temp_scale = 503975,
+       .temp_offset = 273150,
 };
 
 static const struct xadc_ops xadc_us_axi_ops = {
@@ -577,6 +583,12 @@ static const struct xadc_ops xadc_us_axi_ops = {
        .interrupt_handler = xadc_axi_interrupt_handler,
        .flags = XADC_FLAGS_BUFFERED | XADC_FLAGS_IRQ_OPTIONAL,
        .type = XADC_TYPE_US,
+       /**
+        * Values below are for UltraScale+ (SYSMONE4) using internal reference.
+        * See https://docs.xilinx.com/v/u/en-US/ug580-ultrascale-sysmon
+        */
+       .temp_scale = 509314,
+       .temp_offset = 280231,
 };
 
 static int _xadc_update_adc_reg(struct xadc *xadc, unsigned int reg,
@@ -945,8 +957,7 @@ static int xadc_read_raw(struct iio_dev *indio_dev,
                        *val2 = bits;
                        return IIO_VAL_FRACTIONAL_LOG2;
                case IIO_TEMP:
-                       /* Temp in C = (val * 503.975) / 2**bits - 273.15 */
-                       *val = 503975;
+                       *val = xadc->ops->temp_scale;
                        *val2 = bits;
                        return IIO_VAL_FRACTIONAL_LOG2;
                default:
@@ -954,7 +965,7 @@ static int xadc_read_raw(struct iio_dev *indio_dev,
                }
        case IIO_CHAN_INFO_OFFSET:
                /* Only the temperature channel has an offset */
-               *val = -((273150 << bits) / 503975);
+               *val = -((xadc->ops->temp_offset << bits) / xadc->ops->temp_scale);
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_SAMP_FREQ:
                ret = xadc_read_samplerate(xadc);