1/* 2 * Copyright (c) 2014 Samsung Electronics Co., Ltd. 3 * http://www.samsung.com 4 * 5 * arch/arm/mach-exynos/mcpm-exynos.c 6 * 7 * Based on arch/arm/mach-vexpress/dcscb.c 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 12 */ 13 14#include <linux/arm-cci.h> 15#include <linux/delay.h> 16#include <linux/io.h> 17#include <linux/of_address.h> 18#include <linux/syscore_ops.h> 19 20#include <asm/cputype.h> 21#include <asm/cp15.h> 22#include <asm/mcpm.h> 23#include <asm/smp_plat.h> 24 25#include "regs-pmu.h" 26#include "common.h" 27 28#define EXYNOS5420_CPUS_PER_CLUSTER 4 29#define EXYNOS5420_NR_CLUSTERS 2 30 31#define EXYNOS5420_ENABLE_AUTOMATIC_CORE_DOWN BIT(9) 32#define EXYNOS5420_USE_ARM_CORE_DOWN_STATE BIT(29) 33#define EXYNOS5420_USE_L2_COMMON_UP_STATE BIT(30) 34 35static void __iomem *ns_sram_base_addr; 36 37/* 38 * The common v7_exit_coherency_flush API could not be used because of the 39 * Erratum 799270 workaround. This macro is the same as the common one (in 40 * arch/arm/include/asm/cacheflush.h) except for the erratum handling. 41 */ 42#define exynos_v7_exit_coherency_flush(level) \ 43 asm volatile( \ 44 "stmfd sp!, {fp, ip}\n\t"\ 45 "mrc p15, 0, r0, c1, c0, 0 @ get SCTLR\n\t" \ 46 "bic r0, r0, #"__stringify(CR_C)"\n\t" \ 47 "mcr p15, 0, r0, c1, c0, 0 @ set SCTLR\n\t" \ 48 "isb\n\t"\ 49 "bl v7_flush_dcache_"__stringify(level)"\n\t" \ 50 "mrc p15, 0, r0, c1, c0, 1 @ get ACTLR\n\t" \ 51 "bic r0, r0, #(1 << 6) @ disable local coherency\n\t" \ 52 /* Dummy Load of a device register to avoid Erratum 799270 */ \ 53 "ldr r4, [%0]\n\t" \ 54 "and r4, r4, #0\n\t" \ 55 "orr r0, r0, r4\n\t" \ 56 "mcr p15, 0, r0, c1, c0, 1 @ set ACTLR\n\t" \ 57 "isb\n\t" \ 58 "dsb\n\t" \ 59 "ldmfd sp!, {fp, ip}" \ 60 : \ 61 : "Ir" (pmu_base_addr + S5P_INFORM0) \ 62 : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ 63 "r9", "r10", "lr", "memory") 64 65static int exynos_cpu_powerup(unsigned int cpu, unsigned int cluster) 66{ 67 unsigned int cpunr = cpu + (cluster * EXYNOS5420_CPUS_PER_CLUSTER); 68 69 pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster); 70 if (cpu >= EXYNOS5420_CPUS_PER_CLUSTER || 71 cluster >= EXYNOS5420_NR_CLUSTERS) 72 return -EINVAL; 73 74 if (!exynos_cpu_power_state(cpunr)) { 75 exynos_cpu_power_up(cpunr); 76 77 /* 78 * This assumes the cluster number of the big cores(Cortex A15) 79 * is 0 and the Little cores(Cortex A7) is 1. 80 * When the system was booted from the Little core, 81 * they should be reset during power up cpu. 82 */ 83 if (cluster && 84 cluster == MPIDR_AFFINITY_LEVEL(cpu_logical_map(0), 1)) { 85 /* 86 * Before we reset the Little cores, we should wait 87 * the SPARE2 register is set to 1 because the init 88 * codes of the iROM will set the register after 89 * initialization. 90 */ 91 while (!pmu_raw_readl(S5P_PMU_SPARE2)) 92 udelay(10); 93 94 pmu_raw_writel(EXYNOS5420_KFC_CORE_RESET(cpu), 95 EXYNOS_SWRESET); 96 } 97 } 98 99 return 0; 100} 101 102static int exynos_cluster_powerup(unsigned int cluster) 103{ 104 pr_debug("%s: cluster %u\n", __func__, cluster); 105 if (cluster >= EXYNOS5420_NR_CLUSTERS) 106 return -EINVAL; 107 108 exynos_cluster_power_up(cluster); 109 return 0; 110} 111 112static void exynos_cpu_powerdown_prepare(unsigned int cpu, unsigned int cluster) 113{ 114 unsigned int cpunr = cpu + (cluster * EXYNOS5420_CPUS_PER_CLUSTER); 115 116 pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster); 117 BUG_ON(cpu >= EXYNOS5420_CPUS_PER_CLUSTER || 118 cluster >= EXYNOS5420_NR_CLUSTERS); 119 exynos_cpu_power_down(cpunr); 120} 121 122static void exynos_cluster_powerdown_prepare(unsigned int cluster) 123{ 124 pr_debug("%s: cluster %u\n", __func__, cluster); 125 BUG_ON(cluster >= EXYNOS5420_NR_CLUSTERS); 126 exynos_cluster_power_down(cluster); 127} 128 129static void exynos_cpu_cache_disable(void) 130{ 131 /* Disable and flush the local CPU cache. */ 132 exynos_v7_exit_coherency_flush(louis); 133} 134 135static void exynos_cluster_cache_disable(void) 136{ 137 if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A15) { 138 /* 139 * On the Cortex-A15 we need to disable 140 * L2 prefetching before flushing the cache. 141 */ 142 asm volatile( 143 "mcr p15, 1, %0, c15, c0, 3\n\t" 144 "isb\n\t" 145 "dsb" 146 : : "r" (0x400)); 147 } 148 149 /* Flush all cache levels for this cluster. */ 150 exynos_v7_exit_coherency_flush(all); 151 152 /* 153 * Disable cluster-level coherency by masking 154 * incoming snoops and DVM messages: 155 */ 156 cci_disable_port_by_cpu(read_cpuid_mpidr()); 157} 158 159static int exynos_wait_for_powerdown(unsigned int cpu, unsigned int cluster) 160{ 161 unsigned int tries = 100; 162 unsigned int cpunr = cpu + (cluster * EXYNOS5420_CPUS_PER_CLUSTER); 163 164 pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster); 165 BUG_ON(cpu >= EXYNOS5420_CPUS_PER_CLUSTER || 166 cluster >= EXYNOS5420_NR_CLUSTERS); 167 168 /* Wait for the core state to be OFF */ 169 while (tries--) { 170 if ((exynos_cpu_power_state(cpunr) == 0)) 171 return 0; /* success: the CPU is halted */ 172 173 /* Otherwise, wait and retry: */ 174 msleep(1); 175 } 176 177 return -ETIMEDOUT; /* timeout */ 178} 179 180static void exynos_cpu_is_up(unsigned int cpu, unsigned int cluster) 181{ 182 /* especially when resuming: make sure power control is set */ 183 exynos_cpu_powerup(cpu, cluster); 184} 185 186static const struct mcpm_platform_ops exynos_power_ops = { 187 .cpu_powerup = exynos_cpu_powerup, 188 .cluster_powerup = exynos_cluster_powerup, 189 .cpu_powerdown_prepare = exynos_cpu_powerdown_prepare, 190 .cluster_powerdown_prepare = exynos_cluster_powerdown_prepare, 191 .cpu_cache_disable = exynos_cpu_cache_disable, 192 .cluster_cache_disable = exynos_cluster_cache_disable, 193 .wait_for_powerdown = exynos_wait_for_powerdown, 194 .cpu_is_up = exynos_cpu_is_up, 195}; 196 197/* 198 * Enable cluster-level coherency, in preparation for turning on the MMU. 199 */ 200static void __naked exynos_pm_power_up_setup(unsigned int affinity_level) 201{ 202 asm volatile ("\n" 203 "cmp r0, #1\n" 204 "bxne lr\n" 205 "b cci_enable_port_for_self"); 206} 207 208static const struct of_device_id exynos_dt_mcpm_match[] = { 209 { .compatible = "samsung,exynos5420" }, 210 { .compatible = "samsung,exynos5800" }, 211 {}, 212}; 213 214static void exynos_mcpm_setup_entry_point(void) 215{ 216 /* 217 * U-Boot SPL is hardcoded to jump to the start of ns_sram_base_addr 218 * as part of secondary_cpu_start(). Let's redirect it to the 219 * mcpm_entry_point(). This is done during both secondary boot-up as 220 * well as system resume. 221 */ 222 __raw_writel(0xe59f0000, ns_sram_base_addr); /* ldr r0, [pc, #0] */ 223 __raw_writel(0xe12fff10, ns_sram_base_addr + 4); /* bx r0 */ 224 __raw_writel(virt_to_phys(mcpm_entry_point), ns_sram_base_addr + 8); 225} 226 227static struct syscore_ops exynos_mcpm_syscore_ops = { 228 .resume = exynos_mcpm_setup_entry_point, 229}; 230 231static int __init exynos_mcpm_init(void) 232{ 233 struct device_node *node; 234 unsigned int value, i; 235 int ret; 236 237 node = of_find_matching_node(NULL, exynos_dt_mcpm_match); 238 if (!node) 239 return -ENODEV; 240 of_node_put(node); 241 242 if (!cci_probed()) 243 return -ENODEV; 244 245 node = of_find_compatible_node(NULL, NULL, 246 "samsung,exynos4210-sysram-ns"); 247 if (!node) 248 return -ENODEV; 249 250 ns_sram_base_addr = of_iomap(node, 0); 251 of_node_put(node); 252 if (!ns_sram_base_addr) { 253 pr_err("failed to map non-secure iRAM base address\n"); 254 return -ENOMEM; 255 } 256 257 /* 258 * To increase the stability of KFC reset we need to program 259 * the PMU SPARE3 register 260 */ 261 pmu_raw_writel(EXYNOS5420_SWRESET_KFC_SEL, S5P_PMU_SPARE3); 262 263 ret = mcpm_platform_register(&exynos_power_ops); 264 if (!ret) 265 ret = mcpm_sync_init(exynos_pm_power_up_setup); 266 if (!ret) 267 ret = mcpm_loopback(exynos_cluster_cache_disable); /* turn on the CCI */ 268 if (ret) { 269 iounmap(ns_sram_base_addr); 270 return ret; 271 } 272 273 mcpm_smp_set_ops(); 274 275 pr_info("Exynos MCPM support installed\n"); 276 277 /* 278 * On Exynos5420/5800 for the A15 and A7 clusters: 279 * 280 * EXYNOS5420_ENABLE_AUTOMATIC_CORE_DOWN ensures that all the cores 281 * in a cluster are turned off before turning off the cluster L2. 282 * 283 * EXYNOS5420_USE_ARM_CORE_DOWN_STATE ensures that a cores is powered 284 * off before waking it up. 285 * 286 * EXYNOS5420_USE_L2_COMMON_UP_STATE ensures that cluster L2 will be 287 * turned on before the first man is powered up. 288 */ 289 for (i = 0; i < EXYNOS5420_NR_CLUSTERS; i++) { 290 value = pmu_raw_readl(EXYNOS_COMMON_OPTION(i)); 291 value |= EXYNOS5420_ENABLE_AUTOMATIC_CORE_DOWN | 292 EXYNOS5420_USE_ARM_CORE_DOWN_STATE | 293 EXYNOS5420_USE_L2_COMMON_UP_STATE; 294 pmu_raw_writel(value, EXYNOS_COMMON_OPTION(i)); 295 } 296 297 exynos_mcpm_setup_entry_point(); 298 299 register_syscore_ops(&exynos_mcpm_syscore_ops); 300 301 return ret; 302} 303 304early_initcall(exynos_mcpm_init); 305