All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alexander Stein <alexander.stein@ew.tq-group.com>
To: Andy Shevchenko <andriy.shevchenko@linux.intel.com>,
	"linux-gpio@vger.kernel.org" <linux-gpio@vger.kernel.org>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Geert Uytterhoeven <geert@glider.be>,
	Linus Walleij <linus.walleij@linaro.org>,
	Bartosz Golaszewski <brgl@bgdev.pl>,
	Andy Shevchenko <andy@kernel.org>,
	"linux@ew.tq-group.com" <linux@ew.tq-group.com>
Subject: Re: [rfc, rft, PATCH v1 1/1] gpio: aggregator: Introduce delay support for individual output pins
Date: Fri, 09 Jun 2023 08:40:15 +0200	[thread overview]
Message-ID: <4808746.GXAFRqVoOG@steina-w> (raw)
In-Reply-To: <20230608162130.55015-1-andriy.shevchenko@linux.intel.com>

Am Donnerstag, 8. Juni 2023, 18:23:08 CEST schrieb Andy Shevchenko:
> The aggregator mode can also handle properties of the platform, that
> do not belong to the GPIO controller itself. One of such a property
> is signal delay line. Intdoduce support of it.
> 
> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> ---
> 
> I don't like the idea of gpio-delay or similar. We have already GPIO
> aggregator that incorporates the GPIO proxy / forwarder functionality.
> 
> This one is RFC because:
> 1) just compile tested;
> 2) has obvious issues with CONFIG_OF_GPIO;
> 3) contains ~5 patches in a single change for now;
> 4) requires additional work with blocking sysfs for this;
> 5) requires some DT bindings work;
> 6) ...whatever I forgot...
> 
> Any comments are appreciated, and tests are esp. welcome!

FWIW: Replacing CONFIG_GPIO_DELAY=m with CONFIG_GPIO_AGGREGATOR=m works as 
well on my platform.
But I'm not sure if it's worth the additional complexity for gpio-aggregator 
to replace gpio-delay.

Regards,
Alexander

