@@ -24,6 +24,7 @@
#include <linux/pm.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <linux/of_gpio.h>
#include <linux/irqdomain.h>
#include <linux/gpio.h>
#include <linux/platform_data/gpio-omap.h>
@@ -1135,7 +1136,7 @@ static int omap_gpio_probe(struct platform_device *pdev)
bank->domain = irq_domain_add_linear(node, bank->width,
- &irq_domain_simple_ops, NULL);
+ &of_gpio_irq_domain_ops, NULL);
if (!bank->domain)
return -ENODEV;
@@ -15,6 +15,8 @@
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
#include <linux/gpio.h>
#include <linux/of.h>
#include <linux/of_address.h>
@@ -253,3 +255,25 @@ void of_gpiochip_remove(struct gpio_chip *chip)
if (chip->of_node)
of_node_put(chip->of_node);
}
+
+int of_gpio_irq_domain_xlate(struct irq_domain *d, struct device_node *ctrlr,
+ const u32 *intspec, unsigned int intsize,
+ unsigned long *out_hwirq, unsigned int *out_type)
+{
+ int ret;
+
+ if (WARN_ON(intsize < 3))
+ return -EINVAL;
+
+ ret = gpio_request_one(intspec[2], GPIOF_IN, NULL);
+ if (ret)
+ return ret;
+
+ *out_hwirq = intspec[0];
+ *out_type = (intsize > 1) ? intspec[1] : IRQ_TYPE_NONE;
+ return 0;
+}
+
+const struct irq_domain_ops of_gpio_irq_domain_ops = {
+ .xlate = of_gpio_irq_domain_xlate,
+};
@@ -58,6 +58,7 @@ extern void of_gpiochip_remove(struct gpio_chip *gc);
extern int of_gpio_simple_xlate(struct gpio_chip *gc,
const struct of_phandle_args *gpiospec,
u32 *flags);
+extern const struct irq_domain_ops of_gpio_irq_domain_ops;
#else /* CONFIG_OF_GPIO */