Commit ad7b74b415ab5e38dd4ebf935dad1cee3fec4742

Authored by BJ DevOps Team

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