#include <linux/device.h>
 #include <linux/pm_runtime.h>
 #include <linux/pm.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/irqdomain.h>
 
 #include <mach/hardware.h>
 #include <asm/irq.h>
        struct list_head node;
        void __iomem *base;
        u16 irq;
-       u16 virtual_irq_start;
+       int irq_base;
+       struct irq_domain *domain;
        u32 suspend_wakeup;
        u32 saved_wakeup;
        u32 non_wakeup_gpios;
                if (!isr)
                        break;
 
-               gpio_irq = bank->virtual_irq_start;
+               gpio_irq = bank->irq_base;
                for (; isr != 0; isr >>= 1, gpio_irq++) {
                        gpio_index = GPIO_INDEX(bank, irq_to_gpio(gpio_irq));
 
        struct gpio_bank *bank;
 
        bank = container_of(chip, struct gpio_bank, chip);
-       return bank->virtual_irq_start + offset;
+       return bank->irq_base + offset;
 }
 
 /*---------------------------------------------------------------------*/
 
        gpiochip_add(&bank->chip);
 
-       for (j = bank->virtual_irq_start;
-                    j < bank->virtual_irq_start + bank->width; j++) {
+       for (j = bank->irq_base; j < bank->irq_base + bank->width; j++) {
                irq_set_lockdep_class(j, &gpio_lock_class);
                irq_set_chip_data(j, bank);
                if (bank->is_mpuio) {
        irq_set_handler_data(bank->irq, bank);
 }
 
+static const struct of_device_id omap_gpio_match[];
+
 static int __devinit omap_gpio_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
+       struct device_node *node = dev->of_node;
+       const struct of_device_id *match;
        struct omap_gpio_platform_data *pdata;
        struct resource *res;
        struct gpio_bank *bank;
        int ret = 0;
 
-       if (!dev->platform_data)
+       match = of_match_device(of_match_ptr(omap_gpio_match), dev);
+
+       pdata = match ? match->data : dev->platform_data;
+       if (!pdata)
                return -EINVAL;
 
        bank = devm_kzalloc(&pdev->dev, sizeof(struct gpio_bank), GFP_KERNEL);
        }
 
        bank->irq = res->start;
-
-       pdata = pdev->dev.platform_data;
-       bank->virtual_irq_start = pdata->virtual_irq_start;
        bank->dev = dev;
        bank->dbck_flag = pdata->dbck_flag;
        bank->stride = pdata->bank_stride;
        bank->loses_context = pdata->loses_context;
        bank->get_context_loss_count = pdata->get_context_loss_count;
        bank->regs = pdata->regs;
+#ifdef CONFIG_OF_GPIO
+       bank->chip.of_node = of_node_get(node);
+#endif
+
+       bank->irq_base = irq_alloc_descs(-1, 0, bank->width, 0);
+       if (bank->irq_base < 0) {
+               dev_err(dev, "Couldn't allocate IRQ numbers\n");
+               return -ENODEV;
+       }
+
+       bank->domain = irq_domain_add_legacy(node, bank->width, bank->irq_base,
+                                            0, &irq_domain_simple_ops, NULL);
 
        if (bank->regs->set_dataout && bank->regs->clr_dataout)
                bank->set_dataout = _set_gpio_dataout_reg;
                                                                        NULL)
 };
 
