1*dcf4b607SKevin Tung #include "mp2x6xx.hpp"
2*dcf4b607SKevin Tung
3*dcf4b607SKevin Tung #include "common/include/utils.hpp"
4*dcf4b607SKevin Tung
5*dcf4b607SKevin Tung #include <phosphor-logging/lg2.hpp>
6*dcf4b607SKevin Tung
7*dcf4b607SKevin Tung PHOSPHOR_LOG2_USING;
8*dcf4b607SKevin Tung
9*dcf4b607SKevin Tung namespace phosphor::software::VR
10*dcf4b607SKevin Tung {
11*dcf4b607SKevin Tung
12*dcf4b607SKevin Tung static constexpr size_t vendorIdLength = 3;
13*dcf4b607SKevin Tung static constexpr size_t deviceIdLength = 4;
14*dcf4b607SKevin Tung static constexpr size_t configIdLength = 2;
15*dcf4b607SKevin Tung static constexpr size_t statusByteLength = 1;
16*dcf4b607SKevin Tung static constexpr size_t crcLength = 2;
17*dcf4b607SKevin Tung
18*dcf4b607SKevin Tung static constexpr std::string_view productIdRegName = "TRIM_MFR_PRODUCT_ID2";
19*dcf4b607SKevin Tung static constexpr std::string_view crcUserRegName = "CRC_USER";
20*dcf4b607SKevin Tung
21*dcf4b607SKevin Tung static constexpr uint8_t pageMask = 0x0F;
22*dcf4b607SKevin Tung static constexpr uint8_t configMask = 0xF0;
23*dcf4b607SKevin Tung
24*dcf4b607SKevin Tung static constexpr uint8_t disableWriteProtect = 0x00;
25*dcf4b607SKevin Tung static constexpr uint16_t disablePage2WriteProtect = 0x128C;
26*dcf4b607SKevin Tung static constexpr uint16_t disablePage3WriteProtect = 0x0082;
27*dcf4b607SKevin Tung
28*dcf4b607SKevin Tung enum class MP2X6XXCmd : uint8_t
29*dcf4b607SKevin Tung {
30*dcf4b607SKevin Tung // Page 0 commands
31*dcf4b607SKevin Tung readCRCReg = 0xED,
32*dcf4b607SKevin Tung // Page 1 commands
33*dcf4b607SKevin Tung mfrMTPMemoryCtrl = 0xCC,
34*dcf4b607SKevin Tung // Page 2 commands
35*dcf4b607SKevin Tung selectConfigCtrl = 0x1A,
36*dcf4b607SKevin Tung // Page 3 commands
37*dcf4b607SKevin Tung mfrMTPMemoryCtrlPage3 = 0x81,
38*dcf4b607SKevin Tung };
39*dcf4b607SKevin Tung
parseDeviceConfiguration()40*dcf4b607SKevin Tung sdbusplus::async::task<bool> MP2X6XX::parseDeviceConfiguration()
41*dcf4b607SKevin Tung {
42*dcf4b607SKevin Tung if (!configuration)
43*dcf4b607SKevin Tung {
44*dcf4b607SKevin Tung error("Device configuration not initialized");
45*dcf4b607SKevin Tung co_return false;
46*dcf4b607SKevin Tung }
47*dcf4b607SKevin Tung
48*dcf4b607SKevin Tung configuration->vendorId = 0x4D5053;
49*dcf4b607SKevin Tung
50*dcf4b607SKevin Tung for (const auto& tokens : parser->lineTokens)
51*dcf4b607SKevin Tung {
52*dcf4b607SKevin Tung if (!parser->isValidDataTokens(tokens))
53*dcf4b607SKevin Tung {
54*dcf4b607SKevin Tung continue;
55*dcf4b607SKevin Tung }
56*dcf4b607SKevin Tung
57*dcf4b607SKevin Tung auto regName = parser->getVal<std::string>(tokens, ATE::regName);
58*dcf4b607SKevin Tung if (regName == productIdRegName)
59*dcf4b607SKevin Tung {
60*dcf4b607SKevin Tung configuration->productId =
61*dcf4b607SKevin Tung parser->getVal<uint32_t>(tokens, ATE::regDataHex);
62*dcf4b607SKevin Tung configuration->configId =
63*dcf4b607SKevin Tung parser->getVal<uint32_t>(tokens, ATE::configId);
64*dcf4b607SKevin Tung }
65*dcf4b607SKevin Tung else if (regName == crcUserRegName)
66*dcf4b607SKevin Tung {
67*dcf4b607SKevin Tung configuration->crcUser =
68*dcf4b607SKevin Tung parser->getVal<uint32_t>(tokens, ATE::regDataHex);
69*dcf4b607SKevin Tung break;
70*dcf4b607SKevin Tung }
71*dcf4b607SKevin Tung }
72*dcf4b607SKevin Tung
73*dcf4b607SKevin Tung co_return true;
74*dcf4b607SKevin Tung }
75*dcf4b607SKevin Tung
verifyImage(const uint8_t * image,size_t imageSize)76*dcf4b607SKevin Tung sdbusplus::async::task<bool> MP2X6XX::verifyImage(const uint8_t* image,
77*dcf4b607SKevin Tung size_t imageSize)
78*dcf4b607SKevin Tung {
79*dcf4b607SKevin Tung if (!co_await parseImage(image, imageSize))
80*dcf4b607SKevin Tung {
81*dcf4b607SKevin Tung error("Image verification failed: image parsing failed");
82*dcf4b607SKevin Tung co_return false;
83*dcf4b607SKevin Tung }
84*dcf4b607SKevin Tung
85*dcf4b607SKevin Tung if (configuration->registersData.empty())
86*dcf4b607SKevin Tung {
87*dcf4b607SKevin Tung error("Image verification failed - no data found");
88*dcf4b607SKevin Tung co_return false;
89*dcf4b607SKevin Tung }
90*dcf4b607SKevin Tung
91*dcf4b607SKevin Tung if (configuration->productId == 0 || configuration->configId == 0)
92*dcf4b607SKevin Tung {
93*dcf4b607SKevin Tung error("Image verification failed - missing product or config ID");
94*dcf4b607SKevin Tung co_return false;
95*dcf4b607SKevin Tung }
96*dcf4b607SKevin Tung
97*dcf4b607SKevin Tung co_return true;
98*dcf4b607SKevin Tung }
99*dcf4b607SKevin Tung
checkId(PMBusCmd pmBusCmd,uint32_t expected)100*dcf4b607SKevin Tung sdbusplus::async::task<bool> MP2X6XX::checkId(PMBusCmd pmBusCmd,
101*dcf4b607SKevin Tung uint32_t expected)
102*dcf4b607SKevin Tung {
103*dcf4b607SKevin Tung const uint8_t cmd = static_cast<uint8_t>(pmBusCmd);
104*dcf4b607SKevin Tung size_t idLen = 0;
105*dcf4b607SKevin Tung bool blockRead = false;
106*dcf4b607SKevin Tung
107*dcf4b607SKevin Tung switch (pmBusCmd)
108*dcf4b607SKevin Tung {
109*dcf4b607SKevin Tung case PMBusCmd::mfrId:
110*dcf4b607SKevin Tung idLen = vendorIdLength;
111*dcf4b607SKevin Tung blockRead = true;
112*dcf4b607SKevin Tung break;
113*dcf4b607SKevin Tung case PMBusCmd::icDeviceId:
114*dcf4b607SKevin Tung idLen = deviceIdLength;
115*dcf4b607SKevin Tung blockRead = true;
116*dcf4b607SKevin Tung break;
117*dcf4b607SKevin Tung case PMBusCmd::mfrSerial:
118*dcf4b607SKevin Tung idLen = configIdLength;
119*dcf4b607SKevin Tung break;
120*dcf4b607SKevin Tung default:
121*dcf4b607SKevin Tung error("Invalid command for ID check: {CMD}", "CMD", lg2::hex, cmd);
122*dcf4b607SKevin Tung co_return false;
123*dcf4b607SKevin Tung }
124*dcf4b607SKevin Tung
125*dcf4b607SKevin Tung std::vector<uint8_t> rbuf;
126*dcf4b607SKevin Tung std::vector<uint8_t> tbuf;
127*dcf4b607SKevin Tung
128*dcf4b607SKevin Tung tbuf = buildByteVector(PMBusCmd::page, MPSPage::page0);
129*dcf4b607SKevin Tung if (!i2cInterface.sendReceive(tbuf, rbuf))
130*dcf4b607SKevin Tung {
131*dcf4b607SKevin Tung error("Failed to set page 0 for ID check");
132*dcf4b607SKevin Tung co_return false;
133*dcf4b607SKevin Tung }
134*dcf4b607SKevin Tung
135*dcf4b607SKevin Tung tbuf = {cmd};
136*dcf4b607SKevin Tung rbuf.resize(idLen + (blockRead ? statusByteLength : 0));
137*dcf4b607SKevin Tung
138*dcf4b607SKevin Tung if (!i2cInterface.sendReceive(tbuf, rbuf))
139*dcf4b607SKevin Tung {
140*dcf4b607SKevin Tung error("I2C failure during ID check, cmd {CMD}", "CMD", lg2::hex, cmd);
141*dcf4b607SKevin Tung co_return false;
142*dcf4b607SKevin Tung }
143*dcf4b607SKevin Tung
144*dcf4b607SKevin Tung auto idBytes = std::span(rbuf).subspan(blockRead ? statusByteLength : 0);
145*dcf4b607SKevin Tung uint32_t id = bytesToInt<uint32_t>(idBytes);
146*dcf4b607SKevin Tung
147*dcf4b607SKevin Tung if (id != expected)
148*dcf4b607SKevin Tung {
149*dcf4b607SKevin Tung error("ID check failed for cmd {CMD}: got {ID}, expected {EXP}", "CMD",
150*dcf4b607SKevin Tung lg2::hex, cmd, "ID", lg2::hex, id, "EXP", lg2::hex, expected);
151*dcf4b607SKevin Tung co_return false;
152*dcf4b607SKevin Tung }
153*dcf4b607SKevin Tung
154*dcf4b607SKevin Tung co_return true;
155*dcf4b607SKevin Tung }
156*dcf4b607SKevin Tung
unlockWriteProtect()157*dcf4b607SKevin Tung sdbusplus::async::task<bool> MP2X6XX::unlockWriteProtect()
158*dcf4b607SKevin Tung {
159*dcf4b607SKevin Tung std::vector<uint8_t> tbuf;
160*dcf4b607SKevin Tung std::vector<uint8_t> rbuf;
161*dcf4b607SKevin Tung
162*dcf4b607SKevin Tung tbuf = buildByteVector(PMBusCmd::page, MPSPage::page0);
163*dcf4b607SKevin Tung if (!i2cInterface.sendReceive(tbuf, rbuf))
164*dcf4b607SKevin Tung {
165*dcf4b607SKevin Tung error("Failed to set page 0 for unlocking write protect");
166*dcf4b607SKevin Tung co_return false;
167*dcf4b607SKevin Tung }
168*dcf4b607SKevin Tung
169*dcf4b607SKevin Tung tbuf = buildByteVector(PMBusCmd::writeProtect, disableWriteProtect);
170*dcf4b607SKevin Tung if (!i2cInterface.sendReceive(tbuf, rbuf))
171*dcf4b607SKevin Tung {
172*dcf4b607SKevin Tung error("Failed to disable write protect");
173*dcf4b607SKevin Tung co_return false;
174*dcf4b607SKevin Tung }
175*dcf4b607SKevin Tung
176*dcf4b607SKevin Tung // unlock page 2 write protect
177*dcf4b607SKevin Tung tbuf = buildByteVector(PMBusCmd::page, MPSPage::page1);
178*dcf4b607SKevin Tung if (!i2cInterface.sendReceive(tbuf, rbuf))
179*dcf4b607SKevin Tung {
180*dcf4b607SKevin Tung error("Failed to set page 1 for unlocking write protect for page 2");
181*dcf4b607SKevin Tung co_return false;
182*dcf4b607SKevin Tung }
183*dcf4b607SKevin Tung
184*dcf4b607SKevin Tung tbuf =
185*dcf4b607SKevin Tung buildByteVector(MP2X6XXCmd::mfrMTPMemoryCtrl, disablePage2WriteProtect);
186*dcf4b607SKevin Tung if (!i2cInterface.sendReceive(tbuf, rbuf))
187*dcf4b607SKevin Tung {
188*dcf4b607SKevin Tung error("Failed to unlock page 2 write protect");
189*dcf4b607SKevin Tung co_return false;
190*dcf4b607SKevin Tung }
191*dcf4b607SKevin Tung
192*dcf4b607SKevin Tung // unlock page 3 write protect
193*dcf4b607SKevin Tung tbuf = buildByteVector(PMBusCmd::page, MPSPage::page3);
194*dcf4b607SKevin Tung if (!i2cInterface.sendReceive(tbuf, rbuf))
195*dcf4b607SKevin Tung {
196*dcf4b607SKevin Tung error("Failed to set page 3 for unlocking write protect for page 3");
197*dcf4b607SKevin Tung co_return false;
198*dcf4b607SKevin Tung }
199*dcf4b607SKevin Tung
200*dcf4b607SKevin Tung tbuf = buildByteVector(MP2X6XXCmd::mfrMTPMemoryCtrlPage3,
201*dcf4b607SKevin Tung disablePage3WriteProtect);
202*dcf4b607SKevin Tung if (!i2cInterface.sendReceive(tbuf, rbuf))
203*dcf4b607SKevin Tung {
204*dcf4b607SKevin Tung error("Failed to unlock page 3 write protect");
205*dcf4b607SKevin Tung co_return false;
206*dcf4b607SKevin Tung }
207*dcf4b607SKevin Tung
208*dcf4b607SKevin Tung debug("Unlocked write protect");
209*dcf4b607SKevin Tung
210*dcf4b607SKevin Tung co_return true;
211*dcf4b607SKevin Tung }
212*dcf4b607SKevin Tung
selectConfig(uint8_t config)213*dcf4b607SKevin Tung sdbusplus::async::task<bool> MP2X6XX::selectConfig(uint8_t config)
214*dcf4b607SKevin Tung {
215*dcf4b607SKevin Tung // MPS config select command:
216*dcf4b607SKevin Tung // Writes to Page 2 @ 0x1A: value = 0x0F00 | ((config + 7) << 4)
217*dcf4b607SKevin Tung // For config 1–6 → result: 0x0F80 to 0x0FD0
218*dcf4b607SKevin Tung
219*dcf4b607SKevin Tung std::vector<uint8_t> tbuf;
220*dcf4b607SKevin Tung std::vector<uint8_t> rbuf;
221*dcf4b607SKevin Tung
222*dcf4b607SKevin Tung tbuf = buildByteVector(PMBusCmd::page, MPSPage::page2);
223*dcf4b607SKevin Tung if (!i2cInterface.sendReceive(tbuf, rbuf))
224*dcf4b607SKevin Tung {
225*dcf4b607SKevin Tung error("Failed to set page 2 for configuration switch");
226*dcf4b607SKevin Tung co_return false;
227*dcf4b607SKevin Tung }
228*dcf4b607SKevin Tung
229*dcf4b607SKevin Tung constexpr uint8_t baseOffset = 7;
230*dcf4b607SKevin Tung uint8_t encodedNibble = static_cast<uint8_t>((config + baseOffset) << 4);
231*dcf4b607SKevin Tung uint16_t command = 0x0F00 | encodedNibble;
232*dcf4b607SKevin Tung
233*dcf4b607SKevin Tung tbuf = buildByteVector(MP2X6XXCmd::selectConfigCtrl, command);
234*dcf4b607SKevin Tung
235*dcf4b607SKevin Tung if (!i2cInterface.sendReceive(tbuf, rbuf))
236*dcf4b607SKevin Tung {
237*dcf4b607SKevin Tung error("Failed to write config select command {CMD} for config {CONFIG}",
238*dcf4b607SKevin Tung "CMD", lg2::hex, command, "CONFIG", config);
239*dcf4b607SKevin Tung co_return false;
240*dcf4b607SKevin Tung }
241*dcf4b607SKevin Tung
242*dcf4b607SKevin Tung debug("Switched to config {CONFIG}", "CONFIG", config);
243*dcf4b607SKevin Tung co_return true;
244*dcf4b607SKevin Tung }
245*dcf4b607SKevin Tung
programConfigData(const std::vector<MPSData> & gdata)246*dcf4b607SKevin Tung sdbusplus::async::task<bool> MP2X6XX::programConfigData(
247*dcf4b607SKevin Tung const std::vector<MPSData>& gdata)
248*dcf4b607SKevin Tung {
249*dcf4b607SKevin Tung std::vector<uint8_t> tbuf;
250*dcf4b607SKevin Tung std::vector<uint8_t> rbuf;
251*dcf4b607SKevin Tung
252*dcf4b607SKevin Tung for (const auto& data : gdata)
253*dcf4b607SKevin Tung {
254*dcf4b607SKevin Tung uint8_t page = data.page & pageMask;
255*dcf4b607SKevin Tung
256*dcf4b607SKevin Tung tbuf = buildByteVector(PMBusCmd::page, page);
257*dcf4b607SKevin Tung if (!i2cInterface.sendReceive(tbuf, rbuf))
258*dcf4b607SKevin Tung {
259*dcf4b607SKevin Tung error("Failed to set page {PAGE} for register {REG}", "PAGE", page,
260*dcf4b607SKevin Tung "REG", lg2::hex, data.addr);
261*dcf4b607SKevin Tung co_return false;
262*dcf4b607SKevin Tung }
263*dcf4b607SKevin Tung
264*dcf4b607SKevin Tung tbuf = {data.addr};
265*dcf4b607SKevin Tung tbuf.insert(tbuf.end(), data.data.begin(),
266*dcf4b607SKevin Tung data.data.begin() + data.length);
267*dcf4b607SKevin Tung
268*dcf4b607SKevin Tung if (!i2cInterface.sendReceive(tbuf, rbuf))
269*dcf4b607SKevin Tung {
270*dcf4b607SKevin Tung error(
271*dcf4b607SKevin Tung "Failed to write data {DATA} to register {REG} on page {PAGE}",
272*dcf4b607SKevin Tung "DATA", lg2::hex, bytesToInt<uint32_t>(data.data), "REG",
273*dcf4b607SKevin Tung lg2::hex, data.addr, "PAGE", page);
274*dcf4b607SKevin Tung co_return false;
275*dcf4b607SKevin Tung }
276*dcf4b607SKevin Tung }
277*dcf4b607SKevin Tung
278*dcf4b607SKevin Tung if (!co_await storeUserCode())
279*dcf4b607SKevin Tung {
280*dcf4b607SKevin Tung error("Failed to store user code after programming config data");
281*dcf4b607SKevin Tung co_return false;
282*dcf4b607SKevin Tung }
283*dcf4b607SKevin Tung
284*dcf4b607SKevin Tung co_return true;
285*dcf4b607SKevin Tung }
286*dcf4b607SKevin Tung
configAllRegisters()287*dcf4b607SKevin Tung sdbusplus::async::task<bool> MP2X6XX::configAllRegisters()
288*dcf4b607SKevin Tung {
289*dcf4b607SKevin Tung for (const auto& [config, gdata] : getGroupedConfigData(configMask, 4))
290*dcf4b607SKevin Tung {
291*dcf4b607SKevin Tung debug("Configuring registers for config {CONFIG}", "CONFIG", config);
292*dcf4b607SKevin Tung
293*dcf4b607SKevin Tung // Select the appropriate config before programming its registers
294*dcf4b607SKevin Tung if (config > 0 && !co_await selectConfig(config))
295*dcf4b607SKevin Tung {
296*dcf4b607SKevin Tung co_return false;
297*dcf4b607SKevin Tung }
298*dcf4b607SKevin Tung
299*dcf4b607SKevin Tung if (!co_await programConfigData(gdata))
300*dcf4b607SKevin Tung {
301*dcf4b607SKevin Tung error("Failed to program configuration {CONFIG}", "CONFIG", config);
302*dcf4b607SKevin Tung co_return false;
303*dcf4b607SKevin Tung }
304*dcf4b607SKevin Tung
305*dcf4b607SKevin Tung debug("Configured {SIZE} registers for config {CONFIG}", "SIZE",
306*dcf4b607SKevin Tung gdata.size(), "CONFIG", config);
307*dcf4b607SKevin Tung }
308*dcf4b607SKevin Tung
309*dcf4b607SKevin Tung co_return true;
310*dcf4b607SKevin Tung }
311*dcf4b607SKevin Tung
storeUserCode()312*dcf4b607SKevin Tung sdbusplus::async::task<bool> MP2X6XX::storeUserCode()
313*dcf4b607SKevin Tung {
314*dcf4b607SKevin Tung std::vector<uint8_t> tbuf;
315*dcf4b607SKevin Tung std::vector<uint8_t> rbuf;
316*dcf4b607SKevin Tung
317*dcf4b607SKevin Tung tbuf = buildByteVector(PMBusCmd::page, MPSPage::page0);
318*dcf4b607SKevin Tung if (!i2cInterface.sendReceive(tbuf, rbuf))
319*dcf4b607SKevin Tung {
320*dcf4b607SKevin Tung error("Failed to set page 0 for storing user code");
321*dcf4b607SKevin Tung co_return false;
322*dcf4b607SKevin Tung }
323*dcf4b607SKevin Tung
324*dcf4b607SKevin Tung tbuf = buildByteVector(PMBusCmd::storeUserCode);
325*dcf4b607SKevin Tung if (!i2cInterface.sendReceive(tbuf, rbuf))
326*dcf4b607SKevin Tung {
327*dcf4b607SKevin Tung error("Failed to store user code");
328*dcf4b607SKevin Tung co_return false;
329*dcf4b607SKevin Tung }
330*dcf4b607SKevin Tung
331*dcf4b607SKevin Tung // Wait store user code
332*dcf4b607SKevin Tung co_await sdbusplus::async::sleep_for(ctx, std::chrono::milliseconds(500));
333*dcf4b607SKevin Tung
334*dcf4b607SKevin Tung debug("Stored user code");
335*dcf4b607SKevin Tung
336*dcf4b607SKevin Tung co_return true;
337*dcf4b607SKevin Tung }
338*dcf4b607SKevin Tung
getCRC(uint32_t * checksum)339*dcf4b607SKevin Tung sdbusplus::async::task<bool> MP2X6XX::getCRC(uint32_t* checksum)
340*dcf4b607SKevin Tung {
341*dcf4b607SKevin Tung if (checksum == nullptr)
342*dcf4b607SKevin Tung {
343*dcf4b607SKevin Tung error("getCRC() called with null checksum pointer");
344*dcf4b607SKevin Tung co_return false;
345*dcf4b607SKevin Tung }
346*dcf4b607SKevin Tung
347*dcf4b607SKevin Tung std::vector<uint8_t> tbuf;
348*dcf4b607SKevin Tung std::vector<uint8_t> rbuf;
349*dcf4b607SKevin Tung
350*dcf4b607SKevin Tung tbuf = buildByteVector(PMBusCmd::page, MPSPage::page0);
351*dcf4b607SKevin Tung if (!i2cInterface.sendReceive(tbuf, rbuf))
352*dcf4b607SKevin Tung {
353*dcf4b607SKevin Tung error("Failed to set page 0 for CRC read");
354*dcf4b607SKevin Tung co_return false;
355*dcf4b607SKevin Tung }
356*dcf4b607SKevin Tung
357*dcf4b607SKevin Tung tbuf = buildByteVector(MP2X6XXCmd::readCRCReg);
358*dcf4b607SKevin Tung rbuf.resize(crcLength);
359*dcf4b607SKevin Tung if (!i2cInterface.sendReceive(tbuf, rbuf))
360*dcf4b607SKevin Tung {
361*dcf4b607SKevin Tung error("Failed to read CRC from device");
362*dcf4b607SKevin Tung co_return false;
363*dcf4b607SKevin Tung }
364*dcf4b607SKevin Tung
365*dcf4b607SKevin Tung if (rbuf.size() < crcLength)
366*dcf4b607SKevin Tung {
367*dcf4b607SKevin Tung error("CRC read returned insufficient data");
368*dcf4b607SKevin Tung co_return false;
369*dcf4b607SKevin Tung }
370*dcf4b607SKevin Tung
371*dcf4b607SKevin Tung *checksum = bytesToInt<uint32_t>(rbuf);
372*dcf4b607SKevin Tung
373*dcf4b607SKevin Tung debug("Read CRC: {CRC}", "CRC", lg2::hex, *checksum);
374*dcf4b607SKevin Tung
375*dcf4b607SKevin Tung co_return true;
376*dcf4b607SKevin Tung }
377*dcf4b607SKevin Tung
checkMTPCRC()378*dcf4b607SKevin Tung sdbusplus::async::task<bool> MP2X6XX::checkMTPCRC()
379*dcf4b607SKevin Tung {
380*dcf4b607SKevin Tung uint32_t crc = 0;
381*dcf4b607SKevin Tung // NOLINTBEGIN(clang-analyzer-core.uninitialized.Branch)
382*dcf4b607SKevin Tung if (!co_await getCRC(&crc))
383*dcf4b607SKevin Tung // NOLINTEND(clang-analyzer-core.uninitialized.Branch)
384*dcf4b607SKevin Tung {
385*dcf4b607SKevin Tung error("Failed to get CRC for MTP check");
386*dcf4b607SKevin Tung co_return false;
387*dcf4b607SKevin Tung }
388*dcf4b607SKevin Tung
389*dcf4b607SKevin Tung debug("MTP CRC: {CRC}, Expected: {EXP}", "CRC", lg2::hex, crc, "EXP",
390*dcf4b607SKevin Tung lg2::hex, configuration->crcUser);
391*dcf4b607SKevin Tung
392*dcf4b607SKevin Tung co_return configuration->crcUser == crc;
393*dcf4b607SKevin Tung }
394*dcf4b607SKevin Tung
forcedUpdateAllowed()395*dcf4b607SKevin Tung bool MP2X6XX::forcedUpdateAllowed()
396*dcf4b607SKevin Tung {
397*dcf4b607SKevin Tung return true;
398*dcf4b607SKevin Tung }
399*dcf4b607SKevin Tung
updateFirmware(bool force)400*dcf4b607SKevin Tung sdbusplus::async::task<bool> MP2X6XX::updateFirmware(bool force)
401*dcf4b607SKevin Tung {
402*dcf4b607SKevin Tung (void)force;
403*dcf4b607SKevin Tung
404*dcf4b607SKevin Tung if (!co_await checkId(PMBusCmd::mfrId, configuration->vendorId))
405*dcf4b607SKevin Tung {
406*dcf4b607SKevin Tung co_return false;
407*dcf4b607SKevin Tung }
408*dcf4b607SKevin Tung
409*dcf4b607SKevin Tung if (!co_await checkId(PMBusCmd::icDeviceId, configuration->productId))
410*dcf4b607SKevin Tung {
411*dcf4b607SKevin Tung co_return false;
412*dcf4b607SKevin Tung }
413*dcf4b607SKevin Tung
414*dcf4b607SKevin Tung if (!co_await checkId(PMBusCmd::mfrSerial, configuration->configId))
415*dcf4b607SKevin Tung {
416*dcf4b607SKevin Tung co_return false;
417*dcf4b607SKevin Tung }
418*dcf4b607SKevin Tung
419*dcf4b607SKevin Tung if (!co_await unlockWriteProtect())
420*dcf4b607SKevin Tung {
421*dcf4b607SKevin Tung co_return false;
422*dcf4b607SKevin Tung }
423*dcf4b607SKevin Tung
424*dcf4b607SKevin Tung if (!co_await configAllRegisters())
425*dcf4b607SKevin Tung {
426*dcf4b607SKevin Tung co_return false;
427*dcf4b607SKevin Tung }
428*dcf4b607SKevin Tung
429*dcf4b607SKevin Tung if (!(co_await checkMTPCRC()))
430*dcf4b607SKevin Tung {
431*dcf4b607SKevin Tung co_return false;
432*dcf4b607SKevin Tung }
433*dcf4b607SKevin Tung
434*dcf4b607SKevin Tung co_return true;
435*dcf4b607SKevin Tung }
436*dcf4b607SKevin Tung
437*dcf4b607SKevin Tung } // namespace phosphor::software::VR
438