]> Git Repo - J-u-boot.git/blame - drivers/pinctrl/pinctrl-sti.c
Revert "Merge patch series "arm: dts: am62-beagleplay: Fix Beagleplay Ethernet""
[J-u-boot.git] / drivers / pinctrl / pinctrl-sti.c
CommitLineData
83d290c5 1// SPDX-License-Identifier: GPL-2.0+
0c563102
PC
2/*
3 * Pinctrl driver for STMicroelectronics STi SoCs
4 *
fb48bc44 5 * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
0f8106f8 6 * Author(s): Patrice Chotard, <[email protected]> for STMicroelectronics.
0c563102
PC
7 */
8
d678a59d 9#include <common.h>
0c563102
PC
10#include <bitfield.h>
11#include <dm.h>
12#include <errno.h>
13#include <regmap.h>
14#include <syscon.h>
401d1c4f 15#include <asm/global_data.h>
0c563102
PC
16#include <asm/io.h>
17#include <dm/pinctrl.h>
eb41d8a1 18#include <linux/bug.h>
4d72caa5 19#include <linux/libfdt.h>
1e94b46f 20#include <linux/printk.h>
0c563102
PC
21
22DECLARE_GLOBAL_DATA_PTR;
23
24#define MAX_STI_PINCONF_ENTRIES 7
25/* Output enable */
26#define OE (1 << 27)
27/* Pull Up */
28#define PU (1 << 26)
29/* Open Drain */
30#define OD (1 << 25)
31
32/* User-frendly defines for Pin Direction */
33 /* oe = 0, pu = 0, od = 0 */
34#define IN (0)
35 /* oe = 0, pu = 1, od = 0 */
36#define IN_PU (PU)
37 /* oe = 1, pu = 0, od = 0 */
38#define OUT (OE)
39 /* oe = 1, pu = 1, od = 0 */
40#define OUT_PU (OE | PU)
41 /* oe = 1, pu = 0, od = 1 */
42#define BIDIR (OE | OD)
43 /* oe = 1, pu = 1, od = 1 */
44#define BIDIR_PU (OE | PU | OD)
45
8a8d24bd 46struct sti_pinctrl_plat {
0c563102
PC
47 struct regmap *regmap;
48};
49
50struct sti_pin_desc {
51 unsigned char bank;
52 unsigned char pin;
53 unsigned char alt;
54 int dir;
55};
56
57/*
58 * PIO alternative Function selector
59 */
60void sti_alternate_select(struct udevice *dev, struct sti_pin_desc *pin_desc)
61{
8a8d24bd 62 struct sti_pinctrl_plat *plat = dev_get_plat(dev);
0c563102
PC
63 unsigned long sysconf, *sysconfreg;
64 int alt = pin_desc->alt;
65 int bank = pin_desc->bank;
66 int pin = pin_desc->pin;
67
8c1de5e0 68 sysconfreg = (unsigned long *)plat->regmap->ranges[0].start;
0c563102
PC
69
70 switch (bank) {
71 case 0 ... 5: /* in "SBC Bank" */
72 sysconfreg += bank;
73 break;
74 case 10 ... 20: /* in "FRONT Bank" */
75 sysconfreg += bank - 10;
76 break;
77 case 30 ... 35: /* in "REAR Bank" */
78 sysconfreg += bank - 30;
79 break;
80 case 40 ... 42: /* in "FLASH Bank" */
81 sysconfreg += bank - 40;
82 break;
83 default:
84 BUG();
85 return;
86 }
87
88 sysconf = readl(sysconfreg);
89 sysconf = bitfield_replace(sysconf, pin * 4, 3, alt);
90 writel(sysconf, sysconfreg);
91}
92
93/* pin configuration */
94void sti_pin_configure(struct udevice *dev, struct sti_pin_desc *pin_desc)
95{
8a8d24bd 96 struct sti_pinctrl_plat *plat = dev_get_plat(dev);
0c563102
PC
97 int bit;
98 int oe = 0, pu = 0, od = 0;
99 unsigned long *sysconfreg;
100 int bank = pin_desc->bank;
101
8c1de5e0 102 sysconfreg = (unsigned long *)plat->regmap->ranges[0].start + 40;
0c563102
PC
103
104 /*
105 * NOTE: The PIO configuration for the PIO pins in the
106 * "FLASH Bank" are different from all the other banks!
107 * Specifically, the output-enable pin control register
108 * (SYS_CFG_3040) and the pull-up pin control register
109 * (SYS_CFG_3050), are both classed as being "reserved".
110 * Hence, we do not write to these registers to configure
111 * the OE and PU features for PIOs in this bank. However,
112 * the open-drain pin control register (SYS_CFG_3060)
113 * follows the style of the other banks, and so we can
114 * treat that register normally.
115 *
116 * Being pedantic, we should configure the PU and PD features
117 * in the "FLASH Bank" explicitly instead using the four
118 * SYS_CFG registers: 3080, 3081, 3085, and 3086. However, this
119 * would necessitate passing in the alternate function number
120 * to this function, and adding some horrible complexity here.
121 * Alternatively, we could just perform 4 32-bit "pokes" to
122 * these four SYS_CFG registers early in the initialization.
123 * In practice, these four SYS_CFG registers are correct
124 * after a reset, and U-Boot does not need to change them, so
125 * we (cheat and) rely on these registers being correct.
126 * WARNING: Please be aware of this (pragmatic) behaviour!
127 */
128 int flashss = 0; /* bool: PIO in the Flash Sub-System ? */
129
130 switch (pin_desc->dir) {
131 case IN:
132 oe = 0; pu = 0; od = 0;
133 break;
134 case IN_PU:
135 oe = 0; pu = 1; od = 0;
136 break;
137 case OUT:
138 oe = 1; pu = 0; od = 0;
139 break;
140 case BIDIR:
141 oe = 1; pu = 0; od = 1;
142 break;
143 case BIDIR_PU:
144 oe = 1; pu = 1; od = 1;
145 break;
146
147 default:
9b643e31 148 pr_err("%s invalid direction value: 0x%x\n",
0c563102
PC
149 __func__, pin_desc->dir);
150 BUG();
151 break;
152 }
153
154 switch (bank) {
155 case 0 ... 5: /* in "SBC Bank" */
156 sysconfreg += bank / 4;
157 break;
158 case 10 ... 20: /* in "FRONT Bank" */
159 bank -= 10;
160 sysconfreg += bank / 4;
161 break;
162 case 30 ... 35: /* in "REAR Bank" */
163 bank -= 30;
164 sysconfreg += bank / 4;
165 break;
166 case 40 ... 42: /* in "FLASH Bank" */
167 bank -= 40;
168 sysconfreg += bank / 4;
169 flashss = 1; /* pin is in the Flash Sub-System */
170 break;
171 default:
172 BUG();
173 return;
174 }
175
176 bit = ((bank * 8) + pin_desc->pin) % 32;
177
178 /*
179 * set the "Output Enable" pin control
180 * but, do nothing if in the flashSS
181 */
182 if (!flashss) {
183 if (oe)
184 generic_set_bit(bit, sysconfreg);
185 else
186 generic_clear_bit(bit, sysconfreg);
187 }
188
189 sysconfreg += 10; /* skip to next set of syscfg registers */
190
191 /*
192 * set the "Pull Up" pin control
193 * but, do nothing if in the FlashSS
194 */
195
196 if (!flashss) {
197 if (pu)
198 generic_set_bit(bit, sysconfreg);
199 else
200 generic_clear_bit(bit, sysconfreg);
201 }
202
203 sysconfreg += 10; /* skip to next set of syscfg registers */
204
205 /* set the "Open Drain Enable" pin control */
206 if (od)
207 generic_set_bit(bit, sysconfreg);
208 else
209 generic_clear_bit(bit, sysconfreg);
210}
211
212
213static int sti_pinctrl_set_state(struct udevice *dev, struct udevice *config)
214{
215 struct fdtdec_phandle_args args;
216 const void *blob = gd->fdt_blob;
217 const char *prop_name;
218 int node = dev_of_offset(config);
219 int property_offset, prop_len;
220 int pinconf_node, ret, count;
221 const char *bank_name;
222 u32 cells[MAX_STI_PINCONF_ENTRIES];
223
224 struct sti_pin_desc pin_desc;
225
226 /* go to next node "st,pins" which contains the pins configuration */
227 pinconf_node = fdt_subnode_offset(blob, node, "st,pins");
228
229 /*
230 * parse each pins configuration which looks like :
231 * pin_name = <bank_phandle pin_nb alt dir rt_type rt_delay rt_clk>
232 */
233
234 fdt_for_each_property_offset(property_offset, blob, pinconf_node) {
235 fdt_getprop_by_offset(blob, property_offset, &prop_name,
236 &prop_len);
237
238 /* extract the bank of the pin description */
239 ret = fdtdec_parse_phandle_with_args(blob, pinconf_node,
240 prop_name, "#gpio-cells",
241 0, 0, &args);
242 if (ret < 0) {
9b643e31 243 pr_err("Can't get the gpio bank phandle: %d\n", ret);
0c563102
PC
244 return ret;
245 }
246
247 bank_name = fdt_getprop(blob, args.node, "st,bank-name",
248 &count);
249 if (count < 0) {
9b643e31 250 pr_err("Can't find bank-name property %d\n", count);
0c563102
PC
251 return -EINVAL;
252 }
253
254 pin_desc.bank = trailing_strtoln(bank_name, NULL);
255
256 count = fdtdec_get_int_array_count(blob, pinconf_node,
257 prop_name, cells,
258 ARRAY_SIZE(cells));
259 if (count < 0) {
9b643e31 260 pr_err("Bad pin configuration array %d\n", count);
0c563102
PC
261 return -EINVAL;
262 }
263
264 if (count > MAX_STI_PINCONF_ENTRIES) {
9b643e31 265 pr_err("Unsupported pinconf array count %d\n", count);
0c563102
PC
266 return -EINVAL;
267 }
268
269 pin_desc.pin = cells[1];
270 pin_desc.alt = cells[2];
271 pin_desc.dir = cells[3];
272
273 sti_alternate_select(dev, &pin_desc);
274 sti_pin_configure(dev, &pin_desc);
275 };
276
277 return 0;
278}
279
280static int sti_pinctrl_probe(struct udevice *dev)
281{
8a8d24bd 282 struct sti_pinctrl_plat *plat = dev_get_plat(dev);
0c563102
PC
283 struct udevice *syscon;
284 int err;
285
286 /* get corresponding syscon phandle */
287 err = uclass_get_device_by_phandle(UCLASS_SYSCON, dev,
288 "st,syscfg", &syscon);
289 if (err) {
9b643e31 290 pr_err("unable to find syscon device\n");
0c563102
PC
291 return err;
292 }
293
294 plat->regmap = syscon_get_regmap(syscon);
295 if (!plat->regmap) {
9b643e31 296 pr_err("unable to find regmap\n");
0c563102
PC
297 return -ENODEV;
298 }
299
300 return 0;
301}
302
303static const struct udevice_id sti_pinctrl_ids[] = {
304 { .compatible = "st,stih407-sbc-pinctrl" },
305 { .compatible = "st,stih407-front-pinctrl" },
306 { .compatible = "st,stih407-rear-pinctrl" },
307 { .compatible = "st,stih407-flash-pinctrl" },
308 { }
309};
310
311const struct pinctrl_ops sti_pinctrl_ops = {
312 .set_state = sti_pinctrl_set_state,
313};
314
315U_BOOT_DRIVER(pinctrl_sti) = {
316 .name = "pinctrl_sti",
317 .id = UCLASS_PINCTRL,
318 .of_match = sti_pinctrl_ids,
319 .ops = &sti_pinctrl_ops,
320 .probe = sti_pinctrl_probe,
8a8d24bd 321 .plat_auto = sizeof(struct sti_pinctrl_plat),
0c563102
PC
322 .ops = &sti_pinctrl_ops,
323};
This page took 0.285282 seconds and 4 git commands to generate.