1f02daec1SMatt Spinler /**
2f02daec1SMatt Spinler  * Copyright © 2017 IBM Corporation
3f02daec1SMatt Spinler  *
4f02daec1SMatt Spinler  * Licensed under the Apache License, Version 2.0 (the "License");
5f02daec1SMatt Spinler  * you may not use this file except in compliance with the License.
6f02daec1SMatt Spinler  * You may obtain a copy of the License at
7f02daec1SMatt Spinler  *
8f02daec1SMatt Spinler  *     http://www.apache.org/licenses/LICENSE-2.0
9f02daec1SMatt Spinler  *
10f02daec1SMatt Spinler  * Unless required by applicable law or agreed to in writing, software
11f02daec1SMatt Spinler  * distributed under the License is distributed on an "AS IS" BASIS,
12f02daec1SMatt Spinler  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f02daec1SMatt Spinler  * See the License for the specific language governing permissions and
14f02daec1SMatt Spinler  * limitations under the License.
15f02daec1SMatt Spinler  */
1645a054acSMatt Spinler #include "config.h"
17f0f02b9aSMatt Spinler 
18f02daec1SMatt Spinler #include "pgood_monitor.hpp"
19f0f02b9aSMatt Spinler 
20f0f02b9aSMatt Spinler #include "elog-errors.hpp"
21f02daec1SMatt Spinler #include "utility.hpp"
22f02daec1SMatt Spinler 
23f0f02b9aSMatt Spinler #include <org/open_power/Witherspoon/Fault/error.hpp>
24f0f02b9aSMatt Spinler #include <phosphor-logging/log.hpp>
25f0f02b9aSMatt Spinler 
26ab093328SLei YU namespace phosphor
27f02daec1SMatt Spinler {
28f02daec1SMatt Spinler namespace power
29f02daec1SMatt Spinler {
30f02daec1SMatt Spinler 
31f02daec1SMatt Spinler constexpr auto POWER_OBJ_PATH = "/org/openbmc/control/power0";
32f02daec1SMatt Spinler constexpr auto POWER_INTERFACE = "org.openbmc.control.Power";
33f02daec1SMatt Spinler 
34f02daec1SMatt Spinler using namespace phosphor::logging;
35e0eb45ccSBrandon Wyman using namespace sdbusplus::org::open_power::Witherspoon::Fault::Error;
36f02daec1SMatt Spinler 
pgoodPending()37f02daec1SMatt Spinler bool PGOODMonitor::pgoodPending()
38f02daec1SMatt Spinler {
39f02daec1SMatt Spinler     bool pending = false;
40f02daec1SMatt Spinler     int32_t state = 0;
41f02daec1SMatt Spinler     int32_t pgood = 0;
42f02daec1SMatt Spinler 
43f0f02b9aSMatt Spinler     auto service = util::getService(POWER_OBJ_PATH, POWER_INTERFACE, bus);
44f02daec1SMatt Spinler 
45f0f02b9aSMatt Spinler     util::getProperty<int32_t>(POWER_INTERFACE, "pgood", POWER_OBJ_PATH,
46f0f02b9aSMatt Spinler                                service, bus, pgood);
47f02daec1SMatt Spinler 
48f02daec1SMatt Spinler     // When state = 1, system was switched on
49f0f02b9aSMatt Spinler     util::getProperty<int32_t>(POWER_INTERFACE, "state", POWER_OBJ_PATH,
50f0f02b9aSMatt Spinler                                service, bus, state);
51f02daec1SMatt Spinler 
52f02daec1SMatt Spinler     // On but no PGOOD
53f02daec1SMatt Spinler     if (state && !pgood)
54f02daec1SMatt Spinler     {
55f02daec1SMatt Spinler         pending = true;
56f02daec1SMatt Spinler     }
57f02daec1SMatt Spinler 
58f02daec1SMatt Spinler     return pending;
59f02daec1SMatt Spinler }
60f02daec1SMatt Spinler 
analyze()61f02daec1SMatt Spinler void PGOODMonitor::analyze()
62f02daec1SMatt Spinler {
63f02daec1SMatt Spinler     // Timer callback.
64f02daec1SMatt Spinler     // The timer expired before it was stopped.
65f02daec1SMatt Spinler     // If PGOOD is still pending (it should be),
66f02daec1SMatt Spinler     // then there is a real failure.
67f02daec1SMatt Spinler 
68f02daec1SMatt Spinler     if (pgoodPending())
69f02daec1SMatt Spinler     {
7040247cceSAndy YF Wang #ifdef DEVICE_ACCESS
71b2d72511SMatt Spinler         device->onFailure();
7245a054acSMatt Spinler #endif
73f02daec1SMatt Spinler         report<PowerOnFailure>();
74f02daec1SMatt Spinler     }
75f02daec1SMatt Spinler 
76f02daec1SMatt Spinler     // The pgood-wait service (with a longer timeout)
77f02daec1SMatt Spinler     // will handle powering off the system.
781a0c9176SWilliam A. Kennington III     timer.get_event().exit(EXIT_SUCCESS);
79f02daec1SMatt Spinler }
80f02daec1SMatt Spinler 
propertyChanged()81f02daec1SMatt Spinler void PGOODMonitor::propertyChanged()
82f02daec1SMatt Spinler {
83f02daec1SMatt Spinler     // Multiple properties could have changed here.
84f02daec1SMatt Spinler     // Keep things simple and just recheck the important ones.
85f02daec1SMatt Spinler     if (!pgoodPending())
86f02daec1SMatt Spinler     {
87f02daec1SMatt Spinler         // PGOOD is on, or system is off, so we are done.
881a0c9176SWilliam A. Kennington III         timer.get_event().exit(EXIT_SUCCESS);
89f02daec1SMatt Spinler     }
90f02daec1SMatt Spinler }
91f02daec1SMatt Spinler 
startListening()92f02daec1SMatt Spinler void PGOODMonitor::startListening()
93f02daec1SMatt Spinler {
94f02daec1SMatt Spinler     match = std::make_unique<sdbusplus::bus::match_t>(
95f02daec1SMatt Spinler         bus,
96f0f02b9aSMatt Spinler         sdbusplus::bus::match::rules::propertiesChanged(POWER_OBJ_PATH,
97f02daec1SMatt Spinler                                                         POWER_INTERFACE),
9811cb6728SBrad Bishop         [this](auto&) { this->propertyChanged(); });
99f02daec1SMatt Spinler }
100f02daec1SMatt Spinler 
run()101f02daec1SMatt Spinler int PGOODMonitor::run()
102f02daec1SMatt Spinler {
103f02daec1SMatt Spinler     try
104f02daec1SMatt Spinler     {
105f02daec1SMatt Spinler         startListening();
106f02daec1SMatt Spinler 
107f02daec1SMatt Spinler         // If PGOOD came up before we got here, we're done.
108f02daec1SMatt Spinler         // Otherwise if PGOOD doesn't get asserted before
109f02daec1SMatt Spinler         // the timer expires, it's a failure.
110f02daec1SMatt Spinler         if (!pgoodPending())
111f02daec1SMatt Spinler         {
112f02daec1SMatt Spinler             return EXIT_SUCCESS;
113f02daec1SMatt Spinler         }
114f02daec1SMatt Spinler 
1151a0c9176SWilliam A. Kennington III         return timer.get_event().loop();
116f02daec1SMatt Spinler     }
117*c1d4de5eSPatrick Williams     catch (const std::exception& e)
118f02daec1SMatt Spinler     {
119f02daec1SMatt Spinler         log<level::ERR>(e.what());
120f02daec1SMatt Spinler         log<level::ERR>("Unexpected failure prevented PGOOD checking");
121f02daec1SMatt Spinler     }
122f02daec1SMatt Spinler 
123f02daec1SMatt Spinler     // Letting the service fail won't help anything, so don't do it.
124f02daec1SMatt Spinler     return EXIT_SUCCESS;
125f02daec1SMatt Spinler }
126f02daec1SMatt Spinler 
127f0f02b9aSMatt Spinler } // namespace power
128ab093328SLei YU } // namespace phosphor
129