gpio: adnp: switch to use irqchip helpers

This switches the ADNP GPIO driver to use the gpiolib
irqchip helpers. Also do some random refactoring to make it
look like most other GPIO drivers.

Cc: Roland Stigge <stigge@antcom.de>
Cc: Lars Poeschel <poeschel@lemonage.de>
Cc: Thierry Reding <thierry.reding@gmail.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
diff --git a/drivers/gpio/gpio-adnp.c b/drivers/gpio/gpio-adnp.c
index 416b220..d3d0a90 100644
--- a/drivers/gpio/gpio-adnp.c
+++ b/drivers/gpio/gpio-adnp.c
@@ -6,10 +6,9 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
-#include <linux/irqdomain.h>
 #include <linux/module.h>
 #include <linux/of_irq.h>
 #include <linux/seq_file.h>
@@ -27,8 +26,6 @@
 	unsigned int reg_shift;
 
 	struct mutex i2c_lock;
-
-	struct irq_domain *domain;
 	struct mutex irq_lock;
 
 	u8 *irq_enable;
@@ -253,6 +250,7 @@
 static int adnp_gpio_setup(struct adnp *adnp, unsigned int num_gpios)
 {
 	struct gpio_chip *chip = &adnp->gpio;
+	int err;
 
 	adnp->reg_shift = get_count_order(num_gpios) - 3;
 
@@ -272,6 +270,10 @@
 	chip->of_node = chip->dev->of_node;
 	chip->owner = THIS_MODULE;
 
+	err = gpiochip_add(chip);
+	if (err)
+		return err;
+
 	return 0;
 }
 
@@ -326,7 +328,8 @@
 
 		for_each_set_bit(bit, &pending, 8) {
 			unsigned int child_irq;
-			child_irq = irq_find_mapping(adnp->domain, base + bit);
+			child_irq = irq_find_mapping(adnp->gpio.irqdomain,
+						     base + bit);
 			handle_nested_irq(child_irq);
 		}
 	}
@@ -334,35 +337,32 @@
 	return IRQ_HANDLED;
 }
 
-static int adnp_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+static void adnp_irq_mask(struct irq_data *d)
 {
-	struct adnp *adnp = to_adnp(chip);
-	return irq_create_mapping(adnp->domain, offset);
-}
-
-static void adnp_irq_mask(struct irq_data *data)
-{
-	struct adnp *adnp = irq_data_get_irq_chip_data(data);
-	unsigned int reg = data->hwirq >> adnp->reg_shift;
-	unsigned int pos = data->hwirq & 7;
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct adnp *adnp = to_adnp(gc);
+	unsigned int reg = d->hwirq >> adnp->reg_shift;
+	unsigned int pos = d->hwirq & 7;
 
 	adnp->irq_enable[reg] &= ~BIT(pos);
 }
 
-static void adnp_irq_unmask(struct irq_data *data)
+static void adnp_irq_unmask(struct irq_data *d)
 {
-	struct adnp *adnp = irq_data_get_irq_chip_data(data);
-	unsigned int reg = data->hwirq >> adnp->reg_shift;
-	unsigned int pos = data->hwirq & 7;
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct adnp *adnp = to_adnp(gc);
+	unsigned int reg = d->hwirq >> adnp->reg_shift;
+	unsigned int pos = d->hwirq & 7;
 
 	adnp->irq_enable[reg] |= BIT(pos);
 }
 
-static int adnp_irq_set_type(struct irq_data *data, unsigned int type)
+static int adnp_irq_set_type(struct irq_data *d, unsigned int type)
 {
-	struct adnp *adnp = irq_data_get_irq_chip_data(data);
-	unsigned int reg = data->hwirq >> adnp->reg_shift;
-	unsigned int pos = data->hwirq & 7;
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct adnp *adnp = to_adnp(gc);
+	unsigned int reg = d->hwirq >> adnp->reg_shift;
+	unsigned int pos = d->hwirq & 7;
 
 	if (type & IRQ_TYPE_EDGE_RISING)
 		adnp->irq_rise[reg] |= BIT(pos);
@@ -387,16 +387,18 @@
 	return 0;
 }
 
-static void adnp_irq_bus_lock(struct irq_data *data)
+static void adnp_irq_bus_lock(struct irq_data *d)
 {
-	struct adnp *adnp = irq_data_get_irq_chip_data(data);
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct adnp *adnp = to_adnp(gc);
 
 	mutex_lock(&adnp->irq_lock);
 }
 
-static void adnp_irq_bus_unlock(struct irq_data *data)
+static void adnp_irq_bus_unlock(struct irq_data *d)
 {
-	struct adnp *adnp = irq_data_get_irq_chip_data(data);
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct adnp *adnp = to_adnp(gc);
 	unsigned int num_regs = 1 << adnp->reg_shift, i;
 
 	mutex_lock(&adnp->i2c_lock);
@@ -408,26 +410,6 @@
 	mutex_unlock(&adnp->irq_lock);
 }
 
