diff options
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r-- | drivers/pinctrl/Kconfig | 5 | ||||
-rw-r--r-- | drivers/pinctrl/Makefile | 1 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-sunxi.c | 548 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-sunxi.h | 387 |
4 files changed, 941 insertions, 0 deletions
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index c31aeb01bb00..88840a421c6e 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig | |||
@@ -151,6 +151,11 @@ config PINCTRL_SIRF | |||
151 | depends on ARCH_SIRF | 151 | depends on ARCH_SIRF |
152 | select PINMUX | 152 | select PINMUX |
153 | 153 | ||
154 | config PINCTRL_SUNXI | ||
155 | bool | ||
156 | select PINMUX | ||
157 | select GENERIC_PINCONF | ||
158 | |||
154 | config PINCTRL_TEGRA | 159 | config PINCTRL_TEGRA |
155 | bool | 160 | bool |
156 | select PINMUX | 161 | select PINMUX |
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index fc4606f27dc7..a2427da4d58e 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile | |||
@@ -30,6 +30,7 @@ obj-$(CONFIG_PINCTRL_PXA168) += pinctrl-pxa168.o | |||
30 | obj-$(CONFIG_PINCTRL_PXA910) += pinctrl-pxa910.o | 30 | obj-$(CONFIG_PINCTRL_PXA910) += pinctrl-pxa910.o |
31 | obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o | 31 | obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o |
32 | obj-$(CONFIG_PINCTRL_SIRF) += pinctrl-sirf.o | 32 | obj-$(CONFIG_PINCTRL_SIRF) += pinctrl-sirf.o |
33 | obj-$(CONFIG_PINCTRL_SUNXI) += pinctrl-sunxi.o | ||
33 | obj-$(CONFIG_PINCTRL_TEGRA) += pinctrl-tegra.o | 34 | obj-$(CONFIG_PINCTRL_TEGRA) += pinctrl-tegra.o |
34 | obj-$(CONFIG_PINCTRL_TEGRA20) += pinctrl-tegra20.o | 35 | obj-$(CONFIG_PINCTRL_TEGRA20) += pinctrl-tegra20.o |
35 | obj-$(CONFIG_PINCTRL_TEGRA30) += pinctrl-tegra30.o | 36 | obj-$(CONFIG_PINCTRL_TEGRA30) += pinctrl-tegra30.o |
diff --git a/drivers/pinctrl/pinctrl-sunxi.c b/drivers/pinctrl/pinctrl-sunxi.c new file mode 100644 index 000000000000..1a81613e8f77 --- /dev/null +++ b/drivers/pinctrl/pinctrl-sunxi.c | |||
@@ -0,0 +1,548 @@ | |||
1 | /* | ||
2 | * Allwinner A1X SoCs pinctrl driver. | ||
3 | * | ||
4 | * Copyright (C) 2012 Maxime Ripard | ||
5 | * | ||
6 | * Maxime Ripard <maxime.ripard@free-electrons.com> | ||
7 | * | ||
8 | * This file is licensed under the terms of the GNU General Public | ||
9 | * License version 2. This program is licensed "as is" without any | ||
10 | * warranty of any kind, whether express or implied. | ||
11 | */ | ||
12 | |||
13 | #include <linux/io.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/of.h> | ||
16 | #include <linux/of_address.h> | ||
17 | #include <linux/of_device.h> | ||
18 | #include <linux/pinctrl/consumer.h> | ||
19 | #include <linux/pinctrl/machine.h> | ||
20 | #include <linux/pinctrl/pinctrl.h> | ||
21 | #include <linux/pinctrl/pinconf-generic.h> | ||
22 | #include <linux/pinctrl/pinmux.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/slab.h> | ||
25 | |||
26 | #include "core.h" | ||
27 | #include "pinctrl-sunxi.h" | ||
28 | |||
29 | static struct sunxi_pinctrl_group * | ||
30 | sunxi_pinctrl_find_group_by_name(struct sunxi_pinctrl *pctl, const char *group) | ||
31 | { | ||
32 | int i; | ||
33 | |||
34 | for (i = 0; i < pctl->ngroups; i++) { | ||
35 | struct sunxi_pinctrl_group *grp = pctl->groups + i; | ||
36 | |||
37 | if (!strcmp(grp->name, group)) | ||
38 | return grp; | ||
39 | } | ||
40 | |||
41 | return NULL; | ||
42 | } | ||
43 | |||
44 | static struct sunxi_pinctrl_function * | ||
45 | sunxi_pinctrl_find_function_by_name(struct sunxi_pinctrl *pctl, | ||
46 | const char *name) | ||
47 | { | ||
48 | struct sunxi_pinctrl_function *func = pctl->functions; | ||
49 | int i; | ||
50 | |||
51 | for (i = 0; i < pctl->nfunctions; i++) { | ||
52 | if (!func[i].name) | ||
53 | break; | ||
54 | |||
55 | if (!strcmp(func[i].name, name)) | ||
56 | return func + i; | ||
57 | } | ||
58 | |||
59 | return NULL; | ||
60 | } | ||
61 | |||
62 | static struct sunxi_desc_function * | ||
63 | sunxi_pinctrl_desc_find_function_by_name(struct sunxi_pinctrl *pctl, | ||
64 | const char *pin_name, | ||
65 | const char *func_name) | ||
66 | { | ||
67 | int i; | ||
68 | |||
69 | for (i = 0; i < pctl->desc->npins; i++) { | ||
70 | const struct sunxi_desc_pin *pin = pctl->desc->pins + i; | ||
71 | |||
72 | if (!strcmp(pin->pin.name, pin_name)) { | ||
73 | struct sunxi_desc_function *func = pin->functions; | ||
74 | |||
75 | while (func->name) { | ||
76 | if (!strcmp(func->name, func_name)) | ||
77 | return func; | ||
78 | |||
79 | func++; | ||
80 | } | ||
81 | } | ||
82 | } | ||
83 | |||
84 | return NULL; | ||
85 | } | ||
86 | |||
87 | static int sunxi_pctrl_get_groups_count(struct pinctrl_dev *pctldev) | ||
88 | { | ||
89 | struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | ||
90 | |||
91 | return pctl->ngroups; | ||
92 | } | ||
93 | |||
94 | static const char *sunxi_pctrl_get_group_name(struct pinctrl_dev *pctldev, | ||
95 | unsigned group) | ||
96 | { | ||
97 | struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | ||
98 | |||
99 | return pctl->groups[group].name; | ||
100 | } | ||
101 | |||
102 | static int sunxi_pctrl_get_group_pins(struct pinctrl_dev *pctldev, | ||
103 | unsigned group, | ||
104 | const unsigned **pins, | ||
105 | unsigned *num_pins) | ||
106 | { | ||
107 | struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | ||
108 | |||
109 | *pins = (unsigned *)&pctl->groups[group].pin; | ||
110 | *num_pins = 1; | ||
111 | |||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev, | ||
116 | struct device_node *node, | ||
117 | struct pinctrl_map **map, | ||
118 | unsigned *num_maps) | ||
119 | { | ||
120 | struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | ||
121 | unsigned long *pinconfig; | ||
122 | struct property *prop; | ||
123 | const char *function; | ||
124 | const char *group; | ||
125 | int ret, nmaps, i = 0; | ||
126 | u32 val; | ||
127 | |||
128 | *map = NULL; | ||
129 | *num_maps = 0; | ||
130 | |||
131 | ret = of_property_read_string(node, "allwinner,function", &function); | ||
132 | if (ret) { | ||
133 | dev_err(pctl->dev, | ||
134 | "missing allwinner,function property in node %s\n", | ||
135 | node->name); | ||
136 | return -EINVAL; | ||
137 | } | ||
138 | |||
139 | nmaps = of_property_count_strings(node, "allwinner,pins") * 2; | ||
140 | if (nmaps < 0) { | ||
141 | dev_err(pctl->dev, | ||
142 | "missing allwinner,pins property in node %s\n", | ||
143 | node->name); | ||
144 | return -EINVAL; | ||
145 | } | ||
146 | |||
147 | *map = kmalloc(nmaps * sizeof(struct pinctrl_map), GFP_KERNEL); | ||
148 | if (!map) | ||
149 | return -ENOMEM; | ||
150 | |||
151 | of_property_for_each_string(node, "allwinner,pins", prop, group) { | ||
152 | struct sunxi_pinctrl_group *grp = | ||
153 | sunxi_pinctrl_find_group_by_name(pctl, group); | ||
154 | int j = 0, configlen = 0; | ||
155 | |||
156 | if (!grp) { | ||
157 | dev_err(pctl->dev, "unknown pin %s", group); | ||
158 | continue; | ||
159 | } | ||
160 | |||
161 | if (!sunxi_pinctrl_desc_find_function_by_name(pctl, | ||
162 | grp->name, | ||
163 | function)) { | ||
164 | dev_err(pctl->dev, "unsupported function %s on pin %s", | ||
165 | function, group); | ||
166 | continue; | ||
167 | } | ||
168 | |||
169 | (*map)[i].type = PIN_MAP_TYPE_MUX_GROUP; | ||
170 | (*map)[i].data.mux.group = group; | ||
171 | (*map)[i].data.mux.function = function; | ||
172 | |||
173 | i++; | ||
174 | |||
175 | (*map)[i].type = PIN_MAP_TYPE_CONFIGS_GROUP; | ||
176 | (*map)[i].data.configs.group_or_pin = group; | ||
177 | |||
178 | if (of_find_property(node, "allwinner,drive", NULL)) | ||
179 | configlen++; | ||
180 | if (of_find_property(node, "allwinner,pull", NULL)) | ||
181 | configlen++; | ||
182 | |||
183 | pinconfig = kzalloc(configlen * sizeof(*pinconfig), GFP_KERNEL); | ||
184 | |||
185 | if (!of_property_read_u32(node, "allwinner,drive", &val)) { | ||
186 | u16 strength = (val + 1) * 10; | ||
187 | pinconfig[j++] = | ||
188 | pinconf_to_config_packed(PIN_CONFIG_DRIVE_STRENGTH, | ||
189 | strength); | ||
190 | } | ||
191 | |||
192 | if (!of_property_read_u32(node, "allwinner,pull", &val)) { | ||
193 | enum pin_config_param pull = PIN_CONFIG_END; | ||
194 | if (val == 1) | ||
195 | pull = PIN_CONFIG_BIAS_PULL_UP; | ||
196 | else if (val == 2) | ||
197 | pull = PIN_CONFIG_BIAS_PULL_DOWN; | ||
198 | pinconfig[j++] = pinconf_to_config_packed(pull, 0); | ||
199 | } | ||
200 | |||
201 | (*map)[i].data.configs.configs = pinconfig; | ||
202 | (*map)[i].data.configs.num_configs = configlen; | ||
203 | |||
204 | i++; | ||
205 | } | ||
206 | |||
207 | *num_maps = nmaps; | ||
208 | |||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static void sunxi_pctrl_dt_free_map(struct pinctrl_dev *pctldev, | ||
213 | struct pinctrl_map *map, | ||
214 | unsigned num_maps) | ||
215 | { | ||
216 | int i; | ||
217 | |||
218 | for (i = 0; i < num_maps; i++) { | ||
219 | if (map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP) | ||
220 | kfree(map[i].data.configs.configs); | ||
221 | } | ||
222 | |||
223 | kfree(map); | ||
224 | } | ||
225 | |||
226 | static struct pinctrl_ops sunxi_pctrl_ops = { | ||
227 | .dt_node_to_map = sunxi_pctrl_dt_node_to_map, | ||
228 | .dt_free_map = sunxi_pctrl_dt_free_map, | ||
229 | .get_groups_count = sunxi_pctrl_get_groups_count, | ||
230 | .get_group_name = sunxi_pctrl_get_group_name, | ||
231 | .get_group_pins = sunxi_pctrl_get_group_pins, | ||
232 | }; | ||
233 | |||
234 | static int sunxi_pconf_group_get(struct pinctrl_dev *pctldev, | ||
235 | unsigned group, | ||
236 | unsigned long *config) | ||
237 | { | ||
238 | struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | ||
239 | |||
240 | *config = pctl->groups[group].config; | ||
241 | |||
242 | return 0; | ||
243 | } | ||
244 | |||
245 | static int sunxi_pconf_group_set(struct pinctrl_dev *pctldev, | ||
246 | unsigned group, | ||
247 | unsigned long config) | ||
248 | { | ||
249 | struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | ||
250 | struct sunxi_pinctrl_group *g = &pctl->groups[group]; | ||
251 | u32 val, mask; | ||
252 | u16 strength; | ||
253 | u8 dlevel; | ||
254 | |||
255 | switch (pinconf_to_config_param(config)) { | ||
256 | case PIN_CONFIG_DRIVE_STRENGTH: | ||
257 | strength = pinconf_to_config_argument(config); | ||
258 | if (strength > 40) | ||
259 | return -EINVAL; | ||
260 | /* | ||
261 | * We convert from mA to what the register expects: | ||
262 | * 0: 10mA | ||
263 | * 1: 20mA | ||
264 | * 2: 30mA | ||
265 | * 3: 40mA | ||
266 | */ | ||
267 | dlevel = strength / 10 - 1; | ||
268 | val = readl(pctl->membase + sunxi_dlevel_reg(g->pin)); | ||
269 | mask = DLEVEL_PINS_MASK << sunxi_dlevel_offset(g->pin); | ||
270 | writel((val & ~mask) | dlevel << sunxi_dlevel_offset(g->pin), | ||
271 | pctl->membase + sunxi_dlevel_reg(g->pin)); | ||
272 | break; | ||
273 | case PIN_CONFIG_BIAS_PULL_UP: | ||
274 | val = readl(pctl->membase + sunxi_pull_reg(g->pin)); | ||
275 | mask = PULL_PINS_MASK << sunxi_pull_offset(g->pin); | ||
276 | writel((val & ~mask) | 1 << sunxi_pull_offset(g->pin), | ||
277 | pctl->membase + sunxi_pull_reg(g->pin)); | ||
278 | break; | ||
279 | case PIN_CONFIG_BIAS_PULL_DOWN: | ||
280 | val = readl(pctl->membase + sunxi_pull_reg(g->pin)); | ||
281 | mask = PULL_PINS_MASK << sunxi_pull_offset(g->pin); | ||
282 | writel((val & ~mask) | 2 << sunxi_pull_offset(g->pin), | ||
283 | pctl->membase + sunxi_pull_reg(g->pin)); | ||
284 | break; | ||
285 | default: | ||
286 | break; | ||
287 | } | ||
288 | |||
289 | /* cache the config value */ | ||
290 | g->config = config; | ||
291 | |||
292 | return 0; | ||
293 | } | ||
294 | |||
295 | static struct pinconf_ops sunxi_pconf_ops = { | ||
296 | .pin_config_group_get = sunxi_pconf_group_get, | ||
297 | .pin_config_group_set = sunxi_pconf_group_set, | ||
298 | }; | ||
299 | |||
300 | static int sunxi_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev) | ||
301 | { | ||
302 | struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | ||
303 | |||
304 | return pctl->nfunctions; | ||
305 | } | ||
306 | |||
307 | static const char *sunxi_pmx_get_func_name(struct pinctrl_dev *pctldev, | ||
308 | unsigned function) | ||
309 | { | ||
310 | struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | ||
311 | |||
312 | return pctl->functions[function].name; | ||
313 | } | ||
314 | |||
315 | static int sunxi_pmx_get_func_groups(struct pinctrl_dev *pctldev, | ||
316 | unsigned function, | ||
317 | const char * const **groups, | ||
318 | unsigned * const num_groups) | ||
319 | { | ||
320 | struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | ||
321 | |||
322 | *groups = pctl->functions[function].groups; | ||
323 | *num_groups = pctl->functions[function].ngroups; | ||
324 | |||
325 | return 0; | ||
326 | } | ||
327 | |||
328 | static void sunxi_pmx_set(struct pinctrl_dev *pctldev, | ||
329 | unsigned pin, | ||
330 | u8 config) | ||
331 | { | ||
332 | struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | ||
333 | |||
334 | u32 val = readl(pctl->membase + sunxi_mux_reg(pin)); | ||
335 | u32 mask = MUX_PINS_MASK << sunxi_mux_offset(pin); | ||
336 | writel((val & ~mask) | config << sunxi_mux_offset(pin), | ||
337 | pctl->membase + sunxi_mux_reg(pin)); | ||
338 | } | ||
339 | |||
340 | static int sunxi_pmx_enable(struct pinctrl_dev *pctldev, | ||
341 | unsigned function, | ||
342 | unsigned group) | ||
343 | { | ||
344 | struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | ||
345 | struct sunxi_pinctrl_group *g = pctl->groups + group; | ||
346 | struct sunxi_pinctrl_function *func = pctl->functions + function; | ||
347 | struct sunxi_desc_function *desc = | ||
348 | sunxi_pinctrl_desc_find_function_by_name(pctl, | ||
349 | g->name, | ||
350 | func->name); | ||
351 | |||
352 | if (!desc) | ||
353 | return -EINVAL; | ||
354 | |||
355 | sunxi_pmx_set(pctldev, g->pin, desc->muxval); | ||
356 | |||
357 | return 0; | ||
358 | } | ||
359 | |||
360 | static struct pinmux_ops sunxi_pmx_ops = { | ||
361 | .get_functions_count = sunxi_pmx_get_funcs_cnt, | ||
362 | .get_function_name = sunxi_pmx_get_func_name, | ||
363 | .get_function_groups = sunxi_pmx_get_func_groups, | ||
364 | .enable = sunxi_pmx_enable, | ||
365 | }; | ||
366 | |||
367 | static struct pinctrl_desc sunxi_pctrl_desc = { | ||
368 | .confops = &sunxi_pconf_ops, | ||
369 | .pctlops = &sunxi_pctrl_ops, | ||
370 | .pmxops = &sunxi_pmx_ops, | ||
371 | }; | ||
372 | |||
373 | static struct of_device_id sunxi_pinctrl_match[] = { | ||
374 | {} | ||
375 | }; | ||
376 | MODULE_DEVICE_TABLE(of, sunxi_pinctrl_match); | ||
377 | |||
378 | static int sunxi_pinctrl_add_function(struct sunxi_pinctrl *pctl, | ||
379 | const char *name) | ||
380 | { | ||
381 | struct sunxi_pinctrl_function *func = pctl->functions; | ||
382 | |||
383 | while (func->name) { | ||
384 | /* function already there */ | ||
385 | if (strcmp(func->name, name) == 0) { | ||
386 | func->ngroups++; | ||
387 | return -EEXIST; | ||
388 | } | ||
389 | func++; | ||
390 | } | ||
391 | |||
392 | func->name = name; | ||
393 | func->ngroups = 1; | ||
394 | |||
395 | pctl->nfunctions++; | ||
396 | |||
397 | return 0; | ||
398 | } | ||
399 | |||
400 | static int sunxi_pinctrl_build_state(struct platform_device *pdev) | ||
401 | { | ||
402 | struct sunxi_pinctrl *pctl = platform_get_drvdata(pdev); | ||
403 | int i; | ||
404 | |||
405 | pctl->ngroups = pctl->desc->npins; | ||
406 | |||
407 | /* Allocate groups */ | ||
408 | pctl->groups = devm_kzalloc(&pdev->dev, | ||
409 | pctl->ngroups * sizeof(*pctl->groups), | ||
410 | GFP_KERNEL); | ||
411 | if (!pctl->groups) | ||
412 | return -ENOMEM; | ||
413 | |||
414 | for (i = 0; i < pctl->desc->npins; i++) { | ||
415 | const struct sunxi_desc_pin *pin = pctl->desc->pins + i; | ||
416 | struct sunxi_pinctrl_group *group = pctl->groups + i; | ||
417 | |||
418 | group->name = pin->pin.name; | ||
419 | group->pin = pin->pin.number; | ||
420 | } | ||
421 | |||
422 | /* | ||
423 | * We suppose that we won't have any more functions than pins, | ||
424 | * we'll reallocate that later anyway | ||
425 | */ | ||
426 | pctl->functions = devm_kzalloc(&pdev->dev, | ||
427 | pctl->desc->npins * sizeof(*pctl->functions), | ||
428 | GFP_KERNEL); | ||
429 | if (!pctl->functions) | ||
430 | return -ENOMEM; | ||
431 | |||
432 | /* Count functions and their associated groups */ | ||
433 | for (i = 0; i < pctl->desc->npins; i++) { | ||
434 | const struct sunxi_desc_pin *pin = pctl->desc->pins + i; | ||
435 | struct sunxi_desc_function *func = pin->functions; | ||
436 | |||
437 | while (func->name) { | ||
438 | sunxi_pinctrl_add_function(pctl, func->name); | ||
439 | func++; | ||
440 | } | ||
441 | } | ||
442 | |||
443 | pctl->functions = krealloc(pctl->functions, | ||
444 | pctl->nfunctions * sizeof(*pctl->functions), | ||
445 | GFP_KERNEL); | ||
446 | |||
447 | for (i = 0; i < pctl->desc->npins; i++) { | ||
448 | const struct sunxi_desc_pin *pin = pctl->desc->pins + i; | ||
449 | struct sunxi_desc_function *func = pin->functions; | ||
450 | |||
451 | while (func->name) { | ||
452 | struct sunxi_pinctrl_function *func_item; | ||
453 | const char **func_grp; | ||
454 | |||
455 | func_item = sunxi_pinctrl_find_function_by_name(pctl, | ||
456 | func->name); | ||
457 | if (!func_item) | ||
458 | return -EINVAL; | ||
459 | |||
460 | if (!func_item->groups) { | ||
461 | func_item->groups = | ||
462 | devm_kzalloc(&pdev->dev, | ||
463 | func_item->ngroups * sizeof(*func_item->groups), | ||
464 | GFP_KERNEL); | ||
465 | if (!func_item->groups) | ||
466 | return -ENOMEM; | ||
467 | } | ||
468 | |||
469 | func_grp = func_item->groups; | ||
470 | while (*func_grp) | ||
471 | func_grp++; | ||
472 | |||
473 | *func_grp = pin->pin.name; | ||
474 | func++; | ||
475 | } | ||
476 | } | ||
477 | |||
478 | return 0; | ||
479 | } | ||
480 | |||
481 | static int sunxi_pinctrl_probe(struct platform_device *pdev) | ||
482 | { | ||
483 | struct device_node *node = pdev->dev.of_node; | ||
484 | const struct of_device_id *device; | ||
485 | struct pinctrl_pin_desc *pins; | ||
486 | struct sunxi_pinctrl *pctl; | ||
487 | int i, ret; | ||
488 | |||
489 | pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL); | ||
490 | if (!pctl) | ||
491 | return -ENOMEM; | ||
492 | platform_set_drvdata(pdev, pctl); | ||
493 | |||
494 | pctl->membase = of_iomap(node, 0); | ||
495 | if (!pctl->membase) | ||
496 | return -ENOMEM; | ||
497 | |||
498 | device = of_match_device(sunxi_pinctrl_match, &pdev->dev); | ||
499 | if (!device) | ||
500 | return -ENODEV; | ||
501 | |||
502 | pctl->desc = (struct sunxi_pinctrl_desc *)device->data; | ||
503 | |||
504 | ret = sunxi_pinctrl_build_state(pdev); | ||
505 | if (ret) { | ||
506 | dev_err(&pdev->dev, "dt probe failed: %d\n", ret); | ||
507 | return ret; | ||
508 | } | ||
509 | |||
510 | pins = devm_kzalloc(&pdev->dev, | ||
511 | pctl->desc->npins * sizeof(*pins), | ||
512 | GFP_KERNEL); | ||
513 | if (!pins) | ||
514 | return -ENOMEM; | ||
515 | |||
516 | for (i = 0; i < pctl->desc->npins; i++) | ||
517 | pins[i] = pctl->desc->pins[i].pin; | ||
518 | |||
519 | sunxi_pctrl_desc.name = dev_name(&pdev->dev); | ||
520 | sunxi_pctrl_desc.owner = THIS_MODULE; | ||
521 | sunxi_pctrl_desc.pins = pins; | ||
522 | sunxi_pctrl_desc.npins = pctl->desc->npins; | ||
523 | pctl->dev = &pdev->dev; | ||
524 | pctl->pctl_dev = pinctrl_register(&sunxi_pctrl_desc, | ||
525 | &pdev->dev, pctl); | ||
526 | if (!pctl->pctl_dev) { | ||
527 | dev_err(&pdev->dev, "couldn't register pinctrl driver\n"); | ||
528 | return -EINVAL; | ||
529 | } | ||
530 | |||
531 | dev_info(&pdev->dev, "initialized sunXi pin control driver\n"); | ||
532 | |||
533 | return 0; | ||
534 | } | ||
535 | |||
536 | static struct platform_driver sunxi_pinctrl_driver = { | ||
537 | .probe = sunxi_pinctrl_probe, | ||
538 | .driver = { | ||
539 | .name = "sunxi-pinctrl", | ||
540 | .owner = THIS_MODULE, | ||
541 | .of_match_table = sunxi_pinctrl_match, | ||
542 | }, | ||
543 | }; | ||
544 | module_platform_driver(sunxi_pinctrl_driver); | ||
545 | |||
546 | MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com"); | ||
547 | MODULE_DESCRIPTION("Allwinner A1X pinctrl driver"); | ||
548 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/pinctrl/pinctrl-sunxi.h b/drivers/pinctrl/pinctrl-sunxi.h new file mode 100644 index 000000000000..0dc3b9d5321b --- /dev/null +++ b/drivers/pinctrl/pinctrl-sunxi.h | |||
@@ -0,0 +1,387 @@ | |||
1 | /* | ||
2 | * Allwinner A1X SoCs pinctrl driver. | ||
3 | * | ||
4 | * Copyright (C) 2012 Maxime Ripard | ||
5 | * | ||
6 | * Maxime Ripard <maxime.ripard@free-electrons.com> | ||
7 | * | ||
8 | * This file is licensed under the terms of the GNU General Public | ||
9 | * License version 2. This program is licensed "as is" without any | ||
10 | * warranty of any kind, whether express or implied. | ||
11 | */ | ||
12 | |||
13 | #ifndef __PINCTRL_SUNXI_H | ||
14 | #define __PINCTRL_SUNXI_H | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | |||
18 | #define PA_BASE 0 | ||
19 | #define PB_BASE 32 | ||
20 | #define PC_BASE 64 | ||
21 | #define PD_BASE 96 | ||
22 | #define PE_BASE 128 | ||
23 | #define PF_BASE 160 | ||
24 | #define PG_BASE 192 | ||
25 | |||
26 | #define SUNXI_PINCTRL_PIN_PA0 PINCTRL_PIN(PA_BASE + 0, "PA0") | ||
27 | #define SUNXI_PINCTRL_PIN_PA1 PINCTRL_PIN(PA_BASE + 1, "PA1") | ||
28 | #define SUNXI_PINCTRL_PIN_PA2 PINCTRL_PIN(PA_BASE + 2, "PA2") | ||
29 | #define SUNXI_PINCTRL_PIN_PA3 PINCTRL_PIN(PA_BASE + 3, "PA3") | ||
30 | #define SUNXI_PINCTRL_PIN_PA4 PINCTRL_PIN(PA_BASE + 4, "PA4") | ||
31 | #define SUNXI_PINCTRL_PIN_PA5 PINCTRL_PIN(PA_BASE + 5, "PA5") | ||
32 | #define SUNXI_PINCTRL_PIN_PA6 PINCTRL_PIN(PA_BASE + 6, "PA6") | ||
33 | #define SUNXI_PINCTRL_PIN_PA7 PINCTRL_PIN(PA_BASE + 7, "PA7") | ||
34 | #define SUNXI_PINCTRL_PIN_PA8 PINCTRL_PIN(PA_BASE + 8, "PA8") | ||
35 | #define SUNXI_PINCTRL_PIN_PA9 PINCTRL_PIN(PA_BASE + 9, "PA9") | ||
36 | #define SUNXI_PINCTRL_PIN_PA10 PINCTRL_PIN(PA_BASE + 10, "PA10") | ||
37 | #define SUNXI_PINCTRL_PIN_PA11 PINCTRL_PIN(PA_BASE + 11, "PA11") | ||
38 | #define SUNXI_PINCTRL_PIN_PA12 PINCTRL_PIN(PA_BASE + 12, "PA12") | ||
39 | #define SUNXI_PINCTRL_PIN_PA13 PINCTRL_PIN(PA_BASE + 13, "PA13") | ||
40 | #define SUNXI_PINCTRL_PIN_PA14 PINCTRL_PIN(PA_BASE + 14, "PA14") | ||
41 | #define SUNXI_PINCTRL_PIN_PA15 PINCTRL_PIN(PA_BASE + 15, "PA15") | ||
42 | #define SUNXI_PINCTRL_PIN_PA16 PINCTRL_PIN(PA_BASE + 16, "PA16") | ||
43 | #define SUNXI_PINCTRL_PIN_PA17 PINCTRL_PIN(PA_BASE + 17, "PA17") | ||
44 | #define SUNXI_PINCTRL_PIN_PA18 PINCTRL_PIN(PA_BASE + 18, "PA18") | ||
45 | #define SUNXI_PINCTRL_PIN_PA19 PINCTRL_PIN(PA_BASE + 19, "PA19") | ||
46 | #define SUNXI_PINCTRL_PIN_PA20 PINCTRL_PIN(PA_BASE + 20, "PA20") | ||
47 | #define SUNXI_PINCTRL_PIN_PA21 PINCTRL_PIN(PA_BASE + 21, "PA21") | ||
48 | #define SUNXI_PINCTRL_PIN_PA22 PINCTRL_PIN(PA_BASE + 22, "PA22") | ||
49 | #define SUNXI_PINCTRL_PIN_PA23 PINCTRL_PIN(PA_BASE + 23, "PA23") | ||
50 | #define SUNXI_PINCTRL_PIN_PA24 PINCTRL_PIN(PA_BASE + 24, "PA24") | ||
51 | #define SUNXI_PINCTRL_PIN_PA25 PINCTRL_PIN(PA_BASE + 25, "PA25") | ||
52 | #define SUNXI_PINCTRL_PIN_PA26 PINCTRL_PIN(PA_BASE + 26, "PA26") | ||
53 | #define SUNXI_PINCTRL_PIN_PA27 PINCTRL_PIN(PA_BASE + 27, "PA27") | ||
54 | #define SUNXI_PINCTRL_PIN_PA28 PINCTRL_PIN(PA_BASE + 28, "PA28") | ||
55 | #define SUNXI_PINCTRL_PIN_PA29 PINCTRL_PIN(PA_BASE + 29, "PA29") | ||
56 | #define SUNXI_PINCTRL_PIN_PA30 PINCTRL_PIN(PA_BASE + 30, "PA30") | ||
57 | #define SUNXI_PINCTRL_PIN_PA31 PINCTRL_PIN(PA_BASE + 31, "PA31") | ||
58 | |||
59 | #define SUNXI_PINCTRL_PIN_PB0 PINCTRL_PIN(PB_BASE + 0, "PB0") | ||
60 | #define SUNXI_PINCTRL_PIN_PB1 PINCTRL_PIN(PB_BASE + 1, "PB1") | ||
61 | #define SUNXI_PINCTRL_PIN_PB2 PINCTRL_PIN(PB_BASE + 2, "PB2") | ||
62 | #define SUNXI_PINCTRL_PIN_PB3 PINCTRL_PIN(PB_BASE + 3, "PB3") | ||
63 | #define SUNXI_PINCTRL_PIN_PB4 PINCTRL_PIN(PB_BASE + 4, "PB4") | ||
64 | #define SUNXI_PINCTRL_PIN_PB5 PINCTRL_PIN(PB_BASE + 5, "PB5") | ||
65 | #define SUNXI_PINCTRL_PIN_PB6 PINCTRL_PIN(PB_BASE + 6, "PB6") | ||
66 | #define SUNXI_PINCTRL_PIN_PB7 PINCTRL_PIN(PB_BASE + 7, "PB7") | ||
67 | #define SUNXI_PINCTRL_PIN_PB8 PINCTRL_PIN(PB_BASE + 8, "PB8") | ||
68 | #define SUNXI_PINCTRL_PIN_PB9 PINCTRL_PIN(PB_BASE + 9, "PB9") | ||
69 | #define SUNXI_PINCTRL_PIN_PB10 PINCTRL_PIN(PB_BASE + 10, "PB10") | ||
70 | #define SUNXI_PINCTRL_PIN_PB11 PINCTRL_PIN(PB_BASE + 11, "PB11") | ||
71 | #define SUNXI_PINCTRL_PIN_PB12 PINCTRL_PIN(PB_BASE + 12, "PB12") | ||
72 | #define SUNXI_PINCTRL_PIN_PB13 PINCTRL_PIN(PB_BASE + 13, "PB13") | ||
73 | #define SUNXI_PINCTRL_PIN_PB14 PINCTRL_PIN(PB_BASE + 14, "PB14") | ||
74 | #define SUNXI_PINCTRL_PIN_PB15 PINCTRL_PIN(PB_BASE + 15, "PB15") | ||
75 | #define SUNXI_PINCTRL_PIN_PB16 PINCTRL_PIN(PB_BASE + 16, "PB16") | ||
76 | #define SUNXI_PINCTRL_PIN_PB17 PINCTRL_PIN(PB_BASE + 17, "PB17") | ||
77 | #define SUNXI_PINCTRL_PIN_PB18 PINCTRL_PIN(PB_BASE + 18, "PB18") | ||
78 | #define SUNXI_PINCTRL_PIN_PB19 PINCTRL_PIN(PB_BASE + 19, "PB19") | ||
79 | #define SUNXI_PINCTRL_PIN_PB20 PINCTRL_PIN(PB_BASE + 20, "PB20") | ||
80 | #define SUNXI_PINCTRL_PIN_PB21 PINCTRL_PIN(PB_BASE + 21, "PB21") | ||
81 | #define SUNXI_PINCTRL_PIN_PB22 PINCTRL_PIN(PB_BASE + 22, "PB22") | ||
82 | #define SUNXI_PINCTRL_PIN_PB23 PINCTRL_PIN(PB_BASE + 23, "PB23") | ||
83 | #define SUNXI_PINCTRL_PIN_PB24 PINCTRL_PIN(PB_BASE + 24, "PB24") | ||
84 | #define SUNXI_PINCTRL_PIN_PB25 PINCTRL_PIN(PB_BASE + 25, "PB25") | ||
85 | #define SUNXI_PINCTRL_PIN_PB26 PINCTRL_PIN(PB_BASE + 26, "PB26") | ||
86 | #define SUNXI_PINCTRL_PIN_PB27 PINCTRL_PIN(PB_BASE + 27, "PB27") | ||
87 | #define SUNXI_PINCTRL_PIN_PB28 PINCTRL_PIN(PB_BASE + 28, "PB28") | ||
88 | #define SUNXI_PINCTRL_PIN_PB29 PINCTRL_PIN(PB_BASE + 29, "PB29") | ||
89 | #define SUNXI_PINCTRL_PIN_PB30 PINCTRL_PIN(PB_BASE + 30, "PB30") | ||
90 | #define SUNXI_PINCTRL_PIN_PB31 PINCTRL_PIN(PB_BASE + 31, "PB31") | ||
91 | |||
92 | #define SUNXI_PINCTRL_PIN_PC0 PINCTRL_PIN(PC_BASE + 0, "PC0") | ||
93 | #define SUNXI_PINCTRL_PIN_PC1 PINCTRL_PIN(PC_BASE + 1, "PC1") | ||
94 | #define SUNXI_PINCTRL_PIN_PC2 PINCTRL_PIN(PC_BASE + 2, "PC2") | ||
95 | #define SUNXI_PINCTRL_PIN_PC3 PINCTRL_PIN(PC_BASE + 3, "PC3") | ||
96 | #define SUNXI_PINCTRL_PIN_PC4 PINCTRL_PIN(PC_BASE + 4, "PC4") | ||
97 | #define SUNXI_PINCTRL_PIN_PC5 PINCTRL_PIN(PC_BASE + 5, "PC5") | ||
98 | #define SUNXI_PINCTRL_PIN_PC6 PINCTRL_PIN(PC_BASE + 6, "PC6") | ||
99 | #define SUNXI_PINCTRL_PIN_PC7 PINCTRL_PIN(PC_BASE + 7, "PC7") | ||
100 | #define SUNXI_PINCTRL_PIN_PC8 PINCTRL_PIN(PC_BASE + 8, "PC8") | ||
101 | #define SUNXI_PINCTRL_PIN_PC9 PINCTRL_PIN(PC_BASE + 9, "PC9") | ||
102 | #define SUNXI_PINCTRL_PIN_PC10 PINCTRL_PIN(PC_BASE + 10, "PC10") | ||
103 | #define SUNXI_PINCTRL_PIN_PC11 PINCTRL_PIN(PC_BASE + 11, "PC11") | ||
104 | #define SUNXI_PINCTRL_PIN_PC12 PINCTRL_PIN(PC_BASE + 12, "PC12") | ||
105 | #define SUNXI_PINCTRL_PIN_PC13 PINCTRL_PIN(PC_BASE + 13, "PC13") | ||
106 | #define SUNXI_PINCTRL_PIN_PC14 PINCTRL_PIN(PC_BASE + 14, "PC14") | ||
107 | #define SUNXI_PINCTRL_PIN_PC15 PINCTRL_PIN(PC_BASE + 15, "PC15") | ||
108 | #define SUNXI_PINCTRL_PIN_PC16 PINCTRL_PIN(PC_BASE + 16, "PC16") | ||
109 | #define SUNXI_PINCTRL_PIN_PC17 PINCTRL_PIN(PC_BASE + 17, "PC17") | ||
110 | #define SUNXI_PINCTRL_PIN_PC18 PINCTRL_PIN(PC_BASE + 18, "PC18") | ||
111 | #define SUNXI_PINCTRL_PIN_PC19 PINCTRL_PIN(PC_BASE + 19, "PC19") | ||
112 | #define SUNXI_PINCTRL_PIN_PC20 PINCTRL_PIN(PC_BASE + 20, "PC20") | ||
113 | #define SUNXI_PINCTRL_PIN_PC21 PINCTRL_PIN(PC_BASE + 21, "PC21") | ||
114 | #define SUNXI_PINCTRL_PIN_PC22 PINCTRL_PIN(PC_BASE + 22, "PC22") | ||
115 | #define SUNXI_PINCTRL_PIN_PC23 PINCTRL_PIN(PC_BASE + 23, "PC23") | ||
116 | #define SUNXI_PINCTRL_PIN_PC24 PINCTRL_PIN(PC_BASE + 24, "PC24") | ||
117 | #define SUNXI_PINCTRL_PIN_PC25 PINCTRL_PIN(PC_BASE + 25, "PC25") | ||
118 | #define SUNXI_PINCTRL_PIN_PC26 PINCTRL_PIN(PC_BASE + 26, "PC26") | ||
119 | #define SUNXI_PINCTRL_PIN_PC27 PINCTRL_PIN(PC_BASE + 27, "PC27") | ||
120 | #define SUNXI_PINCTRL_PIN_PC28 PINCTRL_PIN(PC_BASE + 28, "PC28") | ||
121 | #define SUNXI_PINCTRL_PIN_PC29 PINCTRL_PIN(PC_BASE + 29, "PC29") | ||
122 | #define SUNXI_PINCTRL_PIN_PC30 PINCTRL_PIN(PC_BASE + 30, "PC30") | ||
123 | #define SUNXI_PINCTRL_PIN_PC31 PINCTRL_PIN(PC_BASE + 31, "PC31") | ||
124 | |||
125 | #define SUNXI_PINCTRL_PIN_PD0 PINCTRL_PIN(PD_BASE + 0, "PD0") | ||
126 | #define SUNXI_PINCTRL_PIN_PD1 PINCTRL_PIN(PD_BASE + 1, "PD1") | ||
127 | #define SUNXI_PINCTRL_PIN_PD2 PINCTRL_PIN(PD_BASE + 2, "PD2") | ||
128 | #define SUNXI_PINCTRL_PIN_PD3 PINCTRL_PIN(PD_BASE + 3, "PD3") | ||
129 | #define SUNXI_PINCTRL_PIN_PD4 PINCTRL_PIN(PD_BASE + 4, "PD4") | ||
130 | #define SUNXI_PINCTRL_PIN_PD5 PINCTRL_PIN(PD_BASE + 5, "PD5") | ||
131 | #define SUNXI_PINCTRL_PIN_PD6 PINCTRL_PIN(PD_BASE + 6, "PD6") | ||
132 | #define SUNXI_PINCTRL_PIN_PD7 PINCTRL_PIN(PD_BASE + 7, "PD7") | ||
133 | #define SUNXI_PINCTRL_PIN_PD8 PINCTRL_PIN(PD_BASE + 8, "PD8") | ||
134 | #define SUNXI_PINCTRL_PIN_PD9 PINCTRL_PIN(PD_BASE + 9, "PD9") | ||
135 | #define SUNXI_PINCTRL_PIN_PD10 PINCTRL_PIN(PD_BASE + 10, "PD10") | ||
136 | #define SUNXI_PINCTRL_PIN_PD11 PINCTRL_PIN(PD_BASE + 11, "PD11") | ||
137 | #define SUNXI_PINCTRL_PIN_PD12 PINCTRL_PIN(PD_BASE + 12, "PD12") | ||
138 | #define SUNXI_PINCTRL_PIN_PD13 PINCTRL_PIN(PD_BASE + 13, "PD13") | ||
139 | #define SUNXI_PINCTRL_PIN_PD14 PINCTRL_PIN(PD_BASE + 14, "PD14") | ||
140 | #define SUNXI_PINCTRL_PIN_PD15 PINCTRL_PIN(PD_BASE + 15, "PD15") | ||
141 | #define SUNXI_PINCTRL_PIN_PD16 PINCTRL_PIN(PD_BASE + 16, "PD16") | ||
142 | #define SUNXI_PINCTRL_PIN_PD17 PINCTRL_PIN(PD_BASE + 17, "PD17") | ||
143 | #define SUNXI_PINCTRL_PIN_PD18 PINCTRL_PIN(PD_BASE + 18, "PD18") | ||
144 | #define SUNXI_PINCTRL_PIN_PD19 PINCTRL_PIN(PD_BASE + 19, "PD19") | ||
145 | #define SUNXI_PINCTRL_PIN_PD20 PINCTRL_PIN(PD_BASE + 20, "PD20") | ||
146 | #define SUNXI_PINCTRL_PIN_PD21 PINCTRL_PIN(PD_BASE + 21, "PD21") | ||
147 | #define SUNXI_PINCTRL_PIN_PD22 PINCTRL_PIN(PD_BASE + 22, "PD22") | ||
148 | #define SUNXI_PINCTRL_PIN_PD23 PINCTRL_PIN(PD_BASE + 23, "PD23") | ||
149 | #define SUNXI_PINCTRL_PIN_PD24 PINCTRL_PIN(PD_BASE + 24, "PD24") | ||
150 | #define SUNXI_PINCTRL_PIN_PD25 PINCTRL_PIN(PD_BASE + 25, "PD25") | ||
151 | #define SUNXI_PINCTRL_PIN_PD26 PINCTRL_PIN(PD_BASE + 26, "PD26") | ||
152 | #define SUNXI_PINCTRL_PIN_PD27 PINCTRL_PIN(PD_BASE + 27, "PD27") | ||
153 | #define SUNXI_PINCTRL_PIN_PD28 PINCTRL_PIN(PD_BASE + 28, "PD28") | ||
154 | #define SUNXI_PINCTRL_PIN_PD29 PINCTRL_PIN(PD_BASE + 29, "PD29") | ||
155 | #define SUNXI_PINCTRL_PIN_PD30 PINCTRL_PIN(PD_BASE + 30, "PD30") | ||
156 | #define SUNXI_PINCTRL_PIN_PD31 PINCTRL_PIN(PD_BASE + 31, "PD31") | ||
157 | |||
158 | #define SUNXI_PINCTRL_PIN_PE0 PINCTRL_PIN(PE_BASE + 0, "PE0") | ||
159 | #define SUNXI_PINCTRL_PIN_PE1 PINCTRL_PIN(PE_BASE + 1, "PE1") | ||
160 | #define SUNXI_PINCTRL_PIN_PE2 PINCTRL_PIN(PE_BASE + 2, "PE2") | ||
161 | #define SUNXI_PINCTRL_PIN_PE3 PINCTRL_PIN(PE_BASE + 3, "PE3") | ||
162 | #define SUNXI_PINCTRL_PIN_PE4 PINCTRL_PIN(PE_BASE + 4, "PE4") | ||
163 | #define SUNXI_PINCTRL_PIN_PE5 PINCTRL_PIN(PE_BASE + 5, "PE5") | ||
164 | #define SUNXI_PINCTRL_PIN_PE6 PINCTRL_PIN(PE_BASE + 6, "PE6") | ||
165 | #define SUNXI_PINCTRL_PIN_PE7 PINCTRL_PIN(PE_BASE + 7, "PE7") | ||
166 | #define SUNXI_PINCTRL_PIN_PE8 PINCTRL_PIN(PE_BASE + 8, "PE8") | ||
167 | #define SUNXI_PINCTRL_PIN_PE9 PINCTRL_PIN(PE_BASE + 9, "PE9") | ||
168 | #define SUNXI_PINCTRL_PIN_PE10 PINCTRL_PIN(PE_BASE + 10, "PE10") | ||
169 | #define SUNXI_PINCTRL_PIN_PE11 PINCTRL_PIN(PE_BASE + 11, "PE11") | ||
170 | #define SUNXI_PINCTRL_PIN_PE12 PINCTRL_PIN(PE_BASE + 12, "PE12") | ||
171 | #define SUNXI_PINCTRL_PIN_PE13 PINCTRL_PIN(PE_BASE + 13, "PE13") | ||
172 | #define SUNXI_PINCTRL_PIN_PE14 PINCTRL_PIN(PE_BASE + 14, "PE14") | ||
173 | #define SUNXI_PINCTRL_PIN_PE15 PINCTRL_PIN(PE_BASE + 15, "PE15") | ||
174 | #define SUNXI_PINCTRL_PIN_PE16 PINCTRL_PIN(PE_BASE + 16, "PE16") | ||
175 | #define SUNXI_PINCTRL_PIN_PE17 PINCTRL_PIN(PE_BASE + 17, "PE17") | ||
176 | #define SUNXI_PINCTRL_PIN_PE18 PINCTRL_PIN(PE_BASE + 18, "PE18") | ||
177 | #define SUNXI_PINCTRL_PIN_PE19 PINCTRL_PIN(PE_BASE + 19, "PE19") | ||
178 | #define SUNXI_PINCTRL_PIN_PE20 PINCTRL_PIN(PE_BASE + 20, "PE20") | ||
179 | #define SUNXI_PINCTRL_PIN_PE21 PINCTRL_PIN(PE_BASE + 21, "PE21") | ||
180 | #define SUNXI_PINCTRL_PIN_PE22 PINCTRL_PIN(PE_BASE + 22, "PE22") | ||
181 | #define SUNXI_PINCTRL_PIN_PE23 PINCTRL_PIN(PE_BASE + 23, "PE23") | ||
182 | #define SUNXI_PINCTRL_PIN_PE24 PINCTRL_PIN(PE_BASE + 24, "PE24") | ||
183 | #define SUNXI_PINCTRL_PIN_PE25 PINCTRL_PIN(PE_BASE + 25, "PE25") | ||
184 | #define SUNXI_PINCTRL_PIN_PE26 PINCTRL_PIN(PE_BASE + 26, "PE26") | ||
185 | #define SUNXI_PINCTRL_PIN_PE27 PINCTRL_PIN(PE_BASE + 27, "PE27") | ||
186 | #define SUNXI_PINCTRL_PIN_PE28 PINCTRL_PIN(PE_BASE + 28, "PE28") | ||
187 | #define SUNXI_PINCTRL_PIN_PE29 PINCTRL_PIN(PE_BASE + 29, "PE29") | ||
188 | #define SUNXI_PINCTRL_PIN_PE30 PINCTRL_PIN(PE_BASE + 30, "PE30") | ||
189 | #define SUNXI_PINCTRL_PIN_PE31 PINCTRL_PIN(PE_BASE + 31, "PE31") | ||
190 | |||
191 | #define SUNXI_PINCTRL_PIN_PF0 PINCTRL_PIN(PF_BASE + 0, "PF0") | ||
192 | #define SUNXI_PINCTRL_PIN_PF1 PINCTRL_PIN(PF_BASE + 1, "PF1") | ||
193 | #define SUNXI_PINCTRL_PIN_PF2 PINCTRL_PIN(PF_BASE + 2, "PF2") | ||
194 | #define SUNXI_PINCTRL_PIN_PF3 PINCTRL_PIN(PF_BASE + 3, "PF3") | ||
195 | #define SUNXI_PINCTRL_PIN_PF4 PINCTRL_PIN(PF_BASE + 4, "PF4") | ||
196 | #define SUNXI_PINCTRL_PIN_PF5 PINCTRL_PIN(PF_BASE + 5, "PF5") | ||
197 | #define SUNXI_PINCTRL_PIN_PF6 PINCTRL_PIN(PF_BASE + 6, "PF6") | ||
198 | #define SUNXI_PINCTRL_PIN_PF7 PINCTRL_PIN(PF_BASE + 7, "PF7") | ||
199 | #define SUNXI_PINCTRL_PIN_PF8 PINCTRL_PIN(PF_BASE + 8, "PF8") | ||
200 | #define SUNXI_PINCTRL_PIN_PF9 PINCTRL_PIN(PF_BASE + 9, "PF9") | ||
201 | #define SUNXI_PINCTRL_PIN_PF10 PINCTRL_PIN(PF_BASE + 10, "PF10") | ||
202 | #define SUNXI_PINCTRL_PIN_PF11 PINCTRL_PIN(PF_BASE + 11, "PF11") | ||
203 | #define SUNXI_PINCTRL_PIN_PF12 PINCTRL_PIN(PF_BASE + 12, "PF12") | ||
204 | #define SUNXI_PINCTRL_PIN_PF13 PINCTRL_PIN(PF_BASE + 13, "PF13") | ||
205 | #define SUNXI_PINCTRL_PIN_PF14 PINCTRL_PIN(PF_BASE + 14, "PF14") | ||
206 | #define SUNXI_PINCTRL_PIN_PF15 PINCTRL_PIN(PF_BASE + 15, "PF15") | ||
207 | #define SUNXI_PINCTRL_PIN_PF16 PINCTRL_PIN(PF_BASE + 16, "PF16") | ||
208 | #define SUNXI_PINCTRL_PIN_PF17 PINCTRL_PIN(PF_BASE + 17, "PF17") | ||
209 | #define SUNXI_PINCTRL_PIN_PF18 PINCTRL_PIN(PF_BASE + 18, "PF18") | ||
210 | #define SUNXI_PINCTRL_PIN_PF19 PINCTRL_PIN(PF_BASE + 19, "PF19") | ||
211 | #define SUNXI_PINCTRL_PIN_PF20 PINCTRL_PIN(PF_BASE + 20, "PF20") | ||
212 | #define SUNXI_PINCTRL_PIN_PF21 PINCTRL_PIN(PF_BASE + 21, "PF21") | ||
213 | #define SUNXI_PINCTRL_PIN_PF22 PINCTRL_PIN(PF_BASE + 22, "PF22") | ||
214 | #define SUNXI_PINCTRL_PIN_PF23 PINCTRL_PIN(PF_BASE + 23, "PF23") | ||
215 | #define SUNXI_PINCTRL_PIN_PF24 PINCTRL_PIN(PF_BASE + 24, "PF24") | ||
216 | #define SUNXI_PINCTRL_PIN_PF25 PINCTRL_PIN(PF_BASE + 25, "PF25") | ||
217 | #define SUNXI_PINCTRL_PIN_PF26 PINCTRL_PIN(PF_BASE + 26, "PF26") | ||
218 | #define SUNXI_PINCTRL_PIN_PF27 PINCTRL_PIN(PF_BASE + 27, "PF27") | ||
219 | #define SUNXI_PINCTRL_PIN_PF28 PINCTRL_PIN(PF_BASE + 28, "PF28") | ||
220 | #define SUNXI_PINCTRL_PIN_PF29 PINCTRL_PIN(PF_BASE + 29, "PF29") | ||
221 | #define SUNXI_PINCTRL_PIN_PF30 PINCTRL_PIN(PF_BASE + 30, "PF30") | ||
222 | #define SUNXI_PINCTRL_PIN_PF31 PINCTRL_PIN(PF_BASE + 31, "PF31") | ||
223 | |||
224 | #define SUNXI_PINCTRL_PIN_PG0 PINCTRL_PIN(PG_BASE + 0, "PG0") | ||
225 | #define SUNXI_PINCTRL_PIN_PG1 PINCTRL_PIN(PG_BASE + 1, "PG1") | ||
226 | #define SUNXI_PINCTRL_PIN_PG2 PINCTRL_PIN(PG_BASE + 2, "PG2") | ||
227 | #define SUNXI_PINCTRL_PIN_PG3 PINCTRL_PIN(PG_BASE + 3, "PG3") | ||
228 | #define SUNXI_PINCTRL_PIN_PG4 PINCTRL_PIN(PG_BASE + 4, "PG4") | ||
229 | #define SUNXI_PINCTRL_PIN_PG5 PINCTRL_PIN(PG_BASE + 5, "PG5") | ||
230 | #define SUNXI_PINCTRL_PIN_PG6 PINCTRL_PIN(PG_BASE + 6, "PG6") | ||
231 | #define SUNXI_PINCTRL_PIN_PG7 PINCTRL_PIN(PG_BASE + 7, "PG7") | ||
232 | #define SUNXI_PINCTRL_PIN_PG8 PINCTRL_PIN(PG_BASE + 8, "PG8") | ||
233 | #define SUNXI_PINCTRL_PIN_PG9 PINCTRL_PIN(PG_BASE + 9, "PG9") | ||
234 | #define SUNXI_PINCTRL_PIN_PG10 PINCTRL_PIN(PG_BASE + 10, "PG10") | ||
235 | #define SUNXI_PINCTRL_PIN_PG11 PINCTRL_PIN(PG_BASE + 11, "PG11") | ||
236 | #define SUNXI_PINCTRL_PIN_PG12 PINCTRL_PIN(PG_BASE + 12, "PG12") | ||
237 | #define SUNXI_PINCTRL_PIN_PG13 PINCTRL_PIN(PG_BASE + 13, "PG13") | ||
238 | #define SUNXI_PINCTRL_PIN_PG14 PINCTRL_PIN(PG_BASE + 14, "PG14") | ||
239 | #define SUNXI_PINCTRL_PIN_PG15 PINCTRL_PIN(PG_BASE + 15, "PG15") | ||
240 | #define SUNXI_PINCTRL_PIN_PG16 PINCTRL_PIN(PG_BASE + 16, "PG16") | ||
241 | #define SUNXI_PINCTRL_PIN_PG17 PINCTRL_PIN(PG_BASE + 17, "PG17") | ||
242 | #define SUNXI_PINCTRL_PIN_PG18 PINCTRL_PIN(PG_BASE + 18, "PG18") | ||
243 | #define SUNXI_PINCTRL_PIN_PG19 PINCTRL_PIN(PG_BASE + 19, "PG19") | ||
244 | #define SUNXI_PINCTRL_PIN_PG20 PINCTRL_PIN(PG_BASE + 20, "PG20") | ||
245 | #define SUNXI_PINCTRL_PIN_PG21 PINCTRL_PIN(PG_BASE + 21, "PG21") | ||
246 | #define SUNXI_PINCTRL_PIN_PG22 PINCTRL_PIN(PG_BASE + 22, "PG22") | ||
247 | #define SUNXI_PINCTRL_PIN_PG23 PINCTRL_PIN(PG_BASE + 23, "PG23") | ||
248 | #define SUNXI_PINCTRL_PIN_PG24 PINCTRL_PIN(PG_BASE + 24, "PG24") | ||
249 | #define SUNXI_PINCTRL_PIN_PG25 PINCTRL_PIN(PG_BASE + 25, "PG25") | ||
250 | #define SUNXI_PINCTRL_PIN_PG26 PINCTRL_PIN(PG_BASE + 26, "PG26") | ||
251 | #define SUNXI_PINCTRL_PIN_PG27 PINCTRL_PIN(PG_BASE + 27, "PG27") | ||
252 | #define SUNXI_PINCTRL_PIN_PG28 PINCTRL_PIN(PG_BASE + 28, "PG28") | ||
253 | #define SUNXI_PINCTRL_PIN_PG29 PINCTRL_PIN(PG_BASE + 29, "PG29") | ||
254 | #define SUNXI_PINCTRL_PIN_PG30 PINCTRL_PIN(PG_BASE + 30, "PG30") | ||
255 | #define SUNXI_PINCTRL_PIN_PG31 PINCTRL_PIN(PG_BASE + 31, "PG31") | ||
256 | |||
257 | #define BANK_MEM_SIZE 0x24 | ||
258 | #define MUX_REGS_OFFSET 0x0 | ||
259 | #define DLEVEL_REGS_OFFSET 0x14 | ||
260 | #define PULL_REGS_OFFSET 0x1c | ||
261 | |||
262 | #define PINS_PER_BANK 32 | ||
263 | #define MUX_PINS_PER_REG 8 | ||
264 | #define MUX_PINS_BITS 4 | ||
265 | #define MUX_PINS_MASK 0x0f | ||
266 | #define DLEVEL_PINS_PER_REG 16 | ||
267 | #define DLEVEL_PINS_BITS 2 | ||
268 | #define DLEVEL_PINS_MASK 0x03 | ||
269 | #define PULL_PINS_PER_REG 16 | ||
270 | #define PULL_PINS_BITS 2 | ||
271 | #define PULL_PINS_MASK 0x03 | ||
272 | |||
273 | struct sunxi_desc_function { | ||
274 | const char *name; | ||
275 | u8 muxval; | ||
276 | }; | ||
277 | |||
278 | struct sunxi_desc_pin { | ||
279 | struct pinctrl_pin_desc pin; | ||
280 | struct sunxi_desc_function *functions; | ||
281 | }; | ||
282 | |||
283 | struct sunxi_pinctrl_desc { | ||
284 | const struct sunxi_desc_pin *pins; | ||
285 | int npins; | ||
286 | }; | ||
287 | |||
288 | struct sunxi_pinctrl_function { | ||
289 | const char *name; | ||
290 | const char **groups; | ||
291 | unsigned ngroups; | ||
292 | }; | ||
293 | |||
294 | struct sunxi_pinctrl_group { | ||
295 | const char *name; | ||
296 | unsigned long config; | ||
297 | unsigned pin; | ||
298 | }; | ||
299 | |||
300 | struct sunxi_pinctrl { | ||
301 | void __iomem *membase; | ||
302 | struct sunxi_pinctrl_desc *desc; | ||
303 | struct device *dev; | ||
304 | struct sunxi_pinctrl_function *functions; | ||
305 | unsigned nfunctions; | ||
306 | struct sunxi_pinctrl_group *groups; | ||
307 | unsigned ngroups; | ||
308 | struct pinctrl_dev *pctl_dev; | ||
309 | }; | ||
310 | |||
311 | #define SUNXI_PIN(_pin, ...) \ | ||
312 | { \ | ||
313 | .pin = _pin, \ | ||
314 | .functions = (struct sunxi_desc_function[]){ \ | ||
315 | __VA_ARGS__, { } }, \ | ||
316 | } | ||
317 | |||
318 | #define SUNXI_FUNCTION(_val, _name) \ | ||
319 | { \ | ||
320 | .name = _name, \ | ||
321 | .muxval = _val, \ | ||
322 | } | ||
323 | |||
324 | |||
325 | /* | ||
326 | * The sunXi PIO registers are organized as is: | ||
327 | * 0x00 - 0x0c Muxing values. | ||
328 | * 8 pins per register, each pin having a 4bits value | ||
329 | * 0x10 Pin values | ||
330 | * 32 bits per register, each pin corresponding to one bit | ||
331 | * 0x14 - 0x18 Drive level | ||
332 | * 16 pins per register, each pin having a 2bits value | ||
333 | * 0x1c - 0x20 Pull-Up values | ||
334 | * 16 pins per register, each pin having a 2bits value | ||
335 | * | ||
336 | * This is for the first bank. Each bank will have the same layout, | ||
337 | * with an offset being a multiple of 0x24. | ||
338 | * | ||
339 | * The following functions calculate from the pin number the register | ||
340 | * and the bit offset that we should access. | ||
341 | */ | ||
342 | static inline u32 sunxi_mux_reg(u16 pin) | ||
343 | { | ||
344 | u8 bank = pin / PINS_PER_BANK; | ||
345 | u32 offset = bank * BANK_MEM_SIZE; | ||
346 | offset += MUX_REGS_OFFSET; | ||
347 | offset += pin % PINS_PER_BANK / MUX_PINS_PER_REG * 0x04; | ||
348 | return round_down(offset, 4); | ||
349 | } | ||
350 | |||
351 | static inline u32 sunxi_mux_offset(u16 pin) | ||
352 | { | ||
353 | u32 pin_num = pin % MUX_PINS_PER_REG; | ||
354 | return pin_num * MUX_PINS_BITS; | ||
355 | } | ||
356 | |||
357 | static inline u32 sunxi_dlevel_reg(u16 pin) | ||
358 | { | ||
359 | u8 bank = pin / PINS_PER_BANK; | ||
360 | u32 offset = bank * BANK_MEM_SIZE; | ||
361 | offset += DLEVEL_REGS_OFFSET; | ||
362 | offset += pin % PINS_PER_BANK / DLEVEL_PINS_PER_REG * 0x04; | ||
363 | return round_down(offset, 4); | ||
364 | } | ||
365 | |||
366 | static inline u32 sunxi_dlevel_offset(u16 pin) | ||
367 | { | ||
368 | u32 pin_num = pin % DLEVEL_PINS_PER_REG; | ||
369 | return pin_num * DLEVEL_PINS_BITS; | ||
370 | } | ||
371 | |||
372 | static inline u32 sunxi_pull_reg(u16 pin) | ||
373 | { | ||
374 | u8 bank = pin / PINS_PER_BANK; | ||
375 | u32 offset = bank * BANK_MEM_SIZE; | ||
376 | offset += PULL_REGS_OFFSET; | ||
377 | offset += pin % PINS_PER_BANK / PULL_PINS_PER_REG * 0x04; | ||
378 | return round_down(offset, 4); | ||
379 | } | ||
380 | |||
381 | static inline u32 sunxi_pull_offset(u16 pin) | ||
382 | { | ||
383 | u32 pin_num = pin % PULL_PINS_PER_REG; | ||
384 | return pin_num * PULL_PINS_BITS; | ||
385 | } | ||
386 | |||
387 | #endif /* __PINCTRL_SUNXI_H */ | ||