xref: /openbmc/phosphor-bmc-code-mgmt/i2c-vr/mps/mps.hpp (revision 3f2f3e6a61777c16094c94c22734659a8d84bdad)
1dcf4b607SKevin Tung #pragma once
2dcf4b607SKevin Tung 
3dcf4b607SKevin Tung #include "common/include/i2c/i2c.hpp"
4dcf4b607SKevin Tung #include "i2c-vr/vr.hpp"
5dcf4b607SKevin Tung 
6dcf4b607SKevin Tung #include <phosphor-logging/lg2.hpp>
7dcf4b607SKevin Tung 
8dcf4b607SKevin Tung #include <cstdint>
9dcf4b607SKevin Tung #include <iterator>
10dcf4b607SKevin Tung #include <memory>
11dcf4b607SKevin Tung #include <string_view>
12dcf4b607SKevin Tung #include <vector>
13dcf4b607SKevin Tung 
14dcf4b607SKevin Tung namespace phosphor::software::VR
15dcf4b607SKevin Tung {
16dcf4b607SKevin Tung 
17dcf4b607SKevin Tung /**
18dcf4b607SKevin Tung  * @brief
19dcf4b607SKevin Tung  * Columns of an Automated Test Equipment (ATE) format configuration file.
20dcf4b607SKevin Tung  * Each enumerator corresponds to a tab-separated column index.
21dcf4b607SKevin Tung  */
22dcf4b607SKevin Tung enum class ATE : uint8_t
23dcf4b607SKevin Tung {
24dcf4b607SKevin Tung     configId = 0,
25dcf4b607SKevin Tung     pageNum,
26dcf4b607SKevin Tung     regAddrHex,
27dcf4b607SKevin Tung     regAddrDec,
28dcf4b607SKevin Tung     regName,
29dcf4b607SKevin Tung     regDataHex,
30dcf4b607SKevin Tung     regDataDec,
31dcf4b607SKevin Tung     writeType,
32dcf4b607SKevin Tung     colCount,
33dcf4b607SKevin Tung };
34dcf4b607SKevin Tung 
35dcf4b607SKevin Tung enum class MPSPage : uint8_t
36dcf4b607SKevin Tung {
37dcf4b607SKevin Tung     page0 = 0,
38dcf4b607SKevin Tung     page1,
39dcf4b607SKevin Tung     page2,
40dcf4b607SKevin Tung     page3,
41dcf4b607SKevin Tung     page4,
42*3f2f3e6aSKevin Tung     page29 = 0x29,
43*3f2f3e6aSKevin Tung     page2A = 0x2A,
44dcf4b607SKevin Tung };
45dcf4b607SKevin Tung 
46dcf4b607SKevin Tung struct MPSData
47dcf4b607SKevin Tung {
48dcf4b607SKevin Tung     uint8_t page = 0;
49dcf4b607SKevin Tung     uint8_t addr = 0;
50dcf4b607SKevin Tung     uint8_t length = 0;
51dcf4b607SKevin Tung     std::array<uint8_t, 4> data{};
52dcf4b607SKevin Tung };
53dcf4b607SKevin Tung 
54dcf4b607SKevin Tung struct MPSConfig
55dcf4b607SKevin Tung {
56dcf4b607SKevin Tung     uint32_t vendorId = 0;
57dcf4b607SKevin Tung     uint32_t productId = 0;
58dcf4b607SKevin Tung     uint32_t configId = 0;
59dcf4b607SKevin Tung     uint32_t crcUser = 0;
60dcf4b607SKevin Tung     uint32_t crcMulti = 0;
61dcf4b607SKevin Tung     std::vector<MPSData> registersData;
62dcf4b607SKevin Tung };
63dcf4b607SKevin Tung 
64dcf4b607SKevin Tung /**
65dcf4b607SKevin Tung  * @brief
66dcf4b607SKevin Tung  * Utility class to iterate over lines and tokenize them by tab characters.
67dcf4b607SKevin Tung  */
68dcf4b607SKevin Tung class TokenizedLines
69dcf4b607SKevin Tung {
70dcf4b607SKevin Tung   public:
TokenizedLines(const uint8_t * d,size_t s)71dcf4b607SKevin Tung     TokenizedLines(const uint8_t* d, size_t s) :
72dcf4b607SKevin Tung         data(reinterpret_cast<const char*>(d), s)
73dcf4b607SKevin Tung     {}
74dcf4b607SKevin Tung     /**
75dcf4b607SKevin Tung      * @brief Iterator over tokenized lines.
76dcf4b607SKevin Tung      */
77dcf4b607SKevin Tung     struct Iterator
78dcf4b607SKevin Tung     {
79dcf4b607SKevin Tung         using iterator_category = std::forward_iterator_tag;
80dcf4b607SKevin Tung         using value_type = std::vector<std::string_view>;
81dcf4b607SKevin Tung         using difference_type = std::ptrdiff_t;
82dcf4b607SKevin Tung         using pointer = const value_type*;
83dcf4b607SKevin Tung         using reference = const value_type&;
84dcf4b607SKevin Tung 
85dcf4b607SKevin Tung         Iterator() = default; // End iterator
Iteratorphosphor::software::VR::TokenizedLines::Iterator86dcf4b607SKevin Tung         Iterator(std::string_view sv) : remaining(sv)
87dcf4b607SKevin Tung         {
88dcf4b607SKevin Tung             next();
89dcf4b607SKevin Tung         }
90dcf4b607SKevin Tung 
operator *phosphor::software::VR::TokenizedLines::Iterator91dcf4b607SKevin Tung         reference operator*() const
92dcf4b607SKevin Tung         {
93dcf4b607SKevin Tung             return currentTokens;
94dcf4b607SKevin Tung         }
95dcf4b607SKevin Tung 
operator ->phosphor::software::VR::TokenizedLines::Iterator96dcf4b607SKevin Tung         pointer operator->() const
97dcf4b607SKevin Tung         {
98dcf4b607SKevin Tung             return &currentTokens;
99dcf4b607SKevin Tung         }
100dcf4b607SKevin Tung 
operator ++phosphor::software::VR::TokenizedLines::Iterator101dcf4b607SKevin Tung         Iterator& operator++()
102dcf4b607SKevin Tung         {
103dcf4b607SKevin Tung             next();
104dcf4b607SKevin Tung             return *this;
105dcf4b607SKevin Tung         }
106dcf4b607SKevin Tung 
operator ++phosphor::software::VR::TokenizedLines::Iterator107dcf4b607SKevin Tung         Iterator operator++(int)
108dcf4b607SKevin Tung         {
109dcf4b607SKevin Tung             auto result = *this;
110dcf4b607SKevin Tung             ++(*this);
111dcf4b607SKevin Tung             return result;
112dcf4b607SKevin Tung         }
113dcf4b607SKevin Tung 
operator ==(const Iterator & a,const Iterator & b)114dcf4b607SKevin Tung         friend bool operator==(const Iterator& a, const Iterator& b)
115dcf4b607SKevin Tung         {
116dcf4b607SKevin Tung             return a.remaining.empty() && b.remaining.empty();
117dcf4b607SKevin Tung         }
118dcf4b607SKevin Tung 
operator !=(const Iterator & a,const Iterator & b)119dcf4b607SKevin Tung         friend bool operator!=(const Iterator& a, const Iterator& b)
120dcf4b607SKevin Tung         {
121dcf4b607SKevin Tung             return !(a == b);
122dcf4b607SKevin Tung         }
123dcf4b607SKevin Tung 
124dcf4b607SKevin Tung       private:
125dcf4b607SKevin Tung         std::string_view remaining;
126dcf4b607SKevin Tung         std::vector<std::string_view> currentTokens;
127dcf4b607SKevin Tung 
nextphosphor::software::VR::TokenizedLines::Iterator128dcf4b607SKevin Tung         void next()
129dcf4b607SKevin Tung         {
130dcf4b607SKevin Tung             currentTokens.clear();
131dcf4b607SKevin Tung             if (remaining.empty())
132dcf4b607SKevin Tung             {
133dcf4b607SKevin Tung                 return;
134dcf4b607SKevin Tung             }
135dcf4b607SKevin Tung 
136dcf4b607SKevin Tung             // Extract current line
137dcf4b607SKevin Tung             auto newlinePos = remaining.find('\n');
138dcf4b607SKevin Tung             std::string_view line = remaining.substr(0, newlinePos);
139dcf4b607SKevin Tung             remaining = (newlinePos == std::string_view::npos)
140dcf4b607SKevin Tung                             ? std::string_view{}
141dcf4b607SKevin Tung                             : remaining.substr(newlinePos + 1);
142dcf4b607SKevin Tung 
143dcf4b607SKevin Tung             // Tokenize by tab
144dcf4b607SKevin Tung             size_t start = 0;
145dcf4b607SKevin Tung             while (start < line.size())
146dcf4b607SKevin Tung             {
147dcf4b607SKevin Tung                 start = line.find_first_not_of('\t', start);
148dcf4b607SKevin Tung                 if (start == std::string_view::npos)
149dcf4b607SKevin Tung                 {
150dcf4b607SKevin Tung                     break;
151dcf4b607SKevin Tung                 }
152dcf4b607SKevin Tung 
153dcf4b607SKevin Tung                 auto end = line.find('\t', start);
154dcf4b607SKevin Tung                 currentTokens.emplace_back(line.substr(start, end - start));
155dcf4b607SKevin Tung                 start = (end == std::string_view::npos) ? line.size() : end;
156dcf4b607SKevin Tung             }
157dcf4b607SKevin Tung         }
158dcf4b607SKevin Tung     };
159dcf4b607SKevin Tung 
begin() const160dcf4b607SKevin Tung     Iterator begin() const
161dcf4b607SKevin Tung     {
162dcf4b607SKevin Tung         return Iterator(data);
163dcf4b607SKevin Tung     }
164dcf4b607SKevin Tung 
end()165dcf4b607SKevin Tung     static Iterator end()
166dcf4b607SKevin Tung     {
167dcf4b607SKevin Tung         return Iterator();
168dcf4b607SKevin Tung     }
169dcf4b607SKevin Tung 
170dcf4b607SKevin Tung   private:
171dcf4b607SKevin Tung     std::string_view data;
172dcf4b607SKevin Tung };
173dcf4b607SKevin Tung 
174dcf4b607SKevin Tung /**
175dcf4b607SKevin Tung  * @brief Base parser for MPS configuration images.
176dcf4b607SKevin Tung  */
177dcf4b607SKevin Tung class MPSImageParser
178dcf4b607SKevin Tung {
179dcf4b607SKevin Tung   public:
MPSImageParser(const uint8_t * image,size_t imageSize)180dcf4b607SKevin Tung     MPSImageParser(const uint8_t* image, size_t imageSize) :
181dcf4b607SKevin Tung         lineTokens(image, imageSize)
182dcf4b607SKevin Tung     {}
183dcf4b607SKevin Tung 
184dcf4b607SKevin Tung     template <typename>
185dcf4b607SKevin Tung     inline static constexpr bool always_false = false;
186dcf4b607SKevin Tung 
187dcf4b607SKevin Tung     /**
188dcf4b607SKevin Tung      * @brief Extract a typed value from a tokenized line.
189dcf4b607SKevin Tung      * @tparam T Return type (string or integral type)
190dcf4b607SKevin Tung      * @param tokens Tokenized line
191dcf4b607SKevin Tung      * @param index Column index (ATE enum)
192dcf4b607SKevin Tung      * @return Parsed value or default if invalid
193dcf4b607SKevin Tung      */
194dcf4b607SKevin Tung     template <typename T>
getVal(const std::vector<std::string_view> & tokens,ATE index)195dcf4b607SKevin Tung     T getVal(const std::vector<std::string_view>& tokens, ATE index)
196dcf4b607SKevin Tung     {
197dcf4b607SKevin Tung         size_t idx = static_cast<size_t>(index);
198dcf4b607SKevin Tung 
199dcf4b607SKevin Tung         if (tokens.size() <= idx)
200dcf4b607SKevin Tung         {
201dcf4b607SKevin Tung             lg2::error("Index out of range for ATE enum: {INDEX}", "INDEX",
202dcf4b607SKevin Tung                        static_cast<uint32_t>(idx));
203dcf4b607SKevin Tung             return T{};
204dcf4b607SKevin Tung         }
205dcf4b607SKevin Tung 
206dcf4b607SKevin Tung         std::string_view token = tokens[idx];
207dcf4b607SKevin Tung 
208dcf4b607SKevin Tung         if constexpr (std::is_same_v<T, std::string>)
209dcf4b607SKevin Tung         {
210dcf4b607SKevin Tung             return std::string(token);
211dcf4b607SKevin Tung         }
212dcf4b607SKevin Tung         else if constexpr (std::is_integral_v<T>)
213dcf4b607SKevin Tung         {
214dcf4b607SKevin Tung             unsigned long val = 0;
215dcf4b607SKevin Tung             try
216dcf4b607SKevin Tung             {
217dcf4b607SKevin Tung                 val = std::stoul(std::string(token), nullptr, 16);
218dcf4b607SKevin Tung             }
219dcf4b607SKevin Tung             catch (...)
220dcf4b607SKevin Tung             {
221dcf4b607SKevin Tung                 lg2::error("Invalid hex value: {INDEX}", "INDEX",
222dcf4b607SKevin Tung                            static_cast<uint32_t>(idx));
223dcf4b607SKevin Tung                 return T{};
224dcf4b607SKevin Tung             }
225dcf4b607SKevin Tung             return static_cast<T>(val);
226dcf4b607SKevin Tung         }
227dcf4b607SKevin Tung         else
228dcf4b607SKevin Tung         {
229dcf4b607SKevin Tung             static_assert(always_false<T>, "Unsupported type in getVal");
230dcf4b607SKevin Tung         }
231dcf4b607SKevin Tung     }
232dcf4b607SKevin Tung 
233dcf4b607SKevin Tung     /**
234dcf4b607SKevin Tung      * @brief Check if a tokenized line contains valid register data.
235dcf4b607SKevin Tung      */
236dcf4b607SKevin Tung     static bool isValidDataTokens(const std::vector<std::string_view>& tokens);
237dcf4b607SKevin Tung 
238dcf4b607SKevin Tung     /**
239dcf4b607SKevin Tung      * @brief Convert tokenized line into MPSData structure.
240dcf4b607SKevin Tung      */
241dcf4b607SKevin Tung     MPSData extractData(const std::vector<std::string_view>& tokens);
242dcf4b607SKevin Tung 
243dcf4b607SKevin Tung     /**
244dcf4b607SKevin Tung      * @brief Collect all register data entries from the parsed image.
245dcf4b607SKevin Tung      */
246dcf4b607SKevin Tung     std::vector<MPSData> getRegistersData();
247dcf4b607SKevin Tung 
248dcf4b607SKevin Tung     TokenizedLines lineTokens;
249dcf4b607SKevin Tung };
250dcf4b607SKevin Tung 
251dcf4b607SKevin Tung /**
252dcf4b607SKevin Tung  * @brief Base class for MPS Voltage Regulators.
253dcf4b607SKevin Tung  */
254dcf4b607SKevin Tung class MPSVoltageRegulator : public VoltageRegulator
255dcf4b607SKevin Tung {
256dcf4b607SKevin Tung   public:
MPSVoltageRegulator(sdbusplus::async::context & ctx,uint16_t bus,uint16_t address)257dcf4b607SKevin Tung     MPSVoltageRegulator(sdbusplus::async::context& ctx, uint16_t bus,
258dcf4b607SKevin Tung                         uint16_t address) :
259dcf4b607SKevin Tung         VoltageRegulator(ctx), i2cInterface(phosphor::i2c::I2C(bus, address))
260dcf4b607SKevin Tung     {}
261dcf4b607SKevin Tung 
262dcf4b607SKevin Tung     /**
263dcf4b607SKevin Tung      * @brief Parse device-specific configuration from the loaded image.
264dcf4b607SKevin Tung      * @return async task returning true if parsing succeeds
265dcf4b607SKevin Tung      */
266dcf4b607SKevin Tung     virtual sdbusplus::async::task<bool> parseDeviceConfiguration() = 0;
267dcf4b607SKevin Tung 
268dcf4b607SKevin Tung     /**
269dcf4b607SKevin Tung      * @brief Parse an image file into internal MPS configuration.
270dcf4b607SKevin Tung      * @param image Pointer to the image data
271dcf4b607SKevin Tung      * @param imageSize Size of the image data
272dcf4b607SKevin Tung      * @return async task returning true if parsing succeeds
273dcf4b607SKevin Tung      */
274dcf4b607SKevin Tung     sdbusplus::async::task<bool> parseImage(const uint8_t* image,
275dcf4b607SKevin Tung                                             size_t imageSize);
276dcf4b607SKevin Tung 
277dcf4b607SKevin Tung     /**
278dcf4b607SKevin Tung      * @brief Group register data by page, optionally masked and shifted.
279dcf4b607SKevin Tung      * @param configMask Bitmask to select relevant page bits (default 0xFF)
280dcf4b607SKevin Tung      * @param shift Number of bits to shift masked value to obtain group key
281dcf4b607SKevin Tung      * @return map of page keys to vector of MPSData
282dcf4b607SKevin Tung      */
283dcf4b607SKevin Tung     std::map<uint8_t, std::vector<MPSData>> getGroupedConfigData(
284dcf4b607SKevin Tung         uint8_t configMask = 0xFF, uint8_t shift = 0);
285dcf4b607SKevin Tung 
286dcf4b607SKevin Tung   protected:
287dcf4b607SKevin Tung     phosphor::i2c::I2C i2cInterface;
288dcf4b607SKevin Tung     std::unique_ptr<MPSImageParser> parser;
289dcf4b607SKevin Tung     std::unique_ptr<MPSConfig> configuration;
290dcf4b607SKevin Tung };
291dcf4b607SKevin Tung 
292dcf4b607SKevin Tung } // namespace phosphor::software::VR
293