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);