* [PATCH v10 01/11] irq: gic: support hip04 gic
2014-07-10 2:03 [PATCH v10 00/11] enable HiP04 SoC Haojian Zhuang
@ 2014-07-10 2:04 ` Haojian Zhuang
2014-07-18 9:20 ` Mark Rutland
2014-07-18 12:05 ` Jason Cooper
2014-07-10 2:04 ` [PATCH v10 02/11] ARM: mcpm: support 4 clusters Haojian Zhuang
` (9 subsequent siblings)
10 siblings, 2 replies; 20+ messages in thread
From: Haojian Zhuang @ 2014-07-10 2:04 UTC (permalink / raw)
To: linux-arm-kernel
There's a little difference between ARM GIC and HiP04 GIC.
* HiP04 GIC could support 16 cores at most, and ARM GIC could support
8 cores at most. So the difination on GIC_DIST_TARGET registers are
different since CPU interfaces are increased from 8-bit to 16-bit.
* HiP04 GIC could support 510 interrupts at most, and ARM GIC could
support 1020 interrupts at most.
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
Documentation/devicetree/bindings/arm/gic.txt | 1 +
drivers/irqchip/irq-gic.c | 141 +++++++++++++++++++-------
2 files changed, 108 insertions(+), 34 deletions(-)
diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt
index 5573c08..150f7d6 100644
--- a/Documentation/devicetree/bindings/arm/gic.txt
+++ b/Documentation/devicetree/bindings/arm/gic.txt
@@ -16,6 +16,7 @@ Main node required properties:
"arm,cortex-a9-gic"
"arm,cortex-a7-gic"
"arm,arm11mp-gic"
+ "hisilicon,hip04-gic"
- interrupt-controller : Identifies the node as an interrupt controller
- #interrupt-cells : Specifies the number of cells needed to encode an
interrupt source. The type shall be a <u32> and the value shall be 3.
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 508b815..55c34fb 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -69,6 +69,9 @@ struct gic_chip_data {
#ifdef CONFIG_GIC_NON_BANKED
void __iomem *(*get_base)(union gic_base *);
#endif
+ u32 nr_cpu_if;
+ u32 nr_cpu_if_mask;
+ u32 cpu_target_shift;
};
static DEFINE_RAW_SPINLOCK(irq_controller_lock);
@@ -77,9 +80,11 @@ 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.
+ *
+ * Hisilicon HiP04 extends the number of CPU interface from 8 to 16.
*/
-#define NR_GIC_CPU_IF 8
-static u8 gic_cpu_map[NR_GIC_CPU_IF] __read_mostly;
+#define NR_GIC_CPU_IF 16
+static u16 gic_cpu_map[NR_GIC_CPU_IF] __read_mostly;
/*
* Supported arch specific GIC irq extension.
@@ -218,12 +223,41 @@ static int gic_retrigger(struct irq_data *d)
return 0;
}
+static bool gic_is_standard(struct gic_chip_data *gic_data)
+{
+ return (gic_data->nr_cpu_if == 8);
+}
+
+static u32 irqs_per_target_reg(struct gic_chip_data *gic_data)
+{
+ return (32 / gic_data->nr_cpu_if);
+}
+
+static u32 irq_to_target_reg(struct gic_chip_data *gic_data, u32 irq)
+{
+ if (!gic_is_standard(gic_data))
+ irq *= 2;
+ irq &= ~3U;
+ return (irq + GIC_DIST_TARGET);
+}
+
#ifdef CONFIG_SMP
+static u32 irq_to_core_shift(struct irq_data *d)
+{
+ struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
+ unsigned int i = gic_irq(d);
+
+ if (gic_is_standard(gic_data))
+ return ((i % 4) << 3);
+ return ((i % 2) << 4);
+}
+
static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
bool force)
{
- void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3);
- unsigned int cpu, shift = (gic_irq(d) % 4) * 8;
+ void __iomem *reg;
+ struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
+ unsigned int cpu, shift = irq_to_core_shift(d);
u32 val, mask, bit;
if (!force)
@@ -231,11 +265,13 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
else
cpu = cpumask_first(mask_val);
- if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids)
+ if (cpu >= gic_data->nr_cpu_if || cpu >= nr_cpu_ids)
return -EINVAL;
+ reg = gic_dist_base(d) + irq_to_target_reg(gic_data, gic_irq(d));
+
raw_spin_lock(&irq_controller_lock);
- mask = 0xff << shift;
+ mask = gic_data->nr_cpu_if_mask << irq_to_core_shift(d);
bit = gic_cpu_map[cpu] << shift;
val = readl_relaxed(reg) & ~mask;
writel_relaxed(val | bit, reg);
@@ -335,15 +371,20 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
irq_set_chained_handler(irq, gic_handle_cascade_irq);
}
-static u8 gic_get_cpumask(struct gic_chip_data *gic)
+static u16 gic_get_cpumask(struct gic_chip_data *gic)
{
void __iomem *base = gic_data_dist_base(gic);
u32 mask, i;
- for (i = mask = 0; i < 32; i += 4) {
- mask = readl_relaxed(base + GIC_DIST_TARGET + i);
+ /*
+ * ARM GIC uses 8 registers for interrupt 0-31,
+ * HiP04 GIC uses 16 registers for interrupt 0-31.
+ */
+ for (i = mask = 0; i < 32; i++) {
+ mask = readl_relaxed(base + irq_to_target_reg(gic, i));
mask |= mask >> 16;
- mask |= mask >> 8;
+ if (gic_is_standard(gic))
+ mask |= mask >> 8;
if (mask)
break;
}
@@ -351,6 +392,10 @@ static u8 gic_get_cpumask(struct gic_chip_data *gic)
if (!mask)
pr_crit("GIC CPU mask not found - kernel will fail to boot.\n");
+ /* ARM GIC needs 8-bit cpu mask, HiP04 GIC needs 16-bit cpu mask. */
+ if (gic_is_standard(gic))
+ mask &= 0xff;
+
return mask;
}
@@ -367,10 +412,11 @@ static void __init gic_dist_init(struct gic_chip_data *gic)
* Set all global interrupts to this CPU only.
*/
cpumask = gic_get_cpumask(gic);
- cpumask |= cpumask << 8;
+ if (gic_is_standard(gic))
+ cpumask |= cpumask << 8;
cpumask |= cpumask << 16;
- for (i = 32; i < gic_irqs; i += 4)
- writel_relaxed(cpumask, base + GIC_DIST_TARGET + i * 4 / 4);
+ for (i = 32; i < gic_irqs; i++)
+ writel_relaxed(cpumask, base + irq_to_target_reg(gic, i));
gic_dist_config(base, gic_irqs, NULL);
@@ -387,7 +433,7 @@ static void gic_cpu_init(struct gic_chip_data *gic)
/*
* Get what the GIC says our CPU mask is.
*/
- BUG_ON(cpu >= NR_GIC_CPU_IF);
+ BUG_ON(cpu >= gic->nr_cpu_if);
cpu_mask = gic_get_cpumask(gic);
gic_cpu_map[cpu] = cpu_mask;
@@ -395,7 +441,7 @@ static void gic_cpu_init(struct gic_chip_data *gic)
* Clear our mask from the other map entries in case they're
* still undefined.
*/
- for (i = 0; i < NR_GIC_CPU_IF; i++)
+ for (i = 0; i < gic->nr_cpu_if; i++)
if (i != cpu)
gic_cpu_map[i] &= ~cpu_mask;
@@ -437,9 +483,10 @@ static void gic_dist_save(unsigned int gic_nr)
gic_data[gic_nr].saved_spi_conf[i] =
readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4);
- for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
+ for (i = 0; i < gic_irqs; i += irqs_per_target_reg(&gic_data[gic_nr]))
gic_data[gic_nr].saved_spi_target[i] =
- readl_relaxed(dist_base + GIC_DIST_TARGET + i * 4);
+ readl_relaxed(dist_base +
+ irq_to_target_reg(&gic_data[gic_nr], i));
for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
gic_data[gic_nr].saved_spi_enable[i] =
@@ -478,9 +525,9 @@ static void gic_dist_restore(unsigned int gic_nr)
writel_relaxed(0xa0a0a0a0,
dist_base + GIC_DIST_PRI + i * 4);
- for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
+ for (i = 0; i < gic_irqs; i += irqs_per_target_reg(&gic_data[gic_nr]))
writel_relaxed(gic_data[gic_nr].saved_spi_target[i],
- dist_base + GIC_DIST_TARGET + i * 4);
+ dist_base + irq_to_target_reg(&gic_data[gic_nr], i));
for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
writel_relaxed(gic_data[gic_nr].saved_spi_enable[i],
@@ -618,9 +665,16 @@ static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
*/
dmb(ishst);
- /* this always happens on GIC0 */
- writel_relaxed(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
-
+ /*
+ * CPUTargetList -- bit[23:16] in GIC_DIST_SOFTINT in ARM GIC.
+ * bit[23:8] in GIC_DIST_SOFTINT in HiP04 GIC.
+ * NSATT -- bit[15] in GIC_DIST_SOFTINT in ARM GIC.
+ * bit[7] in GIC_DIST_SOFTINT in HiP04 GIC.
+ * this always happens on GIC0
+ */
+ map = map << gic_data[0].cpu_target_shift;
+ writel_relaxed(map | irq,
+ gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
}
#endif
@@ -634,10 +688,12 @@ static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
*/
void gic_send_sgi(unsigned int cpu_id, unsigned int irq)
{
- BUG_ON(cpu_id >= NR_GIC_CPU_IF);
+ BUG_ON(cpu_id >= gic_data[0].nr_cpu_if);
cpu_id = 1 << cpu_id;
/* this always happens on GIC0 */
- writel_relaxed((cpu_id << 16) | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
+ cpuid = cpuid << gic_data[0].cpu_target_shift;
+ writel_relaxed(cpu_id | irq,
+ gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
}
/*
@@ -653,7 +709,7 @@ int gic_get_cpu_id(unsigned int cpu)
{
unsigned int cpu_bit;
- if (cpu >= NR_GIC_CPU_IF)
+ if (cpu >= gic_data[0].nr_cpu_if)
return -1;
cpu_bit = gic_cpu_map[cpu];
if (cpu_bit & (cpu_bit - 1))
@@ -700,13 +756,15 @@ void gic_migrate_target(unsigned int new_cpu_id)
* CPU interface and migrate them to the new CPU interface.
* We skip DIST_TARGET 0 to 7 as they are read-only.
*/
- for (i = 8; i < DIV_ROUND_UP(gic_irqs, 4); i++) {
- val = readl_relaxed(dist_base + GIC_DIST_TARGET + i * 4);
+ for (i = 8; i < gic_irqs; i += irqs_per_target_reg(&gic_data[gic_nr])) {
+ val = readl_relaxed(dist_base +
+ irq_to_target_reg(&gic_data[gic_nr], i));
active_mask = val & cur_target_mask;
if (active_mask) {
val &= ~active_mask;
val |= ror32(active_mask, ror_val);
- writel_relaxed(val, dist_base + GIC_DIST_TARGET + i*4);
+ writel_relaxed(val, dist_base +
+ irq_to_target_reg(&gic_data[gic_nr], i));
}
}
@@ -884,7 +942,7 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
irq_hw_number_t hwirq_base;
struct gic_chip_data *gic;
int gic_irqs, irq_base, i;
- int nr_routable_irqs;
+ int nr_routable_irqs, max_nr_irq;
BUG_ON(gic_nr >= MAX_GIC_NR);
@@ -920,12 +978,25 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
gic_set_base_accessor(gic, gic_get_common_base);
}
+ if (of_device_is_compatible(node, "hisilicon,hip04-gic")) {
+ /* HiP04 GIC supports 16 CPUs at most */
+ gic->nr_cpu_if = 16;
+ gic->cpu_target_shift = 8;
+ max_nr_irq = 510;
+ } else {
+ /* ARM/Qualcomm GIC supports 8 CPUs at most */
+ gic->nr_cpu_if = 8;
+ gic->cpu_target_shift = 16;
+ max_nr_irq = 1020;
+ }
+ gic->nr_cpu_if_mask = (1 << gic->nr_cpu_if) - 1;
+
/*
* Initialize the CPU interface map to all CPUs.
* It will be refined as each CPU probes its ID.
*/
- for (i = 0; i < NR_GIC_CPU_IF; i++)
- gic_cpu_map[i] = 0xff;
+ for (i = 0; i < gic->nr_cpu_if; i++)
+ gic_cpu_map[i] = (1 << gic->nr_cpu_if) - 1;
/*
* For primary GICs, skip over SGIs.
@@ -941,12 +1012,13 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
/*
* Find out how many interrupts are supported.
- * The GIC only supports up to 1020 interrupt sources.
+ * The ARM/Qualcomm GIC only supports up to 1020 interrupt sources.
+ * The HiP04 GIC only supports up to 510 interrupt sources.
*/
gic_irqs = readl_relaxed(gic_data_dist_base(gic) + GIC_DIST_CTR) & 0x1f;
gic_irqs = (gic_irqs + 1) * 32;
- if (gic_irqs > 1020)
- gic_irqs = 1020;
+ if (gic_irqs > max_nr_irq)
+ gic_irqs = max_nr_irq;
gic->gic_irqs = gic_irqs;
gic_irqs -= hwirq_base; /* calculate # of irqs to allocate */
@@ -1022,6 +1094,7 @@ gic_of_init(struct device_node *node, struct device_node *parent)
}
IRQCHIP_DECLARE(cortex_a15_gic, "arm,cortex-a15-gic", gic_of_init);
IRQCHIP_DECLARE(cortex_a9_gic, "arm,cortex-a9-gic", gic_of_init);
+IRQCHIP_DECLARE(hip04_gic, "hisilicon,hip04-gic", gic_of_init);
IRQCHIP_DECLARE(msm_8660_qgic, "qcom,msm-8660-qgic", gic_of_init);
IRQCHIP_DECLARE(msm_qgic2, "qcom,msm-qgic2", gic_of_init);
--
1.9.1
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v10 01/11] irq: gic: support hip04 gic
2014-07-10 2:04 ` [PATCH v10 01/11] irq: gic: support hip04 gic Haojian Zhuang
@ 2014-07-18 9:20 ` Mark Rutland
2014-07-18 12:05 ` Jason Cooper
1 sibling, 0 replies; 20+ messages in thread
From: Mark Rutland @ 2014-07-18 9:20 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, Jul 10, 2014 at 03:04:00AM +0100, Haojian Zhuang wrote:
> There's a little difference between ARM GIC and HiP04 GIC.
Given that we can't target interrupts correctly without this patch, and
that the GIC in a HiP04 system can't claim compatibility with any other
GIC, I'd call this a major difference.
>
> * HiP04 GIC could support 16 cores at most, and ARM GIC could support
> 8 cores at most. So the difination on GIC_DIST_TARGET registers are
> different since CPU interfaces are increased from 8-bit to 16-bit.
>
> * HiP04 GIC could support 510 interrupts at most, and ARM GIC could
> support 1020 interrupts at most.
>
> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
> ---
> Documentation/devicetree/bindings/arm/gic.txt | 1 +
> drivers/irqchip/irq-gic.c | 141 +++++++++++++++++++-------
> 2 files changed, 108 insertions(+), 34 deletions(-)
[...]
> +static bool gic_is_standard(struct gic_chip_data *gic_data)
> +{
> + return (gic_data->nr_cpu_if == 8);
> +}
> +
> +static u32 irqs_per_target_reg(struct gic_chip_data *gic_data)
> +{
> + return (32 / gic_data->nr_cpu_if);
> +}
> +
> +static u32 irq_to_target_reg(struct gic_chip_data *gic_data, u32 irq)
> +{
> + if (!gic_is_standard(gic_data))
> + irq *= 2;
If the function is called gic_is_standard, then the only thing we should
know here is whether the GIC follows the GIC standard, not how it
differs from the standard.
Please rename this function to something like gicd_has_16_bit_targets or
anything else that clearly defines what you're ttrying to derive from
it.
Thanks,
Mark.
^ permalink raw reply [flat|nested] 20+ messages in thread* [PATCH v10 01/11] irq: gic: support hip04 gic
2014-07-10 2:04 ` [PATCH v10 01/11] irq: gic: support hip04 gic Haojian Zhuang
2014-07-18 9:20 ` Mark Rutland
@ 2014-07-18 12:05 ` Jason Cooper
2014-07-18 12:44 ` Mark Rutland
1 sibling, 1 reply; 20+ messages in thread
From: Jason Cooper @ 2014-07-18 12:05 UTC (permalink / raw)
To: linux-arm-kernel
Haojian,
On Thu, Jul 10, 2014 at 10:04:00AM +0800, Haojian Zhuang wrote:
> There's a little difference between ARM GIC and HiP04 GIC.
>
> * HiP04 GIC could support 16 cores at most, and ARM GIC could support
> 8 cores at most. So the difination on GIC_DIST_TARGET registers are
> different since CPU interfaces are increased from 8-bit to 16-bit.
>
> * HiP04 GIC could support 510 interrupts at most, and ARM GIC could
> support 1020 interrupts at most.
>
> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
> ---
> Documentation/devicetree/bindings/arm/gic.txt | 1 +
> drivers/irqchip/irq-gic.c | 141 +++++++++++++++++++-------
> 2 files changed, 108 insertions(+), 34 deletions(-)
I need to apologize. This is my first full cycle maintaining irqchip
and I'm still coming up to speed. The tl;dr is, I'm just not
comfortable with the approach in this patch.
If irq-gic.c was only used by one SoC, it'd be different, but in the
scenario we have, I think it would be best if this were a separate
driver, say irq-gic-hip04.c. You can link in irq-gic-common.o to get
gic_dist_config(), and you'll be able to remove a lot of the static
functions and conditionals.
I really think it's worth the extra maintenance overhead to do it this
way.
thx,
Jason.
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v10 01/11] irq: gic: support hip04 gic
2014-07-18 12:05 ` Jason Cooper
@ 2014-07-18 12:44 ` Mark Rutland
0 siblings, 0 replies; 20+ messages in thread
From: Mark Rutland @ 2014-07-18 12:44 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, Jul 18, 2014 at 01:05:26PM +0100, Jason Cooper wrote:
> Haojian,
>
> On Thu, Jul 10, 2014 at 10:04:00AM +0800, Haojian Zhuang wrote:
> > There's a little difference between ARM GIC and HiP04 GIC.
> >
> > * HiP04 GIC could support 16 cores at most, and ARM GIC could support
> > 8 cores at most. So the difination on GIC_DIST_TARGET registers are
> > different since CPU interfaces are increased from 8-bit to 16-bit.
> >
> > * HiP04 GIC could support 510 interrupts at most, and ARM GIC could
> > support 1020 interrupts at most.
> >
> > Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
> > ---
> > Documentation/devicetree/bindings/arm/gic.txt | 1 +
> > drivers/irqchip/irq-gic.c | 141 +++++++++++++++++++-------
> > 2 files changed, 108 insertions(+), 34 deletions(-)
>
> I need to apologize. This is my first full cycle maintaining irqchip
> and I'm still coming up to speed. The tl;dr is, I'm just not
> comfortable with the approach in this patch.
>
> If irq-gic.c was only used by one SoC, it'd be different, but in the
> scenario we have, I think it would be best if this were a separate
> driver, say irq-gic-hip04.c. You can link in irq-gic-common.o to get
> gic_dist_config(), and you'll be able to remove a lot of the static
> functions and conditionals.
A better approach might be to have some function pointers with each
compatible string, and then have associated with the HiP04 compatible
string, and then have those call common (inline) function variants. The
compiler can then deal with the different variants and we don't end up
with multiple GIC drivers getting out-of-sync.
Thanks,
Mark.
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v10 02/11] ARM: mcpm: support 4 clusters
2014-07-10 2:03 [PATCH v10 00/11] enable HiP04 SoC Haojian Zhuang
2014-07-10 2:04 ` [PATCH v10 01/11] irq: gic: support hip04 gic Haojian Zhuang
@ 2014-07-10 2:04 ` Haojian Zhuang
2014-07-10 2:04 ` [PATCH v10 03/11] ARM: hisi: enable MCPM implementation Haojian Zhuang
` (8 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Haojian Zhuang @ 2014-07-10 2:04 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] 20+ messages in thread* [PATCH v10 03/11] ARM: hisi: enable MCPM implementation
2014-07-10 2:03 [PATCH v10 00/11] enable HiP04 SoC Haojian Zhuang
2014-07-10 2:04 ` [PATCH v10 01/11] irq: gic: support hip04 gic Haojian Zhuang
2014-07-10 2:04 ` [PATCH v10 02/11] ARM: mcpm: support 4 clusters Haojian Zhuang
@ 2014-07-10 2:04 ` Haojian Zhuang
2014-07-12 21:31 ` Nicolas Pitre
2014-07-10 2:04 ` [PATCH v10 04/11] ARM: hisi: enable HiP04 Haojian Zhuang
` (7 subsequent siblings)
10 siblings, 1 reply; 20+ messages in thread
From: Haojian Zhuang @ 2014-07-10 2:04 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.
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
arch/arm/mach-hisi/Makefile | 1 +
arch/arm/mach-hisi/platmcpm.c | 331 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 332 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..3befcb3
--- /dev/null
+++ b/arch/arm/mach-hisi/platmcpm.c
@@ -0,0 +1,331 @@
+/*
+ * 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/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 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 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]) {
+ hip04_cpu_table[cluster][cpu]++;
+ spin_unlock_irq(&boot_lock);
+ return 0;
+ }
+
+ 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);
+ }
+
+ 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));
+ spin_unlock_irq(&boot_lock);
+ msleep(POLL_MSEC);
+
+ return 0;
+}
+
+static void hip04_mcpm_power_down(void)
+{
+ unsigned int mpidr, cpu, cluster, data = 0;
+ bool skip_reset = 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_reset = 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_reset) {
+ data = CORE_RESET_BIT(cpu) | NEON_RESET_BIT(cpu) | \
+ CORE_DEBUG_RESET_BIT(cpu);
+ writel_relaxed(data, sysctrl + SC_CPU_RESET_REQ(cluster));
+ }
+}
+
+static int hip04_mcpm_wait_for_powerdown(unsigned int cpu, unsigned int cluster)
+{
+ unsigned int data, tries;
+
+ BUG_ON(cluster >= HIP04_MAX_CLUSTERS ||
+ cpu >= HIP04_MAX_CPUS_PER_CLUSTER);
+
+ for (tries = 0; tries < TIMEOUT_MSEC / POLL_MSEC; tries++) {
+ data = readl_relaxed(sysctrl + SC_CPU_RESET_STATUS(cluster));
+ if (!(data & CORE_RESET_STATUS(cpu))) {
+ msleep(POLL_MSEC);
+ continue;
+ }
+ return 0;
+ }
+ 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"
+ /* calculate fabric phys address */
+" adr r2, 2f \n"
+" ldmia r2, {r1, r3} \n"
+" sub r0, r2, r1 \n"
+" add r2, r0, r3 \n"
+" ldr r2, [r2] \n"
+ /* get cluster id from MPIDR */
+" mrc p15, 0, r0, c0, c0, 5 \n"
+" ubfx r1, r0, #8, #8 \n"
+" and r1, r1, #0xf \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_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;
+
+ 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;
+
+ if (of_property_read_u32(np, "bootwrapper-phys",
+ &hip04_boot.bootwrapper_phys)) {
+ pr_err("failed to get bootwrapper-phys\n");
+ ret = -EINVAL;
+ goto err;
+ }
+ if (of_property_read_u32(np, "bootwrapper-size",
+ &hip04_boot.bootwrapper_size)) {
+ pr_err("failed to get bootwrapper-size\n");
+ ret = -EINVAL;
+ goto err;
+ }
+ if (of_property_read_u32(np, "bootwrapper-magic",
+ &hip04_boot.bootwrapper_magic)) {
+ pr_err("failed to get bootwrapper-magic\n");
+ ret = -EINVAL;
+ goto err;
+ }
+ if (of_property_read_u32(np, "relocation-entry",
+ &hip04_boot.relocation_entry)) {
+ pr_err("failed to get relocation-entry\n");
+ ret = -EINVAL;
+ goto err;
+ }
+ if (of_property_read_u32(np, "relocation-size",
+ &hip04_boot.relocation_size)) {
+ pr_err("failed to get relocation-size\n");
+ ret = -EINVAL;
+ 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] 20+ messages in thread* [PATCH v10 03/11] ARM: hisi: enable MCPM implementation
2014-07-10 2:04 ` [PATCH v10 03/11] ARM: hisi: enable MCPM implementation Haojian Zhuang
@ 2014-07-12 21:31 ` Nicolas Pitre
2014-07-14 2:37 ` Haojian Zhuang
0 siblings, 1 reply; 20+ messages in thread
From: Nicolas Pitre @ 2014-07-12 21:31 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, 10 Jul 2014, Haojian Zhuang wrote:
> Multiple CPU clusters are used in Hisilicon HiP04 SoC. Now use MCPM
> framework to manage power on HiP04 SoC.
>
> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
> ---
> arch/arm/mach-hisi/Makefile | 1 +
> arch/arm/mach-hisi/platmcpm.c | 331 ++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 332 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..3befcb3
> --- /dev/null
> +++ b/arch/arm/mach-hisi/platmcpm.c
> @@ -0,0 +1,331 @@
> +/*
> + * 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/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 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 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]) {
> + hip04_cpu_table[cluster][cpu]++;
> + spin_unlock_irq(&boot_lock);
> + return 0;
> + }
> +
> + 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);
> + }
> +
> + 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));
> + spin_unlock_irq(&boot_lock);
> + msleep(POLL_MSEC);
> +
> + return 0;
> +}
> +
> +static void hip04_mcpm_power_down(void)
> +{
> + unsigned int mpidr, cpu, cluster, data = 0;
> + bool skip_reset = 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_reset = 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);
What if there is a hip04_mcpm_power_up() being called on another CPU
right here? There is a race that I illustrated in a previous email
which is still unresolved.
> +
> + if (!skip_reset) {
> + data = CORE_RESET_BIT(cpu) | NEON_RESET_BIT(cpu) | \
> + CORE_DEBUG_RESET_BIT(cpu);
> + writel_relaxed(data, sysctrl + SC_CPU_RESET_REQ(cluster));
> + }
> +}
> +
> +static int hip04_mcpm_wait_for_powerdown(unsigned int cpu, unsigned int cluster)
> +{
> + unsigned int data, tries;
> +
> + BUG_ON(cluster >= HIP04_MAX_CLUSTERS ||
> + cpu >= HIP04_MAX_CPUS_PER_CLUSTER);
> +
> + for (tries = 0; tries < TIMEOUT_MSEC / POLL_MSEC; tries++) {
> + data = readl_relaxed(sysctrl + SC_CPU_RESET_STATUS(cluster));
> + if (!(data & CORE_RESET_STATUS(cpu))) {
> + msleep(POLL_MSEC);
> + continue;
> + }
> + return 0;
> + }
> + 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"
> + /* calculate fabric phys address */
> +" adr r2, 2f \n"
> +" ldmia r2, {r1, r3} \n"
> +" sub r0, r2, r1 \n"
> +" add r2, r0, r3 \n"
> +" ldr r2, [r2] \n"
You may replace the above 2 instructions with "ldr r2, [r0, r3]".
> + /* get cluster id from MPIDR */
> +" mrc p15, 0, r0, c0, c0, 5 \n"
> +" ubfx r1, r0, #8, #8 \n"
> +" and r1, r1, #0xf \n"
You don't need the "and" here. It is implicit in ubfx.
> + /* 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"
Instead of running all this code all the time, you could simply test r0
at the very beginning and if it is not equal to 1 then return
immediately. If it is 1 that means the CPU executing this code is the
first one to run in the cluster, in which case you also don't have to
test if the cluster snoop is already enabled here.
> +" 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"
> + );
> +}
Of course you will also have to enable the snoops for the current
cluster in hip04_cpu_table_init() as well.
> +
> +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_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;
> +
> + 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;
> +
> + if (of_property_read_u32(np, "bootwrapper-phys",
> + &hip04_boot.bootwrapper_phys)) {
> + pr_err("failed to get bootwrapper-phys\n");
> + ret = -EINVAL;
> + goto err;
> + }
> + if (of_property_read_u32(np, "bootwrapper-size",
> + &hip04_boot.bootwrapper_size)) {
> + pr_err("failed to get bootwrapper-size\n");
> + ret = -EINVAL;
> + goto err;
> + }
> + if (of_property_read_u32(np, "bootwrapper-magic",
> + &hip04_boot.bootwrapper_magic)) {
> + pr_err("failed to get bootwrapper-magic\n");
> + ret = -EINVAL;
> + goto err;
> + }
> + if (of_property_read_u32(np, "relocation-entry",
> + &hip04_boot.relocation_entry)) {
> + pr_err("failed to get relocation-entry\n");
> + ret = -EINVAL;
> + goto err;
> + }
> + if (of_property_read_u32(np, "relocation-size",
> + &hip04_boot.relocation_size)) {
> + pr_err("failed to get relocation-size\n");
> + ret = -EINVAL;
> + 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 [flat|nested] 20+ messages in thread* [PATCH v10 03/11] ARM: hisi: enable MCPM implementation
2014-07-12 21:31 ` Nicolas Pitre
@ 2014-07-14 2:37 ` Haojian Zhuang
2014-07-14 9:41 ` Nicolas Pitre
0 siblings, 1 reply; 20+ messages in thread
From: Haojian Zhuang @ 2014-07-14 2:37 UTC (permalink / raw)
To: linux-arm-kernel
On 13 July 2014 05:31, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> On Thu, 10 Jul 2014, Haojian Zhuang wrote:
>
>> Multiple CPU clusters are used in Hisilicon HiP04 SoC. Now use MCPM
>> framework to manage power on HiP04 SoC.
>>
>> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
>> ---
>> arch/arm/mach-hisi/Makefile | 1 +
>> arch/arm/mach-hisi/platmcpm.c | 331 ++++++++++++++++++++++++++++++++++++++++++
>> 2 files changed, 332 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
>> +
>> +static void hip04_mcpm_power_down(void)
>> +{
>> + unsigned int mpidr, cpu, cluster, data = 0;
>> + bool skip_reset = 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_reset = 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);
>
> What if there is a hip04_mcpm_power_up() being called on another CPU
> right here? There is a race that I illustrated in a previous email
> which is still unresolved.
>
Thanks for your reminder again. I'll move it into the protection.
>> +
>> + if (!skip_reset) {
>> + data = CORE_RESET_BIT(cpu) | NEON_RESET_BIT(cpu) | \
>> + CORE_DEBUG_RESET_BIT(cpu);
>> + writel_relaxed(data, sysctrl + SC_CPU_RESET_REQ(cluster));
>> + }
>> +}
>> +
>> +static int hip04_mcpm_wait_for_powerdown(unsigned int cpu, unsigned int cluster)
>> +{
>> + unsigned int data, tries;
>> +
>> + BUG_ON(cluster >= HIP04_MAX_CLUSTERS ||
>> + cpu >= HIP04_MAX_CPUS_PER_CLUSTER);
>> +
>> + for (tries = 0; tries < TIMEOUT_MSEC / POLL_MSEC; tries++) {
>> + data = readl_relaxed(sysctrl + SC_CPU_RESET_STATUS(cluster));
>> + if (!(data & CORE_RESET_STATUS(cpu))) {
>> + msleep(POLL_MSEC);
>> + continue;
>> + }
>> + return 0;
>> + }
>> + 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"
>> + /* calculate fabric phys address */
>> +" adr r2, 2f \n"
>> +" ldmia r2, {r1, r3} \n"
>> +" sub r0, r2, r1 \n"
>> +" add r2, r0, r3 \n"
>> +" ldr r2, [r2] \n"
>
> You may replace the above 2 instructions with "ldr r2, [r0, r3]".
>
OK.
>> + /* get cluster id from MPIDR */
>> +" mrc p15, 0, r0, c0, c0, 5 \n"
>> +" ubfx r1, r0, #8, #8 \n"
>> +" and r1, r1, #0xf \n"
>
> You don't need the "and" here. It is implicit in ubfx.
>
OK.
>> + /* 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"
>
> Instead of running all this code all the time, you could simply test r0
> at the very beginning and if it is not equal to 1 then return
> immediately. If it is 1 that means the CPU executing this code is the
> first one to run in the cluster, in which case you also don't have to
> test if the cluster snoop is already enabled here.
>
Since I need to enable the cluster snoop for cluster 0. At this time,
it's not enabled although core0 is running.
>> +" 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"
>> + );
>> +}
>
> Of course you will also have to enable the snoops for the current
> cluster in hip04_cpu_table_init() as well.
It means that I need to reserve the copy to enable the snoop in c code
for cluster 0. Is it right?
>
>
>> +
>> +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_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;
>> +
>> + 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;
>> +
>> + if (of_property_read_u32(np, "bootwrapper-phys",
>> + &hip04_boot.bootwrapper_phys)) {
>> + pr_err("failed to get bootwrapper-phys\n");
>> + ret = -EINVAL;
>> + goto err;
>> + }
>> + if (of_property_read_u32(np, "bootwrapper-size",
>> + &hip04_boot.bootwrapper_size)) {
>> + pr_err("failed to get bootwrapper-size\n");
>> + ret = -EINVAL;
>> + goto err;
>> + }
>> + if (of_property_read_u32(np, "bootwrapper-magic",
>> + &hip04_boot.bootwrapper_magic)) {
>> + pr_err("failed to get bootwrapper-magic\n");
>> + ret = -EINVAL;
>> + goto err;
>> + }
>> + if (of_property_read_u32(np, "relocation-entry",
>> + &hip04_boot.relocation_entry)) {
>> + pr_err("failed to get relocation-entry\n");
>> + ret = -EINVAL;
>> + goto err;
>> + }
>> + if (of_property_read_u32(np, "relocation-size",
>> + &hip04_boot.relocation_size)) {
>> + pr_err("failed to get relocation-size\n");
>> + ret = -EINVAL;
>> + 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 [flat|nested] 20+ messages in thread* [PATCH v10 03/11] ARM: hisi: enable MCPM implementation
2014-07-14 2:37 ` Haojian Zhuang
@ 2014-07-14 9:41 ` Nicolas Pitre
0 siblings, 0 replies; 20+ messages in thread
From: Nicolas Pitre @ 2014-07-14 9:41 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, 14 Jul 2014, Haojian Zhuang wrote:
> On 13 July 2014 05:31, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> > On Thu, 10 Jul 2014, Haojian Zhuang wrote:
> >
> >> +static void __naked hip04_mcpm_power_up_setup(unsigned int affinity_level)
> >> +{
> >> + asm volatile (" \n"
> >> + /* calculate fabric phys address */
> >> +" adr r2, 2f \n"
> >> +" ldmia r2, {r1, r3} \n"
> >> +" sub r0, r2, r1 \n"
> >> +" add r2, r0, r3 \n"
> >> +" ldr r2, [r2] \n"
> >
> > You may replace the above 2 instructions with "ldr r2, [r0, r3]".
> >
> OK.
>
> >> + /* get cluster id from MPIDR */
> >> +" mrc p15, 0, r0, c0, c0, 5 \n"
> >> +" ubfx r1, r0, #8, #8 \n"
> >> +" and r1, r1, #0xf \n"
> >
> > You don't need the "and" here. It is implicit in ubfx.
> >
> OK.
>
> >> + /* 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"
> >
> > Instead of running all this code all the time, you could simply test r0
> > at the very beginning and if it is not equal to 1 then return
> > immediately. If it is 1 that means the CPU executing this code is the
> > first one to run in the cluster, in which case you also don't have to
> > test if the cluster snoop is already enabled here.
> >
>
> Since I need to enable the cluster snoop for cluster 0. At this time,
> it's not enabled although core0 is running.
Yes, hence my next comment.
> >> +" 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"
> >> + );
> >> +}
> >
> > Of course you will also have to enable the snoops for the current
> > cluster in hip04_cpu_table_init() as well.
>
> It means that I need to reserve the copy to enable the snoop in c code
> for cluster 0. Is it right?
Yes. And it can be __init just like hip04_cpu_table_init().
Nicolas
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v10 04/11] ARM: hisi: enable HiP04
2014-07-10 2:03 [PATCH v10 00/11] enable HiP04 SoC Haojian Zhuang
` (2 preceding siblings ...)
2014-07-10 2:04 ` [PATCH v10 03/11] ARM: hisi: enable MCPM implementation Haojian Zhuang
@ 2014-07-10 2:04 ` Haojian Zhuang
2014-07-28 11:08 ` Arnd Bergmann
2014-07-10 2:04 ` [PATCH v10 05/11] document: dt: add the binding on HiP04 Haojian Zhuang
` (6 subsequent siblings)
10 siblings, 1 reply; 20+ messages in thread
From: Haojian Zhuang @ 2014-07-10 2:04 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 | 8 ++++++++
arch/arm/mach-hisi/hisilicon.c | 9 +++++++++
arch/arm/mach-hisi/platmcpm.c | 1 -
3 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-hisi/Kconfig b/arch/arm/mach-hisi/Kconfig
index 90fdbb4..a458f28 100644
--- a/arch/arm/mach-hisi/Kconfig
+++ b/arch/arm/mach-hisi/Kconfig
@@ -19,6 +19,14 @@ config ARCH_HI3xxx
help
Support for Hisilicon Hi36xx SoC family
+config ARCH_HIP04
+ bool "Hisilicon HiP04 Cortex A15 family" if ARCH_MULTI_V7
+ 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 e842ca9..938cdba 100644
--- a/arch/arm/mach-hisi/hisilicon.c
+++ b/arch/arm/mach-hisi/hisilicon.c
@@ -114,3 +114,12 @@ DT_MACHINE_START(HIX5HD2_DT, "Hisilicon HIX5HD2 (Flattened Device Tree)")
.smp = smp_ops(hix5hd2_smp_ops),
.restart = hi3xxx_restart,
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
diff --git a/arch/arm/mach-hisi/platmcpm.c b/arch/arm/mach-hisi/platmcpm.c
index 3befcb3..d903d75 100644
--- a/arch/arm/mach-hisi/platmcpm.c
+++ b/arch/arm/mach-hisi/platmcpm.c
@@ -116,7 +116,6 @@ static int hip04_mcpm_power_up(unsigned int cpu, unsigned int cluster)
CORE_DEBUG_RESET_BIT(cpu);
writel_relaxed(data, sysctrl + SC_CPU_RESET_DREQ(cluster));
spin_unlock_irq(&boot_lock);
- msleep(POLL_MSEC);
return 0;
}
--
1.9.1
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v10 04/11] ARM: hisi: enable HiP04
2014-07-10 2:04 ` [PATCH v10 04/11] ARM: hisi: enable HiP04 Haojian Zhuang
@ 2014-07-28 11:08 ` Arnd Bergmann
2014-07-28 11:41 ` Haojian Zhuang
0 siblings, 1 reply; 20+ messages in thread
From: Arnd Bergmann @ 2014-07-28 11:08 UTC (permalink / raw)
To: linux-arm-kernel
On Thursday 10 July 2014, Haojian Zhuang wrote:
> --- a/arch/arm/mach-hisi/platmcpm.c
> +++ b/arch/arm/mach-hisi/platmcpm.c
> @@ -116,7 +116,6 @@ static int hip04_mcpm_power_up(unsigned int cpu, unsigned int cluster)
> CORE_DEBUG_RESET_BIT(cpu);
> writel_relaxed(data, sysctrl + SC_CPU_RESET_DREQ(cluster));
> spin_unlock_irq(&boot_lock);
> - msleep(POLL_MSEC);
>
> return 0;
> }
Is this change intentional? It seems like it should belong into the earlier patch
that introduces this file.
Arnd
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v10 04/11] ARM: hisi: enable HiP04
2014-07-28 11:08 ` Arnd Bergmann
@ 2014-07-28 11:41 ` Haojian Zhuang
0 siblings, 0 replies; 20+ messages in thread
From: Haojian Zhuang @ 2014-07-28 11:41 UTC (permalink / raw)
To: linux-arm-kernel
On 28 July 2014 19:08, Arnd Bergmann <arnd@arndb.de> wrote:
> On Thursday 10 July 2014, Haojian Zhuang wrote:
>> --- a/arch/arm/mach-hisi/platmcpm.c
>> +++ b/arch/arm/mach-hisi/platmcpm.c
>> @@ -116,7 +116,6 @@ static int hip04_mcpm_power_up(unsigned int cpu, unsigned int cluster)
>> CORE_DEBUG_RESET_BIT(cpu);
>> writel_relaxed(data, sysctrl + SC_CPU_RESET_DREQ(cluster));
>> spin_unlock_irq(&boot_lock);
>> - msleep(POLL_MSEC);
>>
>> return 0;
>> }
>
> Is this change intentional? It seems like it should belong into the earlier patch
> that introduces this file.
>
> Arnd
Yes, it should belong to the earlier patch. And it's fixed in v12 or v13.
Regards
Haojian
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v10 05/11] document: dt: add the binding on HiP04
2014-07-10 2:03 [PATCH v10 00/11] enable HiP04 SoC Haojian Zhuang
` (3 preceding siblings ...)
2014-07-10 2:04 ` [PATCH v10 04/11] ARM: hisi: enable HiP04 Haojian Zhuang
@ 2014-07-10 2:04 ` Haojian Zhuang
2014-07-10 2:04 ` [PATCH v10 06/11] document: dt: add the binding on HiP04 clock Haojian Zhuang
` (5 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Haojian Zhuang @ 2014-07-10 2:04 UTC (permalink / raw)
To: linux-arm-kernel
Add bootwrapper-phys, bootwrapper-size, bootwrapper-magic properties for
Hisilicon HiP04 SoC.
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
.../devicetree/bindings/arm/hisilicon/hisilicon.txt | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
index df0a452..5024992 100644
--- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
+++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
@@ -4,6 +4,10 @@ Hisilicon Platforms Device Tree Bindings
Hi4511 Board
Required root node properties:
- compatible = "hisilicon,hi3620-hi4511";
+HiP04 D01 Board
+Required root node properties:
+ - compatible = "hisilicon,hip04-d01";
+
Hisilicon system controller
@@ -19,6 +23,15 @@ Optional properties:
If reg value is not zero, cpun exit wfi and go
- resume-offset : offset in sysctrl for notifying cpu0 when resume
- reboot-offset : offset in sysctrl for system reboot
+- relocation-entry : relocation address of secondary cpu boot code
+- relocation-size : relocation size of secondary cpu boot code
+- bootwrapper-phys : physical address of boot wrapper
+- bootwrapper-size : size of boot wrapper
+- bootwrapper-magic : magic number for secondary cpu in boot wrapper
+The memory area of [bootwrapper-phys : bootwrapper-phys+bootwrapper-size]
+should be reserved. This should be set in /memreserve/ node in DTS file.
+bootwrapper-phys, bootwrapper-size, bootwrapper-magic is used in HiP04
+DTS file.
Example:
@@ -31,6 +44,7 @@ Example:
reboot-offset = <0x4>;
};
+
PCTRL: Peripheral misc control register
Required Properties:
@@ -44,3 +58,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] 20+ messages in thread* [PATCH v10 06/11] document: dt: add the binding on HiP04 clock
2014-07-10 2:03 [PATCH v10 00/11] enable HiP04 SoC Haojian Zhuang
` (4 preceding siblings ...)
2014-07-10 2:04 ` [PATCH v10 05/11] document: dt: add the binding on HiP04 Haojian Zhuang
@ 2014-07-10 2:04 ` Haojian Zhuang
2014-07-10 2:04 ` [PATCH v10 07/11] ARM: dts: append hip04 dts Haojian Zhuang
` (4 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Haojian Zhuang @ 2014-07-10 2:04 UTC (permalink / raw)
To: linux-arm-kernel
The DT binding for Hisilicon HiP04 clock driver.
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
.../devicetree/bindings/clock/hip04-clock.txt | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/hip04-clock.txt
diff --git a/Documentation/devicetree/bindings/clock/hip04-clock.txt b/Documentation/devicetree/bindings/clock/hip04-clock.txt
new file mode 100644
index 0000000..4d31ae3
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/hip04-clock.txt
@@ -0,0 +1,20 @@
+* Hisilicon HiP04 Clock Controller
+
+The HiP04 clock controller generates and supplies clock to various
+controllers within the HiP04 SoC.
+
+Required Properties:
+
+- compatible: should be one of the following.
+ - "hisilicon,hip04-clock" - controller compatible with HiP04 SoC.
+
+- reg: physical base address of the controller and length of memory mapped
+ region.
+
+- #clock-cells: should be 1.
+
+
+Each clock is assigned an identifier and client nodes use this identifier
+to specify the clock which they consume.
+
+All these identifier could be found in <dt-bindings/clock/hip04-clock.h>.
--
1.9.1
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v10 07/11] ARM: dts: append hip04 dts
2014-07-10 2:03 [PATCH v10 00/11] enable HiP04 SoC Haojian Zhuang
` (5 preceding siblings ...)
2014-07-10 2:04 ` [PATCH v10 06/11] document: dt: add the binding on HiP04 clock Haojian Zhuang
@ 2014-07-10 2:04 ` Haojian Zhuang
2014-07-10 2:04 ` [PATCH v10 08/11] ARM: config: append lpae configuration Haojian Zhuang
` (3 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Haojian Zhuang @ 2014-07-10 2:04 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 | 39 ++++++
arch/arm/boot/dts/hip04.dtsi | 267 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 307 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..661c8e5
--- /dev/null
+++ b/arch/arm/boot/dts/hip04-d01.dts
@@ -0,0 +1,39 @@
+/*
+ * 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/;
+
+/* For bootwrapper */
+/memreserve/ 0x10c00000 0x00010000;
+
+#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>;
+ };
+
+ memory at 00000004,c0000000 {
+ device_type = "memory";
+ reg = <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..30942be
--- /dev/null
+++ b/arch/arm/boot/dts/hip04.dtsi
@@ -0,0 +1,267 @@
+/*
+ * 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
+ * publishhed by the Free Software Foundation.
+ */
+
+#include <dt-bindings/clock/hip04-clock.h>
+
+/ {
+ /* 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>;
+ };
+ };
+
+ clock: clock {
+ compatible = "hisilicon,hip04-clock";
+ /* dummy register.
+ * Don't need to access clock registers since they're
+ * configured in firmware already.
+ */
+ reg = <0 0 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ timer {
+ compatible = "arm,armv7-timer";
+ interrupt-parent = <&gic>;
+ interrupts = <1 13 0xf08>,
+ <1 14 0xf08>,
+ <1 11 0xf08>,
+ <1 10 0xf08>;
+ };
+
+ 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-gic";
+ #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>;
+ relocation-entry = <0xe0000100>;
+ relocation-size = <0x1000>;
+ bootwrapper-phys = <0x10c00000>;
+ bootwrapper-size = <0x10000>;
+ bootwrapper-magic = <0xa5a5a5a5>;
+ };
+
+ 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 = <&clock HIP04_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 = <&clock HIP04_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] 20+ messages in thread* [PATCH v10 08/11] ARM: config: append lpae configuration
2014-07-10 2:03 [PATCH v10 00/11] enable HiP04 SoC Haojian Zhuang
` (6 preceding siblings ...)
2014-07-10 2:04 ` [PATCH v10 07/11] ARM: dts: append hip04 dts Haojian Zhuang
@ 2014-07-10 2:04 ` Haojian Zhuang
2014-07-10 2:04 ` [PATCH v10 09/11] ARM: config: append hip04_defconfig Haojian Zhuang
` (2 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Haojian Zhuang @ 2014-07-10 2:04 UTC (permalink / raw)
To: linux-arm-kernel
Append multi_v7_lpae_config. In this default configuration,
CONFIG_ARCH_MULTI_V6 is disabled. CONFIG_ARM_LPAE is enabled.
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
arch/arm/configs/multi_v7_lpae_defconfig | 343 +++++++++++++++++++++++++++++++
1 file changed, 343 insertions(+)
create mode 100644 arch/arm/configs/multi_v7_lpae_defconfig
diff --git a/arch/arm/configs/multi_v7_lpae_defconfig b/arch/arm/configs/multi_v7_lpae_defconfig
new file mode 100644
index 0000000..891937b
--- /dev/null
+++ b/arch/arm/configs/multi_v7_lpae_defconfig
@@ -0,0 +1,343 @@
+CONFIG_SYSVIPC=y
+CONFIG_FHANDLE=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EMBEDDED=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ARCH_MULTI_V6 is not set
+CONFIG_ARCH_MULTI_V7=y
+CONFIG_ARM_LPAE=y
+CONFIG_ARCH_MVEBU=y
+CONFIG_MACH_ARMADA_XP=y
+CONFIG_ARCH_BCM=y
+CONFIG_ARCH_BCM_5301X=y
+CONFIG_ARCH_BCM_MOBILE=y
+CONFIG_GPIO_PCA953X=y
+CONFIG_ARCH_HIGHBANK=y
+CONFIG_ARCH_HISI=y
+CONFIG_ARCH_HIP04=y
+CONFIG_ARCH_KEYSTONE=y
+CONFIG_ARCH_MXC=y
+CONFIG_MACH_IMX51_DT=y
+CONFIG_SOC_IMX53=y
+CONFIG_SOC_IMX6Q=y
+CONFIG_SOC_IMX6SL=y
+CONFIG_SOC_VF610=y
+CONFIG_ARCH_OMAP3=y
+CONFIG_ARCH_OMAP4=y
+CONFIG_SOC_OMAP5=y
+CONFIG_SOC_AM33XX=y
+CONFIG_SOC_DRA7XX=y
+CONFIG_SOC_AM43XX=y
+CONFIG_ARCH_QCOM=y
+CONFIG_ARCH_MSM8X60=y
+CONFIG_ARCH_MSM8960=y
+CONFIG_ARCH_MSM8974=y
+CONFIG_ARCH_ROCKCHIP=y
+CONFIG_ARCH_SOCFPGA=y
+CONFIG_PLAT_SPEAR=y
+CONFIG_ARCH_SPEAR13XX=y
+CONFIG_MACH_SPEAR1310=y
+CONFIG_MACH_SPEAR1340=y
+CONFIG_ARCH_STI=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_ARCH_SIRF=y
+CONFIG_ARCH_TEGRA=y
+CONFIG_ARCH_TEGRA_2x_SOC=y
+CONFIG_ARCH_TEGRA_3x_SOC=y
+CONFIG_ARCH_TEGRA_114_SOC=y
+CONFIG_ARCH_TEGRA_124_SOC=y
+CONFIG_TEGRA_EMC_SCALING_ENABLE=y
+CONFIG_ARCH_U8500=y
+CONFIG_MACH_HREFV60=y
+CONFIG_MACH_SNOWBALL=y
+CONFIG_MACH_UX500_DT=y
+CONFIG_ARCH_VEXPRESS=y
+CONFIG_ARCH_VEXPRESS_CA9X4=y
+CONFIG_ARCH_VIRT=y
+CONFIG_ARCH_WM8850=y
+CONFIG_ARCH_ZYNQ=y
+CONFIG_NEON=y
+CONFIG_TRUSTED_FOUNDATIONS=y
+CONFIG_PCI=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_MVEBU=y
+CONFIG_PCI_TEGRA=y
+CONFIG_SMP=y
+CONFIG_HIGHMEM=y
+CONFIG_HIGHPTE=y
+CONFIG_CMA=y
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_KEXEC=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_CPU_IDLE=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_CFG80211=m
+CONFIG_MAC80211=m
+CONFIG_RFKILL=y
+CONFIG_RFKILL_INPUT=y
+CONFIG_RFKILL_GPIO=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=64
+CONFIG_OMAP_OCP2SCP=y
+CONFIG_MTD=y
+CONFIG_MTD_M25P80=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_ICS932S401=y
+CONFIG_APDS9802ALS=y
+CONFIG_ISL29003=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_ATA=y
+CONFIG_SATA_AHCI_PLATFORM=y
+CONFIG_SATA_HIGHBANK=y
+CONFIG_SATA_MV=y
+CONFIG_NETDEVICES=y
+CONFIG_SUN4I_EMAC=y
+CONFIG_NET_CALXEDA_XGMAC=y
+CONFIG_MV643XX_ETH=y
+CONFIG_MVNETA=y
+CONFIG_KS8851=y
+CONFIG_R8169=y
+CONFIG_SMSC911X=y
+CONFIG_STMMAC_ETH=y
+CONFIG_TI_CPSW=y
+CONFIG_AT803X_PHY=y
+CONFIG_MARVELL_PHY=y
+CONFIG_ICPLUS_PHY=y
+CONFIG_USB_PEGASUS=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_SMSC75XX=y
+CONFIG_USB_NET_SMSC95XX=y
+CONFIG_BRCMFMAC=m
+CONFIG_RT2X00=m
+CONFIG_RT2800USB=m
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_TEGRA=y
+CONFIG_KEYBOARD_SPEAR=y
+CONFIG_KEYBOARD_CROS_EC=y
+CONFIG_MOUSE_PS2_ELANTECH=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_MPU3050=y
+CONFIG_SERIO_AMBAKMI=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_DW=y
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+CONFIG_SERIAL_SIRFSOC=y
+CONFIG_SERIAL_SIRFSOC_CONSOLE=y
+CONFIG_SERIAL_TEGRA=y
+CONFIG_SERIAL_IMX=y
+CONFIG_SERIAL_IMX_CONSOLE=y
+CONFIG_SERIAL_MSM=y
+CONFIG_SERIAL_MSM_CONSOLE=y
+CONFIG_SERIAL_VT8500=y
+CONFIG_SERIAL_VT8500_CONSOLE=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SERIAL_OMAP=y
+CONFIG_SERIAL_OMAP_CONSOLE=y
+CONFIG_SERIAL_XILINX_PS_UART=y
+CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y
+CONFIG_SERIAL_FSL_LPUART=y
+CONFIG_SERIAL_FSL_LPUART_CONSOLE=y
+CONFIG_SERIAL_ST_ASC=y
+CONFIG_SERIAL_ST_ASC_CONSOLE=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MUX=y
+CONFIG_I2C_MUX_PCA954x=y
+CONFIG_I2C_MUX_PINCTRL=y
+CONFIG_I2C_DESIGNWARE_PLATFORM=y
+CONFIG_I2C_MV64XXX=y
+CONFIG_I2C_SIRF=y
+CONFIG_I2C_TEGRA=y
+CONFIG_SPI=y
+CONFIG_SPI_OMAP24XX=y
+CONFIG_SPI_ORION=y
+CONFIG_SPI_PL022=y
+CONFIG_SPI_SIRF=y
+CONFIG_SPI_TEGRA114=y
+CONFIG_SPI_TEGRA20_SFLASH=y
+CONFIG_SPI_TEGRA20_SLINK=y
+CONFIG_PINCTRL_AS3722=y
+CONFIG_PINCTRL_PALMAS=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_GENERIC_PLATFORM=y
+CONFIG_GPIO_PCA953X_IRQ=y
+CONFIG_GPIO_TWL4030=y
+CONFIG_GPIO_PALMAS=y
+CONFIG_GPIO_TPS6586X=y
+CONFIG_GPIO_TPS65910=y
+CONFIG_BATTERY_SBS=y
+CONFIG_CHARGER_TPS65090=y
+CONFIG_POWER_RESET_AS3722=y
+CONFIG_POWER_RESET_GPIO=y
+CONFIG_SENSORS_LM90=y
+CONFIG_THERMAL=y
+CONFIG_DOVE_THERMAL=y
+CONFIG_ARMADA_THERMAL=y
+CONFIG_WATCHDOG=y
+CONFIG_ORION_WATCHDOG=y
+CONFIG_MFD_AS3722=y
+CONFIG_MFD_CROS_EC=y
+CONFIG_MFD_CROS_EC_SPI=y
+CONFIG_MFD_MAX8907=y
+CONFIG_MFD_PALMAS=y
+CONFIG_MFD_TPS65090=y
+CONFIG_MFD_TPS6586X=y
+CONFIG_MFD_TPS65910=y
+CONFIG_REGULATOR_VIRTUAL_CONSUMER=y
+CONFIG_REGULATOR_AB8500=y
+CONFIG_REGULATOR_AS3722=y
+CONFIG_REGULATOR_GPIO=y
+CONFIG_REGULATOR_MAX8907=y
+CONFIG_REGULATOR_PALMAS=y
+CONFIG_REGULATOR_TPS51632=y
+CONFIG_REGULATOR_TPS62360=y
+CONFIG_REGULATOR_TPS65090=y
+CONFIG_REGULATOR_TPS6586X=y
+CONFIG_REGULATOR_TPS65910=y
+CONFIG_REGULATOR_TWL4030=y
+CONFIG_REGULATOR_VEXPRESS=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_USB_SUPPORT=y
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_USB_GSPCA=y
+CONFIG_DRM=y
+CONFIG_DRM_TEGRA=y
+CONFIG_DRM_PANEL_SIMPLE=y
+CONFIG_FB_ARMCLCD=y
+CONFIG_FB_WM8505=y
+CONFIG_FB_SIMPLE=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_TEGRA=y
+CONFIG_SND_SOC_TEGRA_RT5640=y
+CONFIG_SND_SOC_TEGRA_WM8753=y
+CONFIG_SND_SOC_TEGRA_WM8903=y
+CONFIG_SND_SOC_TEGRA_TRIMSLICE=y
+CONFIG_SND_SOC_TEGRA_ALC5632=y
+CONFIG_SND_SOC_TEGRA_MAX98090=y
+CONFIG_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_TEGRA=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_ISP1760_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_CHIPIDEA=y
+CONFIG_USB_CHIPIDEA_HOST=y
+CONFIG_AB8500_USB=y
+CONFIG_OMAP_USB3=y
+CONFIG_SAMSUNG_USB2PHY=y
+CONFIG_SAMSUNG_USB3PHY=y
+CONFIG_USB_GPIO_VBUS=y
+CONFIG_USB_ISP1301=y
+CONFIG_USB_MXS_PHY=y
+CONFIG_MMC=y
+CONFIG_MMC_BLOCK_MINORS=16
+CONFIG_MMC_ARMMMCI=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_ESDHC_IMX=y
+CONFIG_MMC_SDHCI_TEGRA=y
+CONFIG_MMC_SDHCI_DOVE=y
+CONFIG_MMC_SDHCI_SPEAR=y
+CONFIG_MMC_SDHCI_BCM_KONA=y
+CONFIG_MMC_OMAP=y
+CONFIG_MMC_OMAP_HS=y
+CONFIG_MMC_MVSDIO=y
+CONFIG_EDAC=y
+CONFIG_EDAC_MM_EDAC=y
+CONFIG_EDAC_HIGHBANK_MC=y
+CONFIG_EDAC_HIGHBANK_L2=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AS3722=y
+CONFIG_RTC_DRV_MAX8907=y
+CONFIG_RTC_DRV_PALMAS=y
+CONFIG_RTC_DRV_TWL4030=y
+CONFIG_RTC_DRV_TPS6586X=y
+CONFIG_RTC_DRV_TPS65910=y
+CONFIG_RTC_DRV_EM3027=y
+CONFIG_RTC_DRV_PL031=y
+CONFIG_RTC_DRV_VT8500=y
+CONFIG_RTC_DRV_MV=y
+CONFIG_RTC_DRV_TEGRA=y
+CONFIG_DMADEVICES=y
+CONFIG_DW_DMAC=y
+CONFIG_MV_XOR=y
+CONFIG_TEGRA20_APB_DMA=y
+CONFIG_STE_DMA40=y
+CONFIG_SIRF_DMA=y
+CONFIG_TI_EDMA=y
+CONFIG_PL330_DMA=y
+CONFIG_IMX_SDMA=y
+CONFIG_IMX_DMA=y
+CONFIG_MXS_DMA=y
+CONFIG_DMA_OMAP=y
+CONFIG_STAGING=y
+CONFIG_SENSORS_ISL29018=y
+CONFIG_SENSORS_ISL29028=y
+CONFIG_MFD_NVEC=y
+CONFIG_KEYBOARD_NVEC=y
+CONFIG_SERIO_NVEC_PS2=y
+CONFIG_NVEC_POWER=y
+CONFIG_COMMON_CLK_QCOM=y
+CONFIG_MSM_GCC_8660=y
+CONFIG_MSM_MMCC_8960=y
+CONFIG_MSM_MMCC_8974=y
+CONFIG_TEGRA_IOMMU_GART=y
+CONFIG_TEGRA_IOMMU_SMMU=y
+CONFIG_MEMORY=y
+CONFIG_IIO=y
+CONFIG_AK8975=y
+CONFIG_PWM=y
+CONFIG_PWM_TEGRA=y
+CONFIG_PWM_VT8500=y
+CONFIG_OMAP_USB2=y
+CONFIG_EXT4_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_SQUASHFS_XZ=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_MAGIC_SYSRQ=y
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_CRYPTO_DEV_TEGRA_AES=y
--
1.9.1
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v10 09/11] ARM: config: append hip04_defconfig
2014-07-10 2:03 [PATCH v10 00/11] enable HiP04 SoC Haojian Zhuang
` (7 preceding siblings ...)
2014-07-10 2:04 ` [PATCH v10 08/11] ARM: config: append lpae configuration Haojian Zhuang
@ 2014-07-10 2:04 ` Haojian Zhuang
2014-07-10 2:04 ` [PATCH v10 10/11] ARM: hisi: enable erratum 798181 of A15 on HiP04 Haojian Zhuang
2014-07-10 2:04 ` [PATCH v10 11/11] virt: arm: support hip04 gic Haojian Zhuang
10 siblings, 0 replies; 20+ messages in thread
From: Haojian Zhuang @ 2014-07-10 2:04 UTC (permalink / raw)
To: linux-arm-kernel
Select HiP04 SoC configuration by hip04_defconfig.
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
arch/arm/configs/hip04_defconfig | 74 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 74 insertions(+)
create mode 100644 arch/arm/configs/hip04_defconfig
diff --git a/arch/arm/configs/hip04_defconfig b/arch/arm/configs/hip04_defconfig
new file mode 100644
index 0000000..5c471b2
--- /dev/null
+++ b/arch/arm/configs/hip04_defconfig
@@ -0,0 +1,74 @@
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_RD_GZIP=y
+# CONFIG_ARCH_MULTI_V6 is not set
+CONFIG_ARCH_MULTI_V7=y
+CONFIG_ARCH_HISI=y
+CONFIG_ARCH_HIP04=y
+CONFIG_ARM_LPAE=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=16
+CONFIG_MCPM=y
+CONFIG_MCPM_QUAD_CLUSTER=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER=y
+CONFIG_HIGHMEM=y
+CONFIG_VFP=y
+CONFIG_NEON=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=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=8
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_SD=y
+CONFIG_ATA=y
+CONFIG_SATA_AHCI_PLATFORM=y
+CONFIG_NETDEVICES=y
+CONFIG_SERIAL_8250=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_OF_PLATFORM=y
+CONFIG_I2C_DESIGNWARE_PLATFORM=y
+CONFIG_PINCTRL_SINGLE=y
+CONFIG_GPIO_GENERIC_PLATFORM=y
+CONFIG_REGULATOR_GPIO=y
+CONFIG_DRM=y
+CONFIG_FB_SIMPLE=y
+CONFIG_RTC_CLASS=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_DEBUG_LL=y
+CONFIG_DEBUG_UART_8250=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_DEBUG_USER=y
+CONFIG_VIRTUALIZATION=y
+CONFIG_KVM=y
+CONFIG_KVM_ARM_HOST=y
+CONFIG_KVM_ARM_MAX_VCPUS=4
+CONFIG_KVM_ARM_VGIC=y
--
1.9.1
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v10 10/11] ARM: hisi: enable erratum 798181 of A15 on HiP04
2014-07-10 2:03 [PATCH v10 00/11] enable HiP04 SoC Haojian Zhuang
` (8 preceding siblings ...)
2014-07-10 2:04 ` [PATCH v10 09/11] ARM: config: append hip04_defconfig Haojian Zhuang
@ 2014-07-10 2:04 ` Haojian Zhuang
2014-07-10 2:04 ` [PATCH v10 11/11] virt: arm: support hip04 gic Haojian Zhuang
10 siblings, 0 replies; 20+ messages in thread
From: Haojian Zhuang @ 2014-07-10 2:04 UTC (permalink / raw)
To: linux-arm-kernel
From: Kefeng Wang <kefeng.wang@linaro.org>
The commit 93dc688 (ARM: 7684/1: errata: Workaround for Cortex-A15
erratum 798181 (TLBI/DSB operations)) introduced a workaround for
Cortex-A15 erratum 798181. Enable it for HIP04(Cortex-a15 r3p2).
Signed-off-by: Kefeng Wang <kefeng.wang@linaro.org>
Singed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
arch/arm/mach-hisi/Kconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm/mach-hisi/Kconfig b/arch/arm/mach-hisi/Kconfig
index a458f28..8d92e99 100644
--- a/arch/arm/mach-hisi/Kconfig
+++ b/arch/arm/mach-hisi/Kconfig
@@ -21,6 +21,7 @@ config ARCH_HI3xxx
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
--
1.9.1
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v10 11/11] virt: arm: support hip04 gic
2014-07-10 2:03 [PATCH v10 00/11] enable HiP04 SoC Haojian Zhuang
` (9 preceding siblings ...)
2014-07-10 2:04 ` [PATCH v10 10/11] ARM: hisi: enable erratum 798181 of A15 on HiP04 Haojian Zhuang
@ 2014-07-10 2:04 ` Haojian Zhuang
10 siblings, 0 replies; 20+ messages in thread
From: Haojian Zhuang @ 2014-07-10 2:04 UTC (permalink / raw)
To: linux-arm-kernel
In ARM standard GIC, GICH_APR offset is 0xf0 & GICH_LR0 offset is 0x100.
In HiP04 GIC, GICH_APR offset is 0x70 & GICH_LR0 offset is 0x80.
Now reuse the nr_lr field in struct vgic_cpu. Bit[31:16] is used to store
GICH_APR offset in HiP04, and bit[15:0] is used to store real nr_lr
variable. In ARM standard GIC, don't set bit[31:16]. So we could avoid
to change the VGIC implementation in arm64.
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
arch/arm/kernel/asm-offsets.c | 2 +-
arch/arm/kvm/interrupts_head.S | 29 +++++++++++++++++++++++------
arch/arm64/kernel/asm-offsets.c | 2 +-
arch/arm64/kvm/hyp.S | 4 ++--
include/kvm/arm_vgic.h | 7 +++++--
include/linux/irqchip/arm-gic.h | 6 ++++++
virt/kvm/arm/vgic.c | 37 ++++++++++++++++++++++++++-----------
7 files changed, 64 insertions(+), 23 deletions(-)
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 85598b5..166cc98 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -189,7 +189,7 @@ int main(void)
DEFINE(VGIC_CPU_ELRSR, offsetof(struct vgic_cpu, vgic_elrsr));
DEFINE(VGIC_CPU_APR, offsetof(struct vgic_cpu, vgic_apr));
DEFINE(VGIC_CPU_LR, offsetof(struct vgic_cpu, vgic_lr));
- DEFINE(VGIC_CPU_NR_LR, offsetof(struct vgic_cpu, nr_lr));
+ DEFINE(VGIC_CPU_HW_CFG, offsetof(struct vgic_cpu, hw_cfg));
#ifdef CONFIG_KVM_ARM_TIMER
DEFINE(VCPU_TIMER_CNTV_CTL, offsetof(struct kvm_vcpu, arch.timer_cpu.cntv_ctl));
DEFINE(VCPU_TIMER_CNTV_CVAL, offsetof(struct kvm_vcpu, arch.timer_cpu.cntv_cval));
diff --git a/arch/arm/kvm/interrupts_head.S b/arch/arm/kvm/interrupts_head.S
index 76af9302..9fbbf99 100644
--- a/arch/arm/kvm/interrupts_head.S
+++ b/arch/arm/kvm/interrupts_head.S
@@ -419,7 +419,9 @@ vcpu .req r0 @ vcpu pointer always in r0
ldr r7, [r2, #GICH_EISR1]
ldr r8, [r2, #GICH_ELRSR0]
ldr r9, [r2, #GICH_ELRSR1]
- ldr r10, [r2, #GICH_APR]
+ ldr r10, [r11, #VGIC_CPU_HW_CFG]
+ mov r10, r10, lsr #HWCFG_APR_SHIFT
+ ldr r10, [r2, r10]
str r3, [r11, #VGIC_CPU_HCR]
str r4, [r11, #VGIC_CPU_VMCR]
@@ -435,9 +437,15 @@ vcpu .req r0 @ vcpu pointer always in r0
str r5, [r2, #GICH_HCR]
/* Save list registers */
- add r2, r2, #GICH_LR0
+ ldr r4, [r11, #VGIC_CPU_HW_CFG]
+ mov r10, r4, lsr #HWCFG_APR_SHIFT
+ /* the offset between GICH_APR & GICH_LR0 is 0x10 */
+ add r10, r10, #0x10
+ add r2, r2, r10
add r3, r11, #VGIC_CPU_LR
- ldr r4, [r11, #VGIC_CPU_NR_LR]
+ /* Get NR_LR from VGIC_CPU_HW_CFG */
+ ldr r6, =HWCFG_NR_LR_MASK
+ and r4, r4, r6
1: ldr r6, [r2], #4
str r6, [r3], #4
subs r4, r4, #1
@@ -469,12 +477,21 @@ vcpu .req r0 @ vcpu pointer always in r0
str r3, [r2, #GICH_HCR]
str r4, [r2, #GICH_VMCR]
- str r8, [r2, #GICH_APR]
+ ldr r6, [r11, #VGIC_CPU_HW_CFG]
+ mov r6, r6, lsr #HWCFG_APR_SHIFT
+ str r8, [r2, r6]
/* Restore list registers */
- add r2, r2, #GICH_LR0
+ ldr r4, [r11, #VGIC_CPU_HW_CFG]
+ mov r6, r4, lsr #HWCFG_APR_SHIFT
+ /* the offset between GICH_APR & GICH_LR0 is 0x10 */
+ add r6, r6, #0x10
+ /* get offset of GICH_LR0 */
+ add r2, r2, r6
+ /* Get NR_LR from VGIC_CPU_HW_CFG */
add r3, r11, #VGIC_CPU_LR
- ldr r4, [r11, #VGIC_CPU_NR_LR]
+ ldr r6, =HWCFG_NR_LR_MASK
+ and r4, r4, r6
1: ldr r6, [r3], #4
str r6, [r2], #4
subs r4, r4, #1
diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
index 646f888..2422358 100644
--- a/arch/arm64/kernel/asm-offsets.c
+++ b/arch/arm64/kernel/asm-offsets.c
@@ -136,7 +136,7 @@ int main(void)
DEFINE(VGIC_CPU_ELRSR, offsetof(struct vgic_cpu, vgic_elrsr));
DEFINE(VGIC_CPU_APR, offsetof(struct vgic_cpu, vgic_apr));
DEFINE(VGIC_CPU_LR, offsetof(struct vgic_cpu, vgic_lr));
- DEFINE(VGIC_CPU_NR_LR, offsetof(struct vgic_cpu, nr_lr));
+ DEFINE(VGIC_CPU_HW_CFG, offsetof(struct vgic_cpu, hw_cfg));
DEFINE(KVM_VTTBR, offsetof(struct kvm, arch.vttbr));
DEFINE(KVM_VGIC_VCTRL, offsetof(struct kvm, arch.vgic.vctrl_base));
#endif
diff --git a/arch/arm64/kvm/hyp.S b/arch/arm64/kvm/hyp.S
index b0d1512..2dbe337 100644
--- a/arch/arm64/kvm/hyp.S
+++ b/arch/arm64/kvm/hyp.S
@@ -426,7 +426,7 @@ CPU_BE( rev w11, w11 )
/* Save list registers */
add x2, x2, #GICH_LR0
- ldr w4, [x3, #VGIC_CPU_NR_LR]
+ ldr w4, [x3, #VGIC_CPU_HW_CFG]
add x3, x3, #VGIC_CPU_LR
1: ldr w5, [x2], #4
CPU_BE( rev w5, w5 )
@@ -465,7 +465,7 @@ CPU_BE( rev w6, w6 )
/* Restore list registers */
add x2, x2, #GICH_LR0
- ldr w4, [x3, #VGIC_CPU_NR_LR]
+ ldr w4, [x3, #VGIC_CPU_HW_CFG]
add x3, x3, #VGIC_CPU_LR
1: ldr w5, [x3], #4
CPU_BE( rev w5, w5 )
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index f27000f..eba4b51 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -122,8 +122,11 @@ struct vgic_cpu {
/* Bitmap of used/free list registers */
DECLARE_BITMAP( lr_used, VGIC_MAX_LRS);
- /* Number of list registers on this CPU */
- int nr_lr;
+ /*
+ * bit[31:16]: GICH_APR offset
+ * bit[15:0]: Number of list registers on this CPU
+ */
+ u32 hw_cfg;
/* CPU vif control registers for world switch */
u32 vgic_hcr;
diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
index 45e2d8c..b055f92 100644
--- a/include/linux/irqchip/arm-gic.h
+++ b/include/linux/irqchip/arm-gic.h
@@ -49,6 +49,8 @@
#define GICH_ELRSR1 0x34
#define GICH_APR 0xf0
#define GICH_LR0 0x100
+#define HIP04_GICH_APR 0x70
+/* GICH_LR0 offset in HiP04 is 0x80 */
#define GICH_HCR_EN (1 << 0)
#define GICH_HCR_UIE (1 << 1)
@@ -73,6 +75,10 @@
#define GICH_MISR_EOI (1 << 0)
#define GICH_MISR_U (1 << 1)
+#define HWCFG_NR_LR_MASK 0xffff
+#define HWCFG_APR_SHIFT 16
+#define HWCFG_APR_MASK (0xffff << HWCFG_APR_SHIFT)
+
#ifndef __ASSEMBLY__
struct device_node;
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 56ff9be..6c0ee89 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -97,7 +97,7 @@ static void vgic_retire_disabled_irqs(struct kvm_vcpu *vcpu);
static void vgic_update_state(struct kvm *kvm);
static void vgic_kick_vcpus(struct kvm *kvm);
static void vgic_dispatch_sgi(struct kvm_vcpu *vcpu, u32 reg);
-static u32 vgic_nr_lr;
+static u32 vgic_hw_cfg, vgic_nr_lr;
static unsigned int vgic_maint_irq;
@@ -625,7 +625,7 @@ static void vgic_unqueue_irqs(struct kvm_vcpu *vcpu)
int i, irq, source_cpu;
u32 *lr;
- for_each_set_bit(i, vgic_cpu->lr_used, vgic_cpu->nr_lr) {
+ for_each_set_bit(i, vgic_cpu->lr_used, vgic_nr_lr) {
lr = &vgic_cpu->vgic_lr[i];
irq = LR_IRQID(*lr);
source_cpu = LR_CPUID(*lr);
@@ -1006,7 +1006,7 @@ static void vgic_retire_disabled_irqs(struct kvm_vcpu *vcpu)
struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
int lr;
- for_each_set_bit(lr, vgic_cpu->lr_used, vgic_cpu->nr_lr) {
+ for_each_set_bit(lr, vgic_cpu->lr_used, vgic_nr_lr) {
int irq = vgic_cpu->vgic_lr[lr] & GICH_LR_VIRTUALID;
if (!vgic_irq_is_enabled(vcpu, irq)) {
@@ -1047,8 +1047,8 @@ static bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq)
/* Try to use another LR for this interrupt */
lr = find_first_zero_bit((unsigned long *)vgic_cpu->lr_used,
- vgic_cpu->nr_lr);
- if (lr >= vgic_cpu->nr_lr)
+ vgic_nr_lr);
+ if (lr >= vgic_nr_lr)
return false;
kvm_debug("LR%d allocated for IRQ%d %x\n", lr, irq, sgi_source_id);
@@ -1183,7 +1183,7 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu)
int lr, irq;
for_each_set_bit(lr, (unsigned long *)vgic_cpu->vgic_eisr,
- vgic_cpu->nr_lr) {
+ vgic_nr_lr) {
irq = vgic_cpu->vgic_lr[lr] & GICH_LR_VIRTUALID;
vgic_irq_clear_active(vcpu, irq);
@@ -1227,7 +1227,7 @@ static void __kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
/* Clear mappings for empty LRs */
for_each_set_bit(lr, (unsigned long *)vgic_cpu->vgic_elrsr,
- vgic_cpu->nr_lr) {
+ vgic_nr_lr) {
int irq;
if (!test_and_clear_bit(lr, vgic_cpu->lr_used))
@@ -1241,8 +1241,8 @@ static void __kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
/* Check if we still have something up our sleeve... */
pending = find_first_zero_bit((unsigned long *)vgic_cpu->vgic_elrsr,
- vgic_cpu->nr_lr);
- if (level_pending || pending < vgic_cpu->nr_lr)
+ vgic_nr_lr);
+ if (level_pending || pending < vgic_nr_lr)
set_bit(vcpu->vcpu_id, &dist->irq_pending_on_cpu);
}
@@ -1438,7 +1438,7 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
*/
vgic_cpu->vgic_vmcr = 0;
- vgic_cpu->nr_lr = vgic_nr_lr;
+ vgic_cpu->hw_cfg = vgic_hw_cfg;
vgic_cpu->vgic_hcr = GICH_HCR_EN; /* Get the show on the road... */
return 0;
@@ -1470,17 +1470,31 @@ static struct notifier_block vgic_cpu_nb = {
.notifier_call = vgic_cpu_notify,
};
+static const struct of_device_id of_vgic_ids[] = {
+ {
+ .compatible = "arm,cortex-a15-gic",
+ .data = (void *)GICH_APR,
+ }, {
+ .compatible = "hisilicon,hip04-gic",
+ .data = (void *)HIP04_GICH_APR,
+ }, {
+ },
+};
+
int kvm_vgic_hyp_init(void)
{
int ret;
struct resource vctrl_res;
struct resource vcpu_res;
+ const struct of_device_id *match;
- vgic_node = of_find_compatible_node(NULL, NULL, "arm,cortex-a15-gic");
+ vgic_node = of_find_matching_node_and_match(NULL, of_vgic_ids, &match);
if (!vgic_node) {
kvm_err("error: no compatible vgic node in DT\n");
return -ENODEV;
}
+ /* High word of vgic_hw_cfg is the offset of GICH_APR. */
+ vgic_hw_cfg = (unsigned long)match->data << HWCFG_APR_SHIFT;
vgic_maint_irq = irq_of_parse_and_map(vgic_node, 0);
if (!vgic_maint_irq) {
@@ -1517,6 +1531,7 @@ int kvm_vgic_hyp_init(void)
vgic_nr_lr = readl_relaxed(vgic_vctrl_base + GICH_VTR);
vgic_nr_lr = (vgic_nr_lr & 0x3f) + 1;
+ vgic_hw_cfg |= vgic_nr_lr;
ret = create_hyp_io_mappings(vgic_vctrl_base,
vgic_vctrl_base + resource_size(&vctrl_res),
--
1.9.1
^ permalink raw reply related [flat|nested] 20+ messages in thread