i2c-vr: add RAA22X Gen3.5 support
Extend ISL69269 to support Renesas Gen3.5 VR devices which share
similar programming interfaces but use slightly different registers
Related PRs -
EM schema(Merged):
https://gerrit.openbmc.org/c/openbmc/entity-manager/+/84149
Configuration patch(Merged):
https://gerrit.openbmc.org/c/openbmc/entity-manager/+/84150
PDI Hardware change(Merged):
https://gerrit.openbmc.org/c/openbmc/phosphor-dbus-interfaces/+/83529
Testd on Yv5:
```
$ target=$(curl -k ${creds} --silent -X GET https://${bmc}/redfish/v1/UpdateService/FirmwareInventory/ | jq -r '.Members[] | select(.["@odata.id"] | contains("CXL_VR_PVDD")) | .["@odata.id"]')
$ curl -k ${creds} -X GET https://${bmc}${target}
{
"@odata.id": "/redfish/v1/UpdateService/FirmwareInventory/Yosemite5_CXL_VR_PVDD_CORE_6124",
"@odata.type": "#SoftwareInventory.v1_1_0.SoftwareInventory",
"Description": "Unknown image",
"Id": "Yosemite5_CXL_VR_PVDD_CORE_6124",
"Name": "Software Inventory",
"Status": {
"Health": "OK",
"HealthRollup": "OK",
"State": "Enabled"
},
"Updateable": true,
"Version": "4F879069"
}
$ curl -k ${creds} -H "Content-Type:multipart/form-data" -X POST -F UpdateParameters="{\"Targets\":[\"${target}\"],\"@Redfish.OperationApplyTime\":\"OnReset\"};type=application/json" -F "UpdateFile=@${fwpath};type=application/octet-stream" https://${bmc}/redfish/v1/UpdateService/update-multipart
{
"@odata.id": "/redfish/v1/TaskService/Tasks/0",
"@odata.type": "#Task.v1_4_3.Task",
"HidePayload": false,
"Id": "0",
"Messages": [
{
"@odata.type": "#Message.v1_1_1.Message",
"Message": "The task with Id '0' has started.",
"MessageArgs": [
"0"
],
"MessageId": "TaskEvent.1.0.TaskStarted",
"MessageSeverity": "OK",
"Resolution": "None."
}
],
"Name": "Task 0",
"Payload": {
"HttpHeaders": [],
"HttpOperation": "POST",
"TargetUri": "/redfish/v1/UpdateService/update-multipart"
},
"PercentComplete": 0,
"StartTime": "2025-09-15T05:50:48+00:00",
"TaskMonitor": "/redfish/v1/TaskService/TaskMonitors/0",
"TaskState": "Running",
"TaskStatus": "OK"
}
$ curl -k $creds https://$bmc/redfish/v1/TaskService/Tasks/0
{
"@odata.id": "/redfish/v1/TaskService/Tasks/0",
"@odata.type": "#Task.v1_4_3.Task",
"EndTime": "2025-09-15T05:50:49+00:00",
"HidePayload": false,
"Id": "0",
"Messages": [
{
"@odata.type": "#Message.v1_1_1.Message",
"Message": "The task with Id '0' has started.",
"MessageArgs": [
"0"
],
"MessageId": "TaskEvent.1.0.TaskStarted",
"MessageSeverity": "OK",
"Resolution": "None."
},
{
"@odata.type": "#Message.v1_1_1.Message",
"Message": "The task with Id '0' has changed to progress 50 percent complete.",
"MessageArgs": [
"0",
"50"
],
"MessageId": "TaskEvent.1.0.TaskProgressChanged",
"MessageSeverity": "OK",
"Resolution": "None."
},
{
"@odata.type": "#Message.v1_1_1.Message",
"Message": "The task with Id '0' has changed to progress 80 percent complete.",
"MessageArgs": [
"0",
"80"
],
"MessageId": "TaskEvent.1.0.TaskProgressChanged",
"MessageSeverity": "OK",
"Resolution": "None."
},
{
"@odata.type": "#Message.v1_1_1.Message",
"Message": "The task with Id '0' has changed to progress 100 percent complete.",
"MessageArgs": [
"0",
"100"
],
"MessageId": "TaskEvent.1.0.TaskProgressChanged",
"MessageSeverity": "OK",
"Resolution": "None."
},
{
"@odata.type": "#Message.v1_1_1.Message",
"Message": "The task with Id '0' has completed.",
"MessageArgs": [
"0"
],
"MessageId": "TaskEvent.1.0.TaskCompletedOK",
"MessageSeverity": "OK",
"Resolution": "None."
}
],
"Name": "Task 0",
"Payload": {
"HttpHeaders": [],
"HttpOperation": "POST",
"JsonBody": "null",
"TargetUri": "/redfish/v1/UpdateService/update-multipart"
},
"PercentComplete": 100,
"StartTime": "2025-09-15T05:50:48+00:00",
"TaskMonitor": "/redfish/v1/TaskService/TaskMonitors/0",
"TaskState": "Completed",
"TaskStatus": "OK"
```
Change-Id: If99f5571d2d200416247edea2f745c41383af1c4
Signed-off-by: Leo Yang <Leo-Yang@quantatw.com>
diff --git a/i2c-vr/isl69269/isl69269.cpp b/i2c-vr/isl69269/isl69269.cpp
index 81d1e93..077afdd 100644
--- a/i2c-vr/isl69269/isl69269.cpp
+++ b/i2c-vr/isl69269/isl69269.cpp
@@ -27,6 +27,7 @@
constexpr uint8_t gen3Legacy = 1;
constexpr uint8_t gen3Production = 2;
constexpr uint8_t gen2Hex = 3;
+constexpr uint8_t gen3p5 = 4;
constexpr uint16_t cfgId = 7;
constexpr uint16_t gen3FileHead = 5;
@@ -62,6 +63,15 @@
constexpr uint16_t gen2FileHead = 6;
constexpr uint16_t gen2CRC = 600 - gen2FileHead;
+// RAA Gen3p5
+constexpr uint8_t regGen3p5ProgStatus = 0x83;
+constexpr uint8_t gen3p5RegCRC = 0xF8;
+constexpr uint8_t gen3p5HWRevMax = 0x06;
+constexpr uint8_t gen3p5HWRevMin = 0x03;
+constexpr uint16_t gen3p5cfgId = 3;
+constexpr uint16_t gen3p5FileHead = 5;
+constexpr uint16_t gen3p5CRC = 336 - gen3p5FileHead;
+
ISL69269::ISL69269(sdbusplus::async::context& ctx, uint16_t bus,
uint16_t address, Gen gen) :
VoltageRegulator(ctx), i2cInterface(phosphor::i2c::I2C(bus, address)),
@@ -173,6 +183,22 @@
*mode = gen2Hex;
co_return true;
}
+ else if (generation == Gen::Gen3p5)
+ {
+ uint32_t devID = 0;
+ if (!(co_await getDeviceId(&devID)))
+ {
+ error("program failed at getDeviceId");
+ co_return false;
+ }
+ devID = (devID >> 8) & 0xFF;
+
+ if (devID >= 0xBA)
+ {
+ *mode = gen3p5;
+ }
+ co_return true;
+ }
uint8_t tbuf[defaultBufferSize] = {0};
uint8_t rbuf[defaultBufferSize] = {0};
@@ -238,7 +264,7 @@
co_return false;
}
- if (mode == gen3Legacy)
+ if (mode == gen3Legacy || mode == gen3p5)
{
std::memcpy(revision, &rbuf[1], deviceRevisionLen);
}
@@ -255,7 +281,19 @@
uint8_t tbuf[defaultBufferSize] = {0};
uint8_t rbuf[defaultBufferSize] = {0};
- tbuf[0] = (generation == Gen::Gen2) ? gen2RegCRC : regCRC;
+ switch (generation)
+ {
+ case Gen::Gen2:
+ tbuf[0] = gen2RegCRC;
+ break;
+ case Gen::Gen3p5:
+ tbuf[0] = gen3p5RegCRC;
+ break;
+ default:
+ tbuf[0] = regCRC;
+ break;
+ }
+
if (!(co_await dmaReadWrite(tbuf, rbuf)))
{
error("getCRC failed");
@@ -297,6 +335,12 @@
shiftLeftFromMSB(sepLine + 4, &configuration.devIdExp);
debug("device id from configuration: {ID}", "ID", lg2::hex,
configuration.devIdExp);
+ // GEN3p5 IC_DEVICE_ID Byte ID[1]
+ if (generation == Gen::Gen3p5 && sepLine[6] >= 0xBA)
+ {
+ debug("Gen3p5 hex file format recognized");
+ configuration.mode = gen3p5;
+ }
}
else if (sepLine[3] == pmBusDeviceRev)
{
@@ -304,7 +348,7 @@
debug("device revision from config: {ID}", "ID", lg2::hex,
configuration.devRevExp);
- if (generation != Gen::Gen2)
+ if (generation == Gen::Gen3)
{
// According to programing guide:
// If legacy hex file
@@ -353,9 +397,20 @@
switch (dcnt)
{
case cfgId:
- configuration.cfgId = sepLine[4] & 0x0F;
- debug("Config ID: {ID}", "ID", lg2::hex,
- configuration.cfgId);
+ if (configuration.mode != gen3p5)
+ {
+ configuration.cfgId = sepLine[4] & 0x0F;
+ debug("Config ID: {ID}", "ID", lg2::hex,
+ configuration.cfgId);
+ }
+ break;
+ case gen3p5cfgId:
+ if (configuration.mode == gen3p5)
+ {
+ configuration.cfgId = sepLine[4];
+ debug("Config ID: {ID}", "ID", lg2::hex,
+ configuration.cfgId);
+ }
break;
case gen3LegacyCRC:
if (configuration.mode == gen3Legacy)
@@ -384,6 +439,15 @@
configuration.crcExp);
}
break;
+ case gen3p5CRC:
+ if (configuration.mode == gen3p5)
+ {
+ std::memcpy(&configuration.crcExp, &sepLine[4],
+ checksumLen);
+ debug("Config Gen3p5 CRC: {CRC}", "CRC", lg2::hex,
+ configuration.crcExp);
+ }
+ break;
}
dcnt++;
}
@@ -459,6 +523,11 @@
tbuf[0] = gen2RegProgStatus;
tbuf[1] = gen2RegProgStatus;
}
+ else if (generation == Gen::Gen3p5)
+ {
+ tbuf[0] = regGen3p5ProgStatus;
+ tbuf[1] = 0x00;
+ }
else
{
tbuf[0] = regProgStatus;
@@ -637,6 +706,17 @@
error("revision requirements for Gen2 device not fulfilled");
}
break;
+ case gen3p5:
+ if (((devRev >> 24) >= gen3p5HWRevMin) &&
+ ((devRev >> 24) <= gen3p5HWRevMax))
+ {
+ debug("Gen3p5 revision checks out");
+ }
+ else
+ {
+ error("revision requirements for Gen3p5 device not fulfilled");
+ }
+ break;
}
if (!(co_await getCRC(&crc)))
diff --git a/i2c-vr/isl69269/isl69269.hpp b/i2c-vr/isl69269/isl69269.hpp
index 8d9ea01..723ab68 100644
--- a/i2c-vr/isl69269/isl69269.hpp
+++ b/i2c-vr/isl69269/isl69269.hpp
@@ -16,7 +16,8 @@
enum class Gen
{
Gen2,
- Gen3
+ Gen3,
+ Gen3p5
};
ISL69269(sdbusplus::async::context& ctx, uint16_t bus, uint16_t address,