summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndres Salomon <dilinger@queued.net>2010-12-21 13:04:52 -0800
committerAK <andi@firstfloor.org>2011-02-06 11:03:47 -0800
commit4dfbc34551053dcf44fa3c6ab8d2fcf39bd38eea (patch)
treea2335c8db7050dd382e134aef1d5859e901673f7
parent1d95fe9a8ddadc8700e85f5e9d9682842a1c743c (diff)
cs5535-gpio: handle GPIO regs where higher (clear) bits are set
commit 44658a11f312fb9217674cb90b1a11cbe17fd18d upstream. The default for non-READ_BACK GPIO regs is to have the clear bits set; this means that our original errata fix was too simplistic. This changes it to the following behavior: - when setting GPIOs, ignore the higher order bits (they're for clearing, we don't need to care about them). - when clearing GPIOs, keep all the bits, but unset (via XOR) the lower order bit that negates the clear bit that we care about. That is, if we're clearing GPIO 26 (val = 0x04000000), we first XOR what's currently in the register with 0x0400 (GPIO 26's SET bit), and then OR that with the GPIO 26's CLEAR bit. Tested-by: Daniel Drake <dsd@laptop.org> Signed-off-by: Andres Salomon <dilinger@queued.net> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> Signed-off-by: Andi Kleen <ak@linux.intel.com>
-rw-r--r--drivers/gpio/cs5535-gpio.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/drivers/gpio/cs5535-gpio.c b/drivers/gpio/cs5535-gpio.c
index 79eb9c5a2923..d3e55a0ae92b 100644
--- a/drivers/gpio/cs5535-gpio.c
+++ b/drivers/gpio/cs5535-gpio.c
@@ -70,8 +70,12 @@ static void errata_outl(struct cs5535_gpio_chip *chip, u32 val,
* Don't apply this errata to the edge status GPIOs, as writing
* to their lower bits will clear them.
*/
- if (reg != GPIO_POSITIVE_EDGE_STS && reg != GPIO_NEGATIVE_EDGE_STS)
- val |= inl(addr);
+ if (reg != GPIO_POSITIVE_EDGE_STS && reg != GPIO_NEGATIVE_EDGE_STS) {
+ if (val & 0xffff)
+ val |= (inl(addr) & 0xffff); /* ignore the high bits */
+ else
+ val |= (inl(addr) ^ (val >> 16));
+ }
outl(val, addr);
}