1bf7b7b1dSMatthew Barth #pragma once
2bf7b7b1dSMatthew Barth
3043d3230SPatrick Venture #include "env.hpp"
4043d3230SPatrick Venture #include "fan_pwm.hpp"
5043d3230SPatrick Venture #include "fan_speed.hpp"
6043d3230SPatrick Venture #include "hwmonio.hpp"
7043d3230SPatrick Venture
8b4e6557fSMatt Spinler #include <phosphor-logging/elog-errors.hpp>
9b4e6557fSMatt Spinler #include <phosphor-logging/log.hpp>
10b4e6557fSMatt Spinler #include <xyz/openbmc_project/Sensor/Device/error.hpp>
11bf7b7b1dSMatthew Barth
12e8771fd4SPatrick Williams #include <filesystem>
1364129937SPatrick Williams #include <format>
14e8771fd4SPatrick Williams #include <memory>
15e8771fd4SPatrick Williams
16a7e2c1e5SMatt Spinler enum class targetType
17a7e2c1e5SMatt Spinler {
18a7e2c1e5SMatt Spinler DEFAULT,
19a7e2c1e5SMatt Spinler RPM,
20a7e2c1e5SMatt Spinler PWM
21a7e2c1e5SMatt Spinler };
22a7e2c1e5SMatt Spinler
23a7e2c1e5SMatt Spinler static constexpr auto RPM_TARGET = "RPM";
24a7e2c1e5SMatt Spinler static constexpr auto PWM_TARGET = "PWM";
25a7e2c1e5SMatt Spinler
26bf7b7b1dSMatthew Barth /** @class Targets
27bf7b7b1dSMatthew Barth * @brief Target type traits.
28bf7b7b1dSMatthew Barth *
29bf7b7b1dSMatthew Barth * @tparam T - The target type.
30bf7b7b1dSMatthew Barth */
31bf7b7b1dSMatthew Barth template <typename T>
32bf7b7b1dSMatthew Barth struct Targets
33bf7b7b1dSMatthew Barth {
failTargets34bf7b7b1dSMatthew Barth static void fail()
35bf7b7b1dSMatthew Barth {
36bf7b7b1dSMatthew Barth static_assert(sizeof(Targets) == -1, "Unsupported Target type");
37bf7b7b1dSMatthew Barth }
38bf7b7b1dSMatthew Barth };
39bf7b7b1dSMatthew Barth
40bf7b7b1dSMatthew Barth /**@brief Targets specialization for fan speed. */
41bf7b7b1dSMatthew Barth template <>
42048ac87fSMatthew Barth struct Targets<hwmon::FanSpeed>
43bf7b7b1dSMatthew Barth {
44bf7b7b1dSMatthew Barth static constexpr InterfaceType type = InterfaceType::FAN_SPEED;
45bf7b7b1dSMatthew Barth };
46bf7b7b1dSMatthew Barth
479331ab78SPatrick Venture template <>
489331ab78SPatrick Venture struct Targets<hwmon::FanPwm>
499331ab78SPatrick Venture {
509331ab78SPatrick Venture static constexpr InterfaceType type = InterfaceType::FAN_PWM;
519331ab78SPatrick Venture };
529331ab78SPatrick Venture
53bf7b7b1dSMatthew Barth /** @brief addTarget
54bf7b7b1dSMatthew Barth *
55bf7b7b1dSMatthew Barth * Creates the target type interface
56bf7b7b1dSMatthew Barth *
57bf7b7b1dSMatthew Barth * @tparam T - The target type
58bf7b7b1dSMatthew Barth *
59bf7b7b1dSMatthew Barth * @param[in] sensor - A sensor type and name
60b4e6557fSMatt Spinler * @param[in] ioAccess - hwmon sysfs access object
61b4e6557fSMatt Spinler * @param[in] devPath - The /sys/devices sysfs path
62bf7b7b1dSMatthew Barth * @param[in] info - The sdbusplus server connection and interfaces
630a8de645SMatt Spinler *
640a8de645SMatt Spinler * @return A shared pointer to the target interface object
650a8de645SMatt Spinler * Will be empty if no interface was created
66bf7b7b1dSMatthew Barth */
67bf7b7b1dSMatthew Barth template <typename T>
addTarget(const SensorSet::key_type & sensor,const hwmonio::HwmonIOInterface * ioAccess,const std::string & devPath,ObjectInfo & info)680a8de645SMatt Spinler std::shared_ptr<T> addTarget(const SensorSet::key_type& sensor,
6916805a6aSPatrick Venture const hwmonio::HwmonIOInterface* ioAccess,
70043d3230SPatrick Venture const std::string& devPath, ObjectInfo& info)
71bf7b7b1dSMatthew Barth {
720a8de645SMatt Spinler std::shared_ptr<T> target;
739e997b4dSPatrick Venture namespace fs = std::filesystem;
74bf7b7b1dSMatthew Barth
756206723dSPatrick Venture auto& obj = std::get<InterfaceMap>(info);
76bf7b7b1dSMatthew Barth auto& objPath = std::get<std::string>(info);
779331ab78SPatrick Venture auto type = Targets<T>::type;
78bf7b7b1dSMatthew Barth
79bf7b7b1dSMatthew Barth // Check if target sysfs file exists
809331ab78SPatrick Venture std::string sysfsFullPath;
81a4bba96eSLei YU std::string targetName = sensor.first;
82a4bba96eSLei YU std::string targetId = sensor.second;
83a4bba96eSLei YU std::string entry = hwmon::entry::target;
849331ab78SPatrick Venture
859331ab78SPatrick Venture using namespace std::literals;
869331ab78SPatrick Venture const std::string pwm = "pwm"s;
879331ab78SPatrick Venture const std::string empty = ""s;
889331ab78SPatrick Venture
899331ab78SPatrick Venture if (InterfaceType::FAN_PWM == type)
909331ab78SPatrick Venture {
91a4bba96eSLei YU targetName = pwm;
92a4bba96eSLei YU // If PWM_TARGET is set, use the specified pwm id
937a5285deSPatrick Venture auto id = env::getEnv("PWM_TARGET", sensor);
94a4bba96eSLei YU if (!id.empty())
959331ab78SPatrick Venture {
96a4bba96eSLei YU targetId = id;
97a4bba96eSLei YU }
98a4bba96eSLei YU entry = empty;
999331ab78SPatrick Venture }
1009331ab78SPatrick Venture
101*02e598abSPatrick Williams sysfsFullPath =
102*02e598abSPatrick Williams sysfs::make_sysfs_path(ioAccess->path(), targetName, targetId, entry);
103048ac87fSMatthew Barth if (fs::exists(sysfsFullPath))
104bf7b7b1dSMatthew Barth {
10528f8e66dSMatthew Barth auto useTarget = true;
106a24c8808SPatrick Venture auto tmEnv = env::getEnv("TARGET_MODE");
107a24c8808SPatrick Venture if (!tmEnv.empty())
10828f8e66dSMatthew Barth {
10928f8e66dSMatthew Barth std::string mode{tmEnv};
11028f8e66dSMatthew Barth std::transform(mode.begin(), mode.end(), mode.begin(), toupper);
11128f8e66dSMatthew Barth
11228f8e66dSMatthew Barth if (mode == RPM_TARGET)
11328f8e66dSMatthew Barth {
11428f8e66dSMatthew Barth if (type != InterfaceType::FAN_SPEED)
11528f8e66dSMatthew Barth {
11628f8e66dSMatthew Barth useTarget = false;
11728f8e66dSMatthew Barth }
11828f8e66dSMatthew Barth }
11928f8e66dSMatthew Barth else if (mode == PWM_TARGET)
12028f8e66dSMatthew Barth {
12128f8e66dSMatthew Barth if (type != InterfaceType::FAN_PWM)
12228f8e66dSMatthew Barth {
12328f8e66dSMatthew Barth useTarget = false;
12428f8e66dSMatthew Barth }
12528f8e66dSMatthew Barth }
12628f8e66dSMatthew Barth else
12728f8e66dSMatthew Barth {
12828f8e66dSMatthew Barth using namespace phosphor::logging;
129043d3230SPatrick Venture log<level::ERR>(
130043d3230SPatrick Venture "Invalid TARGET_MODE env var found",
131043d3230SPatrick Venture phosphor::logging::entry("TARGET_MODE=%s", tmEnv.c_str()),
132043d3230SPatrick Venture phosphor::logging::entry("DEVPATH=%s", devPath.c_str()));
13328f8e66dSMatthew Barth }
13428f8e66dSMatthew Barth }
13528f8e66dSMatthew Barth
13628f8e66dSMatthew Barth if (useTarget)
13728f8e66dSMatthew Barth {
138b4e6557fSMatt Spinler uint32_t targetSpeed = 0;
139b4e6557fSMatt Spinler
140b4e6557fSMatt Spinler try
141b4e6557fSMatt Spinler {
14216805a6aSPatrick Venture targetSpeed = ioAccess->read(targetName, targetId, entry,
143043d3230SPatrick Venture hwmonio::retries, hwmonio::delay);
1449331ab78SPatrick Venture }
145b4e6557fSMatt Spinler catch (const std::system_error& e)
146b4e6557fSMatt Spinler {
147b4e6557fSMatt Spinler using namespace phosphor::logging;
148043d3230SPatrick Venture using namespace sdbusplus::xyz::openbmc_project::Sensor::
149043d3230SPatrick Venture Device::Error;
150043d3230SPatrick Venture using metadata =
151043d3230SPatrick Venture xyz::openbmc_project::Sensor::Device::ReadFailure;
152b4e6557fSMatt Spinler
153b4e6557fSMatt Spinler report<ReadFailure>(
154b4e6557fSMatt Spinler metadata::CALLOUT_ERRNO(e.code().value()),
155b4e6557fSMatt Spinler metadata::CALLOUT_DEVICE_PATH(devPath.c_str()));
156b4e6557fSMatt Spinler
15764129937SPatrick Williams log<level::INFO>(std::format("Failing sysfs file: {} errno: {}",
1586a391de4SMatt Spinler sysfsFullPath, e.code().value())
1595e034afcSMatt Spinler .c_str());
160b4e6557fSMatt Spinler }
161b4e6557fSMatt Spinler
162685efa16SPatrick Venture static constexpr bool deferSignals = true;
163ad6043f6SPatrick Williams auto& bus = *std::get<sdbusplus::bus_t*>(info);
164685efa16SPatrick Venture
16516805a6aSPatrick Venture // ioAccess->path() is a path like: /sys/class/hwmon/hwmon1
16616805a6aSPatrick Venture // NOTE: When unit-testing, the target won't have an inject-ible
16716805a6aSPatrick Venture // ioAccess: fan_pwm/fan_speed.
16850552377SPatrick Venture target = std::make_shared<T>(
16916805a6aSPatrick Venture std::move(std::make_unique<hwmonio::HwmonIO>(ioAccess->path())),
170043d3230SPatrick Venture devPath, targetId, bus, objPath.c_str(), deferSignals,
171b4e6557fSMatt Spinler targetSpeed);
1720a8de645SMatt Spinler obj[type] = target;
173bf7b7b1dSMatthew Barth }
17428f8e66dSMatthew Barth }
1750a8de645SMatt Spinler
1760a8de645SMatt Spinler return target;
177bf7b7b1dSMatthew Barth }
178