|
@@ -37,6 +37,8 @@ struct davinci_gpio_regs {
|
|
|
u32 intstat;
|
|
|
};
|
|
|
|
|
|
+typedef struct irq_chip *(*gpio_get_irq_chip_cb_t)(unsigned int irq);
|
|
|
+
|
|
|
#define BINTEN 0x8 /* GPIO Interrupt Per-Bank Enable Register */
|
|
|
|
|
|
#define chip2controller(chip) \
|
|
@@ -413,6 +415,26 @@ static const struct irq_domain_ops davinci_gpio_irq_ops = {
|
|
|
.xlate = irq_domain_xlate_onetwocell,
|
|
|
};
|
|
|
|
|
|
+static struct irq_chip *davinci_gpio_get_irq_chip(unsigned int irq)
|
|
|
+{
|
|
|
+ static struct irq_chip_type gpio_unbanked;
|
|
|
+
|
|
|
+ gpio_unbanked = *container_of(irq_get_chip(irq),
|
|
|
+ struct irq_chip_type, chip);
|
|
|
+
|
|
|
+ return &gpio_unbanked.chip;
|
|
|
+};
|
|
|
+
|
|
|
+static struct irq_chip *keystone_gpio_get_irq_chip(unsigned int irq)
|
|
|
+{
|
|
|
+ static struct irq_chip gpio_unbanked;
|
|
|
+
|
|
|
+ gpio_unbanked = *irq_get_chip(irq);
|
|
|
+ return &gpio_unbanked;
|
|
|
+};
|
|
|
+
|
|
|
+static const struct of_device_id davinci_gpio_ids[];
|
|
|
+
|
|
|
/*
|
|
|
* NOTE: for suspend/resume, probably best to make a platform_device with
|
|
|
* suspend_late/resume_resume calls hooking into results of the set_wake()
|
|
@@ -434,6 +456,18 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
|
|
|
struct davinci_gpio_platform_data *pdata = dev->platform_data;
|
|
|
struct davinci_gpio_regs __iomem *g;
|
|
|
struct irq_domain *irq_domain = NULL;
|
|
|
+ const struct of_device_id *match;
|
|
|
+ struct irq_chip *irq_chip;
|
|
|
+ gpio_get_irq_chip_cb_t gpio_get_irq_chip;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Use davinci_gpio_get_irq_chip by default to handle non DT cases
|
|
|
+ */
|
|
|
+ gpio_get_irq_chip = davinci_gpio_get_irq_chip;
|
|
|
+ match = of_match_device(of_match_ptr(davinci_gpio_ids),
|
|
|
+ dev);
|
|
|
+ if (match)
|
|
|
+ gpio_get_irq_chip = (gpio_get_irq_chip_cb_t)match->data;
|
|
|
|
|
|
ngpio = pdata->ngpio;
|
|
|
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
|
@@ -490,8 +524,6 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
|
|
|
* IRQ mux conflicts; gpio_irq_type_unbanked() is only for GPIOs.
|
|
|
*/
|
|
|
if (pdata->gpio_unbanked) {
|
|
|
- static struct irq_chip_type gpio_unbanked;
|
|
|
-
|
|
|
/* pass "bank 0" GPIO IRQs to AINTC */
|
|
|
chips[0].chip.to_irq = gpio_to_irq_unbanked;
|
|
|
chips[0].gpio_irq = bank_irq;
|
|
@@ -500,10 +532,9 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
|
|
|
|
|
|
/* AINTC handles mask/unmask; GPIO handles triggering */
|
|
|
irq = bank_irq;
|
|
|
- gpio_unbanked = *container_of(irq_get_chip(irq),
|
|
|
- struct irq_chip_type, chip);
|
|
|
- gpio_unbanked.chip.name = "GPIO-AINTC";
|
|
|
- gpio_unbanked.chip.irq_set_type = gpio_irq_type_unbanked;
|
|
|
+ irq_chip = gpio_get_irq_chip(irq);
|
|
|
+ irq_chip->name = "GPIO-AINTC";
|
|
|
+ irq_chip->irq_set_type = gpio_irq_type_unbanked;
|
|
|
|
|
|
/* default trigger: both edges */
|
|
|
g = gpio2regs(0);
|
|
@@ -512,7 +543,7 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
|
|
|
|
|
|
/* set the direct IRQs up to use that irqchip */
|
|
|
for (gpio = 0; gpio < pdata->gpio_unbanked; gpio++, irq++) {
|
|
|
- irq_set_chip(irq, &gpio_unbanked.chip);
|
|
|
+ irq_set_chip(irq, irq_chip);
|
|
|
irq_set_handler_data(irq, &chips[gpio / 32]);
|
|
|
irq_set_status_flags(irq, IRQ_TYPE_EDGE_BOTH);
|
|
|
}
|
|
@@ -555,7 +586,8 @@ done:
|
|
|
|
|
|
#if IS_ENABLED(CONFIG_OF)
|
|
|
static const struct of_device_id davinci_gpio_ids[] = {
|
|
|
- { .compatible = "ti,dm6441-gpio", },
|
|
|
+ { .compatible = "ti,keystone-gpio", keystone_gpio_get_irq_chip},
|
|
|
+ { .compatible = "ti,dm6441-gpio", davinci_gpio_get_irq_chip},
|
|
|
{ /* sentinel */ },
|
|
|
};
|
|
|
MODULE_DEVICE_TABLE(of, davinci_gpio_ids);
|