linux/arch/arm/mach-tegra/platsmp.c
<<
>>
Prefs
   1/*
   2 *  linux/arch/arm/mach-tegra/platsmp.c
   3 *
   4 *  Copyright (C) 2002 ARM Ltd.
   5 *  All Rights Reserved
   6 *
   7 *  Copyright (C) 2009 Palm
   8 *  All Rights Reserved
   9 *
  10 * This program is free software; you can redistribute it and/or modify
  11 * it under the terms of the GNU General Public License version 2 as
  12 * published by the Free Software Foundation.
  13 */
  14#include <linux/init.h>
  15#include <linux/errno.h>
  16#include <linux/delay.h>
  17#include <linux/device.h>
  18#include <linux/jiffies.h>
  19#include <linux/smp.h>
  20#include <linux/io.h>
  21#include <linux/clk/tegra.h>
  22
  23#include <asm/cacheflush.h>
  24#include <asm/mach-types.h>
  25#include <asm/smp_scu.h>
  26#include <asm/smp_plat.h>
  27
  28#include "fuse.h"
  29#include "flowctrl.h"
  30#include "reset.h"
  31#include "pmc.h"
  32
  33#include "common.h"
  34#include "iomap.h"
  35
  36static cpumask_t tegra_cpu_init_mask;
  37
  38static void tegra_secondary_init(unsigned int cpu)
  39{
  40        cpumask_set_cpu(cpu, &tegra_cpu_init_mask);
  41}
  42
  43
  44static int tegra20_boot_secondary(unsigned int cpu, struct task_struct *idle)
  45{
  46        cpu = cpu_logical_map(cpu);
  47
  48        /*
  49         * Force the CPU into reset. The CPU must remain in reset when
  50         * the flow controller state is cleared (which will cause the
  51         * flow controller to stop driving reset if the CPU has been
  52         * power-gated via the flow controller). This will have no
  53         * effect on first boot of the CPU since it should already be
  54         * in reset.
  55         */
  56        tegra_put_cpu_in_reset(cpu);
  57
  58        /*
  59         * Unhalt the CPU. If the flow controller was used to
  60         * power-gate the CPU this will cause the flow controller to
  61         * stop driving reset. The CPU will remain in reset because the
  62         * clock and reset block is now driving reset.
  63         */
  64        flowctrl_write_cpu_halt(cpu, 0);
  65
  66        tegra_enable_cpu_clock(cpu);
  67        flowctrl_write_cpu_csr(cpu, 0); /* Clear flow controller CSR. */
  68        tegra_cpu_out_of_reset(cpu);
  69        return 0;
  70}
  71
  72static int tegra30_boot_secondary(unsigned int cpu, struct task_struct *idle)
  73{
  74        int ret;
  75        unsigned long timeout;
  76
  77        cpu = cpu_logical_map(cpu);
  78        tegra_put_cpu_in_reset(cpu);
  79        flowctrl_write_cpu_halt(cpu, 0);
  80
  81        /*
  82         * The power up sequence of cold boot CPU and warm boot CPU
  83         * was different.
  84         *
  85         * For warm boot CPU that was resumed from CPU hotplug, the
  86         * power will be resumed automatically after un-halting the
  87         * flow controller of the warm boot CPU. We need to wait for
  88         * the confirmaiton that the CPU is powered then removing
  89         * the IO clamps.
  90         * For cold boot CPU, do not wait. After the cold boot CPU be
  91         * booted, it will run to tegra_secondary_init() and set
  92         * tegra_cpu_init_mask which influences what tegra30_boot_secondary()
  93         * next time around.
  94         */
  95        if (cpumask_test_cpu(cpu, &tegra_cpu_init_mask)) {
  96                timeout = jiffies + msecs_to_jiffies(50);
  97                do {
  98                        if (tegra_pmc_cpu_is_powered(cpu))
  99                                goto remove_clamps;
 100                        udelay(10);
 101                } while (time_before(jiffies, timeout));
 102        }
 103
 104        /*
 105         * The power status of the cold boot CPU is power gated as
 106         * default. To power up the cold boot CPU, the power should
 107         * be un-gated by un-toggling the power gate register
 108         * manually.
 109         */
 110        if (!tegra_pmc_cpu_is_powered(cpu)) {
 111                ret = tegra_pmc_cpu_power_on(cpu);
 112                if (ret)
 113                        return ret;
 114
 115                /* Wait for the power to come up. */
 116                timeout = jiffies + msecs_to_jiffies(100);
 117                while (tegra_pmc_cpu_is_powered(cpu)) {
 118                        if (time_after(jiffies, timeout))
 119                                return -ETIMEDOUT;
 120                        udelay(10);
 121                }
 122        }
 123
 124remove_clamps:
 125        /* CPU partition is powered. Enable the CPU clock. */
 126        tegra_enable_cpu_clock(cpu);
 127        udelay(10);
 128
 129        /* Remove I/O clamps. */
 130        ret = tegra_pmc_cpu_remove_clamping(cpu);
 131        if (ret)
 132                return ret;
 133
 134        udelay(10);
 135
 136        flowctrl_write_cpu_csr(cpu, 0); /* Clear flow controller CSR. */
 137        tegra_cpu_out_of_reset(cpu);
 138        return 0;
 139}
 140
 141static int tegra114_boot_secondary(unsigned int cpu, struct task_struct *idle)
 142{
 143        int ret = 0;
 144
 145        cpu = cpu_logical_map(cpu);
 146
 147        if (cpumask_test_cpu(cpu, &tegra_cpu_init_mask)) {
 148                /*
 149                 * Warm boot flow
 150                 * The flow controller in charge of the power state and
 151                 * control for each CPU.
 152                 */
 153                /* set SCLK as event trigger for flow controller */
 154                flowctrl_write_cpu_csr(cpu, 1);
 155                flowctrl_write_cpu_halt(cpu,
 156                                FLOW_CTRL_WAITEVENT | FLOW_CTRL_SCLK_RESUME);
 157        } else {
 158                /*
 159                 * Cold boot flow
 160                 * The CPU is powered up by toggling PMC directly. It will
 161                 * also initial power state in flow controller. After that,
 162                 * the CPU's power state is maintained by flow controller.
 163                 */
 164                ret = tegra_pmc_cpu_power_on(cpu);
 165        }
 166
 167        return ret;
 168}
 169
 170static int tegra_boot_secondary(unsigned int cpu,
 171                                          struct task_struct *idle)
 172{
 173        if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_chip_id == TEGRA20)
 174                return tegra20_boot_secondary(cpu, idle);
 175        if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_chip_id == TEGRA30)
 176                return tegra30_boot_secondary(cpu, idle);
 177        if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) && tegra_chip_id == TEGRA114)
 178                return tegra114_boot_secondary(cpu, idle);
 179
 180        return -EINVAL;
 181}
 182
 183static void __init tegra_smp_prepare_cpus(unsigned int max_cpus)
 184{
 185        /* Always mark the boot CPU (CPU0) as initialized. */
 186        cpumask_set_cpu(0, &tegra_cpu_init_mask);
 187
 188        if (scu_a9_has_base())
 189                scu_enable(IO_ADDRESS(scu_a9_get_base()));
 190}
 191
 192struct smp_operations tegra_smp_ops __initdata = {
 193        .smp_prepare_cpus       = tegra_smp_prepare_cpus,
 194        .smp_secondary_init     = tegra_secondary_init,
 195        .smp_boot_secondary     = tegra_boot_secondary,
 196#ifdef CONFIG_HOTPLUG_CPU
 197        .cpu_kill               = tegra_cpu_kill,
 198        .cpu_die                = tegra_cpu_die,
 199#endif
 200};
 201