blob: fe844d510f4f9289afd459ea26819ff4dfcc3b55 [file] [log] [blame]
Jim Wright10eb00f2021-07-21 12:10:38 -05001/**
2 * Copyright © 2021 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Jim Wright539b6082021-08-02 14:50:23 -050017#include "power_control.hpp"
18
19#include "types.hpp"
20
Jim Wright22318a32021-08-27 15:56:09 -050021#include <fmt/format.h>
22
Jim Wright7a5dd992021-08-31 16:56:52 -050023#include <phosphor-logging/elog-errors.hpp>
24#include <phosphor-logging/elog.hpp>
Jim Wright539b6082021-08-02 14:50:23 -050025#include <phosphor-logging/log.hpp>
Jim Wright7a5dd992021-08-31 16:56:52 -050026#include <xyz/openbmc_project/Common/error.hpp>
Jim Wright539b6082021-08-02 14:50:23 -050027
Jim Wright539b6082021-08-02 14:50:23 -050028#include <exception>
Jim Wright7a5dd992021-08-31 16:56:52 -050029#include <string>
Jim Wright539b6082021-08-02 14:50:23 -050030
31using namespace phosphor::logging;
32
33namespace phosphor::power::sequencer
Jim Wright10eb00f2021-07-21 12:10:38 -050034{
Jim Wright539b6082021-08-02 14:50:23 -050035
Jim Wright7a5dd992021-08-31 16:56:52 -050036const std::string powerControlLineName = "power-chassis-control";
37const std::string pgoodLineName = "power-chassis-good";
38
Jim Wright539b6082021-08-02 14:50:23 -050039PowerControl::PowerControl(sdbusplus::bus::bus& bus,
40 const sdeventplus::Event& event) :
Jim Wright22318a32021-08-27 15:56:09 -050041 PowerObject{bus, POWER_OBJ_PATH, true},
42 bus{bus}, timer{event, std::bind(&PowerControl::pollPgood, this),
43 pollInterval}
Jim Wright539b6082021-08-02 14:50:23 -050044{
45 // Obtain dbus service name
46 bus.request_name(POWER_IFACE);
Jim Wright7a5dd992021-08-31 16:56:52 -050047 setUpGpio();
Jim Wright10eb00f2021-07-21 12:10:38 -050048}
Jim Wright539b6082021-08-02 14:50:23 -050049
Jim Wright22318a32021-08-27 15:56:09 -050050int PowerControl::getPgood() const
51{
52 return pgood;
53}
54
55int PowerControl::getPgoodTimeout() const
56{
57 return timeout.count();
58}
59
60int PowerControl::getState() const
61{
62 return state;
63}
64
Jim Wright539b6082021-08-02 14:50:23 -050065void PowerControl::pollPgood()
Jim Wright7a5dd992021-08-31 16:56:52 -050066{
67 if (inStateTransition)
68 {
69 const auto now = std::chrono::steady_clock::now();
70 if (now > pgoodTimeoutTime)
71 {
72 log<level::ERR>("ERROR PowerControl: Pgood poll timeout");
73 inStateTransition = false;
74 return;
75 }
76 }
77
78 int pgoodState = pgoodLine.get_value();
79 if (pgoodState != pgood)
80 {
81 pgood = pgoodState;
82 if (pgoodState == 0)
83 {
84 emitPowerLostSignal();
85 }
86 else
87 {
88 emitPowerGoodSignal();
89 }
90 emitPropertyChangedSignal("pgood");
91 }
92 if (pgoodState == state)
93 {
94 inStateTransition = false;
95 }
96}
Jim Wright539b6082021-08-02 14:50:23 -050097
Jim Wright22318a32021-08-27 15:56:09 -050098void PowerControl::setPgoodTimeout(int t)
99{
100 if (timeout.count() != t)
101 {
102 timeout = std::chrono::seconds(t);
103 emitPropertyChangedSignal("pgood_timeout");
104 }
105}
106
107void PowerControl::setState(int s)
108{
109 if (state == s)
110 {
111 log<level::INFO>(
112 fmt::format("Power already at requested state: {}", state).c_str());
113 return;
114 }
Jim Wright209690b2021-11-11 14:46:42 -0600115 if (s == 0)
116 {
117 // Wait for two seconds when powering down. This is to allow host and
118 // other BMC applications time to complete power off processing
119 std::this_thread::sleep_for(std::chrono::seconds(2));
120 }
Jim Wright22318a32021-08-27 15:56:09 -0500121
122 log<level::INFO>(fmt::format("setState: {}", s).c_str());
Jim Wright7a5dd992021-08-31 16:56:52 -0500123 powerControlLine.request(
124 {"phosphor-power-control", gpiod::line_request::DIRECTION_OUTPUT, 0});
125 powerControlLine.set_value(s);
126 powerControlLine.release();
127
128 pgoodTimeoutTime = std::chrono::steady_clock::now() + timeout;
129 inStateTransition = true;
Jim Wright22318a32021-08-27 15:56:09 -0500130 state = s;
131 emitPropertyChangedSignal("state");
132}
133
Jim Wright7a5dd992021-08-31 16:56:52 -0500134void PowerControl::setUpGpio()
135{
136 pgoodLine = gpiod::find_line(pgoodLineName);
137 if (!pgoodLine)
138 {
Jim Wright209690b2021-11-11 14:46:42 -0600139 std::string errorString{"GPIO line name not found: " + pgoodLineName};
Jim Wright7a5dd992021-08-31 16:56:52 -0500140 log<level::ERR>(errorString.c_str());
141 report<
142 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure>();
143 throw std::runtime_error(errorString);
144 }
145 powerControlLine = gpiod::find_line(powerControlLineName);
146 if (!powerControlLine)
147 {
Jim Wright209690b2021-11-11 14:46:42 -0600148 std::string errorString{"GPIO line name not found: " +
149 powerControlLineName};
Jim Wright7a5dd992021-08-31 16:56:52 -0500150 log<level::ERR>(errorString.c_str());
151 report<
152 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure>();
153 throw std::runtime_error(errorString);
154 }
155
156 pgoodLine.request(
157 {"phosphor-power-control", gpiod::line_request::DIRECTION_INPUT, 0});
158 int pgoodState = pgoodLine.get_value();
159 pgood = pgoodState;
160 state = pgoodState;
161 log<level::INFO>(fmt::format("Pgood state: {}", pgoodState).c_str());
162}
163
Jim Wright539b6082021-08-02 14:50:23 -0500164} // namespace phosphor::power::sequencer