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