static int bcm2835_pinctrl_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct device_node *np = dev->of_node;
	struct bcm2835_pinctrl *pc;
	struct resource iomem;
	int err, i;
	BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_pins) != BCM2835_NUM_GPIOS);
	BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_groups) != BCM2835_NUM_GPIOS);

	pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL);
	if (!pc)
		return -ENOMEM;

	platform_set_drvdata(pdev, pc);
	pc->dev = dev;

	err = of_address_to_resource(np, 0, &iomem);
	if (err) {
		dev_err(dev, "could not get IO memory\n");
		return err;
	}

	pc->base = devm_ioremap_resource(dev, &iomem);
	if (IS_ERR(pc->base))
		return PTR_ERR(pc->base);

	pc->gpio_chip = bcm2835_gpio_chip;
	pc->gpio_chip.dev = dev;
	pc->gpio_chip.of_node = np;

	pc->irq_domain = irq_domain_add_linear(np, BCM2835_NUM_GPIOS,
			&irq_domain_simple_ops, NULL);
	if (!pc->irq_domain) {
		dev_err(dev, "could not create IRQ domain\n");
		return -ENOMEM;
	}

	for (i = 0; i < BCM2835_NUM_GPIOS; i++) {
		int irq = irq_create_mapping(pc->irq_domain, i);
		irq_set_lockdep_class(irq, &gpio_lock_class);
		irq_set_chip_and_handler(irq, &bcm2835_gpio_irq_chip,
				handle_simple_irq);
		irq_set_chip_data(irq, pc);
		set_irq_flags(irq, IRQF_VALID);
	}

	for (i = 0; i < BCM2835_NUM_BANKS; i++) {
		unsigned long events;
		unsigned offset;
		int len;
		char *name;

		/* clear event detection flags */
		bcm2835_gpio_wr(pc, GPREN0 + i * 4, 0);
		bcm2835_gpio_wr(pc, GPFEN0 + i * 4, 0);
		bcm2835_gpio_wr(pc, GPHEN0 + i * 4, 0);
		bcm2835_gpio_wr(pc, GPLEN0 + i * 4, 0);
		bcm2835_gpio_wr(pc, GPAREN0 + i * 4, 0);
		bcm2835_gpio_wr(pc, GPAFEN0 + i * 4, 0);

		/* clear all the events */
		events = bcm2835_gpio_rd(pc, GPEDS0 + i * 4);
		for_each_set_bit(offset, &events, 32)
			bcm2835_gpio_wr(pc, GPEDS0 + i * 4, BIT(offset));

		pc->irq[i] = irq_of_parse_and_map(np, i);
		pc->irq_data[i].pc = pc;
		pc->irq_data[i].bank = i;
		spin_lock_init(&pc->irq_lock[i]);

		len = strlen(dev_name(pc->dev)) + 16;
		name = devm_kzalloc(pc->dev, len, GFP_KERNEL);
		if (!name)
			return -ENOMEM;
		snprintf(name, len, "%s:bank%d", dev_name(pc->dev), i);

		err = devm_request_irq(dev, pc->irq[i],
			bcm2835_gpio_irq_handler, IRQF_SHARED,
			name, &pc->irq_data[i]);
		if (err) {
			dev_err(dev, "unable to request IRQ %d\n", pc->irq[i]);
			return err;
		}
	}

	err = gpiochip_add(&pc->gpio_chip);
	if (err) {
		dev_err(dev, "could not add GPIO chip\n");
		return err;
	}

	pc->pctl_dev = pinctrl_register(&bcm2835_pinctrl_desc, dev, pc);
	if (!pc->pctl_dev) {
		gpiochip_remove(&pc->gpio_chip);
		return -EINVAL;
	}

	pc->gpio_range = bcm2835_pinctrl_gpio_range;
	pc->gpio_range.base = pc->gpio_chip.base;
	pc->gpio_range.gc = &pc->gpio_chip;
	pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range);

	return 0;
}

