blob: 4234cd912c9f0277d5af80fec249a3028c8ecc03 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glass96495d92014-02-26 15:59:24 -07002/*
3 * Copyright (c) 2013 Google, Inc
Simon Glass96495d92014-02-26 15:59:24 -07004 */
5
Simon Glassbe04f1a2021-02-04 21:22:08 -07006#define LOG_CATEGORY UCLASS_GPIO
7
Simon Glass96495d92014-02-26 15:59:24 -07008#include <common.h>
9#include <dm.h>
Simon Glass48609d02021-08-07 07:24:12 -060010#include <dt-structs.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -060011#include <log.h>
Jean-Jacques Hiblotd4b722e2020-09-11 13:43:34 +053012#include <dm/devres.h>
13#include <dm/device_compat.h>
Heiko Schocher5fc7cf82019-06-12 06:11:46 +020014#include <dm/device-internal.h>
15#include <dm/lists.h>
16#include <dm/uclass-internal.h>
Eric Nelson6c880b72016-04-24 16:32:40 -070017#include <dt-bindings/gpio/gpio.h>
Simon Glass96495d92014-02-26 15:59:24 -070018#include <errno.h>
Simon Glass0dac4d52015-01-05 20:05:28 -070019#include <fdtdec.h>
Simon Glassb892d122014-10-04 11:29:42 -060020#include <malloc.h>
Simon Glass29126862020-07-07 13:11:44 -060021#include <acpi/acpi_device.h>
Simon Glass401d1c42020-10-30 21:38:53 -060022#include <asm/global_data.h>
Simon Glass96495d92014-02-26 15:59:24 -070023#include <asm/gpio.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -060024#include <dm/device_compat.h>
Masahiro Yamada84b8bf62016-01-24 23:27:48 +090025#include <linux/bug.h>
Simon Glassfe1ef502014-10-22 21:37:01 -060026#include <linux/ctype.h>
Simon Glass8a45b222021-02-04 21:22:09 -070027#include <linux/delay.h>
Simon Glass96495d92014-02-26 15:59:24 -070028
Simon Glass3669e0e2015-01-05 20:05:29 -070029DECLARE_GLOBAL_DATA_PTR;
30
Marek Vasutaaf5b592023-08-02 01:26:02 +020031#define GPIO_ALLOC_BITS 32
32
Simon Glass96495d92014-02-26 15:59:24 -070033/**
Patrick Delaunay9f2b0662020-01-13 11:35:01 +010034 * gpio_desc_init() - Initialize the GPIO descriptor
35 *
36 * @desc: GPIO descriptor to initialize
37 * @dev: GPIO device
38 * @offset: Offset of device GPIO
39 */
40static void gpio_desc_init(struct gpio_desc *desc,
41 struct udevice *dev,
42 uint offset)
43{
44 desc->dev = dev;
45 desc->offset = offset;
46 desc->flags = 0;
47}
48
49/**
Simon Glass96495d92014-02-26 15:59:24 -070050 * gpio_to_device() - Convert global GPIO number to device, number
Simon Glass96495d92014-02-26 15:59:24 -070051 *
52 * Convert the GPIO number to an entry in the list of GPIOs
53 * or GPIO blocks registered with the GPIO controller. Returns
54 * entry on success, NULL on error.
Simon Glassae7123f2015-01-05 20:05:27 -070055 *
56 * @gpio: The numeric representation of the GPIO
57 * @desc: Returns description (desc->flags will always be 0)
Heinrich Schuchardt185f8122022-01-19 18:05:50 +010058 * Return: 0 if found, -ENOENT if not found
Simon Glass96495d92014-02-26 15:59:24 -070059 */
Simon Glassae7123f2015-01-05 20:05:27 -070060static int gpio_to_device(unsigned int gpio, struct gpio_desc *desc)
Simon Glass96495d92014-02-26 15:59:24 -070061{
62 struct gpio_dev_priv *uc_priv;
Heiko Schocher54c5d082014-05-22 12:43:05 +020063 struct udevice *dev;
Simon Glass96495d92014-02-26 15:59:24 -070064
Michal Suchanek49549372022-10-12 21:58:08 +020065 for (uclass_first_device(UCLASS_GPIO, &dev);
Simon Glass96495d92014-02-26 15:59:24 -070066 dev;
Michal Suchanek49549372022-10-12 21:58:08 +020067 uclass_next_device(&dev)) {
Simon Glasse564f052015-03-05 12:25:20 -070068 uc_priv = dev_get_uclass_priv(dev);
Simon Glass96495d92014-02-26 15:59:24 -070069 if (gpio >= uc_priv->gpio_base &&
70 gpio < uc_priv->gpio_base + uc_priv->gpio_count) {
Patrick Delaunay9f2b0662020-01-13 11:35:01 +010071 gpio_desc_init(desc, dev, gpio - uc_priv->gpio_base);
Simon Glass96495d92014-02-26 15:59:24 -070072 return 0;
73 }
74 }
75
76 /* No such GPIO */
Michal Suchanek49549372022-10-12 21:58:08 +020077 return -ENOENT;
Simon Glass96495d92014-02-26 15:59:24 -070078}
79
Marek Vasutaaf5b592023-08-02 01:26:02 +020080/**
81 * gpio_is_claimed() - Test whether GPIO is claimed by consumer
82 *
83 * Test whether GPIO is claimed by consumer already.
84 *
85 * @uc_priv: gpio_dev_priv pointer.
86 * @offset: gpio offset within the device
87 * @return: true if claimed, false if not claimed
88 */
89static bool gpio_is_claimed(struct gpio_dev_priv *uc_priv, unsigned int offset)
90{
91 return !!(uc_priv->claimed[offset / GPIO_ALLOC_BITS] & BIT(offset % GPIO_ALLOC_BITS));
92}
93
94/**
95 * gpio_set_claim() - Set GPIO claimed by consumer
96 *
97 * Set a bit which indicate the GPIO is claimed by consumer
98 *
99 * @uc_priv: gpio_dev_priv pointer.
100 * @offset: gpio offset within the device
101 */
102static void gpio_set_claim(struct gpio_dev_priv *uc_priv, unsigned int offset)
103{
104 uc_priv->claimed[offset / GPIO_ALLOC_BITS] |= BIT(offset % GPIO_ALLOC_BITS);
105}
106
107/**
108 * gpio_clear_claim() - Clear GPIO claimed by consumer
109 *
110 * Clear a bit which indicate the GPIO is claimed by consumer
111 *
112 * @uc_priv: gpio_dev_priv pointer.
113 * @offset: gpio offset within the device
114 */
115static void gpio_clear_claim(struct gpio_dev_priv *uc_priv, unsigned int offset)
116{
117 uc_priv->claimed[offset / GPIO_ALLOC_BITS] &= ~BIT(offset % GPIO_ALLOC_BITS);
118}
119
Heiko Schocher2bd261d2020-05-22 11:08:59 +0200120#if CONFIG_IS_ENABLED(DM_GPIO_LOOKUP_LABEL)
121/**
122 * dm_gpio_lookup_label() - look for name in gpio device
123 *
124 * search in uc_priv, if there is a gpio with labelname same
125 * as name.
126 *
127 * @name: name which is searched
128 * @uc_priv: gpio_dev_priv pointer.
129 * @offset: gpio offset within the device
130 * @return: 0 if found, -ENOENT if not.
131 */
132static int dm_gpio_lookup_label(const char *name,
133 struct gpio_dev_priv *uc_priv, ulong *offset)
134{
Heiko Schocher2bd261d2020-05-22 11:08:59 +0200135 int i;
136
137 *offset = -1;
Heiko Schocher2bd261d2020-05-22 11:08:59 +0200138 for (i = 0; i < uc_priv->gpio_count; i++) {
Marek Vasutaaf5b592023-08-02 01:26:02 +0200139 if (!gpio_is_claimed(uc_priv, i))
Heiko Schocher2bd261d2020-05-22 11:08:59 +0200140 continue;
Rasmus Villemoes10e66442022-10-03 11:02:45 +0200141 if (!strcmp(name, uc_priv->name[i])) {
Heiko Schocher2bd261d2020-05-22 11:08:59 +0200142 *offset = i;
143 return 0;
144 }
145 }
146 return -ENOENT;
147}
148#else
149static int
150dm_gpio_lookup_label(const char *name, struct gpio_dev_priv *uc_priv,
151 ulong *offset)
152{
153 return -ENOENT;
154}
155#endif
156
Simon Glass32ec1592015-06-23 15:38:40 -0600157int dm_gpio_lookup_name(const char *name, struct gpio_desc *desc)
Simon Glass96495d92014-02-26 15:59:24 -0700158{
Simon Glassfe1ef502014-10-22 21:37:01 -0600159 struct gpio_dev_priv *uc_priv = NULL;
Heiko Schocher54c5d082014-05-22 12:43:05 +0200160 struct udevice *dev;
Simon Glassfe1ef502014-10-22 21:37:01 -0600161 ulong offset;
162 int numeric;
Simon Glass96495d92014-02-26 15:59:24 -0700163
Simon Glass0b1284e2021-07-24 09:03:30 -0600164 numeric = isdigit(*name) ? dectoul(name, NULL) : -1;
Michal Suchanek49549372022-10-12 21:58:08 +0200165 for (uclass_first_device(UCLASS_GPIO, &dev);
Simon Glass96495d92014-02-26 15:59:24 -0700166 dev;
Michal Suchanek49549372022-10-12 21:58:08 +0200167 uclass_next_device(&dev)) {
Simon Glass96495d92014-02-26 15:59:24 -0700168 int len;
169
Simon Glasse564f052015-03-05 12:25:20 -0700170 uc_priv = dev_get_uclass_priv(dev);
Simon Glassfe1ef502014-10-22 21:37:01 -0600171 if (numeric != -1) {
172 offset = numeric - uc_priv->gpio_base;
173 /* Allow GPIOs to be numbered from 0 */
Tom Rini75897912017-05-10 15:20:15 -0400174 if (offset < uc_priv->gpio_count)
Simon Glassfe1ef502014-10-22 21:37:01 -0600175 break;
176 }
177
Simon Glass96495d92014-02-26 15:59:24 -0700178 len = uc_priv->bank_name ? strlen(uc_priv->bank_name) : 0;
179
Simon Glass939cda52014-06-11 23:29:47 -0600180 if (!strncasecmp(name, uc_priv->bank_name, len)) {
Simon Glassfe1ef502014-10-22 21:37:01 -0600181 if (!strict_strtoul(name + len, 10, &offset))
Samuel Holland390ccff2021-09-11 17:05:51 -0500182 if (offset < uc_priv->gpio_count)
183 break;
Simon Glass96495d92014-02-26 15:59:24 -0700184 }
Heiko Schocher2bd261d2020-05-22 11:08:59 +0200185
186 /*
187 * if we did not found a gpio through its bank
188 * name, we search for a valid gpio label.
189 */
190 if (!dm_gpio_lookup_label(name, uc_priv, &offset))
191 break;
Simon Glass96495d92014-02-26 15:59:24 -0700192 }
193
Simon Glassfe1ef502014-10-22 21:37:01 -0600194 if (!dev)
Michal Suchanek49549372022-10-12 21:58:08 +0200195 return -EINVAL;
Simon Glassfe1ef502014-10-22 21:37:01 -0600196
Patrick Delaunay9f2b0662020-01-13 11:35:01 +0100197 gpio_desc_init(desc, dev, offset);
Simon Glass32ec1592015-06-23 15:38:40 -0600198
199 return 0;
200}
201
202int gpio_lookup_name(const char *name, struct udevice **devp,
203 unsigned int *offsetp, unsigned int *gpiop)
204{
205 struct gpio_desc desc;
206 int ret;
207
Simon Glassfe1ef502014-10-22 21:37:01 -0600208 if (devp)
Simon Glass32ec1592015-06-23 15:38:40 -0600209 *devp = NULL;
210 ret = dm_gpio_lookup_name(name, &desc);
211 if (ret)
212 return ret;
213
214 if (devp)
215 *devp = desc.dev;
Simon Glassfe1ef502014-10-22 21:37:01 -0600216 if (offsetp)
Simon Glass32ec1592015-06-23 15:38:40 -0600217 *offsetp = desc.offset;
218 if (gpiop) {
219 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(desc.dev);
220
221 *gpiop = uc_priv->gpio_base + desc.offset;
222 }
Simon Glassfe1ef502014-10-22 21:37:01 -0600223
224 return 0;
Simon Glass96495d92014-02-26 15:59:24 -0700225}
226
Samuel Holland8a479822021-09-11 17:05:53 -0500227unsigned long gpio_flags_xlate(uint32_t arg)
228{
229 unsigned long flags = 0;
230
231 if (arg & GPIO_ACTIVE_LOW)
232 flags |= GPIOD_ACTIVE_LOW;
233
234 /*
235 * need to test 2 bits for gpio output binding:
236 * OPEN_DRAIN (0x6) = SINGLE_ENDED (0x2) | LINE_OPEN_DRAIN (0x4)
237 * OPEN_SOURCE (0x2) = SINGLE_ENDED (0x2) | LINE_OPEN_SOURCE (0x0)
238 */
239 if (arg & GPIO_SINGLE_ENDED) {
240 if (arg & GPIO_LINE_OPEN_DRAIN)
241 flags |= GPIOD_OPEN_DRAIN;
242 else
243 flags |= GPIOD_OPEN_SOURCE;
244 }
245
246 if (arg & GPIO_PULL_UP)
247 flags |= GPIOD_PULL_UP;
248
249 if (arg & GPIO_PULL_DOWN)
250 flags |= GPIOD_PULL_DOWN;
251
252 return flags;
253}
254
Simon Glass3a571232017-05-18 20:09:18 -0600255int gpio_xlate_offs_flags(struct udevice *dev, struct gpio_desc *desc,
256 struct ofnode_phandle_args *args)
Eric Nelson6c880b72016-04-24 16:32:40 -0700257{
Samuel Holland37c10bf2021-09-11 17:05:52 -0500258 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
259
Eric Nelson6c880b72016-04-24 16:32:40 -0700260 if (args->args_count < 1)
261 return -EINVAL;
262
263 desc->offset = args->args[0];
Samuel Holland37c10bf2021-09-11 17:05:52 -0500264 if (desc->offset >= uc_priv->gpio_count)
265 return -EINVAL;
Eric Nelson6c880b72016-04-24 16:32:40 -0700266
267 if (args->args_count < 2)
268 return 0;
269
Samuel Holland8a479822021-09-11 17:05:53 -0500270 desc->flags = gpio_flags_xlate(args->args[1]);
Patrick Delaunay477ca572020-01-13 11:35:07 +0100271
Eric Nelson6c880b72016-04-24 16:32:40 -0700272 return 0;
273}
274
Simon Glass3669e0e2015-01-05 20:05:29 -0700275static int gpio_find_and_xlate(struct gpio_desc *desc,
Simon Glass3a571232017-05-18 20:09:18 -0600276 struct ofnode_phandle_args *args)
Simon Glass0dac4d52015-01-05 20:05:28 -0700277{
Simon Glass3d647742021-02-04 21:22:05 -0700278 const struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
Simon Glass0dac4d52015-01-05 20:05:28 -0700279
Eric Nelson6c880b72016-04-24 16:32:40 -0700280 if (ops->xlate)
281 return ops->xlate(desc->dev, desc, args);
Simon Glass0dac4d52015-01-05 20:05:28 -0700282 else
Eric Nelson6c880b72016-04-24 16:32:40 -0700283 return gpio_xlate_offs_flags(desc->dev, desc, args);
Simon Glass0dac4d52015-01-05 20:05:28 -0700284}
285
Simon Glass48609d02021-08-07 07:24:12 -0600286#if CONFIG_IS_ENABLED(GPIO_HOG)
Heiko Schocher5fc7cf82019-06-12 06:11:46 +0200287
288struct gpio_hog_priv {
289 struct gpio_desc gpiod;
290};
291
292struct gpio_hog_data {
293 int gpiod_flags;
294 int value;
295 u32 val[2];
296};
297
Simon Glassd1998a92020-12-03 16:55:21 -0700298static int gpio_hog_of_to_plat(struct udevice *dev)
Heiko Schocher5fc7cf82019-06-12 06:11:46 +0200299{
Simon Glassc69cda22020-12-03 16:55:20 -0700300 struct gpio_hog_data *plat = dev_get_plat(dev);
Heiko Schocher5fc7cf82019-06-12 06:11:46 +0200301 const char *nodename;
302 int ret;
303
304 plat->value = 0;
305 if (dev_read_bool(dev, "input")) {
306 plat->gpiod_flags = GPIOD_IS_IN;
307 } else if (dev_read_bool(dev, "output-high")) {
308 plat->value = 1;
309 plat->gpiod_flags = GPIOD_IS_OUT;
310 } else if (dev_read_bool(dev, "output-low")) {
311 plat->gpiod_flags = GPIOD_IS_OUT;
312 } else {
313 printf("%s: missing gpio-hog state.\n", __func__);
314 return -EINVAL;
315 }
316 ret = dev_read_u32_array(dev, "gpios", plat->val, 2);
317 if (ret) {
318 printf("%s: wrong gpios property, 2 values needed %d\n",
319 __func__, ret);
320 return ret;
321 }
322 nodename = dev_read_string(dev, "line-name");
Heiko Schocher49b10cb2019-07-17 06:59:51 +0200323 if (nodename)
324 device_set_name(dev, nodename);
Heiko Schocher5fc7cf82019-06-12 06:11:46 +0200325
326 return 0;
327}
328
329static int gpio_hog_probe(struct udevice *dev)
330{
Simon Glassc69cda22020-12-03 16:55:20 -0700331 struct gpio_hog_data *plat = dev_get_plat(dev);
Heiko Schocher5fc7cf82019-06-12 06:11:46 +0200332 struct gpio_hog_priv *priv = dev_get_priv(dev);
333 int ret;
334
335 ret = gpio_dev_request_index(dev->parent, dev->name, "gpio-hog",
336 plat->val[0], plat->gpiod_flags,
337 plat->val[1], &priv->gpiod);
338 if (ret < 0) {
339 debug("%s: node %s could not get gpio.\n", __func__,
340 dev->name);
341 return ret;
342 }
Heiko Schocher49b10cb2019-07-17 06:59:51 +0200343
344 if (plat->gpiod_flags == GPIOD_IS_OUT) {
345 ret = dm_gpio_set_value(&priv->gpiod, plat->value);
346 if (ret < 0) {
347 debug("%s: node %s could not set gpio.\n", __func__,
348 dev->name);
349 return ret;
350 }
351 }
Heiko Schocher5fc7cf82019-06-12 06:11:46 +0200352
353 return 0;
354}
355
Heiko Schocher49b10cb2019-07-17 06:59:51 +0200356int gpio_hog_lookup_name(const char *name, struct gpio_desc **desc)
Heiko Schocher5fc7cf82019-06-12 06:11:46 +0200357{
358 struct udevice *dev;
359
Heiko Schocher49b10cb2019-07-17 06:59:51 +0200360 *desc = NULL;
Heiko Schocher5fc7cf82019-06-12 06:11:46 +0200361 if (!uclass_get_device_by_name(UCLASS_NOP, name, &dev)) {
362 struct gpio_hog_priv *priv = dev_get_priv(dev);
363
Heiko Schocher49b10cb2019-07-17 06:59:51 +0200364 *desc = &priv->gpiod;
365 return 0;
Heiko Schocher5fc7cf82019-06-12 06:11:46 +0200366 }
367
Heiko Schocher49b10cb2019-07-17 06:59:51 +0200368 return -ENODEV;
Heiko Schocher5fc7cf82019-06-12 06:11:46 +0200369}
370
371U_BOOT_DRIVER(gpio_hog) = {
372 .name = "gpio_hog",
373 .id = UCLASS_NOP,
Simon Glassd1998a92020-12-03 16:55:21 -0700374 .of_to_plat = gpio_hog_of_to_plat,
Heiko Schocher5fc7cf82019-06-12 06:11:46 +0200375 .probe = gpio_hog_probe,
Simon Glass41575d82020-12-03 16:55:17 -0700376 .priv_auto = sizeof(struct gpio_hog_priv),
Simon Glasscaa4daa2020-12-03 16:55:18 -0700377 .plat_auto = sizeof(struct gpio_hog_data),
Heiko Schocher5fc7cf82019-06-12 06:11:46 +0200378};
379#else
Heiko Schocher49b10cb2019-07-17 06:59:51 +0200380int gpio_hog_lookup_name(const char *name, struct gpio_desc **desc)
Heiko Schocher5fc7cf82019-06-12 06:11:46 +0200381{
Heiko Schocher49b10cb2019-07-17 06:59:51 +0200382 return 0;
Heiko Schocher5fc7cf82019-06-12 06:11:46 +0200383}
384#endif
385
Simon Glassefa677f2015-06-23 15:38:41 -0600386int dm_gpio_request(struct gpio_desc *desc, const char *label)
Simon Glassae7123f2015-01-05 20:05:27 -0700387{
Simon Glass3d647742021-02-04 21:22:05 -0700388 const struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
Simon Glassae7123f2015-01-05 20:05:27 -0700389 struct udevice *dev = desc->dev;
390 struct gpio_dev_priv *uc_priv;
391 char *str;
392 int ret;
393
Simon Glasse564f052015-03-05 12:25:20 -0700394 uc_priv = dev_get_uclass_priv(dev);
Marek Vasutaaf5b592023-08-02 01:26:02 +0200395 if (gpio_is_claimed(uc_priv, desc->offset))
Simon Glassae7123f2015-01-05 20:05:27 -0700396 return -EBUSY;
397 str = strdup(label);
398 if (!str)
399 return -ENOMEM;
Simon Glass3d647742021-02-04 21:22:05 -0700400 if (ops->request) {
401 ret = ops->request(dev, desc->offset, label);
Simon Glassae7123f2015-01-05 20:05:27 -0700402 if (ret) {
403 free(str);
404 return ret;
405 }
406 }
Marek Vasutaaf5b592023-08-02 01:26:02 +0200407
408 gpio_set_claim(uc_priv, desc->offset);
Simon Glassae7123f2015-01-05 20:05:27 -0700409 uc_priv->name[desc->offset] = str;
410
411 return 0;
412}
413
Simon Glass3669e0e2015-01-05 20:05:29 -0700414static int dm_gpio_requestf(struct gpio_desc *desc, const char *fmt, ...)
415{
Simon Glass27084c02019-09-25 08:56:27 -0600416#if !defined(CONFIG_SPL_BUILD) || !CONFIG_IS_ENABLED(USE_TINY_PRINTF)
Simon Glass3669e0e2015-01-05 20:05:29 -0700417 va_list args;
418 char buf[40];
419
420 va_start(args, fmt);
421 vscnprintf(buf, sizeof(buf), fmt, args);
422 va_end(args);
423 return dm_gpio_request(desc, buf);
Simon Glass4dc52592015-12-29 05:22:48 -0700424#else
425 return dm_gpio_request(desc, fmt);
426#endif
Simon Glass3669e0e2015-01-05 20:05:29 -0700427}
428
Simon Glass96495d92014-02-26 15:59:24 -0700429/**
430 * gpio_request() - [COMPAT] Request GPIO
431 * gpio: GPIO number
432 * label: Name for the requested GPIO
433 *
Simon Glassb892d122014-10-04 11:29:42 -0600434 * The label is copied and allocated so the caller does not need to keep
435 * the pointer around.
436 *
Simon Glass96495d92014-02-26 15:59:24 -0700437 * This function implements the API that's compatible with current
438 * GPIO API used in U-Boot. The request is forwarded to particular
439 * GPIO driver. Returns 0 on success, negative value on error.
440 */
441int gpio_request(unsigned gpio, const char *label)
442{
Simon Glassae7123f2015-01-05 20:05:27 -0700443 struct gpio_desc desc;
Simon Glass96495d92014-02-26 15:59:24 -0700444 int ret;
445
Simon Glassae7123f2015-01-05 20:05:27 -0700446 ret = gpio_to_device(gpio, &desc);
Simon Glass96495d92014-02-26 15:59:24 -0700447 if (ret)
448 return ret;
449
Simon Glassae7123f2015-01-05 20:05:27 -0700450 return dm_gpio_request(&desc, label);
Simon Glass96495d92014-02-26 15:59:24 -0700451}
452
453/**
Simon Glassd44f5972014-10-04 11:29:49 -0600454 * gpio_requestf() - [COMPAT] Request GPIO
455 * @gpio: GPIO number
456 * @fmt: Format string for the requested GPIO
457 * @...: Arguments for the printf() format string
458 *
459 * This function implements the API that's compatible with current
460 * GPIO API used in U-Boot. The request is forwarded to particular
461 * GPIO driver. Returns 0 on success, negative value on error.
462 */
463int gpio_requestf(unsigned gpio, const char *fmt, ...)
464{
Simon Glass27084c02019-09-25 08:56:27 -0600465#if !defined(CONFIG_SPL_BUILD) || !CONFIG_IS_ENABLED(USE_TINY_PRINTF)
Simon Glassd44f5972014-10-04 11:29:49 -0600466 va_list args;
467 char buf[40];
468
469 va_start(args, fmt);
470 vscnprintf(buf, sizeof(buf), fmt, args);
471 va_end(args);
472 return gpio_request(gpio, buf);
Simon Glass4dc52592015-12-29 05:22:48 -0700473#else
474 return gpio_request(gpio, fmt);
475#endif
Simon Glassd44f5972014-10-04 11:29:49 -0600476}
477
Simon Glassae7123f2015-01-05 20:05:27 -0700478int _dm_gpio_free(struct udevice *dev, uint offset)
Simon Glass96495d92014-02-26 15:59:24 -0700479{
Simon Glass3d647742021-02-04 21:22:05 -0700480 const struct dm_gpio_ops *ops = gpio_get_ops(dev);
Simon Glassb892d122014-10-04 11:29:42 -0600481 struct gpio_dev_priv *uc_priv;
Simon Glass96495d92014-02-26 15:59:24 -0700482 int ret;
483
Simon Glasse564f052015-03-05 12:25:20 -0700484 uc_priv = dev_get_uclass_priv(dev);
Marek Vasutaaf5b592023-08-02 01:26:02 +0200485 if (!gpio_is_claimed(uc_priv, offset))
Simon Glassb892d122014-10-04 11:29:42 -0600486 return -ENXIO;
Simon Glass3d647742021-02-04 21:22:05 -0700487 if (ops->rfree) {
488 ret = ops->rfree(dev, offset);
Simon Glassb892d122014-10-04 11:29:42 -0600489 if (ret)
490 return ret;
491 }
492
Marek Vasutaaf5b592023-08-02 01:26:02 +0200493 gpio_clear_claim(uc_priv, offset);
Simon Glassb892d122014-10-04 11:29:42 -0600494 free(uc_priv->name[offset]);
495 uc_priv->name[offset] = NULL;
496
497 return 0;
498}
499
Simon Glassae7123f2015-01-05 20:05:27 -0700500/**
501 * gpio_free() - [COMPAT] Relinquish GPIO
502 * gpio: GPIO number
503 *
504 * This function implements the API that's compatible with current
505 * GPIO API used in U-Boot. The request is forwarded to particular
506 * GPIO driver. Returns 0 on success, negative value on error.
507 */
508int gpio_free(unsigned gpio)
Simon Glassb892d122014-10-04 11:29:42 -0600509{
Simon Glassae7123f2015-01-05 20:05:27 -0700510 struct gpio_desc desc;
511 int ret;
Simon Glassb892d122014-10-04 11:29:42 -0600512
Simon Glassae7123f2015-01-05 20:05:27 -0700513 ret = gpio_to_device(gpio, &desc);
514 if (ret)
515 return ret;
516
517 return _dm_gpio_free(desc.dev, desc.offset);
518}
519
Simon Glass17c43f12016-03-06 19:27:51 -0700520static int check_reserved(const struct gpio_desc *desc, const char *func)
Simon Glassae7123f2015-01-05 20:05:27 -0700521{
Simon Glasseca48662015-07-02 18:16:16 -0600522 struct gpio_dev_priv *uc_priv;
Simon Glassae7123f2015-01-05 20:05:27 -0700523
Simon Glasseca48662015-07-02 18:16:16 -0600524 if (!dm_gpio_is_valid(desc))
525 return -ENOENT;
526
527 uc_priv = dev_get_uclass_priv(desc->dev);
Marek Vasutaaf5b592023-08-02 01:26:02 +0200528 if (!gpio_is_claimed(uc_priv, desc->offset)) {
Simon Glassb892d122014-10-04 11:29:42 -0600529 printf("%s: %s: error: gpio %s%d not reserved\n",
Simon Glassae7123f2015-01-05 20:05:27 -0700530 desc->dev->name, func,
531 uc_priv->bank_name ? uc_priv->bank_name : "",
532 desc->offset);
Simon Glassb892d122014-10-04 11:29:42 -0600533 return -EBUSY;
534 }
535
536 return 0;
Simon Glass96495d92014-02-26 15:59:24 -0700537}
538
539/**
540 * gpio_direction_input() - [COMPAT] Set GPIO direction to input
541 * gpio: GPIO number
542 *
543 * This function implements the API that's compatible with current
544 * GPIO API used in U-Boot. The request is forwarded to particular
545 * GPIO driver. Returns 0 on success, negative value on error.
546 */
547int gpio_direction_input(unsigned gpio)
548{
Simon Glassae7123f2015-01-05 20:05:27 -0700549 struct gpio_desc desc;
Simon Glass96495d92014-02-26 15:59:24 -0700550 int ret;
551
Simon Glassae7123f2015-01-05 20:05:27 -0700552 ret = gpio_to_device(gpio, &desc);
Simon Glass96495d92014-02-26 15:59:24 -0700553 if (ret)
554 return ret;
555
Simon Glassca1e1f52021-02-04 21:22:04 -0700556 return dm_gpio_clrset_flags(&desc, GPIOD_MASK_DIR, GPIOD_IS_IN);
Simon Glass96495d92014-02-26 15:59:24 -0700557}
558
559/**
560 * gpio_direction_output() - [COMPAT] Set GPIO direction to output and set value
561 * gpio: GPIO number
562 * value: Logical value to be set on the GPIO pin
563 *
564 * This function implements the API that's compatible with current
565 * GPIO API used in U-Boot. The request is forwarded to particular
566 * GPIO driver. Returns 0 on success, negative value on error.
567 */
568int gpio_direction_output(unsigned gpio, int value)
569{
Simon Glassae7123f2015-01-05 20:05:27 -0700570 struct gpio_desc desc;
Simon Glassca1e1f52021-02-04 21:22:04 -0700571 ulong flags;
Simon Glass96495d92014-02-26 15:59:24 -0700572 int ret;
573
Simon Glassae7123f2015-01-05 20:05:27 -0700574 ret = gpio_to_device(gpio, &desc);
Simon Glass96495d92014-02-26 15:59:24 -0700575 if (ret)
576 return ret;
577
Simon Glassca1e1f52021-02-04 21:22:04 -0700578 flags = GPIOD_IS_OUT;
579 if (value)
580 flags |= GPIOD_IS_OUT_ACTIVE;
581 return dm_gpio_clrset_flags(&desc, GPIOD_MASK_DIR, flags);
Simon Glassae7123f2015-01-05 20:05:27 -0700582}
583
Patrick Delaunay8a9140c2020-01-13 11:35:02 +0100584static int _gpio_get_value(const struct gpio_desc *desc)
Simon Glassae7123f2015-01-05 20:05:27 -0700585{
Simon Glass3d647742021-02-04 21:22:05 -0700586 const struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
Simon Glassae7123f2015-01-05 20:05:27 -0700587 int value;
Patrick Delaunay8a9140c2020-01-13 11:35:02 +0100588
Simon Glass3d647742021-02-04 21:22:05 -0700589 value = ops->get_value(desc->dev, desc->offset);
Patrick Delaunay8a9140c2020-01-13 11:35:02 +0100590
591 return desc->flags & GPIOD_ACTIVE_LOW ? !value : value;
592}
593
594int dm_gpio_get_value(const struct gpio_desc *desc)
595{
Simon Glassae7123f2015-01-05 20:05:27 -0700596 int ret;
597
598 ret = check_reserved(desc, "get_value");
599 if (ret)
600 return ret;
601
Patrick Delaunay8a9140c2020-01-13 11:35:02 +0100602 return _gpio_get_value(desc);
Simon Glassae7123f2015-01-05 20:05:27 -0700603}
604
Simon Glass17c43f12016-03-06 19:27:51 -0700605int dm_gpio_set_value(const struct gpio_desc *desc, int value)
Simon Glassae7123f2015-01-05 20:05:27 -0700606{
Simon Glass7e0a96d2021-02-04 21:22:03 -0700607 const struct dm_gpio_ops *ops;
Simon Glassae7123f2015-01-05 20:05:27 -0700608 int ret;
609
610 ret = check_reserved(desc, "set_value");
611 if (ret)
612 return ret;
613
614 if (desc->flags & GPIOD_ACTIVE_LOW)
615 value = !value;
Neil Armstrong47bd5332020-05-05 10:43:17 +0200616
Simon Glass7e0a96d2021-02-04 21:22:03 -0700617 /* GPIOD_ are directly managed by driver in set_flags */
618 ops = gpio_get_ops(desc->dev);
619 if (ops->set_flags) {
620 ulong flags = desc->flags;
621
622 if (value)
623 flags |= GPIOD_IS_OUT_ACTIVE;
624 else
625 flags &= ~GPIOD_IS_OUT_ACTIVE;
626 return ops->set_flags(desc->dev, desc->offset, flags);
627 }
628
Neil Armstrong47bd5332020-05-05 10:43:17 +0200629 /*
630 * Emulate open drain by not actively driving the line high or
631 * Emulate open source by not actively driving the line low
632 */
633 if ((desc->flags & GPIOD_OPEN_DRAIN && value) ||
634 (desc->flags & GPIOD_OPEN_SOURCE && !value))
Simon Glass7e0a96d2021-02-04 21:22:03 -0700635 return ops->direction_input(desc->dev, desc->offset);
Neil Armstrong47bd5332020-05-05 10:43:17 +0200636 else if (desc->flags & GPIOD_OPEN_DRAIN ||
637 desc->flags & GPIOD_OPEN_SOURCE)
Simon Glass7e0a96d2021-02-04 21:22:03 -0700638 return ops->direction_output(desc->dev, desc->offset, value);
Neil Armstrong47bd5332020-05-05 10:43:17 +0200639
Simon Glass7e0a96d2021-02-04 21:22:03 -0700640 ret = ops->set_value(desc->dev, desc->offset, value);
641 if (ret)
642 return ret;
643
Simon Glassae7123f2015-01-05 20:05:27 -0700644 return 0;
645}
646
Patrick Delaunay4292fb12020-01-13 11:35:04 +0100647/* check dir flags invalid configuration */
648static int check_dir_flags(ulong flags)
649{
650 if ((flags & GPIOD_IS_OUT) && (flags & GPIOD_IS_IN)) {
651 log_debug("%s: flags 0x%lx has GPIOD_IS_OUT and GPIOD_IS_IN\n",
652 __func__, flags);
653 return -EINVAL;
654 }
655
Patrick Delaunay477ca572020-01-13 11:35:07 +0100656 if ((flags & GPIOD_PULL_UP) && (flags & GPIOD_PULL_DOWN)) {
657 log_debug("%s: flags 0x%lx has GPIOD_PULL_UP and GPIOD_PULL_DOWN\n",
658 __func__, flags);
659 return -EINVAL;
660 }
661
662 if ((flags & GPIOD_OPEN_DRAIN) && (flags & GPIOD_OPEN_SOURCE)) {
663 log_debug("%s: flags 0x%lx has GPIOD_OPEN_DRAIN and GPIOD_OPEN_SOURCE\n",
664 __func__, flags);
665 return -EINVAL;
666 }
667
Patrick Delaunay4292fb12020-01-13 11:35:04 +0100668 return 0;
669}
670
Simon Glass7e0a96d2021-02-04 21:22:03 -0700671/**
672 * _dm_gpio_set_flags() - Send flags to the driver
673 *
674 * This uses the best available method to send the given flags to the driver.
675 * Note that if flags & GPIOD_ACTIVE_LOW, the driver sees the opposite value
676 * of GPIOD_IS_OUT_ACTIVE.
677 *
678 * @desc: GPIO description
679 * @flags: flags value to set
Heinrich Schuchardt185f8122022-01-19 18:05:50 +0100680 * Return: 0 if OK, -ve on error
Simon Glass7e0a96d2021-02-04 21:22:03 -0700681 */
Simon Glass13979fc2021-02-04 21:21:55 -0700682static int _dm_gpio_set_flags(struct gpio_desc *desc, ulong flags)
Simon Glassae7123f2015-01-05 20:05:27 -0700683{
684 struct udevice *dev = desc->dev;
Simon Glass3d647742021-02-04 21:22:05 -0700685 const struct dm_gpio_ops *ops = gpio_get_ops(dev);
Patrick Delaunay4292fb12020-01-13 11:35:04 +0100686 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
Patrick Delaunay788ea832020-01-13 11:35:03 +0100687 int ret = 0;
Simon Glassae7123f2015-01-05 20:05:27 -0700688
Patrick Delaunay4292fb12020-01-13 11:35:04 +0100689 ret = check_dir_flags(flags);
690 if (ret) {
691 dev_dbg(dev,
692 "%s error: set_dir_flags for gpio %s%d has invalid dir flags 0x%lx\n",
693 desc->dev->name,
694 uc_priv->bank_name ? uc_priv->bank_name : "",
695 desc->offset, flags);
696
697 return ret;
698 }
699
Simon Glass7e0a96d2021-02-04 21:22:03 -0700700 /* If active low, invert the output state */
701 if ((flags & (GPIOD_IS_OUT | GPIOD_ACTIVE_LOW)) ==
702 (GPIOD_IS_OUT | GPIOD_ACTIVE_LOW))
703 flags ^= GPIOD_IS_OUT_ACTIVE;
704
Simon Glass13979fc2021-02-04 21:21:55 -0700705 /* GPIOD_ are directly managed by driver in set_flags */
706 if (ops->set_flags) {
707 ret = ops->set_flags(dev, desc->offset, flags);
Patrick Delaunay8fd9daf2020-01-13 11:35:09 +0100708 } else {
709 if (flags & GPIOD_IS_OUT) {
Simon Glass7e0a96d2021-02-04 21:22:03 -0700710 bool value = flags & GPIOD_IS_OUT_ACTIVE;
711
712 ret = ops->direction_output(dev, desc->offset, value);
Patrick Delaunay8fd9daf2020-01-13 11:35:09 +0100713 } else if (flags & GPIOD_IS_IN) {
714 ret = ops->direction_input(dev, desc->offset);
715 }
Simon Glassae7123f2015-01-05 20:05:27 -0700716 }
Patrick Delaunay788ea832020-01-13 11:35:03 +0100717
718 return ret;
719}
720
Simon Glass7e0a96d2021-02-04 21:22:03 -0700721int dm_gpio_clrset_flags(struct gpio_desc *desc, ulong clr, ulong set)
Patrick Delaunay788ea832020-01-13 11:35:03 +0100722{
Simon Glass7e0a96d2021-02-04 21:22:03 -0700723 ulong flags;
Patrick Delaunay788ea832020-01-13 11:35:03 +0100724 int ret;
725
726 ret = check_reserved(desc, "set_dir_flags");
Simon Glassae7123f2015-01-05 20:05:27 -0700727 if (ret)
728 return ret;
Simon Glassae7123f2015-01-05 20:05:27 -0700729
Simon Glass7e0a96d2021-02-04 21:22:03 -0700730 flags = (desc->flags & ~clr) | set;
Patrick Delaunay788ea832020-01-13 11:35:03 +0100731
Simon Glass7e0a96d2021-02-04 21:22:03 -0700732 ret = _dm_gpio_set_flags(desc, flags);
733 if (ret)
734 return ret;
735
736 /* save the flags also in descriptor */
737 desc->flags = flags;
738
739 return 0;
740}
741
742int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
743{
744 /* combine the requested flags (for IN/OUT) and the descriptor flags */
745 return dm_gpio_clrset_flags(desc, GPIOD_MASK_DIR, flags);
Simon Glassae7123f2015-01-05 20:05:27 -0700746}
747
Simon Glass8a45b222021-02-04 21:22:09 -0700748int dm_gpios_clrset_flags(struct gpio_desc *desc, int count, ulong clr,
749 ulong set)
750{
751 int ret;
752 int i;
753
754 for (i = 0; i < count; i++) {
755 ret = dm_gpio_clrset_flags(&desc[i], clr, set);
756 if (ret)
757 return log_ret(ret);
758 }
759
760 return 0;
761}
762
Simon Glassc0c1e622021-02-04 21:21:57 -0700763int dm_gpio_get_flags(struct gpio_desc *desc, ulong *flagsp)
Patrick Delaunay695e5fd2020-01-13 11:35:06 +0100764{
Patrick Delaunayd2c07e52020-01-13 11:35:08 +0100765 struct udevice *dev = desc->dev;
766 int ret, value;
Simon Glass3d647742021-02-04 21:22:05 -0700767 const struct dm_gpio_ops *ops = gpio_get_ops(dev);
Simon Glass96487892021-02-04 21:21:56 -0700768 ulong flags;
Patrick Delaunay695e5fd2020-01-13 11:35:06 +0100769
Simon Glass96487892021-02-04 21:21:56 -0700770 ret = check_reserved(desc, "get_flags");
Patrick Delaunay695e5fd2020-01-13 11:35:06 +0100771 if (ret)
772 return ret;
773
Patrick Delaunayd2c07e52020-01-13 11:35:08 +0100774 /* GPIOD_ are directly provided by driver except GPIOD_ACTIVE_LOW */
Simon Glass96487892021-02-04 21:21:56 -0700775 if (ops->get_flags) {
776 ret = ops->get_flags(dev, desc->offset, &flags);
Patrick Delaunayd2c07e52020-01-13 11:35:08 +0100777 if (ret)
778 return ret;
Patrick Delaunay695e5fd2020-01-13 11:35:06 +0100779
Patrick Delaunayd2c07e52020-01-13 11:35:08 +0100780 /* GPIOD_ACTIVE_LOW is saved in desc->flags */
Simon Glass96487892021-02-04 21:21:56 -0700781 value = flags & GPIOD_IS_OUT_ACTIVE ? 1 : 0;
Patrick Delaunayd2c07e52020-01-13 11:35:08 +0100782 if (desc->flags & GPIOD_ACTIVE_LOW)
783 value = !value;
Simon Glass96487892021-02-04 21:21:56 -0700784 flags &= ~(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT_ACTIVE);
785 flags |= (desc->flags & GPIOD_ACTIVE_LOW);
Patrick Delaunayd2c07e52020-01-13 11:35:08 +0100786 if (value)
Simon Glass96487892021-02-04 21:21:56 -0700787 flags |= GPIOD_IS_OUT_ACTIVE;
Patrick Delaunayd2c07e52020-01-13 11:35:08 +0100788 } else {
Simon Glass96487892021-02-04 21:21:56 -0700789 flags = desc->flags;
Patrick Delaunayd2c07e52020-01-13 11:35:08 +0100790 /* only GPIOD_IS_OUT_ACTIVE is provided by uclass */
Simon Glass96487892021-02-04 21:21:56 -0700791 flags &= ~GPIOD_IS_OUT_ACTIVE;
Patrick Delaunayd2c07e52020-01-13 11:35:08 +0100792 if ((desc->flags & GPIOD_IS_OUT) && _gpio_get_value(desc))
Simon Glass96487892021-02-04 21:21:56 -0700793 flags |= GPIOD_IS_OUT_ACTIVE;
Patrick Delaunayd2c07e52020-01-13 11:35:08 +0100794 }
Simon Glass96487892021-02-04 21:21:56 -0700795 *flagsp = flags;
Patrick Delaunay695e5fd2020-01-13 11:35:06 +0100796
797 return 0;
798}
799
Simon Glass96495d92014-02-26 15:59:24 -0700800/**
801 * gpio_get_value() - [COMPAT] Sample GPIO pin and return it's value
802 * gpio: GPIO number
803 *
804 * This function implements the API that's compatible with current
805 * GPIO API used in U-Boot. The request is forwarded to particular
806 * GPIO driver. Returns the value of the GPIO pin, or negative value
807 * on error.
808 */
809int gpio_get_value(unsigned gpio)
810{
Simon Glass96495d92014-02-26 15:59:24 -0700811 int ret;
812
Simon Glassae7123f2015-01-05 20:05:27 -0700813 struct gpio_desc desc;
814
815 ret = gpio_to_device(gpio, &desc);
Simon Glass96495d92014-02-26 15:59:24 -0700816 if (ret)
817 return ret;
Simon Glassae7123f2015-01-05 20:05:27 -0700818 return dm_gpio_get_value(&desc);
Simon Glass96495d92014-02-26 15:59:24 -0700819}
820
821/**
822 * gpio_set_value() - [COMPAT] Configure logical value on GPIO pin
823 * gpio: GPIO number
824 * value: Logical value to be set on the GPIO pin.
825 *
826 * This function implements the API that's compatible with current
827 * GPIO API used in U-Boot. The request is forwarded to particular
828 * GPIO driver. Returns 0 on success, negative value on error.
829 */
830int gpio_set_value(unsigned gpio, int value)
831{
Simon Glassae7123f2015-01-05 20:05:27 -0700832 struct gpio_desc desc;
Simon Glass96495d92014-02-26 15:59:24 -0700833 int ret;
834
Simon Glassae7123f2015-01-05 20:05:27 -0700835 ret = gpio_to_device(gpio, &desc);
Simon Glass96495d92014-02-26 15:59:24 -0700836 if (ret)
837 return ret;
Simon Glassae7123f2015-01-05 20:05:27 -0700838 return dm_gpio_set_value(&desc, value);
Simon Glass96495d92014-02-26 15:59:24 -0700839}
840
Heiko Schocher54c5d082014-05-22 12:43:05 +0200841const char *gpio_get_bank_info(struct udevice *dev, int *bit_count)
Simon Glass96495d92014-02-26 15:59:24 -0700842{
843 struct gpio_dev_priv *priv;
844
845 /* Must be called on an active device */
Simon Glasse564f052015-03-05 12:25:20 -0700846 priv = dev_get_uclass_priv(dev);
Simon Glass96495d92014-02-26 15:59:24 -0700847 assert(priv);
848
849 *bit_count = priv->gpio_count;
850 return priv->bank_name;
851}
852
Simon Glass6449a502014-10-04 11:29:43 -0600853static const char * const gpio_function[GPIOF_COUNT] = {
854 "input",
855 "output",
856 "unused",
857 "unknown",
858 "func",
859};
860
Masahiro Yamadafb07f972017-06-22 16:50:25 +0900861static int get_function(struct udevice *dev, int offset, bool skip_unused,
862 const char **namep)
Simon Glass6449a502014-10-04 11:29:43 -0600863{
Simon Glasse564f052015-03-05 12:25:20 -0700864 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
Simon Glass3d647742021-02-04 21:22:05 -0700865 const struct dm_gpio_ops *ops = gpio_get_ops(dev);
Simon Glass6449a502014-10-04 11:29:43 -0600866
867 BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function));
868 if (!device_active(dev))
869 return -ENODEV;
870 if (offset < 0 || offset >= uc_priv->gpio_count)
871 return -EINVAL;
872 if (namep)
873 *namep = uc_priv->name[offset];
Marek Vasutaaf5b592023-08-02 01:26:02 +0200874 if (skip_unused && !gpio_is_claimed(uc_priv, offset))
Simon Glass6449a502014-10-04 11:29:43 -0600875 return GPIOF_UNUSED;
876 if (ops->get_function) {
877 int ret;
878
879 ret = ops->get_function(dev, offset);
880 if (ret < 0)
881 return ret;
882 if (ret >= ARRAY_SIZE(gpio_function))
883 return -ENODATA;
884 return ret;
885 }
886
887 return GPIOF_UNKNOWN;
888}
889
890int gpio_get_function(struct udevice *dev, int offset, const char **namep)
891{
892 return get_function(dev, offset, true, namep);
893}
894
895int gpio_get_raw_function(struct udevice *dev, int offset, const char **namep)
896{
897 return get_function(dev, offset, false, namep);
898}
899
Simon Glass07575352014-10-04 11:29:44 -0600900int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize)
901{
Simon Glass3d647742021-02-04 21:22:05 -0700902 const struct dm_gpio_ops *ops = gpio_get_ops(dev);
Simon Glass07575352014-10-04 11:29:44 -0600903 struct gpio_dev_priv *priv;
904 char *str = buf;
Patrice Chotardd7124f02022-08-30 14:09:11 +0200905 const char *label;
Simon Glass07575352014-10-04 11:29:44 -0600906 int func;
907 int ret;
908 int len;
Patrice Chotardd7124f02022-08-30 14:09:11 +0200909 bool used;
Simon Glass07575352014-10-04 11:29:44 -0600910
911 BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function));
912
913 *buf = 0;
Simon Glasse564f052015-03-05 12:25:20 -0700914 priv = dev_get_uclass_priv(dev);
Patrice Chotardd7124f02022-08-30 14:09:11 +0200915 ret = gpio_get_raw_function(dev, offset, &label);
Simon Glass07575352014-10-04 11:29:44 -0600916 if (ret < 0)
917 return ret;
918 func = ret;
919 len = snprintf(str, buffsize, "%s%d: %s",
920 priv->bank_name ? priv->bank_name : "",
921 offset, gpio_function[func]);
Simon Glass07575352014-10-04 11:29:44 -0600922
Patrice Chotardd7124f02022-08-30 14:09:11 +0200923 switch (func) {
924 case GPIOF_FUNC:
925 snprintf(str + len, buffsize - len, " %s", label ? label : "");
926 break;
927 case GPIOF_INPUT:
928 case GPIOF_OUTPUT:
929 case GPIOF_UNUSED:
Simon Glass07575352014-10-04 11:29:44 -0600930 ret = ops->get_value(dev, offset);
931 if (ret < 0)
932 return ret;
933 used = gpio_get_function(dev, offset, &label) != GPIOF_UNUSED;
934 snprintf(str + len, buffsize - len, ": %d [%c]%s%s",
935 ret,
936 used ? 'x' : ' ',
Patrice Chotarda3292082022-08-30 14:09:12 +0200937 label ? " " : "",
Simon Glass07575352014-10-04 11:29:44 -0600938 label ? label : "");
Patrice Chotardd7124f02022-08-30 14:09:11 +0200939 break;
Simon Glass07575352014-10-04 11:29:44 -0600940 }
941
942 return 0;
943}
944
Simon Glass29126862020-07-07 13:11:44 -0600945#if CONFIG_IS_ENABLED(ACPIGEN)
946int gpio_get_acpi(const struct gpio_desc *desc, struct acpi_gpio *gpio)
947{
Simon Glass3d647742021-02-04 21:22:05 -0700948 const struct dm_gpio_ops *ops;
Simon Glass29126862020-07-07 13:11:44 -0600949
950 memset(gpio, '\0', sizeof(*gpio));
951 if (!dm_gpio_is_valid(desc)) {
952 /* Indicate that the GPIO is not valid */
953 gpio->pin_count = 0;
954 gpio->pins[0] = 0;
955 return -EINVAL;
956 }
957
958 ops = gpio_get_ops(desc->dev);
959 if (!ops->get_acpi)
960 return -ENOSYS;
961
962 return ops->get_acpi(desc, gpio);
963}
964#endif
965
Simon Glass962f5ca2015-04-14 21:03:20 -0600966int gpio_claim_vector(const int *gpio_num_array, const char *fmt)
967{
968 int i, ret;
969 int gpio;
970
971 for (i = 0; i < 32; i++) {
972 gpio = gpio_num_array[i];
973 if (gpio == -1)
974 break;
975 ret = gpio_requestf(gpio, fmt, i);
976 if (ret)
977 goto err;
978 ret = gpio_direction_input(gpio);
979 if (ret) {
980 gpio_free(gpio);
981 goto err;
982 }
983 }
984
985 return 0;
986err:
987 for (i--; i >= 0; i--)
988 gpio_free(gpio_num_array[i]);
989
990 return ret;
991}
992
Simon Glasse5901c92014-11-10 18:00:21 -0700993/*
994 * get a number comprised of multiple GPIO values. gpio_num_array points to
995 * the array of gpio pin numbers to scan, terminated by -1.
996 */
Simon Glass962f5ca2015-04-14 21:03:20 -0600997int gpio_get_values_as_int(const int *gpio_list)
Simon Glasse5901c92014-11-10 18:00:21 -0700998{
999 int gpio;
1000 unsigned bitmask = 1;
1001 unsigned vector = 0;
Simon Glass962f5ca2015-04-14 21:03:20 -06001002 int ret;
Simon Glasse5901c92014-11-10 18:00:21 -07001003
1004 while (bitmask &&
Simon Glass962f5ca2015-04-14 21:03:20 -06001005 ((gpio = *gpio_list++) != -1)) {
1006 ret = gpio_get_value(gpio);
1007 if (ret < 0)
1008 return ret;
1009 else if (ret)
Simon Glasse5901c92014-11-10 18:00:21 -07001010 vector |= bitmask;
1011 bitmask <<= 1;
1012 }
Simon Glass962f5ca2015-04-14 21:03:20 -06001013
Simon Glasse5901c92014-11-10 18:00:21 -07001014 return vector;
1015}
1016
Simon Glass17c43f12016-03-06 19:27:51 -07001017int dm_gpio_get_values_as_int(const struct gpio_desc *desc_list, int count)
Simon Glassbbf24782016-03-06 19:27:50 -07001018{
1019 unsigned bitmask = 1;
1020 unsigned vector = 0;
1021 int ret, i;
1022
1023 for (i = 0; i < count; i++) {
1024 ret = dm_gpio_get_value(&desc_list[i]);
1025 if (ret < 0)
1026 return ret;
1027 else if (ret)
1028 vector |= bitmask;
1029 bitmask <<= 1;
1030 }
1031
1032 return vector;
1033}
1034
Simon Glass8a45b222021-02-04 21:22:09 -07001035int dm_gpio_get_values_as_int_base3(struct gpio_desc *desc_list,
1036 int count)
1037{
1038 static const char tristate[] = "01z";
1039 enum {
1040 PULLUP,
1041 PULLDOWN,
1042
1043 NUM_OPTIONS,
1044 };
1045 int vals[NUM_OPTIONS];
1046 uint mask;
1047 uint vector = 0;
1048 int ret, i;
1049
1050 /*
1051 * Limit to 19 digits which should be plenty. This avoids overflow of a
1052 * 32-bit int
1053 */
1054 assert(count < 20);
1055
1056 for (i = 0; i < NUM_OPTIONS; i++) {
1057 uint flags = GPIOD_IS_IN;
1058
1059 flags |= (i == PULLDOWN) ? GPIOD_PULL_DOWN : GPIOD_PULL_UP;
1060 ret = dm_gpios_clrset_flags(desc_list, count, GPIOD_MASK_PULL,
1061 flags);
1062 if (ret)
1063 return log_msg_ret("pu", ret);
1064
1065 /* Give the lines time to settle */
1066 udelay(10);
1067
1068 ret = dm_gpio_get_values_as_int(desc_list, count);
1069 if (ret < 0)
1070 return log_msg_ret("get1", ret);
1071 vals[i] = ret;
1072 }
1073
1074 log_debug("values: %x %x, count = %d\n", vals[0], vals[1], count);
1075 for (i = count - 1, mask = 1 << i; i >= 0; i--, mask >>= 1) {
1076 uint pd = vals[PULLDOWN] & mask ? 1 : 0;
1077 uint pu = vals[PULLUP] & mask ? 1 : 0;
1078 uint digit;
1079
1080 /*
1081 * Get value with internal pulldown active. If this is 1 then
1082 * there is a stronger external pullup, which we call 1. If not
1083 * then call it 0.
1084 *
1085 * If the values differ then the pin is floating so we call
1086 * this a 2.
1087 */
1088 if (pu == pd)
1089 digit = pd;
1090 else
1091 digit = 2;
1092 log_debug("%c ", tristate[digit]);
1093 vector = 3 * vector + digit;
1094 }
1095 log_debug("vector=%d\n", vector);
1096
1097 return vector;
1098}
1099
Heiko Schocher49b10cb2019-07-17 06:59:51 +02001100/**
1101 * gpio_request_tail: common work for requesting a gpio.
1102 *
1103 * ret: return value from previous work in function which calls
1104 * this function.
1105 * This seems bogus (why calling this function instead not
1106 * calling it and end caller function instead?).
1107 * Because on error in caller function we want to set some
1108 * default values in gpio desc and have a common error
1109 * debug message, which provides this function.
1110 * nodename: Name of node for which gpio gets requested
1111 * used for gpio label name.
1112 * args: pointer to output arguments structure
1113 * list_name: Name of GPIO list
1114 * used for gpio label name.
1115 * index: gpio index in gpio list
1116 * used for gpio label name.
1117 * desc: pointer to gpio descriptor, filled from this
1118 * function.
1119 * flags: gpio flags to use.
1120 * add_index: should index added to gpio label name
1121 * gpio_dev: pointer to gpio device from which the gpio
1122 * will be requested. If NULL try to get the
1123 * gpio device with uclass_get_device_by_ofnode()
1124 *
1125 * return: In error case this function sets default values in
1126 * gpio descriptor, also emmits a debug message.
1127 * On success it returns 0 else the error code from
1128 * function calls, or the error code passed through
1129 * ret to this function.
1130 *
1131 */
Heiko Schocher5fc7cf82019-06-12 06:11:46 +02001132static int gpio_request_tail(int ret, const char *nodename,
Simon Glass3a571232017-05-18 20:09:18 -06001133 struct ofnode_phandle_args *args,
1134 const char *list_name, int index,
Heiko Schocher5fc7cf82019-06-12 06:11:46 +02001135 struct gpio_desc *desc, int flags,
Heiko Schocher49b10cb2019-07-17 06:59:51 +02001136 bool add_index, struct udevice *gpio_dev)
Simon Glass3669e0e2015-01-05 20:05:29 -07001137{
Patrick Delaunay9f2b0662020-01-13 11:35:01 +01001138 gpio_desc_init(desc, gpio_dev, 0);
Simon Glass3a571232017-05-18 20:09:18 -06001139 if (ret)
Simon Glass3669e0e2015-01-05 20:05:29 -07001140 goto err;
Simon Glass3669e0e2015-01-05 20:05:29 -07001141
Heiko Schocher5fc7cf82019-06-12 06:11:46 +02001142 if (!desc->dev) {
1143 ret = uclass_get_device_by_ofnode(UCLASS_GPIO, args->node,
1144 &desc->dev);
1145 if (ret) {
Svyatoslav Ryhelc03cd982023-07-26 17:10:06 +03001146#if CONFIG_IS_ENABLED(MAX77663_GPIO) || CONFIG_IS_ENABLED(PALMAS_GPIO)
1147 struct udevice *pmic;
1148 ret = uclass_get_device_by_ofnode(UCLASS_PMIC, args->node,
1149 &pmic);
1150 if (ret) {
1151 log_debug("%s: PMIC device get failed, err %d\n",
1152 __func__, ret);
1153 goto err;
1154 }
1155
1156 device_foreach_child(desc->dev, pmic) {
1157 if (device_get_uclass_id(desc->dev) == UCLASS_GPIO)
1158 break;
1159 }
1160
1161 /* if loop exits without GPIO device return error */
1162 if (device_get_uclass_id(desc->dev) != UCLASS_GPIO)
1163 goto err;
1164#else
Heiko Schocher49b10cb2019-07-17 06:59:51 +02001165 debug("%s: uclass_get_device_by_ofnode failed\n",
1166 __func__);
Heiko Schocher5fc7cf82019-06-12 06:11:46 +02001167 goto err;
Svyatoslav Ryhelc03cd982023-07-26 17:10:06 +03001168#endif
Heiko Schocher5fc7cf82019-06-12 06:11:46 +02001169 }
Simon Glass3669e0e2015-01-05 20:05:29 -07001170 }
Simon Glass3a571232017-05-18 20:09:18 -06001171 ret = gpio_find_and_xlate(desc, args);
Simon Glass3669e0e2015-01-05 20:05:29 -07001172 if (ret) {
1173 debug("%s: gpio_find_and_xlate failed\n", __func__);
1174 goto err;
1175 }
1176 ret = dm_gpio_requestf(desc, add_index ? "%s.%s%d" : "%s.%s",
Heiko Schocher5fc7cf82019-06-12 06:11:46 +02001177 nodename, list_name, index);
Simon Glass3669e0e2015-01-05 20:05:29 -07001178 if (ret) {
1179 debug("%s: dm_gpio_requestf failed\n", __func__);
1180 goto err;
1181 }
Simon Glass7e0a96d2021-02-04 21:22:03 -07001182
1183 /* Keep any direction flags provided by the devicetree */
1184 ret = dm_gpio_set_dir_flags(desc,
1185 flags | (desc->flags & GPIOD_MASK_DIR));
Simon Glass3669e0e2015-01-05 20:05:29 -07001186 if (ret) {
1187 debug("%s: dm_gpio_set_dir failed\n", __func__);
1188 goto err;
1189 }
1190
1191 return 0;
1192err:
1193 debug("%s: Node '%s', property '%s', failed to request GPIO index %d: %d\n",
Heiko Schocher5fc7cf82019-06-12 06:11:46 +02001194 __func__, nodename, list_name, index, ret);
Simon Glass3669e0e2015-01-05 20:05:29 -07001195 return ret;
1196}
1197
Simon Glass95397382021-08-07 07:24:04 -06001198#if CONFIG_IS_ENABLED(OF_REAL)
Simon Glass150c5af2017-05-30 21:47:09 -06001199static int _gpio_request_by_name_nodev(ofnode node, const char *list_name,
1200 int index, struct gpio_desc *desc,
1201 int flags, bool add_index)
Simon Glass3a571232017-05-18 20:09:18 -06001202{
1203 struct ofnode_phandle_args args;
1204 int ret;
1205
Simon Glass150c5af2017-05-30 21:47:09 -06001206 ret = ofnode_parse_phandle_with_args(node, list_name, "#gpio-cells", 0,
1207 index, &args);
Simon Glass3a571232017-05-18 20:09:18 -06001208
Heiko Schocher5fc7cf82019-06-12 06:11:46 +02001209 return gpio_request_tail(ret, ofnode_get_name(node), &args, list_name,
1210 index, desc, flags, add_index, NULL);
Simon Glass3a571232017-05-18 20:09:18 -06001211}
1212
Simon Glass150c5af2017-05-30 21:47:09 -06001213int gpio_request_by_name_nodev(ofnode node, const char *list_name, int index,
Simon Glass3669e0e2015-01-05 20:05:29 -07001214 struct gpio_desc *desc, int flags)
1215{
Simon Glass150c5af2017-05-30 21:47:09 -06001216 return _gpio_request_by_name_nodev(node, list_name, index, desc, flags,
1217 index > 0);
Simon Glass3669e0e2015-01-05 20:05:29 -07001218}
1219
Simon Glass150c5af2017-05-30 21:47:09 -06001220int gpio_request_by_name(struct udevice *dev, const char *list_name, int index,
Simon Glass3669e0e2015-01-05 20:05:29 -07001221 struct gpio_desc *desc, int flags)
1222{
Simon Glass150c5af2017-05-30 21:47:09 -06001223 struct ofnode_phandle_args args;
Heiko Schocher5fc7cf82019-06-12 06:11:46 +02001224 ofnode node;
Simon Glass150c5af2017-05-30 21:47:09 -06001225 int ret;
1226
1227 ret = dev_read_phandle_with_args(dev, list_name, "#gpio-cells", 0,
1228 index, &args);
Heiko Schocher5fc7cf82019-06-12 06:11:46 +02001229 node = dev_ofnode(dev);
1230 return gpio_request_tail(ret, ofnode_get_name(node), &args, list_name,
1231 index, desc, flags, index > 0, NULL);
Simon Glass3669e0e2015-01-05 20:05:29 -07001232}
1233
Andrew Jeffery34be6962022-01-31 13:54:05 +10301234int gpio_request_by_line_name(struct udevice *dev, const char *line_name,
1235 struct gpio_desc *desc, int flags)
1236{
1237 int ret;
1238
Rasmus Villemoese1c97942023-03-17 21:12:22 +01001239 if (!dev) {
1240 uclass_foreach_dev_probe(UCLASS_GPIO, dev)
1241 if (!gpio_request_by_line_name(dev, line_name, desc, flags))
1242 return 0;
1243 return -ENOENT;
1244 }
1245
Andrew Jeffery34be6962022-01-31 13:54:05 +10301246 ret = dev_read_stringlist_search(dev, "gpio-line-names", line_name);
1247 if (ret < 0)
1248 return ret;
1249
1250 desc->dev = dev;
1251 desc->offset = ret;
1252 desc->flags = 0;
1253
1254 ret = dm_gpio_request(desc, line_name);
1255 if (ret) {
1256 debug("%s: dm_gpio_requestf failed\n", __func__);
1257 return ret;
1258 }
1259
1260 ret = dm_gpio_set_dir_flags(desc, flags | desc->flags);
1261 if (ret)
1262 debug("%s: dm_gpio_set_dir failed\n", __func__);
1263
1264 return ret;
1265}
1266
Simon Glass150c5af2017-05-30 21:47:09 -06001267int gpio_request_list_by_name_nodev(ofnode node, const char *list_name,
Simon Glass3669e0e2015-01-05 20:05:29 -07001268 struct gpio_desc *desc, int max_count,
1269 int flags)
1270{
1271 int count;
1272 int ret;
1273
Przemyslaw Marczak2984e7a2015-03-31 18:57:16 +02001274 for (count = 0; count < max_count; count++) {
Simon Glass150c5af2017-05-30 21:47:09 -06001275 ret = _gpio_request_by_name_nodev(node, list_name, count,
Simon Glass3669e0e2015-01-05 20:05:29 -07001276 &desc[count], flags, true);
1277 if (ret == -ENOENT)
1278 break;
1279 else if (ret)
1280 goto err;
1281 }
1282
1283 /* We ran out of GPIOs in the list */
1284 return count;
1285
1286err:
Rasmus Villemoes0fac5c42023-04-19 12:10:13 +02001287 gpio_free_list_nodev(desc, count);
Simon Glass3669e0e2015-01-05 20:05:29 -07001288
1289 return ret;
1290}
1291
1292int gpio_request_list_by_name(struct udevice *dev, const char *list_name,
1293 struct gpio_desc *desc, int max_count,
1294 int flags)
1295{
1296 /*
1297 * This isn't ideal since we don't use dev->name in the debug()
1298 * calls in gpio_request_by_name(), but we can do this until
1299 * gpio_request_list_by_name_nodev() can be dropped.
1300 */
Simon Glass150c5af2017-05-30 21:47:09 -06001301 return gpio_request_list_by_name_nodev(dev_ofnode(dev), list_name, desc,
1302 max_count, flags);
Simon Glass3669e0e2015-01-05 20:05:29 -07001303}
1304
1305int gpio_get_list_count(struct udevice *dev, const char *list_name)
1306{
1307 int ret;
1308
Sean Anderson430e1362021-04-20 10:50:54 -04001309 ret = dev_count_phandle_with_args(dev, list_name, "#gpio-cells",
1310 -ENOENT);
1311 if (ret < 0) {
Simon Glass3669e0e2015-01-05 20:05:29 -07001312 debug("%s: Node '%s', property '%s', GPIO count failed: %d\n",
1313 __func__, dev->name, list_name, ret);
1314 }
1315
1316 return ret;
1317}
Simon Glass4fe40672021-02-04 21:21:54 -07001318#endif /* OF_PLATDATA */
Simon Glass3669e0e2015-01-05 20:05:29 -07001319
Simon Glass48609d02021-08-07 07:24:12 -06001320#if CONFIG_IS_ENABLED(OF_PLATDATA)
1321int gpio_request_by_phandle(struct udevice *dev,
1322 const struct phandle_2_arg *cells,
1323 struct gpio_desc *desc, int flags)
1324{
1325 struct ofnode_phandle_args args;
1326 struct udevice *gpio_dev;
1327 const int index = 0;
1328 int ret;
1329
1330 ret = device_get_by_ofplat_idx(cells->idx, &gpio_dev);
1331 if (ret)
1332 return ret;
1333 args.args[0] = cells->arg[0];
1334 args.args[1] = cells->arg[1];
1335
1336 return gpio_request_tail(ret, NULL, &args, NULL, index, desc, flags,
1337 index > 0, gpio_dev);
1338}
1339#endif
1340
Simon Glass3669e0e2015-01-05 20:05:29 -07001341int dm_gpio_free(struct udevice *dev, struct gpio_desc *desc)
1342{
1343 /* For now, we don't do any checking of dev */
1344 return _dm_gpio_free(desc->dev, desc->offset);
1345}
1346
1347int gpio_free_list(struct udevice *dev, struct gpio_desc *desc, int count)
1348{
1349 int i;
1350
1351 /* For now, we don't do any checking of dev */
1352 for (i = 0; i < count; i++)
1353 dm_gpio_free(dev, &desc[i]);
1354
1355 return 0;
1356}
1357
1358int gpio_free_list_nodev(struct gpio_desc *desc, int count)
1359{
1360 return gpio_free_list(NULL, desc, count);
1361}
1362
Simon Glass96495d92014-02-26 15:59:24 -07001363/* We need to renumber the GPIOs when any driver is probed/removed */
Simon Glassb892d122014-10-04 11:29:42 -06001364static int gpio_renumber(struct udevice *removed_dev)
Simon Glass96495d92014-02-26 15:59:24 -07001365{
1366 struct gpio_dev_priv *uc_priv;
Heiko Schocher54c5d082014-05-22 12:43:05 +02001367 struct udevice *dev;
Simon Glass96495d92014-02-26 15:59:24 -07001368 struct uclass *uc;
1369 unsigned base;
1370 int ret;
1371
1372 ret = uclass_get(UCLASS_GPIO, &uc);
1373 if (ret)
1374 return ret;
1375
1376 /* Ensure that we have a base for each bank */
1377 base = 0;
1378 uclass_foreach_dev(dev, uc) {
Simon Glassb892d122014-10-04 11:29:42 -06001379 if (device_active(dev) && dev != removed_dev) {
Simon Glasse564f052015-03-05 12:25:20 -07001380 uc_priv = dev_get_uclass_priv(dev);
Simon Glass96495d92014-02-26 15:59:24 -07001381 uc_priv->gpio_base = base;
1382 base += uc_priv->gpio_count;
1383 }
1384 }
1385
1386 return 0;
1387}
1388
Simon Glass17c43f12016-03-06 19:27:51 -07001389int gpio_get_number(const struct gpio_desc *desc)
Simon Glass56a71f82015-03-25 12:21:58 -06001390{
1391 struct udevice *dev = desc->dev;
1392 struct gpio_dev_priv *uc_priv;
1393
1394 if (!dev)
1395 return -1;
Simon Glass0fd3d912020-12-22 19:30:28 -07001396 uc_priv = dev_get_uclass_priv(dev);
Simon Glass56a71f82015-03-25 12:21:58 -06001397
1398 return uc_priv->gpio_base + desc->offset;
1399}
1400
Heiko Schocher54c5d082014-05-22 12:43:05 +02001401static int gpio_post_probe(struct udevice *dev)
Simon Glass96495d92014-02-26 15:59:24 -07001402{
Simon Glasse564f052015-03-05 12:25:20 -07001403 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
Simon Glassb892d122014-10-04 11:29:42 -06001404
1405 uc_priv->name = calloc(uc_priv->gpio_count, sizeof(char *));
1406 if (!uc_priv->name)
1407 return -ENOMEM;
1408
Marek Vasutaaf5b592023-08-02 01:26:02 +02001409 uc_priv->claimed = calloc(DIV_ROUND_UP(uc_priv->gpio_count,
1410 GPIO_ALLOC_BITS),
1411 GPIO_ALLOC_BITS / 8);
1412 if (!uc_priv->claimed) {
1413 free(uc_priv->name);
1414 return -ENOMEM;
1415 }
1416
Simon Glassb892d122014-10-04 11:29:42 -06001417 return gpio_renumber(NULL);
Simon Glass96495d92014-02-26 15:59:24 -07001418}
1419
Heiko Schocher54c5d082014-05-22 12:43:05 +02001420static int gpio_pre_remove(struct udevice *dev)
Simon Glass96495d92014-02-26 15:59:24 -07001421{
Simon Glasse564f052015-03-05 12:25:20 -07001422 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
Simon Glassb892d122014-10-04 11:29:42 -06001423 int i;
1424
1425 for (i = 0; i < uc_priv->gpio_count; i++) {
1426 if (uc_priv->name[i])
1427 free(uc_priv->name[i]);
1428 }
Marek Vasutaaf5b592023-08-02 01:26:02 +02001429 free(uc_priv->claimed);
Simon Glassb892d122014-10-04 11:29:42 -06001430 free(uc_priv->name);
1431
1432 return gpio_renumber(dev);
Simon Glass96495d92014-02-26 15:59:24 -07001433}
1434
Heiko Schocher5fc7cf82019-06-12 06:11:46 +02001435int gpio_dev_request_index(struct udevice *dev, const char *nodename,
1436 char *list_name, int index, int flags,
1437 int dtflags, struct gpio_desc *desc)
1438{
1439 struct ofnode_phandle_args args;
1440
1441 args.node = ofnode_null();
1442 args.args_count = 2;
1443 args.args[0] = index;
1444 args.args[1] = dtflags;
1445
1446 return gpio_request_tail(0, nodename, &args, list_name, index, desc,
1447 flags, 0, dev);
1448}
1449
Jean-Jacques Hiblotd4b722e2020-09-11 13:43:34 +05301450static void devm_gpiod_release(struct udevice *dev, void *res)
1451{
1452 dm_gpio_free(dev, res);
1453}
1454
1455static int devm_gpiod_match(struct udevice *dev, void *res, void *data)
1456{
1457 return res == data;
1458}
1459
1460struct gpio_desc *devm_gpiod_get_index(struct udevice *dev, const char *id,
1461 unsigned int index, int flags)
1462{
1463 int rc;
1464 struct gpio_desc *desc;
1465 char *propname;
1466 static const char suffix[] = "-gpios";
1467
1468 propname = malloc(strlen(id) + sizeof(suffix));
1469 if (!propname) {
1470 rc = -ENOMEM;
1471 goto end;
1472 }
1473
1474 strcpy(propname, id);
1475 strcat(propname, suffix);
1476
1477 desc = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc),
1478 __GFP_ZERO);
1479 if (unlikely(!desc)) {
1480 rc = -ENOMEM;
1481 goto end;
1482 }
1483
1484 rc = gpio_request_by_name(dev, propname, index, desc, flags);
1485
1486end:
1487 if (propname)
1488 free(propname);
1489
1490 if (rc)
1491 return ERR_PTR(rc);
1492
1493 devres_add(dev, desc);
1494
1495 return desc;
1496}
1497
1498struct gpio_desc *devm_gpiod_get_index_optional(struct udevice *dev,
1499 const char *id,
1500 unsigned int index,
1501 int flags)
1502{
1503 struct gpio_desc *desc = devm_gpiod_get_index(dev, id, index, flags);
1504
1505 if (IS_ERR(desc))
1506 return NULL;
1507
1508 return desc;
1509}
1510
1511void devm_gpiod_put(struct udevice *dev, struct gpio_desc *desc)
1512{
1513 int rc;
1514
1515 rc = devres_release(dev, devm_gpiod_release, devm_gpiod_match, desc);
1516 WARN_ON(rc);
1517}
1518
Michal Simek1b4c2aa2018-07-12 12:42:27 +02001519static int gpio_post_bind(struct udevice *dev)
1520{
Simon Glass11c341b2023-06-01 10:22:30 -06001521 if (CONFIG_IS_ENABLED(GPIO_HOG) && dev_has_ofnode(dev)) {
Eddie James1d99e672022-02-07 17:09:01 -06001522 struct udevice *child;
1523 ofnode node;
1524
Heiko Schocher49b10cb2019-07-17 06:59:51 +02001525 dev_for_each_subnode(node, dev) {
1526 if (ofnode_read_bool(node, "gpio-hog")) {
1527 const char *name = ofnode_get_name(node);
1528 int ret;
Heiko Schocher5fc7cf82019-06-12 06:11:46 +02001529
Heiko Schocher49b10cb2019-07-17 06:59:51 +02001530 ret = device_bind_driver_to_node(dev,
1531 "gpio_hog",
1532 name, node,
1533 &child);
1534 if (ret)
1535 return ret;
Marek Vasut48b3ecb2022-09-22 17:53:26 +02001536
1537 /*
1538 * Make sure gpio-hogs are probed after bind
1539 * since hogs can be essential to the hardware
1540 * system.
1541 */
1542 dev_or_flags(child, DM_FLAG_PROBE_AFTER_BIND);
Heiko Schocher49b10cb2019-07-17 06:59:51 +02001543 }
Heiko Schocher5fc7cf82019-06-12 06:11:46 +02001544 }
1545 }
Marek Vasut48b3ecb2022-09-22 17:53:26 +02001546
Michal Simek1b4c2aa2018-07-12 12:42:27 +02001547 return 0;
1548}
1549
Simon Glass96495d92014-02-26 15:59:24 -07001550UCLASS_DRIVER(gpio) = {
1551 .id = UCLASS_GPIO,
1552 .name = "gpio",
Bhuvanchandra DVae89bb02015-06-01 18:37:15 +05301553 .flags = DM_UC_FLAG_SEQ_ALIAS,
Simon Glass96495d92014-02-26 15:59:24 -07001554 .post_probe = gpio_post_probe,
Michal Simek1b4c2aa2018-07-12 12:42:27 +02001555 .post_bind = gpio_post_bind,
Simon Glass96495d92014-02-26 15:59:24 -07001556 .pre_remove = gpio_pre_remove,
Simon Glass41575d82020-12-03 16:55:17 -07001557 .per_device_auto = sizeof(struct gpio_dev_priv),
Simon Glass96495d92014-02-26 15:59:24 -07001558};