| .. | .. |
|---|
| 41 | 41 | |
|---|
| 42 | 42 | #define FLAGS_WORKAROUND_GICR_WAKER_MSM8996 (1ULL << 0) |
|---|
| 43 | 43 | #define FLAGS_WORKAROUND_CAVIUM_ERRATUM_38539 (1ULL << 1) |
|---|
| 44 | +#define FLAGS_WORKAROUND_MTK_GICR_SAVE (1ULL << 2) |
|---|
| 44 | 45 | |
|---|
| 45 | 46 | #define GIC_IRQ_TYPE_PARTITION (GIC_IRQ_TYPE_LPI + 1) |
|---|
| 46 | 47 | |
|---|
| .. | .. |
|---|
| 49 | 50 | phys_addr_t phys_base; |
|---|
| 50 | 51 | bool single_redist; |
|---|
| 51 | 52 | }; |
|---|
| 53 | + |
|---|
| 54 | +static DEFINE_STATIC_KEY_FALSE(gic_arm64_2941627_erratum); |
|---|
| 52 | 55 | |
|---|
| 53 | 56 | static struct gic_chip_data gic_data __read_mostly; |
|---|
| 54 | 57 | static DEFINE_STATIC_KEY_TRUE(supports_deactivate_key); |
|---|
| .. | .. |
|---|
| 541 | 544 | gic_irq_set_prio(d, GICD_INT_DEF_PRI); |
|---|
| 542 | 545 | } |
|---|
| 543 | 546 | |
|---|
| 547 | +static bool gic_arm64_erratum_2941627_needed(struct irq_data *d) |
|---|
| 548 | +{ |
|---|
| 549 | + enum gic_intid_range range; |
|---|
| 550 | + |
|---|
| 551 | + if (!static_branch_unlikely(&gic_arm64_2941627_erratum)) |
|---|
| 552 | + return false; |
|---|
| 553 | + |
|---|
| 554 | + range = get_intid_range(d); |
|---|
| 555 | + |
|---|
| 556 | + /* |
|---|
| 557 | + * The workaround is needed if the IRQ is an SPI and |
|---|
| 558 | + * the target cpu is different from the one we are |
|---|
| 559 | + * executing on. |
|---|
| 560 | + */ |
|---|
| 561 | + return (range == SPI_RANGE || range == ESPI_RANGE) && |
|---|
| 562 | + !cpumask_test_cpu(raw_smp_processor_id(), |
|---|
| 563 | + irq_data_get_effective_affinity_mask(d)); |
|---|
| 564 | +} |
|---|
| 565 | + |
|---|
| 544 | 566 | static void gic_eoi_irq(struct irq_data *d) |
|---|
| 545 | 567 | { |
|---|
| 546 | | - gic_write_eoir(gic_irq(d)); |
|---|
| 568 | + write_gicreg(gic_irq(d), ICC_EOIR1_EL1); |
|---|
| 569 | + isb(); |
|---|
| 570 | + |
|---|
| 571 | + if (gic_arm64_erratum_2941627_needed(d)) { |
|---|
| 572 | + /* |
|---|
| 573 | + * Make sure the GIC stream deactivate packet |
|---|
| 574 | + * issued by ICC_EOIR1_EL1 has completed before |
|---|
| 575 | + * deactivating through GICD_IACTIVER. |
|---|
| 576 | + */ |
|---|
| 577 | + dsb(sy); |
|---|
| 578 | + gic_poke_irq(d, GICD_ICACTIVER); |
|---|
| 579 | + } |
|---|
| 547 | 580 | } |
|---|
| 548 | 581 | |
|---|
| 549 | 582 | static void gic_eoimode1_eoi_irq(struct irq_data *d) |
|---|
| .. | .. |
|---|
| 554 | 587 | */ |
|---|
| 555 | 588 | if (gic_irq(d) >= 8192 || irqd_is_forwarded_to_vcpu(d)) |
|---|
| 556 | 589 | return; |
|---|
| 557 | | - gic_write_dir(gic_irq(d)); |
|---|
| 590 | + |
|---|
| 591 | + if (!gic_arm64_erratum_2941627_needed(d)) |
|---|
| 592 | + gic_write_dir(gic_irq(d)); |
|---|
| 593 | + else |
|---|
| 594 | + gic_poke_irq(d, GICD_ICACTIVER); |
|---|
| 558 | 595 | } |
|---|
| 559 | 596 | |
|---|
| 560 | 597 | static int gic_set_type(struct irq_data *d, unsigned int type) |
|---|
| .. | .. |
|---|
| 1472 | 1509 | |
|---|
| 1473 | 1510 | /* |
|---|
| 1474 | 1511 | * Make it clear that broken DTs are... broken. |
|---|
| 1475 | | - * Partitionned PPIs are an unfortunate exception. |
|---|
| 1512 | + * Partitioned PPIs are an unfortunate exception. |
|---|
| 1476 | 1513 | */ |
|---|
| 1477 | 1514 | WARN_ON(*type == IRQ_TYPE_NONE && |
|---|
| 1478 | 1515 | fwspec->param[0] != GIC_IRQ_TYPE_PARTITION); |
|---|
| .. | .. |
|---|
| 1603 | 1640 | return true; |
|---|
| 1604 | 1641 | } |
|---|
| 1605 | 1642 | |
|---|
| 1643 | +static bool gic_enable_quirk_mtk_gicr(void *data) |
|---|
| 1644 | +{ |
|---|
| 1645 | + struct gic_chip_data *d = data; |
|---|
| 1646 | + |
|---|
| 1647 | + d->flags |= FLAGS_WORKAROUND_MTK_GICR_SAVE; |
|---|
| 1648 | + |
|---|
| 1649 | + return true; |
|---|
| 1650 | +} |
|---|
| 1651 | + |
|---|
| 1606 | 1652 | static bool gic_enable_quirk_cavium_38539(void *data) |
|---|
| 1607 | 1653 | { |
|---|
| 1608 | 1654 | struct gic_chip_data *d = data; |
|---|
| .. | .. |
|---|
| 1632 | 1678 | return false; |
|---|
| 1633 | 1679 | } |
|---|
| 1634 | 1680 | |
|---|
| 1681 | +static bool gic_enable_quirk_arm64_2941627(void *data) |
|---|
| 1682 | +{ |
|---|
| 1683 | + static_branch_enable(&gic_arm64_2941627_erratum); |
|---|
| 1684 | + return true; |
|---|
| 1685 | +} |
|---|
| 1686 | + |
|---|
| 1635 | 1687 | static const struct gic_quirk gic_quirks[] = { |
|---|
| 1636 | 1688 | { |
|---|
| 1637 | 1689 | .desc = "GICv3: Qualcomm MSM8996 broken firmware", |
|---|
| 1638 | 1690 | .compatible = "qcom,msm8996-gic-v3", |
|---|
| 1639 | 1691 | .init = gic_enable_quirk_msm8996, |
|---|
| 1692 | + }, |
|---|
| 1693 | + { |
|---|
| 1694 | + .desc = "GICv3: Mediatek Chromebook GICR save problem", |
|---|
| 1695 | + .property = "mediatek,broken-save-restore-fw", |
|---|
| 1696 | + .init = gic_enable_quirk_mtk_gicr, |
|---|
| 1640 | 1697 | }, |
|---|
| 1641 | 1698 | { |
|---|
| 1642 | 1699 | .desc = "GICv3: HIP06 erratum 161010803", |
|---|
| .. | .. |
|---|
| 1664 | 1721 | .init = gic_enable_quirk_cavium_38539, |
|---|
| 1665 | 1722 | }, |
|---|
| 1666 | 1723 | { |
|---|
| 1724 | + /* |
|---|
| 1725 | + * GIC-700: 2941627 workaround - IP variant [0,1] |
|---|
| 1726 | + * |
|---|
| 1727 | + */ |
|---|
| 1728 | + .desc = "GICv3: ARM64 erratum 2941627", |
|---|
| 1729 | + .iidr = 0x0400043b, |
|---|
| 1730 | + .mask = 0xff0e0fff, |
|---|
| 1731 | + .init = gic_enable_quirk_arm64_2941627, |
|---|
| 1732 | + }, |
|---|
| 1733 | + { |
|---|
| 1734 | + /* |
|---|
| 1735 | + * GIC-700: 2941627 workaround - IP variant [2] |
|---|
| 1736 | + */ |
|---|
| 1737 | + .desc = "GICv3: ARM64 erratum 2941627", |
|---|
| 1738 | + .iidr = 0x0402043b, |
|---|
| 1739 | + .mask = 0xff0f0fff, |
|---|
| 1740 | + .init = gic_enable_quirk_arm64_2941627, |
|---|
| 1741 | + }, |
|---|
| 1742 | + { |
|---|
| 1667 | 1743 | } |
|---|
| 1668 | 1744 | }; |
|---|
| 1669 | 1745 | |
|---|
| .. | .. |
|---|
| 1674 | 1750 | if (!gic_prio_masking_enabled()) |
|---|
| 1675 | 1751 | return; |
|---|
| 1676 | 1752 | |
|---|
| 1753 | + if (gic_data.flags & FLAGS_WORKAROUND_MTK_GICR_SAVE) { |
|---|
| 1754 | + pr_warn("Skipping NMI enable due to firmware issues\n"); |
|---|
| 1755 | + return; |
|---|
| 1756 | + } |
|---|
| 1757 | + |
|---|
| 1677 | 1758 | ppi_nmi_refs = kcalloc(gic_data.ppi_nr, sizeof(*ppi_nmi_refs), GFP_KERNEL); |
|---|
| 1678 | 1759 | if (!ppi_nmi_refs) |
|---|
| 1679 | 1760 | return; |
|---|