All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v16 0/9] enable HiP04 SoC
@ 2014-08-04  2:57 Haojian Zhuang
  2014-08-04  2:58 ` [PATCH v16 1/9] ARM: mcpm: support 4 clusters Haojian Zhuang
                   ` (8 more replies)
  0 siblings, 9 replies; 21+ messages in thread
From: Haojian Zhuang @ 2014-08-04  2:57 UTC (permalink / raw)
  To: linux-arm-kernel

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

-- 
1.9.1

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v16 1/9] ARM: mcpm: support 4 clusters
  2014-08-04  2:57 [PATCH v16 0/9] enable HiP04 SoC Haojian Zhuang
@ 2014-08-04  2:58 ` Haojian Zhuang
  2014-08-04  2:58 ` [PATCH v16 2/9] ARM: hisi: enable MCPM implementation Haojian Zhuang
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 21+ messages in thread
From: Haojian Zhuang @ 2014-08-04  2:58 UTC (permalink / raw)
  To: linux-arm-kernel

Add the CONFIG_MCPM_QUAD_CLUSTER configuration to enlarge cluster number
from 2 to 4.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
Reviewed-by: Nicolas Pitre <nico@linaro.org>
---
 arch/arm/Kconfig            | 9 +++++++++
 arch/arm/include/asm/mcpm.h | 5 +++++
 2 files changed, 14 insertions(+)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 87b63fd..10cc6ec 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -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
diff --git a/arch/arm/include/asm/mcpm.h b/arch/arm/include/asm/mcpm.h
index d9702eb..a4fbacc 100644
--- a/arch/arm/include/asm/mcpm.h
+++ b/arch/arm/include/asm/mcpm.h
@@ -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__
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v16 2/9] ARM: hisi: enable MCPM implementation
  2014-08-04  2:57 [PATCH v16 0/9] enable HiP04 SoC Haojian Zhuang
  2014-08-04  2:58 ` [PATCH v16 1/9] ARM: mcpm: support 4 clusters Haojian Zhuang
@ 2014-08-04  2:58 ` Haojian Zhuang
  2014-08-04 22:43   ` Nicolas Pitre
  2014-08-04  2:58 ` [PATCH v16 3/9] ARM: hisi: enable HiP04 Haojian Zhuang
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 21+ messages in thread
From: Haojian Zhuang @ 2014-08-04  2:58 UTC (permalink / raw)
  To: linux-arm-kernel

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.
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.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 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

diff --git a/arch/arm/mach-hisi/Makefile b/arch/arm/mach-hisi/Makefile
index ee2506b..d64831e 100644
--- a/arch/arm/mach-hisi/Makefile
+++ b/arch/arm/mach-hisi/Makefile
@@ -3,4 +3,5 @@
 #
 
 obj-y	+= hisilicon.o
+obj-$(CONFIG_MCPM)		+= platmcpm.o
 obj-$(CONFIG_SMP)		+= platsmp.o hotplug.o headsmp.o
diff --git a/arch/arm/mach-hisi/platmcpm.c b/arch/arm/mach-hisi/platmcpm.c
new file mode 100644
index 0000000..fc17973
--- /dev/null
+++ b/arch/arm/mach-hisi/platmcpm.c
@@ -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;
+	}
+	hip04_boot.bootwrapper_phys = data[1];
+	hip04_boot.bootwrapper_size = data[2];
+	hip04_boot.bootwrapper_magic = data[3];
+	memblock_reserve(data[1], data[2]);
+	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];
+	return 0;
+}
+early_param("relocation", hip04_parse_relocation);
+
+static bool hip04_cluster_down(unsigned int cluster)
+{
+	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);
+	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 {
+			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);
+		BUG();
+	}
+	spin_unlock(&boot_lock);
+
+	v7_exit_coherency_flush(louis);
+
+	__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);
+
+	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);
+			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);
+			continue;
+		}
+	}
+	if (tries >= count)
+		goto err;
+	if (hip04_cluster_down(cluster))
+		hip04_set_snoop_filter(cluster, 0);
+	spin_unlock(&boot_lock);
+	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)
+{
+	asm volatile ("			\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;
+
+	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);
+	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) {
+		mcpm_sync_init(hip04_mcpm_power_up_setup);
+		pr_info("HiP04 MCPM initialized\n");
+	}
+	mcpm_smp_set_ops();
+	return ret;
+err_fabric:
+	iounmap(sysctrl);
+err_sysctrl:
+	iounmap(relocation);
+err:
+	return ret;
+}
+early_initcall(hip04_mcpm_init);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v16 3/9] ARM: hisi: enable HiP04
  2014-08-04  2:57 [PATCH v16 0/9] enable HiP04 SoC Haojian Zhuang
  2014-08-04  2:58 ` [PATCH v16 1/9] ARM: mcpm: support 4 clusters Haojian Zhuang
  2014-08-04  2:58 ` [PATCH v16 2/9] ARM: hisi: enable MCPM implementation Haojian Zhuang
@ 2014-08-04  2:58 ` Haojian Zhuang
  2014-08-04  2:58 ` [PATCH v16 4/9] document: dt: add the binding on HiP04 Haojian Zhuang
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 21+ messages in thread
From: Haojian Zhuang @ 2014-08-04  2:58 UTC (permalink / raw)
  To: linux-arm-kernel

