1*031542fcSKonstantin Porotchkin /* 2*031542fcSKonstantin Porotchkin * Copyright (C) 2018 Marvell International Ltd. 3*031542fcSKonstantin Porotchkin * 4*031542fcSKonstantin Porotchkin * SPDX-License-Identifier: BSD-3-Clause 5*031542fcSKonstantin Porotchkin * https://spdx.org/licenses 6*031542fcSKonstantin Porotchkin */ 7*031542fcSKonstantin Porotchkin 8*031542fcSKonstantin Porotchkin /* AP806 Marvell SoC driver */ 9*031542fcSKonstantin Porotchkin 10*031542fcSKonstantin Porotchkin #include <ap_setup.h> 11*031542fcSKonstantin Porotchkin #include <ccu.h> 12*031542fcSKonstantin Porotchkin #include <cache_llc.h> 13*031542fcSKonstantin Porotchkin #include <debug.h> 14*031542fcSKonstantin Porotchkin #include <io_win.h> 15*031542fcSKonstantin Porotchkin #include <mci.h> 16*031542fcSKonstantin Porotchkin #include <mmio.h> 17*031542fcSKonstantin Porotchkin #include <mvebu_def.h> 18*031542fcSKonstantin Porotchkin 19*031542fcSKonstantin Porotchkin #define SMMU_sACR (MVEBU_SMMU_BASE + 0x10) 20*031542fcSKonstantin Porotchkin #define SMMU_sACR_PG_64K (1 << 16) 21*031542fcSKonstantin Porotchkin 22*031542fcSKonstantin Porotchkin #define CCU_GSPMU_CR (MVEBU_CCU_BASE(MVEBU_AP0) + \ 23*031542fcSKonstantin Porotchkin 0x3F0) 24*031542fcSKonstantin Porotchkin #define GSPMU_CPU_CONTROL (0x1 << 0) 25*031542fcSKonstantin Porotchkin 26*031542fcSKonstantin Porotchkin #define CCU_HTC_CR (MVEBU_CCU_BASE(MVEBU_AP0) + \ 27*031542fcSKonstantin Porotchkin 0x200) 28*031542fcSKonstantin Porotchkin #define CCU_SET_POC_OFFSET 5 29*031542fcSKonstantin Porotchkin 30*031542fcSKonstantin Porotchkin #define CCU_RGF(win) (MVEBU_CCU_BASE(MVEBU_AP0) + \ 31*031542fcSKonstantin Porotchkin 0x90 + 4 * (win)) 32*031542fcSKonstantin Porotchkin 33*031542fcSKonstantin Porotchkin #define DSS_CR0 (MVEBU_RFU_BASE + 0x100) 34*031542fcSKonstantin Porotchkin #define DVM_48BIT_VA_ENABLE (1 << 21) 35*031542fcSKonstantin Porotchkin 36*031542fcSKonstantin Porotchkin /* Secure MoChi incoming access */ 37*031542fcSKonstantin Porotchkin #define SEC_MOCHI_IN_ACC_REG (MVEBU_RFU_BASE + 0x4738) 38*031542fcSKonstantin Porotchkin #define SEC_MOCHI_IN_ACC_IHB0_EN (1) 39*031542fcSKonstantin Porotchkin #define SEC_MOCHI_IN_ACC_IHB1_EN (1 << 3) 40*031542fcSKonstantin Porotchkin #define SEC_MOCHI_IN_ACC_IHB2_EN (1 << 6) 41*031542fcSKonstantin Porotchkin #define SEC_MOCHI_IN_ACC_PIDI_EN (1 << 9) 42*031542fcSKonstantin Porotchkin #define SEC_IN_ACCESS_ENA_ALL_MASTERS (SEC_MOCHI_IN_ACC_IHB0_EN | \ 43*031542fcSKonstantin Porotchkin SEC_MOCHI_IN_ACC_IHB1_EN | \ 44*031542fcSKonstantin Porotchkin SEC_MOCHI_IN_ACC_IHB2_EN | \ 45*031542fcSKonstantin Porotchkin SEC_MOCHI_IN_ACC_PIDI_EN) 46*031542fcSKonstantin Porotchkin 47*031542fcSKonstantin Porotchkin /* SYSRST_OUTn Config definitions */ 48*031542fcSKonstantin Porotchkin #define MVEBU_SYSRST_OUT_CONFIG_REG (MVEBU_MISC_SOC_BASE + 0x4) 49*031542fcSKonstantin Porotchkin #define WD_MASK_SYS_RST_OUT (1 << 2) 50*031542fcSKonstantin Porotchkin 51*031542fcSKonstantin Porotchkin /* Generic Timer System Controller */ 52*031542fcSKonstantin Porotchkin #define MVEBU_MSS_GTCR_REG (MVEBU_REGS_BASE + 0x581000) 53*031542fcSKonstantin Porotchkin #define MVEBU_MSS_GTCR_ENABLE_BIT 0x1 54*031542fcSKonstantin Porotchkin 55*031542fcSKonstantin Porotchkin /* 56*031542fcSKonstantin Porotchkin * AXI Configuration. 57*031542fcSKonstantin Porotchkin */ 58*031542fcSKonstantin Porotchkin 59*031542fcSKonstantin Porotchkin /* Used for Units of AP-806 (e.g. SDIO and etc) */ 60*031542fcSKonstantin Porotchkin #define MVEBU_AXI_ATTR_BASE (MVEBU_REGS_BASE + 0x6F4580) 61*031542fcSKonstantin Porotchkin #define MVEBU_AXI_ATTR_REG(index) (MVEBU_AXI_ATTR_BASE + \ 62*031542fcSKonstantin Porotchkin 0x4 * index) 63*031542fcSKonstantin Porotchkin 64*031542fcSKonstantin Porotchkin enum axi_attr { 65*031542fcSKonstantin Porotchkin AXI_SDIO_ATTR = 0, 66*031542fcSKonstantin Porotchkin AXI_DFX_ATTR, 67*031542fcSKonstantin Porotchkin AXI_MAX_ATTR, 68*031542fcSKonstantin Porotchkin }; 69*031542fcSKonstantin Porotchkin 70*031542fcSKonstantin Porotchkin static void apn_sec_masters_access_en(uint32_t enable) 71*031542fcSKonstantin Porotchkin { 72*031542fcSKonstantin Porotchkin uint32_t reg; 73*031542fcSKonstantin Porotchkin 74*031542fcSKonstantin Porotchkin /* Open/Close incoming access for all masters. 75*031542fcSKonstantin Porotchkin * The access is disabled in trusted boot mode 76*031542fcSKonstantin Porotchkin * Could only be done in EL3 77*031542fcSKonstantin Porotchkin */ 78*031542fcSKonstantin Porotchkin reg = mmio_read_32(SEC_MOCHI_IN_ACC_REG); 79*031542fcSKonstantin Porotchkin if (enable) 80*031542fcSKonstantin Porotchkin mmio_write_32(SEC_MOCHI_IN_ACC_REG, reg | 81*031542fcSKonstantin Porotchkin SEC_IN_ACCESS_ENA_ALL_MASTERS); 82*031542fcSKonstantin Porotchkin else 83*031542fcSKonstantin Porotchkin mmio_write_32(SEC_MOCHI_IN_ACC_REG, reg & 84*031542fcSKonstantin Porotchkin ~SEC_IN_ACCESS_ENA_ALL_MASTERS); 85*031542fcSKonstantin Porotchkin } 86*031542fcSKonstantin Porotchkin 87*031542fcSKonstantin Porotchkin static void setup_smmu(void) 88*031542fcSKonstantin Porotchkin { 89*031542fcSKonstantin Porotchkin uint32_t reg; 90*031542fcSKonstantin Porotchkin 91*031542fcSKonstantin Porotchkin /* Set the SMMU page size to 64 KB */ 92*031542fcSKonstantin Porotchkin reg = mmio_read_32(SMMU_sACR); 93*031542fcSKonstantin Porotchkin reg |= SMMU_sACR_PG_64K; 94*031542fcSKonstantin Porotchkin mmio_write_32(SMMU_sACR, reg); 95*031542fcSKonstantin Porotchkin } 96*031542fcSKonstantin Porotchkin 97*031542fcSKonstantin Porotchkin static void apn806_errata_wa_init(void) 98*031542fcSKonstantin Porotchkin { 99*031542fcSKonstantin Porotchkin /* 100*031542fcSKonstantin Porotchkin * ERRATA ID: RES-3033912 - Internal Address Space Init state causes 101*031542fcSKonstantin Porotchkin * a hang upon accesses to [0xf070_0000, 0xf07f_ffff] 102*031542fcSKonstantin Porotchkin * Workaround: Boot Firmware (ATF) should configure CCU_RGF_WIN(4) to 103*031542fcSKonstantin Porotchkin * split [0x6e_0000, 0xff_ffff] to values [0x6e_0000, 0x6f_ffff] and 104*031542fcSKonstantin Porotchkin * [0x80_0000, 0xff_ffff] that cause accesses to the 105*031542fcSKonstantin Porotchkin * segment of [0xf070_0000, 0xf07f_ffff] to act as RAZWI. 106*031542fcSKonstantin Porotchkin */ 107*031542fcSKonstantin Porotchkin mmio_write_32(CCU_RGF(4), 0x37f9b809); 108*031542fcSKonstantin Porotchkin mmio_write_32(CCU_RGF(5), 0x7ffa0009); 109*031542fcSKonstantin Porotchkin } 110*031542fcSKonstantin Porotchkin 111*031542fcSKonstantin Porotchkin static void init_aurora2(void) 112*031542fcSKonstantin Porotchkin { 113*031542fcSKonstantin Porotchkin uint32_t reg; 114*031542fcSKonstantin Porotchkin 115*031542fcSKonstantin Porotchkin /* Enable GSPMU control by CPU */ 116*031542fcSKonstantin Porotchkin reg = mmio_read_32(CCU_GSPMU_CR); 117*031542fcSKonstantin Porotchkin reg |= GSPMU_CPU_CONTROL; 118*031542fcSKonstantin Porotchkin mmio_write_32(CCU_GSPMU_CR, reg); 119*031542fcSKonstantin Porotchkin 120*031542fcSKonstantin Porotchkin #if LLC_ENABLE 121*031542fcSKonstantin Porotchkin /* Enable LLC for AP806 in exclusive mode */ 122*031542fcSKonstantin Porotchkin llc_enable(0, 1); 123*031542fcSKonstantin Porotchkin 124*031542fcSKonstantin Porotchkin /* Set point of coherency to DDR. 125*031542fcSKonstantin Porotchkin * This is required by units which have 126*031542fcSKonstantin Porotchkin * SW cache coherency 127*031542fcSKonstantin Porotchkin */ 128*031542fcSKonstantin Porotchkin reg = mmio_read_32(CCU_HTC_CR); 129*031542fcSKonstantin Porotchkin reg |= (0x1 << CCU_SET_POC_OFFSET); 130*031542fcSKonstantin Porotchkin mmio_write_32(CCU_HTC_CR, reg); 131*031542fcSKonstantin Porotchkin #endif /* LLC_ENABLE */ 132*031542fcSKonstantin Porotchkin 133*031542fcSKonstantin Porotchkin apn806_errata_wa_init(); 134*031542fcSKonstantin Porotchkin } 135*031542fcSKonstantin Porotchkin 136*031542fcSKonstantin Porotchkin 137*031542fcSKonstantin Porotchkin /* MCIx indirect access register are based by default at 0xf4000000/0xf6000000 138*031542fcSKonstantin Porotchkin * to avoid conflict of internal registers of units connected via MCIx, which 139*031542fcSKonstantin Porotchkin * can be based on the same address (i.e CP1 base is also 0xf4000000), 140*031542fcSKonstantin Porotchkin * the following routines remaps the MCIx indirect bases to another domain 141*031542fcSKonstantin Porotchkin */ 142*031542fcSKonstantin Porotchkin static void mci_remap_indirect_access_base(void) 143*031542fcSKonstantin Porotchkin { 144*031542fcSKonstantin Porotchkin uint32_t mci; 145*031542fcSKonstantin Porotchkin 146*031542fcSKonstantin Porotchkin for (mci = 0; mci < MCI_MAX_UNIT_ID; mci++) 147*031542fcSKonstantin Porotchkin mmio_write_32(MCIX4_REG_START_ADDRESS_REG(mci), 148*031542fcSKonstantin Porotchkin MVEBU_MCI_REG_BASE_REMAP(mci) >> 149*031542fcSKonstantin Porotchkin MCI_REMAP_OFF_SHIFT); 150*031542fcSKonstantin Porotchkin } 151*031542fcSKonstantin Porotchkin 152*031542fcSKonstantin Porotchkin static void apn806_axi_attr_init(void) 153*031542fcSKonstantin Porotchkin { 154*031542fcSKonstantin Porotchkin uint32_t index, data; 155*031542fcSKonstantin Porotchkin 156*031542fcSKonstantin Porotchkin /* Initialize AXI attributes for APN806 */ 157*031542fcSKonstantin Porotchkin 158*031542fcSKonstantin Porotchkin /* Go over the AXI attributes and set Ax-Cache and Ax-Domain */ 159*031542fcSKonstantin Porotchkin for (index = 0; index < AXI_MAX_ATTR; index++) { 160*031542fcSKonstantin Porotchkin switch (index) { 161*031542fcSKonstantin Porotchkin /* DFX works with no coherent only - 162*031542fcSKonstantin Porotchkin * there's no option to configure the Ax-Cache and Ax-Domain 163*031542fcSKonstantin Porotchkin */ 164*031542fcSKonstantin Porotchkin case AXI_DFX_ATTR: 165*031542fcSKonstantin Porotchkin continue; 166*031542fcSKonstantin Porotchkin default: 167*031542fcSKonstantin Porotchkin /* Set Ax-Cache as cacheable, no allocate, modifiable, 168*031542fcSKonstantin Porotchkin * bufferable 169*031542fcSKonstantin Porotchkin * The values are different because Read & Write 170*031542fcSKonstantin Porotchkin * definition is different in Ax-Cache 171*031542fcSKonstantin Porotchkin */ 172*031542fcSKonstantin Porotchkin data = mmio_read_32(MVEBU_AXI_ATTR_REG(index)); 173*031542fcSKonstantin Porotchkin data &= ~MVEBU_AXI_ATTR_ARCACHE_MASK; 174*031542fcSKonstantin Porotchkin data |= (CACHE_ATTR_WRITE_ALLOC | 175*031542fcSKonstantin Porotchkin CACHE_ATTR_CACHEABLE | 176*031542fcSKonstantin Porotchkin CACHE_ATTR_BUFFERABLE) << 177*031542fcSKonstantin Porotchkin MVEBU_AXI_ATTR_ARCACHE_OFFSET; 178*031542fcSKonstantin Porotchkin data &= ~MVEBU_AXI_ATTR_AWCACHE_MASK; 179*031542fcSKonstantin Porotchkin data |= (CACHE_ATTR_READ_ALLOC | 180*031542fcSKonstantin Porotchkin CACHE_ATTR_CACHEABLE | 181*031542fcSKonstantin Porotchkin CACHE_ATTR_BUFFERABLE) << 182*031542fcSKonstantin Porotchkin MVEBU_AXI_ATTR_AWCACHE_OFFSET; 183*031542fcSKonstantin Porotchkin /* Set Ax-Domain as Outer domain */ 184*031542fcSKonstantin Porotchkin data &= ~MVEBU_AXI_ATTR_ARDOMAIN_MASK; 185*031542fcSKonstantin Porotchkin data |= DOMAIN_OUTER_SHAREABLE << 186*031542fcSKonstantin Porotchkin MVEBU_AXI_ATTR_ARDOMAIN_OFFSET; 187*031542fcSKonstantin Porotchkin data &= ~MVEBU_AXI_ATTR_AWDOMAIN_MASK; 188*031542fcSKonstantin Porotchkin data |= DOMAIN_OUTER_SHAREABLE << 189*031542fcSKonstantin Porotchkin MVEBU_AXI_ATTR_AWDOMAIN_OFFSET; 190*031542fcSKonstantin Porotchkin mmio_write_32(MVEBU_AXI_ATTR_REG(index), data); 191*031542fcSKonstantin Porotchkin } 192*031542fcSKonstantin Porotchkin } 193*031542fcSKonstantin Porotchkin } 194*031542fcSKonstantin Porotchkin 195*031542fcSKonstantin Porotchkin static void dss_setup(void) 196*031542fcSKonstantin Porotchkin { 197*031542fcSKonstantin Porotchkin /* Enable 48-bit VA */ 198*031542fcSKonstantin Porotchkin mmio_setbits_32(DSS_CR0, DVM_48BIT_VA_ENABLE); 199*031542fcSKonstantin Porotchkin } 200*031542fcSKonstantin Porotchkin 201*031542fcSKonstantin Porotchkin void misc_soc_configurations(void) 202*031542fcSKonstantin Porotchkin { 203*031542fcSKonstantin Porotchkin uint32_t reg; 204*031542fcSKonstantin Porotchkin 205*031542fcSKonstantin Porotchkin /* Un-mask Watchdog reset from influencing the SYSRST_OUTn. 206*031542fcSKonstantin Porotchkin * Otherwise, upon WD timeout, the WD reset signal won't trigger reset 207*031542fcSKonstantin Porotchkin */ 208*031542fcSKonstantin Porotchkin reg = mmio_read_32(MVEBU_SYSRST_OUT_CONFIG_REG); 209*031542fcSKonstantin Porotchkin reg &= ~(WD_MASK_SYS_RST_OUT); 210*031542fcSKonstantin Porotchkin mmio_write_32(MVEBU_SYSRST_OUT_CONFIG_REG, reg); 211*031542fcSKonstantin Porotchkin } 212*031542fcSKonstantin Porotchkin 213*031542fcSKonstantin Porotchkin void ap_init(void) 214*031542fcSKonstantin Porotchkin { 215*031542fcSKonstantin Porotchkin /* Setup Aurora2. */ 216*031542fcSKonstantin Porotchkin init_aurora2(); 217*031542fcSKonstantin Porotchkin 218*031542fcSKonstantin Porotchkin /* configure MCI mapping */ 219*031542fcSKonstantin Porotchkin mci_remap_indirect_access_base(); 220*031542fcSKonstantin Porotchkin 221*031542fcSKonstantin Porotchkin /* configure IO_WIN windows */ 222*031542fcSKonstantin Porotchkin init_io_win(MVEBU_AP0); 223*031542fcSKonstantin Porotchkin 224*031542fcSKonstantin Porotchkin /* configure CCU windows */ 225*031542fcSKonstantin Porotchkin init_ccu(MVEBU_AP0); 226*031542fcSKonstantin Porotchkin 227*031542fcSKonstantin Porotchkin /* configure DSS */ 228*031542fcSKonstantin Porotchkin dss_setup(); 229*031542fcSKonstantin Porotchkin 230*031542fcSKonstantin Porotchkin /* configure the SMMU */ 231*031542fcSKonstantin Porotchkin setup_smmu(); 232*031542fcSKonstantin Porotchkin 233*031542fcSKonstantin Porotchkin /* Open APN incoming access for all masters */ 234*031542fcSKonstantin Porotchkin apn_sec_masters_access_en(1); 235*031542fcSKonstantin Porotchkin 236*031542fcSKonstantin Porotchkin /* configure axi for APN*/ 237*031542fcSKonstantin Porotchkin apn806_axi_attr_init(); 238*031542fcSKonstantin Porotchkin 239*031542fcSKonstantin Porotchkin /* misc configuration of the SoC */ 240*031542fcSKonstantin Porotchkin misc_soc_configurations(); 241*031542fcSKonstantin Porotchkin } 242*031542fcSKonstantin Porotchkin 243*031542fcSKonstantin Porotchkin void ap_ble_init(void) 244*031542fcSKonstantin Porotchkin { 245*031542fcSKonstantin Porotchkin } 246*031542fcSKonstantin Porotchkin 247*031542fcSKonstantin Porotchkin int ap_get_count(void) 248*031542fcSKonstantin Porotchkin { 249*031542fcSKonstantin Porotchkin return 1; 250*031542fcSKonstantin Porotchkin } 251*031542fcSKonstantin Porotchkin 252