enable HiP04 SoC
Subsystems (7)
v16 cover enable HiP04 SoC
Changelog:
v16:
* Create new hip04 interrupt controller driver.
* Drop both hip04_defconfig & multi_v7_lpae_defconfig. Use hisi_defconfig & multi_v7_defconfig instead.
* Rename hi3xxx_defconfig to hisi_defconfig. Since we need follow the rule of each vendor only using one defconfig.
* Fix parsing memory issue in FDT when 64-bit address is enabled without CONFIG_ARM_LPAE.
* Drop bootwrapper parameters from DTS file. Use command line instead.
* Declare clock node in DTS file since all these clocks are only fixed rate clocks.
* Drop vgic patch.
v15:
* Add p04 debug uart back.
* Refresh since hix5hd2 code updated.
v14:
* Mount function pointers to different implementation on standard GICv2 and Hisilicon HiP04 GIC.
v13:
* Restore power down operation in MCPM.
* Fix disabling snoop filter issue in MCPM.
v12:
* Use wfi as power down state in MCPM.
* Remove wait_for_powerdown() in MCPM because wfi is used now.
v11:
* Fix the protection issue on mcpm power down.
* Clean assembly code in mcpm power up.
v10:
* Move snoop filter code to be executed on secondary cores. And change it to assembly code since MMU isn't enabled at that time.
* Rebase irq gic patch on latest gic patch.
* Use global variable in irq gic patch.
* Use global variable in vgic patch.
* Drop debug uart patch since it's in another patch set.
* Remove some ARCHs from multi_v7_lpae_defconfig.
v9:
* Remove delay workaround in mcpm implementation.
* Clean in gic.
* Rename vgic_cpu_nr_lr to vgic_cpu_hw_cfg in vgic driver.
* Always use high word of vgic_cpu_hw_cfg for GICH_APR offset. So the implementation of arm64 is also updated.
* Drop "irq: gic: use mask field in GICC_IAR" patch since it's merged.
v7:
* Remove hip04_smp_init_ops().
* Remove CONFIG_ARCH_HIP04 in hisilicn.c since hip04_smp_init_ops() is removed.
v6:
* Split HiP04 enabling patch into patches on document, mcpm & hiP04.
* Move reset operation in HiP04 MCPM implementation.
* Remove ARCH_MULTI_V7_NONLPAE & ARCH_MULTI_V7_LPAE according to olof's comment.
v5:
* Add ARCH_MULTI_V7_NONLPAE to avoid change too much things in Kconfig.
* Use memreserve in DTS.
* Remove L2 reset operation in mcpm implementation.
* Re-use nr_lr field to cover HIP04 GICH_APR implementation.
* Add more comments.
v4:
* Add multi_v7_lpae_defconfig.
* Select CONFIG_ARCH_MULTI_V7_LPAE if CONFIG_ARCH_MULTI_V7 is selected.
* Only ARMADA_XP is ARCH_MULTI_V7_LPAE, other ARMADA chips are ARCH_MULTI_V7.
* Remove gich_lr0 variable since we can calculate offset of GICH_LR0 from GICH_APR.
* Cleanup GIC driver to support HiP04 GIC.
* Cleanup HiP04 mcpm implementation.
v3:
* Replace CONFIG_ARCH_MULTI_V7 by CONFIG_ARCH_MULTI_V7_LPAE in some SoC.
* Update MCPM code based on Dave's patch.
* Remove MCPM node in DTS file. Use sysctrl & fabric node instead.
* Move hardcoding on bootwrapper into DTS file.
* Append the CONFIG_MCPM_QUAD_CLUSTER for HiP04.
* Fix the return value from gic_get_cpumask() if it's used in standard gic.
* Add the vgic support on HiP04 GIC.
* Add virtualization support in HiP04 defconfig.
v2:
* Append ARCH_MULTI_V7_LPAE configuration. Define ARCH_MULTI_V7 to only support non-LPAE platform.
* Append document of DT supporting.
* Append ARCH_HISI in hi3xxx_defconfig.
* Enable errata 798181 for HiP04 SoC.
* Add PMU support.
Haojian Zhuang (9):
ARM: mcpm: support 4 clusters
ARM: hisi: enable MCPM implementation
ARM: hisi: enable HiP04
document: dt: add the binding on HiP04
ARM: dts: add hip04 dts
ARM: config: enable hisilicon hip04
ARM: debug: add HiP04 debug uart
irq: enable hip04 irq chip
of: fdt: fix memory address be truncated
.../bindings/arm/hisilicon/hisilicon.txt | 12 + arch/arm/Kconfig | 9 + arch/arm/Kconfig.debug | 10 + arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/hip04-d01.dts | 32 ++ arch/arm/boot/dts/hip04.dtsi | 262 +++++++++++++ arch/arm/configs/hi3xxx_defconfig | 58 --- arch/arm/configs/hisi_defconfig | 72 ++++ arch/arm/configs/multi_v7_defconfig | 2 + arch/arm/include/asm/mcpm.h | 5 + arch/arm/mach-hisi/Kconfig | 9 + arch/arm/mach-hisi/Makefile | 1 + arch/arm/mach-hisi/hisilicon.c | 9 + arch/arm/mach-hisi/platmcpm.c | 374 ++++++++++++++++++ drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-hip04.c | 429 +++++++++++++++++++++ drivers/of/fdt.c | 10 + 17 files changed, 1238 insertions(+), 58 deletions(-) create mode 100644 arch/arm/boot/dts/hip04-d01.dts create mode 100644 arch/arm/boot/dts/hip04.dtsi delete mode 100644 arch/arm/configs/hi3xxx_defconfig create mode 100644 arch/arm/configs/hisi_defconfig create mode 100644 arch/arm/mach-hisi/platmcpm.c create mode 100644 drivers/irqchip/irq-hip04.c
Signature · 1 line
1.9.1
PATCH v16 1/9 ARM: mcpm: support 4 clusters
Add the CONFIG_MCPM_QUAD_CLUSTER configuration to enlarge cluster number from 2 to 4.
--- arch/arm/Kconfig | 9 +++++++++ arch/arm/include/asm/mcpm.h | 5 +++++ 2 files changed, 14 insertions(+)
arch/arm/Kconfig +9 -0
@@ -1490,6 +1490,15 @@ config MCPM for (multi-)cluster based systems, such as big.LITTLE based systems. +config MCPM_QUAD_CLUSTER + bool + depends on MCPM + help + To avoid wasting resources unnecessarily, MCPM only supports up + to 2 clusters by default. + Platforms with 3 or 4 clusters that use MCPM must select this + option to allow the additional clusters to be managed. + config BIG_LITTLE bool "big.LITTLE support (Experimental)" depends on CPU_V7 && SMP
arch/arm/include/asm/mcpm.h +5 -0
@@ -20,7 +20,12 @@* to consider dynamic allocation. */ #define MAX_CPUS_PER_CLUSTER 4 + +#ifdef CONFIG_MCPM_QUAD_CLUSTER +#define MAX_NR_CLUSTERS 4 +#else #define MAX_NR_CLUSTERS 2 +#endif #ifndef __ASSEMBLY__
Signature · 1 line
1.9.1
PATCH v16 2/9 ARM: hisi: enable MCPM implementation
In reply to Haojian ZhuangMultiple CPU clusters are used in Hisilicon HiP04 SoC. Now use MCPM framework to manage power on HiP04 SoC.
Changelog:
v16:
* Parse bootwrapper parameters in command line instead.
v13:
* Restore power down operation in MCPM.
* Fix disabling snoop filter issue in MCPM.
v12:
* Use wfi as power down state in MCPM.
* Remove wait_for_powerdown() in MCPM because wfi is used now.
--- arch/arm/mach-hisi/Makefile | 1 + arch/arm/mach-hisi/platmcpm.c | 374 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 375 insertions(+) create mode 100644 arch/arm/mach-hisi/platmcpm.c
arch/arm/mach-hisi/Makefile +1 -0
@@ -3,4 +3,5 @@ # obj-y += hisilicon.o +obj-$(CONFIG_MCPM) += platmcpm.o obj-$(CONFIG_SMP) += platsmp.o hotplug.o headsmp.o
arch/arm/mach-hisi/platmcpm.c new file +374 -0
374 lines not on this page · raw message
Signature · 1 line
1.9.1
PATCH v16 2/9 ARM: hisi: enable MCPM implementation
Sorry for the delay -- I was on vacation.
Quoted 6 lines · Haojian Zhuang
Multiple CPU clusters are used in Hisilicon HiP04 SoC. Now use MCPM framework to manage power on HiP04 SoC.
Changelog:
v16:
* Parse bootwrapper parameters in command line instead.
What is that about? I don't particularly like to see bootloader handshake details passed to the kernel via the kernel command line mechanism. Given this looks like special memory regions, can't they be specified via the device tree instead?
Quoted 8 lines
v13:
* Restore power down operation in MCPM.
* Fix disabling snoop filter issue in MCPM.
v12:
* Use wfi as power down state in MCPM.
* Removewait_for_powerdown()in MCPM because wfi is used now.Signed-off-by Haojian Zhuang <[email protected]>
More comments below.
Quoted 96 lines
--- arch/arm/mach-hisi/Makefile | 1 + arch/arm/mach-hisi/platmcpm.c | 374 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 375 insertions(+) create mode 100644 arch/arm/mach-hisi/platmcpm.carch/arm/mach-hisi/Makefile +1
-0@@ -3,4 +3,5 @@ # obj-y += hisilicon.o +obj-$(CONFIG_MCPM) += platmcpm.o obj-$(CONFIG_SMP) += platsmp.o hotplug.o headsmp.oarch/arm/mach-hisi/platmcpm.c new file +74
-0@@ -0,0 +1,374 @@ +/* +* Copyright (c) 2013-2014 Linaro Ltd. +* Copyright (c) 2013-2014 Hisilicon Limited. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +*/ +#include <linux/delay.h> +#include <linux/io.h> +#include <linux/memblock.h> +#include <linux/of_address.h> + +#include <asm/cputype.h> +#include <asm/cp15.h> +#include <asm/mcpm.h> + +#include "core.h" + +/* bits definition in SC_CPU_RESET_REQ[x]/SC_CPU_RESET_DREQ[x] +* 1 -- unreset; 0 -- reset +*/ +#define CORE_RESET_BIT (x) (1 << x) +#define NEON_RESET_BIT (x) (1 << (x + 4)) +#define CORE_DEBUG_RESET_BIT (x) (1 << (x + 9)) +#define CLUSTER_L2_RESET_BIT (1 << 8) +#define CLUSTER_DEBUG_RESET_BIT (1 << 13) + +/* +* bits definition in SC_CPU_RESET_STATUS[x] +* 1 -- reset status; 0 -- unreset status +*/ +#define CORE_RESET_STATUS (x) (1 << x) +#define NEON_RESET_STATUS (x) (1 << (x + 4)) +#define CORE_DEBUG_RESET_STATUS (x) (1 << (x + 9)) +#define CLUSTER_L2_RESET_STATUS (1 << 8) +#define CLUSTER_DEBUG_RESET_STATUS (1 << 13) +#define CORE_WFI_STATUS (x) (1 << (x + 16)) +#define CORE_WFE_STATUS (x) (1 << (x + 20)) +#define CORE_DEBUG_ACK (x) (1 << (x + 24)) + +#define SC_CPU_RESET_REQ (x) (0x520 + (x << 3))/* reset */ +#define SC_CPU_RESET_DREQ (x) (0x524 + (x << 3))/* unreset */ +#define SC_CPU_RESET_STATUS (x) (0x1520 + (x << 3)) + +#define FAB_SF_MODE 0x0c +#define FAB_SF_INVLD 0x10 + +/* bits definition in FB_SF_INVLD */ +#define FB_SF_INVLD_START (1 << 8) + +#define HIP04_MAX_CLUSTERS 4 +#define HIP04_MAX_CPUS_PER_CLUSTER 4 + +#define POLL_MSEC 10 +#define TIMEOUT_MSEC 1000 + +struct hip04_secondary_cpu_data { +u32 bootwrapper_phys; +u32 bootwrapper_size; +u32 bootwrapper_magic; +u32 relocation_entry; +u32 relocation_size; +}; + +static void __iomem *relocation, *sysctrl, *fabric; +static int hip04_cpu_table[HIP04_MAX_CLUSTERS ][HIP04_MAX_CPUS_PER_CLUSTER ]; +static DEFINE_SPINLOCK (boot_lock); +static struct hip04_secondary_cpu_data hip04_boot; +static u32 fabric_phys_addr; + +static int __init hip04_parse_bootwrapper (char *p) +{ +int data[4 ];
arch/arm/mach-hisi/platmcpm.c line 84
Quoted 10 lines
arch/arm/mach-hisi/platmcpm.c new file +10
-0+ +get_options (p,ARRAY_SIZE (data), &data[0 ]); +if (!data[0 ] || (data[0 ] <3 )) { +pr_err ("fail to parse bootwrapper parameters\n" ); +return -EINVAL ; + } + hip04_boot.bootwrapper_phys = data[1 ]; + hip04_boot.bootwrapper_size = data[2 ]; + hip04_boot.bootwrapper_magic = data[3 ]; +memblock_reserve (data[1 ], data[2 ]);
What if memblock_reserve() fails? You should at least avoid initializing hip04_boot in that case.
Quoted 10 lines
arch/arm/mach-hisi/platmcpm.c new file +10
-0+return 0 ; +} +early_param ("bootwrapper" , hip04_parse_bootwrapper); + +static int __init hip04_parse_relocation (char *p) +{ +int data[3 ]; + +get_options (p,ARRAY_SIZE (data), &data[0 ]); +if (!data[0 ] || (data[0 ] <2 )) {
arch/arm/mach-hisi/platmcpm.c line 104
Quoted 10 lines
arch/arm/mach-hisi/platmcpm.c new file +10
-0+pr_err ("fail to parse relocation parameters\n" ); +return -EINVAL ; + } + hip04_boot.relocation_entry = data[1 ]; + hip04_boot.relocation_size = data[2 ]; +return 0 ; +} +early_param ("relocation" , hip04_parse_relocation); + +static bool hip04_cluster_down (unsigned int cluster)
I'd suggest renaming this into hip04_cluster_is_down() as it only returns a state and performs no action.
Quoted 42 lines
arch/arm/mach-hisi/platmcpm.c new file +42
-0+{ +int i; + +for (i =0 ; i <HIP04_MAX_CPUS_PER_CLUSTER ; i++) +if (hip04_cpu_table[cluster][i]) +return false; +return true; +} + +static void hip04_set_snoop_filter (unsigned int cluster,unsigned int on) +{ +unsigned long data; + +if (!fabric) +BUG (); + data =readl_relaxed (fabric +FAB_SF_MODE ); +if (on) + data |=1 << cluster; +else + data &= ~(1 << cluster); +writel_relaxed (data, fabric +FAB_SF_MODE ); +while (1 ) { +if (data ==readl_relaxed (fabric +FAB_SF_MODE )) +break ; + } +return ; +} + +static int hip04_mcpm_power_up (unsigned int cpu,unsigned int cluster) +{ +unsigned long data, mask; + +if (!relocation || !sysctrl) +return -ENODEV ; +if (cluster >=HIP04_MAX_CLUSTERS || cpu >=HIP04_MAX_CPUS_PER_CLUSTER ) +return -EINVAL ; + +spin_lock_irq (&boot_lock); + +if (hip04_cpu_table[cluster][cpu]) + goto out; +
arch/arm/mach-hisi/platmcpm.c line 156
Quoted 10 lines
arch/arm/mach-hisi/platmcpm.c new file +10
-0+/* Make secondary core out of reset. */ +writel_relaxed (hip04_boot.bootwrapper_phys, relocation); +writel_relaxed (hip04_boot.bootwrapper_magic, relocation +4 ); +writel_relaxed (virt_to_phys (mcpm_entry_point), relocation +8 ); +writel_relaxed (0 , relocation +12 ); + +if (hip04_cluster_down (cluster)) { + data =CLUSTER_DEBUG_RESET_BIT ; +writel_relaxed (data, sysctrl +SC_CPU_RESET_DREQ (cluster)); + do {
Inserting a cpu_relax() right here wouldn't hurt.
Quoted 30 lines
arch/arm/mach-hisi/platmcpm.c new file +30
-0+ mask =CLUSTER_DEBUG_RESET_STATUS ; + data =readl_relaxed (sysctrl + \ +SC_CPU_RESET_STATUS (cluster)); + }while (data & mask); + } + + data =CORE_RESET_BIT (cpu) |NEON_RESET_BIT (cpu) | \ +CORE_DEBUG_RESET_BIT (cpu); +writel_relaxed (data, sysctrl +SC_CPU_RESET_DREQ (cluster)); +out: + hip04_cpu_table[cluster][cpu]++; +spin_unlock_irq (&boot_lock); + +return 0 ; +} + +static void hip04_mcpm_power_down (void ) +{ +unsigned int mpidr, cpu, cluster; +bool skip_wfi = false; + + mpidr =read_cpuid_mpidr (); + cpu =MPIDR_AFFINITY_LEVEL (mpidr,0 ); + cluster =MPIDR_AFFINITY_LEVEL (mpidr,1 ); + +__mcpm_cpu_going_down (cpu, cluster); + +spin_lock (&boot_lock); +BUG_ON (__mcpm_cluster_state (cluster) !=CLUSTER_UP ); + hip04_cpu_table[cluster][cpu]--;
arch/arm/mach-hisi/platmcpm.c line 196
Quoted 10 lines
arch/arm/mach-hisi/platmcpm.c new file +10
-0+if (hip04_cpu_table[cluster][cpu] ==1 ) { +/* A power_up request went ahead of us. */ + skip_wfi = true; + }else if (hip04_cpu_table[cluster][cpu] >1 ) { +pr_err ("Cluster %d CPU%d boots multiple times\n" , cluster, cpu); +BUG (); + } +spin_unlock (&boot_lock); + +v7_exit_coherency_flush (louis);
If this is the last man, the whole cache must be flushed with v7_exit_coherency_flush(all).
Quoted 10 lines
arch/arm/mach-hisi/platmcpm.c new file +10
-0+ +__mcpm_cpu_down (cpu, cluster); + +if (!skip_wfi) +wfi (); +} + +static int hip04_mcpm_wait_for_powerdown (unsigned int cpu,unsigned int cluster) +{ +unsigned int data, tries, count;
arch/arm/mach-hisi/platmcpm.c line 216
Quoted 10 lines
arch/arm/mach-hisi/platmcpm.c new file +10
-0+ +BUG_ON (cluster >=HIP04_MAX_CLUSTERS || + cpu >=HIP04_MAX_CPUS_PER_CLUSTER ); + + count =TIMEOUT_MSEC /POLL_MSEC ; +spin_lock (&boot_lock); +for (tries =0 ; tries < count; tries++) { + data =readl_relaxed (sysctrl +SC_CPU_RESET_STATUS (cluster)); +if (!(data &CORE_WFI_STATUS (cpu))) { +msleep (POLL_MSEC );
You can't sleep while holding a lock.
arch/arm/mach-hisi/platmcpm.c line 228
Quoted 12 lines
arch/arm/mach-hisi/platmcpm.c new file +12
-0+continue ; + } + } +if (tries >= count) + goto err; + data =CORE_RESET_BIT (cpu) |NEON_RESET_BIT (cpu) | \ +CORE_DEBUG_RESET_BIT (cpu); +writel_relaxed (data, sysctrl +SC_CPU_RESET_REQ (cluster)); +for (tries =0 ; tries < count; tries++) { + data =readl_relaxed (sysctrl +SC_CPU_RESET_STATUS (cluster)); +if (!(data &CORE_RESET_STATUS (cpu))) { +msleep (POLL_MSEC );
Same here.
Also I don't really like the way this MCPM method is abused to shut down a CPU because the target CPU can't do it on its own. We're getting back to this again and I suppose this is because the hardware is not able to do otherwise. However this mysterious CORE_WFI_STATUS bit made its apparition lately, so one may speculate that the hardware might be able to do more than it may seem. The lack of (english) documentation is really making a more optimal implementation impossible at this point. So I'll give in and let this pass but not without a sufficiently comprehensive comment in the code to that effect.
Now... around msleep calls you have to drop and reacquire the lock. And when the lock is reacquired you should check that the CPU count is still 0 and bail out otherwise so not to mess up with a concurrent cpu_up(). This won't be enough to prevent a race against asynchronous wake-ups though, but you are not doing any of that yet. That too would need to be documented in that comment.
arch/arm/mach-hisi/platmcpm.c line 236
Quoted 8 lines
arch/arm/mach-hisi/platmcpm.c new file +8
-0+continue ; + } + } +if (tries >= count) + goto err; +if (hip04_cluster_down (cluster)) +hip04_set_snoop_filter (cluster,0 ); +spin_unlock (&boot_lock);
Oh, and that ought to be spin_lock_irq()/spin_unlock_irq() here.
Quoted 61 lines
arch/arm/mach-hisi/platmcpm.c new file +61
-0+return 0 ; +err: +spin_unlock (&boot_lock); +return -ETIMEDOUT ; +} + +static void hip04_mcpm_powered_up (void ) +{ +if (!relocation) +return ; +spin_lock (&boot_lock); +writel_relaxed (0 , relocation); +writel_relaxed (0 , relocation +4 ); +writel_relaxed (0 , relocation +8 ); +writel_relaxed (0 , relocation +12 ); +spin_unlock (&boot_lock); +} + +static void __naked hip04_mcpm_power_up_setup (unsigned int affinity_level) +{ + asmvolatile (" \n" +" cmp r0, #0 \n" +" bxeq lr \n" +/* calculate fabric phys address */ +" adr r2, 2f \n" +" ldmia r2, {r1, r3} \n" +" sub r0, r2, r1 \n" +" ldr r2, [r0, r3] \n" +/* get cluster id from MPIDR */ +" mrc p15, 0, r0, c0, c0, 5 \n" +" ubfx r1, r0, #8, #8 \n" +/* 1 << cluster id */ +" mov r0, #1 \n" +" mov r3, r0, lsl r1 \n" +" ldr r0, [r2, #"__stringify(FAB_SF_MODE)"] \n" +" tst r0, r3 \n" +" bxne lr \n" +" orr r1, r0, r3 \n" +" str r1, [r2, #"__stringify(FAB_SF_MODE)"] \n" +"1: ldr r0, [r2, #"__stringify(FAB_SF_MODE)"] \n" +" tst r0, r3 \n" +" beq 1b \n" +" bx lr \n" + +" .align 2 \n" +"2: .word . \n" +" .word fabric_phys_addr \n" + ); +} + +static const struct mcpm_platform_ops hip04_mcpm_ops = { + .power_up = hip04_mcpm_power_up, + .power_down = hip04_mcpm_power_down, + .wait_for_powerdown = hip04_mcpm_wait_for_powerdown, + .powered_up = hip04_mcpm_powered_up, +}; + +static bool __init hip04_cpu_table_init (void ) +{ +unsigned int mpidr, cpu, cluster; +
arch/arm/mach-hisi/platmcpm.c line 307
Quoted 10 lines
arch/arm/mach-hisi/platmcpm.c new file +10
-0+ mpidr =read_cpuid_mpidr (); + cpu =MPIDR_AFFINITY_LEVEL (mpidr,0 ); + cluster =MPIDR_AFFINITY_LEVEL (mpidr,1 ); + +if (cluster >=HIP04_MAX_CLUSTERS || + cpu >=HIP04_MAX_CPUS_PER_CLUSTER ) { +pr_err ("%s: boot CPU is out of bound!\n" , __func__); +return false; + } +hip04_set_snoop_filter (0 ,1 );
This should be hip04_set_snoop_filter(cluster, 1).
Quoted 48 lines
arch/arm/mach-hisi/platmcpm.c new file +48
-0+ hip04_cpu_table[cluster][cpu] =1 ; +return true; +} + +static int __init hip04_mcpm_init (void ) +{ +struct device_node *np, *np_fab; +struct resource fab_res; +int ret = -ENODEV ; + +if (!hip04_boot.bootwrapper_phys || !hip04_boot.relocation_entry) { +pr_err ("fail to find bootwrapper or relocation param\n" ); + ret = -EINVAL ; + goto err; + } + + np =of_find_compatible_node (NULL ,NULL ,"hisilicon,sysctrl" ); +if (!np) + goto err; + np_fab =of_find_compatible_node (NULL ,NULL ,"hisilicon,hip04-fabric" ); +if (!np_fab) + goto err; + + relocation =ioremap (hip04_boot.relocation_entry, + hip04_boot.relocation_size); +if (!relocation) { +pr_err ("failed to map relocation space\n" ); + ret = -ENOMEM ; + goto err; + } + sysctrl =of_iomap (np,0 ); +if (!sysctrl) { +pr_err ("failed to get sysctrl base\n" ); + ret = -ENOMEM ; + goto err_sysctrl; + } + ret =of_address_to_resource (np_fab,0 , &fab_res); +if (ret) { +pr_err ("failed to get fabric base phys\n" ); + goto err_fabric; + } + fabric_phys_addr = fab_res.start; +sync_cache_w (&fabric_phys_addr); + fabric =of_iomap (np_fab,0 ); +if (!fabric) { +pr_err ("failed to get fabric base\n" ); + ret = -ENOMEM ; + goto err_fabric;
arch/arm/mach-hisi/platmcpm.c line 365
Quoted 10 lines
arch/arm/mach-hisi/platmcpm.c new file +10
-0+ } + +if (!hip04_cpu_table_init ()) +return -EINVAL ; + ret =mcpm_platform_register (&hip04_mcpm_ops); +if (!ret) { +mcpm_sync_init (hip04_mcpm_power_up_setup); +pr_info ("HiP04 MCPM initialized\n" ); + } +mcpm_smp_set_ops ();
This mcpm_smp_set_ops() should be called only if MCPM registration is successful i.e. right after mcpm_sync_init inside the if conditional above.
Quoted 13 lines
arch/arm/mach-hisi/platmcpm.c new file +9
-0+return ret; +err_fabric: +iounmap (sysctrl); +err_sysctrl: +iounmap (relocation); +err: +return ret; +} +early_initcall (hip04_mcpm_init);Signature · 1 line
1.9.1
PATCH v16 2/9 ARM: hisi: enable MCPM implementation
Quoted 7 lines · Nicolas Pitre
Sorry for the delay -- I was on vacation.
Quoted 3 lines · Haojian Zhuang
Multiple CPU clusters are used in Hisilicon HiP04 SoC. Now use MCPM framework to manage power on HiP04 SoC.
Quoted 9 lines
Quoted 3 lines
Changelog:
v16:
* Parse bootwrapper parameters in command line instead.What is that about? I don't particularly like to see bootloader handshake details passed to the kernel via the kernel command line mechanism. Given this looks like special memory regions, can't they be specified via the device tree instead?
Others don't agree put them into DTS file. So I move them into command line.
Quoted 112 lines
Quoted 8 lines
v13:
* Restore power down operation in MCPM.
* Fix disabling snoop filter issue in MCPM.
v12:
* Use wfi as power down state in MCPM.
* Removewait_for_powerdown()in MCPM because wfi is used now.Signed-off-by Haojian Zhuang <[email protected]>More comments below.
Quoted 101 lines
--- arch/arm/mach-hisi/Makefile | 1 + arch/arm/mach-hisi/platmcpm.c | 374 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 375 insertions(+) create mode 100644 arch/arm/mach-hisi/platmcpm.carch/arm/mach-hisi/Makefile +1
-0@@ -3,4 +3,5 @@ # obj-y += hisilicon.o +obj-$(CONFIG_MCPM) += platmcpm.o obj-$(CONFIG_SMP) += platsmp.o hotplug.o headsmp.oarch/arm/mach-hisi/platmcpm.c new file +79
-0@@ -0,0 +1,374 @@ +/* +* Copyright (c) 2013-2014 Linaro Ltd. +* Copyright (c) 2013-2014 Hisilicon Limited. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +*/ +#include <linux/delay.h> +#include <linux/io.h> +#include <linux/memblock.h> +#include <linux/of_address.h> + +#include <asm/cputype.h> +#include <asm/cp15.h> +#include <asm/mcpm.h> + +#include "core.h" + +/* bits definition in SC_CPU_RESET_REQ[x]/SC_CPU_RESET_DREQ[x] +* 1 -- unreset; 0 -- reset +*/ +#define CORE_RESET_BIT (x) (1 << x) +#define NEON_RESET_BIT (x) (1 << (x + 4)) +#define CORE_DEBUG_RESET_BIT (x) (1 << (x + 9)) +#define CLUSTER_L2_RESET_BIT (1 << 8) +#define CLUSTER_DEBUG_RESET_BIT (1 << 13) + +/* +* bits definition in SC_CPU_RESET_STATUS[x] +* 1 -- reset status; 0 -- unreset status +*/ +#define CORE_RESET_STATUS (x) (1 << x) +#define NEON_RESET_STATUS (x) (1 << (x + 4)) +#define CORE_DEBUG_RESET_STATUS (x) (1 << (x + 9)) +#define CLUSTER_L2_RESET_STATUS (1 << 8) +#define CLUSTER_DEBUG_RESET_STATUS (1 << 13) +#define CORE_WFI_STATUS (x) (1 << (x + 16)) +#define CORE_WFE_STATUS (x) (1 << (x + 20)) +#define CORE_DEBUG_ACK (x) (1 << (x + 24)) + +#define SC_CPU_RESET_REQ (x) (0x520 + (x << 3))/* reset */ +#define SC_CPU_RESET_DREQ (x) (0x524 + (x << 3))/* unreset */ +#define SC_CPU_RESET_STATUS (x) (0x1520 + (x << 3)) + +#define FAB_SF_MODE 0x0c +#define FAB_SF_INVLD 0x10 + +/* bits definition in FB_SF_INVLD */ +#define FB_SF_INVLD_START (1 << 8) + +#define HIP04_MAX_CLUSTERS 4 +#define HIP04_MAX_CPUS_PER_CLUSTER 4 + +#define POLL_MSEC 10 +#define TIMEOUT_MSEC 1000 + +struct hip04_secondary_cpu_data { +u32 bootwrapper_phys; +u32 bootwrapper_size; +u32 bootwrapper_magic; +u32 relocation_entry; +u32 relocation_size; +}; + +static void __iomem *relocation, *sysctrl, *fabric; +static int hip04_cpu_table[HIP04_MAX_CLUSTERS ][HIP04_MAX_CPUS_PER_CLUSTER ]; +static DEFINE_SPINLOCK (boot_lock); +static struct hip04_secondary_cpu_data hip04_boot; +static u32 fabric_phys_addr; + +static int __init hip04_parse_bootwrapper (char *p) +{ +int data[4 ]; + +get_options (p,ARRAY_SIZE (data), &data[0 ]); +if (!data[0 ] || (data[0 ] <3 )) { +pr_err ("fail to parse bootwrapper parameters\n" ); +return -EINVAL ;
Quoted 9 lines
arch/arm/mach-hisi/platmcpm.c line 84
Quoted 5 lines
arch/arm/mach-hisi/platmcpm.c new file +5
-0+ } + hip04_boot.bootwrapper_phys = data[1 ]; + hip04_boot.bootwrapper_size = data[2 ]; + hip04_boot.bootwrapper_magic = data[3 ]; +memblock_reserve (data[1 ], data[2 ]);What if
memblock_reserve()fails? You should at least avoid initializinghip04_bootin that case.
OK. I'll check the return value.
Quoted 15 lines
Quoted 15 lines
arch/arm/mach-hisi/platmcpm.c new file +15
-0+return 0 ; +} +early_param ("bootwrapper" , hip04_parse_bootwrapper); + +static int __init hip04_parse_relocation (char *p) +{ +int data[3 ]; + +get_options (p,ARRAY_SIZE (data), &data[0 ]); +if (!data[0 ] || (data[0 ] <2 )) { +pr_err ("fail to parse relocation parameters\n" ); +return -EINVAL ; + } + hip04_boot.relocation_entry = data[1 ]; + hip04_boot.relocation_size = data[2 ];
Quoted 9 lines
arch/arm/mach-hisi/platmcpm.c line 104
Quoted 5 lines
arch/arm/mach-hisi/platmcpm.c new file +5
-0+return 0 ; +} +early_param ("relocation" , hip04_parse_relocation); + +static bool hip04_cluster_down (unsigned int cluster)I'd suggest renaming this into
hip04_cluster_is_down()as it only returns a state and performs no action.
OK.
Quoted 46 lines
Quoted 46 lines
arch/arm/mach-hisi/platmcpm.c new file +46
-0+{ +int i; + +for (i =0 ; i <HIP04_MAX_CPUS_PER_CLUSTER ; i++) +if (hip04_cpu_table[cluster][i]) +return false; +return true; +} + +static void hip04_set_snoop_filter (unsigned int cluster,unsigned int on) +{ +unsigned long data; + +if (!fabric) +BUG (); + data =readl_relaxed (fabric +FAB_SF_MODE ); +if (on) + data |=1 << cluster; +else + data &= ~(1 << cluster); +writel_relaxed (data, fabric +FAB_SF_MODE ); +while (1 ) { +if (data ==readl_relaxed (fabric +FAB_SF_MODE )) +break ; + } +return ; +} + +static int hip04_mcpm_power_up (unsigned int cpu,unsigned int cluster) +{ +unsigned long data, mask; + +if (!relocation || !sysctrl) +return -ENODEV ; +if (cluster >=HIP04_MAX_CLUSTERS || cpu >=HIP04_MAX_CPUS_PER_CLUSTER ) +return -EINVAL ; + +spin_lock_irq (&boot_lock); + +if (hip04_cpu_table[cluster][cpu]) + goto out; + +/* Make secondary core out of reset. */ +writel_relaxed (hip04_boot.bootwrapper_phys, relocation); +writel_relaxed (hip04_boot.bootwrapper_magic, relocation +4 ); +writel_relaxed (virt_to_phys (mcpm_entry_point), relocation +8 );
Quoted 9 lines
arch/arm/mach-hisi/platmcpm.c line 156
Quoted 6 lines
arch/arm/mach-hisi/platmcpm.c new file +6
-0+writel_relaxed (0 , relocation +12 ); + +if (hip04_cluster_down (cluster)) { + data =CLUSTER_DEBUG_RESET_BIT ; +writel_relaxed (data, sysctrl +SC_CPU_RESET_DREQ (cluster)); + do {Inserting a
cpu_relax()right here wouldn't hurt.
OK
Quoted 35 lines
Quoted 35 lines
arch/arm/mach-hisi/platmcpm.c new file +35
-0+ mask =CLUSTER_DEBUG_RESET_STATUS ; + data =readl_relaxed (sysctrl + \ +SC_CPU_RESET_STATUS (cluster)); + }while (data & mask); + } + + data =CORE_RESET_BIT (cpu) |NEON_RESET_BIT (cpu) | \ +CORE_DEBUG_RESET_BIT (cpu); +writel_relaxed (data, sysctrl +SC_CPU_RESET_DREQ (cluster)); +out: + hip04_cpu_table[cluster][cpu]++; +spin_unlock_irq (&boot_lock); + +return 0 ; +} + +static void hip04_mcpm_power_down (void ) +{ +unsigned int mpidr, cpu, cluster; +bool skip_wfi = false; + + mpidr =read_cpuid_mpidr (); + cpu =MPIDR_AFFINITY_LEVEL (mpidr,0 ); + cluster =MPIDR_AFFINITY_LEVEL (mpidr,1 ); + +__mcpm_cpu_going_down (cpu, cluster); + +spin_lock (&boot_lock); +BUG_ON (__mcpm_cluster_state (cluster) !=CLUSTER_UP ); + hip04_cpu_table[cluster][cpu]--; +if (hip04_cpu_table[cluster][cpu] ==1 ) { +/* A power_up request went ahead of us. */ + skip_wfi = true; + }else if (hip04_cpu_table[cluster][cpu] >1 ) { +pr_err ("Cluster %d CPU%d boots multiple times\n" , cluster, cpu);
Quoted 9 lines
arch/arm/mach-hisi/platmcpm.c line 196
Quoted 5 lines
arch/arm/mach-hisi/platmcpm.c new file +5
-0+BUG (); + } +spin_unlock (&boot_lock); + +v7_exit_coherency_flush (louis);If this is the last man, the whole cache must be flushed with
v7_exit_coherency_flush(all).
OK
Quoted 14 lines
Quoted 14 lines
arch/arm/mach-hisi/platmcpm.c new file +14
-0+ +__mcpm_cpu_down (cpu, cluster); + +if (!skip_wfi) +wfi (); +} + +static int hip04_mcpm_wait_for_powerdown (unsigned int cpu,unsigned int cluster) +{ +unsigned int data, tries, count; + +BUG_ON (cluster >=HIP04_MAX_CLUSTERS || + cpu >=HIP04_MAX_CPUS_PER_CLUSTER ); +
Quoted 9 lines
arch/arm/mach-hisi/platmcpm.c line 216
Quoted 6 lines
arch/arm/mach-hisi/platmcpm.c new file +6
-0+ count =TIMEOUT_MSEC /POLL_MSEC ; +spin_lock (&boot_lock); +for (tries =0 ; tries < count; tries++) { + data =readl_relaxed (sysctrl +SC_CPU_RESET_STATUS (cluster)); +if (!(data &CORE_WFI_STATUS (cpu))) { +msleep (POLL_MSEC );You can't sleep while holding a lock.
Yes, I'll fix it.
Quoted 171 lines
arch/arm/mach-hisi/platmcpm.c line 228
Quoted 12 lines
arch/arm/mach-hisi/platmcpm.c new file +12
-0+continue ; + } + } +if (tries >= count) + goto err; + data =CORE_RESET_BIT (cpu) |NEON_RESET_BIT (cpu) | \ +CORE_DEBUG_RESET_BIT (cpu); +writel_relaxed (data, sysctrl +SC_CPU_RESET_REQ (cluster)); +for (tries =0 ; tries < count; tries++) { + data =readl_relaxed (sysctrl +SC_CPU_RESET_STATUS (cluster)); +if (!(data &CORE_RESET_STATUS (cpu))) { +msleep (POLL_MSEC );Same here.
Also I don't really like the way this MCPM method is abused to shut down a CPU because the target CPU can't do it on its own. We're getting back to this again and I suppose this is because the hardware is not able to do otherwise. However this mysterious
CORE_WFI_STATUSbit made its apparition lately, so one may speculate that the hardware might be able to do more than it may seem. The lack of (english) documentation is really making a more optimal implementation impossible at this point. So I'll give in and let this pass but not without a sufficiently comprehensive comment in the code to that effect.Now... around msleep calls you have to drop and reacquire the lock. And when the lock is reacquired you should check that the CPU count is still 0 and bail out otherwise so not to mess up with a concurrent
cpu_up(). This won't be enough to prevent a race against asynchronous wake-ups though, but you are not doing any of that yet. That too would need to be documented in that comment.arch/arm/mach-hisi/platmcpm.c line 236
Quoted 8 lines
arch/arm/mach-hisi/platmcpm.c new file +8
-0+continue ; + } + } +if (tries >= count) + goto err; +if (hip04_cluster_down (cluster)) +hip04_set_snoop_filter (cluster,0 ); +spin_unlock (&boot_lock);Oh, and that ought to be spin_lock_irq()/spin_unlock_irq() here.
Quoted 61 lines
arch/arm/mach-hisi/platmcpm.c new file +61
-0+return 0 ; +err: +spin_unlock (&boot_lock); +return -ETIMEDOUT ; +} + +static void hip04_mcpm_powered_up (void ) +{ +if (!relocation) +return ; +spin_lock (&boot_lock); +writel_relaxed (0 , relocation); +writel_relaxed (0 , relocation +4 ); +writel_relaxed (0 , relocation +8 ); +writel_relaxed (0 , relocation +12 ); +spin_unlock (&boot_lock); +} + +static void __naked hip04_mcpm_power_up_setup (unsigned int affinity_level) +{ + asmvolatile (" \n" +" cmp r0, #0 \n" +" bxeq lr \n" +/* calculate fabric phys address */ +" adr r2, 2f \n" +" ldmia r2, {r1, r3} \n" +" sub r0, r2, r1 \n" +" ldr r2, [r0, r3] \n" +/* get cluster id from MPIDR */ +" mrc p15, 0, r0, c0, c0, 5 \n" +" ubfx r1, r0, #8, #8 \n" +/* 1 << cluster id */ +" mov r0, #1 \n" +" mov r3, r0, lsl r1 \n" +" ldr r0, [r2, #"__stringify(FAB_SF_MODE)"] \n" +" tst r0, r3 \n" +" bxne lr \n" +" orr r1, r0, r3 \n" +" str r1, [r2, #"__stringify(FAB_SF_MODE)"] \n" +"1: ldr r0, [r2, #"__stringify(FAB_SF_MODE)"] \n" +" tst r0, r3 \n" +" beq 1b \n" +" bx lr \n" + +" .align 2 \n" +"2: .word . \n" +" .word fabric_phys_addr \n" + ); +} + +static const struct mcpm_platform_ops hip04_mcpm_ops = { + .power_up = hip04_mcpm_power_up, + .power_down = hip04_mcpm_power_down, + .wait_for_powerdown = hip04_mcpm_wait_for_powerdown, + .powered_up = hip04_mcpm_powered_up, +}; + +static bool __init hip04_cpu_table_init (void ) +{ +unsigned int mpidr, cpu, cluster; +arch/arm/mach-hisi/platmcpm.c line 307
Quoted 10 lines
arch/arm/mach-hisi/platmcpm.c new file +10
-0+ mpidr =read_cpuid_mpidr (); + cpu =MPIDR_AFFINITY_LEVEL (mpidr,0 ); + cluster =MPIDR_AFFINITY_LEVEL (mpidr,1 ); + +if (cluster >=HIP04_MAX_CLUSTERS || + cpu >=HIP04_MAX_CPUS_PER_CLUSTER ) { +pr_err ("%s: boot CPU is out of bound!\n" , __func__); +return false; + } +hip04_set_snoop_filter (0 ,1 );This should be
hip04_set_snoop_filter(cluster, 1).Quoted 54 lines
arch/arm/mach-hisi/platmcpm.c new file +54
-0+ hip04_cpu_table[cluster][cpu] =1 ; +return true; +} + +static int __init hip04_mcpm_init (void ) +{ +struct device_node *np, *np_fab; +struct resource fab_res; +int ret = -ENODEV ; + +if (!hip04_boot.bootwrapper_phys || !hip04_boot.relocation_entry) { +pr_err ("fail to find bootwrapper or relocation param\n" ); + ret = -EINVAL ; + goto err; + } + + np =of_find_compatible_node (NULL ,NULL ,"hisilicon,sysctrl" ); +if (!np) + goto err; + np_fab =of_find_compatible_node (NULL ,NULL ,"hisilicon,hip04-fabric" ); +if (!np_fab) + goto err; + + relocation =ioremap (hip04_boot.relocation_entry, + hip04_boot.relocation_size); +if (!relocation) { +pr_err ("failed to map relocation space\n" ); + ret = -ENOMEM ; + goto err; + } + sysctrl =of_iomap (np,0 ); +if (!sysctrl) { +pr_err ("failed to get sysctrl base\n" ); + ret = -ENOMEM ; + goto err_sysctrl; + } + ret =of_address_to_resource (np_fab,0 , &fab_res); +if (ret) { +pr_err ("failed to get fabric base phys\n" ); + goto err_fabric; + } + fabric_phys_addr = fab_res.start; +sync_cache_w (&fabric_phys_addr); + fabric =of_iomap (np_fab,0 ); +if (!fabric) { +pr_err ("failed to get fabric base\n" ); + ret = -ENOMEM ; + goto err_fabric; + } + +if (!hip04_cpu_table_init ()) +return -EINVAL ; + ret =mcpm_platform_register (&hip04_mcpm_ops); +if (!ret) {
Quoted 9 lines
arch/arm/mach-hisi/platmcpm.c line 365
Quoted 4 lines
arch/arm/mach-hisi/platmcpm.c new file +4
-0+mcpm_sync_init (hip04_mcpm_power_up_setup); +pr_info ("HiP04 MCPM initialized\n" ); + } +mcpm_smp_set_ops ();This
mcpm_smp_set_ops()should be called only if MCPM registration is successful i.e. right aftermcpm_sync_initinside the if conditional above.
OK
Quoted 13 lines
Quoted 13 lines
arch/arm/mach-hisi/platmcpm.c new file +9
-1+return ret; +err_fabric: +iounmap (sysctrl); +err_sysctrl: +iounmap (relocation); +err: +return ret; +} +early_initcall (hip04_mcpm_init); --1.9.1
PATCH v16 2/9 ARM: hisi: enable MCPM implementation
Quoted 12 lines · Haojian Zhuang
Quoted 11 lines · Nicolas Pitre
Sorry for the delay -- I was on vacation.
Quoted 6 lines · Haojian Zhuang
Multiple CPU clusters are used in Hisilicon HiP04 SoC. Now use MCPM framework to manage power on HiP04 SoC.
Changelog:
v16:
* Parse bootwrapper parameters in command line instead.
Quoted 7 lines
Quoted 5 lines
What is that about? I don't particularly like to see bootloader handshake details passed to the kernel via the kernel command line mechanism. Given this looks like special memory regions, can't they be specified via the device tree instead?
Others don't agree put them into DTS file. So I move them into command line.
Could you give me a pointer to the discussion around that please?
Nicolas
PATCH v16 2/9 ARM: hisi: enable MCPM implementation
Quoted 20 lines · Nicolas Pitre
Quoted 18 lines · Haojian Zhuang
Quoted 16 lines · Nicolas Pitre
Sorry for the delay -- I was on vacation.
Quoted 6 lines · Haojian Zhuang
Multiple CPU clusters are used in Hisilicon HiP04 SoC. Now use MCPM framework to manage power on HiP04 SoC.
Changelog:
v16:
* Parse bootwrapper parameters in command line instead.What is that about? I don't particularly like to see bootloader handshake details passed to the kernel via the kernel command line mechanism. Given this looks like special memory regions, can't they be specified via the device tree instead?
Quoted 6 lines
Quoted 1 line
Others don't agree put them into DTS file. So I move them into command line.
Could you give me a pointer to the discussion around that please?
Nicolas
http://lists.infradead.org/pipermail/linux-arm-kernel/2014-July/275944.html
Mark challenged what's relationship between bootwrapper address and system controller. Actually code in bootwrapper is like trampoline. And it's a software protocol, not hardware description. So I moved them into command line instead.
Regards
Haojian
PATCH v16 2/9 ARM: hisi: enable MCPM implementation
Quoted 26 lines · Haojian Zhuang
Quoted 25 lines · Nicolas Pitre
Quoted 12 lines · Haojian Zhuang
Quoted 11 lines · Nicolas Pitre
Sorry for the delay -- I was on vacation.
Quoted 6 lines · Haojian Zhuang
Multiple CPU clusters are used in Hisilicon HiP04 SoC. Now use MCPM framework to manage power on HiP04 SoC.
Changelog:
v16:
* Parse bootwrapper parameters in command line instead.Quoted 7 lines
Quoted 5 lines
What is that about? I don't particularly like to see bootloader handshake details passed to the kernel via the kernel command line mechanism. Given this looks like special memory regions, can't they be specified via the device tree instead?
Others don't agree put them into DTS file. So I move them into command line.
Could you give me a pointer to the discussion around that please?
Quoted 6 lines
Quoted 1 line
Nicolas
http://lists.infradead.org/pipermail/linux-arm-kernel/2014-July/275944.html
Mark challenged what's relationship between bootwrapper address and system controller.
There is no relation, obviously. Hence this doesn't belong in the system controller node. That doesn't mean it should not be in DT at all.
Quoted 3 lines
Actually code in bootwrapper is like trampoline. And it's a software protocol, not hardware description. So I moved them into command line instead.
There are many examples for software protocols being specified in DT already. The first that comes to my mind is the "boot method = spin table" which has nothing to do with hardware. PSCI bindings are about another software-only thing.
Nicolas
PATCH v16 2/9 ARM: hisi: enable MCPM implementation
Quoted 43 lines · Nicolas Pitre
Quoted 26 lines · Haojian Zhuang
Quoted 25 lines · Nicolas Pitre
Quoted 12 lines · Haojian Zhuang
Quoted 11 lines · Nicolas Pitre
Sorry for the delay -- I was on vacation.
Quoted 6 lines · Haojian Zhuang
Multiple CPU clusters are used in Hisilicon HiP04 SoC. Now use MCPM framework to manage power on HiP04 SoC.
Changelog:
v16:
* Parse bootwrapper parameters in command line instead.Quoted 7 lines
Quoted 5 lines
What is that about? I don't particularly like to see bootloader handshake details passed to the kernel via the kernel command line mechanism. Given this looks like special memory regions, can't they be specified via the device tree instead?
Others don't agree put them into DTS file. So I move them into command line.
Could you give me a pointer to the discussion around that please?
Quoted 6 lines
Quoted 1 line
Nicolas
http://lists.infradead.org/pipermail/linux-arm-kernel/2014-July/275944.html
Mark challenged what's relationship between bootwrapper address and system controller.
There is no relation, obviously. Hence this doesn't belong in the system controller node. That doesn't mean it should not be in DT at all.
Quoted 3 lines
Actually code in bootwrapper is like trampoline. And it's a software protocol, not hardware description. So I moved them into command line instead.
Quoted 7 lines
There are many examples for software protocols being specified in DT already. The first that comes to my mind is the "boot method = spin table" which has nothing to do with hardware. PSCI bindings are about another software-only thing.
Nicolas
bootwrapper {
compatible = "hisilicon,hip04-bootwrapper";
boot-method = <0x10c00000, 0x10000, 0xa5a5a5a5, 0xe0000100, 0x1000>;
};I changed them into this format. Could you help to review?
Regards
Haojian
PATCH v16 2/9 ARM: hisi: enable MCPM implementation
Quoted 50 lines · Haojian Zhuang
Quoted 49 lines · Nicolas Pitre
Quoted 26 lines · Haojian Zhuang
Quoted 25 lines · Nicolas Pitre
Quoted 12 lines · Haojian Zhuang
Quoted 11 lines · Nicolas Pitre
Sorry for the delay -- I was on vacation.
Quoted 6 lines · Haojian Zhuang
Multiple CPU clusters are used in Hisilicon HiP04 SoC. Now use MCPM framework to manage power on HiP04 SoC.
Changelog:
v16:
* Parse bootwrapper parameters in command line instead.Quoted 7 lines
Quoted 5 lines
What is that about? I don't particularly like to see bootloader handshake details passed to the kernel via the kernel command line mechanism. Given this looks like special memory regions, can't they be specified via the device tree instead?
Others don't agree put them into DTS file. So I move them into command line.
Could you give me a pointer to the discussion around that please?
Quoted 6 lines
Quoted 1 line
Nicolas
http://lists.infradead.org/pipermail/linux-arm-kernel/2014-July/275944.html
Mark challenged what's relationship between bootwrapper address and system controller.
There is no relation, obviously. Hence this doesn't belong in the system controller node. That doesn't mean it should not be in DT at all.
Quoted 3 lines
Actually code in bootwrapper is like trampoline. And it's a software protocol, not hardware description. So I moved them into command line instead.
There are many examples for software protocols being specified in DT already. The first that comes to my mind is the "boot method = spin table" which has nothing to do with hardware. PSCI bindings are about another software-only thing.
Quoted 8 lines
Quoted 1 line
Nicolas
bootwrapper { compatible = "hisilicon,hip04-bootwrapper"; boot-method = <0x10c00000, 0x10000, 0xa5a5a5a5, 0xe0000100, 0x1000>; };I changed them into this format. Could you help to review?
Unfortunately I'm not really knowledgeable about best device tree syntax and practices. You'll have to nag someone else for reviewing this.
One thing though, do you really need to put some magic number there? Is it likely to change? If not this could be hardcoded in the code and only describe the special memory region in DT.
Nicolas
PATCH v16 2/9 ARM: hisi: enable MCPM implementation
Quoted 64 lines · Nicolas Pitre
Quoted 50 lines · Haojian Zhuang
Quoted 49 lines · Nicolas Pitre
Quoted 26 lines · Haojian Zhuang
Quoted 25 lines · Nicolas Pitre
Quoted 12 lines · Haojian Zhuang
Quoted 11 lines · Nicolas Pitre
Sorry for the delay -- I was on vacation.
Quoted 6 lines · Haojian Zhuang
Multiple CPU clusters are used in Hisilicon HiP04 SoC. Now use MCPM framework to manage power on HiP04 SoC.
Changelog:
v16:
* Parse bootwrapper parameters in command line instead.Quoted 7 lines
Quoted 5 lines
What is that about? I don't particularly like to see bootloader handshake details passed to the kernel via the kernel command line mechanism. Given this looks like special memory regions, can't they be specified via the device tree instead?
Others don't agree put them into DTS file. So I move them into command line.
Could you give me a pointer to the discussion around that please?
Quoted 6 lines
Quoted 1 line
Nicolas
http://lists.infradead.org/pipermail/linux-arm-kernel/2014-July/275944.html
Mark challenged what's relationship between bootwrapper address and system controller.
There is no relation, obviously. Hence this doesn't belong in the system controller node. That doesn't mean it should not be in DT at all.
Quoted 3 lines
Actually code in bootwrapper is like trampoline. And it's a software protocol, not hardware description. So I moved them into command line instead.
There are many examples for software protocols being specified in DT already. The first that comes to my mind is the "boot method = spin table" which has nothing to do with hardware. PSCI bindings are about another software-only thing.
Quoted 8 lines
Quoted 1 line
Nicolas
bootwrapper { compatible = "hisilicon,hip04-bootwrapper"; boot-method = <0x10c00000, 0x10000, 0xa5a5a5a5, 0xe0000100, 0x1000>; };I changed them into this format. Could you help to review?
Unfortunately I'm not really knowledgeable about best device tree syntax and practices. You'll have to nag someone else for reviewing this.
Quoted 6 lines
One thing though, do you really need to put some magic number there? Is it likely to change? If not this could be hardcoded in the code and only describe the special memory region in DT.
Nicolas
Sure. I can define the magic number as hardcode.
Regards
Haojian
PATCH v16 3/9 ARM: hisi: enable HiP04
In reply to Haojian ZhuangSupport HiP04 SoC what supports 16 cores. And it relies on MCPM framework.
--- arch/arm/mach-hisi/Kconfig | 9 +++++++++ arch/arm/mach-hisi/hisilicon.c | 9 +++++++++ 2 files changed, 18 insertions(+)
arch/arm/mach-hisi/Kconfig +9 -0
@@ -22,6 +22,15 @@ config ARCH_HI3xxx help Support for Hisilicon Hi36xx SoC family +config ARCH_HIP04 + bool "Hisilicon HiP04 Cortex A15 family" if ARCH_MULTI_V7 + select ARM_ERRATA_798181 if SMP + select HAVE_ARM_ARCH_TIMER + select MCPM if SMP + select MCPM_QUAD_CLUSTER if SMP + help + Support for Hisilicon HiP04 SoC family + config ARCH_HIX5HD2 bool "Hisilicon X5HD2 family" if ARCH_MULTI_V7 select CACHE_L2X0
arch/arm/mach-hisi/hisilicon.c +9 -0
@@ -65,3 +65,12 @@ static const char *hix5hd2_compat[] __initconst = {DT_MACHINE_START (HIX5HD2_DT ,"Hisilicon HIX5HD2 (Flattened Device Tree)" ) .dt_compat = hix5hd2_compat, MACHINE_END + +static const char *hip04_compat[]__initconst = { +"hisilicon,hip04-d01" , +NULL , +}; + +DT_MACHINE_START (HIP04 ,"Hisilicon HiP04 (Flattened Device Tree)" ) + .dt_compat = hip04_compat, +MACHINE_END
Signature · 1 line
1.9.1
PATCH v16 4/9 document: dt: add the binding on HiP04
In reply to Haojian ZhuangAdd Hisilicon HiP04 SoC platform & Fabric controller.
Fabric controller could be used to configure snoop filter among multiple clusters.
--- .../devicetree/bindings/arm/hisilicon/hisilicon.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+)
Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt +12 -0
@@ -5,6 +5,11 @@ Hi4511 Board Required root node properties: - compatible = "hisilicon,hi3620-hi4511"; +HiP04 D01 Board +Required root node properties: + - compatible = "hisilicon,hip04-d01"; + + Hisilicon system controller Required properties:
@@ -55,3 +60,10 @@ Example: compatible = "hisilicon,pctrl"; reg = <0xfca09000 0x1000>; }; + +----------------------------------------------------------------------- +Fabric: + +Required Properties: +- compatible: "hisilicon,hip04-fabric"; +- reg: Address and size of Fabric
Signature · 1 line
1.9.1
PATCH v16 5/9 ARM: dts: add hip04 dts
In reply to Haojian ZhuangAdd hip04-d01.dts & hip04.dtsi for hip04 SoC platform.
--- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/hip04-d01.dts | 32 +++++ arch/arm/boot/dts/hip04.dtsi | 262 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 295 insertions(+) create mode 100644 arch/arm/boot/dts/hip04-d01.dts create mode 100644 arch/arm/boot/dts/hip04.dtsi
arch/arm/boot/dts/Makefile +1 -0
@@ -86,6 +86,7 @@ dtb-$(CONFIG_ARCH_HI3xxx) += hi3620-hi4511.dtb dtb-$(CONFIG_ARCH_HIX5HD2) += hix5hd2-dkb.dtb dtb-$(CONFIG_ARCH_HIGHBANK) += highbank.dtb \ ecx-2000.dtb +dtb-$(CONFIG_ARCH_HIP04) += hip04-d01.dtb dtb-$(CONFIG_ARCH_INTEGRATOR) += integratorap.dtb \ integratorcp.dtb dtb-$(CONFIG_ARCH_KEYSTONE) += k2hk-evm.dtb \
arch/arm/boot/dts/hip04-d01.dts new file +32 -0
@@ -0,0 +1,32 @@ +/* + * Copyright (C) 2013-2014 Linaro Ltd. + * Author: Haojian Zhuang <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * publishhed by the Free Software Foundation. + */ + +/dts-v1/; + +#include "hip04.dtsi" + +/ { + /* memory bus is 64-bit */ + #address-cells = <2>; + #size-cells = <2>; + model = "Hisilicon D01 Development Board"; + compatible = "hisilicon,hip04-d01"; + + memory at 00000000,10000000 { + device_type = "memory"; + reg = <0x00000000 0x10000000 0x00000000 0xc0000000>, + <0x00000004 0xc0000000 0x00000003 0x40000000>; + }; + + soc { + uart0: uart at 4007000 { + status = "ok"; + }; + }; +};
arch/arm/boot/dts/hip04.dtsi new file +262 -0
262 lines not on this page · raw message
Signature · 1 line
1.9.1
PATCH v16 6/9 ARM: config: enable hisilicon hip04
In reply to Haojian ZhuangEnable CONFIG_ARCH_HIP04 in both hi3xxx_defconfig & multi_v7_defconfig.
Since CONFIG_ARM_LPAE is disabled by default, only 3GB memory could be support by this defconfig. User should enable CONFIG_ARM_LPAE locally to support 16GB memory on hip04 platform.
Since hip04 doesn't belong to hi3xxx series, rename hi3xxx_defconfig to hisi_defconfig.
--- arch/arm/configs/hi3xxx_defconfig | 58 ------------------------------ arch/arm/configs/hisi_defconfig | 72 +++++++++++++++++++++++++++++++++++++ arch/arm/configs/multi_v7_defconfig | 2 ++ 3 files changed, 74 insertions(+), 58 deletions(-) delete mode 100644 arch/arm/configs/hi3xxx_defconfig create mode 100644 arch/arm/configs/hisi_defconfig
arch/arm/configs/hi3xxx_defconfig deleted +0 -58
@@ -1,58 +0,0 @@ -CONFIG_IRQ_DOMAIN_DEBUG=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_BLK_DEV_INITRD=y -CONFIG_RD_LZMA=y -CONFIG_ARCH_HISI=y -CONFIG_ARCH_HI3xxx=y -CONFIG_ARCH_HIX5HD2=y -CONFIG_SMP=y -CONFIG_PREEMPT=y -CONFIG_AEABI=y -CONFIG_ARM_APPENDED_DTB=y -CONFIG_NET=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_DEVTMPFS=y -CONFIG_DEVTMPFS_MOUNT=y -CONFIG_BLK_DEV_SD=y -CONFIG_ATA=y -CONFIG_SATA_AHCI_PLATFORM=y -CONFIG_NETDEVICES=y -CONFIG_SERIAL_AMBA_PL011=y -CONFIG_SERIAL_AMBA_PL011_CONSOLE=y -CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_I2C_DESIGNWARE_PLATFORM=y -CONFIG_SPI=y -CONFIG_SPI_PL022=y -CONFIG_PINCTRL_SINGLE=y -CONFIG_GPIO_GENERIC_PLATFORM=y -CONFIG_REGULATOR_GPIO=y -CONFIG_DRM=y -CONFIG_FB_SIMPLE=y -CONFIG_USB=y -CONFIG_USB_XHCI_HCD=y -CONFIG_USB_EHCI_HCD=y -CONFIG_USB_EHCI_MXC=y -CONFIG_USB_EHCI_HCD_PLATFORM=y -CONFIG_USB_STORAGE=y -CONFIG_NOP_USB_XCEIV=y -CONFIG_MMC=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_PL031=y -CONFIG_DMADEVICES=y -CONFIG_DW_DMAC=y -CONFIG_PL330_DMA=y -CONFIG_PWM=y -CONFIG_EXT4_FS=y -CONFIG_TMPFS=y -CONFIG_NFS_FS=y -CONFIG_NFS_V3_ACL=y -CONFIG_NFS_V4=y -CONFIG_ROOT_NFS=y -CONFIG_PRINTK_TIME=y -CONFIG_DEBUG_FS=y -CONFIG_DEBUG_KERNEL=y -CONFIG_LOCKUP_DETECTOR=y
arch/arm/configs/hisi_defconfig new file +72 -0
72 lines not on this page · raw message
arch/arm/configs/multi_v7_defconfig +2 -0
@@ -24,8 +24,10 @@ CONFIG_MACH_BERLIN_BG2=y CONFIG_MACH_BERLIN_BG2CD=y CONFIG_MACH_BERLIN_BG2Q=y CONFIG_ARCH_HIGHBANK=y +CONFIG_ARCH_HISI=y CONFIG_ARCH_HI3xxx=y CONFIG_ARCH_HIX5HD2=y +CONFIG_ARCH_HIP04=y CONFIG_ARCH_KEYSTONE=y CONFIG_ARCH_MXC=y CONFIG_MACH_IMX51_DT=y
Signature · 1 line
1.9.1
PATCH v16 7/9 ARM: debug: add HiP04 debug uart
In reply to Haojian ZhuangAdd the support of Hisilicon HiP04 debug uart.
--- arch/arm/Kconfig.debug | 10 ++++++++++ 1 file changed, 10 insertions(+)
arch/arm/Kconfig.debug +10 -0
@@ -231,6 +231,14 @@ choice Say Y here if you want kernel low-level debugging support on Hix5hd2 UART. + config DEBUG_HIP04_UART + bool "Hisilicon HiP04 Debug UART" + depends on ARCH_HIP04 + select DEBUG_UART_8250 + help + Say Y here if you want kernel low-level debugging support + on HIP04 UART. + config DEBUG_HIGHBANK_UART bool "Kernel low-level debugging messages via Highbank UART" depends on ARCH_HIGHBANK
@@ -1095,6 +1103,7 @@ config DEBUG_UART_PHYS default 0xd4017000 if DEBUG_MMP_UART2 default 0xd4018000 if DEBUG_MMP_UART3 default 0xe0000000 if ARCH_SPEAR13XX + default 0xe4007000 if DEBUG_HIP04_UART default 0xf0000be0 if ARCH_EBSA110 default 0xf1012000 if DEBUG_MVEBU_UART_ALTERNATE default 0xf1012000 if ARCH_DOVE || ARCH_KIRKWOOD || ARCH_MV78XX0 || \
@@ -1136,6 +1145,7 @@ config DEBUG_UART_VIRT default 0xf7008000 if DEBUG_S3C24XX_UART && (DEBUG_S3C_UART2 || \ DEBUG_S3C2410_UART2) default 0xf7fc9000 if DEBUG_BERLIN_UART + default 0xf8007000 if DEBUG_HIP04_UART default 0xf8009000 if DEBUG_VEXPRESS_UART0_CA9 default 0xf8090000 if DEBUG_VEXPRESS_UART0_RS1 default 0xfa71e000 if DEBUG_QCOM_UARTDM
Signature · 1 line
1.9.1
PATCH v16 8/9 irq: enable hip04 irq chip
In reply to Haojian ZhuangHiP04 GIC is the variate of ARM GICv2.
ARM GICv2 supports 8 cores. HiP04 GIC extends to support 16 cores. It results that bit fields in GIC_DIST_TARGET & GIC_DIST_SOFTINT are different from ARM GICv2. And the maximium IRQ is downgrade from 1020 to 510.
Since different register offset & bitfields definitation breaks compartible with ARM GICv2, create a new hip04 irq driver.
--- drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-hip04.c | 429 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 430 insertions(+) create mode 100644 drivers/irqchip/irq-hip04.c
drivers/irqchip/Makefile +1 -0
@@ -2,6 +2,7 @@ obj-$(CONFIG_IRQCHIP) += irqchip.o obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o obj-$(CONFIG_ARCH_EXYNOS) += exynos-combiner.o +obj-$(CONFIG_ARCH_HIP04) += irq-hip04.o obj-$(CONFIG_ARCH_MMP) += irq-mmp.o obj-$(CONFIG_ARCH_MVEBU) += irq-armada-370-xp.o obj-$(CONFIG_ARCH_MXS) += irq-mxs.o
drivers/irqchip/irq-hip04.c new file +429 -0
429 lines not on this page · raw message
Signature · 1 line
1.9.1
PATCH v16 8/9 irq: enable hip04 irq chip
Hi,
to me this looks much better than the version integrated into irq-gic.c and is reasonably small and self-contained.
See for comments below...
Quoted 50 lines · Haojian Zhuang
HiP04 GIC is the variate of ARM GICv2.
ARM GICv2 supports 8 cores. HiP04 GIC extends to support 16 cores. It results that bit fields in
GIC_DIST_TARGET&GIC_DIST_SOFTINTare different from ARM GICv2. And the maximium IRQ is downgrade from 1020 to 510.Since different register offset & bitfields definitation breaks compartible with ARM GICv2, create a new hip04 irq driver.
Signed-off-by Haojian Zhuang <[email protected]>--- drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-hip04.c | 429 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 430 insertions(+) create mode 100644 drivers/irqchip/irq-hip04.cdrivers/irqchip/Makefile +1
-0@@ -2,6 +2,7 @@ obj-$(CONFIG_IRQCHIP) += irqchip.o obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o obj-$(CONFIG_ARCH_EXYNOS) += exynos-combiner.o +obj-$(CONFIG_ARCH_HIP04) += irq-hip04.o obj-$(CONFIG_ARCH_MMP) += irq-mmp.o obj-$(CONFIG_ARCH_MVEBU) += irq-armada-370-xp.o obj-$(CONFIG_ARCH_MXS) += irq-mxs.odrivers/irqchip/irq-hip04.c new file +16
-0@@ -0,0 +1,429 @@ +/* +* Hisilicon HiP04 INTC +* +* Copyright (C) 2002-2014 ARM Limited. +* Copyright (c) 2013-2014 Hisilicon Ltd. +* Copyright (c) 2013-2014 Linaro Ltd. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* Interrupt architecture for the HIP04 INTC: +* +* o There is one Interrupt Distributor, which receives interrupts +* from system devices and sends them to the Interrupt Controllers. +*
drivers/irqchip/irq-hip04.c line 26
Quoted 10 lines
drivers/irqchip/irq-hip04.c new file +10
-0+* o There is one CPU Interface per CPU, which sends interrupts sent +* by the Distributor, and interrupts generated locally, to the +* associated CPU. The base address of the CPU interface is usually +* aliased so that the same address points to different chips depending +* on the CPU it is accessed from. +* +* Note that IRQs 0-31 are special - they are local to each CPU. +* As such, the enable set/clear, pending set/clear and active bit +* registers are banked per-cpu for these sources. +*/
I'd find it more useful to have a reference to the GIC code here and only list the delta of the two drivers.
Since you removed (almost) any references to GIC, to an uninitiated reader it's not obvious that this is in fact a stripped and tweaked GIC.
So you could copy some of the rationale from the commit message into here, something along the lines of:
---------
This is derived from irq-gic.c to support the HiSilicon HiP04 interrupt controller, which is similar to the GIC, but deviates at some points. Support for power management, non-banked registers, cascaded GICs (and multiple controllers in general) and bigLittle support has been removed from the GIC driver.
Affinity related functions have been adjusted to match the HiSilicon hardware implementation.
---------
By the way, you removed CONFIG_CPU_PM support, is there any reason for that? I don't see an issue code-wise with keeping this in.
[...]
drivers/irqchip/irq-hip04.c line 276
Quoted 5 lines
drivers/irqchip/irq-hip04.c new file +5
-0+ +void hip04_cpu_if_down (void ) +{ +writel_relaxed (0 , hip04_data.cpu_base +GIC_CPU_CTRL ); +}
Where is this used? The GIC counterpart is only called by some VExpress code, does your platform need a similar call? Otherwise (and since you don't seem to provide a public prototype) this function can be removed.
drivers/irqchip/irq-hip04.c line 288
Quoted 12 lines
drivers/irqchip/irq-hip04.c new file +12
-0+ +#ifdef CONFIG_SMP +static void hip04_raise_softirq (const struct cpumask *mask,unsigned int irq) +{ +int cpu; +unsigned long flags, map =0 ; + +raw_spin_lock_irqsave (&irq_controller_lock, flags); + +/* Convert our logical CPU mask into a physical one. */ +for_each_cpu (cpu, mask) + map |= hip04_cpu_map[cpu];
Are we sure that mask does not contain any CPU number higher than NR_HIP04_CPU_IF?
Regards,
Andre.
Quoted 142 lines
drivers/irqchip/irq-hip04.c new file +141
-0+ +/* +* Ensure that stores to Normal memory are visible to the +* other CPUs before they observe us issuing the IPI. +*/ +dmb (ishst); + +/* this always happens on GIC0 */ +writel_relaxed (map <<8 | irq, hip04_data.dist_base +GIC_DIST_SOFTINT ); + +raw_spin_unlock_irqrestore (&irq_controller_lock, flags); +} +#endif + +static int hip04_irq_domain_map (struct irq_domain *d,unsigned int irq, +irq_hw_number_t hw) +{ +if (hw <32 ) { +irq_set_percpu_devid (irq); +irq_set_chip_and_handler (irq, &hip04_irq_chip, + handle_percpu_devid_irq); +set_irq_flags (irq,IRQF_VALID |IRQF_NOAUTOEN ); + }else { +irq_set_chip_and_handler (irq, &hip04_irq_chip, + handle_fasteoi_irq); +set_irq_flags (irq,IRQF_VALID |IRQF_PROBE ); + } +irq_set_chip_data (irq, d->host_data); +return 0 ; +} + +static int hip04_irq_domain_xlate (struct irq_domain *d, +struct device_node *controller, +const u32 *intspec,unsigned int intsize, +unsigned long *out_hwirq, +unsigned int *out_type) +{ +unsigned long ret =0 ; + +if (d->of_node != controller) +return -EINVAL ; +if (intsize <3 ) +return -EINVAL ; + +/* Get the interrupt number and add 16 to skip over SGIs */ + *out_hwirq = intspec[1 ] +16 ; + +/* For SPIs, we need to add 16 more to get the irq ID number */ +if (!intspec[0 ]) + *out_hwirq +=16 ; + + *out_type = intspec[2 ] &IRQ_TYPE_SENSE_MASK ; + +return ret; +} + +#ifdef CONFIG_SMP +static int hip04_irq_secondary_init (struct notifier_block *nfb, +unsigned long action, +void *hcpu) +{ +if (action ==CPU_STARTING || action ==CPU_STARTING_FROZEN ) +hip04_irq_cpu_init (&hip04_data); +return NOTIFY_OK ; +} + +/* +* Notifier for enabling the INTC CPU interface. Set an arbitrarily high +* priority because the GIC needs to be up before the ARM generic timers. +*/ +static struct notifier_block hip04_irq_cpu_notifier = { + .notifier_call = hip04_irq_secondary_init, + .priority =100 , +}; +#endif + +static const struct irq_domain_ops hip04_irq_domain_ops = { + .map = hip04_irq_domain_map, + .xlate = hip04_irq_domain_xlate, +}; + +static int __init +hip04_of_init (struct device_node *node,struct device_node *parent) +{ +irq_hw_number_t hwirq_base =16 ; +int nr_irqs, irq_base, i; + +if (WARN_ON (!node)) +return -ENODEV ; + + hip04_data.dist_base =of_iomap (node,0 ); +WARN (!hip04_data.dist_base,"fail to map hip04 intc dist registers\n" ); + + hip04_data.cpu_base =of_iomap (node,1 ); +WARN (!hip04_data.cpu_base,"unable to map hip04 intc cpu registers\n" ); + +/* +* Initialize the CPU interface map to all CPUs. +* It will be refined as each CPU probes its ID. +*/ +for (i =0 ; i <NR_HIP04_CPU_IF ; i++) + hip04_cpu_map[i] =0xff ; + +/* +* Find out how many interrupts are supported. +* The HIP04 INTC only supports up to 510 interrupt sources. +*/ + nr_irqs =readl_relaxed (hip04_data.dist_base +GIC_DIST_CTR ) &0x1f ; + nr_irqs = (nr_irqs +1 ) *32 ; +if (nr_irqs >HIP04_MAX_IRQS ) + nr_irqs =HIP04_MAX_IRQS ; + hip04_data.nr_irqs = nr_irqs; + + nr_irqs -= hwirq_base;/* calculate # of irqs to allocate */ + + irq_base =irq_alloc_descs (-1 , hwirq_base, nr_irqs,numa_node_id ()); +if (IS_ERR_VALUE (irq_base)) { +pr_err ("failed to allocate IRQ numbers\n" ); +return -EINVAL ; + } + + hip04_data.domain =irq_domain_add_legacy (node, nr_irqs, irq_base, + hwirq_base, + &hip04_irq_domain_ops, + &hip04_data); + +if (WARN_ON (!hip04_data.domain)) +return -EINVAL ; + +#ifdef CONFIG_SMP +set_smp_cross_call (hip04_raise_softirq); +register_cpu_notifier (&hip04_irq_cpu_notifier); +#endif +set_handle_irq (hip04_handle_irq); + +hip04_irq_dist_init (&hip04_data); +hip04_irq_cpu_init (&hip04_data); + +return 0 ; +} +IRQCHIP_DECLARE (hip04_intc,"hisilicon,hip04-intc" , hip04_of_init);
PATCH v16 8/9 irq: enable hip04 irq chip
Quoted 86 lines · Andre Przywara
Hi,
to me this looks much better than the version integrated into
irq-gic.cand is reasonably small and self-contained.See for comments below...
Quoted 50 lines · Haojian Zhuang
HiP04 GIC is the variate of ARM GICv2.
ARM GICv2 supports 8 cores. HiP04 GIC extends to support 16 cores. It results that bit fields in
GIC_DIST_TARGET&GIC_DIST_SOFTINTare different from ARM GICv2. And the maximium IRQ is downgrade from 1020 to 510.Since different register offset & bitfields definitation breaks compartible with ARM GICv2, create a new hip04 irq driver.
Signed-off-by Haojian Zhuang <[email protected]>--- drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-hip04.c | 429 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 430 insertions(+) create mode 100644 drivers/irqchip/irq-hip04.cdrivers/irqchip/Makefile +1
-0@@ -2,6 +2,7 @@ obj-$(CONFIG_IRQCHIP) += irqchip.o obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o obj-$(CONFIG_ARCH_EXYNOS) += exynos-combiner.o +obj-$(CONFIG_ARCH_HIP04) += irq-hip04.o obj-$(CONFIG_ARCH_MMP) += irq-mmp.o obj-$(CONFIG_ARCH_MVEBU) += irq-armada-370-xp.o obj-$(CONFIG_ARCH_MXS) += irq-mxs.odrivers/irqchip/irq-hip04.c new file +16
-0@@ -0,0 +1,429 @@ +/* +* Hisilicon HiP04 INTC +* +* Copyright (C) 2002-2014 ARM Limited. +* Copyright (c) 2013-2014 Hisilicon Ltd. +* Copyright (c) 2013-2014 Linaro Ltd. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* Interrupt architecture for the HIP04 INTC: +* +* o There is one Interrupt Distributor, which receives interrupts +* from system devices and sends them to the Interrupt Controllers. +* drivers/irqchip/irq-hip04.c line 26
Quoted 10 lines
drivers/irqchip/irq-hip04.c new file +10
-0+* o There is one CPU Interface per CPU, which sends interrupts sent +* by the Distributor, and interrupts generated locally, to the +* associated CPU. The base address of the CPU interface is usually +* aliased so that the same address points to different chips depending +* on the CPU it is accessed from. +* +* Note that IRQs 0-31 are special - they are local to each CPU. +* As such, the enable set/clear, pending set/clear and active bit +* registers are banked per-cpu for these sources. +*/ I'd find it more useful to have a reference to the GIC code here and only list the delta of the two drivers.
Since you removed (almost) any references to GIC, to an uninitiated reader it's not obvious that this is in fact a stripped and tweaked GIC.So you could copy some of the rationale from the commit message into here, something along the lines of:
---------
This is derived fromirq-gic.cto support the HiSilicon HiP04 interrupt controller, which is similar to the GIC, but deviates at some points. Support for power management, non-banked registers, cascaded GICs (and multiple controllers in general) and bigLittle support has been removed from the GIC driver.
Affinity related functions have been adjusted to match the HiSilicon hardware implementation.
---------
Quoted 3 lines
By the way, you removed
CONFIG_CPU_PMsupport, is there any reason for that? I don't see an issue code-wise with keeping this in.
Since we didn't enable power management on HiP04 yet, I removed them. If we enable power management later, I could append them again.
Quoted 11 lines
drivers/irqchip/irq-hip04.c line 276
Quoted 6 lines
drivers/irqchip/irq-hip04.c new file +5
-0+ +void hip04_cpu_if_down (void ) +{ +writel_relaxed (0 , hip04_data.cpu_base +GIC_CPU_CTRL ); +}Where is this used? The GIC counterpart is only called by some VExpress code, does your platform need a similar call? Otherwise (and since you don't seem to provide a public prototype) this function can be removed.
I should remove it. It doesn't help me.
Quoted 17 lines
drivers/irqchip/irq-hip04.c line 288
Quoted 13 lines
drivers/irqchip/irq-hip04.c new file +12
-0+ +#ifdef CONFIG_SMP +static void hip04_raise_softirq (const struct cpumask *mask,unsigned int irq) +{ +int cpu; +unsigned long flags, map =0 ; + +raw_spin_lock_irqsave (&irq_controller_lock, flags); + +/* Convert our logical CPU mask into a physical one. */ +for_each_cpu (cpu, mask) + map |= hip04_cpu_map[cpu];Are we sure that mask does not contain any CPU number higher than
NR_HIP04_CPU_IF?
Yes, the maximum CPU number is 16. We shouldn't configure higher CPU numbers in HiP04.
Regards
Haojian
PATCH v16 9/9 of: fdt: fix memory address be truncated
In reply to Haojian Zhuangearly_init_dt_add_memory_arch() accepts base & size parameters as u64 type. memblock_add() accepts base & size parameters as phys_addr_t type. But phys_addr_t isn't equal to u64. In 32-bit system, phys_addr_t is 32-bit long. If 64-bit memory address is specified in DTS file, it'll be truncated into 32-bit address.
So create two values to store base & size first as phys_addr_t type. Then compare them with u64 base & u64 size. If they don't match, discard them.
--- drivers/of/fdt.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
drivers/of/fdt.c +10 -0
@@ -878,6 +878,8 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,void __init __weak early_init_dt_add_memory_arch (u64 base,u64 size) {const u64 phys_offset =__pa (PAGE_OFFSET ); +phys_addr_t mbase, msize; + base &=PAGE_MASK ; size &=PAGE_MASK ;if (base + size < phys_offset) {
@@ -885,6 +887,14 @@ void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size) base, base + size);return ; } +/* phys_addr_t may not be equal to u64 */ + mbase = base; + msize = size; +if ((mbase != base) || (msize != size)) { +pr_warning ("Ignoring memory block 0x%llx - 0x%llx\n" , + base, base + size); +return ; + }if (base < phys_offset) {pr_warning ("Ignoring memory range 0x%llx - 0x%llx\n" , base, phys_offset);
Signature · 1 line
1.9.1
PATCH v16 9/9 of: fdt: fix memory address be truncated
Quoted 29 lines · Haojian Zhuang
early_init_dt_add_memory_arch()accepts base & size parameters as u64 type.memblock_add()accepts base & size parameters asphys_addr_ttype. Butphys_addr_tisn't equal to u64. In 32-bit system,phys_addr_tis 32-bit long. If 64-bit memory address is specified in DTS file, it'll be truncated into 32-bit address.So create two values to store base & size first as
phys_addr_ttype. Then compare them with u64 base & u64 size. If they don't match, discard them.Signed-off-by Haojian Zhuang <[email protected]>--- drivers/of/fdt.c | 10 ++++++++++ 1 file changed, 10 insertions(+)drivers/of/fdt.c +2
-0@@ -878,6 +878,8 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,void __init __weak early_init_dt_add_memory_arch (u64 base,u64 size) {const u64 phys_offset =__pa (PAGE_OFFSET ); +phys_addr_t mbase, msize; + base &=PAGE_MASK ; size &=PAGE_MASK ;if (base + size < phys_offset) {
drivers/of/fdt.c void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size) · line 896
Quoted 10 lines
drivers/of/fdt.c +7
-0@@ -885,6 +887,14 @@ void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size) base, base + size);return ; } +/* phys_addr_t may not be equal to u64 */ + mbase = base; + msize = size; +if ((mbase != base) || (msize != size)) { +pr_warning ("Ignoring memory block 0x%llx - 0x%llx\n" , + base, base + size); +return ;
Actually, you can do better than this -- you can still use the part that fits in 32 bits even if not all of it does.
-Olof