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