Skip to content
  • Linus Walleij's avatar
    gpio: mmio: Fix up inverted direction registers · d799a4de
    Linus Walleij authored
    
    
    The bgpio_init() takes one of two arguments to specify a register
    to set the direction of the GPIO line: either dirout that
    indicates that a 1 in the bit in that register sets the
    corresponding line to output, or dirin which indicates that
    a 1 in the bit in that register sets the corresponding line to
    input. Conversely setting the bit to 0 on these will turn the
    line into input and output respectively. One of these can
    be defined but not both.
    
    This means that a platform that sets a bit to 1 for output
    only defines dirout and a platform that sets a bit to 0 for
    output only defines dirin. In short this defines the polarity
    of the direction register.
    
    Both can also be left as NULL meaning the GPIO chip is either
    input only or output only.
    
    Tomer Maimon discovered that for get/set chips (those where the
    get and set registers are defined but no separate clear register,
    and specifying BGPIOF_READ_OUTPUT_REG_SET so that we say we
    want to read the output value from the SET register)
    we are unconditionally reading the value from the SET register
    when the direction bit is 1 and from the DAT register when the
    direction bit is 0, not taking the direction bit polarity into
    account.
    
    It would be expected that when the direction bit is inverted
    (dirin is defined but not dirout) we read the current value from
    the DAT register when the bit is 1 and from the SET register
    when the bit is 0.
    
    Currently only some versions of ATH79, brcmstb, some versions of
    CLP711x, GE, IOP and Loongson use the dirin mode (a 1 in the
    register means input). They are unaffected because
    BGPIOF_READ_OUTPUT_REG_SET is not set on any of them. (They
    do not read back the SET register to figure out the output
    value.) So this is no regression with current drivers.
    
    However the behaviour is wrong and does not work with Tomer's
    new driver where he needs to use the BGIOF_READ_OUTPUT_REG_SET.
    This fixes the above issue by:
    
    - Instead of defining separate functions for the inverted case,
      set up a flag in the gpio_chip that indicates that the
      direction is inverted.
    - Remove the special inverted functions for setting
      input/output and getting the direction, rely on the flag
      instead.
    - Respect this flag in bgpio_get_set() and
      bgpio_get_set_multiple()
    
    Reported-by: default avatarTomer Maimon <tmaimon77@gmail.com>
    Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
    d799a4de