~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/arm/mach-tegra/platsmp.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php