]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - sys/contrib/octeon-sdk/cvmx-pow.h
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / sys / contrib / octeon-sdk / cvmx-pow.h
1 /***********************license start***************
2  * Copyright (c) 2003-2011  Cavium Inc. (support@cavium.com). All rights
3  * reserved.
4  *
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *
10  *   * Redistributions of source code must retain the above copyright
11  *     notice, this list of conditions and the following disclaimer.
12  *
13  *   * Redistributions in binary form must reproduce the above
14  *     copyright notice, this list of conditions and the following
15  *     disclaimer in the documentation and/or other materials provided
16  *     with the distribution.
17
18  *   * Neither the name of Cavium Inc. nor the names of
19  *     its contributors may be used to endorse or promote products
20  *     derived from this software without specific prior written
21  *     permission.
22
23  * This Software, including technical data, may be subject to U.S. export  control
24  * laws, including the U.S. Export Administration Act and its  associated
25  * regulations, and may be subject to export or import  regulations in other
26  * countries.
27
28  * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
29  * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
30  * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
31  * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
32  * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
33  * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
34  * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
35  * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
36  * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE  RISK ARISING OUT OF USE OR
37  * PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
38  ***********************license end**************************************/
39
40
41 /**
42  * @file
43  *
44  * Interface to the hardware Packet Order / Work unit.
45  *
46  * New, starting with SDK 1.7.0, cvmx-pow supports a number of
47  * extended consistency checks. The define
48  * CVMX_ENABLE_POW_CHECKS controls the runtime insertion of POW
49  * internal state checks to find common programming errors. If
50  * CVMX_ENABLE_POW_CHECKS is not defined, checks are by default
51  * enabled. For example, cvmx-pow will check for the following
52  * program errors or POW state inconsistency.
53  * - Requesting a POW operation with an active tag switch in
54  *   progress.
55  * - Waiting for a tag switch to complete for an excessively
56  *   long period. This is normally a sign of an error in locking
57  *   causing deadlock.
58  * - Illegal tag switches from NULL_NULL.
59  * - Illegal tag switches from NULL.
60  * - Illegal deschedule request.
61  * - WQE pointer not matching the one attached to the core by
62  *   the POW.
63  *
64  * <hr>$Revision: 70030 $<hr>
65  */
66
67 #ifndef __CVMX_POW_H__
68 #define __CVMX_POW_H__
69
70 #include "cvmx-scratch.h"
71 #include "cvmx-wqe.h"
72
73 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
74 #include <asm/octeon/cvmx-sso-defs.h>
75 #else
76 #include "cvmx-warn.h"
77 #endif
78
79 #ifdef  __cplusplus
80 extern "C" {
81 #endif
82
83 #if defined(__FreeBSD__) && defined(_KERNEL)
84     /*
85      * For the FreeBSD kernel, have POW consistency checks depend on
86      * the setting of INVARIANTS.
87      */
88     #ifndef CVMX_ENABLE_POW_CHECKS
89         #ifdef INVARIANTS
90             #define CVMX_ENABLE_POW_CHECKS 1
91         #else
92             #define CVMX_ENABLE_POW_CHECKS 0
93         #endif
94     #endif
95 #else
96     /* Default to having all POW constancy checks turned on */
97     #ifndef CVMX_ENABLE_POW_CHECKS
98         #define CVMX_ENABLE_POW_CHECKS 1
99     #endif
100 #endif
101
102 /**
103  * Wait flag values for pow functions.
104  */
105 typedef enum
106 {
107     CVMX_POW_WAIT = 1,
108     CVMX_POW_NO_WAIT = 0,
109 } cvmx_pow_wait_t;
110
111 /**
112  *  POW tag operations.  These are used in the data stored to the POW.
113  */
114 typedef enum
115 {
116     CVMX_POW_TAG_OP_SWTAG = 0L,         /**< switch the tag (only) for this PP
117                                             - the previous tag should be non-NULL in this case
118                                             - tag switch response required
119                                             - fields used: op, type, tag */
120     CVMX_POW_TAG_OP_SWTAG_FULL = 1L,    /**< switch the tag for this PP, with full information
121                                             - this should be used when the previous tag is NULL
122                                             - tag switch response required
123                                             - fields used: address, op, grp, type, tag */
124     CVMX_POW_TAG_OP_SWTAG_DESCH = 2L,   /**< switch the tag (and/or group) for this PP and de-schedule
125                                             - OK to keep the tag the same and only change the group
126                                             - fields used: op, no_sched, grp, type, tag */
127     CVMX_POW_TAG_OP_DESCH = 3L,         /**< just de-schedule
128                                             - fields used: op, no_sched */
129     CVMX_POW_TAG_OP_ADDWQ = 4L,         /**< create an entirely new work queue entry
130                                             - fields used: address, op, qos, grp, type, tag */
131     CVMX_POW_TAG_OP_UPDATE_WQP_GRP = 5L,/**< just update the work queue pointer and grp for this PP
132                                             - fields used: address, op, grp */
133     CVMX_POW_TAG_OP_SET_NSCHED = 6L,    /**< set the no_sched bit on the de-schedule list
134                                             - does nothing if the selected entry is not on the de-schedule list
135                                             - does nothing if the stored work queue pointer does not match the address field
136                                             - fields used: address, index, op
137                                             Before issuing a *_NSCHED operation, SW must guarantee that all
138                                             prior deschedules and set/clr NSCHED operations are complete and all
139                                             prior switches are complete. The hardware provides the opsdone bit
140                                             and swdone bit for SW polling. After issuing a *_NSCHED operation,
141                                             SW must guarantee that the set/clr NSCHED is complete before
142                                             any subsequent operations. */
143     CVMX_POW_TAG_OP_CLR_NSCHED = 7L,    /**< clears the no_sched bit on the de-schedule list
144                                             - does nothing if the selected entry is not on the de-schedule list
145                                             - does nothing if the stored work queue pointer does not match the address field
146                                             - fields used: address, index, op
147                                             Before issuing a *_NSCHED operation, SW must guarantee that all
148                                             prior deschedules and set/clr NSCHED operations are complete and all
149                                             prior switches are complete. The hardware provides the opsdone bit
150                                             and swdone bit for SW polling. After issuing a *_NSCHED operation,
151                                             SW must guarantee that the set/clr NSCHED is complete before
152                                             any subsequent operations. */
153     CVMX_POW_TAG_OP_NOP = 15L           /**< do nothing */
154 } cvmx_pow_tag_op_t;
155
156 /**
157  * This structure defines the store data on a store to POW
158  */
159 typedef union
160 {
161     uint64_t u64;
162     struct
163     {
164 #ifdef __BIG_ENDIAN_BITFIELD
165         uint64_t              no_sched  : 1; /**< don't reschedule this entry. no_sched is used for CVMX_POW_TAG_OP_SWTAG_DESCH and CVMX_POW_TAG_OP_DESCH */
166         uint64_t                unused  : 2;
167         uint64_t                 index  :13; /**< contains index of entry for a CVMX_POW_TAG_OP_*_NSCHED */
168         cvmx_pow_tag_op_t          op   : 4; /**< the operation to perform */
169         uint64_t                unused2 : 2;
170         uint64_t                   qos  : 3; /**< the QOS level for the packet. qos is only used for CVMX_POW_TAG_OP_ADDWQ */
171         uint64_t                   grp  : 4; /**< the group that the work queue entry will be scheduled to grp is used for CVMX_POW_TAG_OP_ADDWQ, CVMX_POW_TAG_OP_SWTAG_FULL, CVMX_POW_TAG_OP_SWTAG_DESCH, and CVMX_POW_TAG_OP_UPDATE_WQP_GRP */
172         cvmx_pow_tag_type_t        type : 3; /**< the type of the tag. type is used for everything except CVMX_POW_TAG_OP_DESCH, CVMX_POW_TAG_OP_UPDATE_WQP_GRP, and CVMX_POW_TAG_OP_*_NSCHED */
173         uint64_t                   tag  :32; /**< the actual tag. tag is used for everything except CVMX_POW_TAG_OP_DESCH, CVMX_POW_TAG_OP_UPDATE_WQP_GRP, and CVMX_POW_TAG_OP_*_NSCHED */
174 #else
175         uint64_t                   tag  :32;
176         cvmx_pow_tag_type_t        type : 3;
177         uint64_t                   grp  : 4;
178         uint64_t                   qos  : 3;
179         uint64_t                unused2 : 2;
180         cvmx_pow_tag_op_t          op   : 4;
181         uint64_t                 index  :13;
182         uint64_t                unused  : 2;
183         uint64_t              no_sched  : 1;
184 #endif
185     } s_cn38xx;
186     struct {
187 #ifdef __BIG_ENDIAN_BITFIELD
188         uint64_t              no_sched  : 1; /**< don't reschedule this entry. no_sched is used for CVMX_POW_TAG_OP_SWTAG_DESCH and CVMX_POW_TAG_OP_DESCH */
189         cvmx_pow_tag_op_t          op   : 4; /**< the operation to perform */
190         uint64_t               unused1  : 4;
191         uint64_t                 index  :11; /**< contains index of entry for a CVMX_POW_TAG_OP_*_NSCHED */
192         uint64_t               unused2  : 1;
193         uint64_t                   grp  : 6; /**< the group that the work queue entry will be scheduled to grp is used for CVMX_POW_TAG_OP_ADDWQ, CVMX_POW_TAG_OP_SWTAG_FULL, CVMX_POW_TAG_OP_SWTAG_DESCH, and CVMX_POW_TAG_OP_UPDATE_WQP_GRP */
194         uint64_t               unused3  : 3;
195         cvmx_pow_tag_type_t        type : 2; /**< the type of the tag. type is used for everything except CVMX_POW_TAG_OP_DESCH, CVMX_POW_TAG_OP_UPDATE_WQP_GRP, and CVMX_POW_TAG_OP_*_NSCHED */
196         uint64_t                   tag  :32; /**< the actual tag. tag is used for everything except CVMX_POW_TAG_OP_DESCH, CVMX_POW_TAG_OP_UPDATE_WQP_GRP, and CVMX_POW_TAG_OP_*_NSCHED */
197 #else
198         uint64_t                   tag  :32;
199         cvmx_pow_tag_type_t        type : 2;
200         uint64_t               unused3  : 3;
201         uint64_t                   grp  : 6;
202         uint64_t               unused2  : 1;
203         uint64_t                 index  :11;
204         uint64_t               unused1  : 4;
205         cvmx_pow_tag_op_t          op   : 4;
206         uint64_t              no_sched  : 1;
207 #endif
208     } s_cn68xx_clr;
209     struct {
210 #ifdef __BIG_ENDIAN_BITFIELD
211         uint64_t              no_sched  : 1; /**< don't reschedule this entry. no_sched is used for CVMX_POW_TAG_OP_SWTAG_DESCH and CVMX_POW_TAG_OP_DESCH */
212         cvmx_pow_tag_op_t          op   : 4; /**< the operation to perform */
213         uint64_t               unused1  : 12;
214         uint64_t                    qos : 3; /**< contains index of entry for a CVMX_POW_TAG_OP_*_NSCHED */
215         uint64_t               unused2  : 1;
216         uint64_t                   grp  : 6; /**< the group that the work queue entry will be scheduled to grp is used for CVMX_POW_TAG_OP_ADDWQ, CVMX_POW_TAG_OP_SWTAG_FULL, CVMX_POW_TAG_OP_SWTAG_DESCH, and CVMX_POW_TAG_OP_UPDATE_WQP_GRP */
217         uint64_t               unused3  : 3;
218         cvmx_pow_tag_type_t        type : 2; /**< the type of the tag. type is used for everything except CVMX_POW_TAG_OP_DESCH, CVMX_POW_TAG_OP_UPDATE_WQP_GRP, and CVMX_POW_TAG_OP_*_NSCHED */
219         uint64_t                   tag  :32; /**< the actual tag. tag is used for everything except CVMX_POW_TAG_OP_DESCH, CVMX_POW_TAG_OP_UPDATE_WQP_GRP, and CVMX_POW_TAG_OP_*_NSCHED */
220 #else
221         uint64_t                   tag  :32;
222         cvmx_pow_tag_type_t        type : 2;
223         uint64_t               unused3  : 3;
224         uint64_t                   grp  : 6;
225         uint64_t               unused2  : 1;
226         uint64_t                   qos  : 3;
227         uint64_t               unused1  : 12;
228         cvmx_pow_tag_op_t          op   : 4;
229         uint64_t              no_sched  : 1;
230 #endif
231     } s_cn68xx_add;
232     struct {
233 #ifdef __BIG_ENDIAN_BITFIELD
234         uint64_t              no_sched  : 1; /**< don't reschedule this entry. no_sched is used for CVMX_POW_TAG_OP_SWTAG_DESCH and CVMX_POW_TAG_OP_DESCH */
235         cvmx_pow_tag_op_t          op   : 4; /**< the operation to perform */
236         uint64_t               unused1  : 16;
237         uint64_t                   grp  : 6; /**< the group that the work queue entry will be scheduled to grp is used for CVMX_POW_TAG_OP_ADDWQ, CVMX_POW_TAG_OP_SWTAG_FULL, CVMX_POW_TAG_OP_SWTAG_DESCH, and CVMX_POW_TAG_OP_UPDATE_WQP_GRP */
238         uint64_t               unused3  : 3;
239         cvmx_pow_tag_type_t        type : 2; /**< the type of the tag. type is used for everything except CVMX_POW_TAG_OP_DESCH, CVMX_POW_TAG_OP_UPDATE_WQP_GRP, and CVMX_POW_TAG_OP_*_NSCHED */
240         uint64_t                   tag  :32; /**< the actual tag. tag is used for everything except CVMX_POW_TAG_OP_DESCH, CVMX_POW_TAG_OP_UPDATE_WQP_GRP, and CVMX_POW_TAG_OP_*_NSCHED */
241 #else
242         uint64_t                   tag  :32;
243         cvmx_pow_tag_type_t        type : 2;
244         uint64_t               unused3  : 3;
245         uint64_t                   grp  : 6;
246         uint64_t               unused1  : 16;
247         cvmx_pow_tag_op_t          op   : 4;
248         uint64_t              no_sched  : 1;
249 #endif
250     } s_cn68xx_other;
251
252 } cvmx_pow_tag_req_t;
253
254 typedef struct {
255     uint32_t tag;
256     uint16_t index;
257     uint8_t  grp;
258     uint8_t tag_type;
259 }cvmx_pow_tag_info_t;
260
261 /**
262  * This structure describes the address to load stuff from POW
263  */
264 typedef union
265 {
266     uint64_t u64;
267
268     /**
269      * Address for new work request loads (did<2:0> == 0)
270      */
271     struct
272     {
273 #ifdef __BIG_ENDIAN_BITFIELD
274         uint64_t    mem_region      : 2;    /**< Mips64 address region. Should be CVMX_IO_SEG */
275         uint64_t    reserved_49_61  : 13;   /**< Must be zero */
276         uint64_t    is_io           : 1;    /**< Must be one */
277         uint64_t    did             : 8;    /**< the ID of POW -- did<2:0> == 0 in this case */
278         uint64_t    reserved_4_39   : 36;   /**< Must be zero */
279         uint64_t    wait            : 1;    /**< If set, don't return load response until work is available */
280         uint64_t    reserved_0_2    : 3;    /**< Must be zero */
281 #else
282         uint64_t    reserved_0_2    : 3;
283         uint64_t    wait            : 1;
284         uint64_t    reserved_4_39   : 36;
285         uint64_t    did             : 8;
286         uint64_t    is_io           : 1;
287         uint64_t    reserved_49_61  : 13;
288         uint64_t    mem_region      : 2;
289 #endif
290     } swork;
291
292     /**
293      * Address for loads to get POW internal status
294      */
295     struct
296     {
297 #ifdef __BIG_ENDIAN_BITFIELD
298         uint64_t    mem_region      : 2;    /**< Mips64 address region. Should be CVMX_IO_SEG */
299         uint64_t    reserved_49_61  : 13;   /**< Must be zero */
300         uint64_t    is_io           : 1;    /**< Must be one */
301         uint64_t    did             : 8;    /**< the ID of POW -- did<2:0> == 1 in this case */
302         uint64_t    reserved_10_39  : 30;   /**< Must be zero */
303         uint64_t    coreid          : 4;    /**< The core id to get status for */
304         uint64_t    get_rev         : 1;    /**< If set and get_cur is set, return reverse tag-list pointer rather than forward tag-list pointer */
305         uint64_t    get_cur         : 1;    /**< If set, return current status rather than pending status */
306         uint64_t    get_wqp         : 1;    /**< If set, get the work-queue pointer rather than tag/type */
307         uint64_t    reserved_0_2    : 3;    /**< Must be zero */
308 #else
309         uint64_t    reserved_0_2    : 3;
310         uint64_t    get_wqp         : 1;
311         uint64_t    get_cur         : 1;
312         uint64_t    get_rev         : 1;
313         uint64_t    coreid          : 4;
314         uint64_t    reserved_10_39  : 30;
315         uint64_t    did             : 8;
316         uint64_t    is_io           : 1;
317         uint64_t    reserved_49_61  : 13;
318         uint64_t    mem_region      : 2;
319 #endif
320     } sstatus;
321
322     /**
323      * Address for loads to get 68XX SS0 internal status
324      */
325     struct
326     {
327 #ifdef __BIG_ENDIAN_BITFIELD
328         uint64_t    mem_region      : 2;    /**< Mips64 address region. Should be CVMX_IO_SEG */
329         uint64_t    reserved_49_61  : 13;   /**< Must be zero */
330         uint64_t    is_io           : 1;    /**< Must be one */
331         uint64_t    did             : 8;    /**< the ID of POW -- did<2:0> == 1 in this case */
332         uint64_t    reserved_14_39  : 26;   /**< Must be zero */
333         uint64_t    coreid          : 5;    /**< The core id to get status for */
334         uint64_t    reserved_6_8    : 3;
335         uint64_t    opcode          : 3;    /**< Status operation */
336         uint64_t    reserved_0_2    : 3;    /**< Must be zero */
337 #else
338         uint64_t    reserved_0_2    : 3;
339         uint64_t    opcode          : 3;
340         uint64_t    reserved_6_8    : 3;
341         uint64_t    coreid          : 5;
342         uint64_t    reserved_14_39  : 26;
343         uint64_t    did             : 8;
344         uint64_t    is_io           : 1;
345         uint64_t    reserved_49_61  : 13;
346         uint64_t    mem_region      : 2;
347 #endif
348     } sstatus_cn68xx;
349
350     /**
351      * Address for memory loads to get POW internal state
352      */
353     struct
354     {
355 #ifdef __BIG_ENDIAN_BITFIELD
356         uint64_t    mem_region      : 2;    /**< Mips64 address region. Should be CVMX_IO_SEG */
357         uint64_t    reserved_49_61  : 13;   /**< Must be zero */
358         uint64_t    is_io           : 1;    /**< Must be one */
359         uint64_t    did             : 8;    /**< the ID of POW -- did<2:0> == 2 in this case */
360         uint64_t    reserved_16_39  : 24;   /**< Must be zero */
361         uint64_t    index           : 11;   /**< POW memory index */
362         uint64_t    get_des         : 1;    /**< If set, return deschedule information rather than the standard
363                                                 response for work-queue index (invalid if the work-queue entry is not on the
364                                                 deschedule list). */
365         uint64_t    get_wqp         : 1;    /**< If set, get the work-queue pointer rather than tag/type (no effect when get_des set). */
366         uint64_t    reserved_0_2    : 3;    /**< Must be zero */
367 #else
368         uint64_t    reserved_0_2    : 3;
369         uint64_t    get_wqp         : 1;
370         uint64_t    get_des         : 1;
371         uint64_t    index           : 11;
372         uint64_t    reserved_16_39  : 24;
373         uint64_t    did             : 8;
374         uint64_t    is_io           : 1;
375         uint64_t    reserved_49_61  : 13;
376         uint64_t    mem_region      : 2;
377 #endif
378     } smemload;
379
380     /**
381      * Address for memory loads to get SSO internal state
382      */
383     struct
384     {
385 #ifdef __BIG_ENDIAN_BITFIELD
386         uint64_t    mem_region      : 2;    /**< Mips64 address region. Should be CVMX_IO_SEG */
387         uint64_t    reserved_49_61  : 13;   /**< Must be zero */
388         uint64_t    is_io           : 1;    /**< Must be one */
389         uint64_t    did             : 8;    /**< the ID of SSO - did<2:0> == 2 in this case */
390         uint64_t    reserved_20_39  : 20;   /**< Must be zero */
391         uint64_t    index           : 11;   /**< SSO memory index */
392         uint64_t    reserved_6_8    : 3;    /**< Must be zero */
393         uint64_t    opcode          : 3;    /**< Read TAG/WQ pointer/pending tag/next potr */
394         uint64_t    reserved_0_2    : 3;    /**< Must be zero */
395 #else
396         uint64_t    reserved_0_2    : 3;
397         uint64_t    opcode          : 3;
398         uint64_t    reserved_3_5    : 3;
399         uint64_t    index           : 11;
400         uint64_t    reserved_20_39  : 20;
401         uint64_t    did             : 8;
402         uint64_t    is_io           : 1;
403         uint64_t    reserved_49_61  : 13;
404         uint64_t    mem_region      : 2;
405 #endif
406     } smemload_cn68xx;
407
408     /**
409      * Address for index/pointer loads
410      */
411     struct
412     {
413 #ifdef __BIG_ENDIAN_BITFIELD
414         uint64_t    mem_region      : 2;    /**< Mips64 address region. Should be CVMX_IO_SEG */
415         uint64_t    reserved_49_61  : 13;   /**< Must be zero */
416         uint64_t    is_io           : 1;    /**< Must be one */
417         uint64_t    did             : 8;    /**< the ID of POW -- did<2:0> == 3 in this case */
418         uint64_t    reserved_9_39   : 31;   /**< Must be zero */
419         uint64_t    qosgrp          : 4;    /**< when {get_rmt ==0 AND get_des_get_tail == 0}, this field selects one of
420                                                 eight POW internal-input queues (0-7), one per QOS level; values 8-15 are
421                                                 illegal in this case;
422                                                 when {get_rmt ==0 AND get_des_get_tail == 1}, this field selects one of
423                                                 16 deschedule lists (per group);
424                                                 when get_rmt ==1, this field selects one of 16 memory-input queue lists.
425                                                 The two memory-input queue lists associated with each QOS level are:
426                                                 - qosgrp = 0, qosgrp = 8:      QOS0
427                                                 - qosgrp = 1, qosgrp = 9:      QOS1
428                                                 - qosgrp = 2, qosgrp = 10:     QOS2
429                                                 - qosgrp = 3, qosgrp = 11:     QOS3
430                                                 - qosgrp = 4, qosgrp = 12:     QOS4
431                                                 - qosgrp = 5, qosgrp = 13:     QOS5
432                                                 - qosgrp = 6, qosgrp = 14:     QOS6
433                                                 - qosgrp = 7, qosgrp = 15:     QOS7 */
434         uint64_t    get_des_get_tail: 1;    /**< If set and get_rmt is clear, return deschedule list indexes
435                                                 rather than indexes for the specified qos level; if set and get_rmt is set, return
436                                                 the tail pointer rather than the head pointer for the specified qos level. */
437         uint64_t    get_rmt         : 1;    /**< If set, return remote pointers rather than the local indexes for the specified qos level. */
438         uint64_t    reserved_0_2    : 3;    /**< Must be zero */
439 #else
440         uint64_t    reserved_0_2    : 3;
441         uint64_t    get_rmt         : 1;
442         uint64_t    get_des_get_tail: 1;
443         uint64_t    qosgrp          : 4;
444         uint64_t    reserved_9_39   : 31;
445         uint64_t    did             : 8;
446         uint64_t    is_io           : 1;
447         uint64_t    reserved_49_61  : 13;
448         uint64_t    mem_region      : 2;
449 #endif
450     } sindexload;
451
452     /**
453      * Address for a Index/Pointer loads to get SSO internal state
454      */
455     struct
456     {
457 #ifdef __BIG_ENDIAN_BITFIELD
458         uint64_t    mem_region      : 2;    /**< Mips64 address region. Should be CVMX_IO_SEG */
459         uint64_t    reserved_49_61  : 13;   /**< Must be zero */
460         uint64_t    is_io           : 1;    /**< Must be one */
461         uint64_t    did             : 8;    /**< the ID of SSO - did<2:0> == 2 in this case */
462         uint64_t    reserved_15_39  : 25;   /**< Must be zero */
463         uint64_t    qos_grp         : 6;    /**< When opcode = IPL_IQ, this field specifies IQ (or QOS).
464                                                  When opcode = IPL_DESCHED, this field specifies the group.
465                                                  This field is reserved for all other opcodes. */
466         uint64_t    reserved_6_8    : 3;    /**< Must be zero */
467         uint64_t    opcode          : 3;    /**< Read TAG/WQ pointer/pending tag/next potr */
468         uint64_t    reserved_0_2    : 3;    /**< Must be zero */
469 #else
470         uint64_t    reserved_0_2    : 3;
471         uint64_t    opcode          : 3;
472         uint64_t    reserved_3_5    : 3;
473         uint64_t    qos_grp         : 6;
474         uint64_t    reserved_15_39  : 25;
475         uint64_t    did             : 8;
476         uint64_t    is_io           : 1;
477         uint64_t    reserved_49_61  : 13;
478         uint64_t    mem_region      : 2;
479 #endif
480     } sindexload_cn68xx;
481
482     /**
483      * address for NULL_RD request (did<2:0> == 4)
484      * when this is read, HW attempts to change the state to NULL if it is NULL_NULL
485      * (the hardware cannot switch from NULL_NULL to NULL if a POW entry is not available -
486      * software may need to recover by finishing another piece of work before a POW
487      * entry can ever become available.)
488      */
489     struct
490     {
491 #ifdef __BIG_ENDIAN_BITFIELD
492         uint64_t    mem_region      : 2;    /**< Mips64 address region. Should be CVMX_IO_SEG */
493         uint64_t    reserved_49_61  : 13;   /**< Must be zero */
494         uint64_t    is_io           : 1;    /**< Must be one */
495         uint64_t    did             : 8;    /**< the ID of POW -- did<2:0> == 4 in this case */
496         uint64_t    reserved_0_39   : 40;   /**< Must be zero */
497 #else
498         uint64_t    reserved_0_39   : 40;
499         uint64_t    did             : 8;
500         uint64_t    is_io           : 1;
501         uint64_t    reserved_49_61  : 13;
502         uint64_t    mem_region      : 2;
503 #endif
504     } snull_rd;
505 } cvmx_pow_load_addr_t;
506
507 /**
508  * This structure defines the response to a load/SENDSINGLE to POW (except CSR reads)
509  */
510 typedef union
511 {
512     uint64_t u64;
513
514     /**
515      * Response to new work request loads
516      */
517     struct
518     {
519 #ifdef __BIG_ENDIAN_BITFIELD
520         uint64_t    no_work          : 1;   /**< Set when no new work queue entry was returned.
521                                                 If there was de-scheduled work, the HW will definitely
522                                                 return it. When this bit is set, it could mean
523                                                 either mean:
524                                                 - There was no work, or
525                                                 - There was no work that the HW could find. This
526                                                     case can happen, regardless of the wait bit value
527                                                     in the original request, when there is work
528                                                     in the IQ's that is too deep down the list. */
529         uint64_t    reserved_40_62   : 23;  /**< Must be zero */
530         uint64_t    addr             : 40;  /**< 36 in O1 -- the work queue pointer */
531 #else
532         uint64_t    addr             : 40;
533         uint64_t    reserved_40_62   : 23;
534         uint64_t    no_work          : 1;
535 #endif
536     } s_work;
537
538     /**
539      * Result for a POW Status Load (when get_cur==0 and get_wqp==0)
540      */
541     struct
542     {
543 #ifdef __BIG_ENDIAN_BITFIELD
544         uint64_t    reserved_62_63  : 2;
545         uint64_t    pend_switch     : 1;    /**< Set when there is a pending non-NULL SWTAG or
546                                                 SWTAG_FULL, and the POW entry has not left the list for the original tag. */
547         uint64_t    pend_switch_full: 1;    /**< Set when SWTAG_FULL and pend_switch is set. */
548         uint64_t    pend_switch_null: 1;    /**< Set when there is a pending NULL SWTAG, or an implicit switch to NULL. */
549         uint64_t    pend_desched    : 1;    /**< Set when there is a pending DESCHED or SWTAG_DESCHED. */
550         uint64_t    pend_desched_switch: 1; /**< Set when there is a pending SWTAG_DESCHED and pend_desched is set. */
551         uint64_t    pend_nosched    : 1;    /**< Set when nosched is desired and pend_desched is set. */
552         uint64_t    pend_new_work   : 1;    /**< Set when there is a pending GET_WORK. */
553         uint64_t    pend_new_work_wait: 1;  /**< When pend_new_work is set, this bit indicates that the wait bit was set. */
554         uint64_t    pend_null_rd    : 1;    /**< Set when there is a pending NULL_RD. */
555         uint64_t    pend_nosched_clr: 1;    /**< Set when there is a pending CLR_NSCHED. */
556         uint64_t    reserved_51     : 1;
557         uint64_t    pend_index      : 11;   /**< This is the index when pend_nosched_clr is set. */
558         uint64_t    pend_grp        : 4;    /**< This is the new_grp when (pend_desched AND pend_desched_switch) is set. */
559         uint64_t    reserved_34_35  : 2;
560         uint64_t    pend_type       : 2;    /**< This is the tag type when pend_switch or (pend_desched AND pend_desched_switch) are set. */
561         uint64_t    pend_tag        : 32;   /**< - this is the tag when pend_switch or (pend_desched AND pend_desched_switch) are set. */
562 #else
563         uint64_t    pend_tag        : 32;
564         uint64_t    pend_type       : 2;
565         uint64_t    reserved_34_35  : 2;
566         uint64_t    pend_grp        : 4;
567         uint64_t    pend_index      : 11;
568         uint64_t    reserved_51     : 1;
569         uint64_t    pend_nosched_clr: 1;
570         uint64_t    pend_null_rd    : 1;
571         uint64_t    pend_new_work_wait: 1;
572         uint64_t    pend_new_work   : 1;
573         uint64_t    pend_nosched    : 1;
574         uint64_t    pend_desched_switch: 1;
575         uint64_t    pend_desched    : 1;
576         uint64_t    pend_switch_null: 1;
577         uint64_t    pend_switch_full: 1;
578         uint64_t    pend_switch     : 1;
579         uint64_t    reserved_62_63  : 2;
580 #endif
581     } s_sstatus0;
582
583     /**
584      * Result for a SSO Status Load (when opcode is SL_PENDTAG)
585      */
586     struct
587     {
588 #ifdef __BIG_ENDIAN_BITFIELD
589         uint64_t    pend_switch     : 1;    /**< Set when there is a pending non-UNSCHEDULED SWTAG or
590                                                 SWTAG_FULL, and the SSO entry has not left the list for the original tag. */
591         uint64_t    pend_get_work   : 1;    /**< Set when there is a pending GET_WORK */
592         uint64_t    pend_get_work_wait: 1;  /**< when pend_get_work is set, this biit indicates that the 
593                                                  wait bit was set. */
594         uint64_t    pend_nosched    : 1;    /**< Set when nosched is desired and pend_desched is set. */
595         uint64_t    pend_nosched_clr: 1;    /**< Set when there is a pending CLR_NSCHED. */
596         uint64_t    pend_desched    : 1;    /**< Set when there is a pending DESCHED or SWTAG_DESCHED. */
597         uint64_t    pend_alloc_we   : 1;    /**< Set when there is a pending ALLOC_WE. */
598         uint64_t    reserved_48_56  : 9;
599         uint64_t    pend_index      : 11;   /**< This is the index when pend_nosched_clr is set. */
600         uint64_t    reserved_34_36  : 3;
601         uint64_t    pend_type       : 2;    /**< This is the tag type when pend_switch is set. */
602         uint64_t    pend_tag        : 32;   /**< This is the tag when pend_switch is set. */
603 #else
604         uint64_t    pend_tag        : 32;
605         uint64_t    pend_type       : 2;
606         uint64_t    reserved_34_36  : 3;
607         uint64_t    pend_index      : 11;
608         uint64_t    reserved_48_56  : 9;
609         uint64_t    pend_alloc_we   : 1;
610         uint64_t    pend_desched    : 1;
611         uint64_t    pend_nosched_clr: 1;
612         uint64_t    pend_nosched    : 1;
613         uint64_t    pend_get_work_wait: 1;
614         uint64_t    pend_get_work   : 1;
615         uint64_t    pend_switch     : 1;
616 #endif
617     } s_sstatus0_cn68xx;
618
619     /**
620      * Result for a POW Status Load (when get_cur==0 and get_wqp==1)
621      */
622     struct
623     {
624 #ifdef __BIG_ENDIAN_BITFIELD
625         uint64_t    reserved_62_63  : 2;
626         uint64_t    pend_switch     : 1;    /**< Set when there is a pending non-NULL SWTAG or
627                                                 SWTAG_FULL, and the POW entry has not left the list for the original tag. */
628         uint64_t    pend_switch_full: 1;    /**< Set when SWTAG_FULL and pend_switch is set. */
629         uint64_t    pend_switch_null: 1;    /**< Set when there is a pending NULL SWTAG, or an implicit switch to NULL. */
630         uint64_t    pend_desched    : 1;    /**< Set when there is a pending DESCHED or SWTAG_DESCHED. */
631         uint64_t    pend_desched_switch: 1; /**< Set when there is a pending SWTAG_DESCHED and pend_desched is set. */
632         uint64_t    pend_nosched    : 1;    /**< Set when nosched is desired and pend_desched is set. */
633         uint64_t    pend_new_work   : 1;    /**< Set when there is a pending GET_WORK. */
634         uint64_t    pend_new_work_wait: 1;  /**< When pend_new_work is set, this bit indicates that the wait bit was set. */
635         uint64_t    pend_null_rd    : 1;    /**< Set when there is a pending NULL_RD. */
636         uint64_t    pend_nosched_clr: 1;    /**< Set when there is a pending CLR_NSCHED. */
637         uint64_t    reserved_51     : 1;
638         uint64_t    pend_index      : 11;   /**< This is the index when pend_nosched_clr is set. */
639         uint64_t    pend_grp        : 4;    /**< This is the new_grp when (pend_desched AND pend_desched_switch) is set. */
640         uint64_t    pend_wqp        : 36;   /**< This is the wqp when pend_nosched_clr is set. */
641 #else
642         uint64_t    pend_wqp        : 36;
643         uint64_t    pend_grp        : 4;
644         uint64_t    pend_index      : 11;
645         uint64_t    reserved_51     : 1;
646         uint64_t    pend_nosched_clr: 1;
647         uint64_t    pend_null_rd    : 1;
648         uint64_t    pend_new_work_wait: 1;
649         uint64_t    pend_new_work   : 1;
650         uint64_t    pend_nosched    : 1;
651         uint64_t    pend_desched_switch: 1;
652         uint64_t    pend_desched    : 1;
653         uint64_t    pend_switch_null: 1;
654         uint64_t    pend_switch_full: 1;
655         uint64_t    pend_switch     : 1;
656         uint64_t    reserved_62_63  : 2;
657 #endif
658     } s_sstatus1;
659
660     /**
661      * Result for a SSO Status Load (when opcode is SL_PENDWQP)
662      */
663     struct
664     {
665 #ifdef __BIG_ENDIAN_BITFIELD
666         uint64_t    pend_switch     : 1;    /**< Set when there is a pending non-UNSCHEDULED SWTAG or
667                                                 SWTAG_FULL, and the SSO entry has not left the list for the original tag. */
668         uint64_t    pend_get_work   : 1;    /**< Set when there is a pending GET_WORK */
669         uint64_t    pend_get_work_wait: 1;  /**< when pend_get_work is set, this biit indicates that the 
670                                                  wait bit was set. */
671         uint64_t    pend_nosched    : 1;    /**< Set when nosched is desired and pend_desched is set. */
672         uint64_t    pend_nosched_clr: 1;    /**< Set when there is a pending CLR_NSCHED. */
673         uint64_t    pend_desched    : 1;    /**< Set when there is a pending DESCHED or SWTAG_DESCHED. */
674         uint64_t    pend_alloc_we   : 1;    /**< Set when there is a pending ALLOC_WE. */
675         uint64_t    reserved_51_56  : 6;
676         uint64_t    pend_index      : 11;   /**< This is the index when pend_nosched_clr is set. */
677         uint64_t    reserved_38_39  : 2;
678         uint64_t    pend_wqp        : 38;   /**< This is the wqp when pend_nosched_clr is set. */
679 #else
680         uint64_t    pend_wqp        : 38;
681         uint64_t    reserved_38_39  : 2;
682         uint64_t    pend_index      : 11;
683         uint64_t    reserved_51_56  : 6;
684         uint64_t    pend_alloc_we   : 1;
685         uint64_t    pend_desched    : 1;
686         uint64_t    pend_nosched_clr: 1;
687         uint64_t    pend_nosched    : 1;
688         uint64_t    pend_get_work_wait: 1;
689         uint64_t    pend_get_work   : 1;
690         uint64_t    pend_switch     : 1;
691 #endif
692     } s_sstatus1_cn68xx;
693
694     /**
695      * Result for a POW Status Load (when get_cur==1, get_wqp==0, and get_rev==0)
696      */
697     struct
698     {
699 #ifdef __BIG_ENDIAN_BITFIELD
700         uint64_t    reserved_62_63  : 2;
701         uint64_t    link_index      : 11;    /**< Points to the next POW entry in the tag list when tail == 0 (and
702                                                 tag_type is not NULL or NULL_NULL). */
703         uint64_t    index           : 11;   /**< The POW entry attached to the core. */
704         uint64_t    grp             : 4;    /**< The group attached to the core (updated when new tag list entered on SWTAG_FULL). */
705         uint64_t    head            : 1;    /**< Set when this POW entry is at the head of its tag list (also set when in
706                                                 the NULL or NULL_NULL state). */
707         uint64_t    tail            : 1;    /**< Set when this POW entry is at the tail of its tag list (also set when in the
708                                                 NULL or NULL_NULL state). */
709         uint64_t    tag_type        : 2;    /**< The tag type attached to the core (updated when new tag list
710                                                 entered on SWTAG, SWTAG_FULL, or SWTAG_DESCHED). */
711         uint64_t    tag             : 32;   /**< The tag attached to the core (updated when new tag list entered on
712                                                 SWTAG, SWTAG_FULL, or SWTAG_DESCHED). */
713 #else
714         uint64_t    tag             : 32;
715         uint64_t    tag_type        : 2;
716         uint64_t    tail            : 1;
717         uint64_t    head            : 1;
718         uint64_t    grp             : 4;
719         uint64_t    index           : 11;
720         uint64_t    link_index      : 11;
721         uint64_t    reserved_62_63  : 2;
722 #endif
723     } s_sstatus2;
724
725     /**
726      * Result for a SSO Status Load (when opcode is SL_TAG)
727      */
728     struct
729     {
730 #ifdef __BIG_ENDIAN_BITFIELD
731         uint64_t    reserved_57_63  : 7;
732         uint64_t    index           : 11;   /**< The SSO entry attached to the core. */
733         uint64_t    reserved_45     : 1;
734         uint64_t    grp             : 6;    /**< The group attached to the core (updated when new tag list entered on
735                                                  SWTAG_FULL). */
736         uint64_t    head            : 1;    /**< Set when this SSO entry is at the head of its tag list (also set when in the
737                                                  UNSCHEDULED or EMPTY state). */
738         uint64_t    tail            : 1;    /**< Set when this SSO entry is at the tail of its tag list (also set when in the
739                                                  UNSCHEDULED or EMPTY state). */
740         uint64_t    reserved_34_36  : 3;
741         uint64_t    tag_type        : 2;    /**< The tag type attached to the core (updated when new tag list entered
742                                                  on SWTAG, SWTAG_FULL, or SWTAG_DESCHED). */
743         uint64_t    tag             : 32;   /**< The tag attached to the core (updated when new tag list entered on SWTAG,
744                                                  SWTAG_FULL, or SWTAG_DESCHED). */
745 #else
746         uint64_t    tag             : 32;
747         uint64_t    tag_type        : 2;
748         uint64_t    reserved_34_36  : 3;
749         uint64_t    tail            : 1;
750         uint64_t    head            : 1;
751         uint64_t    grp             : 6;
752         uint64_t    reserved_45     : 1;
753         uint64_t    index           : 11;
754         uint64_t    reserved_57_63  : 7;
755 #endif
756     } s_sstatus2_cn68xx;
757
758     /**
759      * Result for a POW Status Load (when get_cur==1, get_wqp==0, and get_rev==1)
760      */
761     struct
762     {
763 #ifdef __BIG_ENDIAN_BITFIELD
764         uint64_t    reserved_62_63  : 2;
765         uint64_t    revlink_index   : 11;   /**< Points to the prior POW entry in the tag list when head == 0
766                                                 (and tag_type is not NULL or NULL_NULL). This field is unpredictable
767                                                 when the core's state is NULL or NULL_NULL. */
768         uint64_t    index           : 11;   /**< The POW entry attached to the core. */
769         uint64_t    grp             : 4;    /**< The group attached to the core (updated when new tag list entered on SWTAG_FULL). */
770         uint64_t    head            : 1;    /**< Set when this POW entry is at the head of its tag list (also set when in
771                                                 the NULL or NULL_NULL state). */
772         uint64_t    tail            : 1;    /**< Set when this POW entry is at the tail of its tag list (also set when in the
773                                                 NULL or NULL_NULL state). */
774         uint64_t    tag_type        : 2;    /**< The tag type attached to the core (updated when new tag list
775                                                 entered on SWTAG, SWTAG_FULL, or SWTAG_DESCHED). */
776         uint64_t    tag             : 32;   /**< The tag attached to the core (updated when new tag list entered on
777                                                 SWTAG, SWTAG_FULL, or SWTAG_DESCHED). */
778 #else
779         uint64_t    tag             : 32;
780         uint64_t    tag_type        : 2;
781         uint64_t    tail            : 1;
782         uint64_t    head            : 1;
783         uint64_t    grp             : 4;
784         uint64_t    index           : 11;
785         uint64_t    revlink_index   : 11;
786         uint64_t    reserved_62_63  : 2;
787 #endif
788     } s_sstatus3;
789
790     /**
791      * Result for a SSO Status Load (when opcode is SL_WQP)
792      */
793     struct
794     {
795 #ifdef __BIG_ENDIAN_BITFIELD
796         uint64_t    reserved_58_63  : 6;
797         uint64_t    index           : 11;   /**< The SSO entry attached to the core. */
798         uint64_t    reserved_46     : 1;
799         uint64_t    grp             : 6;    /**< The group attached to the core (updated when new tag list entered on
800                                                  SWTAG_FULL). */
801         uint64_t    reserved_38_39  : 2;
802         uint64_t    wqp             : 38;   /**< The wqp attached to the core (updated when new tag list entered on SWTAG_FULL). */
803 #else
804         uint64_t    wqp             : 38;
805         uint64_t    reserved_38_39  : 2;
806         uint64_t    grp             : 6;
807         uint64_t    reserved_46     : 1;
808         uint64_t    index           : 11;
809         uint64_t    reserved_58_63  : 6;
810 #endif
811     } s_sstatus3_cn68xx;
812
813     /**
814      * Result for a POW Status Load (when get_cur==1, get_wqp==1, and get_rev==0)
815      */
816     struct
817     {
818 #ifdef __BIG_ENDIAN_BITFIELD
819         uint64_t    reserved_62_63  : 2;
820         uint64_t    link_index      : 11;    /**< Points to the next POW entry in the tag list when tail == 0 (and
821                                                 tag_type is not NULL or NULL_NULL). */
822         uint64_t    index           : 11;   /**< The POW entry attached to the core. */
823         uint64_t    grp             : 4;    /**< The group attached to the core (updated when new tag list entered on SWTAG_FULL). */
824         uint64_t    wqp             : 36;   /**< The wqp attached to the core (updated when new tag list entered on SWTAG_FULL). */
825 #else
826         uint64_t    wqp             : 36;
827         uint64_t    grp             : 4;
828         uint64_t    index           : 11;
829         uint64_t    link_index      : 11;
830         uint64_t    reserved_62_63  : 2;
831 #endif
832     } s_sstatus4;
833
834     /**
835      * Result for a SSO Status Load (when opcode is SL_LINKS)
836      */
837     struct
838     {
839 #ifdef __BIG_ENDIAN_BITFIELD
840         uint64_t    reserved_46_63  : 18;
841         uint64_t    index           : 11;   /**< The SSO entry attached to the core. */
842         uint64_t    reserved_34     : 1;
843         uint64_t    grp             : 6;    /**< The group attached to the core (updated when new tag list entered on
844                                                  SWTAG_FULL). */
845         uint64_t    head            : 1;    /**< Set when this SSO entry is at the head of its tag list (also set when in the
846                                                  UNSCHEDULED or EMPTY state). */
847         uint64_t    tail            : 1;    /**< Set when this SSO entry is at the tail of its tag list (also set when in the
848                                                  UNSCHEDULED or EMPTY state). */
849         uint64_t    reserved_24_25  : 2;
850         uint64_t    revlink_index   : 11;   /**< Points to the prior SSO entry in the tag list when head==0 (and tag_type is not UNSCHEDULED or EMPTY). */
851         uint64_t    reserved_11_12  : 2;
852         uint64_t    link_index      : 11;   /**< Points to the next SSO entry in the tag list when tail==0 (and tag_type is not UNSCHEDULDED or EMPTY). */
853 #else
854         uint64_t    link_index      : 11;
855         uint64_t    reserved_11_12  : 2;
856         uint64_t    revlink_index   : 11;
857         uint64_t    reserved_24_25  : 2;
858         uint64_t    tail            : 1;
859         uint64_t    head            : 1;
860         uint64_t    grp             : 6;
861         uint64_t    reserved_34     : 1;
862         uint64_t    index           : 11;
863         uint64_t    reserved_46_63  : 18;
864 #endif
865     } s_sstatus4_cn68xx;
866
867     /**
868      * Result for a POW Status Load (when get_cur==1, get_wqp==1, and get_rev==1)
869      */
870     struct
871     {
872 #ifdef __BIG_ENDIAN_BITFIELD
873         uint64_t    reserved_62_63  : 2;
874         uint64_t    revlink_index   : 11;   /**< Points to the prior POW entry in the tag list when head == 0
875                                                 (and tag_type is not NULL or NULL_NULL). This field is unpredictable
876                                                 when the core's state is NULL or NULL_NULL. */
877         uint64_t    index           : 11;   /**< The POW entry attached to the core. */
878         uint64_t    grp             : 4;    /**< The group attached to the core (updated when new tag list entered on SWTAG_FULL). */
879         uint64_t    wqp             : 36;   /**< The wqp attached to the core (updated when new tag list entered on SWTAG_FULL). */
880 #else
881         uint64_t    wqp             : 36;
882         uint64_t    grp             : 4;
883         uint64_t    index           : 11;
884         uint64_t    revlink_index   : 11;
885         uint64_t    reserved_62_63  : 2;
886 #endif
887     } s_sstatus5;
888
889     /**
890      * Result For POW Memory Load (get_des == 0 and get_wqp == 0)
891      */
892     struct
893     {
894 #ifdef __BIG_ENDIAN_BITFIELD
895         uint64_t    reserved_51_63  : 13;
896         uint64_t    next_index      : 11;    /**< The next entry in the input, free, descheduled_head list
897                                                 (unpredictable if entry is the tail of the list). */
898         uint64_t    grp             : 4;    /**< The group of the POW entry. */
899         uint64_t    reserved_35     : 1;
900         uint64_t    tail            : 1;    /**< Set when this POW entry is at the tail of its tag list (also set when in the
901                                                 NULL or NULL_NULL state). */
902         uint64_t    tag_type        : 2;    /**< The tag type of the POW entry. */
903         uint64_t    tag             : 32;   /**< The tag of the POW entry. */
904 #else
905         uint64_t    tag             : 32;
906         uint64_t    tag_type        : 2;
907         uint64_t    tail            : 1;
908         uint64_t    reserved_35     : 1;
909         uint64_t    grp             : 4;
910         uint64_t    next_index      : 11;
911         uint64_t    reserved_51_63  : 13;
912 #endif
913     } s_smemload0;
914
915     /**
916      * Result For SSO Memory Load (opcode is ML_TAG)
917      */
918     struct
919     {
920 #ifdef __BIG_ENDIAN_BITFIELD
921         uint64_t    reserved_38_63  : 26;
922         uint64_t    tail            : 1;    /**< Set when this SSO entry is at the tail of its tag list (also set when in the
923                                                 NULL or NULL_NULL state). */
924         uint64_t    reserved_34_36  : 3;
925         uint64_t    tag_type        : 2;    /**< The tag type of the SSO entry. */
926         uint64_t    tag             : 32;   /**< The tag of the SSO entry. */
927 #else
928         uint64_t    tag             : 32;
929         uint64_t    tag_type        : 2;
930         uint64_t    reserved_34_36  : 3;
931         uint64_t    tail            : 1;
932         uint64_t    reserved_38_63  : 26;
933 #endif
934     } s_smemload0_cn68xx;
935
936     /**
937      * Result For POW Memory Load (get_des == 0 and get_wqp == 1)
938      */
939     struct
940     {
941 #ifdef __BIG_ENDIAN_BITFIELD
942         uint64_t    reserved_51_63  : 13;
943         uint64_t    next_index      : 11;    /**< The next entry in the input, free, descheduled_head list
944                                                 (unpredictable if entry is the tail of the list). */
945         uint64_t    grp             : 4;    /**< The group of the POW entry. */
946         uint64_t    wqp             : 36;   /**< The WQP held in the POW entry. */
947 #else
948         uint64_t    wqp             : 36;
949         uint64_t    grp             : 4;
950         uint64_t    next_index      : 11;
951         uint64_t    reserved_51_63  : 13;
952 #endif
953     } s_smemload1;
954
955     /**
956      * Result For SSO Memory Load (opcode is ML_WQPGRP)
957      */
958     struct
959     {
960 #ifdef __BIG_ENDIAN_BITFIELD
961         uint64_t    reserved_48_63  : 16;
962         uint64_t    nosched         : 1;    /**< The nosched bit for the SSO entry. */
963         uint64_t    reserved_46     : 1;
964         uint64_t    grp             : 6;    /**< The group of the SSO entry. */
965         uint64_t    reserved_38_39  : 2;
966         uint64_t    wqp             : 38;   /**< The WQP held in the SSO entry. */
967 #else
968         uint64_t    wqp             : 38;
969         uint64_t    reserved_38_39  : 2;
970         uint64_t    grp             : 6;
971         uint64_t    reserved_46     : 1;
972         uint64_t    nosched         : 1;
973         uint64_t    reserved_51_63  : 16;
974 #endif
975     } s_smemload1_cn68xx;
976
977     /**
978      * Result For POW Memory Load (get_des == 1)
979      */
980     struct
981     {
982 #ifdef __BIG_ENDIAN_BITFIELD
983         uint64_t    reserved_51_63  : 13;
984         uint64_t    fwd_index       : 11;   /**< The next entry in the tag list connected to the descheduled head. */
985         uint64_t    grp             : 4;    /**< The group of the POW entry. */
986         uint64_t    nosched         : 1;    /**< The nosched bit for the POW entry. */
987         uint64_t    pend_switch     : 1;    /**< There is a pending tag switch */
988         uint64_t    pend_type       : 2;    /**< The next tag type for the new tag list when pend_switch is set. */
989         uint64_t    pend_tag        : 32;   /**< The next tag for the new tag list when pend_switch is set. */
990 #else
991         uint64_t    pend_tag        : 32;
992         uint64_t    pend_type       : 2;
993         uint64_t    pend_switch     : 1;
994         uint64_t    nosched         : 1;
995         uint64_t    grp             : 4;
996         uint64_t    fwd_index       : 11;
997         uint64_t    reserved_51_63  : 13;
998 #endif
999     } s_smemload2;
1000
1001     /**
1002      * Result For SSO Memory Load (opcode is ML_PENTAG)
1003      */
1004     struct
1005     {
1006 #ifdef __BIG_ENDIAN_BITFIELD
1007         uint64_t    reserved_38_63  : 26;
1008         uint64_t    pend_switch     : 1;    /**< Set when there is a pending non-UNSCHEDULED SWTAG or
1009                                                  SWTAG_FULL, and the SSO entry has not left the list for the original tag. */
1010         uint64_t    reserved_34_36  : 3;
1011         uint64_t    pend_type       : 2;    /**< The next tag type for the new tag list when pend_switch is set. */
1012         uint64_t    pend_tag        : 32;   /**< The next tag for the new tag list when pend_switch is set. */
1013 #else
1014         uint64_t    pend_tag        : 32;
1015         uint64_t    pend_type       : 2;
1016         uint64_t    reserved_34_36  : 3;
1017         uint64_t    pend_switch     : 1;
1018         uint64_t    reserved_38_63  : 26;
1019 #endif
1020     } s_smemload2_cn68xx;
1021
1022     /**
1023      * Result For SSO Memory Load (opcode is ML_LINKS)
1024      */
1025     struct
1026     {
1027 #ifdef __BIG_ENDIAN_BITFIELD
1028         uint64_t    reserved_24_63  : 40;
1029         uint64_t    fwd_index       : 11;   /**< The next entry in the tag list connected to the descheduled head. */
1030         uint64_t    reserved_11_12  : 2;
1031         uint64_t    next_index      : 11;   /**< The next entry in the input, free, descheduled_head list
1032                                                  (unpredicatble if entry is the tail of the list). */
1033 #else
1034         uint64_t    next_index      : 11;
1035         uint64_t    reserved_11_12  : 2;
1036         uint64_t    fwd_index       : 11;
1037         uint64_t    reserved_24_63  : 40;
1038 #endif
1039     } s_smemload3_cn68xx;
1040
1041     /**
1042      * Result For POW Index/Pointer Load (get_rmt == 0/get_des_get_tail == 0)
1043      */
1044     struct
1045     {
1046 #ifdef __BIG_ENDIAN_BITFIELD
1047         uint64_t    reserved_52_63  : 12;
1048         uint64_t    free_val        : 1;    /**< - set when there is one or more POW entries on the free list. */
1049         uint64_t    free_one        : 1;    /**< - set when there is exactly one POW entry on the free list. */
1050         uint64_t    reserved_49     : 1;
1051         uint64_t    free_head       : 11;   /**< - when free_val is set, indicates the first entry on the free list. */
1052         uint64_t    reserved_37     : 1;
1053         uint64_t    free_tail       : 11;   /**< - when free_val is set, indicates the last entry on the free list. */
1054         uint64_t    loc_val         : 1;    /**< - set when there is one or more POW entries on the input Q list selected by qosgrp. */
1055         uint64_t    loc_one         : 1;    /**< - set when there is exactly one POW entry on the input Q list selected by qosgrp. */
1056         uint64_t    reserved_23     : 1;
1057         uint64_t    loc_head        : 11;   /**< - when loc_val is set, indicates the first entry on the input Q list selected by qosgrp. */
1058         uint64_t    reserved_11     : 1;
1059         uint64_t    loc_tail        : 11;   /**< - when loc_val is set, indicates the last entry on the input Q list selected by qosgrp. */
1060 #else
1061         uint64_t    loc_tail        : 11;
1062         uint64_t    reserved_11     : 1;
1063         uint64_t    loc_head        : 11;
1064         uint64_t    reserved_23     : 1;
1065         uint64_t    loc_one         : 1;
1066         uint64_t    loc_val         : 1;
1067         uint64_t    free_tail       : 11;
1068         uint64_t    reserved_37     : 1;
1069         uint64_t    free_head       : 11;
1070         uint64_t    reserved_49     : 1;
1071         uint64_t    free_one        : 1;
1072         uint64_t    free_val        : 1;
1073         uint64_t    reserved_52_63  : 12;
1074 #endif
1075     } sindexload0;
1076
1077     /**
1078      * Result for SSO Index/Pointer Load(opcode == IPL_IQ/IPL_DESCHED/IPL_NOSCHED)
1079      */
1080     struct
1081     {
1082 #ifdef __BIG_ENDIAN_BITFIELD
1083         uint64_t    reserved_28_63  : 36;
1084         uint64_t    queue_val       : 1;    /**< - If set, one or more valid entries are in the queue. */
1085         uint64_t    queue_one       : 1;    /**< - If set, exactly one valid entry is in the queue. */
1086         uint64_t    reserved_24_25  : 2;
1087         uint64_t    queue_head      : 11;   /**< - Index of entry at the head of the queue. */
1088         uint64_t    reserved_11_12  : 2;
1089         uint64_t    queue_tail      : 11;   /**< - Index of entry at the tail of the queue. */
1090 #else
1091         uint64_t    queue_tail      : 11;
1092         uint64_t    reserved_11_12  : 2;
1093         uint64_t    queue_head      : 11;
1094         uint64_t    reserved_24_25  : 2;
1095         uint64_t    queue_one       : 1;
1096         uint64_t    queue_val       : 1;
1097         uint64_t    reserved_28_63  : 36;
1098 #endif
1099     } sindexload0_cn68xx;
1100
1101     /**
1102      * Result For POW Index/Pointer Load (get_rmt == 0/get_des_get_tail == 1)
1103      */
1104     struct
1105     {
1106 #ifdef __BIG_ENDIAN_BITFIELD
1107         uint64_t    reserved_52_63  : 12;
1108         uint64_t    nosched_val     : 1;    /**< - set when there is one or more POW entries on the nosched list. */
1109         uint64_t    nosched_one     : 1;    /**< - set when there is exactly one POW entry on the nosched list. */
1110         uint64_t    reserved_49     : 1;
1111         uint64_t    nosched_head    : 11;    /**< - when nosched_val is set, indicates the first entry on the nosched list. */
1112         uint64_t    reserved_37     : 1;
1113         uint64_t    nosched_tail    : 11;    /**< - when nosched_val is set, indicates the last entry on the nosched list. */
1114         uint64_t    des_val         : 1;    /**< - set when there is one or more descheduled heads on the descheduled list selected by qosgrp. */
1115         uint64_t    des_one         : 1;    /**< - set when there is exactly one descheduled head on the descheduled list selected by qosgrp. */
1116         uint64_t    reserved_23     : 1;
1117         uint64_t    des_head        : 11;    /**< - when des_val is set, indicates the first descheduled head on the descheduled list selected by qosgrp. */
1118         uint64_t    reserved_11     : 1;
1119         uint64_t    des_tail        : 11;    /**< - when des_val is set, indicates the last descheduled head on the descheduled list selected by qosgrp. */
1120 #else
1121         uint64_t    des_tail        : 11;
1122         uint64_t    reserved_11     : 1;
1123         uint64_t    des_head        : 11;
1124         uint64_t    reserved_23     : 1;
1125         uint64_t    des_one         : 1;
1126         uint64_t    des_val         : 1;
1127         uint64_t    nosched_tail    : 11;
1128         uint64_t    reserved_37     : 1;
1129         uint64_t    nosched_head    : 11;
1130         uint64_t    reserved_49     : 1;
1131         uint64_t    nosched_one     : 1;
1132         uint64_t    nosched_val     : 1;
1133         uint64_t    reserved_52_63  : 12;
1134 #endif
1135     } sindexload1;
1136
1137     /**
1138      * Result for SSO Index/Pointer Load(opcode == IPL_FREE0/IPL_FREE1/IPL_FREE2)
1139      */
1140     struct
1141     {
1142 #ifdef __BIG_ENDIAN_BITFIELD
1143         uint64_t    reserved_60_63  : 4;
1144         uint64_t    qnum_head       : 2;    /**< - Subqueue with current head */
1145         uint64_t    qnum_tail       : 2;    /**< - Subqueue with current tail */
1146         uint64_t    reserved_28_55  : 28;
1147         uint64_t    queue_val       : 1;    /**< - If set, one or more valid entries are in the queue. */
1148         uint64_t    queue_one       : 1;    /**< - If set, exactly one valid entry is in the queue. */
1149         uint64_t    reserved_24_25  : 2;
1150         uint64_t    queue_head      : 11;   /**< - Index of entry at the head of the queue. */
1151         uint64_t    reserved_11_12  : 2;
1152         uint64_t    queue_tail      : 11;   /**< - Index of entry at the tail of the queue. */
1153 #else
1154         uint64_t    queue_tail      : 11;
1155         uint64_t    reserved_11_12  : 2;
1156         uint64_t    queue_head      : 11;
1157         uint64_t    reserved_24_25  : 2;
1158         uint64_t    queue_one       : 1;
1159         uint64_t    queue_val       : 1;
1160         uint64_t    reserved_28_55  : 28;
1161         uint64_t    qnum_tail       : 2;
1162         uint64_t    qnum_head       : 2;
1163         uint64_t    reserved_60_63  : 4;
1164 #endif
1165     } sindexload1_cn68xx;
1166
1167     /**
1168      * Result For POW Index/Pointer Load (get_rmt == 1/get_des_get_tail == 0)
1169      */
1170     struct
1171     {
1172 #ifdef __BIG_ENDIAN_BITFIELD
1173         uint64_t    reserved_39_63  : 25;
1174         uint64_t    rmt_is_head     : 1;    /**< Set when this DRAM list is the current head (i.e. is the next to
1175                                                 be reloaded when the POW hardware reloads a POW entry from DRAM). The
1176                                                 POW hardware alternates between the two DRAM lists associated with a QOS
1177                                                 level when it reloads work from DRAM into the POW unit. */
1178         uint64_t    rmt_val         : 1;    /**< Set when the DRAM portion of the input Q list selected by qosgrp
1179                                                 contains one or more pieces of work. */
1180         uint64_t    rmt_one         : 1;    /**< Set when the DRAM portion of the input Q list selected by qosgrp
1181                                                 contains exactly one piece of work. */
1182         uint64_t    rmt_head        : 36;   /**< When rmt_val is set, indicates the first piece of work on the
1183                                                 DRAM input Q list selected by qosgrp. */
1184 #else
1185         uint64_t    rmt_head        : 36;
1186         uint64_t    rmt_one         : 1;
1187         uint64_t    rmt_val         : 1;
1188         uint64_t    rmt_is_head     : 1;
1189         uint64_t    reserved_39_63  : 25;
1190 #endif
1191     } sindexload2;
1192
1193     /**
1194      * Result For POW Index/Pointer Load (get_rmt == 1/get_des_get_tail == 1)
1195      */
1196     struct
1197     {
1198 #ifdef __BIG_ENDIAN_BITFIELD
1199         uint64_t    reserved_39_63  : 25;
1200         uint64_t    rmt_is_head     : 1;    /**< - set when this DRAM list is the current head (i.e. is the next to
1201                                                 be reloaded when the POW hardware reloads a POW entry from DRAM). The
1202                                                 POW hardware alternates between the two DRAM lists associated with a QOS
1203                                                 level when it reloads work from DRAM into the POW unit. */
1204         uint64_t    rmt_val         : 1;    /**< - set when the DRAM portion of the input Q list selected by qosgrp
1205                                                 contains one or more pieces of work. */
1206         uint64_t    rmt_one         : 1;    /**< - set when the DRAM portion of the input Q list selected by qosgrp
1207                                                 contains exactly one piece of work. */
1208         uint64_t    rmt_tail        : 36;   /**< - when rmt_val is set, indicates the last piece of work on the DRAM
1209                                                 input Q list selected by qosgrp. */
1210 #else
1211         uint64_t    rmt_tail        : 36;
1212         uint64_t    rmt_one         : 1;
1213         uint64_t    rmt_val         : 1;
1214         uint64_t    rmt_is_head     : 1;
1215         uint64_t    reserved_39_63  : 25;
1216 #endif
1217     } sindexload3;
1218
1219     /**
1220      * Response to NULL_RD request loads
1221      */
1222     struct
1223     {
1224 #ifdef __BIG_ENDIAN_BITFIELD
1225         uint64_t    unused  : 62;
1226         uint64_t    state    : 2;  /**< of type cvmx_pow_tag_type_t. state is one of the following:
1227                                         - CVMX_POW_TAG_TYPE_ORDERED
1228                                         - CVMX_POW_TAG_TYPE_ATOMIC
1229                                         - CVMX_POW_TAG_TYPE_NULL
1230                                         - CVMX_POW_TAG_TYPE_NULL_NULL */
1231 #else
1232         uint64_t    state    : 2;
1233         uint64_t    unused  : 62;
1234 #endif
1235     } s_null_rd;
1236
1237 } cvmx_pow_tag_load_resp_t;
1238
1239 typedef union {
1240     uint64_t u64;
1241     struct {
1242 #ifdef __BIG_ENDIAN_BITFIELD
1243         uint64_t    reserved_57_63  : 7;
1244         uint64_t    index           : 11;
1245         uint64_t    reserved_45     : 1;
1246         uint64_t    grp             : 6;
1247         uint64_t    head            : 1;
1248         uint64_t    tail            : 1;
1249         uint64_t    reserved_34_36  : 3;
1250         uint64_t    tag_type        : 2;
1251         uint64_t    tag             : 32;
1252 #else
1253         uint64_t    tag             : 32;
1254         uint64_t    tag_type        : 2;
1255         uint64_t    reserved_34_36  : 3;
1256         uint64_t    tail            : 1;
1257         uint64_t    head            : 1;
1258         uint64_t    grp             : 6;
1259         uint64_t    reserved_45     : 1;
1260         uint64_t    index           : 11;
1261         uint64_t    reserved_57_63  : 7;
1262 #endif
1263     } s;
1264 } cvmx_pow_sl_tag_resp_t;
1265
1266 /**
1267  * This structure describes the address used for stores to the POW.
1268  *  The store address is meaningful on stores to the POW.  The hardware assumes that an aligned
1269  *  64-bit store was used for all these stores.
1270  *  Note the assumption that the work queue entry is aligned on an 8-byte
1271  *  boundary (since the low-order 3 address bits must be zero).
1272  *  Note that not all fields are used by all operations.
1273  *
1274  *  NOTE: The following is the behavior of the pending switch bit at the PP
1275  *       for POW stores (i.e. when did<7:3> == 0xc)
1276  *     - did<2:0> == 0      => pending switch bit is set
1277  *     - did<2:0> == 1      => no affect on the pending switch bit
1278  *     - did<2:0> == 3      => pending switch bit is cleared
1279  *     - did<2:0> == 7      => no affect on the pending switch bit
1280  *     - did<2:0> == others => must not be used
1281  *     - No other loads/stores have an affect on the pending switch bit
1282  *     - The switch bus from POW can clear the pending switch bit
1283  *
1284  *  NOTE: did<2:0> == 2 is used by the HW for a special single-cycle ADDWQ command
1285  *  that only contains the pointer). SW must never use did<2:0> == 2.
1286  */
1287 typedef union
1288 {
1289     /**
1290      * Unsigned 64 bit integer representation of store address
1291      */
1292     uint64_t u64;
1293
1294     struct
1295     {
1296 #ifdef __BIG_ENDIAN_BITFIELD
1297         uint64_t    mem_reg         : 2;    /**< Memory region.  Should be CVMX_IO_SEG in most cases */
1298         uint64_t    reserved_49_61  : 13;   /**< Must be zero */
1299         uint64_t    is_io           : 1;    /**< Must be one */
1300         uint64_t    did             : 8;    /**< Device ID of POW.  Note that different sub-dids are used. */
1301         uint64_t    reserved_36_39  : 4;    /**< Must be zero */
1302         uint64_t    addr            : 36;   /**< Address field. addr<2:0> must be zero */
1303 #else
1304         uint64_t    addr            : 36;
1305         uint64_t    reserved_36_39  : 4;
1306         uint64_t    did             : 8;
1307         uint64_t    is_io           : 1;
1308         uint64_t    reserved_49_61  : 13;
1309         uint64_t    mem_reg         : 2;
1310 #endif
1311     } stag;
1312 } cvmx_pow_tag_store_addr_t;
1313
1314 /**
1315  * decode of the store data when an IOBDMA SENDSINGLE is sent to POW
1316  */
1317 typedef union
1318 {
1319     uint64_t u64;
1320
1321     struct
1322     {
1323 #ifdef __BIG_ENDIAN_BITFIELD
1324         uint64_t    scraddr : 8;    /**< the (64-bit word) location in scratchpad to write to (if len != 0) */
1325         uint64_t    len     : 8;    /**< the number of words in the response (0 => no response) */
1326         uint64_t    did     : 8;    /**< the ID of the device on the non-coherent bus */
1327         uint64_t    unused  :36;
1328         uint64_t    wait    : 1;    /**< if set, don't return load response until work is available */
1329         uint64_t    unused2 : 3;
1330 #else
1331         uint64_t    unused2 : 3;
1332         uint64_t    wait    : 1;
1333         uint64_t    unused  :36;
1334         uint64_t    did     : 8;
1335         uint64_t    len     : 8;
1336         uint64_t    scraddr : 8;
1337 #endif
1338     } s;
1339
1340 } cvmx_pow_iobdma_store_t;
1341
1342
1343 /* CSR typedefs have been moved to cvmx-pow-defs.h */
1344
1345 /**
1346  * Get the POW tag for this core. This returns the current
1347  * tag type, tag, group, and POW entry index associated with
1348  * this core. Index is only valid if the tag type isn't NULL_NULL.
1349  * If a tag switch is pending this routine returns the tag before
1350  * the tag switch, not after.
1351  *
1352  * @return Current tag
1353  */
1354 static inline cvmx_pow_tag_info_t cvmx_pow_get_current_tag(void)
1355 {
1356     cvmx_pow_load_addr_t load_addr;
1357     cvmx_pow_tag_info_t result;
1358
1359     if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE)) {
1360         cvmx_pow_sl_tag_resp_t load_resp;
1361         load_addr.u64 = 0;
1362         load_addr.sstatus_cn68xx.mem_region = CVMX_IO_SEG;
1363         load_addr.sstatus_cn68xx.is_io = 1;
1364         load_addr.sstatus_cn68xx.did = CVMX_OCT_DID_TAG_TAG5;
1365         load_addr.sstatus_cn68xx.coreid = cvmx_get_core_num();
1366         load_addr.sstatus_cn68xx.opcode = 3;
1367         load_resp.u64 = cvmx_read_csr(load_addr.u64);
1368         result.grp = load_resp.s.grp;
1369         result.index = load_resp.s.index;
1370         result.tag_type = load_resp.s.tag_type;
1371         result.tag = load_resp.s.tag;
1372     } else {
1373         cvmx_pow_tag_load_resp_t load_resp;
1374         load_addr.u64 = 0;
1375         load_addr.sstatus.mem_region = CVMX_IO_SEG;
1376         load_addr.sstatus.is_io = 1;
1377         load_addr.sstatus.did = CVMX_OCT_DID_TAG_TAG1;
1378         load_addr.sstatus.coreid = cvmx_get_core_num();
1379         load_addr.sstatus.get_cur = 1;
1380         load_resp.u64 = cvmx_read_csr(load_addr.u64);
1381         result.grp = load_resp.s_sstatus2.grp;
1382         result.index = load_resp.s_sstatus2.index;
1383         result.tag_type = load_resp.s_sstatus2.tag_type;
1384         result.tag = load_resp.s_sstatus2.tag;
1385     }
1386     return result;
1387 }
1388
1389 /**
1390  * Get the POW WQE for this core. This returns the work queue
1391  * entry currently associated with this core.
1392  *
1393  * @return WQE pointer
1394  */
1395 static inline cvmx_wqe_t *cvmx_pow_get_current_wqp(void)
1396 {
1397     cvmx_pow_load_addr_t load_addr;
1398     cvmx_pow_tag_load_resp_t load_resp;
1399
1400     if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE)) {
1401         load_addr.u64 = 0;
1402         load_addr.sstatus_cn68xx.mem_region = CVMX_IO_SEG;
1403         load_addr.sstatus_cn68xx.is_io = 1;
1404         load_addr.sstatus_cn68xx.did = CVMX_OCT_DID_TAG_TAG5;
1405         load_addr.sstatus_cn68xx.coreid = cvmx_get_core_num();
1406         load_addr.sstatus_cn68xx.opcode = 3;
1407         load_resp.u64 = cvmx_read_csr(load_addr.u64);
1408         if (load_resp.s_sstatus3_cn68xx.wqp)
1409             return (cvmx_wqe_t*)cvmx_phys_to_ptr(load_resp.s_sstatus3_cn68xx.wqp);
1410         else
1411             return (cvmx_wqe_t*)0;
1412     } else {
1413         load_addr.u64 = 0;
1414         load_addr.sstatus.mem_region = CVMX_IO_SEG;
1415         load_addr.sstatus.is_io = 1;
1416         load_addr.sstatus.did = CVMX_OCT_DID_TAG_TAG1;
1417         load_addr.sstatus.coreid = cvmx_get_core_num();
1418         load_addr.sstatus.get_cur = 1;
1419         load_addr.sstatus.get_wqp = 1;
1420         load_resp.u64 = cvmx_read_csr(load_addr.u64);
1421         return (cvmx_wqe_t*)cvmx_phys_to_ptr(load_resp.s_sstatus4.wqp);
1422     }
1423 }
1424
1425
1426 /**
1427  * @INTERNAL
1428  * Print a warning if a tag switch is pending for this core
1429  *
1430  * @param function Function name checking for a pending tag switch
1431  */
1432 static inline void __cvmx_pow_warn_if_pending_switch(const char *function)
1433 {
1434     uint64_t switch_complete;
1435     CVMX_MF_CHORD(switch_complete);
1436     cvmx_warn_if(!switch_complete, "%s called with tag switch in progress\n", function);
1437 }
1438
1439
1440 /**
1441  * Waits for a tag switch to complete by polling the completion bit.
1442  * Note that switches to NULL complete immediately and do not need
1443  * to be waited for.
1444  */
1445 static inline void cvmx_pow_tag_sw_wait(void)
1446 {
1447     const uint64_t MAX_CYCLES = 1ull<<31;
1448     uint64_t switch_complete;
1449     uint64_t start_cycle = cvmx_get_cycle();
1450     while (1)
1451     {
1452         CVMX_MF_CHORD(switch_complete);
1453         if (cvmx_unlikely(switch_complete))
1454             break;
1455         if (cvmx_unlikely(cvmx_get_cycle() > start_cycle + MAX_CYCLES))
1456         {
1457             cvmx_dprintf("WARNING: Tag switch is taking a long time, possible deadlock\n");
1458             start_cycle = -MAX_CYCLES-1;
1459         }
1460     }
1461 }
1462
1463
1464 /**
1465  * Synchronous work request.  Requests work from the POW.
1466  * This function does NOT wait for previous tag switches to complete,
1467  * so the caller must ensure that there is not a pending tag switch.
1468  *
1469  * @param wait   When set, call stalls until work becomes avaiable, or times out.
1470  *               If not set, returns immediately.
1471  *
1472  * @return Returns the WQE pointer from POW. Returns NULL if no work was available.
1473  */
1474 static inline cvmx_wqe_t * cvmx_pow_work_request_sync_nocheck(cvmx_pow_wait_t wait)
1475 {
1476     cvmx_pow_load_addr_t ptr;
1477     cvmx_pow_tag_load_resp_t result;
1478
1479     if (CVMX_ENABLE_POW_CHECKS)
1480         __cvmx_pow_warn_if_pending_switch(__FUNCTION__);
1481
1482     ptr.u64 = 0;
1483     ptr.swork.mem_region = CVMX_IO_SEG;
1484     ptr.swork.is_io = 1;
1485     ptr.swork.did = CVMX_OCT_DID_TAG_SWTAG;
1486     ptr.swork.wait = wait;
1487
1488     result.u64 = cvmx_read_csr(ptr.u64);
1489
1490     if (result.s_work.no_work)
1491         return NULL;
1492     else
1493         return (cvmx_wqe_t*)cvmx_phys_to_ptr(result.s_work.addr);
1494 }
1495
1496
1497 /**
1498  * Synchronous work request.  Requests work from the POW.
1499  * This function waits for any previous tag switch to complete before
1500  * requesting the new work.
1501  *
1502  * @param wait   When set, call stalls until work becomes avaiable, or times out.
1503  *               If not set, returns immediately.
1504  *
1505  * @return Returns the WQE pointer from POW. Returns NULL if no work was available.
1506  */
1507 static inline cvmx_wqe_t * cvmx_pow_work_request_sync(cvmx_pow_wait_t wait)
1508 {
1509     if (CVMX_ENABLE_POW_CHECKS)
1510         __cvmx_pow_warn_if_pending_switch(__FUNCTION__);
1511
1512     /* Must not have a switch pending when requesting work */
1513     cvmx_pow_tag_sw_wait();
1514     return(cvmx_pow_work_request_sync_nocheck(wait));
1515
1516 }
1517
1518
1519 /**
1520  * Synchronous null_rd request.  Requests a switch out of NULL_NULL POW state.
1521  * This function waits for any previous tag switch to complete before
1522  * requesting the null_rd.
1523  *
1524  * @return Returns the POW state of type cvmx_pow_tag_type_t.
1525  */
1526 static inline cvmx_pow_tag_type_t cvmx_pow_work_request_null_rd(void)
1527 {
1528     cvmx_pow_load_addr_t ptr;
1529     cvmx_pow_tag_load_resp_t result;
1530
1531     if (CVMX_ENABLE_POW_CHECKS)
1532         __cvmx_pow_warn_if_pending_switch(__FUNCTION__);
1533
1534     /* Must not have a switch pending when requesting work */
1535     cvmx_pow_tag_sw_wait();
1536
1537     ptr.u64 = 0;
1538     ptr.snull_rd.mem_region = CVMX_IO_SEG;
1539     ptr.snull_rd.is_io = 1;
1540     ptr.snull_rd.did = CVMX_OCT_DID_TAG_NULL_RD;
1541
1542     result.u64 = cvmx_read_csr(ptr.u64);
1543
1544     return (cvmx_pow_tag_type_t)result.s_null_rd.state;
1545 }
1546
1547
1548 /**
1549  * Asynchronous work request.  Work is requested from the POW unit, and should later
1550  * be checked with function cvmx_pow_work_response_async.
1551  * This function does NOT wait for previous tag switches to complete,
1552  * so the caller must ensure that there is not a pending tag switch.
1553  *
1554  * @param scr_addr Scratch memory address that response will be returned to,
1555  *                  which is either a valid WQE, or a response with the invalid bit set.
1556  *                  Byte address, must be 8 byte aligned.
1557  * @param wait      1 to cause response to wait for work to become available (or timeout)
1558  *                  0 to cause response to return immediately
1559  */
1560 static inline void cvmx_pow_work_request_async_nocheck(int scr_addr, cvmx_pow_wait_t wait)
1561 {
1562     cvmx_pow_iobdma_store_t data;
1563
1564     if (CVMX_ENABLE_POW_CHECKS)
1565         __cvmx_pow_warn_if_pending_switch(__FUNCTION__);
1566
1567     /* scr_addr must be 8 byte aligned */
1568     data.u64 = 0;
1569     data.s.scraddr = scr_addr >> 3;
1570     data.s.len = 1;
1571     data.s.did = CVMX_OCT_DID_TAG_SWTAG;
1572     data.s.wait = wait;
1573     cvmx_send_single(data.u64);
1574 }
1575 /**
1576  * Asynchronous work request.  Work is requested from the POW unit, and should later
1577  * be checked with function cvmx_pow_work_response_async.
1578  * This function waits for any previous tag switch to complete before
1579  * requesting the new work.
1580  *
1581  * @param scr_addr Scratch memory address that response will be returned to,
1582  *                  which is either a valid WQE, or a response with the invalid bit set.
1583  *                  Byte address, must be 8 byte aligned.
1584  * @param wait      1 to cause response to wait for work to become available (or timeout)
1585  *                  0 to cause response to return immediately
1586  */
1587 static inline void cvmx_pow_work_request_async(int scr_addr, cvmx_pow_wait_t wait)
1588 {
1589     if (CVMX_ENABLE_POW_CHECKS)
1590         __cvmx_pow_warn_if_pending_switch(__FUNCTION__);
1591
1592     /* Must not have a switch pending when requesting work */
1593     cvmx_pow_tag_sw_wait();
1594     cvmx_pow_work_request_async_nocheck(scr_addr, wait);
1595 }
1596
1597
1598 /**
1599  * Gets result of asynchronous work request.  Performs a IOBDMA sync
1600  * to wait for the response.
1601  *
1602  * @param scr_addr Scratch memory address to get result from
1603  *                  Byte address, must be 8 byte aligned.
1604  * @return Returns the WQE from the scratch register, or NULL if no work was available.
1605  */
1606 static inline cvmx_wqe_t * cvmx_pow_work_response_async(int scr_addr)
1607 {
1608     cvmx_pow_tag_load_resp_t result;
1609
1610     CVMX_SYNCIOBDMA;
1611     result.u64 = cvmx_scratch_read64(scr_addr);
1612
1613     if (result.s_work.no_work)
1614         return NULL;
1615     else
1616         return (cvmx_wqe_t*)cvmx_phys_to_ptr(result.s_work.addr);
1617 }
1618
1619
1620 /**
1621  * Checks if a work queue entry pointer returned by a work
1622  * request is valid.  It may be invalid due to no work
1623  * being available or due to a timeout.
1624  *
1625  * @param wqe_ptr pointer to a work queue entry returned by the POW
1626  *
1627  * @return 0 if pointer is valid
1628  *         1 if invalid (no work was returned)
1629  */
1630 static inline uint64_t cvmx_pow_work_invalid(cvmx_wqe_t *wqe_ptr)
1631 {
1632     return (wqe_ptr == NULL);
1633 }
1634
1635
1636
1637 /**
1638  * Starts a tag switch to the provided tag value and tag type.  Completion for
1639  * the tag switch must be checked for separately.
1640  * This function does NOT update the
1641  * work queue entry in dram to match tag value and type, so the application must
1642  * keep track of these if they are important to the application.
1643  * This tag switch command must not be used for switches to NULL, as the tag
1644  * switch pending bit will be set by the switch request, but never cleared by the
1645  * hardware.
1646  *
1647  * NOTE: This should not be used when switching from a NULL tag.  Use
1648  * cvmx_pow_tag_sw_full() instead.
1649  *
1650  * This function does no checks, so the caller must ensure that any previous tag
1651  * switch has completed.
1652  *
1653  * @param tag      new tag value
1654  * @param tag_type new tag type (ordered or atomic)
1655  */
1656 static inline void cvmx_pow_tag_sw_nocheck(uint32_t tag, cvmx_pow_tag_type_t tag_type)
1657 {
1658     cvmx_addr_t ptr;
1659     cvmx_pow_tag_req_t tag_req;
1660
1661     if (CVMX_ENABLE_POW_CHECKS)
1662     {
1663         cvmx_pow_tag_info_t current_tag;
1664         __cvmx_pow_warn_if_pending_switch(__FUNCTION__);
1665         current_tag = cvmx_pow_get_current_tag();
1666         cvmx_warn_if(current_tag.tag_type == CVMX_POW_TAG_TYPE_NULL_NULL, "%s called with NULL_NULL tag\n", __FUNCTION__);
1667         cvmx_warn_if(current_tag.tag_type == CVMX_POW_TAG_TYPE_NULL, "%s called with NULL tag\n", __FUNCTION__);
1668         cvmx_warn_if((current_tag.tag_type == tag_type) && (current_tag.tag == tag), "%s called to perform a tag switch to the same tag\n", __FUNCTION__);
1669         cvmx_warn_if(tag_type == CVMX_POW_TAG_TYPE_NULL, "%s called to perform a tag switch to NULL. Use cvmx_pow_tag_sw_null() instead\n", __FUNCTION__);
1670     }
1671
1672     /* Note that WQE in DRAM is not updated here, as the POW does not read from DRAM
1673     ** once the WQE is in flight.  See hardware manual for complete details.
1674     ** It is the application's responsibility to keep track of the current tag
1675     ** value if that is important.
1676     */
1677
1678     tag_req.u64 = 0;
1679     if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE)) {
1680         tag_req.s_cn68xx_other.op = CVMX_POW_TAG_OP_SWTAG;
1681         tag_req.s_cn68xx_other.tag = tag;
1682         tag_req.s_cn68xx_other.type = tag_type;
1683     } else {
1684         tag_req.s_cn38xx.op = CVMX_POW_TAG_OP_SWTAG;
1685         tag_req.s_cn38xx.tag = tag;
1686         tag_req.s_cn38xx.type = tag_type;
1687     }
1688
1689     ptr.u64 = 0;
1690     ptr.sio.mem_region = CVMX_IO_SEG;
1691     ptr.sio.is_io = 1;
1692     ptr.sio.did = CVMX_OCT_DID_TAG_SWTAG;
1693
1694     /* once this store arrives at POW, it will attempt the switch
1695        software must wait for the switch to complete separately */
1696     cvmx_write_io(ptr.u64, tag_req.u64);
1697 }
1698
1699
1700 /**
1701  * Starts a tag switch to the provided tag value and tag type.  Completion for
1702  * the tag switch must be checked for separately.
1703  * This function does NOT update the
1704  * work queue entry in dram to match tag value and type, so the application must
1705  * keep track of these if they are important to the application.
1706  * This tag switch command must not be used for switches to NULL, as the tag
1707  * switch pending bit will be set by the switch request, but never cleared by the
1708  * hardware.
1709  *
1710  * NOTE: This should not be used when switching from a NULL tag.  Use
1711  * cvmx_pow_tag_sw_full() instead.
1712  *
1713  * This function waits for any previous tag switch to complete, and also
1714  * displays an error on tag switches to NULL.
1715  *
1716  * @param tag      new tag value
1717  * @param tag_type new tag type (ordered or atomic)
1718  */
1719 static inline void cvmx_pow_tag_sw(uint32_t tag, cvmx_pow_tag_type_t tag_type)
1720 {
1721     if (CVMX_ENABLE_POW_CHECKS)
1722         __cvmx_pow_warn_if_pending_switch(__FUNCTION__);
1723
1724     /* Note that WQE in DRAM is not updated here, as the POW does not read from DRAM
1725     ** once the WQE is in flight.  See hardware manual for complete details.
1726     ** It is the application's responsibility to keep track of the current tag
1727     ** value if that is important.
1728     */
1729
1730     /* Ensure that there is not a pending tag switch, as a tag switch cannot be started
1731     ** if a previous switch is still pending.  */
1732     cvmx_pow_tag_sw_wait();
1733     cvmx_pow_tag_sw_nocheck(tag, tag_type);
1734 }
1735
1736
1737 /**
1738  * Starts a tag switch to the provided tag value and tag type.  Completion for
1739  * the tag switch must be checked for separately.
1740  * This function does NOT update the
1741  * work queue entry in dram to match tag value and type, so the application must
1742  * keep track of these if they are important to the application.
1743  * This tag switch command must not be used for switches to NULL, as the tag
1744  * switch pending bit will be set by the switch request, but never cleared by the
1745  * hardware.
1746  *
1747  * This function must be used for tag switches from NULL.
1748  *
1749  * This function does no checks, so the caller must ensure that any previous tag
1750  * switch has completed.
1751  *
1752  * @param wqp      pointer to work queue entry to submit.  This entry is updated to match the other parameters
1753  * @param tag      tag value to be assigned to work queue entry
1754  * @param tag_type type of tag
1755  * @param group      group value for the work queue entry.
1756  */
1757 static inline void cvmx_pow_tag_sw_full_nocheck(cvmx_wqe_t *wqp, uint32_t tag, cvmx_pow_tag_type_t tag_type, uint64_t group)
1758 {
1759     cvmx_addr_t ptr;
1760     cvmx_pow_tag_req_t tag_req;
1761
1762     if (CVMX_ENABLE_POW_CHECKS)
1763     {
1764         cvmx_pow_tag_info_t current_tag;
1765         __cvmx_pow_warn_if_pending_switch(__FUNCTION__);
1766         current_tag = cvmx_pow_get_current_tag();
1767         cvmx_warn_if(current_tag.tag_type == CVMX_POW_TAG_TYPE_NULL_NULL, "%s called with NULL_NULL tag\n", __FUNCTION__);
1768         cvmx_warn_if((current_tag.tag_type == tag_type) && (current_tag.tag == tag), "%s called to perform a tag switch to the same tag\n", __FUNCTION__);
1769         cvmx_warn_if(tag_type == CVMX_POW_TAG_TYPE_NULL, "%s called to perform a tag switch to NULL. Use cvmx_pow_tag_sw_null() instead\n", __FUNCTION__);
1770         if ((wqp != cvmx_phys_to_ptr(0x80)) && cvmx_pow_get_current_wqp())
1771             cvmx_warn_if(wqp != cvmx_pow_get_current_wqp(), "%s passed WQE(%p) doesn't match the address in the POW(%p)\n", __FUNCTION__, wqp, cvmx_pow_get_current_wqp());
1772     }
1773
1774     /* Note that WQE in DRAM is not updated here, as the POW does not read from DRAM
1775     ** once the WQE is in flight.  See hardware manual for complete details.
1776     ** It is the application's responsibility to keep track of the current tag
1777     ** value if that is important.
1778     */
1779
1780     tag_req.u64 = 0;
1781     if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE)) {
1782         tag_req.s_cn68xx_other.op = CVMX_POW_TAG_OP_SWTAG_FULL;
1783         tag_req.s_cn68xx_other.tag = tag;
1784         tag_req.s_cn68xx_other.type = tag_type;
1785         tag_req.s_cn68xx_other.grp = group;
1786     } else {
1787         tag_req.s_cn38xx.op = CVMX_POW_TAG_OP_SWTAG_FULL;
1788         tag_req.s_cn38xx.tag = tag;
1789         tag_req.s_cn38xx.type = tag_type;
1790         tag_req.s_cn38xx.grp = group;
1791     }
1792
1793     ptr.u64 = 0;
1794     ptr.sio.mem_region = CVMX_IO_SEG;
1795     ptr.sio.is_io = 1;
1796     ptr.sio.did = CVMX_OCT_DID_TAG_SWTAG;
1797     ptr.sio.offset = CAST64(wqp);
1798
1799     /* once this store arrives at POW, it will attempt the switch
1800        software must wait for the switch to complete separately */
1801     cvmx_write_io(ptr.u64, tag_req.u64);
1802 }
1803
1804
1805 /**
1806  * Starts a tag switch to the provided tag value and tag type.  Completion for
1807  * the tag switch must be checked for separately.
1808  * This function does NOT update the
1809  * work queue entry in dram to match tag value and type, so the application must
1810  * keep track of these if they are important to the application.
1811  * This tag switch command must not be used for switches to NULL, as the tag
1812  * switch pending bit will be set by the switch request, but never cleared by the
1813  * hardware.
1814  *
1815  * This function must be used for tag switches from NULL.
1816  *
1817  * This function waits for any pending tag switches to complete
1818  * before requesting the tag switch.
1819  *
1820  * @param wqp      pointer to work queue entry to submit.  This entry is updated to match the other parameters
1821  * @param tag      tag value to be assigned to work queue entry
1822  * @param tag_type type of tag
1823  * @param group      group value for the work queue entry.
1824  */
1825 static inline void cvmx_pow_tag_sw_full(cvmx_wqe_t *wqp, uint32_t tag, cvmx_pow_tag_type_t tag_type, uint64_t group)
1826 {
1827     if (CVMX_ENABLE_POW_CHECKS)
1828         __cvmx_pow_warn_if_pending_switch(__FUNCTION__);
1829
1830     /* Ensure that there is not a pending tag switch, as a tag switch cannot be started
1831     ** if a previous switch is still pending.  */
1832     cvmx_pow_tag_sw_wait();
1833     cvmx_pow_tag_sw_full_nocheck(wqp, tag, tag_type, group);
1834 }
1835
1836
1837 /**
1838  * Switch to a NULL tag, which ends any ordering or
1839  * synchronization provided by the POW for the current
1840  * work queue entry.  This operation completes immediately,
1841  * so completion should not be waited for.
1842  * This function does NOT wait for previous tag switches to complete,
1843  * so the caller must ensure that any previous tag switches have completed.
1844  */
1845 static inline void cvmx_pow_tag_sw_null_nocheck(void)
1846 {
1847     cvmx_addr_t ptr;
1848     cvmx_pow_tag_req_t tag_req;
1849
1850     if (CVMX_ENABLE_POW_CHECKS)
1851     {
1852         cvmx_pow_tag_info_t current_tag;
1853         __cvmx_pow_warn_if_pending_switch(__FUNCTION__);
1854         current_tag = cvmx_pow_get_current_tag();
1855         cvmx_warn_if(current_tag.tag_type == CVMX_POW_TAG_TYPE_NULL_NULL, "%s called with NULL_NULL tag\n", __FUNCTION__);
1856         cvmx_warn_if(current_tag.tag_type == CVMX_POW_TAG_TYPE_NULL, "%s called when we already have a NULL tag\n", __FUNCTION__);
1857     }
1858
1859     tag_req.u64 = 0;
1860     if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE)) {
1861         tag_req.s_cn68xx_other.op = CVMX_POW_TAG_OP_SWTAG;
1862         tag_req.s_cn68xx_other.type = CVMX_POW_TAG_TYPE_NULL;
1863     } else {
1864         tag_req.s_cn38xx.op = CVMX_POW_TAG_OP_SWTAG;
1865         tag_req.s_cn38xx.type = CVMX_POW_TAG_TYPE_NULL;
1866     }
1867
1868
1869     ptr.u64 = 0;
1870     ptr.sio.mem_region = CVMX_IO_SEG;
1871     ptr.sio.is_io = 1;
1872     ptr.sio.did = CVMX_OCT_DID_TAG_TAG1;
1873
1874
1875     cvmx_write_io(ptr.u64, tag_req.u64);
1876
1877     /* switch to NULL completes immediately */
1878 }
1879
1880 /**
1881  * Switch to a NULL tag, which ends any ordering or
1882  * synchronization provided by the POW for the current
1883  * work queue entry.  This operation completes immediatly,
1884  * so completion should not be waited for.
1885  * This function waits for any pending tag switches to complete
1886  * before requesting the switch to NULL.
1887  */
1888 static inline void cvmx_pow_tag_sw_null(void)
1889 {
1890     if (CVMX_ENABLE_POW_CHECKS)
1891         __cvmx_pow_warn_if_pending_switch(__FUNCTION__);
1892
1893     /* Ensure that there is not a pending tag switch, as a tag switch cannot be started
1894     ** if a previous switch is still pending.  */
1895     cvmx_pow_tag_sw_wait();
1896     cvmx_pow_tag_sw_null_nocheck();
1897
1898     /* switch to NULL completes immediately */
1899 }
1900
1901
1902
1903 /**
1904  * Submits work to an input queue.  This function updates the work queue entry in DRAM to match
1905  * the arguments given.
1906  * Note that the tag provided is for the work queue entry submitted, and is unrelated to the tag that
1907  * the core currently holds.
1908  *
1909  * @param wqp      pointer to work queue entry to submit.  This entry is updated to match the other parameters
1910  * @param tag      tag value to be assigned to work queue entry
1911  * @param tag_type type of tag
1912  * @param qos      Input queue to add to.
1913  * @param grp      group value for the work queue entry.
1914  */
1915 static inline void cvmx_pow_work_submit(cvmx_wqe_t *wqp, uint32_t tag, cvmx_pow_tag_type_t tag_type, uint64_t qos, uint64_t grp)
1916 {
1917     cvmx_addr_t ptr;
1918     cvmx_pow_tag_req_t tag_req;
1919
1920     tag_req.u64 = 0;
1921
1922     wqp->word1.s.tag = tag;
1923     wqp->word1.s.tag_type = tag_type;
1924
1925     if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE)) {
1926         /* Reset all reserved bits */
1927         wqp->word1.cn68xx.zero_0 = 0;
1928         wqp->word1.cn68xx.zero_1 = 0;
1929         wqp->word1.cn68xx.zero_2 = 0;
1930         wqp->word1.cn68xx.qos = qos;
1931         wqp->word1.cn68xx.grp = grp;
1932
1933         tag_req.s_cn68xx_add.op = CVMX_POW_TAG_OP_ADDWQ;
1934         tag_req.s_cn68xx_add.type = tag_type;
1935         tag_req.s_cn68xx_add.tag = tag;
1936         tag_req.s_cn68xx_add.qos = qos;
1937         tag_req.s_cn68xx_add.grp = grp;
1938     } else {
1939         /* Reset all reserved bits */
1940         wqp->word1.cn38xx.zero_2 = 0;
1941         wqp->word1.cn38xx.qos = qos;
1942         wqp->word1.cn38xx.grp = grp;
1943
1944         tag_req.s_cn38xx.op = CVMX_POW_TAG_OP_ADDWQ;
1945         tag_req.s_cn38xx.type = tag_type;
1946         tag_req.s_cn38xx.tag = tag;
1947         tag_req.s_cn38xx.qos = qos;
1948         tag_req.s_cn38xx.grp = grp;
1949     }
1950
1951     ptr.u64 = 0;
1952     ptr.sio.mem_region = CVMX_IO_SEG;
1953     ptr.sio.is_io = 1;
1954     ptr.sio.did = CVMX_OCT_DID_TAG_TAG1;
1955     ptr.sio.offset = cvmx_ptr_to_phys(wqp);
1956
1957     /* SYNC write to memory before the work submit.  This is necessary
1958     ** as POW may read values from DRAM at this time */
1959     CVMX_SYNCWS;
1960     cvmx_write_io(ptr.u64, tag_req.u64);
1961 }
1962
1963
1964
1965 /**
1966  * This function sets the group mask for a core.  The group mask
1967  * indicates which groups each core will accept work from. There are
1968  * 16 groups.
1969  *
1970  * @param core_num   core to apply mask to
1971  * @param mask   Group mask. There are 16 groups, so only bits 0-15 are valid,
1972  *               representing groups 0-15.
1973  *               Each 1 bit in the mask enables the core to accept work from
1974  *               the corresponding group.
1975  */
1976 static inline void cvmx_pow_set_group_mask(uint64_t core_num, uint64_t mask)
1977 {
1978
1979     if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE))
1980     {
1981         cvmx_sso_ppx_grp_msk_t grp_msk;
1982         grp_msk.s.grp_msk = mask;
1983         cvmx_write_csr(CVMX_SSO_PPX_GRP_MSK(core_num), grp_msk.u64);
1984     }
1985     else
1986     {
1987         cvmx_pow_pp_grp_mskx_t grp_msk;
1988         grp_msk.u64 = cvmx_read_csr(CVMX_POW_PP_GRP_MSKX(core_num));
1989         grp_msk.s.grp_msk = mask;
1990         cvmx_write_csr(CVMX_POW_PP_GRP_MSKX(core_num), grp_msk.u64);
1991     }
1992 }
1993
1994 /**
1995  * This function sets POW static priorities for a core. Each input queue has
1996  * an associated priority value.
1997  *
1998  * @param core_num   core to apply priorities to
1999  * @param priority   Vector of 8 priorities, one per POW Input Queue (0-7).
2000  *                   Highest priority is 0 and lowest is 7. A priority value
2001  *                   of 0xF instructs POW to skip the Input Queue when
2002  *                   scheduling to this specific core.
2003  *                   NOTE: priorities should not have gaps in values, meaning
2004  *                         {0,1,1,1,1,1,1,1} is a valid configuration while
2005  *                         {0,2,2,2,2,2,2,2} is not.
2006  */
2007 static inline void cvmx_pow_set_priority(uint64_t core_num, const uint8_t priority[])
2008 {
2009     if (OCTEON_IS_MODEL(OCTEON_CN3XXX))
2010         return;
2011
2012     /* Detect gaps between priorities and flag error */
2013     {
2014         int i;
2015         uint32_t prio_mask = 0;
2016
2017         for(i=0; i<8; i++)
2018             if (priority[i] != 0xF)
2019                 prio_mask |= 1<<priority[i];
2020
2021         if ( prio_mask ^ ((1<<cvmx_pop(prio_mask)) - 1))
2022         {
2023             cvmx_dprintf("ERROR: POW static priorities should be contiguous (0x%llx)\n", (unsigned long long)prio_mask);
2024             return;
2025         }
2026     }
2027
2028     /* POW priorities are supported on CN5xxx and later */
2029     if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE))
2030     {
2031         cvmx_sso_ppx_qos_pri_t qos_pri;
2032
2033         qos_pri.u64 = cvmx_read_csr(CVMX_SSO_PPX_QOS_PRI(core_num));
2034         qos_pri.s.qos0_pri = priority[0]; 
2035         qos_pri.s.qos1_pri = priority[1]; 
2036         qos_pri.s.qos2_pri = priority[2]; 
2037         qos_pri.s.qos3_pri = priority[3]; 
2038         qos_pri.s.qos4_pri = priority[4]; 
2039         qos_pri.s.qos5_pri = priority[5]; 
2040         qos_pri.s.qos6_pri = priority[6]; 
2041         qos_pri.s.qos7_pri = priority[7]; 
2042         cvmx_write_csr(CVMX_SSO_PPX_QOS_PRI(core_num), qos_pri.u64);
2043     }
2044     else
2045     {
2046         cvmx_pow_pp_grp_mskx_t grp_msk;
2047
2048         grp_msk.u64 = cvmx_read_csr(CVMX_POW_PP_GRP_MSKX(core_num));
2049         grp_msk.s.qos0_pri = priority[0];
2050         grp_msk.s.qos1_pri = priority[1];
2051         grp_msk.s.qos2_pri = priority[2];
2052         grp_msk.s.qos3_pri = priority[3];
2053         grp_msk.s.qos4_pri = priority[4];
2054         grp_msk.s.qos5_pri = priority[5];
2055         grp_msk.s.qos6_pri = priority[6];
2056         grp_msk.s.qos7_pri = priority[7];
2057
2058         cvmx_write_csr(CVMX_POW_PP_GRP_MSKX(core_num), grp_msk.u64);
2059     }
2060 }
2061
2062 /**
2063  * Performs a tag switch and then an immediate deschedule. This completes
2064  * immediately, so completion must not be waited for.  This function does NOT
2065  * update the wqe in DRAM to match arguments.
2066  *
2067  * This function does NOT wait for any prior tag switches to complete, so the
2068  * calling code must do this.
2069  *
2070  * Note the following CAVEAT of the Octeon HW behavior when
2071  * re-scheduling DE-SCHEDULEd items whose (next) state is
2072  * ORDERED:
2073  *   - If there are no switches pending at the time that the
2074  *     HW executes the de-schedule, the HW will only re-schedule
2075  *     the head of the FIFO associated with the given tag. This
2076  *     means that in many respects, the HW treats this ORDERED
2077  *     tag as an ATOMIC tag. Note that in the SWTAG_DESCH
2078  *     case (to an ORDERED tag), the HW will do the switch
2079  *     before the deschedule whenever it is possible to do
2080  *     the switch immediately, so it may often look like
2081  *     this case.
2082  *   - If there is a pending switch to ORDERED at the time
2083  *     the HW executes the de-schedule, the HW will perform
2084  *     the switch at the time it re-schedules, and will be
2085  *     able to reschedule any/all of the entries with the
2086  *     same tag.
2087  * Due to this behavior, the RECOMMENDATION to software is
2088  * that they have a (next) state of ATOMIC when they
2089  * DE-SCHEDULE. If an ORDERED tag is what was really desired,
2090  * SW can choose to immediately switch to an ORDERED tag
2091  * after the work (that has an ATOMIC tag) is re-scheduled.
2092  * Note that since there are never any tag switches pending
2093  * when the HW re-schedules, this switch can be IMMEDIATE upon
2094  * the reception of the pointer during the re-schedule.
2095  *
2096  * @param tag      New tag value
2097  * @param tag_type New tag type
2098  * @param group    New group value
2099  * @param no_sched Control whether this work queue entry will be rescheduled.
2100  *                 - 1 : don't schedule this work
2101  *                 - 0 : allow this work to be scheduled.
2102  */
2103 static inline void cvmx_pow_tag_sw_desched_nocheck(uint32_t tag, cvmx_pow_tag_type_t tag_type, uint64_t group, uint64_t no_sched)
2104 {
2105     cvmx_addr_t ptr;
2106     cvmx_pow_tag_req_t tag_req;
2107
2108     if (CVMX_ENABLE_POW_CHECKS)
2109     {
2110         cvmx_pow_tag_info_t current_tag;
2111         __cvmx_pow_warn_if_pending_switch(__FUNCTION__);
2112         current_tag = cvmx_pow_get_current_tag();
2113         cvmx_warn_if(current_tag.tag_type == CVMX_POW_TAG_TYPE_NULL_NULL, "%s called with NULL_NULL tag\n", __FUNCTION__);
2114         cvmx_warn_if(current_tag.tag_type == CVMX_POW_TAG_TYPE_NULL, "%s called with NULL tag. Deschedule not allowed from NULL state\n", __FUNCTION__);
2115         cvmx_warn_if((current_tag.tag_type != CVMX_POW_TAG_TYPE_ATOMIC) && (tag_type != CVMX_POW_TAG_TYPE_ATOMIC), "%s called where neither the before or after tag is ATOMIC\n", __FUNCTION__);
2116     }
2117
2118     tag_req.u64 = 0;
2119     if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE)) {
2120         tag_req.s_cn68xx_other.op = CVMX_POW_TAG_OP_SWTAG_DESCH;
2121         tag_req.s_cn68xx_other.tag = tag;
2122         tag_req.s_cn68xx_other.type = tag_type;
2123         tag_req.s_cn68xx_other.grp = group;
2124         tag_req.s_cn68xx_other.no_sched = no_sched;
2125     } else {
2126         tag_req.s_cn38xx.op = CVMX_POW_TAG_OP_SWTAG_DESCH;
2127         tag_req.s_cn38xx.tag = tag;
2128         tag_req.s_cn38xx.type = tag_type;
2129         tag_req.s_cn38xx.grp = group;
2130         tag_req.s_cn38xx.no_sched = no_sched;
2131     }
2132
2133     ptr.u64 = 0;
2134     ptr.sio.mem_region = CVMX_IO_SEG;
2135     ptr.sio.is_io = 1;
2136     ptr.sio.did = CVMX_OCT_DID_TAG_TAG3;
2137
2138     cvmx_write_io(ptr.u64, tag_req.u64); /* since TAG3 is used, this store will clear the local pending switch bit */
2139 }
2140 /**
2141  * Performs a tag switch and then an immediate deschedule. This completes
2142  * immediately, so completion must not be waited for.  This function does NOT
2143  * update the wqe in DRAM to match arguments.
2144  *
2145  * This function waits for any prior tag switches to complete, so the
2146  * calling code may call this function with a pending tag switch.
2147  *
2148  * Note the following CAVEAT of the Octeon HW behavior when
2149  * re-scheduling DE-SCHEDULEd items whose (next) state is
2150  * ORDERED:
2151  *   - If there are no switches pending at the time that the
2152  *     HW executes the de-schedule, the HW will only re-schedule
2153  *     the head of the FIFO associated with the given tag. This
2154  *     means that in many respects, the HW treats this ORDERED
2155  *     tag as an ATOMIC tag. Note that in the SWTAG_DESCH
2156  *     case (to an ORDERED tag), the HW will do the switch
2157  *     before the deschedule whenever it is possible to do
2158  *     the switch immediately, so it may often look like
2159  *     this case.
2160  *   - If there is a pending switch to ORDERED at the time
2161  *     the HW executes the de-schedule, the HW will perform
2162  *     the switch at the time it re-schedules, and will be
2163  *     able to reschedule any/all of the entries with the
2164  *     same tag.
2165  * Due to this behavior, the RECOMMENDATION to software is
2166  * that they have a (next) state of ATOMIC when they
2167  * DE-SCHEDULE. If an ORDERED tag is what was really desired,
2168  * SW can choose to immediately switch to an ORDERED tag
2169  * after the work (that has an ATOMIC tag) is re-scheduled.
2170  * Note that since there are never any tag switches pending
2171  * when the HW re-schedules, this switch can be IMMEDIATE upon
2172  * the reception of the pointer during the re-schedule.
2173  *
2174  * @param tag      New tag value
2175  * @param tag_type New tag type
2176  * @param group    New group value
2177  * @param no_sched Control whether this work queue entry will be rescheduled.
2178  *                 - 1 : don't schedule this work
2179  *                 - 0 : allow this work to be scheduled.
2180  */
2181 static inline void cvmx_pow_tag_sw_desched(uint32_t tag, cvmx_pow_tag_type_t tag_type, uint64_t group, uint64_t no_sched)
2182 {
2183     if (CVMX_ENABLE_POW_CHECKS)
2184         __cvmx_pow_warn_if_pending_switch(__FUNCTION__);
2185
2186     /* Need to make sure any writes to the work queue entry are complete */
2187     CVMX_SYNCWS;
2188     /* Ensure that there is not a pending tag switch, as a tag switch cannot be started
2189     ** if a previous switch is still pending.  */
2190     cvmx_pow_tag_sw_wait();
2191     cvmx_pow_tag_sw_desched_nocheck(tag, tag_type, group, no_sched);
2192 }
2193
2194
2195
2196
2197
2198 /**
2199  * Descchedules the current work queue entry.
2200  *
2201  * @param no_sched no schedule flag value to be set on the work queue entry.  If this is set
2202  *                 the entry will not be rescheduled.
2203  */
2204 static inline void cvmx_pow_desched(uint64_t no_sched)
2205 {
2206     cvmx_addr_t ptr;
2207     cvmx_pow_tag_req_t tag_req;
2208
2209     if (CVMX_ENABLE_POW_CHECKS)
2210     {
2211         cvmx_pow_tag_info_t current_tag;
2212         __cvmx_pow_warn_if_pending_switch(__FUNCTION__);
2213         current_tag = cvmx_pow_get_current_tag();
2214         cvmx_warn_if(current_tag.tag_type == CVMX_POW_TAG_TYPE_NULL_NULL, "%s called with NULL_NULL tag\n", __FUNCTION__);
2215         cvmx_warn_if(current_tag.tag_type == CVMX_POW_TAG_TYPE_NULL, "%s called with NULL tag. Deschedule not expected from NULL state\n", __FUNCTION__);
2216     }
2217
2218     /* Need to make sure any writes to the work queue entry are complete */
2219     CVMX_SYNCWS;
2220
2221     tag_req.u64 = 0;
2222     if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE)) {
2223         tag_req.s_cn68xx_other.op = CVMX_POW_TAG_OP_DESCH;
2224         tag_req.s_cn68xx_other.no_sched = no_sched;
2225     } else {
2226         tag_req.s_cn38xx.op = CVMX_POW_TAG_OP_DESCH;
2227         tag_req.s_cn38xx.no_sched = no_sched;
2228     }
2229
2230     ptr.u64 = 0;
2231     ptr.sio.mem_region = CVMX_IO_SEG;
2232     ptr.sio.is_io = 1;
2233     ptr.sio.did = CVMX_OCT_DID_TAG_TAG3;
2234
2235     cvmx_write_io(ptr.u64, tag_req.u64); /* since TAG3 is used, this store will clear the local pending switch bit */
2236 }
2237
2238
2239
2240
2241
2242
2243
2244 /***********************************************************************************************
2245 ** Define usage of bits within the 32 bit tag values.
2246 ***********************************************************************************************/
2247
2248 /*
2249  * Number of bits of the tag used by software.  The SW bits
2250  * are always a contiguous block of the high starting at bit 31.
2251  * The hardware bits are always the low bits.  By default, the top 8 bits
2252  * of the tag are reserved for software, and the low 24 are set by the IPD unit.
2253  */
2254 #define CVMX_TAG_SW_BITS    (8)
2255 #define CVMX_TAG_SW_SHIFT   (32 - CVMX_TAG_SW_BITS)
2256
2257 /* Below is the list of values for the top 8 bits of the tag. */
2258 #define CVMX_TAG_SW_BITS_INTERNAL  0x1  /* Tag values with top byte of this value are reserved for internal executive uses */
2259 /* The executive divides the remaining 24 bits as follows:
2260 **  * the upper 8 bits (bits 23 - 16 of the tag) define a subgroup
2261 **  * the lower 16 bits (bits 15 - 0 of the tag) define are the value with the subgroup
2262 ** Note that this section describes the format of tags generated by software - refer to the
2263 ** hardware documentation for a description of the tags values generated by the packet input
2264 ** hardware.
2265 ** Subgroups are defined here */
2266 #define CVMX_TAG_SUBGROUP_MASK  0xFFFF /* Mask for the value portion of the tag */
2267 #define CVMX_TAG_SUBGROUP_SHIFT 16
2268 #define CVMX_TAG_SUBGROUP_PKO  0x1
2269
2270
2271 /* End of executive tag subgroup definitions */
2272
2273 /* The remaining values software bit values 0x2 - 0xff are available for application use */
2274
2275
2276
2277 /**
2278  * This function creates a 32 bit tag value from the two values provided.
2279  *
2280  * @param sw_bits The upper bits (number depends on configuration) are set to this value.  The remainder of
2281  *                bits are set by the hw_bits parameter.
2282  * @param hw_bits The lower bits (number depends on configuration) are set to this value.  The remainder of
2283  *                bits are set by the sw_bits parameter.
2284  *
2285  * @return 32 bit value of the combined hw and sw bits.
2286  */
2287 static inline uint32_t cvmx_pow_tag_compose(uint64_t sw_bits, uint64_t hw_bits)
2288 {
2289     return((((sw_bits & cvmx_build_mask(CVMX_TAG_SW_BITS)) << CVMX_TAG_SW_SHIFT) | (hw_bits & cvmx_build_mask(32 - CVMX_TAG_SW_BITS))));
2290 }
2291 /**
2292  * Extracts the bits allocated for software use from the tag
2293  *
2294  * @param tag    32 bit tag value
2295  *
2296  * @return N bit software tag value, where N is configurable with the CVMX_TAG_SW_BITS define
2297  */
2298 static inline uint32_t cvmx_pow_tag_get_sw_bits(uint64_t tag)
2299 {
2300     return((tag >> (32 - CVMX_TAG_SW_BITS)) & cvmx_build_mask(CVMX_TAG_SW_BITS));
2301 }
2302 /**
2303  *
2304  * Extracts the bits allocated for hardware use from the tag
2305  *
2306  * @param tag    32 bit tag value
2307  *
2308  * @return (32 - N) bit software tag value, where N is configurable with the CVMX_TAG_SW_BITS define
2309  */
2310 static inline uint32_t cvmx_pow_tag_get_hw_bits(uint64_t tag)
2311 {
2312     return(tag & cvmx_build_mask(32 - CVMX_TAG_SW_BITS));
2313 }
2314
2315 /**
2316  * Store the current POW internal state into the supplied
2317  * buffer. It is recommended that you pass a buffer of at least
2318  * 128KB. The format of the capture may change based on SDK
2319  * version and Octeon chip.
2320  *
2321  * @param buffer Buffer to store capture into
2322  * @param buffer_size
2323  *               The size of the supplied buffer
2324  *
2325  * @return Zero on sucess, negative on failure
2326  */
2327 extern int cvmx_pow_capture(void *buffer, int buffer_size);
2328
2329 /**
2330  * Dump a POW capture to the console in a human readable format.
2331  *
2332  * @param buffer POW capture from cvmx_pow_capture()
2333  * @param buffer_size
2334  *               Size of the buffer
2335  */
2336 extern void cvmx_pow_display(void *buffer, int buffer_size);
2337
2338 /**
2339  * Return the number of POW entries supported by this chip
2340  *
2341  * @return Number of POW entries
2342  */
2343 extern int cvmx_pow_get_num_entries(void);
2344
2345
2346 #ifdef  __cplusplus
2347 }
2348 #endif
2349
2350 #endif  /* __CVMX_POW_H__ */