blob: b42dae5180509745011a94608d6e3fac343c45d2 [file] [log] [blame]
Shawn McCarneyfec38332024-05-02 13:58:56 -05001/**
2 * Copyright © 2024 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "mock_pmbus.hpp"
18#include "mock_services.hpp"
19#include "pmbus.hpp"
20#include "rail.hpp"
21#include "services.hpp"
22#include "ucd90320_device.hpp"
23
24#include <cstdint>
25#include <map>
26#include <memory>
27#include <optional>
28#include <string>
29#include <utility>
30#include <vector>
31
32#include <gmock/gmock.h>
33#include <gtest/gtest.h>
34
35using namespace phosphor::power::sequencer;
36using namespace phosphor::pmbus;
37
38using ::testing::Return;
39
40/**
41 * Creates a Rail object that checks for a pgood fault using a GPIO.
42 *
43 * @param name Unique name for the rail
44 * @param gpio GPIO line to read to determine the pgood status of the rail
45 * @return Rail object
46 */
47static std::unique_ptr<Rail> createRail(const std::string& name,
48 unsigned int gpioLine)
49{
50 std::optional<std::string> presence{};
51 std::optional<uint8_t> page{};
52 bool isPowerSupplyRail{false};
53 bool checkStatusVout{false};
54 bool compareVoltageToLimit{false};
55 bool activeLow{false};
56 std::optional<GPIO> gpio{GPIO{gpioLine, activeLow}};
57 return std::make_unique<Rail>(name, presence, page, isPowerSupplyRail,
58 checkStatusVout, compareVoltageToLimit, gpio);
59}
60
61TEST(UCD90320DeviceTests, Constructor)
62{
63 MockServices services;
64
Shawn McCarney31234452025-10-28 12:32:05 -050065 uint8_t bus{3};
66 uint16_t address{0x72};
Shawn McCarneyfe536672025-10-29 12:44:08 -050067 std::string powerControlGPIOName{"power-chassis-control"};
68 std::string powerGoodGPIOName{"power-chassis-good"};
Shawn McCarneyfec38332024-05-02 13:58:56 -050069 std::vector<std::unique_ptr<Rail>> rails;
70 rails.emplace_back(createRail("VDD", 5));
71 rails.emplace_back(createRail("VIO", 7));
Shawn McCarneyfe536672025-10-29 12:44:08 -050072 UCD90320Device device{bus,
73 address,
74 powerControlGPIOName,
75 powerGoodGPIOName,
76 std::move(rails),
77 services};
Shawn McCarneyfec38332024-05-02 13:58:56 -050078
79 EXPECT_EQ(device.getName(), "UCD90320");
Shawn McCarney31234452025-10-28 12:32:05 -050080 EXPECT_EQ(device.getBus(), bus);
81 EXPECT_EQ(device.getAddress(), address);
Shawn McCarneyfe536672025-10-29 12:44:08 -050082 EXPECT_EQ(device.getPowerControlGPIOName(), powerControlGPIOName);
83 EXPECT_EQ(device.getPowerGoodGPIOName(), powerGoodGPIOName);
Shawn McCarneyfec38332024-05-02 13:58:56 -050084 EXPECT_EQ(device.getRails().size(), 2);
85 EXPECT_EQ(device.getRails()[0]->getName(), "VDD");
86 EXPECT_EQ(device.getRails()[1]->getName(), "VIO");
Shawn McCarneyfec38332024-05-02 13:58:56 -050087 EXPECT_EQ(device.getDriverName(), "ucd9000");
88 EXPECT_EQ(device.getInstance(), 0);
89 EXPECT_NE(&(device.getPMBusInterface()), nullptr);
90}
91
92TEST(UCD90320DeviceTests, StoreGPIOValues)
93{
94 // This is a protected method and cannot be called directly from a gtest.
95 // Call findPgoodFault() which calls storeGPIOValues().
96
97 // Test where works
98 {
99 std::vector<int> gpioValues{
100 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, // MAR01-12
101 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, // MAR13-24
102 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, // EN1-12
103 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, // EN13-24
104 1, 1, 0, 0, 1, 1, 1, 0, // EN25-32
105 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, // LGP01-12
106 1, 1, 0, 0, // LGP13-16
107 1, 0, 0, 1, 1, 1, 0, 0, // DMON1-8
108 1, 0, 0, 1 // GPIO1-4
109 };
110
111 MockServices services;
112 EXPECT_CALL(services, getGPIOValues("ucd90320"))
113 .Times(1)
114 .WillOnce(Return(gpioValues));
115 EXPECT_CALL(services, logInfoMsg("Device UCD90320 GPIO values:"))
116 .Times(1);
117 EXPECT_CALL(services, logInfoMsg("MAR01-24: ["
118 "1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, "
119 "1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0]"))
120 .Times(1);
121 EXPECT_CALL(services, logInfoMsg("EN1-32: ["
122 "1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, "
123 "1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, "
124 "1, 1, 0, 0, 1, 1, 1, 0]"))
125 .Times(1);
126 EXPECT_CALL(services, logInfoMsg("LGP01-16: ["
127 "1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, "
128 "1, 1, 0, 0]"))
129 .Times(1);
130 EXPECT_CALL(services, logInfoMsg("DMON1-8: ["
131 "1, 0, 0, 1, 1, 1, 0, 0]"))
132 .Times(1);
133 EXPECT_CALL(services, logInfoMsg("GPIO1-4: ["
134 "1, 0, 0, 1]"))
135 .Times(1);
136 EXPECT_CALL(services,
137 logInfoMsg("Device UCD90320 MFR_STATUS: 0x123456789abc"))
138 .Times(1);
139 EXPECT_CALL(
140 services,
141 logErrorMsg(
142 "Pgood fault found in rail monitored by device UCD90320"))
143 .Times(1);
144 EXPECT_CALL(services, logErrorMsg("Pgood fault detected in rail VDD"))
145 .Times(1);
146 EXPECT_CALL(
147 services,
148 logErrorMsg(
149 "Rail VDD pgood GPIO line offset 2 has inactive value 0"))
150 .Times(1);
151
Shawn McCarneyfec38332024-05-02 13:58:56 -0500152 uint8_t bus{3};
153 uint16_t address{0x72};
Shawn McCarneyfe536672025-10-29 12:44:08 -0500154 std::string powerControlGPIOName{"power-chassis-control"};
155 std::string powerGoodGPIOName{"power-chassis-good"};
Shawn McCarney31234452025-10-28 12:32:05 -0500156 std::vector<std::unique_ptr<Rail>> rails;
157 rails.emplace_back(createRail("VDD", 2));
Shawn McCarneyfe536672025-10-29 12:44:08 -0500158 UCD90320Device device{bus,
159 address,
160 powerControlGPIOName,
161 powerGoodGPIOName,
162 std::move(rails),
163 services};
Shawn McCarneyfec38332024-05-02 13:58:56 -0500164
165 MockPMBus& pmbus = static_cast<MockPMBus&>(device.getPMBusInterface());
166 EXPECT_CALL(pmbus, getPath(Type::Hwmon))
167 .Times(1)
168 .WillOnce(Return("/tmp"));
169 EXPECT_CALL(pmbus, read("mfr_status", Type::HwmonDeviceDebug, true))
170 .Times(1)
171 .WillOnce(Return(0x123456789abcull));
172
173 // Call findPgoodFault() which calls storeGPIOValues()
174 std::string powerSupplyError{};
175 std::map<std::string, std::string> additionalData{};
Patrick Williamsf5402192024-08-16 15:20:53 -0400176 std::string error =
177 device.findPgoodFault(services, powerSupplyError, additionalData);
Shawn McCarneyfec38332024-05-02 13:58:56 -0500178 EXPECT_EQ(error,
179 "xyz.openbmc_project.Power.Error.PowerSequencerVoltageFault");
180 EXPECT_EQ(additionalData.size(), 10);
181 EXPECT_EQ(additionalData["MFR_STATUS"], "0x123456789abc");
182 EXPECT_EQ(additionalData["DEVICE_NAME"], "UCD90320");
183 EXPECT_EQ(additionalData["MAR01_24_GPIO_VALUES"],
184 "[1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, "
185 "1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0]");
186 EXPECT_EQ(additionalData["EN1_32_GPIO_VALUES"],
187 "[1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, "
188 "1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, "
189 "1, 1, 0, 0, 1, 1, 1, 0]");
190 EXPECT_EQ(additionalData["LGP01_16_GPIO_VALUES"],
191 "[1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, "
192 "1, 1, 0, 0]");
193 EXPECT_EQ(additionalData["DMON1_8_GPIO_VALUES"],
194 "[1, 0, 0, 1, 1, 1, 0, 0]");
195 EXPECT_EQ(additionalData["GPIO1_4_GPIO_VALUES"], "[1, 0, 0, 1]");
196 EXPECT_EQ(additionalData["RAIL_NAME"], "VDD");
197 EXPECT_EQ(additionalData["GPIO_LINE"], "2");
198 EXPECT_EQ(additionalData["GPIO_VALUE"], "0");
199 }
200
201 // Test where there are the wrong number of GPIOs (83 instead of 84)
202 {
203 std::vector<int> gpioValues{
204 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, // MAR01-12
205 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, // MAR13-24
206 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, // EN1-12
207 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, // EN13-24
208 1, 1, 0, 0, 1, 1, 1, 0, // EN25-32
209 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, // LGP01-12
210 1, 1, 0, 0, // LGP13-16
211 1, 0, 0, 1, 1, 1, 0, 0, // DMON1-8
212 1, 0, 0 // GPIO1-4 (1 missing)
213 };
214
215 MockServices services;
216 EXPECT_CALL(services, getGPIOValues("ucd90320"))
217 .Times(1)
218 .WillOnce(Return(gpioValues));
Patrick Williamsf5402192024-08-16 15:20:53 -0400219 EXPECT_CALL(services,
220 logInfoMsg("Device UCD90320 GPIO values: ["
221 "1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, "
222 "1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, "
223 "1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, "
224 "1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, "
225 "1, 1, 0, 0, 1, 1, 1, 0, "
226 "1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, "
227 "1, 1, 0, 0, "
228 "1, 0, 0, 1, 1, 1, 0, 0, "
229 "1, 0, 0]"))
Shawn McCarneyfec38332024-05-02 13:58:56 -0500230 .Times(1);
231 EXPECT_CALL(services,
232 logInfoMsg("Device UCD90320 MFR_STATUS: 0x123456789abc"))
233 .Times(1);
234 EXPECT_CALL(
235 services,
236 logErrorMsg(
237 "Pgood fault found in rail monitored by device UCD90320"))
238 .Times(1);
239 EXPECT_CALL(services, logErrorMsg("Pgood fault detected in rail VDD"))
240 .Times(1);
241 EXPECT_CALL(
242 services,
243 logErrorMsg(
244 "Rail VDD pgood GPIO line offset 2 has inactive value 0"))
245 .Times(1);
246
Shawn McCarneyfec38332024-05-02 13:58:56 -0500247 uint8_t bus{3};
248 uint16_t address{0x72};
Shawn McCarneyfe536672025-10-29 12:44:08 -0500249 std::string powerControlGPIOName{"power-chassis-control"};
250 std::string powerGoodGPIOName{"power-chassis-good"};
Shawn McCarney31234452025-10-28 12:32:05 -0500251 std::vector<std::unique_ptr<Rail>> rails;
252 rails.emplace_back(createRail("VDD", 2));
Shawn McCarneyfe536672025-10-29 12:44:08 -0500253 UCD90320Device device{bus,
254 address,
255 powerControlGPIOName,
256 powerGoodGPIOName,
257 std::move(rails),
258 services};
Shawn McCarneyfec38332024-05-02 13:58:56 -0500259
260 MockPMBus& pmbus = static_cast<MockPMBus&>(device.getPMBusInterface());
261 EXPECT_CALL(pmbus, getPath(Type::Hwmon))
262 .Times(1)
263 .WillOnce(Return("/tmp"));
264 EXPECT_CALL(pmbus, read("mfr_status", Type::HwmonDeviceDebug, true))
265 .Times(1)
266 .WillOnce(Return(0x123456789abcull));
267
268 // Call findPgoodFault() which calls storeGPIOValues()
269 std::string powerSupplyError{};
270 std::map<std::string, std::string> additionalData{};
Patrick Williamsf5402192024-08-16 15:20:53 -0400271 std::string error =
272 device.findPgoodFault(services, powerSupplyError, additionalData);
Shawn McCarneyfec38332024-05-02 13:58:56 -0500273 EXPECT_EQ(error,
274 "xyz.openbmc_project.Power.Error.PowerSequencerVoltageFault");
275 EXPECT_EQ(additionalData.size(), 6);
276 EXPECT_EQ(additionalData["MFR_STATUS"], "0x123456789abc");
277 EXPECT_EQ(additionalData["DEVICE_NAME"], "UCD90320");
278 EXPECT_EQ(additionalData["GPIO_VALUES"],
279 "[1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, "
280 "1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, "
281 "1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, "
282 "1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, "
283 "1, 1, 0, 0, 1, 1, 1, 0, "
284 "1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, "
285 "1, 1, 0, 0, "
286 "1, 0, 0, 1, 1, 1, 0, 0, "
287 "1, 0, 0]");
288 EXPECT_EQ(additionalData["RAIL_NAME"], "VDD");
289 EXPECT_EQ(additionalData["GPIO_LINE"], "2");
290 EXPECT_EQ(additionalData["GPIO_VALUE"], "0");
291 }
292}