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  */
16f02daec1SMatt Spinler #include <phosphor-logging/log.hpp>
17e0eb45ccSBrandon Wyman #include <org/open_power/Witherspoon/Fault/error.hpp>
1845a054acSMatt Spinler #include "config.h"
19f02daec1SMatt Spinler #include "elog-errors.hpp"
20f02daec1SMatt Spinler #include "pgood_monitor.hpp"
21f02daec1SMatt Spinler #include "utility.hpp"
22f02daec1SMatt Spinler 
23f02daec1SMatt Spinler namespace witherspoon
24f02daec1SMatt Spinler {
25f02daec1SMatt Spinler namespace power
26f02daec1SMatt Spinler {
27f02daec1SMatt Spinler 
28f02daec1SMatt Spinler constexpr auto POWER_OBJ_PATH = "/org/openbmc/control/power0";
29f02daec1SMatt Spinler constexpr auto POWER_INTERFACE = "org.openbmc.control.Power";
30f02daec1SMatt Spinler 
31f02daec1SMatt Spinler using namespace phosphor::logging;
32e0eb45ccSBrandon Wyman using namespace sdbusplus::org::open_power::Witherspoon::Fault::Error;
33f02daec1SMatt Spinler 
34f02daec1SMatt Spinler bool PGOODMonitor::pgoodPending()
35f02daec1SMatt Spinler {
36f02daec1SMatt Spinler     bool pending = false;
37f02daec1SMatt Spinler     int32_t state = 0;
38f02daec1SMatt Spinler     int32_t pgood = 0;
39f02daec1SMatt Spinler 
40f02daec1SMatt Spinler     auto service = util::getService(POWER_OBJ_PATH,
41f02daec1SMatt Spinler             POWER_INTERFACE,
42f02daec1SMatt Spinler             bus);
43f02daec1SMatt Spinler 
44f02daec1SMatt Spinler     util::getProperty<int32_t>(POWER_INTERFACE,
45f02daec1SMatt Spinler             "pgood",
46f02daec1SMatt Spinler             POWER_OBJ_PATH,
47f02daec1SMatt Spinler             service,
48f02daec1SMatt Spinler             bus,
49f02daec1SMatt Spinler             pgood);
50f02daec1SMatt Spinler 
51f02daec1SMatt Spinler     //When state = 1, system was switched on
52f02daec1SMatt Spinler     util::getProperty<int32_t>(POWER_INTERFACE,
53f02daec1SMatt Spinler             "state",
54f02daec1SMatt Spinler             POWER_OBJ_PATH,
55f02daec1SMatt Spinler             service,
56f02daec1SMatt Spinler             bus,
57f02daec1SMatt Spinler             state);
58f02daec1SMatt Spinler 
59f02daec1SMatt Spinler     //On but no PGOOD
60f02daec1SMatt Spinler     if (state && !pgood)
61f02daec1SMatt Spinler     {
62f02daec1SMatt Spinler         pending = true;
63f02daec1SMatt Spinler     }
64f02daec1SMatt Spinler 
65f02daec1SMatt Spinler     return pending;
66f02daec1SMatt Spinler }
67f02daec1SMatt Spinler 
68f02daec1SMatt Spinler 
69f02daec1SMatt Spinler void PGOODMonitor::analyze()
70f02daec1SMatt Spinler {
71f02daec1SMatt Spinler     //Timer callback.
72f02daec1SMatt Spinler     //The timer expired before it was stopped.
73f02daec1SMatt Spinler     //If PGOOD is still pending (it should be),
74f02daec1SMatt Spinler     //then there is a real failure.
75f02daec1SMatt Spinler 
76f02daec1SMatt Spinler     if (pgoodPending())
77f02daec1SMatt Spinler     {
7845a054acSMatt Spinler #ifdef UCD90160_DEVICE_ACCESS
79b2d72511SMatt Spinler         device->onFailure();
8045a054acSMatt Spinler #endif
81f02daec1SMatt Spinler         report<PowerOnFailure>();
82f02daec1SMatt Spinler     }
83f02daec1SMatt Spinler 
84f02daec1SMatt Spinler     //The pgood-wait service (with a longer timeout)
85f02daec1SMatt Spinler     //will handle powering off the system.
86*1a0c9176SWilliam A. Kennington III     timer.get_event().exit(EXIT_SUCCESS);
87f02daec1SMatt Spinler }
88f02daec1SMatt Spinler 
89f02daec1SMatt Spinler void PGOODMonitor::propertyChanged()
90f02daec1SMatt Spinler {
91f02daec1SMatt Spinler     //Multiple properties could have changed here.
92f02daec1SMatt Spinler     //Keep things simple and just recheck the important ones.
93f02daec1SMatt Spinler     if (!pgoodPending())
94f02daec1SMatt Spinler     {
95f02daec1SMatt Spinler         //PGOOD is on, or system is off, so we are done.
96*1a0c9176SWilliam A. Kennington III         timer.get_event().exit(EXIT_SUCCESS);
97f02daec1SMatt Spinler     }
98f02daec1SMatt Spinler }
99f02daec1SMatt Spinler 
100f02daec1SMatt Spinler void PGOODMonitor::startListening()
101f02daec1SMatt Spinler {
102f02daec1SMatt Spinler     match = std::make_unique<sdbusplus::bus::match_t>(
103f02daec1SMatt Spinler             bus,
104f02daec1SMatt Spinler             sdbusplus::bus::match::rules::propertiesChanged(
105f02daec1SMatt Spinler                 POWER_OBJ_PATH,
106f02daec1SMatt Spinler                 POWER_INTERFACE),
107f02daec1SMatt Spinler             [this](auto& msg){this->propertyChanged();});
108f02daec1SMatt Spinler }
109f02daec1SMatt Spinler 
110f02daec1SMatt Spinler int PGOODMonitor::run()
111f02daec1SMatt Spinler {
112f02daec1SMatt Spinler     try
113f02daec1SMatt Spinler     {
114f02daec1SMatt Spinler         startListening();
115f02daec1SMatt Spinler 
116f02daec1SMatt Spinler         //If PGOOD came up before we got here, we're done.
117f02daec1SMatt Spinler         //Otherwise if PGOOD doesn't get asserted before
118f02daec1SMatt Spinler         //the timer expires, it's a failure.
119f02daec1SMatt Spinler         if (!pgoodPending())
120f02daec1SMatt Spinler         {
121f02daec1SMatt Spinler             return EXIT_SUCCESS;
122f02daec1SMatt Spinler         }
123f02daec1SMatt Spinler 
124*1a0c9176SWilliam A. Kennington III         return timer.get_event().loop();
125f02daec1SMatt Spinler     }
126f02daec1SMatt Spinler     catch (std::exception& e)
127f02daec1SMatt Spinler     {
128f02daec1SMatt Spinler         log<level::ERR>(e.what());
129f02daec1SMatt Spinler         log<level::ERR>("Unexpected failure prevented PGOOD checking");
130f02daec1SMatt Spinler     }
131f02daec1SMatt Spinler 
132f02daec1SMatt Spinler     //Letting the service fail won't help anything, so don't do it.
133f02daec1SMatt Spinler     return EXIT_SUCCESS;
134f02daec1SMatt Spinler }
135f02daec1SMatt Spinler 
136f02daec1SMatt Spinler 
137f02daec1SMatt Spinler }
138f02daec1SMatt Spinler }
139