162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci// Copyright (C) ASPEED Technology Inc. 362306a36Sopenharmony_ci// Copyright IBM Corp. 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#include <linux/of_address.h> 662306a36Sopenharmony_ci#include <linux/io.h> 762306a36Sopenharmony_ci#include <linux/of.h> 862306a36Sopenharmony_ci#include <linux/smp.h> 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#define BOOT_ADDR 0x00 1162306a36Sopenharmony_ci#define BOOT_SIG 0x04 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_cistatic struct device_node *secboot_node; 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_cistatic int aspeed_g6_boot_secondary(unsigned int cpu, struct task_struct *idle) 1662306a36Sopenharmony_ci{ 1762306a36Sopenharmony_ci void __iomem *base; 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci base = of_iomap(secboot_node, 0); 2062306a36Sopenharmony_ci if (!base) { 2162306a36Sopenharmony_ci pr_err("could not map the secondary boot base!"); 2262306a36Sopenharmony_ci return -ENODEV; 2362306a36Sopenharmony_ci } 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci writel_relaxed(0, base + BOOT_ADDR); 2662306a36Sopenharmony_ci writel_relaxed(__pa_symbol(secondary_startup_arm), base + BOOT_ADDR); 2762306a36Sopenharmony_ci writel_relaxed((0xABBAAB00 | (cpu & 0xff)), base + BOOT_SIG); 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci dsb_sev(); 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci iounmap(base); 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci return 0; 3462306a36Sopenharmony_ci} 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_cistatic void __init aspeed_g6_smp_prepare_cpus(unsigned int max_cpus) 3762306a36Sopenharmony_ci{ 3862306a36Sopenharmony_ci void __iomem *base; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci secboot_node = of_find_compatible_node(NULL, NULL, "aspeed,ast2600-smpmem"); 4162306a36Sopenharmony_ci if (!secboot_node) { 4262306a36Sopenharmony_ci pr_err("secboot device node found!!\n"); 4362306a36Sopenharmony_ci return; 4462306a36Sopenharmony_ci } 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci base = of_iomap(secboot_node, 0); 4762306a36Sopenharmony_ci if (!base) { 4862306a36Sopenharmony_ci pr_err("could not map the secondary boot base!"); 4962306a36Sopenharmony_ci return; 5062306a36Sopenharmony_ci } 5162306a36Sopenharmony_ci __raw_writel(0xBADABABA, base + BOOT_SIG); 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci iounmap(base); 5462306a36Sopenharmony_ci} 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cistatic const struct smp_operations aspeed_smp_ops __initconst = { 5762306a36Sopenharmony_ci .smp_prepare_cpus = aspeed_g6_smp_prepare_cpus, 5862306a36Sopenharmony_ci .smp_boot_secondary = aspeed_g6_boot_secondary, 5962306a36Sopenharmony_ci}; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ciCPU_METHOD_OF_DECLARE(aspeed_smp, "aspeed,ast2600-smp", &aspeed_smp_ops); 62