* [RFC PATCH 0/5] Add smp booting support for Qualcomm ARMv8 SoCs
@ 2015-04-10 20:43 Kumar Gala
[not found] ` <1428698605-13166-1-git-send-email-galak-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2015-04-10 20:43 ` [RFC PATCH v2 4/4] arm64: qcom: add cpu operations Kumar Gala
0 siblings, 2 replies; 4+ messages in thread
From: Kumar Gala @ 2015-04-10 20:43 UTC (permalink / raw)
To: linux-arm-msm
Cc: Kumar Gala, linux-arm-kernel, linux-kernel, arm, devicetree,
catalin.marinas, will.deacon, abhimany
This patch set adds support for SMP boot on the MSM8x16 family of Qualcomm SoCs.
To support SMP on the MSM8x16 SoCs we need to add ARMv8/64-bit SCM interfaces to
setup the boot/release addresses for the secondary CPUs. In addition we need
a uniquie set of cpu ops. I'm aware the desired methods for booting secondary
CPUs is either via spintable or PSCI. However, these SoCs are shipping with a
firmware that does not support those methods.
v2:
* Dropped introduction and use of CPU_METHOD_OF_DECLARE
* Moved qcom cpu ops from drivers/soc/qcom to arch/arm64/kernel
* Renamed msm to qcom in cpu ops code, minor cleans (remove dead defines/code)
- k
--
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply [flat|nested] 4+ messages in thread
* [RFC PATCH v3 3/4] arm64: smp: move the pen to a header file
[not found] ` <1428698605-13166-1-git-send-email-galak-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
@ 2015-04-10 20:43 ` Kumar Gala
0 siblings, 0 replies; 4+ messages in thread
From: Kumar Gala @ 2015-04-10 20:43 UTC (permalink / raw)
To: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA
Cc: Abhimanyu Kapur,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, arm-DgEjT+Ai2ygdnm+yROfE0A,
devicetree-u79uwXL29TY76Z2rM5mHXA, catalin.marinas-5wv7dgnIgG8,
will.deacon-5wv7dgnIgG8, Kumar Gala
From: Abhimanyu Kapur <abhimany-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
Move the secondary_pen_release variable and the secondary_holding_pen
entry function to asm/smp_plat.h so that the other cpu ops implementations
can share them.
Signed-off-by: Abhimanyu Kapur <abhimany-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
Signed-off-by: Kumar Gala <galak-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
arch/arm64/include/asm/smp_plat.h | 2 ++
arch/arm64/kernel/smp.c | 1 +
arch/arm64/kernel/smp_spin_table.c | 3 ---
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/include/asm/smp_plat.h b/arch/arm64/include/asm/smp_plat.h
index 59e2823..235ff04 100644
--- a/arch/arm64/include/asm/smp_plat.h
+++ b/arch/arm64/include/asm/smp_plat.h
@@ -34,10 +34,12 @@ static inline u32 mpidr_hash_size(void)
return 1 << mpidr_hash.bits;
}
+extern void secondary_holding_pen(void);
/*
* Logical CPU mapping.
*/
extern u64 __cpu_logical_map[NR_CPUS];
#define cpu_logical_map(cpu) __cpu_logical_map[cpu]
+extern volatile unsigned long secondary_holding_pen_release;
#endif /* __ASM_SMP_PLAT_H */
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 328b8ce..4ce1f23 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -61,6 +61,7 @@
* where to place its SVC stack
*/
struct secondary_data secondary_data;
+volatile unsigned long secondary_holding_pen_release = INVALID_HWID;
enum ipi_msg_type {
IPI_RESCHEDULE,
diff --git a/arch/arm64/kernel/smp_spin_table.c b/arch/arm64/kernel/smp_spin_table.c
index 14944e5..808536e 100644
--- a/arch/arm64/kernel/smp_spin_table.c
+++ b/arch/arm64/kernel/smp_spin_table.c
@@ -28,9 +28,6 @@
#include <asm/io.h>
#include <asm/smp_plat.h>
-extern void secondary_holding_pen(void);
-volatile unsigned long secondary_holding_pen_release = INVALID_HWID;
-
static phys_addr_t cpu_release_addr[NR_CPUS];
/*
--
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [RFC PATCH v2 4/4] arm64: qcom: add cpu operations
2015-04-10 20:43 [RFC PATCH 0/5] Add smp booting support for Qualcomm ARMv8 SoCs Kumar Gala
[not found] ` <1428698605-13166-1-git-send-email-galak-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
@ 2015-04-10 20:43 ` Kumar Gala
2015-04-10 20:57 ` Arnd Bergmann
1 sibling, 1 reply; 4+ messages in thread
From: Kumar Gala @ 2015-04-10 20:43 UTC (permalink / raw)
To: linux-arm-msm
Cc: Abhimanyu Kapur, linux-arm-kernel, linux-kernel, arm, devicetree,
catalin.marinas, will.deacon, arnd, Kumar Gala
From: Abhimanyu Kapur <abhimany@codeaurora.org>
Add qcom cpu operations for arm-v8 cpus. Implement secondary cpu boot ops
As a part of this change update device tree documentation for:
1. Arm cortex-a ACC device which provides percpu reg
2. Armv8 cortex-a compatible string in arm/cpus.txt
Signed-off-by: Abhimanyu Kapur <abhimany@codeaurora.org>
Signed-off-by: Kumar Gala <galak@codeaurora.org>
---
Documentation/devicetree/bindings/arm/cpus.txt | 2 +
Documentation/devicetree/bindings/arm/msm/acc.txt | 19 ++
arch/arm64/kernel/Makefile | 3 +
arch/arm64/kernel/cpu_ops.c | 4 +
.../kernel/qcom-special-cpu-ops-dont-copy-this.c | 329 +++++++++++++++++++++
5 files changed, 357 insertions(+)
create mode 100644 Documentation/devicetree/bindings/arm/msm/acc.txt
create mode 100644 arch/arm64/kernel/qcom-special-cpu-ops-dont-copy-this.c
diff --git a/Documentation/devicetree/bindings/arm/cpus.txt b/Documentation/devicetree/bindings/arm/cpus.txt
index 8b9e0a9..35cabe5 100644
--- a/Documentation/devicetree/bindings/arm/cpus.txt
+++ b/Documentation/devicetree/bindings/arm/cpus.txt
@@ -185,6 +185,8 @@ nodes to be present and contain the properties described below.
be one of:
"psci"
"spin-table"
+ "qcom,arm-cortex-acc"
+
# On ARM 32-bit systems this property is optional and
can be one of:
"allwinner,sun6i-a31"
diff --git a/Documentation/devicetree/bindings/arm/msm/acc.txt b/Documentation/devicetree/bindings/arm/msm/acc.txt
new file mode 100644
index 0000000..ae2d725
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/acc.txt
@@ -0,0 +1,19 @@
+Application Processor Sub-system (APSS) Application Clock Controller (ACC)
+
+The ACC provides clock, power domain, and reset control to a CPU. There is one ACC
+register region per CPU within the APSS remapped region as well as an alias register
+region that remaps accesses to the ACC associated with the CPU accessing the region.
+
+Required properties:
+- compatible: Must be "qcom,arm-cortex-acc"
+- reg: The first element specifies the base address and size of
+ the register region. An optional second element specifies
+ the base address and size of the alias register region.
+
+Example:
+
+ clock-controller@b088000 {
+ compatible = "qcom,arm-cortex-acc";
+ reg = <0x0b088000 0x1000>,
+ <0x0b008000 0x1000>;
+ }
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 5ee07ee..8d77ac5 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -25,6 +25,9 @@ arm64-obj-$(CONFIG_COMPAT) += sys32.o kuser32.o signal32.o \
arm64-obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o entry-ftrace.o
arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o
arm64-obj-$(CONFIG_SMP) += smp.o smp_spin_table.o topology.o
+ifdef CONFIG_SMP
+arm64-obj-$(CONFIG_ARCH_QCOM) += qcom-special-cpu-ops-dont-copy-this.o
+endif
arm64-obj-$(CONFIG_PERF_EVENTS) += perf_regs.o
arm64-obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o
arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
diff --git a/arch/arm64/kernel/cpu_ops.c b/arch/arm64/kernel/cpu_ops.c
index cce9524..d002168 100644
--- a/arch/arm64/kernel/cpu_ops.c
+++ b/arch/arm64/kernel/cpu_ops.c
@@ -24,6 +24,7 @@
extern const struct cpu_operations smp_spin_table_ops;
extern const struct cpu_operations cpu_psci_ops;
+extern const struct cpu_operations qcom_cortex_a_ops;
const struct cpu_operations *cpu_ops[NR_CPUS];
@@ -32,6 +33,9 @@ static const struct cpu_operations *supported_cpu_ops[] __initconst = {
&smp_spin_table_ops,
#endif
&cpu_psci_ops,
+#ifdef CONFIG_ARCH_QCOM
+ &qcom_cortex_a_ops,
+#endif
NULL,
};
diff --git a/arch/arm64/kernel/qcom-special-cpu-ops-dont-copy-this.c b/arch/arm64/kernel/qcom-special-cpu-ops-dont-copy-this.c
new file mode 100644
index 0000000..11995d6
--- /dev/null
+++ b/arch/arm64/kernel/qcom-special-cpu-ops-dont-copy-this.c
@@ -0,0 +1,329 @@
+/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/* MSM ARMv8 CPU Operations
+ * Based on arch/arm64/kernel/smp_spin_table.c
+ */
+
+#include <linux/bitops.h>
+#include <linux/cpu.h>
+#include <linux/cpumask.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/smp.h>
+#include <linux/qcom_scm.h>
+
+#include <asm/barrier.h>
+#include <asm/cacheflush.h>
+#include <asm/cpu_ops.h>
+#include <asm/cputype.h>
+#include <asm/smp_plat.h>
+
+static DEFINE_RAW_SPINLOCK(boot_lock);
+
+DEFINE_PER_CPU(int, cold_boot_done);
+
+/* CPU power domain register offsets */
+#define CPU_PWR_CTL 0x4
+#define CPU_PWR_GATE_CTL 0x14
+#define LDO_BHS_PWR_CTL 0x28
+
+/* L2 power domain register offsets */
+#define L2_PWR_CTL_OVERRIDE 0xc
+#define L2_PWR_CTL 0x14
+#define L2_PWR_STATUS 0x18
+#define L2_CORE_CBCR 0x58
+#define L1_RST_DIS 0x284
+
+#define L2_SPM_STS 0xc
+#define L2_VREG_CTL 0x1c
+
+/*
+ * struct qcom_l2ccc_of_info: represents of data for l2 cache clock controller.
+ * @compat: compat string for l2 cache clock controller
+ * @l2_pon: l2 cache power on routine
+ */
+struct qcom_l2ccc_of_info {
+ const char *compat;
+ int (*l2_power_on) (struct device_node *dn, u32 l2_mask, int cpu);
+ u32 l2_power_on_mask;
+};
+
+static int power_on_l2_msm8916(struct device_node *l2ccc_node, u32 pon_mask,
+ int cpu)
+{
+ u32 pon_status;
+ void __iomem *l2_base;
+
+ l2_base = of_iomap(l2ccc_node, 0);
+ if (!l2_base)
+ return -ENOMEM;
+
+ /* Skip power-on sequence if l2 cache is already powered up*/
+ pon_status = (__raw_readl(l2_base + L2_PWR_STATUS) & pon_mask)
+ == pon_mask;
+ if (pon_status) {
+ iounmap(l2_base);
+ return 0;
+ }
+
+ /* Close L2/SCU Logic GDHS and power up the cache */
+ writel_relaxed(0x10D700, l2_base + L2_PWR_CTL);
+
+ /* Assert PRESETDBGn */
+ writel_relaxed(0x400000, l2_base + L2_PWR_CTL_OVERRIDE);
+ mb();
+ udelay(2);
+
+ /* De-assert L2/SCU memory Clamp */
+ writel_relaxed(0x101700, l2_base + L2_PWR_CTL);
+
+ /* Wakeup L2/SCU RAMs by deasserting sleep signals */
+ writel_relaxed(0x101703, l2_base + L2_PWR_CTL);
+ mb();
+ udelay(2);
+
+ /* Enable clocks via SW_CLK_EN */
+ writel_relaxed(0x01, l2_base + L2_CORE_CBCR);
+
+ /* De-assert L2/SCU logic clamp */
+ writel_relaxed(0x101603, l2_base + L2_PWR_CTL);
+ mb();
+ udelay(2);
+
+ /* De-assert PRESSETDBg */
+ writel_relaxed(0x0, l2_base + L2_PWR_CTL_OVERRIDE);
+
+ /* De-assert L2/SCU Logic reset */
+ writel_relaxed(0x100203, l2_base + L2_PWR_CTL);
+ mb();
+ udelay(54);
+
+ /* Turn on the PMIC_APC */
+ writel_relaxed(0x10100203, l2_base + L2_PWR_CTL);
+
+ /* Set H/W clock control for the cpu CBC block */
+ writel_relaxed(0x03, l2_base + L2_CORE_CBCR);
+ mb();
+ iounmap(l2_base);
+
+ return 0;
+}
+
+static const struct qcom_l2ccc_of_info l2ccc_info[] = {
+ {
+ .compat = "qcom,8916-l2ccc",
+ .l2_power_on = power_on_l2_msm8916,
+ .l2_power_on_mask = BIT(9),
+ },
+};
+
+static int power_on_l2_cache(struct device_node *l2ccc_node, int cpu)
+{
+ int ret, i;
+ const char *compat;
+
+ ret = of_property_read_string(l2ccc_node, "compatible", &compat);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < ARRAY_SIZE(l2ccc_info); i++) {
+ const struct qcom_l2ccc_of_info *ptr = &l2ccc_info[i];
+
+ if (!of_compat_cmp(ptr->compat, compat, strlen(compat)))
+ return ptr->l2_power_on(l2ccc_node,
+ ptr->l2_power_on_mask, cpu);
+ }
+ pr_err("Compat string not found for L2CCC node\n");
+ return -EIO;
+}
+
+static int qcom_unclamp_secondary_arm_cpu(unsigned int cpu)
+{
+
+ int ret = 0;
+ struct device_node *cpu_node, *acc_node, *l2_node, *l2ccc_node;
+ void __iomem *reg;
+
+ cpu_node = of_get_cpu_node(cpu, NULL);
+ if (!cpu_node)
+ return -ENODEV;
+
+ acc_node = of_parse_phandle(cpu_node, "qcom,acc", 0);
+ if (!acc_node) {
+ ret = -ENODEV;
+ goto out_acc;
+ }
+
+ l2_node = of_parse_phandle(cpu_node, "next-level-cache", 0);
+ if (!l2_node) {
+ ret = -ENODEV;
+ goto out_l2;
+ }
+
+ l2ccc_node = of_parse_phandle(l2_node, "power-domain", 0);
+ if (!l2ccc_node) {
+ ret = -ENODEV;
+ goto out_l2;
+ }
+
+ /* Ensure L2-cache of the CPU is powered on before
+ * unclamping cpu power rails.
+ */
+ ret = power_on_l2_cache(l2ccc_node, cpu);
+ if (ret) {
+ pr_err("L2 cache power up failed for CPU%d\n", cpu);
+ goto out_l2ccc;
+ }
+
+ reg = of_iomap(acc_node, 0);
+ if (!reg) {
+ ret = -ENOMEM;
+ goto out_acc_reg;
+ }
+
+ /* Assert Reset on cpu-n */
+ writel_relaxed(0x00000033, reg + CPU_PWR_CTL);
+ mb();
+
+ /*Program skew to 16 X0 clock cycles*/
+ writel_relaxed(0x10000001, reg + CPU_PWR_GATE_CTL);
+ mb();
+ udelay(2);
+
+ /* De-assert coremem clamp */
+ writel_relaxed(0x00000031, reg + CPU_PWR_CTL);
+ mb();
+
+ /* Close coremem array gdhs */
+ writel_relaxed(0x00000039, reg + CPU_PWR_CTL);
+ mb();
+ udelay(2);
+
+ /* De-assert cpu-n clamp */
+ writel_relaxed(0x00020038, reg + CPU_PWR_CTL);
+ mb();
+ udelay(2);
+
+ /* De-assert cpu-n reset */
+ writel_relaxed(0x00020008, reg + CPU_PWR_CTL);
+ mb();
+
+ /* Assert PWRDUP signal on core-n */
+ writel_relaxed(0x00020088, reg + CPU_PWR_CTL);
+ mb();
+
+ /* Secondary CPU-N is now alive */
+ iounmap(reg);
+out_acc_reg:
+ of_node_put(l2ccc_node);
+out_l2ccc:
+ of_node_put(l2_node);
+out_l2:
+ of_node_put(acc_node);
+out_acc:
+ of_node_put(cpu_node);
+
+ return ret;
+}
+
+static void write_pen_release(u64 val)
+{
+ void *start = (void *)&secondary_holding_pen_release;
+ unsigned long size = sizeof(secondary_holding_pen_release);
+
+ secondary_holding_pen_release = val;
+ smp_wmb();
+ __flush_dcache_area(start, size);
+}
+
+static int secondary_pen_release(unsigned int cpu)
+{
+ unsigned long timeout;
+
+ /*
+ * Set synchronisation state between this boot processor
+ * and the secondary one
+ */
+ raw_spin_lock(&boot_lock);
+ write_pen_release(cpu_logical_map(cpu));
+
+ timeout = jiffies + (1 * HZ);
+ while (time_before(jiffies, timeout)) {
+ if (secondary_holding_pen_release == INVALID_HWID)
+ break;
+ udelay(10);
+ }
+ raw_spin_unlock(&boot_lock);
+
+ return secondary_holding_pen_release != INVALID_HWID ? -ENOSYS : 0;
+}
+
+static int __init qcom_cpu_init(struct device_node *dn, unsigned int cpu)
+{
+ /* Mark CPU0 cold boot flag as done */
+ if (!cpu && !per_cpu(cold_boot_done, cpu))
+ per_cpu(cold_boot_done, cpu) = true;
+
+ return 0;
+}
+
+static int __init qcom_cpu_prepare(unsigned int cpu)
+{
+ const cpumask_t *mask = cpumask_of(cpu);
+
+ if (qcom_scm_set_cold_boot_addr(secondary_holding_pen, mask)) {
+ pr_warn("CPU%d:Failed to set boot address\n", cpu);
+ return -ENOSYS;
+ }
+
+ return 0;
+}
+
+static int qcom_cpu_boot(unsigned int cpu)
+{
+ int ret = 0;
+
+ if (per_cpu(cold_boot_done, cpu) == false) {
+ ret = qcom_unclamp_secondary_arm_cpu(cpu);
+ if (ret)
+ return ret;
+ per_cpu(cold_boot_done, cpu) = true;
+ }
+ return secondary_pen_release(cpu);
+}
+
+void qcom_cpu_postboot(void)
+{
+ /*
+ * Let the primary processor know we're out of the pen.
+ */
+ write_pen_release(INVALID_HWID);
+
+ /*
+ * Synchronise with the boot thread.
+ */
+ raw_spin_lock(&boot_lock);
+ raw_spin_unlock(&boot_lock);
+}
+
+const struct cpu_operations qcom_cortex_a_ops = {
+ .name = "qcom,arm-cortex-acc",
+ .cpu_init = qcom_cpu_init,
+ .cpu_prepare = qcom_cpu_prepare,
+ .cpu_boot = qcom_cpu_boot,
+ .cpu_postboot = qcom_cpu_postboot,
+};
--
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [RFC PATCH v2 4/4] arm64: qcom: add cpu operations
2015-04-10 20:43 ` [RFC PATCH v2 4/4] arm64: qcom: add cpu operations Kumar Gala
@ 2015-04-10 20:57 ` Arnd Bergmann
0 siblings, 0 replies; 4+ messages in thread
From: Arnd Bergmann @ 2015-04-10 20:57 UTC (permalink / raw)
To: Kumar Gala
Cc: linux-arm-msm, Abhimanyu Kapur, linux-arm-kernel, linux-kernel,
arm, devicetree, catalin.marinas, will.deacon
On Friday 10 April 2015 15:43:25 Kumar Gala wrote:
> +static int qcom_cpu_boot(unsigned int cpu)
> +{
> + int ret = 0;
> +
> + if (per_cpu(cold_boot_done, cpu) == false) {
> + ret = qcom_unclamp_secondary_arm_cpu(cpu);
> + if (ret)
> + return ret;
> + per_cpu(cold_boot_done, cpu) = true;
> + }
> + return secondary_pen_release(cpu);
> +}
> +
Please add a comment here to explain why you need a two-stage process here,
rather than just booting the CPU without the secondary_pen.
Are you working around a specific silicon bug here?
Arnd
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2015-04-10 20:57 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-04-10 20:43 [RFC PATCH 0/5] Add smp booting support for Qualcomm ARMv8 SoCs Kumar Gala
[not found] ` <1428698605-13166-1-git-send-email-galak-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2015-04-10 20:43 ` [RFC PATCH v3 3/4] arm64: smp: move the pen to a header file Kumar Gala
2015-04-10 20:43 ` [RFC PATCH v2 4/4] arm64: qcom: add cpu operations Kumar Gala
2015-04-10 20:57 ` Arnd Bergmann
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).