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/i2cvr_software_manager.cpp b/i2c-vr/i2cvr_software_manager.cpp
index 4fa5ae7..b2afcbe 100644
--- a/i2c-vr/i2cvr_software_manager.cpp
+++ b/i2c-vr/i2cvr_software_manager.cpp
@@ -21,8 +21,9 @@
 
 const std::string configDBusName = "I2CVR";
 const std::vector<std::string> emConfigTypes = {
-    "XDPE1X2XXFirmware", "ISL69269Firmware", "MP2X6XXFirmware",
-    "MP297XFirmware",    "MP5998Firmware",   "RAA22XGen2Firmware"};
+    "XDPE1X2XXFirmware",   "ISL69269Firmware", "MP2X6XXFirmware",
+    "MP297XFirmware",      "MP5998Firmware",   "RAA22XGen2Firmware",
+    "RAA22XGen3p5Firmware"};
 
 I2CVRSoftwareManager::I2CVRSoftwareManager(sdbusplus::async::context& ctx) :
     ManagerInf::SoftwareManager(ctx, configDBusName)
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,
diff --git a/i2c-vr/vr.cpp b/i2c-vr/vr.cpp
index c4befe1..fe41df9 100644
--- a/i2c-vr/vr.cpp
+++ b/i2c-vr/vr.cpp
@@ -30,6 +30,9 @@
         case VRType::RAA22XGen2:
             return std::make_unique<ISL69269>(ctx, bus, address,
                                               ISL69269::Gen::Gen2);
+        case VRType::RAA22XGen3p5:
+            return std::make_unique<ISL69269>(ctx, bus, address,
+                                              ISL69269::Gen::Gen3p5);
         default:
             return nullptr;
     }
@@ -43,7 +46,8 @@
         {"MP2X6XXFirmware", VRType::MP2X6XX},
         {"MP297XFirmware", VRType::MP297X},
         {"MP5998Firmware", VRType::MP5998},
-        {"RAA22XGen2Firmware", VRType::RAA22XGen2}};
+        {"RAA22XGen2Firmware", VRType::RAA22XGen2},
+        {"RAA22XGen3p5Firmware", VRType::RAA22XGen3p5}};
 
     if (VRTypeToString.contains(vrStr))
     {
diff --git a/i2c-vr/vr.hpp b/i2c-vr/vr.hpp
index 8f52c7d..8ab78d3 100644
--- a/i2c-vr/vr.hpp
+++ b/i2c-vr/vr.hpp
@@ -17,6 +17,7 @@
     MP297X,
     MP5998,
     RAA22XGen2,
+    RAA22XGen3p5,
 };
 
 class VoltageRegulator