blob: 3d9f8b32b8d2baeb10e3c950e794fdb4fa22fbd6 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glasse821d182014-02-26 15:59:24 -07002/*
3 * Copyright (c) 2013 Google, Inc
Simon Glasse821d182014-02-26 15:59:24 -07004 */
5
Simon Glasse43eae22021-02-04 21:22:08 -07006#define LOG_CATEGORY UCLASS_GPIO
7
Simon Glasse821d182014-02-26 15:59:24 -07008#include <dm.h>
Simon Glass2149e112021-08-07 07:24:12 -06009#include <dt-structs.h>
Simon Glass0f2af882020-05-10 11:40:05 -060010#include <log.h>
Jean-Jacques Hiblot775d6a22020-09-11 13:43:34 +053011#include <dm/devres.h>
12#include <dm/device_compat.h>
Heiko Schocher39cb3402019-06-12 06:11:46 +020013#include <dm/device-internal.h>
14#include <dm/lists.h>
15#include <dm/uclass-internal.h>
Eric Nelson786e98d2016-04-24 16:32:40 -070016#include <dt-bindings/gpio/gpio.h>
Simon Glasse821d182014-02-26 15:59:24 -070017#include <errno.h>
Simon Glassd3322bb2015-01-05 20:05:28 -070018#include <fdtdec.h>
Simon Glass0f4517d2014-10-04 11:29:42 -060019#include <malloc.h>
Simon Glass3176b6c2020-07-07 13:11:44 -060020#include <acpi/acpi_device.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060021#include <asm/global_data.h>
Simon Glasse821d182014-02-26 15:59:24 -070022#include <asm/gpio.h>
Simon Glass0f2af882020-05-10 11:40:05 -060023#include <dm/device_compat.h>
Masahiro Yamada78eeb912016-01-24 23:27:48 +090024#include <linux/bug.h>
Simon Glass43b2e1a2014-10-22 21:37:01 -060025#include <linux/ctype.h>
Simon Glass247ccf22021-02-04 21:22:09 -070026#include <linux/delay.h>
Simon Glasse821d182014-02-26 15:59:24 -070027
Simon Glass16e10402015-01-05 20:05:29 -070028DECLARE_GLOBAL_DATA_PTR;
29
Marek Vasut3a188472023-08-02 01:26:02 +020030#define GPIO_ALLOC_BITS 32
31
Simon Glasse821d182014-02-26 15:59:24 -070032/**
Patrick Delaunay758bba92020-01-13 11:35:01 +010033 * gpio_desc_init() - Initialize the GPIO descriptor
34 *
35 * @desc: GPIO descriptor to initialize
36 * @dev: GPIO device
37 * @offset: Offset of device GPIO
38 */
39static void gpio_desc_init(struct gpio_desc *desc,
40 struct udevice *dev,
41 uint offset)
42{
43 desc->dev = dev;
44 desc->offset = offset;
45 desc->flags = 0;
46}
47
48/**
Simon Glasse821d182014-02-26 15:59:24 -070049 * gpio_to_device() - Convert global GPIO number to device, number
Simon Glasse821d182014-02-26 15:59:24 -070050 *
51 * Convert the GPIO number to an entry in the list of GPIOs
52 * or GPIO blocks registered with the GPIO controller. Returns
53 * entry on success, NULL on error.
Simon Glassce555292015-01-05 20:05:27 -070054 *
55 * @gpio: The numeric representation of the GPIO
56 * @desc: Returns description (desc->flags will always be 0)
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +010057 * Return: 0 if found, -ENOENT if not found
Simon Glasse821d182014-02-26 15:59:24 -070058 */
Simon Glassce555292015-01-05 20:05:27 -070059static int gpio_to_device(unsigned int gpio, struct gpio_desc *desc)
Simon Glasse821d182014-02-26 15:59:24 -070060{
61 struct gpio_dev_priv *uc_priv;
Heiko Schocherb74fcb42014-05-22 12:43:05 +020062 struct udevice *dev;
Simon Glasse821d182014-02-26 15:59:24 -070063
Michal Suchanek91c96fe2022-10-12 21:58:08 +020064 for (uclass_first_device(UCLASS_GPIO, &dev);
Simon Glasse821d182014-02-26 15:59:24 -070065 dev;
Michal Suchanek91c96fe2022-10-12 21:58:08 +020066 uclass_next_device(&dev)) {
Simon Glassde0977b2015-03-05 12:25:20 -070067 uc_priv = dev_get_uclass_priv(dev);
Simon Glasse821d182014-02-26 15:59:24 -070068 if (gpio >= uc_priv->gpio_base &&
69 gpio < uc_priv->gpio_base + uc_priv->gpio_count) {
Patrick Delaunay758bba92020-01-13 11:35:01 +010070 gpio_desc_init(desc, dev, gpio - uc_priv->gpio_base);
Simon Glasse821d182014-02-26 15:59:24 -070071 return 0;
72 }
73 }
74
75 /* No such GPIO */
Michal Suchanek91c96fe2022-10-12 21:58:08 +020076 return -ENOENT;
Simon Glasse821d182014-02-26 15:59:24 -070077}
78
Marek Vasut3a188472023-08-02 01:26:02 +020079/**
80 * gpio_is_claimed() - Test whether GPIO is claimed by consumer
81 *
82 * Test whether GPIO is claimed by consumer already.
83 *
84 * @uc_priv: gpio_dev_priv pointer.
85 * @offset: gpio offset within the device
86 * @return: true if claimed, false if not claimed
87 */
88static bool gpio_is_claimed(struct gpio_dev_priv *uc_priv, unsigned int offset)
89{
90 return !!(uc_priv->claimed[offset / GPIO_ALLOC_BITS] & BIT(offset % GPIO_ALLOC_BITS));
91}
92
93/**
94 * gpio_set_claim() - Set GPIO claimed by consumer
95 *
96 * Set a bit which indicate the GPIO is claimed by consumer
97 *
98 * @uc_priv: gpio_dev_priv pointer.
99 * @offset: gpio offset within the device
100 */
101static void gpio_set_claim(struct gpio_dev_priv *uc_priv, unsigned int offset)
102{
103 uc_priv->claimed[offset / GPIO_ALLOC_BITS] |= BIT(offset % GPIO_ALLOC_BITS);
104}
105
106/**
107 * gpio_clear_claim() - Clear GPIO claimed by consumer
108 *
109 * Clear a bit which indicate the GPIO is claimed by consumer
110 *
111 * @uc_priv: gpio_dev_priv pointer.
112 * @offset: gpio offset within the device
113 */
114static void gpio_clear_claim(struct gpio_dev_priv *uc_priv, unsigned int offset)
115{
116 uc_priv->claimed[offset / GPIO_ALLOC_BITS] &= ~BIT(offset % GPIO_ALLOC_BITS);
117}
118
Heiko Schochera3e793c2020-05-22 11:08:59 +0200119#if CONFIG_IS_ENABLED(DM_GPIO_LOOKUP_LABEL)
120/**
121 * dm_gpio_lookup_label() - look for name in gpio device
122 *
123 * search in uc_priv, if there is a gpio with labelname same
124 * as name.
125 *
126 * @name: name which is searched
127 * @uc_priv: gpio_dev_priv pointer.
128 * @offset: gpio offset within the device
129 * @return: 0 if found, -ENOENT if not.
130 */
131static int dm_gpio_lookup_label(const char *name,
132 struct gpio_dev_priv *uc_priv, ulong *offset)
133{
Heiko Schochera3e793c2020-05-22 11:08:59 +0200134 int i;
135
136 *offset = -1;
Heiko Schochera3e793c2020-05-22 11:08:59 +0200137 for (i = 0; i < uc_priv->gpio_count; i++) {
Marek Vasut3a188472023-08-02 01:26:02 +0200138 if (!gpio_is_claimed(uc_priv, i))
Heiko Schochera3e793c2020-05-22 11:08:59 +0200139 continue;
Rasmus Villemoes48828082022-10-03 11:02:45 +0200140 if (!strcmp(name, uc_priv->name[i])) {
Heiko Schochera3e793c2020-05-22 11:08:59 +0200141 *offset = i;
142 return 0;
143 }
144 }
145 return -ENOENT;
146}
147#else
148static int
149dm_gpio_lookup_label(const char *name, struct gpio_dev_priv *uc_priv,
150 ulong *offset)
151{
152 return -ENOENT;
153}
154#endif
155
Simon Glass215bcc72015-06-23 15:38:40 -0600156int dm_gpio_lookup_name(const char *name, struct gpio_desc *desc)
Simon Glasse821d182014-02-26 15:59:24 -0700157{
Simon Glass43b2e1a2014-10-22 21:37:01 -0600158 struct gpio_dev_priv *uc_priv = NULL;
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200159 struct udevice *dev;
Simon Glass43b2e1a2014-10-22 21:37:01 -0600160 ulong offset;
161 int numeric;
Simon Glasse821d182014-02-26 15:59:24 -0700162
Simon Glassff9b9032021-07-24 09:03:30 -0600163 numeric = isdigit(*name) ? dectoul(name, NULL) : -1;
Michal Suchanek91c96fe2022-10-12 21:58:08 +0200164 for (uclass_first_device(UCLASS_GPIO, &dev);
Simon Glasse821d182014-02-26 15:59:24 -0700165 dev;
Michal Suchanek91c96fe2022-10-12 21:58:08 +0200166 uclass_next_device(&dev)) {
Simon Glasse821d182014-02-26 15:59:24 -0700167 int len;
168
Simon Glassde0977b2015-03-05 12:25:20 -0700169 uc_priv = dev_get_uclass_priv(dev);
Simon Glass43b2e1a2014-10-22 21:37:01 -0600170 if (numeric != -1) {
171 offset = numeric - uc_priv->gpio_base;
172 /* Allow GPIOs to be numbered from 0 */
Tom Rini26fd9682017-05-10 15:20:15 -0400173 if (offset < uc_priv->gpio_count)
Simon Glass43b2e1a2014-10-22 21:37:01 -0600174 break;
175 }
176
Simon Glasse821d182014-02-26 15:59:24 -0700177 len = uc_priv->bank_name ? strlen(uc_priv->bank_name) : 0;
178
Simon Glassd4acf632014-06-11 23:29:47 -0600179 if (!strncasecmp(name, uc_priv->bank_name, len)) {
Simon Glass43b2e1a2014-10-22 21:37:01 -0600180 if (!strict_strtoul(name + len, 10, &offset))
Samuel Holland8f53a332021-09-11 17:05:51 -0500181 if (offset < uc_priv->gpio_count)
182 break;
Simon Glasse821d182014-02-26 15:59:24 -0700183 }
Heiko Schochera3e793c2020-05-22 11:08:59 +0200184
185 /*
186 * if we did not found a gpio through its bank
187 * name, we search for a valid gpio label.
188 */
189 if (!dm_gpio_lookup_label(name, uc_priv, &offset))
190 break;
Simon Glasse821d182014-02-26 15:59:24 -0700191 }
192
Simon Glass43b2e1a2014-10-22 21:37:01 -0600193 if (!dev)
Michal Suchanek91c96fe2022-10-12 21:58:08 +0200194 return -EINVAL;
Simon Glass43b2e1a2014-10-22 21:37:01 -0600195
Patrick Delaunay758bba92020-01-13 11:35:01 +0100196 gpio_desc_init(desc, dev, offset);
Simon Glass215bcc72015-06-23 15:38:40 -0600197
198 return 0;
199}
200
201int gpio_lookup_name(const char *name, struct udevice **devp,
202 unsigned int *offsetp, unsigned int *gpiop)
203{
204 struct gpio_desc desc;
205 int ret;
206
207 if (devp)
208 *devp = NULL;
209 ret = dm_gpio_lookup_name(name, &desc);
210 if (ret)
211 return ret;
212
Simon Glass43b2e1a2014-10-22 21:37:01 -0600213 if (devp)
Simon Glass215bcc72015-06-23 15:38:40 -0600214 *devp = desc.dev;
Simon Glass43b2e1a2014-10-22 21:37:01 -0600215 if (offsetp)
Simon Glass215bcc72015-06-23 15:38:40 -0600216 *offsetp = desc.offset;
217 if (gpiop) {
218 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(desc.dev);
219
220 *gpiop = uc_priv->gpio_base + desc.offset;
221 }
Simon Glass43b2e1a2014-10-22 21:37:01 -0600222
223 return 0;
Simon Glasse821d182014-02-26 15:59:24 -0700224}
225
Samuel Holland8e10c712021-09-11 17:05:53 -0500226unsigned long gpio_flags_xlate(uint32_t arg)
227{
228 unsigned long flags = 0;
229
230 if (arg & GPIO_ACTIVE_LOW)
231 flags |= GPIOD_ACTIVE_LOW;
232
233 /*
234 * need to test 2 bits for gpio output binding:
235 * OPEN_DRAIN (0x6) = SINGLE_ENDED (0x2) | LINE_OPEN_DRAIN (0x4)
236 * OPEN_SOURCE (0x2) = SINGLE_ENDED (0x2) | LINE_OPEN_SOURCE (0x0)
237 */
238 if (arg & GPIO_SINGLE_ENDED) {
239 if (arg & GPIO_LINE_OPEN_DRAIN)
240 flags |= GPIOD_OPEN_DRAIN;
241 else
242 flags |= GPIOD_OPEN_SOURCE;
243 }
244
245 if (arg & GPIO_PULL_UP)
246 flags |= GPIOD_PULL_UP;
247
248 if (arg & GPIO_PULL_DOWN)
249 flags |= GPIOD_PULL_DOWN;
250
251 return flags;
252}
253
Simon Glass12faa022017-05-18 20:09:18 -0600254int gpio_xlate_offs_flags(struct udevice *dev, struct gpio_desc *desc,
255 struct ofnode_phandle_args *args)
Eric Nelson786e98d2016-04-24 16:32:40 -0700256{
Samuel Holland78acb922021-09-11 17:05:52 -0500257 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
258
Eric Nelson786e98d2016-04-24 16:32:40 -0700259 if (args->args_count < 1)
260 return -EINVAL;
261
262 desc->offset = args->args[0];
Samuel Holland78acb922021-09-11 17:05:52 -0500263 if (desc->offset >= uc_priv->gpio_count)
264 return -EINVAL;
Eric Nelson786e98d2016-04-24 16:32:40 -0700265
266 if (args->args_count < 2)
267 return 0;
268
Samuel Holland8e10c712021-09-11 17:05:53 -0500269 desc->flags = gpio_flags_xlate(args->args[1]);
Patrick Delaunay5c1c06e2020-01-13 11:35:07 +0100270
Eric Nelson786e98d2016-04-24 16:32:40 -0700271 return 0;
272}
273
Simon Glass16e10402015-01-05 20:05:29 -0700274static int gpio_find_and_xlate(struct gpio_desc *desc,
Simon Glass12faa022017-05-18 20:09:18 -0600275 struct ofnode_phandle_args *args)
Simon Glassd3322bb2015-01-05 20:05:28 -0700276{
Simon Glass49f315a2021-02-04 21:22:05 -0700277 const struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
Simon Glassd3322bb2015-01-05 20:05:28 -0700278
Eric Nelson786e98d2016-04-24 16:32:40 -0700279 if (ops->xlate)
280 return ops->xlate(desc->dev, desc, args);
Simon Glassd3322bb2015-01-05 20:05:28 -0700281 else
Eric Nelson786e98d2016-04-24 16:32:40 -0700282 return gpio_xlate_offs_flags(desc->dev, desc, args);
Simon Glassd3322bb2015-01-05 20:05:28 -0700283}
284
Simon Glass2149e112021-08-07 07:24:12 -0600285#if CONFIG_IS_ENABLED(GPIO_HOG)
Heiko Schocher39cb3402019-06-12 06:11:46 +0200286
287struct gpio_hog_priv {
288 struct gpio_desc gpiod;
289};
290
291struct gpio_hog_data {
292 int gpiod_flags;
293 int value;
294 u32 val[2];
295};
296
Simon Glassaad29ae2020-12-03 16:55:21 -0700297static int gpio_hog_of_to_plat(struct udevice *dev)
Heiko Schocher39cb3402019-06-12 06:11:46 +0200298{
Simon Glassfa20e932020-12-03 16:55:20 -0700299 struct gpio_hog_data *plat = dev_get_plat(dev);
Heiko Schocher39cb3402019-06-12 06:11:46 +0200300 const char *nodename;
301 int ret;
302
303 plat->value = 0;
304 if (dev_read_bool(dev, "input")) {
305 plat->gpiod_flags = GPIOD_IS_IN;
306 } else if (dev_read_bool(dev, "output-high")) {
307 plat->value = 1;
308 plat->gpiod_flags = GPIOD_IS_OUT;
309 } else if (dev_read_bool(dev, "output-low")) {
310 plat->gpiod_flags = GPIOD_IS_OUT;
311 } else {
312 printf("%s: missing gpio-hog state.\n", __func__);
313 return -EINVAL;
314 }
315 ret = dev_read_u32_array(dev, "gpios", plat->val, 2);
316 if (ret) {
317 printf("%s: wrong gpios property, 2 values needed %d\n",
318 __func__, ret);
319 return ret;
320 }
321 nodename = dev_read_string(dev, "line-name");
Heiko Schocher58e4c382019-07-17 06:59:51 +0200322 if (nodename)
323 device_set_name(dev, nodename);
Heiko Schocher39cb3402019-06-12 06:11:46 +0200324
325 return 0;
326}
327
328static int gpio_hog_probe(struct udevice *dev)
329{
Simon Glassfa20e932020-12-03 16:55:20 -0700330 struct gpio_hog_data *plat = dev_get_plat(dev);
Heiko Schocher39cb3402019-06-12 06:11:46 +0200331 struct gpio_hog_priv *priv = dev_get_priv(dev);
332 int ret;
333
334 ret = gpio_dev_request_index(dev->parent, dev->name, "gpio-hog",
335 plat->val[0], plat->gpiod_flags,
336 plat->val[1], &priv->gpiod);
337 if (ret < 0) {
338 debug("%s: node %s could not get gpio.\n", __func__,
339 dev->name);
340 return ret;
341 }
Heiko Schocher58e4c382019-07-17 06:59:51 +0200342
343 if (plat->gpiod_flags == GPIOD_IS_OUT) {
344 ret = dm_gpio_set_value(&priv->gpiod, plat->value);
345 if (ret < 0) {
346 debug("%s: node %s could not set gpio.\n", __func__,
347 dev->name);
348 return ret;
349 }
350 }
Heiko Schocher39cb3402019-06-12 06:11:46 +0200351
352 return 0;
353}
354
Heiko Schocher58e4c382019-07-17 06:59:51 +0200355int gpio_hog_lookup_name(const char *name, struct gpio_desc **desc)
Heiko Schocher39cb3402019-06-12 06:11:46 +0200356{
357 struct udevice *dev;
358
Heiko Schocher58e4c382019-07-17 06:59:51 +0200359 *desc = NULL;
Heiko Schocher39cb3402019-06-12 06:11:46 +0200360 if (!uclass_get_device_by_name(UCLASS_NOP, name, &dev)) {
361 struct gpio_hog_priv *priv = dev_get_priv(dev);
362
Heiko Schocher58e4c382019-07-17 06:59:51 +0200363 *desc = &priv->gpiod;
364 return 0;
Heiko Schocher39cb3402019-06-12 06:11:46 +0200365 }
366
Heiko Schocher58e4c382019-07-17 06:59:51 +0200367 return -ENODEV;
Heiko Schocher39cb3402019-06-12 06:11:46 +0200368}
369
370U_BOOT_DRIVER(gpio_hog) = {
371 .name = "gpio_hog",
372 .id = UCLASS_NOP,
Simon Glassaad29ae2020-12-03 16:55:21 -0700373 .of_to_plat = gpio_hog_of_to_plat,
Heiko Schocher39cb3402019-06-12 06:11:46 +0200374 .probe = gpio_hog_probe,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700375 .priv_auto = sizeof(struct gpio_hog_priv),
Simon Glass71fa5b42020-12-03 16:55:18 -0700376 .plat_auto = sizeof(struct gpio_hog_data),
Heiko Schocher39cb3402019-06-12 06:11:46 +0200377};
378#else
Heiko Schocher58e4c382019-07-17 06:59:51 +0200379int gpio_hog_lookup_name(const char *name, struct gpio_desc **desc)
Heiko Schocher39cb3402019-06-12 06:11:46 +0200380{
Heiko Schocher58e4c382019-07-17 06:59:51 +0200381 return 0;
Heiko Schocher39cb3402019-06-12 06:11:46 +0200382}
383#endif
384
Simon Glass047cdb32015-06-23 15:38:41 -0600385int dm_gpio_request(struct gpio_desc *desc, const char *label)
Simon Glassce555292015-01-05 20:05:27 -0700386{
Simon Glass49f315a2021-02-04 21:22:05 -0700387 const struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
Simon Glassce555292015-01-05 20:05:27 -0700388 struct udevice *dev = desc->dev;
389 struct gpio_dev_priv *uc_priv;
390 char *str;
391 int ret;
392
Simon Glassde0977b2015-03-05 12:25:20 -0700393 uc_priv = dev_get_uclass_priv(dev);
Marek Vasut3a188472023-08-02 01:26:02 +0200394 if (gpio_is_claimed(uc_priv, desc->offset))
Simon Glassce555292015-01-05 20:05:27 -0700395 return -EBUSY;
396 str = strdup(label);
397 if (!str)
398 return -ENOMEM;
Simon Glass49f315a2021-02-04 21:22:05 -0700399 if (ops->request) {
400 ret = ops->request(dev, desc->offset, label);
Simon Glassce555292015-01-05 20:05:27 -0700401 if (ret) {
402 free(str);
403 return ret;
404 }
405 }
Marek Vasut3a188472023-08-02 01:26:02 +0200406
407 gpio_set_claim(uc_priv, desc->offset);
Simon Glassce555292015-01-05 20:05:27 -0700408 uc_priv->name[desc->offset] = str;
409
410 return 0;
411}
412
Simon Glass16e10402015-01-05 20:05:29 -0700413static int dm_gpio_requestf(struct gpio_desc *desc, const char *fmt, ...)
414{
Simon Glass7ec24132024-09-29 19:49:48 -0600415#if !defined(CONFIG_XPL_BUILD) || !CONFIG_IS_ENABLED(USE_TINY_PRINTF)
Simon Glass16e10402015-01-05 20:05:29 -0700416 va_list args;
417 char buf[40];
418
419 va_start(args, fmt);
420 vscnprintf(buf, sizeof(buf), fmt, args);
421 va_end(args);
422 return dm_gpio_request(desc, buf);
Simon Glassee8a3d92015-12-29 05:22:48 -0700423#else
424 return dm_gpio_request(desc, fmt);
425#endif
Simon Glass16e10402015-01-05 20:05:29 -0700426}
427
Simon Glasse821d182014-02-26 15:59:24 -0700428/**
429 * gpio_request() - [COMPAT] Request GPIO
430 * gpio: GPIO number
431 * label: Name for the requested GPIO
432 *
Simon Glass0f4517d2014-10-04 11:29:42 -0600433 * The label is copied and allocated so the caller does not need to keep
434 * the pointer around.
435 *
Simon Glasse821d182014-02-26 15:59:24 -0700436 * This function implements the API that's compatible with current
437 * GPIO API used in U-Boot. The request is forwarded to particular
438 * GPIO driver. Returns 0 on success, negative value on error.
439 */
440int gpio_request(unsigned gpio, const char *label)
441{
Simon Glassce555292015-01-05 20:05:27 -0700442 struct gpio_desc desc;
Simon Glasse821d182014-02-26 15:59:24 -0700443 int ret;
444
Simon Glassce555292015-01-05 20:05:27 -0700445 ret = gpio_to_device(gpio, &desc);
Simon Glasse821d182014-02-26 15:59:24 -0700446 if (ret)
447 return ret;
448
Simon Glassce555292015-01-05 20:05:27 -0700449 return dm_gpio_request(&desc, label);
Simon Glasse821d182014-02-26 15:59:24 -0700450}
451
452/**
Simon Glass1b27d602014-10-04 11:29:49 -0600453 * gpio_requestf() - [COMPAT] Request GPIO
454 * @gpio: GPIO number
455 * @fmt: Format string for the requested GPIO
456 * @...: Arguments for the printf() format string
457 *
458 * This function implements the API that's compatible with current
459 * GPIO API used in U-Boot. The request is forwarded to particular
460 * GPIO driver. Returns 0 on success, negative value on error.
461 */
462int gpio_requestf(unsigned gpio, const char *fmt, ...)
463{
Simon Glass7ec24132024-09-29 19:49:48 -0600464#if !defined(CONFIG_XPL_BUILD) || !CONFIG_IS_ENABLED(USE_TINY_PRINTF)
Simon Glass1b27d602014-10-04 11:29:49 -0600465 va_list args;
466 char buf[40];
467
468 va_start(args, fmt);
469 vscnprintf(buf, sizeof(buf), fmt, args);
470 va_end(args);
471 return gpio_request(gpio, buf);
Simon Glassee8a3d92015-12-29 05:22:48 -0700472#else
473 return gpio_request(gpio, fmt);
474#endif
Simon Glass1b27d602014-10-04 11:29:49 -0600475}
476
Simon Glassce555292015-01-05 20:05:27 -0700477int _dm_gpio_free(struct udevice *dev, uint offset)
Simon Glasse821d182014-02-26 15:59:24 -0700478{
Simon Glass49f315a2021-02-04 21:22:05 -0700479 const struct dm_gpio_ops *ops = gpio_get_ops(dev);
Simon Glass0f4517d2014-10-04 11:29:42 -0600480 struct gpio_dev_priv *uc_priv;
Simon Glasse821d182014-02-26 15:59:24 -0700481 int ret;
482
Simon Glassde0977b2015-03-05 12:25:20 -0700483 uc_priv = dev_get_uclass_priv(dev);
Marek Vasut3a188472023-08-02 01:26:02 +0200484 if (!gpio_is_claimed(uc_priv, offset))
Simon Glass0f4517d2014-10-04 11:29:42 -0600485 return -ENXIO;
Simon Glass49f315a2021-02-04 21:22:05 -0700486 if (ops->rfree) {
487 ret = ops->rfree(dev, offset);
Simon Glass0f4517d2014-10-04 11:29:42 -0600488 if (ret)
489 return ret;
490 }
491
Marek Vasut3a188472023-08-02 01:26:02 +0200492 gpio_clear_claim(uc_priv, offset);
Simon Glass0f4517d2014-10-04 11:29:42 -0600493 free(uc_priv->name[offset]);
494 uc_priv->name[offset] = NULL;
495
496 return 0;
497}
498
Simon Glassce555292015-01-05 20:05:27 -0700499/**
500 * gpio_free() - [COMPAT] Relinquish GPIO
501 * gpio: GPIO number
502 *
503 * This function implements the API that's compatible with current
504 * GPIO API used in U-Boot. The request is forwarded to particular
505 * GPIO driver. Returns 0 on success, negative value on error.
506 */
507int gpio_free(unsigned gpio)
508{
509 struct gpio_desc desc;
510 int ret;
511
512 ret = gpio_to_device(gpio, &desc);
513 if (ret)
514 return ret;
515
516 return _dm_gpio_free(desc.dev, desc.offset);
517}
518
Simon Glassfd838972016-03-06 19:27:51 -0700519static int check_reserved(const struct gpio_desc *desc, const char *func)
Simon Glass0f4517d2014-10-04 11:29:42 -0600520{
Simon Glass230c1432015-07-02 18:16:16 -0600521 struct gpio_dev_priv *uc_priv;
522
523 if (!dm_gpio_is_valid(desc))
524 return -ENOENT;
Simon Glass0f4517d2014-10-04 11:29:42 -0600525
Simon Glass230c1432015-07-02 18:16:16 -0600526 uc_priv = dev_get_uclass_priv(desc->dev);
Marek Vasut3a188472023-08-02 01:26:02 +0200527 if (!gpio_is_claimed(uc_priv, desc->offset)) {
Simon Glass0f4517d2014-10-04 11:29:42 -0600528 printf("%s: %s: error: gpio %s%d not reserved\n",
Simon Glassce555292015-01-05 20:05:27 -0700529 desc->dev->name, func,
530 uc_priv->bank_name ? uc_priv->bank_name : "",
531 desc->offset);
Simon Glass0f4517d2014-10-04 11:29:42 -0600532 return -EBUSY;
533 }
534
535 return 0;
Simon Glasse821d182014-02-26 15:59:24 -0700536}
537
538/**
539 * gpio_direction_input() - [COMPAT] Set GPIO direction to input
540 * gpio: GPIO number
541 *
542 * This function implements the API that's compatible with current
543 * GPIO API used in U-Boot. The request is forwarded to particular
544 * GPIO driver. Returns 0 on success, negative value on error.
545 */
546int gpio_direction_input(unsigned gpio)
547{
Simon Glassce555292015-01-05 20:05:27 -0700548 struct gpio_desc desc;
Simon Glasse821d182014-02-26 15:59:24 -0700549 int ret;
550
Simon Glassce555292015-01-05 20:05:27 -0700551 ret = gpio_to_device(gpio, &desc);
Simon Glasse821d182014-02-26 15:59:24 -0700552 if (ret)
553 return ret;
554
Simon Glass722f9682021-02-04 21:22:04 -0700555 return dm_gpio_clrset_flags(&desc, GPIOD_MASK_DIR, GPIOD_IS_IN);
Simon Glasse821d182014-02-26 15:59:24 -0700556}
557
558/**
559 * gpio_direction_output() - [COMPAT] Set GPIO direction to output and set value
560 * gpio: GPIO number
561 * value: Logical value to be set on the GPIO pin
562 *
563 * This function implements the API that's compatible with current
564 * GPIO API used in U-Boot. The request is forwarded to particular
565 * GPIO driver. Returns 0 on success, negative value on error.
566 */
567int gpio_direction_output(unsigned gpio, int value)
568{
Simon Glassce555292015-01-05 20:05:27 -0700569 struct gpio_desc desc;
Simon Glass722f9682021-02-04 21:22:04 -0700570 ulong flags;
Simon Glassce555292015-01-05 20:05:27 -0700571 int ret;
572
573 ret = gpio_to_device(gpio, &desc);
574 if (ret)
575 return ret;
Simon Glassce555292015-01-05 20:05:27 -0700576
Simon Glass722f9682021-02-04 21:22:04 -0700577 flags = GPIOD_IS_OUT;
578 if (value)
579 flags |= GPIOD_IS_OUT_ACTIVE;
580 return dm_gpio_clrset_flags(&desc, GPIOD_MASK_DIR, flags);
Simon Glassce555292015-01-05 20:05:27 -0700581}
582
Patrick Delaunay4c2c96f2020-01-13 11:35:02 +0100583static int _gpio_get_value(const struct gpio_desc *desc)
Simon Glassce555292015-01-05 20:05:27 -0700584{
Simon Glass49f315a2021-02-04 21:22:05 -0700585 const struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
Simon Glassce555292015-01-05 20:05:27 -0700586 int value;
Patrick Delaunay4c2c96f2020-01-13 11:35:02 +0100587
Simon Glass49f315a2021-02-04 21:22:05 -0700588 value = ops->get_value(desc->dev, desc->offset);
Patrick Delaunay4c2c96f2020-01-13 11:35:02 +0100589
590 return desc->flags & GPIOD_ACTIVE_LOW ? !value : value;
591}
592
593int dm_gpio_get_value(const struct gpio_desc *desc)
594{
Simon Glassce555292015-01-05 20:05:27 -0700595 int ret;
596
597 ret = check_reserved(desc, "get_value");
598 if (ret)
599 return ret;
600
Patrick Delaunay4c2c96f2020-01-13 11:35:02 +0100601 return _gpio_get_value(desc);
Simon Glassce555292015-01-05 20:05:27 -0700602}
603
Simon Glassfd838972016-03-06 19:27:51 -0700604int dm_gpio_set_value(const struct gpio_desc *desc, int value)
Simon Glassce555292015-01-05 20:05:27 -0700605{
Simon Glass7b893f92021-02-04 21:22:03 -0700606 const struct dm_gpio_ops *ops;
Simon Glassce555292015-01-05 20:05:27 -0700607 int ret;
608
609 ret = check_reserved(desc, "set_value");
610 if (ret)
611 return ret;
612
613 if (desc->flags & GPIOD_ACTIVE_LOW)
614 value = !value;
Neil Armstrongf51b8da2020-05-05 10:43:17 +0200615
Simon Glass7b893f92021-02-04 21:22:03 -0700616 /* GPIOD_ are directly managed by driver in set_flags */
617 ops = gpio_get_ops(desc->dev);
618 if (ops->set_flags) {
619 ulong flags = desc->flags;
620
621 if (value)
622 flags |= GPIOD_IS_OUT_ACTIVE;
623 else
624 flags &= ~GPIOD_IS_OUT_ACTIVE;
625 return ops->set_flags(desc->dev, desc->offset, flags);
626 }
627
Neil Armstrongf51b8da2020-05-05 10:43:17 +0200628 /*
629 * Emulate open drain by not actively driving the line high or
630 * Emulate open source by not actively driving the line low
631 */
632 if ((desc->flags & GPIOD_OPEN_DRAIN && value) ||
633 (desc->flags & GPIOD_OPEN_SOURCE && !value))
Simon Glass7b893f92021-02-04 21:22:03 -0700634 return ops->direction_input(desc->dev, desc->offset);
Neil Armstrongf51b8da2020-05-05 10:43:17 +0200635 else if (desc->flags & GPIOD_OPEN_DRAIN ||
636 desc->flags & GPIOD_OPEN_SOURCE)
Simon Glass7b893f92021-02-04 21:22:03 -0700637 return ops->direction_output(desc->dev, desc->offset, value);
638
639 ret = ops->set_value(desc->dev, desc->offset, value);
640 if (ret)
641 return ret;
Neil Armstrongf51b8da2020-05-05 10:43:17 +0200642
Simon Glassce555292015-01-05 20:05:27 -0700643 return 0;
644}
645
Patrick Delaunay187c45f2020-01-13 11:35:04 +0100646/* check dir flags invalid configuration */
647static int check_dir_flags(ulong flags)
648{
649 if ((flags & GPIOD_IS_OUT) && (flags & GPIOD_IS_IN)) {
650 log_debug("%s: flags 0x%lx has GPIOD_IS_OUT and GPIOD_IS_IN\n",
651 __func__, flags);
652 return -EINVAL;
653 }
654
Patrick Delaunay5c1c06e2020-01-13 11:35:07 +0100655 if ((flags & GPIOD_PULL_UP) && (flags & GPIOD_PULL_DOWN)) {
656 log_debug("%s: flags 0x%lx has GPIOD_PULL_UP and GPIOD_PULL_DOWN\n",
657 __func__, flags);
658 return -EINVAL;
659 }
660
661 if ((flags & GPIOD_OPEN_DRAIN) && (flags & GPIOD_OPEN_SOURCE)) {
662 log_debug("%s: flags 0x%lx has GPIOD_OPEN_DRAIN and GPIOD_OPEN_SOURCE\n",
663 __func__, flags);
664 return -EINVAL;
665 }
666
Patrick Delaunay187c45f2020-01-13 11:35:04 +0100667 return 0;
668}
669
Simon Glass7b893f92021-02-04 21:22:03 -0700670/**
671 * _dm_gpio_set_flags() - Send flags to the driver
672 *
673 * This uses the best available method to send the given flags to the driver.
674 * Note that if flags & GPIOD_ACTIVE_LOW, the driver sees the opposite value
675 * of GPIOD_IS_OUT_ACTIVE.
676 *
677 * @desc: GPIO description
678 * @flags: flags value to set
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100679 * Return: 0 if OK, -ve on error
Simon Glass7b893f92021-02-04 21:22:03 -0700680 */
Simon Glass54befdd2021-02-04 21:21:55 -0700681static int _dm_gpio_set_flags(struct gpio_desc *desc, ulong flags)
Simon Glassce555292015-01-05 20:05:27 -0700682{
683 struct udevice *dev = desc->dev;
Simon Glass49f315a2021-02-04 21:22:05 -0700684 const struct dm_gpio_ops *ops = gpio_get_ops(dev);
Patrick Delaunay187c45f2020-01-13 11:35:04 +0100685 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
Patrick Delaunay3b2a1172020-01-13 11:35:03 +0100686 int ret = 0;
Simon Glasse821d182014-02-26 15:59:24 -0700687
Patrick Delaunay187c45f2020-01-13 11:35:04 +0100688 ret = check_dir_flags(flags);
689 if (ret) {
690 dev_dbg(dev,
691 "%s error: set_dir_flags for gpio %s%d has invalid dir flags 0x%lx\n",
692 desc->dev->name,
693 uc_priv->bank_name ? uc_priv->bank_name : "",
694 desc->offset, flags);
695
696 return ret;
697 }
698
Simon Glass7b893f92021-02-04 21:22:03 -0700699 /* If active low, invert the output state */
700 if ((flags & (GPIOD_IS_OUT | GPIOD_ACTIVE_LOW)) ==
701 (GPIOD_IS_OUT | GPIOD_ACTIVE_LOW))
702 flags ^= GPIOD_IS_OUT_ACTIVE;
703
Simon Glass54befdd2021-02-04 21:21:55 -0700704 /* GPIOD_ are directly managed by driver in set_flags */
705 if (ops->set_flags) {
706 ret = ops->set_flags(dev, desc->offset, flags);
Patrick Delaunay684326f2020-01-13 11:35:09 +0100707 } else {
Zixun LI1acf0062024-10-21 17:04:51 +0200708 if (flags & GPIOD_MASK_PULL)
709 return -EINVAL;
710
Patrick Delaunay684326f2020-01-13 11:35:09 +0100711 if (flags & GPIOD_IS_OUT) {
Simon Glass7b893f92021-02-04 21:22:03 -0700712 bool value = flags & GPIOD_IS_OUT_ACTIVE;
713
714 ret = ops->direction_output(dev, desc->offset, value);
Patrick Delaunay684326f2020-01-13 11:35:09 +0100715 } else if (flags & GPIOD_IS_IN) {
716 ret = ops->direction_input(dev, desc->offset);
717 }
Simon Glassce555292015-01-05 20:05:27 -0700718 }
Patrick Delaunay3b2a1172020-01-13 11:35:03 +0100719
720 return ret;
721}
722
Simon Glass7b893f92021-02-04 21:22:03 -0700723int dm_gpio_clrset_flags(struct gpio_desc *desc, ulong clr, ulong set)
Patrick Delaunay3b2a1172020-01-13 11:35:03 +0100724{
Simon Glass7b893f92021-02-04 21:22:03 -0700725 ulong flags;
Patrick Delaunay3b2a1172020-01-13 11:35:03 +0100726 int ret;
727
728 ret = check_reserved(desc, "set_dir_flags");
Simon Glassce555292015-01-05 20:05:27 -0700729 if (ret)
730 return ret;
Patrick Delaunay3b2a1172020-01-13 11:35:03 +0100731
Simon Glass7b893f92021-02-04 21:22:03 -0700732 flags = (desc->flags & ~clr) | set;
733
Simon Glass54befdd2021-02-04 21:21:55 -0700734 ret = _dm_gpio_set_flags(desc, flags);
Simon Glass7b893f92021-02-04 21:22:03 -0700735 if (ret)
736 return ret;
Simon Glassce555292015-01-05 20:05:27 -0700737
Simon Glass7b893f92021-02-04 21:22:03 -0700738 /* save the flags also in descriptor */
739 desc->flags = flags;
740
741 return 0;
742}
743
744int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
745{
746 /* combine the requested flags (for IN/OUT) and the descriptor flags */
747 return dm_gpio_clrset_flags(desc, GPIOD_MASK_DIR, flags);
Simon Glassce555292015-01-05 20:05:27 -0700748}
749
Simon Glass247ccf22021-02-04 21:22:09 -0700750int dm_gpios_clrset_flags(struct gpio_desc *desc, int count, ulong clr,
751 ulong set)
752{
753 int ret;
754 int i;
755
756 for (i = 0; i < count; i++) {
757 ret = dm_gpio_clrset_flags(&desc[i], clr, set);
758 if (ret)
759 return log_ret(ret);
760 }
761
762 return 0;
763}
764
Simon Glass909bee32021-02-04 21:21:57 -0700765int dm_gpio_get_flags(struct gpio_desc *desc, ulong *flagsp)
Patrick Delaunayaecf9d72020-01-13 11:35:06 +0100766{
Patrick Delaunayfbacd622020-01-13 11:35:08 +0100767 struct udevice *dev = desc->dev;
768 int ret, value;
Simon Glass49f315a2021-02-04 21:22:05 -0700769 const struct dm_gpio_ops *ops = gpio_get_ops(dev);
Simon Glassd063ce92021-02-04 21:21:56 -0700770 ulong flags;
Patrick Delaunayaecf9d72020-01-13 11:35:06 +0100771
Simon Glassd063ce92021-02-04 21:21:56 -0700772 ret = check_reserved(desc, "get_flags");
Patrick Delaunayaecf9d72020-01-13 11:35:06 +0100773 if (ret)
774 return ret;
775
Patrick Delaunayfbacd622020-01-13 11:35:08 +0100776 /* GPIOD_ are directly provided by driver except GPIOD_ACTIVE_LOW */
Simon Glassd063ce92021-02-04 21:21:56 -0700777 if (ops->get_flags) {
778 ret = ops->get_flags(dev, desc->offset, &flags);
Patrick Delaunayfbacd622020-01-13 11:35:08 +0100779 if (ret)
780 return ret;
Patrick Delaunayaecf9d72020-01-13 11:35:06 +0100781
Patrick Delaunayfbacd622020-01-13 11:35:08 +0100782 /* GPIOD_ACTIVE_LOW is saved in desc->flags */
Simon Glassd063ce92021-02-04 21:21:56 -0700783 value = flags & GPIOD_IS_OUT_ACTIVE ? 1 : 0;
Patrick Delaunayfbacd622020-01-13 11:35:08 +0100784 if (desc->flags & GPIOD_ACTIVE_LOW)
785 value = !value;
Simon Glassd063ce92021-02-04 21:21:56 -0700786 flags &= ~(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT_ACTIVE);
787 flags |= (desc->flags & GPIOD_ACTIVE_LOW);
Patrick Delaunayfbacd622020-01-13 11:35:08 +0100788 if (value)
Simon Glassd063ce92021-02-04 21:21:56 -0700789 flags |= GPIOD_IS_OUT_ACTIVE;
Patrick Delaunayfbacd622020-01-13 11:35:08 +0100790 } else {
Simon Glassd063ce92021-02-04 21:21:56 -0700791 flags = desc->flags;
Patrick Delaunayfbacd622020-01-13 11:35:08 +0100792 /* only GPIOD_IS_OUT_ACTIVE is provided by uclass */
Simon Glassd063ce92021-02-04 21:21:56 -0700793 flags &= ~GPIOD_IS_OUT_ACTIVE;
Patrick Delaunayfbacd622020-01-13 11:35:08 +0100794 if ((desc->flags & GPIOD_IS_OUT) && _gpio_get_value(desc))
Simon Glassd063ce92021-02-04 21:21:56 -0700795 flags |= GPIOD_IS_OUT_ACTIVE;
Patrick Delaunayfbacd622020-01-13 11:35:08 +0100796 }
Simon Glassd063ce92021-02-04 21:21:56 -0700797 *flagsp = flags;
Patrick Delaunayaecf9d72020-01-13 11:35:06 +0100798
799 return 0;
800}
801
Simon Glasse821d182014-02-26 15:59:24 -0700802/**
803 * gpio_get_value() - [COMPAT] Sample GPIO pin and return it's value
804 * gpio: GPIO number
805 *
806 * This function implements the API that's compatible with current
807 * GPIO API used in U-Boot. The request is forwarded to particular
808 * GPIO driver. Returns the value of the GPIO pin, or negative value
809 * on error.
810 */
811int gpio_get_value(unsigned gpio)
812{
Simon Glasse821d182014-02-26 15:59:24 -0700813 int ret;
814
Simon Glassce555292015-01-05 20:05:27 -0700815 struct gpio_desc desc;
816
817 ret = gpio_to_device(gpio, &desc);
Simon Glasse821d182014-02-26 15:59:24 -0700818 if (ret)
819 return ret;
Simon Glassce555292015-01-05 20:05:27 -0700820 return dm_gpio_get_value(&desc);
Simon Glasse821d182014-02-26 15:59:24 -0700821}
822
823/**
824 * gpio_set_value() - [COMPAT] Configure logical value on GPIO pin
825 * gpio: GPIO number
826 * value: Logical value to be set on the GPIO pin.
827 *
828 * This function implements the API that's compatible with current
829 * GPIO API used in U-Boot. The request is forwarded to particular
830 * GPIO driver. Returns 0 on success, negative value on error.
831 */
832int gpio_set_value(unsigned gpio, int value)
833{
Simon Glassce555292015-01-05 20:05:27 -0700834 struct gpio_desc desc;
Simon Glasse821d182014-02-26 15:59:24 -0700835 int ret;
836
Simon Glassce555292015-01-05 20:05:27 -0700837 ret = gpio_to_device(gpio, &desc);
Simon Glasse821d182014-02-26 15:59:24 -0700838 if (ret)
839 return ret;
Simon Glassce555292015-01-05 20:05:27 -0700840 return dm_gpio_set_value(&desc, value);
Simon Glasse821d182014-02-26 15:59:24 -0700841}
842
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200843const char *gpio_get_bank_info(struct udevice *dev, int *bit_count)
Simon Glasse821d182014-02-26 15:59:24 -0700844{
845 struct gpio_dev_priv *priv;
846
847 /* Must be called on an active device */
Simon Glassde0977b2015-03-05 12:25:20 -0700848 priv = dev_get_uclass_priv(dev);
Simon Glasse821d182014-02-26 15:59:24 -0700849 assert(priv);
850
851 *bit_count = priv->gpio_count;
852 return priv->bank_name;
853}
854
Simon Glass6e5e6dd2014-10-04 11:29:43 -0600855static const char * const gpio_function[GPIOF_COUNT] = {
856 "input",
857 "output",
858 "unused",
859 "unknown",
860 "func",
861};
862
Masahiro Yamada286c2522017-06-22 16:50:25 +0900863static int get_function(struct udevice *dev, int offset, bool skip_unused,
864 const char **namep)
Simon Glass6e5e6dd2014-10-04 11:29:43 -0600865{
Simon Glassde0977b2015-03-05 12:25:20 -0700866 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
Simon Glass49f315a2021-02-04 21:22:05 -0700867 const struct dm_gpio_ops *ops = gpio_get_ops(dev);
Simon Glass6e5e6dd2014-10-04 11:29:43 -0600868
869 BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function));
870 if (!device_active(dev))
871 return -ENODEV;
872 if (offset < 0 || offset >= uc_priv->gpio_count)
873 return -EINVAL;
874 if (namep)
875 *namep = uc_priv->name[offset];
Marek Vasut3a188472023-08-02 01:26:02 +0200876 if (skip_unused && !gpio_is_claimed(uc_priv, offset))
Simon Glass6e5e6dd2014-10-04 11:29:43 -0600877 return GPIOF_UNUSED;
878 if (ops->get_function) {
879 int ret;
880
881 ret = ops->get_function(dev, offset);
882 if (ret < 0)
883 return ret;
884 if (ret >= ARRAY_SIZE(gpio_function))
885 return -ENODATA;
886 return ret;
887 }
888
889 return GPIOF_UNKNOWN;
890}
891
892int gpio_get_function(struct udevice *dev, int offset, const char **namep)
893{
894 return get_function(dev, offset, true, namep);
895}
896
897int gpio_get_raw_function(struct udevice *dev, int offset, const char **namep)
898{
899 return get_function(dev, offset, false, namep);
900}
901
Simon Glass6b1ef592014-10-04 11:29:44 -0600902int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize)
903{
Simon Glass49f315a2021-02-04 21:22:05 -0700904 const struct dm_gpio_ops *ops = gpio_get_ops(dev);
Simon Glass6b1ef592014-10-04 11:29:44 -0600905 struct gpio_dev_priv *priv;
906 char *str = buf;
Patrice Chotard8b1310e2022-08-30 14:09:11 +0200907 const char *label;
Simon Glass6b1ef592014-10-04 11:29:44 -0600908 int func;
909 int ret;
910 int len;
Patrice Chotard8b1310e2022-08-30 14:09:11 +0200911 bool used;
Simon Glass6b1ef592014-10-04 11:29:44 -0600912
913 BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function));
914
915 *buf = 0;
Simon Glassde0977b2015-03-05 12:25:20 -0700916 priv = dev_get_uclass_priv(dev);
Patrice Chotard8b1310e2022-08-30 14:09:11 +0200917 ret = gpio_get_raw_function(dev, offset, &label);
Simon Glass6b1ef592014-10-04 11:29:44 -0600918 if (ret < 0)
919 return ret;
920 func = ret;
921 len = snprintf(str, buffsize, "%s%d: %s",
922 priv->bank_name ? priv->bank_name : "",
923 offset, gpio_function[func]);
Simon Glass6b1ef592014-10-04 11:29:44 -0600924
Patrice Chotard8b1310e2022-08-30 14:09:11 +0200925 switch (func) {
926 case GPIOF_FUNC:
927 snprintf(str + len, buffsize - len, " %s", label ? label : "");
928 break;
929 case GPIOF_INPUT:
930 case GPIOF_OUTPUT:
931 case GPIOF_UNUSED:
Simon Glass6b1ef592014-10-04 11:29:44 -0600932 ret = ops->get_value(dev, offset);
933 if (ret < 0)
934 return ret;
935 used = gpio_get_function(dev, offset, &label) != GPIOF_UNUSED;
936 snprintf(str + len, buffsize - len, ": %d [%c]%s%s",
937 ret,
938 used ? 'x' : ' ',
Patrice Chotardeb8f3a72022-08-30 14:09:12 +0200939 label ? " " : "",
Simon Glass6b1ef592014-10-04 11:29:44 -0600940 label ? label : "");
Patrice Chotard8b1310e2022-08-30 14:09:11 +0200941 break;
Simon Glass6b1ef592014-10-04 11:29:44 -0600942 }
943
944 return 0;
945}
946
Simon Glass3176b6c2020-07-07 13:11:44 -0600947#if CONFIG_IS_ENABLED(ACPIGEN)
948int gpio_get_acpi(const struct gpio_desc *desc, struct acpi_gpio *gpio)
949{
Simon Glass49f315a2021-02-04 21:22:05 -0700950 const struct dm_gpio_ops *ops;
Simon Glass3176b6c2020-07-07 13:11:44 -0600951
952 memset(gpio, '\0', sizeof(*gpio));
953 if (!dm_gpio_is_valid(desc)) {
954 /* Indicate that the GPIO is not valid */
955 gpio->pin_count = 0;
956 gpio->pins[0] = 0;
957 return -EINVAL;
958 }
959
960 ops = gpio_get_ops(desc->dev);
961 if (!ops->get_acpi)
962 return -ENOSYS;
963
964 return ops->get_acpi(desc, gpio);
965}
966#endif
967
Simon Glassbef54db2015-04-14 21:03:20 -0600968int gpio_claim_vector(const int *gpio_num_array, const char *fmt)
969{
970 int i, ret;
971 int gpio;
972
973 for (i = 0; i < 32; i++) {
974 gpio = gpio_num_array[i];
975 if (gpio == -1)
976 break;
977 ret = gpio_requestf(gpio, fmt, i);
978 if (ret)
979 goto err;
980 ret = gpio_direction_input(gpio);
981 if (ret) {
982 gpio_free(gpio);
983 goto err;
984 }
985 }
986
987 return 0;
988err:
989 for (i--; i >= 0; i--)
990 gpio_free(gpio_num_array[i]);
991
992 return ret;
993}
994
Simon Glass2c97a8f2014-11-10 18:00:21 -0700995/*
996 * get a number comprised of multiple GPIO values. gpio_num_array points to
997 * the array of gpio pin numbers to scan, terminated by -1.
998 */
Simon Glassbef54db2015-04-14 21:03:20 -0600999int gpio_get_values_as_int(const int *gpio_list)
Simon Glass2c97a8f2014-11-10 18:00:21 -07001000{
1001 int gpio;
1002 unsigned bitmask = 1;
1003 unsigned vector = 0;
Simon Glassbef54db2015-04-14 21:03:20 -06001004 int ret;
Simon Glass2c97a8f2014-11-10 18:00:21 -07001005
1006 while (bitmask &&
Simon Glassbef54db2015-04-14 21:03:20 -06001007 ((gpio = *gpio_list++) != -1)) {
1008 ret = gpio_get_value(gpio);
1009 if (ret < 0)
1010 return ret;
1011 else if (ret)
Simon Glass2c97a8f2014-11-10 18:00:21 -07001012 vector |= bitmask;
1013 bitmask <<= 1;
1014 }
Simon Glassbef54db2015-04-14 21:03:20 -06001015
Simon Glass2c97a8f2014-11-10 18:00:21 -07001016 return vector;
1017}
1018
Simon Glassfd838972016-03-06 19:27:51 -07001019int dm_gpio_get_values_as_int(const struct gpio_desc *desc_list, int count)
Simon Glassdf1687d2016-03-06 19:27:50 -07001020{
1021 unsigned bitmask = 1;
1022 unsigned vector = 0;
1023 int ret, i;
1024
1025 for (i = 0; i < count; i++) {
1026 ret = dm_gpio_get_value(&desc_list[i]);
1027 if (ret < 0)
1028 return ret;
1029 else if (ret)
1030 vector |= bitmask;
1031 bitmask <<= 1;
1032 }
Simon Glass247ccf22021-02-04 21:22:09 -07001033
1034 return vector;
1035}
1036
1037int dm_gpio_get_values_as_int_base3(struct gpio_desc *desc_list,
1038 int count)
1039{
1040 static const char tristate[] = "01z";
1041 enum {
1042 PULLUP,
1043 PULLDOWN,
1044
1045 NUM_OPTIONS,
1046 };
1047 int vals[NUM_OPTIONS];
1048 uint mask;
1049 uint vector = 0;
1050 int ret, i;
1051
1052 /*
1053 * Limit to 19 digits which should be plenty. This avoids overflow of a
1054 * 32-bit int
1055 */
1056 assert(count < 20);
1057
1058 for (i = 0; i < NUM_OPTIONS; i++) {
1059 uint flags = GPIOD_IS_IN;
1060
1061 flags |= (i == PULLDOWN) ? GPIOD_PULL_DOWN : GPIOD_PULL_UP;
1062 ret = dm_gpios_clrset_flags(desc_list, count, GPIOD_MASK_PULL,
1063 flags);
1064 if (ret)
1065 return log_msg_ret("pu", ret);
1066
1067 /* Give the lines time to settle */
1068 udelay(10);
1069
1070 ret = dm_gpio_get_values_as_int(desc_list, count);
1071 if (ret < 0)
1072 return log_msg_ret("get1", ret);
1073 vals[i] = ret;
1074 }
1075
1076 log_debug("values: %x %x, count = %d\n", vals[0], vals[1], count);
1077 for (i = count - 1, mask = 1 << i; i >= 0; i--, mask >>= 1) {
1078 uint pd = vals[PULLDOWN] & mask ? 1 : 0;
1079 uint pu = vals[PULLUP] & mask ? 1 : 0;
1080 uint digit;
1081
1082 /*
1083 * Get value with internal pulldown active. If this is 1 then
1084 * there is a stronger external pullup, which we call 1. If not
1085 * then call it 0.
1086 *
1087 * If the values differ then the pin is floating so we call
1088 * this a 2.
1089 */
1090 if (pu == pd)
1091 digit = pd;
1092 else
1093 digit = 2;
1094 log_debug("%c ", tristate[digit]);
1095 vector = 3 * vector + digit;
1096 }
1097 log_debug("vector=%d\n", vector);
Simon Glassdf1687d2016-03-06 19:27:50 -07001098
1099 return vector;
1100}
1101
Heiko Schocher58e4c382019-07-17 06:59:51 +02001102/**
1103 * gpio_request_tail: common work for requesting a gpio.
1104 *
1105 * ret: return value from previous work in function which calls
1106 * this function.
1107 * This seems bogus (why calling this function instead not
1108 * calling it and end caller function instead?).
1109 * Because on error in caller function we want to set some
1110 * default values in gpio desc and have a common error
1111 * debug message, which provides this function.
1112 * nodename: Name of node for which gpio gets requested
1113 * used for gpio label name.
1114 * args: pointer to output arguments structure
1115 * list_name: Name of GPIO list
1116 * used for gpio label name.
1117 * index: gpio index in gpio list
1118 * used for gpio label name.
1119 * desc: pointer to gpio descriptor, filled from this
1120 * function.
1121 * flags: gpio flags to use.
1122 * add_index: should index added to gpio label name
1123 * gpio_dev: pointer to gpio device from which the gpio
1124 * will be requested. If NULL try to get the
1125 * gpio device with uclass_get_device_by_ofnode()
1126 *
1127 * return: In error case this function sets default values in
1128 * gpio descriptor, also emmits a debug message.
1129 * On success it returns 0 else the error code from
1130 * function calls, or the error code passed through
1131 * ret to this function.
1132 *
1133 */
Heiko Schocher39cb3402019-06-12 06:11:46 +02001134static int gpio_request_tail(int ret, const char *nodename,
Simon Glass12faa022017-05-18 20:09:18 -06001135 struct ofnode_phandle_args *args,
1136 const char *list_name, int index,
Heiko Schocher39cb3402019-06-12 06:11:46 +02001137 struct gpio_desc *desc, int flags,
Heiko Schocher58e4c382019-07-17 06:59:51 +02001138 bool add_index, struct udevice *gpio_dev)
Simon Glass16e10402015-01-05 20:05:29 -07001139{
Patrick Delaunay758bba92020-01-13 11:35:01 +01001140 gpio_desc_init(desc, gpio_dev, 0);
Simon Glass12faa022017-05-18 20:09:18 -06001141 if (ret)
Simon Glass16e10402015-01-05 20:05:29 -07001142 goto err;
Simon Glass16e10402015-01-05 20:05:29 -07001143
Heiko Schocher39cb3402019-06-12 06:11:46 +02001144 if (!desc->dev) {
1145 ret = uclass_get_device_by_ofnode(UCLASS_GPIO, args->node,
1146 &desc->dev);
1147 if (ret) {
Heiko Schocher58e4c382019-07-17 06:59:51 +02001148 debug("%s: uclass_get_device_by_ofnode failed\n",
1149 __func__);
Heiko Schocher39cb3402019-06-12 06:11:46 +02001150 goto err;
1151 }
Simon Glass16e10402015-01-05 20:05:29 -07001152 }
Simon Glass12faa022017-05-18 20:09:18 -06001153 ret = gpio_find_and_xlate(desc, args);
Simon Glass16e10402015-01-05 20:05:29 -07001154 if (ret) {
1155 debug("%s: gpio_find_and_xlate failed\n", __func__);
1156 goto err;
1157 }
1158 ret = dm_gpio_requestf(desc, add_index ? "%s.%s%d" : "%s.%s",
Heiko Schocher39cb3402019-06-12 06:11:46 +02001159 nodename, list_name, index);
Simon Glass16e10402015-01-05 20:05:29 -07001160 if (ret) {
1161 debug("%s: dm_gpio_requestf failed\n", __func__);
1162 goto err;
1163 }
Simon Glass7b893f92021-02-04 21:22:03 -07001164
1165 /* Keep any direction flags provided by the devicetree */
1166 ret = dm_gpio_set_dir_flags(desc,
1167 flags | (desc->flags & GPIOD_MASK_DIR));
Simon Glass16e10402015-01-05 20:05:29 -07001168 if (ret) {
1169 debug("%s: dm_gpio_set_dir failed\n", __func__);
1170 goto err;
1171 }
1172
1173 return 0;
1174err:
1175 debug("%s: Node '%s', property '%s', failed to request GPIO index %d: %d\n",
Heiko Schocher39cb3402019-06-12 06:11:46 +02001176 __func__, nodename, list_name, index, ret);
Simon Glass16e10402015-01-05 20:05:29 -07001177 return ret;
1178}
1179
Simon Glass92882652021-08-07 07:24:04 -06001180#if CONFIG_IS_ENABLED(OF_REAL)
Simon Glass1d9af1f2017-05-30 21:47:09 -06001181static int _gpio_request_by_name_nodev(ofnode node, const char *list_name,
1182 int index, struct gpio_desc *desc,
1183 int flags, bool add_index)
Simon Glass12faa022017-05-18 20:09:18 -06001184{
1185 struct ofnode_phandle_args args;
1186 int ret;
1187
Simon Glass1d9af1f2017-05-30 21:47:09 -06001188 ret = ofnode_parse_phandle_with_args(node, list_name, "#gpio-cells", 0,
1189 index, &args);
Simon Glass12faa022017-05-18 20:09:18 -06001190
Heiko Schocher39cb3402019-06-12 06:11:46 +02001191 return gpio_request_tail(ret, ofnode_get_name(node), &args, list_name,
1192 index, desc, flags, add_index, NULL);
Simon Glass12faa022017-05-18 20:09:18 -06001193}
1194
Simon Glass1d9af1f2017-05-30 21:47:09 -06001195int gpio_request_by_name_nodev(ofnode node, const char *list_name, int index,
Simon Glass16e10402015-01-05 20:05:29 -07001196 struct gpio_desc *desc, int flags)
1197{
Simon Glass1d9af1f2017-05-30 21:47:09 -06001198 return _gpio_request_by_name_nodev(node, list_name, index, desc, flags,
1199 index > 0);
Simon Glass16e10402015-01-05 20:05:29 -07001200}
1201
Simon Glass1d9af1f2017-05-30 21:47:09 -06001202int gpio_request_by_name(struct udevice *dev, const char *list_name, int index,
Simon Glass16e10402015-01-05 20:05:29 -07001203 struct gpio_desc *desc, int flags)
1204{
Simon Glass1d9af1f2017-05-30 21:47:09 -06001205 struct ofnode_phandle_args args;
Heiko Schocher39cb3402019-06-12 06:11:46 +02001206 ofnode node;
Simon Glass1d9af1f2017-05-30 21:47:09 -06001207 int ret;
1208
1209 ret = dev_read_phandle_with_args(dev, list_name, "#gpio-cells", 0,
1210 index, &args);
Heiko Schocher39cb3402019-06-12 06:11:46 +02001211 node = dev_ofnode(dev);
1212 return gpio_request_tail(ret, ofnode_get_name(node), &args, list_name,
1213 index, desc, flags, index > 0, NULL);
Simon Glass16e10402015-01-05 20:05:29 -07001214}
1215
Andrew Jeffery2e62c6b2022-01-31 13:54:05 +10301216int gpio_request_by_line_name(struct udevice *dev, const char *line_name,
1217 struct gpio_desc *desc, int flags)
1218{
1219 int ret;
1220
Rasmus Villemoesf4e744d2023-03-17 21:12:22 +01001221 if (!dev) {
1222 uclass_foreach_dev_probe(UCLASS_GPIO, dev)
1223 if (!gpio_request_by_line_name(dev, line_name, desc, flags))
1224 return 0;
1225 return -ENOENT;
1226 }
1227
Andrew Jeffery2e62c6b2022-01-31 13:54:05 +10301228 ret = dev_read_stringlist_search(dev, "gpio-line-names", line_name);
1229 if (ret < 0)
1230 return ret;
1231
1232 desc->dev = dev;
1233 desc->offset = ret;
1234 desc->flags = 0;
1235
1236 ret = dm_gpio_request(desc, line_name);
1237 if (ret) {
1238 debug("%s: dm_gpio_requestf failed\n", __func__);
1239 return ret;
1240 }
1241
1242 ret = dm_gpio_set_dir_flags(desc, flags | desc->flags);
1243 if (ret)
1244 debug("%s: dm_gpio_set_dir failed\n", __func__);
1245
1246 return ret;
1247}
1248
Simon Glass1d9af1f2017-05-30 21:47:09 -06001249int gpio_request_list_by_name_nodev(ofnode node, const char *list_name,
Simon Glass16e10402015-01-05 20:05:29 -07001250 struct gpio_desc *desc, int max_count,
1251 int flags)
1252{
1253 int count;
1254 int ret;
1255
Przemyslaw Marczak44fc5362015-03-31 18:57:16 +02001256 for (count = 0; count < max_count; count++) {
Simon Glass1d9af1f2017-05-30 21:47:09 -06001257 ret = _gpio_request_by_name_nodev(node, list_name, count,
Simon Glass16e10402015-01-05 20:05:29 -07001258 &desc[count], flags, true);
1259 if (ret == -ENOENT)
1260 break;
1261 else if (ret)
1262 goto err;
1263 }
1264
1265 /* We ran out of GPIOs in the list */
1266 return count;
1267
1268err:
Rasmus Villemoesc9ca11c2023-04-19 12:10:13 +02001269 gpio_free_list_nodev(desc, count);
Simon Glass16e10402015-01-05 20:05:29 -07001270
1271 return ret;
1272}
1273
1274int gpio_request_list_by_name(struct udevice *dev, const char *list_name,
1275 struct gpio_desc *desc, int max_count,
1276 int flags)
1277{
1278 /*
1279 * This isn't ideal since we don't use dev->name in the debug()
1280 * calls in gpio_request_by_name(), but we can do this until
1281 * gpio_request_list_by_name_nodev() can be dropped.
1282 */
Simon Glass1d9af1f2017-05-30 21:47:09 -06001283 return gpio_request_list_by_name_nodev(dev_ofnode(dev), list_name, desc,
1284 max_count, flags);
Simon Glass16e10402015-01-05 20:05:29 -07001285}
1286
1287int gpio_get_list_count(struct udevice *dev, const char *list_name)
1288{
1289 int ret;
1290
Sean Anderson8ad66c52021-04-20 10:50:54 -04001291 ret = dev_count_phandle_with_args(dev, list_name, "#gpio-cells",
1292 -ENOENT);
1293 if (ret < 0) {
Simon Glass16e10402015-01-05 20:05:29 -07001294 debug("%s: Node '%s', property '%s', GPIO count failed: %d\n",
1295 __func__, dev->name, list_name, ret);
1296 }
1297
1298 return ret;
1299}
Simon Glassea383722021-02-04 21:21:54 -07001300#endif /* OF_PLATDATA */
Simon Glass16e10402015-01-05 20:05:29 -07001301
Simon Glass2149e112021-08-07 07:24:12 -06001302#if CONFIG_IS_ENABLED(OF_PLATDATA)
1303int gpio_request_by_phandle(struct udevice *dev,
1304 const struct phandle_2_arg *cells,
1305 struct gpio_desc *desc, int flags)
1306{
1307 struct ofnode_phandle_args args;
1308 struct udevice *gpio_dev;
1309 const int index = 0;
1310 int ret;
1311
1312 ret = device_get_by_ofplat_idx(cells->idx, &gpio_dev);
1313 if (ret)
1314 return ret;
1315 args.args[0] = cells->arg[0];
1316 args.args[1] = cells->arg[1];
1317
1318 return gpio_request_tail(ret, NULL, &args, NULL, index, desc, flags,
1319 index > 0, gpio_dev);
1320}
1321#endif
1322
Simon Glass16e10402015-01-05 20:05:29 -07001323int dm_gpio_free(struct udevice *dev, struct gpio_desc *desc)
1324{
1325 /* For now, we don't do any checking of dev */
1326 return _dm_gpio_free(desc->dev, desc->offset);
1327}
1328
1329int gpio_free_list(struct udevice *dev, struct gpio_desc *desc, int count)
1330{
1331 int i;
1332
1333 /* For now, we don't do any checking of dev */
1334 for (i = 0; i < count; i++)
1335 dm_gpio_free(dev, &desc[i]);
1336
1337 return 0;
1338}
1339
1340int gpio_free_list_nodev(struct gpio_desc *desc, int count)
1341{
1342 return gpio_free_list(NULL, desc, count);
1343}
1344
Simon Glasse821d182014-02-26 15:59:24 -07001345/* We need to renumber the GPIOs when any driver is probed/removed */
Simon Glass0f4517d2014-10-04 11:29:42 -06001346static int gpio_renumber(struct udevice *removed_dev)
Simon Glasse821d182014-02-26 15:59:24 -07001347{
1348 struct gpio_dev_priv *uc_priv;
Heiko Schocherb74fcb42014-05-22 12:43:05 +02001349 struct udevice *dev;
Simon Glasse821d182014-02-26 15:59:24 -07001350 struct uclass *uc;
1351 unsigned base;
1352 int ret;
1353
1354 ret = uclass_get(UCLASS_GPIO, &uc);
1355 if (ret)
1356 return ret;
1357
1358 /* Ensure that we have a base for each bank */
1359 base = 0;
1360 uclass_foreach_dev(dev, uc) {
Simon Glass0f4517d2014-10-04 11:29:42 -06001361 if (device_active(dev) && dev != removed_dev) {
Simon Glassde0977b2015-03-05 12:25:20 -07001362 uc_priv = dev_get_uclass_priv(dev);
Simon Glasse821d182014-02-26 15:59:24 -07001363 uc_priv->gpio_base = base;
1364 base += uc_priv->gpio_count;
1365 }
1366 }
1367
1368 return 0;
1369}
1370
Simon Glassfd838972016-03-06 19:27:51 -07001371int gpio_get_number(const struct gpio_desc *desc)
Simon Glass94f54d12015-03-25 12:21:58 -06001372{
1373 struct udevice *dev = desc->dev;
1374 struct gpio_dev_priv *uc_priv;
1375
1376 if (!dev)
1377 return -1;
Simon Glass95588622020-12-22 19:30:28 -07001378 uc_priv = dev_get_uclass_priv(dev);
Simon Glass94f54d12015-03-25 12:21:58 -06001379
1380 return uc_priv->gpio_base + desc->offset;
1381}
1382
Heiko Schocherb74fcb42014-05-22 12:43:05 +02001383static int gpio_post_probe(struct udevice *dev)
Simon Glasse821d182014-02-26 15:59:24 -07001384{
Simon Glassde0977b2015-03-05 12:25:20 -07001385 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
Simon Glass0f4517d2014-10-04 11:29:42 -06001386
1387 uc_priv->name = calloc(uc_priv->gpio_count, sizeof(char *));
1388 if (!uc_priv->name)
1389 return -ENOMEM;
Marek Vasut3a188472023-08-02 01:26:02 +02001390
1391 uc_priv->claimed = calloc(DIV_ROUND_UP(uc_priv->gpio_count,
1392 GPIO_ALLOC_BITS),
1393 GPIO_ALLOC_BITS / 8);
1394 if (!uc_priv->claimed) {
1395 free(uc_priv->name);
1396 return -ENOMEM;
1397 }
Simon Glass0f4517d2014-10-04 11:29:42 -06001398
1399 return gpio_renumber(NULL);
Simon Glasse821d182014-02-26 15:59:24 -07001400}
1401
Heiko Schocherb74fcb42014-05-22 12:43:05 +02001402static int gpio_pre_remove(struct udevice *dev)
Simon Glasse821d182014-02-26 15:59:24 -07001403{
Simon Glassde0977b2015-03-05 12:25:20 -07001404 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
Simon Glass0f4517d2014-10-04 11:29:42 -06001405 int i;
1406
1407 for (i = 0; i < uc_priv->gpio_count; i++) {
1408 if (uc_priv->name[i])
1409 free(uc_priv->name[i]);
1410 }
Marek Vasut3a188472023-08-02 01:26:02 +02001411 free(uc_priv->claimed);
Simon Glass0f4517d2014-10-04 11:29:42 -06001412 free(uc_priv->name);
1413
1414 return gpio_renumber(dev);
Simon Glasse821d182014-02-26 15:59:24 -07001415}
1416
Heiko Schocher39cb3402019-06-12 06:11:46 +02001417int gpio_dev_request_index(struct udevice *dev, const char *nodename,
1418 char *list_name, int index, int flags,
1419 int dtflags, struct gpio_desc *desc)
1420{
1421 struct ofnode_phandle_args args;
1422
1423 args.node = ofnode_null();
1424 args.args_count = 2;
1425 args.args[0] = index;
1426 args.args[1] = dtflags;
1427
1428 return gpio_request_tail(0, nodename, &args, list_name, index, desc,
1429 flags, 0, dev);
1430}
1431
Jean-Jacques Hiblot775d6a22020-09-11 13:43:34 +05301432static void devm_gpiod_release(struct udevice *dev, void *res)
1433{
1434 dm_gpio_free(dev, res);
1435}
1436
1437static int devm_gpiod_match(struct udevice *dev, void *res, void *data)
1438{
1439 return res == data;
1440}
1441
1442struct gpio_desc *devm_gpiod_get_index(struct udevice *dev, const char *id,
1443 unsigned int index, int flags)
1444{
1445 int rc;
1446 struct gpio_desc *desc;
1447 char *propname;
1448 static const char suffix[] = "-gpios";
1449
1450 propname = malloc(strlen(id) + sizeof(suffix));
1451 if (!propname) {
1452 rc = -ENOMEM;
1453 goto end;
1454 }
1455
1456 strcpy(propname, id);
1457 strcat(propname, suffix);
1458
1459 desc = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc),
1460 __GFP_ZERO);
1461 if (unlikely(!desc)) {
1462 rc = -ENOMEM;
1463 goto end;
1464 }
1465
1466 rc = gpio_request_by_name(dev, propname, index, desc, flags);
1467
1468end:
1469 if (propname)
1470 free(propname);
1471
1472 if (rc)
1473 return ERR_PTR(rc);
1474
1475 devres_add(dev, desc);
1476
1477 return desc;
1478}
1479
1480struct gpio_desc *devm_gpiod_get_index_optional(struct udevice *dev,
1481 const char *id,
1482 unsigned int index,
1483 int flags)
1484{
1485 struct gpio_desc *desc = devm_gpiod_get_index(dev, id, index, flags);
1486
1487 if (IS_ERR(desc))
1488 return NULL;
1489
1490 return desc;
1491}
1492
1493void devm_gpiod_put(struct udevice *dev, struct gpio_desc *desc)
1494{
1495 int rc;
1496
1497 rc = devres_release(dev, devm_gpiod_release, devm_gpiod_match, desc);
1498 WARN_ON(rc);
1499}
1500
Michal Simek5f7202c2018-07-12 12:42:27 +02001501static int gpio_post_bind(struct udevice *dev)
1502{
Simon Glasse418c632023-06-01 10:22:30 -06001503 if (CONFIG_IS_ENABLED(GPIO_HOG) && dev_has_ofnode(dev)) {
Eddie James652b8692022-02-07 17:09:01 -06001504 struct udevice *child;
1505 ofnode node;
1506
Heiko Schocher58e4c382019-07-17 06:59:51 +02001507 dev_for_each_subnode(node, dev) {
1508 if (ofnode_read_bool(node, "gpio-hog")) {
1509 const char *name = ofnode_get_name(node);
1510 int ret;
Heiko Schocher39cb3402019-06-12 06:11:46 +02001511
Heiko Schocher58e4c382019-07-17 06:59:51 +02001512 ret = device_bind_driver_to_node(dev,
1513 "gpio_hog",
1514 name, node,
1515 &child);
1516 if (ret)
1517 return ret;
Marek Vasutba3982f2022-09-22 17:53:26 +02001518
1519 /*
1520 * Make sure gpio-hogs are probed after bind
1521 * since hogs can be essential to the hardware
1522 * system.
1523 */
1524 dev_or_flags(child, DM_FLAG_PROBE_AFTER_BIND);
Heiko Schocher58e4c382019-07-17 06:59:51 +02001525 }
Heiko Schocher39cb3402019-06-12 06:11:46 +02001526 }
1527 }
Marek Vasutba3982f2022-09-22 17:53:26 +02001528
Michal Simek5f7202c2018-07-12 12:42:27 +02001529 return 0;
1530}
1531
Simon Glasse821d182014-02-26 15:59:24 -07001532UCLASS_DRIVER(gpio) = {
1533 .id = UCLASS_GPIO,
1534 .name = "gpio",
Bhuvanchandra DVb1a1fc92015-06-01 18:37:15 +05301535 .flags = DM_UC_FLAG_SEQ_ALIAS,
Simon Glasse821d182014-02-26 15:59:24 -07001536 .post_probe = gpio_post_probe,
Michal Simek5f7202c2018-07-12 12:42:27 +02001537 .post_bind = gpio_post_bind,
Simon Glasse821d182014-02-26 15:59:24 -07001538 .pre_remove = gpio_pre_remove,
Simon Glass8a2b47f2020-12-03 16:55:17 -07001539 .per_device_auto = sizeof(struct gpio_dev_priv),
Simon Glasse821d182014-02-26 15:59:24 -07001540};