Commit ad7b74b415ab5e38dd4ebf935dad1cee3fec4742
Exists in
smarc_8mq_lf_v2020.04
and in
4 other branches
Merge remote-tracking branch 'origin/ls_v2020.04' into lf_v2020.04
* origin/ls_v2020.04: arm64: gic-v3-its: Clear the Pending table before enabling LPIs
Showing 1 changed file 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 |