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 */
439494static 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
535599static 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