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 <acpi/acpi_device.h>
12 #include <asm/gpio.h>
13 #include <dm/acpi.h>
14 #include <dm/device-internal.h>
15 #include <dm/device_compat.h>
16 #include <dm/lists.h>
17 #include <dm/of.h>
18 #include <dm/pinctrl.h>
19 #include <dt-bindings/gpio/gpio.h>
20 #include <dt-bindings/gpio/sandbox-gpio.h>
21
22
23 struct gpio_state {
24 const char *label; /* label given by requester */
25 ulong dir_flags; /* dir_flags (GPIOD_...) */
26 };
27
28 /* Access routines for GPIO dir flags */
get_gpio_dir_flags(struct udevice * dev,unsigned int offset)29 static ulong *get_gpio_dir_flags(struct udevice *dev, unsigned int offset)
30 {
31 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
32 struct gpio_state *state = dev_get_priv(dev);
33
34 if (offset >= uc_priv->gpio_count) {
35 static ulong invalid_dir_flags;
36 printf("sandbox_gpio: error: invalid gpio %u\n", offset);
37 return &invalid_dir_flags;
38 }
39
40 return &state[offset].dir_flags;
41
42 }
43
get_gpio_flag(struct udevice * dev,unsigned int offset,ulong flag)44 static int get_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag)
45 {
46 return (*get_gpio_dir_flags(dev, offset) & flag) != 0;
47 }
48
set_gpio_flag(struct udevice * dev,unsigned int offset,ulong flag,int value)49 static int set_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag,
50 int value)
51 {
52 ulong *gpio = get_gpio_dir_flags(dev, offset);
53
54 if (value)
55 *gpio |= flag;
56 else
57 *gpio &= ~flag;
58
59 return 0;
60 }
61
62 /*
63 * Back-channel sandbox-internal-only access to GPIO state
64 */
65
sandbox_gpio_get_value(struct udevice * dev,unsigned offset)66 int sandbox_gpio_get_value(struct udevice *dev, unsigned offset)
67 {
68 if (get_gpio_flag(dev, offset, GPIOD_IS_OUT))
69 debug("sandbox_gpio: get_value on output gpio %u\n", offset);
70 return get_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE);
71 }
72
sandbox_gpio_set_value(struct udevice * dev,unsigned offset,int value)73 int sandbox_gpio_set_value(struct udevice *dev, unsigned offset, int value)
74 {
75 return set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE, value);
76 }
77
sandbox_gpio_get_direction(struct udevice * dev,unsigned offset)78 int sandbox_gpio_get_direction(struct udevice *dev, unsigned offset)
79 {
80 return get_gpio_flag(dev, offset, GPIOD_IS_OUT);
81 }
82
sandbox_gpio_set_direction(struct udevice * dev,unsigned offset,int output)83 int sandbox_gpio_set_direction(struct udevice *dev, unsigned offset, int output)
84 {
85 set_gpio_flag(dev, offset, GPIOD_IS_OUT, output);
86 set_gpio_flag(dev, offset, GPIOD_IS_IN, !(output));
87
88 return 0;
89 }
90
sandbox_gpio_get_dir_flags(struct udevice * dev,unsigned int offset)91 ulong sandbox_gpio_get_dir_flags(struct udevice *dev, unsigned int offset)
92 {
93 return *get_gpio_dir_flags(dev, offset);
94 }
95
sandbox_gpio_set_dir_flags(struct udevice * dev,unsigned int offset,ulong flags)96 int sandbox_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
97 ulong flags)
98 {
99 *get_gpio_dir_flags(dev, offset) = flags;
100
101 return 0;
102 }
103
104 /*
105 * These functions implement the public interface within U-Boot
106 */
107
108 /* set GPIO port 'offset' as an input */
sb_gpio_direction_input(struct udevice * dev,unsigned offset)109 static int sb_gpio_direction_input(struct udevice *dev, unsigned offset)
110 {
111 debug("%s: offset:%u\n", __func__, offset);
112
113 return sandbox_gpio_set_direction(dev, offset, 0);
114 }
115
116 /* set GPIO port 'offset' as an output, with polarity 'value' */
sb_gpio_direction_output(struct udevice * dev,unsigned offset,int value)117 static int sb_gpio_direction_output(struct udevice *dev, unsigned offset,
118 int value)
119 {
120 debug("%s: offset:%u, value = %d\n", __func__, offset, value);
121
122 return sandbox_gpio_set_direction(dev, offset, 1) |
123 sandbox_gpio_set_value(dev, offset, value);
124 }
125
126 /* read GPIO IN value of port 'offset' */
sb_gpio_get_value(struct udevice * dev,unsigned offset)127 static int sb_gpio_get_value(struct udevice *dev, unsigned offset)
128 {
129 debug("%s: offset:%u\n", __func__, offset);
130
131 return sandbox_gpio_get_value(dev, offset);
132 }
133
134 /* write GPIO OUT value to port 'offset' */
sb_gpio_set_value(struct udevice * dev,unsigned offset,int value)135 static int sb_gpio_set_value(struct udevice *dev, unsigned offset, int value)
136 {
137 debug("%s: offset:%u, value = %d\n", __func__, offset, value);
138
139 if (!sandbox_gpio_get_direction(dev, offset)) {
140 printf("sandbox_gpio: error: set_value on input gpio %u\n",
141 offset);
142 return -1;
143 }
144
145 return sandbox_gpio_set_value(dev, offset, value);
146 }
147
sb_gpio_get_function(struct udevice * dev,unsigned offset)148 static int sb_gpio_get_function(struct udevice *dev, unsigned offset)
149 {
150 if (get_gpio_flag(dev, offset, GPIOD_IS_OUT))
151 return GPIOF_OUTPUT;
152 if (get_gpio_flag(dev, offset, GPIOD_IS_IN))
153 return GPIOF_INPUT;
154
155 return GPIOF_INPUT; /*GPIO is not configurated */
156 }
157
sb_gpio_xlate(struct udevice * dev,struct gpio_desc * desc,struct ofnode_phandle_args * args)158 static int sb_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
159 struct ofnode_phandle_args *args)
160 {
161 desc->offset = args->args[0];
162 if (args->args_count < 2)
163 return 0;
164 /* treat generic binding with gpio uclass */
165 gpio_xlate_offs_flags(dev, desc, args);
166
167 /* sandbox test specific, not defined in gpio.h */
168 if (args->args[1] & GPIO_IN)
169 desc->flags |= GPIOD_IS_IN;
170
171 if (args->args[1] & GPIO_OUT)
172 desc->flags |= GPIOD_IS_OUT;
173
174 if (args->args[1] & GPIO_OUT_ACTIVE)
175 desc->flags |= GPIOD_IS_OUT_ACTIVE;
176
177 return 0;
178 }
179
sb_gpio_set_dir_flags(struct udevice * dev,unsigned int offset,ulong flags)180 static int sb_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
181 ulong flags)
182 {
183 ulong *dir_flags;
184
185 debug("%s: offset:%u, dir_flags = %lx\n", __func__, offset, flags);
186
187 dir_flags = get_gpio_dir_flags(dev, offset);
188
189 /*
190 * For testing purposes keep the output value when switching to input.
191 * This allows us to manipulate the input value via the gpio command.
192 */
193 if (flags & GPIOD_IS_IN)
194 *dir_flags = (flags & ~GPIOD_IS_OUT_ACTIVE) |
195 (*dir_flags & GPIOD_IS_OUT_ACTIVE);
196 else
197 *dir_flags = flags;
198
199 return 0;
200 }
201
sb_gpio_get_dir_flags(struct udevice * dev,unsigned int offset,ulong * flags)202 static int sb_gpio_get_dir_flags(struct udevice *dev, unsigned int offset,
203 ulong *flags)
204 {
205 debug("%s: offset:%u\n", __func__, offset);
206 *flags = *get_gpio_dir_flags(dev, offset);
207
208 return 0;
209 }
210
211 #if CONFIG_IS_ENABLED(ACPIGEN)
sb_gpio_get_acpi(const struct gpio_desc * desc,struct acpi_gpio * gpio)212 static int sb_gpio_get_acpi(const struct gpio_desc *desc,
213 struct acpi_gpio *gpio)
214 {
215 int ret;
216
217 /* Note that gpio_get_acpi() zeroes *gpio before calling here */
218 gpio->pin_count = 1;
219 gpio->pins[0] = desc->offset;
220 ret = acpi_device_scope(desc->dev, gpio->resource,
221 sizeof(gpio->resource));
222 if (ret)
223 return log_ret(ret);
224
225 /* All of these values are just used for testing */
226 if (desc->flags & GPIOD_ACTIVE_LOW) {
227 gpio->pin0_addr = 0x80012 + desc->offset;
228 gpio->type = ACPI_GPIO_TYPE_INTERRUPT;
229 gpio->pull = ACPI_GPIO_PULL_DOWN;
230 gpio->interrupt_debounce_timeout = 4321;
231
232 /* We use the GpioInt part */
233 gpio->irq.pin = desc->offset;
234 gpio->irq.polarity = ACPI_IRQ_ACTIVE_BOTH;
235 gpio->irq.shared = ACPI_IRQ_SHARED;
236 gpio->irq.wake = ACPI_IRQ_WAKE;
237
238 /* The GpioIo part is only used for testing */
239 gpio->polarity = ACPI_GPIO_ACTIVE_LOW;
240 } else {
241 gpio->pin0_addr = 0xc00dc + desc->offset;
242 gpio->type = ACPI_GPIO_TYPE_IO;
243 gpio->pull = ACPI_GPIO_PULL_UP;
244 gpio->interrupt_debounce_timeout = 0;
245
246 /* The GpioInt part is not used */
247
248 /* We use the GpioIo part */
249 gpio->output_drive_strength = 1234;
250 gpio->io_shared = true;
251 gpio->io_restrict = ACPI_GPIO_IO_RESTRICT_INPUT;
252 gpio->polarity = 0;
253 }
254
255 return 0;
256 }
257
sb_gpio_get_name(const struct udevice * dev,char * out_name)258 static int sb_gpio_get_name(const struct udevice *dev, char *out_name)
259 {
260 return acpi_copy_name(out_name, "GPIO");
261 }
262
263 struct acpi_ops gpio_sandbox_acpi_ops = {
264 .get_name = sb_gpio_get_name,
265 };
266 #endif /* ACPIGEN */
267
268 static const struct dm_gpio_ops gpio_sandbox_ops = {
269 .direction_input = sb_gpio_direction_input,
270 .direction_output = sb_gpio_direction_output,
271 .get_value = sb_gpio_get_value,
272 .set_value = sb_gpio_set_value,
273 .get_function = sb_gpio_get_function,
274 .xlate = sb_gpio_xlate,
275 .set_dir_flags = sb_gpio_set_dir_flags,
276 .get_dir_flags = sb_gpio_get_dir_flags,
277 #if CONFIG_IS_ENABLED(ACPIGEN)
278 .get_acpi = sb_gpio_get_acpi,
279 #endif
280 };
281
sandbox_gpio_of_to_plat(struct udevice * dev)282 static int sandbox_gpio_of_to_plat(struct udevice *dev)
283 {
284 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
285
286 uc_priv->gpio_count = dev_read_u32_default(dev, "sandbox,gpio-count",
287 0);
288 uc_priv->bank_name = dev_read_string(dev, "gpio-bank-name");
289
290 return 0;
291 }
292
gpio_sandbox_probe(struct udevice * dev)293 static int gpio_sandbox_probe(struct udevice *dev)
294 {
295 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
296
297 if (!dev_has_ofnode(dev))
298 /* Tell the uclass how many GPIOs we have */
299 uc_priv->gpio_count = CONFIG_SANDBOX_GPIO_COUNT;
300
301 dev_set_priv(dev,
302 calloc(sizeof(struct gpio_state), uc_priv->gpio_count));
303
304 return 0;
305 }
306
gpio_sandbox_remove(struct udevice * dev)307 static int gpio_sandbox_remove(struct udevice *dev)
308 {
309 free(dev_get_priv(dev));
310
311 return 0;
312 }
313
314 static const struct udevice_id sandbox_gpio_ids[] = {
315 { .compatible = "sandbox,gpio" },
316 { }
317 };
318
319 U_BOOT_DRIVER(sandbox_gpio) = {
320 .name = "sandbox_gpio",
321 .id = UCLASS_GPIO,
322 .of_match = sandbox_gpio_ids,
323 .of_to_plat = sandbox_gpio_of_to_plat,
324 .probe = gpio_sandbox_probe,
325 .remove = gpio_sandbox_remove,
326 .ops = &gpio_sandbox_ops,
327 ACPI_OPS_PTR(&gpio_sandbox_acpi_ops)
328 };
329
330 DM_DRIVER_ALIAS(sandbox_gpio, sandbox_gpio_alias)
331
332 /* pincontrol: used only to check GPIO pin configuration (pinmux command) */
333
334 struct sb_pinctrl_priv {
335 int pinctrl_ngpios;
336 struct list_head gpio_dev;
337 };
338
339 struct sb_gpio_bank {
340 struct udevice *gpio_dev;
341 struct list_head list;
342 };
343
sb_populate_gpio_dev_list(struct udevice * dev)344 static int sb_populate_gpio_dev_list(struct udevice *dev)
345 {
346 struct sb_pinctrl_priv *priv = dev_get_priv(dev);
347 struct udevice *gpio_dev;
348 struct udevice *child;
349 struct sb_gpio_bank *gpio_bank;
350 int ret;
351
352 /*
353 * parse pin-controller sub-nodes (ie gpio bank nodes) and fill
354 * a list with all gpio device reference which belongs to the
355 * current pin-controller. This list is used to find pin_name and
356 * pin muxing
357 */
358 list_for_each_entry(child, &dev->child_head, sibling_node) {
359 ret = uclass_get_device_by_name(UCLASS_GPIO, child->name,
360 &gpio_dev);
361 if (ret < 0)
362 continue;
363
364 gpio_bank = malloc(sizeof(*gpio_bank));
365 if (!gpio_bank) {
366 dev_err(dev, "Not enough memory\n");
367 return -ENOMEM;
368 }
369
370 gpio_bank->gpio_dev = gpio_dev;
371 list_add_tail(&gpio_bank->list, &priv->gpio_dev);
372 }
373
374 return 0;
375 }
376
sb_pinctrl_get_pins_count(struct udevice * dev)377 static int sb_pinctrl_get_pins_count(struct udevice *dev)
378 {
379 struct sb_pinctrl_priv *priv = dev_get_priv(dev);
380 struct gpio_dev_priv *uc_priv;
381 struct sb_gpio_bank *gpio_bank;
382
383 /*
384 * if get_pins_count has already been executed once on this
385 * pin-controller, no need to run it again
386 */
387 if (priv->pinctrl_ngpios)
388 return priv->pinctrl_ngpios;
389
390 if (list_empty(&priv->gpio_dev))
391 sb_populate_gpio_dev_list(dev);
392 /*
393 * walk through all banks to retrieve the pin-controller
394 * pins number
395 */
396 list_for_each_entry(gpio_bank, &priv->gpio_dev, list) {
397 uc_priv = dev_get_uclass_priv(gpio_bank->gpio_dev);
398
399 priv->pinctrl_ngpios += uc_priv->gpio_count;
400 }
401
402 return priv->pinctrl_ngpios;
403 }
404
sb_pinctrl_get_gpio_dev(struct udevice * dev,unsigned int selector,unsigned int * idx)405 static struct udevice *sb_pinctrl_get_gpio_dev(struct udevice *dev,
406 unsigned int selector,
407 unsigned int *idx)
408 {
409 struct sb_pinctrl_priv *priv = dev_get_priv(dev);
410 struct sb_gpio_bank *gpio_bank;
411 struct gpio_dev_priv *uc_priv;
412 int pin_count = 0;
413
414 if (list_empty(&priv->gpio_dev))
415 sb_populate_gpio_dev_list(dev);
416
417 /* look up for the bank which owns the requested pin */
418 list_for_each_entry(gpio_bank, &priv->gpio_dev, list) {
419 uc_priv = dev_get_uclass_priv(gpio_bank->gpio_dev);
420
421 if (selector < (pin_count + uc_priv->gpio_count)) {
422 /*
423 * we found the bank, convert pin selector to
424 * gpio bank index
425 */
426 *idx = selector - pin_count;
427
428 return gpio_bank->gpio_dev;
429 }
430 pin_count += uc_priv->gpio_count;
431 }
432
433 return NULL;
434 }
435
sb_pinctrl_get_pin_name(struct udevice * dev,unsigned int selector)436 static const char *sb_pinctrl_get_pin_name(struct udevice *dev,
437 unsigned int selector)
438 {
439 struct gpio_dev_priv *uc_priv;
440 struct udevice *gpio_dev;
441 unsigned int gpio_idx;
442 static char pin_name[PINNAME_SIZE];
443
444 /* look up for the bank which owns the requested pin */
445 gpio_dev = sb_pinctrl_get_gpio_dev(dev, selector, &gpio_idx);
446 if (!gpio_dev) {
447 snprintf(pin_name, PINNAME_SIZE, "Error");
448 } else {
449 uc_priv = dev_get_uclass_priv(gpio_dev);
450
451 snprintf(pin_name, PINNAME_SIZE, "%s%d",
452 uc_priv->bank_name,
453 gpio_idx);
454 }
455
456 return pin_name;
457 }
458
get_dir_flags_string(ulong flags)459 static char *get_dir_flags_string(ulong flags)
460 {
461 if (flags & GPIOD_OPEN_DRAIN)
462 return "drive-open-drain";
463 if (flags & GPIOD_OPEN_SOURCE)
464 return "drive-open-source";
465 if (flags & GPIOD_PULL_UP)
466 return "bias-pull-up";
467 if (flags & GPIOD_PULL_DOWN)
468 return "bias-pull-down";
469 return ".";
470 }
471
sb_pinctrl_get_pin_muxing(struct udevice * dev,unsigned int selector,char * buf,int size)472 static int sb_pinctrl_get_pin_muxing(struct udevice *dev,
473 unsigned int selector,
474 char *buf, int size)
475 {
476 struct udevice *gpio_dev;
477 unsigned int gpio_idx;
478 ulong dir_flags;
479 int function;
480
481 /* look up for the bank which owns the requested pin */
482 gpio_dev = sb_pinctrl_get_gpio_dev(dev, selector, &gpio_idx);
483 if (!gpio_dev) {
484 snprintf(buf, size, "Error");
485 } else {
486 function = sb_gpio_get_function(gpio_dev, gpio_idx);
487 dir_flags = *get_gpio_dir_flags(gpio_dev, gpio_idx);
488
489 snprintf(buf, size, "gpio %s %s",
490 function == GPIOF_OUTPUT ? "output" : "input",
491 get_dir_flags_string(dir_flags));
492 }
493
494 return 0;
495 }
496
497 #if CONFIG_IS_ENABLED(ACPIGEN)
sb_pinctrl_get_name(const struct udevice * dev,char * out_name)498 static int sb_pinctrl_get_name(const struct udevice *dev, char *out_name)
499 {
500 return acpi_copy_name(out_name, "PINC");
501 }
502 #endif
503
sandbox_pinctrl_probe(struct udevice * dev)504 static int sandbox_pinctrl_probe(struct udevice *dev)
505 {
506 struct sb_pinctrl_priv *priv = dev_get_priv(dev);
507
508 INIT_LIST_HEAD(&priv->gpio_dev);
509
510 return 0;
511 }
512
513 static struct pinctrl_ops sandbox_pinctrl_gpio_ops = {
514 .get_pin_name = sb_pinctrl_get_pin_name,
515 .get_pins_count = sb_pinctrl_get_pins_count,
516 .get_pin_muxing = sb_pinctrl_get_pin_muxing,
517 };
518
519 #if CONFIG_IS_ENABLED(ACPIGEN)
520 struct acpi_ops pinctrl_sandbox_acpi_ops = {
521 .get_name = sb_pinctrl_get_name,
522 };
523 #endif
524
525 static const struct udevice_id sandbox_pinctrl_gpio_match[] = {
526 { .compatible = "sandbox,pinctrl-gpio" },
527 { /* sentinel */ }
528 };
529
530 U_BOOT_DRIVER(sandbox_pinctrl_gpio) = {
531 .name = "sandbox_pinctrl_gpio",
532 .id = UCLASS_PINCTRL,
533 .of_match = sandbox_pinctrl_gpio_match,
534 .ops = &sandbox_pinctrl_gpio_ops,
535 .bind = dm_scan_fdt_dev,
536 .probe = sandbox_pinctrl_probe,
537 .priv_auto = sizeof(struct sb_pinctrl_priv),
538 ACPI_OPS_PTR(&pinctrl_sandbox_acpi_ops)
539 };
540