dimm-spd-reader: fix PMIC type detection from SPD
Add support for identifying PMIC unknown state as 0xFF. Update PMIC SPD detection flow to read SPD registers 0x200, 0x204, and 0x208. Check bit7 to determine whether the PMIC is installed, and use SPD bit[3:0] as the PMIC type. Also update the IPMI error handling path to return completion code 0x07 for command 0x6c when PMIC detection fails or the PMIC type is unknown.
This commit is contained in:
@@ -0,0 +1,425 @@
|
||||
From 182a0516acfeffabf6f2ec863d078d3ef72b0265 Mon Sep 17 00:00:00 2001
|
||||
From: Your Name <you@example.com>
|
||||
Date: Thu, 23 Apr 2026 17:48:19 +0800
|
||||
Subject: [PATCH] LUXSHARE_2026041701
|
||||
|
||||
---
|
||||
.../dimm/dimm-spd-reader/dimmSpdReader.cpp | 281 ++++++++++++++----
|
||||
1 file changed, 229 insertions(+), 52 deletions(-)
|
||||
|
||||
diff --git a/meta-luxshare/meta-bhs/recipes-phosphor/dimm/dimm-spd-reader/dimmSpdReader.cpp b/meta-luxshare/meta-bhs/recipes-phosphor/dimm/dimm-spd-reader/dimmSpdReader.cpp
|
||||
index cd730713..7438cbd3 100755
|
||||
--- a/meta-luxshare/meta-bhs/recipes-phosphor/dimm/dimm-spd-reader/dimmSpdReader.cpp
|
||||
+++ b/meta-luxshare/meta-bhs/recipes-phosphor/dimm/dimm-spd-reader/dimmSpdReader.cpp
|
||||
@@ -346,7 +346,7 @@ static int i3cWriteRead(std::string& i3cDev, uint8_t wBuf[], uint16_t wLen,
|
||||
std::cout << "i3c data to write:" << std::endl;
|
||||
for(int i=0; i<wLen; i++)
|
||||
{
|
||||
- std::cout << "wBuf[" << i << "]: " << (int)wBuf[i] << " ";
|
||||
+ std::cout << "wBuf[" << i << "]: 0x" << std::hex << (int)wBuf[i] << std::dec << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
@@ -391,8 +391,12 @@ static int i3cWriteRead(std::string& i3cDev, uint8_t wBuf[], uint16_t wLen,
|
||||
|
||||
if constexpr (debug)
|
||||
{
|
||||
- std::cout << "i3c received data:" << std::endl;
|
||||
- std::cout << "rBuf[0]: " << (int)rBuf[0] << std::endl;
|
||||
+ std::cout << "i3c received data:\n";
|
||||
+ for (int i = 0; i < (int)rLen; i++)
|
||||
+ {
|
||||
+ std::cout << "rBuf[" << i << "]: 0x" << std::hex << (int)rBuf[i] << std::dec << " ";
|
||||
+ }
|
||||
+ std::cout << "\n";
|
||||
}
|
||||
|
||||
close(fd);
|
||||
@@ -452,7 +456,8 @@ int DIMMSpdReader::getPmicType(uint8_t cpuid, uint8_t rank)
|
||||
|
||||
uint8_t index[] = {0xc8, 0xcc, 0xd0};
|
||||
uint16_t wLen = 2;
|
||||
- uint8_t wrBuf[] = {0, 0};
|
||||
+//Jim debug uint8_t wrBuf[] = {0, 0};
|
||||
+ uint8_t wrBuf[] = {0, 0, 0}; //Jim debug
|
||||
uint8_t rdBuf[] = {0};
|
||||
uint16_t rLen = 1;
|
||||
int spd = NUM_TO_SPD(rank);
|
||||
@@ -494,6 +499,101 @@ int DIMMSpdReader::getPmicType(uint8_t cpuid, uint8_t rank)
|
||||
|
||||
gotType[cpuid][rank] = true;
|
||||
|
||||
+//Jim debug+S
|
||||
+
|
||||
+//----------------------------------------------------------------------------
|
||||
+//A. 1B Write R30 = 0x84 // 1 byte format, set 2 byte mode
|
||||
+//B. 2B Read R0030 //check 2 byte mode
|
||||
+// if(R0030 == 0x84)
|
||||
+// 2 byte mode + 1ms delay: R30 success
|
||||
+// Else // Original 2 byte mode
|
||||
+// C. 2B Write R0030 = 0x84
|
||||
+// D. 2B Read R0030
|
||||
+// if(R0030 == 0x84) //check 2 byte mode
|
||||
+// 2 byte mode + 1ms delay: R30 success
|
||||
+ if (pmicType[cpuid][rank] == PMIC5030)
|
||||
+ {
|
||||
+
|
||||
+ int pmic = NUM_TO_PMIC(rank);
|
||||
+ std::string i3cPmicName = I3C_ADDR(cpuid) + to_hex(pmic);
|
||||
+
|
||||
+ if constexpr (debug)
|
||||
+ {
|
||||
+ std::cout << "is PMIC5030"<< std::endl;
|
||||
+ }
|
||||
+ // 1. 1B Write R30 = 0x84
|
||||
+ wLen = 2;
|
||||
+ rLen = 0;
|
||||
+ wrBuf[0] = 0x30; wrBuf[1] = 0x84;
|
||||
+ rdBuf[0] = 0x00;
|
||||
+ ret = i3cWriteRead(i3cPmicName, wrBuf, wLen, rdBuf, rLen);
|
||||
+ if (ret < 0)
|
||||
+ {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ if constexpr (debug)
|
||||
+ {
|
||||
+ std::cout << "first 1B Write R30 = 0x84" << std::endl;
|
||||
+ }
|
||||
+ std::this_thread::sleep_for(std::chrono::milliseconds(9));
|
||||
+
|
||||
+ // 2. 2B Read R0030
|
||||
+ wLen = 2;
|
||||
+ rLen = 1;
|
||||
+ wrBuf[0] = 0x30; wrBuf[1] = 0x00;
|
||||
+ rdBuf[0] = 0x00;
|
||||
+ ret = i3cWriteRead(i3cPmicName, wrBuf, wLen, rdBuf, rLen);
|
||||
+ if (ret < 0)
|
||||
+ {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ if constexpr (debug)
|
||||
+ {
|
||||
+ std::cout << "2B Read R0030 = 0x" << std::hex << (int)rdBuf[0] << std::endl;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ // Successful switch to 2 Byte mode
|
||||
+ if(rdBuf[0] == 0x84)
|
||||
+ {
|
||||
+ if constexpr (debug)
|
||||
+ {
|
||||
+ std::cout << "Is 2 Byte mode" << std::endl;
|
||||
+ }
|
||||
+ }
|
||||
+ // It was originally 2 bytes mode
|
||||
+ else
|
||||
+ {
|
||||
+ //C2-2. 2B Write R30 = 0x84
|
||||
+ wrBuf[0] = 0x30; wrBuf[1] = 0x00; wrBuf[2] = 0x84;
|
||||
+ wLen = 3;
|
||||
+ rLen = 0;
|
||||
+ ret = i3cWriteRead(i3cPmicName, wrBuf, wLen, rdBuf, rLen);
|
||||
+
|
||||
+ std::this_thread::sleep_for(std::chrono::milliseconds(9));
|
||||
+ //C2-2. 2B Read R30 = 0x84
|
||||
+ wrBuf[0] = 0x30; wrBuf[1] = 0x00;
|
||||
+ wLen = 2;
|
||||
+ rLen = 1;
|
||||
+ ret = i3cWriteRead(i3cPmicName, wrBuf, wLen, rdBuf, rLen);
|
||||
+ if constexpr (debug)
|
||||
+ {
|
||||
+ std::cout << "2B Read R0030 = " << std::hex << (int)rdBuf[0] << std::endl;
|
||||
+ }
|
||||
+
|
||||
+ //Force the use of 1-byte mode
|
||||
+ if(rdBuf[0] != 0x84)
|
||||
+ {
|
||||
+ twoByteMode[cpuid][rank] = false;
|
||||
+ std::cout << "Force the use of 1-byte mode" << std::endl;
|
||||
+ }
|
||||
+
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+//Jim debug+E
|
||||
if constexpr (debug)
|
||||
{
|
||||
std::cout << "pmicType[" << (int)cpuid << "][" << (int)rank << "] = "<< (int)pmicType[cpuid][rank] << std::endl;
|
||||
@@ -635,9 +735,11 @@ int DIMMSpdReader::getDIMMRegsVol(uint8_t cpuid, uint8_t rank, DimmData& dimmDat
|
||||
|
||||
int index = (pmicType[cpuid][rank] == PMIC5030) ? 6 : 4;
|
||||
for(int i=0; i<index; i++) {
|
||||
- rLen = 1;
|
||||
+ //Write R30
|
||||
+ rLen = 0; //Jim debug, For Renesas requirements, I3C write commands cannot be directly read; reading requires a separate I3C command.
|
||||
if(twoByteMode[cpuid][rank])
|
||||
{
|
||||
+ adcValue = 0x4; //Jim debug, PMIC5030 fixed the 2 byte mode + 1ms
|
||||
wrBuf[2] = adcValue | adcSel[i];
|
||||
wLen = 3;
|
||||
}
|
||||
@@ -652,8 +754,14 @@ int DIMMSpdReader::getDIMMRegsVol(uint8_t cpuid, uint8_t rank, DimmData& dimmDat
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
-
|
||||
- std::this_thread::sleep_for(std::chrono::milliseconds(adcDelay[cpuid][rank]));
|
||||
+//Jim debug std::this_thread::sleep_for(std::chrono::milliseconds(adcDelay[cpuid][rank]));
|
||||
+//Jim debug+S
|
||||
+ // For Renesas requirements, the JESD spec PMIC5030 needs a 9ms delay.
|
||||
+ if(pmicType[cpuid][rank] == PMIC5030)
|
||||
+ std::this_thread::sleep_for(std::chrono::milliseconds(9));
|
||||
+ else
|
||||
+ std::this_thread::sleep_for(std::chrono::milliseconds(adcDelay[cpuid][rank]));
|
||||
+//Jim debug+E
|
||||
|
||||
wLen = twoByteMode[cpuid][rank] ? 2 : 1;
|
||||
rLen = 1;
|
||||
@@ -700,6 +808,7 @@ static double calStep31CurPower(int index, const uint8_t (&temp)[8])
|
||||
return result;
|
||||
}
|
||||
|
||||
+
|
||||
int DIMMSpdReader::getDIMMRegsCurAndPow(uint8_t cpuid, uint8_t rank, DimmData& dimmData)
|
||||
{
|
||||
int ret = -1;
|
||||
@@ -719,7 +828,8 @@ int DIMMSpdReader::getDIMMRegsCurAndPow(uint8_t cpuid, uint8_t rank, DimmData& d
|
||||
uint8_t adcSelect[] = {0x1b, 0, 0};
|
||||
uint16_t curOut[8];
|
||||
uint8_t temp[8];
|
||||
- uint8_t rdBuf[] = {0};
|
||||
+ uint8_t rdBuf[] = {0, 0, 0, 0, 0, 0, 0, 0}; //Jim debug, For Renesas requirements, I3C command: Continuously read R100~R107
|
||||
+//Jim debug uint8_t rdBuf[] = {0};
|
||||
uint8_t wrBuf[] = {0, 0};
|
||||
|
||||
int pmic = NUM_TO_PMIC(rank);
|
||||
@@ -776,7 +886,7 @@ int DIMMSpdReader::getDIMMRegsCurAndPow(uint8_t cpuid, uint8_t rank, DimmData& d
|
||||
adcSelect[1] = rdBuf[0] & 0xbf; //Read current
|
||||
wLen = 2;
|
||||
}
|
||||
-
|
||||
+ rLen = 0; //Jim debug, For Renesas requirements, I3C write commands cannot be directly read; reading requires a separate I3C command.
|
||||
ret = i3cWriteRead(i3cPmicName, adcSelect, wLen, rdBuf, rLen);
|
||||
if (ret < 0)
|
||||
{
|
||||
@@ -785,19 +895,34 @@ int DIMMSpdReader::getDIMMRegsCurAndPow(uint8_t cpuid, uint8_t rank, DimmData& d
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(adcDelay[cpuid][rank]));
|
||||
|
||||
- for(int i=0; i<index; i++) {
|
||||
- rLen = 1;
|
||||
- rdBuf[0] = 0;
|
||||
+
|
||||
+ if(accStep31)
|
||||
+ {
|
||||
+ rLen = 8;
|
||||
+ memset(rdBuf, 0, sizeof(rdBuf));
|
||||
if(twoByteMode[cpuid][rank])
|
||||
{
|
||||
- wrBuf[0] = static_cast<uint8_t>(curOut[i] & 0xFF);
|
||||
- wrBuf[1] = static_cast<uint8_t>((curOut[i] >> 8) & 0xFF);
|
||||
+ wrBuf[0] = static_cast<uint8_t>(curOut[0] & 0xFF);
|
||||
+ wrBuf[1] = static_cast<uint8_t>((curOut[0] >> 8) & 0xFF);
|
||||
wLen = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
- wrBuf[0] = static_cast<uint8_t>(curOut[i]);
|
||||
- wLen = 1;
|
||||
+ if constexpr (debug)
|
||||
+ {
|
||||
+ std::cout << "twoByteMode[" << (int)cpuid << "][" << (int)rank << "] = "<< (int)twoByteMode[cpuid][rank] << std::endl;
|
||||
+ }
|
||||
+ if(pmicType[cpuid][rank] == PMIC5030)
|
||||
+ {
|
||||
+ return -1;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ for(int i=0; i<6; i++)
|
||||
+ {
|
||||
+ dimmData.current[i] = calStep31CurPower(i, temp);
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
ret = i3cWriteRead(i3cPmicName, wrBuf, wLen, rdBuf, rLen);
|
||||
@@ -805,24 +930,43 @@ int DIMMSpdReader::getDIMMRegsCurAndPow(uint8_t cpuid, uint8_t rank, DimmData& d
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
-
|
||||
- if(accStep31)
|
||||
- {
|
||||
- temp[i] = rdBuf[0];
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- dimmData.current[i] = rdBuf[0] * 125.0 / 1000.0;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- if(accStep31)
|
||||
- {
|
||||
+ for(int i=0; i<index; i++) {
|
||||
+ temp[i] = rdBuf[i];
|
||||
+ }
|
||||
+
|
||||
for(int i=0; i<6; i++)
|
||||
{
|
||||
dimmData.current[i] = calStep31CurPower(i, temp);
|
||||
}
|
||||
}
|
||||
+ else
|
||||
+ {
|
||||
+ for(int i=0; i<index; i++) {
|
||||
+ rLen = 1;
|
||||
+ rdBuf[0] = 0;
|
||||
+ if(twoByteMode[cpuid][rank])
|
||||
+ {
|
||||
+ wrBuf[0] = static_cast<uint8_t>(curOut[i] & 0xFF);
|
||||
+ wrBuf[1] = static_cast<uint8_t>((curOut[i] >> 8) & 0xFF);
|
||||
+ wLen = 2;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ wrBuf[0] = static_cast<uint8_t>(curOut[i]);
|
||||
+ wLen = 1;
|
||||
+ }
|
||||
+
|
||||
+ ret = i3cWriteRead(i3cPmicName, wrBuf, wLen, rdBuf, rLen);
|
||||
+ if (ret < 0)
|
||||
+ {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ dimmData.current[i] = rdBuf[0] * 125.0 / 1000.0;
|
||||
+
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
|
||||
//start to read power
|
||||
if(twoByteMode[cpuid][rank])
|
||||
@@ -835,7 +979,7 @@ int DIMMSpdReader::getDIMMRegsCurAndPow(uint8_t cpuid, uint8_t rank, DimmData& d
|
||||
adcSelect[1] |= 0x40;
|
||||
wLen = 2;
|
||||
}
|
||||
-
|
||||
+ rLen = 0; //Jim debug, For Renesas requirements, I3C write commands cannot be directly read; reading requires a separate I3C command.
|
||||
ret = i3cWriteRead(i3cPmicName, adcSelect, wLen, rdBuf, rLen);
|
||||
if (ret < 0)
|
||||
{
|
||||
@@ -844,19 +988,34 @@ int DIMMSpdReader::getDIMMRegsCurAndPow(uint8_t cpuid, uint8_t rank, DimmData& d
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(adcDelay[cpuid][rank]));
|
||||
|
||||
- for(int i=0; i<index; i++) {
|
||||
- rLen = 1;
|
||||
- rdBuf[0] = 0;
|
||||
+ // For Renesas requirements, I3C command: Continuously read R100~R107
|
||||
+ if(accStep31)
|
||||
+ {
|
||||
+ rLen = 8;
|
||||
+ memset(rdBuf, 0, sizeof(rdBuf));
|
||||
if(twoByteMode[cpuid][rank])
|
||||
{
|
||||
- wrBuf[0] = static_cast<uint8_t>(curOut[i] & 0xFF);
|
||||
- wrBuf[1] = static_cast<uint8_t>((curOut[i] >> 8) & 0xFF);
|
||||
+ wrBuf[0] = static_cast<uint8_t>(curOut[0] & 0xFF);
|
||||
+ wrBuf[1] = static_cast<uint8_t>((curOut[0] >> 8) & 0xFF);
|
||||
wLen = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
- wrBuf[0] = static_cast<uint8_t>(curOut[i]);
|
||||
- wLen = 1;
|
||||
+ if constexpr (debug)
|
||||
+ {
|
||||
+ std::cout << "twoByteMode[" << (int)cpuid << "][" << (int)rank << "] = "<< (int)twoByteMode[cpuid][rank] << std::endl;
|
||||
+ }
|
||||
+ if(pmicType[cpuid][rank] == PMIC5030)
|
||||
+ {
|
||||
+ return -1;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ for(int i=0; i<6; i++)
|
||||
+ {
|
||||
+ dimmData.current[i] = calStep31CurPower(i, temp);
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
ret = i3cWriteRead(i3cPmicName, wrBuf, wLen, rdBuf, rLen);
|
||||
@@ -864,24 +1023,42 @@ int DIMMSpdReader::getDIMMRegsCurAndPow(uint8_t cpuid, uint8_t rank, DimmData& d
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
-
|
||||
- if(accStep31)
|
||||
- {
|
||||
- temp[i] = rdBuf[0];
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- dimmData.power[i] = rdBuf[0] * 125.0 / 1000.0;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- if(accStep31)
|
||||
- {
|
||||
- for(int i=0; i<STATUS_PMIC_RAIL_NUM; i++)
|
||||
+ for(int i=0; i<index; i++) {
|
||||
+ temp[i] = rdBuf[i];
|
||||
+ }
|
||||
+
|
||||
+ for(int i=0; i<6; i++)
|
||||
{
|
||||
dimmData.power[i] = calStep31CurPower(i, temp);
|
||||
}
|
||||
}
|
||||
+ else
|
||||
+ {
|
||||
+ for(int i=0; i<index; i++)
|
||||
+ {
|
||||
+ rLen = 1;
|
||||
+ rdBuf[0] = 0;
|
||||
+ if(twoByteMode[cpuid][rank])
|
||||
+ {
|
||||
+ wrBuf[0] = static_cast<uint8_t>(curOut[i] & 0xFF);
|
||||
+ wrBuf[1] = static_cast<uint8_t>((curOut[i] >> 8) & 0xFF);
|
||||
+ wLen = 2;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ wrBuf[0] = static_cast<uint8_t>(curOut[i]);
|
||||
+ wLen = 1;
|
||||
+ }
|
||||
+
|
||||
+ ret = i3cWriteRead(i3cPmicName, wrBuf, wLen, rdBuf, rLen);
|
||||
+ if (ret < 0)
|
||||
+ {
|
||||
+ return -1;
|
||||
+ }
|
||||
+ dimmData.power[i] = rdBuf[0] * 125.0 / 1000.0;
|
||||
+
|
||||
+ }
|
||||
+ }
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -994,7 +1171,7 @@ void DIMMSpdReader::readDimmInfo()
|
||||
}
|
||||
}
|
||||
updateField(dimmName, TEMP, dData.temp, STATUS_TEMP_NUM);
|
||||
-#if 0
|
||||
+#if 1
|
||||
if(regCounter == 0)
|
||||
{
|
||||
ret = getPmicStatusRegs(cpuid, i, dData);
|
||||
--
|
||||
2.34.1
|
||||
|
||||
Reference in New Issue
Block a user