blob: 0213271e3a69d7d6b39837f9dca902149368672a [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 {
708 if (flags & GPIOD_IS_OUT) {
Simon Glass7b893f92021-02-04 21:22:03 -0700709 bool value = flags & GPIOD_IS_OUT_ACTIVE;
710
711 ret = ops->direction_output(dev, desc->offset, value);
Patrick Delaunay684326f2020-01-13 11:35:09 +0100712 } else if (flags & GPIOD_IS_IN) {
713 ret = ops->direction_input(dev, desc->offset);
714 }
Simon Glassce555292015-01-05 20:05:27 -0700715 }
Patrick Delaunay3b2a1172020-01-13 11:35:03 +0100716
717 return ret;
718}
719
Simon Glass7b893f92021-02-04 21:22:03 -0700720int dm_gpio_clrset_flags(struct gpio_desc *desc, ulong clr, ulong set)
Patrick Delaunay3b2a1172020-01-13 11:35:03 +0100721{
Simon Glass7b893f92021-02-04 21:22:03 -0700722 ulong flags;
Patrick Delaunay3b2a1172020-01-13 11:35:03 +0100723 int ret;
724
725 ret = check_reserved(desc, "set_dir_flags");
Simon Glassce555292015-01-05 20:05:27 -0700726 if (ret)
727 return ret;
Patrick Delaunay3b2a1172020-01-13 11:35:03 +0100728
Simon Glass7b893f92021-02-04 21:22:03 -0700729 flags = (desc->flags & ~clr) | set;
730
Simon Glass54befdd2021-02-04 21:21:55 -0700731 ret = _dm_gpio_set_flags(desc, flags);
Simon Glass7b893f92021-02-04 21:22:03 -0700732 if (ret)
733 return ret;
Simon Glassce555292015-01-05 20:05:27 -0700734
Simon Glass7b893f92021-02-04 21:22:03 -0700735 /* save the flags also in descriptor */
736 desc->flags = flags;
737
738 return 0;
739}
740
741int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
742{
743 /* combine the requested flags (for IN/OUT) and the descriptor flags */
744 return dm_gpio_clrset_flags(desc, GPIOD_MASK_DIR, flags);
Simon Glassce555292015-01-05 20:05:27 -0700745}
746
Simon Glass247ccf22021-02-04 21:22:09 -0700747int dm_gpios_clrset_flags(struct gpio_desc *desc, int count, ulong clr,
748 ulong set)
749{
750 int ret;
751 int i;
752
753 for (i = 0; i < count; i++) {
754 ret = dm_gpio_clrset_flags(&desc[i], clr, set);
755 if (ret)
756 return log_ret(ret);
757 }
758
759 return 0;
760}
761
Simon Glass909bee32021-02-04 21:21:57 -0700762int dm_gpio_get_flags(struct gpio_desc *desc, ulong *flagsp)
Patrick Delaunayaecf9d72020-01-13 11:35:06 +0100763{
Patrick Delaunayfbacd622020-01-13 11:35:08 +0100764 struct udevice *dev = desc->dev;
765 int ret, value;
Simon Glass49f315a2021-02-04 21:22:05 -0700766 const struct dm_gpio_ops *ops = gpio_get_ops(dev);
Simon Glassd063ce92021-02-04 21:21:56 -0700767 ulong flags;
Patrick Delaunayaecf9d72020-01-13 11:35:06 +0100768
Simon Glassd063ce92021-02-04 21:21:56 -0700769 ret = check_reserved(desc, "get_flags");
Patrick Delaunayaecf9d72020-01-13 11:35:06 +0100770 if (ret)
771 return ret;
772
Patrick Delaunayfbacd622020-01-13 11:35:08 +0100773 /* GPIOD_ are directly provided by driver except GPIOD_ACTIVE_LOW */
Simon Glassd063ce92021-02-04 21:21:56 -0700774 if (ops->get_flags) {
775 ret = ops->get_flags(dev, desc->offset, &flags);
Patrick Delaunayfbacd622020-01-13 11:35:08 +0100776 if (ret)
777 return ret;
Patrick Delaunayaecf9d72020-01-13 11:35:06 +0100778
Patrick Delaunayfbacd622020-01-13 11:35:08 +0100779 /* GPIOD_ACTIVE_LOW is saved in desc->flags */
Simon Glassd063ce92021-02-04 21:21:56 -0700780 value = flags & GPIOD_IS_OUT_ACTIVE ? 1 : 0;
Patrick Delaunayfbacd622020-01-13 11:35:08 +0100781 if (desc->flags & GPIOD_ACTIVE_LOW)
782 value = !value;
Simon Glassd063ce92021-02-04 21:21:56 -0700783 flags &= ~(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT_ACTIVE);
784 flags |= (desc->flags & GPIOD_ACTIVE_LOW);
Patrick Delaunayfbacd622020-01-13 11:35:08 +0100785 if (value)
Simon Glassd063ce92021-02-04 21:21:56 -0700786 flags |= GPIOD_IS_OUT_ACTIVE;
Patrick Delaunayfbacd622020-01-13 11:35:08 +0100787 } else {
Simon Glassd063ce92021-02-04 21:21:56 -0700788 flags = desc->flags;
Patrick Delaunayfbacd622020-01-13 11:35:08 +0100789 /* only GPIOD_IS_OUT_ACTIVE is provided by uclass */
Simon Glassd063ce92021-02-04 21:21:56 -0700790 flags &= ~GPIOD_IS_OUT_ACTIVE;
Patrick Delaunayfbacd622020-01-13 11:35:08 +0100791 if ((desc->flags & GPIOD_IS_OUT) && _gpio_get_value(desc))
Simon Glassd063ce92021-02-04 21:21:56 -0700792 flags |= GPIOD_IS_OUT_ACTIVE;
Patrick Delaunayfbacd622020-01-13 11:35:08 +0100793 }
Simon Glassd063ce92021-02-04 21:21:56 -0700794 *flagsp = flags;
Patrick Delaunayaecf9d72020-01-13 11:35:06 +0100795
796 return 0;
797}
798
Simon Glasse821d182014-02-26 15:59:24 -0700799/**
800 * gpio_get_value() - [COMPAT] Sample GPIO pin and return it's value
801 * gpio: GPIO number
802 *
803 * This function implements the API that's compatible with current
804 * GPIO API used in U-Boot. The request is forwarded to particular
805 * GPIO driver. Returns the value of the GPIO pin, or negative value
806 * on error.
807 */
808int gpio_get_value(unsigned gpio)
809{
Simon Glasse821d182014-02-26 15:59:24 -0700810 int ret;
811
Simon Glassce555292015-01-05 20:05:27 -0700812 struct gpio_desc desc;
813
814 ret = gpio_to_device(gpio, &desc);
Simon Glasse821d182014-02-26 15:59:24 -0700815 if (ret)
816 return ret;
Simon Glassce555292015-01-05 20:05:27 -0700817 return dm_gpio_get_value(&desc);
Simon Glasse821d182014-02-26 15:59:24 -0700818}
819
820/**
821 * gpio_set_value() - [COMPAT] Configure logical value on GPIO pin
822 * gpio: GPIO number
823 * value: Logical value to be set on the GPIO pin.
824 *
825 * This function implements the API that's compatible with current
826 * GPIO API used in U-Boot. The request is forwarded to particular
827 * GPIO driver. Returns 0 on success, negative value on error.
828 */
829int gpio_set_value(unsigned gpio, int value)
830{
Simon Glassce555292015-01-05 20:05:27 -0700831 struct gpio_desc desc;
Simon Glasse821d182014-02-26 15:59:24 -0700832 int ret;
833
Simon Glassce555292015-01-05 20:05:27 -0700834 ret = gpio_to_device(gpio, &desc);
Simon Glasse821d182014-02-26 15:59:24 -0700835 if (ret)
836 return ret;
Simon Glassce555292015-01-05 20:05:27 -0700837 return dm_gpio_set_value(&desc, value);
Simon Glasse821d182014-02-26 15:59:24 -0700838}
839
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200840const char *gpio_get_bank_info(struct udevice *dev, int *bit_count)
Simon Glasse821d182014-02-26 15:59:24 -0700841{
842 struct gpio_dev_priv *priv;
843
844 /* Must be called on an active device */
Simon Glassde0977b2015-03-05 12:25:20 -0700845 priv = dev_get_uclass_priv(dev);
Simon Glasse821d182014-02-26 15:59:24 -0700846 assert(priv);
847
848 *bit_count = priv->gpio_count;
849 return priv->bank_name;
850}
851
Simon Glass6e5e6dd2014-10-04 11:29:43 -0600852static const char * const gpio_function[GPIOF_COUNT] = {
853 "input",
854 "output",
855 "unused",
856 "unknown",
857 "func",
858};
859
Masahiro Yamada286c2522017-06-22 16:50:25 +0900860static int get_function(struct udevice *dev, int offset, bool skip_unused,
861 const char **namep)
Simon Glass6e5e6dd2014-10-04 11:29:43 -0600862{
Simon Glassde0977b2015-03-05 12:25:20 -0700863 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
Simon Glass49f315a2021-02-04 21:22:05 -0700864 const struct dm_gpio_ops *ops = gpio_get_ops(dev);
Simon Glass6e5e6dd2014-10-04 11:29:43 -0600865
866 BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function));
867 if (!device_active(dev))
868 return -ENODEV;
869 if (offset < 0 || offset >= uc_priv->gpio_count)
870 return -EINVAL;
871 if (namep)
872 *namep = uc_priv->name[offset];
Marek Vasut3a188472023-08-02 01:26:02 +0200873 if (skip_unused && !gpio_is_claimed(uc_priv, offset))
Simon Glass6e5e6dd2014-10-04 11:29:43 -0600874 return GPIOF_UNUSED;
875 if (ops->get_function) {
876 int ret;
877
878 ret = ops->get_function(dev, offset);
879 if (ret < 0)
880 return ret;
881 if (ret >= ARRAY_SIZE(gpio_function))
882 return -ENODATA;
883 return ret;
884 }
885
886 return GPIOF_UNKNOWN;
887}
888
889int gpio_get_function(struct udevice *dev, int offset, const char **namep)
890{
891 return get_function(dev, offset, true, namep);
892}
893
894int gpio_get_raw_function(struct udevice *dev, int offset, const char **namep)
895{
896 return get_function(dev, offset, false, namep);
897}
898
Simon Glass6b1ef592014-10-04 11:29:44 -0600899int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize)
900{
Simon Glass49f315a2021-02-04 21:22:05 -0700901 const struct dm_gpio_ops *ops = gpio_get_ops(dev);
Simon Glass6b1ef592014-10-04 11:29:44 -0600902 struct gpio_dev_priv *priv;
903 char *str = buf;
Patrice Chotard8b1310e2022-08-30 14:09:11 +0200904 const char *label;
Simon Glass6b1ef592014-10-04 11:29:44 -0600905 int func;
906 int ret;
907 int len;
Patrice Chotard8b1310e2022-08-30 14:09:11 +0200908 bool used;
Simon Glass6b1ef592014-10-04 11:29:44 -0600909
910 BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function));
911
912 *buf = 0;
Simon Glassde0977b2015-03-05 12:25:20 -0700913 priv = dev_get_uclass_priv(dev);
Patrice Chotard8b1310e2022-08-30 14:09:11 +0200914 ret = gpio_get_raw_function(dev, offset, &label);
Simon Glass6b1ef592014-10-04 11:29:44 -0600915 if (ret < 0)
916 return ret;
917 func = ret;
918 len = snprintf(str, buffsize, "%s%d: %s",
919 priv->bank_name ? priv->bank_name : "",
920 offset, gpio_function[func]);
Simon Glass6b1ef592014-10-04 11:29:44 -0600921
Patrice Chotard8b1310e2022-08-30 14:09:11 +0200922 switch (func) {
923 case GPIOF_FUNC:
924 snprintf(str + len, buffsize - len, " %s", label ? label : "");
925 break;
926 case GPIOF_INPUT:
927 case GPIOF_OUTPUT:
928 case GPIOF_UNUSED:
Simon Glass6b1ef592014-10-04 11:29:44 -0600929 ret = ops->get_value(dev, offset);
930 if (ret < 0)
931 return ret;
932 used = gpio_get_function(dev, offset, &label) != GPIOF_UNUSED;
933 snprintf(str + len, buffsize - len, ": %d [%c]%s%s",
934 ret,
935 used ? 'x' : ' ',
Patrice Chotardeb8f3a72022-08-30 14:09:12 +0200936 label ? " " : "",
Simon Glass6b1ef592014-10-04 11:29:44 -0600937 label ? label : "");
Patrice Chotard8b1310e2022-08-30 14:09:11 +0200938 break;
Simon Glass6b1ef592014-10-04 11:29:44 -0600939 }
940
941 return 0;
942}
943
Simon Glass3176b6c2020-07-07 13:11:44 -0600944#if CONFIG_IS_ENABLED(ACPIGEN)
945int gpio_get_acpi(const struct gpio_desc *desc, struct acpi_gpio *gpio)
946{
Simon Glass49f315a2021-02-04 21:22:05 -0700947 const struct dm_gpio_ops *ops;
Simon Glass3176b6c2020-07-07 13:11:44 -0600948
949 memset(gpio, '\0', sizeof(*gpio));
950 if (!dm_gpio_is_valid(desc)) {
951 /* Indicate that the GPIO is not valid */
952 gpio->pin_count = 0;
953 gpio->pins[0] = 0;
954 return -EINVAL;
955 }
956
957 ops = gpio_get_ops(desc->dev);
958 if (!ops->get_acpi)
959 return -ENOSYS;
960
961 return ops->get_acpi(desc, gpio);
962}
963#endif
964
Simon Glassbef54db2015-04-14 21:03:20 -0600965int gpio_claim_vector(const int *gpio_num_array, const char *fmt)
966{
967 int i, ret;
968 int gpio;
969
970 for (i = 0; i < 32; i++) {
971 gpio = gpio_num_array[i];
972 if (gpio == -1)
973 break;
974 ret = gpio_requestf(gpio, fmt, i);
975 if (ret)
976 goto err;
977 ret = gpio_direction_input(gpio);
978 if (ret) {
979 gpio_free(gpio);
980 goto err;
981 }
982 }
983
984 return 0;
985err:
986 for (i--; i >= 0; i--)
987 gpio_free(gpio_num_array[i]);
988
989 return ret;
990}
991
Simon Glass2c97a8f2014-11-10 18:00:21 -0700992/*
993 * get a number comprised of multiple GPIO values. gpio_num_array points to
994 * the array of gpio pin numbers to scan, terminated by -1.
995 */
Simon Glassbef54db2015-04-14 21:03:20 -0600996int gpio_get_values_as_int(const int *gpio_list)
Simon Glass2c97a8f2014-11-10 18:00:21 -0700997{
998 int gpio;
999 unsigned bitmask = 1;
1000 unsigned vector = 0;
Simon Glassbef54db2015-04-14 21:03:20 -06001001 int ret;
Simon Glass2c97a8f2014-11-10 18:00:21 -07001002
1003 while (bitmask &&
Simon Glassbef54db2015-04-14 21:03:20 -06001004 ((gpio = *gpio_list++) != -1)) {
1005 ret = gpio_get_value(gpio);
1006 if (ret < 0)
1007 return ret;
1008 else if (ret)
Simon Glass2c97a8f2014-11-10 18:00:21 -07001009 vector |= bitmask;
1010 bitmask <<= 1;
1011 }
Simon Glassbef54db2015-04-14 21:03:20 -06001012
Simon Glass2c97a8f2014-11-10 18:00:21 -07001013 return vector;
1014}
1015
Simon Glassfd838972016-03-06 19:27:51 -07001016int dm_gpio_get_values_as_int(const struct gpio_desc *desc_list, int count)
Simon Glassdf1687d2016-03-06 19:27:50 -07001017{
1018 unsigned bitmask = 1;
1019 unsigned vector = 0;
1020 int ret, i;
1021
1022 for (i = 0; i < count; i++) {
1023 ret = dm_gpio_get_value(&desc_list[i]);
1024 if (ret < 0)
1025 return ret;
1026 else if (ret)
1027 vector |= bitmask;
1028 bitmask <<= 1;
1029 }
Simon Glass247ccf22021-02-04 21:22:09 -07001030
1031 return vector;
1032}
1033
1034int dm_gpio_get_values_as_int_base3(struct gpio_desc *desc_list,
1035 int count)
1036{
1037 static const char tristate[] = "01z";
1038 enum {
1039 PULLUP,
1040 PULLDOWN,
1041
1042 NUM_OPTIONS,
1043 };
1044 int vals[NUM_OPTIONS];
1045 uint mask;
1046 uint vector = 0;
1047 int ret, i;
1048
1049 /*
1050 * Limit to 19 digits which should be plenty. This avoids overflow of a
1051 * 32-bit int
1052 */
1053 assert(count < 20);
1054
1055 for (i = 0; i < NUM_OPTIONS; i++) {
1056 uint flags = GPIOD_IS_IN;
1057
1058 flags |= (i == PULLDOWN) ? GPIOD_PULL_DOWN : GPIOD_PULL_UP;
1059 ret = dm_gpios_clrset_flags(desc_list, count, GPIOD_MASK_PULL,
1060 flags);
1061 if (ret)
1062 return log_msg_ret("pu", ret);
1063
1064 /* Give the lines time to settle */
1065 udelay(10);
1066
1067 ret = dm_gpio_get_values_as_int(desc_list, count);
1068 if (ret < 0)
1069 return log_msg_ret("get1", ret);
1070 vals[i] = ret;
1071 }
1072
1073 log_debug("values: %x %x, count = %d\n", vals[0], vals[1], count);
1074 for (i = count - 1, mask = 1 << i; i >= 0; i--, mask >>= 1) {
1075 uint pd = vals[PULLDOWN] & mask ? 1 : 0;
1076 uint pu = vals[PULLUP] & mask ? 1 : 0;
1077 uint digit;
1078
1079 /*
1080 * Get value with internal pulldown active. If this is 1 then
1081 * there is a stronger external pullup, which we call 1. If not
1082 * then call it 0.
1083 *
1084 * If the values differ then the pin is floating so we call
1085 * this a 2.
1086 */
1087 if (pu == pd)
1088 digit = pd;
1089 else
1090 digit = 2;
1091 log_debug("%c ", tristate[digit]);
1092 vector = 3 * vector + digit;
1093 }
1094 log_debug("vector=%d\n", vector);
Simon Glassdf1687d2016-03-06 19:27:50 -07001095
1096 return vector;
1097}
1098
Heiko Schocher58e4c382019-07-17 06:59:51 +02001099/**
1100 * gpio_request_tail: common work for requesting a gpio.
1101 *
1102 * ret: return value from previous work in function which calls
1103 * this function.
1104 * This seems bogus (why calling this function instead not
1105 * calling it and end caller function instead?).
1106 * Because on error in caller function we want to set some
1107 * default values in gpio desc and have a common error
1108 * debug message, which provides this function.
1109 * nodename: Name of node for which gpio gets requested
1110 * used for gpio label name.
1111 * args: pointer to output arguments structure
1112 * list_name: Name of GPIO list
1113 * used for gpio label name.
1114 * index: gpio index in gpio list
1115 * used for gpio label name.
1116 * desc: pointer to gpio descriptor, filled from this
1117 * function.
1118 * flags: gpio flags to use.
1119 * add_index: should index added to gpio label name
1120 * gpio_dev: pointer to gpio device from which the gpio
1121 * will be requested. If NULL try to get the
1122 * gpio device with uclass_get_device_by_ofnode()
1123 *
1124 * return: In error case this function sets default values in
1125 * gpio descriptor, also emmits a debug message.
1126 * On success it returns 0 else the error code from
1127 * function calls, or the error code passed through
1128 * ret to this function.
1129 *
1130 */
Heiko Schocher39cb3402019-06-12 06:11:46 +02001131static int gpio_request_tail(int ret, const char *nodename,
Simon Glass12faa022017-05-18 20:09:18 -06001132 struct ofnode_phandle_args *args,
1133 const char *list_name, int index,
Heiko Schocher39cb3402019-06-12 06:11:46 +02001134 struct gpio_desc *desc, int flags,
Heiko Schocher58e4c382019-07-17 06:59:51 +02001135 bool add_index, struct udevice *gpio_dev)
Simon Glass16e10402015-01-05 20:05:29 -07001136{
Patrick Delaunay758bba92020-01-13 11:35:01 +01001137 gpio_desc_init(desc, gpio_dev, 0);
Simon Glass12faa022017-05-18 20:09:18 -06001138 if (ret)
Simon Glass16e10402015-01-05 20:05:29 -07001139 goto err;
Simon Glass16e10402015-01-05 20:05:29 -07001140
Heiko Schocher39cb3402019-06-12 06:11:46 +02001141 if (!desc->dev) {
1142 ret = uclass_get_device_by_ofnode(UCLASS_GPIO, args->node,
1143 &desc->dev);
1144 if (ret) {
Svyatoslav Ryhel5aeca6a2023-07-26 17:10:06 +03001145#if CONFIG_IS_ENABLED(MAX77663_GPIO) || CONFIG_IS_ENABLED(PALMAS_GPIO)
1146 struct udevice *pmic;
1147 ret = uclass_get_device_by_ofnode(UCLASS_PMIC, args->node,
1148 &pmic);
1149 if (ret) {
1150 log_debug("%s: PMIC device get failed, err %d\n",
1151 __func__, ret);
1152 goto err;
1153 }
1154
1155 device_foreach_child(desc->dev, pmic) {
1156 if (device_get_uclass_id(desc->dev) == UCLASS_GPIO)
1157 break;
1158 }
1159
1160 /* if loop exits without GPIO device return error */
1161 if (device_get_uclass_id(desc->dev) != UCLASS_GPIO)
1162 goto err;
1163#else
Heiko Schocher58e4c382019-07-17 06:59:51 +02001164 debug("%s: uclass_get_device_by_ofnode failed\n",
1165 __func__);
Heiko Schocher39cb3402019-06-12 06:11:46 +02001166 goto err;
Svyatoslav Ryhel5aeca6a2023-07-26 17:10:06 +03001167#endif
Heiko Schocher39cb3402019-06-12 06:11:46 +02001168 }
Simon Glass16e10402015-01-05 20:05:29 -07001169 }
Simon Glass12faa022017-05-18 20:09:18 -06001170 ret = gpio_find_and_xlate(desc, args);
Simon Glass16e10402015-01-05 20:05:29 -07001171 if (ret) {
1172 debug("%s: gpio_find_and_xlate failed\n", __func__);
1173 goto err;
1174 }
1175 ret = dm_gpio_requestf(desc, add_index ? "%s.%s%d" : "%s.%s",
Heiko Schocher39cb3402019-06-12 06:11:46 +02001176 nodename, list_name, index);
Simon Glass16e10402015-01-05 20:05:29 -07001177 if (ret) {
1178 debug("%s: dm_gpio_requestf failed\n", __func__);
1179 goto err;
1180 }
Simon Glass7b893f92021-02-04 21:22:03 -07001181
1182 /* Keep any direction flags provided by the devicetree */
1183 ret = dm_gpio_set_dir_flags(desc,
1184 flags | (desc->flags & GPIOD_MASK_DIR));
Simon Glass16e10402015-01-05 20:05:29 -07001185 if (ret) {
1186 debug("%s: dm_gpio_set_dir failed\n", __func__);
1187 goto err;
1188 }
1189
1190 return 0;
1191err:
1192 debug("%s: Node '%s', property '%s', failed to request GPIO index %d: %d\n",
Heiko Schocher39cb3402019-06-12 06:11:46 +02001193 __func__, nodename, list_name, index, ret);
Simon Glass16e10402015-01-05 20:05:29 -07001194 return ret;
1195}
1196
Simon Glass92882652021-08-07 07:24:04 -06001197#if CONFIG_IS_ENABLED(OF_REAL)
Simon Glass1d9af1f2017-05-30 21:47:09 -06001198static int _gpio_request_by_name_nodev(ofnode node, const char *list_name,
1199 int index, struct gpio_desc *desc,
1200 int flags, bool add_index)
Simon Glass12faa022017-05-18 20:09:18 -06001201{
1202 struct ofnode_phandle_args args;
1203 int ret;
1204
Simon Glass1d9af1f2017-05-30 21:47:09 -06001205 ret = ofnode_parse_phandle_with_args(node, list_name, "#gpio-cells", 0,
1206 index, &args);
Simon Glass12faa022017-05-18 20:09:18 -06001207
Heiko Schocher39cb3402019-06-12 06:11:46 +02001208 return gpio_request_tail(ret, ofnode_get_name(node), &args, list_name,
1209 index, desc, flags, add_index, NULL);
Simon Glass12faa022017-05-18 20:09:18 -06001210}
1211
Simon Glass1d9af1f2017-05-30 21:47:09 -06001212int gpio_request_by_name_nodev(ofnode node, const char *list_name, int index,
Simon Glass16e10402015-01-05 20:05:29 -07001213 struct gpio_desc *desc, int flags)
1214{
Simon Glass1d9af1f2017-05-30 21:47:09 -06001215 return _gpio_request_by_name_nodev(node, list_name, index, desc, flags,
1216 index > 0);
Simon Glass16e10402015-01-05 20:05:29 -07001217}
1218
Simon Glass1d9af1f2017-05-30 21:47:09 -06001219int gpio_request_by_name(struct udevice *dev, const char *list_name, int index,
Simon Glass16e10402015-01-05 20:05:29 -07001220 struct gpio_desc *desc, int flags)
1221{
Simon Glass1d9af1f2017-05-30 21:47:09 -06001222 struct ofnode_phandle_args args;
Heiko Schocher39cb3402019-06-12 06:11:46 +02001223 ofnode node;
Simon Glass1d9af1f2017-05-30 21:47:09 -06001224 int ret;
1225
1226 ret = dev_read_phandle_with_args(dev, list_name, "#gpio-cells", 0,
1227 index, &args);
Heiko Schocher39cb3402019-06-12 06:11:46 +02001228 node = dev_ofnode(dev);
1229 return gpio_request_tail(ret, ofnode_get_name(node), &args, list_name,
1230 index, desc, flags, index > 0, NULL);
Simon Glass16e10402015-01-05 20:05:29 -07001231}
1232
Andrew Jeffery2e62c6b2022-01-31 13:54:05 +10301233int gpio_request_by_line_name(struct udevice *dev, const char *line_name,
1234 struct gpio_desc *desc, int flags)
1235{
1236 int ret;
1237
Rasmus Villemoesf4e744d2023-03-17 21:12:22 +01001238 if (!dev) {
1239 uclass_foreach_dev_probe(UCLASS_GPIO, dev)
1240 if (!gpio_request_by_line_name(dev, line_name, desc, flags))
1241 return 0;
1242 return -ENOENT;
1243 }
1244
Andrew Jeffery2e62c6b2022-01-31 13:54:05 +10301245 ret = dev_read_stringlist_search(dev, "gpio-line-names", line_name);
1246 if (ret < 0)
1247 return ret;
1248
1249 desc->dev = dev;
1250 desc->offset = ret;
1251 desc->flags = 0;
1252
1253 ret = dm_gpio_request(desc, line_name);
1254 if (ret) {
1255 debug("%s: dm_gpio_requestf failed\n", __func__);
1256 return ret;
1257 }
1258
1259 ret = dm_gpio_set_dir_flags(desc, flags | desc->flags);
1260 if (ret)
1261 debug("%s: dm_gpio_set_dir failed\n", __func__);
1262
1263 return ret;
1264}
1265
Simon Glass1d9af1f2017-05-30 21:47:09 -06001266int gpio_request_list_by_name_nodev(ofnode node, const char *list_name,
Simon Glass16e10402015-01-05 20:05:29 -07001267 struct gpio_desc *desc, int max_count,
1268 int flags)
1269{
1270 int count;
1271 int ret;
1272
Przemyslaw Marczak44fc5362015-03-31 18:57:16 +02001273 for (count = 0; count < max_count; count++) {
Simon Glass1d9af1f2017-05-30 21:47:09 -06001274 ret = _gpio_request_by_name_nodev(node, list_name, count,
Simon Glass16e10402015-01-05 20:05:29 -07001275 &desc[count], flags, true);
1276 if (ret == -ENOENT)
1277 break;
1278 else if (ret)
1279 goto err;
1280 }
1281
1282 /* We ran out of GPIOs in the list */
1283 return count;
1284
1285err:
Rasmus Villemoesc9ca11c2023-04-19 12:10:13 +02001286 gpio_free_list_nodev(desc, count);
Simon Glass16e10402015-01-05 20:05:29 -07001287
1288 return ret;
1289}
1290
1291int gpio_request_list_by_name(struct udevice *dev, const char *list_name,
1292 struct gpio_desc *desc, int max_count,
1293 int flags)
1294{
1295 /*
1296 * This isn't ideal since we don't use dev->name in the debug()
1297 * calls in gpio_request_by_name(), but we can do this until
1298 * gpio_request_list_by_name_nodev() can be dropped.
1299 */
Simon Glass1d9af1f2017-05-30 21:47:09 -06001300 return gpio_request_list_by_name_nodev(dev_ofnode(dev), list_name, desc,
1301 max_count, flags);
Simon Glass16e10402015-01-05 20:05:29 -07001302}
1303
1304int gpio_get_list_count(struct udevice *dev, const char *list_name)
1305{
1306 int ret;
1307
Sean Anderson8ad66c52021-04-20 10:50:54 -04001308 ret = dev_count_phandle_with_args(dev, list_name, "#gpio-cells",
1309 -ENOENT);
1310 if (ret < 0) {
Simon Glass16e10402015-01-05 20:05:29 -07001311 debug("%s: Node '%s', property '%s', GPIO count failed: %d\n",
1312 __func__, dev->name, list_name, ret);
1313 }
1314
1315 return ret;
1316}
Simon Glassea383722021-02-04 21:21:54 -07001317#endif /* OF_PLATDATA */
Simon Glass16e10402015-01-05 20:05:29 -07001318
Simon Glass2149e112021-08-07 07:24:12 -06001319#if CONFIG_IS_ENABLED(OF_PLATDATA)
1320int gpio_request_by_phandle(struct udevice *dev,
1321 const struct phandle_2_arg *cells,
1322 struct gpio_desc *desc, int flags)
1323{
1324 struct ofnode_phandle_args args;
1325 struct udevice *gpio_dev;
1326 const int index = 0;
1327 int ret;
1328
1329 ret = device_get_by_ofplat_idx(cells->idx, &gpio_dev);
1330 if (ret)
1331 return ret;
1332 args.args[0] = cells->arg[0];
1333 args.args[1] = cells->arg[1];
1334
1335 return gpio_request_tail(ret, NULL, &args, NULL, index, desc, flags,
1336 index > 0, gpio_dev);
1337}
1338#endif
1339
Simon Glass16e10402015-01-05 20:05:29 -07001340int dm_gpio_free(struct udevice *dev, struct gpio_desc *desc)
1341{
1342 /* For now, we don't do any checking of dev */
1343 return _dm_gpio_free(desc->dev, desc->offset);
1344}
1345
1346int gpio_free_list(struct udevice *dev, struct gpio_desc *desc, int count)
1347{
1348 int i;
1349
1350 /* For now, we don't do any checking of dev */
1351 for (i = 0; i < count; i++)
1352 dm_gpio_free(dev, &desc[i]);
1353
1354 return 0;
1355}
1356
1357int gpio_free_list_nodev(struct gpio_desc *desc, int count)
1358{
1359 return gpio_free_list(NULL, desc, count);
1360}
1361
Simon Glasse821d182014-02-26 15:59:24 -07001362/* We need to renumber the GPIOs when any driver is probed/removed */
Simon Glass0f4517d2014-10-04 11:29:42 -06001363static int gpio_renumber(struct udevice *removed_dev)
Simon Glasse821d182014-02-26 15:59:24 -07001364{
1365 struct gpio_dev_priv *uc_priv;
Heiko Schocherb74fcb42014-05-22 12:43:05 +02001366 struct udevice *dev;
Simon Glasse821d182014-02-26 15:59:24 -07001367 struct uclass *uc;
1368 unsigned base;
1369 int ret;
1370
1371 ret = uclass_get(UCLASS_GPIO, &uc);
1372 if (ret)
1373 return ret;
1374
1375 /* Ensure that we have a base for each bank */
1376 base = 0;
1377 uclass_foreach_dev(dev, uc) {
Simon Glass0f4517d2014-10-04 11:29:42 -06001378 if (device_active(dev) && dev != removed_dev) {
Simon Glassde0977b2015-03-05 12:25:20 -07001379 uc_priv = dev_get_uclass_priv(dev);
Simon Glasse821d182014-02-26 15:59:24 -07001380 uc_priv->gpio_base = base;
1381 base += uc_priv->gpio_count;
1382 }
1383 }
1384
1385 return 0;
1386}
1387
Simon Glassfd838972016-03-06 19:27:51 -07001388int gpio_get_number(const struct gpio_desc *desc)
Simon Glass94f54d12015-03-25 12:21:58 -06001389{
1390 struct udevice *dev = desc->dev;
1391 struct gpio_dev_priv *uc_priv;
1392
1393 if (!dev)
1394 return -1;
Simon Glass95588622020-12-22 19:30:28 -07001395 uc_priv = dev_get_uclass_priv(dev);
Simon Glass94f54d12015-03-25 12:21:58 -06001396
1397 return uc_priv->gpio_base + desc->offset;
1398}
1399
Heiko Schocherb74fcb42014-05-22 12:43:05 +02001400static int gpio_post_probe(struct udevice *dev)
Simon Glasse821d182014-02-26 15:59:24 -07001401{
Simon Glassde0977b2015-03-05 12:25:20 -07001402 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
Simon Glass0f4517d2014-10-04 11:29:42 -06001403
1404 uc_priv->name = calloc(uc_priv->gpio_count, sizeof(char *));
1405 if (!uc_priv->name)
1406 return -ENOMEM;
Marek Vasut3a188472023-08-02 01:26:02 +02001407
1408 uc_priv->claimed = calloc(DIV_ROUND_UP(uc_priv->gpio_count,
1409 GPIO_ALLOC_BITS),
1410 GPIO_ALLOC_BITS / 8);
1411 if (!uc_priv->claimed) {
1412 free(uc_priv->name);
1413 return -ENOMEM;
1414 }
Simon Glass0f4517d2014-10-04 11:29:42 -06001415
1416 return gpio_renumber(NULL);
Simon Glasse821d182014-02-26 15:59:24 -07001417}
1418
Heiko Schocherb74fcb42014-05-22 12:43:05 +02001419static int gpio_pre_remove(struct udevice *dev)
Simon Glasse821d182014-02-26 15:59:24 -07001420{
Simon Glassde0977b2015-03-05 12:25:20 -07001421 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
Simon Glass0f4517d2014-10-04 11:29:42 -06001422 int i;
1423
1424 for (i = 0; i < uc_priv->gpio_count; i++) {
1425 if (uc_priv->name[i])
1426 free(uc_priv->name[i]);
1427 }
Marek Vasut3a188472023-08-02 01:26:02 +02001428 free(uc_priv->claimed);
Simon Glass0f4517d2014-10-04 11:29:42 -06001429 free(uc_priv->name);
1430
1431 return gpio_renumber(dev);
Simon Glasse821d182014-02-26 15:59:24 -07001432}
1433
Heiko Schocher39cb3402019-06-12 06:11:46 +02001434int gpio_dev_request_index(struct udevice *dev, const char *nodename,
1435 char *list_name, int index, int flags,
1436 int dtflags, struct gpio_desc *desc)
1437{
1438 struct ofnode_phandle_args args;
1439
1440 args.node = ofnode_null();
1441 args.args_count = 2;
1442 args.args[0] = index;
1443 args.args[1] = dtflags;
1444
1445 return gpio_request_tail(0, nodename, &args, list_name, index, desc,
1446 flags, 0, dev);
1447}
1448
Jean-Jacques Hiblot775d6a22020-09-11 13:43:34 +05301449static void devm_gpiod_release(struct udevice *dev, void *res)
1450{
1451 dm_gpio_free(dev, res);
1452}
1453
1454static int devm_gpiod_match(struct udevice *dev, void *res, void *data)
1455{
1456 return res == data;
1457}
1458
1459struct gpio_desc *devm_gpiod_get_index(struct udevice *dev, const char *id,
1460 unsigned int index, int flags)
1461{
1462 int rc;
1463 struct gpio_desc *desc;
1464 char *propname;
1465 static const char suffix[] = "-gpios";
1466
1467 propname = malloc(strlen(id) + sizeof(suffix));
1468 if (!propname) {
1469 rc = -ENOMEM;
1470 goto end;
1471 }
1472
1473 strcpy(propname, id);
1474 strcat(propname, suffix);
1475
1476 desc = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc),
1477 __GFP_ZERO);
1478 if (unlikely(!desc)) {
1479 rc = -ENOMEM;
1480 goto end;
1481 }
1482
1483 rc = gpio_request_by_name(dev, propname, index, desc, flags);
1484
1485end:
1486 if (propname)
1487 free(propname);
1488
1489 if (rc)
1490 return ERR_PTR(rc);
1491
1492 devres_add(dev, desc);
1493
1494 return desc;
1495}
1496
1497struct gpio_desc *devm_gpiod_get_index_optional(struct udevice *dev,
1498 const char *id,
1499 unsigned int index,
1500 int flags)
1501{
1502 struct gpio_desc *desc = devm_gpiod_get_index(dev, id, index, flags);
1503
1504 if (IS_ERR(desc))
1505 return NULL;
1506
1507 return desc;
1508}
1509
1510void devm_gpiod_put(struct udevice *dev, struct gpio_desc *desc)
1511{
1512 int rc;
1513
1514 rc = devres_release(dev, devm_gpiod_release, devm_gpiod_match, desc);
1515 WARN_ON(rc);
1516}
1517
Michal Simek5f7202c2018-07-12 12:42:27 +02001518static int gpio_post_bind(struct udevice *dev)
1519{
Simon Glasse418c632023-06-01 10:22:30 -06001520 if (CONFIG_IS_ENABLED(GPIO_HOG) && dev_has_ofnode(dev)) {
Eddie James652b8692022-02-07 17:09:01 -06001521 struct udevice *child;
1522 ofnode node;
1523
Heiko Schocher58e4c382019-07-17 06:59:51 +02001524 dev_for_each_subnode(node, dev) {
1525 if (ofnode_read_bool(node, "gpio-hog")) {
1526 const char *name = ofnode_get_name(node);
1527 int ret;
Heiko Schocher39cb3402019-06-12 06:11:46 +02001528
Heiko Schocher58e4c382019-07-17 06:59:51 +02001529 ret = device_bind_driver_to_node(dev,
1530 "gpio_hog",
1531 name, node,
1532 &child);
1533 if (ret)
1534 return ret;
Marek Vasutba3982f2022-09-22 17:53:26 +02001535
1536 /*
1537 * Make sure gpio-hogs are probed after bind
1538 * since hogs can be essential to the hardware
1539 * system.
1540 */
1541 dev_or_flags(child, DM_FLAG_PROBE_AFTER_BIND);
Heiko Schocher58e4c382019-07-17 06:59:51 +02001542 }
Heiko Schocher39cb3402019-06-12 06:11:46 +02001543 }
1544 }
Marek Vasutba3982f2022-09-22 17:53:26 +02001545
Michal Simek5f7202c2018-07-12 12:42:27 +02001546 return 0;
1547}
1548
Simon Glasse821d182014-02-26 15:59:24 -07001549UCLASS_DRIVER(gpio) = {
1550 .id = UCLASS_GPIO,
1551 .name = "gpio",
Bhuvanchandra DVb1a1fc92015-06-01 18:37:15 +05301552 .flags = DM_UC_FLAG_SEQ_ALIAS,
Simon Glasse821d182014-02-26 15:59:24 -07001553 .post_probe = gpio_post_probe,
Michal Simek5f7202c2018-07-12 12:42:27 +02001554 .post_bind = gpio_post_bind,
Simon Glasse821d182014-02-26 15:59:24 -07001555 .pre_remove = gpio_pre_remove,
Simon Glass8a2b47f2020-12-03 16:55:17 -07001556 .per_device_auto = sizeof(struct gpio_dev_priv),
Simon Glasse821d182014-02-26 15:59:24 -07001557};