Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright 2011 Freescale Semiconductor, Inc.
0004  * Copyright 2011 Linaro Ltd.
0005  */
0006 
0007 #include <linux/init.h>
0008 #include <linux/of_address.h>
0009 #include <linux/of.h>
0010 #include <linux/smp.h>
0011 
0012 #include <asm/cacheflush.h>
0013 #include <asm/page.h>
0014 #include <asm/smp_scu.h>
0015 #include <asm/mach/map.h>
0016 
0017 #include "common.h"
0018 #include "hardware.h"
0019 
0020 u32 g_diag_reg;
0021 static void __iomem *scu_base;
0022 
0023 static struct map_desc scu_io_desc __initdata = {
0024     /* .virtual and .pfn are run-time assigned */
0025     .length     = SZ_4K,
0026     .type       = MT_DEVICE,
0027 };
0028 
0029 void __init imx_scu_map_io(void)
0030 {
0031     unsigned long base;
0032 
0033     /* Get SCU base */
0034     asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base));
0035 
0036     scu_io_desc.virtual = IMX_IO_P2V(base);
0037     scu_io_desc.pfn = __phys_to_pfn(base);
0038     iotable_init(&scu_io_desc, 1);
0039 
0040     scu_base = IMX_IO_ADDRESS(base);
0041 }
0042 
0043 static int imx_boot_secondary(unsigned int cpu, struct task_struct *idle)
0044 {
0045     imx_set_cpu_jump(cpu, v7_secondary_startup);
0046     imx_enable_cpu(cpu, true);
0047     return 0;
0048 }
0049 
0050 /*
0051  * Initialise the CPU possible map early - this describes the CPUs
0052  * which may be present or become present in the system.
0053  */
0054 static void __init imx_smp_init_cpus(void)
0055 {
0056     int i, ncores;
0057 
0058     ncores = scu_get_core_count(scu_base);
0059 
0060     for (i = ncores; i < NR_CPUS; i++)
0061         set_cpu_possible(i, false);
0062 }
0063 
0064 void imx_smp_prepare(void)
0065 {
0066     scu_enable(scu_base);
0067 }
0068 
0069 static void __init imx_smp_prepare_cpus(unsigned int max_cpus)
0070 {
0071     imx_smp_prepare();
0072 
0073     /*
0074      * The diagnostic register holds the errata bits.  Mostly bootloader
0075      * does not bring up secondary cores, so that when errata bits are set
0076      * in bootloader, they are set only for boot cpu.  But on a SMP
0077      * configuration, it should be equally done on every single core.
0078      * Read the register from boot cpu here, and will replicate it into
0079      * secondary cores when booting them.
0080      */
0081     asm("mrc p15, 0, %0, c15, c0, 1" : "=r" (g_diag_reg) : : "cc");
0082     sync_cache_w(&g_diag_reg);
0083 }
0084 
0085 const struct smp_operations imx_smp_ops __initconst = {
0086     .smp_init_cpus      = imx_smp_init_cpus,
0087     .smp_prepare_cpus   = imx_smp_prepare_cpus,
0088     .smp_boot_secondary = imx_boot_secondary,
0089 #ifdef CONFIG_HOTPLUG_CPU
0090     .cpu_die        = imx_cpu_die,
0091     .cpu_kill       = imx_cpu_kill,
0092 #endif
0093 };
0094 
0095 /*
0096  * Initialise the CPU possible map early - this describes the CPUs
0097  * which may be present or become present in the system.
0098  */
0099 static void __init imx7_smp_init_cpus(void)
0100 {
0101     struct device_node *np;
0102     int i, ncores = 0;
0103 
0104     /* The iMX7D SCU does not report core count, get it from DT */
0105     for_each_of_cpu_node(np)
0106         ncores++;
0107 
0108     for (i = ncores; i < NR_CPUS; i++)
0109         set_cpu_possible(i, false);
0110 }
0111 
0112 const struct smp_operations imx7_smp_ops __initconst = {
0113     .smp_init_cpus      = imx7_smp_init_cpus,
0114     .smp_boot_secondary = imx_boot_secondary,
0115 #ifdef CONFIG_HOTPLUG_CPU
0116     .cpu_die        = imx_cpu_die,
0117     .cpu_kill       = imx_cpu_kill,
0118 #endif
0119 };
0120 
0121 #define DCFG_CCSR_SCRATCHRW1    0x200
0122 
0123 static int ls1021a_boot_secondary(unsigned int cpu, struct task_struct *idle)
0124 {
0125     arch_send_wakeup_ipi_mask(cpumask_of(cpu));
0126 
0127     return 0;
0128 }
0129 
0130 static void __init ls1021a_smp_prepare_cpus(unsigned int max_cpus)
0131 {
0132     struct device_node *np;
0133     void __iomem *dcfg_base;
0134     unsigned long paddr;
0135 
0136     np = of_find_compatible_node(NULL, NULL, "fsl,ls1021a-dcfg");
0137     dcfg_base = of_iomap(np, 0);
0138     of_node_put(np);
0139     BUG_ON(!dcfg_base);
0140 
0141     paddr = __pa_symbol(secondary_startup);
0142     writel_relaxed(cpu_to_be32(paddr), dcfg_base + DCFG_CCSR_SCRATCHRW1);
0143 
0144     iounmap(dcfg_base);
0145 }
0146 
0147 const struct smp_operations ls1021a_smp_ops __initconst = {
0148     .smp_prepare_cpus   = ls1021a_smp_prepare_cpus,
0149     .smp_boot_secondary = ls1021a_boot_secondary,
0150 };