in gpio-eic-sprd.c [567:653]
static int sprd_eic_probe(struct platform_device *pdev)
{
const struct sprd_eic_variant_data *pdata;
struct gpio_irq_chip *irq;
struct sprd_eic *sprd_eic;
struct resource *res;
int ret, i;
pdata = of_device_get_match_data(&pdev->dev);
if (!pdata) {
dev_err(&pdev->dev, "No matching driver data found.\n");
return -EINVAL;
}
sprd_eic = devm_kzalloc(&pdev->dev, sizeof(*sprd_eic), GFP_KERNEL);
if (!sprd_eic)
return -ENOMEM;
spin_lock_init(&sprd_eic->lock);
sprd_eic->type = pdata->type;
sprd_eic->irq = platform_get_irq(pdev, 0);
if (sprd_eic->irq < 0)
return sprd_eic->irq;
for (i = 0; i < SPRD_EIC_MAX_BANK; i++) {
/*
* We can have maximum 3 banks EICs, and each EIC has
* its own base address. But some platform maybe only
* have one bank EIC, thus base[1] and base[2] can be
* optional.
*/
res = platform_get_resource(pdev, IORESOURCE_MEM, i);
if (!res)
break;
sprd_eic->base[i] = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(sprd_eic->base[i]))
return PTR_ERR(sprd_eic->base[i]);
}
sprd_eic->chip.label = sprd_eic_label_name[sprd_eic->type];
sprd_eic->chip.ngpio = pdata->num_eics;
sprd_eic->chip.base = -1;
sprd_eic->chip.parent = &pdev->dev;
sprd_eic->chip.direction_input = sprd_eic_direction_input;
switch (sprd_eic->type) {
case SPRD_EIC_DEBOUNCE:
sprd_eic->chip.request = sprd_eic_request;
sprd_eic->chip.free = sprd_eic_free;
sprd_eic->chip.set_config = sprd_eic_set_config;
sprd_eic->chip.set = sprd_eic_set;
fallthrough;
case SPRD_EIC_ASYNC:
case SPRD_EIC_SYNC:
sprd_eic->chip.get = sprd_eic_get;
break;
case SPRD_EIC_LATCH:
default:
break;
}
sprd_eic->intc.name = dev_name(&pdev->dev);
sprd_eic->intc.irq_ack = sprd_eic_irq_ack;
sprd_eic->intc.irq_mask = sprd_eic_irq_mask;
sprd_eic->intc.irq_unmask = sprd_eic_irq_unmask;
sprd_eic->intc.irq_set_type = sprd_eic_irq_set_type;
sprd_eic->intc.flags = IRQCHIP_SKIP_SET_WAKE;
irq = &sprd_eic->chip.irq;
irq->chip = &sprd_eic->intc;
irq->handler = handle_bad_irq;
irq->default_type = IRQ_TYPE_NONE;
irq->parent_handler = sprd_eic_irq_handler;
irq->parent_handler_data = sprd_eic;
irq->num_parents = 1;
irq->parents = &sprd_eic->irq;
ret = devm_gpiochip_add_data(&pdev->dev, &sprd_eic->chip, sprd_eic);
if (ret < 0) {
dev_err(&pdev->dev, "Could not register gpiochip %d.\n", ret);
return ret;
}
platform_set_drvdata(pdev, sprd_eic);
return 0;
}