Support HiP04 SoC what supports 16 cores. And it relies on MCPM
framework.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 arch/arm/mach-hisi/Kconfig     | 9 +++++++++
 arch/arm/mach-hisi/hisilicon.c | 9 +++++++++
 2 files changed, 18 insertions(+)

diff --git a/arch/arm/mach-hisi/Kconfig b/arch/arm/mach-hisi/Kconfig
index 9848829..075772b 100644
--- a/arch/arm/mach-hisi/Kconfig
+++ b/arch/arm/mach-hisi/Kconfig
@@ -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
diff --git a/arch/arm/mach-hisi/hisilicon.c b/arch/arm/mach-hisi/hisilicon.c
index f37fb65..5b8c11f 100644
--- a/arch/arm/mach-hisi/hisilicon.c
+++ b/arch/arm/mach-hisi/hisilicon.c
@@ -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
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v16 4/9] document: dt: add the binding on HiP04
  2014-08-04  2:57 [PATCH v16 0/9] enable HiP04 SoC Haojian Zhuang
                   ` (2 preceding siblings ...)
  2014-08-04  2:58 ` [PATCH v16 3/9] ARM: hisi: enable HiP04 Haojian Zhuang
@ 2014-08-04  2:58 ` Haojian Zhuang
  2014-08-04  2:58 ` [PATCH v16 5/9] ARM: dts: add hip04 dts Haojian Zhuang
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 21+ messages in thread
From: Haojian Zhuang @ 2014-08-04  2:58 UTC (permalink / raw)
  To: linux-arm-kernel

Add Hisilicon HiP04 SoC platform & Fabric controller.

Fabric controller could be used to configure snoop filter among multiple
clusters.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 .../devicetree/bindings/arm/hisilicon/hisilicon.txt          | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
index 934f000..fd8a759 100644
--- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
+++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
@@ -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
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v16 5/9] ARM: dts: add hip04 dts
  2014-08-04  2:57 [PATCH v16 0/9] enable HiP04 SoC Haojian Zhuang
                   ` (3 preceding siblings ...)
  2014-08-04  2:58 ` [PATCH v16 4/9] document: dt: add the binding on HiP04 Haojian Zhuang
@ 2014-08-04  2:58 ` Haojian Zhuang
  2014-08-04  2:58 ` [PATCH v16 6/9] ARM: config: enable hisilicon hip04 Haojian Zhuang
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 21+ messages in thread
From: Haojian Zhuang @ 2014-08-04  2:58 UTC (permalink / raw)
  To: linux-arm-kernel

