{
        struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
        struct mvebu_gpio_chip *mvchip = gc->private;
-       u32 mask = ~(1 << (d->irq - gc->irq_base));
+       u32 mask = d->mask;
 
        irq_gc_lock(gc);
-       writel_relaxed(mask, mvebu_gpioreg_edge_cause(mvchip));
+       writel_relaxed(~mask, mvebu_gpioreg_edge_cause(mvchip));
        irq_gc_unlock(gc);
 }
 
        struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
        struct mvebu_gpio_chip *mvchip = gc->private;
        struct irq_chip_type *ct = irq_data_get_chip_type(d);
-       u32 mask = 1 << (d->irq - gc->irq_base);
+       u32 mask = d->mask;
 
        irq_gc_lock(gc);
        ct->mask_cache_priv &= ~mask;
        struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
        struct mvebu_gpio_chip *mvchip = gc->private;
        struct irq_chip_type *ct = irq_data_get_chip_type(d);
-
-       u32 mask = 1 << (d->irq - gc->irq_base);
+       u32 mask = d->mask;
 
        irq_gc_lock(gc);
        ct->mask_cache_priv |= mask;
        struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
        struct mvebu_gpio_chip *mvchip = gc->private;
        struct irq_chip_type *ct = irq_data_get_chip_type(d);
-
-       u32 mask = 1 << (d->irq - gc->irq_base);
+       u32 mask = d->mask;
 
        irq_gc_lock(gc);
        ct->mask_cache_priv &= ~mask;
        struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
        struct mvebu_gpio_chip *mvchip = gc->private;
        struct irq_chip_type *ct = irq_data_get_chip_type(d);
-
-       u32 mask = 1 << (d->irq - gc->irq_base);
+       u32 mask = d->mask;
 
        irq_gc_lock(gc);
        ct->mask_cache_priv |= mask;
        for (i = 0; i < mvchip->chip.ngpio; i++) {
                int irq;
 
-               irq = mvchip->irqbase + i;
+               irq = irq_find_mapping(mvchip->domain, i);
 
                if (!(cause & (1 << i)))
                        continue;
        struct irq_chip_type *ct;
        struct clk *clk;
        unsigned int ngpios;
+       bool have_irqs;
        int soc_variant;
        int i, cpu, id;
        int err;
        else
                soc_variant = MVEBU_GPIO_SOC_VARIANT_ORION;
 
+       /* Some gpio controllers do not provide irq support */
+       have_irqs = of_irq_count(np) != 0;
+
        mvchip = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_gpio_chip),
                              GFP_KERNEL);
        if (!mvchip)
        mvchip->chip.get = mvebu_gpio_get;
        mvchip->chip.direction_output = mvebu_gpio_direction_output;
        mvchip->chip.set = mvebu_gpio_set;
-       mvchip->chip.to_irq = mvebu_gpio_to_irq;
+       if (have_irqs)
+               mvchip->chip.to_irq = mvebu_gpio_to_irq;
        mvchip->chip.base = id * MVEBU_MAX_GPIO_PER_BANK;
        mvchip->chip.ngpio = ngpios;
        mvchip->chip.can_sleep = false;
        devm_gpiochip_add_data(&pdev->dev, &mvchip->chip, mvchip);
 
        /* Some gpio controllers do not provide irq support */
-       if (!of_irq_count(np))
+       if (!have_irqs)
                return 0;
 
-       /* Setup the interrupt handlers. Each chip can have up to 4
-        * interrupt handlers, with each handler dealing with 8 GPIO
-        * pins. */
-       for (i = 0; i < 4; i++) {
-               int irq = platform_get_irq(pdev, i);
-
-               if (irq < 0)
-                       continue;
-               irq_set_chained_handler_and_data(irq, mvebu_gpio_irq_handler,
-                                                mvchip);
-       }
-
-       mvchip->irqbase = irq_alloc_descs(-1, 0, ngpios, -1);
-       if (mvchip->irqbase < 0) {
-               dev_err(&pdev->dev, "no irqs\n");
-               return mvchip->irqbase;
+       mvchip->domain =
+           irq_domain_add_linear(np, ngpios, &irq_generic_chip_ops, NULL);
+       if (!mvchip->domain) {
+               dev_err(&pdev->dev, "couldn't allocate irq domain %s (DT).\n",
+                       mvchip->chip.label);
+               return -ENODEV;
        }
 
-       gc = irq_alloc_generic_chip("mvebu_gpio_irq", 2, mvchip->irqbase,
-                                   mvchip->membase, handle_level_irq);
-       if (!gc) {
-               dev_err(&pdev->dev, "Cannot allocate generic irq_chip\n");
-               return -ENOMEM;
+       err = irq_alloc_domain_generic_chips(
+           mvchip->domain, ngpios, 2, np->name, handle_level_irq,
+           IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_LEVEL, 0, 0);
+       if (err) {
+               dev_err(&pdev->dev, "couldn't allocate irq chips %s (DT).\n",
+                       mvchip->chip.label);
+               goto err_domain;
        }
 
+       /* NOTE: The common accessors cannot be used because of the percpu
+        * access to the mask registers
+        */
+       gc = irq_get_domain_generic_chip(mvchip->domain, 0);
        gc->private = mvchip;
        ct = &gc->chip_types[0];
        ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW;
        ct->handler = handle_edge_irq;
        ct->chip.name = mvchip->chip.label;
 
-       irq_setup_generic_chip(gc, IRQ_MSK(ngpios), 0,
-                              IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
+       /* Setup the interrupt handlers. Each chip can have up to 4
+        * interrupt handlers, with each handler dealing with 8 GPIO
+        * pins.
+        */
+       for (i = 0; i < 4; i++) {
+               int irq = platform_get_irq(pdev, i);
 
-       /* Setup irq domain on top of the generic chip. */
-       mvchip->domain = irq_domain_add_simple(np, mvchip->chip.ngpio,
-                                              mvchip->irqbase,
-                                              &irq_domain_simple_ops,
-                                              mvchip);
-       if (!mvchip->domain) {
-               dev_err(&pdev->dev, "couldn't allocate irq domain %s (DT).\n",
-                       mvchip->chip.label);
-               err = -ENODEV;
-               goto err_generic_chip;
+               if (irq < 0)
+                       continue;
+               irq_set_chained_handler_and_data(irq, mvebu_gpio_irq_handler,
+                                                mvchip);
        }
 
        return 0;
 
-err_generic_chip:
-       irq_remove_generic_chip(gc, IRQ_MSK(ngpios), IRQ_NOREQUEST,
-                               IRQ_LEVEL | IRQ_NOPROBE);
-       kfree(gc);
+err_domain:
+       irq_domain_remove(mvchip->domain);
 
        return err;
 }