blob: a2f1f3e2203042645fe63164fd726aac1890a33f [file] [log] [blame]
Matt Spinleree7adb72017-08-21 15:17:19 -05001/**
2 * Copyright © 2017 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 */
William A. Kennington IIIe5a8b472018-10-18 00:40:04 -070016#include <cassert>
Matt Spinleree7adb72017-08-21 15:17:19 -050017#include <fcntl.h>
18#include <phosphor-logging/elog.hpp>
19#include <phosphor-logging/elog-errors.hpp>
20#include <phosphor-logging/log.hpp>
21#include <sys/ioctl.h>
22#include <xyz/openbmc_project/Common/error.hpp>
23#include "gpio.hpp"
24
25namespace witherspoon
26{
27namespace gpio
28{
29
30using namespace phosphor::logging;
31
32using InternalFailure = sdbusplus::xyz::openbmc_project::Common::
33 Error::InternalFailure;
34
35Value GPIO::read()
36{
37 assert(direction == Direction::input);
38
39 requestLine();
40
41 gpiohandle_data data{};
42
43 auto rc = ioctl(lineFD(),
44 GPIOHANDLE_GET_LINE_VALUES_IOCTL,
45 &data);
46
47 if (rc < 0)
48 {
49 auto e = errno;
50 log<level::ERR>("Failed GET_LINE_VALUES ioctl",
51 entry("ERRNO=%d", e));
52 elog<InternalFailure>();
53 }
54
55 return (data.values[0] == 0) ? Value::low : Value::high;
56}
57
Matt Spinler35aa1432018-01-18 11:13:20 -060058void GPIO::set(Value value)
59{
60 assert(direction == Direction::output);
Matt Spinleree7adb72017-08-21 15:17:19 -050061
Matt Spinler35aa1432018-01-18 11:13:20 -060062 requestLine(value);
63
64 gpiohandle_data data{};
65 data.values[0] = static_cast<gpioValue_t>(value);
66
67 auto rc = ioctl(lineFD(), GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data);
68 if (rc == -1)
69 {
70 auto e = errno;
71 log<level::ERR>("Failed SET_LINE_VALUES ioctl",
72 entry("ERRNO=%d", e));
73 elog<InternalFailure>();
74 }
75}
76
77void GPIO::requestLine(Value defaultValue)
Matt Spinleree7adb72017-08-21 15:17:19 -050078{
79 //Only need to do this once
80 if (lineFD)
81 {
82 return;
83 }
84
85 power::util::FileDescriptor fd{open(device.c_str(), 0)};
86 if (fd() == -1)
87 {
88 auto e = errno;
89 log<level::ERR>("Failed opening GPIO device",
Matt Spinler7475b1c2018-02-27 14:04:58 -060090 entry("DEVICE=%s", device.c_str()),
Matt Spinleree7adb72017-08-21 15:17:19 -050091 entry("ERRNO=%d", e));
92 elog<InternalFailure>();
93 }
94
95 //Make an ioctl call to request the GPIO line, which will
96 //return the descriptor to use to access it.
97 gpiohandle_request request{};
98 strncpy(request.consumer_label,
99 "witherspoon-pfault-analysis",
100 sizeof(request.consumer_label));
101
102 request.flags = (direction == Direction::input) ?
103 GPIOHANDLE_REQUEST_INPUT : GPIOHANDLE_REQUEST_OUTPUT;
104
105 request.lineoffsets[0] = gpio;
106 request.lines = 1;
107
Matt Spinler35aa1432018-01-18 11:13:20 -0600108 if (direction == Direction::output)
109 {
110 request.default_values[0] = static_cast<gpioValue_t>(defaultValue);
111 }
112
Matt Spinleree7adb72017-08-21 15:17:19 -0500113 auto rc = ioctl(fd(), GPIO_GET_LINEHANDLE_IOCTL, &request);
114 if (rc == -1)
115 {
116 auto e = errno;
117 log<level::ERR>("Failed GET_LINEHANDLE ioctl",
118 entry("GPIO=%d", gpio),
119 entry("ERRNO=%d", e));
120 elog<InternalFailure>();
121 }
122
123 lineFD.set(request.fd);
124}
125
126}
127}