1274987Srpaulo/*- 2274987Srpaulo * Copyright (c) 2013-2014 Rui Paulo <rpaulo@FreeBSD.org> 3274987Srpaulo * All rights reserved. 4274987Srpaulo * 5274987Srpaulo * Redistribution and use in source and binary forms, with or without 6274987Srpaulo * modification, are permitted provided that the following conditions 7274987Srpaulo * are met: 8274987Srpaulo * 1. Redistributions of source code must retain the above copyright 9274987Srpaulo * notice, this list of conditions and the following disclaimer. 10274987Srpaulo * 2. Redistributions in binary form must reproduce the above copyright 11274987Srpaulo * notice, this list of conditions and the following disclaimer in the 12274987Srpaulo * documentation and/or other materials provided with the distribution. 13274987Srpaulo * 14274987Srpaulo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15274987Srpaulo * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16274987Srpaulo * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17274987Srpaulo * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 18274987Srpaulo * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19274987Srpaulo * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20274987Srpaulo * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21274987Srpaulo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 22274987Srpaulo * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 23274987Srpaulo * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24274987Srpaulo * POSSIBILITY OF SUCH DAMAGE. 25274987Srpaulo * 26274987Srpaulo * $FreeBSD$ 27274987Srpaulo */ 28274987Srpaulo#include <stdio.h> 29274987Srpaulo#include <fcntl.h> 30274987Srpaulo#include <unistd.h> 31274987Srpaulo#include <stdlib.h> 32274987Srpaulo#include <string.h> 33274987Srpaulo#include <errno.h> 34274987Srpaulo 35274987Srpaulo#include <sys/ioctl.h> 36274987Srpaulo#include <sys/types.h> 37274987Srpaulo 38274987Srpaulo#include <libgpio.h> 39274987Srpaulo 40274987Srpaulogpio_handle_t 41274987Srpaulogpio_open(unsigned int unit) 42274987Srpaulo{ 43274987Srpaulo char device[16]; 44274987Srpaulo 45274987Srpaulo snprintf(device, sizeof(device), "/dev/gpioc%u", unit); 46274987Srpaulo 47274987Srpaulo return (gpio_open_device(device)); 48274987Srpaulo} 49274987Srpaulo 50274987Srpaulogpio_handle_t 51274987Srpaulogpio_open_device(const char *device) 52274987Srpaulo{ 53274987Srpaulo int fd, maxpins; 54274987Srpaulo int serr; 55274987Srpaulo 56274987Srpaulo fd = open(device, O_RDONLY); 57274987Srpaulo if (fd < 0) 58274987Srpaulo return (GPIO_INVALID_HANDLE); 59274987Srpaulo /* 60274987Srpaulo * Check whether a simple ioctl works. 61274987Srpaulo */ 62274987Srpaulo if (ioctl(fd, GPIOMAXPIN, &maxpins) < 0) { 63274987Srpaulo serr = errno; 64274987Srpaulo close(fd); 65274987Srpaulo errno = serr; 66274987Srpaulo return (GPIO_INVALID_HANDLE); 67274987Srpaulo } 68274987Srpaulo 69274987Srpaulo return (fd); 70274987Srpaulo} 71274987Srpaulo 72274987Srpaulovoid 73274987Srpaulogpio_close(gpio_handle_t handle) 74274987Srpaulo{ 75274987Srpaulo close(handle); 76274987Srpaulo} 77274987Srpaulo 78274987Srpauloint 79274987Srpaulogpio_pin_list(gpio_handle_t handle, gpio_config_t **pcfgs) 80274987Srpaulo{ 81274987Srpaulo int maxpins, i; 82274987Srpaulo gpio_config_t *cfgs; 83274987Srpaulo 84274987Srpaulo *pcfgs = NULL; 85274987Srpaulo if (ioctl(handle, GPIOMAXPIN, &maxpins) < 0) 86274987Srpaulo return (-1); 87274987Srpaulo /* Reasonable values. */ 88274987Srpaulo if (maxpins < 0 || maxpins > 4096) { 89274987Srpaulo errno = EINVAL; 90274987Srpaulo return (-1); 91274987Srpaulo } 92275396Srpaulo cfgs = calloc(maxpins + 1, sizeof(*cfgs)); 93274987Srpaulo if (cfgs == NULL) 94274987Srpaulo return (-1); 95274987Srpaulo for (i = 0; i <= maxpins; i++) { 96274987Srpaulo cfgs[i].g_pin = i; 97274987Srpaulo gpio_pin_config(handle, &cfgs[i]); 98274987Srpaulo } 99274987Srpaulo *pcfgs = cfgs; 100274987Srpaulo 101274987Srpaulo return (maxpins); 102274987Srpaulo} 103274987Srpaulo 104274987Srpauloint 105274987Srpaulogpio_pin_config(gpio_handle_t handle, gpio_config_t *cfg) 106274987Srpaulo{ 107274987Srpaulo struct gpio_pin gppin; 108274987Srpaulo 109274987Srpaulo if (cfg == NULL) 110274987Srpaulo return (-1); 111274987Srpaulo gppin.gp_pin = cfg->g_pin; 112274987Srpaulo if (ioctl(handle, GPIOGETCONFIG, &gppin) < 0) 113274987Srpaulo return (-1); 114274987Srpaulo strlcpy(cfg->g_name, gppin.gp_name, GPIOMAXNAME); 115274987Srpaulo cfg->g_caps = gppin.gp_caps; 116274987Srpaulo cfg->g_flags = gppin.gp_flags; 117274987Srpaulo 118274987Srpaulo return (0); 119274987Srpaulo} 120274987Srpaulo 121274987Srpauloint 122279761Sloosgpio_pin_set_name(gpio_handle_t handle, gpio_pin_t pin, char *name) 123279761Sloos{ 124279761Sloos struct gpio_pin gppin; 125279761Sloos 126279761Sloos if (name == NULL) 127279761Sloos return (-1); 128279761Sloos bzero(&gppin, sizeof(gppin)); 129279761Sloos gppin.gp_pin = pin; 130279761Sloos strlcpy(gppin.gp_name, name, GPIOMAXNAME); 131279761Sloos if (ioctl(handle, GPIOSETNAME, &gppin) < 0) 132279761Sloos return (-1); 133279761Sloos 134279761Sloos return (0); 135279761Sloos} 136279761Sloos 137279761Sloosint 138274987Srpaulogpio_pin_set_flags(gpio_handle_t handle, gpio_config_t *cfg) 139274987Srpaulo{ 140274987Srpaulo struct gpio_pin gppin; 141274987Srpaulo 142274987Srpaulo if (cfg == NULL) 143274987Srpaulo return (-1); 144274987Srpaulo gppin.gp_pin = cfg->g_pin; 145274987Srpaulo gppin.gp_flags = cfg->g_flags; 146274987Srpaulo if (ioctl(handle, GPIOSETCONFIG, &gppin) < 0) 147274987Srpaulo return (-1); 148274987Srpaulo 149274987Srpaulo return (0); 150274987Srpaulo} 151274987Srpaulo 152274987Srpaulogpio_value_t 153274987Srpaulogpio_pin_get(gpio_handle_t handle, gpio_pin_t pin) 154274987Srpaulo{ 155274987Srpaulo struct gpio_req gpreq; 156274987Srpaulo 157274987Srpaulo bzero(&gpreq, sizeof(gpreq)); 158274987Srpaulo gpreq.gp_pin = pin; 159274987Srpaulo if (ioctl(handle, GPIOGET, &gpreq) < 0) 160274987Srpaulo return (GPIO_VALUE_INVALID); 161274987Srpaulo 162274987Srpaulo return (gpreq.gp_value); 163274987Srpaulo} 164274987Srpaulo 165274987Srpauloint 166274987Srpaulogpio_pin_set(gpio_handle_t handle, gpio_pin_t pin, gpio_value_t value) 167274987Srpaulo{ 168274987Srpaulo struct gpio_req gpreq; 169274987Srpaulo 170274987Srpaulo if (value == GPIO_VALUE_INVALID) 171274987Srpaulo return (-1); 172274987Srpaulo bzero(&gpreq, sizeof(gpreq)); 173274987Srpaulo gpreq.gp_pin = pin; 174274987Srpaulo gpreq.gp_value = value; 175274987Srpaulo if (ioctl(handle, GPIOSET, &gpreq) < 0) 176274987Srpaulo return (-1); 177274987Srpaulo 178274987Srpaulo return (0); 179274987Srpaulo} 180274987Srpaulo 181274987Srpauloint 182274987Srpaulogpio_pin_toggle(gpio_handle_t handle, gpio_pin_t pin) 183274987Srpaulo{ 184298272Sloos struct gpio_req gpreq; 185274987Srpaulo 186298272Sloos bzero(&gpreq, sizeof(gpreq)); 187298272Sloos gpreq.gp_pin = pin; 188298272Sloos if (ioctl(handle, GPIOTOGGLE, &gpreq) < 0) 189274987Srpaulo return (-1); 190274987Srpaulo 191298272Sloos return (0); 192274987Srpaulo} 193274987Srpaulo 194274987Srpauloint 195274987Srpaulogpio_pin_low(gpio_handle_t handle, gpio_pin_t pin) 196274987Srpaulo{ 197274987Srpaulo return (gpio_pin_set(handle, pin, GPIO_VALUE_LOW)); 198274987Srpaulo} 199274987Srpaulo 200274987Srpauloint 201274987Srpaulogpio_pin_high(gpio_handle_t handle, gpio_pin_t pin) 202274987Srpaulo{ 203274987Srpaulo return (gpio_pin_set(handle, pin, GPIO_VALUE_HIGH)); 204274987Srpaulo} 205274987Srpaulo 206274987Srpaulostatic int 207274987Srpaulogpio_pin_set_flag(gpio_handle_t handle, gpio_pin_t pin, uint32_t flag) 208274987Srpaulo{ 209274987Srpaulo gpio_config_t cfg; 210274987Srpaulo 211274987Srpaulo bzero(&cfg, sizeof(cfg)); 212274987Srpaulo cfg.g_pin = pin; 213274987Srpaulo if (gpio_pin_config(handle, &cfg) < 0) 214274987Srpaulo return (-1); 215274987Srpaulo cfg.g_flags = flag; 216274987Srpaulo 217274987Srpaulo return (gpio_pin_set_flags(handle, &cfg)); 218274987Srpaulo} 219274987Srpaulo 220274987Srpauloint 221274987Srpaulogpio_pin_input(gpio_handle_t handle, gpio_pin_t pin) 222274987Srpaulo{ 223274987Srpaulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_INPUT)); 224274987Srpaulo} 225274987Srpaulo 226274987Srpauloint 227274987Srpaulogpio_pin_output(gpio_handle_t handle, gpio_pin_t pin) 228274987Srpaulo{ 229274987Srpaulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_OUTPUT)); 230274987Srpaulo} 231274987Srpaulo 232274987Srpauloint 233274987Srpaulogpio_pin_opendrain(gpio_handle_t handle, gpio_pin_t pin) 234274987Srpaulo{ 235274987Srpaulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_OPENDRAIN)); 236274987Srpaulo} 237274987Srpaulo 238274987Srpauloint 239274987Srpaulogpio_pin_pushpull(gpio_handle_t handle, gpio_pin_t pin) 240274987Srpaulo{ 241274987Srpaulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PUSHPULL)); 242274987Srpaulo} 243274987Srpaulo 244274987Srpauloint 245274987Srpaulogpio_pin_tristate(gpio_handle_t handle, gpio_pin_t pin) 246274987Srpaulo{ 247274987Srpaulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_TRISTATE)); 248274987Srpaulo} 249274987Srpaulo 250274987Srpauloint 251274987Srpaulogpio_pin_pullup(gpio_handle_t handle, gpio_pin_t pin) 252274987Srpaulo{ 253274987Srpaulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PULLUP)); 254274987Srpaulo} 255274987Srpaulo 256274987Srpauloint 257274987Srpaulogpio_pin_pulldown(gpio_handle_t handle, gpio_pin_t pin) 258274987Srpaulo{ 259274987Srpaulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PULLDOWN)); 260274987Srpaulo} 261274987Srpaulo 262274987Srpauloint 263274987Srpaulogpio_pin_invin(gpio_handle_t handle, gpio_pin_t pin) 264274987Srpaulo{ 265274987Srpaulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_INVIN)); 266274987Srpaulo} 267274987Srpaulo 268274987Srpauloint 269274987Srpaulogpio_pin_invout(gpio_handle_t handle, gpio_pin_t pin) 270274987Srpaulo{ 271274987Srpaulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_INVOUT)); 272274987Srpaulo} 273274987Srpaulo 274274987Srpauloint 275274987Srpaulogpio_pin_pulsate(gpio_handle_t handle, gpio_pin_t pin) 276274987Srpaulo{ 277274987Srpaulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PULSATE)); 278274987Srpaulo} 279