xref: /linux/drivers/pinctrl/bcm/pinctrl-bcm2835.c (revision 4bc80da53317edd1c31c183203aa7d8809c42667)
1a62c3677SStefan Wahren // SPDX-License-Identifier: GPL-2.0+
2e1b2dc70SSimon Arlott /*
3e1b2dc70SSimon Arlott  * Driver for Broadcom BCM2835 GPIO unit (pinctrl + GPIO)
4e1b2dc70SSimon Arlott  *
5e1b2dc70SSimon Arlott  * Copyright (C) 2012 Chris Boot, Simon Arlott, Stephen Warren
6e1b2dc70SSimon Arlott  *
7e1b2dc70SSimon Arlott  * This driver is inspired by:
8e1b2dc70SSimon Arlott  * pinctrl-nomadik.c, please see original file for copyright information
9e1b2dc70SSimon Arlott  * pinctrl-tegra.c, please see original file for copyright information
10e1b2dc70SSimon Arlott  */
11e1b2dc70SSimon Arlott 
12e1b2dc70SSimon Arlott #include <linux/bitmap.h>
13e1b2dc70SSimon Arlott #include <linux/bug.h>
14e1b2dc70SSimon Arlott #include <linux/delay.h>
15e1b2dc70SSimon Arlott #include <linux/device.h>
16e1b2dc70SSimon Arlott #include <linux/err.h>
17e19a5f79SLinus Walleij #include <linux/gpio/driver.h>
18e1b2dc70SSimon Arlott #include <linux/io.h>
19e1b2dc70SSimon Arlott #include <linux/irq.h>
20e1b2dc70SSimon Arlott #include <linux/irqdesc.h>
2134f46848SPaul Gortmaker #include <linux/init.h>
22920fecc1SFlorian Fainelli #include <linux/interrupt.h>
23e1b2dc70SSimon Arlott #include <linux/of_address.h>
24e1b2dc70SSimon Arlott #include <linux/of.h>
25e1b2dc70SSimon Arlott #include <linux/of_irq.h>
26e1b2dc70SSimon Arlott #include <linux/pinctrl/consumer.h>
27e1b2dc70SSimon Arlott #include <linux/pinctrl/machine.h>
28e1b2dc70SSimon Arlott #include <linux/pinctrl/pinconf.h>
29e1b2dc70SSimon Arlott #include <linux/pinctrl/pinctrl.h>
30e1b2dc70SSimon Arlott #include <linux/pinctrl/pinmux.h>
310de70495SMatheus Castello #include <linux/pinctrl/pinconf-generic.h>
32e1b2dc70SSimon Arlott #include <linux/platform_device.h>
33e1b2dc70SSimon Arlott #include <linux/seq_file.h>
34e1b2dc70SSimon Arlott #include <linux/slab.h>
35e1b2dc70SSimon Arlott #include <linux/spinlock.h>
36e1b2dc70SSimon Arlott #include <linux/types.h>
370de70495SMatheus Castello #include <dt-bindings/pinctrl/bcm2835.h>
38e1b2dc70SSimon Arlott 
39e1b2dc70SSimon Arlott #define MODULE_NAME "pinctrl-bcm2835"
40e1b2dc70SSimon Arlott #define BCM2835_NUM_GPIOS 54
41b1d84a3dSStefan Wahren #define BCM2711_NUM_GPIOS 58
42e1b2dc70SSimon Arlott #define BCM2835_NUM_BANKS 2
4300445b5dSPhil Elwell #define BCM2835_NUM_IRQS  3
44e1b2dc70SSimon Arlott 
45e1b2dc70SSimon Arlott /* GPIO register offsets */
46e1b2dc70SSimon Arlott #define GPFSEL0		0x0	/* Function Select */
47e1b2dc70SSimon Arlott #define GPSET0		0x1c	/* Pin Output Set */
48e1b2dc70SSimon Arlott #define GPCLR0		0x28	/* Pin Output Clear */
49e1b2dc70SSimon Arlott #define GPLEV0		0x34	/* Pin Level */
50e1b2dc70SSimon Arlott #define GPEDS0		0x40	/* Pin Event Detect Status */
51e1b2dc70SSimon Arlott #define GPREN0		0x4c	/* Pin Rising Edge Detect Enable */
52e1b2dc70SSimon Arlott #define GPFEN0		0x58	/* Pin Falling Edge Detect Enable */
53e1b2dc70SSimon Arlott #define GPHEN0		0x64	/* Pin High Detect Enable */
54e1b2dc70SSimon Arlott #define GPLEN0		0x70	/* Pin Low Detect Enable */
55e1b2dc70SSimon Arlott #define GPAREN0		0x7c	/* Pin Async Rising Edge Detect */
56e1b2dc70SSimon Arlott #define GPAFEN0		0x88	/* Pin Async Falling Edge Detect */
57e1b2dc70SSimon Arlott #define GPPUD		0x94	/* Pin Pull-up/down Enable */
58e1b2dc70SSimon Arlott #define GPPUDCLK0	0x98	/* Pin Pull-up/down Enable Clock */
59e38a9a43SStefan Wahren #define GP_GPIO_PUP_PDN_CNTRL_REG0 0xe4 /* 2711 Pin Pull-up/down select */
60e1b2dc70SSimon Arlott 
61e1b2dc70SSimon Arlott #define FSEL_REG(p)		(GPFSEL0 + (((p) / 10) * 4))
62e1b2dc70SSimon Arlott #define FSEL_SHIFT(p)		(((p) % 10) * 3)
63e1b2dc70SSimon Arlott #define GPIO_REG_OFFSET(p)	((p) / 32)
64e1b2dc70SSimon Arlott #define GPIO_REG_SHIFT(p)	((p) % 32)
65e1b2dc70SSimon Arlott 
66e38a9a43SStefan Wahren #define PUD_2711_MASK		0x3
67e38a9a43SStefan Wahren #define PUD_2711_REG_OFFSET(p)	((p) / 16)
68e38a9a43SStefan Wahren #define PUD_2711_REG_SHIFT(p)	(((p) % 16) * 2)
69e38a9a43SStefan Wahren 
70e1b2dc70SSimon Arlott /* argument: bcm2835_pinconf_pull */
71b40ac08fSNathan Chancellor #define BCM2835_PINCONF_PARAM_PULL	(PIN_CONFIG_END + 1)
72e1b2dc70SSimon Arlott 
73e38a9a43SStefan Wahren #define BCM2711_PULL_NONE	0x0
74e38a9a43SStefan Wahren #define BCM2711_PULL_UP		0x1
75e38a9a43SStefan Wahren #define BCM2711_PULL_DOWN	0x2
76e38a9a43SStefan Wahren 
77e1b2dc70SSimon Arlott struct bcm2835_pinctrl {
78e1b2dc70SSimon Arlott 	struct device *dev;
79e1b2dc70SSimon Arlott 	void __iomem *base;
80920fecc1SFlorian Fainelli 	int *wake_irq;
81e1b2dc70SSimon Arlott 
82e1b2dc70SSimon Arlott 	/* note: locking assumes each bank will have its own unsigned long */
83e1b2dc70SSimon Arlott 	unsigned long enabled_irq_map[BCM2835_NUM_BANKS];
84b1d84a3dSStefan Wahren 	unsigned int irq_type[BCM2711_NUM_GPIOS];
85e1b2dc70SSimon Arlott 
86e1b2dc70SSimon Arlott 	struct pinctrl_dev *pctl_dev;
87e1b2dc70SSimon Arlott 	struct gpio_chip gpio_chip;
8890bfaf02SStefan Wahren 	struct pinctrl_desc pctl_desc;
89e1b2dc70SSimon Arlott 	struct pinctrl_gpio_range gpio_range;
90e1b2dc70SSimon Arlott 
913c7b30f7SLukas Wunner 	raw_spinlock_t irq_lock[BCM2835_NUM_BANKS];
92e1b2dc70SSimon Arlott };
93e1b2dc70SSimon Arlott 
94e1b2dc70SSimon Arlott /* pins are just named GPIO0..GPIO53 */
95e1b2dc70SSimon Arlott #define BCM2835_GPIO_PIN(a) PINCTRL_PIN(a, "gpio" #a)
96e8ed912eSSachin Kamat static struct pinctrl_pin_desc bcm2835_gpio_pins[] = {
97e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(0),
98e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(1),
99e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(2),
100e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(3),
101e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(4),
102e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(5),
103e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(6),
104e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(7),
105e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(8),
106e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(9),
107e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(10),
108e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(11),
109e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(12),
110e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(13),
111e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(14),
112e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(15),
113e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(16),
114e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(17),
115e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(18),
116e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(19),
117e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(20),
118e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(21),
119e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(22),
120e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(23),
121e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(24),
122e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(25),
123e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(26),
124e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(27),
125e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(28),
126e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(29),
127e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(30),
128e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(31),
129e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(32),
130e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(33),
131e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(34),
132e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(35),
133e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(36),
134e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(37),
135e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(38),
136e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(39),
137e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(40),
138e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(41),
139e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(42),
140e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(43),
141e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(44),
142e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(45),
143e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(46),
144e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(47),
145e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(48),
146e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(49),
147e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(50),
148e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(51),
149e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(52),
150e1b2dc70SSimon Arlott 	BCM2835_GPIO_PIN(53),
151b1d84a3dSStefan Wahren 	BCM2835_GPIO_PIN(54),
152b1d84a3dSStefan Wahren 	BCM2835_GPIO_PIN(55),
153b1d84a3dSStefan Wahren 	BCM2835_GPIO_PIN(56),
154b1d84a3dSStefan Wahren 	BCM2835_GPIO_PIN(57),
155e1b2dc70SSimon Arlott };
156e1b2dc70SSimon Arlott 
157e1b2dc70SSimon Arlott /* one pin per group */
158e1b2dc70SSimon Arlott static const char * const bcm2835_gpio_groups[] = {
159e1b2dc70SSimon Arlott 	"gpio0",
160e1b2dc70SSimon Arlott 	"gpio1",
161e1b2dc70SSimon Arlott 	"gpio2",
162e1b2dc70SSimon Arlott 	"gpio3",
163e1b2dc70SSimon Arlott 	"gpio4",
164e1b2dc70SSimon Arlott 	"gpio5",
165e1b2dc70SSimon Arlott 	"gpio6",
166e1b2dc70SSimon Arlott 	"gpio7",
167e1b2dc70SSimon Arlott 	"gpio8",
168e1b2dc70SSimon Arlott 	"gpio9",
169e1b2dc70SSimon Arlott 	"gpio10",
170e1b2dc70SSimon Arlott 	"gpio11",
171e1b2dc70SSimon Arlott 	"gpio12",
172e1b2dc70SSimon Arlott 	"gpio13",
173e1b2dc70SSimon Arlott 	"gpio14",
174e1b2dc70SSimon Arlott 	"gpio15",
175e1b2dc70SSimon Arlott 	"gpio16",
176e1b2dc70SSimon Arlott 	"gpio17",
177e1b2dc70SSimon Arlott 	"gpio18",
178e1b2dc70SSimon Arlott 	"gpio19",
179e1b2dc70SSimon Arlott 	"gpio20",
180e1b2dc70SSimon Arlott 	"gpio21",
181e1b2dc70SSimon Arlott 	"gpio22",
182e1b2dc70SSimon Arlott 	"gpio23",
183e1b2dc70SSimon Arlott 	"gpio24",
184e1b2dc70SSimon Arlott 	"gpio25",
185e1b2dc70SSimon Arlott 	"gpio26",
186e1b2dc70SSimon Arlott 	"gpio27",
187e1b2dc70SSimon Arlott 	"gpio28",
188e1b2dc70SSimon Arlott 	"gpio29",
189e1b2dc70SSimon Arlott 	"gpio30",
190e1b2dc70SSimon Arlott 	"gpio31",
191e1b2dc70SSimon Arlott 	"gpio32",
192e1b2dc70SSimon Arlott 	"gpio33",
193e1b2dc70SSimon Arlott 	"gpio34",
194e1b2dc70SSimon Arlott 	"gpio35",
195e1b2dc70SSimon Arlott 	"gpio36",
196e1b2dc70SSimon Arlott 	"gpio37",
197e1b2dc70SSimon Arlott 	"gpio38",
198e1b2dc70SSimon Arlott 	"gpio39",
199e1b2dc70SSimon Arlott 	"gpio40",
200e1b2dc70SSimon Arlott 	"gpio41",
201e1b2dc70SSimon Arlott 	"gpio42",
202e1b2dc70SSimon Arlott 	"gpio43",
203e1b2dc70SSimon Arlott 	"gpio44",
204e1b2dc70SSimon Arlott 	"gpio45",
205e1b2dc70SSimon Arlott 	"gpio46",
206e1b2dc70SSimon Arlott 	"gpio47",
207e1b2dc70SSimon Arlott 	"gpio48",
208e1b2dc70SSimon Arlott 	"gpio49",
209e1b2dc70SSimon Arlott 	"gpio50",
210e1b2dc70SSimon Arlott 	"gpio51",
211e1b2dc70SSimon Arlott 	"gpio52",
212e1b2dc70SSimon Arlott 	"gpio53",
213b1d84a3dSStefan Wahren 	"gpio54",
214b1d84a3dSStefan Wahren 	"gpio55",
215b1d84a3dSStefan Wahren 	"gpio56",
216b1d84a3dSStefan Wahren 	"gpio57",
217e1b2dc70SSimon Arlott };
218e1b2dc70SSimon Arlott 
219e1b2dc70SSimon Arlott enum bcm2835_fsel {
220e1b2dc70SSimon Arlott 	BCM2835_FSEL_COUNT = 8,
221e1b2dc70SSimon Arlott 	BCM2835_FSEL_MASK = 0x7,
222e1b2dc70SSimon Arlott };
223e1b2dc70SSimon Arlott 
224e1b2dc70SSimon Arlott static const char * const bcm2835_functions[BCM2835_FSEL_COUNT] = {
225e1b2dc70SSimon Arlott 	[BCM2835_FSEL_GPIO_IN] = "gpio_in",
226e1b2dc70SSimon Arlott 	[BCM2835_FSEL_GPIO_OUT] = "gpio_out",
227e1b2dc70SSimon Arlott 	[BCM2835_FSEL_ALT0] = "alt0",
228e1b2dc70SSimon Arlott 	[BCM2835_FSEL_ALT1] = "alt1",
229e1b2dc70SSimon Arlott 	[BCM2835_FSEL_ALT2] = "alt2",
230e1b2dc70SSimon Arlott 	[BCM2835_FSEL_ALT3] = "alt3",
231e1b2dc70SSimon Arlott 	[BCM2835_FSEL_ALT4] = "alt4",
232e1b2dc70SSimon Arlott 	[BCM2835_FSEL_ALT5] = "alt5",
233e1b2dc70SSimon Arlott };
234e1b2dc70SSimon Arlott 
235e1b2dc70SSimon Arlott static const char * const irq_type_names[] = {
236e1b2dc70SSimon Arlott 	[IRQ_TYPE_NONE] = "none",
237e1b2dc70SSimon Arlott 	[IRQ_TYPE_EDGE_RISING] = "edge-rising",
238e1b2dc70SSimon Arlott 	[IRQ_TYPE_EDGE_FALLING] = "edge-falling",
239e1b2dc70SSimon Arlott 	[IRQ_TYPE_EDGE_BOTH] = "edge-both",
240e1b2dc70SSimon Arlott 	[IRQ_TYPE_LEVEL_HIGH] = "level-high",
241e1b2dc70SSimon Arlott 	[IRQ_TYPE_LEVEL_LOW] = "level-low",
242e1b2dc70SSimon Arlott };
243e1b2dc70SSimon Arlott 
244e1b2dc70SSimon Arlott static inline u32 bcm2835_gpio_rd(struct bcm2835_pinctrl *pc, unsigned reg)
245e1b2dc70SSimon Arlott {
246e1b2dc70SSimon Arlott 	return readl(pc->base + reg);
247e1b2dc70SSimon Arlott }
248e1b2dc70SSimon Arlott 
249e1b2dc70SSimon Arlott static inline void bcm2835_gpio_wr(struct bcm2835_pinctrl *pc, unsigned reg,
250e1b2dc70SSimon Arlott 		u32 val)
251e1b2dc70SSimon Arlott {
252e1b2dc70SSimon Arlott 	writel(val, pc->base + reg);
253e1b2dc70SSimon Arlott }
254e1b2dc70SSimon Arlott 
255e1b2dc70SSimon Arlott static inline int bcm2835_gpio_get_bit(struct bcm2835_pinctrl *pc, unsigned reg,
256e1b2dc70SSimon Arlott 		unsigned bit)
257e1b2dc70SSimon Arlott {
258e1b2dc70SSimon Arlott 	reg += GPIO_REG_OFFSET(bit) * 4;
259e1b2dc70SSimon Arlott 	return (bcm2835_gpio_rd(pc, reg) >> GPIO_REG_SHIFT(bit)) & 1;
260e1b2dc70SSimon Arlott }
261e1b2dc70SSimon Arlott 
262e1b2dc70SSimon Arlott /* note NOT a read/modify/write cycle */
263e1b2dc70SSimon Arlott static inline void bcm2835_gpio_set_bit(struct bcm2835_pinctrl *pc,
264e1b2dc70SSimon Arlott 		unsigned reg, unsigned bit)
265e1b2dc70SSimon Arlott {
266e1b2dc70SSimon Arlott 	reg += GPIO_REG_OFFSET(bit) * 4;
267e1b2dc70SSimon Arlott 	bcm2835_gpio_wr(pc, reg, BIT(GPIO_REG_SHIFT(bit)));
268e1b2dc70SSimon Arlott }
269e1b2dc70SSimon Arlott 
270e1b2dc70SSimon Arlott static inline enum bcm2835_fsel bcm2835_pinctrl_fsel_get(
271e1b2dc70SSimon Arlott 		struct bcm2835_pinctrl *pc, unsigned pin)
272e1b2dc70SSimon Arlott {
273e1b2dc70SSimon Arlott 	u32 val = bcm2835_gpio_rd(pc, FSEL_REG(pin));
274e1b2dc70SSimon Arlott 	enum bcm2835_fsel status = (val >> FSEL_SHIFT(pin)) & BCM2835_FSEL_MASK;
275e1b2dc70SSimon Arlott 
276e1b2dc70SSimon Arlott 	dev_dbg(pc->dev, "get %08x (%u => %s)\n", val, pin,
277e1b2dc70SSimon Arlott 			bcm2835_functions[status]);
278e1b2dc70SSimon Arlott 
279e1b2dc70SSimon Arlott 	return status;
280e1b2dc70SSimon Arlott }
281e1b2dc70SSimon Arlott 
282e1b2dc70SSimon Arlott static inline void bcm2835_pinctrl_fsel_set(
283e1b2dc70SSimon Arlott 		struct bcm2835_pinctrl *pc, unsigned pin,
284e1b2dc70SSimon Arlott 		enum bcm2835_fsel fsel)
285e1b2dc70SSimon Arlott {
286e1b2dc70SSimon Arlott 	u32 val = bcm2835_gpio_rd(pc, FSEL_REG(pin));
287e1b2dc70SSimon Arlott 	enum bcm2835_fsel cur = (val >> FSEL_SHIFT(pin)) & BCM2835_FSEL_MASK;
288e1b2dc70SSimon Arlott 
289e1b2dc70SSimon Arlott 	dev_dbg(pc->dev, "read %08x (%u => %s)\n", val, pin,
290e1b2dc70SSimon Arlott 			bcm2835_functions[cur]);
291e1b2dc70SSimon Arlott 
292e1b2dc70SSimon Arlott 	if (cur == fsel)
293e1b2dc70SSimon Arlott 		return;
294e1b2dc70SSimon Arlott 
295e1b2dc70SSimon Arlott 	if (cur != BCM2835_FSEL_GPIO_IN && fsel != BCM2835_FSEL_GPIO_IN) {
296e1b2dc70SSimon Arlott 		/* always transition through GPIO_IN */
297e1b2dc70SSimon Arlott 		val &= ~(BCM2835_FSEL_MASK << FSEL_SHIFT(pin));
298e1b2dc70SSimon Arlott 		val |= BCM2835_FSEL_GPIO_IN << FSEL_SHIFT(pin);
299e1b2dc70SSimon Arlott 
300e1b2dc70SSimon Arlott 		dev_dbg(pc->dev, "trans %08x (%u <= %s)\n", val, pin,
301e1b2dc70SSimon Arlott 				bcm2835_functions[BCM2835_FSEL_GPIO_IN]);
302e1b2dc70SSimon Arlott 		bcm2835_gpio_wr(pc, FSEL_REG(pin), val);
303e1b2dc70SSimon Arlott 	}
304e1b2dc70SSimon Arlott 
305e1b2dc70SSimon Arlott 	val &= ~(BCM2835_FSEL_MASK << FSEL_SHIFT(pin));
306e1b2dc70SSimon Arlott 	val |= fsel << FSEL_SHIFT(pin);
307e1b2dc70SSimon Arlott 
308e1b2dc70SSimon Arlott 	dev_dbg(pc->dev, "write %08x (%u <= %s)\n", val, pin,
309e1b2dc70SSimon Arlott 			bcm2835_functions[fsel]);
310e1b2dc70SSimon Arlott 	bcm2835_gpio_wr(pc, FSEL_REG(pin), val);
311e1b2dc70SSimon Arlott }
312e1b2dc70SSimon Arlott 
313e1b2dc70SSimon Arlott static int bcm2835_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
314e1b2dc70SSimon Arlott {
315e1b2dc70SSimon Arlott 	return pinctrl_gpio_direction_input(chip->base + offset);
316e1b2dc70SSimon Arlott }
317e1b2dc70SSimon Arlott 
318e1b2dc70SSimon Arlott static int bcm2835_gpio_get(struct gpio_chip *chip, unsigned offset)
319e1b2dc70SSimon Arlott {
320e19a5f79SLinus Walleij 	struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
321e1b2dc70SSimon Arlott 
322e1b2dc70SSimon Arlott 	return bcm2835_gpio_get_bit(pc, GPLEV0, offset);
323e1b2dc70SSimon Arlott }
324e1b2dc70SSimon Arlott 
32520b3d2a7SStefan Wahren static int bcm2835_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
32620b3d2a7SStefan Wahren {
32720b3d2a7SStefan Wahren 	struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
32820b3d2a7SStefan Wahren 	enum bcm2835_fsel fsel = bcm2835_pinctrl_fsel_get(pc, offset);
32920b3d2a7SStefan Wahren 
33020b3d2a7SStefan Wahren 	/* Alternative function doesn't clearly provide a direction */
33120b3d2a7SStefan Wahren 	if (fsel > BCM2835_FSEL_GPIO_OUT)
33220b3d2a7SStefan Wahren 		return -EINVAL;
33320b3d2a7SStefan Wahren 
3343c827873SMatti Vaittinen 	if (fsel == BCM2835_FSEL_GPIO_IN)
3353c827873SMatti Vaittinen 		return GPIO_LINE_DIRECTION_IN;
3363c827873SMatti Vaittinen 
3373c827873SMatti Vaittinen 	return GPIO_LINE_DIRECTION_OUT;
33820b3d2a7SStefan Wahren }
33920b3d2a7SStefan Wahren 
340e1b2dc70SSimon Arlott static void bcm2835_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
341e1b2dc70SSimon Arlott {
342e19a5f79SLinus Walleij 	struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
343e1b2dc70SSimon Arlott 
344e1b2dc70SSimon Arlott 	bcm2835_gpio_set_bit(pc, value ? GPSET0 : GPCLR0, offset);
345e1b2dc70SSimon Arlott }
346e1b2dc70SSimon Arlott 
3474c02cba1SStefan Wahren static int bcm2835_gpio_direction_output(struct gpio_chip *chip,
3484c02cba1SStefan Wahren 		unsigned offset, int value)
3494c02cba1SStefan Wahren {
3504c02cba1SStefan Wahren 	bcm2835_gpio_set(chip, offset, value);
3514c02cba1SStefan Wahren 	return pinctrl_gpio_direction_output(chip->base + offset);
3524c02cba1SStefan Wahren }
3534c02cba1SStefan Wahren 
354531bcf73SGustavo A. R. Silva static const struct gpio_chip bcm2835_gpio_chip = {
355e1b2dc70SSimon Arlott 	.label = MODULE_NAME,
356e1b2dc70SSimon Arlott 	.owner = THIS_MODULE,
35798c85d58SJonas Gorski 	.request = gpiochip_generic_request,
35898c85d58SJonas Gorski 	.free = gpiochip_generic_free,
359e1b2dc70SSimon Arlott 	.direction_input = bcm2835_gpio_direction_input,
360e1b2dc70SSimon Arlott 	.direction_output = bcm2835_gpio_direction_output,
36120b3d2a7SStefan Wahren 	.get_direction = bcm2835_gpio_get_direction,
362e1b2dc70SSimon Arlott 	.get = bcm2835_gpio_get,
363e1b2dc70SSimon Arlott 	.set = bcm2835_gpio_set,
364b6e5531cSStefan Wahren 	.set_config = gpiochip_generic_config,
365e1b2dc70SSimon Arlott 	.base = -1,
366e1b2dc70SSimon Arlott 	.ngpio = BCM2835_NUM_GPIOS,
3679fb1f39eSLinus Walleij 	.can_sleep = false,
368e1b2dc70SSimon Arlott };
369e1b2dc70SSimon Arlott 
370b1d84a3dSStefan Wahren static const struct gpio_chip bcm2711_gpio_chip = {
371b1d84a3dSStefan Wahren 	.label = "pinctrl-bcm2711",
372b1d84a3dSStefan Wahren 	.owner = THIS_MODULE,
373b1d84a3dSStefan Wahren 	.request = gpiochip_generic_request,
374b1d84a3dSStefan Wahren 	.free = gpiochip_generic_free,
375b1d84a3dSStefan Wahren 	.direction_input = bcm2835_gpio_direction_input,
376b1d84a3dSStefan Wahren 	.direction_output = bcm2835_gpio_direction_output,
377b1d84a3dSStefan Wahren 	.get_direction = bcm2835_gpio_get_direction,
378b1d84a3dSStefan Wahren 	.get = bcm2835_gpio_get,
379b1d84a3dSStefan Wahren 	.set = bcm2835_gpio_set,
380b1d84a3dSStefan Wahren 	.set_config = gpiochip_generic_config,
381b1d84a3dSStefan Wahren 	.base = -1,
382b1d84a3dSStefan Wahren 	.ngpio = BCM2711_NUM_GPIOS,
383b1d84a3dSStefan Wahren 	.can_sleep = false,
384b1d84a3dSStefan Wahren };
385b1d84a3dSStefan Wahren 
38685ae9e51SLinus Walleij static void bcm2835_gpio_irq_handle_bank(struct bcm2835_pinctrl *pc,
38700445b5dSPhil Elwell 					 unsigned int bank, u32 mask)
388e1b2dc70SSimon Arlott {
389e1b2dc70SSimon Arlott 	unsigned long events;
390e1b2dc70SSimon Arlott 	unsigned offset;
391e1b2dc70SSimon Arlott 	unsigned gpio;
392e1b2dc70SSimon Arlott 
393e1b2dc70SSimon Arlott 	events = bcm2835_gpio_rd(pc, GPEDS0 + bank * 4);
39400445b5dSPhil Elwell 	events &= mask;
395e1b2dc70SSimon Arlott 	events &= pc->enabled_irq_map[bank];
396e1b2dc70SSimon Arlott 	for_each_set_bit(offset, &events, 32) {
397e1b2dc70SSimon Arlott 		gpio = (32 * bank) + offset;
3989e9355bbSLinus Walleij 		generic_handle_irq(irq_linear_revmap(pc->gpio_chip.irq.domain,
39985ae9e51SLinus Walleij 						     gpio));
40085ae9e51SLinus Walleij 	}
401e1b2dc70SSimon Arlott }
40200445b5dSPhil Elwell 
40385ae9e51SLinus Walleij static void bcm2835_gpio_irq_handler(struct irq_desc *desc)
40400445b5dSPhil Elwell {
40585ae9e51SLinus Walleij 	struct gpio_chip *chip = irq_desc_get_handler_data(desc);
40685ae9e51SLinus Walleij 	struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
40785ae9e51SLinus Walleij 	struct irq_chip *host_chip = irq_desc_get_chip(desc);
40885ae9e51SLinus Walleij 	int irq = irq_desc_get_irq(desc);
40985ae9e51SLinus Walleij 	int group;
41085ae9e51SLinus Walleij 	int i;
41100445b5dSPhil Elwell 
41273345a18SLinus Walleij 	for (i = 0; i < BCM2835_NUM_IRQS; i++) {
41373345a18SLinus Walleij 		if (chip->irq.parents[i] == irq) {
4140d885e9dSThierry Reding 			group = i;
41585ae9e51SLinus Walleij 			break;
41685ae9e51SLinus Walleij 		}
41785ae9e51SLinus Walleij 	}
41885ae9e51SLinus Walleij 	/* This should not happen, every IRQ has a bank */
41973345a18SLinus Walleij 	if (i == BCM2835_NUM_IRQS)
42085ae9e51SLinus Walleij 		BUG();
42185ae9e51SLinus Walleij 
42285ae9e51SLinus Walleij 	chained_irq_enter(host_chip, desc);
42385ae9e51SLinus Walleij 
42485ae9e51SLinus Walleij 	switch (group) {
42500445b5dSPhil Elwell 	case 0: /* IRQ0 covers GPIOs 0-27 */
42685ae9e51SLinus Walleij 		bcm2835_gpio_irq_handle_bank(pc, 0, 0x0fffffff);
42700445b5dSPhil Elwell 		break;
42800445b5dSPhil Elwell 	case 1: /* IRQ1 covers GPIOs 28-45 */
42985ae9e51SLinus Walleij 		bcm2835_gpio_irq_handle_bank(pc, 0, 0xf0000000);
43000445b5dSPhil Elwell 		bcm2835_gpio_irq_handle_bank(pc, 1, 0x00003fff);
43100445b5dSPhil Elwell 		break;
432b1d84a3dSStefan Wahren 	case 2: /* IRQ2 covers GPIOs 46-57 */
43385ae9e51SLinus Walleij 		bcm2835_gpio_irq_handle_bank(pc, 1, 0x003fc000);
43400445b5dSPhil Elwell 		break;
43500445b5dSPhil Elwell 	}
43600445b5dSPhil Elwell 
43785ae9e51SLinus Walleij 	chained_irq_exit(host_chip, desc);
438e1b2dc70SSimon Arlott }
439e1b2dc70SSimon Arlott 
440920fecc1SFlorian Fainelli static irqreturn_t bcm2835_gpio_wake_irq_handler(int irq, void *dev_id)
441920fecc1SFlorian Fainelli {
442920fecc1SFlorian Fainelli 	return IRQ_HANDLED;
443920fecc1SFlorian Fainelli }
444920fecc1SFlorian Fainelli 
445e1b2dc70SSimon Arlott static inline void __bcm2835_gpio_irq_config(struct bcm2835_pinctrl *pc,
446e1b2dc70SSimon Arlott 	unsigned reg, unsigned offset, bool enable)
447e1b2dc70SSimon Arlott {
448e1b2dc70SSimon Arlott 	u32 value;
449e1b2dc70SSimon Arlott 	reg += GPIO_REG_OFFSET(offset) * 4;
450e1b2dc70SSimon Arlott 	value = bcm2835_gpio_rd(pc, reg);
451e1b2dc70SSimon Arlott 	if (enable)
452e1b2dc70SSimon Arlott 		value |= BIT(GPIO_REG_SHIFT(offset));
453e1b2dc70SSimon Arlott 	else
454e1b2dc70SSimon Arlott 		value &= ~(BIT(GPIO_REG_SHIFT(offset)));
455e1b2dc70SSimon Arlott 	bcm2835_gpio_wr(pc, reg, value);
456e1b2dc70SSimon Arlott }
457e1b2dc70SSimon Arlott 
458e1b2dc70SSimon Arlott /* fast path for IRQ handler */
459e1b2dc70SSimon Arlott static void bcm2835_gpio_irq_config(struct bcm2835_pinctrl *pc,
460e1b2dc70SSimon Arlott 	unsigned offset, bool enable)
461e1b2dc70SSimon Arlott {
462e1b2dc70SSimon Arlott 	switch (pc->irq_type[offset]) {
463e1b2dc70SSimon Arlott 	case IRQ_TYPE_EDGE_RISING:
464e1b2dc70SSimon Arlott 		__bcm2835_gpio_irq_config(pc, GPREN0, offset, enable);
465e1b2dc70SSimon Arlott 		break;
466e1b2dc70SSimon Arlott 
467e1b2dc70SSimon Arlott 	case IRQ_TYPE_EDGE_FALLING:
468e1b2dc70SSimon Arlott 		__bcm2835_gpio_irq_config(pc, GPFEN0, offset, enable);
469e1b2dc70SSimon Arlott 		break;
470e1b2dc70SSimon Arlott 
471e1b2dc70SSimon Arlott 	case IRQ_TYPE_EDGE_BOTH:
472e1b2dc70SSimon Arlott 		__bcm2835_gpio_irq_config(pc, GPREN0, offset, enable);
473e1b2dc70SSimon Arlott 		__bcm2835_gpio_irq_config(pc, GPFEN0, offset, enable);
474e1b2dc70SSimon Arlott 		break;
475e1b2dc70SSimon Arlott 
476e1b2dc70SSimon Arlott 	case IRQ_TYPE_LEVEL_HIGH:
477e1b2dc70SSimon Arlott 		__bcm2835_gpio_irq_config(pc, GPHEN0, offset, enable);
478e1b2dc70SSimon Arlott 		break;
479e1b2dc70SSimon Arlott 
480e1b2dc70SSimon Arlott 	case IRQ_TYPE_LEVEL_LOW:
481e1b2dc70SSimon Arlott 		__bcm2835_gpio_irq_config(pc, GPLEN0, offset, enable);
482e1b2dc70SSimon Arlott 		break;
483e1b2dc70SSimon Arlott 	}
484e1b2dc70SSimon Arlott }
485e1b2dc70SSimon Arlott 
486e1b2dc70SSimon Arlott static void bcm2835_gpio_irq_enable(struct irq_data *data)
487e1b2dc70SSimon Arlott {
48885ae9e51SLinus Walleij 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
48985ae9e51SLinus Walleij 	struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
490e1b2dc70SSimon Arlott 	unsigned gpio = irqd_to_hwirq(data);
491e1b2dc70SSimon Arlott 	unsigned offset = GPIO_REG_SHIFT(gpio);
492e1b2dc70SSimon Arlott 	unsigned bank = GPIO_REG_OFFSET(gpio);
493e1b2dc70SSimon Arlott 	unsigned long flags;
494e1b2dc70SSimon Arlott 
4953c7b30f7SLukas Wunner 	raw_spin_lock_irqsave(&pc->irq_lock[bank], flags);
496e1b2dc70SSimon Arlott 	set_bit(offset, &pc->enabled_irq_map[bank]);
497e1b2dc70SSimon Arlott 	bcm2835_gpio_irq_config(pc, gpio, true);
4983c7b30f7SLukas Wunner 	raw_spin_unlock_irqrestore(&pc->irq_lock[bank], flags);
499e1b2dc70SSimon Arlott }
500e1b2dc70SSimon Arlott 
501e1b2dc70SSimon Arlott static void bcm2835_gpio_irq_disable(struct irq_data *data)
502e1b2dc70SSimon Arlott {
50385ae9e51SLinus Walleij 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
50485ae9e51SLinus Walleij 	struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
505e1b2dc70SSimon Arlott 	unsigned gpio = irqd_to_hwirq(data);
506e1b2dc70SSimon Arlott 	unsigned offset = GPIO_REG_SHIFT(gpio);
507e1b2dc70SSimon Arlott 	unsigned bank = GPIO_REG_OFFSET(gpio);
508e1b2dc70SSimon Arlott 	unsigned long flags;
509e1b2dc70SSimon Arlott 
5103c7b30f7SLukas Wunner 	raw_spin_lock_irqsave(&pc->irq_lock[bank], flags);
511e1b2dc70SSimon Arlott 	bcm2835_gpio_irq_config(pc, gpio, false);
512714b1dd8SJonathan Bell 	/* Clear events that were latched prior to clearing event sources */
513714b1dd8SJonathan Bell 	bcm2835_gpio_set_bit(pc, GPEDS0, gpio);
514e1b2dc70SSimon Arlott 	clear_bit(offset, &pc->enabled_irq_map[bank]);
5153c7b30f7SLukas Wunner 	raw_spin_unlock_irqrestore(&pc->irq_lock[bank], flags);
516e1b2dc70SSimon Arlott }
517e1b2dc70SSimon Arlott 
518e1b2dc70SSimon Arlott static int __bcm2835_gpio_irq_set_type_disabled(struct bcm2835_pinctrl *pc,
519e1b2dc70SSimon Arlott 	unsigned offset, unsigned int type)
520e1b2dc70SSimon Arlott {
521e1b2dc70SSimon Arlott 	switch (type) {
522e1b2dc70SSimon Arlott 	case IRQ_TYPE_NONE:
523e1b2dc70SSimon Arlott 	case IRQ_TYPE_EDGE_RISING:
524e1b2dc70SSimon Arlott 	case IRQ_TYPE_EDGE_FALLING:
525e1b2dc70SSimon Arlott 	case IRQ_TYPE_EDGE_BOTH:
526e1b2dc70SSimon Arlott 	case IRQ_TYPE_LEVEL_HIGH:
527e1b2dc70SSimon Arlott 	case IRQ_TYPE_LEVEL_LOW:
528e1b2dc70SSimon Arlott 		pc->irq_type[offset] = type;
529e1b2dc70SSimon Arlott 		break;
530e1b2dc70SSimon Arlott 
531e1b2dc70SSimon Arlott 	default:
532e1b2dc70SSimon Arlott 		return -EINVAL;
533e1b2dc70SSimon Arlott 	}
534e1b2dc70SSimon Arlott 	return 0;
535e1b2dc70SSimon Arlott }
536e1b2dc70SSimon Arlott 
537e1b2dc70SSimon Arlott /* slower path for reconfiguring IRQ type */
538e1b2dc70SSimon Arlott static int __bcm2835_gpio_irq_set_type_enabled(struct bcm2835_pinctrl *pc,
539e1b2dc70SSimon Arlott 	unsigned offset, unsigned int type)
540e1b2dc70SSimon Arlott {
541e1b2dc70SSimon Arlott 	switch (type) {
542e1b2dc70SSimon Arlott 	case IRQ_TYPE_NONE:
543e1b2dc70SSimon Arlott 		if (pc->irq_type[offset] != type) {
544e1b2dc70SSimon Arlott 			bcm2835_gpio_irq_config(pc, offset, false);
545e1b2dc70SSimon Arlott 			pc->irq_type[offset] = type;
546e1b2dc70SSimon Arlott 		}
547e1b2dc70SSimon Arlott 		break;
548e1b2dc70SSimon Arlott 
549e1b2dc70SSimon Arlott 	case IRQ_TYPE_EDGE_RISING:
550e1b2dc70SSimon Arlott 		if (pc->irq_type[offset] == IRQ_TYPE_EDGE_BOTH) {
551e1b2dc70SSimon Arlott 			/* RISING already enabled, disable FALLING */
552e1b2dc70SSimon Arlott 			pc->irq_type[offset] = IRQ_TYPE_EDGE_FALLING;
553e1b2dc70SSimon Arlott 			bcm2835_gpio_irq_config(pc, offset, false);
554e1b2dc70SSimon Arlott 			pc->irq_type[offset] = type;
555e1b2dc70SSimon Arlott 		} else if (pc->irq_type[offset] != type) {
556e1b2dc70SSimon Arlott 			bcm2835_gpio_irq_config(pc, offset, false);
557e1b2dc70SSimon Arlott 			pc->irq_type[offset] = type;
558e1b2dc70SSimon Arlott 			bcm2835_gpio_irq_config(pc, offset, true);
559e1b2dc70SSimon Arlott 		}
560e1b2dc70SSimon Arlott 		break;
561e1b2dc70SSimon Arlott 
562e1b2dc70SSimon Arlott 	case IRQ_TYPE_EDGE_FALLING:
563e1b2dc70SSimon Arlott 		if (pc->irq_type[offset] == IRQ_TYPE_EDGE_BOTH) {
564e1b2dc70SSimon Arlott 			/* FALLING already enabled, disable RISING */
565e1b2dc70SSimon Arlott 			pc->irq_type[offset] = IRQ_TYPE_EDGE_RISING;
566e1b2dc70SSimon Arlott 			bcm2835_gpio_irq_config(pc, offset, false);
567e1b2dc70SSimon Arlott 			pc->irq_type[offset] = type;
568e1b2dc70SSimon Arlott 		} else if (pc->irq_type[offset] != type) {
569e1b2dc70SSimon Arlott 			bcm2835_gpio_irq_config(pc, offset, false);
570e1b2dc70SSimon Arlott 			pc->irq_type[offset] = type;
571e1b2dc70SSimon Arlott 			bcm2835_gpio_irq_config(pc, offset, true);
572e1b2dc70SSimon Arlott 		}
573e1b2dc70SSimon Arlott 		break;
574e1b2dc70SSimon Arlott 
575e1b2dc70SSimon Arlott 	case IRQ_TYPE_EDGE_BOTH:
576e1b2dc70SSimon Arlott 		if (pc->irq_type[offset] == IRQ_TYPE_EDGE_RISING) {
577e1b2dc70SSimon Arlott 			/* RISING already enabled, enable FALLING too */
578e1b2dc70SSimon Arlott 			pc->irq_type[offset] = IRQ_TYPE_EDGE_FALLING;
579e1b2dc70SSimon Arlott 			bcm2835_gpio_irq_config(pc, offset, true);
580e1b2dc70SSimon Arlott 			pc->irq_type[offset] = type;
581e1b2dc70SSimon Arlott 		} else if (pc->irq_type[offset] == IRQ_TYPE_EDGE_FALLING) {
582e1b2dc70SSimon Arlott 			/* FALLING already enabled, enable RISING too */
583e1b2dc70SSimon Arlott 			pc->irq_type[offset] = IRQ_TYPE_EDGE_RISING;
584e1b2dc70SSimon Arlott 			bcm2835_gpio_irq_config(pc, offset, true);
585e1b2dc70SSimon Arlott 			pc->irq_type[offset] = type;
586e1b2dc70SSimon Arlott 		} else if (pc->irq_type[offset] != type) {
587e1b2dc70SSimon Arlott 			bcm2835_gpio_irq_config(pc, offset, false);
588e1b2dc70SSimon Arlott 			pc->irq_type[offset] = type;
589e1b2dc70SSimon Arlott 			bcm2835_gpio_irq_config(pc, offset, true);
590e1b2dc70SSimon Arlott 		}
591e1b2dc70SSimon Arlott 		break;
592e1b2dc70SSimon Arlott 
593e1b2dc70SSimon Arlott 	case IRQ_TYPE_LEVEL_HIGH:
594e1b2dc70SSimon Arlott 	case IRQ_TYPE_LEVEL_LOW:
595e1b2dc70SSimon Arlott 		if (pc->irq_type[offset] != type) {
596e1b2dc70SSimon Arlott 			bcm2835_gpio_irq_config(pc, offset, false);
597e1b2dc70SSimon Arlott 			pc->irq_type[offset] = type;
598e1b2dc70SSimon Arlott 			bcm2835_gpio_irq_config(pc, offset, true);
599e1b2dc70SSimon Arlott 		}
600e1b2dc70SSimon Arlott 		break;
601e1b2dc70SSimon Arlott 
602e1b2dc70SSimon Arlott 	default:
603e1b2dc70SSimon Arlott 		return -EINVAL;
604e1b2dc70SSimon Arlott 	}
605e1b2dc70SSimon Arlott 	return 0;
606e1b2dc70SSimon Arlott }
607e1b2dc70SSimon Arlott 
608e1b2dc70SSimon Arlott static int bcm2835_gpio_irq_set_type(struct irq_data *data, unsigned int type)
609e1b2dc70SSimon Arlott {
61085ae9e51SLinus Walleij 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
61185ae9e51SLinus Walleij 	struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
612e1b2dc70SSimon Arlott 	unsigned gpio = irqd_to_hwirq(data);
613e1b2dc70SSimon Arlott 	unsigned offset = GPIO_REG_SHIFT(gpio);
614e1b2dc70SSimon Arlott 	unsigned bank = GPIO_REG_OFFSET(gpio);
615e1b2dc70SSimon Arlott 	unsigned long flags;
616e1b2dc70SSimon Arlott 	int ret;
617e1b2dc70SSimon Arlott 
6183c7b30f7SLukas Wunner 	raw_spin_lock_irqsave(&pc->irq_lock[bank], flags);
619e1b2dc70SSimon Arlott 
620e1b2dc70SSimon Arlott 	if (test_bit(offset, &pc->enabled_irq_map[bank]))
621e1b2dc70SSimon Arlott 		ret = __bcm2835_gpio_irq_set_type_enabled(pc, gpio, type);
622e1b2dc70SSimon Arlott 	else
623e1b2dc70SSimon Arlott 		ret = __bcm2835_gpio_irq_set_type_disabled(pc, gpio, type);
624e1b2dc70SSimon Arlott 
625b8a19382SCharles Keepax 	if (type & IRQ_TYPE_EDGE_BOTH)
6261aa74fd0SThomas Gleixner 		irq_set_handler_locked(data, handle_edge_irq);
627b8a19382SCharles Keepax 	else
6281aa74fd0SThomas Gleixner 		irq_set_handler_locked(data, handle_level_irq);
629b8a19382SCharles Keepax 
6303c7b30f7SLukas Wunner 	raw_spin_unlock_irqrestore(&pc->irq_lock[bank], flags);
631e1b2dc70SSimon Arlott 
632e1b2dc70SSimon Arlott 	return ret;
633e1b2dc70SSimon Arlott }
634e1b2dc70SSimon Arlott 
635b8a19382SCharles Keepax static void bcm2835_gpio_irq_ack(struct irq_data *data)
636b8a19382SCharles Keepax {
63785ae9e51SLinus Walleij 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
63885ae9e51SLinus Walleij 	struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
639b8a19382SCharles Keepax 	unsigned gpio = irqd_to_hwirq(data);
640b8a19382SCharles Keepax 
641b8a19382SCharles Keepax 	bcm2835_gpio_set_bit(pc, GPEDS0, gpio);
642b8a19382SCharles Keepax }
643b8a19382SCharles Keepax 
644920fecc1SFlorian Fainelli static int bcm2835_gpio_irq_set_wake(struct irq_data *data, unsigned int on)
645920fecc1SFlorian Fainelli {
646920fecc1SFlorian Fainelli 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
647920fecc1SFlorian Fainelli 	struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
648920fecc1SFlorian Fainelli 	unsigned gpio = irqd_to_hwirq(data);
649920fecc1SFlorian Fainelli 	unsigned int irqgroup;
650920fecc1SFlorian Fainelli 	int ret = -EINVAL;
651920fecc1SFlorian Fainelli 
652920fecc1SFlorian Fainelli 	if (!pc->wake_irq)
653920fecc1SFlorian Fainelli 		return ret;
654920fecc1SFlorian Fainelli 
655920fecc1SFlorian Fainelli 	if (gpio <= 27)
656920fecc1SFlorian Fainelli 		irqgroup = 0;
657920fecc1SFlorian Fainelli 	else if (gpio >= 28 && gpio <= 45)
658920fecc1SFlorian Fainelli 		irqgroup = 1;
659920fecc1SFlorian Fainelli 	else if (gpio >= 46 && gpio <= 57)
660920fecc1SFlorian Fainelli 		irqgroup = 2;
661920fecc1SFlorian Fainelli 	else
662920fecc1SFlorian Fainelli 		return ret;
663920fecc1SFlorian Fainelli 
664920fecc1SFlorian Fainelli 	if (on)
665920fecc1SFlorian Fainelli 		ret = enable_irq_wake(pc->wake_irq[irqgroup]);
666920fecc1SFlorian Fainelli 	else
667920fecc1SFlorian Fainelli 		ret = disable_irq_wake(pc->wake_irq[irqgroup]);
668920fecc1SFlorian Fainelli 
669920fecc1SFlorian Fainelli 	return ret;
670920fecc1SFlorian Fainelli }
671920fecc1SFlorian Fainelli 
672e1b2dc70SSimon Arlott static struct irq_chip bcm2835_gpio_irq_chip = {
673e1b2dc70SSimon Arlott 	.name = MODULE_NAME,
674e1b2dc70SSimon Arlott 	.irq_enable = bcm2835_gpio_irq_enable,
675e1b2dc70SSimon Arlott 	.irq_disable = bcm2835_gpio_irq_disable,
676e1b2dc70SSimon Arlott 	.irq_set_type = bcm2835_gpio_irq_set_type,
677b8a19382SCharles Keepax 	.irq_ack = bcm2835_gpio_irq_ack,
678b8a19382SCharles Keepax 	.irq_mask = bcm2835_gpio_irq_disable,
679b8a19382SCharles Keepax 	.irq_unmask = bcm2835_gpio_irq_enable,
680920fecc1SFlorian Fainelli 	.irq_set_wake = bcm2835_gpio_irq_set_wake,
681920fecc1SFlorian Fainelli 	.flags = IRQCHIP_MASK_ON_SUSPEND,
682e1b2dc70SSimon Arlott };
683e1b2dc70SSimon Arlott 
684e1b2dc70SSimon Arlott static int bcm2835_pctl_get_groups_count(struct pinctrl_dev *pctldev)
685e1b2dc70SSimon Arlott {
686b1d84a3dSStefan Wahren 	return BCM2835_NUM_GPIOS;
687e1b2dc70SSimon Arlott }
688e1b2dc70SSimon Arlott 
689e1b2dc70SSimon Arlott static const char *bcm2835_pctl_get_group_name(struct pinctrl_dev *pctldev,
690e1b2dc70SSimon Arlott 		unsigned selector)
691e1b2dc70SSimon Arlott {
692e1b2dc70SSimon Arlott 	return bcm2835_gpio_groups[selector];
693e1b2dc70SSimon Arlott }
694e1b2dc70SSimon Arlott 
695e1b2dc70SSimon Arlott static int bcm2835_pctl_get_group_pins(struct pinctrl_dev *pctldev,
696e1b2dc70SSimon Arlott 		unsigned selector,
697e1b2dc70SSimon Arlott 		const unsigned **pins,
698e1b2dc70SSimon Arlott 		unsigned *num_pins)
699e1b2dc70SSimon Arlott {
700e1b2dc70SSimon Arlott 	*pins = &bcm2835_gpio_pins[selector].number;
701e1b2dc70SSimon Arlott 	*num_pins = 1;
702e1b2dc70SSimon Arlott 
703e1b2dc70SSimon Arlott 	return 0;
704e1b2dc70SSimon Arlott }
705e1b2dc70SSimon Arlott 
706e1b2dc70SSimon Arlott static void bcm2835_pctl_pin_dbg_show(struct pinctrl_dev *pctldev,
707e1b2dc70SSimon Arlott 		struct seq_file *s,
708e1b2dc70SSimon Arlott 		unsigned offset)
709e1b2dc70SSimon Arlott {
710e1b2dc70SSimon Arlott 	struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
71185ae9e51SLinus Walleij 	struct gpio_chip *chip = &pc->gpio_chip;
712e1b2dc70SSimon Arlott 	enum bcm2835_fsel fsel = bcm2835_pinctrl_fsel_get(pc, offset);
713e1b2dc70SSimon Arlott 	const char *fname = bcm2835_functions[fsel];
714e1b2dc70SSimon Arlott 	int value = bcm2835_gpio_get_bit(pc, GPLEV0, offset);
715f0fbe7bcSThierry Reding 	int irq = irq_find_mapping(chip->irq.domain, offset);
716e1b2dc70SSimon Arlott 
717e1b2dc70SSimon Arlott 	seq_printf(s, "function %s in %s; irq %d (%s)",
718e1b2dc70SSimon Arlott 		fname, value ? "hi" : "lo",
719e1b2dc70SSimon Arlott 		irq, irq_type_names[pc->irq_type[offset]]);
720e1b2dc70SSimon Arlott }
721e1b2dc70SSimon Arlott 
722e1b2dc70SSimon Arlott static void bcm2835_pctl_dt_free_map(struct pinctrl_dev *pctldev,
723e1b2dc70SSimon Arlott 		struct pinctrl_map *maps, unsigned num_maps)
724e1b2dc70SSimon Arlott {
725e1b2dc70SSimon Arlott 	int i;
726e1b2dc70SSimon Arlott 
727e1b2dc70SSimon Arlott 	for (i = 0; i < num_maps; i++)
728e1b2dc70SSimon Arlott 		if (maps[i].type == PIN_MAP_TYPE_CONFIGS_PIN)
729e1b2dc70SSimon Arlott 			kfree(maps[i].data.configs.configs);
730e1b2dc70SSimon Arlott 
731e1b2dc70SSimon Arlott 	kfree(maps);
732e1b2dc70SSimon Arlott }
733e1b2dc70SSimon Arlott 
734e1b2dc70SSimon Arlott static int bcm2835_pctl_dt_node_to_map_func(struct bcm2835_pinctrl *pc,
735e1b2dc70SSimon Arlott 		struct device_node *np, u32 pin, u32 fnum,
736e1b2dc70SSimon Arlott 		struct pinctrl_map **maps)
737e1b2dc70SSimon Arlott {
738e1b2dc70SSimon Arlott 	struct pinctrl_map *map = *maps;
739e1b2dc70SSimon Arlott 
740e1b2dc70SSimon Arlott 	if (fnum >= ARRAY_SIZE(bcm2835_functions)) {
741f5292d06SRob Herring 		dev_err(pc->dev, "%pOF: invalid brcm,function %d\n", np, fnum);
742e1b2dc70SSimon Arlott 		return -EINVAL;
743e1b2dc70SSimon Arlott 	}
744e1b2dc70SSimon Arlott 
745e1b2dc70SSimon Arlott 	map->type = PIN_MAP_TYPE_MUX_GROUP;
746e1b2dc70SSimon Arlott 	map->data.mux.group = bcm2835_gpio_groups[pin];
747e1b2dc70SSimon Arlott 	map->data.mux.function = bcm2835_functions[fnum];
748e1b2dc70SSimon Arlott 	(*maps)++;
749e1b2dc70SSimon Arlott 
750e1b2dc70SSimon Arlott 	return 0;
751e1b2dc70SSimon Arlott }
752e1b2dc70SSimon Arlott 
753e1b2dc70SSimon Arlott static int bcm2835_pctl_dt_node_to_map_pull(struct bcm2835_pinctrl *pc,
754e1b2dc70SSimon Arlott 		struct device_node *np, u32 pin, u32 pull,
755e1b2dc70SSimon Arlott 		struct pinctrl_map **maps)
756e1b2dc70SSimon Arlott {
757e1b2dc70SSimon Arlott 	struct pinctrl_map *map = *maps;
758e1b2dc70SSimon Arlott 	unsigned long *configs;
759e1b2dc70SSimon Arlott 
760e1b2dc70SSimon Arlott 	if (pull > 2) {
761f5292d06SRob Herring 		dev_err(pc->dev, "%pOF: invalid brcm,pull %d\n", np, pull);
762e1b2dc70SSimon Arlott 		return -EINVAL;
763e1b2dc70SSimon Arlott 	}
764e1b2dc70SSimon Arlott 
765e1b2dc70SSimon Arlott 	configs = kzalloc(sizeof(*configs), GFP_KERNEL);
766e1b2dc70SSimon Arlott 	if (!configs)
767e1b2dc70SSimon Arlott 		return -ENOMEM;
7680de70495SMatheus Castello 	configs[0] = pinconf_to_config_packed(BCM2835_PINCONF_PARAM_PULL, pull);
769e1b2dc70SSimon Arlott 
770e1b2dc70SSimon Arlott 	map->type = PIN_MAP_TYPE_CONFIGS_PIN;
771e1b2dc70SSimon Arlott 	map->data.configs.group_or_pin = bcm2835_gpio_pins[pin].name;
772e1b2dc70SSimon Arlott 	map->data.configs.configs = configs;
773e1b2dc70SSimon Arlott 	map->data.configs.num_configs = 1;
774e1b2dc70SSimon Arlott 	(*maps)++;
775e1b2dc70SSimon Arlott 
776e1b2dc70SSimon Arlott 	return 0;
777e1b2dc70SSimon Arlott }
778e1b2dc70SSimon Arlott 
779e1b2dc70SSimon Arlott static int bcm2835_pctl_dt_node_to_map(struct pinctrl_dev *pctldev,
780e1b2dc70SSimon Arlott 		struct device_node *np,
7810de70495SMatheus Castello 		struct pinctrl_map **map, unsigned int *num_maps)
782e1b2dc70SSimon Arlott {
783e1b2dc70SSimon Arlott 	struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
784e1b2dc70SSimon Arlott 	struct property *pins, *funcs, *pulls;
785e1b2dc70SSimon Arlott 	int num_pins, num_funcs, num_pulls, maps_per_pin;
786e1b2dc70SSimon Arlott 	struct pinctrl_map *maps, *cur_map;
787e1b2dc70SSimon Arlott 	int i, err;
788e1b2dc70SSimon Arlott 	u32 pin, func, pull;
789e1b2dc70SSimon Arlott 
7900de70495SMatheus Castello 	/* Check for generic binding in this node */
7910de70495SMatheus Castello 	err = pinconf_generic_dt_node_to_map_all(pctldev, np, map, num_maps);
7920de70495SMatheus Castello 	if (err || *num_maps)
7930de70495SMatheus Castello 		return err;
7940de70495SMatheus Castello 
7950de70495SMatheus Castello 	/* Generic binding did not find anything continue with legacy parse */
796e1b2dc70SSimon Arlott 	pins = of_find_property(np, "brcm,pins", NULL);
797e1b2dc70SSimon Arlott 	if (!pins) {
798f5292d06SRob Herring 		dev_err(pc->dev, "%pOF: missing brcm,pins property\n", np);
799e1b2dc70SSimon Arlott 		return -EINVAL;
800e1b2dc70SSimon Arlott 	}
801e1b2dc70SSimon Arlott 
802e1b2dc70SSimon Arlott 	funcs = of_find_property(np, "brcm,function", NULL);
803e1b2dc70SSimon Arlott 	pulls = of_find_property(np, "brcm,pull", NULL);
804e1b2dc70SSimon Arlott 
805e1b2dc70SSimon Arlott 	if (!funcs && !pulls) {
806e1b2dc70SSimon Arlott 		dev_err(pc->dev,
807f5292d06SRob Herring 			"%pOF: neither brcm,function nor brcm,pull specified\n",
808f5292d06SRob Herring 			np);
809e1b2dc70SSimon Arlott 		return -EINVAL;
810e1b2dc70SSimon Arlott 	}
811e1b2dc70SSimon Arlott 
812e1b2dc70SSimon Arlott 	num_pins = pins->length / 4;
813e1b2dc70SSimon Arlott 	num_funcs = funcs ? (funcs->length / 4) : 0;
814e1b2dc70SSimon Arlott 	num_pulls = pulls ? (pulls->length / 4) : 0;
815e1b2dc70SSimon Arlott 
816e1b2dc70SSimon Arlott 	if (num_funcs > 1 && num_funcs != num_pins) {
817e1b2dc70SSimon Arlott 		dev_err(pc->dev,
818f5292d06SRob Herring 			"%pOF: brcm,function must have 1 or %d entries\n",
819f5292d06SRob Herring 			np, num_pins);
820e1b2dc70SSimon Arlott 		return -EINVAL;
821e1b2dc70SSimon Arlott 	}
822e1b2dc70SSimon Arlott 
823e1b2dc70SSimon Arlott 	if (num_pulls > 1 && num_pulls != num_pins) {
824e1b2dc70SSimon Arlott 		dev_err(pc->dev,
825f5292d06SRob Herring 			"%pOF: brcm,pull must have 1 or %d entries\n",
826f5292d06SRob Herring 			np, num_pins);
827e1b2dc70SSimon Arlott 		return -EINVAL;
828e1b2dc70SSimon Arlott 	}
829e1b2dc70SSimon Arlott 
830e1b2dc70SSimon Arlott 	maps_per_pin = 0;
831e1b2dc70SSimon Arlott 	if (num_funcs)
832e1b2dc70SSimon Arlott 		maps_per_pin++;
833e1b2dc70SSimon Arlott 	if (num_pulls)
834e1b2dc70SSimon Arlott 		maps_per_pin++;
8356396bb22SKees Cook 	cur_map = maps = kcalloc(num_pins * maps_per_pin, sizeof(*maps),
836e1b2dc70SSimon Arlott 				 GFP_KERNEL);
837e1b2dc70SSimon Arlott 	if (!maps)
838e1b2dc70SSimon Arlott 		return -ENOMEM;
839e1b2dc70SSimon Arlott 
840e1b2dc70SSimon Arlott 	for (i = 0; i < num_pins; i++) {
841ce63d6d4SStephen Warren 		err = of_property_read_u32_index(np, "brcm,pins", i, &pin);
842ce63d6d4SStephen Warren 		if (err)
843ce63d6d4SStephen Warren 			goto out;
844b1d84a3dSStefan Wahren 		if (pin >= pc->pctl_desc.npins) {
845f5292d06SRob Herring 			dev_err(pc->dev, "%pOF: invalid brcm,pins value %d\n",
846f5292d06SRob Herring 				np, pin);
847e1b2dc70SSimon Arlott 			err = -EINVAL;
848e1b2dc70SSimon Arlott 			goto out;
849e1b2dc70SSimon Arlott 		}
850e1b2dc70SSimon Arlott 
851e1b2dc70SSimon Arlott 		if (num_funcs) {
852ce63d6d4SStephen Warren 			err = of_property_read_u32_index(np, "brcm,function",
853ce63d6d4SStephen Warren 					(num_funcs > 1) ? i : 0, &func);
854ce63d6d4SStephen Warren 			if (err)
855ce63d6d4SStephen Warren 				goto out;
856e1b2dc70SSimon Arlott 			err = bcm2835_pctl_dt_node_to_map_func(pc, np, pin,
857e1b2dc70SSimon Arlott 							func, &cur_map);
858e1b2dc70SSimon Arlott 			if (err)
859e1b2dc70SSimon Arlott 				goto out;
860e1b2dc70SSimon Arlott 		}
861e1b2dc70SSimon Arlott 		if (num_pulls) {
862ce63d6d4SStephen Warren 			err = of_property_read_u32_index(np, "brcm,pull",
8632c7e3306SPhil Elwell 					(num_pulls > 1) ? i : 0, &pull);
864ce63d6d4SStephen Warren 			if (err)
865ce63d6d4SStephen Warren 				goto out;
866e1b2dc70SSimon Arlott 			err = bcm2835_pctl_dt_node_to_map_pull(pc, np, pin,
867e1b2dc70SSimon Arlott 							pull, &cur_map);
868e1b2dc70SSimon Arlott 			if (err)
869e1b2dc70SSimon Arlott 				goto out;
870e1b2dc70SSimon Arlott 		}
871e1b2dc70SSimon Arlott 	}
872e1b2dc70SSimon Arlott 
873e1b2dc70SSimon Arlott 	*map = maps;
874e1b2dc70SSimon Arlott 	*num_maps = num_pins * maps_per_pin;
875e1b2dc70SSimon Arlott 
876e1b2dc70SSimon Arlott 	return 0;
877e1b2dc70SSimon Arlott 
878e1b2dc70SSimon Arlott out:
87953653c6bSStefan Wahren 	bcm2835_pctl_dt_free_map(pctldev, maps, num_pins * maps_per_pin);
880e1b2dc70SSimon Arlott 	return err;
881e1b2dc70SSimon Arlott }
882e1b2dc70SSimon Arlott 
883022ab148SLaurent Pinchart static const struct pinctrl_ops bcm2835_pctl_ops = {
884e1b2dc70SSimon Arlott 	.get_groups_count = bcm2835_pctl_get_groups_count,
885e1b2dc70SSimon Arlott 	.get_group_name = bcm2835_pctl_get_group_name,
886e1b2dc70SSimon Arlott 	.get_group_pins = bcm2835_pctl_get_group_pins,
887e1b2dc70SSimon Arlott 	.pin_dbg_show = bcm2835_pctl_pin_dbg_show,
888e1b2dc70SSimon Arlott 	.dt_node_to_map = bcm2835_pctl_dt_node_to_map,
889e1b2dc70SSimon Arlott 	.dt_free_map = bcm2835_pctl_dt_free_map,
890e1b2dc70SSimon Arlott };
891e1b2dc70SSimon Arlott 
892ccca1ad5SPhil Elwell static int bcm2835_pmx_free(struct pinctrl_dev *pctldev,
893ccca1ad5SPhil Elwell 		unsigned offset)
894ccca1ad5SPhil Elwell {
895ccca1ad5SPhil Elwell 	struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
896ccca1ad5SPhil Elwell 
897ccca1ad5SPhil Elwell 	/* disable by setting to GPIO_IN */
898ccca1ad5SPhil Elwell 	bcm2835_pinctrl_fsel_set(pc, offset, BCM2835_FSEL_GPIO_IN);
899ccca1ad5SPhil Elwell 	return 0;
900ccca1ad5SPhil Elwell }
901ccca1ad5SPhil Elwell 
902e1b2dc70SSimon Arlott static int bcm2835_pmx_get_functions_count(struct pinctrl_dev *pctldev)
903e1b2dc70SSimon Arlott {
904e1b2dc70SSimon Arlott 	return BCM2835_FSEL_COUNT;
905e1b2dc70SSimon Arlott }
906e1b2dc70SSimon Arlott 
907e1b2dc70SSimon Arlott static const char *bcm2835_pmx_get_function_name(struct pinctrl_dev *pctldev,
908e1b2dc70SSimon Arlott 		unsigned selector)
909e1b2dc70SSimon Arlott {
910e1b2dc70SSimon Arlott 	return bcm2835_functions[selector];
911e1b2dc70SSimon Arlott }
912e1b2dc70SSimon Arlott 
913e1b2dc70SSimon Arlott static int bcm2835_pmx_get_function_groups(struct pinctrl_dev *pctldev,
914e1b2dc70SSimon Arlott 		unsigned selector,
915e1b2dc70SSimon Arlott 		const char * const **groups,
916e1b2dc70SSimon Arlott 		unsigned * const num_groups)
917e1b2dc70SSimon Arlott {
918e1b2dc70SSimon Arlott 	/* every pin can do every function */
919e1b2dc70SSimon Arlott 	*groups = bcm2835_gpio_groups;
920b1d84a3dSStefan Wahren 	*num_groups = BCM2835_NUM_GPIOS;
921e1b2dc70SSimon Arlott 
922e1b2dc70SSimon Arlott 	return 0;
923e1b2dc70SSimon Arlott }
924e1b2dc70SSimon Arlott 
92503e9f0caSLinus Walleij static int bcm2835_pmx_set(struct pinctrl_dev *pctldev,
926e1b2dc70SSimon Arlott 		unsigned func_selector,
927e1b2dc70SSimon Arlott 		unsigned group_selector)
928e1b2dc70SSimon Arlott {
929e1b2dc70SSimon Arlott 	struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
930e1b2dc70SSimon Arlott 
931e1b2dc70SSimon Arlott 	bcm2835_pinctrl_fsel_set(pc, group_selector, func_selector);
932e1b2dc70SSimon Arlott 
933e1b2dc70SSimon Arlott 	return 0;
934e1b2dc70SSimon Arlott }
935e1b2dc70SSimon Arlott 
936e1b2dc70SSimon Arlott static void bcm2835_pmx_gpio_disable_free(struct pinctrl_dev *pctldev,
937e1b2dc70SSimon Arlott 		struct pinctrl_gpio_range *range,
938e1b2dc70SSimon Arlott 		unsigned offset)
939e1b2dc70SSimon Arlott {
940e1b2dc70SSimon Arlott 	struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
941e1b2dc70SSimon Arlott 
942e1b2dc70SSimon Arlott 	/* disable by setting to GPIO_IN */
943e1b2dc70SSimon Arlott 	bcm2835_pinctrl_fsel_set(pc, offset, BCM2835_FSEL_GPIO_IN);
944e1b2dc70SSimon Arlott }
945e1b2dc70SSimon Arlott 
946e1b2dc70SSimon Arlott static int bcm2835_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
947e1b2dc70SSimon Arlott 		struct pinctrl_gpio_range *range,
948e1b2dc70SSimon Arlott 		unsigned offset,
949e1b2dc70SSimon Arlott 		bool input)
950e1b2dc70SSimon Arlott {
951e1b2dc70SSimon Arlott 	struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
952e1b2dc70SSimon Arlott 	enum bcm2835_fsel fsel = input ?
953e1b2dc70SSimon Arlott 		BCM2835_FSEL_GPIO_IN : BCM2835_FSEL_GPIO_OUT;
954e1b2dc70SSimon Arlott 
955e1b2dc70SSimon Arlott 	bcm2835_pinctrl_fsel_set(pc, offset, fsel);
956e1b2dc70SSimon Arlott 
957e1b2dc70SSimon Arlott 	return 0;
958e1b2dc70SSimon Arlott }
959e1b2dc70SSimon Arlott 
960022ab148SLaurent Pinchart static const struct pinmux_ops bcm2835_pmx_ops = {
961ccca1ad5SPhil Elwell 	.free = bcm2835_pmx_free,
962e1b2dc70SSimon Arlott 	.get_functions_count = bcm2835_pmx_get_functions_count,
963e1b2dc70SSimon Arlott 	.get_function_name = bcm2835_pmx_get_function_name,
964e1b2dc70SSimon Arlott 	.get_function_groups = bcm2835_pmx_get_function_groups,
96503e9f0caSLinus Walleij 	.set_mux = bcm2835_pmx_set,
966e1b2dc70SSimon Arlott 	.gpio_disable_free = bcm2835_pmx_gpio_disable_free,
967e1b2dc70SSimon Arlott 	.gpio_set_direction = bcm2835_pmx_gpio_set_direction,
968e1b2dc70SSimon Arlott };
969e1b2dc70SSimon Arlott 
970e1b2dc70SSimon Arlott static int bcm2835_pinconf_get(struct pinctrl_dev *pctldev,
971e1b2dc70SSimon Arlott 			unsigned pin, unsigned long *config)
972e1b2dc70SSimon Arlott {
973e1b2dc70SSimon Arlott 	/* No way to read back config in HW */
974e1b2dc70SSimon Arlott 	return -ENOTSUPP;
975e1b2dc70SSimon Arlott }
976e1b2dc70SSimon Arlott 
9770de70495SMatheus Castello static void bcm2835_pull_config_set(struct bcm2835_pinctrl *pc,
9780de70495SMatheus Castello 		unsigned int pin, unsigned int arg)
979e1b2dc70SSimon Arlott {
980e1b2dc70SSimon Arlott 	u32 off, bit;
981e1b2dc70SSimon Arlott 
982e1b2dc70SSimon Arlott 	off = GPIO_REG_OFFSET(pin);
983e1b2dc70SSimon Arlott 	bit = GPIO_REG_SHIFT(pin);
984e1b2dc70SSimon Arlott 
985e1b2dc70SSimon Arlott 	bcm2835_gpio_wr(pc, GPPUD, arg & 3);
986e1b2dc70SSimon Arlott 	/*
987b83bd893SStefan Wahren 	 * BCM2835 datasheet say to wait 150 cycles, but not of what.
988b83bd893SStefan Wahren 	 * But the VideoCore firmware delay for this operation
989b83bd893SStefan Wahren 	 * based nearly on the same amount of VPU cycles and this clock
990b83bd893SStefan Wahren 	 * runs at 250 MHz.
991e1b2dc70SSimon Arlott 	 */
992b83bd893SStefan Wahren 	udelay(1);
993e1b2dc70SSimon Arlott 	bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), BIT(bit));
994b83bd893SStefan Wahren 	udelay(1);
995e1b2dc70SSimon Arlott 	bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), 0);
9960de70495SMatheus Castello }
9970de70495SMatheus Castello 
9980de70495SMatheus Castello static int bcm2835_pinconf_set(struct pinctrl_dev *pctldev,
9990de70495SMatheus Castello 			unsigned int pin, unsigned long *configs,
10000de70495SMatheus Castello 			unsigned int num_configs)
10010de70495SMatheus Castello {
10020de70495SMatheus Castello 	struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
10030de70495SMatheus Castello 	u32 param, arg;
10040de70495SMatheus Castello 	int i;
10050de70495SMatheus Castello 
10060de70495SMatheus Castello 	for (i = 0; i < num_configs; i++) {
10070de70495SMatheus Castello 		param = pinconf_to_config_param(configs[i]);
10080de70495SMatheus Castello 		arg = pinconf_to_config_argument(configs[i]);
10090de70495SMatheus Castello 
10100de70495SMatheus Castello 		switch (param) {
10110de70495SMatheus Castello 		/* Set legacy brcm,pull */
10120de70495SMatheus Castello 		case BCM2835_PINCONF_PARAM_PULL:
10130de70495SMatheus Castello 			bcm2835_pull_config_set(pc, pin, arg);
10140de70495SMatheus Castello 			break;
10150de70495SMatheus Castello 
10160de70495SMatheus Castello 		/* Set pull generic bindings */
10170de70495SMatheus Castello 		case PIN_CONFIG_BIAS_DISABLE:
10180de70495SMatheus Castello 			bcm2835_pull_config_set(pc, pin, BCM2835_PUD_OFF);
10190de70495SMatheus Castello 			break;
10200de70495SMatheus Castello 
10210de70495SMatheus Castello 		case PIN_CONFIG_BIAS_PULL_DOWN:
10220de70495SMatheus Castello 			bcm2835_pull_config_set(pc, pin, BCM2835_PUD_DOWN);
10230de70495SMatheus Castello 			break;
10240de70495SMatheus Castello 
10250de70495SMatheus Castello 		case PIN_CONFIG_BIAS_PULL_UP:
10260de70495SMatheus Castello 			bcm2835_pull_config_set(pc, pin, BCM2835_PUD_UP);
10270de70495SMatheus Castello 			break;
10280de70495SMatheus Castello 
102990b60552SMatheus Castello 		/* Set output-high or output-low */
103090b60552SMatheus Castello 		case PIN_CONFIG_OUTPUT:
103190b60552SMatheus Castello 			bcm2835_gpio_set_bit(pc, arg ? GPSET0 : GPCLR0, pin);
103290b60552SMatheus Castello 			break;
103390b60552SMatheus Castello 
10340de70495SMatheus Castello 		default:
1035b6e5531cSStefan Wahren 			return -ENOTSUPP;
10360de70495SMatheus Castello 
10370de70495SMatheus Castello 		} /* switch param type */
103803b054e9SSherman Yin 	} /* for each config */
1039e1b2dc70SSimon Arlott 
1040e1b2dc70SSimon Arlott 	return 0;
1041e1b2dc70SSimon Arlott }
1042e1b2dc70SSimon Arlott 
1043022ab148SLaurent Pinchart static const struct pinconf_ops bcm2835_pinconf_ops = {
10441cb66f08SStefan Wahren 	.is_generic = true,
1045e1b2dc70SSimon Arlott 	.pin_config_get = bcm2835_pinconf_get,
1046e1b2dc70SSimon Arlott 	.pin_config_set = bcm2835_pinconf_set,
1047e1b2dc70SSimon Arlott };
1048e1b2dc70SSimon Arlott 
1049e38a9a43SStefan Wahren static void bcm2711_pull_config_set(struct bcm2835_pinctrl *pc,
1050e38a9a43SStefan Wahren 				    unsigned int pin, unsigned int arg)
1051e38a9a43SStefan Wahren {
1052e38a9a43SStefan Wahren 	u32 shifter;
1053e38a9a43SStefan Wahren 	u32 value;
1054e38a9a43SStefan Wahren 	u32 off;
1055e38a9a43SStefan Wahren 
1056e38a9a43SStefan Wahren 	off = PUD_2711_REG_OFFSET(pin);
1057e38a9a43SStefan Wahren 	shifter = PUD_2711_REG_SHIFT(pin);
1058e38a9a43SStefan Wahren 
1059e38a9a43SStefan Wahren 	value = bcm2835_gpio_rd(pc, GP_GPIO_PUP_PDN_CNTRL_REG0 + (off * 4));
1060e38a9a43SStefan Wahren 	value &= ~(PUD_2711_MASK << shifter);
1061e38a9a43SStefan Wahren 	value |= (arg << shifter);
1062e38a9a43SStefan Wahren 	bcm2835_gpio_wr(pc, GP_GPIO_PUP_PDN_CNTRL_REG0 + (off * 4), value);
1063e38a9a43SStefan Wahren }
1064e38a9a43SStefan Wahren 
1065e38a9a43SStefan Wahren static int bcm2711_pinconf_set(struct pinctrl_dev *pctldev,
1066e38a9a43SStefan Wahren 			       unsigned int pin, unsigned long *configs,
1067e38a9a43SStefan Wahren 			       unsigned int num_configs)
1068e38a9a43SStefan Wahren {
1069e38a9a43SStefan Wahren 	struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
1070e38a9a43SStefan Wahren 	u32 param, arg;
1071e38a9a43SStefan Wahren 	int i;
1072e38a9a43SStefan Wahren 
1073e38a9a43SStefan Wahren 	for (i = 0; i < num_configs; i++) {
1074e38a9a43SStefan Wahren 		param = pinconf_to_config_param(configs[i]);
1075e38a9a43SStefan Wahren 		arg = pinconf_to_config_argument(configs[i]);
1076e38a9a43SStefan Wahren 
1077e38a9a43SStefan Wahren 		switch (param) {
1078e38a9a43SStefan Wahren 		/* convert legacy brcm,pull */
1079e38a9a43SStefan Wahren 		case BCM2835_PINCONF_PARAM_PULL:
1080e38a9a43SStefan Wahren 			if (arg == BCM2835_PUD_UP)
1081e38a9a43SStefan Wahren 				arg = BCM2711_PULL_UP;
1082e38a9a43SStefan Wahren 			else if (arg == BCM2835_PUD_DOWN)
1083e38a9a43SStefan Wahren 				arg = BCM2711_PULL_DOWN;
1084e38a9a43SStefan Wahren 			else
1085e38a9a43SStefan Wahren 				arg = BCM2711_PULL_NONE;
1086e38a9a43SStefan Wahren 
1087e38a9a43SStefan Wahren 			bcm2711_pull_config_set(pc, pin, arg);
1088e38a9a43SStefan Wahren 			break;
1089e38a9a43SStefan Wahren 
1090e38a9a43SStefan Wahren 		/* Set pull generic bindings */
1091e38a9a43SStefan Wahren 		case PIN_CONFIG_BIAS_DISABLE:
1092e38a9a43SStefan Wahren 			bcm2711_pull_config_set(pc, pin, BCM2711_PULL_NONE);
1093e38a9a43SStefan Wahren 			break;
1094e38a9a43SStefan Wahren 		case PIN_CONFIG_BIAS_PULL_DOWN:
1095e38a9a43SStefan Wahren 			bcm2711_pull_config_set(pc, pin, BCM2711_PULL_DOWN);
1096e38a9a43SStefan Wahren 			break;
1097e38a9a43SStefan Wahren 		case PIN_CONFIG_BIAS_PULL_UP:
1098e38a9a43SStefan Wahren 			bcm2711_pull_config_set(pc, pin, BCM2711_PULL_UP);
1099e38a9a43SStefan Wahren 			break;
1100e38a9a43SStefan Wahren 
1101e38a9a43SStefan Wahren 		/* Set output-high or output-low */
1102e38a9a43SStefan Wahren 		case PIN_CONFIG_OUTPUT:
1103e38a9a43SStefan Wahren 			bcm2835_gpio_set_bit(pc, arg ? GPSET0 : GPCLR0, pin);
1104e38a9a43SStefan Wahren 			break;
1105e38a9a43SStefan Wahren 
1106e38a9a43SStefan Wahren 		default:
1107e38a9a43SStefan Wahren 			return -ENOTSUPP;
1108e38a9a43SStefan Wahren 		}
1109e38a9a43SStefan Wahren 	} /* for each config */
1110e38a9a43SStefan Wahren 
1111e38a9a43SStefan Wahren 	return 0;
1112e38a9a43SStefan Wahren }
1113e38a9a43SStefan Wahren 
1114e38a9a43SStefan Wahren static const struct pinconf_ops bcm2711_pinconf_ops = {
1115e38a9a43SStefan Wahren 	.is_generic = true,
1116e38a9a43SStefan Wahren 	.pin_config_get = bcm2835_pinconf_get,
1117e38a9a43SStefan Wahren 	.pin_config_set = bcm2711_pinconf_set,
1118e38a9a43SStefan Wahren };
1119e38a9a43SStefan Wahren 
112090bfaf02SStefan Wahren static const struct pinctrl_desc bcm2835_pinctrl_desc = {
1121e1b2dc70SSimon Arlott 	.name = MODULE_NAME,
1122e1b2dc70SSimon Arlott 	.pins = bcm2835_gpio_pins,
1123b1d84a3dSStefan Wahren 	.npins = BCM2835_NUM_GPIOS,
1124e1b2dc70SSimon Arlott 	.pctlops = &bcm2835_pctl_ops,
1125e1b2dc70SSimon Arlott 	.pmxops = &bcm2835_pmx_ops,
1126e1b2dc70SSimon Arlott 	.confops = &bcm2835_pinconf_ops,
1127e1b2dc70SSimon Arlott 	.owner = THIS_MODULE,
1128e1b2dc70SSimon Arlott };
1129e1b2dc70SSimon Arlott 
113090bfaf02SStefan Wahren static const struct pinctrl_desc bcm2711_pinctrl_desc = {
1131b1d84a3dSStefan Wahren 	.name = "pinctrl-bcm2711",
113290bfaf02SStefan Wahren 	.pins = bcm2835_gpio_pins,
1133b1d84a3dSStefan Wahren 	.npins = BCM2711_NUM_GPIOS,
113490bfaf02SStefan Wahren 	.pctlops = &bcm2835_pctl_ops,
113590bfaf02SStefan Wahren 	.pmxops = &bcm2835_pmx_ops,
113690bfaf02SStefan Wahren 	.confops = &bcm2711_pinconf_ops,
113790bfaf02SStefan Wahren 	.owner = THIS_MODULE,
113890bfaf02SStefan Wahren };
113990bfaf02SStefan Wahren 
114090bfaf02SStefan Wahren static const struct pinctrl_gpio_range bcm2835_pinctrl_gpio_range = {
1141e1b2dc70SSimon Arlott 	.name = MODULE_NAME,
1142e1b2dc70SSimon Arlott 	.npins = BCM2835_NUM_GPIOS,
1143e1b2dc70SSimon Arlott };
1144e1b2dc70SSimon Arlott 
1145b1d84a3dSStefan Wahren static const struct pinctrl_gpio_range bcm2711_pinctrl_gpio_range = {
1146b1d84a3dSStefan Wahren 	.name = "pinctrl-bcm2711",
1147b1d84a3dSStefan Wahren 	.npins = BCM2711_NUM_GPIOS,
1148b1d84a3dSStefan Wahren };
1149b1d84a3dSStefan Wahren 
115090bfaf02SStefan Wahren struct bcm_plat_data {
115190bfaf02SStefan Wahren 	const struct gpio_chip *gpio_chip;
115290bfaf02SStefan Wahren 	const struct pinctrl_desc *pctl_desc;
115390bfaf02SStefan Wahren 	const struct pinctrl_gpio_range *gpio_range;
115490bfaf02SStefan Wahren };
115590bfaf02SStefan Wahren 
115690bfaf02SStefan Wahren static const struct bcm_plat_data bcm2835_plat_data = {
115790bfaf02SStefan Wahren 	.gpio_chip = &bcm2835_gpio_chip,
115890bfaf02SStefan Wahren 	.pctl_desc = &bcm2835_pinctrl_desc,
115990bfaf02SStefan Wahren 	.gpio_range = &bcm2835_pinctrl_gpio_range,
116090bfaf02SStefan Wahren };
116190bfaf02SStefan Wahren 
116290bfaf02SStefan Wahren static const struct bcm_plat_data bcm2711_plat_data = {
1163b1d84a3dSStefan Wahren 	.gpio_chip = &bcm2711_gpio_chip,
116490bfaf02SStefan Wahren 	.pctl_desc = &bcm2711_pinctrl_desc,
1165b1d84a3dSStefan Wahren 	.gpio_range = &bcm2711_pinctrl_gpio_range,
116690bfaf02SStefan Wahren };
116790bfaf02SStefan Wahren 
1168e38a9a43SStefan Wahren static const struct of_device_id bcm2835_pinctrl_match[] = {
1169e38a9a43SStefan Wahren 	{
1170e38a9a43SStefan Wahren 		.compatible = "brcm,bcm2835-gpio",
117190bfaf02SStefan Wahren 		.data = &bcm2835_plat_data,
1172e38a9a43SStefan Wahren 	},
1173e38a9a43SStefan Wahren 	{
1174e38a9a43SStefan Wahren 		.compatible = "brcm,bcm2711-gpio",
117590bfaf02SStefan Wahren 		.data = &bcm2711_plat_data,
1176e38a9a43SStefan Wahren 	},
1177562c856fSFlorian Fainelli 	{
1178562c856fSFlorian Fainelli 		.compatible = "brcm,bcm7211-gpio",
1179562c856fSFlorian Fainelli 		.data = &bcm2711_plat_data,
1180562c856fSFlorian Fainelli 	},
1181e38a9a43SStefan Wahren 	{}
1182e38a9a43SStefan Wahren };
1183e38a9a43SStefan Wahren 
1184150632b0SGreg Kroah-Hartman static int bcm2835_pinctrl_probe(struct platform_device *pdev)
1185e1b2dc70SSimon Arlott {
1186e1b2dc70SSimon Arlott 	struct device *dev = &pdev->dev;
1187e1b2dc70SSimon Arlott 	struct device_node *np = dev->of_node;
118890bfaf02SStefan Wahren 	const struct bcm_plat_data *pdata;
1189e1b2dc70SSimon Arlott 	struct bcm2835_pinctrl *pc;
119073345a18SLinus Walleij 	struct gpio_irq_chip *girq;
1191e1b2dc70SSimon Arlott 	struct resource iomem;
1192e1b2dc70SSimon Arlott 	int err, i;
1193e38a9a43SStefan Wahren 	const struct of_device_id *match;
1194920fecc1SFlorian Fainelli 	int is_7211 = 0;
1195e38a9a43SStefan Wahren 
1196b1d84a3dSStefan Wahren 	BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_pins) != BCM2711_NUM_GPIOS);
1197b1d84a3dSStefan Wahren 	BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_groups) != BCM2711_NUM_GPIOS);
1198e1b2dc70SSimon Arlott 
1199e1b2dc70SSimon Arlott 	pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL);
1200e1b2dc70SSimon Arlott 	if (!pc)
1201e1b2dc70SSimon Arlott 		return -ENOMEM;
1202e1b2dc70SSimon Arlott 
1203e1b2dc70SSimon Arlott 	platform_set_drvdata(pdev, pc);
1204e1b2dc70SSimon Arlott 	pc->dev = dev;
1205e1b2dc70SSimon Arlott 
1206e1b2dc70SSimon Arlott 	err = of_address_to_resource(np, 0, &iomem);
1207e1b2dc70SSimon Arlott 	if (err) {
1208e1b2dc70SSimon Arlott 		dev_err(dev, "could not get IO memory\n");
1209e1b2dc70SSimon Arlott 		return err;
1210e1b2dc70SSimon Arlott 	}
1211e1b2dc70SSimon Arlott 
12129e0c1fb2SThierry Reding 	pc->base = devm_ioremap_resource(dev, &iomem);
12139e0c1fb2SThierry Reding 	if (IS_ERR(pc->base))
12149e0c1fb2SThierry Reding 		return PTR_ERR(pc->base);
1215e1b2dc70SSimon Arlott 
121690bfaf02SStefan Wahren 	match = of_match_node(bcm2835_pinctrl_match, pdev->dev.of_node);
121790bfaf02SStefan Wahren 	if (!match)
121890bfaf02SStefan Wahren 		return -EINVAL;
121990bfaf02SStefan Wahren 
122090bfaf02SStefan Wahren 	pdata = match->data;
1221920fecc1SFlorian Fainelli 	is_7211 = of_device_is_compatible(np, "brcm,bcm7211-gpio");
122290bfaf02SStefan Wahren 
122390bfaf02SStefan Wahren 	pc->gpio_chip = *pdata->gpio_chip;
122458383c78SLinus Walleij 	pc->gpio_chip.parent = dev;
1225e1b2dc70SSimon Arlott 	pc->gpio_chip.of_node = np;
1226e1b2dc70SSimon Arlott 
1227e1b2dc70SSimon Arlott 	for (i = 0; i < BCM2835_NUM_BANKS; i++) {
1228e1b2dc70SSimon Arlott 		unsigned long events;
1229e1b2dc70SSimon Arlott 		unsigned offset;
1230e1b2dc70SSimon Arlott 
1231e1b2dc70SSimon Arlott 		/* clear event detection flags */
1232e1b2dc70SSimon Arlott 		bcm2835_gpio_wr(pc, GPREN0 + i * 4, 0);
1233e1b2dc70SSimon Arlott 		bcm2835_gpio_wr(pc, GPFEN0 + i * 4, 0);
1234e1b2dc70SSimon Arlott 		bcm2835_gpio_wr(pc, GPHEN0 + i * 4, 0);
1235e1b2dc70SSimon Arlott 		bcm2835_gpio_wr(pc, GPLEN0 + i * 4, 0);
1236e1b2dc70SSimon Arlott 		bcm2835_gpio_wr(pc, GPAREN0 + i * 4, 0);
1237e1b2dc70SSimon Arlott 		bcm2835_gpio_wr(pc, GPAFEN0 + i * 4, 0);
1238e1b2dc70SSimon Arlott 
1239e1b2dc70SSimon Arlott 		/* clear all the events */
1240e1b2dc70SSimon Arlott 		events = bcm2835_gpio_rd(pc, GPEDS0 + i * 4);
1241e1b2dc70SSimon Arlott 		for_each_set_bit(offset, &events, 32)
1242e1b2dc70SSimon Arlott 			bcm2835_gpio_wr(pc, GPEDS0 + i * 4, BIT(offset));
1243e1b2dc70SSimon Arlott 
12443c7b30f7SLukas Wunner 		raw_spin_lock_init(&pc->irq_lock[i]);
124500445b5dSPhil Elwell 	}
124600445b5dSPhil Elwell 
124773345a18SLinus Walleij 	girq = &pc->gpio_chip.irq;
124873345a18SLinus Walleij 	girq->chip = &bcm2835_gpio_irq_chip;
124973345a18SLinus Walleij 	girq->parent_handler = bcm2835_gpio_irq_handler;
125073345a18SLinus Walleij 	girq->num_parents = BCM2835_NUM_IRQS;
125173345a18SLinus Walleij 	girq->parents = devm_kcalloc(dev, BCM2835_NUM_IRQS,
125273345a18SLinus Walleij 				     sizeof(*girq->parents),
125373345a18SLinus Walleij 				     GFP_KERNEL);
125473345a18SLinus Walleij 	if (!girq->parents)
125573345a18SLinus Walleij 		return -ENOMEM;
1256920fecc1SFlorian Fainelli 
1257920fecc1SFlorian Fainelli 	if (is_7211) {
1258920fecc1SFlorian Fainelli 		pc->wake_irq = devm_kcalloc(dev, BCM2835_NUM_IRQS,
1259920fecc1SFlorian Fainelli 					    sizeof(*pc->wake_irq),
1260920fecc1SFlorian Fainelli 					    GFP_KERNEL);
1261920fecc1SFlorian Fainelli 		if (!pc->wake_irq)
1262920fecc1SFlorian Fainelli 			return -ENOMEM;
1263920fecc1SFlorian Fainelli 	}
1264920fecc1SFlorian Fainelli 
126585ae9e51SLinus Walleij 	/*
126685ae9e51SLinus Walleij 	 * Use the same handler for all groups: this is necessary
126785ae9e51SLinus Walleij 	 * since we use one gpiochip to cover all lines - the
126885ae9e51SLinus Walleij 	 * irq handler then needs to figure out which group and
126985ae9e51SLinus Walleij 	 * bank that was firing the IRQ and look up the per-group
127085ae9e51SLinus Walleij 	 * and bank data.
127185ae9e51SLinus Walleij 	 */
1272920fecc1SFlorian Fainelli 	for (i = 0; i < BCM2835_NUM_IRQS; i++) {
1273920fecc1SFlorian Fainelli 		int len;
1274920fecc1SFlorian Fainelli 		char *name;
1275920fecc1SFlorian Fainelli 
127673345a18SLinus Walleij 		girq->parents[i] = irq_of_parse_and_map(np, i);
12774bc80da5SPhil Elwell 		if (!is_7211) {
12784bc80da5SPhil Elwell 			if (!girq->parents[i]) {
12794bc80da5SPhil Elwell 				girq->num_parents = i;
12804bc80da5SPhil Elwell 				break;
12814bc80da5SPhil Elwell 			}
1282920fecc1SFlorian Fainelli 			continue;
12834bc80da5SPhil Elwell 		}
1284920fecc1SFlorian Fainelli 		/* Skip over the all banks interrupts */
1285920fecc1SFlorian Fainelli 		pc->wake_irq[i] = irq_of_parse_and_map(np, i +
1286920fecc1SFlorian Fainelli 						       BCM2835_NUM_IRQS + 1);
1287920fecc1SFlorian Fainelli 
1288920fecc1SFlorian Fainelli 		len = strlen(dev_name(pc->dev)) + 16;
1289920fecc1SFlorian Fainelli 		name = devm_kzalloc(pc->dev, len, GFP_KERNEL);
1290920fecc1SFlorian Fainelli 		if (!name)
1291920fecc1SFlorian Fainelli 			return -ENOMEM;
1292920fecc1SFlorian Fainelli 
1293920fecc1SFlorian Fainelli 		snprintf(name, len, "%s:bank%d", dev_name(pc->dev), i);
1294920fecc1SFlorian Fainelli 
1295920fecc1SFlorian Fainelli 		/* These are optional interrupts */
1296920fecc1SFlorian Fainelli 		err = devm_request_irq(dev, pc->wake_irq[i],
1297920fecc1SFlorian Fainelli 				       bcm2835_gpio_wake_irq_handler,
1298920fecc1SFlorian Fainelli 				       IRQF_SHARED, name, pc);
1299920fecc1SFlorian Fainelli 		if (err)
1300920fecc1SFlorian Fainelli 			dev_warn(dev, "unable to request wake IRQ %d\n",
1301920fecc1SFlorian Fainelli 				 pc->wake_irq[i]);
1302920fecc1SFlorian Fainelli 	}
1303920fecc1SFlorian Fainelli 
130473345a18SLinus Walleij 	girq->default_type = IRQ_TYPE_NONE;
130573345a18SLinus Walleij 	girq->handler = handle_level_irq;
130673345a18SLinus Walleij 
130773345a18SLinus Walleij 	err = gpiochip_add_data(&pc->gpio_chip, pc);
130873345a18SLinus Walleij 	if (err) {
130973345a18SLinus Walleij 		dev_err(dev, "could not add GPIO chip\n");
131073345a18SLinus Walleij 		return err;
131185ae9e51SLinus Walleij 	}
131285ae9e51SLinus Walleij 
131390bfaf02SStefan Wahren 	pc->pctl_desc = *pdata->pctl_desc;
131490bfaf02SStefan Wahren 	pc->pctl_dev = devm_pinctrl_register(dev, &pc->pctl_desc, pc);
1315323de9efSMasahiro Yamada 	if (IS_ERR(pc->pctl_dev)) {
1316e1b2dc70SSimon Arlott 		gpiochip_remove(&pc->gpio_chip);
1317323de9efSMasahiro Yamada 		return PTR_ERR(pc->pctl_dev);
1318e1b2dc70SSimon Arlott 	}
1319e1b2dc70SSimon Arlott 
132090bfaf02SStefan Wahren 	pc->gpio_range = *pdata->gpio_range;
1321e1b2dc70SSimon Arlott 	pc->gpio_range.base = pc->gpio_chip.base;
1322e1b2dc70SSimon Arlott 	pc->gpio_range.gc = &pc->gpio_chip;
1323e1b2dc70SSimon Arlott 	pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range);
1324e1b2dc70SSimon Arlott 
1325e1b2dc70SSimon Arlott 	return 0;
1326e1b2dc70SSimon Arlott }
1327e1b2dc70SSimon Arlott 
1328e1b2dc70SSimon Arlott static struct platform_driver bcm2835_pinctrl_driver = {
1329e1b2dc70SSimon Arlott 	.probe = bcm2835_pinctrl_probe,
1330e1b2dc70SSimon Arlott 	.driver = {
1331e1b2dc70SSimon Arlott 		.name = MODULE_NAME,
1332e1b2dc70SSimon Arlott 		.of_match_table = bcm2835_pinctrl_match,
133334f46848SPaul Gortmaker 		.suppress_bind_attrs = true,
1334e1b2dc70SSimon Arlott 	},
1335e1b2dc70SSimon Arlott };
133634f46848SPaul Gortmaker builtin_platform_driver(bcm2835_pinctrl_driver);
1337