xref: /linux/drivers/pinctrl/pinctrl-ingenic.c (revision f2a967658a5d0f456d6f0530d3bc2b101260eeb5)
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>
14e72394e2SPaul Cercueil #include <linux/of_irq.h>
15b5c23aa4SPaul Cercueil #include <linux/of_platform.h>
16b5c23aa4SPaul Cercueil #include <linux/pinctrl/pinctrl.h>
17b5c23aa4SPaul Cercueil #include <linux/pinctrl/pinmux.h>
18b5c23aa4SPaul Cercueil #include <linux/pinctrl/pinconf.h>
19b5c23aa4SPaul Cercueil #include <linux/pinctrl/pinconf-generic.h>
20b5c23aa4SPaul Cercueil #include <linux/platform_device.h>
21b5c23aa4SPaul Cercueil #include <linux/regmap.h>
22b5c23aa4SPaul Cercueil #include <linux/slab.h>
23b5c23aa4SPaul Cercueil 
24b5c23aa4SPaul Cercueil #include "core.h"
25b5c23aa4SPaul Cercueil #include "pinconf.h"
26b5c23aa4SPaul Cercueil #include "pinmux.h"
27b5c23aa4SPaul Cercueil 
28e72394e2SPaul Cercueil #define GPIO_PIN	0x00
29e72394e2SPaul Cercueil #define GPIO_MSK	0x20
30e72394e2SPaul Cercueil 
31b5c23aa4SPaul Cercueil #define JZ4740_GPIO_DATA	0x10
32b5c23aa4SPaul Cercueil #define JZ4740_GPIO_PULL_DIS	0x30
33b5c23aa4SPaul Cercueil #define JZ4740_GPIO_FUNC	0x40
34b5c23aa4SPaul Cercueil #define JZ4740_GPIO_SELECT	0x50
35b5c23aa4SPaul Cercueil #define JZ4740_GPIO_DIR		0x60
36b5c23aa4SPaul Cercueil #define JZ4740_GPIO_TRIG	0x70
37b5c23aa4SPaul Cercueil #define JZ4740_GPIO_FLAG	0x80
38b5c23aa4SPaul Cercueil 
39b5c23aa4SPaul Cercueil #define JZ4770_GPIO_INT		0x10
40b5c23aa4SPaul Cercueil #define JZ4770_GPIO_PAT1	0x30
41b5c23aa4SPaul Cercueil #define JZ4770_GPIO_PAT0	0x40
42b5c23aa4SPaul Cercueil #define JZ4770_GPIO_FLAG	0x50
43b5c23aa4SPaul Cercueil #define JZ4770_GPIO_PEN		0x70
44b5c23aa4SPaul Cercueil 
45b5c23aa4SPaul Cercueil #define REG_SET(x) ((x) + 0x4)
46b5c23aa4SPaul Cercueil #define REG_CLEAR(x) ((x) + 0x8)
47b5c23aa4SPaul Cercueil 
48b5c23aa4SPaul Cercueil #define PINS_PER_GPIO_CHIP 32
49b5c23aa4SPaul Cercueil 
50b5c23aa4SPaul Cercueil enum jz_version {
51b5c23aa4SPaul Cercueil 	ID_JZ4740,
52*f2a96765SPaul Cercueil 	ID_JZ4725B,
53b5c23aa4SPaul Cercueil 	ID_JZ4770,
54b5c23aa4SPaul Cercueil 	ID_JZ4780,
55b5c23aa4SPaul Cercueil };
56b5c23aa4SPaul Cercueil 
57b5c23aa4SPaul Cercueil struct ingenic_chip_info {
58b5c23aa4SPaul Cercueil 	unsigned int num_chips;
59b5c23aa4SPaul Cercueil 
60b5c23aa4SPaul Cercueil 	const struct group_desc *groups;
61b5c23aa4SPaul Cercueil 	unsigned int num_groups;
62b5c23aa4SPaul Cercueil 
63b5c23aa4SPaul Cercueil 	const struct function_desc *functions;
64b5c23aa4SPaul Cercueil 	unsigned int num_functions;
65b5c23aa4SPaul Cercueil 
66b5c23aa4SPaul Cercueil 	const u32 *pull_ups, *pull_downs;
67b5c23aa4SPaul Cercueil };
68b5c23aa4SPaul Cercueil 
69b5c23aa4SPaul Cercueil struct ingenic_pinctrl {
70b5c23aa4SPaul Cercueil 	struct device *dev;
71b5c23aa4SPaul Cercueil 	struct regmap *map;
72b5c23aa4SPaul Cercueil 	struct pinctrl_dev *pctl;
73b5c23aa4SPaul Cercueil 	struct pinctrl_pin_desc *pdesc;
74b5c23aa4SPaul Cercueil 	enum jz_version version;
75b5c23aa4SPaul Cercueil 
76b5c23aa4SPaul Cercueil 	const struct ingenic_chip_info *info;
77b5c23aa4SPaul Cercueil };
78b5c23aa4SPaul Cercueil 
79e72394e2SPaul Cercueil struct ingenic_gpio_chip {
80e72394e2SPaul Cercueil 	struct ingenic_pinctrl *jzpc;
81e72394e2SPaul Cercueil 	struct gpio_chip gc;
82e72394e2SPaul Cercueil 	struct irq_chip irq_chip;
83e72394e2SPaul Cercueil 	unsigned int irq, reg_base;
84e72394e2SPaul Cercueil };
85e72394e2SPaul Cercueil 
86b5c23aa4SPaul Cercueil static const u32 jz4740_pull_ups[4] = {
87b5c23aa4SPaul Cercueil 	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
88b5c23aa4SPaul Cercueil };
89b5c23aa4SPaul Cercueil 
90b5c23aa4SPaul Cercueil static const u32 jz4740_pull_downs[4] = {
91b5c23aa4SPaul Cercueil 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
92b5c23aa4SPaul Cercueil };
93b5c23aa4SPaul Cercueil 
94b5c23aa4SPaul Cercueil static int jz4740_mmc_1bit_pins[] = { 0x69, 0x68, 0x6a, };
95b5c23aa4SPaul Cercueil static int jz4740_mmc_4bit_pins[] = { 0x6b, 0x6c, 0x6d, };
96b5c23aa4SPaul Cercueil static int jz4740_uart0_data_pins[] = { 0x7a, 0x79, };
97b5c23aa4SPaul Cercueil static int jz4740_uart0_hwflow_pins[] = { 0x7e, 0x7f, };
98b5c23aa4SPaul Cercueil static int jz4740_uart1_data_pins[] = { 0x7e, 0x7f, };
99b5c23aa4SPaul Cercueil static int jz4740_lcd_8bit_pins[] = {
100b5c23aa4SPaul Cercueil 	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x52, 0x53, 0x54,
101b5c23aa4SPaul Cercueil };
102b5c23aa4SPaul Cercueil static int jz4740_lcd_16bit_pins[] = {
103b5c23aa4SPaul Cercueil 	0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x55,
104b5c23aa4SPaul Cercueil };
105b5c23aa4SPaul Cercueil static int jz4740_lcd_18bit_pins[] = { 0x50, 0x51, };
106b5c23aa4SPaul Cercueil static int jz4740_lcd_18bit_tft_pins[] = { 0x56, 0x57, 0x31, 0x32, };
107b5c23aa4SPaul Cercueil static int jz4740_nand_cs1_pins[] = { 0x39, };
108b5c23aa4SPaul Cercueil static int jz4740_nand_cs2_pins[] = { 0x3a, };
109b5c23aa4SPaul Cercueil static int jz4740_nand_cs3_pins[] = { 0x3b, };
110b5c23aa4SPaul Cercueil static int jz4740_nand_cs4_pins[] = { 0x3c, };
111b5c23aa4SPaul Cercueil static int jz4740_pwm_pwm0_pins[] = { 0x77, };
112b5c23aa4SPaul Cercueil static int jz4740_pwm_pwm1_pins[] = { 0x78, };
113b5c23aa4SPaul Cercueil static int jz4740_pwm_pwm2_pins[] = { 0x79, };
114b5c23aa4SPaul Cercueil static int jz4740_pwm_pwm3_pins[] = { 0x7a, };
115b5c23aa4SPaul Cercueil static int jz4740_pwm_pwm4_pins[] = { 0x7b, };
116b5c23aa4SPaul Cercueil static int jz4740_pwm_pwm5_pins[] = { 0x7c, };
117b5c23aa4SPaul Cercueil static int jz4740_pwm_pwm6_pins[] = { 0x7e, };
118b5c23aa4SPaul Cercueil static int jz4740_pwm_pwm7_pins[] = { 0x7f, };
119b5c23aa4SPaul Cercueil 
120b5c23aa4SPaul Cercueil static int jz4740_mmc_1bit_funcs[] = { 0, 0, 0, };
121b5c23aa4SPaul Cercueil static int jz4740_mmc_4bit_funcs[] = { 0, 0, 0, };
122b5c23aa4SPaul Cercueil static int jz4740_uart0_data_funcs[] = { 1, 1, };
123b5c23aa4SPaul Cercueil static int jz4740_uart0_hwflow_funcs[] = { 1, 1, };
124b5c23aa4SPaul Cercueil static int jz4740_uart1_data_funcs[] = { 2, 2, };
125b5c23aa4SPaul Cercueil static int jz4740_lcd_8bit_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
126b5c23aa4SPaul Cercueil static int jz4740_lcd_16bit_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, };
127b5c23aa4SPaul Cercueil static int jz4740_lcd_18bit_funcs[] = { 0, 0, };
128b5c23aa4SPaul Cercueil static int jz4740_lcd_18bit_tft_funcs[] = { 0, 0, 0, 0, };
129b5c23aa4SPaul Cercueil static int jz4740_nand_cs1_funcs[] = { 0, };
130b5c23aa4SPaul Cercueil static int jz4740_nand_cs2_funcs[] = { 0, };
131b5c23aa4SPaul Cercueil static int jz4740_nand_cs3_funcs[] = { 0, };
132b5c23aa4SPaul Cercueil static int jz4740_nand_cs4_funcs[] = { 0, };
133b5c23aa4SPaul Cercueil static int jz4740_pwm_pwm0_funcs[] = { 0, };
134b5c23aa4SPaul Cercueil static int jz4740_pwm_pwm1_funcs[] = { 0, };
135b5c23aa4SPaul Cercueil static int jz4740_pwm_pwm2_funcs[] = { 0, };
136b5c23aa4SPaul Cercueil static int jz4740_pwm_pwm3_funcs[] = { 0, };
137b5c23aa4SPaul Cercueil static int jz4740_pwm_pwm4_funcs[] = { 0, };
138b5c23aa4SPaul Cercueil static int jz4740_pwm_pwm5_funcs[] = { 0, };
139b5c23aa4SPaul Cercueil static int jz4740_pwm_pwm6_funcs[] = { 0, };
140b5c23aa4SPaul Cercueil static int jz4740_pwm_pwm7_funcs[] = { 0, };
141b5c23aa4SPaul Cercueil 
142b5c23aa4SPaul Cercueil #define INGENIC_PIN_GROUP(name, id)			\
143b5c23aa4SPaul Cercueil 	{						\
144b5c23aa4SPaul Cercueil 		name,					\
145b5c23aa4SPaul Cercueil 		id##_pins,				\
146b5c23aa4SPaul Cercueil 		ARRAY_SIZE(id##_pins),			\
147b5c23aa4SPaul Cercueil 		id##_funcs,				\
148b5c23aa4SPaul Cercueil 	}
149b5c23aa4SPaul Cercueil 
150b5c23aa4SPaul Cercueil static const struct group_desc jz4740_groups[] = {
151b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("mmc-1bit", jz4740_mmc_1bit),
152b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("mmc-4bit", jz4740_mmc_4bit),
153b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("uart0-data", jz4740_uart0_data),
154b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("uart0-hwflow", jz4740_uart0_hwflow),
155b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("uart1-data", jz4740_uart1_data),
156b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("lcd-8bit", jz4740_lcd_8bit),
157b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("lcd-16bit", jz4740_lcd_16bit),
158b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("lcd-18bit", jz4740_lcd_18bit),
159b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("lcd-18bit-tft", jz4740_lcd_18bit_tft),
160b5c23aa4SPaul Cercueil 	{ "lcd-no-pins", },
161b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("nand-cs1", jz4740_nand_cs1),
162b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("nand-cs2", jz4740_nand_cs2),
163b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("nand-cs3", jz4740_nand_cs3),
164b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("nand-cs4", jz4740_nand_cs4),
165b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("pwm0", jz4740_pwm_pwm0),
166b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("pwm1", jz4740_pwm_pwm1),
167b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("pwm2", jz4740_pwm_pwm2),
168b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("pwm3", jz4740_pwm_pwm3),
169b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("pwm4", jz4740_pwm_pwm4),
170b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("pwm5", jz4740_pwm_pwm5),
171b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("pwm6", jz4740_pwm_pwm6),
172b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("pwm7", jz4740_pwm_pwm7),
173b5c23aa4SPaul Cercueil };
174b5c23aa4SPaul Cercueil 
175b5c23aa4SPaul Cercueil static const char *jz4740_mmc_groups[] = { "mmc-1bit", "mmc-4bit", };
176b5c23aa4SPaul Cercueil static const char *jz4740_uart0_groups[] = { "uart0-data", "uart0-hwflow", };
177b5c23aa4SPaul Cercueil static const char *jz4740_uart1_groups[] = { "uart1-data", };
178b5c23aa4SPaul Cercueil static const char *jz4740_lcd_groups[] = {
179b5c23aa4SPaul Cercueil 	"lcd-8bit", "lcd-16bit", "lcd-18bit", "lcd-18bit-tft", "lcd-no-pins",
180b5c23aa4SPaul Cercueil };
181b5c23aa4SPaul Cercueil static const char *jz4740_nand_groups[] = {
182b5c23aa4SPaul Cercueil 	"nand-cs1", "nand-cs2", "nand-cs3", "nand-cs4",
183b5c23aa4SPaul Cercueil };
184b5c23aa4SPaul Cercueil static const char *jz4740_pwm0_groups[] = { "pwm0", };
185b5c23aa4SPaul Cercueil static const char *jz4740_pwm1_groups[] = { "pwm1", };
186b5c23aa4SPaul Cercueil static const char *jz4740_pwm2_groups[] = { "pwm2", };
187b5c23aa4SPaul Cercueil static const char *jz4740_pwm3_groups[] = { "pwm3", };
188b5c23aa4SPaul Cercueil static const char *jz4740_pwm4_groups[] = { "pwm4", };
189b5c23aa4SPaul Cercueil static const char *jz4740_pwm5_groups[] = { "pwm5", };
190b5c23aa4SPaul Cercueil static const char *jz4740_pwm6_groups[] = { "pwm6", };
191b5c23aa4SPaul Cercueil static const char *jz4740_pwm7_groups[] = { "pwm7", };
192b5c23aa4SPaul Cercueil 
193b5c23aa4SPaul Cercueil static const struct function_desc jz4740_functions[] = {
194b5c23aa4SPaul Cercueil 	{ "mmc", jz4740_mmc_groups, ARRAY_SIZE(jz4740_mmc_groups), },
195b5c23aa4SPaul Cercueil 	{ "uart0", jz4740_uart0_groups, ARRAY_SIZE(jz4740_uart0_groups), },
196b5c23aa4SPaul Cercueil 	{ "uart1", jz4740_uart1_groups, ARRAY_SIZE(jz4740_uart1_groups), },
197b5c23aa4SPaul Cercueil 	{ "lcd", jz4740_lcd_groups, ARRAY_SIZE(jz4740_lcd_groups), },
198b5c23aa4SPaul Cercueil 	{ "nand", jz4740_nand_groups, ARRAY_SIZE(jz4740_nand_groups), },
199b5c23aa4SPaul Cercueil 	{ "pwm0", jz4740_pwm0_groups, ARRAY_SIZE(jz4740_pwm0_groups), },
200b5c23aa4SPaul Cercueil 	{ "pwm1", jz4740_pwm1_groups, ARRAY_SIZE(jz4740_pwm1_groups), },
201b5c23aa4SPaul Cercueil 	{ "pwm2", jz4740_pwm2_groups, ARRAY_SIZE(jz4740_pwm2_groups), },
202b5c23aa4SPaul Cercueil 	{ "pwm3", jz4740_pwm3_groups, ARRAY_SIZE(jz4740_pwm3_groups), },
203b5c23aa4SPaul Cercueil 	{ "pwm4", jz4740_pwm4_groups, ARRAY_SIZE(jz4740_pwm4_groups), },
204b5c23aa4SPaul Cercueil 	{ "pwm5", jz4740_pwm5_groups, ARRAY_SIZE(jz4740_pwm5_groups), },
205b5c23aa4SPaul Cercueil 	{ "pwm6", jz4740_pwm6_groups, ARRAY_SIZE(jz4740_pwm6_groups), },
206b5c23aa4SPaul Cercueil 	{ "pwm7", jz4740_pwm7_groups, ARRAY_SIZE(jz4740_pwm7_groups), },
207b5c23aa4SPaul Cercueil };
208b5c23aa4SPaul Cercueil 
209b5c23aa4SPaul Cercueil static const struct ingenic_chip_info jz4740_chip_info = {
210b5c23aa4SPaul Cercueil 	.num_chips = 4,
211b5c23aa4SPaul Cercueil 	.groups = jz4740_groups,
212b5c23aa4SPaul Cercueil 	.num_groups = ARRAY_SIZE(jz4740_groups),
213b5c23aa4SPaul Cercueil 	.functions = jz4740_functions,
214b5c23aa4SPaul Cercueil 	.num_functions = ARRAY_SIZE(jz4740_functions),
215b5c23aa4SPaul Cercueil 	.pull_ups = jz4740_pull_ups,
216b5c23aa4SPaul Cercueil 	.pull_downs = jz4740_pull_downs,
217b5c23aa4SPaul Cercueil };
218b5c23aa4SPaul Cercueil 
219*f2a96765SPaul Cercueil static int jz4725b_mmc0_1bit_pins[] = { 0x48, 0x49, 0x5c, };
220*f2a96765SPaul Cercueil static int jz4725b_mmc0_4bit_pins[] = { 0x5d, 0x5b, 0x56, };
221*f2a96765SPaul Cercueil static int jz4725b_mmc1_1bit_pins[] = { 0x7a, 0x7b, 0x7c, };
222*f2a96765SPaul Cercueil static int jz4725b_mmc1_4bit_pins[] = { 0x7d, 0x7e, 0x7f, };
223*f2a96765SPaul Cercueil static int jz4725b_uart_data_pins[] = { 0x4c, 0x4d, };
224*f2a96765SPaul Cercueil static int jz4725b_nand_cs1_pins[] = { 0x55, };
225*f2a96765SPaul Cercueil static int jz4725b_nand_cs2_pins[] = { 0x56, };
226*f2a96765SPaul Cercueil static int jz4725b_nand_cs3_pins[] = { 0x57, };
227*f2a96765SPaul Cercueil static int jz4725b_nand_cs4_pins[] = { 0x58, };
228*f2a96765SPaul Cercueil static int jz4725b_nand_cle_ale_pins[] = { 0x48, 0x49 };
229*f2a96765SPaul Cercueil static int jz4725b_nand_fre_fwe_pins[] = { 0x5c, 0x5d };
230*f2a96765SPaul Cercueil static int jz4725b_pwm_pwm0_pins[] = { 0x4a, };
231*f2a96765SPaul Cercueil static int jz4725b_pwm_pwm1_pins[] = { 0x4b, };
232*f2a96765SPaul Cercueil static int jz4725b_pwm_pwm2_pins[] = { 0x4c, };
233*f2a96765SPaul Cercueil static int jz4725b_pwm_pwm3_pins[] = { 0x4d, };
234*f2a96765SPaul Cercueil static int jz4725b_pwm_pwm4_pins[] = { 0x4e, };
235*f2a96765SPaul Cercueil static int jz4725b_pwm_pwm5_pins[] = { 0x4f, };
236*f2a96765SPaul Cercueil 
237*f2a96765SPaul Cercueil static int jz4725b_mmc0_1bit_funcs[] = { 1, 1, 1, };
238*f2a96765SPaul Cercueil static int jz4725b_mmc0_4bit_funcs[] = { 1, 0, 1, };
239*f2a96765SPaul Cercueil static int jz4725b_mmc1_1bit_funcs[] = { 0, 0, 0, };
240*f2a96765SPaul Cercueil static int jz4725b_mmc1_4bit_funcs[] = { 0, 0, 0, };
241*f2a96765SPaul Cercueil static int jz4725b_uart_data_funcs[] = { 1, 1, };
242*f2a96765SPaul Cercueil static int jz4725b_nand_cs1_funcs[] = { 0, };
243*f2a96765SPaul Cercueil static int jz4725b_nand_cs2_funcs[] = { 0, };
244*f2a96765SPaul Cercueil static int jz4725b_nand_cs3_funcs[] = { 0, };
245*f2a96765SPaul Cercueil static int jz4725b_nand_cs4_funcs[] = { 0, };
246*f2a96765SPaul Cercueil static int jz4725b_nand_cle_ale_funcs[] = { 0, 0, };
247*f2a96765SPaul Cercueil static int jz4725b_nand_fre_fwe_funcs[] = { 0, 0, };
248*f2a96765SPaul Cercueil static int jz4725b_pwm_pwm0_funcs[] = { 0, };
249*f2a96765SPaul Cercueil static int jz4725b_pwm_pwm1_funcs[] = { 0, };
250*f2a96765SPaul Cercueil static int jz4725b_pwm_pwm2_funcs[] = { 0, };
251*f2a96765SPaul Cercueil static int jz4725b_pwm_pwm3_funcs[] = { 0, };
252*f2a96765SPaul Cercueil static int jz4725b_pwm_pwm4_funcs[] = { 0, };
253*f2a96765SPaul Cercueil static int jz4725b_pwm_pwm5_funcs[] = { 0, };
254*f2a96765SPaul Cercueil 
255*f2a96765SPaul Cercueil static const struct group_desc jz4725b_groups[] = {
256*f2a96765SPaul Cercueil 	INGENIC_PIN_GROUP("mmc0-1bit", jz4725b_mmc0_1bit),
257*f2a96765SPaul Cercueil 	INGENIC_PIN_GROUP("mmc0-4bit", jz4725b_mmc0_4bit),
258*f2a96765SPaul Cercueil 	INGENIC_PIN_GROUP("mmc1-1bit", jz4725b_mmc1_1bit),
259*f2a96765SPaul Cercueil 	INGENIC_PIN_GROUP("mmc1-4bit", jz4725b_mmc1_4bit),
260*f2a96765SPaul Cercueil 	INGENIC_PIN_GROUP("uart-data", jz4725b_uart_data),
261*f2a96765SPaul Cercueil 	INGENIC_PIN_GROUP("nand-cs1", jz4725b_nand_cs1),
262*f2a96765SPaul Cercueil 	INGENIC_PIN_GROUP("nand-cs2", jz4725b_nand_cs2),
263*f2a96765SPaul Cercueil 	INGENIC_PIN_GROUP("nand-cs3", jz4725b_nand_cs3),
264*f2a96765SPaul Cercueil 	INGENIC_PIN_GROUP("nand-cs4", jz4725b_nand_cs4),
265*f2a96765SPaul Cercueil 	INGENIC_PIN_GROUP("nand-cle-ale", jz4725b_nand_cle_ale),
266*f2a96765SPaul Cercueil 	INGENIC_PIN_GROUP("nand-fre-fwe", jz4725b_nand_fre_fwe),
267*f2a96765SPaul Cercueil 	INGENIC_PIN_GROUP("pwm0", jz4725b_pwm_pwm0),
268*f2a96765SPaul Cercueil 	INGENIC_PIN_GROUP("pwm1", jz4725b_pwm_pwm1),
269*f2a96765SPaul Cercueil 	INGENIC_PIN_GROUP("pwm2", jz4725b_pwm_pwm2),
270*f2a96765SPaul Cercueil 	INGENIC_PIN_GROUP("pwm3", jz4725b_pwm_pwm3),
271*f2a96765SPaul Cercueil 	INGENIC_PIN_GROUP("pwm4", jz4725b_pwm_pwm4),
272*f2a96765SPaul Cercueil 	INGENIC_PIN_GROUP("pwm5", jz4725b_pwm_pwm5),
273*f2a96765SPaul Cercueil };
274*f2a96765SPaul Cercueil 
275*f2a96765SPaul Cercueil static const char *jz4725b_mmc0_groups[] = { "mmc0-1bit", "mmc0-4bit", };
276*f2a96765SPaul Cercueil static const char *jz4725b_mmc1_groups[] = { "mmc1-1bit", "mmc1-4bit", };
277*f2a96765SPaul Cercueil static const char *jz4725b_uart_groups[] = { "uart-data", };
278*f2a96765SPaul Cercueil static const char *jz4725b_nand_groups[] = {
279*f2a96765SPaul Cercueil 	"nand-cs1", "nand-cs2", "nand-cs3", "nand-cs4",
280*f2a96765SPaul Cercueil 	"nand-cle-ale", "nand-fre-fwe",
281*f2a96765SPaul Cercueil };
282*f2a96765SPaul Cercueil static const char *jz4725b_pwm0_groups[] = { "pwm0", };
283*f2a96765SPaul Cercueil static const char *jz4725b_pwm1_groups[] = { "pwm1", };
284*f2a96765SPaul Cercueil static const char *jz4725b_pwm2_groups[] = { "pwm2", };
285*f2a96765SPaul Cercueil static const char *jz4725b_pwm3_groups[] = { "pwm3", };
286*f2a96765SPaul Cercueil static const char *jz4725b_pwm4_groups[] = { "pwm4", };
287*f2a96765SPaul Cercueil static const char *jz4725b_pwm5_groups[] = { "pwm5", };
288*f2a96765SPaul Cercueil 
289*f2a96765SPaul Cercueil static const struct function_desc jz4725b_functions[] = {
290*f2a96765SPaul Cercueil 	{ "mmc0", jz4725b_mmc0_groups, ARRAY_SIZE(jz4725b_mmc0_groups), },
291*f2a96765SPaul Cercueil 	{ "mmc1", jz4725b_mmc1_groups, ARRAY_SIZE(jz4725b_mmc1_groups), },
292*f2a96765SPaul Cercueil 	{ "uart", jz4725b_uart_groups, ARRAY_SIZE(jz4725b_uart_groups), },
293*f2a96765SPaul Cercueil 	{ "nand", jz4725b_nand_groups, ARRAY_SIZE(jz4725b_nand_groups), },
294*f2a96765SPaul Cercueil 	{ "pwm0", jz4725b_pwm0_groups, ARRAY_SIZE(jz4725b_pwm0_groups), },
295*f2a96765SPaul Cercueil 	{ "pwm1", jz4725b_pwm1_groups, ARRAY_SIZE(jz4725b_pwm1_groups), },
296*f2a96765SPaul Cercueil 	{ "pwm2", jz4725b_pwm2_groups, ARRAY_SIZE(jz4725b_pwm2_groups), },
297*f2a96765SPaul Cercueil 	{ "pwm3", jz4725b_pwm3_groups, ARRAY_SIZE(jz4725b_pwm3_groups), },
298*f2a96765SPaul Cercueil 	{ "pwm4", jz4725b_pwm4_groups, ARRAY_SIZE(jz4725b_pwm4_groups), },
299*f2a96765SPaul Cercueil 	{ "pwm5", jz4725b_pwm5_groups, ARRAY_SIZE(jz4725b_pwm5_groups), },
300*f2a96765SPaul Cercueil };
301*f2a96765SPaul Cercueil 
302*f2a96765SPaul Cercueil static const struct ingenic_chip_info jz4725b_chip_info = {
303*f2a96765SPaul Cercueil 	.num_chips = 4,
304*f2a96765SPaul Cercueil 	.groups = jz4725b_groups,
305*f2a96765SPaul Cercueil 	.num_groups = ARRAY_SIZE(jz4725b_groups),
306*f2a96765SPaul Cercueil 	.functions = jz4725b_functions,
307*f2a96765SPaul Cercueil 	.num_functions = ARRAY_SIZE(jz4725b_functions),
308*f2a96765SPaul Cercueil 	.pull_ups = jz4740_pull_ups,
309*f2a96765SPaul Cercueil 	.pull_downs = jz4740_pull_downs,
310*f2a96765SPaul Cercueil };
311*f2a96765SPaul Cercueil 
312b5c23aa4SPaul Cercueil static const u32 jz4770_pull_ups[6] = {
313b5c23aa4SPaul Cercueil 	0x3fffffff, 0xfff0030c, 0xffffffff, 0xffff4fff, 0xfffffb7c, 0xffa7f00f,
314b5c23aa4SPaul Cercueil };
315b5c23aa4SPaul Cercueil 
316b5c23aa4SPaul Cercueil static const u32 jz4770_pull_downs[6] = {
317b5c23aa4SPaul Cercueil 	0x00000000, 0x000f0c03, 0x00000000, 0x0000b000, 0x00000483, 0x00580ff0,
318b5c23aa4SPaul Cercueil };
319b5c23aa4SPaul Cercueil 
320b5c23aa4SPaul Cercueil static int jz4770_uart0_data_pins[] = { 0xa0, 0xa3, };
321b5c23aa4SPaul Cercueil static int jz4770_uart0_hwflow_pins[] = { 0xa1, 0xa2, };
322b5c23aa4SPaul Cercueil static int jz4770_uart1_data_pins[] = { 0x7a, 0x7c, };
323b5c23aa4SPaul Cercueil static int jz4770_uart1_hwflow_pins[] = { 0x7b, 0x7d, };
324b5c23aa4SPaul Cercueil static int jz4770_uart2_data_pins[] = { 0x66, 0x67, };
325b5c23aa4SPaul Cercueil static int jz4770_uart2_hwflow_pins[] = { 0x65, 0x64, };
326b5c23aa4SPaul Cercueil static int jz4770_uart3_data_pins[] = { 0x6c, 0x85, };
327b5c23aa4SPaul Cercueil static int jz4770_uart3_hwflow_pins[] = { 0x88, 0x89, };
328b5c23aa4SPaul Cercueil static int jz4770_uart4_data_pins[] = { 0x54, 0x4a, };
329b5c23aa4SPaul Cercueil static int jz4770_mmc0_8bit_a_pins[] = { 0x04, 0x05, 0x06, 0x07, 0x18, };
330b5c23aa4SPaul Cercueil static int jz4770_mmc0_4bit_a_pins[] = { 0x15, 0x16, 0x17, };
331b5c23aa4SPaul Cercueil static int jz4770_mmc0_1bit_a_pins[] = { 0x12, 0x13, 0x14, };
332b5c23aa4SPaul Cercueil static int jz4770_mmc0_4bit_e_pins[] = { 0x95, 0x96, 0x97, };
333b5c23aa4SPaul Cercueil static int jz4770_mmc0_1bit_e_pins[] = { 0x9c, 0x9d, 0x94, };
334b5c23aa4SPaul Cercueil static int jz4770_mmc1_4bit_d_pins[] = { 0x75, 0x76, 0x77, };
335b5c23aa4SPaul Cercueil static int jz4770_mmc1_1bit_d_pins[] = { 0x78, 0x79, 0x74, };
336b5c23aa4SPaul Cercueil static int jz4770_mmc1_4bit_e_pins[] = { 0x95, 0x96, 0x97, };
337b5c23aa4SPaul Cercueil static int jz4770_mmc1_1bit_e_pins[] = { 0x9c, 0x9d, 0x94, };
338b5c23aa4SPaul Cercueil static int jz4770_nemc_data_pins[] = {
339b5c23aa4SPaul Cercueil 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
340b5c23aa4SPaul Cercueil };
341b5c23aa4SPaul Cercueil static int jz4770_nemc_cle_ale_pins[] = { 0x20, 0x21, };
342b5c23aa4SPaul Cercueil static int jz4770_nemc_addr_pins[] = { 0x22, 0x23, 0x24, 0x25, };
343b5c23aa4SPaul Cercueil static int jz4770_nemc_rd_we_pins[] = { 0x10, 0x11, };
344b5c23aa4SPaul Cercueil static int jz4770_nemc_frd_fwe_pins[] = { 0x12, 0x13, };
345b5c23aa4SPaul Cercueil static int jz4770_nemc_cs1_pins[] = { 0x15, };
346b5c23aa4SPaul Cercueil static int jz4770_nemc_cs2_pins[] = { 0x16, };
347b5c23aa4SPaul Cercueil static int jz4770_nemc_cs3_pins[] = { 0x17, };
348b5c23aa4SPaul Cercueil static int jz4770_nemc_cs4_pins[] = { 0x18, };
349b5c23aa4SPaul Cercueil static int jz4770_nemc_cs5_pins[] = { 0x19, };
350b5c23aa4SPaul Cercueil static int jz4770_nemc_cs6_pins[] = { 0x1a, };
351b5c23aa4SPaul Cercueil static int jz4770_i2c0_pins[] = { 0x6e, 0x6f, };
352b5c23aa4SPaul Cercueil static int jz4770_i2c1_pins[] = { 0x8e, 0x8f, };
353b5c23aa4SPaul Cercueil static int jz4770_i2c2_pins[] = { 0xb0, 0xb1, };
354b5c23aa4SPaul Cercueil static int jz4770_i2c3_pins[] = { 0x6a, 0x6b, };
355b5c23aa4SPaul Cercueil static int jz4770_i2c4_e_pins[] = { 0x8c, 0x8d, };
356b5c23aa4SPaul Cercueil static int jz4770_i2c4_f_pins[] = { 0xb9, 0xb8, };
357b5c23aa4SPaul Cercueil static int jz4770_cim_pins[] = {
358b5c23aa4SPaul Cercueil 	0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31,
359b5c23aa4SPaul Cercueil };
360b5c23aa4SPaul Cercueil static int jz4770_lcd_32bit_pins[] = {
361b5c23aa4SPaul Cercueil 	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
362b5c23aa4SPaul Cercueil 	0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
363b5c23aa4SPaul Cercueil 	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
364b5c23aa4SPaul Cercueil 	0x58, 0x59, 0x51,
365b5c23aa4SPaul Cercueil };
366b5c23aa4SPaul Cercueil static int jz4770_pwm_pwm0_pins[] = { 0x80, };
367b5c23aa4SPaul Cercueil static int jz4770_pwm_pwm1_pins[] = { 0x81, };
368b5c23aa4SPaul Cercueil static int jz4770_pwm_pwm2_pins[] = { 0x82, };
369b5c23aa4SPaul Cercueil static int jz4770_pwm_pwm3_pins[] = { 0x83, };
370b5c23aa4SPaul Cercueil static int jz4770_pwm_pwm4_pins[] = { 0x84, };
371b5c23aa4SPaul Cercueil static int jz4770_pwm_pwm5_pins[] = { 0x85, };
372b5c23aa4SPaul Cercueil static int jz4770_pwm_pwm6_pins[] = { 0x6a, };
373b5c23aa4SPaul Cercueil static int jz4770_pwm_pwm7_pins[] = { 0x6b, };
374b5c23aa4SPaul Cercueil 
375b5c23aa4SPaul Cercueil static int jz4770_uart0_data_funcs[] = { 0, 0, };
376b5c23aa4SPaul Cercueil static int jz4770_uart0_hwflow_funcs[] = { 0, 0, };
377b5c23aa4SPaul Cercueil static int jz4770_uart1_data_funcs[] = { 0, 0, };
378b5c23aa4SPaul Cercueil static int jz4770_uart1_hwflow_funcs[] = { 0, 0, };
379b5c23aa4SPaul Cercueil static int jz4770_uart2_data_funcs[] = { 1, 1, };
380b5c23aa4SPaul Cercueil static int jz4770_uart2_hwflow_funcs[] = { 1, 1, };
381b5c23aa4SPaul Cercueil static int jz4770_uart3_data_funcs[] = { 0, 1, };
382b5c23aa4SPaul Cercueil static int jz4770_uart3_hwflow_funcs[] = { 0, 0, };
383b5c23aa4SPaul Cercueil static int jz4770_uart4_data_funcs[] = { 2, 2, };
384b5c23aa4SPaul Cercueil static int jz4770_mmc0_8bit_a_funcs[] = { 1, 1, 1, 1, 1, };
385b5c23aa4SPaul Cercueil static int jz4770_mmc0_4bit_a_funcs[] = { 1, 1, 1, };
386b5c23aa4SPaul Cercueil static int jz4770_mmc0_1bit_a_funcs[] = { 1, 1, 0, };
387b5c23aa4SPaul Cercueil static int jz4770_mmc0_4bit_e_funcs[] = { 0, 0, 0, };
388b5c23aa4SPaul Cercueil static int jz4770_mmc0_1bit_e_funcs[] = { 0, 0, 0, };
389b5c23aa4SPaul Cercueil static int jz4770_mmc1_4bit_d_funcs[] = { 0, 0, 0, };
390b5c23aa4SPaul Cercueil static int jz4770_mmc1_1bit_d_funcs[] = { 0, 0, 0, };
391b5c23aa4SPaul Cercueil static int jz4770_mmc1_4bit_e_funcs[] = { 1, 1, 1, };
392b5c23aa4SPaul Cercueil static int jz4770_mmc1_1bit_e_funcs[] = { 1, 1, 1, };
393b5c23aa4SPaul Cercueil static int jz4770_nemc_data_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, };
394b5c23aa4SPaul Cercueil static int jz4770_nemc_cle_ale_funcs[] = { 0, 0, };
395b5c23aa4SPaul Cercueil static int jz4770_nemc_addr_funcs[] = { 0, 0, 0, 0, };
396b5c23aa4SPaul Cercueil static int jz4770_nemc_rd_we_funcs[] = { 0, 0, };
397b5c23aa4SPaul Cercueil static int jz4770_nemc_frd_fwe_funcs[] = { 0, 0, };
398b5c23aa4SPaul Cercueil static int jz4770_nemc_cs1_funcs[] = { 0, };
399b5c23aa4SPaul Cercueil static int jz4770_nemc_cs2_funcs[] = { 0, };
400b5c23aa4SPaul Cercueil static int jz4770_nemc_cs3_funcs[] = { 0, };
401b5c23aa4SPaul Cercueil static int jz4770_nemc_cs4_funcs[] = { 0, };
402b5c23aa4SPaul Cercueil static int jz4770_nemc_cs5_funcs[] = { 0, };
403b5c23aa4SPaul Cercueil static int jz4770_nemc_cs6_funcs[] = { 0, };
404b5c23aa4SPaul Cercueil static int jz4770_i2c0_funcs[] = { 0, 0, };
405b5c23aa4SPaul Cercueil static int jz4770_i2c1_funcs[] = { 0, 0, };
406b5c23aa4SPaul Cercueil static int jz4770_i2c2_funcs[] = { 2, 2, };
407b5c23aa4SPaul Cercueil static int jz4770_i2c3_funcs[] = { 1, 1, };
408b5c23aa4SPaul Cercueil static int jz4770_i2c4_e_funcs[] = { 1, 1, };
409b5c23aa4SPaul Cercueil static int jz4770_i2c4_f_funcs[] = { 1, 1, };
410b5c23aa4SPaul Cercueil static int jz4770_cim_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
411b5c23aa4SPaul Cercueil static int jz4770_lcd_32bit_funcs[] = {
412b5c23aa4SPaul Cercueil 	0, 0, 0, 0, 0, 0, 0, 0,
413b5c23aa4SPaul Cercueil 	0, 0, 0, 0, 0, 0, 0, 0,
414b5c23aa4SPaul Cercueil 	0, 0, 0,
415b5c23aa4SPaul Cercueil };
416b5c23aa4SPaul Cercueil static int jz4770_pwm_pwm0_funcs[] = { 0, };
417b5c23aa4SPaul Cercueil static int jz4770_pwm_pwm1_funcs[] = { 0, };
418b5c23aa4SPaul Cercueil static int jz4770_pwm_pwm2_funcs[] = { 0, };
419b5c23aa4SPaul Cercueil static int jz4770_pwm_pwm3_funcs[] = { 0, };
420b5c23aa4SPaul Cercueil static int jz4770_pwm_pwm4_funcs[] = { 0, };
421b5c23aa4SPaul Cercueil static int jz4770_pwm_pwm5_funcs[] = { 0, };
422b5c23aa4SPaul Cercueil static int jz4770_pwm_pwm6_funcs[] = { 0, };
423b5c23aa4SPaul Cercueil static int jz4770_pwm_pwm7_funcs[] = { 0, };
424b5c23aa4SPaul Cercueil 
425b5c23aa4SPaul Cercueil static const struct group_desc jz4770_groups[] = {
426b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("uart0-data", jz4770_uart0_data),
427b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("uart0-hwflow", jz4770_uart0_hwflow),
428b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("uart1-data", jz4770_uart1_data),
429b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("uart1-hwflow", jz4770_uart1_hwflow),
430b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("uart2-data", jz4770_uart2_data),
431b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("uart2-hwflow", jz4770_uart2_hwflow),
432b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("uart3-data", jz4770_uart3_data),
433b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("uart3-hwflow", jz4770_uart3_hwflow),
434b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("uart4-data", jz4770_uart4_data),
435b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("mmc0-8bit-a", jz4770_mmc0_8bit_a),
436b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("mmc0-4bit-a", jz4770_mmc0_4bit_a),
437b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("mmc0-1bit-a", jz4770_mmc0_1bit_a),
438b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("mmc0-4bit-e", jz4770_mmc0_4bit_e),
439b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("mmc0-1bit-e", jz4770_mmc0_1bit_e),
440b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("mmc1-4bit-d", jz4770_mmc1_4bit_d),
441b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("mmc1-1bit-d", jz4770_mmc1_1bit_d),
442b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("mmc1-4bit-e", jz4770_mmc1_4bit_e),
443b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("mmc1-1bit-e", jz4770_mmc1_1bit_e),
444b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("nemc-data", jz4770_nemc_data),
445b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("nemc-cle-ale", jz4770_nemc_cle_ale),
446b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("nemc-addr", jz4770_nemc_addr),
447b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("nemc-rd-we", jz4770_nemc_rd_we),
448b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("nemc-frd-fwe", jz4770_nemc_frd_fwe),
449b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("nemc-cs1", jz4770_nemc_cs1),
450b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("nemc-cs2", jz4770_nemc_cs2),
451b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("nemc-cs3", jz4770_nemc_cs3),
452b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("nemc-cs4", jz4770_nemc_cs4),
453b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("nemc-cs5", jz4770_nemc_cs5),
454b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("nemc-cs6", jz4770_nemc_cs6),
455b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("i2c0-data", jz4770_i2c0),
456b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("i2c1-data", jz4770_i2c1),
457b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("i2c2-data", jz4770_i2c2),
458b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("i2c3-data", jz4770_i2c3),
459b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("i2c4-data-e", jz4770_i2c4_e),
460b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("i2c4-data-f", jz4770_i2c4_f),
461b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("cim-data", jz4770_cim),
462b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("lcd-32bit", jz4770_lcd_32bit),
463b5c23aa4SPaul Cercueil 	{ "lcd-no-pins", },
464b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("pwm0", jz4770_pwm_pwm0),
465b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("pwm1", jz4770_pwm_pwm1),
466b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("pwm2", jz4770_pwm_pwm2),
467b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("pwm3", jz4770_pwm_pwm3),
468b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("pwm4", jz4770_pwm_pwm4),
469b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("pwm5", jz4770_pwm_pwm5),
470b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("pwm6", jz4770_pwm_pwm6),
471b5c23aa4SPaul Cercueil 	INGENIC_PIN_GROUP("pwm7", jz4770_pwm_pwm7),
472b5c23aa4SPaul Cercueil };
473b5c23aa4SPaul Cercueil 
474b5c23aa4SPaul Cercueil static const char *jz4770_uart0_groups[] = { "uart0-data", "uart0-hwflow", };
475b5c23aa4SPaul Cercueil static const char *jz4770_uart1_groups[] = { "uart1-data", "uart1-hwflow", };
476b5c23aa4SPaul Cercueil static const char *jz4770_uart2_groups[] = { "uart2-data", "uart2-hwflow", };
477b5c23aa4SPaul Cercueil static const char *jz4770_uart3_groups[] = { "uart3-data", "uart3-hwflow", };
478b5c23aa4SPaul Cercueil static const char *jz4770_uart4_groups[] = { "uart4-data", };
479b5c23aa4SPaul Cercueil static const char *jz4770_mmc0_groups[] = {
480b5c23aa4SPaul Cercueil 	"mmc0-8bit-a", "mmc0-4bit-a", "mmc0-1bit-a",
481b5c23aa4SPaul Cercueil 	"mmc0-1bit-e", "mmc0-4bit-e",
482b5c23aa4SPaul Cercueil };
483b5c23aa4SPaul Cercueil static const char *jz4770_mmc1_groups[] = {
484b5c23aa4SPaul Cercueil 	"mmc1-1bit-d", "mmc1-4bit-d", "mmc1-1bit-e", "mmc1-4bit-e",
485b5c23aa4SPaul Cercueil };
486b5c23aa4SPaul Cercueil static const char *jz4770_nemc_groups[] = {
487b5c23aa4SPaul Cercueil 	"nemc-data", "nemc-cle-ale", "nemc-addr", "nemc-rd-we", "nemc-frd-fwe",
488b5c23aa4SPaul Cercueil };
489b5c23aa4SPaul Cercueil static const char *jz4770_cs1_groups[] = { "nemc-cs1", };
490b5c23aa4SPaul Cercueil static const char *jz4770_cs6_groups[] = { "nemc-cs6", };
491b5c23aa4SPaul Cercueil static const char *jz4770_i2c0_groups[] = { "i2c0-data", };
492b5c23aa4SPaul Cercueil static const char *jz4770_i2c1_groups[] = { "i2c1-data", };
493b5c23aa4SPaul Cercueil static const char *jz4770_i2c2_groups[] = { "i2c2-data", };
494b5c23aa4SPaul Cercueil static const char *jz4770_i2c3_groups[] = { "i2c3-data", };
495b5c23aa4SPaul Cercueil static const char *jz4770_i2c4_groups[] = { "i2c4-data-e", "i2c4-data-f", };
496b5c23aa4SPaul Cercueil static const char *jz4770_cim_groups[] = { "cim-data", };
497b5c23aa4SPaul Cercueil static const char *jz4770_lcd_groups[] = { "lcd-32bit", "lcd-no-pins", };
498b5c23aa4SPaul Cercueil static const char *jz4770_pwm0_groups[] = { "pwm0", };
499b5c23aa4SPaul Cercueil static const char *jz4770_pwm1_groups[] = { "pwm1", };
500b5c23aa4SPaul Cercueil static const char *jz4770_pwm2_groups[] = { "pwm2", };
501b5c23aa4SPaul Cercueil static const char *jz4770_pwm3_groups[] = { "pwm3", };
502b5c23aa4SPaul Cercueil static const char *jz4770_pwm4_groups[] = { "pwm4", };
503b5c23aa4SPaul Cercueil static const char *jz4770_pwm5_groups[] = { "pwm5", };
504b5c23aa4SPaul Cercueil static const char *jz4770_pwm6_groups[] = { "pwm6", };
505b5c23aa4SPaul Cercueil static const char *jz4770_pwm7_groups[] = { "pwm7", };
506b5c23aa4SPaul Cercueil 
507b5c23aa4SPaul Cercueil static const struct function_desc jz4770_functions[] = {
508b5c23aa4SPaul Cercueil 	{ "uart0", jz4770_uart0_groups, ARRAY_SIZE(jz4770_uart0_groups), },
509b5c23aa4SPaul Cercueil 	{ "uart1", jz4770_uart1_groups, ARRAY_SIZE(jz4770_uart1_groups), },
510b5c23aa4SPaul Cercueil 	{ "uart2", jz4770_uart2_groups, ARRAY_SIZE(jz4770_uart2_groups), },
511b5c23aa4SPaul Cercueil 	{ "uart3", jz4770_uart3_groups, ARRAY_SIZE(jz4770_uart3_groups), },
512b5c23aa4SPaul Cercueil 	{ "uart4", jz4770_uart4_groups, ARRAY_SIZE(jz4770_uart4_groups), },
513b5c23aa4SPaul Cercueil 	{ "mmc0", jz4770_mmc0_groups, ARRAY_SIZE(jz4770_mmc0_groups), },
514b5c23aa4SPaul Cercueil 	{ "mmc1", jz4770_mmc1_groups, ARRAY_SIZE(jz4770_mmc1_groups), },
515b5c23aa4SPaul Cercueil 	{ "nemc", jz4770_nemc_groups, ARRAY_SIZE(jz4770_nemc_groups), },
516b5c23aa4SPaul Cercueil 	{ "nemc-cs1", jz4770_cs1_groups, ARRAY_SIZE(jz4770_cs1_groups), },
517b5c23aa4SPaul Cercueil 	{ "nemc-cs6", jz4770_cs6_groups, ARRAY_SIZE(jz4770_cs6_groups), },
518b5c23aa4SPaul Cercueil 	{ "i2c0", jz4770_i2c0_groups, ARRAY_SIZE(jz4770_i2c0_groups), },
519b5c23aa4SPaul Cercueil 	{ "i2c1", jz4770_i2c1_groups, ARRAY_SIZE(jz4770_i2c1_groups), },
520b5c23aa4SPaul Cercueil 	{ "i2c2", jz4770_i2c2_groups, ARRAY_SIZE(jz4770_i2c2_groups), },
521b5c23aa4SPaul Cercueil 	{ "i2c3", jz4770_i2c3_groups, ARRAY_SIZE(jz4770_i2c3_groups), },
522b5c23aa4SPaul Cercueil 	{ "i2c4", jz4770_i2c4_groups, ARRAY_SIZE(jz4770_i2c4_groups), },
523b5c23aa4SPaul Cercueil 	{ "cim", jz4770_cim_groups, ARRAY_SIZE(jz4770_cim_groups), },
524b5c23aa4SPaul Cercueil 	{ "lcd", jz4770_lcd_groups, ARRAY_SIZE(jz4770_lcd_groups), },
525b5c23aa4SPaul Cercueil 	{ "pwm0", jz4770_pwm0_groups, ARRAY_SIZE(jz4770_pwm0_groups), },
526b5c23aa4SPaul Cercueil 	{ "pwm1", jz4770_pwm1_groups, ARRAY_SIZE(jz4770_pwm1_groups), },
527b5c23aa4SPaul Cercueil 	{ "pwm2", jz4770_pwm2_groups, ARRAY_SIZE(jz4770_pwm2_groups), },
528b5c23aa4SPaul Cercueil 	{ "pwm3", jz4770_pwm3_groups, ARRAY_SIZE(jz4770_pwm3_groups), },
529b5c23aa4SPaul Cercueil 	{ "pwm4", jz4770_pwm4_groups, ARRAY_SIZE(jz4770_pwm4_groups), },
530b5c23aa4SPaul Cercueil 	{ "pwm5", jz4770_pwm5_groups, ARRAY_SIZE(jz4770_pwm5_groups), },
531b5c23aa4SPaul Cercueil 	{ "pwm6", jz4770_pwm6_groups, ARRAY_SIZE(jz4770_pwm6_groups), },
532b5c23aa4SPaul Cercueil 	{ "pwm7", jz4770_pwm7_groups, ARRAY_SIZE(jz4770_pwm7_groups), },
533b5c23aa4SPaul Cercueil };
534b5c23aa4SPaul Cercueil 
535b5c23aa4SPaul Cercueil static const struct ingenic_chip_info jz4770_chip_info = {
536b5c23aa4SPaul Cercueil 	.num_chips = 6,
537b5c23aa4SPaul Cercueil 	.groups = jz4770_groups,
538b5c23aa4SPaul Cercueil 	.num_groups = ARRAY_SIZE(jz4770_groups),
539b5c23aa4SPaul Cercueil 	.functions = jz4770_functions,
540b5c23aa4SPaul Cercueil 	.num_functions = ARRAY_SIZE(jz4770_functions),
541b5c23aa4SPaul Cercueil 	.pull_ups = jz4770_pull_ups,
542b5c23aa4SPaul Cercueil 	.pull_downs = jz4770_pull_downs,
543b5c23aa4SPaul Cercueil };
544b5c23aa4SPaul Cercueil 
545e72394e2SPaul Cercueil static u32 gpio_ingenic_read_reg(struct ingenic_gpio_chip *jzgc, u8 reg)
546e72394e2SPaul Cercueil {
547e72394e2SPaul Cercueil 	unsigned int val;
548e72394e2SPaul Cercueil 
549e72394e2SPaul Cercueil 	regmap_read(jzgc->jzpc->map, jzgc->reg_base + reg, &val);
550e72394e2SPaul Cercueil 
551e72394e2SPaul Cercueil 	return (u32) val;
552e72394e2SPaul Cercueil }
553e72394e2SPaul Cercueil 
554e72394e2SPaul Cercueil static void gpio_ingenic_set_bit(struct ingenic_gpio_chip *jzgc,
555e72394e2SPaul Cercueil 		u8 reg, u8 offset, bool set)
556e72394e2SPaul Cercueil {
557e72394e2SPaul Cercueil 	if (set)
558e72394e2SPaul Cercueil 		reg = REG_SET(reg);
559e72394e2SPaul Cercueil 	else
560e72394e2SPaul Cercueil 		reg = REG_CLEAR(reg);
561e72394e2SPaul Cercueil 
562e72394e2SPaul Cercueil 	regmap_write(jzgc->jzpc->map, jzgc->reg_base + reg, BIT(offset));
563e72394e2SPaul Cercueil }
564e72394e2SPaul Cercueil 
565e72394e2SPaul Cercueil static inline bool ingenic_gpio_get_value(struct ingenic_gpio_chip *jzgc,
566e72394e2SPaul Cercueil 					  u8 offset)
567e72394e2SPaul Cercueil {
568e72394e2SPaul Cercueil 	unsigned int val = gpio_ingenic_read_reg(jzgc, GPIO_PIN);
569e72394e2SPaul Cercueil 
570e72394e2SPaul Cercueil 	return !!(val & BIT(offset));
571e72394e2SPaul Cercueil }
572e72394e2SPaul Cercueil 
573e72394e2SPaul Cercueil static void ingenic_gpio_set_value(struct ingenic_gpio_chip *jzgc,
574e72394e2SPaul Cercueil 				   u8 offset, int value)
575e72394e2SPaul Cercueil {
576e72394e2SPaul Cercueil 	if (jzgc->jzpc->version >= ID_JZ4770)
577e72394e2SPaul Cercueil 		gpio_ingenic_set_bit(jzgc, JZ4770_GPIO_PAT0, offset, !!value);
578e72394e2SPaul Cercueil 	else
579e72394e2SPaul Cercueil 		gpio_ingenic_set_bit(jzgc, JZ4740_GPIO_DATA, offset, !!value);
580e72394e2SPaul Cercueil }
581e72394e2SPaul Cercueil 
582e72394e2SPaul Cercueil static void irq_set_type(struct ingenic_gpio_chip *jzgc,
583e72394e2SPaul Cercueil 		u8 offset, unsigned int type)
584e72394e2SPaul Cercueil {
585e72394e2SPaul Cercueil 	u8 reg1, reg2;
586e72394e2SPaul Cercueil 
587e72394e2SPaul Cercueil 	if (jzgc->jzpc->version >= ID_JZ4770) {
588e72394e2SPaul Cercueil 		reg1 = JZ4770_GPIO_PAT1;
589e72394e2SPaul Cercueil 		reg2 = JZ4770_GPIO_PAT0;
590e72394e2SPaul Cercueil 	} else {
591e72394e2SPaul Cercueil 		reg1 = JZ4740_GPIO_TRIG;
592e72394e2SPaul Cercueil 		reg2 = JZ4740_GPIO_DIR;
593e72394e2SPaul Cercueil 	}
594e72394e2SPaul Cercueil 
595e72394e2SPaul Cercueil 	switch (type) {
596e72394e2SPaul Cercueil 	case IRQ_TYPE_EDGE_RISING:
597e72394e2SPaul Cercueil 		gpio_ingenic_set_bit(jzgc, reg2, offset, true);
598e72394e2SPaul Cercueil 		gpio_ingenic_set_bit(jzgc, reg1, offset, true);
599e72394e2SPaul Cercueil 		break;
600e72394e2SPaul Cercueil 	case IRQ_TYPE_EDGE_FALLING:
601e72394e2SPaul Cercueil 		gpio_ingenic_set_bit(jzgc, reg2, offset, false);
602e72394e2SPaul Cercueil 		gpio_ingenic_set_bit(jzgc, reg1, offset, true);
603e72394e2SPaul Cercueil 		break;
604e72394e2SPaul Cercueil 	case IRQ_TYPE_LEVEL_HIGH:
605e72394e2SPaul Cercueil 		gpio_ingenic_set_bit(jzgc, reg2, offset, true);
606e72394e2SPaul Cercueil 		gpio_ingenic_set_bit(jzgc, reg1, offset, false);
607e72394e2SPaul Cercueil 		break;
608e72394e2SPaul Cercueil 	case IRQ_TYPE_LEVEL_LOW:
609e72394e2SPaul Cercueil 	default:
610e72394e2SPaul Cercueil 		gpio_ingenic_set_bit(jzgc, reg2, offset, false);
611e72394e2SPaul Cercueil 		gpio_ingenic_set_bit(jzgc, reg1, offset, false);
612e72394e2SPaul Cercueil 		break;
613e72394e2SPaul Cercueil 	}
614e72394e2SPaul Cercueil }
615e72394e2SPaul Cercueil 
616e72394e2SPaul Cercueil static void ingenic_gpio_irq_mask(struct irq_data *irqd)
617e72394e2SPaul Cercueil {
618e72394e2SPaul Cercueil 	struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
619e72394e2SPaul Cercueil 	struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
620e72394e2SPaul Cercueil 
621e72394e2SPaul Cercueil 	gpio_ingenic_set_bit(jzgc, GPIO_MSK, irqd->hwirq, true);
622e72394e2SPaul Cercueil }
623e72394e2SPaul Cercueil 
624e72394e2SPaul Cercueil static void ingenic_gpio_irq_unmask(struct irq_data *irqd)
625e72394e2SPaul Cercueil {
626e72394e2SPaul Cercueil 	struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
627e72394e2SPaul Cercueil 	struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
628e72394e2SPaul Cercueil 
629e72394e2SPaul Cercueil 	gpio_ingenic_set_bit(jzgc, GPIO_MSK, irqd->hwirq, false);
630e72394e2SPaul Cercueil }
631e72394e2SPaul Cercueil 
632e72394e2SPaul Cercueil static void ingenic_gpio_irq_enable(struct irq_data *irqd)
633e72394e2SPaul Cercueil {
634e72394e2SPaul Cercueil 	struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
635e72394e2SPaul Cercueil 	struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
636e72394e2SPaul Cercueil 	int irq = irqd->hwirq;
637e72394e2SPaul Cercueil 
638e72394e2SPaul Cercueil 	if (jzgc->jzpc->version >= ID_JZ4770)
639e72394e2SPaul Cercueil 		gpio_ingenic_set_bit(jzgc, JZ4770_GPIO_INT, irq, true);
640e72394e2SPaul Cercueil 	else
641e72394e2SPaul Cercueil 		gpio_ingenic_set_bit(jzgc, JZ4740_GPIO_SELECT, irq, true);
642e72394e2SPaul Cercueil 
643e72394e2SPaul Cercueil 	ingenic_gpio_irq_unmask(irqd);
644e72394e2SPaul Cercueil }
645e72394e2SPaul Cercueil 
646e72394e2SPaul Cercueil static void ingenic_gpio_irq_disable(struct irq_data *irqd)
647e72394e2SPaul Cercueil {
648e72394e2SPaul Cercueil 	struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
649e72394e2SPaul Cercueil 	struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
650e72394e2SPaul Cercueil 	int irq = irqd->hwirq;
651e72394e2SPaul Cercueil 
652e72394e2SPaul Cercueil 	ingenic_gpio_irq_mask(irqd);
653e72394e2SPaul Cercueil 
654e72394e2SPaul Cercueil 	if (jzgc->jzpc->version >= ID_JZ4770)
655e72394e2SPaul Cercueil 		gpio_ingenic_set_bit(jzgc, JZ4770_GPIO_INT, irq, false);
656e72394e2SPaul Cercueil 	else
657e72394e2SPaul Cercueil 		gpio_ingenic_set_bit(jzgc, JZ4740_GPIO_SELECT, irq, false);
658e72394e2SPaul Cercueil }
659e72394e2SPaul Cercueil 
660e72394e2SPaul Cercueil static void ingenic_gpio_irq_ack(struct irq_data *irqd)
661e72394e2SPaul Cercueil {
662e72394e2SPaul Cercueil 	struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
663e72394e2SPaul Cercueil 	struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
664e72394e2SPaul Cercueil 	int irq = irqd->hwirq;
665e72394e2SPaul Cercueil 	bool high;
666e72394e2SPaul Cercueil 
667e72394e2SPaul Cercueil 	if (irqd_get_trigger_type(irqd) == IRQ_TYPE_EDGE_BOTH) {
668e72394e2SPaul Cercueil 		/*
669e72394e2SPaul Cercueil 		 * Switch to an interrupt for the opposite edge to the one that
670e72394e2SPaul Cercueil 		 * triggered the interrupt being ACKed.
671e72394e2SPaul Cercueil 		 */
672e72394e2SPaul Cercueil 		high = ingenic_gpio_get_value(jzgc, irq);
673e72394e2SPaul Cercueil 		if (high)
674e72394e2SPaul Cercueil 			irq_set_type(jzgc, irq, IRQ_TYPE_EDGE_FALLING);
675e72394e2SPaul Cercueil 		else
676e72394e2SPaul Cercueil 			irq_set_type(jzgc, irq, IRQ_TYPE_EDGE_RISING);
677e72394e2SPaul Cercueil 	}
678e72394e2SPaul Cercueil 
679e72394e2SPaul Cercueil 	if (jzgc->jzpc->version >= ID_JZ4770)
680e72394e2SPaul Cercueil 		gpio_ingenic_set_bit(jzgc, JZ4770_GPIO_FLAG, irq, false);
681e72394e2SPaul Cercueil 	else
682e72394e2SPaul Cercueil 		gpio_ingenic_set_bit(jzgc, JZ4740_GPIO_DATA, irq, true);
683e72394e2SPaul Cercueil }
684e72394e2SPaul Cercueil 
685e72394e2SPaul Cercueil static int ingenic_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
686e72394e2SPaul Cercueil {
687e72394e2SPaul Cercueil 	struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
688e72394e2SPaul Cercueil 	struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
689e72394e2SPaul Cercueil 
690e72394e2SPaul Cercueil 	switch (type) {
691e72394e2SPaul Cercueil 	case IRQ_TYPE_EDGE_BOTH:
692e72394e2SPaul Cercueil 	case IRQ_TYPE_EDGE_RISING:
693e72394e2SPaul Cercueil 	case IRQ_TYPE_EDGE_FALLING:
694e72394e2SPaul Cercueil 		irq_set_handler_locked(irqd, handle_edge_irq);
695e72394e2SPaul Cercueil 		break;
696e72394e2SPaul Cercueil 	case IRQ_TYPE_LEVEL_HIGH:
697e72394e2SPaul Cercueil 	case IRQ_TYPE_LEVEL_LOW:
698e72394e2SPaul Cercueil 		irq_set_handler_locked(irqd, handle_level_irq);
699e72394e2SPaul Cercueil 		break;
700e72394e2SPaul Cercueil 	default:
701e72394e2SPaul Cercueil 		irq_set_handler_locked(irqd, handle_bad_irq);
702e72394e2SPaul Cercueil 	}
703e72394e2SPaul Cercueil 
704e72394e2SPaul Cercueil 	if (type == IRQ_TYPE_EDGE_BOTH) {
705e72394e2SPaul Cercueil 		/*
706e72394e2SPaul Cercueil 		 * The hardware does not support interrupts on both edges. The
707e72394e2SPaul Cercueil 		 * best we can do is to set up a single-edge interrupt and then
708e72394e2SPaul Cercueil 		 * switch to the opposing edge when ACKing the interrupt.
709e72394e2SPaul Cercueil 		 */
710e72394e2SPaul Cercueil 		bool high = ingenic_gpio_get_value(jzgc, irqd->hwirq);
711e72394e2SPaul Cercueil 
712e72394e2SPaul Cercueil 		type = high ? IRQ_TYPE_EDGE_FALLING : IRQ_TYPE_EDGE_RISING;
713e72394e2SPaul Cercueil 	}
714e72394e2SPaul Cercueil 
715e72394e2SPaul Cercueil 	irq_set_type(jzgc, irqd->hwirq, type);
716e72394e2SPaul Cercueil 	return 0;
717e72394e2SPaul Cercueil }
718e72394e2SPaul Cercueil 
719e72394e2SPaul Cercueil static int ingenic_gpio_irq_set_wake(struct irq_data *irqd, unsigned int on)
720e72394e2SPaul Cercueil {
721e72394e2SPaul Cercueil 	struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
722e72394e2SPaul Cercueil 	struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
723e72394e2SPaul Cercueil 
724e72394e2SPaul Cercueil 	return irq_set_irq_wake(jzgc->irq, on);
725e72394e2SPaul Cercueil }
726e72394e2SPaul Cercueil 
727e72394e2SPaul Cercueil static void ingenic_gpio_irq_handler(struct irq_desc *desc)
728e72394e2SPaul Cercueil {
729e72394e2SPaul Cercueil 	struct gpio_chip *gc = irq_desc_get_handler_data(desc);
730e72394e2SPaul Cercueil 	struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
731e72394e2SPaul Cercueil 	struct irq_chip *irq_chip = irq_data_get_irq_chip(&desc->irq_data);
732e72394e2SPaul Cercueil 	unsigned long flag, i;
733e72394e2SPaul Cercueil 
734e72394e2SPaul Cercueil 	chained_irq_enter(irq_chip, desc);
735e72394e2SPaul Cercueil 
736e72394e2SPaul Cercueil 	if (jzgc->jzpc->version >= ID_JZ4770)
737e72394e2SPaul Cercueil 		flag = gpio_ingenic_read_reg(jzgc, JZ4770_GPIO_FLAG);
738e72394e2SPaul Cercueil 	else
739e72394e2SPaul Cercueil 		flag = gpio_ingenic_read_reg(jzgc, JZ4740_GPIO_FLAG);
740e72394e2SPaul Cercueil 
741e72394e2SPaul Cercueil 	for_each_set_bit(i, &flag, 32)
742e72394e2SPaul Cercueil 		generic_handle_irq(irq_linear_revmap(gc->irq.domain, i));
743e72394e2SPaul Cercueil 	chained_irq_exit(irq_chip, desc);
744e72394e2SPaul Cercueil }
745e72394e2SPaul Cercueil 
746e72394e2SPaul Cercueil static void ingenic_gpio_set(struct gpio_chip *gc,
747e72394e2SPaul Cercueil 		unsigned int offset, int value)
748e72394e2SPaul Cercueil {
749e72394e2SPaul Cercueil 	struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
750e72394e2SPaul Cercueil 
751e72394e2SPaul Cercueil 	ingenic_gpio_set_value(jzgc, offset, value);
752e72394e2SPaul Cercueil }
753e72394e2SPaul Cercueil 
754e72394e2SPaul Cercueil static int ingenic_gpio_get(struct gpio_chip *gc, unsigned int offset)
755e72394e2SPaul Cercueil {
756e72394e2SPaul Cercueil 	struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
757e72394e2SPaul Cercueil 
758e72394e2SPaul Cercueil 	return (int) ingenic_gpio_get_value(jzgc, offset);
759e72394e2SPaul Cercueil }
760e72394e2SPaul Cercueil 
761e72394e2SPaul Cercueil static int ingenic_gpio_direction_input(struct gpio_chip *gc,
762e72394e2SPaul Cercueil 		unsigned int offset)
763e72394e2SPaul Cercueil {
764e72394e2SPaul Cercueil 	return pinctrl_gpio_direction_input(gc->base + offset);
765e72394e2SPaul Cercueil }
766e72394e2SPaul Cercueil 
767e72394e2SPaul Cercueil static int ingenic_gpio_direction_output(struct gpio_chip *gc,
768e72394e2SPaul Cercueil 		unsigned int offset, int value)
769e72394e2SPaul Cercueil {
770e72394e2SPaul Cercueil 	ingenic_gpio_set(gc, offset, value);
771e72394e2SPaul Cercueil 	return pinctrl_gpio_direction_output(gc->base + offset);
772e72394e2SPaul Cercueil }
773e72394e2SPaul Cercueil 
774b5c23aa4SPaul Cercueil static inline void ingenic_config_pin(struct ingenic_pinctrl *jzpc,
775b5c23aa4SPaul Cercueil 		unsigned int pin, u8 reg, bool set)
776b5c23aa4SPaul Cercueil {
777b5c23aa4SPaul Cercueil 	unsigned int idx = pin % PINS_PER_GPIO_CHIP;
778b5c23aa4SPaul Cercueil 	unsigned int offt = pin / PINS_PER_GPIO_CHIP;
779b5c23aa4SPaul Cercueil 
780b5c23aa4SPaul Cercueil 	regmap_write(jzpc->map, offt * 0x100 +
781b5c23aa4SPaul Cercueil 			(set ? REG_SET(reg) : REG_CLEAR(reg)), BIT(idx));
782b5c23aa4SPaul Cercueil }
783b5c23aa4SPaul Cercueil 
784b5c23aa4SPaul Cercueil static inline bool ingenic_get_pin_config(struct ingenic_pinctrl *jzpc,
785b5c23aa4SPaul Cercueil 		unsigned int pin, u8 reg)
786b5c23aa4SPaul Cercueil {
787b5c23aa4SPaul Cercueil 	unsigned int idx = pin % PINS_PER_GPIO_CHIP;
788b5c23aa4SPaul Cercueil 	unsigned int offt = pin / PINS_PER_GPIO_CHIP;
789b5c23aa4SPaul Cercueil 	unsigned int val;
790b5c23aa4SPaul Cercueil 
791b5c23aa4SPaul Cercueil 	regmap_read(jzpc->map, offt * 0x100 + reg, &val);
792b5c23aa4SPaul Cercueil 
793b5c23aa4SPaul Cercueil 	return val & BIT(idx);
794b5c23aa4SPaul Cercueil }
795b5c23aa4SPaul Cercueil 
796ebd66514SPaul Cercueil static int ingenic_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
797ebd66514SPaul Cercueil {
798ebd66514SPaul Cercueil 	struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
799ebd66514SPaul Cercueil 	struct ingenic_pinctrl *jzpc = jzgc->jzpc;
800ebd66514SPaul Cercueil 	unsigned int pin = gc->base + offset;
801ebd66514SPaul Cercueil 
802ebd66514SPaul Cercueil 	if (jzpc->version >= ID_JZ4770)
803ebd66514SPaul Cercueil 		return ingenic_get_pin_config(jzpc, pin, JZ4770_GPIO_PAT1);
804ebd66514SPaul Cercueil 
805ebd66514SPaul Cercueil 	if (ingenic_get_pin_config(jzpc, pin, JZ4740_GPIO_SELECT))
806ebd66514SPaul Cercueil 		return true;
807ebd66514SPaul Cercueil 
808ebd66514SPaul Cercueil 	return !ingenic_get_pin_config(jzpc, pin, JZ4740_GPIO_DIR);
809ebd66514SPaul Cercueil }
810ebd66514SPaul Cercueil 
8115bf7b849SJulia Lawall static const struct pinctrl_ops ingenic_pctlops = {
812b5c23aa4SPaul Cercueil 	.get_groups_count = pinctrl_generic_get_group_count,
813b5c23aa4SPaul Cercueil 	.get_group_name = pinctrl_generic_get_group_name,
814b5c23aa4SPaul Cercueil 	.get_group_pins = pinctrl_generic_get_group_pins,
815b5c23aa4SPaul Cercueil 	.dt_node_to_map = pinconf_generic_dt_node_to_map_all,
816b5c23aa4SPaul Cercueil 	.dt_free_map = pinconf_generic_dt_free_map,
817b5c23aa4SPaul Cercueil };
818b5c23aa4SPaul Cercueil 
819b5c23aa4SPaul Cercueil static int ingenic_pinmux_set_pin_fn(struct ingenic_pinctrl *jzpc,
820b5c23aa4SPaul Cercueil 		int pin, int func)
821b5c23aa4SPaul Cercueil {
822b5c23aa4SPaul Cercueil 	unsigned int idx = pin % PINS_PER_GPIO_CHIP;
823b5c23aa4SPaul Cercueil 	unsigned int offt = pin / PINS_PER_GPIO_CHIP;
824b5c23aa4SPaul Cercueil 
825b5c23aa4SPaul Cercueil 	dev_dbg(jzpc->dev, "set pin P%c%u to function %u\n",
826b5c23aa4SPaul Cercueil 			'A' + offt, idx, func);
827b5c23aa4SPaul Cercueil 
828b5c23aa4SPaul Cercueil 	if (jzpc->version >= ID_JZ4770) {
829b5c23aa4SPaul Cercueil 		ingenic_config_pin(jzpc, pin, JZ4770_GPIO_INT, false);
830e72394e2SPaul Cercueil 		ingenic_config_pin(jzpc, pin, GPIO_MSK, false);
831b5c23aa4SPaul Cercueil 		ingenic_config_pin(jzpc, pin, JZ4770_GPIO_PAT1, func & 0x2);
832b5c23aa4SPaul Cercueil 		ingenic_config_pin(jzpc, pin, JZ4770_GPIO_PAT0, func & 0x1);
833b5c23aa4SPaul Cercueil 	} else {
834b5c23aa4SPaul Cercueil 		ingenic_config_pin(jzpc, pin, JZ4740_GPIO_FUNC, true);
835b5c23aa4SPaul Cercueil 		ingenic_config_pin(jzpc, pin, JZ4740_GPIO_TRIG, func & 0x2);
836b5c23aa4SPaul Cercueil 		ingenic_config_pin(jzpc, pin, JZ4740_GPIO_SELECT, func > 0);
837b5c23aa4SPaul Cercueil 	}
838b5c23aa4SPaul Cercueil 
839b5c23aa4SPaul Cercueil 	return 0;
840b5c23aa4SPaul Cercueil }
841b5c23aa4SPaul Cercueil 
842b5c23aa4SPaul Cercueil static int ingenic_pinmux_set_mux(struct pinctrl_dev *pctldev,
843b5c23aa4SPaul Cercueil 		unsigned int selector, unsigned int group)
844b5c23aa4SPaul Cercueil {
845b5c23aa4SPaul Cercueil 	struct ingenic_pinctrl *jzpc = pinctrl_dev_get_drvdata(pctldev);
846b5c23aa4SPaul Cercueil 	struct function_desc *func;
847b5c23aa4SPaul Cercueil 	struct group_desc *grp;
848b5c23aa4SPaul Cercueil 	unsigned int i;
849b5c23aa4SPaul Cercueil 
850b5c23aa4SPaul Cercueil 	func = pinmux_generic_get_function(pctldev, selector);
851b5c23aa4SPaul Cercueil 	if (!func)
852b5c23aa4SPaul Cercueil 		return -EINVAL;
853b5c23aa4SPaul Cercueil 
854b5c23aa4SPaul Cercueil 	grp = pinctrl_generic_get_group(pctldev, group);
855b5c23aa4SPaul Cercueil 	if (!grp)
856b5c23aa4SPaul Cercueil 		return -EINVAL;
857b5c23aa4SPaul Cercueil 
858b5c23aa4SPaul Cercueil 	dev_dbg(pctldev->dev, "enable function %s group %s\n",
859b5c23aa4SPaul Cercueil 		func->name, grp->name);
860b5c23aa4SPaul Cercueil 
861b5c23aa4SPaul Cercueil 	for (i = 0; i < grp->num_pins; i++) {
862b5c23aa4SPaul Cercueil 		int *pin_modes = grp->data;
863b5c23aa4SPaul Cercueil 
864b5c23aa4SPaul Cercueil 		ingenic_pinmux_set_pin_fn(jzpc, grp->pins[i], pin_modes[i]);
865b5c23aa4SPaul Cercueil 	}
866b5c23aa4SPaul Cercueil 
867b5c23aa4SPaul Cercueil 	return 0;
868b5c23aa4SPaul Cercueil }
869b5c23aa4SPaul Cercueil 
870b5c23aa4SPaul Cercueil static int ingenic_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
871b5c23aa4SPaul Cercueil 		struct pinctrl_gpio_range *range,
872b5c23aa4SPaul Cercueil 		unsigned int pin, bool input)
873b5c23aa4SPaul Cercueil {
874b5c23aa4SPaul Cercueil 	struct ingenic_pinctrl *jzpc = pinctrl_dev_get_drvdata(pctldev);
875b5c23aa4SPaul Cercueil 	unsigned int idx = pin % PINS_PER_GPIO_CHIP;
876b5c23aa4SPaul Cercueil 	unsigned int offt = pin / PINS_PER_GPIO_CHIP;
877b5c23aa4SPaul Cercueil 
878b5c23aa4SPaul Cercueil 	dev_dbg(pctldev->dev, "set pin P%c%u to %sput\n",
879b5c23aa4SPaul Cercueil 			'A' + offt, idx, input ? "in" : "out");
880b5c23aa4SPaul Cercueil 
881b5c23aa4SPaul Cercueil 	if (jzpc->version >= ID_JZ4770) {
882b5c23aa4SPaul Cercueil 		ingenic_config_pin(jzpc, pin, JZ4770_GPIO_INT, false);
883e72394e2SPaul Cercueil 		ingenic_config_pin(jzpc, pin, GPIO_MSK, true);
884b5c23aa4SPaul Cercueil 		ingenic_config_pin(jzpc, pin, JZ4770_GPIO_PAT1, input);
885b5c23aa4SPaul Cercueil 	} else {
886b5c23aa4SPaul Cercueil 		ingenic_config_pin(jzpc, pin, JZ4740_GPIO_SELECT, false);
8870084a786SPaul Cercueil 		ingenic_config_pin(jzpc, pin, JZ4740_GPIO_DIR, !input);
888b5c23aa4SPaul Cercueil 		ingenic_config_pin(jzpc, pin, JZ4740_GPIO_FUNC, false);
889b5c23aa4SPaul Cercueil 	}
890b5c23aa4SPaul Cercueil 
891b5c23aa4SPaul Cercueil 	return 0;
892b5c23aa4SPaul Cercueil }
893b5c23aa4SPaul Cercueil 
8945bf7b849SJulia Lawall static const struct pinmux_ops ingenic_pmxops = {
895b5c23aa4SPaul Cercueil 	.get_functions_count = pinmux_generic_get_function_count,
896b5c23aa4SPaul Cercueil 	.get_function_name = pinmux_generic_get_function_name,
897b5c23aa4SPaul Cercueil 	.get_function_groups = pinmux_generic_get_function_groups,
898b5c23aa4SPaul Cercueil 	.set_mux = ingenic_pinmux_set_mux,
899b5c23aa4SPaul Cercueil 	.gpio_set_direction = ingenic_pinmux_gpio_set_direction,
900b5c23aa4SPaul Cercueil };
901b5c23aa4SPaul Cercueil 
902b5c23aa4SPaul Cercueil static int ingenic_pinconf_get(struct pinctrl_dev *pctldev,
903b5c23aa4SPaul Cercueil 		unsigned int pin, unsigned long *config)
904b5c23aa4SPaul Cercueil {
905b5c23aa4SPaul Cercueil 	struct ingenic_pinctrl *jzpc = pinctrl_dev_get_drvdata(pctldev);
906b5c23aa4SPaul Cercueil 	enum pin_config_param param = pinconf_to_config_param(*config);
907b5c23aa4SPaul Cercueil 	unsigned int idx = pin % PINS_PER_GPIO_CHIP;
908b5c23aa4SPaul Cercueil 	unsigned int offt = pin / PINS_PER_GPIO_CHIP;
909b5c23aa4SPaul Cercueil 	bool pull;
910b5c23aa4SPaul Cercueil 
911b5c23aa4SPaul Cercueil 	if (jzpc->version >= ID_JZ4770)
912b5c23aa4SPaul Cercueil 		pull = !ingenic_get_pin_config(jzpc, pin, JZ4770_GPIO_PEN);
913b5c23aa4SPaul Cercueil 	else
914b5c23aa4SPaul Cercueil 		pull = !ingenic_get_pin_config(jzpc, pin, JZ4740_GPIO_PULL_DIS);
915b5c23aa4SPaul Cercueil 
916b5c23aa4SPaul Cercueil 	switch (param) {
917b5c23aa4SPaul Cercueil 	case PIN_CONFIG_BIAS_DISABLE:
918b5c23aa4SPaul Cercueil 		if (pull)
919b5c23aa4SPaul Cercueil 			return -EINVAL;
920b5c23aa4SPaul Cercueil 		break;
921b5c23aa4SPaul Cercueil 
922b5c23aa4SPaul Cercueil 	case PIN_CONFIG_BIAS_PULL_UP:
923b5c23aa4SPaul Cercueil 		if (!pull || !(jzpc->info->pull_ups[offt] & BIT(idx)))
924b5c23aa4SPaul Cercueil 			return -EINVAL;
925b5c23aa4SPaul Cercueil 		break;
926b5c23aa4SPaul Cercueil 
927b5c23aa4SPaul Cercueil 	case PIN_CONFIG_BIAS_PULL_DOWN:
928b5c23aa4SPaul Cercueil 		if (!pull || !(jzpc->info->pull_downs[offt] & BIT(idx)))
929b5c23aa4SPaul Cercueil 			return -EINVAL;
930b5c23aa4SPaul Cercueil 		break;
931b5c23aa4SPaul Cercueil 
932b5c23aa4SPaul Cercueil 	default:
933b5c23aa4SPaul Cercueil 		return -ENOTSUPP;
934b5c23aa4SPaul Cercueil 	}
935b5c23aa4SPaul Cercueil 
936b5c23aa4SPaul Cercueil 	*config = pinconf_to_config_packed(param, 1);
937b5c23aa4SPaul Cercueil 	return 0;
938b5c23aa4SPaul Cercueil }
939b5c23aa4SPaul Cercueil 
940b5c23aa4SPaul Cercueil static void ingenic_set_bias(struct ingenic_pinctrl *jzpc,
941b5c23aa4SPaul Cercueil 		unsigned int pin, bool enabled)
942b5c23aa4SPaul Cercueil {
943b5c23aa4SPaul Cercueil 	if (jzpc->version >= ID_JZ4770)
944b5c23aa4SPaul Cercueil 		ingenic_config_pin(jzpc, pin, JZ4770_GPIO_PEN, !enabled);
945b5c23aa4SPaul Cercueil 	else
946b5c23aa4SPaul Cercueil 		ingenic_config_pin(jzpc, pin, JZ4740_GPIO_PULL_DIS, !enabled);
947b5c23aa4SPaul Cercueil }
948b5c23aa4SPaul Cercueil 
949b5c23aa4SPaul Cercueil static int ingenic_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
950b5c23aa4SPaul Cercueil 		unsigned long *configs, unsigned int num_configs)
951b5c23aa4SPaul Cercueil {
952b5c23aa4SPaul Cercueil 	struct ingenic_pinctrl *jzpc = pinctrl_dev_get_drvdata(pctldev);
953b5c23aa4SPaul Cercueil 	unsigned int idx = pin % PINS_PER_GPIO_CHIP;
954b5c23aa4SPaul Cercueil 	unsigned int offt = pin / PINS_PER_GPIO_CHIP;
955b5c23aa4SPaul Cercueil 	unsigned int cfg;
956b5c23aa4SPaul Cercueil 
957b5c23aa4SPaul Cercueil 	for (cfg = 0; cfg < num_configs; cfg++) {
958b5c23aa4SPaul Cercueil 		switch (pinconf_to_config_param(configs[cfg])) {
959b5c23aa4SPaul Cercueil 		case PIN_CONFIG_BIAS_DISABLE:
960b5c23aa4SPaul Cercueil 		case PIN_CONFIG_BIAS_PULL_UP:
961b5c23aa4SPaul Cercueil 		case PIN_CONFIG_BIAS_PULL_DOWN:
962b5c23aa4SPaul Cercueil 			continue;
963b5c23aa4SPaul Cercueil 		default:
964b5c23aa4SPaul Cercueil 			return -ENOTSUPP;
965b5c23aa4SPaul Cercueil 		}
966b5c23aa4SPaul Cercueil 	}
967b5c23aa4SPaul Cercueil 
968b5c23aa4SPaul Cercueil 	for (cfg = 0; cfg < num_configs; cfg++) {
969b5c23aa4SPaul Cercueil 		switch (pinconf_to_config_param(configs[cfg])) {
970b5c23aa4SPaul Cercueil 		case PIN_CONFIG_BIAS_DISABLE:
971b5c23aa4SPaul Cercueil 			dev_dbg(jzpc->dev, "disable pull-over for pin P%c%u\n",
972b5c23aa4SPaul Cercueil 					'A' + offt, idx);
973b5c23aa4SPaul Cercueil 			ingenic_set_bias(jzpc, pin, false);
974b5c23aa4SPaul Cercueil 			break;
975b5c23aa4SPaul Cercueil 
976b5c23aa4SPaul Cercueil 		case PIN_CONFIG_BIAS_PULL_UP:
977b5c23aa4SPaul Cercueil 			if (!(jzpc->info->pull_ups[offt] & BIT(idx)))
978b5c23aa4SPaul Cercueil 				return -EINVAL;
979b5c23aa4SPaul Cercueil 			dev_dbg(jzpc->dev, "set pull-up for pin P%c%u\n",
980b5c23aa4SPaul Cercueil 					'A' + offt, idx);
981b5c23aa4SPaul Cercueil 			ingenic_set_bias(jzpc, pin, true);
982b5c23aa4SPaul Cercueil 			break;
983b5c23aa4SPaul Cercueil 
984b5c23aa4SPaul Cercueil 		case PIN_CONFIG_BIAS_PULL_DOWN:
985b5c23aa4SPaul Cercueil 			if (!(jzpc->info->pull_downs[offt] & BIT(idx)))
986b5c23aa4SPaul Cercueil 				return -EINVAL;
987b5c23aa4SPaul Cercueil 			dev_dbg(jzpc->dev, "set pull-down for pin P%c%u\n",
988b5c23aa4SPaul Cercueil 					'A' + offt, idx);
989b5c23aa4SPaul Cercueil 			ingenic_set_bias(jzpc, pin, true);
990b5c23aa4SPaul Cercueil 			break;
991b5c23aa4SPaul Cercueil 
992b5c23aa4SPaul Cercueil 		default:
993b5c23aa4SPaul Cercueil 			unreachable();
994b5c23aa4SPaul Cercueil 		}
995b5c23aa4SPaul Cercueil 	}
996b5c23aa4SPaul Cercueil 
997b5c23aa4SPaul Cercueil 	return 0;
998b5c23aa4SPaul Cercueil }
999b5c23aa4SPaul Cercueil 
1000b5c23aa4SPaul Cercueil static int ingenic_pinconf_group_get(struct pinctrl_dev *pctldev,
1001b5c23aa4SPaul Cercueil 		unsigned int group, unsigned long *config)
1002b5c23aa4SPaul Cercueil {
1003b5c23aa4SPaul Cercueil 	const unsigned int *pins;
1004b5c23aa4SPaul Cercueil 	unsigned int i, npins, old = 0;
1005b5c23aa4SPaul Cercueil 	int ret;
1006b5c23aa4SPaul Cercueil 
1007b5c23aa4SPaul Cercueil 	ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins);
1008b5c23aa4SPaul Cercueil 	if (ret)
1009b5c23aa4SPaul Cercueil 		return ret;
1010b5c23aa4SPaul Cercueil 
1011b5c23aa4SPaul Cercueil 	for (i = 0; i < npins; i++) {
1012b5c23aa4SPaul Cercueil 		if (ingenic_pinconf_get(pctldev, pins[i], config))
1013b5c23aa4SPaul Cercueil 			return -ENOTSUPP;
1014b5c23aa4SPaul Cercueil 
1015b5c23aa4SPaul Cercueil 		/* configs do not match between two pins */
1016b5c23aa4SPaul Cercueil 		if (i && (old != *config))
1017b5c23aa4SPaul Cercueil 			return -ENOTSUPP;
1018b5c23aa4SPaul Cercueil 
1019b5c23aa4SPaul Cercueil 		old = *config;
1020b5c23aa4SPaul Cercueil 	}
1021b5c23aa4SPaul Cercueil 
1022b5c23aa4SPaul Cercueil 	return 0;
1023b5c23aa4SPaul Cercueil }
1024b5c23aa4SPaul Cercueil 
1025b5c23aa4SPaul Cercueil static int ingenic_pinconf_group_set(struct pinctrl_dev *pctldev,
1026b5c23aa4SPaul Cercueil 		unsigned int group, unsigned long *configs,
1027b5c23aa4SPaul Cercueil 		unsigned int num_configs)
1028b5c23aa4SPaul Cercueil {
1029b5c23aa4SPaul Cercueil 	const unsigned int *pins;
1030b5c23aa4SPaul Cercueil 	unsigned int i, npins;
1031b5c23aa4SPaul Cercueil 	int ret;
1032b5c23aa4SPaul Cercueil 
1033b5c23aa4SPaul Cercueil 	ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins);
1034b5c23aa4SPaul Cercueil 	if (ret)
1035b5c23aa4SPaul Cercueil 		return ret;
1036b5c23aa4SPaul Cercueil 
1037b5c23aa4SPaul Cercueil 	for (i = 0; i < npins; i++) {
1038b5c23aa4SPaul Cercueil 		ret = ingenic_pinconf_set(pctldev,
1039b5c23aa4SPaul Cercueil 				pins[i], configs, num_configs);
1040b5c23aa4SPaul Cercueil 		if (ret)
1041b5c23aa4SPaul Cercueil 			return ret;
1042b5c23aa4SPaul Cercueil 	}
1043b5c23aa4SPaul Cercueil 
1044b5c23aa4SPaul Cercueil 	return 0;
1045b5c23aa4SPaul Cercueil }
1046b5c23aa4SPaul Cercueil 
10475bf7b849SJulia Lawall static const struct pinconf_ops ingenic_confops = {
1048b5c23aa4SPaul Cercueil 	.is_generic = true,
1049b5c23aa4SPaul Cercueil 	.pin_config_get = ingenic_pinconf_get,
1050b5c23aa4SPaul Cercueil 	.pin_config_set = ingenic_pinconf_set,
1051b5c23aa4SPaul Cercueil 	.pin_config_group_get = ingenic_pinconf_group_get,
1052b5c23aa4SPaul Cercueil 	.pin_config_group_set = ingenic_pinconf_group_set,
1053b5c23aa4SPaul Cercueil };
1054b5c23aa4SPaul Cercueil 
1055b5c23aa4SPaul Cercueil static const struct regmap_config ingenic_pinctrl_regmap_config = {
1056b5c23aa4SPaul Cercueil 	.reg_bits = 32,
1057b5c23aa4SPaul Cercueil 	.val_bits = 32,
1058b5c23aa4SPaul Cercueil 	.reg_stride = 4,
1059b5c23aa4SPaul Cercueil };
1060b5c23aa4SPaul Cercueil 
1061b5c23aa4SPaul Cercueil static const struct of_device_id ingenic_pinctrl_of_match[] = {
1062b5c23aa4SPaul Cercueil 	{ .compatible = "ingenic,jz4740-pinctrl", .data = (void *) ID_JZ4740 },
1063*f2a96765SPaul Cercueil 	{ .compatible = "ingenic,jz4725b-pinctrl", .data = (void *)ID_JZ4725B },
1064b5c23aa4SPaul Cercueil 	{ .compatible = "ingenic,jz4770-pinctrl", .data = (void *) ID_JZ4770 },
1065b5c23aa4SPaul Cercueil 	{ .compatible = "ingenic,jz4780-pinctrl", .data = (void *) ID_JZ4780 },
1066b5c23aa4SPaul Cercueil 	{},
1067b5c23aa4SPaul Cercueil };
1068b5c23aa4SPaul Cercueil 
1069e72394e2SPaul Cercueil static const struct of_device_id ingenic_gpio_of_match[] __initconst = {
1070e72394e2SPaul Cercueil 	{ .compatible = "ingenic,jz4740-gpio", },
1071e72394e2SPaul Cercueil 	{ .compatible = "ingenic,jz4770-gpio", },
1072e72394e2SPaul Cercueil 	{ .compatible = "ingenic,jz4780-gpio", },
1073e72394e2SPaul Cercueil 	{},
1074e72394e2SPaul Cercueil };
1075e72394e2SPaul Cercueil 
1076e72394e2SPaul Cercueil static int __init ingenic_gpio_probe(struct ingenic_pinctrl *jzpc,
1077e72394e2SPaul Cercueil 				     struct device_node *node)
1078e72394e2SPaul Cercueil {
1079e72394e2SPaul Cercueil 	struct ingenic_gpio_chip *jzgc;
1080e72394e2SPaul Cercueil 	struct device *dev = jzpc->dev;
1081e72394e2SPaul Cercueil 	unsigned int bank;
1082e72394e2SPaul Cercueil 	int err;
1083e72394e2SPaul Cercueil 
1084e72394e2SPaul Cercueil 	err = of_property_read_u32(node, "reg", &bank);
1085e72394e2SPaul Cercueil 	if (err) {
1086e72394e2SPaul Cercueil 		dev_err(dev, "Cannot read \"reg\" property: %i\n", err);
1087e72394e2SPaul Cercueil 		return err;
1088e72394e2SPaul Cercueil 	}
1089e72394e2SPaul Cercueil 
1090e72394e2SPaul Cercueil 	jzgc = devm_kzalloc(dev, sizeof(*jzgc), GFP_KERNEL);
1091e72394e2SPaul Cercueil 	if (!jzgc)
1092e72394e2SPaul Cercueil 		return -ENOMEM;
1093e72394e2SPaul Cercueil 
1094e72394e2SPaul Cercueil 	jzgc->jzpc = jzpc;
1095e72394e2SPaul Cercueil 	jzgc->reg_base = bank * 0x100;
1096e72394e2SPaul Cercueil 
1097e72394e2SPaul Cercueil 	jzgc->gc.label = devm_kasprintf(dev, GFP_KERNEL, "GPIO%c", 'A' + bank);
1098e72394e2SPaul Cercueil 	if (!jzgc->gc.label)
1099e72394e2SPaul Cercueil 		return -ENOMEM;
1100e72394e2SPaul Cercueil 
1101e72394e2SPaul Cercueil 	/* DO NOT EXPAND THIS: FOR BACKWARD GPIO NUMBERSPACE COMPATIBIBILITY
1102e72394e2SPaul Cercueil 	 * ONLY: WORK TO TRANSITION CONSUMERS TO USE THE GPIO DESCRIPTOR API IN
1103e72394e2SPaul Cercueil 	 * <linux/gpio/consumer.h> INSTEAD.
1104e72394e2SPaul Cercueil 	 */
1105e72394e2SPaul Cercueil 	jzgc->gc.base = bank * 32;
1106e72394e2SPaul Cercueil 
1107e72394e2SPaul Cercueil 	jzgc->gc.ngpio = 32;
1108e72394e2SPaul Cercueil 	jzgc->gc.parent = dev;
1109e72394e2SPaul Cercueil 	jzgc->gc.of_node = node;
1110e72394e2SPaul Cercueil 	jzgc->gc.owner = THIS_MODULE;
1111e72394e2SPaul Cercueil 
1112e72394e2SPaul Cercueil 	jzgc->gc.set = ingenic_gpio_set;
1113e72394e2SPaul Cercueil 	jzgc->gc.get = ingenic_gpio_get;
1114e72394e2SPaul Cercueil 	jzgc->gc.direction_input = ingenic_gpio_direction_input;
1115e72394e2SPaul Cercueil 	jzgc->gc.direction_output = ingenic_gpio_direction_output;
1116ebd66514SPaul Cercueil 	jzgc->gc.get_direction = ingenic_gpio_get_direction;
1117e72394e2SPaul Cercueil 
1118e72394e2SPaul Cercueil 	if (of_property_read_bool(node, "gpio-ranges")) {
1119e72394e2SPaul Cercueil 		jzgc->gc.request = gpiochip_generic_request;
1120e72394e2SPaul Cercueil 		jzgc->gc.free = gpiochip_generic_free;
1121e72394e2SPaul Cercueil 	}
1122e72394e2SPaul Cercueil 
1123e72394e2SPaul Cercueil 	err = devm_gpiochip_add_data(dev, &jzgc->gc, jzgc);
1124e72394e2SPaul Cercueil 	if (err)
1125e72394e2SPaul Cercueil 		return err;
1126e72394e2SPaul Cercueil 
1127e72394e2SPaul Cercueil 	jzgc->irq = irq_of_parse_and_map(node, 0);
1128e72394e2SPaul Cercueil 	if (!jzgc->irq)
1129e72394e2SPaul Cercueil 		return -EINVAL;
1130e72394e2SPaul Cercueil 
1131e72394e2SPaul Cercueil 	jzgc->irq_chip.name = jzgc->gc.label;
1132e72394e2SPaul Cercueil 	jzgc->irq_chip.irq_enable = ingenic_gpio_irq_enable;
1133e72394e2SPaul Cercueil 	jzgc->irq_chip.irq_disable = ingenic_gpio_irq_disable;
1134e72394e2SPaul Cercueil 	jzgc->irq_chip.irq_unmask = ingenic_gpio_irq_unmask;
1135e72394e2SPaul Cercueil 	jzgc->irq_chip.irq_mask = ingenic_gpio_irq_mask;
1136e72394e2SPaul Cercueil 	jzgc->irq_chip.irq_ack = ingenic_gpio_irq_ack;
1137e72394e2SPaul Cercueil 	jzgc->irq_chip.irq_set_type = ingenic_gpio_irq_set_type;
1138e72394e2SPaul Cercueil 	jzgc->irq_chip.irq_set_wake = ingenic_gpio_irq_set_wake;
1139e72394e2SPaul Cercueil 	jzgc->irq_chip.flags = IRQCHIP_MASK_ON_SUSPEND;
1140e72394e2SPaul Cercueil 
1141e72394e2SPaul Cercueil 	err = gpiochip_irqchip_add(&jzgc->gc, &jzgc->irq_chip, 0,
1142e72394e2SPaul Cercueil 			handle_level_irq, IRQ_TYPE_NONE);
1143e72394e2SPaul Cercueil 	if (err)
1144e72394e2SPaul Cercueil 		return err;
1145e72394e2SPaul Cercueil 
1146e72394e2SPaul Cercueil 	gpiochip_set_chained_irqchip(&jzgc->gc, &jzgc->irq_chip,
1147e72394e2SPaul Cercueil 			jzgc->irq, ingenic_gpio_irq_handler);
1148e72394e2SPaul Cercueil 	return 0;
1149e72394e2SPaul Cercueil }
1150e72394e2SPaul Cercueil 
11514717b11fSPaul Cercueil static int __init ingenic_pinctrl_probe(struct platform_device *pdev)
1152b5c23aa4SPaul Cercueil {
1153b5c23aa4SPaul Cercueil 	struct device *dev = &pdev->dev;
1154b5c23aa4SPaul Cercueil 	struct ingenic_pinctrl *jzpc;
1155b5c23aa4SPaul Cercueil 	struct pinctrl_desc *pctl_desc;
1156b5c23aa4SPaul Cercueil 	void __iomem *base;
1157b5c23aa4SPaul Cercueil 	const struct platform_device_id *id = platform_get_device_id(pdev);
1158b5c23aa4SPaul Cercueil 	const struct of_device_id *of_id = of_match_device(
1159b5c23aa4SPaul Cercueil 			ingenic_pinctrl_of_match, dev);
1160b5c23aa4SPaul Cercueil 	const struct ingenic_chip_info *chip_info;
1161e72394e2SPaul Cercueil 	struct device_node *node;
1162b5c23aa4SPaul Cercueil 	unsigned int i;
1163b5c23aa4SPaul Cercueil 	int err;
1164b5c23aa4SPaul Cercueil 
1165b5c23aa4SPaul Cercueil 	jzpc = devm_kzalloc(dev, sizeof(*jzpc), GFP_KERNEL);
1166b5c23aa4SPaul Cercueil 	if (!jzpc)
1167b5c23aa4SPaul Cercueil 		return -ENOMEM;
1168b5c23aa4SPaul Cercueil 
1169b5c23aa4SPaul Cercueil 	base = devm_ioremap_resource(dev,
1170b5c23aa4SPaul Cercueil 			platform_get_resource(pdev, IORESOURCE_MEM, 0));
1171119fcf47SWei Yongjun 	if (IS_ERR(base))
1172b5c23aa4SPaul Cercueil 		return PTR_ERR(base);
1173b5c23aa4SPaul Cercueil 
1174b5c23aa4SPaul Cercueil 	jzpc->map = devm_regmap_init_mmio(dev, base,
1175b5c23aa4SPaul Cercueil 			&ingenic_pinctrl_regmap_config);
1176b5c23aa4SPaul Cercueil 	if (IS_ERR(jzpc->map)) {
1177b5c23aa4SPaul Cercueil 		dev_err(dev, "Failed to create regmap\n");
1178b5c23aa4SPaul Cercueil 		return PTR_ERR(jzpc->map);
1179b5c23aa4SPaul Cercueil 	}
1180b5c23aa4SPaul Cercueil 
1181b5c23aa4SPaul Cercueil 	jzpc->dev = dev;
1182b5c23aa4SPaul Cercueil 
1183b5c23aa4SPaul Cercueil 	if (of_id)
1184b5c23aa4SPaul Cercueil 		jzpc->version = (enum jz_version)of_id->data;
1185b5c23aa4SPaul Cercueil 	else
1186b5c23aa4SPaul Cercueil 		jzpc->version = (enum jz_version)id->driver_data;
1187b5c23aa4SPaul Cercueil 
1188b5c23aa4SPaul Cercueil 	if (jzpc->version >= ID_JZ4770)
1189b5c23aa4SPaul Cercueil 		chip_info = &jz4770_chip_info;
1190*f2a96765SPaul Cercueil 	else if (jzpc->version >= ID_JZ4725B)
1191*f2a96765SPaul Cercueil 		chip_info = &jz4725b_chip_info;
1192b5c23aa4SPaul Cercueil 	else
1193b5c23aa4SPaul Cercueil 		chip_info = &jz4740_chip_info;
1194b5c23aa4SPaul Cercueil 	jzpc->info = chip_info;
1195b5c23aa4SPaul Cercueil 
1196b5c23aa4SPaul Cercueil 	pctl_desc = devm_kzalloc(&pdev->dev, sizeof(*pctl_desc), GFP_KERNEL);
1197b5c23aa4SPaul Cercueil 	if (!pctl_desc)
1198b5c23aa4SPaul Cercueil 		return -ENOMEM;
1199b5c23aa4SPaul Cercueil 
1200b5c23aa4SPaul Cercueil 	/* fill in pinctrl_desc structure */
1201b5c23aa4SPaul Cercueil 	pctl_desc->name = dev_name(dev);
1202b5c23aa4SPaul Cercueil 	pctl_desc->owner = THIS_MODULE;
1203b5c23aa4SPaul Cercueil 	pctl_desc->pctlops = &ingenic_pctlops;
1204b5c23aa4SPaul Cercueil 	pctl_desc->pmxops = &ingenic_pmxops;
1205b5c23aa4SPaul Cercueil 	pctl_desc->confops = &ingenic_confops;
1206b5c23aa4SPaul Cercueil 	pctl_desc->npins = chip_info->num_chips * PINS_PER_GPIO_CHIP;
1207a86854d0SKees Cook 	pctl_desc->pins = jzpc->pdesc = devm_kcalloc(&pdev->dev,
1208a86854d0SKees Cook 			pctl_desc->npins, sizeof(*jzpc->pdesc), GFP_KERNEL);
1209b5c23aa4SPaul Cercueil 	if (!jzpc->pdesc)
1210b5c23aa4SPaul Cercueil 		return -ENOMEM;
1211b5c23aa4SPaul Cercueil 
1212b5c23aa4SPaul Cercueil 	for (i = 0; i < pctl_desc->npins; i++) {
1213b5c23aa4SPaul Cercueil 		jzpc->pdesc[i].number = i;
1214b5c23aa4SPaul Cercueil 		jzpc->pdesc[i].name = kasprintf(GFP_KERNEL, "P%c%d",
1215b5c23aa4SPaul Cercueil 						'A' + (i / PINS_PER_GPIO_CHIP),
1216b5c23aa4SPaul Cercueil 						i % PINS_PER_GPIO_CHIP);
1217b5c23aa4SPaul Cercueil 	}
1218b5c23aa4SPaul Cercueil 
1219b5c23aa4SPaul Cercueil 	jzpc->pctl = devm_pinctrl_register(dev, pctl_desc, jzpc);
1220e7f4c4bfSDan Carpenter 	if (IS_ERR(jzpc->pctl)) {
1221b5c23aa4SPaul Cercueil 		dev_err(dev, "Failed to register pinctrl\n");
1222e7f4c4bfSDan Carpenter 		return PTR_ERR(jzpc->pctl);
1223b5c23aa4SPaul Cercueil 	}
1224b5c23aa4SPaul Cercueil 
1225b5c23aa4SPaul Cercueil 	for (i = 0; i < chip_info->num_groups; i++) {
1226b5c23aa4SPaul Cercueil 		const struct group_desc *group = &chip_info->groups[i];
1227b5c23aa4SPaul Cercueil 
1228b5c23aa4SPaul Cercueil 		err = pinctrl_generic_add_group(jzpc->pctl, group->name,
1229b5c23aa4SPaul Cercueil 				group->pins, group->num_pins, group->data);
1230b5c23aa4SPaul Cercueil 		if (err) {
1231b5c23aa4SPaul Cercueil 			dev_err(dev, "Failed to register group %s\n",
1232b5c23aa4SPaul Cercueil 					group->name);
1233b5c23aa4SPaul Cercueil 			return err;
1234b5c23aa4SPaul Cercueil 		}
1235b5c23aa4SPaul Cercueil 	}
1236b5c23aa4SPaul Cercueil 
1237b5c23aa4SPaul Cercueil 	for (i = 0; i < chip_info->num_functions; i++) {
1238b5c23aa4SPaul Cercueil 		const struct function_desc *func = &chip_info->functions[i];
1239b5c23aa4SPaul Cercueil 
1240b5c23aa4SPaul Cercueil 		err = pinmux_generic_add_function(jzpc->pctl, func->name,
1241b5c23aa4SPaul Cercueil 				func->group_names, func->num_group_names,
1242b5c23aa4SPaul Cercueil 				func->data);
1243b5c23aa4SPaul Cercueil 		if (err) {
1244b5c23aa4SPaul Cercueil 			dev_err(dev, "Failed to register function %s\n",
1245b5c23aa4SPaul Cercueil 					func->name);
1246b5c23aa4SPaul Cercueil 			return err;
1247b5c23aa4SPaul Cercueil 		}
1248b5c23aa4SPaul Cercueil 	}
1249b5c23aa4SPaul Cercueil 
1250b5c23aa4SPaul Cercueil 	dev_set_drvdata(dev, jzpc->map);
1251b5c23aa4SPaul Cercueil 
1252e72394e2SPaul Cercueil 	for_each_child_of_node(dev->of_node, node) {
1253e72394e2SPaul Cercueil 		if (of_match_node(ingenic_gpio_of_match, node)) {
1254e72394e2SPaul Cercueil 			err = ingenic_gpio_probe(jzpc, node);
1255e72394e2SPaul Cercueil 			if (err)
1256b5c23aa4SPaul Cercueil 				return err;
1257b5c23aa4SPaul Cercueil 		}
1258b5c23aa4SPaul Cercueil 	}
1259b5c23aa4SPaul Cercueil 
1260b5c23aa4SPaul Cercueil 	return 0;
1261b5c23aa4SPaul Cercueil }
1262b5c23aa4SPaul Cercueil 
1263b5c23aa4SPaul Cercueil static const struct platform_device_id ingenic_pinctrl_ids[] = {
1264b5c23aa4SPaul Cercueil 	{ "jz4740-pinctrl", ID_JZ4740 },
1265*f2a96765SPaul Cercueil 	{ "jz4725b-pinctrl", ID_JZ4725B },
1266b5c23aa4SPaul Cercueil 	{ "jz4770-pinctrl", ID_JZ4770 },
1267b5c23aa4SPaul Cercueil 	{ "jz4780-pinctrl", ID_JZ4780 },
1268b5c23aa4SPaul Cercueil 	{},
1269b5c23aa4SPaul Cercueil };
1270b5c23aa4SPaul Cercueil 
1271b5c23aa4SPaul Cercueil static struct platform_driver ingenic_pinctrl_driver = {
1272b5c23aa4SPaul Cercueil 	.driver = {
1273b5c23aa4SPaul Cercueil 		.name = "pinctrl-ingenic",
1274b5c23aa4SPaul Cercueil 		.of_match_table = of_match_ptr(ingenic_pinctrl_of_match),
1275b5c23aa4SPaul Cercueil 	},
1276b5c23aa4SPaul Cercueil 	.id_table = ingenic_pinctrl_ids,
1277b5c23aa4SPaul Cercueil };
1278b5c23aa4SPaul Cercueil 
1279b5c23aa4SPaul Cercueil static int __init ingenic_pinctrl_drv_register(void)
1280b5c23aa4SPaul Cercueil {
12814717b11fSPaul Cercueil 	return platform_driver_probe(&ingenic_pinctrl_driver,
12824717b11fSPaul Cercueil 				     ingenic_pinctrl_probe);
1283b5c23aa4SPaul Cercueil }
1284556a36a7SPaul Cercueil subsys_initcall(ingenic_pinctrl_drv_register);
1285