1 /** 2 * Copyright © 2021 IBM Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #pragma once 17 18 #include "sensors.hpp" 19 20 #include <sdbusplus/bus.hpp> 21 #include <sdbusplus/server/object.hpp> 22 #include <xyz/openbmc_project/Association/Definitions/server.hpp> 23 #include <xyz/openbmc_project/Sensor/Value/server.hpp> 24 #include <xyz/openbmc_project/State/Decorator/Availability/server.hpp> 25 #include <xyz/openbmc_project/State/Decorator/OperationalStatus/server.hpp> 26 27 #include <memory> 28 #include <string> 29 #include <tuple> 30 #include <vector> 31 32 namespace phosphor::power::regulators 33 { 34 35 /** 36 * Define simple name for the generated C++ class that implements the 37 * xyz.openbmc_project.Sensor.Value interface. 38 */ 39 using ValueInterface = sdbusplus::xyz::openbmc_project::Sensor::server::Value; 40 41 /** 42 * Define simple name for the generated C++ class that implements the 43 * xyz.openbmc_project.State.Decorator.OperationalStatus interface. 44 */ 45 using OperationalStatusInterface = sdbusplus::xyz::openbmc_project::State:: 46 Decorator::server::OperationalStatus; 47 48 /** 49 * Define simple name for the generated C++ class that implements the 50 * xyz.openbmc_project.State.Decorator.Availability interface. 51 */ 52 using AvailabilityInterface = 53 sdbusplus::xyz::openbmc_project::State::Decorator::server::Availability; 54 55 /** 56 * Define simple name for the generated C++ class that implements the 57 * xyz.openbmc_project.Association.Definitions interface. 58 */ 59 using AssociationDefinitionsInterface = 60 sdbusplus::xyz::openbmc_project::Association::server::Definitions; 61 62 /** 63 * Define simple name for the sdbusplus object_t class that implements all 64 * the necessary D-Bus interfaces via templates/multiple inheritance. 65 */ 66 using DBusSensorObject = 67 sdbusplus::server::object_t<ValueInterface, OperationalStatusInterface, 68 AvailabilityInterface, 69 AssociationDefinitionsInterface>; 70 71 /** 72 * Define simple name for the generated C++ enum that implements the 73 * valid sensor Unit values on D-Bus. 74 */ 75 using Unit = sdbusplus::xyz::openbmc_project::Sensor::server::Value::Unit; 76 77 /** 78 * Define simple name for the tuple used to create D-Bus associations. 79 */ 80 using AssocationTuple = std::tuple<std::string, std::string, std::string>; 81 82 /** 83 * Root object path for sensors. 84 */ 85 constexpr const char* sensorsObjectPath = "/xyz/openbmc_project/sensors"; 86 87 /** 88 * @class DBusSensor 89 * 90 * This class represents a voltage regulator sensor on D-Bus. 91 * 92 * Each voltage rail in the system may provide multiple types of sensor data, 93 * such as temperature, output voltage, and output current. A DBusSensor tracks 94 * one of these data types for a voltage rail. 95 */ 96 class DBusSensor 97 { 98 public: 99 // Specify which compiler-generated methods we want 100 DBusSensor() = delete; 101 DBusSensor(const DBusSensor&) = delete; 102 DBusSensor(DBusSensor&&) = delete; 103 DBusSensor& operator=(const DBusSensor&) = delete; 104 DBusSensor& operator=(DBusSensor&&) = delete; 105 virtual ~DBusSensor() = default; 106 107 /** 108 * Constructor. 109 * 110 * @param bus D-Bus bus object 111 * @param name sensor name 112 * @param type sensor type 113 * @param value sensor value 114 * @param rail voltage rail associated with this sensor 115 * @param deviceInventoryPath D-Bus inventory path of the voltage regulator 116 * device that produces the rail 117 * @param chassisInventoryPath D-Bus inventory path of the chassis that 118 * contains the voltage regulator device 119 */ 120 explicit DBusSensor(sdbusplus::bus::bus& bus, const std::string& name, 121 SensorType type, double value, const std::string& rail, 122 const std::string& deviceInventoryPath, 123 const std::string& chassisInventoryPath); 124 125 /** 126 * Disable this sensor. 127 * 128 * Updates the sensor properties on D-Bus to indicate it is no longer 129 * receiving value updates. 130 * 131 * This method is normally called when the system is being powered off. 132 * Sensors are not read when the system is powered off. 133 */ 134 void disable(); 135 136 /** 137 * Return the sensor name. 138 * 139 * @return sensor name 140 */ 141 const std::string& getName() const 142 { 143 return name; 144 } 145 146 /** 147 * Return the voltage regulator rail associated with this sensor. 148 * 149 * @return rail 150 */ 151 const std::string& getRail() const 152 { 153 return rail; 154 } 155 156 /** 157 * Return the sensor type. 158 * 159 * @return sensor type 160 */ 161 SensorType getType() const 162 { 163 return type; 164 } 165 166 /** 167 * Set this sensor to the error state. 168 * 169 * Updates the sensor properties on D-Bus to indicate an error occurred and 170 * the sensor value could not be read. 171 */ 172 void setToErrorState(); 173 174 /** 175 * Set the value of this sensor. 176 * 177 * Do not specify the value NaN. This special value is used internally to 178 * indicate the sensor has been disabled or is in the error state. Call the 179 * disable() or setToErrorState() method instead so that all affected D-Bus 180 * interfaces are updated correctly. 181 * 182 * @param value new sensor value 183 */ 184 void setValue(double value); 185 186 private: 187 /** 188 * Sensor value update policy. 189 * 190 * Determines whether a new sensor value should replace the current value on 191 * D-Bus. 192 */ 193 enum class ValueUpdatePolicy : unsigned char 194 { 195 /** 196 * Hysteresis value update policy. 197 * 198 * The sensor value will only be updated if the new value differs from 199 * the current value by at least the hysteresis amount. This avoids 200 * constant D-Bus traffic due to insignificant value changes. 201 */ 202 hysteresis, 203 204 /** 205 * Highest value update policy. 206 * 207 * The sensor value will only be updated if the new value is higher than 208 * the current value. 209 * 210 * Some sensors contain the highest value observed by the voltage 211 * regulator, such as the highest temperature or highest output voltage. 212 * The regulator internally calculates this value since it can poll the 213 * value very quickly and can catch transient events. 214 * 215 * When the sensor is read from the regulator, the regulator will often 216 * clear its internal value. It will begin calculating a new highest 217 * value. For this reason, the D-Bus sensor value is set to the highest 218 * value that has been read across all monitoring cycles. 219 * 220 * The D-Bus sensor value is cleared when the sensor is disabled. This 221 * normally occurs when the system is powered off. Thus, the D-Bus 222 * sensor value is normally the highest value read since the system was 223 * powered on. 224 */ 225 highest, 226 227 /** 228 * Lowest value update policy. 229 * 230 * The sensor value will only be updated if the new value is lower than 231 * the current value. 232 * 233 * Some sensors contain the lowest value observed by the voltage 234 * regulator, such as the lowest output current or lowest output 235 * voltage. The regulator internally calculates this value since it can 236 * poll the value very quickly and can catch transient events. 237 * 238 * When the sensor is read from the regulator, the regulator will often 239 * clear its internal value. It will begin calculating a new lowest 240 * value. For this reason, the D-Bus sensor value is set to the lowest 241 * value that has been read across all monitoring cycles. 242 * 243 * The D-Bus sensor value is cleared when the sensor is disabled. This 244 * normally occurs when the system is powered off. Thus, the D-Bus 245 * sensor value is normally the lowest value read since the system was 246 * powered on. 247 */ 248 lowest 249 }; 250 251 /** 252 * Get the D-Bus associations to create for this sensor. 253 * 254 * @param deviceInventoryPath D-Bus inventory path of the voltage regulator 255 * device that produces the rail 256 * @param chassisInventoryPath D-Bus inventory path of the chassis that 257 * contains the voltage regulator device 258 */ 259 std::vector<AssocationTuple> 260 getAssociations(const std::string& deviceInventoryPath, 261 const std::string& chassisInventoryPath); 262 263 /** 264 * Get sensor properties that are based on the sensor type. 265 * 266 * The properties are returned in output parameters. 267 * 268 * Also initializes some data members whose value is based on the sensor 269 * type. 270 * 271 * @param objectPath returns the object path of this sensor 272 * @param unit returns the D-Bus unit for the sensor value 273 * @param minValue returns the minimum sensor value 274 * @param maxValue returns the maximum sensor value 275 */ 276 void getTypeBasedProperties(std::string& objectPath, Unit& unit, 277 double& minValue, double& maxValue); 278 279 /** 280 * Set the sensor value on D-Bus to NaN. 281 */ 282 void setValueToNaN(); 283 284 /** 285 * Returns whether to update the sensor value on D-Bus with the specified 286 * new value. 287 * 288 * @param value new sensor value 289 * @return true if value should be updated on D-Bus, false otherwise 290 */ 291 bool shouldUpdateValue(double value); 292 293 /** 294 * D-Bus bus object. 295 */ 296 sdbusplus::bus::bus& bus; 297 298 /** 299 * Sensor name. 300 */ 301 std::string name{}; 302 303 /** 304 * Sensor type. 305 */ 306 SensorType type; 307 308 /** 309 * Voltage regulator rail associated with this sensor. 310 */ 311 std::string rail{}; 312 313 /** 314 * Sensor value update policy. 315 */ 316 ValueUpdatePolicy updatePolicy{ValueUpdatePolicy::hysteresis}; 317 318 /** 319 * Hysteresis value. 320 * 321 * Only used when updatePolicy is hysteresis. 322 */ 323 double hysteresis{0.0}; 324 325 /** 326 * sdbusplus object_t class that implements all the necessary D-Bus 327 * interfaces via templates and multiple inheritance. 328 */ 329 std::unique_ptr<DBusSensorObject> dbusObject{}; 330 }; 331 332 } // namespace phosphor::power::regulators 333