Skip to content

[PDDF] Add IIO, SMBus, scaling and threshold support to voltage sensor base class#25875

Open
pbdspec wants to merge 1 commit intosonic-net:masterfrom
pbdspec:pddfVoltageSensors
Open

[PDDF] Add IIO, SMBus, scaling and threshold support to voltage sensor base class#25875
pbdspec wants to merge 1 commit intosonic-net:masterfrom
pbdspec:pddfVoltageSensors

Conversation

@pbdspec
Copy link

@pbdspec pbdspec commented Mar 4, 2026

Why I did it

The existing PDDF PddfVoltageSensor base class only supports hwmon sysfs reads. This forces any vendor with non-hwmon voltage sensors (IIO ADCs, raw PMBus chips without hwmon drivers) to write their own custom platform-specific Python code, duplicating effort across vendors.

Many switch platforms use:

  • IIO ADC chips (max1139, max11613, ads7828, lt2488) that expose voltage via iio:deviceX/in_voltageN_raw — not hwmon
  • PMBus VRM chips behind I2C MUXes that lack a hwmon driver, requiring raw SMBus reads of VOUT_MODE (0x20) + READ_VOUT (0x8B) registers
  • Voltage dividers or millivolt-scale outputs needing scaling factors
  • Per-sensor operational thresholds (high/low/crit) from JSON config

Without this change, each vendor must independently implement IIO reads, PMBus Linear16/VID decoding, scaling arithmetic, and threshold lookups — all of which are generic and belong in the common base class.

How I did it

pddf_voltage_sensor.py:

  1. Three-way sensor dispatch in get_value() based on sensor_type in JSON dev_attr:

    • sensor_type absent or default → existing hwmon sysfs path (unchanged)
    • sensor_type = "iio" → new _read_iio() method
    • sensor_type = "smbus" → new _read_smbus() / _read_smbus_via_parent()
  2. IIO read path (_read_iio):

    • Discovers iio:deviceX/in_voltageN_raw from bus/addr/channel_id
    • Caches the resolved sysfs path for subsequent reads
    • Reads raw ADC count, applies multi_factor/decimate_factor scaling
    • Auto-creates I2C device via new_device if not yet bound
  3. SMBus read path (_read_smbus / _read_smbus_via_parent):

    • Reads VOUT_MODE register to determine output format
    • Reads READ_VOUT register for raw voltage data
    • Decodes PMBus Linear16 format (mode=0): mantissa × 2^exponent
    • Decodes PMBus VID format (mode=1): VR12/VR12.5/VR13 lookup tables
    • Supports cascaded MUX topologies via _read_smbus_via_parent() which manually selects MUX channel, reads, then deselects
  4. Scaling support:

    • multi_factor: multiplication after raw read (e.g., 4 for 4:1 divider)
    • decimate_factor: division after raw read (e.g., 10 for mV→V scaling)
    • Applied uniformly to all three read paths
  5. Threshold support:

    • get_high_threshold(), get_low_threshold(), get_high_critical_threshold(), get_low_critical_threshold()
    • Priority: sysfs hwmon limits first (chip hardware limits), JSON dev_attr fallback (high_threshold, low_threshold, high_crit_threshold, low_crit_threshold)
    • Returns float millivolts or None
  6. Named PMBus constants replacing all magic numbers:

    • PMBUS_VOUT_MODE (0x20), PMBUS_READ_VOUT (0x8B)
    • PMBUS_VOUT_MODE_LINEAR (0), PMBUS_VOUT_MODE_VID (1)
    • PMBUS_VOUT_MODE_SHIFT (5), PMBUS_VOUT_MODE_MASK (0x07)
    • PMBUS_VOUT_EXP_MASK, PMBUS_VOUT_EXP_SIGN_BIT, PMBUS_VOUT_EXP_OFFSET
    • VID_VR12_BASE_MV, VID_VR12_STEP_MV, VID_VR13_BASE_MV, VID_VR13_STEP_MV
    • MV_PER_VOLT (1000), MUX_DESELECT (0x00)
  7. Robust error handling:

    • try/except on all JSON float/int parsing (ValueError, TypeError)
    • try/except on all I/O operations with None return on failure
    • Guarded smbus2 import (HAS_SMBUS2 flag)

