1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Software Node helpers for the GPIO API 4 * 5 * Copyright 2022 Google LLC 6 */ 7 #include <linux/err.h> 8 #include <linux/errno.h> 9 #include <linux/gpio/consumer.h> 10 #include <linux/gpio/driver.h> 11 #include <linux/kernel.h> 12 #include <linux/printk.h> 13 #include <linux/property.h> 14 #include <linux/string.h> 15 16 #include "gpiolib.h" 17 #include "gpiolib-swnode.h" 18 19 static void swnode_format_propname(const char *con_id, char *propname, 20 size_t max_size) 21 { 22 /* 23 * Note we do not need to try both -gpios and -gpio suffixes, 24 * as, unlike OF and ACPI, we can fix software nodes to conform 25 * to the proper binding. 26 */ 27 if (con_id) 28 snprintf(propname, max_size, "%s-gpios", con_id); 29 else 30 strscpy(propname, "gpios", max_size); 31 } 32 33 static int swnode_gpiochip_match_name(struct gpio_chip *chip, void *data) 34 { 35 return !strcmp(chip->label, data); 36 } 37 38 static struct gpio_chip *swnode_get_chip(struct fwnode_handle *fwnode) 39 { 40 const struct software_node *chip_node; 41 struct gpio_chip *chip; 42 43 chip_node = to_software_node(fwnode); 44 if (!chip_node || !chip_node->name) 45 return ERR_PTR(-EINVAL); 46 47 chip = gpiochip_find((void *)chip_node->name, swnode_gpiochip_match_name); 48 return chip ?: ERR_PTR(-EPROBE_DEFER); 49 } 50 51 struct gpio_desc *swnode_find_gpio(struct fwnode_handle *fwnode, 52 const char *con_id, unsigned int idx, 53 unsigned long *flags) 54 { 55 const struct software_node *swnode; 56 struct fwnode_reference_args args; 57 struct gpio_chip *chip; 58 struct gpio_desc *desc; 59 char propname[32]; /* 32 is max size of property name */ 60 int error; 61 62 swnode = to_software_node(fwnode); 63 if (!swnode) 64 return ERR_PTR(-EINVAL); 65 66 swnode_format_propname(con_id, propname, sizeof(propname)); 67 68 /* 69 * We expect all swnode-described GPIOs have GPIO number and 70 * polarity arguments, hence nargs is set to 2. 71 */ 72 error = fwnode_property_get_reference_args(fwnode, propname, NULL, 2, idx, &args); 73 if (error) { 74 pr_debug("%s: can't parse '%s' property of node '%pfwP[%d]'\n", 75 __func__, propname, fwnode, idx); 76 return ERR_PTR(error); 77 } 78 79 chip = swnode_get_chip(args.fwnode); 80 fwnode_handle_put(args.fwnode); 81 if (IS_ERR(chip)) 82 return ERR_CAST(chip); 83 84 desc = gpiochip_get_desc(chip, args.args[0]); 85 *flags = args.args[1]; /* We expect native GPIO flags */ 86 87 pr_debug("%s: parsed '%s' property of node '%pfwP[%d]' - status (%d)\n", 88 __func__, propname, fwnode, idx, PTR_ERR_OR_ZERO(desc)); 89 90 return desc; 91 } 92 93 /** 94 * swnode_gpio_count - count the GPIOs associated with a device / function 95 * @fwnode: firmware node of the GPIO consumer, can be %NULL for 96 * system-global GPIOs 97 * @con_id: function within the GPIO consumer 98 * 99 * Return: 100 * The number of GPIOs associated with a device / function or %-ENOENT, 101 * if no GPIO has been assigned to the requested function. 102 */ 103 int swnode_gpio_count(const struct fwnode_handle *fwnode, const char *con_id) 104 { 105 struct fwnode_reference_args args; 106 char propname[32]; 107 int count; 108 109 swnode_format_propname(con_id, propname, sizeof(propname)); 110 111 /* 112 * This is not very efficient, but GPIO lists usually have only 113 * 1 or 2 entries. 114 */ 115 count = 0; 116 while (fwnode_property_get_reference_args(fwnode, propname, NULL, 0, 117 count, &args) == 0) { 118 fwnode_handle_put(args.fwnode); 119 count++; 120 } 121 122 return count ?: -ENOENT; 123 } 124