diff mbox

[Xen-devel,01/10] xen/arm: Implement hip04-d01 platform

Message ID 1415009522-6344-2-git-send-email-frediano.ziglio@huawei.com
State New
Headers show

Commit Message

Frediano Ziglio Nov. 3, 2014, 10:11 a.m. UTC
Add this new platform to Xen.
This platform require specific code to initialize CPUs.

Signed-off-by: Frediano Ziglio <frediano.ziglio@huawei.com>
Signed-off-by: Zoltan Kiss <zoltan.kiss@huawei.com>
---
 xen/arch/arm/platforms/Makefile |   1 +
 xen/arch/arm/platforms/hip04.c  | 258 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 259 insertions(+)
 create mode 100644 xen/arch/arm/platforms/hip04.c

Comments

Julien Grall Nov. 3, 2014, 1:39 p.m. UTC | #1
Hi Frediano,

On 11/03/2014 10:11 AM, Frediano Ziglio wrote:
> Add this new platform to Xen.
> This platform require specific code to initialize CPUs.

s/require/requires/

I guess your platform doesn't support PSCI?

> 
> Signed-off-by: Frediano Ziglio <frediano.ziglio@huawei.com>
> Signed-off-by: Zoltan Kiss <zoltan.kiss@huawei.com>
> ---

[..]

> diff --git a/xen/arch/arm/platforms/hip04.c b/xen/arch/arm/platforms/hip04.c
> new file mode 100644
> index 0000000..bf38c23
> --- /dev/null
> +++ b/xen/arch/arm/platforms/hip04.c
> @@ -0,0 +1,258 @@

[..]

