linux/arch/arm/mach-imx/platsmp.c
<<
>>
Prefs
   1/*
   2 * Copyright 2011 Freescale Semiconductor, Inc.
   3 * Copyright 2011 Linaro Ltd.
   4 *
   5 * The code contained herein is licensed under the GNU General Public
   6 * License. You may obtain a copy of the GNU General Public License
   7 * Version 2 or later at the following locations:
   8 *
   9 * http://www.opensource.org/licenses/gpl-license.html
  10 * http://www.gnu.org/copyleft/gpl.html
  11 */
  12
  13#include <linux/init.h>
  14#include <linux/smp.h>
  15#include <linux/irqchip/arm-gic.h>
  16#include <asm/page.h>
  17#include <asm/smp_scu.h>
  18#include <asm/mach/map.h>
  19
  20#include "common.h"
  21#include "hardware.h"
  22
  23#define SCU_STANDBY_ENABLE      (1 << 5)
  24
  25static void __iomem *scu_base;
  26
  27static struct map_desc scu_io_desc __initdata = {
  28        /* .virtual and .pfn are run-time assigned */
  29        .length         = SZ_4K,
  30        .type           = MT_DEVICE,
  31};
  32
  33void __init imx_scu_map_io(void)
  34{
  35        unsigned long base;
  36
  37        /* Get SCU base */
  38        asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base));
  39
  40        scu_io_desc.virtual = IMX_IO_P2V(base);
  41        scu_io_desc.pfn = __phys_to_pfn(base);
  42        iotable_init(&scu_io_desc, 1);
  43
  44        scu_base = IMX_IO_ADDRESS(base);
  45}
  46
  47void imx_scu_standby_enable(void)
  48{
  49        u32 val = readl_relaxed(scu_base);
  50
  51        val |= SCU_STANDBY_ENABLE;
  52        writel_relaxed(val, scu_base);
  53}
  54
  55static void __cpuinit imx_secondary_init(unsigned int cpu)
  56{
  57        /*
  58         * if any interrupts are already enabled for the primary
  59         * core (e.g. timer irq), then they will not have been enabled
  60         * for us: do so
  61         */
  62        gic_secondary_init(0);
  63}
  64
  65static int __cpuinit imx_boot_secondary(unsigned int cpu, struct task_struct *idle)
  66{
  67        imx_set_cpu_jump(cpu, v7_secondary_startup);
  68        imx_enable_cpu(cpu, true);
  69        return 0;
  70}
  71
  72/*
  73 * Initialise the CPU possible map early - this describes the CPUs
  74 * which may be present or become present in the system.
  75 */
  76static void __init imx_smp_init_cpus(void)
  77{
  78        int i, ncores;
  79
  80        ncores = scu_get_core_count(scu_base);
  81
  82        for (i = 0; i < ncores; i++)
  83                set_cpu_possible(i, true);
  84}
  85
  86void imx_smp_prepare(void)
  87{
  88        scu_enable(scu_base);
  89}
  90
  91static void __init imx_smp_prepare_cpus(unsigned int max_cpus)
  92{
  93        imx_smp_prepare();
  94}
  95
  96struct smp_operations  imx_smp_ops __initdata = {
  97        .smp_init_cpus          = imx_smp_init_cpus,
  98        .smp_prepare_cpus       = imx_smp_prepare_cpus,
  99        .smp_secondary_init     = imx_secondary_init,
 100        .smp_boot_secondary     = imx_boot_secondary,
 101#ifdef CONFIG_HOTPLUG_CPU
 102        .cpu_die                = imx_cpu_die,
 103        .cpu_kill               = imx_cpu_kill,
 104#endif
 105};
 106