xref: /linux/drivers/pinctrl/pinctrl-ingenic.c (revision 3ad0876554cafa368f574d4d408468510543e9ff)
1 /*
2  * Ingenic SoCs pinctrl driver
3  *
4  * Copyright (c) 2017 Paul Cercueil <paul@crapouillou.net>
5  *
6  * License terms: GNU General Public License (GPL) version 2
7  */
8 
9 #include <linux/compiler.h>
10 #include <linux/gpio.h>
11 #include <linux/interrupt.h>
12 #include <linux/io.h>
13 #include <linux/of_device.h>
14 #include <linux/of_platform.h>
15 #include <linux/pinctrl/pinctrl.h>
16 #include <linux/pinctrl/pinmux.h>
17 #include <linux/pinctrl/pinconf.h>
18 #include <linux/pinctrl/pinconf-generic.h>
19 #include <linux/platform_device.h>
20 #include <linux/regmap.h>
21 #include <linux/slab.h>
22 
23 #include "core.h"
24 #include "pinconf.h"
25 #include "pinmux.h"
26 
27 #define JZ4740_GPIO_DATA	0x10
28 #define JZ4740_GPIO_PULL_DIS	0x30
29 #define JZ4740_GPIO_FUNC	0x40
30 #define JZ4740_GPIO_SELECT	0x50
31 #define JZ4740_GPIO_DIR		0x60
32 #define JZ4740_GPIO_TRIG	0x70
33 #define JZ4740_GPIO_FLAG	0x80
34 
35 #define JZ4770_GPIO_INT		0x10
36 #define JZ4770_GPIO_MSK		0x20
37 #define JZ4770_GPIO_PAT1	0x30
38 #define JZ4770_GPIO_PAT0	0x40
39 #define JZ4770_GPIO_FLAG	0x50
40 #define JZ4770_GPIO_PEN		0x70
41 
42 #define REG_SET(x) ((x) + 0x4)
43 #define REG_CLEAR(x) ((x) + 0x8)
44 
45 #define PINS_PER_GPIO_CHIP 32
46 
47 enum jz_version {
48 	ID_JZ4740,
49 	ID_JZ4770,
50 	ID_JZ4780,
51 };
52 
53 struct ingenic_chip_info {
54 	unsigned int num_chips;
55 
56 	const struct group_desc *groups;
57 	unsigned int num_groups;
58 
59 	const struct function_desc *functions;
60 	unsigned int num_functions;
61 
62 	const u32 *pull_ups, *pull_downs;
63 };
64 
65 struct ingenic_pinctrl {
66 	struct device *dev;
67 	struct regmap *map;
68 	struct pinctrl_dev *pctl;
69 	struct pinctrl_pin_desc *pdesc;
70 	enum jz_version version;
71 
72 	const struct ingenic_chip_info *info;
73 };
74 
75 static const u32 jz4740_pull_ups[4] = {
76 	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
77 };
78 
79 static const u32 jz4740_pull_downs[4] = {
80 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
81 };
82 
83 static int jz4740_mmc_1bit_pins[] = { 0x69, 0x68, 0x6a, };
84 static int jz4740_mmc_4bit_pins[] = { 0x6b, 0x6c, 0x6d, };
85 static int jz4740_uart0_data_pins[] = { 0x7a, 0x79, };
86 static int jz4740_uart0_hwflow_pins[] = { 0x7e, 0x7f, };
87 static int jz4740_uart1_data_pins[] = { 0x7e, 0x7f, };
88 static int jz4740_lcd_8bit_pins[] = {
89 	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x52, 0x53, 0x54,
90 };
91 static int jz4740_lcd_16bit_pins[] = {
92 	0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x55,
93 };
94 static int jz4740_lcd_18bit_pins[] = { 0x50, 0x51, };
95 static int jz4740_lcd_18bit_tft_pins[] = { 0x56, 0x57, 0x31, 0x32, };
96 static int jz4740_nand_cs1_pins[] = { 0x39, };
97 static int jz4740_nand_cs2_pins[] = { 0x3a, };
98 static int jz4740_nand_cs3_pins[] = { 0x3b, };
99 static int jz4740_nand_cs4_pins[] = { 0x3c, };
100 static int jz4740_pwm_pwm0_pins[] = { 0x77, };
101 static int jz4740_pwm_pwm1_pins[] = { 0x78, };
102 static int jz4740_pwm_pwm2_pins[] = { 0x79, };
103 static int jz4740_pwm_pwm3_pins[] = { 0x7a, };
104 static int jz4740_pwm_pwm4_pins[] = { 0x7b, };
105 static int jz4740_pwm_pwm5_pins[] = { 0x7c, };
106 static int jz4740_pwm_pwm6_pins[] = { 0x7e, };
107 static int jz4740_pwm_pwm7_pins[] = { 0x7f, };
108 
109 static int jz4740_mmc_1bit_funcs[] = { 0, 0, 0, };
110 static int jz4740_mmc_4bit_funcs[] = { 0, 0, 0, };
111 static int jz4740_uart0_data_funcs[] = { 1, 1, };
112 static int jz4740_uart0_hwflow_funcs[] = { 1, 1, };
113 static int jz4740_uart1_data_funcs[] = { 2, 2, };
114 static int jz4740_lcd_8bit_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
115 static int jz4740_lcd_16bit_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, };
116 static int jz4740_lcd_18bit_funcs[] = { 0, 0, };
117 static int jz4740_lcd_18bit_tft_funcs[] = { 0, 0, 0, 0, };
118 static int jz4740_nand_cs1_funcs[] = { 0, };
119 static int jz4740_nand_cs2_funcs[] = { 0, };
120 static int jz4740_nand_cs3_funcs[] = { 0, };
121 static int jz4740_nand_cs4_funcs[] = { 0, };
122 static int jz4740_pwm_pwm0_funcs[] = { 0, };
123 static int jz4740_pwm_pwm1_funcs[] = { 0, };
124 static int jz4740_pwm_pwm2_funcs[] = { 0, };
125 static int jz4740_pwm_pwm3_funcs[] = { 0, };
126 static int jz4740_pwm_pwm4_funcs[] = { 0, };
127 static int jz4740_pwm_pwm5_funcs[] = { 0, };
128 static int jz4740_pwm_pwm6_funcs[] = { 0, };
129 static int jz4740_pwm_pwm7_funcs[] = { 0, };
130 
131 #define INGENIC_PIN_GROUP(name, id)			\
132 	{						\
133 		name,					\
134 		id##_pins,				\
135 		ARRAY_SIZE(id##_pins),			\
136 		id##_funcs,				\
137 	}
138 
139 static const struct group_desc jz4740_groups[] = {
140 	INGENIC_PIN_GROUP("mmc-1bit", jz4740_mmc_1bit),
141 	INGENIC_PIN_GROUP("mmc-4bit", jz4740_mmc_4bit),
142 	INGENIC_PIN_GROUP("uart0-data", jz4740_uart0_data),
143 	INGENIC_PIN_GROUP("uart0-hwflow", jz4740_uart0_hwflow),
144 	INGENIC_PIN_GROUP("uart1-data", jz4740_uart1_data),
145 	INGENIC_PIN_GROUP("lcd-8bit", jz4740_lcd_8bit),
146 	INGENIC_PIN_GROUP("lcd-16bit", jz4740_lcd_16bit),
147 	INGENIC_PIN_GROUP("lcd-18bit", jz4740_lcd_18bit),
148 	INGENIC_PIN_GROUP("lcd-18bit-tft", jz4740_lcd_18bit_tft),
149 	{ "lcd-no-pins", },
150 	INGENIC_PIN_GROUP("nand-cs1", jz4740_nand_cs1),
151 	INGENIC_PIN_GROUP("nand-cs2", jz4740_nand_cs2),
152 	INGENIC_PIN_GROUP("nand-cs3", jz4740_nand_cs3),
153 	INGENIC_PIN_GROUP("nand-cs4", jz4740_nand_cs4),
154 	INGENIC_PIN_GROUP("pwm0", jz4740_pwm_pwm0),
155 	INGENIC_PIN_GROUP("pwm1", jz4740_pwm_pwm1),
156 	INGENIC_PIN_GROUP("pwm2", jz4740_pwm_pwm2),
157 	INGENIC_PIN_GROUP("pwm3", jz4740_pwm_pwm3),
158 	INGENIC_PIN_GROUP("pwm4", jz4740_pwm_pwm4),
159 	INGENIC_PIN_GROUP("pwm5", jz4740_pwm_pwm5),
160 	INGENIC_PIN_GROUP("pwm6", jz4740_pwm_pwm6),
161 	INGENIC_PIN_GROUP("pwm7", jz4740_pwm_pwm7),
162 };
163 
164 static const char *jz4740_mmc_groups[] = { "mmc-1bit", "mmc-4bit", };
165 static const char *jz4740_uart0_groups[] = { "uart0-data", "uart0-hwflow", };
166 static const char *jz4740_uart1_groups[] = { "uart1-data", };
167 static const char *jz4740_lcd_groups[] = {
168 	"lcd-8bit", "lcd-16bit", "lcd-18bit", "lcd-18bit-tft", "lcd-no-pins",
169 };
170 static const char *jz4740_nand_groups[] = {
171 	"nand-cs1", "nand-cs2", "nand-cs3", "nand-cs4",
172 };
173 static const char *jz4740_pwm0_groups[] = { "pwm0", };
174 static const char *jz4740_pwm1_groups[] = { "pwm1", };
175 static const char *jz4740_pwm2_groups[] = { "pwm2", };
176 static const char *jz4740_pwm3_groups[] = { "pwm3", };
177 static const char *jz4740_pwm4_groups[] = { "pwm4", };
178 static const char *jz4740_pwm5_groups[] = { "pwm5", };
179 static const char *jz4740_pwm6_groups[] = { "pwm6", };
180 static const char *jz4740_pwm7_groups[] = { "pwm7", };
181 
182 static const struct function_desc jz4740_functions[] = {
183 	{ "mmc", jz4740_mmc_groups, ARRAY_SIZE(jz4740_mmc_groups), },
184 	{ "uart0", jz4740_uart0_groups, ARRAY_SIZE(jz4740_uart0_groups), },
185 	{ "uart1", jz4740_uart1_groups, ARRAY_SIZE(jz4740_uart1_groups), },
186 	{ "lcd", jz4740_lcd_groups, ARRAY_SIZE(jz4740_lcd_groups), },
187 	{ "nand", jz4740_nand_groups, ARRAY_SIZE(jz4740_nand_groups), },
188 	{ "pwm0", jz4740_pwm0_groups, ARRAY_SIZE(jz4740_pwm0_groups), },
189 	{ "pwm1", jz4740_pwm1_groups, ARRAY_SIZE(jz4740_pwm1_groups), },
190 	{ "pwm2", jz4740_pwm2_groups, ARRAY_SIZE(jz4740_pwm2_groups), },
191 	{ "pwm3", jz4740_pwm3_groups, ARRAY_SIZE(jz4740_pwm3_groups), },
192 	{ "pwm4", jz4740_pwm4_groups, ARRAY_SIZE(jz4740_pwm4_groups), },
193 	{ "pwm5", jz4740_pwm5_groups, ARRAY_SIZE(jz4740_pwm5_groups), },
194 	{ "pwm6", jz4740_pwm6_groups, ARRAY_SIZE(jz4740_pwm6_groups), },
195 	{ "pwm7", jz4740_pwm7_groups, ARRAY_SIZE(jz4740_pwm7_groups), },
196 };
197 
198 static const struct ingenic_chip_info jz4740_chip_info = {
199 	.num_chips = 4,
200 	.groups = jz4740_groups,
201 	.num_groups = ARRAY_SIZE(jz4740_groups),
202 	.functions = jz4740_functions,
203 	.num_functions = ARRAY_SIZE(jz4740_functions),
204 	.pull_ups = jz4740_pull_ups,
205 	.pull_downs = jz4740_pull_downs,
206 };
207 
208 static const u32 jz4770_pull_ups[6] = {
209 	0x3fffffff, 0xfff0030c, 0xffffffff, 0xffff4fff, 0xfffffb7c, 0xffa7f00f,
210 };
211 
212 static const u32 jz4770_pull_downs[6] = {
213 	0x00000000, 0x000f0c03, 0x00000000, 0x0000b000, 0x00000483, 0x00580ff0,
214 };
215 
216 static int jz4770_uart0_data_pins[] = { 0xa0, 0xa3, };
217 static int jz4770_uart0_hwflow_pins[] = { 0xa1, 0xa2, };
218 static int jz4770_uart1_data_pins[] = { 0x7a, 0x7c, };
219 static int jz4770_uart1_hwflow_pins[] = { 0x7b, 0x7d, };
220 static int jz4770_uart2_data_pins[] = { 0x66, 0x67, };
221 static int jz4770_uart2_hwflow_pins[] = { 0x65, 0x64, };
222 static int jz4770_uart3_data_pins[] = { 0x6c, 0x85, };
223 static int jz4770_uart3_hwflow_pins[] = { 0x88, 0x89, };
224 static int jz4770_uart4_data_pins[] = { 0x54, 0x4a, };
225 static int jz4770_mmc0_8bit_a_pins[] = { 0x04, 0x05, 0x06, 0x07, 0x18, };
226 static int jz4770_mmc0_4bit_a_pins[] = { 0x15, 0x16, 0x17, };
227 static int jz4770_mmc0_1bit_a_pins[] = { 0x12, 0x13, 0x14, };
228 static int jz4770_mmc0_4bit_e_pins[] = { 0x95, 0x96, 0x97, };
229 static int jz4770_mmc0_1bit_e_pins[] = { 0x9c, 0x9d, 0x94, };
230 static int jz4770_mmc1_4bit_d_pins[] = { 0x75, 0x76, 0x77, };
231 static int jz4770_mmc1_1bit_d_pins[] = { 0x78, 0x79, 0x74, };
232 static int jz4770_mmc1_4bit_e_pins[] = { 0x95, 0x96, 0x97, };
233 static int jz4770_mmc1_1bit_e_pins[] = { 0x9c, 0x9d, 0x94, };
234 static int jz4770_nemc_data_pins[] = {
235 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
236 };
237 static int jz4770_nemc_cle_ale_pins[] = { 0x20, 0x21, };
238 static int jz4770_nemc_addr_pins[] = { 0x22, 0x23, 0x24, 0x25, };
239 static int jz4770_nemc_rd_we_pins[] = { 0x10, 0x11, };
240 static int jz4770_nemc_frd_fwe_pins[] = { 0x12, 0x13, };
241 static int jz4770_nemc_cs1_pins[] = { 0x15, };
242 static int jz4770_nemc_cs2_pins[] = { 0x16, };
243 static int jz4770_nemc_cs3_pins[] = { 0x17, };
244 static int jz4770_nemc_cs4_pins[] = { 0x18, };
245 static int jz4770_nemc_cs5_pins[] = { 0x19, };
246 static int jz4770_nemc_cs6_pins[] = { 0x1a, };
247 static int jz4770_i2c0_pins[] = { 0x6e, 0x6f, };
248 static int jz4770_i2c1_pins[] = { 0x8e, 0x8f, };
249 static int jz4770_i2c2_pins[] = { 0xb0, 0xb1, };
250 static int jz4770_i2c3_pins[] = { 0x6a, 0x6b, };
251 static int jz4770_i2c4_e_pins[] = { 0x8c, 0x8d, };
252 static int jz4770_i2c4_f_pins[] = { 0xb9, 0xb8, };
253 static int jz4770_cim_pins[] = {
254 	0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31,
255 };
256 static int jz4770_lcd_32bit_pins[] = {
257 	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
258 	0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
259 	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
260 	0x58, 0x59, 0x51,
261 };
262 static int jz4770_pwm_pwm0_pins[] = { 0x80, };
263 static int jz4770_pwm_pwm1_pins[] = { 0x81, };
264 static int jz4770_pwm_pwm2_pins[] = { 0x82, };
265 static int jz4770_pwm_pwm3_pins[] = { 0x83, };
266 static int jz4770_pwm_pwm4_pins[] = { 0x84, };
267 static int jz4770_pwm_pwm5_pins[] = { 0x85, };
268 static int jz4770_pwm_pwm6_pins[] = { 0x6a, };
269 static int jz4770_pwm_pwm7_pins[] = { 0x6b, };
270 
271 static int jz4770_uart0_data_funcs[] = { 0, 0, };
272 static int jz4770_uart0_hwflow_funcs[] = { 0, 0, };
273 static int jz4770_uart1_data_funcs[] = { 0, 0, };
274 static int jz4770_uart1_hwflow_funcs[] = { 0, 0, };
275 static int jz4770_uart2_data_funcs[] = { 1, 1, };
276 static int jz4770_uart2_hwflow_funcs[] = { 1, 1, };
277 static int jz4770_uart3_data_funcs[] = { 0, 1, };
278 static int jz4770_uart3_hwflow_funcs[] = { 0, 0, };
279 static int jz4770_uart4_data_funcs[] = { 2, 2, };
280 static int jz4770_mmc0_8bit_a_funcs[] = { 1, 1, 1, 1, 1, };
281 static int jz4770_mmc0_4bit_a_funcs[] = { 1, 1, 1, };
282 static int jz4770_mmc0_1bit_a_funcs[] = { 1, 1, 0, };
283 static int jz4770_mmc0_4bit_e_funcs[] = { 0, 0, 0, };
284 static int jz4770_mmc0_1bit_e_funcs[] = { 0, 0, 0, };
285 static int jz4770_mmc1_4bit_d_funcs[] = { 0, 0, 0, };
286 static int jz4770_mmc1_1bit_d_funcs[] = { 0, 0, 0, };
287 static int jz4770_mmc1_4bit_e_funcs[] = { 1, 1, 1, };
288 static int jz4770_mmc1_1bit_e_funcs[] = { 1, 1, 1, };
289 static int jz4770_nemc_data_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, };
290 static int jz4770_nemc_cle_ale_funcs[] = { 0, 0, };
291 static int jz4770_nemc_addr_funcs[] = { 0, 0, 0, 0, };
292 static int jz4770_nemc_rd_we_funcs[] = { 0, 0, };
293 static int jz4770_nemc_frd_fwe_funcs[] = { 0, 0, };
294 static int jz4770_nemc_cs1_funcs[] = { 0, };
295 static int jz4770_nemc_cs2_funcs[] = { 0, };
296 static int jz4770_nemc_cs3_funcs[] = { 0, };
297 static int jz4770_nemc_cs4_funcs[] = { 0, };
298 static int jz4770_nemc_cs5_funcs[] = { 0, };
299 static int jz4770_nemc_cs6_funcs[] = { 0, };
300 static int jz4770_i2c0_funcs[] = { 0, 0, };
301 static int jz4770_i2c1_funcs[] = { 0, 0, };
302 static int jz4770_i2c2_funcs[] = { 2, 2, };
303 static int jz4770_i2c3_funcs[] = { 1, 1, };
304 static int jz4770_i2c4_e_funcs[] = { 1, 1, };
305 static int jz4770_i2c4_f_funcs[] = { 1, 1, };
306 static int jz4770_cim_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
307 static int jz4770_lcd_32bit_funcs[] = {
308 	0, 0, 0, 0, 0, 0, 0, 0,
309 	0, 0, 0, 0, 0, 0, 0, 0,
310 	0, 0, 0,
311 };
312 static int jz4770_pwm_pwm0_funcs[] = { 0, };
313 static int jz4770_pwm_pwm1_funcs[] = { 0, };
314 static int jz4770_pwm_pwm2_funcs[] = { 0, };
315 static int jz4770_pwm_pwm3_funcs[] = { 0, };
316 static int jz4770_pwm_pwm4_funcs[] = { 0, };
317 static int jz4770_pwm_pwm5_funcs[] = { 0, };
318 static int jz4770_pwm_pwm6_funcs[] = { 0, };
319 static int jz4770_pwm_pwm7_funcs[] = { 0, };
320 
321 static const struct group_desc jz4770_groups[] = {
322 	INGENIC_PIN_GROUP("uart0-data", jz4770_uart0_data),
323 	INGENIC_PIN_GROUP("uart0-hwflow", jz4770_uart0_hwflow),
324 	INGENIC_PIN_GROUP("uart1-data", jz4770_uart1_data),
325 	INGENIC_PIN_GROUP("uart1-hwflow", jz4770_uart1_hwflow),
326 	INGENIC_PIN_GROUP("uart2-data", jz4770_uart2_data),
327 	INGENIC_PIN_GROUP("uart2-hwflow", jz4770_uart2_hwflow),
328 	INGENIC_PIN_GROUP("uart3-data", jz4770_uart3_data),
329 	INGENIC_PIN_GROUP("uart3-hwflow", jz4770_uart3_hwflow),
330 	INGENIC_PIN_GROUP("uart4-data", jz4770_uart4_data),
331 	INGENIC_PIN_GROUP("mmc0-8bit-a", jz4770_mmc0_8bit_a),
332 	INGENIC_PIN_GROUP("mmc0-4bit-a", jz4770_mmc0_4bit_a),
333 	INGENIC_PIN_GROUP("mmc0-1bit-a", jz4770_mmc0_1bit_a),
334 	INGENIC_PIN_GROUP("mmc0-4bit-e", jz4770_mmc0_4bit_e),
335 	INGENIC_PIN_GROUP("mmc0-1bit-e", jz4770_mmc0_1bit_e),
336 	INGENIC_PIN_GROUP("mmc1-4bit-d", jz4770_mmc1_4bit_d),
337 	INGENIC_PIN_GROUP("mmc1-1bit-d", jz4770_mmc1_1bit_d),
338 	INGENIC_PIN_GROUP("mmc1-4bit-e", jz4770_mmc1_4bit_e),
339 	INGENIC_PIN_GROUP("mmc1-1bit-e", jz4770_mmc1_1bit_e),
340 	INGENIC_PIN_GROUP("nemc-data", jz4770_nemc_data),
341 	INGENIC_PIN_GROUP("nemc-cle-ale", jz4770_nemc_cle_ale),
342 	INGENIC_PIN_GROUP("nemc-addr", jz4770_nemc_addr),
343 	INGENIC_PIN_GROUP("nemc-rd-we", jz4770_nemc_rd_we),
344 	INGENIC_PIN_GROUP("nemc-frd-fwe", jz4770_nemc_frd_fwe),
345 	INGENIC_PIN_GROUP("nemc-cs1", jz4770_nemc_cs1),
346 	INGENIC_PIN_GROUP("nemc-cs2", jz4770_nemc_cs2),
347 	INGENIC_PIN_GROUP("nemc-cs3", jz4770_nemc_cs3),
348 	INGENIC_PIN_GROUP("nemc-cs4", jz4770_nemc_cs4),
349 	INGENIC_PIN_GROUP("nemc-cs5", jz4770_nemc_cs5),
350 	INGENIC_PIN_GROUP("nemc-cs6", jz4770_nemc_cs6),
351 	INGENIC_PIN_GROUP("i2c0-data", jz4770_i2c0),
352 	INGENIC_PIN_GROUP("i2c1-data", jz4770_i2c1),
353 	INGENIC_PIN_GROUP("i2c2-data", jz4770_i2c2),
354 	INGENIC_PIN_GROUP("i2c3-data", jz4770_i2c3),
355 	INGENIC_PIN_GROUP("i2c4-data-e", jz4770_i2c4_e),
356 	INGENIC_PIN_GROUP("i2c4-data-f", jz4770_i2c4_f),
357 	INGENIC_PIN_GROUP("cim-data", jz4770_cim),
358 	INGENIC_PIN_GROUP("lcd-32bit", jz4770_lcd_32bit),
359 	{ "lcd-no-pins", },
360 	INGENIC_PIN_GROUP("pwm0", jz4770_pwm_pwm0),
361 	INGENIC_PIN_GROUP("pwm1", jz4770_pwm_pwm1),
362 	INGENIC_PIN_GROUP("pwm2", jz4770_pwm_pwm2),
363 	INGENIC_PIN_GROUP("pwm3", jz4770_pwm_pwm3),
364 	INGENIC_PIN_GROUP("pwm4", jz4770_pwm_pwm4),
365 	INGENIC_PIN_GROUP("pwm5", jz4770_pwm_pwm5),
366 	INGENIC_PIN_GROUP("pwm6", jz4770_pwm_pwm6),
367 	INGENIC_PIN_GROUP("pwm7", jz4770_pwm_pwm7),
368 };
369 
370 static const char *jz4770_uart0_groups[] = { "uart0-data", "uart0-hwflow", };
371 static const char *jz4770_uart1_groups[] = { "uart1-data", "uart1-hwflow", };
372 static const char *jz4770_uart2_groups[] = { "uart2-data", "uart2-hwflow", };
373 static const char *jz4770_uart3_groups[] = { "uart3-data", "uart3-hwflow", };
374 static const char *jz4770_uart4_groups[] = { "uart4-data", };
375 static const char *jz4770_mmc0_groups[] = {
376 	"mmc0-8bit-a", "mmc0-4bit-a", "mmc0-1bit-a",
377 	"mmc0-1bit-e", "mmc0-4bit-e",
378 };
379 static const char *jz4770_mmc1_groups[] = {
380 	"mmc1-1bit-d", "mmc1-4bit-d", "mmc1-1bit-e", "mmc1-4bit-e",
381 };
382 static const char *jz4770_nemc_groups[] = {
383 	"nemc-data", "nemc-cle-ale", "nemc-addr", "nemc-rd-we", "nemc-frd-fwe",
384 };
385 static const char *jz4770_cs1_groups[] = { "nemc-cs1", };
386 static const char *jz4770_cs6_groups[] = { "nemc-cs6", };
387 static const char *jz4770_i2c0_groups[] = { "i2c0-data", };
388 static const char *jz4770_i2c1_groups[] = { "i2c1-data", };
389 static const char *jz4770_i2c2_groups[] = { "i2c2-data", };
390 static const char *jz4770_i2c3_groups[] = { "i2c3-data", };
391 static const char *jz4770_i2c4_groups[] = { "i2c4-data-e", "i2c4-data-f", };
392 static const char *jz4770_cim_groups[] = { "cim-data", };
393 static const char *jz4770_lcd_groups[] = { "lcd-32bit", "lcd-no-pins", };
394 static const char *jz4770_pwm0_groups[] = { "pwm0", };
395 static const char *jz4770_pwm1_groups[] = { "pwm1", };
396 static const char *jz4770_pwm2_groups[] = { "pwm2", };
397 static const char *jz4770_pwm3_groups[] = { "pwm3", };
398 static const char *jz4770_pwm4_groups[] = { "pwm4", };
399 static const char *jz4770_pwm5_groups[] = { "pwm5", };
400 static const char *jz4770_pwm6_groups[] = { "pwm6", };
401 static const char *jz4770_pwm7_groups[] = { "pwm7", };
402 
403 static const struct function_desc jz4770_functions[] = {
404 	{ "uart0", jz4770_uart0_groups, ARRAY_SIZE(jz4770_uart0_groups), },
405 	{ "uart1", jz4770_uart1_groups, ARRAY_SIZE(jz4770_uart1_groups), },
406 	{ "uart2", jz4770_uart2_groups, ARRAY_SIZE(jz4770_uart2_groups), },
407 	{ "uart3", jz4770_uart3_groups, ARRAY_SIZE(jz4770_uart3_groups), },
408 	{ "uart4", jz4770_uart4_groups, ARRAY_SIZE(jz4770_uart4_groups), },
409 	{ "mmc0", jz4770_mmc0_groups, ARRAY_SIZE(jz4770_mmc0_groups), },
410 	{ "mmc1", jz4770_mmc1_groups, ARRAY_SIZE(jz4770_mmc1_groups), },
411 	{ "nemc", jz4770_nemc_groups, ARRAY_SIZE(jz4770_nemc_groups), },
412 	{ "nemc-cs1", jz4770_cs1_groups, ARRAY_SIZE(jz4770_cs1_groups), },
413 	{ "nemc-cs6", jz4770_cs6_groups, ARRAY_SIZE(jz4770_cs6_groups), },
414 	{ "i2c0", jz4770_i2c0_groups, ARRAY_SIZE(jz4770_i2c0_groups), },
415 	{ "i2c1", jz4770_i2c1_groups, ARRAY_SIZE(jz4770_i2c1_groups), },
416 	{ "i2c2", jz4770_i2c2_groups, ARRAY_SIZE(jz4770_i2c2_groups), },
417 	{ "i2c3", jz4770_i2c3_groups, ARRAY_SIZE(jz4770_i2c3_groups), },
418 	{ "i2c4", jz4770_i2c4_groups, ARRAY_SIZE(jz4770_i2c4_groups), },
419 	{ "cim", jz4770_cim_groups, ARRAY_SIZE(jz4770_cim_groups), },
420 	{ "lcd", jz4770_lcd_groups, ARRAY_SIZE(jz4770_lcd_groups), },
421 	{ "pwm0", jz4770_pwm0_groups, ARRAY_SIZE(jz4770_pwm0_groups), },
422 	{ "pwm1", jz4770_pwm1_groups, ARRAY_SIZE(jz4770_pwm1_groups), },
423 	{ "pwm2", jz4770_pwm2_groups, ARRAY_SIZE(jz4770_pwm2_groups), },
424 	{ "pwm3", jz4770_pwm3_groups, ARRAY_SIZE(jz4770_pwm3_groups), },
425 	{ "pwm4", jz4770_pwm4_groups, ARRAY_SIZE(jz4770_pwm4_groups), },
426 	{ "pwm5", jz4770_pwm5_groups, ARRAY_SIZE(jz4770_pwm5_groups), },
427 	{ "pwm6", jz4770_pwm6_groups, ARRAY_SIZE(jz4770_pwm6_groups), },
428 	{ "pwm7", jz4770_pwm7_groups, ARRAY_SIZE(jz4770_pwm7_groups), },
429 };
430 
431 static const struct ingenic_chip_info jz4770_chip_info = {
432 	.num_chips = 6,
433 	.groups = jz4770_groups,
434 	.num_groups = ARRAY_SIZE(jz4770_groups),
435 	.functions = jz4770_functions,
436 	.num_functions = ARRAY_SIZE(jz4770_functions),
437 	.pull_ups = jz4770_pull_ups,
438 	.pull_downs = jz4770_pull_downs,
439 };
440 
441 static inline void ingenic_config_pin(struct ingenic_pinctrl *jzpc,
442 		unsigned int pin, u8 reg, bool set)
443 {
444 	unsigned int idx = pin % PINS_PER_GPIO_CHIP;
445 	unsigned int offt = pin / PINS_PER_GPIO_CHIP;
446 
447 	regmap_write(jzpc->map, offt * 0x100 +
448 			(set ? REG_SET(reg) : REG_CLEAR(reg)), BIT(idx));
449 }
450 
451 static inline bool ingenic_get_pin_config(struct ingenic_pinctrl *jzpc,
452 		unsigned int pin, u8 reg)
453 {
454 	unsigned int idx = pin % PINS_PER_GPIO_CHIP;
455 	unsigned int offt = pin / PINS_PER_GPIO_CHIP;
456 	unsigned int val;
457 
458 	regmap_read(jzpc->map, offt * 0x100 + reg, &val);
459 
460 	return val & BIT(idx);
461 }
462 
463 static const struct pinctrl_ops ingenic_pctlops = {
464 	.get_groups_count = pinctrl_generic_get_group_count,
465 	.get_group_name = pinctrl_generic_get_group_name,
466 	.get_group_pins = pinctrl_generic_get_group_pins,
467 	.dt_node_to_map = pinconf_generic_dt_node_to_map_all,
468 	.dt_free_map = pinconf_generic_dt_free_map,
469 };
470 
471 static int ingenic_pinmux_set_pin_fn(struct ingenic_pinctrl *jzpc,
472 		int pin, int func)
473 {
474 	unsigned int idx = pin % PINS_PER_GPIO_CHIP;
475 	unsigned int offt = pin / PINS_PER_GPIO_CHIP;
476 
477 	dev_dbg(jzpc->dev, "set pin P%c%u to function %u\n",
478 			'A' + offt, idx, func);
479 
480 	if (jzpc->version >= ID_JZ4770) {
481 		ingenic_config_pin(jzpc, pin, JZ4770_GPIO_INT, false);
482 		ingenic_config_pin(jzpc, pin, JZ4770_GPIO_MSK, false);
483 		ingenic_config_pin(jzpc, pin, JZ4770_GPIO_PAT1, func & 0x2);
484 		ingenic_config_pin(jzpc, pin, JZ4770_GPIO_PAT0, func & 0x1);
485 	} else {
486 		ingenic_config_pin(jzpc, pin, JZ4740_GPIO_FUNC, true);
487 		ingenic_config_pin(jzpc, pin, JZ4740_GPIO_TRIG, func & 0x2);
488 		ingenic_config_pin(jzpc, pin, JZ4740_GPIO_SELECT, func > 0);
489 	}
490 
491 	return 0;
492 }
493 
494 static int ingenic_pinmux_set_mux(struct pinctrl_dev *pctldev,
495 		unsigned int selector, unsigned int group)
496 {
497 	struct ingenic_pinctrl *jzpc = pinctrl_dev_get_drvdata(pctldev);
498 	struct function_desc *func;
499 	struct group_desc *grp;
500 	unsigned int i;
501 
502 	func = pinmux_generic_get_function(pctldev, selector);
503 	if (!func)
504 		return -EINVAL;
505 
506 	grp = pinctrl_generic_get_group(pctldev, group);
507 	if (!grp)
508 		return -EINVAL;
509 
510 	dev_dbg(pctldev->dev, "enable function %s group %s\n",
511 		func->name, grp->name);
512 
513 	for (i = 0; i < grp->num_pins; i++) {
514 		int *pin_modes = grp->data;
515 
516 		ingenic_pinmux_set_pin_fn(jzpc, grp->pins[i], pin_modes[i]);
517 	}
518 
519 	return 0;
520 }
521 
522 static int ingenic_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
523 		struct pinctrl_gpio_range *range,
524 		unsigned int pin, bool input)
525 {
526 	struct ingenic_pinctrl *jzpc = pinctrl_dev_get_drvdata(pctldev);
527 	unsigned int idx = pin % PINS_PER_GPIO_CHIP;
528 	unsigned int offt = pin / PINS_PER_GPIO_CHIP;
529 
530 	dev_dbg(pctldev->dev, "set pin P%c%u to %sput\n",
531 			'A' + offt, idx, input ? "in" : "out");
532 
533 	if (jzpc->version >= ID_JZ4770) {
534 		ingenic_config_pin(jzpc, pin, JZ4770_GPIO_INT, false);
535 		ingenic_config_pin(jzpc, pin, JZ4770_GPIO_MSK, true);
536 		ingenic_config_pin(jzpc, pin, JZ4770_GPIO_PAT1, input);
537 	} else {
538 		ingenic_config_pin(jzpc, pin, JZ4740_GPIO_SELECT, false);
539 		ingenic_config_pin(jzpc, pin, JZ4740_GPIO_DIR, input);
540 		ingenic_config_pin(jzpc, pin, JZ4740_GPIO_FUNC, false);
541 	}
542 
543 	return 0;
544 }
545 
546 static const struct pinmux_ops ingenic_pmxops = {
547 	.get_functions_count = pinmux_generic_get_function_count,
548 	.get_function_name = pinmux_generic_get_function_name,
549 	.get_function_groups = pinmux_generic_get_function_groups,
550 	.set_mux = ingenic_pinmux_set_mux,
551 	.gpio_set_direction = ingenic_pinmux_gpio_set_direction,
552 };
553 
554 static int ingenic_pinconf_get(struct pinctrl_dev *pctldev,
555 		unsigned int pin, unsigned long *config)
556 {
557 	struct ingenic_pinctrl *jzpc = pinctrl_dev_get_drvdata(pctldev);
558 	enum pin_config_param param = pinconf_to_config_param(*config);
559 	unsigned int idx = pin % PINS_PER_GPIO_CHIP;
560 	unsigned int offt = pin / PINS_PER_GPIO_CHIP;
561 	bool pull;
562 
563 	if (jzpc->version >= ID_JZ4770)
564 		pull = !ingenic_get_pin_config(jzpc, pin, JZ4770_GPIO_PEN);
565 	else
566 		pull = !ingenic_get_pin_config(jzpc, pin, JZ4740_GPIO_PULL_DIS);
567 
568 	switch (param) {
569 	case PIN_CONFIG_BIAS_DISABLE:
570 		if (pull)
571 			return -EINVAL;
572 		break;
573 
574 	case PIN_CONFIG_BIAS_PULL_UP:
575 		if (!pull || !(jzpc->info->pull_ups[offt] & BIT(idx)))
576 			return -EINVAL;
577 		break;
578 
579 	case PIN_CONFIG_BIAS_PULL_DOWN:
580 		if (!pull || !(jzpc->info->pull_downs[offt] & BIT(idx)))
581 			return -EINVAL;
582 		break;
583 
584 	default:
585 		return -ENOTSUPP;
586 	}
587 
588 	*config = pinconf_to_config_packed(param, 1);
589 	return 0;
590 }
591 
592 static void ingenic_set_bias(struct ingenic_pinctrl *jzpc,
593 		unsigned int pin, bool enabled)
594 {
595 	if (jzpc->version >= ID_JZ4770)
596 		ingenic_config_pin(jzpc, pin, JZ4770_GPIO_PEN, !enabled);
597 	else
598 		ingenic_config_pin(jzpc, pin, JZ4740_GPIO_PULL_DIS, !enabled);
599 }
600 
601 static int ingenic_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
602 		unsigned long *configs, unsigned int num_configs)
603 {
604 	struct ingenic_pinctrl *jzpc = pinctrl_dev_get_drvdata(pctldev);
605 	unsigned int idx = pin % PINS_PER_GPIO_CHIP;
606 	unsigned int offt = pin / PINS_PER_GPIO_CHIP;
607 	unsigned int cfg;
608 
609 	for (cfg = 0; cfg < num_configs; cfg++) {
610 		switch (pinconf_to_config_param(configs[cfg])) {
611 		case PIN_CONFIG_BIAS_DISABLE:
612 		case PIN_CONFIG_BIAS_PULL_UP:
613 		case PIN_CONFIG_BIAS_PULL_DOWN:
614 			continue;
615 		default:
616 			return -ENOTSUPP;
617 		}
618 	}
619 
620 	for (cfg = 0; cfg < num_configs; cfg++) {
621 		switch (pinconf_to_config_param(configs[cfg])) {
622 		case PIN_CONFIG_BIAS_DISABLE:
623 			dev_dbg(jzpc->dev, "disable pull-over for pin P%c%u\n",
624 					'A' + offt, idx);
625 			ingenic_set_bias(jzpc, pin, false);
626 			break;
627 
628 		case PIN_CONFIG_BIAS_PULL_UP:
629 			if (!(jzpc->info->pull_ups[offt] & BIT(idx)))
630 				return -EINVAL;
631 			dev_dbg(jzpc->dev, "set pull-up for pin P%c%u\n",
632 					'A' + offt, idx);
633 			ingenic_set_bias(jzpc, pin, true);
634 			break;
635 
636 		case PIN_CONFIG_BIAS_PULL_DOWN:
637 			if (!(jzpc->info->pull_downs[offt] & BIT(idx)))
638 				return -EINVAL;
639 			dev_dbg(jzpc->dev, "set pull-down for pin P%c%u\n",
640 					'A' + offt, idx);
641 			ingenic_set_bias(jzpc, pin, true);
642 			break;
643 
644 		default:
645 			unreachable();
646 		}
647 	}
648 
649 	return 0;
650 }
651 
652 static int ingenic_pinconf_group_get(struct pinctrl_dev *pctldev,
653 		unsigned int group, unsigned long *config)
654 {
655 	const unsigned int *pins;
656 	unsigned int i, npins, old = 0;
657 	int ret;
658 
659 	ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins);
660 	if (ret)
661 		return ret;
662 
663 	for (i = 0; i < npins; i++) {
664 		if (ingenic_pinconf_get(pctldev, pins[i], config))
665 			return -ENOTSUPP;
666 
667 		/* configs do not match between two pins */
668 		if (i && (old != *config))
669 			return -ENOTSUPP;
670 
671 		old = *config;
672 	}
673 
674 	return 0;
675 }
676 
677 static int ingenic_pinconf_group_set(struct pinctrl_dev *pctldev,
678 		unsigned int group, unsigned long *configs,
679 		unsigned int num_configs)
680 {
681 	const unsigned int *pins;
682 	unsigned int i, npins;
683 	int ret;
684 
685 	ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins);
686 	if (ret)
687 		return ret;
688 
689 	for (i = 0; i < npins; i++) {
690 		ret = ingenic_pinconf_set(pctldev,
691 				pins[i], configs, num_configs);
692 		if (ret)
693 			return ret;
694 	}
695 
696 	return 0;
697 }
698 
699 static const struct pinconf_ops ingenic_confops = {
700 	.is_generic = true,
701 	.pin_config_get = ingenic_pinconf_get,
702 	.pin_config_set = ingenic_pinconf_set,
703 	.pin_config_group_get = ingenic_pinconf_group_get,
704 	.pin_config_group_set = ingenic_pinconf_group_set,
705 };
706 
707 static const struct regmap_config ingenic_pinctrl_regmap_config = {
708 	.reg_bits = 32,
709 	.val_bits = 32,
710 	.reg_stride = 4,
711 };
712 
713 static const struct of_device_id ingenic_pinctrl_of_match[] = {
714 	{ .compatible = "ingenic,jz4740-pinctrl", .data = (void *) ID_JZ4740 },
715 	{ .compatible = "ingenic,jz4770-pinctrl", .data = (void *) ID_JZ4770 },
716 	{ .compatible = "ingenic,jz4780-pinctrl", .data = (void *) ID_JZ4780 },
717 	{},
718 };
719 
720 static int ingenic_pinctrl_probe(struct platform_device *pdev)
721 {
722 	struct device *dev = &pdev->dev;
723 	struct ingenic_pinctrl *jzpc;
724 	struct pinctrl_desc *pctl_desc;
725 	void __iomem *base;
726 	const struct platform_device_id *id = platform_get_device_id(pdev);
727 	const struct of_device_id *of_id = of_match_device(
728 			ingenic_pinctrl_of_match, dev);
729 	const struct ingenic_chip_info *chip_info;
730 	unsigned int i;
731 	int err;
732 
733 	jzpc = devm_kzalloc(dev, sizeof(*jzpc), GFP_KERNEL);
734 	if (!jzpc)
735 		return -ENOMEM;
736 
737 	base = devm_ioremap_resource(dev,
738 			platform_get_resource(pdev, IORESOURCE_MEM, 0));
739 	if (IS_ERR(base))
740 		return PTR_ERR(base);
741 
742 	jzpc->map = devm_regmap_init_mmio(dev, base,
743 			&ingenic_pinctrl_regmap_config);
744 	if (IS_ERR(jzpc->map)) {
745 		dev_err(dev, "Failed to create regmap\n");
746 		return PTR_ERR(jzpc->map);
747 	}
748 
749 	jzpc->dev = dev;
750 
751 	if (of_id)
752 		jzpc->version = (enum jz_version)of_id->data;
753 	else
754 		jzpc->version = (enum jz_version)id->driver_data;
755 
756 	if (jzpc->version >= ID_JZ4770)
757 		chip_info = &jz4770_chip_info;
758 	else
759 		chip_info = &jz4740_chip_info;
760 	jzpc->info = chip_info;
761 
762 	pctl_desc = devm_kzalloc(&pdev->dev, sizeof(*pctl_desc), GFP_KERNEL);
763 	if (!pctl_desc)
764 		return -ENOMEM;
765 
766 	/* fill in pinctrl_desc structure */
767 	pctl_desc->name = dev_name(dev);
768 	pctl_desc->owner = THIS_MODULE;
769 	pctl_desc->pctlops = &ingenic_pctlops;
770 	pctl_desc->pmxops = &ingenic_pmxops;
771 	pctl_desc->confops = &ingenic_confops;
772 	pctl_desc->npins = chip_info->num_chips * PINS_PER_GPIO_CHIP;
773 	pctl_desc->pins = jzpc->pdesc = devm_kzalloc(&pdev->dev,
774 			sizeof(*jzpc->pdesc) * pctl_desc->npins, GFP_KERNEL);
775 	if (!jzpc->pdesc)
776 		return -ENOMEM;
777 
778 	for (i = 0; i < pctl_desc->npins; i++) {
779 		jzpc->pdesc[i].number = i;
780 		jzpc->pdesc[i].name = kasprintf(GFP_KERNEL, "P%c%d",
781 						'A' + (i / PINS_PER_GPIO_CHIP),
782 						i % PINS_PER_GPIO_CHIP);
783 	}
784 
785 	jzpc->pctl = devm_pinctrl_register(dev, pctl_desc, jzpc);
786 	if (IS_ERR(jzpc->pctl)) {
787 		dev_err(dev, "Failed to register pinctrl\n");
788 		return PTR_ERR(jzpc->pctl);
789 	}
790 
791 	for (i = 0; i < chip_info->num_groups; i++) {
792 		const struct group_desc *group = &chip_info->groups[i];
793 
794 		err = pinctrl_generic_add_group(jzpc->pctl, group->name,
795 				group->pins, group->num_pins, group->data);
796 		if (err) {
797 			dev_err(dev, "Failed to register group %s\n",
798 					group->name);
799 			return err;
800 		}
801 	}
802 
803 	for (i = 0; i < chip_info->num_functions; i++) {
804 		const struct function_desc *func = &chip_info->functions[i];
805 
806 		err = pinmux_generic_add_function(jzpc->pctl, func->name,
807 				func->group_names, func->num_group_names,
808 				func->data);
809 		if (err) {
810 			dev_err(dev, "Failed to register function %s\n",
811 					func->name);
812 			return err;
813 		}
814 	}
815 
816 	dev_set_drvdata(dev, jzpc->map);
817 
818 	if (dev->of_node) {
819 		err = of_platform_populate(dev->of_node, NULL, NULL, dev);
820 		if (err) {
821 			dev_err(dev, "Failed to probe GPIO devices\n");
822 			return err;
823 		}
824 	}
825 
826 	return 0;
827 }
828 
829 static const struct platform_device_id ingenic_pinctrl_ids[] = {
830 	{ "jz4740-pinctrl", ID_JZ4740 },
831 	{ "jz4770-pinctrl", ID_JZ4770 },
832 	{ "jz4780-pinctrl", ID_JZ4780 },
833 	{},
834 };
835 
836 static struct platform_driver ingenic_pinctrl_driver = {
837 	.driver = {
838 		.name = "pinctrl-ingenic",
839 		.of_match_table = of_match_ptr(ingenic_pinctrl_of_match),
840 		.suppress_bind_attrs = true,
841 	},
842 	.probe = ingenic_pinctrl_probe,
843 	.id_table = ingenic_pinctrl_ids,
844 };
845 
846 static int __init ingenic_pinctrl_drv_register(void)
847 {
848 	return platform_driver_register(&ingenic_pinctrl_driver);
849 }
850 postcore_initcall(ingenic_pinctrl_drv_register);
851