pddfapi.py:

  1. show_attr_voltage_sensor_device(): checks sensor_type in dev_attr, routes "iio" → show_attr_iio_device(), else → show_attr_hwmon_device()

  2. New show_attr_iio_device(): resolves IIO sysfs path from bus/addr/channel_id, reads in_voltageN_raw, supports virt_parent for parent device hwmon resolution

Backward compatibility:

  • Platforms without sensor_type in JSON continue to use the existing hwmon path — behavior is identical to the original base class
  • No changes to existing pddf-device.json files required
  • No new dependencies (smbus2 is optional, gracefully degrades)

Sample JSON configuration for each sensor type:

hwmon (existing, unchanged — uses DCDC parent + virt_parent):
"VOLTAGE12": {
"dev_info": {"device_type": "VOLTAGE_SENSOR"},
"i2c": {
"virt_parent": "VRM1",
"attr_list": [{"attr_name": "volt1_input",
"drv_attr_name": "in2_input"}],
"dev_attr": {"display_name": "MB_TRVDD1_0V9",
"high_threshold": "927",
"low_threshold": "873"}
}
}

IIO ADC (new — sensor_type + channel_id + scaling):
"VOLTAGE1": {
"dev_info": {"device_type": "VOLTAGE_SENSOR"},
"i2c": {
"topo_info": {"parent_bus": "0x9",
"dev_addr": "0x34",
"dev_type": "max1139"},
"dev_attr": {"sensor_type": "iio",
"channel_id": "0",
"multi_factor": "4",
"display_name": "BXX_VCC5P0",
"high_threshold": "5250",
"low_threshold": "4750"}
}
}

SMBus raw PMBus (new — sensor_type + optional parent MUX):
"VOLTAGE28": {
"dev_info": {"device_type": "VOLTAGE_SENSOR"},
"i2c": {
"topo_info": {"parent_bus": "0x3f",
"dev_addr": "0x20",
"dev_type": "max20796"},
"dev_attr": {"sensor_type": "smbus",
"display_name": "FPC_VDD_0V85",
"high_threshold": "875",
"low_threshold": "825",
"parent_mux_bus": "0x3d",
"parent_mux_addr": "0x70",
"parent_mux_ch": "0x08"}
}
}

How to verify it

  1. For hwmon sensors (backward compatible):

    • No changes to existing JSON needed
    • 'show platform voltage' should show same values as before
  2. For IIO sensors:

    • Add VOLTAGE_SENSOR entries with sensor_type="iio" in pddf-device.json
    • Ensure IIO ADC driver is loaded (e.g., max1363 for max1139)
    • 'show platform voltage' should show IIO sensor values with scaling
  3. For SMBus sensors:

    • Add VOLTAGE_SENSOR entries with sensor_type="smbus" in pddf-device.json
    • Ensure smbus2 Python package is available in pmon container
    • 'show platform voltage' should show PMBus voltage decoded values
  4. For thresholds:

    • Add high_threshold/low_threshold in JSON dev_attr (millivolts)
    • 'show platform voltage' should display Warning=True when sensor value exceeds configured thresholds
  5. Tested on Juniper platform with:

    • 15 hwmon sensors (tps53659, max16602, max16545 via DCDC+virt_parent)
    • 16 IIO sensors (max1139, max11613 ADCs with multi_factor scaling)
    • 8 SMBus sensors (max20796 behind PCA9548 MUX)
    • All 39 sensors reading correctly with thresholds

Which release branch to backport

N/A

Tested branch

master
Verified on Juniper platform hardware with SONiC master

Description for the changelog

Add IIO, SMBus, scaling and threshold support to PDDF voltage sensor

Link to config_db schema for YANG module changes

N/A

Signed-off-by: Satish Gopalakrishnan satishg@juniper.net

…r base class

#### Why I did it

The existing PDDF PddfVoltageSensor base class only supports hwmon sysfs
reads. This forces any vendor with non-hwmon voltage sensors (IIO ADCs,
raw PMBus chips without hwmon drivers) to write their own custom
platform-specific Python code, duplicating effort across vendors.

