Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  arch/arm/mach-sti/platsmp.c
0004  *
0005  * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
0006  *      http://www.st.com
0007  *
0008  * Cloned from linux/arch/arm/mach-vexpress/platsmp.c
0009  *
0010  *  Copyright (C) 2002 ARM Ltd.
0011  *  All Rights Reserved
0012  */
0013 #include <linux/init.h>
0014 #include <linux/errno.h>
0015 #include <linux/delay.h>
0016 #include <linux/smp.h>
0017 #include <linux/io.h>
0018 #include <linux/of.h>
0019 #include <linux/of_address.h>
0020 #include <linux/memblock.h>
0021 
0022 #include <asm/cacheflush.h>
0023 #include <asm/smp_plat.h>
0024 #include <asm/smp_scu.h>
0025 
0026 #include "smp.h"
0027 
0028 static u32 __iomem *cpu_strt_ptr;
0029 
0030 static int sti_boot_secondary(unsigned int cpu, struct task_struct *idle)
0031 {
0032     unsigned long entry_pa = __pa_symbol(secondary_startup);
0033 
0034     /*
0035      * Secondary CPU is initialised and started by a U-BOOTROM firmware.
0036      * Secondary CPU is spinning and waiting for a write at cpu_strt_ptr.
0037      * Writing secondary_startup address at cpu_strt_ptr makes it to
0038      * jump directly to secondary_startup().
0039      */
0040     __raw_writel(entry_pa, cpu_strt_ptr);
0041 
0042     /* wmb so that data is actually written before cache flush is done */
0043     smp_wmb();
0044     sync_cache_w(cpu_strt_ptr);
0045 
0046     return 0;
0047 }
0048 
0049 static void __init sti_smp_prepare_cpus(unsigned int max_cpus)
0050 {
0051     struct device_node *np;
0052     void __iomem *scu_base;
0053     u32 release_phys;
0054     int cpu;
0055 
0056     np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
0057 
0058     if (np) {
0059         scu_base = of_iomap(np, 0);
0060         scu_enable(scu_base);
0061         of_node_put(np);
0062     }
0063 
0064     if (max_cpus <= 1)
0065         return;
0066 
0067     for_each_possible_cpu(cpu) {
0068 
0069         np = of_get_cpu_node(cpu, NULL);
0070 
0071         if (!np)
0072             continue;
0073 
0074         if (of_property_read_u32(np, "cpu-release-addr",
0075                         &release_phys)) {
0076             pr_err("CPU %d: missing or invalid cpu-release-addr "
0077                 "property\n", cpu);
0078             continue;
0079         }
0080 
0081         /*
0082          * cpu-release-addr is usually configured in SBC DMEM but can
0083          * also be in RAM.
0084          */
0085 
0086         if (!memblock_is_memory(release_phys))
0087             cpu_strt_ptr =
0088                 ioremap(release_phys, sizeof(release_phys));
0089         else
0090             cpu_strt_ptr =
0091                 (u32 __iomem *)phys_to_virt(release_phys);
0092 
0093         set_cpu_possible(cpu, true);
0094     }
0095 }
0096 
0097 const struct smp_operations sti_smp_ops __initconst = {
0098     .smp_prepare_cpus   = sti_smp_prepare_cpus,
0099     .smp_boot_secondary = sti_boot_secondary,
0100 };