blob: 9d8c9145259b48edd3492ad24fe57149b274330c [file] [log] [blame]
Brandon Wyman1d7a7df2020-03-26 10:14:05 -05001#include "config.h"
2
Brandon Wymanaed1f752019-11-25 18:10:52 -06003#include "power_supply.hpp"
4
5#include "types.hpp"
Brandon Wyman3f1242f2020-01-28 13:11:25 -06006#include "util.hpp"
Brandon Wymanaed1f752019-11-25 18:10:52 -06007
Brandon Wymandf13c3a2020-12-15 14:25:22 -06008#include <fmt/format.h>
9
Brandon Wyman3f1242f2020-01-28 13:11:25 -060010#include <xyz/openbmc_project/Common/Device/error.hpp>
11
Brandon Wyman1d7a7df2020-03-26 10:14:05 -050012#include <chrono> // sleep_for()
13#include <cstdint> // uint8_t...
B. J. Wyman681b2a32021-04-20 22:31:22 +000014#include <fstream>
15#include <thread> // sleep_for()
Brandon Wyman1d7a7df2020-03-26 10:14:05 -050016
Brandon Wyman3f1242f2020-01-28 13:11:25 -060017namespace phosphor::power::psu
Brandon Wymanaed1f752019-11-25 18:10:52 -060018{
B. J. Wyman681b2a32021-04-20 22:31:22 +000019// Amount of time in milliseconds to delay between power supply going from
20// missing to present before running the bind command(s).
21constexpr auto bindDelay = 1000;
Brandon Wymanaed1f752019-11-25 18:10:52 -060022
23using namespace phosphor::logging;
Brandon Wyman3f1242f2020-01-28 13:11:25 -060024using namespace sdbusplus::xyz::openbmc_project::Common::Device::Error;
Brandon Wymanaed1f752019-11-25 18:10:52 -060025
Brandon Wyman510acaa2020-11-05 18:32:04 -060026PowerSupply::PowerSupply(sdbusplus::bus::bus& bus, const std::string& invpath,
B. J. Wyman681b2a32021-04-20 22:31:22 +000027 std::uint8_t i2cbus, std::uint16_t i2caddr,
28 const std::string& gpioLineName) :
Brandon Wyman510acaa2020-11-05 18:32:04 -060029 bus(bus),
B. J. Wyman681b2a32021-04-20 22:31:22 +000030 inventoryPath(invpath), bindPath("/sys/bus/i2c/drivers/ibm-cffps")
Brandon Wyman510acaa2020-11-05 18:32:04 -060031{
32 if (inventoryPath.empty())
33 {
34 throw std::invalid_argument{"Invalid empty inventoryPath"};
35 }
36
B. J. Wyman681b2a32021-04-20 22:31:22 +000037 if (gpioLineName.empty())
38 {
39 throw std::invalid_argument{"Invalid empty gpioLineName"};
40 }
Brandon Wyman510acaa2020-11-05 18:32:04 -060041
B. J. Wyman681b2a32021-04-20 22:31:22 +000042 log<level::DEBUG>(fmt::format("gpioLineName: {}", gpioLineName).c_str());
43 presenceGPIO = createGPIO(gpioLineName);
Brandon Wyman510acaa2020-11-05 18:32:04 -060044
45 std::ostringstream ss;
46 ss << std::hex << std::setw(4) << std::setfill('0') << i2caddr;
47 std::string addrStr = ss.str();
B. J. Wyman681b2a32021-04-20 22:31:22 +000048 std::string busStr = std::to_string(i2cbus);
49 bindDevice = busStr;
50 bindDevice.append("-");
51 bindDevice.append(addrStr);
52
Brandon Wyman510acaa2020-11-05 18:32:04 -060053 pmbusIntf = phosphor::pmbus::createPMBus(i2cbus, addrStr);
54
55 // Get the current state of the Present property.
B. J. Wyman681b2a32021-04-20 22:31:22 +000056 try
57 {
58 updatePresenceGPIO();
59 }
60 catch (...)
61 {
62 // If the above attempt to use the GPIO failed, it likely means that the
63 // GPIOs are in use by the kernel, meaning it is using gpio-keys.
64 // So, I should rely on phosphor-gpio-presence to update D-Bus, and
65 // work that way for power supply presence.
66 presenceGPIO = nullptr;
67 // Setup the functions to call when the D-Bus inventory path for the
68 // Present property changes.
69 presentMatch = std::make_unique<sdbusplus::bus::match_t>(
70 bus,
71 sdbusplus::bus::match::rules::propertiesChanged(inventoryPath,
72 INVENTORY_IFACE),
73 [this](auto& msg) { this->inventoryChanged(msg); });
74
75 presentAddedMatch = std::make_unique<sdbusplus::bus::match_t>(
76 bus,
77 sdbusplus::bus::match::rules::interfacesAdded() +
78 sdbusplus::bus::match::rules::argNpath(0, inventoryPath),
79 [this](auto& msg) { this->inventoryAdded(msg); });
80
81 updatePresence();
82 updateInventory();
83 }
84}
85
86void PowerSupply::bindOrUnbindDriver(bool present)
87{
88 auto action = (present) ? "bind" : "unbind";
89 auto path = bindPath / action;
90
91 if (present)
92 {
93 log<level::INFO>(
94 fmt::format("Binding device driver. path: {} device: {}",
95 path.string(), bindDevice)
96 .c_str());
97 }
98 else
99 {
100 log<level::INFO>(
101 fmt::format("Unbinding device driver. path: {} device: {}",
102 path.string(), bindDevice)
103 .c_str());
104 }
105
106 std::ofstream file;
107
108 file.exceptions(std::ofstream::failbit | std::ofstream::badbit |
109 std::ofstream::eofbit);
110
111 try
112 {
113 file.open(path);
114 file << bindDevice;
115 file.close();
116 }
Patrick Williamsc1d4de52021-10-06 12:45:57 -0500117 catch (const std::exception& e)
B. J. Wyman681b2a32021-04-20 22:31:22 +0000118 {
119 auto err = errno;
120
121 log<level::ERR>(
122 fmt::format("Failed binding or unbinding device. errno={}", err)
123 .c_str());
124 }
Brandon Wyman510acaa2020-11-05 18:32:04 -0600125}
126
Brandon Wymanaed1f752019-11-25 18:10:52 -0600127void PowerSupply::updatePresence()
128{
129 try
130 {
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600131 present = getPresence(bus, inventoryPath);
Brandon Wymanaed1f752019-11-25 18:10:52 -0600132 }
Patrick Williams69f10ad2021-09-02 09:46:49 -0500133 catch (const sdbusplus::exception::exception& e)
Brandon Wymanaed1f752019-11-25 18:10:52 -0600134 {
135 // Relying on property change or interface added to retry.
136 // Log an informational trace to the journal.
Brandon Wymandf13c3a2020-12-15 14:25:22 -0600137 log<level::INFO>(
138 fmt::format("D-Bus property {} access failure exception",
139 inventoryPath)
140 .c_str());
Brandon Wymanaed1f752019-11-25 18:10:52 -0600141 }
142}
143
B. J. Wyman681b2a32021-04-20 22:31:22 +0000144void PowerSupply::updatePresenceGPIO()
145{
146 bool presentOld = present;
147
148 try
149 {
150 if (presenceGPIO->read() > 0)
151 {
152 present = true;
153 }
154 else
155 {
156 present = false;
157 }
158 }
Patrick Williamsc1d4de52021-10-06 12:45:57 -0500159 catch (const std::exception& e)
B. J. Wyman681b2a32021-04-20 22:31:22 +0000160 {
161 log<level::ERR>(
162 fmt::format("presenceGPIO read fail: {}", e.what()).c_str());
163 throw;
164 }
165
166 if (presentOld != present)
167 {
168 log<level::DEBUG>(
169 fmt::format("presentOld: {} present: {}", presentOld, present)
170 .c_str());
171 if (present)
172 {
173 std::this_thread::sleep_for(std::chrono::milliseconds(bindDelay));
174 bindOrUnbindDriver(present);
175 pmbusIntf->findHwmonDir();
176 onOffConfig(phosphor::pmbus::ON_OFF_CONFIG_CONTROL_PIN_ONLY);
177 clearFaults();
178 }
179 else
180 {
181 bindOrUnbindDriver(present);
182 }
183
184 auto invpath = inventoryPath.substr(strlen(INVENTORY_OBJ_PATH));
185 auto const lastSlashPos = invpath.find_last_of('/');
186 std::string prettyName = invpath.substr(lastSlashPos + 1);
187 setPresence(bus, invpath, present, prettyName);
188 updateInventory();
189 }
190}
191
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600192void PowerSupply::analyze()
193{
194 using namespace phosphor::pmbus;
195
B. J. Wyman681b2a32021-04-20 22:31:22 +0000196 if (presenceGPIO)
197 {
198 updatePresenceGPIO();
199 }
200
Brandon Wymanf65c4062020-08-19 13:15:53 -0500201 if ((present) && (readFail < LOG_LIMIT))
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600202 {
203 try
204 {
Brandon Wymanfed0ba22020-09-26 20:02:51 -0500205 statusWord = pmbusIntf->read(STATUS_WORD, Type::Debug);
Brandon Wymanf65c4062020-08-19 13:15:53 -0500206 // Read worked, reset the fail count.
207 readFail = 0;
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600208
209 if (statusWord)
210 {
Jay Meyer10d94052020-11-30 14:41:21 -0600211 statusMFR = pmbusIntf->read(STATUS_MFR, Type::Debug);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600212 if (statusWord & status_word::INPUT_FAULT_WARN)
213 {
214 if (!inputFault)
215 {
Brandon Wymanc8996602021-10-12 19:28:56 +0000216 log<level::INFO>(
217 fmt::format("INPUT fault: "
218 "STATUS_WORD = {:#04x}, "
219 "STATUS_MFR_SPECIFIC = {:#02x}",
220 statusWord, statusMFR)
221 .c_str());
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600222 }
223
224 faultFound = true;
225 inputFault = true;
226 }
227
228 if (statusWord & status_word::MFR_SPECIFIC_FAULT)
229 {
230 if (!mfrFault)
231 {
Brandon Wymanc8996602021-10-12 19:28:56 +0000232 log<level::ERR>(
233 fmt::format("MFR fault: "
234 "STATUS_WORD = {:#04x} "
235 "STATUS_MFR_SPECIFIC = {:#02x}",
236 statusWord, statusMFR)
237 .c_str());
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600238 }
239 faultFound = true;
240 mfrFault = true;
241 }
242
243 if (statusWord & status_word::VIN_UV_FAULT)
244 {
245 if (!vinUVFault)
246 {
Brandon Wymanc8996602021-10-12 19:28:56 +0000247 log<level::INFO>(
248 fmt::format("VIN_UV fault: "
249 "STATUS_WORD = {:#04x}, "
250 "STATUS_MFR_SPECIFIC = {:#02x}",
251 statusWord, statusMFR)
252 .c_str());
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600253 }
254
255 faultFound = true;
256 vinUVFault = true;
257 }
258 }
259 else
260 {
261 faultFound = false;
262 inputFault = false;
263 mfrFault = false;
264 vinUVFault = false;
265 }
266 }
Patrick Williamsc1d4de52021-10-06 12:45:57 -0500267 catch (const ReadFailure& e)
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600268 {
Brandon Wymanf65c4062020-08-19 13:15:53 -0500269 readFail++;
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600270 phosphor::logging::commit<ReadFailure>();
271 }
272 }
273}
274
Brandon Wyman59a35792020-06-04 12:37:40 -0500275void PowerSupply::onOffConfig(uint8_t data)
276{
277 using namespace phosphor::pmbus;
278
279 if (present)
280 {
281 log<level::INFO>("ON_OFF_CONFIG write", entry("DATA=0x%02X", data));
282 try
283 {
284 std::vector<uint8_t> configData{data};
285 pmbusIntf->writeBinary(ON_OFF_CONFIG, configData,
286 Type::HwmonDeviceDebug);
287 }
288 catch (...)
289 {
290 // The underlying code in writeBinary will log a message to the
B. J. Wyman681b2a32021-04-20 22:31:22 +0000291 // journal if the write fails. If the ON_OFF_CONFIG is not setup
292 // as desired, later fault detection and analysis code should
293 // catch any of the fall out. We should not need to terminate
294 // the application if this write fails.
Brandon Wyman59a35792020-06-04 12:37:40 -0500295 }
296 }
297}
298
Brandon Wyman3c208462020-05-13 16:25:58 -0500299void PowerSupply::clearFaults()
300{
Brandon Wyman5474c912021-02-23 14:39:43 -0600301 faultLogged = false;
Brandon Wyman3c208462020-05-13 16:25:58 -0500302 // The PMBus device driver does not allow for writing CLEAR_FAULTS
303 // directly. However, the pmbus hwmon device driver code will send a
304 // CLEAR_FAULTS after reading from any of the hwmon "files" in sysfs, so
305 // reading in1_input should result in clearing the fault bits in
306 // STATUS_BYTE/STATUS_WORD.
307 // I do not care what the return value is.
Brandon Wyman11151532020-11-10 13:45:57 -0600308 if (present)
Brandon Wyman3c208462020-05-13 16:25:58 -0500309 {
Brandon Wyman9564e942020-11-10 14:01:42 -0600310 faultFound = false;
311 inputFault = false;
312 mfrFault = false;
Jay Meyer10d94052020-11-30 14:41:21 -0600313 statusMFR = 0;
Brandon Wyman9564e942020-11-10 14:01:42 -0600314 vinUVFault = false;
315 readFail = 0;
Brandon Wyman9564e942020-11-10 14:01:42 -0600316
Brandon Wyman11151532020-11-10 13:45:57 -0600317 try
318 {
319 static_cast<void>(
320 pmbusIntf->read("in1_input", phosphor::pmbus::Type::Hwmon));
321 }
Patrick Williamsc1d4de52021-10-06 12:45:57 -0500322 catch (const ReadFailure& e)
Brandon Wyman11151532020-11-10 13:45:57 -0600323 {
324 // Since I do not care what the return value is, I really do not
B. J. Wyman681b2a32021-04-20 22:31:22 +0000325 // care much if it gets a ReadFailure either. However, this
326 // should not prevent the application from continuing to run, so
327 // catching the read failure.
Brandon Wyman11151532020-11-10 13:45:57 -0600328 }
Brandon Wyman3c208462020-05-13 16:25:58 -0500329 }
330}
331
Brandon Wymanaed1f752019-11-25 18:10:52 -0600332void PowerSupply::inventoryChanged(sdbusplus::message::message& msg)
333{
334 std::string msgSensor;
Patrick Williamsabe49412020-05-13 17:59:47 -0500335 std::map<std::string, std::variant<uint32_t, bool>> msgData;
Brandon Wymanaed1f752019-11-25 18:10:52 -0600336 msg.read(msgSensor, msgData);
337
338 // Check if it was the Present property that changed.
339 auto valPropMap = msgData.find(PRESENT_PROP);
340 if (valPropMap != msgData.end())
341 {
342 if (std::get<bool>(valPropMap->second))
343 {
344 present = true;
B. J. Wyman681b2a32021-04-20 22:31:22 +0000345 // TODO: Immediately trying to read or write the "files" causes
346 // read or write failures.
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500347 using namespace std::chrono_literals;
348 std::this_thread::sleep_for(20ms);
Brandon Wyman9564e942020-11-10 14:01:42 -0600349 pmbusIntf->findHwmonDir();
Brandon Wyman59a35792020-06-04 12:37:40 -0500350 onOffConfig(phosphor::pmbus::ON_OFF_CONFIG_CONTROL_PIN_ONLY);
Brandon Wymanaed1f752019-11-25 18:10:52 -0600351 clearFaults();
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500352 updateInventory();
Brandon Wymanaed1f752019-11-25 18:10:52 -0600353 }
354 else
355 {
356 present = false;
357
358 // Clear out the now outdated inventory properties
359 updateInventory();
360 }
361 }
362}
363
Brandon Wyman9a507db2021-02-25 16:15:22 -0600364void PowerSupply::inventoryAdded(sdbusplus::message::message& msg)
365{
366 sdbusplus::message::object_path path;
367 msg.read(path);
368 // Make sure the signal is for the PSU inventory path
369 if (path == inventoryPath)
370 {
371 std::map<std::string, std::map<std::string, std::variant<bool>>>
372 interfaces;
373 // Get map of interfaces and their properties
374 msg.read(interfaces);
375
376 auto properties = interfaces.find(INVENTORY_IFACE);
377 if (properties != interfaces.end())
378 {
379 auto property = properties->second.find(PRESENT_PROP);
380 if (property != properties->second.end())
381 {
382 present = std::get<bool>(property->second);
383
384 log<level::INFO>(fmt::format("Power Supply {} Present {}",
385 inventoryPath, present)
386 .c_str());
387
388 updateInventory();
389 }
390 }
391 }
392}
393
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500394void PowerSupply::updateInventory()
395{
396 using namespace phosphor::pmbus;
397
Chanh Nguyenc12c53b2021-04-06 17:24:47 +0700398#if IBM_VPD
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500399 std::string ccin;
400 std::string pn;
401 std::string fn;
402 std::string header;
403 std::string sn;
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500404 using PropertyMap =
George Liu070c1bc2020-10-12 11:28:01 +0800405 std::map<std::string,
406 std::variant<std::string, std::vector<uint8_t>, bool>>;
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500407 PropertyMap assetProps;
George Liu070c1bc2020-10-12 11:28:01 +0800408 PropertyMap operProps;
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500409 PropertyMap versionProps;
410 PropertyMap ipzvpdDINFProps;
411 PropertyMap ipzvpdVINIProps;
412 using InterfaceMap = std::map<std::string, PropertyMap>;
413 InterfaceMap interfaces;
414 using ObjectMap = std::map<sdbusplus::message::object_path, InterfaceMap>;
415 ObjectMap object;
416#endif
B. J. Wyman681b2a32021-04-20 22:31:22 +0000417 log<level::DEBUG>(
418 fmt::format("updateInventory() inventoryPath: {}", inventoryPath)
419 .c_str());
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500420
421 if (present)
422 {
423 // TODO: non-IBM inventory updates?
424
Chanh Nguyenc12c53b2021-04-06 17:24:47 +0700425#if IBM_VPD
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500426 try
427 {
428 ccin = pmbusIntf->readString(CCIN, Type::HwmonDeviceDebug);
429 assetProps.emplace(MODEL_PROP, ccin);
Adriana Kobylak572a9052021-03-30 15:58:07 +0000430 modelName = ccin;
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500431 }
Patrick Williamsc1d4de52021-10-06 12:45:57 -0500432 catch (const ReadFailure& e)
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500433 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000434 // Ignore the read failure, let pmbus code indicate failure,
435 // path...
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500436 // TODO - ibm918
437 // https://github.com/openbmc/docs/blob/master/designs/vpd-collection.md
438 // The BMC must log errors if any of the VPD cannot be properly
439 // parsed or fails ECC checks.
440 }
441
442 try
443 {
444 pn = pmbusIntf->readString(PART_NUMBER, Type::HwmonDeviceDebug);
445 assetProps.emplace(PN_PROP, pn);
446 }
Patrick Williamsc1d4de52021-10-06 12:45:57 -0500447 catch (const ReadFailure& e)
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500448 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000449 // Ignore the read failure, let pmbus code indicate failure,
450 // path...
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500451 }
452
453 try
454 {
455 fn = pmbusIntf->readString(FRU_NUMBER, Type::HwmonDeviceDebug);
456 }
Patrick Williamsc1d4de52021-10-06 12:45:57 -0500457 catch (const ReadFailure& e)
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500458 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000459 // Ignore the read failure, let pmbus code indicate failure,
460 // path...
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500461 }
462
463 try
464 {
465 header =
466 pmbusIntf->readString(SERIAL_HEADER, Type::HwmonDeviceDebug);
467 sn = pmbusIntf->readString(SERIAL_NUMBER, Type::HwmonDeviceDebug);
468 assetProps.emplace(SN_PROP, sn);
469 }
Patrick Williamsc1d4de52021-10-06 12:45:57 -0500470 catch (const ReadFailure& e)
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500471 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000472 // Ignore the read failure, let pmbus code indicate failure,
473 // path...
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500474 }
475
476 try
477 {
Brandon Wymanc9efe412020-10-09 15:42:50 -0500478 fwVersion =
479 pmbusIntf->readString(FW_VERSION, Type::HwmonDeviceDebug);
480 versionProps.emplace(VERSION_PROP, fwVersion);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500481 }
Patrick Williamsc1d4de52021-10-06 12:45:57 -0500482 catch (const ReadFailure& e)
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500483 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000484 // Ignore the read failure, let pmbus code indicate failure,
485 // path...
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500486 }
487
488 ipzvpdVINIProps.emplace("CC",
489 std::vector<uint8_t>(ccin.begin(), ccin.end()));
490 ipzvpdVINIProps.emplace("PN",
491 std::vector<uint8_t>(pn.begin(), pn.end()));
492 ipzvpdVINIProps.emplace("FN",
493 std::vector<uint8_t>(fn.begin(), fn.end()));
494 std::string header_sn = header + sn + '\0';
495 ipzvpdVINIProps.emplace(
496 "SN", std::vector<uint8_t>(header_sn.begin(), header_sn.end()));
497 std::string description = "IBM PS";
498 ipzvpdVINIProps.emplace(
499 "DR", std::vector<uint8_t>(description.begin(), description.end()));
500
501 // Update the Resource Identifier (RI) keyword
502 // 2 byte FRC: 0x0003
503 // 2 byte RID: 0x1000, 0x1001...
504 std::uint8_t num = std::stoul(
505 inventoryPath.substr(inventoryPath.size() - 1, 1), nullptr, 0);
506 std::vector<uint8_t> ri{0x00, 0x03, 0x10, num};
507 ipzvpdDINFProps.emplace("RI", ri);
508
509 // Fill in the FRU Label (FL) keyword.
510 std::string fl = "E";
511 fl.push_back(inventoryPath.back());
512 fl.resize(FL_KW_SIZE, ' ');
513 ipzvpdDINFProps.emplace("FL",
514 std::vector<uint8_t>(fl.begin(), fl.end()));
515
516 interfaces.emplace(ASSET_IFACE, std::move(assetProps));
517 interfaces.emplace(VERSION_IFACE, std::move(versionProps));
518 interfaces.emplace(DINF_IFACE, std::move(ipzvpdDINFProps));
519 interfaces.emplace(VINI_IFACE, std::move(ipzvpdVINIProps));
520
George Liu070c1bc2020-10-12 11:28:01 +0800521 // Update the Functional
522 operProps.emplace(FUNCTIONAL_PROP, present);
523 interfaces.emplace(OPERATIONAL_STATE_IFACE, std::move(operProps));
524
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500525 auto path = inventoryPath.substr(strlen(INVENTORY_OBJ_PATH));
526 object.emplace(path, std::move(interfaces));
527
528 try
529 {
530 auto service =
531 util::getService(INVENTORY_OBJ_PATH, INVENTORY_MGR_IFACE, bus);
532
533 if (service.empty())
534 {
535 log<level::ERR>("Unable to get inventory manager service");
536 return;
537 }
538
539 auto method =
540 bus.new_method_call(service.c_str(), INVENTORY_OBJ_PATH,
541 INVENTORY_MGR_IFACE, "Notify");
542
543 method.append(std::move(object));
544
545 auto reply = bus.call(method);
546 }
Patrick Williamsc1d4de52021-10-06 12:45:57 -0500547 catch (const std::exception& e)
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500548 {
Jay Meyer6a3fd2c2020-08-25 16:37:16 -0500549 log<level::ERR>(
550 std::string(e.what() + std::string(" PATH=") + inventoryPath)
551 .c_str());
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500552 }
553#endif
554 }
555}
556
Adriana Kobylak4175ffb2021-08-02 14:51:05 +0000557void PowerSupply::getInputVoltage(double& actualInputVoltage,
558 int& inputVoltage) const
559{
560 using namespace phosphor::pmbus;
561
562 actualInputVoltage = in_input::VIN_VOLTAGE_0;
563 inputVoltage = in_input::VIN_VOLTAGE_0;
564
565 if (present)
566 {
567 try
568 {
569 // Read input voltage in millivolts
570 auto inputVoltageStr = pmbusIntf->readString(READ_VIN, Type::Hwmon);
571
572 // Convert to volts
573 actualInputVoltage = std::stod(inputVoltageStr) / 1000;
574
575 // Calculate the voltage based on voltage thresholds
576 if (actualInputVoltage < in_input::VIN_VOLTAGE_MIN)
577 {
578 inputVoltage = in_input::VIN_VOLTAGE_0;
579 }
580 else if (actualInputVoltage < in_input::VIN_VOLTAGE_110_THRESHOLD)
581 {
582 inputVoltage = in_input::VIN_VOLTAGE_110;
583 }
584 else
585 {
586 inputVoltage = in_input::VIN_VOLTAGE_220;
587 }
588 }
589 catch (const std::exception& e)
590 {
591 log<level::ERR>(
592 fmt::format("READ_VIN read error: {}", e.what()).c_str());
593 }
594 }
595}
596
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600597} // namespace phosphor::power::psu