* irq/gpio-immutable: : . : First try at preventing the GPIO subsystem from abusing irq_chip : data structures. The general idea is to have an irq_chip flag : to tell the GPIO subsystem that these structures are immutable, : and to convert drivers one by one. : . Documentation: Update the recommended pattern for GPIO irqchips gpio: Update TODO to mention immutable irq_chip structures pinctrl: amd: Make the irqchip immutable pinctrl: msmgpio: Make the irqchip immutable pinctrl: apple-gpio: Make the irqchip immutable gpio: pl061: Make the irqchip immutable gpio: tegra186: Make the irqchip immutable gpio: Add helpers to ease the transition towards immutable irq_chip gpio: Expose the gpiochip_irq_re[ql]res helpers gpio: Don't fiddle with irqchips marked as immutable
Unified · Split
| @@ -417,30 +417,66 @@ struct gpio_irq_chip inside struct gpio_chip before adding the gpio_chip. · 416 unmodified lines | ||
| 417 | 417 | If you do this, the additional irq_chip will be set up by gpiolib at the |
| 418 | 418 | same time as setting up the rest of the GPIO functionality. The following |
| 419 | 419 | is a typical example of a chained cascaded interrupt handler using |
| 420 | −the gpio_irq_chip: | |
| 420 | +the gpio_irq_chip. Note how the mask/unmask (or disable/enable) functions | |
| 421 | +call into the core gpiolib code: | |
| 421 | 422 | |
| 422 | 423 | .. code-block:: c |
| 423 | 424 | |
| 424 | − /* Typical state container with dynamic irqchip */ | |
| 425 | + /* Typical state container */ | |
| 425 | 426 | struct my_gpio { |
| 426 | 427 | struct gpio_chip gc; |
| 427 | − struct irq_chip irq; | |
| 428 | + }; | |
| 429 | + | |
| 430 | + static void my_gpio_mask_irq(struct irq_data *d) | |
| 431 | + { | |
| 432 | + struct gpio_chip *gc = irq_desc_get_handler_data(d); | |
| 433 | + | |
| 434 | + /* | |
| 435 | + * Perform any necessary action to mask the interrupt, | |
| 436 | + * and then call into the core code to synchronise the | |
| 437 | + * state. | |
| 438 | + */ | |
| 439 | + | |
| 440 | + gpiochip_disable_irq(gc, d->hwirq); | |
| 441 | + } | |
| 442 | + | |
| 443 | + static void my_gpio_unmask_irq(struct irq_data *d) | |
| 444 | + { | |
| 445 | + struct gpio_chip *gc = irq_desc_get_handler_data(d); | |
| 446 | + | |
| 447 | + gpiochip_enable_irq(gc, d->hwirq); | |
| 448 | + | |
| 449 | + /* | |
| 450 | + * Perform any necessary action to unmask the interrupt, | |
| 451 | + * after having called into the core code to synchronise | |
| 452 | + * the state. | |
| 453 | + */ | |
| 454 | + } | |
| 455 | + | |
| 456 | + /* | |
| 457 | + * Statically populate the irqchip. Note that it is made const | |
| 458 | + * (further indicated by the IRQCHIP_IMMUTABLE flag), and that | |
| 459 | + * the GPIOCHIP_IRQ_RESOURCE_HELPER macro adds some extra | |
| 460 | + * callbacks to the structure. | |
| 461 | + */ | |
| 462 | + static const struct irq_chip my_gpio_irq_chip = { | |
| 463 | + .name = "my_gpio_irq", | |
| 464 | + .irq_ack = my_gpio_ack_irq, | |
| 465 | + .irq_mask = my_gpio_mask_irq, | |
| 466 | + .irq_unmask = my_gpio_unmask_irq, | |
| 467 | + .irq_set_type = my_gpio_set_irq_type, | |
| 468 | + .flags = IRQCHIP_IMMUTABLE, | |
| 469 | + /* Provide the gpio resource callbacks */ | |
| 470 | + GPIOCHIP_IRQ_RESOURCE_HELPERS, | |
| 428 | 471 | }; |
| 429 | 472 | |
| 430 | 473 | int irq; /* from platform etc */ |
| 431 | 474 | struct my_gpio *g; |
| 432 | 475 | struct gpio_irq_chip *girq; |
| 433 | 476 | |
| 434 | − /* Set up the irqchip dynamically */ | |
| 435 | − g->irq.name = "my_gpio_irq"; | |
| 436 | − g->irq.irq_ack = my_gpio_ack_irq; | |
| 437 | − g->irq.irq_mask = my_gpio_mask_irq; | |
| 438 | − g->irq.irq_unmask = my_gpio_unmask_irq; | |
| 439 | − g->irq.irq_set_type = my_gpio_set_irq_type; | |
| 440 | − | |
| 441 | 477 | /* Get a pointer to the gpio_irq_chip */ |
| 442 | 478 | girq = &g->gc.irq; |
| 443 | − girq->chip = &g->irq; | |
| 479 | + gpio_irq_chip_set_chip(girq, &my_gpio_irq_chip); | |
| 444 | 480 | girq->parent_handler = ftgpio_gpio_irq_handler; |
| 445 | 481 | girq->num_parents = 1; |
| 446 | 482 | girq->parents = devm_kcalloc(dev, 1, sizeof(*girq->parents), |
| @@ -458,23 +494,58 @@ the interrupt separately and go with it: · 11 unmodified lines | ||
| 458 | 494 | |
| 459 | 495 | .. code-block:: c |
| 460 | 496 | |
| 461 | − /* Typical state container with dynamic irqchip */ | |
| 497 | + /* Typical state container */ | |
| 462 | 498 | struct my_gpio { |
| 463 | 499 | struct gpio_chip gc; |
| 464 | − struct irq_chip irq; | |
| 500 | + }; | |
| 501 | + | |
| 502 | + static void my_gpio_mask_irq(struct irq_data *d) | |
| 503 | + { | |
| 504 | + struct gpio_chip *gc = irq_desc_get_handler_data(d); | |
| 505 | + | |
| 506 | + /* | |
| 507 | + * Perform any necessary action to mask the interrupt, | |
| 508 | + * and then call into the core code to synchronise the | |
| 509 | + * state. | |
| 510 | + */ | |
| 511 | + | |
| 512 | + gpiochip_disable_irq(gc, d->hwirq); | |
| 513 | + } | |
| 514 | + | |
| 515 | + static void my_gpio_unmask_irq(struct irq_data *d) | |
| 516 | + { | |
| 517 | + struct gpio_chip *gc = irq_desc_get_handler_data(d); | |
| 518 | + | |
| 519 | + gpiochip_enable_irq(gc, d->hwirq); | |
| 520 | + | |
| 521 | + /* | |
| 522 | + * Perform any necessary action to unmask the interrupt, | |
| 523 | + * after having called into the core code to synchronise | |
| 524 | + * the state. | |
| 525 | + */ | |
| 526 | + } | |
| 527 | + | |
| 528 | + /* | |
| 529 | + * Statically populate the irqchip. Note that it is made const | |
| 530 | + * (further indicated by the IRQCHIP_IMMUTABLE flag), and that | |
| 531 | + * the GPIOCHIP_IRQ_RESOURCE_HELPER macro adds some extra | |
| 532 | + * callbacks to the structure. | |
| 533 | + */ | |
| 534 | + static const struct irq_chip my_gpio_irq_chip = { | |
| 535 | + .name = "my_gpio_irq", | |
| 536 | + .irq_ack = my_gpio_ack_irq, | |
| 537 | + .irq_mask = my_gpio_mask_irq, | |
| 538 | + .irq_unmask = my_gpio_unmask_irq, | |
| 539 | + .irq_set_type = my_gpio_set_irq_type, | |
| 540 | + .flags = IRQCHIP_IMMUTABLE, | |
| 541 | + /* Provide the gpio resource callbacks */ | |
| 542 | + GPIOCHIP_IRQ_RESOURCE_HELPERS, | |
| 465 | 543 | }; |
| 466 | 544 | |
| 467 | 545 | int irq; /* from platform etc */ |
| 468 | 546 | struct my_gpio *g; |
| 469 | 547 | struct gpio_irq_chip *girq; |
| 470 | 548 | |
| 471 | − /* Set up the irqchip dynamically */ | |
| 472 | − g->irq.name = "my_gpio_irq"; | |
| 473 | − g->irq.irq_ack = my_gpio_ack_irq; | |
| 474 | − g->irq.irq_mask = my_gpio_mask_irq; | |
| 475 | − g->irq.irq_unmask = my_gpio_unmask_irq; | |
| 476 | − g->irq.irq_set_type = my_gpio_set_irq_type; | |
| 477 | − | |
| 478 | 549 | ret = devm_request_threaded_irq(dev, irq, NULL, |
| 479 | 550 | irq_thread_fn, IRQF_ONESHOT, "my-chip", g); |
| 480 | 551 | if (ret < 0) |
| @@ -482,7 +553,7 @@ the interrupt separately and go with it: · 1 unmodified line | ||
| 482 | 553 | |
| 483 | 554 | /* Get a pointer to the gpio_irq_chip */ |
| 484 | 555 | girq = &g->gc.irq; |
| 485 | − girq->chip = &g->irq; | |
| 556 | + gpio_irq_chip_set_chip(girq, &my_gpio_irq_chip); | |
| 486 | 557 | /* This will let us handle the parent IRQ in the driver */ |
| 487 | 558 | girq->parent_handler = NULL; |
| 488 | 559 | girq->num_parents = 0; |
| @@ -500,24 +571,61 @@ In this case the typical set-up will look like this: · 11 unmodified lines | ||
| 500 | 571 | /* Typical state container with dynamic irqchip */ |
| 501 | 572 | struct my_gpio { |
| 502 | 573 | struct gpio_chip gc; |
| 503 | − struct irq_chip irq; | |
| 504 | 574 | struct fwnode_handle *fwnode; |
| 505 | 575 | }; |
| 506 | 576 | |
| 507 | − int irq; /* from platform etc */ | |
| 577 | + static void my_gpio_mask_irq(struct irq_data *d) | |
| 578 | + { | |
| 579 | + struct gpio_chip *gc = irq_desc_get_handler_data(d); | |
| 580 | + | |
| 581 | + /* | |
| 582 | + * Perform any necessary action to mask the interrupt, | |
| 583 | + * and then call into the core code to synchronise the | |
| 584 | + * state. | |
| 585 | + */ | |
| 586 | + | |
| 587 | + gpiochip_disable_irq(gc, d->hwirq); | |
| 588 | + irq_mask_mask_parent(d); | |
| 589 | + } | |
| 590 | + | |
| 591 | + static void my_gpio_unmask_irq(struct irq_data *d) | |
| 592 | + { | |
| 593 | + struct gpio_chip *gc = irq_desc_get_handler_data(d); | |
| 594 | + | |
| 595 | + gpiochip_enable_irq(gc, d->hwirq); | |
| 596 | + | |
| 597 | + /* | |
| 598 | + * Perform any necessary action to unmask the interrupt, | |
| 599 | + * after having called into the core code to synchronise | |
| 600 | + * the state. | |
| 601 | + */ | |
| 602 | + | |
| 603 | + irq_mask_unmask_parent(d); | |
| 604 | + } | |
| 605 | + | |
| 606 | + /* | |
| 607 | + * Statically populate the irqchip. Note that it is made const | |
| 608 | + * (further indicated by the IRQCHIP_IMMUTABLE flag), and that | |
| 609 | + * the GPIOCHIP_IRQ_RESOURCE_HELPER macro adds some extra | |
| 610 | + * callbacks to the structure. | |
| 611 | + */ | |
| 612 | + static const struct irq_chip my_gpio_irq_chip = { | |
| 613 | + .name = "my_gpio_irq", | |
| 614 | + .irq_ack = my_gpio_ack_irq, | |
| 615 | + .irq_mask = my_gpio_mask_irq, | |
| 616 | + .irq_unmask = my_gpio_unmask_irq, | |
| 617 | + .irq_set_type = my_gpio_set_irq_type, | |
| 618 | + .flags = IRQCHIP_IMMUTABLE, | |
| 619 | + /* Provide the gpio resource callbacks */ | |
| 620 | + GPIOCHIP_IRQ_RESOURCE_HELPERS, | |
| 621 | + }; | |
| 622 | + | |
| 508 | 623 | struct my_gpio *g; |
| 509 | 624 | struct gpio_irq_chip *girq; |
| 510 | 625 | |
| 511 | − /* Set up the irqchip dynamically */ | |
| 512 | − g->irq.name = "my_gpio_irq"; | |
| 513 | − g->irq.irq_ack = my_gpio_ack_irq; | |
| 514 | − g->irq.irq_mask = my_gpio_mask_irq; | |
| 515 | − g->irq.irq_unmask = my_gpio_unmask_irq; | |
| 516 | − g->irq.irq_set_type = my_gpio_set_irq_type; | |
| 517 | − | |
| 518 | 626 | /* Get a pointer to the gpio_irq_chip */ |
| 519 | 627 | girq = &g->gc.irq; |
| 520 | − girq->chip = &g->irq; | |
| 628 | + gpio_irq_chip_set_chip(girq, &my_gpio_irq_chip); | |
| 521 | 629 | girq->default_type = IRQ_TYPE_NONE; |
| 522 | 630 | girq->handler = handle_bad_irq; |
| 523 | 631 | girq->fwnode = g->fwnode; |
| @@ -605,8 +713,9 @@ When implementing an irqchip inside a GPIO driver, these two functions should · 81 unmodified lines | ||
| 605 | 713 | typically be called in the .irq_disable() and .irq_enable() callbacks from the |
| 606 | 714 | irqchip. |
| 607 | 715 | |
| 608 | −When using the gpiolib irqchip helpers, these callbacks are automatically | |
| 609 | −assigned. | |
| 716 | +When IRQCHIP_IMMUTABLE is not advertised by the irqchip, these callbacks | |
| 717 | +are automatically assigned. This behaviour is deprecated and on its way | |
| 718 | +to be removed from the kernel. | |
| 610 | 719 | |
| 611 | 720 | |
| 612 | 721 | Real-Time compliance for GPIO IRQ chips |
| @@ -178,3 +178,22 @@ discussed but the idea is to provide a low-level access point · 177 unmodified lines | ||
| 178 | 178 | for debugging and hacking and to expose all lines without the |
| 179 | 179 | need of any exporting. Also provide ample ammunition to shoot |
| 180 | 180 | oneself in the foot, because this is debugfs after all. |
| 181 | + | |
| 182 | + | |
| 183 | +Moving over to immutable irq_chip structures | |
| 184 | + | |
| 185 | +Most of the gpio chips implementing interrupt support rely on gpiolib | |
| 186 | +intercepting some of the irq_chip callbacks, preventing the structures | |
| 187 | +from being made read-only and forcing duplication of structures that | |
| 188 | +should otherwise be unique. | |
| 189 | + | |
| 190 | +The solution is to call into the gpiolib code when needed (resource | |
| 191 | +management, enable/disable or unmask/mask callbacks), and to let the | |
| 192 | +core code know about that by exposing a flag (IRQCHIP_IMMUTABLE) in | |
| 193 | +the irq_chip structure. The irq_chip structure can then be made unique | |
| 194 | +and const. | |
| 195 | + | |
| 196 | +A small number of drivers have been converted (pl061, tegra186, msm, | |
| 197 | +amd, apple), and can be used as examples of how to proceed with this | |
| 198 | +conversion. Note that drivers using the generic irqchip framework | |
| 199 | +cannot be converted yet, but watch this space! | |
| @@ -52,7 +52,6 @@ struct pl061 { · 51 unmodified lines | ||
| 52 | 52 | |
| 53 | 53 | void __iomem *base; |
| 54 | 54 | struct gpio_chip gc; |
| 55 | − struct irq_chip irq_chip; | |
| 56 | 55 | int parent_irq; |
| 57 | 56 | |
| 58 | 57 | #ifdef CONFIG_PM |
| @@ -241,6 +240,8 @@ static void pl061_irq_mask(struct irq_data *d) · 182 unmodified lines | ||
| 241 | 240 | gpioie = readb(pl061->base + GPIOIE) & ~mask; |
| 242 | 241 | writeb(gpioie, pl061->base + GPIOIE); |
| 243 | 242 | raw_spin_unlock(&pl061->lock); |
| 243 | + | |
| 244 | + gpiochip_disable_irq(gc, d->hwirq); | |
| 244 | 245 | } |
| 245 | 246 | |
| 246 | 247 | static void pl061_irq_unmask(struct irq_data *d) |
| @@ -250,6 +251,8 @@ static void pl061_irq_unmask(struct irq_data *d) · 3 unmodified lines | ||
| 250 | 251 | u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR); |
| 251 | 252 | u8 gpioie; |
| 252 | 253 | |
| 254 | + gpiochip_enable_irq(gc, d->hwirq); | |
| 255 | + | |
| 253 | 256 | raw_spin_lock(&pl061->lock); |
| 254 | 257 | gpioie = readb(pl061->base + GPIOIE) | mask; |
| 255 | 258 | writeb(gpioie, pl061->base + GPIOIE); |
| @@ -283,6 +286,24 @@ static int pl061_irq_set_wake(struct irq_data *d, unsigned int state) · 27 unmodified lines | ||
| 283 | 286 | return irq_set_irq_wake(pl061->parent_irq, state); |
| 284 | 287 | } |
| 285 | 288 | |
| 289 | +static void pl061_irq_print_chip(struct irq_data *data, struct seq_file *p) | |
| 290 | +{ | |
| 291 | + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); | |
| 292 | + | |
| 293 | + seq_printf(p, dev_name(gc->parent)); | |
| 294 | +} | |
| 295 | + | |
| 296 | +static const struct irq_chip pl061_irq_chip = { | |
| 297 | + .irq_ack = pl061_irq_ack, | |
| 298 | + .irq_mask = pl061_irq_mask, | |
| 299 | + .irq_unmask = pl061_irq_unmask, | |
| 300 | + .irq_set_type = pl061_irq_type, | |
| 301 | + .irq_set_wake = pl061_irq_set_wake, | |
| 302 | + .irq_print_chip = pl061_irq_print_chip, | |
| 303 | + .flags = IRQCHIP_IMMUTABLE, | |
| 304 | + GPIOCHIP_IRQ_RESOURCE_HELPERS, | |
| 305 | +}; | |
| 306 | + | |
| 286 | 307 | static int pl061_probe(struct amba_device *adev, const struct amba_id *id) |
| 287 | 308 | { |
| 288 | 309 | struct device *dev = &adev->dev; |
| @@ -315,13 +336,6 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id) · 26 unmodified lines | ||
| 315 | 336 | /* |
| 316 | 337 | * irq_chip support |
| 317 | 338 | */ |
| 318 | − pl061->irq_chip.name = dev_name(dev); | |
| 319 | − pl061->irq_chip.irq_ack = pl061_irq_ack; | |
| 320 | − pl061->irq_chip.irq_mask = pl061_irq_mask; | |
| 321 | − pl061->irq_chip.irq_unmask = pl061_irq_unmask; | |
| 322 | − pl061->irq_chip.irq_set_type = pl061_irq_type; | |
| 323 | − pl061->irq_chip.irq_set_wake = pl061_irq_set_wake; | |
| 324 | − | |
| 325 | 339 | writeb(0, pl061->base + GPIOIE); /* disable irqs */ |
| 326 | 340 | irq = adev->irq[0]; |
| 327 | 341 | if (!irq) |
| @@ -329,7 +343,7 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id) · 1 unmodified line | ||
| 329 | 343 | pl061->parent_irq = irq; |
| 330 | 344 | |
| 331 | 345 | girq = &pl061->gc.irq; |
| 332 | − girq->chip = &pl061->irq_chip; | |
| 346 | + gpio_irq_chip_set_chip(girq, &pl061_irq_chip); | |
| 333 | 347 | girq->parent_handler = pl061_irq_handler; |
| 334 | 348 | girq->num_parents = 1; |
| 335 | 349 | girq->parents = devm_kcalloc(dev, 1, sizeof(*girq->parents), |
| @@ -80,7 +80,6 @@ struct tegra_gpio_soc { · 79 unmodified lines | ||
| 80 | 80 | |
| 81 | 81 | struct tegra_gpio { |
| 82 | 82 | struct gpio_chip gpio; |
| 83 | − struct irq_chip intc; | |
| 84 | 83 | unsigned int num_irq; |
| 85 | 84 | unsigned int *irq; |
| 86 | 85 | |
| @@ -372,6 +371,8 @@ static void tegra186_irq_mask(struct irq_data *data) · 285 unmodified lines | ||
| 372 | 371 | value = readl(base + TEGRA186_GPIO_ENABLE_CONFIG); |
| 373 | 372 | value &= ~TEGRA186_GPIO_ENABLE_CONFIG_INTERRUPT; |
| 374 | 373 | writel(value, base + TEGRA186_GPIO_ENABLE_CONFIG); |
| 374 | + | |
| 375 | + gpiochip_disable_irq(&gpio->gpio, data->hwirq); | |
| 375 | 376 | } |
| 376 | 377 | |
| 377 | 378 | static void tegra186_irq_unmask(struct irq_data *data) |
| @@ -385,6 +386,8 @@ static void tegra186_irq_unmask(struct irq_data *data) · 7 unmodified lines | ||
| 385 | 386 | if (WARN_ON(base == NULL)) |
| 386 | 387 | return; |
| 387 | 388 | |
| 389 | + gpiochip_enable_irq(&gpio->gpio, data->hwirq); | |
| 390 | + | |
| 388 | 391 | value = readl(base + TEGRA186_GPIO_ENABLE_CONFIG); |
| 389 | 392 | value |= TEGRA186_GPIO_ENABLE_CONFIG_INTERRUPT; |
| 390 | 393 | writel(value, base + TEGRA186_GPIO_ENABLE_CONFIG); |
| @@ -456,6 +459,24 @@ static int tegra186_irq_set_wake(struct irq_data *data, unsigned int on) · 65 unmodified lines | ||
| 456 | 459 | return 0; |
| 457 | 460 | } |
| 458 | 461 | |
| 462 | +static void tegra186_irq_print_chip(struct irq_data *data, struct seq_file *p) | |
| 463 | +{ | |
| 464 | + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); | |
| 465 | + | |
| 466 | + seq_printf(p, dev_name(gc->parent)); | |
| 467 | +} | |
| 468 | + | |
| 469 | +static const struct irq_chip tegra186_gpio_irq_chip = { | |
| 470 | + .irq_ack = tegra186_irq_ack, | |
| 471 | + .irq_mask = tegra186_irq_mask, | |
| 472 | + .irq_unmask = tegra186_irq_unmask, | |
| 473 | + .irq_set_type = tegra186_irq_set_type, | |
| 474 | + .irq_set_wake = tegra186_irq_set_wake, | |
| 475 | + .irq_print_chip = tegra186_irq_print_chip, | |
| 476 | + .flags = IRQCHIP_IMMUTABLE, | |
| 477 | + GPIOCHIP_IRQ_RESOURCE_HELPERS, | |
| 478 | +}; | |
| 479 | + | |
| 459 | 480 | static void tegra186_gpio_irq(struct irq_desc *desc) |
| 460 | 481 | { |
| 461 | 482 | struct tegra_gpio *gpio = irq_desc_get_handler_data(desc); |
| @@ -760,15 +781,8 @@ static int tegra186_gpio_probe(struct platform_device *pdev) · 298 unmodified lines | ||
| 760 | 781 | gpio->gpio.of_xlate = tegra186_gpio_of_xlate; |
| 761 | 782 | #endif /* CONFIG_OF_GPIO */ |
| 762 | 783 | |
| 763 | − gpio->intc.name = dev_name(&pdev->dev); | |
| 764 | − gpio->intc.irq_ack = tegra186_irq_ack; | |
| 765 | − gpio->intc.irq_mask = tegra186_irq_mask; | |
| 766 | − gpio->intc.irq_unmask = tegra186_irq_unmask; | |
| 767 | − gpio->intc.irq_set_type = tegra186_irq_set_type; | |
| 768 | − gpio->intc.irq_set_wake = tegra186_irq_set_wake; | |
| 769 | − | |
| 770 | 784 | irq = &gpio->gpio.irq; |
| 771 | − irq->chip = &gpio->intc; | |
| 785 | + gpio_irq_chip_set_chip(irq, &tegra186_gpio_irq_chip); | |
| 772 | 786 | irq->fwnode = of_node_to_fwnode(pdev->dev.of_node); |
| 773 | 787 | irq->child_to_parent_hwirq = tegra186_gpio_child_to_parent_hwirq; |
| 774 | 788 | irq->populate_parent_alloc_arg = tegra186_gpio_populate_parent_fwspec; |
| @@ -1433,19 +1433,21 @@ static int gpiochip_to_irq(struct gpio_chip *gc, unsigned int offset) · 1432 unmodified lines | ||
| 1433 | 1433 | return irq_create_mapping(domain, offset); |
| 1434 | 1434 | } |
| 1435 | 1435 | |
| 1436 | −static int gpiochip_irq_reqres(struct irq_data *d) | |
| 1436 | +int gpiochip_irq_reqres(struct irq_data *d) | |
| 1437 | 1437 | { |
| 1438 | 1438 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
| 1439 | 1439 | |
| 1440 | 1440 | return gpiochip_reqres_irq(gc, d->hwirq); |
| 1441 | 1441 | } |
| 1442 | +EXPORT_SYMBOL(gpiochip_irq_reqres); | |
| 1442 | 1443 | |
| 1443 | −static void gpiochip_irq_relres(struct irq_data *d) | |
| 1444 | +void gpiochip_irq_relres(struct irq_data *d) | |
| 1444 | 1445 | { |
| 1445 | 1446 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
| 1446 | 1447 | |
| 1447 | 1448 | gpiochip_relres_irq(gc, d->hwirq); |
| 1448 | 1449 | } |
| 1450 | +EXPORT_SYMBOL(gpiochip_irq_relres); | |
| 1449 | 1451 | |
| 1450 | 1452 | static void gpiochip_irq_mask(struct irq_data *d) |
| 1451 | 1453 | { |
| @@ -1485,6 +1487,11 @@ static void gpiochip_set_irq_hooks(struct gpio_chip *gc) · 33 unmodified lines | ||
| 1485 | 1487 | { |
| 1486 | 1488 | struct irq_chip *irqchip = gc->irq.chip; |
| 1487 | 1489 | |
| 1490 | + if (irqchip->flags & IRQCHIP_IMMUTABLE) | |
| 1491 | + return; | |
| 1492 | + | |
| 1493 | + chip_warn(gc, "not an immutable chip, please consider fixing it!\n"); | |
| 1494 | + | |
| 1488 | 1495 | if (!irqchip->irq_request_resources && |
| 1489 | 1496 | !irqchip->irq_release_resources) { |
| 1490 | 1497 | irqchip->irq_request_resources = gpiochip_irq_reqres; |
| @@ -1652,7 +1659,7 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gc) · 161 unmodified lines | ||
| 1652 | 1659 | irq_domain_remove(gc->irq.domain); |
| 1653 | 1660 | } |
| 1654 | 1661 | |
| 1655 | − if (irqchip) { | |
| 1662 | + if (irqchip && !(irqchip->flags & IRQCHIP_IMMUTABLE)) { | |
| 1656 | 1663 | if (irqchip->irq_request_resources == gpiochip_irq_reqres) { |
| 1657 | 1664 | irqchip->irq_request_resources = NULL; |
| 1658 | 1665 | irqchip->irq_release_resources = NULL; |
| @@ -387,6 +387,8 @@ static void amd_gpio_irq_enable(struct irq_data *d) · 386 unmodified lines | ||
| 387 | 387 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
| 388 | 388 | struct amd_gpio *gpio_dev = gpiochip_get_data(gc); |
| 389 | 389 | |
| 390 | + gpiochip_enable_irq(gc, d->hwirq); | |
| 391 | + | |
| 390 | 392 | raw_spin_lock_irqsave(&gpio_dev->lock, flags); |
| 391 | 393 | pin_reg = readl(gpio_dev->base + (d->hwirq)*4); |
| 392 | 394 | pin_reg |= BIT(INTERRUPT_ENABLE_OFF); |
| @@ -408,6 +410,8 @@ static void amd_gpio_irq_disable(struct irq_data *d) · 15 unmodified lines | ||
| 408 | 410 | pin_reg &= ~BIT(INTERRUPT_MASK_OFF); |
| 409 | 411 | writel(pin_reg, gpio_dev->base + (d->hwirq)*4); |
| 410 | 412 | raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); |
| 413 | + | |
| 414 | + gpiochip_disable_irq(gc, d->hwirq); | |
| 411 | 415 | } |
| 412 | 416 | |
| 413 | 417 | static void amd_gpio_irq_mask(struct irq_data *d) |
| @@ -577,7 +581,7 @@ static void amd_irq_ack(struct irq_data *d) · 163 unmodified lines | ||
| 577 | 581 | */ |
| 578 | 582 | } |
| 579 | 583 | |
| 580 | −static struct irq_chip amd_gpio_irqchip = { | |
| 584 | +static const struct irq_chip amd_gpio_irqchip = { | |
| 581 | 585 | .name = "amd_gpio", |
| 582 | 586 | .irq_ack = amd_irq_ack, |
| 583 | 587 | .irq_enable = amd_gpio_irq_enable, |
| @@ -593,7 +597,8 @@ static struct irq_chip amd_gpio_irqchip = { · 9 unmodified lines | ||
| 593 | 597 | * the wake event. Otherwise the wake event will never clear and |
| 594 | 598 | * prevent the system from suspending. |
| 595 | 599 | */ |
| 596 | − .flags = IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND, | |
| 600 | + .flags = IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND | IRQCHIP_IMMUTABLE, | |
| 601 | + GPIOCHIP_IRQ_RESOURCE_HELPERS, | |
| 597 | 602 | }; |
| 598 | 603 | |
| 599 | 604 | #define PIN_IRQ_PENDING (BIT(INTERRUPT_STS_OFF) | BIT(WAKE_STS_OFF)) |
| @@ -1026,7 +1031,7 @@ static int amd_gpio_probe(struct platform_device *pdev) · 426 unmodified lines | ||
| 1026 | 1031 | amd_gpio_irq_init(gpio_dev); |
| 1027 | 1032 | |
| 1028 | 1033 | girq = &gpio_dev->gc.irq; |
| 1029 | − girq->chip = &amd_gpio_irqchip; | |
| 1034 | + gpio_irq_chip_set_chip(girq, &amd_gpio_irqchip); | |
| 1030 | 1035 | /* This will let us handle the parent IRQ in the driver */ |
| 1031 | 1036 | girq->parent_handler = NULL; |
| 1032 | 1037 | girq->num_parents = 0; |
| @@ -36,7 +36,6 @@ struct apple_gpio_pinctrl { · 35 unmodified lines | ||
| 36 | 36 | |
| 37 | 37 | struct pinctrl_desc pinctrl_desc; |
| 38 | 38 | struct gpio_chip gpio_chip; |
| 39 | − struct irq_chip irq_chip; | |
| 40 | 39 | u8 irqgrps[]; |
| 41 | 40 | }; |
| 42 | 41 | |
| @@ -275,17 +274,21 @@ static unsigned int apple_gpio_irq_type(unsigned int type) · 232 unmodified lines | ||
| 275 | 274 | |
| 276 | 275 | static void apple_gpio_irq_mask(struct irq_data *data) |
| 277 | 276 | { |
| 278 | − struct apple_gpio_pinctrl *pctl = gpiochip_get_data(irq_data_get_irq_chip_data(data)); | |
| 277 | + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); | |
| 278 | + struct apple_gpio_pinctrl *pctl = gpiochip_get_data(gc); | |
| 279 | 279 | |
| 280 | 280 | apple_gpio_set_reg(pctl, data->hwirq, REG_GPIOx_MODE, |
| 281 | 281 | FIELD_PREP(REG_GPIOx_MODE, REG_GPIOx_IN_IRQ_OFF)); |
| 282 | + gpiochip_disable_irq(gc, data->hwirq); | |
| 282 | 283 | } |
| 283 | 284 | |
| 284 | 285 | static void apple_gpio_irq_unmask(struct irq_data *data) |
| 285 | 286 | { |
| 286 | − struct apple_gpio_pinctrl *pctl = gpiochip_get_data(irq_data_get_irq_chip_data(data)); | |
| 287 | + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); | |
| 288 | + struct apple_gpio_pinctrl *pctl = gpiochip_get_data(gc); | |
| 287 | 289 | unsigned int irqtype = apple_gpio_irq_type(irqd_get_trigger_type(data)); |
| 288 | 290 | |
| 291 | + gpiochip_enable_irq(gc, data->hwirq); | |
| 289 | 292 | apple_gpio_set_reg(pctl, data->hwirq, REG_GPIOx_MODE, |
| 290 | 293 | FIELD_PREP(REG_GPIOx_MODE, irqtype)); |
| 291 | 294 | } |
| @@ -343,13 +346,15 @@ static void apple_gpio_irq_handler(struct irq_desc *desc) · 51 unmodified lines | ||
| 343 | 346 | chained_irq_exit(chip, desc); |
| 344 | 347 | } |
| 345 | 348 | |
| 346 | −static struct irq_chip apple_gpio_irqchip = { | |
| 347 | − .name = "Apple-GPIO", | |
| 348 | − .irq_startup = apple_gpio_irq_startup, | |
| 349 | − .irq_ack = apple_gpio_irq_ack, | |
| 350 | − .irq_mask = apple_gpio_irq_mask, | |
| 351 | − .irq_unmask = apple_gpio_irq_unmask, | |
| 352 | − .irq_set_type = apple_gpio_irq_set_type, | |
| 349 | +static const struct irq_chip apple_gpio_irqchip = { | |
| 350 | + .name = "Apple-GPIO", | |
| 351 | + .irq_startup = apple_gpio_irq_startup, | |
| 352 | + .irq_ack = apple_gpio_irq_ack, | |
| 353 | + .irq_mask = apple_gpio_irq_mask, | |
| 354 | + .irq_unmask = apple_gpio_irq_unmask, | |
| 355 | + .irq_set_type = apple_gpio_irq_set_type, | |
| 356 | + .flags = IRQCHIP_IMMUTABLE, | |
| 357 | + GPIOCHIP_IRQ_RESOURCE_HELPERS, | |
| 353 | 358 | }; |
| 354 | 359 | |
| 355 | 360 | /* Probe & register */ |
| @@ -360,8 +365,6 @@ static int apple_gpio_register(struct apple_gpio_pinctrl *pctl) · 4 unmodified lines | ||
| 360 | 365 | void **irq_data = NULL; |
| 361 | 366 | int ret; |
| 362 | 367 | |
| 363 | − pctl->irq_chip = apple_gpio_irqchip; | |
| 364 | − | |
| 365 | 368 | pctl->gpio_chip.label = dev_name(pctl->dev); |
| 366 | 369 | pctl->gpio_chip.request = gpiochip_generic_request; |
| 367 | 370 | pctl->gpio_chip.free = gpiochip_generic_free; |
| @@ -377,7 +380,7 @@ static int apple_gpio_register(struct apple_gpio_pinctrl *pctl) · 9 unmodified lines | ||
| 377 | 380 | if (girq->num_parents) { |
| 378 | 381 | int i; |
| 379 | 382 | |
| 380 | − girq->chip = &pctl->irq_chip; | |
| 383 | + gpio_irq_chip_set_chip(girq, &apple_gpio_irqchip); | |
| 381 | 384 | girq->parent_handler = apple_gpio_irq_handler; |
| 382 | 385 | |
| 383 | 386 | girq->parents = kmalloc_array(girq->num_parents, |
| @@ -42,7 +42,6 @@ · 41 unmodified lines | ||
| 42 | 42 | * @chip: gpiochip handle. |
| 43 | 43 | * @desc: pin controller descriptor |
| 44 | 44 | * @restart_nb: restart notifier block. |
| 45 | − * @irq_chip: irq chip information | |
| 46 | 45 | * @irq: parent irq for the TLMM irq_chip. |
| 47 | 46 | * @intr_target_use_scm: route irq to application cpu using scm calls |
| 48 | 47 | * @lock: Spinlock to protect register resources as well |
| @@ -63,7 +62,6 @@ struct msm_pinctrl { · 14 unmodified lines | ||
| 63 | 62 | struct pinctrl_desc desc; |
| 64 | 63 | struct notifier_block restart_nb; |
| 65 | 64 | |
| 66 | − struct irq_chip irq_chip; | |
| 67 | 65 | int irq; |
| 68 | 66 | |
| 69 | 67 | bool intr_target_use_scm; |
| @@ -868,6 +866,8 @@ static void msm_gpio_irq_enable(struct irq_data *d) · 798 unmodified lines | ||
| 868 | 866 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
| 869 | 867 | struct msm_pinctrl *pctrl = gpiochip_get_data(gc); |
| 870 | 868 | |
| 869 | + gpiochip_enable_irq(gc, d->hwirq); | |
| 870 | + | |
| 871 | 871 | if (d->parent_data) |
| 872 | 872 | irq_chip_enable_parent(d); |
| 873 | 873 | |
| @@ -885,6 +885,8 @@ static void msm_gpio_irq_disable(struct irq_data *d) · 11 unmodified lines | ||
| 885 | 885 | |
| 886 | 886 | if (!test_bit(d->hwirq, pctrl->skip_wake_irqs)) |
| 887 | 887 | msm_gpio_irq_mask(d); |
| 888 | + | |
| 889 | + gpiochip_disable_irq(gc, d->hwirq); | |
| 888 | 890 | } |
| 889 | 891 | |
| 890 | 892 | /** |
| @@ -958,6 +960,14 @@ static void msm_gpio_irq_ack(struct irq_data *d) · 67 unmodified lines | ||
| 958 | 960 | raw_spin_unlock_irqrestore(&pctrl->lock, flags); |
| 959 | 961 | } |
| 960 | 962 | |
| 963 | +static void msm_gpio_irq_eoi(struct irq_data *d) | |
| 964 | +{ | |
| 965 | + d = d->parent_data; | |
| 966 | + | |
| 967 | + if (d) | |
| 968 | + d->chip->irq_eoi(d); | |
| 969 | +} | |
| 970 | + | |
| 961 | 971 | static bool msm_gpio_needs_dual_edge_parent_workaround(struct irq_data *d, |
| 962 | 972 | unsigned int type) |
| 963 | 973 | { |
| @@ -1255,6 +1265,26 @@ static bool msm_gpio_needs_valid_mask(struct msm_pinctrl *pctrl) · 291 unmodified lines | ||
| 1255 | 1265 | return device_property_count_u16(pctrl->dev, "gpios") > 0; |
| 1256 | 1266 | } |
| 1257 | 1267 | |
| 1268 | +static const struct irq_chip msm_gpio_irq_chip = { | |
| 1269 | + .name = "msmgpio", | |
| 1270 | + .irq_enable = msm_gpio_irq_enable, | |
| 1271 | + .irq_disable = msm_gpio_irq_disable, | |
| 1272 | + .irq_mask = msm_gpio_irq_mask, | |
| 1273 | + .irq_unmask = msm_gpio_irq_unmask, | |
| 1274 | + .irq_ack = msm_gpio_irq_ack, | |
| 1275 | + .irq_eoi = msm_gpio_irq_eoi, | |
| 1276 | + .irq_set_type = msm_gpio_irq_set_type, | |
| 1277 | + .irq_set_wake = msm_gpio_irq_set_wake, | |
| 1278 | + .irq_request_resources = msm_gpio_irq_reqres, | |
| 1279 | + .irq_release_resources = msm_gpio_irq_relres, | |
| 1280 | + .irq_set_affinity = msm_gpio_irq_set_affinity, | |
| 1281 | + .irq_set_vcpu_affinity = msm_gpio_irq_set_vcpu_affinity, | |
| 1282 | + .flags = (IRQCHIP_MASK_ON_SUSPEND | | |
| 1283 | + IRQCHIP_SET_TYPE_MASKED | | |
| 1284 | + IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND | | |
| 1285 | + IRQCHIP_IMMUTABLE), | |
| 1286 | +}; | |
| 1287 | + | |
| 1258 | 1288 | static int msm_gpio_init(struct msm_pinctrl *pctrl) |
| 1259 | 1289 | { |
| 1260 | 1290 | struct gpio_chip *chip; |
| @@ -1276,22 +1306,6 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl) · 15 unmodified lines | ||
| 1276 | 1306 | if (msm_gpio_needs_valid_mask(pctrl)) |
| 1277 | 1307 | chip->init_valid_mask = msm_gpio_init_valid_mask; |
| 1278 | 1308 | |
| 1279 | − pctrl->irq_chip.name = "msmgpio"; | |
| 1280 | − pctrl->irq_chip.irq_enable = msm_gpio_irq_enable; | |
| 1281 | − pctrl->irq_chip.irq_disable = msm_gpio_irq_disable; | |
| 1282 | − pctrl->irq_chip.irq_mask = msm_gpio_irq_mask; | |
| 1283 | − pctrl->irq_chip.irq_unmask = msm_gpio_irq_unmask; | |
| 1284 | − pctrl->irq_chip.irq_ack = msm_gpio_irq_ack; | |
| 1285 | − pctrl->irq_chip.irq_set_type = msm_gpio_irq_set_type; | |
| 1286 | − pctrl->irq_chip.irq_set_wake = msm_gpio_irq_set_wake; | |
| 1287 | − pctrl->irq_chip.irq_request_resources = msm_gpio_irq_reqres; | |
| 1288 | − pctrl->irq_chip.irq_release_resources = msm_gpio_irq_relres; | |
| 1289 | − pctrl->irq_chip.irq_set_affinity = msm_gpio_irq_set_affinity; | |
| 1290 | − pctrl->irq_chip.irq_set_vcpu_affinity = msm_gpio_irq_set_vcpu_affinity; | |
| 1291 | − pctrl->irq_chip.flags = IRQCHIP_MASK_ON_SUSPEND | | |
| 1292 | − IRQCHIP_SET_TYPE_MASKED | | |
| 1293 | − IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND; | |
| 1294 | − | |
| 1295 | 1309 | np = of_parse_phandle(pctrl->dev->of_node, "wakeup-parent", 0); |
| 1296 | 1310 | if (np) { |
| 1297 | 1311 | chip->irq.parent_domain = irq_find_matching_host(np, |
| @@ -1300,7 +1314,6 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl) · 2 unmodified lines | ||
| 1300 | 1314 | if (!chip->irq.parent_domain) |
| 1301 | 1315 | return -EPROBE_DEFER; |
| 1302 | 1316 | chip->irq.child_to_parent_hwirq = msm_gpio_wakeirq; |
| 1303 | − pctrl->irq_chip.irq_eoi = irq_chip_eoi_parent; | |
| 1304 | 1317 | /* |
| 1305 | 1318 | * Let's skip handling the GPIOs, if the parent irqchip |
| 1306 | 1319 | * is handling the direct connect IRQ of the GPIO. |
| @@ -1313,7 +1326,7 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl) · 6 unmodified lines | ||
| 1313 | 1326 | } |
| 1314 | 1327 | |
| 1315 | 1328 | girq = &chip->irq; |
| 1316 | − girq->chip = &pctrl->irq_chip; | |
| 1329 | + gpio_irq_chip_set_chip(girq, &msm_gpio_irq_chip); | |
| 1317 | 1330 | girq->parent_handler = msm_gpio_irq_handler; |
| 1318 | 1331 | girq->fwnode = pctrl->dev->fwnode; |
| 1319 | 1332 | girq->num_parents = 1; |
| @@ -588,6 +588,22 @@ void gpiochip_relres_irq(struct gpio_chip *gc, unsigned int offset); · 587 unmodified lines | ||
| 588 | 588 | void gpiochip_disable_irq(struct gpio_chip *gc, unsigned int offset); |
| 589 | 589 | void gpiochip_enable_irq(struct gpio_chip *gc, unsigned int offset); |
| 590 | 590 | |
| 591 | +/* irq_data versions of the above */ | |
| 592 | +int gpiochip_irq_reqres(struct irq_data *data); | |
| 593 | +void gpiochip_irq_relres(struct irq_data *data); | |
| 594 | + | |
| 595 | +/* Paste this in your irq_chip structure */ | |
| 596 | +#define GPIOCHIP_IRQ_RESOURCE_HELPERS \ | |
| 597 | + .irq_request_resources = gpiochip_irq_reqres, \ | |
| 598 | + .irq_release_resources = gpiochip_irq_relres | |
| 599 | + | |
| 600 | +static inline void gpio_irq_chip_set_chip(struct gpio_irq_chip *girq, | |
| 601 | + const struct irq_chip *chip) | |
| 602 | +{ | |
| 603 | + /* Yes, dropping const is ugly, but it isn't like we have a choice */ | |
| 604 | + girq->chip = (struct irq_chip *)chip; | |
| 605 | +} | |
| 606 | + | |
| 591 | 607 | /* Line status inquiry for drivers */ |
| 592 | 608 | bool gpiochip_line_is_open_drain(struct gpio_chip *gc, unsigned int offset); |
| 593 | 609 | bool gpiochip_line_is_open_source(struct gpio_chip *gc, unsigned int offset); |
| @@ -569,6 +569,7 @@ struct irq_chip { · 568 unmodified lines | ||
| 569 | 569 | * IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND: Invokes __enable_irq()/__disable_irq() for wake irqs |
| 570 | 570 | * in the suspend path if they are in disabled state |
| 571 | 571 | * IRQCHIP_AFFINITY_PRE_STARTUP: Default affinity update before startup |
| 572 | + * IRQCHIP_IMMUTABLE: Don't ever change anything in this chip | |
| 572 | 573 | */ |
| 573 | 574 | enum { |
| 574 | 575 | IRQCHIP_SET_TYPE_MASKED = (1 << 0), |
| @@ -582,6 +583,7 @@ enum { · 7 unmodified lines | ||
| 582 | 583 | IRQCHIP_SUPPORTS_NMI = (1 << 8), |
| 583 | 584 | IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND = (1 << 9), |
| 584 | 585 | IRQCHIP_AFFINITY_PRE_STARTUP = (1 << 10), |
| 586 | + IRQCHIP_IMMUTABLE = (1 << 11), | |
| 585 | 587 | }; |
| 586 | 588 | |
| 587 | 589 | #include <linux/irqdesc.h> |
| @@ -58,6 +58,7 @@ static const struct irq_bit_descr irqchip_flags[] = { · 57 unmodified lines | ||
| 58 | 58 | BIT_MASK_DESCR(IRQCHIP_SUPPORTS_LEVEL_MSI), |
| 59 | 59 | BIT_MASK_DESCR(IRQCHIP_SUPPORTS_NMI), |
| 60 | 60 | BIT_MASK_DESCR(IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND), |
| 61 | + BIT_MASK_DESCR(IRQCHIP_IMMUTABLE), | |
| 61 | 62 | }; |
| 62 | 63 | |
| 63 | 64 | static void |