xref: /rk3399_ARM-atf/lib/extensions/amu/aarch32/amu.c (revision 81e2ff1f364fdf18e086f690eb3715bc89307592)
1ef69e1eaSDimitris Papastamos /*
2873d4241Sjohpow01  * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
3ef69e1eaSDimitris Papastamos  *
4ef69e1eaSDimitris Papastamos  * SPDX-License-Identifier: BSD-3-Clause
5ef69e1eaSDimitris Papastamos  */
6ef69e1eaSDimitris Papastamos 
7f3ccf036SAlexei Fedorov #include <assert.h>
833b9be6dSChris Kay #include <cdefs.h>
909d40e0eSAntonio Nino Diaz #include <stdbool.h>
1009d40e0eSAntonio Nino Diaz 
11ef69e1eaSDimitris Papastamos #include <arch.h>
12ef69e1eaSDimitris Papastamos #include <arch_helpers.h>
13f3ccf036SAlexei Fedorov 
1409d40e0eSAntonio Nino Diaz #include <lib/el3_runtime/pubsub_events.h>
1509d40e0eSAntonio Nino Diaz #include <lib/extensions/amu.h>
1609d40e0eSAntonio Nino Diaz #include <lib/extensions/amu_private.h>
17f3ccf036SAlexei Fedorov 
1809d40e0eSAntonio Nino Diaz #include <plat/common/platform.h>
19b6eb3932SDimitris Papastamos 
20b6eb3932SDimitris Papastamos static struct amu_ctx amu_ctxs[PLATFORM_CORE_COUNT];
21ef69e1eaSDimitris Papastamos 
2233b9be6dSChris Kay static inline __unused uint32_t read_id_pfr0_amu(void)
23ef69e1eaSDimitris Papastamos {
2433b9be6dSChris Kay 	return (read_id_pfr0() >> ID_PFR0_AMU_SHIFT) &
25873d4241Sjohpow01 		ID_PFR0_AMU_MASK;
26c70da546SJoel Hutton }
27c70da546SJoel Hutton 
2833b9be6dSChris Kay static inline __unused void write_hcptr_tam(uint32_t value)
2933b9be6dSChris Kay {
3033b9be6dSChris Kay 	write_hcptr((read_hcptr() & ~TAM_BIT) |
3133b9be6dSChris Kay 		((value << TAM_SHIFT) & TAM_BIT));
3233b9be6dSChris Kay }
3333b9be6dSChris Kay 
3433b9be6dSChris Kay static inline __unused void write_amcr_cg1rz(uint32_t value)
3533b9be6dSChris Kay {
3633b9be6dSChris Kay 	write_amcr((read_amcr() & ~AMCR_CG1RZ_BIT) |
3733b9be6dSChris Kay 		((value << AMCR_CG1RZ_SHIFT) & AMCR_CG1RZ_BIT));
3833b9be6dSChris Kay }
3933b9be6dSChris Kay 
4033b9be6dSChris Kay static inline __unused uint32_t read_amcfgr_ncg(void)
4133b9be6dSChris Kay {
4233b9be6dSChris Kay 	return (read_amcfgr() >> AMCFGR_NCG_SHIFT) &
4333b9be6dSChris Kay 		AMCFGR_NCG_MASK;
4433b9be6dSChris Kay }
4533b9be6dSChris Kay 
46*81e2ff1fSChris Kay static inline __unused uint32_t read_amcgcr_cg0nc(void)
47*81e2ff1fSChris Kay {
48*81e2ff1fSChris Kay 	return (read_amcgcr() >> AMCGCR_CG0NC_SHIFT) &
49*81e2ff1fSChris Kay 		AMCGCR_CG0NC_MASK;
50*81e2ff1fSChris Kay }
51*81e2ff1fSChris Kay 
5233b9be6dSChris Kay static inline __unused uint32_t read_amcgcr_cg1nc(void)
5333b9be6dSChris Kay {
5433b9be6dSChris Kay 	return (read_amcgcr() >> AMCGCR_CG1NC_SHIFT) &
5533b9be6dSChris Kay 		AMCGCR_CG1NC_MASK;
5633b9be6dSChris Kay }
5733b9be6dSChris Kay 
5833b9be6dSChris Kay static inline __unused uint32_t read_amcntenset0_px(void)
5933b9be6dSChris Kay {
6033b9be6dSChris Kay 	return (read_amcntenset0() >> AMCNTENSET0_Pn_SHIFT) &
6133b9be6dSChris Kay 		AMCNTENSET0_Pn_MASK;
6233b9be6dSChris Kay }
6333b9be6dSChris Kay 
6433b9be6dSChris Kay static inline __unused uint32_t read_amcntenset1_px(void)
6533b9be6dSChris Kay {
6633b9be6dSChris Kay 	return (read_amcntenset1() >> AMCNTENSET1_Pn_SHIFT) &
6733b9be6dSChris Kay 		AMCNTENSET1_Pn_MASK;
6833b9be6dSChris Kay }
6933b9be6dSChris Kay 
7033b9be6dSChris Kay static inline __unused void write_amcntenset0_px(uint32_t px)
7133b9be6dSChris Kay {
7233b9be6dSChris Kay 	uint32_t value = read_amcntenset0();
7333b9be6dSChris Kay 
7433b9be6dSChris Kay 	value &= ~AMCNTENSET0_Pn_MASK;
7533b9be6dSChris Kay 	value |= (px << AMCNTENSET0_Pn_SHIFT) &
7633b9be6dSChris Kay 		AMCNTENSET0_Pn_MASK;
7733b9be6dSChris Kay 
7833b9be6dSChris Kay 	write_amcntenset0(value);
7933b9be6dSChris Kay }
8033b9be6dSChris Kay 
8133b9be6dSChris Kay static inline __unused void write_amcntenset1_px(uint32_t px)
8233b9be6dSChris Kay {
8333b9be6dSChris Kay 	uint32_t value = read_amcntenset1();
8433b9be6dSChris Kay 
8533b9be6dSChris Kay 	value &= ~AMCNTENSET1_Pn_MASK;
8633b9be6dSChris Kay 	value |= (px << AMCNTENSET1_Pn_SHIFT) &
8733b9be6dSChris Kay 		AMCNTENSET1_Pn_MASK;
8833b9be6dSChris Kay 
8933b9be6dSChris Kay 	write_amcntenset1(value);
9033b9be6dSChris Kay }
9133b9be6dSChris Kay 
9233b9be6dSChris Kay static inline __unused void write_amcntenclr0_px(uint32_t px)
9333b9be6dSChris Kay {
9433b9be6dSChris Kay 	uint32_t value = read_amcntenclr0();
9533b9be6dSChris Kay 
9633b9be6dSChris Kay 	value &= ~AMCNTENCLR0_Pn_MASK;
9733b9be6dSChris Kay 	value |= (px << AMCNTENCLR0_Pn_SHIFT) & AMCNTENCLR0_Pn_MASK;
9833b9be6dSChris Kay 
9933b9be6dSChris Kay 	write_amcntenclr0(value);
10033b9be6dSChris Kay }
10133b9be6dSChris Kay 
10233b9be6dSChris Kay static inline __unused void write_amcntenclr1_px(uint32_t px)
10333b9be6dSChris Kay {
10433b9be6dSChris Kay 	uint32_t value = read_amcntenclr1();
10533b9be6dSChris Kay 
10633b9be6dSChris Kay 	value &= ~AMCNTENCLR1_Pn_MASK;
10733b9be6dSChris Kay 	value |= (px << AMCNTENCLR1_Pn_SHIFT) & AMCNTENCLR1_Pn_MASK;
10833b9be6dSChris Kay 
10933b9be6dSChris Kay 	write_amcntenclr1(value);
11033b9be6dSChris Kay }
11133b9be6dSChris Kay 
11233b9be6dSChris Kay static bool amu_supported(void)
11333b9be6dSChris Kay {
11433b9be6dSChris Kay 	return read_id_pfr0_amu() >= ID_PFR0_AMU_V1;
11533b9be6dSChris Kay }
11633b9be6dSChris Kay 
11733b9be6dSChris Kay static bool amu_v1p1_supported(void)
11833b9be6dSChris Kay {
11933b9be6dSChris Kay 	return read_id_pfr0_amu() >= ID_PFR0_AMU_V1P1;
12033b9be6dSChris Kay }
12133b9be6dSChris Kay 
12233b9be6dSChris Kay #if ENABLE_AMU_AUXILIARY_COUNTERS
123b4b726eaSChris Kay static bool amu_group1_supported(void)
124f3ccf036SAlexei Fedorov {
12533b9be6dSChris Kay 	return read_amcfgr_ncg() > 0U;
126f3ccf036SAlexei Fedorov }
127f3ccf036SAlexei Fedorov #endif
128f3ccf036SAlexei Fedorov 
129f3ccf036SAlexei Fedorov /*
130f3ccf036SAlexei Fedorov  * Enable counters. This function is meant to be invoked
131f3ccf036SAlexei Fedorov  * by the context management library before exiting from EL3.
132f3ccf036SAlexei Fedorov  */
13340daecc1SAntonio Nino Diaz void amu_enable(bool el2_unused)
134c70da546SJoel Hutton {
13533b9be6dSChris Kay 	if (!amu_supported()) {
1360767d50eSDimitris Papastamos 		return;
137f3ccf036SAlexei Fedorov 	}
138f3ccf036SAlexei Fedorov 
1391fd685a7SChris Kay #if ENABLE_AMU_AUXILIARY_COUNTERS
1401fd685a7SChris Kay 	if (AMU_GROUP1_NR_COUNTERS > 0U) {
141f3ccf036SAlexei Fedorov 		/* Check and set presence of group 1 counters */
142f3ccf036SAlexei Fedorov 		if (!amu_group1_supported()) {
143f3ccf036SAlexei Fedorov 			ERROR("AMU Counter Group 1 is not implemented\n");
144f3ccf036SAlexei Fedorov 			panic();
145f3ccf036SAlexei Fedorov 		}
146f3ccf036SAlexei Fedorov 
147f3ccf036SAlexei Fedorov 		/* Check number of group 1 counters */
14833b9be6dSChris Kay 		uint32_t cnt_num = read_amcgcr_cg1nc();
1491fd685a7SChris Kay 
150f3ccf036SAlexei Fedorov 		VERBOSE("%s%u. %s%u\n",
151f3ccf036SAlexei Fedorov 			"Number of AMU Group 1 Counters ", cnt_num,
152f3ccf036SAlexei Fedorov 			"Requested number ", AMU_GROUP1_NR_COUNTERS);
153f3ccf036SAlexei Fedorov 
154f3ccf036SAlexei Fedorov 		if (cnt_num < AMU_GROUP1_NR_COUNTERS) {
155f3ccf036SAlexei Fedorov 			ERROR("%s%u is less than %s%u\n",
156f3ccf036SAlexei Fedorov 			"Number of AMU Group 1 Counters ", cnt_num,
157f3ccf036SAlexei Fedorov 			"Requested number ", AMU_GROUP1_NR_COUNTERS);
158f3ccf036SAlexei Fedorov 			panic();
159f3ccf036SAlexei Fedorov 		}
1601fd685a7SChris Kay 	}
161f3ccf036SAlexei Fedorov #endif
1620767d50eSDimitris Papastamos 
163ef69e1eaSDimitris Papastamos 	if (el2_unused) {
164ef69e1eaSDimitris Papastamos 		/*
165ef69e1eaSDimitris Papastamos 		 * Non-secure access from EL0 or EL1 to the Activity Monitor
166ef69e1eaSDimitris Papastamos 		 * registers do not trap to EL2.
167ef69e1eaSDimitris Papastamos 		 */
16833b9be6dSChris Kay 		write_hcptr_tam(0U);
169ef69e1eaSDimitris Papastamos 	}
170ef69e1eaSDimitris Papastamos 
171ef69e1eaSDimitris Papastamos 	/* Enable group 0 counters */
172*81e2ff1fSChris Kay 	write_amcntenset0_px((UINT32_C(1) << read_amcgcr_cg0nc()) - 1U);
173c70da546SJoel Hutton 
1741fd685a7SChris Kay #if ENABLE_AMU_AUXILIARY_COUNTERS
1751fd685a7SChris Kay 	if (AMU_GROUP1_NR_COUNTERS > 0U) {
176c70da546SJoel Hutton 		/* Enable group 1 counters */
17733b9be6dSChris Kay 		write_amcntenset1_px(AMU_GROUP1_COUNTERS_MASK);
1781fd685a7SChris Kay 	}
179f3ccf036SAlexei Fedorov #endif
180873d4241Sjohpow01 
181873d4241Sjohpow01 	/* Initialize FEAT_AMUv1p1 features if present. */
18233b9be6dSChris Kay 	if (!amu_v1p1_supported()) {
183873d4241Sjohpow01 		return;
184873d4241Sjohpow01 	}
185873d4241Sjohpow01 
186873d4241Sjohpow01 #if AMU_RESTRICT_COUNTERS
187873d4241Sjohpow01 	/*
188873d4241Sjohpow01 	 * FEAT_AMUv1p1 adds a register field to restrict access to group 1
189873d4241Sjohpow01 	 * counters at all but the highest implemented EL.  This is controlled
190873d4241Sjohpow01 	 * with the AMU_RESTRICT_COUNTERS compile time flag, when set, system
191873d4241Sjohpow01 	 * register reads at lower ELs return zero.  Reads from the memory
192873d4241Sjohpow01 	 * mapped view are unaffected.
193873d4241Sjohpow01 	 */
194873d4241Sjohpow01 	VERBOSE("AMU group 1 counter access restricted.\n");
19533b9be6dSChris Kay 	write_amcr_cg1rz(1U);
196873d4241Sjohpow01 #else
19733b9be6dSChris Kay 	write_amcr_cg1rz(0U);
198873d4241Sjohpow01 #endif
199c70da546SJoel Hutton }
200c70da546SJoel Hutton 
201c70da546SJoel Hutton /* Read the group 0 counter identified by the given `idx`. */
202b4b726eaSChris Kay static uint64_t amu_group0_cnt_read(unsigned int idx)
203c70da546SJoel Hutton {
20433b9be6dSChris Kay 	assert(amu_supported());
205*81e2ff1fSChris Kay 	assert(idx < read_amcgcr_cg0nc());
206c70da546SJoel Hutton 
207c70da546SJoel Hutton 	return amu_group0_cnt_read_internal(idx);
208c70da546SJoel Hutton }
209c70da546SJoel Hutton 
210f3ccf036SAlexei Fedorov /* Write the group 0 counter identified by the given `idx` with `val` */
211b4b726eaSChris Kay static void amu_group0_cnt_write(unsigned  int idx, uint64_t val)
212c70da546SJoel Hutton {
21333b9be6dSChris Kay 	assert(amu_supported());
214*81e2ff1fSChris Kay 	assert(idx < read_amcgcr_cg0nc());
215c70da546SJoel Hutton 
216c70da546SJoel Hutton 	amu_group0_cnt_write_internal(idx, val);
217c70da546SJoel Hutton 	isb();
218c70da546SJoel Hutton }
219c70da546SJoel Hutton 
2201fd685a7SChris Kay #if ENABLE_AMU_AUXILIARY_COUNTERS
221f3ccf036SAlexei Fedorov /* Read the group 1 counter identified by the given `idx` */
222b4b726eaSChris Kay static uint64_t amu_group1_cnt_read(unsigned  int idx)
223c70da546SJoel Hutton {
22433b9be6dSChris Kay 	assert(amu_supported());
225f3ccf036SAlexei Fedorov 	assert(amu_group1_supported());
226f3ccf036SAlexei Fedorov 	assert(idx < AMU_GROUP1_NR_COUNTERS);
227c70da546SJoel Hutton 
228c70da546SJoel Hutton 	return amu_group1_cnt_read_internal(idx);
229c70da546SJoel Hutton }
230c70da546SJoel Hutton 
231f3ccf036SAlexei Fedorov /* Write the group 1 counter identified by the given `idx` with `val` */
232b4b726eaSChris Kay static void amu_group1_cnt_write(unsigned  int idx, uint64_t val)
233c70da546SJoel Hutton {
23433b9be6dSChris Kay 	assert(amu_supported());
235f3ccf036SAlexei Fedorov 	assert(amu_group1_supported());
236f3ccf036SAlexei Fedorov 	assert(idx < AMU_GROUP1_NR_COUNTERS);
237c70da546SJoel Hutton 
238c70da546SJoel Hutton 	amu_group1_cnt_write_internal(idx, val);
239c70da546SJoel Hutton 	isb();
240c70da546SJoel Hutton }
2411fd685a7SChris Kay #endif
242b6eb3932SDimitris Papastamos 
243b6eb3932SDimitris Papastamos static void *amu_context_save(const void *arg)
244b6eb3932SDimitris Papastamos {
245f3ccf036SAlexei Fedorov 	struct amu_ctx *ctx = &amu_ctxs[plat_my_core_pos()];
246f3ccf036SAlexei Fedorov 	unsigned int i;
247b6eb3932SDimitris Papastamos 
24833b9be6dSChris Kay 	if (!amu_supported()) {
249b6eb3932SDimitris Papastamos 		return (void *)-1;
250f3ccf036SAlexei Fedorov 	}
251b6eb3932SDimitris Papastamos 
2521fd685a7SChris Kay #if ENABLE_AMU_AUXILIARY_COUNTERS
2531fd685a7SChris Kay 	if (AMU_GROUP1_NR_COUNTERS > 0U) {
254f3ccf036SAlexei Fedorov 		if (!amu_group1_supported()) {
255f3ccf036SAlexei Fedorov 			return (void *)-1;
256f3ccf036SAlexei Fedorov 		}
2571fd685a7SChris Kay 	}
258f3ccf036SAlexei Fedorov #endif
2591fd685a7SChris Kay 
260f3ccf036SAlexei Fedorov 	/* Assert that group 0/1 counter configuration is what we expect */
261*81e2ff1fSChris Kay 	assert(read_amcntenset0_px() ==
262*81e2ff1fSChris Kay 		((UINT32_C(1) << read_amcgcr_cg0nc()) - 1U));
263b6eb3932SDimitris Papastamos 
2641fd685a7SChris Kay #if ENABLE_AMU_AUXILIARY_COUNTERS
2651fd685a7SChris Kay 	if (AMU_GROUP1_NR_COUNTERS > 0U) {
26633b9be6dSChris Kay 		assert(read_amcntenset1_px() == AMU_GROUP1_COUNTERS_MASK);
2671fd685a7SChris Kay 	}
268f3ccf036SAlexei Fedorov #endif
269b6eb3932SDimitris Papastamos 	/*
270f3ccf036SAlexei Fedorov 	 * Disable group 0/1 counters to avoid other observers like SCP sampling
271b6eb3932SDimitris Papastamos 	 * counter values from the future via the memory mapped view.
272b6eb3932SDimitris Papastamos 	 */
273*81e2ff1fSChris Kay 	write_amcntenclr0_px((UINT32_C(1) << read_amcgcr_cg0nc()) - 1U);
274f3ccf036SAlexei Fedorov 
2751fd685a7SChris Kay #if ENABLE_AMU_AUXILIARY_COUNTERS
2761fd685a7SChris Kay 	if (AMU_GROUP1_NR_COUNTERS > 0U) {
27733b9be6dSChris Kay 		write_amcntenclr1_px(AMU_GROUP1_COUNTERS_MASK);
2781fd685a7SChris Kay 	}
279f3ccf036SAlexei Fedorov #endif
2801fd685a7SChris Kay 
281b6eb3932SDimitris Papastamos 	isb();
282b6eb3932SDimitris Papastamos 
283f3ccf036SAlexei Fedorov 	/* Save all group 0 counters */
284*81e2ff1fSChris Kay 	for (i = 0U; i < read_amcgcr_cg0nc(); i++) {
285c70da546SJoel Hutton 		ctx->group0_cnts[i] = amu_group0_cnt_read(i);
286f3ccf036SAlexei Fedorov 	}
287c70da546SJoel Hutton 
2881fd685a7SChris Kay #if ENABLE_AMU_AUXILIARY_COUNTERS
2891fd685a7SChris Kay 	if (AMU_GROUP1_NR_COUNTERS > 0U) {
290f3ccf036SAlexei Fedorov 		/* Save group 1 counters */
291f3ccf036SAlexei Fedorov 		for (i = 0U; i < AMU_GROUP1_NR_COUNTERS; i++) {
292f3ccf036SAlexei Fedorov 			if ((AMU_GROUP1_COUNTERS_MASK & (1U << i)) != 0U) {
293c70da546SJoel Hutton 				ctx->group1_cnts[i] = amu_group1_cnt_read(i);
294f3ccf036SAlexei Fedorov 			}
295f3ccf036SAlexei Fedorov 		}
2961fd685a7SChris Kay 	}
297f3ccf036SAlexei Fedorov #endif
2981fd685a7SChris Kay 
29940daecc1SAntonio Nino Diaz 	return (void *)0;
300b6eb3932SDimitris Papastamos }
301b6eb3932SDimitris Papastamos 
302b6eb3932SDimitris Papastamos static void *amu_context_restore(const void *arg)
303b6eb3932SDimitris Papastamos {
304f3ccf036SAlexei Fedorov 	struct amu_ctx *ctx = &amu_ctxs[plat_my_core_pos()];
305f3ccf036SAlexei Fedorov 	unsigned int i;
306b6eb3932SDimitris Papastamos 
30733b9be6dSChris Kay 	if (!amu_supported()) {
308b6eb3932SDimitris Papastamos 		return (void *)-1;
309f3ccf036SAlexei Fedorov 	}
310b6eb3932SDimitris Papastamos 
3111fd685a7SChris Kay #if ENABLE_AMU_AUXILIARY_COUNTERS
3121fd685a7SChris Kay 	if (AMU_GROUP1_NR_COUNTERS > 0U) {
3131fd685a7SChris Kay 		if (!amu_group1_supported()) {
314f3ccf036SAlexei Fedorov 			return (void *)-1;
315f3ccf036SAlexei Fedorov 		}
3161fd685a7SChris Kay 	}
317f3ccf036SAlexei Fedorov #endif
3181fd685a7SChris Kay 
319b6eb3932SDimitris Papastamos 	/* Counters were disabled in `amu_context_save()` */
32033b9be6dSChris Kay 	assert(read_amcntenset0_px() == 0U);
321b6eb3932SDimitris Papastamos 
3221fd685a7SChris Kay #if ENABLE_AMU_AUXILIARY_COUNTERS
3231fd685a7SChris Kay 	if (AMU_GROUP1_NR_COUNTERS > 0U) {
32433b9be6dSChris Kay 		assert(read_amcntenset1_px() == 0U);
3251fd685a7SChris Kay 	}
326f3ccf036SAlexei Fedorov #endif
327f3ccf036SAlexei Fedorov 
328f3ccf036SAlexei Fedorov 	/* Restore all group 0 counters */
329*81e2ff1fSChris Kay 	for (i = 0U; i < read_amcgcr_cg0nc(); i++) {
330c70da546SJoel Hutton 		amu_group0_cnt_write(i, ctx->group0_cnts[i]);
331f3ccf036SAlexei Fedorov 	}
332b6eb3932SDimitris Papastamos 
333f3ccf036SAlexei Fedorov 	/* Restore group 0 counter configuration */
334*81e2ff1fSChris Kay 	write_amcntenset0_px((UINT32_C(1) << read_amcgcr_cg0nc()) - 1U);
335b6eb3932SDimitris Papastamos 
3361fd685a7SChris Kay #if ENABLE_AMU_AUXILIARY_COUNTERS
3371fd685a7SChris Kay 	if (AMU_GROUP1_NR_COUNTERS > 0U) {
338f3ccf036SAlexei Fedorov 		/* Restore group 1 counters */
339f3ccf036SAlexei Fedorov 		for (i = 0U; i < AMU_GROUP1_NR_COUNTERS; i++) {
340f3ccf036SAlexei Fedorov 			if ((AMU_GROUP1_COUNTERS_MASK & (1U << i)) != 0U) {
341f3ccf036SAlexei Fedorov 				amu_group1_cnt_write(i, ctx->group1_cnts[i]);
342f3ccf036SAlexei Fedorov 			}
343f3ccf036SAlexei Fedorov 		}
344f3ccf036SAlexei Fedorov 
345f3ccf036SAlexei Fedorov 		/* Restore group 1 counter configuration */
34633b9be6dSChris Kay 		write_amcntenset1_px(AMU_GROUP1_COUNTERS_MASK);
3471fd685a7SChris Kay 	}
348f3ccf036SAlexei Fedorov #endif
349f3ccf036SAlexei Fedorov 
35040daecc1SAntonio Nino Diaz 	return (void *)0;
351b6eb3932SDimitris Papastamos }
352b6eb3932SDimitris Papastamos 
353b6eb3932SDimitris Papastamos SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_start, amu_context_save);
354b6eb3932SDimitris Papastamos SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_finish, amu_context_restore);
355