1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2017 - 2020, Broadcom 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <common/debug.h> 8*91f16700Schasinglulu #include <lib/mmio.h> 9*91f16700Schasinglulu 10*91f16700Schasinglulu #include <iommu.h> 11*91f16700Schasinglulu #include <platform_def.h> 12*91f16700Schasinglulu #include <sr_utils.h> 13*91f16700Schasinglulu 14*91f16700Schasinglulu #define PAXC_BASE 0x60400000 15*91f16700Schasinglulu #define PAXC_AXI_CFG_PF 0x10 16*91f16700Schasinglulu #define PAXC_AXI_CFG_PF_OFFSET(pf) (PAXC_AXI_CFG_PF + (pf) * 4) 17*91f16700Schasinglulu #define PAXC_ARPROT_PF_CFG 0x40 18*91f16700Schasinglulu #define PAXC_AWPROT_PF_CFG 0x44 19*91f16700Schasinglulu 20*91f16700Schasinglulu #define PAXC_ARQOS_PF_CFG 0x48 21*91f16700Schasinglulu #define PAXC_ARQOS_VAL 0xaaaaaaaa 22*91f16700Schasinglulu 23*91f16700Schasinglulu #define PAXC_AWQOS_PF_CFG 0x4c 24*91f16700Schasinglulu #define PAXC_AWQOS_VAL 0xeeeeeeee 25*91f16700Schasinglulu 26*91f16700Schasinglulu #define PAXC_CFG_IND_ADDR_OFFSET 0x1f0 27*91f16700Schasinglulu #define PAXC_CFG_IND_ADDR_MASK 0xffc 28*91f16700Schasinglulu #define PAXC_CFG_IND_DATA_OFFSET 0x1f4 29*91f16700Schasinglulu 30*91f16700Schasinglulu /* offsets for PAXC root complex configuration space registers */ 31*91f16700Schasinglulu 32*91f16700Schasinglulu #define PAXC_CFG_ID_OFFSET 0x434 33*91f16700Schasinglulu #define PAXC_RC_VENDOR_ID 0x14e4 34*91f16700Schasinglulu #define PAXC_RC_VENDOR_ID_SHIFT 16 35*91f16700Schasinglulu 36*91f16700Schasinglulu #define PAXC_RC_DEVICE_ID 0xd750 37*91f16700Schasinglulu 38*91f16700Schasinglulu #define PAXC_CFG_LINK_CAP_OFFSET 0x4dc 39*91f16700Schasinglulu #define PAXC_RC_LINK_CAP_SPD_SHIFT 0 40*91f16700Schasinglulu #define PAXC_RC_LINK_CAP_SPD_MASK (0xf << PAXC_RC_LINK_CAP_SPD_SHIFT) 41*91f16700Schasinglulu #define PAXC_RC_LINK_CAP_SPD 3 42*91f16700Schasinglulu #define PAXC_RC_LINK_CAP_WIDTH_SHIFT 4 43*91f16700Schasinglulu #define PAXC_RC_LINK_CAP_WIDTH_MASK (0x1f << PAXC_RC_LINK_CAP_WIDTH_SHIFT) 44*91f16700Schasinglulu #define PAXC_RC_LINK_CAP_WIDTH 16 45*91f16700Schasinglulu 46*91f16700Schasinglulu /* offsets for MHB registers */ 47*91f16700Schasinglulu 48*91f16700Schasinglulu #define MHB_BASE 0x60401000 49*91f16700Schasinglulu #define MHB_MEM_PWR_STATUS_PAXC (MHB_BASE + 0x1c0) 50*91f16700Schasinglulu #define MHB_PWR_ARR_POWERON 0x8 51*91f16700Schasinglulu #define MHB_PWR_ARR_POWEROK 0x4 52*91f16700Schasinglulu #define MHB_PWR_POWERON 0x2 53*91f16700Schasinglulu #define MHB_PWR_POWEROK 0x1 54*91f16700Schasinglulu #define MHB_PWR_STATUS_MASK (MHB_PWR_ARR_POWERON | \ 55*91f16700Schasinglulu MHB_PWR_ARR_POWEROK | \ 56*91f16700Schasinglulu MHB_PWR_POWERON | \ 57*91f16700Schasinglulu MHB_PWR_POWEROK) 58*91f16700Schasinglulu 59*91f16700Schasinglulu /* max number of PFs from Nitro that PAXC sees */ 60*91f16700Schasinglulu #define MAX_NR_NITRO_PF 8 61*91f16700Schasinglulu 62*91f16700Schasinglulu #ifdef EMULATION_SETUP 63*91f16700Schasinglulu static void paxc_reg_dump(void) 64*91f16700Schasinglulu { 65*91f16700Schasinglulu } 66*91f16700Schasinglulu #else 67*91f16700Schasinglulu /* total number of PAXC registers */ 68*91f16700Schasinglulu #define NR_PAXC_REGS 53 69*91f16700Schasinglulu static void paxc_reg_dump(void) 70*91f16700Schasinglulu { 71*91f16700Schasinglulu uint32_t idx, offset = 0; 72*91f16700Schasinglulu 73*91f16700Schasinglulu VERBOSE("PAXC register dump start\n"); 74*91f16700Schasinglulu for (idx = 0; idx < NR_PAXC_REGS; idx++, offset += 4) 75*91f16700Schasinglulu VERBOSE("offset: 0x%x val: 0x%x\n", offset, 76*91f16700Schasinglulu mmio_read_32(PAXC_BASE + offset)); 77*91f16700Schasinglulu VERBOSE("PAXC register dump end\n"); 78*91f16700Schasinglulu } 79*91f16700Schasinglulu #endif /* EMULATION_SETUP */ 80*91f16700Schasinglulu 81*91f16700Schasinglulu #ifdef EMULATION_SETUP 82*91f16700Schasinglulu static void mhb_reg_dump(void) 83*91f16700Schasinglulu { 84*91f16700Schasinglulu } 85*91f16700Schasinglulu #else 86*91f16700Schasinglulu #define NR_MHB_REGS 227 87*91f16700Schasinglulu static void mhb_reg_dump(void) 88*91f16700Schasinglulu { 89*91f16700Schasinglulu uint32_t idx, offset = 0; 90*91f16700Schasinglulu 91*91f16700Schasinglulu VERBOSE("MHB register dump start\n"); 92*91f16700Schasinglulu for (idx = 0; idx < NR_MHB_REGS; idx++, offset += 4) 93*91f16700Schasinglulu VERBOSE("offset: 0x%x val: 0x%x\n", offset, 94*91f16700Schasinglulu mmio_read_32(MHB_BASE + offset)); 95*91f16700Schasinglulu VERBOSE("MHB register dump end\n"); 96*91f16700Schasinglulu } 97*91f16700Schasinglulu #endif /* EMULATION_SETUP */ 98*91f16700Schasinglulu 99*91f16700Schasinglulu static void paxc_rc_cfg_write(uint32_t where, uint32_t val) 100*91f16700Schasinglulu { 101*91f16700Schasinglulu mmio_write_32(PAXC_BASE + PAXC_CFG_IND_ADDR_OFFSET, 102*91f16700Schasinglulu where & PAXC_CFG_IND_ADDR_MASK); 103*91f16700Schasinglulu mmio_write_32(PAXC_BASE + PAXC_CFG_IND_DATA_OFFSET, val); 104*91f16700Schasinglulu } 105*91f16700Schasinglulu 106*91f16700Schasinglulu static uint32_t paxc_rc_cfg_read(uint32_t where) 107*91f16700Schasinglulu { 108*91f16700Schasinglulu mmio_write_32(PAXC_BASE + PAXC_CFG_IND_ADDR_OFFSET, 109*91f16700Schasinglulu where & PAXC_CFG_IND_ADDR_MASK); 110*91f16700Schasinglulu return mmio_read_32(PAXC_BASE + PAXC_CFG_IND_DATA_OFFSET); 111*91f16700Schasinglulu } 112*91f16700Schasinglulu 113*91f16700Schasinglulu /* 114*91f16700Schasinglulu * Function to program PAXC root complex link capability register 115*91f16700Schasinglulu */ 116*91f16700Schasinglulu static void paxc_cfg_link_cap(void) 117*91f16700Schasinglulu { 118*91f16700Schasinglulu uint32_t val; 119*91f16700Schasinglulu 120*91f16700Schasinglulu val = paxc_rc_cfg_read(PAXC_CFG_LINK_CAP_OFFSET); 121*91f16700Schasinglulu val &= ~(PAXC_RC_LINK_CAP_SPD_MASK | PAXC_RC_LINK_CAP_WIDTH_MASK); 122*91f16700Schasinglulu val |= (PAXC_RC_LINK_CAP_SPD << PAXC_RC_LINK_CAP_SPD_SHIFT) | 123*91f16700Schasinglulu (PAXC_RC_LINK_CAP_WIDTH << PAXC_RC_LINK_CAP_WIDTH_SHIFT); 124*91f16700Schasinglulu paxc_rc_cfg_write(PAXC_CFG_LINK_CAP_OFFSET, val); 125*91f16700Schasinglulu } 126*91f16700Schasinglulu 127*91f16700Schasinglulu /* 128*91f16700Schasinglulu * Function to program PAXC root complex vendor ID and device ID 129*91f16700Schasinglulu */ 130*91f16700Schasinglulu static void paxc_cfg_id(void) 131*91f16700Schasinglulu { 132*91f16700Schasinglulu uint32_t val; 133*91f16700Schasinglulu 134*91f16700Schasinglulu val = (PAXC_RC_VENDOR_ID << PAXC_RC_VENDOR_ID_SHIFT) | 135*91f16700Schasinglulu PAXC_RC_DEVICE_ID; 136*91f16700Schasinglulu paxc_rc_cfg_write(PAXC_CFG_ID_OFFSET, val); 137*91f16700Schasinglulu } 138*91f16700Schasinglulu 139*91f16700Schasinglulu void paxc_init(void) 140*91f16700Schasinglulu { 141*91f16700Schasinglulu unsigned int pf_index; 142*91f16700Schasinglulu unsigned int val; 143*91f16700Schasinglulu 144*91f16700Schasinglulu val = mmio_read_32(MHB_MEM_PWR_STATUS_PAXC); 145*91f16700Schasinglulu if ((val & MHB_PWR_STATUS_MASK) != MHB_PWR_STATUS_MASK) { 146*91f16700Schasinglulu INFO("PAXC not powered\n"); 147*91f16700Schasinglulu return; 148*91f16700Schasinglulu } 149*91f16700Schasinglulu 150*91f16700Schasinglulu paxc_cfg_id(); 151*91f16700Schasinglulu paxc_cfg_link_cap(); 152*91f16700Schasinglulu 153*91f16700Schasinglulu paxc_reg_dump(); 154*91f16700Schasinglulu mhb_reg_dump(); 155*91f16700Schasinglulu 156*91f16700Schasinglulu #ifdef USE_DDR 157*91f16700Schasinglulu /* 158*91f16700Schasinglulu * Set AWCACHE and ARCACHE to 0xff (Cacheable write-back, 159*91f16700Schasinglulu * allocate on both reads and writes) per 160*91f16700Schasinglulu * recommendation from the ASIC team 161*91f16700Schasinglulu */ 162*91f16700Schasinglulu val = 0xff; 163*91f16700Schasinglulu #else 164*91f16700Schasinglulu /* disable IO cache if non-DDR memory is used, e.g., external SRAM */ 165*91f16700Schasinglulu val = 0x0; 166*91f16700Schasinglulu #endif 167*91f16700Schasinglulu for (pf_index = 0; pf_index < MAX_NR_NITRO_PF; pf_index++) 168*91f16700Schasinglulu mmio_write_32(PAXC_BASE + PAXC_AXI_CFG_PF_OFFSET(pf_index), 169*91f16700Schasinglulu val); 170*91f16700Schasinglulu 171*91f16700Schasinglulu /* 172*91f16700Schasinglulu * Set ARPROT and AWPROT to enable non-secure access from 173*91f16700Schasinglulu * PAXC to all PFs, PF0 to PF7 174*91f16700Schasinglulu */ 175*91f16700Schasinglulu mmio_write_32(PAXC_BASE + PAXC_ARPROT_PF_CFG, 0x22222222); 176*91f16700Schasinglulu mmio_write_32(PAXC_BASE + PAXC_AWPROT_PF_CFG, 0x22222222); 177*91f16700Schasinglulu 178*91f16700Schasinglulu mmio_write_32(PAXC_BASE + PAXC_ARQOS_PF_CFG, PAXC_ARQOS_VAL); 179*91f16700Schasinglulu mmio_write_32(PAXC_BASE + PAXC_AWQOS_PF_CFG, PAXC_AWQOS_VAL); 180*91f16700Schasinglulu 181*91f16700Schasinglulu INFO("PAXC init done\n"); 182*91f16700Schasinglulu } 183*91f16700Schasinglulu 184*91f16700Schasinglulu /* 185*91f16700Schasinglulu * These defines do not match the regfile but they are renamed in a way such 186*91f16700Schasinglulu * that they are much more readible 187*91f16700Schasinglulu */ 188*91f16700Schasinglulu 189*91f16700Schasinglulu #define MHB_NIC_SECURITY_BASE 0x60500000 190*91f16700Schasinglulu #define MHB_NIC_PAXC_AXI_NS 0x0008 191*91f16700Schasinglulu #define MHB_NIC_IDM_NS 0x000c 192*91f16700Schasinglulu #define MHB_NIC_MHB_APB_NS 0x0010 193*91f16700Schasinglulu #define MHB_NIC_NITRO_AXI_NS 0x0014 194*91f16700Schasinglulu #define MHB_NIC_PCIE_AXI_NS 0x0018 195*91f16700Schasinglulu #define MHB_NIC_PAXC_APB_NS 0x001c 196*91f16700Schasinglulu #define MHB_NIC_EP_APB_NS 0x0020 197*91f16700Schasinglulu 198*91f16700Schasinglulu #define MHB_NIC_PAXC_APB_S_IDM_SHIFT 5 199*91f16700Schasinglulu #define MHB_NIC_EP_APB_S_IDM_SHIFT 4 200*91f16700Schasinglulu #define MHB_NIC_MHB_APB_S_IDM_SHIFT 3 201*91f16700Schasinglulu #define MHB_NIC_PAXC_AXI_S_IDM_SHIFT 2 202*91f16700Schasinglulu #define MHB_NIC_PCIE_AXI_S_IDM_SHIFT 1 203*91f16700Schasinglulu #define MHB_NIC_NITRO_AXI_S_IDM_SHIFT 0 204*91f16700Schasinglulu 205*91f16700Schasinglulu #define NIC400_NITRO_TOP_NIC_SECURITY_BASE 0x60d00000 206*91f16700Schasinglulu 207*91f16700Schasinglulu #define NITRO_NIC_SECURITY_3_SHIFT 0x14 208*91f16700Schasinglulu #define NITRO_NIC_SECURITY_4_SHIFT 0x18 209*91f16700Schasinglulu #define NITRO_NIC_SECURITY_5_SHIFT 0x1c 210*91f16700Schasinglulu #define NITRO_NIC_SECURITY_6_SHIFT 0x20 211*91f16700Schasinglulu 212*91f16700Schasinglulu void paxc_mhb_ns_init(void) 213*91f16700Schasinglulu { 214*91f16700Schasinglulu unsigned int val; 215*91f16700Schasinglulu uintptr_t mhb_nic_gpv = MHB_NIC_SECURITY_BASE; 216*91f16700Schasinglulu #ifndef NITRO_SECURE_ACCESS 217*91f16700Schasinglulu uintptr_t nic400_nitro_gpv = NIC400_NITRO_TOP_NIC_SECURITY_BASE; 218*91f16700Schasinglulu #endif /* NITRO_SECURE_ACCESS */ 219*91f16700Schasinglulu 220*91f16700Schasinglulu /* set PAXC AXI to allow non-secure access */ 221*91f16700Schasinglulu val = mmio_read_32(mhb_nic_gpv + MHB_NIC_PAXC_AXI_NS); 222*91f16700Schasinglulu val |= 0x1; 223*91f16700Schasinglulu mmio_write_32(mhb_nic_gpv + MHB_NIC_PAXC_AXI_NS, val); 224*91f16700Schasinglulu 225*91f16700Schasinglulu /* set various MHB IDM interfaces to allow non-secure access */ 226*91f16700Schasinglulu val = mmio_read_32(mhb_nic_gpv + MHB_NIC_IDM_NS); 227*91f16700Schasinglulu val |= (0x1 << MHB_NIC_PAXC_APB_S_IDM_SHIFT); 228*91f16700Schasinglulu val |= (0x1 << MHB_NIC_EP_APB_S_IDM_SHIFT); 229*91f16700Schasinglulu val |= (0x1 << MHB_NIC_MHB_APB_S_IDM_SHIFT); 230*91f16700Schasinglulu val |= (0x1 << MHB_NIC_PAXC_AXI_S_IDM_SHIFT); 231*91f16700Schasinglulu val |= (0x1 << MHB_NIC_PCIE_AXI_S_IDM_SHIFT); 232*91f16700Schasinglulu val |= (0x1 << MHB_NIC_NITRO_AXI_S_IDM_SHIFT); 233*91f16700Schasinglulu mmio_write_32(mhb_nic_gpv + MHB_NIC_IDM_NS, val); 234*91f16700Schasinglulu 235*91f16700Schasinglulu /* set MHB APB to allow non-secure access */ 236*91f16700Schasinglulu val = mmio_read_32(mhb_nic_gpv + MHB_NIC_MHB_APB_NS); 237*91f16700Schasinglulu val |= 0x1; 238*91f16700Schasinglulu mmio_write_32(mhb_nic_gpv + MHB_NIC_MHB_APB_NS, val); 239*91f16700Schasinglulu 240*91f16700Schasinglulu /* set Nitro AXI to allow non-secure access */ 241*91f16700Schasinglulu val = mmio_read_32(mhb_nic_gpv + MHB_NIC_NITRO_AXI_NS); 242*91f16700Schasinglulu val |= 0x1; 243*91f16700Schasinglulu mmio_write_32(mhb_nic_gpv + MHB_NIC_NITRO_AXI_NS, val); 244*91f16700Schasinglulu 245*91f16700Schasinglulu /* set PCIe AXI to allow non-secure access */ 246*91f16700Schasinglulu val = mmio_read_32(mhb_nic_gpv + MHB_NIC_PCIE_AXI_NS); 247*91f16700Schasinglulu val |= 0x1; 248*91f16700Schasinglulu mmio_write_32(mhb_nic_gpv + MHB_NIC_PCIE_AXI_NS, val); 249*91f16700Schasinglulu 250*91f16700Schasinglulu /* set PAXC APB to allow non-secure access */ 251*91f16700Schasinglulu val = mmio_read_32(mhb_nic_gpv + MHB_NIC_PAXC_APB_NS); 252*91f16700Schasinglulu val |= 0x1; 253*91f16700Schasinglulu mmio_write_32(mhb_nic_gpv + MHB_NIC_PAXC_APB_NS, val); 254*91f16700Schasinglulu 255*91f16700Schasinglulu /* set EP APB to allow non-secure access */ 256*91f16700Schasinglulu val = mmio_read_32(mhb_nic_gpv + MHB_NIC_EP_APB_NS); 257*91f16700Schasinglulu val |= 0x1; 258*91f16700Schasinglulu mmio_write_32(mhb_nic_gpv + MHB_NIC_EP_APB_NS, val); 259*91f16700Schasinglulu 260*91f16700Schasinglulu #ifndef NITRO_SECURE_ACCESS 261*91f16700Schasinglulu /* Set NIC400 to allow non-secure access */ 262*91f16700Schasinglulu mmio_setbits_32(nic400_nitro_gpv + NITRO_NIC_SECURITY_3_SHIFT, 0x1); 263*91f16700Schasinglulu mmio_setbits_32(nic400_nitro_gpv + NITRO_NIC_SECURITY_4_SHIFT, 0x1); 264*91f16700Schasinglulu mmio_setbits_32(nic400_nitro_gpv + NITRO_NIC_SECURITY_5_SHIFT, 0x1); 265*91f16700Schasinglulu mmio_setbits_32(nic400_nitro_gpv + NITRO_NIC_SECURITY_6_SHIFT, 0x1); 266*91f16700Schasinglulu #endif /* NITRO_SECURE_ACCESS */ 267*91f16700Schasinglulu } 268