mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-11 13:27:06 +09:00
[ARM] tegra: nvrm: remove AVP module relocation
Change-Id: I8ba0907f7c1dec77e7ca3f22874837cf044300a2 Signed-off-by: Dima Zavin <dima@android.com>
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ typedef enum
|
||||
{
|
||||
NvRmModuleLoaderReason_Attach = 0,
|
||||
NvRmModuleLoaderReason_Detach,
|
||||
NvRmModuleLoaderReason_AttachGreedy,
|
||||
NvRmModuleLoaderReason_Num,
|
||||
NvRmModuleLoaderReason_Force32 = 0x7FFFFFFF
|
||||
} NvRmModuleLoaderReason;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
66
arch/arm/mach-tegra/nv/nvrm/core/common/headavp.S
Normal file
66
arch/arm/mach-tegra/nv/nvrm/core/common/headavp.S
Normal 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
|
||||
39
arch/arm/mach-tegra/nv/nvrm/core/common/headavp.h
Normal file
39
arch/arm/mach-tegra/nv/nvrm/core/common/headavp.h
Normal 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
|
||||
@@ -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
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user