1*f12128e4SRui Paulo /*- 2*f12128e4SRui Paulo * Copyright (c) 2013-2014 Rui Paulo <rpaulo@FreeBSD.org> 3*f12128e4SRui Paulo * All rights reserved. 4*f12128e4SRui Paulo * 5*f12128e4SRui Paulo * Redistribution and use in source and binary forms, with or without 6*f12128e4SRui Paulo * modification, are permitted provided that the following conditions 7*f12128e4SRui Paulo * are met: 8*f12128e4SRui Paulo * 1. Redistributions of source code must retain the above copyright 9*f12128e4SRui Paulo * notice, this list of conditions and the following disclaimer. 10*f12128e4SRui Paulo * 2. Redistributions in binary form must reproduce the above copyright 11*f12128e4SRui Paulo * notice, this list of conditions and the following disclaimer in the 12*f12128e4SRui Paulo * documentation and/or other materials provided with the distribution. 13*f12128e4SRui Paulo * 14*f12128e4SRui Paulo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15*f12128e4SRui Paulo * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16*f12128e4SRui Paulo * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17*f12128e4SRui Paulo * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 18*f12128e4SRui Paulo * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19*f12128e4SRui Paulo * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20*f12128e4SRui Paulo * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21*f12128e4SRui Paulo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 22*f12128e4SRui Paulo * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 23*f12128e4SRui Paulo * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24*f12128e4SRui Paulo * POSSIBILITY OF SUCH DAMAGE. 25*f12128e4SRui Paulo * 26*f12128e4SRui Paulo * $FreeBSD$ 27*f12128e4SRui Paulo */ 28*f12128e4SRui Paulo #include <stdio.h> 29*f12128e4SRui Paulo #include <fcntl.h> 30*f12128e4SRui Paulo #include <unistd.h> 31*f12128e4SRui Paulo #include <stdlib.h> 32*f12128e4SRui Paulo #include <string.h> 33*f12128e4SRui Paulo #include <errno.h> 34*f12128e4SRui Paulo 35*f12128e4SRui Paulo #include <sys/ioctl.h> 36*f12128e4SRui Paulo #include <sys/types.h> 37*f12128e4SRui Paulo 38*f12128e4SRui Paulo #include <libgpio.h> 39*f12128e4SRui Paulo 40*f12128e4SRui Paulo gpio_handle_t 41*f12128e4SRui Paulo gpio_open(unsigned int unit) 42*f12128e4SRui Paulo { 43*f12128e4SRui Paulo char device[16]; 44*f12128e4SRui Paulo 45*f12128e4SRui Paulo snprintf(device, sizeof(device), "/dev/gpioc%u", unit); 46*f12128e4SRui Paulo 47*f12128e4SRui Paulo return (gpio_open_device(device)); 48*f12128e4SRui Paulo } 49*f12128e4SRui Paulo 50*f12128e4SRui Paulo gpio_handle_t 51*f12128e4SRui Paulo gpio_open_device(const char *device) 52*f12128e4SRui Paulo { 53*f12128e4SRui Paulo int fd, maxpins; 54*f12128e4SRui Paulo int serr; 55*f12128e4SRui Paulo 56*f12128e4SRui Paulo fd = open(device, O_RDONLY); 57*f12128e4SRui Paulo if (fd < 0) 58*f12128e4SRui Paulo return (GPIO_INVALID_HANDLE); 59*f12128e4SRui Paulo /* 60*f12128e4SRui Paulo * Check whether a simple ioctl works. 61*f12128e4SRui Paulo */ 62*f12128e4SRui Paulo if (ioctl(fd, GPIOMAXPIN, &maxpins) < 0) { 63*f12128e4SRui Paulo serr = errno; 64*f12128e4SRui Paulo close(fd); 65*f12128e4SRui Paulo errno = serr; 66*f12128e4SRui Paulo return (GPIO_INVALID_HANDLE); 67*f12128e4SRui Paulo } 68*f12128e4SRui Paulo 69*f12128e4SRui Paulo return (fd); 70*f12128e4SRui Paulo } 71*f12128e4SRui Paulo 72*f12128e4SRui Paulo void 73*f12128e4SRui Paulo gpio_close(gpio_handle_t handle) 74*f12128e4SRui Paulo { 75*f12128e4SRui Paulo close(handle); 76*f12128e4SRui Paulo } 77*f12128e4SRui Paulo 78*f12128e4SRui Paulo int 79*f12128e4SRui Paulo gpio_pin_list(gpio_handle_t handle, gpio_config_t **pcfgs) 80*f12128e4SRui Paulo { 81*f12128e4SRui Paulo int maxpins, i; 82*f12128e4SRui Paulo gpio_config_t *cfgs; 83*f12128e4SRui Paulo 84*f12128e4SRui Paulo *pcfgs = NULL; 85*f12128e4SRui Paulo if (ioctl(handle, GPIOMAXPIN, &maxpins) < 0) 86*f12128e4SRui Paulo return (-1); 87*f12128e4SRui Paulo /* Reasonable values. */ 88*f12128e4SRui Paulo if (maxpins < 0 || maxpins > 4096) { 89*f12128e4SRui Paulo errno = EINVAL; 90*f12128e4SRui Paulo return (-1); 91*f12128e4SRui Paulo } 92*f12128e4SRui Paulo cfgs = calloc(maxpins, sizeof(*cfgs)); 93*f12128e4SRui Paulo if (cfgs == NULL) 94*f12128e4SRui Paulo return (-1); 95*f12128e4SRui Paulo for (i = 0; i <= maxpins; i++) { 96*f12128e4SRui Paulo cfgs[i].g_pin = i; 97*f12128e4SRui Paulo gpio_pin_config(handle, &cfgs[i]); 98*f12128e4SRui Paulo } 99*f12128e4SRui Paulo *pcfgs = cfgs; 100*f12128e4SRui Paulo 101*f12128e4SRui Paulo return (maxpins); 102*f12128e4SRui Paulo } 103*f12128e4SRui Paulo 104*f12128e4SRui Paulo int 105*f12128e4SRui Paulo gpio_pin_config(gpio_handle_t handle, gpio_config_t *cfg) 106*f12128e4SRui Paulo { 107*f12128e4SRui Paulo struct gpio_pin gppin; 108*f12128e4SRui Paulo 109*f12128e4SRui Paulo if (cfg == NULL) 110*f12128e4SRui Paulo return (-1); 111*f12128e4SRui Paulo gppin.gp_pin = cfg->g_pin; 112*f12128e4SRui Paulo if (ioctl(handle, GPIOGETCONFIG, &gppin) < 0) 113*f12128e4SRui Paulo return (-1); 114*f12128e4SRui Paulo strlcpy(cfg->g_name, gppin.gp_name, GPIOMAXNAME); 115*f12128e4SRui Paulo cfg->g_caps = gppin.gp_caps; 116*f12128e4SRui Paulo cfg->g_flags = gppin.gp_flags; 117*f12128e4SRui Paulo 118*f12128e4SRui Paulo return (0); 119*f12128e4SRui Paulo } 120*f12128e4SRui Paulo 121*f12128e4SRui Paulo int 122*f12128e4SRui Paulo gpio_pin_set_flags(gpio_handle_t handle, gpio_config_t *cfg) 123*f12128e4SRui Paulo { 124*f12128e4SRui Paulo struct gpio_pin gppin; 125*f12128e4SRui Paulo 126*f12128e4SRui Paulo if (cfg == NULL) 127*f12128e4SRui Paulo return (-1); 128*f12128e4SRui Paulo gppin.gp_pin = cfg->g_pin; 129*f12128e4SRui Paulo gppin.gp_flags = cfg->g_flags; 130*f12128e4SRui Paulo if (ioctl(handle, GPIOSETCONFIG, &gppin) < 0) 131*f12128e4SRui Paulo return (-1); 132*f12128e4SRui Paulo 133*f12128e4SRui Paulo return (0); 134*f12128e4SRui Paulo } 135*f12128e4SRui Paulo 136*f12128e4SRui Paulo gpio_value_t 137*f12128e4SRui Paulo gpio_pin_get(gpio_handle_t handle, gpio_pin_t pin) 138*f12128e4SRui Paulo { 139*f12128e4SRui Paulo struct gpio_req gpreq; 140*f12128e4SRui Paulo 141*f12128e4SRui Paulo bzero(&gpreq, sizeof(gpreq)); 142*f12128e4SRui Paulo gpreq.gp_pin = pin; 143*f12128e4SRui Paulo if (ioctl(handle, GPIOGET, &gpreq) < 0) 144*f12128e4SRui Paulo return (GPIO_VALUE_INVALID); 145*f12128e4SRui Paulo 146*f12128e4SRui Paulo return (gpreq.gp_value); 147*f12128e4SRui Paulo } 148*f12128e4SRui Paulo 149*f12128e4SRui Paulo int 150*f12128e4SRui Paulo gpio_pin_set(gpio_handle_t handle, gpio_pin_t pin, gpio_value_t value) 151*f12128e4SRui Paulo { 152*f12128e4SRui Paulo struct gpio_req gpreq; 153*f12128e4SRui Paulo 154*f12128e4SRui Paulo if (value == GPIO_VALUE_INVALID) 155*f12128e4SRui Paulo return (-1); 156*f12128e4SRui Paulo bzero(&gpreq, sizeof(gpreq)); 157*f12128e4SRui Paulo gpreq.gp_pin = pin; 158*f12128e4SRui Paulo gpreq.gp_value = value; 159*f12128e4SRui Paulo if (ioctl(handle, GPIOSET, &gpreq) < 0) 160*f12128e4SRui Paulo return (-1); 161*f12128e4SRui Paulo 162*f12128e4SRui Paulo return (0); 163*f12128e4SRui Paulo } 164*f12128e4SRui Paulo 165*f12128e4SRui Paulo int 166*f12128e4SRui Paulo gpio_pin_toggle(gpio_handle_t handle, gpio_pin_t pin) 167*f12128e4SRui Paulo { 168*f12128e4SRui Paulo gpio_value_t value; 169*f12128e4SRui Paulo 170*f12128e4SRui Paulo value = gpio_pin_get(handle, pin); 171*f12128e4SRui Paulo if (value == GPIO_VALUE_INVALID) 172*f12128e4SRui Paulo return (-1); 173*f12128e4SRui Paulo value = !value; 174*f12128e4SRui Paulo 175*f12128e4SRui Paulo return (gpio_pin_set(handle, pin, value)); 176*f12128e4SRui Paulo } 177*f12128e4SRui Paulo 178*f12128e4SRui Paulo int 179*f12128e4SRui Paulo gpio_pin_low(gpio_handle_t handle, gpio_pin_t pin) 180*f12128e4SRui Paulo { 181*f12128e4SRui Paulo return (gpio_pin_set(handle, pin, GPIO_VALUE_LOW)); 182*f12128e4SRui Paulo } 183*f12128e4SRui Paulo 184*f12128e4SRui Paulo int 185*f12128e4SRui Paulo gpio_pin_high(gpio_handle_t handle, gpio_pin_t pin) 186*f12128e4SRui Paulo { 187*f12128e4SRui Paulo return (gpio_pin_set(handle, pin, GPIO_VALUE_HIGH)); 188*f12128e4SRui Paulo } 189*f12128e4SRui Paulo 190*f12128e4SRui Paulo static int 191*f12128e4SRui Paulo gpio_pin_set_flag(gpio_handle_t handle, gpio_pin_t pin, uint32_t flag) 192*f12128e4SRui Paulo { 193*f12128e4SRui Paulo gpio_config_t cfg; 194*f12128e4SRui Paulo 195*f12128e4SRui Paulo bzero(&cfg, sizeof(cfg)); 196*f12128e4SRui Paulo cfg.g_pin = pin; 197*f12128e4SRui Paulo if (gpio_pin_config(handle, &cfg) < 0) 198*f12128e4SRui Paulo return (-1); 199*f12128e4SRui Paulo cfg.g_flags = flag; 200*f12128e4SRui Paulo 201*f12128e4SRui Paulo return (gpio_pin_set_flags(handle, &cfg)); 202*f12128e4SRui Paulo } 203*f12128e4SRui Paulo 204*f12128e4SRui Paulo int 205*f12128e4SRui Paulo gpio_pin_input(gpio_handle_t handle, gpio_pin_t pin) 206*f12128e4SRui Paulo { 207*f12128e4SRui Paulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_INPUT)); 208*f12128e4SRui Paulo } 209*f12128e4SRui Paulo 210*f12128e4SRui Paulo int 211*f12128e4SRui Paulo gpio_pin_output(gpio_handle_t handle, gpio_pin_t pin) 212*f12128e4SRui Paulo { 213*f12128e4SRui Paulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_OUTPUT)); 214*f12128e4SRui Paulo } 215*f12128e4SRui Paulo 216*f12128e4SRui Paulo int 217*f12128e4SRui Paulo gpio_pin_opendrain(gpio_handle_t handle, gpio_pin_t pin) 218*f12128e4SRui Paulo { 219*f12128e4SRui Paulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_OPENDRAIN)); 220*f12128e4SRui Paulo } 221*f12128e4SRui Paulo 222*f12128e4SRui Paulo int 223*f12128e4SRui Paulo gpio_pin_pushpull(gpio_handle_t handle, gpio_pin_t pin) 224*f12128e4SRui Paulo { 225*f12128e4SRui Paulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PUSHPULL)); 226*f12128e4SRui Paulo } 227*f12128e4SRui Paulo 228*f12128e4SRui Paulo int 229*f12128e4SRui Paulo gpio_pin_tristate(gpio_handle_t handle, gpio_pin_t pin) 230*f12128e4SRui Paulo { 231*f12128e4SRui Paulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_TRISTATE)); 232*f12128e4SRui Paulo } 233*f12128e4SRui Paulo 234*f12128e4SRui Paulo int 235*f12128e4SRui Paulo gpio_pin_pullup(gpio_handle_t handle, gpio_pin_t pin) 236*f12128e4SRui Paulo { 237*f12128e4SRui Paulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PULLUP)); 238*f12128e4SRui Paulo } 239*f12128e4SRui Paulo 240*f12128e4SRui Paulo int 241*f12128e4SRui Paulo gpio_pin_pulldown(gpio_handle_t handle, gpio_pin_t pin) 242*f12128e4SRui Paulo { 243*f12128e4SRui Paulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PULLDOWN)); 244*f12128e4SRui Paulo } 245*f12128e4SRui Paulo 246*f12128e4SRui Paulo int 247*f12128e4SRui Paulo gpio_pin_invin(gpio_handle_t handle, gpio_pin_t pin) 248*f12128e4SRui Paulo { 249*f12128e4SRui Paulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_INVIN)); 250*f12128e4SRui Paulo } 251*f12128e4SRui Paulo 252*f12128e4SRui Paulo int 253*f12128e4SRui Paulo gpio_pin_invout(gpio_handle_t handle, gpio_pin_t pin) 254*f12128e4SRui Paulo { 255*f12128e4SRui Paulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_INVOUT)); 256*f12128e4SRui Paulo } 257*f12128e4SRui Paulo 258*f12128e4SRui Paulo int 259*f12128e4SRui Paulo gpio_pin_pulsate(gpio_handle_t handle, gpio_pin_t pin) 260*f12128e4SRui Paulo { 261*f12128e4SRui Paulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PULSATE)); 262*f12128e4SRui Paulo } 263