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>
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)
-{
- g_assert (gpio != NULL);
- int rc = GPIO_OK;
- char buf[1];
- buf[0] = value;
-
- if (lseek(gpio->fd, 0, SEEK_SET) == -1)
- {
- return GPIO_ERROR;
- }
-
- if (write(gpio->fd, buf, 1) != 1)
- {
- rc = GPIO_WRITE_ERROR;
- }
- return rc;
-}
-
int gpio_write(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));
+ 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_read(GPIO* gpio, uint8_t *value)
{
g_assert (gpio != NULL);
- char buf[1];
- int r = GPIO_OK;
+ struct gpiohandle_data data;
+ memset(&data, 0, sizeof(data));
+
if (gpio->fd <= 0)
{
- r = GPIO_ERROR;
+ return GPIO_ERROR;
}
- else
- {
- if (lseek(gpio->fd, 0, SEEK_SET) == -1)
- {
- return GPIO_ERROR;
- }
- if (read(gpio->fd,&buf,1) != 1)
- {
- r = GPIO_READ_ERROR;
- } else {
- if (buf[0]=='1') {
- *value = 1;
- } else {
- *value = 0;
- }
- }
+ if (ioctl(gpio->fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data) < 0)
+ {
+ return GPIO_READ_ERROR;
}
- 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;
+
+ *value = data.values[0];
+
+ return GPIO_OK;
}
/**
@@ -215,16 +171,6 @@
*/
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 @@
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 @@
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 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;
-}
-
-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;
- 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 rc;
-}
-
-int gpio_open(GPIO* gpio)
+int gpio_open(GPIO* gpio, uint8_t default_value)
{
g_assert (gpio != NULL);
- // open gpio for writing or reading
- char buf[254];
- int rc = 0;
- gpio->fd = -1;
- if (gpio->direction == NULL) {
- return GPIO_OPEN_ERROR;
- }
- if (strcmp(gpio->direction,"in")==0)
- {
- sprintf(buf, "%s/gpio%d/value", gpio->dev, gpio->num);
- gpio->fd = open(buf, O_RDONLY);
- }
- else
- {
- sprintf(buf, "%s/gpio%d/value", gpio->dev, gpio->num);
- gpio->fd = open(buf, O_RDWR);
- }
- if (gpio->fd == -1) {
+ char buf[255];
+ sprintf(buf, "/dev/gpiochip%d", gpio->chip_id);
+ gpio->fd = open(buf, 0);
+ if (gpio->fd == -1)
+ {
return GPIO_OPEN_ERROR;
}
+
+ 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
+ if (gpio->direction == NULL)
+ {
+ gpio_close(gpio);
+ return GPIO_OPEN_ERROR;
+ }
+ 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)
+ {
+ req.default_values[0] = default_value;
+ }
+
+ 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 @@
gchar* name;
gchar* dev;
uint16_t num;
+ uint16_t chip_id;
gchar* direction;
int fd;
bool irq_inited;
@@ -24,13 +25,10 @@
#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();
diff --git a/op-pwrctl/power_control_obj.c b/op-pwrctl/power_control_obj.c
index dedcbe2..ada9b3b 100644
--- a/op-pwrctl/power_control_obj.c
+++ b/op-pwrctl/power_control_obj.c
@@ -52,8 +52,9 @@
}
uint8_t pgood_state;
- int rc = gpio_open(&g_gpio_configs.power_gpio.power_good_in);
+ int rc = gpio_open(&g_gpio_configs.power_gpio.power_good_in, 0);
if(rc != GPIO_OK) {
+ gpio_close(&g_gpio_configs.power_gpio.power_good_in);
g_print("ERROR PowerControl: GPIO open error (gpio=%s,rc=%d)\n",
g_gpio_configs.power_gpio.power_good_in.name, rc);
return FALSE;
@@ -81,15 +82,16 @@
for(i = 0; i < g_gpio_configs.power_gpio.num_reset_outs; i++)
{
GPIO *reset_out = &g_gpio_configs.power_gpio.reset_outs[i];
- rc = gpio_open(reset_out);
+ reset_state = pgood_state ^ g_gpio_configs.power_gpio.reset_pols[i];
+ rc = gpio_open(reset_out, reset_state);
if(rc != GPIO_OK)
{
+ gpio_close(reset_out);
g_print("ERROR PowerControl: GPIO open error (gpio=%s,rc=%d)\n",
reset_out->name, rc);
continue;
}
- reset_state = pgood_state ^ g_gpio_configs.power_gpio.reset_pols[i];
g_print("PowerControl: pgood: %d, setting reset %s to %d\n",
(int)pgood_state, reset_out->name, (int)reset_state);
gpio_write(reset_out, reset_state);
@@ -111,15 +113,16 @@
continue;
}
}
- rc = gpio_open(pci_reset_out);
+ reset_state = pgood_state ^ g_gpio_configs.power_gpio.pci_reset_pols[i];
+ rc = gpio_open(pci_reset_out, reset_state);
if(rc != GPIO_OK)
{
+ gpio_close(pci_reset_out);
g_print("ERROR PowerControl: GPIO open error (gpio=%s,rc=%d)\n",
pci_reset_out->name, rc);
continue;
}
- reset_state = pgood_state ^ g_gpio_configs.power_gpio.pci_reset_pols[i];
g_print("PowerControl: pgood: %d, setting pci reset %s to %d\n",
(int)pgood_state, pci_reset_out->name, (int)reset_state);
gpio_write(pci_reset_out, reset_state);
@@ -202,9 +205,10 @@
if (ignore)
return;
- rc = gpio_open(&g_gpio_configs.power_gpio.power_good_in);
+ rc = gpio_open(&g_gpio_configs.power_gpio.power_good_in, 0);
if(rc != GPIO_OK)
{
+ gpio_close(&g_gpio_configs.power_gpio.power_good_in);
g_print("ERROR PowerControl: on_boot_progress(): GPIO open error (gpio=%s,rc=%d)\n",
g_gpio_configs.power_gpio.power_good_in.name, rc);
return;
@@ -220,15 +224,16 @@
if(!g_gpio_configs.power_gpio.pci_reset_holds[i])
continue;
- rc = gpio_open(pci_reset_out);
+ reset_state = pgood_state ^ g_gpio_configs.power_gpio.pci_reset_pols[i];
+ rc = gpio_open(pci_reset_out, reset_state);
if(rc != GPIO_OK)
{
+ gpio_close(pci_reset_out);
g_print("ERROR PowerControl: GPIO open error (gpio=%s,rc=%d)\n",
pci_reset_out->name, rc);
continue;
}
- reset_state = pgood_state ^ g_gpio_configs.power_gpio.pci_reset_pols[i];
g_print("PowerControl: pgood: %d, setting pci reset %s to %d\n",
(int)pgood_state, pci_reset_out->name, (int)reset_state);
gpio_write(pci_reset_out, reset_state);
@@ -267,17 +272,19 @@
uint8_t power_up_out;
for (i = 0; i < power_gpio->num_power_up_outs; i++) {
GPIO *power_pin = &power_gpio->power_up_outs[i];
- error = gpio_open(power_pin);
+ power_up_out = state ^ !power_gpio->power_up_pols[i];
+ error = gpio_open(power_pin, power_up_out);
if(error != GPIO_OK) {
+ gpio_close(power_pin);
g_print("ERROR PowerControl: GPIO open error (gpio=%s,rc=%d)\n",
power_gpio->power_up_outs[i].name, error);
continue;
}
- power_up_out = state ^ !power_gpio->power_up_pols[i];
g_print("PowerControl: setting power up %s to %d\n",
power_gpio->power_up_outs[i].name, (int)power_up_out);
error = gpio_write(power_pin, power_up_out);
if(error != GPIO_OK) {
+ gpio_close(power_pin);
continue;
}
gpio_close(power_pin);
@@ -294,16 +301,17 @@
* power pins' states. This commits the changes to the latch states. */
if (power_gpio->latch_out.name != NULL) {
int rc;
- uint8_t latch_value = 0;
- rc = gpio_open(&power_gpio->latch_out);
+ uint8_t latch_value = 1;
+ rc = gpio_open(&power_gpio->latch_out, latch_value);
if (rc != GPIO_OK) {
/* Failures are non-fatal. */
+ gpio_close(&power_gpio->latch_out);
g_print("PowerControl ERROR failed to open latch %s rc=%d\n",
power_gpio->latch_out.name, rc);
return TRUE;
}
/* Make the latch transparent for as brief of a time as possible. */
- rc = gpio_write(&power_gpio->latch_out, 1);
+ rc = gpio_write(&power_gpio->latch_out, latch_value--);
if (rc != GPIO_OK) {
g_print("PowerControl ERROR failed to assert latch %s rc=%d\n",
power_gpio->latch_out.name, rc);
@@ -311,7 +319,7 @@
g_print("PowerControl asserted latch %s\n",
power_gpio->latch_out.name);
}
- rc = gpio_write(&power_gpio->latch_out, 0);
+ rc = gpio_write(&power_gpio->latch_out, latch_value);
if (rc != GPIO_OK) {
g_print("PowerControl ERROR failed to clear latch %s rc=%d\n",
power_gpio->latch_out.name, rc);
@@ -355,29 +363,29 @@
// get gpio device paths
if(power_gpio->latch_out.name != NULL) { /* latch is optional */
- rc = gpio_init(&power_gpio->latch_out);
+ rc = gpio_get_params(&power_gpio->latch_out);
if(rc != GPIO_OK) {
error = rc;
}
}
- rc = gpio_init(&power_gpio->power_good_in);
+ rc = gpio_get_params(&power_gpio->power_good_in);
if(rc != GPIO_OK) {
error = rc;
}
for(int i = 0; i < power_gpio->num_power_up_outs; i++) {
- rc = gpio_init(&power_gpio->power_up_outs[i]);
+ rc = gpio_get_params(&power_gpio->power_up_outs[i]);
if(rc != GPIO_OK) {
error = rc;
}
}
for(int i = 0; i < power_gpio->num_reset_outs; i++) {
- rc = gpio_init(&power_gpio->reset_outs[i]);
+ rc = gpio_get_params(&power_gpio->reset_outs[i]);
if(rc != GPIO_OK) {
error = rc;
}
}
for(int i = 0; i < power_gpio->num_pci_reset_outs; i++) {
- rc = gpio_init(&power_gpio->pci_reset_outs[i]);
+ rc = gpio_get_params(&power_gpio->pci_reset_outs[i]);
if(rc != GPIO_OK) {
error = rc;
}
@@ -385,12 +393,14 @@
gpio_inits_done();
- rc = gpio_open(&power_gpio->power_good_in);
+ rc = gpio_open(&power_gpio->power_good_in, 0);
if(rc != GPIO_OK) {
+ gpio_close(&power_gpio->power_good_in);
return rc;
}
rc = gpio_read(&power_gpio->power_good_in, &pgood_state);
if(rc != GPIO_OK) {
+ gpio_close(&power_gpio->power_good_in);
return rc;
}
gpio_close(&power_gpio->power_good_in);