1*782d6eedSFreddieJheng #include "mp5998.hpp"
2*782d6eedSFreddieJheng
3*782d6eedSFreddieJheng #include "common/include/utils.hpp"
4*782d6eedSFreddieJheng
5*782d6eedSFreddieJheng #include <phosphor-logging/lg2.hpp>
6*782d6eedSFreddieJheng
7*782d6eedSFreddieJheng #include <fstream>
8*782d6eedSFreddieJheng
9*782d6eedSFreddieJheng PHOSPHOR_LOG2_USING;
10*782d6eedSFreddieJheng
11*782d6eedSFreddieJheng namespace phosphor::software::VR
12*782d6eedSFreddieJheng {
13*782d6eedSFreddieJheng
14*782d6eedSFreddieJheng static constexpr std::string_view crcUserRegName = "CRC_USER";
15*782d6eedSFreddieJheng static constexpr uint8_t eepromFaultBit = 0x01;
16*782d6eedSFreddieJheng static constexpr uint8_t unlockData = 0x00;
17*782d6eedSFreddieJheng static constexpr size_t statusByteLength = 1;
18*782d6eedSFreddieJheng
19*782d6eedSFreddieJheng enum class MP5998Cmd : uint8_t
20*782d6eedSFreddieJheng {
21*782d6eedSFreddieJheng crcUser = 0xF8,
22*782d6eedSFreddieJheng passwordReg = 0x0E,
23*782d6eedSFreddieJheng };
24*782d6eedSFreddieJheng
parseDeviceConfiguration()25*782d6eedSFreddieJheng sdbusplus::async::task<bool> MP5998::parseDeviceConfiguration()
26*782d6eedSFreddieJheng {
27*782d6eedSFreddieJheng if (!configuration)
28*782d6eedSFreddieJheng {
29*782d6eedSFreddieJheng error("Device configuration not initialized");
30*782d6eedSFreddieJheng co_return false;
31*782d6eedSFreddieJheng }
32*782d6eedSFreddieJheng
33*782d6eedSFreddieJheng configuration->vendorId = 0x4D5053;
34*782d6eedSFreddieJheng configuration->productId = 0x35393938;
35*782d6eedSFreddieJheng
36*782d6eedSFreddieJheng for (const auto& tokens : parser->lineTokens)
37*782d6eedSFreddieJheng {
38*782d6eedSFreddieJheng if (!parser->isValidDataTokens(tokens))
39*782d6eedSFreddieJheng {
40*782d6eedSFreddieJheng continue;
41*782d6eedSFreddieJheng }
42*782d6eedSFreddieJheng
43*782d6eedSFreddieJheng auto regName = parser->getVal<std::string>(tokens, ATE::regName);
44*782d6eedSFreddieJheng
45*782d6eedSFreddieJheng if (regName == crcUserRegName)
46*782d6eedSFreddieJheng {
47*782d6eedSFreddieJheng configuration->configId =
48*782d6eedSFreddieJheng parser->getVal<uint32_t>(tokens, ATE::configId);
49*782d6eedSFreddieJheng configuration->crcUser =
50*782d6eedSFreddieJheng parser->getVal<uint32_t>(tokens, ATE::regDataHex);
51*782d6eedSFreddieJheng }
52*782d6eedSFreddieJheng }
53*782d6eedSFreddieJheng
54*782d6eedSFreddieJheng co_return true;
55*782d6eedSFreddieJheng }
56*782d6eedSFreddieJheng
verifyImage(const uint8_t * image,size_t imageSize)57*782d6eedSFreddieJheng sdbusplus::async::task<bool> MP5998::verifyImage(const uint8_t* image,
58*782d6eedSFreddieJheng size_t imageSize)
59*782d6eedSFreddieJheng {
60*782d6eedSFreddieJheng if (!co_await parseImage(image, imageSize))
61*782d6eedSFreddieJheng {
62*782d6eedSFreddieJheng error("Image verification failed: image parsing failed");
63*782d6eedSFreddieJheng co_return false;
64*782d6eedSFreddieJheng }
65*782d6eedSFreddieJheng
66*782d6eedSFreddieJheng if (configuration->registersData.empty())
67*782d6eedSFreddieJheng {
68*782d6eedSFreddieJheng error("Image verification failed - no register data found");
69*782d6eedSFreddieJheng co_return false;
70*782d6eedSFreddieJheng }
71*782d6eedSFreddieJheng
72*782d6eedSFreddieJheng if (configuration->configId == 0)
73*782d6eedSFreddieJheng {
74*782d6eedSFreddieJheng error("Image verification failed - missing config ID");
75*782d6eedSFreddieJheng co_return false;
76*782d6eedSFreddieJheng }
77*782d6eedSFreddieJheng
78*782d6eedSFreddieJheng co_return true;
79*782d6eedSFreddieJheng }
80*782d6eedSFreddieJheng
checkId(PMBusCmd idCmd,uint32_t expected)81*782d6eedSFreddieJheng sdbusplus::async::task<bool> MP5998::checkId(PMBusCmd idCmd, uint32_t expected)
82*782d6eedSFreddieJheng {
83*782d6eedSFreddieJheng static constexpr size_t mfrIdLength = 3;
84*782d6eedSFreddieJheng static constexpr size_t mfrModelLength = 5;
85*782d6eedSFreddieJheng
86*782d6eedSFreddieJheng std::vector<uint8_t> tbuf;
87*782d6eedSFreddieJheng std::vector<uint8_t> rbuf;
88*782d6eedSFreddieJheng
89*782d6eedSFreddieJheng tbuf = buildByteVector(PMBusCmd::page, MPSPage::page0);
90*782d6eedSFreddieJheng if (!i2cInterface.sendReceive(tbuf, rbuf))
91*782d6eedSFreddieJheng {
92*782d6eedSFreddieJheng error("MP5998: Failed to set page 0 for ID check");
93*782d6eedSFreddieJheng co_return false;
94*782d6eedSFreddieJheng }
95*782d6eedSFreddieJheng
96*782d6eedSFreddieJheng size_t bufferSize;
97*782d6eedSFreddieJheng
98*782d6eedSFreddieJheng if (idCmd == PMBusCmd::mfrId)
99*782d6eedSFreddieJheng {
100*782d6eedSFreddieJheng bufferSize = statusByteLength + mfrIdLength;
101*782d6eedSFreddieJheng }
102*782d6eedSFreddieJheng else if (idCmd == PMBusCmd::mfrModel)
103*782d6eedSFreddieJheng {
104*782d6eedSFreddieJheng bufferSize = statusByteLength + mfrModelLength;
105*782d6eedSFreddieJheng }
106*782d6eedSFreddieJheng else
107*782d6eedSFreddieJheng {
108*782d6eedSFreddieJheng error("MP5998: Unsupported ID command: 0x{CMD}", "CMD", lg2::hex,
109*782d6eedSFreddieJheng static_cast<uint8_t>(idCmd));
110*782d6eedSFreddieJheng co_return false;
111*782d6eedSFreddieJheng }
112*782d6eedSFreddieJheng
113*782d6eedSFreddieJheng tbuf = buildByteVector(idCmd);
114*782d6eedSFreddieJheng rbuf.resize(bufferSize);
115*782d6eedSFreddieJheng
116*782d6eedSFreddieJheng if (!i2cInterface.sendReceive(tbuf, rbuf))
117*782d6eedSFreddieJheng {
118*782d6eedSFreddieJheng error("MP5998: I2C sendReceive failed for command 0x{CMD}", "CMD",
119*782d6eedSFreddieJheng lg2::hex, static_cast<uint8_t>(idCmd));
120*782d6eedSFreddieJheng co_return false;
121*782d6eedSFreddieJheng }
122*782d6eedSFreddieJheng
123*782d6eedSFreddieJheng auto idBytes = std::span(rbuf).subspan(statusByteLength);
124*782d6eedSFreddieJheng uint32_t id;
125*782d6eedSFreddieJheng if (idCmd == PMBusCmd::mfrModel)
126*782d6eedSFreddieJheng {
127*782d6eedSFreddieJheng auto productBytes = idBytes.subspan(1, 4);
128*782d6eedSFreddieJheng id = bytesToInt<uint32_t>(productBytes);
129*782d6eedSFreddieJheng }
130*782d6eedSFreddieJheng else
131*782d6eedSFreddieJheng {
132*782d6eedSFreddieJheng id = bytesToInt<uint32_t>(idBytes);
133*782d6eedSFreddieJheng }
134*782d6eedSFreddieJheng
135*782d6eedSFreddieJheng debug("Check ID cmd {CMD}: Got={ID}, Expected={EXP}", "CMD", lg2::hex,
136*782d6eedSFreddieJheng static_cast<uint8_t>(idCmd), "ID", lg2::hex, id, "EXP", lg2::hex,
137*782d6eedSFreddieJheng expected);
138*782d6eedSFreddieJheng
139*782d6eedSFreddieJheng co_return id == expected;
140*782d6eedSFreddieJheng }
141*782d6eedSFreddieJheng
unlockPasswordProtection()142*782d6eedSFreddieJheng sdbusplus::async::task<bool> MP5998::unlockPasswordProtection()
143*782d6eedSFreddieJheng {
144*782d6eedSFreddieJheng constexpr uint8_t passwordUnlockBit = 0x08;
145*782d6eedSFreddieJheng constexpr uint16_t passwordData = 0x0000;
146*782d6eedSFreddieJheng
147*782d6eedSFreddieJheng std::vector<uint8_t> tbuf;
148*782d6eedSFreddieJheng std::vector<uint8_t> rbuf;
149*782d6eedSFreddieJheng
150*782d6eedSFreddieJheng tbuf = buildByteVector(PMBusCmd::page, MPSPage::page0);
151*782d6eedSFreddieJheng if (!i2cInterface.sendReceive(tbuf, rbuf))
152*782d6eedSFreddieJheng {
153*782d6eedSFreddieJheng error("Failed to set page 0 for password unlock");
154*782d6eedSFreddieJheng co_return false;
155*782d6eedSFreddieJheng }
156*782d6eedSFreddieJheng
157*782d6eedSFreddieJheng tbuf = buildByteVector(MP5998Cmd::passwordReg, passwordData);
158*782d6eedSFreddieJheng if (!i2cInterface.sendReceive(tbuf, rbuf))
159*782d6eedSFreddieJheng {
160*782d6eedSFreddieJheng error("Failed to write password");
161*782d6eedSFreddieJheng co_return false;
162*782d6eedSFreddieJheng }
163*782d6eedSFreddieJheng
164*782d6eedSFreddieJheng tbuf = buildByteVector(PMBusCmd::statusCML);
165*782d6eedSFreddieJheng rbuf.resize(statusByteLength);
166*782d6eedSFreddieJheng if (!i2cInterface.sendReceive(tbuf, rbuf))
167*782d6eedSFreddieJheng {
168*782d6eedSFreddieJheng error("Failed to read STATUS_CML");
169*782d6eedSFreddieJheng co_return false;
170*782d6eedSFreddieJheng }
171*782d6eedSFreddieJheng
172*782d6eedSFreddieJheng bool unlocked = (rbuf[0] & passwordUnlockBit) == 0;
173*782d6eedSFreddieJheng
174*782d6eedSFreddieJheng co_return unlocked;
175*782d6eedSFreddieJheng }
176*782d6eedSFreddieJheng
unlockWriteProtection()177*782d6eedSFreddieJheng sdbusplus::async::task<bool> MP5998::unlockWriteProtection()
178*782d6eedSFreddieJheng {
179*782d6eedSFreddieJheng std::vector<uint8_t> tbuf;
180*782d6eedSFreddieJheng std::vector<uint8_t> rbuf;
181*782d6eedSFreddieJheng
182*782d6eedSFreddieJheng tbuf = buildByteVector(PMBusCmd::page, MPSPage::page0);
183*782d6eedSFreddieJheng if (!i2cInterface.sendReceive(tbuf, rbuf))
184*782d6eedSFreddieJheng {
185*782d6eedSFreddieJheng error("Failed to set page 0 for write protection unlock");
186*782d6eedSFreddieJheng co_return false;
187*782d6eedSFreddieJheng }
188*782d6eedSFreddieJheng
189*782d6eedSFreddieJheng tbuf = buildByteVector(PMBusCmd::writeProtect, unlockData);
190*782d6eedSFreddieJheng if (!i2cInterface.sendReceive(tbuf, rbuf))
191*782d6eedSFreddieJheng {
192*782d6eedSFreddieJheng error("Failed to unlock write protection");
193*782d6eedSFreddieJheng co_return false;
194*782d6eedSFreddieJheng }
195*782d6eedSFreddieJheng
196*782d6eedSFreddieJheng debug("Write protection unlocked");
197*782d6eedSFreddieJheng co_return true;
198*782d6eedSFreddieJheng }
199*782d6eedSFreddieJheng
programAllRegisters()200*782d6eedSFreddieJheng sdbusplus::async::task<bool> MP5998::programAllRegisters()
201*782d6eedSFreddieJheng {
202*782d6eedSFreddieJheng uint8_t currentPage = 0xFF;
203*782d6eedSFreddieJheng
204*782d6eedSFreddieJheng for (const auto& regData : configuration->registersData)
205*782d6eedSFreddieJheng {
206*782d6eedSFreddieJheng if (regData.page != currentPage)
207*782d6eedSFreddieJheng {
208*782d6eedSFreddieJheng std::vector<uint8_t> tbuf =
209*782d6eedSFreddieJheng buildByteVector(PMBusCmd::page, regData.page);
210*782d6eedSFreddieJheng std::vector<uint8_t> rbuf;
211*782d6eedSFreddieJheng if (!i2cInterface.sendReceive(tbuf, rbuf))
212*782d6eedSFreddieJheng {
213*782d6eedSFreddieJheng error("Failed to set page {PAGE}", "PAGE", regData.page);
214*782d6eedSFreddieJheng co_return false;
215*782d6eedSFreddieJheng }
216*782d6eedSFreddieJheng currentPage = regData.page;
217*782d6eedSFreddieJheng }
218*782d6eedSFreddieJheng
219*782d6eedSFreddieJheng std::vector<uint8_t> tbuf;
220*782d6eedSFreddieJheng std::vector<uint8_t> rbuf;
221*782d6eedSFreddieJheng
222*782d6eedSFreddieJheng tbuf.push_back(regData.addr);
223*782d6eedSFreddieJheng
224*782d6eedSFreddieJheng for (uint8_t i = 0; i < regData.length && i < 4; ++i)
225*782d6eedSFreddieJheng {
226*782d6eedSFreddieJheng tbuf.push_back(regData.data[i]);
227*782d6eedSFreddieJheng }
228*782d6eedSFreddieJheng
229*782d6eedSFreddieJheng if (!i2cInterface.sendReceive(tbuf, rbuf))
230*782d6eedSFreddieJheng {
231*782d6eedSFreddieJheng error("Failed to write register 0x{REG} on page {PAGE}", "REG",
232*782d6eedSFreddieJheng lg2::hex, regData.addr, "PAGE", regData.page);
233*782d6eedSFreddieJheng co_return false;
234*782d6eedSFreddieJheng }
235*782d6eedSFreddieJheng }
236*782d6eedSFreddieJheng
237*782d6eedSFreddieJheng debug("All registers programmed successfully");
238*782d6eedSFreddieJheng co_return true;
239*782d6eedSFreddieJheng }
240*782d6eedSFreddieJheng
storeMTP()241*782d6eedSFreddieJheng sdbusplus::async::task<bool> MP5998::storeMTP()
242*782d6eedSFreddieJheng {
243*782d6eedSFreddieJheng std::vector<uint8_t> tbuf;
244*782d6eedSFreddieJheng std::vector<uint8_t> rbuf;
245*782d6eedSFreddieJheng
246*782d6eedSFreddieJheng tbuf = buildByteVector(PMBusCmd::page, MPSPage::page0);
247*782d6eedSFreddieJheng if (!i2cInterface.sendReceive(tbuf, rbuf))
248*782d6eedSFreddieJheng {
249*782d6eedSFreddieJheng error("Failed to set page 0 for MTP store");
250*782d6eedSFreddieJheng co_return false;
251*782d6eedSFreddieJheng }
252*782d6eedSFreddieJheng
253*782d6eedSFreddieJheng tbuf = buildByteVector(PMBusCmd::storeUserCode);
254*782d6eedSFreddieJheng if (!i2cInterface.sendReceive(tbuf, rbuf))
255*782d6eedSFreddieJheng {
256*782d6eedSFreddieJheng error("Failed to send STORE_USER_ALL command");
257*782d6eedSFreddieJheng co_return false;
258*782d6eedSFreddieJheng }
259*782d6eedSFreddieJheng
260*782d6eedSFreddieJheng co_return true;
261*782d6eedSFreddieJheng }
262*782d6eedSFreddieJheng
waitForMTPComplete()263*782d6eedSFreddieJheng sdbusplus::async::task<bool> MP5998::waitForMTPComplete()
264*782d6eedSFreddieJheng {
265*782d6eedSFreddieJheng constexpr uint16_t mtpStoreWaitmS = 1200;
266*782d6eedSFreddieJheng co_await sdbusplus::async::sleep_for(
267*782d6eedSFreddieJheng ctx, std::chrono::milliseconds(mtpStoreWaitmS));
268*782d6eedSFreddieJheng std::vector<uint8_t> tbuf = buildByteVector(PMBusCmd::statusCML);
269*782d6eedSFreddieJheng std::vector<uint8_t> rbuf;
270*782d6eedSFreddieJheng rbuf.resize(statusByteLength);
271*782d6eedSFreddieJheng
272*782d6eedSFreddieJheng if (!i2cInterface.sendReceive(tbuf, rbuf))
273*782d6eedSFreddieJheng {
274*782d6eedSFreddieJheng error("Failed to read STATUS_CML after MTP store");
275*782d6eedSFreddieJheng co_return false;
276*782d6eedSFreddieJheng }
277*782d6eedSFreddieJheng
278*782d6eedSFreddieJheng bool eepromFault = rbuf[0] & eepromFaultBit;
279*782d6eedSFreddieJheng
280*782d6eedSFreddieJheng if (eepromFault)
281*782d6eedSFreddieJheng {
282*782d6eedSFreddieJheng error("EEPROM fault detected after MTP store");
283*782d6eedSFreddieJheng co_return false;
284*782d6eedSFreddieJheng }
285*782d6eedSFreddieJheng
286*782d6eedSFreddieJheng co_return true;
287*782d6eedSFreddieJheng }
288*782d6eedSFreddieJheng
verifyCRC()289*782d6eedSFreddieJheng sdbusplus::async::task<bool> MP5998::verifyCRC()
290*782d6eedSFreddieJheng {
291*782d6eedSFreddieJheng uint32_t deviceCRC{0};
292*782d6eedSFreddieJheng // NOLINTBEGIN(clang-analyzer-core.uninitialized.Branch)
293*782d6eedSFreddieJheng bool getCRCSuccess = co_await getCRC(&deviceCRC);
294*782d6eedSFreddieJheng // NOLINTEND(clang-analyzer-core.uninitialized.Branch)
295*782d6eedSFreddieJheng if (!getCRCSuccess)
296*782d6eedSFreddieJheng {
297*782d6eedSFreddieJheng error("Failed to read CRC from device");
298*782d6eedSFreddieJheng co_return false;
299*782d6eedSFreddieJheng }
300*782d6eedSFreddieJheng
301*782d6eedSFreddieJheng bool crcMatch = (deviceCRC == configuration->crcUser);
302*782d6eedSFreddieJheng
303*782d6eedSFreddieJheng co_return crcMatch;
304*782d6eedSFreddieJheng }
305*782d6eedSFreddieJheng
getCRC(uint32_t * checksum)306*782d6eedSFreddieJheng sdbusplus::async::task<bool> MP5998::getCRC(uint32_t* checksum)
307*782d6eedSFreddieJheng {
308*782d6eedSFreddieJheng constexpr size_t crcLength = 2;
309*782d6eedSFreddieJheng
310*782d6eedSFreddieJheng std::vector<uint8_t> tbuf;
311*782d6eedSFreddieJheng std::vector<uint8_t> rbuf;
312*782d6eedSFreddieJheng
313*782d6eedSFreddieJheng tbuf = buildByteVector(PMBusCmd::page, MPSPage::page0);
314*782d6eedSFreddieJheng if (!i2cInterface.sendReceive(tbuf, rbuf))
315*782d6eedSFreddieJheng {
316*782d6eedSFreddieJheng error("Failed to set page 0 for CRC read");
317*782d6eedSFreddieJheng co_return false;
318*782d6eedSFreddieJheng }
319*782d6eedSFreddieJheng
320*782d6eedSFreddieJheng tbuf = buildByteVector(MP5998Cmd::crcUser);
321*782d6eedSFreddieJheng rbuf.resize(crcLength);
322*782d6eedSFreddieJheng if (!i2cInterface.sendReceive(tbuf, rbuf))
323*782d6eedSFreddieJheng {
324*782d6eedSFreddieJheng error("Failed to read CRC_USER register");
325*782d6eedSFreddieJheng co_return false;
326*782d6eedSFreddieJheng }
327*782d6eedSFreddieJheng
328*782d6eedSFreddieJheng *checksum = bytesToInt<uint32_t>(rbuf);
329*782d6eedSFreddieJheng
330*782d6eedSFreddieJheng co_return true;
331*782d6eedSFreddieJheng }
332*782d6eedSFreddieJheng
sendRestoreMTPCommand()333*782d6eedSFreddieJheng sdbusplus::async::task<bool> MP5998::sendRestoreMTPCommand()
334*782d6eedSFreddieJheng {
335*782d6eedSFreddieJheng std::vector<uint8_t> tbuf;
336*782d6eedSFreddieJheng std::vector<uint8_t> rbuf;
337*782d6eedSFreddieJheng
338*782d6eedSFreddieJheng tbuf = buildByteVector(PMBusCmd::page, MPSPage::page0);
339*782d6eedSFreddieJheng if (!i2cInterface.sendReceive(tbuf, rbuf))
340*782d6eedSFreddieJheng {
341*782d6eedSFreddieJheng error("Failed to set page 0 for MTP restore");
342*782d6eedSFreddieJheng co_return false;
343*782d6eedSFreddieJheng }
344*782d6eedSFreddieJheng
345*782d6eedSFreddieJheng tbuf = buildByteVector(PMBusCmd::restoreUserAll);
346*782d6eedSFreddieJheng if (!i2cInterface.sendReceive(tbuf, rbuf))
347*782d6eedSFreddieJheng {
348*782d6eedSFreddieJheng error("Failed to send RESTORE_ALL command");
349*782d6eedSFreddieJheng co_return false;
350*782d6eedSFreddieJheng }
351*782d6eedSFreddieJheng
352*782d6eedSFreddieJheng co_return true;
353*782d6eedSFreddieJheng }
354*782d6eedSFreddieJheng
checkEEPROMFaultAfterRestore()355*782d6eedSFreddieJheng sdbusplus::async::task<bool> MP5998::checkEEPROMFaultAfterRestore()
356*782d6eedSFreddieJheng {
357*782d6eedSFreddieJheng std::vector<uint8_t> tbuf;
358*782d6eedSFreddieJheng std::vector<uint8_t> rbuf;
359*782d6eedSFreddieJheng
360*782d6eedSFreddieJheng tbuf = buildByteVector(PMBusCmd::page, MPSPage::page0);
361*782d6eedSFreddieJheng if (!i2cInterface.sendReceive(tbuf, rbuf))
362*782d6eedSFreddieJheng {
363*782d6eedSFreddieJheng error("Failed to set page 0 for EEPROM fault check");
364*782d6eedSFreddieJheng co_return false;
365*782d6eedSFreddieJheng }
366*782d6eedSFreddieJheng
367*782d6eedSFreddieJheng tbuf = buildByteVector(PMBusCmd::statusCML);
368*782d6eedSFreddieJheng rbuf.resize(1);
369*782d6eedSFreddieJheng if (!i2cInterface.sendReceive(tbuf, rbuf))
370*782d6eedSFreddieJheng {
371*782d6eedSFreddieJheng error("Failed to read STATUS_CML register");
372*782d6eedSFreddieJheng co_return false;
373*782d6eedSFreddieJheng }
374*782d6eedSFreddieJheng
375*782d6eedSFreddieJheng bool eepromFault = (rbuf[0] & eepromFaultBit) != 0;
376*782d6eedSFreddieJheng
377*782d6eedSFreddieJheng co_return !eepromFault;
378*782d6eedSFreddieJheng }
379*782d6eedSFreddieJheng
restoreMTPAndVerify()380*782d6eedSFreddieJheng sdbusplus::async::task<bool> MP5998::restoreMTPAndVerify()
381*782d6eedSFreddieJheng {
382*782d6eedSFreddieJheng constexpr uint16_t mtpRestoreWait = 1600;
383*782d6eedSFreddieJheng
384*782d6eedSFreddieJheng if (!co_await sendRestoreMTPCommand())
385*782d6eedSFreddieJheng {
386*782d6eedSFreddieJheng error("Failed to send RESTORE_ALL command");
387*782d6eedSFreddieJheng co_return false;
388*782d6eedSFreddieJheng }
389*782d6eedSFreddieJheng
390*782d6eedSFreddieJheng co_await sdbusplus::async::sleep_for(
391*782d6eedSFreddieJheng ctx, std::chrono::microseconds(mtpRestoreWait));
392*782d6eedSFreddieJheng if (!co_await checkEEPROMFaultAfterRestore())
393*782d6eedSFreddieJheng {
394*782d6eedSFreddieJheng error("EEPROM fault detected after MTP restore");
395*782d6eedSFreddieJheng co_return false;
396*782d6eedSFreddieJheng }
397*782d6eedSFreddieJheng
398*782d6eedSFreddieJheng co_return true;
399*782d6eedSFreddieJheng }
400*782d6eedSFreddieJheng
forcedUpdateAllowed()401*782d6eedSFreddieJheng bool MP5998::forcedUpdateAllowed()
402*782d6eedSFreddieJheng {
403*782d6eedSFreddieJheng return true;
404*782d6eedSFreddieJheng }
405*782d6eedSFreddieJheng
updateFirmware(bool force)406*782d6eedSFreddieJheng sdbusplus::async::task<bool> MP5998::updateFirmware(bool force)
407*782d6eedSFreddieJheng {
408*782d6eedSFreddieJheng (void)force;
409*782d6eedSFreddieJheng
410*782d6eedSFreddieJheng if (!co_await checkId(PMBusCmd::mfrId, configuration->vendorId))
411*782d6eedSFreddieJheng {
412*782d6eedSFreddieJheng co_return false;
413*782d6eedSFreddieJheng }
414*782d6eedSFreddieJheng
415*782d6eedSFreddieJheng if (!co_await checkId(PMBusCmd::mfrModel, configuration->productId))
416*782d6eedSFreddieJheng {
417*782d6eedSFreddieJheng co_return false;
418*782d6eedSFreddieJheng }
419*782d6eedSFreddieJheng
420*782d6eedSFreddieJheng if (!co_await unlockWriteProtection())
421*782d6eedSFreddieJheng {
422*782d6eedSFreddieJheng co_return false;
423*782d6eedSFreddieJheng }
424*782d6eedSFreddieJheng
425*782d6eedSFreddieJheng if (!co_await programAllRegisters())
426*782d6eedSFreddieJheng {
427*782d6eedSFreddieJheng co_return false;
428*782d6eedSFreddieJheng }
429*782d6eedSFreddieJheng
430*782d6eedSFreddieJheng if (!co_await storeMTP())
431*782d6eedSFreddieJheng {
432*782d6eedSFreddieJheng co_return false;
433*782d6eedSFreddieJheng }
434*782d6eedSFreddieJheng
435*782d6eedSFreddieJheng if (!co_await waitForMTPComplete())
436*782d6eedSFreddieJheng {
437*782d6eedSFreddieJheng co_return false;
438*782d6eedSFreddieJheng }
439*782d6eedSFreddieJheng
440*782d6eedSFreddieJheng if (!co_await verifyCRC())
441*782d6eedSFreddieJheng {
442*782d6eedSFreddieJheng co_return false;
443*782d6eedSFreddieJheng }
444*782d6eedSFreddieJheng
445*782d6eedSFreddieJheng if (!co_await restoreMTPAndVerify())
446*782d6eedSFreddieJheng {
447*782d6eedSFreddieJheng co_return false;
448*782d6eedSFreddieJheng }
449*782d6eedSFreddieJheng
450*782d6eedSFreddieJheng co_return true;
451*782d6eedSFreddieJheng }
452*782d6eedSFreddieJheng
453*782d6eedSFreddieJheng } // namespace phosphor::software::VR
454