1 /** 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 17 #include "power_control.hpp" 18 19 #include "types.hpp" 20 21 #include <fmt/format.h> 22 23 #include <phosphor-logging/elog-errors.hpp> 24 #include <phosphor-logging/elog.hpp> 25 #include <phosphor-logging/log.hpp> 26 #include <xyz/openbmc_project/Common/error.hpp> 27 28 #include <exception> 29 #include <string> 30 31 using namespace phosphor::logging; 32 33 namespace phosphor::power::sequencer 34 { 35 36 const std::string powerControlLineName = "power-chassis-control"; 37 const std::string pgoodLineName = "power-chassis-good"; 38 39 PowerControl::PowerControl(sdbusplus::bus::bus& bus, 40 const sdeventplus::Event& event) : 41 PowerObject{bus, POWER_OBJ_PATH, true}, 42 bus{bus}, timer{event, std::bind(&PowerControl::pollPgood, this), 43 pollInterval} 44 { 45 // Obtain dbus service name 46 bus.request_name(POWER_IFACE); 47 setUpGpio(); 48 } 49 50 int PowerControl::getPgood() const 51 { 52 return pgood; 53 } 54 55 int PowerControl::getPgoodTimeout() const 56 { 57 return timeout.count(); 58 } 59 60 int PowerControl::getState() const 61 { 62 return state; 63 } 64 65 void PowerControl::pollPgood() 66 { 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 } 97 98 void PowerControl::setPgoodTimeout(int t) 99 { 100 if (timeout.count() != t) 101 { 102 timeout = std::chrono::seconds(t); 103 emitPropertyChangedSignal("pgood_timeout"); 104 } 105 } 106 107 void 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 } 115 116 log<level::INFO>(fmt::format("setState: {}", s).c_str()); 117 powerControlLine.request( 118 {"phosphor-power-control", gpiod::line_request::DIRECTION_OUTPUT, 0}); 119 powerControlLine.set_value(s); 120 powerControlLine.release(); 121 122 pgoodTimeoutTime = std::chrono::steady_clock::now() + timeout; 123 inStateTransition = true; 124 state = s; 125 emitPropertyChangedSignal("state"); 126 } 127 128 void PowerControl::setUpGpio() 129 { 130 pgoodLine = gpiod::find_line(pgoodLineName); 131 if (!pgoodLine) 132 { 133 std::string errorString = 134 fmt::format("GPIO line name not found: {}", pgoodLineName); 135 log<level::ERR>(errorString.c_str()); 136 report< 137 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure>(); 138 throw std::runtime_error(errorString); 139 } 140 powerControlLine = gpiod::find_line(powerControlLineName); 141 if (!powerControlLine) 142 { 143 std::string errorString = 144 fmt::format("GPIO line name not found: {}", powerControlLineName); 145 log<level::ERR>(errorString.c_str()); 146 report< 147 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure>(); 148 throw std::runtime_error(errorString); 149 } 150 151 pgoodLine.request( 152 {"phosphor-power-control", gpiod::line_request::DIRECTION_INPUT, 0}); 153 int pgoodState = pgoodLine.get_value(); 154 pgood = pgoodState; 155 state = pgoodState; 156 log<level::INFO>(fmt::format("Pgood state: {}", pgoodState).c_str()); 157 } 158 159 } // namespace phosphor::power::sequencer 160