Enable dynamic presence detect of FRUs
This commit enables presence detect of FRUs at runtime.
Anytime any FRU can get attached or de-attached,
this code will detect it and will enable/disable the corresponding
output I2C pin respectively.
Right now we have only one FRU- op-panel, which is attachable or
de-attachable at runtime.
Test- Tested on Simics:
>> 2timers keep running, as part of vpd-manager-
./vpd-manager
keep checking for event occurance...
hasEventOccurred ?
keep checking for event occurance...
hasEventOccurred ?
>> changed signal at presence-pin of FRU2
keep checking for event occurance...
hasEventOccurred ?
keep checking for event occurance...
hasEventOccurred ?
Yes, togggle the gpio <---------------------event on 2nd timer
>> Again, changed signal at presence-pin of FRU2
keep checking for event occurance...
hasEventOccurred ?
keep checking for event occurance...
hasEventOccurred ?
Yes, togggle the gpio <---------------------event on 2nd timer
>> changed signal at presence-pin of FRU1
keep checking for event occurance...
hasEventOccurred ?
Yes, togggle the gpio <---------------------event on 1st timer
keep checking for event occurance...
hasEventOccurred ?
>> Again changed signal at presence-pin of FRU1
keep checking for event occurance...
hasEventOccurred ?
Yes, togggle the gpio <---------------------event on 1st timer
keep checking for event occurance...
hasEventOccurred ?
>> Noticed change on output gpio after every signal change.
As of now for testing, output gpio is same for both of these FRUs-
>> Effects on i2c-
i2cdetect -y 7
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: 20 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- UU -- -- -- -- -- -- --
50: UU UU UU -- -- -- -- -- -- -- 5a -- -- -- -- --
60: UU UU UU -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- UU --
i2cdetect -y 7
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: 20 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- UU -- -- -- -- -- -- --
50: UU 51 UU -- -- -- -- -- -- -- 5a -- -- -- -- --
60: UU UU UU -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- UU --
Also tested for write functionality, shouldn't be affected due to this change
It looks fine.
root@p10bmc:~# busctl introspect xyz.openbmc_project.Inventory.Manager /xyz/openbmc_project/inventory/system/chassis/motherboard |grep PN
.PN property ay 7 48 50 87 71 54 55 56 emits-change writable
root@p10bmc:~# busctl call com.ibm.VPD.Manager /com/ibm/VPD/Manager com.ibm.VPD.Manager WriteKeyword ossay "/system/chassis/motherboard" "VINI" "PN" 1 80
root@p10bmc:~# busctl introspect xyz.openbmc_project.Inventory.Manager /xyz/openbmc_project/inventory/system/chassis/motherboard |grep PN
.PN property ay 7 80 50 87 71 54 55 56 emits-change writable
root@p10bmc:~# busctl call com.ibm.VPD.Manager /com/ibm/VPD/Manager com.ibm.VPD.Manager WriteKeyword ossay "/system/chassis/motherboard" "VINI" "PN" 1 48
root@p10bmc:~# busctl introspect xyz.openbmc_project.Inventory.Manager /xyz/openbmc_project/inventory/system/chassis/motherboard |grep PN
.PN property ay 7 48 50 87 71 54 55 56 emits-change writable
Change-Id: If7d311d36bf56ece751afe393a9ba2d83be5df11
Signed-off-by: Alpana Kumari <alpankum@in.ibm.com>
diff --git a/vpd-manager/gpioMonitor.cpp b/vpd-manager/gpioMonitor.cpp
new file mode 100644
index 0000000..b57d52c
--- /dev/null
+++ b/vpd-manager/gpioMonitor.cpp
@@ -0,0 +1,173 @@
+#include "gpioMonitor.hpp"
+
+#include "common_utility.hpp"
+#include "ibm_vpd_utils.hpp"
+
+#include <systemd/sd-event.h>
+
+#include <chrono>
+#include <gpiod.hpp>
+#include <sdeventplus/clock.hpp>
+#include <sdeventplus/utility/timer.hpp>
+
+using namespace std;
+using namespace openpower::vpd::constants;
+using sdeventplus::ClockId;
+using sdeventplus::Event;
+using Timer = sdeventplus::utility::Timer<ClockId::Monotonic>;
+using namespace std::chrono_literals;
+
+namespace openpower
+{
+namespace vpd
+{
+namespace manager
+{
+
+bool GpioEventHandler::getPresencePinValue()
+{
+ Byte gpioData = 1;
+ gpiod::line presenceLine = gpiod::find_line(presencePin);
+ if (!presenceLine)
+ {
+ cerr << "Error getPresencePinValue: couldn't find presence line:"
+ << presencePin << " on GPIO \n";
+ // return previous state as we couldn't read current state
+ return prevPresPinValue;
+ }
+
+ presenceLine.request(
+ {"Op-panel presence line", gpiod::line_request::DIRECTION_INPUT, 0});
+
+ gpioData = presenceLine.get_value();
+
+ return gpioData;
+}
+
+void GpioMonitor::initGpioInfos(Event& event)
+{
+ Byte outputValue = 0;
+ Byte presenceValue = 0;
+ string presencePinName{}, outputPinName{};
+ string devNameAddr{}, driverType{}, busType{}, objectPath{};
+
+ for (const auto& eachFRU : jsonFile["frus"].items())
+ {
+ for (const auto& eachInventory : eachFRU.value())
+ {
+ objectPath = eachInventory["inventoryPath"];
+
+ if ((eachInventory.find("presence") != eachInventory.end()) &&
+ (eachInventory.find("preAction") != eachInventory.end()))
+ {
+ for (const auto& presStatus : eachInventory["presence"].items())
+ {
+ if (presStatus.key() == "pin")
+ {
+ presencePinName = presStatus.value();
+ }
+ else if (presStatus.key() == "value")
+ {
+ presenceValue = presStatus.value();
+ }
+ }
+
+ // Based on presence pin value, preAction pin will be set/reset
+ // This action will be taken before vpd collection.
+ for (const auto& preAction : eachInventory["preAction"].items())
+ {
+ if (preAction.key() == "pin")
+ {
+ outputPinName = preAction.value();
+ }
+ else if (preAction.key() == "value")
+ {
+ outputValue = preAction.value();
+ }
+ }
+
+ devNameAddr = eachInventory["devAddress"];
+ driverType = eachInventory["driverType"];
+ busType = eachInventory["busType"];
+
+ // Init all Gpio info variables
+ std::shared_ptr<GpioEventHandler> gpioObj =
+ make_shared<GpioEventHandler>(
+ presencePinName, presenceValue, outputPinName,
+ outputValue, devNameAddr, driverType, busType,
+ objectPath, event);
+
+ gpioObjects.push_back(gpioObj);
+ }
+ }
+ }
+}
+
+void GpioEventHandler::toggleGpio()
+{
+ bool presPinVal = getPresencePinValue();
+ bool isPresent = false;
+
+ // preserve the new value
+ prevPresPinValue = presPinVal;
+
+ if (presPinVal == presenceValue)
+ {
+ isPresent = true;
+ }
+
+ // if FRU went away set the present property to false
+ if (!isPresent)
+ {
+ inventory::ObjectMap objects;
+ inventory::InterfaceMap interfaces;
+ inventory::PropertyMap presProp;
+
+ presProp.emplace("Present", false);
+ interfaces.emplace("xyz.openbmc_project.Inventory.Item", presProp);
+ objects.emplace(objectPath, move(interfaces));
+
+ common::utility::callPIM(move(objects));
+ }
+
+ gpiod::line outputLine = gpiod::find_line(outputPin);
+ if (!outputLine)
+ {
+ cerr << "Error: toggleGpio: couldn't find output line:" << outputPin
+ << ". Skipping update\n";
+
+ return;
+ }
+
+ outputLine.request({"FRU presence: update the output GPIO pin",
+ gpiod::line_request::DIRECTION_OUTPUT, 0},
+ isPresent ? outputValue : (!outputValue));
+
+ string cmnd = createBindUnbindDriverCmnd(devNameAddr, busType, driverType,
+ isPresent ? "bind" : "unbind");
+
+ cout << cmnd << endl;
+ executeCmd(cmnd);
+}
+
+void GpioEventHandler::doEventAndTimerSetup(sdeventplus::Event& event)
+{
+ prevPresPinValue = getPresencePinValue();
+
+ static vector<shared_ptr<Timer>> timers;
+ shared_ptr<Timer> timer = make_shared<Timer>(
+ event,
+ [this](Timer&) {
+ if (hasEventOccurred())
+ {
+ toggleGpio();
+ }
+ },
+ std::chrono::seconds{5s});
+
+ timers.push_back(timer);
+}
+
+} // namespace manager
+} // namespace vpd
+} // namespace openpower
\ No newline at end of file