1 /** 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 */ 16 #include <fcntl.h> 17 #include <phosphor-logging/elog.hpp> 18 #include <phosphor-logging/elog-errors.hpp> 19 #include <phosphor-logging/log.hpp> 20 #include <sys/ioctl.h> 21 #include <xyz/openbmc_project/Common/error.hpp> 22 #include "gpio.hpp" 23 24 namespace witherspoon 25 { 26 namespace gpio 27 { 28 29 using namespace phosphor::logging; 30 31 using InternalFailure = sdbusplus::xyz::openbmc_project::Common:: 32 Error::InternalFailure; 33 34 Value GPIO::read() 35 { 36 assert(direction == Direction::input); 37 38 requestLine(); 39 40 gpiohandle_data data{}; 41 42 auto rc = ioctl(lineFD(), 43 GPIOHANDLE_GET_LINE_VALUES_IOCTL, 44 &data); 45 46 if (rc < 0) 47 { 48 auto e = errno; 49 log<level::ERR>("Failed GET_LINE_VALUES ioctl", 50 entry("ERRNO=%d", e)); 51 elog<InternalFailure>(); 52 } 53 54 return (data.values[0] == 0) ? Value::low : Value::high; 55 } 56 57 58 void GPIO::requestLine() 59 { 60 //Only need to do this once 61 if (lineFD) 62 { 63 return; 64 } 65 66 power::util::FileDescriptor fd{open(device.c_str(), 0)}; 67 if (fd() == -1) 68 { 69 auto e = errno; 70 log<level::ERR>("Failed opening GPIO device", 71 entry("DEVICE=%s", device), 72 entry("ERRNO=%d", e)); 73 elog<InternalFailure>(); 74 } 75 76 //Make an ioctl call to request the GPIO line, which will 77 //return the descriptor to use to access it. 78 gpiohandle_request request{}; 79 strncpy(request.consumer_label, 80 "witherspoon-pfault-analysis", 81 sizeof(request.consumer_label)); 82 83 request.flags = (direction == Direction::input) ? 84 GPIOHANDLE_REQUEST_INPUT : GPIOHANDLE_REQUEST_OUTPUT; 85 86 request.lineoffsets[0] = gpio; 87 request.lines = 1; 88 89 auto rc = ioctl(fd(), GPIO_GET_LINEHANDLE_IOCTL, &request); 90 if (rc == -1) 91 { 92 auto e = errno; 93 log<level::ERR>("Failed GET_LINEHANDLE ioctl", 94 entry("GPIO=%d", gpio), 95 entry("ERRNO=%d", e)); 96 elog<InternalFailure>(); 97 } 98 99 lineFD.set(request.fd); 100 } 101 102 } 103 } 104