arch: arm: Program GIC LPI configuration table
Programs the following: 1. Redistributor PROCBASER configuration table (which is common for all redistributors) 2. Redistributor pending table (PENDBASER), for all the available redistributors. Signed-off-by: Bharat Kumar Reddy Gooty <bharat.gooty@broadcom.com> Signed-off-by: Vladimir Olovyannikov <vladimir.olovyannikov@broadcom.com>
This commit is contained in:
parent
5819466dc1
commit
0bc4356dea
@ -61,6 +61,16 @@ config LNX_KRNL_IMG_TEXT_OFFSET_BASE
|
||||
endif
|
||||
endif
|
||||
|
||||
config GIC_V3_ITS
|
||||
bool "ARM GICV3 ITS"
|
||||
help
|
||||
ARM GICV3 Interrupt translation service (ITS).
|
||||
Basic support for programming locality specific peripheral
|
||||
interrupts (LPI) configuration tables and enable LPI tables.
|
||||
LPI configuration table can be used by u-boot or Linux.
|
||||
ARM GICV3 has limitation, once the LPI table is enabled, LPI
|
||||
configuration table can not be re-programmed, unless GICV3 reset.
|
||||
|
||||
config STATIC_RELA
|
||||
bool
|
||||
default y if ARM64 && !POSITION_INDEPENDENT
|
||||
|
134
arch/arm/include/asm/gic-v3.h
Normal file
134
arch/arm/include/asm/gic-v3.h
Normal file
@ -0,0 +1,134 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
*/
|
||||
|
||||
#ifndef __GIC_V3_H__
|
||||
#define __GIC_V3_H__
|
||||
|
||||
#define GICR_CTLR_ENABLE_LPIS BIT(0)
|
||||
#define GICR_CTLR_RWP BIT(3)
|
||||
|
||||
#define GICR_TYPER_CPU_NUMBER(r) (((r) >> 8) & 0xffff)
|
||||
|
||||
#define GICR_WAKER_PROCESSORSLEEP BIT(1)
|
||||
#define GICR_WAKER_CHILDRENASLEEP BIT(2)
|
||||
|
||||
#define GIC_BASER_CACHE_NCNB 0ULL
|
||||
#define GIC_BASER_CACHE_SAMEASINNER 0ULL
|
||||
#define GIC_BASER_CACHE_NC 1ULL
|
||||
#define GIC_BASER_CACHE_RAWT 2ULL
|
||||
#define GIC_BASER_CACHE_RAWB 3ULL
|
||||
#define GIC_BASER_CACHE_WAWT 4ULL
|
||||
#define GIC_BASER_CACHE_WAWB 5ULL
|
||||
#define GIC_BASER_CACHE_RAWAWT 6ULL
|
||||
#define GIC_BASER_CACHE_RAWAWB 7ULL
|
||||
#define GIC_BASER_CACHE_MASK 7ULL
|
||||
#define GIC_BASER_NONSHAREABLE 0ULL
|
||||
#define GIC_BASER_INNERSHAREABLE 1ULL
|
||||
#define GIC_BASER_OUTERSHAREABLE 2ULL
|
||||
#define GIC_BASER_SHAREABILITY_MASK 3ULL
|
||||
|
||||
#define GIC_BASER_CACHEABILITY(reg, inner_outer, type) \
|
||||
(GIC_BASER_CACHE_##type << reg##_##inner_outer##_CACHEABILITY_SHIFT)
|
||||
|
||||
#define GIC_BASER_SHAREABILITY(reg, type) \
|
||||
(GIC_BASER_##type << reg##_SHAREABILITY_SHIFT)
|
||||
|
||||
/* encode a size field of width @w containing @n - 1 units */
|
||||
#define GIC_ENCODE_SZ(n, w) (((unsigned long)(n) - 1) &\
|
||||
GENMASK_ULL(((w) - 1), 0))
|
||||
|
||||
#define GICR_PROPBASER_SHAREABILITY_SHIFT (10)
|
||||
#define GICR_PROPBASER_INNER_CACHEABILITY_SHIFT (7)
|
||||
#define GICR_PROPBASER_OUTER_CACHEABILITY_SHIFT (56)
|
||||
#define GICR_PROPBASER_SHAREABILITY_MASK \
|
||||
GIC_BASER_SHAREABILITY(GICR_PROPBASER, SHAREABILITY_MASK)
|
||||
#define GICR_PROPBASER_INNER_CACHEABILITY_MASK \
|
||||
GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, MASK)
|
||||
#define GICR_PROPBASER_OUTER_CACHEABILITY_MASK \
|
||||
GIC_BASER_CACHEABILITY(GICR_PROPBASER, OUTER, MASK)
|
||||
#define GICR_PROPBASER_CACHEABILITY_MASK GICR_PROPBASER_INNER_CACHEABILITY_MASK
|
||||
|
||||
#define GICR_PROPBASER_INNERSHAREABLE \
|
||||
GIC_BASER_SHAREABILITY(GICR_PROPBASER, INNERSHAREABLE)
|
||||
|
||||
#define GICR_PROPBASER_NCNB \
|
||||
GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, NCNB)
|
||||
#define GICR_PROPBASER_NC \
|
||||
GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, NC)
|
||||
#define GICR_PROPBASER_RAWT \
|
||||
GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, RAWT)
|
||||
#define GICR_PROPBASER_RAWB \
|
||||
GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, RAWB)
|
||||
#define GICR_PROPBASER_WAWT \
|
||||
GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, WAWT)
|
||||
#define GICR_PROPBASER_WAWB \
|
||||
GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, WAWB)
|
||||
#define GICR_PROPBASER_RAWAWT \
|
||||
GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, RAWAWT)
|
||||
#define GICR_PROPBASER_RAWAWB \
|
||||
GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, RAWAWB)
|
||||
|
||||
#define GICR_PROPBASER_IDBITS_MASK (0x1f)
|
||||
#define GICR_PROPBASER_ADDRESS(x) ((x) & GENMASK_ULL(51, 12))
|
||||
#define GICR_PENDBASER_ADDRESS(x) ((x) & GENMASK_ULL(51, 16))
|
||||
|
||||
#define GICR_PENDBASER_SHAREABILITY_SHIFT (10)
|
||||
#define GICR_PENDBASER_INNER_CACHEABILITY_SHIFT (7)
|
||||
#define GICR_PENDBASER_OUTER_CACHEABILITY_SHIFT (56)
|
||||
#define GICR_PENDBASER_SHAREABILITY_MASK \
|
||||
GIC_BASER_SHAREABILITY(GICR_PENDBASER, SHAREABILITY_MASK)
|
||||
#define GICR_PENDBASER_INNER_CACHEABILITY_MASK \
|
||||
GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, MASK)
|
||||
#define GICR_PENDBASER_OUTER_CACHEABILITY_MASK \
|
||||
GIC_BASER_CACHEABILITY(GICR_PENDBASER, OUTER, MASK)
|
||||
#define GICR_PENDBASER_CACHEABILITY_MASK \
|
||||
GICR_PENDBASER_INNER_CACHEABILITY_MASK
|
||||
|
||||
#define GICR_PENDBASER_INNERSHAREABLE \
|
||||
GIC_BASER_SHAREABILITY(GICR_PENDBASER, INNERSHAREABLE)
|
||||
|
||||
#define GICR_PENDBASER_NCNB \
|
||||
GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, NCNB)
|
||||
#define GICR_PENDBASER_NC \
|
||||
GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, NC)
|
||||
#define GICR_PENDBASER_RAWT \
|
||||
GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, RAWT)
|
||||
#define GICR_PENDBASER_RAWB \
|
||||
GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, RAWB)
|
||||
#define GICR_PENDBASER_WAWT \
|
||||
GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, WAWT)
|
||||
#define GICR_PENDBASER_WAWB \
|
||||
GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, WAWB)
|
||||
#define GICR_PENDBASER_RAWAWT \
|
||||
GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, RAWAWT)
|
||||
#define GICR_PENDBASER_RAWAWB \
|
||||
GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, RAWAWB)
|
||||
|
||||
#define GICR_PENDBASER_PTZ BIT_ULL(62)
|
||||
|
||||
#define ITS_MAX_LPI_NRBITS 16 /* 64K LPIs */
|
||||
|
||||
#define GICD_TYPER_ID_BITS(typer) ((((typer) >> 19) & 0x1f) + 1)
|
||||
#define GICD_TYPER_NUM_LPIS(typer) ((((typer) >> 11) & 0x1f) + 1)
|
||||
#define GICD_TYPER_IRQS(typer) ((((typer) & 0x1f) + 1) * 32)
|
||||
|
||||
/* Message based interrupts support */
|
||||
#define GICD_TYPER_MBIS BIT(16)
|
||||
/* LPI support */
|
||||
#define GICD_TYPER_LPIS BIT(17)
|
||||
#define GICD_TYPER_RSS BIT(26)
|
||||
|
||||
#define GIC_REDISTRIBUTOR_OFFSET 0x20000
|
||||
|
||||
#ifdef CONFIG_GIC_V3_ITS
|
||||
int gic_lpi_tables_init(u64 base, u32 max_redist);
|
||||
#else
|
||||
int gic_lpi_tables_init(u64 base, u32 max_redist)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_GIC_V3_ITS */
|
||||
|
||||
#endif /* __GIC_V3_H__ */
|
@ -52,6 +52,7 @@ obj-$(CONFIG_FSL_LAYERSCAPE) += ccn504.o
|
||||
ifneq ($(CONFIG_GICV2)$(CONFIG_GICV3),)
|
||||
obj-y += gic_64.o
|
||||
endif
|
||||
obj-$(CONFIG_GIC_V3_ITS) += gic-v3-its.o
|
||||
obj-y += interrupts_64.o
|
||||
else
|
||||
obj-y += interrupts.o
|
||||
|
100
arch/arm/lib/gic-v3-its.c
Normal file
100
arch/arm/lib/gic-v3-its.c
Normal file
@ -0,0 +1,100 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <asm/gic.h>
|
||||
#include <asm/gic-v3.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
static u32 lpi_id_bits;
|
||||
|
||||
#define LPI_NRBITS lpi_id_bits
|
||||
#define LPI_PROPBASE_SZ ALIGN(BIT(LPI_NRBITS), SZ_64K)
|
||||
#define LPI_PENDBASE_SZ ALIGN(BIT(LPI_NRBITS) / 8, SZ_64K)
|
||||
|
||||
/*
|
||||
* Program the GIC LPI configuration tables for all
|
||||
* the re-distributors and enable the LPI table
|
||||
* base: Configuration table address
|
||||
* num_redist: number of redistributors
|
||||
*/
|
||||
int gic_lpi_tables_init(u64 base, u32 num_redist)
|
||||
{
|
||||
u32 gicd_typer;
|
||||
u64 val;
|
||||
u64 tmp;
|
||||
int i;
|
||||
u64 redist_lpi_base;
|
||||
u64 pend_base = GICR_BASE + GICR_PENDBASER;
|
||||
|
||||
gicd_typer = readl(GICD_BASE + GICD_TYPER);
|
||||
|
||||
/* GIC support for Locality specific peripheral interrupts (LPI's) */
|
||||
if (!(gicd_typer & GICD_TYPER_LPIS)) {
|
||||
pr_err("GIC implementation does not support LPI's\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for LPI is disabled for all the redistributors.
|
||||
* Once the LPI table is enabled, can not program the
|
||||
* LPI configuration tables again, unless the GIC is reset.
|
||||
*/
|
||||
for (i = 0; i < num_redist; i++) {
|
||||
u32 offset = i * GIC_REDISTRIBUTOR_OFFSET;
|
||||
|
||||
if ((readl((uintptr_t)(GICR_BASE + offset))) &
|
||||
GICR_CTLR_ENABLE_LPIS) {
|
||||
pr_err("Re-Distributor %d LPI is already enabled\n",
|
||||
i);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* lpi_id_bits to get LPI_PENDBASE_SZ and LPi_PROPBASE_SZ */
|
||||
lpi_id_bits = min_t(u32, GICD_TYPER_ID_BITS(gicd_typer),
|
||||
ITS_MAX_LPI_NRBITS);
|
||||
|
||||
/* Set PropBase */
|
||||
val = (base |
|
||||
GICR_PROPBASER_INNERSHAREABLE |
|
||||
GICR_PROPBASER_RAWAWB |
|
||||
((LPI_NRBITS - 1) & GICR_PROPBASER_IDBITS_MASK));
|
||||
|
||||
writeq(val, (GICR_BASE + GICR_PROPBASER));
|
||||
tmp = readl(GICR_BASE + GICR_PROPBASER);
|
||||
if ((tmp ^ val) & GICR_PROPBASER_SHAREABILITY_MASK) {
|
||||
if (!(tmp & GICR_PROPBASER_SHAREABILITY_MASK)) {
|
||||
val &= ~(GICR_PROPBASER_SHAREABILITY_MASK |
|
||||
GICR_PROPBASER_CACHEABILITY_MASK);
|
||||
val |= GICR_PROPBASER_NC;
|
||||
writeq(val, (GICR_BASE + GICR_PROPBASER));
|
||||
}
|
||||
}
|
||||
|
||||
redist_lpi_base = base + LPI_PROPBASE_SZ;
|
||||
|
||||
for (i = 0; i < num_redist; i++) {
|
||||
u32 offset = i * GIC_REDISTRIBUTOR_OFFSET;
|
||||
|
||||
val = ((redist_lpi_base + (i * LPI_PENDBASE_SZ)) |
|
||||
GICR_PENDBASER_INNERSHAREABLE |
|
||||
GICR_PENDBASER_RAWAWB);
|
||||
|
||||
writeq(val, (uintptr_t)(pend_base + offset));
|
||||
tmp = readq((uintptr_t)(pend_base + offset));
|
||||
if (!(tmp & GICR_PENDBASER_SHAREABILITY_MASK)) {
|
||||
val &= ~(GICR_PENDBASER_SHAREABILITY_MASK |
|
||||
GICR_PENDBASER_CACHEABILITY_MASK);
|
||||
val |= GICR_PENDBASER_NC;
|
||||
writeq(val, (uintptr_t)(pend_base + offset));
|
||||
}
|
||||
|
||||
/* Enable LPI for the redistributor */
|
||||
writel(GICR_CTLR_ENABLE_LPIS, (uintptr_t)(GICR_BASE + offset));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user