-static int adnp_irq_reqres(struct irq_data *data)
-{
-	struct adnp *adnp = irq_data_get_irq_chip_data(data);
-
-	if (gpio_lock_as_irq(&adnp->gpio, data->hwirq)) {
-		dev_err(adnp->gpio.dev,
-			"unable to lock HW IRQ %lu for IRQ\n",
-			data->hwirq);
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static void adnp_irq_relres(struct irq_data *data)
-{
-	struct adnp *adnp = irq_data_get_irq_chip_data(data);
-
-	gpio_unlock_as_irq(&adnp->gpio, data->hwirq);
-}
-
 static struct irq_chip adnp_irq_chip = {
 	.name = "gpio-adnp",
 	.irq_mask = adnp_irq_mask,
@@ -435,29 +417,6 @@
 	.irq_set_type = adnp_irq_set_type,
 	.irq_bus_lock = adnp_irq_bus_lock,
 	.irq_bus_sync_unlock = adnp_irq_bus_unlock,
-	.irq_request_resources = adnp_irq_reqres,
-	.irq_release_resources = adnp_irq_relres,
-};
-
-static int adnp_irq_map(struct irq_domain *domain, unsigned int irq,
-			irq_hw_number_t hwirq)
-{
-	irq_set_chip_data(irq, domain->host_data);
-	irq_set_chip(irq, &adnp_irq_chip);
-	irq_set_nested_thread(irq, true);
-
-#ifdef CONFIG_ARM
-	set_irq_flags(irq, IRQF_VALID);
-#else
-	irq_set_noprobe(irq);
-#endif
-
-	return 0;
-}
-
-static const struct irq_domain_ops adnp_irq_domain_ops = {
-	.map = adnp_irq_map,
-	.xlate = irq_domain_xlate_twocell,
 };
 
 static int adnp_irq_setup(struct adnp *adnp)
@@ -503,35 +462,28 @@
 		adnp->irq_enable[i] = 0x00;
 	}
 
-	adnp->domain = irq_domain_add_linear(chip->of_node, chip->ngpio,
-					     &adnp_irq_domain_ops, adnp);
-
-	err = request_threaded_irq(adnp->client->irq, NULL, adnp_irq,
-				   IRQF_TRIGGER_RISING | IRQF_ONESHOT,
-				   dev_name(chip->dev), adnp);
+	err = devm_request_threaded_irq(chip->dev, adnp->client->irq,
+					NULL, adnp_irq,
+					IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+					dev_name(chip->dev), adnp);
 	if (err != 0) {
 		dev_err(chip->dev, "can't request IRQ#%d: %d\n",
 			adnp->client->irq, err);
 		return err;
 	}
 
-	chip->to_irq = adnp_gpio_to_irq;
-	return 0;
-}
-
-static void adnp_irq_teardown(struct adnp *adnp)
-{
-	unsigned int irq, i;
-
-	free_irq(adnp->client->irq, adnp);
-
-	for (i = 0; i < adnp->gpio.ngpio; i++) {
-		irq = irq_find_mapping(adnp->domain, i);
-		if (irq > 0)
-			irq_dispose_mapping(irq);
+	err = gpiochip_irqchip_add(chip,
+				   &adnp_irq_chip,
+				   0,
+				   handle_simple_irq,
+				   IRQ_TYPE_NONE);
+	if (err) {
+		dev_err(chip->dev,
+			"could not connect irqchip to gpiochip\n");
+		return err;
 	}
 
-	irq_domain_remove(adnp->domain);
+	return 0;
 }
 
 static int adnp_i2c_probe(struct i2c_client *client,
@@ -558,38 +510,25 @@
 	adnp->client = client;
 
 	err = adnp_gpio_setup(adnp, num_gpios);
-	if (err < 0)
+	if (err)
 		return err;
 
 	if (of_find_property(np, "interrupt-controller", NULL)) {
 		err = adnp_irq_setup(adnp);
-		if (err < 0)
-			goto teardown;
+		if (err)
+			return err;
 	}
 
-	err = gpiochip_add(&adnp->gpio);
-	if (err < 0)
-		goto teardown;
-
 	i2c_set_clientdata(client, adnp);
+
 	return 0;
-
-teardown:
-	if (of_find_property(np, "interrupt-controller", NULL))
-		adnp_irq_teardown(adnp);
-
-	return err;
 }
 
 static int adnp_i2c_remove(struct i2c_client *client)
 {
 	struct adnp *adnp = i2c_get_clientdata(client);
-	struct device_node *np = client->dev.of_node;
 
 	gpiochip_remove(&adnp->gpio);
-	if (of_find_property(np, "interrupt-controller", NULL))
-		adnp_irq_teardown(adnp);
-
 	return 0;
 }