1ce8dc094SAlexandre Belloni // SPDX-License-Identifier: (GPL-2.0 OR MIT)
2ce8dc094SAlexandre Belloni /*
3ce8dc094SAlexandre Belloni  * Microsemi SoCs pinctrl driver
4ce8dc094SAlexandre Belloni  *
5ce8dc094SAlexandre Belloni  * Author: <alexandre.belloni@free-electrons.com>
6ce8dc094SAlexandre Belloni  * License: Dual MIT/GPL
7ce8dc094SAlexandre Belloni  * Copyright (c) 2017 Microsemi Corporation
8ce8dc094SAlexandre Belloni  */
9ce8dc094SAlexandre Belloni 
10ce8dc094SAlexandre Belloni #include <linux/gpio/driver.h>
11ce8dc094SAlexandre Belloni #include <linux/interrupt.h>
12ce8dc094SAlexandre Belloni #include <linux/io.h>
13ce8dc094SAlexandre Belloni #include <linux/of_device.h>
14be36abb7SQuentin Schulz #include <linux/of_irq.h>
15ce8dc094SAlexandre Belloni #include <linux/of_platform.h>
16ce8dc094SAlexandre Belloni #include <linux/pinctrl/pinctrl.h>
17ce8dc094SAlexandre Belloni #include <linux/pinctrl/pinmux.h>
18ce8dc094SAlexandre Belloni #include <linux/pinctrl/pinconf.h>
19ce8dc094SAlexandre Belloni #include <linux/pinctrl/pinconf-generic.h>
20ce8dc094SAlexandre Belloni #include <linux/platform_device.h>
21ce8dc094SAlexandre Belloni #include <linux/regmap.h>
22ce8dc094SAlexandre Belloni #include <linux/slab.h>
23ce8dc094SAlexandre Belloni 
24ce8dc094SAlexandre Belloni #include "core.h"
25ce8dc094SAlexandre Belloni #include "pinconf.h"
26ce8dc094SAlexandre Belloni #include "pinmux.h"
27ce8dc094SAlexandre Belloni 
28ce8dc094SAlexandre Belloni #define OCELOT_GPIO_OUT_SET	0x0
29ce8dc094SAlexandre Belloni #define OCELOT_GPIO_OUT_CLR	0x4
30ce8dc094SAlexandre Belloni #define OCELOT_GPIO_OUT		0x8
31ce8dc094SAlexandre Belloni #define OCELOT_GPIO_IN		0xc
32ce8dc094SAlexandre Belloni #define OCELOT_GPIO_OE		0x10
33ce8dc094SAlexandre Belloni #define OCELOT_GPIO_INTR	0x14
34ce8dc094SAlexandre Belloni #define OCELOT_GPIO_INTR_ENA	0x18
35ce8dc094SAlexandre Belloni #define OCELOT_GPIO_INTR_IDENT	0x1c
36ce8dc094SAlexandre Belloni #define OCELOT_GPIO_ALT0	0x20
37ce8dc094SAlexandre Belloni #define OCELOT_GPIO_ALT1	0x24
38ce8dc094SAlexandre Belloni #define OCELOT_GPIO_SD_MAP	0x28
39ce8dc094SAlexandre Belloni 
40ce8dc094SAlexandre Belloni #define OCELOT_FUNC_PER_PIN	4
41ce8dc094SAlexandre Belloni 
42ce8dc094SAlexandre Belloni enum {
43ce8dc094SAlexandre Belloni 	FUNC_NONE,
44ce8dc094SAlexandre Belloni 	FUNC_GPIO,
45ce8dc094SAlexandre Belloni 	FUNC_IRQ0_IN,
46ce8dc094SAlexandre Belloni 	FUNC_IRQ0_OUT,
47ce8dc094SAlexandre Belloni 	FUNC_IRQ1_IN,
48ce8dc094SAlexandre Belloni 	FUNC_IRQ1_OUT,
49ce8dc094SAlexandre Belloni 	FUNC_MIIM1,
50da801ab5SAlexandre Belloni 	FUNC_MIIM2,
51ce8dc094SAlexandre Belloni 	FUNC_PCI_WAKE,
52ce8dc094SAlexandre Belloni 	FUNC_PTP0,
53ce8dc094SAlexandre Belloni 	FUNC_PTP1,
54ce8dc094SAlexandre Belloni 	FUNC_PTP2,
55ce8dc094SAlexandre Belloni 	FUNC_PTP3,
56ce8dc094SAlexandre Belloni 	FUNC_PWM,
57ce8dc094SAlexandre Belloni 	FUNC_RECO_CLK0,
58ce8dc094SAlexandre Belloni 	FUNC_RECO_CLK1,
59ce8dc094SAlexandre Belloni 	FUNC_SFP0,
60ce8dc094SAlexandre Belloni 	FUNC_SFP1,
61ce8dc094SAlexandre Belloni 	FUNC_SFP2,
62ce8dc094SAlexandre Belloni 	FUNC_SFP3,
63ce8dc094SAlexandre Belloni 	FUNC_SFP4,
64ce8dc094SAlexandre Belloni 	FUNC_SFP5,
65da801ab5SAlexandre Belloni 	FUNC_SFP6,
66da801ab5SAlexandre Belloni 	FUNC_SFP7,
67da801ab5SAlexandre Belloni 	FUNC_SFP8,
68da801ab5SAlexandre Belloni 	FUNC_SFP9,
69da801ab5SAlexandre Belloni 	FUNC_SFP10,
70da801ab5SAlexandre Belloni 	FUNC_SFP11,
71da801ab5SAlexandre Belloni 	FUNC_SFP12,
72da801ab5SAlexandre Belloni 	FUNC_SFP13,
73da801ab5SAlexandre Belloni 	FUNC_SFP14,
74da801ab5SAlexandre Belloni 	FUNC_SFP15,
75ce8dc094SAlexandre Belloni 	FUNC_SG0,
76da801ab5SAlexandre Belloni 	FUNC_SG1,
77da801ab5SAlexandre Belloni 	FUNC_SG2,
78ce8dc094SAlexandre Belloni 	FUNC_SI,
79ce8dc094SAlexandre Belloni 	FUNC_TACHO,
80ce8dc094SAlexandre Belloni 	FUNC_TWI,
81da801ab5SAlexandre Belloni 	FUNC_TWI2,
82ce8dc094SAlexandre Belloni 	FUNC_TWI_SCL_M,
83ce8dc094SAlexandre Belloni 	FUNC_UART,
84ce8dc094SAlexandre Belloni 	FUNC_UART2,
85ce8dc094SAlexandre Belloni 	FUNC_MAX
86ce8dc094SAlexandre Belloni };
87ce8dc094SAlexandre Belloni 
88ce8dc094SAlexandre Belloni static const char *const ocelot_function_names[] = {
89ce8dc094SAlexandre Belloni 	[FUNC_NONE]		= "none",
90ce8dc094SAlexandre Belloni 	[FUNC_GPIO]		= "gpio",
91ce8dc094SAlexandre Belloni 	[FUNC_IRQ0_IN]		= "irq0_in",
92ce8dc094SAlexandre Belloni 	[FUNC_IRQ0_OUT]		= "irq0_out",
93ce8dc094SAlexandre Belloni 	[FUNC_IRQ1_IN]		= "irq1_in",
94ce8dc094SAlexandre Belloni 	[FUNC_IRQ1_OUT]		= "irq1_out",
95ce8dc094SAlexandre Belloni 	[FUNC_MIIM1]		= "miim1",
96da801ab5SAlexandre Belloni 	[FUNC_MIIM2]		= "miim2",
97ce8dc094SAlexandre Belloni 	[FUNC_PCI_WAKE]		= "pci_wake",
98ce8dc094SAlexandre Belloni 	[FUNC_PTP0]		= "ptp0",
99ce8dc094SAlexandre Belloni 	[FUNC_PTP1]		= "ptp1",
100ce8dc094SAlexandre Belloni 	[FUNC_PTP2]		= "ptp2",
101ce8dc094SAlexandre Belloni 	[FUNC_PTP3]		= "ptp3",
102ce8dc094SAlexandre Belloni 	[FUNC_PWM]		= "pwm",
103ce8dc094SAlexandre Belloni 	[FUNC_RECO_CLK0]	= "reco_clk0",
104ce8dc094SAlexandre Belloni 	[FUNC_RECO_CLK1]	= "reco_clk1",
105ce8dc094SAlexandre Belloni 	[FUNC_SFP0]		= "sfp0",
106ce8dc094SAlexandre Belloni 	[FUNC_SFP1]		= "sfp1",
107ce8dc094SAlexandre Belloni 	[FUNC_SFP2]		= "sfp2",
108ce8dc094SAlexandre Belloni 	[FUNC_SFP3]		= "sfp3",
109ce8dc094SAlexandre Belloni 	[FUNC_SFP4]		= "sfp4",
110ce8dc094SAlexandre Belloni 	[FUNC_SFP5]		= "sfp5",
111da801ab5SAlexandre Belloni 	[FUNC_SFP6]		= "sfp6",
112da801ab5SAlexandre Belloni 	[FUNC_SFP7]		= "sfp7",
113da801ab5SAlexandre Belloni 	[FUNC_SFP8]		= "sfp8",
114da801ab5SAlexandre Belloni 	[FUNC_SFP9]		= "sfp9",
115da801ab5SAlexandre Belloni 	[FUNC_SFP10]		= "sfp10",
116da801ab5SAlexandre Belloni 	[FUNC_SFP11]		= "sfp11",
117da801ab5SAlexandre Belloni 	[FUNC_SFP12]		= "sfp12",
118da801ab5SAlexandre Belloni 	[FUNC_SFP13]		= "sfp13",
119da801ab5SAlexandre Belloni 	[FUNC_SFP14]		= "sfp14",
120da801ab5SAlexandre Belloni 	[FUNC_SFP15]		= "sfp15",
121ce8dc094SAlexandre Belloni 	[FUNC_SG0]		= "sg0",
122da801ab5SAlexandre Belloni 	[FUNC_SG1]		= "sg1",
123da801ab5SAlexandre Belloni 	[FUNC_SG2]		= "sg2",
124ce8dc094SAlexandre Belloni 	[FUNC_SI]		= "si",
125ce8dc094SAlexandre Belloni 	[FUNC_TACHO]		= "tacho",
126ce8dc094SAlexandre Belloni 	[FUNC_TWI]		= "twi",
127da801ab5SAlexandre Belloni 	[FUNC_TWI2]		= "twi2",
128ce8dc094SAlexandre Belloni 	[FUNC_TWI_SCL_M]	= "twi_scl_m",
129ce8dc094SAlexandre Belloni 	[FUNC_UART]		= "uart",
130ce8dc094SAlexandre Belloni 	[FUNC_UART2]		= "uart2",
131ce8dc094SAlexandre Belloni };
132ce8dc094SAlexandre Belloni 
133ce8dc094SAlexandre Belloni struct ocelot_pmx_func {
134ce8dc094SAlexandre Belloni 	const char **groups;
135ce8dc094SAlexandre Belloni 	unsigned int ngroups;
136ce8dc094SAlexandre Belloni };
137ce8dc094SAlexandre Belloni 
138ce8dc094SAlexandre Belloni struct ocelot_pin_caps {
139ce8dc094SAlexandre Belloni 	unsigned int pin;
140ce8dc094SAlexandre Belloni 	unsigned char functions[OCELOT_FUNC_PER_PIN];
141ce8dc094SAlexandre Belloni };
142ce8dc094SAlexandre Belloni 
143ce8dc094SAlexandre Belloni struct ocelot_pinctrl {
144ce8dc094SAlexandre Belloni 	struct device *dev;
145ce8dc094SAlexandre Belloni 	struct pinctrl_dev *pctl;
146ce8dc094SAlexandre Belloni 	struct gpio_chip gpio_chip;
147ce8dc094SAlexandre Belloni 	struct regmap *map;
148da801ab5SAlexandre Belloni 	struct pinctrl_desc *desc;
149ce8dc094SAlexandre Belloni 	struct ocelot_pmx_func func[FUNC_MAX];
150da801ab5SAlexandre Belloni 	u8 stride;
151ce8dc094SAlexandre Belloni };
152ce8dc094SAlexandre Belloni 
153ce8dc094SAlexandre Belloni #define OCELOT_P(p, f0, f1, f2)						\
154ce8dc094SAlexandre Belloni static struct ocelot_pin_caps ocelot_pin_##p = {			\
155ce8dc094SAlexandre Belloni 	.pin = p,							\
156ce8dc094SAlexandre Belloni 	.functions = {							\
157ce8dc094SAlexandre Belloni 			FUNC_GPIO, FUNC_##f0, FUNC_##f1, FUNC_##f2,	\
158ce8dc094SAlexandre Belloni 	},								\
159ce8dc094SAlexandre Belloni }
160ce8dc094SAlexandre Belloni 
161ce8dc094SAlexandre Belloni OCELOT_P(0,  SG0,       NONE,      NONE);
162ce8dc094SAlexandre Belloni OCELOT_P(1,  SG0,       NONE,      NONE);
163ce8dc094SAlexandre Belloni OCELOT_P(2,  SG0,       NONE,      NONE);
164ce8dc094SAlexandre Belloni OCELOT_P(3,  SG0,       NONE,      NONE);
16517f79084SAlexandre Belloni OCELOT_P(4,  IRQ0_IN,   IRQ0_OUT,  TWI_SCL_M);
166ce8dc094SAlexandre Belloni OCELOT_P(5,  IRQ1_IN,   IRQ1_OUT,  PCI_WAKE);
167ce8dc094SAlexandre Belloni OCELOT_P(6,  UART,      TWI_SCL_M, NONE);
168ce8dc094SAlexandre Belloni OCELOT_P(7,  UART,      TWI_SCL_M, NONE);
169ce8dc094SAlexandre Belloni OCELOT_P(8,  SI,        TWI_SCL_M, IRQ0_OUT);
170ce8dc094SAlexandre Belloni OCELOT_P(9,  SI,        TWI_SCL_M, IRQ1_OUT);
171ce8dc094SAlexandre Belloni OCELOT_P(10, PTP2,      TWI_SCL_M, SFP0);
172ce8dc094SAlexandre Belloni OCELOT_P(11, PTP3,      TWI_SCL_M, SFP1);
173ce8dc094SAlexandre Belloni OCELOT_P(12, UART2,     TWI_SCL_M, SFP2);
174ce8dc094SAlexandre Belloni OCELOT_P(13, UART2,     TWI_SCL_M, SFP3);
175ce8dc094SAlexandre Belloni OCELOT_P(14, MIIM1,     TWI_SCL_M, SFP4);
176ce8dc094SAlexandre Belloni OCELOT_P(15, MIIM1,     TWI_SCL_M, SFP5);
177ce8dc094SAlexandre Belloni OCELOT_P(16, TWI,       NONE,      SI);
178ce8dc094SAlexandre Belloni OCELOT_P(17, TWI,       TWI_SCL_M, SI);
179ce8dc094SAlexandre Belloni OCELOT_P(18, PTP0,      TWI_SCL_M, NONE);
180ce8dc094SAlexandre Belloni OCELOT_P(19, PTP1,      TWI_SCL_M, NONE);
181ce8dc094SAlexandre Belloni OCELOT_P(20, RECO_CLK0, TACHO,     NONE);
182ce8dc094SAlexandre Belloni OCELOT_P(21, RECO_CLK1, PWM,       NONE);
183ce8dc094SAlexandre Belloni 
184ce8dc094SAlexandre Belloni #define OCELOT_PIN(n) {						\
185ce8dc094SAlexandre Belloni 	.number = n,						\
186ce8dc094SAlexandre Belloni 	.name = "GPIO_"#n,					\
187ce8dc094SAlexandre Belloni 	.drv_data = &ocelot_pin_##n				\
188ce8dc094SAlexandre Belloni }
189ce8dc094SAlexandre Belloni 
190ce8dc094SAlexandre Belloni static const struct pinctrl_pin_desc ocelot_pins[] = {
191ce8dc094SAlexandre Belloni 	OCELOT_PIN(0),
192ce8dc094SAlexandre Belloni 	OCELOT_PIN(1),
193ce8dc094SAlexandre Belloni 	OCELOT_PIN(2),
194ce8dc094SAlexandre Belloni 	OCELOT_PIN(3),
195ce8dc094SAlexandre Belloni 	OCELOT_PIN(4),
196ce8dc094SAlexandre Belloni 	OCELOT_PIN(5),
197ce8dc094SAlexandre Belloni 	OCELOT_PIN(6),
198ce8dc094SAlexandre Belloni 	OCELOT_PIN(7),
199ce8dc094SAlexandre Belloni 	OCELOT_PIN(8),
200ce8dc094SAlexandre Belloni 	OCELOT_PIN(9),
201ce8dc094SAlexandre Belloni 	OCELOT_PIN(10),
202ce8dc094SAlexandre Belloni 	OCELOT_PIN(11),
203ce8dc094SAlexandre Belloni 	OCELOT_PIN(12),
204ce8dc094SAlexandre Belloni 	OCELOT_PIN(13),
205ce8dc094SAlexandre Belloni 	OCELOT_PIN(14),
206ce8dc094SAlexandre Belloni 	OCELOT_PIN(15),
207ce8dc094SAlexandre Belloni 	OCELOT_PIN(16),
208ce8dc094SAlexandre Belloni 	OCELOT_PIN(17),
209ce8dc094SAlexandre Belloni 	OCELOT_PIN(18),
210ce8dc094SAlexandre Belloni 	OCELOT_PIN(19),
211ce8dc094SAlexandre Belloni 	OCELOT_PIN(20),
212ce8dc094SAlexandre Belloni 	OCELOT_PIN(21),
213ce8dc094SAlexandre Belloni };
214ce8dc094SAlexandre Belloni 
215da801ab5SAlexandre Belloni #define JAGUAR2_P(p, f0, f1)						\
216da801ab5SAlexandre Belloni static struct ocelot_pin_caps jaguar2_pin_##p = {			\
217da801ab5SAlexandre Belloni 	.pin = p,							\
218da801ab5SAlexandre Belloni 	.functions = {							\
219da801ab5SAlexandre Belloni 			FUNC_GPIO, FUNC_##f0, FUNC_##f1, FUNC_NONE	\
220da801ab5SAlexandre Belloni 	},								\
221da801ab5SAlexandre Belloni }
222da801ab5SAlexandre Belloni 
223da801ab5SAlexandre Belloni JAGUAR2_P(0,  SG0,       NONE);
224da801ab5SAlexandre Belloni JAGUAR2_P(1,  SG0,       NONE);
225da801ab5SAlexandre Belloni JAGUAR2_P(2,  SG0,       NONE);
226da801ab5SAlexandre Belloni JAGUAR2_P(3,  SG0,       NONE);
227da801ab5SAlexandre Belloni JAGUAR2_P(4,  SG1,       NONE);
228da801ab5SAlexandre Belloni JAGUAR2_P(5,  SG1,       NONE);
229da801ab5SAlexandre Belloni JAGUAR2_P(6,  IRQ0_IN,   IRQ0_OUT);
230da801ab5SAlexandre Belloni JAGUAR2_P(7,  IRQ1_IN,   IRQ1_OUT);
231da801ab5SAlexandre Belloni JAGUAR2_P(8,  PTP0,      NONE);
232da801ab5SAlexandre Belloni JAGUAR2_P(9,  PTP1,      NONE);
233da801ab5SAlexandre Belloni JAGUAR2_P(10, UART,      NONE);
234da801ab5SAlexandre Belloni JAGUAR2_P(11, UART,      NONE);
235da801ab5SAlexandre Belloni JAGUAR2_P(12, SG1,       NONE);
236da801ab5SAlexandre Belloni JAGUAR2_P(13, SG1,       NONE);
237da801ab5SAlexandre Belloni JAGUAR2_P(14, TWI,       TWI_SCL_M);
238da801ab5SAlexandre Belloni JAGUAR2_P(15, TWI,       NONE);
239da801ab5SAlexandre Belloni JAGUAR2_P(16, SI,        TWI_SCL_M);
240da801ab5SAlexandre Belloni JAGUAR2_P(17, SI,        TWI_SCL_M);
241da801ab5SAlexandre Belloni JAGUAR2_P(18, SI,        TWI_SCL_M);
242da801ab5SAlexandre Belloni JAGUAR2_P(19, PCI_WAKE,  NONE);
243da801ab5SAlexandre Belloni JAGUAR2_P(20, IRQ0_OUT,  TWI_SCL_M);
244da801ab5SAlexandre Belloni JAGUAR2_P(21, IRQ1_OUT,  TWI_SCL_M);
245da801ab5SAlexandre Belloni JAGUAR2_P(22, TACHO,     NONE);
246da801ab5SAlexandre Belloni JAGUAR2_P(23, PWM,       NONE);
247da801ab5SAlexandre Belloni JAGUAR2_P(24, UART2,     NONE);
248da801ab5SAlexandre Belloni JAGUAR2_P(25, UART2,     SI);
249da801ab5SAlexandre Belloni JAGUAR2_P(26, PTP2,      SI);
250da801ab5SAlexandre Belloni JAGUAR2_P(27, PTP3,      SI);
251da801ab5SAlexandre Belloni JAGUAR2_P(28, TWI2,      SI);
252da801ab5SAlexandre Belloni JAGUAR2_P(29, TWI2,      SI);
253da801ab5SAlexandre Belloni JAGUAR2_P(30, SG2,       SI);
254da801ab5SAlexandre Belloni JAGUAR2_P(31, SG2,       SI);
255da801ab5SAlexandre Belloni JAGUAR2_P(32, SG2,       SI);
256da801ab5SAlexandre Belloni JAGUAR2_P(33, SG2,       SI);
257da801ab5SAlexandre Belloni JAGUAR2_P(34, NONE,      TWI_SCL_M);
258da801ab5SAlexandre Belloni JAGUAR2_P(35, NONE,      TWI_SCL_M);
259da801ab5SAlexandre Belloni JAGUAR2_P(36, NONE,      TWI_SCL_M);
260da801ab5SAlexandre Belloni JAGUAR2_P(37, NONE,      TWI_SCL_M);
261da801ab5SAlexandre Belloni JAGUAR2_P(38, NONE,      TWI_SCL_M);
262da801ab5SAlexandre Belloni JAGUAR2_P(39, NONE,      TWI_SCL_M);
263da801ab5SAlexandre Belloni JAGUAR2_P(40, NONE,      TWI_SCL_M);
264da801ab5SAlexandre Belloni JAGUAR2_P(41, NONE,      TWI_SCL_M);
265da801ab5SAlexandre Belloni JAGUAR2_P(42, NONE,      TWI_SCL_M);
266da801ab5SAlexandre Belloni JAGUAR2_P(43, NONE,      TWI_SCL_M);
267da801ab5SAlexandre Belloni JAGUAR2_P(44, NONE,      SFP8);
268da801ab5SAlexandre Belloni JAGUAR2_P(45, NONE,      SFP9);
269da801ab5SAlexandre Belloni JAGUAR2_P(46, NONE,      SFP10);
270da801ab5SAlexandre Belloni JAGUAR2_P(47, NONE,      SFP11);
271da801ab5SAlexandre Belloni JAGUAR2_P(48, SFP0,      NONE);
272da801ab5SAlexandre Belloni JAGUAR2_P(49, SFP1,      SI);
273da801ab5SAlexandre Belloni JAGUAR2_P(50, SFP2,      SI);
274da801ab5SAlexandre Belloni JAGUAR2_P(51, SFP3,      SI);
275da801ab5SAlexandre Belloni JAGUAR2_P(52, SFP4,      NONE);
276da801ab5SAlexandre Belloni JAGUAR2_P(53, SFP5,      NONE);
277da801ab5SAlexandre Belloni JAGUAR2_P(54, SFP6,      NONE);
278da801ab5SAlexandre Belloni JAGUAR2_P(55, SFP7,      NONE);
279da801ab5SAlexandre Belloni JAGUAR2_P(56, MIIM1,     SFP12);
280da801ab5SAlexandre Belloni JAGUAR2_P(57, MIIM1,     SFP13);
281da801ab5SAlexandre Belloni JAGUAR2_P(58, MIIM2,     SFP14);
282da801ab5SAlexandre Belloni JAGUAR2_P(59, MIIM2,     SFP15);
283da801ab5SAlexandre Belloni JAGUAR2_P(60, NONE,      NONE);
284da801ab5SAlexandre Belloni JAGUAR2_P(61, NONE,      NONE);
285da801ab5SAlexandre Belloni JAGUAR2_P(62, NONE,      NONE);
286da801ab5SAlexandre Belloni JAGUAR2_P(63, NONE,      NONE);
287da801ab5SAlexandre Belloni 
288da801ab5SAlexandre Belloni #define JAGUAR2_PIN(n) {					\
289da801ab5SAlexandre Belloni 	.number = n,						\
290da801ab5SAlexandre Belloni 	.name = "GPIO_"#n,					\
291da801ab5SAlexandre Belloni 	.drv_data = &jaguar2_pin_##n				\
292da801ab5SAlexandre Belloni }
293da801ab5SAlexandre Belloni 
294da801ab5SAlexandre Belloni static const struct pinctrl_pin_desc jaguar2_pins[] = {
295da801ab5SAlexandre Belloni 	JAGUAR2_PIN(0),
296da801ab5SAlexandre Belloni 	JAGUAR2_PIN(1),
297da801ab5SAlexandre Belloni 	JAGUAR2_PIN(2),
298da801ab5SAlexandre Belloni 	JAGUAR2_PIN(3),
299da801ab5SAlexandre Belloni 	JAGUAR2_PIN(4),
300da801ab5SAlexandre Belloni 	JAGUAR2_PIN(5),
301da801ab5SAlexandre Belloni 	JAGUAR2_PIN(6),
302da801ab5SAlexandre Belloni 	JAGUAR2_PIN(7),
303da801ab5SAlexandre Belloni 	JAGUAR2_PIN(8),
304da801ab5SAlexandre Belloni 	JAGUAR2_PIN(9),
305da801ab5SAlexandre Belloni 	JAGUAR2_PIN(10),
306da801ab5SAlexandre Belloni 	JAGUAR2_PIN(11),
307da801ab5SAlexandre Belloni 	JAGUAR2_PIN(12),
308da801ab5SAlexandre Belloni 	JAGUAR2_PIN(13),
309da801ab5SAlexandre Belloni 	JAGUAR2_PIN(14),
310da801ab5SAlexandre Belloni 	JAGUAR2_PIN(15),
311da801ab5SAlexandre Belloni 	JAGUAR2_PIN(16),
312da801ab5SAlexandre Belloni 	JAGUAR2_PIN(17),
313da801ab5SAlexandre Belloni 	JAGUAR2_PIN(18),
314da801ab5SAlexandre Belloni 	JAGUAR2_PIN(19),
315da801ab5SAlexandre Belloni 	JAGUAR2_PIN(20),
316da801ab5SAlexandre Belloni 	JAGUAR2_PIN(21),
317da801ab5SAlexandre Belloni 	JAGUAR2_PIN(22),
318da801ab5SAlexandre Belloni 	JAGUAR2_PIN(23),
319da801ab5SAlexandre Belloni 	JAGUAR2_PIN(24),
320da801ab5SAlexandre Belloni 	JAGUAR2_PIN(25),
321da801ab5SAlexandre Belloni 	JAGUAR2_PIN(26),
322da801ab5SAlexandre Belloni 	JAGUAR2_PIN(27),
323da801ab5SAlexandre Belloni 	JAGUAR2_PIN(28),
324da801ab5SAlexandre Belloni 	JAGUAR2_PIN(29),
325da801ab5SAlexandre Belloni 	JAGUAR2_PIN(30),
326da801ab5SAlexandre Belloni 	JAGUAR2_PIN(31),
327da801ab5SAlexandre Belloni 	JAGUAR2_PIN(32),
328da801ab5SAlexandre Belloni 	JAGUAR2_PIN(33),
329da801ab5SAlexandre Belloni 	JAGUAR2_PIN(34),
330da801ab5SAlexandre Belloni 	JAGUAR2_PIN(35),
331da801ab5SAlexandre Belloni 	JAGUAR2_PIN(36),
332da801ab5SAlexandre Belloni 	JAGUAR2_PIN(37),
333da801ab5SAlexandre Belloni 	JAGUAR2_PIN(38),
334da801ab5SAlexandre Belloni 	JAGUAR2_PIN(39),
335da801ab5SAlexandre Belloni 	JAGUAR2_PIN(40),
336da801ab5SAlexandre Belloni 	JAGUAR2_PIN(41),
337da801ab5SAlexandre Belloni 	JAGUAR2_PIN(42),
338da801ab5SAlexandre Belloni 	JAGUAR2_PIN(43),
339da801ab5SAlexandre Belloni 	JAGUAR2_PIN(44),
340da801ab5SAlexandre Belloni 	JAGUAR2_PIN(45),
341da801ab5SAlexandre Belloni 	JAGUAR2_PIN(46),
342da801ab5SAlexandre Belloni 	JAGUAR2_PIN(47),
343da801ab5SAlexandre Belloni 	JAGUAR2_PIN(48),
344da801ab5SAlexandre Belloni 	JAGUAR2_PIN(49),
345da801ab5SAlexandre Belloni 	JAGUAR2_PIN(50),
346da801ab5SAlexandre Belloni 	JAGUAR2_PIN(51),
347da801ab5SAlexandre Belloni 	JAGUAR2_PIN(52),
348da801ab5SAlexandre Belloni 	JAGUAR2_PIN(53),
349da801ab5SAlexandre Belloni 	JAGUAR2_PIN(54),
350da801ab5SAlexandre Belloni 	JAGUAR2_PIN(55),
351da801ab5SAlexandre Belloni 	JAGUAR2_PIN(56),
352da801ab5SAlexandre Belloni 	JAGUAR2_PIN(57),
353da801ab5SAlexandre Belloni 	JAGUAR2_PIN(58),
354da801ab5SAlexandre Belloni 	JAGUAR2_PIN(59),
355da801ab5SAlexandre Belloni 	JAGUAR2_PIN(60),
356da801ab5SAlexandre Belloni 	JAGUAR2_PIN(61),
357da801ab5SAlexandre Belloni 	JAGUAR2_PIN(62),
358da801ab5SAlexandre Belloni 	JAGUAR2_PIN(63),
359da801ab5SAlexandre Belloni };
360da801ab5SAlexandre Belloni 
361ce8dc094SAlexandre Belloni static int ocelot_get_functions_count(struct pinctrl_dev *pctldev)
362ce8dc094SAlexandre Belloni {
363ce8dc094SAlexandre Belloni 	return ARRAY_SIZE(ocelot_function_names);
364ce8dc094SAlexandre Belloni }
365ce8dc094SAlexandre Belloni 
366ce8dc094SAlexandre Belloni static const char *ocelot_get_function_name(struct pinctrl_dev *pctldev,
367ce8dc094SAlexandre Belloni 					    unsigned int function)
368ce8dc094SAlexandre Belloni {
369ce8dc094SAlexandre Belloni 	return ocelot_function_names[function];
370ce8dc094SAlexandre Belloni }
371ce8dc094SAlexandre Belloni 
372ce8dc094SAlexandre Belloni static int ocelot_get_function_groups(struct pinctrl_dev *pctldev,
373ce8dc094SAlexandre Belloni 				      unsigned int function,
374ce8dc094SAlexandre Belloni 				      const char *const **groups,
375ce8dc094SAlexandre Belloni 				      unsigned *const num_groups)
376ce8dc094SAlexandre Belloni {
377ce8dc094SAlexandre Belloni 	struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
378ce8dc094SAlexandre Belloni 
379ce8dc094SAlexandre Belloni 	*groups  = info->func[function].groups;
380ce8dc094SAlexandre Belloni 	*num_groups = info->func[function].ngroups;
381ce8dc094SAlexandre Belloni 
382ce8dc094SAlexandre Belloni 	return 0;
383ce8dc094SAlexandre Belloni }
384ce8dc094SAlexandre Belloni 
385da801ab5SAlexandre Belloni static int ocelot_pin_function_idx(struct ocelot_pinctrl *info,
386da801ab5SAlexandre Belloni 				   unsigned int pin, unsigned int function)
387ce8dc094SAlexandre Belloni {
388da801ab5SAlexandre Belloni 	struct ocelot_pin_caps *p = info->desc->pins[pin].drv_data;
389ce8dc094SAlexandre Belloni 	int i;
390ce8dc094SAlexandre Belloni 
391ce8dc094SAlexandre Belloni 	for (i = 0; i < OCELOT_FUNC_PER_PIN; i++) {
392ce8dc094SAlexandre Belloni 		if (function == p->functions[i])
393ce8dc094SAlexandre Belloni 			return i;
394ce8dc094SAlexandre Belloni 	}
395ce8dc094SAlexandre Belloni 
396ce8dc094SAlexandre Belloni 	return -1;
397ce8dc094SAlexandre Belloni }
398ce8dc094SAlexandre Belloni 
399da801ab5SAlexandre Belloni #define REG(r, info, p) ((r) * (info)->stride + (4 * ((p) / 32)))
400da801ab5SAlexandre Belloni 
401ce8dc094SAlexandre Belloni static int ocelot_pinmux_set_mux(struct pinctrl_dev *pctldev,
402ce8dc094SAlexandre Belloni 				 unsigned int selector, unsigned int group)
403ce8dc094SAlexandre Belloni {
404ce8dc094SAlexandre Belloni 	struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
405da801ab5SAlexandre Belloni 	struct ocelot_pin_caps *pin = info->desc->pins[group].drv_data;
406da801ab5SAlexandre Belloni 	unsigned int p = pin->pin % 32;
407ce8dc094SAlexandre Belloni 	int f;
408ce8dc094SAlexandre Belloni 
409da801ab5SAlexandre Belloni 	f = ocelot_pin_function_idx(info, group, selector);
410ce8dc094SAlexandre Belloni 	if (f < 0)
411ce8dc094SAlexandre Belloni 		return -EINVAL;
412ce8dc094SAlexandre Belloni 
413ce8dc094SAlexandre Belloni 	/*
414ce8dc094SAlexandre Belloni 	 * f is encoded on two bits.
415ce8dc094SAlexandre Belloni 	 * bit 0 of f goes in BIT(pin) of ALT0, bit 1 of f goes in BIT(pin) of
416ce8dc094SAlexandre Belloni 	 * ALT1
417ce8dc094SAlexandre Belloni 	 * This is racy because both registers can't be updated at the same time
418ce8dc094SAlexandre Belloni 	 * but it doesn't matter much for now.
419ce8dc094SAlexandre Belloni 	 */
420da801ab5SAlexandre Belloni 	regmap_update_bits(info->map, REG(OCELOT_GPIO_ALT0, info, pin->pin),
421da801ab5SAlexandre Belloni 			   BIT(p), f << p);
422da801ab5SAlexandre Belloni 	regmap_update_bits(info->map, REG(OCELOT_GPIO_ALT1, info, pin->pin),
423da801ab5SAlexandre Belloni 			   BIT(p), f << (p - 1));
424ce8dc094SAlexandre Belloni 
425ce8dc094SAlexandre Belloni 	return 0;
426ce8dc094SAlexandre Belloni }
427ce8dc094SAlexandre Belloni 
428ce8dc094SAlexandre Belloni static int ocelot_gpio_set_direction(struct pinctrl_dev *pctldev,
429ce8dc094SAlexandre Belloni 				     struct pinctrl_gpio_range *range,
430ce8dc094SAlexandre Belloni 				     unsigned int pin, bool input)
431ce8dc094SAlexandre Belloni {
432ce8dc094SAlexandre Belloni 	struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
433da801ab5SAlexandre Belloni 	unsigned int p = pin % 32;
434ce8dc094SAlexandre Belloni 
435da801ab5SAlexandre Belloni 	regmap_update_bits(info->map, REG(OCELOT_GPIO_OE, info, p), BIT(p),
436da801ab5SAlexandre Belloni 			   input ? 0 : BIT(p));
437ce8dc094SAlexandre Belloni 
438ce8dc094SAlexandre Belloni 	return 0;
439ce8dc094SAlexandre Belloni }
440ce8dc094SAlexandre Belloni 
441ce8dc094SAlexandre Belloni static int ocelot_gpio_request_enable(struct pinctrl_dev *pctldev,
442ce8dc094SAlexandre Belloni 				      struct pinctrl_gpio_range *range,
443ce8dc094SAlexandre Belloni 				      unsigned int offset)
444ce8dc094SAlexandre Belloni {
445ce8dc094SAlexandre Belloni 	struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
446da801ab5SAlexandre Belloni 	unsigned int p = offset % 32;
447ce8dc094SAlexandre Belloni 
448da801ab5SAlexandre Belloni 	regmap_update_bits(info->map, REG(OCELOT_GPIO_ALT0, info, offset),
449da801ab5SAlexandre Belloni 			   BIT(p), 0);
450da801ab5SAlexandre Belloni 	regmap_update_bits(info->map, REG(OCELOT_GPIO_ALT1, info, offset),
451da801ab5SAlexandre Belloni 			   BIT(p), 0);
452ce8dc094SAlexandre Belloni 
453ce8dc094SAlexandre Belloni 	return 0;
454ce8dc094SAlexandre Belloni }
455ce8dc094SAlexandre Belloni 
456ce8dc094SAlexandre Belloni static const struct pinmux_ops ocelot_pmx_ops = {
457ce8dc094SAlexandre Belloni 	.get_functions_count = ocelot_get_functions_count,
458ce8dc094SAlexandre Belloni 	.get_function_name = ocelot_get_function_name,
459ce8dc094SAlexandre Belloni 	.get_function_groups = ocelot_get_function_groups,
460ce8dc094SAlexandre Belloni 	.set_mux = ocelot_pinmux_set_mux,
461ce8dc094SAlexandre Belloni 	.gpio_set_direction = ocelot_gpio_set_direction,
462ce8dc094SAlexandre Belloni 	.gpio_request_enable = ocelot_gpio_request_enable,
463ce8dc094SAlexandre Belloni };
464ce8dc094SAlexandre Belloni 
465ce8dc094SAlexandre Belloni static int ocelot_pctl_get_groups_count(struct pinctrl_dev *pctldev)
466ce8dc094SAlexandre Belloni {
467da801ab5SAlexandre Belloni 	struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
468da801ab5SAlexandre Belloni 
469da801ab5SAlexandre Belloni 	return info->desc->npins;
470ce8dc094SAlexandre Belloni }
471ce8dc094SAlexandre Belloni 
472ce8dc094SAlexandre Belloni static const char *ocelot_pctl_get_group_name(struct pinctrl_dev *pctldev,
473ce8dc094SAlexandre Belloni 					      unsigned int group)
474ce8dc094SAlexandre Belloni {
475da801ab5SAlexandre Belloni 	struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
476da801ab5SAlexandre Belloni 
477da801ab5SAlexandre Belloni 	return info->desc->pins[group].name;
478ce8dc094SAlexandre Belloni }
479ce8dc094SAlexandre Belloni 
480ce8dc094SAlexandre Belloni static int ocelot_pctl_get_group_pins(struct pinctrl_dev *pctldev,
481ce8dc094SAlexandre Belloni 				      unsigned int group,
482ce8dc094SAlexandre Belloni 				      const unsigned int **pins,
483ce8dc094SAlexandre Belloni 				      unsigned int *num_pins)
484ce8dc094SAlexandre Belloni {
485da801ab5SAlexandre Belloni 	struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
486da801ab5SAlexandre Belloni 
487da801ab5SAlexandre Belloni 	*pins = &info->desc->pins[group].number;
488ce8dc094SAlexandre Belloni 	*num_pins = 1;
489ce8dc094SAlexandre Belloni 
490ce8dc094SAlexandre Belloni 	return 0;
491ce8dc094SAlexandre Belloni }
492ce8dc094SAlexandre Belloni 
493ce8dc094SAlexandre Belloni static const struct pinctrl_ops ocelot_pctl_ops = {
494ce8dc094SAlexandre Belloni 	.get_groups_count = ocelot_pctl_get_groups_count,
495ce8dc094SAlexandre Belloni 	.get_group_name = ocelot_pctl_get_group_name,
496ce8dc094SAlexandre Belloni 	.get_group_pins = ocelot_pctl_get_group_pins,
497ce8dc094SAlexandre Belloni 	.dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
498ce8dc094SAlexandre Belloni 	.dt_free_map = pinconf_generic_dt_free_map,
499ce8dc094SAlexandre Belloni };
500ce8dc094SAlexandre Belloni 
501ce8dc094SAlexandre Belloni static struct pinctrl_desc ocelot_desc = {
502ce8dc094SAlexandre Belloni 	.name = "ocelot-pinctrl",
503ce8dc094SAlexandre Belloni 	.pins = ocelot_pins,
504ce8dc094SAlexandre Belloni 	.npins = ARRAY_SIZE(ocelot_pins),
505ce8dc094SAlexandre Belloni 	.pctlops = &ocelot_pctl_ops,
506ce8dc094SAlexandre Belloni 	.pmxops = &ocelot_pmx_ops,
507ce8dc094SAlexandre Belloni 	.owner = THIS_MODULE,
508ce8dc094SAlexandre Belloni };
509ce8dc094SAlexandre Belloni 
510da801ab5SAlexandre Belloni static struct pinctrl_desc jaguar2_desc = {
511da801ab5SAlexandre Belloni 	.name = "jaguar2-pinctrl",
512da801ab5SAlexandre Belloni 	.pins = jaguar2_pins,
513da801ab5SAlexandre Belloni 	.npins = ARRAY_SIZE(jaguar2_pins),
514da801ab5SAlexandre Belloni 	.pctlops = &ocelot_pctl_ops,
515da801ab5SAlexandre Belloni 	.pmxops = &ocelot_pmx_ops,
516da801ab5SAlexandre Belloni 	.owner = THIS_MODULE,
517da801ab5SAlexandre Belloni };
518da801ab5SAlexandre Belloni 
519ce8dc094SAlexandre Belloni static int ocelot_create_group_func_map(struct device *dev,
520ce8dc094SAlexandre Belloni 					struct ocelot_pinctrl *info)
521ce8dc094SAlexandre Belloni {
522ce8dc094SAlexandre Belloni 	int f, npins, i;
523da801ab5SAlexandre Belloni 	u8 *pins = kcalloc(info->desc->npins, sizeof(u8), GFP_KERNEL);
524da801ab5SAlexandre Belloni 
525da801ab5SAlexandre Belloni 	if (!pins)
526da801ab5SAlexandre Belloni 		return -ENOMEM;
527ce8dc094SAlexandre Belloni 
528ce8dc094SAlexandre Belloni 	for (f = 0; f < FUNC_MAX; f++) {
529da801ab5SAlexandre Belloni 		for (npins = 0, i = 0; i < info->desc->npins; i++) {
530da801ab5SAlexandre Belloni 			if (ocelot_pin_function_idx(info, i, f) >= 0)
531ce8dc094SAlexandre Belloni 				pins[npins++] = i;
532ce8dc094SAlexandre Belloni 		}
533ce8dc094SAlexandre Belloni 
534da801ab5SAlexandre Belloni 		if (!npins)
535da801ab5SAlexandre Belloni 			continue;
536da801ab5SAlexandre Belloni 
537ce8dc094SAlexandre Belloni 		info->func[f].ngroups = npins;
538da801ab5SAlexandre Belloni 		info->func[f].groups = devm_kcalloc(dev, npins, sizeof(char *),
539ce8dc094SAlexandre Belloni 						    GFP_KERNEL);
540da801ab5SAlexandre Belloni 		if (!info->func[f].groups) {
541da801ab5SAlexandre Belloni 			kfree(pins);
542ce8dc094SAlexandre Belloni 			return -ENOMEM;
543da801ab5SAlexandre Belloni 		}
544ce8dc094SAlexandre Belloni 
545ce8dc094SAlexandre Belloni 		for (i = 0; i < npins; i++)
546da801ab5SAlexandre Belloni 			info->func[f].groups[i] = info->desc->pins[pins[i]].name;
547ce8dc094SAlexandre Belloni 	}
548ce8dc094SAlexandre Belloni 
549da801ab5SAlexandre Belloni 	kfree(pins);
550da801ab5SAlexandre Belloni 
551ce8dc094SAlexandre Belloni 	return 0;
552ce8dc094SAlexandre Belloni }
553ce8dc094SAlexandre Belloni 
554ce8dc094SAlexandre Belloni static int ocelot_pinctrl_register(struct platform_device *pdev,
555ce8dc094SAlexandre Belloni 				   struct ocelot_pinctrl *info)
556ce8dc094SAlexandre Belloni {
557ce8dc094SAlexandre Belloni 	int ret;
558ce8dc094SAlexandre Belloni 
559ce8dc094SAlexandre Belloni 	ret = ocelot_create_group_func_map(&pdev->dev, info);
560ce8dc094SAlexandre Belloni 	if (ret) {
561ce8dc094SAlexandre Belloni 		dev_err(&pdev->dev, "Unable to create group func map.\n");
562ce8dc094SAlexandre Belloni 		return ret;
563ce8dc094SAlexandre Belloni 	}
564ce8dc094SAlexandre Belloni 
565da801ab5SAlexandre Belloni 	info->pctl = devm_pinctrl_register(&pdev->dev, info->desc, info);
566ce8dc094SAlexandre Belloni 	if (IS_ERR(info->pctl)) {
567ce8dc094SAlexandre Belloni 		dev_err(&pdev->dev, "Failed to register pinctrl\n");
568ce8dc094SAlexandre Belloni 		return PTR_ERR(info->pctl);
569ce8dc094SAlexandre Belloni 	}
570ce8dc094SAlexandre Belloni 
571ce8dc094SAlexandre Belloni 	return 0;
572ce8dc094SAlexandre Belloni }
573ce8dc094SAlexandre Belloni 
574ce8dc094SAlexandre Belloni static int ocelot_gpio_get(struct gpio_chip *chip, unsigned int offset)
575ce8dc094SAlexandre Belloni {
576ce8dc094SAlexandre Belloni 	struct ocelot_pinctrl *info = gpiochip_get_data(chip);
577ce8dc094SAlexandre Belloni 	unsigned int val;
578ce8dc094SAlexandre Belloni 
579da801ab5SAlexandre Belloni 	regmap_read(info->map, REG(OCELOT_GPIO_IN, info, offset), &val);
580ce8dc094SAlexandre Belloni 
581da801ab5SAlexandre Belloni 	return !!(val & BIT(offset % 32));
582ce8dc094SAlexandre Belloni }
583ce8dc094SAlexandre Belloni 
584ce8dc094SAlexandre Belloni static void ocelot_gpio_set(struct gpio_chip *chip, unsigned int offset,
585ce8dc094SAlexandre Belloni 			    int value)
586ce8dc094SAlexandre Belloni {
587ce8dc094SAlexandre Belloni 	struct ocelot_pinctrl *info = gpiochip_get_data(chip);
588ce8dc094SAlexandre Belloni 
589ce8dc094SAlexandre Belloni 	if (value)
590da801ab5SAlexandre Belloni 		regmap_write(info->map, REG(OCELOT_GPIO_OUT_SET, info, offset),
591da801ab5SAlexandre Belloni 			     BIT(offset % 32));
592ce8dc094SAlexandre Belloni 	else
593da801ab5SAlexandre Belloni 		regmap_write(info->map, REG(OCELOT_GPIO_OUT_CLR, info, offset),
594da801ab5SAlexandre Belloni 			     BIT(offset % 32));
595ce8dc094SAlexandre Belloni }
596ce8dc094SAlexandre Belloni 
597ce8dc094SAlexandre Belloni static int ocelot_gpio_get_direction(struct gpio_chip *chip,
598ce8dc094SAlexandre Belloni 				     unsigned int offset)
599ce8dc094SAlexandre Belloni {
600ce8dc094SAlexandre Belloni 	struct ocelot_pinctrl *info = gpiochip_get_data(chip);
601ce8dc094SAlexandre Belloni 	unsigned int val;
602ce8dc094SAlexandre Belloni 
603da801ab5SAlexandre Belloni 	regmap_read(info->map, REG(OCELOT_GPIO_OE, info, offset), &val);
604ce8dc094SAlexandre Belloni 
605da801ab5SAlexandre Belloni 	return !(val & BIT(offset % 32));
606ce8dc094SAlexandre Belloni }
607ce8dc094SAlexandre Belloni 
608ce8dc094SAlexandre Belloni static int ocelot_gpio_direction_input(struct gpio_chip *chip,
609ce8dc094SAlexandre Belloni 				       unsigned int offset)
610ce8dc094SAlexandre Belloni {
611ce8dc094SAlexandre Belloni 	return pinctrl_gpio_direction_input(chip->base + offset);
612ce8dc094SAlexandre Belloni }
613ce8dc094SAlexandre Belloni 
614ce8dc094SAlexandre Belloni static int ocelot_gpio_direction_output(struct gpio_chip *chip,
615ce8dc094SAlexandre Belloni 					unsigned int offset, int value)
616ce8dc094SAlexandre Belloni {
617ce8dc094SAlexandre Belloni 	struct ocelot_pinctrl *info = gpiochip_get_data(chip);
618da801ab5SAlexandre Belloni 	unsigned int pin = BIT(offset % 32);
619ce8dc094SAlexandre Belloni 
620ce8dc094SAlexandre Belloni 	if (value)
621da801ab5SAlexandre Belloni 		regmap_write(info->map, REG(OCELOT_GPIO_OUT_SET, info, offset),
622da801ab5SAlexandre Belloni 			     pin);
623ce8dc094SAlexandre Belloni 	else
624da801ab5SAlexandre Belloni 		regmap_write(info->map, REG(OCELOT_GPIO_OUT_CLR, info, offset),
625da801ab5SAlexandre Belloni 			     pin);
626ce8dc094SAlexandre Belloni 
627ce8dc094SAlexandre Belloni 	return pinctrl_gpio_direction_output(chip->base + offset);
628ce8dc094SAlexandre Belloni }
629ce8dc094SAlexandre Belloni 
630ce8dc094SAlexandre Belloni static const struct gpio_chip ocelot_gpiolib_chip = {
631ce8dc094SAlexandre Belloni 	.request = gpiochip_generic_request,
632ce8dc094SAlexandre Belloni 	.free = gpiochip_generic_free,
633ce8dc094SAlexandre Belloni 	.set = ocelot_gpio_set,
634ce8dc094SAlexandre Belloni 	.get = ocelot_gpio_get,
635ce8dc094SAlexandre Belloni 	.get_direction = ocelot_gpio_get_direction,
636ce8dc094SAlexandre Belloni 	.direction_input = ocelot_gpio_direction_input,
637ce8dc094SAlexandre Belloni 	.direction_output = ocelot_gpio_direction_output,
638ce8dc094SAlexandre Belloni 	.owner = THIS_MODULE,
639ce8dc094SAlexandre Belloni };
640ce8dc094SAlexandre Belloni 
641be36abb7SQuentin Schulz static void ocelot_irq_mask(struct irq_data *data)
642be36abb7SQuentin Schulz {
643be36abb7SQuentin Schulz 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
644be36abb7SQuentin Schulz 	struct ocelot_pinctrl *info = gpiochip_get_data(chip);
645be36abb7SQuentin Schulz 	unsigned int gpio = irqd_to_hwirq(data);
646be36abb7SQuentin Schulz 
647da801ab5SAlexandre Belloni 	regmap_update_bits(info->map, REG(OCELOT_GPIO_INTR_ENA, info, gpio),
648da801ab5SAlexandre Belloni 			   BIT(gpio % 32), 0);
649be36abb7SQuentin Schulz }
650be36abb7SQuentin Schulz 
651be36abb7SQuentin Schulz static void ocelot_irq_unmask(struct irq_data *data)
652be36abb7SQuentin Schulz {
653be36abb7SQuentin Schulz 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
654be36abb7SQuentin Schulz 	struct ocelot_pinctrl *info = gpiochip_get_data(chip);
655be36abb7SQuentin Schulz 	unsigned int gpio = irqd_to_hwirq(data);
656be36abb7SQuentin Schulz 
657da801ab5SAlexandre Belloni 	regmap_update_bits(info->map, REG(OCELOT_GPIO_INTR_ENA, info, gpio),
658da801ab5SAlexandre Belloni 			   BIT(gpio % 32), BIT(gpio % 32));
659be36abb7SQuentin Schulz }
660be36abb7SQuentin Schulz 
661be36abb7SQuentin Schulz static void ocelot_irq_ack(struct irq_data *data)
662be36abb7SQuentin Schulz {
663be36abb7SQuentin Schulz 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
664be36abb7SQuentin Schulz 	struct ocelot_pinctrl *info = gpiochip_get_data(chip);
665be36abb7SQuentin Schulz 	unsigned int gpio = irqd_to_hwirq(data);
666be36abb7SQuentin Schulz 
667da801ab5SAlexandre Belloni 	regmap_write_bits(info->map, REG(OCELOT_GPIO_INTR, info, gpio),
668da801ab5SAlexandre Belloni 			  BIT(gpio % 32), BIT(gpio % 32));
669be36abb7SQuentin Schulz }
670be36abb7SQuentin Schulz 
671be36abb7SQuentin Schulz static int ocelot_irq_set_type(struct irq_data *data, unsigned int type);
672be36abb7SQuentin Schulz 
673be36abb7SQuentin Schulz static struct irq_chip ocelot_eoi_irqchip = {
674be36abb7SQuentin Schulz 	.name		= "gpio",
675be36abb7SQuentin Schulz 	.irq_mask	= ocelot_irq_mask,
676be36abb7SQuentin Schulz 	.irq_eoi	= ocelot_irq_ack,
677be36abb7SQuentin Schulz 	.irq_unmask	= ocelot_irq_unmask,
678be36abb7SQuentin Schulz 	.flags          = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED,
679be36abb7SQuentin Schulz 	.irq_set_type	= ocelot_irq_set_type,
680be36abb7SQuentin Schulz };
681be36abb7SQuentin Schulz 
682be36abb7SQuentin Schulz static struct irq_chip ocelot_irqchip = {
683be36abb7SQuentin Schulz 	.name		= "gpio",
684be36abb7SQuentin Schulz 	.irq_mask	= ocelot_irq_mask,
685be36abb7SQuentin Schulz 	.irq_ack	= ocelot_irq_ack,
686be36abb7SQuentin Schulz 	.irq_unmask	= ocelot_irq_unmask,
687be36abb7SQuentin Schulz 	.irq_set_type	= ocelot_irq_set_type,
688be36abb7SQuentin Schulz };
689be36abb7SQuentin Schulz 
690be36abb7SQuentin Schulz static int ocelot_irq_set_type(struct irq_data *data, unsigned int type)
691be36abb7SQuentin Schulz {
692be36abb7SQuentin Schulz 	type &= IRQ_TYPE_SENSE_MASK;
693be36abb7SQuentin Schulz 
694be36abb7SQuentin Schulz 	if (!(type & (IRQ_TYPE_EDGE_BOTH | IRQ_TYPE_LEVEL_HIGH)))
695be36abb7SQuentin Schulz 		return -EINVAL;
696be36abb7SQuentin Schulz 
697be36abb7SQuentin Schulz 	if (type & IRQ_TYPE_LEVEL_HIGH)
698be36abb7SQuentin Schulz 		irq_set_chip_handler_name_locked(data, &ocelot_eoi_irqchip,
699be36abb7SQuentin Schulz 						 handle_fasteoi_irq, NULL);
700be36abb7SQuentin Schulz 	if (type & IRQ_TYPE_EDGE_BOTH)
701be36abb7SQuentin Schulz 		irq_set_chip_handler_name_locked(data, &ocelot_irqchip,
702be36abb7SQuentin Schulz 						 handle_edge_irq, NULL);
703be36abb7SQuentin Schulz 
704be36abb7SQuentin Schulz 	return 0;
705be36abb7SQuentin Schulz }
706be36abb7SQuentin Schulz 
707be36abb7SQuentin Schulz static void ocelot_irq_handler(struct irq_desc *desc)
708be36abb7SQuentin Schulz {
709be36abb7SQuentin Schulz 	struct irq_chip *parent_chip = irq_desc_get_chip(desc);
710be36abb7SQuentin Schulz 	struct gpio_chip *chip = irq_desc_get_handler_data(desc);
711be36abb7SQuentin Schulz 	struct ocelot_pinctrl *info = gpiochip_get_data(chip);
712da801ab5SAlexandre Belloni 	unsigned int reg = 0, irq, i;
713be36abb7SQuentin Schulz 	unsigned long irqs;
714be36abb7SQuentin Schulz 
715da801ab5SAlexandre Belloni 	for (i = 0; i < info->stride; i++) {
716da801ab5SAlexandre Belloni 		regmap_read(info->map, OCELOT_GPIO_INTR_IDENT + 4 * i, &reg);
717be36abb7SQuentin Schulz 		if (!reg)
718da801ab5SAlexandre Belloni 			continue;
719be36abb7SQuentin Schulz 
720be36abb7SQuentin Schulz 		chained_irq_enter(parent_chip, desc);
721be36abb7SQuentin Schulz 
722be36abb7SQuentin Schulz 		irqs = reg;
723be36abb7SQuentin Schulz 
724da801ab5SAlexandre Belloni 		for_each_set_bit(irq, &irqs,
725da801ab5SAlexandre Belloni 				 min(32U, info->desc->npins - 32 * i))
726da801ab5SAlexandre Belloni 			generic_handle_irq(irq_linear_revmap(chip->irq.domain,
727da801ab5SAlexandre Belloni 							     irq + 32 * i));
728be36abb7SQuentin Schulz 
729be36abb7SQuentin Schulz 		chained_irq_exit(parent_chip, desc);
730be36abb7SQuentin Schulz 	}
731da801ab5SAlexandre Belloni }
732be36abb7SQuentin Schulz 
733ce8dc094SAlexandre Belloni static int ocelot_gpiochip_register(struct platform_device *pdev,
734ce8dc094SAlexandre Belloni 				    struct ocelot_pinctrl *info)
735ce8dc094SAlexandre Belloni {
736ce8dc094SAlexandre Belloni 	struct gpio_chip *gc;
737be36abb7SQuentin Schulz 	int ret, irq;
738ce8dc094SAlexandre Belloni 
739ce8dc094SAlexandre Belloni 	info->gpio_chip = ocelot_gpiolib_chip;
740ce8dc094SAlexandre Belloni 
741ce8dc094SAlexandre Belloni 	gc = &info->gpio_chip;
742da801ab5SAlexandre Belloni 	gc->ngpio = info->desc->npins;
743ce8dc094SAlexandre Belloni 	gc->parent = &pdev->dev;
744ce8dc094SAlexandre Belloni 	gc->base = 0;
745ce8dc094SAlexandre Belloni 	gc->of_node = info->dev->of_node;
746ce8dc094SAlexandre Belloni 	gc->label = "ocelot-gpio";
747ce8dc094SAlexandre Belloni 
748ce8dc094SAlexandre Belloni 	ret = devm_gpiochip_add_data(&pdev->dev, gc, info);
749ce8dc094SAlexandre Belloni 	if (ret)
750ce8dc094SAlexandre Belloni 		return ret;
751ce8dc094SAlexandre Belloni 
752be36abb7SQuentin Schulz 	irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
753be36abb7SQuentin Schulz 	if (irq <= 0)
754be36abb7SQuentin Schulz 		return irq;
755be36abb7SQuentin Schulz 
756be36abb7SQuentin Schulz 	ret = gpiochip_irqchip_add(gc, &ocelot_irqchip, 0, handle_edge_irq,
757be36abb7SQuentin Schulz 				   IRQ_TYPE_NONE);
758be36abb7SQuentin Schulz 	if (ret)
759be36abb7SQuentin Schulz 		return ret;
760be36abb7SQuentin Schulz 
761be36abb7SQuentin Schulz 	gpiochip_set_chained_irqchip(gc, &ocelot_irqchip, irq,
762be36abb7SQuentin Schulz 				     ocelot_irq_handler);
763ce8dc094SAlexandre Belloni 
764ce8dc094SAlexandre Belloni 	return 0;
765ce8dc094SAlexandre Belloni }
766ce8dc094SAlexandre Belloni 
767ce8dc094SAlexandre Belloni static const struct of_device_id ocelot_pinctrl_of_match[] = {
768da801ab5SAlexandre Belloni 	{ .compatible = "mscc,ocelot-pinctrl", .data = &ocelot_desc },
769da801ab5SAlexandre Belloni 	{ .compatible = "mscc,jaguar2-pinctrl", .data = &jaguar2_desc },
770ce8dc094SAlexandre Belloni 	{},
771ce8dc094SAlexandre Belloni };
772ce8dc094SAlexandre Belloni 
773ce3e7f0eSColin Ian King static int ocelot_pinctrl_probe(struct platform_device *pdev)
774ce8dc094SAlexandre Belloni {
775ce8dc094SAlexandre Belloni 	struct device *dev = &pdev->dev;
776ce8dc094SAlexandre Belloni 	struct ocelot_pinctrl *info;
777ce8dc094SAlexandre Belloni 	void __iomem *base;
778ce8dc094SAlexandre Belloni 	int ret;
779da801ab5SAlexandre Belloni 	struct regmap_config regmap_config = {
780da801ab5SAlexandre Belloni 		.reg_bits = 32,
781da801ab5SAlexandre Belloni 		.val_bits = 32,
782da801ab5SAlexandre Belloni 		.reg_stride = 4,
783da801ab5SAlexandre Belloni 	};
784ce8dc094SAlexandre Belloni 
785ce8dc094SAlexandre Belloni 	info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
786ce8dc094SAlexandre Belloni 	if (!info)
787ce8dc094SAlexandre Belloni 		return -ENOMEM;
788ce8dc094SAlexandre Belloni 
789da801ab5SAlexandre Belloni 	info->desc = (struct pinctrl_desc *)device_get_match_data(dev);
790da801ab5SAlexandre Belloni 
791ce8dc094SAlexandre Belloni 	base = devm_ioremap_resource(dev,
792ce8dc094SAlexandre Belloni 			platform_get_resource(pdev, IORESOURCE_MEM, 0));
793ce8dc094SAlexandre Belloni 	if (IS_ERR(base)) {
794ce8dc094SAlexandre Belloni 		dev_err(dev, "Failed to ioremap registers\n");
795ce8dc094SAlexandre Belloni 		return PTR_ERR(base);
796ce8dc094SAlexandre Belloni 	}
797ce8dc094SAlexandre Belloni 
798da801ab5SAlexandre Belloni 	info->stride = 1 + (info->desc->npins - 1) / 32;
799da801ab5SAlexandre Belloni 	regmap_config.max_register = OCELOT_GPIO_SD_MAP * info->stride + 15 * 4;
800da801ab5SAlexandre Belloni 
801da801ab5SAlexandre Belloni 	info->map = devm_regmap_init_mmio(dev, base, &regmap_config);
802ce8dc094SAlexandre Belloni 	if (IS_ERR(info->map)) {
803ce8dc094SAlexandre Belloni 		dev_err(dev, "Failed to create regmap\n");
804ce8dc094SAlexandre Belloni 		return PTR_ERR(info->map);
805ce8dc094SAlexandre Belloni 	}
806ce8dc094SAlexandre Belloni 	dev_set_drvdata(dev, info->map);
807ce8dc094SAlexandre Belloni 	info->dev = dev;
808ce8dc094SAlexandre Belloni 
809ce8dc094SAlexandre Belloni 	ret = ocelot_pinctrl_register(pdev, info);
810ce8dc094SAlexandre Belloni 	if (ret)
811ce8dc094SAlexandre Belloni 		return ret;
812ce8dc094SAlexandre Belloni 
813ce8dc094SAlexandre Belloni 	ret = ocelot_gpiochip_register(pdev, info);
814ce8dc094SAlexandre Belloni 	if (ret)
815ce8dc094SAlexandre Belloni 		return ret;
816ce8dc094SAlexandre Belloni 
817ce8dc094SAlexandre Belloni 	return 0;
818ce8dc094SAlexandre Belloni }
819ce8dc094SAlexandre Belloni 
820ce8dc094SAlexandre Belloni static struct platform_driver ocelot_pinctrl_driver = {
821ce8dc094SAlexandre Belloni 	.driver = {
822ce8dc094SAlexandre Belloni 		.name = "pinctrl-ocelot",
823ce8dc094SAlexandre Belloni 		.of_match_table = of_match_ptr(ocelot_pinctrl_of_match),
824ce8dc094SAlexandre Belloni 		.suppress_bind_attrs = true,
825ce8dc094SAlexandre Belloni 	},
826ce8dc094SAlexandre Belloni 	.probe = ocelot_pinctrl_probe,
827ce8dc094SAlexandre Belloni };
828ce8dc094SAlexandre Belloni builtin_platform_driver(ocelot_pinctrl_driver);
829