1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  *  Copyright (C) 2016-2017 Intel Corporation <www.intel.com>
4  */
5 
6 #include <asm/arch/pinmux.h>
7 #include <asm/io.h>
8 #include <common.h>
9 #include <fdtdec.h>
10 
11 static int do_pinctr_pin(const void *blob, int child, const char *node_name)
12 {
13 	int len;
14 	fdt_addr_t base_addr;
15 	fdt_size_t size;
16 	const u32 *cell;
17 	u32 offset, value;
18 
19 	base_addr = fdtdec_get_addr_size(blob, child, "reg", &size);
20 	if (base_addr != FDT_ADDR_T_NONE) {
21 		cell = fdt_getprop(blob, child, "pinctrl-single,pins", &len);
22 		if (!cell || len <= 0)
23 			return -EFAULT;
24 
25 		debug("%p %d\n", cell, len);
26 		for (; len > 0; len -= (2 * sizeof(u32))) {
27 			offset = fdt32_to_cpu(*cell++);
28 			value = fdt32_to_cpu(*cell++);
29 			debug("<0x%x 0x%x>\n", offset, value);
30 			writel(value, base_addr + offset);
31 		}
32 		return 0;
33 	}
34 	return -EFAULT;
35 }
36 
37 static int do_pinctrl_pins(const void *blob, int node, const char *child_name)
38 {
39 	int child, len;
40 	const char *node_name;
41 
42 	child = fdt_first_subnode(blob, node);
43 
44 	if (child < 0)
45 		return -EINVAL;
46 
47 	node_name = fdt_get_name(blob, child, &len);
48 
49 	while (node_name) {
50 		if (!strcmp(child_name, node_name))
51 			return do_pinctr_pin(blob, child, node_name);
52 
53 		child = fdt_next_subnode(blob, child);
54 
55 		if (child < 0)
56 			break;
57 
58 		node_name = fdt_get_name(blob, child, &len);
59 	}
60 
61 	return -EFAULT;
62 }
63 
64 int config_dedicated_pins(const void *blob)
65 {
66 	int node;
67 
68 	node = fdtdec_next_compatible(blob, 0,
69 			COMPAT_ALTERA_SOCFPGA_PINCTRL_SINGLE);
70 	if (node < 0)
71 		return -EINVAL;
72 
73 	if (do_pinctrl_pins(blob, node, "dedicated_cfg"))
74 		return -EFAULT;
75 
76 	if (do_pinctrl_pins(blob, node, "dedicated"))
77 		return -EFAULT;
78 
79 	return 0;
80 }
81 
82 int config_pins(const void *blob, const char *pin_grp)
83 {
84 	int node;
85 
86 	node = fdtdec_next_compatible(blob, 0,
87 			COMPAT_ALTERA_SOCFPGA_PINCTRL_SINGLE);
88 	if (node < 0)
89 		return -EINVAL;
90 
91 	if (do_pinctrl_pins(blob, node, pin_grp))
92 		return -EFAULT;
93 
94 	return 0;
95 }
96