Commit ecba1eaa authored by Geert Uytterhoeven's avatar Geert Uytterhoeven Committed by Bartosz Golaszewski

gpio: rcar: Optimize GPIO pin state read on R-Car Gen3

Currently, the R-Car GPIO driver treats R-Car Gen2 and R-Car Gen3 GPIO
controllers the same.  However, there exist small differences, like the
behavior of the General Input Register (INDT):
  - On R-Car Gen1, R-Car Gen2, and RZ/G1, INDT only reflects the state
    of an input pin if the GPIO is configured for input,
  - On R-Car Gen3 and RZ/G2, INDT always reflects the state of the input
    pins.
Hence to accommodate all variants, the driver does not use the INDT
register to read the status of a GPIO line when configured for output,
at the expense of doing 2 or 3 register reads instead of 1.

Given register accesses are slow, change the .get() and .get_multiple()
callbacks to always use INDT to read pin state on SoCs where this is
supported.
Signed-off-by: default avatarGeert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: default avatarYoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Tested-by: default avatarWolfram Sang <wsa+renesas@sang-engineering.com>
Reviewed-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarBartosz Golaszewski <bgolaszewski@baylibre.com>
parent 2a84708c
...@@ -35,6 +35,7 @@ struct gpio_rcar_bank_info { ...@@ -35,6 +35,7 @@ struct gpio_rcar_bank_info {
struct gpio_rcar_info { struct gpio_rcar_info {
bool has_outdtsel; bool has_outdtsel;
bool has_both_edge_trigger; bool has_both_edge_trigger;
bool has_always_in;
}; };
struct gpio_rcar_priv { struct gpio_rcar_priv {
...@@ -302,9 +303,11 @@ static int gpio_rcar_get(struct gpio_chip *chip, unsigned offset) ...@@ -302,9 +303,11 @@ static int gpio_rcar_get(struct gpio_chip *chip, unsigned offset)
struct gpio_rcar_priv *p = gpiochip_get_data(chip); struct gpio_rcar_priv *p = gpiochip_get_data(chip);
u32 bit = BIT(offset); u32 bit = BIT(offset);
/* testing on r8a7790 shows that INDT does not show correct pin state /*
* when configured as output, so use OUTDT in case of output pins */ * Before R-Car Gen3, INDT does not show correct pin state when
if (gpio_rcar_read(p, INOUTSEL) & bit) * configured as output, so use OUTDT in case of output pins
*/
if (!p->info.has_always_in && (gpio_rcar_read(p, INOUTSEL) & bit))
return !!(gpio_rcar_read(p, OUTDT) & bit); return !!(gpio_rcar_read(p, OUTDT) & bit);
else else
return !!(gpio_rcar_read(p, INDT) & bit); return !!(gpio_rcar_read(p, INDT) & bit);
...@@ -324,6 +327,11 @@ static int gpio_rcar_get_multiple(struct gpio_chip *chip, unsigned long *mask, ...@@ -324,6 +327,11 @@ static int gpio_rcar_get_multiple(struct gpio_chip *chip, unsigned long *mask,
if (!bankmask) if (!bankmask)
return 0; return 0;
if (p->info.has_always_in) {
bits[0] = gpio_rcar_read(p, INDT) & bankmask;
return 0;
}
spin_lock_irqsave(&p->lock, flags); spin_lock_irqsave(&p->lock, flags);
outputs = gpio_rcar_read(p, INOUTSEL); outputs = gpio_rcar_read(p, INOUTSEL);
m = outputs & bankmask; m = outputs & bankmask;
...@@ -383,11 +391,19 @@ static int gpio_rcar_direction_output(struct gpio_chip *chip, unsigned offset, ...@@ -383,11 +391,19 @@ static int gpio_rcar_direction_output(struct gpio_chip *chip, unsigned offset,
static const struct gpio_rcar_info gpio_rcar_info_gen1 = { static const struct gpio_rcar_info gpio_rcar_info_gen1 = {
.has_outdtsel = false, .has_outdtsel = false,
.has_both_edge_trigger = false, .has_both_edge_trigger = false,
.has_always_in = false,
}; };
static const struct gpio_rcar_info gpio_rcar_info_gen2 = { static const struct gpio_rcar_info gpio_rcar_info_gen2 = {
.has_outdtsel = true, .has_outdtsel = true,
.has_both_edge_trigger = true, .has_both_edge_trigger = true,
.has_always_in = false,
};
static const struct gpio_rcar_info gpio_rcar_info_gen3 = {
.has_outdtsel = true,
.has_both_edge_trigger = true,
.has_always_in = true,
}; };
static const struct of_device_id gpio_rcar_of_table[] = { static const struct of_device_id gpio_rcar_of_table[] = {
...@@ -399,8 +415,7 @@ static const struct of_device_id gpio_rcar_of_table[] = { ...@@ -399,8 +415,7 @@ static const struct of_device_id gpio_rcar_of_table[] = {
.data = &gpio_rcar_info_gen2, .data = &gpio_rcar_info_gen2,
}, { }, {
.compatible = "renesas,rcar-gen3-gpio", .compatible = "renesas,rcar-gen3-gpio",
/* Gen3 GPIO is identical to Gen2. */ .data = &gpio_rcar_info_gen3,
.data = &gpio_rcar_info_gen2,
}, { }, {
.compatible = "renesas,gpio-rcar", .compatible = "renesas,gpio-rcar",
.data = &gpio_rcar_info_gen1, .data = &gpio_rcar_info_gen1,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment