intel-gpio for v5.19-1

* Introduce helpers to iterate over GPIO chip nodes and covert some drivers
 
 The following is an automated git shortlog grouped by driver:
 
 gpiolib:
  -  Introduce a helper to get first GPIO controller node
  -  Introduce gpiochip_node_count() helper
  -  Introduce for_each_gpiochip_node() loop helper
 
 pinctrl:
  -  meson: Replace custom code by gpiochip_node_count() call
  -  meson: Enable COMPILE_TEST
  -  meson: Rename REG_* to MESON_REG_*
  -  armada-37xx: Reuse GPIO fwnode in armada_37xx_irqchip_register()
  -  armada-37xx: Switch to use fwnode instead of of_node
  -  samsung: Switch to use for_each_gpiochip_node() helper
  -  samsung: Drop redundant node parameter in samsung_banks_of_node_get()
  -  npcm7xx: Switch to use for_each_gpiochip_node() helper
  -  renesas: rza1: Switch to use for_each_gpiochip_node() helper
  -  renesas: rza1: Replace custom code by gpiochip_node_count() call
  -  stm32: Switch to use for_each_gpiochip_node() helper
  -  stm32: Replace custom code by gpiochip_node_count() call
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYIAB0WIQSu93Raj3rZDNXzGZv7cr9lmVa5zAUCYmwsmgAKCRD7cr9lmVa5
 zEYPAP4q31AbTJHk6Fs1A79esVSo+DZSkZSzbk/n8Vr3oYG56gD/dVu5EmLNKPHU
 6o5+BvdXqjHrymihHasdyD9YqI30zwM=
 =MIEU
 -----END PGP SIGNATURE-----

Merge tag 'intel-gpio-v5.19-1' of git://git.kernel.org/pub/scm/linux/kernel/git/andy/linux-gpio-intel into devel

intel-gpio for v5.19-1

* Introduce helpers to iterate over GPIO chip nodes and covert some drivers

The following is an automated git shortlog grouped by driver:

gpiolib:
 -  Introduce a helper to get first GPIO controller node
 -  Introduce gpiochip_node_count() helper
 -  Introduce for_each_gpiochip_node() loop helper

pinctrl:
 -  meson: Replace custom code by gpiochip_node_count() call
 -  meson: Enable COMPILE_TEST
 -  meson: Rename REG_* to MESON_REG_*
 -  armada-37xx: Reuse GPIO fwnode in armada_37xx_irqchip_register()
 -  armada-37xx: Switch to use fwnode instead of of_node
 -  samsung: Switch to use for_each_gpiochip_node() helper
 -  samsung: Drop redundant node parameter in samsung_banks_of_node_get()
 -  npcm7xx: Switch to use for_each_gpiochip_node() helper
 -  renesas: rza1: Switch to use for_each_gpiochip_node() helper
 -  renesas: rza1: Replace custom code by gpiochip_node_count() call
 -  stm32: Switch to use for_each_gpiochip_node() helper
 -  stm32: Replace custom code by gpiochip_node_count() call
This commit is contained in:
Linus Walleij 2022-05-04 23:15:21 +02:00
commit a091208308
13 changed files with 208 additions and 251 deletions

View File

@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only # SPDX-License-Identifier: GPL-2.0-only
menuconfig PINCTRL_MESON menuconfig PINCTRL_MESON
tristate "Amlogic SoC pinctrl drivers" tristate "Amlogic SoC pinctrl drivers"
depends on ARCH_MESON depends on ARCH_MESON || COMPILE_TEST
depends on OF depends on OF
default y default y
select PINMUX select PINMUX

View File

