127038c3eSVladimir Zapolskiy // SPDX-License-Identifier: GPL-2.0+ 2f141ed65SGrant Likely /* 3f141ed65SGrant Likely * OF helpers for the GPIO API 4f141ed65SGrant Likely * 5f141ed65SGrant Likely * Copyright (c) 2007-2008 MontaVista Software, Inc. 6f141ed65SGrant Likely * 7f141ed65SGrant Likely * Author: Anton Vorontsov <avorontsov@ru.mvista.com> 8f141ed65SGrant Likely */ 9f141ed65SGrant Likely 10f141ed65SGrant Likely #include <linux/device.h> 11bea4dbeeSSachin Kamat #include <linux/err.h> 12f141ed65SGrant Likely #include <linux/errno.h> 13f141ed65SGrant Likely #include <linux/io.h> 14380c7ba3SAndy Shevchenko #include <linux/module.h> 15f141ed65SGrant Likely #include <linux/of.h> 16f141ed65SGrant Likely #include <linux/of_address.h> 17f141ed65SGrant Likely #include <linux/of_gpio.h> 18f23f1516SShiraz Hashim #include <linux/pinctrl/pinctrl.h> 19f141ed65SGrant Likely #include <linux/slab.h> 20380c7ba3SAndy Shevchenko #include <linux/string.h> 21380c7ba3SAndy Shevchenko 22380c7ba3SAndy Shevchenko #include <linux/gpio/consumer.h> 23f625d460SBenoit Parrot #include <linux/gpio/machine.h> 24f141ed65SGrant Likely 251bd6b601SAlexandre Courbot #include "gpiolib.h" 26f626d6dfSLinus Walleij #include "gpiolib-of.h" 27f626d6dfSLinus Walleij 28eed5a3bfSAndy Shevchenko /* 29eed5a3bfSAndy Shevchenko * This is Linux-specific flags. By default controllers' and Linux' mapping 30eed5a3bfSAndy Shevchenko * match, but GPIO controllers are free to translate their own flags to 31eed5a3bfSAndy Shevchenko * Linux-specific in their .xlate callback. Though, 1:1 mapping is recommended. 32eed5a3bfSAndy Shevchenko */ 33eed5a3bfSAndy Shevchenko enum of_gpio_flags { 34eed5a3bfSAndy Shevchenko OF_GPIO_ACTIVE_LOW = 0x1, 35eed5a3bfSAndy Shevchenko OF_GPIO_SINGLE_ENDED = 0x2, 36eed5a3bfSAndy Shevchenko OF_GPIO_OPEN_DRAIN = 0x4, 37eed5a3bfSAndy Shevchenko OF_GPIO_TRANSITORY = 0x8, 38eed5a3bfSAndy Shevchenko OF_GPIO_PULL_UP = 0x10, 39eed5a3bfSAndy Shevchenko OF_GPIO_PULL_DOWN = 0x20, 40eed5a3bfSAndy Shevchenko OF_GPIO_PULL_DISABLE = 0x40, 41eed5a3bfSAndy Shevchenko }; 42eed5a3bfSAndy Shevchenko 4371b8f600SLinus Walleij /** 44c7835652SDmitry Torokhov * of_gpio_named_count() - Count GPIOs for a device 45c7835652SDmitry Torokhov * @np: device node to count GPIOs for 46c7835652SDmitry Torokhov * @propname: property name containing gpio specifier(s) 47c7835652SDmitry Torokhov * 48c7835652SDmitry Torokhov * The function returns the count of GPIOs specified for a node. 49c7835652SDmitry Torokhov * Note that the empty GPIO specifiers count too. Returns either 50c7835652SDmitry Torokhov * Number of gpios defined in property, 51c7835652SDmitry Torokhov * -EINVAL for an incorrectly formed gpios property, or 52c7835652SDmitry Torokhov * -ENOENT for a missing gpios property 53c7835652SDmitry Torokhov * 54c7835652SDmitry Torokhov * Example: 55c7835652SDmitry Torokhov * gpios = <0 56c7835652SDmitry Torokhov * &gpio1 1 2 57c7835652SDmitry Torokhov * 0 58c7835652SDmitry Torokhov * &gpio2 3 4>; 59c7835652SDmitry Torokhov * 60c7835652SDmitry Torokhov * The above example defines four GPIOs, two of which are not specified. 61c7835652SDmitry Torokhov * This function will return '4' 62c7835652SDmitry Torokhov */ 63c7835652SDmitry Torokhov static int of_gpio_named_count(const struct device_node *np, 64c7835652SDmitry Torokhov const char *propname) 65c7835652SDmitry Torokhov { 66c7835652SDmitry Torokhov return of_count_phandle_with_args(np, propname, "#gpio-cells"); 67c7835652SDmitry Torokhov } 68c7835652SDmitry Torokhov 69c7835652SDmitry Torokhov /** 7071b8f600SLinus Walleij * of_gpio_spi_cs_get_count() - special GPIO counting for SPI 71c5a66b97SLee Jones * @dev: Consuming device 72c5a66b97SLee Jones * @con_id: Function within the GPIO consumer 73c5a66b97SLee Jones * 7471b8f600SLinus Walleij * Some elder GPIO controllers need special quirks. Currently we handle 7547267732SLinus Walleij * the Freescale and PPC GPIO controller with bindings that doesn't use the 7671b8f600SLinus Walleij * established "cs-gpios" for chip selects but instead rely on 7771b8f600SLinus Walleij * "gpios" for the chip select lines. If we detect this, we redirect 7871b8f600SLinus Walleij * the counting of "cs-gpios" to count "gpios" transparent to the 7971b8f600SLinus Walleij * driver. 8071b8f600SLinus Walleij */ 81a1f4c96bSYueHaibing static int of_gpio_spi_cs_get_count(struct device *dev, const char *con_id) 8271b8f600SLinus Walleij { 8371b8f600SLinus Walleij struct device_node *np = dev->of_node; 8471b8f600SLinus Walleij 8571b8f600SLinus Walleij if (!IS_ENABLED(CONFIG_SPI_MASTER)) 8671b8f600SLinus Walleij return 0; 8771b8f600SLinus Walleij if (!con_id || strcmp(con_id, "cs")) 8871b8f600SLinus Walleij return 0; 8971b8f600SLinus Walleij if (!of_device_is_compatible(np, "fsl,spi") && 9047267732SLinus Walleij !of_device_is_compatible(np, "aeroflexgaisler,spictrl") && 9147267732SLinus Walleij !of_device_is_compatible(np, "ibm,ppc4xx-spi")) 9271b8f600SLinus Walleij return 0; 9371b8f600SLinus Walleij return of_gpio_named_count(np, "gpios"); 9471b8f600SLinus Walleij } 9571b8f600SLinus Walleij 96f626d6dfSLinus Walleij int of_gpio_get_count(struct device *dev, const char *con_id) 97f626d6dfSLinus Walleij { 98f626d6dfSLinus Walleij int ret; 99f626d6dfSLinus Walleij char propname[32]; 100f626d6dfSLinus Walleij unsigned int i; 101f626d6dfSLinus Walleij 10271b8f600SLinus Walleij ret = of_gpio_spi_cs_get_count(dev, con_id); 10371b8f600SLinus Walleij if (ret > 0) 10471b8f600SLinus Walleij return ret; 10571b8f600SLinus Walleij 106f626d6dfSLinus Walleij for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) { 107f626d6dfSLinus Walleij if (con_id) 108f626d6dfSLinus Walleij snprintf(propname, sizeof(propname), "%s-%s", 109f626d6dfSLinus Walleij con_id, gpio_suffixes[i]); 110f626d6dfSLinus Walleij else 111f626d6dfSLinus Walleij snprintf(propname, sizeof(propname), "%s", 112f626d6dfSLinus Walleij gpio_suffixes[i]); 113f626d6dfSLinus Walleij 114f626d6dfSLinus Walleij ret = of_gpio_named_count(dev->of_node, propname); 115f626d6dfSLinus Walleij if (ret > 0) 116f626d6dfSLinus Walleij break; 117f626d6dfSLinus Walleij } 118f626d6dfSLinus Walleij return ret ? ret : -ENOENT; 119f626d6dfSLinus Walleij } 120af8b6375SAlexandre Courbot 121c7e9d398SMasahiro Yamada static int of_gpiochip_match_node_and_xlate(struct gpio_chip *chip, void *data) 1223d0f7cf0SGrant Likely { 123c7e9d398SMasahiro Yamada struct of_phandle_args *gpiospec = data; 124c7e9d398SMasahiro Yamada 125d59fdbc7SAndy Shevchenko return device_match_of_node(&chip->gpiodev->dev, gpiospec->np) && 126d49b48f0SVincent Whitchurch chip->of_xlate && 127c7e9d398SMasahiro Yamada chip->of_xlate(chip, gpiospec, NULL) >= 0; 1287b8792bbSHans Holmberg } 1293d0f7cf0SGrant Likely 130c7e9d398SMasahiro Yamada static struct gpio_chip *of_find_gpiochip_by_xlate( 131c7e9d398SMasahiro Yamada struct of_phandle_args *gpiospec) 132762c2e46SMasahiro Yamada { 133c7e9d398SMasahiro Yamada return gpiochip_find(gpiospec, of_gpiochip_match_node_and_xlate); 1343d0f7cf0SGrant Likely } 1353d0f7cf0SGrant Likely 13699468c1aSMasahiro Yamada static struct gpio_desc *of_xlate_and_get_gpiod_flags(struct gpio_chip *chip, 13799468c1aSMasahiro Yamada struct of_phandle_args *gpiospec, 13899468c1aSMasahiro Yamada enum of_gpio_flags *flags) 13999468c1aSMasahiro Yamada { 14099468c1aSMasahiro Yamada int ret; 14199468c1aSMasahiro Yamada 14299468c1aSMasahiro Yamada if (chip->of_gpio_n_cells != gpiospec->args_count) 14399468c1aSMasahiro Yamada return ERR_PTR(-EINVAL); 14499468c1aSMasahiro Yamada 14599468c1aSMasahiro Yamada ret = chip->of_xlate(chip, gpiospec, flags); 14699468c1aSMasahiro Yamada if (ret < 0) 14799468c1aSMasahiro Yamada return ERR_PTR(ret); 14899468c1aSMasahiro Yamada 14999468c1aSMasahiro Yamada return gpiochip_get_desc(chip, ret); 150f141ed65SGrant Likely } 151f141ed65SGrant Likely 152e3186e36SDmitry Torokhov /* 153e3186e36SDmitry Torokhov * Overrides stated polarity of a gpio line and warns when there is a 154e3186e36SDmitry Torokhov * discrepancy. 155e3186e36SDmitry Torokhov */ 156e3186e36SDmitry Torokhov static void of_gpio_quirk_polarity(const struct device_node *np, 157e3186e36SDmitry Torokhov bool active_high, 158e3186e36SDmitry Torokhov enum of_gpio_flags *flags) 159e3186e36SDmitry Torokhov { 160e3186e36SDmitry Torokhov if (active_high) { 161e3186e36SDmitry Torokhov if (*flags & OF_GPIO_ACTIVE_LOW) { 162e3186e36SDmitry Torokhov pr_warn("%s GPIO handle specifies active low - ignored\n", 163e3186e36SDmitry Torokhov of_node_full_name(np)); 164e3186e36SDmitry Torokhov *flags &= ~OF_GPIO_ACTIVE_LOW; 165e3186e36SDmitry Torokhov } 166e3186e36SDmitry Torokhov } else { 167e3186e36SDmitry Torokhov if (!(*flags & OF_GPIO_ACTIVE_LOW)) 168e3186e36SDmitry Torokhov pr_info("%s enforce active low on GPIO handle\n", 169e3186e36SDmitry Torokhov of_node_full_name(np)); 170e3186e36SDmitry Torokhov *flags |= OF_GPIO_ACTIVE_LOW; 171e3186e36SDmitry Torokhov } 172e3186e36SDmitry Torokhov } 173e3186e36SDmitry Torokhov 17499d18d42SDmitry Torokhov /* 17599d18d42SDmitry Torokhov * This quirk does static polarity overrides in cases where existing 17699d18d42SDmitry Torokhov * DTS specified incorrect polarity. 17799d18d42SDmitry Torokhov */ 17899d18d42SDmitry Torokhov static void of_gpio_try_fixup_polarity(const struct device_node *np, 17999d18d42SDmitry Torokhov const char *propname, 18099d18d42SDmitry Torokhov enum of_gpio_flags *flags) 18199d18d42SDmitry Torokhov { 18299d18d42SDmitry Torokhov static const struct { 18399d18d42SDmitry Torokhov const char *compatible; 18499d18d42SDmitry Torokhov const char *propname; 18599d18d42SDmitry Torokhov bool active_high; 18699d18d42SDmitry Torokhov } gpios[] = { 18799d18d42SDmitry Torokhov #if !IS_ENABLED(CONFIG_LCD_HX8357) 18899d18d42SDmitry Torokhov /* 18999d18d42SDmitry Torokhov * Himax LCD controllers used incorrectly named 19099d18d42SDmitry Torokhov * "gpios-reset" property and also specified wrong 19199d18d42SDmitry Torokhov * polarity. 19299d18d42SDmitry Torokhov */ 19399d18d42SDmitry Torokhov { "himax,hx8357", "gpios-reset", false }, 19499d18d42SDmitry Torokhov { "himax,hx8369", "gpios-reset", false }, 19599d18d42SDmitry Torokhov #endif 19699d18d42SDmitry Torokhov }; 19799d18d42SDmitry Torokhov unsigned int i; 19899d18d42SDmitry Torokhov 19999d18d42SDmitry Torokhov for (i = 0; i < ARRAY_SIZE(gpios); i++) { 20099d18d42SDmitry Torokhov if (of_device_is_compatible(np, gpios[i].compatible) && 20199d18d42SDmitry Torokhov !strcmp(propname, gpios[i].propname)) { 20299d18d42SDmitry Torokhov of_gpio_quirk_polarity(np, gpios[i].active_high, flags); 20399d18d42SDmitry Torokhov break; 20499d18d42SDmitry Torokhov } 20599d18d42SDmitry Torokhov } 20699d18d42SDmitry Torokhov } 20799d18d42SDmitry Torokhov 20834cb9352SDmitry Torokhov static void of_gpio_set_polarity_by_property(const struct device_node *np, 20989a5e15bSLinus Walleij const char *propname, 21034cb9352SDmitry Torokhov enum of_gpio_flags *flags) 211a603a2b8SLinus Walleij { 212*98ac9e4fSBalamanikandan Gunasundar const struct device_node *np_compat = np; 213*98ac9e4fSBalamanikandan Gunasundar const struct device_node *np_propname = np; 21434cb9352SDmitry Torokhov static const struct { 21534cb9352SDmitry Torokhov const char *compatible; 21634cb9352SDmitry Torokhov const char *gpio_propname; 21734cb9352SDmitry Torokhov const char *polarity_propname; 21834cb9352SDmitry Torokhov } gpios[] = { 21934cb9352SDmitry Torokhov #if IS_ENABLED(CONFIG_FEC) 22034cb9352SDmitry Torokhov /* Freescale Fast Ethernet Controller */ 22134cb9352SDmitry Torokhov { "fsl,imx25-fec", "phy-reset-gpios", "phy-reset-active-high" }, 22234cb9352SDmitry Torokhov { "fsl,imx27-fec", "phy-reset-gpios", "phy-reset-active-high" }, 22334cb9352SDmitry Torokhov { "fsl,imx28-fec", "phy-reset-gpios", "phy-reset-active-high" }, 22434cb9352SDmitry Torokhov { "fsl,imx6q-fec", "phy-reset-gpios", "phy-reset-active-high" }, 22534cb9352SDmitry Torokhov { "fsl,mvf600-fec", "phy-reset-gpios", "phy-reset-active-high" }, 22634cb9352SDmitry Torokhov { "fsl,imx6sx-fec", "phy-reset-gpios", "phy-reset-active-high" }, 22734cb9352SDmitry Torokhov { "fsl,imx6ul-fec", "phy-reset-gpios", "phy-reset-active-high" }, 22834cb9352SDmitry Torokhov { "fsl,imx8mq-fec", "phy-reset-gpios", "phy-reset-active-high" }, 22934cb9352SDmitry Torokhov { "fsl,imx8qm-fec", "phy-reset-gpios", "phy-reset-active-high" }, 23034cb9352SDmitry Torokhov { "fsl,s32v234-fec", "phy-reset-gpios", "phy-reset-active-high" }, 23134cb9352SDmitry Torokhov #endif 232b8b80348SDmitry Torokhov #if IS_ENABLED(CONFIG_PCI_IMX6) 233b8b80348SDmitry Torokhov { "fsl,imx6q-pcie", "reset-gpio", "reset-gpio-active-high" }, 234b8b80348SDmitry Torokhov { "fsl,imx6sx-pcie", "reset-gpio", "reset-gpio-active-high" }, 235b8b80348SDmitry Torokhov { "fsl,imx6qp-pcie", "reset-gpio", "reset-gpio-active-high" }, 236b8b80348SDmitry Torokhov { "fsl,imx7d-pcie", "reset-gpio", "reset-gpio-active-high" }, 237b8b80348SDmitry Torokhov { "fsl,imx8mq-pcie", "reset-gpio", "reset-gpio-active-high" }, 238b8b80348SDmitry Torokhov { "fsl,imx8mm-pcie", "reset-gpio", "reset-gpio-active-high" }, 239b8b80348SDmitry Torokhov { "fsl,imx8mp-pcie", "reset-gpio", "reset-gpio-active-high" }, 240b8b80348SDmitry Torokhov #endif 24199d18d42SDmitry Torokhov 242a603a2b8SLinus Walleij /* 243a603a2b8SLinus Walleij * The regulator GPIO handles are specified such that the 244a603a2b8SLinus Walleij * presence or absence of "enable-active-high" solely controls 245a603a2b8SLinus Walleij * the polarity of the GPIO line. Any phandle flags must 246a603a2b8SLinus Walleij * be actively ignored. 247a603a2b8SLinus Walleij */ 24834cb9352SDmitry Torokhov #if IS_ENABLED(CONFIG_REGULATOR_FIXED_VOLTAGE) 24934cb9352SDmitry Torokhov { "regulator-fixed", "gpios", "enable-active-high" }, 25034cb9352SDmitry Torokhov { "regulator-fixed", "gpio", "enable-active-high" }, 25134cb9352SDmitry Torokhov { "reg-fixed-voltage", "gpios", "enable-active-high" }, 25234cb9352SDmitry Torokhov { "reg-fixed-voltage", "gpio", "enable-active-high" }, 25334cb9352SDmitry Torokhov #endif 25434cb9352SDmitry Torokhov #if IS_ENABLED(CONFIG_REGULATOR_GPIO) 25534cb9352SDmitry Torokhov { "regulator-gpio", "enable-gpio", "enable-active-high" }, 25634cb9352SDmitry Torokhov { "regulator-gpio", "enable-gpios", "enable-active-high" }, 25734cb9352SDmitry Torokhov #endif 258*98ac9e4fSBalamanikandan Gunasundar #if IS_ENABLED(CONFIG_MMC_ATMELMCI) 259*98ac9e4fSBalamanikandan Gunasundar { "atmel,hsmci", "cd-gpios", "cd-inverted" }, 260*98ac9e4fSBalamanikandan Gunasundar #endif 26134cb9352SDmitry Torokhov }; 26234cb9352SDmitry Torokhov unsigned int i; 26334cb9352SDmitry Torokhov bool active_high; 26434cb9352SDmitry Torokhov 265*98ac9e4fSBalamanikandan Gunasundar #if IS_ENABLED(CONFIG_MMC_ATMELMCI) 266*98ac9e4fSBalamanikandan Gunasundar /* 267*98ac9e4fSBalamanikandan Gunasundar * The Atmel HSMCI has compatible property in the parent node and 268*98ac9e4fSBalamanikandan Gunasundar * gpio property in a child node 269*98ac9e4fSBalamanikandan Gunasundar */ 270*98ac9e4fSBalamanikandan Gunasundar if (of_device_is_compatible(np->parent, "atmel,hsmci")) { 271*98ac9e4fSBalamanikandan Gunasundar np_compat = np->parent; 272*98ac9e4fSBalamanikandan Gunasundar np_propname = np; 273*98ac9e4fSBalamanikandan Gunasundar } 274*98ac9e4fSBalamanikandan Gunasundar #endif 275*98ac9e4fSBalamanikandan Gunasundar 27634cb9352SDmitry Torokhov for (i = 0; i < ARRAY_SIZE(gpios); i++) { 277*98ac9e4fSBalamanikandan Gunasundar if (of_device_is_compatible(np_compat, gpios[i].compatible) && 27834cb9352SDmitry Torokhov !strcmp(propname, gpios[i].gpio_propname)) { 279*98ac9e4fSBalamanikandan Gunasundar active_high = of_property_read_bool(np_propname, 28034cb9352SDmitry Torokhov gpios[i].polarity_propname); 281e3186e36SDmitry Torokhov of_gpio_quirk_polarity(np, active_high, flags); 28234cb9352SDmitry Torokhov break; 283a603a2b8SLinus Walleij } 28434cb9352SDmitry Torokhov } 28534cb9352SDmitry Torokhov } 28634cb9352SDmitry Torokhov 28734cb9352SDmitry Torokhov static void of_gpio_flags_quirks(const struct device_node *np, 28834cb9352SDmitry Torokhov const char *propname, 28934cb9352SDmitry Torokhov enum of_gpio_flags *flags, 29034cb9352SDmitry Torokhov int index) 29134cb9352SDmitry Torokhov { 29234cb9352SDmitry Torokhov of_gpio_try_fixup_polarity(np, propname, flags); 29334cb9352SDmitry Torokhov of_gpio_set_polarity_by_property(np, propname, flags); 29434cb9352SDmitry Torokhov 295a603a2b8SLinus Walleij /* 296a603a2b8SLinus Walleij * Legacy open drain handling for fixed voltage regulators. 297a603a2b8SLinus Walleij */ 298a603a2b8SLinus Walleij if (IS_ENABLED(CONFIG_REGULATOR) && 299a603a2b8SLinus Walleij of_device_is_compatible(np, "reg-fixed-voltage") && 300a603a2b8SLinus Walleij of_property_read_bool(np, "gpio-open-drain")) { 301a603a2b8SLinus Walleij *flags |= (OF_GPIO_SINGLE_ENDED | OF_GPIO_OPEN_DRAIN); 302a603a2b8SLinus Walleij pr_info("%s uses legacy open drain flag - update the DTS if you can\n", 303a603a2b8SLinus Walleij of_node_full_name(np)); 304a603a2b8SLinus Walleij } 3056953c57aSLinus Walleij 3066953c57aSLinus Walleij /* 3076953c57aSLinus Walleij * Legacy handling of SPI active high chip select. If we have a 3086953c57aSLinus Walleij * property named "cs-gpios" we need to inspect the child node 3096953c57aSLinus Walleij * to determine if the flags should have inverted semantics. 3106953c57aSLinus Walleij */ 311da7f1349SLinus Walleij if (IS_ENABLED(CONFIG_SPI_MASTER) && !strcmp(propname, "cs-gpios") && 312a71a81e7SGeert Uytterhoeven of_property_read_bool(np, "cs-gpios")) { 3136953c57aSLinus Walleij struct device_node *child; 3146953c57aSLinus Walleij u32 cs; 3156953c57aSLinus Walleij int ret; 3166953c57aSLinus Walleij 3176953c57aSLinus Walleij for_each_child_of_node(np, child) { 3186953c57aSLinus Walleij ret = of_property_read_u32(child, "reg", &cs); 319c1c04ceaSLinus Walleij if (ret) 3206953c57aSLinus Walleij continue; 3216953c57aSLinus Walleij if (cs == index) { 3226953c57aSLinus Walleij /* 3236953c57aSLinus Walleij * SPI children have active low chip selects 3246953c57aSLinus Walleij * by default. This can be specified negatively 3256953c57aSLinus Walleij * by just omitting "spi-cs-high" in the 3266953c57aSLinus Walleij * device node, or actively by tagging on 3276953c57aSLinus Walleij * GPIO_ACTIVE_LOW as flag in the device 3286953c57aSLinus Walleij * tree. If the line is simultaneously 3296953c57aSLinus Walleij * tagged as active low in the device tree 3306953c57aSLinus Walleij * and has the "spi-cs-high" set, we get a 3316953c57aSLinus Walleij * conflict and the "spi-cs-high" flag will 3326953c57aSLinus Walleij * take precedence. 3336953c57aSLinus Walleij */ 334e3186e36SDmitry Torokhov bool active_high = of_property_read_bool(child, 335e3186e36SDmitry Torokhov "spi-cs-high"); 336e3186e36SDmitry Torokhov of_gpio_quirk_polarity(child, active_high, 337e3186e36SDmitry Torokhov flags); 33889fea04cSNishka Dasgupta of_node_put(child); 3396953c57aSLinus Walleij break; 3406953c57aSLinus Walleij } 3416953c57aSLinus Walleij } 3426953c57aSLinus Walleij } 343edc1ef3fSMartin Blumenstingl 344edc1ef3fSMartin Blumenstingl /* Legacy handling of stmmac's active-low PHY reset line */ 345edc1ef3fSMartin Blumenstingl if (IS_ENABLED(CONFIG_STMMAC_ETH) && 346edc1ef3fSMartin Blumenstingl !strcmp(propname, "snps,reset-gpio") && 347edc1ef3fSMartin Blumenstingl of_property_read_bool(np, "snps,reset-active-low")) 348edc1ef3fSMartin Blumenstingl *flags |= OF_GPIO_ACTIVE_LOW; 349a603a2b8SLinus Walleij } 350a603a2b8SLinus Walleij 351f141ed65SGrant Likely /** 352af8b6375SAlexandre Courbot * of_get_named_gpiod_flags() - Get a GPIO descriptor and flags for GPIO API 353f141ed65SGrant Likely * @np: device node to get GPIO from 354f141ed65SGrant Likely * @propname: property name containing gpio specifier(s) 355f141ed65SGrant Likely * @index: index of the GPIO 356f141ed65SGrant Likely * @flags: a flags pointer to fill in 357f141ed65SGrant Likely * 358af8b6375SAlexandre Courbot * Returns GPIO descriptor to use with Linux GPIO API, or one of the errno 359f141ed65SGrant Likely * value on the error condition. If @flags is not NULL the function also fills 360f141ed65SGrant Likely * in flags for the GPIO. 361f141ed65SGrant Likely */ 362e6ae9a83SKrzysztof Kozlowski static struct gpio_desc *of_get_named_gpiod_flags(const struct device_node *np, 363af8b6375SAlexandre Courbot const char *propname, int index, enum of_gpio_flags *flags) 364f141ed65SGrant Likely { 365762c2e46SMasahiro Yamada struct of_phandle_args gpiospec; 366762c2e46SMasahiro Yamada struct gpio_chip *chip; 367762c2e46SMasahiro Yamada struct gpio_desc *desc; 368f141ed65SGrant Likely int ret; 369f141ed65SGrant Likely 370c11e6f0fSStephen Boyd ret = of_parse_phandle_with_args_map(np, propname, "gpio", index, 371762c2e46SMasahiro Yamada &gpiospec); 3723d0f7cf0SGrant Likely if (ret) { 3737eb6ce2fSRob Herring pr_debug("%s: can't parse '%s' property of node '%pOF[%d]'\n", 3747eb6ce2fSRob Herring __func__, propname, np, index); 375af8b6375SAlexandre Courbot return ERR_PTR(ret); 3763d0f7cf0SGrant Likely } 377f141ed65SGrant Likely 378c7e9d398SMasahiro Yamada chip = of_find_gpiochip_by_xlate(&gpiospec); 379762c2e46SMasahiro Yamada if (!chip) { 380762c2e46SMasahiro Yamada desc = ERR_PTR(-EPROBE_DEFER); 381762c2e46SMasahiro Yamada goto out; 382762c2e46SMasahiro Yamada } 3833d0f7cf0SGrant Likely 38499468c1aSMasahiro Yamada desc = of_xlate_and_get_gpiod_flags(chip, &gpiospec, flags); 385762c2e46SMasahiro Yamada if (IS_ERR(desc)) 386762c2e46SMasahiro Yamada goto out; 387762c2e46SMasahiro Yamada 388605f2d34SLinus Walleij if (flags) 38989a5e15bSLinus Walleij of_gpio_flags_quirks(np, propname, flags, index); 390a603a2b8SLinus Walleij 3917eb6ce2fSRob Herring pr_debug("%s: parsed '%s' property of node '%pOF[%d]' - status (%d)\n", 3927eb6ce2fSRob Herring __func__, propname, np, index, 393762c2e46SMasahiro Yamada PTR_ERR_OR_ZERO(desc)); 394762c2e46SMasahiro Yamada 395762c2e46SMasahiro Yamada out: 396762c2e46SMasahiro Yamada of_node_put(gpiospec.np); 397762c2e46SMasahiro Yamada 398762c2e46SMasahiro Yamada return desc; 399f141ed65SGrant Likely } 400f141ed65SGrant Likely 40140fc56eeSDmitry Torokhov /** 40240fc56eeSDmitry Torokhov * of_get_named_gpio() - Get a GPIO number to use with GPIO API 40340fc56eeSDmitry Torokhov * @np: device node to get GPIO from 40440fc56eeSDmitry Torokhov * @propname: Name of property containing gpio specifier(s) 40540fc56eeSDmitry Torokhov * @index: index of the GPIO 40640fc56eeSDmitry Torokhov * 40740fc56eeSDmitry Torokhov * Returns GPIO number to use with Linux generic GPIO API, or one of the errno 40840fc56eeSDmitry Torokhov * value on the error condition. 40940fc56eeSDmitry Torokhov */ 41040fc56eeSDmitry Torokhov int of_get_named_gpio(const struct device_node *np, const char *propname, 41140fc56eeSDmitry Torokhov int index) 412f01d9075SAlexandre Courbot { 413f01d9075SAlexandre Courbot struct gpio_desc *desc; 414f01d9075SAlexandre Courbot 41540fc56eeSDmitry Torokhov desc = of_get_named_gpiod_flags(np, propname, index, NULL); 416f01d9075SAlexandre Courbot 417f01d9075SAlexandre Courbot if (IS_ERR(desc)) 418f01d9075SAlexandre Courbot return PTR_ERR(desc); 419f01d9075SAlexandre Courbot else 420f01d9075SAlexandre Courbot return desc_to_gpio(desc); 421f01d9075SAlexandre Courbot } 42240fc56eeSDmitry Torokhov EXPORT_SYMBOL_GPL(of_get_named_gpio); 423f01d9075SAlexandre Courbot 424d9e7f0e3SDmitry Torokhov /* Converts gpio_lookup_flags into bitmask of GPIO_* values */ 425d9e7f0e3SDmitry Torokhov static unsigned long of_convert_gpio_flags(enum of_gpio_flags flags) 426d9e7f0e3SDmitry Torokhov { 427d9e7f0e3SDmitry Torokhov unsigned long lflags = GPIO_LOOKUP_FLAGS_DEFAULT; 428d9e7f0e3SDmitry Torokhov 429d9e7f0e3SDmitry Torokhov if (flags & OF_GPIO_ACTIVE_LOW) 430d9e7f0e3SDmitry Torokhov lflags |= GPIO_ACTIVE_LOW; 431d9e7f0e3SDmitry Torokhov 432d9e7f0e3SDmitry Torokhov if (flags & OF_GPIO_SINGLE_ENDED) { 433d9e7f0e3SDmitry Torokhov if (flags & OF_GPIO_OPEN_DRAIN) 434d9e7f0e3SDmitry Torokhov lflags |= GPIO_OPEN_DRAIN; 435d9e7f0e3SDmitry Torokhov else 436d9e7f0e3SDmitry Torokhov lflags |= GPIO_OPEN_SOURCE; 437d9e7f0e3SDmitry Torokhov } 438d9e7f0e3SDmitry Torokhov 439d9e7f0e3SDmitry Torokhov if (flags & OF_GPIO_TRANSITORY) 440d9e7f0e3SDmitry Torokhov lflags |= GPIO_TRANSITORY; 441d9e7f0e3SDmitry Torokhov 442d9e7f0e3SDmitry Torokhov if (flags & OF_GPIO_PULL_UP) 443d9e7f0e3SDmitry Torokhov lflags |= GPIO_PULL_UP; 444d9e7f0e3SDmitry Torokhov 445d9e7f0e3SDmitry Torokhov if (flags & OF_GPIO_PULL_DOWN) 446d9e7f0e3SDmitry Torokhov lflags |= GPIO_PULL_DOWN; 447d9e7f0e3SDmitry Torokhov 448d9e7f0e3SDmitry Torokhov if (flags & OF_GPIO_PULL_DISABLE) 449d9e7f0e3SDmitry Torokhov lflags |= GPIO_PULL_DISABLE; 450d9e7f0e3SDmitry Torokhov 451d9e7f0e3SDmitry Torokhov return lflags; 452d9e7f0e3SDmitry Torokhov } 453d9e7f0e3SDmitry Torokhov 454b311c5cbSDmitry Torokhov static struct gpio_desc *of_find_gpio_rename(struct device_node *np, 45598c3c940SDmitry Torokhov const char *con_id, 45698c3c940SDmitry Torokhov unsigned int idx, 457c8582339SLinus Walleij enum of_gpio_flags *of_flags) 458c8582339SLinus Walleij { 459b311c5cbSDmitry Torokhov static const struct of_rename_gpio { 460b311c5cbSDmitry Torokhov const char *con_id; 461b311c5cbSDmitry Torokhov const char *legacy_id; /* NULL - same as con_id */ 462b311c5cbSDmitry Torokhov /* 463b311c5cbSDmitry Torokhov * Compatible string can be set to NULL in case where 464b311c5cbSDmitry Torokhov * matching to a particular compatible is not practical, 465b311c5cbSDmitry Torokhov * but it should only be done for gpio names that have 466b311c5cbSDmitry Torokhov * vendor prefix to reduce risk of false positives. 467b311c5cbSDmitry Torokhov * Addition of such entries is strongly discouraged. 468b311c5cbSDmitry Torokhov */ 469b311c5cbSDmitry Torokhov const char *compatible; 470b311c5cbSDmitry Torokhov } gpios[] = { 471fbbbcd17SDmitry Torokhov #if !IS_ENABLED(CONFIG_LCD_HX8357) 472fbbbcd17SDmitry Torokhov /* Himax LCD controllers used "gpios-reset" */ 473fbbbcd17SDmitry Torokhov { "reset", "gpios-reset", "himax,hx8357" }, 474fbbbcd17SDmitry Torokhov { "reset", "gpios-reset", "himax,hx8369" }, 475fbbbcd17SDmitry Torokhov #endif 476b311c5cbSDmitry Torokhov #if IS_ENABLED(CONFIG_MFD_ARIZONA) 477b311c5cbSDmitry Torokhov { "wlf,reset", NULL, NULL }, 478b311c5cbSDmitry Torokhov #endif 479eaf1a296SDmitry Torokhov #if IS_ENABLED(CONFIG_RTC_DRV_MOXART) 480eaf1a296SDmitry Torokhov { "rtc-data", "gpio-rtc-data", "moxa,moxart-rtc" }, 481eaf1a296SDmitry Torokhov { "rtc-sclk", "gpio-rtc-sclk", "moxa,moxart-rtc" }, 482eaf1a296SDmitry Torokhov { "rtc-reset", "gpio-rtc-reset", "moxa,moxart-rtc" }, 483eaf1a296SDmitry Torokhov #endif 4849c2cc717SDmitry Torokhov #if IS_ENABLED(CONFIG_NFC_MRVL_I2C) 4859c2cc717SDmitry Torokhov { "reset", "reset-n-io", "marvell,nfc-i2c" }, 4869c2cc717SDmitry Torokhov #endif 4879c2cc717SDmitry Torokhov #if IS_ENABLED(CONFIG_NFC_MRVL_SPI) 4889c2cc717SDmitry Torokhov { "reset", "reset-n-io", "marvell,nfc-spi" }, 4899c2cc717SDmitry Torokhov #endif 4909c2cc717SDmitry Torokhov #if IS_ENABLED(CONFIG_NFC_MRVL_UART) 4919c2cc717SDmitry Torokhov { "reset", "reset-n-io", "marvell,nfc-uart" }, 4929c2cc717SDmitry Torokhov { "reset", "reset-n-io", "mrvl,nfc-uart" }, 4939c2cc717SDmitry Torokhov #endif 494fbbbcd17SDmitry Torokhov #if !IS_ENABLED(CONFIG_PCI_LANTIQ) 495fbbbcd17SDmitry Torokhov /* MIPS Lantiq PCI */ 496fbbbcd17SDmitry Torokhov { "reset", "gpios-reset", "lantiq,pci-xway" }, 497fbbbcd17SDmitry Torokhov #endif 498307c593bSDmitry Torokhov 499b311c5cbSDmitry Torokhov /* 500b311c5cbSDmitry Torokhov * Some regulator bindings happened before we managed to 501b311c5cbSDmitry Torokhov * establish that GPIO properties should be named 502b311c5cbSDmitry Torokhov * "foo-gpios" so we have this special kludge for them. 503b311c5cbSDmitry Torokhov */ 504307c593bSDmitry Torokhov #if IS_ENABLED(CONFIG_REGULATOR_ARIZONA_LDO1) 505b311c5cbSDmitry Torokhov { "wlf,ldoena", NULL, NULL }, /* Arizona */ 506307c593bSDmitry Torokhov #endif 507307c593bSDmitry Torokhov #if IS_ENABLED(CONFIG_REGULATOR_WM8994) 508b311c5cbSDmitry Torokhov { "wlf,ldo1ena", NULL, NULL }, /* WM8994 */ 509b311c5cbSDmitry Torokhov { "wlf,ldo2ena", NULL, NULL }, /* WM8994 */ 510b311c5cbSDmitry Torokhov #endif 511c8582339SLinus Walleij 512944004ebSDmitry Torokhov #if IS_ENABLED(CONFIG_SND_SOC_CS42L56) 513944004ebSDmitry Torokhov { "reset", "cirrus,gpio-nreset", "cirrus,cs42l56" }, 514944004ebSDmitry Torokhov #endif 515fbbbcd17SDmitry Torokhov #if IS_ENABLED(CONFIG_SND_SOC_TLV320AIC3X) 516fbbbcd17SDmitry Torokhov { "reset", "gpio-reset", "ti,tlv320aic3x" }, 517fbbbcd17SDmitry Torokhov { "reset", "gpio-reset", "ti,tlv320aic33" }, 518fbbbcd17SDmitry Torokhov { "reset", "gpio-reset", "ti,tlv320aic3007" }, 519fbbbcd17SDmitry Torokhov { "reset", "gpio-reset", "ti,tlv320aic3104" }, 520fbbbcd17SDmitry Torokhov { "reset", "gpio-reset", "ti,tlv320aic3106" }, 521fbbbcd17SDmitry Torokhov #endif 522307c593bSDmitry Torokhov #if IS_ENABLED(CONFIG_SPI_GPIO) 523c8582339SLinus Walleij /* 524b311c5cbSDmitry Torokhov * The SPI GPIO bindings happened before we managed to 525b311c5cbSDmitry Torokhov * establish that GPIO properties should be named 526b311c5cbSDmitry Torokhov * "foo-gpios" so we have this special kludge for them. 527c8582339SLinus Walleij */ 528b311c5cbSDmitry Torokhov { "miso", "gpio-miso", "spi-gpio" }, 529b311c5cbSDmitry Torokhov { "mosi", "gpio-mosi", "spi-gpio" }, 530b311c5cbSDmitry Torokhov { "sck", "gpio-sck", "spi-gpio" }, 531307c593bSDmitry Torokhov #endif 532c8582339SLinus Walleij 5336a537d48SLinus Walleij /* 534b311c5cbSDmitry Torokhov * The old Freescale bindings use simply "gpios" as name 535b311c5cbSDmitry Torokhov * for the chip select lines rather than "cs-gpios" like 536b311c5cbSDmitry Torokhov * all other SPI hardware. Allow this specifically for 537b311c5cbSDmitry Torokhov * Freescale and PPC devices. 538e3023bf8SLinus Walleij */ 539307c593bSDmitry Torokhov #if IS_ENABLED(CONFIG_SPI_FSL_SPI) 540b311c5cbSDmitry Torokhov { "cs", "gpios", "fsl,spi" }, 541b311c5cbSDmitry Torokhov { "cs", "gpios", "aeroflexgaisler,spictrl" }, 542307c593bSDmitry Torokhov #endif 543307c593bSDmitry Torokhov #if IS_ENABLED(CONFIG_SPI_PPC4xx) 544b311c5cbSDmitry Torokhov { "cs", "gpios", "ibm,ppc4xx-spi" }, 545b311c5cbSDmitry Torokhov #endif 546307c593bSDmitry Torokhov 547b311c5cbSDmitry Torokhov #if IS_ENABLED(CONFIG_TYPEC_FUSB302) 548e3023bf8SLinus Walleij /* 549b311c5cbSDmitry Torokhov * Fairchild FUSB302 host is using undocumented "fcs,int_n" 550b311c5cbSDmitry Torokhov * property without the compulsory "-gpios" suffix. 551e3023bf8SLinus Walleij */ 552b311c5cbSDmitry Torokhov { "fcs,int_n", NULL, "fcs,fusb302" }, 553b311c5cbSDmitry Torokhov #endif 5546a537d48SLinus Walleij }; 555b311c5cbSDmitry Torokhov struct gpio_desc *desc; 556b311c5cbSDmitry Torokhov const char *legacy_id; 557b311c5cbSDmitry Torokhov unsigned int i; 5586a537d48SLinus Walleij 5596a537d48SLinus Walleij if (!con_id) 5606a537d48SLinus Walleij return ERR_PTR(-ENOENT); 5616a537d48SLinus Walleij 562b311c5cbSDmitry Torokhov for (i = 0; i < ARRAY_SIZE(gpios); i++) { 563b311c5cbSDmitry Torokhov if (strcmp(con_id, gpios[i].con_id)) 564b311c5cbSDmitry Torokhov continue; 5656a537d48SLinus Walleij 566b311c5cbSDmitry Torokhov if (gpios[i].compatible && 567b311c5cbSDmitry Torokhov !of_device_is_compatible(np, gpios[i].compatible)) 568b311c5cbSDmitry Torokhov continue; 569b311c5cbSDmitry Torokhov 570b311c5cbSDmitry Torokhov legacy_id = gpios[i].legacy_id ?: gpios[i].con_id; 571b311c5cbSDmitry Torokhov desc = of_get_named_gpiod_flags(np, legacy_id, idx, of_flags); 572b311c5cbSDmitry Torokhov if (!gpiod_not_found(desc)) { 573b311c5cbSDmitry Torokhov pr_info("%s uses legacy gpio name '%s' instead of '%s-gpios'\n", 574b311c5cbSDmitry Torokhov of_node_full_name(np), legacy_id, con_id); 575b311c5cbSDmitry Torokhov return desc; 576b311c5cbSDmitry Torokhov } 5776a537d48SLinus Walleij } 5786a537d48SLinus Walleij 57911c43bb0SDmitry Torokhov return ERR_PTR(-ENOENT); 5806e24826dSLinus Walleij } 5816e24826dSLinus Walleij 582326c3753SDmitry Torokhov static struct gpio_desc *of_find_mt2701_gpio(struct device_node *np, 583326c3753SDmitry Torokhov const char *con_id, 584326c3753SDmitry Torokhov unsigned int idx, 585326c3753SDmitry Torokhov enum of_gpio_flags *of_flags) 586326c3753SDmitry Torokhov { 587326c3753SDmitry Torokhov struct gpio_desc *desc; 588326c3753SDmitry Torokhov const char *legacy_id; 589326c3753SDmitry Torokhov 590326c3753SDmitry Torokhov if (!IS_ENABLED(CONFIG_SND_SOC_MT2701_CS42448)) 591326c3753SDmitry Torokhov return ERR_PTR(-ENOENT); 592326c3753SDmitry Torokhov 593326c3753SDmitry Torokhov if (!of_device_is_compatible(np, "mediatek,mt2701-cs42448-machine")) 594326c3753SDmitry Torokhov return ERR_PTR(-ENOENT); 595326c3753SDmitry Torokhov 596326c3753SDmitry Torokhov if (!con_id || strcmp(con_id, "i2s1-in-sel")) 597326c3753SDmitry Torokhov return ERR_PTR(-ENOENT); 598326c3753SDmitry Torokhov 599326c3753SDmitry Torokhov if (idx == 0) 600326c3753SDmitry Torokhov legacy_id = "i2s1-in-sel-gpio1"; 601326c3753SDmitry Torokhov else if (idx == 1) 602326c3753SDmitry Torokhov legacy_id = "i2s1-in-sel-gpio2"; 603326c3753SDmitry Torokhov else 604326c3753SDmitry Torokhov return ERR_PTR(-ENOENT); 605326c3753SDmitry Torokhov 606326c3753SDmitry Torokhov desc = of_get_named_gpiod_flags(np, legacy_id, 0, of_flags); 607326c3753SDmitry Torokhov if (!gpiod_not_found(desc)) 608326c3753SDmitry Torokhov pr_info("%s is using legacy gpio name '%s' instead of '%s-gpios'\n", 609326c3753SDmitry Torokhov of_node_full_name(np), legacy_id, con_id); 610326c3753SDmitry Torokhov 611326c3753SDmitry Torokhov return desc; 612326c3753SDmitry Torokhov } 613326c3753SDmitry Torokhov 614a2b5e207SDmitry Torokhov typedef struct gpio_desc *(*of_find_gpio_quirk)(struct device_node *np, 615a2b5e207SDmitry Torokhov const char *con_id, 616a2b5e207SDmitry Torokhov unsigned int idx, 617a2b5e207SDmitry Torokhov enum of_gpio_flags *of_flags); 618a2b5e207SDmitry Torokhov static const of_find_gpio_quirk of_find_gpio_quirks[] = { 619b311c5cbSDmitry Torokhov of_find_gpio_rename, 620326c3753SDmitry Torokhov of_find_mt2701_gpio, 6218b10ca2fSMichael Walle NULL 622a2b5e207SDmitry Torokhov }; 623a2b5e207SDmitry Torokhov 62407445ae1SDmitry Torokhov struct gpio_desc *of_find_gpio(struct device_node *np, const char *con_id, 625fed7026aSAndy Shevchenko unsigned int idx, unsigned long *flags) 626ea713bc4SLinus Walleij { 627ea713bc4SLinus Walleij char prop_name[32]; /* 32 is max size of property name */ 628ea713bc4SLinus Walleij enum of_gpio_flags of_flags; 629a2b5e207SDmitry Torokhov const of_find_gpio_quirk *q; 630ea713bc4SLinus Walleij struct gpio_desc *desc; 631ea713bc4SLinus Walleij unsigned int i; 632ea713bc4SLinus Walleij 633c8582339SLinus Walleij /* Try GPIO property "foo-gpios" and "foo-gpio" */ 634ea713bc4SLinus Walleij for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) { 635ea713bc4SLinus Walleij if (con_id) 636ea713bc4SLinus Walleij snprintf(prop_name, sizeof(prop_name), "%s-%s", con_id, 637ea713bc4SLinus Walleij gpio_suffixes[i]); 638ea713bc4SLinus Walleij else 639ea713bc4SLinus Walleij snprintf(prop_name, sizeof(prop_name), "%s", 640ea713bc4SLinus Walleij gpio_suffixes[i]); 641ea713bc4SLinus Walleij 64207445ae1SDmitry Torokhov desc = of_get_named_gpiod_flags(np, prop_name, idx, &of_flags); 6436662ae6aSMaxime Ripard 6447b58696dSAndy Shevchenko if (!gpiod_not_found(desc)) 645ea713bc4SLinus Walleij break; 646ea713bc4SLinus Walleij } 647ea713bc4SLinus Walleij 648a2b5e207SDmitry Torokhov /* Properly named GPIO was not found, try workarounds */ 649a2b5e207SDmitry Torokhov for (q = of_find_gpio_quirks; gpiod_not_found(desc) && *q; q++) 65007445ae1SDmitry Torokhov desc = (*q)(np, con_id, idx, &of_flags); 6516e24826dSLinus Walleij 652ea713bc4SLinus Walleij if (IS_ERR(desc)) 653ea713bc4SLinus Walleij return desc; 654ea713bc4SLinus Walleij 655d9e7f0e3SDmitry Torokhov *flags = of_convert_gpio_flags(of_flags); 656d449991cSThomas Petazzoni 657ea713bc4SLinus Walleij return desc; 658ea713bc4SLinus Walleij } 659ea713bc4SLinus Walleij 660f141ed65SGrant Likely /** 661fd7337fdSMarkus Pargmann * of_parse_own_gpio() - Get a GPIO hog descriptor, names and flags for GPIO API 662f625d460SBenoit Parrot * @np: device node to get GPIO from 663be715343SMasahiro Yamada * @chip: GPIO chip whose hog is parsed 664a79fead5SGeert Uytterhoeven * @idx: Index of the GPIO to parse 665f625d460SBenoit Parrot * @name: GPIO line name 666fed7026aSAndy Shevchenko * @lflags: bitmask of gpio_lookup_flags GPIO_* values - returned from 667fed7026aSAndy Shevchenko * of_find_gpio() or of_parse_own_gpio() 668f625d460SBenoit Parrot * @dflags: gpiod_flags - optional GPIO initialization flags 669f625d460SBenoit Parrot * 670f625d460SBenoit Parrot * Returns GPIO descriptor to use with Linux GPIO API, or one of the errno 671f625d460SBenoit Parrot * value on the error condition. 672f625d460SBenoit Parrot */ 673fd7337fdSMarkus Pargmann static struct gpio_desc *of_parse_own_gpio(struct device_node *np, 674be715343SMasahiro Yamada struct gpio_chip *chip, 675a79fead5SGeert Uytterhoeven unsigned int idx, const char **name, 676fed7026aSAndy Shevchenko unsigned long *lflags, 677f625d460SBenoit Parrot enum gpiod_flags *dflags) 678f625d460SBenoit Parrot { 679f625d460SBenoit Parrot struct device_node *chip_np; 680f625d460SBenoit Parrot enum of_gpio_flags xlate_flags; 681be715343SMasahiro Yamada struct of_phandle_args gpiospec; 682be715343SMasahiro Yamada struct gpio_desc *desc; 683a79fead5SGeert Uytterhoeven unsigned int i; 684f625d460SBenoit Parrot u32 tmp; 6853f9547e1SMasahiro Yamada int ret; 686f625d460SBenoit Parrot 68770d0fc42SAndy Shevchenko chip_np = dev_of_node(&chip->gpiodev->dev); 688f625d460SBenoit Parrot if (!chip_np) 689f625d460SBenoit Parrot return ERR_PTR(-EINVAL); 690f625d460SBenoit Parrot 691f625d460SBenoit Parrot xlate_flags = 0; 6922d6c06f5SAndy Shevchenko *lflags = GPIO_LOOKUP_FLAGS_DEFAULT; 69340941954SAndy Shevchenko *dflags = GPIOD_ASIS; 694f625d460SBenoit Parrot 695f625d460SBenoit Parrot ret = of_property_read_u32(chip_np, "#gpio-cells", &tmp); 696f625d460SBenoit Parrot if (ret) 697f625d460SBenoit Parrot return ERR_PTR(ret); 698f625d460SBenoit Parrot 699be715343SMasahiro Yamada gpiospec.np = chip_np; 700be715343SMasahiro Yamada gpiospec.args_count = tmp; 701f625d460SBenoit Parrot 702a79fead5SGeert Uytterhoeven for (i = 0; i < tmp; i++) { 703a79fead5SGeert Uytterhoeven ret = of_property_read_u32_index(np, "gpios", idx * tmp + i, 704a79fead5SGeert Uytterhoeven &gpiospec.args[i]); 705f625d460SBenoit Parrot if (ret) 706f625d460SBenoit Parrot return ERR_PTR(ret); 707a79fead5SGeert Uytterhoeven } 708f625d460SBenoit Parrot 70999468c1aSMasahiro Yamada desc = of_xlate_and_get_gpiod_flags(chip, &gpiospec, &xlate_flags); 710be715343SMasahiro Yamada if (IS_ERR(desc)) 711be715343SMasahiro Yamada return desc; 712f625d460SBenoit Parrot 713d9e7f0e3SDmitry Torokhov *lflags = of_convert_gpio_flags(xlate_flags); 714f625d460SBenoit Parrot 715f625d460SBenoit Parrot if (of_property_read_bool(np, "input")) 716f625d460SBenoit Parrot *dflags |= GPIOD_IN; 717f625d460SBenoit Parrot else if (of_property_read_bool(np, "output-low")) 718f625d460SBenoit Parrot *dflags |= GPIOD_OUT_LOW; 719f625d460SBenoit Parrot else if (of_property_read_bool(np, "output-high")) 720f625d460SBenoit Parrot *dflags |= GPIOD_OUT_HIGH; 721f625d460SBenoit Parrot else { 72262cdcb6cSRob Herring pr_warn("GPIO line %d (%pOFn): no hogging state specified, bailing out\n", 72362cdcb6cSRob Herring desc_to_gpio(desc), np); 724f625d460SBenoit Parrot return ERR_PTR(-EINVAL); 725f625d460SBenoit Parrot } 726f625d460SBenoit Parrot 727f625d460SBenoit Parrot if (name && of_property_read_string(np, "line-name", name)) 728f625d460SBenoit Parrot *name = np->name; 729f625d460SBenoit Parrot 730be715343SMasahiro Yamada return desc; 731f625d460SBenoit Parrot } 732f625d460SBenoit Parrot 733f625d460SBenoit Parrot /** 734bc21077eSGeert Uytterhoeven * of_gpiochip_add_hog - Add all hogs in a hog device node 735bc21077eSGeert Uytterhoeven * @chip: gpio chip to act on 736bc21077eSGeert Uytterhoeven * @hog: device node describing the hogs 737bc21077eSGeert Uytterhoeven * 738bc21077eSGeert Uytterhoeven * Returns error if it fails otherwise 0 on success. 739bc21077eSGeert Uytterhoeven */ 740bc21077eSGeert Uytterhoeven static int of_gpiochip_add_hog(struct gpio_chip *chip, struct device_node *hog) 741bc21077eSGeert Uytterhoeven { 742bc21077eSGeert Uytterhoeven enum gpiod_flags dflags; 743bc21077eSGeert Uytterhoeven struct gpio_desc *desc; 744bc21077eSGeert Uytterhoeven unsigned long lflags; 745bc21077eSGeert Uytterhoeven const char *name; 746bc21077eSGeert Uytterhoeven unsigned int i; 747bc21077eSGeert Uytterhoeven int ret; 748bc21077eSGeert Uytterhoeven 749bc21077eSGeert Uytterhoeven for (i = 0;; i++) { 750bc21077eSGeert Uytterhoeven desc = of_parse_own_gpio(hog, chip, i, &name, &lflags, &dflags); 751bc21077eSGeert Uytterhoeven if (IS_ERR(desc)) 752bc21077eSGeert Uytterhoeven break; 753bc21077eSGeert Uytterhoeven 754bc21077eSGeert Uytterhoeven ret = gpiod_hog(desc, name, lflags, dflags); 755bc21077eSGeert Uytterhoeven if (ret < 0) 756bc21077eSGeert Uytterhoeven return ret; 75763636d95SGeert Uytterhoeven 75863636d95SGeert Uytterhoeven #ifdef CONFIG_OF_DYNAMIC 75963636d95SGeert Uytterhoeven desc->hog = hog; 76063636d95SGeert Uytterhoeven #endif 761bc21077eSGeert Uytterhoeven } 762bc21077eSGeert Uytterhoeven 763bc21077eSGeert Uytterhoeven return 0; 764bc21077eSGeert Uytterhoeven } 765bc21077eSGeert Uytterhoeven 766bc21077eSGeert Uytterhoeven /** 767fd7337fdSMarkus Pargmann * of_gpiochip_scan_gpios - Scan gpio-controller for gpio definitions 768f625d460SBenoit Parrot * @chip: gpio chip to act on 769f625d460SBenoit Parrot * 770f625d460SBenoit Parrot * This is only used by of_gpiochip_add to request/set GPIO initial 771f625d460SBenoit Parrot * configuration. 772ead066e6SGeert Uytterhoeven * It returns error if it fails otherwise 0 on success. 773f625d460SBenoit Parrot */ 774dfbd379bSLaxman Dewangan static int of_gpiochip_scan_gpios(struct gpio_chip *chip) 775f625d460SBenoit Parrot { 776f625d460SBenoit Parrot struct device_node *np; 777dfbd379bSLaxman Dewangan int ret; 778f625d460SBenoit Parrot 77970d0fc42SAndy Shevchenko for_each_available_child_of_node(dev_of_node(&chip->gpiodev->dev), np) { 780f625d460SBenoit Parrot if (!of_property_read_bool(np, "gpio-hog")) 781f625d460SBenoit Parrot continue; 782f625d460SBenoit Parrot 783bc21077eSGeert Uytterhoeven ret = of_gpiochip_add_hog(chip, np); 78409e258afSWei Yongjun if (ret < 0) { 78509e258afSWei Yongjun of_node_put(np); 786dfbd379bSLaxman Dewangan return ret; 787f625d460SBenoit Parrot } 78863636d95SGeert Uytterhoeven 78963636d95SGeert Uytterhoeven of_node_set_flag(np, OF_POPULATED); 79009e258afSWei Yongjun } 791dfbd379bSLaxman Dewangan 792dfbd379bSLaxman Dewangan return 0; 793f625d460SBenoit Parrot } 794f625d460SBenoit Parrot 79563636d95SGeert Uytterhoeven #ifdef CONFIG_OF_DYNAMIC 79663636d95SGeert Uytterhoeven /** 79763636d95SGeert Uytterhoeven * of_gpiochip_remove_hog - Remove all hogs in a hog device node 79863636d95SGeert Uytterhoeven * @chip: gpio chip to act on 79963636d95SGeert Uytterhoeven * @hog: device node describing the hogs 80063636d95SGeert Uytterhoeven */ 80163636d95SGeert Uytterhoeven static void of_gpiochip_remove_hog(struct gpio_chip *chip, 80263636d95SGeert Uytterhoeven struct device_node *hog) 80363636d95SGeert Uytterhoeven { 80480c78fbeSAndy Shevchenko struct gpio_desc *desc; 80563636d95SGeert Uytterhoeven 80657017eddSAndy Shevchenko for_each_gpio_desc_with_flag(chip, desc, FLAG_IS_HOGGED) 80780c78fbeSAndy Shevchenko if (desc->hog == hog) 80880c78fbeSAndy Shevchenko gpiochip_free_own_desc(desc); 80963636d95SGeert Uytterhoeven } 81063636d95SGeert Uytterhoeven 81163636d95SGeert Uytterhoeven static int of_gpiochip_match_node(struct gpio_chip *chip, void *data) 81263636d95SGeert Uytterhoeven { 813597a8a88SAndy Shevchenko return device_match_of_node(&chip->gpiodev->dev, data); 81463636d95SGeert Uytterhoeven } 81563636d95SGeert Uytterhoeven 81663636d95SGeert Uytterhoeven static struct gpio_chip *of_find_gpiochip_by_node(struct device_node *np) 81763636d95SGeert Uytterhoeven { 81863636d95SGeert Uytterhoeven return gpiochip_find(np, of_gpiochip_match_node); 81963636d95SGeert Uytterhoeven } 82063636d95SGeert Uytterhoeven 82163636d95SGeert Uytterhoeven static int of_gpio_notify(struct notifier_block *nb, unsigned long action, 82263636d95SGeert Uytterhoeven void *arg) 82363636d95SGeert Uytterhoeven { 82463636d95SGeert Uytterhoeven struct of_reconfig_data *rd = arg; 82563636d95SGeert Uytterhoeven struct gpio_chip *chip; 82663636d95SGeert Uytterhoeven int ret; 82763636d95SGeert Uytterhoeven 82863636d95SGeert Uytterhoeven /* 82963636d95SGeert Uytterhoeven * This only supports adding and removing complete gpio-hog nodes. 83063636d95SGeert Uytterhoeven * Modifying an existing gpio-hog node is not supported (except for 83163636d95SGeert Uytterhoeven * changing its "status" property, which is treated the same as 83263636d95SGeert Uytterhoeven * addition/removal). 83363636d95SGeert Uytterhoeven */ 83463636d95SGeert Uytterhoeven switch (of_reconfig_get_state_change(action, arg)) { 83563636d95SGeert Uytterhoeven case OF_RECONFIG_CHANGE_ADD: 83663636d95SGeert Uytterhoeven if (!of_property_read_bool(rd->dn, "gpio-hog")) 83763636d95SGeert Uytterhoeven return NOTIFY_OK; /* not for us */ 83863636d95SGeert Uytterhoeven 83963636d95SGeert Uytterhoeven if (of_node_test_and_set_flag(rd->dn, OF_POPULATED)) 84063636d95SGeert Uytterhoeven return NOTIFY_OK; 84163636d95SGeert Uytterhoeven 84263636d95SGeert Uytterhoeven chip = of_find_gpiochip_by_node(rd->dn->parent); 84363636d95SGeert Uytterhoeven if (chip == NULL) 84463636d95SGeert Uytterhoeven return NOTIFY_OK; /* not for us */ 84563636d95SGeert Uytterhoeven 84663636d95SGeert Uytterhoeven ret = of_gpiochip_add_hog(chip, rd->dn); 84763636d95SGeert Uytterhoeven if (ret < 0) { 84863636d95SGeert Uytterhoeven pr_err("%s: failed to add hogs for %pOF\n", __func__, 84963636d95SGeert Uytterhoeven rd->dn); 85063636d95SGeert Uytterhoeven of_node_clear_flag(rd->dn, OF_POPULATED); 85163636d95SGeert Uytterhoeven return notifier_from_errno(ret); 85263636d95SGeert Uytterhoeven } 85363636d95SGeert Uytterhoeven break; 85463636d95SGeert Uytterhoeven 85563636d95SGeert Uytterhoeven case OF_RECONFIG_CHANGE_REMOVE: 85663636d95SGeert Uytterhoeven if (!of_node_check_flag(rd->dn, OF_POPULATED)) 85763636d95SGeert Uytterhoeven return NOTIFY_OK; /* already depopulated */ 85863636d95SGeert Uytterhoeven 85963636d95SGeert Uytterhoeven chip = of_find_gpiochip_by_node(rd->dn->parent); 86063636d95SGeert Uytterhoeven if (chip == NULL) 86163636d95SGeert Uytterhoeven return NOTIFY_OK; /* not for us */ 86263636d95SGeert Uytterhoeven 86363636d95SGeert Uytterhoeven of_gpiochip_remove_hog(chip, rd->dn); 86463636d95SGeert Uytterhoeven of_node_clear_flag(rd->dn, OF_POPULATED); 86563636d95SGeert Uytterhoeven break; 86663636d95SGeert Uytterhoeven } 86763636d95SGeert Uytterhoeven 86863636d95SGeert Uytterhoeven return NOTIFY_OK; 86963636d95SGeert Uytterhoeven } 87063636d95SGeert Uytterhoeven 87163636d95SGeert Uytterhoeven struct notifier_block gpio_of_notifier = { 87263636d95SGeert Uytterhoeven .notifier_call = of_gpio_notify, 87363636d95SGeert Uytterhoeven }; 87463636d95SGeert Uytterhoeven #endif /* CONFIG_OF_DYNAMIC */ 87563636d95SGeert Uytterhoeven 876f625d460SBenoit Parrot /** 87767049c50SThierry Reding * of_gpio_simple_xlate - translate gpiospec to the GPIO number and flags 878f141ed65SGrant Likely * @gc: pointer to the gpio_chip structure 87967049c50SThierry Reding * @gpiospec: GPIO specifier as found in the device tree 880f141ed65SGrant Likely * @flags: a flags pointer to fill in 881f141ed65SGrant Likely * 882f141ed65SGrant Likely * This is simple translation function, suitable for the most 1:1 mapped 88367049c50SThierry Reding * GPIO chips. This function performs only one sanity check: whether GPIO 884f141ed65SGrant Likely * is less than ngpios (that is specified in the gpio_chip). 885f141ed65SGrant Likely */ 886b0c7e73bSGeert Uytterhoeven static int of_gpio_simple_xlate(struct gpio_chip *gc, 887b0c7e73bSGeert Uytterhoeven const struct of_phandle_args *gpiospec, 888b0c7e73bSGeert Uytterhoeven u32 *flags) 889f141ed65SGrant Likely { 890f141ed65SGrant Likely /* 891f141ed65SGrant Likely * We're discouraging gpio_cells < 2, since that way you'll have to 89220a8a968SColin Cronin * write your own xlate function (that will have to retrieve the GPIO 893f141ed65SGrant Likely * number and the flags from a single gpio cell -- this is possible, 894f141ed65SGrant Likely * but not recommended). 895f141ed65SGrant Likely */ 896f141ed65SGrant Likely if (gc->of_gpio_n_cells < 2) { 897f141ed65SGrant Likely WARN_ON(1); 898f141ed65SGrant Likely return -EINVAL; 899f141ed65SGrant Likely } 900f141ed65SGrant Likely 901f141ed65SGrant Likely if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells)) 902f141ed65SGrant Likely return -EINVAL; 903f141ed65SGrant Likely 9047b96c686SGrant Likely if (gpiospec->args[0] >= gc->ngpio) 905f141ed65SGrant Likely return -EINVAL; 906f141ed65SGrant Likely 907f141ed65SGrant Likely if (flags) 908f141ed65SGrant Likely *flags = gpiospec->args[1]; 909f141ed65SGrant Likely 910f141ed65SGrant Likely return gpiospec->args[0]; 911f141ed65SGrant Likely } 912f141ed65SGrant Likely 913a99cc668SArnd Bergmann #if IS_ENABLED(CONFIG_OF_GPIO_MM_GPIOCHIP) 914a99cc668SArnd Bergmann #include <linux/gpio/legacy-of-mm-gpiochip.h> 915f141ed65SGrant Likely /** 9163208b0f0SLinus Walleij * of_mm_gpiochip_add_data - Add memory mapped GPIO chip (bank) 917f141ed65SGrant Likely * @np: device node of the GPIO chip 918f141ed65SGrant Likely * @mm_gc: pointer to the of_mm_gpio_chip allocated structure 9193208b0f0SLinus Walleij * @data: driver data to store in the struct gpio_chip 920f141ed65SGrant Likely * 921f141ed65SGrant Likely * To use this function you should allocate and fill mm_gc with: 922f141ed65SGrant Likely * 923f141ed65SGrant Likely * 1) In the gpio_chip structure: 924f141ed65SGrant Likely * - all the callbacks 925f141ed65SGrant Likely * - of_gpio_n_cells 926f141ed65SGrant Likely * - of_xlate callback (optional) 927f141ed65SGrant Likely * 928f141ed65SGrant Likely * 3) In the of_mm_gpio_chip structure: 929f141ed65SGrant Likely * - save_regs callback (optional) 930f141ed65SGrant Likely * 931f141ed65SGrant Likely * If succeeded, this function will map bank's memory and will 932f141ed65SGrant Likely * do all necessary work for you. Then you'll able to use .regs 933f141ed65SGrant Likely * to manage GPIOs from the callbacks. 934f141ed65SGrant Likely */ 9353208b0f0SLinus Walleij int of_mm_gpiochip_add_data(struct device_node *np, 9363208b0f0SLinus Walleij struct of_mm_gpio_chip *mm_gc, 9373208b0f0SLinus Walleij void *data) 938f141ed65SGrant Likely { 939f141ed65SGrant Likely int ret = -ENOMEM; 940f141ed65SGrant Likely struct gpio_chip *gc = &mm_gc->gc; 941f141ed65SGrant Likely 9427eb6ce2fSRob Herring gc->label = kasprintf(GFP_KERNEL, "%pOF", np); 943f141ed65SGrant Likely if (!gc->label) 944f141ed65SGrant Likely goto err0; 945f141ed65SGrant Likely 946f141ed65SGrant Likely mm_gc->regs = of_iomap(np, 0); 947f141ed65SGrant Likely if (!mm_gc->regs) 948f141ed65SGrant Likely goto err1; 949f141ed65SGrant Likely 950f141ed65SGrant Likely gc->base = -1; 951f141ed65SGrant Likely 952f141ed65SGrant Likely if (mm_gc->save_regs) 953f141ed65SGrant Likely mm_gc->save_regs(mm_gc); 954f141ed65SGrant Likely 95577289b2fSAndy Shevchenko fwnode_handle_put(mm_gc->gc.fwnode); 95677289b2fSAndy Shevchenko mm_gc->gc.fwnode = fwnode_handle_get(of_fwnode_handle(np)); 957f141ed65SGrant Likely 9583208b0f0SLinus Walleij ret = gpiochip_add_data(gc, data); 959f141ed65SGrant Likely if (ret) 960f141ed65SGrant Likely goto err2; 961f141ed65SGrant Likely 962f141ed65SGrant Likely return 0; 963f141ed65SGrant Likely err2: 9645d07a692SLiang He of_node_put(np); 965f141ed65SGrant Likely iounmap(mm_gc->regs); 966f141ed65SGrant Likely err1: 967f141ed65SGrant Likely kfree(gc->label); 968f141ed65SGrant Likely err0: 9697eb6ce2fSRob Herring pr_err("%pOF: GPIO chip registration failed with status %d\n", np, ret); 970f141ed65SGrant Likely return ret; 971f141ed65SGrant Likely } 9726d662455SGeert Uytterhoeven EXPORT_SYMBOL_GPL(of_mm_gpiochip_add_data); 973f141ed65SGrant Likely 974d621e8baSRicardo Ribalda Delgado /** 975d621e8baSRicardo Ribalda Delgado * of_mm_gpiochip_remove - Remove memory mapped GPIO chip (bank) 976d621e8baSRicardo Ribalda Delgado * @mm_gc: pointer to the of_mm_gpio_chip allocated structure 977d621e8baSRicardo Ribalda Delgado */ 978d621e8baSRicardo Ribalda Delgado void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc) 979d621e8baSRicardo Ribalda Delgado { 980d621e8baSRicardo Ribalda Delgado struct gpio_chip *gc = &mm_gc->gc; 981d621e8baSRicardo Ribalda Delgado 982d621e8baSRicardo Ribalda Delgado gpiochip_remove(gc); 983d621e8baSRicardo Ribalda Delgado iounmap(mm_gc->regs); 984d621e8baSRicardo Ribalda Delgado kfree(gc->label); 985d621e8baSRicardo Ribalda Delgado } 9866d662455SGeert Uytterhoeven EXPORT_SYMBOL_GPL(of_mm_gpiochip_remove); 987a99cc668SArnd Bergmann #endif 988d621e8baSRicardo Ribalda Delgado 989f23f1516SShiraz Hashim #ifdef CONFIG_PINCTRL 99028355f81STomeu Vizoso static int of_gpiochip_add_pin_range(struct gpio_chip *chip) 991f23f1516SShiraz Hashim { 992f23f1516SShiraz Hashim struct of_phandle_args pinspec; 9931e63d7b9SLinus Walleij struct pinctrl_dev *pctldev; 99470d0fc42SAndy Shevchenko struct device_node *np; 995f23f1516SShiraz Hashim int index = 0, ret; 996586a87e6SChristian Ruppert const char *name; 997586a87e6SChristian Ruppert static const char group_names_propname[] = "gpio-ranges-group-names"; 998586a87e6SChristian Ruppert struct property *group_names; 999f23f1516SShiraz Hashim 100070d0fc42SAndy Shevchenko np = dev_of_node(&chip->gpiodev->dev); 1001f23f1516SShiraz Hashim if (!np) 100228355f81STomeu Vizoso return 0; 1003f23f1516SShiraz Hashim 1004586a87e6SChristian Ruppert group_names = of_find_property(np, group_names_propname, NULL); 1005586a87e6SChristian Ruppert 1006ad4e1a7cSHaojian Zhuang for (;; index++) { 1007d9fe0039SStephen Warren ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, 1008d9fe0039SStephen Warren index, &pinspec); 1009f23f1516SShiraz Hashim if (ret) 1010f23f1516SShiraz Hashim break; 1011f23f1516SShiraz Hashim 10121e63d7b9SLinus Walleij pctldev = of_pinctrl_get(pinspec.np); 1013602cf638SMasahiro Yamada of_node_put(pinspec.np); 10141e63d7b9SLinus Walleij if (!pctldev) 101528355f81STomeu Vizoso return -EPROBE_DEFER; 1016f23f1516SShiraz Hashim 1017586a87e6SChristian Ruppert if (pinspec.args[2]) { 1018586a87e6SChristian Ruppert if (group_names) { 101972858602SLaurent Navet of_property_read_string_index(np, 1020586a87e6SChristian Ruppert group_names_propname, 1021586a87e6SChristian Ruppert index, &name); 1022586a87e6SChristian Ruppert if (strlen(name)) { 10237eb6ce2fSRob Herring pr_err("%pOF: Group name of numeric GPIO ranges must be the empty string.\n", 10247eb6ce2fSRob Herring np); 1025586a87e6SChristian Ruppert break; 1026586a87e6SChristian Ruppert } 1027586a87e6SChristian Ruppert } 1028586a87e6SChristian Ruppert /* npins != 0: linear range */ 10291e63d7b9SLinus Walleij ret = gpiochip_add_pin_range(chip, 1030ef5e3eefSHaojian Zhuang pinctrl_dev_get_devname(pctldev), 10311e63d7b9SLinus Walleij pinspec.args[0], 103286853c83SHaojian Zhuang pinspec.args[1], 103386853c83SHaojian Zhuang pinspec.args[2]); 10341e63d7b9SLinus Walleij if (ret) 103528355f81STomeu Vizoso return ret; 1036586a87e6SChristian Ruppert } else { 1037586a87e6SChristian Ruppert /* npins == 0: special range */ 1038586a87e6SChristian Ruppert if (pinspec.args[1]) { 10397eb6ce2fSRob Herring pr_err("%pOF: Illegal gpio-range format.\n", 10407eb6ce2fSRob Herring np); 1041586a87e6SChristian Ruppert break; 1042586a87e6SChristian Ruppert } 1043586a87e6SChristian Ruppert 1044586a87e6SChristian Ruppert if (!group_names) { 10457eb6ce2fSRob Herring pr_err("%pOF: GPIO group range requested but no %s property.\n", 10467eb6ce2fSRob Herring np, group_names_propname); 1047586a87e6SChristian Ruppert break; 1048586a87e6SChristian Ruppert } 1049586a87e6SChristian Ruppert 1050586a87e6SChristian Ruppert ret = of_property_read_string_index(np, 1051586a87e6SChristian Ruppert group_names_propname, 1052586a87e6SChristian Ruppert index, &name); 1053586a87e6SChristian Ruppert if (ret) 1054586a87e6SChristian Ruppert break; 1055586a87e6SChristian Ruppert 1056586a87e6SChristian Ruppert if (!strlen(name)) { 10577eb6ce2fSRob Herring pr_err("%pOF: Group name of GPIO group range cannot be the empty string.\n", 10587eb6ce2fSRob Herring np); 1059586a87e6SChristian Ruppert break; 1060586a87e6SChristian Ruppert } 1061586a87e6SChristian Ruppert 1062586a87e6SChristian Ruppert ret = gpiochip_add_pingroup_range(chip, pctldev, 1063586a87e6SChristian Ruppert pinspec.args[0], name); 1064586a87e6SChristian Ruppert if (ret) 106528355f81STomeu Vizoso return ret; 1066586a87e6SChristian Ruppert } 1067ad4e1a7cSHaojian Zhuang } 106828355f81STomeu Vizoso 106928355f81STomeu Vizoso return 0; 1070f23f1516SShiraz Hashim } 1071f23f1516SShiraz Hashim 1072f23f1516SShiraz Hashim #else 107328355f81STomeu Vizoso static int of_gpiochip_add_pin_range(struct gpio_chip *chip) { return 0; } 1074f23f1516SShiraz Hashim #endif 1075f23f1516SShiraz Hashim 107628355f81STomeu Vizoso int of_gpiochip_add(struct gpio_chip *chip) 1077f141ed65SGrant Likely { 10788afe8255SAndy Shevchenko struct device_node *np; 1079f0d1ab05SLinus Walleij int ret; 108028355f81STomeu Vizoso 108170d0fc42SAndy Shevchenko np = dev_of_node(&chip->gpiodev->dev); 10828afe8255SAndy Shevchenko if (!np) 108328355f81STomeu Vizoso return 0; 1084f141ed65SGrant Likely 1085f141ed65SGrant Likely if (!chip->of_xlate) { 1086f141ed65SGrant Likely chip->of_gpio_n_cells = 2; 1087f141ed65SGrant Likely chip->of_xlate = of_gpio_simple_xlate; 1088f141ed65SGrant Likely } 1089f141ed65SGrant Likely 10901020dfd1SMasahiro Yamada if (chip->of_gpio_n_cells > MAX_PHANDLE_ARGS) 10911020dfd1SMasahiro Yamada return -EINVAL; 10921020dfd1SMasahiro Yamada 1093f0d1ab05SLinus Walleij ret = of_gpiochip_add_pin_range(chip); 1094f0d1ab05SLinus Walleij if (ret) 1095f0d1ab05SLinus Walleij return ret; 109628355f81STomeu Vizoso 10978afe8255SAndy Shevchenko fwnode_handle_get(chip->fwnode); 1098f625d460SBenoit Parrot 1099f0d1ab05SLinus Walleij ret = of_gpiochip_scan_gpios(chip); 11002f4133bbSAndy Shevchenko if (ret) 11018afe8255SAndy Shevchenko fwnode_handle_put(chip->fwnode); 1102f7299d44SGeert Uytterhoeven 1103f0d1ab05SLinus Walleij return ret; 1104f141ed65SGrant Likely } 1105f141ed65SGrant Likely 1106f141ed65SGrant Likely void of_gpiochip_remove(struct gpio_chip *chip) 1107f141ed65SGrant Likely { 11088afe8255SAndy Shevchenko fwnode_handle_put(chip->fwnode); 1109f141ed65SGrant Likely } 1110