aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpio-pl061.c
diff options
context:
space:
mode:
authorHaojian Zhuang <haojian.zhuang@linaro.org>2013-02-17 06:42:49 -0500
committerLinus Walleij <linus.walleij@linaro.org>2013-03-06 23:27:30 -0500
commitf1f70479e999217ecbf619d71837fc5d77c680fb (patch)
treed93df998879dd641df05cbd1797f1322c8c522fd /drivers/gpio/gpio-pl061.c
parent86853c83e33738397564e9377ceeff94d4bc041c (diff)
gpio: pl061: support irqdomain
Drop the support of irq generic chip. Now support irqdomain instead. Although set_wake() is defined in irq generic chip & it is not really used in pl061 gpio driver. Drop it at the same time. Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio/gpio-pl061.c')
-rw-r--r--drivers/gpio/gpio-pl061.c104
1 files changed, 65 insertions, 39 deletions
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c
index b820869ca93c..d1d603585a93 100644
--- a/drivers/gpio/gpio-pl061.c
+++ b/drivers/gpio/gpio-pl061.c
@@ -15,6 +15,7 @@
15#include <linux/io.h> 15#include <linux/io.h>
16#include <linux/ioport.h> 16#include <linux/ioport.h>
17#include <linux/irq.h> 17#include <linux/irq.h>
18#include <linux/irqdomain.h>
18#include <linux/bitops.h> 19#include <linux/bitops.h>
19#include <linux/workqueue.h> 20#include <linux/workqueue.h>
20#include <linux/gpio.h> 21#include <linux/gpio.h>
@@ -51,8 +52,7 @@ struct pl061_gpio {
51 spinlock_t lock; 52 spinlock_t lock;
52 53
53 void __iomem *base; 54 void __iomem *base;
54 int irq_base; 55 struct irq_domain *domain;
55 struct irq_chip_generic *irq_gc;
56 struct gpio_chip gc; 56 struct gpio_chip gc;
57 57
58#ifdef CONFIG_PM 58#ifdef CONFIG_PM
@@ -122,24 +122,20 @@ static int pl061_to_irq(struct gpio_chip *gc, unsigned offset)
122{ 122{
123 struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); 123 struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
124 124
125 if (chip->irq_base <= 0) 125 return irq_create_mapping(chip->domain, offset);
126 return -EINVAL;
127
128 return chip->irq_base + offset;
129} 126}
130 127
131static int pl061_irq_type(struct irq_data *d, unsigned trigger) 128static int pl061_irq_type(struct irq_data *d, unsigned trigger)
132{ 129{
133 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 130 struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
134 struct pl061_gpio *chip = gc->private; 131 int offset = irqd_to_hwirq(d);
135 int offset = d->irq - chip->irq_base;
136 unsigned long flags; 132 unsigned long flags;
137 u8 gpiois, gpioibe, gpioiev; 133 u8 gpiois, gpioibe, gpioiev;
138 134
139 if (offset < 0 || offset >= PL061_GPIO_NR) 135 if (offset < 0 || offset >= PL061_GPIO_NR)
140 return -EINVAL; 136 return -EINVAL;
141 137
142 raw_spin_lock_irqsave(&gc->lock, flags); 138 spin_lock_irqsave(&chip->lock, flags);
143 139
144 gpioiev = readb(chip->base + GPIOIEV); 140 gpioiev = readb(chip->base + GPIOIEV);
145 141
@@ -168,7 +164,7 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger)
168 164
169 writeb(gpioiev, chip->base + GPIOIEV); 165 writeb(gpioiev, chip->base + GPIOIEV);
170 166
171 raw_spin_unlock_irqrestore(&gc->lock, flags); 167 spin_unlock_irqrestore(&chip->lock, flags);
172 168
173 return 0; 169 return 0;
174} 170}
@@ -192,31 +188,61 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc)
192 chained_irq_exit(irqchip, desc); 188 chained_irq_exit(irqchip, desc);
193} 189}
194 190
195static void __init pl061_init_gc(struct pl061_gpio *chip, int irq_base) 191static void pl061_irq_mask(struct irq_data *d)
196{ 192{
197 struct irq_chip_type *ct; 193 struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
194 u8 mask = 1 << (irqd_to_hwirq(d) % PL061_GPIO_NR);
195 u8 gpioie;
196
197 spin_lock(&chip->lock);
198 gpioie = readb(chip->base + GPIOIE) & ~mask;
199 writeb(gpioie, chip->base + GPIOIE);
200 spin_unlock(&chip->lock);
201}
198 202
199 chip->irq_gc = irq_alloc_generic_chip("gpio-pl061", 1, irq_base, 203static void pl061_irq_unmask(struct irq_data *d)
200 chip->base, handle_simple_irq); 204{
201 chip->irq_gc->private = chip; 205 struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
206 u8 mask = 1 << (irqd_to_hwirq(d) % PL061_GPIO_NR);
207 u8 gpioie;
208
209 spin_lock(&chip->lock);
210 gpioie = readb(chip->base + GPIOIE) | mask;
211 writeb(gpioie, chip->base + GPIOIE);
212 spin_unlock(&chip->lock);
213}
214
215static struct irq_chip pl061_irqchip = {
216 .name = "pl061 gpio",
217 .irq_mask = pl061_irq_mask,
218 .irq_unmask = pl061_irq_unmask,
219 .irq_set_type = pl061_irq_type,
220};
221
222static int pl061_irq_map(struct irq_domain *d, unsigned int virq,
223 irq_hw_number_t hw)
224{
225 struct pl061_gpio *chip = d->host_data;
202 226
203 ct = chip->irq_gc->chip_types; 227 irq_set_chip_and_handler_name(virq, &pl061_irqchip, handle_simple_irq,
204 ct->chip.irq_mask = irq_gc_mask_clr_bit; 228 "pl061");
205 ct->chip.irq_unmask = irq_gc_mask_set_bit; 229 irq_set_chip_data(virq, chip);
206 ct->chip.irq_set_type = pl061_irq_type; 230 irq_set_irq_type(virq, IRQ_TYPE_NONE);
207 ct->chip.irq_set_wake = irq_gc_set_wake;
208 ct->regs.mask = GPIOIE;
209 231
210 irq_setup_generic_chip(chip->irq_gc, IRQ_MSK(PL061_GPIO_NR), 232 return 0;
211 IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0);
212} 233}
213 234
235static const struct irq_domain_ops pl061_domain_ops = {
236 .map = pl061_irq_map,
237 .xlate = irq_domain_xlate_twocell,
238};
239
214static int pl061_probe(struct amba_device *adev, const struct amba_id *id) 240static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
215{ 241{
216 struct device *dev = &adev->dev; 242 struct device *dev = &adev->dev;
217 struct pl061_platform_data *pdata = dev->platform_data; 243 struct pl061_platform_data *pdata = dev->platform_data;
218 struct pl061_gpio *chip; 244 struct pl061_gpio *chip;
219 int ret, irq, i; 245 int ret, irq, i, irq_base;
220 246
221 chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); 247 chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
222 if (chip == NULL) 248 if (chip == NULL)
@@ -224,22 +250,28 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
224 250
225 if (pdata) { 251 if (pdata) {
226 chip->gc.base = pdata->gpio_base; 252 chip->gc.base = pdata->gpio_base;
227 chip->irq_base = pdata->irq_base; 253 irq_base = pdata->irq_base;
228 } else if (adev->dev.of_node) { 254 if (irq_base <= 0)
255 return -ENODEV;
256 } else {
229 chip->gc.base = -1; 257 chip->gc.base = -1;
230 chip->irq_base = 0; 258 irq_base = 0;
231 } else 259 }
232 return -ENODEV;
233 260
234 if (!devm_request_mem_region(dev, adev->res.start, 261 if (!devm_request_mem_region(dev, adev->res.start,
235 resource_size(&adev->res), "pl061")) 262 resource_size(&adev->res), "pl061"))
236 return -EBUSY; 263 return -EBUSY;
237 264
238 chip->base = devm_ioremap(dev, adev->res.start, 265 chip->base = devm_ioremap(dev, adev->res.start,
239 resource_size(&adev->res)); 266 resource_size(&adev->res));
240 if (chip->base == NULL) 267 if (!chip->base)
241 return -ENOMEM; 268 return -ENOMEM;
242 269
270 chip->domain = irq_domain_add_simple(adev->dev.of_node, PL061_GPIO_NR,
271 irq_base, &pl061_domain_ops, chip);
272 if (!chip->domain)
273 return -ENODEV;
274
243 spin_lock_init(&chip->lock); 275 spin_lock_init(&chip->lock);
244 276
245 chip->gc.direction_input = pl061_direction_input; 277 chip->gc.direction_input = pl061_direction_input;
@@ -259,12 +291,6 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
259 /* 291 /*
260 * irq_chip support 292 * irq_chip support
261 */ 293 */
262
263 if (chip->irq_base <= 0)
264 return 0;
265
266 pl061_init_gc(chip, chip->irq_base);
267
268 writeb(0, chip->base + GPIOIE); /* disable irqs */ 294 writeb(0, chip->base + GPIOIE); /* disable irqs */
269 irq = adev->irq[0]; 295 irq = adev->irq[0];
270 if (irq < 0) 296 if (irq < 0)