1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2011 The Chromium OS Authors.
4  */
5 
6 #include <common.h>
7 #include <dm.h>
8 #include <fdtdec.h>
9 #include <log.h>
10 #include <malloc.h>
11 #include <asm/gpio.h>
12 #include <dm/device_compat.h>
13 #include <dm/lists.h>
14 #include <dm/of.h>
15 #include <dm/pinctrl.h>
16 #include <dt-bindings/gpio/gpio.h>
17 #include <dt-bindings/gpio/sandbox-gpio.h>
18 
19 
20 struct gpio_state {
21 	const char *label;	/* label given by requester */
22 	ulong dir_flags;	/* dir_flags (GPIOD_...) */
23 };
24 
25 /* Access routines for GPIO dir flags */
get_gpio_dir_flags(struct udevice * dev,unsigned int offset)26 static ulong *get_gpio_dir_flags(struct udevice *dev, unsigned int offset)
27 {
28 	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
29 	struct gpio_state *state = dev_get_priv(dev);
30 
31 	if (offset >= uc_priv->gpio_count) {
32 		static ulong invalid_dir_flags;
33 		printf("sandbox_gpio: error: invalid gpio %u\n", offset);
34 		return &invalid_dir_flags;
35 	}
36 
37 	return &state[offset].dir_flags;
38 
39 }
40 
get_gpio_flag(struct udevice * dev,unsigned int offset,ulong flag)41 static int get_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag)
42 {
43 	return (*get_gpio_dir_flags(dev, offset) & flag) != 0;
44 }
45 
set_gpio_flag(struct udevice * dev,unsigned int offset,ulong flag,int value)46 static int set_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag,
47 			 int value)
48 {
49 	ulong *gpio = get_gpio_dir_flags(dev, offset);
50 
51 	if (value)
52 		*gpio |= flag;
53 	else
54 		*gpio &= ~flag;
55 
56 	return 0;
57 }
58 
59 /*
60  * Back-channel sandbox-internal-only access to GPIO state
61  */
62 
sandbox_gpio_get_value(struct udevice * dev,unsigned offset)63 int sandbox_gpio_get_value(struct udevice *dev, unsigned offset)
64 {
65 	if (get_gpio_flag(dev, offset, GPIOD_IS_OUT))
66 		debug("sandbox_gpio: get_value on output gpio %u\n", offset);
67 	return get_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE);
68 }
69 
sandbox_gpio_set_value(struct udevice * dev,unsigned offset,int value)70 int sandbox_gpio_set_value(struct udevice *dev, unsigned offset, int value)
71 {
72 	return set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE, value);
73 }
74 
sandbox_gpio_get_direction(struct udevice * dev,unsigned offset)75 int sandbox_gpio_get_direction(struct udevice *dev, unsigned offset)
76 {
77 	return get_gpio_flag(dev, offset, GPIOD_IS_OUT);
78 }
79 
sandbox_gpio_set_direction(struct udevice * dev,unsigned offset,int output)80 int sandbox_gpio_set_direction(struct udevice *dev, unsigned offset, int output)
81 {
82 	set_gpio_flag(dev, offset, GPIOD_IS_OUT, output);
83 	set_gpio_flag(dev, offset, GPIOD_IS_IN, !(output));
84 
85 	return 0;
86 }
87 
sandbox_gpio_get_dir_flags(struct udevice * dev,unsigned int offset)88 ulong sandbox_gpio_get_dir_flags(struct udevice *dev, unsigned int offset)
89 {
90 	return *get_gpio_dir_flags(dev, offset);
91 }
92 
sandbox_gpio_set_dir_flags(struct udevice * dev,unsigned int offset,ulong flags)93 int sandbox_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
94 			       ulong flags)
95 {
96 	*get_gpio_dir_flags(dev, offset) = flags;
97 
98 	return 0;
99 }
100 
101 /*
102  * These functions implement the public interface within U-Boot
103  */
104 
105 /* set GPIO port 'offset' as an input */
sb_gpio_direction_input(struct udevice * dev,unsigned offset)106 static int sb_gpio_direction_input(struct udevice *dev, unsigned offset)
107 {
108 	debug("%s: offset:%u\n", __func__, offset);
109 
110 	return sandbox_gpio_set_direction(dev, offset, 0);
111 }
112 
113 /* set GPIO port 'offset' as an output, with polarity 'value' */
sb_gpio_direction_output(struct udevice * dev,unsigned offset,int value)114 static int sb_gpio_direction_output(struct udevice *dev, unsigned offset,
115 				    int value)
116 {
117 	debug("%s: offset:%u, value = %d\n", __func__, offset, value);
118 
119 	return sandbox_gpio_set_direction(dev, offset, 1) |
120 		sandbox_gpio_set_value(dev, offset, value);
121 }
122 
123 /* read GPIO IN value of port 'offset' */
sb_gpio_get_value(struct udevice * dev,unsigned offset)124 static int sb_gpio_get_value(struct udevice *dev, unsigned offset)
125 {
126 	debug("%s: offset:%u\n", __func__, offset);
127 
128 	return sandbox_gpio_get_value(dev, offset);
129 }
130 
131 /* write GPIO OUT value to port 'offset' */
sb_gpio_set_value(struct udevice * dev,unsigned offset,int value)132 static int sb_gpio_set_value(struct udevice *dev, unsigned offset, int value)
133 {
134 	debug("%s: offset:%u, value = %d\n", __func__, offset, value);
135 
136 	if (!sandbox_gpio_get_direction(dev, offset)) {
137 		printf("sandbox_gpio: error: set_value on input gpio %u\n",
138 		       offset);
139 		return -1;
140 	}
141 
142 	return sandbox_gpio_set_value(dev, offset, value);
143 }
144 
sb_gpio_get_function(struct udevice * dev,unsigned offset)145 static int sb_gpio_get_function(struct udevice *dev, unsigned offset)
146 {
147 	if (get_gpio_flag(dev, offset, GPIOD_IS_OUT))
148 		return GPIOF_OUTPUT;
149 	if (get_gpio_flag(dev, offset, GPIOD_IS_IN))
150 		return GPIOF_INPUT;
151 
152 	return GPIOF_INPUT; /*GPIO is not configurated */
153 }
154 
sb_gpio_xlate(struct udevice * dev,struct gpio_desc * desc,struct ofnode_phandle_args * args)155 static int sb_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
156 			 struct ofnode_phandle_args *args)
157 {
158 	desc->offset = args->args[0];
159 	if (args->args_count < 2)
160 		return 0;
161 	/* treat generic binding with gpio uclass */
162 	gpio_xlate_offs_flags(dev, desc, args);
163 
164 	/* sandbox test specific, not defined in gpio.h */
165 	if (args->args[1] & GPIO_IN)
166 		desc->flags |= GPIOD_IS_IN;
167 
168 	if (args->args[1] & GPIO_OUT)
169 		desc->flags |= GPIOD_IS_OUT;
170 
171 	if (args->args[1] & GPIO_OUT_ACTIVE)
172 		desc->flags |= GPIOD_IS_OUT_ACTIVE;
173 
174 	return 0;
175 }
176 
sb_gpio_set_dir_flags(struct udevice * dev,unsigned int offset,ulong flags)177 static int sb_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
178 				 ulong flags)
179 {
180 	ulong *dir_flags;
181 
182 	debug("%s: offset:%u, dir_flags = %lx\n", __func__, offset, flags);
183 
184 	dir_flags = get_gpio_dir_flags(dev, offset);
185 
186 	*dir_flags = flags;
187 
188 	return 0;
189 }
190 
sb_gpio_get_dir_flags(struct udevice * dev,unsigned int offset,ulong * flags)191 static int sb_gpio_get_dir_flags(struct udevice *dev, unsigned int offset,
192 				 ulong *flags)
193 {
194 	debug("%s: offset:%u\n", __func__, offset);
195 	*flags = *get_gpio_dir_flags(dev, offset);
196 
197 	return 0;
198 }
199 
200 static const struct dm_gpio_ops gpio_sandbox_ops = {
201 	.direction_input	= sb_gpio_direction_input,
202 	.direction_output	= sb_gpio_direction_output,
203 	.get_value		= sb_gpio_get_value,
204 	.set_value		= sb_gpio_set_value,
205 	.get_function		= sb_gpio_get_function,
206 	.xlate			= sb_gpio_xlate,
207 	.set_dir_flags		= sb_gpio_set_dir_flags,
208 	.get_dir_flags		= sb_gpio_get_dir_flags,
209 };
210 
sandbox_gpio_ofdata_to_platdata(struct udevice * dev)211 static int sandbox_gpio_ofdata_to_platdata(struct udevice *dev)
212 {
213 	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
214 
215 	uc_priv->gpio_count = dev_read_u32_default(dev, "sandbox,gpio-count",
216 						   0);
217 	uc_priv->bank_name = dev_read_string(dev, "gpio-bank-name");
218 
219 	return 0;
220 }
221 
gpio_sandbox_probe(struct udevice * dev)222 static int gpio_sandbox_probe(struct udevice *dev)
223 {
224 	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
225 
226 	if (!dev_of_valid(dev))
227 		/* Tell the uclass how many GPIOs we have */
228 		uc_priv->gpio_count = CONFIG_SANDBOX_GPIO_COUNT;
229 
230 	dev->priv = calloc(sizeof(struct gpio_state), uc_priv->gpio_count);
231 
232 	return 0;
233 }
234 
gpio_sandbox_remove(struct udevice * dev)235 static int gpio_sandbox_remove(struct udevice *dev)
236 {
237 	free(dev->priv);
238 
239 	return 0;
240 }
241 
242 static const struct udevice_id sandbox_gpio_ids[] = {
243 	{ .compatible = "sandbox,gpio" },
244 	{ }
245 };
246 
247 U_BOOT_DRIVER(gpio_sandbox) = {
248 	.name	= "gpio_sandbox",
249 	.id	= UCLASS_GPIO,
250 	.of_match = sandbox_gpio_ids,
251 	.ofdata_to_platdata = sandbox_gpio_ofdata_to_platdata,
252 	.probe	= gpio_sandbox_probe,
253 	.remove	= gpio_sandbox_remove,
254 	.ops	= &gpio_sandbox_ops,
255 };
256 
257 /* pincontrol: used only to check GPIO pin configuration (pinmux command) */
258 
259 struct sb_pinctrl_priv {
260 	int pinctrl_ngpios;
261 	struct list_head gpio_dev;
262 };
263 
264 struct sb_gpio_bank {
265 	struct udevice *gpio_dev;
266 	struct list_head list;
267 };
268 
sb_populate_gpio_dev_list(struct udevice * dev)269 static int sb_populate_gpio_dev_list(struct udevice *dev)
270 {
271 	struct sb_pinctrl_priv *priv = dev_get_priv(dev);
272 	struct udevice *gpio_dev;
273 	struct udevice *child;
274 	struct sb_gpio_bank *gpio_bank;
275 	int ret;
276 
277 	/*
278 	 * parse pin-controller sub-nodes (ie gpio bank nodes) and fill
279 	 * a list with all gpio device reference which belongs to the
280 	 * current pin-controller. This list is used to find pin_name and
281 	 * pin muxing
282 	 */
283 	list_for_each_entry(child, &dev->child_head, sibling_node) {
284 		ret = uclass_get_device_by_name(UCLASS_GPIO, child->name,
285 						&gpio_dev);
286 		if (ret < 0)
287 			continue;
288 
289 		gpio_bank = malloc(sizeof(*gpio_bank));
290 		if (!gpio_bank) {
291 			dev_err(dev, "Not enough memory\n");
292 			return -ENOMEM;
293 		}
294 
295 		gpio_bank->gpio_dev = gpio_dev;
296 		list_add_tail(&gpio_bank->list, &priv->gpio_dev);
297 	}
298 
299 	return 0;
300 }
301 
sb_pinctrl_get_pins_count(struct udevice * dev)302 static int sb_pinctrl_get_pins_count(struct udevice *dev)
303 {
304 	struct sb_pinctrl_priv *priv = dev_get_priv(dev);
305 	struct gpio_dev_priv *uc_priv;
306 	struct sb_gpio_bank *gpio_bank;
307 
308 	/*
309 	 * if get_pins_count has already been executed once on this
310 	 * pin-controller, no need to run it again
311 	 */
312 	if (priv->pinctrl_ngpios)
313 		return priv->pinctrl_ngpios;
314 
315 	if (list_empty(&priv->gpio_dev))
316 		sb_populate_gpio_dev_list(dev);
317 	/*
318 	 * walk through all banks to retrieve the pin-controller
319 	 * pins number
320 	 */
321 	list_for_each_entry(gpio_bank, &priv->gpio_dev, list) {
322 		uc_priv = dev_get_uclass_priv(gpio_bank->gpio_dev);
323 
324 		priv->pinctrl_ngpios += uc_priv->gpio_count;
325 	}
326 
327 	return priv->pinctrl_ngpios;
328 }
329 
sb_pinctrl_get_gpio_dev(struct udevice * dev,unsigned int selector,unsigned int * idx)330 static struct udevice *sb_pinctrl_get_gpio_dev(struct udevice *dev,
331 					       unsigned int selector,
332 					       unsigned int *idx)
333 {
334 	struct sb_pinctrl_priv *priv = dev_get_priv(dev);
335 	struct sb_gpio_bank *gpio_bank;
336 	struct gpio_dev_priv *uc_priv;
337 	int pin_count = 0;
338 
339 	if (list_empty(&priv->gpio_dev))
340 		sb_populate_gpio_dev_list(dev);
341 
342 	/* look up for the bank which owns the requested pin */
343 	list_for_each_entry(gpio_bank, &priv->gpio_dev, list) {
344 		uc_priv = dev_get_uclass_priv(gpio_bank->gpio_dev);
345 
346 		if (selector < (pin_count + uc_priv->gpio_count)) {
347 			/*
348 			 * we found the bank, convert pin selector to
349 			 * gpio bank index
350 			 */
351 			*idx = selector - pin_count;
352 
353 			return gpio_bank->gpio_dev;
354 		}
355 		pin_count += uc_priv->gpio_count;
356 	}
357 
358 	return NULL;
359 }
360 
sb_pinctrl_get_pin_name(struct udevice * dev,unsigned int selector)361 static const char *sb_pinctrl_get_pin_name(struct udevice *dev,
362 					   unsigned int selector)
363 {
364 	struct gpio_dev_priv *uc_priv;
365 	struct udevice *gpio_dev;
366 	unsigned int gpio_idx;
367 	static char pin_name[PINNAME_SIZE];
368 
369 	/* look up for the bank which owns the requested pin */
370 	gpio_dev = sb_pinctrl_get_gpio_dev(dev, selector, &gpio_idx);
371 	if (!gpio_dev) {
372 		snprintf(pin_name, PINNAME_SIZE, "Error");
373 	} else {
374 		uc_priv = dev_get_uclass_priv(gpio_dev);
375 
376 		snprintf(pin_name, PINNAME_SIZE, "%s%d",
377 			 uc_priv->bank_name,
378 			 gpio_idx);
379 	}
380 
381 	return pin_name;
382 }
383 
get_dir_flags_string(ulong flags)384 static char *get_dir_flags_string(ulong flags)
385 {
386 	if (flags & GPIOD_OPEN_DRAIN)
387 		return "drive-open-drain";
388 	if (flags & GPIOD_OPEN_SOURCE)
389 		return "drive-open-source";
390 	if (flags & GPIOD_PULL_UP)
391 		return "bias-pull-up";
392 	if (flags & GPIOD_PULL_DOWN)
393 		return "bias-pull-down";
394 	return ".";
395 }
396 
sb_pinctrl_get_pin_muxing(struct udevice * dev,unsigned int selector,char * buf,int size)397 static int sb_pinctrl_get_pin_muxing(struct udevice *dev,
398 				     unsigned int selector,
399 				     char *buf, int size)
400 {
401 	struct udevice *gpio_dev;
402 	unsigned int gpio_idx;
403 	ulong dir_flags;
404 	int function;
405 
406 	/* look up for the bank which owns the requested pin */
407 	gpio_dev = sb_pinctrl_get_gpio_dev(dev, selector, &gpio_idx);
408 	if (!gpio_dev) {
409 		snprintf(buf, size, "Error");
410 	} else {
411 		function = sb_gpio_get_function(gpio_dev, gpio_idx);
412 		dir_flags = *get_gpio_dir_flags(gpio_dev, gpio_idx);
413 
414 		snprintf(buf, size, "gpio %s %s",
415 			 function == GPIOF_OUTPUT ? "output" : "input",
416 			 get_dir_flags_string(dir_flags));
417 	}
418 
419 	return 0;
420 }
421 
sandbox_pinctrl_probe(struct udevice * dev)422 static int sandbox_pinctrl_probe(struct udevice *dev)
423 {
424 	struct sb_pinctrl_priv *priv = dev_get_priv(dev);
425 
426 	INIT_LIST_HEAD(&priv->gpio_dev);
427 
428 	return 0;
429 }
430 
431 static struct pinctrl_ops sandbox_pinctrl_gpio_ops = {
432 	.get_pin_name		= sb_pinctrl_get_pin_name,
433 	.get_pins_count		= sb_pinctrl_get_pins_count,
434 	.get_pin_muxing		= sb_pinctrl_get_pin_muxing,
435 };
436 
437 static const struct udevice_id sandbox_pinctrl_gpio_match[] = {
438 	{ .compatible = "sandbox,pinctrl-gpio" },
439 	{ /* sentinel */ }
440 };
441 
442 U_BOOT_DRIVER(sandbox_pinctrl_gpio) = {
443 	.name = "sandbox_pinctrl_gpio",
444 	.id = UCLASS_PINCTRL,
445 	.of_match = sandbox_pinctrl_gpio_match,
446 	.ops = &sandbox_pinctrl_gpio_ops,
447 	.bind = dm_scan_fdt_dev,
448 	.probe = sandbox_pinctrl_probe,
449 	.priv_auto_alloc_size	= sizeof(struct sb_pinctrl_priv),
450 };
451