1/* Copyright (c) 2022 Intel Corporation
2 * SPDX-License-Identifier: Apache-2.0
3 */
4
5#include "asm_ldo_management.h"
6#include "asm_memory_management.h"
7#include "adsp_memory.h"
8
9#define IPC_HOST_BASE		0x00071E00
10#define IPC_DIPCIDD		0x18
11#define IPC_DIPCIDR		0x10
12
13	.section .text, "ax"
14	.align 64
15power_down_literals:
16	.literal_position
17set_dx_reply:
18	/* BUSY (bit31), MODULE_MSG (bit30), reply (bit29), SET_DX (bit 24-28: 7) */
19	.word 0xE7000000
20sram_dis_loop_cnt:
21	.word 4096
22
23	.global power_down_cavs
24	.type power_down_cavs, @function
25
26/**
27 * Perform power down.
28 *
29 * Depending on arguments, memories are switched off.
30 * A2 - argument for LPSRAM
31 * A3 - pointer to array containing power gating mask.
32 *Size of array is determined by MEMORY_SEGMENTS define.
33 * A4 - platform type
34 * A5 - response_to_ipc
35 */
36
37#define b_enable_lpsram              a2
38#define pu32_hpsram_mask             a3
39#define temp_reg0                    a6
40#define temp_reg1                    a7
41#define temp_reg2                    a8
42#define temp_reg3                    a9
43#define host_base		     a10
44#define pfl_reg                      a15
45
46power_down_cavs:
47	entry sp, 32
48	/**
49	* effectively executes:
50	* xthal_dcache_region_lock(&literals, 128);
51	* xthal_icache_region_lock(&powerdown, 256);
52	* xthal_dcache_region_lock(&pu32_hpsram_mask, 64);
53	*/
54	movi pfl_reg, power_down_literals
55	dpfl pfl_reg, 0
56	dpfl pfl_reg, 64
57
58	movi pfl_reg, power_down_cavs
59	ipfl pfl_reg, 0
60	ipfl pfl_reg, 64
61	ipfl pfl_reg, 128
62	ipfl pfl_reg, 192
63
64	mov  pfl_reg, pu32_hpsram_mask
65	dpfl pfl_reg, 0
66
67	movi host_base, IPC_HOST_BASE
68
69_PD_DISABLE_LPSRAM:
70/* effectively executes:
71 * if (b_enable_lpsram){
72 *  cavs_lpsram_power_down_entire();
73 * }
74 */
75	beqz b_enable_lpsram, _PD_DISABLE_HPSRAM
76	m_cavs_lpsram_power_down_entire temp_reg0, temp_reg1, temp_reg2, sram_dis_loop_cnt
77	j _PD_DISABLE_HPSRAM
78
79_PD_DISABLE_HPSRAM:
80 /* if value in memory pointed by pu32_hpsram_mask = 0
81	 (hpsram_pwrgating_mask) - do not disable hpsram. */
82	beqz pu32_hpsram_mask, _PD_SEND_IPC
83
84/* mandatory sequence for LDO ON - effectively executes:
85 * m_cavs_s_set_ldo_hpsram_on_state();
86 * WAIT_300NS();
87 */
88	movi temp_reg0, SHIM_LDOCTL_HPSRAM_LDO_ON
89	m_cavs_set_hpldo_state temp_reg0, temp_reg1, temp_reg2
90	movi temp_reg0, 128
911 :
92	addi temp_reg0, temp_reg0, -1
93	bnez temp_reg0, 1b
94
95
96/* effectively executes:
97 * for (size_t seg_index = (MAX_MEMORY_SEGMENTS - 1); seg_index >= 0;
98 * --seg_index) {
99 * cavs_hpsram_power_change(seg_index, mask[seg_index]);
100 * }
101 * where mask is given in pu32_hpsram_mask register
102 */
103
104	.set seg_index, HPSRAM_SEGMENTS - 1
105	.rept HPSRAM_SEGMENTS
106	l32i temp_reg0, pu32_hpsram_mask, 4 * seg_index
107	m_cavs_hpsram_power_change\
108	/*segment_index=*/	seg_index,\
109	/*mask=*/	temp_reg0,\
110	temp_reg1,\
111	temp_reg2,\
112	temp_reg3
113	.set seg_index, seg_index - 1
114	.endr
115
116
117/* mandatory sequence for LDO OFF - effectively executes:
118 * WAIT_300NS();
119 * m_cavs_set_ldo_hpsram_on_state()
120 */
121	movi temp_reg0, 128
1221 :
123	addi temp_reg0, temp_reg0, -1
124	bnez temp_reg0, 1b
125
126	movi temp_reg0, SHIM_LDOCTL_HPSRAM_LDO_OFF
127	m_cavs_set_hpldo_state temp_reg0, temp_reg1, temp_reg2
128
129_PD_SEND_IPC:
130/* Send IPC reply for SET_DX message */
131	movi temp_reg1, 0
132	s32i temp_reg1, host_base, IPC_DIPCIDD
133
134	movi temp_reg1, set_dx_reply
135	l32i temp_reg1, temp_reg1, 0
136	s32i temp_reg1, host_base, IPC_DIPCIDR
137
138_PD_SLEEP:
139/* effecfively executes:
140 * xmp_spin()
141 * waiti 5
142 */
143	movi temp_reg0, 128
144loop:
145	addi temp_reg0, temp_reg0, -1
146	bnez temp_reg0, loop
147
148    extw
149    extw
150    waiti 5
151    1:
152    j 1b
153
154.size power_down_cavs , . - power_down_cavs
155
156
157