diff options
Diffstat (limited to 'arch/arm/mach-tegra/platsmp.c')
| -rw-r--r-- | arch/arm/mach-tegra/platsmp.c | 117 | 
1 files changed, 53 insertions, 64 deletions
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c index 2c6b3d55213..516aab28fe3 100644 --- a/arch/arm/mach-tegra/platsmp.c +++ b/arch/arm/mach-tegra/platsmp.c @@ -26,22 +26,16 @@  #include <asm/smp_scu.h>  #include <asm/smp_plat.h> -#include <mach/powergate.h> -  #include "fuse.h"  #include "flowctrl.h"  #include "reset.h" +#include "pmc.h"  #include "common.h"  #include "iomap.h" -extern void tegra_secondary_startup(void); -  static cpumask_t tegra_cpu_init_mask; -#define EVP_CPU_RESET_VECTOR \ -	(IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + 0x100) -  static void __cpuinit tegra_secondary_init(unsigned int cpu)  {  	/* @@ -54,25 +48,43 @@ static void __cpuinit tegra_secondary_init(unsigned int cpu)  	cpumask_set_cpu(cpu, &tegra_cpu_init_mask);  } -static int tegra20_power_up_cpu(unsigned int cpu) + +static int tegra20_boot_secondary(unsigned int cpu, struct task_struct *idle)  { -	/* Enable the CPU clock. */ -	tegra_enable_cpu_clock(cpu); +	cpu = cpu_logical_map(cpu); + +	/* +	 * 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); -	/* Clear flow controller CSR. */ -	flowctrl_write_cpu_csr(cpu, 0); +	/* +	 * 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);  	return 0;  } -static int tegra30_power_up_cpu(unsigned int cpu) +static int tegra30_boot_secondary(unsigned int cpu, struct task_struct *idle)  { -	int ret, pwrgateid; +	int ret;  	unsigned long timeout; -	pwrgateid = tegra_cpu_powergate_id(cpu); -	if (pwrgateid < 0) -		return pwrgateid; +	cpu = cpu_logical_map(cpu); +	tegra_put_cpu_in_reset(cpu); +	flowctrl_write_cpu_halt(cpu, 0);  	/*  	 * The power up sequence of cold boot CPU and warm boot CPU @@ -85,13 +97,13 @@ static int tegra30_power_up_cpu(unsigned int cpu)  	 * 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 -	 * tegra_cpu_init_mask which influences what tegra30_power_up_cpu() +	 * tegra_cpu_init_mask which influences what tegra30_boot_secondary()  	 * next time around.  	 */  	if (cpumask_test_cpu(cpu, &tegra_cpu_init_mask)) {  		timeout = jiffies + msecs_to_jiffies(50);  		do { -			if (!tegra_powergate_is_powered(pwrgateid)) +			if (tegra_pmc_cpu_is_powered(cpu))  				goto remove_clamps;  			udelay(10);  		} while (time_before(jiffies, timeout)); @@ -103,14 +115,14 @@ static int tegra30_power_up_cpu(unsigned int cpu)  	 * be un-gated by un-toggling the power gate register  	 * manually.  	 */ -	if (!tegra_powergate_is_powered(pwrgateid)) { -		ret = tegra_powergate_power_on(pwrgateid); +	if (!tegra_pmc_cpu_is_powered(cpu)) { +		ret = tegra_pmc_cpu_power_on(cpu);  		if (ret)  			return ret;  		/* Wait for the power to come up. */  		timeout = jiffies + msecs_to_jiffies(100); -		while (tegra_powergate_is_powered(pwrgateid)) { +		while (tegra_pmc_cpu_is_powered(cpu)) {  			if (time_after(jiffies, timeout))  				return -ETIMEDOUT;  			udelay(10); @@ -123,57 +135,34 @@ remove_clamps:  	udelay(10);  	/* Remove I/O clamps. */ -	ret = tegra_powergate_remove_clamping(pwrgateid); -	udelay(10); +	ret = tegra_pmc_cpu_remove_clamping(cpu); +	if (ret) +		return ret; -	/* Clear flow controller CSR. */ -	flowctrl_write_cpu_csr(cpu, 0); +	udelay(10); +	flowctrl_write_cpu_csr(cpu, 0); /* Clear flow controller CSR. */ +	tegra_cpu_out_of_reset(cpu);  	return 0;  } -static int __cpuinit tegra_boot_secondary(unsigned int cpu, struct task_struct *idle) +static int tegra114_boot_secondary(unsigned int cpu, struct task_struct *idle)  { -	int status; -  	cpu = cpu_logical_map(cpu); +	return tegra_pmc_cpu_power_on(cpu); +} -	/* -	 * 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); - -	/* -	 * 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); - -	switch (tegra_chip_id) { -	case TEGRA20: -		status = tegra20_power_up_cpu(cpu); -		break; -	case TEGRA30: -		status = tegra30_power_up_cpu(cpu); -		break; -	default: -		status = -EINVAL; -		break; -	} - -	if (status) -		goto done; +static int __cpuinit tegra_boot_secondary(unsigned int cpu, +					  struct task_struct *idle) +{ +	if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_chip_id == TEGRA20) +		return tegra20_boot_secondary(cpu, idle); +	if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_chip_id == TEGRA30) +		return tegra30_boot_secondary(cpu, idle); +	if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) && tegra_chip_id == TEGRA114) +		return tegra114_boot_secondary(cpu, idle); -	/* Take the CPU out of reset. */ -	tegra_cpu_out_of_reset(cpu); -done: -	return status; +	return -EINVAL;  }  static void __init tegra_smp_prepare_cpus(unsigned int max_cpus)  |