Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

gpio: mmio: introduce BGPIOF_NO_SET_ON_INPUT

Some gpio controllers ignores pin value writing when that pin is
configured as input mode. As a result, bgpio_dir_out should set
pin to output before configuring pin values or gpio pin values
can't be set up properly.
Introduce two variants of bgpio_dir_out: bgpio_dir_out_val_first
and bgpio_dir_out_dir_first, and assign direction_output according
to a new flag: BGPIOF_NO_SET_ON_INPUT.

Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
Tested-by: René van Dorst <opensource@vdorst.com>
Reviewed-by: Sergio Paracuellos <sergio.paracuellos@gmail.com>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>

authored by

Chuanhong Guo and committed by
Bartosz Golaszewski
d19d2de6 d1ee7e1f

+20 -4
+19 -4
drivers/gpio/gpio-mmio.c
··· 389 389 return GPIO_LINE_DIRECTION_IN; 390 390 } 391 391 392 - static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) 392 + static void bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) 393 393 { 394 394 unsigned long flags; 395 - 396 - gc->set(gc, gpio, val); 397 395 398 396 spin_lock_irqsave(&gc->bgpio_lock, flags); 399 397 ··· 403 405 gc->write_reg(gc->reg_dir_out, gc->bgpio_dir); 404 406 405 407 spin_unlock_irqrestore(&gc->bgpio_lock, flags); 408 + } 406 409 410 + static int bgpio_dir_out_dir_first(struct gpio_chip *gc, unsigned int gpio, 411 + int val) 412 + { 413 + bgpio_dir_out(gc, gpio, val); 414 + gc->set(gc, gpio, val); 415 + return 0; 416 + } 417 + 418 + static int bgpio_dir_out_val_first(struct gpio_chip *gc, unsigned int gpio, 419 + int val) 420 + { 421 + gc->set(gc, gpio, val); 422 + bgpio_dir_out(gc, gpio, val); 407 423 return 0; 408 424 } 409 425 ··· 550 538 if (dirout || dirin) { 551 539 gc->reg_dir_out = dirout; 552 540 gc->reg_dir_in = dirin; 553 - gc->direction_output = bgpio_dir_out; 541 + if (flags & BGPIOF_NO_SET_ON_INPUT) 542 + gc->direction_output = bgpio_dir_out_dir_first; 543 + else 544 + gc->direction_output = bgpio_dir_out_val_first; 554 545 gc->direction_input = bgpio_dir_in; 555 546 gc->get_direction = bgpio_get_dir; 556 547 } else {
+1
include/linux/gpio/driver.h
··· 572 572 #define BGPIOF_BIG_ENDIAN_BYTE_ORDER BIT(3) 573 573 #define BGPIOF_READ_OUTPUT_REG_SET BIT(4) /* reg_set stores output value */ 574 574 #define BGPIOF_NO_OUTPUT BIT(5) /* only input */ 575 + #define BGPIOF_NO_SET_ON_INPUT BIT(6) 575 576 576 577 int gpiochip_irq_map(struct irq_domain *d, unsigned int irq, 577 578 irq_hw_number_t hwirq);