diff options
author | Haojian Zhuang <haojian.zhuang@linaro.org> | 2013-02-17 06:42:49 -0500 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2013-03-06 23:27:30 -0500 |
commit | f1f70479e999217ecbf619d71837fc5d77c680fb (patch) | |
tree | d93df998879dd641df05cbd1797f1322c8c522fd /drivers/gpio | |
parent | 86853c83e33738397564e9377ceeff94d4bc041c (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')
-rw-r--r-- | drivers/gpio/gpio-pl061.c | 104 |
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 | ||
131 | static int pl061_irq_type(struct irq_data *d, unsigned trigger) | 128 | static 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 | ||
195 | static void __init pl061_init_gc(struct pl061_gpio *chip, int irq_base) | 191 | static 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, | 203 | static 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 | |||
215 | static 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 | |||
222 | static 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 | ||
235 | static const struct irq_domain_ops pl061_domain_ops = { | ||
236 | .map = pl061_irq_map, | ||
237 | .xlate = irq_domain_xlate_twocell, | ||
238 | }; | ||
239 | |||
214 | static int pl061_probe(struct amba_device *adev, const struct amba_id *id) | 240 | static 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) |