1 #pragma once
2 
3 #include "occ_errors.hpp"
4 #include "utils.hpp"
5 
6 #include <org/open_power/OCC/PassThrough/server.hpp>
7 #include <sdbusplus/bus.hpp>
8 #include <sdbusplus/server/object.hpp>
9 
10 #include <format>
11 #include <string>
12 #include <utility>
13 
14 namespace open_power
15 {
16 namespace occ
17 {
18 
19 // For waiting on signals
20 namespace sdbusRule = sdbusplus::bus::match::rules;
21 
22 enum class CmdType
23 {
24     POLL = 0x00,
25     CLEAR_ERROR_LOG = 0x12,
26     SET_MODE_AND_STATE = 0x20,
27     SET_CONFIG_DATA = 0x21,
28     SET_USER_PCAP = 0x22,
29     RESET_PREP = 0x25,
30     SEND_AMBIENT = 0x30,
31     DEBUG_PASS_THROUGH = 0x40,
32     AME_PASS_THROUGH = 0x41,
33     GET_FIELD_DEBUG_DATA = 0x42,
34     MFG_TEST = 0x53
35 };
36 
37 enum class OccState
38 {
39     NO_CHANGE = 0x00,
40     STANDBY = 0x01,
41     OBSERVATION = 0x02,
42     ACTIVE = 0x03,
43     SAFE = 0x04,
44     CHARACTERIZATION = 0x05
45 };
46 
47 enum class SysPwrMode
48 {
49     NO_CHANGE = 0,
50     STATIC = 0x01,            // Static Base Frequencey
51     NON_DETERMINISTIC = 0x02, // Non-Deterministic
52     SFP = 0x03,               // Static Frequency Point (requires freqPt)
53     SAFE = 0x04,         // reported when system is in SAFE mode (not settable)
54     POWER_SAVING = 0x05, // Static Power Saving
55     EFF_FAVOR_POWER = 0x06, // Efficiency - Favor Power
56     EFF_FAVOR_PERF = 0x07,  // Efficiency - Favor Performance
57     MAX_FREQ = 0x09,        // Maximum Frequency (per chip)
58     BALANCED_PERF = 0x0A,   // Balanced Performance
59     FFO = 0x0B,             // Fixed Frequency Override (requires freqPt)
60     MAX_PERF = 0x0C         // Maximum Performance
61 };
62 
63 // Only some of the SysPwrModes are currently supported and allowed to be set
64 #define VALID_POWER_MODE_SETTING(mode)                                         \
65     ((mode == SysPwrMode::STATIC) || (mode == SysPwrMode::POWER_SAVING) ||     \
66      (mode == SysPwrMode::BALANCED_PERF) || (mode == SysPwrMode::MAX_PERF) ||  \
67      (mode == SysPwrMode::EFF_FAVOR_POWER) ||                                  \
68      (mode == SysPwrMode::EFF_FAVOR_PERF))
69 #define VALID_OEM_POWER_MODE_SETTING(mode)                                     \
70     ((mode == SysPwrMode::SFP) || (mode == SysPwrMode::FFO) ||                 \
71      (mode == SysPwrMode::MAX_FREQ) ||                                         \
72      (mode == SysPwrMode::NON_DETERMINISTIC))
73 
74 enum class RspStatus
75 {
76     SUCCESS = 0x00,
77     CONDITIONAL_SUCCESS = 0x01,
78     INVALID_COMMAND = 0x11,
79     INVALID_COMMAND_LENGTH = 0x12,
80     INVALID_DATA_FIELD = 0x13,
81     CHECKSUM_FAILURE = 0x14,
82     INTERNAL_ERROR = 0x15,
83     PRESENT_STATE_PROHIBITS = 0x16,
84     COMMAND_IN_PROGRESS = 0xFF
85 };
86 
87 enum class CmdStatus
88 {
89     SUCCESS = 0x00,
90     FAILURE = 0x02,
91     COMM_FAILURE = 0x03
92 };
93 
94 /** @brief Trace block of data in hex with log<level:INFO>
95  *
96  *  @param[in] data - vector containing data to trace
97  *  @param[in] data_len - optional number of bytes to trace
98  *  If 0, entire vector will be traced.
99  */
100 void dump_hex(const std::vector<std::uint8_t>& data,
101               const unsigned int data_len = 0);
102 
103 /** @class OccCommand
104  *  @brief Send commands and process respsonses from the OCC
105  */
106 class OccCommand
107 {
108   public:
109     OccCommand() = delete;
110     OccCommand(const OccCommand&) = delete;
111     OccCommand& operator=(const OccCommand&) = delete;
112     OccCommand(OccCommand&&) = default;
113     OccCommand& operator=(OccCommand&&) = default;
114 
115     /** @brief Ctor to set up which OCC the command will go to
116      *
117      *  @param[in] instance - OCC instance
118      *  @param[in] path - Path to attach at
119      */
120     OccCommand(uint8_t instance, const char* path);
121 
122     /** @brief Dtor to clean up and close device */
~OccCommand()123     ~OccCommand()
124     {
125         closeDevice();
126     }
127 
128     /** @brief Send the command to the OCC and collect the response.
129      * The checksum will be validated and removed from the response.
130      *
131      *  @param[in] command - command to pass-through
132      *  @param[out] response - response
133      *  returns SUCCESS if response was received
134      */
135     CmdStatus send(const std::vector<std::uint8_t>& command,
136                    std::vector<std::uint8_t>& response);
137 
138   private:
139     /** @brief Instance number of the target OCC */
140     uint8_t occInstance;
141 
142     /** @brief OCC path on the bus */
143     std::string path;
144 
145     /** @brief OCC device path
146      *  For now, here is the hard-coded mapping until
147      *  the udev rule is in.
148      *  occ0 --> /dev/occ1
149      *  occ1 --> /dev/occ2
150      *  ...
151      */
152     std::string devicePath;
153 
154     /** @brief Indicates whether or not the OCC is currently active */
155     bool occActive = false;
156 
157     /** brief file descriptor associated with occ device */
158     int fd = -1;
159 
160     /** @brief Subscribe to OCC Status signal
161      *
162      *  Once the OCC status gets to active, only then we will get /dev/occ2
163      *  populated and hence need to wait on that before opening that
164      */
165     sdbusplus::bus::match_t activeStatusSignal;
166 
167     /** Opens devicePath and populates file descriptor */
168     void openDevice();
169 
170     /** Closed the fd associated with opened device */
171     void closeDevice();
172 
173     /** @brief Callback function on OCC Status change signals
174      *
175      *  @param[in]  msg - Data associated with subscribed signal
176      */
177     void activeStatusEvent(sdbusplus::message_t& msg);
178 };
179 
180 } // namespace occ
181 } // namespace open_power
182 
183 template <>
184 struct std::formatter<open_power::occ::SysPwrMode> : formatter<int>
185 {
formatstd::formatter186     auto format(open_power::occ::SysPwrMode f, format_context& ctx) const
187     {
188         return formatter<int>::format(std::to_underlying(f), ctx);
189     }
190 };
191 
192 template <>
193 struct std::formatter<open_power::occ::CmdStatus> : formatter<int>
194 {
formatstd::formatter195     auto format(open_power::occ::CmdStatus f, format_context& ctx) const
196     {
197         return formatter<int>::format(std::to_underlying(f), ctx);
198     }
199 };
200