1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Atmel PIO4 pinctrl driver
4  *
5  * Copyright (C) 2016 Atmel Corporation
6  *               Wenyou.Yang <wenyou.yang@atmel.com>
7  */
8 
9 #include <common.h>
10 #include <dm.h>
11 #include <asm/global_data.h>
12 #include <dm/pinctrl.h>
13 #include <linux/bitops.h>
14 #include <linux/io.h>
15 #include <linux/err.h>
16 #include <mach/atmel_pio4.h>
17 
18 DECLARE_GLOBAL_DATA_PTR;
19 
20 /*
21  * Warning:
22  * In order to not introduce confusion between Atmel PIO groups and pinctrl
23  * framework groups, Atmel PIO groups will be called banks.
24  */
25 
26 struct atmel_pio4_plat {
27 	struct atmel_pio4_port *reg_base;
28 };
29 
30 static const struct pinconf_param conf_params[] = {
31 	{ "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
32 	{ "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
33 	{ "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
34 	{ "drive-open-drain", PIN_CONFIG_DRIVE_OPEN_DRAIN, 0 },
35 	{ "input-schmitt-disable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 0 },
36 	{ "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 },
37 	{ "input-debounce", PIN_CONFIG_INPUT_DEBOUNCE, 0 },
38 	{ "atmel,drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 },
39 };
40 
atmel_pinctrl_get_pinconf(struct udevice * config)41 static u32 atmel_pinctrl_get_pinconf(struct udevice *config)
42 {
43 	const struct pinconf_param *params;
44 	u32 param, arg, conf = 0;
45 	u32 i;
46 	u32 val;
47 
48 	for (i = 0; i < ARRAY_SIZE(conf_params); i++) {
49 		params = &conf_params[i];
50 		if (!dev_read_prop(config, params->property, NULL))
51 			continue;
52 
53 		param = params->param;
54 		arg = params->default_value;
55 
56 		switch (param) {
57 		case PIN_CONFIG_BIAS_DISABLE:
58 			conf &= (~ATMEL_PIO_PUEN_MASK);
59 			conf &= (~ATMEL_PIO_PDEN_MASK);
60 			break;
61 		case PIN_CONFIG_BIAS_PULL_UP:
62 			conf |= ATMEL_PIO_PUEN_MASK;
63 			break;
64 		case PIN_CONFIG_BIAS_PULL_DOWN:
65 			conf |= ATMEL_PIO_PDEN_MASK;
66 			break;
67 		case PIN_CONFIG_DRIVE_OPEN_DRAIN:
68 			if (arg == 0)
69 				conf &= (~ATMEL_PIO_OPD_MASK);
70 			else
71 				conf |= ATMEL_PIO_OPD_MASK;
72 			break;
73 		case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
74 			if (arg == 0)
75 				conf |= ATMEL_PIO_SCHMITT_MASK;
76 			else
77 				conf &= (~ATMEL_PIO_SCHMITT_MASK);
78 			break;
79 		case PIN_CONFIG_INPUT_DEBOUNCE:
80 			if (arg == 0) {
81 				conf &= (~ATMEL_PIO_IFEN_MASK);
82 				conf &= (~ATMEL_PIO_IFSCEN_MASK);
83 			} else {
84 				conf |= ATMEL_PIO_IFEN_MASK;
85 				conf |= ATMEL_PIO_IFSCEN_MASK;
86 			}
87 			break;
88 		case PIN_CONFIG_DRIVE_STRENGTH:
89 			dev_read_u32(config, params->property, &val);
90 			conf &= (~ATMEL_PIO_DRVSTR_MASK);
91 			conf |= (val << ATMEL_PIO_DRVSTR_OFFSET)
92 				& ATMEL_PIO_DRVSTR_MASK;
93 			break;
94 		default:
95 			printf("%s: Unsupported configuration parameter: %u\n",
96 			       __func__, param);
97 			break;
98 		}
99 	}
100 
101 	return conf;
102 }
103 
atmel_pio4_bank_base(struct udevice * dev,u32 bank)104 static inline struct atmel_pio4_port *atmel_pio4_bank_base(struct udevice *dev,
105 							   u32 bank)
106 {
107 	struct atmel_pio4_plat *plat = dev_get_plat(dev);
108 	struct atmel_pio4_port *bank_base =
109 			(struct atmel_pio4_port *)((u32)plat->reg_base +
110 			ATMEL_PIO_BANK_OFFSET * bank);
111 
112 	return bank_base;
113 }
114 
115 #define MAX_PINMUX_ENTRIES	40
116 
atmel_pinctrl_set_state(struct udevice * dev,struct udevice * config)117 static int atmel_pinctrl_set_state(struct udevice *dev, struct udevice *config)
118 {
119 	struct atmel_pio4_port *bank_base;
120 	const void *blob = gd->fdt_blob;
121 	int node = dev_of_offset(config);
122 	u32 offset, func, bank, line;
123 	u32 cells[MAX_PINMUX_ENTRIES];
124 	u32 i, conf;
125 	int count;
126 
127 	conf = atmel_pinctrl_get_pinconf(config);
128 
129 	count = fdtdec_get_int_array_count(blob, node, "pinmux",
130 					   cells, ARRAY_SIZE(cells));
131 	if (count < 0) {
132 		printf("%s: bad pinmux array %d\n", __func__, count);
133 		return -EINVAL;
134 	}
135 
136 	if (count > MAX_PINMUX_ENTRIES) {
137 		printf("%s: unsupported pinmux array count %d\n",
138 		       __func__, count);
139 		return -EINVAL;
140 	}
141 
142 	for (i = 0 ; i < count; i++) {
143 		offset = ATMEL_GET_PIN_NO(cells[i]);
144 		func = ATMEL_GET_PIN_FUNC(cells[i]);
145 
146 		bank = ATMEL_PIO_BANK(offset);
147 		line = ATMEL_PIO_LINE(offset);
148 
149 		bank_base = atmel_pio4_bank_base(dev, bank);
150 
151 		writel(BIT(line), &bank_base->mskr);
152 		conf &= (~ATMEL_PIO_CFGR_FUNC_MASK);
153 		conf |= (func & ATMEL_PIO_CFGR_FUNC_MASK);
154 		writel(conf, &bank_base->cfgr);
155 	}
156 
157 	return 0;
158 }
159 
160 const struct pinctrl_ops atmel_pinctrl_ops  = {
161 	.set_state = atmel_pinctrl_set_state,
162 };
163 
atmel_pinctrl_probe(struct udevice * dev)164 static int atmel_pinctrl_probe(struct udevice *dev)
165 {
166 	struct atmel_pio4_plat *plat = dev_get_plat(dev);
167 	fdt_addr_t addr_base;
168 
169 	dev = dev_get_parent(dev);
170 	addr_base = dev_read_addr(dev);
171 	if (addr_base == FDT_ADDR_T_NONE)
172 		return -EINVAL;
173 
174 	plat->reg_base = (struct atmel_pio4_port *)addr_base;
175 
176 	return 0;
177 }
178 
179 static const struct udevice_id atmel_pinctrl_match[] = {
180 	{ .compatible = "atmel,sama5d2-pinctrl" },
181 	{ .compatible = "microchip,sama7g5-pinctrl" },
182 	{}
183 };
184 
185 U_BOOT_DRIVER(atmel_pinctrl) = {
186 	.name = "pinctrl_atmel_pio4",
187 	.id = UCLASS_PINCTRL,
188 	.of_match = atmel_pinctrl_match,
189 	.probe = atmel_pinctrl_probe,
190 	.plat_auto	= sizeof(struct atmel_pio4_plat),
191 	.ops = &atmel_pinctrl_ops,
192 };
193