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 122f12128e4SRui Paulo gpio_pin_set_flags(gpio_handle_t handle, gpio_config_t *cfg) 123f12128e4SRui Paulo { 124f12128e4SRui Paulo struct gpio_pin gppin; 125f12128e4SRui Paulo 126f12128e4SRui Paulo if (cfg == NULL) 127f12128e4SRui Paulo return (-1); 128f12128e4SRui Paulo gppin.gp_pin = cfg->g_pin; 129f12128e4SRui Paulo gppin.gp_flags = cfg->g_flags; 130f12128e4SRui Paulo if (ioctl(handle, GPIOSETCONFIG, &gppin) < 0) 131f12128e4SRui Paulo return (-1); 132f12128e4SRui Paulo 133f12128e4SRui Paulo return (0); 134f12128e4SRui Paulo } 135f12128e4SRui Paulo 136f12128e4SRui Paulo gpio_value_t 137f12128e4SRui Paulo gpio_pin_get(gpio_handle_t handle, gpio_pin_t pin) 138f12128e4SRui Paulo { 139f12128e4SRui Paulo struct gpio_req gpreq; 140f12128e4SRui Paulo 141f12128e4SRui Paulo bzero(&gpreq, sizeof(gpreq)); 142f12128e4SRui Paulo gpreq.gp_pin = pin; 143f12128e4SRui Paulo if (ioctl(handle, GPIOGET, &gpreq) < 0) 144f12128e4SRui Paulo return (GPIO_VALUE_INVALID); 145f12128e4SRui Paulo 146f12128e4SRui Paulo return (gpreq.gp_value); 147f12128e4SRui Paulo } 148f12128e4SRui Paulo 149f12128e4SRui Paulo int 150f12128e4SRui Paulo gpio_pin_set(gpio_handle_t handle, gpio_pin_t pin, gpio_value_t value) 151f12128e4SRui Paulo { 152f12128e4SRui Paulo struct gpio_req gpreq; 153f12128e4SRui Paulo 154f12128e4SRui Paulo if (value == GPIO_VALUE_INVALID) 155f12128e4SRui Paulo return (-1); 156f12128e4SRui Paulo bzero(&gpreq, sizeof(gpreq)); 157f12128e4SRui Paulo gpreq.gp_pin = pin; 158f12128e4SRui Paulo gpreq.gp_value = value; 159f12128e4SRui Paulo if (ioctl(handle, GPIOSET, &gpreq) < 0) 160f12128e4SRui Paulo return (-1); 161f12128e4SRui Paulo 162f12128e4SRui Paulo return (0); 163f12128e4SRui Paulo } 164f12128e4SRui Paulo 165f12128e4SRui Paulo int 166f12128e4SRui Paulo gpio_pin_toggle(gpio_handle_t handle, gpio_pin_t pin) 167f12128e4SRui Paulo { 168f12128e4SRui Paulo gpio_value_t value; 169f12128e4SRui Paulo 170f12128e4SRui Paulo value = gpio_pin_get(handle, pin); 171f12128e4SRui Paulo if (value == GPIO_VALUE_INVALID) 172f12128e4SRui Paulo return (-1); 173f12128e4SRui Paulo value = !value; 174f12128e4SRui Paulo 175f12128e4SRui Paulo return (gpio_pin_set(handle, pin, value)); 176f12128e4SRui Paulo } 177f12128e4SRui Paulo 178f12128e4SRui Paulo int 179f12128e4SRui Paulo gpio_pin_low(gpio_handle_t handle, gpio_pin_t pin) 180f12128e4SRui Paulo { 181f12128e4SRui Paulo return (gpio_pin_set(handle, pin, GPIO_VALUE_LOW)); 182f12128e4SRui Paulo } 183f12128e4SRui Paulo 184f12128e4SRui Paulo int 185f12128e4SRui Paulo gpio_pin_high(gpio_handle_t handle, gpio_pin_t pin) 186f12128e4SRui Paulo { 187f12128e4SRui Paulo return (gpio_pin_set(handle, pin, GPIO_VALUE_HIGH)); 188f12128e4SRui Paulo } 189f12128e4SRui Paulo 190f12128e4SRui Paulo static int 191f12128e4SRui Paulo gpio_pin_set_flag(gpio_handle_t handle, gpio_pin_t pin, uint32_t flag) 192f12128e4SRui Paulo { 193f12128e4SRui Paulo gpio_config_t cfg; 194f12128e4SRui Paulo 195f12128e4SRui Paulo bzero(&cfg, sizeof(cfg)); 196f12128e4SRui Paulo cfg.g_pin = pin; 197f12128e4SRui Paulo if (gpio_pin_config(handle, &cfg) < 0) 198f12128e4SRui Paulo return (-1); 199f12128e4SRui Paulo cfg.g_flags = flag; 200f12128e4SRui Paulo 201f12128e4SRui Paulo return (gpio_pin_set_flags(handle, &cfg)); 202f12128e4SRui Paulo } 203f12128e4SRui Paulo 204f12128e4SRui Paulo int 205f12128e4SRui Paulo gpio_pin_input(gpio_handle_t handle, gpio_pin_t pin) 206f12128e4SRui Paulo { 207f12128e4SRui Paulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_INPUT)); 208f12128e4SRui Paulo } 209f12128e4SRui Paulo 210f12128e4SRui Paulo int 211f12128e4SRui Paulo gpio_pin_output(gpio_handle_t handle, gpio_pin_t pin) 212f12128e4SRui Paulo { 213f12128e4SRui Paulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_OUTPUT)); 214f12128e4SRui Paulo } 215f12128e4SRui Paulo 216f12128e4SRui Paulo int 217f12128e4SRui Paulo gpio_pin_opendrain(gpio_handle_t handle, gpio_pin_t pin) 218f12128e4SRui Paulo { 219f12128e4SRui Paulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_OPENDRAIN)); 220f12128e4SRui Paulo } 221f12128e4SRui Paulo 222f12128e4SRui Paulo int 223f12128e4SRui Paulo gpio_pin_pushpull(gpio_handle_t handle, gpio_pin_t pin) 224f12128e4SRui Paulo { 225f12128e4SRui Paulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PUSHPULL)); 226f12128e4SRui Paulo } 227f12128e4SRui Paulo 228f12128e4SRui Paulo int 229f12128e4SRui Paulo gpio_pin_tristate(gpio_handle_t handle, gpio_pin_t pin) 230f12128e4SRui Paulo { 231f12128e4SRui Paulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_TRISTATE)); 232f12128e4SRui Paulo } 233f12128e4SRui Paulo 234f12128e4SRui Paulo int 235f12128e4SRui Paulo gpio_pin_pullup(gpio_handle_t handle, gpio_pin_t pin) 236f12128e4SRui Paulo { 237f12128e4SRui Paulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PULLUP)); 238f12128e4SRui Paulo } 239f12128e4SRui Paulo 240f12128e4SRui Paulo int 241f12128e4SRui Paulo gpio_pin_pulldown(gpio_handle_t handle, gpio_pin_t pin) 242f12128e4SRui Paulo { 243f12128e4SRui Paulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PULLDOWN)); 244f12128e4SRui Paulo } 245f12128e4SRui Paulo 246f12128e4SRui Paulo int 247f12128e4SRui Paulo gpio_pin_invin(gpio_handle_t handle, gpio_pin_t pin) 248f12128e4SRui Paulo { 249f12128e4SRui Paulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_INVIN)); 250f12128e4SRui Paulo } 251f12128e4SRui Paulo 252f12128e4SRui Paulo int 253f12128e4SRui Paulo gpio_pin_invout(gpio_handle_t handle, gpio_pin_t pin) 254f12128e4SRui Paulo { 255f12128e4SRui Paulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_INVOUT)); 256f12128e4SRui Paulo } 257f12128e4SRui Paulo 258f12128e4SRui Paulo int 259f12128e4SRui Paulo gpio_pin_pulsate(gpio_handle_t handle, gpio_pin_t pin) 260f12128e4SRui Paulo { 261f12128e4SRui Paulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PULSATE)); 262f12128e4SRui Paulo } 263