/* SPDX-License-Identifier: GPL-2.0-only */1/*2* Coherency fabric: low level functions3*4* Copyright (C) 2012 Marvell5*6* Gregory CLEMENT <[email protected]>7*8* This file implements the assembly function to add a CPU to the9* coherency fabric. This function is called by each of the secondary10* CPUs during their early boot in an SMP kernel, this why this11* function have to callable from assembly. It can also be called by a12* primary CPU from C code during its boot.13*/1415#include <linux/linkage.h>16#define ARMADA_XP_CFB_CTL_REG_OFFSET 0x017#define ARMADA_XP_CFB_CFG_REG_OFFSET 0x41819#include <asm/assembler.h>20#include <asm/cp15.h>2122.arch armv7-a23.text24/*25* Returns the coherency base address in r1 (r0 is untouched), or 0 if26* the coherency fabric is not enabled.27*/28ENTRY(ll_get_coherency_base)29mrc p15, 0, r1, c1, c0, 030tst r1, #CR_M @ Check MMU bit enabled31bne 1f3233/*34* MMU is disabled, use the physical address of the coherency35* base address, (or 0x0 if the coherency fabric is not mapped)36*/37adr r1, 3f38ldr r3, [r1]39ldr r1, [r1, r3]40b 2f411:42/*43* MMU is enabled, use the virtual address of the coherency44* base address.45*/46ldr r1, =coherency_base47ldr r1, [r1]482:49ret lr50ENDPROC(ll_get_coherency_base)5152/*53* Returns the coherency CPU mask in r3 (r0 is untouched). This54* coherency CPU mask can be used with the coherency fabric55* configuration and control registers. Note that the mask is already56* endian-swapped as appropriate so that the calling functions do not57* have to care about endianness issues while accessing the coherency58* fabric registers59*/60ENTRY(ll_get_coherency_cpumask)61mrc p15, 0, r3, cr0, cr0, 562and r3, r3, #1563mov r2, #(1 << 24)64lsl r3, r2, r365ARM_BE8(rev r3, r3)66ret lr67ENDPROC(ll_get_coherency_cpumask)6869/*70* ll_add_cpu_to_smp_group(), ll_enable_coherency() and71* ll_disable_coherency() use the strex/ldrex instructions while the72* MMU can be disabled. The Armada XP SoC has an exclusive monitor73* that tracks transactions to Device and/or SO memory and thanks to74* that, exclusive transactions are functional even when the MMU is75* disabled.76*/7778ENTRY(ll_add_cpu_to_smp_group)79/*80* As r0 is not modified by ll_get_coherency_base() and81* ll_get_coherency_cpumask(), we use it to temporarly save lr82* and avoid it being modified by the branch and link83* calls. This function is used very early in the secondary84* CPU boot, and no stack is available at this point.85*/86mov r0, lr87bl ll_get_coherency_base88/* Bail out if the coherency is not enabled */89cmp r1, #090reteq r091bl ll_get_coherency_cpumask92mov lr, r093add r0, r1, #ARMADA_XP_CFB_CFG_REG_OFFSET941:95ldrex r2, [r0]96orr r2, r2, r397strex r1, r2, [r0]98cmp r1, #099bne 1b100ret lr101ENDPROC(ll_add_cpu_to_smp_group)102103ENTRY(ll_enable_coherency)104/*105* As r0 is not modified by ll_get_coherency_base() and106* ll_get_coherency_cpumask(), we use it to temporarly save lr107* and avoid it being modified by the branch and link108* calls. This function is used very early in the secondary109* CPU boot, and no stack is available at this point.110*/111mov r0, lr112bl ll_get_coherency_base113/* Bail out if the coherency is not enabled */114cmp r1, #0115reteq r0116bl ll_get_coherency_cpumask117mov lr, r0118add r0, r1, #ARMADA_XP_CFB_CTL_REG_OFFSET1191:120ldrex r2, [r0]121orr r2, r2, r3122strex r1, r2, [r0]123cmp r1, #0124bne 1b125dsb126mov r0, #0127ret lr128ENDPROC(ll_enable_coherency)129130ENTRY(ll_disable_coherency)131/*132* As r0 is not modified by ll_get_coherency_base() and133* ll_get_coherency_cpumask(), we use it to temporarly save lr134* and avoid it being modified by the branch and link135* calls. This function is used very early in the secondary136* CPU boot, and no stack is available at this point.137*/138mov r0, lr139bl ll_get_coherency_base140/* Bail out if the coherency is not enabled */141cmp r1, #0142reteq r0143bl ll_get_coherency_cpumask144mov lr, r0145add r0, r1, #ARMADA_XP_CFB_CTL_REG_OFFSET1461:147ldrex r2, [r0]148bic r2, r2, r3149strex r1, r2, [r0]150cmp r1, #0151bne 1b152dsb153ret lr154ENDPROC(ll_disable_coherency)155156.align 21573:158.long coherency_phys_base - .159160161