Many switch platforms use:
- IIO ADC chips (max1139, max11613, ads7828, lt2488) that expose
  voltage via iio:deviceX/in_voltageN_raw — not hwmon
- PMBus VRM chips behind I2C MUXes that lack a hwmon driver, requiring
  raw SMBus reads of VOUT_MODE (0x20) + READ_VOUT (0x8B) registers
- Voltage dividers or millivolt-scale outputs needing scaling factors
- Per-sensor operational thresholds (high/low/crit) from JSON config

Without this change, each vendor must independently implement IIO reads,
PMBus Linear16/VID decoding, scaling arithmetic, and threshold lookups —
all of which are generic and belong in the common base class.

#### How I did it

**pddf_voltage_sensor.py:**

1. Three-way sensor dispatch in get_value() based on sensor_type in
   JSON dev_attr:
   - sensor_type absent or default → existing hwmon sysfs path (unchanged)
   - sensor_type = "iio" → new _read_iio() method
   - sensor_type = "smbus" → new _read_smbus() / _read_smbus_via_parent()

2. IIO read path (_read_iio):
   - Discovers iio:deviceX/in_voltageN_raw from bus/addr/channel_id
   - Caches the resolved sysfs path for subsequent reads
   - Reads raw ADC count, applies multi_factor/decimate_factor scaling
   - Auto-creates I2C device via new_device if not yet bound

3. SMBus read path (_read_smbus / _read_smbus_via_parent):
   - Reads VOUT_MODE register to determine output format
   - Reads READ_VOUT register for raw voltage data
   - Decodes PMBus Linear16 format (mode=0): mantissa × 2^exponent
   - Decodes PMBus VID format (mode=1): VR12/VR12.5/VR13 lookup tables
   - Supports cascaded MUX topologies via _read_smbus_via_parent()
     which manually selects MUX channel, reads, then deselects

4. Scaling support:
   - multi_factor: multiplication after raw read (e.g., 4 for 4:1 divider)
   - decimate_factor: division after raw read (e.g., 10 for mV→V scaling)
   - Applied uniformly to all three read paths

5. Threshold support:
   - get_high_threshold(), get_low_threshold(),
     get_high_critical_threshold(), get_low_critical_threshold()
   - Priority: sysfs hwmon limits first (chip hardware limits),
     JSON dev_attr fallback (high_threshold, low_threshold,
     high_crit_threshold, low_crit_threshold)
   - Returns float millivolts or None

6. Named PMBus constants replacing all magic numbers:
   - PMBUS_VOUT_MODE (0x20), PMBUS_READ_VOUT (0x8B)
   - PMBUS_VOUT_MODE_LINEAR (0), PMBUS_VOUT_MODE_VID (1)
   - PMBUS_VOUT_MODE_SHIFT (5), PMBUS_VOUT_MODE_MASK (0x07)
   - PMBUS_VOUT_EXP_MASK, PMBUS_VOUT_EXP_SIGN_BIT, PMBUS_VOUT_EXP_OFFSET
   - VID_VR12_BASE_MV, VID_VR12_STEP_MV, VID_VR13_BASE_MV, VID_VR13_STEP_MV
   - MV_PER_VOLT (1000), MUX_DESELECT (0x00)

7. Robust error handling:
   - try/except on all JSON float/int parsing (ValueError, TypeError)
   - try/except on all I/O operations with None return on failure
   - Guarded smbus2 import (HAS_SMBUS2 flag)

**pddfapi.py:**

1. show_attr_voltage_sensor_device(): checks sensor_type in dev_attr,
   routes "iio" → show_attr_iio_device(), else → show_attr_hwmon_device()

2. New show_attr_iio_device(): resolves IIO sysfs path from
   bus/addr/channel_id, reads in_voltageN_raw, supports virt_parent
   for parent device hwmon resolution

**Backward compatibility:**
- Platforms without sensor_type in JSON continue to use the existing
  hwmon path — behavior is identical to the original base class
- No changes to existing pddf-device.json files required
- No new dependencies (smbus2 is optional, gracefully degrades)

**Sample JSON configuration for each sensor type:**

hwmon (existing, unchanged — uses DCDC parent + virt_parent):
  "VOLTAGE12": {
    "dev_info": {"device_type": "VOLTAGE_SENSOR"},
    "i2c": {
      "virt_parent": "VRM1",
      "attr_list": [{"attr_name": "volt1_input",
                       "drv_attr_name": "in2_input"}],
      "dev_attr": {"display_name": "MB_TRVDD1_0V9",
                     "high_threshold": "927",
                     "low_threshold": "873"}
    }
  }

IIO ADC (new — sensor_type + channel_id + scaling):
  "VOLTAGE1": {
    "dev_info": {"device_type": "VOLTAGE_SENSOR"},
    "i2c": {
      "topo_info": {"parent_bus": "0x9",
                      "dev_addr": "0x34",
                      "dev_type": "max1139"},
      "dev_attr": {"sensor_type": "iio",
                     "channel_id": "0",
                     "multi_factor": "4",
                     "display_name": "BXX_VCC5P0",
                     "high_threshold": "5250",
                     "low_threshold": "4750"}
    }
  }

SMBus raw PMBus (new — sensor_type + optional parent MUX):
  "VOLTAGE28": {
    "dev_info": {"device_type": "VOLTAGE_SENSOR"},
    "i2c": {
      "topo_info": {"parent_bus": "0x3f",
                      "dev_addr": "0x20",
                      "dev_type": "max20796"},
      "dev_attr": {"sensor_type": "smbus",
                     "display_name": "FPC_VDD_0V85",
                     "high_threshold": "875",
                     "low_threshold": "825",
                     "parent_mux_bus": "0x3d",
                     "parent_mux_addr": "0x70",
                     "parent_mux_ch": "0x08"}
    }
  }

#### How to verify it

1. For hwmon sensors (backward compatible):
   - No changes to existing JSON needed
   - 'show platform voltage' should show same values as before

2. For IIO sensors:
   - Add VOLTAGE_SENSOR entries with sensor_type="iio" in pddf-device.json
   - Ensure IIO ADC driver is loaded (e.g., max1363 for max1139)
   - 'show platform voltage' should show IIO sensor values with scaling

3. For SMBus sensors:
   - Add VOLTAGE_SENSOR entries with sensor_type="smbus" in pddf-device.json
   - Ensure smbus2 Python package is available in pmon container
   - 'show platform voltage' should show PMBus voltage decoded values

4. For thresholds:
   - Add high_threshold/low_threshold in JSON dev_attr (millivolts)
   - 'show platform voltage' should display Warning=True when
     sensor value exceeds configured thresholds

5. Tested on Juniper platform with:
   - 15 hwmon sensors (tps53659, max16602, max16545 via DCDC+virt_parent)
   - 16 IIO sensors (max1139, max11613 ADCs with multi_factor scaling)
   - 8 SMBus sensors (max20796 behind PCA9548 MUX)
   - All 39 sensors reading correctly with thresholds

#### Which release branch to backport

N/A

#### Tested branch

master
Verified on Juniper platform hardware with SONiC master

#### Description for the changelog

Enhance PDDF voltage sensor base class to support IIO subsystem reads,
raw SMBus/PMBus register reads (Linear16 and VID decode), multi_factor/
decimate_factor scaling, and per-sensor threshold configuration from JSON.
This allows vendors with IIO ADCs or raw PMBus chips to leverage the PDDF
common infrastructure without writing custom platform-specific Python code.
Fully backward compatible — existing hwmon-only platforms are unaffected.

#### Link to config_db schema for YANG module changes

N/A — no config_db or YANG changes. Only pddf-device.json dev_attr
fields are extended (sensor_type, channel_id, multi_factor,
decimate_factor, high_threshold, low_threshold, high_crit_threshold,
low_crit_threshold, parent_mux_bus, parent_mux_addr, parent_mux_ch).

Signed-off-by: Satish Gopalakrishnan <satishg@juniper.net>
@pbdspec pbdspec requested a review from lguohan as a code owner March 4, 2026 04:16
@linux-foundation-easycla
Copy link

