blob: 057c4c8ac7ffe46a50f4f241dbe1575564f4f5cf [file] [log] [blame]
/**
* 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 <cstdint>
#include <memory>
#include <stdexcept>
#include <string>
#include <utility>
#include <vector>
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<std::unique_ptr<Rail>> 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<std::unique_ptr<Rail>>& 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<std::unique_ptr<Rail>> rails{};
/**
* Specifies whether this device is open.
*/
bool isDeviceOpen{false};
/**
* GPIO that turns this device on and off.
*/
std::unique_ptr<GPIO> powerControlGPIO{};
/**
* GPIO that reads the power good signal from this device.
*/
std::unique_ptr<GPIO> powerGoodGPIO{};
};
} // namespace phosphor::power::sequencer