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