Skip to content

Commit b466622

Browse files
andy-shevBartosz Golaszewski
authored andcommitted
gpio: aggregator: Support delay for setting up individual GPIOs
In some cases the GPIO may require an additional delay after setting its value. Add support for that into the GPIO forwarder code. This will be fully enabled for use in the following changes. 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 b89a9e9 commit b466622

1 file changed

Lines changed: 31 additions & 0 deletions

File tree

drivers/gpio/gpio-aggregator.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <linux/bitmap.h>
1111
#include <linux/bitops.h>
1212
#include <linux/ctype.h>
13+
#include <linux/delay.h>
1314
#include <linux/idr.h>
1415
#include <linux/kernel.h>
1516
#include <linux/mod_devicetable.h>
@@ -240,13 +241,19 @@ static void __exit gpio_aggregator_remove_all(void)
240241
* GPIO Forwarder
241242
*/
242243

244+
struct gpiochip_fwd_timing {
245+
u32 ramp_up_us;
246+
u32 ramp_down_us;
247+
};
248+
243249
struct gpiochip_fwd {
244250
struct gpio_chip chip;
245251
struct gpio_desc **descs;
246252
union {
247253
struct mutex mlock; /* protects tmp[] if can_sleep */
248254
spinlock_t slock; /* protects tmp[] if !can_sleep */
249255
};
256+
struct gpiochip_fwd_timing *delay_timings;
250257
unsigned long tmp[]; /* values and descs for multiple ops */
251258
};
252259

@@ -331,6 +338,27 @@ static int gpio_fwd_get_multiple_locked(struct gpio_chip *chip,
331338
return error;
332339
}
333340

341+
static void gpio_fwd_delay(struct gpio_chip *chip, unsigned int offset, int value)
342+
{
343+
struct gpiochip_fwd *fwd = gpiochip_get_data(chip);
344+
const struct gpiochip_fwd_timing *delay_timings;
345+
bool is_active_low = gpiod_is_active_low(fwd->descs[offset]);
346+
u32 delay_us;
347+
348+
delay_timings = &fwd->delay_timings[offset];
349+
if ((!is_active_low && value) || (is_active_low && !value))
350+
delay_us = delay_timings->ramp_up_us;
351+
else
352+
delay_us = delay_timings->ramp_down_us;
353+
if (!delay_us)
354+
return;
355+
356+
if (chip->can_sleep)
357+
fsleep(delay_us);
358+
else
359+
udelay(delay_us);
360+
}
361+
334362
static void gpio_fwd_set(struct gpio_chip *chip, unsigned int offset, int value)
335363
{
336364
struct gpiochip_fwd *fwd = gpiochip_get_data(chip);
@@ -339,6 +367,9 @@ static void gpio_fwd_set(struct gpio_chip *chip, unsigned int offset, int value)
339367
gpiod_set_value_cansleep(fwd->descs[offset], value);
340368
else
341369
gpiod_set_value(fwd->descs[offset], value);
370+
371+
if (fwd->delay_timings)
372+
gpio_fwd_delay(chip, offset, value);
342373
}
343374

344375
static void gpio_fwd_set_multiple(struct gpiochip_fwd *fwd, unsigned long *mask,

0 commit comments

Comments
 (0)