blob: 8c80ef3ec826fee3419ee9e43827b429bd55c438 [file] [log] [blame]
Brandon Wymanaed1f752019-11-25 18:10:52 -06001#include "power_supply.hpp"
2
3#include "types.hpp"
Brandon Wyman3f1242f2020-01-28 13:11:25 -06004#include "util.hpp"
Brandon Wymanaed1f752019-11-25 18:10:52 -06005
Brandon Wyman3f1242f2020-01-28 13:11:25 -06006#include <xyz/openbmc_project/Common/Device/error.hpp>
7
8namespace phosphor::power::psu
Brandon Wymanaed1f752019-11-25 18:10:52 -06009{
10
11using namespace phosphor::logging;
Brandon Wyman3f1242f2020-01-28 13:11:25 -060012using namespace sdbusplus::xyz::openbmc_project::Common::Device::Error;
Brandon Wymanaed1f752019-11-25 18:10:52 -060013
14void PowerSupply::updatePresence()
15{
16 try
17 {
Brandon Wyman3f1242f2020-01-28 13:11:25 -060018 present = getPresence(bus, inventoryPath);
Brandon Wymanaed1f752019-11-25 18:10:52 -060019 }
20 catch (const sdbusplus::exception::SdBusError& e)
21 {
22 // Relying on property change or interface added to retry.
23 // Log an informational trace to the journal.
24 log<level::INFO>("D-Bus property access failure exception");
25 }
26}
27
Brandon Wyman3f1242f2020-01-28 13:11:25 -060028void PowerSupply::analyze()
29{
30 using namespace phosphor::pmbus;
31
32 if (present)
33 {
34 try
35 {
36 auto statusWord{pmbusIntf->read(STATUS_WORD, Type::Debug)};
37
38 if (statusWord)
39 {
40 if (statusWord & status_word::INPUT_FAULT_WARN)
41 {
42 if (!inputFault)
43 {
44 log<level::INFO>(
45 "INPUT fault",
46 entry("STATUS_WORD=0x%04X",
47 static_cast<uint16_t>(statusWord)));
48 }
49
50 faultFound = true;
51 inputFault = true;
52 }
53
54 if (statusWord & status_word::MFR_SPECIFIC_FAULT)
55 {
56 if (!mfrFault)
57 {
58 log<level::INFO>(
59 "MFRSPECIFIC fault",
60 entry("STATUS_WORD=0x%04X",
61 static_cast<uint16_t>(statusWord)));
62 }
63 faultFound = true;
64 mfrFault = true;
65 }
66
67 if (statusWord & status_word::VIN_UV_FAULT)
68 {
69 if (!vinUVFault)
70 {
71 log<level::INFO>(
72 "VIN_UV fault",
73 entry("STATUS_WORD=0x%04X",
74 static_cast<uint16_t>(statusWord)));
75 }
76
77 faultFound = true;
78 vinUVFault = true;
79 }
80 }
81 else
82 {
83 faultFound = false;
84 inputFault = false;
85 mfrFault = false;
86 vinUVFault = false;
87 }
88 }
89 catch (ReadFailure& e)
90 {
91 phosphor::logging::commit<ReadFailure>();
92 }
93 }
94}
95
Brandon Wyman59a35792020-06-04 12:37:40 -050096void PowerSupply::onOffConfig(uint8_t data)
97{
98 using namespace phosphor::pmbus;
99
100 if (present)
101 {
102 log<level::INFO>("ON_OFF_CONFIG write", entry("DATA=0x%02X", data));
103 try
104 {
105 std::vector<uint8_t> configData{data};
106 pmbusIntf->writeBinary(ON_OFF_CONFIG, configData,
107 Type::HwmonDeviceDebug);
108 }
109 catch (...)
110 {
111 // The underlying code in writeBinary will log a message to the
112 // journal if the write fails. If the ON_OFF_CONFIG is not setup as
113 // desired, later fault detection and analysis code should catch any
114 // of the fall out. We should not need to terminate the application
115 // if this write fails.
116 }
117 }
118}
119
Brandon Wyman3c208462020-05-13 16:25:58 -0500120void PowerSupply::clearFaults()
121{
122 faultFound = false;
123 inputFault = false;
124 mfrFault = false;
125 vinUVFault = false;
126
127 // The PMBus device driver does not allow for writing CLEAR_FAULTS
128 // directly. However, the pmbus hwmon device driver code will send a
129 // CLEAR_FAULTS after reading from any of the hwmon "files" in sysfs, so
130 // reading in1_input should result in clearing the fault bits in
131 // STATUS_BYTE/STATUS_WORD.
132 // I do not care what the return value is.
133 try
134 {
135 static_cast<void>(
136 pmbusIntf->read("in1_input", phosphor::pmbus::Type::Hwmon));
137 }
138 catch (ReadFailure& e)
139 {
140 // Since I do not care what the return value is, I really do not
141 // care much if it gets a ReadFailure either. However, this should not
142 // prevent the application from continuing to run, so catching the read
143 // failure.
144 }
145}
146
Brandon Wymanaed1f752019-11-25 18:10:52 -0600147void PowerSupply::inventoryChanged(sdbusplus::message::message& msg)
148{
149 std::string msgSensor;
Patrick Williamsabe49412020-05-13 17:59:47 -0500150 std::map<std::string, std::variant<uint32_t, bool>> msgData;
Brandon Wymanaed1f752019-11-25 18:10:52 -0600151 msg.read(msgSensor, msgData);
152
153 // Check if it was the Present property that changed.
154 auto valPropMap = msgData.find(PRESENT_PROP);
155 if (valPropMap != msgData.end())
156 {
157 if (std::get<bool>(valPropMap->second))
158 {
159 present = true;
Brandon Wyman59a35792020-06-04 12:37:40 -0500160 onOffConfig(phosphor::pmbus::ON_OFF_CONFIG_CONTROL_PIN_ONLY);
Brandon Wymanaed1f752019-11-25 18:10:52 -0600161 clearFaults();
162 }
163 else
164 {
165 present = false;
166
167 // Clear out the now outdated inventory properties
168 updateInventory();
169 }
170 }
171}
172
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600173} // namespace phosphor::power::psu