From e02c75201244202d6a9adc74c219c715b3f439b4 Mon Sep 17 00:00:00 2001 From: Gary King Date: Wed, 1 Sep 2010 13:19:38 -0700 Subject: [PATCH] [ARM] tegra: nvrm_transport: handshake AVP reset with kernel the AVP kernel modifies the AVP reset vector after it starts to its own value; poll this register to verify that the AVP kernel has started properly. Change-Id: I5d9f36dd2763c0df28576f3cb86de20f6aae0ef2 Signed-off-by: Gary King --- .../nv/nvrm/core/common/nvrm_moduleloader.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-tegra/nv/nvrm/core/common/nvrm_moduleloader.c b/arch/arm/mach-tegra/nv/nvrm/core/common/nvrm_moduleloader.c index 22241b72a70e..695216c8fed3 100644 --- a/arch/arm/mach-tegra/nv/nvrm/core/common/nvrm_moduleloader.c +++ b/arch/arm/mach-tegra/nv/nvrm/core/common/nvrm_moduleloader.c @@ -516,6 +516,7 @@ static void NvRmPrivResetAvp(NvRmDeviceHandle hRm, unsigned long reset_va) u32 *stub_va = &_tegra_avp_launcher_stub_data[AVP_LAUNCHER_START_VA]; unsigned long stub_addr = virt_to_phys(_tegra_avp_launcher_stub); unsigned int tmp; + unsigned long timeout; *stub_va = reset_va; __cpuc_flush_dcache_area(stub_va, sizeof(*stub_va)); @@ -526,8 +527,18 @@ static void NvRmPrivResetAvp(NvRmDeviceHandle hRm, unsigned long reset_va) barrier(); NvRmModuleReset(hRm, NvRmModuleID_Avp); writel(0, IO_ADDRESS(TEGRA_FLOW_CTRL_BASE) + FLOW_CTRL_HALT_COP); + barrier(); - writel(tmp, _TEGRA_AVP_RESET_VECTOR_ADDR); + timeout = jiffies + HZ; + /* the AVP firmware will reprogram its reset vector as the kernel + * starts, so a dead kernel can be detected by polling this value */ + while (time_before(jiffies, timeout)) { + if (readl(_TEGRA_AVP_RESET_VECTOR_ADDR) != stub_addr) + break; + cpu_relax(); + } + + WARN_ON(readl(_TEGRA_AVP_RESET_VECTOR_ADDR) == stub_addr); } void NvRmPrivXpcSendMsgAddress(void); -- 2.34.1