blob: 057c4c8ac7ffe46a50f4f241dbe1575564f4f5cf [file] [log] [blame]
Shawn McCarney73944672025-11-26 16:37:31 -06001/**
2 * Copyright © 2025 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#pragma once
17
18#include "gpio.hpp"
19#include "power_sequencer_device.hpp"
20#include "rail.hpp"
21#include "services.hpp"
22
23#include <cstdint>
24#include <memory>
Shawn McCarney77c1c262025-12-02 16:26:53 -060025#include <stdexcept>
Shawn McCarney73944672025-11-26 16:37:31 -060026#include <string>
27#include <utility>
28#include <vector>
29
30namespace phosphor::power::sequencer
31{
32
33/**
34 * @class BasicDevice
35 *
36 * PowerSequencerDevice sub-class that implements basic functionality.
37 *
38 * BasicDevice implements the following:
39 * - Data members and methods for the power sequencer properties from the JSON
40 * configuration file.
41 * - Methods that utilize the named GPIOs, such as powerOn() and getPowerGood().
42 */
43class BasicDevice : public PowerSequencerDevice
44{
45 public:
46 BasicDevice() = delete;
47 BasicDevice(const BasicDevice&) = delete;
48 BasicDevice(BasicDevice&&) = delete;
49 BasicDevice& operator=(const BasicDevice&) = delete;
50 BasicDevice& operator=(BasicDevice&&) = delete;
Shawn McCarney73944672025-11-26 16:37:31 -060051
52 /**
53 * Constructor.
54 *
55 * Throws an exception if an error occurs during initialization.
56 *
57 * @param name device name
58 * @param bus I2C bus for the device
59 * @param address I2C address for the device
60 * @param powerControlGPIOName name of the GPIO that turns this device on
61 * and off
62 * @param powerGoodGPIOName name of the GPIO that reads the power good
63 * signal from this device
64 * @param rails voltage rails that are enabled and monitored by this device
Shawn McCarney73944672025-11-26 16:37:31 -060065 */
66 explicit BasicDevice(const std::string& name, uint8_t bus, uint16_t address,
67 const std::string& powerControlGPIOName,
68 const std::string& powerGoodGPIOName,
Shawn McCarney77c1c262025-12-02 16:26:53 -060069 std::vector<std::unique_ptr<Rail>> rails) :
Shawn McCarney73944672025-11-26 16:37:31 -060070 name{name}, bus{bus}, address{address},
71 powerControlGPIOName{powerControlGPIOName},
72 powerGoodGPIOName{powerGoodGPIOName}, rails{std::move(rails)}
Shawn McCarney77c1c262025-12-02 16:26:53 -060073 {}
Shawn McCarney73944672025-11-26 16:37:31 -060074
Shawn McCarney77c1c262025-12-02 16:26:53 -060075 /**
76 * Destructor.
77 *
78 * Closes the device if it is open.
79 */
80 virtual ~BasicDevice()
81 {
82 if (isOpen())
83 {
84 // Destructors must not throw exceptions
85 closeWithoutException();
86 }
Shawn McCarney73944672025-11-26 16:37:31 -060087 }
88
89 /** @copydoc PowerSequencerDevice::getName() */
90 virtual const std::string& getName() const override
91 {
92 return name;
93 }
94
95 /** @copydoc PowerSequencerDevice::getBus() */
96 virtual uint8_t getBus() const override
97 {
98 return bus;
99 }
100
101 /** @copydoc PowerSequencerDevice::getAddress() */
102 virtual uint16_t getAddress() const override
103 {
104 return address;
105 }
106
107 /** @copydoc PowerSequencerDevice::getPowerControlGPIOName() */
108 virtual const std::string& getPowerControlGPIOName() const override
109 {
110 return powerControlGPIOName;
111 }
112
113 /** @copydoc PowerSequencerDevice::getPowerGoodGPIOName() */
114 virtual const std::string& getPowerGoodGPIOName() const override
115 {
116 return powerGoodGPIOName;
117 }
118
119 /** @copydoc PowerSequencerDevice::getRails() */
120 virtual const std::vector<std::unique_ptr<Rail>>& getRails() const override
121 {
122 return rails;
123 }
124
Shawn McCarney77c1c262025-12-02 16:26:53 -0600125 /** @copydoc PowerSequencerDevice::open() */
126 virtual void open(Services& services) override
127 {
128 if (!isOpen())
129 {
130 powerControlGPIO = services.createGPIO(powerControlGPIOName);
131
132 powerGoodGPIO = services.createGPIO(powerGoodGPIOName);
133 powerGoodGPIO->requestRead();
134
135 isDeviceOpen = true;
136 }
137 }
138
139 /** @copydoc PowerSequencerDevice::isOpen() */
140 virtual bool isOpen() const override
141 {
142 return isDeviceOpen;
143 }
144
145 /** @copydoc PowerSequencerDevice::close() */
146 virtual void close() override
147 {
148 if (isOpen())
149 {
150 powerControlGPIO.reset();
151
152 // Verify pointer valid in case close() threw exception previously
153 if (powerGoodGPIO)
154 {
155 powerGoodGPIO->release();
156 }
157 powerGoodGPIO.reset();
158
159 isDeviceOpen = false;
160 }
161 }
162
163 /** @copydoc PowerSequencerDevice::closeWithoutException() */
164 virtual void closeWithoutException() noexcept override
165 {
166 try
167 {
168 close();
169 }
170 catch (...)
171 {}
172 }
173
Shawn McCarney73944672025-11-26 16:37:31 -0600174 /** @copydoc PowerSequencerDevice::getPowerControlGPIO() */
175 virtual GPIO& getPowerControlGPIO() override
176 {
Shawn McCarney77c1c262025-12-02 16:26:53 -0600177 verifyIsOpen();
Shawn McCarney73944672025-11-26 16:37:31 -0600178 return *powerControlGPIO;
179 }
180
181 /** @copydoc PowerSequencerDevice::getPowerGoodGPIO() */
182 virtual GPIO& getPowerGoodGPIO() override
183 {
Shawn McCarney77c1c262025-12-02 16:26:53 -0600184 verifyIsOpen();
Shawn McCarney73944672025-11-26 16:37:31 -0600185 return *powerGoodGPIO;
186 }
187
188 /** @copydoc PowerSequencerDevice::powerOn() */
189 virtual void powerOn() override
190 {
Shawn McCarney77c1c262025-12-02 16:26:53 -0600191 verifyIsOpen();
Shawn McCarney73944672025-11-26 16:37:31 -0600192 powerControlGPIO->requestWrite(1);
193 powerControlGPIO->setValue(1);
194 powerControlGPIO->release();
195 }
196
197 /** @copydoc PowerSequencerDevice::powerOff() */
198 virtual void powerOff() override
199 {
Shawn McCarney77c1c262025-12-02 16:26:53 -0600200 verifyIsOpen();
Shawn McCarney73944672025-11-26 16:37:31 -0600201 powerControlGPIO->requestWrite(0);
202 powerControlGPIO->setValue(0);
203 powerControlGPIO->release();
204 }
205
206 /** @copydoc PowerSequencerDevice::getPowerGood() */
207 virtual bool getPowerGood() override
208 {
Shawn McCarney77c1c262025-12-02 16:26:53 -0600209 verifyIsOpen();
Shawn McCarney73944672025-11-26 16:37:31 -0600210 return (powerGoodGPIO->getValue() == 1);
211 }
212
213 protected:
214 /**
Shawn McCarney77c1c262025-12-02 16:26:53 -0600215 * Verifies that this device is open.
216 *
217 * Throws an exception if device is not open.
218 */
219 virtual void verifyIsOpen()
220 {
221 if (!isOpen())
222 {
223 throw std::runtime_error{"Device not open: " + name};
224 }
225 }
226
227 /**
Shawn McCarney73944672025-11-26 16:37:31 -0600228 * Device name.
229 */
230 std::string name{};
231
232 /**
233 * I2C bus for the device.
234 */
235 uint8_t bus;
236
237 /**
238 * I2C address for the device.
239 */
240 uint16_t address;
241
242 /**
243 * Name of the GPIO that turns this device on and off.
244 */
245 std::string powerControlGPIOName{};
246
247 /**
248 * Name of the GPIO that reads the power good signal from this device.
249 */
250 std::string powerGoodGPIOName{};
251
252 /**
253 * Voltage rails that are enabled and monitored by this device.
254 */
255 std::vector<std::unique_ptr<Rail>> rails{};
256
257 /**
Shawn McCarney77c1c262025-12-02 16:26:53 -0600258 * Specifies whether this device is open.
259 */
260 bool isDeviceOpen{false};
261
262 /**
Shawn McCarney73944672025-11-26 16:37:31 -0600263 * GPIO that turns this device on and off.
264 */
265 std::unique_ptr<GPIO> powerControlGPIO{};
266
267 /**
268 * GPIO that reads the power good signal from this device.
269 */
270 std::unique_ptr<GPIO> powerGoodGPIO{};
271};
272
273} // namespace phosphor::power::sequencer