1*b45b5bacSMarek Vasut /* 2*b45b5bacSMarek Vasut * Copyright (c) 2015-2025, Renesas Electronics Corporation. All rights reserved. 3*b45b5bacSMarek Vasut * 4*b45b5bacSMarek Vasut * SPDX-License-Identifier: BSD-3-Clause 5*b45b5bacSMarek Vasut */ 6*b45b5bacSMarek Vasut 7*b45b5bacSMarek Vasut #include <assert.h> 8*b45b5bacSMarek Vasut #include <string.h> 9*b45b5bacSMarek Vasut 10*b45b5bacSMarek Vasut #include <arch.h> 11*b45b5bacSMarek Vasut #include <arch_helpers.h> 12*b45b5bacSMarek Vasut #include <common/debug.h> 13*b45b5bacSMarek Vasut #include <lib/bakery_lock.h> 14*b45b5bacSMarek Vasut #include <lib/mmio.h> 15*b45b5bacSMarek Vasut #include <lib/xlat_tables/xlat_tables_v2.h> 16*b45b5bacSMarek Vasut #include <plat/common/platform.h> 17*b45b5bacSMarek Vasut 18*b45b5bacSMarek Vasut #include "pwrc.h" 19*b45b5bacSMarek Vasut #include "rcar_def.h" 20*b45b5bacSMarek Vasut #include "rcar_private.h" 21*b45b5bacSMarek Vasut 22*b45b5bacSMarek Vasut #ifndef __ASSEMBLER__ 23*b45b5bacSMarek Vasut IMPORT_SYM(uintptr_t, __system_ram_start__, SYSTEM_RAM_START); 24*b45b5bacSMarek Vasut IMPORT_SYM(uintptr_t, __system_ram_end__, SYSTEM_RAM_END); 25*b45b5bacSMarek Vasut IMPORT_SYM(uintptr_t, __SRAM_COPY_START__, SRAM_COPY_START); 26*b45b5bacSMarek Vasut #endif /*__ASSEMBLER__*/ 27*b45b5bacSMarek Vasut 28*b45b5bacSMarek Vasut #define RCAR_CODE_COPY_NONE 0 29*b45b5bacSMarek Vasut #define RCAR_CODE_COPY_DONE 1 30*b45b5bacSMarek Vasut 31*b45b5bacSMarek Vasut static uint32_t dummy_sdram = 0xAAAAAAAA; 32*b45b5bacSMarek Vasut static uint32_t rcar_pwrc_code_copy_state; 33*b45b5bacSMarek Vasut 34*b45b5bacSMarek Vasut /* 35*b45b5bacSMarek Vasut * Someday there will be a generic power controller API. At the moment each 36*b45b5bacSMarek Vasut * platform has its own PWRC so just exporting functions should be acceptable. 37*b45b5bacSMarek Vasut */ 38*b45b5bacSMarek Vasut static RCAR_INSTANTIATE_LOCK; 39*b45b5bacSMarek Vasut 40*b45b5bacSMarek Vasut static u_register_t rcar_boot_mpidr; 41*b45b5bacSMarek Vasut 42*b45b5bacSMarek Vasut /* APSREG boot configuration */ 43*b45b5bacSMarek Vasut static uintptr_t apsreg_ap_cluster_aux0(uint32_t n) 44*b45b5bacSMarek Vasut { 45*b45b5bacSMarek Vasut return APSREG_BASE + 0x10UL + ((n & 0x3) * 0x1000UL); 46*b45b5bacSMarek Vasut } 47*b45b5bacSMarek Vasut 48*b45b5bacSMarek Vasut /* APMU */ 49*b45b5bacSMarek Vasut static uintptr_t rcar_apmu_cluster_base(uint32_t n) 50*b45b5bacSMarek Vasut { 51*b45b5bacSMarek Vasut return RCAR_APMU_BASE + 0x400UL + ((n & 0x3) * 0x40UL); 52*b45b5bacSMarek Vasut } 53*b45b5bacSMarek Vasut 54*b45b5bacSMarek Vasut static uintptr_t rcar_apmu_cpu_base(uint32_t n) 55*b45b5bacSMarek Vasut { 56*b45b5bacSMarek Vasut return RCAR_APMU_BASE + 0x800UL + ((n & 0x6) * 0x100UL) + 57*b45b5bacSMarek Vasut ((n & 0x1) * 0x40UL); 58*b45b5bacSMarek Vasut } 59*b45b5bacSMarek Vasut 60*b45b5bacSMarek Vasut static uintptr_t rcar_apmu_pwrctrlcl(uint32_t n) 61*b45b5bacSMarek Vasut { 62*b45b5bacSMarek Vasut return rcar_apmu_cluster_base(n); 63*b45b5bacSMarek Vasut } 64*b45b5bacSMarek Vasut 65*b45b5bacSMarek Vasut static uintptr_t rcar_apmu_pwrctrlc(uint32_t n) 66*b45b5bacSMarek Vasut { 67*b45b5bacSMarek Vasut return rcar_apmu_cpu_base(n); 68*b45b5bacSMarek Vasut } 69*b45b5bacSMarek Vasut 70*b45b5bacSMarek Vasut static uintptr_t rcar_apmu_safectrlc(uint32_t n) 71*b45b5bacSMarek Vasut { 72*b45b5bacSMarek Vasut return rcar_apmu_cpu_base(n) + 0x20UL; 73*b45b5bacSMarek Vasut } 74*b45b5bacSMarek Vasut 75*b45b5bacSMarek Vasut static uintptr_t rcar_apmu_rvbarplc(uint32_t n) 76*b45b5bacSMarek Vasut { 77*b45b5bacSMarek Vasut return rcar_apmu_cpu_base(n) + 0x38UL; 78*b45b5bacSMarek Vasut } 79*b45b5bacSMarek Vasut 80*b45b5bacSMarek Vasut static uintptr_t rcar_apmu_rvbarphc(uint32_t n) 81*b45b5bacSMarek Vasut { 82*b45b5bacSMarek Vasut return rcar_apmu_cpu_base(n) + 0x3cUL; 83*b45b5bacSMarek Vasut } 84*b45b5bacSMarek Vasut 85*b45b5bacSMarek Vasut static uintptr_t rcar_apmu_fsmstsrc(uint32_t n) 86*b45b5bacSMarek Vasut { 87*b45b5bacSMarek Vasut return rcar_apmu_cpu_base(n) + 0x18UL; 88*b45b5bacSMarek Vasut } 89*b45b5bacSMarek Vasut 90*b45b5bacSMarek Vasut /* Product register */ 91*b45b5bacSMarek Vasut static uint32_t prr_caxx_xx_en_cpu(uint32_t n) 92*b45b5bacSMarek Vasut { 93*b45b5bacSMarek Vasut return BIT(n & 0x1); 94*b45b5bacSMarek Vasut } 95*b45b5bacSMarek Vasut 96*b45b5bacSMarek Vasut static void write_cpupwrctlr(u_register_t v) 97*b45b5bacSMarek Vasut { 98*b45b5bacSMarek Vasut __asm__ volatile ("msr S3_0_C15_C2_7, %0" : : "r" (v)); 99*b45b5bacSMarek Vasut } 100*b45b5bacSMarek Vasut 101*b45b5bacSMarek Vasut static uint32_t rcar_pwrc_core_pos(u_register_t mpidr) 102*b45b5bacSMarek Vasut { 103*b45b5bacSMarek Vasut int cpu; 104*b45b5bacSMarek Vasut 105*b45b5bacSMarek Vasut cpu = plat_core_pos_by_mpidr(mpidr); 106*b45b5bacSMarek Vasut if (cpu < 0) { 107*b45b5bacSMarek Vasut ERROR("BL3-1 : The value of passed MPIDR is invalid."); 108*b45b5bacSMarek Vasut panic(); 109*b45b5bacSMarek Vasut } 110*b45b5bacSMarek Vasut 111*b45b5bacSMarek Vasut return (uint32_t)cpu; 112*b45b5bacSMarek Vasut } 113*b45b5bacSMarek Vasut 114*b45b5bacSMarek Vasut static uint64_t rcar_pwrc_saved_cntpct_el0; 115*b45b5bacSMarek Vasut static uint32_t rcar_pwrc_saved_cntfid; 116*b45b5bacSMarek Vasut 117*b45b5bacSMarek Vasut void rcar_pwrc_cpuon(u_register_t mpidr) 118*b45b5bacSMarek Vasut { 119*b45b5bacSMarek Vasut uint32_t cluster, cpu; 120*b45b5bacSMarek Vasut 121*b45b5bacSMarek Vasut rcar_lock_get(); 122*b45b5bacSMarek Vasut 123*b45b5bacSMarek Vasut cpu = rcar_pwrc_core_pos(mpidr); 124*b45b5bacSMarek Vasut 125*b45b5bacSMarek Vasut cluster = rcar_pwrc_get_mpidr_cluster(mpidr); 126*b45b5bacSMarek Vasut 127*b45b5bacSMarek Vasut /* clear Cluster OFF bit */ 128*b45b5bacSMarek Vasut mmio_clrbits_32(rcar_apmu_pwrctrlcl(cluster), 129*b45b5bacSMarek Vasut RCAR_APMU_PWRCTRLCL_PCHPDNEN); 130*b45b5bacSMarek Vasut 131*b45b5bacSMarek Vasut /* clear Core OFF bit */ 132*b45b5bacSMarek Vasut mmio_clrbits_32(rcar_apmu_pwrctrlc(cpu), RCAR_APMU_PWRCTRLC_PCHPDNEN); 133*b45b5bacSMarek Vasut while (mmio_read_32(rcar_apmu_pwrctrlc(cpu)) & RCAR_APMU_PWRCTRLC_PCHPDNEN) 134*b45b5bacSMarek Vasut ; 135*b45b5bacSMarek Vasut 136*b45b5bacSMarek Vasut mmio_setbits_32(rcar_apmu_pwrctrlc(cpu), RCAR_APMU_PWRCTRLC_WUP_REQ); 137*b45b5bacSMarek Vasut 138*b45b5bacSMarek Vasut /* Wait until CAXX wake up sequence finishes */ 139*b45b5bacSMarek Vasut while ((mmio_read_32(rcar_apmu_pwrctrlc(cpu)) & RCAR_APMU_PWRCTRLC_WUP_REQ) == 140*b45b5bacSMarek Vasut RCAR_APMU_PWRCTRLC_WUP_REQ) 141*b45b5bacSMarek Vasut ; 142*b45b5bacSMarek Vasut 143*b45b5bacSMarek Vasut rcar_lock_release(); 144*b45b5bacSMarek Vasut 145*b45b5bacSMarek Vasut /* 146*b45b5bacSMarek Vasut * mask should match the kernel's MPIDR_HWID_BITMASK so the core can be 147*b45b5bacSMarek Vasut * identified during cpuhotplug (check the kernel's psci migrate set of 148*b45b5bacSMarek Vasut * functions 149*b45b5bacSMarek Vasut */ 150*b45b5bacSMarek Vasut rcar_boot_mpidr = read_mpidr_el1() & RCAR_MPIDR_AFFMASK; 151*b45b5bacSMarek Vasut } 152*b45b5bacSMarek Vasut 153*b45b5bacSMarek Vasut int32_t rcar_pwrc_cpu_migrate_info(u_register_t *resident_cpu) 154*b45b5bacSMarek Vasut { 155*b45b5bacSMarek Vasut *resident_cpu = rcar_boot_mpidr; 156*b45b5bacSMarek Vasut 157*b45b5bacSMarek Vasut return PSCI_TOS_NOT_UP_MIG_CAP; 158*b45b5bacSMarek Vasut } 159*b45b5bacSMarek Vasut 160*b45b5bacSMarek Vasut bool rcar_pwrc_mpidr_is_boot_cpu(u_register_t mpidr) 161*b45b5bacSMarek Vasut { 162*b45b5bacSMarek Vasut return (mpidr & RCAR_MPIDR_AFFMASK) == rcar_boot_mpidr; 163*b45b5bacSMarek Vasut } 164*b45b5bacSMarek Vasut 165*b45b5bacSMarek Vasut static void rcar_pwrc_cpuoff_sub(uint32_t cpu) 166*b45b5bacSMarek Vasut { 167*b45b5bacSMarek Vasut /* Clear DBGGEN_PPDN bit for core down to 'OFF' mode */ 168*b45b5bacSMarek Vasut mmio_clrbits_32(rcar_apmu_safectrlc(cpu), RCAR_APMU_SAFECTRLC_DBGGEN); 169*b45b5bacSMarek Vasut /* for Core OFF */ 170*b45b5bacSMarek Vasut mmio_setbits_32(rcar_apmu_pwrctrlc(cpu), RCAR_APMU_PWRCTRLC_PCHPDNEN); 171*b45b5bacSMarek Vasut 172*b45b5bacSMarek Vasut write_cpupwrctlr(CPUPWRCTLR_PWDN); 173*b45b5bacSMarek Vasut } 174*b45b5bacSMarek Vasut 175*b45b5bacSMarek Vasut void rcar_pwrc_cpuoff(u_register_t mpidr) 176*b45b5bacSMarek Vasut { 177*b45b5bacSMarek Vasut uint32_t cpu; 178*b45b5bacSMarek Vasut 179*b45b5bacSMarek Vasut rcar_lock_get(); 180*b45b5bacSMarek Vasut 181*b45b5bacSMarek Vasut cpu = rcar_pwrc_core_pos(mpidr); 182*b45b5bacSMarek Vasut 183*b45b5bacSMarek Vasut rcar_pwrc_cpuoff_sub(cpu); 184*b45b5bacSMarek Vasut 185*b45b5bacSMarek Vasut rcar_lock_release(); 186*b45b5bacSMarek Vasut } 187*b45b5bacSMarek Vasut 188*b45b5bacSMarek Vasut void rcar_pwrc_enable_interrupt_wakeup(u_register_t mpidr) 189*b45b5bacSMarek Vasut { 190*b45b5bacSMarek Vasut uint32_t cpu; 191*b45b5bacSMarek Vasut 192*b45b5bacSMarek Vasut rcar_lock_get(); 193*b45b5bacSMarek Vasut 194*b45b5bacSMarek Vasut cpu = rcar_pwrc_core_pos(mpidr); 195*b45b5bacSMarek Vasut 196*b45b5bacSMarek Vasut mmio_setbits_32(rcar_apmu_pwrctrlc(cpu), RCAR_APMU_PWRCTRLC_IWUP_EN); 197*b45b5bacSMarek Vasut 198*b45b5bacSMarek Vasut rcar_lock_release(); 199*b45b5bacSMarek Vasut } 200*b45b5bacSMarek Vasut 201*b45b5bacSMarek Vasut void rcar_pwrc_disable_interrupt_wakeup(u_register_t mpidr) 202*b45b5bacSMarek Vasut { 203*b45b5bacSMarek Vasut uint32_t cpu; 204*b45b5bacSMarek Vasut 205*b45b5bacSMarek Vasut rcar_lock_get(); 206*b45b5bacSMarek Vasut 207*b45b5bacSMarek Vasut cpu = rcar_pwrc_core_pos(mpidr); 208*b45b5bacSMarek Vasut 209*b45b5bacSMarek Vasut mmio_clrbits_32(rcar_apmu_pwrctrlc(cpu), RCAR_APMU_PWRCTRLC_IWUP_EN); 210*b45b5bacSMarek Vasut 211*b45b5bacSMarek Vasut rcar_lock_release(); 212*b45b5bacSMarek Vasut } 213*b45b5bacSMarek Vasut 214*b45b5bacSMarek Vasut void rcar_pwrc_clusteroff(u_register_t mpidr) 215*b45b5bacSMarek Vasut { 216*b45b5bacSMarek Vasut uint32_t cluster, cpu; 217*b45b5bacSMarek Vasut 218*b45b5bacSMarek Vasut rcar_lock_get(); 219*b45b5bacSMarek Vasut 220*b45b5bacSMarek Vasut cpu = rcar_pwrc_core_pos(mpidr); 221*b45b5bacSMarek Vasut 222*b45b5bacSMarek Vasut cluster = rcar_pwrc_get_mpidr_cluster(mpidr); 223*b45b5bacSMarek Vasut 224*b45b5bacSMarek Vasut /* for Cluster OFF */ 225*b45b5bacSMarek Vasut mmio_setbits_32(rcar_apmu_pwrctrlcl(cluster), 226*b45b5bacSMarek Vasut RCAR_APMU_PWRCTRLCL_PCHPDNEN); 227*b45b5bacSMarek Vasut 228*b45b5bacSMarek Vasut rcar_pwrc_cpuoff_sub(cpu); 229*b45b5bacSMarek Vasut 230*b45b5bacSMarek Vasut rcar_lock_release(); 231*b45b5bacSMarek Vasut } 232*b45b5bacSMarek Vasut 233*b45b5bacSMarek Vasut void rcar_pwrc_setup(void) 234*b45b5bacSMarek Vasut { 235*b45b5bacSMarek Vasut uintptr_t rst_barh, rst_barl; 236*b45b5bacSMarek Vasut uint32_t cpu, i, j, reg; 237*b45b5bacSMarek Vasut uint64_t reset; 238*b45b5bacSMarek Vasut 239*b45b5bacSMarek Vasut reset = (uint64_t)(&plat_secondary_reset) & 0xFFFFFFFFU; 240*b45b5bacSMarek Vasut reset &= RCAR_APMU_RVBARPLC_MASK; 241*b45b5bacSMarek Vasut reset |= RCAR_APMU_RVBARPL_VLD; 242*b45b5bacSMarek Vasut 243*b45b5bacSMarek Vasut reg = mmio_read_32(RCAR_PRR) >> 17; 244*b45b5bacSMarek Vasut for (i = 0; i < PLATFORM_CLUSTER_COUNT; i++) { 245*b45b5bacSMarek Vasut reg >>= 3; 246*b45b5bacSMarek Vasut 247*b45b5bacSMarek Vasut if ((reg & PRR_CAXX_XX_EN_CLUSTER_MASK) != RCAR_CPU_HAVE_CAXX) 248*b45b5bacSMarek Vasut continue; 249*b45b5bacSMarek Vasut 250*b45b5bacSMarek Vasut mmio_setbits_32(apsreg_ap_cluster_aux0(i), 251*b45b5bacSMarek Vasut APSREG_AP_CLUSTER_AUX0_INIT); 252*b45b5bacSMarek Vasut 253*b45b5bacSMarek Vasut for (j = 0; j < PLATFORM_MAX_CPUS_PER_CLUSTER; j++) { 254*b45b5bacSMarek Vasut cpu = (i * PLATFORM_MAX_CPUS_PER_CLUSTER) + j; 255*b45b5bacSMarek Vasut 256*b45b5bacSMarek Vasut if ((reg & prr_caxx_xx_en_cpu(cpu)) != RCAR_CPU_HAVE_CAXX) 257*b45b5bacSMarek Vasut continue; 258*b45b5bacSMarek Vasut 259*b45b5bacSMarek Vasut rst_barh = rcar_apmu_rvbarphc(cpu); 260*b45b5bacSMarek Vasut rst_barl = rcar_apmu_rvbarplc(cpu); 261*b45b5bacSMarek Vasut mmio_write_32(rst_barh, 0); 262*b45b5bacSMarek Vasut mmio_write_32(rst_barl, (uint32_t)reset); 263*b45b5bacSMarek Vasut } 264*b45b5bacSMarek Vasut } 265*b45b5bacSMarek Vasut 266*b45b5bacSMarek Vasut mmio_setbits_32(APSREG_CCI500_AUX, APSREG_CCI500_AUX_INIT); 267*b45b5bacSMarek Vasut mmio_setbits_32(APSREG_P_CCI500_AUX, APSREG_P_CCI500_AUX_INIT); 268*b45b5bacSMarek Vasut 269*b45b5bacSMarek Vasut rcar_lock_init(); 270*b45b5bacSMarek Vasut } 271*b45b5bacSMarek Vasut 272*b45b5bacSMarek Vasut uint32_t rcar_pwrc_get_mpidr_cluster(u_register_t mpidr) 273*b45b5bacSMarek Vasut { 274*b45b5bacSMarek Vasut int32_t cluster = rcar_cluster_pos_by_mpidr(mpidr); 275*b45b5bacSMarek Vasut 276*b45b5bacSMarek Vasut if (cluster < 0) { 277*b45b5bacSMarek Vasut ERROR("BL3-1 : The value of passed MPIDR is invalid."); 278*b45b5bacSMarek Vasut panic(); 279*b45b5bacSMarek Vasut } 280*b45b5bacSMarek Vasut 281*b45b5bacSMarek Vasut return (uint32_t)cluster; 282*b45b5bacSMarek Vasut } 283*b45b5bacSMarek Vasut 284*b45b5bacSMarek Vasut uint32_t rcar_pwrc_cpu_on_check(u_register_t mpidr) 285*b45b5bacSMarek Vasut { 286*b45b5bacSMarek Vasut uint32_t core_pos, cpu, i, j, prr, state; 287*b45b5bacSMarek Vasut uint32_t count = 0; 288*b45b5bacSMarek Vasut 289*b45b5bacSMarek Vasut core_pos = rcar_pwrc_core_pos(mpidr); 290*b45b5bacSMarek Vasut prr = mmio_read_32(RCAR_PRR) >> 17; 291*b45b5bacSMarek Vasut for (i = 0; i < PLATFORM_CLUSTER_COUNT; i++) { 292*b45b5bacSMarek Vasut prr >>= 3; 293*b45b5bacSMarek Vasut 294*b45b5bacSMarek Vasut /* check the cluster has cores */ 295*b45b5bacSMarek Vasut if ((prr & PRR_CAXX_XX_EN_CLUSTER_MASK) != RCAR_CPU_HAVE_CAXX) 296*b45b5bacSMarek Vasut continue; 297*b45b5bacSMarek Vasut 298*b45b5bacSMarek Vasut for (j = 0; j < PLATFORM_MAX_CPUS_PER_CLUSTER; j++) { 299*b45b5bacSMarek Vasut cpu = (i * PLATFORM_MAX_CPUS_PER_CLUSTER) + j; 300*b45b5bacSMarek Vasut 301*b45b5bacSMarek Vasut /* check the core be implemented */ 302*b45b5bacSMarek Vasut if ((prr & prr_caxx_xx_en_cpu(cpu)) != RCAR_CPU_HAVE_CAXX) 303*b45b5bacSMarek Vasut continue; 304*b45b5bacSMarek Vasut 305*b45b5bacSMarek Vasut if (core_pos != cpu) { 306*b45b5bacSMarek Vasut state = mmio_read_32(rcar_apmu_fsmstsrc(cpu)); 307*b45b5bacSMarek Vasut if (state != RCAR_APMU_FSMSTSRC_STATE_OFF) 308*b45b5bacSMarek Vasut count++; 309*b45b5bacSMarek Vasut } 310*b45b5bacSMarek Vasut } 311*b45b5bacSMarek Vasut } 312*b45b5bacSMarek Vasut 313*b45b5bacSMarek Vasut return count; 314*b45b5bacSMarek Vasut } 315*b45b5bacSMarek Vasut 316*b45b5bacSMarek Vasut static void rcar_pwrc_save_timer_state(void) 317*b45b5bacSMarek Vasut { 318*b45b5bacSMarek Vasut rcar_pwrc_saved_cntpct_el0 = read_cntpct_el0(); 319*b45b5bacSMarek Vasut 320*b45b5bacSMarek Vasut rcar_pwrc_saved_cntfid = 321*b45b5bacSMarek Vasut mmio_read_32((uintptr_t)(RCAR_CNTC_BASE + CNTFID_OFF)); 322*b45b5bacSMarek Vasut } 323*b45b5bacSMarek Vasut 324*b45b5bacSMarek Vasut void rcar_pwrc_restore_timer_state(void) 325*b45b5bacSMarek Vasut { 326*b45b5bacSMarek Vasut /* Stop timer before restoring counter value */ 327*b45b5bacSMarek Vasut mmio_write_32((uintptr_t)(RCAR_CNTC_BASE + CNTCR_OFF), 0U); 328*b45b5bacSMarek Vasut 329*b45b5bacSMarek Vasut /* restore lower counter value */ 330*b45b5bacSMarek Vasut mmio_write_32((uintptr_t)(RCAR_CNTC_BASE + RCAR_CNTCVL_OFF), 331*b45b5bacSMarek Vasut (uint32_t)(rcar_pwrc_saved_cntpct_el0 & 0xFFFFFFFFU)); 332*b45b5bacSMarek Vasut /* restore upper counter value */ 333*b45b5bacSMarek Vasut mmio_write_32((uintptr_t)(RCAR_CNTC_BASE + RCAR_CNTCVU_OFF), 334*b45b5bacSMarek Vasut (uint32_t)(rcar_pwrc_saved_cntpct_el0 >> 32U)); 335*b45b5bacSMarek Vasut /* restore counter frequency setting */ 336*b45b5bacSMarek Vasut mmio_write_32((uintptr_t)(RCAR_CNTC_BASE + CNTFID_OFF), 337*b45b5bacSMarek Vasut rcar_pwrc_saved_cntfid); 338*b45b5bacSMarek Vasut 339*b45b5bacSMarek Vasut /* Start generic timer back */ 340*b45b5bacSMarek Vasut write_cntfrq_el0((u_register_t)plat_get_syscnt_freq2()); 341*b45b5bacSMarek Vasut 342*b45b5bacSMarek Vasut mmio_write_32((uintptr_t)(RCAR_CNTC_BASE + CNTCR_OFF), 343*b45b5bacSMarek Vasut CNTCR_FCREQ((uint32_t)(0)) | CNTCR_EN); 344*b45b5bacSMarek Vasut } 345*b45b5bacSMarek Vasut 346*b45b5bacSMarek Vasut static void __section(".system_ram") rcar_pwrc_set_self_refresh(void) 347*b45b5bacSMarek Vasut { 348*b45b5bacSMarek Vasut uint64_t base_count, freq, get_count, wait_time; 349*b45b5bacSMarek Vasut uint32_t reg; 350*b45b5bacSMarek Vasut 351*b45b5bacSMarek Vasut /* Enable DBSC4 register access */ 352*b45b5bacSMarek Vasut mmio_write_32(DBSC4_REG_DBSYSCNT0, DBSC4_SET_DBSYSCNT0_WRITE_ENABLE); 353*b45b5bacSMarek Vasut 354*b45b5bacSMarek Vasut /* DFI_PHYMSTR_ACK setting */ 355*b45b5bacSMarek Vasut mmio_clrbits_32(DBSC4_REG_DBDFIPMSTRCNF, DBSC4_BIT_DBDFIPMSTRCNF_PMSTREN); 356*b45b5bacSMarek Vasut 357*b45b5bacSMarek Vasut /* Set the Self-Refresh mode */ 358*b45b5bacSMarek Vasut 359*b45b5bacSMarek Vasut /* Disable access to the SDRAM */ 360*b45b5bacSMarek Vasut mmio_write_32(DBSC4_REG_DBACEN, 0); 361*b45b5bacSMarek Vasut 362*b45b5bacSMarek Vasut /* Flush the access request in DBSC */ 363*b45b5bacSMarek Vasut mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 1); 364*b45b5bacSMarek Vasut 365*b45b5bacSMarek Vasut /* Wait succeed to flush */ 366*b45b5bacSMarek Vasut freq = read_cntfrq_el0(); 367*b45b5bacSMarek Vasut base_count = read_cntpct_el0(); 368*b45b5bacSMarek Vasut 369*b45b5bacSMarek Vasut while ((mmio_read_32(DBSC4_REG_DBCAM0STAT0) & DBSC4_BIT_DBCAM0STAT0) 370*b45b5bacSMarek Vasut != DBSC4_BIT_DBCAM0STAT0) { 371*b45b5bacSMarek Vasut 372*b45b5bacSMarek Vasut get_count = read_cntpct_el0(); 373*b45b5bacSMarek Vasut wait_time = ((get_count - base_count) * RCAR_CONV_MICROSEC) / freq; 374*b45b5bacSMarek Vasut 375*b45b5bacSMarek Vasut /* Get base counter */ 376*b45b5bacSMarek Vasut if (wait_time >= RCAR_WAIT_DBCS4_FLUSH) { 377*b45b5bacSMarek Vasut 378*b45b5bacSMarek Vasut /* Stop flushing and enable access to SDRAM */ 379*b45b5bacSMarek Vasut mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 0); 380*b45b5bacSMarek Vasut mmio_write_32(DBSC4_REG_DBACEN, 1); 381*b45b5bacSMarek Vasut 382*b45b5bacSMarek Vasut /* Dummy write to SDRAM */ 383*b45b5bacSMarek Vasut dummy_sdram = ~dummy_sdram; 384*b45b5bacSMarek Vasut 385*b45b5bacSMarek Vasut /* Re-Disable access and flush */ 386*b45b5bacSMarek Vasut mmio_write_32(DBSC4_REG_DBACEN, 0); 387*b45b5bacSMarek Vasut mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 1); 388*b45b5bacSMarek Vasut 389*b45b5bacSMarek Vasut /* refresh base counter */ 390*b45b5bacSMarek Vasut base_count = read_cntpct_el0(); 391*b45b5bacSMarek Vasut } 392*b45b5bacSMarek Vasut } 393*b45b5bacSMarek Vasut 394*b45b5bacSMarek Vasut /* Clear the SDRAM calibration configuration register */ 395*b45b5bacSMarek Vasut mmio_write_32(DBSC4_REG_DBCALCNF, 0); 396*b45b5bacSMarek Vasut 397*b45b5bacSMarek Vasut /* Issue Precharge All (PREA) command */ 398*b45b5bacSMarek Vasut reg = DBSC4_SET_DBCMD_OPC_PRE | DBSC4_SET_DBCMD_CH_ALL | 399*b45b5bacSMarek Vasut DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_ALL; 400*b45b5bacSMarek Vasut mmio_write_32(DBSC4_REG_DBCMD, reg); 401*b45b5bacSMarek Vasut 402*b45b5bacSMarek Vasut /* Wait to complete PREA operation */ 403*b45b5bacSMarek Vasut while (mmio_read_32(DBSC4_REG_DBWAIT) != 0) 404*b45b5bacSMarek Vasut ; 405*b45b5bacSMarek Vasut 406*b45b5bacSMarek Vasut /* Issue Self-Refresh Entry (SRE) command */ 407*b45b5bacSMarek Vasut reg = DBSC4_SET_DBCMD_OPC_SR | DBSC4_SET_DBCMD_CH_ALL | 408*b45b5bacSMarek Vasut DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_ENTER; 409*b45b5bacSMarek Vasut mmio_write_32(DBSC4_REG_DBCMD, reg); 410*b45b5bacSMarek Vasut 411*b45b5bacSMarek Vasut /* Wait to complete SRE operation */ 412*b45b5bacSMarek Vasut while (mmio_read_32(DBSC4_REG_DBWAIT) != 0) 413*b45b5bacSMarek Vasut ; 414*b45b5bacSMarek Vasut 415*b45b5bacSMarek Vasut /* Issue Mode Register 11 (MR11) write command. (ODT disabled) */ 416*b45b5bacSMarek Vasut reg = DBSC4_SET_DBCMD_OPC_MRW | DBSC4_SET_DBCMD_CH_ALL | 417*b45b5bacSMarek Vasut DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_MRW_ODTC; 418*b45b5bacSMarek Vasut mmio_write_32(DBSC4_REG_DBCMD, reg); 419*b45b5bacSMarek Vasut 420*b45b5bacSMarek Vasut /* Wait to complete MR11 operation */ 421*b45b5bacSMarek Vasut while (mmio_read_32(DBSC4_REG_DBWAIT) != 0) 422*b45b5bacSMarek Vasut ; 423*b45b5bacSMarek Vasut 424*b45b5bacSMarek Vasut /* Issue Power Down (PD) command */ 425*b45b5bacSMarek Vasut reg = DBSC4_SET_DBCMD_OPC_PD | DBSC4_SET_DBCMD_CH_ALL | 426*b45b5bacSMarek Vasut DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_ENTER; 427*b45b5bacSMarek Vasut mmio_write_32(DBSC4_REG_DBCMD, reg); 428*b45b5bacSMarek Vasut 429*b45b5bacSMarek Vasut /* Wait to complete PD operation */ 430*b45b5bacSMarek Vasut while (mmio_read_32(DBSC4_REG_DBWAIT) != 0) 431*b45b5bacSMarek Vasut ; 432*b45b5bacSMarek Vasut 433*b45b5bacSMarek Vasut /* Issue set the Auto-Refresh Enable register */ 434*b45b5bacSMarek Vasut /* to stop the auto-refresh function */ 435*b45b5bacSMarek Vasut mmio_write_32(DBSC4_REG_DBRFEN, 0); 436*b45b5bacSMarek Vasut 437*b45b5bacSMarek Vasut /* Dummy read DBWAIT register to wait tCKELPD time */ 438*b45b5bacSMarek Vasut (void)mmio_read_32(DBSC4_REG_DBWAIT); 439*b45b5bacSMarek Vasut 440*b45b5bacSMarek Vasut /* Disable DBSC4 register access */ 441*b45b5bacSMarek Vasut mmio_write_32(DBSC4_REG_DBSYSCNT0, DBSC4_SET_DBSYSCNT0_WRITE_DISABLE); 442*b45b5bacSMarek Vasut } 443*b45b5bacSMarek Vasut 444*b45b5bacSMarek Vasut static void __section(".system_ram") __attribute__ ((noinline)) 445*b45b5bacSMarek Vasut rcar_pwrc_go_suspend_to_ram(void) 446*b45b5bacSMarek Vasut { 447*b45b5bacSMarek Vasut rcar_scmi_sys_suspend(); 448*b45b5bacSMarek Vasut rcar_pwrc_set_self_refresh(); 449*b45b5bacSMarek Vasut 450*b45b5bacSMarek Vasut wfi(); 451*b45b5bacSMarek Vasut 452*b45b5bacSMarek Vasut /* Do not return */ 453*b45b5bacSMarek Vasut while (true) 454*b45b5bacSMarek Vasut ; 455*b45b5bacSMarek Vasut } 456*b45b5bacSMarek Vasut 457*b45b5bacSMarek Vasut void rcar_pwrc_suspend_to_ram(void) 458*b45b5bacSMarek Vasut { 459*b45b5bacSMarek Vasut uintptr_t jump = (uintptr_t) rcar_pwrc_go_suspend_to_ram; 460*b45b5bacSMarek Vasut uintptr_t stack = (uintptr_t) (DEVICE_SRAM_STACK_BASE + 461*b45b5bacSMarek Vasut DEVICE_SRAM_STACK_SIZE); 462*b45b5bacSMarek Vasut 463*b45b5bacSMarek Vasut rcar_pwrc_save_timer_state(); 464*b45b5bacSMarek Vasut 465*b45b5bacSMarek Vasut /* Clear code copy state to execute copy on next boot time */ 466*b45b5bacSMarek Vasut rcar_pwrc_code_copy_state = RCAR_CODE_COPY_NONE; 467*b45b5bacSMarek Vasut 468*b45b5bacSMarek Vasut /* disable MMU */ 469*b45b5bacSMarek Vasut disable_mmu_el3(); 470*b45b5bacSMarek Vasut 471*b45b5bacSMarek Vasut /* cache flush */ 472*b45b5bacSMarek Vasut dcsw_op_all(DCCISW); 473*b45b5bacSMarek Vasut 474*b45b5bacSMarek Vasut (void)rcar_pwrc_switch_stack(jump, stack, NULL); 475*b45b5bacSMarek Vasut } 476*b45b5bacSMarek Vasut 477*b45b5bacSMarek Vasut void rcar_pwrc_code_copy_to_system_ram(void) 478*b45b5bacSMarek Vasut { 479*b45b5bacSMarek Vasut int __maybe_unused ret; 480*b45b5bacSMarek Vasut uint32_t attr; 481*b45b5bacSMarek Vasut struct { 482*b45b5bacSMarek Vasut uintptr_t base; 483*b45b5bacSMarek Vasut size_t len; 484*b45b5bacSMarek Vasut } sram = { 485*b45b5bacSMarek Vasut .base = (uintptr_t) DEVICE_SRAM_BASE, 486*b45b5bacSMarek Vasut .len = DEVICE_SRAM_SIZE 487*b45b5bacSMarek Vasut }, code = { 488*b45b5bacSMarek Vasut .base = (uintptr_t) SRAM_COPY_START, 489*b45b5bacSMarek Vasut .len = (size_t)(SYSTEM_RAM_END - SYSTEM_RAM_START) 490*b45b5bacSMarek Vasut }; 491*b45b5bacSMarek Vasut 492*b45b5bacSMarek Vasut /* 493*b45b5bacSMarek Vasut * The copy of the code should only be executed for ColdBoot, 494*b45b5bacSMarek Vasut * and for WarmBoot from SuspendToRAM. 495*b45b5bacSMarek Vasut */ 496*b45b5bacSMarek Vasut if (rcar_pwrc_code_copy_state == RCAR_CODE_COPY_DONE) { 497*b45b5bacSMarek Vasut /* No need to run because it has already been copied */ 498*b45b5bacSMarek Vasut return; 499*b45b5bacSMarek Vasut } 500*b45b5bacSMarek Vasut 501*b45b5bacSMarek Vasut rcar_pwrc_code_copy_state = RCAR_CODE_COPY_DONE; 502*b45b5bacSMarek Vasut flush_dcache_range((uintptr_t)(&rcar_pwrc_code_copy_state), 503*b45b5bacSMarek Vasut sizeof(rcar_pwrc_code_copy_state)); 504*b45b5bacSMarek Vasut 505*b45b5bacSMarek Vasut attr = MT_MEMORY | MT_RW | MT_SECURE | MT_EXECUTE_NEVER; 506*b45b5bacSMarek Vasut ret = xlat_change_mem_attributes(sram.base, sram.len, attr); 507*b45b5bacSMarek Vasut assert(ret == 0); 508*b45b5bacSMarek Vasut 509*b45b5bacSMarek Vasut (void)memcpy((void *)sram.base, (void *)code.base, code.len); 510*b45b5bacSMarek Vasut flush_dcache_range(sram.base, code.len); 511*b45b5bacSMarek Vasut 512*b45b5bacSMarek Vasut /* Invalidate instruction cache */ 513*b45b5bacSMarek Vasut plat_invalidate_icache(); 514*b45b5bacSMarek Vasut dsb(); 515*b45b5bacSMarek Vasut isb(); 516*b45b5bacSMarek Vasut 517*b45b5bacSMarek Vasut attr = MT_MEMORY | MT_RO | MT_SECURE | MT_EXECUTE; 518*b45b5bacSMarek Vasut ret = xlat_change_mem_attributes(sram.base, sram.len, attr); 519*b45b5bacSMarek Vasut assert(ret == 0); 520*b45b5bacSMarek Vasut 521*b45b5bacSMarek Vasut /* clean up data and stack area in system ram */ 522*b45b5bacSMarek Vasut (void)memset((void *)DEVICE_SRAM_DATA_BASE, 0x0, 523*b45b5bacSMarek Vasut DEVICE_SRAM_DATA_SIZE + DEVICE_SRAM_STACK_SIZE); 524*b45b5bacSMarek Vasut flush_dcache_range((uintptr_t)DEVICE_SRAM_DATA_BASE, 525*b45b5bacSMarek Vasut DEVICE_SRAM_DATA_SIZE + DEVICE_SRAM_STACK_SIZE); 526*b45b5bacSMarek Vasut } 527