diff options
-rw-r--r-- | arch/arm64/Kconfig | 17 | ||||
-rw-r--r-- | drivers/irqchip/irq-gic-v3-its.c | 37 |
2 files changed, 50 insertions, 4 deletions
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 490df449377d..440d906429de 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig | |||
@@ -348,6 +348,23 @@ config ARM64_ERRATUM_843419 | |||
348 | 348 | ||
349 | If unsure, say Y. | 349 | If unsure, say Y. |
350 | 350 | ||
351 | config CAVIUM_ERRATUM_22375 | ||
352 | bool "Cavium erratum 22375, 24313" | ||
353 | default y | ||
354 | help | ||
355 | Enable workaround for erratum 22375, 24313. | ||
356 | |||
357 | This implements two gicv3-its errata workarounds for ThunderX. Both | ||
358 | with small impact affecting only ITS table allocation. | ||
359 | |||
360 | erratum 22375: only alloc 8MB table size | ||
361 | erratum 24313: ignore memory access type | ||
362 | |||
363 | The fixes are in ITS initialization and basically ignore memory access | ||
364 | type and table size provided by the TYPER and BASER registers. | ||
365 | |||
366 | If unsure, say Y. | ||
367 | |||
351 | config CAVIUM_ERRATUM_23154 | 368 | config CAVIUM_ERRATUM_23154 |
352 | bool "Cavium erratum 23154: Access to ICC_IAR1_EL1 is not sync'ed" | 369 | bool "Cavium erratum 23154: Access to ICC_IAR1_EL1 is not sync'ed" |
353 | default y | 370 | default y |
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 82622afc916b..eac44dd28ca1 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c | |||
@@ -39,7 +39,8 @@ | |||
39 | 39 | ||
40 | #include "irq-gic-common.h" | 40 | #include "irq-gic-common.h" |
41 | 41 | ||
42 | #define ITS_FLAGS_CMDQ_NEEDS_FLUSHING (1 << 0) | 42 | #define ITS_FLAGS_CMDQ_NEEDS_FLUSHING (1ULL << 0) |
43 | #define ITS_FLAGS_WORKAROUND_CAVIUM_22375 (1ULL << 1) | ||
43 | 44 | ||
44 | #define RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING (1 << 0) | 45 | #define RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING (1 << 0) |
45 | 46 | ||
@@ -816,9 +817,22 @@ static int its_alloc_tables(const char *node_name, struct its_node *its) | |||
816 | int i; | 817 | int i; |
817 | int psz = SZ_64K; | 818 | int psz = SZ_64K; |
818 | u64 shr = GITS_BASER_InnerShareable; | 819 | u64 shr = GITS_BASER_InnerShareable; |
819 | u64 cache = GITS_BASER_WaWb; | 820 | u64 cache; |
820 | u64 typer = readq_relaxed(its->base + GITS_TYPER); | 821 | u64 typer; |
821 | u32 ids = GITS_TYPER_DEVBITS(typer); | 822 | u32 ids; |
823 | |||
824 | if (its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_22375) { | ||
825 | /* | ||
826 | * erratum 22375: only alloc 8MB table size | ||
827 | * erratum 24313: ignore memory access type | ||
828 | */ | ||
829 | cache = 0; | ||
830 | ids = 0x14; /* 20 bits, 8MB */ | ||
831 | } else { | ||
832 | cache = GITS_BASER_WaWb; | ||
833 | typer = readq_relaxed(its->base + GITS_TYPER); | ||
834 | ids = GITS_TYPER_DEVBITS(typer); | ||
835 | } | ||
822 | 836 | ||
823 | for (i = 0; i < GITS_BASER_NR_REGS; i++) { | 837 | for (i = 0; i < GITS_BASER_NR_REGS; i++) { |
824 | u64 val = readq_relaxed(its->base + GITS_BASER + i * 8); | 838 | u64 val = readq_relaxed(its->base + GITS_BASER + i * 8); |
@@ -1377,7 +1391,22 @@ static int its_force_quiescent(void __iomem *base) | |||
1377 | } | 1391 | } |
1378 | } | 1392 | } |
1379 | 1393 | ||
1394 | static void __maybe_unused its_enable_quirk_cavium_22375(void *data) | ||
1395 | { | ||
1396 | struct its_node *its = data; | ||
1397 | |||
1398 | its->flags |= ITS_FLAGS_WORKAROUND_CAVIUM_22375; | ||
1399 | } | ||
1400 | |||
1380 | static const struct gic_quirk its_quirks[] = { | 1401 | static const struct gic_quirk its_quirks[] = { |
1402 | #ifdef CONFIG_CAVIUM_ERRATUM_22375 | ||
1403 | { | ||
1404 | .desc = "ITS: Cavium errata 22375, 24313", | ||
1405 | .iidr = 0xa100034c, /* ThunderX pass 1.x */ | ||
1406 | .mask = 0xffff0fff, | ||
1407 | .init = its_enable_quirk_cavium_22375, | ||
1408 | }, | ||
1409 | #endif | ||
1381 | { | 1410 | { |
1382 | } | 1411 | } |
1383 | }; | 1412 | }; |