| /* | 
 |  * Driver for Broadcom BCM2835 GPIO unit (pinctrl + GPIO) | 
 |  * | 
 |  * Copyright (C) 2012 Chris Boot, Simon Arlott, Stephen Warren | 
 |  * | 
 |  * This driver is inspired by: | 
 |  * pinctrl-nomadik.c, please see original file for copyright information | 
 |  * pinctrl-tegra.c, please see original file for copyright information | 
 |  * | 
 |  * This program is free software; you can redistribute it and/or modify | 
 |  * it under the terms of the GNU General Public License as published by | 
 |  * the Free Software Foundation; either version 2 of the License, or | 
 |  * (at your option) any later version. | 
 |  * | 
 |  * This program is distributed in the hope that it will be useful, | 
 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
 |  * GNU General Public License for more details. | 
 |  */ | 
 |  | 
 | #include <linux/bitmap.h> | 
 | #include <linux/bug.h> | 
 | #include <linux/delay.h> | 
 | #include <linux/device.h> | 
 | #include <linux/err.h> | 
 | #include <linux/gpio/driver.h> | 
 | #include <linux/io.h> | 
 | #include <linux/irq.h> | 
 | #include <linux/irqdesc.h> | 
 | #include <linux/init.h> | 
 | #include <linux/of_address.h> | 
 | #include <linux/of.h> | 
 | #include <linux/of_irq.h> | 
 | #include <linux/pinctrl/consumer.h> | 
 | #include <linux/pinctrl/machine.h> | 
 | #include <linux/pinctrl/pinconf.h> | 
 | #include <linux/pinctrl/pinctrl.h> | 
 | #include <linux/pinctrl/pinmux.h> | 
 | #include <linux/platform_device.h> | 
 | #include <linux/seq_file.h> | 
 | #include <linux/slab.h> | 
 | #include <linux/spinlock.h> | 
 | #include <linux/types.h> | 
 |  | 
 | #define MODULE_NAME "pinctrl-bcm2835" | 
 | #define BCM2835_NUM_GPIOS 54 | 
 | #define BCM2835_NUM_BANKS 2 | 
 | #define BCM2835_NUM_IRQS  3 | 
 |  | 
 | #define BCM2835_PIN_BITMAP_SZ \ | 
 | 	DIV_ROUND_UP(BCM2835_NUM_GPIOS, sizeof(unsigned long) * 8) | 
 |  | 
 | /* GPIO register offsets */ | 
 | #define GPFSEL0		0x0	/* Function Select */ | 
 | #define GPSET0		0x1c	/* Pin Output Set */ | 
 | #define GPCLR0		0x28	/* Pin Output Clear */ | 
 | #define GPLEV0		0x34	/* Pin Level */ | 
 | #define GPEDS0		0x40	/* Pin Event Detect Status */ | 
 | #define GPREN0		0x4c	/* Pin Rising Edge Detect Enable */ | 
 | #define GPFEN0		0x58	/* Pin Falling Edge Detect Enable */ | 
 | #define GPHEN0		0x64	/* Pin High Detect Enable */ | 
 | #define GPLEN0		0x70	/* Pin Low Detect Enable */ | 
 | #define GPAREN0		0x7c	/* Pin Async Rising Edge Detect */ | 
 | #define GPAFEN0		0x88	/* Pin Async Falling Edge Detect */ | 
 | #define GPPUD		0x94	/* Pin Pull-up/down Enable */ | 
 | #define GPPUDCLK0	0x98	/* Pin Pull-up/down Enable Clock */ | 
 |  | 
 | #define FSEL_REG(p)		(GPFSEL0 + (((p) / 10) * 4)) | 
 | #define FSEL_SHIFT(p)		(((p) % 10) * 3) | 
 | #define GPIO_REG_OFFSET(p)	((p) / 32) | 
 | #define GPIO_REG_SHIFT(p)	((p) % 32) | 
 |  | 
 | enum bcm2835_pinconf_param { | 
 | 	/* argument: bcm2835_pinconf_pull */ | 
 | 	BCM2835_PINCONF_PARAM_PULL, | 
 | }; | 
 |  | 
 | #define BCM2835_PINCONF_PACK(_param_, _arg_) ((_param_) << 16 | (_arg_)) | 
 | #define BCM2835_PINCONF_UNPACK_PARAM(_conf_) ((_conf_) >> 16) | 
 | #define BCM2835_PINCONF_UNPACK_ARG(_conf_) ((_conf_) & 0xffff) | 
 |  | 
 | struct bcm2835_pinctrl { | 
 | 	struct device *dev; | 
 | 	void __iomem *base; | 
 | 	int irq[BCM2835_NUM_IRQS]; | 
 |  | 
 | 	/* note: locking assumes each bank will have its own unsigned long */ | 
 | 	unsigned long enabled_irq_map[BCM2835_NUM_BANKS]; | 
 | 	unsigned int irq_type[BCM2835_NUM_GPIOS]; | 
 |  | 
 | 	struct pinctrl_dev *pctl_dev; | 
 | 	struct gpio_chip gpio_chip; | 
 | 	struct pinctrl_gpio_range gpio_range; | 
 |  | 
 | 	spinlock_t irq_lock[BCM2835_NUM_BANKS]; | 
 | }; | 
 |  | 
 | /* pins are just named GPIO0..GPIO53 */ | 
 | #define BCM2835_GPIO_PIN(a) PINCTRL_PIN(a, "gpio" #a) | 
 | static struct pinctrl_pin_desc bcm2835_gpio_pins[] = { | 
 | 	BCM2835_GPIO_PIN(0), | 
 | 	BCM2835_GPIO_PIN(1), | 
 | 	BCM2835_GPIO_PIN(2), | 
 | 	BCM2835_GPIO_PIN(3), | 
 | 	BCM2835_GPIO_PIN(4), | 
 | 	BCM2835_GPIO_PIN(5), | 
 | 	BCM2835_GPIO_PIN(6), | 
 | 	BCM2835_GPIO_PIN(7), | 
 | 	BCM2835_GPIO_PIN(8), | 
 | 	BCM2835_GPIO_PIN(9), | 
 | 	BCM2835_GPIO_PIN(10), | 
 | 	BCM2835_GPIO_PIN(11), | 
 | 	BCM2835_GPIO_PIN(12), | 
 | 	BCM2835_GPIO_PIN(13), | 
 | 	BCM2835_GPIO_PIN(14), | 
 | 	BCM2835_GPIO_PIN(15), | 
 | 	BCM2835_GPIO_PIN(16), | 
 | 	BCM2835_GPIO_PIN(17), | 
 | 	BCM2835_GPIO_PIN(18), | 
 | 	BCM2835_GPIO_PIN(19), | 
 | 	BCM2835_GPIO_PIN(20), | 
 | 	BCM2835_GPIO_PIN(21), | 
 | 	BCM2835_GPIO_PIN(22), | 
 | 	BCM2835_GPIO_PIN(23), | 
 | 	BCM2835_GPIO_PIN(24), | 
 | 	BCM2835_GPIO_PIN(25), | 
 | 	BCM2835_GPIO_PIN(26), | 
 | 	BCM2835_GPIO_PIN(27), | 
 | 	BCM2835_GPIO_PIN(28), | 
 | 	BCM2835_GPIO_PIN(29), | 
 | 	BCM2835_GPIO_PIN(30), | 
 | 	BCM2835_GPIO_PIN(31), | 
 | 	BCM2835_GPIO_PIN(32), | 
 | 	BCM2835_GPIO_PIN(33), | 
 | 	BCM2835_GPIO_PIN(34), | 
 | 	BCM2835_GPIO_PIN(35), | 
 | 	BCM2835_GPIO_PIN(36), | 
 | 	BCM2835_GPIO_PIN(37), | 
 | 	BCM2835_GPIO_PIN(38), | 
 | 	BCM2835_GPIO_PIN(39), | 
 | 	BCM2835_GPIO_PIN(40), | 
 | 	BCM2835_GPIO_PIN(41), | 
 | 	BCM2835_GPIO_PIN(42), | 
 | 	BCM2835_GPIO_PIN(43), | 
 | 	BCM2835_GPIO_PIN(44), | 
 | 	BCM2835_GPIO_PIN(45), | 
 | 	BCM2835_GPIO_PIN(46), | 
 | 	BCM2835_GPIO_PIN(47), | 
 | 	BCM2835_GPIO_PIN(48), | 
 | 	BCM2835_GPIO_PIN(49), | 
 | 	BCM2835_GPIO_PIN(50), | 
 | 	BCM2835_GPIO_PIN(51), | 
 | 	BCM2835_GPIO_PIN(52), | 
 | 	BCM2835_GPIO_PIN(53), | 
 | }; | 
 |  | 
 | /* one pin per group */ | 
 | static const char * const bcm2835_gpio_groups[] = { | 
 | 	"gpio0", | 
 | 	"gpio1", | 
 | 	"gpio2", | 
 | 	"gpio3", | 
 | 	"gpio4", | 
 | 	"gpio5", | 
 | 	"gpio6", | 
 | 	"gpio7", | 
 | 	"gpio8", | 
 | 	"gpio9", | 
 | 	"gpio10", | 
 | 	"gpio11", | 
 | 	"gpio12", | 
 | 	"gpio13", | 
 | 	"gpio14", | 
 | 	"gpio15", | 
 | 	"gpio16", | 
 | 	"gpio17", | 
 | 	"gpio18", | 
 | 	"gpio19", | 
 | 	"gpio20", | 
 | 	"gpio21", | 
 | 	"gpio22", | 
 | 	"gpio23", | 
 | 	"gpio24", | 
 | 	"gpio25", | 
 | 	"gpio26", | 
 | 	"gpio27", | 
 | 	"gpio28", | 
 | 	"gpio29", | 
 | 	"gpio30", | 
 | 	"gpio31", | 
 | 	"gpio32", | 
 | 	"gpio33", | 
 | 	"gpio34", | 
 | 	"gpio35", | 
 | 	"gpio36", | 
 | 	"gpio37", | 
 | 	"gpio38", | 
 | 	"gpio39", | 
 | 	"gpio40", | 
 | 	"gpio41", | 
 | 	"gpio42", | 
 | 	"gpio43", | 
 | 	"gpio44", | 
 | 	"gpio45", | 
 | 	"gpio46", | 
 | 	"gpio47", | 
 | 	"gpio48", | 
 | 	"gpio49", | 
 | 	"gpio50", | 
 | 	"gpio51", | 
 | 	"gpio52", | 
 | 	"gpio53", | 
 | }; | 
 |  | 
 | enum bcm2835_fsel { | 
 | 	BCM2835_FSEL_GPIO_IN = 0, | 
 | 	BCM2835_FSEL_GPIO_OUT = 1, | 
 | 	BCM2835_FSEL_ALT0 = 4, | 
 | 	BCM2835_FSEL_ALT1 = 5, | 
 | 	BCM2835_FSEL_ALT2 = 6, | 
 | 	BCM2835_FSEL_ALT3 = 7, | 
 | 	BCM2835_FSEL_ALT4 = 3, | 
 | 	BCM2835_FSEL_ALT5 = 2, | 
 | 	BCM2835_FSEL_COUNT = 8, | 
 | 	BCM2835_FSEL_MASK = 0x7, | 
 | }; | 
 |  | 
 | static const char * const bcm2835_functions[BCM2835_FSEL_COUNT] = { | 
 | 	[BCM2835_FSEL_GPIO_IN] = "gpio_in", | 
 | 	[BCM2835_FSEL_GPIO_OUT] = "gpio_out", | 
 | 	[BCM2835_FSEL_ALT0] = "alt0", | 
 | 	[BCM2835_FSEL_ALT1] = "alt1", | 
 | 	[BCM2835_FSEL_ALT2] = "alt2", | 
 | 	[BCM2835_FSEL_ALT3] = "alt3", | 
 | 	[BCM2835_FSEL_ALT4] = "alt4", | 
 | 	[BCM2835_FSEL_ALT5] = "alt5", | 
 | }; | 
 |  | 
 | static const char * const irq_type_names[] = { | 
 | 	[IRQ_TYPE_NONE] = "none", | 
 | 	[IRQ_TYPE_EDGE_RISING] = "edge-rising", | 
 | 	[IRQ_TYPE_EDGE_FALLING] = "edge-falling", | 
 | 	[IRQ_TYPE_EDGE_BOTH] = "edge-both", | 
 | 	[IRQ_TYPE_LEVEL_HIGH] = "level-high", | 
 | 	[IRQ_TYPE_LEVEL_LOW] = "level-low", | 
 | }; | 
 |  | 
 | static inline u32 bcm2835_gpio_rd(struct bcm2835_pinctrl *pc, unsigned reg) | 
 | { | 
 | 	return readl(pc->base + reg); | 
 | } | 
 |  | 
 | static inline void bcm2835_gpio_wr(struct bcm2835_pinctrl *pc, unsigned reg, | 
 | 		u32 val) | 
 | { | 
 | 	writel(val, pc->base + reg); | 
 | } | 
 |  | 
 | static inline int bcm2835_gpio_get_bit(struct bcm2835_pinctrl *pc, unsigned reg, | 
 | 		unsigned bit) | 
 | { | 
 | 	reg += GPIO_REG_OFFSET(bit) * 4; | 
 | 	return (bcm2835_gpio_rd(pc, reg) >> GPIO_REG_SHIFT(bit)) & 1; | 
 | } | 
 |  | 
 | /* note NOT a read/modify/write cycle */ | 
 | static inline void bcm2835_gpio_set_bit(struct bcm2835_pinctrl *pc, | 
 | 		unsigned reg, unsigned bit) | 
 | { | 
 | 	reg += GPIO_REG_OFFSET(bit) * 4; | 
 | 	bcm2835_gpio_wr(pc, reg, BIT(GPIO_REG_SHIFT(bit))); | 
 | } | 
 |  | 
 | static inline enum bcm2835_fsel bcm2835_pinctrl_fsel_get( | 
 | 		struct bcm2835_pinctrl *pc, unsigned pin) | 
 | { | 
 | 	u32 val = bcm2835_gpio_rd(pc, FSEL_REG(pin)); | 
 | 	enum bcm2835_fsel status = (val >> FSEL_SHIFT(pin)) & BCM2835_FSEL_MASK; | 
 |  | 
 | 	dev_dbg(pc->dev, "get %08x (%u => %s)\n", val, pin, | 
 | 			bcm2835_functions[status]); | 
 |  | 
 | 	return status; | 
 | } | 
 |  | 
 | static inline void bcm2835_pinctrl_fsel_set( | 
 | 		struct bcm2835_pinctrl *pc, unsigned pin, | 
 | 		enum bcm2835_fsel fsel) | 
 | { | 
 | 	u32 val = bcm2835_gpio_rd(pc, FSEL_REG(pin)); | 
 | 	enum bcm2835_fsel cur = (val >> FSEL_SHIFT(pin)) & BCM2835_FSEL_MASK; | 
 |  | 
 | 	dev_dbg(pc->dev, "read %08x (%u => %s)\n", val, pin, | 
 | 			bcm2835_functions[cur]); | 
 |  | 
 | 	if (cur == fsel) | 
 | 		return; | 
 |  | 
 | 	if (cur != BCM2835_FSEL_GPIO_IN && fsel != BCM2835_FSEL_GPIO_IN) { | 
 | 		/* always transition through GPIO_IN */ | 
 | 		val &= ~(BCM2835_FSEL_MASK << FSEL_SHIFT(pin)); | 
 | 		val |= BCM2835_FSEL_GPIO_IN << FSEL_SHIFT(pin); | 
 |  | 
 | 		dev_dbg(pc->dev, "trans %08x (%u <= %s)\n", val, pin, | 
 | 				bcm2835_functions[BCM2835_FSEL_GPIO_IN]); | 
 | 		bcm2835_gpio_wr(pc, FSEL_REG(pin), val); | 
 | 	} | 
 |  | 
 | 	val &= ~(BCM2835_FSEL_MASK << FSEL_SHIFT(pin)); | 
 | 	val |= fsel << FSEL_SHIFT(pin); | 
 |  | 
 | 	dev_dbg(pc->dev, "write %08x (%u <= %s)\n", val, pin, | 
 | 			bcm2835_functions[fsel]); | 
 | 	bcm2835_gpio_wr(pc, FSEL_REG(pin), val); | 
 | } | 
 |  | 
 | static int bcm2835_gpio_direction_input(struct gpio_chip *chip, unsigned offset) | 
 | { | 
 | 	return pinctrl_gpio_direction_input(chip->base + offset); | 
 | } | 
 |  | 
 | static int bcm2835_gpio_get(struct gpio_chip *chip, unsigned offset) | 
 | { | 
 | 	struct bcm2835_pinctrl *pc = gpiochip_get_data(chip); | 
 |  | 
 | 	return bcm2835_gpio_get_bit(pc, GPLEV0, offset); | 
 | } | 
 |  | 
 | static int bcm2835_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) | 
 | { | 
 | 	struct bcm2835_pinctrl *pc = gpiochip_get_data(chip); | 
 | 	enum bcm2835_fsel fsel = bcm2835_pinctrl_fsel_get(pc, offset); | 
 |  | 
 | 	/* Alternative function doesn't clearly provide a direction */ | 
 | 	if (fsel > BCM2835_FSEL_GPIO_OUT) | 
 | 		return -EINVAL; | 
 |  | 
 | 	return (fsel == BCM2835_FSEL_GPIO_IN); | 
 | } | 
 |  | 
 | static void bcm2835_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | 
 | { | 
 | 	struct bcm2835_pinctrl *pc = gpiochip_get_data(chip); | 
 |  | 
 | 	bcm2835_gpio_set_bit(pc, value ? GPSET0 : GPCLR0, offset); | 
 | } | 
 |  | 
 | static int bcm2835_gpio_direction_output(struct gpio_chip *chip, | 
 | 		unsigned offset, int value) | 
 | { | 
 | 	bcm2835_gpio_set(chip, offset, value); | 
 | 	return pinctrl_gpio_direction_output(chip->base + offset); | 
 | } | 
 |  | 
 | static const struct gpio_chip bcm2835_gpio_chip = { | 
 | 	.label = MODULE_NAME, | 
 | 	.owner = THIS_MODULE, | 
 | 	.request = gpiochip_generic_request, | 
 | 	.free = gpiochip_generic_free, | 
 | 	.direction_input = bcm2835_gpio_direction_input, | 
 | 	.direction_output = bcm2835_gpio_direction_output, | 
 | 	.get_direction = bcm2835_gpio_get_direction, | 
 | 	.get = bcm2835_gpio_get, | 
 | 	.set = bcm2835_gpio_set, | 
 | 	.base = -1, | 
 | 	.ngpio = BCM2835_NUM_GPIOS, | 
 | 	.can_sleep = false, | 
 | }; | 
 |  | 
 | static void bcm2835_gpio_irq_handle_bank(struct bcm2835_pinctrl *pc, | 
 | 					 unsigned int bank, u32 mask) | 
 | { | 
 | 	unsigned long events; | 
 | 	unsigned offset; | 
 | 	unsigned gpio; | 
 | 	unsigned int type; | 
 |  | 
 | 	events = bcm2835_gpio_rd(pc, GPEDS0 + bank * 4); | 
 | 	events &= mask; | 
 | 	events &= pc->enabled_irq_map[bank]; | 
 | 	for_each_set_bit(offset, &events, 32) { | 
 | 		gpio = (32 * bank) + offset; | 
 | 		/* FIXME: no clue why the code looks up the type here */ | 
 | 		type = pc->irq_type[gpio]; | 
 |  | 
 | 		generic_handle_irq(irq_linear_revmap(pc->gpio_chip.irqdomain, | 
 | 						     gpio)); | 
 | 	} | 
 | } | 
 |  | 
 | static void bcm2835_gpio_irq_handler(struct irq_desc *desc) | 
 | { | 
 | 	struct gpio_chip *chip = irq_desc_get_handler_data(desc); | 
 | 	struct bcm2835_pinctrl *pc = gpiochip_get_data(chip); | 
 | 	struct irq_chip *host_chip = irq_desc_get_chip(desc); | 
 | 	int irq = irq_desc_get_irq(desc); | 
 | 	int group; | 
 | 	int i; | 
 |  | 
 | 	for (i = 0; i < ARRAY_SIZE(pc->irq); i++) { | 
 | 		if (pc->irq[i] == irq) { | 
 | 			group = i; | 
 | 			break; | 
 | 		} | 
 | 	} | 
 | 	/* This should not happen, every IRQ has a bank */ | 
 | 	if (i == ARRAY_SIZE(pc->irq)) | 
 | 		BUG(); | 
 |  | 
 | 	chained_irq_enter(host_chip, desc); | 
 |  | 
 | 	switch (group) { | 
 | 	case 0: /* IRQ0 covers GPIOs 0-27 */ | 
 | 		bcm2835_gpio_irq_handle_bank(pc, 0, 0x0fffffff); | 
 | 		break; | 
 | 	case 1: /* IRQ1 covers GPIOs 28-45 */ | 
 | 		bcm2835_gpio_irq_handle_bank(pc, 0, 0xf0000000); | 
 | 		bcm2835_gpio_irq_handle_bank(pc, 1, 0x00003fff); | 
 | 		break; | 
 | 	case 2: /* IRQ2 covers GPIOs 46-53 */ | 
 | 		bcm2835_gpio_irq_handle_bank(pc, 1, 0x003fc000); | 
 | 		break; | 
 | 	} | 
 |  | 
 | 	chained_irq_exit(host_chip, desc); | 
 | } | 
 |  | 
 | static inline void __bcm2835_gpio_irq_config(struct bcm2835_pinctrl *pc, | 
 | 	unsigned reg, unsigned offset, bool enable) | 
 | { | 
 | 	u32 value; | 
 | 	reg += GPIO_REG_OFFSET(offset) * 4; | 
 | 	value = bcm2835_gpio_rd(pc, reg); | 
 | 	if (enable) | 
 | 		value |= BIT(GPIO_REG_SHIFT(offset)); | 
 | 	else | 
 | 		value &= ~(BIT(GPIO_REG_SHIFT(offset))); | 
 | 	bcm2835_gpio_wr(pc, reg, value); | 
 | } | 
 |  | 
 | /* fast path for IRQ handler */ | 
 | static void bcm2835_gpio_irq_config(struct bcm2835_pinctrl *pc, | 
 | 	unsigned offset, bool enable) | 
 | { | 
 | 	switch (pc->irq_type[offset]) { | 
 | 	case IRQ_TYPE_EDGE_RISING: | 
 | 		__bcm2835_gpio_irq_config(pc, GPREN0, offset, enable); | 
 | 		break; | 
 |  | 
 | 	case IRQ_TYPE_EDGE_FALLING: | 
 | 		__bcm2835_gpio_irq_config(pc, GPFEN0, offset, enable); | 
 | 		break; | 
 |  | 
 | 	case IRQ_TYPE_EDGE_BOTH: | 
 | 		__bcm2835_gpio_irq_config(pc, GPREN0, offset, enable); | 
 | 		__bcm2835_gpio_irq_config(pc, GPFEN0, offset, enable); | 
 | 		break; | 
 |  | 
 | 	case IRQ_TYPE_LEVEL_HIGH: | 
 | 		__bcm2835_gpio_irq_config(pc, GPHEN0, offset, enable); | 
 | 		break; | 
 |  | 
 | 	case IRQ_TYPE_LEVEL_LOW: | 
 | 		__bcm2835_gpio_irq_config(pc, GPLEN0, offset, enable); | 
 | 		break; | 
 | 	} | 
 | } | 
 |  | 
 | static void bcm2835_gpio_irq_enable(struct irq_data *data) | 
 | { | 
 | 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data); | 
 | 	struct bcm2835_pinctrl *pc = gpiochip_get_data(chip); | 
 | 	unsigned gpio = irqd_to_hwirq(data); | 
 | 	unsigned offset = GPIO_REG_SHIFT(gpio); | 
 | 	unsigned bank = GPIO_REG_OFFSET(gpio); | 
 | 	unsigned long flags; | 
 |  | 
 | 	spin_lock_irqsave(&pc->irq_lock[bank], flags); | 
 | 	set_bit(offset, &pc->enabled_irq_map[bank]); | 
 | 	bcm2835_gpio_irq_config(pc, gpio, true); | 
 | 	spin_unlock_irqrestore(&pc->irq_lock[bank], flags); | 
 | } | 
 |  | 
 | static void bcm2835_gpio_irq_disable(struct irq_data *data) | 
 | { | 
 | 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data); | 
 | 	struct bcm2835_pinctrl *pc = gpiochip_get_data(chip); | 
 | 	unsigned gpio = irqd_to_hwirq(data); | 
 | 	unsigned offset = GPIO_REG_SHIFT(gpio); | 
 | 	unsigned bank = GPIO_REG_OFFSET(gpio); | 
 | 	unsigned long flags; | 
 |  | 
 | 	spin_lock_irqsave(&pc->irq_lock[bank], flags); | 
 | 	bcm2835_gpio_irq_config(pc, gpio, false); | 
 | 	/* Clear events that were latched prior to clearing event sources */ | 
 | 	bcm2835_gpio_set_bit(pc, GPEDS0, gpio); | 
 | 	clear_bit(offset, &pc->enabled_irq_map[bank]); | 
 | 	spin_unlock_irqrestore(&pc->irq_lock[bank], flags); | 
 | } | 
 |  | 
 | static int __bcm2835_gpio_irq_set_type_disabled(struct bcm2835_pinctrl *pc, | 
 | 	unsigned offset, unsigned int type) | 
 | { | 
 | 	switch (type) { | 
 | 	case IRQ_TYPE_NONE: | 
 | 	case IRQ_TYPE_EDGE_RISING: | 
 | 	case IRQ_TYPE_EDGE_FALLING: | 
 | 	case IRQ_TYPE_EDGE_BOTH: | 
 | 	case IRQ_TYPE_LEVEL_HIGH: | 
 | 	case IRQ_TYPE_LEVEL_LOW: | 
 | 		pc->irq_type[offset] = type; | 
 | 		break; | 
 |  | 
 | 	default: | 
 | 		return -EINVAL; | 
 | 	} | 
 | 	return 0; | 
 | } | 
 |  | 
 | /* slower path for reconfiguring IRQ type */ | 
 | static int __bcm2835_gpio_irq_set_type_enabled(struct bcm2835_pinctrl *pc, | 
 | 	unsigned offset, unsigned int type) | 
 | { | 
 | 	switch (type) { | 
 | 	case IRQ_TYPE_NONE: | 
 | 		if (pc->irq_type[offset] != type) { | 
 | 			bcm2835_gpio_irq_config(pc, offset, false); | 
 | 			pc->irq_type[offset] = type; | 
 | 		} | 
 | 		break; | 
 |  | 
 | 	case IRQ_TYPE_EDGE_RISING: | 
 | 		if (pc->irq_type[offset] == IRQ_TYPE_EDGE_BOTH) { | 
 | 			/* RISING already enabled, disable FALLING */ | 
 | 			pc->irq_type[offset] = IRQ_TYPE_EDGE_FALLING; | 
 | 			bcm2835_gpio_irq_config(pc, offset, false); | 
 | 			pc->irq_type[offset] = type; | 
 | 		} else if (pc->irq_type[offset] != type) { | 
 | 			bcm2835_gpio_irq_config(pc, offset, false); | 
 | 			pc->irq_type[offset] = type; | 
 | 			bcm2835_gpio_irq_config(pc, offset, true); | 
 | 		} | 
 | 		break; | 
 |  | 
 | 	case IRQ_TYPE_EDGE_FALLING: | 
 | 		if (pc->irq_type[offset] == IRQ_TYPE_EDGE_BOTH) { | 
 | 			/* FALLING already enabled, disable RISING */ | 
 | 			pc->irq_type[offset] = IRQ_TYPE_EDGE_RISING; | 
 | 			bcm2835_gpio_irq_config(pc, offset, false); | 
 | 			pc->irq_type[offset] = type; | 
 | 		} else if (pc->irq_type[offset] != type) { | 
 | 			bcm2835_gpio_irq_config(pc, offset, false); | 
 | 			pc->irq_type[offset] = type; | 
 | 			bcm2835_gpio_irq_config(pc, offset, true); | 
 | 		} | 
 | 		break; | 
 |  | 
 | 	case IRQ_TYPE_EDGE_BOTH: | 
 | 		if (pc->irq_type[offset] == IRQ_TYPE_EDGE_RISING) { | 
 | 			/* RISING already enabled, enable FALLING too */ | 
 | 			pc->irq_type[offset] = IRQ_TYPE_EDGE_FALLING; | 
 | 			bcm2835_gpio_irq_config(pc, offset, true); | 
 | 			pc->irq_type[offset] = type; | 
 | 		} else if (pc->irq_type[offset] == IRQ_TYPE_EDGE_FALLING) { | 
 | 			/* FALLING already enabled, enable RISING too */ | 
 | 			pc->irq_type[offset] = IRQ_TYPE_EDGE_RISING; | 
 | 			bcm2835_gpio_irq_config(pc, offset, true); | 
 | 			pc->irq_type[offset] = type; | 
 | 		} else if (pc->irq_type[offset] != type) { | 
 | 			bcm2835_gpio_irq_config(pc, offset, false); | 
 | 			pc->irq_type[offset] = type; | 
 | 			bcm2835_gpio_irq_config(pc, offset, true); | 
 | 		} | 
 | 		break; | 
 |  | 
 | 	case IRQ_TYPE_LEVEL_HIGH: | 
 | 	case IRQ_TYPE_LEVEL_LOW: | 
 | 		if (pc->irq_type[offset] != type) { | 
 | 			bcm2835_gpio_irq_config(pc, offset, false); | 
 | 			pc->irq_type[offset] = type; | 
 | 			bcm2835_gpio_irq_config(pc, offset, true); | 
 | 		} | 
 | 		break; | 
 |  | 
 | 	default: | 
 | 		return -EINVAL; | 
 | 	} | 
 | 	return 0; | 
 | } | 
 |  | 
 | static int bcm2835_gpio_irq_set_type(struct irq_data *data, unsigned int type) | 
 | { | 
 | 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data); | 
 | 	struct bcm2835_pinctrl *pc = gpiochip_get_data(chip); | 
 | 	unsigned gpio = irqd_to_hwirq(data); | 
 | 	unsigned offset = GPIO_REG_SHIFT(gpio); | 
 | 	unsigned bank = GPIO_REG_OFFSET(gpio); | 
 | 	unsigned long flags; | 
 | 	int ret; | 
 |  | 
 | 	spin_lock_irqsave(&pc->irq_lock[bank], flags); | 
 |  | 
 | 	if (test_bit(offset, &pc->enabled_irq_map[bank])) | 
 | 		ret = __bcm2835_gpio_irq_set_type_enabled(pc, gpio, type); | 
 | 	else | 
 | 		ret = __bcm2835_gpio_irq_set_type_disabled(pc, gpio, type); | 
 |  | 
 | 	if (type & IRQ_TYPE_EDGE_BOTH) | 
 | 		irq_set_handler_locked(data, handle_edge_irq); | 
 | 	else | 
 | 		irq_set_handler_locked(data, handle_level_irq); | 
 |  | 
 | 	spin_unlock_irqrestore(&pc->irq_lock[bank], flags); | 
 |  | 
 | 	return ret; | 
 | } | 
 |  | 
 | static void bcm2835_gpio_irq_ack(struct irq_data *data) | 
 | { | 
 | 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data); | 
 | 	struct bcm2835_pinctrl *pc = gpiochip_get_data(chip); | 
 | 	unsigned gpio = irqd_to_hwirq(data); | 
 |  | 
 | 	bcm2835_gpio_set_bit(pc, GPEDS0, gpio); | 
 | } | 
 |  | 
 | static struct irq_chip bcm2835_gpio_irq_chip = { | 
 | 	.name = MODULE_NAME, | 
 | 	.irq_enable = bcm2835_gpio_irq_enable, | 
 | 	.irq_disable = bcm2835_gpio_irq_disable, | 
 | 	.irq_set_type = bcm2835_gpio_irq_set_type, | 
 | 	.irq_ack = bcm2835_gpio_irq_ack, | 
 | 	.irq_mask = bcm2835_gpio_irq_disable, | 
 | 	.irq_unmask = bcm2835_gpio_irq_enable, | 
 | }; | 
 |  | 
 | static int bcm2835_pctl_get_groups_count(struct pinctrl_dev *pctldev) | 
 | { | 
 | 	return ARRAY_SIZE(bcm2835_gpio_groups); | 
 | } | 
 |  | 
 | static const char *bcm2835_pctl_get_group_name(struct pinctrl_dev *pctldev, | 
 | 		unsigned selector) | 
 | { | 
 | 	return bcm2835_gpio_groups[selector]; | 
 | } | 
 |  | 
 | static int bcm2835_pctl_get_group_pins(struct pinctrl_dev *pctldev, | 
 | 		unsigned selector, | 
 | 		const unsigned **pins, | 
 | 		unsigned *num_pins) | 
 | { | 
 | 	*pins = &bcm2835_gpio_pins[selector].number; | 
 | 	*num_pins = 1; | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static void bcm2835_pctl_pin_dbg_show(struct pinctrl_dev *pctldev, | 
 | 		struct seq_file *s, | 
 | 		unsigned offset) | 
 | { | 
 | 	struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); | 
 | 	struct gpio_chip *chip = &pc->gpio_chip; | 
 | 	enum bcm2835_fsel fsel = bcm2835_pinctrl_fsel_get(pc, offset); | 
 | 	const char *fname = bcm2835_functions[fsel]; | 
 | 	int value = bcm2835_gpio_get_bit(pc, GPLEV0, offset); | 
 | 	int irq = irq_find_mapping(chip->irqdomain, offset); | 
 |  | 
 | 	seq_printf(s, "function %s in %s; irq %d (%s)", | 
 | 		fname, value ? "hi" : "lo", | 
 | 		irq, irq_type_names[pc->irq_type[offset]]); | 
 | } | 
 |  | 
 | static void bcm2835_pctl_dt_free_map(struct pinctrl_dev *pctldev, | 
 | 		struct pinctrl_map *maps, unsigned num_maps) | 
 | { | 
 | 	int i; | 
 |  | 
 | 	for (i = 0; i < num_maps; i++) | 
 | 		if (maps[i].type == PIN_MAP_TYPE_CONFIGS_PIN) | 
 | 			kfree(maps[i].data.configs.configs); | 
 |  | 
 | 	kfree(maps); | 
 | } | 
 |  | 
 | static int bcm2835_pctl_dt_node_to_map_func(struct bcm2835_pinctrl *pc, | 
 | 		struct device_node *np, u32 pin, u32 fnum, | 
 | 		struct pinctrl_map **maps) | 
 | { | 
 | 	struct pinctrl_map *map = *maps; | 
 |  | 
 | 	if (fnum >= ARRAY_SIZE(bcm2835_functions)) { | 
 | 		dev_err(pc->dev, "%pOF: invalid brcm,function %d\n", np, fnum); | 
 | 		return -EINVAL; | 
 | 	} | 
 |  | 
 | 	map->type = PIN_MAP_TYPE_MUX_GROUP; | 
 | 	map->data.mux.group = bcm2835_gpio_groups[pin]; | 
 | 	map->data.mux.function = bcm2835_functions[fnum]; | 
 | 	(*maps)++; | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static int bcm2835_pctl_dt_node_to_map_pull(struct bcm2835_pinctrl *pc, | 
 | 		struct device_node *np, u32 pin, u32 pull, | 
 | 		struct pinctrl_map **maps) | 
 | { | 
 | 	struct pinctrl_map *map = *maps; | 
 | 	unsigned long *configs; | 
 |  | 
 | 	if (pull > 2) { | 
 | 		dev_err(pc->dev, "%pOF: invalid brcm,pull %d\n", np, pull); | 
 | 		return -EINVAL; | 
 | 	} | 
 |  | 
 | 	configs = kzalloc(sizeof(*configs), GFP_KERNEL); | 
 | 	if (!configs) | 
 | 		return -ENOMEM; | 
 | 	configs[0] = BCM2835_PINCONF_PACK(BCM2835_PINCONF_PARAM_PULL, pull); | 
 |  | 
 | 	map->type = PIN_MAP_TYPE_CONFIGS_PIN; | 
 | 	map->data.configs.group_or_pin = bcm2835_gpio_pins[pin].name; | 
 | 	map->data.configs.configs = configs; | 
 | 	map->data.configs.num_configs = 1; | 
 | 	(*maps)++; | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static int bcm2835_pctl_dt_node_to_map(struct pinctrl_dev *pctldev, | 
 | 		struct device_node *np, | 
 | 		struct pinctrl_map **map, unsigned *num_maps) | 
 | { | 
 | 	struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); | 
 | 	struct property *pins, *funcs, *pulls; | 
 | 	int num_pins, num_funcs, num_pulls, maps_per_pin; | 
 | 	struct pinctrl_map *maps, *cur_map; | 
 | 	int i, err; | 
 | 	u32 pin, func, pull; | 
 |  | 
 | 	pins = of_find_property(np, "brcm,pins", NULL); | 
 | 	if (!pins) { | 
 | 		dev_err(pc->dev, "%pOF: missing brcm,pins property\n", np); | 
 | 		return -EINVAL; | 
 | 	} | 
 |  | 
 | 	funcs = of_find_property(np, "brcm,function", NULL); | 
 | 	pulls = of_find_property(np, "brcm,pull", NULL); | 
 |  | 
 | 	if (!funcs && !pulls) { | 
 | 		dev_err(pc->dev, | 
 | 			"%pOF: neither brcm,function nor brcm,pull specified\n", | 
 | 			np); | 
 | 		return -EINVAL; | 
 | 	} | 
 |  | 
 | 	num_pins = pins->length / 4; | 
 | 	num_funcs = funcs ? (funcs->length / 4) : 0; | 
 | 	num_pulls = pulls ? (pulls->length / 4) : 0; | 
 |  | 
 | 	if (num_funcs > 1 && num_funcs != num_pins) { | 
 | 		dev_err(pc->dev, | 
 | 			"%pOF: brcm,function must have 1 or %d entries\n", | 
 | 			np, num_pins); | 
 | 		return -EINVAL; | 
 | 	} | 
 |  | 
 | 	if (num_pulls > 1 && num_pulls != num_pins) { | 
 | 		dev_err(pc->dev, | 
 | 			"%pOF: brcm,pull must have 1 or %d entries\n", | 
 | 			np, num_pins); | 
 | 		return -EINVAL; | 
 | 	} | 
 |  | 
 | 	maps_per_pin = 0; | 
 | 	if (num_funcs) | 
 | 		maps_per_pin++; | 
 | 	if (num_pulls) | 
 | 		maps_per_pin++; | 
 | 	cur_map = maps = kzalloc(num_pins * maps_per_pin * sizeof(*maps), | 
 | 				GFP_KERNEL); | 
 | 	if (!maps) | 
 | 		return -ENOMEM; | 
 |  | 
 | 	for (i = 0; i < num_pins; i++) { | 
 | 		err = of_property_read_u32_index(np, "brcm,pins", i, &pin); | 
 | 		if (err) | 
 | 			goto out; | 
 | 		if (pin >= ARRAY_SIZE(bcm2835_gpio_pins)) { | 
 | 			dev_err(pc->dev, "%pOF: invalid brcm,pins value %d\n", | 
 | 				np, pin); | 
 | 			err = -EINVAL; | 
 | 			goto out; | 
 | 		} | 
 |  | 
 | 		if (num_funcs) { | 
 | 			err = of_property_read_u32_index(np, "brcm,function", | 
 | 					(num_funcs > 1) ? i : 0, &func); | 
 | 			if (err) | 
 | 				goto out; | 
 | 			err = bcm2835_pctl_dt_node_to_map_func(pc, np, pin, | 
 | 							func, &cur_map); | 
 | 			if (err) | 
 | 				goto out; | 
 | 		} | 
 | 		if (num_pulls) { | 
 | 			err = of_property_read_u32_index(np, "brcm,pull", | 
 | 					(num_pulls > 1) ? i : 0, &pull); | 
 | 			if (err) | 
 | 				goto out; | 
 | 			err = bcm2835_pctl_dt_node_to_map_pull(pc, np, pin, | 
 | 							pull, &cur_map); | 
 | 			if (err) | 
 | 				goto out; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	*map = maps; | 
 | 	*num_maps = num_pins * maps_per_pin; | 
 |  | 
 | 	return 0; | 
 |  | 
 | out: | 
 | 	bcm2835_pctl_dt_free_map(pctldev, maps, num_pins * maps_per_pin); | 
 | 	return err; | 
 | } | 
 |  | 
 | static const struct pinctrl_ops bcm2835_pctl_ops = { | 
 | 	.get_groups_count = bcm2835_pctl_get_groups_count, | 
 | 	.get_group_name = bcm2835_pctl_get_group_name, | 
 | 	.get_group_pins = bcm2835_pctl_get_group_pins, | 
 | 	.pin_dbg_show = bcm2835_pctl_pin_dbg_show, | 
 | 	.dt_node_to_map = bcm2835_pctl_dt_node_to_map, | 
 | 	.dt_free_map = bcm2835_pctl_dt_free_map, | 
 | }; | 
 |  | 
 | static int bcm2835_pmx_free(struct pinctrl_dev *pctldev, | 
 | 		unsigned offset) | 
 | { | 
 | 	struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); | 
 |  | 
 | 	/* disable by setting to GPIO_IN */ | 
 | 	bcm2835_pinctrl_fsel_set(pc, offset, BCM2835_FSEL_GPIO_IN); | 
 | 	return 0; | 
 | } | 
 |  | 
 | static int bcm2835_pmx_get_functions_count(struct pinctrl_dev *pctldev) | 
 | { | 
 | 	return BCM2835_FSEL_COUNT; | 
 | } | 
 |  | 
 | static const char *bcm2835_pmx_get_function_name(struct pinctrl_dev *pctldev, | 
 | 		unsigned selector) | 
 | { | 
 | 	return bcm2835_functions[selector]; | 
 | } | 
 |  | 
 | static int bcm2835_pmx_get_function_groups(struct pinctrl_dev *pctldev, | 
 | 		unsigned selector, | 
 | 		const char * const **groups, | 
 | 		unsigned * const num_groups) | 
 | { | 
 | 	/* every pin can do every function */ | 
 | 	*groups = bcm2835_gpio_groups; | 
 | 	*num_groups = ARRAY_SIZE(bcm2835_gpio_groups); | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static int bcm2835_pmx_set(struct pinctrl_dev *pctldev, | 
 | 		unsigned func_selector, | 
 | 		unsigned group_selector) | 
 | { | 
 | 	struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); | 
 |  | 
 | 	bcm2835_pinctrl_fsel_set(pc, group_selector, func_selector); | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static void bcm2835_pmx_gpio_disable_free(struct pinctrl_dev *pctldev, | 
 | 		struct pinctrl_gpio_range *range, | 
 | 		unsigned offset) | 
 | { | 
 | 	struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); | 
 |  | 
 | 	/* disable by setting to GPIO_IN */ | 
 | 	bcm2835_pinctrl_fsel_set(pc, offset, BCM2835_FSEL_GPIO_IN); | 
 | } | 
 |  | 
 | static int bcm2835_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, | 
 | 		struct pinctrl_gpio_range *range, | 
 | 		unsigned offset, | 
 | 		bool input) | 
 | { | 
 | 	struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); | 
 | 	enum bcm2835_fsel fsel = input ? | 
 | 		BCM2835_FSEL_GPIO_IN : BCM2835_FSEL_GPIO_OUT; | 
 |  | 
 | 	bcm2835_pinctrl_fsel_set(pc, offset, fsel); | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static const struct pinmux_ops bcm2835_pmx_ops = { | 
 | 	.free = bcm2835_pmx_free, | 
 | 	.get_functions_count = bcm2835_pmx_get_functions_count, | 
 | 	.get_function_name = bcm2835_pmx_get_function_name, | 
 | 	.get_function_groups = bcm2835_pmx_get_function_groups, | 
 | 	.set_mux = bcm2835_pmx_set, | 
 | 	.gpio_disable_free = bcm2835_pmx_gpio_disable_free, | 
 | 	.gpio_set_direction = bcm2835_pmx_gpio_set_direction, | 
 | }; | 
 |  | 
 | static int bcm2835_pinconf_get(struct pinctrl_dev *pctldev, | 
 | 			unsigned pin, unsigned long *config) | 
 | { | 
 | 	/* No way to read back config in HW */ | 
 | 	return -ENOTSUPP; | 
 | } | 
 |  | 
 | static int bcm2835_pinconf_set(struct pinctrl_dev *pctldev, | 
 | 			unsigned pin, unsigned long *configs, | 
 | 			unsigned num_configs) | 
 | { | 
 | 	struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); | 
 | 	enum bcm2835_pinconf_param param; | 
 | 	u16 arg; | 
 | 	u32 off, bit; | 
 | 	int i; | 
 |  | 
 | 	for (i = 0; i < num_configs; i++) { | 
 | 		param = BCM2835_PINCONF_UNPACK_PARAM(configs[i]); | 
 | 		arg = BCM2835_PINCONF_UNPACK_ARG(configs[i]); | 
 |  | 
 | 		if (param != BCM2835_PINCONF_PARAM_PULL) | 
 | 			return -EINVAL; | 
 |  | 
 | 		off = GPIO_REG_OFFSET(pin); | 
 | 		bit = GPIO_REG_SHIFT(pin); | 
 |  | 
 | 		bcm2835_gpio_wr(pc, GPPUD, arg & 3); | 
 | 		/* | 
 | 		 * BCM2835 datasheet say to wait 150 cycles, but not of what. | 
 | 		 * But the VideoCore firmware delay for this operation | 
 | 		 * based nearly on the same amount of VPU cycles and this clock | 
 | 		 * runs at 250 MHz. | 
 | 		 */ | 
 | 		udelay(1); | 
 | 		bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), BIT(bit)); | 
 | 		udelay(1); | 
 | 		bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), 0); | 
 | 	} /* for each config */ | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static const struct pinconf_ops bcm2835_pinconf_ops = { | 
 | 	.pin_config_get = bcm2835_pinconf_get, | 
 | 	.pin_config_set = bcm2835_pinconf_set, | 
 | }; | 
 |  | 
 | static struct pinctrl_desc bcm2835_pinctrl_desc = { | 
 | 	.name = MODULE_NAME, | 
 | 	.pins = bcm2835_gpio_pins, | 
 | 	.npins = ARRAY_SIZE(bcm2835_gpio_pins), | 
 | 	.pctlops = &bcm2835_pctl_ops, | 
 | 	.pmxops = &bcm2835_pmx_ops, | 
 | 	.confops = &bcm2835_pinconf_ops, | 
 | 	.owner = THIS_MODULE, | 
 | }; | 
 |  | 
 | static struct pinctrl_gpio_range bcm2835_pinctrl_gpio_range = { | 
 | 	.name = MODULE_NAME, | 
 | 	.npins = BCM2835_NUM_GPIOS, | 
 | }; | 
 |  | 
 | 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.parent = dev; | 
 | 	pc->gpio_chip.of_node = np; | 
 |  | 
 | 	for (i = 0; i < BCM2835_NUM_BANKS; i++) { | 
 | 		unsigned long events; | 
 | 		unsigned offset; | 
 |  | 
 | 		/* 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)); | 
 |  | 
 | 		spin_lock_init(&pc->irq_lock[i]); | 
 | 	} | 
 |  | 
 | 	err = gpiochip_add_data(&pc->gpio_chip, pc); | 
 | 	if (err) { | 
 | 		dev_err(dev, "could not add GPIO chip\n"); | 
 | 		return err; | 
 | 	} | 
 |  | 
 | 	err = gpiochip_irqchip_add(&pc->gpio_chip, &bcm2835_gpio_irq_chip, | 
 | 				   0, handle_level_irq, IRQ_TYPE_NONE); | 
 | 	if (err) { | 
 | 		dev_info(dev, "could not add irqchip\n"); | 
 | 		return err; | 
 | 	} | 
 |  | 
 | 	for (i = 0; i < BCM2835_NUM_IRQS; i++) { | 
 | 		pc->irq[i] = irq_of_parse_and_map(np, i); | 
 |  | 
 | 		if (pc->irq[i] == 0) | 
 | 			continue; | 
 |  | 
 | 		/* | 
 | 		 * Use the same handler for all groups: this is necessary | 
 | 		 * since we use one gpiochip to cover all lines - the | 
 | 		 * irq handler then needs to figure out which group and | 
 | 		 * bank that was firing the IRQ and look up the per-group | 
 | 		 * and bank data. | 
 | 		 */ | 
 | 		gpiochip_set_chained_irqchip(&pc->gpio_chip, | 
 | 					     &bcm2835_gpio_irq_chip, | 
 | 					     pc->irq[i], | 
 | 					     bcm2835_gpio_irq_handler); | 
 | 	} | 
 |  | 
 | 	pc->pctl_dev = devm_pinctrl_register(dev, &bcm2835_pinctrl_desc, pc); | 
 | 	if (IS_ERR(pc->pctl_dev)) { | 
 | 		gpiochip_remove(&pc->gpio_chip); | 
 | 		return PTR_ERR(pc->pctl_dev); | 
 | 	} | 
 |  | 
 | 	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; | 
 | } | 
 |  | 
 | static const struct of_device_id bcm2835_pinctrl_match[] = { | 
 | 	{ .compatible = "brcm,bcm2835-gpio" }, | 
 | 	{} | 
 | }; | 
 |  | 
 | static struct platform_driver bcm2835_pinctrl_driver = { | 
 | 	.probe = bcm2835_pinctrl_probe, | 
 | 	.driver = { | 
 | 		.name = MODULE_NAME, | 
 | 		.of_match_table = bcm2835_pinctrl_match, | 
 | 		.suppress_bind_attrs = true, | 
 | 	}, | 
 | }; | 
 | builtin_platform_driver(bcm2835_pinctrl_driver); |