^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2002 ARM Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2008 STMicroelctronics.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2009 ST-Ericsson.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * This file is based on arm realview platform
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/smp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <asm/cacheflush.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <asm/smp_plat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <asm/smp_scu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "db8500-regs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) /* Magic triggers in backup RAM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define UX500_CPU1_JUMPADDR_OFFSET 0x1FF4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define UX500_CPU1_WAKEMAGIC_OFFSET 0x1FF0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static void __iomem *backupram;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static void __init ux500_smp_prepare_cpus(unsigned int max_cpus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) struct device_node *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static void __iomem *scu_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) unsigned int ncores;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) np = of_find_compatible_node(NULL, NULL, "ste,dbx500-backupram");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) if (!np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) pr_err("No backupram base address\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) backupram = of_iomap(np, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) of_node_put(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) if (!backupram) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) pr_err("No backupram remap\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (!np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) pr_err("No SCU base address\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) scu_base = of_iomap(np, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) of_node_put(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (!scu_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) pr_err("No SCU remap\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) scu_enable(scu_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) ncores = scu_get_core_count(scu_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) for (i = 0; i < ncores; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) set_cpu_possible(i, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) iounmap(scu_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static int ux500_boot_secondary(unsigned int cpu, struct task_struct *idle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * write the address of secondary startup into the backup ram register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * at offset 0x1FF4, then write the magic number 0xA1FEED01 to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * backup ram register at offset 0x1FF0, which is what boot rom code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * is waiting for. This will wake up the secondary core from WFE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) writel(__pa_symbol(secondary_startup),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) backupram + UX500_CPU1_JUMPADDR_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) writel(0xA1FEED01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) backupram + UX500_CPU1_WAKEMAGIC_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /* make sure write buffer is drained */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) arch_send_wakeup_ipi_mask(cpumask_of(cpu));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #ifdef CONFIG_HOTPLUG_CPU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) void ux500_cpu_die(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) wfi();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) static const struct smp_operations ux500_smp_ops __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) .smp_prepare_cpus = ux500_smp_prepare_cpus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) .smp_boot_secondary = ux500_boot_secondary,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #ifdef CONFIG_HOTPLUG_CPU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) .cpu_die = ux500_cpu_die,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) CPU_METHOD_OF_DECLARE(ux500_smp, "ste,dbx500-smp", &ux500_smp_ops);