Add hip04-d01.dts & hip04.dtsi for hip04 SoC platform.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 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

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 721525e..6587bbf 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -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 \
diff --git a/arch/arm/boot/dts/hip04-d01.dts b/arch/arm/boot/dts/hip04-d01.dts
new file mode 100644
index 0000000..40a9e33
--- /dev/null
+++ b/arch/arm/boot/dts/hip04-d01.dts
@@ -0,0 +1,32 @@
+/*
+ *  Copyright (C) 2013-2014 Linaro Ltd.
+ *  Author: Haojian Zhuang <haojian.zhuang@linaro.org>
+ *
+ *  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";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/hip04.dtsi b/arch/arm/boot/dts/hip04.dtsi
new file mode 100644
index 0000000..6602f66
--- /dev/null
+++ b/arch/arm/boot/dts/hip04.dtsi
@@ -0,0 +1,262 @@
+/*
+ * Hisilicon Ltd. HiP04 SoC
+ *
+ * Copyright (C) 2013-2014 Hisilicon Ltd.
+ * Copyright (C) 2013-2014 Linaro Ltd.
+ *
+ * Author: Haojian Zhuang <haojian.zhuang@linaro.org>
+ *
+ * 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.
+ */
+
+/ {
+	/* memory bus is 64-bit */
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu-map {
+			cluster0 {
+				core0 {
+					cpu = <&CPU0>;
+				};
+				core1 {
+					cpu = <&CPU1>;
+				};
+				core2 {
+					cpu = <&CPU2>;
+				};
+				core3 {
+					cpu = <&CPU3>;
+				};
+			};
+			cluster1 {
+				core0 {
+					cpu = <&CPU4>;
+				};
+				core1 {
+					cpu = <&CPU5>;
+				};
+				core2 {
+					cpu = <&CPU6>;
+				};
+				core3 {
+					cpu = <&CPU7>;
+				};
+			};
+			cluster2 {
+				core0 {
+					cpu = <&CPU8>;
+				};
+				core1 {
+					cpu = <&CPU9>;
+				};
+				core2 {
+					cpu = <&CPU10>;
+				};
+				core3 {
+					cpu = <&CPU11>;
+				};
+			};
+			cluster3 {
+				core0 {
+					cpu = <&CPU12>;
+				};
+				core1 {
+					cpu = <&CPU13>;
+				};
+				core2 {
+					cpu = <&CPU14>;
+				};
+				core3 {
+					cpu = <&CPU15>;
+				};
+			};
+		};
+		CPU0: cpu at 0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0>;
+		};
+		CPU1: cpu at 1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <1>;
+		};
+		CPU2: cpu at 2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <2>;
+		};
+		CPU3: cpu at 3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <3>;
+		};
+		CPU4: cpu at 100 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0x100>;
+		};
+		CPU5: cpu at 101 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0x101>;
+		};
+		CPU6: cpu at 102 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0x102>;
+		};
+		CPU7: cpu at 103 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0x103>;
+		};
+		CPU8: cpu at 200 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0x200>;
+		};
+		CPU9: cpu at 201 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0x201>;
+		};
+		CPU10: cpu at 202 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0x202>;
+		};
+		CPU11: cpu at 203 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0x203>;
+		};
+		CPU12: cpu at 300 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0x300>;
+		};
+		CPU13: cpu at 301 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0x301>;
+		};
+		CPU14: cpu at 302 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0x302>;
+		};
+		CPU15: cpu at 303 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0x303>;
+		};
+	};
+
+	timer {
+		compatible = "arm,armv7-timer";
+		interrupt-parent = <&gic>;
+		interrupts = <1 13 0xf08>,
+			     <1 14 0xf08>,
+			     <1 11 0xf08>,
+			     <1 10 0xf08>;
+	};
+
+	clk_50m: clk_50m {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <50000000>;
+	};
+
+	clk_168m: clk_168m {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <168000000>;
+	};
+
+	soc {
+		/* It's a 32-bit SoC. */
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		interrupt-parent = <&gic>;
+		ranges = <0 0 0xe0000000 0x10000000>;
+
+		gic: interrupt-controller at c01000 {
+			compatible = "hisilicon,hip04-intc";
+			#interrupt-cells = <3>;
+			#address-cells = <0>;
+			interrupt-controller;
+			interrupts = <1 9 0xf04>;
+
+			reg = <0xc01000 0x1000>, <0xc02000 0x1000>,
+			      <0xc04000 0x2000>, <0xc06000 0x2000>;
+		};
+
+		sysctrl: sysctrl {
+			compatible = "hisilicon,sysctrl";
+			reg = <0x3e00000 0x00100000>;
+		};
+
+		fabric: fabric {
+			compatible = "hisilicon,hip04-fabric";
+			reg = <0x302a000 0x1000>;
+		};
+
+		dual_timer0: dual_timer at 3000000 {
+			compatible = "arm,sp804", "arm,primecell";
+			reg = <0x3000000 0x1000>;
+			interrupts = <0 224 4>;
+			clocks = <&clk_50m>, <&clk_50m>;
+			clock-names = "apb_pclk";
+		};
+
+		arm-pmu {
+			compatible = "arm,cortex-a15-pmu";
+			interrupts = <0 64 4>,
+				     <0 65 4>,
+				     <0 66 4>,
+				     <0 67 4>,
+				     <0 68 4>,
+				     <0 69 4>,
+				     <0 70 4>,
+				     <0 71 4>,
+				     <0 72 4>,
+				     <0 73 4>,
+				     <0 74 4>,
+				     <0 75 4>,
+				     <0 76 4>,
+				     <0 77 4>,
+				     <0 78 4>,
+				     <0 79 4>;
+		};
+
+		uart0: uart at 4007000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x4007000 0x1000>;
+			interrupts = <0 381 4>;
+			clocks = <&clk_168m>;
+			clock-names = "uartclk";
+			reg-shift = <2>;
+			status = "disabled";
+		};
+
+		sata0: sata at a000000 {
+			compatible = "hisilicon,hisi-ahci";
+			reg = <0xa000000 0x1000000>;
+			interrupts = <0 372 4>;
+		};
+
+	};
+};
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v16 6/9] ARM: config: enable hisilicon hip04
  2014-08-04  2:57 [PATCH v16 0/9] enable HiP04 SoC Haojian Zhuang
                   ` (4 preceding siblings ...)
  2014-08-04  2:58 ` [PATCH v16 5/9] ARM: dts: add hip04 dts Haojian Zhuang
@ 2014-08-04  2:58 ` Haojian Zhuang
  2014-08-04  2:58 ` [PATCH v16 7/9] ARM: debug: add HiP04 debug uart Haojian Zhuang
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 21+ messages in thread
From: Haojian Zhuang @ 2014-08-04  2:58 UTC (permalink / raw)
  To: linux-arm-kernel

Enable 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.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 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

diff --git a/arch/arm/configs/hi3xxx_defconfig b/arch/arm/configs/hi3xxx_defconfig
deleted file mode 100644
index 9630687..0000000
--- a/arch/arm/configs/hi3xxx_defconfig
+++ /dev/null
@@ -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
diff --git a/arch/arm/configs/hisi_defconfig b/arch/arm/configs/hisi_defconfig
new file mode 100644
index 0000000..a68ee94
--- /dev/null
+++ b/arch/arm/configs/hisi_defconfig
@@ -0,0 +1,72 @@
+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_ARCH_HIP04=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=16
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER=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_8250=y
+CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+CONFIG_SERIAL_8250_DW=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
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index d34ab30..fd8694d 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -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
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v16 7/9] ARM: debug: add HiP04 debug uart
  2014-08-04  2:57 [PATCH v16 0/9] enable HiP04 SoC Haojian Zhuang
                   ` (5 preceding siblings ...)
  2014-08-04  2:58 ` [PATCH v16 6/9] ARM: config: enable hisilicon hip04 Haojian Zhuang
