irqdomain: Port system to new API

The following merge commit chose the irq_domain implementation
from AU_LINUX_ANDROID_ICS.04.00.04.00.126 instead of the version
in v3.4.

commit f132c6cf77251e011e1dad0ec88c0b1fda16d5aa
Merge: 23016de 3f6240f
Author: Steve Muckle <smuckle@codeaurora.org>
Date:   Wed Jun 6 18:30:57 2012 -0700

    Merge commit 'AU_LINUX_ANDROID_ICS.04.00.04.00.126' into
    msm-3.4

Since this version is inconsistent with the upstream,
port the irq_domain framework to the version in v3.4 and
makes all necessary changes to clients that are out of spec.

Details of client ports are below.

-Update the qpnp-int driver for revmap irq_domain API. The revmap
irq_domain implementation introduces a reverse lookup scheme using
a radix tree. This scheme is useful for controllers like qpnp-int
that require a large range of hwirqs.

-Bring the ARM GIC driver up to v3.4, being careful
to port existing CAF changes.

-Partially port the gpio-msm-common driver to the new irq_domain API.
Enable the gpio-msm-common driver to work with the new irq_domain
API using a linear revmap. It is not a full port since irq_domain
is still only registered for Device Tree configurations. It should
be registered even for legacy configurations.

In addition, the irq_domains .map function should be setting all
the fields currently done in msm_gpio_probe(). That's not
currently possible since msm_gpio_probe is invoked
unconditionally - even from Device Tree configurations.

Finally, gpio-msm-common should be converted into a real
platform_device so that probe() is invoked due to driver and
device matching.

Change-Id: I19fa50171bd244759fb6076e3cddc70896d8727b
Signed-off-by: Michael Bohan <mbohan@codeaurora.org>
diff --git a/drivers/gpio/gpio-msm-common.c b/drivers/gpio/gpio-msm-common.c
index 9a9a783..5539950 100644
--- a/drivers/gpio/gpio-msm-common.c
+++ b/drivers/gpio/gpio-msm-common.c
@@ -100,7 +100,7 @@
 	DECLARE_BITMAP(enabled_irqs, NR_MSM_GPIOS);
 	DECLARE_BITMAP(wake_irqs, NR_MSM_GPIOS);
 	DECLARE_BITMAP(dual_edge_irqs, NR_MSM_GPIOS);
-	struct irq_domain domain;
+	struct irq_domain *domain;
 };
 
 static DEFINE_SPINLOCK(tlmm_lock);
@@ -152,15 +152,14 @@
 static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
 {
 	struct msm_gpio_dev *g_dev = to_msm_gpio_dev(chip);
-	struct irq_domain *domain = &g_dev->domain;
-	return domain->irq_base + (offset - chip->base);
+	struct irq_domain *domain = g_dev->domain;
+	return irq_linear_revmap(domain, offset - chip->base);
 }
 
 static inline int msm_irq_to_gpio(struct gpio_chip *chip, unsigned irq)
 {
-	struct msm_gpio_dev *g_dev = to_msm_gpio_dev(chip);
-	struct irq_domain *domain = &g_dev->domain;
-	return irq - domain->irq_base;
+	struct irq_data *irq_data = irq_get_irq_data(irq);
+	return irq_data->hwirq;
 }
 #else
 static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
@@ -391,6 +390,7 @@
  */
 static struct lock_class_key msm_gpio_lock_class;
 
+/* TODO: This should be a real platform_driver */
 static int __devinit msm_gpio_probe(void)
 {
 	int i, irq, ret;
@@ -573,12 +573,12 @@
 EXPORT_SYMBOL(msm_gpio_install_direct_irq);
 
 #ifdef CONFIG_OF
-static int msm_gpio_domain_dt_translate(struct irq_domain *d,
-					struct device_node *controller,
-					const u32 *intspec,
-					unsigned int intsize,
-					unsigned long *out_hwirq,
-					unsigned int *out_type)
+static int msm_gpio_irq_domain_xlate(struct irq_domain *d,
+				     struct device_node *controller,
+				     const u32 *intspec,
+				     unsigned int intsize,
+				     unsigned long *out_hwirq,
+				     unsigned int *out_type)
 {
 	if (d->of_node != controller)
 		return -EINVAL;
@@ -593,32 +593,32 @@
 	return 0;
 }
 
+/*
+ * TODO: this really should be doing all the things that msm_gpio_probe() does,
+ * but since the msm_gpio_probe is called unconditionally for DT and non-DT
+ * configs, we can't duplicate it here. This should be fixed.
+ */
+int msm_gpio_irq_domain_map(struct irq_domain *d, unsigned int irq,
+			  irq_hw_number_t hwirq)
+{
+	return 0;
+}
+
 static struct irq_domain_ops msm_gpio_irq_domain_ops = {
-	.dt_translate = msm_gpio_domain_dt_translate,
+	.xlate = msm_gpio_irq_domain_xlate,
+	.map = msm_gpio_irq_domain_map,
 };
 
 int __init msm_gpio_of_init(struct device_node *node,
 			    struct device_node *parent)
 {
-	struct irq_domain *domain = &msm_gpio.domain;
-	int start;
-
-	start = irq_domain_find_free_range(0, NR_MSM_GPIOS);
-	domain->irq_base = irq_alloc_descs(start, 0, NR_MSM_GPIOS,
-							numa_node_id());
-	if (IS_ERR_VALUE(domain->irq_base)) {
-		WARN(1, "Cannot allocate irq_descs @ IRQ%d\n", start);
-		return domain->irq_base;
+	msm_gpio.domain = irq_domain_add_linear(node, NR_MSM_GPIOS,
+			&msm_gpio_irq_domain_ops, &msm_gpio);
+	if (!msm_gpio.domain) {
+		WARN(1, "Cannot allocate irq_domain\n");
+		return -ENOMEM;
 	}
 
-	domain->nr_irq = NR_MSM_GPIOS;
-	domain->of_node = of_node_get(node);
-	domain->priv = &msm_gpio;
-	domain->ops = &msm_gpio_irq_domain_ops;
-	irq_domain_add(domain);
-	msm_gpio.gpio_chip.of_node = of_node_get(node);
-	pr_debug("%s: irq_base = %u\n", __func__, domain->irq_base);
-
 	return 0;
 }
 #endif