linux/arch/arm/mach-mvebu/coherency_ll.S

129 lines
2.9 KiB
ArmAsm
Raw Normal View History

/*
* Coherency fabric: low level functions
*
* Copyright (C) 2012 Marvell
*
* Gregory CLEMENT <gregory.clement@free-electrons.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*
* This file implements the assembly function to add a CPU to the
* coherency fabric. This function is called by each of the secondary
* CPUs during their early boot in an SMP kernel, this why this
* function have to callable from assembly. It can also be called by a
* primary CPU from C code during its boot.
*/
#include <linux/linkage.h>
#define ARMADA_XP_CFB_CTL_REG_OFFSET 0x0
#define ARMADA_XP_CFB_CFG_REG_OFFSET 0x4
#include <asm/assembler.h>
#include <asm/cp15.h>
.text
/* Returns with the coherency address in r1 (r0 is untouched)*/
ENTRY(ll_get_coherency_base)
mrc p15, 0, r1, c1, c0, 0
tst r1, #CR_M @ Check MMU bit enabled
bne 1f
/* use physical address of the coherency register */
adr r1, 3f
ldr r3, [r1]
ldr r1, [r1, r3]
b 2f
1:
/* use virtual address of the coherency register */
ldr r1, =coherency_base
ldr r1, [r1]
2:
mov pc, lr
ENDPROC(ll_get_coherency_base)
/* Returns with the CPU ID in r3 (r0 is untouched)*/
ENTRY(ll_get_cpuid)
mrc 15, 0, r3, cr0, cr0, 5
and r3, r3, #15
mov r2, #(1 << 24)
lsl r3, r2, r3
ARM_BE8(rev r1, r1)
mov pc, lr
ENDPROC(ll_get_cpuid)
/* ll_add_cpu_to_smp_group, ll_enable_coherency and
* ll_disable_coherency use strex/ldrex whereas MMU can be off. The
* Armada XP SoC has an exclusive monitor that can track transactions
* to Device and/or SO and as such also when MMU is disabled the
* exclusive transactions will be functional
*/
ENTRY(ll_add_cpu_to_smp_group)
/*
* r0 being untouched in ll_get_coherency_base and
* ll_get_cpuid, we can use it to save lr modifing it with the
* following bl
*/
mov r0, lr
bl ll_get_coherency_base
bl ll_get_cpuid
mov lr, r0
add r0, r1, #ARMADA_XP_CFB_CFG_REG_OFFSET
1:
ldrex r2, [r0]
orr r2, r2, r3
strex r1, r2, [r0]
cmp r1, #0
bne 1b
mov pc, lr
ENDPROC(ll_add_cpu_to_smp_group)
ENTRY(ll_enable_coherency)
/*
* r0 being untouched in ll_get_coherency_base and
* ll_get_cpuid, we can use it to save lr modifing it with the
* following bl
*/
mov r0, lr
bl ll_get_coherency_base
bl ll_get_cpuid
mov lr, r0
add r0, r1, #ARMADA_XP_CFB_CTL_REG_OFFSET
1:
ldrex r2, [r0]
orr r2, r2, r3
strex r1, r2, [r0]
cmp r1, #0
bne 1b
dsb
mov r0, #0
mov pc, lr
ENDPROC(ll_enable_coherency)
ENTRY(ll_disable_coherency)
/*
* r0 being untouched in ll_get_coherency_base and
* ll_get_cpuid, we can use it to save lr modifing it with the
* following bl
*/
mov r0, lr
bl ll_get_coherency_base
bl ll_get_cpuid
mov lr, r0
add r0, r1, #ARMADA_XP_CFB_CTL_REG_OFFSET
1:
ldrex r2, [r0]
bic r2, r2, r3
strex r1, r2, [r0]
cmp r1, #0
bne 1b
dsb
mov pc, lr
ENDPROC(ll_disable_coherency)
.align 2
3:
.long coherency_phys_base - .