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