Loading arch/arm/include/asm/fixmap.h +1 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ enum fixed_addresses { FIX_EARLYCON_MEM_BASE, FIX_SMP_MEM_BASE, __end_of_permanent_fixed_addresses, FIX_KMAP_BEGIN = __end_of_permanent_fixed_addresses, Loading arch/arm/mach-qcom/board-msm8909.c +2 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ #include <asm/mach/map.h> #include <asm/mach/arch.h> #include "board-dt.h" #include "platsmp.h" static const char *msm8909_dt_match[] __initconst = { "qcom,msm8909", Loading @@ -30,4 +31,5 @@ DT_MACHINE_START(MSM8909_DT, "Qualcomm Technologies, Inc. MSM 8909 (Flattened Device Tree)") .init_machine = msm8909_init, .dt_compat = msm8909_dt_match, .smp = &msm8909_smp_ops, MACHINE_END arch/arm/mach-qcom/platsmp.c +116 −0 Original line number Diff line number Diff line Loading @@ -20,7 +20,13 @@ #include <linux/qcom_scm.h> #include <asm/smp_plat.h> #include <asm/fixmap.h> #include "platsmp.h" #define MSM_APCS_IDR 0x0B011030 /* Base Address of APC IPC block */ #define APCS_ALIAS0_APC_SECURE 0x0B088000 #define VDD_SC1_ARRAY_CLAMP_GFS_CTL 0x35a0 #define SCSS_CPU1CORE_RESET 0x2d80 Loading @@ -29,9 +35,12 @@ #define APCS_CPU_PWR_CTL 0x04 #define PLL_CLAMP BIT(8) #define CORE_PWRD_UP BIT(7) #define GATE_CLK BIT(6) #define COREPOR_RST BIT(5) #define CORE_RST BIT(4) #define L2DT_SLP BIT(3) #define L1_RST_DIS BIT(2) #define CORE_MEM_CLAMP BIT(1) #define CLAMP BIT(0) #define APC_PWR_GATE_CTL 0x14 Loading Loading @@ -270,6 +279,67 @@ static int kpssv2_release_secondary(unsigned int cpu) static DEFINE_PER_CPU(int, cold_boot_done); /* * writing to physical address: * 0xb088000 + (cpu * 0x10000) + 0x04 and * 0xb088000 + (cpu * 0x10000) + 0x014 * For each secondary cpu */ static int arm_release_secondary(unsigned int cpu) { phys_addr_t base = APCS_ALIAS0_APC_SECURE; void __iomem *base_ptr; unsigned int reg_val; base_ptr = ioremap_nocache(base + (cpu * 0x10000), SZ_4K); if (!base_ptr) return -ENODEV; reg_val = COREPOR_RST | CORE_RST | CORE_MEM_CLAMP | CLAMP; writel_relaxed(reg_val, base_ptr + APCS_CPU_PWR_CTL); /* memory barrier */ mb(); /* Turn on the BHS, set the BHS_CNT value with 16 */ reg_val = (0x10 << BHS_CNT_SHIFT) | BHS_EN; writel_relaxed(reg_val, base_ptr + APC_PWR_GATE_CTL); /* memory barrier */ mb(); udelay(2); reg_val = COREPOR_RST | CORE_RST | CLAMP; writel_relaxed(reg_val, base_ptr + APCS_CPU_PWR_CTL); /* memory barrier */ mb(); reg_val = COREPOR_RST | CORE_RST | L2DT_SLP | CLAMP; writel_relaxed(reg_val, base_ptr + APCS_CPU_PWR_CTL); /* memory barrier */ mb(); udelay(2); reg_val = COREPOR_RST | CORE_RST | L2DT_SLP; writel_relaxed(reg_val, base_ptr + APCS_CPU_PWR_CTL); /* memory barrier */ mb(); udelay(2); reg_val = L2DT_SLP; writel_relaxed(reg_val, base_ptr + APCS_CPU_PWR_CTL); /* memory barrier */ mb(); reg_val = CORE_PWRD_UP | L2DT_SLP; writel_relaxed(reg_val, base_ptr + APCS_CPU_PWR_CTL); /* memory barrier */ mb(); iounmap(base_ptr); return 0; } static int qcom_boot_secondary(unsigned int cpu, int (*func)(unsigned int)) { int ret = 0; Loading Loading @@ -302,6 +372,40 @@ static int qcom_boot_secondary(unsigned int cpu, int (*func)(unsigned int)) return ret; } /* * Initialise the CPU possible map early - this describes the CPUs * which may be present or become present in the system. */ static void __init arm_smp_init_cpus(void) { unsigned int i, ncores; void __iomem *base; set_fixmap_io(FIX_SMP_MEM_BASE, MSM_APCS_IDR & PAGE_MASK); base = (void __iomem *)__fix_to_virt(FIX_SMP_MEM_BASE); if (!base) return; base += MSM_APCS_IDR & ~PAGE_MASK; ncores = (__raw_readl(base)) & 0xF; if (ncores > nr_cpu_ids) { pr_warn("SMP: %u cores greater than maximum (%u), clipping\n", ncores, nr_cpu_ids); ncores = nr_cpu_ids; } for (i = 0; i < ncores; i++) set_cpu_possible(i, true); } static int msm8909_boot_secondary(unsigned int cpu, struct task_struct *idle) { pr_debug("Starting secondary CPU %d\n", cpu); return qcom_boot_secondary(cpu, arm_release_secondary); } static int msm8660_boot_secondary(unsigned int cpu, struct task_struct *idle) { return qcom_boot_secondary(cpu, scss_release_secondary); Loading Loading @@ -361,3 +465,15 @@ static const struct smp_operations qcom_smp_kpssv2_ops __initconst = { #endif }; CPU_METHOD_OF_DECLARE(qcom_smp_kpssv2, "qcom,kpss-acc-v2", &qcom_smp_kpssv2_ops); struct smp_operations msm8909_smp_ops __initdata = { .smp_init_cpus = arm_smp_init_cpus, .smp_prepare_cpus = qcom_smp_prepare_cpus, .smp_secondary_init = qcom_secondary_init, .smp_boot_secondary = msm8909_boot_secondary, #ifdef CONFIG_HOTPLUG_CPU .cpu_die = qcom_cpu_die, #endif }; CPU_METHOD_OF_DECLARE(qcom_smp_8909, "qcom,apss-8909", &msm8909_smp_ops); arch/arm/mach-qcom/platsmp.h 0 → 100644 +13 −0 Original line number Diff line number Diff line /* Copyright (c) 2012-2016, 2018, The Linux Foundation. All rights reserved. * * 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. */ extern struct smp_operations msm8909_smp_ops; Loading
arch/arm/include/asm/fixmap.h +1 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ enum fixed_addresses { FIX_EARLYCON_MEM_BASE, FIX_SMP_MEM_BASE, __end_of_permanent_fixed_addresses, FIX_KMAP_BEGIN = __end_of_permanent_fixed_addresses, Loading
arch/arm/mach-qcom/board-msm8909.c +2 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ #include <asm/mach/map.h> #include <asm/mach/arch.h> #include "board-dt.h" #include "platsmp.h" static const char *msm8909_dt_match[] __initconst = { "qcom,msm8909", Loading @@ -30,4 +31,5 @@ DT_MACHINE_START(MSM8909_DT, "Qualcomm Technologies, Inc. MSM 8909 (Flattened Device Tree)") .init_machine = msm8909_init, .dt_compat = msm8909_dt_match, .smp = &msm8909_smp_ops, MACHINE_END
arch/arm/mach-qcom/platsmp.c +116 −0 Original line number Diff line number Diff line Loading @@ -20,7 +20,13 @@ #include <linux/qcom_scm.h> #include <asm/smp_plat.h> #include <asm/fixmap.h> #include "platsmp.h" #define MSM_APCS_IDR 0x0B011030 /* Base Address of APC IPC block */ #define APCS_ALIAS0_APC_SECURE 0x0B088000 #define VDD_SC1_ARRAY_CLAMP_GFS_CTL 0x35a0 #define SCSS_CPU1CORE_RESET 0x2d80 Loading @@ -29,9 +35,12 @@ #define APCS_CPU_PWR_CTL 0x04 #define PLL_CLAMP BIT(8) #define CORE_PWRD_UP BIT(7) #define GATE_CLK BIT(6) #define COREPOR_RST BIT(5) #define CORE_RST BIT(4) #define L2DT_SLP BIT(3) #define L1_RST_DIS BIT(2) #define CORE_MEM_CLAMP BIT(1) #define CLAMP BIT(0) #define APC_PWR_GATE_CTL 0x14 Loading Loading @@ -270,6 +279,67 @@ static int kpssv2_release_secondary(unsigned int cpu) static DEFINE_PER_CPU(int, cold_boot_done); /* * writing to physical address: * 0xb088000 + (cpu * 0x10000) + 0x04 and * 0xb088000 + (cpu * 0x10000) + 0x014 * For each secondary cpu */ static int arm_release_secondary(unsigned int cpu) { phys_addr_t base = APCS_ALIAS0_APC_SECURE; void __iomem *base_ptr; unsigned int reg_val; base_ptr = ioremap_nocache(base + (cpu * 0x10000), SZ_4K); if (!base_ptr) return -ENODEV; reg_val = COREPOR_RST | CORE_RST | CORE_MEM_CLAMP | CLAMP; writel_relaxed(reg_val, base_ptr + APCS_CPU_PWR_CTL); /* memory barrier */ mb(); /* Turn on the BHS, set the BHS_CNT value with 16 */ reg_val = (0x10 << BHS_CNT_SHIFT) | BHS_EN; writel_relaxed(reg_val, base_ptr + APC_PWR_GATE_CTL); /* memory barrier */ mb(); udelay(2); reg_val = COREPOR_RST | CORE_RST | CLAMP; writel_relaxed(reg_val, base_ptr + APCS_CPU_PWR_CTL); /* memory barrier */ mb(); reg_val = COREPOR_RST | CORE_RST | L2DT_SLP | CLAMP; writel_relaxed(reg_val, base_ptr + APCS_CPU_PWR_CTL); /* memory barrier */ mb(); udelay(2); reg_val = COREPOR_RST | CORE_RST | L2DT_SLP; writel_relaxed(reg_val, base_ptr + APCS_CPU_PWR_CTL); /* memory barrier */ mb(); udelay(2); reg_val = L2DT_SLP; writel_relaxed(reg_val, base_ptr + APCS_CPU_PWR_CTL); /* memory barrier */ mb(); reg_val = CORE_PWRD_UP | L2DT_SLP; writel_relaxed(reg_val, base_ptr + APCS_CPU_PWR_CTL); /* memory barrier */ mb(); iounmap(base_ptr); return 0; } static int qcom_boot_secondary(unsigned int cpu, int (*func)(unsigned int)) { int ret = 0; Loading Loading @@ -302,6 +372,40 @@ static int qcom_boot_secondary(unsigned int cpu, int (*func)(unsigned int)) return ret; } /* * Initialise the CPU possible map early - this describes the CPUs * which may be present or become present in the system. */ static void __init arm_smp_init_cpus(void) { unsigned int i, ncores; void __iomem *base; set_fixmap_io(FIX_SMP_MEM_BASE, MSM_APCS_IDR & PAGE_MASK); base = (void __iomem *)__fix_to_virt(FIX_SMP_MEM_BASE); if (!base) return; base += MSM_APCS_IDR & ~PAGE_MASK; ncores = (__raw_readl(base)) & 0xF; if (ncores > nr_cpu_ids) { pr_warn("SMP: %u cores greater than maximum (%u), clipping\n", ncores, nr_cpu_ids); ncores = nr_cpu_ids; } for (i = 0; i < ncores; i++) set_cpu_possible(i, true); } static int msm8909_boot_secondary(unsigned int cpu, struct task_struct *idle) { pr_debug("Starting secondary CPU %d\n", cpu); return qcom_boot_secondary(cpu, arm_release_secondary); } static int msm8660_boot_secondary(unsigned int cpu, struct task_struct *idle) { return qcom_boot_secondary(cpu, scss_release_secondary); Loading Loading @@ -361,3 +465,15 @@ static const struct smp_operations qcom_smp_kpssv2_ops __initconst = { #endif }; CPU_METHOD_OF_DECLARE(qcom_smp_kpssv2, "qcom,kpss-acc-v2", &qcom_smp_kpssv2_ops); struct smp_operations msm8909_smp_ops __initdata = { .smp_init_cpus = arm_smp_init_cpus, .smp_prepare_cpus = qcom_smp_prepare_cpus, .smp_secondary_init = qcom_secondary_init, .smp_boot_secondary = msm8909_boot_secondary, #ifdef CONFIG_HOTPLUG_CPU .cpu_die = qcom_cpu_die, #endif }; CPU_METHOD_OF_DECLARE(qcom_smp_8909, "qcom,apss-8909", &msm8909_smp_ops);
arch/arm/mach-qcom/platsmp.h 0 → 100644 +13 −0 Original line number Diff line number Diff line /* Copyright (c) 2012-2016, 2018, The Linux Foundation. All rights reserved. * * 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. */ extern struct smp_operations msm8909_smp_ops;