>  drivers/gpio/gpio-aggregator.c | 84 ++++++++++++++++++++++++++++++----
>  1 file changed, 74 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/gpio/gpio-aggregator.c b/drivers/gpio/gpio-aggregator.c
> index 20a686f12df7..802d123f0188 100644
> --- a/drivers/gpio/gpio-aggregator.c
> +++ b/drivers/gpio/gpio-aggregator.c
> @@ -10,12 +10,14 @@
>  #include <linux/bitmap.h>
>  #include <linux/bitops.h>
>  #include <linux/ctype.h>
> +#include <linux/delay.h>
>  #include <linux/idr.h>
>  #include <linux/kernel.h>
>  #include <linux/module.h>
>  #include <linux/mutex.h>
>  #include <linux/overflow.h>
>  #include <linux/platform_device.h>
> +#include <linux/property.h>
>  #include <linux/slab.h>
>  #include <linux/spinlock.h>
>  #include <linux/string.h>
> @@ -239,6 +241,11 @@ static void __exit gpio_aggregator_remove_all(void)
>   *  GPIO Forwarder
>   */
> 
> +struct gpiochip_fwd_timing {
> +	unsigned long ramp_up_us;
> +	unsigned long ramp_down_us;
> +};
> +
>  struct gpiochip_fwd {
>  	struct gpio_chip chip;
>  	struct gpio_desc **descs;
> @@ -246,6 +253,7 @@ struct gpiochip_fwd {
>  		struct mutex mlock;	/* protects tmp[] if can_sleep */
>  		spinlock_t slock;	/* protects tmp[] if !can_sleep */
>  	};
> +	struct gpiochip_fwd_timing *delay_timings;
>  	unsigned long tmp[];		/* values and descs for multiple ops 
*/
>  };
> 
> @@ -333,11 +341,28 @@ static int gpio_fwd_get_multiple_locked(struct
> gpio_chip *chip, static void gpio_fwd_set(struct gpio_chip *chip, unsigned
> int offset, int value) {
>  	struct gpiochip_fwd *fwd = gpiochip_get_data(chip);
> +	const struct gpiochip_fwd_timing *delay_timings;
> +	struct gpio_desc *desc = fwd->descs[offset];
> +	bool is_active_low = gpiod_is_active_low(desc);
> +	bool ramp_up;
> 
> -	if (chip->can_sleep)
> -		gpiod_set_value_cansleep(fwd->descs[offset], value);
> -	else
> -		gpiod_set_value(fwd->descs[offset], value);
> +	delay_timings = &fwd->delay_timings[offset];
> +	ramp_up = (!is_active_low && value) || (is_active_low && !value);
> +	if (chip->can_sleep) {
> +		gpiod_set_value_cansleep(desc, value);
> +
> +		if (ramp_up && delay_timings->ramp_up_us)
> +			fsleep(delay_timings->ramp_up_us);
> +		if (!ramp_up && delay_timings->ramp_down_us)
> +			fsleep(delay_timings->ramp_down_us);
> +	} else {
> +		gpiod_set_value(desc, value);
> +
> +		if (ramp_up && delay_timings->ramp_up_us)
> +			udelay(delay_timings->ramp_up_us);
> +		if (!ramp_up && delay_timings->ramp_down_us)
> +			udelay(delay_timings->ramp_down_us);
> +	}
>  }
> 
>  static void gpio_fwd_set_multiple(struct gpiochip_fwd *fwd, unsigned long
> *mask, @@ -390,6 +415,28 @@ static int gpio_fwd_to_irq(struct gpio_chip
> *chip, unsigned int offset) return gpiod_to_irq(fwd->descs[offset]);
>  }
> 
> +static int gpiochip_fwd_delay_of_xlate(struct gpio_chip *chip,
> +				       const struct of_phandle_args 
*gpiospec,
> +				       u32 *flags)
> +{
> +	struct gpiochip_fwd *fwd = gpiochip_get_data(chip);
> +	struct gpiochip_fwd_timing *timings;
> +	u32 line;
> +
> +	if (gpiospec->args_count != chip->of_gpio_n_cells)
> +		return -EINVAL;
> +
> +	line = gpiospec->args[0];
> +	if (line >= chip->ngpio)
> +		return -EINVAL;
> +
> +	timings = &fwd->delay_timings[line];
> +	timings->ramp_up_us = gpiospec->args[1];
> +	timings->ramp_down_us = gpiospec->args[2];
> +
> +	return line;
> +}
> +
>  /**
>   * gpiochip_fwd_create() - Create a new GPIO forwarder
>   * @dev: Parent device pointer
> @@ -397,6 +444,7 @@ static int gpio_fwd_to_irq(struct gpio_chip *chip,
> unsigned int offset) * @descs: Array containing the GPIO descriptors to
> forward to.
>   *         This array must contain @ngpios entries, and must not be
> deallocated *         before the forwarder has been destroyed again.
> + * @delay: True if the pins have an external delay line.
>   *
>   * This function creates a new gpiochip, which forwards all GPIO operations
> to * the passed GPIO descriptors.
> @@ -406,7 +454,8 @@ static int gpio_fwd_to_irq(struct gpio_chip *chip,
> unsigned int offset) */
>  static struct gpiochip_fwd *gpiochip_fwd_create(struct device *dev,
>  						unsigned int 
ngpios,
> -						struct gpio_desc 
*descs[])
> +						struct gpio_desc 
*descs[],
> +						bool delay)
>  {
>  	const char *label = dev_name(dev);
>  	struct gpiochip_fwd *fwd;
> @@ -459,6 +508,17 @@ static struct gpiochip_fwd *gpiochip_fwd_create(struct
> device *dev, else
>  		spin_lock_init(&fwd->slock);
> 
> +	if (delay) {
> +		fwd->delay_timings = devm_kcalloc(dev, ngpios,
> +						  sizeof(*fwd-
>delay_timings),
> +						  GFP_KERNEL);
> +		if (!fwd->delay_timings)
> +			return ERR_PTR(-ENOMEM);
> +
> +		chip->of_xlate = gpiochip_fwd_delay_of_xlate;
> +		chip->of_gpio_n_cells = 3;
> +	}
> +
>  	error = devm_gpiochip_add_data(dev, chip, fwd);
>  	if (error)
>  		return ERR_PTR(error);
> @@ -476,6 +536,7 @@ static int gpio_aggregator_probe(struct platform_device
> *pdev) struct device *dev = &pdev->dev;
>  	struct gpio_desc **descs;
>  	struct gpiochip_fwd *fwd;
> +	bool delay;
>  	int i, n;
> 
>  	n = gpiod_count(dev, NULL);
> @@ -492,7 +553,9 @@ static int gpio_aggregator_probe(struct platform_device
> *pdev) return PTR_ERR(descs[i]);
>  	}
> 
> -	fwd = gpiochip_fwd_create(dev, n, descs);
> +	delay = fwnode_device_is_compatible(dev_fwnode(dev), "gpio-delay");
> +
> +	fwd = gpiochip_fwd_create(dev, n, descs, delay);
>  	if (IS_ERR(fwd))
>  		return PTR_ERR(fwd);
> 
> @@ -500,23 +563,24 @@ static int gpio_aggregator_probe(struct
> platform_device *pdev) return 0;
>  }
> 
> -#ifdef CONFIG_OF
>  static const struct of_device_id gpio_aggregator_dt_ids[] = {
>  	/*
>  	 * Add GPIO-operated devices controlled from userspace below,
> -	 * or use "driver_override" in sysfs
> +	 * or use "driver_override" in sysfs.
>  	 */
> +	{
> +		.compatible = "gpio-delay",
> +	},
>  	{}
>  };
>  MODULE_DEVICE_TABLE(of, gpio_aggregator_dt_ids);
> -#endif
> 
>  static struct platform_driver gpio_aggregator_driver = {
>  	.probe = gpio_aggregator_probe,
>  	.driver = {
>  		.name = DRV_NAME,
>  		.groups = gpio_aggregator_groups,
> -		.of_match_table = of_match_ptr(gpio_aggregator_dt_ids),
> +		.of_match_table = gpio_aggregator_dt_ids,
>  	},
>  };


