aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorFelix Radensky <felix@embedded-sol.com>2009-08-12 01:57:39 -0400
committerKumar Gala <galak@kernel.crashing.org>2009-12-10 22:11:08 -0500
commitc1a676dfa2fa25fb9ec77c92ebe3ff580648b6ac (patch)
tree748ab9277c1d78cc83c27dd040722c681bcda7dc /arch
parent78331aded913d76c7ff996a1a0747d54b057460b (diff)
powerpc/85xx: Workaround MPC8572/MPC8536 GPIO 1 errata.
On MPC8572 and MPC8536 the status of GPIO pins configured as output cannot be determined by reading GPDAT register. Workaround by reading the status of input pins from GPDAT and the status of output pins from a shadow register. Signed-off-by: Felix Radensky <felix@embedded-sol.com> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/sysdev/mpc8xxx_gpio.c21
1 files changed, 20 insertions, 1 deletions
diff --git a/arch/powerpc/sysdev/mpc8xxx_gpio.c b/arch/powerpc/sysdev/mpc8xxx_gpio.c
index 103eace36194..ee1c0e1cf4a7 100644
--- a/arch/powerpc/sysdev/mpc8xxx_gpio.c
+++ b/arch/powerpc/sysdev/mpc8xxx_gpio.c
@@ -54,6 +54,22 @@ static void mpc8xxx_gpio_save_regs(struct of_mm_gpio_chip *mm)
54 mpc8xxx_gc->data = in_be32(mm->regs + GPIO_DAT); 54 mpc8xxx_gc->data = in_be32(mm->regs + GPIO_DAT);
55} 55}
56 56
57/* Workaround GPIO 1 errata on MPC8572/MPC8536. The status of GPIOs
58 * defined as output cannot be determined by reading GPDAT register,
59 * so we use shadow data register instead. The status of input pins
60 * is determined by reading GPDAT register.
61 */
62static int mpc8572_gpio_get(struct gpio_chip *gc, unsigned int gpio)
63{
64 u32 val;
65 struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
66 struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
67
68 val = in_be32(mm->regs + GPIO_DAT) & ~in_be32(mm->regs + GPIO_DIR);
69
70 return (val | mpc8xxx_gc->data) & mpc8xxx_gpio2mask(gpio);
71}
72
57static int mpc8xxx_gpio_get(struct gpio_chip *gc, unsigned int gpio) 73static int mpc8xxx_gpio_get(struct gpio_chip *gc, unsigned int gpio)
58{ 74{
59 struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); 75 struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
@@ -136,7 +152,10 @@ static void __init mpc8xxx_add_controller(struct device_node *np)
136 gc->ngpio = MPC8XXX_GPIO_PINS; 152 gc->ngpio = MPC8XXX_GPIO_PINS;
137 gc->direction_input = mpc8xxx_gpio_dir_in; 153 gc->direction_input = mpc8xxx_gpio_dir_in;
138 gc->direction_output = mpc8xxx_gpio_dir_out; 154 gc->direction_output = mpc8xxx_gpio_dir_out;
139 gc->get = mpc8xxx_gpio_get; 155 if (of_device_is_compatible(np, "fsl,mpc8572-gpio"))
156 gc->get = mpc8572_gpio_get;
157 else
158 gc->get = mpc8xxx_gpio_get;
140 gc->set = mpc8xxx_gpio_set; 159 gc->set = mpc8xxx_gpio_set;
141 160
142 ret = of_mm_gpiochip_add(np, mm_gc); 161 ret = of_mm_gpiochip_add(np, mm_gc);