Skip to content

Commit 3ae4f3a

Browse files
Vladimir Zapolskiylinusw
authored andcommitted
gpio: rcar: select General Output Register to set output states
R-Car GPIO controller provides two interfaces to set GPIO line output signal state, and for a particular GPIO line the selected interface is determined by OUTDTSEL bit value. At the moment the driver supports only one of two interfaces, namely OUTDT General Output Register is used to control the output signal. While this selection is the default one on reset, it is not explicitly configured on probe, thus it might be possible that kernel and userspace consumers of a GPIO won't be able to set the wanted GPIO output signal. Below is a simple test case to reproduce the described problem and verify this fix in the kernel on H3 ULCB by setting non-default OUTDTSEL configuration from a bootloader: u-boot > mw.l 0xe6055440 0x3000 1 ... userspace > echo default-on > /sys/devices/platform/leds/leds/led5/trigger userspace > echo default-on > /sys/devices/platform/leds/leds/led6/trigger Signed-off-by: Vladimir Zapolskiy <vladimir_zapolskiy@mentor.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
1 parent b597c3a commit 3ae4f3a

File tree

1 file changed

+11
-1
lines changed

1 file changed

+11
-1
lines changed

drivers/gpio/gpio-rcar.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ struct gpio_rcar_priv {
4040
struct irq_chip irq_chip;
4141
unsigned int irq_parent;
4242
atomic_t wakeup_path;
43+
bool has_outdtsel;
4344
bool has_both_edge_trigger;
4445
struct gpio_rcar_bank_info bank_info;
4546
};
@@ -55,6 +56,7 @@ struct gpio_rcar_priv {
5556
#define POSNEG 0x20 /* Positive/Negative Logic Select Register */
5657
#define EDGLEVEL 0x24 /* Edge/level Select Register */
5758
#define FILONOFF 0x28 /* Chattering Prevention On/Off Register */
59+
#define OUTDTSEL 0x40 /* Output Data Select Register */
5860
#define BOTHEDGE 0x4c /* One Edge/Both Edge Select Register */
5961

6062
#define RCAR_MAX_GPIO_PER_BANK 32
@@ -235,6 +237,10 @@ static void gpio_rcar_config_general_input_output_mode(struct gpio_chip *chip,
235237
/* Select Input Mode or Output Mode in INOUTSEL */
236238
gpio_rcar_modify_bit(p, INOUTSEL, gpio, output);
237239

240+
/* Select General Output Register to output data in OUTDTSEL */
241+
if (p->has_outdtsel && output)
242+
gpio_rcar_modify_bit(p, OUTDTSEL, gpio, false);
243+
238244
spin_unlock_irqrestore(&p->lock, flags);
239245
}
240246

@@ -336,14 +342,17 @@ static int gpio_rcar_direction_output(struct gpio_chip *chip, unsigned offset,
336342
}
337343

338344
struct gpio_rcar_info {
345+
bool has_outdtsel;
339346
bool has_both_edge_trigger;
340347
};
341348

342349
static const struct gpio_rcar_info gpio_rcar_info_gen1 = {
350+
.has_outdtsel = false,
343351
.has_both_edge_trigger = false,
344352
};
345353

346354
static const struct gpio_rcar_info gpio_rcar_info_gen2 = {
355+
.has_outdtsel = true,
347356
.has_both_edge_trigger = true,
348357
};
349358

@@ -403,10 +412,11 @@ static int gpio_rcar_parse_dt(struct gpio_rcar_priv *p, unsigned int *npins)
403412
int ret;
404413

405414
info = of_device_get_match_data(p->dev);
415+
p->has_outdtsel = info->has_outdtsel;
416+
p->has_both_edge_trigger = info->has_both_edge_trigger;
406417

407418
ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, 0, &args);
408419
*npins = ret == 0 ? args.args[2] : RCAR_MAX_GPIO_PER_BANK;
409-
p->has_both_edge_trigger = info->has_both_edge_trigger;
410420

411421
if (*npins == 0 || *npins > RCAR_MAX_GPIO_PER_BANK) {
412422
dev_warn(p->dev, "Invalid number of gpio lines %u, using %u\n",

0 commit comments

Comments
 (0)