aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpio-pl061.c
diff options
context:
space:
mode:
authorRob Herring <rob.herring@calxeda.com>2011-10-21 09:05:53 -0400
committerRob Herring <rob.herring@calxeda.com>2012-01-05 09:47:12 -0500
commit3ab52475447641a6facf6ee5450bea24e477b811 (patch)
treea0910cfda03eddecbb07d2d0e57d02a325013477 /drivers/gpio/gpio-pl061.c
parent2b84112718ea816bb1147d6eabd4469143f89ddd (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.c74
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 */
131static 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
145static 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
159static int pl061_irq_type(struct irq_data *d, unsigned trigger) 128static 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
203static 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
210static void pl061_irq_handler(unsigned irq, struct irq_desc *desc) 173static 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
198static 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
235static int pl061_probe(struct amba_device *dev, const struct amba_id *id) 217static 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;