blob: cb45c39f4865edd5de1c403bda22d1f6453f8831 [file] [log] [blame]
Daniel Hsub602aad2025-08-14 10:44:38 +08001#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
12namespace phosphor::software::cpld
13{
14
15enum class latticeChip
16{
17 LCMXO2_4000HC,
18 LCMXO3LF_2100C,
19 LCMXO3LF_4300C,
20 LCMXO3D_4300,
21 LCMXO3D_9400,
22 UNSUPPORTED = -1,
23};
24
25enum class latticeStringType
26{
27 typeString,
28 modelString,
29};
30
31inline 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
62enum class latticeChipFamily
63{
64 XO2,
65 XO3,
66};
67
68struct cpldInfo
69{
70 latticeChipFamily chipFamily;
71 std::vector<uint8_t> deviceId;
72};
73
74const 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
87struct 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
97enum 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
114constexpr std::chrono::milliseconds waitBusyTime(200);
115
116class 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