File Index
Files and directories
Sign in
FILE

gpiolib-swnode.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpio/gpiolib-swnode.c C
  1// SPDX-License-Identifier: GPL-2.0+
  2/*
  3 * Software Node helpers for the GPIO API
  4 *
  5 * Copyright 2022 Google LLC
  6 */
  7
  8#define pr_fmt(fmt) "gpiolib: swnode: " fmt
  9
 10#include <linux/err.h>
 11#include <linux/errno.h>
 12#include <linux/export.h>
 13#include <linux/init.h>
 14#include <linux/kernel.h>
 15#include <linux/printk.h>
 16#include <linux/property.h>
 17#include <linux/string.h>
 18
 19#include <linux/gpio/consumer.h>
 20#include <linux/gpio/driver.h>
 21
 22#include "gpiolib.h"
 23#include "gpiolib-swnode.h"
 24
 25#define GPIOLIB_SWNODE_UNDEFINED_NAME "swnode-gpio-undefined"
 26
 27static struct gpio_device *swnode_get_gpio_device(struct fwnode_handle *fwnode)
 28{
 29	const struct software_node *gdev_node;
 30	struct gpio_device *gdev;
 31
 32	gdev_node = to_software_node(fwnode);
 33	if (!gdev_node || !gdev_node->name)
 34		goto fwnode_lookup;
 35
 36	/*
 37	 * Check for a special node that identifies undefined GPIOs, this is
 38	 * primarily used as a key for internal chip selects in SPI bindings.
 39	 */
 40	if (IS_ENABLED(CONFIG_GPIO_SWNODE_UNDEFINED) &&
 41	    !strcmp(gdev_node->name, GPIOLIB_SWNODE_UNDEFINED_NAME))
 42		return ERR_PTR(-ENOENT);
 43
 44fwnode_lookup:
 45	gdev = gpio_device_find_by_fwnode(fwnode);
 46	if (!gdev && gdev_node && gdev_node->name)
 47		/*
 48		 * FIXME: We shouldn't need to compare the GPIO controller's
 49		 * label against the software node that is supposedly attached
 50		 * to it. However there are currently GPIO users that - knowing
 51		 * the expected label of the GPIO chip whose pins they want to
 52		 * control - set up dummy software nodes named after those GPIO
 53		 * controllers, which aren't actually attached to them. In this
 54		 * case gpio_device_find_by_fwnode() will fail as no device on
 55		 * the GPIO bus is actually associated with the fwnode we're
 56		 * looking for.
 57		 *
 58		 * As a fallback: continue checking the label if we have no
 59		 * match. However, the situation described above is an abuse
 60		 * of the software node API and should be phased out and the
 61		 * following line - eventually removed.
 62		 */
 63		gdev = gpio_device_find_by_label(gdev_node->name);
 64
 65	return gdev ?: ERR_PTR(-EPROBE_DEFER);
 66}
 67
 68static int swnode_gpio_get_reference(const struct fwnode_handle *fwnode,
 69				     const char *propname, unsigned int idx,
 70				     struct fwnode_reference_args *args)
 71{
 72	/*
 73	 * We expect all swnode-described GPIOs have GPIO number and
 74	 * polarity arguments, hence nargs is set to 2.
 75	 */
 76	return fwnode_property_get_reference_args(fwnode, propname, NULL, 2, idx, args);
 77}
 78
 79struct gpio_desc *swnode_find_gpio(struct fwnode_handle *fwnode,
 80				   const char *con_id, unsigned int idx,
 81				   unsigned long *flags)
 82{
 83	const struct software_node *swnode;
 84	struct fwnode_reference_args args;
 85	struct gpio_desc *desc;
 86	char propname[32]; /* 32 is max size of property name */
 87	int ret = 0;
 88
 89	swnode = to_software_node(fwnode);
 90	if (!swnode)
 91		return ERR_PTR(-EINVAL);
 92
 93	for_each_gpio_property_name(propname, con_id) {
 94		ret = swnode_gpio_get_reference(fwnode, propname, idx, &args);
 95		if (ret == 0)
 96			break;
 97	}
 98	if (ret) {
 99		pr_debug("%s: can't parse '%s' property of node '%pfwP[%d]'\n",
100			__func__, propname, fwnode, idx);
101		return ERR_PTR(ret);
102	}
103
104	struct gpio_device *gdev __free(gpio_device_put) =
105					swnode_get_gpio_device(args.fwnode);
106	fwnode_handle_put(args.fwnode);
107	if (IS_ERR(gdev))
108		return ERR_CAST(gdev);
109
110	/*
111	 * FIXME: The GPIO device reference is put at return but the descriptor
112	 * is passed on. Find a proper solution.
113	 */
114	desc = gpio_device_get_desc(gdev, args.args[0]);
115	*flags = args.args[1]; /* We expect native GPIO flags */
116
117	pr_debug("%s: parsed '%s' property of node '%pfwP[%d]' - status (%d)\n",
118		 __func__, propname, fwnode, idx, PTR_ERR_OR_ZERO(desc));
119
120	return desc;
121}
122
123/**
124 * swnode_gpio_count - count the GPIOs associated with a device / function
125 * @fwnode:	firmware node of the GPIO consumer, can be %NULL for
126 *		system-global GPIOs
127 * @con_id:	function within the GPIO consumer
128 *
129 * Returns:
130 * The number of GPIOs associated with a device / function or %-ENOENT,
131 * if no GPIO has been assigned to the requested function.
132 */
133int swnode_gpio_count(const struct fwnode_handle *fwnode, const char *con_id)
134{
135	struct fwnode_reference_args args;
136	char propname[32];
137	int count;
138
139	/*
140	 * This is not very efficient, but GPIO lists usually have only
141	 * 1 or 2 entries.
142	 */
143	for_each_gpio_property_name(propname, con_id) {
144		count = 0;
145		while (swnode_gpio_get_reference(fwnode, propname, count, &args) == 0) {
146			fwnode_handle_put(args.fwnode);
147			count++;
148		}
149		if (count)
150			return count;
151	}
152
153	return -ENOENT;
154}
155
156#if IS_ENABLED(CONFIG_GPIO_SWNODE_UNDEFINED)
157/*
158 * A special node that identifies undefined GPIOs, this is primarily used as
159 * a key for internal chip selects in SPI bindings.
160 */
161const struct software_node swnode_gpio_undefined = {
162	.name = GPIOLIB_SWNODE_UNDEFINED_NAME,
163};
164EXPORT_SYMBOL_NS_GPL(swnode_gpio_undefined, "GPIO_SWNODE");
165
166static int __init swnode_gpio_init(void)
167{
168	int ret;
169
170	ret = software_node_register(&swnode_gpio_undefined);
171	if (ret < 0)
172		pr_err("failed to register swnode: %d\n", ret);
173
174	return ret;
175}
176subsys_initcall(swnode_gpio_init);
177
178static void __exit swnode_gpio_cleanup(void)
179{
180	software_node_unregister(&swnode_gpio_undefined);
181}
182__exitcall(swnode_gpio_cleanup);
183#endif
~/ Read-only file preview.