#include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/slab.h>
 
 #include <asm/mach/irq.h>
 
 struct nmk_gpio_chip {
        struct gpio_chip chip;
+       struct irq_domain *domain;
        void __iomem *addr;
        struct clk *clk;
        unsigned int bank;
                struct nmk_gpio_chip *nmk_chip;
                int pin = PIN_NUM(cfgs[i]);
 
-               nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(pin));
+               nmk_chip = nmk_gpio_chips[pin / NMK_GPIO_PER_CHIP];
                if (!nmk_chip) {
                        ret = -EINVAL;
                        break;
 
                clk_enable(nmk_chip->clk);
                spin_lock(&nmk_chip->lock);
-               __nmk_config_pin(nmk_chip, pin - nmk_chip->chip.base,
+               __nmk_config_pin(nmk_chip, pin % NMK_GPIO_PER_CHIP,
                                 cfgs[i], sleep, glitch ? slpm : NULL);
                spin_unlock(&nmk_chip->lock);
                clk_disable(nmk_chip->clk);
        struct nmk_gpio_chip *nmk_chip;
        unsigned long flags;
 
-       nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
+       nmk_chip = nmk_gpio_chips[gpio / NMK_GPIO_PER_CHIP];
        if (!nmk_chip)
                return -EINVAL;
 
        spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
        spin_lock(&nmk_chip->lock);
 
-       __nmk_gpio_set_slpm(nmk_chip, gpio - nmk_chip->chip.base, mode);
+       __nmk_gpio_set_slpm(nmk_chip, gpio % NMK_GPIO_PER_CHIP, mode);
 
        spin_unlock(&nmk_chip->lock);
        spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
        struct nmk_gpio_chip *nmk_chip;
        unsigned long flags;
 
-       nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
+       nmk_chip = nmk_gpio_chips[gpio / NMK_GPIO_PER_CHIP];
        if (!nmk_chip)
                return -EINVAL;
 
        clk_enable(nmk_chip->clk);
        spin_lock_irqsave(&nmk_chip->lock, flags);
-       __nmk_gpio_set_pull(nmk_chip, gpio - nmk_chip->chip.base, pull);
+       __nmk_gpio_set_pull(nmk_chip, gpio % NMK_GPIO_PER_CHIP, pull);
        spin_unlock_irqrestore(&nmk_chip->lock, flags);
        clk_disable(nmk_chip->clk);
 
        struct nmk_gpio_chip *nmk_chip;
        unsigned long flags;
 
-       nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
+       nmk_chip = nmk_gpio_chips[gpio / NMK_GPIO_PER_CHIP];
        if (!nmk_chip)
                return -EINVAL;
 
        clk_enable(nmk_chip->clk);
        spin_lock_irqsave(&nmk_chip->lock, flags);
-       __nmk_gpio_set_mode(nmk_chip, gpio - nmk_chip->chip.base, gpio_mode);
+       __nmk_gpio_set_mode(nmk_chip, gpio % NMK_GPIO_PER_CHIP, gpio_mode);
        spin_unlock_irqrestore(&nmk_chip->lock, flags);
        clk_disable(nmk_chip->clk);
 
        struct nmk_gpio_chip *nmk_chip;
        u32 afunc, bfunc, bit;
 
-       nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
+       nmk_chip = nmk_gpio_chips[gpio / NMK_GPIO_PER_CHIP];
        if (!nmk_chip)
                return -EINVAL;
 
-       bit = 1 << (gpio - nmk_chip->chip.base);
+       bit = 1 << (gpio % NMK_GPIO_PER_CHIP);
 
        clk_enable(nmk_chip->clk);
 
 /* IRQ functions */
 static inline int nmk_gpio_get_bitmask(int gpio)
 {
-       return 1 << (gpio % 32);
+       return 1 << (gpio % NMK_GPIO_PER_CHIP);
 }
 
 static void nmk_gpio_irq_ack(struct irq_data *d)
 {
-       int gpio;
        struct nmk_gpio_chip *nmk_chip;
 
-       gpio = NOMADIK_IRQ_TO_GPIO(d->irq);
        nmk_chip = irq_data_get_irq_chip_data(d);
        if (!nmk_chip)
                return;
 
        clk_enable(nmk_chip->clk);
-       writel(nmk_gpio_get_bitmask(gpio), nmk_chip->addr + NMK_GPIO_IC);
+       writel(nmk_gpio_get_bitmask(d->hwirq), nmk_chip->addr + NMK_GPIO_IC);
        clk_disable(nmk_chip->clk);
 }
 
         * wakeup is anyhow controlled by the RIMSC and FIMSC registers.
         */
        if (nmk_chip->sleepmode && on) {
-               __nmk_gpio_set_slpm(nmk_chip, gpio - nmk_chip->chip.base,
+               __nmk_gpio_set_slpm(nmk_chip, gpio % nmk_chip->chip.base,
                                    NMK_GPIO_SLPM_WAKEUP_ENABLE);
        }
 
 
 static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable)
 {
-       int gpio;
        struct nmk_gpio_chip *nmk_chip;
        unsigned long flags;
        u32 bitmask;
 
-       gpio = NOMADIK_IRQ_TO_GPIO(d->irq);
        nmk_chip = irq_data_get_irq_chip_data(d);
-       bitmask = nmk_gpio_get_bitmask(gpio);
+       bitmask = nmk_gpio_get_bitmask(d->hwirq);
        if (!nmk_chip)
                return -EINVAL;
 
        spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
        spin_lock(&nmk_chip->lock);
 
-       __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, enable);
+       __nmk_gpio_irq_modify(nmk_chip, d->hwirq, NORMAL, enable);
 
        if (!(nmk_chip->real_wake & bitmask))
-               __nmk_gpio_set_wake(nmk_chip, gpio, enable);
+               __nmk_gpio_set_wake(nmk_chip, d->hwirq, enable);
 
        spin_unlock(&nmk_chip->lock);
        spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
        struct nmk_gpio_chip *nmk_chip;
        unsigned long flags;
        u32 bitmask;
-       int gpio;
 
-       gpio = NOMADIK_IRQ_TO_GPIO(d->irq);
        nmk_chip = irq_data_get_irq_chip_data(d);
        if (!nmk_chip)
                return -EINVAL;
-       bitmask = nmk_gpio_get_bitmask(gpio);
+       bitmask = nmk_gpio_get_bitmask(d->hwirq);
 
        clk_enable(nmk_chip->clk);
        spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
        spin_lock(&nmk_chip->lock);
 
        if (irqd_irq_disabled(d))
-               __nmk_gpio_set_wake(nmk_chip, gpio, on);
+               __nmk_gpio_set_wake(nmk_chip, d->hwirq, on);
 
        if (on)
                nmk_chip->real_wake |= bitmask;
 {
        bool enabled = !irqd_irq_disabled(d);
        bool wake = irqd_is_wakeup_set(d);
-       int gpio;
        struct nmk_gpio_chip *nmk_chip;
        unsigned long flags;
        u32 bitmask;
 
-       gpio = NOMADIK_IRQ_TO_GPIO(d->irq);
        nmk_chip = irq_data_get_irq_chip_data(d);
-       bitmask = nmk_gpio_get_bitmask(gpio);
+       bitmask = nmk_gpio_get_bitmask(d->hwirq);
        if (!nmk_chip)
                return -EINVAL;
-
        if (type & IRQ_TYPE_LEVEL_HIGH)
                return -EINVAL;
        if (type & IRQ_TYPE_LEVEL_LOW)
        spin_lock_irqsave(&nmk_chip->lock, flags);
 
        if (enabled)
-               __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, false);
+               __nmk_gpio_irq_modify(nmk_chip, d->hwirq, NORMAL, false);
 
        if (enabled || wake)
-               __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, false);
+               __nmk_gpio_irq_modify(nmk_chip, d->hwirq, WAKE, false);
 
        nmk_chip->edge_rising &= ~bitmask;
        if (type & IRQ_TYPE_EDGE_RISING)
                nmk_chip->edge_falling |= bitmask;
 
        if (enabled)
-               __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, true);
+               __nmk_gpio_irq_modify(nmk_chip, d->hwirq, NORMAL, true);
 
        if (enabled || wake)
