diff options
author | Rob Herring <rob.herring@calxeda.com> | 2011-10-21 09:05:53 -0400 |
---|---|---|
committer | Rob Herring <rob.herring@calxeda.com> | 2012-01-05 09:47:12 -0500 |
commit | 3ab52475447641a6facf6ee5450bea24e477b811 (patch) | |
tree | a0910cfda03eddecbb07d2d0e57d02a325013477 /drivers/gpio/gpio-pl061.c | |
parent | 2b84112718ea816bb1147d6eabd4469143f89ddd (diff) |
gpio: pl061: convert to use generic irq chip
Convert the pl061 irq_chip code to use the generic irq chip code.
This has the side effect of using 32-bit accesses rather than 8-bit
accesses to interrupt registers. The h/w TRM and testing seem to indicate
this is fine.
Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Acked-by: Grant Likely <grant.likely@secretlab.ca>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio/gpio-pl061.c')
-rw-r--r-- | drivers/gpio/gpio-pl061.c | 74 |
1 files changed, 26 insertions, 48 deletions
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index fe19dec4b117..96ff6b28e9ad 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c | |||
@@ -50,10 +50,10 @@ struct pl061_gpio { | |||
50 | * the IRQ code simpler. | 50 | * the IRQ code simpler. |
51 | */ | 51 | */ |
52 | spinlock_t lock; /* GPIO registers */ | 52 | spinlock_t lock; /* GPIO registers */ |
53 | spinlock_t irq_lock; /* IRQ registers */ | ||
54 | 53 | ||
55 | void __iomem *base; | 54 | void __iomem *base; |
56 | int irq_base; | 55 | int irq_base; |
56 | struct irq_chip_generic *irq_gc; | ||
57 | struct gpio_chip gc; | 57 | struct gpio_chip gc; |
58 | }; | 58 | }; |
59 | 59 | ||
@@ -125,40 +125,10 @@ static int pl061_to_irq(struct gpio_chip *gc, unsigned offset) | |||
125 | return chip->irq_base + offset; | 125 | return chip->irq_base + offset; |
126 | } | 126 | } |
127 | 127 | ||
128 | /* | ||
129 | * PL061 GPIO IRQ | ||
130 | */ | ||
131 | static void pl061_irq_disable(struct irq_data *d) | ||
132 | { | ||
133 | struct pl061_gpio *chip = irq_data_get_irq_chip_data(d); | ||
134 | int offset = d->irq - chip->irq_base; | ||
135 | unsigned long flags; | ||
136 | u8 gpioie; | ||
137 | |||
138 | spin_lock_irqsave(&chip->irq_lock, flags); | ||
139 | gpioie = readb(chip->base + GPIOIE); | ||
140 | gpioie &= ~(1 << offset); | ||
141 | writeb(gpioie, chip->base + GPIOIE); | ||
142 | spin_unlock_irqrestore(&chip->irq_lock, flags); | ||
143 | } | ||
144 | |||
145 | static void pl061_irq_enable(struct irq_data *d) | ||
146 | { | ||
147 | struct pl061_gpio *chip = irq_data_get_irq_chip_data(d); | ||
148 | int offset = d->irq - chip->irq_base; | ||
149 | unsigned long flags; | ||
150 | u8 gpioie; | ||
151 | |||
152 | spin_lock_irqsave(&chip->irq_lock, flags); | ||
153 | gpioie = readb(chip->base + GPIOIE); | ||
154 | gpioie |= 1 << offset; | ||
155 | writeb(gpioie, chip->base + GPIOIE); | ||
156 | spin_unlock_irqrestore(&chip->irq_lock, flags); | ||
157 | } | ||
158 | |||
159 | static int pl061_irq_type(struct irq_data *d, unsigned trigger) | 128 | static int pl061_irq_type(struct irq_data *d, unsigned trigger) |
160 | { | 129 | { |
161 | struct pl061_gpio *chip = irq_data_get_irq_chip_data(d); | 130 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); |
131 | struct pl061_gpio *chip = gc->private; | ||
162 | int offset = d->irq - chip->irq_base; | 132 | int offset = d->irq - chip->irq_base; |
163 | unsigned long flags; | 133 | unsigned long flags; |
164 | u8 gpiois, gpioibe, gpioiev; | 134 | u8 gpiois, gpioibe, gpioiev; |
@@ -166,7 +136,7 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger) | |||
166 | if (offset < 0 || offset >= PL061_GPIO_NR) | 136 | if (offset < 0 || offset >= PL061_GPIO_NR) |
167 | return -EINVAL; | 137 | return -EINVAL; |
168 | 138 | ||
169 | spin_lock_irqsave(&chip->irq_lock, flags); | 139 | raw_spin_lock_irqsave(&gc->lock, flags); |
170 | 140 | ||
171 | gpioiev = readb(chip->base + GPIOIEV); | 141 | gpioiev = readb(chip->base + GPIOIEV); |
172 | 142 | ||
@@ -195,18 +165,11 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger) | |||
195 | 165 | ||
196 | writeb(gpioiev, chip->base + GPIOIEV); | 166 | writeb(gpioiev, chip->base + GPIOIEV); |
197 | 167 | ||
198 | spin_unlock_irqrestore(&chip->irq_lock, flags); | 168 | raw_spin_unlock_irqrestore(&gc->lock, flags); |
199 | 169 | ||
200 | return 0; | 170 | return 0; |
201 | } | 171 | } |
202 | 172 | ||
203 | static struct irq_chip pl061_irqchip = { | ||
204 | .name = "GPIO", | ||
205 | .irq_enable = pl061_irq_enable, | ||
206 | .irq_disable = pl061_irq_disable, | ||
207 | .irq_set_type = pl061_irq_type, | ||
208 | }; | ||
209 | |||
210 | static void pl061_irq_handler(unsigned irq, struct irq_desc *desc) | 173 | static void pl061_irq_handler(unsigned irq, struct irq_desc *desc) |
211 | { | 174 | { |
212 | struct list_head *chip_list = irq_get_handler_data(irq); | 175 | struct list_head *chip_list = irq_get_handler_data(irq); |
@@ -232,6 +195,25 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc) | |||
232 | chained_irq_exit(irqchip, desc); | 195 | chained_irq_exit(irqchip, desc); |
233 | } | 196 | } |
234 | 197 | ||
198 | static void __init pl061_init_gc(struct pl061_gpio *chip, int irq_base) | ||
199 | { | ||
200 | struct irq_chip_type *ct; | ||
201 | |||
202 | chip->irq_gc = irq_alloc_generic_chip("gpio-pl061", 1, irq_base, | ||
203 | chip->base, handle_simple_irq); | ||
204 | chip->irq_gc->private = chip; | ||
205 | |||
206 | ct = chip->irq_gc->chip_types; | ||
207 | ct->chip.irq_mask = irq_gc_mask_clr_bit; | ||
208 | ct->chip.irq_unmask = irq_gc_mask_set_bit; | ||
209 | ct->chip.irq_set_type = pl061_irq_type; | ||
210 | ct->chip.irq_set_wake = irq_gc_set_wake; | ||
211 | ct->regs.mask = GPIOIE; | ||
212 | |||
213 | irq_setup_generic_chip(chip->irq_gc, IRQ_MSK(PL061_GPIO_NR), | ||
214 | IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0); | ||
215 | } | ||
216 | |||
235 | static int pl061_probe(struct amba_device *dev, const struct amba_id *id) | 217 | static int pl061_probe(struct amba_device *dev, const struct amba_id *id) |
236 | { | 218 | { |
237 | struct pl061_platform_data *pdata; | 219 | struct pl061_platform_data *pdata; |
@@ -269,7 +251,6 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id) | |||
269 | } | 251 | } |
270 | 252 | ||
271 | spin_lock_init(&chip->lock); | 253 | spin_lock_init(&chip->lock); |
272 | spin_lock_init(&chip->irq_lock); | ||
273 | INIT_LIST_HEAD(&chip->list); | 254 | INIT_LIST_HEAD(&chip->list); |
274 | 255 | ||
275 | chip->gc.direction_input = pl061_direction_input; | 256 | chip->gc.direction_input = pl061_direction_input; |
@@ -293,6 +274,8 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id) | |||
293 | if (chip->irq_base <= 0) | 274 | if (chip->irq_base <= 0) |
294 | return 0; | 275 | return 0; |
295 | 276 | ||
277 | pl061_init_gc(chip, chip->irq_base); | ||
278 | |||
296 | writeb(0, chip->base + GPIOIE); /* disable irqs */ | 279 | writeb(0, chip->base + GPIOIE); /* disable irqs */ |
297 | irq = dev->irq[0]; | 280 | irq = dev->irq[0]; |
298 | if (irq < 0) { | 281 | if (irq < 0) { |
@@ -321,11 +304,6 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id) | |||
321 | else | 304 | else |
322 | pl061_direction_input(&chip->gc, i); | 305 | pl061_direction_input(&chip->gc, i); |
323 | } | 306 | } |
324 | |||
325 | irq_set_chip_and_handler(i + chip->irq_base, &pl061_irqchip, | ||
326 | handle_simple_irq); | ||
327 | set_irq_flags(i+chip->irq_base, IRQF_VALID); | ||
328 | irq_set_chip_data(i + chip->irq_base, chip); | ||
329 | } | 307 | } |
330 | 308 | ||
331 | return 0; | 309 | return 0; |