+#if defined(CONFIG_OF)
+static struct omap_gpio_reg_offs omap2_gpio_regs = {
+       .revision =             OMAP24XX_GPIO_REVISION,
+       .direction =            OMAP24XX_GPIO_OE,
+       .datain =               OMAP24XX_GPIO_DATAIN,
+       .dataout =              OMAP24XX_GPIO_DATAOUT,
+       .set_dataout =          OMAP24XX_GPIO_SETDATAOUT,
+       .clr_dataout =          OMAP24XX_GPIO_CLEARDATAOUT,
+       .irqstatus =            OMAP24XX_GPIO_IRQSTATUS1,
+       .irqstatus2 =           OMAP24XX_GPIO_IRQSTATUS2,
+       .irqenable =            OMAP24XX_GPIO_IRQENABLE1,
+       .irqenable2 =           OMAP24XX_GPIO_IRQENABLE2,
+       .set_irqenable =        OMAP24XX_GPIO_SETIRQENABLE1,
+       .clr_irqenable =        OMAP24XX_GPIO_CLEARIRQENABLE1,
+       .debounce =             OMAP24XX_GPIO_DEBOUNCE_VAL,
+       .debounce_en =          OMAP24XX_GPIO_DEBOUNCE_EN,
+       .ctrl =                 OMAP24XX_GPIO_CTRL,
+       .wkup_en =              OMAP24XX_GPIO_WAKE_EN,
+       .leveldetect0 =         OMAP24XX_GPIO_LEVELDETECT0,
+       .leveldetect1 =         OMAP24XX_GPIO_LEVELDETECT1,
+       .risingdetect =         OMAP24XX_GPIO_RISINGDETECT,
+       .fallingdetect =        OMAP24XX_GPIO_FALLINGDETECT,
+};
+
+static struct omap_gpio_reg_offs omap4_gpio_regs = {
+       .revision =             OMAP4_GPIO_REVISION,
+       .direction =            OMAP4_GPIO_OE,
+       .datain =               OMAP4_GPIO_DATAIN,
+       .dataout =              OMAP4_GPIO_DATAOUT,
+       .set_dataout =          OMAP4_GPIO_SETDATAOUT,
+       .clr_dataout =          OMAP4_GPIO_CLEARDATAOUT,
+       .irqstatus =            OMAP4_GPIO_IRQSTATUS0,
+       .irqstatus2 =           OMAP4_GPIO_IRQSTATUS1,
+       .irqenable =            OMAP4_GPIO_IRQSTATUSSET0,
+       .irqenable2 =           OMAP4_GPIO_IRQSTATUSSET1,
+       .set_irqenable =        OMAP4_GPIO_IRQSTATUSSET0,
+       .clr_irqenable =        OMAP4_GPIO_IRQSTATUSCLR0,
+       .debounce =             OMAP4_GPIO_DEBOUNCINGTIME,
+       .debounce_en =          OMAP4_GPIO_DEBOUNCENABLE,
+       .ctrl =                 OMAP4_GPIO_CTRL,
+       .wkup_en =              OMAP4_GPIO_IRQWAKEN0,
+       .leveldetect0 =         OMAP4_GPIO_LEVELDETECT0,
+       .leveldetect1 =         OMAP4_GPIO_LEVELDETECT1,
+       .risingdetect =         OMAP4_GPIO_RISINGDETECT,
+       .fallingdetect =        OMAP4_GPIO_FALLINGDETECT,
+};
+
+static struct omap_gpio_platform_data omap2_pdata = {
+       .regs = &omap2_gpio_regs,
+       .bank_width = 32,
+       .dbck_flag = false,
+};
+
+static struct omap_gpio_platform_data omap3_pdata = {
+       .regs = &omap2_gpio_regs,
+       .bank_width = 32,
+       .dbck_flag = true,
+};
+
+static struct omap_gpio_platform_data omap4_pdata = {
+       .regs = &omap4_gpio_regs,
+       .bank_width = 32,
+       .dbck_flag = true,
+};
+
+static const struct of_device_id omap_gpio_match[] = {
+       {
+               .compatible = "ti,omap4-gpio",
+               .data = &omap4_pdata,
+       },
+       {
+               .compatible = "ti,omap3-gpio",
+               .data = &omap3_pdata,
+       },
+       {
+               .compatible = "ti,omap2-gpio",
+               .data = &omap2_pdata,
+       },
+       { },
+};
+MODULE_DEVICE_TABLE(of, omap_gpio_match);
+#endif
+
 static struct platform_driver omap_gpio_driver = {
        .probe          = omap_gpio_probe,
        .driver         = {
                .name   = "omap_gpio",
                .pm     = &gpio_pm_ops,
+               .of_match_table = of_match_ptr(omap_gpio_match),
        },
 };