1*91a6c3ceSAndrew Jones /* 2*91a6c3ceSAndrew Jones * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com> 3*91a6c3ceSAndrew Jones * 4*91a6c3ceSAndrew Jones * This work is licensed under the terms of the GNU LGPL, version 2. 5*91a6c3ceSAndrew Jones */ 6*91a6c3ceSAndrew Jones #include <asm/gic.h> 7*91a6c3ceSAndrew Jones #include <asm/io.h> 8*91a6c3ceSAndrew Jones 9*91a6c3ceSAndrew Jones void gicv3_set_redist_base(size_t stride) 10*91a6c3ceSAndrew Jones { 11*91a6c3ceSAndrew Jones u32 aff = mpidr_compress(get_mpidr()); 12*91a6c3ceSAndrew Jones void *ptr = gicv3_data.redist_base[0]; 13*91a6c3ceSAndrew Jones u64 typer; 14*91a6c3ceSAndrew Jones 15*91a6c3ceSAndrew Jones do { 16*91a6c3ceSAndrew Jones typer = gicv3_read_typer(ptr + GICR_TYPER); 17*91a6c3ceSAndrew Jones if ((typer >> 32) == aff) { 18*91a6c3ceSAndrew Jones gicv3_redist_base() = ptr; 19*91a6c3ceSAndrew Jones return; 20*91a6c3ceSAndrew Jones } 21*91a6c3ceSAndrew Jones ptr += stride; /* skip RD_base, SGI_base, etc. */ 22*91a6c3ceSAndrew Jones } while (!(typer & GICR_TYPER_LAST)); 23*91a6c3ceSAndrew Jones 24*91a6c3ceSAndrew Jones /* should never reach here */ 25*91a6c3ceSAndrew Jones assert(0); 26*91a6c3ceSAndrew Jones } 27*91a6c3ceSAndrew Jones 28*91a6c3ceSAndrew Jones void gicv3_enable_defaults(void) 29*91a6c3ceSAndrew Jones { 30*91a6c3ceSAndrew Jones void *dist = gicv3_dist_base(); 31*91a6c3ceSAndrew Jones void *sgi_base; 32*91a6c3ceSAndrew Jones unsigned int i; 33*91a6c3ceSAndrew Jones 34*91a6c3ceSAndrew Jones gicv3_data.irq_nr = GICD_TYPER_IRQS(readl(dist + GICD_TYPER)); 35*91a6c3ceSAndrew Jones if (gicv3_data.irq_nr > 1020) 36*91a6c3ceSAndrew Jones gicv3_data.irq_nr = 1020; 37*91a6c3ceSAndrew Jones 38*91a6c3ceSAndrew Jones writel(0, dist + GICD_CTLR); 39*91a6c3ceSAndrew Jones gicv3_dist_wait_for_rwp(); 40*91a6c3ceSAndrew Jones 41*91a6c3ceSAndrew Jones writel(GICD_CTLR_ARE_NS | GICD_CTLR_ENABLE_G1A | GICD_CTLR_ENABLE_G1, 42*91a6c3ceSAndrew Jones dist + GICD_CTLR); 43*91a6c3ceSAndrew Jones gicv3_dist_wait_for_rwp(); 44*91a6c3ceSAndrew Jones 45*91a6c3ceSAndrew Jones for (i = 0; i < gicv3_data.irq_nr; i += 4) 46*91a6c3ceSAndrew Jones writel(~0, dist + GICD_IGROUPR + i); 47*91a6c3ceSAndrew Jones 48*91a6c3ceSAndrew Jones if (!gicv3_redist_base()) 49*91a6c3ceSAndrew Jones gicv3_set_redist_base(SZ_64K * 2); 50*91a6c3ceSAndrew Jones sgi_base = gicv3_sgi_base(); 51*91a6c3ceSAndrew Jones 52*91a6c3ceSAndrew Jones writel(~0, sgi_base + GICR_IGROUPR0); 53*91a6c3ceSAndrew Jones 54*91a6c3ceSAndrew Jones for (i = 0; i < 16; i += 4) 55*91a6c3ceSAndrew Jones writel(GICD_INT_DEF_PRI_X4, sgi_base + GICR_IPRIORITYR0 + i); 56*91a6c3ceSAndrew Jones 57*91a6c3ceSAndrew Jones writel(GICD_INT_EN_SET_SGI, sgi_base + GICR_ISENABLER0); 58*91a6c3ceSAndrew Jones 59*91a6c3ceSAndrew Jones gicv3_write_pmr(GICC_INT_PRI_THRESHOLD); 60*91a6c3ceSAndrew Jones gicv3_write_grpen1(1); 61*91a6c3ceSAndrew Jones } 62