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