arm: socfpga: Add SMP support for actual socfpga harware
Because the CPU1 start address is different for socfpga-vt and socfpga-cyclone5, we add code to use the correct CPU1 start addr. Signed-off-by: Dinh Nguyen <dinguyen@altera.com> Signed-off-by: Pavel Machek <pavel@denx.de> Cc: Russell King <linux@arm.linux.org.uk> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Olof Johansson <olof@lixom.net> Cc: Rob Herring <rob.herring@calxeda.com> Cc: Grant Likely <grant.likely@secretlab.ca> Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
parent
c08e20d246
commit
d6dd735f4b
7 changed files with 41 additions and 12 deletions
|
@ -3,9 +3,11 @@ Altera SOCFPGA System Manager
|
||||||
Required properties:
|
Required properties:
|
||||||
- compatible : "altr,sys-mgr"
|
- compatible : "altr,sys-mgr"
|
||||||
- reg : Should contain 1 register ranges(address and length)
|
- reg : Should contain 1 register ranges(address and length)
|
||||||
|
- cpu1-start-addr : CPU1 start address in hex.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
sysmgr@ffd08000 {
|
sysmgr@ffd08000 {
|
||||||
compatible = "altr,sys-mgr";
|
compatible = "altr,sys-mgr";
|
||||||
reg = <0xffd08000 0x1000>;
|
reg = <0xffd08000 0x1000>;
|
||||||
|
cpu1-start-addr = <0xffd080c4>;
|
||||||
};
|
};
|
||||||
|
|
|
@ -56,5 +56,9 @@
|
||||||
serial1@ffc03000 {
|
serial1@ffc03000 {
|
||||||
clock-frequency = <100000000>;
|
clock-frequency = <100000000>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
sysmgr@ffd08000 {
|
||||||
|
cpu1-start-addr = <0xffd080c4>;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -56,5 +56,9 @@
|
||||||
serial1@ffc03000 {
|
serial1@ffc03000 {
|
||||||
clock-frequency = <7372800>;
|
clock-frequency = <7372800>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
sysmgr@ffd08000 {
|
||||||
|
cpu1-start-addr = <0xffd08010>;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#ifndef __MACH_CORE_H
|
#ifndef __MACH_CORE_H
|
||||||
#define __MACH_CORE_H
|
#define __MACH_CORE_H
|
||||||
|
|
||||||
extern void secondary_startup(void);
|
extern void socfpga_secondary_startup(void);
|
||||||
extern void __iomem *socfpga_scu_base_addr;
|
extern void __iomem *socfpga_scu_base_addr;
|
||||||
|
|
||||||
extern void socfpga_init_clocks(void);
|
extern void socfpga_init_clocks(void);
|
||||||
|
@ -29,6 +29,8 @@ extern void socfpga_sysmgr_init(void);
|
||||||
extern struct smp_operations socfpga_smp_ops;
|
extern struct smp_operations socfpga_smp_ops;
|
||||||
extern char secondary_trampoline, secondary_trampoline_end;
|
extern char secondary_trampoline, secondary_trampoline_end;
|
||||||
|
|
||||||
|
extern unsigned long cpu1start_addr;
|
||||||
|
|
||||||
#define SOCFPGA_SCU_VIRT_BASE 0xfffec000
|
#define SOCFPGA_SCU_VIRT_BASE 0xfffec000
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -13,13 +13,21 @@
|
||||||
__CPUINIT
|
__CPUINIT
|
||||||
.arch armv7-a
|
.arch armv7-a
|
||||||
|
|
||||||
#define CPU1_START_ADDR 0xffd08010
|
|
||||||
|
|
||||||
ENTRY(secondary_trampoline)
|
ENTRY(secondary_trampoline)
|
||||||
movw r0, #:lower16:CPU1_START_ADDR
|
movw r2, #:lower16:cpu1start_addr
|
||||||
movt r0, #:upper16:CPU1_START_ADDR
|
movt r2, #:upper16:cpu1start_addr
|
||||||
|
|
||||||
|
/* The socfpga VT cannot handle a 0xC0000000 page offset when loading
|
||||||
|
the cpu1start_addr, we bit clear it. Tested on HW and VT. */
|
||||||
|
bic r2, r2, #0x40000000
|
||||||
|
|
||||||
|
ldr r0, [r2]
|
||||||
ldr r1, [r0]
|
ldr r1, [r0]
|
||||||
bx r1
|
bx r1
|
||||||
|
|
||||||
ENTRY(secondary_trampoline_end)
|
ENTRY(secondary_trampoline_end)
|
||||||
|
|
||||||
|
ENTRY(socfpga_secondary_startup)
|
||||||
|
bl v7_invalidate_l1
|
||||||
|
b secondary_startup
|
||||||
|
ENDPROC(socfpga_secondary_startup)
|
||||||
|
|
|
@ -47,9 +47,11 @@ static int __cpuinit socfpga_boot_secondary(unsigned int cpu, struct task_struct
|
||||||
{
|
{
|
||||||
int trampoline_size = &secondary_trampoline_end - &secondary_trampoline;
|
int trampoline_size = &secondary_trampoline_end - &secondary_trampoline;
|
||||||
|
|
||||||
|
if (cpu1start_addr) {
|
||||||
memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size);
|
memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size);
|
||||||
|
|
||||||
__raw_writel(virt_to_phys(secondary_startup), (sys_manager_base_addr+0x10));
|
__raw_writel(virt_to_phys(socfpga_secondary_startup),
|
||||||
|
(sys_manager_base_addr + (cpu1start_addr & 0x000000ff)));
|
||||||
|
|
||||||
flush_cache_all();
|
flush_cache_all();
|
||||||
smp_wmb();
|
smp_wmb();
|
||||||
|
@ -57,6 +59,7 @@ static int __cpuinit socfpga_boot_secondary(unsigned int cpu, struct task_struct
|
||||||
|
|
||||||
/* This will release CPU #1 out of reset.*/
|
/* This will release CPU #1 out of reset.*/
|
||||||
__raw_writel(0, rst_manager_base_addr + 0x10);
|
__raw_writel(0, rst_manager_base_addr + 0x10);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
void __iomem *socfpga_scu_base_addr = ((void __iomem *)(SOCFPGA_SCU_VIRT_BASE));
|
void __iomem *socfpga_scu_base_addr = ((void __iomem *)(SOCFPGA_SCU_VIRT_BASE));
|
||||||
void __iomem *sys_manager_base_addr;
|
void __iomem *sys_manager_base_addr;
|
||||||
void __iomem *rst_manager_base_addr;
|
void __iomem *rst_manager_base_addr;
|
||||||
|
unsigned long cpu1start_addr;
|
||||||
|
|
||||||
static struct map_desc scu_io_desc __initdata = {
|
static struct map_desc scu_io_desc __initdata = {
|
||||||
.virtual = SOCFPGA_SCU_VIRT_BASE,
|
.virtual = SOCFPGA_SCU_VIRT_BASE,
|
||||||
|
@ -72,6 +73,11 @@ void __init socfpga_sysmgr_init(void)
|
||||||
struct device_node *np;
|
struct device_node *np;
|
||||||
|
|
||||||
np = of_find_compatible_node(NULL, NULL, "altr,sys-mgr");
|
np = of_find_compatible_node(NULL, NULL, "altr,sys-mgr");
|
||||||
|
|
||||||
|
if (of_property_read_u32(np, "cpu1-start-addr",
|
||||||
|
(u32 *) &cpu1start_addr))
|
||||||
|
pr_err("SMP: Need cpu1-start-addr in device tree.\n");
|
||||||
|
|
||||||
sys_manager_base_addr = of_iomap(np, 0);
|
sys_manager_base_addr = of_iomap(np, 0);
|
||||||
|
|
||||||
np = of_find_compatible_node(NULL, NULL, "altr,rst-mgr");
|
np = of_find_compatible_node(NULL, NULL, "altr,rst-mgr");
|
||||||
|
|
Loading…
Reference in a new issue