18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * SMP support for R-Mobile / SH-Mobile - sh73a0 portion
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2010  Magnus Damm
68c2ecf20Sopenharmony_ci * Copyright (C) 2010  Takashi Yoshii
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci#include <linux/kernel.h>
98c2ecf20Sopenharmony_ci#include <linux/init.h>
108c2ecf20Sopenharmony_ci#include <linux/smp.h>
118c2ecf20Sopenharmony_ci#include <linux/io.h>
128c2ecf20Sopenharmony_ci#include <linux/delay.h>
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include <asm/smp_plat.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#include "common.h"
178c2ecf20Sopenharmony_ci#include "sh73a0.h"
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci#define WUPCR		IOMEM(0xe6151010)
208c2ecf20Sopenharmony_ci#define SRESCR		IOMEM(0xe6151018)
218c2ecf20Sopenharmony_ci#define PSTR		IOMEM(0xe6151040)
228c2ecf20Sopenharmony_ci#define SBAR		IOMEM(0xe6180020)
238c2ecf20Sopenharmony_ci#define APARMBAREA	IOMEM(0xe6f10020)
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci#define SH73A0_SCU_BASE 0xf0000000
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_cistatic int sh73a0_boot_secondary(unsigned int cpu, struct task_struct *idle)
288c2ecf20Sopenharmony_ci{
298c2ecf20Sopenharmony_ci	unsigned int lcpu = cpu_logical_map(cpu);
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci	if (((__raw_readl(PSTR) >> (4 * lcpu)) & 3) == 3)
328c2ecf20Sopenharmony_ci		__raw_writel(1 << lcpu, WUPCR);	/* wake up */
338c2ecf20Sopenharmony_ci	else
348c2ecf20Sopenharmony_ci		__raw_writel(1 << lcpu, SRESCR);	/* reset */
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci	return 0;
378c2ecf20Sopenharmony_ci}
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_cistatic void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus)
408c2ecf20Sopenharmony_ci{
418c2ecf20Sopenharmony_ci	/* Map the reset vector (in headsmp.S) */
428c2ecf20Sopenharmony_ci	__raw_writel(0, APARMBAREA);      /* 4k */
438c2ecf20Sopenharmony_ci	__raw_writel(__pa(shmobile_boot_vector), SBAR);
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci	/* setup sh73a0 specific SCU bits */
468c2ecf20Sopenharmony_ci	shmobile_smp_scu_prepare_cpus(SH73A0_SCU_BASE, max_cpus);
478c2ecf20Sopenharmony_ci}
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ciconst struct smp_operations sh73a0_smp_ops __initconst = {
508c2ecf20Sopenharmony_ci	.smp_prepare_cpus	= sh73a0_smp_prepare_cpus,
518c2ecf20Sopenharmony_ci	.smp_boot_secondary	= sh73a0_boot_secondary,
528c2ecf20Sopenharmony_ci#ifdef CONFIG_HOTPLUG_CPU
538c2ecf20Sopenharmony_ci	.cpu_can_disable	= shmobile_smp_cpu_can_disable,
548c2ecf20Sopenharmony_ci	.cpu_die		= shmobile_smp_scu_cpu_die,
558c2ecf20Sopenharmony_ci	.cpu_kill		= shmobile_smp_scu_cpu_kill,
568c2ecf20Sopenharmony_ci#endif
578c2ecf20Sopenharmony_ci};
58