1c40739a6SBiju Das /* 20dae56bbSToshiyuki Ogasahara * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. 3c40739a6SBiju Das * 4c40739a6SBiju Das * SPDX-License-Identifier: BSD-3-Clause 5c40739a6SBiju Das */ 6c40739a6SBiju Das 7c40739a6SBiju Das #include <assert.h> 8c40739a6SBiju Das #include <string.h> 9c40739a6SBiju Das 10c40739a6SBiju Das #include <arch.h> 11c40739a6SBiju Das #include <arch_helpers.h> 12c40739a6SBiju Das #include <common/debug.h> 13c40739a6SBiju Das #include <lib/bakery_lock.h> 14c40739a6SBiju Das #include <lib/mmio.h> 15c40739a6SBiju Das #include <lib/xlat_tables/xlat_tables_v2.h> 16c40739a6SBiju Das #include <plat/common/platform.h> 17c40739a6SBiju Das 18c40739a6SBiju Das #include "iic_dvfs.h" 19c40739a6SBiju Das #include "micro_delay.h" 20c40739a6SBiju Das #include "pwrc.h" 21c40739a6SBiju Das #include "rcar_def.h" 22c40739a6SBiju Das #include "rcar_private.h" 230dae56bbSToshiyuki Ogasahara #include "cpg_registers.h" 24c40739a6SBiju Das 25c40739a6SBiju Das /* 26c40739a6SBiju Das * Someday there will be a generic power controller api. At the moment each 27c40739a6SBiju Das * platform has its own pwrc so just exporting functions should be acceptable. 28c40739a6SBiju Das */ 29c40739a6SBiju Das RCAR_INSTANTIATE_LOCK 30c40739a6SBiju Das 31c40739a6SBiju Das #define WUP_IRQ_SHIFT (0U) 32c40739a6SBiju Das #define WUP_FIQ_SHIFT (8U) 33c40739a6SBiju Das #define WUP_CSD_SHIFT (16U) 34c40739a6SBiju Das #define BIT_SOFTRESET (1U << 15) 35c40739a6SBiju Das #define BIT_CA53_SCU (1U << 21) 36c40739a6SBiju Das #define BIT_CA57_SCU (1U << 12) 37c40739a6SBiju Das #define REQ_RESUME (1U << 1) 38c40739a6SBiju Das #define REQ_OFF (1U << 0) 39c40739a6SBiju Das #define STATUS_PWRUP (1U << 4) 40c40739a6SBiju Das #define STATUS_PWRDOWN (1U << 0) 41c40739a6SBiju Das #define STATE_CA57_CPU (27U) 42c40739a6SBiju Das #define STATE_CA53_CPU (22U) 43c40739a6SBiju Das #define MODE_L2_DOWN (0x00000002U) 44c40739a6SBiju Das #define CPU_PWR_OFF (0x00000003U) 45c40739a6SBiju Das #define RCAR_PSTR_MASK (0x00000003U) 46c40739a6SBiju Das #define ST_ALL_STANDBY (0x00003333U) 4763a7a347SToshiyuki Ogasahara #define SYSCEXTMASK_EXTMSK0 (0x00000001U) 48c40739a6SBiju Das /* Suspend to ram */ 49c40739a6SBiju Das #define DBSC4_REG_BASE (0xE6790000U) 50c40739a6SBiju Das #define DBSC4_REG_DBSYSCNT0 (DBSC4_REG_BASE + 0x0100U) 51c40739a6SBiju Das #define DBSC4_REG_DBACEN (DBSC4_REG_BASE + 0x0200U) 52c40739a6SBiju Das #define DBSC4_REG_DBCMD (DBSC4_REG_BASE + 0x0208U) 53c40739a6SBiju Das #define DBSC4_REG_DBRFEN (DBSC4_REG_BASE + 0x0204U) 54c40739a6SBiju Das #define DBSC4_REG_DBWAIT (DBSC4_REG_BASE + 0x0210U) 55c40739a6SBiju Das #define DBSC4_REG_DBCALCNF (DBSC4_REG_BASE + 0x0424U) 56c40739a6SBiju Das #define DBSC4_REG_DBDFIPMSTRCNF (DBSC4_REG_BASE + 0x0520U) 57c40739a6SBiju Das #define DBSC4_REG_DBPDLK0 (DBSC4_REG_BASE + 0x0620U) 58c40739a6SBiju Das #define DBSC4_REG_DBPDRGA0 (DBSC4_REG_BASE + 0x0624U) 59c40739a6SBiju Das #define DBSC4_REG_DBPDRGD0 (DBSC4_REG_BASE + 0x0628U) 60c40739a6SBiju Das #define DBSC4_REG_DBCAM0CTRL0 (DBSC4_REG_BASE + 0x0940U) 61c40739a6SBiju Das #define DBSC4_REG_DBCAM0STAT0 (DBSC4_REG_BASE + 0x0980U) 62c40739a6SBiju Das #define DBSC4_REG_DBCAM1STAT0 (DBSC4_REG_BASE + 0x0990U) 63c40739a6SBiju Das #define DBSC4_REG_DBCAM2STAT0 (DBSC4_REG_BASE + 0x09A0U) 64c40739a6SBiju Das #define DBSC4_REG_DBCAM3STAT0 (DBSC4_REG_BASE + 0x09B0U) 65c40739a6SBiju Das #define DBSC4_BIT_DBACEN_ACCEN ((uint32_t)(1U << 0)) 66c40739a6SBiju Das #define DBSC4_BIT_DBRFEN_ARFEN ((uint32_t)(1U << 0)) 67c40739a6SBiju Das #define DBSC4_BIT_DBCAMxSTAT0 (0x00000001U) 68c40739a6SBiju Das #define DBSC4_BIT_DBDFIPMSTRCNF_PMSTREN (0x00000001U) 69c40739a6SBiju Das #define DBSC4_SET_DBCMD_OPC_PRE (0x04000000U) 70c40739a6SBiju Das #define DBSC4_SET_DBCMD_OPC_SR (0x0A000000U) 71c40739a6SBiju Das #define DBSC4_SET_DBCMD_OPC_PD (0x08000000U) 72c40739a6SBiju Das #define DBSC4_SET_DBCMD_OPC_MRW (0x0E000000U) 73c40739a6SBiju Das #define DBSC4_SET_DBCMD_CH_ALL (0x00800000U) 74c40739a6SBiju Das #define DBSC4_SET_DBCMD_RANK_ALL (0x00040000U) 75c40739a6SBiju Das #define DBSC4_SET_DBCMD_ARG_ALL (0x00000010U) 76c40739a6SBiju Das #define DBSC4_SET_DBCMD_ARG_ENTER (0x00000000U) 77c40739a6SBiju Das #define DBSC4_SET_DBCMD_ARG_MRW_ODTC (0x00000B00U) 78c40739a6SBiju Das #define DBSC4_SET_DBSYSCNT0_WRITE_ENABLE (0x00001234U) 79c40739a6SBiju Das #define DBSC4_SET_DBSYSCNT0_WRITE_DISABLE (0x00000000U) 80c40739a6SBiju Das #define DBSC4_SET_DBPDLK0_PHY_ACCESS (0x0000A55AU) 81c40739a6SBiju Das #define DBSC4_SET_DBPDRGA0_ACIOCR0 (0x0000001AU) 82c40739a6SBiju Das #define DBSC4_SET_DBPDRGD0_ACIOCR0 (0x33C03C11U) 83c40739a6SBiju Das #define DBSC4_SET_DBPDRGA0_DXCCR (0x00000020U) 84c40739a6SBiju Das #define DBSC4_SET_DBPDRGD0_DXCCR (0x00181006U) 85c40739a6SBiju Das #define DBSC4_SET_DBPDRGA0_PGCR1 (0x00000003U) 86c40739a6SBiju Das #define DBSC4_SET_DBPDRGD0_PGCR1 (0x0380C600U) 87c40739a6SBiju Das #define DBSC4_SET_DBPDRGA0_ACIOCR1 (0x0000001BU) 88c40739a6SBiju Das #define DBSC4_SET_DBPDRGD0_ACIOCR1 (0xAAAAAAAAU) 89c40739a6SBiju Das #define DBSC4_SET_DBPDRGA0_ACIOCR3 (0x0000001DU) 90c40739a6SBiju Das #define DBSC4_SET_DBPDRGD0_ACIOCR3 (0xAAAAAAAAU) 91c40739a6SBiju Das #define DBSC4_SET_DBPDRGA0_ACIOCR5 (0x0000001FU) 92c40739a6SBiju Das #define DBSC4_SET_DBPDRGD0_ACIOCR5 (0x000000AAU) 93c40739a6SBiju Das #define DBSC4_SET_DBPDRGA0_DX0GCR2 (0x000000A2U) 94c40739a6SBiju Das #define DBSC4_SET_DBPDRGD0_DX0GCR2 (0xAAAA0000U) 95c40739a6SBiju Das #define DBSC4_SET_DBPDRGA0_DX1GCR2 (0x000000C2U) 96c40739a6SBiju Das #define DBSC4_SET_DBPDRGD0_DX1GCR2 (0xAAAA0000U) 97c40739a6SBiju Das #define DBSC4_SET_DBPDRGA0_DX2GCR2 (0x000000E2U) 98c40739a6SBiju Das #define DBSC4_SET_DBPDRGD0_DX2GCR2 (0xAAAA0000U) 99c40739a6SBiju Das #define DBSC4_SET_DBPDRGA0_DX3GCR2 (0x00000102U) 100c40739a6SBiju Das #define DBSC4_SET_DBPDRGD0_DX3GCR2 (0xAAAA0000U) 101c40739a6SBiju Das #define DBSC4_SET_DBPDRGA0_ZQCR (0x00000090U) 102c40739a6SBiju Das #define DBSC4_SET_DBPDRGD0_ZQCR_MD19_0 (0x04058904U) 103c40739a6SBiju Das #define DBSC4_SET_DBPDRGD0_ZQCR_MD19_1 (0x04058A04U) 104c40739a6SBiju Das #define DBSC4_SET_DBPDRGA0_DX0GCR0 (0x000000A0U) 105c40739a6SBiju Das #define DBSC4_SET_DBPDRGD0_DX0GCR0 (0x7C0002E5U) 106c40739a6SBiju Das #define DBSC4_SET_DBPDRGA0_DX1GCR0 (0x000000C0U) 107c40739a6SBiju Das #define DBSC4_SET_DBPDRGD0_DX1GCR0 (0x7C0002E5U) 108c40739a6SBiju Das #define DBSC4_SET_DBPDRGA0_DX2GCR0 (0x000000E0U) 109c40739a6SBiju Das #define DBSC4_SET_DBPDRGD0_DX2GCR0 (0x7C0002E5U) 110c40739a6SBiju Das #define DBSC4_SET_DBPDRGA0_DX3GCR0 (0x00000100U) 111c40739a6SBiju Das #define DBSC4_SET_DBPDRGD0_DX3GCR0 (0x7C0002E5U) 112c40739a6SBiju Das #define DBSC4_SET_DBPDRGA0_DX0GCR1 (0x000000A1U) 113c40739a6SBiju Das #define DBSC4_SET_DBPDRGD0_DX0GCR1 (0x55550000U) 114c40739a6SBiju Das #define DBSC4_SET_DBPDRGA0_DX1GCR1 (0x000000C1U) 115c40739a6SBiju Das #define DBSC4_SET_DBPDRGD0_DX1GCR1 (0x55550000U) 116c40739a6SBiju Das #define DBSC4_SET_DBPDRGA0_DX2GCR1 (0x000000E1U) 117c40739a6SBiju Das #define DBSC4_SET_DBPDRGD0_DX2GCR1 (0x55550000U) 118c40739a6SBiju Das #define DBSC4_SET_DBPDRGA0_DX3GCR1 (0x00000101U) 119c40739a6SBiju Das #define DBSC4_SET_DBPDRGD0_DX3GCR1 (0x55550000U) 120c40739a6SBiju Das #define DBSC4_SET_DBPDRGA0_DX0GCR3 (0x000000A3U) 121c40739a6SBiju Das #define DBSC4_SET_DBPDRGD0_DX0GCR3 (0x00008484U) 122c40739a6SBiju Das #define DBSC4_SET_DBPDRGA0_DX1GCR3 (0x000000C3U) 123c40739a6SBiju Das #define DBSC4_SET_DBPDRGD0_DX1GCR3 (0x00008484U) 124c40739a6SBiju Das #define DBSC4_SET_DBPDRGA0_DX2GCR3 (0x000000E3U) 125c40739a6SBiju Das #define DBSC4_SET_DBPDRGD0_DX2GCR3 (0x00008484U) 126c40739a6SBiju Das #define DBSC4_SET_DBPDRGA0_DX3GCR3 (0x00000103U) 127c40739a6SBiju Das #define DBSC4_SET_DBPDRGD0_DX3GCR3 (0x00008484U) 128c40739a6SBiju Das #define RST_BASE (0xE6160000U) 129c40739a6SBiju Das #define RST_MODEMR (RST_BASE + 0x0060U) 130c40739a6SBiju Das #define RST_MODEMR_BIT0 (0x00000001U) 131c40739a6SBiju Das 132c40739a6SBiju Das #define RCAR_CNTCR_OFF (0x00U) 133c40739a6SBiju Das #define RCAR_CNTCVL_OFF (0x08U) 134c40739a6SBiju Das #define RCAR_CNTCVU_OFF (0x0CU) 135c40739a6SBiju Das #define RCAR_CNTFID_OFF (0x20U) 136c40739a6SBiju Das 137c40739a6SBiju Das #define RCAR_CNTCR_EN ((uint32_t)1U << 0U) 138c40739a6SBiju Das #define RCAR_CNTCR_FCREQ(x) ((uint32_t)(x) << 8U) 139c40739a6SBiju Das 140c40739a6SBiju Das #if PMIC_ROHM_BD9571 141c40739a6SBiju Das #define BIT_BKUP_CTRL_OUT ((uint8_t)(1U << 4)) 142c40739a6SBiju Das #define PMIC_BKUP_MODE_CNT (0x20U) 143c40739a6SBiju Das #define PMIC_QLLM_CNT (0x27U) 144c40739a6SBiju Das #define PMIC_RETRY_MAX (100U) 145c40739a6SBiju Das #endif /* PMIC_ROHM_BD9571 */ 146c40739a6SBiju Das #define SCTLR_EL3_M_BIT ((uint32_t)1U << 0) 147c40739a6SBiju Das #define RCAR_CA53CPU_NUM_MAX (4U) 148c40739a6SBiju Das #define RCAR_CA57CPU_NUM_MAX (4U) 149c40739a6SBiju Das #define IS_A53A57(c) ((c) == RCAR_CLUSTER_A53A57) 150c40739a6SBiju Das #define IS_CA57(c) ((c) == RCAR_CLUSTER_CA57) 151c40739a6SBiju Das #define IS_CA53(c) ((c) == RCAR_CLUSTER_CA53) 152c40739a6SBiju Das 153c40739a6SBiju Das #ifndef __ASSEMBLER__ 154c40739a6SBiju Das IMPORT_SYM(unsigned long, __system_ram_start__, SYSTEM_RAM_START); 155c40739a6SBiju Das IMPORT_SYM(unsigned long, __system_ram_end__, SYSTEM_RAM_END); 156c40739a6SBiju Das IMPORT_SYM(unsigned long, __SRAM_COPY_START__, SRAM_COPY_START); 157c40739a6SBiju Das #endif 158c40739a6SBiju Das 159c40739a6SBiju Das uint32_t rcar_pwrc_status(uint64_t mpidr) 160c40739a6SBiju Das { 161c40739a6SBiju Das uint32_t ret = 0; 162c40739a6SBiju Das uint64_t cm, cpu; 163c40739a6SBiju Das uint32_t reg; 164c40739a6SBiju Das uint32_t c; 165c40739a6SBiju Das 166c40739a6SBiju Das rcar_lock_get(); 167c40739a6SBiju Das 168c40739a6SBiju Das c = rcar_pwrc_get_cluster(); 169c40739a6SBiju Das cm = mpidr & MPIDR_CLUSTER_MASK; 170c40739a6SBiju Das 171c40739a6SBiju Das if (!IS_A53A57(c) && cm != 0) { 172c40739a6SBiju Das ret = RCAR_INVALID; 173c40739a6SBiju Das goto done; 174c40739a6SBiju Das } 175c40739a6SBiju Das 176c40739a6SBiju Das reg = mmio_read_32(RCAR_PRR); 177c40739a6SBiju Das cpu = mpidr & MPIDR_CPU_MASK; 178c40739a6SBiju Das 179c40739a6SBiju Das if (IS_CA53(c)) 180c40739a6SBiju Das if (reg & (1 << (STATE_CA53_CPU + cpu))) 181c40739a6SBiju Das ret = RCAR_INVALID; 182c40739a6SBiju Das if (IS_CA57(c)) 183c40739a6SBiju Das if (reg & (1 << (STATE_CA57_CPU + cpu))) 184c40739a6SBiju Das ret = RCAR_INVALID; 185c40739a6SBiju Das done: 186c40739a6SBiju Das rcar_lock_release(); 187c40739a6SBiju Das 188c40739a6SBiju Das return ret; 189c40739a6SBiju Das } 190c40739a6SBiju Das 191c40739a6SBiju Das static void scu_power_up(uint64_t mpidr) 192c40739a6SBiju Das { 193c40739a6SBiju Das uintptr_t reg_pwrsr, reg_cpumcr, reg_pwron, reg_pwrer; 194c40739a6SBiju Das uint32_t c, sysc_reg_bit; 19563a7a347SToshiyuki Ogasahara uint32_t lsi_product; 19663a7a347SToshiyuki Ogasahara uint32_t lsi_cut; 197c40739a6SBiju Das 198c40739a6SBiju Das c = rcar_pwrc_get_mpidr_cluster(mpidr); 199c40739a6SBiju Das reg_cpumcr = IS_CA57(c) ? RCAR_CA57CPUCMCR : RCAR_CA53CPUCMCR; 200c40739a6SBiju Das sysc_reg_bit = IS_CA57(c) ? BIT_CA57_SCU : BIT_CA53_SCU; 201c40739a6SBiju Das reg_pwron = IS_CA57(c) ? RCAR_PWRONCR5 : RCAR_PWRONCR3; 202c40739a6SBiju Das reg_pwrer = IS_CA57(c) ? RCAR_PWRER5 : RCAR_PWRER3; 203c40739a6SBiju Das reg_pwrsr = IS_CA57(c) ? RCAR_PWRSR5 : RCAR_PWRSR3; 204c40739a6SBiju Das 205c40739a6SBiju Das if ((mmio_read_32(reg_pwrsr) & STATUS_PWRDOWN) == 0) 206c40739a6SBiju Das return; 207c40739a6SBiju Das 208c40739a6SBiju Das if (mmio_read_32(reg_cpumcr) != 0) 209c40739a6SBiju Das mmio_write_32(reg_cpumcr, 0); 210c40739a6SBiju Das 21163a7a347SToshiyuki Ogasahara lsi_product = mmio_read_32((uintptr_t)RCAR_PRR); 21263a7a347SToshiyuki Ogasahara lsi_cut = lsi_product & PRR_CUT_MASK; 21363a7a347SToshiyuki Ogasahara lsi_product &= PRR_PRODUCT_MASK; 21463a7a347SToshiyuki Ogasahara 21563a7a347SToshiyuki Ogasahara if ((lsi_product == PRR_PRODUCT_M3 && lsi_cut >= PRR_PRODUCT_30) || 21663a7a347SToshiyuki Ogasahara lsi_product == PRR_PRODUCT_H3 || 21763a7a347SToshiyuki Ogasahara lsi_product == PRR_PRODUCT_M3N || 21863a7a347SToshiyuki Ogasahara lsi_product == PRR_PRODUCT_E3) { 21963a7a347SToshiyuki Ogasahara mmio_setbits_32(RCAR_SYSCEXTMASK, SYSCEXTMASK_EXTMSK0); 22063a7a347SToshiyuki Ogasahara } 22163a7a347SToshiyuki Ogasahara 222c40739a6SBiju Das mmio_setbits_32(RCAR_SYSCIER, sysc_reg_bit); 223c40739a6SBiju Das mmio_setbits_32(RCAR_SYSCIMR, sysc_reg_bit); 224c40739a6SBiju Das 225c40739a6SBiju Das do { 226c40739a6SBiju Das while ((mmio_read_32(RCAR_SYSCSR) & REQ_RESUME) == 0) 227c40739a6SBiju Das ; 228c40739a6SBiju Das mmio_write_32(reg_pwron, 1); 229c40739a6SBiju Das } while (mmio_read_32(reg_pwrer) & 1); 230c40739a6SBiju Das 231c40739a6SBiju Das while ((mmio_read_32(RCAR_SYSCISR) & sysc_reg_bit) == 0) 232c40739a6SBiju Das ; 233*d10f8767SToshiyuki Ogasahara mmio_write_32(RCAR_SYSCISCR, sysc_reg_bit); 23463a7a347SToshiyuki Ogasahara 23563a7a347SToshiyuki Ogasahara if ((lsi_product == PRR_PRODUCT_M3 && lsi_cut >= PRR_PRODUCT_30) || 23663a7a347SToshiyuki Ogasahara lsi_product == PRR_PRODUCT_H3 || 23763a7a347SToshiyuki Ogasahara lsi_product == PRR_PRODUCT_M3N || 23863a7a347SToshiyuki Ogasahara lsi_product == PRR_PRODUCT_E3) { 23963a7a347SToshiyuki Ogasahara mmio_clrbits_32(RCAR_SYSCEXTMASK, SYSCEXTMASK_EXTMSK0); 24063a7a347SToshiyuki Ogasahara } 24163a7a347SToshiyuki Ogasahara 242c40739a6SBiju Das while ((mmio_read_32(reg_pwrsr) & STATUS_PWRUP) == 0) 243c40739a6SBiju Das ; 244c40739a6SBiju Das } 245c40739a6SBiju Das 246c40739a6SBiju Das void rcar_pwrc_cpuon(uint64_t mpidr) 247c40739a6SBiju Das { 248c40739a6SBiju Das uint32_t res_data, on_data; 249c40739a6SBiju Das uintptr_t res_reg, on_reg; 250c40739a6SBiju Das uint32_t limit, c; 251c40739a6SBiju Das uint64_t cpu; 252c40739a6SBiju Das 253c40739a6SBiju Das rcar_lock_get(); 254c40739a6SBiju Das 255c40739a6SBiju Das c = rcar_pwrc_get_mpidr_cluster(mpidr); 256c40739a6SBiju Das res_reg = IS_CA53(c) ? RCAR_CA53RESCNT : RCAR_CA57RESCNT; 257c40739a6SBiju Das on_reg = IS_CA53(c) ? RCAR_CA53WUPCR : RCAR_CA57WUPCR; 258c40739a6SBiju Das limit = IS_CA53(c) ? 0x5A5A0000 : 0xA5A50000; 259c40739a6SBiju Das 260c40739a6SBiju Das res_data = mmio_read_32(res_reg) | limit; 261c40739a6SBiju Das scu_power_up(mpidr); 262c40739a6SBiju Das cpu = mpidr & MPIDR_CPU_MASK; 263c40739a6SBiju Das on_data = 1 << cpu; 2640dae56bbSToshiyuki Ogasahara mmio_write_32(CPG_CPGWPR, ~on_data); 265c40739a6SBiju Das mmio_write_32(on_reg, on_data); 266c40739a6SBiju Das mmio_write_32(res_reg, res_data & (~(1 << (3 - cpu)))); 267c40739a6SBiju Das 268c40739a6SBiju Das rcar_lock_release(); 269c40739a6SBiju Das } 270c40739a6SBiju Das 271c40739a6SBiju Das void rcar_pwrc_cpuoff(uint64_t mpidr) 272c40739a6SBiju Das { 273c40739a6SBiju Das uint32_t c; 274c40739a6SBiju Das uintptr_t reg; 275c40739a6SBiju Das uint64_t cpu; 276c40739a6SBiju Das 277c40739a6SBiju Das rcar_lock_get(); 278c40739a6SBiju Das 279c40739a6SBiju Das cpu = mpidr & MPIDR_CPU_MASK; 280c40739a6SBiju Das c = rcar_pwrc_get_mpidr_cluster(mpidr); 281c40739a6SBiju Das reg = IS_CA53(c) ? RCAR_CA53CPU0CR : RCAR_CA57CPU0CR; 282c40739a6SBiju Das 283c40739a6SBiju Das if (read_mpidr_el1() != mpidr) 284c40739a6SBiju Das panic(); 285c40739a6SBiju Das 2860dae56bbSToshiyuki Ogasahara mmio_write_32(CPG_CPGWPR, ~CPU_PWR_OFF); 287c40739a6SBiju Das mmio_write_32(reg + cpu * 0x0010, CPU_PWR_OFF); 288c40739a6SBiju Das 289c40739a6SBiju Das rcar_lock_release(); 290c40739a6SBiju Das } 291c40739a6SBiju Das 292c40739a6SBiju Das void rcar_pwrc_enable_interrupt_wakeup(uint64_t mpidr) 293c40739a6SBiju Das { 294c40739a6SBiju Das uint32_t c, shift_irq, shift_fiq; 295c40739a6SBiju Das uintptr_t reg; 296c40739a6SBiju Das uint64_t cpu; 297c40739a6SBiju Das 298c40739a6SBiju Das rcar_lock_get(); 299c40739a6SBiju Das 300c40739a6SBiju Das cpu = mpidr & MPIDR_CPU_MASK; 301c40739a6SBiju Das c = rcar_pwrc_get_mpidr_cluster(mpidr); 302c40739a6SBiju Das reg = IS_CA53(c) ? RCAR_WUPMSKCA53 : RCAR_WUPMSKCA57; 303c40739a6SBiju Das 304c40739a6SBiju Das shift_irq = WUP_IRQ_SHIFT + cpu; 305c40739a6SBiju Das shift_fiq = WUP_FIQ_SHIFT + cpu; 306c40739a6SBiju Das 307c40739a6SBiju Das mmio_write_32(reg, ~((uint32_t) 1 << shift_irq) & 308c40739a6SBiju Das ~((uint32_t) 1 << shift_fiq)); 309c40739a6SBiju Das rcar_lock_release(); 310c40739a6SBiju Das } 311c40739a6SBiju Das 312c40739a6SBiju Das void rcar_pwrc_disable_interrupt_wakeup(uint64_t mpidr) 313c40739a6SBiju Das { 314c40739a6SBiju Das uint32_t c, shift_irq, shift_fiq; 315c40739a6SBiju Das uintptr_t reg; 316c40739a6SBiju Das uint64_t cpu; 317c40739a6SBiju Das 318c40739a6SBiju Das rcar_lock_get(); 319c40739a6SBiju Das 320c40739a6SBiju Das cpu = mpidr & MPIDR_CPU_MASK; 321c40739a6SBiju Das c = rcar_pwrc_get_mpidr_cluster(mpidr); 322c40739a6SBiju Das reg = IS_CA53(c) ? RCAR_WUPMSKCA53 : RCAR_WUPMSKCA57; 323c40739a6SBiju Das 324c40739a6SBiju Das shift_irq = WUP_IRQ_SHIFT + cpu; 325c40739a6SBiju Das shift_fiq = WUP_FIQ_SHIFT + cpu; 326c40739a6SBiju Das 327c40739a6SBiju Das mmio_write_32(reg, ((uint32_t) 1 << shift_irq) | 328c40739a6SBiju Das ((uint32_t) 1 << shift_fiq)); 329c40739a6SBiju Das rcar_lock_release(); 330c40739a6SBiju Das } 331c40739a6SBiju Das 332c40739a6SBiju Das void rcar_pwrc_clusteroff(uint64_t mpidr) 333c40739a6SBiju Das { 334c40739a6SBiju Das uint32_t c, product, cut, reg; 335c40739a6SBiju Das uintptr_t dst; 336c40739a6SBiju Das 337c40739a6SBiju Das rcar_lock_get(); 338c40739a6SBiju Das 339c40739a6SBiju Das reg = mmio_read_32(RCAR_PRR); 340c40739a6SBiju Das product = reg & PRR_PRODUCT_MASK; 341c40739a6SBiju Das cut = reg & PRR_CUT_MASK; 342c40739a6SBiju Das 343c40739a6SBiju Das c = rcar_pwrc_get_mpidr_cluster(mpidr); 344c40739a6SBiju Das dst = IS_CA53(c) ? RCAR_CA53CPUCMCR : RCAR_CA57CPUCMCR; 345c40739a6SBiju Das 346c40739a6SBiju Das if (product == PRR_PRODUCT_M3 && cut < PRR_PRODUCT_30) { 347c40739a6SBiju Das goto done; 348c40739a6SBiju Das } 349c40739a6SBiju Das 350c40739a6SBiju Das if (product == PRR_PRODUCT_H3 && cut <= PRR_PRODUCT_20) { 351c40739a6SBiju Das goto done; 352c40739a6SBiju Das } 353c40739a6SBiju Das 354c40739a6SBiju Das /* all of the CPUs in the cluster is in the CoreStandby mode */ 355c40739a6SBiju Das mmio_write_32(dst, MODE_L2_DOWN); 356c40739a6SBiju Das done: 357c40739a6SBiju Das rcar_lock_release(); 358c40739a6SBiju Das } 359c40739a6SBiju Das 360c40739a6SBiju Das static uint64_t rcar_pwrc_saved_cntpct_el0; 361c40739a6SBiju Das static uint32_t rcar_pwrc_saved_cntfid; 362c40739a6SBiju Das 363c40739a6SBiju Das #if RCAR_SYSTEM_SUSPEND 364c40739a6SBiju Das static void rcar_pwrc_save_timer_state(void) 365c40739a6SBiju Das { 366c40739a6SBiju Das rcar_pwrc_saved_cntpct_el0 = read_cntpct_el0(); 367c40739a6SBiju Das 368c40739a6SBiju Das rcar_pwrc_saved_cntfid = 369c40739a6SBiju Das mmio_read_32((uintptr_t)(RCAR_CNTC_BASE + RCAR_CNTFID_OFF)); 370c40739a6SBiju Das } 371c40739a6SBiju Das #endif /* RCAR_SYSTEM_SUSPEND */ 372c40739a6SBiju Das 373c40739a6SBiju Das void rcar_pwrc_restore_timer_state(void) 374c40739a6SBiju Das { 375c40739a6SBiju Das /* Stop timer before restoring counter value */ 376c40739a6SBiju Das mmio_write_32((uintptr_t)(RCAR_CNTC_BASE + RCAR_CNTCR_OFF), 0U); 377c40739a6SBiju Das 378c40739a6SBiju Das mmio_write_32((uintptr_t)(RCAR_CNTC_BASE + RCAR_CNTCVL_OFF), 379c40739a6SBiju Das (uint32_t)(rcar_pwrc_saved_cntpct_el0 & 0xFFFFFFFFU)); 380c40739a6SBiju Das mmio_write_32((uintptr_t)(RCAR_CNTC_BASE + RCAR_CNTCVU_OFF), 381c40739a6SBiju Das (uint32_t)(rcar_pwrc_saved_cntpct_el0 >> 32U)); 382c40739a6SBiju Das 383c40739a6SBiju Das mmio_write_32((uintptr_t)(RCAR_CNTC_BASE + RCAR_CNTFID_OFF), 384c40739a6SBiju Das rcar_pwrc_saved_cntfid); 385c40739a6SBiju Das 386c40739a6SBiju Das /* Start generic timer back */ 387c40739a6SBiju Das write_cntfrq_el0((u_register_t)plat_get_syscnt_freq2()); 388c40739a6SBiju Das 389c40739a6SBiju Das mmio_write_32((uintptr_t)(RCAR_CNTC_BASE + RCAR_CNTCR_OFF), 390c40739a6SBiju Das (RCAR_CNTCR_FCREQ(0U) | RCAR_CNTCR_EN)); 391c40739a6SBiju Das } 392c40739a6SBiju Das 393c40739a6SBiju Das #if !PMIC_ROHM_BD9571 394c40739a6SBiju Das void rcar_pwrc_system_reset(void) 395c40739a6SBiju Das { 396c40739a6SBiju Das mmio_write_32(RCAR_SRESCR, 0x5AA50000U | BIT_SOFTRESET); 397c40739a6SBiju Das } 398c40739a6SBiju Das #endif /* PMIC_ROHM_BD9571 */ 399c40739a6SBiju Das 400c40739a6SBiju Das #define RST_CA53_CPU0_BARH (0xE6160080U) 401c40739a6SBiju Das #define RST_CA53_CPU0_BARL (0xE6160084U) 402c40739a6SBiju Das #define RST_CA57_CPU0_BARH (0xE61600C0U) 403c40739a6SBiju Das #define RST_CA57_CPU0_BARL (0xE61600C4U) 404c40739a6SBiju Das 405c40739a6SBiju Das void rcar_pwrc_setup(void) 406c40739a6SBiju Das { 407c40739a6SBiju Das uintptr_t rst_barh; 408c40739a6SBiju Das uintptr_t rst_barl; 409c40739a6SBiju Das uint32_t i, j; 410c40739a6SBiju Das uint64_t reset = (uint64_t) (&plat_secondary_reset) & 0xFFFFFFFF; 411c40739a6SBiju Das 412c40739a6SBiju Das const uint32_t cluster[PLATFORM_CLUSTER_COUNT] = { 413c40739a6SBiju Das RCAR_CLUSTER_CA53, 414c40739a6SBiju Das RCAR_CLUSTER_CA57 415c40739a6SBiju Das }; 416c40739a6SBiju Das const uintptr_t reg_barh[PLATFORM_CLUSTER_COUNT] = { 417c40739a6SBiju Das RST_CA53_CPU0_BARH, 418c40739a6SBiju Das RST_CA57_CPU0_BARH 419c40739a6SBiju Das }; 420c40739a6SBiju Das const uintptr_t reg_barl[PLATFORM_CLUSTER_COUNT] = { 421c40739a6SBiju Das RST_CA53_CPU0_BARL, 422c40739a6SBiju Das RST_CA57_CPU0_BARL 423c40739a6SBiju Das }; 424c40739a6SBiju Das 425c40739a6SBiju Das for (i = 0; i < PLATFORM_CLUSTER_COUNT; i++) { 426c40739a6SBiju Das rst_barh = reg_barh[i]; 427c40739a6SBiju Das rst_barl = reg_barl[i]; 428c40739a6SBiju Das for (j = 0; j < rcar_pwrc_get_cpu_num(cluster[i]); j++) { 429c40739a6SBiju Das mmio_write_32(rst_barh, 0); 430c40739a6SBiju Das mmio_write_32(rst_barl, (uint32_t) reset); 431c40739a6SBiju Das rst_barh += 0x10; 432c40739a6SBiju Das rst_barl += 0x10; 433c40739a6SBiju Das } 434c40739a6SBiju Das } 435c40739a6SBiju Das 436c40739a6SBiju Das rcar_lock_init(); 437c40739a6SBiju Das } 438c40739a6SBiju Das 439c40739a6SBiju Das #if RCAR_SYSTEM_SUSPEND 440c40739a6SBiju Das #define DBCAM_FLUSH(__bit) \ 441c40739a6SBiju Das do { \ 442c40739a6SBiju Das ; \ 443c40739a6SBiju Das } while (!(mmio_read_32(DBSC4_REG_DBCAM##__bit##STAT0) & DBSC4_BIT_DBCAMxSTAT0)) 444c40739a6SBiju Das 445c40739a6SBiju Das 446c40739a6SBiju Das static void __attribute__ ((section(".system_ram"))) 447c40739a6SBiju Das rcar_pwrc_set_self_refresh(void) 448c40739a6SBiju Das { 449c40739a6SBiju Das uint32_t reg = mmio_read_32(RCAR_PRR); 450c40739a6SBiju Das uint32_t cut, product; 451c40739a6SBiju Das 452c40739a6SBiju Das product = reg & PRR_PRODUCT_MASK; 453c40739a6SBiju Das cut = reg & PRR_CUT_MASK; 454c40739a6SBiju Das 455c40739a6SBiju Das if (product == PRR_PRODUCT_M3 && cut < PRR_PRODUCT_30) { 456c40739a6SBiju Das goto self_refresh; 457c40739a6SBiju Das } 458c40739a6SBiju Das 459c40739a6SBiju Das if (product == PRR_PRODUCT_H3 && cut < PRR_PRODUCT_20) { 460c40739a6SBiju Das goto self_refresh; 461c40739a6SBiju Das } 462c40739a6SBiju Das 463c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBSYSCNT0, DBSC4_SET_DBSYSCNT0_WRITE_ENABLE); 464c40739a6SBiju Das 465c40739a6SBiju Das self_refresh: 466c40739a6SBiju Das 467c40739a6SBiju Das /* DFI_PHYMSTR_ACK setting */ 468c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBDFIPMSTRCNF, 469c40739a6SBiju Das mmio_read_32(DBSC4_REG_DBDFIPMSTRCNF) & 470c40739a6SBiju Das (~DBSC4_BIT_DBDFIPMSTRCNF_PMSTREN)); 471c40739a6SBiju Das 472c40739a6SBiju Das /* Set the Self-Refresh mode */ 473c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBACEN, 0); 474c40739a6SBiju Das 475c40739a6SBiju Das if (product == PRR_PRODUCT_H3 && cut < PRR_PRODUCT_20) 476c40739a6SBiju Das rcar_micro_delay(100); 477c40739a6SBiju Das else if (product == PRR_PRODUCT_H3) { 478c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 1); 479c40739a6SBiju Das DBCAM_FLUSH(0); 480c40739a6SBiju Das DBCAM_FLUSH(1); 481c40739a6SBiju Das DBCAM_FLUSH(2); 482c40739a6SBiju Das DBCAM_FLUSH(3); 483c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 0); 484c40739a6SBiju Das } else if (product == PRR_PRODUCT_M3) { 485c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 1); 486c40739a6SBiju Das DBCAM_FLUSH(0); 487c40739a6SBiju Das DBCAM_FLUSH(1); 488c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 0); 489c40739a6SBiju Das } else { 490c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 1); 491c40739a6SBiju Das DBCAM_FLUSH(0); 492c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 0); 493c40739a6SBiju Das } 494c40739a6SBiju Das 495c40739a6SBiju Das /* Set the SDRAM calibration configuration register */ 496c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBCALCNF, 0); 497c40739a6SBiju Das 498c40739a6SBiju Das reg = DBSC4_SET_DBCMD_OPC_PRE | DBSC4_SET_DBCMD_CH_ALL | 499c40739a6SBiju Das DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_ALL; 500c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBCMD, reg); 501c40739a6SBiju Das while (mmio_read_32(DBSC4_REG_DBWAIT)) 502c40739a6SBiju Das ; 503c40739a6SBiju Das 504c40739a6SBiju Das /* Self-Refresh entry command */ 505c40739a6SBiju Das reg = DBSC4_SET_DBCMD_OPC_SR | DBSC4_SET_DBCMD_CH_ALL | 506c40739a6SBiju Das DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_ENTER; 507c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBCMD, reg); 508c40739a6SBiju Das while (mmio_read_32(DBSC4_REG_DBWAIT)) 509c40739a6SBiju Das ; 510c40739a6SBiju Das 511c40739a6SBiju Das /* Mode Register Write command. (ODT disabled) */ 512c40739a6SBiju Das reg = DBSC4_SET_DBCMD_OPC_MRW | DBSC4_SET_DBCMD_CH_ALL | 513c40739a6SBiju Das DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_MRW_ODTC; 514c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBCMD, reg); 515c40739a6SBiju Das while (mmio_read_32(DBSC4_REG_DBWAIT)) 516c40739a6SBiju Das ; 517c40739a6SBiju Das 518c40739a6SBiju Das /* Power Down entry command */ 519c40739a6SBiju Das reg = DBSC4_SET_DBCMD_OPC_PD | DBSC4_SET_DBCMD_CH_ALL | 520c40739a6SBiju Das DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_ENTER; 521c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBCMD, reg); 522c40739a6SBiju Das while (mmio_read_32(DBSC4_REG_DBWAIT)) 523c40739a6SBiju Das ; 524c40739a6SBiju Das 525c40739a6SBiju Das /* Set the auto-refresh enable register */ 526c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBRFEN, 0U); 527c40739a6SBiju Das rcar_micro_delay(1U); 528c40739a6SBiju Das 529c40739a6SBiju Das if (product == PRR_PRODUCT_M3 && cut < PRR_PRODUCT_30) 530c40739a6SBiju Das return; 531c40739a6SBiju Das 532c40739a6SBiju Das if (product == PRR_PRODUCT_H3 && cut < PRR_PRODUCT_20) 533c40739a6SBiju Das return; 534c40739a6SBiju Das 535c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBSYSCNT0, DBSC4_SET_DBSYSCNT0_WRITE_DISABLE); 536c40739a6SBiju Das } 537c40739a6SBiju Das 538c40739a6SBiju Das static void __attribute__ ((section(".system_ram"))) 539c40739a6SBiju Das rcar_pwrc_set_self_refresh_e3(void) 540c40739a6SBiju Das { 541c40739a6SBiju Das uint32_t ddr_md; 542c40739a6SBiju Das uint32_t reg; 543c40739a6SBiju Das 544c40739a6SBiju Das ddr_md = (mmio_read_32(RST_MODEMR) >> 19) & RST_MODEMR_BIT0; 545c40739a6SBiju Das 546c40739a6SBiju Das /* Write enable */ 547c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBSYSCNT0, DBSC4_SET_DBSYSCNT0_WRITE_ENABLE); 548c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBACEN, 0); 549c40739a6SBiju Das DBCAM_FLUSH(0); 550c40739a6SBiju Das 551c40739a6SBiju Das reg = DBSC4_SET_DBCMD_OPC_PRE | DBSC4_SET_DBCMD_CH_ALL | 552c40739a6SBiju Das DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_ALL; 553c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBCMD, reg); 554c40739a6SBiju Das while (mmio_read_32(DBSC4_REG_DBWAIT)) 555c40739a6SBiju Das ; 556c40739a6SBiju Das 557c40739a6SBiju Das reg = DBSC4_SET_DBCMD_OPC_SR | DBSC4_SET_DBCMD_CH_ALL | 558c40739a6SBiju Das DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_ENTER; 559c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBCMD, reg); 560c40739a6SBiju Das while (mmio_read_32(DBSC4_REG_DBWAIT)) 561c40739a6SBiju Das ; 562c40739a6SBiju Das 563c40739a6SBiju Das /* 564c40739a6SBiju Das * Set the auto-refresh enable register 565c40739a6SBiju Das * Set the ARFEN bit to 0 in the DBRFEN 566c40739a6SBiju Das */ 567c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBRFEN, 0); 568c40739a6SBiju Das 569c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDLK0, DBSC4_SET_DBPDLK0_PHY_ACCESS); 570c40739a6SBiju Das 571c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_ACIOCR0); 572c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_ACIOCR0); 573c40739a6SBiju Das 574c40739a6SBiju Das /* DDR_DXCCR */ 575c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DXCCR); 576c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DXCCR); 577c40739a6SBiju Das 578c40739a6SBiju Das /* DDR_PGCR1 */ 579c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_PGCR1); 580c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_PGCR1); 581c40739a6SBiju Das 582c40739a6SBiju Das /* DDR_ACIOCR1 */ 583c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_ACIOCR1); 584c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_ACIOCR1); 585c40739a6SBiju Das 586c40739a6SBiju Das /* DDR_ACIOCR3 */ 587c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_ACIOCR3); 588c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_ACIOCR3); 589c40739a6SBiju Das 590c40739a6SBiju Das /* DDR_ACIOCR5 */ 591c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_ACIOCR5); 592c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_ACIOCR5); 593c40739a6SBiju Das 594c40739a6SBiju Das /* DDR_DX0GCR2 */ 595c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX0GCR2); 596c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX0GCR2); 597c40739a6SBiju Das 598c40739a6SBiju Das /* DDR_DX1GCR2 */ 599c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX1GCR2); 600c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX1GCR2); 601c40739a6SBiju Das 602c40739a6SBiju Das /* DDR_DX2GCR2 */ 603c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX2GCR2); 604c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX2GCR2); 605c40739a6SBiju Das 606c40739a6SBiju Das /* DDR_DX3GCR2 */ 607c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX3GCR2); 608c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX3GCR2); 609c40739a6SBiju Das 610c40739a6SBiju Das /* DDR_ZQCR */ 611c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_ZQCR); 612c40739a6SBiju Das 613c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, ddr_md == 0 ? 614c40739a6SBiju Das DBSC4_SET_DBPDRGD0_ZQCR_MD19_0 : 615c40739a6SBiju Das DBSC4_SET_DBPDRGD0_ZQCR_MD19_1); 616c40739a6SBiju Das 617c40739a6SBiju Das /* DDR_DX0GCR0 */ 618c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX0GCR0); 619c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX0GCR0); 620c40739a6SBiju Das 621c40739a6SBiju Das /* DDR_DX1GCR0 */ 622c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX1GCR0); 623c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX1GCR0); 624c40739a6SBiju Das 625c40739a6SBiju Das /* DDR_DX2GCR0 */ 626c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX2GCR0); 627c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX2GCR0); 628c40739a6SBiju Das 629c40739a6SBiju Das /* DDR_DX3GCR0 */ 630c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX3GCR0); 631c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX3GCR0); 632c40739a6SBiju Das 633c40739a6SBiju Das /* DDR_DX0GCR1 */ 634c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX0GCR1); 635c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX0GCR1); 636c40739a6SBiju Das 637c40739a6SBiju Das /* DDR_DX1GCR1 */ 638c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX1GCR1); 639c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX1GCR1); 640c40739a6SBiju Das 641c40739a6SBiju Das /* DDR_DX2GCR1 */ 642c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX2GCR1); 643c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX2GCR1); 644c40739a6SBiju Das 645c40739a6SBiju Das /* DDR_DX3GCR1 */ 646c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX3GCR1); 647c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX3GCR1); 648c40739a6SBiju Das 649c40739a6SBiju Das /* DDR_DX0GCR3 */ 650c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX0GCR3); 651c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX0GCR3); 652c40739a6SBiju Das 653c40739a6SBiju Das /* DDR_DX1GCR3 */ 654c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX1GCR3); 655c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX1GCR3); 656c40739a6SBiju Das 657c40739a6SBiju Das /* DDR_DX2GCR3 */ 658c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX2GCR3); 659c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX2GCR3); 660c40739a6SBiju Das 661c40739a6SBiju Das /* DDR_DX3GCR3 */ 662c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX3GCR3); 663c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX3GCR3); 664c40739a6SBiju Das 665c40739a6SBiju Das /* Write disable */ 666c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBSYSCNT0, DBSC4_SET_DBSYSCNT0_WRITE_DISABLE); 667c40739a6SBiju Das } 668c40739a6SBiju Das 669c40739a6SBiju Das void __attribute__ ((section(".system_ram"))) __attribute__ ((noinline)) 670c40739a6SBiju Das rcar_pwrc_go_suspend_to_ram(void) 671c40739a6SBiju Das { 672c40739a6SBiju Das #if PMIC_ROHM_BD9571 673c40739a6SBiju Das int32_t rc = -1, qllm = -1; 674c40739a6SBiju Das uint8_t mode; 675c40739a6SBiju Das uint32_t i; 676c40739a6SBiju Das #endif 677c40739a6SBiju Das uint32_t reg, product; 678c40739a6SBiju Das 679c40739a6SBiju Das reg = mmio_read_32(RCAR_PRR); 680c40739a6SBiju Das product = reg & PRR_PRODUCT_MASK; 681c40739a6SBiju Das 682c40739a6SBiju Das if (product != PRR_PRODUCT_E3) 683c40739a6SBiju Das rcar_pwrc_set_self_refresh(); 684c40739a6SBiju Das else 685c40739a6SBiju Das rcar_pwrc_set_self_refresh_e3(); 686c40739a6SBiju Das 687c40739a6SBiju Das #if PMIC_ROHM_BD9571 688c40739a6SBiju Das /* Set QLLM Cnt Disable */ 689c40739a6SBiju Das for (i = 0; (i < PMIC_RETRY_MAX) && (qllm != 0); i++) 690c40739a6SBiju Das qllm = rcar_iic_dvfs_send(PMIC, PMIC_QLLM_CNT, 0); 691c40739a6SBiju Das 692c40739a6SBiju Das /* Set trigger of power down to PMIV */ 693c40739a6SBiju Das for (i = 0; (i < PMIC_RETRY_MAX) && (rc != 0) && (qllm == 0); i++) { 694c40739a6SBiju Das rc = rcar_iic_dvfs_receive(PMIC, PMIC_BKUP_MODE_CNT, &mode); 695c40739a6SBiju Das if (rc == 0) { 696c40739a6SBiju Das mode |= BIT_BKUP_CTRL_OUT; 697c40739a6SBiju Das rc = rcar_iic_dvfs_send(PMIC, PMIC_BKUP_MODE_CNT, mode); 698c40739a6SBiju Das } 699c40739a6SBiju Das } 700c40739a6SBiju Das #endif 701c40739a6SBiju Das wfi(); 702c40739a6SBiju Das 703c40739a6SBiju Das while (1) 704c40739a6SBiju Das ; 705c40739a6SBiju Das } 706c40739a6SBiju Das 707c40739a6SBiju Das void rcar_pwrc_set_suspend_to_ram(void) 708c40739a6SBiju Das { 709c40739a6SBiju Das uintptr_t jump = (uintptr_t) &rcar_pwrc_go_suspend_to_ram; 710c40739a6SBiju Das uintptr_t stack = (uintptr_t) (DEVICE_SRAM_STACK_BASE + 711c40739a6SBiju Das DEVICE_SRAM_STACK_SIZE); 712c40739a6SBiju Das uint32_t sctlr; 713c40739a6SBiju Das 714c40739a6SBiju Das rcar_pwrc_save_timer_state(); 715c40739a6SBiju Das 716c40739a6SBiju Das /* disable MMU */ 717c40739a6SBiju Das sctlr = (uint32_t) read_sctlr_el3(); 718c40739a6SBiju Das sctlr &= (uint32_t) ~SCTLR_EL3_M_BIT; 719c40739a6SBiju Das write_sctlr_el3((uint64_t) sctlr); 720c40739a6SBiju Das 721c40739a6SBiju Das rcar_pwrc_switch_stack(jump, stack, NULL); 722c40739a6SBiju Das } 723c40739a6SBiju Das 724c40739a6SBiju Das void rcar_pwrc_init_suspend_to_ram(void) 725c40739a6SBiju Das { 726c40739a6SBiju Das #if PMIC_ROHM_BD9571 727c40739a6SBiju Das uint8_t mode; 728c40739a6SBiju Das 729c40739a6SBiju Das if (rcar_iic_dvfs_receive(PMIC, PMIC_BKUP_MODE_CNT, &mode)) 730c40739a6SBiju Das panic(); 731c40739a6SBiju Das 732c40739a6SBiju Das mode &= (uint8_t) (~BIT_BKUP_CTRL_OUT); 733c40739a6SBiju Das if (rcar_iic_dvfs_send(PMIC, PMIC_BKUP_MODE_CNT, mode)) 734c40739a6SBiju Das panic(); 735c40739a6SBiju Das #endif 736c40739a6SBiju Das } 737c40739a6SBiju Das 738c40739a6SBiju Das void rcar_pwrc_suspend_to_ram(void) 739c40739a6SBiju Das { 740c40739a6SBiju Das #if RCAR_SYSTEM_RESET_KEEPON_DDR 741c40739a6SBiju Das int32_t error; 742c40739a6SBiju Das 743c40739a6SBiju Das error = rcar_iic_dvfs_send(PMIC, REG_KEEP10, 0); 744c40739a6SBiju Das if (error) { 745c40739a6SBiju Das ERROR("Failed send KEEP10 init ret=%d\n", error); 746c40739a6SBiju Das return; 747c40739a6SBiju Das } 748c40739a6SBiju Das #endif 749c40739a6SBiju Das rcar_pwrc_set_suspend_to_ram(); 750c40739a6SBiju Das } 751c40739a6SBiju Das #endif 752c40739a6SBiju Das 753c40739a6SBiju Das void rcar_pwrc_code_copy_to_system_ram(void) 754c40739a6SBiju Das { 755c40739a6SBiju Das int ret __attribute__ ((unused)); /* in assert */ 756c40739a6SBiju Das uint32_t attr; 757c40739a6SBiju Das struct device_sram_t { 758c40739a6SBiju Das uintptr_t base; 759c40739a6SBiju Das size_t len; 760c40739a6SBiju Das } sram = { 761c40739a6SBiju Das .base = (uintptr_t) DEVICE_SRAM_BASE, 762c40739a6SBiju Das .len = DEVICE_SRAM_SIZE, 763c40739a6SBiju Das }; 764c40739a6SBiju Das struct ddr_code_t { 765c40739a6SBiju Das void *base; 766c40739a6SBiju Das size_t len; 767c40739a6SBiju Das } code = { 768c40739a6SBiju Das .base = (void *) SRAM_COPY_START, 769c40739a6SBiju Das .len = SYSTEM_RAM_END - SYSTEM_RAM_START, 770c40739a6SBiju Das }; 771c40739a6SBiju Das 772c40739a6SBiju Das attr = MT_MEMORY | MT_RW | MT_SECURE | MT_EXECUTE_NEVER; 773c40739a6SBiju Das ret = xlat_change_mem_attributes(sram.base, sram.len, attr); 774c40739a6SBiju Das assert(ret == 0); 775c40739a6SBiju Das 776c40739a6SBiju Das memcpy((void *)sram.base, code.base, code.len); 777c40739a6SBiju Das flush_dcache_range((uint64_t) sram.base, code.len); 778c40739a6SBiju Das 779c40739a6SBiju Das /* Invalidate instruction cache */ 780c40739a6SBiju Das plat_invalidate_icache(); 781c40739a6SBiju Das dsb(); 782c40739a6SBiju Das isb(); 783c40739a6SBiju Das 784c40739a6SBiju Das attr = MT_MEMORY | MT_RO | MT_SECURE | MT_EXECUTE; 785c40739a6SBiju Das ret = xlat_change_mem_attributes(sram.base, sram.len, attr); 786c40739a6SBiju Das assert(ret == 0); 787c40739a6SBiju Das } 788c40739a6SBiju Das 789c40739a6SBiju Das uint32_t rcar_pwrc_get_cluster(void) 790c40739a6SBiju Das { 791c40739a6SBiju Das uint32_t reg; 792c40739a6SBiju Das 793c40739a6SBiju Das reg = mmio_read_32(RCAR_PRR); 794c40739a6SBiju Das 795c40739a6SBiju Das if (reg & (1U << (STATE_CA53_CPU + RCAR_CA53CPU_NUM_MAX))) 796c40739a6SBiju Das return RCAR_CLUSTER_CA57; 797c40739a6SBiju Das 798c40739a6SBiju Das if (reg & (1U << (STATE_CA57_CPU + RCAR_CA57CPU_NUM_MAX))) 799c40739a6SBiju Das return RCAR_CLUSTER_CA53; 800c40739a6SBiju Das 801c40739a6SBiju Das return RCAR_CLUSTER_A53A57; 802c40739a6SBiju Das } 803c40739a6SBiju Das 804c40739a6SBiju Das uint32_t rcar_pwrc_get_mpidr_cluster(uint64_t mpidr) 805c40739a6SBiju Das { 806c40739a6SBiju Das uint32_t c = rcar_pwrc_get_cluster(); 807c40739a6SBiju Das 808c40739a6SBiju Das if (IS_A53A57(c)) { 809c40739a6SBiju Das if (mpidr & MPIDR_CLUSTER_MASK) 810c40739a6SBiju Das return RCAR_CLUSTER_CA53; 811c40739a6SBiju Das 812c40739a6SBiju Das return RCAR_CLUSTER_CA57; 813c40739a6SBiju Das } 814c40739a6SBiju Das 815c40739a6SBiju Das return c; 816c40739a6SBiju Das } 817c40739a6SBiju Das 818c40739a6SBiju Das #if RCAR_LSI == RCAR_D3 819c40739a6SBiju Das uint32_t rcar_pwrc_get_cpu_num(uint32_t c) 820c40739a6SBiju Das { 821c40739a6SBiju Das return 1; 822c40739a6SBiju Das } 823c40739a6SBiju Das #else 824c40739a6SBiju Das uint32_t rcar_pwrc_get_cpu_num(uint32_t c) 825c40739a6SBiju Das { 826c40739a6SBiju Das uint32_t reg = mmio_read_32(RCAR_PRR); 827c40739a6SBiju Das uint32_t count = 0, i; 828c40739a6SBiju Das 829c40739a6SBiju Das if (IS_A53A57(c) || IS_CA53(c)) { 830c40739a6SBiju Das if (reg & (1 << (STATE_CA53_CPU + RCAR_CA53CPU_NUM_MAX))) 831c40739a6SBiju Das goto count_ca57; 832c40739a6SBiju Das 833c40739a6SBiju Das for (i = 0; i < RCAR_CA53CPU_NUM_MAX; i++) { 834c40739a6SBiju Das if (reg & (1 << (STATE_CA53_CPU + i))) 835c40739a6SBiju Das continue; 836c40739a6SBiju Das count++; 837c40739a6SBiju Das } 838c40739a6SBiju Das } 839c40739a6SBiju Das 840c40739a6SBiju Das count_ca57: 841c40739a6SBiju Das if (IS_A53A57(c) || IS_CA57(c)) { 842c40739a6SBiju Das if (reg & (1U << (STATE_CA57_CPU + RCAR_CA57CPU_NUM_MAX))) 843c40739a6SBiju Das goto done; 844c40739a6SBiju Das 845c40739a6SBiju Das for (i = 0; i < RCAR_CA57CPU_NUM_MAX; i++) { 846c40739a6SBiju Das if (reg & (1 << (STATE_CA57_CPU + i))) 847c40739a6SBiju Das continue; 848c40739a6SBiju Das count++; 849c40739a6SBiju Das } 850c40739a6SBiju Das } 851c40739a6SBiju Das 852c40739a6SBiju Das done: 853c40739a6SBiju Das return count; 854c40739a6SBiju Das } 855c40739a6SBiju Das #endif 856c40739a6SBiju Das 857c40739a6SBiju Das int32_t rcar_pwrc_cpu_on_check(uint64_t mpidr) 858c40739a6SBiju Das { 859c40739a6SBiju Das uint64_t i; 860c40739a6SBiju Das uint64_t j; 861c40739a6SBiju Das uint64_t cpu_count; 862c40739a6SBiju Das uintptr_t reg_PSTR; 863c40739a6SBiju Das uint32_t status; 864c40739a6SBiju Das uint64_t my_cpu; 865c40739a6SBiju Das int32_t rtn; 866c40739a6SBiju Das uint32_t my_cluster_type; 867c40739a6SBiju Das const uint32_t cluster_type[PLATFORM_CLUSTER_COUNT] = { 868c40739a6SBiju Das RCAR_CLUSTER_CA53, 869c40739a6SBiju Das RCAR_CLUSTER_CA57 870c40739a6SBiju Das }; 871c40739a6SBiju Das const uintptr_t registerPSTR[PLATFORM_CLUSTER_COUNT] = { 872c40739a6SBiju Das RCAR_CA53PSTR, 873c40739a6SBiju Das RCAR_CA57PSTR 874c40739a6SBiju Das }; 875c40739a6SBiju Das 876c40739a6SBiju Das my_cluster_type = rcar_pwrc_get_cluster(); 877c40739a6SBiju Das 878c40739a6SBiju Das rtn = 0; 879c40739a6SBiju Das my_cpu = mpidr & ((uint64_t)(MPIDR_CPU_MASK)); 880c40739a6SBiju Das for (i = 0U; i < ((uint64_t)(PLATFORM_CLUSTER_COUNT)); i++) { 881c40739a6SBiju Das cpu_count = rcar_pwrc_get_cpu_num(cluster_type[i]); 882c40739a6SBiju Das reg_PSTR = registerPSTR[i]; 883c40739a6SBiju Das for (j = 0U; j < cpu_count; j++) { 884c40739a6SBiju Das if ((my_cluster_type != cluster_type[i]) || (my_cpu != j)) { 885c40739a6SBiju Das status = mmio_read_32(reg_PSTR) >> (j * 4U); 886c40739a6SBiju Das if ((status & 0x00000003U) == 0U) { 887c40739a6SBiju Das rtn--; 888c40739a6SBiju Das } 889c40739a6SBiju Das } 890c40739a6SBiju Das } 891c40739a6SBiju Das } 892c40739a6SBiju Das 893c40739a6SBiju Das return rtn; 894c40739a6SBiju Das } 895