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