Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

gpio: thunderx: Switch to GPIOLIB_IRQCHIP

The main parts of this patch are from commit a7fc89f9d5fc ("gpio:
thunderx: Switch to GPIOLIB_IRQCHIP") and patch [1]. And also adjust
thunderx_gpio_child_to_parent_hwirq() and add
thunderx_gpio_populate_parent_alloc_info() to make sure that
the correct hwirq are passed to the parent msi irqdomain.

[1] https://patchwork.ozlabs.org/patch/1210180/

Signed-off-by: Kevin Hao <haokexin@gmail.com>
Link: https://lore.kernel.org/r/20200114082821.14015-5-haokexin@gmail.com
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

authored by

Kevin Hao and committed by
Linus Walleij
7a9f4460 880b7cf2

+78 -100
+1
drivers/gpio/Kconfig
··· 573 573 tristate "Cavium ThunderX/OCTEON-TX GPIO" 574 574 depends on ARCH_THUNDER || (64BIT && COMPILE_TEST) 575 575 depends on PCI_MSI 576 + select GPIOLIB_IRQCHIP 576 577 select IRQ_DOMAIN_HIERARCHY 577 578 select IRQ_FASTEOI_HIERARCHY_HANDLERS 578 579 help
+77 -100
drivers/gpio/gpio-thunderx.c
··· 15 15 #include <linux/module.h> 16 16 #include <linux/pci.h> 17 17 #include <linux/spinlock.h> 18 + #include <asm-generic/msi.h> 18 19 19 20 20 21 #define GPIO_RX_DAT 0x0 ··· 54 53 struct thunderx_gpio { 55 54 struct gpio_chip chip; 56 55 u8 __iomem *register_base; 57 - struct irq_domain *irqd; 58 56 struct msix_entry *msix_entries; /* per line MSI-X */ 59 57 struct thunderx_line *line_entries; /* per line irq info */ 60 58 raw_spinlock_t lock; ··· 286 286 } 287 287 } 288 288 289 - static void thunderx_gpio_irq_ack(struct irq_data *data) 289 + static void thunderx_gpio_irq_ack(struct irq_data *d) 290 290 { 291 - struct thunderx_line *txline = irq_data_get_irq_chip_data(data); 291 + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 292 + struct thunderx_gpio *txgpio = gpiochip_get_data(gc); 292 293 293 294 writeq(GPIO_INTR_INTR, 294 - txline->txgpio->register_base + intr_reg(txline->line)); 295 + txgpio->register_base + intr_reg(irqd_to_hwirq(d))); 295 296 } 296 297 297 - static void thunderx_gpio_irq_mask(struct irq_data *data) 298 + static void thunderx_gpio_irq_mask(struct irq_data *d) 298 299 { 299 - struct thunderx_line *txline = irq_data_get_irq_chip_data(data); 300 + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 301 + struct thunderx_gpio *txgpio = gpiochip_get_data(gc); 300 302 301 303 writeq(GPIO_INTR_ENA_W1C, 302 - txline->txgpio->register_base + intr_reg(txline->line)); 304 + txgpio->register_base + intr_reg(irqd_to_hwirq(d))); 303 305 } 304 306 305 - static void thunderx_gpio_irq_mask_ack(struct irq_data *data) 307 + static void thunderx_gpio_irq_mask_ack(struct irq_data *d) 306 308 { 307 - struct thunderx_line *txline = irq_data_get_irq_chip_data(data); 309 + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 310 + struct thunderx_gpio *txgpio = gpiochip_get_data(gc); 308 311 309 312 writeq(GPIO_INTR_ENA_W1C | GPIO_INTR_INTR, 310 - txline->txgpio->register_base + intr_reg(txline->line)); 313 + txgpio->register_base + intr_reg(irqd_to_hwirq(d))); 311 314 } 312 315 313 - static void thunderx_gpio_irq_unmask(struct irq_data *data) 316 + static void thunderx_gpio_irq_unmask(struct irq_data *d) 314 317 { 315 - struct thunderx_line *txline = irq_data_get_irq_chip_data(data); 318 + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 319 + struct thunderx_gpio *txgpio = gpiochip_get_data(gc); 316 320 317 321 writeq(GPIO_INTR_ENA_W1S, 318 - txline->txgpio->register_base + intr_reg(txline->line)); 322 + txgpio->register_base + intr_reg(irqd_to_hwirq(d))); 319 323 } 320 324 321 - static int thunderx_gpio_irq_set_type(struct irq_data *data, 325 + static int thunderx_gpio_irq_set_type(struct irq_data *d, 322 326 unsigned int flow_type) 323 327 { 324 - struct thunderx_line *txline = irq_data_get_irq_chip_data(data); 325 - struct thunderx_gpio *txgpio = txline->txgpio; 328 + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 329 + struct thunderx_gpio *txgpio = gpiochip_get_data(gc); 330 + struct thunderx_line *txline = 331 + &txgpio->line_entries[irqd_to_hwirq(d)]; 326 332 u64 bit_cfg; 327 333 328 - irqd_set_trigger_type(data, flow_type); 334 + irqd_set_trigger_type(d, flow_type); 329 335 330 336 bit_cfg = txline->fil_bits | GPIO_BIT_CFG_INT_EN; 331 337 332 338 if (flow_type & IRQ_TYPE_EDGE_BOTH) { 333 - irq_set_handler_locked(data, handle_fasteoi_ack_irq); 339 + irq_set_handler_locked(d, handle_fasteoi_ack_irq); 334 340 bit_cfg |= GPIO_BIT_CFG_INT_TYPE; 335 341 } else { 336 - irq_set_handler_locked(data, handle_fasteoi_mask_irq); 342 + irq_set_handler_locked(d, handle_fasteoi_mask_irq); 337 343 } 338 344 339 345 raw_spin_lock(&txgpio->lock); ··· 368 362 irq_chip_disable_parent(data); 369 363 } 370 364 371 - static int thunderx_gpio_irq_request_resources(struct irq_data *data) 372 - { 373 - struct thunderx_line *txline = irq_data_get_irq_chip_data(data); 374 - struct thunderx_gpio *txgpio = txline->txgpio; 375 - int r; 376 - 377 - r = gpiochip_lock_as_irq(&txgpio->chip, txline->line); 378 - if (r) 379 - return r; 380 - 381 - r = irq_chip_request_resources_parent(data); 382 - if (r) 383 - gpiochip_unlock_as_irq(&txgpio->chip, txline->line); 384 - 385 - return r; 386 - } 387 - 388 - static void thunderx_gpio_irq_release_resources(struct irq_data *data) 389 - { 390 - struct thunderx_line *txline = irq_data_get_irq_chip_data(data); 391 - struct thunderx_gpio *txgpio = txline->txgpio; 392 - 393 - irq_chip_release_resources_parent(data); 394 - 395 - gpiochip_unlock_as_irq(&txgpio->chip, txline->line); 396 - } 397 - 398 365 /* 399 366 * Interrupts are chained from underlying MSI-X vectors. We have 400 367 * these irq_chip functions to be able to handle level triggering ··· 384 405 .irq_unmask = thunderx_gpio_irq_unmask, 385 406 .irq_eoi = irq_chip_eoi_parent, 386 407 .irq_set_affinity = irq_chip_set_affinity_parent, 387 - .irq_request_resources = thunderx_gpio_irq_request_resources, 388 - .irq_release_resources = thunderx_gpio_irq_release_resources, 389 408 .irq_set_type = thunderx_gpio_irq_set_type, 390 409 391 410 .flags = IRQCHIP_SET_TYPE_MASKED 392 411 }; 393 412 394 - static int thunderx_gpio_irq_translate(struct irq_domain *d, 395 - struct irq_fwspec *fwspec, 396 - irq_hw_number_t *hwirq, 397 - unsigned int *type) 413 + static int thunderx_gpio_child_to_parent_hwirq(struct gpio_chip *gc, 414 + unsigned int child, 415 + unsigned int child_type, 416 + unsigned int *parent, 417 + unsigned int *parent_type) 398 418 { 399 - struct thunderx_gpio *txgpio = d->host_data; 419 + struct thunderx_gpio *txgpio = gpiochip_get_data(gc); 420 + struct irq_data *irqd; 421 + unsigned int irq; 400 422 401 - if (WARN_ON(fwspec->param_count < 2)) 423 + irq = txgpio->msix_entries[child].vector; 424 + irqd = irq_domain_get_irq_data(gc->irq.parent_domain, irq); 425 + if (!irqd) 402 426 return -EINVAL; 403 - if (fwspec->param[0] >= txgpio->chip.ngpio) 404 - return -EINVAL; 405 - *hwirq = fwspec->param[0]; 406 - *type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK; 427 + *parent = irqd_to_hwirq(irqd); 428 + *parent_type = IRQ_TYPE_LEVEL_HIGH; 407 429 return 0; 408 430 } 409 431 410 - static int thunderx_gpio_irq_alloc(struct irq_domain *d, unsigned int virq, 411 - unsigned int nr_irqs, void *arg) 432 + static void *thunderx_gpio_populate_parent_alloc_info(struct gpio_chip *chip, 433 + unsigned int parent_hwirq, 434 + unsigned int parent_type) 412 435 { 413 - struct thunderx_line *txline = arg; 436 + msi_alloc_info_t *info; 414 437 415 - return irq_domain_set_hwirq_and_chip(d, virq, txline->line, 416 - &thunderx_gpio_irq_chip, txline); 417 - } 438 + info = kmalloc(sizeof(*info), GFP_KERNEL); 439 + if (!info) 440 + return NULL; 418 441 419 - static const struct irq_domain_ops thunderx_gpio_irqd_ops = { 420 - .alloc = thunderx_gpio_irq_alloc, 421 - .translate = thunderx_gpio_irq_translate 422 - }; 423 - 424 - static int thunderx_gpio_to_irq(struct gpio_chip *chip, unsigned int offset) 425 - { 426 - struct thunderx_gpio *txgpio = gpiochip_get_data(chip); 427 - 428 - return irq_find_mapping(txgpio->irqd, offset); 442 + info->hwirq = parent_hwirq; 443 + return info; 429 444 } 430 445 431 446 static int thunderx_gpio_probe(struct pci_dev *pdev, ··· 429 456 struct device *dev = &pdev->dev; 430 457 struct thunderx_gpio *txgpio; 431 458 struct gpio_chip *chip; 459 + struct gpio_irq_chip *girq; 432 460 int ngpio, i; 433 461 int err = 0; 434 462 ··· 474 500 } 475 501 476 502 txgpio->msix_entries = devm_kcalloc(dev, 477 - ngpio, sizeof(struct msix_entry), 478 - GFP_KERNEL); 503 + ngpio, sizeof(struct msix_entry), 504 + GFP_KERNEL); 479 505 if (!txgpio->msix_entries) { 480 506 err = -ENOMEM; 481 507 goto out; ··· 516 542 if (err < 0) 517 543 goto out; 518 544 519 - /* 520 - * Push GPIO specific irqdomain on hierarchy created as a side 521 - * effect of the pci_enable_msix() 522 - */ 523 - txgpio->irqd = irq_domain_create_hierarchy(irq_get_irq_data(txgpio->msix_entries[0].vector)->domain, 524 - 0, 0, of_node_to_fwnode(dev->of_node), 525 - &thunderx_gpio_irqd_ops, txgpio); 526 - if (!txgpio->irqd) { 527 - err = -ENOMEM; 528 - goto out; 529 - } 530 - 531 - /* Push on irq_data and the domain for each line. */ 532 - for (i = 0; i < ngpio; i++) { 533 - err = irq_domain_push_irq(txgpio->irqd, 534 - txgpio->msix_entries[i].vector, 535 - &txgpio->line_entries[i]); 536 - if (err < 0) 537 - dev_err(dev, "irq_domain_push_irq: %d\n", err); 538 - } 539 - 540 545 chip->label = KBUILD_MODNAME; 541 546 chip->parent = dev; 542 547 chip->owner = THIS_MODULE; ··· 530 577 chip->set = thunderx_gpio_set; 531 578 chip->set_multiple = thunderx_gpio_set_multiple; 532 579 chip->set_config = thunderx_gpio_set_config; 533 - chip->to_irq = thunderx_gpio_to_irq; 580 + girq = &chip->irq; 581 + girq->chip = &thunderx_gpio_irq_chip; 582 + girq->fwnode = of_node_to_fwnode(dev->of_node); 583 + girq->parent_domain = 584 + irq_get_irq_data(txgpio->msix_entries[0].vector)->domain; 585 + girq->child_to_parent_hwirq = thunderx_gpio_child_to_parent_hwirq; 586 + girq->populate_parent_alloc_arg = thunderx_gpio_populate_parent_alloc_info; 587 + girq->handler = handle_bad_irq; 588 + girq->default_type = IRQ_TYPE_NONE; 589 + 534 590 err = devm_gpiochip_add_data(dev, chip, txgpio); 535 591 if (err) 536 592 goto out; 593 + 594 + /* Push on irq_data and the domain for each line. */ 595 + for (i = 0; i < ngpio; i++) { 596 + struct irq_fwspec fwspec; 597 + 598 + fwspec.fwnode = of_node_to_fwnode(dev->of_node); 599 + fwspec.param_count = 2; 600 + fwspec.param[0] = i; 601 + fwspec.param[1] = IRQ_TYPE_NONE; 602 + err = irq_domain_push_irq(girq->domain, 603 + txgpio->msix_entries[i].vector, 604 + &fwspec); 605 + if (err < 0) 606 + dev_err(dev, "irq_domain_push_irq: %d\n", err); 607 + } 537 608 538 609 dev_info(dev, "ThunderX GPIO: %d lines with base %d.\n", 539 610 ngpio, chip->base); ··· 573 596 struct thunderx_gpio *txgpio = pci_get_drvdata(pdev); 574 597 575 598 for (i = 0; i < txgpio->chip.ngpio; i++) 576 - irq_domain_pop_irq(txgpio->irqd, 599 + irq_domain_pop_irq(txgpio->chip.irq.domain, 577 600 txgpio->msix_entries[i].vector); 578 601 579 - irq_domain_remove(txgpio->irqd); 602 + irq_domain_remove(txgpio->chip.irq.domain); 580 603 581 604 pci_set_drvdata(pdev, NULL); 582 605 }