blob: 710062be524136ac1f28f37b6bba19b0d003df84 [file] [log] [blame]
Paul Cercueilb5c23aa2017-05-12 18:52:56 +02001/*
2 * Ingenic SoCs pinctrl driver
3 *
4 * Copyright (c) 2017 Paul Cercueil <paul@crapouillou.net>
5 *
6 * License terms: GNU General Public License (GPL) version 2
7 */
8
9#include <linux/compiler.h>
Linus Walleij28d6eeb2018-08-29 13:39:54 +020010#include <linux/gpio/driver.h>
Paul Cercueilb5c23aa2017-05-12 18:52:56 +020011#include <linux/interrupt.h>
12#include <linux/io.h>
13#include <linux/of_device.h>
Paul Cercueile72394e2018-08-21 18:42:32 +020014#include <linux/of_irq.h>
Paul Cercueilb5c23aa2017-05-12 18:52:56 +020015#include <linux/of_platform.h>
16#include <linux/pinctrl/pinctrl.h>
17#include <linux/pinctrl/pinmux.h>
18#include <linux/pinctrl/pinconf.h>
19#include <linux/pinctrl/pinconf-generic.h>
20#include <linux/platform_device.h>
21#include <linux/regmap.h>
22#include <linux/slab.h>
23
24#include "core.h"
25#include "pinconf.h"
26#include "pinmux.h"
27
Paul Cercueile72394e2018-08-21 18:42:32 +020028#define GPIO_PIN 0x00
29#define GPIO_MSK 0x20
30
Paul Cercueilb5c23aa2017-05-12 18:52:56 +020031#define JZ4740_GPIO_DATA 0x10
32#define JZ4740_GPIO_PULL_DIS 0x30
33#define JZ4740_GPIO_FUNC 0x40
34#define JZ4740_GPIO_SELECT 0x50
35#define JZ4740_GPIO_DIR 0x60
36#define JZ4740_GPIO_TRIG 0x70
37#define JZ4740_GPIO_FLAG 0x80
38
39#define JZ4770_GPIO_INT 0x10
Paul Cercueilb5c23aa2017-05-12 18:52:56 +020040#define JZ4770_GPIO_PAT1 0x30
41#define JZ4770_GPIO_PAT0 0x40
42#define JZ4770_GPIO_FLAG 0x50
43#define JZ4770_GPIO_PEN 0x70
44
45#define REG_SET(x) ((x) + 0x4)
46#define REG_CLEAR(x) ((x) + 0x8)
47
48#define PINS_PER_GPIO_CHIP 32
49
50enum jz_version {
51 ID_JZ4740,
Paul Cercueilf2a96762018-08-21 18:42:34 +020052 ID_JZ4725B,
Paul Cercueilb5c23aa2017-05-12 18:52:56 +020053 ID_JZ4770,
54 ID_JZ4780,
55};
56
57struct ingenic_chip_info {
58 unsigned int num_chips;
59
60 const struct group_desc *groups;
61 unsigned int num_groups;
62
63 const struct function_desc *functions;
64 unsigned int num_functions;
65
66 const u32 *pull_ups, *pull_downs;
67};
68
69struct ingenic_pinctrl {
70 struct device *dev;
71 struct regmap *map;
72 struct pinctrl_dev *pctl;
73 struct pinctrl_pin_desc *pdesc;
74 enum jz_version version;
75
76 const struct ingenic_chip_info *info;
77};
78
Paul Cercueile72394e2018-08-21 18:42:32 +020079struct ingenic_gpio_chip {
80 struct ingenic_pinctrl *jzpc;
81 struct gpio_chip gc;
82 struct irq_chip irq_chip;
83 unsigned int irq, reg_base;
84};
85
Paul Cercueilb5c23aa2017-05-12 18:52:56 +020086static const u32 jz4740_pull_ups[4] = {
87 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
88};
89
90static const u32 jz4740_pull_downs[4] = {
91 0x00000000, 0x00000000, 0x00000000, 0x00000000,
92};
93
94static int jz4740_mmc_1bit_pins[] = { 0x69, 0x68, 0x6a, };
95static int jz4740_mmc_4bit_pins[] = { 0x6b, 0x6c, 0x6d, };
96static int jz4740_uart0_data_pins[] = { 0x7a, 0x79, };
97static int jz4740_uart0_hwflow_pins[] = { 0x7e, 0x7f, };
98static int jz4740_uart1_data_pins[] = { 0x7e, 0x7f, };
99static int jz4740_lcd_8bit_pins[] = {
100 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x52, 0x53, 0x54,
101};
102static int jz4740_lcd_16bit_pins[] = {
103 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x55,
104};
105static int jz4740_lcd_18bit_pins[] = { 0x50, 0x51, };
106static int jz4740_lcd_18bit_tft_pins[] = { 0x56, 0x57, 0x31, 0x32, };
107static int jz4740_nand_cs1_pins[] = { 0x39, };
108static int jz4740_nand_cs2_pins[] = { 0x3a, };
109static int jz4740_nand_cs3_pins[] = { 0x3b, };
110static int jz4740_nand_cs4_pins[] = { 0x3c, };
111static int jz4740_pwm_pwm0_pins[] = { 0x77, };
112static int jz4740_pwm_pwm1_pins[] = { 0x78, };
113static int jz4740_pwm_pwm2_pins[] = { 0x79, };
114static int jz4740_pwm_pwm3_pins[] = { 0x7a, };
115static int jz4740_pwm_pwm4_pins[] = { 0x7b, };
116static int jz4740_pwm_pwm5_pins[] = { 0x7c, };
117static int jz4740_pwm_pwm6_pins[] = { 0x7e, };
118static int jz4740_pwm_pwm7_pins[] = { 0x7f, };
119
120static int jz4740_mmc_1bit_funcs[] = { 0, 0, 0, };
121static int jz4740_mmc_4bit_funcs[] = { 0, 0, 0, };
122static int jz4740_uart0_data_funcs[] = { 1, 1, };
123static int jz4740_uart0_hwflow_funcs[] = { 1, 1, };
124static int jz4740_uart1_data_funcs[] = { 2, 2, };
125static int jz4740_lcd_8bit_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
126static int jz4740_lcd_16bit_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, };
127static int jz4740_lcd_18bit_funcs[] = { 0, 0, };
128static int jz4740_lcd_18bit_tft_funcs[] = { 0, 0, 0, 0, };
129static int jz4740_nand_cs1_funcs[] = { 0, };
130static int jz4740_nand_cs2_funcs[] = { 0, };
131static int jz4740_nand_cs3_funcs[] = { 0, };
132static int jz4740_nand_cs4_funcs[] = { 0, };
133static int jz4740_pwm_pwm0_funcs[] = { 0, };
134static int jz4740_pwm_pwm1_funcs[] = { 0, };
135static int jz4740_pwm_pwm2_funcs[] = { 0, };
136static int jz4740_pwm_pwm3_funcs[] = { 0, };
137static int jz4740_pwm_pwm4_funcs[] = { 0, };
138static int jz4740_pwm_pwm5_funcs[] = { 0, };
139static int jz4740_pwm_pwm6_funcs[] = { 0, };
140static int jz4740_pwm_pwm7_funcs[] = { 0, };
141
142#define INGENIC_PIN_GROUP(name, id) \
143 { \
144 name, \
145 id##_pins, \
146 ARRAY_SIZE(id##_pins), \
147 id##_funcs, \
148 }
149
150static const struct group_desc jz4740_groups[] = {
151 INGENIC_PIN_GROUP("mmc-1bit", jz4740_mmc_1bit),
152 INGENIC_PIN_GROUP("mmc-4bit", jz4740_mmc_4bit),
153 INGENIC_PIN_GROUP("uart0-data", jz4740_uart0_data),
154 INGENIC_PIN_GROUP("uart0-hwflow", jz4740_uart0_hwflow),
155 INGENIC_PIN_GROUP("uart1-data", jz4740_uart1_data),
156 INGENIC_PIN_GROUP("lcd-8bit", jz4740_lcd_8bit),
157 INGENIC_PIN_GROUP("lcd-16bit", jz4740_lcd_16bit),
158 INGENIC_PIN_GROUP("lcd-18bit", jz4740_lcd_18bit),
159 INGENIC_PIN_GROUP("lcd-18bit-tft", jz4740_lcd_18bit_tft),
160 { "lcd-no-pins", },
161 INGENIC_PIN_GROUP("nand-cs1", jz4740_nand_cs1),
162 INGENIC_PIN_GROUP("nand-cs2", jz4740_nand_cs2),
163 INGENIC_PIN_GROUP("nand-cs3", jz4740_nand_cs3),
164 INGENIC_PIN_GROUP("nand-cs4", jz4740_nand_cs4),
165 INGENIC_PIN_GROUP("pwm0", jz4740_pwm_pwm0),
166 INGENIC_PIN_GROUP("pwm1", jz4740_pwm_pwm1),
167 INGENIC_PIN_GROUP("pwm2", jz4740_pwm_pwm2),
168 INGENIC_PIN_GROUP("pwm3", jz4740_pwm_pwm3),
169 INGENIC_PIN_GROUP("pwm4", jz4740_pwm_pwm4),
170 INGENIC_PIN_GROUP("pwm5", jz4740_pwm_pwm5),
171 INGENIC_PIN_GROUP("pwm6", jz4740_pwm_pwm6),
172 INGENIC_PIN_GROUP("pwm7", jz4740_pwm_pwm7),
173};
174
175static const char *jz4740_mmc_groups[] = { "mmc-1bit", "mmc-4bit", };
176static const char *jz4740_uart0_groups[] = { "uart0-data", "uart0-hwflow", };
177static const char *jz4740_uart1_groups[] = { "uart1-data", };
178static const char *jz4740_lcd_groups[] = {
179 "lcd-8bit", "lcd-16bit", "lcd-18bit", "lcd-18bit-tft", "lcd-no-pins",
180};
181static const char *jz4740_nand_groups[] = {
182 "nand-cs1", "nand-cs2", "nand-cs3", "nand-cs4",
183};
184static const char *jz4740_pwm0_groups[] = { "pwm0", };
185static const char *jz4740_pwm1_groups[] = { "pwm1", };
186static const char *jz4740_pwm2_groups[] = { "pwm2", };
187static const char *jz4740_pwm3_groups[] = { "pwm3", };
188static const char *jz4740_pwm4_groups[] = { "pwm4", };
189static const char *jz4740_pwm5_groups[] = { "pwm5", };
190static const char *jz4740_pwm6_groups[] = { "pwm6", };
191static const char *jz4740_pwm7_groups[] = { "pwm7", };
192
193static const struct function_desc jz4740_functions[] = {
194 { "mmc", jz4740_mmc_groups, ARRAY_SIZE(jz4740_mmc_groups), },
195 { "uart0", jz4740_uart0_groups, ARRAY_SIZE(jz4740_uart0_groups), },
196 { "uart1", jz4740_uart1_groups, ARRAY_SIZE(jz4740_uart1_groups), },
197 { "lcd", jz4740_lcd_groups, ARRAY_SIZE(jz4740_lcd_groups), },
198 { "nand", jz4740_nand_groups, ARRAY_SIZE(jz4740_nand_groups), },
199 { "pwm0", jz4740_pwm0_groups, ARRAY_SIZE(jz4740_pwm0_groups), },
200 { "pwm1", jz4740_pwm1_groups, ARRAY_SIZE(jz4740_pwm1_groups), },
201 { "pwm2", jz4740_pwm2_groups, ARRAY_SIZE(jz4740_pwm2_groups), },
202 { "pwm3", jz4740_pwm3_groups, ARRAY_SIZE(jz4740_pwm3_groups), },
203 { "pwm4", jz4740_pwm4_groups, ARRAY_SIZE(jz4740_pwm4_groups), },
204 { "pwm5", jz4740_pwm5_groups, ARRAY_SIZE(jz4740_pwm5_groups), },
205 { "pwm6", jz4740_pwm6_groups, ARRAY_SIZE(jz4740_pwm6_groups), },
206 { "pwm7", jz4740_pwm7_groups, ARRAY_SIZE(jz4740_pwm7_groups), },
207};
208
209static const struct ingenic_chip_info jz4740_chip_info = {
210 .num_chips = 4,
211 .groups = jz4740_groups,
212 .num_groups = ARRAY_SIZE(jz4740_groups),
213 .functions = jz4740_functions,
214 .num_functions = ARRAY_SIZE(jz4740_functions),
215 .pull_ups = jz4740_pull_ups,
216 .pull_downs = jz4740_pull_downs,
217};
218
Paul Cercueilf2a96762018-08-21 18:42:34 +0200219static int jz4725b_mmc0_1bit_pins[] = { 0x48, 0x49, 0x5c, };
220static int jz4725b_mmc0_4bit_pins[] = { 0x5d, 0x5b, 0x56, };
221static int jz4725b_mmc1_1bit_pins[] = { 0x7a, 0x7b, 0x7c, };
222static int jz4725b_mmc1_4bit_pins[] = { 0x7d, 0x7e, 0x7f, };
223static int jz4725b_uart_data_pins[] = { 0x4c, 0x4d, };
224static int jz4725b_nand_cs1_pins[] = { 0x55, };
225static int jz4725b_nand_cs2_pins[] = { 0x56, };
226static int jz4725b_nand_cs3_pins[] = { 0x57, };
227static int jz4725b_nand_cs4_pins[] = { 0x58, };
228static int jz4725b_nand_cle_ale_pins[] = { 0x48, 0x49 };
229static int jz4725b_nand_fre_fwe_pins[] = { 0x5c, 0x5d };
230static int jz4725b_pwm_pwm0_pins[] = { 0x4a, };
231static int jz4725b_pwm_pwm1_pins[] = { 0x4b, };
232static int jz4725b_pwm_pwm2_pins[] = { 0x4c, };
233static int jz4725b_pwm_pwm3_pins[] = { 0x4d, };
234static int jz4725b_pwm_pwm4_pins[] = { 0x4e, };
235static int jz4725b_pwm_pwm5_pins[] = { 0x4f, };
236
237static int jz4725b_mmc0_1bit_funcs[] = { 1, 1, 1, };
238static int jz4725b_mmc0_4bit_funcs[] = { 1, 0, 1, };
239static int jz4725b_mmc1_1bit_funcs[] = { 0, 0, 0, };
240static int jz4725b_mmc1_4bit_funcs[] = { 0, 0, 0, };
241static int jz4725b_uart_data_funcs[] = { 1, 1, };
242static int jz4725b_nand_cs1_funcs[] = { 0, };
243static int jz4725b_nand_cs2_funcs[] = { 0, };
244static int jz4725b_nand_cs3_funcs[] = { 0, };
245static int jz4725b_nand_cs4_funcs[] = { 0, };
246static int jz4725b_nand_cle_ale_funcs[] = { 0, 0, };
247static int jz4725b_nand_fre_fwe_funcs[] = { 0, 0, };
248static int jz4725b_pwm_pwm0_funcs[] = { 0, };
249static int jz4725b_pwm_pwm1_funcs[] = { 0, };
250static int jz4725b_pwm_pwm2_funcs[] = { 0, };
251static int jz4725b_pwm_pwm3_funcs[] = { 0, };
252static int jz4725b_pwm_pwm4_funcs[] = { 0, };
253static int jz4725b_pwm_pwm5_funcs[] = { 0, };
254
255static const struct group_desc jz4725b_groups[] = {
256 INGENIC_PIN_GROUP("mmc0-1bit", jz4725b_mmc0_1bit),
257 INGENIC_PIN_GROUP("mmc0-4bit", jz4725b_mmc0_4bit),
258 INGENIC_PIN_GROUP("mmc1-1bit", jz4725b_mmc1_1bit),
259 INGENIC_PIN_GROUP("mmc1-4bit", jz4725b_mmc1_4bit),
260 INGENIC_PIN_GROUP("uart-data", jz4725b_uart_data),
261 INGENIC_PIN_GROUP("nand-cs1", jz4725b_nand_cs1),
262 INGENIC_PIN_GROUP("nand-cs2", jz4725b_nand_cs2),
263 INGENIC_PIN_GROUP("nand-cs3", jz4725b_nand_cs3),
264 INGENIC_PIN_GROUP("nand-cs4", jz4725b_nand_cs4),
265 INGENIC_PIN_GROUP("nand-cle-ale", jz4725b_nand_cle_ale),
266 INGENIC_PIN_GROUP("nand-fre-fwe", jz4725b_nand_fre_fwe),
267 INGENIC_PIN_GROUP("pwm0", jz4725b_pwm_pwm0),
268 INGENIC_PIN_GROUP("pwm1", jz4725b_pwm_pwm1),
269 INGENIC_PIN_GROUP("pwm2", jz4725b_pwm_pwm2),
270 INGENIC_PIN_GROUP("pwm3", jz4725b_pwm_pwm3),
271 INGENIC_PIN_GROUP("pwm4", jz4725b_pwm_pwm4),
272 INGENIC_PIN_GROUP("pwm5", jz4725b_pwm_pwm5),
273};
274
275static const char *jz4725b_mmc0_groups[] = { "mmc0-1bit", "mmc0-4bit", };
276static const char *jz4725b_mmc1_groups[] = { "mmc1-1bit", "mmc1-4bit", };
277static const char *jz4725b_uart_groups[] = { "uart-data", };
278static const char *jz4725b_nand_groups[] = {
279 "nand-cs1", "nand-cs2", "nand-cs3", "nand-cs4",
280 "nand-cle-ale", "nand-fre-fwe",
281};
282static const char *jz4725b_pwm0_groups[] = { "pwm0", };
283static const char *jz4725b_pwm1_groups[] = { "pwm1", };
284static const char *jz4725b_pwm2_groups[] = { "pwm2", };
285static const char *jz4725b_pwm3_groups[] = { "pwm3", };
286static const char *jz4725b_pwm4_groups[] = { "pwm4", };
287static const char *jz4725b_pwm5_groups[] = { "pwm5", };
288
289static const struct function_desc jz4725b_functions[] = {
290 { "mmc0", jz4725b_mmc0_groups, ARRAY_SIZE(jz4725b_mmc0_groups), },
291 { "mmc1", jz4725b_mmc1_groups, ARRAY_SIZE(jz4725b_mmc1_groups), },
292 { "uart", jz4725b_uart_groups, ARRAY_SIZE(jz4725b_uart_groups), },
293 { "nand", jz4725b_nand_groups, ARRAY_SIZE(jz4725b_nand_groups), },
294 { "pwm0", jz4725b_pwm0_groups, ARRAY_SIZE(jz4725b_pwm0_groups), },
295 { "pwm1", jz4725b_pwm1_groups, ARRAY_SIZE(jz4725b_pwm1_groups), },
296 { "pwm2", jz4725b_pwm2_groups, ARRAY_SIZE(jz4725b_pwm2_groups), },
297 { "pwm3", jz4725b_pwm3_groups, ARRAY_SIZE(jz4725b_pwm3_groups), },
298 { "pwm4", jz4725b_pwm4_groups, ARRAY_SIZE(jz4725b_pwm4_groups), },
299 { "pwm5", jz4725b_pwm5_groups, ARRAY_SIZE(jz4725b_pwm5_groups), },
300};
301
302static const struct ingenic_chip_info jz4725b_chip_info = {
303 .num_chips = 4,
304 .groups = jz4725b_groups,
305 .num_groups = ARRAY_SIZE(jz4725b_groups),
306 .functions = jz4725b_functions,
307 .num_functions = ARRAY_SIZE(jz4725b_functions),
308 .pull_ups = jz4740_pull_ups,
309 .pull_downs = jz4740_pull_downs,
310};
311
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200312static const u32 jz4770_pull_ups[6] = {
313 0x3fffffff, 0xfff0030c, 0xffffffff, 0xffff4fff, 0xfffffb7c, 0xffa7f00f,
314};
315
316static const u32 jz4770_pull_downs[6] = {
317 0x00000000, 0x000f0c03, 0x00000000, 0x0000b000, 0x00000483, 0x00580ff0,
318};
319
320static int jz4770_uart0_data_pins[] = { 0xa0, 0xa3, };
321static int jz4770_uart0_hwflow_pins[] = { 0xa1, 0xa2, };
322static int jz4770_uart1_data_pins[] = { 0x7a, 0x7c, };
323static int jz4770_uart1_hwflow_pins[] = { 0x7b, 0x7d, };
Zhou Yanjieff656e42019-01-28 23:19:57 +0800324static int jz4770_uart2_data_pins[] = { 0x5c, 0x5e, };
325static int jz4770_uart2_hwflow_pins[] = { 0x5d, 0x5f, };
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200326static int jz4770_uart3_data_pins[] = { 0x6c, 0x85, };
327static int jz4770_uart3_hwflow_pins[] = { 0x88, 0x89, };
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200328static int jz4770_mmc0_1bit_a_pins[] = { 0x12, 0x13, 0x14, };
Zhou Yanjieff656e42019-01-28 23:19:57 +0800329static int jz4770_mmc0_4bit_a_pins[] = { 0x15, 0x16, 0x17, };
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200330static int jz4770_mmc0_1bit_e_pins[] = { 0x9c, 0x9d, 0x94, };
Zhou Yanjieff656e42019-01-28 23:19:57 +0800331static int jz4770_mmc0_4bit_e_pins[] = { 0x95, 0x96, 0x97, };
332static int jz4770_mmc0_8bit_e_pins[] = { 0x98, 0x99, 0x9a, 0x9b, };
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200333static int jz4770_mmc1_1bit_d_pins[] = { 0x78, 0x79, 0x74, };
Zhou Yanjieff656e42019-01-28 23:19:57 +0800334static int jz4770_mmc1_4bit_d_pins[] = { 0x75, 0x76, 0x77, };
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200335static int jz4770_mmc1_1bit_e_pins[] = { 0x9c, 0x9d, 0x94, };
Zhou Yanjieff656e42019-01-28 23:19:57 +0800336static int jz4770_mmc1_4bit_e_pins[] = { 0x95, 0x96, 0x97, };
337static int jz4770_mmc1_8bit_e_pins[] = { 0x98, 0x99, 0x9a, 0x9b, };
338static int jz4770_nemc_8bit_data_pins[] = {
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200339 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
340};
Zhou Yanjieff656e42019-01-28 23:19:57 +0800341static int jz4770_nemc_16bit_data_pins[] = {
342 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
343};
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200344static int jz4770_nemc_cle_ale_pins[] = { 0x20, 0x21, };
345static int jz4770_nemc_addr_pins[] = { 0x22, 0x23, 0x24, 0x25, };
346static int jz4770_nemc_rd_we_pins[] = { 0x10, 0x11, };
347static int jz4770_nemc_frd_fwe_pins[] = { 0x12, 0x13, };
348static int jz4770_nemc_cs1_pins[] = { 0x15, };
349static int jz4770_nemc_cs2_pins[] = { 0x16, };
350static int jz4770_nemc_cs3_pins[] = { 0x17, };
351static int jz4770_nemc_cs4_pins[] = { 0x18, };
352static int jz4770_nemc_cs5_pins[] = { 0x19, };
353static int jz4770_nemc_cs6_pins[] = { 0x1a, };
Zhou Yanjieff656e42019-01-28 23:19:57 +0800354static int jz4770_i2c0_pins[] = { 0x7e, 0x7f, };
355static int jz4770_i2c1_pins[] = { 0x9e, 0x9f, };
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200356static int jz4770_i2c2_pins[] = { 0xb0, 0xb1, };
Zhou Yanjieff656e42019-01-28 23:19:57 +0800357static int jz4770_cim_8bit_pins[] = {
358 0x26, 0x27, 0x28, 0x29,
359 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31,
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200360};
Zhou Yanjieff656e42019-01-28 23:19:57 +0800361static int jz4770_cim_12bit_pins[] = {
362 0x32, 0x33, 0xb0, 0xb1,
363};
364static int jz4770_lcd_24bit_pins[] = {
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200365 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
366 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
367 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
Zhou Yanjieff656e42019-01-28 23:19:57 +0800368 0x58, 0x59, 0x5a, 0x5b,
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200369};
370static int jz4770_pwm_pwm0_pins[] = { 0x80, };
371static int jz4770_pwm_pwm1_pins[] = { 0x81, };
372static int jz4770_pwm_pwm2_pins[] = { 0x82, };
373static int jz4770_pwm_pwm3_pins[] = { 0x83, };
374static int jz4770_pwm_pwm4_pins[] = { 0x84, };
375static int jz4770_pwm_pwm5_pins[] = { 0x85, };
376static int jz4770_pwm_pwm6_pins[] = { 0x6a, };
377static int jz4770_pwm_pwm7_pins[] = { 0x6b, };
378
379static int jz4770_uart0_data_funcs[] = { 0, 0, };
380static int jz4770_uart0_hwflow_funcs[] = { 0, 0, };
381static int jz4770_uart1_data_funcs[] = { 0, 0, };
382static int jz4770_uart1_hwflow_funcs[] = { 0, 0, };
Zhou Yanjieff656e42019-01-28 23:19:57 +0800383static int jz4770_uart2_data_funcs[] = { 0, 0, };
384static int jz4770_uart2_hwflow_funcs[] = { 0, 0, };
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200385static int jz4770_uart3_data_funcs[] = { 0, 1, };
386static int jz4770_uart3_hwflow_funcs[] = { 0, 0, };
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200387static int jz4770_mmc0_1bit_a_funcs[] = { 1, 1, 0, };
Zhou Yanjieff656e42019-01-28 23:19:57 +0800388static int jz4770_mmc0_4bit_a_funcs[] = { 1, 1, 1, };
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200389static int jz4770_mmc0_1bit_e_funcs[] = { 0, 0, 0, };
Zhou Yanjieff656e42019-01-28 23:19:57 +0800390static int jz4770_mmc0_4bit_e_funcs[] = { 0, 0, 0, };
391static int jz4770_mmc0_8bit_e_funcs[] = { 0, 0, 0, 0, };
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200392static int jz4770_mmc1_1bit_d_funcs[] = { 0, 0, 0, };
Zhou Yanjieff656e42019-01-28 23:19:57 +0800393static int jz4770_mmc1_4bit_d_funcs[] = { 0, 0, 0, };
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200394static int jz4770_mmc1_1bit_e_funcs[] = { 1, 1, 1, };
Zhou Yanjieff656e42019-01-28 23:19:57 +0800395static int jz4770_mmc1_4bit_e_funcs[] = { 1, 1, 1, };
396static int jz4770_mmc1_8bit_e_funcs[] = { 1, 1, 1, 1, };
397static int jz4770_nemc_8bit_data_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, };
398static int jz4770_nemc_16bit_data_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, };
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200399static int jz4770_nemc_cle_ale_funcs[] = { 0, 0, };
400static int jz4770_nemc_addr_funcs[] = { 0, 0, 0, 0, };
401static int jz4770_nemc_rd_we_funcs[] = { 0, 0, };
402static int jz4770_nemc_frd_fwe_funcs[] = { 0, 0, };
403static int jz4770_nemc_cs1_funcs[] = { 0, };
404static int jz4770_nemc_cs2_funcs[] = { 0, };
405static int jz4770_nemc_cs3_funcs[] = { 0, };
406static int jz4770_nemc_cs4_funcs[] = { 0, };
407static int jz4770_nemc_cs5_funcs[] = { 0, };
408static int jz4770_nemc_cs6_funcs[] = { 0, };
409static int jz4770_i2c0_funcs[] = { 0, 0, };
410static int jz4770_i2c1_funcs[] = { 0, 0, };
411static int jz4770_i2c2_funcs[] = { 2, 2, };
Zhou Yanjieff656e42019-01-28 23:19:57 +0800412static int jz4770_cim_8bit_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
413static int jz4770_cim_12bit_funcs[] = { 0, 0, 0, 0, };
414static int jz4770_lcd_24bit_funcs[] = {
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200415 0, 0, 0, 0, 0, 0, 0, 0,
416 0, 0, 0, 0, 0, 0, 0, 0,
Zhou Yanjieff656e42019-01-28 23:19:57 +0800417 0, 0, 0, 0, 0, 0, 0, 0,
418 0, 0, 0, 0,
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200419};
420static int jz4770_pwm_pwm0_funcs[] = { 0, };
421static int jz4770_pwm_pwm1_funcs[] = { 0, };
422static int jz4770_pwm_pwm2_funcs[] = { 0, };
423static int jz4770_pwm_pwm3_funcs[] = { 0, };
424static int jz4770_pwm_pwm4_funcs[] = { 0, };
425static int jz4770_pwm_pwm5_funcs[] = { 0, };
426static int jz4770_pwm_pwm6_funcs[] = { 0, };
427static int jz4770_pwm_pwm7_funcs[] = { 0, };
428
429static const struct group_desc jz4770_groups[] = {
430 INGENIC_PIN_GROUP("uart0-data", jz4770_uart0_data),
431 INGENIC_PIN_GROUP("uart0-hwflow", jz4770_uart0_hwflow),
432 INGENIC_PIN_GROUP("uart1-data", jz4770_uart1_data),
433 INGENIC_PIN_GROUP("uart1-hwflow", jz4770_uart1_hwflow),
434 INGENIC_PIN_GROUP("uart2-data", jz4770_uart2_data),
435 INGENIC_PIN_GROUP("uart2-hwflow", jz4770_uart2_hwflow),
436 INGENIC_PIN_GROUP("uart3-data", jz4770_uart3_data),
437 INGENIC_PIN_GROUP("uart3-hwflow", jz4770_uart3_hwflow),
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200438 INGENIC_PIN_GROUP("mmc0-1bit-a", jz4770_mmc0_1bit_a),
Zhou Yanjieff656e42019-01-28 23:19:57 +0800439 INGENIC_PIN_GROUP("mmc0-4bit-a", jz4770_mmc0_4bit_a),
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200440 INGENIC_PIN_GROUP("mmc0-1bit-e", jz4770_mmc0_1bit_e),
Zhou Yanjieff656e42019-01-28 23:19:57 +0800441 INGENIC_PIN_GROUP("mmc0-4bit-e", jz4770_mmc0_4bit_e),
442 INGENIC_PIN_GROUP("mmc0-8bit-e", jz4770_mmc0_8bit_e),
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200443 INGENIC_PIN_GROUP("mmc1-1bit-d", jz4770_mmc1_1bit_d),
Zhou Yanjieff656e42019-01-28 23:19:57 +0800444 INGENIC_PIN_GROUP("mmc1-4bit-d", jz4770_mmc1_4bit_d),
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200445 INGENIC_PIN_GROUP("mmc1-1bit-e", jz4770_mmc1_1bit_e),
Zhou Yanjieff656e42019-01-28 23:19:57 +0800446 INGENIC_PIN_GROUP("mmc1-4bit-e", jz4770_mmc1_4bit_e),
447 INGENIC_PIN_GROUP("mmc1-8bit-e", jz4770_mmc1_8bit_e),
448 INGENIC_PIN_GROUP("nemc-8bit-data", jz4770_nemc_8bit_data),
449 INGENIC_PIN_GROUP("nemc-16bit-data", jz4770_nemc_16bit_data),
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200450 INGENIC_PIN_GROUP("nemc-cle-ale", jz4770_nemc_cle_ale),
451 INGENIC_PIN_GROUP("nemc-addr", jz4770_nemc_addr),
452 INGENIC_PIN_GROUP("nemc-rd-we", jz4770_nemc_rd_we),
453 INGENIC_PIN_GROUP("nemc-frd-fwe", jz4770_nemc_frd_fwe),
454 INGENIC_PIN_GROUP("nemc-cs1", jz4770_nemc_cs1),
455 INGENIC_PIN_GROUP("nemc-cs2", jz4770_nemc_cs2),
456 INGENIC_PIN_GROUP("nemc-cs3", jz4770_nemc_cs3),
457 INGENIC_PIN_GROUP("nemc-cs4", jz4770_nemc_cs4),
458 INGENIC_PIN_GROUP("nemc-cs5", jz4770_nemc_cs5),
459 INGENIC_PIN_GROUP("nemc-cs6", jz4770_nemc_cs6),
460 INGENIC_PIN_GROUP("i2c0-data", jz4770_i2c0),
461 INGENIC_PIN_GROUP("i2c1-data", jz4770_i2c1),
462 INGENIC_PIN_GROUP("i2c2-data", jz4770_i2c2),
Zhou Yanjieff656e42019-01-28 23:19:57 +0800463 INGENIC_PIN_GROUP("cim-data-8bit", jz4770_cim_8bit),
464 INGENIC_PIN_GROUP("cim-data-12bit", jz4770_cim_12bit),
465 INGENIC_PIN_GROUP("lcd-24bit", jz4770_lcd_24bit),
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200466 { "lcd-no-pins", },
467 INGENIC_PIN_GROUP("pwm0", jz4770_pwm_pwm0),
468 INGENIC_PIN_GROUP("pwm1", jz4770_pwm_pwm1),
469 INGENIC_PIN_GROUP("pwm2", jz4770_pwm_pwm2),
470 INGENIC_PIN_GROUP("pwm3", jz4770_pwm_pwm3),
471 INGENIC_PIN_GROUP("pwm4", jz4770_pwm_pwm4),
472 INGENIC_PIN_GROUP("pwm5", jz4770_pwm_pwm5),
473 INGENIC_PIN_GROUP("pwm6", jz4770_pwm_pwm6),
474 INGENIC_PIN_GROUP("pwm7", jz4770_pwm_pwm7),
475};
476
477static const char *jz4770_uart0_groups[] = { "uart0-data", "uart0-hwflow", };
478static const char *jz4770_uart1_groups[] = { "uart1-data", "uart1-hwflow", };
479static const char *jz4770_uart2_groups[] = { "uart2-data", "uart2-hwflow", };
480static const char *jz4770_uart3_groups[] = { "uart3-data", "uart3-hwflow", };
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200481static const char *jz4770_mmc0_groups[] = {
Zhou Yanjieff656e42019-01-28 23:19:57 +0800482 "mmc0-1bit-a", "mmc0-4bit-a",
483 "mmc0-1bit-e", "mmc0-4bit-e", "mmc0-8bit-e",
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200484};
485static const char *jz4770_mmc1_groups[] = {
Zhou Yanjieff656e42019-01-28 23:19:57 +0800486 "mmc1-1bit-d", "mmc1-4bit-d",
487 "mmc1-1bit-e", "mmc1-4bit-e", "mmc1-8bit-e",
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200488};
489static const char *jz4770_nemc_groups[] = {
Zhou Yanjieff656e42019-01-28 23:19:57 +0800490 "nemc-8bit-data", "nemc-16bit-data", "nemc-cle-ale",
491 "nemc-addr", "nemc-rd-we", "nemc-frd-fwe",
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200492};
493static const char *jz4770_cs1_groups[] = { "nemc-cs1", };
Zhou Yanjieff656e42019-01-28 23:19:57 +0800494static const char *jz4770_cs2_groups[] = { "nemc-cs2", };
495static const char *jz4770_cs3_groups[] = { "nemc-cs3", };
496static const char *jz4770_cs4_groups[] = { "nemc-cs4", };
497static const char *jz4770_cs5_groups[] = { "nemc-cs5", };
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200498static const char *jz4770_cs6_groups[] = { "nemc-cs6", };
499static const char *jz4770_i2c0_groups[] = { "i2c0-data", };
500static const char *jz4770_i2c1_groups[] = { "i2c1-data", };
501static const char *jz4770_i2c2_groups[] = { "i2c2-data", };
Zhou Yanjieff656e42019-01-28 23:19:57 +0800502static const char *jz4770_cim_groups[] = { "cim-data-8bit", "cim-data-12bit", };
503static const char *jz4770_lcd_groups[] = { "lcd-24bit", "lcd-no-pins", };
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200504static const char *jz4770_pwm0_groups[] = { "pwm0", };
505static const char *jz4770_pwm1_groups[] = { "pwm1", };
506static const char *jz4770_pwm2_groups[] = { "pwm2", };
507static const char *jz4770_pwm3_groups[] = { "pwm3", };
508static const char *jz4770_pwm4_groups[] = { "pwm4", };
509static const char *jz4770_pwm5_groups[] = { "pwm5", };
510static const char *jz4770_pwm6_groups[] = { "pwm6", };
511static const char *jz4770_pwm7_groups[] = { "pwm7", };
512
513static const struct function_desc jz4770_functions[] = {
514 { "uart0", jz4770_uart0_groups, ARRAY_SIZE(jz4770_uart0_groups), },
515 { "uart1", jz4770_uart1_groups, ARRAY_SIZE(jz4770_uart1_groups), },
516 { "uart2", jz4770_uart2_groups, ARRAY_SIZE(jz4770_uart2_groups), },
517 { "uart3", jz4770_uart3_groups, ARRAY_SIZE(jz4770_uart3_groups), },
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200518 { "mmc0", jz4770_mmc0_groups, ARRAY_SIZE(jz4770_mmc0_groups), },
519 { "mmc1", jz4770_mmc1_groups, ARRAY_SIZE(jz4770_mmc1_groups), },
520 { "nemc", jz4770_nemc_groups, ARRAY_SIZE(jz4770_nemc_groups), },
521 { "nemc-cs1", jz4770_cs1_groups, ARRAY_SIZE(jz4770_cs1_groups), },
Zhou Yanjieff656e42019-01-28 23:19:57 +0800522 { "nemc-cs2", jz4770_cs2_groups, ARRAY_SIZE(jz4770_cs2_groups), },
523 { "nemc-cs3", jz4770_cs3_groups, ARRAY_SIZE(jz4770_cs3_groups), },
524 { "nemc-cs4", jz4770_cs4_groups, ARRAY_SIZE(jz4770_cs4_groups), },
525 { "nemc-cs5", jz4770_cs5_groups, ARRAY_SIZE(jz4770_cs5_groups), },
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200526 { "nemc-cs6", jz4770_cs6_groups, ARRAY_SIZE(jz4770_cs6_groups), },
527 { "i2c0", jz4770_i2c0_groups, ARRAY_SIZE(jz4770_i2c0_groups), },
528 { "i2c1", jz4770_i2c1_groups, ARRAY_SIZE(jz4770_i2c1_groups), },
529 { "i2c2", jz4770_i2c2_groups, ARRAY_SIZE(jz4770_i2c2_groups), },
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200530 { "cim", jz4770_cim_groups, ARRAY_SIZE(jz4770_cim_groups), },
531 { "lcd", jz4770_lcd_groups, ARRAY_SIZE(jz4770_lcd_groups), },
532 { "pwm0", jz4770_pwm0_groups, ARRAY_SIZE(jz4770_pwm0_groups), },
533 { "pwm1", jz4770_pwm1_groups, ARRAY_SIZE(jz4770_pwm1_groups), },
534 { "pwm2", jz4770_pwm2_groups, ARRAY_SIZE(jz4770_pwm2_groups), },
535 { "pwm3", jz4770_pwm3_groups, ARRAY_SIZE(jz4770_pwm3_groups), },
536 { "pwm4", jz4770_pwm4_groups, ARRAY_SIZE(jz4770_pwm4_groups), },
537 { "pwm5", jz4770_pwm5_groups, ARRAY_SIZE(jz4770_pwm5_groups), },
538 { "pwm6", jz4770_pwm6_groups, ARRAY_SIZE(jz4770_pwm6_groups), },
539 { "pwm7", jz4770_pwm7_groups, ARRAY_SIZE(jz4770_pwm7_groups), },
540};
541
542static const struct ingenic_chip_info jz4770_chip_info = {
543 .num_chips = 6,
544 .groups = jz4770_groups,
545 .num_groups = ARRAY_SIZE(jz4770_groups),
546 .functions = jz4770_functions,
547 .num_functions = ARRAY_SIZE(jz4770_functions),
548 .pull_ups = jz4770_pull_ups,
549 .pull_downs = jz4770_pull_downs,
550};
551
Zhou Yanjieff656e42019-01-28 23:19:57 +0800552static int jz4780_uart2_data_pins[] = { 0x66, 0x67, };
553static int jz4780_uart2_hwflow_pins[] = { 0x65, 0x64, };
554static int jz4780_uart4_data_pins[] = { 0x54, 0x4a, };
555static int jz4780_mmc0_8bit_a_pins[] = { 0x04, 0x05, 0x06, 0x07, 0x18, };
556static int jz4780_i2c3_pins[] = { 0x6a, 0x6b, };
557static int jz4780_i2c4_e_pins[] = { 0x8c, 0x8d, };
558static int jz4780_i2c4_f_pins[] = { 0xb9, 0xb8, };
559
560static int jz4780_uart2_data_funcs[] = { 1, 1, };
561static int jz4780_uart2_hwflow_funcs[] = { 1, 1, };
562static int jz4780_uart4_data_funcs[] = { 2, 2, };
563static int jz4780_mmc0_8bit_a_funcs[] = { 1, 1, 1, 1, 1, };
564static int jz4780_i2c3_funcs[] = { 1, 1, };
565static int jz4780_i2c4_e_funcs[] = { 1, 1, };
566static int jz4780_i2c4_f_funcs[] = { 1, 1, };
567
568static const struct group_desc jz4780_groups[] = {
569 INGENIC_PIN_GROUP("uart0-data", jz4770_uart0_data),
570 INGENIC_PIN_GROUP("uart0-hwflow", jz4770_uart0_hwflow),
571 INGENIC_PIN_GROUP("uart1-data", jz4770_uart1_data),
572 INGENIC_PIN_GROUP("uart1-hwflow", jz4770_uart1_hwflow),
573 INGENIC_PIN_GROUP("uart2-data", jz4780_uart2_data),
574 INGENIC_PIN_GROUP("uart2-hwflow", jz4780_uart2_hwflow),
575 INGENIC_PIN_GROUP("uart3-data", jz4770_uart3_data),
576 INGENIC_PIN_GROUP("uart3-hwflow", jz4770_uart3_hwflow),
577 INGENIC_PIN_GROUP("uart4-data", jz4780_uart4_data),
578 INGENIC_PIN_GROUP("mmc0-1bit-a", jz4770_mmc0_1bit_a),
579 INGENIC_PIN_GROUP("mmc0-4bit-a", jz4770_mmc0_4bit_a),
580 INGENIC_PIN_GROUP("mmc0-8bit-a", jz4780_mmc0_8bit_a),
581 INGENIC_PIN_GROUP("mmc0-1bit-e", jz4770_mmc0_1bit_e),
582 INGENIC_PIN_GROUP("mmc0-4bit-e", jz4770_mmc0_4bit_e),
583 INGENIC_PIN_GROUP("mmc1-1bit-d", jz4770_mmc1_1bit_d),
584 INGENIC_PIN_GROUP("mmc1-4bit-d", jz4770_mmc1_4bit_d),
585 INGENIC_PIN_GROUP("mmc1-1bit-e", jz4770_mmc1_1bit_e),
586 INGENIC_PIN_GROUP("mmc1-4bit-e", jz4770_mmc1_4bit_e),
587 INGENIC_PIN_GROUP("nemc-data", jz4770_nemc_8bit_data),
588 INGENIC_PIN_GROUP("nemc-cle-ale", jz4770_nemc_cle_ale),
589 INGENIC_PIN_GROUP("nemc-addr", jz4770_nemc_addr),
590 INGENIC_PIN_GROUP("nemc-rd-we", jz4770_nemc_rd_we),
591 INGENIC_PIN_GROUP("nemc-frd-fwe", jz4770_nemc_frd_fwe),
592 INGENIC_PIN_GROUP("nemc-cs1", jz4770_nemc_cs1),
593 INGENIC_PIN_GROUP("nemc-cs2", jz4770_nemc_cs2),
594 INGENIC_PIN_GROUP("nemc-cs3", jz4770_nemc_cs3),
595 INGENIC_PIN_GROUP("nemc-cs4", jz4770_nemc_cs4),
596 INGENIC_PIN_GROUP("nemc-cs5", jz4770_nemc_cs5),
597 INGENIC_PIN_GROUP("nemc-cs6", jz4770_nemc_cs6),
598 INGENIC_PIN_GROUP("i2c0-data", jz4770_i2c0),
599 INGENIC_PIN_GROUP("i2c1-data", jz4770_i2c1),
600 INGENIC_PIN_GROUP("i2c2-data", jz4770_i2c2),
601 INGENIC_PIN_GROUP("i2c3-data", jz4780_i2c3),
602 INGENIC_PIN_GROUP("i2c4-data-e", jz4780_i2c4_e),
603 INGENIC_PIN_GROUP("i2c4-data-f", jz4780_i2c4_f),
604 INGENIC_PIN_GROUP("cim-data", jz4770_cim_8bit),
605 INGENIC_PIN_GROUP("lcd-24bit", jz4770_lcd_24bit),
606 { "lcd-no-pins", },
607 INGENIC_PIN_GROUP("pwm0", jz4770_pwm_pwm0),
608 INGENIC_PIN_GROUP("pwm1", jz4770_pwm_pwm1),
609 INGENIC_PIN_GROUP("pwm2", jz4770_pwm_pwm2),
610 INGENIC_PIN_GROUP("pwm3", jz4770_pwm_pwm3),
611 INGENIC_PIN_GROUP("pwm4", jz4770_pwm_pwm4),
612 INGENIC_PIN_GROUP("pwm5", jz4770_pwm_pwm5),
613 INGENIC_PIN_GROUP("pwm6", jz4770_pwm_pwm6),
614 INGENIC_PIN_GROUP("pwm7", jz4770_pwm_pwm7),
615};
616
617static const char *jz4780_uart2_groups[] = { "uart2-data", "uart2-hwflow", };
618static const char *jz4780_uart4_groups[] = { "uart4-data", };
619static const char *jz4780_mmc0_groups[] = {
620 "mmc0-1bit-a", "mmc0-4bit-a", "mmc0-8bit-a",
621 "mmc0-1bit-e", "mmc0-4bit-e",
622};
623static const char *jz4780_mmc1_groups[] = {
624 "mmc1-1bit-d", "mmc1-4bit-d", "mmc1-1bit-e", "mmc1-4bit-e",
625};
626static const char *jz4780_nemc_groups[] = {
627 "nemc-data", "nemc-cle-ale", "nemc-addr",
628 "nemc-rd-we", "nemc-frd-fwe",
629};
630static const char *jz4780_i2c3_groups[] = { "i2c3-data", };
631static const char *jz4780_i2c4_groups[] = { "i2c4-data-e", "i2c4-data-f", };
632static const char *jz4780_cim_groups[] = { "cim-data", };
633
634static const struct function_desc jz4780_functions[] = {
635 { "uart0", jz4770_uart0_groups, ARRAY_SIZE(jz4770_uart0_groups), },
636 { "uart1", jz4770_uart1_groups, ARRAY_SIZE(jz4770_uart1_groups), },
637 { "uart2", jz4780_uart2_groups, ARRAY_SIZE(jz4780_uart2_groups), },
638 { "uart3", jz4770_uart3_groups, ARRAY_SIZE(jz4770_uart3_groups), },
639 { "uart4", jz4780_uart4_groups, ARRAY_SIZE(jz4780_uart4_groups), },
640 { "mmc0", jz4780_mmc0_groups, ARRAY_SIZE(jz4780_mmc0_groups), },
641 { "mmc1", jz4780_mmc1_groups, ARRAY_SIZE(jz4780_mmc1_groups), },
642 { "nemc", jz4780_nemc_groups, ARRAY_SIZE(jz4780_nemc_groups), },
643 { "nemc-cs1", jz4770_cs1_groups, ARRAY_SIZE(jz4770_cs1_groups), },
644 { "nemc-cs2", jz4770_cs2_groups, ARRAY_SIZE(jz4770_cs2_groups), },
645 { "nemc-cs3", jz4770_cs3_groups, ARRAY_SIZE(jz4770_cs3_groups), },
646 { "nemc-cs4", jz4770_cs4_groups, ARRAY_SIZE(jz4770_cs4_groups), },
647 { "nemc-cs5", jz4770_cs5_groups, ARRAY_SIZE(jz4770_cs5_groups), },
648 { "nemc-cs6", jz4770_cs6_groups, ARRAY_SIZE(jz4770_cs6_groups), },
649 { "i2c0", jz4770_i2c0_groups, ARRAY_SIZE(jz4770_i2c0_groups), },
650 { "i2c1", jz4770_i2c1_groups, ARRAY_SIZE(jz4770_i2c1_groups), },
651 { "i2c2", jz4770_i2c2_groups, ARRAY_SIZE(jz4770_i2c2_groups), },
652 { "i2c3", jz4780_i2c3_groups, ARRAY_SIZE(jz4780_i2c3_groups), },
653 { "i2c4", jz4780_i2c4_groups, ARRAY_SIZE(jz4780_i2c4_groups), },
654 { "cim", jz4780_cim_groups, ARRAY_SIZE(jz4780_cim_groups), },
655 { "lcd", jz4770_lcd_groups, ARRAY_SIZE(jz4770_lcd_groups), },
656 { "pwm0", jz4770_pwm0_groups, ARRAY_SIZE(jz4770_pwm0_groups), },
657 { "pwm1", jz4770_pwm1_groups, ARRAY_SIZE(jz4770_pwm1_groups), },
658 { "pwm2", jz4770_pwm2_groups, ARRAY_SIZE(jz4770_pwm2_groups), },
659 { "pwm3", jz4770_pwm3_groups, ARRAY_SIZE(jz4770_pwm3_groups), },
660 { "pwm4", jz4770_pwm4_groups, ARRAY_SIZE(jz4770_pwm4_groups), },
661 { "pwm5", jz4770_pwm5_groups, ARRAY_SIZE(jz4770_pwm5_groups), },
662 { "pwm6", jz4770_pwm6_groups, ARRAY_SIZE(jz4770_pwm6_groups), },
663 { "pwm7", jz4770_pwm7_groups, ARRAY_SIZE(jz4770_pwm7_groups), },
664};
665
666static const struct ingenic_chip_info jz4780_chip_info = {
667 .num_chips = 6,
668 .groups = jz4780_groups,
669 .num_groups = ARRAY_SIZE(jz4780_groups),
670 .functions = jz4780_functions,
671 .num_functions = ARRAY_SIZE(jz4780_functions),
672 .pull_ups = jz4770_pull_ups,
673 .pull_downs = jz4770_pull_downs,
674};
675
Paul Cercueile72394e2018-08-21 18:42:32 +0200676static u32 gpio_ingenic_read_reg(struct ingenic_gpio_chip *jzgc, u8 reg)
677{
678 unsigned int val;
679
680 regmap_read(jzgc->jzpc->map, jzgc->reg_base + reg, &val);
681
682 return (u32) val;
683}
684
685static void gpio_ingenic_set_bit(struct ingenic_gpio_chip *jzgc,
686 u8 reg, u8 offset, bool set)
687{
688 if (set)
689 reg = REG_SET(reg);
690 else
691 reg = REG_CLEAR(reg);
692
693 regmap_write(jzgc->jzpc->map, jzgc->reg_base + reg, BIT(offset));
694}
695
696static inline bool ingenic_gpio_get_value(struct ingenic_gpio_chip *jzgc,
697 u8 offset)
698{
699 unsigned int val = gpio_ingenic_read_reg(jzgc, GPIO_PIN);
700
701 return !!(val & BIT(offset));
702}
703
704static void ingenic_gpio_set_value(struct ingenic_gpio_chip *jzgc,
705 u8 offset, int value)
706{
707 if (jzgc->jzpc->version >= ID_JZ4770)
708 gpio_ingenic_set_bit(jzgc, JZ4770_GPIO_PAT0, offset, !!value);
709 else
710 gpio_ingenic_set_bit(jzgc, JZ4740_GPIO_DATA, offset, !!value);
711}
712
713static void irq_set_type(struct ingenic_gpio_chip *jzgc,
714 u8 offset, unsigned int type)
715{
716 u8 reg1, reg2;
717
718 if (jzgc->jzpc->version >= ID_JZ4770) {
719 reg1 = JZ4770_GPIO_PAT1;
720 reg2 = JZ4770_GPIO_PAT0;
721 } else {
722 reg1 = JZ4740_GPIO_TRIG;
723 reg2 = JZ4740_GPIO_DIR;
724 }
725
726 switch (type) {
727 case IRQ_TYPE_EDGE_RISING:
728 gpio_ingenic_set_bit(jzgc, reg2, offset, true);
729 gpio_ingenic_set_bit(jzgc, reg1, offset, true);
730 break;
731 case IRQ_TYPE_EDGE_FALLING:
732 gpio_ingenic_set_bit(jzgc, reg2, offset, false);
733 gpio_ingenic_set_bit(jzgc, reg1, offset, true);
734 break;
735 case IRQ_TYPE_LEVEL_HIGH:
736 gpio_ingenic_set_bit(jzgc, reg2, offset, true);
737 gpio_ingenic_set_bit(jzgc, reg1, offset, false);
738 break;
739 case IRQ_TYPE_LEVEL_LOW:
740 default:
741 gpio_ingenic_set_bit(jzgc, reg2, offset, false);
742 gpio_ingenic_set_bit(jzgc, reg1, offset, false);
743 break;
744 }
745}
746
747static void ingenic_gpio_irq_mask(struct irq_data *irqd)
748{
749 struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
750 struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
751
752 gpio_ingenic_set_bit(jzgc, GPIO_MSK, irqd->hwirq, true);
753}
754
755static void ingenic_gpio_irq_unmask(struct irq_data *irqd)
756{
757 struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
758 struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
759
760 gpio_ingenic_set_bit(jzgc, GPIO_MSK, irqd->hwirq, false);
761}
762
763static void ingenic_gpio_irq_enable(struct irq_data *irqd)
764{
765 struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
766 struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
767 int irq = irqd->hwirq;
768
769 if (jzgc->jzpc->version >= ID_JZ4770)
770 gpio_ingenic_set_bit(jzgc, JZ4770_GPIO_INT, irq, true);
771 else
772 gpio_ingenic_set_bit(jzgc, JZ4740_GPIO_SELECT, irq, true);
773
774 ingenic_gpio_irq_unmask(irqd);
775}
776
777static void ingenic_gpio_irq_disable(struct irq_data *irqd)
778{
779 struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
780 struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
781 int irq = irqd->hwirq;
782
783 ingenic_gpio_irq_mask(irqd);
784
785 if (jzgc->jzpc->version >= ID_JZ4770)
786 gpio_ingenic_set_bit(jzgc, JZ4770_GPIO_INT, irq, false);
787 else
788 gpio_ingenic_set_bit(jzgc, JZ4740_GPIO_SELECT, irq, false);
789}
790
791static void ingenic_gpio_irq_ack(struct irq_data *irqd)
792{
793 struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
794 struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
795 int irq = irqd->hwirq;
796 bool high;
797
798 if (irqd_get_trigger_type(irqd) == IRQ_TYPE_EDGE_BOTH) {
799 /*
800 * Switch to an interrupt for the opposite edge to the one that
801 * triggered the interrupt being ACKed.
802 */
803 high = ingenic_gpio_get_value(jzgc, irq);
804 if (high)
805 irq_set_type(jzgc, irq, IRQ_TYPE_EDGE_FALLING);
806 else
807 irq_set_type(jzgc, irq, IRQ_TYPE_EDGE_RISING);
808 }
809
810 if (jzgc->jzpc->version >= ID_JZ4770)
811 gpio_ingenic_set_bit(jzgc, JZ4770_GPIO_FLAG, irq, false);
812 else
813 gpio_ingenic_set_bit(jzgc, JZ4740_GPIO_DATA, irq, true);
814}
815
816static int ingenic_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
817{
818 struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
819 struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
820
821 switch (type) {
822 case IRQ_TYPE_EDGE_BOTH:
823 case IRQ_TYPE_EDGE_RISING:
824 case IRQ_TYPE_EDGE_FALLING:
825 irq_set_handler_locked(irqd, handle_edge_irq);
826 break;
827 case IRQ_TYPE_LEVEL_HIGH:
828 case IRQ_TYPE_LEVEL_LOW:
829 irq_set_handler_locked(irqd, handle_level_irq);
830 break;
831 default:
832 irq_set_handler_locked(irqd, handle_bad_irq);
833 }
834
835 if (type == IRQ_TYPE_EDGE_BOTH) {
836 /*
837 * The hardware does not support interrupts on both edges. The
838 * best we can do is to set up a single-edge interrupt and then
839 * switch to the opposing edge when ACKing the interrupt.
840 */
841 bool high = ingenic_gpio_get_value(jzgc, irqd->hwirq);
842
843 type = high ? IRQ_TYPE_EDGE_FALLING : IRQ_TYPE_EDGE_RISING;
844 }
845
846 irq_set_type(jzgc, irqd->hwirq, type);
847 return 0;
848}
849
850static int ingenic_gpio_irq_set_wake(struct irq_data *irqd, unsigned int on)
851{
852 struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
853 struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
854
855 return irq_set_irq_wake(jzgc->irq, on);
856}
857
858static void ingenic_gpio_irq_handler(struct irq_desc *desc)
859{
860 struct gpio_chip *gc = irq_desc_get_handler_data(desc);
861 struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
862 struct irq_chip *irq_chip = irq_data_get_irq_chip(&desc->irq_data);
863 unsigned long flag, i;
864
865 chained_irq_enter(irq_chip, desc);
866
867 if (jzgc->jzpc->version >= ID_JZ4770)
868 flag = gpio_ingenic_read_reg(jzgc, JZ4770_GPIO_FLAG);
869 else
870 flag = gpio_ingenic_read_reg(jzgc, JZ4740_GPIO_FLAG);
871
872 for_each_set_bit(i, &flag, 32)
873 generic_handle_irq(irq_linear_revmap(gc->irq.domain, i));
874 chained_irq_exit(irq_chip, desc);
875}
876
877static void ingenic_gpio_set(struct gpio_chip *gc,
878 unsigned int offset, int value)
879{
880 struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
881
882 ingenic_gpio_set_value(jzgc, offset, value);
883}
884
885static int ingenic_gpio_get(struct gpio_chip *gc, unsigned int offset)
886{
887 struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
888
889 return (int) ingenic_gpio_get_value(jzgc, offset);
890}
891
892static int ingenic_gpio_direction_input(struct gpio_chip *gc,
893 unsigned int offset)
894{
895 return pinctrl_gpio_direction_input(gc->base + offset);
896}
897
898static int ingenic_gpio_direction_output(struct gpio_chip *gc,
899 unsigned int offset, int value)
900{
901 ingenic_gpio_set(gc, offset, value);
902 return pinctrl_gpio_direction_output(gc->base + offset);
903}
904
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200905static inline void ingenic_config_pin(struct ingenic_pinctrl *jzpc,
906 unsigned int pin, u8 reg, bool set)
907{
908 unsigned int idx = pin % PINS_PER_GPIO_CHIP;
909 unsigned int offt = pin / PINS_PER_GPIO_CHIP;
910
911 regmap_write(jzpc->map, offt * 0x100 +
912 (set ? REG_SET(reg) : REG_CLEAR(reg)), BIT(idx));
913}
914
915static inline bool ingenic_get_pin_config(struct ingenic_pinctrl *jzpc,
916 unsigned int pin, u8 reg)
917{
918 unsigned int idx = pin % PINS_PER_GPIO_CHIP;
919 unsigned int offt = pin / PINS_PER_GPIO_CHIP;
920 unsigned int val;
921
922 regmap_read(jzpc->map, offt * 0x100 + reg, &val);
923
924 return val & BIT(idx);
925}
926
Paul Cercueilebd66512018-08-21 18:42:33 +0200927static int ingenic_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
928{
929 struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
930 struct ingenic_pinctrl *jzpc = jzgc->jzpc;
931 unsigned int pin = gc->base + offset;
932
933 if (jzpc->version >= ID_JZ4770)
934 return ingenic_get_pin_config(jzpc, pin, JZ4770_GPIO_PAT1);
935
936 if (ingenic_get_pin_config(jzpc, pin, JZ4740_GPIO_SELECT))
937 return true;
938
939 return !ingenic_get_pin_config(jzpc, pin, JZ4740_GPIO_DIR);
940}
941
Julia Lawall5bf7b842017-08-10 12:06:23 +0200942static const struct pinctrl_ops ingenic_pctlops = {
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200943 .get_groups_count = pinctrl_generic_get_group_count,
944 .get_group_name = pinctrl_generic_get_group_name,
945 .get_group_pins = pinctrl_generic_get_group_pins,
946 .dt_node_to_map = pinconf_generic_dt_node_to_map_all,
947 .dt_free_map = pinconf_generic_dt_free_map,
948};
949
950static int ingenic_pinmux_set_pin_fn(struct ingenic_pinctrl *jzpc,
951 int pin, int func)
952{
953 unsigned int idx = pin % PINS_PER_GPIO_CHIP;
954 unsigned int offt = pin / PINS_PER_GPIO_CHIP;
955
956 dev_dbg(jzpc->dev, "set pin P%c%u to function %u\n",
957 'A' + offt, idx, func);
958
959 if (jzpc->version >= ID_JZ4770) {
960 ingenic_config_pin(jzpc, pin, JZ4770_GPIO_INT, false);
Paul Cercueile72394e2018-08-21 18:42:32 +0200961 ingenic_config_pin(jzpc, pin, GPIO_MSK, false);
Paul Cercueilb5c23aa2017-05-12 18:52:56 +0200962 ingenic_config_pin(jzpc, pin, JZ4770_GPIO_PAT1, func & 0x2);
963 ingenic_config_pin(jzpc, pin, JZ4770_GPIO_PAT0, func & 0x1);
964 } else {
965 ingenic_config_pin(jzpc, pin, JZ4740_GPIO_FUNC, true);
966 ingenic_config_pin(jzpc, pin, JZ4740_GPIO_TRIG, func & 0x2);
967 ingenic_config_pin(jzpc, pin, JZ4740_GPIO_SELECT, func > 0);
968 }
969
970 return 0;
971}
972
973static int ingenic_pinmux_set_mux(struct pinctrl_dev *pctldev,
974 unsigned int selector, unsigned int group)
975{
976 struct ingenic_pinctrl *jzpc = pinctrl_dev_get_drvdata(pctldev);
977 struct function_desc *func;
978 struct group_desc *grp;
979 unsigned int i;
980
981 func = pinmux_generic_get_function(pctldev, selector);
982 if (!func)
983 return -EINVAL;
984
985 grp = pinctrl_generic_get_group(pctldev, group);
986 if (!grp)
987 return -EINVAL;
988
989 dev_dbg(pctldev->dev, "enable function %s group %s\n",
990 func->name, grp->name);
991
992 for (i = 0; i < grp->num_pins; i++) {
993 int *pin_modes = grp->data;
994
995 ingenic_pinmux_set_pin_fn(jzpc, grp->pins[i], pin_modes[i]);
996 }
997
998 return 0;
999}
1000
1001static int ingenic_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
1002 struct pinctrl_gpio_range *range,
1003 unsigned int pin, bool input)
1004{
1005 struct ingenic_pinctrl *jzpc = pinctrl_dev_get_drvdata(pctldev);
1006 unsigned int idx = pin % PINS_PER_GPIO_CHIP;
1007 unsigned int offt = pin / PINS_PER_GPIO_CHIP;
1008
1009 dev_dbg(pctldev->dev, "set pin P%c%u to %sput\n",
1010 'A' + offt, idx, input ? "in" : "out");
1011
1012 if (jzpc->version >= ID_JZ4770) {
1013 ingenic_config_pin(jzpc, pin, JZ4770_GPIO_INT, false);
Paul Cercueile72394e2018-08-21 18:42:32 +02001014 ingenic_config_pin(jzpc, pin, GPIO_MSK, true);
Paul Cercueilb5c23aa2017-05-12 18:52:56 +02001015 ingenic_config_pin(jzpc, pin, JZ4770_GPIO_PAT1, input);
1016 } else {
1017 ingenic_config_pin(jzpc, pin, JZ4740_GPIO_SELECT, false);
Paul Cercueil0084a782018-06-27 13:49:02 +02001018 ingenic_config_pin(jzpc, pin, JZ4740_GPIO_DIR, !input);
Paul Cercueilb5c23aa2017-05-12 18:52:56 +02001019 ingenic_config_pin(jzpc, pin, JZ4740_GPIO_FUNC, false);
1020 }
1021
1022 return 0;
1023}
1024
Julia Lawall5bf7b842017-08-10 12:06:23 +02001025static const struct pinmux_ops ingenic_pmxops = {
Paul Cercueilb5c23aa2017-05-12 18:52:56 +02001026 .get_functions_count = pinmux_generic_get_function_count,
1027 .get_function_name = pinmux_generic_get_function_name,
1028 .get_function_groups = pinmux_generic_get_function_groups,
1029 .set_mux = ingenic_pinmux_set_mux,
1030 .gpio_set_direction = ingenic_pinmux_gpio_set_direction,
1031};
1032
1033static int ingenic_pinconf_get(struct pinctrl_dev *pctldev,
1034 unsigned int pin, unsigned long *config)
1035{
1036 struct ingenic_pinctrl *jzpc = pinctrl_dev_get_drvdata(pctldev);
1037 enum pin_config_param param = pinconf_to_config_param(*config);
1038 unsigned int idx = pin % PINS_PER_GPIO_CHIP;
1039 unsigned int offt = pin / PINS_PER_GPIO_CHIP;
1040 bool pull;
1041
1042 if (jzpc->version >= ID_JZ4770)
1043 pull = !ingenic_get_pin_config(jzpc, pin, JZ4770_GPIO_PEN);
1044 else
1045 pull = !ingenic_get_pin_config(jzpc, pin, JZ4740_GPIO_PULL_DIS);
1046
1047 switch (param) {
1048 case PIN_CONFIG_BIAS_DISABLE:
1049 if (pull)
1050 return -EINVAL;
1051 break;
1052
1053 case PIN_CONFIG_BIAS_PULL_UP:
1054 if (!pull || !(jzpc->info->pull_ups[offt] & BIT(idx)))
1055 return -EINVAL;
1056 break;
1057
1058 case PIN_CONFIG_BIAS_PULL_DOWN:
1059 if (!pull || !(jzpc->info->pull_downs[offt] & BIT(idx)))
1060 return -EINVAL;
1061 break;
1062
1063 default:
1064 return -ENOTSUPP;
1065 }
1066
1067 *config = pinconf_to_config_packed(param, 1);
1068 return 0;
1069}
1070
1071static void ingenic_set_bias(struct ingenic_pinctrl *jzpc,
1072 unsigned int pin, bool enabled)
1073{
1074 if (jzpc->version >= ID_JZ4770)
1075 ingenic_config_pin(jzpc, pin, JZ4770_GPIO_PEN, !enabled);
1076 else
1077 ingenic_config_pin(jzpc, pin, JZ4740_GPIO_PULL_DIS, !enabled);
1078}
1079
1080static int ingenic_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
1081 unsigned long *configs, unsigned int num_configs)
1082{
1083 struct ingenic_pinctrl *jzpc = pinctrl_dev_get_drvdata(pctldev);
1084 unsigned int idx = pin % PINS_PER_GPIO_CHIP;
1085 unsigned int offt = pin / PINS_PER_GPIO_CHIP;
1086 unsigned int cfg;
1087
1088 for (cfg = 0; cfg < num_configs; cfg++) {
1089 switch (pinconf_to_config_param(configs[cfg])) {
1090 case PIN_CONFIG_BIAS_DISABLE:
1091 case PIN_CONFIG_BIAS_PULL_UP:
1092 case PIN_CONFIG_BIAS_PULL_DOWN:
1093 continue;
1094 default:
1095 return -ENOTSUPP;
1096 }
1097 }
1098
1099 for (cfg = 0; cfg < num_configs; cfg++) {
1100 switch (pinconf_to_config_param(configs[cfg])) {
1101 case PIN_CONFIG_BIAS_DISABLE:
1102 dev_dbg(jzpc->dev, "disable pull-over for pin P%c%u\n",
1103 'A' + offt, idx);
1104 ingenic_set_bias(jzpc, pin, false);
1105 break;
1106
1107 case PIN_CONFIG_BIAS_PULL_UP:
1108 if (!(jzpc->info->pull_ups[offt] & BIT(idx)))
1109 return -EINVAL;
1110 dev_dbg(jzpc->dev, "set pull-up for pin P%c%u\n",
1111 'A' + offt, idx);
1112 ingenic_set_bias(jzpc, pin, true);
1113 break;
1114
1115 case PIN_CONFIG_BIAS_PULL_DOWN:
1116 if (!(jzpc->info->pull_downs[offt] & BIT(idx)))
1117 return -EINVAL;
1118 dev_dbg(jzpc->dev, "set pull-down for pin P%c%u\n",
1119 'A' + offt, idx);
1120 ingenic_set_bias(jzpc, pin, true);
1121 break;
1122
1123 default:
1124 unreachable();
1125 }
1126 }
1127
1128 return 0;
1129}
1130
1131static int ingenic_pinconf_group_get(struct pinctrl_dev *pctldev,
1132 unsigned int group, unsigned long *config)
1133{
1134 const unsigned int *pins;
1135 unsigned int i, npins, old = 0;
1136 int ret;
1137
1138 ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins);
1139 if (ret)
1140 return ret;
1141
1142 for (i = 0; i < npins; i++) {
1143 if (ingenic_pinconf_get(pctldev, pins[i], config))
1144 return -ENOTSUPP;
1145
1146 /* configs do not match between two pins */
1147 if (i && (old != *config))
1148 return -ENOTSUPP;
1149
1150 old = *config;
1151 }
1152
1153 return 0;
1154}
1155
1156static int ingenic_pinconf_group_set(struct pinctrl_dev *pctldev,
1157 unsigned int group, unsigned long *configs,
1158 unsigned int num_configs)
1159{
1160 const unsigned int *pins;
1161 unsigned int i, npins;
1162 int ret;
1163
1164 ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins);
1165 if (ret)
1166 return ret;
1167
1168 for (i = 0; i < npins; i++) {
1169 ret = ingenic_pinconf_set(pctldev,
1170 pins[i], configs, num_configs);
1171 if (ret)
1172 return ret;
1173 }
1174
1175 return 0;
1176}
1177
Julia Lawall5bf7b842017-08-10 12:06:23 +02001178static const struct pinconf_ops ingenic_confops = {
Paul Cercueilb5c23aa2017-05-12 18:52:56 +02001179 .is_generic = true,
1180 .pin_config_get = ingenic_pinconf_get,
1181 .pin_config_set = ingenic_pinconf_set,
1182 .pin_config_group_get = ingenic_pinconf_group_get,
1183 .pin_config_group_set = ingenic_pinconf_group_set,
1184};
1185
1186static const struct regmap_config ingenic_pinctrl_regmap_config = {
1187 .reg_bits = 32,
1188 .val_bits = 32,
1189 .reg_stride = 4,
1190};
1191
1192static const struct of_device_id ingenic_pinctrl_of_match[] = {
1193 { .compatible = "ingenic,jz4740-pinctrl", .data = (void *) ID_JZ4740 },
Paul Cercueilf2a96762018-08-21 18:42:34 +02001194 { .compatible = "ingenic,jz4725b-pinctrl", .data = (void *)ID_JZ4725B },
Paul Cercueilb5c23aa2017-05-12 18:52:56 +02001195 { .compatible = "ingenic,jz4770-pinctrl", .data = (void *) ID_JZ4770 },
1196 { .compatible = "ingenic,jz4780-pinctrl", .data = (void *) ID_JZ4780 },
1197 {},
1198};
1199
Paul Cercueile72394e2018-08-21 18:42:32 +02001200static const struct of_device_id ingenic_gpio_of_match[] __initconst = {
1201 { .compatible = "ingenic,jz4740-gpio", },
1202 { .compatible = "ingenic,jz4770-gpio", },
1203 { .compatible = "ingenic,jz4780-gpio", },
1204 {},
1205};
1206
1207static int __init ingenic_gpio_probe(struct ingenic_pinctrl *jzpc,
1208 struct device_node *node)
1209{
1210 struct ingenic_gpio_chip *jzgc;
1211 struct device *dev = jzpc->dev;
1212 unsigned int bank;
1213 int err;
1214
1215 err = of_property_read_u32(node, "reg", &bank);
1216 if (err) {
1217 dev_err(dev, "Cannot read \"reg\" property: %i\n", err);
1218 return err;
1219 }
1220
1221 jzgc = devm_kzalloc(dev, sizeof(*jzgc), GFP_KERNEL);
1222 if (!jzgc)
1223 return -ENOMEM;
1224
1225 jzgc->jzpc = jzpc;
1226 jzgc->reg_base = bank * 0x100;
1227
1228 jzgc->gc.label = devm_kasprintf(dev, GFP_KERNEL, "GPIO%c", 'A' + bank);
1229 if (!jzgc->gc.label)
1230 return -ENOMEM;
1231
1232 /* DO NOT EXPAND THIS: FOR BACKWARD GPIO NUMBERSPACE COMPATIBIBILITY
1233 * ONLY: WORK TO TRANSITION CONSUMERS TO USE THE GPIO DESCRIPTOR API IN
1234 * <linux/gpio/consumer.h> INSTEAD.
1235 */
1236 jzgc->gc.base = bank * 32;
1237
1238 jzgc->gc.ngpio = 32;
1239 jzgc->gc.parent = dev;
1240 jzgc->gc.of_node = node;
1241 jzgc->gc.owner = THIS_MODULE;
1242
1243 jzgc->gc.set = ingenic_gpio_set;
1244 jzgc->gc.get = ingenic_gpio_get;
1245 jzgc->gc.direction_input = ingenic_gpio_direction_input;
1246 jzgc->gc.direction_output = ingenic_gpio_direction_output;
Paul Cercueilebd66512018-08-21 18:42:33 +02001247 jzgc->gc.get_direction = ingenic_gpio_get_direction;
Paul Cercueile72394e2018-08-21 18:42:32 +02001248
1249 if (of_property_read_bool(node, "gpio-ranges")) {
1250 jzgc->gc.request = gpiochip_generic_request;
1251 jzgc->gc.free = gpiochip_generic_free;
1252 }
1253
1254 err = devm_gpiochip_add_data(dev, &jzgc->gc, jzgc);
1255 if (err)
1256 return err;
1257
1258 jzgc->irq = irq_of_parse_and_map(node, 0);
1259 if (!jzgc->irq)
1260 return -EINVAL;
1261
1262 jzgc->irq_chip.name = jzgc->gc.label;
1263 jzgc->irq_chip.irq_enable = ingenic_gpio_irq_enable;
1264 jzgc->irq_chip.irq_disable = ingenic_gpio_irq_disable;
1265 jzgc->irq_chip.irq_unmask = ingenic_gpio_irq_unmask;
1266 jzgc->irq_chip.irq_mask = ingenic_gpio_irq_mask;
1267 jzgc->irq_chip.irq_ack = ingenic_gpio_irq_ack;
1268 jzgc->irq_chip.irq_set_type = ingenic_gpio_irq_set_type;
1269 jzgc->irq_chip.irq_set_wake = ingenic_gpio_irq_set_wake;
1270 jzgc->irq_chip.flags = IRQCHIP_MASK_ON_SUSPEND;
1271
1272 err = gpiochip_irqchip_add(&jzgc->gc, &jzgc->irq_chip, 0,
1273 handle_level_irq, IRQ_TYPE_NONE);
1274 if (err)
1275 return err;
1276
1277 gpiochip_set_chained_irqchip(&jzgc->gc, &jzgc->irq_chip,
1278 jzgc->irq, ingenic_gpio_irq_handler);
1279 return 0;
1280}
1281
Paul Cercueil4717b112018-08-21 18:42:31 +02001282static int __init ingenic_pinctrl_probe(struct platform_device *pdev)
Paul Cercueilb5c23aa2017-05-12 18:52:56 +02001283{
1284 struct device *dev = &pdev->dev;
1285 struct ingenic_pinctrl *jzpc;
1286 struct pinctrl_desc *pctl_desc;
1287 void __iomem *base;
1288 const struct platform_device_id *id = platform_get_device_id(pdev);
1289 const struct of_device_id *of_id = of_match_device(
1290 ingenic_pinctrl_of_match, dev);
1291 const struct ingenic_chip_info *chip_info;
Paul Cercueile72394e2018-08-21 18:42:32 +02001292 struct device_node *node;
Paul Cercueilb5c23aa2017-05-12 18:52:56 +02001293 unsigned int i;
1294 int err;
1295
1296 jzpc = devm_kzalloc(dev, sizeof(*jzpc), GFP_KERNEL);
1297 if (!jzpc)
1298 return -ENOMEM;
1299
1300 base = devm_ioremap_resource(dev,
1301 platform_get_resource(pdev, IORESOURCE_MEM, 0));
Wei Yongjun119fcf42018-01-17 11:29:17 +00001302 if (IS_ERR(base))
Paul Cercueilb5c23aa2017-05-12 18:52:56 +02001303 return PTR_ERR(base);
Paul Cercueilb5c23aa2017-05-12 18:52:56 +02001304
1305 jzpc->map = devm_regmap_init_mmio(dev, base,
1306 &ingenic_pinctrl_regmap_config);
1307 if (IS_ERR(jzpc->map)) {
1308 dev_err(dev, "Failed to create regmap\n");
1309 return PTR_ERR(jzpc->map);
1310 }
1311
1312 jzpc->dev = dev;
1313
1314 if (of_id)
1315 jzpc->version = (enum jz_version)of_id->data;
1316 else
1317 jzpc->version = (enum jz_version)id->driver_data;
1318
Zhou Yanjieff656e42019-01-28 23:19:57 +08001319 if (jzpc->version >= ID_JZ4780)
1320 chip_info = &jz4780_chip_info;
1321 else if (jzpc->version >= ID_JZ4770)
Paul Cercueilb5c23aa2017-05-12 18:52:56 +02001322 chip_info = &jz4770_chip_info;
Paul Cercueilf2a96762018-08-21 18:42:34 +02001323 else if (jzpc->version >= ID_JZ4725B)
1324 chip_info = &jz4725b_chip_info;
Paul Cercueilb5c23aa2017-05-12 18:52:56 +02001325 else
1326 chip_info = &jz4740_chip_info;
1327 jzpc->info = chip_info;
1328
1329 pctl_desc = devm_kzalloc(&pdev->dev, sizeof(*pctl_desc), GFP_KERNEL);
1330 if (!pctl_desc)
1331 return -ENOMEM;
1332
1333 /* fill in pinctrl_desc structure */
1334 pctl_desc->name = dev_name(dev);
1335 pctl_desc->owner = THIS_MODULE;
1336 pctl_desc->pctlops = &ingenic_pctlops;
1337 pctl_desc->pmxops = &ingenic_pmxops;
1338 pctl_desc->confops = &ingenic_confops;
1339 pctl_desc->npins = chip_info->num_chips * PINS_PER_GPIO_CHIP;
Kees Cooka86854d2018-06-12 14:07:58 -07001340 pctl_desc->pins = jzpc->pdesc = devm_kcalloc(&pdev->dev,
1341 pctl_desc->npins, sizeof(*jzpc->pdesc), GFP_KERNEL);
Paul Cercueilb5c23aa2017-05-12 18:52:56 +02001342 if (!jzpc->pdesc)
1343 return -ENOMEM;
1344
1345 for (i = 0; i < pctl_desc->npins; i++) {
1346 jzpc->pdesc[i].number = i;
1347 jzpc->pdesc[i].name = kasprintf(GFP_KERNEL, "P%c%d",
1348 'A' + (i / PINS_PER_GPIO_CHIP),
1349 i % PINS_PER_GPIO_CHIP);
1350 }
1351
1352 jzpc->pctl = devm_pinctrl_register(dev, pctl_desc, jzpc);
Dan Carpentere7f4c4b2017-06-14 12:12:09 +03001353 if (IS_ERR(jzpc->pctl)) {
Paul Cercueilb5c23aa2017-05-12 18:52:56 +02001354 dev_err(dev, "Failed to register pinctrl\n");
Dan Carpentere7f4c4b2017-06-14 12:12:09 +03001355 return PTR_ERR(jzpc->pctl);
Paul Cercueilb5c23aa2017-05-12 18:52:56 +02001356 }
1357
1358 for (i = 0; i < chip_info->num_groups; i++) {
1359 const struct group_desc *group = &chip_info->groups[i];
1360
1361 err = pinctrl_generic_add_group(jzpc->pctl, group->name,
1362 group->pins, group->num_pins, group->data);
Paul Burton823dd712018-08-25 10:53:28 -07001363 if (err < 0) {
Paul Cercueilb5c23aa2017-05-12 18:52:56 +02001364 dev_err(dev, "Failed to register group %s\n",
1365 group->name);
1366 return err;
1367 }
1368 }
1369
1370 for (i = 0; i < chip_info->num_functions; i++) {
1371 const struct function_desc *func = &chip_info->functions[i];
1372
1373 err = pinmux_generic_add_function(jzpc->pctl, func->name,
1374 func->group_names, func->num_group_names,
1375 func->data);
Paul Burton823dd712018-08-25 10:53:28 -07001376 if (err < 0) {
Paul Cercueilb5c23aa2017-05-12 18:52:56 +02001377 dev_err(dev, "Failed to register function %s\n",
1378 func->name);
1379 return err;
1380 }
1381 }
1382
1383 dev_set_drvdata(dev, jzpc->map);
1384
Paul Cercueile72394e2018-08-21 18:42:32 +02001385 for_each_child_of_node(dev->of_node, node) {
1386 if (of_match_node(ingenic_gpio_of_match, node)) {
1387 err = ingenic_gpio_probe(jzpc, node);
1388 if (err)
1389 return err;
Paul Cercueilb5c23aa2017-05-12 18:52:56 +02001390 }
1391 }
1392
1393 return 0;
1394}
1395
1396static const struct platform_device_id ingenic_pinctrl_ids[] = {
1397 { "jz4740-pinctrl", ID_JZ4740 },
Paul Cercueilf2a96762018-08-21 18:42:34 +02001398 { "jz4725b-pinctrl", ID_JZ4725B },
Paul Cercueilb5c23aa2017-05-12 18:52:56 +02001399 { "jz4770-pinctrl", ID_JZ4770 },
1400 { "jz4780-pinctrl", ID_JZ4780 },
1401 {},
1402};
1403
1404static struct platform_driver ingenic_pinctrl_driver = {
1405 .driver = {
1406 .name = "pinctrl-ingenic",
1407 .of_match_table = of_match_ptr(ingenic_pinctrl_of_match),
Paul Cercueilb5c23aa2017-05-12 18:52:56 +02001408 },
Paul Cercueilb5c23aa2017-05-12 18:52:56 +02001409 .id_table = ingenic_pinctrl_ids,
1410};
1411
1412static int __init ingenic_pinctrl_drv_register(void)
1413{
Paul Cercueil4717b112018-08-21 18:42:31 +02001414 return platform_driver_probe(&ingenic_pinctrl_driver,
1415 ingenic_pinctrl_probe);
Paul Cercueilb5c23aa2017-05-12 18:52:56 +02001416}
Paul Cercueil556a36a2018-08-21 18:42:30 +02001417subsys_initcall(ingenic_pinctrl_drv_register);