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