1 /* 2 * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * Redistributions of source code must retain the above copyright notice, this 8 * list of conditions and the following disclaimer. 9 * 10 * Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * Neither the name of ARM nor the names of its contributors may be used 15 * to endorse or promote products derived from this software without specific 16 * prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include <arch_helpers.h> 32 #include <assert.h> 33 #include <bakery_lock.h> 34 #include <debug.h> 35 #include <delay_timer.h> 36 #include <errno.h> 37 #include <mmio.h> 38 #include <platform.h> 39 #include <platform_def.h> 40 #include <plat_private.h> 41 #include <rk3399_def.h> 42 #include <pmu_sram.h> 43 #include <soc.h> 44 #include <pmu.h> 45 #include <pmu_com.h> 46 47 static struct psram_data_t *psram_sleep_cfg = 48 (struct psram_data_t *)PSRAM_DT_BASE; 49 50 static uint32_t cpu_warm_boot_addr; 51 52 /* 53 * There are two ways to powering on or off on core. 54 * 1) Control it power domain into on or off in PMU_PWRDN_CON reg, 55 * it is core_pwr_pd mode 56 * 2) Enable the core power manage in PMU_CORE_PM_CON reg, 57 * then, if the core enter into wfi, it power domain will be 58 * powered off automatically. it is core_pwr_wfi or core_pwr_wfi_int mode 59 * so we need core_pm_cfg_info to distinguish which method be used now. 60 */ 61 62 static uint32_t core_pm_cfg_info[PLATFORM_CORE_COUNT] 63 #if USE_COHERENT_MEM 64 __attribute__ ((section("tzfw_coherent_mem"))) 65 #endif 66 ;/* coheront */ 67 68 void rk3399_flash_l2_b(void) 69 { 70 uint32_t wait_cnt = 0; 71 72 mmio_setbits_32(PMU_BASE + PMU_SFT_CON, BIT(L2_FLUSH_REQ_CLUSTER_B)); 73 dsb(); 74 75 while (!(mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST) & 76 BIT(L2_FLUSHDONE_CLUSTER_B))) { 77 wait_cnt++; 78 if (!(wait_cnt % MAX_WAIT_CONUT)) 79 WARN("%s:reg %x,wait\n", __func__, 80 mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST)); 81 } 82 83 mmio_clrbits_32(PMU_BASE + PMU_SFT_CON, BIT(L2_FLUSH_REQ_CLUSTER_B)); 84 } 85 86 static void pmu_scu_b_pwrdn(void) 87 { 88 uint32_t wait_cnt = 0; 89 90 if ((mmio_read_32(PMU_BASE + PMU_PWRDN_ST) & 91 (BIT(PMU_A72_B0_PWRDWN_ST) | BIT(PMU_A72_B1_PWRDWN_ST))) != 92 (BIT(PMU_A72_B0_PWRDWN_ST) | BIT(PMU_A72_B1_PWRDWN_ST))) { 93 ERROR("%s: not all cpus is off\n", __func__); 94 return; 95 } 96 97 rk3399_flash_l2_b(); 98 99 mmio_setbits_32(PMU_BASE + PMU_SFT_CON, BIT(ACINACTM_CLUSTER_B_CFG)); 100 101 while (!(mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST) & 102 BIT(STANDBY_BY_WFIL2_CLUSTER_B))) { 103 wait_cnt++; 104 if (!(wait_cnt % MAX_WAIT_CONUT)) 105 ERROR("%s:wait cluster-b l2(%x)\n", __func__, 106 mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST)); 107 } 108 } 109 110 static void pmu_scu_b_pwrup(void) 111 { 112 mmio_clrbits_32(PMU_BASE + PMU_SFT_CON, BIT(ACINACTM_CLUSTER_B_CFG)); 113 } 114 115 void plat_rockchip_pmusram_prepare(void) 116 { 117 uint32_t *sram_dst, *sram_src; 118 size_t sram_size = 2; 119 120 /* 121 * pmu sram code and data prepare 122 */ 123 sram_dst = (uint32_t *)PMUSRAM_BASE; 124 sram_src = (uint32_t *)&pmu_cpuson_entrypoint_start; 125 sram_size = (uint32_t *)&pmu_cpuson_entrypoint_end - 126 (uint32_t *)sram_src; 127 128 u32_align_cpy(sram_dst, sram_src, sram_size); 129 130 psram_sleep_cfg->sp = PSRAM_DT_BASE; 131 } 132 133 static inline uint32_t get_cpus_pwr_domain_cfg_info(uint32_t cpu_id) 134 { 135 return core_pm_cfg_info[cpu_id]; 136 } 137 138 static inline void set_cpus_pwr_domain_cfg_info(uint32_t cpu_id, uint32_t value) 139 { 140 core_pm_cfg_info[cpu_id] = value; 141 #if !USE_COHERENT_MEM 142 flush_dcache_range((uintptr_t)&core_pm_cfg_info[cpu_id], 143 sizeof(uint32_t)); 144 #endif 145 } 146 147 static int cpus_power_domain_on(uint32_t cpu_id) 148 { 149 uint32_t cfg_info; 150 uint32_t cpu_pd = PD_CPUL0 + cpu_id; 151 /* 152 * There are two ways to powering on or off on core. 153 * 1) Control it power domain into on or off in PMU_PWRDN_CON reg 154 * 2) Enable the core power manage in PMU_CORE_PM_CON reg, 155 * then, if the core enter into wfi, it power domain will be 156 * powered off automatically. 157 */ 158 159 cfg_info = get_cpus_pwr_domain_cfg_info(cpu_id); 160 161 if (cfg_info == core_pwr_pd) { 162 /* disable core_pm cfg */ 163 mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), 164 CORES_PM_DISABLE); 165 /* if the cores have be on, power off it firstly */ 166 if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) { 167 mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), 0); 168 pmu_power_domain_ctr(cpu_pd, pmu_pd_off); 169 } 170 171 pmu_power_domain_ctr(cpu_pd, pmu_pd_on); 172 } else { 173 if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) { 174 WARN("%s: cpu%d is not in off,!\n", __func__, cpu_id); 175 return -EINVAL; 176 } 177 178 mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), 179 BIT(core_pm_sft_wakeup_en)); 180 dsb(); 181 } 182 183 return 0; 184 } 185 186 static int cpus_power_domain_off(uint32_t cpu_id, uint32_t pd_cfg) 187 { 188 uint32_t cpu_pd; 189 uint32_t core_pm_value; 190 191 cpu_pd = PD_CPUL0 + cpu_id; 192 if (pmu_power_domain_st(cpu_pd) == pmu_pd_off) 193 return 0; 194 195 if (pd_cfg == core_pwr_pd) { 196 if (check_cpu_wfie(cpu_id, CKECK_WFEI_MSK)) 197 return -EINVAL; 198 199 /* disable core_pm cfg */ 200 mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), 201 CORES_PM_DISABLE); 202 203 set_cpus_pwr_domain_cfg_info(cpu_id, pd_cfg); 204 pmu_power_domain_ctr(cpu_pd, pmu_pd_off); 205 } else { 206 set_cpus_pwr_domain_cfg_info(cpu_id, pd_cfg); 207 208 core_pm_value = BIT(core_pm_en); 209 if (pd_cfg == core_pwr_wfi_int) 210 core_pm_value |= BIT(core_pm_int_wakeup_en); 211 mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), 212 core_pm_value); 213 dsb(); 214 } 215 216 return 0; 217 } 218 219 static void nonboot_cpus_off(void) 220 { 221 uint32_t boot_cpu, cpu; 222 223 boot_cpu = plat_my_core_pos(); 224 225 /* turn off noboot cpus */ 226 for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) { 227 if (cpu == boot_cpu) 228 continue; 229 cpus_power_domain_off(cpu, core_pwr_pd); 230 } 231 } 232 233 static int cores_pwr_domain_on(unsigned long mpidr, uint64_t entrypoint) 234 { 235 uint32_t cpu_id = plat_core_pos_by_mpidr(mpidr); 236 237 assert(cpuson_flags[cpu_id] == 0); 238 cpuson_flags[cpu_id] = PMU_CPU_HOTPLUG; 239 cpuson_entry_point[cpu_id] = entrypoint; 240 dsb(); 241 242 cpus_power_domain_on(cpu_id); 243 244 return 0; 245 } 246 247 static int cores_pwr_domain_off(void) 248 { 249 uint32_t cpu_id = plat_my_core_pos(); 250 251 cpus_power_domain_off(cpu_id, core_pwr_wfi); 252 253 return 0; 254 } 255 256 static int cores_pwr_domain_suspend(void) 257 { 258 uint32_t cpu_id = plat_my_core_pos(); 259 260 assert(cpuson_flags[cpu_id] == 0); 261 cpuson_flags[cpu_id] = PMU_CPU_AUTO_PWRDN; 262 cpuson_entry_point[cpu_id] = (uintptr_t)psci_entrypoint; 263 dsb(); 264 265 cpus_power_domain_off(cpu_id, core_pwr_wfi_int); 266 267 return 0; 268 } 269 270 static int cores_pwr_domain_on_finish(void) 271 { 272 uint32_t cpu_id = plat_my_core_pos(); 273 274 /* Disable core_pm */ 275 mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), CORES_PM_DISABLE); 276 277 return 0; 278 } 279 280 static int cores_pwr_domain_resume(void) 281 { 282 uint32_t cpu_id = plat_my_core_pos(); 283 284 /* Disable core_pm */ 285 mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), CORES_PM_DISABLE); 286 287 return 0; 288 } 289 290 static void sys_slp_config(void) 291 { 292 uint32_t slp_mode_cfg = 0; 293 294 mmio_write_32(PMU_BASE + PMU_CCI500_CON, 295 BIT_WITH_WMSK(PMU_CLR_PREQ_CCI500_HW) | 296 BIT_WITH_WMSK(PMU_CLR_QREQ_CCI500_HW) | 297 BIT_WITH_WMSK(PMU_QGATING_CCI500_CFG)); 298 299 mmio_write_32(PMU_BASE + PMU_ADB400_CON, 300 BIT_WITH_WMSK(PMU_CLR_CORE_L_HW) | 301 BIT_WITH_WMSK(PMU_CLR_CORE_L_2GIC_HW) | 302 BIT_WITH_WMSK(PMU_CLR_GIC2_CORE_L_HW)); 303 304 mmio_write_32(PMUGRF_BASE + PMUGRF_GPIO1A_IOMUX, 305 BIT_WITH_WMSK(AP_PWROFF)); 306 307 slp_mode_cfg = BIT(PMU_PWR_MODE_EN) | 308 BIT(PMU_POWER_OFF_REQ_CFG) | 309 BIT(PMU_CPU0_PD_EN) | 310 BIT(PMU_L2_FLUSH_EN) | 311 BIT(PMU_L2_IDLE_EN) | 312 BIT(PMU_SCU_PD_EN); 313 314 mmio_setbits_32(PMU_BASE + PMU_WKUP_CFG4, PMU_CLUSTER_L_WKUP_EN); 315 mmio_setbits_32(PMU_BASE + PMU_WKUP_CFG4, PMU_CLUSTER_B_WKUP_EN); 316 mmio_clrbits_32(PMU_BASE + PMU_WKUP_CFG4, PMU_GPIO_WKUP_EN); 317 318 mmio_write_32(PMU_BASE + PMU_PWRMODE_CON, slp_mode_cfg); 319 320 mmio_write_32(PMU_BASE + PMU_STABLE_CNT, CYCL_24M_CNT_MS(5)); 321 mmio_write_32(PMU_BASE + PMU_SCU_L_PWRDN_CNT, CYCL_24M_CNT_MS(2)); 322 mmio_write_32(PMU_BASE + PMU_SCU_L_PWRUP_CNT, CYCL_24M_CNT_MS(2)); 323 mmio_write_32(PMU_BASE + PMU_SCU_B_PWRDN_CNT, CYCL_24M_CNT_MS(2)); 324 mmio_write_32(PMU_BASE + PMU_SCU_B_PWRUP_CNT, CYCL_24M_CNT_MS(2)); 325 } 326 327 static int sys_pwr_domain_suspend(void) 328 { 329 sys_slp_config(); 330 plls_suspend(); 331 pmu_sgrf_rst_hld(); 332 333 mmio_write_32(SGRF_BASE + SGRF_SOC_CON0_1(1), 334 (PMUSRAM_BASE >> CPU_BOOT_ADDR_ALIGN) | 335 CPU_BOOT_ADDR_WMASK); 336 337 pmu_scu_b_pwrdn(); 338 339 mmio_write_32(PMU_BASE + PMU_ADB400_CON, 340 BIT_WITH_WMSK(PMU_PWRDWN_REQ_CORE_B_2GIC_SW) | 341 BIT_WITH_WMSK(PMU_PWRDWN_REQ_CORE_B_SW) | 342 BIT_WITH_WMSK(PMU_PWRDWN_REQ_GIC2_CORE_B_SW)); 343 dsb(); 344 mmio_setbits_32(PMU_BASE + PMU_PWRDN_CON, BIT(PMU_SCU_B_PWRDWN_EN)); 345 346 return 0; 347 } 348 349 static int sys_pwr_domain_resume(void) 350 { 351 pmu_sgrf_rst_hld(); 352 353 mmio_write_32(SGRF_BASE + SGRF_SOC_CON0_1(1), 354 (cpu_warm_boot_addr >> CPU_BOOT_ADDR_ALIGN) | 355 CPU_BOOT_ADDR_WMASK); 356 357 plls_resume(); 358 359 mmio_write_32(PMU_BASE + PMU_CCI500_CON, 360 WMSK_BIT(PMU_CLR_PREQ_CCI500_HW) | 361 WMSK_BIT(PMU_CLR_QREQ_CCI500_HW) | 362 WMSK_BIT(PMU_QGATING_CCI500_CFG)); 363 364 mmio_write_32(PMU_BASE + PMU_ADB400_CON, 365 WMSK_BIT(PMU_CLR_CORE_L_HW) | 366 WMSK_BIT(PMU_CLR_CORE_L_2GIC_HW) | 367 WMSK_BIT(PMU_CLR_GIC2_CORE_L_HW)); 368 369 mmio_clrbits_32(PMU_BASE + PMU_PWRDN_CON, 370 BIT(PMU_SCU_B_PWRDWN_EN)); 371 372 mmio_write_32(PMU_BASE + PMU_ADB400_CON, 373 WMSK_BIT(PMU_PWRDWN_REQ_CORE_B_2GIC_SW) | 374 WMSK_BIT(PMU_PWRDWN_REQ_CORE_B_SW) | 375 WMSK_BIT(PMU_PWRDWN_REQ_GIC2_CORE_B_SW)); 376 377 pmu_scu_b_pwrup(); 378 379 plat_rockchip_gic_cpuif_enable(); 380 return 0; 381 } 382 383 static struct rockchip_pm_ops_cb pm_ops = { 384 .cores_pwr_dm_on = cores_pwr_domain_on, 385 .cores_pwr_dm_off = cores_pwr_domain_off, 386 .cores_pwr_dm_on_finish = cores_pwr_domain_on_finish, 387 .cores_pwr_dm_suspend = cores_pwr_domain_suspend, 388 .cores_pwr_dm_resume = cores_pwr_domain_resume, 389 .sys_pwr_dm_suspend = sys_pwr_domain_suspend, 390 .sys_pwr_dm_resume = sys_pwr_domain_resume, 391 .sys_gbl_soft_reset = soc_global_soft_reset, 392 }; 393 394 void plat_rockchip_pmu_init(void) 395 { 396 uint32_t cpu; 397 398 rockchip_pd_lock_init(); 399 plat_setup_rockchip_pm_ops(&pm_ops); 400 401 /* register requires 32bits mode, switch it to 32 bits */ 402 cpu_warm_boot_addr = (uint64_t)platform_cpu_warmboot; 403 404 for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) 405 cpuson_flags[cpu] = 0; 406 407 psram_sleep_cfg->ddr_func = 0x00; 408 psram_sleep_cfg->ddr_data = 0x00; 409 psram_sleep_cfg->ddr_flag = 0x00; 410 psram_sleep_cfg->boot_mpidr = read_mpidr_el1() & 0xffff; 411 412 /* cpu boot from pmusram */ 413 mmio_write_32(SGRF_BASE + SGRF_SOC_CON0_1(1), 414 (cpu_warm_boot_addr >> CPU_BOOT_ADDR_ALIGN) | 415 CPU_BOOT_ADDR_WMASK); 416 417 nonboot_cpus_off(); 418 419 INFO("%s(%d): pd status %x\n", __func__, __LINE__, 420 mmio_read_32(PMU_BASE + PMU_PWRDN_ST)); 421 } 422