1*da2e0fe9SMatt Spinler /** 2*da2e0fe9SMatt Spinler * Copyright © 2017 IBM Corporation 3*da2e0fe9SMatt Spinler * 4*da2e0fe9SMatt Spinler * Licensed under the Apache License, Version 2.0 (the "License"); 5*da2e0fe9SMatt Spinler * you may not use this file except in compliance with the License. 6*da2e0fe9SMatt Spinler * You may obtain a copy of the License at 7*da2e0fe9SMatt Spinler * 8*da2e0fe9SMatt Spinler * http://www.apache.org/licenses/LICENSE-2.0 9*da2e0fe9SMatt Spinler * 10*da2e0fe9SMatt Spinler * Unless required by applicable law or agreed to in writing, software 11*da2e0fe9SMatt Spinler * distributed under the License is distributed on an "AS IS" BASIS, 12*da2e0fe9SMatt Spinler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*da2e0fe9SMatt Spinler * See the License for the specific language governing permissions and 14*da2e0fe9SMatt Spinler * limitations under the License. 15*da2e0fe9SMatt Spinler */ 16*da2e0fe9SMatt Spinler #include <fcntl.h> 17*da2e0fe9SMatt Spinler #include <phosphor-logging/elog.hpp> 18*da2e0fe9SMatt Spinler #include <phosphor-logging/elog-errors.hpp> 19*da2e0fe9SMatt Spinler #include <phosphor-logging/log.hpp> 20*da2e0fe9SMatt Spinler #include <sys/ioctl.h> 21*da2e0fe9SMatt Spinler #include <xyz/openbmc_project/Common/error.hpp> 22*da2e0fe9SMatt Spinler #include "gpio.hpp" 23*da2e0fe9SMatt Spinler 24*da2e0fe9SMatt Spinler namespace witherspoon 25*da2e0fe9SMatt Spinler { 26*da2e0fe9SMatt Spinler namespace gpio 27*da2e0fe9SMatt Spinler { 28*da2e0fe9SMatt Spinler 29*da2e0fe9SMatt Spinler using namespace phosphor::logging; 30*da2e0fe9SMatt Spinler 31*da2e0fe9SMatt Spinler using InternalFailure = sdbusplus::xyz::openbmc_project::Common:: 32*da2e0fe9SMatt Spinler Error::InternalFailure; 33*da2e0fe9SMatt Spinler 34*da2e0fe9SMatt Spinler Value GPIO::read() 35*da2e0fe9SMatt Spinler { 36*da2e0fe9SMatt Spinler assert(direction == Direction::input); 37*da2e0fe9SMatt Spinler 38*da2e0fe9SMatt Spinler requestLine(); 39*da2e0fe9SMatt Spinler 40*da2e0fe9SMatt Spinler gpiohandle_data data{}; 41*da2e0fe9SMatt Spinler 42*da2e0fe9SMatt Spinler auto rc = ioctl(lineFD(), 43*da2e0fe9SMatt Spinler GPIOHANDLE_GET_LINE_VALUES_IOCTL, 44*da2e0fe9SMatt Spinler &data); 45*da2e0fe9SMatt Spinler 46*da2e0fe9SMatt Spinler if (rc < 0) 47*da2e0fe9SMatt Spinler { 48*da2e0fe9SMatt Spinler auto e = errno; 49*da2e0fe9SMatt Spinler log<level::ERR>("Failed GET_LINE_VALUES ioctl", 50*da2e0fe9SMatt Spinler entry("ERRNO=%d", e)); 51*da2e0fe9SMatt Spinler elog<InternalFailure>(); 52*da2e0fe9SMatt Spinler } 53*da2e0fe9SMatt Spinler 54*da2e0fe9SMatt Spinler return (data.values[0] == 0) ? Value::low : Value::high; 55*da2e0fe9SMatt Spinler } 56*da2e0fe9SMatt Spinler 57*da2e0fe9SMatt Spinler 58*da2e0fe9SMatt Spinler void GPIO::requestLine() 59*da2e0fe9SMatt Spinler { 60*da2e0fe9SMatt Spinler //Only need to do this once 61*da2e0fe9SMatt Spinler if (lineFD) 62*da2e0fe9SMatt Spinler { 63*da2e0fe9SMatt Spinler return; 64*da2e0fe9SMatt Spinler } 65*da2e0fe9SMatt Spinler 66*da2e0fe9SMatt Spinler power::util::FileDescriptor fd{open(device.c_str(), 0)}; 67*da2e0fe9SMatt Spinler if (fd() == -1) 68*da2e0fe9SMatt Spinler { 69*da2e0fe9SMatt Spinler auto e = errno; 70*da2e0fe9SMatt Spinler log<level::ERR>("Failed opening GPIO device", 71*da2e0fe9SMatt Spinler entry("DEVICE=%s", device), 72*da2e0fe9SMatt Spinler entry("ERRNO=%d", e)); 73*da2e0fe9SMatt Spinler elog<InternalFailure>(); 74*da2e0fe9SMatt Spinler } 75*da2e0fe9SMatt Spinler 76*da2e0fe9SMatt Spinler //Make an ioctl call to request the GPIO line, which will 77*da2e0fe9SMatt Spinler //return the descriptor to use to access it. 78*da2e0fe9SMatt Spinler gpiohandle_request request{}; 79*da2e0fe9SMatt Spinler strncpy(request.consumer_label, 80*da2e0fe9SMatt Spinler "witherspoon-pfault-analysis", 81*da2e0fe9SMatt Spinler sizeof(request.consumer_label)); 82*da2e0fe9SMatt Spinler 83*da2e0fe9SMatt Spinler request.flags = (direction == Direction::input) ? 84*da2e0fe9SMatt Spinler GPIOHANDLE_REQUEST_INPUT : GPIOHANDLE_REQUEST_OUTPUT; 85*da2e0fe9SMatt Spinler 86*da2e0fe9SMatt Spinler request.lineoffsets[0] = gpio; 87*da2e0fe9SMatt Spinler request.lines = 1; 88*da2e0fe9SMatt Spinler 89*da2e0fe9SMatt Spinler auto rc = ioctl(fd(), GPIO_GET_LINEHANDLE_IOCTL, &request); 90*da2e0fe9SMatt Spinler if (rc == -1) 91*da2e0fe9SMatt Spinler { 92*da2e0fe9SMatt Spinler auto e = errno; 93*da2e0fe9SMatt Spinler log<level::ERR>("Failed GET_LINEHANDLE ioctl", 94*da2e0fe9SMatt Spinler entry("GPIO=%d", gpio), 95*da2e0fe9SMatt Spinler entry("ERRNO=%d", e)); 96*da2e0fe9SMatt Spinler elog<InternalFailure>(); 97*da2e0fe9SMatt Spinler } 98*da2e0fe9SMatt Spinler 99*da2e0fe9SMatt Spinler lineFD.set(request.fd); 100*da2e0fe9SMatt Spinler } 101*da2e0fe9SMatt Spinler 102*da2e0fe9SMatt Spinler } 103*da2e0fe9SMatt Spinler } 104