diff options
-rw-r--r-- | drivers/gpio/Kconfig | 2 | ||||
-rw-r--r-- | drivers/gpio/gpio-brcmstb.c | 188 |
2 files changed, 146 insertions, 44 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index e7f3f39e69df..f002edda555b 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -139,7 +139,7 @@ config GPIO_BRCMSTB | |||
139 | default y if (ARCH_BRCMSTB || BMIPS_GENERIC) | 139 | default y if (ARCH_BRCMSTB || BMIPS_GENERIC) |
140 | depends on OF_GPIO && (ARCH_BRCMSTB || BMIPS_GENERIC || COMPILE_TEST) | 140 | depends on OF_GPIO && (ARCH_BRCMSTB || BMIPS_GENERIC || COMPILE_TEST) |
141 | select GPIO_GENERIC | 141 | select GPIO_GENERIC |
142 | select GPIOLIB_IRQCHIP | 142 | select IRQ_DOMAIN |
143 | help | 143 | help |
144 | Say yes here to enable GPIO support for Broadcom STB (BCM7XXX) SoCs. | 144 | Say yes here to enable GPIO support for Broadcom STB (BCM7XXX) SoCs. |
145 | 145 | ||
diff --git a/drivers/gpio/gpio-brcmstb.c b/drivers/gpio/gpio-brcmstb.c index 183863902f7f..9a8c603625a3 100644 --- a/drivers/gpio/gpio-brcmstb.c +++ b/drivers/gpio/gpio-brcmstb.c | |||
@@ -38,20 +38,22 @@ struct brcmstb_gpio_bank { | |||
38 | struct gpio_chip gc; | 38 | struct gpio_chip gc; |
39 | struct brcmstb_gpio_priv *parent_priv; | 39 | struct brcmstb_gpio_priv *parent_priv; |
40 | u32 width; | 40 | u32 width; |
41 | struct irq_chip irq_chip; | ||
42 | }; | 41 | }; |
43 | 42 | ||
44 | struct brcmstb_gpio_priv { | 43 | struct brcmstb_gpio_priv { |
45 | struct list_head bank_list; | 44 | struct list_head bank_list; |
46 | void __iomem *reg_base; | 45 | void __iomem *reg_base; |
47 | struct platform_device *pdev; | 46 | struct platform_device *pdev; |
47 | struct irq_domain *irq_domain; | ||
48 | struct irq_chip irq_chip; | ||
48 | int parent_irq; | 49 | int parent_irq; |
49 | int gpio_base; | 50 | int gpio_base; |
51 | int num_gpios; | ||
50 | int parent_wake_irq; | 52 | int parent_wake_irq; |
51 | struct notifier_block reboot_notifier; | 53 | struct notifier_block reboot_notifier; |
52 | }; | 54 | }; |
53 | 55 | ||
54 | #define MAX_GPIO_PER_BANK 32 | 56 | #define MAX_GPIO_PER_BANK 32 |
55 | #define GPIO_BANK(gpio) ((gpio) >> 5) | 57 | #define GPIO_BANK(gpio) ((gpio) >> 5) |
56 | /* assumes MAX_GPIO_PER_BANK is a multiple of 2 */ | 58 | /* assumes MAX_GPIO_PER_BANK is a multiple of 2 */ |
57 | #define GPIO_BIT(gpio) ((gpio) & (MAX_GPIO_PER_BANK - 1)) | 59 | #define GPIO_BIT(gpio) ((gpio) & (MAX_GPIO_PER_BANK - 1)) |
@@ -78,24 +80,42 @@ brcmstb_gpio_get_active_irqs(struct brcmstb_gpio_bank *bank) | |||
78 | return status; | 80 | return status; |
79 | } | 81 | } |
80 | 82 | ||
83 | static int brcmstb_gpio_hwirq_to_offset(irq_hw_number_t hwirq, | ||
84 | struct brcmstb_gpio_bank *bank) | ||
85 | { | ||
86 | return hwirq - (bank->gc.base - bank->parent_priv->gpio_base); | ||
87 | } | ||
88 | |||
81 | static void brcmstb_gpio_set_imask(struct brcmstb_gpio_bank *bank, | 89 | static void brcmstb_gpio_set_imask(struct brcmstb_gpio_bank *bank, |
82 | unsigned int offset, bool enable) | 90 | unsigned int hwirq, bool enable) |
83 | { | 91 | { |
84 | struct gpio_chip *gc = &bank->gc; | 92 | struct gpio_chip *gc = &bank->gc; |
85 | struct brcmstb_gpio_priv *priv = bank->parent_priv; | 93 | struct brcmstb_gpio_priv *priv = bank->parent_priv; |
94 | u32 mask = BIT(brcmstb_gpio_hwirq_to_offset(hwirq, bank)); | ||
86 | u32 imask; | 95 | u32 imask; |
87 | unsigned long flags; | 96 | unsigned long flags; |
88 | 97 | ||
89 | spin_lock_irqsave(&gc->bgpio_lock, flags); | 98 | spin_lock_irqsave(&gc->bgpio_lock, flags); |
90 | imask = gc->read_reg(priv->reg_base + GIO_MASK(bank->id)); | 99 | imask = gc->read_reg(priv->reg_base + GIO_MASK(bank->id)); |
91 | if (enable) | 100 | if (enable) |
92 | imask |= BIT(offset); | 101 | imask |= mask; |
93 | else | 102 | else |
94 | imask &= ~BIT(offset); | 103 | imask &= ~mask; |
95 | gc->write_reg(priv->reg_base + GIO_MASK(bank->id), imask); | 104 | gc->write_reg(priv->reg_base + GIO_MASK(bank->id), imask); |
96 | spin_unlock_irqrestore(&gc->bgpio_lock, flags); | 105 | spin_unlock_irqrestore(&gc->bgpio_lock, flags); |
97 | } | 106 | } |
98 | 107 | ||
108 | static int brcmstb_gpio_to_irq(struct gpio_chip *gc, unsigned offset) | ||
109 | { | ||
110 | struct brcmstb_gpio_priv *priv = brcmstb_gpio_gc_to_priv(gc); | ||
111 | /* gc_offset is relative to this gpio_chip; want real offset */ | ||
112 | int hwirq = offset + (gc->base - priv->gpio_base); | ||
113 | |||
114 | if (hwirq >= priv->num_gpios) | ||
115 | return -ENXIO; | ||
116 | return irq_create_mapping(priv->irq_domain, hwirq); | ||
117 | } | ||
118 | |||
99 | /* -------------------- IRQ chip functions -------------------- */ | 119 | /* -------------------- IRQ chip functions -------------------- */ |
100 | 120 | ||
101 | static void brcmstb_gpio_irq_mask(struct irq_data *d) | 121 | static void brcmstb_gpio_irq_mask(struct irq_data *d) |
@@ -119,7 +139,7 @@ static void brcmstb_gpio_irq_ack(struct irq_data *d) | |||
119 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); | 139 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
120 | struct brcmstb_gpio_bank *bank = gpiochip_get_data(gc); | 140 | struct brcmstb_gpio_bank *bank = gpiochip_get_data(gc); |
121 | struct brcmstb_gpio_priv *priv = bank->parent_priv; | 141 | struct brcmstb_gpio_priv *priv = bank->parent_priv; |
122 | u32 mask = BIT(d->hwirq); | 142 | u32 mask = BIT(brcmstb_gpio_hwirq_to_offset(d->hwirq, bank)); |
123 | 143 | ||
124 | gc->write_reg(priv->reg_base + GIO_STAT(bank->id), mask); | 144 | gc->write_reg(priv->reg_base + GIO_STAT(bank->id), mask); |
125 | } | 145 | } |
@@ -129,7 +149,7 @@ static int brcmstb_gpio_irq_set_type(struct irq_data *d, unsigned int type) | |||
129 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); | 149 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
130 | struct brcmstb_gpio_bank *bank = gpiochip_get_data(gc); | 150 | struct brcmstb_gpio_bank *bank = gpiochip_get_data(gc); |
131 | struct brcmstb_gpio_priv *priv = bank->parent_priv; | 151 | struct brcmstb_gpio_priv *priv = bank->parent_priv; |
132 | u32 mask = BIT(d->hwirq); | 152 | u32 mask = BIT(brcmstb_gpio_hwirq_to_offset(d->hwirq, bank)); |
133 | u32 edge_insensitive, iedge_insensitive; | 153 | u32 edge_insensitive, iedge_insensitive; |
134 | u32 edge_config, iedge_config; | 154 | u32 edge_config, iedge_config; |
135 | u32 level, ilevel; | 155 | u32 level, ilevel; |
@@ -226,18 +246,20 @@ static irqreturn_t brcmstb_gpio_wake_irq_handler(int irq, void *data) | |||
226 | static void brcmstb_gpio_irq_bank_handler(struct brcmstb_gpio_bank *bank) | 246 | static void brcmstb_gpio_irq_bank_handler(struct brcmstb_gpio_bank *bank) |
227 | { | 247 | { |
228 | struct brcmstb_gpio_priv *priv = bank->parent_priv; | 248 | struct brcmstb_gpio_priv *priv = bank->parent_priv; |
229 | struct irq_domain *irq_domain = bank->gc.irqdomain; | 249 | struct irq_domain *domain = priv->irq_domain; |
250 | int hwbase = bank->gc.base - priv->gpio_base; | ||
230 | unsigned long status; | 251 | unsigned long status; |
231 | 252 | ||
232 | while ((status = brcmstb_gpio_get_active_irqs(bank))) { | 253 | while ((status = brcmstb_gpio_get_active_irqs(bank))) { |
233 | int bit; | 254 | unsigned int irq, offset; |
234 | 255 | ||
235 | for_each_set_bit(bit, &status, 32) { | 256 | for_each_set_bit(offset, &status, 32) { |
236 | if (bit >= bank->width) | 257 | if (offset >= bank->width) |
237 | dev_warn(&priv->pdev->dev, | 258 | dev_warn(&priv->pdev->dev, |
238 | "IRQ for invalid GPIO (bank=%d, offset=%d)\n", | 259 | "IRQ for invalid GPIO (bank=%d, offset=%d)\n", |
239 | bank->id, bit); | 260 | bank->id, offset); |
240 | generic_handle_irq(irq_find_mapping(irq_domain, bit)); | 261 | irq = irq_linear_revmap(domain, hwbase + offset); |
262 | generic_handle_irq(irq); | ||
241 | } | 263 | } |
242 | } | 264 | } |
243 | } | 265 | } |
@@ -245,8 +267,7 @@ static void brcmstb_gpio_irq_bank_handler(struct brcmstb_gpio_bank *bank) | |||
245 | /* Each UPG GIO block has one IRQ for all banks */ | 267 | /* Each UPG GIO block has one IRQ for all banks */ |
246 | static void brcmstb_gpio_irq_handler(struct irq_desc *desc) | 268 | static void brcmstb_gpio_irq_handler(struct irq_desc *desc) |
247 | { | 269 | { |
248 | struct gpio_chip *gc = irq_desc_get_handler_data(desc); | 270 | struct brcmstb_gpio_priv *priv = irq_desc_get_handler_data(desc); |
249 | struct brcmstb_gpio_priv *priv = brcmstb_gpio_gc_to_priv(gc); | ||
250 | struct irq_chip *chip = irq_desc_get_chip(desc); | 271 | struct irq_chip *chip = irq_desc_get_chip(desc); |
251 | struct brcmstb_gpio_bank *bank; | 272 | struct brcmstb_gpio_bank *bank; |
252 | 273 | ||
@@ -272,6 +293,63 @@ static int brcmstb_gpio_reboot(struct notifier_block *nb, | |||
272 | return NOTIFY_DONE; | 293 | return NOTIFY_DONE; |
273 | } | 294 | } |
274 | 295 | ||
296 | static struct brcmstb_gpio_bank *brcmstb_gpio_hwirq_to_bank( | ||
297 | struct brcmstb_gpio_priv *priv, irq_hw_number_t hwirq) | ||
298 | { | ||
299 | struct brcmstb_gpio_bank *bank; | ||
300 | int i = 0; | ||
301 | |||
302 | /* banks are in descending order */ | ||
303 | list_for_each_entry_reverse(bank, &priv->bank_list, node) { | ||
304 | i += bank->gc.ngpio; | ||
305 | if (hwirq < i) | ||
306 | return bank; | ||
307 | } | ||
308 | return NULL; | ||
309 | } | ||
310 | |||
311 | /* | ||
312 | * This lock class tells lockdep that GPIO irqs are in a different | ||
313 | * category than their parents, so it won't report false recursion. | ||
314 | */ | ||
315 | static struct lock_class_key brcmstb_gpio_irq_lock_class; | ||
316 | |||
317 | |||
318 | static int brcmstb_gpio_irq_map(struct irq_domain *d, unsigned int irq, | ||
319 | irq_hw_number_t hwirq) | ||
320 | { | ||
321 | struct brcmstb_gpio_priv *priv = d->host_data; | ||
322 | struct brcmstb_gpio_bank *bank = | ||
323 | brcmstb_gpio_hwirq_to_bank(priv, hwirq); | ||
324 | struct platform_device *pdev = priv->pdev; | ||
325 | int ret; | ||
326 | |||
327 | if (!bank) | ||
328 | return -EINVAL; | ||
329 | |||
330 | dev_dbg(&pdev->dev, "Mapping irq %d for gpio line %d (bank %d)\n", | ||
331 | irq, (int)hwirq, bank->id); | ||
332 | ret = irq_set_chip_data(irq, &bank->gc); | ||
333 | if (ret < 0) | ||
334 | return ret; | ||
335 | irq_set_lockdep_class(irq, &brcmstb_gpio_irq_lock_class); | ||
336 | irq_set_chip_and_handler(irq, &priv->irq_chip, handle_level_irq); | ||
337 | irq_set_noprobe(irq); | ||
338 | return 0; | ||
339 | } | ||
340 | |||
341 | static void brcmstb_gpio_irq_unmap(struct irq_domain *d, unsigned int irq) | ||
342 | { | ||
343 | irq_set_chip_and_handler(irq, NULL, NULL); | ||
344 | irq_set_chip_data(irq, NULL); | ||
345 | } | ||
346 | |||
347 | static const struct irq_domain_ops brcmstb_gpio_irq_domain_ops = { | ||
348 | .map = brcmstb_gpio_irq_map, | ||
349 | .unmap = brcmstb_gpio_irq_unmap, | ||
350 | .xlate = irq_domain_xlate_twocell, | ||
351 | }; | ||
352 | |||
275 | /* Make sure that the number of banks matches up between properties */ | 353 | /* Make sure that the number of banks matches up between properties */ |
276 | static int brcmstb_gpio_sanity_check_banks(struct device *dev, | 354 | static int brcmstb_gpio_sanity_check_banks(struct device *dev, |
277 | struct device_node *np, struct resource *res) | 355 | struct device_node *np, struct resource *res) |
@@ -293,13 +371,25 @@ static int brcmstb_gpio_remove(struct platform_device *pdev) | |||
293 | { | 371 | { |
294 | struct brcmstb_gpio_priv *priv = platform_get_drvdata(pdev); | 372 | struct brcmstb_gpio_priv *priv = platform_get_drvdata(pdev); |
295 | struct brcmstb_gpio_bank *bank; | 373 | struct brcmstb_gpio_bank *bank; |
296 | int ret = 0; | 374 | int offset, ret = 0, virq; |
297 | 375 | ||
298 | if (!priv) { | 376 | if (!priv) { |
299 | dev_err(&pdev->dev, "called %s without drvdata!\n", __func__); | 377 | dev_err(&pdev->dev, "called %s without drvdata!\n", __func__); |
300 | return -EFAULT; | 378 | return -EFAULT; |
301 | } | 379 | } |
302 | 380 | ||
381 | if (priv->parent_irq > 0) | ||
382 | irq_set_chained_handler_and_data(priv->parent_irq, NULL, NULL); | ||
383 | |||
384 | /* Remove all IRQ mappings and delete the domain */ | ||
385 | if (priv->irq_domain) { | ||
386 | for (offset = 0; offset < priv->num_gpios; offset++) { | ||
387 | virq = irq_find_mapping(priv->irq_domain, offset); | ||
388 | irq_dispose_mapping(virq); | ||
389 | } | ||
390 | irq_domain_remove(priv->irq_domain); | ||
391 | } | ||
392 | |||
303 | /* | 393 | /* |
304 | * You can lose return values below, but we report all errors, and it's | 394 | * You can lose return values below, but we report all errors, and it's |
305 | * more important to actually perform all of the steps. | 395 | * more important to actually perform all of the steps. |
@@ -347,26 +437,24 @@ static int brcmstb_gpio_of_xlate(struct gpio_chip *gc, | |||
347 | return offset; | 437 | return offset; |
348 | } | 438 | } |
349 | 439 | ||
350 | /* Before calling, must have bank->parent_irq set and gpiochip registered */ | 440 | /* priv->parent_irq and priv->num_gpios must be set before calling */ |
351 | static int brcmstb_gpio_irq_setup(struct platform_device *pdev, | 441 | static int brcmstb_gpio_irq_setup(struct platform_device *pdev, |
352 | struct brcmstb_gpio_bank *bank) | 442 | struct brcmstb_gpio_priv *priv) |
353 | { | 443 | { |
354 | struct brcmstb_gpio_priv *priv = bank->parent_priv; | ||
355 | struct device *dev = &pdev->dev; | 444 | struct device *dev = &pdev->dev; |
356 | struct device_node *np = dev->of_node; | 445 | struct device_node *np = dev->of_node; |
357 | int err; | 446 | int err; |
358 | 447 | ||
359 | bank->irq_chip.name = dev_name(dev); | 448 | priv->irq_domain = |
360 | bank->irq_chip.irq_mask = brcmstb_gpio_irq_mask; | 449 | irq_domain_add_linear(np, priv->num_gpios, |
361 | bank->irq_chip.irq_unmask = brcmstb_gpio_irq_unmask; | 450 | &brcmstb_gpio_irq_domain_ops, |
362 | bank->irq_chip.irq_ack = brcmstb_gpio_irq_ack; | 451 | priv); |
363 | bank->irq_chip.irq_set_type = brcmstb_gpio_irq_set_type; | 452 | if (!priv->irq_domain) { |
364 | 453 | dev_err(dev, "Couldn't allocate IRQ domain\n"); | |
365 | /* Ensures that all non-wakeup IRQs are disabled at suspend */ | 454 | return -ENXIO; |
366 | bank->irq_chip.flags = IRQCHIP_MASK_ON_SUSPEND; | 455 | } |
367 | 456 | ||
368 | if (IS_ENABLED(CONFIG_PM_SLEEP) && !priv->parent_wake_irq && | 457 | if (of_property_read_bool(np, "wakeup-source")) { |
369 | of_property_read_bool(np, "wakeup-source")) { | ||
370 | priv->parent_wake_irq = platform_get_irq(pdev, 1); | 458 | priv->parent_wake_irq = platform_get_irq(pdev, 1); |
371 | if (priv->parent_wake_irq < 0) { | 459 | if (priv->parent_wake_irq < 0) { |
372 | priv->parent_wake_irq = 0; | 460 | priv->parent_wake_irq = 0; |
@@ -387,7 +475,7 @@ static int brcmstb_gpio_irq_setup(struct platform_device *pdev, | |||
387 | 475 | ||
388 | if (err < 0) { | 476 | if (err < 0) { |
389 | dev_err(dev, "Couldn't request wake IRQ"); | 477 | dev_err(dev, "Couldn't request wake IRQ"); |
390 | return err; | 478 | goto out_free_domain; |
391 | } | 479 | } |
392 | 480 | ||
393 | priv->reboot_notifier.notifier_call = | 481 | priv->reboot_notifier.notifier_call = |
@@ -396,17 +484,28 @@ static int brcmstb_gpio_irq_setup(struct platform_device *pdev, | |||
396 | } | 484 | } |
397 | } | 485 | } |
398 | 486 | ||
487 | priv->irq_chip.name = dev_name(dev); | ||
488 | priv->irq_chip.irq_disable = brcmstb_gpio_irq_mask; | ||
489 | priv->irq_chip.irq_mask = brcmstb_gpio_irq_mask; | ||
490 | priv->irq_chip.irq_unmask = brcmstb_gpio_irq_unmask; | ||
491 | priv->irq_chip.irq_ack = brcmstb_gpio_irq_ack; | ||
492 | priv->irq_chip.irq_set_type = brcmstb_gpio_irq_set_type; | ||
493 | |||
494 | /* Ensures that all non-wakeup IRQs are disabled at suspend */ | ||
495 | priv->irq_chip.flags = IRQCHIP_MASK_ON_SUSPEND; | ||
496 | |||
399 | if (priv->parent_wake_irq) | 497 | if (priv->parent_wake_irq) |
400 | bank->irq_chip.irq_set_wake = brcmstb_gpio_irq_set_wake; | 498 | priv->irq_chip.irq_set_wake = brcmstb_gpio_irq_set_wake; |
401 | 499 | ||
402 | err = gpiochip_irqchip_add(&bank->gc, &bank->irq_chip, 0, | 500 | irq_set_chained_handler_and_data(priv->parent_irq, |
403 | handle_level_irq, IRQ_TYPE_NONE); | 501 | brcmstb_gpio_irq_handler, priv); |
404 | if (err) | ||
405 | return err; | ||
406 | gpiochip_set_chained_irqchip(&bank->gc, &bank->irq_chip, | ||
407 | priv->parent_irq, brcmstb_gpio_irq_handler); | ||
408 | 502 | ||
409 | return 0; | 503 | return 0; |
504 | |||
505 | out_free_domain: | ||
506 | irq_domain_remove(priv->irq_domain); | ||
507 | |||
508 | return err; | ||
410 | } | 509 | } |
411 | 510 | ||
412 | static int brcmstb_gpio_probe(struct platform_device *pdev) | 511 | static int brcmstb_gpio_probe(struct platform_device *pdev) |
@@ -511,6 +610,8 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) | |||
511 | gc->of_xlate = brcmstb_gpio_of_xlate; | 610 | gc->of_xlate = brcmstb_gpio_of_xlate; |
512 | /* not all ngpio lines are valid, will use bank width later */ | 611 | /* not all ngpio lines are valid, will use bank width later */ |
513 | gc->ngpio = MAX_GPIO_PER_BANK; | 612 | gc->ngpio = MAX_GPIO_PER_BANK; |
613 | if (priv->parent_irq > 0) | ||
614 | gc->to_irq = brcmstb_gpio_to_irq; | ||
514 | 615 | ||
515 | /* | 616 | /* |
516 | * Mask all interrupts by default, since wakeup interrupts may | 617 | * Mask all interrupts by default, since wakeup interrupts may |
@@ -526,12 +627,6 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) | |||
526 | } | 627 | } |
527 | gpio_base += gc->ngpio; | 628 | gpio_base += gc->ngpio; |
528 | 629 | ||
529 | if (priv->parent_irq > 0) { | ||
530 | err = brcmstb_gpio_irq_setup(pdev, bank); | ||
531 | if (err) | ||
532 | goto fail; | ||
533 | } | ||
534 | |||
535 | dev_dbg(dev, "bank=%d, base=%d, ngpio=%d, width=%d\n", bank->id, | 630 | dev_dbg(dev, "bank=%d, base=%d, ngpio=%d, width=%d\n", bank->id, |
536 | gc->base, gc->ngpio, bank->width); | 631 | gc->base, gc->ngpio, bank->width); |
537 | 632 | ||
@@ -541,6 +636,13 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) | |||
541 | num_banks++; | 636 | num_banks++; |
542 | } | 637 | } |
543 | 638 | ||
639 | priv->num_gpios = gpio_base - priv->gpio_base; | ||
640 | if (priv->parent_irq > 0) { | ||
641 | err = brcmstb_gpio_irq_setup(pdev, priv); | ||
642 | if (err) | ||
643 | goto fail; | ||
644 | } | ||
645 | |||
544 | dev_info(dev, "Registered %d banks (GPIO(s): %d-%d)\n", | 646 | dev_info(dev, "Registered %d banks (GPIO(s): %d-%d)\n", |
545 | num_banks, priv->gpio_base, gpio_base - 1); | 647 | num_banks, priv->gpio_base, gpio_base - 1); |
546 | 648 | ||