blob: e7e85ac8d1411623b84ef917a0c97987ce8fd775 [file] [log] [blame]
/**
* Copyright © 2024 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 "pmbus.hpp"
#include "rail.hpp"
#include "services.hpp"
#include "standard_device.hpp"
#include <stddef.h> // for size_t
#include <cstdint>
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>
namespace phosphor::power::sequencer
{
/**
* @class PMBusDriverDevice
*
* StandardDevice sub-class for power sequencer devices that are bound to a
* PMBus device driver.
*/
class PMBusDriverDevice : public StandardDevice
{
public:
// Specify which compiler-generated methods we want
PMBusDriverDevice() = delete;
PMBusDriverDevice(const PMBusDriverDevice&) = delete;
PMBusDriverDevice(PMBusDriverDevice&&) = delete;
PMBusDriverDevice& operator=(const PMBusDriverDevice&) = delete;
PMBusDriverDevice& operator=(PMBusDriverDevice&&) = delete;
virtual ~PMBusDriverDevice() = default;
/**
* Constructor.
*
* @param name Device name
* @param rails Voltage rails that are enabled and monitored by this device
* @param services System services like hardware presence and the journal
* @param bus I2C bus for the device
* @param address I2C address for the device
* @param driverName Device driver name
* @param instance Chip instance number
*/
explicit PMBusDriverDevice(const std::string& name,
std::vector<std::unique_ptr<Rail>> rails,
Services& services, uint8_t bus,
uint16_t address,
const std::string& driverName = "",
size_t instance = 0) :
StandardDevice(name, std::move(rails)),
bus{bus}, address{address}, driverName{driverName}, instance{instance}
{
pmbusInterface = services.createPMBus(bus, address, driverName,
instance);
}
/**
* Returns the I2C bus for the device.
*
* @return I2C bus
*/
uint8_t getBus() const
{
return bus;
}
/**
* Returns the I2C address for the device.
*
* @return I2C address
*/
uint16_t getAddress() const
{
return address;
}
/**
* Returns the device driver name.
*
* @return driver name
*/
const std::string& getDriverName() const
{
return driverName;
}
/**
* Returns the chip instance number.
*
* @return chip instance
*/
size_t getInstance() const
{
return instance;
}
/**
* Returns interface to the PMBus information that is provided by the device
* driver in sysfs.
*
* @return PMBus interface object
*/
pmbus::PMBusBase& getPMBusInterface()
{
return *pmbusInterface;
}
/** @copydoc PowerSequencerDevice::getGPIOValues() */
virtual std::vector<int> getGPIOValues(Services& services) override;
/** @copydoc PowerSequencerDevice::getStatusWord() */
virtual uint16_t getStatusWord(uint8_t page) override;
/** @copydoc PowerSequencerDevice::getStatusVout() */
virtual uint8_t getStatusVout(uint8_t page) override;
/** @copydoc PowerSequencerDevice::getReadVout() */
virtual double getReadVout(uint8_t page) override;
/** @copydoc PowerSequencerDevice::getVoutUVFaultLimit() */
virtual double getVoutUVFaultLimit(uint8_t page) override;
/**
* Returns map from PMBus PAGE numbers to sysfs hwmon file numbers.
*
* Throws an exception if an error occurs trying to build the map.
*
* @return page to file number map
*/
const std::map<uint8_t, unsigned int>& getPageToFileNumberMap()
{
if (pageToFileNumber.empty())
{
buildPageToFileNumberMap();
}
return pageToFileNumber;
}
/**
* Returns the hwmon file number that corresponds to the specified PMBus
* PAGE number.
*
* Throws an exception if a file number was not found for the specified PAGE
* number.
*
* @param page PMBus PAGE number
* @return hwmon file number
*/
unsigned int getFileNumber(uint8_t page);
protected:
/** @copydoc StandardDevice::prepareForPgoodFaultDetection() */
virtual void prepareForPgoodFaultDetection(Services& services) override
{
// Rebuild PMBus PAGE to hwmon file number map
buildPageToFileNumberMap();
// Call parent class method to do any actions defined there
StandardDevice::prepareForPgoodFaultDetection(services);
}
/**
* Build mapping from PMBus PAGE numbers to the hwmon file numbers in
* sysfs.
*
* hwmon file names have the format:
* <type><number>_<item>
*
* The <number> is not the PMBus PAGE number. The PMBus PAGE is determined
* by reading the contents of the <type><number>_label file.
*
* If the map is not empty, it is cleared and rebuilt. This is necessary
* over time because power devices may have been added or removed.
*
* Throws an exception if an error occurs trying to build the map.
*/
virtual void buildPageToFileNumberMap();
/**
* Returns whether the specified sysfs hwmon file is a voltage label file.
*
* If it is a label file, the hwmon file number is obtained from the file
* name and returned.
*
* @param fileName file within the sysfs hwmon directory
* @param fileNumber the hwmon file number is stored in this output
* parameter if this is a label file
* @return true if specified file is a voltage label file, false otherwise
*/
virtual bool isLabelFile(const std::string& fileName,
unsigned int& fileNumber);
/**
* Reads the specified voltage label file to obtain the associated PMBus
* PAGE number.
*
* The returned optional variable will have no value if the PMBus PAGE
* number could not be obtained due to an error.
*
* @param fileName voltage label file within the sysfs hwmon directory
* @return PMBus page number
*/
virtual std::optional<uint8_t>
readPageFromLabelFile(const std::string& fileName);
/**
* I2C bus for the device.
*/
uint8_t bus;
/**
* I2C address for the device.
*/
uint16_t address;
/**
* Device driver name.
*/
std::string driverName;
/**
* Chip instance number.
*/
size_t instance;
/**
* Interface to the PMBus information that is provided by the device driver
* in sysfs.
*/
std::unique_ptr<pmbus::PMBusBase> pmbusInterface;
/**
* Map from PMBus PAGE numbers to sysfs hwmon file numbers.
*/
std::map<uint8_t, unsigned int> pageToFileNumber;
};
} // namespace phosphor::power::sequencer