1dfc7ec73SVishwanatha Subbanna #include <experimental/filesystem>
2dfc7ec73SVishwanatha Subbanna #include <phosphor-logging/log.hpp>
3dfc7ec73SVishwanatha Subbanna #include <phosphor-logging/elog-errors.hpp>
4dfc7ec73SVishwanatha Subbanna #include <xyz/openbmc_project/Common/error.hpp>
5dfc7ec73SVishwanatha Subbanna #include "occ_finder.hpp"
6dfc7ec73SVishwanatha Subbanna #include "occ_manager.hpp"
7dfc7ec73SVishwanatha Subbanna #include "i2c_occ.hpp"
8dfc7ec73SVishwanatha Subbanna #include "utils.hpp"
9dfc7ec73SVishwanatha Subbanna #include "config.h"
10dfc7ec73SVishwanatha Subbanna 
11dfc7ec73SVishwanatha Subbanna namespace open_power
12dfc7ec73SVishwanatha Subbanna {
13dfc7ec73SVishwanatha Subbanna namespace occ
14dfc7ec73SVishwanatha Subbanna {
15dfc7ec73SVishwanatha Subbanna 
16dfc7ec73SVishwanatha Subbanna void Manager::findAndCreateObjects()
17dfc7ec73SVishwanatha Subbanna {
18dfc7ec73SVishwanatha Subbanna     for (auto id = 0; id < MAX_CPUS; ++id)
19dfc7ec73SVishwanatha Subbanna     {
2030417a15SDeepak Kodihalli         // Create one occ per cpu
2130417a15SDeepak Kodihalli         auto occ = std::string(OCC_NAME) + std::to_string(id);
22dfc7ec73SVishwanatha Subbanna         createObjects(occ);
23dfc7ec73SVishwanatha Subbanna     }
24dfc7ec73SVishwanatha Subbanna }
25dfc7ec73SVishwanatha Subbanna 
26dfc7ec73SVishwanatha Subbanna int Manager::cpuCreated(sdbusplus::message::message& msg)
27dfc7ec73SVishwanatha Subbanna {
28dfc7ec73SVishwanatha Subbanna     namespace fs = std::experimental::filesystem;
29dfc7ec73SVishwanatha Subbanna 
30dfc7ec73SVishwanatha Subbanna     sdbusplus::message::object_path o;
31dfc7ec73SVishwanatha Subbanna     msg.read(o);
32dfc7ec73SVishwanatha Subbanna     fs::path cpuPath(std::string(std::move(o)));
33dfc7ec73SVishwanatha Subbanna 
34dfc7ec73SVishwanatha Subbanna     auto name = cpuPath.filename().string();
35dfc7ec73SVishwanatha Subbanna     auto index = name.find(CPU_NAME);
36dfc7ec73SVishwanatha Subbanna     name.replace(index, std::strlen(CPU_NAME), OCC_NAME);
37dfc7ec73SVishwanatha Subbanna 
38dfc7ec73SVishwanatha Subbanna     createObjects(name);
39dfc7ec73SVishwanatha Subbanna 
40dfc7ec73SVishwanatha Subbanna     return 0;
41dfc7ec73SVishwanatha Subbanna }
42dfc7ec73SVishwanatha Subbanna 
43dfc7ec73SVishwanatha Subbanna void Manager::createObjects(const std::string& occ)
44dfc7ec73SVishwanatha Subbanna {
45dfc7ec73SVishwanatha Subbanna     auto path = fs::path(OCC_CONTROL_ROOT) / occ;
46dfc7ec73SVishwanatha Subbanna 
47dfc7ec73SVishwanatha Subbanna     passThroughObjects.emplace_back(
48dfc7ec73SVishwanatha Subbanna             std::make_unique<PassThrough>(
49dfc7ec73SVishwanatha Subbanna                 bus,
50dfc7ec73SVishwanatha Subbanna                 path.c_str()));
51dfc7ec73SVishwanatha Subbanna 
52dfc7ec73SVishwanatha Subbanna     statusObjects.emplace_back(
53dfc7ec73SVishwanatha Subbanna             std::make_unique<Status>(
54dfc7ec73SVishwanatha Subbanna                 bus,
55dfc7ec73SVishwanatha Subbanna                 event,
56dfc7ec73SVishwanatha Subbanna                 path.c_str(),
57636577f4SEdward A. James                 *this,
58dfc7ec73SVishwanatha Subbanna                 std::bind(std::mem_fn(&Manager::statusCallBack),
59dfc7ec73SVishwanatha Subbanna                     this, std::placeholders::_1)));
60dfc7ec73SVishwanatha Subbanna 
61dfc7ec73SVishwanatha Subbanna     // Create the power cap monitor object for master occ (0)
62dfc7ec73SVishwanatha Subbanna     if (!pcap)
63dfc7ec73SVishwanatha Subbanna     {
64dfc7ec73SVishwanatha Subbanna         pcap = std::make_unique<open_power::occ::powercap::PowerCap>(
65dfc7ec73SVishwanatha Subbanna                 bus,
66dfc7ec73SVishwanatha Subbanna                 *statusObjects.front());
67dfc7ec73SVishwanatha Subbanna     }
68dfc7ec73SVishwanatha Subbanna }
69dfc7ec73SVishwanatha Subbanna 
70dfc7ec73SVishwanatha Subbanna void Manager::statusCallBack(bool status)
71dfc7ec73SVishwanatha Subbanna {
72dfc7ec73SVishwanatha Subbanna     using namespace phosphor::logging;
73dfc7ec73SVishwanatha Subbanna     using InternalFailure = sdbusplus::xyz::openbmc_project::Common::
74dfc7ec73SVishwanatha Subbanna         Error::InternalFailure;
75dfc7ec73SVishwanatha Subbanna 
76dfc7ec73SVishwanatha Subbanna     // At this time, it won't happen but keeping it
77dfc7ec73SVishwanatha Subbanna     // here just in case something changes in the future
78dfc7ec73SVishwanatha Subbanna     if ((activeCount == 0) && (!status))
79dfc7ec73SVishwanatha Subbanna     {
80dfc7ec73SVishwanatha Subbanna         log<level::ERR>("Invalid update on OCCActive");
81dfc7ec73SVishwanatha Subbanna         elog<InternalFailure>();
82dfc7ec73SVishwanatha Subbanna     }
83dfc7ec73SVishwanatha Subbanna 
84dfc7ec73SVishwanatha Subbanna     activeCount += status ? 1 : -1;
85dfc7ec73SVishwanatha Subbanna 
86dfc7ec73SVishwanatha Subbanna     // If all the OCCs are bound, then start error detection
87dfc7ec73SVishwanatha Subbanna     if (activeCount == statusObjects.size())
88dfc7ec73SVishwanatha Subbanna     {
89dfc7ec73SVishwanatha Subbanna         for (const auto& occ: statusObjects)
90dfc7ec73SVishwanatha Subbanna         {
91dfc7ec73SVishwanatha Subbanna             occ->addErrorWatch();
92dfc7ec73SVishwanatha Subbanna         }
93dfc7ec73SVishwanatha Subbanna     }
94dfc7ec73SVishwanatha Subbanna     else if (!status)
95dfc7ec73SVishwanatha Subbanna     {
96dfc7ec73SVishwanatha Subbanna         // If some OCCs are not bound yet, those will be a NO-OP
97dfc7ec73SVishwanatha Subbanna         for (const auto& occ: statusObjects)
98dfc7ec73SVishwanatha Subbanna         {
99dfc7ec73SVishwanatha Subbanna             occ->removeErrorWatch();
100dfc7ec73SVishwanatha Subbanna         }
101dfc7ec73SVishwanatha Subbanna     }
102dfc7ec73SVishwanatha Subbanna }
103dfc7ec73SVishwanatha Subbanna 
104dfc7ec73SVishwanatha Subbanna #ifdef I2C_OCC
105dfc7ec73SVishwanatha Subbanna void Manager::initStatusObjects()
106dfc7ec73SVishwanatha Subbanna {
107dfc7ec73SVishwanatha Subbanna     // Make sure we have a valid path string
108dfc7ec73SVishwanatha Subbanna     static_assert(sizeof(DEV_PATH) != 0);
109dfc7ec73SVishwanatha Subbanna 
110dfc7ec73SVishwanatha Subbanna     auto deviceNames = i2c_occ::getOccHwmonDevices(DEV_PATH);
111*41470e56SLei YU     auto occMasterName = deviceNames.front();
112dfc7ec73SVishwanatha Subbanna     for (auto& name : deviceNames)
113dfc7ec73SVishwanatha Subbanna     {
114dfc7ec73SVishwanatha Subbanna         i2c_occ::i2cToDbus(name);
115b5259a1eSLei YU         name = std::string(OCC_NAME) + '_' + name;
116dfc7ec73SVishwanatha Subbanna         auto path = fs::path(OCC_CONTROL_ROOT) / name;
117dfc7ec73SVishwanatha Subbanna         statusObjects.emplace_back(
118dfc7ec73SVishwanatha Subbanna             std::make_unique<Status>(
119dfc7ec73SVishwanatha Subbanna                 bus,
120dfc7ec73SVishwanatha Subbanna                 event,
121636577f4SEdward A. James                 path.c_str(),
122636577f4SEdward A. James                 *this));
123dfc7ec73SVishwanatha Subbanna     }
124*41470e56SLei YU     // The first device is master occ
125*41470e56SLei YU     pcap = std::make_unique<open_power::occ::powercap::PowerCap>(
126*41470e56SLei YU                bus,
127*41470e56SLei YU                *statusObjects.front(),
128*41470e56SLei YU                occMasterName);
129dfc7ec73SVishwanatha Subbanna }
130dfc7ec73SVishwanatha Subbanna #endif
131dfc7ec73SVishwanatha Subbanna 
132dfc7ec73SVishwanatha Subbanna } // namespace occ
133dfc7ec73SVishwanatha Subbanna } // namespace open_power
134