| #pragma once |
| |
| #include "occ_errors.hpp" |
| #include "utils.hpp" |
| |
| #include <org/open_power/OCC/PassThrough/server.hpp> |
| #include <sdbusplus/bus.hpp> |
| #include <sdbusplus/server/object.hpp> |
| |
| #include <format> |
| #include <string> |
| #include <utility> |
| |
| namespace open_power |
| { |
| namespace occ |
| { |
| |
| // For waiting on signals |
| namespace sdbusRule = sdbusplus::bus::match::rules; |
| |
| enum class CmdType |
| { |
| POLL = 0x00, |
| CLEAR_ERROR_LOG = 0x12, |
| SET_MODE_AND_STATE = 0x20, |
| SET_CONFIG_DATA = 0x21, |
| SET_USER_PCAP = 0x22, |
| RESET_PREP = 0x25, |
| SEND_AMBIENT = 0x30, |
| DEBUG_PASS_THROUGH = 0x40, |
| AME_PASS_THROUGH = 0x41, |
| GET_FIELD_DEBUG_DATA = 0x42, |
| MFG_TEST = 0x53 |
| }; |
| |
| enum class OccState |
| { |
| NO_CHANGE = 0x00, |
| STANDBY = 0x01, |
| OBSERVATION = 0x02, |
| ACTIVE = 0x03, |
| SAFE = 0x04, |
| CHARACTERIZATION = 0x05 |
| }; |
| |
| enum class SysPwrMode |
| { |
| NO_CHANGE = 0, |
| STATIC = 0x01, // Static Base Frequencey |
| NON_DETERMINISTIC = 0x02, // Non-Deterministic |
| SFP = 0x03, // Static Frequency Point (requires freqPt) |
| SAFE = 0x04, // reported when system is in SAFE mode (not settable) |
| POWER_SAVING = 0x05, // Static Power Saving |
| EFF_FAVOR_POWER = 0x06, // Efficiency - Favor Power |
| EFF_FAVOR_PERF = 0x07, // Efficiency - Favor Performance |
| MAX_FREQ = 0x09, // Maximum Frequency (per chip) |
| BALANCED_PERF = 0x0A, // Balanced Performance |
| FFO = 0x0B, // Fixed Frequency Override (requires freqPt) |
| MAX_PERF = 0x0C // Maximum Performance |
| }; |
| |
| static inline auto format_as(SysPwrMode spm) |
| { |
| return std::to_underlying(spm); |
| } |
| |
| // Only some of the SysPwrModes are currently supported and allowed to be set |
| #define VALID_POWER_MODE_SETTING(mode) \ |
| ((mode == SysPwrMode::STATIC) || (mode == SysPwrMode::POWER_SAVING) || \ |
| (mode == SysPwrMode::BALANCED_PERF) || (mode == SysPwrMode::MAX_PERF) || \ |
| (mode == SysPwrMode::EFF_FAVOR_POWER) || \ |
| (mode == SysPwrMode::EFF_FAVOR_PERF)) |
| #define VALID_OEM_POWER_MODE_SETTING(mode) \ |
| ((mode == SysPwrMode::SFP) || (mode == SysPwrMode::FFO) || \ |
| (mode == SysPwrMode::MAX_FREQ) || \ |
| (mode == SysPwrMode::NON_DETERMINISTIC)) |
| |
| enum class RspStatus |
| { |
| SUCCESS = 0x00, |
| CONDITIONAL_SUCCESS = 0x01, |
| INVALID_COMMAND = 0x11, |
| INVALID_COMMAND_LENGTH = 0x12, |
| INVALID_DATA_FIELD = 0x13, |
| CHECKSUM_FAILURE = 0x14, |
| INTERNAL_ERROR = 0x15, |
| PRESENT_STATE_PROHIBITS = 0x16, |
| COMMAND_IN_PROGRESS = 0xFF |
| }; |
| |
| enum class CmdStatus |
| { |
| SUCCESS = 0x00, |
| FAILURE = 0x02, |
| COMM_FAILURE = 0x03 |
| }; |
| |
| static inline auto format_as(CmdStatus cs) |
| { |
| return std::to_underlying(cs); |
| } |
| |
| /** @brief Trace block of data in hex with log<level:INFO> |
| * |
| * @param[in] data - vector containing data to trace |
| * @param[in] data_len - optional number of bytes to trace |
| * If 0, entire vector will be traced. |
| */ |
| void dump_hex(const std::vector<std::uint8_t>& data, |
| const unsigned int data_len = 0); |
| |
| /** @class OccCommand |
| * @brief Send commands and process respsonses from the OCC |
| */ |
| class OccCommand |
| { |
| public: |
| OccCommand() = delete; |
| OccCommand(const OccCommand&) = delete; |
| OccCommand& operator=(const OccCommand&) = delete; |
| OccCommand(OccCommand&&) = default; |
| OccCommand& operator=(OccCommand&&) = default; |
| |
| /** @brief Ctor to set up which OCC the command will go to |
| * |
| * @param[in] instance - OCC instance |
| * @param[in] path - Path to attach at |
| */ |
| OccCommand(uint8_t instance, const char* path); |
| |
| /** @brief Dtor to clean up and close device */ |
| ~OccCommand() |
| { |
| closeDevice(); |
| } |
| |
| /** @brief Send the command to the OCC and collect the response. |
| * The checksum will be validated and removed from the response. |
| * |
| * @param[in] command - command to pass-through |
| * @param[out] response - response |
| * returns SUCCESS if response was received |
| */ |
| CmdStatus send(const std::vector<std::uint8_t>& command, |
| std::vector<std::uint8_t>& response); |
| |
| private: |
| /** @brief Instance number of the target OCC */ |
| uint8_t occInstance; |
| |
| /** @brief OCC path on the bus */ |
| std::string path; |
| |
| /** @brief OCC device path |
| * For now, here is the hard-coded mapping until |
| * the udev rule is in. |
| * occ0 --> /dev/occ1 |
| * occ1 --> /dev/occ2 |
| * ... |
| */ |
| std::string devicePath; |
| |
| /** @brief Indicates whether or not the OCC is currently active */ |
| bool occActive = false; |
| |
| /** brief file descriptor associated with occ device */ |
| int fd = -1; |
| |
| /** @brief Subscribe to OCC Status signal |
| * |
| * Once the OCC status gets to active, only then we will get /dev/occ2 |
| * populated and hence need to wait on that before opening that |
| */ |
| sdbusplus::bus::match_t activeStatusSignal; |
| |
| /** Opens devicePath and populates file descriptor */ |
| void openDevice(); |
| |
| /** Closed the fd associated with opened device */ |
| void closeDevice(); |
| |
| /** @brief Callback function on OCC Status change signals |
| * |
| * @param[in] msg - Data associated with subscribed signal |
| */ |
| void activeStatusEvent(sdbusplus::message_t& msg); |
| }; |
| |
| } // namespace occ |
| } // namespace open_power |