arch: arm: use dt and UCLASS_IRQ to get gic details
Use device tree and UCLASS_IRQ driver to get following Generic Interrupt Controller (GIC) details, -GIC Distributor interface (GICD) base address and -GIC Redistributors (GICR) base address. Signed-off-by: Rayagonda Kokatanur <rayagonda.kokatanur@broadcom.com> Reviewed-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
		
							parent
							
								
									7aa17569b0
								
							
						
					
					
						commit
						a76bfe5693
					
				| 
						 | 
					@ -3,6 +3,7 @@
 | 
				
			||||||
 * Copyright 2019 Broadcom.
 | 
					 * Copyright 2019 Broadcom.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#include <common.h>
 | 
					#include <common.h>
 | 
				
			||||||
 | 
					#include <dm.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>
 | 
				
			||||||
| 
						 | 
					@ -15,6 +16,48 @@ 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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * gic_v3_its_priv - gic details
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @gicd_base: gicd base address
 | 
				
			||||||
 | 
					 * @gicr_base: gicr base address
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct gic_v3_its_priv {
 | 
				
			||||||
 | 
						ulong gicd_base;
 | 
				
			||||||
 | 
						ulong gicr_base;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int gic_v3_its_get_gic_addr(struct gic_v3_its_priv *priv)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct udevice *dev;
 | 
				
			||||||
 | 
						fdt_addr_t addr;
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = uclass_get_device_by_driver(UCLASS_IRQ,
 | 
				
			||||||
 | 
										  DM_GET_DRIVER(arm_gic_v3_its), &dev);
 | 
				
			||||||
 | 
						if (ret) {
 | 
				
			||||||
 | 
							pr_err("%s: failed to get %s irq device\n", __func__,
 | 
				
			||||||
 | 
							       DM_GET_DRIVER(arm_gic_v3_its)->name);
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						addr = dev_read_addr_index(dev, 0);
 | 
				
			||||||
 | 
						if (addr == FDT_ADDR_T_NONE) {
 | 
				
			||||||
 | 
							pr_err("%s: failed to get GICD address\n", __func__);
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						priv->gicd_base = addr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						addr = dev_read_addr_index(dev, 1);
 | 
				
			||||||
 | 
						if (addr == FDT_ADDR_T_NONE) {
 | 
				
			||||||
 | 
							pr_err("%s: failed to get GICR address\n", __func__);
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						priv->gicr_base = addr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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
 | 
				
			||||||
| 
						 | 
					@ -23,15 +66,18 @@ static u32 lpi_id_bits;
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int gic_lpi_tables_init(u64 base, u32 num_redist)
 | 
					int gic_lpi_tables_init(u64 base, u32 num_redist)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct gic_v3_its_priv priv;
 | 
				
			||||||
	u32 gicd_typer;
 | 
						u32 gicd_typer;
 | 
				
			||||||
	u64 val;
 | 
						u64 val;
 | 
				
			||||||
	u64 tmp;
 | 
						u64 tmp;
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
	u64 redist_lpi_base;
 | 
						u64 redist_lpi_base;
 | 
				
			||||||
	u64 pend_base = GICR_BASE + GICR_PENDBASER;
 | 
						u64 pend_base;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	gicd_typer = readl(GICD_BASE + GICD_TYPER);
 | 
						if (gic_v3_its_get_gic_addr(&priv))
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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)) {
 | 
				
			||||||
		pr_err("GIC implementation does not support LPI's\n");
 | 
							pr_err("GIC implementation does not support LPI's\n");
 | 
				
			||||||
| 
						 | 
					@ -46,7 +92,7 @@ int gic_lpi_tables_init(u64 base, u32 num_redist)
 | 
				
			||||||
	for (i = 0; i < num_redist; i++) {
 | 
						for (i = 0; i < num_redist; i++) {
 | 
				
			||||||
		u32 offset = i * GIC_REDISTRIBUTOR_OFFSET;
 | 
							u32 offset = i * GIC_REDISTRIBUTOR_OFFSET;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if ((readl((uintptr_t)(GICR_BASE + offset))) &
 | 
							if ((readl((uintptr_t)(priv.gicr_base + offset))) &
 | 
				
			||||||
		    GICR_CTLR_ENABLE_LPIS) {
 | 
							    GICR_CTLR_ENABLE_LPIS) {
 | 
				
			||||||
			pr_err("Re-Distributor %d LPI is already enabled\n",
 | 
								pr_err("Re-Distributor %d LPI is already enabled\n",
 | 
				
			||||||
			       i);
 | 
								       i);
 | 
				
			||||||
| 
						 | 
					@ -64,19 +110,21 @@ int gic_lpi_tables_init(u64 base, u32 num_redist)
 | 
				
			||||||
	       GICR_PROPBASER_RAWAWB |
 | 
						       GICR_PROPBASER_RAWAWB |
 | 
				
			||||||
	       ((LPI_NRBITS - 1) & GICR_PROPBASER_IDBITS_MASK));
 | 
						       ((LPI_NRBITS - 1) & GICR_PROPBASER_IDBITS_MASK));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	writeq(val, (GICR_BASE + GICR_PROPBASER));
 | 
						writeq(val, (uintptr_t)(priv.gicr_base + GICR_PROPBASER));
 | 
				
			||||||
	tmp = readl(GICR_BASE + GICR_PROPBASER);
 | 
						tmp = readl((uintptr_t)(priv.gicr_base + GICR_PROPBASER));
 | 
				
			||||||
	if ((tmp ^ val) & GICR_PROPBASER_SHAREABILITY_MASK) {
 | 
						if ((tmp ^ val) & GICR_PROPBASER_SHAREABILITY_MASK) {
 | 
				
			||||||
		if (!(tmp & GICR_PROPBASER_SHAREABILITY_MASK)) {
 | 
							if (!(tmp & GICR_PROPBASER_SHAREABILITY_MASK)) {
 | 
				
			||||||
			val &= ~(GICR_PROPBASER_SHAREABILITY_MASK |
 | 
								val &= ~(GICR_PROPBASER_SHAREABILITY_MASK |
 | 
				
			||||||
				GICR_PROPBASER_CACHEABILITY_MASK);
 | 
									GICR_PROPBASER_CACHEABILITY_MASK);
 | 
				
			||||||
			val |= GICR_PROPBASER_NC;
 | 
								val |= GICR_PROPBASER_NC;
 | 
				
			||||||
			writeq(val, (GICR_BASE + GICR_PROPBASER));
 | 
								writeq(val,
 | 
				
			||||||
 | 
								       (uintptr_t)(priv.gicr_base + GICR_PROPBASER));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	redist_lpi_base = base + LPI_PROPBASE_SZ;
 | 
						redist_lpi_base = base + LPI_PROPBASE_SZ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pend_base = priv.gicr_base + GICR_PENDBASER;
 | 
				
			||||||
	for (i = 0; i < num_redist; i++) {
 | 
						for (i = 0; i < num_redist; i++) {
 | 
				
			||||||
		u32 offset = i * GIC_REDISTRIBUTOR_OFFSET;
 | 
							u32 offset = i * GIC_REDISTRIBUTOR_OFFSET;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -94,9 +142,20 @@ int gic_lpi_tables_init(u64 base, u32 num_redist)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Enable LPI for the redistributor */
 | 
							/* Enable LPI for the redistributor */
 | 
				
			||||||
		writel(GICR_CTLR_ENABLE_LPIS, (uintptr_t)(GICR_BASE + offset));
 | 
							writel(GICR_CTLR_ENABLE_LPIS,
 | 
				
			||||||
 | 
							       (uintptr_t)(priv.gicr_base + offset));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct udevice_id gic_v3_its_ids[] = {
 | 
				
			||||||
 | 
						{ .compatible = "arm,gic-v3" },
 | 
				
			||||||
 | 
						{}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					U_BOOT_DRIVER(arm_gic_v3_its) = {
 | 
				
			||||||
 | 
						.name		= "gic-v3",
 | 
				
			||||||
 | 
						.id		= UCLASS_IRQ,
 | 
				
			||||||
 | 
						.of_match	= gic_v3_its_ids,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue