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