/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Based on several files from Linux version v5.10: arch/arm/mm/proc-macros.S,
 * arch/arm/mm/proc-v7.S.
 */

#ifndef __ASSEMBLER__
#error "Only include this from assembly code"
#endif

#ifndef _ASMARM_ASSEMBLER_H_
#define _ASMARM_ASSEMBLER_H_

/*
 * dcache_line_size - get the minimum D-cache line size from the CTR register
 * on ARMv7.
 */
	.macro	dcache_line_size, reg, tmp
	mrc	p15, 0, \tmp, c0, c0, 1		// read ctr
	lsr	\tmp, \tmp, #16
	and	\tmp, \tmp, #0xf		// cache line size encoding
	mov	\reg, #4			// bytes per word
	mov	\reg, \reg, lsl \tmp		// actual cache line size
	.endm

/*
 * Macro to perform a data cache maintenance for the interval
 * [addr, addr + size).
 *
 * 	op:		operation to execute
 * 	domain		domain used in the dsb instruction
 * 	addr:		starting virtual address of the region
 * 	size:		size of the region
 * 	Corrupts:	addr, size, tmp1, tmp2
 */
	.macro dcache_by_line_op op, domain, addr, size, tmp1, tmp2
	dcache_line_size \tmp1, \tmp2
	add	\size, \addr, \size
	sub	\tmp2, \tmp1, #1
	bic	\addr, \addr, \tmp2
9998:
	.ifc	\op, dccimvac
	mcr	p15, 0, \addr, c7, c14, 1
	.else
	.err
	.endif
	add	\addr, \addr, \tmp1
	cmp	\addr, \size
	blo	9998b
	dsb	\domain
	.endm

#endif	/* _ASMARM_ASSEMBLER_H_ */