psu-ng: Add code to detect temperature fault
If the low byte of STATUS_WORD has bit 2 on/1, there is a temperature
fault or warning.
Tested:
Verify no error logged for temperature fault during normal operation
on real hardware.
Verify temperature fault error logged when simulated
over-temperature fault.
Change-Id: Ib5b0fe849699e72e517ea4d59a69bbb6de1e5283
Signed-off-by: Brandon Wyman <bjwyman@gmail.com>
diff --git a/phosphor-power-supply/test/power_supply_tests.cpp b/phosphor-power-supply/test/power_supply_tests.cpp
index c131621..7fb7d03 100644
--- a/phosphor-power-supply/test/power_supply_tests.cpp
+++ b/phosphor-power-supply/test/power_supply_tests.cpp
@@ -29,6 +29,7 @@
uint8_t statusMFRValue{0x00};
uint8_t statusCMLValue{0x00};
uint8_t statusVOUTValue{0x00};
+ uint8_t statusTempValue{0x00};
};
// Helper function to setup expectations for various STATUS_* commands
@@ -42,7 +43,8 @@
if (expectations.statusWordValue != 0)
{
// If fault bits are on in STATUS_WORD, there will also be a read of
- // STATUS_INPUT, STATUS_MFR, and STATUS_CML.
+ // STATUS_INPUT, STATUS_MFR, STATUS_CML, STATUS_VOUT (page 0), and
+ // STATUS_TEMPERATURE.
EXPECT_CALL(mockPMBus, read(STATUS_INPUT, _))
.Times(1)
.WillOnce(Return(expectations.statusInputValue));
@@ -59,6 +61,9 @@
EXPECT_CALL(mockPMBus, read("status0_vout", _))
.Times(1)
.WillOnce(Return(expectations.statusVOUTValue));
+ EXPECT_CALL(mockPMBus, read(STATUS_TEMPERATURE, _))
+ .Times(1)
+ .WillOnce(Return(expectations.statusTempValue));
}
}
@@ -141,6 +146,7 @@
EXPECT_EQ(psu->hasMFRFault(), false);
EXPECT_EQ(psu->hasVINUVFault(), false);
EXPECT_EQ(psu->hasVoutOVFault(), false);
+ EXPECT_EQ(psu->hasTempFault(), false);
}
catch (...)
{
@@ -186,6 +192,7 @@
EXPECT_EQ(psu.hasVINUVFault(), false);
EXPECT_EQ(psu.hasCommFault(), false);
EXPECT_EQ(psu.hasVoutOVFault(), false);
+ EXPECT_EQ(psu.hasTempFault(), false);
}
PowerSupply psu2{bus, PSUInventoryPath, 5, 0x6a, PSUGPIOLineName};
@@ -218,8 +225,10 @@
EXPECT_EQ(psu2.hasVINUVFault(), false);
EXPECT_EQ(psu2.hasCommFault(), false);
EXPECT_EQ(psu2.hasVoutOVFault(), false);
+ EXPECT_EQ(psu2.hasTempFault(), false);
// Update expectations for STATUS_WORD input fault/warn
+ // STATUS_INPUT fault bits ... on.
expectations.statusWordValue = (status_word::INPUT_FAULT_WARN);
expectations.statusInputValue = 0x38;
setPMBusExpectations(mockPMBus, expectations);
@@ -231,6 +240,7 @@
EXPECT_EQ(psu2.hasVINUVFault(), false);
EXPECT_EQ(psu2.hasCommFault(), false);
EXPECT_EQ(psu2.hasVoutOVFault(), false);
+ EXPECT_EQ(psu2.hasTempFault(), false);
}
// STATUS_WORD INPUT/UV fault.
@@ -253,6 +263,7 @@
EXPECT_EQ(psu2.hasVINUVFault(), true);
EXPECT_EQ(psu2.hasCommFault(), false);
EXPECT_EQ(psu2.hasVoutOVFault(), false);
+ EXPECT_EQ(psu2.hasTempFault(), false);
}
// STATUS_WORD MFR fault.
@@ -274,9 +285,10 @@
EXPECT_EQ(psu2.hasVINUVFault(), false);
EXPECT_EQ(psu2.hasCommFault(), false);
EXPECT_EQ(psu2.hasVoutOVFault(), false);
+ EXPECT_EQ(psu2.hasTempFault(), false);
}
- // Ignore Temperature fault.
+ // Temperature fault.
{
// First STATUS_WORD with no bits set, then with temperature fault.
PMBusExpectations expectations;
@@ -284,17 +296,18 @@
psu2.analyze();
// STATUS_WORD with temperature fault bit on.
expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
- // STATUS_INPUT, STATUS_MFR, STATUS_CML, and STATUS_VOUT fault bits ...
- // don't care (defaults).
+ // STATUS_TEMPERATURE with fault bit(s) on.
+ expectations.statusTempValue = 0x10;
setPMBusExpectations(mockPMBus, expectations);
psu2.analyze();
EXPECT_EQ(psu2.isPresent(), true);
- EXPECT_EQ(psu2.isFaulted(), false);
+ EXPECT_EQ(psu2.isFaulted(), true);
EXPECT_EQ(psu2.hasInputFault(), false);
EXPECT_EQ(psu2.hasMFRFault(), false);
EXPECT_EQ(psu2.hasVINUVFault(), false);
EXPECT_EQ(psu2.hasCommFault(), false);
EXPECT_EQ(psu2.hasVoutOVFault(), false);
+ EXPECT_EQ(psu2.hasTempFault(), true);
}
// CML fault
@@ -316,6 +329,7 @@
EXPECT_EQ(psu2.hasVINUVFault(), false);
EXPECT_EQ(psu2.hasCommFault(), true);
EXPECT_EQ(psu2.hasVoutOVFault(), false);
+ EXPECT_EQ(psu2.hasTempFault(), false);
}
// VOUT_OV_FAULT fault
@@ -329,6 +343,7 @@
((status_word::VOUT_FAULT) | (status_word::VOUT_OV_FAULT));
// Turn on STATUS_VOUT fault bit(s)
expectations.statusVOUTValue = 0xA0;
+ // STATUS_TEMPERATURE don't care (default)
setPMBusExpectations(mockPMBus, expectations);
psu2.analyze();
EXPECT_EQ(psu2.isPresent(), true);
@@ -338,6 +353,7 @@
EXPECT_EQ(psu2.hasVINUVFault(), false);
EXPECT_EQ(psu2.hasCommFault(), false);
EXPECT_EQ(psu2.hasVoutOVFault(), true);
+ EXPECT_EQ(psu2.hasTempFault(), false);
}
// Ignore fan fault
@@ -356,6 +372,7 @@
EXPECT_EQ(psu2.hasVINUVFault(), false);
EXPECT_EQ(psu2.hasCommFault(), false);
EXPECT_EQ(psu2.hasVoutOVFault(), false);
+ EXPECT_EQ(psu2.hasTempFault(), false);
}
// TODO: ReadFailure
}
@@ -428,6 +445,7 @@
EXPECT_EQ(psu.hasVINUVFault(), false);
EXPECT_EQ(psu.hasCommFault(), false);
EXPECT_EQ(psu.hasVoutOVFault(), false);
+ EXPECT_EQ(psu.hasTempFault(), false);
// STATUS_WORD with fault bits galore!
expectations.statusWordValue = 0xFFFF;
@@ -439,6 +457,8 @@
expectations.statusCMLValue = 0xFF;
// STATUS_VOUT with bits on.
expectations.statusVOUTValue = 0xFF;
+ // STATUS_TEMPERATURE with bits on.
+ expectations.statusTempValue = 0xFF;
setPMBusExpectations(mockPMBus, expectations);
psu.analyze();
EXPECT_EQ(psu.isPresent(), true);
@@ -448,6 +468,7 @@
EXPECT_EQ(psu.hasVINUVFault(), true);
EXPECT_EQ(psu.hasCommFault(), true);
EXPECT_EQ(psu.hasVoutOVFault(), true);
+ EXPECT_EQ(psu.hasTempFault(), true);
EXPECT_CALL(mockPMBus, read("in1_input", _))
.Times(1)
.WillOnce(Return(209000));
@@ -459,6 +480,7 @@
EXPECT_EQ(psu.hasVINUVFault(), false);
EXPECT_EQ(psu.hasCommFault(), false);
EXPECT_EQ(psu.hasVoutOVFault(), false);
+ EXPECT_EQ(psu.hasTempFault(), false);
// TODO: Faults clear on missing/present?
}
@@ -548,6 +570,8 @@
expectations.statusCMLValue = 0xFF;
// STATUS_VOUT with fault bits on.
expectations.statusVOUTValue = 0xFF;
+ // STATUS_TEMPERATURE with fault bits on.
+ expectations.statusTempValue = 0xFF;
setPMBusExpectations(mockPMBus, expectations);
psu.analyze();
EXPECT_EQ(psu.isFaulted(), true);
@@ -669,6 +693,7 @@
expectations.statusWordValue = (status_word::VOUT_OV_FAULT);
// STATUS_VOUT fault bit(s)
expectations.statusVOUTValue = 0x80;
+ // STATUS_TEMPERATURE default.
setPMBusExpectations(mockPMBus, expectations);
psu.analyze();
EXPECT_EQ(psu.hasVoutOVFault(), true);
@@ -678,3 +703,34 @@
psu.analyze();
EXPECT_EQ(psu.hasVoutOVFault(), false);
}
+
+TEST_F(PowerSupplyTests, HasTempFault)
+{
+ auto bus = sdbusplus::bus::new_default();
+
+ PowerSupply psu{bus, PSUInventoryPath, 3, 0x6a, PSUGPIOLineName};
+ MockedGPIOInterface* mockPresenceGPIO =
+ static_cast<MockedGPIOInterface*>(psu.getPresenceGPIO());
+ // Always return 1 to indicate present.
+ EXPECT_CALL(*mockPresenceGPIO, read()).WillRepeatedly(Return(1));
+ psu.analyze();
+ MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
+ EXPECT_EQ(psu.hasTempFault(), false);
+ // STATUS_WORD 0x0000 is powered on, no faults.
+ PMBusExpectations expectations;
+ setPMBusExpectations(mockPMBus, expectations);
+ psu.analyze();
+ EXPECT_EQ(psu.hasTempFault(), false);
+ // Turn fault on.
+ expectations.statusWordValue = (status_word::TEMPERATURE_FAULT_WARN);
+ // STATUS_TEMPERATURE fault bit on (OT Fault)
+ expectations.statusTempValue = 0x80;
+ setPMBusExpectations(mockPMBus, expectations);
+ psu.analyze();
+ EXPECT_EQ(psu.hasTempFault(), true);
+ // Back to no fault bits on in STATUS_WORD
+ expectations.statusWordValue = 0;
+ setPMBusExpectations(mockPMBus, expectations);
+ psu.analyze();
+ EXPECT_EQ(psu.hasTempFault(), false);
+}