1/* SPDX-License-Identifier: BSD-3-Clause 2 * 3 * Copyright(c) 2016 Intel Corporation. All rights reserved. 4 * 5 * Author: Lech Betlej <lech.betlej@linux.intel.com> 6 */ 7 8/** 9 * \file platform/intel/cavs/lib/power_down.S 10 * \brief Power gating memory banks - implementation specific for platforms 11 * with cAVS 2.5 (i.e. Tiger Lake) 12 * \author Lech Betlej <lech.betlej@linux.intel.com> 13 */ 14 15 16#include <cavs/version.h> 17#include <cavs/drivers/sideband-ipc.h> 18#include <cavs/lib/asm_ldo_management.h> 19#include <cavs/lib/asm_memory_management.h> 20#include <sof/lib/memory.h> 21#include <sof/lib/shim.h> 22 23 .section .text, "ax" 24 .align 64 25power_down_literals: 26 .literal_position 27#if CONFIG_IPC_MAJOR_3 28ipc_flag: 29 .word IPC_DIPCTDR_BUSY 30#elif CONFIG_IPC_MAJOR_4 31set_dx_reply: 32 /* BUSY (bit31), MODULE_MSG (bit30), reply (bit29), SET_DX (bit 24-28: 7) */ 33 .word 0xE7000000 34 35#endif 36sram_dis_loop_cnt: 37 .word 4096 38 39 .global power_down 40 .type power_down, @function 41 42/** 43 * Perform power down. 44 * 45 * Depending on arguments, memories are switched off. 46 * A2 - argument for LPSRAM 47 * A3 - pointer to array containing power gating mask. 48 *Size of array is determined by MEMORY_SEGMENTS define. 49 * A4 - platform type 50 * A5 - response_to_ipc 51 */ 52 53#define b_enable_lpsram a2 54#define pu32_hpsram_mask a3 55#define temp_reg0 a6 56#define temp_reg1 a7 57#define temp_reg2 a8 58#define temp_reg3 a9 59#define host_base a10 60#define pfl_reg a15 61 62power_down: 63 entry sp, 32 64 // effectively executes: 65 // xthal_dcache_region_lock(&literals, 128); 66 // xthal_dcache_region_lock(&powerdown, 256); 67 // xthal_dcache_region_lock(&pu32_hpsram_mask, 64); 68 movi pfl_reg, power_down_literals 69 dpfl pfl_reg, 0 70 dpfl pfl_reg, 64 71 72 movi pfl_reg, power_down 73 ipfl pfl_reg, 0 74 ipfl pfl_reg, 64 75 ipfl pfl_reg, 128 76 ipfl pfl_reg, 192 77 78 mov pfl_reg, pu32_hpsram_mask 79 dpfl pfl_reg, 0 80 81_PD_DISABLE_LPSRAM: 82/* effectively executes: 83 * if (b_enable_lpsram){ 84 * cavs_lpsram_power_down_entire(); 85 * } 86 */ 87 movi host_base, IPC_HOST_BASE 88 89 beqz b_enable_lpsram, _PD_DISABLE_HPSRAM 90 m_cavs_lpsram_power_down_entire temp_reg0, temp_reg1, temp_reg2,\ 91 sram_dis_loop_cnt 92 j _PD_DISABLE_HPSRAM 93 94_PD_DISABLE_HPSRAM: 95 /* if value in memory pointed by pu32_hpsram_mask = 0 96 (hpsram_pwrgating_mask) - do not disable hpsram. */ 97 beqz pu32_hpsram_mask, _PD_SEND_IPC 98 99/* mandatory sequence for LDO ON - effectively executes: 100 * m_cavs_s_set_ldo_hpsram_on_state(); 101 * WAIT_300NS(); 102 */ 103 movi temp_reg0, SHIM_LDOCTL_HPSRAM_LDO_ON 104 m_cavs_set_hpldo_state temp_reg0, temp_reg1, temp_reg2 105 movi temp_reg0, 128 1061 : 107 addi temp_reg0, temp_reg0, -1 108 bnez temp_reg0, 1b 109 110 111/* effectively executes: 112 * for (size_t seg_index = (MAX_MEMORY_SEGMENTS - 1); seg_index >= 0; 113 * --seg_index) { 114 * cavs_hpsram_power_change(seg_index, mask[seg_index]); 115 * } 116 * where mask is given in pu32_hpsram_mask register 117 */ 118 119 .set seg_index, MAX_MEMORY_SEGMENTS - 1 120 .rept MAX_MEMORY_SEGMENTS 121 l32i temp_reg0, pu32_hpsram_mask, 4 * seg_index 122 m_cavs_hpsram_power_change\ 123 /*segment_index=*/ seg_index,\ 124 /*mask=*/ temp_reg0,\ 125 temp_reg1,\ 126 temp_reg2,\ 127 temp_reg3 128 .set seg_index, seg_index - 1 129 .endr 130 131 132/* mandatory sequence for LDO OFF - effectively executes: 133 * WAIT_300NS(); 134 * m_cavs_set_ldo_hpsram_on_state() 135 */ 136 movi temp_reg0, 128 1371 : 138 addi temp_reg0, temp_reg0, -1 139 bnez temp_reg0, 1b 140 141 movi temp_reg0, SHIM_LDOCTL_HPSRAM_LDO_OFF 142 m_cavs_set_hpldo_state temp_reg0, temp_reg1, temp_reg2 143 144_PD_SEND_IPC: 145#if CONFIG_IPC_MAJOR_3 146/* Send IPC to host informing of PD completion - Clear BUSY 147 * bit by writing IPC_DIPCTDR_BUSY to IPC_DIPCTDR 148 * and writing IPC_DIPCTDA_DONE to IPC_DIPCTDA 149 */ 150 l32i temp_reg1, host_base, IPC_DIPCTDR 151 movi temp_reg2, ipc_flag 152 l32i temp_reg2, temp_reg2, 0 153 or temp_reg1, temp_reg1, temp_reg2 154 s32i temp_reg1, host_base, IPC_DIPCTDR 155 156 l32i temp_reg1, host_base, IPC_DIPCTDA 157 or temp_reg1, temp_reg1, temp_reg2 158 s32i temp_reg1, host_base, IPC_DIPCTDA 159#elif CONFIG_IPC_MAJOR_4 160/* Send IPC reply for SET_DX message */ 161 movi temp_reg1, 0 162 s32i temp_reg1, host_base, IPC_DIPCIDD 163 164 movi temp_reg1, set_dx_reply 165 l32i temp_reg1, temp_reg1, 0 166 s32i temp_reg1, host_base, IPC_DIPCIDR 167#else 168#error "Support for this IPC version is not implemented" 169#endif 170 171_PD_SLEEP: 172/* effecfively executes: 173 * xmp_spin() 174 * waiti 5 175 */ 176 movi temp_reg0, 128 177loop: 178 addi temp_reg0, temp_reg0, -1 179 bnez temp_reg0, loop 180 181 extw 182 extw 183 waiti 5 184 1: 185 j 1b 186 187.size power_down , . - power_down 188