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