u-boot/arch/arm/cpu/ixp/npe/IxNpeDlNpeMgr.c

932 lines
27 KiB
C
Raw Normal View History

/**
* @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,
&regVal);
}
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,
&regVal);
}
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, &regVal);
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 ();
}