1 #include "util.hpp"
2 
3 #include <gpiod.hpp>
4 
5 namespace phosphor::power::psu
6 {
7 
8 const UtilBase& getUtils()
9 {
10     static Util util;
11     return util;
12 }
13 
14 GPIOInterface::GPIOInterface(const std::string& namedGpio)
15 {
16     try
17     {
18         line = gpiod::find_line(namedGpio);
19         if (!line)
20         {
21             throw std::runtime_error("Line does not exist: " + namedGpio);
22         }
23     }
24     catch (const std::exception& e)
25     {
26         throw std::runtime_error(std::string("Failed to find line: ") +
27                                  e.what());
28     }
29 }
30 
31 std::unique_ptr<GPIOInterfaceBase>
32     GPIOInterface::createGPIO(const std::string& namedGpio)
33 {
34     return std::make_unique<GPIOInterface>(namedGpio);
35 }
36 
37 std::string GPIOInterface::getName() const
38 {
39     return line.name();
40 }
41 
42 int GPIOInterface::read()
43 {
44     using namespace phosphor::logging;
45 
46     int value = -1;
47 
48     if (!line)
49     {
50         log<level::ERR>("Failed line");
51         throw std::runtime_error{std::string{"Failed to find line"}};
52     }
53 
54     try
55     {
56         line.request({__FUNCTION__, gpiod::line_request::DIRECTION_INPUT,
57                       gpiod::line_request::FLAG_ACTIVE_LOW});
58         try
59         {
60             value = line.get_value();
61         }
62         catch (const std::exception& e)
63         {
64             log<level::ERR>(
65                 fmt::format("Failed to get_value of GPIO line: {}", e.what())
66                     .c_str());
67             line.release();
68             throw;
69         }
70 
71         line.release();
72     }
73     catch (const std::exception& e)
74     {
75         log<level::ERR>("Failed to request GPIO line",
76                         entry("MSG=%s", e.what()));
77         throw;
78     }
79 
80     return value;
81 }
82 
83 void GPIOInterface::write(int value, std::bitset<32> flags)
84 {
85     using namespace phosphor::logging;
86 
87     if (!line)
88     {
89         log<level::ERR>("Failed line");
90         throw std::runtime_error{std::string{"Failed to find line"}};
91     }
92 
93     try
94     {
95         line.request(
96             {__FUNCTION__, gpiod::line_request::DIRECTION_OUTPUT, flags},
97             value);
98 
99         line.release();
100     }
101     catch (std::exception& e)
102     {
103         log<level::ERR>("Failed to set GPIO line", entry("MSG=%s", e.what()),
104                         entry("VALUE=%d", value));
105         throw;
106     }
107 }
108 
109 void GPIOInterface::toggleLowHigh(const std::chrono::milliseconds& delay)
110 {
111     auto flags = gpiod::line_request::FLAG_OPEN_DRAIN;
112     write(0, flags);
113     std::this_thread::sleep_for(delay);
114     write(1, flags);
115 }
116 
117 std::unique_ptr<GPIOInterfaceBase> createGPIO(const std::string& namedGpio)
118 {
119     return GPIOInterface::createGPIO(namedGpio);
120 }
121 
122 } // namespace phosphor::power::psu
123