linux-foundation-easycla bot commented Mar 4, 2026

CLA Signed
The committers listed above are authorized under a signed CLA.

  • ✅ login: satishg173 / name: Satish Gopalakrishnan (3ea3441)

@mssonicbld
Copy link
Collaborator

/azp run Azure.sonic-buildimage

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@pbdspec
Copy link
Author

pbdspec commented Mar 4, 2026

azpw/ run

@pbdspec
Copy link
Author

pbdspec commented Mar 4, 2026

=== Voltage Sensor Readings (39 sensors) — Juniper Platform ===

Sensor Name Value(mV) HighThresh LowThresh Status

--- IIO sensors (max1139 ADC, channel 0-10) ---
MAX1139_BLRE_SD1V1 1108.0 1160.0 1040.0 OK
MAX1139_BLRE_VCC1V1 1104.0 1160.0 1040.0 OK
MAX1139_CPU0_VCC1P8_AUX_NAC 1806.0 1890.0 1710.0 OK
MAX1139_PTP_VCCO1V8 1808.0 1890.0 1710.0 OK
MAX1139_PTP_VCCO3V3 3320.0 3470.0 3130.0 OK
MAX1139_PTP_VINT1V0 1006.0 1050.0 950.0 OK
MAX1139_PTP_VMGT1V2 1232.0 1260.0 1140.0 OK
MAX1139_SSD0_BIAS3P3 3316.0 3470.0 3130.0 OK
MAX1139_SSD1_BIAS3P3 3324.0 3470.0 3130.0 OK
MAX1139_USB_VCC5P0 5028.0 5250.0 4750.0 OK
MAX1139_VDD5V0 5028.0 5250.0 4750.0 OK

--- hwmon sensors (tps53659, max16602, max16545 via DCDC+virt_parent) ---
CPU0_VCC1P2_VDDQ01 1230.0 1260.0 1140.0 OK
CPU0_VCC2P5_VPP01 2500.0 2560.0 2440.0 OK
CPU0_VCC1P8_AUX 1800.0 1860.0 1740.0 OK
CPU0_VCCIN_CPU 1790.0 1860.0 1740.0 OK
CPU0_VCC1P05 1060.0 1100.0 1000.0 OK
CPU0_VCCVNN_PCH 950.0 1013.0 917.0 OK
CPU0_VCC1P0_PCIE4 1000.0 1060.0 940.0 OK
CPU0_VCCVNN_NAC 855.0 893.0 807.0 OK
CPU0_VCC3P3_AUX 3300.0 3465.0 3135.0 OK
CPU_HOTSWAP 1192.0 1260.0 1140.0 OK
BXX_HOTSWAP_0 1198.0 1260.0 1140.0 OK
BXX_HOTSWAP_1 1191.0 1260.0 1140.0 OK
BXX_HOTSWAP_2 1194.0 1260.0 1140.0 OK
BXX_HOTSWAP_3 1199.0 1260.0 1140.0 OK
BXX_HOTSWAP_4 1196.0 1260.0 1140.0 OK

--- SMBus sensors (max20796 via raw PMBus reads behind PCA9548 MUX) ---
BXX_FAB_0V85 847.0 893.0 807.0 OK
BXX_WAN_0V85 849.0 893.0 807.0 OK
BXX_FAB_1V1 1097.0 1155.0 1045.0 OK
BX0_CORE_0V75 750.0 800.0 700.0 OK
BX1_CORE_0V75 750.0 800.0 700.0 OK
BXX_WAN_1V1 1100.0 1260.0 1140.0 Warning
BXX_HBM_1V2 1199.0 1260.0 1140.0 OK
BX0_DIE_CRACK_MON 702.0 800.0 550.0 OK
BX1_DIE_CRACK_MON 702.0 800.0 550.0 OK
BX0_RING_H 1822.0 2500.0 0.0 OK
BX0_RING_T 2.0 2500.0 0.0 OK
BX1_RING_H 1822.0 2500.0 0.0 OK
BX1_RING_T 2.0 2500.0 0.0 OK

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants