Add support for multiple gpio banks

Currently, the code assumes that all the GPIOs are on one bank. Support
for systems that do not use the alphanumeric reference and have multiple
gpio banks is added. Using the num/pin key distinction, the parsing
process is differentiated between an alphanumeric reference and integer
labeling.

NOTE: Since this change assumes /dev/gpiochip0 is present, systems using
it need to be using at least Linux kernel 4.8.

Change-Id: Ib11531bf326f6a9291fc03caaad323c0779b5a0d
Signed-off-by: Jonico Eustaquio <jonico.eustaquio@fii-na.com>
diff --git a/libopenbmc_intf/gpio.c b/libopenbmc_intf/gpio.c
index 1785e79..c59de31 100644
--- a/libopenbmc_intf/gpio.c
+++ b/libopenbmc_intf/gpio.c
@@ -19,6 +19,7 @@
 
 #define GPIO_PORT_OFFSET 8
 #define GPIO_BASE_PATH "/sys/class/gpio"
+#define DEV_NAME "/dev/gpiochip0"
 
 cJSON* gpio_json = NULL;
 
@@ -295,7 +296,36 @@
 	const cJSON* num = cJSON_GetObjectItem(def, "num");
 	if ((num != NULL) && cJSON_IsNumber(num))
 	{
-		gpio->num = num->valueint;
+		// When the "num" key is used, we will assume
+		// that the system has gpiochip0 and that each
+		// bank has the same amount of pins
+
+		struct gpiochip_info info;
+		int fd, ret;
+		// Open the device
+		fd = open(DEV_NAME, O_RDONLY);
+		if (fd < 0)
+		{
+			fprintf(stderr, "Unable to open %s: %s\n",
+					DEV_NAME, strerror(errno));
+			return GPIO_LOOKUP_ERROR;
+		}
+
+		// Query GPIO chip info
+		ret = ioctl(fd, GPIO_GET_CHIPINFO_IOCTL, &info);
+		if (ret == -1)
+		{
+			fprintf(stderr, "Unable to get chip info from ioctl: %s\n",
+					strerror(errno));
+			close(fd);
+			return GPIO_LOOKUP_ERROR;
+		}
+
+		close(fd);
+		printf("Number of pins per bank: %d\n", info.lines);
+
+		gpio->num = (num->valueint) % info.lines;
+		gpio->chip_id = (num->valueint) / info.lines;
 	}
 	else
 	{