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