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