spinlock_t      lock;
        void __iomem    *base;
        struct sa1111_platform_data *pdata;
+       struct irq_domain *irqdomain;
        struct gpio_chip gc;
 #ifdef CONFIG_PM
        void            *saved_state;
        },
 };
 
+static void sa1111_handle_irqdomain(struct irq_domain *irqdomain, int irq)
+{
+       struct irq_desc *d = irq_to_desc(irq_linear_revmap(irqdomain, irq));
+
+       if (d)
+               generic_handle_irq_desc(d);
+}
+
 /*
  * SA1111 interrupt support.  Since clearing an IRQ while there are
  * active IRQs causes the interrupt output to pulse, the upper levels
 {
        unsigned int stat0, stat1, i;
        struct sa1111 *sachip = irq_desc_get_handler_data(desc);
+       struct irq_domain *irqdomain;
        void __iomem *mapbase = sachip->base + SA1111_INTC;
 
        stat0 = readl_relaxed(mapbase + SA1111_INTSTATCLR0);
                return;
        }
 
+       irqdomain = sachip->irqdomain;
+
        for (i = 0; stat0; i++, stat0 >>= 1)
                if (stat0 & 1)
-                       generic_handle_irq(i + sachip->irq_base);
+                       sa1111_handle_irqdomain(irqdomain, i);
 
        for (i = 32; stat1; i++, stat1 >>= 1)
                if (stat1 & 1)
-                       generic_handle_irq(i + sachip->irq_base);
+                       sa1111_handle_irqdomain(irqdomain, i);
 
        /* For level-based interrupts */
        desc->irq_data.chip->irq_unmask(&desc->irq_data);
 }
 
-#define SA1111_IRQMASK_LO(x)   (1 << (x - sachip->irq_base))
-#define SA1111_IRQMASK_HI(x)   (1 << (x - sachip->irq_base - 32))
-
 static u32 sa1111_irqmask(struct irq_data *d)
 {
-       struct sa1111 *sachip = irq_data_get_irq_chip_data(d);
-
-       return BIT((d->irq - sachip->irq_base) & 31);
+       return BIT(irqd_to_hwirq(d) & 31);
 }
 
 static int sa1111_irqbank(struct irq_data *d)
 {
-       struct sa1111 *sachip = irq_data_get_irq_chip_data(d);
-
-       return ((d->irq - sachip->irq_base) / 32) * 4;
+       return (irqd_to_hwirq(d) / 32) * 4;
 }
 
 static void sa1111_ack_irq(struct irq_data *d)
        .irq_set_wake   = sa1111_wake_irq,
 };
 
+static int sa1111_irqdomain_map(struct irq_domain *d, unsigned int irq,
+       irq_hw_number_t hwirq)
+{
+       struct sa1111 *sachip = d->host_data;
+
+       irq_set_chip_data(irq, sachip);
+       irq_set_chip_and_handler(irq, &sa1111_irq_chip, handle_edge_irq);
+       irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
+
+       return 0;
+}
+
+static const struct irq_domain_ops sa1111_irqdomain_ops = {
+       .map = sa1111_irqdomain_map,
+       .xlate = irq_domain_xlate_twocell,
+};
+
 static int sa1111_setup_irq(struct sa1111 *sachip, unsigned irq_base)
 {
        void __iomem *irqbase = sachip->base + SA1111_INTC;
-       unsigned i, irq;
        int ret;
 
        /*
        writel_relaxed(~0, irqbase + SA1111_INTSTATCLR0);
        writel_relaxed(~0, irqbase + SA1111_INTSTATCLR1);
 
-       for (i = IRQ_GPAIN0; i <= SSPROR; i++) {
-               irq = sachip->irq_base + i;
-               irq_set_chip_and_handler(irq, &sa1111_irq_chip, handle_edge_irq);
-               irq_set_chip_data(irq, sachip);
-               irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
+       sachip->irqdomain = irq_domain_add_linear(NULL, SA1111_IRQ_NR,
+                                                 &sa1111_irqdomain_ops,
+                                                 sachip);
+       if (!sachip->irqdomain) {
+               irq_free_descs(sachip->irq_base, SA1111_IRQ_NR);
+               return -ENOMEM;
        }
 
-       for (i = AUDXMTDMADONEA; i <= IRQ_S1_BVD1_STSCHG; i++) {
-               irq = sachip->irq_base + i;
-               irq_set_chip_and_handler(irq, &sa1111_irq_chip, handle_edge_irq);
-               irq_set_chip_data(irq, sachip);
-               irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
-       }
+       irq_domain_associate_many(sachip->irqdomain,
+                                 sachip->irq_base + IRQ_GPAIN0,
+                                 IRQ_GPAIN0, SSPROR + 1 - IRQ_GPAIN0);
+       irq_domain_associate_many(sachip->irqdomain,
+                                 sachip->irq_base + AUDXMTDMADONEA,
+                                 AUDXMTDMADONEA,
+                                 IRQ_S1_BVD1_STSCHG + 1 - AUDXMTDMADONEA);
 
        /*
         * Register SA1111 interrupt
        writel_relaxed(0, irqbase + SA1111_WAKEEN0);
        writel_relaxed(0, irqbase + SA1111_WAKEEN1);
 
-       if (sachip->irq != NO_IRQ) {
-               irq_set_chained_handler_and_data(sachip->irq, NULL, NULL);
-               irq_free_descs(sachip->irq_base, SA1111_IRQ_NR);
+       irq_domain_remove(sachip->irqdomain);
 
-               release_mem_region(sachip->phys + SA1111_INTC, 512);
-       }
+       irq_set_chained_handler_and_data(sachip->irq, NULL, NULL);
+       irq_free_descs(sachip->irq_base, SA1111_IRQ_NR);
+
+       release_mem_region(sachip->phys + SA1111_INTC, 512);
 }
 
 enum {