18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2013 MundoReader S.L. 48c2ecf20Sopenharmony_ci * Author: Heiko Stuebner <heiko@sntech.de> 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <linux/delay.h> 88c2ecf20Sopenharmony_ci#include <linux/init.h> 98c2ecf20Sopenharmony_ci#include <linux/smp.h> 108c2ecf20Sopenharmony_ci#include <linux/io.h> 118c2ecf20Sopenharmony_ci#include <linux/of.h> 128c2ecf20Sopenharmony_ci#include <linux/of_address.h> 138c2ecf20Sopenharmony_ci#include <linux/regmap.h> 148c2ecf20Sopenharmony_ci#include <linux/mfd/syscon.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include <linux/reset.h> 178c2ecf20Sopenharmony_ci#include <linux/cpu.h> 188c2ecf20Sopenharmony_ci#include <asm/cacheflush.h> 198c2ecf20Sopenharmony_ci#include <asm/cp15.h> 208c2ecf20Sopenharmony_ci#include <asm/smp_scu.h> 218c2ecf20Sopenharmony_ci#include <asm/smp_plat.h> 228c2ecf20Sopenharmony_ci#include <asm/mach/map.h> 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#include "core.h" 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_cistatic void __iomem *scu_base_addr; 278c2ecf20Sopenharmony_cistatic void __iomem *sram_base_addr; 288c2ecf20Sopenharmony_cistatic int ncores; 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#define PMU_PWRDN_CON 0x08 318c2ecf20Sopenharmony_ci#define PMU_PWRDN_ST 0x0c 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#define PMU_PWRDN_SCU 4 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cistatic struct regmap *pmu; 368c2ecf20Sopenharmony_cistatic int has_pmu = true; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_cistatic int pmu_power_domain_is_on(int pd) 398c2ecf20Sopenharmony_ci{ 408c2ecf20Sopenharmony_ci u32 val; 418c2ecf20Sopenharmony_ci int ret; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci ret = regmap_read(pmu, PMU_PWRDN_ST, &val); 448c2ecf20Sopenharmony_ci if (ret < 0) 458c2ecf20Sopenharmony_ci return ret; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci return !(val & BIT(pd)); 488c2ecf20Sopenharmony_ci} 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_cistatic struct reset_control *rockchip_get_core_reset(int cpu) 518c2ecf20Sopenharmony_ci{ 528c2ecf20Sopenharmony_ci struct device *dev = get_cpu_device(cpu); 538c2ecf20Sopenharmony_ci struct device_node *np; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci /* The cpu device is only available after the initial core bringup */ 568c2ecf20Sopenharmony_ci if (dev) 578c2ecf20Sopenharmony_ci np = dev->of_node; 588c2ecf20Sopenharmony_ci else 598c2ecf20Sopenharmony_ci np = of_get_cpu_node(cpu, NULL); 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci return of_reset_control_get_exclusive(np, NULL); 628c2ecf20Sopenharmony_ci} 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_cistatic int pmu_set_power_domain(int pd, bool on) 658c2ecf20Sopenharmony_ci{ 668c2ecf20Sopenharmony_ci u32 val = (on) ? 0 : BIT(pd); 678c2ecf20Sopenharmony_ci struct reset_control *rstc = rockchip_get_core_reset(pd); 688c2ecf20Sopenharmony_ci int ret; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci if (IS_ERR(rstc) && read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) { 718c2ecf20Sopenharmony_ci pr_err("%s: could not get reset control for core %d\n", 728c2ecf20Sopenharmony_ci __func__, pd); 738c2ecf20Sopenharmony_ci return PTR_ERR(rstc); 748c2ecf20Sopenharmony_ci } 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci /* 778c2ecf20Sopenharmony_ci * We need to soft reset the cpu when we turn off the cpu power domain, 788c2ecf20Sopenharmony_ci * or else the active processors might be stalled when the individual 798c2ecf20Sopenharmony_ci * processor is powered down. 808c2ecf20Sopenharmony_ci */ 818c2ecf20Sopenharmony_ci if (!IS_ERR(rstc) && !on) 828c2ecf20Sopenharmony_ci reset_control_assert(rstc); 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci if (has_pmu) { 858c2ecf20Sopenharmony_ci ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val); 868c2ecf20Sopenharmony_ci if (ret < 0) { 878c2ecf20Sopenharmony_ci pr_err("%s: could not update power domain\n", 888c2ecf20Sopenharmony_ci __func__); 898c2ecf20Sopenharmony_ci return ret; 908c2ecf20Sopenharmony_ci } 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci ret = -1; 938c2ecf20Sopenharmony_ci while (ret != on) { 948c2ecf20Sopenharmony_ci ret = pmu_power_domain_is_on(pd); 958c2ecf20Sopenharmony_ci if (ret < 0) { 968c2ecf20Sopenharmony_ci pr_err("%s: could not read power domain state\n", 978c2ecf20Sopenharmony_ci __func__); 988c2ecf20Sopenharmony_ci return ret; 998c2ecf20Sopenharmony_ci } 1008c2ecf20Sopenharmony_ci } 1018c2ecf20Sopenharmony_ci } 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci if (!IS_ERR(rstc)) { 1048c2ecf20Sopenharmony_ci if (on) 1058c2ecf20Sopenharmony_ci reset_control_deassert(rstc); 1068c2ecf20Sopenharmony_ci reset_control_put(rstc); 1078c2ecf20Sopenharmony_ci } 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci return 0; 1108c2ecf20Sopenharmony_ci} 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci/* 1138c2ecf20Sopenharmony_ci * Handling of CPU cores 1148c2ecf20Sopenharmony_ci */ 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_cistatic int rockchip_boot_secondary(unsigned int cpu, struct task_struct *idle) 1178c2ecf20Sopenharmony_ci{ 1188c2ecf20Sopenharmony_ci int ret; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci if (!sram_base_addr || (has_pmu && !pmu)) { 1218c2ecf20Sopenharmony_ci pr_err("%s: sram or pmu missing for cpu boot\n", __func__); 1228c2ecf20Sopenharmony_ci return -ENXIO; 1238c2ecf20Sopenharmony_ci } 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci if (cpu >= ncores) { 1268c2ecf20Sopenharmony_ci pr_err("%s: cpu %d outside maximum number of cpus %d\n", 1278c2ecf20Sopenharmony_ci __func__, cpu, ncores); 1288c2ecf20Sopenharmony_ci return -ENXIO; 1298c2ecf20Sopenharmony_ci } 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci /* start the core */ 1328c2ecf20Sopenharmony_ci ret = pmu_set_power_domain(0 + cpu, true); 1338c2ecf20Sopenharmony_ci if (ret < 0) 1348c2ecf20Sopenharmony_ci return ret; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) { 1378c2ecf20Sopenharmony_ci /* 1388c2ecf20Sopenharmony_ci * We communicate with the bootrom to active the cpus other 1398c2ecf20Sopenharmony_ci * than cpu0, after a blob of initialize code, they will 1408c2ecf20Sopenharmony_ci * stay at wfe state, once they are actived, they will check 1418c2ecf20Sopenharmony_ci * the mailbox: 1428c2ecf20Sopenharmony_ci * sram_base_addr + 4: 0xdeadbeaf 1438c2ecf20Sopenharmony_ci * sram_base_addr + 8: start address for pc 1448c2ecf20Sopenharmony_ci * The cpu0 need to wait the other cpus other than cpu0 entering 1458c2ecf20Sopenharmony_ci * the wfe state.The wait time is affected by many aspects. 1468c2ecf20Sopenharmony_ci * (e.g: cpu frequency, bootrom frequency, sram frequency, ...) 1478c2ecf20Sopenharmony_ci */ 1488c2ecf20Sopenharmony_ci mdelay(1); /* ensure the cpus other than cpu0 to startup */ 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci writel(__pa_symbol(secondary_startup), sram_base_addr + 8); 1518c2ecf20Sopenharmony_ci writel(0xDEADBEAF, sram_base_addr + 4); 1528c2ecf20Sopenharmony_ci dsb_sev(); 1538c2ecf20Sopenharmony_ci } 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci return 0; 1568c2ecf20Sopenharmony_ci} 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci/** 1598c2ecf20Sopenharmony_ci * rockchip_smp_prepare_sram - populate necessary sram block 1608c2ecf20Sopenharmony_ci * Starting cores execute the code residing at the start of the on-chip sram 1618c2ecf20Sopenharmony_ci * after power-on. Therefore make sure, this sram region is reserved and 1628c2ecf20Sopenharmony_ci * big enough. After this check, copy the trampoline code that directs the 1638c2ecf20Sopenharmony_ci * core to the real startup code in ram into the sram-region. 1648c2ecf20Sopenharmony_ci * @node: mmio-sram device node 1658c2ecf20Sopenharmony_ci */ 1668c2ecf20Sopenharmony_cistatic int __init rockchip_smp_prepare_sram(struct device_node *node) 1678c2ecf20Sopenharmony_ci{ 1688c2ecf20Sopenharmony_ci unsigned int trampoline_sz = &rockchip_secondary_trampoline_end - 1698c2ecf20Sopenharmony_ci &rockchip_secondary_trampoline; 1708c2ecf20Sopenharmony_ci struct resource res; 1718c2ecf20Sopenharmony_ci unsigned int rsize; 1728c2ecf20Sopenharmony_ci int ret; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci ret = of_address_to_resource(node, 0, &res); 1758c2ecf20Sopenharmony_ci if (ret < 0) { 1768c2ecf20Sopenharmony_ci pr_err("%s: could not get address for node %pOF\n", 1778c2ecf20Sopenharmony_ci __func__, node); 1788c2ecf20Sopenharmony_ci return ret; 1798c2ecf20Sopenharmony_ci } 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci rsize = resource_size(&res); 1828c2ecf20Sopenharmony_ci if (rsize < trampoline_sz) { 1838c2ecf20Sopenharmony_ci pr_err("%s: reserved block with size 0x%x is too small for trampoline size 0x%x\n", 1848c2ecf20Sopenharmony_ci __func__, rsize, trampoline_sz); 1858c2ecf20Sopenharmony_ci return -EINVAL; 1868c2ecf20Sopenharmony_ci } 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci /* set the boot function for the sram code */ 1898c2ecf20Sopenharmony_ci rockchip_boot_fn = __pa_symbol(secondary_startup); 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci /* copy the trampoline to sram, that runs during startup of the core */ 1928c2ecf20Sopenharmony_ci memcpy(sram_base_addr, &rockchip_secondary_trampoline, trampoline_sz); 1938c2ecf20Sopenharmony_ci flush_cache_all(); 1948c2ecf20Sopenharmony_ci outer_clean_range(0, trampoline_sz); 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci dsb_sev(); 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci return 0; 1998c2ecf20Sopenharmony_ci} 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_cistatic const struct regmap_config rockchip_pmu_regmap_config = { 2028c2ecf20Sopenharmony_ci .name = "rockchip-pmu", 2038c2ecf20Sopenharmony_ci .reg_bits = 32, 2048c2ecf20Sopenharmony_ci .val_bits = 32, 2058c2ecf20Sopenharmony_ci .reg_stride = 4, 2068c2ecf20Sopenharmony_ci}; 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_cistatic int __init rockchip_smp_prepare_pmu(void) 2098c2ecf20Sopenharmony_ci{ 2108c2ecf20Sopenharmony_ci struct device_node *node; 2118c2ecf20Sopenharmony_ci void __iomem *pmu_base; 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci /* 2148c2ecf20Sopenharmony_ci * This function is only called via smp_ops->smp_prepare_cpu(). 2158c2ecf20Sopenharmony_ci * That only happens if a "/cpus" device tree node exists 2168c2ecf20Sopenharmony_ci * and has an "enable-method" property that selects the SMP 2178c2ecf20Sopenharmony_ci * operations defined herein. 2188c2ecf20Sopenharmony_ci */ 2198c2ecf20Sopenharmony_ci node = of_find_node_by_path("/cpus"); 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci pmu = syscon_regmap_lookup_by_phandle(node, "rockchip,pmu"); 2228c2ecf20Sopenharmony_ci of_node_put(node); 2238c2ecf20Sopenharmony_ci if (!IS_ERR(pmu)) 2248c2ecf20Sopenharmony_ci return 0; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci pmu = syscon_regmap_lookup_by_compatible("rockchip,rk3066-pmu"); 2278c2ecf20Sopenharmony_ci if (!IS_ERR(pmu)) 2288c2ecf20Sopenharmony_ci return 0; 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci /* fallback, create our own regmap for the pmu area */ 2318c2ecf20Sopenharmony_ci pmu = NULL; 2328c2ecf20Sopenharmony_ci node = of_find_compatible_node(NULL, NULL, "rockchip,rk3066-pmu"); 2338c2ecf20Sopenharmony_ci if (!node) { 2348c2ecf20Sopenharmony_ci pr_err("%s: could not find pmu dt node\n", __func__); 2358c2ecf20Sopenharmony_ci return -ENODEV; 2368c2ecf20Sopenharmony_ci } 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci pmu_base = of_iomap(node, 0); 2398c2ecf20Sopenharmony_ci of_node_put(node); 2408c2ecf20Sopenharmony_ci if (!pmu_base) { 2418c2ecf20Sopenharmony_ci pr_err("%s: could not map pmu registers\n", __func__); 2428c2ecf20Sopenharmony_ci return -ENOMEM; 2438c2ecf20Sopenharmony_ci } 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci pmu = regmap_init_mmio(NULL, pmu_base, &rockchip_pmu_regmap_config); 2468c2ecf20Sopenharmony_ci if (IS_ERR(pmu)) { 2478c2ecf20Sopenharmony_ci int ret = PTR_ERR(pmu); 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci iounmap(pmu_base); 2508c2ecf20Sopenharmony_ci pmu = NULL; 2518c2ecf20Sopenharmony_ci pr_err("%s: regmap init failed\n", __func__); 2528c2ecf20Sopenharmony_ci return ret; 2538c2ecf20Sopenharmony_ci } 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci return 0; 2568c2ecf20Sopenharmony_ci} 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_cistatic void __init rockchip_smp_prepare_cpus(unsigned int max_cpus) 2598c2ecf20Sopenharmony_ci{ 2608c2ecf20Sopenharmony_ci struct device_node *node; 2618c2ecf20Sopenharmony_ci unsigned int i; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci node = of_find_compatible_node(NULL, NULL, "rockchip,rk3066-smp-sram"); 2648c2ecf20Sopenharmony_ci if (!node) { 2658c2ecf20Sopenharmony_ci pr_err("%s: could not find sram dt node\n", __func__); 2668c2ecf20Sopenharmony_ci return; 2678c2ecf20Sopenharmony_ci } 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci sram_base_addr = of_iomap(node, 0); 2708c2ecf20Sopenharmony_ci if (!sram_base_addr) { 2718c2ecf20Sopenharmony_ci pr_err("%s: could not map sram registers\n", __func__); 2728c2ecf20Sopenharmony_ci of_node_put(node); 2738c2ecf20Sopenharmony_ci return; 2748c2ecf20Sopenharmony_ci } 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci if (has_pmu && rockchip_smp_prepare_pmu()) { 2778c2ecf20Sopenharmony_ci of_node_put(node); 2788c2ecf20Sopenharmony_ci return; 2798c2ecf20Sopenharmony_ci } 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) { 2828c2ecf20Sopenharmony_ci if (rockchip_smp_prepare_sram(node)) { 2838c2ecf20Sopenharmony_ci of_node_put(node); 2848c2ecf20Sopenharmony_ci return; 2858c2ecf20Sopenharmony_ci } 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci /* enable the SCU power domain */ 2888c2ecf20Sopenharmony_ci pmu_set_power_domain(PMU_PWRDN_SCU, true); 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci of_node_put(node); 2918c2ecf20Sopenharmony_ci node = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu"); 2928c2ecf20Sopenharmony_ci if (!node) { 2938c2ecf20Sopenharmony_ci pr_err("%s: missing scu\n", __func__); 2948c2ecf20Sopenharmony_ci return; 2958c2ecf20Sopenharmony_ci } 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci scu_base_addr = of_iomap(node, 0); 2988c2ecf20Sopenharmony_ci if (!scu_base_addr) { 2998c2ecf20Sopenharmony_ci pr_err("%s: could not map scu registers\n", __func__); 3008c2ecf20Sopenharmony_ci of_node_put(node); 3018c2ecf20Sopenharmony_ci return; 3028c2ecf20Sopenharmony_ci } 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci /* 3058c2ecf20Sopenharmony_ci * While the number of cpus is gathered from dt, also get the 3068c2ecf20Sopenharmony_ci * number of cores from the scu to verify this value when 3078c2ecf20Sopenharmony_ci * booting the cores. 3088c2ecf20Sopenharmony_ci */ 3098c2ecf20Sopenharmony_ci ncores = scu_get_core_count(scu_base_addr); 3108c2ecf20Sopenharmony_ci pr_err("%s: ncores %d\n", __func__, ncores); 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci scu_enable(scu_base_addr); 3138c2ecf20Sopenharmony_ci } else { 3148c2ecf20Sopenharmony_ci unsigned int l2ctlr; 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci asm ("mrc p15, 1, %0, c9, c0, 2\n" : "=r" (l2ctlr)); 3178c2ecf20Sopenharmony_ci ncores = ((l2ctlr >> 24) & 0x3) + 1; 3188c2ecf20Sopenharmony_ci } 3198c2ecf20Sopenharmony_ci of_node_put(node); 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci /* Make sure that all cores except the first are really off */ 3228c2ecf20Sopenharmony_ci for (i = 1; i < ncores; i++) 3238c2ecf20Sopenharmony_ci pmu_set_power_domain(0 + i, false); 3248c2ecf20Sopenharmony_ci} 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_cistatic void __init rk3036_smp_prepare_cpus(unsigned int max_cpus) 3278c2ecf20Sopenharmony_ci{ 3288c2ecf20Sopenharmony_ci has_pmu = false; 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci rockchip_smp_prepare_cpus(max_cpus); 3318c2ecf20Sopenharmony_ci} 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci#ifdef CONFIG_HOTPLUG_CPU 3348c2ecf20Sopenharmony_cistatic int rockchip_cpu_kill(unsigned int cpu) 3358c2ecf20Sopenharmony_ci{ 3368c2ecf20Sopenharmony_ci /* 3378c2ecf20Sopenharmony_ci * We need a delay here to ensure that the dying CPU can finish 3388c2ecf20Sopenharmony_ci * executing v7_coherency_exit() and reach the WFI/WFE state 3398c2ecf20Sopenharmony_ci * prior to having the power domain disabled. 3408c2ecf20Sopenharmony_ci */ 3418c2ecf20Sopenharmony_ci mdelay(1); 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci pmu_set_power_domain(0 + cpu, false); 3448c2ecf20Sopenharmony_ci return 1; 3458c2ecf20Sopenharmony_ci} 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_cistatic void rockchip_cpu_die(unsigned int cpu) 3488c2ecf20Sopenharmony_ci{ 3498c2ecf20Sopenharmony_ci v7_exit_coherency_flush(louis); 3508c2ecf20Sopenharmony_ci while (1) 3518c2ecf20Sopenharmony_ci cpu_do_idle(); 3528c2ecf20Sopenharmony_ci} 3538c2ecf20Sopenharmony_ci#endif 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_cistatic const struct smp_operations rk3036_smp_ops __initconst = { 3568c2ecf20Sopenharmony_ci .smp_prepare_cpus = rk3036_smp_prepare_cpus, 3578c2ecf20Sopenharmony_ci .smp_boot_secondary = rockchip_boot_secondary, 3588c2ecf20Sopenharmony_ci#ifdef CONFIG_HOTPLUG_CPU 3598c2ecf20Sopenharmony_ci .cpu_kill = rockchip_cpu_kill, 3608c2ecf20Sopenharmony_ci .cpu_die = rockchip_cpu_die, 3618c2ecf20Sopenharmony_ci#endif 3628c2ecf20Sopenharmony_ci}; 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_cistatic const struct smp_operations rockchip_smp_ops __initconst = { 3658c2ecf20Sopenharmony_ci .smp_prepare_cpus = rockchip_smp_prepare_cpus, 3668c2ecf20Sopenharmony_ci .smp_boot_secondary = rockchip_boot_secondary, 3678c2ecf20Sopenharmony_ci#ifdef CONFIG_HOTPLUG_CPU 3688c2ecf20Sopenharmony_ci .cpu_kill = rockchip_cpu_kill, 3698c2ecf20Sopenharmony_ci .cpu_die = rockchip_cpu_die, 3708c2ecf20Sopenharmony_ci#endif 3718c2ecf20Sopenharmony_ci}; 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ciCPU_METHOD_OF_DECLARE(rk3036_smp, "rockchip,rk3036-smp", &rk3036_smp_ops); 3748c2ecf20Sopenharmony_ciCPU_METHOD_OF_DECLARE(rk3066_smp, "rockchip,rk3066-smp", &rockchip_smp_ops); 375