1
0
mirror of https://xff.cz/git/u-boot/ synced 2025-09-30 06:51:28 +02:00

arch: arm: use dt and UCLASS_SYSCON to get gic lpi details

Use device tree and UCLASS_SYSCON driver to get
Generic Interrupt Controller (GIC) lpi address and
maximum GIC redistributors count.

Also update Kconfig to select REGMAP and SYSCON when
GIC_V3_ITS is enabled.

Signed-off-by: Rayagonda Kokatanur <rayagonda.kokatanur@broadcom.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Rayagonda Kokatanur
2020-07-26 22:37:33 +05:30
committed by Tom Rini
parent a76bfe5693
commit 2ae7adc659
4 changed files with 61 additions and 36 deletions

View File

@@ -64,6 +64,8 @@ endif
config GIC_V3_ITS config GIC_V3_ITS
bool "ARM GICV3 ITS" bool "ARM GICV3 ITS"
select REGMAP
select SYSCON
help help
ARM GICV3 Interrupt translation service (ITS). ARM GICV3 Interrupt translation service (ITS).
Basic support for programming locality specific peripheral Basic support for programming locality specific peripheral

View File

@@ -41,37 +41,11 @@ DECLARE_GLOBAL_DATA_PTR;
#endif #endif
#ifdef CONFIG_GIC_V3_ITS #ifdef CONFIG_GIC_V3_ITS
#define PENDTABLE_MAX_SZ ALIGN(BIT(ITS_MAX_LPI_NRBITS), SZ_64K)
#define PROPTABLE_MAX_SZ ALIGN(BIT(ITS_MAX_LPI_NRBITS) / 8, SZ_64K)
#define GIC_LPI_SIZE ALIGN(cpu_numcores() * PENDTABLE_MAX_SZ + \
PROPTABLE_MAX_SZ, SZ_1M)
static int fdt_add_resv_mem_gic_rd_tables(void *blob, u64 base, size_t size)
{
u32 phandle;
int err;
struct fdt_memory gic_rd_tables;
gic_rd_tables.start = base;
gic_rd_tables.end = base + size - 1;
err = fdtdec_add_reserved_memory(blob, "gic-rd-tables", &gic_rd_tables,
&phandle);
if (err < 0)
debug("%s: failed to add reserved memory: %d\n", __func__, err);
return err;
}
int ls_gic_rd_tables_init(void *blob) int ls_gic_rd_tables_init(void *blob)
{ {
u64 gic_lpi_base;
int ret; int ret;
gic_lpi_base = ALIGN(gd->arch.resv_ram - GIC_LPI_SIZE, SZ_64K); ret = gic_lpi_tables_init();
ret = fdt_add_resv_mem_gic_rd_tables(blob, gic_lpi_base, GIC_LPI_SIZE);
if (ret)
return ret;
ret = gic_lpi_tables_init(gic_lpi_base, cpu_numcores());
if (ret) if (ret)
debug("%s: failed to init gic-lpi-tables\n", __func__); debug("%s: failed to init gic-lpi-tables\n", __func__);

View File

@@ -127,9 +127,9 @@
#define GIC_REDISTRIBUTOR_OFFSET 0x20000 #define GIC_REDISTRIBUTOR_OFFSET 0x20000
#ifdef CONFIG_GIC_V3_ITS #ifdef CONFIG_GIC_V3_ITS
int gic_lpi_tables_init(u64 base, u32 max_redist); int gic_lpi_tables_init(void);
#else #else
int gic_lpi_tables_init(u64 base, u32 max_redist) int gic_lpi_tables_init(void)
{ {
return 0; return 0;
} }

View File

@@ -4,6 +4,8 @@
*/ */
#include <common.h> #include <common.h>
#include <dm.h> #include <dm.h>
#include <regmap.h>
#include <syscon.h>
#include <asm/gic.h> #include <asm/gic.h>
#include <asm/gic-v3.h> #include <asm/gic-v3.h>
#include <asm/io.h> #include <asm/io.h>
@@ -16,15 +18,22 @@ static u32 lpi_id_bits;
#define LPI_PROPBASE_SZ ALIGN(BIT(LPI_NRBITS), SZ_64K) #define LPI_PROPBASE_SZ ALIGN(BIT(LPI_NRBITS), SZ_64K)
#define LPI_PENDBASE_SZ ALIGN(BIT(LPI_NRBITS) / 8, SZ_64K) #define LPI_PENDBASE_SZ ALIGN(BIT(LPI_NRBITS) / 8, SZ_64K)
/* Number of GIC re-distributors */
#define MAX_GIC_REDISTRIBUTORS 8
/* /*
* gic_v3_its_priv - gic details * gic_v3_its_priv - gic details
* *
* @gicd_base: gicd base address * @gicd_base: gicd base address
* @gicr_base: gicr base address * @gicr_base: gicr base address
* @lpi_base: gic lpi base address
* @num_redist: number of gic re-distributors
*/ */
struct gic_v3_its_priv { struct gic_v3_its_priv {
ulong gicd_base; ulong gicd_base;
ulong gicr_base; ulong gicr_base;
ulong lpi_base;
u32 num_redist;
}; };
static int gic_v3_its_get_gic_addr(struct gic_v3_its_priv *priv) static int gic_v3_its_get_gic_addr(struct gic_v3_its_priv *priv)
@@ -58,13 +67,39 @@ static int gic_v3_its_get_gic_addr(struct gic_v3_its_priv *priv)
return 0; return 0;
} }
static int gic_v3_its_get_gic_lpi_addr(struct gic_v3_its_priv *priv)
{
struct regmap *regmap;
struct udevice *dev;
int ret;
ret = uclass_get_device_by_driver(UCLASS_SYSCON,
DM_GET_DRIVER(gic_lpi_syscon), &dev);
if (ret) {
pr_err("%s: failed to get %s syscon device\n", __func__,
DM_GET_DRIVER(gic_lpi_syscon)->name);
return ret;
}
regmap = syscon_get_regmap(dev);
if (!regmap) {
pr_err("%s: failed to regmap for %s syscon device\n", __func__,
DM_GET_DRIVER(gic_lpi_syscon)->name);
return -ENODEV;
}
priv->lpi_base = regmap->ranges[0].start;
priv->num_redist = dev_read_u32_default(dev, "max-gic-redistributors",
MAX_GIC_REDISTRIBUTORS);
return 0;
}
/* /*
* Program the GIC LPI configuration tables for all * Program the GIC LPI configuration tables for all
* the re-distributors and enable the LPI table * 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) int gic_lpi_tables_init(void)
{ {
struct gic_v3_its_priv priv; struct gic_v3_its_priv priv;
u32 gicd_typer; u32 gicd_typer;
@@ -77,6 +112,9 @@ int gic_lpi_tables_init(u64 base, u32 num_redist)
if (gic_v3_its_get_gic_addr(&priv)) if (gic_v3_its_get_gic_addr(&priv))
return -EINVAL; return -EINVAL;
if (gic_v3_its_get_gic_lpi_addr(&priv))
return -EINVAL;
gicd_typer = readl((uintptr_t)(priv.gicd_base + GICD_TYPER)); gicd_typer = readl((uintptr_t)(priv.gicd_base + GICD_TYPER));
/* GIC support for Locality specific peripheral interrupts (LPI's) */ /* GIC support for Locality specific peripheral interrupts (LPI's) */
if (!(gicd_typer & GICD_TYPER_LPIS)) { if (!(gicd_typer & GICD_TYPER_LPIS)) {
@@ -89,7 +127,7 @@ int gic_lpi_tables_init(u64 base, u32 num_redist)
* Once the LPI table is enabled, can not program the * Once the LPI table is enabled, can not program the
* LPI configuration tables again, unless the GIC is reset. * LPI configuration tables again, unless the GIC is reset.
*/ */
for (i = 0; i < num_redist; i++) { for (i = 0; i < priv.num_redist; i++) {
u32 offset = i * GIC_REDISTRIBUTOR_OFFSET; u32 offset = i * GIC_REDISTRIBUTOR_OFFSET;
if ((readl((uintptr_t)(priv.gicr_base + offset))) & if ((readl((uintptr_t)(priv.gicr_base + offset))) &
@@ -105,7 +143,7 @@ int gic_lpi_tables_init(u64 base, u32 num_redist)
ITS_MAX_LPI_NRBITS); ITS_MAX_LPI_NRBITS);
/* Set PropBase */ /* Set PropBase */
val = (base | val = (priv.lpi_base |
GICR_PROPBASER_INNERSHAREABLE | GICR_PROPBASER_INNERSHAREABLE |
GICR_PROPBASER_RAWAWB | GICR_PROPBASER_RAWAWB |
((LPI_NRBITS - 1) & GICR_PROPBASER_IDBITS_MASK)); ((LPI_NRBITS - 1) & GICR_PROPBASER_IDBITS_MASK));
@@ -122,10 +160,10 @@ int gic_lpi_tables_init(u64 base, u32 num_redist)
} }
} }
redist_lpi_base = base + LPI_PROPBASE_SZ; redist_lpi_base = priv.lpi_base + LPI_PROPBASE_SZ;
pend_base = priv.gicr_base + GICR_PENDBASER; pend_base = priv.gicr_base + GICR_PENDBASER;
for (i = 0; i < num_redist; i++) { for (i = 0; i < priv.num_redist; i++) {
u32 offset = i * GIC_REDISTRIBUTOR_OFFSET; u32 offset = i * GIC_REDISTRIBUTOR_OFFSET;
val = ((redist_lpi_base + (i * LPI_PENDBASE_SZ)) | val = ((redist_lpi_base + (i * LPI_PENDBASE_SZ)) |
@@ -159,3 +197,14 @@ U_BOOT_DRIVER(arm_gic_v3_its) = {
.id = UCLASS_IRQ, .id = UCLASS_IRQ,
.of_match = gic_v3_its_ids, .of_match = gic_v3_its_ids,
}; };
static const struct udevice_id gic_lpi_syscon_ids[] = {
{ .compatible = "gic-lpi-base" },
{}
};
U_BOOT_DRIVER(gic_lpi_syscon) = {
.name = "gic-lpi-base",
.id = UCLASS_SYSCON,
.of_match = gic_lpi_syscon_ids,
};