diff options
| author | Linus Walleij <linus.walleij@linaro.org> | 2014-03-25 05:42:35 -0400 |
|---|---|---|
| committer | Linus Walleij <linus.walleij@linaro.org> | 2014-03-26 05:31:33 -0400 |
| commit | 8d5b24bd30c23930e666813ea0adc4672ea58c62 (patch) | |
| tree | 1f0d7d96bd8c4a81719ca514e8c8301f7706a423 | |
| parent | 1425052097b53de841e064dc190a9009480c208c (diff) | |
gpio: pl061: convert driver to use gpiolib irqchip
This converts the PL061 driver to register its chained irq
handler and irqchip using the helpers in the gpiolib core.
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
| -rw-r--r-- | drivers/gpio/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/gpio/gpio-pl061.c | 80 |
2 files changed, 19 insertions, 62 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 51c782532687..92d8e9a064b4 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
| @@ -247,6 +247,7 @@ config GPIO_PL061 | |||
| 247 | bool "PrimeCell PL061 GPIO support" | 247 | bool "PrimeCell PL061 GPIO support" |
| 248 | depends on ARM_AMBA | 248 | depends on ARM_AMBA |
| 249 | select IRQ_DOMAIN | 249 | select IRQ_DOMAIN |
| 250 | select GPIOLIB_IRQCHIP | ||
| 250 | help | 251 | help |
| 251 | Say yes here to support the PrimeCell PL061 GPIO device | 252 | Say yes here to support the PrimeCell PL061 GPIO device |
| 252 | 253 | ||
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index d2a0ad5fc752..b0f475243cef 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c | |||
| @@ -15,7 +15,6 @@ | |||
| 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> | ||
| 19 | #include <linux/irqchip/chained_irq.h> | 18 | #include <linux/irqchip/chained_irq.h> |
| 20 | #include <linux/bitops.h> | 19 | #include <linux/bitops.h> |
| 21 | #include <linux/workqueue.h> | 20 | #include <linux/workqueue.h> |
| @@ -53,7 +52,6 @@ struct pl061_gpio { | |||
| 53 | spinlock_t lock; | 52 | spinlock_t lock; |
| 54 | 53 | ||
| 55 | void __iomem *base; | 54 | void __iomem *base; |
| 56 | struct irq_domain *domain; | ||
| 57 | struct gpio_chip gc; | 55 | struct gpio_chip gc; |
| 58 | 56 | ||
| 59 | #ifdef CONFIG_PM | 57 | #ifdef CONFIG_PM |
| @@ -137,16 +135,10 @@ static void pl061_set_value(struct gpio_chip *gc, unsigned offset, int value) | |||
| 137 | writeb(!!value << offset, chip->base + (1 << (offset + 2))); | 135 | writeb(!!value << offset, chip->base + (1 << (offset + 2))); |
| 138 | } | 136 | } |
| 139 | 137 | ||
| 140 | static int pl061_to_irq(struct gpio_chip *gc, unsigned offset) | ||
| 141 | { | ||
| 142 | struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); | ||
| 143 | |||
| 144 | return irq_create_mapping(chip->domain, offset); | ||
| 145 | } | ||
| 146 | |||
| 147 | static int pl061_irq_type(struct irq_data *d, unsigned trigger) | 138 | static int pl061_irq_type(struct irq_data *d, unsigned trigger) |
| 148 | { | 139 | { |
| 149 | struct pl061_gpio *chip = irq_data_get_irq_chip_data(d); | 140 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
| 141 | struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); | ||
| 150 | int offset = irqd_to_hwirq(d); | 142 | int offset = irqd_to_hwirq(d); |
| 151 | unsigned long flags; | 143 | unsigned long flags; |
| 152 | u8 gpiois, gpioibe, gpioiev; | 144 | u8 gpiois, gpioibe, gpioiev; |
| @@ -194,7 +186,8 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc) | |||
| 194 | { | 186 | { |
| 195 | unsigned long pending; | 187 | unsigned long pending; |
| 196 | int offset; | 188 | int offset; |
| 197 | struct pl061_gpio *chip = irq_desc_get_handler_data(desc); | 189 | struct gpio_chip *gc = irq_desc_get_handler_data(desc); |
| 190 | struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); | ||
| 198 | struct irq_chip *irqchip = irq_desc_get_chip(desc); | 191 | struct irq_chip *irqchip = irq_desc_get_chip(desc); |
| 199 | 192 | ||
| 200 | chained_irq_enter(irqchip, desc); | 193 | chained_irq_enter(irqchip, desc); |
| @@ -203,7 +196,8 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc) | |||
| 203 | writeb(pending, chip->base + GPIOIC); | 196 | writeb(pending, chip->base + GPIOIC); |
| 204 | if (pending) { | 197 | if (pending) { |
| 205 | for_each_set_bit(offset, &pending, PL061_GPIO_NR) | 198 | for_each_set_bit(offset, &pending, PL061_GPIO_NR) |
| 206 | generic_handle_irq(pl061_to_irq(&chip->gc, offset)); | 199 | generic_handle_irq(irq_find_mapping(gc->irqdomain, |
| 200 | offset)); | ||
| 207 | } | 201 | } |
| 208 | 202 | ||
| 209 | chained_irq_exit(irqchip, desc); | 203 | chained_irq_exit(irqchip, desc); |
| @@ -211,7 +205,8 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc) | |||
| 211 | 205 | ||
| 212 | static void pl061_irq_mask(struct irq_data *d) | 206 | static void pl061_irq_mask(struct irq_data *d) |
| 213 | { | 207 | { |
| 214 | struct pl061_gpio *chip = irq_data_get_irq_chip_data(d); | 208 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
| 209 | struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); | ||
| 215 | u8 mask = 1 << (irqd_to_hwirq(d) % PL061_GPIO_NR); | 210 | u8 mask = 1 << (irqd_to_hwirq(d) % PL061_GPIO_NR); |
| 216 | u8 gpioie; | 211 | u8 gpioie; |
| 217 | 212 | ||
| @@ -223,7 +218,8 @@ static void pl061_irq_mask(struct irq_data *d) | |||
| 223 | 218 | ||
| 224 | static void pl061_irq_unmask(struct irq_data *d) | 219 | static void pl061_irq_unmask(struct irq_data *d) |
| 225 | { | 220 | { |
| 226 | struct pl061_gpio *chip = irq_data_get_irq_chip_data(d); | 221 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
| 222 | struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); | ||
| 227 | u8 mask = 1 << (irqd_to_hwirq(d) % PL061_GPIO_NR); | 223 | u8 mask = 1 << (irqd_to_hwirq(d) % PL061_GPIO_NR); |
| 228 | u8 gpioie; | 224 | u8 gpioie; |
| 229 | 225 | ||
| @@ -233,50 +229,11 @@ static void pl061_irq_unmask(struct irq_data *d) | |||
| 233 | spin_unlock(&chip->lock); | 229 | spin_unlock(&chip->lock); |
| 234 | } | 230 | } |
| 235 | 231 | ||
| 236 | static int pl061_irq_reqres(struct irq_data *d) | ||
| 237 | { | ||
| 238 | struct pl061_gpio *chip = irq_data_get_irq_chip_data(d); | ||
| 239 | |||
| 240 | if (gpio_lock_as_irq(&chip->gc, irqd_to_hwirq(d))) { | ||
| 241 | dev_err(chip->gc.dev, | ||
| 242 | "unable to lock HW IRQ %lu for IRQ\n", | ||
| 243 | irqd_to_hwirq(d)); | ||
| 244 | return -EINVAL; | ||
| 245 | } | ||
| 246 | return 0; | ||
| 247 | } | ||
| 248 | |||
| 249 | static void pl061_irq_relres(struct irq_data *d) | ||
| 250 | { | ||
| 251 | struct pl061_gpio *chip = irq_data_get_irq_chip_data(d); | ||
| 252 | |||
| 253 | gpio_unlock_as_irq(&chip->gc, irqd_to_hwirq(d)); | ||
| 254 | } | ||
| 255 | |||
| 256 | static struct irq_chip pl061_irqchip = { | 232 | static struct irq_chip pl061_irqchip = { |
| 257 | .name = "pl061", | 233 | .name = "pl061", |
| 258 | .irq_mask = pl061_irq_mask, | 234 | .irq_mask = pl061_irq_mask, |
| 259 | .irq_unmask = pl061_irq_unmask, | 235 | .irq_unmask = pl061_irq_unmask, |
| 260 | .irq_set_type = pl061_irq_type, | 236 | .irq_set_type = pl061_irq_type, |
| 261 | .irq_request_resources = pl061_irq_reqres, | ||
| 262 | .irq_release_resources = pl061_irq_relres, | ||
| 263 | }; | ||
| 264 | |||
| 265 | static int pl061_irq_map(struct irq_domain *d, unsigned int irq, | ||
| 266 | irq_hw_number_t hwirq) | ||
| 267 | { | ||
| 268 | struct pl061_gpio *chip = d->host_data; | ||
| 269 | |||
| 270 | irq_set_chip_and_handler(irq, &pl061_irqchip, handle_simple_irq); | ||
| 271 | irq_set_chip_data(irq, chip); | ||
| 272 | irq_set_irq_type(irq, IRQ_TYPE_NONE); | ||
| 273 | |||
| 274 | return 0; | ||
| 275 | } | ||
| 276 | |||
| 277 | static const struct irq_domain_ops pl061_domain_ops = { | ||
| 278 | .map = pl061_irq_map, | ||
| 279 | .xlate = irq_domain_xlate_twocell, | ||
| 280 | }; | 237 | }; |
| 281 | 238 | ||
| 282 | static int pl061_probe(struct amba_device *adev, const struct amba_id *id) | 239 | static int pl061_probe(struct amba_device *adev, const struct amba_id *id) |
| @@ -314,7 +271,6 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id) | |||
| 314 | chip->gc.direction_output = pl061_direction_output; | 271 | chip->gc.direction_output = pl061_direction_output; |
| 315 | chip->gc.get = pl061_get_value; | 272 | chip->gc.get = pl061_get_value; |
| 316 | chip->gc.set = pl061_set_value; | 273 | chip->gc.set = pl061_set_value; |
| 317 | chip->gc.to_irq = pl061_to_irq; | ||
| 318 | chip->gc.ngpio = PL061_GPIO_NR; | 274 | chip->gc.ngpio = PL061_GPIO_NR; |
| 319 | chip->gc.label = dev_name(dev); | 275 | chip->gc.label = dev_name(dev); |
| 320 | chip->gc.dev = dev; | 276 | chip->gc.dev = dev; |
| @@ -334,15 +290,15 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id) | |||
| 334 | return -ENODEV; | 290 | return -ENODEV; |
| 335 | } | 291 | } |
| 336 | 292 | ||
| 337 | irq_set_chained_handler(irq, pl061_irq_handler); | 293 | ret = gpiochip_irqchip_add(&chip->gc, &pl061_irqchip, |
| 338 | irq_set_handler_data(irq, chip); | 294 | irq_base, handle_simple_irq, |
| 339 | 295 | IRQ_TYPE_NONE); | |
| 340 | chip->domain = irq_domain_add_simple(adev->dev.of_node, PL061_GPIO_NR, | 296 | if (ret) { |
| 341 | irq_base, &pl061_domain_ops, chip); | 297 | dev_info(&adev->dev, "could not add irqchip\n"); |
| 342 | if (!chip->domain) { | 298 | return ret; |
| 343 | dev_err(&adev->dev, "no irq domain\n"); | ||
| 344 | return -ENODEV; | ||
| 345 | } | 299 | } |
| 300 | gpiochip_set_chained_irqchip(&chip->gc, &pl061_irqchip, | ||
| 301 | irq, pl061_irq_handler); | ||
| 346 | 302 | ||
| 347 | for (i = 0; i < PL061_GPIO_NR; i++) { | 303 | for (i = 0; i < PL061_GPIO_NR; i++) { |
| 348 | if (pdata) { | 304 | if (pdata) { |