-- 
TQ-Systems GmbH | Mühlstraße 2, Gut Delling | 82229 Seefeld, Germany
Amtsgericht München, HRB 105018
Geschäftsführer: Detlef Schneider, Rüdiger Stahl, Stefan Schneider
http://www.tq-group.com/



  parent reply	other threads:[~2023-06-09  6:40 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-06-08 16:21 [rfc, rft, PATCH v1 1/1] gpio: aggregator: Introduce delay support for individual output pins Andy Shevchenko
2023-06-08 19:32 ` kernel test robot
2023-06-08 19:43 ` kernel test robot
2023-06-09  6:40 ` Alexander Stein [this message]
2023-06-12 17:30   ` Andy Shevchenko
2023-06-09  7:11 ` Geert Uytterhoeven
2023-06-12 17:32   ` Andy Shevchenko
2023-06-09  7:50 ` Linus Walleij
2023-06-12 17:34   ` Andy Shevchenko

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=4808746.GXAFRqVoOG@steina-w \
    --to=alexander.stein@ew.tq-group.com \
    --cc=andriy.shevchenko@linux.intel.com \
    --cc=andy@kernel.org \
    --cc=brgl@bgdev.pl \
    --cc=geert@glider.be \
    --cc=linus.walleij@linaro.org \
    --cc=linux-gpio@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@ew.tq-group.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.