From 81e166ec0a35ed5a01e2453603b0b1c73a0532cc Mon Sep 17 00:00:00 2001
From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Date: Fri, 19 Feb 2016 07:18:26 -0800
Subject: [PATCH 2/6] gpio: pca953x: provide GPIO base based on _UID

Custom kernel for Intel Galileo Gen2 provides and moreover libmraa relies on
the continuous GPIO space. To do such we have to configure GPIO base per each
GPIO expander. The only value we can use is the ACPI _UID.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

Upstream-status: Inappropriate, custom code for legacy userspace
Signed-off-by: Saul Wold <sgw@linux.intel.com>
Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
---
 drivers/gpio/gpio-pca953x.c | 44 +++++++++++++++++++++++++++++++++++++-------
 1 file changed, 37 insertions(+), 7 deletions(-)

diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index 2d4892cc70fb..f23a4b4c26a2 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -77,12 +77,6 @@ static const struct i2c_device_id pca953x_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, pca953x_id);
 
-static const struct acpi_device_id pca953x_acpi_ids[] = {
-	{ "INT3491", 16 | PCA953X_TYPE | PCA_INT, },
-	{ }
-};
-MODULE_DEVICE_TABLE(acpi, pca953x_acpi_ids);
-
 #define MAX_BANK 5
 #define BANK_SZ 8
 
@@ -109,6 +103,35 @@ struct pca953x_chip {
 	unsigned long driver_data;
 };
 
+struct pca953x_info {
+	kernel_ulong_t driver_data;
+	void (*setup)(struct pca953x_chip *chip);
+};
+
+static void pca953x_setup_int3491(struct pca953x_chip *chip)
+{
+	struct acpi_device *adev = ACPI_COMPANION(&chip->client->dev);
+	unsigned int uid;
+
+	if (kstrtouint(acpi_device_uid(adev), 0, &uid) || !uid--)
+		return;
+
+	chip->gpio_start = 8 /* sch_gpio */ +
+			   8 /* gpio-dwapb */ +
+			  16 /* pca9535 */ * uid;
+}
+
+static const struct pca953x_info pca953x_info_int3491 = {
+	.driver_data = 16 | PCA953X_TYPE | PCA_INT,
+	.setup = pca953x_setup_int3491,
+};
+
+static const struct acpi_device_id pca953x_acpi_ids[] = {
+	{ "INT3491",  (kernel_ulong_t)&pca953x_info_int3491 },
+	{ }
+};
+MODULE_DEVICE_TABLE(acpi, pca953x_acpi_ids);
+
 static inline struct pca953x_chip *to_pca(struct gpio_chip *gc)
 {
 	return container_of(gc, struct pca953x_chip, gpio_chip);
@@ -691,12 +714,19 @@ static int pca953x_probe(struct i2c_client *client,
 		chip->driver_data = id->driver_data;
 	} else {
 		const struct acpi_device_id *id;
+		const struct pca953x_info *info;
 
 		id = acpi_match_device(pca953x_acpi_ids, &client->dev);
 		if (!id)
 			return -ENODEV;
 
-		chip->driver_data = id->driver_data;
+		info = (struct pca953x_info *)id->driver_data;
+		if (!info)
+			return -ENODEV;
+
+		chip->driver_data = info->driver_data;
+		if (info->setup)
+			info->setup(chip);
 	}
 
 	chip->chip_type = PCA_CHIP_TYPE(chip->driver_data);
-- 
2.5.0

