1 /**
2  * @file IxNpeDlNpeMgr.c
3  *
4  * @author Intel Corporation
5  * @date 09 January 2002
6  *
7  * @brief This file contains the implementation of the private API for the
8  *        IXP425 NPE Downloader NpeMgr module
9  *
10  *
11  * @par
12  * IXP400 SW Release version 2.0
13  *
14  * -- Copyright Notice --
15  *
16  * @par
17  * Copyright 2001-2005, Intel Corporation.
18  * All rights reserved.
19  *
20  * @par
21  * Redistribution and use in source and binary forms, with or without
22  * modification, are permitted provided that the following conditions
23  * are met:
24  * 1. Redistributions of source code must retain the above copyright
25  *    notice, this list of conditions and the following disclaimer.
26  * 2. Redistributions in binary form must reproduce the above copyright
27  *    notice, this list of conditions and the following disclaimer in the
28  *    documentation and/or other materials provided with the distribution.
29  * 3. Neither the name of the Intel Corporation nor the names of its contributors
30  *    may be used to endorse or promote products derived from this software
31  *    without specific prior written permission.
32  *
33  * @par
34  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
35  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
38  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
39  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
40  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
43  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44  * SUCH DAMAGE.
45  *
46  * @par
47  * -- End of Copyright Notice --
48 */
49 
50 
51 /*
52  * Put the user defined include files required.
53  */
54 
55 
56 /*
57  * Put the user defined include files required.
58  */
59 #include "IxOsal.h"
60 #include "IxNpeDl.h"
61 #include "IxNpeDlNpeMgr_p.h"
62 #include "IxNpeDlNpeMgrUtils_p.h"
63 #include "IxNpeDlNpeMgrEcRegisters_p.h"
64 #include "IxNpeDlMacros_p.h"
65 #include "IxFeatureCtrl.h"
66 
67 /*
68  * #defines and macros used in this file.
69  */
70 #define IX_NPEDL_BYTES_PER_WORD                   4
71 
72 /* used to read download map from version in microcode image */
73 #define IX_NPEDL_BLOCK_TYPE_INSTRUCTION           0x00000000
74 #define IX_NPEDL_BLOCK_TYPE_DATA                  0x00000001
75 #define IX_NPEDL_BLOCK_TYPE_STATE                 0x00000002
76 #define IX_NPEDL_END_OF_DOWNLOAD_MAP              0x0000000F
77 
78 /*
79  * masks used to extract address info from State information context
80  * register addresses as read from microcode image
81  */
82 #define IX_NPEDL_MASK_STATE_ADDR_CTXT_REG         0x0000000F
83 #define IX_NPEDL_MASK_STATE_ADDR_CTXT_NUM         0x000000F0
84 
85 /* LSB offset of Context Number field in State-Info Context Address */
86 #define IX_NPEDL_OFFSET_STATE_ADDR_CTXT_NUM       4
87 
88 /* size (in words) of single State Information entry (ctxt reg address|data) */
89 #define IX_NPEDL_STATE_INFO_ENTRY_SIZE            2
90 
91 
92  #define IX_NPEDL_RESET_NPE_PARITY  0x0800
93  #define IX_NPEDL_PARITY_BIT_MASK   0x3F00FFFF
94  #define IX_NPEDL_CONFIG_CTRL_REG_MASK  0x3F3FFFFF
95 
96 
97 /*
98  * Typedefs whose scope is limited to this file.
99  */
100 
101 typedef struct
102 {
103     UINT32 type;
104     UINT32 offset;
105 } IxNpeDlNpeMgrDownloadMapBlockEntry;
106 
107 typedef union
108 {
109     IxNpeDlNpeMgrDownloadMapBlockEntry block;
110     UINT32 eodmMarker;
111 } IxNpeDlNpeMgrDownloadMapEntry;
112 
113 typedef struct
114 {
115     /* 1st entry in the download map (there may be more than one) */
116     IxNpeDlNpeMgrDownloadMapEntry entry[1];
117 } IxNpeDlNpeMgrDownloadMap;
118 
119 
120 /* used to access an instruction or data block in a microcode image */
121 typedef struct
122 {
123     UINT32 npeMemAddress;
124     UINT32 size;
125     UINT32 data[1];
126 } IxNpeDlNpeMgrCodeBlock;
127 
128 /* used to access each Context Reg entry state-information block */
129 typedef struct
130 {
131     UINT32 addressInfo;
132     UINT32 value;
133 } IxNpeDlNpeMgrStateInfoCtxtRegEntry;
134 
135 /* used to access a state-information block in a microcode image */
136 typedef struct
137 {
138     UINT32 size;
139     IxNpeDlNpeMgrStateInfoCtxtRegEntry ctxtRegEntry[1];
140 } IxNpeDlNpeMgrStateInfoBlock;
141 
142 /* used to store some useful NPE information for easy access */
143 typedef struct
144 {
145     UINT32 baseAddress;
146     UINT32 insMemSize;
147     UINT32 dataMemSize;
148 } IxNpeDlNpeInfo;
149 
150 /* used to distinguish instruction and data memory operations */
151 typedef enum
152 {
153   IX_NPEDL_MEM_TYPE_INSTRUCTION = 0,
154   IX_NPEDL_MEM_TYPE_DATA
155 } IxNpeDlNpeMemType;
156 
157 /* used to hold a reset value for a particular ECS register */
158 typedef struct
159 {
160     UINT32 regAddr;
161     UINT32 regResetVal;
162 } IxNpeDlEcsRegResetValue;
163 
164 /* prototype of function to write either Instruction or Data memory */
165 typedef IX_STATUS (*IxNpeDlNpeMgrMemWrite) (UINT32 npeBaseAddress,
166 					    UINT32 npeMemAddress,
167 					    UINT32 npeMemData,
168 					    BOOL verify);
169 
170 /* module statistics counters */
171 typedef struct
172 {
173     UINT32 instructionBlocksLoaded;
174     UINT32 dataBlocksLoaded;
175     UINT32 stateInfoBlocksLoaded;
176     UINT32 criticalNpeErrors;
177     UINT32 criticalMicrocodeErrors;
178     UINT32 npeStarts;
179     UINT32 npeStops;
180     UINT32 npeResets;
181 } IxNpeDlNpeMgrStats;
182 
183 
184 /*
185  * Variable declarations global to this file only.  Externs are followed by
186  * static variables.
187  */
188 static IxNpeDlNpeInfo ixNpeDlNpeInfo[] =
189 {
190     {
191 	0,
192 	IX_NPEDL_INS_MEMSIZE_WORDS_NPEA,
193 	IX_NPEDL_DATA_MEMSIZE_WORDS_NPEA
194     },
195     {
196 	0,
197 	IX_NPEDL_INS_MEMSIZE_WORDS_NPEB,
198 	IX_NPEDL_DATA_MEMSIZE_WORDS_NPEB
199     },
200     {
201 	0,
202 	IX_NPEDL_INS_MEMSIZE_WORDS_NPEC,
203 	IX_NPEDL_DATA_MEMSIZE_WORDS_NPEC
204     }
205 };
206 
207 /* contains Reset values for Context Store Registers  */
208 static UINT32 ixNpeDlCtxtRegResetValues[] =
209 {
210     IX_NPEDL_CTXT_REG_RESET_STEVT,
211     IX_NPEDL_CTXT_REG_RESET_STARTPC,
212     IX_NPEDL_CTXT_REG_RESET_REGMAP,
213     IX_NPEDL_CTXT_REG_RESET_CINDEX,
214 };
215 
216 /* contains Reset values for Context Store Registers  */
217 static IxNpeDlEcsRegResetValue ixNpeDlEcsRegResetValues[] =
218 {
219     {IX_NPEDL_ECS_BG_CTXT_REG_0,    IX_NPEDL_ECS_BG_CTXT_REG_0_RESET},
220     {IX_NPEDL_ECS_BG_CTXT_REG_1,    IX_NPEDL_ECS_BG_CTXT_REG_1_RESET},
221     {IX_NPEDL_ECS_BG_CTXT_REG_2,    IX_NPEDL_ECS_BG_CTXT_REG_2_RESET},
222     {IX_NPEDL_ECS_PRI_1_CTXT_REG_0, IX_NPEDL_ECS_PRI_1_CTXT_REG_0_RESET},
223     {IX_NPEDL_ECS_PRI_1_CTXT_REG_1, IX_NPEDL_ECS_PRI_1_CTXT_REG_1_RESET},
224     {IX_NPEDL_ECS_PRI_1_CTXT_REG_2, IX_NPEDL_ECS_PRI_1_CTXT_REG_2_RESET},
225     {IX_NPEDL_ECS_PRI_2_CTXT_REG_0, IX_NPEDL_ECS_PRI_2_CTXT_REG_0_RESET},
226     {IX_NPEDL_ECS_PRI_2_CTXT_REG_1, IX_NPEDL_ECS_PRI_2_CTXT_REG_1_RESET},
227     {IX_NPEDL_ECS_PRI_2_CTXT_REG_2, IX_NPEDL_ECS_PRI_2_CTXT_REG_2_RESET},
228     {IX_NPEDL_ECS_DBG_CTXT_REG_0,   IX_NPEDL_ECS_DBG_CTXT_REG_0_RESET},
229     {IX_NPEDL_ECS_DBG_CTXT_REG_1,   IX_NPEDL_ECS_DBG_CTXT_REG_1_RESET},
230     {IX_NPEDL_ECS_DBG_CTXT_REG_2,   IX_NPEDL_ECS_DBG_CTXT_REG_2_RESET},
231     {IX_NPEDL_ECS_INSTRUCT_REG,     IX_NPEDL_ECS_INSTRUCT_REG_RESET}
232 };
233 
234 static IxNpeDlNpeMgrStats ixNpeDlNpeMgrStats;
235 
236 /* Set when NPE register memory has been mapped */
237 static BOOL ixNpeDlMemInitialised = FALSE;
238 
239 
240 /*
241  * static function prototypes.
242  */
243 PRIVATE IX_STATUS
244 ixNpeDlNpeMgrMemLoad (IxNpeDlNpeId npeId, UINT32 npeBaseAddress,
245 		      IxNpeDlNpeMgrCodeBlock *codeBlockPtr,
246 		      BOOL verify, IxNpeDlNpeMemType npeMemType);
247 PRIVATE IX_STATUS
248 ixNpeDlNpeMgrStateInfoLoad (UINT32 npeBaseAddress,
249 			    IxNpeDlNpeMgrStateInfoBlock *codeBlockPtr,
250 			    BOOL verify);
251 PRIVATE BOOL
252 ixNpeDlNpeMgrBitsSetCheck (UINT32 npeBaseAddress, UINT32 regOffset,
253 			   UINT32 expectedBitsSet);
254 
255 PRIVATE UINT32
256 ixNpeDlNpeMgrBaseAddressGet (IxNpeDlNpeId npeId);
257 
258 /*
259  * Function definition: ixNpeDlNpeMgrBaseAddressGet
260  */
261 PRIVATE UINT32
ixNpeDlNpeMgrBaseAddressGet(IxNpeDlNpeId npeId)262 ixNpeDlNpeMgrBaseAddressGet (IxNpeDlNpeId npeId)
263 {
264     IX_OSAL_ASSERT (ixNpeDlMemInitialised);
265     return ixNpeDlNpeInfo[npeId].baseAddress;
266 }
267 
268 
269 /*
270  * Function definition: ixNpeDlNpeMgrInit
271  */
272 void
ixNpeDlNpeMgrInit(void)273 ixNpeDlNpeMgrInit (void)
274 {
275     /* Only map the memory once */
276     if (!ixNpeDlMemInitialised)
277     {
278 	UINT32 virtAddr;
279 
280 	/* map the register memory for NPE-A */
281 	virtAddr = (UINT32) IX_OSAL_MEM_MAP (IX_NPEDL_NPEBASEADDRESS_NPEA,
282 					    IX_OSAL_IXP400_NPEA_MAP_SIZE);
283 	IX_OSAL_ASSERT(virtAddr);
284 	ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEA].baseAddress = virtAddr;
285 
286 	/* map the register memory for NPE-B */
287 	virtAddr = (UINT32) IX_OSAL_MEM_MAP (IX_NPEDL_NPEBASEADDRESS_NPEB,
288 					    IX_OSAL_IXP400_NPEB_MAP_SIZE);
289 	IX_OSAL_ASSERT(virtAddr);
290 	ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEB].baseAddress = virtAddr;
291 
292 	/* map the register memory for NPE-C */
293 	virtAddr = (UINT32) IX_OSAL_MEM_MAP (IX_NPEDL_NPEBASEADDRESS_NPEC,
294 					    IX_OSAL_IXP400_NPEC_MAP_SIZE);
295 	IX_OSAL_ASSERT(virtAddr);
296 	ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEC].baseAddress = virtAddr;
297 
298 	ixNpeDlMemInitialised = TRUE;
299     }
300 }
301 
302 
303 /*
304  * Function definition: ixNpeDlNpeMgrUninit
305  */
306 IX_STATUS
ixNpeDlNpeMgrUninit(void)307 ixNpeDlNpeMgrUninit (void)
308 {
309     if (!ixNpeDlMemInitialised)
310     {
311 	return IX_FAIL;
312     }
313 
314     IX_OSAL_MEM_UNMAP (ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEA].baseAddress);
315     IX_OSAL_MEM_UNMAP (ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEB].baseAddress);
316     IX_OSAL_MEM_UNMAP (ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEC].baseAddress);
317 
318     ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEA].baseAddress = 0;
319     ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEB].baseAddress = 0;
320     ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEC].baseAddress = 0;
321 
322     ixNpeDlMemInitialised = FALSE;
323 
324     return IX_SUCCESS;
325 }
326 
327 /*
328  * Function definition: ixNpeDlNpeMgrImageLoad
329  */
330 IX_STATUS
ixNpeDlNpeMgrImageLoad(IxNpeDlNpeId npeId,UINT32 * imageCodePtr,BOOL verify)331 ixNpeDlNpeMgrImageLoad (
332     IxNpeDlNpeId npeId,
333     UINT32 *imageCodePtr,
334     BOOL verify)
335 {
336     UINT32 npeBaseAddress;
337     IxNpeDlNpeMgrDownloadMap *downloadMap;
338     UINT32 *blockPtr;
339     UINT32 mapIndex = 0;
340     IX_STATUS status = IX_SUCCESS;
341 
342     IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
343 		     "Entering ixNpeDlNpeMgrImageLoad\n");
344 
345     /* get base memory address of NPE from npeId */
346     npeBaseAddress = ixNpeDlNpeMgrBaseAddressGet (npeId);
347 
348     /* check execution status of NPE to verify NPE Stop was successful */
349     if (!ixNpeDlNpeMgrBitsSetCheck (npeBaseAddress, IX_NPEDL_REG_OFFSET_EXCTL,
350 				    IX_NPEDL_EXCTL_STATUS_STOP))
351     {
352 	IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrImageDownload - "
353 			       "NPE was not stopped before download\n");
354 	status = IX_FAIL;
355     }
356     else
357     {
358 	/*
359 	 * Read Download Map, checking each block type and calling
360 	 * appropriate function to perform download
361 	 */
362 	downloadMap = (IxNpeDlNpeMgrDownloadMap *) imageCodePtr;
363 	while ((downloadMap->entry[mapIndex].eodmMarker !=
364 		IX_NPEDL_END_OF_DOWNLOAD_MAP)
365 	       && (status == IX_SUCCESS))
366 	{
367 	    /* calculate pointer to block to be downloaded */
368 	    blockPtr = imageCodePtr +
369 		downloadMap->entry[mapIndex].block.offset;
370 
371 	    switch (downloadMap->entry[mapIndex].block.type)
372 	    {
373 	    case IX_NPEDL_BLOCK_TYPE_INSTRUCTION:
374 		status = ixNpeDlNpeMgrMemLoad (npeId, npeBaseAddress,
375 					     (IxNpeDlNpeMgrCodeBlock *)blockPtr,
376 					       verify,
377 					       IX_NPEDL_MEM_TYPE_INSTRUCTION);
378 		break;
379 	    case IX_NPEDL_BLOCK_TYPE_DATA:
380 		status = ixNpeDlNpeMgrMemLoad (npeId, npeBaseAddress,
381                                              (IxNpeDlNpeMgrCodeBlock *)blockPtr,
382 					       verify, IX_NPEDL_MEM_TYPE_DATA);
383 		break;
384 	    case IX_NPEDL_BLOCK_TYPE_STATE:
385 		status = ixNpeDlNpeMgrStateInfoLoad (npeBaseAddress,
386 				       (IxNpeDlNpeMgrStateInfoBlock *) blockPtr,
387 						     verify);
388 		break;
389 	    default:
390 		IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrImageLoad: "
391 				       "unknown block type in download map\n");
392 		status = IX_NPEDL_CRITICAL_MICROCODE_ERR;
393 		ixNpeDlNpeMgrStats.criticalMicrocodeErrors++;
394 		break;
395 	    }
396 	    mapIndex++;
397 	}/* loop: for each entry in download map, while status == SUCCESS */
398     }/* condition: NPE stopped before attempting download */
399 
400     IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
401 		     "Exiting ixNpeDlNpeMgrImageLoad : status = %d\n",
402 		     status);
403     return status;
404 }
405 
406 
407 /*
408  * Function definition: ixNpeDlNpeMgrMemLoad
409  */
410 PRIVATE IX_STATUS
ixNpeDlNpeMgrMemLoad(IxNpeDlNpeId npeId,UINT32 npeBaseAddress,IxNpeDlNpeMgrCodeBlock * blockPtr,BOOL verify,IxNpeDlNpeMemType npeMemType)411 ixNpeDlNpeMgrMemLoad (
412     IxNpeDlNpeId npeId,
413     UINT32 npeBaseAddress,
414     IxNpeDlNpeMgrCodeBlock *blockPtr,
415     BOOL verify,
416     IxNpeDlNpeMemType npeMemType)
417 {
418     UINT32 npeMemAddress;
419     UINT32 blockSize;
420     UINT32 memSize = 0;
421     IxNpeDlNpeMgrMemWrite memWriteFunc = NULL;
422     UINT32 localIndex = 0;
423     IX_STATUS status = IX_SUCCESS;
424 
425     IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
426 		     "Entering ixNpeDlNpeMgrMemLoad\n");
427 
428     /*
429      * select NPE EXCTL reg read/write commands depending on memory
430      * type (instruction/data) to be accessed
431      */
432     if (npeMemType == IX_NPEDL_MEM_TYPE_INSTRUCTION)
433     {
434 	memSize = ixNpeDlNpeInfo[npeId].insMemSize;
435 	memWriteFunc = (IxNpeDlNpeMgrMemWrite) ixNpeDlNpeMgrInsMemWrite;
436     }
437     else if (npeMemType == IX_NPEDL_MEM_TYPE_DATA)
438     {
439 	memSize = ixNpeDlNpeInfo[npeId].dataMemSize;
440 	memWriteFunc = (IxNpeDlNpeMgrMemWrite) ixNpeDlNpeMgrDataMemWrite;
441     }
442 
443     /*
444      * NPE memory is loaded contiguously from each block, so only address
445      * of 1st word in block is needed
446      */
447     npeMemAddress = blockPtr->npeMemAddress;
448     /* number of words of instruction/data microcode in block to download */
449     blockSize = blockPtr->size;
450     if ((npeMemAddress + blockSize) > memSize)
451     {
452 	IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrMemLoad: "
453 			       "Block size too big for NPE memory\n");
454 	status = IX_NPEDL_CRITICAL_MICROCODE_ERR;
455 	ixNpeDlNpeMgrStats.criticalMicrocodeErrors++;
456     }
457     else
458     {
459 	for (localIndex = 0; localIndex < blockSize; localIndex++)
460 	{
461 	    status = memWriteFunc (npeBaseAddress, npeMemAddress,
462 				   blockPtr->data[localIndex], verify);
463 
464 	    if (status != IX_SUCCESS)
465 	    {
466 		IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrMemLoad: "
467 				       "write to NPE memory failed\n");
468 		status = IX_NPEDL_CRITICAL_NPE_ERR;
469 		ixNpeDlNpeMgrStats.criticalNpeErrors++;
470 		break;   /* abort download */
471 	    }
472 	    /* increment target (word)address in NPE memory */
473 	    npeMemAddress++;
474 	}
475     }/* condition: block size will fit in NPE memory */
476 
477     if (status == IX_SUCCESS)
478     {
479 	if (npeMemType == IX_NPEDL_MEM_TYPE_INSTRUCTION)
480 	{
481 	    ixNpeDlNpeMgrStats.instructionBlocksLoaded++;
482 	}
483 	else if (npeMemType == IX_NPEDL_MEM_TYPE_DATA)
484 	{
485 	    ixNpeDlNpeMgrStats.dataBlocksLoaded++;
486 	}
487     }
488 
489     IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
490 		     "Exiting ixNpeDlNpeMgrMemLoad : status = %d\n", status);
491     return status;
492 }
493 
494 
495 /*
496  * Function definition: ixNpeDlNpeMgrStateInfoLoad
497  */
498 PRIVATE IX_STATUS
ixNpeDlNpeMgrStateInfoLoad(UINT32 npeBaseAddress,IxNpeDlNpeMgrStateInfoBlock * blockPtr,BOOL verify)499 ixNpeDlNpeMgrStateInfoLoad (
500     UINT32 npeBaseAddress,
501     IxNpeDlNpeMgrStateInfoBlock *blockPtr,
502     BOOL verify)
503 {
504     UINT32 blockSize;
505     UINT32 ctxtRegAddrInfo;
506     UINT32 ctxtRegVal;
507     IxNpeDlCtxtRegNum ctxtReg; /* identifies Context Store reg (0-3) */
508     UINT32 ctxtNum;            /* identifies Context number (0-16)   */
509     UINT32 i;
510     IX_STATUS status = IX_SUCCESS;
511 
512     IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
513 		     "Entering ixNpeDlNpeMgrStateInfoLoad\n");
514 
515     /* block size contains number of words of state-info in block */
516     blockSize = blockPtr->size;
517 
518     ixNpeDlNpeMgrDebugInstructionPreExec (npeBaseAddress);
519 
520     /* for each state-info context register entry in block */
521     for (i = 0; i < (blockSize/IX_NPEDL_STATE_INFO_ENTRY_SIZE); i++)
522     {
523 	/* each state-info entry is 2 words (address, value) in length */
524 	ctxtRegAddrInfo = (blockPtr->ctxtRegEntry[i]).addressInfo;
525 	ctxtRegVal      = (blockPtr->ctxtRegEntry[i]).value;
526 
527 	ctxtReg = (ctxtRegAddrInfo & IX_NPEDL_MASK_STATE_ADDR_CTXT_REG);
528 	ctxtNum = (ctxtRegAddrInfo & IX_NPEDL_MASK_STATE_ADDR_CTXT_NUM) >>
529 	    IX_NPEDL_OFFSET_STATE_ADDR_CTXT_NUM;
530 
531 	/* error-check Context Register No. and Context Number values  */
532 	/* NOTE that there is no STEVT register for Context 0 */
533 	if ((ctxtReg < 0) ||
534 	    (ctxtReg >= IX_NPEDL_CTXT_REG_MAX) ||
535 	    (ctxtNum > IX_NPEDL_CTXT_NUM_MAX) ||
536 	    ((ctxtNum == 0) && (ctxtReg == IX_NPEDL_CTXT_REG_STEVT)))
537 	{
538 	    IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrStateInfoLoad: "
539 				   "invalid Context Register Address\n");
540 	    status = IX_NPEDL_CRITICAL_MICROCODE_ERR;
541 	    ixNpeDlNpeMgrStats.criticalMicrocodeErrors++;
542 	    break;   /* abort download */
543 	}
544 
545 	status = ixNpeDlNpeMgrCtxtRegWrite (npeBaseAddress, ctxtNum, ctxtReg,
546 					    ctxtRegVal, verify);
547 	if (status != IX_SUCCESS)
548 	{
549 	    IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrStateInfoLoad: "
550 				   "write of state-info to NPE failed\n");
551 	    status = IX_NPEDL_CRITICAL_NPE_ERR;
552 	    ixNpeDlNpeMgrStats.criticalNpeErrors++;
553 	    break;   /* abort download */
554 	}
555     }/* loop: for each context reg entry in State Info block */
556 
557     ixNpeDlNpeMgrDebugInstructionPostExec (npeBaseAddress);
558 
559     if (status == IX_SUCCESS)
560     {
561 	ixNpeDlNpeMgrStats.stateInfoBlocksLoaded++;
562     }
563 
564     IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
565 		     "Exiting ixNpeDlNpeMgrStateInfoLoad : status = %d\n",
566 		     status);
567     return status;
568 }
569 
570 
571 /*
572  * Function definition: ixNpeDlNpeMgrNpeReset
573  */
574 IX_STATUS
ixNpeDlNpeMgrNpeReset(IxNpeDlNpeId npeId)575 ixNpeDlNpeMgrNpeReset (
576     IxNpeDlNpeId npeId)
577 {
578     UINT32 npeBaseAddress;
579     IxNpeDlCtxtRegNum ctxtReg; /* identifies Context Store reg (0-3) */
580     UINT32 ctxtNum;            /* identifies Context number (0-16)   */
581     UINT32 regAddr;
582     UINT32 regVal;
583     UINT32 localIndex;
584     UINT32 indexMax;
585     IX_STATUS status = IX_SUCCESS;
586     IxFeatureCtrlReg unitFuseReg;
587     UINT32 ixNpeConfigCtrlRegVal;
588 
589     IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
590 		     "Entering ixNpeDlNpeMgrNpeReset\n");
591 
592     /* get base memory address of NPE from npeId */
593     npeBaseAddress = ixNpeDlNpeMgrBaseAddressGet (npeId);
594 
595     /* pre-store the NPE Config Control Register Value */
596     IX_NPEDL_REG_READ (npeBaseAddress, IX_NPEDL_REG_OFFSET_CTL, &ixNpeConfigCtrlRegVal);
597 
598     ixNpeConfigCtrlRegVal |= 0x3F000000;
599 
600     /* disable the parity interrupt */
601     IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_CTL, (ixNpeConfigCtrlRegVal & IX_NPEDL_PARITY_BIT_MASK));
602 
603     ixNpeDlNpeMgrDebugInstructionPreExec (npeBaseAddress);
604 
605     /*
606      * clear the FIFOs
607      */
608     while (ixNpeDlNpeMgrBitsSetCheck (npeBaseAddress,
609 				      IX_NPEDL_REG_OFFSET_WFIFO,
610 				      IX_NPEDL_MASK_WFIFO_VALID))
611     {
612 	/* read from the Watch-point FIFO until empty */
613 	IX_NPEDL_REG_READ (npeBaseAddress, IX_NPEDL_REG_OFFSET_WFIFO,
614 			   &regVal);
615     }
616 
617     while (ixNpeDlNpeMgrBitsSetCheck (npeBaseAddress,
618 					  IX_NPEDL_REG_OFFSET_STAT,
619 				      IX_NPEDL_MASK_STAT_OFNE))
620     {
621 	/* read from the outFIFO until empty */
622 	IX_NPEDL_REG_READ (npeBaseAddress, IX_NPEDL_REG_OFFSET_FIFO,
623 			   &regVal);
624     }
625 
626     while (ixNpeDlNpeMgrBitsSetCheck (npeBaseAddress,
627 				      IX_NPEDL_REG_OFFSET_STAT,
628 				      IX_NPEDL_MASK_STAT_IFNE))
629     {
630 	/*
631 	 * step execution of the NPE intruction to read inFIFO using
632 	 * the Debug Executing Context stack
633 	 */
634 	status = ixNpeDlNpeMgrDebugInstructionExec (npeBaseAddress,
635 					   IX_NPEDL_INSTR_RD_FIFO, 0, 0);
636 
637     if (IX_SUCCESS != status)
638     {
639         return status;
640     }
641 
642     }
643 
644     /*
645      * Reset the mailbox reg
646      */
647     /* ...from XScale side */
648     IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_MBST,
649 			IX_NPEDL_REG_RESET_MBST);
650     /* ...from NPE side */
651     status = ixNpeDlNpeMgrDebugInstructionExec (npeBaseAddress,
652 				       IX_NPEDL_INSTR_RESET_MBOX, 0, 0);
653 
654     if (IX_SUCCESS != status)
655     {
656         return status;
657     }
658 
659     /*
660      *   Reset the physical registers in the NPE register file:
661      *   Note: no need to save/restore REGMAP for Context 0 here
662      *   since all Context Store regs are reset in subsequent code
663      */
664     for (regAddr = 0;
665 	 (regAddr < IX_NPEDL_TOTAL_NUM_PHYS_REG) && (status != IX_FAIL);
666 	 regAddr++)
667     {
668 	/* for each physical register in the NPE reg file, write 0 : */
669 	status = ixNpeDlNpeMgrPhysicalRegWrite (npeBaseAddress, regAddr,
670 						0, TRUE);
671 	if (status != IX_SUCCESS)
672 	{
673 	    return status;  /* abort reset */
674 	}
675     }
676 
677 
678     /*
679      * Reset the context store:
680      */
681     for (ctxtNum = IX_NPEDL_CTXT_NUM_MIN;
682 	 ctxtNum <= IX_NPEDL_CTXT_NUM_MAX; ctxtNum++)
683     {
684 	/* set each context's Context Store registers to reset values: */
685 	for (ctxtReg = 0; ctxtReg < IX_NPEDL_CTXT_REG_MAX; ctxtReg++)
686 	{
687 	    /* NOTE that there is no STEVT register for Context 0 */
688 	    if (!((ctxtNum == 0) && (ctxtReg == IX_NPEDL_CTXT_REG_STEVT)))
689 	    {
690 		regVal = ixNpeDlCtxtRegResetValues[ctxtReg];
691 		status = ixNpeDlNpeMgrCtxtRegWrite (npeBaseAddress, ctxtNum,
692 						    ctxtReg, regVal, TRUE);
693 		if (status != IX_SUCCESS)
694 		{
695 		    return status;  /* abort reset */
696 		}
697 	    }
698 	}
699     }
700 
701     ixNpeDlNpeMgrDebugInstructionPostExec (npeBaseAddress);
702 
703     /* write Reset values to Execution Context Stack registers */
704     indexMax = sizeof (ixNpeDlEcsRegResetValues) /
705 	sizeof (IxNpeDlEcsRegResetValue);
706     for (localIndex = 0; localIndex < indexMax; localIndex++)
707     {
708 	regAddr = ixNpeDlEcsRegResetValues[localIndex].regAddr;
709 	regVal = ixNpeDlEcsRegResetValues[localIndex].regResetVal;
710 	ixNpeDlNpeMgrExecAccRegWrite (npeBaseAddress, regAddr, regVal);
711     }
712 
713     /* clear the profile counter */
714     ixNpeDlNpeMgrCommandIssue (npeBaseAddress,
715 			       IX_NPEDL_EXCTL_CMD_CLR_PROFILE_CNT);
716 
717     /* clear registers EXCT, AP0, AP1, AP2 and AP3 */
718     for (regAddr = IX_NPEDL_REG_OFFSET_EXCT;
719 	     regAddr <= IX_NPEDL_REG_OFFSET_AP3;
720 	 regAddr += IX_NPEDL_BYTES_PER_WORD)
721     {
722 	IX_NPEDL_REG_WRITE (npeBaseAddress, regAddr, 0);
723     }
724 
725     /* Reset the Watch-count register */
726     IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_WC, 0);
727 
728     /*
729      * WR IXA00055043 - Remove IMEM Parity Introduced by NPE Reset Operation
730      */
731 
732     /*
733      * Call the feature control API to fused out and reset the NPE and its
734      * coprocessor - to reset internal states and remove parity error
735      */
736     unitFuseReg = ixFeatureCtrlRead ();
737     unitFuseReg |= (IX_NPEDL_RESET_NPE_PARITY << npeId);
738     ixFeatureCtrlWrite (unitFuseReg);
739 
740     /* call the feature control API to un-fused and un-reset the NPE & COP */
741     unitFuseReg &= (~(IX_NPEDL_RESET_NPE_PARITY << npeId));
742     ixFeatureCtrlWrite (unitFuseReg);
743 
744     /*
745      * Call NpeMgr function to stop the NPE again after the Feature Control
746      * has unfused and Un-Reset the NPE and its associated Coprocessors
747      */
748     status = ixNpeDlNpeMgrNpeStop (npeId);
749 
750     /* restore NPE configuration bus Control Register - Parity Settings  */
751     IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_CTL,
752         (ixNpeConfigCtrlRegVal & IX_NPEDL_CONFIG_CTRL_REG_MASK));
753 
754     ixNpeDlNpeMgrStats.npeResets++;
755 
756     IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
757 		     "Exiting ixNpeDlNpeMgrNpeReset : status = %d\n", status);
758     return status;
759 }
760 
761 
762 /*
763  * Function definition: ixNpeDlNpeMgrNpeStart
764  */
765 IX_STATUS
ixNpeDlNpeMgrNpeStart(IxNpeDlNpeId npeId)766 ixNpeDlNpeMgrNpeStart (
767     IxNpeDlNpeId npeId)
768 {
769     UINT32    npeBaseAddress;
770     UINT32    ecsRegVal;
771     BOOL      npeRunning;
772     IX_STATUS status = IX_SUCCESS;
773 
774     IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
775 		     "Entering ixNpeDlNpeMgrNpeStart\n");
776 
777     /* get base memory address of NPE from npeId */
778     npeBaseAddress = ixNpeDlNpeMgrBaseAddressGet (npeId);
779 
780     /*
781      * ensure only Background Context Stack Level is Active by turning off
782      * the Active bit in each of the other Executing Context Stack levels
783      */
784     ecsRegVal = ixNpeDlNpeMgrExecAccRegRead (npeBaseAddress,
785 					     IX_NPEDL_ECS_PRI_1_CTXT_REG_0);
786     ecsRegVal &= ~IX_NPEDL_MASK_ECS_REG_0_ACTIVE;
787     ixNpeDlNpeMgrExecAccRegWrite (npeBaseAddress, IX_NPEDL_ECS_PRI_1_CTXT_REG_0,
788 				  ecsRegVal);
789 
790     ecsRegVal = ixNpeDlNpeMgrExecAccRegRead (npeBaseAddress,
791 					     IX_NPEDL_ECS_PRI_2_CTXT_REG_0);
792     ecsRegVal &= ~IX_NPEDL_MASK_ECS_REG_0_ACTIVE;
793     ixNpeDlNpeMgrExecAccRegWrite (npeBaseAddress, IX_NPEDL_ECS_PRI_2_CTXT_REG_0,
794 				  ecsRegVal);
795 
796     ecsRegVal = ixNpeDlNpeMgrExecAccRegRead (npeBaseAddress,
797 					     IX_NPEDL_ECS_DBG_CTXT_REG_0);
798     ecsRegVal &= ~IX_NPEDL_MASK_ECS_REG_0_ACTIVE;
799     ixNpeDlNpeMgrExecAccRegWrite (npeBaseAddress, IX_NPEDL_ECS_DBG_CTXT_REG_0,
800 				  ecsRegVal);
801 
802     /* clear the pipeline */
803     ixNpeDlNpeMgrCommandIssue (npeBaseAddress, IX_NPEDL_EXCTL_CMD_NPE_CLR_PIPE);
804 
805     /* start NPE execution by issuing command through EXCTL register on NPE */
806     ixNpeDlNpeMgrCommandIssue (npeBaseAddress, IX_NPEDL_EXCTL_CMD_NPE_START);
807 
808     /*
809      * check execution status of NPE to verify NPE Start operation was
810      * successful
811      */
812     npeRunning = ixNpeDlNpeMgrBitsSetCheck (npeBaseAddress,
813 					    IX_NPEDL_REG_OFFSET_EXCTL,
814 					    IX_NPEDL_EXCTL_STATUS_RUN);
815     if (npeRunning)
816     {
817 	ixNpeDlNpeMgrStats.npeStarts++;
818     }
819     else
820     {
821 	IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrNpeStart: "
822 			       "failed to start NPE execution\n");
823 	status = IX_FAIL;
824     }
825 
826 
827     IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
828 		     "Exiting ixNpeDlNpeMgrNpeStart : status = %d\n", status);
829     return status;
830 }
831 
832 
833 /*
834  * Function definition: ixNpeDlNpeMgrNpeStop
835  */
836 IX_STATUS
ixNpeDlNpeMgrNpeStop(IxNpeDlNpeId npeId)837 ixNpeDlNpeMgrNpeStop (
838     IxNpeDlNpeId npeId)
839 {
840     UINT32    npeBaseAddress;
841     IX_STATUS status = IX_SUCCESS;
842 
843     IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
844 		     "Entering ixNpeDlNpeMgrNpeStop\n");
845 
846     /* get base memory address of NPE from npeId */
847     npeBaseAddress = ixNpeDlNpeMgrBaseAddressGet (npeId);
848 
849     /* stop NPE execution by issuing command through EXCTL register on NPE */
850     ixNpeDlNpeMgrCommandIssue (npeBaseAddress, IX_NPEDL_EXCTL_CMD_NPE_STOP);
851 
852     /* verify that NPE Stop was successful */
853     if (! ixNpeDlNpeMgrBitsSetCheck (npeBaseAddress, IX_NPEDL_REG_OFFSET_EXCTL,
854 				     IX_NPEDL_EXCTL_STATUS_STOP))
855     {
856 	IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrNpeStop: "
857 			       "failed to stop NPE execution\n");
858 	status = IX_FAIL;
859     }
860 
861     ixNpeDlNpeMgrStats.npeStops++;
862 
863     IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
864 		     "Exiting ixNpeDlNpeMgrNpeStop : status = %d\n", status);
865     return status;
866 }
867 
868 
869 /*
870  * Function definition: ixNpeDlNpeMgrBitsSetCheck
871  */
872 PRIVATE BOOL
ixNpeDlNpeMgrBitsSetCheck(UINT32 npeBaseAddress,UINT32 regOffset,UINT32 expectedBitsSet)873 ixNpeDlNpeMgrBitsSetCheck (
874     UINT32 npeBaseAddress,
875     UINT32 regOffset,
876     UINT32 expectedBitsSet)
877 {
878     UINT32 regVal;
879     IX_NPEDL_REG_READ (npeBaseAddress, regOffset, &regVal);
880 
881     return expectedBitsSet == (expectedBitsSet & regVal);
882 }
883 
884 
885 /*
886  * Function definition: ixNpeDlNpeMgrStatsShow
887  */
888 void
ixNpeDlNpeMgrStatsShow(void)889 ixNpeDlNpeMgrStatsShow (void)
890 {
891     ixOsalLog (IX_OSAL_LOG_LVL_USER,
892                IX_OSAL_LOG_DEV_STDOUT,
893                "\nixNpeDlNpeMgrStatsShow:\n"
894                "\tInstruction Blocks loaded: %u\n"
895                "\tData Blocks loaded: %u\n"
896                "\tState Information Blocks loaded: %u\n"
897                "\tCritical NPE errors: %u\n"
898                "\tCritical Microcode errors: %u\n",
899                ixNpeDlNpeMgrStats.instructionBlocksLoaded,
900                ixNpeDlNpeMgrStats.dataBlocksLoaded,
901                ixNpeDlNpeMgrStats.stateInfoBlocksLoaded,
902                ixNpeDlNpeMgrStats.criticalNpeErrors,
903                ixNpeDlNpeMgrStats.criticalMicrocodeErrors,
904                0);
905 
906     ixOsalLog (IX_OSAL_LOG_LVL_USER,
907                IX_OSAL_LOG_DEV_STDOUT,
908                "\tSuccessful NPE Starts: %u\n"
909                "\tSuccessful NPE Stops: %u\n"
910                "\tSuccessful NPE Resets: %u\n\n",
911                ixNpeDlNpeMgrStats.npeStarts,
912                ixNpeDlNpeMgrStats.npeStops,
913                ixNpeDlNpeMgrStats.npeResets,
914                0,0,0);
915 
916     ixNpeDlNpeMgrUtilsStatsShow ();
917 }
918 
919 
920 /*
921  * Function definition: ixNpeDlNpeMgrStatsReset
922  */
923 void
ixNpeDlNpeMgrStatsReset(void)924 ixNpeDlNpeMgrStatsReset (void)
925 {
926     ixNpeDlNpeMgrStats.instructionBlocksLoaded = 0;
927     ixNpeDlNpeMgrStats.dataBlocksLoaded = 0;
928     ixNpeDlNpeMgrStats.stateInfoBlocksLoaded = 0;
929     ixNpeDlNpeMgrStats.criticalNpeErrors = 0;
930     ixNpeDlNpeMgrStats.criticalMicrocodeErrors = 0;
931     ixNpeDlNpeMgrStats.npeStarts = 0;
932     ixNpeDlNpeMgrStats.npeStops = 0;
933     ixNpeDlNpeMgrStats.npeResets = 0;
934 
935     ixNpeDlNpeMgrUtilsStatsReset ();
936 }
937