meta-quanta: gbs: add hwmon sensors

Define the configuration files of the related sensors
and test pass

0001-lev-add-poweron-monitor-feature.patch
In-Review: https://gerrit.openbmc-project.xyz/c/openbmc/phosphor-hwmon/+/28181

0002-lev-add-sensors-slow-readings.patch
In-Review: https://gerrit.openbmc-project.xyz/c/openbmc/phosphor-hwmon/+/24337

(From meta-quanta rev: a66f2b941cede5fc15fe0d6d56ca2ac9352fdf77)

Signed-off-by: George Hung <george.hung@quantatw.com>
Change-Id: If7f767cbd952cde593e03d30c45572a21cc7c960
Signed-off-by: Andrew Geissler <geissonator@yahoo.com>
diff --git a/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/0001-lev-add-poweron-monitor-feature.patch b/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/0001-lev-add-poweron-monitor-feature.patch
new file mode 100644
index 0000000..dfe82ef
--- /dev/null
+++ b/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/0001-lev-add-poweron-monitor-feature.patch
@@ -0,0 +1,256 @@
+From 58eec8f1f80e274ff669bd19c00b8f1ea8ceae0f Mon Sep 17 00:00:00 2001
+From: Duke Du <Duke.Du@quantatw.com>
+Date: Mon, 18 May 2020 19:45:27 +0800
+Subject: [PATCH] lev-add-poweron-monitor-feature
+
+---
+ Makefile.am    |   2 ++
+ mainloop.cpp   | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ sensor.cpp     |  11 ++++++-
+ sensor.hpp     |  13 ++++++++
+ thresholds.hpp |   2 --
+ 5 files changed, 126 insertions(+), 3 deletions(-)
+
+diff --git a/Makefile.am b/Makefile.am
+index 378c565..5fa230a 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -46,6 +46,7 @@ libhwmon_la_LIBADD = \
+ 	$(SDEVENTPLUS_LIBS) \
+ 	$(PHOSPHOR_DBUS_INTERFACES_LIBS) \
+ 	$(PHOSPHOR_LOGGING_LIBS) \
++	$(PTHREAD_LIBS) \
+ 	$(GPIOPLUS_LIBS) \
+ 	$(STDPLUS_LIBS) \
+ 	$(CODE_COVERAGE_LIBS)
+@@ -54,6 +55,7 @@ libhwmon_la_CXXFLAGS = \
+ 	$(SDEVENTPLUS_CFLAGS) \
+ 	$(PHOSPHOR_DBUS_INTERFACES_CFLAGS) \
+ 	$(PHOSPHOR_LOGGING_CFLAGS) \
++	$(PTHREAD_CFLAGS) \
+ 	$(STDPLUS_CFLAGS) \
+ 	$(CODE_COVERAGE_CXXFLAGS)
+ 
+diff --git a/mainloop.cpp b/mainloop.cpp
+index bd334a0..1769e94 100644
+--- a/mainloop.cpp
++++ b/mainloop.cpp
+@@ -39,6 +39,12 @@
+ #include <string>
+ #include <unordered_set>
+ #include <xyz/openbmc_project/Sensor/Device/error.hpp>
++#include <boost/container/flat_map.hpp>
++#include <boost/algorithm/string/predicate.hpp>
++#include <sdbusplus/asio/connection.hpp>
++#include <sdbusplus/asio/object_server.hpp>
++#include <sdbusplus/message/types.hpp>
++#include <sdbusplus/timer.hpp>
+ 
+ using namespace phosphor::logging;
+ 
+@@ -74,6 +80,12 @@ decltype(
+     Thresholds<CriticalObject>::alarmHi) Thresholds<CriticalObject>::alarmHi =
+     &CriticalObject::criticalAlarmHigh;
+ 
++static std::unique_ptr<phosphor::Timer> cacheTimer = nullptr;
++static std::unique_ptr<sdbusplus::bus::match::match> powerMatch = nullptr;
++static bool powerStatusOn = false;
++static boost::asio::io_service io; 
++static auto conn = std::make_shared<sdbusplus::asio::connection>(io);
++
+ void updateSensorInterfaces(InterfaceMap& ifaces, int64_t value)
+ {
+     for (auto& iface : ifaces)
+@@ -101,6 +113,83 @@ void updateSensorInterfaces(InterfaceMap& ifaces, int64_t value)
+     }
+ }
+ 
++void powerStatusSet()
++{
++    powerStatusOn = true;
++    return;
++}
++
++void createTimer()
++{
++    if (cacheTimer == nullptr)
++    {
++        cacheTimer = std::make_unique<phosphor::Timer>(powerStatusSet);
++    }
++}
++
++bool isPowerOn(void)
++{
++    if (!powerMatch)
++    {
++        throw std::runtime_error("Power Match Not Created");
++    }
++    return powerStatusOn;
++}
++
++void setupPowerMatch(sdbusplus::bus::bus& bus)
++{
++    if (powerMatch)
++    {
++        return;
++    }
++
++    powerMatch = std::make_unique<sdbusplus::bus::match::match>(
++        bus,
++        "type='signal',interface='org.freedesktop.DBus.Properties',path='/xyz/"
++        "openbmc_project/state/"
++        "host0',arg0='xyz.openbmc_project.State.Host'",
++       [](sdbusplus::message::message& message) {
++            std::string objectName;
++            boost::container::flat_map<std::string, std::variant<std::string>>
++                values;
++	    message.read(objectName, values);
++	    auto findState = values.find("CurrentHostState");
++	    if (findState != values.end())
++	    {
++	        bool on = boost::ends_with(
++                    std::get<std::string>(findState->second), "Running");
++		if (!on)
++                {
++		    cacheTimer->stop();
++                    powerStatusOn = false;
++                    return;
++                }
++		cacheTimer->start(std::chrono::duration_cast<std::chrono::microseconds>(
++                    std::chrono::seconds(10)));
++	    }
++	    else {
++		powerStatusOn = false;
++            }
++       });
++
++    conn->async_method_call(
++        [](boost::system::error_code ec,
++           const std::variant<std::string>& state) {
++            if (ec)
++            {
++                return;
++            }
++            powerStatusOn =
++                boost::ends_with(std::get<std::string>(state), "Running");
++        },
++        "xyz.openbmc_project.State.Host", 
++	"/xyz/openbmc_project/state/host0", 
++	"org.freedesktop.DBus.Properties", "Get",
++        "xyz.openbmc_project.State.Host", "CurrentHostState");
++
++    createTimer();
++}
++
+ std::string MainLoop::getID(SensorSet::container_t::const_reference sensor)
+ {
+     std::string id;
+@@ -385,6 +474,7 @@ void MainLoop::init()
+             _interval = std::strtoull(interval.c_str(), NULL, 10);
+         }
+     }
++    setupPowerMatch(_bus);
+ }
+ 
+ void MainLoop::read()
+@@ -429,6 +519,12 @@ void MainLoop::read()
+ 
+         try
+         {
++            if(sensor->pwrOnMonitor() && !isPowerOn())
++            {
++                statusIface->functional(false);
++                continue;
++            }
++
+             if (sensor->hasFaultFile())
+             {
+                 auto fault = _ioAccess->read(sensorSysfsType, sensorSysfsNum,
+@@ -491,6 +587,11 @@ void MainLoop::read()
+                 }
+             }
+ 
++            if(sensor->pwrOnMonitor() && !isPowerOn())
++            {
++		statusIface->functional(false);
++	        continue;    
++            }
+             updateSensorInterfaces(obj, value);
+         }
+         catch (const std::system_error& e)
+diff --git a/sensor.cpp b/sensor.cpp
+index 145ba6c..93bbb03 100644
+--- a/sensor.cpp
++++ b/sensor.cpp
+@@ -41,7 +41,7 @@ Sensor::Sensor(const SensorSet::key_type& sensor,
+                const hwmonio::HwmonIOInterface* ioAccess,
+                const std::string& devPath) :
+     _sensor(sensor),
+-    _ioAccess(ioAccess), _devPath(devPath), _scale(0), _hasFaultFile(false)
++    _ioAccess(ioAccess), _devPath(devPath), _scale(0), _hasFaultFile(false), _pwrOnMonitor(false)
+ {
+     auto chip = env::getEnv("GPIOCHIP", sensor);
+     auto access = env::getEnv("GPIO", sensor);
+@@ -70,6 +70,15 @@ Sensor::Sensor(const SensorSet::key_type& sensor,
+     auto senRmRCs = env::getEnv("REMOVERCS", sensor);
+     // Add sensor removal return codes defined per sensor
+     addRemoveRCs(senRmRCs);
++
++    auto pwrOnMon = env::getEnv("PWRONMON", sensor);
++    if (!pwrOnMon.empty())
++    {
++        if (pwrOnMon == "ON")
++        {
++            _pwrOnMonitor = true;
++        }
++    }
+ }
+ 
+ void Sensor::addRemoveRCs(const std::string& rcList)
+diff --git a/sensor.hpp b/sensor.hpp
+index 4b2d281..369a252 100644
+--- a/sensor.hpp
++++ b/sensor.hpp
+@@ -135,6 +135,16 @@ class Sensor
+         return _hasFaultFile;
+     }
+ 
++    /**
++     * @brief Get whether the sensor only need to be monitored in power on state or not.
++     *
++     * @return - Boolean on whether the sensor only need to be monitored in power on state
++     */
++    inline bool pwrOnMonitor(void) const
++    {
++        return _pwrOnMonitor;
++    }
++
+   private:
+     /** @brief Sensor object's identifiers */
+     SensorSet::key_type _sensor;
+@@ -156,6 +166,9 @@ class Sensor
+ 
+     /** @brief Tracks whether the sensor has a fault file or not. */
+     bool _hasFaultFile;
++
++    /** @brief Whether the sensor only need to be monitored in power on state or not. */
++    bool _pwrOnMonitor;
+ };
+ 
+ /**
+diff --git a/thresholds.hpp b/thresholds.hpp
+index 4d2fcff..972a469 100644
+--- a/thresholds.hpp
++++ b/thresholds.hpp
+@@ -101,8 +101,6 @@ auto addThreshold(const std::string& sensorType, const std::string& sensorID,
+         auto hi = stod(tHi) * std::pow(10, scale);
+         (*iface.*Thresholds<T>::setLo)(lo);
+         (*iface.*Thresholds<T>::setHi)(hi);
+-        (*iface.*Thresholds<T>::alarmLo)(value <= lo);
+-        (*iface.*Thresholds<T>::alarmHi)(value >= hi);
+         auto type = Thresholds<T>::type;
+         obj[type] = iface;
+     }
+-- 
+2.7.4
+
diff --git a/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/0002-lev-add-sensors-slow-readings.patch b/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/0002-lev-add-sensors-slow-readings.patch
new file mode 100644
index 0000000..0a2efd8
--- /dev/null
+++ b/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/0002-lev-add-sensors-slow-readings.patch
@@ -0,0 +1,284 @@
+From 61b91122b72d7a3a5c93b80b6fb6d3ac892619dc Mon Sep 17 00:00:00 2001
+From: Eddielu <Eddie.Lu@quantatw.com>
+Date: Mon, 1 Jun 2020 14:18:33 +0800
+Subject: [PATCH] add sensors slow readings
+
+---
+ mainloop.cpp | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
+ mainloop.hpp |  3 +++
+ sensor.cpp   | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++-------
+ sensor.hpp   | 21 +++++++++++++++--
+ 4 files changed, 158 insertions(+), 15 deletions(-)
+
+diff --git a/mainloop.cpp b/mainloop.cpp
+index 1769e94..5094343 100644
+--- a/mainloop.cpp
++++ b/mainloop.cpp
+@@ -32,6 +32,7 @@
+ #include <cassert>
+ #include <cstdlib>
+ #include <functional>
++#include <future>
+ #include <iostream>
+ #include <memory>
+ #include <phosphor-logging/elog-errors.hpp>
+@@ -296,7 +297,7 @@ std::optional<ObjectStateData>
+     {
+         // Add status interface based on _fault file being present
+         sensorObj->addStatus(info);
+-        valueInterface = sensorObj->addValue(retryIO, info);
++        valueInterface = sensorObj->addValue(retryIO, info, _timedoutMap);
+     }
+     catch (const std::system_error& e)
+     {
+@@ -542,10 +543,74 @@ void MainLoop::read()
+                 // RAII object for GPIO unlock / lock
+                 auto locker = sensor::gpioUnlock(sensor->getGpio());
+ 
+-                // Retry for up to a second if device is busy
+-                // or has a transient error.
+-                value = _ioAccess->read(sensorSysfsType, sensorSysfsNum, input,
++                // For sensors with attribute ASYNC_READ_TIMEOUT,
++                // spawn a thread with timeout
++                auto asyncRead =
++                    env::getEnv("ASYNC_READ_TIMEOUT", sensorSetKey);
++                if (!asyncRead.empty())
++                {
++                    // Default async read timeout
++                    std::chrono::milliseconds asyncReadTimeout{
++                        std::stoi(asyncRead)};
++                    bool valueIsValid = false;
++                    std::future<SensorValueType> asyncThread;
++
++                    auto asyncIter = _timedoutMap.find(sensorSetKey);
++                    if (asyncIter == _timedoutMap.end())
++                    {
++                        // If sesnor not found in timedoutMap, spawn an async
++                        // thread
++                        asyncThread = std::async(
++                            std::launch::async,
++                            &hwmonio::HwmonIOInterface::read, _ioAccess,
++                            sensorSysfsType, sensorSysfsNum, input,
++                            hwmonio::retries, hwmonio::delay);
++                        valueIsValid = true;
++                    }
++                    else
++                    {
++                        // If we already have the async thread in the
++                        // timedoutMap, it means this sensor has already timed
++                        // out in the previous reads. No need to wait on
++                        // subsequent reads
++                        asyncReadTimeout = std::chrono::seconds(0);
++                        asyncThread = std::move(asyncIter->second);
++                    }
++
++                    std::future_status status =
++                        asyncThread.wait_for(asyncReadTimeout);
++                    switch (status)
++                    {
++                        // Read has finished
++                        case std::future_status::ready:
++                            // Read has finished
++                            if (valueIsValid)
++                            {
++                                value = asyncThread.get();
++                                break;
++                                // Good sensor reads should skip the code below
++                            }
++                            // Async read thread has completed, erase from
++                            // timedoutMap to allow retry then throw
++                            _timedoutMap.erase(sensorSetKey);
++                            throw sensor::AsyncSensorReadTimeOut();
++                        default:
++                            // Read timed out so add the thread to the
++                            // timedoutMap (if the entry already exists,
++                            // operator[] updates it)
++                            _timedoutMap[sensorSetKey] = std::move(asyncThread);
++                            throw sensor::AsyncSensorReadTimeOut();
++                    }
++                }
++                else
++                {
++                    // Retry for up to a second if device is busy
++                    // or has a transient error.
++                    value =
++                        _ioAccess->read(sensorSysfsType, sensorSysfsNum, input,
+                                         hwmonio::retries, hwmonio::delay);
++                }
++
+                 // Set functional property to true if we could read sensor
+                 statusIface->functional(true);
+ 
+diff --git a/mainloop.hpp b/mainloop.hpp
+index 6c5b8e0..cfe34d5 100644
+--- a/mainloop.hpp
++++ b/mainloop.hpp
+@@ -9,6 +9,7 @@
+ #include "types.hpp"
+ 
+ #include <any>
++#include <future>
+ #include <memory>
+ #include <optional>
+ #include <sdbusplus/server.hpp>
+@@ -116,6 +117,8 @@ class MainLoop
+     /** @brief Store the specifications of sensor objects */
+     std::map<SensorSet::key_type, std::unique_ptr<sensor::Sensor>>
+         _sensorObjects;
++    /** @brief Store the async futures of timed out sensor objects */
++    std::map<SensorSet::key_type, std::future<SensorValueType>> _timedoutMap;
+ 
+     /**
+      * @brief Map of removed sensors
+diff --git a/sensor.cpp b/sensor.cpp
+index 93bbb03..7b681e1 100644
+--- a/sensor.cpp
++++ b/sensor.cpp
+@@ -13,6 +13,7 @@
+ #include <cmath>
+ #include <cstring>
+ #include <filesystem>
++#include <future>
+ #include <phosphor-logging/elog-errors.hpp>
+ #include <thread>
+ #include <xyz/openbmc_project/Common/error.hpp>
+@@ -135,8 +136,9 @@ SensorValueType Sensor::adjustValue(SensorValueType value)
+     return value;
+ }
+ 
+-std::shared_ptr<ValueObject> Sensor::addValue(const RetryIO& retryIO,
+-                                              ObjectInfo& info)
++std::shared_ptr<ValueObject> Sensor::addValue(
++    const RetryIO& retryIO, ObjectInfo& info,
++    std::map<SensorSet::key_type, std::future<SensorValueType>>& timedoutMap)
+ {
+     static constexpr bool deferSignals = true;
+ 
+@@ -163,13 +165,69 @@ std::shared_ptr<ValueObject> Sensor::addValue(const RetryIO& retryIO,
+             // RAII object for GPIO unlock / lock
+             auto locker = gpioUnlock(getGpio());
+ 
+-            // Retry for up to a second if device is busy
+-            // or has a transient error.
+-            val =
+-                _ioAccess->read(_sensor.first, _sensor.second,
+-                                hwmon::entry::cinput, std::get<size_t>(retryIO),
+-                                std::get<std::chrono::milliseconds>(retryIO));
+-
++            // For sensors with attribute ASYNC_READ_TIMEOUT,
++            // spawn a thread with timeout
++            auto asyncRead = env::getEnv("ASYNC_READ_TIMEOUT", _sensor);
++            if (!asyncRead.empty())
++            {
++                // Default async read timeout
++                std::chrono::milliseconds asyncReadTimeout{
++                    std::stoi(asyncRead)};
++                bool valueIsValid = false;
++                std::future<SensorValueType> asyncThread;
++
++                auto asyncIter = timedoutMap.find(_sensor);
++                if (asyncIter == timedoutMap.end())
++                {
++                    // If sesnor not found in timedoutMap, spawn an async thread
++                    asyncThread = std::async(
++                        std::launch::async, &hwmonio::HwmonIOInterface::read,
++                        _ioAccess, _sensor.first, _sensor.second,
++                        hwmon::entry::cinput, std::get<size_t>(retryIO),
++                        std::get<std::chrono::milliseconds>(retryIO));
++                    valueIsValid = true;
++                }
++                else
++                {
++                    // If we already have the async thread in the timedoutMap,
++                    // it means this sensor has already timed out in the
++                    // previous reads. No need to wait on subsequent reads
++                    asyncReadTimeout = std::chrono::seconds(0);
++                    asyncThread = std::move(asyncIter->second);
++                }
++
++                std::future_status status =
++                    asyncThread.wait_for(asyncReadTimeout);
++                switch (status)
++                {
++                    case std::future_status::ready:
++                        // Read has finished
++                        if (valueIsValid)
++                        {
++                            val = asyncThread.get();
++                            break;
++                            // Good sensor reads should skip the code below
++                        }
++                        // Async read thread has completed, erase from
++                        // timedoutMap to allow retry then throw
++                        timedoutMap.erase(_sensor);
++                        throw AsyncSensorReadTimeOut();
++                    default:
++                        // Read timed out so add the thread to the timedoutMap
++                        // (if the entry already exists, operator[] updates it)
++                        timedoutMap[_sensor] = std::move(asyncThread);
++                        throw AsyncSensorReadTimeOut();
++                }
++            }
++            else
++            {
++                // Retry for up to a second if device is busy
++                // or has a transient error.
++                val = _ioAccess->read(
++                    _sensor.first, _sensor.second, hwmon::entry::cinput,
++                    std::get<size_t>(retryIO),
++                    std::get<std::chrono::milliseconds>(retryIO));
++            }
+             val = adjustValue(val);
+         }
+ #ifdef UPDATE_FUNCTIONAL_ON_FAIL
+diff --git a/sensor.hpp b/sensor.hpp
+index 369a252..d1d6730 100644
+--- a/sensor.hpp
++++ b/sensor.hpp
+@@ -4,6 +4,8 @@
+ #include "sensorset.hpp"
+ #include "types.hpp"
+ 
++#include <cerrno>
++#include <future>
+ #include <gpioplus/handle.hpp>
+ #include <memory>
+ #include <optional>
+@@ -20,6 +22,17 @@ struct valueAdjust
+     std::unordered_set<int> rmRCs;
+ };
+ 
++/** @brief Custom exception for async sensor reading timeout
++ */
++struct AsyncSensorReadTimeOut : public std::system_error
++{
++    AsyncSensorReadTimeOut() :
++        system_error(std::error_code(ETIMEDOUT, std::system_category()),
++                     "Async sensor read timed out")
++    {
++    }
++};
++
+ /** @class Sensor
+  *  @brief Sensor object based on a SensorSet container's key type
+  *  @details Sensor object to create and modify an associated device's sensor
+@@ -87,10 +100,14 @@ class Sensor
+      *                      (number of and delay between)
+      * @param[in] info - Sensor object information
+      *
++     * @param[in] timedoutMap - Map to track timed out threads
++     *
+      * @return - Shared pointer to the value object
+      */
+-    std::shared_ptr<ValueObject> addValue(const RetryIO& retryIO,
+-                                          ObjectInfo& info);
++    std::shared_ptr<ValueObject>
++        addValue(const RetryIO& retryIO, ObjectInfo& info,
++                 std::map<SensorSet::key_type, std::future<SensorValueType>>&
++                     timedoutMap);
+ 
+     /**
+      * @brief Add status interface and functional property for sensor
+-- 
+2.7.4
+
diff --git a/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@82000/sbtsi@4c.conf b/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@82000/sbtsi@4c.conf
new file mode 100644
index 0000000..de988aa
--- /dev/null
+++ b/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@82000/sbtsi@4c.conf
@@ -0,0 +1,9 @@
+LABEL_temp1 = "cputemp"
+CRITHI_temp1 = "85000"
+CRITLO_temp1 = "5000"
+WARNHI_temp1 = "85000"
+WARNLO_temp1 = "5000"
+MINVALUE_temp1 = "-128"
+MAXVALUE_temp1 = "127"
+ASYNC_READ_TIMEOUT_temp1 = "500"
+PWRONMON_temp1 = "ON"
diff --git a/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@85000/i2c-switch@71/i2c@0/max31725@54.conf b/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@85000/i2c-switch@71/i2c@0/max31725@54.conf
new file mode 100644
index 0000000..839a7c6
--- /dev/null
+++ b/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@85000/i2c-switch@71/i2c@0/max31725@54.conf
@@ -0,0 +1,8 @@
+LABEL_temp1 = "i2cool_0"
+CRITHI_temp1 = "35000"
+CRITLO_temp1 = "0"
+WARNHI_temp1 = "35000"
+WARNLO_temp1 = "0"
+MINVALUE_temp1 = "-128"
+MAXVALUE_temp1 = "127"
+ASYNC_READ_TIMEOUT_temp1 = "500"
diff --git a/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@85000/i2c-switch@71/i2c@1/max31725@55.conf b/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@85000/i2c-switch@71/i2c@1/max31725@55.conf
new file mode 100644
index 0000000..174c62b
--- /dev/null
+++ b/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@85000/i2c-switch@71/i2c@1/max31725@55.conf
@@ -0,0 +1,8 @@
+LABEL_temp1 = "i2cool_1"
+CRITHI_temp1 = "70000"
+CRITLO_temp1 = "0"
+WARNHI_temp1 = "70000"
+WARNLO_temp1 = "0"
+MINVALUE_temp1 = "-128"
+MAXVALUE_temp1 = "127"
+ASYNC_READ_TIMEOUT_temp1 = "500"
diff --git a/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@85000/i2c-switch@71/i2c@2/max31725@5d.conf b/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@85000/i2c-switch@71/i2c@2/max31725@5d.conf
new file mode 100644
index 0000000..3fb0cee
--- /dev/null
+++ b/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@85000/i2c-switch@71/i2c@2/max31725@5d.conf
@@ -0,0 +1,8 @@
+LABEL_temp1 = "i2cool_2"
+CRITHI_temp1 = "70000"
+CRITLO_temp1 = "0"
+WARNHI_temp1 = "70000"
+WARNLO_temp1 = "0"
+MINVALUE_temp1 = "-128"
+MAXVALUE_temp1 = "127"
+ASYNC_READ_TIMEOUT_temp1 = "500"
diff --git a/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@88000/adm1272@10.conf b/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@88000/adm1272@10.conf
new file mode 100644
index 0000000..3a83519
--- /dev/null
+++ b/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@88000/adm1272@10.conf
@@ -0,0 +1,31 @@
+LABEL_in1 = "hotswap_vin"
+CRITHI_in1 = "60000"
+CRITLO_in1 = "40000"
+WARNHI_in1 = "60000"
+WARNLO_in1 = "40000"
+MINVALUE_in1 = "0"
+MAXVALUE_in1 = "66"
+
+LABEL_in2 = "hotswap_vout"
+CRITHI_in2 = "60000"
+CRITLO_in2 = "40000"
+WARNHI_in2 = "60000"
+WARNLO_in2 = "40000"
+MINVALUE_in2 = "0"
+MAXVALUE_in2 = "66"
+
+LABEL_curr1= "hotswap_iout"
+CRITHI_curr1= "40000"
+CRITLO_curr1= "0"
+WARNHI_curr1= "40000"
+WARNLO_curr1= "0"
+MINVALUE_curr1 = "0"
+MAXVALUE_curr1 = "55"
+
+LABEL_power1= "hotswap_pout"
+CRITHI_power1= "1920000000"
+CRITLO_power1= "0"
+WARNHI_power1= "1920000000"
+WARNLO_power1= "0"
+MINVALUE_power1 = "0"
+MAXVALUE_power1 = "2200"
diff --git a/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@89000/i2c-switch@71/i2c@0/vrm@60.conf b/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@89000/i2c-switch@71/i2c@0/vrm@60.conf
new file mode 100644
index 0000000..09cdfaf
--- /dev/null
+++ b/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@89000/i2c-switch@71/i2c@0/vrm@60.conf
@@ -0,0 +1,37 @@
+LABEL_in1 = "vddcr_cpu_in"
+CRITHI_in1 = "12600"
+CRITLO_in1 = "11400"
+WARNHI_in1 = "12600"
+WARNLO_in1 = "11400"
+MINVALUE_in1 = "0"
+MAXVALUE_in1 = "14"
+# READ_VIN is direct value *10
+GAIN_in1 = "10.0"
+PWRONMON_in1 = "ON"
+
+LABEL_in2 = "vddcr_cpu_out"
+CRITHI_in2 = "1300"
+CRITLO_in2 = "400"
+WARNHI_in2 = "1300"
+WARNLO_in2 = "400"
+MINVALUE_in2 = "0"
+MAXVALUE_in2 = "2"
+PWRONMON_in2 = "ON"
+
+LABEL_curr1 = "vddcr_cpu_in"
+CRITHI_curr1 = "16700"
+CRITLO_curr1 = "0"
+WARNHI_curr1 = "16700"
+WARNLO_curr1 = "0"
+MINVALUE_curr1 = "0"
+MAXVALUE_curr1 = "20"
+PWRONMON_curr1 = "ON"
+
+LABEL_curr2 = "vddcr_cpu_out"
+CRITHI_curr2 = "200000"
+CRITLO_curr2 = "0"
+WARNHI_curr2 = "200000"
+WARNLO_curr2 = "0"
+MINVALUE_curr2 = "0"
+MAXVALUE_curr2 = "250"
+PWRONMON_curr2 = "ON"
diff --git a/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@89000/i2c-switch@71/i2c@1/vrm@61.conf b/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@89000/i2c-switch@71/i2c@1/vrm@61.conf
new file mode 100644
index 0000000..c1c3d3e
--- /dev/null
+++ b/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@89000/i2c-switch@71/i2c@1/vrm@61.conf
@@ -0,0 +1,37 @@
+LABEL_in1 = "vddcr_soc_in"
+CRITHI_in1 = "12600"
+CRITLO_in1 = "11400"
+WARNHI_in1 = "12600"
+WARNLO_in1 = "11400"
+MINVALUE_in1 = "0"
+MAXVALUE_in1 = "14"
+# READ_VIN is direct value *10
+GAIN_in1 = "10.0"
+PWRONMON_in1 = "ON"
+
+LABEL_in2 = "vddcr_soc_out"
+CRITHI_in2 = "1300"
+CRITLO_in2 = "500"
+WARNHI_in2 = "1300"
+WARNLO_in2 = "500"
+MINVALUE_in2 = "0"
+MAXVALUE_in2 = "2"
+PWRONMON_in2 = "ON"
+
+LABEL_curr1 = "vddcr_soc_in"
+CRITHI_curr1 = "6700"
+CRITLO_curr1 = "0"
+WARNHI_curr1 = "6700"
+WARNLO_curr1 = "0"
+MINVALUE_curr1 = "0"
+MAXVALUE_curr1 = "9"
+PWRONMON_curr1 = "ON"
+
+LABEL_curr2 = "vddcr_soc_out"
+CRITHI_curr2 = "80000"
+CRITLO_curr2 = "0"
+WARNHI_curr2 = "80000"
+WARNLO_curr2 = "0"
+MINVALUE_curr2 = "0"
+MAXVALUE_curr2 = "88"
+PWRONMON_curr2 = "ON"
diff --git a/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@89000/i2c-switch@71/i2c@2/vrm@63.conf b/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@89000/i2c-switch@71/i2c@2/vrm@63.conf
new file mode 100644
index 0000000..757e699
--- /dev/null
+++ b/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@89000/i2c-switch@71/i2c@2/vrm@63.conf
@@ -0,0 +1,37 @@
+LABEL_in1 = "vddq_efgh_in"
+CRITHI_in1 = "12600"
+CRITLO_in1 = "11400"
+WARNHI_in1 = "12600"
+WARNLO_in1 = "11400"
+MINVALUE_in1 = "0"
+MAXVALUE_in1 = "14"
+# READ_VIN is direct value *10
+GAIN_in1 = "10.0"
+PWRONMON_in1 = "ON"
+
+LABEL_in2 = "vddq_efgh_out"
+CRITHI_in2 = "1320"
+CRITLO_in2 = "800"
+WARNHI_in2 = "1320"
+WARNLO_in2 = "800"
+MINVALUE_in2 = "0"
+MAXVALUE_in2 = "2"
+PWRONMON_in2 = "ON"
+
+LABEL_curr1 = "vddq_efgh_in"
+CRITHI_curr1 = "8400"
+CRITLO_curr1 = "0"
+WARNHI_curr1 = "8400"
+WARNLO_curr1 = "0"
+MINVALUE_curr1 = "0"
+MAXVALUE_curr1 = "9"
+PWRONMON_curr1 = "ON"
+
+LABEL_curr2 = "vddq_efgh_out"
+CRITHI_curr2 = "84000"
+CRITLO_curr2 = "0"
+WARNHI_curr2 = "84000"
+WARNLO_curr2 = "0"
+MINVALUE_curr2 = "0"
+MAXVALUE_curr2 = "88"
+PWRONMON_curr2 = "ON"
diff --git a/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@89000/i2c-switch@71/i2c@3/vrm@45.conf b/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@89000/i2c-switch@71/i2c@3/vrm@45.conf
new file mode 100644
index 0000000..df12a20
--- /dev/null
+++ b/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@89000/i2c-switch@71/i2c@3/vrm@45.conf
@@ -0,0 +1,37 @@
+LABEL_in1 = "vddq_abcd_in"
+CRITHI_in1 = "12600"
+CRITLO_in1 = "11400"
+WARNHI_in1 = "12600"
+WARNLO_in1 = "11400"
+MINVALUE_in1 = "0"
+MAXVALUE_in1 = "14"
+# READ_VIN is direct value *10
+GAIN_in1 = "10.0"
+PWRONMON_in1 = "ON"
+
+LABEL_in2 = "vddq_abcd_out"
+CRITHI_in2 = "1320"
+CRITLO_in2 = "800"
+WARNHI_in2 = "1320"
+WARNLO_in2 = "800"
+MINVALUE_in2 = "0"
+MAXVALUE_in2 = "2"
+PWRONMON_in2 = "ON"
+
+LABEL_curr1 = "vddq_abcd_in"
+CRITHI_curr1 = "8400"
+CRITLO_curr1 = "0"
+WARNHI_curr1 = "8400"
+WARNLO_curr1 = "0"
+MINVALUE_curr1 = "0"
+MAXVALUE_curr1 = "9"
+PWRONMON_curr1 = "ON"
+
+LABEL_curr2 = "vddq_abcd_out"
+CRITHI_curr2 = "84000"
+CRITLO_curr2 = "0"
+WARNHI_curr2 = "84000"
+WARNLO_curr2 = "0"
+MINVALUE_curr2 = "0"
+MAXVALUE_curr2 = "88"
+PWRONMON_curr2 = "ON"
diff --git a/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@8c000/max34451@4e.conf b/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@8c000/max34451@4e.conf
new file mode 100644
index 0000000..eda5341
--- /dev/null
+++ b/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@8c000/max34451@4e.conf
@@ -0,0 +1,116 @@
+LABEL_in1 = "p1v8_stby"
+CRITHI_in1 = "1890"
+CRITLO_in1 = "1710"
+WARNHI_in1 = "1890"
+WARNLO_in1 = "1710"
+MINVALUE_in1 = "0"
+MAXVALUE_in1 = "2"
+PWRONMON_in1 = "ON"
+
+LABEL_in2 = "vddcr_soc_stby"
+CRITHI_in2 = "945"
+CRITLO_in2 = "855"
+WARNHI_in2 = "945"
+WARNLO_in2 = "855"
+MINVALUE_in2 = "0"
+MAXVALUE_in2 = "1"
+PWRONMON_in2 = "ON"
+
+LABEL_in3 = "p2v5_stby"
+CRITHI_in3 = "2625"
+CRITLO_in3 = "2375"
+WARNHI_in3 = "2625"
+WARNLO_in3 = "2375"
+MINVALUE_in3 = "0"
+MAXVALUE_in3 = "3"
+PWRONMON_in3 = "ON"
+
+LABEL_in4 = "p1v2_stby"
+CRITHI_in4 = "1260"
+CRITLO_in4 = "1140"
+WARNHI_in4 = "1260"
+WARNLO_in4 = "1140"
+MINVALUE_in4 = "0"
+MAXVALUE_in4 = "2"
+PWRONMON_in4 = "ON"
+
+LABEL_in5 = "p1v175_stby"
+CRITHI_in5 = "1234"
+CRITLO_in5 = "1116"
+WARNHI_in5 = "1234"
+WARNLO_in5 = "1116"
+MINVALUE_in5 = "0"
+MAXVALUE_in5 = "2"
+PWRONMON_in5 = "ON"
+
+LABEL_in6 = "p1v8"
+CRITHI_in6 = "1890"
+CRITLO_in6 = "1710"
+WARNHI_in6 = "1890"
+WARNLO_in6 = "1710"
+MINVALUE_in6 = "0"
+MAXVALUE_in6 = "2"
+PWRONMON_in6 = "ON"
+
+LABEL_in7 = "p3v3"
+CRITHI_in7 = "3465"
+CRITLO_in7 = "3135"
+WARNHI_in7 = "3465"
+WARNLO_in7 = "3135"
+MINVALUE_in7 = "0"
+MAXVALUE_in7 = "4"
+PWRONMON_in7 = "ON"
+
+LABEL_in8 = "pwrgd_pvpp"
+CRITHI_in8 = "3600"
+CRITLO_in8 = "2600"
+WARNHI_in8 = "3600"
+WARNLO_in8 = "2600"
+MINVALUE_in8 = "0"
+MAXVALUE_in8 = "4"
+PWRONMON_in8 = "ON"
+
+LABEL_in9 = "pwrgd_pvddio"
+CRITHI_in9 = "3600"
+CRITLO_in9 = "2600"
+WARNHI_in9 = "3600"
+WARNLO_in9 = "2600"
+MINVALUE_in9 = "0"
+MAXVALUE_in9 = "4"
+PWRONMON_in9 = "ON"
+
+LABEL_in10 = "pwrgd_cpuvr"
+CRITHI_in10 = "3600"
+CRITLO_in10 = "2600"
+WARNHI_in10 = "3600"
+WARNLO_in10 = "2600"
+MINVALUE_in10 = "0"
+MAXVALUE_in10 = "4"
+PWRONMON_in10 = "ON"
+
+LABEL_in11 = "p3v3_stby"
+CRITHI_in11 = "3465"
+CRITLO_in11 = "3135"
+WARNHI_in11 = "3465"
+WARNLO_in11 = "3135"
+MINVALUE_in11 = "0"
+MAXVALUE_in11 = "4"
+PWRONMON_in11 = "ON"
+
+LABEL_in12 = "p5v_stby"
+CRITHI_in12 = "5250"
+CRITLO_in12 = "4750"
+WARNHI_in12 = "5250"
+WARNLO_in12 = "4750"
+MINVALUE_in12 = "0"
+MAXVALUE_in12 = "6"
+PWRONMON_in12 = "ON"
+
+LABEL_temp1 = "powerseq_temp"
+CRITHI_temp1 = "85000"
+CRITLO_temp1 = "5000"
+WARNHI_temp1 = "85000"
+WARNLO_temp1 = "5000"
+MINVALUE_temp1 = "-128"
+MAXVALUE_temp1 = "127"
+ASYNC_READ_TIMEOUT_temp1 = "500"
diff --git a/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@8c000/vrm@5d.conf b/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@8c000/vrm@5d.conf
new file mode 100644
index 0000000..9ccd602
--- /dev/null
+++ b/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@8c000/vrm@5d.conf
@@ -0,0 +1,37 @@
+LABEL_in1 = "p12v_2_in"
+CRITHI_in1 = "60000"
+CRITLO_in1 = "40000"
+WARNHI_in1 = "60000"
+WARNLO_in1 = "40000"
+MINVALUE_in1 = "0"
+MAXVALUE_in1 = "65"
+# READ_VIN is direct value *10
+GAIN_in1 = "10.0"
+PWRONMON_in1 = "ON"
+
+LABEL_in2 = "p12v_2_out"
+CRITHI_in2 = "12600"
+CRITLO_in2 = "11400"
+WARNHI_in2 = "12600"
+WARNLO_in2 = "11400"
+MINVALUE_in2 = "0"
+MAXVALUE_in2 = "14"
+PWRONMON_in2 = "ON"
+
+LABEL_curr1 = "p12v_2_in"
+CRITHI_curr1 = "22000"
+CRITLO_curr1 = "0"
+WARNHI_curr1 = "22000"
+WARNLO_curr1 = "0"
+MINVALUE_curr1 = "0"
+MAXVALUE_curr1 = "35"
+PWRONMON_curr1 = "ON"
+
+LABEL_curr2 = "p12v_2_out"
+CRITHI_curr2 = "88000"
+CRITLO_curr2 = "0"
+WARNHI_curr2 = "88000"
+WARNLO_curr2 = "0"
+MINVALUE_curr2 = "0"
+MAXVALUE_curr2 = "150"
+PWRONMON_curr2 = "ON"
diff --git a/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@8c000/vrm@5e.conf b/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@8c000/vrm@5e.conf
new file mode 100644
index 0000000..aac47ac
--- /dev/null
+++ b/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c@8c000/vrm@5e.conf
@@ -0,0 +1,37 @@
+LABEL_in1 = "p12v_1_in"
+CRITHI_in1 = "60000"
+CRITLO_in1 = "40000"
+WARNHI_in1 = "60000"
+WARNLO_in1 = "40000"
+MINVALUE_in1 = "0"
+MAXVALUE_in1 = "65"
+# READ_VIN is direct value *10
+GAIN_in1 = "10.0"
+PWRONMON_in1 = "ON"
+
+LABEL_in2 = "p12v_1_out"
+CRITHI_in2 = "12600"
+CRITLO_in2 = "11400"
+WARNHI_in2 = "12600"
+WARNLO_in2 = "11400"
+MINVALUE_in2 = "0"
+MAXVALUE_in2 = "14"
+PWRONMON_in2 = "ON"
+
+LABEL_curr1 = "p12v_1_in"
+CRITHI_curr1 = "30000"
+CRITLO_curr1 = "0"
+WARNHI_curr1 = "30000"
+WARNLO_curr1 = "0"
+MINVALUE_curr1 = "0"
+MAXVALUE_curr1 = "35"
+PWRONMON_curr1 = "ON"
+
+LABEL_curr2 = "p12v_1_out"
+CRITHI_curr2 = "10000"
+CRITLO_curr2 = "0"
+WARNHI_curr2 = "10000"
+WARNLO_curr2 = "0"
+MINVALUE_curr2 = "0"
+MAXVALUE_curr2 = "150"
+PWRONMON_curr2 = "ON"
diff --git a/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/pwm-fan-controller@103000.conf b/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/pwm-fan-controller@103000.conf
new file mode 100644
index 0000000..c7312e6
--- /dev/null
+++ b/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/pwm-fan-controller@103000.conf
@@ -0,0 +1,44 @@
+LABEL_fan1= "fan0"
+WARNHI_fan1= "19800"
+WARNLO_fan1= "600"
+CRITHI_fan1= "19800"
+CRITLO_fan1= "600"
+MINVALUE_fan1 = "0"
+MAXVALUE_fan1 = "20775"
+PWM_TARGET_fan1 = 1
+
+LABEL_fan2= "fan1"
+WARNHI_fan2= "19800"
+WARNLO_fan2= "600"
+CRITHI_fan2= "19800"
+CRITLO_fan2= "600"
+MINVALUE_fan2 = "0"
+MAXVALUE_fan2 = "20775"
+PWM_TARGET_fan2 = 2
+
+LABEL_fan3= "fan2"
+WARNHI_fan3= "19800"
+WARNLO_fan3= "600"
+CRITHI_fan3= "19800"
+CRITLO_fan3= "600"
+MINVALUE_fan3 = "0"
+MAXVALUE_fan3 = "20775"
+PWM_TARGET_fan3 = 3
+
+LABEL_fan4= "fan3"
+WARNHI_fan4= "19800"
+WARNLO_fan4= "600"
+CRITHI_fan4= "19800"
+CRITLO_fan4= "600"
+MINVALUE_fan4 = "0"
+MAXVALUE_fan4 = "20775"
+PWM_TARGET_fan4 = 4
+
+LABEL_fan5= "fan4"
+WARNHI_fan5= "19800"
+WARNLO_fan5= "600"
+CRITHI_fan5= "19800"
+CRITLO_fan5= "600"
+MINVALUE_fan5 = "0"
+MAXVALUE_fan5 = "20775"
+PWM_TARGET_fan5 = 5
diff --git a/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/iio-hwmon-battery.conf b/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/iio-hwmon-battery.conf
new file mode 100644
index 0000000..5b2833a
--- /dev/null
+++ b/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/iio-hwmon-battery.conf
@@ -0,0 +1,15 @@
+LABEL_in1 = "p3v_bat_adc"
+CRITLO_in1 = "2690"
+CRITHI_in1 = "3480"
+WARNHI_in1 = "3480"
+WARNLO_in1 = "2690"
+MINVALUE_in1 = "0"
+MAXVALUE_in1 = "4"
+
+# The battery read is controlled by GPIO18
+GPIOCHIP_in1=0
+GPIO_in1=18
+GAIN_in1 = "3.35"
+
+# Sleep 24hrs per poll. Number is in microseconds.
+INTERVAL=86400000000
diff --git a/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon_%.bbappend b/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon_%.bbappend
new file mode 100644
index 0000000..c779b85
--- /dev/null
+++ b/meta-quanta/meta-gbs/recipes-phosphor/sensors/phosphor-hwmon_%.bbappend
@@ -0,0 +1,35 @@
+FILESEXTRAPATHS_prepend_gbs := "${THISDIR}/${PN}:"
+
+SRC_URI_append_gbs = " file://0001-lev-add-poweron-monitor-feature.patch \
+                       file://0002-lev-add-sensors-slow-readings.patch \
+                     "
+
+GBS_NAMES = " \
+        i2c@82000/sbtsi@4c \
+        i2c@85000/i2c-switch@71/i2c@0/max31725@54 \
+        i2c@85000/i2c-switch@71/i2c@1/max31725@55 \
+        i2c@85000/i2c-switch@71/i2c@2/max31725@5d \
+        i2c@88000/adm1272@10 \
+        i2c@89000/i2c-switch@71/i2c@0/vrm@60 \
+        i2c@89000/i2c-switch@71/i2c@1/vrm@61 \
+        i2c@89000/i2c-switch@71/i2c@2/vrm@63 \
+        i2c@89000/i2c-switch@71/i2c@3/vrm@45 \
+        i2c@8c000/max34451@4e \
+        i2c@8c000/vrm@5d \
+        i2c@8c000/vrm@5e \
+        "
+GBS_ITEMSFMT = "ahb/apb/{0}.conf"
+
+GBS_ITEMS += "${@compose_list(d, 'GBS_ITEMSFMT', 'GBS_NAMES')}"
+GBS_ITEMS_append_gbs += " iio-hwmon-battery.conf"
+
+ENVS = "obmc/hwmon/{0}"
+SYSTEMD_ENVIRONMENT_FILE_${PN}_append_gbs = " ${@compose_list(d, 'ENVS', 'GBS_ITEMS')}"
+
+# Fan sensors
+FITEMS = "pwm-fan-controller@103000.conf"
+FENVS = "obmc/hwmon/ahb/apb/{0}"
+SYSTEMD_ENVIRONMENT_FILE_${PN}_append_gbs = " ${@compose_list(d, 'FENVS', 'FITEMS')}"
+
+
+EXTRA_OECONF_append_gbs = " --enable-update-functional-on-fail"