Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 //
0003 // Copyright (C) 2012 Samsung Electronics.
0004 // Kyungmin Park <kyungmin.park@samsung.com>
0005 // Tomasz Figa <t.figa@samsung.com>
0006 
0007 #include <linux/kernel.h>
0008 #include <linux/io.h>
0009 #include <linux/init.h>
0010 #include <linux/of.h>
0011 #include <linux/of_address.h>
0012 
0013 #include <asm/cacheflush.h>
0014 #include <asm/cputype.h>
0015 #include <asm/firmware.h>
0016 #include <asm/hardware/cache-l2x0.h>
0017 #include <asm/suspend.h>
0018 
0019 #include "common.h"
0020 #include "smc.h"
0021 
0022 #define EXYNOS_BOOT_ADDR    0x8
0023 #define EXYNOS_BOOT_FLAG    0xc
0024 
0025 static void exynos_save_cp15(void)
0026 {
0027     /* Save Power control and Diagnostic registers */
0028     asm ("mrc p15, 0, %0, c15, c0, 0\n"
0029          "mrc p15, 0, %1, c15, c0, 1\n"
0030          : "=r" (cp15_save_power), "=r" (cp15_save_diag)
0031          : : "cc");
0032 }
0033 
0034 static int exynos_do_idle(unsigned long mode)
0035 {
0036     switch (mode) {
0037     case FW_DO_IDLE_AFTR:
0038         if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
0039             exynos_save_cp15();
0040         writel_relaxed(__pa_symbol(exynos_cpu_resume_ns),
0041                    sysram_ns_base_addr + 0x24);
0042         writel_relaxed(EXYNOS_AFTR_MAGIC, sysram_ns_base_addr + 0x20);
0043         if (soc_is_exynos3250()) {
0044             flush_cache_all();
0045             exynos_smc(SMC_CMD_SAVE, OP_TYPE_CORE,
0046                    SMC_POWERSTATE_IDLE, 0);
0047             exynos_smc(SMC_CMD_SHUTDOWN, OP_TYPE_CLUSTER,
0048                    SMC_POWERSTATE_IDLE, 0);
0049         } else
0050             exynos_smc(SMC_CMD_CPU0AFTR, 0, 0, 0);
0051         break;
0052     case FW_DO_IDLE_SLEEP:
0053         exynos_smc(SMC_CMD_SLEEP, 0, 0, 0);
0054     }
0055     return 0;
0056 }
0057 
0058 static int exynos_cpu_boot(int cpu)
0059 {
0060     /*
0061      * Exynos3250 doesn't need to send smc command for secondary CPU boot
0062      * because Exynos3250 removes WFE in secure mode.
0063      *
0064      * On Exynos5 devices the call is ignored by trustzone firmware.
0065      */
0066     if (!soc_is_exynos4210() && !soc_is_exynos4412())
0067         return 0;
0068 
0069     /*
0070      * The second parameter of SMC_CMD_CPU1BOOT command means CPU id.
0071      */
0072     exynos_smc(SMC_CMD_CPU1BOOT, cpu, 0, 0);
0073     return 0;
0074 }
0075 
0076 static int exynos_set_cpu_boot_addr(int cpu, unsigned long boot_addr)
0077 {
0078     void __iomem *boot_reg;
0079 
0080     if (!sysram_ns_base_addr)
0081         return -ENODEV;
0082 
0083     boot_reg = sysram_ns_base_addr + 0x1c;
0084 
0085     /*
0086      * Almost all Exynos-series of SoCs that run in secure mode don't need
0087      * additional offset for every CPU, with Exynos4412 being the only
0088      * exception.
0089      */
0090     if (soc_is_exynos4412())
0091         boot_reg += 4 * cpu;
0092 
0093     writel_relaxed(boot_addr, boot_reg);
0094     return 0;
0095 }
0096 
0097 static int exynos_get_cpu_boot_addr(int cpu, unsigned long *boot_addr)
0098 {
0099     void __iomem *boot_reg;
0100 
0101     if (!sysram_ns_base_addr)
0102         return -ENODEV;
0103 
0104     boot_reg = sysram_ns_base_addr + 0x1c;
0105 
0106     if (soc_is_exynos4412())
0107         boot_reg += 4 * cpu;
0108 
0109     *boot_addr = readl_relaxed(boot_reg);
0110     return 0;
0111 }
0112 
0113 static int exynos_cpu_suspend(unsigned long arg)
0114 {
0115     flush_cache_all();
0116     outer_flush_all();
0117 
0118     exynos_smc(SMC_CMD_SLEEP, 0, 0, 0);
0119 
0120     pr_info("Failed to suspend the system\n");
0121     writel(0, sysram_ns_base_addr + EXYNOS_BOOT_FLAG);
0122     return 1;
0123 }
0124 
0125 static int exynos_suspend(void)
0126 {
0127     if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
0128         exynos_save_cp15();
0129 
0130     writel(EXYNOS_SLEEP_MAGIC, sysram_ns_base_addr + EXYNOS_BOOT_FLAG);
0131     writel(__pa_symbol(exynos_cpu_resume_ns),
0132         sysram_ns_base_addr + EXYNOS_BOOT_ADDR);
0133 
0134     return cpu_suspend(0, exynos_cpu_suspend);
0135 }
0136 
0137 static int exynos_resume(void)
0138 {
0139     writel(0, sysram_ns_base_addr + EXYNOS_BOOT_FLAG);
0140 
0141     return 0;
0142 }
0143 
0144 static const struct firmware_ops exynos_firmware_ops = {
0145     .do_idle        = IS_ENABLED(CONFIG_EXYNOS_CPU_SUSPEND) ? exynos_do_idle : NULL,
0146     .set_cpu_boot_addr  = exynos_set_cpu_boot_addr,
0147     .get_cpu_boot_addr  = exynos_get_cpu_boot_addr,
0148     .cpu_boot       = exynos_cpu_boot,
0149     .suspend        = IS_ENABLED(CONFIG_PM_SLEEP) ? exynos_suspend : NULL,
0150     .resume         = IS_ENABLED(CONFIG_EXYNOS_CPU_SUSPEND) ? exynos_resume : NULL,
0151 };
0152 
0153 static void exynos_l2_write_sec(unsigned long val, unsigned reg)
0154 {
0155     static int l2cache_enabled;
0156 
0157     switch (reg) {
0158     case L2X0_CTRL:
0159         if (val & L2X0_CTRL_EN) {
0160             /*
0161              * Before the cache can be enabled, due to firmware
0162              * design, SMC_CMD_L2X0INVALL must be called.
0163              */
0164             if (!l2cache_enabled) {
0165                 exynos_smc(SMC_CMD_L2X0INVALL, 0, 0, 0);
0166                 l2cache_enabled = 1;
0167             }
0168         } else {
0169             l2cache_enabled = 0;
0170         }
0171         exynos_smc(SMC_CMD_L2X0CTRL, val, 0, 0);
0172         break;
0173 
0174     case L2X0_DEBUG_CTRL:
0175         exynos_smc(SMC_CMD_L2X0DEBUG, val, 0, 0);
0176         break;
0177 
0178     default:
0179         WARN_ONCE(1, "%s: ignoring write to reg 0x%x\n", __func__, reg);
0180     }
0181 }
0182 
0183 static void exynos_l2_configure(const struct l2x0_regs *regs)
0184 {
0185     exynos_smc(SMC_CMD_L2X0SETUP1, regs->tag_latency, regs->data_latency,
0186            regs->prefetch_ctrl);
0187     exynos_smc(SMC_CMD_L2X0SETUP2, regs->pwr_ctrl, regs->aux_ctrl, 0);
0188 }
0189 
0190 bool __init exynos_secure_firmware_available(void)
0191 {
0192     struct device_node *nd;
0193     const __be32 *addr;
0194 
0195     nd = of_find_compatible_node(NULL, NULL,
0196                     "samsung,secure-firmware");
0197     if (!nd)
0198         return false;
0199 
0200     addr = of_get_address(nd, 0, NULL, NULL);
0201     of_node_put(nd);
0202     if (!addr) {
0203         pr_err("%s: No address specified.\n", __func__);
0204         return false;
0205     }
0206 
0207     return true;
0208 }
0209 
0210 void __init exynos_firmware_init(void)
0211 {
0212     if (!exynos_secure_firmware_available())
0213         return;
0214 
0215     pr_info("Running under secure firmware.\n");
0216 
0217     register_firmware_ops(&exynos_firmware_ops);
0218 
0219     /*
0220      * Exynos 4 SoCs (based on Cortex A9 and equipped with L2C-310),
0221      * running under secure firmware, require certain registers of L2
0222      * cache controller to be written in secure mode. Here .write_sec
0223      * callback is provided to perform necessary SMC calls.
0224      */
0225     if (IS_ENABLED(CONFIG_CACHE_L2X0) &&
0226         read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) {
0227         outer_cache.write_sec = exynos_l2_write_sec;
0228         outer_cache.configure = exynos_l2_configure;
0229     }
0230 }
0231 
0232 #define REG_CPU_STATE_ADDR  (sysram_ns_base_addr + 0x28)
0233 #define BOOT_MODE_MASK      0x1f
0234 
0235 void exynos_set_boot_flag(unsigned int cpu, unsigned int mode)
0236 {
0237     unsigned int tmp;
0238 
0239     tmp = readl_relaxed(REG_CPU_STATE_ADDR + cpu * 4);
0240 
0241     if (mode & BOOT_MODE_MASK)
0242         tmp &= ~BOOT_MODE_MASK;
0243 
0244     tmp |= mode;
0245     writel_relaxed(tmp, REG_CPU_STATE_ADDR + cpu * 4);
0246 }
0247 
0248 void exynos_clear_boot_flag(unsigned int cpu, unsigned int mode)
0249 {
0250     unsigned int tmp;
0251 
0252     tmp = readl_relaxed(REG_CPU_STATE_ADDR + cpu * 4);
0253     tmp &= ~mode;
0254     writel_relaxed(tmp, REG_CPU_STATE_ADDR + cpu * 4);
0255 }