diff options
author | Anthony Wilson <wilsonan@us.ibm.com> | 2019-03-06 10:54:58 -0600 |
---|---|---|
committer | Brad Bishop <bradleyb@fuzziesquirrel.com> | 2019-04-10 01:44:48 +0000 |
commit | c0c74e7cca35179a9c4496a49f64e00db4c47870 (patch) | |
tree | a4f72ff8f6843da2505f28a5892f618b2223eb06 /libopenbmc_intf | |
parent | c0da84767c00657c0b3b1afff7d9c5c2f1ed5fdb (diff) | |
download | talos-skeleton-c0c74e7cca35179a9c4496a49f64e00db4c47870.tar.gz talos-skeleton-c0c74e7cca35179a9c4496a49f64e00db4c47870.zip |
skeleton: Use ioctl gpio handling
Now that chassiskill is a standalone app and is
using ioctl gpio handling (through the gpioplus library),
the gpio libraries here need to use ioctl as well for
chassiskill to be compatible.
Tested: Verified chassiskill works as intended and checked
that nothing else broke.
Change-Id: I67c431027d31e87c332c3e1771fc2d3423f56652
Signed-off-by: Anthony Wilson <wilsonan@us.ibm.com>
Diffstat (limited to 'libopenbmc_intf')
-rw-r--r-- | libopenbmc_intf/gpio.c | 249 | ||||
-rw-r--r-- | libopenbmc_intf/gpio.h | 8 |
2 files changed, 60 insertions, 197 deletions
diff --git a/libopenbmc_intf/gpio.c b/libopenbmc_intf/gpio.c index 33a9ffe..afa0914 100644 --- a/libopenbmc_intf/gpio.c +++ b/libopenbmc_intf/gpio.c @@ -14,97 +14,53 @@ #include "gpio.h" #include "gpio_json.h" +#include <sys/ioctl.h> +#include <linux/gpio.h> + #define GPIO_PORT_OFFSET 8 #define GPIO_BASE_PATH "/sys/class/gpio" cJSON* gpio_json = NULL; -int gpio_writec(GPIO* gpio, char value) +int gpio_write(GPIO* gpio, uint8_t value) { g_assert (gpio != NULL); - int rc = GPIO_OK; - char buf[1]; - buf[0] = value; + struct gpiohandle_data data; + memset(&data, 0, sizeof(data)); + data.values[0] = value; - if (lseek(gpio->fd, 0, SEEK_SET) == -1) + if (gpio->fd <= 0) { return GPIO_ERROR; } - if (write(gpio->fd, buf, 1) != 1) + if (ioctl(gpio->fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data) < 0) { - rc = GPIO_WRITE_ERROR; + return GPIO_WRITE_ERROR; } - return rc; + + return GPIO_OK; } -int gpio_write(GPIO* gpio, uint8_t value) +int gpio_read(GPIO* gpio, uint8_t *value) { g_assert (gpio != NULL); - int rc = GPIO_OK; - char buf[1]; - buf[0] = '0'; - if (value==1) - { - buf[0]='1'; - } + struct gpiohandle_data data; + memset(&data, 0, sizeof(data)); - if (lseek(gpio->fd, 0, SEEK_SET) == -1) + if (gpio->fd <= 0) { return GPIO_ERROR; } - if (write(gpio->fd, buf, 1) != 1) + if (ioctl(gpio->fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data) < 0) { - rc = GPIO_WRITE_ERROR; + return GPIO_READ_ERROR; } - return rc; -} -int gpio_read(GPIO* gpio, uint8_t *value) -{ - g_assert (gpio != NULL); - char buf[1]; - int r = GPIO_OK; - if (gpio->fd <= 0) - { - r = GPIO_ERROR; - } - else - { - if (lseek(gpio->fd, 0, SEEK_SET) == -1) - { - return GPIO_ERROR; - } + *value = data.values[0]; - if (read(gpio->fd,&buf,1) != 1) - { - r = GPIO_READ_ERROR; - } else { - if (buf[0]=='1') { - *value = 1; - } else { - *value = 0; - } - } - } - return r; -} -int gpio_clock_cycle(GPIO* gpio, int num_clks) { - g_assert (gpio != NULL); - int i=0; - int r=GPIO_OK; - for (i=0;i<num_clks;i++) { - if (gpio_writec(gpio,'0') == -1) { - r = GPIO_WRITE_ERROR; - break; - } - if (gpio_writec(gpio,'1') == -1) { - r = GPIO_WRITE_ERROR; - break; - } - } - return r; + return GPIO_OK; } /** @@ -215,16 +171,6 @@ int get_gpio_base() */ int convert_gpio_to_num(const char* gpio) { - static int gpio_base = -1; - if (gpio_base == -1) - { - gpio_base = get_gpio_base(); - if (gpio_base < 0) - { - return gpio_base; - } - } - size_t len = strlen(gpio); if (len < 2) { @@ -255,7 +201,7 @@ int convert_gpio_to_num(const char* gpio) port += 26 * (toupper(gpio[len-3]) - 'A' + 1); } - return gpio_base + (port * GPIO_PORT_OFFSET) + offset; + return (port * GPIO_PORT_OFFSET) + offset; } /** @@ -351,145 +297,64 @@ int gpio_get_params(GPIO* gpio) return GPIO_LOOKUP_ERROR; } } + // TODO: For the purposes of skeleton and the projects that use it, + // it should be safe to assume this will always be 0. Eventually skeleton + // should be going away, but if the need arises before then this may need + // to be updated to handle non-zero cases. + gpio->chip_id = 0; return GPIO_OK; } -// Gets the gpio device path from gpio manager object -int gpio_init(GPIO* gpio) +int gpio_open(GPIO* gpio, uint8_t default_value) { - int rc = gpio_get_params(gpio); - if (rc != GPIO_OK) - { - return rc; - } - - g_print("GPIO Lookup: %s = %d,%s\n",gpio->name,gpio->num,gpio->direction); - - //export and set direction - char dev[254]; - char data[4]; - int fd; - do { - struct stat st; - - sprintf(dev,"%s/gpio%d/value",gpio->dev,gpio->num); - //check if gpio is exported, if not export - int result = stat(dev, &st); - if (result) - { - sprintf(dev,"%s/export",gpio->dev); - fd = open(dev, O_WRONLY); - if (fd == GPIO_ERROR) { - rc = GPIO_OPEN_ERROR; - break; - } - sprintf(data,"%d",gpio->num); - rc = write(fd,data,strlen(data)); - close(fd); - if (rc != strlen(data)) { - rc = GPIO_WRITE_ERROR; - break; - } - } - const char* file = "edge"; - const char* direction = gpio->direction; - if (strcmp(direction, "in") == 0) - { - file = "direction"; - } - else if (strcmp(direction, "out") == 0) - { - file = "direction"; - - // Read current value, so we can set 'high' or 'low'. - // Setting direction directly to 'out' is the same as - // setting to 'low' which can change the value in the - // GPIO. - uint8_t value = 0; - rc = gpio_open(gpio); - if (rc) break; - rc = gpio_read(gpio, &value); - if (rc) break; - gpio_close(gpio); - - direction = (value ? "high" : "low"); - } - sprintf(dev,"%s/gpio%d/%s",gpio->dev,gpio->num,file); - fd = open(dev,O_WRONLY); - if (fd == GPIO_ERROR) { - rc = GPIO_WRITE_ERROR; - break; - } - rc = write(fd,direction,strlen(direction)); - if (rc != strlen(direction)) { - rc = GPIO_WRITE_ERROR; - break; - } - - close(fd); - rc = GPIO_OK; - } while(0); - - return rc; -} - - - - -char* get_gpio_dev(GPIO* gpio) -{ - char* buf; - asprintf(&buf, "%s/gpio%d/value", gpio->dev, gpio->num); - return buf; -} + g_assert (gpio != NULL); -int gpio_open_interrupt(GPIO* gpio, GIOFunc func, gpointer user_data) -{ - int rc = GPIO_OK; char buf[255]; - sprintf(buf, "%s/gpio%d/value", gpio->dev, gpio->num); - gpio->fd = open(buf, O_RDONLY | O_NONBLOCK ); - gpio->irq_inited = false; + sprintf(buf, "/dev/gpiochip%d", gpio->chip_id); + gpio->fd = open(buf, 0); if (gpio->fd == -1) { - rc = GPIO_OPEN_ERROR; - } - else - { - GIOChannel* channel = g_io_channel_unix_new( gpio->fd); - guint id = g_io_add_watch( channel, G_IO_PRI, func, user_data ); + return GPIO_OPEN_ERROR; } - return rc; -} -int gpio_open(GPIO* gpio) -{ - g_assert (gpio != NULL); + struct gpiohandle_request req; + memset(&req, 0, sizeof(req)); + strncpy(req.consumer_label, "skeleton-gpio", sizeof(req.consumer_label)); + // open gpio for writing or reading - char buf[254]; - int rc = 0; - gpio->fd = -1; - if (gpio->direction == NULL) { + if (gpio->direction == NULL) + { + gpio_close(gpio); return GPIO_OPEN_ERROR; } - if (strcmp(gpio->direction,"in")==0) + req.flags = (strcmp(gpio->direction,"in") == 0) ? GPIOHANDLE_REQUEST_INPUT + : GPIOHANDLE_REQUEST_OUTPUT; + + req.lineoffsets[0] = gpio->num; + req.lines = 1; + + if (strcmp(gpio->direction,"out") == 0) { - sprintf(buf, "%s/gpio%d/value", gpio->dev, gpio->num); - gpio->fd = open(buf, O_RDONLY); + req.default_values[0] = default_value; } - else - { - sprintf(buf, "%s/gpio%d/value", gpio->dev, gpio->num); - gpio->fd = open(buf, O_RDWR); - } - if (gpio->fd == -1) { + int rc = ioctl(gpio->fd, GPIO_GET_LINEHANDLE_IOCTL, &req); + if (rc < 0) + { + gpio_close(gpio); return GPIO_OPEN_ERROR; } + gpio_close(gpio); + gpio->fd = req.fd; + return GPIO_OK; } void gpio_close(GPIO* gpio) { + if(gpio->fd < 0) + return; + close(gpio->fd); + gpio->fd = -1; } diff --git a/libopenbmc_intf/gpio.h b/libopenbmc_intf/gpio.h index dc439c8..54ff6af 100644 --- a/libopenbmc_intf/gpio.h +++ b/libopenbmc_intf/gpio.h @@ -9,6 +9,7 @@ typedef struct { gchar* name; gchar* dev; uint16_t num; + uint16_t chip_id; gchar* direction; int fd; bool irq_inited; @@ -24,13 +25,10 @@ typedef struct { #define GPIO_WRITE_ERROR 0x10 #define GPIO_LOOKUP_ERROR 0x20 -int gpio_init(GPIO*); void gpio_close(GPIO*); -int gpio_open(GPIO*); -int gpio_open_interrupt(GPIO*, GIOFunc, gpointer); +int gpio_open(GPIO*, uint8_t); int gpio_write(GPIO*, uint8_t); -int gpio_writec(GPIO*, char); -int gpio_clock_cycle(GPIO*, int); +int gpio_get_params(GPIO*); int gpio_read(GPIO*,uint8_t*); void gpio_inits_done(); |