162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0+ */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2013 Samsung Electronics Co., Ltd.
462306a36Sopenharmony_ci *		http://www.samsung.com
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Exynos low-level resume code
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <linux/linkage.h>
1062306a36Sopenharmony_ci#include <asm/asm-offsets.h>
1162306a36Sopenharmony_ci#include <asm/hardware/cache-l2x0.h>
1262306a36Sopenharmony_ci#include "smc.h"
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#define CPU_MASK	0xff0ffff0
1562306a36Sopenharmony_ci#define CPU_CORTEX_A9	0x410fc090
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci	.text
1862306a36Sopenharmony_ci	.align
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci	/*
2162306a36Sopenharmony_ci	 * sleep magic, to allow the bootloader to check for an valid
2262306a36Sopenharmony_ci	 * image to resume to. Must be the first word before the
2362306a36Sopenharmony_ci	 * exynos_cpu_resume entry.
2462306a36Sopenharmony_ci	 */
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci	.word	0x2bedf00d
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci	/*
2962306a36Sopenharmony_ci	 * exynos_cpu_resume
3062306a36Sopenharmony_ci	 *
3162306a36Sopenharmony_ci	 * resume code entry for bootloader to call
3262306a36Sopenharmony_ci	 */
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ciENTRY(exynos_cpu_resume)
3562306a36Sopenharmony_ci#ifdef CONFIG_CACHE_L2X0
3662306a36Sopenharmony_ci	mrc	p15, 0, r0, c0, c0, 0
3762306a36Sopenharmony_ci	ldr	r1, =CPU_MASK
3862306a36Sopenharmony_ci	and	r0, r0, r1
3962306a36Sopenharmony_ci	ldr	r1, =CPU_CORTEX_A9
4062306a36Sopenharmony_ci	cmp	r0, r1
4162306a36Sopenharmony_ci	bleq	l2c310_early_resume
4262306a36Sopenharmony_ci#endif
4362306a36Sopenharmony_ci	b	cpu_resume
4462306a36Sopenharmony_ciENDPROC(exynos_cpu_resume)
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	.align
4762306a36Sopenharmony_ci	.arch armv7-a
4862306a36Sopenharmony_ci	.arch_extension sec
4962306a36Sopenharmony_ciENTRY(exynos_cpu_resume_ns)
5062306a36Sopenharmony_ci	mrc	p15, 0, r0, c0, c0, 0
5162306a36Sopenharmony_ci	ldr	r1, =CPU_MASK
5262306a36Sopenharmony_ci	and	r0, r0, r1
5362306a36Sopenharmony_ci	ldr	r1, =CPU_CORTEX_A9
5462306a36Sopenharmony_ci	cmp	r0, r1
5562306a36Sopenharmony_ci	bne	skip_cp15
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	adr	r0, _cp15_save_power
5862306a36Sopenharmony_ci	ldr	r1, [r0]
5962306a36Sopenharmony_ci	ldr	r1, [r0, r1]
6062306a36Sopenharmony_ci	adr	r0, _cp15_save_diag
6162306a36Sopenharmony_ci	ldr	r2, [r0]
6262306a36Sopenharmony_ci	ldr	r2, [r0, r2]
6362306a36Sopenharmony_ci	mov	r0, #SMC_CMD_C15RESUME
6462306a36Sopenharmony_ci	dsb
6562306a36Sopenharmony_ci	smc	#0
6662306a36Sopenharmony_ci#ifdef CONFIG_CACHE_L2X0
6762306a36Sopenharmony_ci	adr	r0, 1f
6862306a36Sopenharmony_ci	ldr	r2, [r0]
6962306a36Sopenharmony_ci	add	r0, r2, r0
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	/* Check that the address has been initialised. */
7262306a36Sopenharmony_ci	ldr	r1, [r0, #L2X0_R_PHY_BASE]
7362306a36Sopenharmony_ci	teq	r1, #0
7462306a36Sopenharmony_ci	beq	skip_l2x0
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci	/* Check if controller has been enabled. */
7762306a36Sopenharmony_ci	ldr	r2, [r1, #L2X0_CTRL]
7862306a36Sopenharmony_ci	tst	r2, #0x1
7962306a36Sopenharmony_ci	bne	skip_l2x0
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci	ldr	r1, [r0, #L2X0_R_TAG_LATENCY]
8262306a36Sopenharmony_ci	ldr	r2, [r0, #L2X0_R_DATA_LATENCY]
8362306a36Sopenharmony_ci	ldr	r3, [r0, #L2X0_R_PREFETCH_CTRL]
8462306a36Sopenharmony_ci	mov	r0, #SMC_CMD_L2X0SETUP1
8562306a36Sopenharmony_ci	smc	#0
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	/* Reload saved regs pointer because smc corrupts registers. */
8862306a36Sopenharmony_ci	adr	r0, 1f
8962306a36Sopenharmony_ci	ldr	r2, [r0]
9062306a36Sopenharmony_ci	add	r0, r2, r0
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	ldr	r1, [r0, #L2X0_R_PWR_CTRL]
9362306a36Sopenharmony_ci	ldr	r2, [r0, #L2X0_R_AUX_CTRL]
9462306a36Sopenharmony_ci	mov	r0, #SMC_CMD_L2X0SETUP2
9562306a36Sopenharmony_ci	smc	#0
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci	mov	r0, #SMC_CMD_L2X0INVALL
9862306a36Sopenharmony_ci	smc	#0
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci	mov	r1, #1
10162306a36Sopenharmony_ci	mov	r0, #SMC_CMD_L2X0CTRL
10262306a36Sopenharmony_ci	smc	#0
10362306a36Sopenharmony_ciskip_l2x0:
10462306a36Sopenharmony_ci#endif /* CONFIG_CACHE_L2X0 */
10562306a36Sopenharmony_ciskip_cp15:
10662306a36Sopenharmony_ci	b	cpu_resume
10762306a36Sopenharmony_ciENDPROC(exynos_cpu_resume_ns)
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	.align
11062306a36Sopenharmony_ci_cp15_save_power:
11162306a36Sopenharmony_ci	.long	cp15_save_power - .
11262306a36Sopenharmony_ci_cp15_save_diag:
11362306a36Sopenharmony_ci	.long	cp15_save_diag - .
11462306a36Sopenharmony_ci#ifdef CONFIG_CACHE_L2X0
11562306a36Sopenharmony_ci1:	.long	l2x0_saved_regs - .
11662306a36Sopenharmony_ci#endif /* CONFIG_CACHE_L2X0 */
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	.data
11962306a36Sopenharmony_ci	.align	2
12062306a36Sopenharmony_ci	.globl cp15_save_diag
12162306a36Sopenharmony_cicp15_save_diag:
12262306a36Sopenharmony_ci	.long	0	@ cp15 diagnostic
12362306a36Sopenharmony_ci	.globl cp15_save_power
12462306a36Sopenharmony_cicp15_save_power:
12562306a36Sopenharmony_ci	.long	0	@ cp15 power control
126