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