xref: /openbmc/phosphor-power/phosphor-power-sequencer/src/gpio.hpp (revision 77c1c26ff2a90bfbbd80eb6d35366f49ce70eb87)
1 /**
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 <gpiod.hpp>
19 
20 #include <string>
21 
22 namespace phosphor::power::sequencer
23 {
24 
25 /**
26  * @class GPIO
27  *
28  * Abstract base class for a General-Purpose Input/Output pin.
29  */
30 class GPIO
31 {
32   public:
33     GPIO() = default;
34     GPIO(const GPIO&) = delete;
35     GPIO(GPIO&&) = delete;
36     GPIO& operator=(const GPIO&) = delete;
37     GPIO& operator=(GPIO&&) = delete;
38     virtual ~GPIO() = default;
39 
40     /**
41      * Request ownership of the GPIO for reading.
42      *
43      * Throws an exception if an error occurs.
44      *
45      * This is required before getting the GPIO value.
46      */
47     virtual void requestRead() = 0;
48 
49     /**
50      * Request ownership of the GPIO for writing.
51      *
52      * Throws an exception if an error occurs.
53      *
54      * This is required before setting the GPIO value.
55      *
56      * @param initialValue initial value GPIO will be set to
57      */
58     virtual void requestWrite(int initialValue) = 0;
59 
60     /**
61      * Gets the value of the GPIO.
62      *
63      * Throws an exception if an error occurs.
64      *
65      * @return 0 or 1
66      */
67     virtual int getValue() = 0;
68 
69     /**
70      * Sets the value of the GPIO.
71      *
72      * Throws an exception if an error occurs.
73      *
74      * @param value new value (0 or 1)
75      */
76     virtual void setValue(int value) = 0;
77 
78     /**
79      * Release ownership of the GPIO.
80      *
81      * Throws an exception if an error occurs.
82      */
83     virtual void release() = 0;
84 };
85 
86 /**
87  * @class BMCGPIO
88  *
89  * Implementation of the GPIO interface using the standard BMC API (libgpiod).
90  */
91 class BMCGPIO : public GPIO
92 {
93   public:
94     BMCGPIO() = delete;
95     BMCGPIO(const BMCGPIO&) = delete;
96     BMCGPIO(BMCGPIO&&) = delete;
97     BMCGPIO& operator=(const BMCGPIO&) = delete;
98     BMCGPIO& operator=(BMCGPIO&&) = delete;
99 
100     /**
101      * Constructor.
102      *
103      * Throws an exception if a GPIO with the specified name cannot be found.
104      *
105      * @param name GPIO name
106      */
BMCGPIO(const std::string & name)107     explicit BMCGPIO(const std::string& name)
108     {
109         line = gpiod::find_line(name);
110         if (!line)
111         {
112             throw std::invalid_argument{"Invalid GPIO name: " + name};
113         }
114     }
115 
116     /**
117      * Destructor.
118      *
119      * Releases ownership of the GPIO if it had been previously requested.
120      */
~BMCGPIO()121     virtual ~BMCGPIO()
122     {
123         // Destructors must not throw exceptions
124         try
125         {
126             if (line.is_requested())
127             {
128                 release();
129             }
130         }
131         catch (...)
132         {}
133     }
134 
135     /** @copydoc GPIO::requestRead() */
requestRead()136     virtual void requestRead() override
137     {
138         line.request({consumer, gpiod::line_request::DIRECTION_INPUT, 0});
139     }
140 
141     /** @copydoc GPIO::requestWrite() */
requestWrite(int initialValue)142     virtual void requestWrite(int initialValue) override
143     {
144         line.request({consumer, gpiod::line_request::DIRECTION_OUTPUT, 0},
145                      initialValue);
146     }
147 
148     /** @copydoc GPIO::getValue() */
getValue()149     virtual int getValue() override
150     {
151         return line.get_value();
152     }
153 
154     /** @copydoc GPIO::setValue() */
setValue(int value)155     virtual void setValue(int value) override
156     {
157         line.set_value(value);
158     }
159 
160     /** @copydoc GPIO::release() */
release()161     virtual void release() override
162     {
163         line.release();
164     }
165 
166   private:
167     /**
168      * Consumer value specified when requesting the GPIO line.
169      */
170     inline static const std::string consumer{"phosphor-power-control"};
171 
172     /**
173      * GPIO line to access the pin.
174      */
175     gpiod::line line;
176 };
177 
178 } // namespace phosphor::power::sequencer
179