diff options
author | Nicolas Dechesne <nicolas.dechesne@linaro.org> | 2016-10-03 15:28:52 +0200 |
---|---|---|
committer | Nicolas Dechesne <nicolas.dechesne@linaro.org> | 2016-10-03 15:28:52 +0200 |
commit | 4fffd62d74b4db1163b32800976086771a1924ae (patch) | |
tree | c08989ea4b9a3a3dbe09526bc4f829f44baed5af | |
parent | 78e0b05674be3954e36de2d4df9f29f357025904 (diff) | |
parent | d6d921fb6f37dc4c8a7a80fcad8abe4eb2ab050b (diff) |
Merge remote-tracking branch 'agross/psci-for-4.4-lt' into release/qcomlt-4.4debian-qcom-dragonboard410c-16.09
-rw-r--r-- | Documentation/devicetree/bindings/arm/cpus.txt | 2 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/arm/msm/acc.txt | 19 | ||||
-rw-r--r-- | arch/arm64/boot/dts/qcom/msm8916.dtsi | 70 | ||||
-rw-r--r-- | drivers/firmware/qcom_scm-64.c | 87 | ||||
-rw-r--r-- | drivers/firmware/qcom_scm.h | 7 | ||||
-rw-r--r-- | drivers/soc/qcom/Makefile | 1 | ||||
-rw-r--r-- | drivers/soc/qcom/cpu_ops.c | 343 |
7 files changed, 31 insertions, 498 deletions
diff --git a/Documentation/devicetree/bindings/arm/cpus.txt b/Documentation/devicetree/bindings/arm/cpus.txt index 8dd9f94ca423..3a07a87fef20 100644 --- a/Documentation/devicetree/bindings/arm/cpus.txt +++ b/Documentation/devicetree/bindings/arm/cpus.txt @@ -185,8 +185,6 @@ 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 deleted file mode 100644 index ae2d7253b363..000000000000 --- a/Documentation/devicetree/bindings/arm/msm/acc.txt +++ /dev/null @@ -1,19 +0,0 @@ -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/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi index 2a04e76fc9e5..551c12ae2948 100644 --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi @@ -105,8 +105,6 @@ device_type = "cpu"; compatible = "arm,cortex-a53", "arm,armv8"; reg = <0x0>; - enable-method = "qcom,arm-cortex-acc"; - qcom,acc = <&acc0>; next-level-cache = <&L2_0>; clocks = <&a53cc 1>; clock-latency = <200000>; @@ -115,19 +113,14 @@ cooling-min-level = <0>; cooling-max-level = <7>; #cooling-cells = <2>; - L2_0: l2-cache { - compatible = "arm,arch-cache"; - cache-level = <2>; - power-domain = <&l2ccc_0>; - }; + enable-method = "psci"; + cpu-idle-states = <&CPU_SPC>; }; CPU1: cpu@1 { device_type = "cpu"; compatible = "arm,cortex-a53", "arm,armv8"; reg = <0x1>; - enable-method = "qcom,arm-cortex-acc"; - qcom,acc = <&acc1>; next-level-cache = <&L2_0>; clocks = <&a53cc 1>; clock-latency = <200000>; @@ -136,14 +129,14 @@ cooling-min-level = <0>; cooling-max-level = <7>; #cooling-cells = <2>; + enable-method = "psci"; + cpu-idle-states = <&CPU_SPC>; }; CPU2: cpu@2 { device_type = "cpu"; compatible = "arm,cortex-a53", "arm,armv8"; reg = <0x2>; - enable-method = "qcom,arm-cortex-acc"; - qcom,acc = <&acc2>; next-level-cache = <&L2_0>; clocks = <&a53cc 1>; clock-latency = <200000>; @@ -152,14 +145,14 @@ cooling-min-level = <0>; cooling-max-level = <7>; #cooling-cells = <2>; + enable-method = "psci"; + cpu-idle-states = <&CPU_SPC>; }; CPU3: cpu@3 { device_type = "cpu"; compatible = "arm,cortex-a53", "arm,armv8"; reg = <0x3>; - enable-method = "qcom,arm-cortex-acc"; - qcom,acc = <&acc3>; next-level-cache = <&L2_0>; clocks = <&a53cc 1>; clock-latency = <200000>; @@ -168,6 +161,24 @@ cooling-min-level = <0>; cooling-max-level = <7>; #cooling-cells = <2>; + enable-method = "psci"; + cpu-idle-states = <&CPU_SPC>; + }; + + idle-states { + CPU_SPC: spc { + compatible = "arm,idle-state"; + arm,psci-suspend-param = <0x40000002>; + entry-latency-us = <130>; + exit-latency-us = <150>; + min-residency-us = <2000>; + local-timer-stop; + }; + }; + + L2_0: l2-cache { + compatible = "cache"; + cache-level = <2>; }; }; @@ -232,6 +243,11 @@ }; }; + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + timer { compatible = "arm,armv8-timer"; interrupts = <GIC_PPI 2 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>, @@ -725,11 +741,6 @@ reg = <0x0b000000 0x1000>, <0x0b002000 0x1000>; }; - l2ccc_0: clock-controller@b011000 { - compatible = "qcom,8916-l2ccc"; - reg = <0x0b011000 0x1000>; - }; - timer@b020000 { #address-cells = <1>; #size-cells = <1>; @@ -813,29 +824,6 @@ clocks = <&gcc GCC_PRNG_AHB_CLK>; clock-names = "core"; }; - acc0: clock-controller@b088000 { - compatible = "qcom,arm-cortex-acc"; - reg = <0x0b088000 0x1000>, - <0x0b008000 0x1000>; - }; - - acc1: clock-controller@b098000 { - compatible = "qcom,arm-cortex-acc"; - reg = <0x0b098000 0x1000>, - <0x0b008000 0x1000>; - }; - - acc2: clock-controller@b0a8000 { - compatible = "qcom,arm-cortex-acc"; - reg = <0x0b0a8000 0x1000>, - <0x0b008000 0x1000>; - }; - - acc3: clock-controller@b0b8000 { - compatible = "qcom,arm-cortex-acc"; - reg = <0x0b0b8000 0x1000>, - <0x0b008000 0x1000>; - }; /* Audio */ diff --git a/drivers/firmware/qcom_scm-64.c b/drivers/firmware/qcom_scm-64.c index 7784f1dc8977..e8dedcbbce78 100644 --- a/drivers/firmware/qcom_scm-64.c +++ b/drivers/firmware/qcom_scm-64.c @@ -333,101 +333,18 @@ static int qcom_scm_call(u32 svc_id, u32 cmd_id, struct qcom_scm_desc *desc) return 0; } -/** - * qcom_scm_call_atomic() - Invoke a syscall in the secure world - * - * Similar to qcom_scm_call except that this can be invoked in atomic context. - * There is also no retry mechanism implemented. Please ensure that the - * secure world syscall can be executed in such a context and can complete - * in a timely manner. - */ -static int qcom_scm_call_atomic(u32 s, u32 c, struct qcom_scm_desc *desc) -{ - int arglen = desc->arginfo & 0xf; - int ret; - u32 fn_id = QCOM_SCM_SIP_FNID(s, c); - u64 x0; - - ret = allocate_extra_arg_buffer(desc, GFP_ATOMIC); - if (ret) - return ret; - - x0 = fn_id | BIT(SMC_ATOMIC_SYSCALL) | qcom_scm_version_mask; - - pr_debug("qcom_scm_call: func id %#llx, args: %#x, %#llx, %#llx, %#llx, %#llx\n", - x0, desc->arginfo, desc->args[0], desc->args[1], - desc->args[2], desc->x5); - - if (qcom_scm_version == QCOM_SCM_ARMV8_64) - ret = __qcom_scm_call_armv8_64(x0, desc->arginfo, desc->args[0], - desc->args[1], desc->args[2], - desc->x5, &desc->ret[0], - &desc->ret[1], &desc->ret[2]); - else - ret = __qcom_scm_call_armv8_32(x0, desc->arginfo, desc->args[0], - desc->args[1], desc->args[2], - desc->x5, &desc->ret[0], - &desc->ret[1], &desc->ret[2]); - if (ret < 0) - pr_err("qcom_scm_call failed: func id %#llx, arginfo: %#x, args: %#llx, %#llx, %#llx, %#llx, ret: %d, syscall returns: %#llx, %#llx, %#llx\n", - x0, desc->arginfo, desc->args[0], desc->args[1], - desc->args[2], desc->x5, ret, desc->ret[0], - desc->ret[1], desc->ret[2]); - - if (arglen > N_REGISTER_ARGS) - kfree(desc->extra_arg_buf); - if (ret < 0) - return qcom_scm_remap_error(ret); - return ret; -} - -static int qcom_scm_set_boot_addr(void *entry, const cpumask_t *cpus, int flags) -{ - struct qcom_scm_desc desc = {0}; - unsigned int cpu = cpumask_first(cpus); - u64 mpidr_el1 = cpu_logical_map(cpu); - - /* For now we assume only a single cpu is set in the mask */ - WARN_ON(cpumask_weight(cpus) != 1); - - if (mpidr_el1 & ~MPIDR_HWID_BITMASK) { - pr_err("CPU%d:Failed to set boot address\n", cpu); - return -ENOSYS; - } - - desc.args[0] = virt_to_phys(entry); - desc.args[1] = BIT(MPIDR_AFFINITY_LEVEL(mpidr_el1, 0)); - desc.args[2] = BIT(MPIDR_AFFINITY_LEVEL(mpidr_el1, 1)); - desc.args[3] = BIT(MPIDR_AFFINITY_LEVEL(mpidr_el1, 2)); - desc.args[4] = ~0ULL; - desc.args[5] = QCOM_SCM_FLAG_HLOS | flags; - desc.arginfo = QCOM_SCM_ARGS(6); - - return qcom_scm_call(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_ADDR_MC, &desc); -} - int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus) { - int flags = QCOM_SCM_FLAG_COLDBOOT_MC; - - return qcom_scm_set_boot_addr(entry, cpus, flags); + return -EOPNOTSUPP; } int __qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus) { - int flags = QCOM_SCM_FLAG_WARMBOOT_MC; - - return qcom_scm_set_boot_addr(entry, cpus, flags); + return -EOPNOTSUPP; } void __qcom_scm_cpu_power_down(u32 flags) { - struct qcom_scm_desc desc = {0}; - desc.args[0] = QCOM_SCM_CMD_CORE_HOTPLUGGED | - (flags & QCOM_SCM_FLUSH_FLAG_MASK); - desc.arginfo = QCOM_SCM_ARGS(1); - - qcom_scm_call_atomic(QCOM_SCM_SVC_BOOT, QCOM_SCM_CMD_TERMINATE_PC, &desc); } int __qcom_scm_is_call_available(u32 svc_id, u32 cmd_id) diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index e1d6a42ba466..ff407a6c0155 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -57,9 +57,6 @@ extern int __qcom_scm_pas_mss_reset(bool reset); #define QCOM_SCM_EINVAL_ARG -2 #define QCOM_SCM_ERROR -1 #define QCOM_SCM_INTERRUPTED 1 -#define QCOM_SCM_EBUSY -55 -#define QCOM_SCM_V2_EBUSY -12 - static inline int qcom_scm_remap_error(int err) { @@ -73,10 +70,6 @@ static inline int qcom_scm_remap_error(int err) return -EOPNOTSUPP; case QCOM_SCM_ENOMEM: return -ENOMEM; - case QCOM_SCM_EBUSY: - return QCOM_SCM_EBUSY; - case QCOM_SCM_V2_EBUSY: - return QCOM_SCM_V2_EBUSY; } return -EINVAL; } diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index 56da0a585cfd..20126f48b69b 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -1,4 +1,3 @@ -obj-$(CONFIG_ARM64) += cpu_ops.o obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o obj-$(CONFIG_QCOM_PM) += spm.o obj-$(CONFIG_QCOM_SMD) += smd.o diff --git a/drivers/soc/qcom/cpu_ops.c b/drivers/soc/qcom/cpu_ops.c deleted file mode 100644 index d831cb071d3d..000000000000 --- a/drivers/soc/qcom/cpu_ops.c +++ /dev/null @@ -1,343 +0,0 @@ -/* 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); - -#if 0 -static int cold_boot_flags[] = { - 0, - QCOM_SCM_FLAG_COLDBOOT_CPU1, - QCOM_SCM_FLAG_COLDBOOT_CPU2, - QCOM_SCM_FLAG_COLDBOOT_CPU3, -}; -#endif - -/* 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 - -#define SCM_IO_READ 1 -#define SCM_IO_WRITE 2 - -/* - * struct msm_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 msm_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 msm_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 msm_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 msm_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 msm_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 msm_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 msm_cpu_boot(unsigned int cpu) -{ - int ret = 0; - - if (per_cpu(cold_boot_done, cpu) == false) { - ret = msm_unclamp_secondary_arm_cpu(cpu); - if (ret) - return ret; - per_cpu(cold_boot_done, cpu) = true; - } - return secondary_pen_release(cpu); -} - -void msm_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); -} - -static const struct cpu_operations msm_cortex_a_ops = { - .name = "qcom,arm-cortex-acc", - .cpu_init = msm_cpu_init, - .cpu_prepare = msm_cpu_prepare, - .cpu_boot = msm_cpu_boot, - .cpu_postboot = msm_cpu_postboot, -}; -CPU_METHOD_OF_DECLARE(msm_cortex_a_ops, &msm_cortex_a_ops); |