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