blob: eb1f62cd524019aef3aeca52e3f15c61ada6edbc [file] [log] [blame]
From 707a3a52d5884078e2173571d421829449b54225 Mon Sep 17 00:00:00 2001
From: Supreeth Venkatesh <supreeth.venkatesh@amd.com>
Date: Tue, 18 Aug 2020 13:47:55 -0500
Subject: [PATCH 1/1] Amd power control modifications for EthanolX
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
This patch modifies recipes-x86 chassis manager code to support AMD
EthanolX customer reference board.
The configuration Json file is updated with the GPIO signals present on
AMD EthanolX file.
The Service file is updated to indicate this is modified version of x86
power control suitable for AMD platforms.
The source file is modified to remove Intel specific SIO signals and
functions, modify it to support AMD specific GPIO signals.
Further, Beep() is replaced by lighting up Fault LED, as AMD CRBs does
not have a beeper.
Signed-off-by: Supreeth Venkatesh <supreeth.venkatesh@amd.com>
---
.../config/power-config-host0.json | 23 +-
...nbmc_project.Chassis.Control.Power.service | 2 +-
power-control-x86/src/power_control.cpp | 335 ++----------------
3 files changed, 44 insertions(+), 316 deletions(-)
diff --git a/power-control-x86/config/power-config-host0.json b/power-control-x86/config/power-config-host0.json
index 567f419..9e1a54a 100644
--- a/power-control-x86/config/power-config-host0.json
+++ b/power-control-x86/config/power-config-host0.json
@@ -1,15 +1,14 @@
{
- "IdButton": "ID_BUTTON",
- "NMIButton": "NMI_BUTTON",
- "NMIOut": "NMI_OUT",
- "PostComplete": "POST_COMPLETE",
- "PwrButton": "POWER_BUTTON",
- "PwrOK": "PS_PWROK",
- "PwrOut": "POWER_OUT",
- "RstButton": "RESET_BUTTON",
- "RstOut": "RESET_OUT",
- "SIOOnCtl": "SIO_ONCONTROL",
- "SIOPwrGd": "SIO_POWER_GOOD",
- "SIOS5": "SIO_S5"
+ "IdButton": "CHASSIS_ID_BTN",
+ "NMIButton": "MON_P0_NMI_BTN",
+ "NMIOut": "ASSERT_NMI_BTN",
+ "PostComplete": "MON_PWROK",
+ "PwrButton": "MON_P0_PWR_BTN",
+ "PwrOK": "MON_P0_PWR_GOOD",
+ "PwrOut": "ASSERT_PWR_BTN",
+ "RstButton": "MON_P0_RST_BTN",
+ "RstOut": "ASSERT_RST_BTN",
+ "BmcReady": "ASSERT_BMC_READY",
+ "FaultLed": "FAULT_LED"
}
diff --git a/power-control-x86/service_files/xyz.openbmc_project.Chassis.Control.Power.service b/power-control-x86/service_files/xyz.openbmc_project.Chassis.Control.Power.service
index a80235e..43cf1a7 100644
--- a/power-control-x86/service_files/xyz.openbmc_project.Chassis.Control.Power.service
+++ b/power-control-x86/service_files/xyz.openbmc_project.Chassis.Control.Power.service
@@ -1,5 +1,5 @@
[Unit]
-Description=Intel Power Control
+Description=Amd Power Control
[Service]
Restart=always
diff --git a/power-control-x86/src/power_control.cpp b/power-control-x86/src/power_control.cpp
index b8bb313..73ddf71 100644
--- a/power-control-x86/src/power_control.cpp
+++ b/power-control-x86/src/power_control.cpp
@@ -42,9 +42,8 @@ static std::string powerOutName;
static std::string powerOkName;
static std::string resetOutName;
static std::string nmiOutName;
-static std::string sioPwrGoodName;
-static std::string sioOnControlName;
-static std::string sioS5Name;
+static std::string bmcReadyName;
+static std::string faultLedName;
static std::string postCompleteName;
static std::string powerButtonName;
static std::string resetButtonName;
@@ -70,11 +69,9 @@ const static constexpr int powerPulseTimeMs = 200;
const static constexpr int forceOffPulseTimeMs = 15000;
const static constexpr int resetPulseTimeMs = 500;
const static constexpr int powerCycleTimeMs = 5000;
-const static constexpr int sioPowerGoodWatchdogTimeMs = 1000;
const static constexpr int psPowerOKWatchdogTimeMs = 8000;
const static constexpr int gracefulPowerOffTimeMs = 60000;
const static constexpr int warmResetCheckTimeMs = 500;
-const static constexpr int buttonMaskTimeMs = 60000;
const static constexpr int powerOffSaveTimeMs = 7000;
const static std::filesystem::path powerControlDir = "/var/lib/power-control";
@@ -93,24 +90,14 @@ static boost::asio::steady_timer gracefulPowerOffTimer(io);
static boost::asio::steady_timer warmResetCheckTimer(io);
// Time power supply power OK assertion on power-on
static boost::asio::steady_timer psPowerOKWatchdogTimer(io);
-// Time SIO power good assertion on power-on
-static boost::asio::steady_timer sioPowerGoodWatchdogTimer(io);
// Time power-off state save for power loss tracking
static boost::asio::steady_timer powerStateSaveTimer(io);
// POH timer
static boost::asio::steady_timer pohCounterTimer(io);
-// Time when to allow restart cause updates
-static boost::asio::steady_timer restartCauseTimer(io);
// GPIO Lines and Event Descriptors
static gpiod::line psPowerOKLine;
static boost::asio::posix::stream_descriptor psPowerOKEvent(io);
-static gpiod::line sioPowerGoodLine;
-static boost::asio::posix::stream_descriptor sioPowerGoodEvent(io);
-static gpiod::line sioOnControlLine;
-static boost::asio::posix::stream_descriptor sioOnControlEvent(io);
-static gpiod::line sioS5Line;
-static boost::asio::posix::stream_descriptor sioS5Event(io);
static gpiod::line powerButtonLine;
static boost::asio::posix::stream_descriptor powerButtonEvent(io);
static gpiod::line resetButtonLine;
@@ -123,31 +110,10 @@ static gpiod::line postCompleteLine;
static boost::asio::posix::stream_descriptor postCompleteEvent(io);
static gpiod::line nmiOutLine;
-static constexpr uint8_t beepPowerFail = 8;
-
-static void beep(const uint8_t& beepPriority)
-{
- std::cerr << "Beep with priority: " << (unsigned)beepPriority << "\n";
-
- conn->async_method_call(
- [](boost::system::error_code ec) {
- if (ec)
- {
- std::cerr << "beep returned error with "
- "async_method_call (ec = "
- << ec << ")\n";
- return;
- }
- },
- "xyz.openbmc_project.BeepCode", "/xyz/openbmc_project/BeepCode",
- "xyz.openbmc_project.BeepCode", "Beep", uint8_t(beepPriority));
-}
-
enum class PowerState
{
on,
waitForPSPowerOK,
- waitForSIOPowerGood,
off,
transitionToOff,
gracefulTransitionToOff,
@@ -167,9 +133,6 @@ static std::string getPowerStateName(PowerState state)
case PowerState::waitForPSPowerOK:
return "Wait for Power Supply Power OK";
break;
- case PowerState::waitForSIOPowerGood:
- return "Wait for SIO Power Good";
- break;
case PowerState::off:
return "Off";
break;
@@ -210,17 +173,12 @@ enum class Event
{
psPowerOKAssert,
psPowerOKDeAssert,
- sioPowerGoodAssert,
- sioPowerGoodDeAssert,
- sioS5Assert,
- sioS5DeAssert,
postCompleteAssert,
postCompleteDeAssert,
powerButtonPressed,
resetButtonPressed,
powerCycleTimerExpired,
psPowerOKWatchdogTimerExpired,
- sioPowerGoodWatchdogTimerExpired,
gracefulPowerOffTimerExpired,
powerOnRequest,
powerOffRequest,
@@ -240,18 +198,6 @@ static std::string getEventName(Event event)
case Event::psPowerOKDeAssert:
return "power supply power OK de-assert";
break;
- case Event::sioPowerGoodAssert:
- return "SIO power good assert";
- break;
- case Event::sioPowerGoodDeAssert:
- return "SIO power good de-assert";
- break;
- case Event::sioS5Assert:
- return "SIO S5 assert";
- break;
- case Event::sioS5DeAssert:
- return "SIO S5 de-assert";
- break;
case Event::postCompleteAssert:
return "POST Complete assert";
break;
@@ -270,9 +216,6 @@ static std::string getEventName(Event event)
case Event::psPowerOKWatchdogTimerExpired:
return "power supply power OK watchdog timer expired";
break;
- case Event::sioPowerGoodWatchdogTimerExpired:
- return "SIO power good watchdog timer expired";
- break;
case Event::gracefulPowerOffTimerExpired:
return "graceful power-off timer expired";
break;
@@ -314,7 +257,6 @@ static void logEvent(const std::string_view stateHandler, const Event event)
// Power state handlers
static void powerStateOn(const Event event);
static void powerStateWaitForPSPowerOK(const Event event);
-static void powerStateWaitForSIOPowerGood(const Event event);
static void powerStateOff(const Event event);
static void powerStateTransitionToOff(const Event event);
static void powerStateGracefulTransitionToOff(const Event event);
@@ -333,9 +275,6 @@ static std::function<void(const Event)> getPowerStateHandler(PowerState state)
case PowerState::waitForPSPowerOK:
return powerStateWaitForPSPowerOK;
break;
- case PowerState::waitForSIOPowerGood:
- return powerStateWaitForSIOPowerGood;
- break;
case PowerState::off:
return powerStateOff;
break;
@@ -399,7 +338,6 @@ static constexpr std::string_view getHostState(const PowerState state)
return "xyz.openbmc_project.State.Host.HostState.Running";
break;
case PowerState::waitForPSPowerOK:
- case PowerState::waitForSIOPowerGood:
case PowerState::off:
case PowerState::transitionToOff:
case PowerState::transitionToCycleOff:
@@ -425,7 +363,6 @@ static constexpr std::string_view getChassisState(const PowerState state)
return "xyz.openbmc_project.State.Chassis.PowerState.On";
break;
case PowerState::waitForPSPowerOK:
- case PowerState::waitForSIOPowerGood:
case PowerState::off:
case PowerState::cycleOff:
return "xyz.openbmc_project.State.Chassis.PowerState.Off";
@@ -593,7 +530,7 @@ static void systemPowerGoodFailedLog()
"MESSAGE=PowerControl: system power good failed to assert (VR failure)",
"PRIORITY=%i", LOG_INFO, "REDFISH_MESSAGE_ID=%s",
"OpenBMC.0.1.SystemPowerGoodFailed", "REDFISH_MESSAGE_ARGS=%d",
- sioPowerGoodWatchdogTimeMs, NULL);
+ psPowerOKWatchdogTimeMs, NULL);
}
static void psPowerOKFailedLog()
@@ -1081,54 +1018,24 @@ static int setGPIOOutputForMs(const std::string& name, const int value,
static void powerOn()
{
- setGPIOOutputForMs(power_control::powerOutName, 0, powerPulseTimeMs);
+ setGPIOOutputForMs(power_control::powerOutName, 1, powerPulseTimeMs);
}
static void gracefulPowerOff()
{
- setGPIOOutputForMs(power_control::powerOutName, 0, powerPulseTimeMs);
+ setGPIOOutputForMs(power_control::powerOutName, 1, powerPulseTimeMs);
}
static void forcePowerOff()
{
- if (setGPIOOutputForMs(power_control::powerOutName, 0,
- forceOffPulseTimeMs) < 0)
- {
- return;
- }
+ setGPIOOutputForMs(power_control::powerOutName, 1, forceOffPulseTimeMs);
- // If the force off timer expires, then the PCH power-button override
- // failed, so attempt the Unconditional Powerdown SMBus command.
- gpioAssertTimer.async_wait([](const boost::system::error_code ec) {
- if (ec)
- {
- // operation_aborted is expected if timer is canceled before
- // completion.
- if (ec != boost::asio::error::operation_aborted)
- {
- std::cerr << "Force power off async_wait failed: "
- << ec.message() << "\n";
- }
- return;
- }
- std::cerr << "PCH Power-button override failed. Issuing Unconditional "
- "Powerdown SMBus command.\n";
- const static constexpr size_t pchDevBusAddress = 3;
- const static constexpr size_t pchDevSlaveAddress = 0x44;
- const static constexpr size_t pchCmdReg = 0;
- const static constexpr size_t pchPowerDownCmd = 0x02;
- if (i2cSet(pchDevBusAddress, pchDevSlaveAddress, pchCmdReg,
- pchPowerDownCmd) < 0)
- {
- std::cerr << "Unconditional Powerdown command failed! Not sure "
- "what to do now.\n";
- }
- });
+ return;
}
static void reset()
{
- setGPIOOutputForMs(power_control::resetOutName, 0, resetPulseTimeMs);
+ setGPIOOutputForMs(power_control::resetOutName, 1, resetPulseTimeMs);
}
static void gracefulPowerOffTimerStart()
@@ -1373,43 +1280,16 @@ static void currentHostStateMonitor()
});
}
-static void sioPowerGoodWatchdogTimerStart()
-{
- std::cerr << "SIO power good watchdog timer started\n";
- sioPowerGoodWatchdogTimer.expires_after(
- std::chrono::milliseconds(sioPowerGoodWatchdogTimeMs));
- sioPowerGoodWatchdogTimer.async_wait(
- [](const boost::system::error_code ec) {
- if (ec)
- {
- // operation_aborted is expected if timer is canceled before
- // completion.
- if (ec != boost::asio::error::operation_aborted)
- {
- std::cerr << "SIO power good watchdog async_wait failed: "
- << ec.message() << "\n";
- }
- std::cerr << "SIO power good watchdog timer canceled\n";
- return;
- }
- std::cerr << "SIO power good watchdog timer completed\n";
- sendPowerControlEvent(Event::sioPowerGoodWatchdogTimerExpired);
- });
-}
-
static void powerStateOn(const Event event)
{
+ gpiod::line line;
logEvent(__FUNCTION__, event);
switch (event)
{
case Event::psPowerOKDeAssert:
setPowerState(PowerState::off);
- // DC power is unexpectedly lost, beep
- beep(beepPowerFail);
- break;
- case Event::sioS5Assert:
- setPowerState(PowerState::transitionToOff);
- addRestartCause(RestartCause::softReset);
+ // DC power is unexpectedly lost, Light Up fault LED
+ power_control::setGPIOOutput(power_control::faultLedName, 1, line);
break;
case Event::postCompleteDeAssert:
setPowerState(PowerState::checkForWarmReset);
@@ -1461,37 +1341,12 @@ static void powerStateWaitForPSPowerOK(const Event event)
// Cancel any GPIO assertions held during the transition
gpioAssertTimer.cancel();
psPowerOKWatchdogTimer.cancel();
- sioPowerGoodWatchdogTimerStart();
- setPowerState(PowerState::waitForSIOPowerGood);
+ setPowerState(PowerState::on);
break;
case Event::psPowerOKWatchdogTimerExpired:
setPowerState(PowerState::off);
psPowerOKFailedLog();
break;
- case Event::sioPowerGoodAssert:
- psPowerOKWatchdogTimer.cancel();
- setPowerState(PowerState::on);
- break;
- default:
- phosphor::logging::log<phosphor::logging::level::INFO>(
- "No action taken.");
- break;
- }
-}
-
-static void powerStateWaitForSIOPowerGood(const Event event)
-{
- logEvent(__FUNCTION__, event);
- switch (event)
- {
- case Event::sioPowerGoodAssert:
- sioPowerGoodWatchdogTimer.cancel();
- setPowerState(PowerState::on);
- break;
- case Event::sioPowerGoodWatchdogTimerExpired:
- setPowerState(PowerState::off);
- systemPowerGoodFailedLog();
- break;
default:
phosphor::logging::log<phosphor::logging::level::INFO>(
"No action taken.");
@@ -1505,12 +1360,6 @@ static void powerStateOff(const Event event)
switch (event)
{
case Event::psPowerOKAssert:
- setPowerState(PowerState::waitForSIOPowerGood);
- break;
- case Event::sioS5DeAssert:
- setPowerState(PowerState::waitForPSPowerOK);
- break;
- case Event::sioPowerGoodAssert:
setPowerState(PowerState::on);
break;
case Event::powerButtonPressed:
@@ -1572,11 +1421,11 @@ static void powerStateCycleOff(const Event event)
{
case Event::psPowerOKAssert:
powerCycleTimer.cancel();
- setPowerState(PowerState::waitForSIOPowerGood);
+ setPowerState(PowerState::on);
break;
- case Event::sioS5DeAssert:
+ case Event::psPowerOKDeAssert:
powerCycleTimer.cancel();
- setPowerState(PowerState::waitForPSPowerOK);
+ setPowerState(PowerState::off);
break;
case Event::powerButtonPressed:
powerCycleTimer.cancel();
@@ -1635,21 +1484,18 @@ static void powerStateGracefulTransitionToCycleOff(const Event event)
static void powerStateCheckForWarmReset(const Event event)
{
+ gpiod::line line;
logEvent(__FUNCTION__, event);
switch (event)
{
- case Event::sioS5Assert:
- warmResetCheckTimer.cancel();
- setPowerState(PowerState::transitionToOff);
- break;
case Event::warmResetDetected:
setPowerState(PowerState::on);
break;
case Event::psPowerOKDeAssert:
warmResetCheckTimer.cancel();
setPowerState(PowerState::off);
- // DC power is unexpectedly lost, beep
- beep(beepPowerFail);
+ // DC power is unexpectedly lost, Light up Fault LED
+ power_control::setGPIOOutput(power_control::faultLedName, 1, line);
break;
default:
phosphor::logging::log<phosphor::logging::level::INFO>(
@@ -1681,71 +1527,6 @@ static void psPowerOKHandler()
});
}
-static void sioPowerGoodHandler()
-{
- gpiod::line_event gpioLineEvent = sioPowerGoodLine.event_read();
-
- Event powerControlEvent =
- gpioLineEvent.event_type == gpiod::line_event::RISING_EDGE
- ? Event::sioPowerGoodAssert
- : Event::sioPowerGoodDeAssert;
-
- sendPowerControlEvent(powerControlEvent);
- sioPowerGoodEvent.async_wait(
- boost::asio::posix::stream_descriptor::wait_read,
- [](const boost::system::error_code ec) {
- if (ec)
- {
- std::cerr << "SIO power good handler error: " << ec.message()
- << "\n";
- return;
- }
- sioPowerGoodHandler();
- });
-}
-
-static void sioOnControlHandler()
-{
- gpiod::line_event gpioLineEvent = sioOnControlLine.event_read();
-
- bool sioOnControl =
- gpioLineEvent.event_type == gpiod::line_event::RISING_EDGE;
- std::cerr << "SIO_ONCONTROL value changed: " << sioOnControl << "\n";
- sioOnControlEvent.async_wait(
- boost::asio::posix::stream_descriptor::wait_read,
- [](const boost::system::error_code ec) {
- if (ec)
- {
- std::cerr << "SIO ONCONTROL handler error: " << ec.message()
- << "\n";
- return;
- }
- sioOnControlHandler();
- });
-}
-
-static void sioS5Handler()
-{
- gpiod::line_event gpioLineEvent = sioS5Line.event_read();
-
- Event powerControlEvent =
- gpioLineEvent.event_type == gpiod::line_event::FALLING_EDGE
- ? Event::sioS5Assert
- : Event::sioS5DeAssert;
-
- sendPowerControlEvent(powerControlEvent);
- sioS5Event.async_wait(boost::asio::posix::stream_descriptor::wait_read,
- [](const boost::system::error_code ec) {
- if (ec)
- {
- std::cerr << "SIO S5 handler error: "
- << ec.message() << "\n";
- return;
- }
- sioS5Handler();
- });
-}
-
static void powerButtonHandler()
{
gpiod::line_event gpioLineEvent = powerButtonLine.event_read();
@@ -2007,7 +1788,7 @@ static void postCompleteHandler()
gpiod::line_event gpioLineEvent = postCompleteLine.event_read();
bool postComplete =
- gpioLineEvent.event_type == gpiod::line_event::FALLING_EDGE;
+ gpioLineEvent.event_type == gpiod::line_event::RISING_EDGE;
if (postComplete)
{
sendPowerControlEvent(Event::postCompleteAssert);
@@ -2095,19 +1876,14 @@ static int loadConfigValues()
resetOutName = data["RstOut"];
}
- if (data.contains("SIOOnCtl"))
- {
- sioOnControlName = data["SIOOnCtl"];
- }
-
- if (data.contains("SIOPwrGd"))
+ if (data.contains("BmcReady"))
{
- sioPwrGoodName = data["SIOPwrGd"];
+ bmcReadyName = data["BmcReady"];
}
- if (data.contains("SIOS5"))
+ if (data.contains("FaultLed"))
{
- sioS5Name = data["SIOS5"];
+ faultLedName = data["FaultLed"];
}
return 0;
@@ -2155,60 +1931,6 @@ int main(int argc, char* argv[])
return -1;
}
- // Request SIO_POWER_GOOD GPIO events
- if (!power_control::sioPwrGoodName.empty())
- {
- if (!power_control::requestGPIOEvents(
- power_control::sioPwrGoodName,
- power_control::sioPowerGoodHandler,
- power_control::sioPowerGoodLine,
- power_control::sioPowerGoodEvent))
- {
- return -1;
- }
- }
- else
- {
- std::cerr
- << "sioPwrGood name should be configured from json config file\n";
- return -1;
- }
-
- // Request SIO_ONCONTROL GPIO events
- if (!power_control::sioOnControlName.empty())
- {
- if (!power_control::requestGPIOEvents(
- power_control::sioOnControlName,
- power_control::sioOnControlHandler,
- power_control::sioOnControlLine,
- power_control::sioOnControlEvent))
- {
- return -1;
- }
- }
- else
- {
- std::cerr
- << "sioOnControl name should be configured from json config file\n";
- return -1;
- }
-
- // Request SIO_S5 GPIO events
- if (!power_control::sioS5Name.empty())
- {
- if (!power_control::requestGPIOEvents(
- power_control::sioS5Name, power_control::sioS5Handler,
- power_control::sioS5Line, power_control::sioS5Event))
- {
- return -1;
- }
- }
- else
- {
- std::cerr << "sioS5 name should be configured from json config file\n";
- return -1;
- }
-
// Request POWER_BUTTON GPIO events
if (!power_control::powerButtonName.empty())
{
@@ -2286,12 +2008,12 @@ int main(int argc, char* argv[])
// Initialize POWER_OUT and RESET_OUT GPIO.
gpiod::line line;
- if (!power_control::setGPIOOutput(power_control::powerOutName, 1, line))
+ if (!power_control::setGPIOOutput(power_control::powerOutName, 0, line))
{
return -1;
}
- if (!power_control::setGPIOOutput(power_control::resetOutName, 1, line))
+ if (!power_control::setGPIOOutput(power_control::resetOutName, 0, line))
{
return -1;
}
@@ -2299,6 +2021,13 @@ int main(int argc, char* argv[])
// Release line
line.reset();
+ // DRIVE BMC_READY HIGH
+ gpiod::line bmcReadyline;
+ if (!power_control::setGPIOOutput(power_control::bmcReadyName, 1, bmcReadyline))
+ {
+ return -1;
+ }
+
// Initialize the power state
power_control::powerState = power_control::PowerState::off;
// Check power good
--
2.17.1