-               __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, true);
+               __nmk_gpio_irq_modify(nmk_chip, d->hwirq, WAKE, true);
 
        spin_unlock_irqrestore(&nmk_chip->lock, flags);
        clk_disable(nmk_chip->clk);
        chained_irq_enter(host_chip, desc);
 
        nmk_chip = irq_get_handler_data(irq);
-       first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base);
+       first_irq = nmk_chip->domain->revmap_data.legacy.first_irq;
        while (status) {
                int bit = __ffs(status);
 
 
 static int nmk_gpio_init_irq(struct nmk_gpio_chip *nmk_chip)
 {
-       unsigned int first_irq;
-       int i;
-
-       first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base);
-       for (i = first_irq; i < first_irq + nmk_chip->chip.ngpio; i++) {
-               irq_set_chip_and_handler(i, &nmk_gpio_irq_chip,
-                                        handle_edge_irq);
-               set_irq_flags(i, IRQF_VALID);
-               irq_set_chip_data(i, nmk_chip);
-               irq_set_irq_type(i, IRQ_TYPE_EDGE_FALLING);
-       }
-
        irq_set_chained_handler(nmk_chip->parent_irq, nmk_gpio_irq_handler);
        irq_set_handler_data(nmk_chip->parent_irq, nmk_chip);
 
        struct nmk_gpio_chip *nmk_chip =
                container_of(chip, struct nmk_gpio_chip, chip);
 
-       return NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base) + offset;
+       return irq_find_mapping(nmk_chip->domain, offset);
 }
 
 #ifdef CONFIG_DEBUG_FS
        }
 }
 
