1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 2011 The Chromium OS Authors.
13 #include <dm/pinctrl.h>
14 #include <dt-bindings/gpio/gpio.h>
15 #include <dt-bindings/gpio/sandbox-gpio.h>
19 const char *label; /* label given by requester */
20 ulong dir_flags; /* dir_flags (GPIOD_...) */
23 /* Access routines for GPIO dir flags */
24 static ulong *get_gpio_dir_flags(struct udevice *dev, unsigned int offset)
26 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
27 struct gpio_state *state = dev_get_priv(dev);
29 if (offset >= uc_priv->gpio_count) {
30 static ulong invalid_dir_flags;
31 printf("sandbox_gpio: error: invalid gpio %u\n", offset);
32 return &invalid_dir_flags;
35 return &state[offset].dir_flags;
39 static int get_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag)
41 return (*get_gpio_dir_flags(dev, offset) & flag) != 0;
44 static int set_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag,
47 ulong *gpio = get_gpio_dir_flags(dev, offset);
58 * Back-channel sandbox-internal-only access to GPIO state
61 int sandbox_gpio_get_value(struct udevice *dev, unsigned offset)
63 if (get_gpio_flag(dev, offset, GPIOD_IS_OUT))
64 debug("sandbox_gpio: get_value on output gpio %u\n", offset);
65 return get_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE);
68 int sandbox_gpio_set_value(struct udevice *dev, unsigned offset, int value)
70 return set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE, value);
73 int sandbox_gpio_get_direction(struct udevice *dev, unsigned offset)
75 return get_gpio_flag(dev, offset, GPIOD_IS_OUT);
78 int sandbox_gpio_set_direction(struct udevice *dev, unsigned offset, int output)
80 set_gpio_flag(dev, offset, GPIOD_IS_OUT, output);
81 set_gpio_flag(dev, offset, GPIOD_IS_IN, !(output));
86 ulong sandbox_gpio_get_dir_flags(struct udevice *dev, unsigned int offset)
88 return *get_gpio_dir_flags(dev, offset);
91 int sandbox_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
94 *get_gpio_dir_flags(dev, offset) = flags;
100 * These functions implement the public interface within U-Boot
103 /* set GPIO port 'offset' as an input */
104 static int sb_gpio_direction_input(struct udevice *dev, unsigned offset)
106 debug("%s: offset:%u\n", __func__, offset);
108 return sandbox_gpio_set_direction(dev, offset, 0);
111 /* set GPIO port 'offset' as an output, with polarity 'value' */
112 static int sb_gpio_direction_output(struct udevice *dev, unsigned offset,
115 debug("%s: offset:%u, value = %d\n", __func__, offset, value);
117 return sandbox_gpio_set_direction(dev, offset, 1) |
118 sandbox_gpio_set_value(dev, offset, value);
121 /* read GPIO IN value of port 'offset' */
122 static int sb_gpio_get_value(struct udevice *dev, unsigned offset)
124 debug("%s: offset:%u\n", __func__, offset);
126 return sandbox_gpio_get_value(dev, offset);
129 /* write GPIO OUT value to port 'offset' */
130 static int sb_gpio_set_value(struct udevice *dev, unsigned offset, int value)
132 debug("%s: offset:%u, value = %d\n", __func__, offset, value);
134 if (!sandbox_gpio_get_direction(dev, offset)) {
135 printf("sandbox_gpio: error: set_value on input gpio %u\n",
140 return sandbox_gpio_set_value(dev, offset, value);
143 static int sb_gpio_get_function(struct udevice *dev, unsigned offset)
145 if (get_gpio_flag(dev, offset, GPIOD_IS_OUT))
147 if (get_gpio_flag(dev, offset, GPIOD_IS_IN))
150 return GPIOF_INPUT; /*GPIO is not configurated */
153 static int sb_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
154 struct ofnode_phandle_args *args)
156 desc->offset = args->args[0];
157 if (args->args_count < 2)
159 /* treat generic binding with gpio uclass */
160 gpio_xlate_offs_flags(dev, desc, args);
162 /* sandbox test specific, not defined in gpio.h */
163 if (args->args[1] & GPIO_IN)
164 desc->flags |= GPIOD_IS_IN;
166 if (args->args[1] & GPIO_OUT)
167 desc->flags |= GPIOD_IS_OUT;
169 if (args->args[1] & GPIO_OUT_ACTIVE)
170 desc->flags |= GPIOD_IS_OUT_ACTIVE;
175 static int sb_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
180 debug("%s: offset:%u, dir_flags = %lx\n", __func__, offset, flags);
182 dir_flags = get_gpio_dir_flags(dev, offset);
189 static int sb_gpio_get_dir_flags(struct udevice *dev, unsigned int offset,
192 debug("%s: offset:%u\n", __func__, offset);
193 *flags = *get_gpio_dir_flags(dev, offset);
198 static const struct dm_gpio_ops gpio_sandbox_ops = {
199 .direction_input = sb_gpio_direction_input,
200 .direction_output = sb_gpio_direction_output,
201 .get_value = sb_gpio_get_value,
202 .set_value = sb_gpio_set_value,
203 .get_function = sb_gpio_get_function,
204 .xlate = sb_gpio_xlate,
205 .set_dir_flags = sb_gpio_set_dir_flags,
206 .get_dir_flags = sb_gpio_get_dir_flags,
209 static int sandbox_gpio_ofdata_to_platdata(struct udevice *dev)
211 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
213 uc_priv->gpio_count = dev_read_u32_default(dev, "sandbox,gpio-count",
215 uc_priv->bank_name = dev_read_string(dev, "gpio-bank-name");
220 static int gpio_sandbox_probe(struct udevice *dev)
222 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
224 if (!dev_of_valid(dev))
225 /* Tell the uclass how many GPIOs we have */
226 uc_priv->gpio_count = CONFIG_SANDBOX_GPIO_COUNT;
228 dev->priv = calloc(sizeof(struct gpio_state), uc_priv->gpio_count);
233 static int gpio_sandbox_remove(struct udevice *dev)
240 static const struct udevice_id sandbox_gpio_ids[] = {
241 { .compatible = "sandbox,gpio" },
245 U_BOOT_DRIVER(gpio_sandbox) = {
246 .name = "gpio_sandbox",
248 .of_match = sandbox_gpio_ids,
249 .ofdata_to_platdata = sandbox_gpio_ofdata_to_platdata,
250 .probe = gpio_sandbox_probe,
251 .remove = gpio_sandbox_remove,
252 .ops = &gpio_sandbox_ops,