xref: /openbmc/phosphor-bmc-code-mgmt/cpld/lattice/lattice_base_cpld.hpp (revision b602aad5026847e2a4895598c6b5b7b08a377282)
1*b602aad5SDaniel Hsu #pragma once
2*b602aad5SDaniel Hsu #include "common/include/i2c/i2c.hpp"
3*b602aad5SDaniel Hsu 
4*b602aad5SDaniel Hsu #include <phosphor-logging/lg2.hpp>
5*b602aad5SDaniel Hsu 
6*b602aad5SDaniel Hsu #include <chrono>
7*b602aad5SDaniel Hsu #include <iostream>
8*b602aad5SDaniel Hsu #include <string_view>
9*b602aad5SDaniel Hsu #include <unordered_map>
10*b602aad5SDaniel Hsu #include <utility>
11*b602aad5SDaniel Hsu 
12*b602aad5SDaniel Hsu namespace phosphor::software::cpld
13*b602aad5SDaniel Hsu {
14*b602aad5SDaniel Hsu 
15*b602aad5SDaniel Hsu enum class latticeChip
16*b602aad5SDaniel Hsu {
17*b602aad5SDaniel Hsu     LCMXO2_4000HC,
18*b602aad5SDaniel Hsu     LCMXO3LF_2100C,
19*b602aad5SDaniel Hsu     LCMXO3LF_4300C,
20*b602aad5SDaniel Hsu     LCMXO3D_4300,
21*b602aad5SDaniel Hsu     LCMXO3D_9400,
22*b602aad5SDaniel Hsu     UNSUPPORTED = -1,
23*b602aad5SDaniel Hsu };
24*b602aad5SDaniel Hsu 
25*b602aad5SDaniel Hsu enum class latticeStringType
26*b602aad5SDaniel Hsu {
27*b602aad5SDaniel Hsu     typeString,
28*b602aad5SDaniel Hsu     modelString,
29*b602aad5SDaniel Hsu };
30*b602aad5SDaniel Hsu 
31*b602aad5SDaniel Hsu inline std::string getLatticeChipStr(latticeChip chip,
32*b602aad5SDaniel Hsu                                      latticeStringType stringType)
33*b602aad5SDaniel Hsu {
34*b602aad5SDaniel Hsu     static const std::unordered_map<latticeChip, std::string> chipStringMap = {
35*b602aad5SDaniel Hsu         {latticeChip::LCMXO2_4000HC, "LCMXO2_4000HC"},
36*b602aad5SDaniel Hsu         {latticeChip::LCMXO3LF_2100C, "LCMXO3LF_2100C"},
37*b602aad5SDaniel Hsu         {latticeChip::LCMXO3LF_4300C, "LCMXO3LF_4300C"},
38*b602aad5SDaniel Hsu         {latticeChip::LCMXO3D_4300, "LCMXO3D_4300"},
39*b602aad5SDaniel Hsu         {latticeChip::LCMXO3D_9400, "LCMXO3D_9400"},
40*b602aad5SDaniel Hsu     };
41*b602aad5SDaniel Hsu     auto chipString = chipStringMap.at(chip);
42*b602aad5SDaniel Hsu     if (chipStringMap.find(chip) == chipStringMap.end())
43*b602aad5SDaniel Hsu     {
44*b602aad5SDaniel Hsu         lg2::error("Unsupported chip enum: {CHIPENUM}", "CHIPENUM", chip);
45*b602aad5SDaniel Hsu         return "";
46*b602aad5SDaniel Hsu     }
47*b602aad5SDaniel Hsu 
48*b602aad5SDaniel Hsu     switch (stringType)
49*b602aad5SDaniel Hsu     {
50*b602aad5SDaniel Hsu         case latticeStringType::typeString:
51*b602aad5SDaniel Hsu             return std::string("Lattice" + chipString + "Firmware");
52*b602aad5SDaniel Hsu         case latticeStringType::modelString:
53*b602aad5SDaniel Hsu             std::replace(chipString.begin(), chipString.end(), '_', '-');
54*b602aad5SDaniel Hsu             return chipString;
55*b602aad5SDaniel Hsu         default:
56*b602aad5SDaniel Hsu             lg2::error("Unsupported string type: {STRINGTYPE}", "STRINGTYPE",
57*b602aad5SDaniel Hsu                        stringType);
58*b602aad5SDaniel Hsu             return "";
59*b602aad5SDaniel Hsu     }
60*b602aad5SDaniel Hsu };
61*b602aad5SDaniel Hsu 
62*b602aad5SDaniel Hsu enum class latticeChipFamily
63*b602aad5SDaniel Hsu {
64*b602aad5SDaniel Hsu     XO2,
65*b602aad5SDaniel Hsu     XO3,
66*b602aad5SDaniel Hsu };
67*b602aad5SDaniel Hsu 
68*b602aad5SDaniel Hsu struct cpldInfo
69*b602aad5SDaniel Hsu {
70*b602aad5SDaniel Hsu     latticeChipFamily chipFamily;
71*b602aad5SDaniel Hsu     std::vector<uint8_t> deviceId;
72*b602aad5SDaniel Hsu };
73*b602aad5SDaniel Hsu 
74*b602aad5SDaniel Hsu const std::map<latticeChip, cpldInfo> supportedDeviceMap = {
75*b602aad5SDaniel Hsu     {latticeChip::LCMXO2_4000HC,
76*b602aad5SDaniel Hsu      {latticeChipFamily::XO2, {0x01, 0x2b, 0xc0, 0x43}}},
77*b602aad5SDaniel Hsu     {latticeChip::LCMXO3LF_2100C,
78*b602aad5SDaniel Hsu      {latticeChipFamily::XO3, {0x61, 0x2b, 0xb0, 0x43}}},
79*b602aad5SDaniel Hsu     {latticeChip::LCMXO3LF_4300C,
80*b602aad5SDaniel Hsu      {latticeChipFamily::XO3, {0x61, 0x2b, 0xc0, 0x43}}},
81*b602aad5SDaniel Hsu     {latticeChip::LCMXO3D_4300,
82*b602aad5SDaniel Hsu      {latticeChipFamily::XO3, {0x01, 0x2e, 0x20, 0x43}}},
83*b602aad5SDaniel Hsu     {latticeChip::LCMXO3D_9400,
84*b602aad5SDaniel Hsu      {latticeChipFamily::XO3, {0x21, 0x2e, 0x30, 0x43}}},
85*b602aad5SDaniel Hsu };
86*b602aad5SDaniel Hsu 
87*b602aad5SDaniel Hsu struct cpldI2cInfo
88*b602aad5SDaniel Hsu {
89*b602aad5SDaniel Hsu     unsigned long int fuseQuantity;
90*b602aad5SDaniel Hsu     unsigned int* userFlashMemory;
91*b602aad5SDaniel Hsu     unsigned int version;
92*b602aad5SDaniel Hsu     unsigned int checksum;
93*b602aad5SDaniel Hsu     std::vector<uint8_t> cfgData;
94*b602aad5SDaniel Hsu     std::vector<uint8_t> ufmData;
95*b602aad5SDaniel Hsu };
96*b602aad5SDaniel Hsu 
97*b602aad5SDaniel Hsu enum cpldI2cCmd
98*b602aad5SDaniel Hsu {
99*b602aad5SDaniel Hsu     commandEraseFlash = 0x0E,
100*b602aad5SDaniel Hsu     commandDisableConfigInterface = 0x26,
101*b602aad5SDaniel Hsu     commandReadStatusReg = 0x3C,
102*b602aad5SDaniel Hsu     commandResetConfigFlash = 0x46,
103*b602aad5SDaniel Hsu     commandProgramDone = 0x5E,
104*b602aad5SDaniel Hsu     commandProgramPage = 0x70,
105*b602aad5SDaniel Hsu     commandReadPage = 0x73,
106*b602aad5SDaniel Hsu     commandEnableConfigMode = 0x74,
107*b602aad5SDaniel Hsu     commandSetPageAddress = 0xB4,
108*b602aad5SDaniel Hsu     commandReadFwVersion = 0xC0,
109*b602aad5SDaniel Hsu     commandProgramUserCode = 0xC2,
110*b602aad5SDaniel Hsu     commandReadDeviceId = 0xE0,
111*b602aad5SDaniel Hsu     commandReadBusyFlag = 0xF0,
112*b602aad5SDaniel Hsu };
113*b602aad5SDaniel Hsu 
114*b602aad5SDaniel Hsu constexpr std::chrono::milliseconds waitBusyTime(200);
115*b602aad5SDaniel Hsu 
116*b602aad5SDaniel Hsu class LatticeBaseCPLD
117*b602aad5SDaniel Hsu {
118*b602aad5SDaniel Hsu   public:
119*b602aad5SDaniel Hsu     LatticeBaseCPLD(sdbusplus::async::context& ctx, const uint16_t bus,
120*b602aad5SDaniel Hsu                     const uint8_t address, const std::string& chip,
121*b602aad5SDaniel Hsu                     const std::string& target, const bool debugMode) :
122*b602aad5SDaniel Hsu         ctx(ctx), chip(chip), target(target), debugMode(debugMode),
123*b602aad5SDaniel Hsu         i2cInterface(phosphor::i2c::I2C(bus, address))
124*b602aad5SDaniel Hsu     {}
125*b602aad5SDaniel Hsu     virtual ~LatticeBaseCPLD() = default;
126*b602aad5SDaniel Hsu     LatticeBaseCPLD(const LatticeBaseCPLD&) = delete;
127*b602aad5SDaniel Hsu     LatticeBaseCPLD& operator=(const LatticeBaseCPLD&) = delete;
128*b602aad5SDaniel Hsu     LatticeBaseCPLD(LatticeBaseCPLD&&) noexcept = delete;
129*b602aad5SDaniel Hsu     LatticeBaseCPLD& operator=(LatticeBaseCPLD&&) noexcept = delete;
130*b602aad5SDaniel Hsu 
131*b602aad5SDaniel Hsu     sdbusplus::async::task<bool> updateFirmware(
132*b602aad5SDaniel Hsu         const uint8_t* image, size_t imageSize,
133*b602aad5SDaniel Hsu         std::function<bool(int)> progressCallBack);
134*b602aad5SDaniel Hsu 
135*b602aad5SDaniel Hsu     sdbusplus::async::task<bool> getVersion(std::string& version);
136*b602aad5SDaniel Hsu 
137*b602aad5SDaniel Hsu   protected:
138*b602aad5SDaniel Hsu     sdbusplus::async::context& ctx;
139*b602aad5SDaniel Hsu     cpldI2cInfo fwInfo{};
140*b602aad5SDaniel Hsu     std::string chip;
141*b602aad5SDaniel Hsu     std::string target;
142*b602aad5SDaniel Hsu     std::vector<uint8_t> sumOnly;
143*b602aad5SDaniel Hsu     bool isLCMXO3D = false;
144*b602aad5SDaniel Hsu     bool debugMode = false;
145*b602aad5SDaniel Hsu     phosphor::i2c::I2C i2cInterface;
146*b602aad5SDaniel Hsu 
147*b602aad5SDaniel Hsu     virtual sdbusplus::async::task<bool> prepareUpdate(const uint8_t*,
148*b602aad5SDaniel Hsu                                                        size_t) = 0;
149*b602aad5SDaniel Hsu     virtual sdbusplus::async::task<bool> doUpdate() = 0;
150*b602aad5SDaniel Hsu     virtual sdbusplus::async::task<bool> finishUpdate() = 0;
151*b602aad5SDaniel Hsu 
152*b602aad5SDaniel Hsu     bool jedFileParser(const uint8_t* image, size_t imageSize);
153*b602aad5SDaniel Hsu     bool verifyChecksum();
154*b602aad5SDaniel Hsu     sdbusplus::async::task<bool> enableProgramMode();
155*b602aad5SDaniel Hsu     sdbusplus::async::task<bool> resetConfigFlash();
156*b602aad5SDaniel Hsu     sdbusplus::async::task<bool> programDone();
157*b602aad5SDaniel Hsu     sdbusplus::async::task<bool> disableConfigInterface();
158*b602aad5SDaniel Hsu     sdbusplus::async::task<bool> waitBusyAndVerify();
159*b602aad5SDaniel Hsu 
160*b602aad5SDaniel Hsu   private:
161*b602aad5SDaniel Hsu     virtual sdbusplus::async::task<bool> readUserCode(uint32_t&) = 0;
162*b602aad5SDaniel Hsu     sdbusplus::async::task<bool> readBusyFlag(uint8_t& busyFlag);
163*b602aad5SDaniel Hsu     sdbusplus::async::task<bool> readStatusReg(uint8_t& statusReg);
164*b602aad5SDaniel Hsu     static std::string uint32ToHexStr(uint32_t value);
165*b602aad5SDaniel Hsu };
166*b602aad5SDaniel Hsu 
167*b602aad5SDaniel Hsu } // namespace phosphor::software::cpld
168