ARM: tegra: cleanup
This pull request contains various cleanup and minor changes to core Tegra code: * Tegra clocksource driver is moved to drivers/clocksource. * Various typos, warning cleanup, statics cleanup, section mismatch fixes, etc. * Various small fixes/cleanups for CPU/hotplug/SMP code. This pull request is based on a merge of v3.8-rc3 and at least part of arm-soc's timer/cleanup branch. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJRCYapAAoJEMzrak5tbycxp0kQAKYlx2XFf8lgv+V/zDRmzXvr 7dW1bByqBIqrhoOxYM+WGLtcVT+n23MbwXUsbRp2hKGzNSD4+VG05bBrEutfjdnf bDiJeLkA+95e1Slx/BPzE7SYoOuNxR0YuVuFD8JkL+ykD0NtoJsoS3eUZB+7/bQ7 Ld9GscUndy7GDoo04Dr72OhVwESVHqahvSPWc5xPsE8ua6ZTiTg+x4UgzrbUpHoQ CN3ABkJfeYr2pERSiZDJwuyWTDx/d9MHpcK2JNVht0AayIcXRUKUwKiJiUPtDsA1 RQvk3UB0iwA6lWnr+ApJtDpNQOfx7MbYY/VIRJ2krmZiOGl3fewMkNUhpTcs+wBJ HumdCb9bDha+o8hYAthibhBurENP6ydwEpkinIANsj4HIQYwGNVaFBZaN9gbrtKs 8jgQsrjiZSwFSpyyMyuNy1mg2M3TI0WExEpTQx0KG41g49CvhlhrPpR6HfbjjpDb 9/Pw5J7nMrSNNjxYKMUKfBtnrceAaZ96riFZfDJmc1WTnv0OCfzfRfTkc3+6peE7 ItNHwux5p6M1DfPvMEZA9qwKbLSdZCGtKQ0vElJjQeqU+tXNtb2H9AEOYoZkTUSQ 7rdkJM9nDLWtXjb1vql8XEYsxD28nLGyOWnE5yOrM/qZ28sgfY7bmt9R0NGaoWRO moveNklG/UDcANbi2LuU =H2vV -----END PGP SIGNATURE----- Merge tag 'tegra-for-3.9-cleanup' of git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra into next/cleanup From Stephen Warren: ARM: tegra: cleanup This pull request contains various cleanup and minor changes to core Tegra code: * Tegra clocksource driver is moved to drivers/clocksource. * Various typos, warning cleanup, statics cleanup, section mismatch fixes, etc. * Various small fixes/cleanups for CPU/hotplug/SMP code. This pull request is based on a merge of v3.8-rc3 and at least part of arm-soc's timer/cleanup branch. * tag 'tegra-for-3.9-cleanup' of git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra: ARM: tegra: fix compile error when disable CPU_IDLE ARM: tegra30: make the wait time of CPU power up to proportional to HZ ARM: tegra: make device can run on UP ARM: tegra: clean up the CPUINIT section ARM: tegra: moving the clock gating procedure to tegra_cpu_kill ARM: tegra: update the cache maintenance order for CPU shutdown ARM: tegra30: fix power up sequence for boot_secondary ARM: tegra: cpufreq: move clk_get/put out of function tegra_cpu_init/exit ARM: tegra: fix Kconfig warnings when !SMP ARM: tegra: Make variables static clocksource: tegra: cosmetic: Fix error message ARM: tegra: move timer.c to drivers/clocksource/ Signed-off-by: Olof Johansson <olof@lixom.net> Trivial conflicts: arch/arm/mach-tegra/board-dt-tegra20.c arch/arm/mach-tegra/board-dt-tegra30.c drivers/clocksource/Makefile
This commit is contained in:
commit
f0390669d1
|
@ -642,6 +642,7 @@ config ARCH_TEGRA
|
||||||
select ARCH_HAS_CPUFREQ
|
select ARCH_HAS_CPUFREQ
|
||||||
select CLKDEV_LOOKUP
|
select CLKDEV_LOOKUP
|
||||||
select CLKSRC_MMIO
|
select CLKSRC_MMIO
|
||||||
|
select CLKSRC_OF
|
||||||
select COMMON_CLK
|
select COMMON_CLK
|
||||||
select GENERIC_CLOCKEVENTS
|
select GENERIC_CLOCKEVENTS
|
||||||
select HAVE_CLK
|
select HAVE_CLK
|
||||||
|
|
|
@ -6,9 +6,9 @@ config ARCH_TEGRA_2x_SOC
|
||||||
bool "Enable support for Tegra20 family"
|
bool "Enable support for Tegra20 family"
|
||||||
select ARCH_REQUIRE_GPIOLIB
|
select ARCH_REQUIRE_GPIOLIB
|
||||||
select ARM_ERRATA_720789
|
select ARM_ERRATA_720789
|
||||||
select ARM_ERRATA_742230
|
select ARM_ERRATA_742230 if SMP
|
||||||
select ARM_ERRATA_751472
|
select ARM_ERRATA_751472
|
||||||
select ARM_ERRATA_754327
|
select ARM_ERRATA_754327 if SMP
|
||||||
select ARM_ERRATA_764369 if SMP
|
select ARM_ERRATA_764369 if SMP
|
||||||
select ARM_GIC
|
select ARM_GIC
|
||||||
select CPU_FREQ_TABLE if CPU_FREQ
|
select CPU_FREQ_TABLE if CPU_FREQ
|
||||||
|
|
|
@ -2,15 +2,16 @@ obj-y += common.o
|
||||||
obj-y += io.o
|
obj-y += io.o
|
||||||
obj-y += irq.o
|
obj-y += irq.o
|
||||||
obj-y += clock.o
|
obj-y += clock.o
|
||||||
obj-y += timer.o
|
|
||||||
obj-y += fuse.o
|
obj-y += fuse.o
|
||||||
obj-y += pmc.o
|
obj-y += pmc.o
|
||||||
obj-y += flowctrl.o
|
obj-y += flowctrl.o
|
||||||
obj-y += powergate.o
|
obj-y += powergate.o
|
||||||
obj-y += apbio.o
|
obj-y += apbio.o
|
||||||
obj-y += pm.o
|
obj-y += pm.o
|
||||||
|
obj-y += reset.o
|
||||||
|
obj-y += reset-handler.o
|
||||||
|
obj-y += sleep.o
|
||||||
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
|
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
|
||||||
obj-$(CONFIG_CPU_IDLE) += sleep.o
|
|
||||||
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_clocks.o
|
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_clocks.o
|
||||||
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_clocks_data.o
|
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_clocks_data.o
|
||||||
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_speedo.o
|
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_speedo.o
|
||||||
|
@ -27,7 +28,6 @@ ifeq ($(CONFIG_CPU_IDLE),y)
|
||||||
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += cpuidle-tegra30.o
|
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += cpuidle-tegra30.o
|
||||||
endif
|
endif
|
||||||
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
|
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
|
||||||
obj-$(CONFIG_SMP) += reset.o
|
|
||||||
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
|
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
|
||||||
obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o
|
obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o
|
||||||
obj-$(CONFIG_TEGRA_PCI) += pcie.o
|
obj-$(CONFIG_TEGRA_PCI) += pcie.o
|
||||||
|
|
|
@ -38,7 +38,7 @@ static void tegra_apb_writel_direct(u32 value, unsigned long offset);
|
||||||
static struct dma_chan *tegra_apb_dma_chan;
|
static struct dma_chan *tegra_apb_dma_chan;
|
||||||
static struct dma_slave_config dma_sconfig;
|
static struct dma_slave_config dma_sconfig;
|
||||||
|
|
||||||
bool tegra_apb_dma_init(void)
|
static bool tegra_apb_dma_init(void)
|
||||||
{
|
{
|
||||||
dma_cap_mask_t mask;
|
dma_cap_mask_t mask;
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/clocksource.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
|
@ -43,31 +44,31 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "iomap.h"
|
#include "iomap.h"
|
||||||
|
|
||||||
struct tegra_ehci_platform_data tegra_ehci1_pdata = {
|
static struct tegra_ehci_platform_data tegra_ehci1_pdata = {
|
||||||
.operating_mode = TEGRA_USB_OTG,
|
.operating_mode = TEGRA_USB_OTG,
|
||||||
.power_down_on_bus_suspend = 1,
|
.power_down_on_bus_suspend = 1,
|
||||||
.vbus_gpio = -1,
|
.vbus_gpio = -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config = {
|
static struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config = {
|
||||||
.reset_gpio = -1,
|
.reset_gpio = -1,
|
||||||
.clk = "cdev2",
|
.clk = "cdev2",
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tegra_ehci_platform_data tegra_ehci2_pdata = {
|
static struct tegra_ehci_platform_data tegra_ehci2_pdata = {
|
||||||
.phy_config = &tegra_ehci2_ulpi_phy_config,
|
.phy_config = &tegra_ehci2_ulpi_phy_config,
|
||||||
.operating_mode = TEGRA_USB_HOST,
|
.operating_mode = TEGRA_USB_HOST,
|
||||||
.power_down_on_bus_suspend = 1,
|
.power_down_on_bus_suspend = 1,
|
||||||
.vbus_gpio = -1,
|
.vbus_gpio = -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tegra_ehci_platform_data tegra_ehci3_pdata = {
|
static struct tegra_ehci_platform_data tegra_ehci3_pdata = {
|
||||||
.operating_mode = TEGRA_USB_HOST,
|
.operating_mode = TEGRA_USB_HOST,
|
||||||
.power_down_on_bus_suspend = 1,
|
.power_down_on_bus_suspend = 1,
|
||||||
.vbus_gpio = -1,
|
.vbus_gpio = -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
|
static struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
|
||||||
OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC1_BASE, "sdhci-tegra.0", NULL),
|
OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC1_BASE, "sdhci-tegra.0", NULL),
|
||||||
OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC2_BASE, "sdhci-tegra.1", NULL),
|
OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC2_BASE, "sdhci-tegra.1", NULL),
|
||||||
OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC3_BASE, "sdhci-tegra.2", NULL),
|
OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC3_BASE, "sdhci-tegra.2", NULL),
|
||||||
|
@ -200,7 +201,7 @@ DT_MACHINE_START(TEGRA_DT, "nVidia Tegra20 (Flattened Device Tree)")
|
||||||
.smp = smp_ops(tegra_smp_ops),
|
.smp = smp_ops(tegra_smp_ops),
|
||||||
.init_early = tegra20_init_early,
|
.init_early = tegra20_init_early,
|
||||||
.init_irq = tegra_dt_init_irq,
|
.init_irq = tegra_dt_init_irq,
|
||||||
.init_time = tegra_init_timer,
|
.init_time = clocksource_of_init,
|
||||||
.init_machine = tegra_dt_init,
|
.init_machine = tegra_dt_init,
|
||||||
.init_late = tegra_dt_init_late,
|
.init_late = tegra_dt_init_late,
|
||||||
.restart = tegra_assert_system_reset,
|
.restart = tegra_assert_system_reset,
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/clocksource.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/of_address.h>
|
#include <linux/of_address.h>
|
||||||
|
@ -37,7 +38,7 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "iomap.h"
|
#include "iomap.h"
|
||||||
|
|
||||||
struct of_dev_auxdata tegra30_auxdata_lookup[] __initdata = {
|
static struct of_dev_auxdata tegra30_auxdata_lookup[] __initdata = {
|
||||||
OF_DEV_AUXDATA("nvidia,tegra20-sdhci", 0x78000000, "sdhci-tegra.0", NULL),
|
OF_DEV_AUXDATA("nvidia,tegra20-sdhci", 0x78000000, "sdhci-tegra.0", NULL),
|
||||||
OF_DEV_AUXDATA("nvidia,tegra20-sdhci", 0x78000200, "sdhci-tegra.1", NULL),
|
OF_DEV_AUXDATA("nvidia,tegra20-sdhci", 0x78000200, "sdhci-tegra.1", NULL),
|
||||||
OF_DEV_AUXDATA("nvidia,tegra20-sdhci", 0x78000400, "sdhci-tegra.2", NULL),
|
OF_DEV_AUXDATA("nvidia,tegra20-sdhci", 0x78000400, "sdhci-tegra.2", NULL),
|
||||||
|
@ -111,7 +112,7 @@ DT_MACHINE_START(TEGRA30_DT, "NVIDIA Tegra30 (Flattened Device Tree)")
|
||||||
.map_io = tegra_map_common_io,
|
.map_io = tegra_map_common_io,
|
||||||
.init_early = tegra30_init_early,
|
.init_early = tegra30_init_early,
|
||||||
.init_irq = tegra_dt_init_irq,
|
.init_irq = tegra_dt_init_irq,
|
||||||
.init_time = tegra_init_timer,
|
.init_time = clocksource_of_init,
|
||||||
.init_machine = tegra30_dt_init,
|
.init_machine = tegra30_dt_init,
|
||||||
.init_late = tegra_init_late,
|
.init_late = tegra_init_late,
|
||||||
.restart = tegra_assert_system_reset,
|
.restart = tegra_assert_system_reset,
|
||||||
|
|
|
@ -55,5 +55,4 @@ static inline int harmony_pcie_init(void) { return 0; }
|
||||||
|
|
||||||
void __init tegra_paz00_wifikill_init(void);
|
void __init tegra_paz00_wifikill_init(void);
|
||||||
|
|
||||||
extern void tegra_init_timer(void);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include "apbio.h"
|
#include "apbio.h"
|
||||||
#include "sleep.h"
|
#include "sleep.h"
|
||||||
#include "pm.h"
|
#include "pm.h"
|
||||||
|
#include "reset.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Storage for debug-macro.S's state.
|
* Storage for debug-macro.S's state.
|
||||||
|
@ -131,6 +132,7 @@ static void __init tegra_init_cache(void)
|
||||||
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
|
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
|
||||||
void __init tegra20_init_early(void)
|
void __init tegra20_init_early(void)
|
||||||
{
|
{
|
||||||
|
tegra_cpu_reset_handler_init();
|
||||||
tegra_apb_io_init();
|
tegra_apb_io_init();
|
||||||
tegra_init_fuse();
|
tegra_init_fuse();
|
||||||
tegra2_init_clocks();
|
tegra2_init_clocks();
|
||||||
|
@ -144,6 +146,7 @@ void __init tegra20_init_early(void)
|
||||||
#ifdef CONFIG_ARCH_TEGRA_3x_SOC
|
#ifdef CONFIG_ARCH_TEGRA_3x_SOC
|
||||||
void __init tegra30_init_early(void)
|
void __init tegra30_init_early(void)
|
||||||
{
|
{
|
||||||
|
tegra_cpu_reset_handler_init();
|
||||||
tegra_apb_io_init();
|
tegra_apb_io_init();
|
||||||
tegra_init_fuse();
|
tegra_init_fuse();
|
||||||
tegra30_init_clocks();
|
tegra30_init_clocks();
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
extern struct smp_operations tegra_smp_ops;
|
extern struct smp_operations tegra_smp_ops;
|
||||||
|
|
||||||
|
extern int tegra_cpu_kill(unsigned int cpu);
|
||||||
extern void tegra_cpu_die(unsigned int cpu);
|
extern void tegra_cpu_die(unsigned int cpu);
|
||||||
extern int tegra_cpu_disable(unsigned int cpu);
|
extern int tegra_cpu_disable(unsigned int cpu);
|
||||||
|
|
|
@ -214,24 +214,6 @@ static int tegra_cpu_init(struct cpufreq_policy *policy)
|
||||||
if (policy->cpu >= NUM_CPUS)
|
if (policy->cpu >= NUM_CPUS)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
cpu_clk = clk_get_sys(NULL, "cpu");
|
|
||||||
if (IS_ERR(cpu_clk))
|
|
||||||
return PTR_ERR(cpu_clk);
|
|
||||||
|
|
||||||
pll_x_clk = clk_get_sys(NULL, "pll_x");
|
|
||||||
if (IS_ERR(pll_x_clk))
|
|
||||||
return PTR_ERR(pll_x_clk);
|
|
||||||
|
|
||||||
pll_p_clk = clk_get_sys(NULL, "pll_p");
|
|
||||||
if (IS_ERR(pll_p_clk))
|
|
||||||
return PTR_ERR(pll_p_clk);
|
|
||||||
|
|
||||||
emc_clk = clk_get_sys("cpu", "emc");
|
|
||||||
if (IS_ERR(emc_clk)) {
|
|
||||||
clk_put(cpu_clk);
|
|
||||||
return PTR_ERR(emc_clk);
|
|
||||||
}
|
|
||||||
|
|
||||||
clk_prepare_enable(emc_clk);
|
clk_prepare_enable(emc_clk);
|
||||||
clk_prepare_enable(cpu_clk);
|
clk_prepare_enable(cpu_clk);
|
||||||
|
|
||||||
|
@ -256,8 +238,6 @@ static int tegra_cpu_exit(struct cpufreq_policy *policy)
|
||||||
{
|
{
|
||||||
cpufreq_frequency_table_cpuinfo(policy, freq_table);
|
cpufreq_frequency_table_cpuinfo(policy, freq_table);
|
||||||
clk_disable_unprepare(emc_clk);
|
clk_disable_unprepare(emc_clk);
|
||||||
clk_put(emc_clk);
|
|
||||||
clk_put(cpu_clk);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,12 +258,32 @@ static struct cpufreq_driver tegra_cpufreq_driver = {
|
||||||
|
|
||||||
static int __init tegra_cpufreq_init(void)
|
static int __init tegra_cpufreq_init(void)
|
||||||
{
|
{
|
||||||
|
cpu_clk = clk_get_sys(NULL, "cpu");
|
||||||
|
if (IS_ERR(cpu_clk))
|
||||||
|
return PTR_ERR(cpu_clk);
|
||||||
|
|
||||||
|
pll_x_clk = clk_get_sys(NULL, "pll_x");
|
||||||
|
if (IS_ERR(pll_x_clk))
|
||||||
|
return PTR_ERR(pll_x_clk);
|
||||||
|
|
||||||
|
pll_p_clk = clk_get_sys(NULL, "pll_p");
|
||||||
|
if (IS_ERR(pll_p_clk))
|
||||||
|
return PTR_ERR(pll_p_clk);
|
||||||
|
|
||||||
|
emc_clk = clk_get_sys("cpu", "emc");
|
||||||
|
if (IS_ERR(emc_clk)) {
|
||||||
|
clk_put(cpu_clk);
|
||||||
|
return PTR_ERR(emc_clk);
|
||||||
|
}
|
||||||
|
|
||||||
return cpufreq_register_driver(&tegra_cpufreq_driver);
|
return cpufreq_register_driver(&tegra_cpufreq_driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit tegra_cpufreq_exit(void)
|
static void __exit tegra_cpufreq_exit(void)
|
||||||
{
|
{
|
||||||
cpufreq_unregister_driver(&tegra_cpufreq_driver);
|
cpufreq_unregister_driver(&tegra_cpufreq_driver);
|
||||||
|
clk_put(emc_clk);
|
||||||
|
clk_put(cpu_clk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -121,9 +121,9 @@ static inline bool tegra30_cpu_core_power_down(struct cpuidle_device *dev,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int __cpuinit tegra30_idle_lp2(struct cpuidle_device *dev,
|
static int tegra30_idle_lp2(struct cpuidle_device *dev,
|
||||||
struct cpuidle_driver *drv,
|
struct cpuidle_driver *drv,
|
||||||
int index)
|
int index)
|
||||||
{
|
{
|
||||||
u32 cpu = is_smp() ? cpu_logical_map(dev->cpu) : dev->cpu;
|
u32 cpu = is_smp() ? cpu_logical_map(dev->cpu) : dev->cpu;
|
||||||
bool entered_lp2 = false;
|
bool entered_lp2 = false;
|
||||||
|
|
|
@ -26,14 +26,14 @@
|
||||||
#include "flowctrl.h"
|
#include "flowctrl.h"
|
||||||
#include "iomap.h"
|
#include "iomap.h"
|
||||||
|
|
||||||
u8 flowctrl_offset_halt_cpu[] = {
|
static u8 flowctrl_offset_halt_cpu[] = {
|
||||||
FLOW_CTRL_HALT_CPU0_EVENTS,
|
FLOW_CTRL_HALT_CPU0_EVENTS,
|
||||||
FLOW_CTRL_HALT_CPU1_EVENTS,
|
FLOW_CTRL_HALT_CPU1_EVENTS,
|
||||||
FLOW_CTRL_HALT_CPU1_EVENTS + 8,
|
FLOW_CTRL_HALT_CPU1_EVENTS + 8,
|
||||||
FLOW_CTRL_HALT_CPU1_EVENTS + 16,
|
FLOW_CTRL_HALT_CPU1_EVENTS + 16,
|
||||||
};
|
};
|
||||||
|
|
||||||
u8 flowctrl_offset_cpu_csr[] = {
|
static u8 flowctrl_offset_cpu_csr[] = {
|
||||||
FLOW_CTRL_CPU0_CSR,
|
FLOW_CTRL_CPU0_CSR,
|
||||||
FLOW_CTRL_CPU1_CSR,
|
FLOW_CTRL_CPU1_CSR,
|
||||||
FLOW_CTRL_CPU1_CSR + 8,
|
FLOW_CTRL_CPU1_CSR + 8,
|
||||||
|
|
|
@ -1,22 +1,9 @@
|
||||||
#include <linux/linkage.h>
|
#include <linux/linkage.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
|
||||||
#include <asm/cache.h>
|
|
||||||
#include <asm/asm-offsets.h>
|
|
||||||
#include <asm/hardware/cache-l2x0.h>
|
|
||||||
|
|
||||||
#include "flowctrl.h"
|
|
||||||
#include "iomap.h"
|
|
||||||
#include "reset.h"
|
|
||||||
#include "sleep.h"
|
#include "sleep.h"
|
||||||
|
|
||||||
#define APB_MISC_GP_HIDREV 0x804
|
|
||||||
#define PMC_SCRATCH41 0x140
|
|
||||||
|
|
||||||
#define RESET_DATA(x) ((TEGRA_RESET_##x)*4)
|
|
||||||
|
|
||||||
.section ".text.head", "ax"
|
.section ".text.head", "ax"
|
||||||
__CPUINIT
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Tegra specific entry point for secondary CPUs.
|
* Tegra specific entry point for secondary CPUs.
|
||||||
|
@ -61,7 +48,6 @@ ENTRY(v7_invalidate_l1)
|
||||||
mov pc, lr
|
mov pc, lr
|
||||||
ENDPROC(v7_invalidate_l1)
|
ENDPROC(v7_invalidate_l1)
|
||||||
|
|
||||||
|
|
||||||
ENTRY(tegra_secondary_startup)
|
ENTRY(tegra_secondary_startup)
|
||||||
bl v7_invalidate_l1
|
bl v7_invalidate_l1
|
||||||
/* Enable coresight */
|
/* Enable coresight */
|
||||||
|
@ -69,210 +55,3 @@ ENTRY(tegra_secondary_startup)
|
||||||
mcr p14, 0, r0, c7, c12, 6
|
mcr p14, 0, r0, c7, c12, 6
|
||||||
b secondary_startup
|
b secondary_startup
|
||||||
ENDPROC(tegra_secondary_startup)
|
ENDPROC(tegra_secondary_startup)
|
||||||
|
|
||||||
#ifdef CONFIG_PM_SLEEP
|
|
||||||
/*
|
|
||||||
* tegra_resume
|
|
||||||
*
|
|
||||||
* CPU boot vector when restarting the a CPU following
|
|
||||||
* an LP2 transition. Also branched to by LP0 and LP1 resume after
|
|
||||||
* re-enabling sdram.
|
|
||||||
*/
|
|
||||||
ENTRY(tegra_resume)
|
|
||||||
bl v7_invalidate_l1
|
|
||||||
/* Enable coresight */
|
|
||||||
mov32 r0, 0xC5ACCE55
|
|
||||||
mcr p14, 0, r0, c7, c12, 6
|
|
||||||
|
|
||||||
cpu_id r0
|
|
||||||
cmp r0, #0 @ CPU0?
|
|
||||||
bne cpu_resume @ no
|
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_TEGRA_3x_SOC
|
|
||||||
/* Are we on Tegra20? */
|
|
||||||
mov32 r6, TEGRA_APB_MISC_BASE
|
|
||||||
ldr r0, [r6, #APB_MISC_GP_HIDREV]
|
|
||||||
and r0, r0, #0xff00
|
|
||||||
cmp r0, #(0x20 << 8)
|
|
||||||
beq 1f @ Yes
|
|
||||||
/* Clear the flow controller flags for this CPU. */
|
|
||||||
mov32 r2, TEGRA_FLOW_CTRL_BASE + FLOW_CTRL_CPU0_CSR @ CPU0 CSR
|
|
||||||
ldr r1, [r2]
|
|
||||||
/* Clear event & intr flag */
|
|
||||||
orr r1, r1, \
|
|
||||||
#FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
|
|
||||||
movw r0, #0x0FFD @ enable, cluster_switch, immed, & bitmaps
|
|
||||||
bic r1, r1, r0
|
|
||||||
str r1, [r2]
|
|
||||||
1:
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_HAVE_ARM_SCU
|
|
||||||
/* enable SCU */
|
|
||||||
mov32 r0, TEGRA_ARM_PERIF_BASE
|
|
||||||
ldr r1, [r0]
|
|
||||||
orr r1, r1, #1
|
|
||||||
str r1, [r0]
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* L2 cache resume & re-enable */
|
|
||||||
l2_cache_resume r0, r1, r2, l2x0_saved_regs_addr
|
|
||||||
|
|
||||||
b cpu_resume
|
|
||||||
ENDPROC(tegra_resume)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_CACHE_L2X0
|
|
||||||
.globl l2x0_saved_regs_addr
|
|
||||||
l2x0_saved_regs_addr:
|
|
||||||
.long 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
.align L1_CACHE_SHIFT
|
|
||||||
ENTRY(__tegra_cpu_reset_handler_start)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* __tegra_cpu_reset_handler:
|
|
||||||
*
|
|
||||||
* Common handler for all CPU reset events.
|
|
||||||
*
|
|
||||||
* Register usage within the reset handler:
|
|
||||||
*
|
|
||||||
* R7 = CPU present (to the OS) mask
|
|
||||||
* R8 = CPU in LP1 state mask
|
|
||||||
* R9 = CPU in LP2 state mask
|
|
||||||
* R10 = CPU number
|
|
||||||
* R11 = CPU mask
|
|
||||||
* R12 = pointer to reset handler data
|
|
||||||
*
|
|
||||||
* NOTE: This code is copied to IRAM. All code and data accesses
|
|
||||||
* must be position-independent.
|
|
||||||
*/
|
|
||||||
|
|
||||||
.align L1_CACHE_SHIFT
|
|
||||||
ENTRY(__tegra_cpu_reset_handler)
|
|
||||||
|
|
||||||
cpsid aif, 0x13 @ SVC mode, interrupts disabled
|
|
||||||
mrc p15, 0, r10, c0, c0, 5 @ MPIDR
|
|
||||||
and r10, r10, #0x3 @ R10 = CPU number
|
|
||||||
mov r11, #1
|
|
||||||
mov r11, r11, lsl r10 @ R11 = CPU mask
|
|
||||||
adr r12, __tegra_cpu_reset_handler_data
|
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
|
||||||
/* Does the OS know about this CPU? */
|
|
||||||
ldr r7, [r12, #RESET_DATA(MASK_PRESENT)]
|
|
||||||
tst r7, r11 @ if !present
|
|
||||||
bleq __die @ CPU not present (to OS)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
|
|
||||||
/* Are we on Tegra20? */
|
|
||||||
mov32 r6, TEGRA_APB_MISC_BASE
|
|
||||||
ldr r0, [r6, #APB_MISC_GP_HIDREV]
|
|
||||||
and r0, r0, #0xff00
|
|
||||||
cmp r0, #(0x20 << 8)
|
|
||||||
bne 1f
|
|
||||||
/* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */
|
|
||||||
mov32 r6, TEGRA_PMC_BASE
|
|
||||||
mov r0, #0
|
|
||||||
cmp r10, #0
|
|
||||||
strne r0, [r6, #PMC_SCRATCH41]
|
|
||||||
1:
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Waking up from LP2? */
|
|
||||||
ldr r9, [r12, #RESET_DATA(MASK_LP2)]
|
|
||||||
tst r9, r11 @ if in_lp2
|
|
||||||
beq __is_not_lp2
|
|
||||||
ldr lr, [r12, #RESET_DATA(STARTUP_LP2)]
|
|
||||||
cmp lr, #0
|
|
||||||
bleq __die @ no LP2 startup handler
|
|
||||||
bx lr
|
|
||||||
|
|
||||||
__is_not_lp2:
|
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
|
||||||
/*
|
|
||||||
* Can only be secondary boot (initial or hotplug) but CPU 0
|
|
||||||
* cannot be here.
|
|
||||||
*/
|
|
||||||
cmp r10, #0
|
|
||||||
bleq __die @ CPU0 cannot be here
|
|
||||||
ldr lr, [r12, #RESET_DATA(STARTUP_SECONDARY)]
|
|
||||||
cmp lr, #0
|
|
||||||
bleq __die @ no secondary startup handler
|
|
||||||
bx lr
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We don't know why the CPU reset. Just kill it.
|
|
||||||
* The LR register will contain the address we died at + 4.
|
|
||||||
*/
|
|
||||||
|
|
||||||
__die:
|
|
||||||
sub lr, lr, #4
|
|
||||||
mov32 r7, TEGRA_PMC_BASE
|
|
||||||
str lr, [r7, #PMC_SCRATCH41]
|
|
||||||
|
|
||||||
mov32 r7, TEGRA_CLK_RESET_BASE
|
|
||||||
|
|
||||||
/* Are we on Tegra20? */
|
|
||||||
mov32 r6, TEGRA_APB_MISC_BASE
|
|
||||||
ldr r0, [r6, #APB_MISC_GP_HIDREV]
|
|
||||||
and r0, r0, #0xff00
|
|
||||||
cmp r0, #(0x20 << 8)
|
|
||||||
bne 1f
|
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
|
|
||||||
mov32 r0, 0x1111
|
|
||||||
mov r1, r0, lsl r10
|
|
||||||
str r1, [r7, #0x340] @ CLK_RST_CPU_CMPLX_SET
|
|
||||||
#endif
|
|
||||||
1:
|
|
||||||
#ifdef CONFIG_ARCH_TEGRA_3x_SOC
|
|
||||||
mov32 r6, TEGRA_FLOW_CTRL_BASE
|
|
||||||
|
|
||||||
cmp r10, #0
|
|
||||||
moveq r1, #FLOW_CTRL_HALT_CPU0_EVENTS
|
|
||||||
moveq r2, #FLOW_CTRL_CPU0_CSR
|
|
||||||
movne r1, r10, lsl #3
|
|
||||||
addne r2, r1, #(FLOW_CTRL_CPU1_CSR-8)
|
|
||||||
addne r1, r1, #(FLOW_CTRL_HALT_CPU1_EVENTS-8)
|
|
||||||
|
|
||||||
/* Clear CPU "event" and "interrupt" flags and power gate
|
|
||||||
it when halting but not before it is in the "WFI" state. */
|
|
||||||
ldr r0, [r6, +r2]
|
|
||||||
orr r0, r0, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
|
|
||||||
orr r0, r0, #FLOW_CTRL_CSR_ENABLE
|
|
||||||
str r0, [r6, +r2]
|
|
||||||
|
|
||||||
/* Unconditionally halt this CPU */
|
|
||||||
mov r0, #FLOW_CTRL_WAITEVENT
|
|
||||||
str r0, [r6, +r1]
|
|
||||||
ldr r0, [r6, +r1] @ memory barrier
|
|
||||||
|
|
||||||
dsb
|
|
||||||
isb
|
|
||||||
wfi @ CPU should be power gated here
|
|
||||||
|
|
||||||
/* If the CPU didn't power gate above just kill it's clock. */
|
|
||||||
|
|
||||||
mov r0, r11, lsl #8
|
|
||||||
str r0, [r7, #348] @ CLK_CPU_CMPLX_SET
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* If the CPU still isn't dead, just spin here. */
|
|
||||||
b .
|
|
||||||
ENDPROC(__tegra_cpu_reset_handler)
|
|
||||||
|
|
||||||
.align L1_CACHE_SHIFT
|
|
||||||
.type __tegra_cpu_reset_handler_data, %object
|
|
||||||
.globl __tegra_cpu_reset_handler_data
|
|
||||||
__tegra_cpu_reset_handler_data:
|
|
||||||
.rept TEGRA_RESET_DATA_SIZE
|
|
||||||
.long 0
|
|
||||||
.endr
|
|
||||||
.align L1_CACHE_SHIFT
|
|
||||||
|
|
||||||
ENTRY(__tegra_cpu_reset_handler_end)
|
|
||||||
|
|
|
@ -19,6 +19,17 @@
|
||||||
|
|
||||||
static void (*tegra_hotplug_shutdown)(void);
|
static void (*tegra_hotplug_shutdown)(void);
|
||||||
|
|
||||||
|
int tegra_cpu_kill(unsigned cpu)
|
||||||
|
{
|
||||||
|
cpu = cpu_logical_map(cpu);
|
||||||
|
|
||||||
|
/* Clock gate the CPU */
|
||||||
|
tegra_wait_cpu_in_reset(cpu);
|
||||||
|
tegra_disable_cpu_clock(cpu);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* platform-specific code to shutdown a CPU
|
* platform-specific code to shutdown a CPU
|
||||||
*
|
*
|
||||||
|
@ -26,18 +37,12 @@ static void (*tegra_hotplug_shutdown)(void);
|
||||||
*/
|
*/
|
||||||
void __ref tegra_cpu_die(unsigned int cpu)
|
void __ref tegra_cpu_die(unsigned int cpu)
|
||||||
{
|
{
|
||||||
cpu = cpu_logical_map(cpu);
|
/* Clean L1 data cache */
|
||||||
|
tegra_disable_clean_inv_dcache();
|
||||||
/* Flush the L1 data cache. */
|
|
||||||
flush_cache_all();
|
|
||||||
|
|
||||||
/* Shut down the current CPU. */
|
/* Shut down the current CPU. */
|
||||||
tegra_hotplug_shutdown();
|
tegra_hotplug_shutdown();
|
||||||
|
|
||||||
/* Clock gate the CPU */
|
|
||||||
tegra_wait_cpu_in_reset(cpu);
|
|
||||||
tegra_disable_cpu_clock(cpu);
|
|
||||||
|
|
||||||
/* Should never return here. */
|
/* Should never return here. */
|
||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
#include <asm/mach-types.h>
|
#include <asm/mach-types.h>
|
||||||
#include <asm/smp_scu.h>
|
#include <asm/smp_scu.h>
|
||||||
|
#include <asm/smp_plat.h>
|
||||||
|
|
||||||
#include <mach/powergate.h>
|
#include <mach/powergate.h>
|
||||||
|
|
||||||
|
@ -36,6 +37,7 @@
|
||||||
|
|
||||||
extern void tegra_secondary_startup(void);
|
extern void tegra_secondary_startup(void);
|
||||||
|
|
||||||
|
static cpumask_t tegra_cpu_init_mask;
|
||||||
static void __iomem *scu_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE);
|
static void __iomem *scu_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE);
|
||||||
|
|
||||||
#define EVP_CPU_RESET_VECTOR \
|
#define EVP_CPU_RESET_VECTOR \
|
||||||
|
@ -50,6 +52,7 @@ static void __cpuinit tegra_secondary_init(unsigned int cpu)
|
||||||
*/
|
*/
|
||||||
gic_secondary_init(0);
|
gic_secondary_init(0);
|
||||||
|
|
||||||
|
cpumask_set_cpu(cpu, &tegra_cpu_init_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tegra20_power_up_cpu(unsigned int cpu)
|
static int tegra20_power_up_cpu(unsigned int cpu)
|
||||||
|
@ -72,14 +75,42 @@ static int tegra30_power_up_cpu(unsigned int cpu)
|
||||||
if (pwrgateid < 0)
|
if (pwrgateid < 0)
|
||||||
return pwrgateid;
|
return pwrgateid;
|
||||||
|
|
||||||
/* If this is the first boot, toggle powergates directly. */
|
/*
|
||||||
|
* 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
|
||||||
|
* the confirmaiton that the CPU is powered then removing
|
||||||
|
* 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()
|
||||||
|
* 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))
|
||||||
|
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.
|
||||||
|
*/
|
||||||
if (!tegra_powergate_is_powered(pwrgateid)) {
|
if (!tegra_powergate_is_powered(pwrgateid)) {
|
||||||
ret = tegra_powergate_power_on(pwrgateid);
|
ret = tegra_powergate_power_on(pwrgateid);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Wait for the power to come up. */
|
/* Wait for the power to come up. */
|
||||||
timeout = jiffies + 10*HZ;
|
timeout = jiffies + msecs_to_jiffies(100);
|
||||||
while (tegra_powergate_is_powered(pwrgateid)) {
|
while (tegra_powergate_is_powered(pwrgateid)) {
|
||||||
if (time_after(jiffies, timeout))
|
if (time_after(jiffies, timeout))
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
|
@ -87,6 +118,7 @@ static int tegra30_power_up_cpu(unsigned int cpu)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
remove_clamps:
|
||||||
/* CPU partition is powered. Enable the CPU clock. */
|
/* CPU partition is powered. Enable the CPU clock. */
|
||||||
tegra_enable_cpu_clock(cpu);
|
tegra_enable_cpu_clock(cpu);
|
||||||
udelay(10);
|
udelay(10);
|
||||||
|
@ -105,6 +137,8 @@ static int __cpuinit tegra_boot_secondary(unsigned int cpu, struct task_struct *
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
|
cpu = cpu_logical_map(cpu);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Force the CPU into reset. The CPU must remain in reset when the
|
* Force the CPU into reset. The CPU must remain in reset when the
|
||||||
* flow controller state is cleared (which will cause the flow
|
* flow controller state is cleared (which will cause the flow
|
||||||
|
@ -163,7 +197,9 @@ static void __init tegra_smp_init_cpus(void)
|
||||||
|
|
||||||
static void __init tegra_smp_prepare_cpus(unsigned int max_cpus)
|
static void __init tegra_smp_prepare_cpus(unsigned int max_cpus)
|
||||||
{
|
{
|
||||||
tegra_cpu_reset_handler_init();
|
/* Always mark the boot CPU (CPU0) as initialized. */
|
||||||
|
cpumask_set_cpu(0, &tegra_cpu_init_mask);
|
||||||
|
|
||||||
scu_enable(scu_base);
|
scu_enable(scu_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,6 +209,7 @@ struct smp_operations tegra_smp_ops __initdata = {
|
||||||
.smp_secondary_init = tegra_secondary_init,
|
.smp_secondary_init = tegra_secondary_init,
|
||||||
.smp_boot_secondary = tegra_boot_secondary,
|
.smp_boot_secondary = tegra_boot_secondary,
|
||||||
#ifdef CONFIG_HOTPLUG_CPU
|
#ifdef CONFIG_HOTPLUG_CPU
|
||||||
|
.cpu_kill = tegra_cpu_kill,
|
||||||
.cpu_die = tegra_cpu_die,
|
.cpu_die = tegra_cpu_die,
|
||||||
.cpu_disable = tegra_cpu_disable,
|
.cpu_disable = tegra_cpu_disable,
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -148,7 +148,7 @@ static void suspend_cpu_complex(void)
|
||||||
save_cpu_arch_register();
|
save_cpu_arch_register();
|
||||||
}
|
}
|
||||||
|
|
||||||
void __cpuinit tegra_clear_cpu_in_lp2(int phy_cpu_id)
|
void tegra_clear_cpu_in_lp2(int phy_cpu_id)
|
||||||
{
|
{
|
||||||
u32 *cpu_in_lp2 = tegra_cpu_lp2_mask;
|
u32 *cpu_in_lp2 = tegra_cpu_lp2_mask;
|
||||||
|
|
||||||
|
@ -160,7 +160,7 @@ void __cpuinit tegra_clear_cpu_in_lp2(int phy_cpu_id)
|
||||||
spin_unlock(&tegra_lp2_lock);
|
spin_unlock(&tegra_lp2_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool __cpuinit tegra_set_cpu_in_lp2(int phy_cpu_id)
|
bool tegra_set_cpu_in_lp2(int phy_cpu_id)
|
||||||
{
|
{
|
||||||
bool last_cpu = false;
|
bool last_cpu = false;
|
||||||
cpumask_t *cpu_lp2_mask = tegra_cpu_lp2_mask;
|
cpumask_t *cpu_lp2_mask = tegra_cpu_lp2_mask;
|
||||||
|
|
|
@ -0,0 +1,239 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012, NVIDIA Corporation. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/linkage.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
|
||||||
|
#include <asm/cache.h>
|
||||||
|
#include <asm/asm-offsets.h>
|
||||||
|
#include <asm/hardware/cache-l2x0.h>
|
||||||
|
|
||||||
|
#include "flowctrl.h"
|
||||||
|
#include "iomap.h"
|
||||||
|
#include "reset.h"
|
||||||
|
#include "sleep.h"
|
||||||
|
|
||||||
|
#define APB_MISC_GP_HIDREV 0x804
|
||||||
|
#define PMC_SCRATCH41 0x140
|
||||||
|
|
||||||
|
#define RESET_DATA(x) ((TEGRA_RESET_##x)*4)
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
/*
|
||||||
|
* tegra_resume
|
||||||
|
*
|
||||||
|
* CPU boot vector when restarting the a CPU following
|
||||||
|
* an LP2 transition. Also branched to by LP0 and LP1 resume after
|
||||||
|
* re-enabling sdram.
|
||||||
|
*/
|
||||||
|
ENTRY(tegra_resume)
|
||||||
|
bl v7_invalidate_l1
|
||||||
|
/* Enable coresight */
|
||||||
|
mov32 r0, 0xC5ACCE55
|
||||||
|
mcr p14, 0, r0, c7, c12, 6
|
||||||
|
|
||||||
|
cpu_id r0
|
||||||
|
cmp r0, #0 @ CPU0?
|
||||||
|
bne cpu_resume @ no
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARCH_TEGRA_3x_SOC
|
||||||
|
/* Are we on Tegra20? */
|
||||||
|
mov32 r6, TEGRA_APB_MISC_BASE
|
||||||
|
ldr r0, [r6, #APB_MISC_GP_HIDREV]
|
||||||
|
and r0, r0, #0xff00
|
||||||
|
cmp r0, #(0x20 << 8)
|
||||||
|
beq 1f @ Yes
|
||||||
|
/* Clear the flow controller flags for this CPU. */
|
||||||
|
mov32 r2, TEGRA_FLOW_CTRL_BASE + FLOW_CTRL_CPU0_CSR @ CPU0 CSR
|
||||||
|
ldr r1, [r2]
|
||||||
|
/* Clear event & intr flag */
|
||||||
|
orr r1, r1, \
|
||||||
|
#FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
|
||||||
|
movw r0, #0x0FFD @ enable, cluster_switch, immed, & bitmaps
|
||||||
|
bic r1, r1, r0
|
||||||
|
str r1, [r2]
|
||||||
|
1:
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_HAVE_ARM_SCU
|
||||||
|
/* enable SCU */
|
||||||
|
mov32 r0, TEGRA_ARM_PERIF_BASE
|
||||||
|
ldr r1, [r0]
|
||||||
|
orr r1, r1, #1
|
||||||
|
str r1, [r0]
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* L2 cache resume & re-enable */
|
||||||
|
l2_cache_resume r0, r1, r2, l2x0_saved_regs_addr
|
||||||
|
|
||||||
|
b cpu_resume
|
||||||
|
ENDPROC(tegra_resume)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_CACHE_L2X0
|
||||||
|
.globl l2x0_saved_regs_addr
|
||||||
|
l2x0_saved_regs_addr:
|
||||||
|
.long 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
.align L1_CACHE_SHIFT
|
||||||
|
ENTRY(__tegra_cpu_reset_handler_start)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* __tegra_cpu_reset_handler:
|
||||||
|
*
|
||||||
|
* Common handler for all CPU reset events.
|
||||||
|
*
|
||||||
|
* Register usage within the reset handler:
|
||||||
|
*
|
||||||
|
* R7 = CPU present (to the OS) mask
|
||||||
|
* R8 = CPU in LP1 state mask
|
||||||
|
* R9 = CPU in LP2 state mask
|
||||||
|
* R10 = CPU number
|
||||||
|
* R11 = CPU mask
|
||||||
|
* R12 = pointer to reset handler data
|
||||||
|
*
|
||||||
|
* NOTE: This code is copied to IRAM. All code and data accesses
|
||||||
|
* must be position-independent.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.align L1_CACHE_SHIFT
|
||||||
|
ENTRY(__tegra_cpu_reset_handler)
|
||||||
|
|
||||||
|
cpsid aif, 0x13 @ SVC mode, interrupts disabled
|
||||||
|
mrc p15, 0, r10, c0, c0, 5 @ MPIDR
|
||||||
|
and r10, r10, #0x3 @ R10 = CPU number
|
||||||
|
mov r11, #1
|
||||||
|
mov r11, r11, lsl r10 @ R11 = CPU mask
|
||||||
|
adr r12, __tegra_cpu_reset_handler_data
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
/* Does the OS know about this CPU? */
|
||||||
|
ldr r7, [r12, #RESET_DATA(MASK_PRESENT)]
|
||||||
|
tst r7, r11 @ if !present
|
||||||
|
bleq __die @ CPU not present (to OS)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
|
||||||
|
/* Are we on Tegra20? */
|
||||||
|
mov32 r6, TEGRA_APB_MISC_BASE
|
||||||
|
ldr r0, [r6, #APB_MISC_GP_HIDREV]
|
||||||
|
and r0, r0, #0xff00
|
||||||
|
cmp r0, #(0x20 << 8)
|
||||||
|
bne 1f
|
||||||
|
/* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */
|
||||||
|
mov32 r6, TEGRA_PMC_BASE
|
||||||
|
mov r0, #0
|
||||||
|
cmp r10, #0
|
||||||
|
strne r0, [r6, #PMC_SCRATCH41]
|
||||||
|
1:
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Waking up from LP2? */
|
||||||
|
ldr r9, [r12, #RESET_DATA(MASK_LP2)]
|
||||||
|
tst r9, r11 @ if in_lp2
|
||||||
|
beq __is_not_lp2
|
||||||
|
ldr lr, [r12, #RESET_DATA(STARTUP_LP2)]
|
||||||
|
cmp lr, #0
|
||||||
|
bleq __die @ no LP2 startup handler
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
__is_not_lp2:
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
/*
|
||||||
|
* Can only be secondary boot (initial or hotplug) but CPU 0
|
||||||
|
* cannot be here.
|
||||||
|
*/
|
||||||
|
cmp r10, #0
|
||||||
|
bleq __die @ CPU0 cannot be here
|
||||||
|
ldr lr, [r12, #RESET_DATA(STARTUP_SECONDARY)]
|
||||||
|
cmp lr, #0
|
||||||
|
bleq __die @ no secondary startup handler
|
||||||
|
bx lr
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We don't know why the CPU reset. Just kill it.
|
||||||
|
* The LR register will contain the address we died at + 4.
|
||||||
|
*/
|
||||||
|
|
||||||
|
__die:
|
||||||
|
sub lr, lr, #4
|
||||||
|
mov32 r7, TEGRA_PMC_BASE
|
||||||
|
str lr, [r7, #PMC_SCRATCH41]
|
||||||
|
|
||||||
|
mov32 r7, TEGRA_CLK_RESET_BASE
|
||||||
|
|
||||||
|
/* Are we on Tegra20? */
|
||||||
|
mov32 r6, TEGRA_APB_MISC_BASE
|
||||||
|
ldr r0, [r6, #APB_MISC_GP_HIDREV]
|
||||||
|
and r0, r0, #0xff00
|
||||||
|
cmp r0, #(0x20 << 8)
|
||||||
|
bne 1f
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
|
||||||
|
mov32 r0, 0x1111
|
||||||
|
mov r1, r0, lsl r10
|
||||||
|
str r1, [r7, #0x340] @ CLK_RST_CPU_CMPLX_SET
|
||||||
|
#endif
|
||||||
|
1:
|
||||||
|
#ifdef CONFIG_ARCH_TEGRA_3x_SOC
|
||||||
|
mov32 r6, TEGRA_FLOW_CTRL_BASE
|
||||||
|
|
||||||
|
cmp r10, #0
|
||||||
|
moveq r1, #FLOW_CTRL_HALT_CPU0_EVENTS
|
||||||
|
moveq r2, #FLOW_CTRL_CPU0_CSR
|
||||||
|
movne r1, r10, lsl #3
|
||||||
|
addne r2, r1, #(FLOW_CTRL_CPU1_CSR-8)
|
||||||
|
addne r1, r1, #(FLOW_CTRL_HALT_CPU1_EVENTS-8)
|
||||||
|
|
||||||
|
/* Clear CPU "event" and "interrupt" flags and power gate
|
||||||
|
it when halting but not before it is in the "WFI" state. */
|
||||||
|
ldr r0, [r6, +r2]
|
||||||
|
orr r0, r0, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
|
||||||
|
orr r0, r0, #FLOW_CTRL_CSR_ENABLE
|
||||||
|
str r0, [r6, +r2]
|
||||||
|
|
||||||
|
/* Unconditionally halt this CPU */
|
||||||
|
mov r0, #FLOW_CTRL_WAITEVENT
|
||||||
|
str r0, [r6, +r1]
|
||||||
|
ldr r0, [r6, +r1] @ memory barrier
|
||||||
|
|
||||||
|
dsb
|
||||||
|
isb
|
||||||
|
wfi @ CPU should be power gated here
|
||||||
|
|
||||||
|
/* If the CPU didn't power gate above just kill it's clock. */
|
||||||
|
|
||||||
|
mov r0, r11, lsl #8
|
||||||
|
str r0, [r7, #348] @ CLK_CPU_CMPLX_SET
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* If the CPU still isn't dead, just spin here. */
|
||||||
|
b .
|
||||||
|
ENDPROC(__tegra_cpu_reset_handler)
|
||||||
|
|
||||||
|
.align L1_CACHE_SHIFT
|
||||||
|
.type __tegra_cpu_reset_handler_data, %object
|
||||||
|
.globl __tegra_cpu_reset_handler_data
|
||||||
|
__tegra_cpu_reset_handler_data:
|
||||||
|
.rept TEGRA_RESET_DATA_SIZE
|
||||||
|
.long 0
|
||||||
|
.endr
|
||||||
|
.align L1_CACHE_SHIFT
|
||||||
|
|
||||||
|
ENTRY(__tegra_cpu_reset_handler_end)
|
|
@ -75,7 +75,7 @@ void __init tegra_cpu_reset_handler_init(void)
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
__tegra_cpu_reset_handler_data[TEGRA_RESET_MASK_PRESENT] =
|
__tegra_cpu_reset_handler_data[TEGRA_RESET_MASK_PRESENT] =
|
||||||
*((u32 *)cpu_present_mask);
|
*((u32 *)cpu_possible_mask);
|
||||||
__tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_SECONDARY] =
|
__tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_SECONDARY] =
|
||||||
virt_to_phys((void *)tegra_secondary_startup);
|
virt_to_phys((void *)tegra_secondary_startup);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -33,9 +33,6 @@
|
||||||
* should never return
|
* should never return
|
||||||
*/
|
*/
|
||||||
ENTRY(tegra20_hotplug_shutdown)
|
ENTRY(tegra20_hotplug_shutdown)
|
||||||
/* Turn off SMP coherency */
|
|
||||||
exit_smp r4, r5
|
|
||||||
|
|
||||||
/* Put this CPU down */
|
/* Put this CPU down */
|
||||||
cpu_id r0
|
cpu_id r0
|
||||||
bl tegra20_cpu_shutdown
|
bl tegra20_cpu_shutdown
|
||||||
|
|
|
@ -32,9 +32,6 @@
|
||||||
* Should never return.
|
* Should never return.
|
||||||
*/
|
*/
|
||||||
ENTRY(tegra30_hotplug_shutdown)
|
ENTRY(tegra30_hotplug_shutdown)
|
||||||
/* Turn off SMP coherency */
|
|
||||||
exit_smp r4, r5
|
|
||||||
|
|
||||||
/* Powergate this CPU */
|
/* Powergate this CPU */
|
||||||
mov r0, #TEGRA30_POWER_HOTPLUG_SHUTDOWN
|
mov r0, #TEGRA30_POWER_HOTPLUG_SHUTDOWN
|
||||||
bl tegra30_cpu_shutdown
|
bl tegra30_cpu_shutdown
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
#include "flowctrl.h"
|
#include "flowctrl.h"
|
||||||
#include "sleep.h"
|
#include "sleep.h"
|
||||||
|
|
||||||
#ifdef CONFIG_PM_SLEEP
|
#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP)
|
||||||
/*
|
/*
|
||||||
* tegra_disable_clean_inv_dcache
|
* tegra_disable_clean_inv_dcache
|
||||||
*
|
*
|
||||||
|
@ -60,7 +60,9 @@ ENTRY(tegra_disable_clean_inv_dcache)
|
||||||
|
|
||||||
ldmfd sp!, {r0, r4-r5, r7, r9-r11, pc}
|
ldmfd sp!, {r0, r4-r5, r7, r9-r11, pc}
|
||||||
ENDPROC(tegra_disable_clean_inv_dcache)
|
ENDPROC(tegra_disable_clean_inv_dcache)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
/*
|
/*
|
||||||
* tegra_sleep_cpu_finish(unsigned long v2p)
|
* tegra_sleep_cpu_finish(unsigned long v2p)
|
||||||
*
|
*
|
||||||
|
|
|
@ -106,6 +106,7 @@ exit_l2_resume:
|
||||||
#else
|
#else
|
||||||
void tegra_resume(void);
|
void tegra_resume(void);
|
||||||
int tegra_sleep_cpu_finish(unsigned long);
|
int tegra_sleep_cpu_finish(unsigned long);
|
||||||
|
void tegra_disable_clean_inv_dcache(void);
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG_CPU
|
#ifdef CONFIG_HOTPLUG_CPU
|
||||||
void tegra20_hotplug_init(void);
|
void tegra20_hotplug_init(void);
|
||||||
|
|
|
@ -1183,7 +1183,7 @@ static struct clk tegra_dsib = {
|
||||||
.num_parents = ARRAY_SIZE(mux_plld_out0_plld2_out0),
|
.num_parents = ARRAY_SIZE(mux_plld_out0_plld2_out0),
|
||||||
};
|
};
|
||||||
|
|
||||||
struct clk *tegra_list_clks[] = {
|
static struct clk *tegra_list_clks[] = {
|
||||||
&tegra_apbdma,
|
&tegra_apbdma,
|
||||||
&tegra_rtc,
|
&tegra_rtc,
|
||||||
&tegra_kbc,
|
&tegra_kbc,
|
||||||
|
@ -1289,7 +1289,7 @@ struct clk *tegra_list_clks[] = {
|
||||||
* configuration. List those here to register them twice in the clock lookup
|
* configuration. List those here to register them twice in the clock lookup
|
||||||
* table under two names.
|
* table under two names.
|
||||||
*/
|
*/
|
||||||
struct clk_duplicate tegra_clk_duplicates[] = {
|
static struct clk_duplicate tegra_clk_duplicates[] = {
|
||||||
CLK_DUPLICATE("uarta", "serial8250.0", NULL),
|
CLK_DUPLICATE("uarta", "serial8250.0", NULL),
|
||||||
CLK_DUPLICATE("uartb", "serial8250.1", NULL),
|
CLK_DUPLICATE("uartb", "serial8250.1", NULL),
|
||||||
CLK_DUPLICATE("uartc", "serial8250.2", NULL),
|
CLK_DUPLICATE("uartc", "serial8250.2", NULL),
|
||||||
|
@ -1340,7 +1340,7 @@ struct clk_duplicate tegra_clk_duplicates[] = {
|
||||||
CLK_DUPLICATE("pll_d2_out0", "hdmi", "parent"),
|
CLK_DUPLICATE("pll_d2_out0", "hdmi", "parent"),
|
||||||
};
|
};
|
||||||
|
|
||||||
struct clk *tegra_ptr_clks[] = {
|
static struct clk *tegra_ptr_clks[] = {
|
||||||
&tegra_clk_32k,
|
&tegra_clk_32k,
|
||||||
&tegra_clk_m,
|
&tegra_clk_m,
|
||||||
&tegra_clk_m_div2,
|
&tegra_clk_m_div2,
|
||||||
|
|
|
@ -17,6 +17,7 @@ obj-$(CONFIG_CLKSRC_DBX500_PRCMU) += clksrc-dbx500-prcmu.o
|
||||||
obj-$(CONFIG_ARMADA_370_XP_TIMER) += time-armada-370-xp.o
|
obj-$(CONFIG_ARMADA_370_XP_TIMER) += time-armada-370-xp.o
|
||||||
obj-$(CONFIG_ARCH_BCM2835) += bcm2835_timer.o
|
obj-$(CONFIG_ARCH_BCM2835) += bcm2835_timer.o
|
||||||
obj-$(CONFIG_SUNXI_TIMER) += sunxi_timer.o
|
obj-$(CONFIG_SUNXI_TIMER) += sunxi_timer.o
|
||||||
|
obj-$(CONFIG_ARCH_TEGRA) += tegra20_timer.o
|
||||||
obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o
|
obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o
|
||||||
|
|
||||||
obj-$(CONFIG_CLKSRC_ARM_GENERIC) += arm_generic.o
|
obj-$(CONFIG_CLKSRC_ARM_GENERIC) += arm_generic.o
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
/*
|
/*
|
||||||
* arch/arch/mach-tegra/timer.c
|
|
||||||
*
|
|
||||||
* Copyright (C) 2010 Google, Inc.
|
* Copyright (C) 2010 Google, Inc.
|
||||||
*
|
*
|
||||||
* Author:
|
* Author:
|
||||||
|
@ -33,8 +31,6 @@
|
||||||
#include <asm/smp_twd.h>
|
#include <asm/smp_twd.h>
|
||||||
#include <asm/sched_clock.h>
|
#include <asm/sched_clock.h>
|
||||||
|
|
||||||
#include "board.h"
|
|
||||||
|
|
||||||
#define RTC_SECONDS 0x08
|
#define RTC_SECONDS 0x08
|
||||||
#define RTC_SHADOW_SECONDS 0x0c
|
#define RTC_SHADOW_SECONDS 0x0c
|
||||||
#define RTC_MILLISECONDS 0x10
|
#define RTC_MILLISECONDS 0x10
|
||||||
|
@ -168,7 +164,7 @@ static const struct of_device_id rtc_match[] __initconst = {
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
void __init tegra_init_timer(void)
|
static void __init tegra20_init_timer(void)
|
||||||
{
|
{
|
||||||
struct device_node *np;
|
struct device_node *np;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
|
@ -183,7 +179,7 @@ void __init tegra_init_timer(void)
|
||||||
|
|
||||||
timer_reg_base = of_iomap(np, 0);
|
timer_reg_base = of_iomap(np, 0);
|
||||||
if (!timer_reg_base) {
|
if (!timer_reg_base) {
|
||||||
pr_err("Can't map timer registers");
|
pr_err("Can't map timer registers\n");
|
||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,6 +264,7 @@ void __init tegra_init_timer(void)
|
||||||
#endif
|
#endif
|
||||||
register_persistent_clock(NULL, tegra_read_persistent_clock);
|
register_persistent_clock(NULL, tegra_read_persistent_clock);
|
||||||
}
|
}
|
||||||
|
CLOCKSOURCE_OF_DECLARE(tegra20, "nvidia,tegra20-timer", tegra20_init_timer);
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
static u32 usec_config;
|
static u32 usec_config;
|
Loading…
Reference in New Issue