blob: 7d2e4c9ce49e1263a2938fa6dda38e5934f653f1 [file] [log] [blame]
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001#include "../power_supply.hpp"
2#include "mock.hpp"
3
4#include <xyz/openbmc_project/Common/Device/error.hpp>
5#include <xyz/openbmc_project/Common/error.hpp>
6
7#include <gmock/gmock.h>
8#include <gtest/gtest.h>
9
10using namespace phosphor::power::psu;
11using namespace phosphor::pmbus;
12
13using ::testing::_;
Brandon Wyman59a35792020-06-04 12:37:40 -050014using ::testing::Args;
Brandon Wyman3f1242f2020-01-28 13:11:25 -060015using ::testing::Assign;
16using ::testing::DoAll;
Brandon Wyman59a35792020-06-04 12:37:40 -050017using ::testing::ElementsAre;
Matt Spinler592bd272023-08-30 11:00:01 -050018using ::testing::IsNan;
Brandon Wyman59a35792020-06-04 12:37:40 -050019using ::testing::NotNull;
Brandon Wyman3f1242f2020-01-28 13:11:25 -060020using ::testing::Return;
21using ::testing::StrEq;
22
23static auto PSUInventoryPath = "/xyz/bmc/inv/sys/chassis/board/powersupply0";
B. J. Wyman681b2a32021-04-20 22:31:22 +000024static auto PSUGPIOLineName = "presence-ps0";
George Liu9464c422023-02-27 14:30:27 +080025static auto isPowerOn = []() { return true; };
Brandon Wyman3f1242f2020-01-28 13:11:25 -060026
Brandon Wymanb654c612021-11-05 23:24:51 +000027struct PMBusExpectations
28{
29 uint16_t statusWordValue{0x0000};
30 uint8_t statusInputValue{0x00};
31 uint8_t statusMFRValue{0x00};
32 uint8_t statusCMLValue{0x00};
33 uint8_t statusVOUTValue{0x00};
Brandon Wymanb10b3be2021-11-09 22:12:15 +000034 uint8_t statusIOUTValue{0x00};
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +000035 uint8_t statusFans12Value{0x00};
Brandon Wyman96893a42021-11-05 19:56:57 +000036 uint8_t statusTempValue{0x00};
Brandon Wymanb654c612021-11-05 23:24:51 +000037};
38
Brandon Wyman8da35c52021-10-28 22:45:08 +000039// Helper function to setup expectations for various STATUS_* commands
Brandon Wymanb654c612021-11-05 23:24:51 +000040void setPMBusExpectations(MockedPMBus& mockPMBus,
41 const PMBusExpectations& expectations)
Brandon Wyman8da35c52021-10-28 22:45:08 +000042{
Brandon Wyman32453e92021-12-15 19:00:14 +000043 EXPECT_CALL(mockPMBus, read(STATUS_WORD, _, _))
Brandon Wyman8da35c52021-10-28 22:45:08 +000044 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000045 .WillOnce(Return(expectations.statusWordValue));
Brandon Wyman8da35c52021-10-28 22:45:08 +000046
Brandon Wymanb654c612021-11-05 23:24:51 +000047 if (expectations.statusWordValue != 0)
Brandon Wyman8da35c52021-10-28 22:45:08 +000048 {
49 // If fault bits are on in STATUS_WORD, there will also be a read of
Brandon Wyman96893a42021-11-05 19:56:57 +000050 // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT (page 0), and
51 // STATUS_TEMPERATURE.
Brandon Wyman32453e92021-12-15 19:00:14 +000052 EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _, _))
Brandon Wyman8da35c52021-10-28 22:45:08 +000053 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000054 .WillOnce(Return(expectations.statusInputValue));
Brandon Wyman32453e92021-12-15 19:00:14 +000055 EXPECT_CALL(mockPMBus, read(STATUS_MFR, _, _))
Brandon Wyman8da35c52021-10-28 22:45:08 +000056 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000057 .WillOnce(Return(expectations.statusMFRValue));
Brandon Wyman32453e92021-12-15 19:00:14 +000058 EXPECT_CALL(mockPMBus, read(STATUS_CML, _, _))
Brandon Wyman8da35c52021-10-28 22:45:08 +000059 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000060 .WillOnce(Return(expectations.statusCMLValue));
Brandon Wyman6710ba22021-10-27 17:39:31 +000061 // Page will need to be set to 0 to read STATUS_VOUT.
62 EXPECT_CALL(mockPMBus, insertPageNum(STATUS_VOUT, 0))
63 .Times(1)
64 .WillOnce(Return("status0_vout"));
Brandon Wyman32453e92021-12-15 19:00:14 +000065 EXPECT_CALL(mockPMBus, read("status0_vout", _, _))
Brandon Wyman6710ba22021-10-27 17:39:31 +000066 .Times(1)
Brandon Wymanb654c612021-11-05 23:24:51 +000067 .WillOnce(Return(expectations.statusVOUTValue));
Brandon Wyman32453e92021-12-15 19:00:14 +000068 EXPECT_CALL(mockPMBus, read(STATUS_IOUT, _, _))
Brandon Wymanb10b3be2021-11-09 22:12:15 +000069 .Times(1)
70 .WillOnce(Return(expectations.statusIOUTValue));
Brandon Wyman32453e92021-12-15 19:00:14 +000071 EXPECT_CALL(mockPMBus, read(STATUS_FANS_1_2, _, _))
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +000072 .Times(1)
73 .WillOnce(Return(expectations.statusFans12Value));
Brandon Wyman32453e92021-12-15 19:00:14 +000074 EXPECT_CALL(mockPMBus, read(STATUS_TEMPERATURE, _, _))
Brandon Wyman96893a42021-11-05 19:56:57 +000075 .Times(1)
76 .WillOnce(Return(expectations.statusTempValue));
Brandon Wyman8da35c52021-10-28 22:45:08 +000077 }
Matt Spinler592bd272023-08-30 11:00:01 -050078
79 // Default max/peak is 213W
80 ON_CALL(mockPMBus, readBinary(INPUT_HISTORY, Type::HwmonDeviceDebug, 5))
81 .WillByDefault(
82 Return(std::vector<uint8_t>{0x01, 0x5c, 0xf3, 0x54, 0xf3}));
Brandon Wyman8da35c52021-10-28 22:45:08 +000083}
84
Brandon Wyman3f1242f2020-01-28 13:11:25 -060085class PowerSupplyTests : public ::testing::Test
86{
87 public:
88 PowerSupplyTests() :
89 mockedUtil(reinterpret_cast<const MockedUtil&>(getUtils()))
90 {
91 ON_CALL(mockedUtil, getPresence(_, _)).WillByDefault(Return(false));
92 }
93
94 ~PowerSupplyTests() override
95 {
96 freeUtils();
97 }
98
99 const MockedUtil& mockedUtil;
100};
101
Brandon Wyman391a0692021-12-08 23:28:18 +0000102// Helper function for when a power supply goes from missing to present.
103void setMissingToPresentExpects(MockedPMBus& pmbus, const MockedUtil& util)
104{
105 // Call to analyze() will update to present, that will trigger updating
106 // to the correct/latest HWMON directory, in case it changes.
107 EXPECT_CALL(pmbus, findHwmonDir());
108 // Presence change from missing to present will trigger write to
109 // ON_OFF_CONFIG.
110 EXPECT_CALL(pmbus, writeBinary(ON_OFF_CONFIG, _, _));
111 // Presence change from missing to present will trigger in1_input read
112 // in an attempt to get CLEAR_FAULTS called.
Brandon Wyman82affd92021-11-24 19:12:49 +0000113 // This READ_VIN for CLEAR_FAULTS does not check the returned value.
Brandon Wyman3225a452022-03-18 18:51:49 +0000114 EXPECT_CALL(pmbus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
115 // The call for clearing faults includes clearing VIN_UV fault.
116 // The voltage defaults to 0, the first call to analyze should update the
117 // voltage to the current reading, triggering clearing VIN_UV fault(s)
118 // due to below minimum to within range voltage.
119 EXPECT_CALL(pmbus, read("in1_lcrit_alarm", _, _))
Brandon Wyman82affd92021-11-24 19:12:49 +0000120 .Times(2)
Brandon Wyman3225a452022-03-18 18:51:49 +0000121 .WillRepeatedly(Return(1));
Brandon Wyman391a0692021-12-08 23:28:18 +0000122 // Missing/present call will update Presence in inventory.
Brandon Wyman391a0692021-12-08 23:28:18 +0000123 EXPECT_CALL(util, setPresence(_, _, true, _));
124}
125
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600126TEST_F(PowerSupplyTests, Constructor)
127{
128 /**
129 * @param[in] invpath - String for inventory path to use
130 * @param[in] i2cbus - The bus number this power supply is on
131 * @param[in] i2caddr - The 16-bit I2C address of the power supply
B. J. Wyman681b2a32021-04-20 22:31:22 +0000132 * @param[in] gpioLineName - The string for the gpio-line-name to read for
133 * presence.
134 * @param[in] bindDelay - Time in milliseconds to delay binding the device
135 * driver after seeing the presence line go active.
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600136 */
137 auto bus = sdbusplus::bus::new_default();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600138
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500139 // Try where inventory path is empty, constructor should fail.
140 try
141 {
Brandon Wymanc3324422022-03-24 20:30:57 +0000142 auto psu = std::make_unique<PowerSupply>(bus, "", 3, 0x68, "ibm-cffps",
George Liu9464c422023-02-27 14:30:27 +0800143 PSUGPIOLineName, isPowerOn);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500144 ADD_FAILURE() << "Should not have reached this line.";
145 }
146 catch (const std::invalid_argument& e)
147 {
148 EXPECT_STREQ(e.what(), "Invalid empty inventoryPath");
149 }
150 catch (...)
151 {
152 ADD_FAILURE() << "Should not have caught exception.";
153 }
154
B. J. Wyman681b2a32021-04-20 22:31:22 +0000155 // TODO: Try invalid i2c address?
156
157 // Try where gpioLineName is empty.
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500158 try
159 {
Brandon Wymanc3324422022-03-24 20:30:57 +0000160 auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68,
George Liu9464c422023-02-27 14:30:27 +0800161 "ibm-cffps", "", isPowerOn);
B. J. Wyman681b2a32021-04-20 22:31:22 +0000162 ADD_FAILURE()
163 << "Should not have reached this line. Invalid gpioLineName.";
164 }
165 catch (const std::invalid_argument& e)
166 {
167 EXPECT_STREQ(e.what(), "Invalid empty gpioLineName");
168 }
169 catch (...)
170 {
171 ADD_FAILURE() << "Should not have caught exception.";
172 }
173
174 // Test with valid arguments
175 // NOT using D-Bus inventory path for presence.
176 try
177 {
178 auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, 0x68,
George Liu9464c422023-02-27 14:30:27 +0800179 "ibm-cffps", PSUGPIOLineName,
180 isPowerOn);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500181
182 EXPECT_EQ(psu->isPresent(), false);
183 EXPECT_EQ(psu->isFaulted(), false);
Brandon Wyman8da35c52021-10-28 22:45:08 +0000184 EXPECT_EQ(psu->hasCommFault(), false);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500185 EXPECT_EQ(psu->hasInputFault(), false);
186 EXPECT_EQ(psu->hasMFRFault(), false);
187 EXPECT_EQ(psu->hasVINUVFault(), false);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000188 EXPECT_EQ(psu->hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000189 EXPECT_EQ(psu->hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000190 EXPECT_EQ(psu->hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000191 EXPECT_EQ(psu->hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000192 EXPECT_EQ(psu->hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000193 EXPECT_EQ(psu->hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000194 EXPECT_EQ(psu->hasPSKillFault(), false);
195 EXPECT_EQ(psu->hasPS12VcsFault(), false);
196 EXPECT_EQ(psu->hasPSCS12VFault(), false);
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500197 }
198 catch (...)
199 {
200 ADD_FAILURE() << "Should not have caught exception.";
201 }
B. J. Wyman681b2a32021-04-20 22:31:22 +0000202
203 // Test with valid arguments
204 // TODO: Using D-Bus inventory path for presence.
205 try
206 {
207 // FIXME: How do I get that presenceGPIO.read() in the startup to throw
208 // an exception?
209
210 // EXPECT_CALL(mockedUtil, getPresence(_,
211 // StrEq(PSUInventoryPath)))
212 // .Times(1);
213 }
214 catch (...)
215 {
216 ADD_FAILURE() << "Should not have caught exception.";
217 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600218}
219
220TEST_F(PowerSupplyTests, Analyze)
221{
222 auto bus = sdbusplus::bus::new_default();
223
Brandon Wymanb654c612021-11-05 23:24:51 +0000224 {
225 // If I default to reading the GPIO, I will NOT expect a call to
226 // getPresence().
B. J. Wyman681b2a32021-04-20 22:31:22 +0000227
George Liu9464c422023-02-27 14:30:27 +0800228 PowerSupply psu{bus, PSUInventoryPath, 4, 0x69,
229 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Brandon Wymanb654c612021-11-05 23:24:51 +0000230 MockedGPIOInterface* mockPresenceGPIO =
231 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
232 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(0));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000233
Brandon Wymanb654c612021-11-05 23:24:51 +0000234 psu.analyze();
235 // By default, nothing should change.
236 EXPECT_EQ(psu.isPresent(), false);
237 EXPECT_EQ(psu.isFaulted(), false);
238 EXPECT_EQ(psu.hasInputFault(), false);
239 EXPECT_EQ(psu.hasMFRFault(), false);
240 EXPECT_EQ(psu.hasVINUVFault(), false);
241 EXPECT_EQ(psu.hasCommFault(), false);
242 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000243 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000244 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000245 EXPECT_EQ(psu.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000246 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000247 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000248 EXPECT_EQ(psu.hasPSKillFault(), false);
249 EXPECT_EQ(psu.hasPS12VcsFault(), false);
250 EXPECT_EQ(psu.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000251 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600252
George Liu9464c422023-02-27 14:30:27 +0800253 PowerSupply psu2{bus, PSUInventoryPath, 5, 0x6a,
254 "ibm-cffps", PSUGPIOLineName, isPowerOn};
B. J. Wyman681b2a32021-04-20 22:31:22 +0000255 // In order to get the various faults tested, the power supply needs to
256 // be present in order to read from the PMBus device(s).
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000257 MockedGPIOInterface* mockPresenceGPIO2 =
258 static_cast<MockedGPIOInterface*>(psu2.getPresenceGPIO());
Brandon Wyman06ca4592021-12-06 22:52:23 +0000259 // Always return 1 to indicate present.
260 // Each analyze() call will trigger a read of the presence GPIO.
261 EXPECT_CALL(*mockPresenceGPIO2, read()).WillRepeatedly(Return(1));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000262 EXPECT_EQ(psu2.isPresent(), false);
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600263
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600264 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu2.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +0000265 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +0000266 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
267 // for INPUT_HISTORY will check max_power_out to see if it is
268 // old/unsupported power supply. Indicate good value, supported.
269 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -0500270 .WillRepeatedly(Return("2000"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600271
Brandon Wymanb654c612021-11-05 23:24:51 +0000272 // STATUS_WORD INPUT fault.
273 {
274 // Start with STATUS_WORD 0x0000. Powered on, no faults.
275 // Set expectations for a no fault
276 PMBusExpectations expectations;
277 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000278 // After reading STATUS_WORD, etc., there will be a READ_VIN check.
279 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
280 .Times(1)
281 .WillOnce(Return("206000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000282 psu2.analyze();
283 EXPECT_EQ(psu2.isPresent(), true);
284 EXPECT_EQ(psu2.isFaulted(), false);
285 EXPECT_EQ(psu2.hasInputFault(), false);
286 EXPECT_EQ(psu2.hasMFRFault(), false);
287 EXPECT_EQ(psu2.hasVINUVFault(), false);
288 EXPECT_EQ(psu2.hasCommFault(), false);
289 EXPECT_EQ(psu2.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000290 EXPECT_EQ(psu2.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000291 EXPECT_EQ(psu2.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000292 EXPECT_EQ(psu2.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000293 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000294 EXPECT_EQ(psu2.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000295 EXPECT_EQ(psu2.hasPSKillFault(), false);
296 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
297 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000298
299 // Update expectations for STATUS_WORD input fault/warn
Brandon Wyman96893a42021-11-05 19:56:57 +0000300 // STATUS_INPUT fault bits ... on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000301 expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
Brandon Wyman3225a452022-03-18 18:51:49 +0000302 // IIN_OC fault.
303 expectations.statusInputValue = 0x04;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000304
305 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
306 {
307 setPMBusExpectations(mockPMBus, expectations);
308 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
309 .Times(1)
310 .WillOnce(Return("207000"));
311 psu2.analyze();
312 EXPECT_EQ(psu2.isPresent(), true);
313 // Should not be faulted until it reaches the deglitch limit.
314 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
315 EXPECT_EQ(psu2.hasInputFault(), x >= DEGLITCH_LIMIT);
316 EXPECT_EQ(psu2.hasMFRFault(), false);
317 EXPECT_EQ(psu2.hasVINUVFault(), false);
318 EXPECT_EQ(psu2.hasCommFault(), false);
319 EXPECT_EQ(psu2.hasVoutOVFault(), false);
320 EXPECT_EQ(psu2.hasIoutOCFault(), false);
321 EXPECT_EQ(psu2.hasVoutUVFault(), false);
322 EXPECT_EQ(psu2.hasFanFault(), false);
323 EXPECT_EQ(psu2.hasTempFault(), false);
324 EXPECT_EQ(psu2.hasPgoodFault(), false);
325 EXPECT_EQ(psu2.hasPSKillFault(), false);
326 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
327 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
328 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000329 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600330
Brandon Wyman32453e92021-12-15 19:00:14 +0000331 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
Brandon Wyman3225a452022-03-18 18:51:49 +0000332 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
333 .Times(1)
334 .WillOnce(Return(1));
Brandon Wymanc2906f42021-12-21 20:14:56 +0000335 psu2.clearFaults();
336
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600337 // STATUS_WORD INPUT/UV fault.
Brandon Wymanb654c612021-11-05 23:24:51 +0000338 {
339 // First need it to return good status, then the fault
340 PMBusExpectations expectations;
341 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000342 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
343 .Times(1)
344 .WillOnce(Return("208000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000345 psu2.analyze();
Brandon Wymanc2906f42021-12-21 20:14:56 +0000346 EXPECT_EQ(psu2.isFaulted(), false);
347 EXPECT_EQ(psu2.hasInputFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000348 // Now set fault bits in STATUS_WORD
349 expectations.statusWordValue =
350 (status_word::INPUT_FAULT_WARN | status_word::VIN_UV_FAULT);
351 // STATUS_INPUT fault bits ... on.
Brandon Wyman3225a452022-03-18 18:51:49 +0000352 expectations.statusInputValue = 0x18;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000353 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
354 {
355 setPMBusExpectations(mockPMBus, expectations);
356 // Input/UV fault, so voltage should read back low.
357 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
358 .Times(1)
359 .WillOnce(Return("19123"));
360 psu2.analyze();
361 EXPECT_EQ(psu2.isPresent(), true);
362 // Only faulted if hit deglitch limit
363 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
364 EXPECT_EQ(psu2.hasInputFault(), x >= DEGLITCH_LIMIT);
365 EXPECT_EQ(psu2.hasVINUVFault(), x >= DEGLITCH_LIMIT);
366 EXPECT_EQ(psu2.hasMFRFault(), false);
367 EXPECT_EQ(psu2.hasCommFault(), false);
368 EXPECT_EQ(psu2.hasVoutOVFault(), false);
369 EXPECT_EQ(psu2.hasIoutOCFault(), false);
370 EXPECT_EQ(psu2.hasVoutUVFault(), false);
371 EXPECT_EQ(psu2.hasFanFault(), false);
372 EXPECT_EQ(psu2.hasTempFault(), false);
373 EXPECT_EQ(psu2.hasPgoodFault(), false);
374 EXPECT_EQ(psu2.hasPSKillFault(), false);
375 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
376 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
377 }
Brandon Wyman82affd92021-11-24 19:12:49 +0000378 // Turning VIN_UV fault off causes clearing of faults, causing read of
379 // in1_input as an attempt to get CLEAR_FAULTS called.
380 expectations.statusWordValue = 0;
381 setPMBusExpectations(mockPMBus, expectations);
382 // The call to read the voltage
383 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
384 .Times(1)
385 .WillOnce(Return("209000"));
Brandon Wyman3225a452022-03-18 18:51:49 +0000386 // The call to clear VIN_UV/Off fault(s)
387 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
Brandon Wyman32453e92021-12-15 19:00:14 +0000388 .Times(1)
Brandon Wyman3225a452022-03-18 18:51:49 +0000389 .WillOnce(Return(1));
Brandon Wyman82affd92021-11-24 19:12:49 +0000390 psu2.analyze();
391 // Should remain present, no longer be faulted, no input fault, no
392 // VIN_UV fault. Nothing else should change.
393 EXPECT_EQ(psu2.isPresent(), true);
394 EXPECT_EQ(psu2.isFaulted(), false);
395 EXPECT_EQ(psu2.hasInputFault(), false);
396 EXPECT_EQ(psu2.hasVINUVFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000397 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600398
Brandon Wyman32453e92021-12-15 19:00:14 +0000399 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
Brandon Wyman3225a452022-03-18 18:51:49 +0000400 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
401 .Times(1)
402 .WillOnce(Return(1));
Brandon Wymanc2906f42021-12-21 20:14:56 +0000403 psu2.clearFaults();
404
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600405 // STATUS_WORD MFR fault.
Brandon Wymanb654c612021-11-05 23:24:51 +0000406 {
407 // First need it to return good status, then the fault
408 PMBusExpectations expectations;
409 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000410 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
411 .Times(1)
412 .WillOnce(Return("210000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000413 psu2.analyze();
414 // Now STATUS_WORD with MFR fault bit on.
415 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
416 // STATUS_MFR bits on.
417 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000418
419 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
420 {
421 setPMBusExpectations(mockPMBus, expectations);
422 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
423 .Times(1)
424 .WillOnce(Return("211000"));
425 psu2.analyze();
426 EXPECT_EQ(psu2.isPresent(), true);
427 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
428 EXPECT_EQ(psu2.hasInputFault(), false);
429 EXPECT_EQ(psu2.hasMFRFault(), x >= DEGLITCH_LIMIT);
430 EXPECT_EQ(psu2.hasPSKillFault(), x >= DEGLITCH_LIMIT);
431 EXPECT_EQ(psu2.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
432 EXPECT_EQ(psu2.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
433 EXPECT_EQ(psu2.hasVINUVFault(), false);
434 EXPECT_EQ(psu2.hasCommFault(), false);
435 EXPECT_EQ(psu2.hasVoutOVFault(), false);
436 EXPECT_EQ(psu2.hasIoutOCFault(), false);
437 EXPECT_EQ(psu2.hasVoutUVFault(), false);
438 EXPECT_EQ(psu2.hasFanFault(), false);
439 EXPECT_EQ(psu2.hasTempFault(), false);
440 EXPECT_EQ(psu2.hasPgoodFault(), false);
441 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000442 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600443
Brandon Wyman32453e92021-12-15 19:00:14 +0000444 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _)).Times(1).WillOnce(Return(1));
Brandon Wyman3225a452022-03-18 18:51:49 +0000445 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
446 .Times(1)
447 .WillOnce(Return(1));
Brandon Wymanc2906f42021-12-21 20:14:56 +0000448 psu2.clearFaults();
Brandon Wyman3225a452022-03-18 18:51:49 +0000449
Brandon Wyman96893a42021-11-05 19:56:57 +0000450 // Temperature fault.
Brandon Wymanb654c612021-11-05 23:24:51 +0000451 {
452 // First STATUS_WORD with no bits set, then with temperature fault.
453 PMBusExpectations expectations;
454 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000455 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
456 .Times(1)
457 .WillOnce(Return("212000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000458 psu2.analyze();
459 // STATUS_WORD with temperature fault bit on.
460 expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
Brandon Wyman96893a42021-11-05 19:56:57 +0000461 // STATUS_TEMPERATURE with fault bit(s) on.
462 expectations.statusTempValue = 0x10;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000463 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
464 {
465 setPMBusExpectations(mockPMBus, expectations);
466 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
467 .Times(1)
468 .WillOnce(Return("213000"));
469 psu2.analyze();
470 EXPECT_EQ(psu2.isPresent(), true);
471 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
472 EXPECT_EQ(psu2.hasInputFault(), false);
473 EXPECT_EQ(psu2.hasMFRFault(), false);
474 EXPECT_EQ(psu2.hasVINUVFault(), false);
475 EXPECT_EQ(psu2.hasCommFault(), false);
476 EXPECT_EQ(psu2.hasVoutOVFault(), false);
477 EXPECT_EQ(psu2.hasIoutOCFault(), false);
478 EXPECT_EQ(psu2.hasVoutUVFault(), false);
479 EXPECT_EQ(psu2.hasFanFault(), false);
480 EXPECT_EQ(psu2.hasTempFault(), x >= DEGLITCH_LIMIT);
481 EXPECT_EQ(psu2.hasPgoodFault(), false);
482 EXPECT_EQ(psu2.hasPSKillFault(), false);
483 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
484 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
485 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000486 }
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000487
Brandon Wyman6710ba22021-10-27 17:39:31 +0000488 // VOUT_OV_FAULT fault
Brandon Wymanb654c612021-11-05 23:24:51 +0000489 {
490 // First STATUS_WORD with no bits set, then with VOUT/VOUT_OV fault.
491 PMBusExpectations expectations;
492 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000493 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
494 .Times(1)
495 .WillOnce(Return("216000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000496 psu2.analyze();
497 // STATUS_WORD with VOUT/VOUT_OV fault.
498 expectations.statusWordValue =
499 ((status_word::VOUT_FAULT) | (status_word::VOUT_OV_FAULT));
500 // Turn on STATUS_VOUT fault bit(s)
501 expectations.statusVOUTValue = 0xA0;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000502 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
503 {
504 // STATUS_TEMPERATURE don't care (default)
505 setPMBusExpectations(mockPMBus, expectations);
506 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
507 .Times(1)
508 .WillOnce(Return("217000"));
509 psu2.analyze();
510 EXPECT_EQ(psu2.isPresent(), true);
511 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
512 EXPECT_EQ(psu2.hasInputFault(), false);
513 EXPECT_EQ(psu2.hasMFRFault(), false);
514 EXPECT_EQ(psu2.hasVINUVFault(), false);
515 EXPECT_EQ(psu2.hasCommFault(), false);
516 EXPECT_EQ(psu2.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
517 EXPECT_EQ(psu2.hasVoutUVFault(), false);
518 EXPECT_EQ(psu2.hasIoutOCFault(), false);
519 EXPECT_EQ(psu2.hasFanFault(), false);
520 EXPECT_EQ(psu2.hasTempFault(), false);
521 EXPECT_EQ(psu2.hasPgoodFault(), false);
522 EXPECT_EQ(psu2.hasPSKillFault(), false);
523 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
524 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
525 }
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000526 }
527
528 // IOUT_OC_FAULT fault
529 {
530 // First STATUS_WORD with no bits set, then with IOUT_OC fault.
531 PMBusExpectations expectations;
532 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000533 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
534 .Times(1)
535 .WillOnce(Return("218000"));
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000536 psu2.analyze();
537 // STATUS_WORD with IOUT_OC fault.
538 expectations.statusWordValue = status_word::IOUT_OC_FAULT;
539 // Turn on STATUS_IOUT fault bit(s)
540 expectations.statusIOUTValue = 0x88;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000541 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
542 {
543 setPMBusExpectations(mockPMBus, expectations);
544 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
545 .Times(1)
546 .WillOnce(Return("219000"));
547 psu2.analyze();
548 EXPECT_EQ(psu2.isPresent(), true);
549 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
550 EXPECT_EQ(psu2.hasInputFault(), false);
551 EXPECT_EQ(psu2.hasMFRFault(), false);
552 EXPECT_EQ(psu2.hasVINUVFault(), false);
553 EXPECT_EQ(psu2.hasCommFault(), false);
554 EXPECT_EQ(psu2.hasVoutOVFault(), false);
555 EXPECT_EQ(psu2.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
556 EXPECT_EQ(psu2.hasVoutUVFault(), false);
557 EXPECT_EQ(psu2.hasFanFault(), false);
558 EXPECT_EQ(psu2.hasTempFault(), false);
559 EXPECT_EQ(psu2.hasPgoodFault(), false);
560 EXPECT_EQ(psu2.hasPSKillFault(), false);
561 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
562 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
563 }
Brandon Wyman2cf46942021-10-28 19:09:16 +0000564 }
565
566 // VOUT_UV_FAULT
567 {
568 // First STATUS_WORD with no bits set, then with VOUT fault.
569 PMBusExpectations expectations;
570 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000571 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
572 .Times(1)
573 .WillOnce(Return("220000"));
Brandon Wyman2cf46942021-10-28 19:09:16 +0000574 psu2.analyze();
575 // Change STATUS_WORD to indicate VOUT fault.
576 expectations.statusWordValue = (status_word::VOUT_FAULT);
577 // Turn on STATUS_VOUT fault bit(s)
578 expectations.statusVOUTValue = 0x30;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000579 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
580 {
581 setPMBusExpectations(mockPMBus, expectations);
582 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
583 .Times(1)
584 .WillOnce(Return("221000"));
585 psu2.analyze();
586 EXPECT_EQ(psu2.isPresent(), true);
587 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
588 EXPECT_EQ(psu2.hasInputFault(), false);
589 EXPECT_EQ(psu2.hasMFRFault(), false);
590 EXPECT_EQ(psu2.hasVINUVFault(), false);
591 EXPECT_EQ(psu2.hasCommFault(), false);
592 EXPECT_EQ(psu2.hasVoutOVFault(), false);
593 EXPECT_EQ(psu2.hasIoutOCFault(), false);
594 EXPECT_EQ(psu2.hasVoutUVFault(), x >= DEGLITCH_LIMIT);
595 EXPECT_EQ(psu2.hasFanFault(), false);
596 EXPECT_EQ(psu2.hasTempFault(), false);
597 EXPECT_EQ(psu2.hasPgoodFault(), false);
598 EXPECT_EQ(psu2.hasPSKillFault(), false);
599 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
600 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
601 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000602 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600603
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000604 // Fan fault
Brandon Wymanb654c612021-11-05 23:24:51 +0000605 {
606 // First STATUS_WORD with no bits set, then with fan fault.
607 PMBusExpectations expectations;
608 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000609 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
610 .Times(1)
611 .WillOnce(Return("222000"));
Brandon Wymanb654c612021-11-05 23:24:51 +0000612 psu2.analyze();
613 expectations.statusWordValue = (status_word::FAN_FAULT);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000614 // STATUS_FANS_1_2 with fan 1 warning & fault bits on.
615 expectations.statusFans12Value = 0xA0;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000616
617 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
618 {
619 setPMBusExpectations(mockPMBus, expectations);
620 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
621 .Times(1)
622 .WillOnce(Return("223000"));
623 psu2.analyze();
624 EXPECT_EQ(psu2.isPresent(), true);
625 EXPECT_EQ(psu2.isFaulted(), x >= DEGLITCH_LIMIT);
626 EXPECT_EQ(psu2.hasFanFault(), x >= DEGLITCH_LIMIT);
627 EXPECT_EQ(psu2.hasInputFault(), false);
628 EXPECT_EQ(psu2.hasMFRFault(), false);
629 EXPECT_EQ(psu2.hasVINUVFault(), false);
630 EXPECT_EQ(psu2.hasCommFault(), false);
631 EXPECT_EQ(psu2.hasVoutOVFault(), false);
632 EXPECT_EQ(psu2.hasIoutOCFault(), false);
633 EXPECT_EQ(psu2.hasVoutUVFault(), false);
634 EXPECT_EQ(psu2.hasTempFault(), false);
635 EXPECT_EQ(psu2.hasPgoodFault(), false);
636 EXPECT_EQ(psu2.hasPSKillFault(), false);
637 EXPECT_EQ(psu2.hasPS12VcsFault(), false);
638 EXPECT_EQ(psu2.hasPSCS12VFault(), false);
639 }
Brandon Wymanb654c612021-11-05 23:24:51 +0000640 }
Brandon Wyman2916ea52021-11-06 03:31:18 +0000641
Brandon Wyman06ca4592021-12-06 22:52:23 +0000642 // PGOOD/OFF fault. Deglitched, needs to reach DEGLITCH_LIMIT.
Brandon Wyman2916ea52021-11-06 03:31:18 +0000643 {
Brandon Wyman2916ea52021-11-06 03:31:18 +0000644 // First STATUS_WORD with no bits set.
645 PMBusExpectations expectations;
646 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000647 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
648 .Times(1)
649 .WillOnce(Return("123000"));
Brandon Wyman2916ea52021-11-06 03:31:18 +0000650 psu2.analyze();
651 EXPECT_EQ(psu2.isFaulted(), false);
652 // POWER_GOOD# inactive, and OFF bit on.
653 expectations.statusWordValue =
654 ((status_word::POWER_GOOD_NEGATED) | (status_word::UNIT_IS_OFF));
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000655 for (auto x = 1; x <= PGOOD_DEGLITCH_LIMIT; x++)
Brandon Wyman06ca4592021-12-06 22:52:23 +0000656 {
657 // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT, and
658 // STATUS_TEMPERATURE: Don't care if bits set or not (defaults).
659 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000660 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
661 .Times(1)
662 .WillOnce(Return("124000"));
Brandon Wyman06ca4592021-12-06 22:52:23 +0000663 psu2.analyze();
664 EXPECT_EQ(psu2.isPresent(), true);
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000665 EXPECT_EQ(psu2.isFaulted(), x >= PGOOD_DEGLITCH_LIMIT);
Brandon Wyman06ca4592021-12-06 22:52:23 +0000666 EXPECT_EQ(psu2.hasInputFault(), false);
667 EXPECT_EQ(psu2.hasMFRFault(), false);
668 EXPECT_EQ(psu2.hasVINUVFault(), false);
669 EXPECT_EQ(psu2.hasCommFault(), false);
670 EXPECT_EQ(psu2.hasVoutOVFault(), false);
671 EXPECT_EQ(psu2.hasVoutUVFault(), false);
672 EXPECT_EQ(psu2.hasIoutOCFault(), false);
673 EXPECT_EQ(psu2.hasFanFault(), false);
674 EXPECT_EQ(psu2.hasTempFault(), false);
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000675 EXPECT_EQ(psu2.hasPgoodFault(), x >= PGOOD_DEGLITCH_LIMIT);
Brandon Wyman06ca4592021-12-06 22:52:23 +0000676 }
Brandon Wyman2916ea52021-11-06 03:31:18 +0000677 }
678
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600679 // TODO: ReadFailure
680}
681
Brandon Wyman59a35792020-06-04 12:37:40 -0500682TEST_F(PowerSupplyTests, OnOffConfig)
683{
684 auto bus = sdbusplus::bus::new_default();
685 uint8_t data = 0x15;
686
687 // Test where PSU is NOT present
688 try
689 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000690 // Assume GPIO presence, not inventory presence?
Matt Spinler0975eaf2022-02-14 15:38:30 -0600691 EXPECT_CALL(mockedUtil, setAvailable(_, _, _)).Times(0);
George Liu9464c422023-02-27 14:30:27 +0800692 PowerSupply psu{bus, PSUInventoryPath, 4, 0x69,
693 "ibm-cffps", PSUGPIOLineName, isPowerOn};
B. J. Wyman681b2a32021-04-20 22:31:22 +0000694
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000695 MockedGPIOInterface* mockPresenceGPIO =
696 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000697 ON_CALL(*mockPresenceGPIO, read()).WillByDefault(Return(0));
Brandon Wyman59a35792020-06-04 12:37:40 -0500698 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000699 // Constructor should set initial presence, default read returns 0.
Brandon Wyman59a35792020-06-04 12:37:40 -0500700 // If it is not present, I should not be trying to write to it.
701 EXPECT_CALL(mockPMBus, writeBinary(_, _, _)).Times(0);
702 psu.onOffConfig(data);
703 }
704 catch (...)
Adriana Kobylak0c9a33d2021-09-13 18:05:09 +0000705 {}
Brandon Wyman59a35792020-06-04 12:37:40 -0500706
707 // Test where PSU is present
708 try
709 {
B. J. Wyman681b2a32021-04-20 22:31:22 +0000710 // Assume GPIO presence, not inventory presence?
Matt Spinler0975eaf2022-02-14 15:38:30 -0600711 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
George Liu9464c422023-02-27 14:30:27 +0800712 PowerSupply psu{bus, PSUInventoryPath, 5, 0x6a,
713 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000714 MockedGPIOInterface* mockPresenceGPIO =
715 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wyman391a0692021-12-08 23:28:18 +0000716 // There will potentially be multiple calls, we want it to continue
717 // returning 1 for the GPIO read to keep the power supply present.
718 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman59a35792020-06-04 12:37:40 -0500719 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +0000720 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +0000721 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
722 // for INPUT_HISTORY will check max_power_out to see if it is
723 // old/unsupported power supply. Indicate good value, supported.
724 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -0500725 .WillRepeatedly(Return("2000"));
Brandon Wyman391a0692021-12-08 23:28:18 +0000726 // If I am calling analyze(), I should probably give it good data.
727 // STATUS_WORD 0x0000 is powered on, no faults.
728 PMBusExpectations expectations;
729 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000730 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
731 .Times(1)
732 .WillOnce(Return("205000"));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000733 psu.analyze();
Brandon Wyman391a0692021-12-08 23:28:18 +0000734 // I definitely should be writting ON_OFF_CONFIG if I call the function
735 EXPECT_CALL(mockPMBus, writeBinary(ON_OFF_CONFIG, ElementsAre(0x15),
736 Type::HwmonDeviceDebug))
Brandon Wyman59a35792020-06-04 12:37:40 -0500737 .Times(1);
738 psu.onOffConfig(data);
739 }
740 catch (...)
Adriana Kobylak0c9a33d2021-09-13 18:05:09 +0000741 {}
Brandon Wyman59a35792020-06-04 12:37:40 -0500742}
743
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600744TEST_F(PowerSupplyTests, ClearFaults)
745{
746 auto bus = sdbusplus::bus::new_default();
George Liu9464c422023-02-27 14:30:27 +0800747 PowerSupply psu{bus, PSUInventoryPath, 13, 0x68,
748 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000749 MockedGPIOInterface* mockPresenceGPIO =
750 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wyman06ca4592021-12-06 22:52:23 +0000751 // Always return 1 to indicate present.
752 // Each analyze() call will trigger a read of the presence GPIO.
753 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000754 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +0000755 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +0000756 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
757 // for INPUT_HISTORY will check max_power_out to see if it is
758 // old/unsupported power supply. Indicate good value, supported.
759 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -0500760 .WillRepeatedly(Return("2000"));
Brandon Wyman8da35c52021-10-28 22:45:08 +0000761 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +0000762 PMBusExpectations expectations;
763 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +0000764 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
765 .Times(1)
766 .WillOnce(Return("207000"));
B. J. Wyman681b2a32021-04-20 22:31:22 +0000767 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600768 EXPECT_EQ(psu.isPresent(), true);
769 EXPECT_EQ(psu.isFaulted(), false);
770 EXPECT_EQ(psu.hasInputFault(), false);
771 EXPECT_EQ(psu.hasMFRFault(), false);
772 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000773 EXPECT_EQ(psu.hasCommFault(), false);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000774 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000775 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000776 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000777 EXPECT_EQ(psu.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000778 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000779 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000780 EXPECT_EQ(psu.hasPSKillFault(), false);
781 EXPECT_EQ(psu.hasPS12VcsFault(), false);
782 EXPECT_EQ(psu.hasPSCS12VFault(), false);
Brandon Wymanb654c612021-11-05 23:24:51 +0000783
Brandon Wymanf07bc792021-10-12 19:00:35 +0000784 // STATUS_WORD with fault bits galore!
Brandon Wymanb654c612021-11-05 23:24:51 +0000785 expectations.statusWordValue = 0xFFFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000786 // STATUS_INPUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000787 expectations.statusInputValue = 0xFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +0000788 // STATUS_MFR_SPEFIC with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000789 expectations.statusMFRValue = 0xFF;
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000790 // STATUS_CML with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000791 expectations.statusCMLValue = 0xFF;
Brandon Wyman6710ba22021-10-27 17:39:31 +0000792 // STATUS_VOUT with bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +0000793 expectations.statusVOUTValue = 0xFF;
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000794 // STATUS_IOUT with bits on.
795 expectations.statusIOUTValue = 0xFF;
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000796 // STATUS_FANS_1_2 with bits on.
797 expectations.statusFans12Value = 0xFF;
Brandon Wyman96893a42021-11-05 19:56:57 +0000798 // STATUS_TEMPERATURE with bits on.
799 expectations.statusTempValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000800
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000801 for (auto x = 1; x <= PGOOD_DEGLITCH_LIMIT; x++)
Brandon Wymanc2906f42021-12-21 20:14:56 +0000802 {
803 setPMBusExpectations(mockPMBus, expectations);
804 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
805 .Times(1)
806 .WillOnce(Return("0"));
Matt Spinler0975eaf2022-02-14 15:38:30 -0600807 if (x == DEGLITCH_LIMIT)
808 {
809 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
810 }
Brandon Wymanc2906f42021-12-21 20:14:56 +0000811 psu.analyze();
812 EXPECT_EQ(psu.isPresent(), true);
813 // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
814 // Rely on HasVoutUVFault() to verify this sets and clears.
815 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000816 // pgoodFault at PGOOD_DEGLITCH_LIMIT, all other faults are deglitched
817 // up to DEGLITCH_LIMIT
Brandon Wymanc2906f42021-12-21 20:14:56 +0000818 EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT);
819 EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT);
820 EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT);
821 EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT);
Brandon Wymanc2906f42021-12-21 20:14:56 +0000822 EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
823 EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
824 EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT);
825 EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT);
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000826 EXPECT_EQ(psu.hasPgoodFault(), x >= PGOOD_DEGLITCH_LIMIT);
Brandon Wymanc2906f42021-12-21 20:14:56 +0000827 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
828 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
829 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
830 }
831
Brandon Wyman32453e92021-12-15 19:00:14 +0000832 EXPECT_CALL(mockPMBus, read(READ_VIN, _, _))
833 .Times(1)
834 .WillOnce(Return(207000));
Brandon Wyman3225a452022-03-18 18:51:49 +0000835 // Clearing VIN_UV fault via in1_lcrit_alarm
836 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
837 .Times(1)
838 .WillOnce(Return(1));
Matt Spinler0975eaf2022-02-14 15:38:30 -0600839 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600840 psu.clearFaults();
841 EXPECT_EQ(psu.isPresent(), true);
842 EXPECT_EQ(psu.isFaulted(), false);
843 EXPECT_EQ(psu.hasInputFault(), false);
844 EXPECT_EQ(psu.hasMFRFault(), false);
845 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wyman85c7bf42021-10-19 22:28:48 +0000846 EXPECT_EQ(psu.hasCommFault(), false);
Brandon Wyman6710ba22021-10-27 17:39:31 +0000847 EXPECT_EQ(psu.hasVoutOVFault(), false);
Brandon Wymanb10b3be2021-11-09 22:12:15 +0000848 EXPECT_EQ(psu.hasIoutOCFault(), false);
Brandon Wyman2cf46942021-10-28 19:09:16 +0000849 EXPECT_EQ(psu.hasVoutUVFault(), false);
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +0000850 EXPECT_EQ(psu.hasFanFault(), false);
Brandon Wyman96893a42021-11-05 19:56:57 +0000851 EXPECT_EQ(psu.hasTempFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +0000852 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman39ea02b2021-11-23 23:22:23 +0000853 EXPECT_EQ(psu.hasPSKillFault(), false);
854 EXPECT_EQ(psu.hasPS12VcsFault(), false);
855 EXPECT_EQ(psu.hasPSCS12VFault(), false);
B. J. Wyman681b2a32021-04-20 22:31:22 +0000856
Brandon Wyman82affd92021-11-24 19:12:49 +0000857 // Faults clear on READ_VIN 0 -> !0
858 // STATUS_WORD with fault bits galore!
859 expectations.statusWordValue = 0xFFFF;
860 // STATUS_INPUT with fault bits on.
861 expectations.statusInputValue = 0xFF;
862 // STATUS_MFR_SPEFIC with bits on.
863 expectations.statusMFRValue = 0xFF;
864 // STATUS_CML with bits on.
865 expectations.statusCMLValue = 0xFF;
866 // STATUS_VOUT with bits on.
867 expectations.statusVOUTValue = 0xFF;
868 // STATUS_IOUT with bits on.
869 expectations.statusIOUTValue = 0xFF;
870 // STATUS_FANS_1_2 with bits on.
871 expectations.statusFans12Value = 0xFF;
872 // STATUS_TEMPERATURE with bits on.
873 expectations.statusTempValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +0000874
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000875 // All faults deglitched now. Check for false before limit above.
Brandon Wymanc2906f42021-12-21 20:14:56 +0000876 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
877 {
878 setPMBusExpectations(mockPMBus, expectations);
879 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
880 .Times(1)
881 .WillOnce(Return("0"));
Matt Spinler0975eaf2022-02-14 15:38:30 -0600882 if (x == DEGLITCH_LIMIT)
883 {
884 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
885 }
Brandon Wymanc2906f42021-12-21 20:14:56 +0000886 psu.analyze();
887 }
888
Brandon Wyman82affd92021-11-24 19:12:49 +0000889 EXPECT_EQ(psu.isPresent(), true);
890 EXPECT_EQ(psu.isFaulted(), true);
891 EXPECT_EQ(psu.hasInputFault(), true);
892 EXPECT_EQ(psu.hasMFRFault(), true);
893 EXPECT_EQ(psu.hasVINUVFault(), true);
Brandon Wyman6869acb2021-11-03 16:38:05 +0000894 EXPECT_EQ(psu.hasCommFault(), false);
Brandon Wyman82affd92021-11-24 19:12:49 +0000895 EXPECT_EQ(psu.hasVoutOVFault(), true);
896 EXPECT_EQ(psu.hasIoutOCFault(), true);
897 // Cannot have VOUT_OV_FAULT and VOUT_UV_FAULT.
898 // Rely on HasVoutUVFault() to verify this sets and clears.
899 EXPECT_EQ(psu.hasVoutUVFault(), false);
900 EXPECT_EQ(psu.hasFanFault(), true);
901 EXPECT_EQ(psu.hasTempFault(), true);
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000902 // No PGOOD fault, as less than PGOOD_DEGLITCH_LIMIT
903 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman82affd92021-11-24 19:12:49 +0000904 EXPECT_EQ(psu.hasPSKillFault(), true);
905 EXPECT_EQ(psu.hasPS12VcsFault(), true);
906 EXPECT_EQ(psu.hasPSCS12VFault(), true);
907 // STATUS_WORD with INPUT/VIN_UV fault bits off.
908 expectations.statusWordValue = 0xDFF7;
909 // STATUS_INPUT with VIN_UV_WARNING, VIN_UV_FAULT, and Unit Off For
910 // Insufficient Input Voltage bits off.
911 expectations.statusInputValue = 0xC7;
912 setPMBusExpectations(mockPMBus, expectations);
913 // READ_VIN back in range.
914 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
915 .Times(1)
916 .WillOnce(Return("206000"));
Brandon Wyman3225a452022-03-18 18:51:49 +0000917 // VIN_UV cleared via in1_lcrit_alarm when voltage back in range.
918 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
919 .Times(1)
920 .WillOnce(Return(1));
921 psu.analyze();
922 // We only cleared the VIN_UV and OFF faults.
923 EXPECT_EQ(psu.isPresent(), true);
924 EXPECT_EQ(psu.isFaulted(), true);
925 EXPECT_EQ(psu.hasInputFault(), false);
926 EXPECT_EQ(psu.hasMFRFault(), true);
927 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wyman6869acb2021-11-03 16:38:05 +0000928 EXPECT_EQ(psu.hasCommFault(), false);
Brandon Wyman3225a452022-03-18 18:51:49 +0000929 EXPECT_EQ(psu.hasVoutOVFault(), true);
930 EXPECT_EQ(psu.hasIoutOCFault(), true);
931 EXPECT_EQ(psu.hasVoutUVFault(), false);
932 EXPECT_EQ(psu.hasFanFault(), true);
933 EXPECT_EQ(psu.hasTempFault(), true);
Brandon Wyman6d469fd2022-06-15 16:58:21 +0000934 // No PGOOD fault, as less than PGOOD_DEGLITCH_LIMIT
935 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman3225a452022-03-18 18:51:49 +0000936 EXPECT_EQ(psu.hasPSKillFault(), true);
937 EXPECT_EQ(psu.hasPS12VcsFault(), true);
938 EXPECT_EQ(psu.hasPSCS12VFault(), true);
939
940 // All faults cleared
941 expectations = {0};
942 setPMBusExpectations(mockPMBus, expectations);
943 // READ_VIN back in range.
944 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
945 .Times(1)
946 .WillOnce(Return("206000"));
Matt Spinler0975eaf2022-02-14 15:38:30 -0600947 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wyman82affd92021-11-24 19:12:49 +0000948 psu.analyze();
949 EXPECT_EQ(psu.isPresent(), true);
950 EXPECT_EQ(psu.isFaulted(), false);
951 EXPECT_EQ(psu.hasInputFault(), false);
952 EXPECT_EQ(psu.hasMFRFault(), false);
953 EXPECT_EQ(psu.hasVINUVFault(), false);
954 EXPECT_EQ(psu.hasCommFault(), false);
955 EXPECT_EQ(psu.hasVoutOVFault(), false);
956 EXPECT_EQ(psu.hasIoutOCFault(), false);
957 EXPECT_EQ(psu.hasVoutUVFault(), false);
958 EXPECT_EQ(psu.hasFanFault(), false);
959 EXPECT_EQ(psu.hasTempFault(), false);
960 EXPECT_EQ(psu.hasPgoodFault(), false);
961 EXPECT_EQ(psu.hasPSKillFault(), false);
962 EXPECT_EQ(psu.hasPS12VcsFault(), false);
963 EXPECT_EQ(psu.hasPSCS12VFault(), false);
964
B. J. Wyman681b2a32021-04-20 22:31:22 +0000965 // TODO: Faults clear on missing/present?
Brandon Wyman3f1242f2020-01-28 13:11:25 -0600966}
967
968TEST_F(PowerSupplyTests, UpdateInventory)
969{
970 auto bus = sdbusplus::bus::new_default();
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500971
972 try
973 {
George Liu9464c422023-02-27 14:30:27 +0800974 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68,
975 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500976 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
977 // If it is not present, I should not be trying to read a string
978 EXPECT_CALL(mockPMBus, readString(_, _)).Times(0);
979 psu.updateInventory();
980 }
981 catch (...)
982 {
983 ADD_FAILURE() << "Should not have caught exception.";
984 }
985
986 try
987 {
George Liu9464c422023-02-27 14:30:27 +0800988 PowerSupply psu{bus, PSUInventoryPath, 13, 0x69,
989 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +0000990 MockedGPIOInterface* mockPresenceGPIO =
991 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +0000992 // GPIO read return 1 to indicate present.
993 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
Brandon Wyman1d7a7df2020-03-26 10:14:05 -0500994 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +0000995 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +0000996 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
997 // for INPUT_HISTORY will check max_power_out to see if it is
998 // old/unsupported power supply. Indicate good value, supported.
999 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -05001000 .WillRepeatedly(Return("2000"));
Brandon Wyman391a0692021-12-08 23:28:18 +00001001 // STATUS_WORD 0x0000 is powered on, no faults.
1002 PMBusExpectations expectations;
1003 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001004 // Call to analyze will read voltage, trigger clear faults for 0 to
1005 // within range.
1006 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1007 .Times(1)
1008 .WillOnce(Return("123456"));
Brandon Wyman391a0692021-12-08 23:28:18 +00001009 psu.analyze();
Brandon Wyman1d7a7df2020-03-26 10:14:05 -05001010 EXPECT_CALL(mockPMBus, readString(_, _)).WillRepeatedly(Return(""));
1011 psu.updateInventory();
1012
Brandon Wyman3c530fb2021-04-13 13:13:22 -05001013#if IBM_VPD
Brandon Wyman1d7a7df2020-03-26 10:14:05 -05001014 EXPECT_CALL(mockPMBus, readString(_, _))
1015 .WillOnce(Return("CCIN"))
1016 .WillOnce(Return("PN3456"))
1017 .WillOnce(Return("FN3456"))
1018 .WillOnce(Return("HEADER"))
1019 .WillOnce(Return("SN3456"))
1020 .WillOnce(Return("FW3456"));
Brandon Wyman3c530fb2021-04-13 13:13:22 -05001021#endif
Brandon Wyman1d7a7df2020-03-26 10:14:05 -05001022 psu.updateInventory();
1023 // TODO: D-Bus mocking to verify values stored on D-Bus (???)
1024 }
1025 catch (...)
1026 {
1027 ADD_FAILURE() << "Should not have caught exception.";
1028 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001029}
1030
1031TEST_F(PowerSupplyTests, IsPresent)
1032{
1033 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001034
George Liu9464c422023-02-27 14:30:27 +08001035 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68,
1036 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001037 MockedGPIOInterface* mockPresenceGPIO =
1038 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001039 EXPECT_EQ(psu.isPresent(), false);
1040
B. J. Wyman681b2a32021-04-20 22:31:22 +00001041 // Change GPIO read to return 1 to indicate present.
1042 EXPECT_CALL(*mockPresenceGPIO, read()).Times(1).WillOnce(Return(1));
Brandon Wyman391a0692021-12-08 23:28:18 +00001043 // Call to analyze() will update to present, that will trigger updating
1044 // to the correct/latest HWMON directory, in case it changes.
1045 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1046 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001047 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1048 // for INPUT_HISTORY will check max_power_out to see if it is
1049 // old/unsupported power supply. Indicate good value, supported.
1050 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -05001051 .WillRepeatedly(Return("2000"));
Brandon Wyman391a0692021-12-08 23:28:18 +00001052 // Call to analyze things will trigger read of STATUS_WORD and READ_VIN.
1053 // Default expectations will be on, no faults.
1054 PMBusExpectations expectations;
1055 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001056 // Give it an input voltage in the 100-volt range.
1057 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1058 .Times(1)
1059 .WillOnce(Return("123456"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001060 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
B. J. Wyman681b2a32021-04-20 22:31:22 +00001061 psu.analyze();
1062 EXPECT_EQ(psu.isPresent(), true);
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001063}
1064
1065TEST_F(PowerSupplyTests, IsFaulted)
1066{
1067 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001068
George Liu9464c422023-02-27 14:30:27 +08001069 PowerSupply psu{bus, PSUInventoryPath, 11, 0x6f,
1070 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001071 MockedGPIOInterface* mockPresenceGPIO =
1072 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +00001073 // Always return 1 to indicate present.
1074 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman391a0692021-12-08 23:28:18 +00001075 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1076 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001077 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1078 // for INPUT_HISTORY will check max_power_out to see if it is
1079 // old/unsupported power supply. Indicate good value, supported.
1080 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -05001081 .WillRepeatedly(Return("2000"));
Brandon Wyman391a0692021-12-08 23:28:18 +00001082 // Call to analyze things will trigger read of STATUS_WORD and READ_VIN.
1083 // Default expectations will be on, no faults.
1084 PMBusExpectations expectations;
1085 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001086 // Give it an input voltage in the 100-volt range.
1087 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1088 .Times(1)
1089 .WillOnce(Return("124680"));
B. J. Wyman681b2a32021-04-20 22:31:22 +00001090 psu.analyze();
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001091 EXPECT_EQ(psu.isFaulted(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001092 // STATUS_WORD with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001093 expectations.statusWordValue = 0xFFFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +00001094 // STATUS_INPUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001095 expectations.statusInputValue = 0xFF;
Brandon Wymanf07bc792021-10-12 19:00:35 +00001096 // STATUS_MFR_SPECIFIC with faults bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001097 expectations.statusMFRValue = 0xFF;
Brandon Wyman85c7bf42021-10-19 22:28:48 +00001098 // STATUS_CML with faults bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001099 expectations.statusCMLValue = 0xFF;
Brandon Wyman6710ba22021-10-27 17:39:31 +00001100 // STATUS_VOUT with fault bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001101 expectations.statusVOUTValue = 0xFF;
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001102 // STATUS_IOUT with fault bits on.
1103 expectations.statusIOUTValue = 0xFF;
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001104 // STATUS_FANS_1_2 with bits on.
1105 expectations.statusFans12Value = 0xFF;
Brandon Wyman96893a42021-11-05 19:56:57 +00001106 // STATUS_TEMPERATURE with fault bits on.
1107 expectations.statusTempValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001108 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1109 {
1110 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman4fc191f2022-03-10 23:07:13 +00001111 // Also get another read of READ_VIN, faulted, so not in 100-volt range
Brandon Wymanc2906f42021-12-21 20:14:56 +00001112 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1113 .Times(1)
Brandon Wyman4fc191f2022-03-10 23:07:13 +00001114 .WillOnce(Return("19000"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001115 if (x == DEGLITCH_LIMIT)
1116 {
1117 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1118 }
Brandon Wymanc2906f42021-12-21 20:14:56 +00001119 psu.analyze();
1120 EXPECT_EQ(psu.isFaulted(), x >= DEGLITCH_LIMIT);
1121 }
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001122}
1123
1124TEST_F(PowerSupplyTests, HasInputFault)
1125{
1126 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001127
George Liu9464c422023-02-27 14:30:27 +08001128 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68,
1129 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001130 MockedGPIOInterface* mockPresenceGPIO =
1131 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +00001132 // Always return 1 to indicate present.
1133 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001134 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001135 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001136 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1137 // for INPUT_HISTORY will check max_power_out to see if it is
1138 // old/unsupported power supply. Indicate good value, supported.
1139 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -05001140 .WillRepeatedly(Return("2000"));
Brandon Wyman8da35c52021-10-28 22:45:08 +00001141 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +00001142 PMBusExpectations expectations;
1143 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001144 // Analyze call will also need good READ_VIN value to check.
1145 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1146 .Times(1)
1147 .WillOnce(Return("201100"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001148 psu.analyze();
1149 EXPECT_EQ(psu.hasInputFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001150 // STATUS_WORD with input fault/warn on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001151 expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001152 // STATUS_INPUT with an input fault bit on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001153 expectations.statusInputValue = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001154 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1155 {
1156 setPMBusExpectations(mockPMBus, expectations);
1157 // Analyze call will also need good READ_VIN value to check.
1158 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1159 .Times(1)
1160 .WillOnce(Return("201200"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001161 if (x == DEGLITCH_LIMIT)
1162 {
1163 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1164 }
Brandon Wymanc2906f42021-12-21 20:14:56 +00001165 psu.analyze();
1166 EXPECT_EQ(psu.hasInputFault(), x >= DEGLITCH_LIMIT);
1167 }
Brandon Wymanf07bc792021-10-12 19:00:35 +00001168 // STATUS_WORD with no bits on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001169 expectations.statusWordValue = 0;
1170 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001171 // Analyze call will also need good READ_VIN value to check.
1172 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1173 .Times(1)
1174 .WillOnce(Return("201300"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001175 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001176 psu.analyze();
1177 EXPECT_EQ(psu.hasInputFault(), false);
1178}
1179
1180TEST_F(PowerSupplyTests, HasMFRFault)
1181{
1182 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001183
George Liu9464c422023-02-27 14:30:27 +08001184 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68,
1185 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001186 MockedGPIOInterface* mockPresenceGPIO =
1187 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +00001188 // Always return 1 to indicate present.
1189 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001190 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001191 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001192 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1193 // for INPUT_HISTORY will check max_power_out to see if it is
1194 // old/unsupported power supply. Indicate good value, supported.
1195 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -05001196 .WillRepeatedly(Return("2000"));
Brandon Wymanf07bc792021-10-12 19:00:35 +00001197 // First return STATUS_WORD with no bits on.
Brandon Wyman8da35c52021-10-28 22:45:08 +00001198 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +00001199 PMBusExpectations expectations;
1200 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001201 // Analyze call will also need good READ_VIN value to check.
1202 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1203 .Times(1)
1204 .WillOnce(Return("202100"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001205 psu.analyze();
1206 EXPECT_EQ(psu.hasMFRFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001207 // Next return STATUS_WORD with MFR fault bit on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001208 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001209 // STATUS_MFR_SPEFIC with bit(s) on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001210 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001211 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1212 {
1213 setPMBusExpectations(mockPMBus, expectations);
1214 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1215 .Times(1)
1216 .WillOnce(Return("202200"));
1217 psu.analyze();
1218 EXPECT_EQ(psu.hasMFRFault(), x >= DEGLITCH_LIMIT);
1219 }
Brandon Wymanf07bc792021-10-12 19:00:35 +00001220 // Back to no bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +00001221 expectations.statusWordValue = 0;
1222 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001223 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1224 .Times(1)
1225 .WillOnce(Return("202300"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001226 psu.analyze();
1227 EXPECT_EQ(psu.hasMFRFault(), false);
1228}
1229
1230TEST_F(PowerSupplyTests, HasVINUVFault)
1231{
1232 auto bus = sdbusplus::bus::new_default();
B. J. Wyman681b2a32021-04-20 22:31:22 +00001233
George Liu9464c422023-02-27 14:30:27 +08001234 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68,
1235 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Adriana Kobylak3ca062a2021-10-20 15:27:23 +00001236 MockedGPIOInterface* mockPresenceGPIO =
1237 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
B. J. Wyman681b2a32021-04-20 22:31:22 +00001238 // Always return 1 to indicate present.
1239 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001240 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001241 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001242 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1243 // for INPUT_HISTORY will check max_power_out to see if it is
1244 // old/unsupported power supply. Indicate good value, supported.
1245 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -05001246 .WillRepeatedly(Return("2000"));
Brandon Wyman82affd92021-11-24 19:12:49 +00001247
1248 // Presence change from missing to present will trigger in1_input read in
1249 // an attempt to get CLEAR_FAULTS called. Return value ignored.
1250 // Zero to non-zero voltage, for missing/present change, triggers clear
1251 // faults call again. Return value ignored.
1252 // Fault (low voltage) to not faulted (voltage in range) triggers clear
1253 // faults call a third time.
1254
Brandon Wyman8da35c52021-10-28 22:45:08 +00001255 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +00001256 PMBusExpectations expectations;
1257 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001258 // Analyze call will also need good READ_VIN value to check.
1259 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1260 .Times(1)
1261 .WillOnce(Return("201100"));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001262 psu.analyze();
1263 EXPECT_EQ(psu.hasVINUVFault(), false);
Brandon Wymanf07bc792021-10-12 19:00:35 +00001264 // Turn fault on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001265 expectations.statusWordValue = (status_word::VIN_UV_FAULT);
Brandon Wyman85c7bf42021-10-19 22:28:48 +00001266 // Curious disagreement between PMBus Spec. Part II Figure 16 and 33. Go by
1267 // Figure 16, and assume bits on in STATUS_INPUT.
Brandon Wymanb654c612021-11-05 23:24:51 +00001268 expectations.statusInputValue = 0x18;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001269 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1270 {
1271 setPMBusExpectations(mockPMBus, expectations);
1272 // If there is a VIN_UV fault, fake reading voltage of less than 20V
1273 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1274 .Times(1)
1275 .WillOnce(Return("19876"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001276 if (x == DEGLITCH_LIMIT)
1277 {
1278 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1279 }
Brandon Wymanc2906f42021-12-21 20:14:56 +00001280 psu.analyze();
1281 EXPECT_EQ(psu.hasVINUVFault(), x >= DEGLITCH_LIMIT);
1282 }
Brandon Wymanf07bc792021-10-12 19:00:35 +00001283 // Back to no fault bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +00001284 expectations.statusWordValue = 0;
1285 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001286 // Updates now result in clearing faults if read voltage goes from below the
1287 // minimum, to within a valid range.
1288 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1289 .Times(1)
1290 .WillOnce(Return("201300"));
Brandon Wyman3225a452022-03-18 18:51:49 +00001291 // Went from below minimum to within range, expect clearVinUVFault().
1292 EXPECT_CALL(mockPMBus, read("in1_lcrit_alarm", _, _))
1293 .Times(1)
1294 .WillOnce(Return(1));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001295 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wyman3f1242f2020-01-28 13:11:25 -06001296 psu.analyze();
1297 EXPECT_EQ(psu.hasVINUVFault(), false);
1298}
Brandon Wyman6710ba22021-10-27 17:39:31 +00001299
1300TEST_F(PowerSupplyTests, HasVoutOVFault)
1301{
1302 auto bus = sdbusplus::bus::new_default();
1303
George Liu9464c422023-02-27 14:30:27 +08001304 PowerSupply psu{bus, PSUInventoryPath, 3, 0x69,
1305 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Brandon Wyman6710ba22021-10-27 17:39:31 +00001306 MockedGPIOInterface* mockPresenceGPIO =
1307 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1308 // Always return 1 to indicate present.
1309 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman6710ba22021-10-27 17:39:31 +00001310 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001311 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001312 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1313 // for INPUT_HISTORY will check max_power_out to see if it is
1314 // old/unsupported power supply. Indicate good value, supported.
1315 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -05001316 .WillRepeatedly(Return("2000"));
Brandon Wyman6710ba22021-10-27 17:39:31 +00001317 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wymanb654c612021-11-05 23:24:51 +00001318 PMBusExpectations expectations;
1319 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001320 // Call to analyze will trigger read of "in1_input" to check voltage.
1321 // Initial value would be 0, so this read updates it to non-zero.
1322 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1323 .Times(1)
1324 .WillOnce(Return("202100"));
Brandon Wyman6710ba22021-10-27 17:39:31 +00001325 psu.analyze();
1326 EXPECT_EQ(psu.hasVoutOVFault(), false);
1327 // Turn fault on.
Brandon Wymanb654c612021-11-05 23:24:51 +00001328 expectations.statusWordValue = (status_word::VOUT_OV_FAULT);
Brandon Wyman6710ba22021-10-27 17:39:31 +00001329 // STATUS_VOUT fault bit(s)
Brandon Wymanb654c612021-11-05 23:24:51 +00001330 expectations.statusVOUTValue = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001331 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1332 {
1333 setPMBusExpectations(mockPMBus, expectations);
1334 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1335 .Times(1)
1336 .WillOnce(Return("202200"));
1337 psu.analyze();
1338 EXPECT_EQ(psu.hasVoutOVFault(), x >= DEGLITCH_LIMIT);
1339 }
Brandon Wyman6710ba22021-10-27 17:39:31 +00001340 // Back to no fault bits on in STATUS_WORD
Brandon Wymanb654c612021-11-05 23:24:51 +00001341 expectations.statusWordValue = 0;
1342 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001343 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1344 .Times(1)
1345 .WillOnce(Return("202300"));
Brandon Wyman6710ba22021-10-27 17:39:31 +00001346 psu.analyze();
1347 EXPECT_EQ(psu.hasVoutOVFault(), false);
1348}
Brandon Wyman96893a42021-11-05 19:56:57 +00001349
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001350TEST_F(PowerSupplyTests, HasIoutOCFault)
1351{
1352 auto bus = sdbusplus::bus::new_default();
1353
George Liu9464c422023-02-27 14:30:27 +08001354 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6d,
1355 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001356 MockedGPIOInterface* mockPresenceGPIO =
1357 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1358 // Always return 1 to indicate present.
1359 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001360 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001361 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001362 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1363 // for INPUT_HISTORY will check max_power_out to see if it is
1364 // old/unsupported power supply. Indicate good value, supported.
1365 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -05001366 .WillRepeatedly(Return("2000"));
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001367 // STATUS_WORD 0x0000 is powered on, no faults.
1368 PMBusExpectations expectations;
1369 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001370 // Call to analyze will trigger read of "in1_input" to check voltage.
1371 // Initial value would be 0, so this read updates it to non-zero.
1372 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1373 .Times(1)
1374 .WillOnce(Return("203100"));
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001375 psu.analyze();
1376 EXPECT_EQ(psu.hasIoutOCFault(), false);
1377 // Turn fault on.
1378 expectations.statusWordValue = status_word::IOUT_OC_FAULT;
1379 // STATUS_IOUT fault bit(s)
1380 expectations.statusIOUTValue = 0x88;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001381 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1382 {
1383 setPMBusExpectations(mockPMBus, expectations);
1384 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1385 .Times(1)
1386 .WillOnce(Return("203200"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001387 if (x == DEGLITCH_LIMIT)
1388 {
1389 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1390 }
Brandon Wymanc2906f42021-12-21 20:14:56 +00001391 psu.analyze();
1392 EXPECT_EQ(psu.hasIoutOCFault(), x >= DEGLITCH_LIMIT);
1393 }
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001394 // Back to no fault bits on in STATUS_WORD
1395 expectations.statusWordValue = 0;
1396 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001397 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1398 .Times(1)
1399 .WillOnce(Return("203300"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001400 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wymanb10b3be2021-11-09 22:12:15 +00001401 psu.analyze();
1402 EXPECT_EQ(psu.hasIoutOCFault(), false);
1403}
1404
Brandon Wyman2cf46942021-10-28 19:09:16 +00001405TEST_F(PowerSupplyTests, HasVoutUVFault)
1406{
1407 auto bus = sdbusplus::bus::new_default();
1408
George Liu9464c422023-02-27 14:30:27 +08001409 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a,
1410 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Brandon Wyman2cf46942021-10-28 19:09:16 +00001411 MockedGPIOInterface* mockPresenceGPIO =
1412 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1413 // Always return 1 to indicate present.
1414 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman2cf46942021-10-28 19:09:16 +00001415 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001416 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001417 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1418 // for INPUT_HISTORY will check max_power_out to see if it is
1419 // old/unsupported power supply. Indicate good value, supported.
1420 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -05001421 .WillRepeatedly(Return("2000"));
Brandon Wyman391a0692021-12-08 23:28:18 +00001422 // STATUS_WORD 0x0000 is powered on, no faults.
Brandon Wyman2cf46942021-10-28 19:09:16 +00001423 PMBusExpectations expectations;
1424 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001425 // Call to analyze will trigger read of "in1_input" to check voltage.
1426 // Initial value would be 0, so this read updates it to non-zero.
1427 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1428 .Times(1)
1429 .WillOnce(Return("204100"));
Brandon Wyman2cf46942021-10-28 19:09:16 +00001430 psu.analyze();
1431 EXPECT_EQ(psu.hasVoutUVFault(), false);
1432 // Turn fault on.
1433 expectations.statusWordValue = (status_word::VOUT_FAULT);
1434 // STATUS_VOUT fault bit(s)
1435 expectations.statusVOUTValue = 0x30;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001436 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1437 {
1438 setPMBusExpectations(mockPMBus, expectations);
1439 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1440 .Times(1)
1441 .WillOnce(Return("204200"));
1442 psu.analyze();
1443 EXPECT_EQ(psu.hasVoutUVFault(), x >= DEGLITCH_LIMIT);
1444 }
Brandon Wyman2cf46942021-10-28 19:09:16 +00001445 // Back to no fault bits on in STATUS_WORD
1446 expectations.statusWordValue = 0;
1447 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001448 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1449 .Times(1)
1450 .WillOnce(Return("204300"));
Brandon Wyman2cf46942021-10-28 19:09:16 +00001451 psu.analyze();
1452 EXPECT_EQ(psu.hasVoutUVFault(), false);
1453}
1454
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001455TEST_F(PowerSupplyTests, HasFanFault)
1456{
1457 auto bus = sdbusplus::bus::new_default();
1458
Matt Spinler0975eaf2022-02-14 15:38:30 -06001459 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)).Times(1);
1460 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)).Times(0);
1461
George Liu9464c422023-02-27 14:30:27 +08001462 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6d,
1463 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001464 MockedGPIOInterface* mockPresenceGPIO =
1465 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1466 // Always return 1 to indicate present.
1467 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001468 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001469 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001470 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1471 // for INPUT_HISTORY will check max_power_out to see if it is
1472 // old/unsupported power supply. Indicate good value, supported.
1473 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -05001474 .WillRepeatedly(Return("2000"));
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001475 // STATUS_WORD 0x0000 is powered on, no faults.
1476 PMBusExpectations expectations;
1477 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001478 // Call to analyze will trigger read of "in1_input" to check voltage.
1479 // Initial value would be 0, so this read updates it to non-zero.
1480 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1481 .Times(1)
1482 .WillOnce(Return("205100"));
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001483 psu.analyze();
1484 EXPECT_EQ(psu.hasFanFault(), false);
1485 // Turn fault on.
1486 expectations.statusWordValue = (status_word::FAN_FAULT);
1487 // STATUS_FANS_1_2 fault bit on (Fan 1 Fault)
1488 expectations.statusFans12Value = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001489 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1490 {
1491 setPMBusExpectations(mockPMBus, expectations);
1492 // Call to analyze will trigger read of "in1_input" to check voltage.
1493 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1494 .Times(1)
1495 .WillOnce(Return("205200"));
1496 psu.analyze();
1497 EXPECT_EQ(psu.hasFanFault(), x >= DEGLITCH_LIMIT);
1498 }
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001499 // Back to no fault bits on in STATUS_WORD
1500 expectations.statusWordValue = 0;
1501 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001502 // Call to analyze will trigger read of "in1_input" to check voltage.
1503 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1504 .Times(1)
1505 .WillOnce(Return("205300"));
Brandon Wyman7ee4d7e2021-11-19 20:48:23 +00001506 psu.analyze();
1507 EXPECT_EQ(psu.hasFanFault(), false);
1508}
1509
Brandon Wyman96893a42021-11-05 19:56:57 +00001510TEST_F(PowerSupplyTests, HasTempFault)
1511{
1512 auto bus = sdbusplus::bus::new_default();
1513
Matt Spinler0975eaf2022-02-14 15:38:30 -06001514 EXPECT_CALL(mockedUtil, setAvailable(_, _, true)).Times(1);
1515 EXPECT_CALL(mockedUtil, setAvailable(_, _, false)).Times(0);
1516
George Liu9464c422023-02-27 14:30:27 +08001517 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a,
1518 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Brandon Wyman96893a42021-11-05 19:56:57 +00001519 MockedGPIOInterface* mockPresenceGPIO =
1520 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1521 // Always return 1 to indicate present.
1522 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman96893a42021-11-05 19:56:57 +00001523 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001524 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001525 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1526 // for INPUT_HISTORY will check max_power_out to see if it is
1527 // old/unsupported power supply. Indicate good value, supported.
1528 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -05001529 .WillRepeatedly(Return("2000"));
Brandon Wyman96893a42021-11-05 19:56:57 +00001530 // STATUS_WORD 0x0000 is powered on, no faults.
1531 PMBusExpectations expectations;
1532 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001533 // Call to analyze will trigger read of "in1_input" to check voltage.
1534 // Initial value would be 0, so this read updates it to non-zero.
1535 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1536 .Times(1)
1537 .WillOnce(Return("206100"));
Brandon Wyman96893a42021-11-05 19:56:57 +00001538 psu.analyze();
1539 EXPECT_EQ(psu.hasTempFault(), false);
1540 // Turn fault on.
1541 expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
1542 // STATUS_TEMPERATURE fault bit on (OT Fault)
1543 expectations.statusTempValue = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001544 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1545 {
1546 setPMBusExpectations(mockPMBus, expectations);
1547 // Call to analyze will trigger read of "in1_input" to check voltage.
1548 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1549 .Times(1)
1550 .WillOnce(Return("206200"));
1551 psu.analyze();
1552 EXPECT_EQ(psu.hasTempFault(), x >= DEGLITCH_LIMIT);
1553 }
Brandon Wyman96893a42021-11-05 19:56:57 +00001554 // Back to no fault bits on in STATUS_WORD
1555 expectations.statusWordValue = 0;
1556 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001557 // Call to analyze will trigger read of "in1_input" to check voltage.
1558 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1559 .Times(1)
1560 .WillOnce(Return("206300"));
Brandon Wyman96893a42021-11-05 19:56:57 +00001561 psu.analyze();
1562 EXPECT_EQ(psu.hasTempFault(), false);
1563}
Brandon Wyman2916ea52021-11-06 03:31:18 +00001564
1565TEST_F(PowerSupplyTests, HasPgoodFault)
1566{
1567 auto bus = sdbusplus::bus::new_default();
1568
George Liu9464c422023-02-27 14:30:27 +08001569 PowerSupply psu{bus, PSUInventoryPath, 3, 0x6b,
1570 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Brandon Wyman2916ea52021-11-06 03:31:18 +00001571 MockedGPIOInterface* mockPresenceGPIO =
1572 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1573 // Always return 1 to indicate present.
1574 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001575 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman391a0692021-12-08 23:28:18 +00001576 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001577 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1578 // for INPUT_HISTORY will check max_power_out to see if it is
1579 // old/unsupported power supply. Indicate good value, supported.
1580 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -05001581 .WillRepeatedly(Return("2000"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001582 // STATUS_WORD 0x0000 is powered on, no faults.
1583 PMBusExpectations expectations;
1584 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001585 // Call to analyze will trigger read of "in1_input" to check voltage.
1586 // Initial value would be 0, so this read updates it to non-zero.
1587 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1588 .Times(1)
1589 .WillOnce(Return("207100"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001590 psu.analyze();
1591 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman391a0692021-12-08 23:28:18 +00001592 // Setup another expectation of no faults.
1593 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001594 // Call to analyze will trigger read of "in1_input" to check voltage.
1595 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1596 .Times(1)
1597 .WillOnce(Return("207200"));
1598 psu.analyze();
1599 EXPECT_EQ(psu.hasPgoodFault(), false);
1600 // Setup another expectation of no faults.
1601 setPMBusExpectations(mockPMBus, expectations);
1602 // Call to analyze will trigger read of "in1_input" to check voltage.
1603 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1604 .Times(1)
1605 .WillOnce(Return("207300"));
Brandon Wyman391a0692021-12-08 23:28:18 +00001606 psu.analyze();
1607 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman2916ea52021-11-06 03:31:18 +00001608 // Turn PGOOD# off (fault on).
1609 expectations.statusWordValue = (status_word::POWER_GOOD_NEGATED);
1610 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001611 // Call to analyze will trigger read of "in1_input" to check voltage.
1612 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1613 .Times(1)
1614 .WillOnce(Return("207400"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001615 psu.analyze();
Brandon Wyman6d469fd2022-06-15 16:58:21 +00001616 // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 1
Brandon Wyman06ca4592021-12-06 22:52:23 +00001617 EXPECT_EQ(psu.hasPgoodFault(), false);
1618 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001619 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1620 .Times(1)
1621 .WillOnce(Return("207500"));
Brandon Wyman06ca4592021-12-06 22:52:23 +00001622 psu.analyze();
Brandon Wyman6d469fd2022-06-15 16:58:21 +00001623 // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 2
Brandon Wyman06ca4592021-12-06 22:52:23 +00001624 EXPECT_EQ(psu.hasPgoodFault(), false);
1625 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001626 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1627 .Times(1)
1628 .WillOnce(Return("207600"));
Brandon Wyman06ca4592021-12-06 22:52:23 +00001629 psu.analyze();
Brandon Wyman6d469fd2022-06-15 16:58:21 +00001630 // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 3
1631 EXPECT_EQ(psu.hasPgoodFault(), false);
1632 setPMBusExpectations(mockPMBus, expectations);
1633 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1634 .Times(1)
1635 .WillOnce(Return("207700"));
1636 psu.analyze();
1637 // Expect false until reaches PGOOD_DEGLITCH_LIMIT @ 4
1638 EXPECT_EQ(psu.hasPgoodFault(), false);
1639 setPMBusExpectations(mockPMBus, expectations);
1640 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1641 .Times(1)
1642 .WillOnce(Return("207800"));
1643 psu.analyze();
1644 // Expect true. PGOOD_DEGLITCH_LIMIT @ 5
Brandon Wyman2916ea52021-11-06 03:31:18 +00001645 EXPECT_EQ(psu.hasPgoodFault(), true);
1646 // Back to no fault bits on in STATUS_WORD
1647 expectations.statusWordValue = 0;
1648 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001649 // Call to analyze will trigger read of "in1_input" to check voltage.
1650 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1651 .Times(1)
1652 .WillOnce(Return("207700"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001653 psu.analyze();
1654 EXPECT_EQ(psu.hasPgoodFault(), false);
Brandon Wyman82affd92021-11-24 19:12:49 +00001655
Brandon Wyman2916ea52021-11-06 03:31:18 +00001656 // Turn OFF bit on
1657 expectations.statusWordValue = (status_word::UNIT_IS_OFF);
1658 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001659 // Call to analyze will trigger read of "in1_input" to check voltage.
1660 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1661 .Times(1)
1662 .WillOnce(Return("208100"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001663 psu.analyze();
Brandon Wyman06ca4592021-12-06 22:52:23 +00001664 EXPECT_EQ(psu.hasPgoodFault(), false);
1665 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001666 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1667 .Times(1)
1668 .WillOnce(Return("208200"));
Brandon Wyman06ca4592021-12-06 22:52:23 +00001669 psu.analyze();
1670 EXPECT_EQ(psu.hasPgoodFault(), false);
1671 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001672 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1673 .Times(1)
1674 .WillOnce(Return("208300"));
Brandon Wyman06ca4592021-12-06 22:52:23 +00001675 psu.analyze();
Brandon Wyman6d469fd2022-06-15 16:58:21 +00001676 EXPECT_EQ(psu.hasPgoodFault(), false);
1677 setPMBusExpectations(mockPMBus, expectations);
1678 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1679 .Times(1)
1680 .WillOnce(Return("208400"));
1681 psu.analyze();
1682 EXPECT_EQ(psu.hasPgoodFault(), false);
1683 setPMBusExpectations(mockPMBus, expectations);
1684 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1685 .Times(1)
1686 .WillOnce(Return("208500"));
1687 psu.analyze();
Brandon Wyman2916ea52021-11-06 03:31:18 +00001688 EXPECT_EQ(psu.hasPgoodFault(), true);
1689 // Back to no fault bits on in STATUS_WORD
1690 expectations.statusWordValue = 0;
1691 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001692 // Call to analyze will trigger read of "in1_input" to check voltage.
1693 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1694 .Times(1)
Brandon Wyman6d469fd2022-06-15 16:58:21 +00001695 .WillOnce(Return("208000"));
Brandon Wyman2916ea52021-11-06 03:31:18 +00001696 psu.analyze();
1697 EXPECT_EQ(psu.hasPgoodFault(), false);
1698}
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001699
1700TEST_F(PowerSupplyTests, HasPSKillFault)
1701{
1702 auto bus = sdbusplus::bus::new_default();
George Liu9464c422023-02-27 14:30:27 +08001703 PowerSupply psu{bus, PSUInventoryPath, 4, 0x6d,
1704 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001705 MockedGPIOInterface* mockPresenceGPIO =
1706 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1707 // Always return 1 to indicate present.
1708 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001709 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman82affd92021-11-24 19:12:49 +00001710 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001711 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1712 // for INPUT_HISTORY will check max_power_out to see if it is
1713 // old/unsupported power supply. Indicate good value, supported.
1714 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -05001715 .WillRepeatedly(Return("2000"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001716 // STATUS_WORD 0x0000 is powered on, no faults.
1717 PMBusExpectations expectations;
1718 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001719 // Call to analyze will trigger read of "in1_input" to check voltage.
1720 // Initial value would be 0, so this read updates it to non-zero.
1721 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1722 .Times(1)
1723 .WillOnce(Return("208100"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001724 psu.analyze();
1725 EXPECT_EQ(psu.hasPSKillFault(), false);
1726 // Next return STATUS_WORD with MFR fault bit on.
1727 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1728 // STATUS_MFR_SPEFIC with bit(s) on.
1729 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001730
1731 // Deglitching faults, false until read the fault bits on up to the limit.
1732 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1733 {
1734 setPMBusExpectations(mockPMBus, expectations);
1735 // Call to analyze will trigger read of "in1_input" to check voltage.
1736 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1737 .Times(1)
1738 .WillOnce(Return("208200"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001739 if (x == DEGLITCH_LIMIT)
1740 {
1741 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1742 }
Brandon Wymanc2906f42021-12-21 20:14:56 +00001743 psu.analyze();
1744 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
1745 }
1746
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001747 // Back to no bits on in STATUS_WORD
1748 expectations.statusWordValue = 0;
1749 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001750 // Call to analyze will trigger read of "in1_input" to check voltage.
1751 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1752 .Times(1)
1753 .WillOnce(Return("208300"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001754 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001755 psu.analyze();
1756 EXPECT_EQ(psu.hasPSKillFault(), false);
1757 // Next return STATUS_WORD with MFR fault bit on.
1758 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1759 // STATUS_MFR_SPEFIC with bit 4 on.
1760 expectations.statusMFRValue = 0x10;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001761
1762 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1763 {
1764 setPMBusExpectations(mockPMBus, expectations);
1765 // Call to analyze will trigger read of "in1_input" to check voltage.
1766 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1767 .Times(1)
1768 .WillOnce(Return("208400"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001769 if (x == DEGLITCH_LIMIT)
1770 {
1771 EXPECT_CALL(mockedUtil, setAvailable(_, _, false));
1772 }
Brandon Wymanc2906f42021-12-21 20:14:56 +00001773 psu.analyze();
1774 EXPECT_EQ(psu.hasPSKillFault(), x >= DEGLITCH_LIMIT);
1775 }
1776
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001777 // Back to no bits on in STATUS_WORD
1778 expectations.statusWordValue = 0;
1779 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001780 // Call to analyze will trigger read of "in1_input" to check voltage.
1781 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1782 .Times(1)
1783 .WillOnce(Return("208500"));
Matt Spinler0975eaf2022-02-14 15:38:30 -06001784 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001785 psu.analyze();
1786 EXPECT_EQ(psu.hasPSKillFault(), false);
1787}
1788
1789TEST_F(PowerSupplyTests, HasPS12VcsFault)
1790{
1791 auto bus = sdbusplus::bus::new_default();
George Liu9464c422023-02-27 14:30:27 +08001792 PowerSupply psu{bus, PSUInventoryPath, 5, 0x6e,
1793 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001794 MockedGPIOInterface* mockPresenceGPIO =
1795 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1796 // Always return 1 to indicate present.
1797 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001798 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman82affd92021-11-24 19:12:49 +00001799 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001800 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1801 // for INPUT_HISTORY will check max_power_out to see if it is
1802 // old/unsupported power supply. Indicate good value, supported.
1803 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -05001804 .WillRepeatedly(Return("2000"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001805 // STATUS_WORD 0x0000 is powered on, no faults.
1806 PMBusExpectations expectations;
1807 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001808 // Call to analyze will trigger read of "in1_input" to check voltage.
1809 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1810 .Times(1)
1811 .WillOnce(Return("209100"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001812 psu.analyze();
1813 EXPECT_EQ(psu.hasPS12VcsFault(), false);
1814 // Next return STATUS_WORD with MFR fault bit on.
1815 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1816 // STATUS_MFR_SPEFIC with bit(s) on.
1817 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001818
1819 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1820 {
1821 setPMBusExpectations(mockPMBus, expectations);
1822 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1823 .Times(1)
1824 .WillOnce(Return("209200"));
1825 psu.analyze();
1826 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
1827 }
1828
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001829 // Back to no bits on in STATUS_WORD
1830 expectations.statusWordValue = 0;
1831 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001832 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1833 .Times(1)
1834 .WillOnce(Return("209300"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001835 psu.analyze();
1836 EXPECT_EQ(psu.hasPS12VcsFault(), false);
1837 // Next return STATUS_WORD with MFR fault bit on.
1838 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1839 // STATUS_MFR_SPEFIC with bit 6 on.
1840 expectations.statusMFRValue = 0x40;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001841
1842 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1843 {
1844 setPMBusExpectations(mockPMBus, expectations);
1845 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1846 .Times(1)
1847 .WillOnce(Return("209400"));
1848 psu.analyze();
1849 EXPECT_EQ(psu.hasPS12VcsFault(), x >= DEGLITCH_LIMIT);
1850 }
1851
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001852 // Back to no bits on in STATUS_WORD
1853 expectations.statusWordValue = 0;
1854 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001855 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1856 .Times(1)
1857 .WillOnce(Return("209500"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001858 psu.analyze();
1859 EXPECT_EQ(psu.hasPS12VcsFault(), false);
1860}
1861
1862TEST_F(PowerSupplyTests, HasPSCS12VFault)
1863{
1864 auto bus = sdbusplus::bus::new_default();
George Liu9464c422023-02-27 14:30:27 +08001865 PowerSupply psu{bus, PSUInventoryPath, 6, 0x6f,
1866 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001867 MockedGPIOInterface* mockPresenceGPIO =
1868 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1869 // Always return 1 to indicate present.
1870 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001871 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wyman82affd92021-11-24 19:12:49 +00001872 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001873 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
1874 // for INPUT_HISTORY will check max_power_out to see if it is
1875 // old/unsupported power supply. Indicate good value, supported.
1876 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -05001877 .WillRepeatedly(Return("2000"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001878 // STATUS_WORD 0x0000 is powered on, no faults.
1879 PMBusExpectations expectations;
1880 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001881 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1882 .Times(1)
1883 .WillOnce(Return("209100"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001884 psu.analyze();
1885 EXPECT_EQ(psu.hasPSCS12VFault(), false);
1886 // Next return STATUS_WORD with MFR fault bit on.
1887 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1888 // STATUS_MFR_SPEFIC with bit(s) on.
1889 expectations.statusMFRValue = 0xFF;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001890
1891 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1892 {
1893 setPMBusExpectations(mockPMBus, expectations);
1894 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1895 .Times(1)
1896 .WillOnce(Return("209200"));
1897 psu.analyze();
1898 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
1899 }
1900
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001901 // Back to no bits on in STATUS_WORD
1902 expectations.statusWordValue = 0;
1903 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001904 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1905 .Times(1)
1906 .WillOnce(Return("209300"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001907 psu.analyze();
1908 EXPECT_EQ(psu.hasPSCS12VFault(), false);
1909 // Next return STATUS_WORD with MFR fault bit on.
1910 expectations.statusWordValue = (status_word::MFR_SPECIFIC_FAULT);
1911 // STATUS_MFR_SPEFIC with bit 7 on.
1912 expectations.statusMFRValue = 0x80;
Brandon Wymanc2906f42021-12-21 20:14:56 +00001913
1914 for (auto x = 1; x <= DEGLITCH_LIMIT; x++)
1915 {
1916 setPMBusExpectations(mockPMBus, expectations);
1917 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1918 .Times(1)
1919 .WillOnce(Return("209400"));
1920 psu.analyze();
1921 EXPECT_EQ(psu.hasPSCS12VFault(), x >= DEGLITCH_LIMIT);
1922 }
1923
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001924 // Back to no bits on in STATUS_WORD
1925 expectations.statusWordValue = 0;
1926 setPMBusExpectations(mockPMBus, expectations);
Brandon Wyman82affd92021-11-24 19:12:49 +00001927 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1928 .Times(1)
1929 .WillOnce(Return("209500"));
Brandon Wyman39ea02b2021-11-23 23:22:23 +00001930 psu.analyze();
1931 EXPECT_EQ(psu.hasPSCS12VFault(), false);
1932}
Brandon Wymanc3324422022-03-24 20:30:57 +00001933
Matt Spinler592bd272023-08-30 11:00:01 -05001934TEST_F(PowerSupplyTests, PeakInputPowerSensor)
Brandon Wymanc3324422022-03-24 20:30:57 +00001935{
1936 auto bus = sdbusplus::bus::new_default();
1937 {
George Liu9464c422023-02-27 14:30:27 +08001938 PowerSupply psu{bus, PSUInventoryPath, 6, 0x6f,
1939 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Matt Spinler592bd272023-08-30 11:00:01 -05001940 EXPECT_EQ(psu.getPeakInputPower(), std::nullopt);
1941
Brandon Wymanc3324422022-03-24 20:30:57 +00001942 MockedGPIOInterface* mockPresenceGPIO =
1943 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Brandon Wymanae35ac52022-05-23 22:33:40 +00001944 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Brandon Wymanc3324422022-03-24 20:30:57 +00001945 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Matt Spinler592bd272023-08-30 11:00:01 -05001946
Brandon Wymanae35ac52022-05-23 22:33:40 +00001947 setMissingToPresentExpects(mockPMBus, mockedUtil);
1948 PMBusExpectations expectations;
1949 setPMBusExpectations(mockPMBus, expectations);
Matt Spinler592bd272023-08-30 11:00:01 -05001950
Brandon Wymanae35ac52022-05-23 22:33:40 +00001951 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
1952 .Times(1)
1953 .WillOnce(Return("206000"));
Brandon Wymanae35ac52022-05-23 22:33:40 +00001954 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Brandon Wymanae35ac52022-05-23 22:33:40 +00001955 .WillRepeatedly(Return("2000"));
Matt Spinler592bd272023-08-30 11:00:01 -05001956
Brandon Wymanc3324422022-03-24 20:30:57 +00001957 psu.analyze();
Matt Spinler592bd272023-08-30 11:00:01 -05001958 EXPECT_EQ(psu.getPeakInputPower().value_or(0), 213);
Brandon Wymanc3324422022-03-24 20:30:57 +00001959 }
Matt Spinler592bd272023-08-30 11:00:01 -05001960
1961 // Test that there is no peak power sensor on 1400W PSs
Brandon Wymanc3324422022-03-24 20:30:57 +00001962 {
George Liu9464c422023-02-27 14:30:27 +08001963 PowerSupply psu{bus, PSUInventoryPath, 3, 0x68,
1964 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Brandon Wymanae35ac52022-05-23 22:33:40 +00001965 MockedGPIOInterface* mockPresenceGPIO =
1966 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
1967 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Matt Spinler592bd272023-08-30 11:00:01 -05001968
Brandon Wymanae35ac52022-05-23 22:33:40 +00001969 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Matt Spinler592bd272023-08-30 11:00:01 -05001970
Brandon Wymanae35ac52022-05-23 22:33:40 +00001971 setMissingToPresentExpects(mockPMBus, mockedUtil);
Matt Spinler592bd272023-08-30 11:00:01 -05001972
Brandon Wymanae35ac52022-05-23 22:33:40 +00001973 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Brandon Wymanae35ac52022-05-23 22:33:40 +00001974 .WillRepeatedly(Return("30725"));
Matt Spinler592bd272023-08-30 11:00:01 -05001975
Brandon Wymanae35ac52022-05-23 22:33:40 +00001976 PMBusExpectations expectations;
1977 setPMBusExpectations(mockPMBus, expectations);
Matt Spinler592bd272023-08-30 11:00:01 -05001978
Brandon Wymanae35ac52022-05-23 22:33:40 +00001979 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
Matt Spinler592bd272023-08-30 11:00:01 -05001980 .WillRepeatedly(Return("206000"));
Brandon Wymanae35ac52022-05-23 22:33:40 +00001981 psu.analyze();
Matt Spinler592bd272023-08-30 11:00:01 -05001982
1983 EXPECT_EQ(psu.getPeakInputPower(), std::nullopt);
Brandon Wymanae35ac52022-05-23 22:33:40 +00001984 }
Matt Spinler592bd272023-08-30 11:00:01 -05001985
1986 // Test that IPSPS power supplies don't have peak power
Brandon Wymanae35ac52022-05-23 22:33:40 +00001987 {
George Liu9464c422023-02-27 14:30:27 +08001988 PowerSupply psu{bus, PSUInventoryPath, 11,
1989 0x58, "inspur-ipsps", PSUGPIOLineName,
1990 isPowerOn};
Matt Spinler592bd272023-08-30 11:00:01 -05001991
Brandon Wymanc3324422022-03-24 20:30:57 +00001992 MockedGPIOInterface* mockPresenceGPIO =
1993 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
Matt Spinler592bd272023-08-30 11:00:01 -05001994
Brandon Wymanae35ac52022-05-23 22:33:40 +00001995 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
Matt Spinler592bd272023-08-30 11:00:01 -05001996
Brandon Wymanc3324422022-03-24 20:30:57 +00001997 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
Matt Spinler592bd272023-08-30 11:00:01 -05001998
Brandon Wymanae35ac52022-05-23 22:33:40 +00001999 setMissingToPresentExpects(mockPMBus, mockedUtil);
2000 PMBusExpectations expectations;
2001 setPMBusExpectations(mockPMBus, expectations);
Matt Spinler592bd272023-08-30 11:00:01 -05002002
2003 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
2004 .WillRepeatedly(Return("206000"));
2005
2006 psu.analyze();
2007
2008 EXPECT_EQ(psu.getPeakInputPower(), std::nullopt);
2009 }
2010
2011 // Test that a bad response from the input_history command leads
2012 // to an NaN value.
2013 {
2014 PowerSupply psu{bus, PSUInventoryPath, 6, 0x6f,
2015 "ibm-cffps", PSUGPIOLineName, isPowerOn};
2016
2017 MockedGPIOInterface* mockPresenceGPIO =
2018 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
2019 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
2020
2021 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
2022
2023 setMissingToPresentExpects(mockPMBus, mockedUtil);
2024 PMBusExpectations expectations;
2025 setPMBusExpectations(mockPMBus, expectations);
2026
Brandon Wymanae35ac52022-05-23 22:33:40 +00002027 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
2028 .Times(1)
2029 .WillOnce(Return("206000"));
Matt Spinler592bd272023-08-30 11:00:01 -05002030 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
2031 .WillRepeatedly(Return("2000"));
Brandon Wymanc3324422022-03-24 20:30:57 +00002032
Matt Spinler592bd272023-08-30 11:00:01 -05002033 // Don't return the full 5 bytes.
2034 EXPECT_CALL(mockPMBus,
2035 readBinary(INPUT_HISTORY, Type::HwmonDeviceDebug, 5))
2036 .WillRepeatedly(Return(std::vector<uint8_t>{0x01, 0x5c}));
2037
2038 psu.analyze();
2039 EXPECT_THAT(psu.getPeakInputPower().value_or(0), IsNan());
2040 }
Brandon Wymanc3324422022-03-24 20:30:57 +00002041}
Brandon Wyman18a24d92022-04-19 22:48:34 +00002042
2043TEST_F(PowerSupplyTests, IsSyncHistoryRequired)
2044{
2045 auto bus = sdbusplus::bus::new_default();
George Liu9464c422023-02-27 14:30:27 +08002046 PowerSupply psu{bus, PSUInventoryPath, 8, 0x6f,
2047 "ibm-cffps", PSUGPIOLineName, isPowerOn};
Brandon Wyman18a24d92022-04-19 22:48:34 +00002048 EXPECT_EQ(psu.isSyncHistoryRequired(), false);
2049 MockedGPIOInterface* mockPresenceGPIO =
2050 static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
2051 // Always return 1 to indicate present.
2052 EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
2053 MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
2054 setMissingToPresentExpects(mockPMBus, mockedUtil);
Brandon Wymanae35ac52022-05-23 22:33:40 +00002055 // Missing/present will trigger attempt to setup INPUT_HISTORY. Setup
2056 // for INPUT_HISTORY will check max_power_out to see if it is
2057 // old/unsupported power supply. Indicate good value, supported.
2058 EXPECT_CALL(mockPMBus, readString(MFR_POUT_MAX, _))
Matt Spinler592bd272023-08-30 11:00:01 -05002059 .WillRepeatedly(Return("2000"));
Brandon Wyman18a24d92022-04-19 22:48:34 +00002060 PMBusExpectations expectations;
2061 setPMBusExpectations(mockPMBus, expectations);
2062 EXPECT_CALL(mockPMBus, readString(READ_VIN, _))
2063 .Times(1)
2064 .WillRepeatedly(Return("205000"));
2065 EXPECT_CALL(mockedUtil, setAvailable(_, _, true));
2066 psu.analyze();
Brandon Wyman18a24d92022-04-19 22:48:34 +00002067 // Missing -> Present requires history sync
2068 EXPECT_EQ(psu.isSyncHistoryRequired(), true);
2069 psu.clearSyncHistoryRequired();
2070 EXPECT_EQ(psu.isSyncHistoryRequired(), false);
2071}
Matt Spinler592bd272023-08-30 11:00:01 -05002072
2073TEST_F(PowerSupplyTests, TestLinearConversions)
2074{
2075 // Mantissa > 0, exponent = 0
2076 EXPECT_EQ(0, PowerSupply::linearToInteger(0));
2077 EXPECT_EQ(1, PowerSupply::linearToInteger(1));
2078 EXPECT_EQ(38, PowerSupply::linearToInteger(0x26));
2079 EXPECT_EQ(1023, PowerSupply::linearToInteger(0x3FF));
2080
2081 // Mantissa < 0, exponent = 0
2082 EXPECT_EQ(-1, PowerSupply::linearToInteger(0x7FF));
2083 EXPECT_EQ(-20, PowerSupply::linearToInteger(0x7EC));
2084 EXPECT_EQ(-769, PowerSupply::linearToInteger(0x4FF));
2085 EXPECT_EQ(-989, PowerSupply::linearToInteger(0x423));
2086 EXPECT_EQ(-1024, PowerSupply::linearToInteger(0x400));
2087
2088 // Mantissa >= 0, exponent > 0
2089 // M = 1, E = 2
2090 EXPECT_EQ(4, PowerSupply::linearToInteger(0x1001));
2091
2092 // M = 1000, E = 10
2093 EXPECT_EQ(1024000, PowerSupply::linearToInteger(0x53E8));
2094
2095 // M = 10, E = 15
2096 EXPECT_EQ(327680, PowerSupply::linearToInteger(0x780A));
2097
2098 // Mantissa >= 0, exponent < 0
2099 // M = 0, E = -1
2100 EXPECT_EQ(0, PowerSupply::linearToInteger(0xF800));
2101
2102 // M = 100, E = -2
2103 EXPECT_EQ(25, PowerSupply::linearToInteger(0xF064));
2104
2105 // Mantissa < 0, exponent < 0
2106 // M = -100, E = -1
2107 EXPECT_EQ(-50, PowerSupply::linearToInteger(0xFF9C));
2108
2109 // M = -1024, E = -7
2110 EXPECT_EQ(-8, PowerSupply::linearToInteger(0xCC00));
2111}