diff options
author | Alexander Shiyan <shc_work@mail.ru> | 2012-10-24 04:34:46 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2012-10-26 03:16:15 -0400 |
commit | d6a2fa0424aefe97289aa561444ec3ae09bdbba0 (patch) | |
tree | 0fea81d789d6a74ecf97fdacf1261c7ffe2b09a5 /drivers/gpio/gpio-clps711x.c | |
parent | 41b3996e3b6825bd3a0624d62fde53fbad092ed0 (diff) |
GPIO: clps711x: Fix direction logic for PORTD
PORTD have different direction logic, i.e. "0" is output and "1" is input.
This patch fix this issue.
Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio/gpio-clps711x.c')
-rw-r--r-- | drivers/gpio/gpio-clps711x.c | 65 |
1 files changed, 51 insertions, 14 deletions
diff --git a/drivers/gpio/gpio-clps711x.c b/drivers/gpio/gpio-clps711x.c index 0753b3a9a34d..ad181db79508 100644 --- a/drivers/gpio/gpio-clps711x.c +++ b/drivers/gpio/gpio-clps711x.c | |||
@@ -65,7 +65,7 @@ static void gpio_clps711x_set(struct gpio_chip *chip, unsigned offset, | |||
65 | spin_unlock_irqrestore(&gpio->lock, flags); | 65 | spin_unlock_irqrestore(&gpio->lock, flags); |
66 | } | 66 | } |
67 | 67 | ||
68 | static int gpio_clps711x_direction_in(struct gpio_chip *chip, unsigned offset) | 68 | static int gpio_clps711x_dir_in(struct gpio_chip *chip, unsigned offset) |
69 | { | 69 | { |
70 | int tmp; | 70 | int tmp; |
71 | unsigned long flags; | 71 | unsigned long flags; |
@@ -79,8 +79,8 @@ static int gpio_clps711x_direction_in(struct gpio_chip *chip, unsigned offset) | |||
79 | return 0; | 79 | return 0; |
80 | } | 80 | } |
81 | 81 | ||
82 | static int gpio_clps711x_direction_out(struct gpio_chip *chip, unsigned offset, | 82 | static int gpio_clps711x_dir_out(struct gpio_chip *chip, unsigned offset, |
83 | int value) | 83 | int value) |
84 | { | 84 | { |
85 | int tmp; | 85 | int tmp; |
86 | unsigned long flags; | 86 | unsigned long flags; |
@@ -98,17 +98,49 @@ static int gpio_clps711x_direction_out(struct gpio_chip *chip, unsigned offset, | |||
98 | return 0; | 98 | return 0; |
99 | } | 99 | } |
100 | 100 | ||
101 | struct clps711x_gpio_port { | 101 | static int gpio_clps711x_dir_in_inv(struct gpio_chip *chip, unsigned offset) |
102 | { | ||
103 | int tmp; | ||
104 | unsigned long flags; | ||
105 | struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev); | ||
106 | |||
107 | spin_lock_irqsave(&gpio->lock, flags); | ||
108 | tmp = readb(clps711x_pdir(chip)) | (1 << offset); | ||
109 | writeb(tmp, clps711x_pdir(chip)); | ||
110 | spin_unlock_irqrestore(&gpio->lock, flags); | ||
111 | |||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static int gpio_clps711x_dir_out_inv(struct gpio_chip *chip, unsigned offset, | ||
116 | int value) | ||
117 | { | ||
118 | int tmp; | ||
119 | unsigned long flags; | ||
120 | struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev); | ||
121 | |||
122 | spin_lock_irqsave(&gpio->lock, flags); | ||
123 | tmp = readb(clps711x_pdir(chip)) & ~(1 << offset); | ||
124 | writeb(tmp, clps711x_pdir(chip)); | ||
125 | tmp = readb(clps711x_port(chip)) & ~(1 << offset); | ||
126 | if (value) | ||
127 | tmp |= 1 << offset; | ||
128 | writeb(tmp, clps711x_port(chip)); | ||
129 | spin_unlock_irqrestore(&gpio->lock, flags); | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | static struct { | ||
102 | char *name; | 135 | char *name; |
103 | int nr; | 136 | int nr; |
104 | }; | 137 | int inv_dir; |
105 | 138 | } clps711x_gpio_ports[] __initconst = { | |
106 | static const struct clps711x_gpio_port clps711x_gpio_ports[] __initconst = { | 139 | { "PORTA", 8, 0, }, |
107 | { "PORTA", 8, }, | 140 | { "PORTB", 8, 0, }, |
108 | { "PORTB", 8, }, | 141 | { "PORTC", 8, 0, }, |
109 | { "PORTC", 8, }, | 142 | { "PORTD", 8, 1, }, |
110 | { "PORTD", 8, }, | 143 | { "PORTE", 3, 0, }, |
111 | { "PORTE", 3, }, | ||
112 | }; | 144 | }; |
113 | 145 | ||
114 | static int __init gpio_clps711x_init(void) | 146 | static int __init gpio_clps711x_init(void) |
@@ -145,10 +177,15 @@ static int __init gpio_clps711x_init(void) | |||
145 | gpio->chip[i].label = clps711x_gpio_ports[i].name; | 177 | gpio->chip[i].label = clps711x_gpio_ports[i].name; |
146 | gpio->chip[i].base = i * 8; | 178 | gpio->chip[i].base = i * 8; |
147 | gpio->chip[i].ngpio = clps711x_gpio_ports[i].nr; | 179 | gpio->chip[i].ngpio = clps711x_gpio_ports[i].nr; |
148 | gpio->chip[i].direction_input = gpio_clps711x_direction_in; | ||
149 | gpio->chip[i].get = gpio_clps711x_get; | 180 | gpio->chip[i].get = gpio_clps711x_get; |
150 | gpio->chip[i].direction_output = gpio_clps711x_direction_out; | ||
151 | gpio->chip[i].set = gpio_clps711x_set; | 181 | gpio->chip[i].set = gpio_clps711x_set; |
182 | if (!clps711x_gpio_ports[i].inv_dir) { | ||
183 | gpio->chip[i].direction_input = gpio_clps711x_dir_in; | ||
184 | gpio->chip[i].direction_output = gpio_clps711x_dir_out; | ||
185 | } else { | ||
186 | gpio->chip[i].direction_input = gpio_clps711x_dir_in_inv; | ||
187 | gpio->chip[i].direction_output = gpio_clps711x_dir_out_inv; | ||
188 | } | ||
152 | WARN_ON(gpiochip_add(&gpio->chip[i])); | 189 | WARN_ON(gpiochip_add(&gpio->chip[i])); |
153 | } | 190 | } |
154 | 191 | ||