xref: /openbmc/linux/arch/arm/mm/proc-v6.S (revision 7ae9fb1b7ecbb5d85d07857943f677fd1a559b18)
1d2912cb1SThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-only */
21da177e4SLinus Torvalds/*
31da177e4SLinus Torvalds *  linux/arch/arm/mm/proc-v6.S
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds *  Copyright (C) 2001 Deep Blue Solutions Ltd.
6d090dddaSHyok S. Choi *  Modified by Catalin Marinas for noMMU support
71da177e4SLinus Torvalds *
81da177e4SLinus Torvalds *  This is the "shell" of the ARMv6 processor support.
91da177e4SLinus Torvalds */
10991da17eSTim Abbott#include <linux/init.h>
111da177e4SLinus Torvalds#include <linux/linkage.h>
1265fddcfcSMike Rapoport#include <linux/pgtable.h>
131da177e4SLinus Torvalds#include <asm/assembler.h>
14e6ae744dSSam Ravnborg#include <asm/asm-offsets.h>
155ec9407dSRussell King#include <asm/hwcap.h>
1674945c86SRussell King#include <asm/pgtable-hwdef.h>
171da177e4SLinus Torvalds
181da177e4SLinus Torvalds#include "proc-macros.S"
191da177e4SLinus Torvalds
201da177e4SLinus Torvalds#define D_CACHE_LINE_SIZE	32
211da177e4SLinus Torvalds
223747b36eSRussell King#define TTB_C		(1 << 0)
233747b36eSRussell King#define TTB_S		(1 << 1)
243747b36eSRussell King#define TTB_IMP		(1 << 2)
253747b36eSRussell King#define TTB_RGN_NC	(0 << 3)
263747b36eSRussell King#define TTB_RGN_WBWA	(1 << 3)
273747b36eSRussell King#define TTB_RGN_WT	(2 << 3)
283747b36eSRussell King#define TTB_RGN_WB	(3 << 3)
293747b36eSRussell King
30f00ec48fSRussell King#define TTB_FLAGS_UP	TTB_RGN_WBWA
31f00ec48fSRussell King#define PMD_FLAGS_UP	PMD_SECT_WB
32f00ec48fSRussell King#define TTB_FLAGS_SMP	TTB_RGN_WBWA|TTB_S
33f00ec48fSRussell King#define PMD_FLAGS_SMP	PMD_SECT_WBWA|PMD_SECT_S
34f2131d34SRussell King
35*a2faac39SNick Desaulniers.arch armv6
36*a2faac39SNick Desaulniers
371da177e4SLinus TorvaldsENTRY(cpu_v6_proc_init)
386ebbf2ceSRussell King	ret	lr
391da177e4SLinus Torvalds
401da177e4SLinus TorvaldsENTRY(cpu_v6_proc_fin)
4167c5587aSTony Lindgren	mrc	p15, 0, r0, c1, c0, 0		@ ctrl register
4267c5587aSTony Lindgren	bic	r0, r0, #0x1000			@ ...i............
4367c5587aSTony Lindgren	bic	r0, r0, #0x0006			@ .............ca.
4467c5587aSTony Lindgren	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
456ebbf2ceSRussell King	ret	lr
461da177e4SLinus Torvalds
471da177e4SLinus Torvalds/*
481da177e4SLinus Torvalds *	cpu_v6_reset(loc)
491da177e4SLinus Torvalds *
501da177e4SLinus Torvalds *	Perform a soft reset of the system.  Put the CPU into the
511da177e4SLinus Torvalds *	same state as it would be if it had been reset, and branch
521da177e4SLinus Torvalds *	to what would be the reset vector.
531da177e4SLinus Torvalds *
541da177e4SLinus Torvalds *	- loc   - location to jump to for soft reset
551da177e4SLinus Torvalds */
561da177e4SLinus Torvalds	.align	5
571a4baafaSWill Deacon	.pushsection	.idmap.text, "ax"
581da177e4SLinus TorvaldsENTRY(cpu_v6_reset)
59f4daf06fSWill Deacon	mrc	p15, 0, r1, c1, c0, 0		@ ctrl register
60f4daf06fSWill Deacon	bic	r1, r1, #0x1			@ ...............m
61f4daf06fSWill Deacon	mcr	p15, 0, r1, c1, c0, 0		@ disable MMU
62f4daf06fSWill Deacon	mov	r1, #0
63f4daf06fSWill Deacon	mcr	p15, 0, r1, c7, c5, 4		@ ISB
646ebbf2ceSRussell King	ret	r0
651a4baafaSWill DeaconENDPROC(cpu_v6_reset)
661a4baafaSWill Deacon	.popsection
671da177e4SLinus Torvalds
681da177e4SLinus Torvalds/*
691da177e4SLinus Torvalds *	cpu_v6_do_idle()
701da177e4SLinus Torvalds *
711da177e4SLinus Torvalds *	Idle the processor (eg, wait for interrupt).
721da177e4SLinus Torvalds *
731da177e4SLinus Torvalds *	IRQs are already disabled.
741da177e4SLinus Torvalds */
751da177e4SLinus TorvaldsENTRY(cpu_v6_do_idle)
768553cb67SCatalin Marinas	mov	r1, #0
778553cb67SCatalin Marinas	mcr	p15, 0, r1, c7, c10, 4		@ DWB - WFI may enter a low-power mode
781da177e4SLinus Torvalds	mcr	p15, 0, r1, c7, c0, 4		@ wait for interrupt
796ebbf2ceSRussell King	ret	lr
801da177e4SLinus Torvalds
811da177e4SLinus TorvaldsENTRY(cpu_v6_dcache_clean_area)
821da177e4SLinus Torvalds1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
831da177e4SLinus Torvalds	add	r0, r0, #D_CACHE_LINE_SIZE
841da177e4SLinus Torvalds	subs	r1, r1, #D_CACHE_LINE_SIZE
851da177e4SLinus Torvalds	bhi	1b
866ebbf2ceSRussell King	ret	lr
871da177e4SLinus Torvalds
881da177e4SLinus Torvalds/*
892b6e204fSNicolas Pitre *	cpu_v6_switch_mm(pgd_phys, tsk)
901da177e4SLinus Torvalds *
911da177e4SLinus Torvalds *	Set the translation table base pointer to be pgd_phys
921da177e4SLinus Torvalds *
931da177e4SLinus Torvalds *	- pgd_phys - physical address of new TTB
941da177e4SLinus Torvalds *
951da177e4SLinus Torvalds *	It is assumed that:
961da177e4SLinus Torvalds *	- we are not using split page tables
971da177e4SLinus Torvalds */
981da177e4SLinus TorvaldsENTRY(cpu_v6_switch_mm)
99d090dddaSHyok S. Choi#ifdef CONFIG_MMU
1001da177e4SLinus Torvalds	mov	r2, #0
101251019fbSBen Dooks	mmid	r1, r1				@ get mm->context.id
102f00ec48fSRussell King	ALT_SMP(orr	r0, r0, #TTB_FLAGS_SMP)
103f00ec48fSRussell King	ALT_UP(orr	r0, r0, #TTB_FLAGS_UP)
1041da177e4SLinus Torvalds	mcr	p15, 0, r2, c7, c5, 6		@ flush BTAC/BTB
1051da177e4SLinus Torvalds	mcr	p15, 0, r2, c7, c10, 4		@ drain write buffer
1061da177e4SLinus Torvalds	mcr	p15, 0, r0, c2, c0, 0		@ set TTB 0
107575320d6SWill Deacon#ifdef CONFIG_PID_IN_CONTEXTIDR
108575320d6SWill Deacon	mrc	p15, 0, r2, c13, c0, 1		@ read current context ID
109575320d6SWill Deacon	bic	r2, r2, #0xff			@ extract the PID
110575320d6SWill Deacon	and	r1, r1, #0xff
111575320d6SWill Deacon	orr	r1, r1, r2			@ insert into new context ID
112575320d6SWill Deacon#endif
1131da177e4SLinus Torvalds	mcr	p15, 0, r1, c13, c0, 1		@ set context ID
114d090dddaSHyok S. Choi#endif
1156ebbf2ceSRussell King	ret	lr
1161da177e4SLinus Torvalds
1171da177e4SLinus Torvalds/*
118ad1ae2feSRussell King *	cpu_v6_set_pte_ext(ptep, pte, ext)
1191da177e4SLinus Torvalds *
1201da177e4SLinus Torvalds *	Set a level 2 translation table entry.
1211da177e4SLinus Torvalds *
1221da177e4SLinus Torvalds *	- ptep  - pointer to level 2 translation table entry
1231da177e4SLinus Torvalds *		  (hardware version is stored at -1024 bytes)
1241da177e4SLinus Torvalds *	- pte   - PTE value to store
125ad1ae2feSRussell King *	- ext	- value for extended PTE bits
1261da177e4SLinus Torvalds */
127639b0ae7SRussell King	armv6_mt_table cpu_v6
128639b0ae7SRussell King
129ad1ae2feSRussell KingENTRY(cpu_v6_set_pte_ext)
130d090dddaSHyok S. Choi#ifdef CONFIG_MMU
131639b0ae7SRussell King	armv6_set_pte_ext cpu_v6
132d090dddaSHyok S. Choi#endif
1336ebbf2ceSRussell King	ret	lr
1341da177e4SLinus Torvalds
135f6b0fa02SRussell King/* Suspend/resume support: taken from arch/arm/mach-s3c64xx/sleep.S */
136f6b0fa02SRussell King.globl	cpu_v6_suspend_size
1371aede681SRussell King.equ	cpu_v6_suspend_size, 4 * 6
138b6c7aabdSRussell King#ifdef CONFIG_ARM_CPU_SUSPEND
139f6b0fa02SRussell KingENTRY(cpu_v6_do_suspend)
1401aede681SRussell King	stmfd	sp!, {r4 - r9, lr}
141f6b0fa02SRussell King	mrc	p15, 0, r4, c13, c0, 0	@ FCSE/PID
142aa1aadc3SWill Deacon#ifdef CONFIG_MMU
1431aede681SRussell King	mrc	p15, 0, r5, c3, c0, 0	@ Domain ID
1441aede681SRussell King	mrc	p15, 0, r6, c2, c0, 1	@ Translation table base 1
145aa1aadc3SWill Deacon#endif
1461aede681SRussell King	mrc	p15, 0, r7, c1, c0, 1	@ auxiliary control register
1471aede681SRussell King	mrc	p15, 0, r8, c1, c0, 2	@ co-processor access control
1481aede681SRussell King	mrc	p15, 0, r9, c1, c0, 0	@ control register
1491aede681SRussell King	stmia	r0, {r4 - r9}
1501aede681SRussell King	ldmfd	sp!, {r4- r9, pc}
151f6b0fa02SRussell KingENDPROC(cpu_v6_do_suspend)
152f6b0fa02SRussell King
153f6b0fa02SRussell KingENTRY(cpu_v6_do_resume)
154f6b0fa02SRussell King	mov	ip, #0
155f6b0fa02SRussell King	mcr	p15, 0, ip, c7, c14, 0	@ clean+invalidate D cache
156f6b0fa02SRussell King	mcr	p15, 0, ip, c7, c5, 0	@ invalidate I cache
157f6b0fa02SRussell King	mcr	p15, 0, ip, c7, c15, 0	@ clean+invalidate cache
158f6b0fa02SRussell King	mcr	p15, 0, ip, c7, c10, 4	@ drain write buffer
1591aede681SRussell King	mcr	p15, 0, ip, c13, c0, 1	@ set reserved context ID
1601aede681SRussell King	ldmia	r0, {r4 - r9}
161f6b0fa02SRussell King	mcr	p15, 0, r4, c13, c0, 0	@ FCSE/PID
162aa1aadc3SWill Deacon#ifdef CONFIG_MMU
1631aede681SRussell King	mcr	p15, 0, r5, c3, c0, 0	@ Domain ID
164de8e71caSRussell King	ALT_SMP(orr	r1, r1, #TTB_FLAGS_SMP)
165de8e71caSRussell King	ALT_UP(orr	r1, r1, #TTB_FLAGS_UP)
166de8e71caSRussell King	mcr	p15, 0, r1, c2, c0, 0	@ Translation table base 0
1671aede681SRussell King	mcr	p15, 0, r6, c2, c0, 1	@ Translation table base 1
168aa1aadc3SWill Deacon	mcr	p15, 0, ip, c2, c0, 2	@ TTB control register
169aa1aadc3SWill Deacon#endif
1701aede681SRussell King	mcr	p15, 0, r7, c1, c0, 1	@ auxiliary control register
1711aede681SRussell King	mcr	p15, 0, r8, c1, c0, 2	@ co-processor access control
172f6b0fa02SRussell King	mcr	p15, 0, ip, c7, c5, 4	@ ISB
1731aede681SRussell King	mov	r0, r9			@ control register
174f6b0fa02SRussell King	b	cpu_resume_mmu
175f6b0fa02SRussell KingENDPROC(cpu_v6_do_resume)
176f6b0fa02SRussell King#endif
1771da177e4SLinus Torvalds
1787b7dc6e8SDave Martin	string	cpu_v6_name, "ARMv6-compatible processor"
179edabd38eSSaeed Bishara
1801da177e4SLinus Torvalds	.align
1811da177e4SLinus Torvalds
1821da177e4SLinus Torvalds/*
1831da177e4SLinus Torvalds *	__v6_setup
1841da177e4SLinus Torvalds *
1851da177e4SLinus Torvalds *	Initialise TLB, Caches, and MMU state ready to switch the MMU
1861da177e4SLinus Torvalds *	on.  Return in r0 the new CP15 C1 control register setting.
1871da177e4SLinus Torvalds *
1881da177e4SLinus Torvalds *	We automatically detect if we have a Harvard cache, and use the
1891da177e4SLinus Torvalds *	Harvard cache control instructions insead of the unified cache
1901da177e4SLinus Torvalds *	control instructions.
1911da177e4SLinus Torvalds *
1921da177e4SLinus Torvalds *	This should be able to cover all ARMv6 cores.
1931da177e4SLinus Torvalds *
1941da177e4SLinus Torvalds *	It is assumed that:
1951da177e4SLinus Torvalds *	- cache type register is implemented
1961da177e4SLinus Torvalds */
1971da177e4SLinus Torvalds__v6_setup:
198862184feSRussell King#ifdef CONFIG_SMP
199f00ec48fSRussell King	ALT_SMP(mrc	p15, 0, r0, c1, c0, 1)	@ Enable SMP/nAMP mode
200f00ec48fSRussell King	ALT_UP(nop)
201862184feSRussell King	orr	r0, r0, #0x20
202f00ec48fSRussell King	ALT_SMP(mcr	p15, 0, r0, c1, c0, 1)
203f00ec48fSRussell King	ALT_UP(nop)
204862184feSRussell King#endif
205862184feSRussell King
2061da177e4SLinus Torvalds	mov	r0, #0
2071da177e4SLinus Torvalds	mcr	p15, 0, r0, c7, c14, 0		@ clean+invalidate D cache
2081da177e4SLinus Torvalds	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
2091da177e4SLinus Torvalds	mcr	p15, 0, r0, c7, c15, 0		@ clean+invalidate cache
210d090dddaSHyok S. Choi#ifdef CONFIG_MMU
2111da177e4SLinus Torvalds	mcr	p15, 0, r0, c8, c7, 0		@ invalidate I + D TLBs
2121da177e4SLinus Torvalds	mcr	p15, 0, r0, c2, c0, 2		@ TTB control register
213f00ec48fSRussell King	ALT_SMP(orr	r4, r4, #TTB_FLAGS_SMP)
214f00ec48fSRussell King	ALT_UP(orr	r4, r4, #TTB_FLAGS_UP)
215d427958aSCatalin Marinas	ALT_SMP(orr	r8, r8, #TTB_FLAGS_SMP)
216d427958aSCatalin Marinas	ALT_UP(orr	r8, r8, #TTB_FLAGS_UP)
217d427958aSCatalin Marinas	mcr	p15, 0, r8, c2, c0, 1		@ load TTB1
218d090dddaSHyok S. Choi#endif /* CONFIG_MMU */
219bae0ca2bSWill Deacon	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer and
220bae0ca2bSWill Deacon						@ complete invalidations
22122b19086SRussell King	adr	r5, v6_crval
22222b19086SRussell King	ldmia	r5, {r5, r6}
223457c2403SBen Dooks ARM_BE8(orr	r6, r6, #1 << 25)		@ big-endian page tables
2241da177e4SLinus Torvalds	mrc	p15, 0, r0, c1, c0, 0		@ read control register
2251da177e4SLinus Torvalds	bic	r0, r0, r5			@ clear bits them
22622b19086SRussell King	orr	r0, r0, r6			@ set them
227145e10e1SCatalin Marinas#ifdef CONFIG_ARM_ERRATA_364296
228145e10e1SCatalin Marinas	/*
229145e10e1SCatalin Marinas	 * Workaround for the 364296 ARM1136 r0p2 erratum (possible cache data
230145e10e1SCatalin Marinas	 * corruption with hit-under-miss enabled). The conditional code below
231145e10e1SCatalin Marinas	 * (setting the undocumented bit 31 in the auxiliary control register
232145e10e1SCatalin Marinas	 * and the FI bit in the control register) disables hit-under-miss
233145e10e1SCatalin Marinas	 * without putting the processor into full low interrupt latency mode.
234145e10e1SCatalin Marinas	 */
235145e10e1SCatalin Marinas	ldr	r6, =0x4107b362			@ id for ARM1136 r0p2
236145e10e1SCatalin Marinas	mrc	p15, 0, r5, c0, c0, 0		@ get processor id
237145e10e1SCatalin Marinas	teq	r5, r6				@ check for the faulty core
238145e10e1SCatalin Marinas	mrceq	p15, 0, r5, c1, c0, 1		@ load aux control reg
239145e10e1SCatalin Marinas	orreq	r5, r5, #(1 << 31)		@ set the undocumented bit 31
240145e10e1SCatalin Marinas	mcreq	p15, 0, r5, c1, c0, 1		@ write aux control reg
241145e10e1SCatalin Marinas	orreq	r0, r0, #(1 << 21)		@ low interrupt latency configuration
242145e10e1SCatalin Marinas#endif
2436ebbf2ceSRussell King	ret	lr				@ return to head.S:__ret
2441da177e4SLinus Torvalds
2451da177e4SLinus Torvalds	/*
2461da177e4SLinus Torvalds	 *         V X F   I D LR
2471da177e4SLinus Torvalds	 * .... ...E PUI. .T.T 4RVI ZFRS BLDP WCAM
2481da177e4SLinus Torvalds	 * rrrr rrrx xxx0 0101 xxxx xxxx x111 xxxx < forced
2491da177e4SLinus Torvalds	 *         0 110       0011 1.00 .111 1101 < we want
2501da177e4SLinus Torvalds	 */
25122b19086SRussell King	.type	v6_crval, #object
25222b19086SRussell Kingv6_crval:
25322b19086SRussell King	crval	clear=0x01e0fb7f, mmuset=0x00c0387d, ucset=0x00c0187c
2541da177e4SLinus Torvalds
2555085f3ffSRussell King	__INITDATA
2565085f3ffSRussell King
2577b7dc6e8SDave Martin	@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
2587b7dc6e8SDave Martin	define_processor_functions v6, dabort=v6_early_abort, pabort=v6_pabort, suspend=1
2591da177e4SLinus Torvalds
2605085f3ffSRussell King	.section ".rodata"
2615085f3ffSRussell King
2627b7dc6e8SDave Martin	string	cpu_arch_name, "armv6"
2637b7dc6e8SDave Martin	string	cpu_elf_name, "v6"
2641da177e4SLinus Torvalds	.align
2651da177e4SLinus Torvalds
266790756c7SNick Desaulniers	.section ".proc.info.init", "a"
2671da177e4SLinus Torvalds
2681da177e4SLinus Torvalds	/*
2691da177e4SLinus Torvalds	 * Match any ARMv6 processor core.
2701da177e4SLinus Torvalds	 */
2711da177e4SLinus Torvalds	.type	__v6_proc_info, #object
2721da177e4SLinus Torvalds__v6_proc_info:
2731da177e4SLinus Torvalds	.long	0x0007b000
2741da177e4SLinus Torvalds	.long	0x0007f000
275f00ec48fSRussell King	ALT_SMP(.long \
276f00ec48fSRussell King		PMD_TYPE_SECT | \
2771da177e4SLinus Torvalds		PMD_SECT_AP_WRITE | \
2784b46d641SRussell King		PMD_SECT_AP_READ | \
279f00ec48fSRussell King		PMD_FLAGS_SMP)
280f00ec48fSRussell King	ALT_UP(.long \
281f00ec48fSRussell King		PMD_TYPE_SECT | \
282f00ec48fSRussell King		PMD_SECT_AP_WRITE | \
283f00ec48fSRussell King		PMD_SECT_AP_READ | \
284f00ec48fSRussell King		PMD_FLAGS_UP)
2858799ee9fSRussell King	.long   PMD_TYPE_SECT | \
2868799ee9fSRussell King		PMD_SECT_XN | \
2878799ee9fSRussell King		PMD_SECT_AP_WRITE | \
2888799ee9fSRussell King		PMD_SECT_AP_READ
289bf35706fSArd Biesheuvel	initfn	__v6_setup, __v6_proc_info
2901da177e4SLinus Torvalds	.long	cpu_arch_name
2911da177e4SLinus Torvalds	.long	cpu_elf_name
292f159f4edSTony Lindgren	/* See also feat_v6_fixup() for HWCAP_TLS */
293f159f4edSTony Lindgren	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_JAVA|HWCAP_TLS
2941da177e4SLinus Torvalds	.long	cpu_v6_name
2951da177e4SLinus Torvalds	.long	v6_processor_functions
2961da177e4SLinus Torvalds	.long	v6wbi_tlb_fns
2971da177e4SLinus Torvalds	.long	v6_user_fns
2981da177e4SLinus Torvalds	.long	v6_cache_fns
2991da177e4SLinus Torvalds	.size	__v6_proc_info, . - __v6_proc_info
300