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