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