xref: /linux/drivers/pinctrl/pinctrl-eyeq5.c (revision 3a39d672e7f48b8d6b91a09afa4b55352773b4b5)
1*41795aa1SThéo Lebrun // SPDX-License-Identifier: GPL-2.0-only
2*41795aa1SThéo Lebrun /*
3*41795aa1SThéo Lebrun  * Pinctrl driver for the Mobileye EyeQ5 platform.
4*41795aa1SThéo Lebrun  *
5*41795aa1SThéo Lebrun  * The registers are located in a syscon region called OLB. There are two pin
6*41795aa1SThéo Lebrun  * banks, each being controlled by 5 registers (see enum eq5p_regs) for
7*41795aa1SThéo Lebrun  * pull-down, pull-up, drive strength and muxing.
8*41795aa1SThéo Lebrun  *
9*41795aa1SThéo Lebrun  * For each pin, muxing is between two functions: (0) GPIO or (1) another one
10*41795aa1SThéo Lebrun  * that is pin-dependent. Functions are declared statically in this driver.
11*41795aa1SThéo Lebrun  *
12*41795aa1SThéo Lebrun  * We create pinctrl groups that are 1:1 equivalent to pins: each group has a
13*41795aa1SThéo Lebrun  * single pin, and its index/selector is the pin number.
14*41795aa1SThéo Lebrun  *
15*41795aa1SThéo Lebrun  * We use eq5p_ as prefix, as-in "EyeQ5 Pinctrl", but way shorter.
16*41795aa1SThéo Lebrun  *
17*41795aa1SThéo Lebrun  * Copyright (C) 2024 Mobileye Vision Technologies Ltd.
18*41795aa1SThéo Lebrun  */
19*41795aa1SThéo Lebrun 
20*41795aa1SThéo Lebrun #include <linux/array_size.h>
21*41795aa1SThéo Lebrun #include <linux/auxiliary_bus.h>
22*41795aa1SThéo Lebrun #include <linux/bits.h>
23*41795aa1SThéo Lebrun #include <linux/bug.h>
24*41795aa1SThéo Lebrun #include <linux/device.h>
25*41795aa1SThéo Lebrun #include <linux/err.h>
26*41795aa1SThéo Lebrun #include <linux/errno.h>
27*41795aa1SThéo Lebrun #include <linux/io.h>
28*41795aa1SThéo Lebrun #include <linux/mod_devicetable.h>
29*41795aa1SThéo Lebrun #include <linux/seq_file.h>
30*41795aa1SThéo Lebrun #include <linux/slab.h>
31*41795aa1SThéo Lebrun #include <linux/types.h>
32*41795aa1SThéo Lebrun 
33*41795aa1SThéo Lebrun #include <linux/pinctrl/pinconf-generic.h>
34*41795aa1SThéo Lebrun #include <linux/pinctrl/pinconf.h>
35*41795aa1SThéo Lebrun #include <linux/pinctrl/pinctrl.h>
36*41795aa1SThéo Lebrun #include <linux/pinctrl/pinmux.h>
37*41795aa1SThéo Lebrun 
38*41795aa1SThéo Lebrun #include "core.h"
39*41795aa1SThéo Lebrun #include "pinctrl-utils.h"
40*41795aa1SThéo Lebrun 
41*41795aa1SThéo Lebrun struct eq5p_pinctrl {
42*41795aa1SThéo Lebrun 	struct pinctrl_desc	desc;
43*41795aa1SThéo Lebrun 	void __iomem		*base;
44*41795aa1SThéo Lebrun };
45*41795aa1SThéo Lebrun 
46*41795aa1SThéo Lebrun enum eq5p_bank {
47*41795aa1SThéo Lebrun 	EQ5P_BANK_A,
48*41795aa1SThéo Lebrun 	EQ5P_BANK_B,
49*41795aa1SThéo Lebrun 
50*41795aa1SThéo Lebrun 	EQ5P_BANK_COUNT,
51*41795aa1SThéo Lebrun };
52*41795aa1SThéo Lebrun 
53*41795aa1SThéo Lebrun enum eq5p_regs {
54*41795aa1SThéo Lebrun 	EQ5P_PD,
55*41795aa1SThéo Lebrun 	EQ5P_PU,
56*41795aa1SThéo Lebrun 	EQ5P_DS_LOW,
57*41795aa1SThéo Lebrun 	EQ5P_DS_HIGH,
58*41795aa1SThéo Lebrun 	EQ5P_IOCR,
59*41795aa1SThéo Lebrun 
60*41795aa1SThéo Lebrun 	EQ5P_REG_COUNT,
61*41795aa1SThéo Lebrun };
62*41795aa1SThéo Lebrun 
63*41795aa1SThéo Lebrun static const unsigned int eq5p_regs[EQ5P_BANK_COUNT][EQ5P_REG_COUNT] = {
64*41795aa1SThéo Lebrun 	[EQ5P_BANK_A] = {0x0C0, 0x0C4, 0x0D0, 0x0D4, 0x0B0},
65*41795aa1SThéo Lebrun 	[EQ5P_BANK_B] = {0x0C8, 0x0CC, 0x0D8, 0x0DC, 0x0B4},
66*41795aa1SThéo Lebrun };
67*41795aa1SThéo Lebrun 
68*41795aa1SThéo Lebrun /*
69*41795aa1SThéo Lebrun  * Drive strength; two bits per pin.
70*41795aa1SThéo Lebrun  */
71*41795aa1SThéo Lebrun #define EQ5P_DS_MASK	GENMASK(1, 0)
72*41795aa1SThéo Lebrun 
73*41795aa1SThéo Lebrun /*
74*41795aa1SThéo Lebrun  * Comments to the right of each pin are the "signal name" in the datasheet.
75*41795aa1SThéo Lebrun  */
76*41795aa1SThéo Lebrun static const struct pinctrl_pin_desc eq5p_pins[] = {
77*41795aa1SThéo Lebrun 	/* Bank A */
78*41795aa1SThéo Lebrun 	PINCTRL_PIN(0,  "PA0"),  /* A0_TIMER0_CK */
79*41795aa1SThéo Lebrun 	PINCTRL_PIN(1,  "PA1"),  /* A1_TIMER0_EOC */
80*41795aa1SThéo Lebrun 	PINCTRL_PIN(2,  "PA2"),  /* A2_TIMER1_CK */
81*41795aa1SThéo Lebrun 	PINCTRL_PIN(3,  "PA3"),  /* A3_TIMER1_EOC */
82*41795aa1SThéo Lebrun 	PINCTRL_PIN(4,  "PA4"),  /* A4_TIMER2_CK */
83*41795aa1SThéo Lebrun 	PINCTRL_PIN(5,  "PA5"),  /* A5_TIMER2_EOC */
84*41795aa1SThéo Lebrun 	PINCTRL_PIN(6,  "PA6"),  /* A6_TIMER5_EXT_INCAP1 */
85*41795aa1SThéo Lebrun 	PINCTRL_PIN(7,  "PA7"),  /* A7_TIMER5_EXT_INCAP2 */
86*41795aa1SThéo Lebrun 	PINCTRL_PIN(8,  "PA8"),  /* A8_TIMER5_EXT_OUTCMP1 */
87*41795aa1SThéo Lebrun 	PINCTRL_PIN(9,  "PA9"),  /* A9_TIMER5_EXT_OUTCMP2 */
88*41795aa1SThéo Lebrun 	PINCTRL_PIN(10, "PA10"), /* A10_UART_0_TX */
89*41795aa1SThéo Lebrun 	PINCTRL_PIN(11, "PA11"), /* A11_UART_0_RX */
90*41795aa1SThéo Lebrun 	PINCTRL_PIN(12, "PA12"), /* A12_UART_1_TX */
91*41795aa1SThéo Lebrun 	PINCTRL_PIN(13, "PA13"), /* A13_UART_1_RX */
92*41795aa1SThéo Lebrun 	PINCTRL_PIN(14, "PA14"), /* A14_CAN_0_TX */
93*41795aa1SThéo Lebrun 	PINCTRL_PIN(15, "PA15"), /* A15_CAN_0_RX */
94*41795aa1SThéo Lebrun 	PINCTRL_PIN(16, "PA16"), /* A16_CAN_1_TX */
95*41795aa1SThéo Lebrun 	PINCTRL_PIN(17, "PA17"), /* A17_CAN_1_RX */
96*41795aa1SThéo Lebrun 	PINCTRL_PIN(18, "PA18"), /* A18_SPI_0_DO */
97*41795aa1SThéo Lebrun 	PINCTRL_PIN(19, "PA19"), /* A19_SPI_0_DI */
98*41795aa1SThéo Lebrun 	PINCTRL_PIN(20, "PA20"), /* A20_SPI_0_CK */
99*41795aa1SThéo Lebrun 	PINCTRL_PIN(21, "PA21"), /* A21_SPI_0_CS0 */
100*41795aa1SThéo Lebrun 	PINCTRL_PIN(22, "PA22"), /* A22_SPI_0_CS1 */
101*41795aa1SThéo Lebrun 	PINCTRL_PIN(23, "PA23"), /* A23_SPI_1_DO */
102*41795aa1SThéo Lebrun 	PINCTRL_PIN(24, "PA24"), /* A24_SPI_1_DI */
103*41795aa1SThéo Lebrun 	PINCTRL_PIN(25, "PA25"), /* A25_SPI_1_CK */
104*41795aa1SThéo Lebrun 	PINCTRL_PIN(26, "PA26"), /* A26_SPI_1_CS0 */
105*41795aa1SThéo Lebrun 	PINCTRL_PIN(27, "PA27"), /* A27_SPI_1_CS1 */
106*41795aa1SThéo Lebrun 	PINCTRL_PIN(28, "PA28"), /* A28_REF_CLK0 */
107*41795aa1SThéo Lebrun 
108*41795aa1SThéo Lebrun #define EQ5P_PIN_OFFSET_BANK_B	29
109*41795aa1SThéo Lebrun 
110*41795aa1SThéo Lebrun 	/* Bank B */
111*41795aa1SThéo Lebrun 	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 0,  "PB0"),  /* B0_TIMER3_CK */
112*41795aa1SThéo Lebrun 	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 1,  "PB1"),  /* B1_TIMER3_EOC */
113*41795aa1SThéo Lebrun 	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 2,  "PB2"),  /* B2_TIMER4_CK */
114*41795aa1SThéo Lebrun 	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 3,  "PB3"),  /* B3_TIMER4_EOC */
115*41795aa1SThéo Lebrun 	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 4,  "PB4"),  /* B4_TIMER6_EXT_INCAP1 */
116*41795aa1SThéo Lebrun 	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 5,  "PB5"),  /* B5_TIMER6_EXT_INCAP2 */
117*41795aa1SThéo Lebrun 	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 6,  "PB6"),  /* B6_TIMER6_EXT_OUTCMP1 */
118*41795aa1SThéo Lebrun 	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 7,  "PB7"),  /* B7_TIMER6_EXT_OUTCMP2 */
119*41795aa1SThéo Lebrun 	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 8,  "PB8"),  /* B8_UART_2_TX */
120*41795aa1SThéo Lebrun 	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 9,  "PB9"),  /* B9_UART_2_RX */
121*41795aa1SThéo Lebrun 	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 10, "PB10"), /* B10_CAN_2_TX */
122*41795aa1SThéo Lebrun 	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 11, "PB11"), /* B11_CAN_2_RX */
123*41795aa1SThéo Lebrun 	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 12, "PB12"), /* B12_SPI_2_DO */
124*41795aa1SThéo Lebrun 	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 13, "PB13"), /* B13_SPI_2_DI */
125*41795aa1SThéo Lebrun 	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 14, "PB14"), /* B14_SPI_2_CK */
126*41795aa1SThéo Lebrun 	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 15, "PB15"), /* B15_SPI_2_CS0 */
127*41795aa1SThéo Lebrun 	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 16, "PB16"), /* B16_SPI_2_CS1 */
128*41795aa1SThéo Lebrun 	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 17, "PB17"), /* B17_SPI_3_DO */
129*41795aa1SThéo Lebrun 	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 18, "PB18"), /* B18_SPI_3_DI */
130*41795aa1SThéo Lebrun 	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 19, "PB19"), /* B19_SPI_3_CK */
131*41795aa1SThéo Lebrun 	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 20, "PB20"), /* B20_SPI_3_CS0 */
132*41795aa1SThéo Lebrun 	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 21, "PB21"), /* B21_SPI_3_CS1 */
133*41795aa1SThéo Lebrun 	PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 22, "PB22"), /* B22_MCLK0 */
134*41795aa1SThéo Lebrun };
135*41795aa1SThéo Lebrun 
136*41795aa1SThéo Lebrun static const char * const gpio_groups[] = {
137*41795aa1SThéo Lebrun 	/* Bank A */
138*41795aa1SThéo Lebrun 	"PA0",  "PA1",  "PA2",  "PA3",  "PA4",  "PA5",  "PA6",  "PA7",
139*41795aa1SThéo Lebrun 	"PA8",  "PA9",  "PA10", "PA11", "PA12", "PA13", "PA14", "PA15",
140*41795aa1SThéo Lebrun 	"PA16", "PA17", "PA18", "PA19", "PA20", "PA21", "PA22", "PA23",
141*41795aa1SThéo Lebrun 	"PA24", "PA25", "PA26", "PA27", "PA28",
142*41795aa1SThéo Lebrun 
143*41795aa1SThéo Lebrun 	/* Bank B */
144*41795aa1SThéo Lebrun 	"PB0",  "PB1",  "PB2",  "PB3",  "PB4",  "PB5",  "PB6",  "PB7",
145*41795aa1SThéo Lebrun 	"PB8",  "PB9",  "PB10", "PB11", "PB12", "PB13", "PB14", "PB15",
146*41795aa1SThéo Lebrun 	"PB16", "PB17", "PB18", "PB19", "PB20", "PB21", "PB22",
147*41795aa1SThéo Lebrun };
148*41795aa1SThéo Lebrun 
149*41795aa1SThéo Lebrun /* Groups of functions on bank A */
150*41795aa1SThéo Lebrun static const char * const timer0_groups[] = { "PA0", "PA1" };
151*41795aa1SThéo Lebrun static const char * const timer1_groups[] = { "PA2", "PA3" };
152*41795aa1SThéo Lebrun static const char * const timer2_groups[] = { "PA4", "PA5" };
153*41795aa1SThéo Lebrun static const char * const timer5_groups[] = { "PA6", "PA7", "PA8", "PA9" };
154*41795aa1SThéo Lebrun static const char * const uart0_groups[] = { "PA10", "PA11" };
155*41795aa1SThéo Lebrun static const char * const uart1_groups[] = { "PA12", "PA13" };
156*41795aa1SThéo Lebrun static const char * const can0_groups[] = { "PA14", "PA15" };
157*41795aa1SThéo Lebrun static const char * const can1_groups[] = { "PA16", "PA17" };
158*41795aa1SThéo Lebrun static const char * const spi0_groups[] = { "PA18", "PA19", "PA20", "PA21", "PA22" };
159*41795aa1SThéo Lebrun static const char * const spi1_groups[] = { "PA23", "PA24", "PA25", "PA26", "PA27" };
160*41795aa1SThéo Lebrun static const char * const refclk0_groups[] = { "PA28" };
161*41795aa1SThéo Lebrun 
162*41795aa1SThéo Lebrun /* Groups of functions on bank B */
163*41795aa1SThéo Lebrun static const char * const timer3_groups[] = { "PB0", "PB1" };
164*41795aa1SThéo Lebrun static const char * const timer4_groups[] = { "PB2", "PB3" };
165*41795aa1SThéo Lebrun static const char * const timer6_groups[] = { "PB4", "PB5", "PB6", "PB7" };
166*41795aa1SThéo Lebrun static const char * const uart2_groups[] = { "PB8", "PB9" };
167*41795aa1SThéo Lebrun static const char * const can2_groups[] = { "PB10", "PB11" };
168*41795aa1SThéo Lebrun static const char * const spi2_groups[] = { "PB12", "PB13", "PB14", "PB15", "PB16" };
169*41795aa1SThéo Lebrun static const char * const spi3_groups[] = { "PB17", "PB18", "PB19", "PB20", "PB21" };
170*41795aa1SThéo Lebrun static const char * const mclk0_groups[] = { "PB22" };
171*41795aa1SThéo Lebrun 
172*41795aa1SThéo Lebrun static const struct pinfunction eq5p_functions[] = {
173*41795aa1SThéo Lebrun 	/* GPIO having a fixed index is depended upon, see GPIO_FUNC_SELECTOR. */
174*41795aa1SThéo Lebrun 	PINCTRL_PINFUNCTION("gpio", gpio_groups, ARRAY_SIZE(gpio_groups)),
175*41795aa1SThéo Lebrun #define GPIO_FUNC_SELECTOR 0
176*41795aa1SThéo Lebrun 
177*41795aa1SThéo Lebrun 	/* Bank A functions */
178*41795aa1SThéo Lebrun 	PINCTRL_PINFUNCTION("timer0", timer0_groups, ARRAY_SIZE(timer0_groups)),
179*41795aa1SThéo Lebrun 	PINCTRL_PINFUNCTION("timer1", timer1_groups, ARRAY_SIZE(timer1_groups)),
180*41795aa1SThéo Lebrun 	PINCTRL_PINFUNCTION("timer2", timer2_groups, ARRAY_SIZE(timer2_groups)),
181*41795aa1SThéo Lebrun 	PINCTRL_PINFUNCTION("timer5", timer5_groups, ARRAY_SIZE(timer5_groups)),
182*41795aa1SThéo Lebrun 	PINCTRL_PINFUNCTION("uart0", uart0_groups, ARRAY_SIZE(uart0_groups)),
183*41795aa1SThéo Lebrun 	PINCTRL_PINFUNCTION("uart1", uart1_groups, ARRAY_SIZE(uart1_groups)),
184*41795aa1SThéo Lebrun 	PINCTRL_PINFUNCTION("can0", can0_groups, ARRAY_SIZE(can0_groups)),
185*41795aa1SThéo Lebrun 	PINCTRL_PINFUNCTION("can1", can1_groups, ARRAY_SIZE(can1_groups)),
186*41795aa1SThéo Lebrun 	PINCTRL_PINFUNCTION("spi0", spi0_groups, ARRAY_SIZE(spi0_groups)),
187*41795aa1SThéo Lebrun 	PINCTRL_PINFUNCTION("spi1", spi1_groups, ARRAY_SIZE(spi1_groups)),
188*41795aa1SThéo Lebrun 	PINCTRL_PINFUNCTION("refclk0", refclk0_groups, ARRAY_SIZE(refclk0_groups)),
189*41795aa1SThéo Lebrun 
190*41795aa1SThéo Lebrun 	/* Bank B functions */
191*41795aa1SThéo Lebrun 	PINCTRL_PINFUNCTION("timer3", timer3_groups, ARRAY_SIZE(timer3_groups)),
192*41795aa1SThéo Lebrun 	PINCTRL_PINFUNCTION("timer4", timer4_groups, ARRAY_SIZE(timer4_groups)),
193*41795aa1SThéo Lebrun 	PINCTRL_PINFUNCTION("timer6", timer6_groups, ARRAY_SIZE(timer6_groups)),
194*41795aa1SThéo Lebrun 	PINCTRL_PINFUNCTION("uart2", uart2_groups, ARRAY_SIZE(uart2_groups)),
195*41795aa1SThéo Lebrun 	PINCTRL_PINFUNCTION("can2", can2_groups, ARRAY_SIZE(can2_groups)),
196*41795aa1SThéo Lebrun 	PINCTRL_PINFUNCTION("spi2", spi2_groups, ARRAY_SIZE(spi2_groups)),
197*41795aa1SThéo Lebrun 	PINCTRL_PINFUNCTION("spi3", spi3_groups, ARRAY_SIZE(spi3_groups)),
198*41795aa1SThéo Lebrun 	PINCTRL_PINFUNCTION("mclk0", mclk0_groups, ARRAY_SIZE(mclk0_groups)),
199*41795aa1SThéo Lebrun };
200*41795aa1SThéo Lebrun 
eq5p_update_bits(const struct eq5p_pinctrl * pctrl,enum eq5p_bank bank,enum eq5p_regs reg,u32 mask,u32 val)201*41795aa1SThéo Lebrun static void eq5p_update_bits(const struct eq5p_pinctrl *pctrl,
202*41795aa1SThéo Lebrun 			     enum eq5p_bank bank, enum eq5p_regs reg,
203*41795aa1SThéo Lebrun 			     u32 mask, u32 val)
204*41795aa1SThéo Lebrun {
205*41795aa1SThéo Lebrun 	void __iomem *ptr = pctrl->base + eq5p_regs[bank][reg];
206*41795aa1SThéo Lebrun 
207*41795aa1SThéo Lebrun 	writel((readl(ptr) & ~mask) | (val & mask), ptr);
208*41795aa1SThéo Lebrun }
209*41795aa1SThéo Lebrun 
eq5p_test_bit(const struct eq5p_pinctrl * pctrl,enum eq5p_bank bank,enum eq5p_regs reg,int offset)210*41795aa1SThéo Lebrun static bool eq5p_test_bit(const struct eq5p_pinctrl *pctrl,
211*41795aa1SThéo Lebrun 			  enum eq5p_bank bank, enum eq5p_regs reg, int offset)
212*41795aa1SThéo Lebrun {
213*41795aa1SThéo Lebrun 	u32 val = readl(pctrl->base + eq5p_regs[bank][reg]);
214*41795aa1SThéo Lebrun 
215*41795aa1SThéo Lebrun 	if (WARN_ON(offset > 31))
216*41795aa1SThéo Lebrun 		return false;
217*41795aa1SThéo Lebrun 
218*41795aa1SThéo Lebrun 	return (val & BIT(offset)) != 0;
219*41795aa1SThéo Lebrun }
220*41795aa1SThéo Lebrun 
eq5p_pin_to_bank(unsigned int pin)221*41795aa1SThéo Lebrun static enum eq5p_bank eq5p_pin_to_bank(unsigned int pin)
222*41795aa1SThéo Lebrun {
223*41795aa1SThéo Lebrun 	if (pin < EQ5P_PIN_OFFSET_BANK_B)
224*41795aa1SThéo Lebrun 		return EQ5P_BANK_A;
225*41795aa1SThéo Lebrun 	else
226*41795aa1SThéo Lebrun 		return EQ5P_BANK_B;
227*41795aa1SThéo Lebrun }
228*41795aa1SThéo Lebrun 
eq5p_pin_to_offset(unsigned int pin)229*41795aa1SThéo Lebrun static unsigned int eq5p_pin_to_offset(unsigned int pin)
230*41795aa1SThéo Lebrun {
231*41795aa1SThéo Lebrun 	if (pin < EQ5P_PIN_OFFSET_BANK_B)
232*41795aa1SThéo Lebrun 		return pin;
233*41795aa1SThéo Lebrun 	else
234*41795aa1SThéo Lebrun 		return pin - EQ5P_PIN_OFFSET_BANK_B;
235*41795aa1SThéo Lebrun }
236*41795aa1SThéo Lebrun 
eq5p_pinctrl_get_groups_count(struct pinctrl_dev * pctldev)237*41795aa1SThéo Lebrun static int eq5p_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
238*41795aa1SThéo Lebrun {
239*41795aa1SThéo Lebrun 	return ARRAY_SIZE(eq5p_pins);
240*41795aa1SThéo Lebrun }
241*41795aa1SThéo Lebrun 
eq5p_pinctrl_get_group_name(struct pinctrl_dev * pctldev,unsigned int selector)242*41795aa1SThéo Lebrun static const char *eq5p_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
243*41795aa1SThéo Lebrun 					       unsigned int selector)
244*41795aa1SThéo Lebrun {
245*41795aa1SThéo Lebrun 	return pctldev->desc->pins[selector].name;
246*41795aa1SThéo Lebrun }
247*41795aa1SThéo Lebrun 
eq5p_pinctrl_get_group_pins(struct pinctrl_dev * pctldev,unsigned int selector,const unsigned int ** pins,unsigned int * num_pins)248*41795aa1SThéo Lebrun static int eq5p_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
249*41795aa1SThéo Lebrun 				       unsigned int selector,
250*41795aa1SThéo Lebrun 				       const unsigned int **pins,
251*41795aa1SThéo Lebrun 				       unsigned int *num_pins)
252*41795aa1SThéo Lebrun {
253*41795aa1SThéo Lebrun 	*pins = &pctldev->desc->pins[selector].number;
254*41795aa1SThéo Lebrun 	*num_pins = 1;
255*41795aa1SThéo Lebrun 	return 0;
256*41795aa1SThéo Lebrun }
257*41795aa1SThéo Lebrun 
eq5p_pinconf_get(struct pinctrl_dev * pctldev,unsigned int pin,unsigned long * config)258*41795aa1SThéo Lebrun static int eq5p_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
259*41795aa1SThéo Lebrun 			    unsigned long *config)
260*41795aa1SThéo Lebrun {
261*41795aa1SThéo Lebrun 	enum pin_config_param param = pinconf_to_config_param(*config);
262*41795aa1SThéo Lebrun 	struct eq5p_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
263*41795aa1SThéo Lebrun 	unsigned int offset = eq5p_pin_to_offset(pin);
264*41795aa1SThéo Lebrun 	enum eq5p_bank bank = eq5p_pin_to_bank(pin);
265*41795aa1SThéo Lebrun 	u32 val_ds, arg;
266*41795aa1SThéo Lebrun 	bool pd, pu;
267*41795aa1SThéo Lebrun 
268*41795aa1SThéo Lebrun 	pd = eq5p_test_bit(pctrl, bank, EQ5P_PD, offset);
269*41795aa1SThéo Lebrun 	pu = eq5p_test_bit(pctrl, bank, EQ5P_PU, offset);
270*41795aa1SThéo Lebrun 
271*41795aa1SThéo Lebrun 	switch (param) {
272*41795aa1SThéo Lebrun 	case PIN_CONFIG_BIAS_DISABLE:
273*41795aa1SThéo Lebrun 		arg = !(pd || pu);
274*41795aa1SThéo Lebrun 		break;
275*41795aa1SThéo Lebrun 	case PIN_CONFIG_BIAS_PULL_DOWN:
276*41795aa1SThéo Lebrun 		arg = pd;
277*41795aa1SThéo Lebrun 		break;
278*41795aa1SThéo Lebrun 	case PIN_CONFIG_BIAS_PULL_UP:
279*41795aa1SThéo Lebrun 		arg = pu;
280*41795aa1SThéo Lebrun 		break;
281*41795aa1SThéo Lebrun 	case PIN_CONFIG_DRIVE_STRENGTH:
282*41795aa1SThéo Lebrun 		offset *= 2; /* two bits per pin */
283*41795aa1SThéo Lebrun 		if (offset >= 32) {
284*41795aa1SThéo Lebrun 			val_ds = readl(pctrl->base + eq5p_regs[bank][EQ5P_DS_HIGH]);
285*41795aa1SThéo Lebrun 			offset -= 32;
286*41795aa1SThéo Lebrun 		} else {
287*41795aa1SThéo Lebrun 			val_ds = readl(pctrl->base + eq5p_regs[bank][EQ5P_DS_LOW]);
288*41795aa1SThéo Lebrun 		}
289*41795aa1SThéo Lebrun 		arg = (val_ds >> offset) & EQ5P_DS_MASK;
290*41795aa1SThéo Lebrun 		break;
291*41795aa1SThéo Lebrun 	default:
292*41795aa1SThéo Lebrun 		return -ENOTSUPP;
293*41795aa1SThéo Lebrun 	}
294*41795aa1SThéo Lebrun 
295*41795aa1SThéo Lebrun 	*config = pinconf_to_config_packed(param, arg);
296*41795aa1SThéo Lebrun 	return 0;
297*41795aa1SThéo Lebrun }
298*41795aa1SThéo Lebrun 
eq5p_pinctrl_pin_dbg_show(struct pinctrl_dev * pctldev,struct seq_file * s,unsigned int pin)299*41795aa1SThéo Lebrun static void eq5p_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
300*41795aa1SThéo Lebrun 				      struct seq_file *s,
301*41795aa1SThéo Lebrun 				      unsigned int pin)
302*41795aa1SThéo Lebrun {
303*41795aa1SThéo Lebrun 	struct eq5p_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
304*41795aa1SThéo Lebrun 	const char *pin_name = pctrl->desc.pins[pin].name;
305*41795aa1SThéo Lebrun 	unsigned int offset = eq5p_pin_to_offset(pin);
306*41795aa1SThéo Lebrun 	enum eq5p_bank bank = eq5p_pin_to_bank(pin);
307*41795aa1SThéo Lebrun 	const char *func_name, *bias;
308*41795aa1SThéo Lebrun 	unsigned long ds_config;
309*41795aa1SThéo Lebrun 	u32 drive_strength;
310*41795aa1SThéo Lebrun 	bool pd, pu;
311*41795aa1SThéo Lebrun 	int i, j;
312*41795aa1SThéo Lebrun 
313*41795aa1SThéo Lebrun 	/*
314*41795aa1SThéo Lebrun 	 * First, let's get the function name. All pins have only two functions:
315*41795aa1SThéo Lebrun 	 * GPIO (IOCR == 0) and something else (IOCR == 1).
316*41795aa1SThéo Lebrun 	 */
317*41795aa1SThéo Lebrun 	if (eq5p_test_bit(pctrl, bank, EQ5P_IOCR, offset)) {
318*41795aa1SThéo Lebrun 		func_name = NULL;
319*41795aa1SThéo Lebrun 		for (i = 0; i < ARRAY_SIZE(eq5p_functions); i++) {
320*41795aa1SThéo Lebrun 			if (i == GPIO_FUNC_SELECTOR)
321*41795aa1SThéo Lebrun 				continue;
322*41795aa1SThéo Lebrun 
323*41795aa1SThéo Lebrun 			for (j = 0; j < eq5p_functions[i].ngroups; j++) {
324*41795aa1SThéo Lebrun 				/* Groups and pins are the same thing for us. */
325*41795aa1SThéo Lebrun 				const char *x = eq5p_functions[i].groups[j];
326*41795aa1SThéo Lebrun 
327*41795aa1SThéo Lebrun 				if (strcmp(x, pin_name) == 0) {
328*41795aa1SThéo Lebrun 					func_name = eq5p_functions[i].name;
329*41795aa1SThéo Lebrun 					break;
330*41795aa1SThéo Lebrun 				}
331*41795aa1SThéo Lebrun 			}
332*41795aa1SThéo Lebrun 
333*41795aa1SThéo Lebrun 			if (func_name)
334*41795aa1SThéo Lebrun 				break;
335*41795aa1SThéo Lebrun 		}
336*41795aa1SThéo Lebrun 
337*41795aa1SThéo Lebrun 		/*
338*41795aa1SThéo Lebrun 		 * We have not found the function attached to this pin, this
339*41795aa1SThéo Lebrun 		 * should never occur as all pins have exactly two functions.
340*41795aa1SThéo Lebrun 		 */
341*41795aa1SThéo Lebrun 		if (!func_name)
342*41795aa1SThéo Lebrun 			func_name = "unknown";
343*41795aa1SThéo Lebrun 	} else {
344*41795aa1SThéo Lebrun 		func_name = eq5p_functions[GPIO_FUNC_SELECTOR].name;
345*41795aa1SThéo Lebrun 	}
346*41795aa1SThéo Lebrun 
347*41795aa1SThéo Lebrun 	/* Second, we retrieve the bias. */
348*41795aa1SThéo Lebrun 	pd = eq5p_test_bit(pctrl, bank, EQ5P_PD, offset);
349*41795aa1SThéo Lebrun 	pu = eq5p_test_bit(pctrl, bank, EQ5P_PU, offset);
350*41795aa1SThéo Lebrun 	if (pd && pu)
351*41795aa1SThéo Lebrun 		bias = "both";
352*41795aa1SThéo Lebrun 	else if (pd && !pu)
353*41795aa1SThéo Lebrun 		bias = "pulldown";
354*41795aa1SThéo Lebrun 	else if (!pd && pu)
355*41795aa1SThéo Lebrun 		bias = "pullup";
356*41795aa1SThéo Lebrun 	else
357*41795aa1SThéo Lebrun 		bias = "none";
358*41795aa1SThéo Lebrun 
359*41795aa1SThéo Lebrun 	/* Third, we get the drive strength. */
360*41795aa1SThéo Lebrun 	ds_config = pinconf_to_config_packed(PIN_CONFIG_DRIVE_STRENGTH, 0);
361*41795aa1SThéo Lebrun 	eq5p_pinconf_get(pctldev, pin, &ds_config);
362*41795aa1SThéo Lebrun 	drive_strength = pinconf_to_config_argument(ds_config);
363*41795aa1SThéo Lebrun 
364*41795aa1SThéo Lebrun 	seq_printf(s, "function=%s bias=%s drive_strength=%d",
365*41795aa1SThéo Lebrun 		   func_name, bias, drive_strength);
366*41795aa1SThéo Lebrun }
367*41795aa1SThéo Lebrun 
368*41795aa1SThéo Lebrun static const struct pinctrl_ops eq5p_pinctrl_ops = {
369*41795aa1SThéo Lebrun 	.get_groups_count	= eq5p_pinctrl_get_groups_count,
370*41795aa1SThéo Lebrun 	.get_group_name		= eq5p_pinctrl_get_group_name,
371*41795aa1SThéo Lebrun 	.get_group_pins		= eq5p_pinctrl_get_group_pins,
372*41795aa1SThéo Lebrun 	.pin_dbg_show		= eq5p_pinctrl_pin_dbg_show,
373*41795aa1SThéo Lebrun 	.dt_node_to_map		= pinconf_generic_dt_node_to_map_pin,
374*41795aa1SThéo Lebrun 	.dt_free_map		= pinctrl_utils_free_map,
375*41795aa1SThéo Lebrun };
376*41795aa1SThéo Lebrun 
eq5p_pinmux_get_functions_count(struct pinctrl_dev * pctldev)377*41795aa1SThéo Lebrun static int eq5p_pinmux_get_functions_count(struct pinctrl_dev *pctldev)
378*41795aa1SThéo Lebrun {
379*41795aa1SThéo Lebrun 	return ARRAY_SIZE(eq5p_functions);
380*41795aa1SThéo Lebrun }
381*41795aa1SThéo Lebrun 
eq5p_pinmux_get_function_name(struct pinctrl_dev * pctldev,unsigned int selector)382*41795aa1SThéo Lebrun static const char *eq5p_pinmux_get_function_name(struct pinctrl_dev *pctldev,
383*41795aa1SThéo Lebrun 						 unsigned int selector)
384*41795aa1SThéo Lebrun {
385*41795aa1SThéo Lebrun 	return eq5p_functions[selector].name;
386*41795aa1SThéo Lebrun }
387*41795aa1SThéo Lebrun 
eq5p_pinmux_get_function_groups(struct pinctrl_dev * pctldev,unsigned int selector,const char * const ** groups,unsigned int * num_groups)388*41795aa1SThéo Lebrun static int eq5p_pinmux_get_function_groups(struct pinctrl_dev *pctldev,
389*41795aa1SThéo Lebrun 					   unsigned int selector,
390*41795aa1SThéo Lebrun 					   const char * const **groups,
391*41795aa1SThéo Lebrun 					   unsigned int *num_groups)
392*41795aa1SThéo Lebrun {
393*41795aa1SThéo Lebrun 	*groups = eq5p_functions[selector].groups;
394*41795aa1SThéo Lebrun 	*num_groups = eq5p_functions[selector].ngroups;
395*41795aa1SThéo Lebrun 	return 0;
396*41795aa1SThéo Lebrun }
397*41795aa1SThéo Lebrun 
eq5p_pinmux_set_mux(struct pinctrl_dev * pctldev,unsigned int func_selector,unsigned int pin)398*41795aa1SThéo Lebrun static int eq5p_pinmux_set_mux(struct pinctrl_dev *pctldev,
399*41795aa1SThéo Lebrun 			       unsigned int func_selector, unsigned int pin)
400*41795aa1SThéo Lebrun {
401*41795aa1SThéo Lebrun 	struct eq5p_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
402*41795aa1SThéo Lebrun 	const char *func_name = eq5p_functions[func_selector].name;
403*41795aa1SThéo Lebrun 	const char *group_name = pctldev->desc->pins[pin].name;
404*41795aa1SThéo Lebrun 	bool is_gpio = func_selector == GPIO_FUNC_SELECTOR;
405*41795aa1SThéo Lebrun 	unsigned int offset = eq5p_pin_to_offset(pin);
406*41795aa1SThéo Lebrun 	enum eq5p_bank bank = eq5p_pin_to_bank(pin);
407*41795aa1SThéo Lebrun 	u32 mask, val;
408*41795aa1SThéo Lebrun 
409*41795aa1SThéo Lebrun 	dev_dbg(pctldev->dev, "func=%s group=%s\n", func_name, group_name);
410*41795aa1SThéo Lebrun 
411*41795aa1SThéo Lebrun 	mask = BIT(offset);
412*41795aa1SThéo Lebrun 	val = is_gpio ? 0 : mask;
413*41795aa1SThéo Lebrun 	eq5p_update_bits(pctrl, bank, EQ5P_IOCR, mask, val);
414*41795aa1SThéo Lebrun 	return 0;
415*41795aa1SThéo Lebrun }
416*41795aa1SThéo Lebrun 
eq5p_pinmux_gpio_request_enable(struct pinctrl_dev * pctldev,struct pinctrl_gpio_range * range,unsigned int pin)417*41795aa1SThéo Lebrun static int eq5p_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev,
418*41795aa1SThéo Lebrun 					   struct pinctrl_gpio_range *range,
419*41795aa1SThéo Lebrun 					   unsigned int pin)
420*41795aa1SThéo Lebrun {
421*41795aa1SThéo Lebrun 	/* Pin numbers and group selectors are the same thing in our case. */
422*41795aa1SThéo Lebrun 	return eq5p_pinmux_set_mux(pctldev, GPIO_FUNC_SELECTOR, pin);
423*41795aa1SThéo Lebrun }
424*41795aa1SThéo Lebrun 
425*41795aa1SThéo Lebrun static const struct pinmux_ops eq5p_pinmux_ops = {
426*41795aa1SThéo Lebrun 	.get_functions_count	= eq5p_pinmux_get_functions_count,
427*41795aa1SThéo Lebrun 	.get_function_name	= eq5p_pinmux_get_function_name,
428*41795aa1SThéo Lebrun 	.get_function_groups	= eq5p_pinmux_get_function_groups,
429*41795aa1SThéo Lebrun 	.set_mux		= eq5p_pinmux_set_mux,
430*41795aa1SThéo Lebrun 	.gpio_request_enable	= eq5p_pinmux_gpio_request_enable,
431*41795aa1SThéo Lebrun 	.strict			= true,
432*41795aa1SThéo Lebrun };
433*41795aa1SThéo Lebrun 
eq5p_pinconf_set_drive_strength(struct pinctrl_dev * pctldev,unsigned int pin,u32 arg)434*41795aa1SThéo Lebrun static int eq5p_pinconf_set_drive_strength(struct pinctrl_dev *pctldev,
435*41795aa1SThéo Lebrun 					   unsigned int pin, u32 arg)
436*41795aa1SThéo Lebrun {
437*41795aa1SThéo Lebrun 	struct eq5p_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
438*41795aa1SThéo Lebrun 	unsigned int offset = eq5p_pin_to_offset(pin);
439*41795aa1SThéo Lebrun 	enum eq5p_bank bank = eq5p_pin_to_bank(pin);
440*41795aa1SThéo Lebrun 	unsigned int reg;
441*41795aa1SThéo Lebrun 	u32 mask, val;
442*41795aa1SThéo Lebrun 
443*41795aa1SThéo Lebrun 	if (arg & ~EQ5P_DS_MASK) {
444*41795aa1SThéo Lebrun 		dev_err(pctldev->dev, "Unsupported drive strength: %u\n", arg);
445*41795aa1SThéo Lebrun 		return -EINVAL;
446*41795aa1SThéo Lebrun 	}
447*41795aa1SThéo Lebrun 
448*41795aa1SThéo Lebrun 	offset *= 2; /* two bits per pin */
449*41795aa1SThéo Lebrun 
450*41795aa1SThéo Lebrun 	if (offset >= 32) {
451*41795aa1SThéo Lebrun 		reg = EQ5P_DS_HIGH;
452*41795aa1SThéo Lebrun 		offset -= 32;
453*41795aa1SThéo Lebrun 	} else {
454*41795aa1SThéo Lebrun 		reg = EQ5P_DS_LOW;
455*41795aa1SThéo Lebrun 	}
456*41795aa1SThéo Lebrun 
457*41795aa1SThéo Lebrun 	mask = EQ5P_DS_MASK << offset;
458*41795aa1SThéo Lebrun 	val = arg << offset;
459*41795aa1SThéo Lebrun 	eq5p_update_bits(pctrl, bank, reg, mask, val);
460*41795aa1SThéo Lebrun 	return 0;
461*41795aa1SThéo Lebrun }
462*41795aa1SThéo Lebrun 
eq5p_pinconf_set(struct pinctrl_dev * pctldev,unsigned int pin,unsigned long * configs,unsigned int num_configs)463*41795aa1SThéo Lebrun static int eq5p_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
464*41795aa1SThéo Lebrun 			    unsigned long *configs, unsigned int num_configs)
465*41795aa1SThéo Lebrun {
466*41795aa1SThéo Lebrun 	struct eq5p_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
467*41795aa1SThéo Lebrun 	const char *pin_name = pctldev->desc->pins[pin].name;
468*41795aa1SThéo Lebrun 	unsigned int offset = eq5p_pin_to_offset(pin);
469*41795aa1SThéo Lebrun 	enum eq5p_bank bank = eq5p_pin_to_bank(pin);
470*41795aa1SThéo Lebrun 	struct device *dev = pctldev->dev;
471*41795aa1SThéo Lebrun 	u32 val = BIT(offset);
472*41795aa1SThéo Lebrun 	unsigned int i;
473*41795aa1SThéo Lebrun 
474*41795aa1SThéo Lebrun 	for (i = 0; i < num_configs; i++) {
475*41795aa1SThéo Lebrun 		enum pin_config_param param = pinconf_to_config_param(configs[i]);
476*41795aa1SThéo Lebrun 		u32 arg = pinconf_to_config_argument(configs[i]);
477*41795aa1SThéo Lebrun 
478*41795aa1SThéo Lebrun 		switch (param) {
479*41795aa1SThéo Lebrun 		case PIN_CONFIG_BIAS_DISABLE:
480*41795aa1SThéo Lebrun 			dev_dbg(dev, "pin=%s bias_disable\n", pin_name);
481*41795aa1SThéo Lebrun 
482*41795aa1SThéo Lebrun 			eq5p_update_bits(pctrl, bank, EQ5P_PD, val, 0);
483*41795aa1SThéo Lebrun 			eq5p_update_bits(pctrl, bank, EQ5P_PU, val, 0);
484*41795aa1SThéo Lebrun 			break;
485*41795aa1SThéo Lebrun 
486*41795aa1SThéo Lebrun 		case PIN_CONFIG_BIAS_PULL_DOWN:
487*41795aa1SThéo Lebrun 			dev_dbg(dev, "pin=%s bias_pull_down arg=%u\n",
488*41795aa1SThéo Lebrun 				pin_name, arg);
489*41795aa1SThéo Lebrun 
490*41795aa1SThéo Lebrun 			if (arg == 0) /* cannot connect to GND */
491*41795aa1SThéo Lebrun 				return -ENOTSUPP;
492*41795aa1SThéo Lebrun 
493*41795aa1SThéo Lebrun 			eq5p_update_bits(pctrl, bank, EQ5P_PD, val, val);
494*41795aa1SThéo Lebrun 			eq5p_update_bits(pctrl, bank, EQ5P_PU, val, 0);
495*41795aa1SThéo Lebrun 			break;
496*41795aa1SThéo Lebrun 
497*41795aa1SThéo Lebrun 		case PIN_CONFIG_BIAS_PULL_UP:
498*41795aa1SThéo Lebrun 			dev_dbg(dev, "pin=%s bias_pull_up arg=%u\n",
499*41795aa1SThéo Lebrun 				pin_name, arg);
500*41795aa1SThéo Lebrun 
501*41795aa1SThéo Lebrun 			if (arg == 0) /* cannot connect to VDD */
502*41795aa1SThéo Lebrun 				return -ENOTSUPP;
503*41795aa1SThéo Lebrun 
504*41795aa1SThéo Lebrun 			eq5p_update_bits(pctrl, bank, EQ5P_PD, val, 0);
505*41795aa1SThéo Lebrun 			eq5p_update_bits(pctrl, bank, EQ5P_PU, val, val);
506*41795aa1SThéo Lebrun 			break;
507*41795aa1SThéo Lebrun 
508*41795aa1SThéo Lebrun 		case PIN_CONFIG_DRIVE_STRENGTH:
509*41795aa1SThéo Lebrun 			dev_dbg(dev, "pin=%s drive_strength arg=%u\n",
510*41795aa1SThéo Lebrun 				pin_name, arg);
511*41795aa1SThéo Lebrun 
512*41795aa1SThéo Lebrun 			eq5p_pinconf_set_drive_strength(pctldev, pin, arg);
513*41795aa1SThéo Lebrun 			break;
514*41795aa1SThéo Lebrun 
515*41795aa1SThéo Lebrun 		default:
516*41795aa1SThéo Lebrun 			dev_err(dev, "Unsupported pinconf %u\n", param);
517*41795aa1SThéo Lebrun 			return -ENOTSUPP;
518*41795aa1SThéo Lebrun 		}
519*41795aa1SThéo Lebrun 	}
520*41795aa1SThéo Lebrun 
521*41795aa1SThéo Lebrun 	return 0;
522*41795aa1SThéo Lebrun }
523*41795aa1SThéo Lebrun 
524*41795aa1SThéo Lebrun static const struct pinconf_ops eq5p_pinconf_ops = {
525*41795aa1SThéo Lebrun 	.is_generic = true,
526*41795aa1SThéo Lebrun 	.pin_config_get = eq5p_pinconf_get,
527*41795aa1SThéo Lebrun 	.pin_config_set = eq5p_pinconf_set,
528*41795aa1SThéo Lebrun 	/* Pins and groups are equivalent in this driver. */
529*41795aa1SThéo Lebrun 	.pin_config_group_get = eq5p_pinconf_get,
530*41795aa1SThéo Lebrun 	.pin_config_group_set = eq5p_pinconf_set,
531*41795aa1SThéo Lebrun };
532*41795aa1SThéo Lebrun 
eq5p_probe(struct auxiliary_device * adev,const struct auxiliary_device_id * id)533*41795aa1SThéo Lebrun static int eq5p_probe(struct auxiliary_device *adev,
534*41795aa1SThéo Lebrun 		      const struct auxiliary_device_id *id)
535*41795aa1SThéo Lebrun {
536*41795aa1SThéo Lebrun 	struct device *dev = &adev->dev;
537*41795aa1SThéo Lebrun 	struct pinctrl_dev *pctldev;
538*41795aa1SThéo Lebrun 	struct eq5p_pinctrl *pctrl;
539*41795aa1SThéo Lebrun 	int ret;
540*41795aa1SThéo Lebrun 
541*41795aa1SThéo Lebrun 	pctrl = devm_kzalloc(dev, sizeof(*pctrl), GFP_KERNEL);
542*41795aa1SThéo Lebrun 	if (!pctrl)
543*41795aa1SThéo Lebrun 		return -ENOMEM;
544*41795aa1SThéo Lebrun 
545*41795aa1SThéo Lebrun 	pctrl->base = (void __iomem *)dev_get_platdata(dev);
546*41795aa1SThéo Lebrun 	pctrl->desc.name = dev_name(dev);
547*41795aa1SThéo Lebrun 	pctrl->desc.pins = eq5p_pins;
548*41795aa1SThéo Lebrun 	pctrl->desc.npins = ARRAY_SIZE(eq5p_pins);
549*41795aa1SThéo Lebrun 	pctrl->desc.pctlops = &eq5p_pinctrl_ops;
550*41795aa1SThéo Lebrun 	pctrl->desc.pmxops = &eq5p_pinmux_ops;
551*41795aa1SThéo Lebrun 	pctrl->desc.confops = &eq5p_pinconf_ops;
552*41795aa1SThéo Lebrun 	pctrl->desc.owner = THIS_MODULE;
553*41795aa1SThéo Lebrun 
554*41795aa1SThéo Lebrun 	ret = devm_pinctrl_register_and_init(dev, &pctrl->desc, pctrl, &pctldev);
555*41795aa1SThéo Lebrun 	if (ret)
556*41795aa1SThéo Lebrun 		return dev_err_probe(dev, ret, "failed registering pinctrl device\n");
557*41795aa1SThéo Lebrun 
558*41795aa1SThéo Lebrun 	ret = pinctrl_enable(pctldev);
559*41795aa1SThéo Lebrun 	if (ret)
560*41795aa1SThéo Lebrun 		return dev_err_probe(dev, ret, "failed enabling pinctrl device\n");
561*41795aa1SThéo Lebrun 
562*41795aa1SThéo Lebrun 	return 0;
563*41795aa1SThéo Lebrun }
564*41795aa1SThéo Lebrun 
565*41795aa1SThéo Lebrun static const struct auxiliary_device_id eq5p_id_table[] = {
566*41795aa1SThéo Lebrun 	{ .name = "clk_eyeq.pinctrl" },
567*41795aa1SThéo Lebrun 	{}
568*41795aa1SThéo Lebrun };
569*41795aa1SThéo Lebrun MODULE_DEVICE_TABLE(auxiliary, eq5p_id_table);
570*41795aa1SThéo Lebrun 
571*41795aa1SThéo Lebrun static struct auxiliary_driver eq5p_driver = {
572*41795aa1SThéo Lebrun 	.probe = eq5p_probe,
573*41795aa1SThéo Lebrun 	.id_table = eq5p_id_table,
574*41795aa1SThéo Lebrun };
575*41795aa1SThéo Lebrun module_auxiliary_driver(eq5p_driver);
576