> +
> +struct hip04_secondary_cpu_data {

coding style:

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 struct hip04_secondary_cpu_data hip04_boot;
> +
> +static void hip04_reset(void)
> +{
> +    /* TODO */

Why did you implement the reset in a separate patch rather than here?

> +}
> +
> +static void hip04_set_snoop_filter(unsigned int cluster, unsigned int on)
> +{
> +    unsigned long data;
> +
> +    if (!fabric)

Coding style:

if ( !fabric )

> +        return;
> +    data = readl_relaxed(fabric + FAB_SF_MODE);
> +    if (on)

if ( on )

> +        data |= 1 << cluster;
> +    else
> +        data &= ~(1 << cluster);
> +    writel_relaxed(data, fabric + FAB_SF_MODE);
> +    while (1) {

while ( 1 )
{

> +        if (data == readl_relaxed(fabric + FAB_SF_MODE))

if ( ... )

> +            break;
> +    }

The loop is turning in an infinite loop if the reading value is never
correct.

> +}
> +
> +static bool __init hip04_cpu_table_init(void)
> +{
> +    unsigned int mpidr, cpu, cluster;
> +
> +    mpidr = cpu_logical_map(smp_processor_id());
> +    cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
> +    cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
> +
> +    if (cluster >= HIP04_MAX_CLUSTERS ||
> +        cpu >= HIP04_MAX_CPUS_PER_CLUSTER) {

if ( ...
     ... )
{

> +        printk(XENLOG_ERR "%s: boot CPU is out of bound!\n", __func__);
> +        return false;
> +    }
> +    hip04_set_snoop_filter(cluster, 1);
> +    hip04_cpu_table[cluster][cpu] = 1;

Missing blank line

> +    return true;
> +}
> +
> +static bool hip04_cluster_down(unsigned int cluster)
> +{
> +    int i;
> +
> +    for (i = 0; i < HIP04_MAX_CPUS_PER_CLUSTER; i++)

for ( ... )

> +        if (hip04_cpu_table[cluster][i])

if ( ... )

> +            return false;
> +    return true;
> +}
> +
> +static void hip04_cluster_up(unsigned int cluster)
> +{
> +    unsigned long data, mask;
> +
> +    if ( hip04_cluster_down(cluster) ) {

Wouldn't it be easier to return if the cluster is up? It will one layer
of indentation.

> +        data = CLUSTER_L2_RESET_BIT | CLUSTER_DEBUG_RESET_BIT;
> +        writel_relaxed(data, sysctrl + SC_CPU_RESET_DREQ(cluster));
> +        do {
> +            mask = CLUSTER_L2_RESET_STATUS | \
> +                   CLUSTER_DEBUG_RESET_STATUS;
> +            data = readl_relaxed(sysctrl + \
> +                         SC_CPU_RESET_STATUS(cluster));
> +        } while (data & mask);
> +        hip04_set_snoop_filter(cluster, 1);
> +    }
> +}
> +
> +static int __init hip04_smp_init(void)
> +{
> +    struct dt_device_node *np, *np_fab;

The device node are not modified so:

const struct

[..]

> +    writel_relaxed(hip04_boot.bootwrapper_phys, relocation);
> +    writel_relaxed(hip04_boot.bootwrapper_magic, relocation + 4);
> +    writel_relaxed(__pa(init_secondary), relocation + 8);
> +    writel_relaxed(0, relocation + 12);
> +
> +    return 0;
> +
> +err:

For consistence, you should unmap everything you mapped with ioremap_*

> +    printk("%s", msg);
> +    return -ENXIO;
> +}
> +
> +static int hip04_cpu_up(int cpu)
> +{
> +    unsigned int cluster = cpu / 4;

The number 4 is confusing here, why not using the define you've created
above? Such as  HIP04_MAX_CPUS_PER_CLUSTER

> +    unsigned long data;

The coding style requires a blank line after the declarations block.

> +    cpu %= 4;

Ditto for the number 4.

Regards,
diff mbox

Patch

diff --git a/xen/arch/arm/platforms/Makefile b/xen/arch/arm/platforms/Makefile
index 8f47c16..d0b2d99 100644
--- a/xen/arch/arm/platforms/Makefile
+++ b/xen/arch/arm/platforms/Makefile
@@ -5,4 +5,5 @@  obj-$(CONFIG_ARM_32) += midway.o
 obj-$(CONFIG_ARM_32) += omap5.o
 obj-$(CONFIG_ARM_32) += sunxi.o
 obj-$(CONFIG_ARM_64) += seattle.o
+obj-$(CONFIG_ARM_32) += hip04.o
 obj-$(CONFIG_ARM_64) += xgene-storm.o
diff --git a/xen/arch/arm/platforms/hip04.c b/xen/arch/arm/platforms/hip04.c
new file mode 100644
index 0000000..bf38c23
--- /dev/null
+++ b/xen/arch/arm/platforms/hip04.c
@@ -0,0 +1,258 @@ 
+/*
+ * xen/arch/arm/platforms/hip04.c
+ *
+ * HiSilicon HIP-04 D01 board
+ *
+ * Copyright (c) 2012-2013 Hisilicon Ltd.
+ * Copyright (c) 2012-2013 Linaro Ltd.
+ * Copyright (c) 2014 Huawei Tech. Co., Ltd.
+ *
+ * Author: Frediano Ziglio <frediano.ziglio@huawei.com>
+ *
+ * Original code from Linux kernel arch/arm/mach-hisi/hisilicon.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <asm/platform.h>
+#include <xen/mm.h>
+#include <xen/vmap.h>
+#include <asm/io.h>
+#include <asm/gic.h>
+
+#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)
+
+#define CLUSTER_L2_RESET_STATUS      (1 << 8)
+#define CLUSTER_DEBUG_RESET_STATUS   (1 << 13)
+
+#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 HIP04_MAX_CLUSTERS           4
+#define HIP04_MAX_CPUS_PER_CLUSTER   4
+
+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 struct hip04_secondary_cpu_data hip04_boot;
+
+static void hip04_reset(void)
+{
+    /* TODO */
+}
+
+static void hip04_set_snoop_filter(unsigned int cluster, unsigned int on)
+{
+    unsigned long data;
+
+    if (!fabric)
+        return;
+    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;
+    }
+}
+
+static bool __init hip04_cpu_table_init(void)
+{
+    unsigned int mpidr, cpu, cluster;
+
+    mpidr = cpu_logical_map(smp_processor_id());
+    cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
+    cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
+
+    if (cluster >= HIP04_MAX_CLUSTERS ||
+        cpu >= HIP04_MAX_CPUS_PER_CLUSTER) {
+        printk(XENLOG_ERR "%s: boot CPU is out of bound!\n", __func__);
+        return false;
+    }
+    hip04_set_snoop_filter(cluster, 1);
+    hip04_cpu_table[cluster][cpu] = 1;
+    return true;
+}
+
+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_cluster_up(unsigned int cluster)
+{
+    unsigned long data, mask;
+
+    if ( hip04_cluster_down(cluster) ) {
+        data = CLUSTER_L2_RESET_BIT | CLUSTER_DEBUG_RESET_BIT;
+        writel_relaxed(data, sysctrl + SC_CPU_RESET_DREQ(cluster));
+        do {
+            mask = CLUSTER_L2_RESET_STATUS | \
+                   CLUSTER_DEBUG_RESET_STATUS;
+            data = readl_relaxed(sysctrl + \
+                         SC_CPU_RESET_STATUS(cluster));
+        } while (data & mask);
+        hip04_set_snoop_filter(cluster, 1);
+    }
+}
+
+static int __init hip04_smp_init(void)
+{
+    struct dt_device_node *np, *np_fab;
+    const char *msg;
+    u64 addr, size;
+
+    np = dt_find_compatible_node(NULL, NULL, "hisilicon,sysctrl");
+    msg = "hisilicon,sysctrl missing in DT\n";
+    if ( !np )
+        goto err;
+
+    np_fab = dt_find_compatible_node(NULL, NULL, "hisilicon,hip04-fabric");
+    msg = "hisilicon,hip04-fabric missing in DT\n";
+    if ( !np_fab )
+        goto err;
+
+    msg = "failed to get bootwrapper-phys\n";
+    if ( !dt_property_read_u32(np, "bootwrapper-phys",
+                               &hip04_boot.bootwrapper_phys) )
+        goto err;
+
+    msg = "failed to get bootwrapper-size\n";
+    if ( !dt_property_read_u32(np, "bootwrapper-size",
+                               &hip04_boot.bootwrapper_size) )
+        goto err;
+
+    msg = "failed to get bootwrapper-magic\n";
+    if ( !dt_property_read_u32(np, "bootwrapper-magic",
+                               &hip04_boot.bootwrapper_magic) )
+        goto err;
+
+    msg = "failed to get relocation-entry\n";
+    if ( !dt_property_read_u32(np, "relocation-entry",
+                               &hip04_boot.relocation_entry) )
+        goto err;
+
+    msg = "failed to get relocation-size\n";
+    if ( !dt_property_read_u32(np, "relocation-size",
+                 &hip04_boot.relocation_size) )
+        goto err;
+
+    relocation = ioremap_nocache(hip04_boot.relocation_entry,
+                                 hip04_boot.relocation_size);
+    msg = "failed to map relocation space\n";
+    if ( !relocation )
+        goto err;
+
+    msg = "Error in \"hisilicon,sysctrl\"\n";
+    if ( dt_device_get_address(np, 0, &addr, &size) )
+        goto err;
+    sysctrl = ioremap_nocache(addr, size);
+    if ( !sysctrl )
+        goto err;
+
+    msg = "Error in \"hisilicon,hip04-fabric\"\n";
+    if ( dt_device_get_address(np_fab, 0, &addr, &size) )
+        goto err;
+    fabric = ioremap_nocache(addr, size);
+    if ( !fabric )
+        goto err;
+
+    msg = "Error initializing SMP table\n";
+    if ( !hip04_cpu_table_init() )
+        goto err;
+
+    writel_relaxed(hip04_boot.bootwrapper_phys, relocation);
+    writel_relaxed(hip04_boot.bootwrapper_magic, relocation + 4);
+    writel_relaxed(__pa(init_secondary), relocation + 8);
+    writel_relaxed(0, relocation + 12);
+
+    return 0;
+
+err:
+    printk("%s", msg);
+    return -ENXIO;
+}
+
+static int hip04_cpu_up(int cpu)
+{
+    unsigned int cluster = cpu / 4;
+    unsigned long data;
+    cpu %= 4;
+
+    writel_relaxed(hip04_boot.bootwrapper_phys, relocation);
+    writel_relaxed(hip04_boot.bootwrapper_magic, relocation + 4);
+    writel_relaxed(__pa(init_secondary), relocation + 8);
+    writel_relaxed(0, relocation + 12);
+
+    hip04_cluster_up(cluster);
+
+    hip04_cpu_table[cluster][cpu]++;
+
+    data = CORE_RESET_BIT(cpu) | NEON_RESET_BIT(cpu) | \
+           CORE_DEBUG_RESET_BIT(cpu);
+    writel_relaxed(data, sysctrl + SC_CPU_RESET_DREQ(cluster));
+
+    return cpu_up_send_sgi(cpu);
+}
+
+
+static const char * const hip04_dt_compat[] __initconst =
+{
+    "hisilicon,hip04-d01",
+    NULL
+};
+
+static const struct dt_device_match hip04_blacklist_dev[] __initconst =
+{
+    /* Hardware power management */
+    DT_MATCH_COMPATIBLE("hisilicon,sysctrl"),
+    DT_MATCH_COMPATIBLE("hisilicon,hip04-fabric"),
+    { /* sentinel */ },
+};
+
+
+PLATFORM_START(hip04, "HISILICON HIP04")
+    .compatible = hip04_dt_compat,
+    .smp_init = hip04_smp_init,
+    .cpu_up = hip04_cpu_up,
+    .reset = hip04_reset,
+    .blacklist_dev = hip04_blacklist_dev,
+PLATFORM_END
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */