Skip to content

Commit 81674be

Browse files
andy-shevBartosz Golaszewski
authored andcommitted
gpio: aggregator: Set up a parser of delay line parameters
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 a signal delay line. Set up a parser to support it. Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be> Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Tested-by: Alexander Stein <alexander.stein@ew.tq-group.com> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
1 parent b466622 commit 81674be

1 file changed

Lines changed: 70 additions & 2 deletions

File tree

drivers/gpio/gpio-aggregator.c

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/mutex.h>
1919
#include <linux/overflow.h>
2020
#include <linux/platform_device.h>
21+
#include <linux/property.h>
2122
#include <linux/slab.h>
2223
#include <linux/spinlock.h>
2324
#include <linux/string.h>
@@ -422,13 +423,67 @@ static int gpio_fwd_to_irq(struct gpio_chip *chip, unsigned int offset)
422423
return gpiod_to_irq(fwd->descs[offset]);
423424
}
424425

426+
/*
427+
* The GPIO delay provides a way to configure platform specific delays
428+
* for the GPIO ramp-up or ramp-down delays. This can serve the following
429+
* purposes:
430+
* - Open-drain output using an RC filter
431+
*/
432+
#define FWD_FEATURE_DELAY BIT(0)
433+
434+
#ifdef CONFIG_OF_GPIO
435+
static int gpiochip_fwd_delay_of_xlate(struct gpio_chip *chip,
436+
const struct of_phandle_args *gpiospec,
437+
u32 *flags)
438+
{
439+
struct gpiochip_fwd *fwd = gpiochip_get_data(chip);
440+
struct gpiochip_fwd_timing *timings;
441+
u32 line;
442+
443+
if (gpiospec->args_count != chip->of_gpio_n_cells)
444+
return -EINVAL;
445+
446+
line = gpiospec->args[0];
447+
if (line >= chip->ngpio)
448+
return -EINVAL;
449+
450+
timings = &fwd->delay_timings[line];
451+
timings->ramp_up_us = gpiospec->args[1];
452+
timings->ramp_down_us = gpiospec->args[2];
453+
454+
return line;
455+
}
456+
457+
static int gpiochip_fwd_setup_delay_line(struct device *dev, struct gpio_chip *chip,
458+
struct gpiochip_fwd *fwd)
459+
{
460+
fwd->delay_timings = devm_kcalloc(dev, chip->ngpio,
461+
sizeof(*fwd->delay_timings),
462+
GFP_KERNEL);
463+
if (!fwd->delay_timings)
464+
return -ENOMEM;
465+
466+
chip->of_xlate = gpiochip_fwd_delay_of_xlate;
467+
chip->of_gpio_n_cells = 3;
468+
469+
return 0;
470+
}
471+
#else
472+
static int gpiochip_fwd_setup_delay_line(struct device *dev, struct gpio_chip *chip,
473+
struct gpiochip_fwd *fwd)
474+
{
475+
return 0;
476+
}
477+
#endif /* !CONFIG_OF_GPIO */
478+
425479
/**
426480
* gpiochip_fwd_create() - Create a new GPIO forwarder
427481
* @dev: Parent device pointer
428482
* @ngpios: Number of GPIOs in the forwarder.
429483
* @descs: Array containing the GPIO descriptors to forward to.
430484
* This array must contain @ngpios entries, and must not be deallocated
431485
* before the forwarder has been destroyed again.
486+
* @features: Bitwise ORed features as defined with FWD_FEATURE_*.
432487
*
433488
* This function creates a new gpiochip, which forwards all GPIO operations to
434489
* the passed GPIO descriptors.
@@ -438,7 +493,8 @@ static int gpio_fwd_to_irq(struct gpio_chip *chip, unsigned int offset)
438493
*/
439494
static struct gpiochip_fwd *gpiochip_fwd_create(struct device *dev,
440495
unsigned int ngpios,
441-
struct gpio_desc *descs[])
496+
struct gpio_desc *descs[],
497+
unsigned long features)
442498
{
443499
const char *label = dev_name(dev);
444500
struct gpiochip_fwd *fwd;
@@ -491,6 +547,12 @@ static struct gpiochip_fwd *gpiochip_fwd_create(struct device *dev,
491547
else
492548
spin_lock_init(&fwd->slock);
493549

550+
if (features & FWD_FEATURE_DELAY) {
551+
error = gpiochip_fwd_setup_delay_line(dev, chip, fwd);
552+
if (error)
553+
return ERR_PTR(error);
554+
}
555+
494556
error = devm_gpiochip_add_data(dev, chip, fwd);
495557
if (error)
496558
return ERR_PTR(error);
@@ -508,6 +570,7 @@ static int gpio_aggregator_probe(struct platform_device *pdev)
508570
struct device *dev = &pdev->dev;
509571
struct gpio_desc **descs;
510572
struct gpiochip_fwd *fwd;
573+
unsigned long features;
511574
int i, n;
512575

513576
n = gpiod_count(dev, NULL);
@@ -524,7 +587,8 @@ static int gpio_aggregator_probe(struct platform_device *pdev)
524587
return PTR_ERR(descs[i]);
525588
}
526589

527-
fwd = gpiochip_fwd_create(dev, n, descs);
590+
features = (uintptr_t)device_get_match_data(dev);
591+
fwd = gpiochip_fwd_create(dev, n, descs, features);
528592
if (IS_ERR(fwd))
529593
return PTR_ERR(fwd);
530594

@@ -533,6 +597,10 @@ static int gpio_aggregator_probe(struct platform_device *pdev)
533597
}
534598

535599
static const struct of_device_id gpio_aggregator_dt_ids[] = {
600+
{
601+
.compatible = "gpio-delay",
602+
.data = (void *)FWD_FEATURE_DELAY,
603+
},
536604
/*
537605
* Add GPIO-operated devices controlled from userspace below,
538606
* or use "driver_override" in sysfs.

0 commit comments

Comments
 (0)