xref: /rk3399_rockchip-uboot/drivers/cpu/rockchip_amp.c (revision 49cfbee5b0f5f60b2089257e5ddae83202d00c23)
14388decaSJoseph Chen // SPDX-License-Identifier: GPL-2.0
24388decaSJoseph Chen /*
331f8f6ebSJoseph Chen  * Copyright (c) 2021 Rockchip Electronics Co., Ltd
44388decaSJoseph Chen  */
531f8f6ebSJoseph Chen 
64388decaSJoseph Chen #include <common.h>
74388decaSJoseph Chen #include <amp.h>
84388decaSJoseph Chen #include <bidram.h>
931f8f6ebSJoseph Chen #include <boot_rkimg.h>
10*49cfbee5SJoseph Chen #include <config.h>
114388decaSJoseph Chen #include <sysmem.h>
12*49cfbee5SJoseph Chen #include <asm/gic.h>
13*49cfbee5SJoseph Chen #include <asm/io.h>
144388decaSJoseph Chen #include <asm/arch/rockchip_smccc.h>
154388decaSJoseph Chen 
16bb4a1f43SJoseph Chen /*
17bb4a1f43SJoseph Chen  * [Design Principles]
18bb4a1f43SJoseph Chen  *
19bb4a1f43SJoseph Chen  * [amp.img]
20bb4a1f43SJoseph Chen  *	The amp image with FIT format which consists of non-linux firmwares.
21bb4a1f43SJoseph Chen  *	Please refer to: driver/cpu/amp.its.
22bb4a1f43SJoseph Chen  *
23bb4a1f43SJoseph Chen  *	amp.img generation: ./tools/mkimage -f drivers/cpu/amp.its -E -p 0xe00 amp.img
24bb4a1f43SJoseph Chen  *
25bb4a1f43SJoseph Chen  * [linux]
26bb4a1f43SJoseph Chen  *	We still use the traditional solution for a better compatibility:
27bb4a1f43SJoseph Chen  *	boot.img/recovery.img with FIT format or Android format.
28bb4a1f43SJoseph Chen  *
29bb4a1f43SJoseph Chen  *	The developer need add "/configurations/conf/linux" node to configure:
30bb4a1f43SJoseph Chen  *	description, arch, cpu, thumb, hyp, udelay(optional) properties.
31bb4a1f43SJoseph Chen  *	The addresses depend on U-Boot: kernel_addr_r, fdt_addr_r and
32bb4a1f43SJoseph Chen  *	ramdisk_addr_r. Please refer to: driver/cpu/amp.its.
33bb4a1f43SJoseph Chen  *
34bb4a1f43SJoseph Chen  * [memory management]
35bb4a1f43SJoseph Chen  *	U-Boot is not responsible for memory distribution/fixup any more, please
36bb4a1f43SJoseph Chen  *	handle this on kernel dts "/memory".
37bb4a1f43SJoseph Chen  *
38bb4a1f43SJoseph Chen  * [trust]
39bb4a1f43SJoseph Chen  *	The AMP feature requires trust support.
40bb4a1f43SJoseph Chen  */
41bb4a1f43SJoseph Chen 
4231f8f6ebSJoseph Chen #define AMP_PART	"amp"
43*49cfbee5SJoseph Chen #define gicd_readl(offset)	readl((void *)GICD_BASE + (offset))
44*49cfbee5SJoseph Chen #define gicd_writel(v, offset)	writel(v, (void *)GICD_BASE + (offset))
454388decaSJoseph Chen 
46bb4a1f43SJoseph Chen typedef struct boot_args {
47bb4a1f43SJoseph Chen 	ulong arg0;
48bb4a1f43SJoseph Chen 	ulong arg1;
49bb4a1f43SJoseph Chen 	ulong arg2;
50bb4a1f43SJoseph Chen 	ulong arg3;
51bb4a1f43SJoseph Chen } boot_args_t;
52bb4a1f43SJoseph Chen 
53bb4a1f43SJoseph Chen typedef struct boot_cpu {
54bb4a1f43SJoseph Chen 	u32 arch;
55bb4a1f43SJoseph Chen 	u32 state;
56bb4a1f43SJoseph Chen 	u32 entry;
57bb4a1f43SJoseph Chen 	u32 linux_os;
58bb4a1f43SJoseph Chen } boot_cpu_t;
59bb4a1f43SJoseph Chen 
60bb4a1f43SJoseph Chen static boot_cpu_t g_bootcpu;
6131f8f6ebSJoseph Chen 
6231f8f6ebSJoseph Chen static u32 fit_get_u32_default(const void *fit, int noffset,
6331f8f6ebSJoseph Chen 			       const char *prop, u32 def)
640df2c3dfSJoseph Chen {
6531f8f6ebSJoseph Chen 	const fdt32_t *val;
660df2c3dfSJoseph Chen 
6731f8f6ebSJoseph Chen 	val = fdt_getprop(fit, noffset, prop, NULL);
6831f8f6ebSJoseph Chen 	if (!val)
6931f8f6ebSJoseph Chen 		return def;
700df2c3dfSJoseph Chen 
7131f8f6ebSJoseph Chen 	return fdt32_to_cpu(*val);
720df2c3dfSJoseph Chen }
730df2c3dfSJoseph Chen 
74bb4a1f43SJoseph Chen static int load_linux_for_nonboot_cpu(u32 cpu, u32 aarch64, u32 load,
75bb4a1f43SJoseph Chen 				      u32 *entry, boot_args_t *args)
764388decaSJoseph Chen {
77bb4a1f43SJoseph Chen 	static const char *boot_cmd[] = {
78bb4a1f43SJoseph Chen 		"boot_fit", "boot_android ${devtype} ${devnum}" };
79bb4a1f43SJoseph Chen 	int i, ret;
80bb4a1f43SJoseph Chen 
81bb4a1f43SJoseph Chen 	env_set_hex("bootm_states_unmask", BOOTM_STATE_OS_GO);
82bb4a1f43SJoseph Chen 	for (i = 0; i < ARRAY_SIZE(boot_cmd); i++) {
83bb4a1f43SJoseph Chen 		ret = run_command(boot_cmd[i], 0);
84bb4a1f43SJoseph Chen 		if (!ret)
85bb4a1f43SJoseph Chen 			break;
86bb4a1f43SJoseph Chen 	}
87bb4a1f43SJoseph Chen 	env_set("bootm_states_unmask", NULL);
88bb4a1f43SJoseph Chen 	if (ret) {
89bb4a1f43SJoseph Chen 		AMP_E("Load linux failed, ret=%d\n", ret);
90bb4a1f43SJoseph Chen 		return ret;
91bb4a1f43SJoseph Chen 	}
92bb4a1f43SJoseph Chen 
93bb4a1f43SJoseph Chen 	/* linux boot args */
94bb4a1f43SJoseph Chen 	if (aarch64) {
95bb4a1f43SJoseph Chen 		args->arg0 = (ulong)gd->fdt_blob;
96bb4a1f43SJoseph Chen 		args->arg1 = 0;
97bb4a1f43SJoseph Chen 		args->arg2 = 0;
98bb4a1f43SJoseph Chen 	} else {
99bb4a1f43SJoseph Chen 		args->arg0 = 0;
100bb4a1f43SJoseph Chen 		args->arg1 = 0;
101bb4a1f43SJoseph Chen 		args->arg2 = (ulong)gd->fdt_blob;
102bb4a1f43SJoseph Chen 	}
103bb4a1f43SJoseph Chen 
104bb4a1f43SJoseph Chen 	/* don't need call cleanup_before_linux() as this nonboot cpu is clean */
105bb4a1f43SJoseph Chen 	board_quiesce_devices(&images);
106bb4a1f43SJoseph Chen 	flush_dcache_all();
107bb4a1f43SJoseph Chen 
108bb4a1f43SJoseph Chen 	/* fixup: ramdisk/fdt/entry depend on U-Boot */
109bb4a1f43SJoseph Chen 	*entry = env_get_ulong("kernel_addr_r", 16, 0);
110bb4a1f43SJoseph Chen 
111bb4a1f43SJoseph Chen 	return 0;
112bb4a1f43SJoseph Chen }
113bb4a1f43SJoseph Chen 
114bb4a1f43SJoseph Chen static int is_default_pe_state(u32 pe_state)
115bb4a1f43SJoseph Chen {
116bb4a1f43SJoseph Chen #ifdef CONFIG_ARM64
117bb4a1f43SJoseph Chen 	return (pe_state == PE_STATE(1, 1, 0, 0));
118bb4a1f43SJoseph Chen #else
119bb4a1f43SJoseph Chen 	return (pe_state == PE_STATE(0, 0, 0, 0));
120bb4a1f43SJoseph Chen #endif
121bb4a1f43SJoseph Chen }
122bb4a1f43SJoseph Chen 
123*49cfbee5SJoseph Chen static void setup_sync_bits_for_linux(void)
124*49cfbee5SJoseph Chen {
125*49cfbee5SJoseph Chen 	u32 val, num_irq, offset;
126*49cfbee5SJoseph Chen 
127*49cfbee5SJoseph Chen 	val = gicd_readl(GICD_CTLR);
128*49cfbee5SJoseph Chen 	val &= ~0x3;
129*49cfbee5SJoseph Chen 	gicd_writel(val, GICD_CTLR);
130*49cfbee5SJoseph Chen 
131*49cfbee5SJoseph Chen 	num_irq = 32 * ((gicd_readl(GICD_TYPER) & 0x1F) + 1);
132*49cfbee5SJoseph Chen 	offset = ((num_irq - 1) / 4) * 4;
133*49cfbee5SJoseph Chen 	gicd_writel(0x0, GICD_IPRIORITYRn + offset);
134*49cfbee5SJoseph Chen }
135*49cfbee5SJoseph Chen 
136bb4a1f43SJoseph Chen static int smc_cpu_on(u32 cpu, u32 pe_state, u32 entry, boot_args_t *args)
137bb4a1f43SJoseph Chen {
13831f8f6ebSJoseph Chen 	int ret;
1394388decaSJoseph Chen 
140bb4a1f43SJoseph Chen 	AMP_I("Brought up cpu[%x] with state 0x%x, entry 0x%08x ...",
141bb4a1f43SJoseph Chen 	      cpu, pe_state, entry);
142bb4a1f43SJoseph Chen 
143bb4a1f43SJoseph Chen 	if (is_default_pe_state(pe_state))
144bb4a1f43SJoseph Chen 		goto finish;
145bb4a1f43SJoseph Chen 
146bb4a1f43SJoseph Chen 	ret = sip_smc_amp_cfg(AMP_PE_STATE, cpu, pe_state, 0);
147bb4a1f43SJoseph Chen 	if (ret) {
148bb4a1f43SJoseph Chen 		AMP_E("smc pe-state, ret=%d\n", ret);
149bb4a1f43SJoseph Chen 		return ret;
150bb4a1f43SJoseph Chen 	}
151bb4a1f43SJoseph Chen 
152bb4a1f43SJoseph Chen 	ret = sip_smc_amp_cfg(AMP_BOOT_ARG01, cpu, args->arg0, args->arg1);
153bb4a1f43SJoseph Chen 	if (ret) {
154bb4a1f43SJoseph Chen 		AMP_E("smc boot arg01, ret=%d\n", ret);
155bb4a1f43SJoseph Chen 		return ret;
156bb4a1f43SJoseph Chen 	}
157bb4a1f43SJoseph Chen 
158bb4a1f43SJoseph Chen 	ret = sip_smc_amp_cfg(AMP_BOOT_ARG23, cpu, args->arg2, args->arg3);
159bb4a1f43SJoseph Chen 	if (ret) {
160bb4a1f43SJoseph Chen 		AMP_E("smc boot arg23, ret=%d\n", ret);
161bb4a1f43SJoseph Chen 		return ret;
162bb4a1f43SJoseph Chen 	}
163bb4a1f43SJoseph Chen 
164bb4a1f43SJoseph Chen finish:
165bb4a1f43SJoseph Chen 	ret = psci_cpu_on(cpu, entry);
166bb4a1f43SJoseph Chen 	if (ret) {
167bb4a1f43SJoseph Chen 		printf("cpu up failed, ret=%d\n", ret);
168bb4a1f43SJoseph Chen 		return ret;
169bb4a1f43SJoseph Chen 	}
170bb4a1f43SJoseph Chen 	printf("OK\n");
171bb4a1f43SJoseph Chen 
172bb4a1f43SJoseph Chen 	return 0;
173bb4a1f43SJoseph Chen }
174bb4a1f43SJoseph Chen 
175bb4a1f43SJoseph Chen static int brought_up_amp(void *fit, int noffset,
176bb4a1f43SJoseph Chen 			  boot_cpu_t *bootcpu, int is_linux)
177bb4a1f43SJoseph Chen {
178bb4a1f43SJoseph Chen 	const char *desc;
179bb4a1f43SJoseph Chen 	boot_args_t args;
180bb4a1f43SJoseph Chen 	u32 cpu, aarch64, hyp;
181bb4a1f43SJoseph Chen 	u32 load, thumb, us;
182bb4a1f43SJoseph Chen 	u32 pe_state, entry;
183bb4a1f43SJoseph Chen 	int data_size;
184bb4a1f43SJoseph Chen 	int ret;
185bb4a1f43SJoseph Chen 	u8  arch = -ENODATA;
1864388decaSJoseph Chen 
18731f8f6ebSJoseph Chen 	desc = fdt_getprop(fit, noffset, "description", NULL);
18831f8f6ebSJoseph Chen 	cpu = fit_get_u32_default(fit, noffset, "cpu", -ENODATA);
18931f8f6ebSJoseph Chen 	hyp = fit_get_u32_default(fit, noffset, "hyp", 0);
19031f8f6ebSJoseph Chen 	thumb = fit_get_u32_default(fit, noffset, "thumb", 0);
19131f8f6ebSJoseph Chen 	load = fit_get_u32_default(fit, noffset, "load", -ENODATA);
19231f8f6ebSJoseph Chen 	us = fit_get_u32_default(fit, noffset, "udelay", 0);
19331f8f6ebSJoseph Chen 	fit_image_get_arch(fit, noffset, &arch);
19431f8f6ebSJoseph Chen 	fit_image_get_data_size(fit, noffset, &data_size);
195bb4a1f43SJoseph Chen 	memset(&args, 0, sizeof(args));
1964388decaSJoseph Chen 
197bb4a1f43SJoseph Chen 	if (!desc || cpu == -ENODATA || arch == -ENODATA ||
198bb4a1f43SJoseph Chen 	    (load == -ENODATA && !is_linux)) {
199bb4a1f43SJoseph Chen 		AMP_E("Property missing!\n");
20031f8f6ebSJoseph Chen 		return -EINVAL;
2014388decaSJoseph Chen 	}
20231f8f6ebSJoseph Chen 	aarch64 = (arch == IH_ARCH_ARM) ? 0 : 1;
203bb4a1f43SJoseph Chen 	pe_state = PE_STATE(aarch64, hyp, thumb, 0);
204bb4a1f43SJoseph Chen 	entry = load;
20531f8f6ebSJoseph Chen 
20631f8f6ebSJoseph Chen #ifdef DEBUG
207bb4a1f43SJoseph Chen 	AMP_I("       desc: %s\n", desc);
20831f8f6ebSJoseph Chen 	AMP_I("        cpu: 0x%x\n", cpu);
20931f8f6ebSJoseph Chen 	AMP_I("    aarch64: %d\n", aarch64);
21031f8f6ebSJoseph Chen 	AMP_I("        hyp: %d\n", hyp);
21131f8f6ebSJoseph Chen 	AMP_I("      thumb: %d\n", thumb);
21231f8f6ebSJoseph Chen 	AMP_I("      entry: 0x%08x\n", entry);
213bb4a1f43SJoseph Chen 	AMP_I("   pe_state: 0x%08x\n", pe_state);
214bb4a1f43SJoseph Chen 	AMP_I("   linux-os: %d\n\n", is_linux);
21531f8f6ebSJoseph Chen #endif
21631f8f6ebSJoseph Chen 
2176aef53bdSJoseph Chen 	if ((read_mpidr() & 0x0fff) == cpu) {
218bb4a1f43SJoseph Chen 		bootcpu->arch = arch;
219bb4a1f43SJoseph Chen 		bootcpu->entry = entry;
220bb4a1f43SJoseph Chen 		bootcpu->state = pe_state;
221bb4a1f43SJoseph Chen 		bootcpu->linux_os = is_linux;
222bb4a1f43SJoseph Chen 		return 0;
2236aef53bdSJoseph Chen 	}
2246aef53bdSJoseph Chen 
225bb4a1f43SJoseph Chen 	/* === only nonboot cpu can reach here === */
226bb4a1f43SJoseph Chen 
227bb4a1f43SJoseph Chen 	/* load or check */
228bb4a1f43SJoseph Chen 	if (is_linux) {
229bb4a1f43SJoseph Chen 		ret = load_linux_for_nonboot_cpu(cpu,
230bb4a1f43SJoseph Chen 				aarch64, load, &entry, &args);
231bb4a1f43SJoseph Chen 		if (ret)
232bb4a1f43SJoseph Chen 			return ret;
233*49cfbee5SJoseph Chen 		/*
234*49cfbee5SJoseph Chen 		 * Must setup before jump to linux.
235*49cfbee5SJoseph Chen 		 * This is an appointment on RK amp solution to handle
236*49cfbee5SJoseph Chen 		 * GIC configure competition.
237*49cfbee5SJoseph Chen 		 */
238*49cfbee5SJoseph Chen 		setup_sync_bits_for_linux();
239bb4a1f43SJoseph Chen 	} else {
240bb4a1f43SJoseph Chen 		if (!sysmem_alloc_base_by_name(desc,
241bb4a1f43SJoseph Chen 				(phys_addr_t)load, data_size))
24231f8f6ebSJoseph Chen 			return -ENXIO;
243f06413e4SJoseph Chen 	}
2444388decaSJoseph Chen 
245bb4a1f43SJoseph Chen 	/* wakeup */
246bb4a1f43SJoseph Chen 	ret = smc_cpu_on(cpu, pe_state, entry, &args);
247bb4a1f43SJoseph Chen 	if (ret)
24839be8a08SJoseph Chen 		return ret;
24931f8f6ebSJoseph Chen 
25031f8f6ebSJoseph Chen 	if (us)
25131f8f6ebSJoseph Chen 		udelay(us);
252bb4a1f43SJoseph Chen 
253bb4a1f43SJoseph Chen 	return 0;
25439be8a08SJoseph Chen }
2554388decaSJoseph Chen 
256bb4a1f43SJoseph Chen static int brought_up_all_amp(void *fit, const char *fit_uname_cfg)
257bb4a1f43SJoseph Chen {
258bb4a1f43SJoseph Chen 	int loadables_index;
259bb4a1f43SJoseph Chen 	int linux_noffset;
260bb4a1f43SJoseph Chen 	int conf_noffset;
261bb4a1f43SJoseph Chen 	int cpu_noffset;
262bb4a1f43SJoseph Chen 	int ret;
263bb4a1f43SJoseph Chen 	const char *uname;
264bb4a1f43SJoseph Chen 
265bb4a1f43SJoseph Chen 	conf_noffset = fit_conf_get_node(fit, fit_uname_cfg);
266bb4a1f43SJoseph Chen 	if (conf_noffset < 0)
267bb4a1f43SJoseph Chen 		return conf_noffset;
268bb4a1f43SJoseph Chen 
269bb4a1f43SJoseph Chen 	linux_noffset = fdt_subnode_offset(fit, conf_noffset, "linux");
270bb4a1f43SJoseph Chen 	if (linux_noffset > 0) {
271bb4a1f43SJoseph Chen 		ret = brought_up_amp(fit, linux_noffset, &g_bootcpu, 1);
272bb4a1f43SJoseph Chen 		if (ret)
273bb4a1f43SJoseph Chen 			return ret;
274bb4a1f43SJoseph Chen 	}
275bb4a1f43SJoseph Chen 
276bb4a1f43SJoseph Chen 	for (loadables_index = 0;
277bb4a1f43SJoseph Chen 	     uname = fdt_stringlist_get(fit, conf_noffset,
278bb4a1f43SJoseph Chen 			FIT_LOADABLE_PROP, loadables_index, NULL), uname;
279bb4a1f43SJoseph Chen 	     loadables_index++) {
280bb4a1f43SJoseph Chen 		cpu_noffset = fit_image_get_node(fit, uname);
281bb4a1f43SJoseph Chen 		if (cpu_noffset < 0)
282bb4a1f43SJoseph Chen 			return cpu_noffset;
283bb4a1f43SJoseph Chen 
284bb4a1f43SJoseph Chen 		ret = brought_up_amp(fit, cpu_noffset, &g_bootcpu, 0);
285bb4a1f43SJoseph Chen 		if (ret)
286bb4a1f43SJoseph Chen 			return ret;
287bb4a1f43SJoseph Chen 	}
288bb4a1f43SJoseph Chen 
289bb4a1f43SJoseph Chen 	/* === only boot cpu can reach here === */
290bb4a1f43SJoseph Chen 
291bb4a1f43SJoseph Chen 	if (!g_bootcpu.linux_os) {
29231f8f6ebSJoseph Chen 		flush_dcache_all();
29331f8f6ebSJoseph Chen 		AMP_I("Brought up cpu[%x, self] with state 0x%x, entry 0x%08x ...",
294bb4a1f43SJoseph Chen 		      (u32)read_mpidr() & 0x0fff, g_bootcpu.state, g_bootcpu.entry);
29531f8f6ebSJoseph Chen 		cleanup_before_linux();
29631f8f6ebSJoseph Chen 		printf("OK\n");
297bb4a1f43SJoseph Chen 		armv8_switch_to_el2(0, 0, 0, g_bootcpu.state, (u64)g_bootcpu.entry,
298bb4a1f43SJoseph Chen 		     g_bootcpu.arch == IH_ARCH_ARM ? ES_TO_AARCH32 : ES_TO_AARCH64);
2994388decaSJoseph Chen 	}
3004388decaSJoseph Chen 
301bb4a1f43SJoseph Chen 	/* return: boot cpu continue to boot linux */
302bb4a1f43SJoseph Chen 	return 0;
30331f8f6ebSJoseph Chen }
3044388decaSJoseph Chen 
30531f8f6ebSJoseph Chen int amp_cpus_on(void)
3064388decaSJoseph Chen {
30731f8f6ebSJoseph Chen 	struct blk_desc *dev_desc;
30831f8f6ebSJoseph Chen 	bootm_headers_t images;
30931f8f6ebSJoseph Chen 	disk_partition_t part;
31031f8f6ebSJoseph Chen 	void *fit;
31131f8f6ebSJoseph Chen 	int ret = 0;
31231f8f6ebSJoseph Chen 
31331f8f6ebSJoseph Chen 	dev_desc = rockchip_get_bootdev();
31431f8f6ebSJoseph Chen 	if (!dev_desc)
31531f8f6ebSJoseph Chen 		return -EIO;
31631f8f6ebSJoseph Chen 
31731f8f6ebSJoseph Chen 	if (part_get_info_by_name(dev_desc, AMP_PART, &part) < 0)
31831f8f6ebSJoseph Chen 		return -ENODEV;
31931f8f6ebSJoseph Chen 
320bb4a1f43SJoseph Chen 	fit = malloc(part.size * part.blksz);
321bb4a1f43SJoseph Chen 	if (!fit) {
322bb4a1f43SJoseph Chen 		AMP_E("No memory, please increase CONFIG_SYS_MALLOC_LEN\n");
32331f8f6ebSJoseph Chen 		return -ENOMEM;
324bb4a1f43SJoseph Chen 	}
32531f8f6ebSJoseph Chen 
32631f8f6ebSJoseph Chen 	if (blk_dread(dev_desc, part.start, part.size, fit) != part.size) {
32731f8f6ebSJoseph Chen 		ret = -EIO;
32831f8f6ebSJoseph Chen 		goto out;
3294388decaSJoseph Chen 	}
3304388decaSJoseph Chen 
33131f8f6ebSJoseph Chen 	if (fdt_check_header(fit)) {
332bb4a1f43SJoseph Chen 		AMP_E("Not fit\n");
33331f8f6ebSJoseph Chen 		ret = -EINVAL;
33431f8f6ebSJoseph Chen 		goto out;
33531f8f6ebSJoseph Chen 	}
3364388decaSJoseph Chen 
337bb4a1f43SJoseph Chen 	/* Load loadables */
33831f8f6ebSJoseph Chen 	memset(&images, 0, sizeof(images));
33931f8f6ebSJoseph Chen 	images.fit_uname_cfg = "conf";
34031f8f6ebSJoseph Chen 	images.fit_hdr_os = fit;
34131f8f6ebSJoseph Chen 	images.verify = 1;
342bb4a1f43SJoseph Chen 	ret = boot_get_loadable(0, NULL, &images, IH_ARCH_DEFAULT, NULL, NULL);
34331f8f6ebSJoseph Chen 	if (ret) {
344bb4a1f43SJoseph Chen 		AMP_E("Load loadables, ret=%d\n", ret);
345bb4a1f43SJoseph Chen 		goto out;
34631f8f6ebSJoseph Chen 	}
34731f8f6ebSJoseph Chen 	flush_dcache_all();
34831f8f6ebSJoseph Chen 
349bb4a1f43SJoseph Chen 	/* Wakeup */
35031f8f6ebSJoseph Chen 	ret = brought_up_all_amp(images.fit_hdr_os, images.fit_uname_cfg);
351bb4a1f43SJoseph Chen 	if (ret)
352bb4a1f43SJoseph Chen 		AMP_E("Brought up amps, ret=%d\n", ret);
35331f8f6ebSJoseph Chen out:
354bb4a1f43SJoseph Chen 	free(fit);
35531f8f6ebSJoseph Chen 
35631f8f6ebSJoseph Chen 	return ret;
35731f8f6ebSJoseph Chen }
35831f8f6ebSJoseph Chen 
3598223aa47SJoseph Chen int arm64_switch_amp_pe(bootm_headers_t *images)
36031f8f6ebSJoseph Chen {
361bb4a1f43SJoseph Chen 	images->os.arch = g_bootcpu.arch;
362bb4a1f43SJoseph Chen 	return g_bootcpu.state;
36331f8f6ebSJoseph Chen }
36431f8f6ebSJoseph Chen 
365