/** * Copyright © 2025 IBM Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include "gpio.hpp" #include "power_sequencer_device.hpp" #include "rail.hpp" #include "services.hpp" #include #include #include #include #include #include namespace phosphor::power::sequencer { /** * @class BasicDevice * * PowerSequencerDevice sub-class that implements basic functionality. * * BasicDevice implements the following: * - Data members and methods for the power sequencer properties from the JSON * configuration file. * - Methods that utilize the named GPIOs, such as powerOn() and getPowerGood(). */ class BasicDevice : public PowerSequencerDevice { public: BasicDevice() = delete; BasicDevice(const BasicDevice&) = delete; BasicDevice(BasicDevice&&) = delete; BasicDevice& operator=(const BasicDevice&) = delete; BasicDevice& operator=(BasicDevice&&) = delete; /** * Constructor. * * Throws an exception if an error occurs during initialization. * * @param name device name * @param bus I2C bus for the device * @param address I2C address for the device * @param powerControlGPIOName name of the GPIO that turns this device on * and off * @param powerGoodGPIOName name of the GPIO that reads the power good * signal from this device * @param rails voltage rails that are enabled and monitored by this device */ explicit BasicDevice(const std::string& name, uint8_t bus, uint16_t address, const std::string& powerControlGPIOName, const std::string& powerGoodGPIOName, std::vector> rails) : name{name}, bus{bus}, address{address}, powerControlGPIOName{powerControlGPIOName}, powerGoodGPIOName{powerGoodGPIOName}, rails{std::move(rails)} {} /** * Destructor. * * Closes the device if it is open. */ virtual ~BasicDevice() { if (isOpen()) { // Destructors must not throw exceptions closeWithoutException(); } } /** @copydoc PowerSequencerDevice::getName() */ virtual const std::string& getName() const override { return name; } /** @copydoc PowerSequencerDevice::getBus() */ virtual uint8_t getBus() const override { return bus; } /** @copydoc PowerSequencerDevice::getAddress() */ virtual uint16_t getAddress() const override { return address; } /** @copydoc PowerSequencerDevice::getPowerControlGPIOName() */ virtual const std::string& getPowerControlGPIOName() const override { return powerControlGPIOName; } /** @copydoc PowerSequencerDevice::getPowerGoodGPIOName() */ virtual const std::string& getPowerGoodGPIOName() const override { return powerGoodGPIOName; } /** @copydoc PowerSequencerDevice::getRails() */ virtual const std::vector>& getRails() const override { return rails; } /** @copydoc PowerSequencerDevice::open() */ virtual void open(Services& services) override { if (!isOpen()) { powerControlGPIO = services.createGPIO(powerControlGPIOName); powerGoodGPIO = services.createGPIO(powerGoodGPIOName); powerGoodGPIO->requestRead(); isDeviceOpen = true; } } /** @copydoc PowerSequencerDevice::isOpen() */ virtual bool isOpen() const override { return isDeviceOpen; } /** @copydoc PowerSequencerDevice::close() */ virtual void close() override { if (isOpen()) { powerControlGPIO.reset(); // Verify pointer valid in case close() threw exception previously if (powerGoodGPIO) { powerGoodGPIO->release(); } powerGoodGPIO.reset(); isDeviceOpen = false; } } /** @copydoc PowerSequencerDevice::closeWithoutException() */ virtual void closeWithoutException() noexcept override { try { close(); } catch (...) {} } /** @copydoc PowerSequencerDevice::getPowerControlGPIO() */ virtual GPIO& getPowerControlGPIO() override { verifyIsOpen(); return *powerControlGPIO; } /** @copydoc PowerSequencerDevice::getPowerGoodGPIO() */ virtual GPIO& getPowerGoodGPIO() override { verifyIsOpen(); return *powerGoodGPIO; } /** @copydoc PowerSequencerDevice::powerOn() */ virtual void powerOn() override { verifyIsOpen(); powerControlGPIO->requestWrite(1); powerControlGPIO->setValue(1); powerControlGPIO->release(); } /** @copydoc PowerSequencerDevice::powerOff() */ virtual void powerOff() override { verifyIsOpen(); powerControlGPIO->requestWrite(0); powerControlGPIO->setValue(0); powerControlGPIO->release(); } /** @copydoc PowerSequencerDevice::getPowerGood() */ virtual bool getPowerGood() override { verifyIsOpen(); return (powerGoodGPIO->getValue() == 1); } protected: /** * Verifies that this device is open. * * Throws an exception if device is not open. */ virtual void verifyIsOpen() { if (!isOpen()) { throw std::runtime_error{"Device not open: " + name}; } } /** * Device name. */ std::string name{}; /** * I2C bus for the device. */ uint8_t bus; /** * I2C address for the device. */ uint16_t address; /** * Name of the GPIO that turns this device on and off. */ std::string powerControlGPIOName{}; /** * Name of the GPIO that reads the power good signal from this device. */ std::string powerGoodGPIOName{}; /** * Voltage rails that are enabled and monitored by this device. */ std::vector> rails{}; /** * Specifies whether this device is open. */ bool isDeviceOpen{false}; /** * GPIO that turns this device on and off. */ std::unique_ptr powerControlGPIO{}; /** * GPIO that reads the power good signal from this device. */ std::unique_ptr powerGoodGPIO{}; }; } // namespace phosphor::power::sequencer