Support Marvell bootloaders remapping registers at different locations
Subsystems (3)
cover Support Marvell bootloaders remapping registers at different locations
Hello,
On Marvell platforms, the base address of the "internal registers" (i.e registers of all peripherals) can be configured at runtime. At reset, it is set to 0xD0000000, but it can freely be changed to some other location.
On all previous Marvell SoC families, Linux assumes the bootloader has remapped the internal registers at 0xF1000000, and Marvell is now moving to do the same on Armada 370/XP, since it allows to use as much RAM as possible in the 0 -> 4G area. However, due to early issues, until now, Marvell bootloaders were leaving the internal registers address set to 0xD0000000, and recently, Marvell has started shipping bootloaders that remapped those registers to 0xF1000000.
In order to support those two cases, we want to make sure the Device Tree is the only location where the physical base address of the internal registers is stored. This patch set removes the places where the physical base address of the registers was hardcoded and provides two Kconfig options for the earlyprintk UART address selection (one for 0xD0000000 and one for 0xF1000000).
It no longer uses the CP15 trick, nor it tries to do runtime remapping to 0xF1 if it wasn't done by the bootloader. But it allows to easily boot a kernel with both old and new bootloaders by doing a simple change, in a single location in the Device Tree.
This patch series is based on jcooper/mvebu/fixes-non-critical and jcooper/mvebu/cleanup, which contains 3 patches that are necessary to make this patch series work properly.
Thanks,
Thomas
Thomas Petazzoni (8):
arm: mvebu: remove dependency of SMP init on static I/O mapping
arm: mvebu: avoid hardcoded virtual address in coherency code
arm: mvebu: move cache and mvebu-mbus initialization later
arm: mvebu: remove hardcoded static I/O mapping
arm: mvebu: don't hardcode a physical address in headsmp.S
arm: mvebu: don't hardcode the physical address for mvebu-mbus
arm: mvebu: add another earlyprintk Kconfig option
arm: mvebu: disable DEBUG_LL/EARLY_PRINTK in defconfig
arch/arm/Kconfig.debug | 30 ++++++++++++++++++++-- arch/arm/configs/mvebu_defconfig | 2 -- arch/arm/include/debug/mvebu.S | 5 ++++ arch/arm/mach-mvebu/armada-370-xp.c | 51 ++++++++++++++++++++----------------- arch/arm/mach-mvebu/armada-370-xp.h | 10 -------- arch/arm/mach-mvebu/coherency.c | 36 ++++++++++---------------- arch/arm/mach-mvebu/coherency.h | 4 --- arch/arm/mach-mvebu/common.h | 2 ++ arch/arm/mach-mvebu/headsmp.S | 19 ++++++++------ arch/arm/mach-mvebu/platsmp.c | 10 +++++++- 10 files changed, 96 insertions(+), 73 deletions(-)
Signature · 1 line
1.8.1.2
PATCH 1/8 arm: mvebu: remove dependency of SMP init on static I/O mapping
The ->smp_init_cpus() function is called very early during boot, at a point where dynamic I/O mappings are not yet possible. However, in the Armada 370/XP implementation of this function, we have to get the number of CPUs. We used to do that by accessing a hardware register, which requires relying on a static I/O mapping set up by ->map_io(). Not only this requires hardcoding a virtual address, but it also prevents us from removing the static I/O mapping.
So this commit changes the way used to get the number of CPUs: we now use the Device Tree, which is a representation of the hardware, and provides us the number of available CPUs. This is also more accurate, because it potentially allows to boot the Linux kernel on only a number of CPUs given by the Device Tree, instead of unconditionally on all CPUs.
As a consequence, the coherency_get_cpu_count() function becomes no longer used, so we remove it.
--- arch/arm/mach-mvebu/coherency.c | 12 ------------ arch/arm/mach-mvebu/coherency.h | 4 ---- arch/arm/mach-mvebu/common.h | 2 ++ arch/arm/mach-mvebu/platsmp.c | 10 +++++++++- 4 files changed, 11 insertions(+), 17 deletions(-)
arch/arm/mach-mvebu/coherency.c +0 -12
@@ -47,18 +47,6 @@ static struct of_device_id of_coherency_table[] = { { /* 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);
arch/arm/mach-mvebu/coherency.h +0 -4
@@ -14,10 +14,6 @@#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 );
arch/arm/mach-mvebu/common.h +2 -0
@@ -15,6 +15,8 @@#ifndef __ARCH_MVEBU_COMMON_H#define __ARCH_MVEBU_COMMON_H +#define ARMADA_XP_MAX_CPUS 4 +void mvebu_restart (char mode,const char *cmd);void armada_370_xp_init_irq (void );
arch/arm/mach-mvebu/platsmp.c +9 -1
@@ -88,8 +88,16 @@ static int __cpuinit armada_xp_boot_secondary(unsigned int cpu,static void __init armada_xp_smp_init_cpus (void ) { +struct device_node *np;unsigned int i, ncores; - ncores =coherency_get_cpu_count (); + + np =of_find_node_by_name (NULL ,"cpus" ); +if (!np) +panic ("No 'cpus' node found\n" ); + + ncores =of_get_child_count (np); +if (ncores ==0 || ncores >ARMADA_XP_MAX_CPUS ) +panic ("Invalid number of CPUs in DT\n" );/* Limit possible CPUs to defconfig */ if (ncores > nr_cpu_ids) {
Signature · 1 line
1.8.1.2
PATCH 2/8 arm: mvebu: avoid hardcoded virtual address in coherency code
In reply to Thomas PetazzoniNow that the coherency_get_cpu_count() function no longer requires a very early mapping of the coherency unit registers, we can avoid the hardcoded virtual address in coherency.c. However, the coherency features are still used quite early, so we need to do the of_iomap() early enough, at the ->init_timer() level, so we have the call of coherency_init() at this point.
Unfortunately, at ->init_timer() time, it is not possible to register a bus notifier, so we add a separate coherency_late_init() function that gets called as as postcore_initcall(), when bus notifiers are available.
--- arch/arm/mach-mvebu/armada-370-xp.c | 2 +- arch/arm/mach-mvebu/coherency.c | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-)
arch/arm/mach-mvebu/armada-370-xp.c +1 -1
@@ -46,6 +46,7 @@ static void __init armada_370_xp_timer_and_clk_init(void) {mvebu_clocks_init ();armada_370_xp_timer_init (); +coherency_init (); }static void __init armada_370_xp_init_early (void )
@@ -75,7 +76,6 @@ static void __init armada_370_xp_init_early(void)static void __init armada_370_xp_dt_init (void ) {of_platform_populate (NULL , of_default_bus_match_table,NULL ,NULL ); -coherency_init (); }static const char *const armada_370_xp_dt_compat[] = {
arch/arm/mach-mvebu/coherency.c +10 -10
@@ -27,14 +27,7 @@#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 ; +static void __iomem *coherency_base;static void __iomem *coherency_cpu_base;/* Coherency fabric registers */
@@ -135,9 +128,16 @@ int __init coherency_init(void) coherency_base =of_iomap (np,0 ); coherency_cpu_base =of_iomap (np,1 );set_cpu_coherent (cpu_logical_map (smp_processor_id ()),0 ); -bus_register_notifier (&platform_bus_type, - &mvebu_hwcc_platform_nb); }return 0 ; } + +static int __init coherency_late_init (void ) +{ +bus_register_notifier (&platform_bus_type, + &mvebu_hwcc_platform_nb); +return 0 ; +} + +postcore_initcall (coherency_late_init);
Signature · 1 line
1.8.1.2
PATCH 3/8 arm: mvebu: move cache and mvebu-mbus initialization later
In reply to Thomas PetazzoniCurrent, the L2 cache and the mvebu-mbus drivers are initialized at ->init_early() time. However, at ->init_early() time, ioremap() only works if a static I/O mapping has already been put in place. If it's not the case, it tries to do a memory allocation with kmalloc() which is not possible so early at this stage of the initialization.
Since we want to get rid of the static I/O mapping, we cannot initialize the L2 cache driver and the mvebu-mbus driver so early. So, we move their initialization to the ->init_time() level, which is slightly later (so ioremap() works properly), but sufficiently early to be before the call of the ->smp_prepare_cpus() hook, which creates an address decoding window for the BootROM, which requires the mvebu-mbus driver to be properly initialized.
--- arch/arm/mach-mvebu/armada-370-xp.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-)
arch/arm/mach-mvebu/armada-370-xp.c +2 -6
@@ -44,14 +44,11 @@ static void __init armada_370_xp_map_io(void)static void __init armada_370_xp_timer_and_clk_init (void ) { +char *mbus_soc_name; +mvebu_clocks_init ();armada_370_xp_timer_init ();coherency_init (); -} - -static void __init armada_370_xp_init_early (void ) -{ -char *mbus_soc_name;/* * This initialization will be replaced by a DT-based
@@ -87,7 +84,6 @@ DT_MACHINE_START(ARMADA_XP_DT, "Marvell Armada 370/XP (Device Tree)") .smp = smp_ops(armada_xp_smp_ops), .init_machine = armada_370_xp_dt_init, .map_io = armada_370_xp_map_io, - .init_early = armada_370_xp_init_early, .init_time = armada_370_xp_timer_and_clk_init, .restart = mvebu_restart, .dt_compat = armada_370_xp_dt_compat,
Signature · 1 line
1.8.1.2
PATCH 4/8 arm: mvebu: remove hardcoded static I/O mapping
In reply to Thomas PetazzoniNow that we have removed the need of the static I/O mapping for early initialization reasons, and fixed the registers area length that were broken, we can get rid of the static I/O mapping. Only the earlyprintk mapping needs to be set up, using the debug_ll_io_init() helper function.
--- arch/arm/mach-mvebu/armada-370-xp.c | 11 +---------- arch/arm/mach-mvebu/armada-370-xp.h | 2 -- 2 files changed, 1 insertion(+), 12 deletions(-)
arch/arm/mach-mvebu/armada-370-xp.c +1 -10
@@ -28,18 +28,9 @@#include "common.h" #include "coherency.h" -static struct map_desc armada_370_xp_io_desc[]__initdata = { - { - .virtual = (unsigned long )ARMADA_370_XP_REGS_VIRT_BASE , - .pfn =__phys_to_pfn (ARMADA_370_XP_REGS_PHYS_BASE ), - .length =ARMADA_370_XP_REGS_SIZE , - .type =MT_DEVICE , - }, -}; -static void __init armada_370_xp_map_io (void ) { -iotable_init (armada_370_xp_io_desc,ARRAY_SIZE (armada_370_xp_io_desc)); +debug_ll_io_init (); }static void __init armada_370_xp_timer_and_clk_init (void )
arch/arm/mach-mvebu/armada-370-xp.h +0 -2
@@ -16,8 +16,6 @@#define __MACH_ARMADA_370_XP_H#define ARMADA_370_XP_REGS_PHYS_BASE 0xd0000000 -#define ARMADA_370_XP_REGS_VIRT_BASE IOMEM(0xfec00000) -#define ARMADA_370_XP_REGS_SIZE SZ_1M/* These defines can go away once mvebu-mbus has a DT binding */ #define ARMADA_370_XP_MBUS_WINS_BASE (ARMADA_370_XP_REGS_PHYS_BASE + 0x20000)
Signature · 1 line
1.8.1.2
PATCH 5/8 arm: mvebu: don't hardcode a physical address in headsmp.S
In reply to Thomas PetazzoniNow that the coherency_init() function is called a bit earlier, we can actually read the physical address of the coherency unit registers from the Device Tree, and communicate that to the headsmp.S code, which avoids hardcoding a physical address.
--- arch/arm/mach-mvebu/coherency.c | 4 ++++ arch/arm/mach-mvebu/headsmp.S | 19 +++++++++++-------- 2 files changed, 15 insertions(+), 8 deletions(-)
arch/arm/mach-mvebu/coherency.c +4 -0
@@ -27,6 +27,7 @@#include <asm/smp_plat.h> #include "armada-370-xp.h" +unsigned long __cpuinitdata coherency_phys_base;static void __iomem *coherency_base;static void __iomem *coherency_cpu_base;
@@ -124,7 +125,10 @@ int __init coherency_init(void) np =of_find_matching_node (NULL , of_coherency_table);if (np) { +struct resource res;pr_info ("Initializing Coherency fabric\n" ); +of_address_to_resource (np,0 , &res); + coherency_phys_base = res.start; coherency_base =of_iomap (np,0 ); coherency_cpu_base =of_iomap (np,1 );set_cpu_coherent (cpu_logical_map (smp_processor_id ()),0 );
arch/arm/mach-mvebu/headsmp.S +11 -8
@@ -21,12 +21,6 @@ #include <linux/linkage.h> #include <linux/init.h> -/* - * At this stage the secondary CPUs don't have acces yet to the MMU, so - * we have to provide physical addresses - */ -#define ARMADA_XP_CFB_BASE 0xD0020200 - __CPUINIT /*
@@ -35,15 +29,24 @@ * startup */ ENTRY(armada_xp_secondary_startup) + /* Get coherency fabric base physical address */ + adr r0, 1f + ldmia r0, {r1, r2} + sub r0, r0, r1 + add r2, r2, r0 + ldr r0, [r2] /* Read CPU id */ mrc p15, 0, r1, c0, c0, 5 and r1, r1, #0xF /* Add CPU to coherency fabric */ - ldr r0, =ARMADA_XP_CFB_BASE - bl ll_set_cpu_coherent b secondary_startup ENDPROC(armada_xp_secondary_startup) + + .align 2 +1: + .long . + .long coherency_phys_base
Signature · 1 line
1.8.1.2
PATCH 5/8 arm: mvebu: don't hardcode a physical address in headsmp.S
On Wed, 5 Jun 2013, Thomas Petazzoni wrote:
[...]
Quoted 7 lines
ENTRY(armada_xp_secondary_startup)arch/arm/mach-mvebu/headsmp.S +6
-0+ /* Get coherency fabric base physical address */ + adr r0, 1f + ldmia r0, {r1, r2} + sub r0, r0, r1 + add r2, r2, r0 + ldr r0, [r2]
[...]
arch/arm/mach-mvebu/headsmp.S line 52
Quoted 5 lines
arch/arm/mach-mvebu/headsmp.S +5
-0+ + .align 2 +1: + .long . + .long coherency_phys_base
You may simplify the above like this:
adr r0, 1f ldr r1, [r0] ldr r0, [r0, r1] ...,
1: .long coherency_phys_base - .
Nicolas
PATCH 5/8 arm: mvebu: don't hardcode a physical address in headsmp.S
Dear Nicolas Pitre,
Quoted 7 lines · Nicolas Pitre
You may simplify the above like this:
adr r0, 1f ldr r1, [r0] ldr r0, [r0, r1] ...,1: .long
coherency_phys_base- .
Ok, thanks, will try this. Note that the piece of code I've used was shamelessly copied from other headsmp.S implementations, such as plat-versatile, mach-ux500, mach-prima2 and mach-msm.
Thanks!
Thomas
Signature · 4 lines
Thomas Petazzoni, Free Electrons Kernel, drivers, real-time and embedded Linux development, consulting, training and support. http://free-electrons.com
PATCH 5/8 arm: mvebu: don't hardcode a physical address in headsmp.S
In reply to Thomas PetazzoniHi Thomas,
Quoted 24 lines · Thomas Petazzoni
Now that the
coherency_init()function is called a bit earlier, we can actually read the physical address of the coherency unit registers from the Device Tree, and communicate that to theheadsmp.Scode, which avoids hardcoding a physical address.Signed-off-by Thomas Petazzoni <[email protected]>--- arch/arm/mach-mvebu/coherency.c | 4 ++++ arch/arm/mach-mvebu/headsmp.S | 19 +++++++++++-------- 2 files changed, 15 insertions(+), 8 deletions(-)arch/arm/mach-mvebu/coherency.c +1
-0@@ -27,6 +27,7 @@#include <asm/smp_plat.h> #include "armada-370-xp.h" +unsigned long __cpuinitdata coherency_phys_base;static void __iomem *coherency_base;static void __iomem *coherency_cpu_base;
arch/arm/mach-mvebu/coherency.c int __init coherency_init(void) · line 131
Quoted 7 lines
arch/arm/mach-mvebu/coherency.c +3
-0@@ -124,7 +125,10 @@ int __init coherency_init(void) np =of_find_matching_node (NULL , of_coherency_table);if (np) { +struct resource res;pr_info ("Initializing Coherency fabric\n" ); +of_address_to_resource (np,0 , &res); + coherency_phys_base = res.start;
So you have the primary CPU writing this address, before it is coherent...
Quoted 21 lines
arch/arm/mach-mvebu/coherency.c +0
-0coherency_base =of_iomap (np,0 ); coherency_cpu_base =of_iomap (np,1 );set_cpu_coherent (cpu_logical_map (smp_processor_id ()),0 );arch/arm/mach-mvebu/headsmp.S +0
-6@@ -21,12 +21,6 @@ #include <linux/linkage.h> #include <linux/init.h> -/* - * At this stage the secondary CPUs don't have acces yet to the MMU, so - * we have to provide physical addresses - */ -#define ARMADA_XP_CFB_BASE 0xD0020200 - __CPUINIT /*
arch/arm/mach-mvebu/headsmp.S line 37
Quoted 9 lines
arch/arm/mach-mvebu/headsmp.S +6
-0@@ -35,15 +29,24 @@ * startup */ ENTRY(armada_xp_secondary_startup) + /* Get coherency fabric base physical address */ + adr r0, 1f + ldmia r0, {r1, r2} + sub r0, r0, r1 + add r2, r2, r0 + ldr r0, [r2]
... and the secondaries reading it, before they are coherent. How do you ensure that the write is indeed visible?
Furthermore, it's worth noting that of_find_matching_node takes the devtree_lock spinlock, so you need to be careful calling that if you're not coherent.
Will
PATCH 5/8 arm: mvebu: don't hardcode a physical address in headsmp.S
Dear Will Deacon,
Quoted 7 lines · Will Deacon
arch/arm/mach-mvebu/coherency.c int __init coherency_init(void) · line 131
Quoted 4 lines
arch/arm/mach-mvebu/coherency.c +3
-0+struct resource res;pr_info ("Initializing Coherency fabric\n" ); +of_address_to_resource (np,0 , &res); + coherency_phys_base = res.start;So you have the primary CPU writing this address, before it is coherent...
[...]
Quoted 10 lines
arch/arm/mach-mvebu/headsmp.S line 37
Quoted 7 lines
ENTRY(armada_xp_secondary_startup)arch/arm/mach-mvebu/headsmp.S +6
-0+ /* Get coherency fabric base physical address */ + adr r0, 1f + ldmia r0, {r1, r2} + sub r0, r0, r1 + add r2, r2, r0 + ldr r0, [r2]... and the secondaries reading it, before they are coherent. How do you ensure that the write is indeed visible?
Indeed. As discussed on IRC, I've fixed that by adding a sync_cache_w() on the coherency_phys_base variable after it has been updated by the boot CPU. By the time the secondary CPUs read their value, the MMU is not enabled, so the caches aren't enabled, so they are directly seeing the contents of the memory. So hopefully, this should solve your concern.
Quoted 3 lines
Furthermore, it's worth noting that
of_find_matching_nodetakes thedevtree_lockspinlock, so you need to be careful calling that if you're not coherent.
Also as discussed on IRC, we're not coherent with regard to the secondary CPUs, but those other CPUs have not started yet. And being part of the coherency unit is apparently not required for strex and al. to operate properly.
I've just sent a v2 of this patch that adds the sync_cache_w(), and also adjust the assembly code as per the suggestions of Nicolas Pitre.
Thanks for your comments!
Thomas
Signature · 4 lines
Thomas Petazzoni, Free Electrons Kernel, drivers, real-time and embedded Linux development, consulting, training and support. http://free-electrons.com
PATCH v2 1/1 arm: mvebu: don't hardcode a physical address in headsmp.S
In reply to Thomas PetazzoniNow that the coherency_init() function is called a bit earlier, we can actually read the physical address of the coherency unit registers from the Device Tree, and communicate that to the headsmp.S code, which avoids hardcoding a physical address.
---
Changes from v1 to v2:
* Simplified the code in headsmp.S to compute the physical address of the coherency unit base address. Suggested by Nicolas Pitre.
* Added a sync_cache_w() call to ensure the physical address of the coherency unit stored in the coherency_phys_base is visible by the other CPUs. The other CPUs are reading this before they join the coherency fabric, so we need to make some manual cache coherency here. Noticed by Will Deacon.
arch/arm/mach-mvebu/coherency.c | 12 ++++++++++++ arch/arm/mach-mvebu/headsmp.S | 16 ++++++++-------- 2 files changed, 20 insertions(+), 8 deletions(-)
arch/arm/mach-mvebu/coherency.c +12 -0
@@ -25,8 +25,10 @@#include <linux/dma-mapping.h> #include <linux/platform_device.h> #include <asm/smp_plat.h> +#include <asm/cacheflush.h> #include "armada-370-xp.h" +unsigned long __cpuinitdata coherency_phys_base;static void __iomem *coherency_base;static void __iomem *coherency_cpu_base;
@@ -124,7 +126,17 @@ int __init coherency_init(void) np =of_find_matching_node (NULL , of_coherency_table);if (np) { +struct resource res;pr_info ("Initializing Coherency fabric\n" ); +of_address_to_resource (np,0 , &res); + coherency_phys_base = res.start; +/* +* Ensure secondary CPUs will see the updated value, +* which they read before they join the coherency +* fabric, and therefore before they are coherent with +* the boot CPU cache. +*/ +sync_cache_w (&coherency_phys_base); coherency_base =of_iomap (np,0 ); coherency_cpu_base =of_iomap (np,1 );set_cpu_coherent (cpu_logical_map (smp_processor_id ()),0 );
arch/arm/mach-mvebu/headsmp.S +8 -8
@@ -21,12 +21,6 @@ #include <linux/linkage.h> #include <linux/init.h> -/* - * At this stage the secondary CPUs don't have acces yet to the MMU, so - * we have to provide physical addresses - */ -#define ARMADA_XP_CFB_BASE 0xD0020200 - __CPUINIT /*
@@ -35,15 +29,21 @@ * startup */ ENTRY(armada_xp_secondary_startup) + /* Get coherency fabric base physical address */ + adr r0, 1f + ldr r1, [r0] + ldr r0, [r0, r1] /* Read CPU id */ mrc p15, 0, r1, c0, c0, 5 and r1, r1, #0xF /* Add CPU to coherency fabric */ - ldr r0, =ARMADA_XP_CFB_BASE - bl ll_set_cpu_coherent b secondary_startup ENDPROC(armada_xp_secondary_startup) + + .align 2 +1: + .long coherency_phys_base - .
Signature · 1 line
1.8.1.2
PATCH v2 1/1 arm: mvebu: don't hardcode a physical address in headsmp.S
Quoted 18 lines · Thomas Petazzoni
Now that the
coherency_init()function is called a bit earlier, we can actually read the physical address of the coherency unit registers from the Device Tree, and communicate that to theheadsmp.Scode, which avoids hardcoding a physical address.Signed-off-by Thomas Petazzoni <[email protected]>---
Changes from v1 to v2:* Simplified the code in
headsmp.Sto compute the physical address of the coherency unit base address. Suggested by Nicolas Pitre.* Added a
sync_cache_w()call to ensure the physical address of the coherency unit stored in thecoherency_phys_baseis visible by the other CPUs. The other CPUs are reading this before they join the coherency fabric, so we need to make some manual cache coherency here. Noticed by Will Deacon.
Quoted 3 lines
arch/arm/mach-mvebu/coherency.c | 12 ++++++++++++ arch/arm/mach-mvebu/headsmp.S | 16 ++++++++-------- 2 files changed, 20 insertions(+), 8 deletions(-)
This looks better to me, cheers.
Will
PATCH v2 1/1 arm: mvebu: don't hardcode a physical address in headsmp.S
In reply to Thomas PetazzoniQuoted 6 lines · Thomas Petazzoni
Now that the
coherency_init()function is called a bit earlier, we can actually read the physical address of the coherency unit registers from the Device Tree, and communicate that to theheadsmp.Scode, which avoids hardcoding a physical address.Signed-off-by Thomas Petazzoni <[email protected]>
Quoted 93 lines
---
Changes from v1 to v2:* Simplified the code in
headsmp.Sto compute the physical address of the coherency unit base address. Suggested by Nicolas Pitre.* Added a
sync_cache_w()call to ensure the physical address of the coherency unit stored in thecoherency_phys_baseis visible by the other CPUs. The other CPUs are reading this before they join the coherency fabric, so we need to make some manual cache coherency here. Noticed by Will Deacon.arch/arm/mach-mvebu/coherency.c | 12 ++++++++++++ arch/arm/mach-mvebu/headsmp.S | 16 ++++++++-------- 2 files changed, 20 insertions(+), 8 deletions(-)arch/arm/mach-mvebu/coherency.c +12
-0@@ -25,8 +25,10 @@#include <linux/dma-mapping.h> #include <linux/platform_device.h> #include <asm/smp_plat.h> +#include <asm/cacheflush.h> #include "armada-370-xp.h" +unsigned long __cpuinitdata coherency_phys_base;static void __iomem *coherency_base;static void __iomem *coherency_cpu_base;@@ -124,7 +126,17 @@ int __init coherency_init(void) np =of_find_matching_node (NULL , of_coherency_table);if (np) { +struct resource res;pr_info ("Initializing Coherency fabric\n" ); +of_address_to_resource (np,0 , &res); + coherency_phys_base = res.start; +/* +* Ensure secondary CPUs will see the updated value, +* which they read before they join the coherency +* fabric, and therefore before they are coherent with +* the boot CPU cache. +*/ +sync_cache_w (&coherency_phys_base); coherency_base =of_iomap (np,0 ); coherency_cpu_base =of_iomap (np,1 );set_cpu_coherent (cpu_logical_map (smp_processor_id ()),0 );arch/arm/mach-mvebu/headsmp.S +8
-8@@ -21,12 +21,6 @@ #include <linux/linkage.h> #include <linux/init.h> -/* - * At this stage the secondary CPUs don't have acces yet to the MMU, so - * we have to provide physical addresses - */ -#define ARMADA_XP_CFB_BASE 0xD0020200 - __CPUINIT /*@@ -35,15 +29,21 @@ * startup */ ENTRY(armada_xp_secondary_startup) + /* Get coherency fabric base physical address */ + adr r0, 1f + ldr r1, [r0] + ldr r0, [r0, r1] /* Read CPU id */ mrc p15, 0, r1, c0, c0, 5 and r1, r1, #0xF /* Add CPU to coherency fabric */ - ldr r0, =ARMADA_XP_CFB_BASE - bl ll_set_cpu_coherent b secondary_startup ENDPROC(armada_xp_secondary_startup) + + .align 2 +1: + .long coherency_phys_base - .Signature · 1 line
1.8.1.2
PATCH v2 1/1 arm: mvebu: don't hardcode a physical address in headsmp.S
In reply to Thomas PetazzoniQuoted 18 lines · Thomas Petazzoni
Now that the
coherency_init()function is called a bit earlier, we can actually read the physical address of the coherency unit registers from the Device Tree, and communicate that to theheadsmp.Scode, which avoids hardcoding a physical address.Signed-off-by Thomas Petazzoni <[email protected]>---
Changes from v1 to v2:* Simplified the code in
headsmp.Sto compute the physical address of the coherency unit base address. Suggested by Nicolas Pitre.* Added a
sync_cache_w()call to ensure the physical address of the coherency unit stored in thecoherency_phys_baseis visible by the other CPUs. The other CPUs are reading this before they join the coherency fabric, so we need to make some manual cache coherency here. Noticed by Will Deacon.
Quoted 3 lines
arch/arm/mach-mvebu/coherency.c | 12 ++++++++++++ arch/arm/mach-mvebu/headsmp.S | 16 ++++++++-------- 2 files changed, 20 insertions(+), 8 deletions(-)
Inserted into (read: rebase!) mvebu/regmap with Acks/Reviewed-by's from Arnd, Nico and Will.
thx,
Jason.
PATCH 6/8 arm: mvebu: don't hardcode the physical address for mvebu-mbus
In reply to Thomas PetazzoniSince the mvebu-mbus driver doesn't yet have a DT binding (and this DT binding may not necessarily be ready for 3.11), the physical address of the mvebu-mbus registers are currently hardcoded. This doesn't play well with the fact that the internal registers base address may be different depending on the bootloader.
In order to have only one central place for the physical address of the internal registers, we now use of_translate_address() to translate the mvebu-mbus register offsets into the real physical address, by using DT-based address translation. This will go away once the mvebu-mbus driver gains a proper DT binding.
--- arch/arm/mach-mvebu/armada-370-xp.c | 38 ++++++++++++++++++++++++++----------- arch/arm/mach-mvebu/armada-370-xp.h | 8 -------- 2 files changed, 27 insertions(+), 19 deletions(-)
arch/arm/mach-mvebu/armada-370-xp.c +27 -11
@@ -14,6 +14,7 @@#include <linux/kernel.h> #include <linux/init.h> +#include <linux/of_address.h> #include <linux/of_platform.h> #include <linux/io.h> #include <linux/time-armada-370-xp.h>
@@ -33,29 +34,44 @@ static void __init armada_370_xp_map_io(void)debug_ll_io_init (); } -static void __init armada_370_xp_timer_and_clk_init (void ) +/* +* This initialization will be replaced by a DT-based +* initialization once the mvebu-mbus driver gains DT support. +*/ + +#define ARMADA_370_XP_MBUS_WINS_OFFS 0x20000 +#define ARMADA_370_XP_MBUS_WINS_SIZE 0x100 +#define ARMADA_370_XP_SDRAM_WINS_OFFS 0x20180 +#define ARMADA_370_XP_SDRAM_WINS_SIZE 0x20 + +static void __init armada_370_xp_mbus_init (void ) {char *mbus_soc_name; +struct device_node *dn; +const __be32 mbus_wins_offs =cpu_to_be32 (ARMADA_370_XP_MBUS_WINS_OFFS ); +const __be32 sdram_wins_offs =cpu_to_be32 (ARMADA_370_XP_SDRAM_WINS_OFFS ); -mvebu_clocks_init (); -armada_370_xp_timer_init (); -coherency_init (); - -/* -* This initialization will be replaced by a DT-based -* initialization once the mvebu-mbus driver gains DT support. -*/ if (of_machine_is_compatible ("marvell,armada370" )) mbus_soc_name ="marvell,armada370-mbus" ;else mbus_soc_name ="marvell,armadaxp-mbus" ; + dn =of_find_node_by_name (NULL ,"internal-regs" ); +BUG_ON (!dn); +mvebu_mbus_init (mbus_soc_name, -ARMADA_370_XP_MBUS_WINS_BASE , +of_translate_address (dn, &mbus_wins_offs),ARMADA_370_XP_MBUS_WINS_SIZE , -ARMADA_370_XP_SDRAM_WINS_BASE , +of_translate_address (dn, &sdram_wins_offs),ARMADA_370_XP_SDRAM_WINS_SIZE ); +} +static void __init armada_370_xp_timer_and_clk_init (void ) +{ +mvebu_clocks_init (); +armada_370_xp_timer_init (); +coherency_init (); +armada_370_xp_mbus_init ();#ifdef CONFIG_CACHE_L2X0 l2x0_of_init (0 , ~0UL );#endif
arch/arm/mach-mvebu/armada-370-xp.h +0 -8
@@ -15,14 +15,6 @@#ifndef __MACH_ARMADA_370_XP_H#define __MACH_ARMADA_370_XP_H -#define ARMADA_370_XP_REGS_PHYS_BASE 0xd0000000 - -/* These defines can go away once mvebu-mbus has a DT binding */ -#define ARMADA_370_XP_MBUS_WINS_BASE (ARMADA_370_XP_REGS_PHYS_BASE + 0x20000) -#define ARMADA_370_XP_MBUS_WINS_SIZE 0x100 -#define ARMADA_370_XP_SDRAM_WINS_BASE (ARMADA_370_XP_REGS_PHYS_BASE + 0x20180) -#define ARMADA_370_XP_SDRAM_WINS_SIZE 0x20 -#ifdef CONFIG_SMP #include <linux/cpumask.h>
Signature · 1 line
1.8.1.2
PATCH 7/8 arm: mvebu: add another earlyprintk Kconfig option
In reply to Thomas PetazzoniIn order to support both old and new bootloaders, we add a new Kconfig option for the earlyprintk UART selection. The existing option allows to work with old bootloaders (that keep the internal registers mapped at 0xd0000000), while the newly introduced option allows to work with new bootloaders (that remap the internal registers at 0xf1000000).
--- arch/arm/Kconfig.debug | 30 ++++++++++++++++++++++++++++-- arch/arm/include/debug/mvebu.S | 5 +++++ 2 files changed, 33 insertions(+), 2 deletions(-)
arch/arm/Kconfig.debug +28 -2
@@ -303,12 +303,37 @@ choice their output to the serial port on MSM 8960 devices. config DEBUG_MVEBU_UART - bool "Kernel low-level debugging messages via MVEBU UART" + bool "Kernel low-level debugging messages via MVEBU UART (old bootloaders)" depends on ARCH_MVEBU help Say Y here if you want kernel low-level debugging support on MVEBU based platforms. + This option should be used with the old bootloaders + that left the internal registers mapped at + 0xd0000000. As of today, this is the case on + platforms such as the Globalscale Mirabox or the + Plathome OpenBlocks AX3, when using the original + bootloader. + + If the wrong DEBUG_MVEBU_UART* option is selected, + when u-boot hands over to the kernel, the system + silently crashes, with no serial output at all. + + config DEBUG_MVEBU_UART_ALTERNATE + bool "Kernel low-level debugging messages via MVEBU UART (new bootloaders)" + depends on ARCH_MVEBU + help + Say Y here if you want kernel low-level debugging support + on MVEBU based platforms. + + This option should be used with the new bootloaders + that remap the internal registers at 0xf1000000. + + If the wrong DEBUG_MVEBU_UART* option is selected, + when u-boot hands over to the kernel, the system + silently crashes, with no serial output at all. + config DEBUG_NOMADIK_UART bool "Kernel low-level debugging messages via NOMADIK UART" depends on ARCH_NOMADIK
@@ -632,7 +657,8 @@ config DEBUG_LL_INCLUDE DEBUG_IMX51_UART || \ DEBUG_IMX53_UART ||\ DEBUG_IMX6Q_UART - default "debug/mvebu.S" if DEBUG_MVEBU_UART + default "debug/mvebu.S" if DEBUG_MVEBU_UART || \ + DEBUG_MVEBU_UART_ALTERNATE default "debug/mxs.S" if DEBUG_IMX23_UART || DEBUG_IMX28_UART default "debug/nomadik.S" if DEBUG_NOMADIK_UART default "debug/omap2plus.S" if DEBUG_OMAP2PLUS_UART
arch/arm/include/debug/mvebu.S +5 -0
@@ -11,7 +11,12 @@ * published by the Free Software Foundation. */ +#ifdef CONFIG_DEBUG_MVEBU_UART_ALTERNATE +#define ARMADA_370_XP_REGS_PHYS_BASE 0xf1000000 +#else #define ARMADA_370_XP_REGS_PHYS_BASE 0xd0000000 +#endif + #define ARMADA_370_XP_REGS_VIRT_BASE 0xfec00000 .macro addruart, rp, rv, tmp
Signature · 1 line
1.8.1.2
PATCH 7/8 arm: mvebu: add another earlyprintk Kconfig option
Quoted 17 lines · Thomas Petazzoni
In order to support both old and new bootloaders, we add a new
Kconfigoption for the earlyprintk UART selection. The existing option allows to work with old bootloaders (that keep the internal registers mapped at0xd0000000), while the newly introduced option allows to work with new bootloaders (that remap the internal registers at0xf1000000).Signed-off-by Thomas Petazzoni <[email protected]>--- arch/arm/Kconfig.debug | 30 ++++++++++++++++++++++++++++-- arch/arm/include/debug/mvebu.S | 5 +++++ 2 files changed, 33 insertions(+), 2 deletions(-)arch/arm/Kconfig.debug +0
-0
arch/arm/Kconfig.debug choice · line 305
Quoted 3 lines
arch/arm/Kconfig.debug +0
-0@@ -303,12 +303,37 @@ choice their output to the serial port on MSM 8960 devices. config DEBUG_MVEBU_UART
Perhaps we should change this to DEBUG_MVEBU_UART_LEGACY?
Quoted 9 lines
arch/arm/Kconfig.debug +3
-1- bool "Kernel low-level debugging messages via MVEBU UART" + bool "Kernel low-level debugging messages via MVEBU UART (old bootloaders)" depends on ARCH_MVEBU help Say Y here if you want kernel low-level debugging support on MVEBU based platforms. + This option should be used with the old bootloaders + that left the internal registers mapped at
arch/arm/Kconfig.debug choice · line 323
Quoted 10 lines
arch/arm/Kconfig.debug +10
-0+ 0xd0000000. As of today, this is the case on + platforms such as the Globalscale Mirabox or the + Plathome OpenBlocks AX3, when using the original + bootloader. + + If the wrong DEBUG_MVEBU_UART* option is selected, + when u-boot hands over to the kernel, the system + silently crashes, with no serial output at all. + + config DEBUG_MVEBU_UART_ALTERNATE
And this to DEBUG_MVEBU_UART?
arch/arm/Kconfig.debug choice · line 324
Quoted 1 line
arch/arm/Kconfig.debug +1
-0+ bool "Kernel low-level debugging messages via MVEBU UART (new bootloaders)"
and remove '(new bootloaders)...
Quoted 30 lines
arch/arm/Kconfig.debug +14
-1+ depends on ARCH_MVEBU + help + Say Y here if you want kernel low-level debugging support + on MVEBU based platforms. + + This option should be used with the new bootloaders + that remap the internal registers at 0xf1000000. + + If the wrong DEBUG_MVEBU_UART* option is selected, + when u-boot hands over to the kernel, the system + silently crashes, with no serial output at all. + config DEBUG_NOMADIK_UART bool "Kernel low-level debugging messages via NOMADIK UART" depends on ARCH_NOMADIK@@ -632,7 +657,8 @@ config DEBUG_LL_INCLUDE DEBUG_IMX51_UART || \ DEBUG_IMX53_UART ||\ DEBUG_IMX6Q_UART - default "debug/mvebu.S" if DEBUG_MVEBU_UART + default "debug/mvebu.S" if DEBUG_MVEBU_UART || \ + DEBUG_MVEBU_UART_ALTERNATE default "debug/mxs.S" if DEBUG_IMX23_UART || DEBUG_IMX28_UART default "debug/nomadik.S" if DEBUG_NOMADIK_UART default "debug/omap2plus.S" if DEBUG_OMAP2PLUS_UARTarch/arm/include/debug/mvebu.S +0
-0
arch/arm/include/debug/mvebu.S line 18
Quoted 8 lines
arch/arm/include/debug/mvebu.S +4
-0@@ -11,7 +11,12 @@ * published by the Free Software Foundation. */ +#ifdef CONFIG_DEBUG_MVEBU_UART_ALTERNATE +#define ARMADA_370_XP_REGS_PHYS_BASE 0xf1000000 +#else #define ARMADA_370_XP_REGS_PHYS_BASE 0xd0000000 +#endif
And then switch this logic.
thx,
Jason.
Quoted 7 lines
arch/arm/include/debug/mvebu.S +1
-0+ #define ARMADA_370_XP_REGS_VIRT_BASE 0xfec00000 .macro addruart, rp, rv, tmpSignature · 1 line
1.8.1.2
PATCH 7/8 arm: mvebu: add another earlyprintk Kconfig option
Dear Jason Cooper,
Quoted 7 lines · Jason Cooper
Quoted 1 line
config
DEBUG_MVEBU_UARTPerhaps we should change this to
DEBUG_MVEBU_UART_LEGACY?arch/arm/Kconfig.debug choice · line 323
Quoted 1 line
arch/arm/Kconfig.debug +1
-0+ config DEBUG_MVEBU_UART_ALTERNATEAnd this to
DEBUG_MVEBU_UART?
I'm fine with doing that, but it means that people who will keep their current .config that has CONFIG_DEBUG_MVEBU_UART=y will suddenly see their earlyprintk use 0xf1 instead of 0xd0. So in terms of kconfig backward compatibility, it's not the nicest thing, but if you believe that's ok, I'll change the patch as you proposed.
Best regards,
Thomas
Signature · 4 lines
Thomas Petazzoni, Free Electrons Kernel, drivers, real-time and embedded Linux development, consulting, training and support. http://free-electrons.com
PATCH 7/8 arm: mvebu: add another earlyprintk Kconfig option
Quoted 12 lines · Thomas Petazzoni
Dear Jason Cooper,
Quoted 7 lines · Jason Cooper
Quoted 1 line
config
DEBUG_MVEBU_UARTPerhaps we should change this to
DEBUG_MVEBU_UART_LEGACY?arch/arm/Kconfig.debug choice · line 323
Quoted 1 line
arch/arm/Kconfig.debug +1
-0+ config DEBUG_MVEBU_UART_ALTERNATEAnd this to
DEBUG_MVEBU_UART?
Quoted 5 lines
I'm fine with doing that, but it means that people who will keep their current .config that has
CONFIG_DEBUG_MVEBU_UART=ywill suddenly see their earlyprintk use0xf1instead of0xd0. So in terms of kconfig backward compatibility, it's not the nicest thing, but if you believe that's ok, I'll change the patch as you proposed.
Very true. I was purely looking at form. Backwards compatibility is definitely more important.
thx,
Jason.
PATCH 8/8 arm: mvebu: disable DEBUG_LL/EARLY_PRINTK in defconfig
In reply to Thomas PetazzoniNow that we have two different addresses for the UART, depending on which bootloader is used, it is no longer desirable to enable earlyprintk by default in the defconfig. Users who need earlyprintk support will have to enable it explicitly, and select the right UART configuration depending on their platform.
--- arch/arm/configs/mvebu_defconfig | 2 -- 1 file changed, 2 deletions(-)
arch/arm/configs/mvebu_defconfig +0 -2
@@ -96,5 +96,3 @@ CONFIG_TIMER_STATS=y # CONFIG_DEBUG_BUGVERBOSE is not set CONFIG_DEBUG_INFO=y CONFIG_DEBUG_USER=y -CONFIG_DEBUG_LL=y -CONFIG_EARLY_PRINTK=y
Signature · 1 line
1.8.1.2
cover Support Marvell bootloaders remapping registers at different locations
In reply to Thomas PetazzoniQuoted 21 lines · On Wednesday 05 June 2013 09:04:53 Thomas Petazzoni wrote:
On Marvell platforms, the base address of the "internal registers" (i.e registers of all peripherals) can be configured at runtime. At reset, it is set to
0xD0000000, but it can freely be changed to some other location.On all previous Marvell SoC families, Linux assumes the bootloader has remapped the internal registers at
0xF1000000, and Marvell is now moving to do the same on Armada 370/XP, since it allows to use as much RAM as possible in the 0 -> 4G area. However, due to early issues, until now, Marvell bootloaders were leaving the internal registers address set to0xD0000000, and recently, Marvell has started shipping bootloaders that remapped those registers to0xF1000000.In order to support those two cases, we want to make sure the Device Tree is the only location where the physical base address of the internal registers is stored. This patch set removes the places where the physical base address of the registers was hardcoded and provides two
Kconfigoptions for the earlyprintk UART address selection (one for0xD0000000and one for0xF1000000).
Quoted 8 lines
It no longer uses the CP15 trick, nor it tries to do runtime remapping to
0xF1if it wasn't done by the bootloader. But it allows to easily boot a kernel with both old and new bootloaders by doing a simple change, in a single location in the Device Tree.This patch series is based on jcooper/mvebu/fixes-non-critical and jcooper/mvebu/cleanup, which contains 3 patches that are necessary to make this patch series work properly.
Looks all good to me, thanks a lot for sorting this out!
cover Support Marvell bootloaders remapping registers at different locations
In reply to Thomas PetazzoniQuoted 3 lines · Thomas Petazzoni
This patch series is based on jcooper/mvebu/fixes-non-critical and jcooper/mvebu/cleanup, which contains 3 patches that are necessary to make this patch series work properly.
Thomas,
I've tentatively pulled your series into mvebu/regmap with appropriate dependencies.
I was going to put this in for-next, but I got a build error after merging it. Could you do me a favor and try merging this with mvebu/seb_clk? Just shoot me the merge resolution that builds mvebu_defconfig correctly, and I'll incorporate it into the merge. No need to rebase the series.
If you want to reproduce what I saw, just merge mvebu/regmap with for-next (up shortly), and build mvebu_defconfig.
thx,
Jason.
cover Support Marvell bootloaders remapping registers at different locations
Quoted 10 lines · Jason Cooper
Quoted 3 lines · Thomas Petazzoni
This patch series is based on jcooper/mvebu/fixes-non-critical and jcooper/mvebu/cleanup, which contains 3 patches that are necessary to make this patch series work properly.
Thomas,
I've tentatively pulled your series into mvebu/regmap with appropriate dependencies.
Quoted 8 lines
I was going to put this in for-next, but I got a build error after merging it. Could you do me a favor and try merging this with mvebu/seb_clk? Just shoot me the merge resolution that builds
mvebu_defconfigcorrectly, and I'll incorporate it into the merge. No need to rebase the series.If you want to reproduce what I saw, just merge mvebu/regmap with for-next (up shortly), and build
mvebu_defconfig.
This has now been resolved, whole series, with v2 of the one patch is in mvebu/regmap.
thx,
Jason.
cover Support Marvell bootloaders remapping registers at different locations
Dear Jason Cooper,
Quoted 9 lines · Jason Cooper
Quoted 9 lines
I've tentatively pulled your series into mvebu/regmap with appropriate dependencies.
I was going to put this in for-next, but I got a build error after merging it. Could you do me a favor and try merging this with mvebu/seb_clk? Just shoot me the merge resolution that builds
mvebu_defconfigcorrectly, and I'll incorporate it into the merge. No need to rebase the series.
Quoted 5 lines
Quoted 2 lines
If you want to reproduce what I saw, just merge mvebu/regmap with for-next (up shortly), and build
mvebu_defconfig.This has now been resolved, whole series, with v2 of the one patch is in mvebu/regmap.
Ah, yes, sorry, I didn't reply to your e-mail, but we sorted it together on IRC right after you sent the mail.
Thanks for integrating the v2 of the patch!
Best regards,
Thomas
Signature · 4 lines
Thomas Petazzoni, Free Electrons Kernel, drivers, real-time and embedded Linux development, consulting, training and support. http://free-electrons.com