blob: c2f80472b83a8a900f813e2f66db51bfba3e23a5 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glassb43d0442012-02-15 15:51:13 -08002/*
3 * Copyright (c) 2011 The Chromium OS Authors.
Simon Glassb43d0442012-02-15 15:51:13 -08004 */
5
6#include <common.h>
Simon Glassb4d70702014-02-26 15:59:25 -07007#include <dm.h>
8#include <fdtdec.h>
Simon Glass0f2af882020-05-10 11:40:05 -06009#include <log.h>
Simon Glassb4d70702014-02-26 15:59:25 -070010#include <malloc.h>
Simon Glass3176b6c2020-07-07 13:11:44 -060011#include <acpi/acpi_device.h>
Simon Glassb43d0442012-02-15 15:51:13 -080012#include <asm/gpio.h>
Simon Glass3176b6c2020-07-07 13:11:44 -060013#include <dm/acpi.h>
Patrick Delaunay1b4a22f2020-01-13 11:35:15 +010014#include <dm/device_compat.h>
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010015#include <dm/lists.h>
Simon Glass12faa022017-05-18 20:09:18 -060016#include <dm/of.h>
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010017#include <dm/pinctrl.h>
Simon Glass16e10402015-01-05 20:05:29 -070018#include <dt-bindings/gpio/gpio.h>
Patrick Delaunay23aee612020-01-13 11:35:13 +010019#include <dt-bindings/gpio/sandbox-gpio.h>
Simon Glassb43d0442012-02-15 15:51:13 -080020
Simon Glassb43d0442012-02-15 15:51:13 -080021
22struct gpio_state {
23 const char *label; /* label given by requester */
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010024 ulong dir_flags; /* dir_flags (GPIOD_...) */
Simon Glassb43d0442012-02-15 15:51:13 -080025};
26
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010027/* Access routines for GPIO dir flags */
28static ulong *get_gpio_dir_flags(struct udevice *dev, unsigned int offset)
Simon Glassb43d0442012-02-15 15:51:13 -080029{
Simon Glassde0977b2015-03-05 12:25:20 -070030 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
Simon Glassb4d70702014-02-26 15:59:25 -070031 struct gpio_state *state = dev_get_priv(dev);
32
33 if (offset >= uc_priv->gpio_count) {
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010034 static ulong invalid_dir_flags;
Simon Glassb4d70702014-02-26 15:59:25 -070035 printf("sandbox_gpio: error: invalid gpio %u\n", offset);
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010036 return &invalid_dir_flags;
Simon Glassb43d0442012-02-15 15:51:13 -080037 }
38
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010039 return &state[offset].dir_flags;
40
Simon Glassb43d0442012-02-15 15:51:13 -080041}
42
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010043static int get_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag)
Simon Glassb43d0442012-02-15 15:51:13 -080044{
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010045 return (*get_gpio_dir_flags(dev, offset) & flag) != 0;
Simon Glassb43d0442012-02-15 15:51:13 -080046}
47
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010048static int set_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag,
Simon Glassb4d70702014-02-26 15:59:25 -070049 int value)
Simon Glassb43d0442012-02-15 15:51:13 -080050{
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010051 ulong *gpio = get_gpio_dir_flags(dev, offset);
Simon Glassb43d0442012-02-15 15:51:13 -080052
53 if (value)
54 *gpio |= flag;
55 else
56 *gpio &= ~flag;
57
58 return 0;
59}
60
Simon Glassb43d0442012-02-15 15:51:13 -080061/*
62 * Back-channel sandbox-internal-only access to GPIO state
63 */
64
Heiko Schocherb74fcb42014-05-22 12:43:05 +020065int sandbox_gpio_get_value(struct udevice *dev, unsigned offset)
Simon Glassb43d0442012-02-15 15:51:13 -080066{
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010067 if (get_gpio_flag(dev, offset, GPIOD_IS_OUT))
Simon Glassb4d70702014-02-26 15:59:25 -070068 debug("sandbox_gpio: get_value on output gpio %u\n", offset);
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010069 return get_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE);
Simon Glassb43d0442012-02-15 15:51:13 -080070}
71
Heiko Schocherb74fcb42014-05-22 12:43:05 +020072int sandbox_gpio_set_value(struct udevice *dev, unsigned offset, int value)
Simon Glassb43d0442012-02-15 15:51:13 -080073{
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010074 return set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE, value);
Simon Glassb43d0442012-02-15 15:51:13 -080075}
76
Heiko Schocherb74fcb42014-05-22 12:43:05 +020077int sandbox_gpio_get_direction(struct udevice *dev, unsigned offset)
Simon Glassb43d0442012-02-15 15:51:13 -080078{
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010079 return get_gpio_flag(dev, offset, GPIOD_IS_OUT);
Simon Glassb43d0442012-02-15 15:51:13 -080080}
81
Heiko Schocherb74fcb42014-05-22 12:43:05 +020082int sandbox_gpio_set_direction(struct udevice *dev, unsigned offset, int output)
Simon Glassb43d0442012-02-15 15:51:13 -080083{
Patrick Delaunay28bdaa52020-01-13 11:35:14 +010084 set_gpio_flag(dev, offset, GPIOD_IS_OUT, output);
85 set_gpio_flag(dev, offset, GPIOD_IS_IN, !(output));
86
87 return 0;
88}
89
90ulong sandbox_gpio_get_dir_flags(struct udevice *dev, unsigned int offset)
91{
92 return *get_gpio_dir_flags(dev, offset);
93}
94
95int sandbox_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
96 ulong flags)
97{
98 *get_gpio_dir_flags(dev, offset) = flags;
99
100 return 0;
Simon Glassb43d0442012-02-15 15:51:13 -0800101}
102
103/*
104 * These functions implement the public interface within U-Boot
105 */
106
Simon Glassb4d70702014-02-26 15:59:25 -0700107/* set GPIO port 'offset' as an input */
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200108static int sb_gpio_direction_input(struct udevice *dev, unsigned offset)
Simon Glassb43d0442012-02-15 15:51:13 -0800109{
Simon Glassb4d70702014-02-26 15:59:25 -0700110 debug("%s: offset:%u\n", __func__, offset);
Simon Glassb43d0442012-02-15 15:51:13 -0800111
Simon Glassb4d70702014-02-26 15:59:25 -0700112 return sandbox_gpio_set_direction(dev, offset, 0);
Simon Glassb43d0442012-02-15 15:51:13 -0800113}
114
Simon Glassb4d70702014-02-26 15:59:25 -0700115/* set GPIO port 'offset' as an output, with polarity 'value' */
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200116static int sb_gpio_direction_output(struct udevice *dev, unsigned offset,
Simon Glassb4d70702014-02-26 15:59:25 -0700117 int value)
Simon Glassb43d0442012-02-15 15:51:13 -0800118{
Simon Glassb4d70702014-02-26 15:59:25 -0700119 debug("%s: offset:%u, value = %d\n", __func__, offset, value);
Simon Glassb43d0442012-02-15 15:51:13 -0800120
Simon Glassb4d70702014-02-26 15:59:25 -0700121 return sandbox_gpio_set_direction(dev, offset, 1) |
122 sandbox_gpio_set_value(dev, offset, value);
Simon Glassb43d0442012-02-15 15:51:13 -0800123}
124
Simon Glassb4d70702014-02-26 15:59:25 -0700125/* read GPIO IN value of port 'offset' */
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200126static int sb_gpio_get_value(struct udevice *dev, unsigned offset)
Simon Glassb43d0442012-02-15 15:51:13 -0800127{
Simon Glassb4d70702014-02-26 15:59:25 -0700128 debug("%s: offset:%u\n", __func__, offset);
Simon Glassb43d0442012-02-15 15:51:13 -0800129
Simon Glassb4d70702014-02-26 15:59:25 -0700130 return sandbox_gpio_get_value(dev, offset);
Simon Glassb43d0442012-02-15 15:51:13 -0800131}
132
Simon Glassb4d70702014-02-26 15:59:25 -0700133/* write GPIO OUT value to port 'offset' */
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200134static int sb_gpio_set_value(struct udevice *dev, unsigned offset, int value)
Simon Glassb43d0442012-02-15 15:51:13 -0800135{
Simon Glassb4d70702014-02-26 15:59:25 -0700136 debug("%s: offset:%u, value = %d\n", __func__, offset, value);
Simon Glassb43d0442012-02-15 15:51:13 -0800137
Simon Glassb4d70702014-02-26 15:59:25 -0700138 if (!sandbox_gpio_get_direction(dev, offset)) {
139 printf("sandbox_gpio: error: set_value on input gpio %u\n",
140 offset);
Simon Glassb43d0442012-02-15 15:51:13 -0800141 return -1;
142 }
143
Simon Glassb4d70702014-02-26 15:59:25 -0700144 return sandbox_gpio_set_value(dev, offset, value);
Simon Glassb43d0442012-02-15 15:51:13 -0800145}
146
Simon Glass32048632014-10-04 11:29:45 -0600147static int sb_gpio_get_function(struct udevice *dev, unsigned offset)
148{
Patrick Delaunay28bdaa52020-01-13 11:35:14 +0100149 if (get_gpio_flag(dev, offset, GPIOD_IS_OUT))
Simon Glass32048632014-10-04 11:29:45 -0600150 return GPIOF_OUTPUT;
Patrick Delaunay28bdaa52020-01-13 11:35:14 +0100151 if (get_gpio_flag(dev, offset, GPIOD_IS_IN))
152 return GPIOF_INPUT;
153
154 return GPIOF_INPUT; /*GPIO is not configurated */
Simon Glass32048632014-10-04 11:29:45 -0600155}
156
Simon Glass16e10402015-01-05 20:05:29 -0700157static int sb_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
Simon Glass12faa022017-05-18 20:09:18 -0600158 struct ofnode_phandle_args *args)
Simon Glass16e10402015-01-05 20:05:29 -0700159{
160 desc->offset = args->args[0];
161 if (args->args_count < 2)
162 return 0;
Patrick Delaunay23aee612020-01-13 11:35:13 +0100163 /* treat generic binding with gpio uclass */
164 gpio_xlate_offs_flags(dev, desc, args);
165
166 /* sandbox test specific, not defined in gpio.h */
167 if (args->args[1] & GPIO_IN)
Simon Glass16e10402015-01-05 20:05:29 -0700168 desc->flags |= GPIOD_IS_IN;
Patrick Delaunay28bdaa52020-01-13 11:35:14 +0100169
Patrick Delaunay23aee612020-01-13 11:35:13 +0100170 if (args->args[1] & GPIO_OUT)
Simon Glass16e10402015-01-05 20:05:29 -0700171 desc->flags |= GPIOD_IS_OUT;
Patrick Delaunay28bdaa52020-01-13 11:35:14 +0100172
Patrick Delaunay23aee612020-01-13 11:35:13 +0100173 if (args->args[1] & GPIO_OUT_ACTIVE)
Simon Glass16e10402015-01-05 20:05:29 -0700174 desc->flags |= GPIOD_IS_OUT_ACTIVE;
175
176 return 0;
177}
178
Patrick Delaunay28bdaa52020-01-13 11:35:14 +0100179static int sb_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
180 ulong flags)
181{
182 ulong *dir_flags;
183
184 debug("%s: offset:%u, dir_flags = %lx\n", __func__, offset, flags);
185
186 dir_flags = get_gpio_dir_flags(dev, offset);
187
188 *dir_flags = flags;
189
190 return 0;
191}
192
193static int sb_gpio_get_dir_flags(struct udevice *dev, unsigned int offset,
194 ulong *flags)
195{
196 debug("%s: offset:%u\n", __func__, offset);
197 *flags = *get_gpio_dir_flags(dev, offset);
198
199 return 0;
200}
201
Simon Glass3176b6c2020-07-07 13:11:44 -0600202#if CONFIG_IS_ENABLED(ACPIGEN)
203static int sb_gpio_get_acpi(const struct gpio_desc *desc,
204 struct acpi_gpio *gpio)
205{
206 int ret;
207
208 /* Note that gpio_get_acpi() zeroes *gpio before calling here */
209 gpio->pin_count = 1;
210 gpio->pins[0] = desc->offset;
211 ret = acpi_device_scope(desc->dev, gpio->resource,
212 sizeof(gpio->resource));
213 if (ret)
214 return log_ret(ret);
215
216 /* All of these values are just used for testing */
217 if (desc->flags & GPIOD_ACTIVE_LOW) {
218 gpio->pin0_addr = 0x80012 + desc->offset;
219 gpio->type = ACPI_GPIO_TYPE_INTERRUPT;
220 gpio->pull = ACPI_GPIO_PULL_DOWN;
221 gpio->interrupt_debounce_timeout = 4321;
222
223 /* We use the GpioInt part */
224 gpio->irq.pin = desc->offset;
225 gpio->irq.polarity = ACPI_IRQ_ACTIVE_BOTH;
226 gpio->irq.shared = ACPI_IRQ_SHARED;
227 gpio->irq.wake = ACPI_IRQ_WAKE;
228
229 /* The GpioIo part is only used for testing */
230 gpio->polarity = ACPI_GPIO_ACTIVE_LOW;
231 } else {
232 gpio->pin0_addr = 0xc00dc + desc->offset;
233 gpio->type = ACPI_GPIO_TYPE_IO;
234 gpio->pull = ACPI_GPIO_PULL_UP;
235 gpio->interrupt_debounce_timeout = 0;
236
237 /* The GpioInt part is not used */
238
239 /* We use the GpioIo part */
240 gpio->output_drive_strength = 1234;
241 gpio->io_shared = true;
242 gpio->io_restrict = ACPI_GPIO_IO_RESTRICT_INPUT;
243 gpio->polarity = 0;
244 }
245
246 return 0;
247}
248
249static int sb_gpio_get_name(const struct udevice *dev, char *out_name)
250{
251 return acpi_copy_name(out_name, "GPIO");
252}
253
254struct acpi_ops gpio_sandbox_acpi_ops = {
255 .get_name = sb_gpio_get_name,
256};
257#endif /* ACPIGEN */
258
Simon Glassb4d70702014-02-26 15:59:25 -0700259static const struct dm_gpio_ops gpio_sandbox_ops = {
Simon Glassb4d70702014-02-26 15:59:25 -0700260 .direction_input = sb_gpio_direction_input,
261 .direction_output = sb_gpio_direction_output,
262 .get_value = sb_gpio_get_value,
263 .set_value = sb_gpio_set_value,
Simon Glass32048632014-10-04 11:29:45 -0600264 .get_function = sb_gpio_get_function,
Simon Glass16e10402015-01-05 20:05:29 -0700265 .xlate = sb_gpio_xlate,
Patrick Delaunay28bdaa52020-01-13 11:35:14 +0100266 .set_dir_flags = sb_gpio_set_dir_flags,
267 .get_dir_flags = sb_gpio_get_dir_flags,
Simon Glass3176b6c2020-07-07 13:11:44 -0600268#if CONFIG_IS_ENABLED(ACPIGEN)
269 .get_acpi = sb_gpio_get_acpi,
270#endif
Simon Glassb4d70702014-02-26 15:59:25 -0700271};
272
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200273static int sandbox_gpio_ofdata_to_platdata(struct udevice *dev)
Simon Glassb43d0442012-02-15 15:51:13 -0800274{
Simon Glassde0977b2015-03-05 12:25:20 -0700275 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
Simon Glassb43d0442012-02-15 15:51:13 -0800276
Simon Glass9e7ab232018-02-03 10:36:59 -0700277 uc_priv->gpio_count = dev_read_u32_default(dev, "sandbox,gpio-count",
278 0);
Simon Glass1185fcb2017-05-18 20:09:20 -0600279 uc_priv->bank_name = dev_read_string(dev, "gpio-bank-name");
Simon Glassb43d0442012-02-15 15:51:13 -0800280
Simon Glassb4d70702014-02-26 15:59:25 -0700281 return 0;
282}
Simon Glassb43d0442012-02-15 15:51:13 -0800283
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200284static int gpio_sandbox_probe(struct udevice *dev)
Simon Glassb4d70702014-02-26 15:59:25 -0700285{
Simon Glassde0977b2015-03-05 12:25:20 -0700286 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
Simon Glassb4d70702014-02-26 15:59:25 -0700287
Simon Glass1185fcb2017-05-18 20:09:20 -0600288 if (!dev_of_valid(dev))
Simon Glassb4d70702014-02-26 15:59:25 -0700289 /* Tell the uclass how many GPIOs we have */
290 uc_priv->gpio_count = CONFIG_SANDBOX_GPIO_COUNT;
Simon Glassb4d70702014-02-26 15:59:25 -0700291
292 dev->priv = calloc(sizeof(struct gpio_state), uc_priv->gpio_count);
293
294 return 0;
Simon Glassb43d0442012-02-15 15:51:13 -0800295}
Simon Glassb4d70702014-02-26 15:59:25 -0700296
Simon Glassa367f1d2014-10-04 11:29:46 -0600297static int gpio_sandbox_remove(struct udevice *dev)
298{
299 free(dev->priv);
300
301 return 0;
302}
303
Simon Glass767827a2014-06-11 23:29:45 -0600304static const struct udevice_id sandbox_gpio_ids[] = {
Simon Glassb4d70702014-02-26 15:59:25 -0700305 { .compatible = "sandbox,gpio" },
306 { }
307};
308
Walter Lozano2901ac62020-06-25 01:10:04 -0300309U_BOOT_DRIVER(sandbox_gpio) = {
310 .name = "sandbox_gpio",
Simon Glassb4d70702014-02-26 15:59:25 -0700311 .id = UCLASS_GPIO,
312 .of_match = sandbox_gpio_ids,
313 .ofdata_to_platdata = sandbox_gpio_ofdata_to_platdata,
314 .probe = gpio_sandbox_probe,
Simon Glassa367f1d2014-10-04 11:29:46 -0600315 .remove = gpio_sandbox_remove,
Simon Glassb4d70702014-02-26 15:59:25 -0700316 .ops = &gpio_sandbox_ops,
Simon Glass3176b6c2020-07-07 13:11:44 -0600317 ACPI_OPS_PTR(&gpio_sandbox_acpi_ops)
Simon Glassb4d70702014-02-26 15:59:25 -0700318};
Patrick Delaunay1b4a22f2020-01-13 11:35:15 +0100319
Walter Lozano48e5b042020-06-25 01:10:06 -0300320U_BOOT_DRIVER_ALIAS(sandbox_gpio, sandbox_gpio_alias)
321
Patrick Delaunay1b4a22f2020-01-13 11:35:15 +0100322/* pincontrol: used only to check GPIO pin configuration (pinmux command) */
323
324struct sb_pinctrl_priv {
325 int pinctrl_ngpios;
326 struct list_head gpio_dev;
327};
328
329struct sb_gpio_bank {
330 struct udevice *gpio_dev;
331 struct list_head list;
332};
333
334static int sb_populate_gpio_dev_list(struct udevice *dev)
335{
336 struct sb_pinctrl_priv *priv = dev_get_priv(dev);
337 struct udevice *gpio_dev;
338 struct udevice *child;
339 struct sb_gpio_bank *gpio_bank;
340 int ret;
341
342 /*
343 * parse pin-controller sub-nodes (ie gpio bank nodes) and fill
344 * a list with all gpio device reference which belongs to the
345 * current pin-controller. This list is used to find pin_name and
346 * pin muxing
347 */
348 list_for_each_entry(child, &dev->child_head, sibling_node) {
349 ret = uclass_get_device_by_name(UCLASS_GPIO, child->name,
350 &gpio_dev);
351 if (ret < 0)
352 continue;
353
354 gpio_bank = malloc(sizeof(*gpio_bank));
355 if (!gpio_bank) {
356 dev_err(dev, "Not enough memory\n");
357 return -ENOMEM;
358 }
359
360 gpio_bank->gpio_dev = gpio_dev;
361 list_add_tail(&gpio_bank->list, &priv->gpio_dev);
362 }
363
364 return 0;
365}
366
367static int sb_pinctrl_get_pins_count(struct udevice *dev)
368{
369 struct sb_pinctrl_priv *priv = dev_get_priv(dev);
370 struct gpio_dev_priv *uc_priv;
371 struct sb_gpio_bank *gpio_bank;
372
373 /*
374 * if get_pins_count has already been executed once on this
375 * pin-controller, no need to run it again
376 */
377 if (priv->pinctrl_ngpios)
378 return priv->pinctrl_ngpios;
379
380 if (list_empty(&priv->gpio_dev))
381 sb_populate_gpio_dev_list(dev);
382 /*
383 * walk through all banks to retrieve the pin-controller
384 * pins number
385 */
386 list_for_each_entry(gpio_bank, &priv->gpio_dev, list) {
387 uc_priv = dev_get_uclass_priv(gpio_bank->gpio_dev);
388
389 priv->pinctrl_ngpios += uc_priv->gpio_count;
390 }
391
392 return priv->pinctrl_ngpios;
393}
394
395static struct udevice *sb_pinctrl_get_gpio_dev(struct udevice *dev,
396 unsigned int selector,
397 unsigned int *idx)
398{
399 struct sb_pinctrl_priv *priv = dev_get_priv(dev);
400 struct sb_gpio_bank *gpio_bank;
401 struct gpio_dev_priv *uc_priv;
402 int pin_count = 0;
403
404 if (list_empty(&priv->gpio_dev))
405 sb_populate_gpio_dev_list(dev);
406
407 /* look up for the bank which owns the requested pin */
408 list_for_each_entry(gpio_bank, &priv->gpio_dev, list) {
409 uc_priv = dev_get_uclass_priv(gpio_bank->gpio_dev);
410
411 if (selector < (pin_count + uc_priv->gpio_count)) {
412 /*
413 * we found the bank, convert pin selector to
414 * gpio bank index
415 */
416 *idx = selector - pin_count;
417
418 return gpio_bank->gpio_dev;
419 }
420 pin_count += uc_priv->gpio_count;
421 }
422
423 return NULL;
424}
425
426static const char *sb_pinctrl_get_pin_name(struct udevice *dev,
427 unsigned int selector)
428{
429 struct gpio_dev_priv *uc_priv;
430 struct udevice *gpio_dev;
431 unsigned int gpio_idx;
432 static char pin_name[PINNAME_SIZE];
433
434 /* look up for the bank which owns the requested pin */
435 gpio_dev = sb_pinctrl_get_gpio_dev(dev, selector, &gpio_idx);
436 if (!gpio_dev) {
437 snprintf(pin_name, PINNAME_SIZE, "Error");
438 } else {
439 uc_priv = dev_get_uclass_priv(gpio_dev);
440
441 snprintf(pin_name, PINNAME_SIZE, "%s%d",
442 uc_priv->bank_name,
443 gpio_idx);
444 }
445
446 return pin_name;
447}
448
449static char *get_dir_flags_string(ulong flags)
450{
451 if (flags & GPIOD_OPEN_DRAIN)
452 return "drive-open-drain";
453 if (flags & GPIOD_OPEN_SOURCE)
454 return "drive-open-source";
455 if (flags & GPIOD_PULL_UP)
456 return "bias-pull-up";
457 if (flags & GPIOD_PULL_DOWN)
458 return "bias-pull-down";
459 return ".";
460}
461
462static int sb_pinctrl_get_pin_muxing(struct udevice *dev,
463 unsigned int selector,
464 char *buf, int size)
465{
466 struct udevice *gpio_dev;
467 unsigned int gpio_idx;
468 ulong dir_flags;
469 int function;
470
471 /* look up for the bank which owns the requested pin */
472 gpio_dev = sb_pinctrl_get_gpio_dev(dev, selector, &gpio_idx);
473 if (!gpio_dev) {
474 snprintf(buf, size, "Error");
475 } else {
476 function = sb_gpio_get_function(gpio_dev, gpio_idx);
477 dir_flags = *get_gpio_dir_flags(gpio_dev, gpio_idx);
478
479 snprintf(buf, size, "gpio %s %s",
480 function == GPIOF_OUTPUT ? "output" : "input",
481 get_dir_flags_string(dir_flags));
482 }
483
484 return 0;
485}
Simon Glass3176b6c2020-07-07 13:11:44 -0600486
487#if CONFIG_IS_ENABLED(ACPIGEN)
488static int sb_pinctrl_get_name(const struct udevice *dev, char *out_name)
489{
490 return acpi_copy_name(out_name, "PINC");
491}
492#endif
Patrick Delaunay1b4a22f2020-01-13 11:35:15 +0100493
494static int sandbox_pinctrl_probe(struct udevice *dev)
495{
496 struct sb_pinctrl_priv *priv = dev_get_priv(dev);
497
498 INIT_LIST_HEAD(&priv->gpio_dev);
499
500 return 0;
501}
502
503static struct pinctrl_ops sandbox_pinctrl_gpio_ops = {
504 .get_pin_name = sb_pinctrl_get_pin_name,
505 .get_pins_count = sb_pinctrl_get_pins_count,
506 .get_pin_muxing = sb_pinctrl_get_pin_muxing,
507};
Simon Glass3176b6c2020-07-07 13:11:44 -0600508
509#if CONFIG_IS_ENABLED(ACPIGEN)
510struct acpi_ops pinctrl_sandbox_acpi_ops = {
511 .get_name = sb_pinctrl_get_name,
512};
513#endif
Patrick Delaunay1b4a22f2020-01-13 11:35:15 +0100514
515static const struct udevice_id sandbox_pinctrl_gpio_match[] = {
516 { .compatible = "sandbox,pinctrl-gpio" },
517 { /* sentinel */ }
518};
519
520U_BOOT_DRIVER(sandbox_pinctrl_gpio) = {
521 .name = "sandbox_pinctrl_gpio",
522 .id = UCLASS_PINCTRL,
523 .of_match = sandbox_pinctrl_gpio_match,
524 .ops = &sandbox_pinctrl_gpio_ops,
525 .bind = dm_scan_fdt_dev,
526 .probe = sandbox_pinctrl_probe,
527 .priv_auto_alloc_size = sizeof(struct sb_pinctrl_priv),
Simon Glass3176b6c2020-07-07 13:11:44 -0600528 ACPI_OPS_PTR(&pinctrl_sandbox_acpi_ops)
Patrick Delaunay1b4a22f2020-01-13 11:35:15 +0100529};