xref: /openbmc/phosphor-power/pmbus.cpp (revision 92261f88729b618b1c31d20f28328a8aff73b83b)
1015e3adeSMatt Spinler /**
2015e3adeSMatt Spinler  * Copyright © 2017 IBM Corporation
3015e3adeSMatt Spinler  *
4015e3adeSMatt Spinler  * Licensed under the Apache License, Version 2.0 (the "License");
5015e3adeSMatt Spinler  * you may not use this file except in compliance with the License.
6015e3adeSMatt Spinler  * You may obtain a copy of the License at
7015e3adeSMatt Spinler  *
8015e3adeSMatt Spinler  *     http://www.apache.org/licenses/LICENSE-2.0
9015e3adeSMatt Spinler  *
10015e3adeSMatt Spinler  * Unless required by applicable law or agreed to in writing, software
11015e3adeSMatt Spinler  * distributed under the License is distributed on an "AS IS" BASIS,
12015e3adeSMatt Spinler  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13015e3adeSMatt Spinler  * See the License for the specific language governing permissions and
14015e3adeSMatt Spinler  * limitations under the License.
15015e3adeSMatt Spinler  */
16f0f02b9aSMatt Spinler #include "pmbus.hpp"
17f0f02b9aSMatt Spinler 
18015e3adeSMatt Spinler #include <phosphor-logging/elog-errors.hpp>
19f0f02b9aSMatt Spinler #include <phosphor-logging/elog.hpp>
20ceacf941SMatt Spinler #include <xyz/openbmc_project/Common/Device/error.hpp>
21f0f02b9aSMatt Spinler #include <xyz/openbmc_project/Common/error.hpp>
22015e3adeSMatt Spinler 
23d1bc4cecSBrandon Wyman #include <filesystem>
24d1bc4cecSBrandon Wyman #include <fstream>
25d1bc4cecSBrandon Wyman 
26ab093328SLei YU namespace phosphor
27015e3adeSMatt Spinler {
28015e3adeSMatt Spinler namespace pmbus
29015e3adeSMatt Spinler {
30015e3adeSMatt Spinler 
31015e3adeSMatt Spinler using namespace phosphor::logging;
32015e3adeSMatt Spinler using namespace sdbusplus::xyz::openbmc_project::Common::Error;
33ceacf941SMatt Spinler using namespace sdbusplus::xyz::openbmc_project::Common::Device::Error;
349c7897ceSBrandon Wyman namespace fs = std::filesystem;
35015e3adeSMatt Spinler 
36fa23e330SMatt Spinler /**
37fa23e330SMatt Spinler  * @brief Helper to close a file handle
38fa23e330SMatt Spinler  */
39fa23e330SMatt Spinler struct FileCloser
40fa23e330SMatt Spinler {
operator ()phosphor::pmbus::FileCloser41fa23e330SMatt Spinler     void operator()(FILE* fp) const
42fa23e330SMatt Spinler     {
43fa23e330SMatt Spinler         fclose(fp);
44fa23e330SMatt Spinler     }
45fa23e330SMatt Spinler };
46fa23e330SMatt Spinler 
insertPageNum(const std::string & templateName,size_t page)47f0f02b9aSMatt Spinler std::string PMBus::insertPageNum(const std::string& templateName, size_t page)
48015e3adeSMatt Spinler {
49015e3adeSMatt Spinler     auto name = templateName;
50015e3adeSMatt Spinler 
51015e3adeSMatt Spinler     // insert the page where the P was
52015e3adeSMatt Spinler     auto pos = name.find('P');
53015e3adeSMatt Spinler     if (pos != std::string::npos)
54015e3adeSMatt Spinler     {
55015e3adeSMatt Spinler         name.replace(pos, 1, std::to_string(page));
56015e3adeSMatt Spinler     }
57015e3adeSMatt Spinler 
58015e3adeSMatt Spinler     return name;
59015e3adeSMatt Spinler }
60015e3adeSMatt Spinler 
getPath(Type type)61ff5f339cSBrandon Wyman fs::path PMBus::getPath(Type type)
62ff5f339cSBrandon Wyman {
63ff5f339cSBrandon Wyman     switch (type)
64ff5f339cSBrandon Wyman     {
65ff5f339cSBrandon Wyman         default:
66ff5f339cSBrandon Wyman         /* fall through */
67ff5f339cSBrandon Wyman         case Type::Base:
68ff5f339cSBrandon Wyman             return basePath;
69ff5f339cSBrandon Wyman             break;
70ff5f339cSBrandon Wyman         case Type::Hwmon:
71ff5f339cSBrandon Wyman             return basePath / "hwmon" / hwmonDir;
72ff5f339cSBrandon Wyman             break;
73ff5f339cSBrandon Wyman         case Type::Debug:
748f0d953fSMatt Spinler             return debugPath / "pmbus" / hwmonDir;
758f0d953fSMatt Spinler             break;
768f0d953fSMatt Spinler         case Type::DeviceDebug:
774dc4678eSMatt Spinler         {
788f0d953fSMatt Spinler             auto dir = driverName + "." + std::to_string(instance);
798f0d953fSMatt Spinler             return debugPath / dir;
80ff5f339cSBrandon Wyman             break;
81ff5f339cSBrandon Wyman         }
824dc4678eSMatt Spinler         case Type::HwmonDeviceDebug:
834dc4678eSMatt Spinler             return debugPath / "pmbus" / hwmonDir / getDeviceName();
844dc4678eSMatt Spinler             break;
854dc4678eSMatt Spinler     }
86ff5f339cSBrandon Wyman }
87ff5f339cSBrandon Wyman 
getDeviceName()88ba05348fSMatt Spinler std::string PMBus::getDeviceName()
89ba05348fSMatt Spinler {
90ba05348fSMatt Spinler     std::string name;
91ba05348fSMatt Spinler     std::ifstream file;
92ba05348fSMatt Spinler     auto path = basePath / "name";
93ba05348fSMatt Spinler 
94f0f02b9aSMatt Spinler     file.exceptions(std::ifstream::failbit | std::ifstream::badbit |
95ba05348fSMatt Spinler                     std::ifstream::eofbit);
96ba05348fSMatt Spinler     try
97ba05348fSMatt Spinler     {
98ba05348fSMatt Spinler         file.open(path);
99ba05348fSMatt Spinler         file >> name;
100ba05348fSMatt Spinler     }
101c1d4de5eSPatrick Williams     catch (const std::exception& e)
102ba05348fSMatt Spinler     {
1036a3fd2c2SJay Meyer         log<level::ERR>((std::string("Unable to read PMBus device name "
1046a3fd2c2SJay Meyer                                      "PATH=") +
1056a3fd2c2SJay Meyer                          path.string())
1066a3fd2c2SJay Meyer                             .c_str());
107ba05348fSMatt Spinler     }
108ba05348fSMatt Spinler 
109ba05348fSMatt Spinler     return name;
110ba05348fSMatt Spinler }
111ba05348fSMatt Spinler 
readBitInPage(const std::string & name,size_t page,Type type)112f0f02b9aSMatt Spinler bool PMBus::readBitInPage(const std::string& name, size_t page, Type type)
113015e3adeSMatt Spinler {
114015e3adeSMatt Spinler     auto pagedBit = insertPageNum(name, page);
11557868bc5SMatt Spinler     return readBit(pagedBit, type);
116015e3adeSMatt Spinler }
117015e3adeSMatt Spinler 
readBit(const std::string & name,Type type)11857868bc5SMatt Spinler bool PMBus::readBit(const std::string& name, Type type)
119015e3adeSMatt Spinler {
120015e3adeSMatt Spinler     unsigned long int value = 0;
121015e3adeSMatt Spinler     std::ifstream file;
122ff5f339cSBrandon Wyman     fs::path path = getPath(type);
12357868bc5SMatt Spinler 
124015e3adeSMatt Spinler     path /= name;
125015e3adeSMatt Spinler 
126f0f02b9aSMatt Spinler     file.exceptions(std::ifstream::failbit | std::ifstream::badbit |
127015e3adeSMatt Spinler                     std::ifstream::eofbit);
128015e3adeSMatt Spinler 
129015e3adeSMatt Spinler     try
130015e3adeSMatt Spinler     {
131757ad6a9SJayanth Othayoth         char* err = nullptr;
132015e3adeSMatt Spinler         std::string val{1, '\0'};
133015e3adeSMatt Spinler 
134015e3adeSMatt Spinler         file.open(path);
135015e3adeSMatt Spinler         file.read(&val[0], 1);
136015e3adeSMatt Spinler 
137015e3adeSMatt Spinler         value = strtoul(val.c_str(), &err, 10);
138015e3adeSMatt Spinler 
139015e3adeSMatt Spinler         if (*err)
140015e3adeSMatt Spinler         {
1416a3fd2c2SJay Meyer             log<level::ERR>((std::string("Invalid character in sysfs file"
1426a3fd2c2SJay Meyer                                          " FILE=") +
1436a3fd2c2SJay Meyer                              path.string() + std::string(" CONTENTS=") + val)
1446a3fd2c2SJay Meyer                                 .c_str());
145015e3adeSMatt Spinler 
146015e3adeSMatt Spinler             // Catch below and handle as a read failure
147015e3adeSMatt Spinler             elog<InternalFailure>();
148015e3adeSMatt Spinler         }
149015e3adeSMatt Spinler     }
150c1d4de5eSPatrick Williams     catch (const std::exception& e)
151015e3adeSMatt Spinler     {
152015e3adeSMatt Spinler         auto rc = errno;
153015e3adeSMatt Spinler 
154f5402197SPatrick Williams         log<level::ERR>(
155f5402197SPatrick Williams             (std::string("Failed to read sysfs file "
1566a3fd2c2SJay Meyer                          "errno=") +
157f5402197SPatrick Williams              std::to_string(rc) + std::string(" FILENAME=") + path.string())
1586a3fd2c2SJay Meyer                 .c_str());
159015e3adeSMatt Spinler 
160ceacf941SMatt Spinler         using metadata = xyz::openbmc_project::Common::Device::ReadFailure;
161ceacf941SMatt Spinler 
162f0f02b9aSMatt Spinler         elog<ReadFailure>(
163f0f02b9aSMatt Spinler             metadata::CALLOUT_ERRNO(rc),
164f0f02b9aSMatt Spinler             metadata::CALLOUT_DEVICE_PATH(fs::canonical(basePath).c_str()));
165015e3adeSMatt Spinler     }
166015e3adeSMatt Spinler 
167015e3adeSMatt Spinler     return value != 0;
168015e3adeSMatt Spinler }
169015e3adeSMatt Spinler 
exists(const std::string & name,Type type)1703b7b38baSBrandon Wyman bool PMBus::exists(const std::string& name, Type type)
1713b7b38baSBrandon Wyman {
1723b7b38baSBrandon Wyman     auto path = getPath(type);
1733b7b38baSBrandon Wyman     path /= name;
1743b7b38baSBrandon Wyman     return fs::exists(path);
1753b7b38baSBrandon Wyman }
1763b7b38baSBrandon Wyman 
read(const std::string & name,Type type,bool errTrace)17732453e9bSBrandon Wyman uint64_t PMBus::read(const std::string& name, Type type, bool errTrace)
178f855e82aSBrandon Wyman {
179f855e82aSBrandon Wyman     uint64_t data = 0;
180f855e82aSBrandon Wyman     std::ifstream file;
181f855e82aSBrandon Wyman     auto path = getPath(type);
182f855e82aSBrandon Wyman     path /= name;
183f855e82aSBrandon Wyman 
184f0f02b9aSMatt Spinler     file.exceptions(std::ifstream::failbit | std::ifstream::badbit |
185f855e82aSBrandon Wyman                     std::ifstream::eofbit);
186f855e82aSBrandon Wyman 
187f855e82aSBrandon Wyman     try
188f855e82aSBrandon Wyman     {
189f855e82aSBrandon Wyman         file.open(path);
190f855e82aSBrandon Wyman         file >> std::hex >> data;
191f855e82aSBrandon Wyman     }
192c1d4de5eSPatrick Williams     catch (const std::exception& e)
193f855e82aSBrandon Wyman     {
194f855e82aSBrandon Wyman         auto rc = errno;
19532453e9bSBrandon Wyman 
19632453e9bSBrandon Wyman         if (errTrace)
19732453e9bSBrandon Wyman         {
1986a3fd2c2SJay Meyer             log<level::ERR>((std::string("Failed to read sysfs file "
1996a3fd2c2SJay Meyer                                          "errno=") +
2006a3fd2c2SJay Meyer                              std::to_string(rc) + " FILENAME=" + path.string())
2016a3fd2c2SJay Meyer                                 .c_str());
202f855e82aSBrandon Wyman 
203ceacf941SMatt Spinler             using metadata = xyz::openbmc_project::Common::Device::ReadFailure;
204f855e82aSBrandon Wyman 
205f0f02b9aSMatt Spinler             elog<ReadFailure>(
206f0f02b9aSMatt Spinler                 metadata::CALLOUT_ERRNO(rc),
207f0f02b9aSMatt Spinler                 metadata::CALLOUT_DEVICE_PATH(fs::canonical(basePath).c_str()));
208f855e82aSBrandon Wyman         }
20932453e9bSBrandon Wyman         else
21032453e9bSBrandon Wyman         {
21132453e9bSBrandon Wyman             throw ReadFailure();
21232453e9bSBrandon Wyman         }
21332453e9bSBrandon Wyman     }
214f855e82aSBrandon Wyman 
215f855e82aSBrandon Wyman     return data;
216f855e82aSBrandon Wyman }
217f855e82aSBrandon Wyman 
readString(const std::string & name,Type type)218fbae7b6cSMatt Spinler std::string PMBus::readString(const std::string& name, Type type)
219fbae7b6cSMatt Spinler {
220fbae7b6cSMatt Spinler     std::string data;
221fbae7b6cSMatt Spinler     std::ifstream file;
222fbae7b6cSMatt Spinler     auto path = getPath(type);
223fbae7b6cSMatt Spinler     path /= name;
224fbae7b6cSMatt Spinler 
225f0f02b9aSMatt Spinler     file.exceptions(std::ifstream::failbit | std::ifstream::badbit |
226fbae7b6cSMatt Spinler                     std::ifstream::eofbit);
227fbae7b6cSMatt Spinler 
228fbae7b6cSMatt Spinler     try
229fbae7b6cSMatt Spinler     {
230fbae7b6cSMatt Spinler         file.open(path);
231fbae7b6cSMatt Spinler         file >> data;
232fbae7b6cSMatt Spinler     }
233c1d4de5eSPatrick Williams     catch (const std::exception& e)
234fbae7b6cSMatt Spinler     {
235fbae7b6cSMatt Spinler         auto rc = errno;
2366a3fd2c2SJay Meyer         log<level::ERR>((std::string("Failed to read sysfs file "
2376a3fd2c2SJay Meyer                                      "errno=") +
2386a3fd2c2SJay Meyer                          std::to_string(rc) + " FILENAME=" + path.string())
2396a3fd2c2SJay Meyer                             .c_str());
240fbae7b6cSMatt Spinler 
241fbae7b6cSMatt Spinler         using metadata = xyz::openbmc_project::Common::Device::ReadFailure;
242fbae7b6cSMatt Spinler 
243f0f02b9aSMatt Spinler         elog<ReadFailure>(
244f0f02b9aSMatt Spinler             metadata::CALLOUT_ERRNO(rc),
245f0f02b9aSMatt Spinler             metadata::CALLOUT_DEVICE_PATH(fs::canonical(basePath).c_str()));
246fbae7b6cSMatt Spinler     }
247fbae7b6cSMatt Spinler 
248fbae7b6cSMatt Spinler     return data;
249fbae7b6cSMatt Spinler }
250fbae7b6cSMatt Spinler 
readBinary(const std::string & name,Type type,size_t length)251f0f02b9aSMatt Spinler std::vector<uint8_t> PMBus::readBinary(const std::string& name, Type type,
252fa23e330SMatt Spinler                                        size_t length)
253fa23e330SMatt Spinler {
254fa23e330SMatt Spinler     auto path = getPath(type) / name;
255fa23e330SMatt Spinler 
256fa23e330SMatt Spinler     // Use C style IO because it's easier to handle telling the difference
257fa23e330SMatt Spinler     // between hitting EOF or getting an actual error.
258fa23e330SMatt Spinler     std::unique_ptr<FILE, FileCloser> file{fopen(path.c_str(), "rb")};
259fa23e330SMatt Spinler 
260fa23e330SMatt Spinler     if (file)
261fa23e330SMatt Spinler     {
262fa23e330SMatt Spinler         std::vector<uint8_t> data(length, 0);
263fa23e330SMatt Spinler 
264f5402197SPatrick Williams         auto bytes =
265f5402197SPatrick Williams             fread(data.data(), sizeof(decltype(data[0])), length, file.get());
266fa23e330SMatt Spinler 
267fa23e330SMatt Spinler         if (bytes != length)
268fa23e330SMatt Spinler         {
269fa23e330SMatt Spinler             // If hit EOF, just return the amount of data that was read.
270fa23e330SMatt Spinler             if (feof(file.get()))
271fa23e330SMatt Spinler             {
272fa23e330SMatt Spinler                 data.erase(data.begin() + bytes, data.end());
273fa23e330SMatt Spinler             }
274fa23e330SMatt Spinler             else if (ferror(file.get()))
275fa23e330SMatt Spinler             {
276fa23e330SMatt Spinler                 auto rc = errno;
277f5402197SPatrick Williams                 log<level::ERR>(
278f5402197SPatrick Williams                     (std::string("Failed to read sysfs file "
2796a3fd2c2SJay Meyer                                  "errno=") +
280f5402197SPatrick Williams                      std::to_string(rc) + " FILENAME=" + path.string())
2816a3fd2c2SJay Meyer                         .c_str());
282f0f02b9aSMatt Spinler                 using metadata =
283f0f02b9aSMatt Spinler                     xyz::openbmc_project::Common::Device::ReadFailure;
284fa23e330SMatt Spinler 
285fa23e330SMatt Spinler                 elog<ReadFailure>(metadata::CALLOUT_ERRNO(rc),
286fa23e330SMatt Spinler                                   metadata::CALLOUT_DEVICE_PATH(
287fa23e330SMatt Spinler                                       fs::canonical(basePath).c_str()));
288fa23e330SMatt Spinler             }
289fa23e330SMatt Spinler         }
290fa23e330SMatt Spinler         return data;
291fa23e330SMatt Spinler     }
292fa23e330SMatt Spinler 
293fa23e330SMatt Spinler     return std::vector<uint8_t>{};
294fa23e330SMatt Spinler }
295fa23e330SMatt Spinler 
write(const std::string & name,int value,Type type)29657868bc5SMatt Spinler void PMBus::write(const std::string& name, int value, Type type)
297015e3adeSMatt Spinler {
298015e3adeSMatt Spinler     std::ofstream file;
299ff5f339cSBrandon Wyman     fs::path path = getPath(type);
30057868bc5SMatt Spinler 
301015e3adeSMatt Spinler     path /= name;
302015e3adeSMatt Spinler 
303f0f02b9aSMatt Spinler     file.exceptions(std::ofstream::failbit | std::ofstream::badbit |
304015e3adeSMatt Spinler                     std::ofstream::eofbit);
305015e3adeSMatt Spinler 
306015e3adeSMatt Spinler     try
307015e3adeSMatt Spinler     {
308015e3adeSMatt Spinler         file.open(path);
309015e3adeSMatt Spinler         file << value;
310015e3adeSMatt Spinler     }
311015e3adeSMatt Spinler     catch (const std::exception& e)
312015e3adeSMatt Spinler     {
313015e3adeSMatt Spinler         auto rc = errno;
3146a3fd2c2SJay Meyer         log<level::ERR>((std::string("Failed to write sysfs file "
3156a3fd2c2SJay Meyer                                      "errno=") +
3166a3fd2c2SJay Meyer                          std::to_string(rc) + " FILENAME=" + path.string())
3176a3fd2c2SJay Meyer                             .c_str());
318015e3adeSMatt Spinler 
319ceacf941SMatt Spinler         using metadata = xyz::openbmc_project::Common::Device::WriteFailure;
320ceacf941SMatt Spinler 
321f0f02b9aSMatt Spinler         elog<WriteFailure>(
322f0f02b9aSMatt Spinler             metadata::CALLOUT_ERRNO(rc),
323f0f02b9aSMatt Spinler             metadata::CALLOUT_DEVICE_PATH(fs::canonical(basePath).c_str()));
324015e3adeSMatt Spinler     }
325015e3adeSMatt Spinler }
326015e3adeSMatt Spinler 
writeBinary(const std::string & name,std::vector<uint8_t> data,Type type)32759a35793SBrandon Wyman void PMBus::writeBinary(const std::string& name, std::vector<uint8_t> data,
32859a35793SBrandon Wyman                         Type type)
32959a35793SBrandon Wyman {
33059a35793SBrandon Wyman     std::ofstream file;
33159a35793SBrandon Wyman     fs::path path = getPath(type);
33259a35793SBrandon Wyman 
33359a35793SBrandon Wyman     path /= name;
33459a35793SBrandon Wyman 
33559a35793SBrandon Wyman     file.exceptions(std::ofstream::failbit | std::ofstream::badbit |
33659a35793SBrandon Wyman                     std::ofstream::eofbit);
33759a35793SBrandon Wyman 
33859a35793SBrandon Wyman     try
33959a35793SBrandon Wyman     {
34059a35793SBrandon Wyman         // I need to specify binary mode when I construct the ofstream
34159a35793SBrandon Wyman         file.open(path, std::ios::out | std::ios_base::binary);
3426a3fd2c2SJay Meyer         log<level::DEBUG>(std::string("Write data to sysfs file "
3436a3fd2c2SJay Meyer                                       "FILENAME=" +
3446a3fd2c2SJay Meyer                                       path.string())
3456a3fd2c2SJay Meyer                               .c_str());
34659a35793SBrandon Wyman         file.write(reinterpret_cast<const char*>(&data[0]), data.size());
34759a35793SBrandon Wyman     }
34859a35793SBrandon Wyman     catch (const std::exception& e)
34959a35793SBrandon Wyman     {
35059a35793SBrandon Wyman         auto rc = errno;
3516a3fd2c2SJay Meyer         log<level::ERR>(
3526a3fd2c2SJay Meyer             (std::string("Failed to write binary data to sysfs file "
3536a3fd2c2SJay Meyer                          "errno=") +
3546a3fd2c2SJay Meyer              std::to_string(rc) + " FILENAME=" + path.string())
3556a3fd2c2SJay Meyer                 .c_str());
35659a35793SBrandon Wyman 
35759a35793SBrandon Wyman         using metadata = xyz::openbmc_project::Common::Device::WriteFailure;
35859a35793SBrandon Wyman 
35959a35793SBrandon Wyman         elog<WriteFailure>(
36059a35793SBrandon Wyman             metadata::CALLOUT_ERRNO(rc),
36159a35793SBrandon Wyman             metadata::CALLOUT_DEVICE_PATH(fs::canonical(basePath).c_str()));
36259a35793SBrandon Wyman     }
36359a35793SBrandon Wyman }
36459a35793SBrandon Wyman 
findHwmonDir()365ff5f339cSBrandon Wyman void PMBus::findHwmonDir()
36657868bc5SMatt Spinler {
36757868bc5SMatt Spinler     fs::path path{basePath};
36857868bc5SMatt Spinler     path /= "hwmon";
36957868bc5SMatt Spinler 
370aad73e92SBrandon Wyman     // Make sure the directory exists, otherwise for things that can be
371aad73e92SBrandon Wyman     // dynamically present or not present an exception will be thrown if the
372aad73e92SBrandon Wyman     // hwmon directory is not there, resulting in a program termination.
373aad73e92SBrandon Wyman     if (fs::is_directory(path))
374aad73e92SBrandon Wyman     {
37557868bc5SMatt Spinler         // look for <basePath>/hwmon/hwmonN/
37657868bc5SMatt Spinler         for (auto& f : fs::directory_iterator(path))
37757868bc5SMatt Spinler         {
37857868bc5SMatt Spinler             if ((f.path().filename().string().find("hwmon") !=
37957868bc5SMatt Spinler                  std::string::npos) &&
38057868bc5SMatt Spinler                 (fs::is_directory(f.path())))
38157868bc5SMatt Spinler             {
382ff5f339cSBrandon Wyman                 hwmonDir = f.path().filename();
38357868bc5SMatt Spinler                 break;
38457868bc5SMatt Spinler             }
38557868bc5SMatt Spinler         }
386aad73e92SBrandon Wyman     }
38757868bc5SMatt Spinler 
38857868bc5SMatt Spinler     // Don't really want to crash here, just log it
38957868bc5SMatt Spinler     // and let accesses fail later
390ff5f339cSBrandon Wyman     if (hwmonDir.empty())
39157868bc5SMatt Spinler     {
3926a3fd2c2SJay Meyer         log<level::INFO>(std::string("Unable to find hwmon directory "
3936a3fd2c2SJay Meyer                                      "in device base path"
3946a3fd2c2SJay Meyer                                      " DEVICE_PATH=" +
3956a3fd2c2SJay Meyer                                      basePath.string())
3966a3fd2c2SJay Meyer                              .c_str());
39757868bc5SMatt Spinler     }
39857868bc5SMatt Spinler }
39957868bc5SMatt Spinler 
createPMBus(std::uint8_t bus,const std::string & address)400*92261f88SPatrick Williams std::unique_ptr<PMBusBase> PMBus::createPMBus(std::uint8_t bus,
401*92261f88SPatrick Williams                                               const std::string& address)
4028d195771SBrandon Wyman {
403f5402197SPatrick Williams     const std::string physpath = {
404f5402197SPatrick Williams         "/sys/bus/i2c/devices/" + std::to_string(bus) + "-" + address};
4058d195771SBrandon Wyman     auto interface = std::make_unique<PMBus>(physpath);
4068d195771SBrandon Wyman 
4078d195771SBrandon Wyman     return interface;
4088d195771SBrandon Wyman }
4098d195771SBrandon Wyman 
createPMBus(std::uint8_t bus,const std::string & address)4108d195771SBrandon Wyman std::unique_ptr<PMBusBase> createPMBus(std::uint8_t bus,
4118d195771SBrandon Wyman                                        const std::string& address)
4128d195771SBrandon Wyman {
4138d195771SBrandon Wyman     return PMBus::createPMBus(bus, address);
4148d195771SBrandon Wyman }
4158d195771SBrandon Wyman 
416f0f02b9aSMatt Spinler } // namespace pmbus
417ab093328SLei YU } // namespace phosphor
418