blob: eaa9a21ad738c7972cccb1c23d2bcbd24d24fc47 [file] [log] [blame]
Wolfgang Denk4646d2a2006-05-30 15:56:48 +02001/**
2 * @file IxNpeMhConfig.c
3 *
4 * @author Intel Corporation
5 * @date 18 Jan 2002
6 *
7 * @brief This file contains the implementation of the private API for the
8 * Configuration 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
Wolfgang Denkc57eadc2013-07-28 22:12:47 +020021 * SPDX-License-Identifier: BSD-3-Clause
Wolfgang Denk4646d2a2006-05-30 15:56:48 +020022 * @par
23 * -- End of Copyright Notice --
24*/
25
26/*
27 * Put the system defined include files required.
28 */
29
30
31/*
32 * Put the user defined include files required.
33 */
34
35#include "IxOsal.h"
36
37#include "IxNpeMhMacros_p.h"
38
39#include "IxNpeMhConfig_p.h"
40
41/*
42 * #defines and macros used in this file.
43 */
44#define IX_NPE_MH_MAX_NUM_OF_RETRIES 1000000 /**< Maximum number of
45 * retries before
46 * timeout
47 */
48
49/*
50 * Typedefs whose scope is limited to this file.
51 */
52
53/**
54 * @struct IxNpeMhConfigStats
55 *
56 * @brief This structure is used to maintain statistics for the
57 * Configuration module.
58 */
59
60typedef struct
61{
62 UINT32 outFifoReads; /**< outFifo reads */
63 UINT32 inFifoWrites; /**< inFifo writes */
64 UINT32 maxInFifoFullRetries; /**< max retries if inFIFO full */
65 UINT32 maxOutFifoEmptyRetries; /**< max retries if outFIFO empty */
66} IxNpeMhConfigStats;
67
68/*
69 * Variable declarations global to this file only. Externs are followed by
70 * static variables.
71 */
72
73IxNpeMhConfigNpeInfo ixNpeMhConfigNpeInfo[IX_NPEMH_NUM_NPES] =
74{
75 {
76 0,
77 IX_NPEMH_NPEA_INT,
78 0,
79 0,
80 0,
81 0,
82 0,
83 NULL,
York Sun4a598092013-04-01 11:29:11 -070084 false
Wolfgang Denk4646d2a2006-05-30 15:56:48 +020085 },
86 {
87 0,
88 IX_NPEMH_NPEB_INT,
89 0,
90 0,
91 0,
92 0,
93 0,
94 NULL,
York Sun4a598092013-04-01 11:29:11 -070095 false
Wolfgang Denk4646d2a2006-05-30 15:56:48 +020096 },
97 {
98 0,
99 IX_NPEMH_NPEC_INT,
100 0,
101 0,
102 0,
103 0,
104 0,
105 NULL,
York Sun4a598092013-04-01 11:29:11 -0700106 false
Wolfgang Denk4646d2a2006-05-30 15:56:48 +0200107 }
108};
109
110PRIVATE IxNpeMhConfigStats ixNpeMhConfigStats[IX_NPEMH_NUM_NPES];
111
112/*
113 * Extern function prototypes.
114 */
115
116/*
117 * Static function prototypes.
118 */
119PRIVATE
120void ixNpeMhConfigIsr (void *parameter);
121
122/*
123 * Function definition: ixNpeMhConfigIsr
124 */
125
126PRIVATE
127void ixNpeMhConfigIsr (void *parameter)
128{
129 IxNpeMhNpeId npeId = (IxNpeMhNpeId)parameter;
130 UINT32 ofint;
131 volatile UINT32 *statusReg =
132 (UINT32 *)ixNpeMhConfigNpeInfo[npeId].statusRegister;
133
134 IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
135 "ixNpeMhConfigIsr\n");
136
137 /* get the OFINT (OutFifo interrupt) bit of the status register */
138 IX_NPEMH_REGISTER_READ_BITS (statusReg, &ofint, IX_NPEMH_NPE_STAT_OFINT);
139
140 /* if the OFINT status bit is set */
141 if (ofint)
142 {
143 /* if there is an ISR registered for this NPE */
144 if (ixNpeMhConfigNpeInfo[npeId].isr != NULL)
145 {
146 /* invoke the ISR routine */
147 ixNpeMhConfigNpeInfo[npeId].isr (npeId);
148 }
149 else
150 {
151 /* if we don't service the interrupt the NPE will continue */
152 /* to trigger the interrupt indefinitely */
153 IX_NPEMH_ERROR_REPORT ("No ISR registered to service "
154 "interrupt\n");
155 }
156 }
157
158 IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
159 "ixNpeMhConfigIsr\n");
160}
161
162/*
163 * Function definition: ixNpeMhConfigInitialize
164 */
165
166void ixNpeMhConfigInitialize (
167 IxNpeMhNpeInterrupts npeInterrupts)
168{
169 IxNpeMhNpeId npeId;
170 UINT32 virtualAddr[IX_NPEMH_NUM_NPES];
171
172 IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
173 "ixNpeMhConfigInitialize\n");
174
175 /* Request a mapping for the NPE-A config register address space */
176 virtualAddr[IX_NPEMH_NPEID_NPEA] =
177 (UINT32) IX_OSAL_MEM_MAP (IX_NPEMH_NPEA_BASE,
178 IX_OSAL_IXP400_NPEA_MAP_SIZE);
179 IX_OSAL_ASSERT (virtualAddr[IX_NPEMH_NPEID_NPEA]);
180
181 /* Request a mapping for the NPE-B config register address space */
182 virtualAddr[IX_NPEMH_NPEID_NPEB] =
183 (UINT32) IX_OSAL_MEM_MAP (IX_NPEMH_NPEB_BASE,
184 IX_OSAL_IXP400_NPEB_MAP_SIZE);
185 IX_OSAL_ASSERT (virtualAddr[IX_NPEMH_NPEID_NPEB]);
186
187 /* Request a mapping for the NPE-C config register address space */
188 virtualAddr[IX_NPEMH_NPEID_NPEC] =
189 (UINT32) IX_OSAL_MEM_MAP (IX_NPEMH_NPEC_BASE,
190 IX_OSAL_IXP400_NPEC_MAP_SIZE);
191 IX_OSAL_ASSERT (virtualAddr[IX_NPEMH_NPEID_NPEC]);
192
193 /* for each NPE ... */
194 for (npeId = 0; npeId < IX_NPEMH_NUM_NPES; npeId++)
195 {
196 /* declare a convenience pointer */
197 IxNpeMhConfigNpeInfo *npeInfo = &ixNpeMhConfigNpeInfo[npeId];
198
199 /* store the virtual addresses of the NPE registers for later use */
200 npeInfo->virtualRegisterBase = virtualAddr[npeId];
201 npeInfo->statusRegister = virtualAddr[npeId] + IX_NPEMH_NPESTAT_OFFSET;
202 npeInfo->controlRegister = virtualAddr[npeId] + IX_NPEMH_NPECTL_OFFSET;
203 npeInfo->inFifoRegister = virtualAddr[npeId] + IX_NPEMH_NPEFIFO_OFFSET;
204 npeInfo->outFifoRegister = virtualAddr[npeId] + IX_NPEMH_NPEFIFO_OFFSET;
205
206 /* for test purposes - to verify the register addresses */
207 IX_NPEMH_TRACE2 (IX_NPEMH_DEBUG, "NPE %d status register = "
208 "0x%08X\n", npeId, npeInfo->statusRegister);
209 IX_NPEMH_TRACE2 (IX_NPEMH_DEBUG, "NPE %d control register = "
210 "0x%08X\n", npeId, npeInfo->controlRegister);
211 IX_NPEMH_TRACE2 (IX_NPEMH_DEBUG, "NPE %d inFifo register = "
212 "0x%08X\n", npeId, npeInfo->inFifoRegister);
213 IX_NPEMH_TRACE2 (IX_NPEMH_DEBUG, "NPE %d outFifo register = "
214 "0x%08X\n", npeId, npeInfo->outFifoRegister);
215
216 /* connect our ISR to the NPE interrupt */
217 (void) ixOsalIrqBind (
218 npeInfo->interruptId, ixNpeMhConfigIsr, (void *)npeId);
219
220 /* initialise a mutex for this NPE */
221 (void) ixOsalMutexInit (&npeInfo->mutex);
222
223 /* if we should service the NPE's "outFIFO not empty" interrupt */
224 if (npeInterrupts == IX_NPEMH_NPEINTERRUPTS_YES)
225 {
226 /* enable the NPE's "outFIFO not empty" interrupt */
227 ixNpeMhConfigNpeInterruptEnable (npeId);
228 }
229 else
230 {
231 /* disable the NPE's "outFIFO not empty" interrupt */
232 ixNpeMhConfigNpeInterruptDisable (npeId);
233 }
234 }
235
236 IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
237 "ixNpeMhConfigInitialize\n");
238}
239
240/*
241 * Function definition: ixNpeMhConfigUninit
242 */
243
244void ixNpeMhConfigUninit (void)
245{
246 IxNpeMhNpeId npeId;
247
248 IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
249 "ixNpeMhConfigUninit\n");
250
251 /* for each NPE ... */
252 for (npeId = 0; npeId < IX_NPEMH_NUM_NPES; npeId++)
253 {
254 /* declare a convenience pointer */
255 IxNpeMhConfigNpeInfo *npeInfo = &ixNpeMhConfigNpeInfo[npeId];
256
257 /* disconnect ISR */
258 ixOsalIrqUnbind(npeInfo->interruptId);
259
260 /* destroy mutex associated with this NPE */
261 ixOsalMutexDestroy(&npeInfo->mutex);
262
263 IX_OSAL_MEM_UNMAP (npeInfo->virtualRegisterBase);
264
265 npeInfo->virtualRegisterBase = 0;
266 npeInfo->statusRegister = 0;
267 npeInfo->controlRegister = 0;
268 npeInfo->inFifoRegister = 0;
269 npeInfo->outFifoRegister = 0;
270 }
271
272 IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
273 "ixNpeMhConfigUninit\n");
274}
275
276/*
277 * Function definition: ixNpeMhConfigIsrRegister
278 */
279
280void ixNpeMhConfigIsrRegister (
281 IxNpeMhNpeId npeId,
282 IxNpeMhConfigIsr isr)
283{
284 IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
285 "ixNpeMhConfigIsrRegister\n");
286
287 /* check if there is already an ISR registered for this NPE */
288 if (ixNpeMhConfigNpeInfo[npeId].isr != NULL)
289 {
290 IX_NPEMH_TRACE0 (IX_NPEMH_DEBUG, "Over-writing registered NPE ISR\n");
291 }
292
293 /* save the ISR routine with the NPE info */
294 ixNpeMhConfigNpeInfo[npeId].isr = isr;
295
296 IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
297 "ixNpeMhConfigIsrRegister\n");
298}
299
300/*
301 * Function definition: ixNpeMhConfigNpeInterruptEnable
302 */
303
304BOOL ixNpeMhConfigNpeInterruptEnable (
305 IxNpeMhNpeId npeId)
306{
307 UINT32 ofe;
308 volatile UINT32 *controlReg =
309 (UINT32 *)ixNpeMhConfigNpeInfo[npeId].controlRegister;
310
311 /* get the OFE (OutFifoEnable) bit of the control register */
312 IX_NPEMH_REGISTER_READ_BITS (controlReg, &ofe, IX_NPEMH_NPE_CTL_OFE);
313
314 /* if the interrupt is disabled then we must enable it */
315 if (!ofe)
316 {
317 /* set the OFE (OutFifoEnable) bit of the control register */
318 /* we must set the OFEWE (OutFifoEnableWriteEnable) at the same */
319 /* time for the write to have effect */
320 IX_NPEMH_REGISTER_WRITE_BITS (controlReg,
321 (IX_NPEMH_NPE_CTL_OFE |
322 IX_NPEMH_NPE_CTL_OFEWE),
323 (IX_NPEMH_NPE_CTL_OFE |
324 IX_NPEMH_NPE_CTL_OFEWE));
325 }
326
327 /* return the previous state of the interrupt */
328 return (ofe != 0);
329}
330
331/*
332 * Function definition: ixNpeMhConfigNpeInterruptDisable
333 */
334
335BOOL ixNpeMhConfigNpeInterruptDisable (
336 IxNpeMhNpeId npeId)
337{
338 UINT32 ofe;
339 volatile UINT32 *controlReg =
340 (UINT32 *)ixNpeMhConfigNpeInfo[npeId].controlRegister;
341
342 /* get the OFE (OutFifoEnable) bit of the control register */
343 IX_NPEMH_REGISTER_READ_BITS (controlReg, &ofe, IX_NPEMH_NPE_CTL_OFE);
344
345 /* if the interrupt is enabled then we must disable it */
346 if (ofe)
347 {
348 /* unset the OFE (OutFifoEnable) bit of the control register */
349 /* we must set the OFEWE (OutFifoEnableWriteEnable) at the same */
350 /* time for the write to have effect */
351 IX_NPEMH_REGISTER_WRITE_BITS (controlReg,
352 (0 |
353 IX_NPEMH_NPE_CTL_OFEWE),
354 (IX_NPEMH_NPE_CTL_OFE |
355 IX_NPEMH_NPE_CTL_OFEWE));
356 }
357
358 /* return the previous state of the interrupt */
359 return (ofe != 0);
360}
361
362/*
363 * Function definition: ixNpeMhConfigMessageIdGet
364 */
365
366IxNpeMhMessageId ixNpeMhConfigMessageIdGet (
367 IxNpeMhMessage message)
368{
369 /* return the most-significant byte of the first word of the */
370 /* message */
371 return ((IxNpeMhMessageId) ((message.data[0] >> 24) & 0xFF));
372}
373
374/*
375 * Function definition: ixNpeMhConfigNpeIdIsValid
376 */
377
378BOOL ixNpeMhConfigNpeIdIsValid (
379 IxNpeMhNpeId npeId)
380{
381 /* check that the npeId parameter is within the range of valid IDs */
382 return (npeId >= 0 && npeId < IX_NPEMH_NUM_NPES);
383}
384
385/*
386 * Function definition: ixNpeMhConfigLockGet
387 */
388
389void ixNpeMhConfigLockGet (
390 IxNpeMhNpeId npeId)
391{
392 IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
393 "ixNpeMhConfigLockGet\n");
394
395 /* lock the mutex for this NPE */
396 (void) ixOsalMutexLock (&ixNpeMhConfigNpeInfo[npeId].mutex,
397 IX_OSAL_WAIT_FOREVER);
398
399 /* disable the NPE's "outFIFO not empty" interrupt */
400 ixNpeMhConfigNpeInfo[npeId].oldInterruptState =
401 ixNpeMhConfigNpeInterruptDisable (npeId);
402
403 IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
404 "ixNpeMhConfigLockGet\n");
405}
406
407/*
408 * Function definition: ixNpeMhConfigLockRelease
409 */
410
411void ixNpeMhConfigLockRelease (
412 IxNpeMhNpeId npeId)
413{
414 IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
415 "ixNpeMhConfigLockRelease\n");
416
417 /* if the interrupt was previously enabled */
418 if (ixNpeMhConfigNpeInfo[npeId].oldInterruptState)
419 {
420 /* enable the NPE's "outFIFO not empty" interrupt */
421 ixNpeMhConfigNpeInfo[npeId].oldInterruptState =
422 ixNpeMhConfigNpeInterruptEnable (npeId);
423 }
424
425 /* unlock the mutex for this NPE */
426 (void) ixOsalMutexUnlock (&ixNpeMhConfigNpeInfo[npeId].mutex);
427
428 IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
429 "ixNpeMhConfigLockRelease\n");
430}
431
432/*
433 * Function definition: ixNpeMhConfigInFifoWrite
434 */
435
436IX_STATUS ixNpeMhConfigInFifoWrite (
437 IxNpeMhNpeId npeId,
438 IxNpeMhMessage message)
439{
440 volatile UINT32 *npeInFifo =
441 (UINT32 *)ixNpeMhConfigNpeInfo[npeId].inFifoRegister;
442 UINT32 retriesCount = 0;
443
444 /* write the first word of the message to the NPE's inFIFO */
445 IX_NPEMH_REGISTER_WRITE (npeInFifo, message.data[0]);
446
447 /* need to wait for room to write second word - see SCR #493,
448 poll for maximum number of retries, if exceed maximum
449 retries, exit from while loop */
450 while ((IX_NPE_MH_MAX_NUM_OF_RETRIES > retriesCount)
451 && ixNpeMhConfigInFifoIsFull (npeId))
452 {
453 retriesCount++;
454 }
455
456 /* Return TIMEOUT status to caller, indicate that NPE Hang / Halt */
457 if (IX_NPE_MH_MAX_NUM_OF_RETRIES == retriesCount)
458 {
459 return IX_NPEMH_CRITICAL_NPE_ERR;
460 }
461
462 /* write the second word of the message to the NPE's inFIFO */
463 IX_NPEMH_REGISTER_WRITE (npeInFifo, message.data[1]);
464
465 /* record in the stats the maximum number of retries needed */
466 if (ixNpeMhConfigStats[npeId].maxInFifoFullRetries < retriesCount)
467 {
468 ixNpeMhConfigStats[npeId].maxInFifoFullRetries = retriesCount;
469 }
470
471 /* update statistical info */
472 ixNpeMhConfigStats[npeId].inFifoWrites++;
473
474 return IX_SUCCESS;
475}
476
477/*
478 * Function definition: ixNpeMhConfigOutFifoRead
479 */
480
481IX_STATUS ixNpeMhConfigOutFifoRead (
482 IxNpeMhNpeId npeId,
483 IxNpeMhMessage *message)
484{
485 volatile UINT32 *npeOutFifo =
486 (UINT32 *)ixNpeMhConfigNpeInfo[npeId].outFifoRegister;
487 UINT32 retriesCount = 0;
488
489 /* read the first word of the message from the NPE's outFIFO */
490 IX_NPEMH_REGISTER_READ (npeOutFifo, &message->data[0]);
491
492 /* need to wait for NPE to write second word - see SCR #493
493 poll for maximum number of retries, if exceed maximum
494 retries, exit from while loop */
495 while ((IX_NPE_MH_MAX_NUM_OF_RETRIES > retriesCount)
496 && ixNpeMhConfigOutFifoIsEmpty (npeId))
497 {
498 retriesCount++;
499 }
500
501 /* Return TIMEOUT status to caller, indicate that NPE Hang / Halt */
502 if (IX_NPE_MH_MAX_NUM_OF_RETRIES == retriesCount)
503 {
504 return IX_NPEMH_CRITICAL_NPE_ERR;
505 }
506
507 /* read the second word of the message from the NPE's outFIFO */
508 IX_NPEMH_REGISTER_READ (npeOutFifo, &message->data[1]);
509
510 /* record in the stats the maximum number of retries needed */
511 if (ixNpeMhConfigStats[npeId].maxOutFifoEmptyRetries < retriesCount)
512 {
513 ixNpeMhConfigStats[npeId].maxOutFifoEmptyRetries = retriesCount;
514 }
515
516 /* update statistical info */
517 ixNpeMhConfigStats[npeId].outFifoReads++;
518
519 return IX_SUCCESS;
520}
521
522/*
523 * Function definition: ixNpeMhConfigShow
524 */
525
526void ixNpeMhConfigShow (
527 IxNpeMhNpeId npeId)
528{
529 /* show the message fifo read counter */
530 IX_NPEMH_SHOW ("Message FIFO reads",
531 ixNpeMhConfigStats[npeId].outFifoReads);
532
533 /* show the message fifo write counter */
534 IX_NPEMH_SHOW ("Message FIFO writes",
535 ixNpeMhConfigStats[npeId].inFifoWrites);
536
537 /* show the max retries performed when inFIFO full */
538 IX_NPEMH_SHOW ("Max inFIFO Full retries",
539 ixNpeMhConfigStats[npeId].maxInFifoFullRetries);
540
541 /* show the max retries performed when outFIFO empty */
542 IX_NPEMH_SHOW ("Max outFIFO Empty retries",
543 ixNpeMhConfigStats[npeId].maxOutFifoEmptyRetries);
544
545 /* show the current status of the inFifo */
546 ixOsalLog (IX_OSAL_LOG_LVL_USER, IX_OSAL_LOG_DEV_STDOUT,
547 "InFifo is %s and %s\n",
548 (ixNpeMhConfigInFifoIsEmpty (npeId) ?
549 (int) "EMPTY" : (int) "NOT EMPTY"),
550 (ixNpeMhConfigInFifoIsFull (npeId) ?
551 (int) "FULL" : (int) "NOT FULL"),
552 0, 0, 0, 0);
553
554 /* show the current status of the outFifo */
555 ixOsalLog (IX_OSAL_LOG_LVL_USER, IX_OSAL_LOG_DEV_STDOUT,
556 "OutFifo is %s and %s\n",
557 (ixNpeMhConfigOutFifoIsEmpty (npeId) ?
558 (int) "EMPTY" : (int) "NOT EMPTY"),
559 (ixNpeMhConfigOutFifoIsFull (npeId) ?
560 (int) "FULL" : (int) "NOT FULL"),
561 0, 0, 0, 0);
562}
563
564/*
565 * Function definition: ixNpeMhConfigShowReset
566 */
567
568void ixNpeMhConfigShowReset (
569 IxNpeMhNpeId npeId)
570{
571 /* reset the message fifo read counter */
572 ixNpeMhConfigStats[npeId].outFifoReads = 0;
573
574 /* reset the message fifo write counter */
575 ixNpeMhConfigStats[npeId].inFifoWrites = 0;
576
577 /* reset the max inFIFO Full retries counter */
578 ixNpeMhConfigStats[npeId].maxInFifoFullRetries = 0;
579
580 /* reset the max outFIFO empty retries counter */
581 ixNpeMhConfigStats[npeId].maxOutFifoEmptyRetries = 0;
582}
583
584