+int nmk_gpio_irq_map(struct irq_domain *d, unsigned int irq,
+                         irq_hw_number_t hwirq)
+{
+       struct nmk_gpio_chip *nmk_chip = d->host_data;
+
+       if (!nmk_chip)
+               return -EINVAL;
+
+       irq_set_chip_and_handler(irq, &nmk_gpio_irq_chip, handle_edge_irq);
+       set_irq_flags(irq, IRQF_VALID);
+       irq_set_chip_data(irq, nmk_chip);
+       irq_set_irq_type(irq, IRQ_TYPE_EDGE_FALLING);
+
+       return 0;
+}
+
+const struct irq_domain_ops nmk_gpio_irq_simple_ops = {
+       .map = nmk_gpio_irq_map,
+       .xlate = irq_domain_xlate_twocell,
+};
+
 static int __devinit nmk_gpio_probe(struct platform_device *dev)
 {
        struct nmk_gpio_platform_data *pdata = dev->dev.platform_data;
                if (of_property_read_u32(np, "gpio-bank", &dev->id)) {
                        dev_err(&dev->dev, "gpio-bank property not found\n");
                        ret = -EINVAL;
-                       goto out_dt;
+                       goto out;
                }
 
                pdata->first_gpio = dev->id * NMK_GPIO_PER_CHIP;
 
        platform_set_drvdata(dev, nmk_chip);
 
+       nmk_chip->domain = irq_domain_add_legacy(np, NMK_GPIO_PER_CHIP,
+                                               NOMADIK_GPIO_TO_IRQ(pdata->first_gpio),
+                                               0, &nmk_gpio_irq_simple_ops, nmk_chip);
+       if (!nmk_chip->domain) {
+               pr_err("%s: Failed to create irqdomain\n", np->full_name);
+               ret = -ENOSYS;
+               goto out_free;
+       }
+
        nmk_gpio_init_irq(nmk_chip);
 
        dev_info(&dev->dev, "at address %p\n", nmk_chip->addr);
 out:
        dev_err(&dev->dev, "Failure %i for GPIO %i-%i\n", ret,
                  pdata->first_gpio, pdata->first_gpio+31);
-out_dt:
        if (np)
                kfree(pdata);