/** * @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 * SPDX-License-Identifier: BSD-3-Clause * @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 (); }