mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-19 03:08:31 +00:00
61e129885a
Signed-off-by: Marek Vasut <marex@denx.de> Cc: Bryan Hundven <bryanhundven@gmail.com> Cc: Michael Schwingen <rincewind@discworld.dascon.de> Cc: Wolfgang Denk <wd@denx.de> Cc: Albert Aribaud <albert.u.boot@aribaud.net> Cc: U-Boot DM <u-boot-dm@lists.denx.de> Cc: Joe Hershberger <joe.hershberger@ni.com>
931 lines
27 KiB
C
931 lines
27 KiB
C
/**
|
|
* @file IxNpeDlNpeMgr.c
|
|
*
|
|
* @author Intel Corporation
|
|
* @date 09 January 2002
|
|
*
|
|
* @brief This file contains the implementation of the private API for the
|
|
* IXP425 NPE Downloader NpeMgr module
|
|
*
|
|
*
|
|
* @par
|
|
* IXP400 SW Release version 2.0
|
|
*
|
|
* -- Copyright Notice --
|
|
*
|
|
* @par
|
|
* Copyright 2001-2005, Intel Corporation.
|
|
* All rights reserved.
|
|
*
|
|
* @par
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* @par
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
* SUCH DAMAGE.
|
|
*
|
|
* @par
|
|
* -- End of Copyright Notice --
|
|
*/
|
|
|
|
|
|
/*
|
|
* Put the user defined include files required.
|
|
*/
|
|
#include "IxOsal.h"
|
|
#include "IxNpeDl.h"
|
|
#include "IxNpeDlNpeMgr_p.h"
|
|
#include "IxNpeDlNpeMgrUtils_p.h"
|
|
#include "IxNpeDlNpeMgrEcRegisters_p.h"
|
|
#include "IxNpeDlMacros_p.h"
|
|
#include "IxFeatureCtrl.h"
|
|
|
|
/*
|
|
* #defines and macros used in this file.
|
|
*/
|
|
#define IX_NPEDL_BYTES_PER_WORD 4
|
|
|
|
/* used to read download map from version in microcode image */
|
|
#define IX_NPEDL_BLOCK_TYPE_INSTRUCTION 0x00000000
|
|
#define IX_NPEDL_BLOCK_TYPE_DATA 0x00000001
|
|
#define IX_NPEDL_BLOCK_TYPE_STATE 0x00000002
|
|
#define IX_NPEDL_END_OF_DOWNLOAD_MAP 0x0000000F
|
|
|
|
/*
|
|
* masks used to extract address info from State information context
|
|
* register addresses as read from microcode image
|
|
*/
|
|
#define IX_NPEDL_MASK_STATE_ADDR_CTXT_REG 0x0000000F
|
|
#define IX_NPEDL_MASK_STATE_ADDR_CTXT_NUM 0x000000F0
|
|
|
|
/* LSB offset of Context Number field in State-Info Context Address */
|
|
#define IX_NPEDL_OFFSET_STATE_ADDR_CTXT_NUM 4
|
|
|
|
/* size (in words) of single State Information entry (ctxt reg address|data) */
|
|
#define IX_NPEDL_STATE_INFO_ENTRY_SIZE 2
|
|
|
|
|
|
#define IX_NPEDL_RESET_NPE_PARITY 0x0800
|
|
#define IX_NPEDL_PARITY_BIT_MASK 0x3F00FFFF
|
|
#define IX_NPEDL_CONFIG_CTRL_REG_MASK 0x3F3FFFFF
|
|
|
|
|
|
/*
|
|
* Typedefs whose scope is limited to this file.
|
|
*/
|
|
|
|
typedef struct
|
|
{
|
|
UINT32 type;
|
|
UINT32 offset;
|
|
} IxNpeDlNpeMgrDownloadMapBlockEntry;
|
|
|
|
typedef union
|
|
{
|
|
IxNpeDlNpeMgrDownloadMapBlockEntry block;
|
|
UINT32 eodmMarker;
|
|
} IxNpeDlNpeMgrDownloadMapEntry;
|
|
|
|
typedef struct
|
|
{
|
|
/* 1st entry in the download map (there may be more than one) */
|
|
IxNpeDlNpeMgrDownloadMapEntry entry[1];
|
|
} IxNpeDlNpeMgrDownloadMap;
|
|
|
|
|
|
/* used to access an instruction or data block in a microcode image */
|
|
typedef struct
|
|
{
|
|
UINT32 npeMemAddress;
|
|
UINT32 size;
|
|
UINT32 data[1];
|
|
} IxNpeDlNpeMgrCodeBlock;
|
|
|
|
/* used to access each Context Reg entry state-information block */
|
|
typedef struct
|
|
{
|
|
UINT32 addressInfo;
|
|
UINT32 value;
|
|
} IxNpeDlNpeMgrStateInfoCtxtRegEntry;
|
|
|
|
/* used to access a state-information block in a microcode image */
|
|
typedef struct
|
|
{
|
|
UINT32 size;
|
|
IxNpeDlNpeMgrStateInfoCtxtRegEntry ctxtRegEntry[1];
|
|
} IxNpeDlNpeMgrStateInfoBlock;
|
|
|
|
/* used to store some useful NPE information for easy access */
|
|
typedef struct
|
|
{
|
|
UINT32 baseAddress;
|
|
UINT32 insMemSize;
|
|
UINT32 dataMemSize;
|
|
} IxNpeDlNpeInfo;
|
|
|
|
/* used to distinguish instruction and data memory operations */
|
|
typedef enum
|
|
{
|
|
IX_NPEDL_MEM_TYPE_INSTRUCTION = 0,
|
|
IX_NPEDL_MEM_TYPE_DATA
|
|
} IxNpeDlNpeMemType;
|
|
|
|
/* used to hold a reset value for a particular ECS register */
|
|
typedef struct
|
|
{
|
|
UINT32 regAddr;
|
|
UINT32 regResetVal;
|
|
} IxNpeDlEcsRegResetValue;
|
|
|
|
/* prototype of function to write either Instruction or Data memory */
|
|
typedef IX_STATUS (*IxNpeDlNpeMgrMemWrite) (UINT32 npeBaseAddress,
|
|
UINT32 npeMemAddress,
|
|
UINT32 npeMemData,
|
|
BOOL verify);
|
|
|
|
/* module statistics counters */
|
|
typedef struct
|
|
{
|
|
UINT32 instructionBlocksLoaded;
|
|
UINT32 dataBlocksLoaded;
|
|
UINT32 stateInfoBlocksLoaded;
|
|
UINT32 criticalNpeErrors;
|
|
UINT32 criticalMicrocodeErrors;
|
|
UINT32 npeStarts;
|
|
UINT32 npeStops;
|
|
UINT32 npeResets;
|
|
} IxNpeDlNpeMgrStats;
|
|
|
|
|
|
/*
|
|
* Variable declarations global to this file only. Externs are followed by
|
|
* static variables.
|
|
*/
|
|
static IxNpeDlNpeInfo ixNpeDlNpeInfo[] =
|
|
{
|
|
{
|
|
0,
|
|
IX_NPEDL_INS_MEMSIZE_WORDS_NPEA,
|
|
IX_NPEDL_DATA_MEMSIZE_WORDS_NPEA
|
|
},
|
|
{
|
|
0,
|
|
IX_NPEDL_INS_MEMSIZE_WORDS_NPEB,
|
|
IX_NPEDL_DATA_MEMSIZE_WORDS_NPEB
|
|
},
|
|
{
|
|
0,
|
|
IX_NPEDL_INS_MEMSIZE_WORDS_NPEC,
|
|
IX_NPEDL_DATA_MEMSIZE_WORDS_NPEC
|
|
}
|
|
};
|
|
|
|
/* contains Reset values for Context Store Registers */
|
|
static UINT32 ixNpeDlCtxtRegResetValues[] =
|
|
{
|
|
IX_NPEDL_CTXT_REG_RESET_STEVT,
|
|
IX_NPEDL_CTXT_REG_RESET_STARTPC,
|
|
IX_NPEDL_CTXT_REG_RESET_REGMAP,
|
|
IX_NPEDL_CTXT_REG_RESET_CINDEX,
|
|
};
|
|
|
|
/* contains Reset values for Context Store Registers */
|
|
static IxNpeDlEcsRegResetValue ixNpeDlEcsRegResetValues[] =
|
|
{
|
|
{IX_NPEDL_ECS_BG_CTXT_REG_0, IX_NPEDL_ECS_BG_CTXT_REG_0_RESET},
|
|
{IX_NPEDL_ECS_BG_CTXT_REG_1, IX_NPEDL_ECS_BG_CTXT_REG_1_RESET},
|
|
{IX_NPEDL_ECS_BG_CTXT_REG_2, IX_NPEDL_ECS_BG_CTXT_REG_2_RESET},
|
|
{IX_NPEDL_ECS_PRI_1_CTXT_REG_0, IX_NPEDL_ECS_PRI_1_CTXT_REG_0_RESET},
|
|
{IX_NPEDL_ECS_PRI_1_CTXT_REG_1, IX_NPEDL_ECS_PRI_1_CTXT_REG_1_RESET},
|
|
{IX_NPEDL_ECS_PRI_1_CTXT_REG_2, IX_NPEDL_ECS_PRI_1_CTXT_REG_2_RESET},
|
|
{IX_NPEDL_ECS_PRI_2_CTXT_REG_0, IX_NPEDL_ECS_PRI_2_CTXT_REG_0_RESET},
|
|
{IX_NPEDL_ECS_PRI_2_CTXT_REG_1, IX_NPEDL_ECS_PRI_2_CTXT_REG_1_RESET},
|
|
{IX_NPEDL_ECS_PRI_2_CTXT_REG_2, IX_NPEDL_ECS_PRI_2_CTXT_REG_2_RESET},
|
|
{IX_NPEDL_ECS_DBG_CTXT_REG_0, IX_NPEDL_ECS_DBG_CTXT_REG_0_RESET},
|
|
{IX_NPEDL_ECS_DBG_CTXT_REG_1, IX_NPEDL_ECS_DBG_CTXT_REG_1_RESET},
|
|
{IX_NPEDL_ECS_DBG_CTXT_REG_2, IX_NPEDL_ECS_DBG_CTXT_REG_2_RESET},
|
|
{IX_NPEDL_ECS_INSTRUCT_REG, IX_NPEDL_ECS_INSTRUCT_REG_RESET}
|
|
};
|
|
|
|
static IxNpeDlNpeMgrStats ixNpeDlNpeMgrStats;
|
|
|
|
/* Set when NPE register memory has been mapped */
|
|
static BOOL ixNpeDlMemInitialised = FALSE;
|
|
|
|
|
|
/*
|
|
* static function prototypes.
|
|
*/
|
|
PRIVATE IX_STATUS
|
|
ixNpeDlNpeMgrMemLoad (IxNpeDlNpeId npeId, UINT32 npeBaseAddress,
|
|
IxNpeDlNpeMgrCodeBlock *codeBlockPtr,
|
|
BOOL verify, IxNpeDlNpeMemType npeMemType);
|
|
PRIVATE IX_STATUS
|
|
ixNpeDlNpeMgrStateInfoLoad (UINT32 npeBaseAddress,
|
|
IxNpeDlNpeMgrStateInfoBlock *codeBlockPtr,
|
|
BOOL verify);
|
|
PRIVATE BOOL
|
|
ixNpeDlNpeMgrBitsSetCheck (UINT32 npeBaseAddress, UINT32 regOffset,
|
|
UINT32 expectedBitsSet);
|
|
|
|
PRIVATE UINT32
|
|
ixNpeDlNpeMgrBaseAddressGet (IxNpeDlNpeId npeId);
|
|
|
|
/*
|
|
* Function definition: ixNpeDlNpeMgrBaseAddressGet
|
|
*/
|
|
PRIVATE UINT32
|
|
ixNpeDlNpeMgrBaseAddressGet (IxNpeDlNpeId npeId)
|
|
{
|
|
IX_OSAL_ASSERT (ixNpeDlMemInitialised);
|
|
return ixNpeDlNpeInfo[npeId].baseAddress;
|
|
}
|
|
|
|
|
|
/*
|
|
* Function definition: ixNpeDlNpeMgrInit
|
|
*/
|
|
void
|
|
ixNpeDlNpeMgrInit (void)
|
|
{
|
|
/* Only map the memory once */
|
|
if (!ixNpeDlMemInitialised)
|
|
{
|
|
UINT32 virtAddr;
|
|
|
|
/* map the register memory for NPE-A */
|
|
virtAddr = (UINT32) IX_OSAL_MEM_MAP (IX_NPEDL_NPEBASEADDRESS_NPEA,
|
|
IX_OSAL_IXP400_NPEA_MAP_SIZE);
|
|
IX_OSAL_ASSERT(virtAddr);
|
|
ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEA].baseAddress = virtAddr;
|
|
|
|
/* map the register memory for NPE-B */
|
|
virtAddr = (UINT32) IX_OSAL_MEM_MAP (IX_NPEDL_NPEBASEADDRESS_NPEB,
|
|
IX_OSAL_IXP400_NPEB_MAP_SIZE);
|
|
IX_OSAL_ASSERT(virtAddr);
|
|
ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEB].baseAddress = virtAddr;
|
|
|
|
/* map the register memory for NPE-C */
|
|
virtAddr = (UINT32) IX_OSAL_MEM_MAP (IX_NPEDL_NPEBASEADDRESS_NPEC,
|
|
IX_OSAL_IXP400_NPEC_MAP_SIZE);
|
|
IX_OSAL_ASSERT(virtAddr);
|
|
ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEC].baseAddress = virtAddr;
|
|
|
|
ixNpeDlMemInitialised = TRUE;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Function definition: ixNpeDlNpeMgrUninit
|
|
*/
|
|
IX_STATUS
|
|
ixNpeDlNpeMgrUninit (void)
|
|
{
|
|
if (!ixNpeDlMemInitialised)
|
|
{
|
|
return IX_FAIL;
|
|
}
|
|
|
|
IX_OSAL_MEM_UNMAP (ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEA].baseAddress);
|
|
IX_OSAL_MEM_UNMAP (ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEB].baseAddress);
|
|
IX_OSAL_MEM_UNMAP (ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEC].baseAddress);
|
|
|
|
ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEA].baseAddress = 0;
|
|
ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEB].baseAddress = 0;
|
|
ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEC].baseAddress = 0;
|
|
|
|
ixNpeDlMemInitialised = FALSE;
|
|
|
|
return IX_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Function definition: ixNpeDlNpeMgrImageLoad
|
|
*/
|
|
IX_STATUS
|
|
ixNpeDlNpeMgrImageLoad (
|
|
IxNpeDlNpeId npeId,
|
|
UINT32 *imageCodePtr,
|
|
BOOL verify)
|
|
{
|
|
UINT32 npeBaseAddress;
|
|
IxNpeDlNpeMgrDownloadMap *downloadMap;
|
|
UINT32 *blockPtr;
|
|
UINT32 mapIndex = 0;
|
|
IX_STATUS status = IX_SUCCESS;
|
|
|
|
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
|
"Entering ixNpeDlNpeMgrImageLoad\n");
|
|
|
|
/* get base memory address of NPE from npeId */
|
|
npeBaseAddress = ixNpeDlNpeMgrBaseAddressGet (npeId);
|
|
|
|
/* check execution status of NPE to verify NPE Stop was successful */
|
|
if (!ixNpeDlNpeMgrBitsSetCheck (npeBaseAddress, IX_NPEDL_REG_OFFSET_EXCTL,
|
|
IX_NPEDL_EXCTL_STATUS_STOP))
|
|
{
|
|
IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrImageDownload - "
|
|
"NPE was not stopped before download\n");
|
|
status = IX_FAIL;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Read Download Map, checking each block type and calling
|
|
* appropriate function to perform download
|
|
*/
|
|
downloadMap = (IxNpeDlNpeMgrDownloadMap *) imageCodePtr;
|
|
while ((downloadMap->entry[mapIndex].eodmMarker !=
|
|
IX_NPEDL_END_OF_DOWNLOAD_MAP)
|
|
&& (status == IX_SUCCESS))
|
|
{
|
|
/* calculate pointer to block to be downloaded */
|
|
blockPtr = imageCodePtr +
|
|
downloadMap->entry[mapIndex].block.offset;
|
|
|
|
switch (downloadMap->entry[mapIndex].block.type)
|
|
{
|
|
case IX_NPEDL_BLOCK_TYPE_INSTRUCTION:
|
|
status = ixNpeDlNpeMgrMemLoad (npeId, npeBaseAddress,
|
|
(IxNpeDlNpeMgrCodeBlock *)blockPtr,
|
|
verify,
|
|
IX_NPEDL_MEM_TYPE_INSTRUCTION);
|
|
break;
|
|
case IX_NPEDL_BLOCK_TYPE_DATA:
|
|
status = ixNpeDlNpeMgrMemLoad (npeId, npeBaseAddress,
|
|
(IxNpeDlNpeMgrCodeBlock *)blockPtr,
|
|
verify, IX_NPEDL_MEM_TYPE_DATA);
|
|
break;
|
|
case IX_NPEDL_BLOCK_TYPE_STATE:
|
|
status = ixNpeDlNpeMgrStateInfoLoad (npeBaseAddress,
|
|
(IxNpeDlNpeMgrStateInfoBlock *) blockPtr,
|
|
verify);
|
|
break;
|
|
default:
|
|
IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrImageLoad: "
|
|
"unknown block type in download map\n");
|
|
status = IX_NPEDL_CRITICAL_MICROCODE_ERR;
|
|
ixNpeDlNpeMgrStats.criticalMicrocodeErrors++;
|
|
break;
|
|
}
|
|
mapIndex++;
|
|
}/* loop: for each entry in download map, while status == SUCCESS */
|
|
}/* condition: NPE stopped before attempting download */
|
|
|
|
IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
|
|
"Exiting ixNpeDlNpeMgrImageLoad : status = %d\n",
|
|
status);
|
|
return status;
|
|
}
|
|
|
|
|
|
/*
|
|
* Function definition: ixNpeDlNpeMgrMemLoad
|
|
*/
|
|
PRIVATE IX_STATUS
|
|
ixNpeDlNpeMgrMemLoad (
|
|
IxNpeDlNpeId npeId,
|
|
UINT32 npeBaseAddress,
|
|
IxNpeDlNpeMgrCodeBlock *blockPtr,
|
|
BOOL verify,
|
|
IxNpeDlNpeMemType npeMemType)
|
|
{
|
|
UINT32 npeMemAddress;
|
|
UINT32 blockSize;
|
|
UINT32 memSize = 0;
|
|
IxNpeDlNpeMgrMemWrite memWriteFunc = NULL;
|
|
UINT32 localIndex = 0;
|
|
IX_STATUS status = IX_SUCCESS;
|
|
|
|
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
|
"Entering ixNpeDlNpeMgrMemLoad\n");
|
|
|
|
/*
|
|
* select NPE EXCTL reg read/write commands depending on memory
|
|
* type (instruction/data) to be accessed
|
|
*/
|
|
if (npeMemType == IX_NPEDL_MEM_TYPE_INSTRUCTION)
|
|
{
|
|
memSize = ixNpeDlNpeInfo[npeId].insMemSize;
|
|
memWriteFunc = (IxNpeDlNpeMgrMemWrite) ixNpeDlNpeMgrInsMemWrite;
|
|
}
|
|
else if (npeMemType == IX_NPEDL_MEM_TYPE_DATA)
|
|
{
|
|
memSize = ixNpeDlNpeInfo[npeId].dataMemSize;
|
|
memWriteFunc = (IxNpeDlNpeMgrMemWrite) ixNpeDlNpeMgrDataMemWrite;
|
|
}
|
|
|
|
/*
|
|
* NPE memory is loaded contiguously from each block, so only address
|
|
* of 1st word in block is needed
|
|
*/
|
|
npeMemAddress = blockPtr->npeMemAddress;
|
|
/* number of words of instruction/data microcode in block to download */
|
|
blockSize = blockPtr->size;
|
|
if ((npeMemAddress + blockSize) > memSize)
|
|
{
|
|
IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrMemLoad: "
|
|
"Block size too big for NPE memory\n");
|
|
status = IX_NPEDL_CRITICAL_MICROCODE_ERR;
|
|
ixNpeDlNpeMgrStats.criticalMicrocodeErrors++;
|
|
}
|
|
else
|
|
{
|
|
for (localIndex = 0; localIndex < blockSize; localIndex++)
|
|
{
|
|
status = memWriteFunc (npeBaseAddress, npeMemAddress,
|
|
blockPtr->data[localIndex], verify);
|
|
|
|
if (status != IX_SUCCESS)
|
|
{
|
|
IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrMemLoad: "
|
|
"write to NPE memory failed\n");
|
|
status = IX_NPEDL_CRITICAL_NPE_ERR;
|
|
ixNpeDlNpeMgrStats.criticalNpeErrors++;
|
|
break; /* abort download */
|
|
}
|
|
/* increment target (word)address in NPE memory */
|
|
npeMemAddress++;
|
|
}
|
|
}/* condition: block size will fit in NPE memory */
|
|
|
|
if (status == IX_SUCCESS)
|
|
{
|
|
if (npeMemType == IX_NPEDL_MEM_TYPE_INSTRUCTION)
|
|
{
|
|
ixNpeDlNpeMgrStats.instructionBlocksLoaded++;
|
|
}
|
|
else if (npeMemType == IX_NPEDL_MEM_TYPE_DATA)
|
|
{
|
|
ixNpeDlNpeMgrStats.dataBlocksLoaded++;
|
|
}
|
|
}
|
|
|
|
IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
|
|
"Exiting ixNpeDlNpeMgrMemLoad : status = %d\n", status);
|
|
return status;
|
|
}
|
|
|
|
|
|
/*
|
|
* Function definition: ixNpeDlNpeMgrStateInfoLoad
|
|
*/
|
|
PRIVATE IX_STATUS
|
|
ixNpeDlNpeMgrStateInfoLoad (
|
|
UINT32 npeBaseAddress,
|
|
IxNpeDlNpeMgrStateInfoBlock *blockPtr,
|
|
BOOL verify)
|
|
{
|
|
UINT32 blockSize;
|
|
UINT32 ctxtRegAddrInfo;
|
|
UINT32 ctxtRegVal;
|
|
IxNpeDlCtxtRegNum ctxtReg; /* identifies Context Store reg (0-3) */
|
|
UINT32 ctxtNum; /* identifies Context number (0-16) */
|
|
UINT32 i;
|
|
IX_STATUS status = IX_SUCCESS;
|
|
|
|
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
|
"Entering ixNpeDlNpeMgrStateInfoLoad\n");
|
|
|
|
/* block size contains number of words of state-info in block */
|
|
blockSize = blockPtr->size;
|
|
|
|
ixNpeDlNpeMgrDebugInstructionPreExec (npeBaseAddress);
|
|
|
|
/* for each state-info context register entry in block */
|
|
for (i = 0; i < (blockSize/IX_NPEDL_STATE_INFO_ENTRY_SIZE); i++)
|
|
{
|
|
/* each state-info entry is 2 words (address, value) in length */
|
|
ctxtRegAddrInfo = (blockPtr->ctxtRegEntry[i]).addressInfo;
|
|
ctxtRegVal = (blockPtr->ctxtRegEntry[i]).value;
|
|
|
|
ctxtReg = (ctxtRegAddrInfo & IX_NPEDL_MASK_STATE_ADDR_CTXT_REG);
|
|
ctxtNum = (ctxtRegAddrInfo & IX_NPEDL_MASK_STATE_ADDR_CTXT_NUM) >>
|
|
IX_NPEDL_OFFSET_STATE_ADDR_CTXT_NUM;
|
|
|
|
/* error-check Context Register No. and Context Number values */
|
|
/* NOTE that there is no STEVT register for Context 0 */
|
|
if ((ctxtReg < 0) ||
|
|
(ctxtReg >= IX_NPEDL_CTXT_REG_MAX) ||
|
|
(ctxtNum > IX_NPEDL_CTXT_NUM_MAX) ||
|
|
((ctxtNum == 0) && (ctxtReg == IX_NPEDL_CTXT_REG_STEVT)))
|
|
{
|
|
IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrStateInfoLoad: "
|
|
"invalid Context Register Address\n");
|
|
status = IX_NPEDL_CRITICAL_MICROCODE_ERR;
|
|
ixNpeDlNpeMgrStats.criticalMicrocodeErrors++;
|
|
break; /* abort download */
|
|
}
|
|
|
|
status = ixNpeDlNpeMgrCtxtRegWrite (npeBaseAddress, ctxtNum, ctxtReg,
|
|
ctxtRegVal, verify);
|
|
if (status != IX_SUCCESS)
|
|
{
|
|
IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrStateInfoLoad: "
|
|
"write of state-info to NPE failed\n");
|
|
status = IX_NPEDL_CRITICAL_NPE_ERR;
|
|
ixNpeDlNpeMgrStats.criticalNpeErrors++;
|
|
break; /* abort download */
|
|
}
|
|
}/* loop: for each context reg entry in State Info block */
|
|
|
|
ixNpeDlNpeMgrDebugInstructionPostExec (npeBaseAddress);
|
|
|
|
if (status == IX_SUCCESS)
|
|
{
|
|
ixNpeDlNpeMgrStats.stateInfoBlocksLoaded++;
|
|
}
|
|
|
|
IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
|
|
"Exiting ixNpeDlNpeMgrStateInfoLoad : status = %d\n",
|
|
status);
|
|
return status;
|
|
}
|
|
|
|
|
|
/*
|
|
* Function definition: ixNpeDlNpeMgrNpeReset
|
|
*/
|
|
IX_STATUS
|
|
ixNpeDlNpeMgrNpeReset (
|
|
IxNpeDlNpeId npeId)
|
|
{
|
|
UINT32 npeBaseAddress;
|
|
IxNpeDlCtxtRegNum ctxtReg; /* identifies Context Store reg (0-3) */
|
|
UINT32 ctxtNum; /* identifies Context number (0-16) */
|
|
UINT32 regAddr;
|
|
UINT32 regVal;
|
|
UINT32 localIndex;
|
|
UINT32 indexMax;
|
|
IX_STATUS status = IX_SUCCESS;
|
|
IxFeatureCtrlReg unitFuseReg;
|
|
UINT32 ixNpeConfigCtrlRegVal;
|
|
|
|
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
|
"Entering ixNpeDlNpeMgrNpeReset\n");
|
|
|
|
/* get base memory address of NPE from npeId */
|
|
npeBaseAddress = ixNpeDlNpeMgrBaseAddressGet (npeId);
|
|
|
|
/* pre-store the NPE Config Control Register Value */
|
|
IX_NPEDL_REG_READ (npeBaseAddress, IX_NPEDL_REG_OFFSET_CTL, &ixNpeConfigCtrlRegVal);
|
|
|
|
ixNpeConfigCtrlRegVal |= 0x3F000000;
|
|
|
|
/* disable the parity interrupt */
|
|
IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_CTL, (ixNpeConfigCtrlRegVal & IX_NPEDL_PARITY_BIT_MASK));
|
|
|
|
ixNpeDlNpeMgrDebugInstructionPreExec (npeBaseAddress);
|
|
|
|
/*
|
|
* clear the FIFOs
|
|
*/
|
|
while (ixNpeDlNpeMgrBitsSetCheck (npeBaseAddress,
|
|
IX_NPEDL_REG_OFFSET_WFIFO,
|
|
IX_NPEDL_MASK_WFIFO_VALID))
|
|
{
|
|
/* read from the Watch-point FIFO until empty */
|
|
IX_NPEDL_REG_READ (npeBaseAddress, IX_NPEDL_REG_OFFSET_WFIFO,
|
|
®Val);
|
|
}
|
|
|
|
while (ixNpeDlNpeMgrBitsSetCheck (npeBaseAddress,
|
|
IX_NPEDL_REG_OFFSET_STAT,
|
|
IX_NPEDL_MASK_STAT_OFNE))
|
|
{
|
|
/* read from the outFIFO until empty */
|
|
IX_NPEDL_REG_READ (npeBaseAddress, IX_NPEDL_REG_OFFSET_FIFO,
|
|
®Val);
|
|
}
|
|
|
|
while (ixNpeDlNpeMgrBitsSetCheck (npeBaseAddress,
|
|
IX_NPEDL_REG_OFFSET_STAT,
|
|
IX_NPEDL_MASK_STAT_IFNE))
|
|
{
|
|
/*
|
|
* step execution of the NPE intruction to read inFIFO using
|
|
* the Debug Executing Context stack
|
|
*/
|
|
status = ixNpeDlNpeMgrDebugInstructionExec (npeBaseAddress,
|
|
IX_NPEDL_INSTR_RD_FIFO, 0, 0);
|
|
|
|
if (IX_SUCCESS != status)
|
|
{
|
|
return status;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* Reset the mailbox reg
|
|
*/
|
|
/* ...from XScale side */
|
|
IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_MBST,
|
|
IX_NPEDL_REG_RESET_MBST);
|
|
/* ...from NPE side */
|
|
status = ixNpeDlNpeMgrDebugInstructionExec (npeBaseAddress,
|
|
IX_NPEDL_INSTR_RESET_MBOX, 0, 0);
|
|
|
|
if (IX_SUCCESS != status)
|
|
{
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* Reset the physical registers in the NPE register file:
|
|
* Note: no need to save/restore REGMAP for Context 0 here
|
|
* since all Context Store regs are reset in subsequent code
|
|
*/
|
|
for (regAddr = 0;
|
|
(regAddr < IX_NPEDL_TOTAL_NUM_PHYS_REG) && (status != IX_FAIL);
|
|
regAddr++)
|
|
{
|
|
/* for each physical register in the NPE reg file, write 0 : */
|
|
status = ixNpeDlNpeMgrPhysicalRegWrite (npeBaseAddress, regAddr,
|
|
0, TRUE);
|
|
if (status != IX_SUCCESS)
|
|
{
|
|
return status; /* abort reset */
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Reset the context store:
|
|
*/
|
|
for (ctxtNum = IX_NPEDL_CTXT_NUM_MIN;
|
|
ctxtNum <= IX_NPEDL_CTXT_NUM_MAX; ctxtNum++)
|
|
{
|
|
/* set each context's Context Store registers to reset values: */
|
|
for (ctxtReg = 0; ctxtReg < IX_NPEDL_CTXT_REG_MAX; ctxtReg++)
|
|
{
|
|
/* NOTE that there is no STEVT register for Context 0 */
|
|
if (!((ctxtNum == 0) && (ctxtReg == IX_NPEDL_CTXT_REG_STEVT)))
|
|
{
|
|
regVal = ixNpeDlCtxtRegResetValues[ctxtReg];
|
|
status = ixNpeDlNpeMgrCtxtRegWrite (npeBaseAddress, ctxtNum,
|
|
ctxtReg, regVal, TRUE);
|
|
if (status != IX_SUCCESS)
|
|
{
|
|
return status; /* abort reset */
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ixNpeDlNpeMgrDebugInstructionPostExec (npeBaseAddress);
|
|
|
|
/* write Reset values to Execution Context Stack registers */
|
|
indexMax = sizeof (ixNpeDlEcsRegResetValues) /
|
|
sizeof (IxNpeDlEcsRegResetValue);
|
|
for (localIndex = 0; localIndex < indexMax; localIndex++)
|
|
{
|
|
regAddr = ixNpeDlEcsRegResetValues[localIndex].regAddr;
|
|
regVal = ixNpeDlEcsRegResetValues[localIndex].regResetVal;
|
|
ixNpeDlNpeMgrExecAccRegWrite (npeBaseAddress, regAddr, regVal);
|
|
}
|
|
|
|
/* clear the profile counter */
|
|
ixNpeDlNpeMgrCommandIssue (npeBaseAddress,
|
|
IX_NPEDL_EXCTL_CMD_CLR_PROFILE_CNT);
|
|
|
|
/* clear registers EXCT, AP0, AP1, AP2 and AP3 */
|
|
for (regAddr = IX_NPEDL_REG_OFFSET_EXCT;
|
|
regAddr <= IX_NPEDL_REG_OFFSET_AP3;
|
|
regAddr += IX_NPEDL_BYTES_PER_WORD)
|
|
{
|
|
IX_NPEDL_REG_WRITE (npeBaseAddress, regAddr, 0);
|
|
}
|
|
|
|
/* Reset the Watch-count register */
|
|
IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_WC, 0);
|
|
|
|
/*
|
|
* WR IXA00055043 - Remove IMEM Parity Introduced by NPE Reset Operation
|
|
*/
|
|
|
|
/*
|
|
* Call the feature control API to fused out and reset the NPE and its
|
|
* coprocessor - to reset internal states and remove parity error
|
|
*/
|
|
unitFuseReg = ixFeatureCtrlRead ();
|
|
unitFuseReg |= (IX_NPEDL_RESET_NPE_PARITY << npeId);
|
|
ixFeatureCtrlWrite (unitFuseReg);
|
|
|
|
/* call the feature control API to un-fused and un-reset the NPE & COP */
|
|
unitFuseReg &= (~(IX_NPEDL_RESET_NPE_PARITY << npeId));
|
|
ixFeatureCtrlWrite (unitFuseReg);
|
|
|
|
/*
|
|
* Call NpeMgr function to stop the NPE again after the Feature Control
|
|
* has unfused and Un-Reset the NPE and its associated Coprocessors
|
|
*/
|
|
status = ixNpeDlNpeMgrNpeStop (npeId);
|
|
|
|
/* restore NPE configuration bus Control Register - Parity Settings */
|
|
IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_CTL,
|
|
(ixNpeConfigCtrlRegVal & IX_NPEDL_CONFIG_CTRL_REG_MASK));
|
|
|
|
ixNpeDlNpeMgrStats.npeResets++;
|
|
|
|
IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
|
|
"Exiting ixNpeDlNpeMgrNpeReset : status = %d\n", status);
|
|
return status;
|
|
}
|
|
|
|
|
|
/*
|
|
* Function definition: ixNpeDlNpeMgrNpeStart
|
|
*/
|
|
IX_STATUS
|
|
ixNpeDlNpeMgrNpeStart (
|
|
IxNpeDlNpeId npeId)
|
|
{
|
|
UINT32 npeBaseAddress;
|
|
UINT32 ecsRegVal;
|
|
BOOL npeRunning;
|
|
IX_STATUS status = IX_SUCCESS;
|
|
|
|
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
|
"Entering ixNpeDlNpeMgrNpeStart\n");
|
|
|
|
/* get base memory address of NPE from npeId */
|
|
npeBaseAddress = ixNpeDlNpeMgrBaseAddressGet (npeId);
|
|
|
|
/*
|
|
* ensure only Background Context Stack Level is Active by turning off
|
|
* the Active bit in each of the other Executing Context Stack levels
|
|
*/
|
|
ecsRegVal = ixNpeDlNpeMgrExecAccRegRead (npeBaseAddress,
|
|
IX_NPEDL_ECS_PRI_1_CTXT_REG_0);
|
|
ecsRegVal &= ~IX_NPEDL_MASK_ECS_REG_0_ACTIVE;
|
|
ixNpeDlNpeMgrExecAccRegWrite (npeBaseAddress, IX_NPEDL_ECS_PRI_1_CTXT_REG_0,
|
|
ecsRegVal);
|
|
|
|
ecsRegVal = ixNpeDlNpeMgrExecAccRegRead (npeBaseAddress,
|
|
IX_NPEDL_ECS_PRI_2_CTXT_REG_0);
|
|
ecsRegVal &= ~IX_NPEDL_MASK_ECS_REG_0_ACTIVE;
|
|
ixNpeDlNpeMgrExecAccRegWrite (npeBaseAddress, IX_NPEDL_ECS_PRI_2_CTXT_REG_0,
|
|
ecsRegVal);
|
|
|
|
ecsRegVal = ixNpeDlNpeMgrExecAccRegRead (npeBaseAddress,
|
|
IX_NPEDL_ECS_DBG_CTXT_REG_0);
|
|
ecsRegVal &= ~IX_NPEDL_MASK_ECS_REG_0_ACTIVE;
|
|
ixNpeDlNpeMgrExecAccRegWrite (npeBaseAddress, IX_NPEDL_ECS_DBG_CTXT_REG_0,
|
|
ecsRegVal);
|
|
|
|
/* clear the pipeline */
|
|
ixNpeDlNpeMgrCommandIssue (npeBaseAddress, IX_NPEDL_EXCTL_CMD_NPE_CLR_PIPE);
|
|
|
|
/* start NPE execution by issuing command through EXCTL register on NPE */
|
|
ixNpeDlNpeMgrCommandIssue (npeBaseAddress, IX_NPEDL_EXCTL_CMD_NPE_START);
|
|
|
|
/*
|
|
* check execution status of NPE to verify NPE Start operation was
|
|
* successful
|
|
*/
|
|
npeRunning = ixNpeDlNpeMgrBitsSetCheck (npeBaseAddress,
|
|
IX_NPEDL_REG_OFFSET_EXCTL,
|
|
IX_NPEDL_EXCTL_STATUS_RUN);
|
|
if (npeRunning)
|
|
{
|
|
ixNpeDlNpeMgrStats.npeStarts++;
|
|
}
|
|
else
|
|
{
|
|
IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrNpeStart: "
|
|
"failed to start NPE execution\n");
|
|
status = IX_FAIL;
|
|
}
|
|
|
|
|
|
IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
|
|
"Exiting ixNpeDlNpeMgrNpeStart : status = %d\n", status);
|
|
return status;
|
|
}
|
|
|
|
|
|
/*
|
|
* Function definition: ixNpeDlNpeMgrNpeStop
|
|
*/
|
|
IX_STATUS
|
|
ixNpeDlNpeMgrNpeStop (
|
|
IxNpeDlNpeId npeId)
|
|
{
|
|
UINT32 npeBaseAddress;
|
|
IX_STATUS status = IX_SUCCESS;
|
|
|
|
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
|
"Entering ixNpeDlNpeMgrNpeStop\n");
|
|
|
|
/* get base memory address of NPE from npeId */
|
|
npeBaseAddress = ixNpeDlNpeMgrBaseAddressGet (npeId);
|
|
|
|
/* stop NPE execution by issuing command through EXCTL register on NPE */
|
|
ixNpeDlNpeMgrCommandIssue (npeBaseAddress, IX_NPEDL_EXCTL_CMD_NPE_STOP);
|
|
|
|
/* verify that NPE Stop was successful */
|
|
if (! ixNpeDlNpeMgrBitsSetCheck (npeBaseAddress, IX_NPEDL_REG_OFFSET_EXCTL,
|
|
IX_NPEDL_EXCTL_STATUS_STOP))
|
|
{
|
|
IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrNpeStop: "
|
|
"failed to stop NPE execution\n");
|
|
status = IX_FAIL;
|
|
}
|
|
|
|
ixNpeDlNpeMgrStats.npeStops++;
|
|
|
|
IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
|
|
"Exiting ixNpeDlNpeMgrNpeStop : status = %d\n", status);
|
|
return status;
|
|
}
|
|
|
|
|
|
/*
|
|
* Function definition: ixNpeDlNpeMgrBitsSetCheck
|
|
*/
|
|
PRIVATE BOOL
|
|
ixNpeDlNpeMgrBitsSetCheck (
|
|
UINT32 npeBaseAddress,
|
|
UINT32 regOffset,
|
|
UINT32 expectedBitsSet)
|
|
{
|
|
UINT32 regVal;
|
|
IX_NPEDL_REG_READ (npeBaseAddress, regOffset, ®Val);
|
|
|
|
return expectedBitsSet == (expectedBitsSet & regVal);
|
|
}
|
|
|
|
|
|
/*
|
|
* Function definition: ixNpeDlNpeMgrStatsShow
|
|
*/
|
|
void
|
|
ixNpeDlNpeMgrStatsShow (void)
|
|
{
|
|
ixOsalLog (IX_OSAL_LOG_LVL_USER,
|
|
IX_OSAL_LOG_DEV_STDOUT,
|
|
"\nixNpeDlNpeMgrStatsShow:\n"
|
|
"\tInstruction Blocks loaded: %u\n"
|
|
"\tData Blocks loaded: %u\n"
|
|
"\tState Information Blocks loaded: %u\n"
|
|
"\tCritical NPE errors: %u\n"
|
|
"\tCritical Microcode errors: %u\n",
|
|
ixNpeDlNpeMgrStats.instructionBlocksLoaded,
|
|
ixNpeDlNpeMgrStats.dataBlocksLoaded,
|
|
ixNpeDlNpeMgrStats.stateInfoBlocksLoaded,
|
|
ixNpeDlNpeMgrStats.criticalNpeErrors,
|
|
ixNpeDlNpeMgrStats.criticalMicrocodeErrors,
|
|
0);
|
|
|
|
ixOsalLog (IX_OSAL_LOG_LVL_USER,
|
|
IX_OSAL_LOG_DEV_STDOUT,
|
|
"\tSuccessful NPE Starts: %u\n"
|
|
"\tSuccessful NPE Stops: %u\n"
|
|
"\tSuccessful NPE Resets: %u\n\n",
|
|
ixNpeDlNpeMgrStats.npeStarts,
|
|
ixNpeDlNpeMgrStats.npeStops,
|
|
ixNpeDlNpeMgrStats.npeResets,
|
|
0,0,0);
|
|
|
|
ixNpeDlNpeMgrUtilsStatsShow ();
|
|
}
|
|
|
|
|
|
/*
|
|
* Function definition: ixNpeDlNpeMgrStatsReset
|
|
*/
|
|
void
|
|
ixNpeDlNpeMgrStatsReset (void)
|
|
{
|
|
ixNpeDlNpeMgrStats.instructionBlocksLoaded = 0;
|
|
ixNpeDlNpeMgrStats.dataBlocksLoaded = 0;
|
|
ixNpeDlNpeMgrStats.stateInfoBlocksLoaded = 0;
|
|
ixNpeDlNpeMgrStats.criticalNpeErrors = 0;
|
|
ixNpeDlNpeMgrStats.criticalMicrocodeErrors = 0;
|
|
ixNpeDlNpeMgrStats.npeStarts = 0;
|
|
ixNpeDlNpeMgrStats.npeStops = 0;
|
|
ixNpeDlNpeMgrStats.npeResets = 0;
|
|
|
|
ixNpeDlNpeMgrUtilsStatsReset ();
|
|
}
|