@ 2014-08-04  2:58 ` Haojian Zhuang
  2014-08-04  2:58 ` [PATCH v16 8/9] irq: enable hip04 irq chip Haojian Zhuang
  2014-08-04  2:58 ` [PATCH v16 9/9] of: fdt: fix memory address be truncated Haojian Zhuang
  8 siblings, 0 replies; 21+ messages in thread
From: Haojian Zhuang @ 2014-08-04  2:58 UTC (permalink / raw)
  To: linux-arm-kernel

Add the support of Hisilicon HiP04 debug uart.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 arch/arm/Kconfig.debug | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index d061de0..c6499cc 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -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
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v16 8/9] irq: enable hip04 irq chip
  2014-08-04  2:57 [PATCH v16 0/9] enable HiP04 SoC Haojian Zhuang
                   ` (6 preceding siblings ...)
  2014-08-04  2:58 ` [PATCH v16 7/9] ARM: debug: add HiP04 debug uart Haojian Zhuang
@ 2014-08-04  2:58 ` Haojian Zhuang
  2014-08-06 15:26   ` Andre Przywara
  2014-08-04  2:58 ` [PATCH v16 9/9] of: fdt: fix memory address be truncated Haojian Zhuang
  8 siblings, 1 reply; 21+ messages in thread
From: Haojian Zhuang @ 2014-08-04  2:58 UTC (permalink / raw)
  To: linux-arm-kernel

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_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.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 drivers/irqchip/Makefile    |   1 +
 drivers/irqchip/irq-hip04.c | 429 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 430 insertions(+)
 create mode 100644 drivers/irqchip/irq-hip04.c

diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index c57e642..23dcf45 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -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
diff --git a/drivers/irqchip/irq-hip04.c b/drivers/irqchip/irq-hip04.c
new file mode 100644
index 0000000..751a7ee
--- /dev/null
+++ b/drivers/irqchip/irq-hip04.c
@@ -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.
+ *
+ * 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.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/smp.h>
+#include <linux/cpu.h>
+#include <linux/cpu_pm.h>
+#include <linux/cpumask.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/irqchip/arm-gic.h>
+
+#include <asm/irq.h>
+#include <asm/exception.h>
+#include <asm/smp_plat.h>
+
+#include "irq-gic-common.h"
+#include "irqchip.h"
+
+#define HIP04_MAX_IRQS		510
+
+struct hip04_irq_data {
+	void __iomem *dist_base;
+	void __iomem *cpu_base;
+	struct irq_domain *domain;
+	unsigned int nr_irqs;
+};
+
+static DEFINE_RAW_SPINLOCK(irq_controller_lock);
+
+/*
+ * The GIC mapping of CPU interfaces does not necessarily match
+ * the logical CPU numbering.  Let's use a mapping as returned
+ * by the GIC itself.
+ */
+#define NR_HIP04_CPU_IF 16
+static u16 hip04_cpu_map[NR_HIP04_CPU_IF] __read_mostly;
+
+static struct hip04_irq_data hip04_data __read_mostly;
+
+static inline void __iomem *hip04_dist_base(struct irq_data *d)
+{
+	struct hip04_irq_data *hip04_data = irq_data_get_irq_chip_data(d);
+	return hip04_data->dist_base;
+}
+
+static inline void __iomem *hip04_cpu_base(struct irq_data *d)
+{
+	struct hip04_irq_data *hip04_data = irq_data_get_irq_chip_data(d);
+	return hip04_data->cpu_base;
+}
+
+static inline unsigned int hip04_irq(struct irq_data *d)
+{
+	return d->hwirq;
+}
+
+/*
+ * Routines to acknowledge, disable and enable interrupts
+ */
+static void hip04_mask_irq(struct irq_data *d)
+{
+	u32 mask = 1 << (hip04_irq(d) % 32);
+
+	raw_spin_lock(&irq_controller_lock);
+	writel_relaxed(mask, hip04_dist_base(d) + GIC_DIST_ENABLE_CLEAR +
+		       (hip04_irq(d) / 32) * 4);
+	raw_spin_unlock(&irq_controller_lock);
+}
+
+static void hip04_unmask_irq(struct irq_data *d)
+{
+	u32 mask = 1 << (hip04_irq(d) % 32);
+
+	raw_spin_lock(&irq_controller_lock);
+	writel_relaxed(mask, hip04_dist_base(d) + GIC_DIST_ENABLE_SET +
+		       (hip04_irq(d) / 32) * 4);
+	raw_spin_unlock(&irq_controller_lock);
+}
+
+static void hip04_eoi_irq(struct irq_data *d)
+{
+	writel_relaxed(hip04_irq(d), hip04_cpu_base(d) + GIC_CPU_EOI);
+}
+
+static int hip04_irq_set_type(struct irq_data *d, unsigned int type)
+{
+	void __iomem *base = hip04_dist_base(d);
+	unsigned int irq = hip04_irq(d);
+
+	/* Interrupt configuration for SGIs can't be changed */
+	if (irq < 16)
+		return -EINVAL;
+
+	if (type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING)
+		return -EINVAL;
+
+	raw_spin_lock(&irq_controller_lock);
+
+	gic_configure_irq(irq, type, base, NULL);
+
+	raw_spin_unlock(&irq_controller_lock);
+
+	return 0;
+}
+
+#ifdef CONFIG_SMP
+static int hip04_irq_set_affinity(struct irq_data *d,
+				  const struct cpumask *mask_val,
+				  bool force)
+{
+	void __iomem *reg;
+	unsigned int cpu, shift = (hip04_irq(d) % 2) * 16;
+	u32 val, mask, bit;
+
+	if (!force)
+		cpu = cpumask_any_and(mask_val, cpu_online_mask);
+	else
+		cpu = cpumask_first(mask_val);
+
+	if (cpu >= NR_HIP04_CPU_IF || cpu >= nr_cpu_ids)
+		return -EINVAL;
+
+	raw_spin_lock(&irq_controller_lock);
+	reg = hip04_dist_base(d) + GIC_DIST_TARGET + ((hip04_irq(d) * 2) & ~3);
+	mask = 0xffff << shift;
+	bit = hip04_cpu_map[cpu] << shift;
+	val = readl_relaxed(reg) & ~mask;
+	writel_relaxed(val | bit, reg);
+	raw_spin_unlock(&irq_controller_lock);
+
+	return IRQ_SET_MASK_OK;
+}
+#endif
+
+static void __exception_irq_entry hip04_handle_irq(struct pt_regs *regs)
+{
+	u32 irqstat, irqnr;
+	void __iomem *cpu_base = hip04_data.cpu_base;
+
+	do {
+		irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK);
+		irqnr = irqstat & GICC_IAR_INT_ID_MASK;
+
+		if (likely(irqnr > 15 && irqnr <= HIP04_MAX_IRQS)) {
+			irqnr = irq_find_mapping(hip04_data.domain, irqnr);
+			handle_IRQ(irqnr, regs);
+			continue;
+		}
+		if (irqnr < 16) {
+			writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI);
+#ifdef CONFIG_SMP
+			handle_IPI(irqnr, regs);
+#endif
+			continue;
+		}
+		break;
+	} while (1);
+}
+
+static struct irq_chip hip04_irq_chip = {
+	.name			= "HIP04 INTC",
+	.irq_mask		= hip04_mask_irq,
+	.irq_unmask		= hip04_unmask_irq,
+	.irq_eoi		= hip04_eoi_irq,
+	.irq_set_type		= hip04_irq_set_type,
+#ifdef CONFIG_SMP
+	.irq_set_affinity	= hip04_irq_set_affinity,
+#endif
+};
+
+static u16 hip04_get_cpumask(struct hip04_irq_data *intc)
+{
+	void __iomem *base = intc->dist_base;
+	u32 mask, i;
+
+	for (i = mask = 0; i < 32; i += 2) {
+		mask = readl_relaxed(base + GIC_DIST_TARGET + i * 2);
+		mask |= mask >> 16;
+		if (mask)
+			break;
+	}
+
+	if (!mask)
+		pr_crit("GIC CPU mask not found - kernel will fail to boot.\n");
+
+	return mask;
+}
+
+static void __init hip04_irq_dist_init(struct hip04_irq_data *intc)
+{
+	unsigned int i;
+	u32 cpumask;
+	unsigned int nr_irqs = intc->nr_irqs;
+	void __iomem *base = intc->dist_base;
+
+	writel_relaxed(0, base + GIC_DIST_CTRL);
+
+	/*
+	 * Set all global interrupts to this CPU only.
+	 */
+	cpumask = hip04_get_cpumask(intc);
+	cpumask |= cpumask << 16;
+	for (i = 32; i < nr_irqs; i += 2)
+		writel_relaxed(cpumask, base + GIC_DIST_TARGET + ((i * 2) & ~3));
+
+	gic_dist_config(base, nr_irqs, NULL);
+
+	writel_relaxed(1, base + GIC_DIST_CTRL);
+}
+
+static void hip04_irq_cpu_init(struct hip04_irq_data *intc)
+{
+	void __iomem *dist_base = intc->dist_base;
+	void __iomem *base = intc->cpu_base;
+	unsigned int cpu_mask, cpu = smp_processor_id();
+	int i;
+
+	/*
+	 * Get what the GIC says our CPU mask is.
+	 */
+	BUG_ON(cpu >= NR_HIP04_CPU_IF);
+	cpu_mask = hip04_get_cpumask(intc);
+	hip04_cpu_map[cpu] = cpu_mask;
+
+	/*
+	 * Clear our mask from the other map entries in case they're
+	 * still undefined.
+	 */
+	for (i = 0; i < NR_HIP04_CPU_IF; i++)
+		if (i != cpu)
+			hip04_cpu_map[i] &= ~cpu_mask;
+
+	gic_cpu_config(dist_base, NULL);
+
+	writel_relaxed(0xf0, base + GIC_CPU_PRIMASK);
+	writel_relaxed(1, base + GIC_CPU_CTRL);
+}
+
+void hip04_cpu_if_down(void)
+{
+	writel_relaxed(0, hip04_data.cpu_base + GIC_CPU_CTRL);
+}
+
+#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];
+
+	/*
+	 * 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);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v16 9/9] of: fdt: fix memory address be truncated
  2014-08-04  2:57 [PATCH v16 0/9] enable HiP04 SoC Haojian Zhuang
                   ` (7 preceding siblings ...)
  2014-08-04  2:58 ` [PATCH v16 8/9] irq: enable hip04 irq chip Haojian Zhuang
@ 2014-08-04  2:58 ` Haojian Zhuang
  2014-08-24 18:27   ` Olof Johansson
  8 siblings, 1 reply; 21+ messages in thread
From: Haojian Zhuang @ 2014-08-04  2:58 UTC (permalink / raw)
  To: linux-arm-kernel

early_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.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
 drivers/of/fdt.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index c4cddf0..10d5382 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -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);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v16 2/9] ARM: hisi: enable MCPM implementation
  2014-08-04  2:58 ` [PATCH v16 2/9] ARM: hisi: enable MCPM implementation Haojian Zhuang
@ 2014-08-04 22:43   ` Nicolas Pitre
  2014-08-05  0:07     ` Haojian Zhuang
  0 siblings, 1 reply; 21+ messages in thread
From: Nicolas Pitre @ 2014-08-04 22:43 UTC (permalink / raw)
  To: linux-arm-kernel

Sorry for the delay -- I was on vacation.

On Mon, 4 Aug 2014, Haojian Zhuang wrote:

> 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?

> 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.
> 
> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>

More comments below.

> ---
>  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
> 
> diff --git a/arch/arm/mach-hisi/Makefile b/arch/arm/mach-hisi/Makefile
> index ee2506b..d64831e 100644
> --- a/arch/arm/mach-hisi/Makefile
> +++ b/arch/arm/mach-hisi/Makefile
> @@ -3,4 +3,5 @@
>  #
>  
>  obj-y	+= hisilicon.o
> +obj-$(CONFIG_MCPM)		+= platmcpm.o
>  obj-$(CONFIG_SMP)		+= platsmp.o hotplug.o headsmp.o
> diff --git a/arch/arm/mach-hisi/platmcpm.c b/arch/arm/mach-hisi/platmcpm.c
> new file mode 100644
> index 0000000..fc17973
> --- /dev/null
> +++ b/arch/arm/mach-hisi/platmcpm.c
> @@ -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;
> +	}
> +	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.

> +	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];
> +	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.

> +{
> +	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);
> +	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.

> +			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);
> +		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).

> +
> +	__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);
> +
> +	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.

> +			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.

> +			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.

> +	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)
> +{
> +	asm volatile ("			\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;
> +
> +	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).

> +	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) {
> +		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.

> +	return ret;
> +err_fabric:
> +	iounmap(sysctrl);
> +err_sysctrl:
> +	iounmap(relocation);
> +err:
> +	return ret;
> +}
> +early_initcall(hip04_mcpm_init);
> -- 
> 1.9.1
> 
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v16 2/9] ARM: hisi: enable MCPM implementation
  2014-08-04 22:43   ` Nicolas Pitre
@ 2014-08-05  0:07     ` Haojian Zhuang
  2014-08-05  1:02       ` Nicolas Pitre
  0 siblings, 1 reply; 21+ messages in thread
From: Haojian Zhuang @ 2014-08-05  0:07 UTC (permalink / raw)
  To: linux-arm-kernel

On 5 August 2014 06:43, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> Sorry for the delay -- I was on vacation.
>
> On Mon, 4 Aug 2014, Haojian Zhuang wrote:
>
>> 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?
>

Others don't agree put them into DTS file. So I move them into command line.

>> 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.
>>
>> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
>
> More comments below.
>
>> ---
>>  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
>>
>> diff --git a/arch/arm/mach-hisi/Makefile b/arch/arm/mach-hisi/Makefile
>> index ee2506b..d64831e 100644
>> --- a/arch/arm/mach-hisi/Makefile
>> +++ b/arch/arm/mach-hisi/Makefile
>> @@ -3,4 +3,5 @@
>>  #
>>
>>  obj-y        += hisilicon.o
>> +obj-$(CONFIG_MCPM)           += platmcpm.o
>>  obj-$(CONFIG_SMP)            += platsmp.o hotplug.o headsmp.o
>> diff --git a/arch/arm/mach-hisi/platmcpm.c b/arch/arm/mach-hisi/platmcpm.c
>> new file mode 100644
>> index 0000000..fc17973
>> --- /dev/null
>> +++ b/arch/arm/mach-hisi/platmcpm.c
>> @@ -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;
>> +     }
>> +     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.
>

OK. I'll check the return value.

>> +     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];
>> +     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.

>> +{
>> +     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);
>> +     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
>> +                     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);
>> +             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
>> +
>> +     __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);
>> +
>> +     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.

>> +                     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.
>
>> +                     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.
>
>> +     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)
>> +{
>> +     asm volatile ("                 \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;
>> +
>> +     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).
>
>> +     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) {
>> +             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.
>

OK

>> +     return ret;
>> +err_fabric:
>> +     iounmap(sysctrl);
>> +err_sysctrl:
>> +     iounmap(relocation);
>> +err:
>> +     return ret;
>> +}
>> +early_initcall(hip04_mcpm_init);
>> --
>> 1.9.1
>>
>>

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v16 2/9] ARM: hisi: enable MCPM implementation
  2014-08-05  0:07     ` Haojian Zhuang
@ 2014-08-05  1:02       ` Nicolas Pitre
  2014-08-05  1:18         ` Haojian Zhuang
  0 siblings, 1 reply; 21+ messages in thread
From: Nicolas Pitre @ 2014-08-05  1:02 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 5 Aug 2014, Haojian Zhuang wrote:

> On 5 August 2014 06:43, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> > Sorry for the delay -- I was on vacation.
> >
> > On Mon, 4 Aug 2014, Haojian Zhuang wrote:
> >
> >> 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?
> >
> 
> 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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v16 2/9] ARM: hisi: enable MCPM implementation
  2014-08-05  1:02       ` Nicolas Pitre
@ 2014-08-05  1:18         ` Haojian Zhuang
  2014-08-05  1:32           ` Nicolas Pitre
  0 siblings, 1 reply; 21+ messages in thread
From: Haojian Zhuang @ 2014-08-05  1:18 UTC (permalink / raw)
  To: linux-arm-kernel

On 5 August 2014 09:02, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> On Tue, 5 Aug 2014, Haojian Zhuang wrote:
>
>> On 5 August 2014 06:43, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
>> > Sorry for the delay -- I was on vacation.
>> >
>> > On Mon, 4 Aug 2014, Haojian Zhuang wrote:
>> >
>> >> 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?
>> >
>>
>> 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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v16 2/9] ARM: hisi: enable MCPM implementation
  2014-08-05  1:18         ` Haojian Zhuang
@ 2014-08-05  1:32           ` Nicolas Pitre
  2014-08-05  1:38             ` Haojian Zhuang
  0 siblings, 1 reply; 21+ messages in thread
From: Nicolas Pitre @ 2014-08-05  1:32 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 5 Aug 2014, Haojian Zhuang wrote:

> On 5 August 2014 09:02, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> > On Tue, 5 Aug 2014, Haojian Zhuang wrote:
> >
> >> On 5 August 2014 06:43, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> >> > Sorry for the delay -- I was on vacation.
> >> >
> >> > On Mon, 4 Aug 2014, Haojian Zhuang wrote:
> >> >
> >> >> 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?
> >> >
> >>
> >> 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.

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.

> 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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v16 2/9] ARM: hisi: enable MCPM implementation
  2014-08-05  1:32           ` Nicolas Pitre
@ 2014-08-05  1:38             ` Haojian Zhuang
  2014-08-05  2:01               ` Nicolas Pitre
  0 siblings, 1 reply; 21+ messages in thread
From: Haojian Zhuang @ 2014-08-05  1:38 UTC (permalink / raw)
  To: linux-arm-kernel

On 5 August 2014 09:32, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> On Tue, 5 Aug 2014, Haojian Zhuang wrote:
>
>> On 5 August 2014 09:02, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
>> > On Tue, 5 Aug 2014, Haojian Zhuang wrote:
>> >
>> >> On 5 August 2014 06:43, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
>> >> > Sorry for the delay -- I was on vacation.
>> >> >
>> >> > On Mon, 4 Aug 2014, Haojian Zhuang wrote:
>> >> >
>> >> >> 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?
>> >> >
>> >>
>> >> 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.
>
> 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.
>
>> 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

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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v16 2/9] ARM: hisi: enable MCPM implementation
  2014-08-05  1:38             ` Haojian Zhuang
@ 2014-08-05  2:01               ` Nicolas Pitre
  2014-08-05  2:05                 ` Haojian Zhuang
  0 siblings, 1 reply; 21+ messages in thread
From: Nicolas Pitre @ 2014-08-05  2:01 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 5 Aug 2014, Haojian Zhuang wrote:

> On 5 August 2014 09:32, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> > On Tue, 5 Aug 2014, Haojian Zhuang wrote:
> >
> >> On 5 August 2014 09:02, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> >> > On Tue, 5 Aug 2014, Haojian Zhuang wrote:
> >> >
> >> >> On 5 August 2014 06:43, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> >> >> > Sorry for the delay -- I was on vacation.
> >> >> >
> >> >> > On Mon, 4 Aug 2014, Haojian Zhuang wrote:
> >> >> >
> >> >> >> 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?
> >> >> >
> >> >>
> >> >> 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.
> >
> > 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.
> >
> >> 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
> 
> 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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v16 2/9] ARM: hisi: enable MCPM implementation
  2014-08-05  2:01               ` Nicolas Pitre
@ 2014-08-05  2:05                 ` Haojian Zhuang
  0 siblings, 0 replies; 21+ messages in thread
From: Haojian Zhuang @ 2014-08-05  2:05 UTC (permalink / raw)
  To: linux-arm-kernel

On 5 August 2014 10:01, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> On Tue, 5 Aug 2014, Haojian Zhuang wrote:
>
>> On 5 August 2014 09:32, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
>> > On Tue, 5 Aug 2014, Haojian Zhuang wrote:
>> >
>> >> On 5 August 2014 09:02, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
>> >> > On Tue, 5 Aug 2014, Haojian Zhuang wrote:
>> >> >
>> >> >> On 5 August 2014 06:43, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
>> >> >> > Sorry for the delay -- I was on vacation.
>> >> >> >
>> >> >> > On Mon, 4 Aug 2014, Haojian Zhuang wrote:
>> >> >> >
>> >> >> >> 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?
>> >> >> >
>> >> >>
>> >> >> 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.
>> >
>> > 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.
>> >
>> >> 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
>>
>> 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

Sure. I can define the magic number as hardcode.

Regards
Haojian

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v16 8/9] irq: enable hip04 irq chip
  2014-08-04  2:58 ` [PATCH v16 8/9] irq: enable hip04 irq chip Haojian Zhuang
@ 2014-08-06 15:26   ` Andre Przywara
  2014-08-07  5:26     ` Haojian Zhuang
  0 siblings, 1 reply; 21+ messages in thread
From: Andre Przywara @ 2014-08-06 15:26 UTC (permalink / raw)
  To: linux-arm-kernel

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...

On 04/08/14 03:58, Haojian Zhuang wrote:
> 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_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.
> 
> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
> ---
>  drivers/irqchip/Makefile    |   1 +
>  drivers/irqchip/irq-hip04.c | 429 ++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 430 insertions(+)
>  create mode 100644 drivers/irqchip/irq-hip04.c
> 
> diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
> index c57e642..23dcf45 100644
> --- a/drivers/irqchip/Makefile
> +++ b/drivers/irqchip/Makefile
> @@ -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
> diff --git a/drivers/irqchip/irq-hip04.c b/drivers/irqchip/irq-hip04.c
> new file mode 100644
> index 0000000..751a7ee
> --- /dev/null
> +++ b/drivers/irqchip/irq-hip04.c
> @@ -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.
> + *
> + * 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.

[...]

> +
> +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.


> +
> +#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.

> +
> +	/*
> +	 * 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);
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v16 8/9] irq: enable hip04 irq chip
  2014-08-06 15:26   ` Andre Przywara
@ 2014-08-07  5:26     ` Haojian Zhuang
  0 siblings, 0 replies; 21+ messages in thread
From: Haojian Zhuang @ 2014-08-07  5:26 UTC (permalink / raw)
  To: linux-arm-kernel

On 6 August 2014 23:26, Andre Przywara <andre.przywara@arm.com> wrote:
> 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...
>
> On 04/08/14 03:58, Haojian Zhuang wrote:
>> 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_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.
>>
>> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
>> ---
>>  drivers/irqchip/Makefile    |   1 +
>>  drivers/irqchip/irq-hip04.c | 429 ++++++++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 430 insertions(+)
>>  create mode 100644 drivers/irqchip/irq-hip04.c
>>
>> diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
>> index c57e642..23dcf45 100644
>> --- a/drivers/irqchip/Makefile
>> +++ b/drivers/irqchip/Makefile
>> @@ -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
>> diff --git a/drivers/irqchip/irq-hip04.c b/drivers/irqchip/irq-hip04.c
>> new file mode 100644
>> index 0000000..751a7ee
>> --- /dev/null
>> +++ b/drivers/irqchip/irq-hip04.c
>> @@ -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.
>> + *
>> + * 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.
>
Since we didn't enable power management on HiP04 yet, I removed them.
If we enable power management later, I could append them again.

>
>> +
>> +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.

>
>> +
>> +#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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v16 9/9] of: fdt: fix memory address be truncated
  2014-08-04  2:58 ` [PATCH v16 9/9] of: fdt: fix memory address be truncated Haojian Zhuang
@ 2014-08-24 18:27   ` Olof Johansson
  0 siblings, 0 replies; 21+ messages in thread
From: Olof Johansson @ 2014-08-24 18:27 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Aug 04, 2014 at 10:58:08AM +0800, Haojian Zhuang wrote:
> early_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.
> 
> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
> ---
>  drivers/of/fdt.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
> index c4cddf0..10d5382 100644
> --- a/drivers/of/fdt.c
> +++ b/drivers/of/fdt.c
> @@ -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;

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

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2014-08-24 18:27 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-08-04  2:57 [PATCH v16 0/9] enable HiP04 SoC Haojian Zhuang
2014-08-04  2:58 ` [PATCH v16 1/9] ARM: mcpm: support 4 clusters Haojian Zhuang
2014-08-04  2:58 ` [PATCH v16 2/9] ARM: hisi: enable MCPM implementation Haojian Zhuang
2014-08-04 22:43   ` Nicolas Pitre
2014-08-05  0:07     ` Haojian Zhuang
2014-08-05  1:02       ` Nicolas Pitre
2014-08-05  1:18         ` Haojian Zhuang
2014-08-05  1:32           ` Nicolas Pitre
2014-08-05  1:38             ` Haojian Zhuang
2014-08-05  2:01               ` Nicolas Pitre
2014-08-05  2:05                 ` Haojian Zhuang
2014-08-04  2:58 ` [PATCH v16 3/9] ARM: hisi: enable HiP04 Haojian Zhuang
2014-08-04  2:58 ` [PATCH v16 4/9] document: dt: add the binding on HiP04 Haojian Zhuang
2014-08-04  2:58 ` [PATCH v16 5/9] ARM: dts: add hip04 dts Haojian Zhuang
2014-08-04  2:58 ` [PATCH v16 6/9] ARM: config: enable hisilicon hip04 Haojian Zhuang
2014-08-04  2:58 ` [PATCH v16 7/9] ARM: debug: add HiP04 debug uart Haojian Zhuang
2014-08-04  2:58 ` [PATCH v16 8/9] irq: enable hip04 irq chip Haojian Zhuang
2014-08-06 15:26   ` Andre Przywara
2014-08-07  5:26     ` Haojian Zhuang
2014-08-04  2:58 ` [PATCH v16 9/9] of: fdt: fix memory address be truncated Haojian Zhuang
2014-08-24 18:27   ` Olof Johansson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.