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/module.h> 14f141ed65SGrant Likely #include <linux/io.h> 15af8b6375SAlexandre Courbot #include <linux/gpio/consumer.h> 16f141ed65SGrant Likely #include <linux/of.h> 17f141ed65SGrant Likely #include <linux/of_address.h> 18f141ed65SGrant Likely #include <linux/of_gpio.h> 19f23f1516SShiraz Hashim #include <linux/pinctrl/pinctrl.h> 20f141ed65SGrant Likely #include <linux/slab.h> 21f625d460SBenoit Parrot #include <linux/gpio/machine.h> 22f141ed65SGrant Likely 231bd6b601SAlexandre Courbot #include "gpiolib.h" 24f626d6dfSLinus Walleij #include "gpiolib-of.h" 25f626d6dfSLinus Walleij 26eed5a3bfSAndy Shevchenko /* 27eed5a3bfSAndy Shevchenko * This is Linux-specific flags. By default controllers' and Linux' mapping 28eed5a3bfSAndy Shevchenko * match, but GPIO controllers are free to translate their own flags to 29eed5a3bfSAndy Shevchenko * Linux-specific in their .xlate callback. Though, 1:1 mapping is recommended. 30eed5a3bfSAndy Shevchenko */ 31eed5a3bfSAndy Shevchenko enum of_gpio_flags { 32eed5a3bfSAndy Shevchenko OF_GPIO_ACTIVE_LOW = 0x1, 33eed5a3bfSAndy Shevchenko OF_GPIO_SINGLE_ENDED = 0x2, 34eed5a3bfSAndy Shevchenko OF_GPIO_OPEN_DRAIN = 0x4, 35eed5a3bfSAndy Shevchenko OF_GPIO_TRANSITORY = 0x8, 36eed5a3bfSAndy Shevchenko OF_GPIO_PULL_UP = 0x10, 37eed5a3bfSAndy Shevchenko OF_GPIO_PULL_DOWN = 0x20, 38eed5a3bfSAndy Shevchenko OF_GPIO_PULL_DISABLE = 0x40, 39eed5a3bfSAndy Shevchenko }; 40eed5a3bfSAndy Shevchenko 4171b8f600SLinus Walleij /** 42c7835652SDmitry Torokhov * of_gpio_named_count() - Count GPIOs for a device 43c7835652SDmitry Torokhov * @np: device node to count GPIOs for 44c7835652SDmitry Torokhov * @propname: property name containing gpio specifier(s) 45c7835652SDmitry Torokhov * 46c7835652SDmitry Torokhov * The function returns the count of GPIOs specified for a node. 47c7835652SDmitry Torokhov * Note that the empty GPIO specifiers count too. Returns either 48c7835652SDmitry Torokhov * Number of gpios defined in property, 49c7835652SDmitry Torokhov * -EINVAL for an incorrectly formed gpios property, or 50c7835652SDmitry Torokhov * -ENOENT for a missing gpios property 51c7835652SDmitry Torokhov * 52c7835652SDmitry Torokhov * Example: 53c7835652SDmitry Torokhov * gpios = <0 54c7835652SDmitry Torokhov * &gpio1 1 2 55c7835652SDmitry Torokhov * 0 56c7835652SDmitry Torokhov * &gpio2 3 4>; 57c7835652SDmitry Torokhov * 58c7835652SDmitry Torokhov * The above example defines four GPIOs, two of which are not specified. 59c7835652SDmitry Torokhov * This function will return '4' 60c7835652SDmitry Torokhov */ 61c7835652SDmitry Torokhov static int of_gpio_named_count(const struct device_node *np, 62c7835652SDmitry Torokhov const char *propname) 63c7835652SDmitry Torokhov { 64c7835652SDmitry Torokhov return of_count_phandle_with_args(np, propname, "#gpio-cells"); 65c7835652SDmitry Torokhov } 66c7835652SDmitry Torokhov 67c7835652SDmitry Torokhov /** 6871b8f600SLinus Walleij * of_gpio_spi_cs_get_count() - special GPIO counting for SPI 69c5a66b97SLee Jones * @dev: Consuming device 70c5a66b97SLee Jones * @con_id: Function within the GPIO consumer 71c5a66b97SLee Jones * 7271b8f600SLinus Walleij * Some elder GPIO controllers need special quirks. Currently we handle 7347267732SLinus Walleij * the Freescale and PPC GPIO controller with bindings that doesn't use the 7471b8f600SLinus Walleij * established "cs-gpios" for chip selects but instead rely on 7571b8f600SLinus Walleij * "gpios" for the chip select lines. If we detect this, we redirect 7671b8f600SLinus Walleij * the counting of "cs-gpios" to count "gpios" transparent to the 7771b8f600SLinus Walleij * driver. 7871b8f600SLinus Walleij */ 79a1f4c96bSYueHaibing static int of_gpio_spi_cs_get_count(struct device *dev, const char *con_id) 8071b8f600SLinus Walleij { 8171b8f600SLinus Walleij struct device_node *np = dev->of_node; 8271b8f600SLinus Walleij 8371b8f600SLinus Walleij if (!IS_ENABLED(CONFIG_SPI_MASTER)) 8471b8f600SLinus Walleij return 0; 8571b8f600SLinus Walleij if (!con_id || strcmp(con_id, "cs")) 8671b8f600SLinus Walleij return 0; 8771b8f600SLinus Walleij if (!of_device_is_compatible(np, "fsl,spi") && 8847267732SLinus Walleij !of_device_is_compatible(np, "aeroflexgaisler,spictrl") && 8947267732SLinus Walleij !of_device_is_compatible(np, "ibm,ppc4xx-spi")) 9071b8f600SLinus Walleij return 0; 9171b8f600SLinus Walleij return of_gpio_named_count(np, "gpios"); 9271b8f600SLinus Walleij } 9371b8f600SLinus Walleij 94f626d6dfSLinus Walleij int of_gpio_get_count(struct device *dev, const char *con_id) 95f626d6dfSLinus Walleij { 96f626d6dfSLinus Walleij int ret; 97f626d6dfSLinus Walleij char propname[32]; 98f626d6dfSLinus Walleij unsigned int i; 99f626d6dfSLinus Walleij 10071b8f600SLinus Walleij ret = of_gpio_spi_cs_get_count(dev, con_id); 10171b8f600SLinus Walleij if (ret > 0) 10271b8f600SLinus Walleij return ret; 10371b8f600SLinus Walleij 104f626d6dfSLinus Walleij for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) { 105f626d6dfSLinus Walleij if (con_id) 106f626d6dfSLinus Walleij snprintf(propname, sizeof(propname), "%s-%s", 107f626d6dfSLinus Walleij con_id, gpio_suffixes[i]); 108f626d6dfSLinus Walleij else 109f626d6dfSLinus Walleij snprintf(propname, sizeof(propname), "%s", 110f626d6dfSLinus Walleij gpio_suffixes[i]); 111f626d6dfSLinus Walleij 112f626d6dfSLinus Walleij ret = of_gpio_named_count(dev->of_node, propname); 113f626d6dfSLinus Walleij if (ret > 0) 114f626d6dfSLinus Walleij break; 115f626d6dfSLinus Walleij } 116f626d6dfSLinus Walleij return ret ? ret : -ENOENT; 117f626d6dfSLinus Walleij } 118af8b6375SAlexandre Courbot 119c7e9d398SMasahiro Yamada static int of_gpiochip_match_node_and_xlate(struct gpio_chip *chip, void *data) 1203d0f7cf0SGrant Likely { 121c7e9d398SMasahiro Yamada struct of_phandle_args *gpiospec = data; 122c7e9d398SMasahiro Yamada 123d59fdbc7SAndy Shevchenko return device_match_of_node(&chip->gpiodev->dev, gpiospec->np) && 124d49b48f0SVincent Whitchurch chip->of_xlate && 125c7e9d398SMasahiro Yamada chip->of_xlate(chip, gpiospec, NULL) >= 0; 1267b8792bbSHans Holmberg } 1273d0f7cf0SGrant Likely 128c7e9d398SMasahiro Yamada static struct gpio_chip *of_find_gpiochip_by_xlate( 129c7e9d398SMasahiro Yamada struct of_phandle_args *gpiospec) 130762c2e46SMasahiro Yamada { 131c7e9d398SMasahiro Yamada return gpiochip_find(gpiospec, of_gpiochip_match_node_and_xlate); 1323d0f7cf0SGrant Likely } 1333d0f7cf0SGrant Likely 13499468c1aSMasahiro Yamada static struct gpio_desc *of_xlate_and_get_gpiod_flags(struct gpio_chip *chip, 13599468c1aSMasahiro Yamada struct of_phandle_args *gpiospec, 13699468c1aSMasahiro Yamada enum of_gpio_flags *flags) 13799468c1aSMasahiro Yamada { 13899468c1aSMasahiro Yamada int ret; 13999468c1aSMasahiro Yamada 14099468c1aSMasahiro Yamada if (chip->of_gpio_n_cells != gpiospec->args_count) 14199468c1aSMasahiro Yamada return ERR_PTR(-EINVAL); 14299468c1aSMasahiro Yamada 14399468c1aSMasahiro Yamada ret = chip->of_xlate(chip, gpiospec, flags); 14499468c1aSMasahiro Yamada if (ret < 0) 14599468c1aSMasahiro Yamada return ERR_PTR(ret); 14699468c1aSMasahiro Yamada 14799468c1aSMasahiro Yamada return gpiochip_get_desc(chip, ret); 148f141ed65SGrant Likely } 149f141ed65SGrant Likely 150e3186e36SDmitry Torokhov /* 151e3186e36SDmitry Torokhov * Overrides stated polarity of a gpio line and warns when there is a 152e3186e36SDmitry Torokhov * discrepancy. 153e3186e36SDmitry Torokhov */ 154e3186e36SDmitry Torokhov static void of_gpio_quirk_polarity(const struct device_node *np, 155e3186e36SDmitry Torokhov bool active_high, 156e3186e36SDmitry Torokhov enum of_gpio_flags *flags) 157e3186e36SDmitry Torokhov { 158e3186e36SDmitry Torokhov if (active_high) { 159e3186e36SDmitry Torokhov if (*flags & OF_GPIO_ACTIVE_LOW) { 160e3186e36SDmitry Torokhov pr_warn("%s GPIO handle specifies active low - ignored\n", 161e3186e36SDmitry Torokhov of_node_full_name(np)); 162e3186e36SDmitry Torokhov *flags &= ~OF_GPIO_ACTIVE_LOW; 163e3186e36SDmitry Torokhov } 164e3186e36SDmitry Torokhov } else { 165e3186e36SDmitry Torokhov if (!(*flags & OF_GPIO_ACTIVE_LOW)) 166e3186e36SDmitry Torokhov pr_info("%s enforce active low on GPIO handle\n", 167e3186e36SDmitry Torokhov of_node_full_name(np)); 168e3186e36SDmitry Torokhov *flags |= OF_GPIO_ACTIVE_LOW; 169e3186e36SDmitry Torokhov } 170e3186e36SDmitry Torokhov } 171e3186e36SDmitry Torokhov 17299d18d42SDmitry Torokhov /* 17399d18d42SDmitry Torokhov * This quirk does static polarity overrides in cases where existing 17499d18d42SDmitry Torokhov * DTS specified incorrect polarity. 17599d18d42SDmitry Torokhov */ 17699d18d42SDmitry Torokhov static void of_gpio_try_fixup_polarity(const struct device_node *np, 17799d18d42SDmitry Torokhov const char *propname, 17899d18d42SDmitry Torokhov enum of_gpio_flags *flags) 17999d18d42SDmitry Torokhov { 18099d18d42SDmitry Torokhov static const struct { 18199d18d42SDmitry Torokhov const char *compatible; 18299d18d42SDmitry Torokhov const char *propname; 18399d18d42SDmitry Torokhov bool active_high; 18499d18d42SDmitry Torokhov } gpios[] = { 18599d18d42SDmitry Torokhov #if !IS_ENABLED(CONFIG_LCD_HX8357) 18699d18d42SDmitry Torokhov /* 18799d18d42SDmitry Torokhov * Himax LCD controllers used incorrectly named 18899d18d42SDmitry Torokhov * "gpios-reset" property and also specified wrong 18999d18d42SDmitry Torokhov * polarity. 19099d18d42SDmitry Torokhov */ 19199d18d42SDmitry Torokhov { "himax,hx8357", "gpios-reset", false }, 19299d18d42SDmitry Torokhov { "himax,hx8369", "gpios-reset", false }, 19399d18d42SDmitry Torokhov #endif 19499d18d42SDmitry Torokhov }; 19599d18d42SDmitry Torokhov unsigned int i; 19699d18d42SDmitry Torokhov 19799d18d42SDmitry Torokhov for (i = 0; i < ARRAY_SIZE(gpios); i++) { 19899d18d42SDmitry Torokhov if (of_device_is_compatible(np, gpios[i].compatible) && 19999d18d42SDmitry Torokhov !strcmp(propname, gpios[i].propname)) { 20099d18d42SDmitry Torokhov of_gpio_quirk_polarity(np, gpios[i].active_high, flags); 20199d18d42SDmitry Torokhov break; 20299d18d42SDmitry Torokhov } 20399d18d42SDmitry Torokhov } 20499d18d42SDmitry Torokhov } 20599d18d42SDmitry Torokhov 20634cb9352SDmitry Torokhov static void of_gpio_set_polarity_by_property(const struct device_node *np, 20789a5e15bSLinus Walleij const char *propname, 20834cb9352SDmitry Torokhov enum of_gpio_flags *flags) 209a603a2b8SLinus Walleij { 21034cb9352SDmitry Torokhov static const struct { 21134cb9352SDmitry Torokhov const char *compatible; 21234cb9352SDmitry Torokhov const char *gpio_propname; 21334cb9352SDmitry Torokhov const char *polarity_propname; 21434cb9352SDmitry Torokhov } gpios[] = { 21534cb9352SDmitry Torokhov #if IS_ENABLED(CONFIG_FEC) 21634cb9352SDmitry Torokhov /* Freescale Fast Ethernet Controller */ 21734cb9352SDmitry Torokhov { "fsl,imx25-fec", "phy-reset-gpios", "phy-reset-active-high" }, 21834cb9352SDmitry Torokhov { "fsl,imx27-fec", "phy-reset-gpios", "phy-reset-active-high" }, 21934cb9352SDmitry Torokhov { "fsl,imx28-fec", "phy-reset-gpios", "phy-reset-active-high" }, 22034cb9352SDmitry Torokhov { "fsl,imx6q-fec", "phy-reset-gpios", "phy-reset-active-high" }, 22134cb9352SDmitry Torokhov { "fsl,mvf600-fec", "phy-reset-gpios", "phy-reset-active-high" }, 22234cb9352SDmitry Torokhov { "fsl,imx6sx-fec", "phy-reset-gpios", "phy-reset-active-high" }, 22334cb9352SDmitry Torokhov { "fsl,imx6ul-fec", "phy-reset-gpios", "phy-reset-active-high" }, 22434cb9352SDmitry Torokhov { "fsl,imx8mq-fec", "phy-reset-gpios", "phy-reset-active-high" }, 22534cb9352SDmitry Torokhov { "fsl,imx8qm-fec", "phy-reset-gpios", "phy-reset-active-high" }, 22634cb9352SDmitry Torokhov { "fsl,s32v234-fec", "phy-reset-gpios", "phy-reset-active-high" }, 22734cb9352SDmitry Torokhov #endif 228b8b80348SDmitry Torokhov #if IS_ENABLED(CONFIG_PCI_IMX6) 229b8b80348SDmitry Torokhov { "fsl,imx6q-pcie", "reset-gpio", "reset-gpio-active-high" }, 230b8b80348SDmitry Torokhov { "fsl,imx6sx-pcie", "reset-gpio", "reset-gpio-active-high" }, 231b8b80348SDmitry Torokhov { "fsl,imx6qp-pcie", "reset-gpio", "reset-gpio-active-high" }, 232b8b80348SDmitry Torokhov { "fsl,imx7d-pcie", "reset-gpio", "reset-gpio-active-high" }, 233b8b80348SDmitry Torokhov { "fsl,imx8mq-pcie", "reset-gpio", "reset-gpio-active-high" }, 234b8b80348SDmitry Torokhov { "fsl,imx8mm-pcie", "reset-gpio", "reset-gpio-active-high" }, 235b8b80348SDmitry Torokhov { "fsl,imx8mp-pcie", "reset-gpio", "reset-gpio-active-high" }, 236b8b80348SDmitry Torokhov #endif 23799d18d42SDmitry Torokhov 238a603a2b8SLinus Walleij /* 239a603a2b8SLinus Walleij * The regulator GPIO handles are specified such that the 240a603a2b8SLinus Walleij * presence or absence of "enable-active-high" solely controls 241a603a2b8SLinus Walleij * the polarity of the GPIO line. Any phandle flags must 242a603a2b8SLinus Walleij * be actively ignored. 243a603a2b8SLinus Walleij */ 24434cb9352SDmitry Torokhov #if IS_ENABLED(CONFIG_REGULATOR_FIXED_VOLTAGE) 24534cb9352SDmitry Torokhov { "regulator-fixed", "gpios", "enable-active-high" }, 24634cb9352SDmitry Torokhov { "regulator-fixed", "gpio", "enable-active-high" }, 24734cb9352SDmitry Torokhov { "reg-fixed-voltage", "gpios", "enable-active-high" }, 24834cb9352SDmitry Torokhov { "reg-fixed-voltage", "gpio", "enable-active-high" }, 24934cb9352SDmitry Torokhov #endif 25034cb9352SDmitry Torokhov #if IS_ENABLED(CONFIG_REGULATOR_GPIO) 25134cb9352SDmitry Torokhov { "regulator-gpio", "enable-gpio", "enable-active-high" }, 25234cb9352SDmitry Torokhov { "regulator-gpio", "enable-gpios", "enable-active-high" }, 25334cb9352SDmitry Torokhov #endif 25434cb9352SDmitry Torokhov }; 25534cb9352SDmitry Torokhov unsigned int i; 25634cb9352SDmitry Torokhov bool active_high; 25734cb9352SDmitry Torokhov 25834cb9352SDmitry Torokhov for (i = 0; i < ARRAY_SIZE(gpios); i++) { 25934cb9352SDmitry Torokhov if (of_device_is_compatible(np, gpios[i].compatible) && 26034cb9352SDmitry Torokhov !strcmp(propname, gpios[i].gpio_propname)) { 26134cb9352SDmitry Torokhov active_high = of_property_read_bool(np, 26234cb9352SDmitry Torokhov gpios[i].polarity_propname); 263e3186e36SDmitry Torokhov of_gpio_quirk_polarity(np, active_high, flags); 26434cb9352SDmitry Torokhov break; 265a603a2b8SLinus Walleij } 26634cb9352SDmitry Torokhov } 26734cb9352SDmitry Torokhov } 26834cb9352SDmitry Torokhov 26934cb9352SDmitry Torokhov static void of_gpio_flags_quirks(const struct device_node *np, 27034cb9352SDmitry Torokhov const char *propname, 27134cb9352SDmitry Torokhov enum of_gpio_flags *flags, 27234cb9352SDmitry Torokhov int index) 27334cb9352SDmitry Torokhov { 27434cb9352SDmitry Torokhov of_gpio_try_fixup_polarity(np, propname, flags); 27534cb9352SDmitry Torokhov of_gpio_set_polarity_by_property(np, propname, flags); 27634cb9352SDmitry Torokhov 277a603a2b8SLinus Walleij /* 278a603a2b8SLinus Walleij * Legacy open drain handling for fixed voltage regulators. 279a603a2b8SLinus Walleij */ 280a603a2b8SLinus Walleij if (IS_ENABLED(CONFIG_REGULATOR) && 281a603a2b8SLinus Walleij of_device_is_compatible(np, "reg-fixed-voltage") && 282a603a2b8SLinus Walleij of_property_read_bool(np, "gpio-open-drain")) { 283a603a2b8SLinus Walleij *flags |= (OF_GPIO_SINGLE_ENDED | OF_GPIO_OPEN_DRAIN); 284a603a2b8SLinus Walleij pr_info("%s uses legacy open drain flag - update the DTS if you can\n", 285a603a2b8SLinus Walleij of_node_full_name(np)); 286a603a2b8SLinus Walleij } 2876953c57aSLinus Walleij 2886953c57aSLinus Walleij /* 2896953c57aSLinus Walleij * Legacy handling of SPI active high chip select. If we have a 2906953c57aSLinus Walleij * property named "cs-gpios" we need to inspect the child node 2916953c57aSLinus Walleij * to determine if the flags should have inverted semantics. 2926953c57aSLinus Walleij */ 293da7f1349SLinus Walleij if (IS_ENABLED(CONFIG_SPI_MASTER) && !strcmp(propname, "cs-gpios") && 294a71a81e7SGeert Uytterhoeven of_property_read_bool(np, "cs-gpios")) { 2956953c57aSLinus Walleij struct device_node *child; 2966953c57aSLinus Walleij u32 cs; 2976953c57aSLinus Walleij int ret; 2986953c57aSLinus Walleij 2996953c57aSLinus Walleij for_each_child_of_node(np, child) { 3006953c57aSLinus Walleij ret = of_property_read_u32(child, "reg", &cs); 301c1c04ceaSLinus Walleij if (ret) 3026953c57aSLinus Walleij continue; 3036953c57aSLinus Walleij if (cs == index) { 3046953c57aSLinus Walleij /* 3056953c57aSLinus Walleij * SPI children have active low chip selects 3066953c57aSLinus Walleij * by default. This can be specified negatively 3076953c57aSLinus Walleij * by just omitting "spi-cs-high" in the 3086953c57aSLinus Walleij * device node, or actively by tagging on 3096953c57aSLinus Walleij * GPIO_ACTIVE_LOW as flag in the device 3106953c57aSLinus Walleij * tree. If the line is simultaneously 3116953c57aSLinus Walleij * tagged as active low in the device tree 3126953c57aSLinus Walleij * and has the "spi-cs-high" set, we get a 3136953c57aSLinus Walleij * conflict and the "spi-cs-high" flag will 3146953c57aSLinus Walleij * take precedence. 3156953c57aSLinus Walleij */ 316e3186e36SDmitry Torokhov bool active_high = of_property_read_bool(child, 317e3186e36SDmitry Torokhov "spi-cs-high"); 318e3186e36SDmitry Torokhov of_gpio_quirk_polarity(child, active_high, 319e3186e36SDmitry Torokhov flags); 32089fea04cSNishka Dasgupta of_node_put(child); 3216953c57aSLinus Walleij break; 3226953c57aSLinus Walleij } 3236953c57aSLinus Walleij } 3246953c57aSLinus Walleij } 325edc1ef3fSMartin Blumenstingl 326edc1ef3fSMartin Blumenstingl /* Legacy handling of stmmac's active-low PHY reset line */ 327edc1ef3fSMartin Blumenstingl if (IS_ENABLED(CONFIG_STMMAC_ETH) && 328edc1ef3fSMartin Blumenstingl !strcmp(propname, "snps,reset-gpio") && 329edc1ef3fSMartin Blumenstingl of_property_read_bool(np, "snps,reset-active-low")) 330edc1ef3fSMartin Blumenstingl *flags |= OF_GPIO_ACTIVE_LOW; 331a603a2b8SLinus Walleij } 332a603a2b8SLinus Walleij 333f141ed65SGrant Likely /** 334af8b6375SAlexandre Courbot * of_get_named_gpiod_flags() - Get a GPIO descriptor and flags for GPIO API 335f141ed65SGrant Likely * @np: device node to get GPIO from 336f141ed65SGrant Likely * @propname: property name containing gpio specifier(s) 337f141ed65SGrant Likely * @index: index of the GPIO 338f141ed65SGrant Likely * @flags: a flags pointer to fill in 339f141ed65SGrant Likely * 340af8b6375SAlexandre Courbot * Returns GPIO descriptor to use with Linux GPIO API, or one of the errno 341f141ed65SGrant Likely * value on the error condition. If @flags is not NULL the function also fills 342f141ed65SGrant Likely * in flags for the GPIO. 343f141ed65SGrant Likely */ 344e6ae9a83SKrzysztof Kozlowski static struct gpio_desc *of_get_named_gpiod_flags(const struct device_node *np, 345af8b6375SAlexandre Courbot const char *propname, int index, enum of_gpio_flags *flags) 346f141ed65SGrant Likely { 347762c2e46SMasahiro Yamada struct of_phandle_args gpiospec; 348762c2e46SMasahiro Yamada struct gpio_chip *chip; 349762c2e46SMasahiro Yamada struct gpio_desc *desc; 350f141ed65SGrant Likely int ret; 351f141ed65SGrant Likely 352c11e6f0fSStephen Boyd ret = of_parse_phandle_with_args_map(np, propname, "gpio", index, 353762c2e46SMasahiro Yamada &gpiospec); 3543d0f7cf0SGrant Likely if (ret) { 3557eb6ce2fSRob Herring pr_debug("%s: can't parse '%s' property of node '%pOF[%d]'\n", 3567eb6ce2fSRob Herring __func__, propname, np, index); 357af8b6375SAlexandre Courbot return ERR_PTR(ret); 3583d0f7cf0SGrant Likely } 359f141ed65SGrant Likely 360c7e9d398SMasahiro Yamada chip = of_find_gpiochip_by_xlate(&gpiospec); 361762c2e46SMasahiro Yamada if (!chip) { 362762c2e46SMasahiro Yamada desc = ERR_PTR(-EPROBE_DEFER); 363762c2e46SMasahiro Yamada goto out; 364762c2e46SMasahiro Yamada } 3653d0f7cf0SGrant Likely 36699468c1aSMasahiro Yamada desc = of_xlate_and_get_gpiod_flags(chip, &gpiospec, flags); 367762c2e46SMasahiro Yamada if (IS_ERR(desc)) 368762c2e46SMasahiro Yamada goto out; 369762c2e46SMasahiro Yamada 370605f2d34SLinus Walleij if (flags) 37189a5e15bSLinus Walleij of_gpio_flags_quirks(np, propname, flags, index); 372a603a2b8SLinus Walleij 3737eb6ce2fSRob Herring pr_debug("%s: parsed '%s' property of node '%pOF[%d]' - status (%d)\n", 3747eb6ce2fSRob Herring __func__, propname, np, index, 375762c2e46SMasahiro Yamada PTR_ERR_OR_ZERO(desc)); 376762c2e46SMasahiro Yamada 377762c2e46SMasahiro Yamada out: 378762c2e46SMasahiro Yamada of_node_put(gpiospec.np); 379762c2e46SMasahiro Yamada 380762c2e46SMasahiro Yamada return desc; 381f141ed65SGrant Likely } 382f141ed65SGrant Likely 38340fc56eeSDmitry Torokhov /** 38440fc56eeSDmitry Torokhov * of_get_named_gpio() - Get a GPIO number to use with GPIO API 38540fc56eeSDmitry Torokhov * @np: device node to get GPIO from 38640fc56eeSDmitry Torokhov * @propname: Name of property containing gpio specifier(s) 38740fc56eeSDmitry Torokhov * @index: index of the GPIO 38840fc56eeSDmitry Torokhov * 38940fc56eeSDmitry Torokhov * Returns GPIO number to use with Linux generic GPIO API, or one of the errno 39040fc56eeSDmitry Torokhov * value on the error condition. 39140fc56eeSDmitry Torokhov */ 39240fc56eeSDmitry Torokhov int of_get_named_gpio(const struct device_node *np, const char *propname, 39340fc56eeSDmitry Torokhov int index) 394f01d9075SAlexandre Courbot { 395f01d9075SAlexandre Courbot struct gpio_desc *desc; 396f01d9075SAlexandre Courbot 39740fc56eeSDmitry Torokhov desc = of_get_named_gpiod_flags(np, propname, index, NULL); 398f01d9075SAlexandre Courbot 399f01d9075SAlexandre Courbot if (IS_ERR(desc)) 400f01d9075SAlexandre Courbot return PTR_ERR(desc); 401f01d9075SAlexandre Courbot else 402f01d9075SAlexandre Courbot return desc_to_gpio(desc); 403f01d9075SAlexandre Courbot } 40440fc56eeSDmitry Torokhov EXPORT_SYMBOL_GPL(of_get_named_gpio); 405f01d9075SAlexandre Courbot 406d9e7f0e3SDmitry Torokhov /* Converts gpio_lookup_flags into bitmask of GPIO_* values */ 407d9e7f0e3SDmitry Torokhov static unsigned long of_convert_gpio_flags(enum of_gpio_flags flags) 408d9e7f0e3SDmitry Torokhov { 409d9e7f0e3SDmitry Torokhov unsigned long lflags = GPIO_LOOKUP_FLAGS_DEFAULT; 410d9e7f0e3SDmitry Torokhov 411d9e7f0e3SDmitry Torokhov if (flags & OF_GPIO_ACTIVE_LOW) 412d9e7f0e3SDmitry Torokhov lflags |= GPIO_ACTIVE_LOW; 413d9e7f0e3SDmitry Torokhov 414d9e7f0e3SDmitry Torokhov if (flags & OF_GPIO_SINGLE_ENDED) { 415d9e7f0e3SDmitry Torokhov if (flags & OF_GPIO_OPEN_DRAIN) 416d9e7f0e3SDmitry Torokhov lflags |= GPIO_OPEN_DRAIN; 417d9e7f0e3SDmitry Torokhov else 418d9e7f0e3SDmitry Torokhov lflags |= GPIO_OPEN_SOURCE; 419d9e7f0e3SDmitry Torokhov } 420d9e7f0e3SDmitry Torokhov 421d9e7f0e3SDmitry Torokhov if (flags & OF_GPIO_TRANSITORY) 422d9e7f0e3SDmitry Torokhov lflags |= GPIO_TRANSITORY; 423d9e7f0e3SDmitry Torokhov 424d9e7f0e3SDmitry Torokhov if (flags & OF_GPIO_PULL_UP) 425d9e7f0e3SDmitry Torokhov lflags |= GPIO_PULL_UP; 426d9e7f0e3SDmitry Torokhov 427d9e7f0e3SDmitry Torokhov if (flags & OF_GPIO_PULL_DOWN) 428d9e7f0e3SDmitry Torokhov lflags |= GPIO_PULL_DOWN; 429d9e7f0e3SDmitry Torokhov 430d9e7f0e3SDmitry Torokhov if (flags & OF_GPIO_PULL_DISABLE) 431d9e7f0e3SDmitry Torokhov lflags |= GPIO_PULL_DISABLE; 432d9e7f0e3SDmitry Torokhov 433d9e7f0e3SDmitry Torokhov return lflags; 434d9e7f0e3SDmitry Torokhov } 435d9e7f0e3SDmitry Torokhov 436b311c5cbSDmitry Torokhov static struct gpio_desc *of_find_gpio_rename(struct device_node *np, 43798c3c940SDmitry Torokhov const char *con_id, 43898c3c940SDmitry Torokhov unsigned int idx, 439c8582339SLinus Walleij enum of_gpio_flags *of_flags) 440c8582339SLinus Walleij { 441b311c5cbSDmitry Torokhov static const struct of_rename_gpio { 442b311c5cbSDmitry Torokhov const char *con_id; 443b311c5cbSDmitry Torokhov const char *legacy_id; /* NULL - same as con_id */ 444b311c5cbSDmitry Torokhov /* 445b311c5cbSDmitry Torokhov * Compatible string can be set to NULL in case where 446b311c5cbSDmitry Torokhov * matching to a particular compatible is not practical, 447b311c5cbSDmitry Torokhov * but it should only be done for gpio names that have 448b311c5cbSDmitry Torokhov * vendor prefix to reduce risk of false positives. 449b311c5cbSDmitry Torokhov * Addition of such entries is strongly discouraged. 450b311c5cbSDmitry Torokhov */ 451b311c5cbSDmitry Torokhov const char *compatible; 452b311c5cbSDmitry Torokhov } gpios[] = { 453fbbbcd17SDmitry Torokhov #if !IS_ENABLED(CONFIG_LCD_HX8357) 454fbbbcd17SDmitry Torokhov /* Himax LCD controllers used "gpios-reset" */ 455fbbbcd17SDmitry Torokhov { "reset", "gpios-reset", "himax,hx8357" }, 456fbbbcd17SDmitry Torokhov { "reset", "gpios-reset", "himax,hx8369" }, 457fbbbcd17SDmitry Torokhov #endif 458b311c5cbSDmitry Torokhov #if IS_ENABLED(CONFIG_MFD_ARIZONA) 459b311c5cbSDmitry Torokhov { "wlf,reset", NULL, NULL }, 460b311c5cbSDmitry Torokhov #endif 461eaf1a296SDmitry Torokhov #if IS_ENABLED(CONFIG_RTC_DRV_MOXART) 462eaf1a296SDmitry Torokhov { "rtc-data", "gpio-rtc-data", "moxa,moxart-rtc" }, 463eaf1a296SDmitry Torokhov { "rtc-sclk", "gpio-rtc-sclk", "moxa,moxart-rtc" }, 464eaf1a296SDmitry Torokhov { "rtc-reset", "gpio-rtc-reset", "moxa,moxart-rtc" }, 465eaf1a296SDmitry Torokhov #endif 4669c2cc717SDmitry Torokhov #if IS_ENABLED(CONFIG_NFC_MRVL_I2C) 4679c2cc717SDmitry Torokhov { "reset", "reset-n-io", "marvell,nfc-i2c" }, 4689c2cc717SDmitry Torokhov #endif 4699c2cc717SDmitry Torokhov #if IS_ENABLED(CONFIG_NFC_MRVL_SPI) 4709c2cc717SDmitry Torokhov { "reset", "reset-n-io", "marvell,nfc-spi" }, 4719c2cc717SDmitry Torokhov #endif 4729c2cc717SDmitry Torokhov #if IS_ENABLED(CONFIG_NFC_MRVL_UART) 4739c2cc717SDmitry Torokhov { "reset", "reset-n-io", "marvell,nfc-uart" }, 4749c2cc717SDmitry Torokhov { "reset", "reset-n-io", "mrvl,nfc-uart" }, 4759c2cc717SDmitry Torokhov #endif 476fbbbcd17SDmitry Torokhov #if !IS_ENABLED(CONFIG_PCI_LANTIQ) 477fbbbcd17SDmitry Torokhov /* MIPS Lantiq PCI */ 478fbbbcd17SDmitry Torokhov { "reset", "gpios-reset", "lantiq,pci-xway" }, 479fbbbcd17SDmitry Torokhov #endif 480307c593bSDmitry Torokhov 481b311c5cbSDmitry Torokhov /* 482b311c5cbSDmitry Torokhov * Some regulator bindings happened before we managed to 483b311c5cbSDmitry Torokhov * establish that GPIO properties should be named 484b311c5cbSDmitry Torokhov * "foo-gpios" so we have this special kludge for them. 485b311c5cbSDmitry Torokhov */ 486307c593bSDmitry Torokhov #if IS_ENABLED(CONFIG_REGULATOR_ARIZONA_LDO1) 487b311c5cbSDmitry Torokhov { "wlf,ldoena", NULL, NULL }, /* Arizona */ 488307c593bSDmitry Torokhov #endif 489307c593bSDmitry Torokhov #if IS_ENABLED(CONFIG_REGULATOR_WM8994) 490b311c5cbSDmitry Torokhov { "wlf,ldo1ena", NULL, NULL }, /* WM8994 */ 491b311c5cbSDmitry Torokhov { "wlf,ldo2ena", NULL, NULL }, /* WM8994 */ 492b311c5cbSDmitry Torokhov #endif 493c8582339SLinus Walleij 494944004ebSDmitry Torokhov #if IS_ENABLED(CONFIG_SND_SOC_CS42L56) 495944004ebSDmitry Torokhov { "reset", "cirrus,gpio-nreset", "cirrus,cs42l56" }, 496944004ebSDmitry Torokhov #endif 497fbbbcd17SDmitry Torokhov #if IS_ENABLED(CONFIG_SND_SOC_TLV320AIC3X) 498fbbbcd17SDmitry Torokhov { "reset", "gpio-reset", "ti,tlv320aic3x" }, 499fbbbcd17SDmitry Torokhov { "reset", "gpio-reset", "ti,tlv320aic33" }, 500fbbbcd17SDmitry Torokhov { "reset", "gpio-reset", "ti,tlv320aic3007" }, 501fbbbcd17SDmitry Torokhov { "reset", "gpio-reset", "ti,tlv320aic3104" }, 502fbbbcd17SDmitry Torokhov { "reset", "gpio-reset", "ti,tlv320aic3106" }, 503fbbbcd17SDmitry Torokhov #endif 504307c593bSDmitry Torokhov #if IS_ENABLED(CONFIG_SPI_GPIO) 505c8582339SLinus Walleij /* 506b311c5cbSDmitry Torokhov * The SPI GPIO bindings happened before we managed to 507b311c5cbSDmitry Torokhov * establish that GPIO properties should be named 508b311c5cbSDmitry Torokhov * "foo-gpios" so we have this special kludge for them. 509c8582339SLinus Walleij */ 510b311c5cbSDmitry Torokhov { "miso", "gpio-miso", "spi-gpio" }, 511b311c5cbSDmitry Torokhov { "mosi", "gpio-mosi", "spi-gpio" }, 512b311c5cbSDmitry Torokhov { "sck", "gpio-sck", "spi-gpio" }, 513307c593bSDmitry Torokhov #endif 514c8582339SLinus Walleij 5156a537d48SLinus Walleij /* 516b311c5cbSDmitry Torokhov * The old Freescale bindings use simply "gpios" as name 517b311c5cbSDmitry Torokhov * for the chip select lines rather than "cs-gpios" like 518b311c5cbSDmitry Torokhov * all other SPI hardware. Allow this specifically for 519b311c5cbSDmitry Torokhov * Freescale and PPC devices. 520e3023bf8SLinus Walleij */ 521307c593bSDmitry Torokhov #if IS_ENABLED(CONFIG_SPI_FSL_SPI) 522b311c5cbSDmitry Torokhov { "cs", "gpios", "fsl,spi" }, 523b311c5cbSDmitry Torokhov { "cs", "gpios", "aeroflexgaisler,spictrl" }, 524307c593bSDmitry Torokhov #endif 525307c593bSDmitry Torokhov #if IS_ENABLED(CONFIG_SPI_PPC4xx) 526b311c5cbSDmitry Torokhov { "cs", "gpios", "ibm,ppc4xx-spi" }, 527b311c5cbSDmitry Torokhov #endif 528307c593bSDmitry Torokhov 529b311c5cbSDmitry Torokhov #if IS_ENABLED(CONFIG_TYPEC_FUSB302) 530e3023bf8SLinus Walleij /* 531b311c5cbSDmitry Torokhov * Fairchild FUSB302 host is using undocumented "fcs,int_n" 532b311c5cbSDmitry Torokhov * property without the compulsory "-gpios" suffix. 533e3023bf8SLinus Walleij */ 534b311c5cbSDmitry Torokhov { "fcs,int_n", NULL, "fcs,fusb302" }, 535b311c5cbSDmitry Torokhov #endif 5366a537d48SLinus Walleij }; 537b311c5cbSDmitry Torokhov struct gpio_desc *desc; 538b311c5cbSDmitry Torokhov const char *legacy_id; 539b311c5cbSDmitry Torokhov unsigned int i; 5406a537d48SLinus Walleij 5416a537d48SLinus Walleij if (!con_id) 5426a537d48SLinus Walleij return ERR_PTR(-ENOENT); 5436a537d48SLinus Walleij 544b311c5cbSDmitry Torokhov for (i = 0; i < ARRAY_SIZE(gpios); i++) { 545b311c5cbSDmitry Torokhov if (strcmp(con_id, gpios[i].con_id)) 546b311c5cbSDmitry Torokhov continue; 5476a537d48SLinus Walleij 548b311c5cbSDmitry Torokhov if (gpios[i].compatible && 549b311c5cbSDmitry Torokhov !of_device_is_compatible(np, gpios[i].compatible)) 550b311c5cbSDmitry Torokhov continue; 551b311c5cbSDmitry Torokhov 552b311c5cbSDmitry Torokhov legacy_id = gpios[i].legacy_id ?: gpios[i].con_id; 553b311c5cbSDmitry Torokhov desc = of_get_named_gpiod_flags(np, legacy_id, idx, of_flags); 554b311c5cbSDmitry Torokhov if (!gpiod_not_found(desc)) { 555b311c5cbSDmitry Torokhov pr_info("%s uses legacy gpio name '%s' instead of '%s-gpios'\n", 556b311c5cbSDmitry Torokhov of_node_full_name(np), legacy_id, con_id); 557b311c5cbSDmitry Torokhov return desc; 558b311c5cbSDmitry Torokhov } 5596a537d48SLinus Walleij } 5606a537d48SLinus Walleij 56111c43bb0SDmitry Torokhov return ERR_PTR(-ENOENT); 5626e24826dSLinus Walleij } 5636e24826dSLinus Walleij 564326c3753SDmitry Torokhov static struct gpio_desc *of_find_mt2701_gpio(struct device_node *np, 565326c3753SDmitry Torokhov const char *con_id, 566326c3753SDmitry Torokhov unsigned int idx, 567326c3753SDmitry Torokhov enum of_gpio_flags *of_flags) 568326c3753SDmitry Torokhov { 569326c3753SDmitry Torokhov struct gpio_desc *desc; 570326c3753SDmitry Torokhov const char *legacy_id; 571326c3753SDmitry Torokhov 572326c3753SDmitry Torokhov if (!IS_ENABLED(CONFIG_SND_SOC_MT2701_CS42448)) 573326c3753SDmitry Torokhov return ERR_PTR(-ENOENT); 574326c3753SDmitry Torokhov 575326c3753SDmitry Torokhov if (!of_device_is_compatible(np, "mediatek,mt2701-cs42448-machine")) 576326c3753SDmitry Torokhov return ERR_PTR(-ENOENT); 577326c3753SDmitry Torokhov 578326c3753SDmitry Torokhov if (!con_id || strcmp(con_id, "i2s1-in-sel")) 579326c3753SDmitry Torokhov return ERR_PTR(-ENOENT); 580326c3753SDmitry Torokhov 581326c3753SDmitry Torokhov if (idx == 0) 582326c3753SDmitry Torokhov legacy_id = "i2s1-in-sel-gpio1"; 583326c3753SDmitry Torokhov else if (idx == 1) 584326c3753SDmitry Torokhov legacy_id = "i2s1-in-sel-gpio2"; 585326c3753SDmitry Torokhov else 586326c3753SDmitry Torokhov return ERR_PTR(-ENOENT); 587326c3753SDmitry Torokhov 588326c3753SDmitry Torokhov desc = of_get_named_gpiod_flags(np, legacy_id, 0, of_flags); 589326c3753SDmitry Torokhov if (!gpiod_not_found(desc)) 590326c3753SDmitry Torokhov pr_info("%s is using legacy gpio name '%s' instead of '%s-gpios'\n", 591326c3753SDmitry Torokhov of_node_full_name(np), legacy_id, con_id); 592326c3753SDmitry Torokhov 593326c3753SDmitry Torokhov return desc; 594326c3753SDmitry Torokhov } 595326c3753SDmitry Torokhov 596a2b5e207SDmitry Torokhov typedef struct gpio_desc *(*of_find_gpio_quirk)(struct device_node *np, 597a2b5e207SDmitry Torokhov const char *con_id, 598a2b5e207SDmitry Torokhov unsigned int idx, 599a2b5e207SDmitry Torokhov enum of_gpio_flags *of_flags); 600a2b5e207SDmitry Torokhov static const of_find_gpio_quirk of_find_gpio_quirks[] = { 601b311c5cbSDmitry Torokhov of_find_gpio_rename, 602326c3753SDmitry Torokhov of_find_mt2701_gpio, 6038b10ca2fSMichael Walle NULL 604a2b5e207SDmitry Torokhov }; 605a2b5e207SDmitry Torokhov 60607445ae1SDmitry Torokhov struct gpio_desc *of_find_gpio(struct device_node *np, const char *con_id, 607fed7026aSAndy Shevchenko unsigned int idx, unsigned long *flags) 608ea713bc4SLinus Walleij { 609ea713bc4SLinus Walleij char prop_name[32]; /* 32 is max size of property name */ 610ea713bc4SLinus Walleij enum of_gpio_flags of_flags; 611a2b5e207SDmitry Torokhov const of_find_gpio_quirk *q; 612ea713bc4SLinus Walleij struct gpio_desc *desc; 613ea713bc4SLinus Walleij unsigned int i; 614ea713bc4SLinus Walleij 615c8582339SLinus Walleij /* Try GPIO property "foo-gpios" and "foo-gpio" */ 616ea713bc4SLinus Walleij for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) { 617ea713bc4SLinus Walleij if (con_id) 618ea713bc4SLinus Walleij snprintf(prop_name, sizeof(prop_name), "%s-%s", con_id, 619ea713bc4SLinus Walleij gpio_suffixes[i]); 620ea713bc4SLinus Walleij else 621ea713bc4SLinus Walleij snprintf(prop_name, sizeof(prop_name), "%s", 622ea713bc4SLinus Walleij gpio_suffixes[i]); 623ea713bc4SLinus Walleij 62407445ae1SDmitry Torokhov desc = of_get_named_gpiod_flags(np, prop_name, idx, &of_flags); 6256662ae6aSMaxime Ripard 6267b58696dSAndy Shevchenko if (!gpiod_not_found(desc)) 627ea713bc4SLinus Walleij break; 628ea713bc4SLinus Walleij } 629ea713bc4SLinus Walleij 630a2b5e207SDmitry Torokhov /* Properly named GPIO was not found, try workarounds */ 631a2b5e207SDmitry Torokhov for (q = of_find_gpio_quirks; gpiod_not_found(desc) && *q; q++) 63207445ae1SDmitry Torokhov desc = (*q)(np, con_id, idx, &of_flags); 6336e24826dSLinus Walleij 634ea713bc4SLinus Walleij if (IS_ERR(desc)) 635ea713bc4SLinus Walleij return desc; 636ea713bc4SLinus Walleij 637d9e7f0e3SDmitry Torokhov *flags = of_convert_gpio_flags(of_flags); 638d449991cSThomas Petazzoni 639ea713bc4SLinus Walleij return desc; 640ea713bc4SLinus Walleij } 641ea713bc4SLinus Walleij 642f141ed65SGrant Likely /** 643fd7337fdSMarkus Pargmann * of_parse_own_gpio() - Get a GPIO hog descriptor, names and flags for GPIO API 644f625d460SBenoit Parrot * @np: device node to get GPIO from 645be715343SMasahiro Yamada * @chip: GPIO chip whose hog is parsed 646a79fead5SGeert Uytterhoeven * @idx: Index of the GPIO to parse 647f625d460SBenoit Parrot * @name: GPIO line name 648fed7026aSAndy Shevchenko * @lflags: bitmask of gpio_lookup_flags GPIO_* values - returned from 649fed7026aSAndy Shevchenko * of_find_gpio() or of_parse_own_gpio() 650f625d460SBenoit Parrot * @dflags: gpiod_flags - optional GPIO initialization flags 651f625d460SBenoit Parrot * 652f625d460SBenoit Parrot * Returns GPIO descriptor to use with Linux GPIO API, or one of the errno 653f625d460SBenoit Parrot * value on the error condition. 654f625d460SBenoit Parrot */ 655fd7337fdSMarkus Pargmann static struct gpio_desc *of_parse_own_gpio(struct device_node *np, 656be715343SMasahiro Yamada struct gpio_chip *chip, 657a79fead5SGeert Uytterhoeven unsigned int idx, const char **name, 658fed7026aSAndy Shevchenko unsigned long *lflags, 659f625d460SBenoit Parrot enum gpiod_flags *dflags) 660f625d460SBenoit Parrot { 661f625d460SBenoit Parrot struct device_node *chip_np; 662f625d460SBenoit Parrot enum of_gpio_flags xlate_flags; 663be715343SMasahiro Yamada struct of_phandle_args gpiospec; 664be715343SMasahiro Yamada struct gpio_desc *desc; 665a79fead5SGeert Uytterhoeven unsigned int i; 666f625d460SBenoit Parrot u32 tmp; 6673f9547e1SMasahiro Yamada int ret; 668f625d460SBenoit Parrot 66970d0fc42SAndy Shevchenko chip_np = dev_of_node(&chip->gpiodev->dev); 670f625d460SBenoit Parrot if (!chip_np) 671f625d460SBenoit Parrot return ERR_PTR(-EINVAL); 672f625d460SBenoit Parrot 673f625d460SBenoit Parrot xlate_flags = 0; 6742d6c06f5SAndy Shevchenko *lflags = GPIO_LOOKUP_FLAGS_DEFAULT; 67540941954SAndy Shevchenko *dflags = GPIOD_ASIS; 676f625d460SBenoit Parrot 677f625d460SBenoit Parrot ret = of_property_read_u32(chip_np, "#gpio-cells", &tmp); 678f625d460SBenoit Parrot if (ret) 679f625d460SBenoit Parrot return ERR_PTR(ret); 680f625d460SBenoit Parrot 681be715343SMasahiro Yamada gpiospec.np = chip_np; 682be715343SMasahiro Yamada gpiospec.args_count = tmp; 683f625d460SBenoit Parrot 684a79fead5SGeert Uytterhoeven for (i = 0; i < tmp; i++) { 685a79fead5SGeert Uytterhoeven ret = of_property_read_u32_index(np, "gpios", idx * tmp + i, 686a79fead5SGeert Uytterhoeven &gpiospec.args[i]); 687f625d460SBenoit Parrot if (ret) 688f625d460SBenoit Parrot return ERR_PTR(ret); 689a79fead5SGeert Uytterhoeven } 690f625d460SBenoit Parrot 69199468c1aSMasahiro Yamada desc = of_xlate_and_get_gpiod_flags(chip, &gpiospec, &xlate_flags); 692be715343SMasahiro Yamada if (IS_ERR(desc)) 693be715343SMasahiro Yamada return desc; 694f625d460SBenoit Parrot 695d9e7f0e3SDmitry Torokhov *lflags = of_convert_gpio_flags(xlate_flags); 696f625d460SBenoit Parrot 697f625d460SBenoit Parrot if (of_property_read_bool(np, "input")) 698f625d460SBenoit Parrot *dflags |= GPIOD_IN; 699f625d460SBenoit Parrot else if (of_property_read_bool(np, "output-low")) 700f625d460SBenoit Parrot *dflags |= GPIOD_OUT_LOW; 701f625d460SBenoit Parrot else if (of_property_read_bool(np, "output-high")) 702f625d460SBenoit Parrot *dflags |= GPIOD_OUT_HIGH; 703f625d460SBenoit Parrot else { 70462cdcb6cSRob Herring pr_warn("GPIO line %d (%pOFn): no hogging state specified, bailing out\n", 70562cdcb6cSRob Herring desc_to_gpio(desc), np); 706f625d460SBenoit Parrot return ERR_PTR(-EINVAL); 707f625d460SBenoit Parrot } 708f625d460SBenoit Parrot 709f625d460SBenoit Parrot if (name && of_property_read_string(np, "line-name", name)) 710f625d460SBenoit Parrot *name = np->name; 711f625d460SBenoit Parrot 712be715343SMasahiro Yamada return desc; 713f625d460SBenoit Parrot } 714f625d460SBenoit Parrot 715f625d460SBenoit Parrot /** 716bc21077eSGeert Uytterhoeven * of_gpiochip_add_hog - Add all hogs in a hog device node 717bc21077eSGeert Uytterhoeven * @chip: gpio chip to act on 718bc21077eSGeert Uytterhoeven * @hog: device node describing the hogs 719bc21077eSGeert Uytterhoeven * 720bc21077eSGeert Uytterhoeven * Returns error if it fails otherwise 0 on success. 721bc21077eSGeert Uytterhoeven */ 722bc21077eSGeert Uytterhoeven static int of_gpiochip_add_hog(struct gpio_chip *chip, struct device_node *hog) 723bc21077eSGeert Uytterhoeven { 724bc21077eSGeert Uytterhoeven enum gpiod_flags dflags; 725bc21077eSGeert Uytterhoeven struct gpio_desc *desc; 726bc21077eSGeert Uytterhoeven unsigned long lflags; 727bc21077eSGeert Uytterhoeven const char *name; 728bc21077eSGeert Uytterhoeven unsigned int i; 729bc21077eSGeert Uytterhoeven int ret; 730bc21077eSGeert Uytterhoeven 731bc21077eSGeert Uytterhoeven for (i = 0;; i++) { 732bc21077eSGeert Uytterhoeven desc = of_parse_own_gpio(hog, chip, i, &name, &lflags, &dflags); 733bc21077eSGeert Uytterhoeven if (IS_ERR(desc)) 734bc21077eSGeert Uytterhoeven break; 735bc21077eSGeert Uytterhoeven 736bc21077eSGeert Uytterhoeven ret = gpiod_hog(desc, name, lflags, dflags); 737bc21077eSGeert Uytterhoeven if (ret < 0) 738bc21077eSGeert Uytterhoeven return ret; 73963636d95SGeert Uytterhoeven 74063636d95SGeert Uytterhoeven #ifdef CONFIG_OF_DYNAMIC 74163636d95SGeert Uytterhoeven desc->hog = hog; 74263636d95SGeert Uytterhoeven #endif 743bc21077eSGeert Uytterhoeven } 744bc21077eSGeert Uytterhoeven 745bc21077eSGeert Uytterhoeven return 0; 746bc21077eSGeert Uytterhoeven } 747bc21077eSGeert Uytterhoeven 748bc21077eSGeert Uytterhoeven /** 749fd7337fdSMarkus Pargmann * of_gpiochip_scan_gpios - Scan gpio-controller for gpio definitions 750f625d460SBenoit Parrot * @chip: gpio chip to act on 751f625d460SBenoit Parrot * 752f625d460SBenoit Parrot * This is only used by of_gpiochip_add to request/set GPIO initial 753f625d460SBenoit Parrot * configuration. 754ead066e6SGeert Uytterhoeven * It returns error if it fails otherwise 0 on success. 755f625d460SBenoit Parrot */ 756dfbd379bSLaxman Dewangan static int of_gpiochip_scan_gpios(struct gpio_chip *chip) 757f625d460SBenoit Parrot { 758f625d460SBenoit Parrot struct device_node *np; 759dfbd379bSLaxman Dewangan int ret; 760f625d460SBenoit Parrot 76170d0fc42SAndy Shevchenko for_each_available_child_of_node(dev_of_node(&chip->gpiodev->dev), np) { 762f625d460SBenoit Parrot if (!of_property_read_bool(np, "gpio-hog")) 763f625d460SBenoit Parrot continue; 764f625d460SBenoit Parrot 765bc21077eSGeert Uytterhoeven ret = of_gpiochip_add_hog(chip, np); 76609e258afSWei Yongjun if (ret < 0) { 76709e258afSWei Yongjun of_node_put(np); 768dfbd379bSLaxman Dewangan return ret; 769f625d460SBenoit Parrot } 77063636d95SGeert Uytterhoeven 77163636d95SGeert Uytterhoeven of_node_set_flag(np, OF_POPULATED); 77209e258afSWei Yongjun } 773dfbd379bSLaxman Dewangan 774dfbd379bSLaxman Dewangan return 0; 775f625d460SBenoit Parrot } 776f625d460SBenoit Parrot 77763636d95SGeert Uytterhoeven #ifdef CONFIG_OF_DYNAMIC 77863636d95SGeert Uytterhoeven /** 77963636d95SGeert Uytterhoeven * of_gpiochip_remove_hog - Remove all hogs in a hog device node 78063636d95SGeert Uytterhoeven * @chip: gpio chip to act on 78163636d95SGeert Uytterhoeven * @hog: device node describing the hogs 78263636d95SGeert Uytterhoeven */ 78363636d95SGeert Uytterhoeven static void of_gpiochip_remove_hog(struct gpio_chip *chip, 78463636d95SGeert Uytterhoeven struct device_node *hog) 78563636d95SGeert Uytterhoeven { 78680c78fbeSAndy Shevchenko struct gpio_desc *desc; 78763636d95SGeert Uytterhoeven 78857017eddSAndy Shevchenko for_each_gpio_desc_with_flag(chip, desc, FLAG_IS_HOGGED) 78980c78fbeSAndy Shevchenko if (desc->hog == hog) 79080c78fbeSAndy Shevchenko gpiochip_free_own_desc(desc); 79163636d95SGeert Uytterhoeven } 79263636d95SGeert Uytterhoeven 79363636d95SGeert Uytterhoeven static int of_gpiochip_match_node(struct gpio_chip *chip, void *data) 79463636d95SGeert Uytterhoeven { 795597a8a88SAndy Shevchenko return device_match_of_node(&chip->gpiodev->dev, data); 79663636d95SGeert Uytterhoeven } 79763636d95SGeert Uytterhoeven 79863636d95SGeert Uytterhoeven static struct gpio_chip *of_find_gpiochip_by_node(struct device_node *np) 79963636d95SGeert Uytterhoeven { 80063636d95SGeert Uytterhoeven return gpiochip_find(np, of_gpiochip_match_node); 80163636d95SGeert Uytterhoeven } 80263636d95SGeert Uytterhoeven 80363636d95SGeert Uytterhoeven static int of_gpio_notify(struct notifier_block *nb, unsigned long action, 80463636d95SGeert Uytterhoeven void *arg) 80563636d95SGeert Uytterhoeven { 80663636d95SGeert Uytterhoeven struct of_reconfig_data *rd = arg; 80763636d95SGeert Uytterhoeven struct gpio_chip *chip; 80863636d95SGeert Uytterhoeven int ret; 80963636d95SGeert Uytterhoeven 81063636d95SGeert Uytterhoeven /* 81163636d95SGeert Uytterhoeven * This only supports adding and removing complete gpio-hog nodes. 81263636d95SGeert Uytterhoeven * Modifying an existing gpio-hog node is not supported (except for 81363636d95SGeert Uytterhoeven * changing its "status" property, which is treated the same as 81463636d95SGeert Uytterhoeven * addition/removal). 81563636d95SGeert Uytterhoeven */ 81663636d95SGeert Uytterhoeven switch (of_reconfig_get_state_change(action, arg)) { 81763636d95SGeert Uytterhoeven case OF_RECONFIG_CHANGE_ADD: 81863636d95SGeert Uytterhoeven if (!of_property_read_bool(rd->dn, "gpio-hog")) 81963636d95SGeert Uytterhoeven return NOTIFY_OK; /* not for us */ 82063636d95SGeert Uytterhoeven 82163636d95SGeert Uytterhoeven if (of_node_test_and_set_flag(rd->dn, OF_POPULATED)) 82263636d95SGeert Uytterhoeven return NOTIFY_OK; 82363636d95SGeert Uytterhoeven 82463636d95SGeert Uytterhoeven chip = of_find_gpiochip_by_node(rd->dn->parent); 82563636d95SGeert Uytterhoeven if (chip == NULL) 82663636d95SGeert Uytterhoeven return NOTIFY_OK; /* not for us */ 82763636d95SGeert Uytterhoeven 82863636d95SGeert Uytterhoeven ret = of_gpiochip_add_hog(chip, rd->dn); 82963636d95SGeert Uytterhoeven if (ret < 0) { 83063636d95SGeert Uytterhoeven pr_err("%s: failed to add hogs for %pOF\n", __func__, 83163636d95SGeert Uytterhoeven rd->dn); 83263636d95SGeert Uytterhoeven of_node_clear_flag(rd->dn, OF_POPULATED); 83363636d95SGeert Uytterhoeven return notifier_from_errno(ret); 83463636d95SGeert Uytterhoeven } 83563636d95SGeert Uytterhoeven break; 83663636d95SGeert Uytterhoeven 83763636d95SGeert Uytterhoeven case OF_RECONFIG_CHANGE_REMOVE: 83863636d95SGeert Uytterhoeven if (!of_node_check_flag(rd->dn, OF_POPULATED)) 83963636d95SGeert Uytterhoeven return NOTIFY_OK; /* already depopulated */ 84063636d95SGeert Uytterhoeven 84163636d95SGeert Uytterhoeven chip = of_find_gpiochip_by_node(rd->dn->parent); 84263636d95SGeert Uytterhoeven if (chip == NULL) 84363636d95SGeert Uytterhoeven return NOTIFY_OK; /* not for us */ 84463636d95SGeert Uytterhoeven 84563636d95SGeert Uytterhoeven of_gpiochip_remove_hog(chip, rd->dn); 84663636d95SGeert Uytterhoeven of_node_clear_flag(rd->dn, OF_POPULATED); 84763636d95SGeert Uytterhoeven break; 84863636d95SGeert Uytterhoeven } 84963636d95SGeert Uytterhoeven 85063636d95SGeert Uytterhoeven return NOTIFY_OK; 85163636d95SGeert Uytterhoeven } 85263636d95SGeert Uytterhoeven 85363636d95SGeert Uytterhoeven struct notifier_block gpio_of_notifier = { 85463636d95SGeert Uytterhoeven .notifier_call = of_gpio_notify, 85563636d95SGeert Uytterhoeven }; 85663636d95SGeert Uytterhoeven #endif /* CONFIG_OF_DYNAMIC */ 85763636d95SGeert Uytterhoeven 858f625d460SBenoit Parrot /** 85967049c50SThierry Reding * of_gpio_simple_xlate - translate gpiospec to the GPIO number and flags 860f141ed65SGrant Likely * @gc: pointer to the gpio_chip structure 86167049c50SThierry Reding * @gpiospec: GPIO specifier as found in the device tree 862f141ed65SGrant Likely * @flags: a flags pointer to fill in 863f141ed65SGrant Likely * 864f141ed65SGrant Likely * This is simple translation function, suitable for the most 1:1 mapped 86567049c50SThierry Reding * GPIO chips. This function performs only one sanity check: whether GPIO 866f141ed65SGrant Likely * is less than ngpios (that is specified in the gpio_chip). 867f141ed65SGrant Likely */ 868b0c7e73bSGeert Uytterhoeven static int of_gpio_simple_xlate(struct gpio_chip *gc, 869b0c7e73bSGeert Uytterhoeven const struct of_phandle_args *gpiospec, 870b0c7e73bSGeert Uytterhoeven u32 *flags) 871f141ed65SGrant Likely { 872f141ed65SGrant Likely /* 873f141ed65SGrant Likely * We're discouraging gpio_cells < 2, since that way you'll have to 87420a8a968SColin Cronin * write your own xlate function (that will have to retrieve the GPIO 875f141ed65SGrant Likely * number and the flags from a single gpio cell -- this is possible, 876f141ed65SGrant Likely * but not recommended). 877f141ed65SGrant Likely */ 878f141ed65SGrant Likely if (gc->of_gpio_n_cells < 2) { 879f141ed65SGrant Likely WARN_ON(1); 880f141ed65SGrant Likely return -EINVAL; 881f141ed65SGrant Likely } 882f141ed65SGrant Likely 883f141ed65SGrant Likely if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells)) 884f141ed65SGrant Likely return -EINVAL; 885f141ed65SGrant Likely 8867b96c686SGrant Likely if (gpiospec->args[0] >= gc->ngpio) 887f141ed65SGrant Likely return -EINVAL; 888f141ed65SGrant Likely 889f141ed65SGrant Likely if (flags) 890f141ed65SGrant Likely *flags = gpiospec->args[1]; 891f141ed65SGrant Likely 892f141ed65SGrant Likely return gpiospec->args[0]; 893f141ed65SGrant Likely } 894f141ed65SGrant Likely 895*a99cc668SArnd Bergmann #if IS_ENABLED(CONFIG_OF_GPIO_MM_GPIOCHIP) 896*a99cc668SArnd Bergmann #include <linux/gpio/legacy-of-mm-gpiochip.h> 897f141ed65SGrant Likely /** 8983208b0f0SLinus Walleij * of_mm_gpiochip_add_data - Add memory mapped GPIO chip (bank) 899f141ed65SGrant Likely * @np: device node of the GPIO chip 900f141ed65SGrant Likely * @mm_gc: pointer to the of_mm_gpio_chip allocated structure 9013208b0f0SLinus Walleij * @data: driver data to store in the struct gpio_chip 902f141ed65SGrant Likely * 903f141ed65SGrant Likely * To use this function you should allocate and fill mm_gc with: 904f141ed65SGrant Likely * 905f141ed65SGrant Likely * 1) In the gpio_chip structure: 906f141ed65SGrant Likely * - all the callbacks 907f141ed65SGrant Likely * - of_gpio_n_cells 908f141ed65SGrant Likely * - of_xlate callback (optional) 909f141ed65SGrant Likely * 910f141ed65SGrant Likely * 3) In the of_mm_gpio_chip structure: 911f141ed65SGrant Likely * - save_regs callback (optional) 912f141ed65SGrant Likely * 913f141ed65SGrant Likely * If succeeded, this function will map bank's memory and will 914f141ed65SGrant Likely * do all necessary work for you. Then you'll able to use .regs 915f141ed65SGrant Likely * to manage GPIOs from the callbacks. 916f141ed65SGrant Likely */ 9173208b0f0SLinus Walleij int of_mm_gpiochip_add_data(struct device_node *np, 9183208b0f0SLinus Walleij struct of_mm_gpio_chip *mm_gc, 9193208b0f0SLinus Walleij void *data) 920f141ed65SGrant Likely { 921f141ed65SGrant Likely int ret = -ENOMEM; 922f141ed65SGrant Likely struct gpio_chip *gc = &mm_gc->gc; 923f141ed65SGrant Likely 9247eb6ce2fSRob Herring gc->label = kasprintf(GFP_KERNEL, "%pOF", np); 925f141ed65SGrant Likely if (!gc->label) 926f141ed65SGrant Likely goto err0; 927f141ed65SGrant Likely 928f141ed65SGrant Likely mm_gc->regs = of_iomap(np, 0); 929f141ed65SGrant Likely if (!mm_gc->regs) 930f141ed65SGrant Likely goto err1; 931f141ed65SGrant Likely 932f141ed65SGrant Likely gc->base = -1; 933f141ed65SGrant Likely 934f141ed65SGrant Likely if (mm_gc->save_regs) 935f141ed65SGrant Likely mm_gc->save_regs(mm_gc); 936f141ed65SGrant Likely 93777289b2fSAndy Shevchenko fwnode_handle_put(mm_gc->gc.fwnode); 93877289b2fSAndy Shevchenko mm_gc->gc.fwnode = fwnode_handle_get(of_fwnode_handle(np)); 939f141ed65SGrant Likely 9403208b0f0SLinus Walleij ret = gpiochip_add_data(gc, data); 941f141ed65SGrant Likely if (ret) 942f141ed65SGrant Likely goto err2; 943f141ed65SGrant Likely 944f141ed65SGrant Likely return 0; 945f141ed65SGrant Likely err2: 9465d07a692SLiang He of_node_put(np); 947f141ed65SGrant Likely iounmap(mm_gc->regs); 948f141ed65SGrant Likely err1: 949f141ed65SGrant Likely kfree(gc->label); 950f141ed65SGrant Likely err0: 9517eb6ce2fSRob Herring pr_err("%pOF: GPIO chip registration failed with status %d\n", np, ret); 952f141ed65SGrant Likely return ret; 953f141ed65SGrant Likely } 9546d662455SGeert Uytterhoeven EXPORT_SYMBOL_GPL(of_mm_gpiochip_add_data); 955f141ed65SGrant Likely 956d621e8baSRicardo Ribalda Delgado /** 957d621e8baSRicardo Ribalda Delgado * of_mm_gpiochip_remove - Remove memory mapped GPIO chip (bank) 958d621e8baSRicardo Ribalda Delgado * @mm_gc: pointer to the of_mm_gpio_chip allocated structure 959d621e8baSRicardo Ribalda Delgado */ 960d621e8baSRicardo Ribalda Delgado void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc) 961d621e8baSRicardo Ribalda Delgado { 962d621e8baSRicardo Ribalda Delgado struct gpio_chip *gc = &mm_gc->gc; 963d621e8baSRicardo Ribalda Delgado 964d621e8baSRicardo Ribalda Delgado gpiochip_remove(gc); 965d621e8baSRicardo Ribalda Delgado iounmap(mm_gc->regs); 966d621e8baSRicardo Ribalda Delgado kfree(gc->label); 967d621e8baSRicardo Ribalda Delgado } 9686d662455SGeert Uytterhoeven EXPORT_SYMBOL_GPL(of_mm_gpiochip_remove); 969*a99cc668SArnd Bergmann #endif 970d621e8baSRicardo Ribalda Delgado 971f23f1516SShiraz Hashim #ifdef CONFIG_PINCTRL 97228355f81STomeu Vizoso static int of_gpiochip_add_pin_range(struct gpio_chip *chip) 973f23f1516SShiraz Hashim { 974f23f1516SShiraz Hashim struct of_phandle_args pinspec; 9751e63d7b9SLinus Walleij struct pinctrl_dev *pctldev; 97670d0fc42SAndy Shevchenko struct device_node *np; 977f23f1516SShiraz Hashim int index = 0, ret; 978586a87e6SChristian Ruppert const char *name; 979586a87e6SChristian Ruppert static const char group_names_propname[] = "gpio-ranges-group-names"; 980586a87e6SChristian Ruppert struct property *group_names; 981f23f1516SShiraz Hashim 98270d0fc42SAndy Shevchenko np = dev_of_node(&chip->gpiodev->dev); 983f23f1516SShiraz Hashim if (!np) 98428355f81STomeu Vizoso return 0; 985f23f1516SShiraz Hashim 986586a87e6SChristian Ruppert group_names = of_find_property(np, group_names_propname, NULL); 987586a87e6SChristian Ruppert 988ad4e1a7cSHaojian Zhuang for (;; index++) { 989d9fe0039SStephen Warren ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, 990d9fe0039SStephen Warren index, &pinspec); 991f23f1516SShiraz Hashim if (ret) 992f23f1516SShiraz Hashim break; 993f23f1516SShiraz Hashim 9941e63d7b9SLinus Walleij pctldev = of_pinctrl_get(pinspec.np); 995602cf638SMasahiro Yamada of_node_put(pinspec.np); 9961e63d7b9SLinus Walleij if (!pctldev) 99728355f81STomeu Vizoso return -EPROBE_DEFER; 998f23f1516SShiraz Hashim 999586a87e6SChristian Ruppert if (pinspec.args[2]) { 1000586a87e6SChristian Ruppert if (group_names) { 100172858602SLaurent Navet of_property_read_string_index(np, 1002586a87e6SChristian Ruppert group_names_propname, 1003586a87e6SChristian Ruppert index, &name); 1004586a87e6SChristian Ruppert if (strlen(name)) { 10057eb6ce2fSRob Herring pr_err("%pOF: Group name of numeric GPIO ranges must be the empty string.\n", 10067eb6ce2fSRob Herring np); 1007586a87e6SChristian Ruppert break; 1008586a87e6SChristian Ruppert } 1009586a87e6SChristian Ruppert } 1010586a87e6SChristian Ruppert /* npins != 0: linear range */ 10111e63d7b9SLinus Walleij ret = gpiochip_add_pin_range(chip, 1012ef5e3eefSHaojian Zhuang pinctrl_dev_get_devname(pctldev), 10131e63d7b9SLinus Walleij pinspec.args[0], 101486853c83SHaojian Zhuang pinspec.args[1], 101586853c83SHaojian Zhuang pinspec.args[2]); 10161e63d7b9SLinus Walleij if (ret) 101728355f81STomeu Vizoso return ret; 1018586a87e6SChristian Ruppert } else { 1019586a87e6SChristian Ruppert /* npins == 0: special range */ 1020586a87e6SChristian Ruppert if (pinspec.args[1]) { 10217eb6ce2fSRob Herring pr_err("%pOF: Illegal gpio-range format.\n", 10227eb6ce2fSRob Herring np); 1023586a87e6SChristian Ruppert break; 1024586a87e6SChristian Ruppert } 1025586a87e6SChristian Ruppert 1026586a87e6SChristian Ruppert if (!group_names) { 10277eb6ce2fSRob Herring pr_err("%pOF: GPIO group range requested but no %s property.\n", 10287eb6ce2fSRob Herring np, group_names_propname); 1029586a87e6SChristian Ruppert break; 1030586a87e6SChristian Ruppert } 1031586a87e6SChristian Ruppert 1032586a87e6SChristian Ruppert ret = of_property_read_string_index(np, 1033586a87e6SChristian Ruppert group_names_propname, 1034586a87e6SChristian Ruppert index, &name); 1035586a87e6SChristian Ruppert if (ret) 1036586a87e6SChristian Ruppert break; 1037586a87e6SChristian Ruppert 1038586a87e6SChristian Ruppert if (!strlen(name)) { 10397eb6ce2fSRob Herring pr_err("%pOF: Group name of GPIO group range cannot be the empty string.\n", 10407eb6ce2fSRob Herring np); 1041586a87e6SChristian Ruppert break; 1042586a87e6SChristian Ruppert } 1043586a87e6SChristian Ruppert 1044586a87e6SChristian Ruppert ret = gpiochip_add_pingroup_range(chip, pctldev, 1045586a87e6SChristian Ruppert pinspec.args[0], name); 1046586a87e6SChristian Ruppert if (ret) 104728355f81STomeu Vizoso return ret; 1048586a87e6SChristian Ruppert } 1049ad4e1a7cSHaojian Zhuang } 105028355f81STomeu Vizoso 105128355f81STomeu Vizoso return 0; 1052f23f1516SShiraz Hashim } 1053f23f1516SShiraz Hashim 1054f23f1516SShiraz Hashim #else 105528355f81STomeu Vizoso static int of_gpiochip_add_pin_range(struct gpio_chip *chip) { return 0; } 1056f23f1516SShiraz Hashim #endif 1057f23f1516SShiraz Hashim 105828355f81STomeu Vizoso int of_gpiochip_add(struct gpio_chip *chip) 1059f141ed65SGrant Likely { 10608afe8255SAndy Shevchenko struct device_node *np; 1061f0d1ab05SLinus Walleij int ret; 106228355f81STomeu Vizoso 106370d0fc42SAndy Shevchenko np = dev_of_node(&chip->gpiodev->dev); 10648afe8255SAndy Shevchenko if (!np) 106528355f81STomeu Vizoso return 0; 1066f141ed65SGrant Likely 1067f141ed65SGrant Likely if (!chip->of_xlate) { 1068f141ed65SGrant Likely chip->of_gpio_n_cells = 2; 1069f141ed65SGrant Likely chip->of_xlate = of_gpio_simple_xlate; 1070f141ed65SGrant Likely } 1071f141ed65SGrant Likely 10721020dfd1SMasahiro Yamada if (chip->of_gpio_n_cells > MAX_PHANDLE_ARGS) 10731020dfd1SMasahiro Yamada return -EINVAL; 10741020dfd1SMasahiro Yamada 1075f0d1ab05SLinus Walleij ret = of_gpiochip_add_pin_range(chip); 1076f0d1ab05SLinus Walleij if (ret) 1077f0d1ab05SLinus Walleij return ret; 107828355f81STomeu Vizoso 10798afe8255SAndy Shevchenko fwnode_handle_get(chip->fwnode); 1080f625d460SBenoit Parrot 1081f0d1ab05SLinus Walleij ret = of_gpiochip_scan_gpios(chip); 10822f4133bbSAndy Shevchenko if (ret) 10838afe8255SAndy Shevchenko fwnode_handle_put(chip->fwnode); 1084f7299d44SGeert Uytterhoeven 1085f0d1ab05SLinus Walleij return ret; 1086f141ed65SGrant Likely } 1087f141ed65SGrant Likely 1088f141ed65SGrant Likely void of_gpiochip_remove(struct gpio_chip *chip) 1089f141ed65SGrant Likely { 10908afe8255SAndy Shevchenko fwnode_handle_put(chip->fwnode); 1091f141ed65SGrant Likely } 1092