164 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * Software Node helpers for the GPIO API4 *5 * Copyright 2022 Google LLC6 */7 8#define pr_fmt(fmt) "gpiolib: swnode: " fmt9 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 return ERR_PTR(-EINVAL);35 36 /*37 * Check for a special node that identifies undefined GPIOs, this is38 * 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 44 gdev = gpio_device_find_by_label(gdev_node->name);45 return gdev ?: ERR_PTR(-EPROBE_DEFER);46}47 48static int swnode_gpio_get_reference(const struct fwnode_handle *fwnode,49 const char *propname, unsigned int idx,50 struct fwnode_reference_args *args)51{52 /*53 * We expect all swnode-described GPIOs have GPIO number and54 * polarity arguments, hence nargs is set to 2.55 */56 return fwnode_property_get_reference_args(fwnode, propname, NULL, 2, idx, args);57}58 59struct gpio_desc *swnode_find_gpio(struct fwnode_handle *fwnode,60 const char *con_id, unsigned int idx,61 unsigned long *flags)62{63 const struct software_node *swnode;64 struct fwnode_reference_args args;65 struct gpio_desc *desc;66 char propname[32]; /* 32 is max size of property name */67 int ret = 0;68 69 swnode = to_software_node(fwnode);70 if (!swnode)71 return ERR_PTR(-EINVAL);72 73 for_each_gpio_property_name(propname, con_id) {74 ret = swnode_gpio_get_reference(fwnode, propname, idx, &args);75 if (ret == 0)76 break;77 }78 if (ret) {79 pr_debug("%s: can't parse '%s' property of node '%pfwP[%d]'\n",80 __func__, propname, fwnode, idx);81 return ERR_PTR(ret);82 }83 84 struct gpio_device *gdev __free(gpio_device_put) =85 swnode_get_gpio_device(args.fwnode);86 fwnode_handle_put(args.fwnode);87 if (IS_ERR(gdev))88 return ERR_CAST(gdev);89 90 /*91 * FIXME: The GPIO device reference is put at return but the descriptor92 * is passed on. Find a proper solution.93 */94 desc = gpio_device_get_desc(gdev, args.args[0]);95 *flags = args.args[1]; /* We expect native GPIO flags */96 97 pr_debug("%s: parsed '%s' property of node '%pfwP[%d]' - status (%d)\n",98 __func__, propname, fwnode, idx, PTR_ERR_OR_ZERO(desc));99 100 return desc;101}102 103/**104 * swnode_gpio_count - count the GPIOs associated with a device / function105 * @fwnode: firmware node of the GPIO consumer, can be %NULL for106 * system-global GPIOs107 * @con_id: function within the GPIO consumer108 *109 * Returns:110 * The number of GPIOs associated with a device / function or %-ENOENT,111 * if no GPIO has been assigned to the requested function.112 */113int swnode_gpio_count(const struct fwnode_handle *fwnode, const char *con_id)114{115 struct fwnode_reference_args args;116 char propname[32];117 int count;118 119 /*120 * This is not very efficient, but GPIO lists usually have only121 * 1 or 2 entries.122 */123 for_each_gpio_property_name(propname, con_id) {124 count = 0;125 while (swnode_gpio_get_reference(fwnode, propname, count, &args) == 0) {126 fwnode_handle_put(args.fwnode);127 count++;128 }129 if (count)130 return count;131 }132 133 return -ENOENT;134}135 136#if IS_ENABLED(CONFIG_GPIO_SWNODE_UNDEFINED)137/*138 * A special node that identifies undefined GPIOs, this is primarily used as139 * a key for internal chip selects in SPI bindings.140 */141const struct software_node swnode_gpio_undefined = {142 .name = GPIOLIB_SWNODE_UNDEFINED_NAME,143};144EXPORT_SYMBOL_NS_GPL(swnode_gpio_undefined, GPIO_SWNODE);145 146static int __init swnode_gpio_init(void)147{148 int ret;149 150 ret = software_node_register(&swnode_gpio_undefined);151 if (ret < 0)152 pr_err("failed to register swnode: %d\n", ret);153 154 return ret;155}156subsys_initcall(swnode_gpio_init);157 158static void __exit swnode_gpio_cleanup(void)159{160 software_node_unregister(&swnode_gpio_undefined);161}162__exitcall(swnode_gpio_cleanup);163#endif164