1 #include "sbe_interfaces.hpp"
2 
3 #include "sbe_chipOp_handler.hpp"
4 
5 #include <endian.h>
6 
7 #include <array>
8 #include <iostream>
9 #include <stdexcept>
10 
11 namespace openpower
12 {
13 namespace sbe
14 {
15 
16 constexpr size_t RESP_HEADER_LEN = 0x3;
17 
18 // Helper interfaces
upper(uint64_t value)19 static inline uint32_t upper(uint64_t value)
20 {
21     return ((value & 0xFFFFFFFF00000000ull) >> 32);
22 }
23 
lower(uint64_t value)24 static inline uint32_t lower(uint64_t value)
25 {
26     return (value & 0xFFFFFFFF);
27 }
28 
29 using sbe_word_t = uint32_t;
30 
31 namespace scom
32 {
33 
34 // Constants specific to SCOM operations
35 static constexpr sbe_word_t READ_OPCODE = 0x0000A201;
36 static constexpr sbe_word_t WRITE_OPCODE = 0x0000A202;
37 static constexpr size_t READ_CMD_LENGTH = 0x4;
38 static constexpr size_t WRITE_CMD_LENGTH = 0x6;
39 static constexpr size_t READ_RESP_LENGTH = 0x2;
40 
41 // Reading SCOM Registers
read(const char * devPath,uint64_t address)42 uint64_t read(const char* devPath, uint64_t address)
43 {
44     uint64_t value = 0;
45 
46     // Validate input device path
47     if (devPath == nullptr)
48     {
49         throw std::runtime_error("NULL FIFO device path");
50     }
51 
52     // Build SCOM read request command.
53     // Handle byte order mismatch ,SBE is big endian and BMC is
54     // little endian.
55     std::array<sbe_word_t, READ_CMD_LENGTH> command = {
56         static_cast<sbe_word_t>(htobe32(READ_CMD_LENGTH)), htobe32(READ_OPCODE),
57         htobe32(upper(address)), htobe32(lower(address))};
58 
59     // Buffer to hold the response data along with the SBE header
60     const size_t respLength = RESP_HEADER_LEN + READ_RESP_LENGTH;
61     std::array<sbe_word_t, respLength> response = {};
62 
63     // Write the command buffer to the SBE FIFO and obtain the response from the
64     // SBE FIFO device.This interface will parse the obtained SBE response and
65     // any internal SBE failures will be communicated via exceptions
66     invokeSBEChipOperation(devPath, command, response);
67 
68     value = (((static_cast<uint64_t>(response[0])) << 32) | response[1]);
69     return value;
70 }
71 
write(const char * devPath,uint64_t address,uint64_t data)72 void write(const char* devPath, uint64_t address, uint64_t data)
73 {
74     // Validate input device path
75     if (devPath == nullptr)
76     {
77         throw std::runtime_error("NULL FIFO device path");
78     }
79 
80     // Build SCOM write request command
81     // Handle byte order mismatch, SBE is big endian and BMC is
82     // little endian.
83     std::array<sbe_word_t, WRITE_CMD_LENGTH> command = {
84         static_cast<sbe_word_t>(htobe32(WRITE_CMD_LENGTH)),
85         htobe32(WRITE_OPCODE),
86         htobe32(upper(address)),
87         htobe32(lower(address)),
88         htobe32(upper(data)),
89         htobe32(lower(data))};
90 
91     // Buffer to hold the SBE response status
92     const size_t respLength = RESP_HEADER_LEN;
93     std::array<sbe_word_t, respLength> response = {};
94 
95     // Write the command buffer to the SBE FIFO and obtain the response from the
96     // SBE FIFO device.This interface will parse the obtained SBE response and
97     // any internal SBE failures will be communicated via exceptions
98     invokeSBEChipOperation(devPath, command, response);
99 }
100 
101 } // namespace scom
102 } // namespace sbe
103 } // namespace openpower
104