in gpio-ep93xx.c [332:418]
static int ep93xx_gpio_add_bank(struct ep93xx_gpio_chip *egc,
struct platform_device *pdev,
struct ep93xx_gpio *epg,
struct ep93xx_gpio_bank *bank)
{
void __iomem *data = epg->base + bank->data;
void __iomem *dir = epg->base + bank->dir;
struct gpio_chip *gc = &egc->gc;
struct device *dev = &pdev->dev;
struct gpio_irq_chip *girq;
int err;
err = bgpio_init(gc, dev, 1, data, NULL, NULL, dir, NULL, 0);
if (err)
return err;
gc->label = bank->label;
gc->base = bank->base;
girq = &gc->irq;
if (bank->has_irq || bank->has_hierarchical_irq) {
struct irq_chip *ic;
gc->set_config = ep93xx_gpio_set_config;
egc->eic = devm_kcalloc(dev, 1,
sizeof(*egc->eic),
GFP_KERNEL);
if (!egc->eic)
return -ENOMEM;
egc->eic->irq_offset = bank->irq;
ic = &egc->eic->ic;
ic->name = devm_kasprintf(dev, GFP_KERNEL, "gpio-irq-%s", bank->label);
if (!ic->name)
return -ENOMEM;
ep93xx_init_irq_chip(dev, ic);
girq->chip = ic;
}
if (bank->has_irq) {
int ab_parent_irq = platform_get_irq(pdev, 0);
girq->parent_handler = ep93xx_gpio_ab_irq_handler;
girq->num_parents = 1;
girq->parents = devm_kcalloc(dev, girq->num_parents,
sizeof(*girq->parents),
GFP_KERNEL);
if (!girq->parents)
return -ENOMEM;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_level_irq;
girq->parents[0] = ab_parent_irq;
girq->first = bank->irq_base;
}
/* Only bank F has especially funky IRQ handling */
if (bank->has_hierarchical_irq) {
int gpio_irq;
int i;
/*
* FIXME: convert this to use hierarchical IRQ support!
* this requires fixing the root irqchip to be hierarchical.
*/
girq->parent_handler = ep93xx_gpio_f_irq_handler;
girq->num_parents = 8;
girq->parents = devm_kcalloc(dev, girq->num_parents,
sizeof(*girq->parents),
GFP_KERNEL);
if (!girq->parents)
return -ENOMEM;
/* Pick resources 1..8 for these IRQs */
for (i = 0; i < girq->num_parents; i++) {
girq->parents[i] = platform_get_irq(pdev, i + 1);
gpio_irq = bank->irq_base + i;
irq_set_chip_data(gpio_irq, &epg->gc[5]);
irq_set_chip_and_handler(gpio_irq,
girq->chip,
handle_level_irq);
irq_clear_status_flags(gpio_irq, IRQ_NOREQUEST);
}
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_level_irq;
girq->first = bank->irq_base;
}
return devm_gpiochip_add_data(dev, gc, epg);
}