[ARM] tegra: nvrm: remove AVP module relocation

Change-Id: I8ba0907f7c1dec77e7ca3f22874837cf044300a2
Signed-off-by: Dima Zavin <dima@android.com>
This commit is contained in:
Gary King
2010-08-24 19:06:58 -07:00
committed by Colin Cross
parent 5e82e54db9
commit 31f9e3abeb
9 changed files with 519 additions and 1504 deletions

View File

@@ -102,6 +102,9 @@
#define TEGRA_APB_DMA_CH0_BASE 0x6000B000
#define TEGRA_APB_DMA_CH0_SIZE 32
#define TEGRA_AVP_CACHE_BASE 0x6000C000
#define TEGRA_AVP_CACHE_SIZE 4
#define TEGRA_AHB_GIZMO_BASE 0x6000C004
#define TEGRA_AHB_GIZMO_SIZE 0x10C

View File

@@ -50,6 +50,7 @@ typedef enum
{
NvRmModuleLoaderReason_Attach = 0,
NvRmModuleLoaderReason_Detach,
NvRmModuleLoaderReason_AttachGreedy,
NvRmModuleLoaderReason_Num,
NvRmModuleLoaderReason_Force32 = 0x7FFFFFFF
} NvRmModuleLoaderReason;

View File

@@ -35,6 +35,7 @@
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/firmware.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
@@ -56,22 +57,14 @@
#include "mach/io.h"
#include "mach/iomap.h"
static NvU32 s_AvpInitialized = NV_FALSE;
static NvRmLibraryHandle s_hAvpLibrary = NULL;
#define _TEGRA_AVP_RESET_VECTOR_ADDR \
(IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + EVP_COP_RESET_VECTOR_0)
#define NV_USE_AOS 1
#define AVP_EXECUTABLE_NAME "nvrm_avp.axf"
void NvRmPrivProcessMessage(NvRmRPCHandle hRPCHandle, char *pRecvMessage, int messageLength)
{
NvError Error = NvSuccess;
NvRmMemHandle hMem;
switch ((NvRmMsg)*pRecvMessage) {
switch (*(NvRmMsg *)pRecvMessage) {
case NvRmMsg_MemHandleCreate:
{
@@ -107,7 +100,7 @@ void NvRmPrivProcessMessage(NvRmRPCHandle hRPCHandle, char *pRecvMessage, int me
NvRmMessage_Response msgResponse;
msgMemAlloc = (NvRmMessage_MemAlloc*)pRecvMessage;
Error = NvRmMemAlloc(msgMemAlloc->hMem,
Error = NvRmMemAlloc(msgMemAlloc->hMem,
(msgMemAlloc->NumHeaps == 0) ? NULL : msgMemAlloc->Heaps,
msgMemAlloc->NumHeaps,
msgMemAlloc->Alignment,
@@ -267,175 +260,15 @@ void NvRmPrivProcessMessage(NvRmRPCHandle hRPCHandle, char *pRecvMessage, int me
NvRmMessage_RemotePrintf *msg;
msg = (NvRmMessage_RemotePrintf*)pRecvMessage;
NvOsDebugPrintf("AVP: %s", msg->string);
printk("AVP: %s", msg->string);
}
break;
case NvRmMsg_AVP_Reset:
NvOsDebugPrintf("AVP has been reset by WDT\n");
break;
default:
NV_ASSERT( !"AVP Service::ProcessMessage: bad message" );
break;
panic("AVP Service::ProcessMessage: bad message");
break;
}
}
NvError
NvRmPrivInitAvp(NvRmDeviceHandle hDevice)
{
NvError err = NvSuccess;
void* avpExecutionJumpAddress;
NvU32 RegVal, resetVector;
// Do this only once.
if (s_AvpInitialized) return NvSuccess;
NvOsDebugPrintf("%s <kernel impl>: called\n", __func__);
err = NvRmPrivLoadKernelLibrary(hDevice, AVP_EXECUTABLE_NAME, &s_hAvpLibrary);
if (err != NvSuccess) {
NV_DEBUG_PRINTF(("AVP executable file not found\n"));
NV_ASSERT(!"AVP executable file not found");
}
err = NvRmGetProcAddress(s_hAvpLibrary, "main", &avpExecutionJumpAddress);
NV_ASSERT(err == NvSuccess);
NvOsDebugPrintf("%s <kernel impl>: avpExecutionJumpAddress=%x\n", __func__, avpExecutionJumpAddress);
resetVector = (NvU32)avpExecutionJumpAddress & 0xFFFFFFFE;
NV_WRITE32(_TEGRA_AVP_RESET_VECTOR_ADDR, resetVector);
RegVal = NV_READ32(_TEGRA_AVP_RESET_VECTOR_ADDR);
NV_ASSERT( RegVal == resetVector );
NvRmModuleReset(hDevice, NvRmModuleID_Avp);
/// Resume AVP
RegVal = NV_DRF_DEF(FLOW_CTLR, HALT_COP_EVENTS, MODE, FLOW_MODE_NONE);
NV_WRITE32(IO_ADDRESS(TEGRA_FLOW_CTRL_BASE) + FLOW_CTLR_HALT_COP_EVENTS_0, RegVal);
s_AvpInitialized = NV_TRUE;
err = NvRmPrivInitService(hDevice);
if (err) return err;
err = NvRmPrivInitModuleLoaderRPC(hDevice);
if (err) return err;
return err;
}
static void __iomem *iram_base = IO_ADDRESS(TEGRA_IRAM_BASE);
static void __iomem *iram_backup;
static dma_addr_t iram_backup_addr;
static u32 iram_size = TEGRA_IRAM_SIZE;
static u32 iram_backup_size = TEGRA_IRAM_SIZE + 4;
static u32 avp_resume_addr;
NvError
NvRmPrivSuspendAvp(NvRmRPCHandle hRPCHandle)
{
NvError err = NvSuccess;
NvRmMessage_InitiateLP0 lp0_msg;
void *avp_suspend_done = iram_backup + iram_size;
unsigned long timeout;
pr_info("%s()+\n", __func__);
if (!s_AvpInitialized)
goto done;
else if (!iram_backup_addr) {
/* XXX: should we return error? */
pr_warning("%s: iram backup ram missing, not suspending avp\n",
__func__);
goto done;
}
NV_ASSERT(hRPCHandle->svcTransportHandle != NULL);
lp0_msg.msg = NvRmMsg_InitiateLP0;
lp0_msg.sourceAddr = (u32)TEGRA_IRAM_BASE;
lp0_msg.bufferAddr = (u32)iram_backup_addr;
lp0_msg.bufferSize = (u32)iram_size;
writel(0, avp_suspend_done);
NvOsMutexLock(hRPCHandle->RecvLock);
err = NvRmTransportSendMsg(hRPCHandle->svcTransportHandle, &lp0_msg,
sizeof(lp0_msg), 1000);
NvOsMutexUnlock(hRPCHandle->RecvLock);
if (err != NvSuccess) {
pr_err("%s: cannot send AVP LP0 message\n", __func__);
goto done;
}
timeout = jiffies + msecs_to_jiffies(1000);
while (!readl(avp_suspend_done) && time_before(jiffies, timeout)) {
udelay(10);
cpu_relax();
}
if (!readl(avp_suspend_done)) {
pr_err("%s: AVP failed to suspend\n", __func__);
err = NvError_Timeout;
goto done;
}
avp_resume_addr = readl(iram_base);
if (!avp_resume_addr) {
pr_err("%s: AVP failed to set it's resume address\n", __func__);
err = NvError_InvalidState;
goto done;
}
pr_info("avp_suspend: resume_addr=%x\n", avp_resume_addr);
avp_resume_addr &= 0xFFFFFFFE;
pr_info("%s()-\n", __func__);
done:
return err;
}
NvError
NvRmPrivResumeAvp(NvRmRPCHandle hRPCHandle)
{
NvError ret = NvSuccess;
u32 tmp;
pr_info("%s()+\n", __func__);
if (!s_AvpInitialized || !avp_resume_addr)
goto done;
writel(avp_resume_addr, _TEGRA_AVP_RESET_VECTOR_ADDR);
tmp = readl(_TEGRA_AVP_RESET_VECTOR_ADDR);
NV_ASSERT(tmp == resetVector);
NvRmModuleReset(hRPCHandle->hRmDevice, NvRmModuleID_Avp);
/// Resume AVP
tmp = NV_DRF_DEF(FLOW_CTLR, HALT_COP_EVENTS, MODE, FLOW_MODE_NONE);
writel(tmp, IO_ADDRESS(TEGRA_FLOW_CTRL_BASE) + FLOW_CTLR_HALT_COP_EVENTS_0);
/* clear the avp resume addr so that if suspend fails, we don't try to
* resume */
avp_resume_addr = 0;
pr_info("%s()-\n", __func__);
done:
return ret;
}
int __init _avp_suspend_resume_init(void)
{
/* allocate an iram sized chunk of ram to give to the AVP */
iram_backup = dma_alloc_coherent(NULL, iram_backup_size,
&iram_backup_addr, GFP_KERNEL);
if (!iram_backup) {
pr_err("%s: Unable to allocate iram backup mem\n", __func__);
return -ENOMEM;
}
return 0;
}

View File

@@ -10,6 +10,7 @@ ccflags-y += -Iarch/arm/mach-tegra/nv/include
ccflags-y += -Iarch/arm/mach-tegra/nv/nvrm/core/common
ccflags-y += -Iarch/arm/mach-tegra/nv/nvrm/core
obj-y += headavp.o
obj-y += nvrm_avp_cpu_rpc.o
obj-y += nvrm_moduleloader.o
obj-y += nvrm_rmctrace.o

View File

@@ -0,0 +1,66 @@
/*
* arch/arm/mach-tegra/headavp.S
*
* AVP kernel launcher stub; programs the AVP MMU and jumps to the
* kernel code. Must use ONLY ARMv4 instructions, and must be compiled
* in ARM mode.
*
* Copyright (c) 2010, NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that 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, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
#include "headavp.h"
#define PTE0_COMPARE 0
/* the default translation will translate any VA within
* 0x0010:0000..0x001f:ffff to the (megabyte-aligned) value written to
* _tegra_avp_launcher_stub_data[AVP_LAUNCHER_MMU_PHYSICAL]
*/
#define PTE0_DEFAULT (0x00100000 | 0x3ff0)
#define PTE0_TRANSLATE 4
#define TRANSLATE_DATA (1 << 11)
#define TRANSLATE_CODE (1 << 10)
#define TRANSLATE_WR (1 << 9)
#define TRANSLATE_RD (1 << 8)
#define TRANSLATE_HIT (1 << 7)
#define TRANSLATE_EN (1 << 2)
#define TRANSLATE_OPT (TRANSLATE_DATA | TRANSLATE_CODE | TRANSLATE_WR | \
TRANSLATE_RD | TRANSLATE_HIT)
ENTRY(_tegra_avp_launcher_stub)
adr r4, _tegra_avp_launcher_stub_data
ldmia r4, {r0-r3}
str r2, [r0, #PTE0_COMPARE]
bic r3, r3, #0xff0
bic r3, r3, #0x00f
orr r3, r3, #TRANSLATE_OPT
orr r3, r3, #TRANSLATE_EN
str r3, [r0, #PTE0_TRANSLATE]
bx r1
b .
ENDPROC(_tegra_avp_launcher_stub)
.type _tegra_avp_launcher_stub_data, %object
ENTRY(_tegra_avp_launcher_stub_data)
.long AVP_MMU_TLB_BASE
.long 0xdeadbeef
.long PTE0_DEFAULT
.long 0xdeadd00d
.size _tegra_avp_launcher_stub_data, . - _tegra_avp_launcher_stub_data

View File

@@ -0,0 +1,39 @@
/*
* arch/arm/mach-tegra/headavp.h
*
* Copyright (c) 2010, NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that 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, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef _MACH_TEGRA_HEADAVP_H
#define _MACH_TEGRA_HEADAVP_H
#define AVP_MMU_TLB_BASE 0xF000F000
#define AVP_LAUNCHER_START_VA 1
#define AVP_LAUNCHER_MMU_VIRTUAL 2
#define AVP_LAUNCHER_MMU_PHYSICAL 3
#define EVP_COP_RESET 0x200
#define FLOW_CTRL_HALT_COP 0x4
#ifndef __ASSEMBLY__
extern void _tegra_avp_launcher_stub(void);
extern u32 _tegra_avp_launcher_stub_data[];
#endif
#endif

View File

@@ -121,7 +121,7 @@ typedef struct{
typedef struct{
NvRmMsg msg;
NvRmMemHandle hMem;
NvRmHeap Heaps[NvRmHeap_Num];
NvRmHeap Heaps[4];
NvU32 NumHeaps;
NvU32 Alignment;
NvOsMemAttribute Coherency;
@@ -244,21 +244,23 @@ typedef struct{
typedef struct{
NvRmMsg msg;
NvU32 entryAddress;
NvU32 address;
NvU32 size;
NvU32 filesize;
char args[MAX_ARGS_SIZE];
NvU32 reason;
}NvRmMessage_AttachModule;
typedef struct{
typedef struct {
NvRmMsg msg;
NvError error;
NvU32 libraryId;
}NvRmMessage_AttachModuleResponse;
typedef struct{
typedef struct {
NvRmMsg msg;
NvU32 reason;
NvU32 entryAddress;
NvU32 libraryId;
}NvRmMessage_DetachModule;
typedef struct{

File diff suppressed because it is too large Load Diff

View File

@@ -93,9 +93,7 @@ struct SegmentRec
/// ModuleLoader handle structure
typedef struct NvRmLibraryRec
{
void* pLibBaseAddress;
void* EntryAddress;
SegmentNode *pList;
NvU32 libraryId;
} NvRmLibHandle;
NvError
@@ -148,7 +146,6 @@ NvRmPrivGetProcAddress(NvRmLibraryHandle Handle,
NvError NvRmPrivFreeLibrary(NvRmLibHandle *hLibHandle);
NvError NvRmPrivInitModuleLoaderRPC(NvRmDeviceHandle hDevice);
NvError NvRmPrivInitAvp(NvRmDeviceHandle hDevice);
/// Unmap memory segments
void UnMapRegion(SegmentNode *pList);