18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * arch/arm/include/asm/arch_gicv3.h 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2015 ARM Ltd. 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci#ifndef __ASM_ARCH_GICV3_H 88c2ecf20Sopenharmony_ci#define __ASM_ARCH_GICV3_H 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <linux/io.h> 138c2ecf20Sopenharmony_ci#include <linux/io-64-nonatomic-lo-hi.h> 148c2ecf20Sopenharmony_ci#include <asm/barrier.h> 158c2ecf20Sopenharmony_ci#include <asm/cacheflush.h> 168c2ecf20Sopenharmony_ci#include <asm/cp15.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#define ICC_EOIR1 __ACCESS_CP15(c12, 0, c12, 1) 198c2ecf20Sopenharmony_ci#define ICC_DIR __ACCESS_CP15(c12, 0, c11, 1) 208c2ecf20Sopenharmony_ci#define ICC_IAR1 __ACCESS_CP15(c12, 0, c12, 0) 218c2ecf20Sopenharmony_ci#define ICC_SGI1R __ACCESS_CP15_64(0, c12) 228c2ecf20Sopenharmony_ci#define ICC_PMR __ACCESS_CP15(c4, 0, c6, 0) 238c2ecf20Sopenharmony_ci#define ICC_CTLR __ACCESS_CP15(c12, 0, c12, 4) 248c2ecf20Sopenharmony_ci#define ICC_SRE __ACCESS_CP15(c12, 0, c12, 5) 258c2ecf20Sopenharmony_ci#define ICC_IGRPEN1 __ACCESS_CP15(c12, 0, c12, 7) 268c2ecf20Sopenharmony_ci#define ICC_BPR1 __ACCESS_CP15(c12, 0, c12, 3) 278c2ecf20Sopenharmony_ci#define ICC_RPR __ACCESS_CP15(c12, 0, c11, 3) 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#define __ICC_AP0Rx(x) __ACCESS_CP15(c12, 0, c8, 4 | x) 308c2ecf20Sopenharmony_ci#define ICC_AP0R0 __ICC_AP0Rx(0) 318c2ecf20Sopenharmony_ci#define ICC_AP0R1 __ICC_AP0Rx(1) 328c2ecf20Sopenharmony_ci#define ICC_AP0R2 __ICC_AP0Rx(2) 338c2ecf20Sopenharmony_ci#define ICC_AP0R3 __ICC_AP0Rx(3) 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#define __ICC_AP1Rx(x) __ACCESS_CP15(c12, 0, c9, x) 368c2ecf20Sopenharmony_ci#define ICC_AP1R0 __ICC_AP1Rx(0) 378c2ecf20Sopenharmony_ci#define ICC_AP1R1 __ICC_AP1Rx(1) 388c2ecf20Sopenharmony_ci#define ICC_AP1R2 __ICC_AP1Rx(2) 398c2ecf20Sopenharmony_ci#define ICC_AP1R3 __ICC_AP1Rx(3) 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci#define CPUIF_MAP(a32, a64) \ 428c2ecf20Sopenharmony_cistatic inline void write_ ## a64(u32 val) \ 438c2ecf20Sopenharmony_ci{ \ 448c2ecf20Sopenharmony_ci write_sysreg(val, a32); \ 458c2ecf20Sopenharmony_ci} \ 468c2ecf20Sopenharmony_cistatic inline u32 read_ ## a64(void) \ 478c2ecf20Sopenharmony_ci{ \ 488c2ecf20Sopenharmony_ci return read_sysreg(a32); \ 498c2ecf20Sopenharmony_ci} \ 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ciCPUIF_MAP(ICC_PMR, ICC_PMR_EL1) 528c2ecf20Sopenharmony_ciCPUIF_MAP(ICC_AP0R0, ICC_AP0R0_EL1) 538c2ecf20Sopenharmony_ciCPUIF_MAP(ICC_AP0R1, ICC_AP0R1_EL1) 548c2ecf20Sopenharmony_ciCPUIF_MAP(ICC_AP0R2, ICC_AP0R2_EL1) 558c2ecf20Sopenharmony_ciCPUIF_MAP(ICC_AP0R3, ICC_AP0R3_EL1) 568c2ecf20Sopenharmony_ciCPUIF_MAP(ICC_AP1R0, ICC_AP1R0_EL1) 578c2ecf20Sopenharmony_ciCPUIF_MAP(ICC_AP1R1, ICC_AP1R1_EL1) 588c2ecf20Sopenharmony_ciCPUIF_MAP(ICC_AP1R2, ICC_AP1R2_EL1) 598c2ecf20Sopenharmony_ciCPUIF_MAP(ICC_AP1R3, ICC_AP1R3_EL1) 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci#define read_gicreg(r) read_##r() 628c2ecf20Sopenharmony_ci#define write_gicreg(v, r) write_##r(v) 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci/* Low-level accessors */ 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_cistatic inline void gic_write_eoir(u32 irq) 678c2ecf20Sopenharmony_ci{ 688c2ecf20Sopenharmony_ci write_sysreg(irq, ICC_EOIR1); 698c2ecf20Sopenharmony_ci isb(); 708c2ecf20Sopenharmony_ci} 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_cistatic inline void gic_write_dir(u32 val) 738c2ecf20Sopenharmony_ci{ 748c2ecf20Sopenharmony_ci write_sysreg(val, ICC_DIR); 758c2ecf20Sopenharmony_ci isb(); 768c2ecf20Sopenharmony_ci} 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_cistatic inline u32 gic_read_iar(void) 798c2ecf20Sopenharmony_ci{ 808c2ecf20Sopenharmony_ci u32 irqstat = read_sysreg(ICC_IAR1); 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci dsb(sy); 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci return irqstat; 858c2ecf20Sopenharmony_ci} 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_cistatic inline void gic_write_ctlr(u32 val) 888c2ecf20Sopenharmony_ci{ 898c2ecf20Sopenharmony_ci write_sysreg(val, ICC_CTLR); 908c2ecf20Sopenharmony_ci isb(); 918c2ecf20Sopenharmony_ci} 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_cistatic inline u32 gic_read_ctlr(void) 948c2ecf20Sopenharmony_ci{ 958c2ecf20Sopenharmony_ci return read_sysreg(ICC_CTLR); 968c2ecf20Sopenharmony_ci} 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_cistatic inline void gic_write_grpen1(u32 val) 998c2ecf20Sopenharmony_ci{ 1008c2ecf20Sopenharmony_ci write_sysreg(val, ICC_IGRPEN1); 1018c2ecf20Sopenharmony_ci isb(); 1028c2ecf20Sopenharmony_ci} 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_cistatic inline void gic_write_sgi1r(u64 val) 1058c2ecf20Sopenharmony_ci{ 1068c2ecf20Sopenharmony_ci write_sysreg(val, ICC_SGI1R); 1078c2ecf20Sopenharmony_ci} 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_cistatic inline u32 gic_read_sre(void) 1108c2ecf20Sopenharmony_ci{ 1118c2ecf20Sopenharmony_ci return read_sysreg(ICC_SRE); 1128c2ecf20Sopenharmony_ci} 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_cistatic inline void gic_write_sre(u32 val) 1158c2ecf20Sopenharmony_ci{ 1168c2ecf20Sopenharmony_ci write_sysreg(val, ICC_SRE); 1178c2ecf20Sopenharmony_ci isb(); 1188c2ecf20Sopenharmony_ci} 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_cistatic inline void gic_write_bpr1(u32 val) 1218c2ecf20Sopenharmony_ci{ 1228c2ecf20Sopenharmony_ci write_sysreg(val, ICC_BPR1); 1238c2ecf20Sopenharmony_ci} 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_cistatic inline u32 gic_read_pmr(void) 1268c2ecf20Sopenharmony_ci{ 1278c2ecf20Sopenharmony_ci return read_sysreg(ICC_PMR); 1288c2ecf20Sopenharmony_ci} 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_cistatic inline void gic_write_pmr(u32 val) 1318c2ecf20Sopenharmony_ci{ 1328c2ecf20Sopenharmony_ci write_sysreg(val, ICC_PMR); 1338c2ecf20Sopenharmony_ci} 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_cistatic inline u32 gic_read_rpr(void) 1368c2ecf20Sopenharmony_ci{ 1378c2ecf20Sopenharmony_ci return read_sysreg(ICC_RPR); 1388c2ecf20Sopenharmony_ci} 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci/* 1418c2ecf20Sopenharmony_ci * Even in 32bit systems that use LPAE, there is no guarantee that the I/O 1428c2ecf20Sopenharmony_ci * interface provides true 64bit atomic accesses, so using strd/ldrd doesn't 1438c2ecf20Sopenharmony_ci * make much sense. 1448c2ecf20Sopenharmony_ci * Moreover, 64bit I/O emulation is extremely difficult to implement on 1458c2ecf20Sopenharmony_ci * AArch32, since the syndrome register doesn't provide any information for 1468c2ecf20Sopenharmony_ci * them. 1478c2ecf20Sopenharmony_ci * Consequently, the following IO helpers use 32bit accesses. 1488c2ecf20Sopenharmony_ci */ 1498c2ecf20Sopenharmony_cistatic inline void __gic_writeq_nonatomic(u64 val, volatile void __iomem *addr) 1508c2ecf20Sopenharmony_ci{ 1518c2ecf20Sopenharmony_ci writel_relaxed((u32)val, addr); 1528c2ecf20Sopenharmony_ci writel_relaxed((u32)(val >> 32), addr + 4); 1538c2ecf20Sopenharmony_ci} 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_cistatic inline u64 __gic_readq_nonatomic(const volatile void __iomem *addr) 1568c2ecf20Sopenharmony_ci{ 1578c2ecf20Sopenharmony_ci u64 val; 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci val = readl_relaxed(addr); 1608c2ecf20Sopenharmony_ci val |= (u64)readl_relaxed(addr + 4) << 32; 1618c2ecf20Sopenharmony_ci return val; 1628c2ecf20Sopenharmony_ci} 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci#define gic_flush_dcache_to_poc(a,l) __cpuc_flush_dcache_area((a), (l)) 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci/* 1678c2ecf20Sopenharmony_ci * GICD_IROUTERn, contain the affinity values associated to each interrupt. 1688c2ecf20Sopenharmony_ci * The upper-word (aff3) will always be 0, so there is no need for a lock. 1698c2ecf20Sopenharmony_ci */ 1708c2ecf20Sopenharmony_ci#define gic_write_irouter(v, c) __gic_writeq_nonatomic(v, c) 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci/* 1738c2ecf20Sopenharmony_ci * GICR_TYPER is an ID register and doesn't need atomicity. 1748c2ecf20Sopenharmony_ci */ 1758c2ecf20Sopenharmony_ci#define gic_read_typer(c) __gic_readq_nonatomic(c) 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci/* 1788c2ecf20Sopenharmony_ci * GITS_BASER - hi and lo bits may be accessed independently. 1798c2ecf20Sopenharmony_ci */ 1808c2ecf20Sopenharmony_ci#define gits_read_baser(c) __gic_readq_nonatomic(c) 1818c2ecf20Sopenharmony_ci#define gits_write_baser(v, c) __gic_writeq_nonatomic(v, c) 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci/* 1848c2ecf20Sopenharmony_ci * GICR_PENDBASER and GICR_PROPBASE are changed with LPIs disabled, so they 1858c2ecf20Sopenharmony_ci * won't be being used during any updates and can be changed non-atomically 1868c2ecf20Sopenharmony_ci */ 1878c2ecf20Sopenharmony_ci#define gicr_read_propbaser(c) __gic_readq_nonatomic(c) 1888c2ecf20Sopenharmony_ci#define gicr_write_propbaser(v, c) __gic_writeq_nonatomic(v, c) 1898c2ecf20Sopenharmony_ci#define gicr_read_pendbaser(c) __gic_readq_nonatomic(c) 1908c2ecf20Sopenharmony_ci#define gicr_write_pendbaser(v, c) __gic_writeq_nonatomic(v, c) 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci/* 1938c2ecf20Sopenharmony_ci * GICR_xLPIR - only the lower bits are significant 1948c2ecf20Sopenharmony_ci */ 1958c2ecf20Sopenharmony_ci#define gic_read_lpir(c) readl_relaxed(c) 1968c2ecf20Sopenharmony_ci#define gic_write_lpir(v, c) writel_relaxed(lower_32_bits(v), c) 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci/* 1998c2ecf20Sopenharmony_ci * GITS_TYPER is an ID register and doesn't need atomicity. 2008c2ecf20Sopenharmony_ci */ 2018c2ecf20Sopenharmony_ci#define gits_read_typer(c) __gic_readq_nonatomic(c) 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci/* 2048c2ecf20Sopenharmony_ci * GITS_CBASER - hi and lo bits may be accessed independently. 2058c2ecf20Sopenharmony_ci */ 2068c2ecf20Sopenharmony_ci#define gits_read_cbaser(c) __gic_readq_nonatomic(c) 2078c2ecf20Sopenharmony_ci#define gits_write_cbaser(v, c) __gic_writeq_nonatomic(v, c) 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci/* 2108c2ecf20Sopenharmony_ci * GITS_CWRITER - hi and lo bits may be accessed independently. 2118c2ecf20Sopenharmony_ci */ 2128c2ecf20Sopenharmony_ci#define gits_write_cwriter(v, c) __gic_writeq_nonatomic(v, c) 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci/* 2158c2ecf20Sopenharmony_ci * GICR_VPROPBASER - hi and lo bits may be accessed independently. 2168c2ecf20Sopenharmony_ci */ 2178c2ecf20Sopenharmony_ci#define gicr_read_vpropbaser(c) __gic_readq_nonatomic(c) 2188c2ecf20Sopenharmony_ci#define gicr_write_vpropbaser(v, c) __gic_writeq_nonatomic(v, c) 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci/* 2218c2ecf20Sopenharmony_ci * GICR_VPENDBASER - the Valid bit must be cleared before changing 2228c2ecf20Sopenharmony_ci * anything else. 2238c2ecf20Sopenharmony_ci */ 2248c2ecf20Sopenharmony_cistatic inline void gicr_write_vpendbaser(u64 val, void __iomem *addr) 2258c2ecf20Sopenharmony_ci{ 2268c2ecf20Sopenharmony_ci u32 tmp; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci tmp = readl_relaxed(addr + 4); 2298c2ecf20Sopenharmony_ci if (tmp & (GICR_VPENDBASER_Valid >> 32)) { 2308c2ecf20Sopenharmony_ci tmp &= ~(GICR_VPENDBASER_Valid >> 32); 2318c2ecf20Sopenharmony_ci writel_relaxed(tmp, addr + 4); 2328c2ecf20Sopenharmony_ci } 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci /* 2358c2ecf20Sopenharmony_ci * Use the fact that __gic_writeq_nonatomic writes the second 2368c2ecf20Sopenharmony_ci * half of the 64bit quantity after the first. 2378c2ecf20Sopenharmony_ci */ 2388c2ecf20Sopenharmony_ci __gic_writeq_nonatomic(val, addr); 2398c2ecf20Sopenharmony_ci} 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci#define gicr_read_vpendbaser(c) __gic_readq_nonatomic(c) 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_cistatic inline bool gic_prio_masking_enabled(void) 2448c2ecf20Sopenharmony_ci{ 2458c2ecf20Sopenharmony_ci return false; 2468c2ecf20Sopenharmony_ci} 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_cistatic inline void gic_pmr_mask_irqs(void) 2498c2ecf20Sopenharmony_ci{ 2508c2ecf20Sopenharmony_ci /* Should not get called. */ 2518c2ecf20Sopenharmony_ci WARN_ON_ONCE(true); 2528c2ecf20Sopenharmony_ci} 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_cistatic inline void gic_arch_enable_irqs(void) 2558c2ecf20Sopenharmony_ci{ 2568c2ecf20Sopenharmony_ci /* Should not get called. */ 2578c2ecf20Sopenharmony_ci WARN_ON_ONCE(true); 2588c2ecf20Sopenharmony_ci} 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci#endif /* !__ASSEMBLY__ */ 2618c2ecf20Sopenharmony_ci#endif /* !__ASM_ARCH_GICV3_H */ 262