Commit c7c0a4c5d77c58efd048b34498110972bdac43ce
Committed by
Priyanka Jain
1 parent
28121af8c1
Exists in
smarc_8mq_lf_v2020.04
and in
4 other branches
arm64: gic-v3-its: Clear the Pending table before enabling LPIs
The GICv3 RM requires "The first 1KB of memory for the LPI Pending tables must contain only zeros on initial allocation, and this must be visible to the Redistributors, or else the effect is UNPREDICTABLE". And as the following statement, we here clear the whole Pending tables instead of the first 1KB. "An LPI Pending table that contains only zeros, including in the first 1KB, indicates that there are no pending LPIs. The first 1KB of the LPI Pending table is IMPLEMENTATION DEFINED. However, if the first 1KB of the LPI Pending table and the rest of the table contain only zeros, this must indicate that there are no pending LPIs." And there isn't any pending LPI under U-Boot, so it's unnecessary to loading the contents of the Pending table during the enablement, then set the GICR_PENDBASER.PTZ flag. Signed-off-by: Hou Zhiqiang <Zhiqiang.Hou@nxp.com> Tested-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Showing 1 changed file with 11 additions and 1 deletions Inline Diff
arch/arm/lib/gic-v3-its.c
1 | // SPDX-License-Identifier: GPL-2.0+ | 1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | 2 | /* |
3 | * Copyright 2019 Broadcom. | 3 | * Copyright 2019 Broadcom. |
4 | */ | 4 | */ |
5 | #include <common.h> | 5 | #include <common.h> |
6 | #include <cpu_func.h> | ||
6 | #include <asm/gic.h> | 7 | #include <asm/gic.h> |
7 | #include <asm/gic-v3.h> | 8 | #include <asm/gic-v3.h> |
8 | #include <asm/io.h> | 9 | #include <asm/io.h> |
9 | #include <linux/sizes.h> | 10 | #include <linux/sizes.h> |
10 | 11 | ||
11 | static u32 lpi_id_bits; | 12 | static u32 lpi_id_bits; |
12 | 13 | ||
13 | #define LPI_NRBITS lpi_id_bits | 14 | #define LPI_NRBITS lpi_id_bits |
14 | #define LPI_PROPBASE_SZ ALIGN(BIT(LPI_NRBITS), SZ_64K) | 15 | #define LPI_PROPBASE_SZ ALIGN(BIT(LPI_NRBITS), SZ_64K) |
15 | #define LPI_PENDBASE_SZ ALIGN(BIT(LPI_NRBITS) / 8, SZ_64K) | 16 | #define LPI_PENDBASE_SZ ALIGN(BIT(LPI_NRBITS) / 8, SZ_64K) |
16 | 17 | ||
17 | /* | 18 | /* |
18 | * Program the GIC LPI configuration tables for all | 19 | * Program the GIC LPI configuration tables for all |
19 | * the re-distributors and enable the LPI table | 20 | * the re-distributors and enable the LPI table |
20 | * base: Configuration table address | 21 | * base: Configuration table address |
21 | * num_redist: number of redistributors | 22 | * num_redist: number of redistributors |
22 | */ | 23 | */ |
23 | int gic_lpi_tables_init(u64 base, u32 num_redist) | 24 | int gic_lpi_tables_init(u64 base, u32 num_redist) |
24 | { | 25 | { |
25 | u32 gicd_typer; | 26 | u32 gicd_typer; |
26 | u64 val; | 27 | u64 val; |
27 | u64 tmp; | 28 | u64 tmp; |
28 | int i; | 29 | int i; |
29 | u64 redist_lpi_base; | 30 | u64 redist_lpi_base; |
30 | u64 pend_base = GICR_BASE + GICR_PENDBASER; | 31 | u64 pend_base = GICR_BASE + GICR_PENDBASER; |
32 | ulong pend_tab_total_sz; | ||
33 | void *pend_tab_va; | ||
31 | 34 | ||
32 | gicd_typer = readl(GICD_BASE + GICD_TYPER); | 35 | gicd_typer = readl(GICD_BASE + GICD_TYPER); |
33 | 36 | ||
34 | /* GIC support for Locality specific peripheral interrupts (LPI's) */ | 37 | /* GIC support for Locality specific peripheral interrupts (LPI's) */ |
35 | if (!(gicd_typer & GICD_TYPER_LPIS)) { | 38 | if (!(gicd_typer & GICD_TYPER_LPIS)) { |
36 | pr_err("GIC implementation does not support LPI's\n"); | 39 | pr_err("GIC implementation does not support LPI's\n"); |
37 | return -EINVAL; | 40 | return -EINVAL; |
38 | } | 41 | } |
39 | 42 | ||
40 | /* | 43 | /* |
41 | * Check for LPI is disabled for all the redistributors. | 44 | * Check for LPI is disabled for all the redistributors. |
42 | * Once the LPI table is enabled, can not program the | 45 | * Once the LPI table is enabled, can not program the |
43 | * LPI configuration tables again, unless the GIC is reset. | 46 | * LPI configuration tables again, unless the GIC is reset. |
44 | */ | 47 | */ |
45 | for (i = 0; i < num_redist; i++) { | 48 | for (i = 0; i < num_redist; i++) { |
46 | u32 offset = i * GIC_REDISTRIBUTOR_OFFSET; | 49 | u32 offset = i * GIC_REDISTRIBUTOR_OFFSET; |
47 | 50 | ||
48 | if ((readl((uintptr_t)(GICR_BASE + offset))) & | 51 | if ((readl((uintptr_t)(GICR_BASE + offset))) & |
49 | GICR_CTLR_ENABLE_LPIS) { | 52 | GICR_CTLR_ENABLE_LPIS) { |
50 | pr_err("Re-Distributor %d LPI is already enabled\n", | 53 | pr_err("Re-Distributor %d LPI is already enabled\n", |
51 | i); | 54 | i); |
52 | return -EINVAL; | 55 | return -EINVAL; |
53 | } | 56 | } |
54 | } | 57 | } |
55 | 58 | ||
56 | /* lpi_id_bits to get LPI_PENDBASE_SZ and LPi_PROPBASE_SZ */ | 59 | /* lpi_id_bits to get LPI_PENDBASE_SZ and LPi_PROPBASE_SZ */ |
57 | lpi_id_bits = min_t(u32, GICD_TYPER_ID_BITS(gicd_typer), | 60 | lpi_id_bits = min_t(u32, GICD_TYPER_ID_BITS(gicd_typer), |
58 | ITS_MAX_LPI_NRBITS); | 61 | ITS_MAX_LPI_NRBITS); |
59 | 62 | ||
60 | /* Set PropBase */ | 63 | /* Set PropBase */ |
61 | val = (base | | 64 | val = (base | |
62 | GICR_PROPBASER_INNERSHAREABLE | | 65 | GICR_PROPBASER_INNERSHAREABLE | |
63 | GICR_PROPBASER_RAWAWB | | 66 | GICR_PROPBASER_RAWAWB | |
64 | ((LPI_NRBITS - 1) & GICR_PROPBASER_IDBITS_MASK)); | 67 | ((LPI_NRBITS - 1) & GICR_PROPBASER_IDBITS_MASK)); |
65 | 68 | ||
66 | writeq(val, (GICR_BASE + GICR_PROPBASER)); | 69 | writeq(val, (GICR_BASE + GICR_PROPBASER)); |
67 | tmp = readl(GICR_BASE + GICR_PROPBASER); | 70 | tmp = readl(GICR_BASE + GICR_PROPBASER); |
68 | if ((tmp ^ val) & GICR_PROPBASER_SHAREABILITY_MASK) { | 71 | if ((tmp ^ val) & GICR_PROPBASER_SHAREABILITY_MASK) { |
69 | if (!(tmp & GICR_PROPBASER_SHAREABILITY_MASK)) { | 72 | if (!(tmp & GICR_PROPBASER_SHAREABILITY_MASK)) { |
70 | val &= ~(GICR_PROPBASER_SHAREABILITY_MASK | | 73 | val &= ~(GICR_PROPBASER_SHAREABILITY_MASK | |
71 | GICR_PROPBASER_CACHEABILITY_MASK); | 74 | GICR_PROPBASER_CACHEABILITY_MASK); |
72 | val |= GICR_PROPBASER_NC; | 75 | val |= GICR_PROPBASER_NC; |
73 | writeq(val, (GICR_BASE + GICR_PROPBASER)); | 76 | writeq(val, (GICR_BASE + GICR_PROPBASER)); |
74 | } | 77 | } |
75 | } | 78 | } |
76 | 79 | ||
77 | redist_lpi_base = base + LPI_PROPBASE_SZ; | 80 | redist_lpi_base = base + LPI_PROPBASE_SZ; |
78 | 81 | ||
82 | pend_tab_total_sz = num_redist * LPI_PENDBASE_SZ; | ||
83 | pend_tab_va = map_physmem(redist_lpi_base, pend_tab_total_sz, MAP_NOCACHE); | ||
84 | memset(pend_tab_va, 0, pend_tab_total_sz); | ||
85 | flush_cache((ulong)pend_tab_va, pend_tab_total_sz); | ||
86 | unmap_physmem(pend_tab_va, MAP_NOCACHE); | ||
87 | |||
79 | for (i = 0; i < num_redist; i++) { | 88 | for (i = 0; i < num_redist; i++) { |
80 | u32 offset = i * GIC_REDISTRIBUTOR_OFFSET; | 89 | u32 offset = i * GIC_REDISTRIBUTOR_OFFSET; |
81 | 90 | ||
82 | val = ((redist_lpi_base + (i * LPI_PENDBASE_SZ)) | | 91 | val = ((redist_lpi_base + (i * LPI_PENDBASE_SZ)) | |
83 | GICR_PENDBASER_INNERSHAREABLE | | 92 | GICR_PENDBASER_INNERSHAREABLE | |
84 | GICR_PENDBASER_RAWAWB); | 93 | GICR_PENDBASER_RAWAWB | |
94 | GICR_PENDBASER_PTZ); | ||
85 | 95 | ||
86 | writeq(val, (uintptr_t)(pend_base + offset)); | 96 | writeq(val, (uintptr_t)(pend_base + offset)); |
87 | tmp = readq((uintptr_t)(pend_base + offset)); | 97 | tmp = readq((uintptr_t)(pend_base + offset)); |
88 | if (!(tmp & GICR_PENDBASER_SHAREABILITY_MASK)) { | 98 | if (!(tmp & GICR_PENDBASER_SHAREABILITY_MASK)) { |
89 | val &= ~(GICR_PENDBASER_SHAREABILITY_MASK | | 99 | val &= ~(GICR_PENDBASER_SHAREABILITY_MASK | |
90 | GICR_PENDBASER_CACHEABILITY_MASK); | 100 | GICR_PENDBASER_CACHEABILITY_MASK); |
91 | val |= GICR_PENDBASER_NC; | 101 | val |= GICR_PENDBASER_NC; |
92 | writeq(val, (uintptr_t)(pend_base + offset)); | 102 | writeq(val, (uintptr_t)(pend_base + offset)); |
93 | } | 103 | } |
94 | 104 | ||
95 | /* Enable LPI for the redistributor */ | 105 | /* Enable LPI for the redistributor */ |
96 | writel(GICR_CTLR_ENABLE_LPIS, (uintptr_t)(GICR_BASE + offset)); | 106 | writel(GICR_CTLR_ENABLE_LPIS, (uintptr_t)(GICR_BASE + offset)); |
97 | } | 107 | } |
98 | 108 | ||
99 | return 0; | 109 | return 0; |
100 | } | 110 | } |
101 | 111 | ||
102 | 112 |