arm: mvebu: Add support for coherency fabric in mach-mvebu
The Armada 370 and Armada XP SOCs have a coherency fabric unit which is responsible for ensuring hardware coherency between all CPUs and between CPUs and I/O masters. This patch provides the basic support needed for SMP. Signed-off-by: Yehuda Yitschak <yehuday@marvell.com> Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com> Reviewed-by: Will Deacon <will.deacon@arm.com>
This commit is contained in:
parent
1611f87251
commit
009f13159b
|
@ -0,0 +1,16 @@
|
||||||
|
Coherency fabric
|
||||||
|
----------------
|
||||||
|
Available on Marvell SOCs: Armada 370 and Armada XP
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
|
||||||
|
- compatible: "marvell,coherency-fabric"
|
||||||
|
- reg: Should contain,coherency fabric registers location and length.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
coherency-fabric@d0020200 {
|
||||||
|
compatible = "marvell,coherency-fabric";
|
||||||
|
reg = <0xd0020200 0xb0>;
|
||||||
|
};
|
||||||
|
|
|
@ -36,6 +36,11 @@
|
||||||
interrupt-controller;
|
interrupt-controller;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
coherency-fabric@d0020200 {
|
||||||
|
compatible = "marvell,coherency-fabric";
|
||||||
|
reg = <0xd0020200 0xb0>;
|
||||||
|
};
|
||||||
|
|
||||||
soc {
|
soc {
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
|
|
|
@ -2,4 +2,4 @@ ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \
|
||||||
-I$(srctree)/arch/arm/plat-orion/include
|
-I$(srctree)/arch/arm/plat-orion/include
|
||||||
|
|
||||||
obj-y += system-controller.o
|
obj-y += system-controller.o
|
||||||
obj-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-xp.o irq-armada-370-xp.o addr-map.o
|
obj-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-xp.o irq-armada-370-xp.o addr-map.o coherency.o coherency_ll.o
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
* Coherency fabric (Aurora) support for Armada 370 and XP platforms.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Marvell
|
||||||
|
*
|
||||||
|
* Yehuda Yitschak <yehuday@marvell.com>
|
||||||
|
* Gregory Clement <gregory.clement@free-electrons.com>
|
||||||
|
* Thomas Petazzoni <thomas.petazzoni@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.
|
||||||
|
*
|
||||||
|
* The Armada 370 and Armada XP SOCs have a coherency fabric which is
|
||||||
|
* responsible for ensuring hardware coherency between all CPUs and between
|
||||||
|
* CPUs and I/O masters. This file initializes the coherency fabric and
|
||||||
|
* supplies basic routines for configuring and controlling hardware coherency
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/of_address.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/smp.h>
|
||||||
|
#include <asm/smp_plat.h>
|
||||||
|
#include "armada-370-xp.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some functions in this file are called very early during SMP
|
||||||
|
* initialization. At that time the device tree framework is not yet
|
||||||
|
* ready, and it is not possible to get the register address to
|
||||||
|
* ioremap it. That's why the pointer below is given with an initial
|
||||||
|
* value matching its virtual mapping
|
||||||
|
*/
|
||||||
|
static void __iomem *coherency_base = ARMADA_370_XP_REGS_VIRT_BASE + 0x20200;
|
||||||
|
|
||||||
|
/* Coherency fabric registers */
|
||||||
|
#define COHERENCY_FABRIC_CFG_OFFSET 0x4
|
||||||
|
|
||||||
|
static struct of_device_id of_coherency_table[] = {
|
||||||
|
{.compatible = "marvell,coherency-fabric"},
|
||||||
|
{ /* end of list */ },
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
int coherency_get_cpu_count(void)
|
||||||
|
{
|
||||||
|
int reg, cnt;
|
||||||
|
|
||||||
|
reg = readl(coherency_base + COHERENCY_FABRIC_CFG_OFFSET);
|
||||||
|
cnt = (reg & 0xF) + 1;
|
||||||
|
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Function defined in coherency_ll.S */
|
||||||
|
int ll_set_cpu_coherent(void __iomem *base_addr, unsigned int hw_cpu_id);
|
||||||
|
|
||||||
|
int set_cpu_coherent(unsigned int hw_cpu_id, int smp_group_id)
|
||||||
|
{
|
||||||
|
if (!coherency_base) {
|
||||||
|
pr_warn("Can't make CPU %d cache coherent.\n", hw_cpu_id);
|
||||||
|
pr_warn("Coherency fabric is not initialized\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ll_set_cpu_coherent(coherency_base, hw_cpu_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
int __init coherency_init(void)
|
||||||
|
{
|
||||||
|
struct device_node *np;
|
||||||
|
|
||||||
|
np = of_find_matching_node(NULL, of_coherency_table);
|
||||||
|
if (np) {
|
||||||
|
pr_info("Initializing Coherency fabric\n");
|
||||||
|
coherency_base = of_iomap(np, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* arch/arm/mach-mvebu/include/mach/coherency.h
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Coherency fabric (Aurora) support for Armada 370 and XP platforms.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Marvell
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MACH_370_XP_COHERENCY_H
|
||||||
|
#define __MACH_370_XP_COHERENCY_H
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
int coherency_get_cpu_count(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int set_cpu_coherent(int cpu_id, int smp_group_id);
|
||||||
|
int coherency_init(void);
|
||||||
|
|
||||||
|
#endif /* __MACH_370_XP_COHERENCY_H */
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
.text
|
||||||
|
/*
|
||||||
|
* r0: Coherency fabric base register address
|
||||||
|
* r1: HW CPU id
|
||||||
|
*/
|
||||||
|
ENTRY(ll_set_cpu_coherent)
|
||||||
|
/* Create bit by cpu index */
|
||||||
|
mov r3, #(1 << 24)
|
||||||
|
lsl r1, r3, r1
|
||||||
|
|
||||||
|
/* Add CPU to SMP group - Atomic */
|
||||||
|
add r3, r0, #ARMADA_XP_CFB_CTL_REG_OFFSET
|
||||||
|
ldr r2, [r3]
|
||||||
|
orr r2, r2, r1
|
||||||
|
str r2, [r3]
|
||||||
|
|
||||||
|
/* Enable coherency on CPU - Atomic */
|
||||||
|
add r3, r0, #ARMADA_XP_CFB_CFG_REG_OFFSET
|
||||||
|
ldr r2, [r3]
|
||||||
|
orr r2, r2, r1
|
||||||
|
str r2, [r3]
|
||||||
|
|
||||||
|
dsb
|
||||||
|
|
||||||
|
mov r0, #0
|
||||||
|
mov pc, lr
|
||||||
|
ENDPROC(ll_set_cpu_coherent)
|
|
@ -20,4 +20,5 @@ void mvebu_restart(char mode, const char *cmd);
|
||||||
void armada_370_xp_init_irq(void);
|
void armada_370_xp_init_irq(void);
|
||||||
void armada_370_xp_handle_irq(struct pt_regs *regs);
|
void armada_370_xp_handle_irq(struct pt_regs *regs);
|
||||||
|
|
||||||
|
int armada_370_xp_coherency_init(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue