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 159*ffb725beSTakuya Sakata uint32_t rcar_pwrc_status(u_register_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 191*ffb725beSTakuya Sakata static void scu_power_up(u_register_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 ; 233d10f8767SToshiyuki 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 246*ffb725beSTakuya Sakata void rcar_pwrc_cpuon(u_register_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 271*ffb725beSTakuya Sakata void rcar_pwrc_cpuoff(u_register_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 292*ffb725beSTakuya Sakata void rcar_pwrc_enable_interrupt_wakeup(u_register_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 30782bb6c2eSTakuya Sakata mmio_clrbits_32(reg, ((uint32_t) 1 << shift_irq) | 30882bb6c2eSTakuya Sakata ((uint32_t) 1 << shift_fiq)); 309c40739a6SBiju Das rcar_lock_release(); 310c40739a6SBiju Das } 311c40739a6SBiju Das 312*ffb725beSTakuya Sakata void rcar_pwrc_disable_interrupt_wakeup(u_register_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 32782bb6c2eSTakuya Sakata mmio_setbits_32(reg, ((uint32_t) 1 << shift_irq) | 328c40739a6SBiju Das ((uint32_t) 1 << shift_fiq)); 329c40739a6SBiju Das rcar_lock_release(); 330c40739a6SBiju Das } 331c40739a6SBiju Das 332d9912cf3STakuya Sakata void rcar_pwrc_all_disable_interrupt_wakeup(void) 333d9912cf3STakuya Sakata { 334*ffb725beSTakuya Sakata uint32_t cpu_num; 335*ffb725beSTakuya Sakata u_register_t cl, cpu, mpidr; 336d9912cf3STakuya Sakata 337d9912cf3STakuya Sakata const uint32_t cluster[PLATFORM_CLUSTER_COUNT] = { 338d9912cf3STakuya Sakata RCAR_CLUSTER_CA57, 339d9912cf3STakuya Sakata RCAR_CLUSTER_CA53 340d9912cf3STakuya Sakata }; 341d9912cf3STakuya Sakata 342d9912cf3STakuya Sakata for (cl = 0; cl < PLATFORM_CLUSTER_COUNT; cl++) { 343d9912cf3STakuya Sakata cpu_num = rcar_pwrc_get_cpu_num(cluster[cl]); 344d9912cf3STakuya Sakata for (cpu = 0; cpu < cpu_num; cpu++) { 345*ffb725beSTakuya Sakata mpidr = ((cl << MPIDR_AFFINITY_BITS) | cpu); 346*ffb725beSTakuya Sakata if (mpidr == rcar_boot_mpidr) { 347d9912cf3STakuya Sakata rcar_pwrc_enable_interrupt_wakeup(mpidr); 348d9912cf3STakuya Sakata } else { 349d9912cf3STakuya Sakata rcar_pwrc_disable_interrupt_wakeup(mpidr); 350d9912cf3STakuya Sakata } 351d9912cf3STakuya Sakata } 352d9912cf3STakuya Sakata } 353d9912cf3STakuya Sakata } 354d9912cf3STakuya Sakata 355*ffb725beSTakuya Sakata void rcar_pwrc_clusteroff(u_register_t mpidr) 356c40739a6SBiju Das { 357c40739a6SBiju Das uint32_t c, product, cut, reg; 358c40739a6SBiju Das uintptr_t dst; 359c40739a6SBiju Das 360c40739a6SBiju Das rcar_lock_get(); 361c40739a6SBiju Das 362c40739a6SBiju Das reg = mmio_read_32(RCAR_PRR); 363c40739a6SBiju Das product = reg & PRR_PRODUCT_MASK; 364c40739a6SBiju Das cut = reg & PRR_CUT_MASK; 365c40739a6SBiju Das 366c40739a6SBiju Das c = rcar_pwrc_get_mpidr_cluster(mpidr); 367c40739a6SBiju Das dst = IS_CA53(c) ? RCAR_CA53CPUCMCR : RCAR_CA57CPUCMCR; 368c40739a6SBiju Das 369c40739a6SBiju Das if (product == PRR_PRODUCT_M3 && cut < PRR_PRODUCT_30) { 370c40739a6SBiju Das goto done; 371c40739a6SBiju Das } 372c40739a6SBiju Das 373c40739a6SBiju Das if (product == PRR_PRODUCT_H3 && cut <= PRR_PRODUCT_20) { 374c40739a6SBiju Das goto done; 375c40739a6SBiju Das } 376c40739a6SBiju Das 377c40739a6SBiju Das /* all of the CPUs in the cluster is in the CoreStandby mode */ 378c40739a6SBiju Das mmio_write_32(dst, MODE_L2_DOWN); 379c40739a6SBiju Das done: 380c40739a6SBiju Das rcar_lock_release(); 381c40739a6SBiju Das } 382c40739a6SBiju Das 383c40739a6SBiju Das static uint64_t rcar_pwrc_saved_cntpct_el0; 384c40739a6SBiju Das static uint32_t rcar_pwrc_saved_cntfid; 385c40739a6SBiju Das 386c40739a6SBiju Das #if RCAR_SYSTEM_SUSPEND 387c40739a6SBiju Das static void rcar_pwrc_save_timer_state(void) 388c40739a6SBiju Das { 389c40739a6SBiju Das rcar_pwrc_saved_cntpct_el0 = read_cntpct_el0(); 390c40739a6SBiju Das 391c40739a6SBiju Das rcar_pwrc_saved_cntfid = 392c40739a6SBiju Das mmio_read_32((uintptr_t)(RCAR_CNTC_BASE + RCAR_CNTFID_OFF)); 393c40739a6SBiju Das } 394c40739a6SBiju Das #endif /* RCAR_SYSTEM_SUSPEND */ 395c40739a6SBiju Das 396c40739a6SBiju Das void rcar_pwrc_restore_timer_state(void) 397c40739a6SBiju Das { 398c40739a6SBiju Das /* Stop timer before restoring counter value */ 399c40739a6SBiju Das mmio_write_32((uintptr_t)(RCAR_CNTC_BASE + RCAR_CNTCR_OFF), 0U); 400c40739a6SBiju Das 401c40739a6SBiju Das mmio_write_32((uintptr_t)(RCAR_CNTC_BASE + RCAR_CNTCVL_OFF), 402c40739a6SBiju Das (uint32_t)(rcar_pwrc_saved_cntpct_el0 & 0xFFFFFFFFU)); 403c40739a6SBiju Das mmio_write_32((uintptr_t)(RCAR_CNTC_BASE + RCAR_CNTCVU_OFF), 404c40739a6SBiju Das (uint32_t)(rcar_pwrc_saved_cntpct_el0 >> 32U)); 405c40739a6SBiju Das 406c40739a6SBiju Das mmio_write_32((uintptr_t)(RCAR_CNTC_BASE + RCAR_CNTFID_OFF), 407c40739a6SBiju Das rcar_pwrc_saved_cntfid); 408c40739a6SBiju Das 409c40739a6SBiju Das /* Start generic timer back */ 410c40739a6SBiju Das write_cntfrq_el0((u_register_t)plat_get_syscnt_freq2()); 411c40739a6SBiju Das 412c40739a6SBiju Das mmio_write_32((uintptr_t)(RCAR_CNTC_BASE + RCAR_CNTCR_OFF), 413c40739a6SBiju Das (RCAR_CNTCR_FCREQ(0U) | RCAR_CNTCR_EN)); 414c40739a6SBiju Das } 415c40739a6SBiju Das 416c40739a6SBiju Das #if !PMIC_ROHM_BD9571 417c40739a6SBiju Das void rcar_pwrc_system_reset(void) 418c40739a6SBiju Das { 419c40739a6SBiju Das mmio_write_32(RCAR_SRESCR, 0x5AA50000U | BIT_SOFTRESET); 420c40739a6SBiju Das } 421c40739a6SBiju Das #endif /* PMIC_ROHM_BD9571 */ 422c40739a6SBiju Das 423c40739a6SBiju Das #define RST_CA53_CPU0_BARH (0xE6160080U) 424c40739a6SBiju Das #define RST_CA53_CPU0_BARL (0xE6160084U) 425c40739a6SBiju Das #define RST_CA57_CPU0_BARH (0xE61600C0U) 426c40739a6SBiju Das #define RST_CA57_CPU0_BARL (0xE61600C4U) 427c40739a6SBiju Das 428c40739a6SBiju Das void rcar_pwrc_setup(void) 429c40739a6SBiju Das { 430c40739a6SBiju Das uintptr_t rst_barh; 431c40739a6SBiju Das uintptr_t rst_barl; 432c40739a6SBiju Das uint32_t i, j; 433c40739a6SBiju Das uint64_t reset = (uint64_t) (&plat_secondary_reset) & 0xFFFFFFFF; 434c40739a6SBiju Das 435c40739a6SBiju Das const uint32_t cluster[PLATFORM_CLUSTER_COUNT] = { 436c40739a6SBiju Das RCAR_CLUSTER_CA53, 437c40739a6SBiju Das RCAR_CLUSTER_CA57 438c40739a6SBiju Das }; 439c40739a6SBiju Das const uintptr_t reg_barh[PLATFORM_CLUSTER_COUNT] = { 440c40739a6SBiju Das RST_CA53_CPU0_BARH, 441c40739a6SBiju Das RST_CA57_CPU0_BARH 442c40739a6SBiju Das }; 443c40739a6SBiju Das const uintptr_t reg_barl[PLATFORM_CLUSTER_COUNT] = { 444c40739a6SBiju Das RST_CA53_CPU0_BARL, 445c40739a6SBiju Das RST_CA57_CPU0_BARL 446c40739a6SBiju Das }; 447c40739a6SBiju Das 448c40739a6SBiju Das for (i = 0; i < PLATFORM_CLUSTER_COUNT; i++) { 449c40739a6SBiju Das rst_barh = reg_barh[i]; 450c40739a6SBiju Das rst_barl = reg_barl[i]; 451c40739a6SBiju Das for (j = 0; j < rcar_pwrc_get_cpu_num(cluster[i]); j++) { 452c40739a6SBiju Das mmio_write_32(rst_barh, 0); 453c40739a6SBiju Das mmio_write_32(rst_barl, (uint32_t) reset); 454c40739a6SBiju Das rst_barh += 0x10; 455c40739a6SBiju Das rst_barl += 0x10; 456c40739a6SBiju Das } 457c40739a6SBiju Das } 458c40739a6SBiju Das 459c40739a6SBiju Das rcar_lock_init(); 460c40739a6SBiju Das } 461c40739a6SBiju Das 462c40739a6SBiju Das #if RCAR_SYSTEM_SUSPEND 463c40739a6SBiju Das #define DBCAM_FLUSH(__bit) \ 464c40739a6SBiju Das do { \ 465c40739a6SBiju Das ; \ 466c40739a6SBiju Das } while (!(mmio_read_32(DBSC4_REG_DBCAM##__bit##STAT0) & DBSC4_BIT_DBCAMxSTAT0)) 467c40739a6SBiju Das 468c40739a6SBiju Das 469c40739a6SBiju Das static void __attribute__ ((section(".system_ram"))) 470c40739a6SBiju Das rcar_pwrc_set_self_refresh(void) 471c40739a6SBiju Das { 472c40739a6SBiju Das uint32_t reg = mmio_read_32(RCAR_PRR); 473c40739a6SBiju Das uint32_t cut, product; 474c40739a6SBiju Das 475c40739a6SBiju Das product = reg & PRR_PRODUCT_MASK; 476c40739a6SBiju Das cut = reg & PRR_CUT_MASK; 477c40739a6SBiju Das 478c40739a6SBiju Das if (product == PRR_PRODUCT_M3 && cut < PRR_PRODUCT_30) { 479c40739a6SBiju Das goto self_refresh; 480c40739a6SBiju Das } 481c40739a6SBiju Das 482c40739a6SBiju Das if (product == PRR_PRODUCT_H3 && cut < PRR_PRODUCT_20) { 483c40739a6SBiju Das goto self_refresh; 484c40739a6SBiju Das } 485c40739a6SBiju Das 486c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBSYSCNT0, DBSC4_SET_DBSYSCNT0_WRITE_ENABLE); 487c40739a6SBiju Das 488c40739a6SBiju Das self_refresh: 489c40739a6SBiju Das 490c40739a6SBiju Das /* DFI_PHYMSTR_ACK setting */ 491c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBDFIPMSTRCNF, 492c40739a6SBiju Das mmio_read_32(DBSC4_REG_DBDFIPMSTRCNF) & 493c40739a6SBiju Das (~DBSC4_BIT_DBDFIPMSTRCNF_PMSTREN)); 494c40739a6SBiju Das 495c40739a6SBiju Das /* Set the Self-Refresh mode */ 496c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBACEN, 0); 497c40739a6SBiju Das 498c40739a6SBiju Das if (product == PRR_PRODUCT_H3 && cut < PRR_PRODUCT_20) 499c40739a6SBiju Das rcar_micro_delay(100); 500c40739a6SBiju Das else if (product == PRR_PRODUCT_H3) { 501c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 1); 502c40739a6SBiju Das DBCAM_FLUSH(0); 503c40739a6SBiju Das DBCAM_FLUSH(1); 504c40739a6SBiju Das DBCAM_FLUSH(2); 505c40739a6SBiju Das DBCAM_FLUSH(3); 506c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 0); 507c40739a6SBiju Das } else if (product == PRR_PRODUCT_M3) { 508c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 1); 509c40739a6SBiju Das DBCAM_FLUSH(0); 510c40739a6SBiju Das DBCAM_FLUSH(1); 511c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 0); 512c40739a6SBiju Das } else { 513c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 1); 514c40739a6SBiju Das DBCAM_FLUSH(0); 515c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 0); 516c40739a6SBiju Das } 517c40739a6SBiju Das 518c40739a6SBiju Das /* Set the SDRAM calibration configuration register */ 519c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBCALCNF, 0); 520c40739a6SBiju Das 521c40739a6SBiju Das reg = DBSC4_SET_DBCMD_OPC_PRE | DBSC4_SET_DBCMD_CH_ALL | 522c40739a6SBiju Das DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_ALL; 523c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBCMD, reg); 524c40739a6SBiju Das while (mmio_read_32(DBSC4_REG_DBWAIT)) 525c40739a6SBiju Das ; 526c40739a6SBiju Das 527c40739a6SBiju Das /* Self-Refresh entry command */ 528c40739a6SBiju Das reg = DBSC4_SET_DBCMD_OPC_SR | DBSC4_SET_DBCMD_CH_ALL | 529c40739a6SBiju Das DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_ENTER; 530c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBCMD, reg); 531c40739a6SBiju Das while (mmio_read_32(DBSC4_REG_DBWAIT)) 532c40739a6SBiju Das ; 533c40739a6SBiju Das 534c40739a6SBiju Das /* Mode Register Write command. (ODT disabled) */ 535c40739a6SBiju Das reg = DBSC4_SET_DBCMD_OPC_MRW | DBSC4_SET_DBCMD_CH_ALL | 536c40739a6SBiju Das DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_MRW_ODTC; 537c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBCMD, reg); 538c40739a6SBiju Das while (mmio_read_32(DBSC4_REG_DBWAIT)) 539c40739a6SBiju Das ; 540c40739a6SBiju Das 541c40739a6SBiju Das /* Power Down entry command */ 542c40739a6SBiju Das reg = DBSC4_SET_DBCMD_OPC_PD | DBSC4_SET_DBCMD_CH_ALL | 543c40739a6SBiju Das DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_ENTER; 544c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBCMD, reg); 545c40739a6SBiju Das while (mmio_read_32(DBSC4_REG_DBWAIT)) 546c40739a6SBiju Das ; 547c40739a6SBiju Das 548c40739a6SBiju Das /* Set the auto-refresh enable register */ 549c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBRFEN, 0U); 550c40739a6SBiju Das rcar_micro_delay(1U); 551c40739a6SBiju Das 552c40739a6SBiju Das if (product == PRR_PRODUCT_M3 && cut < PRR_PRODUCT_30) 553c40739a6SBiju Das return; 554c40739a6SBiju Das 555c40739a6SBiju Das if (product == PRR_PRODUCT_H3 && cut < PRR_PRODUCT_20) 556c40739a6SBiju Das return; 557c40739a6SBiju Das 558c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBSYSCNT0, DBSC4_SET_DBSYSCNT0_WRITE_DISABLE); 559c40739a6SBiju Das } 560c40739a6SBiju Das 561c40739a6SBiju Das static void __attribute__ ((section(".system_ram"))) 562c40739a6SBiju Das rcar_pwrc_set_self_refresh_e3(void) 563c40739a6SBiju Das { 564c40739a6SBiju Das uint32_t ddr_md; 565c40739a6SBiju Das uint32_t reg; 566c40739a6SBiju Das 567c40739a6SBiju Das ddr_md = (mmio_read_32(RST_MODEMR) >> 19) & RST_MODEMR_BIT0; 568c40739a6SBiju Das 569c40739a6SBiju Das /* Write enable */ 570c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBSYSCNT0, DBSC4_SET_DBSYSCNT0_WRITE_ENABLE); 571c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBACEN, 0); 572c40739a6SBiju Das DBCAM_FLUSH(0); 573c40739a6SBiju Das 574c40739a6SBiju Das reg = DBSC4_SET_DBCMD_OPC_PRE | DBSC4_SET_DBCMD_CH_ALL | 575c40739a6SBiju Das DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_ALL; 576c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBCMD, reg); 577c40739a6SBiju Das while (mmio_read_32(DBSC4_REG_DBWAIT)) 578c40739a6SBiju Das ; 579c40739a6SBiju Das 580c40739a6SBiju Das reg = DBSC4_SET_DBCMD_OPC_SR | DBSC4_SET_DBCMD_CH_ALL | 581c40739a6SBiju Das DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_ENTER; 582c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBCMD, reg); 583c40739a6SBiju Das while (mmio_read_32(DBSC4_REG_DBWAIT)) 584c40739a6SBiju Das ; 585c40739a6SBiju Das 586c40739a6SBiju Das /* 587c40739a6SBiju Das * Set the auto-refresh enable register 588c40739a6SBiju Das * Set the ARFEN bit to 0 in the DBRFEN 589c40739a6SBiju Das */ 590c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBRFEN, 0); 591c40739a6SBiju Das 592c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDLK0, DBSC4_SET_DBPDLK0_PHY_ACCESS); 593c40739a6SBiju Das 594c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_ACIOCR0); 595c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_ACIOCR0); 596c40739a6SBiju Das 597c40739a6SBiju Das /* DDR_DXCCR */ 598c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DXCCR); 599c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DXCCR); 600c40739a6SBiju Das 601c40739a6SBiju Das /* DDR_PGCR1 */ 602c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_PGCR1); 603c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_PGCR1); 604c40739a6SBiju Das 605c40739a6SBiju Das /* DDR_ACIOCR1 */ 606c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_ACIOCR1); 607c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_ACIOCR1); 608c40739a6SBiju Das 609c40739a6SBiju Das /* DDR_ACIOCR3 */ 610c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_ACIOCR3); 611c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_ACIOCR3); 612c40739a6SBiju Das 613c40739a6SBiju Das /* DDR_ACIOCR5 */ 614c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_ACIOCR5); 615c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_ACIOCR5); 616c40739a6SBiju Das 617c40739a6SBiju Das /* DDR_DX0GCR2 */ 618c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX0GCR2); 619c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX0GCR2); 620c40739a6SBiju Das 621c40739a6SBiju Das /* DDR_DX1GCR2 */ 622c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX1GCR2); 623c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX1GCR2); 624c40739a6SBiju Das 625c40739a6SBiju Das /* DDR_DX2GCR2 */ 626c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX2GCR2); 627c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX2GCR2); 628c40739a6SBiju Das 629c40739a6SBiju Das /* DDR_DX3GCR2 */ 630c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX3GCR2); 631c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX3GCR2); 632c40739a6SBiju Das 633c40739a6SBiju Das /* DDR_ZQCR */ 634c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_ZQCR); 635c40739a6SBiju Das 636c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, ddr_md == 0 ? 637c40739a6SBiju Das DBSC4_SET_DBPDRGD0_ZQCR_MD19_0 : 638c40739a6SBiju Das DBSC4_SET_DBPDRGD0_ZQCR_MD19_1); 639c40739a6SBiju Das 640c40739a6SBiju Das /* DDR_DX0GCR0 */ 641c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX0GCR0); 642c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX0GCR0); 643c40739a6SBiju Das 644c40739a6SBiju Das /* DDR_DX1GCR0 */ 645c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX1GCR0); 646c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX1GCR0); 647c40739a6SBiju Das 648c40739a6SBiju Das /* DDR_DX2GCR0 */ 649c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX2GCR0); 650c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX2GCR0); 651c40739a6SBiju Das 652c40739a6SBiju Das /* DDR_DX3GCR0 */ 653c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX3GCR0); 654c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX3GCR0); 655c40739a6SBiju Das 656c40739a6SBiju Das /* DDR_DX0GCR1 */ 657c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX0GCR1); 658c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX0GCR1); 659c40739a6SBiju Das 660c40739a6SBiju Das /* DDR_DX1GCR1 */ 661c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX1GCR1); 662c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX1GCR1); 663c40739a6SBiju Das 664c40739a6SBiju Das /* DDR_DX2GCR1 */ 665c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX2GCR1); 666c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX2GCR1); 667c40739a6SBiju Das 668c40739a6SBiju Das /* DDR_DX3GCR1 */ 669c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX3GCR1); 670c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX3GCR1); 671c40739a6SBiju Das 672c40739a6SBiju Das /* DDR_DX0GCR3 */ 673c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX0GCR3); 674c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX0GCR3); 675c40739a6SBiju Das 676c40739a6SBiju Das /* DDR_DX1GCR3 */ 677c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX1GCR3); 678c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX1GCR3); 679c40739a6SBiju Das 680c40739a6SBiju Das /* DDR_DX2GCR3 */ 681c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX2GCR3); 682c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX2GCR3); 683c40739a6SBiju Das 684c40739a6SBiju Das /* DDR_DX3GCR3 */ 685c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX3GCR3); 686c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX3GCR3); 687c40739a6SBiju Das 688c40739a6SBiju Das /* Write disable */ 689c40739a6SBiju Das mmio_write_32(DBSC4_REG_DBSYSCNT0, DBSC4_SET_DBSYSCNT0_WRITE_DISABLE); 690c40739a6SBiju Das } 691c40739a6SBiju Das 692c40739a6SBiju Das void __attribute__ ((section(".system_ram"))) __attribute__ ((noinline)) 693c40739a6SBiju Das rcar_pwrc_go_suspend_to_ram(void) 694c40739a6SBiju Das { 695c40739a6SBiju Das #if PMIC_ROHM_BD9571 696c40739a6SBiju Das int32_t rc = -1, qllm = -1; 697c40739a6SBiju Das uint8_t mode; 698c40739a6SBiju Das uint32_t i; 699c40739a6SBiju Das #endif 700c40739a6SBiju Das uint32_t reg, product; 701c40739a6SBiju Das 702c40739a6SBiju Das reg = mmio_read_32(RCAR_PRR); 703c40739a6SBiju Das product = reg & PRR_PRODUCT_MASK; 704c40739a6SBiju Das 705c40739a6SBiju Das if (product != PRR_PRODUCT_E3) 706c40739a6SBiju Das rcar_pwrc_set_self_refresh(); 707c40739a6SBiju Das else 708c40739a6SBiju Das rcar_pwrc_set_self_refresh_e3(); 709c40739a6SBiju Das 710c40739a6SBiju Das #if PMIC_ROHM_BD9571 711c40739a6SBiju Das /* Set QLLM Cnt Disable */ 712c40739a6SBiju Das for (i = 0; (i < PMIC_RETRY_MAX) && (qllm != 0); i++) 713c40739a6SBiju Das qllm = rcar_iic_dvfs_send(PMIC, PMIC_QLLM_CNT, 0); 714c40739a6SBiju Das 715c40739a6SBiju Das /* Set trigger of power down to PMIV */ 716c40739a6SBiju Das for (i = 0; (i < PMIC_RETRY_MAX) && (rc != 0) && (qllm == 0); i++) { 717c40739a6SBiju Das rc = rcar_iic_dvfs_receive(PMIC, PMIC_BKUP_MODE_CNT, &mode); 718c40739a6SBiju Das if (rc == 0) { 719c40739a6SBiju Das mode |= BIT_BKUP_CTRL_OUT; 720c40739a6SBiju Das rc = rcar_iic_dvfs_send(PMIC, PMIC_BKUP_MODE_CNT, mode); 721c40739a6SBiju Das } 722c40739a6SBiju Das } 723c40739a6SBiju Das #endif 724c40739a6SBiju Das wfi(); 725c40739a6SBiju Das 726c40739a6SBiju Das while (1) 727c40739a6SBiju Das ; 728c40739a6SBiju Das } 729c40739a6SBiju Das 730c40739a6SBiju Das void rcar_pwrc_set_suspend_to_ram(void) 731c40739a6SBiju Das { 732c40739a6SBiju Das uintptr_t jump = (uintptr_t) &rcar_pwrc_go_suspend_to_ram; 733c40739a6SBiju Das uintptr_t stack = (uintptr_t) (DEVICE_SRAM_STACK_BASE + 734c40739a6SBiju Das DEVICE_SRAM_STACK_SIZE); 735c40739a6SBiju Das uint32_t sctlr; 736c40739a6SBiju Das 737c40739a6SBiju Das rcar_pwrc_save_timer_state(); 738c40739a6SBiju Das 739c40739a6SBiju Das /* disable MMU */ 740c40739a6SBiju Das sctlr = (uint32_t) read_sctlr_el3(); 741c40739a6SBiju Das sctlr &= (uint32_t) ~SCTLR_EL3_M_BIT; 742c40739a6SBiju Das write_sctlr_el3((uint64_t) sctlr); 743c40739a6SBiju Das 744c40739a6SBiju Das rcar_pwrc_switch_stack(jump, stack, NULL); 745c40739a6SBiju Das } 746c40739a6SBiju Das 747c40739a6SBiju Das void rcar_pwrc_init_suspend_to_ram(void) 748c40739a6SBiju Das { 749c40739a6SBiju Das #if PMIC_ROHM_BD9571 750c40739a6SBiju Das uint8_t mode; 751c40739a6SBiju Das 752c40739a6SBiju Das if (rcar_iic_dvfs_receive(PMIC, PMIC_BKUP_MODE_CNT, &mode)) 753c40739a6SBiju Das panic(); 754c40739a6SBiju Das 755c40739a6SBiju Das mode &= (uint8_t) (~BIT_BKUP_CTRL_OUT); 756c40739a6SBiju Das if (rcar_iic_dvfs_send(PMIC, PMIC_BKUP_MODE_CNT, mode)) 757c40739a6SBiju Das panic(); 758c40739a6SBiju Das #endif 759c40739a6SBiju Das } 760c40739a6SBiju Das 761c40739a6SBiju Das void rcar_pwrc_suspend_to_ram(void) 762c40739a6SBiju Das { 763c40739a6SBiju Das #if RCAR_SYSTEM_RESET_KEEPON_DDR 764c40739a6SBiju Das int32_t error; 765c40739a6SBiju Das 766c40739a6SBiju Das error = rcar_iic_dvfs_send(PMIC, REG_KEEP10, 0); 767c40739a6SBiju Das if (error) { 768c40739a6SBiju Das ERROR("Failed send KEEP10 init ret=%d\n", error); 769c40739a6SBiju Das return; 770c40739a6SBiju Das } 771c40739a6SBiju Das #endif 772c40739a6SBiju Das rcar_pwrc_set_suspend_to_ram(); 773c40739a6SBiju Das } 774c40739a6SBiju Das #endif 775c40739a6SBiju Das 776c40739a6SBiju Das void rcar_pwrc_code_copy_to_system_ram(void) 777c40739a6SBiju Das { 778c40739a6SBiju Das int ret __attribute__ ((unused)); /* in assert */ 779c40739a6SBiju Das uint32_t attr; 780c40739a6SBiju Das struct device_sram_t { 781c40739a6SBiju Das uintptr_t base; 782c40739a6SBiju Das size_t len; 783c40739a6SBiju Das } sram = { 784c40739a6SBiju Das .base = (uintptr_t) DEVICE_SRAM_BASE, 785c40739a6SBiju Das .len = DEVICE_SRAM_SIZE, 786c40739a6SBiju Das }; 787c40739a6SBiju Das struct ddr_code_t { 788c40739a6SBiju Das void *base; 789c40739a6SBiju Das size_t len; 790c40739a6SBiju Das } code = { 791c40739a6SBiju Das .base = (void *) SRAM_COPY_START, 792c40739a6SBiju Das .len = SYSTEM_RAM_END - SYSTEM_RAM_START, 793c40739a6SBiju Das }; 794c40739a6SBiju Das 795c40739a6SBiju Das attr = MT_MEMORY | MT_RW | MT_SECURE | MT_EXECUTE_NEVER; 796c40739a6SBiju Das ret = xlat_change_mem_attributes(sram.base, sram.len, attr); 797c40739a6SBiju Das assert(ret == 0); 798c40739a6SBiju Das 799c40739a6SBiju Das memcpy((void *)sram.base, code.base, code.len); 800c40739a6SBiju Das flush_dcache_range((uint64_t) sram.base, code.len); 801c40739a6SBiju Das 80249593cc1SToshiyuki Ogasahara attr = MT_MEMORY | MT_RO | MT_SECURE | MT_EXECUTE; 80349593cc1SToshiyuki Ogasahara ret = xlat_change_mem_attributes(sram.base, sram.len, attr); 80449593cc1SToshiyuki Ogasahara assert(ret == 0); 80549593cc1SToshiyuki Ogasahara 806c40739a6SBiju Das /* Invalidate instruction cache */ 807c40739a6SBiju Das plat_invalidate_icache(); 808c40739a6SBiju Das dsb(); 809c40739a6SBiju Das isb(); 810c40739a6SBiju Das } 811c40739a6SBiju Das 812c40739a6SBiju Das uint32_t rcar_pwrc_get_cluster(void) 813c40739a6SBiju Das { 814c40739a6SBiju Das uint32_t reg; 815c40739a6SBiju Das 816c40739a6SBiju Das reg = mmio_read_32(RCAR_PRR); 817c40739a6SBiju Das 818c40739a6SBiju Das if (reg & (1U << (STATE_CA53_CPU + RCAR_CA53CPU_NUM_MAX))) 819c40739a6SBiju Das return RCAR_CLUSTER_CA57; 820c40739a6SBiju Das 821c40739a6SBiju Das if (reg & (1U << (STATE_CA57_CPU + RCAR_CA57CPU_NUM_MAX))) 822c40739a6SBiju Das return RCAR_CLUSTER_CA53; 823c40739a6SBiju Das 824c40739a6SBiju Das return RCAR_CLUSTER_A53A57; 825c40739a6SBiju Das } 826c40739a6SBiju Das 827*ffb725beSTakuya Sakata uint32_t rcar_pwrc_get_mpidr_cluster(u_register_t mpidr) 828c40739a6SBiju Das { 829c40739a6SBiju Das uint32_t c = rcar_pwrc_get_cluster(); 830c40739a6SBiju Das 831c40739a6SBiju Das if (IS_A53A57(c)) { 832c40739a6SBiju Das if (mpidr & MPIDR_CLUSTER_MASK) 833c40739a6SBiju Das return RCAR_CLUSTER_CA53; 834c40739a6SBiju Das 835c40739a6SBiju Das return RCAR_CLUSTER_CA57; 836c40739a6SBiju Das } 837c40739a6SBiju Das 838c40739a6SBiju Das return c; 839c40739a6SBiju Das } 840c40739a6SBiju Das 841c40739a6SBiju Das #if RCAR_LSI == RCAR_D3 842c40739a6SBiju Das uint32_t rcar_pwrc_get_cpu_num(uint32_t c) 843c40739a6SBiju Das { 844c40739a6SBiju Das return 1; 845c40739a6SBiju Das } 846c40739a6SBiju Das #else 847c40739a6SBiju Das uint32_t rcar_pwrc_get_cpu_num(uint32_t c) 848c40739a6SBiju Das { 849c40739a6SBiju Das uint32_t reg = mmio_read_32(RCAR_PRR); 850c40739a6SBiju Das uint32_t count = 0, i; 851c40739a6SBiju Das 852c40739a6SBiju Das if (IS_A53A57(c) || IS_CA53(c)) { 853c40739a6SBiju Das if (reg & (1 << (STATE_CA53_CPU + RCAR_CA53CPU_NUM_MAX))) 854c40739a6SBiju Das goto count_ca57; 855c40739a6SBiju Das 856c40739a6SBiju Das for (i = 0; i < RCAR_CA53CPU_NUM_MAX; i++) { 857c40739a6SBiju Das if (reg & (1 << (STATE_CA53_CPU + i))) 858c40739a6SBiju Das continue; 859c40739a6SBiju Das count++; 860c40739a6SBiju Das } 861c40739a6SBiju Das } 862c40739a6SBiju Das 863c40739a6SBiju Das count_ca57: 864c40739a6SBiju Das if (IS_A53A57(c) || IS_CA57(c)) { 865c40739a6SBiju Das if (reg & (1U << (STATE_CA57_CPU + RCAR_CA57CPU_NUM_MAX))) 866c40739a6SBiju Das goto done; 867c40739a6SBiju Das 868c40739a6SBiju Das for (i = 0; i < RCAR_CA57CPU_NUM_MAX; i++) { 869c40739a6SBiju Das if (reg & (1 << (STATE_CA57_CPU + i))) 870c40739a6SBiju Das continue; 871c40739a6SBiju Das count++; 872c40739a6SBiju Das } 873c40739a6SBiju Das } 874c40739a6SBiju Das 875c40739a6SBiju Das done: 876c40739a6SBiju Das return count; 877c40739a6SBiju Das } 878c40739a6SBiju Das #endif 879c40739a6SBiju Das 880*ffb725beSTakuya Sakata int32_t rcar_pwrc_cpu_on_check(u_register_t mpidr) 881c40739a6SBiju Das { 882c40739a6SBiju Das uint64_t i; 883c40739a6SBiju Das uint64_t j; 884c40739a6SBiju Das uint64_t cpu_count; 885c40739a6SBiju Das uintptr_t reg_PSTR; 886c40739a6SBiju Das uint32_t status; 887c40739a6SBiju Das uint64_t my_cpu; 888c40739a6SBiju Das int32_t rtn; 889c40739a6SBiju Das uint32_t my_cluster_type; 890c40739a6SBiju Das const uint32_t cluster_type[PLATFORM_CLUSTER_COUNT] = { 891c40739a6SBiju Das RCAR_CLUSTER_CA53, 892c40739a6SBiju Das RCAR_CLUSTER_CA57 893c40739a6SBiju Das }; 894c40739a6SBiju Das const uintptr_t registerPSTR[PLATFORM_CLUSTER_COUNT] = { 895c40739a6SBiju Das RCAR_CA53PSTR, 896c40739a6SBiju Das RCAR_CA57PSTR 897c40739a6SBiju Das }; 898c40739a6SBiju Das 899c40739a6SBiju Das my_cluster_type = rcar_pwrc_get_cluster(); 900c40739a6SBiju Das 901c40739a6SBiju Das rtn = 0; 902c40739a6SBiju Das my_cpu = mpidr & ((uint64_t)(MPIDR_CPU_MASK)); 903c40739a6SBiju Das for (i = 0U; i < ((uint64_t)(PLATFORM_CLUSTER_COUNT)); i++) { 904c40739a6SBiju Das cpu_count = rcar_pwrc_get_cpu_num(cluster_type[i]); 905c40739a6SBiju Das reg_PSTR = registerPSTR[i]; 906c40739a6SBiju Das for (j = 0U; j < cpu_count; j++) { 907c40739a6SBiju Das if ((my_cluster_type != cluster_type[i]) || (my_cpu != j)) { 908c40739a6SBiju Das status = mmio_read_32(reg_PSTR) >> (j * 4U); 909c40739a6SBiju Das if ((status & 0x00000003U) == 0U) { 910c40739a6SBiju Das rtn--; 911c40739a6SBiju Das } 912c40739a6SBiju Das } 913c40739a6SBiju Das } 914c40739a6SBiju Das } 915c40739a6SBiju Das 916c40739a6SBiju Das return rtn; 917c40739a6SBiju Das } 918