1da2e0fe9SMatt Spinler /** 2da2e0fe9SMatt Spinler * Copyright © 2017 IBM Corporation 3da2e0fe9SMatt Spinler * 4da2e0fe9SMatt Spinler * Licensed under the Apache License, Version 2.0 (the "License"); 5da2e0fe9SMatt Spinler * you may not use this file except in compliance with the License. 6da2e0fe9SMatt Spinler * You may obtain a copy of the License at 7da2e0fe9SMatt Spinler * 8da2e0fe9SMatt Spinler * http://www.apache.org/licenses/LICENSE-2.0 9da2e0fe9SMatt Spinler * 10da2e0fe9SMatt Spinler * Unless required by applicable law or agreed to in writing, software 11da2e0fe9SMatt Spinler * distributed under the License is distributed on an "AS IS" BASIS, 12da2e0fe9SMatt Spinler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13da2e0fe9SMatt Spinler * See the License for the specific language governing permissions and 14da2e0fe9SMatt Spinler * limitations under the License. 15da2e0fe9SMatt Spinler */ 16da2e0fe9SMatt Spinler #include <fcntl.h> 17da2e0fe9SMatt Spinler #include <phosphor-logging/elog.hpp> 18da2e0fe9SMatt Spinler #include <phosphor-logging/elog-errors.hpp> 19da2e0fe9SMatt Spinler #include <phosphor-logging/log.hpp> 20da2e0fe9SMatt Spinler #include <sys/ioctl.h> 21da2e0fe9SMatt Spinler #include <xyz/openbmc_project/Common/error.hpp> 22da2e0fe9SMatt Spinler #include "gpio.hpp" 23da2e0fe9SMatt Spinler 24da2e0fe9SMatt Spinler namespace witherspoon 25da2e0fe9SMatt Spinler { 26da2e0fe9SMatt Spinler namespace gpio 27da2e0fe9SMatt Spinler { 28da2e0fe9SMatt Spinler 29da2e0fe9SMatt Spinler using namespace phosphor::logging; 30da2e0fe9SMatt Spinler 31da2e0fe9SMatt Spinler using InternalFailure = sdbusplus::xyz::openbmc_project::Common:: 32da2e0fe9SMatt Spinler Error::InternalFailure; 33da2e0fe9SMatt Spinler 34da2e0fe9SMatt Spinler Value GPIO::read() 35da2e0fe9SMatt Spinler { 36da2e0fe9SMatt Spinler assert(direction == Direction::input); 37da2e0fe9SMatt Spinler 38da2e0fe9SMatt Spinler requestLine(); 39da2e0fe9SMatt Spinler 40da2e0fe9SMatt Spinler gpiohandle_data data{}; 41da2e0fe9SMatt Spinler 42da2e0fe9SMatt Spinler auto rc = ioctl(lineFD(), 43da2e0fe9SMatt Spinler GPIOHANDLE_GET_LINE_VALUES_IOCTL, 44da2e0fe9SMatt Spinler &data); 45da2e0fe9SMatt Spinler 46da2e0fe9SMatt Spinler if (rc < 0) 47da2e0fe9SMatt Spinler { 48da2e0fe9SMatt Spinler auto e = errno; 49da2e0fe9SMatt Spinler log<level::ERR>("Failed GET_LINE_VALUES ioctl", 50da2e0fe9SMatt Spinler entry("ERRNO=%d", e)); 51da2e0fe9SMatt Spinler elog<InternalFailure>(); 52da2e0fe9SMatt Spinler } 53da2e0fe9SMatt Spinler 54da2e0fe9SMatt Spinler return (data.values[0] == 0) ? Value::low : Value::high; 55da2e0fe9SMatt Spinler } 56da2e0fe9SMatt Spinler 5735aa1433SMatt Spinler void GPIO::set(Value value) 5835aa1433SMatt Spinler { 5935aa1433SMatt Spinler assert(direction == Direction::output); 60da2e0fe9SMatt Spinler 6135aa1433SMatt Spinler requestLine(value); 6235aa1433SMatt Spinler 6335aa1433SMatt Spinler gpiohandle_data data{}; 6435aa1433SMatt Spinler data.values[0] = static_cast<gpioValue_t>(value); 6535aa1433SMatt Spinler 6635aa1433SMatt Spinler auto rc = ioctl(lineFD(), GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data); 6735aa1433SMatt Spinler if (rc == -1) 6835aa1433SMatt Spinler { 6935aa1433SMatt Spinler auto e = errno; 7035aa1433SMatt Spinler log<level::ERR>("Failed SET_LINE_VALUES ioctl", 7135aa1433SMatt Spinler entry("ERRNO=%d", e)); 7235aa1433SMatt Spinler elog<InternalFailure>(); 7335aa1433SMatt Spinler } 7435aa1433SMatt Spinler } 7535aa1433SMatt Spinler 7635aa1433SMatt Spinler void GPIO::requestLine(Value defaultValue) 77da2e0fe9SMatt Spinler { 78da2e0fe9SMatt Spinler //Only need to do this once 79da2e0fe9SMatt Spinler if (lineFD) 80da2e0fe9SMatt Spinler { 81da2e0fe9SMatt Spinler return; 82da2e0fe9SMatt Spinler } 83da2e0fe9SMatt Spinler 84da2e0fe9SMatt Spinler power::util::FileDescriptor fd{open(device.c_str(), 0)}; 85da2e0fe9SMatt Spinler if (fd() == -1) 86da2e0fe9SMatt Spinler { 87da2e0fe9SMatt Spinler auto e = errno; 88da2e0fe9SMatt Spinler log<level::ERR>("Failed opening GPIO device", 89*7475b1c1SMatt Spinler entry("DEVICE=%s", device.c_str()), 90da2e0fe9SMatt Spinler entry("ERRNO=%d", e)); 91da2e0fe9SMatt Spinler elog<InternalFailure>(); 92da2e0fe9SMatt Spinler } 93da2e0fe9SMatt Spinler 94da2e0fe9SMatt Spinler //Make an ioctl call to request the GPIO line, which will 95da2e0fe9SMatt Spinler //return the descriptor to use to access it. 96da2e0fe9SMatt Spinler gpiohandle_request request{}; 97da2e0fe9SMatt Spinler strncpy(request.consumer_label, 98da2e0fe9SMatt Spinler "witherspoon-pfault-analysis", 99da2e0fe9SMatt Spinler sizeof(request.consumer_label)); 100da2e0fe9SMatt Spinler 101da2e0fe9SMatt Spinler request.flags = (direction == Direction::input) ? 102da2e0fe9SMatt Spinler GPIOHANDLE_REQUEST_INPUT : GPIOHANDLE_REQUEST_OUTPUT; 103da2e0fe9SMatt Spinler 104da2e0fe9SMatt Spinler request.lineoffsets[0] = gpio; 105da2e0fe9SMatt Spinler request.lines = 1; 106da2e0fe9SMatt Spinler 10735aa1433SMatt Spinler if (direction == Direction::output) 10835aa1433SMatt Spinler { 10935aa1433SMatt Spinler request.default_values[0] = static_cast<gpioValue_t>(defaultValue); 11035aa1433SMatt Spinler } 11135aa1433SMatt Spinler 112da2e0fe9SMatt Spinler auto rc = ioctl(fd(), GPIO_GET_LINEHANDLE_IOCTL, &request); 113da2e0fe9SMatt Spinler if (rc == -1) 114da2e0fe9SMatt Spinler { 115da2e0fe9SMatt Spinler auto e = errno; 116da2e0fe9SMatt Spinler log<level::ERR>("Failed GET_LINEHANDLE ioctl", 117da2e0fe9SMatt Spinler entry("GPIO=%d", gpio), 118da2e0fe9SMatt Spinler entry("ERRNO=%d", e)); 119da2e0fe9SMatt Spinler elog<InternalFailure>(); 120da2e0fe9SMatt Spinler } 121da2e0fe9SMatt Spinler 122da2e0fe9SMatt Spinler lineFD.set(request.fd); 123da2e0fe9SMatt Spinler } 124da2e0fe9SMatt Spinler 125da2e0fe9SMatt Spinler } 126da2e0fe9SMatt Spinler } 127