From: Benoit Parrot <bparrot@ti.com>
To: Alexandre Courbot <gnurou@gmail.com>
Cc: Linus Walleij <linus.walleij@linaro.org>,
"linux-gpio@vger.kernel.org" <linux-gpio@vger.kernel.org>,
Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
"devicetree@vger.kernel.org" <devicetree@vger.kernel.org>,
Pantelis Antoniou <panto@antoniou-consulting.com>,
Jiri Prchal <jiri.prchal@aksignal.cz>
Subject: Re: [RFC Patch] gpio: add GPIO hogging mechanism
Date: Wed, 29 Oct 2014 11:21:05 -0500 [thread overview]
Message-ID: <20141029162105.GA29965@ti.com> (raw)
In-Reply-To: <CAAVeFuK4PaFbbYjUsvA-oO78P5qmQvyGqG+Ov4GLghoC=yPAoA@mail.gmail.com>
Alexandre,
Thanks for the feedback.
Alexandre Courbot <gnurou@gmail.com> wrote on Wed [2014-Oct-29 16:09:59 +0900]:
> Sorry for the delay in reviewing. Adding Jiri and Pantelis who might
> want to extend over this patch and thus will likely have interesting
> comments to make.
>
> On Wed, Oct 22, 2014 at 5:09 AM, Benoit Parrot <bparrot@ti.com> wrote:
> > Based on Boris Brezillion work this is a reworked patch
> > of his initial GPIO hogging mechanism.
> > This patch provides a way to initally configure specific GPIO
> > when the gpio controller is probe.
>
> Typo nit: s/probe/probed
Will fix.
>
> >
> > The actual DT scanning to collect the GPIO specific data is performed
> > as part of the gpiochip_add().
> >
> > The purpose of this is to allows specific GPIOs to be configured
> > without any driver specific code.
> > This particularly usueful because board design are getting
>
> s/suseful/useful
>
> > increassingly complex and given SoC pins can now have upward
>
> s/increassingly/increasingly
Will fix.
>
> > of 10 mux values a lot of connections are now dependent on
> > external IO muxes to switch various modes and combination.
> >
> > Specific drivers should not necessarily need to be aware of
> > what accounts to a specific board implementation. This board level
> > "description" should be best kept as part of the dts file.
> >
> > Signed-off-by: Benoit Parrot <bparrot@ti.com>
> > ---
> > Documentation/devicetree/bindings/gpio/gpio.txt | 33 +++++++++
> > drivers/gpio/gpiolib-of.c | 99 +++++++++++++++++++++++++
> > drivers/gpio/gpiolib.c | 81 ++++++++++++++++++++
> > include/linux/of_gpio.h | 11 +++
> > 4 files changed, 224 insertions(+)
> >
> > diff --git a/Documentation/devicetree/bindings/gpio/gpio.txt b/Documentation/devicetree/bindings/gpio/gpio.txt
> > index 3fb8f53..a9700d8 100644
> > --- a/Documentation/devicetree/bindings/gpio/gpio.txt
> > +++ b/Documentation/devicetree/bindings/gpio/gpio.txt
>
> Note: changes to DT bindings documentation should generally come as a
> separate patch.
Ok.
>
> > @@ -103,6 +103,26 @@ Every GPIO controller node must contain both an empty "gpio-controller"
> > property, and a #gpio-cells integer property, which indicates the number of
> > cells in a gpio-specifier.
> >
> > +It might contain GPIO hog definitions. GPIO hogging is a mechanism providing
> > +automatic GPIO request and configuration as part of the gpio-controller's
> > +driver probe function.
> > +
> > +Each GPIO hog definition is represented as a child node of the GPIO controller.
> > +Required properties:
> > +- gpios: store the gpio information (id, flags, ...). Shall contain the
> > + number of cells specified in its parent node (GPIO controller node).
>
> If would be nice to be able to specify several GPIO references to that
> they can be all set to the same configuration in one row instead of
> requiring one node each.
>
> > +- input: a property specifying to set the GPIO direction as input.
> > +- output-high: a property specifying to set the GPIO direction to output with
> > + the value high.
> > +- output-low: a property specifying to set the GPIO direction to output with
> > + the value low.
>
> Wouldn't a "direction" property taking one of the values "input",
> "output-low" or "output-high" be easier to parse and generally
> clearer?
I guess here you mean something like this:
...
line_y: line_y {
gpios = <15 0>;
direction = <output-low>;
};
Not sure about easier to parse, but it would be clearer.
>
> > +
> > +Optional properties:
> > +- line-name: the GPIO label name. If not present the node name is used.
>
> I guess we also could use this for naming the GPIO during its export
> if we decide to allow this in a near-future patch.
>
Right.
> > +
> > +A GPIO controller can request GPIO hogs using the "gpio-hogs" property, which
> > +encodes a list of requested GPIO hogs.
> > +
> > Example of two SOC GPIO banks defined as gpio-controller nodes:
> >
> > qe_pio_a: gpio-controller@1400 {
> > @@ -110,6 +130,19 @@ Example of two SOC GPIO banks defined as gpio-controller nodes:
> > reg = <0x1400 0x18>;
> > gpio-controller;
> > #gpio-cells = <2>;
> > + gpio-hogs = <&line_b>;
> > +
> > + /* line_a hog is defined but not enabled in this example*/
> > + line_a: line_a {
> > + gpios = <5 0>;
> > + input;
> > + };
> > +
> > + line_b: line_b {
> > + gpios = <6 0>;
> > + output-low;
> > + line-name = "foo-bar-gpio";
> > + };
>
> I think it might be good to group the hog nodes such as to allow
> complex configurations to be set in one go, à la pinmux:
See below.
>
> gpio-controller;
> #gpio-cells = <2>;
> + gpio-hogs = <&line_b>;
> +
> + line_a: line_a {
> + line_a {
> + gpios = <5 0>;
> + input;
> + };
> + line_c {
> + gpios = <7 0>;
> + inputl
> + };
> + };
> +
> + line_b: line_b {
> + line_b {
> + gpios = <6 0>;
> + output-low;
> + line-name = "foo-bar-gpio";
> + };
> + };
>
> Here if you want to enable the first configuration you don't need to
> specify all the lines one by one, you just need to select the right
> group.
>
> I wonder if such usage of child nodes could not interfere with GPIO
> drivers (existing or to be) that need to use child nodes for other
> purposes. Right now there is no way to distinguish a hog node from a
> node that serves another purpose, and that might become a problem in
> the future. Not sure how that should be addressed though - maybe by
> enforcing a "-hog" suffix for the group nodes, e.g. line_a-hog?
> Comments from people more experienced with DT would be nice.
I did consider a "pinmux" flavored format (not sure how hard to parse it would be).
It would allow grouping if nothing else.
/* Line syntax: line_name <gpio# flags> direction-value [export] */
gpio-hogs = <&group_y>;
group_y: group_y {
gpio-hogs-group = <
line_x <15 0> output-low
line_y <16 0> output-high export
line_z <17 0> input
>;
};
>
> > };
> >
> > qe_pio_e: gpio-controller@1460 {
> > diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
> > index 604dbe6..7308dfc 100644
> > --- a/drivers/gpio/gpiolib-of.c
> > +++ b/drivers/gpio/gpiolib-of.c
> > @@ -111,6 +111,105 @@ int of_get_named_gpio_flags(struct device_node *np, const char *list_name,
> > EXPORT_SYMBOL(of_get_named_gpio_flags);
> >
> > /**
> > + * of_get_gpio_hog() - Get a GPIO hog descriptor, names and flags for GPIO API
> > + * @np: device node to get GPIO from
> > + * @index: index of the GPIO
> > + * @name: GPIO line name
> > + * @flags: a flags pointer to fill in
> > + *
> > + * Returns GPIO descriptor to use with Linux GPIO API, or one of the errno
> > + * value on the error condition.
> > + */
> > +struct gpio_desc *of_get_gpio_hog(struct device_node *np, int index,
> > + const char **name, unsigned long *flags)
> > +{
> > + struct device_node *cfg_np, *chip_np;
> > + enum of_gpio_flags xlate_flags;
> > + unsigned long req_flags = 0;
> > + struct gpio_desc *desc;
> > + struct gg_data gg_data = {
> > + .flags = &xlate_flags,
> > + .out_gpio = NULL,
> > + };
> > + u32 tmp;
> > + int i;
> > + int ret;
> > +
> > + cfg_np = of_parse_phandle(np, "gpio-hogs", index);
> > + if (!cfg_np)
> > + return ERR_PTR(-EINVAL);
> > +
> > + chip_np = cfg_np->parent;
> > + if (!chip_np) {
> > + desc = ERR_PTR(-EINVAL);
> > + goto out;
> > + }
> > +
> > + ret = of_property_read_u32(chip_np, "#gpio-cells", &tmp);
> > + if (ret) {
> > + desc = ERR_PTR(ret);
> > + goto out;
> > + }
> > +
> > + if (tmp > MAX_PHANDLE_ARGS) {
> > + desc = ERR_PTR(-EINVAL);
> > + goto out;
> > + }
> > +
> > + gg_data.gpiospec.args_count = tmp;
> > + gg_data.gpiospec.np = chip_np;
> > + for (i = 0; i < tmp; i++) {
> > + ret = of_property_read_u32(cfg_np, "gpios",
> > + &gg_data.gpiospec.args[i]);
> > + if (ret) {
> > + desc = ERR_PTR(ret);
> > + goto out;
> > + }
> > + }
> > +
> > + gpiochip_find(&gg_data, of_gpiochip_find_and_xlate);
> > + if (!gg_data.out_gpio) {
> > + if (cfg_np->parent == np)
> > + desc = ERR_PTR(-ENXIO);
> > + else
> > + desc = ERR_PTR(-EPROBE_DEFER);
> > +
> > + goto out;
> > + }
> > +
> > + if (xlate_flags & OF_GPIO_ACTIVE_LOW)
> > + req_flags |= GPIOF_ACTIVE_LOW;
> > +
> > + if (of_property_read_bool(cfg_np, "input")) {
> > + req_flags |= GPIOF_DIR_IN;
> > + } else if (of_property_read_bool(cfg_np, "output-high")) {
> > + req_flags |= GPIOF_INIT_HIGH;
> > + } else if (!of_property_read_bool(cfg_np, "output-low")) {
> > + desc = ERR_PTR(-EINVAL);
> > + goto out;
> > + }
>
> That's why I would prefer a "direction" property instead of these 3
> ones: because if you have the following node:
>
> line_foo {
> gpios = <1 GPIO_ACTIVE_HIGH>;
> input;
> output-high;
> };
>
> Then this code will not trigger an error and will just configure the
> GPIO as input.
Understood.
>
> > +
> > + if (of_property_read_bool(cfg_np, "open-drain-line"))
> > + req_flags |= GPIOF_OPEN_DRAIN;
> > +
> > + if (of_property_read_bool(cfg_np, "open-source-line"))
> > + req_flags |= GPIOF_OPEN_DRAIN;
> > +
> > + if (name && of_property_read_string(cfg_np, "line-name", name))
> > + *name = cfg_np->name;
> > +
> > + if (flags)
> > + *flags = req_flags;
> > +
> > + desc = gg_data.out_gpio;
> > +
> > +out:
> > + of_node_put(cfg_np);
> > +
> > + return desc;
> > +}
> > +
> > +/**
> > * of_gpio_simple_xlate - translate gpio_spec to the GPIO number and flags
> > * @gc: pointer to the gpio_chip structure
> > * @np: device node of the GPIO chip
> > diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
> > index e8e98ca..b6f5bdb 100644
> > --- a/drivers/gpio/gpiolib.c
> > +++ b/drivers/gpio/gpiolib.c
> > @@ -55,6 +55,9 @@ static DEFINE_MUTEX(gpio_lookup_lock);
> > static LIST_HEAD(gpio_lookup_list);
> > LIST_HEAD(gpio_chips);
> >
> > +struct gpio_desc *__must_check gpiod_get_hog_index(struct device *dev,
> > + unsigned int idx);
> > +
> > static inline void desc_set_label(struct gpio_desc *d, const char *label)
> > {
> > d->label = label;
> > @@ -226,6 +229,8 @@ int gpiochip_add(struct gpio_chip *chip)
> > int status = 0;
> > unsigned id;
> > int base = chip->base;
> > + struct gpio_desc *desc;
> > + int i;
> >
> > if ((!gpio_is_valid(base) || !gpio_is_valid(base + chip->ngpio - 1))
> > && base >= 0) {
> > @@ -275,6 +280,16 @@ int gpiochip_add(struct gpio_chip *chip)
> > of_gpiochip_add(chip);
> > acpi_gpiochip_add(chip);
> >
> > + /*
> > + * Instantiate GPIO hogs
> > + * There shouldn't be mores hogs then gpio available on this chip
>
> s/then/than
Will fix.
>
> > + */
> > + for (i = 0; i < chip->ngpio; i++) {
> > + desc = gpiod_get_hog_index(chip->dev, i);
> > + if (IS_ERR(desc))
> > + break;
> > + }
>
> chip->ngpio? Isn't there a better way to know the number of phandles
> in your gpio-hogs property?
Maybe there is. I'll look into it.
>
> Also you may have an error returned either because you reached the end
> of the list, or because the hog configuration itself failed. In the
> latter case don't you want to continue to go through the list?
Understood.
>
> Finally your desc variable should be declared within this loop since
> it is not used elsewhere.
>
Understood.
> > +
> > if (status)
> > goto fail;
> >
> > @@ -1742,6 +1757,72 @@ struct gpio_desc *__must_check __gpiod_get_index_optional(struct device *dev,
> > EXPORT_SYMBOL_GPL(__gpiod_get_index_optional);
> >
> > /**
> > + * gpiod_get_hog_index - obtain a GPIO from a multi-index GPIO hog
> > + * @dev: GPIO consumer
> > + * @idx: index of the GPIO to obtain
> > + *
> > + * This should only be used by the gpiochip_add to request/set GPIO initial
> > + * configuration.
> > + *
> > + * Return a valid GPIO descriptor, or an IS_ERR() condition in case of error.
> > + */
> > +struct gpio_desc *__must_check gpiod_get_hog_index(struct device *dev,
> > + unsigned int idx)
> > +{
> > + struct gpio_desc *desc = NULL;
> > + int err;
> > + unsigned long flags;
> > + const char *name;
> > +
> > + /* Using device tree? */
> > + if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node)
> > + desc = of_get_gpio_hog(dev->of_node, idx, &name, &flags);
> > +
> > + if (!desc)
> > + return ERR_PTR(-ENOTSUPP);
> > + else if (IS_ERR(desc))
> > + return desc;
> > +
> > + dev_dbg(dev, "gpio-hog: GPIO:%d (%s) as %s%s\n",
> > + desc_to_gpio(desc), name, (flags&GPIOF_DIR_IN)?"input":"output",
> > + (flags&GPIOF_DIR_IN)?"":(flags&GPIOF_INIT_HIGH)?"/high":"/low");
> > +
>
> ...
I guess this means to remove the dev_dbg code?
>
> > + err = gpiod_request(desc, name);
> > + if (err)
> > + return ERR_PTR(err);
> > +
> > + if (flags & GPIOF_OPEN_DRAIN)
> > + set_bit(FLAG_OPEN_DRAIN, &desc->flags);
> > +
> > + if (flags & GPIOF_OPEN_SOURCE)
> > + set_bit(FLAG_OPEN_SOURCE, &desc->flags);
> > +
> > + if (flags & GPIOF_ACTIVE_LOW)
> > + set_bit(FLAG_ACTIVE_LOW, &desc->flags);
> > +
> > + if (flags & GPIOF_DIR_IN)
> > + err = gpiod_direction_input(desc);
> > + else
> > + err = gpiod_direction_output_raw(desc,
> > + (flags & GPIOF_INIT_HIGH) ? 1 : 0);
> > +
>
> This part of the code is very similar to what is found in
> __gpiod_get_index. Could you maybe try to extract the common code into
> its own function and call it from both sites instead of duplicating
> code?
Agreed.
Originally I was making use of gpio_request_one, but then I noticed it was move to the "_legacy" and would probably dissapear.
>
> > + if (err)
> > + goto free_gpio;
> > +
> > + if (flags & GPIOF_EXPORT) {
> > + err = gpiod_export(desc, flags & GPIOF_EXPORT_CHANGEABLE);
> > + if (err)
> > + goto free_gpio;
>
> Right now export is not possible so I don't think you need that block.
Unless the export feature is requested along with this pacth.
>
> > + }
> > +
> > + return desc;
> > +
> > +free_gpio:
> > + gpiod_free(desc);
> > + return ERR_PTR(err);
> > +}
> > +
> > +/**
> > * gpiod_put - dispose of a GPIO descriptor
> > * @desc: GPIO descriptor to dispose of
> > *
> > diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h
> > index 38fc050..52d154c 100644
> > --- a/include/linux/of_gpio.h
> > +++ b/include/linux/of_gpio.h
> > @@ -59,6 +59,9 @@ extern int of_gpio_simple_xlate(struct gpio_chip *gc,
> > const struct of_phandle_args *gpiospec,
> > u32 *flags);
> >
> > +extern struct gpio_desc *of_get_gpio_hog(struct device_node *np, int index,
> > + const char **name,
> > + unsigned long *flags);
>
> This function is gpiolib-private, therefore it should be declared in
> drivers/gpio/gpiolib.h alongside with the declaration of
> of_get_named_gpiod_flags.
Ah yes would be much better.
>
> If I understood the latest discussions correctly we might want to add
> an export (and named export) feature on top of this patch. Linus, am I
> correct to understand that you are not opposed to both features? In
> this case, we might want to go ahead with the merging of one of the
> named GPIOs patches, so that Jiri and Pantelis can implement export
> based on this patch.
--
To unsubscribe from this list: send the line "unsubscribe linux-gpio" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
WARNING: multiple messages have this Message-ID (diff)
From: Benoit Parrot <bparrot@ti.com>
To: Alexandre Courbot <gnurou@gmail.com>
Cc: Linus Walleij <linus.walleij@linaro.org>,
"linux-gpio@vger.kernel.org" <linux-gpio@vger.kernel.org>,
Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
"devicetree@vger.kernel.org" <devicetree@vger.kernel.org>,
Pantelis Antoniou <panto@antoniou-consulting.com>,
Jiri Prchal <jiri.prchal@aksignal.cz>
Subject: Re: [RFC Patch] gpio: add GPIO hogging mechanism
Date: Wed, 29 Oct 2014 11:21:05 -0500 [thread overview]
Message-ID: <20141029162105.GA29965@ti.com> (raw)
In-Reply-To: <CAAVeFuK4PaFbbYjUsvA-oO78P5qmQvyGqG+Ov4GLghoC=yPAoA@mail.gmail.com>
Alexandre,
Thanks for the feedback.
Alexandre Courbot <gnurou@gmail.com> wrote on Wed [2014-Oct-29 16:09:59 +0900]:
> Sorry for the delay in reviewing. Adding Jiri and Pantelis who might
> want to extend over this patch and thus will likely have interesting
> comments to make.
>
> On Wed, Oct 22, 2014 at 5:09 AM, Benoit Parrot <bparrot@ti.com> wrote:
> > Based on Boris Brezillion work this is a reworked patch
> > of his initial GPIO hogging mechanism.
> > This patch provides a way to initally configure specific GPIO
> > when the gpio controller is probe.
>
> Typo nit: s/probe/probed
Will fix.
>
> >
> > The actual DT scanning to collect the GPIO specific data is performed
> > as part of the gpiochip_add().
> >
> > The purpose of this is to allows specific GPIOs to be configured
> > without any driver specific code.
> > This particularly usueful because board design are getting
>
> s/suseful/useful
>
> > increassingly complex and given SoC pins can now have upward
>
> s/increassingly/increasingly
Will fix.
>
> > of 10 mux values a lot of connections are now dependent on
> > external IO muxes to switch various modes and combination.
> >
> > Specific drivers should not necessarily need to be aware of
> > what accounts to a specific board implementation. This board level
> > "description" should be best kept as part of the dts file.
> >
> > Signed-off-by: Benoit Parrot <bparrot@ti.com>
> > ---
> > Documentation/devicetree/bindings/gpio/gpio.txt | 33 +++++++++
> > drivers/gpio/gpiolib-of.c | 99 +++++++++++++++++++++++++
> > drivers/gpio/gpiolib.c | 81 ++++++++++++++++++++
> > include/linux/of_gpio.h | 11 +++
> > 4 files changed, 224 insertions(+)
> >
> > diff --git a/Documentation/devicetree/bindings/gpio/gpio.txt b/Documentation/devicetree/bindings/gpio/gpio.txt
> > index 3fb8f53..a9700d8 100644
> > --- a/Documentation/devicetree/bindings/gpio/gpio.txt
> > +++ b/Documentation/devicetree/bindings/gpio/gpio.txt
>
> Note: changes to DT bindings documentation should generally come as a
> separate patch.
Ok.
>
> > @@ -103,6 +103,26 @@ Every GPIO controller node must contain both an empty "gpio-controller"
> > property, and a #gpio-cells integer property, which indicates the number of
> > cells in a gpio-specifier.
> >
> > +It might contain GPIO hog definitions. GPIO hogging is a mechanism providing
> > +automatic GPIO request and configuration as part of the gpio-controller's
> > +driver probe function.
> > +
> > +Each GPIO hog definition is represented as a child node of the GPIO controller.
> > +Required properties:
> > +- gpios: store the gpio information (id, flags, ...). Shall contain the
> > + number of cells specified in its parent node (GPIO controller node).
>
> If would be nice to be able to specify several GPIO references to that
> they can be all set to the same configuration in one row instead of
> requiring one node each.
>
> > +- input: a property specifying to set the GPIO direction as input.
> > +- output-high: a property specifying to set the GPIO direction to output with
> > + the value high.
> > +- output-low: a property specifying to set the GPIO direction to output with
> > + the value low.
>
> Wouldn't a "direction" property taking one of the values "input",
> "output-low" or "output-high" be easier to parse and generally
> clearer?
I guess here you mean something like this:
...
line_y: line_y {
gpios = <15 0>;
direction = <output-low>;
};
Not sure about easier to parse, but it would be clearer.
>
> > +
> > +Optional properties:
> > +- line-name: the GPIO label name. If not present the node name is used.
>
> I guess we also could use this for naming the GPIO during its export
> if we decide to allow this in a near-future patch.
>
Right.
> > +
> > +A GPIO controller can request GPIO hogs using the "gpio-hogs" property, which
> > +encodes a list of requested GPIO hogs.
> > +
> > Example of two SOC GPIO banks defined as gpio-controller nodes:
> >
> > qe_pio_a: gpio-controller@1400 {
> > @@ -110,6 +130,19 @@ Example of two SOC GPIO banks defined as gpio-controller nodes:
> > reg = <0x1400 0x18>;
> > gpio-controller;
> > #gpio-cells = <2>;
> > + gpio-hogs = <&line_b>;
> > +
> > + /* line_a hog is defined but not enabled in this example*/
> > + line_a: line_a {
> > + gpios = <5 0>;
> > + input;
> > + };
> > +
> > + line_b: line_b {
> > + gpios = <6 0>;
> > + output-low;
> > + line-name = "foo-bar-gpio";
> > + };
>
> I think it might be good to group the hog nodes such as to allow
> complex configurations to be set in one go, à la pinmux:
See below.
>
> gpio-controller;
> #gpio-cells = <2>;
> + gpio-hogs = <&line_b>;
> +
> + line_a: line_a {
> + line_a {
> + gpios = <5 0>;
> + input;
> + };
> + line_c {
> + gpios = <7 0>;
> + inputl
> + };
> + };
> +
> + line_b: line_b {
> + line_b {
> + gpios = <6 0>;
> + output-low;
> + line-name = "foo-bar-gpio";
> + };
> + };
>
> Here if you want to enable the first configuration you don't need to
> specify all the lines one by one, you just need to select the right
> group.
>
> I wonder if such usage of child nodes could not interfere with GPIO
> drivers (existing or to be) that need to use child nodes for other
> purposes. Right now there is no way to distinguish a hog node from a
> node that serves another purpose, and that might become a problem in
> the future. Not sure how that should be addressed though - maybe by
> enforcing a "-hog" suffix for the group nodes, e.g. line_a-hog?
> Comments from people more experienced with DT would be nice.
I did consider a "pinmux" flavored format (not sure how hard to parse it would be).
It would allow grouping if nothing else.
/* Line syntax: line_name <gpio# flags> direction-value [export] */
gpio-hogs = <&group_y>;
group_y: group_y {
gpio-hogs-group = <
line_x <15 0> output-low
line_y <16 0> output-high export
line_z <17 0> input
>;
};
>
> > };
> >
> > qe_pio_e: gpio-controller@1460 {
> > diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
> > index 604dbe6..7308dfc 100644
> > --- a/drivers/gpio/gpiolib-of.c
> > +++ b/drivers/gpio/gpiolib-of.c
> > @@ -111,6 +111,105 @@ int of_get_named_gpio_flags(struct device_node *np, const char *list_name,
> > EXPORT_SYMBOL(of_get_named_gpio_flags);
> >
> > /**
> > + * of_get_gpio_hog() - Get a GPIO hog descriptor, names and flags for GPIO API
> > + * @np: device node to get GPIO from
> > + * @index: index of the GPIO
> > + * @name: GPIO line name
> > + * @flags: a flags pointer to fill in
> > + *
> > + * Returns GPIO descriptor to use with Linux GPIO API, or one of the errno
> > + * value on the error condition.
> > + */
> > +struct gpio_desc *of_get_gpio_hog(struct device_node *np, int index,
> > + const char **name, unsigned long *flags)
> > +{
> > + struct device_node *cfg_np, *chip_np;
> > + enum of_gpio_flags xlate_flags;
> > + unsigned long req_flags = 0;
> > + struct gpio_desc *desc;
> > + struct gg_data gg_data = {
> > + .flags = &xlate_flags,
> > + .out_gpio = NULL,
> > + };
> > + u32 tmp;
> > + int i;
> > + int ret;
> > +
> > + cfg_np = of_parse_phandle(np, "gpio-hogs", index);
> > + if (!cfg_np)
> > + return ERR_PTR(-EINVAL);
> > +
> > + chip_np = cfg_np->parent;
> > + if (!chip_np) {
> > + desc = ERR_PTR(-EINVAL);
> > + goto out;
> > + }
> > +
> > + ret = of_property_read_u32(chip_np, "#gpio-cells", &tmp);
> > + if (ret) {
> > + desc = ERR_PTR(ret);
> > + goto out;
> > + }
> > +
> > + if (tmp > MAX_PHANDLE_ARGS) {
> > + desc = ERR_PTR(-EINVAL);
> > + goto out;
> > + }
> > +
> > + gg_data.gpiospec.args_count = tmp;
> > + gg_data.gpiospec.np = chip_np;
> > + for (i = 0; i < tmp; i++) {
> > + ret = of_property_read_u32(cfg_np, "gpios",
> > + &gg_data.gpiospec.args[i]);
> > + if (ret) {
> > + desc = ERR_PTR(ret);
> > + goto out;
> > + }
> > + }
> > +
> > + gpiochip_find(&gg_data, of_gpiochip_find_and_xlate);
> > + if (!gg_data.out_gpio) {
> > + if (cfg_np->parent == np)
> > + desc = ERR_PTR(-ENXIO);
> > + else
> > + desc = ERR_PTR(-EPROBE_DEFER);
> > +
> > + goto out;
> > + }
> > +
> > + if (xlate_flags & OF_GPIO_ACTIVE_LOW)
> > + req_flags |= GPIOF_ACTIVE_LOW;
> > +
> > + if (of_property_read_bool(cfg_np, "input")) {
> > + req_flags |= GPIOF_DIR_IN;
> > + } else if (of_property_read_bool(cfg_np, "output-high")) {
> > + req_flags |= GPIOF_INIT_HIGH;
> > + } else if (!of_property_read_bool(cfg_np, "output-low")) {
> > + desc = ERR_PTR(-EINVAL);
> > + goto out;
> > + }
>
> That's why I would prefer a "direction" property instead of these 3
> ones: because if you have the following node:
>
> line_foo {
> gpios = <1 GPIO_ACTIVE_HIGH>;
> input;
> output-high;
> };
>
> Then this code will not trigger an error and will just configure the
> GPIO as input.
Understood.
>
> > +
> > + if (of_property_read_bool(cfg_np, "open-drain-line"))
> > + req_flags |= GPIOF_OPEN_DRAIN;
> > +
> > + if (of_property_read_bool(cfg_np, "open-source-line"))
> > + req_flags |= GPIOF_OPEN_DRAIN;
> > +
> > + if (name && of_property_read_string(cfg_np, "line-name", name))
> > + *name = cfg_np->name;
> > +
> > + if (flags)
> > + *flags = req_flags;
> > +
> > + desc = gg_data.out_gpio;
> > +
> > +out:
> > + of_node_put(cfg_np);
> > +
> > + return desc;
> > +}
> > +
> > +/**
> > * of_gpio_simple_xlate - translate gpio_spec to the GPIO number and flags
> > * @gc: pointer to the gpio_chip structure
> > * @np: device node of the GPIO chip
> > diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
> > index e8e98ca..b6f5bdb 100644
> > --- a/drivers/gpio/gpiolib.c
> > +++ b/drivers/gpio/gpiolib.c
> > @@ -55,6 +55,9 @@ static DEFINE_MUTEX(gpio_lookup_lock);
> > static LIST_HEAD(gpio_lookup_list);
> > LIST_HEAD(gpio_chips);
> >
> > +struct gpio_desc *__must_check gpiod_get_hog_index(struct device *dev,
> > + unsigned int idx);
> > +
> > static inline void desc_set_label(struct gpio_desc *d, const char *label)
> > {
> > d->label = label;
> > @@ -226,6 +229,8 @@ int gpiochip_add(struct gpio_chip *chip)
> > int status = 0;
> > unsigned id;
> > int base = chip->base;
> > + struct gpio_desc *desc;
> > + int i;
> >
> > if ((!gpio_is_valid(base) || !gpio_is_valid(base + chip->ngpio - 1))
> > && base >= 0) {
> > @@ -275,6 +280,16 @@ int gpiochip_add(struct gpio_chip *chip)
> > of_gpiochip_add(chip);
> > acpi_gpiochip_add(chip);
> >
> > + /*
> > + * Instantiate GPIO hogs
> > + * There shouldn't be mores hogs then gpio available on this chip
>
> s/then/than
Will fix.
>
> > + */
> > + for (i = 0; i < chip->ngpio; i++) {
> > + desc = gpiod_get_hog_index(chip->dev, i);
> > + if (IS_ERR(desc))
> > + break;
> > + }
>
> chip->ngpio? Isn't there a better way to know the number of phandles
> in your gpio-hogs property?
Maybe there is. I'll look into it.
>
> Also you may have an error returned either because you reached the end
> of the list, or because the hog configuration itself failed. In the
> latter case don't you want to continue to go through the list?
Understood.
>
> Finally your desc variable should be declared within this loop since
> it is not used elsewhere.
>
Understood.
> > +
> > if (status)
> > goto fail;
> >
> > @@ -1742,6 +1757,72 @@ struct gpio_desc *__must_check __gpiod_get_index_optional(struct device *dev,
> > EXPORT_SYMBOL_GPL(__gpiod_get_index_optional);
> >
> > /**
> > + * gpiod_get_hog_index - obtain a GPIO from a multi-index GPIO hog
> > + * @dev: GPIO consumer
> > + * @idx: index of the GPIO to obtain
> > + *
> > + * This should only be used by the gpiochip_add to request/set GPIO initial
> > + * configuration.
> > + *
> > + * Return a valid GPIO descriptor, or an IS_ERR() condition in case of error.
> > + */
> > +struct gpio_desc *__must_check gpiod_get_hog_index(struct device *dev,
> > + unsigned int idx)
> > +{
> > + struct gpio_desc *desc = NULL;
> > + int err;
> > + unsigned long flags;
> > + const char *name;
> > +
> > + /* Using device tree? */
> > + if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node)
> > + desc = of_get_gpio_hog(dev->of_node, idx, &name, &flags);
> > +
> > + if (!desc)
> > + return ERR_PTR(-ENOTSUPP);
> > + else if (IS_ERR(desc))
> > + return desc;
> > +
> > + dev_dbg(dev, "gpio-hog: GPIO:%d (%s) as %s%s\n",
> > + desc_to_gpio(desc), name, (flags&GPIOF_DIR_IN)?"input":"output",
> > + (flags&GPIOF_DIR_IN)?"":(flags&GPIOF_INIT_HIGH)?"/high":"/low");
> > +
>
> ...
I guess this means to remove the dev_dbg code?
>
> > + err = gpiod_request(desc, name);
> > + if (err)
> > + return ERR_PTR(err);
> > +
> > + if (flags & GPIOF_OPEN_DRAIN)
> > + set_bit(FLAG_OPEN_DRAIN, &desc->flags);
> > +
> > + if (flags & GPIOF_OPEN_SOURCE)
> > + set_bit(FLAG_OPEN_SOURCE, &desc->flags);
> > +
> > + if (flags & GPIOF_ACTIVE_LOW)
> > + set_bit(FLAG_ACTIVE_LOW, &desc->flags);
> > +
> > + if (flags & GPIOF_DIR_IN)
> > + err = gpiod_direction_input(desc);
> > + else
> > + err = gpiod_direction_output_raw(desc,
> > + (flags & GPIOF_INIT_HIGH) ? 1 : 0);
> > +
>
> This part of the code is very similar to what is found in
> __gpiod_get_index. Could you maybe try to extract the common code into
> its own function and call it from both sites instead of duplicating
> code?
Agreed.
Originally I was making use of gpio_request_one, but then I noticed it was move to the "_legacy" and would probably dissapear.
>
> > + if (err)
> > + goto free_gpio;
> > +
> > + if (flags & GPIOF_EXPORT) {
> > + err = gpiod_export(desc, flags & GPIOF_EXPORT_CHANGEABLE);
> > + if (err)
> > + goto free_gpio;
>
> Right now export is not possible so I don't think you need that block.
Unless the export feature is requested along with this pacth.
>
> > + }
> > +
> > + return desc;
> > +
> > +free_gpio:
> > + gpiod_free(desc);
> > + return ERR_PTR(err);
> > +}
> > +
> > +/**
> > * gpiod_put - dispose of a GPIO descriptor
> > * @desc: GPIO descriptor to dispose of
> > *
> > diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h
> > index 38fc050..52d154c 100644
> > --- a/include/linux/of_gpio.h
> > +++ b/include/linux/of_gpio.h
> > @@ -59,6 +59,9 @@ extern int of_gpio_simple_xlate(struct gpio_chip *gc,
> > const struct of_phandle_args *gpiospec,
> > u32 *flags);
> >
> > +extern struct gpio_desc *of_get_gpio_hog(struct device_node *np, int index,
> > + const char **name,
> > + unsigned long *flags);
>
> This function is gpiolib-private, therefore it should be declared in
> drivers/gpio/gpiolib.h alongside with the declaration of
> of_get_named_gpiod_flags.
Ah yes would be much better.
>
> If I understood the latest discussions correctly we might want to add
> an export (and named export) feature on top of this patch. Linus, am I
> correct to understand that you are not opposed to both features? In
> this case, we might want to go ahead with the merging of one of the
> named GPIOs patches, so that Jiri and Pantelis can implement export
> based on this patch.
next prev parent reply other threads:[~2014-10-29 16:21 UTC|newest]
Thread overview: 53+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-10-21 20:09 [RFC Patch] gpio: add GPIO hogging mechanism Benoit Parrot
2014-10-21 20:09 ` Benoit Parrot
2014-10-29 7:09 ` Alexandre Courbot
2014-10-29 7:09 ` Alexandre Courbot
2014-10-29 16:21 ` Benoit Parrot [this message]
2014-10-29 16:21 ` Benoit Parrot
2014-10-30 0:29 ` Alexandre Courbot
2014-11-14 9:19 ` Linus Walleij
2014-11-14 10:22 ` Maxime Ripard
2014-10-29 8:53 ` Pantelis Antoniou
2014-10-29 8:53 ` Pantelis Antoniou
2014-10-29 16:34 ` Benoit Parrot
2014-10-29 16:34 ` Benoit Parrot
2014-10-29 16:42 ` Pantelis Antoniou
2014-10-29 19:36 ` Benoit Parrot
2014-10-29 19:36 ` Benoit Parrot
2014-10-30 0:31 ` Alexandre Courbot
2014-10-30 0:31 ` Alexandre Courbot
2014-11-03 9:43 ` Linus Walleij
2014-11-03 9:43 ` Linus Walleij
2014-10-29 10:45 ` Maxime Ripard
2014-10-29 16:41 ` Benoit Parrot
2014-10-29 16:41 ` Benoit Parrot
2014-10-29 16:47 ` Maxime Ripard
2014-10-29 23:09 ` Benoit Parrot
2014-10-29 23:09 ` Benoit Parrot
2014-10-30 17:16 ` Maxime Ripard
2014-11-03 9:59 ` Linus Walleij
2014-11-04 0:38 ` Benoit Parrot
[not found] ` <20141104003827.GA24005-l0cyMroinI0@public.gmane.org>
2014-11-14 9:16 ` Linus Walleij
2014-11-14 9:16 ` Linus Walleij
-- strict thread matches above, loose matches on Subject: below --
2014-10-06 11:58 [GIT PULL] bulk pin control changes for v3.18 Linus Walleij
2014-10-06 15:37 ` [RFC PATCH] gpio: add GPIO hogging mechanism Benoit Parrot
2014-10-06 15:37 ` Benoit Parrot
2014-10-21 10:55 ` Linus Walleij
2013-12-19 14:34 Boris BREZILLON
[not found] ` <1387463671-1164-1-git-send-email-b.brezillon-ZNYIgs0QAGpBDgjK7y7TUQ@public.gmane.org>
2013-12-19 14:34 ` Boris BREZILLON
2013-12-19 14:34 ` Boris BREZILLON
2013-12-19 16:41 ` Greg Kroah-Hartman
2013-12-19 16:47 ` Felipe Balbi
2013-12-19 16:47 ` Felipe Balbi
2013-12-19 17:18 ` boris brezillon
2013-12-19 18:22 ` Felipe Balbi
2013-12-19 18:22 ` Felipe Balbi
2013-12-30 9:48 ` boris brezillon
2014-01-08 9:45 ` Linus Walleij
[not found] ` <20131219164109.GB27409-U8xfFu+wG4EAvxtiuMwx3w@public.gmane.org>
2013-12-19 17:13 ` boris brezillon
2013-12-19 17:13 ` boris brezillon
2014-09-20 21:37 ` Ben Gamari
2014-09-20 22:26 ` Ben Gamari
2014-01-08 9:37 ` Linus Walleij
2014-01-08 10:18 ` boris brezillon
2014-01-14 10:27 ` Linus Walleij
2014-10-02 15:47 ` Benoit Parrot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20141029162105.GA29965@ti.com \
--to=bparrot@ti.com \
--cc=devicetree@vger.kernel.org \
--cc=gnurou@gmail.com \
--cc=jiri.prchal@aksignal.cz \
--cc=linus.walleij@linaro.org \
--cc=linux-gpio@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=panto@antoniou-consulting.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.