2019-06-04 10:11:33 +02:00
// SPDX-License-Identifier: GPL-2.0-only
2010-02-21 17:46:23 -08:00
/*
* linux / arch / arm / mach - tegra / platsmp . c
*
* Copyright ( C ) 2002 ARM Ltd .
* All Rights Reserved
*
* Copyright ( C ) 2009 Palm
* All Rights Reserved
*/
2014-07-11 09:44:49 +02:00
# include <linux/clk/tegra.h>
2010-02-21 17:46:23 -08:00
# include <linux/delay.h>
# include <linux/device.h>
2014-07-11 09:44:49 +02:00
# include <linux/errno.h>
# include <linux/init.h>
# include <linux/io.h>
2010-02-21 17:46:23 -08:00
# include <linux/jiffies.h>
# include <linux/smp.h>
2017-03-28 13:42:54 +01:00
# include <soc/tegra/flowctrl.h>
2014-07-11 09:52:41 +02:00
# include <soc/tegra/fuse.h>
2014-07-11 13:19:06 +02:00
# include <soc/tegra/pmc.h>
2014-07-11 09:52:41 +02:00
2010-02-21 17:46:23 -08:00
# include <asm/cacheflush.h>
# include <asm/mach-types.h>
2013-01-03 15:31:31 +08:00
# include <asm/smp_plat.h>
2014-07-11 09:44:49 +02:00
# include <asm/smp_scu.h>
2012-02-10 01:47:45 +02:00
2011-09-08 13:15:22 +01:00
# include "common.h"
2012-10-04 14:24:09 -06:00
# include "iomap.h"
2014-07-11 09:44:49 +02:00
# include "reset.h"
2011-09-08 13:15:22 +01:00
2013-01-03 15:31:31 +08:00
static cpumask_t tegra_cpu_init_mask ;
2010-02-21 17:46:23 -08:00
2013-06-17 15:43:14 -04:00
static void tegra_secondary_init ( unsigned int cpu )
2010-02-21 17:46:23 -08:00
{
2013-01-03 15:31:31 +08:00
cpumask_set_cpu ( cpu , & tegra_cpu_init_mask ) ;
2010-02-21 17:46:23 -08:00
}
2013-02-22 14:24:27 +08:00
static int tegra20_boot_secondary ( unsigned int cpu , struct task_struct * idle )
2010-02-21 17:46:23 -08:00
{
2013-02-22 14:24:27 +08:00
cpu = cpu_logical_map ( cpu ) ;
2010-02-21 17:46:23 -08:00
2013-02-22 14:24:27 +08:00
/*
* Force the CPU into reset . The CPU must remain in reset when
* the flow controller state is cleared ( which will cause the
* flow controller to stop driving reset if the CPU has been
* power - gated via the flow controller ) . This will have no
* effect on first boot of the CPU since it should already be
* in reset .
*/
tegra_put_cpu_in_reset ( cpu ) ;
2010-02-21 17:46:23 -08:00
2013-02-22 14:24:27 +08:00
/*
* Unhalt the CPU . If the flow controller was used to
* power - gate the CPU this will cause the flow controller to
* stop driving reset . The CPU will remain in reset because the
* clock and reset block is now driving reset .
*/
flowctrl_write_cpu_halt ( cpu , 0 ) ;
tegra_enable_cpu_clock ( cpu ) ;
flowctrl_write_cpu_csr ( cpu , 0 ) ; /* Clear flow controller CSR. */
tegra_cpu_out_of_reset ( cpu ) ;
2012-02-10 01:47:45 +02:00
return 0 ;
}
2010-02-21 17:46:23 -08:00
2013-02-22 14:24:27 +08:00
static int tegra30_boot_secondary ( unsigned int cpu , struct task_struct * idle )
2012-02-10 01:47:50 +02:00
{
2013-02-26 16:28:06 +00:00
int ret ;
2012-02-10 01:47:50 +02:00
unsigned long timeout ;
2013-02-22 14:24:27 +08:00
cpu = cpu_logical_map ( cpu ) ;
tegra_put_cpu_in_reset ( cpu ) ;
flowctrl_write_cpu_halt ( cpu , 0 ) ;
2013-01-03 15:31:31 +08:00
/*
* The power up sequence of cold boot CPU and warm boot CPU
* was different .
*
* For warm boot CPU that was resumed from CPU hotplug , the
* power will be resumed automatically after un - halting the
* flow controller of the warm boot CPU . We need to wait for
2022-03-18 11:37:03 +01:00
* the confirmation that the CPU is powered then removing
2013-01-03 15:31:31 +08:00
* the IO clamps .
* For cold boot CPU , do not wait . After the cold boot CPU be
* booted , it will run to tegra_secondary_init ( ) and set
2013-02-22 14:24:27 +08:00
* tegra_cpu_init_mask which influences what tegra30_boot_secondary ( )
2013-01-03 15:31:31 +08:00
* next time around .
*/
if ( cpumask_test_cpu ( cpu , & tegra_cpu_init_mask ) ) {
2013-01-07 10:56:14 +08:00
timeout = jiffies + msecs_to_jiffies ( 50 ) ;
2013-01-03 15:31:31 +08:00
do {
2013-02-26 16:28:06 +00:00
if ( tegra_pmc_cpu_is_powered ( cpu ) )
2013-01-03 15:31:31 +08:00
goto remove_clamps ;
udelay ( 10 ) ;
} while ( time_before ( jiffies , timeout ) ) ;
}
/*
* The power status of the cold boot CPU is power gated as
* default . To power up the cold boot CPU , the power should
* be un - gated by un - toggling the power gate register
* manually .
*/
2016-02-26 15:48:40 +00:00
ret = tegra_pmc_cpu_power_on ( cpu ) ;
if ( ret )
return ret ;
2012-02-10 01:47:50 +02:00
2013-01-03 15:31:31 +08:00
remove_clamps :
2012-02-10 01:47:50 +02:00
/* CPU partition is powered. Enable the CPU clock. */
2012-08-16 17:31:49 +08:00
tegra_enable_cpu_clock ( cpu ) ;
2012-02-10 01:47:50 +02:00
udelay ( 10 ) ;
/* Remove I/O clamps. */
2013-02-26 16:28:06 +00:00
ret = tegra_pmc_cpu_remove_clamping ( cpu ) ;
2013-02-22 14:24:25 +08:00
if ( ret )
return ret ;
2012-02-10 01:47:50 +02:00
udelay ( 10 ) ;
2013-02-22 14:24:27 +08:00
flowctrl_write_cpu_csr ( cpu , 0 ) ; /* Clear flow controller CSR. */
tegra_cpu_out_of_reset ( cpu ) ;
2012-02-10 01:47:50 +02:00
return 0 ;
}
2013-02-26 16:28:07 +00:00
static int tegra114_boot_secondary ( unsigned int cpu , struct task_struct * idle )
{
2013-05-20 18:39:27 +08:00
int ret = 0 ;
2013-02-26 16:28:07 +00:00
cpu = cpu_logical_map ( cpu ) ;
2013-05-20 18:39:27 +08:00
if ( cpumask_test_cpu ( cpu , & tegra_cpu_init_mask ) ) {
/*
* Warm boot flow
* The flow controller in charge of the power state and
* control for each CPU .
*/
/* set SCLK as event trigger for flow controller */
flowctrl_write_cpu_csr ( cpu , 1 ) ;
flowctrl_write_cpu_halt ( cpu ,
FLOW_CTRL_WAITEVENT | FLOW_CTRL_SCLK_RESUME ) ;
} else {
/*
* Cold boot flow
* The CPU is powered up by toggling PMC directly . It will
* also initial power state in flow controller . After that ,
* the CPU ' s power state is maintained by flow controller .
*/
ret = tegra_pmc_cpu_power_on ( cpu ) ;
}
return ret ;
2013-02-26 16:28:07 +00:00
}
2013-06-17 15:43:14 -04:00
static int tegra_boot_secondary ( unsigned int cpu ,
2013-02-22 14:24:27 +08:00
struct task_struct * idle )
2012-02-10 01:47:45 +02:00
{
2014-07-11 09:52:41 +02:00
if ( IS_ENABLED ( CONFIG_ARCH_TEGRA_2x_SOC ) & & tegra_get_chip_id ( ) = = TEGRA20 )
2013-02-22 14:24:27 +08:00
return tegra20_boot_secondary ( cpu , idle ) ;
2014-07-11 09:52:41 +02:00
if ( IS_ENABLED ( CONFIG_ARCH_TEGRA_3x_SOC ) & & tegra_get_chip_id ( ) = = TEGRA30 )
2013-02-22 14:24:27 +08:00
return tegra30_boot_secondary ( cpu , idle ) ;
2014-07-11 09:52:41 +02:00
if ( IS_ENABLED ( CONFIG_ARCH_TEGRA_114_SOC ) & & tegra_get_chip_id ( ) = = TEGRA114 )
2013-02-26 16:28:07 +00:00
return tegra114_boot_secondary ( cpu , idle ) ;
2014-07-11 09:52:41 +02:00
if ( IS_ENABLED ( CONFIG_ARCH_TEGRA_124_SOC ) & & tegra_get_chip_id ( ) = = TEGRA124 )
2013-10-08 12:50:03 +08:00
return tegra114_boot_secondary ( cpu , idle ) ;
2010-02-21 17:46:23 -08:00
2013-02-22 14:24:27 +08:00
return - EINVAL ;
2010-02-21 17:46:23 -08:00
}
2011-09-08 13:15:22 +01:00
static void __init tegra_smp_prepare_cpus ( unsigned int max_cpus )
2010-02-21 17:46:23 -08:00
{
2013-01-03 15:31:31 +08:00
/* Always mark the boot CPU (CPU0) as initialized. */
cpumask_set_cpu ( 0 , & tegra_cpu_init_mask ) ;
2013-01-22 07:52:02 +02:00
if ( scu_a9_has_base ( ) )
scu_enable ( IO_ADDRESS ( scu_a9_get_base ( ) ) ) ;
2010-02-21 17:46:23 -08:00
}
2011-09-08 13:15:22 +01:00
2015-11-15 10:39:53 +09:00
const struct smp_operations tegra_smp_ops __initconst = {
2011-09-08 13:15:22 +01:00
. smp_prepare_cpus = tegra_smp_prepare_cpus ,
. smp_secondary_init = tegra_secondary_init ,
. smp_boot_secondary = tegra_boot_secondary ,
# ifdef CONFIG_HOTPLUG_CPU
2013-01-03 14:43:00 +08:00
. cpu_kill = tegra_cpu_kill ,
2011-09-08 13:15:22 +01:00
. cpu_die = tegra_cpu_die ,
# endif
} ;