@ -49,6 +49,7 @@
#include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h> #include <linux/pinctrl/pinmux.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
@ -218,13 +219,13 @@ static int meson_pinconf_set_output(struct meson_pinctrl *pc,
unsigned int pin, unsigned int pin,
bool out) bool out)
{ {
return meson_pinconf_set_gpio_bit(pc, pin, REG_DIR, !out); return meson_pinconf_set_gpio_bit(pc, pin, MESON_REG_DIR, !out);
} }
static int meson_pinconf_get_output(struct meson_pinctrl *pc, static int meson_pinconf_get_output(struct meson_pinctrl *pc,
unsigned int pin) unsigned int pin)
{ {
int ret = meson_pinconf_get_gpio_bit(pc, pin, REG_DIR); int ret = meson_pinconf_get_gpio_bit(pc, pin, MESON_REG_DIR);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -236,13 +237,13 @@ static int meson_pinconf_set_drive(struct meson_pinctrl *pc,
unsigned int pin, unsigned int pin,
bool high) bool high)
{ {
return meson_pinconf_set_gpio_bit(pc, pin, REG_OUT, high); return meson_pinconf_set_gpio_bit(pc, pin, MESON_REG_OUT, high);
} }
static int meson_pinconf_get_drive(struct meson_pinctrl *pc, static int meson_pinconf_get_drive(struct meson_pinctrl *pc,
unsigned int pin) unsigned int pin)
{ {
return meson_pinconf_get_gpio_bit(pc, pin, REG_OUT); return meson_pinconf_get_gpio_bit(pc, pin, MESON_REG_OUT);
} }
static int meson_pinconf_set_output_drive(struct meson_pinctrl *pc, static int meson_pinconf_set_output_drive(struct meson_pinctrl *pc,
@ -269,7 +270,7 @@ static int meson_pinconf_disable_bias(struct meson_pinctrl *pc,
if (ret) if (ret)
return ret; return ret;
meson_calc_reg_and_bit(bank, pin, REG_PULLEN, &reg, &bit); meson_calc_reg_and_bit(bank, pin, MESON_REG_PULLEN, &reg, &bit);
ret = regmap_update_bits(pc->reg_pullen, reg, BIT(bit), 0); ret = regmap_update_bits(pc->reg_pullen, reg, BIT(bit), 0);
if (ret) if (ret)
return ret; return ret;
@ -288,7 +289,7 @@ static int meson_pinconf_enable_bias(struct meson_pinctrl *pc, unsigned int pin,
if (ret) if (ret)
return ret; return ret;
meson_calc_reg_and_bit(bank, pin, REG_PULL, &reg, &bit); meson_calc_reg_and_bit(bank, pin, MESON_REG_PULL, &reg, &bit);
if (pull_up) if (pull_up)
val = BIT(bit); val = BIT(bit);
@ -296,7 +297,7 @@ static int meson_pinconf_enable_bias(struct meson_pinctrl *pc, unsigned int pin,
if (ret) if (ret)
return ret; return ret;
meson_calc_reg_and_bit(bank, pin, REG_PULLEN, &reg, &bit); meson_calc_reg_and_bit(bank, pin, MESON_REG_PULLEN, &reg, &bit);
ret = regmap_update_bits(pc->reg_pullen, reg, BIT(bit), BIT(bit)); ret = regmap_update_bits(pc->reg_pullen, reg, BIT(bit), BIT(bit));
if (ret) if (ret)
return ret; return ret;
@ -321,7 +322,7 @@ static int meson_pinconf_set_drive_strength(struct meson_pinctrl *pc,
if (ret) if (ret)
return ret; return ret;
meson_calc_reg_and_bit(bank, pin, REG_DS, &reg, &bit); meson_calc_reg_and_bit(bank, pin, MESON_REG_DS, &reg, &bit);
if (drive_strength_ua <= 500) { if (drive_strength_ua <= 500) {
ds_val = MESON_PINCONF_DRV_500UA; ds_val = MESON_PINCONF_DRV_500UA;
@ -407,7 +408,7 @@ static int meson_pinconf_get_pull(struct meson_pinctrl *pc, unsigned int pin)
if (ret) if (ret)
return ret; return ret;
meson_calc_reg_and_bit(bank, pin, REG_PULLEN, &reg, &bit); meson_calc_reg_and_bit(bank, pin, MESON_REG_PULLEN, &reg, &bit);
ret = regmap_read(pc->reg_pullen, reg, &val); ret = regmap_read(pc->reg_pullen, reg, &val);
if (ret) if (ret)
@ -416,7 +417,7 @@ static int meson_pinconf_get_pull(struct meson_pinctrl *pc, unsigned int pin)
if (!(val & BIT(bit))) { if (!(val & BIT(bit))) {
conf = PIN_CONFIG_BIAS_DISABLE; conf = PIN_CONFIG_BIAS_DISABLE;
} else { } else {
meson_calc_reg_and_bit(bank, pin, REG_PULL, &reg, &bit); meson_calc_reg_and_bit(bank, pin, MESON_REG_PULL, &reg, &bit);
ret = regmap_read(pc->reg_pull, reg, &val); ret = regmap_read(pc->reg_pull, reg, &val);
if (ret) if (ret)
@ -447,7 +448,7 @@ static int meson_pinconf_get_drive_strength(struct meson_pinctrl *pc,
if (ret) if (ret)
return ret; return ret;
meson_calc_reg_and_bit(bank, pin, REG_DS, &reg, &bit); meson_calc_reg_and_bit(bank, pin, MESON_REG_DS, &reg, &bit);
ret = regmap_read(pc->reg_ds, reg, &val); ret = regmap_read(pc->reg_ds, reg, &val);
if (ret) if (ret)
@ -595,7 +596,7 @@ static int meson_gpio_get(struct gpio_chip *chip, unsigned gpio)
if (ret) if (ret)
return ret; return ret;
meson_calc_reg_and_bit(bank, gpio, REG_IN, &reg, &bit); meson_calc_reg_and_bit(bank, gpio, MESON_REG_IN, &reg, &bit);
regmap_read(pc->reg_gpio, reg, &val); regmap_read(pc->reg_gpio, reg, &val);
return !!(val & BIT(bit)); return !!(val & BIT(bit));
@ -662,27 +663,22 @@ static struct regmap *meson_map_resource(struct meson_pinctrl *pc,
return devm_regmap_init_mmio(pc->dev, base, &meson_regmap_config); return devm_regmap_init_mmio(pc->dev, base, &meson_regmap_config);
} }
static int meson_pinctrl_parse_dt(struct meson_pinctrl *pc, static int meson_pinctrl_parse_dt(struct meson_pinctrl *pc)
struct device_node *node)
{ {
struct device_node *np, *gpio_np = NULL; struct device_node *gpio_np;
unsigned int chips;
for_each_child_of_node(node, np) { chips = gpiochip_node_count(pc->dev);
if (!of_find_property(np, "gpio-controller", NULL)) if (!chips) {
continue;
if (gpio_np) {
dev_err(pc->dev, "multiple gpio nodes\n");
of_node_put(np);
return -EINVAL;
}
gpio_np = np;
}
if (!gpio_np) {
dev_err(pc->dev, "no gpio node found\n"); dev_err(pc->dev, "no gpio node found\n");
return -EINVAL; return -EINVAL;
} }
if (chips > 1) {
dev_err(pc->dev, "multiple gpio nodes\n");
return -EINVAL;
}
gpio_np = to_of_node(gpiochip_node_get_first(pc->dev));
pc->of_node = gpio_np; pc->of_node = gpio_np;
pc->reg_mux = meson_map_resource(pc, gpio_np, "mux"); pc->reg_mux = meson_map_resource(pc, gpio_np, "mux");
@ -751,7 +747,7 @@ int meson_pinctrl_probe(struct platform_device *pdev)
pc->dev = dev; pc->dev = dev;
pc->data = (struct meson_pinctrl_data *) of_device_get_match_data(dev); pc->data = (struct meson_pinctrl_data *) of_device_get_match_data(dev);
ret = meson_pinctrl_parse_dt(pc, dev->of_node); ret = meson_pinctrl_parse_dt(pc);
if (ret) if (ret)
return ret; return ret;

View File

@ -63,13 +63,13 @@ struct meson_reg_desc {
* enum meson_reg_type - type of registers encoded in @meson_reg_desc * enum meson_reg_type - type of registers encoded in @meson_reg_desc
*/ */
enum meson_reg_type { enum meson_reg_type {
REG_PULLEN, MESON_REG_PULLEN,
REG_PULL, MESON_REG_PULL,
REG_DIR, MESON_REG_DIR,
REG_OUT, MESON_REG_OUT,
REG_IN, MESON_REG_IN,
REG_DS, MESON_REG_DS,
NUM_REG, MESON_NUM_REG,
}; };
/** /**
@ -102,7 +102,7 @@ struct meson_bank {
unsigned int last; unsigned int last;
int irq_first; int irq_first;
int irq_last; int irq_last;
struct meson_reg_desc regs[NUM_REG]; struct meson_reg_desc regs[MESON_NUM_REG];
}; };
struct meson_pinctrl_data { struct meson_pinctrl_data {
@ -150,12 +150,12 @@ struct meson_pinctrl {
.irq_first = fi, \ .irq_first = fi, \
.irq_last = li, \ .irq_last = li, \
.regs = { \ .regs = { \
[REG_PULLEN] = { per, peb }, \ [MESON_REG_PULLEN] = { per, peb }, \
[REG_PULL] = { pr, pb }, \ [MESON_REG_PULL] = { pr, pb }, \
[REG_DIR] = { dr, db }, \ [MESON_REG_DIR] = { dr, db }, \
[REG_OUT] = { or, ob }, \ [MESON_REG_OUT] = { or, ob }, \
[REG_IN] = { ir, ib }, \ [MESON_REG_IN] = { ir, ib }, \
[REG_DS] = { dsr, dsb }, \ [MESON_REG_DS] = { dsr, dsb }, \
}, \ }, \
} }

View File

@ -21,6 +21,7 @@
#include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h> #include <linux/pinctrl/pinmux.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/string_helpers.h> #include <linux/string_helpers.h>
@ -726,23 +727,13 @@ static int armada_37xx_irqchip_register(struct platform_device *pdev,
struct gpio_chip *gc = &info->gpio_chip; struct gpio_chip *gc = &info->gpio_chip;
struct irq_chip *irqchip = &info->irq_chip; struct irq_chip *irqchip = &info->irq_chip;
struct gpio_irq_chip *girq = &gc->irq; struct gpio_irq_chip *girq = &gc->irq;
struct device_node *np = to_of_node(gc->fwnode);
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device_node *np; unsigned int i, nr_irq_parent;
int ret = -ENODEV, i, nr_irq_parent;
/* Check if we have at least one gpio-controller child node */
for_each_child_of_node(dev->of_node, np) {
if (of_property_read_bool(np, "gpio-controller")) {
ret = 0;
break;
}
}
if (ret)
return dev_err_probe(dev, ret, "no gpio-controller child node\n");
nr_irq_parent = of_irq_count(np);
spin_lock_init(&info->irq_lock); spin_lock_init(&info->irq_lock);
nr_irq_parent = of_irq_count(np);
if (!nr_irq_parent) { if (!nr_irq_parent) {
dev_err(dev, "invalid or no IRQ\n"); dev_err(dev, "invalid or no IRQ\n");
return 0; return 0;
@ -787,18 +778,13 @@ static int armada_37xx_gpiochip_register(struct platform_device *pdev,
struct armada_37xx_pinctrl *info) struct armada_37xx_pinctrl *info)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device_node *np; struct fwnode_handle *fwnode;
struct gpio_chip *gc; struct gpio_chip *gc;
int ret = -ENODEV; int ret;
for_each_child_of_node(dev->of_node, np) { fwnode = gpiochip_node_get_first(dev);
if (of_find_property(np, "gpio-controller", NULL)) { if (!fwnode)
ret = 0; return -ENODEV;
break;
}
}
if (ret)
return ret;
info->gpio_chip = armada_37xx_gpiolib_chip; info->gpio_chip = armada_37xx_gpiolib_chip;
@ -806,7 +792,7 @@ static int armada_37xx_gpiochip_register(struct platform_device *pdev,
gc->ngpio = info->data->nr_pins; gc->ngpio = info->data->nr_pins;
gc->parent = dev; gc->parent = dev;
gc->base = -1; gc->base = -1;
gc->of_node = np; gc->fwnode = fwnode;
gc->label = info->data->name; gc->label = info->data->name;
ret = armada_37xx_irqchip_register(pdev, info); ret = armada_37xx_irqchip_register(pdev, info);

View File

@ -17,6 +17,7 @@
#include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h> #include <linux/pinctrl/pinmux.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/regmap.h> #include <linux/regmap.h>
/* GCR registers */ /* GCR registers */
@ -1862,88 +1863,69 @@ static int npcm7xx_gpio_of(struct npcm7xx_pinctrl *pctrl)
{ {
int ret = -ENXIO; int ret = -ENXIO;
struct resource res; struct resource res;
int id = 0, irq; struct device *dev = pctrl->dev;
struct device_node *np; struct fwnode_reference_args args;
struct of_phandle_args pinspec; struct fwnode_handle *child;
int id = 0;
for_each_available_child_of_node(pctrl->dev->of_node, np) for_each_gpiochip_node(dev, child) {
if (of_find_property(np, "gpio-controller", NULL)) { struct device_node *np = to_of_node(child);
ret = of_address_to_resource(np, 0, &res);
if (ret < 0) {
dev_err(pctrl->dev,
"Resource fail for GPIO bank %u\n", id);
return ret;
}
pctrl->gpio_bank[id].base = ret = of_address_to_resource(np, 0, &res);
ioremap(res.start, resource_size(&res)); if (ret < 0) {
dev_err(dev, "Resource fail for GPIO bank %u\n", id);
irq = irq_of_parse_and_map(np, 0); return ret;
if (irq < 0) {
dev_err(pctrl->dev,
"No IRQ for GPIO bank %u\n", id);
ret = irq;
return ret;
}
ret = bgpio_init(&pctrl->gpio_bank[id].gc,
pctrl->dev, 4,
pctrl->gpio_bank[id].base +
NPCM7XX_GP_N_DIN,
pctrl->gpio_bank[id].base +
NPCM7XX_GP_N_DOUT,
NULL,
NULL,
pctrl->gpio_bank[id].base +
NPCM7XX_GP_N_IEM,
BGPIOF_READ_OUTPUT_REG_SET);
if (ret) {
dev_err(pctrl->dev, "bgpio_init() failed\n");
return ret;
}
ret = of_parse_phandle_with_fixed_args(np,
"gpio-ranges", 3,
0, &pinspec);
if (ret < 0) {
dev_err(pctrl->dev,
"gpio-ranges fail for GPIO bank %u\n",
id);
return ret;
}
pctrl->gpio_bank[id].irq = irq;
pctrl->gpio_bank[id].irq_chip = npcmgpio_irqchip;
pctrl->gpio_bank[id].gc.parent = pctrl->dev;
pctrl->gpio_bank[id].irqbase =
id * NPCM7XX_GPIO_PER_BANK;
pctrl->gpio_bank[id].pinctrl_id = pinspec.args[0];
pctrl->gpio_bank[id].gc.base = pinspec.args[1];
pctrl->gpio_bank[id].gc.ngpio = pinspec.args[2];
pctrl->gpio_bank[id].gc.owner = THIS_MODULE;
pctrl->gpio_bank[id].gc.label =
devm_kasprintf(pctrl->dev, GFP_KERNEL, "%pOF",
np);
if (pctrl->gpio_bank[id].gc.label == NULL)
return -ENOMEM;
pctrl->gpio_bank[id].gc.dbg_show = npcmgpio_dbg_show;
pctrl->gpio_bank[id].direction_input =
pctrl->gpio_bank[id].gc.direction_input;
pctrl->gpio_bank[id].gc.direction_input =
npcmgpio_direction_input;
pctrl->gpio_bank[id].direction_output =
pctrl->gpio_bank[id].gc.direction_output;
pctrl->gpio_bank[id].gc.direction_output =
npcmgpio_direction_output;
pctrl->gpio_bank[id].request =
pctrl->gpio_bank[id].gc.request;
pctrl->gpio_bank[id].gc.request = npcmgpio_gpio_request;
pctrl->gpio_bank[id].gc.free = npcmgpio_gpio_free;
pctrl->gpio_bank[id].gc.of_node = np;
id++;
} }
pctrl->gpio_bank[id].base = ioremap(res.start, resource_size(&res));
ret = bgpio_init(&pctrl->gpio_bank[id].gc, dev, 4,
pctrl->gpio_bank[id].base + NPCM7XX_GP_N_DIN,
pctrl->gpio_bank[id].base + NPCM7XX_GP_N_DOUT,
NULL,
NULL,
pctrl->gpio_bank[id].base + NPCM7XX_GP_N_IEM,
BGPIOF_READ_OUTPUT_REG_SET);
if (ret) {
dev_err(dev, "bgpio_init() failed\n");
return ret;
}
ret = fwnode_property_get_reference_args(child, "gpio-ranges", NULL, 3, 0, &args);
if (ret < 0) {
dev_err(dev, "gpio-ranges fail for GPIO bank %u\n", id);
return ret;
}
ret = irq_of_parse_and_map(np, 0);
if (ret < 0) {
dev_err(dev, "No IRQ for GPIO bank %u\n", id);
return ret;
}
pctrl->gpio_bank[id].irq = ret;
pctrl->gpio_bank[id].irq_chip = npcmgpio_irqchip;
pctrl->gpio_bank[id].irqbase = id * NPCM7XX_GPIO_PER_BANK;
pctrl->gpio_bank[id].pinctrl_id = args.args[0];
pctrl->gpio_bank[id].gc.base = args.args[1];
pctrl->gpio_bank[id].gc.ngpio = args.args[2];
pctrl->gpio_bank[id].gc.owner = THIS_MODULE;
pctrl->gpio_bank[id].gc.parent = dev;
pctrl->gpio_bank[id].gc.fwnode = child;
pctrl->gpio_bank[id].gc.label = devm_kasprintf(dev, GFP_KERNEL, "%pfw", child);
if (pctrl->gpio_bank[id].gc.label == NULL)
return -ENOMEM;
pctrl->gpio_bank[id].gc.dbg_show = npcmgpio_dbg_show;
pctrl->gpio_bank[id].direction_input = pctrl->gpio_bank[id].gc.direction_input;
pctrl->gpio_bank[id].gc.direction_input = npcmgpio_direction_input;
pctrl->gpio_bank[id].direction_output = pctrl->gpio_bank[id].gc.direction_output;
pctrl->gpio_bank[id].gc.direction_output = npcmgpio_direction_output;
pctrl->gpio_bank[id].request = pctrl->gpio_bank[id].gc.request;
pctrl->gpio_bank[id].gc.request = npcmgpio_gpio_request;
pctrl->gpio_bank[id].gc.free = npcmgpio_gpio_free;
id++;
}
pctrl->bank_num = id; pctrl->bank_num = id;
return ret; return ret;
} }

View File

@ -24,6 +24,7 @@
#include <linux/pinctrl/pinconf-generic.h> #include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h> #include <linux/pinctrl/pinmux.h>
#include <linux/property.h>
#include <linux/slab.h> #include <linux/slab.h>
#include "../core.h" #include "../core.h"
@ -1154,21 +1155,6 @@ static const struct pinmux_ops rza1_pinmux_ops = {
* RZ/A1 pin controller driver operations * RZ/A1 pin controller driver operations
*/ */
static unsigned int rza1_count_gpio_chips(struct device_node *np)
{
struct device_node *child;
unsigned int count = 0;
for_each_child_of_node(np, child) {
if (!of_property_read_bool(child, "gpio-controller"))
continue;
count++;
}
return count;
}
/** /**
* rza1_parse_gpiochip() - parse and register a gpio chip and pin range * rza1_parse_gpiochip() - parse and register a gpio chip and pin range
* *
@ -1176,22 +1162,22 @@ static unsigned int rza1_count_gpio_chips(struct device_node *np)
* defined by gpio device tree binding documentation. * defined by gpio device tree binding documentation.
* *
* @rza1_pctl: RZ/A1 pin controller device * @rza1_pctl: RZ/A1 pin controller device
* @np: of gpio-controller node * @fwnode: gpio-controller firmware node
* @chip: gpio chip to register to gpiolib * @chip: gpio chip to register to gpiolib
* @range: pin range to register to pinctrl core * @range: pin range to register to pinctrl core
*/ */
static int rza1_parse_gpiochip(struct rza1_pinctrl *rza1_pctl, static int rza1_parse_gpiochip(struct rza1_pinctrl *rza1_pctl,
struct device_node *np, struct fwnode_handle *fwnode,
struct gpio_chip *chip, struct gpio_chip *chip,
struct pinctrl_gpio_range *range) struct pinctrl_gpio_range *range)
{ {
const char *list_name = "gpio-ranges"; const char *list_name = "gpio-ranges";
struct of_phandle_args of_args; struct fwnode_reference_args args;
unsigned int gpioport; unsigned int gpioport;
u32 pinctrl_base; u32 pinctrl_base;
int ret; int ret;
ret = of_parse_phandle_with_fixed_args(np, list_name, 3, 0, &of_args); ret = fwnode_property_get_reference_args(fwnode, list_name, NULL, 3, 0, &args);
if (ret) { if (ret) {
dev_err(rza1_pctl->dev, "Unable to parse %s list property\n", dev_err(rza1_pctl->dev, "Unable to parse %s list property\n",
list_name); list_name);
@ -1202,7 +1188,7 @@ static int rza1_parse_gpiochip(struct rza1_pinctrl *rza1_pctl,
* Find out on which port this gpio-chip maps to by inspecting the * Find out on which port this gpio-chip maps to by inspecting the
* second argument of the "gpio-ranges" property. * second argument of the "gpio-ranges" property.
*/ */
pinctrl_base = of_args.args[1]; pinctrl_base = args.args[1];
gpioport = RZA1_PIN_ID_TO_PORT(pinctrl_base); gpioport = RZA1_PIN_ID_TO_PORT(pinctrl_base);
if (gpioport >= RZA1_NPORTS) { if (gpioport >= RZA1_NPORTS) {
dev_err(rza1_pctl->dev, dev_err(rza1_pctl->dev,
@ -1212,19 +1198,18 @@ static int rza1_parse_gpiochip(struct rza1_pinctrl *rza1_pctl,
*chip = rza1_gpiochip_template; *chip = rza1_gpiochip_template;
chip->base = -1; chip->base = -1;
chip->label = devm_kasprintf(rza1_pctl->dev, GFP_KERNEL, "%pOFn", chip->ngpio = args.args[2];
np); chip->label = devm_kasprintf(rza1_pctl->dev, GFP_KERNEL, "%pfwP", fwnode);
if (!chip->label) if (!chip->label)
return -ENOMEM; return -ENOMEM;
chip->ngpio = of_args.args[2]; chip->fwnode = fwnode;
chip->of_node = np;
chip->parent = rza1_pctl->dev; chip->parent = rza1_pctl->dev;
range->id = gpioport; range->id = gpioport;
range->name = chip->label; range->name = chip->label;
range->pin_base = range->base = pinctrl_base; range->pin_base = range->base = pinctrl_base;
range->npins = of_args.args[2]; range->npins = args.args[2];
range->gc = chip; range->gc = chip;
ret = devm_gpiochip_add_data(rza1_pctl->dev, chip, ret = devm_gpiochip_add_data(rza1_pctl->dev, chip,
@ -1247,15 +1232,14 @@ static int rza1_parse_gpiochip(struct rza1_pinctrl *rza1_pctl,
*/ */
static int rza1_gpio_register(struct rza1_pinctrl *rza1_pctl) static int rza1_gpio_register(struct rza1_pinctrl *rza1_pctl)
{ {
struct device_node *np = rza1_pctl->dev->of_node;
struct pinctrl_gpio_range *gpio_ranges; struct pinctrl_gpio_range *gpio_ranges;
struct gpio_chip *gpio_chips; struct gpio_chip *gpio_chips;
struct device_node *child; struct fwnode_handle *child;
unsigned int ngpiochips; unsigned int ngpiochips;
unsigned int i; unsigned int i;
int ret; int ret;
ngpiochips = rza1_count_gpio_chips(np); ngpiochips = gpiochip_node_count(rza1_pctl->dev);
if (ngpiochips == 0) { if (ngpiochips == 0) {
dev_dbg(rza1_pctl->dev, "No gpiochip registered\n"); dev_dbg(rza1_pctl->dev, "No gpiochip registered\n");
return 0; return 0;
@ -1269,14 +1253,11 @@ static int rza1_gpio_register(struct rza1_pinctrl *rza1_pctl)
return -ENOMEM; return -ENOMEM;
i = 0; i = 0;
for_each_child_of_node(np, child) { for_each_gpiochip_node(rza1_pctl->dev, child) {
if (!of_property_read_bool(child, "gpio-controller"))
continue;
ret = rza1_parse_gpiochip(rza1_pctl, child, &gpio_chips[i], ret = rza1_parse_gpiochip(rza1_pctl, child, &gpio_chips[i],
&gpio_ranges[i]); &gpio_ranges[i]);
if (ret) { if (ret) {
of_node_put(child); fwnode_handle_put(child);
return ret; return ret;
} }

View File

@ -307,7 +307,7 @@ __init int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
} }
bank->irq_chip->chip.name = bank->name; bank->irq_chip->chip.name = bank->name;
bank->irq_domain = irq_domain_add_linear(bank->of_node, bank->irq_domain = irq_domain_create_linear(bank->fwnode,
bank->nr_pins, &exynos_eint_irqd_ops, bank); bank->nr_pins, &exynos_eint_irqd_ops, bank);
if (!bank->irq_domain) { if (!bank->irq_domain) {
dev_err(dev, "gpio irq domain add failed\n"); dev_err(dev, "gpio irq domain add failed\n");
@ -565,7 +565,7 @@ __init int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
} }
bank->irq_chip->chip.name = bank->name; bank->irq_chip->chip.name = bank->name;
bank->irq_domain = irq_domain_add_linear(bank->of_node, bank->irq_domain = irq_domain_create_linear(bank->fwnode,
bank->nr_pins, &exynos_eint_irqd_ops, bank); bank->nr_pins, &exynos_eint_irqd_ops, bank);
if (!bank->irq_domain) { if (!bank->irq_domain) {
dev_err(dev, "wkup irq domain add failed\n"); dev_err(dev, "wkup irq domain add failed\n");
@ -573,7 +573,7 @@ __init int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
return -ENXIO; return -ENXIO;
} }
if (!of_find_property(bank->of_node, "interrupts", NULL)) { if (!fwnode_property_present(bank->fwnode, "interrupts")) {
bank->eint_type = EINT_TYPE_WKUP_MUX; bank->eint_type = EINT_TYPE_WKUP_MUX;
++muxed_banks; ++muxed_banks;
continue; continue;
@ -588,7 +588,7 @@ __init int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
} }
for (idx = 0; idx < bank->nr_pins; ++idx) { for (idx = 0; idx < bank->nr_pins; ++idx) {
irq = irq_of_parse_and_map(bank->of_node, idx); irq = irq_of_parse_and_map(to_of_node(bank->fwnode), idx);
if (!irq) { if (!irq) {
dev_err(dev, "irq number for eint-%s-%d not found\n", dev_err(dev, "irq number for eint-%s-%d not found\n",
bank->name, idx); bank->name, idx);

View File

@ -525,7 +525,7 @@ static int s3c24xx_eint_init(struct samsung_pinctrl_drv_data *d)
ops = (bank->eint_offset == 0) ? &s3c24xx_gpf_irq_ops ops = (bank->eint_offset == 0) ? &s3c24xx_gpf_irq_ops
: &s3c24xx_gpg_irq_ops; : &s3c24xx_gpg_irq_ops;
bank->irq_domain = irq_domain_add_linear(bank->of_node, bank->irq_domain = irq_domain_create_linear(bank->fwnode,
bank->nr_pins, ops, ddata); bank->nr_pins, ops, ddata);
if (!bank->irq_domain) { if (!bank->irq_domain) {
dev_err(dev, "wkup irq domain add failed\n"); dev_err(dev, "wkup irq domain add failed\n");

View File

@ -471,7 +471,7 @@ static int s3c64xx_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
mask = bank->eint_mask; mask = bank->eint_mask;
nr_eints = fls(mask); nr_eints = fls(mask);
bank->irq_domain = irq_domain_add_linear(bank->of_node, bank->irq_domain = irq_domain_create_linear(bank->fwnode,
nr_eints, &s3c64xx_gpio_irqd_ops, bank); nr_eints, &s3c64xx_gpio_irqd_ops, bank);
if (!bank->irq_domain) { if (!bank->irq_domain) {
dev_err(dev, "gpio irq domain add failed\n"); dev_err(dev, "gpio irq domain add failed\n");
@ -743,7 +743,7 @@ static int s3c64xx_eint_eint0_init(struct samsung_pinctrl_drv_data *d)
return -ENOMEM; return -ENOMEM;
ddata->bank = bank; ddata->bank = bank;
bank->irq_domain = irq_domain_add_linear(bank->of_node, bank->irq_domain = irq_domain_create_linear(bank->fwnode,
nr_eints, &s3c64xx_eint0_irqd_ops, ddata); nr_eints, &s3c64xx_eint0_irqd_ops, ddata);
if (!bank->irq_domain) { if (!bank->irq_domain) {
dev_err(dev, "wkup irq domain add failed\n"); dev_err(dev, "wkup irq domain add failed\n");

View File

@ -18,6 +18,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/property.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/gpio/driver.h> #include <linux/gpio/driver.h>
@ -966,7 +967,7 @@ static int samsung_gpiolib_register(struct platform_device *pdev,
gc->base = bank->grange.base; gc->base = bank->grange.base;
gc->ngpio = bank->nr_pins; gc->ngpio = bank->nr_pins;
gc->parent = &pdev->dev; gc->parent = &pdev->dev;
gc->of_node = bank->of_node; gc->fwnode = bank->fwnode;
gc->label = bank->name; gc->label = bank->name;
ret = devm_gpiochip_add_data(&pdev->dev, gc, bank); ret = devm_gpiochip_add_data(&pdev->dev, gc, bank);
@ -1002,27 +1003,25 @@ samsung_pinctrl_get_soc_data_for_of_alias(struct platform_device *pdev)
return &(of_data->ctrl[id]); return &(of_data->ctrl[id]);
} }
static void samsung_banks_of_node_put(struct samsung_pinctrl_drv_data *d) static void samsung_banks_node_put(struct samsung_pinctrl_drv_data *d)
{ {
struct samsung_pin_bank *bank; struct samsung_pin_bank *bank;
unsigned int i; unsigned int i;
bank = d->pin_banks; bank = d->pin_banks;
for (i = 0; i < d->nr_banks; ++i, ++bank) for (i = 0; i < d->nr_banks; ++i, ++bank)
of_node_put(bank->of_node); fwnode_handle_put(bank->fwnode);
} }
/* /*
* Iterate over all driver pin banks to find one matching the name of node, * Iterate over all driver pin banks to find one matching the name of node,
* skipping optional "-gpio" node suffix. When found, assign node to the bank. * skipping optional "-gpio" node suffix. When found, assign node to the bank.
*/ */
static void samsung_banks_of_node_get(struct device *dev, static void samsung_banks_node_get(struct device *dev, struct samsung_pinctrl_drv_data *d)
struct samsung_pinctrl_drv_data *d,
struct device_node *node)
{ {
const char *suffix = "-gpio-bank"; const char *suffix = "-gpio-bank";
struct samsung_pin_bank *bank; struct samsung_pin_bank *bank;
struct device_node *child; struct fwnode_handle *child;
/* Pin bank names are up to 4 characters */ /* Pin bank names are up to 4 characters */
char node_name[20]; char node_name[20];
unsigned int i; unsigned int i;
@ -1038,17 +1037,17 @@ static void samsung_banks_of_node_get(struct device *dev,
continue; continue;
} }
for_each_child_of_node(node, child) { for_each_gpiochip_node(dev, child) {
if (!of_find_property(child, "gpio-controller", NULL)) struct device_node *np = to_of_node(child);
continue;
if (of_node_name_eq(child, node_name)) if (of_node_name_eq(np, node_name))
break; break;
else if (of_node_name_eq(child, bank->name)) if (of_node_name_eq(np, bank->name))
break; break;
} }
if (child) if (child)
bank->of_node = child; bank->fwnode = child;
else else
dev_warn(dev, "Missing node for bank %s - invalid DTB\n", dev_warn(dev, "Missing node for bank %s - invalid DTB\n",
bank->name); bank->name);
@ -1061,7 +1060,6 @@ static const struct samsung_pin_ctrl *
samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d, samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d,
struct platform_device *pdev) struct platform_device *pdev)
{ {
struct device_node *node = pdev->dev.of_node;
const struct samsung_pin_bank_data *bdata; const struct samsung_pin_bank_data *bdata;
const struct samsung_pin_ctrl *ctrl; const struct samsung_pin_ctrl *ctrl;
struct samsung_pin_bank *bank; struct samsung_pin_bank *bank;
@ -1125,7 +1123,7 @@ samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d,
*/ */
d->virt_base = virt_base[0]; d->virt_base = virt_base[0];
samsung_banks_of_node_get(&pdev->dev, d, node); samsung_banks_node_get(&pdev->dev, d);
d->pin_base = pin_base; d->pin_base = pin_base;
pin_base += d->nr_pins; pin_base += d->nr_pins;
@ -1186,7 +1184,7 @@ static int samsung_pinctrl_probe(struct platform_device *pdev)
err_unregister: err_unregister:
samsung_pinctrl_unregister(pdev, drvdata); samsung_pinctrl_unregister(pdev, drvdata);
err_put_banks: err_put_banks:
samsung_banks_of_node_put(drvdata); samsung_banks_node_put(drvdata);
return ret; return ret;
} }

View File

@ -165,7 +165,7 @@ struct samsung_pin_bank {
u32 pin_base; u32 pin_base;
void *soc_priv; void *soc_priv;
struct device_node *of_node; struct fwnode_handle *fwnode;
struct samsung_pinctrl_drv_data *drvdata; struct samsung_pinctrl_drv_data *drvdata;
struct irq_domain *irq_domain; struct irq_domain *irq_domain;
struct gpio_chip gpio_chip; struct gpio_chip gpio_chip;

View File

@ -24,6 +24,7 @@
#include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h> #include <linux/pinctrl/pinmux.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/reset.h> #include <linux/reset.h>
#include <linux/slab.h> #include <linux/slab.h>
@ -1190,13 +1191,12 @@ static const struct pinconf_ops stm32_pconf_ops = {
.pin_config_dbg_show = stm32_pconf_dbg_show, .pin_config_dbg_show = stm32_pconf_dbg_show,
}; };
static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, struct fwnode_handle *fwnode)
struct device_node *np)
{ {
struct stm32_gpio_bank *bank = &pctl->banks[pctl->nbanks]; struct stm32_gpio_bank *bank = &pctl->banks[pctl->nbanks];
int bank_ioport_nr; int bank_ioport_nr;
struct pinctrl_gpio_range *range = &bank->range; struct pinctrl_gpio_range *range = &bank->range;
struct of_phandle_args args; struct fwnode_reference_args args;
struct device *dev = pctl->dev; struct device *dev = pctl->dev;
struct resource res; struct resource res;
int npins = STM32_GPIO_PINS_PER_BANK; int npins = STM32_GPIO_PINS_PER_BANK;
@ -1205,7 +1205,7 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl,
if (!IS_ERR(bank->rstc)) if (!IS_ERR(bank->rstc))
reset_control_deassert(bank->rstc); reset_control_deassert(bank->rstc);
if (of_address_to_resource(np, 0, &res)) if (of_address_to_resource(to_of_node(fwnode), 0, &res))
return -ENODEV; return -ENODEV;
bank->base = devm_ioremap_resource(dev, &res); bank->base = devm_ioremap_resource(dev, &res);
@ -1220,15 +1220,15 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl,
bank->gpio_chip = stm32_gpio_template; bank->gpio_chip = stm32_gpio_template;
of_property_read_string(np, "st,bank-name", &bank->gpio_chip.label); fwnode_property_read_string(fwnode, "st,bank-name", &bank->gpio_chip.label);
if (!of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, i, &args)) { if (!fwnode_property_get_reference_args(fwnode, "gpio-ranges", NULL, 3, i, &args)) {
bank_nr = args.args[1] / STM32_GPIO_PINS_PER_BANK; bank_nr = args.args[1] / STM32_GPIO_PINS_PER_BANK;
bank->gpio_chip.base = args.args[1]; bank->gpio_chip.base = args.args[1];
/* get the last defined gpio line (offset + nb of pins) */ /* get the last defined gpio line (offset + nb of pins) */
npins = args.args[0] + args.args[2]; npins = args.args[0] + args.args[2];
while (!of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, ++i, &args)) while (!fwnode_property_get_reference_args(fwnode, "gpio-ranges", NULL, 3, ++i, &args))
npins = max(npins, (int)(args.args[0] + args.args[2])); npins = max(npins, (int)(args.args[0] + args.args[2]));
} else { } else {
bank_nr = pctl->nbanks; bank_nr = pctl->nbanks;
@ -1243,20 +1243,20 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl,
&pctl->banks[bank_nr].range); &pctl->banks[bank_nr].range);
} }
if (of_property_read_u32(np, "st,bank-ioport", &bank_ioport_nr)) if (fwnode_property_read_u32(fwnode, "st,bank-ioport", &bank_ioport_nr))
bank_ioport_nr = bank_nr; bank_ioport_nr = bank_nr;
bank->gpio_chip.base = bank_nr * STM32_GPIO_PINS_PER_BANK; bank->gpio_chip.base = bank_nr * STM32_GPIO_PINS_PER_BANK;
bank->gpio_chip.ngpio = npins; bank->gpio_chip.ngpio = npins;
bank->gpio_chip.of_node = np; bank->gpio_chip.fwnode = fwnode;
bank->gpio_chip.parent = dev; bank->gpio_chip.parent = dev;
bank->bank_nr = bank_nr; bank->bank_nr = bank_nr;
bank->bank_ioport_nr = bank_ioport_nr; bank->bank_ioport_nr = bank_ioport_nr;
spin_lock_init(&bank->lock); spin_lock_init(&bank->lock);
/* create irq hierarchical domain */ /* create irq hierarchical domain */
bank->fwnode = of_node_to_fwnode(np); bank->fwnode = fwnode;
bank->domain = irq_domain_create_hierarchy(pctl->domain, 0, bank->domain = irq_domain_create_hierarchy(pctl->domain, 0,
STM32_GPIO_IRQ_LINE, bank->fwnode, STM32_GPIO_IRQ_LINE, bank->fwnode,
@ -1399,12 +1399,13 @@ static int stm32_pctrl_create_pins_tab(struct stm32_pinctrl *pctl,
int stm32_pctl_probe(struct platform_device *pdev) int stm32_pctl_probe(struct platform_device *pdev)
{ {
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
struct device_node *child; struct fwnode_handle *child;
const struct of_device_id *match; const struct of_device_id *match;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct stm32_pinctrl *pctl; struct stm32_pinctrl *pctl;
struct pinctrl_pin_desc *pins; struct pinctrl_pin_desc *pins;
int i, ret, hwlock_id, banks = 0; int i, ret, hwlock_id;
unsigned int banks;
if (!np) if (!np)
return -EINVAL; return -EINVAL;
@ -1494,10 +1495,7 @@ int stm32_pctl_probe(struct platform_device *pdev)
return PTR_ERR(pctl->pctl_dev); return PTR_ERR(pctl->pctl_dev);
} }
for_each_available_child_of_node(np, child) banks = gpiochip_node_count(dev);
if (of_property_read_bool(child, "gpio-controller"))
banks++;
if (!banks) { if (!banks) {
dev_err(dev, "at least one GPIO bank is required\n"); dev_err(dev, "at least one GPIO bank is required\n");
return -EINVAL; return -EINVAL;
@ -1508,44 +1506,34 @@ int stm32_pctl_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
i = 0; i = 0;
for_each_available_child_of_node(np, child) { for_each_gpiochip_node(dev, child) {
struct stm32_gpio_bank *bank = &pctl->banks[i]; struct stm32_gpio_bank *bank = &pctl->banks[i];
struct device_node *np = to_of_node(child);
if (of_property_read_bool(child, "gpio-controller")) { bank->rstc = of_reset_control_get_exclusive(np, NULL);
bank->rstc = of_reset_control_get_exclusive(child, if (PTR_ERR(bank->rstc) == -EPROBE_DEFER) {
NULL); fwnode_handle_put(child);
if (PTR_ERR(bank->rstc) == -EPROBE_DEFER) { return -EPROBE_DEFER;
of_node_put(child);
return -EPROBE_DEFER;
}
bank->clk = of_clk_get_by_name(child, NULL);
if (IS_ERR(bank->clk)) {
if (PTR_ERR(bank->clk) != -EPROBE_DEFER)
dev_err(dev,
"failed to get clk (%ld)\n",
PTR_ERR(bank->clk));
of_node_put(child);
return PTR_ERR(bank->clk);
}
i++;
} }
bank->clk = of_clk_get_by_name(np, NULL);
if (IS_ERR(bank->clk)) {
if (PTR_ERR(bank->clk) != -EPROBE_DEFER)
dev_err(dev, "failed to get clk (%ld)\n", PTR_ERR(bank->clk));
fwnode_handle_put(child);
return PTR_ERR(bank->clk);
}
i++;
} }
for_each_available_child_of_node(np, child) { for_each_gpiochip_node(dev, child) {
if (of_property_read_bool(child, "gpio-controller")) { ret = stm32_gpiolib_register_bank(pctl, child);
ret = stm32_gpiolib_register_bank(pctl, child); if (ret) {
if (ret) { fwnode_handle_put(child);
of_node_put(child); return ret;
for (i = 0; i < pctl->nbanks; i++)
clk_disable_unprepare(pctl->banks[i].clk);
return ret;
}
pctl->nbanks++;
} }
pctl->nbanks++;
} }
dev_info(dev, "Pinctrl STM32 initialized\n"); dev_info(dev, "Pinctrl STM32 initialized\n");

View File

@ -3,13 +3,14 @@
#define __LINUX_GPIO_DRIVER_H #define __LINUX_GPIO_DRIVER_H
#include <linux/device.h> #include <linux/device.h>
#include <linux/types.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/irqchip/chained_irq.h> #include <linux/irqchip/chained_irq.h>
#include <linux/irqdomain.h> #include <linux/irqdomain.h>
#include <linux/lockdep.h> #include <linux/lockdep.h>
#include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinconf-generic.h> #include <linux/pinctrl/pinconf-generic.h>
#include <linux/property.h>
#include <linux/types.h>
struct gpio_desc; struct gpio_desc;
struct of_phandle_args; struct of_phandle_args;
@ -771,4 +772,29 @@ static inline void gpiochip_unlock_as_irq(struct gpio_chip *gc,
} }
#endif /* CONFIG_GPIOLIB */ #endif /* CONFIG_GPIOLIB */
#define for_each_gpiochip_node(dev, child) \
device_for_each_child_node(dev, child) \
if (!fwnode_property_present(child, "gpio-controller")) {} else
static inline unsigned int gpiochip_node_count(struct device *dev)
{
struct fwnode_handle *child;
unsigned int count = 0;
for_each_gpiochip_node(dev, child)
count++;
return count;
}
static inline struct fwnode_handle *gpiochip_node_get_first(struct device *dev)
{
struct fwnode_handle *fwnode;
for_each_gpiochip_node(dev, fwnode)
return fwnode;
return NULL;
}
#endif /* __LINUX_GPIO_DRIVER_H */ #endif /* __LINUX_GPIO_DRIVER_H */