162306a36Sopenharmony_ci/***********************license start***************
262306a36Sopenharmony_ci * Author: Cavium Networks
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Contact: support@caviumnetworks.com
562306a36Sopenharmony_ci * This file is part of the OCTEON SDK
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Copyright (c) 2003-2008 Cavium Networks
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * This file is free software; you can redistribute it and/or modify
1062306a36Sopenharmony_ci * it under the terms of the GNU General Public License, Version 2, as
1162306a36Sopenharmony_ci * published by the Free Software Foundation.
1262306a36Sopenharmony_ci *
1362306a36Sopenharmony_ci * This file is distributed in the hope that it will be useful, but
1462306a36Sopenharmony_ci * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
1562306a36Sopenharmony_ci * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
1662306a36Sopenharmony_ci * NONINFRINGEMENT.  See the GNU General Public License for more
1762306a36Sopenharmony_ci * details.
1862306a36Sopenharmony_ci *
1962306a36Sopenharmony_ci * You should have received a copy of the GNU General Public License
2062306a36Sopenharmony_ci * along with this file; if not, write to the Free Software
2162306a36Sopenharmony_ci * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2262306a36Sopenharmony_ci * or visit http://www.gnu.org/licenses/.
2362306a36Sopenharmony_ci *
2462306a36Sopenharmony_ci * This file may also be available under a different license from Cavium.
2562306a36Sopenharmony_ci * Contact Cavium Networks for more information
2662306a36Sopenharmony_ci ***********************license end**************************************/
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci/**
2962306a36Sopenharmony_ci * Interface to the hardware Packet Order / Work unit.
3062306a36Sopenharmony_ci *
3162306a36Sopenharmony_ci * New, starting with SDK 1.7.0, cvmx-pow supports a number of
3262306a36Sopenharmony_ci * extended consistency checks. The define
3362306a36Sopenharmony_ci * CVMX_ENABLE_POW_CHECKS controls the runtime insertion of POW
3462306a36Sopenharmony_ci * internal state checks to find common programming errors. If
3562306a36Sopenharmony_ci * CVMX_ENABLE_POW_CHECKS is not defined, checks are by default
3662306a36Sopenharmony_ci * enabled. For example, cvmx-pow will check for the following
3762306a36Sopenharmony_ci * program errors or POW state inconsistency.
3862306a36Sopenharmony_ci * - Requesting a POW operation with an active tag switch in
3962306a36Sopenharmony_ci *   progress.
4062306a36Sopenharmony_ci * - Waiting for a tag switch to complete for an excessively
4162306a36Sopenharmony_ci *   long period. This is normally a sign of an error in locking
4262306a36Sopenharmony_ci *   causing deadlock.
4362306a36Sopenharmony_ci * - Illegal tag switches from NULL_NULL.
4462306a36Sopenharmony_ci * - Illegal tag switches from NULL.
4562306a36Sopenharmony_ci * - Illegal deschedule request.
4662306a36Sopenharmony_ci * - WQE pointer not matching the one attached to the core by
4762306a36Sopenharmony_ci *   the POW.
4862306a36Sopenharmony_ci *
4962306a36Sopenharmony_ci */
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci#ifndef __CVMX_POW_H__
5262306a36Sopenharmony_ci#define __CVMX_POW_H__
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci#include <asm/octeon/cvmx-pow-defs.h>
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci#include <asm/octeon/cvmx-scratch.h>
5762306a36Sopenharmony_ci#include <asm/octeon/cvmx-wqe.h>
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci/* Default to having all POW constancy checks turned on */
6062306a36Sopenharmony_ci#ifndef CVMX_ENABLE_POW_CHECKS
6162306a36Sopenharmony_ci#define CVMX_ENABLE_POW_CHECKS 1
6262306a36Sopenharmony_ci#endif
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_cienum cvmx_pow_tag_type {
6562306a36Sopenharmony_ci	/* Tag ordering is maintained */
6662306a36Sopenharmony_ci	CVMX_POW_TAG_TYPE_ORDERED   = 0L,
6762306a36Sopenharmony_ci	/* Tag ordering is maintained, and at most one PP has the tag */
6862306a36Sopenharmony_ci	CVMX_POW_TAG_TYPE_ATOMIC    = 1L,
6962306a36Sopenharmony_ci	/*
7062306a36Sopenharmony_ci	 * The work queue entry from the order - NEVER tag switch from
7162306a36Sopenharmony_ci	 * NULL to NULL
7262306a36Sopenharmony_ci	 */
7362306a36Sopenharmony_ci	CVMX_POW_TAG_TYPE_NULL	    = 2L,
7462306a36Sopenharmony_ci	/* A tag switch to NULL, and there is no space reserved in POW
7562306a36Sopenharmony_ci	 * - NEVER tag switch to NULL_NULL
7662306a36Sopenharmony_ci	 * - NEVER tag switch from NULL_NULL
7762306a36Sopenharmony_ci	 * - NULL_NULL is entered at the beginning of time and on a deschedule.
7862306a36Sopenharmony_ci	 * - NULL_NULL can be exited by a new work request. A NULL_SWITCH
7962306a36Sopenharmony_ci	 * load can also switch the state to NULL
8062306a36Sopenharmony_ci	 */
8162306a36Sopenharmony_ci	CVMX_POW_TAG_TYPE_NULL_NULL = 3L
8262306a36Sopenharmony_ci};
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci/**
8562306a36Sopenharmony_ci * Wait flag values for pow functions.
8662306a36Sopenharmony_ci */
8762306a36Sopenharmony_citypedef enum {
8862306a36Sopenharmony_ci	CVMX_POW_WAIT = 1,
8962306a36Sopenharmony_ci	CVMX_POW_NO_WAIT = 0,
9062306a36Sopenharmony_ci} cvmx_pow_wait_t;
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci/**
9362306a36Sopenharmony_ci *  POW tag operations.	 These are used in the data stored to the POW.
9462306a36Sopenharmony_ci */
9562306a36Sopenharmony_citypedef enum {
9662306a36Sopenharmony_ci	/*
9762306a36Sopenharmony_ci	 * switch the tag (only) for this PP
9862306a36Sopenharmony_ci	 * - the previous tag should be non-NULL in this case
9962306a36Sopenharmony_ci	 * - tag switch response required
10062306a36Sopenharmony_ci	 * - fields used: op, type, tag
10162306a36Sopenharmony_ci	 */
10262306a36Sopenharmony_ci	CVMX_POW_TAG_OP_SWTAG = 0L,
10362306a36Sopenharmony_ci	/*
10462306a36Sopenharmony_ci	 * switch the tag for this PP, with full information
10562306a36Sopenharmony_ci	 * - this should be used when the previous tag is NULL
10662306a36Sopenharmony_ci	 * - tag switch response required
10762306a36Sopenharmony_ci	 * - fields used: address, op, grp, type, tag
10862306a36Sopenharmony_ci	 */
10962306a36Sopenharmony_ci	CVMX_POW_TAG_OP_SWTAG_FULL = 1L,
11062306a36Sopenharmony_ci	/*
11162306a36Sopenharmony_ci	 * switch the tag (and/or group) for this PP and de-schedule
11262306a36Sopenharmony_ci	 * - OK to keep the tag the same and only change the group
11362306a36Sopenharmony_ci	 * - fields used: op, no_sched, grp, type, tag
11462306a36Sopenharmony_ci	 */
11562306a36Sopenharmony_ci	CVMX_POW_TAG_OP_SWTAG_DESCH = 2L,
11662306a36Sopenharmony_ci	/*
11762306a36Sopenharmony_ci	 * just de-schedule
11862306a36Sopenharmony_ci	 * - fields used: op, no_sched
11962306a36Sopenharmony_ci	 */
12062306a36Sopenharmony_ci	CVMX_POW_TAG_OP_DESCH = 3L,
12162306a36Sopenharmony_ci	/*
12262306a36Sopenharmony_ci	 * create an entirely new work queue entry
12362306a36Sopenharmony_ci	 * - fields used: address, op, qos, grp, type, tag
12462306a36Sopenharmony_ci	 */
12562306a36Sopenharmony_ci	CVMX_POW_TAG_OP_ADDWQ = 4L,
12662306a36Sopenharmony_ci	/*
12762306a36Sopenharmony_ci	 * just update the work queue pointer and grp for this PP
12862306a36Sopenharmony_ci	 * - fields used: address, op, grp
12962306a36Sopenharmony_ci	 */
13062306a36Sopenharmony_ci	CVMX_POW_TAG_OP_UPDATE_WQP_GRP = 5L,
13162306a36Sopenharmony_ci	/*
13262306a36Sopenharmony_ci	 * set the no_sched bit on the de-schedule list
13362306a36Sopenharmony_ci	 *
13462306a36Sopenharmony_ci	 * - does nothing if the selected entry is not on the
13562306a36Sopenharmony_ci	 *   de-schedule list
13662306a36Sopenharmony_ci	 *
13762306a36Sopenharmony_ci	 * - does nothing if the stored work queue pointer does not
13862306a36Sopenharmony_ci	 *   match the address field
13962306a36Sopenharmony_ci	 *
14062306a36Sopenharmony_ci	 * - fields used: address, index, op
14162306a36Sopenharmony_ci	 *
14262306a36Sopenharmony_ci	 *  Before issuing a *_NSCHED operation, SW must guarantee
14362306a36Sopenharmony_ci	 *  that all prior deschedules and set/clr NSCHED operations
14462306a36Sopenharmony_ci	 *  are complete and all prior switches are complete. The
14562306a36Sopenharmony_ci	 *  hardware provides the opsdone bit and swdone bit for SW
14662306a36Sopenharmony_ci	 *  polling. After issuing a *_NSCHED operation, SW must
14762306a36Sopenharmony_ci	 *  guarantee that the set/clr NSCHED is complete before any
14862306a36Sopenharmony_ci	 *  subsequent operations.
14962306a36Sopenharmony_ci	 */
15062306a36Sopenharmony_ci	CVMX_POW_TAG_OP_SET_NSCHED = 6L,
15162306a36Sopenharmony_ci	/*
15262306a36Sopenharmony_ci	 * clears the no_sched bit on the de-schedule list
15362306a36Sopenharmony_ci	 *
15462306a36Sopenharmony_ci	 * - does nothing if the selected entry is not on the
15562306a36Sopenharmony_ci	 *   de-schedule list
15662306a36Sopenharmony_ci	 *
15762306a36Sopenharmony_ci	 * - does nothing if the stored work queue pointer does not
15862306a36Sopenharmony_ci	 *   match the address field
15962306a36Sopenharmony_ci	 *
16062306a36Sopenharmony_ci	 * - fields used: address, index, op
16162306a36Sopenharmony_ci	 *
16262306a36Sopenharmony_ci	 * Before issuing a *_NSCHED operation, SW must guarantee that
16362306a36Sopenharmony_ci	 * all prior deschedules and set/clr NSCHED operations are
16462306a36Sopenharmony_ci	 * complete and all prior switches are complete. The hardware
16562306a36Sopenharmony_ci	 * provides the opsdone bit and swdone bit for SW
16662306a36Sopenharmony_ci	 * polling. After issuing a *_NSCHED operation, SW must
16762306a36Sopenharmony_ci	 * guarantee that the set/clr NSCHED is complete before any
16862306a36Sopenharmony_ci	 * subsequent operations.
16962306a36Sopenharmony_ci	 */
17062306a36Sopenharmony_ci	CVMX_POW_TAG_OP_CLR_NSCHED = 7L,
17162306a36Sopenharmony_ci	/* do nothing */
17262306a36Sopenharmony_ci	CVMX_POW_TAG_OP_NOP = 15L
17362306a36Sopenharmony_ci} cvmx_pow_tag_op_t;
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci/**
17662306a36Sopenharmony_ci * This structure defines the store data on a store to POW
17762306a36Sopenharmony_ci */
17862306a36Sopenharmony_citypedef union {
17962306a36Sopenharmony_ci	uint64_t u64;
18062306a36Sopenharmony_ci	struct {
18162306a36Sopenharmony_ci#ifdef __BIG_ENDIAN_BITFIELD
18262306a36Sopenharmony_ci		/*
18362306a36Sopenharmony_ci		 * Don't reschedule this entry. no_sched is used for
18462306a36Sopenharmony_ci		 * CVMX_POW_TAG_OP_SWTAG_DESCH and
18562306a36Sopenharmony_ci		 * CVMX_POW_TAG_OP_DESCH
18662306a36Sopenharmony_ci		 */
18762306a36Sopenharmony_ci		uint64_t no_sched:1;
18862306a36Sopenharmony_ci		uint64_t unused:2;
18962306a36Sopenharmony_ci		/* Tontains index of entry for a CVMX_POW_TAG_OP_*_NSCHED */
19062306a36Sopenharmony_ci		uint64_t index:13;
19162306a36Sopenharmony_ci		/* The operation to perform */
19262306a36Sopenharmony_ci		cvmx_pow_tag_op_t op:4;
19362306a36Sopenharmony_ci		uint64_t unused2:2;
19462306a36Sopenharmony_ci		/*
19562306a36Sopenharmony_ci		 * The QOS level for the packet. qos is only used for
19662306a36Sopenharmony_ci		 * CVMX_POW_TAG_OP_ADDWQ
19762306a36Sopenharmony_ci		 */
19862306a36Sopenharmony_ci		uint64_t qos:3;
19962306a36Sopenharmony_ci		/*
20062306a36Sopenharmony_ci		 * The group that the work queue entry will be
20162306a36Sopenharmony_ci		 * scheduled to grp is used for CVMX_POW_TAG_OP_ADDWQ,
20262306a36Sopenharmony_ci		 * CVMX_POW_TAG_OP_SWTAG_FULL,
20362306a36Sopenharmony_ci		 * CVMX_POW_TAG_OP_SWTAG_DESCH, and
20462306a36Sopenharmony_ci		 * CVMX_POW_TAG_OP_UPDATE_WQP_GRP
20562306a36Sopenharmony_ci		 */
20662306a36Sopenharmony_ci		uint64_t grp:4;
20762306a36Sopenharmony_ci		/*
20862306a36Sopenharmony_ci		 * The type of the tag. type is used for everything
20962306a36Sopenharmony_ci		 * except CVMX_POW_TAG_OP_DESCH,
21062306a36Sopenharmony_ci		 * CVMX_POW_TAG_OP_UPDATE_WQP_GRP, and
21162306a36Sopenharmony_ci		 * CVMX_POW_TAG_OP_*_NSCHED
21262306a36Sopenharmony_ci		 */
21362306a36Sopenharmony_ci		uint64_t type:3;
21462306a36Sopenharmony_ci		/*
21562306a36Sopenharmony_ci		 * The actual tag. tag is used for everything except
21662306a36Sopenharmony_ci		 * CVMX_POW_TAG_OP_DESCH,
21762306a36Sopenharmony_ci		 * CVMX_POW_TAG_OP_UPDATE_WQP_GRP, and
21862306a36Sopenharmony_ci		 * CVMX_POW_TAG_OP_*_NSCHED
21962306a36Sopenharmony_ci		 */
22062306a36Sopenharmony_ci		uint64_t tag:32;
22162306a36Sopenharmony_ci#else
22262306a36Sopenharmony_ci		uint64_t tag:32;
22362306a36Sopenharmony_ci		uint64_t type:3;
22462306a36Sopenharmony_ci		uint64_t grp:4;
22562306a36Sopenharmony_ci		uint64_t qos:3;
22662306a36Sopenharmony_ci		uint64_t unused2:2;
22762306a36Sopenharmony_ci		cvmx_pow_tag_op_t op:4;
22862306a36Sopenharmony_ci		uint64_t index:13;
22962306a36Sopenharmony_ci		uint64_t unused:2;
23062306a36Sopenharmony_ci		uint64_t no_sched:1;
23162306a36Sopenharmony_ci#endif
23262306a36Sopenharmony_ci	} s;
23362306a36Sopenharmony_ci} cvmx_pow_tag_req_t;
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci/**
23662306a36Sopenharmony_ci * This structure describes the address to load stuff from POW
23762306a36Sopenharmony_ci */
23862306a36Sopenharmony_citypedef union {
23962306a36Sopenharmony_ci	uint64_t u64;
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci    /**
24262306a36Sopenharmony_ci     * Address for new work request loads (did<2:0> == 0)
24362306a36Sopenharmony_ci     */
24462306a36Sopenharmony_ci	struct {
24562306a36Sopenharmony_ci#ifdef __BIG_ENDIAN_BITFIELD
24662306a36Sopenharmony_ci		/* Mips64 address region. Should be CVMX_IO_SEG */
24762306a36Sopenharmony_ci		uint64_t mem_region:2;
24862306a36Sopenharmony_ci		/* Must be zero */
24962306a36Sopenharmony_ci		uint64_t reserved_49_61:13;
25062306a36Sopenharmony_ci		/* Must be one */
25162306a36Sopenharmony_ci		uint64_t is_io:1;
25262306a36Sopenharmony_ci		/* the ID of POW -- did<2:0> == 0 in this case */
25362306a36Sopenharmony_ci		uint64_t did:8;
25462306a36Sopenharmony_ci		/* Must be zero */
25562306a36Sopenharmony_ci		uint64_t reserved_4_39:36;
25662306a36Sopenharmony_ci		/*
25762306a36Sopenharmony_ci		 * If set, don't return load response until work is
25862306a36Sopenharmony_ci		 * available.
25962306a36Sopenharmony_ci		 */
26062306a36Sopenharmony_ci		uint64_t wait:1;
26162306a36Sopenharmony_ci		/* Must be zero */
26262306a36Sopenharmony_ci		uint64_t reserved_0_2:3;
26362306a36Sopenharmony_ci#else
26462306a36Sopenharmony_ci		uint64_t reserved_0_2:3;
26562306a36Sopenharmony_ci		uint64_t wait:1;
26662306a36Sopenharmony_ci		uint64_t reserved_4_39:36;
26762306a36Sopenharmony_ci		uint64_t did:8;
26862306a36Sopenharmony_ci		uint64_t is_io:1;
26962306a36Sopenharmony_ci		uint64_t reserved_49_61:13;
27062306a36Sopenharmony_ci		uint64_t mem_region:2;
27162306a36Sopenharmony_ci#endif
27262306a36Sopenharmony_ci	} swork;
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci    /**
27562306a36Sopenharmony_ci     * Address for loads to get POW internal status
27662306a36Sopenharmony_ci     */
27762306a36Sopenharmony_ci	struct {
27862306a36Sopenharmony_ci#ifdef __BIG_ENDIAN_BITFIELD
27962306a36Sopenharmony_ci		/* Mips64 address region. Should be CVMX_IO_SEG */
28062306a36Sopenharmony_ci		uint64_t mem_region:2;
28162306a36Sopenharmony_ci		/* Must be zero */
28262306a36Sopenharmony_ci		uint64_t reserved_49_61:13;
28362306a36Sopenharmony_ci		/* Must be one */
28462306a36Sopenharmony_ci		uint64_t is_io:1;
28562306a36Sopenharmony_ci		/* the ID of POW -- did<2:0> == 1 in this case */
28662306a36Sopenharmony_ci		uint64_t did:8;
28762306a36Sopenharmony_ci		/* Must be zero */
28862306a36Sopenharmony_ci		uint64_t reserved_10_39:30;
28962306a36Sopenharmony_ci		/* The core id to get status for */
29062306a36Sopenharmony_ci		uint64_t coreid:4;
29162306a36Sopenharmony_ci		/*
29262306a36Sopenharmony_ci		 * If set and get_cur is set, return reverse tag-list
29362306a36Sopenharmony_ci		 * pointer rather than forward tag-list pointer.
29462306a36Sopenharmony_ci		 */
29562306a36Sopenharmony_ci		uint64_t get_rev:1;
29662306a36Sopenharmony_ci		/*
29762306a36Sopenharmony_ci		 * If set, return current status rather than pending
29862306a36Sopenharmony_ci		 * status.
29962306a36Sopenharmony_ci		 */
30062306a36Sopenharmony_ci		uint64_t get_cur:1;
30162306a36Sopenharmony_ci		/*
30262306a36Sopenharmony_ci		 * If set, get the work-queue pointer rather than
30362306a36Sopenharmony_ci		 * tag/type.
30462306a36Sopenharmony_ci		 */
30562306a36Sopenharmony_ci		uint64_t get_wqp:1;
30662306a36Sopenharmony_ci		/* Must be zero */
30762306a36Sopenharmony_ci		uint64_t reserved_0_2:3;
30862306a36Sopenharmony_ci#else
30962306a36Sopenharmony_ci		uint64_t reserved_0_2:3;
31062306a36Sopenharmony_ci		uint64_t get_wqp:1;
31162306a36Sopenharmony_ci		uint64_t get_cur:1;
31262306a36Sopenharmony_ci		uint64_t get_rev:1;
31362306a36Sopenharmony_ci		uint64_t coreid:4;
31462306a36Sopenharmony_ci		uint64_t reserved_10_39:30;
31562306a36Sopenharmony_ci		uint64_t did:8;
31662306a36Sopenharmony_ci		uint64_t is_io:1;
31762306a36Sopenharmony_ci		uint64_t reserved_49_61:13;
31862306a36Sopenharmony_ci		uint64_t mem_region:2;
31962306a36Sopenharmony_ci#endif
32062306a36Sopenharmony_ci	} sstatus;
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci    /**
32362306a36Sopenharmony_ci     * Address for memory loads to get POW internal state
32462306a36Sopenharmony_ci     */
32562306a36Sopenharmony_ci	struct {
32662306a36Sopenharmony_ci#ifdef __BIG_ENDIAN_BITFIELD
32762306a36Sopenharmony_ci		/* Mips64 address region. Should be CVMX_IO_SEG */
32862306a36Sopenharmony_ci		uint64_t mem_region:2;
32962306a36Sopenharmony_ci		/* Must be zero */
33062306a36Sopenharmony_ci		uint64_t reserved_49_61:13;
33162306a36Sopenharmony_ci		/* Must be one */
33262306a36Sopenharmony_ci		uint64_t is_io:1;
33362306a36Sopenharmony_ci		/* the ID of POW -- did<2:0> == 2 in this case */
33462306a36Sopenharmony_ci		uint64_t did:8;
33562306a36Sopenharmony_ci		/* Must be zero */
33662306a36Sopenharmony_ci		uint64_t reserved_16_39:24;
33762306a36Sopenharmony_ci		/* POW memory index */
33862306a36Sopenharmony_ci		uint64_t index:11;
33962306a36Sopenharmony_ci		/*
34062306a36Sopenharmony_ci		 * If set, return deschedule information rather than
34162306a36Sopenharmony_ci		 * the standard response for work-queue index (invalid
34262306a36Sopenharmony_ci		 * if the work-queue entry is not on the deschedule
34362306a36Sopenharmony_ci		 * list).
34462306a36Sopenharmony_ci		 */
34562306a36Sopenharmony_ci		uint64_t get_des:1;
34662306a36Sopenharmony_ci		/*
34762306a36Sopenharmony_ci		 * If set, get the work-queue pointer rather than
34862306a36Sopenharmony_ci		 * tag/type (no effect when get_des set).
34962306a36Sopenharmony_ci		 */
35062306a36Sopenharmony_ci		uint64_t get_wqp:1;
35162306a36Sopenharmony_ci		/* Must be zero */
35262306a36Sopenharmony_ci		uint64_t reserved_0_2:3;
35362306a36Sopenharmony_ci#else
35462306a36Sopenharmony_ci		uint64_t reserved_0_2:3;
35562306a36Sopenharmony_ci		uint64_t get_wqp:1;
35662306a36Sopenharmony_ci		uint64_t get_des:1;
35762306a36Sopenharmony_ci		uint64_t index:11;
35862306a36Sopenharmony_ci		uint64_t reserved_16_39:24;
35962306a36Sopenharmony_ci		uint64_t did:8;
36062306a36Sopenharmony_ci		uint64_t is_io:1;
36162306a36Sopenharmony_ci		uint64_t reserved_49_61:13;
36262306a36Sopenharmony_ci		uint64_t mem_region:2;
36362306a36Sopenharmony_ci#endif
36462306a36Sopenharmony_ci	} smemload;
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci    /**
36762306a36Sopenharmony_ci     * Address for index/pointer loads
36862306a36Sopenharmony_ci     */
36962306a36Sopenharmony_ci	struct {
37062306a36Sopenharmony_ci#ifdef __BIG_ENDIAN_BITFIELD
37162306a36Sopenharmony_ci		/* Mips64 address region. Should be CVMX_IO_SEG */
37262306a36Sopenharmony_ci		uint64_t mem_region:2;
37362306a36Sopenharmony_ci		/* Must be zero */
37462306a36Sopenharmony_ci		uint64_t reserved_49_61:13;
37562306a36Sopenharmony_ci		/* Must be one */
37662306a36Sopenharmony_ci		uint64_t is_io:1;
37762306a36Sopenharmony_ci		/* the ID of POW -- did<2:0> == 3 in this case */
37862306a36Sopenharmony_ci		uint64_t did:8;
37962306a36Sopenharmony_ci		/* Must be zero */
38062306a36Sopenharmony_ci		uint64_t reserved_9_39:31;
38162306a36Sopenharmony_ci		/*
38262306a36Sopenharmony_ci		 * when {get_rmt ==0 AND get_des_get_tail == 0}, this
38362306a36Sopenharmony_ci		 * field selects one of eight POW internal-input
38462306a36Sopenharmony_ci		 * queues (0-7), one per QOS level; values 8-15 are
38562306a36Sopenharmony_ci		 * illegal in this case; when {get_rmt ==0 AND
38662306a36Sopenharmony_ci		 * get_des_get_tail == 1}, this field selects one of
38762306a36Sopenharmony_ci		 * 16 deschedule lists (per group); when get_rmt ==1,
38862306a36Sopenharmony_ci		 * this field selects one of 16 memory-input queue
38962306a36Sopenharmony_ci		 * lists.  The two memory-input queue lists associated
39062306a36Sopenharmony_ci		 * with each QOS level are:
39162306a36Sopenharmony_ci		 *
39262306a36Sopenharmony_ci		 * - qosgrp = 0, qosgrp = 8:	  QOS0
39362306a36Sopenharmony_ci		 * - qosgrp = 1, qosgrp = 9:	  QOS1
39462306a36Sopenharmony_ci		 * - qosgrp = 2, qosgrp = 10:	  QOS2
39562306a36Sopenharmony_ci		 * - qosgrp = 3, qosgrp = 11:	  QOS3
39662306a36Sopenharmony_ci		 * - qosgrp = 4, qosgrp = 12:	  QOS4
39762306a36Sopenharmony_ci		 * - qosgrp = 5, qosgrp = 13:	  QOS5
39862306a36Sopenharmony_ci		 * - qosgrp = 6, qosgrp = 14:	  QOS6
39962306a36Sopenharmony_ci		 * - qosgrp = 7, qosgrp = 15:	  QOS7
40062306a36Sopenharmony_ci		 */
40162306a36Sopenharmony_ci		uint64_t qosgrp:4;
40262306a36Sopenharmony_ci		/*
40362306a36Sopenharmony_ci		 * If set and get_rmt is clear, return deschedule list
40462306a36Sopenharmony_ci		 * indexes rather than indexes for the specified qos
40562306a36Sopenharmony_ci		 * level; if set and get_rmt is set, return the tail
40662306a36Sopenharmony_ci		 * pointer rather than the head pointer for the
40762306a36Sopenharmony_ci		 * specified qos level.
40862306a36Sopenharmony_ci		 */
40962306a36Sopenharmony_ci		uint64_t get_des_get_tail:1;
41062306a36Sopenharmony_ci		/*
41162306a36Sopenharmony_ci		 * If set, return remote pointers rather than the
41262306a36Sopenharmony_ci		 * local indexes for the specified qos level.
41362306a36Sopenharmony_ci		 */
41462306a36Sopenharmony_ci		uint64_t get_rmt:1;
41562306a36Sopenharmony_ci		/* Must be zero */
41662306a36Sopenharmony_ci		uint64_t reserved_0_2:3;
41762306a36Sopenharmony_ci#else
41862306a36Sopenharmony_ci		uint64_t reserved_0_2:3;
41962306a36Sopenharmony_ci		uint64_t get_rmt:1;
42062306a36Sopenharmony_ci		uint64_t get_des_get_tail:1;
42162306a36Sopenharmony_ci		uint64_t qosgrp:4;
42262306a36Sopenharmony_ci		uint64_t reserved_9_39:31;
42362306a36Sopenharmony_ci		uint64_t did:8;
42462306a36Sopenharmony_ci		uint64_t is_io:1;
42562306a36Sopenharmony_ci		uint64_t reserved_49_61:13;
42662306a36Sopenharmony_ci		uint64_t mem_region:2;
42762306a36Sopenharmony_ci#endif
42862306a36Sopenharmony_ci	} sindexload;
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_ci    /**
43162306a36Sopenharmony_ci     * address for NULL_RD request (did<2:0> == 4) when this is read,
43262306a36Sopenharmony_ci     * HW attempts to change the state to NULL if it is NULL_NULL (the
43362306a36Sopenharmony_ci     * hardware cannot switch from NULL_NULL to NULL if a POW entry is
43462306a36Sopenharmony_ci     * not available - software may need to recover by finishing
43562306a36Sopenharmony_ci     * another piece of work before a POW entry can ever become
43662306a36Sopenharmony_ci     * available.)
43762306a36Sopenharmony_ci     */
43862306a36Sopenharmony_ci	struct {
43962306a36Sopenharmony_ci#ifdef __BIG_ENDIAN_BITFIELD
44062306a36Sopenharmony_ci		/* Mips64 address region. Should be CVMX_IO_SEG */
44162306a36Sopenharmony_ci		uint64_t mem_region:2;
44262306a36Sopenharmony_ci		/* Must be zero */
44362306a36Sopenharmony_ci		uint64_t reserved_49_61:13;
44462306a36Sopenharmony_ci		/* Must be one */
44562306a36Sopenharmony_ci		uint64_t is_io:1;
44662306a36Sopenharmony_ci		/* the ID of POW -- did<2:0> == 4 in this case */
44762306a36Sopenharmony_ci		uint64_t did:8;
44862306a36Sopenharmony_ci		/* Must be zero */
44962306a36Sopenharmony_ci		uint64_t reserved_0_39:40;
45062306a36Sopenharmony_ci#else
45162306a36Sopenharmony_ci		uint64_t reserved_0_39:40;
45262306a36Sopenharmony_ci		uint64_t did:8;
45362306a36Sopenharmony_ci		uint64_t is_io:1;
45462306a36Sopenharmony_ci		uint64_t reserved_49_61:13;
45562306a36Sopenharmony_ci		uint64_t mem_region:2;
45662306a36Sopenharmony_ci#endif
45762306a36Sopenharmony_ci	} snull_rd;
45862306a36Sopenharmony_ci} cvmx_pow_load_addr_t;
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci/**
46162306a36Sopenharmony_ci * This structure defines the response to a load/SENDSINGLE to POW
46262306a36Sopenharmony_ci * (except CSR reads)
46362306a36Sopenharmony_ci */
46462306a36Sopenharmony_citypedef union {
46562306a36Sopenharmony_ci	uint64_t u64;
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_ci    /**
46862306a36Sopenharmony_ci     * Response to new work request loads
46962306a36Sopenharmony_ci     */
47062306a36Sopenharmony_ci	struct {
47162306a36Sopenharmony_ci#ifdef __BIG_ENDIAN_BITFIELD
47262306a36Sopenharmony_ci		/*
47362306a36Sopenharmony_ci		 * Set when no new work queue entry was returned.  *
47462306a36Sopenharmony_ci		 * If there was de-scheduled work, the HW will
47562306a36Sopenharmony_ci		 * definitely return it. When this bit is set, it
47662306a36Sopenharmony_ci		 * could mean either mean:
47762306a36Sopenharmony_ci		 *
47862306a36Sopenharmony_ci		 * - There was no work, or
47962306a36Sopenharmony_ci		 *
48062306a36Sopenharmony_ci		 * - There was no work that the HW could find. This
48162306a36Sopenharmony_ci		 *   case can happen, regardless of the wait bit value
48262306a36Sopenharmony_ci		 *   in the original request, when there is work in
48362306a36Sopenharmony_ci		 *   the IQ's that is too deep down the list.
48462306a36Sopenharmony_ci		 */
48562306a36Sopenharmony_ci		uint64_t no_work:1;
48662306a36Sopenharmony_ci		/* Must be zero */
48762306a36Sopenharmony_ci		uint64_t reserved_40_62:23;
48862306a36Sopenharmony_ci		/* 36 in O1 -- the work queue pointer */
48962306a36Sopenharmony_ci		uint64_t addr:40;
49062306a36Sopenharmony_ci#else
49162306a36Sopenharmony_ci		uint64_t addr:40;
49262306a36Sopenharmony_ci		uint64_t reserved_40_62:23;
49362306a36Sopenharmony_ci		uint64_t no_work:1;
49462306a36Sopenharmony_ci#endif
49562306a36Sopenharmony_ci	} s_work;
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_ci    /**
49862306a36Sopenharmony_ci     * Result for a POW Status Load (when get_cur==0 and get_wqp==0)
49962306a36Sopenharmony_ci     */
50062306a36Sopenharmony_ci	struct {
50162306a36Sopenharmony_ci#ifdef __BIG_ENDIAN_BITFIELD
50262306a36Sopenharmony_ci		uint64_t reserved_62_63:2;
50362306a36Sopenharmony_ci		/* Set when there is a pending non-NULL SWTAG or
50462306a36Sopenharmony_ci		 * SWTAG_FULL, and the POW entry has not left the list
50562306a36Sopenharmony_ci		 * for the original tag. */
50662306a36Sopenharmony_ci		uint64_t pend_switch:1;
50762306a36Sopenharmony_ci		/* Set when SWTAG_FULL and pend_switch is set. */
50862306a36Sopenharmony_ci		uint64_t pend_switch_full:1;
50962306a36Sopenharmony_ci		/*
51062306a36Sopenharmony_ci		 * Set when there is a pending NULL SWTAG, or an
51162306a36Sopenharmony_ci		 * implicit switch to NULL.
51262306a36Sopenharmony_ci		 */
51362306a36Sopenharmony_ci		uint64_t pend_switch_null:1;
51462306a36Sopenharmony_ci		/* Set when there is a pending DESCHED or SWTAG_DESCHED. */
51562306a36Sopenharmony_ci		uint64_t pend_desched:1;
51662306a36Sopenharmony_ci		/*
51762306a36Sopenharmony_ci		 * Set when there is a pending SWTAG_DESCHED and
51862306a36Sopenharmony_ci		 * pend_desched is set.
51962306a36Sopenharmony_ci		 */
52062306a36Sopenharmony_ci		uint64_t pend_desched_switch:1;
52162306a36Sopenharmony_ci		/* Set when nosched is desired and pend_desched is set. */
52262306a36Sopenharmony_ci		uint64_t pend_nosched:1;
52362306a36Sopenharmony_ci		/* Set when there is a pending GET_WORK. */
52462306a36Sopenharmony_ci		uint64_t pend_new_work:1;
52562306a36Sopenharmony_ci		/*
52662306a36Sopenharmony_ci		 * When pend_new_work is set, this bit indicates that
52762306a36Sopenharmony_ci		 * the wait bit was set.
52862306a36Sopenharmony_ci		 */
52962306a36Sopenharmony_ci		uint64_t pend_new_work_wait:1;
53062306a36Sopenharmony_ci		/* Set when there is a pending NULL_RD. */
53162306a36Sopenharmony_ci		uint64_t pend_null_rd:1;
53262306a36Sopenharmony_ci		/* Set when there is a pending CLR_NSCHED. */
53362306a36Sopenharmony_ci		uint64_t pend_nosched_clr:1;
53462306a36Sopenharmony_ci		uint64_t reserved_51:1;
53562306a36Sopenharmony_ci		/* This is the index when pend_nosched_clr is set. */
53662306a36Sopenharmony_ci		uint64_t pend_index:11;
53762306a36Sopenharmony_ci		/*
53862306a36Sopenharmony_ci		 * This is the new_grp when (pend_desched AND
53962306a36Sopenharmony_ci		 * pend_desched_switch) is set.
54062306a36Sopenharmony_ci		 */
54162306a36Sopenharmony_ci		uint64_t pend_grp:4;
54262306a36Sopenharmony_ci		uint64_t reserved_34_35:2;
54362306a36Sopenharmony_ci		/*
54462306a36Sopenharmony_ci		 * This is the tag type when pend_switch or
54562306a36Sopenharmony_ci		 * (pend_desched AND pend_desched_switch) are set.
54662306a36Sopenharmony_ci		 */
54762306a36Sopenharmony_ci		uint64_t pend_type:2;
54862306a36Sopenharmony_ci		/*
54962306a36Sopenharmony_ci		 * - this is the tag when pend_switch or (pend_desched
55062306a36Sopenharmony_ci		 *    AND pend_desched_switch) are set.
55162306a36Sopenharmony_ci		 */
55262306a36Sopenharmony_ci		uint64_t pend_tag:32;
55362306a36Sopenharmony_ci#else
55462306a36Sopenharmony_ci		uint64_t pend_tag:32;
55562306a36Sopenharmony_ci		uint64_t pend_type:2;
55662306a36Sopenharmony_ci		uint64_t reserved_34_35:2;
55762306a36Sopenharmony_ci		uint64_t pend_grp:4;
55862306a36Sopenharmony_ci		uint64_t pend_index:11;
55962306a36Sopenharmony_ci		uint64_t reserved_51:1;
56062306a36Sopenharmony_ci		uint64_t pend_nosched_clr:1;
56162306a36Sopenharmony_ci		uint64_t pend_null_rd:1;
56262306a36Sopenharmony_ci		uint64_t pend_new_work_wait:1;
56362306a36Sopenharmony_ci		uint64_t pend_new_work:1;
56462306a36Sopenharmony_ci		uint64_t pend_nosched:1;
56562306a36Sopenharmony_ci		uint64_t pend_desched_switch:1;
56662306a36Sopenharmony_ci		uint64_t pend_desched:1;
56762306a36Sopenharmony_ci		uint64_t pend_switch_null:1;
56862306a36Sopenharmony_ci		uint64_t pend_switch_full:1;
56962306a36Sopenharmony_ci		uint64_t pend_switch:1;
57062306a36Sopenharmony_ci		uint64_t reserved_62_63:2;
57162306a36Sopenharmony_ci#endif
57262306a36Sopenharmony_ci	} s_sstatus0;
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_ci    /**
57562306a36Sopenharmony_ci     * Result for a POW Status Load (when get_cur==0 and get_wqp==1)
57662306a36Sopenharmony_ci     */
57762306a36Sopenharmony_ci	struct {
57862306a36Sopenharmony_ci#ifdef __BIG_ENDIAN_BITFIELD
57962306a36Sopenharmony_ci		uint64_t reserved_62_63:2;
58062306a36Sopenharmony_ci		/*
58162306a36Sopenharmony_ci		 * Set when there is a pending non-NULL SWTAG or
58262306a36Sopenharmony_ci		 * SWTAG_FULL, and the POW entry has not left the list
58362306a36Sopenharmony_ci		 * for the original tag.
58462306a36Sopenharmony_ci		 */
58562306a36Sopenharmony_ci		uint64_t pend_switch:1;
58662306a36Sopenharmony_ci		/* Set when SWTAG_FULL and pend_switch is set. */
58762306a36Sopenharmony_ci		uint64_t pend_switch_full:1;
58862306a36Sopenharmony_ci		/*
58962306a36Sopenharmony_ci		 * Set when there is a pending NULL SWTAG, or an
59062306a36Sopenharmony_ci		 * implicit switch to NULL.
59162306a36Sopenharmony_ci		 */
59262306a36Sopenharmony_ci		uint64_t pend_switch_null:1;
59362306a36Sopenharmony_ci		/*
59462306a36Sopenharmony_ci		 * Set when there is a pending DESCHED or
59562306a36Sopenharmony_ci		 * SWTAG_DESCHED.
59662306a36Sopenharmony_ci		 */
59762306a36Sopenharmony_ci		uint64_t pend_desched:1;
59862306a36Sopenharmony_ci		/*
59962306a36Sopenharmony_ci		 * Set when there is a pending SWTAG_DESCHED and
60062306a36Sopenharmony_ci		 * pend_desched is set.
60162306a36Sopenharmony_ci		 */
60262306a36Sopenharmony_ci		uint64_t pend_desched_switch:1;
60362306a36Sopenharmony_ci		/* Set when nosched is desired and pend_desched is set. */
60462306a36Sopenharmony_ci		uint64_t pend_nosched:1;
60562306a36Sopenharmony_ci		/* Set when there is a pending GET_WORK. */
60662306a36Sopenharmony_ci		uint64_t pend_new_work:1;
60762306a36Sopenharmony_ci		/*
60862306a36Sopenharmony_ci		 * When pend_new_work is set, this bit indicates that
60962306a36Sopenharmony_ci		 * the wait bit was set.
61062306a36Sopenharmony_ci		 */
61162306a36Sopenharmony_ci		uint64_t pend_new_work_wait:1;
61262306a36Sopenharmony_ci		/* Set when there is a pending NULL_RD. */
61362306a36Sopenharmony_ci		uint64_t pend_null_rd:1;
61462306a36Sopenharmony_ci		/* Set when there is a pending CLR_NSCHED. */
61562306a36Sopenharmony_ci		uint64_t pend_nosched_clr:1;
61662306a36Sopenharmony_ci		uint64_t reserved_51:1;
61762306a36Sopenharmony_ci		/* This is the index when pend_nosched_clr is set. */
61862306a36Sopenharmony_ci		uint64_t pend_index:11;
61962306a36Sopenharmony_ci		/*
62062306a36Sopenharmony_ci		 * This is the new_grp when (pend_desched AND
62162306a36Sopenharmony_ci		 * pend_desched_switch) is set.
62262306a36Sopenharmony_ci		 */
62362306a36Sopenharmony_ci		uint64_t pend_grp:4;
62462306a36Sopenharmony_ci		/* This is the wqp when pend_nosched_clr is set. */
62562306a36Sopenharmony_ci		uint64_t pend_wqp:36;
62662306a36Sopenharmony_ci#else
62762306a36Sopenharmony_ci	        uint64_t pend_wqp:36;
62862306a36Sopenharmony_ci	        uint64_t pend_grp:4;
62962306a36Sopenharmony_ci	        uint64_t pend_index:11;
63062306a36Sopenharmony_ci	        uint64_t reserved_51:1;
63162306a36Sopenharmony_ci	        uint64_t pend_nosched_clr:1;
63262306a36Sopenharmony_ci	        uint64_t pend_null_rd:1;
63362306a36Sopenharmony_ci	        uint64_t pend_new_work_wait:1;
63462306a36Sopenharmony_ci	        uint64_t pend_new_work:1;
63562306a36Sopenharmony_ci	        uint64_t pend_nosched:1;
63662306a36Sopenharmony_ci	        uint64_t pend_desched_switch:1;
63762306a36Sopenharmony_ci	        uint64_t pend_desched:1;
63862306a36Sopenharmony_ci	        uint64_t pend_switch_null:1;
63962306a36Sopenharmony_ci	        uint64_t pend_switch_full:1;
64062306a36Sopenharmony_ci	        uint64_t pend_switch:1;
64162306a36Sopenharmony_ci	        uint64_t reserved_62_63:2;
64262306a36Sopenharmony_ci#endif
64362306a36Sopenharmony_ci	} s_sstatus1;
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_ci    /**
64662306a36Sopenharmony_ci     * Result for a POW Status Load (when get_cur==1, get_wqp==0, and
64762306a36Sopenharmony_ci     * get_rev==0)
64862306a36Sopenharmony_ci     */
64962306a36Sopenharmony_ci	struct {
65062306a36Sopenharmony_ci#ifdef __BIG_ENDIAN_BITFIELD
65162306a36Sopenharmony_ci		uint64_t reserved_62_63:2;
65262306a36Sopenharmony_ci		/*
65362306a36Sopenharmony_ci		 * Points to the next POW entry in the tag list when
65462306a36Sopenharmony_ci		 * tail == 0 (and tag_type is not NULL or NULL_NULL).
65562306a36Sopenharmony_ci		 */
65662306a36Sopenharmony_ci		uint64_t link_index:11;
65762306a36Sopenharmony_ci		/* The POW entry attached to the core. */
65862306a36Sopenharmony_ci		uint64_t index:11;
65962306a36Sopenharmony_ci		/*
66062306a36Sopenharmony_ci		 * The group attached to the core (updated when new
66162306a36Sopenharmony_ci		 * tag list entered on SWTAG_FULL).
66262306a36Sopenharmony_ci		 */
66362306a36Sopenharmony_ci		uint64_t grp:4;
66462306a36Sopenharmony_ci		/*
66562306a36Sopenharmony_ci		 * Set when this POW entry is at the head of its tag
66662306a36Sopenharmony_ci		 * list (also set when in the NULL or NULL_NULL
66762306a36Sopenharmony_ci		 * state).
66862306a36Sopenharmony_ci		 */
66962306a36Sopenharmony_ci		uint64_t head:1;
67062306a36Sopenharmony_ci		/*
67162306a36Sopenharmony_ci		 * Set when this POW entry is at the tail of its tag
67262306a36Sopenharmony_ci		 * list (also set when in the NULL or NULL_NULL
67362306a36Sopenharmony_ci		 * state).
67462306a36Sopenharmony_ci		 */
67562306a36Sopenharmony_ci		uint64_t tail:1;
67662306a36Sopenharmony_ci		/*
67762306a36Sopenharmony_ci		 * The tag type attached to the core (updated when new
67862306a36Sopenharmony_ci		 * tag list entered on SWTAG, SWTAG_FULL, or
67962306a36Sopenharmony_ci		 * SWTAG_DESCHED).
68062306a36Sopenharmony_ci		 */
68162306a36Sopenharmony_ci		uint64_t tag_type:2;
68262306a36Sopenharmony_ci		/*
68362306a36Sopenharmony_ci		 * The tag attached to the core (updated when new tag
68462306a36Sopenharmony_ci		 * list entered on SWTAG, SWTAG_FULL, or
68562306a36Sopenharmony_ci		 * SWTAG_DESCHED).
68662306a36Sopenharmony_ci		 */
68762306a36Sopenharmony_ci		uint64_t tag:32;
68862306a36Sopenharmony_ci#else
68962306a36Sopenharmony_ci	        uint64_t tag:32;
69062306a36Sopenharmony_ci	        uint64_t tag_type:2;
69162306a36Sopenharmony_ci	        uint64_t tail:1;
69262306a36Sopenharmony_ci	        uint64_t head:1;
69362306a36Sopenharmony_ci	        uint64_t grp:4;
69462306a36Sopenharmony_ci	        uint64_t index:11;
69562306a36Sopenharmony_ci	        uint64_t link_index:11;
69662306a36Sopenharmony_ci	        uint64_t reserved_62_63:2;
69762306a36Sopenharmony_ci#endif
69862306a36Sopenharmony_ci	} s_sstatus2;
69962306a36Sopenharmony_ci
70062306a36Sopenharmony_ci    /**
70162306a36Sopenharmony_ci     * Result for a POW Status Load (when get_cur==1, get_wqp==0, and get_rev==1)
70262306a36Sopenharmony_ci     */
70362306a36Sopenharmony_ci	struct {
70462306a36Sopenharmony_ci#ifdef __BIG_ENDIAN_BITFIELD
70562306a36Sopenharmony_ci		uint64_t reserved_62_63:2;
70662306a36Sopenharmony_ci		/*
70762306a36Sopenharmony_ci		 * Points to the prior POW entry in the tag list when
70862306a36Sopenharmony_ci		 * head == 0 (and tag_type is not NULL or
70962306a36Sopenharmony_ci		 * NULL_NULL). This field is unpredictable when the
71062306a36Sopenharmony_ci		 * core's state is NULL or NULL_NULL.
71162306a36Sopenharmony_ci		 */
71262306a36Sopenharmony_ci		uint64_t revlink_index:11;
71362306a36Sopenharmony_ci		/* The POW entry attached to the core. */
71462306a36Sopenharmony_ci		uint64_t index:11;
71562306a36Sopenharmony_ci		/*
71662306a36Sopenharmony_ci		 * The group attached to the core (updated when new
71762306a36Sopenharmony_ci		 * tag list entered on SWTAG_FULL).
71862306a36Sopenharmony_ci		 */
71962306a36Sopenharmony_ci		uint64_t grp:4;
72062306a36Sopenharmony_ci		/* Set when this POW entry is at the head of its tag
72162306a36Sopenharmony_ci		 * list (also set when in the NULL or NULL_NULL
72262306a36Sopenharmony_ci		 * state).
72362306a36Sopenharmony_ci		 */
72462306a36Sopenharmony_ci		uint64_t head:1;
72562306a36Sopenharmony_ci		/*
72662306a36Sopenharmony_ci		 * Set when this POW entry is at the tail of its tag
72762306a36Sopenharmony_ci		 * list (also set when in the NULL or NULL_NULL
72862306a36Sopenharmony_ci		 * state).
72962306a36Sopenharmony_ci		 */
73062306a36Sopenharmony_ci		uint64_t tail:1;
73162306a36Sopenharmony_ci		/*
73262306a36Sopenharmony_ci		 * The tag type attached to the core (updated when new
73362306a36Sopenharmony_ci		 * tag list entered on SWTAG, SWTAG_FULL, or
73462306a36Sopenharmony_ci		 * SWTAG_DESCHED).
73562306a36Sopenharmony_ci		 */
73662306a36Sopenharmony_ci		uint64_t tag_type:2;
73762306a36Sopenharmony_ci		/*
73862306a36Sopenharmony_ci		 * The tag attached to the core (updated when new tag
73962306a36Sopenharmony_ci		 * list entered on SWTAG, SWTAG_FULL, or
74062306a36Sopenharmony_ci		 * SWTAG_DESCHED).
74162306a36Sopenharmony_ci		 */
74262306a36Sopenharmony_ci		uint64_t tag:32;
74362306a36Sopenharmony_ci#else
74462306a36Sopenharmony_ci	        uint64_t tag:32;
74562306a36Sopenharmony_ci	        uint64_t tag_type:2;
74662306a36Sopenharmony_ci	        uint64_t tail:1;
74762306a36Sopenharmony_ci	        uint64_t head:1;
74862306a36Sopenharmony_ci	        uint64_t grp:4;
74962306a36Sopenharmony_ci	        uint64_t index:11;
75062306a36Sopenharmony_ci	        uint64_t revlink_index:11;
75162306a36Sopenharmony_ci	        uint64_t reserved_62_63:2;
75262306a36Sopenharmony_ci#endif
75362306a36Sopenharmony_ci	} s_sstatus3;
75462306a36Sopenharmony_ci
75562306a36Sopenharmony_ci    /**
75662306a36Sopenharmony_ci     * Result for a POW Status Load (when get_cur==1, get_wqp==1, and
75762306a36Sopenharmony_ci     * get_rev==0)
75862306a36Sopenharmony_ci     */
75962306a36Sopenharmony_ci	struct {
76062306a36Sopenharmony_ci#ifdef __BIG_ENDIAN_BITFIELD
76162306a36Sopenharmony_ci		uint64_t reserved_62_63:2;
76262306a36Sopenharmony_ci		/*
76362306a36Sopenharmony_ci		 * Points to the next POW entry in the tag list when
76462306a36Sopenharmony_ci		 * tail == 0 (and tag_type is not NULL or NULL_NULL).
76562306a36Sopenharmony_ci		 */
76662306a36Sopenharmony_ci		uint64_t link_index:11;
76762306a36Sopenharmony_ci		/* The POW entry attached to the core. */
76862306a36Sopenharmony_ci		uint64_t index:11;
76962306a36Sopenharmony_ci		/*
77062306a36Sopenharmony_ci		 * The group attached to the core (updated when new
77162306a36Sopenharmony_ci		 * tag list entered on SWTAG_FULL).
77262306a36Sopenharmony_ci		 */
77362306a36Sopenharmony_ci		uint64_t grp:4;
77462306a36Sopenharmony_ci		/*
77562306a36Sopenharmony_ci		 * The wqp attached to the core (updated when new tag
77662306a36Sopenharmony_ci		 * list entered on SWTAG_FULL).
77762306a36Sopenharmony_ci		 */
77862306a36Sopenharmony_ci		uint64_t wqp:36;
77962306a36Sopenharmony_ci#else
78062306a36Sopenharmony_ci	        uint64_t wqp:36;
78162306a36Sopenharmony_ci	        uint64_t grp:4;
78262306a36Sopenharmony_ci	        uint64_t index:11;
78362306a36Sopenharmony_ci	        uint64_t link_index:11;
78462306a36Sopenharmony_ci	        uint64_t reserved_62_63:2;
78562306a36Sopenharmony_ci#endif
78662306a36Sopenharmony_ci	} s_sstatus4;
78762306a36Sopenharmony_ci
78862306a36Sopenharmony_ci    /**
78962306a36Sopenharmony_ci     * Result for a POW Status Load (when get_cur==1, get_wqp==1, and
79062306a36Sopenharmony_ci     * get_rev==1)
79162306a36Sopenharmony_ci     */
79262306a36Sopenharmony_ci	struct {
79362306a36Sopenharmony_ci#ifdef __BIG_ENDIAN_BITFIELD
79462306a36Sopenharmony_ci		uint64_t reserved_62_63:2;
79562306a36Sopenharmony_ci		/*
79662306a36Sopenharmony_ci		 * Points to the prior POW entry in the tag list when
79762306a36Sopenharmony_ci		 * head == 0 (and tag_type is not NULL or
79862306a36Sopenharmony_ci		 * NULL_NULL). This field is unpredictable when the
79962306a36Sopenharmony_ci		 * core's state is NULL or NULL_NULL.
80062306a36Sopenharmony_ci		 */
80162306a36Sopenharmony_ci		uint64_t revlink_index:11;
80262306a36Sopenharmony_ci		/* The POW entry attached to the core. */
80362306a36Sopenharmony_ci		uint64_t index:11;
80462306a36Sopenharmony_ci		/*
80562306a36Sopenharmony_ci		 * The group attached to the core (updated when new
80662306a36Sopenharmony_ci		 * tag list entered on SWTAG_FULL).
80762306a36Sopenharmony_ci		 */
80862306a36Sopenharmony_ci		uint64_t grp:4;
80962306a36Sopenharmony_ci		/*
81062306a36Sopenharmony_ci		 * The wqp attached to the core (updated when new tag
81162306a36Sopenharmony_ci		 * list entered on SWTAG_FULL).
81262306a36Sopenharmony_ci		 */
81362306a36Sopenharmony_ci		uint64_t wqp:36;
81462306a36Sopenharmony_ci#else
81562306a36Sopenharmony_ci	        uint64_t wqp:36;
81662306a36Sopenharmony_ci	        uint64_t grp:4;
81762306a36Sopenharmony_ci	        uint64_t index:11;
81862306a36Sopenharmony_ci	        uint64_t revlink_index:11;
81962306a36Sopenharmony_ci	        uint64_t reserved_62_63:2;
82062306a36Sopenharmony_ci#endif
82162306a36Sopenharmony_ci	} s_sstatus5;
82262306a36Sopenharmony_ci
82362306a36Sopenharmony_ci    /**
82462306a36Sopenharmony_ci     * Result For POW Memory Load (get_des == 0 and get_wqp == 0)
82562306a36Sopenharmony_ci     */
82662306a36Sopenharmony_ci	struct {
82762306a36Sopenharmony_ci#ifdef __BIG_ENDIAN_BITFIELD
82862306a36Sopenharmony_ci		uint64_t reserved_51_63:13;
82962306a36Sopenharmony_ci		/*
83062306a36Sopenharmony_ci		 * The next entry in the input, free, descheduled_head
83162306a36Sopenharmony_ci		 * list (unpredictable if entry is the tail of the
83262306a36Sopenharmony_ci		 * list).
83362306a36Sopenharmony_ci		 */
83462306a36Sopenharmony_ci		uint64_t next_index:11;
83562306a36Sopenharmony_ci		/* The group of the POW entry. */
83662306a36Sopenharmony_ci		uint64_t grp:4;
83762306a36Sopenharmony_ci		uint64_t reserved_35:1;
83862306a36Sopenharmony_ci		/*
83962306a36Sopenharmony_ci		 * Set when this POW entry is at the tail of its tag
84062306a36Sopenharmony_ci		 * list (also set when in the NULL or NULL_NULL
84162306a36Sopenharmony_ci		 * state).
84262306a36Sopenharmony_ci		 */
84362306a36Sopenharmony_ci		uint64_t tail:1;
84462306a36Sopenharmony_ci		/* The tag type of the POW entry. */
84562306a36Sopenharmony_ci		uint64_t tag_type:2;
84662306a36Sopenharmony_ci		/* The tag of the POW entry. */
84762306a36Sopenharmony_ci		uint64_t tag:32;
84862306a36Sopenharmony_ci#else
84962306a36Sopenharmony_ci	        uint64_t tag:32;
85062306a36Sopenharmony_ci	        uint64_t tag_type:2;
85162306a36Sopenharmony_ci	        uint64_t tail:1;
85262306a36Sopenharmony_ci	        uint64_t reserved_35:1;
85362306a36Sopenharmony_ci	        uint64_t grp:4;
85462306a36Sopenharmony_ci	        uint64_t next_index:11;
85562306a36Sopenharmony_ci	        uint64_t reserved_51_63:13;
85662306a36Sopenharmony_ci#endif
85762306a36Sopenharmony_ci	} s_smemload0;
85862306a36Sopenharmony_ci
85962306a36Sopenharmony_ci    /**
86062306a36Sopenharmony_ci     * Result For POW Memory Load (get_des == 0 and get_wqp == 1)
86162306a36Sopenharmony_ci     */
86262306a36Sopenharmony_ci	struct {
86362306a36Sopenharmony_ci#ifdef __BIG_ENDIAN_BITFIELD
86462306a36Sopenharmony_ci		uint64_t reserved_51_63:13;
86562306a36Sopenharmony_ci		/*
86662306a36Sopenharmony_ci		 * The next entry in the input, free, descheduled_head
86762306a36Sopenharmony_ci		 * list (unpredictable if entry is the tail of the
86862306a36Sopenharmony_ci		 * list).
86962306a36Sopenharmony_ci		 */
87062306a36Sopenharmony_ci		uint64_t next_index:11;
87162306a36Sopenharmony_ci		/* The group of the POW entry. */
87262306a36Sopenharmony_ci		uint64_t grp:4;
87362306a36Sopenharmony_ci		/* The WQP held in the POW entry. */
87462306a36Sopenharmony_ci		uint64_t wqp:36;
87562306a36Sopenharmony_ci#else
87662306a36Sopenharmony_ci	        uint64_t wqp:36;
87762306a36Sopenharmony_ci	        uint64_t grp:4;
87862306a36Sopenharmony_ci	        uint64_t next_index:11;
87962306a36Sopenharmony_ci	        uint64_t reserved_51_63:13;
88062306a36Sopenharmony_ci#endif
88162306a36Sopenharmony_ci	} s_smemload1;
88262306a36Sopenharmony_ci
88362306a36Sopenharmony_ci    /**
88462306a36Sopenharmony_ci     * Result For POW Memory Load (get_des == 1)
88562306a36Sopenharmony_ci     */
88662306a36Sopenharmony_ci	struct {
88762306a36Sopenharmony_ci#ifdef __BIG_ENDIAN_BITFIELD
88862306a36Sopenharmony_ci		uint64_t reserved_51_63:13;
88962306a36Sopenharmony_ci		/*
89062306a36Sopenharmony_ci		 * The next entry in the tag list connected to the
89162306a36Sopenharmony_ci		 * descheduled head.
89262306a36Sopenharmony_ci		 */
89362306a36Sopenharmony_ci		uint64_t fwd_index:11;
89462306a36Sopenharmony_ci		/* The group of the POW entry. */
89562306a36Sopenharmony_ci		uint64_t grp:4;
89662306a36Sopenharmony_ci		/* The nosched bit for the POW entry. */
89762306a36Sopenharmony_ci		uint64_t nosched:1;
89862306a36Sopenharmony_ci		/* There is a pending tag switch */
89962306a36Sopenharmony_ci		uint64_t pend_switch:1;
90062306a36Sopenharmony_ci		/*
90162306a36Sopenharmony_ci		 * The next tag type for the new tag list when
90262306a36Sopenharmony_ci		 * pend_switch is set.
90362306a36Sopenharmony_ci		 */
90462306a36Sopenharmony_ci		uint64_t pend_type:2;
90562306a36Sopenharmony_ci		/*
90662306a36Sopenharmony_ci		 * The next tag for the new tag list when pend_switch
90762306a36Sopenharmony_ci		 * is set.
90862306a36Sopenharmony_ci		 */
90962306a36Sopenharmony_ci		uint64_t pend_tag:32;
91062306a36Sopenharmony_ci#else
91162306a36Sopenharmony_ci	        uint64_t pend_tag:32;
91262306a36Sopenharmony_ci	        uint64_t pend_type:2;
91362306a36Sopenharmony_ci	        uint64_t pend_switch:1;
91462306a36Sopenharmony_ci	        uint64_t nosched:1;
91562306a36Sopenharmony_ci	        uint64_t grp:4;
91662306a36Sopenharmony_ci	        uint64_t fwd_index:11;
91762306a36Sopenharmony_ci	        uint64_t reserved_51_63:13;
91862306a36Sopenharmony_ci#endif
91962306a36Sopenharmony_ci	} s_smemload2;
92062306a36Sopenharmony_ci
92162306a36Sopenharmony_ci    /**
92262306a36Sopenharmony_ci     * Result For POW Index/Pointer Load (get_rmt == 0/get_des_get_tail == 0)
92362306a36Sopenharmony_ci     */
92462306a36Sopenharmony_ci	struct {
92562306a36Sopenharmony_ci#ifdef __BIG_ENDIAN_BITFIELD
92662306a36Sopenharmony_ci		uint64_t reserved_52_63:12;
92762306a36Sopenharmony_ci		/*
92862306a36Sopenharmony_ci		 * set when there is one or more POW entries on the
92962306a36Sopenharmony_ci		 * free list.
93062306a36Sopenharmony_ci		 */
93162306a36Sopenharmony_ci		uint64_t free_val:1;
93262306a36Sopenharmony_ci		/*
93362306a36Sopenharmony_ci		 * set when there is exactly one POW entry on the free
93462306a36Sopenharmony_ci		 * list.
93562306a36Sopenharmony_ci		 */
93662306a36Sopenharmony_ci		uint64_t free_one:1;
93762306a36Sopenharmony_ci		uint64_t reserved_49:1;
93862306a36Sopenharmony_ci		/*
93962306a36Sopenharmony_ci		 * when free_val is set, indicates the first entry on
94062306a36Sopenharmony_ci		 * the free list.
94162306a36Sopenharmony_ci		 */
94262306a36Sopenharmony_ci		uint64_t free_head:11;
94362306a36Sopenharmony_ci		uint64_t reserved_37:1;
94462306a36Sopenharmony_ci		/*
94562306a36Sopenharmony_ci		 * when free_val is set, indicates the last entry on
94662306a36Sopenharmony_ci		 * the free list.
94762306a36Sopenharmony_ci		 */
94862306a36Sopenharmony_ci		uint64_t free_tail:11;
94962306a36Sopenharmony_ci		/*
95062306a36Sopenharmony_ci		 * set when there is one or more POW entries on the
95162306a36Sopenharmony_ci		 * input Q list selected by qosgrp.
95262306a36Sopenharmony_ci		 */
95362306a36Sopenharmony_ci		uint64_t loc_val:1;
95462306a36Sopenharmony_ci		/*
95562306a36Sopenharmony_ci		 * set when there is exactly one POW entry on the
95662306a36Sopenharmony_ci		 * input Q list selected by qosgrp.
95762306a36Sopenharmony_ci		 */
95862306a36Sopenharmony_ci		uint64_t loc_one:1;
95962306a36Sopenharmony_ci		uint64_t reserved_23:1;
96062306a36Sopenharmony_ci		/*
96162306a36Sopenharmony_ci		 * when loc_val is set, indicates the first entry on
96262306a36Sopenharmony_ci		 * the input Q list selected by qosgrp.
96362306a36Sopenharmony_ci		 */
96462306a36Sopenharmony_ci		uint64_t loc_head:11;
96562306a36Sopenharmony_ci		uint64_t reserved_11:1;
96662306a36Sopenharmony_ci		/*
96762306a36Sopenharmony_ci		 * when loc_val is set, indicates the last entry on
96862306a36Sopenharmony_ci		 * the input Q list selected by qosgrp.
96962306a36Sopenharmony_ci		 */
97062306a36Sopenharmony_ci		uint64_t loc_tail:11;
97162306a36Sopenharmony_ci#else
97262306a36Sopenharmony_ci	        uint64_t loc_tail:11;
97362306a36Sopenharmony_ci	        uint64_t reserved_11:1;
97462306a36Sopenharmony_ci	        uint64_t loc_head:11;
97562306a36Sopenharmony_ci	        uint64_t reserved_23:1;
97662306a36Sopenharmony_ci	        uint64_t loc_one:1;
97762306a36Sopenharmony_ci	        uint64_t loc_val:1;
97862306a36Sopenharmony_ci	        uint64_t free_tail:11;
97962306a36Sopenharmony_ci	        uint64_t reserved_37:1;
98062306a36Sopenharmony_ci	        uint64_t free_head:11;
98162306a36Sopenharmony_ci	        uint64_t reserved_49:1;
98262306a36Sopenharmony_ci	        uint64_t free_one:1;
98362306a36Sopenharmony_ci	        uint64_t free_val:1;
98462306a36Sopenharmony_ci	        uint64_t reserved_52_63:12;
98562306a36Sopenharmony_ci#endif
98662306a36Sopenharmony_ci	} sindexload0;
98762306a36Sopenharmony_ci
98862306a36Sopenharmony_ci    /**
98962306a36Sopenharmony_ci     * Result For POW Index/Pointer Load (get_rmt == 0/get_des_get_tail == 1)
99062306a36Sopenharmony_ci     */
99162306a36Sopenharmony_ci	struct {
99262306a36Sopenharmony_ci#ifdef __BIG_ENDIAN_BITFIELD
99362306a36Sopenharmony_ci		uint64_t reserved_52_63:12;
99462306a36Sopenharmony_ci		/*
99562306a36Sopenharmony_ci		 * set when there is one or more POW entries on the
99662306a36Sopenharmony_ci		 * nosched list.
99762306a36Sopenharmony_ci		 */
99862306a36Sopenharmony_ci		uint64_t nosched_val:1;
99962306a36Sopenharmony_ci		/*
100062306a36Sopenharmony_ci		 * set when there is exactly one POW entry on the
100162306a36Sopenharmony_ci		 * nosched list.
100262306a36Sopenharmony_ci		 */
100362306a36Sopenharmony_ci		uint64_t nosched_one:1;
100462306a36Sopenharmony_ci		uint64_t reserved_49:1;
100562306a36Sopenharmony_ci		/*
100662306a36Sopenharmony_ci		 * when nosched_val is set, indicates the first entry
100762306a36Sopenharmony_ci		 * on the nosched list.
100862306a36Sopenharmony_ci		 */
100962306a36Sopenharmony_ci		uint64_t nosched_head:11;
101062306a36Sopenharmony_ci		uint64_t reserved_37:1;
101162306a36Sopenharmony_ci		/*
101262306a36Sopenharmony_ci		 * when nosched_val is set, indicates the last entry
101362306a36Sopenharmony_ci		 * on the nosched list.
101462306a36Sopenharmony_ci		 */
101562306a36Sopenharmony_ci		uint64_t nosched_tail:11;
101662306a36Sopenharmony_ci		/*
101762306a36Sopenharmony_ci		 * set when there is one or more descheduled heads on
101862306a36Sopenharmony_ci		 * the descheduled list selected by qosgrp.
101962306a36Sopenharmony_ci		 */
102062306a36Sopenharmony_ci		uint64_t des_val:1;
102162306a36Sopenharmony_ci		/*
102262306a36Sopenharmony_ci		 * set when there is exactly one descheduled head on
102362306a36Sopenharmony_ci		 * the descheduled list selected by qosgrp.
102462306a36Sopenharmony_ci		 */
102562306a36Sopenharmony_ci		uint64_t des_one:1;
102662306a36Sopenharmony_ci		uint64_t reserved_23:1;
102762306a36Sopenharmony_ci		/*
102862306a36Sopenharmony_ci		 * when des_val is set, indicates the first
102962306a36Sopenharmony_ci		 * descheduled head on the descheduled list selected
103062306a36Sopenharmony_ci		 * by qosgrp.
103162306a36Sopenharmony_ci		 */
103262306a36Sopenharmony_ci		uint64_t des_head:11;
103362306a36Sopenharmony_ci		uint64_t reserved_11:1;
103462306a36Sopenharmony_ci		/*
103562306a36Sopenharmony_ci		 * when des_val is set, indicates the last descheduled
103662306a36Sopenharmony_ci		 * head on the descheduled list selected by qosgrp.
103762306a36Sopenharmony_ci		 */
103862306a36Sopenharmony_ci		uint64_t des_tail:11;
103962306a36Sopenharmony_ci#else
104062306a36Sopenharmony_ci	        uint64_t des_tail:11;
104162306a36Sopenharmony_ci	        uint64_t reserved_11:1;
104262306a36Sopenharmony_ci	        uint64_t des_head:11;
104362306a36Sopenharmony_ci	        uint64_t reserved_23:1;
104462306a36Sopenharmony_ci	        uint64_t des_one:1;
104562306a36Sopenharmony_ci	        uint64_t des_val:1;
104662306a36Sopenharmony_ci	        uint64_t nosched_tail:11;
104762306a36Sopenharmony_ci	        uint64_t reserved_37:1;
104862306a36Sopenharmony_ci	        uint64_t nosched_head:11;
104962306a36Sopenharmony_ci	        uint64_t reserved_49:1;
105062306a36Sopenharmony_ci	        uint64_t nosched_one:1;
105162306a36Sopenharmony_ci	        uint64_t nosched_val:1;
105262306a36Sopenharmony_ci	        uint64_t reserved_52_63:12;
105362306a36Sopenharmony_ci#endif
105462306a36Sopenharmony_ci	} sindexload1;
105562306a36Sopenharmony_ci
105662306a36Sopenharmony_ci    /**
105762306a36Sopenharmony_ci     * Result For POW Index/Pointer Load (get_rmt == 1/get_des_get_tail == 0)
105862306a36Sopenharmony_ci     */
105962306a36Sopenharmony_ci	struct {
106062306a36Sopenharmony_ci#ifdef __BIG_ENDIAN_BITFIELD
106162306a36Sopenharmony_ci		uint64_t reserved_39_63:25;
106262306a36Sopenharmony_ci		/*
106362306a36Sopenharmony_ci		 * Set when this DRAM list is the current head
106462306a36Sopenharmony_ci		 * (i.e. is the next to be reloaded when the POW
106562306a36Sopenharmony_ci		 * hardware reloads a POW entry from DRAM). The POW
106662306a36Sopenharmony_ci		 * hardware alternates between the two DRAM lists
106762306a36Sopenharmony_ci		 * associated with a QOS level when it reloads work
106862306a36Sopenharmony_ci		 * from DRAM into the POW unit.
106962306a36Sopenharmony_ci		 */
107062306a36Sopenharmony_ci		uint64_t rmt_is_head:1;
107162306a36Sopenharmony_ci		/*
107262306a36Sopenharmony_ci		 * Set when the DRAM portion of the input Q list
107362306a36Sopenharmony_ci		 * selected by qosgrp contains one or more pieces of
107462306a36Sopenharmony_ci		 * work.
107562306a36Sopenharmony_ci		 */
107662306a36Sopenharmony_ci		uint64_t rmt_val:1;
107762306a36Sopenharmony_ci		/*
107862306a36Sopenharmony_ci		 * Set when the DRAM portion of the input Q list
107962306a36Sopenharmony_ci		 * selected by qosgrp contains exactly one piece of
108062306a36Sopenharmony_ci		 * work.
108162306a36Sopenharmony_ci		 */
108262306a36Sopenharmony_ci		uint64_t rmt_one:1;
108362306a36Sopenharmony_ci		/*
108462306a36Sopenharmony_ci		 * When rmt_val is set, indicates the first piece of
108562306a36Sopenharmony_ci		 * work on the DRAM input Q list selected by
108662306a36Sopenharmony_ci		 * qosgrp.
108762306a36Sopenharmony_ci		 */
108862306a36Sopenharmony_ci		uint64_t rmt_head:36;
108962306a36Sopenharmony_ci#else
109062306a36Sopenharmony_ci	        uint64_t rmt_head:36;
109162306a36Sopenharmony_ci	        uint64_t rmt_one:1;
109262306a36Sopenharmony_ci	        uint64_t rmt_val:1;
109362306a36Sopenharmony_ci	        uint64_t rmt_is_head:1;
109462306a36Sopenharmony_ci	        uint64_t reserved_39_63:25;
109562306a36Sopenharmony_ci#endif
109662306a36Sopenharmony_ci	} sindexload2;
109762306a36Sopenharmony_ci
109862306a36Sopenharmony_ci    /**
109962306a36Sopenharmony_ci     * Result For POW Index/Pointer Load (get_rmt ==
110062306a36Sopenharmony_ci     * 1/get_des_get_tail == 1)
110162306a36Sopenharmony_ci     */
110262306a36Sopenharmony_ci	struct {
110362306a36Sopenharmony_ci#ifdef __BIG_ENDIAN_BITFIELD
110462306a36Sopenharmony_ci		uint64_t reserved_39_63:25;
110562306a36Sopenharmony_ci		/*
110662306a36Sopenharmony_ci		 * set when this DRAM list is the current head
110762306a36Sopenharmony_ci		 * (i.e. is the next to be reloaded when the POW
110862306a36Sopenharmony_ci		 * hardware reloads a POW entry from DRAM). The POW
110962306a36Sopenharmony_ci		 * hardware alternates between the two DRAM lists
111062306a36Sopenharmony_ci		 * associated with a QOS level when it reloads work
111162306a36Sopenharmony_ci		 * from DRAM into the POW unit.
111262306a36Sopenharmony_ci		 */
111362306a36Sopenharmony_ci		uint64_t rmt_is_head:1;
111462306a36Sopenharmony_ci		/*
111562306a36Sopenharmony_ci		 * set when the DRAM portion of the input Q list
111662306a36Sopenharmony_ci		 * selected by qosgrp contains one or more pieces of
111762306a36Sopenharmony_ci		 * work.
111862306a36Sopenharmony_ci		 */
111962306a36Sopenharmony_ci		uint64_t rmt_val:1;
112062306a36Sopenharmony_ci		/*
112162306a36Sopenharmony_ci		 * set when the DRAM portion of the input Q list
112262306a36Sopenharmony_ci		 * selected by qosgrp contains exactly one piece of
112362306a36Sopenharmony_ci		 * work.
112462306a36Sopenharmony_ci		 */
112562306a36Sopenharmony_ci		uint64_t rmt_one:1;
112662306a36Sopenharmony_ci		/*
112762306a36Sopenharmony_ci		 * when rmt_val is set, indicates the last piece of
112862306a36Sopenharmony_ci		 * work on the DRAM input Q list selected by
112962306a36Sopenharmony_ci		 * qosgrp.
113062306a36Sopenharmony_ci		 */
113162306a36Sopenharmony_ci		uint64_t rmt_tail:36;
113262306a36Sopenharmony_ci#else
113362306a36Sopenharmony_ci	        uint64_t rmt_tail:36;
113462306a36Sopenharmony_ci	        uint64_t rmt_one:1;
113562306a36Sopenharmony_ci	        uint64_t rmt_val:1;
113662306a36Sopenharmony_ci	        uint64_t rmt_is_head:1;
113762306a36Sopenharmony_ci	        uint64_t reserved_39_63:25;
113862306a36Sopenharmony_ci#endif
113962306a36Sopenharmony_ci	} sindexload3;
114062306a36Sopenharmony_ci
114162306a36Sopenharmony_ci    /**
114262306a36Sopenharmony_ci     * Response to NULL_RD request loads
114362306a36Sopenharmony_ci     */
114462306a36Sopenharmony_ci	struct {
114562306a36Sopenharmony_ci#ifdef __BIG_ENDIAN_BITFIELD
114662306a36Sopenharmony_ci		uint64_t unused:62;
114762306a36Sopenharmony_ci		/* of type cvmx_pow_tag_type_t. state is one of the
114862306a36Sopenharmony_ci		 * following:
114962306a36Sopenharmony_ci		 *
115062306a36Sopenharmony_ci		 * - CVMX_POW_TAG_TYPE_ORDERED
115162306a36Sopenharmony_ci		 * - CVMX_POW_TAG_TYPE_ATOMIC
115262306a36Sopenharmony_ci		 * - CVMX_POW_TAG_TYPE_NULL
115362306a36Sopenharmony_ci		 * - CVMX_POW_TAG_TYPE_NULL_NULL
115462306a36Sopenharmony_ci		 */
115562306a36Sopenharmony_ci		uint64_t state:2;
115662306a36Sopenharmony_ci#else
115762306a36Sopenharmony_ci	        uint64_t state:2;
115862306a36Sopenharmony_ci	        uint64_t unused:62;
115962306a36Sopenharmony_ci#endif
116062306a36Sopenharmony_ci	} s_null_rd;
116162306a36Sopenharmony_ci
116262306a36Sopenharmony_ci} cvmx_pow_tag_load_resp_t;
116362306a36Sopenharmony_ci
116462306a36Sopenharmony_ci/**
116562306a36Sopenharmony_ci * This structure describes the address used for stores to the POW.
116662306a36Sopenharmony_ci *  The store address is meaningful on stores to the POW.  The
116762306a36Sopenharmony_ci *  hardware assumes that an aligned 64-bit store was used for all
116862306a36Sopenharmony_ci *  these stores.  Note the assumption that the work queue entry is
116962306a36Sopenharmony_ci *  aligned on an 8-byte boundary (since the low-order 3 address bits
117062306a36Sopenharmony_ci *  must be zero).  Note that not all fields are used by all
117162306a36Sopenharmony_ci *  operations.
117262306a36Sopenharmony_ci *
117362306a36Sopenharmony_ci *  NOTE: The following is the behavior of the pending switch bit at the PP
117462306a36Sopenharmony_ci *	 for POW stores (i.e. when did<7:3> == 0xc)
117562306a36Sopenharmony_ci *     - did<2:0> == 0	    => pending switch bit is set
117662306a36Sopenharmony_ci *     - did<2:0> == 1	    => no affect on the pending switch bit
117762306a36Sopenharmony_ci *     - did<2:0> == 3	    => pending switch bit is cleared
117862306a36Sopenharmony_ci *     - did<2:0> == 7	    => no affect on the pending switch bit
117962306a36Sopenharmony_ci *     - did<2:0> == others => must not be used
118062306a36Sopenharmony_ci *     - No other loads/stores have an affect on the pending switch bit
118162306a36Sopenharmony_ci *     - The switch bus from POW can clear the pending switch bit
118262306a36Sopenharmony_ci *
118362306a36Sopenharmony_ci *  NOTE: did<2:0> == 2 is used by the HW for a special single-cycle
118462306a36Sopenharmony_ci *  ADDWQ command that only contains the pointer). SW must never use
118562306a36Sopenharmony_ci *  did<2:0> == 2.
118662306a36Sopenharmony_ci */
118762306a36Sopenharmony_citypedef union {
118862306a36Sopenharmony_ci    /**
118962306a36Sopenharmony_ci     * Unsigned 64 bit integer representation of store address
119062306a36Sopenharmony_ci     */
119162306a36Sopenharmony_ci	uint64_t u64;
119262306a36Sopenharmony_ci
119362306a36Sopenharmony_ci	struct {
119462306a36Sopenharmony_ci#ifdef __BIG_ENDIAN_BITFIELD
119562306a36Sopenharmony_ci		/* Memory region.  Should be CVMX_IO_SEG in most cases */
119662306a36Sopenharmony_ci		uint64_t mem_reg:2;
119762306a36Sopenharmony_ci		uint64_t reserved_49_61:13;	/* Must be zero */
119862306a36Sopenharmony_ci		uint64_t is_io:1;	/* Must be one */
119962306a36Sopenharmony_ci		/* Device ID of POW.  Note that different sub-dids are used. */
120062306a36Sopenharmony_ci		uint64_t did:8;
120162306a36Sopenharmony_ci		uint64_t reserved_36_39:4;	/* Must be zero */
120262306a36Sopenharmony_ci		/* Address field. addr<2:0> must be zero */
120362306a36Sopenharmony_ci		uint64_t addr:36;
120462306a36Sopenharmony_ci#else
120562306a36Sopenharmony_ci	        uint64_t addr:36;
120662306a36Sopenharmony_ci	        uint64_t reserved_36_39:4;
120762306a36Sopenharmony_ci	        uint64_t did:8;
120862306a36Sopenharmony_ci	        uint64_t is_io:1;
120962306a36Sopenharmony_ci	        uint64_t reserved_49_61:13;
121062306a36Sopenharmony_ci	        uint64_t mem_reg:2;
121162306a36Sopenharmony_ci#endif
121262306a36Sopenharmony_ci	} stag;
121362306a36Sopenharmony_ci} cvmx_pow_tag_store_addr_t;
121462306a36Sopenharmony_ci
121562306a36Sopenharmony_ci/**
121662306a36Sopenharmony_ci * decode of the store data when an IOBDMA SENDSINGLE is sent to POW
121762306a36Sopenharmony_ci */
121862306a36Sopenharmony_citypedef union {
121962306a36Sopenharmony_ci	uint64_t u64;
122062306a36Sopenharmony_ci
122162306a36Sopenharmony_ci	struct {
122262306a36Sopenharmony_ci#ifdef __BIG_ENDIAN_BITFIELD
122362306a36Sopenharmony_ci		/*
122462306a36Sopenharmony_ci		 * the (64-bit word) location in scratchpad to write
122562306a36Sopenharmony_ci		 * to (if len != 0)
122662306a36Sopenharmony_ci		 */
122762306a36Sopenharmony_ci		uint64_t scraddr:8;
122862306a36Sopenharmony_ci		/* the number of words in the response (0 => no response) */
122962306a36Sopenharmony_ci		uint64_t len:8;
123062306a36Sopenharmony_ci		/* the ID of the device on the non-coherent bus */
123162306a36Sopenharmony_ci		uint64_t did:8;
123262306a36Sopenharmony_ci		uint64_t unused:36;
123362306a36Sopenharmony_ci		/* if set, don't return load response until work is available */
123462306a36Sopenharmony_ci		uint64_t wait:1;
123562306a36Sopenharmony_ci		uint64_t unused2:3;
123662306a36Sopenharmony_ci#else
123762306a36Sopenharmony_ci	        uint64_t unused2:3;
123862306a36Sopenharmony_ci	        uint64_t wait:1;
123962306a36Sopenharmony_ci	        uint64_t unused:36;
124062306a36Sopenharmony_ci	        uint64_t did:8;
124162306a36Sopenharmony_ci	        uint64_t len:8;
124262306a36Sopenharmony_ci	        uint64_t scraddr:8;
124362306a36Sopenharmony_ci#endif
124462306a36Sopenharmony_ci	} s;
124562306a36Sopenharmony_ci
124662306a36Sopenharmony_ci} cvmx_pow_iobdma_store_t;
124762306a36Sopenharmony_ci
124862306a36Sopenharmony_ci/* CSR typedefs have been moved to cvmx-csr-*.h */
124962306a36Sopenharmony_ci
125062306a36Sopenharmony_ci/**
125162306a36Sopenharmony_ci * Get the POW tag for this core. This returns the current
125262306a36Sopenharmony_ci * tag type, tag, group, and POW entry index associated with
125362306a36Sopenharmony_ci * this core. Index is only valid if the tag type isn't NULL_NULL.
125462306a36Sopenharmony_ci * If a tag switch is pending this routine returns the tag before
125562306a36Sopenharmony_ci * the tag switch, not after.
125662306a36Sopenharmony_ci *
125762306a36Sopenharmony_ci * Returns Current tag
125862306a36Sopenharmony_ci */
125962306a36Sopenharmony_cistatic inline cvmx_pow_tag_req_t cvmx_pow_get_current_tag(void)
126062306a36Sopenharmony_ci{
126162306a36Sopenharmony_ci	cvmx_pow_load_addr_t load_addr;
126262306a36Sopenharmony_ci	cvmx_pow_tag_load_resp_t load_resp;
126362306a36Sopenharmony_ci	cvmx_pow_tag_req_t result;
126462306a36Sopenharmony_ci
126562306a36Sopenharmony_ci	load_addr.u64 = 0;
126662306a36Sopenharmony_ci	load_addr.sstatus.mem_region = CVMX_IO_SEG;
126762306a36Sopenharmony_ci	load_addr.sstatus.is_io = 1;
126862306a36Sopenharmony_ci	load_addr.sstatus.did = CVMX_OCT_DID_TAG_TAG1;
126962306a36Sopenharmony_ci	load_addr.sstatus.coreid = cvmx_get_core_num();
127062306a36Sopenharmony_ci	load_addr.sstatus.get_cur = 1;
127162306a36Sopenharmony_ci	load_resp.u64 = cvmx_read_csr(load_addr.u64);
127262306a36Sopenharmony_ci	result.u64 = 0;
127362306a36Sopenharmony_ci	result.s.grp = load_resp.s_sstatus2.grp;
127462306a36Sopenharmony_ci	result.s.index = load_resp.s_sstatus2.index;
127562306a36Sopenharmony_ci	result.s.type = load_resp.s_sstatus2.tag_type;
127662306a36Sopenharmony_ci	result.s.tag = load_resp.s_sstatus2.tag;
127762306a36Sopenharmony_ci	return result;
127862306a36Sopenharmony_ci}
127962306a36Sopenharmony_ci
128062306a36Sopenharmony_ci/**
128162306a36Sopenharmony_ci * Get the POW WQE for this core. This returns the work queue
128262306a36Sopenharmony_ci * entry currently associated with this core.
128362306a36Sopenharmony_ci *
128462306a36Sopenharmony_ci * Returns WQE pointer
128562306a36Sopenharmony_ci */
128662306a36Sopenharmony_cistatic inline struct cvmx_wqe *cvmx_pow_get_current_wqp(void)
128762306a36Sopenharmony_ci{
128862306a36Sopenharmony_ci	cvmx_pow_load_addr_t load_addr;
128962306a36Sopenharmony_ci	cvmx_pow_tag_load_resp_t load_resp;
129062306a36Sopenharmony_ci
129162306a36Sopenharmony_ci	load_addr.u64 = 0;
129262306a36Sopenharmony_ci	load_addr.sstatus.mem_region = CVMX_IO_SEG;
129362306a36Sopenharmony_ci	load_addr.sstatus.is_io = 1;
129462306a36Sopenharmony_ci	load_addr.sstatus.did = CVMX_OCT_DID_TAG_TAG1;
129562306a36Sopenharmony_ci	load_addr.sstatus.coreid = cvmx_get_core_num();
129662306a36Sopenharmony_ci	load_addr.sstatus.get_cur = 1;
129762306a36Sopenharmony_ci	load_addr.sstatus.get_wqp = 1;
129862306a36Sopenharmony_ci	load_resp.u64 = cvmx_read_csr(load_addr.u64);
129962306a36Sopenharmony_ci	return (struct cvmx_wqe *) cvmx_phys_to_ptr(load_resp.s_sstatus4.wqp);
130062306a36Sopenharmony_ci}
130162306a36Sopenharmony_ci
130262306a36Sopenharmony_ci#ifndef CVMX_MF_CHORD
130362306a36Sopenharmony_ci#define CVMX_MF_CHORD(dest)	    CVMX_RDHWR(dest, 30)
130462306a36Sopenharmony_ci#endif
130562306a36Sopenharmony_ci
130662306a36Sopenharmony_ci/**
130762306a36Sopenharmony_ci * Print a warning if a tag switch is pending for this core
130862306a36Sopenharmony_ci *
130962306a36Sopenharmony_ci * @function: Function name checking for a pending tag switch
131062306a36Sopenharmony_ci */
131162306a36Sopenharmony_cistatic inline void __cvmx_pow_warn_if_pending_switch(const char *function)
131262306a36Sopenharmony_ci{
131362306a36Sopenharmony_ci	uint64_t switch_complete;
131462306a36Sopenharmony_ci	CVMX_MF_CHORD(switch_complete);
131562306a36Sopenharmony_ci	if (!switch_complete)
131662306a36Sopenharmony_ci		pr_warn("%s called with tag switch in progress\n", function);
131762306a36Sopenharmony_ci}
131862306a36Sopenharmony_ci
131962306a36Sopenharmony_ci/**
132062306a36Sopenharmony_ci * Waits for a tag switch to complete by polling the completion bit.
132162306a36Sopenharmony_ci * Note that switches to NULL complete immediately and do not need
132262306a36Sopenharmony_ci * to be waited for.
132362306a36Sopenharmony_ci */
132462306a36Sopenharmony_cistatic inline void cvmx_pow_tag_sw_wait(void)
132562306a36Sopenharmony_ci{
132662306a36Sopenharmony_ci	const uint64_t MAX_CYCLES = 1ull << 31;
132762306a36Sopenharmony_ci	uint64_t switch_complete;
132862306a36Sopenharmony_ci	uint64_t start_cycle = cvmx_get_cycle();
132962306a36Sopenharmony_ci	while (1) {
133062306a36Sopenharmony_ci		CVMX_MF_CHORD(switch_complete);
133162306a36Sopenharmony_ci		if (unlikely(switch_complete))
133262306a36Sopenharmony_ci			break;
133362306a36Sopenharmony_ci		if (unlikely(cvmx_get_cycle() > start_cycle + MAX_CYCLES)) {
133462306a36Sopenharmony_ci			pr_warn("Tag switch is taking a long time, possible deadlock\n");
133562306a36Sopenharmony_ci			start_cycle = -MAX_CYCLES - 1;
133662306a36Sopenharmony_ci		}
133762306a36Sopenharmony_ci	}
133862306a36Sopenharmony_ci}
133962306a36Sopenharmony_ci
134062306a36Sopenharmony_ci/**
134162306a36Sopenharmony_ci * Synchronous work request.  Requests work from the POW.
134262306a36Sopenharmony_ci * This function does NOT wait for previous tag switches to complete,
134362306a36Sopenharmony_ci * so the caller must ensure that there is not a pending tag switch.
134462306a36Sopenharmony_ci *
134562306a36Sopenharmony_ci * @wait:   When set, call stalls until work becomes avaiable, or times out.
134662306a36Sopenharmony_ci *		 If not set, returns immediately.
134762306a36Sopenharmony_ci *
134862306a36Sopenharmony_ci * Returns: the WQE pointer from POW. Returns NULL if no work
134962306a36Sopenharmony_ci * was available.
135062306a36Sopenharmony_ci */
135162306a36Sopenharmony_cistatic inline struct cvmx_wqe *cvmx_pow_work_request_sync_nocheck(cvmx_pow_wait_t
135262306a36Sopenharmony_ci							     wait)
135362306a36Sopenharmony_ci{
135462306a36Sopenharmony_ci	cvmx_pow_load_addr_t ptr;
135562306a36Sopenharmony_ci	cvmx_pow_tag_load_resp_t result;
135662306a36Sopenharmony_ci
135762306a36Sopenharmony_ci	if (CVMX_ENABLE_POW_CHECKS)
135862306a36Sopenharmony_ci		__cvmx_pow_warn_if_pending_switch(__func__);
135962306a36Sopenharmony_ci
136062306a36Sopenharmony_ci	ptr.u64 = 0;
136162306a36Sopenharmony_ci	ptr.swork.mem_region = CVMX_IO_SEG;
136262306a36Sopenharmony_ci	ptr.swork.is_io = 1;
136362306a36Sopenharmony_ci	ptr.swork.did = CVMX_OCT_DID_TAG_SWTAG;
136462306a36Sopenharmony_ci	ptr.swork.wait = wait;
136562306a36Sopenharmony_ci
136662306a36Sopenharmony_ci	result.u64 = cvmx_read_csr(ptr.u64);
136762306a36Sopenharmony_ci
136862306a36Sopenharmony_ci	if (result.s_work.no_work)
136962306a36Sopenharmony_ci		return NULL;
137062306a36Sopenharmony_ci	else
137162306a36Sopenharmony_ci		return (struct cvmx_wqe *) cvmx_phys_to_ptr(result.s_work.addr);
137262306a36Sopenharmony_ci}
137362306a36Sopenharmony_ci
137462306a36Sopenharmony_ci/**
137562306a36Sopenharmony_ci * Synchronous work request.  Requests work from the POW.
137662306a36Sopenharmony_ci * This function waits for any previous tag switch to complete before
137762306a36Sopenharmony_ci * requesting the new work.
137862306a36Sopenharmony_ci *
137962306a36Sopenharmony_ci * @wait:   When set, call stalls until work becomes avaiable, or times out.
138062306a36Sopenharmony_ci *		 If not set, returns immediately.
138162306a36Sopenharmony_ci *
138262306a36Sopenharmony_ci * Returns: the WQE pointer from POW. Returns NULL if no work
138362306a36Sopenharmony_ci * was available.
138462306a36Sopenharmony_ci */
138562306a36Sopenharmony_cistatic inline struct cvmx_wqe *cvmx_pow_work_request_sync(cvmx_pow_wait_t wait)
138662306a36Sopenharmony_ci{
138762306a36Sopenharmony_ci	if (CVMX_ENABLE_POW_CHECKS)
138862306a36Sopenharmony_ci		__cvmx_pow_warn_if_pending_switch(__func__);
138962306a36Sopenharmony_ci
139062306a36Sopenharmony_ci	/* Must not have a switch pending when requesting work */
139162306a36Sopenharmony_ci	cvmx_pow_tag_sw_wait();
139262306a36Sopenharmony_ci	return cvmx_pow_work_request_sync_nocheck(wait);
139362306a36Sopenharmony_ci
139462306a36Sopenharmony_ci}
139562306a36Sopenharmony_ci
139662306a36Sopenharmony_ci/**
139762306a36Sopenharmony_ci * Synchronous null_rd request.	 Requests a switch out of NULL_NULL POW state.
139862306a36Sopenharmony_ci * This function waits for any previous tag switch to complete before
139962306a36Sopenharmony_ci * requesting the null_rd.
140062306a36Sopenharmony_ci *
140162306a36Sopenharmony_ci * Returns: the POW state of type cvmx_pow_tag_type_t.
140262306a36Sopenharmony_ci */
140362306a36Sopenharmony_cistatic inline enum cvmx_pow_tag_type cvmx_pow_work_request_null_rd(void)
140462306a36Sopenharmony_ci{
140562306a36Sopenharmony_ci	cvmx_pow_load_addr_t ptr;
140662306a36Sopenharmony_ci	cvmx_pow_tag_load_resp_t result;
140762306a36Sopenharmony_ci
140862306a36Sopenharmony_ci	if (CVMX_ENABLE_POW_CHECKS)
140962306a36Sopenharmony_ci		__cvmx_pow_warn_if_pending_switch(__func__);
141062306a36Sopenharmony_ci
141162306a36Sopenharmony_ci	/* Must not have a switch pending when requesting work */
141262306a36Sopenharmony_ci	cvmx_pow_tag_sw_wait();
141362306a36Sopenharmony_ci
141462306a36Sopenharmony_ci	ptr.u64 = 0;
141562306a36Sopenharmony_ci	ptr.snull_rd.mem_region = CVMX_IO_SEG;
141662306a36Sopenharmony_ci	ptr.snull_rd.is_io = 1;
141762306a36Sopenharmony_ci	ptr.snull_rd.did = CVMX_OCT_DID_TAG_NULL_RD;
141862306a36Sopenharmony_ci
141962306a36Sopenharmony_ci	result.u64 = cvmx_read_csr(ptr.u64);
142062306a36Sopenharmony_ci
142162306a36Sopenharmony_ci	return (enum cvmx_pow_tag_type) result.s_null_rd.state;
142262306a36Sopenharmony_ci}
142362306a36Sopenharmony_ci
142462306a36Sopenharmony_ci/**
142562306a36Sopenharmony_ci * Asynchronous work request.  Work is requested from the POW unit,
142662306a36Sopenharmony_ci * and should later be checked with function
142762306a36Sopenharmony_ci * cvmx_pow_work_response_async.  This function does NOT wait for
142862306a36Sopenharmony_ci * previous tag switches to complete, so the caller must ensure that
142962306a36Sopenharmony_ci * there is not a pending tag switch.
143062306a36Sopenharmony_ci *
143162306a36Sopenharmony_ci * @scr_addr: Scratch memory address that response will be returned
143262306a36Sopenharmony_ci *	      to, which is either a valid WQE, or a response with the
143362306a36Sopenharmony_ci *	      invalid bit set.	Byte address, must be 8 byte aligned.
143462306a36Sopenharmony_ci *
143562306a36Sopenharmony_ci * @wait: 1 to cause response to wait for work to become available (or
143662306a36Sopenharmony_ci *	  timeout), 0 to cause response to return immediately
143762306a36Sopenharmony_ci */
143862306a36Sopenharmony_cistatic inline void cvmx_pow_work_request_async_nocheck(int scr_addr,
143962306a36Sopenharmony_ci						       cvmx_pow_wait_t wait)
144062306a36Sopenharmony_ci{
144162306a36Sopenharmony_ci	cvmx_pow_iobdma_store_t data;
144262306a36Sopenharmony_ci
144362306a36Sopenharmony_ci	if (CVMX_ENABLE_POW_CHECKS)
144462306a36Sopenharmony_ci		__cvmx_pow_warn_if_pending_switch(__func__);
144562306a36Sopenharmony_ci
144662306a36Sopenharmony_ci	/* scr_addr must be 8 byte aligned */
144762306a36Sopenharmony_ci	data.s.scraddr = scr_addr >> 3;
144862306a36Sopenharmony_ci	data.s.len = 1;
144962306a36Sopenharmony_ci	data.s.did = CVMX_OCT_DID_TAG_SWTAG;
145062306a36Sopenharmony_ci	data.s.wait = wait;
145162306a36Sopenharmony_ci	cvmx_send_single(data.u64);
145262306a36Sopenharmony_ci}
145362306a36Sopenharmony_ci
145462306a36Sopenharmony_ci/**
145562306a36Sopenharmony_ci * Asynchronous work request.  Work is requested from the POW unit,
145662306a36Sopenharmony_ci * and should later be checked with function
145762306a36Sopenharmony_ci * cvmx_pow_work_response_async.  This function waits for any previous
145862306a36Sopenharmony_ci * tag switch to complete before requesting the new work.
145962306a36Sopenharmony_ci *
146062306a36Sopenharmony_ci * @scr_addr: Scratch memory address that response will be returned
146162306a36Sopenharmony_ci *	      to, which is either a valid WQE, or a response with the
146262306a36Sopenharmony_ci *	      invalid bit set.	Byte address, must be 8 byte aligned.
146362306a36Sopenharmony_ci *
146462306a36Sopenharmony_ci * @wait: 1 to cause response to wait for work to become available (or
146562306a36Sopenharmony_ci *		    timeout), 0 to cause response to return immediately
146662306a36Sopenharmony_ci */
146762306a36Sopenharmony_cistatic inline void cvmx_pow_work_request_async(int scr_addr,
146862306a36Sopenharmony_ci					       cvmx_pow_wait_t wait)
146962306a36Sopenharmony_ci{
147062306a36Sopenharmony_ci	if (CVMX_ENABLE_POW_CHECKS)
147162306a36Sopenharmony_ci		__cvmx_pow_warn_if_pending_switch(__func__);
147262306a36Sopenharmony_ci
147362306a36Sopenharmony_ci	/* Must not have a switch pending when requesting work */
147462306a36Sopenharmony_ci	cvmx_pow_tag_sw_wait();
147562306a36Sopenharmony_ci	cvmx_pow_work_request_async_nocheck(scr_addr, wait);
147662306a36Sopenharmony_ci}
147762306a36Sopenharmony_ci
147862306a36Sopenharmony_ci/**
147962306a36Sopenharmony_ci * Gets result of asynchronous work request.  Performs a IOBDMA sync
148062306a36Sopenharmony_ci * to wait for the response.
148162306a36Sopenharmony_ci *
148262306a36Sopenharmony_ci * @scr_addr: Scratch memory address to get result from Byte address,
148362306a36Sopenharmony_ci *	      must be 8 byte aligned.
148462306a36Sopenharmony_ci *
148562306a36Sopenharmony_ci * Returns: the WQE from the scratch register, or NULL if no
148662306a36Sopenharmony_ci * work was available.
148762306a36Sopenharmony_ci */
148862306a36Sopenharmony_cistatic inline struct cvmx_wqe *cvmx_pow_work_response_async(int scr_addr)
148962306a36Sopenharmony_ci{
149062306a36Sopenharmony_ci	cvmx_pow_tag_load_resp_t result;
149162306a36Sopenharmony_ci
149262306a36Sopenharmony_ci	CVMX_SYNCIOBDMA;
149362306a36Sopenharmony_ci	result.u64 = cvmx_scratch_read64(scr_addr);
149462306a36Sopenharmony_ci
149562306a36Sopenharmony_ci	if (result.s_work.no_work)
149662306a36Sopenharmony_ci		return NULL;
149762306a36Sopenharmony_ci	else
149862306a36Sopenharmony_ci		return (struct cvmx_wqe *) cvmx_phys_to_ptr(result.s_work.addr);
149962306a36Sopenharmony_ci}
150062306a36Sopenharmony_ci
150162306a36Sopenharmony_ci/**
150262306a36Sopenharmony_ci * Checks if a work queue entry pointer returned by a work
150362306a36Sopenharmony_ci * request is valid.  It may be invalid due to no work
150462306a36Sopenharmony_ci * being available or due to a timeout.
150562306a36Sopenharmony_ci *
150662306a36Sopenharmony_ci * @wqe_ptr: pointer to a work queue entry returned by the POW
150762306a36Sopenharmony_ci *
150862306a36Sopenharmony_ci * Returns 0 if pointer is valid
150962306a36Sopenharmony_ci *	   1 if invalid (no work was returned)
151062306a36Sopenharmony_ci */
151162306a36Sopenharmony_cistatic inline uint64_t cvmx_pow_work_invalid(struct cvmx_wqe *wqe_ptr)
151262306a36Sopenharmony_ci{
151362306a36Sopenharmony_ci	return wqe_ptr == NULL;
151462306a36Sopenharmony_ci}
151562306a36Sopenharmony_ci
151662306a36Sopenharmony_ci/**
151762306a36Sopenharmony_ci * Starts a tag switch to the provided tag value and tag type.
151862306a36Sopenharmony_ci * Completion for the tag switch must be checked for separately.  This
151962306a36Sopenharmony_ci * function does NOT update the work queue entry in dram to match tag
152062306a36Sopenharmony_ci * value and type, so the application must keep track of these if they
152162306a36Sopenharmony_ci * are important to the application.  This tag switch command must not
152262306a36Sopenharmony_ci * be used for switches to NULL, as the tag switch pending bit will be
152362306a36Sopenharmony_ci * set by the switch request, but never cleared by the hardware.
152462306a36Sopenharmony_ci *
152562306a36Sopenharmony_ci * NOTE: This should not be used when switching from a NULL tag.  Use
152662306a36Sopenharmony_ci * cvmx_pow_tag_sw_full() instead.
152762306a36Sopenharmony_ci *
152862306a36Sopenharmony_ci * This function does no checks, so the caller must ensure that any
152962306a36Sopenharmony_ci * previous tag switch has completed.
153062306a36Sopenharmony_ci *
153162306a36Sopenharmony_ci * @tag:      new tag value
153262306a36Sopenharmony_ci * @tag_type: new tag type (ordered or atomic)
153362306a36Sopenharmony_ci */
153462306a36Sopenharmony_cistatic inline void cvmx_pow_tag_sw_nocheck(uint32_t tag,
153562306a36Sopenharmony_ci					   enum cvmx_pow_tag_type tag_type)
153662306a36Sopenharmony_ci{
153762306a36Sopenharmony_ci	cvmx_addr_t ptr;
153862306a36Sopenharmony_ci	cvmx_pow_tag_req_t tag_req;
153962306a36Sopenharmony_ci
154062306a36Sopenharmony_ci	if (CVMX_ENABLE_POW_CHECKS) {
154162306a36Sopenharmony_ci		cvmx_pow_tag_req_t current_tag;
154262306a36Sopenharmony_ci		__cvmx_pow_warn_if_pending_switch(__func__);
154362306a36Sopenharmony_ci		current_tag = cvmx_pow_get_current_tag();
154462306a36Sopenharmony_ci		if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL_NULL)
154562306a36Sopenharmony_ci			pr_warn("%s called with NULL_NULL tag\n", __func__);
154662306a36Sopenharmony_ci		if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL)
154762306a36Sopenharmony_ci			pr_warn("%s called with NULL tag\n", __func__);
154862306a36Sopenharmony_ci		if ((current_tag.s.type == tag_type)
154962306a36Sopenharmony_ci		   && (current_tag.s.tag == tag))
155062306a36Sopenharmony_ci			pr_warn("%s called to perform a tag switch to the same tag\n",
155162306a36Sopenharmony_ci				__func__);
155262306a36Sopenharmony_ci		if (tag_type == CVMX_POW_TAG_TYPE_NULL)
155362306a36Sopenharmony_ci			pr_warn("%s called to perform a tag switch to NULL. Use cvmx_pow_tag_sw_null() instead\n",
155462306a36Sopenharmony_ci				__func__);
155562306a36Sopenharmony_ci	}
155662306a36Sopenharmony_ci
155762306a36Sopenharmony_ci	/*
155862306a36Sopenharmony_ci	 * Note that WQE in DRAM is not updated here, as the POW does
155962306a36Sopenharmony_ci	 * not read from DRAM once the WQE is in flight.  See hardware
156062306a36Sopenharmony_ci	 * manual for complete details.	 It is the application's
156162306a36Sopenharmony_ci	 * responsibility to keep track of the current tag value if
156262306a36Sopenharmony_ci	 * that is important.
156362306a36Sopenharmony_ci	 */
156462306a36Sopenharmony_ci
156562306a36Sopenharmony_ci	tag_req.u64 = 0;
156662306a36Sopenharmony_ci	tag_req.s.op = CVMX_POW_TAG_OP_SWTAG;
156762306a36Sopenharmony_ci	tag_req.s.tag = tag;
156862306a36Sopenharmony_ci	tag_req.s.type = tag_type;
156962306a36Sopenharmony_ci
157062306a36Sopenharmony_ci	ptr.u64 = 0;
157162306a36Sopenharmony_ci	ptr.sio.mem_region = CVMX_IO_SEG;
157262306a36Sopenharmony_ci	ptr.sio.is_io = 1;
157362306a36Sopenharmony_ci	ptr.sio.did = CVMX_OCT_DID_TAG_SWTAG;
157462306a36Sopenharmony_ci
157562306a36Sopenharmony_ci	/* once this store arrives at POW, it will attempt the switch
157662306a36Sopenharmony_ci	   software must wait for the switch to complete separately */
157762306a36Sopenharmony_ci	cvmx_write_io(ptr.u64, tag_req.u64);
157862306a36Sopenharmony_ci}
157962306a36Sopenharmony_ci
158062306a36Sopenharmony_ci/**
158162306a36Sopenharmony_ci * Starts a tag switch to the provided tag value and tag type.
158262306a36Sopenharmony_ci * Completion for the tag switch must be checked for separately.  This
158362306a36Sopenharmony_ci * function does NOT update the work queue entry in dram to match tag
158462306a36Sopenharmony_ci * value and type, so the application must keep track of these if they
158562306a36Sopenharmony_ci * are important to the application.  This tag switch command must not
158662306a36Sopenharmony_ci * be used for switches to NULL, as the tag switch pending bit will be
158762306a36Sopenharmony_ci * set by the switch request, but never cleared by the hardware.
158862306a36Sopenharmony_ci *
158962306a36Sopenharmony_ci * NOTE: This should not be used when switching from a NULL tag.  Use
159062306a36Sopenharmony_ci * cvmx_pow_tag_sw_full() instead.
159162306a36Sopenharmony_ci *
159262306a36Sopenharmony_ci * This function waits for any previous tag switch to complete, and also
159362306a36Sopenharmony_ci * displays an error on tag switches to NULL.
159462306a36Sopenharmony_ci *
159562306a36Sopenharmony_ci * @tag:      new tag value
159662306a36Sopenharmony_ci * @tag_type: new tag type (ordered or atomic)
159762306a36Sopenharmony_ci */
159862306a36Sopenharmony_cistatic inline void cvmx_pow_tag_sw(uint32_t tag,
159962306a36Sopenharmony_ci				   enum cvmx_pow_tag_type tag_type)
160062306a36Sopenharmony_ci{
160162306a36Sopenharmony_ci	if (CVMX_ENABLE_POW_CHECKS)
160262306a36Sopenharmony_ci		__cvmx_pow_warn_if_pending_switch(__func__);
160362306a36Sopenharmony_ci
160462306a36Sopenharmony_ci	/*
160562306a36Sopenharmony_ci	 * Note that WQE in DRAM is not updated here, as the POW does
160662306a36Sopenharmony_ci	 * not read from DRAM once the WQE is in flight.  See hardware
160762306a36Sopenharmony_ci	 * manual for complete details.	 It is the application's
160862306a36Sopenharmony_ci	 * responsibility to keep track of the current tag value if
160962306a36Sopenharmony_ci	 * that is important.
161062306a36Sopenharmony_ci	 */
161162306a36Sopenharmony_ci
161262306a36Sopenharmony_ci	/*
161362306a36Sopenharmony_ci	 * Ensure that there is not a pending tag switch, as a tag
161462306a36Sopenharmony_ci	 * switch cannot be started if a previous switch is still
161562306a36Sopenharmony_ci	 * pending.
161662306a36Sopenharmony_ci	 */
161762306a36Sopenharmony_ci	cvmx_pow_tag_sw_wait();
161862306a36Sopenharmony_ci	cvmx_pow_tag_sw_nocheck(tag, tag_type);
161962306a36Sopenharmony_ci}
162062306a36Sopenharmony_ci
162162306a36Sopenharmony_ci/**
162262306a36Sopenharmony_ci * Starts a tag switch to the provided tag value and tag type.
162362306a36Sopenharmony_ci * Completion for the tag switch must be checked for separately.  This
162462306a36Sopenharmony_ci * function does NOT update the work queue entry in dram to match tag
162562306a36Sopenharmony_ci * value and type, so the application must keep track of these if they
162662306a36Sopenharmony_ci * are important to the application.  This tag switch command must not
162762306a36Sopenharmony_ci * be used for switches to NULL, as the tag switch pending bit will be
162862306a36Sopenharmony_ci * set by the switch request, but never cleared by the hardware.
162962306a36Sopenharmony_ci *
163062306a36Sopenharmony_ci * This function must be used for tag switches from NULL.
163162306a36Sopenharmony_ci *
163262306a36Sopenharmony_ci * This function does no checks, so the caller must ensure that any
163362306a36Sopenharmony_ci * previous tag switch has completed.
163462306a36Sopenharmony_ci *
163562306a36Sopenharmony_ci * @wqp:      pointer to work queue entry to submit.  This entry is
163662306a36Sopenharmony_ci *	      updated to match the other parameters
163762306a36Sopenharmony_ci * @tag:      tag value to be assigned to work queue entry
163862306a36Sopenharmony_ci * @tag_type: type of tag
163962306a36Sopenharmony_ci * @group:    group value for the work queue entry.
164062306a36Sopenharmony_ci */
164162306a36Sopenharmony_cistatic inline void cvmx_pow_tag_sw_full_nocheck(struct cvmx_wqe *wqp, uint32_t tag,
164262306a36Sopenharmony_ci						enum cvmx_pow_tag_type tag_type,
164362306a36Sopenharmony_ci						uint64_t group)
164462306a36Sopenharmony_ci{
164562306a36Sopenharmony_ci	cvmx_addr_t ptr;
164662306a36Sopenharmony_ci	cvmx_pow_tag_req_t tag_req;
164762306a36Sopenharmony_ci
164862306a36Sopenharmony_ci	if (CVMX_ENABLE_POW_CHECKS) {
164962306a36Sopenharmony_ci		cvmx_pow_tag_req_t current_tag;
165062306a36Sopenharmony_ci		__cvmx_pow_warn_if_pending_switch(__func__);
165162306a36Sopenharmony_ci		current_tag = cvmx_pow_get_current_tag();
165262306a36Sopenharmony_ci		if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL_NULL)
165362306a36Sopenharmony_ci			pr_warn("%s called with NULL_NULL tag\n", __func__);
165462306a36Sopenharmony_ci		if ((current_tag.s.type == tag_type)
165562306a36Sopenharmony_ci		   && (current_tag.s.tag == tag))
165662306a36Sopenharmony_ci			pr_warn("%s called to perform a tag switch to the same tag\n",
165762306a36Sopenharmony_ci				__func__);
165862306a36Sopenharmony_ci		if (tag_type == CVMX_POW_TAG_TYPE_NULL)
165962306a36Sopenharmony_ci			pr_warn("%s called to perform a tag switch to NULL. Use cvmx_pow_tag_sw_null() instead\n",
166062306a36Sopenharmony_ci				__func__);
166162306a36Sopenharmony_ci		if (wqp != cvmx_phys_to_ptr(0x80))
166262306a36Sopenharmony_ci			if (wqp != cvmx_pow_get_current_wqp())
166362306a36Sopenharmony_ci				pr_warn("%s passed WQE(%p) doesn't match the address in the POW(%p)\n",
166462306a36Sopenharmony_ci					__func__, wqp,
166562306a36Sopenharmony_ci					cvmx_pow_get_current_wqp());
166662306a36Sopenharmony_ci	}
166762306a36Sopenharmony_ci
166862306a36Sopenharmony_ci	/*
166962306a36Sopenharmony_ci	 * Note that WQE in DRAM is not updated here, as the POW does
167062306a36Sopenharmony_ci	 * not read from DRAM once the WQE is in flight.  See hardware
167162306a36Sopenharmony_ci	 * manual for complete details.	 It is the application's
167262306a36Sopenharmony_ci	 * responsibility to keep track of the current tag value if
167362306a36Sopenharmony_ci	 * that is important.
167462306a36Sopenharmony_ci	 */
167562306a36Sopenharmony_ci
167662306a36Sopenharmony_ci	tag_req.u64 = 0;
167762306a36Sopenharmony_ci	tag_req.s.op = CVMX_POW_TAG_OP_SWTAG_FULL;
167862306a36Sopenharmony_ci	tag_req.s.tag = tag;
167962306a36Sopenharmony_ci	tag_req.s.type = tag_type;
168062306a36Sopenharmony_ci	tag_req.s.grp = group;
168162306a36Sopenharmony_ci
168262306a36Sopenharmony_ci	ptr.u64 = 0;
168362306a36Sopenharmony_ci	ptr.sio.mem_region = CVMX_IO_SEG;
168462306a36Sopenharmony_ci	ptr.sio.is_io = 1;
168562306a36Sopenharmony_ci	ptr.sio.did = CVMX_OCT_DID_TAG_SWTAG;
168662306a36Sopenharmony_ci	ptr.sio.offset = CAST64(wqp);
168762306a36Sopenharmony_ci
168862306a36Sopenharmony_ci	/*
168962306a36Sopenharmony_ci	 * once this store arrives at POW, it will attempt the switch
169062306a36Sopenharmony_ci	 * software must wait for the switch to complete separately.
169162306a36Sopenharmony_ci	 */
169262306a36Sopenharmony_ci	cvmx_write_io(ptr.u64, tag_req.u64);
169362306a36Sopenharmony_ci}
169462306a36Sopenharmony_ci
169562306a36Sopenharmony_ci/**
169662306a36Sopenharmony_ci * Starts a tag switch to the provided tag value and tag type.
169762306a36Sopenharmony_ci * Completion for the tag switch must be checked for separately.  This
169862306a36Sopenharmony_ci * function does NOT update the work queue entry in dram to match tag
169962306a36Sopenharmony_ci * value and type, so the application must keep track of these if they
170062306a36Sopenharmony_ci * are important to the application.  This tag switch command must not
170162306a36Sopenharmony_ci * be used for switches to NULL, as the tag switch pending bit will be
170262306a36Sopenharmony_ci * set by the switch request, but never cleared by the hardware.
170362306a36Sopenharmony_ci *
170462306a36Sopenharmony_ci * This function must be used for tag switches from NULL.
170562306a36Sopenharmony_ci *
170662306a36Sopenharmony_ci * This function waits for any pending tag switches to complete
170762306a36Sopenharmony_ci * before requesting the tag switch.
170862306a36Sopenharmony_ci *
170962306a36Sopenharmony_ci * @wqp:      pointer to work queue entry to submit.  This entry is updated
171062306a36Sopenharmony_ci *	      to match the other parameters
171162306a36Sopenharmony_ci * @tag:      tag value to be assigned to work queue entry
171262306a36Sopenharmony_ci * @tag_type: type of tag
171362306a36Sopenharmony_ci * @group:	group value for the work queue entry.
171462306a36Sopenharmony_ci */
171562306a36Sopenharmony_cistatic inline void cvmx_pow_tag_sw_full(struct cvmx_wqe *wqp, uint32_t tag,
171662306a36Sopenharmony_ci					enum cvmx_pow_tag_type tag_type,
171762306a36Sopenharmony_ci					uint64_t group)
171862306a36Sopenharmony_ci{
171962306a36Sopenharmony_ci	if (CVMX_ENABLE_POW_CHECKS)
172062306a36Sopenharmony_ci		__cvmx_pow_warn_if_pending_switch(__func__);
172162306a36Sopenharmony_ci
172262306a36Sopenharmony_ci	/*
172362306a36Sopenharmony_ci	 * Ensure that there is not a pending tag switch, as a tag
172462306a36Sopenharmony_ci	 * switch cannot be started if a previous switch is still
172562306a36Sopenharmony_ci	 * pending.
172662306a36Sopenharmony_ci	 */
172762306a36Sopenharmony_ci	cvmx_pow_tag_sw_wait();
172862306a36Sopenharmony_ci	cvmx_pow_tag_sw_full_nocheck(wqp, tag, tag_type, group);
172962306a36Sopenharmony_ci}
173062306a36Sopenharmony_ci
173162306a36Sopenharmony_ci/**
173262306a36Sopenharmony_ci * Switch to a NULL tag, which ends any ordering or
173362306a36Sopenharmony_ci * synchronization provided by the POW for the current
173462306a36Sopenharmony_ci * work queue entry.  This operation completes immediately,
173562306a36Sopenharmony_ci * so completion should not be waited for.
173662306a36Sopenharmony_ci * This function does NOT wait for previous tag switches to complete,
173762306a36Sopenharmony_ci * so the caller must ensure that any previous tag switches have completed.
173862306a36Sopenharmony_ci */
173962306a36Sopenharmony_cistatic inline void cvmx_pow_tag_sw_null_nocheck(void)
174062306a36Sopenharmony_ci{
174162306a36Sopenharmony_ci	cvmx_addr_t ptr;
174262306a36Sopenharmony_ci	cvmx_pow_tag_req_t tag_req;
174362306a36Sopenharmony_ci
174462306a36Sopenharmony_ci	if (CVMX_ENABLE_POW_CHECKS) {
174562306a36Sopenharmony_ci		cvmx_pow_tag_req_t current_tag;
174662306a36Sopenharmony_ci		__cvmx_pow_warn_if_pending_switch(__func__);
174762306a36Sopenharmony_ci		current_tag = cvmx_pow_get_current_tag();
174862306a36Sopenharmony_ci		if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL_NULL)
174962306a36Sopenharmony_ci			pr_warn("%s called with NULL_NULL tag\n", __func__);
175062306a36Sopenharmony_ci		if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL)
175162306a36Sopenharmony_ci			pr_warn("%s called when we already have a NULL tag\n",
175262306a36Sopenharmony_ci				__func__);
175362306a36Sopenharmony_ci	}
175462306a36Sopenharmony_ci
175562306a36Sopenharmony_ci	tag_req.u64 = 0;
175662306a36Sopenharmony_ci	tag_req.s.op = CVMX_POW_TAG_OP_SWTAG;
175762306a36Sopenharmony_ci	tag_req.s.type = CVMX_POW_TAG_TYPE_NULL;
175862306a36Sopenharmony_ci
175962306a36Sopenharmony_ci	ptr.u64 = 0;
176062306a36Sopenharmony_ci	ptr.sio.mem_region = CVMX_IO_SEG;
176162306a36Sopenharmony_ci	ptr.sio.is_io = 1;
176262306a36Sopenharmony_ci	ptr.sio.did = CVMX_OCT_DID_TAG_TAG1;
176362306a36Sopenharmony_ci
176462306a36Sopenharmony_ci	cvmx_write_io(ptr.u64, tag_req.u64);
176562306a36Sopenharmony_ci
176662306a36Sopenharmony_ci	/* switch to NULL completes immediately */
176762306a36Sopenharmony_ci}
176862306a36Sopenharmony_ci
176962306a36Sopenharmony_ci/**
177062306a36Sopenharmony_ci * Switch to a NULL tag, which ends any ordering or
177162306a36Sopenharmony_ci * synchronization provided by the POW for the current
177262306a36Sopenharmony_ci * work queue entry.  This operation completes immediately,
177362306a36Sopenharmony_ci * so completion should not be waited for.
177462306a36Sopenharmony_ci * This function waits for any pending tag switches to complete
177562306a36Sopenharmony_ci * before requesting the switch to NULL.
177662306a36Sopenharmony_ci */
177762306a36Sopenharmony_cistatic inline void cvmx_pow_tag_sw_null(void)
177862306a36Sopenharmony_ci{
177962306a36Sopenharmony_ci	if (CVMX_ENABLE_POW_CHECKS)
178062306a36Sopenharmony_ci		__cvmx_pow_warn_if_pending_switch(__func__);
178162306a36Sopenharmony_ci
178262306a36Sopenharmony_ci	/*
178362306a36Sopenharmony_ci	 * Ensure that there is not a pending tag switch, as a tag
178462306a36Sopenharmony_ci	 * switch cannot be started if a previous switch is still
178562306a36Sopenharmony_ci	 * pending.
178662306a36Sopenharmony_ci	 */
178762306a36Sopenharmony_ci	cvmx_pow_tag_sw_wait();
178862306a36Sopenharmony_ci	cvmx_pow_tag_sw_null_nocheck();
178962306a36Sopenharmony_ci
179062306a36Sopenharmony_ci	/* switch to NULL completes immediately */
179162306a36Sopenharmony_ci}
179262306a36Sopenharmony_ci
179362306a36Sopenharmony_ci/**
179462306a36Sopenharmony_ci * Submits work to an input queue.  This function updates the work
179562306a36Sopenharmony_ci * queue entry in DRAM to match the arguments given.  Note that the
179662306a36Sopenharmony_ci * tag provided is for the work queue entry submitted, and is
179762306a36Sopenharmony_ci * unrelated to the tag that the core currently holds.
179862306a36Sopenharmony_ci *
179962306a36Sopenharmony_ci * @wqp:      pointer to work queue entry to submit.  This entry is
180062306a36Sopenharmony_ci *	      updated to match the other parameters
180162306a36Sopenharmony_ci * @tag:      tag value to be assigned to work queue entry
180262306a36Sopenharmony_ci * @tag_type: type of tag
180362306a36Sopenharmony_ci * @qos:      Input queue to add to.
180462306a36Sopenharmony_ci * @grp:      group value for the work queue entry.
180562306a36Sopenharmony_ci */
180662306a36Sopenharmony_cistatic inline void cvmx_pow_work_submit(struct cvmx_wqe *wqp, uint32_t tag,
180762306a36Sopenharmony_ci					enum cvmx_pow_tag_type tag_type,
180862306a36Sopenharmony_ci					uint64_t qos, uint64_t grp)
180962306a36Sopenharmony_ci{
181062306a36Sopenharmony_ci	cvmx_addr_t ptr;
181162306a36Sopenharmony_ci	cvmx_pow_tag_req_t tag_req;
181262306a36Sopenharmony_ci
181362306a36Sopenharmony_ci	wqp->word1.tag = tag;
181462306a36Sopenharmony_ci	wqp->word1.tag_type = tag_type;
181562306a36Sopenharmony_ci
181662306a36Sopenharmony_ci	cvmx_wqe_set_qos(wqp, qos);
181762306a36Sopenharmony_ci	cvmx_wqe_set_grp(wqp, grp);
181862306a36Sopenharmony_ci
181962306a36Sopenharmony_ci	tag_req.u64 = 0;
182062306a36Sopenharmony_ci	tag_req.s.op = CVMX_POW_TAG_OP_ADDWQ;
182162306a36Sopenharmony_ci	tag_req.s.type = tag_type;
182262306a36Sopenharmony_ci	tag_req.s.tag = tag;
182362306a36Sopenharmony_ci	tag_req.s.qos = qos;
182462306a36Sopenharmony_ci	tag_req.s.grp = grp;
182562306a36Sopenharmony_ci
182662306a36Sopenharmony_ci	ptr.u64 = 0;
182762306a36Sopenharmony_ci	ptr.sio.mem_region = CVMX_IO_SEG;
182862306a36Sopenharmony_ci	ptr.sio.is_io = 1;
182962306a36Sopenharmony_ci	ptr.sio.did = CVMX_OCT_DID_TAG_TAG1;
183062306a36Sopenharmony_ci	ptr.sio.offset = cvmx_ptr_to_phys(wqp);
183162306a36Sopenharmony_ci
183262306a36Sopenharmony_ci	/*
183362306a36Sopenharmony_ci	 * SYNC write to memory before the work submit.	 This is
183462306a36Sopenharmony_ci	 * necessary as POW may read values from DRAM at this time.
183562306a36Sopenharmony_ci	 */
183662306a36Sopenharmony_ci	CVMX_SYNCWS;
183762306a36Sopenharmony_ci	cvmx_write_io(ptr.u64, tag_req.u64);
183862306a36Sopenharmony_ci}
183962306a36Sopenharmony_ci
184062306a36Sopenharmony_ci/**
184162306a36Sopenharmony_ci * This function sets the group mask for a core.  The group mask
184262306a36Sopenharmony_ci * indicates which groups each core will accept work from. There are
184362306a36Sopenharmony_ci * 16 groups.
184462306a36Sopenharmony_ci *
184562306a36Sopenharmony_ci * @core_num:	core to apply mask to
184662306a36Sopenharmony_ci * @mask:   Group mask. There are 16 groups, so only bits 0-15 are valid,
184762306a36Sopenharmony_ci *		 representing groups 0-15.
184862306a36Sopenharmony_ci *		 Each 1 bit in the mask enables the core to accept work from
184962306a36Sopenharmony_ci *		 the corresponding group.
185062306a36Sopenharmony_ci */
185162306a36Sopenharmony_cistatic inline void cvmx_pow_set_group_mask(uint64_t core_num, uint64_t mask)
185262306a36Sopenharmony_ci{
185362306a36Sopenharmony_ci	union cvmx_pow_pp_grp_mskx grp_msk;
185462306a36Sopenharmony_ci
185562306a36Sopenharmony_ci	grp_msk.u64 = cvmx_read_csr(CVMX_POW_PP_GRP_MSKX(core_num));
185662306a36Sopenharmony_ci	grp_msk.s.grp_msk = mask;
185762306a36Sopenharmony_ci	cvmx_write_csr(CVMX_POW_PP_GRP_MSKX(core_num), grp_msk.u64);
185862306a36Sopenharmony_ci}
185962306a36Sopenharmony_ci
186062306a36Sopenharmony_ci/**
186162306a36Sopenharmony_ci * This function sets POW static priorities for a core. Each input queue has
186262306a36Sopenharmony_ci * an associated priority value.
186362306a36Sopenharmony_ci *
186462306a36Sopenharmony_ci * @core_num:	core to apply priorities to
186562306a36Sopenharmony_ci * @priority:	Vector of 8 priorities, one per POW Input Queue (0-7).
186662306a36Sopenharmony_ci *		     Highest priority is 0 and lowest is 7. A priority value
186762306a36Sopenharmony_ci *		     of 0xF instructs POW to skip the Input Queue when
186862306a36Sopenharmony_ci *		     scheduling to this specific core.
186962306a36Sopenharmony_ci *		     NOTE: priorities should not have gaps in values, meaning
187062306a36Sopenharmony_ci *			   {0,1,1,1,1,1,1,1} is a valid configuration while
187162306a36Sopenharmony_ci *			   {0,2,2,2,2,2,2,2} is not.
187262306a36Sopenharmony_ci */
187362306a36Sopenharmony_cistatic inline void cvmx_pow_set_priority(uint64_t core_num,
187462306a36Sopenharmony_ci					 const uint8_t priority[])
187562306a36Sopenharmony_ci{
187662306a36Sopenharmony_ci	/* POW priorities are supported on CN5xxx and later */
187762306a36Sopenharmony_ci	if (!OCTEON_IS_MODEL(OCTEON_CN3XXX)) {
187862306a36Sopenharmony_ci		union cvmx_pow_pp_grp_mskx grp_msk;
187962306a36Sopenharmony_ci
188062306a36Sopenharmony_ci		grp_msk.u64 = cvmx_read_csr(CVMX_POW_PP_GRP_MSKX(core_num));
188162306a36Sopenharmony_ci		grp_msk.s.qos0_pri = priority[0];
188262306a36Sopenharmony_ci		grp_msk.s.qos1_pri = priority[1];
188362306a36Sopenharmony_ci		grp_msk.s.qos2_pri = priority[2];
188462306a36Sopenharmony_ci		grp_msk.s.qos3_pri = priority[3];
188562306a36Sopenharmony_ci		grp_msk.s.qos4_pri = priority[4];
188662306a36Sopenharmony_ci		grp_msk.s.qos5_pri = priority[5];
188762306a36Sopenharmony_ci		grp_msk.s.qos6_pri = priority[6];
188862306a36Sopenharmony_ci		grp_msk.s.qos7_pri = priority[7];
188962306a36Sopenharmony_ci
189062306a36Sopenharmony_ci		/* Detect gaps between priorities and flag error */
189162306a36Sopenharmony_ci		{
189262306a36Sopenharmony_ci			int i;
189362306a36Sopenharmony_ci			uint32_t prio_mask = 0;
189462306a36Sopenharmony_ci
189562306a36Sopenharmony_ci			for (i = 0; i < 8; i++)
189662306a36Sopenharmony_ci				if (priority[i] != 0xF)
189762306a36Sopenharmony_ci					prio_mask |= 1 << priority[i];
189862306a36Sopenharmony_ci
189962306a36Sopenharmony_ci			if (prio_mask ^ ((1 << cvmx_pop(prio_mask)) - 1)) {
190062306a36Sopenharmony_ci				pr_err("POW static priorities should be "
190162306a36Sopenharmony_ci				       "contiguous (0x%llx)\n",
190262306a36Sopenharmony_ci				     (unsigned long long)prio_mask);
190362306a36Sopenharmony_ci				return;
190462306a36Sopenharmony_ci			}
190562306a36Sopenharmony_ci		}
190662306a36Sopenharmony_ci
190762306a36Sopenharmony_ci		cvmx_write_csr(CVMX_POW_PP_GRP_MSKX(core_num), grp_msk.u64);
190862306a36Sopenharmony_ci	}
190962306a36Sopenharmony_ci}
191062306a36Sopenharmony_ci
191162306a36Sopenharmony_ci/**
191262306a36Sopenharmony_ci * Performs a tag switch and then an immediate deschedule. This completes
191362306a36Sopenharmony_ci * immediately, so completion must not be waited for.  This function does NOT
191462306a36Sopenharmony_ci * update the wqe in DRAM to match arguments.
191562306a36Sopenharmony_ci *
191662306a36Sopenharmony_ci * This function does NOT wait for any prior tag switches to complete, so the
191762306a36Sopenharmony_ci * calling code must do this.
191862306a36Sopenharmony_ci *
191962306a36Sopenharmony_ci * Note the following CAVEAT of the Octeon HW behavior when
192062306a36Sopenharmony_ci * re-scheduling DE-SCHEDULEd items whose (next) state is
192162306a36Sopenharmony_ci * ORDERED:
192262306a36Sopenharmony_ci *   - If there are no switches pending at the time that the
192362306a36Sopenharmony_ci *     HW executes the de-schedule, the HW will only re-schedule
192462306a36Sopenharmony_ci *     the head of the FIFO associated with the given tag. This
192562306a36Sopenharmony_ci *     means that in many respects, the HW treats this ORDERED
192662306a36Sopenharmony_ci *     tag as an ATOMIC tag. Note that in the SWTAG_DESCH
192762306a36Sopenharmony_ci *     case (to an ORDERED tag), the HW will do the switch
192862306a36Sopenharmony_ci *     before the deschedule whenever it is possible to do
192962306a36Sopenharmony_ci *     the switch immediately, so it may often look like
193062306a36Sopenharmony_ci *     this case.
193162306a36Sopenharmony_ci *   - If there is a pending switch to ORDERED at the time
193262306a36Sopenharmony_ci *     the HW executes the de-schedule, the HW will perform
193362306a36Sopenharmony_ci *     the switch at the time it re-schedules, and will be
193462306a36Sopenharmony_ci *     able to reschedule any/all of the entries with the
193562306a36Sopenharmony_ci *     same tag.
193662306a36Sopenharmony_ci * Due to this behavior, the RECOMMENDATION to software is
193762306a36Sopenharmony_ci * that they have a (next) state of ATOMIC when they
193862306a36Sopenharmony_ci * DE-SCHEDULE. If an ORDERED tag is what was really desired,
193962306a36Sopenharmony_ci * SW can choose to immediately switch to an ORDERED tag
194062306a36Sopenharmony_ci * after the work (that has an ATOMIC tag) is re-scheduled.
194162306a36Sopenharmony_ci * Note that since there are never any tag switches pending
194262306a36Sopenharmony_ci * when the HW re-schedules, this switch can be IMMEDIATE upon
194362306a36Sopenharmony_ci * the reception of the pointer during the re-schedule.
194462306a36Sopenharmony_ci *
194562306a36Sopenharmony_ci * @tag:      New tag value
194662306a36Sopenharmony_ci * @tag_type: New tag type
194762306a36Sopenharmony_ci * @group:    New group value
194862306a36Sopenharmony_ci * @no_sched: Control whether this work queue entry will be rescheduled.
194962306a36Sopenharmony_ci *		   - 1 : don't schedule this work
195062306a36Sopenharmony_ci *		   - 0 : allow this work to be scheduled.
195162306a36Sopenharmony_ci */
195262306a36Sopenharmony_cistatic inline void cvmx_pow_tag_sw_desched_nocheck(
195362306a36Sopenharmony_ci	uint32_t tag,
195462306a36Sopenharmony_ci	enum cvmx_pow_tag_type tag_type,
195562306a36Sopenharmony_ci	uint64_t group,
195662306a36Sopenharmony_ci	uint64_t no_sched)
195762306a36Sopenharmony_ci{
195862306a36Sopenharmony_ci	cvmx_addr_t ptr;
195962306a36Sopenharmony_ci	cvmx_pow_tag_req_t tag_req;
196062306a36Sopenharmony_ci
196162306a36Sopenharmony_ci	if (CVMX_ENABLE_POW_CHECKS) {
196262306a36Sopenharmony_ci		cvmx_pow_tag_req_t current_tag;
196362306a36Sopenharmony_ci		__cvmx_pow_warn_if_pending_switch(__func__);
196462306a36Sopenharmony_ci		current_tag = cvmx_pow_get_current_tag();
196562306a36Sopenharmony_ci		if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL_NULL)
196662306a36Sopenharmony_ci			pr_warn("%s called with NULL_NULL tag\n", __func__);
196762306a36Sopenharmony_ci		if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL)
196862306a36Sopenharmony_ci			pr_warn("%s called with NULL tag. Deschedule not allowed from NULL state\n",
196962306a36Sopenharmony_ci				__func__);
197062306a36Sopenharmony_ci		if ((current_tag.s.type != CVMX_POW_TAG_TYPE_ATOMIC)
197162306a36Sopenharmony_ci			&& (tag_type != CVMX_POW_TAG_TYPE_ATOMIC))
197262306a36Sopenharmony_ci			pr_warn("%s called where neither the before or after tag is ATOMIC\n",
197362306a36Sopenharmony_ci				__func__);
197462306a36Sopenharmony_ci	}
197562306a36Sopenharmony_ci
197662306a36Sopenharmony_ci	tag_req.u64 = 0;
197762306a36Sopenharmony_ci	tag_req.s.op = CVMX_POW_TAG_OP_SWTAG_DESCH;
197862306a36Sopenharmony_ci	tag_req.s.tag = tag;
197962306a36Sopenharmony_ci	tag_req.s.type = tag_type;
198062306a36Sopenharmony_ci	tag_req.s.grp = group;
198162306a36Sopenharmony_ci	tag_req.s.no_sched = no_sched;
198262306a36Sopenharmony_ci
198362306a36Sopenharmony_ci	ptr.u64 = 0;
198462306a36Sopenharmony_ci	ptr.sio.mem_region = CVMX_IO_SEG;
198562306a36Sopenharmony_ci	ptr.sio.is_io = 1;
198662306a36Sopenharmony_ci	ptr.sio.did = CVMX_OCT_DID_TAG_TAG3;
198762306a36Sopenharmony_ci	/*
198862306a36Sopenharmony_ci	 * since TAG3 is used, this store will clear the local pending
198962306a36Sopenharmony_ci	 * switch bit.
199062306a36Sopenharmony_ci	 */
199162306a36Sopenharmony_ci	cvmx_write_io(ptr.u64, tag_req.u64);
199262306a36Sopenharmony_ci}
199362306a36Sopenharmony_ci
199462306a36Sopenharmony_ci/**
199562306a36Sopenharmony_ci * Performs a tag switch and then an immediate deschedule. This completes
199662306a36Sopenharmony_ci * immediately, so completion must not be waited for.  This function does NOT
199762306a36Sopenharmony_ci * update the wqe in DRAM to match arguments.
199862306a36Sopenharmony_ci *
199962306a36Sopenharmony_ci * This function waits for any prior tag switches to complete, so the
200062306a36Sopenharmony_ci * calling code may call this function with a pending tag switch.
200162306a36Sopenharmony_ci *
200262306a36Sopenharmony_ci * Note the following CAVEAT of the Octeon HW behavior when
200362306a36Sopenharmony_ci * re-scheduling DE-SCHEDULEd items whose (next) state is
200462306a36Sopenharmony_ci * ORDERED:
200562306a36Sopenharmony_ci *   - If there are no switches pending at the time that the
200662306a36Sopenharmony_ci *     HW executes the de-schedule, the HW will only re-schedule
200762306a36Sopenharmony_ci *     the head of the FIFO associated with the given tag. This
200862306a36Sopenharmony_ci *     means that in many respects, the HW treats this ORDERED
200962306a36Sopenharmony_ci *     tag as an ATOMIC tag. Note that in the SWTAG_DESCH
201062306a36Sopenharmony_ci *     case (to an ORDERED tag), the HW will do the switch
201162306a36Sopenharmony_ci *     before the deschedule whenever it is possible to do
201262306a36Sopenharmony_ci *     the switch immediately, so it may often look like
201362306a36Sopenharmony_ci *     this case.
201462306a36Sopenharmony_ci *   - If there is a pending switch to ORDERED at the time
201562306a36Sopenharmony_ci *     the HW executes the de-schedule, the HW will perform
201662306a36Sopenharmony_ci *     the switch at the time it re-schedules, and will be
201762306a36Sopenharmony_ci *     able to reschedule any/all of the entries with the
201862306a36Sopenharmony_ci *     same tag.
201962306a36Sopenharmony_ci * Due to this behavior, the RECOMMENDATION to software is
202062306a36Sopenharmony_ci * that they have a (next) state of ATOMIC when they
202162306a36Sopenharmony_ci * DE-SCHEDULE. If an ORDERED tag is what was really desired,
202262306a36Sopenharmony_ci * SW can choose to immediately switch to an ORDERED tag
202362306a36Sopenharmony_ci * after the work (that has an ATOMIC tag) is re-scheduled.
202462306a36Sopenharmony_ci * Note that since there are never any tag switches pending
202562306a36Sopenharmony_ci * when the HW re-schedules, this switch can be IMMEDIATE upon
202662306a36Sopenharmony_ci * the reception of the pointer during the re-schedule.
202762306a36Sopenharmony_ci *
202862306a36Sopenharmony_ci * @tag:      New tag value
202962306a36Sopenharmony_ci * @tag_type: New tag type
203062306a36Sopenharmony_ci * @group:    New group value
203162306a36Sopenharmony_ci * @no_sched: Control whether this work queue entry will be rescheduled.
203262306a36Sopenharmony_ci *		   - 1 : don't schedule this work
203362306a36Sopenharmony_ci *		   - 0 : allow this work to be scheduled.
203462306a36Sopenharmony_ci */
203562306a36Sopenharmony_cistatic inline void cvmx_pow_tag_sw_desched(uint32_t tag,
203662306a36Sopenharmony_ci					   enum cvmx_pow_tag_type tag_type,
203762306a36Sopenharmony_ci					   uint64_t group, uint64_t no_sched)
203862306a36Sopenharmony_ci{
203962306a36Sopenharmony_ci	if (CVMX_ENABLE_POW_CHECKS)
204062306a36Sopenharmony_ci		__cvmx_pow_warn_if_pending_switch(__func__);
204162306a36Sopenharmony_ci
204262306a36Sopenharmony_ci	/* Need to make sure any writes to the work queue entry are complete */
204362306a36Sopenharmony_ci	CVMX_SYNCWS;
204462306a36Sopenharmony_ci	/*
204562306a36Sopenharmony_ci	 * Ensure that there is not a pending tag switch, as a tag
204662306a36Sopenharmony_ci	 * switch cannot be started if a previous switch is still
204762306a36Sopenharmony_ci	 * pending.
204862306a36Sopenharmony_ci	 */
204962306a36Sopenharmony_ci	cvmx_pow_tag_sw_wait();
205062306a36Sopenharmony_ci	cvmx_pow_tag_sw_desched_nocheck(tag, tag_type, group, no_sched);
205162306a36Sopenharmony_ci}
205262306a36Sopenharmony_ci
205362306a36Sopenharmony_ci/**
205462306a36Sopenharmony_ci * Deschedules the current work queue entry.
205562306a36Sopenharmony_ci *
205662306a36Sopenharmony_ci * @no_sched: no schedule flag value to be set on the work queue
205762306a36Sopenharmony_ci *	      entry.  If this is set the entry will not be
205862306a36Sopenharmony_ci *	      rescheduled.
205962306a36Sopenharmony_ci */
206062306a36Sopenharmony_cistatic inline void cvmx_pow_desched(uint64_t no_sched)
206162306a36Sopenharmony_ci{
206262306a36Sopenharmony_ci	cvmx_addr_t ptr;
206362306a36Sopenharmony_ci	cvmx_pow_tag_req_t tag_req;
206462306a36Sopenharmony_ci
206562306a36Sopenharmony_ci	if (CVMX_ENABLE_POW_CHECKS) {
206662306a36Sopenharmony_ci		cvmx_pow_tag_req_t current_tag;
206762306a36Sopenharmony_ci		__cvmx_pow_warn_if_pending_switch(__func__);
206862306a36Sopenharmony_ci		current_tag = cvmx_pow_get_current_tag();
206962306a36Sopenharmony_ci		if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL_NULL)
207062306a36Sopenharmony_ci			pr_warn("%s called with NULL_NULL tag\n", __func__);
207162306a36Sopenharmony_ci		if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL)
207262306a36Sopenharmony_ci			pr_warn("%s called with NULL tag. Deschedule not expected from NULL state\n",
207362306a36Sopenharmony_ci				__func__);
207462306a36Sopenharmony_ci	}
207562306a36Sopenharmony_ci
207662306a36Sopenharmony_ci	/* Need to make sure any writes to the work queue entry are complete */
207762306a36Sopenharmony_ci	CVMX_SYNCWS;
207862306a36Sopenharmony_ci
207962306a36Sopenharmony_ci	tag_req.u64 = 0;
208062306a36Sopenharmony_ci	tag_req.s.op = CVMX_POW_TAG_OP_DESCH;
208162306a36Sopenharmony_ci	tag_req.s.no_sched = no_sched;
208262306a36Sopenharmony_ci
208362306a36Sopenharmony_ci	ptr.u64 = 0;
208462306a36Sopenharmony_ci	ptr.sio.mem_region = CVMX_IO_SEG;
208562306a36Sopenharmony_ci	ptr.sio.is_io = 1;
208662306a36Sopenharmony_ci	ptr.sio.did = CVMX_OCT_DID_TAG_TAG3;
208762306a36Sopenharmony_ci	/*
208862306a36Sopenharmony_ci	 * since TAG3 is used, this store will clear the local pending
208962306a36Sopenharmony_ci	 * switch bit.
209062306a36Sopenharmony_ci	 */
209162306a36Sopenharmony_ci	cvmx_write_io(ptr.u64, tag_req.u64);
209262306a36Sopenharmony_ci}
209362306a36Sopenharmony_ci
209462306a36Sopenharmony_ci/****************************************************
209562306a36Sopenharmony_ci* Define usage of bits within the 32 bit tag values.
209662306a36Sopenharmony_ci*****************************************************/
209762306a36Sopenharmony_ci
209862306a36Sopenharmony_ci/*
209962306a36Sopenharmony_ci * Number of bits of the tag used by software.	The SW bits are always
210062306a36Sopenharmony_ci * a contiguous block of the high starting at bit 31.  The hardware
210162306a36Sopenharmony_ci * bits are always the low bits.  By default, the top 8 bits of the
210262306a36Sopenharmony_ci * tag are reserved for software, and the low 24 are set by the IPD
210362306a36Sopenharmony_ci * unit.
210462306a36Sopenharmony_ci */
210562306a36Sopenharmony_ci#define CVMX_TAG_SW_BITS    (8)
210662306a36Sopenharmony_ci#define CVMX_TAG_SW_SHIFT   (32 - CVMX_TAG_SW_BITS)
210762306a36Sopenharmony_ci
210862306a36Sopenharmony_ci/* Below is the list of values for the top 8 bits of the tag. */
210962306a36Sopenharmony_ci/*
211062306a36Sopenharmony_ci * Tag values with top byte of this value are reserved for internal
211162306a36Sopenharmony_ci * executive uses.
211262306a36Sopenharmony_ci */
211362306a36Sopenharmony_ci#define CVMX_TAG_SW_BITS_INTERNAL  0x1
211462306a36Sopenharmony_ci/* The executive divides the remaining 24 bits as follows:
211562306a36Sopenharmony_ci *  - the upper 8 bits (bits 23 - 16 of the tag) define a subgroup
211662306a36Sopenharmony_ci *
211762306a36Sopenharmony_ci *  - the lower 16 bits (bits 15 - 0 of the tag) define are the value
211862306a36Sopenharmony_ci *    with the subgroup
211962306a36Sopenharmony_ci *
212062306a36Sopenharmony_ci * Note that this section describes the format of tags generated by
212162306a36Sopenharmony_ci * software - refer to the hardware documentation for a description of
212262306a36Sopenharmony_ci * the tags values generated by the packet input hardware.  Subgroups
212362306a36Sopenharmony_ci * are defined here.
212462306a36Sopenharmony_ci */
212562306a36Sopenharmony_ci/* Mask for the value portion of the tag */
212662306a36Sopenharmony_ci#define CVMX_TAG_SUBGROUP_MASK	0xFFFF
212762306a36Sopenharmony_ci#define CVMX_TAG_SUBGROUP_SHIFT 16
212862306a36Sopenharmony_ci#define CVMX_TAG_SUBGROUP_PKO  0x1
212962306a36Sopenharmony_ci
213062306a36Sopenharmony_ci/* End of executive tag subgroup definitions */
213162306a36Sopenharmony_ci
213262306a36Sopenharmony_ci/*
213362306a36Sopenharmony_ci * The remaining values software bit values 0x2 - 0xff are available
213462306a36Sopenharmony_ci * for application use.
213562306a36Sopenharmony_ci */
213662306a36Sopenharmony_ci
213762306a36Sopenharmony_ci/**
213862306a36Sopenharmony_ci * This function creates a 32 bit tag value from the two values provided.
213962306a36Sopenharmony_ci *
214062306a36Sopenharmony_ci * @sw_bits: The upper bits (number depends on configuration) are set
214162306a36Sopenharmony_ci *	     to this value.  The remainder of bits are set by the
214262306a36Sopenharmony_ci *	     hw_bits parameter.
214362306a36Sopenharmony_ci *
214462306a36Sopenharmony_ci * @hw_bits: The lower bits (number depends on configuration) are set
214562306a36Sopenharmony_ci *	     to this value.  The remainder of bits are set by the
214662306a36Sopenharmony_ci *	     sw_bits parameter.
214762306a36Sopenharmony_ci *
214862306a36Sopenharmony_ci * Returns 32 bit value of the combined hw and sw bits.
214962306a36Sopenharmony_ci */
215062306a36Sopenharmony_cistatic inline uint32_t cvmx_pow_tag_compose(uint64_t sw_bits, uint64_t hw_bits)
215162306a36Sopenharmony_ci{
215262306a36Sopenharmony_ci	return ((sw_bits & cvmx_build_mask(CVMX_TAG_SW_BITS)) <<
215362306a36Sopenharmony_ci			CVMX_TAG_SW_SHIFT) |
215462306a36Sopenharmony_ci		(hw_bits & cvmx_build_mask(32 - CVMX_TAG_SW_BITS));
215562306a36Sopenharmony_ci}
215662306a36Sopenharmony_ci
215762306a36Sopenharmony_ci/**
215862306a36Sopenharmony_ci * Extracts the bits allocated for software use from the tag
215962306a36Sopenharmony_ci *
216062306a36Sopenharmony_ci * @tag:    32 bit tag value
216162306a36Sopenharmony_ci *
216262306a36Sopenharmony_ci * Returns N bit software tag value, where N is configurable with the
216362306a36Sopenharmony_ci * CVMX_TAG_SW_BITS define
216462306a36Sopenharmony_ci */
216562306a36Sopenharmony_cistatic inline uint32_t cvmx_pow_tag_get_sw_bits(uint64_t tag)
216662306a36Sopenharmony_ci{
216762306a36Sopenharmony_ci	return (tag >> (32 - CVMX_TAG_SW_BITS)) &
216862306a36Sopenharmony_ci		cvmx_build_mask(CVMX_TAG_SW_BITS);
216962306a36Sopenharmony_ci}
217062306a36Sopenharmony_ci
217162306a36Sopenharmony_ci/**
217262306a36Sopenharmony_ci *
217362306a36Sopenharmony_ci * Extracts the bits allocated for hardware use from the tag
217462306a36Sopenharmony_ci *
217562306a36Sopenharmony_ci * @tag:    32 bit tag value
217662306a36Sopenharmony_ci *
217762306a36Sopenharmony_ci * Returns (32 - N) bit software tag value, where N is configurable
217862306a36Sopenharmony_ci * with the CVMX_TAG_SW_BITS define
217962306a36Sopenharmony_ci */
218062306a36Sopenharmony_cistatic inline uint32_t cvmx_pow_tag_get_hw_bits(uint64_t tag)
218162306a36Sopenharmony_ci{
218262306a36Sopenharmony_ci	return tag & cvmx_build_mask(32 - CVMX_TAG_SW_BITS);
218362306a36Sopenharmony_ci}
218462306a36Sopenharmony_ci
218562306a36Sopenharmony_ci/**
218662306a36Sopenharmony_ci * Store the current POW internal state into the supplied
218762306a36Sopenharmony_ci * buffer. It is recommended that you pass a buffer of at least
218862306a36Sopenharmony_ci * 128KB. The format of the capture may change based on SDK
218962306a36Sopenharmony_ci * version and Octeon chip.
219062306a36Sopenharmony_ci *
219162306a36Sopenharmony_ci * @buffer: Buffer to store capture into
219262306a36Sopenharmony_ci * @buffer_size:
219362306a36Sopenharmony_ci *		 The size of the supplied buffer
219462306a36Sopenharmony_ci *
219562306a36Sopenharmony_ci * Returns Zero on success, negative on failure
219662306a36Sopenharmony_ci */
219762306a36Sopenharmony_ciextern int cvmx_pow_capture(void *buffer, int buffer_size);
219862306a36Sopenharmony_ci
219962306a36Sopenharmony_ci/**
220062306a36Sopenharmony_ci * Dump a POW capture to the console in a human readable format.
220162306a36Sopenharmony_ci *
220262306a36Sopenharmony_ci * @buffer: POW capture from cvmx_pow_capture()
220362306a36Sopenharmony_ci * @buffer_size:
220462306a36Sopenharmony_ci *		 Size of the buffer
220562306a36Sopenharmony_ci */
220662306a36Sopenharmony_ciextern void cvmx_pow_display(void *buffer, int buffer_size);
220762306a36Sopenharmony_ci
220862306a36Sopenharmony_ci/**
220962306a36Sopenharmony_ci * Return the number of POW entries supported by this chip
221062306a36Sopenharmony_ci *
221162306a36Sopenharmony_ci * Returns Number of POW entries
221262306a36Sopenharmony_ci */
221362306a36Sopenharmony_ciextern int cvmx_pow_get_num_entries(void);
221462306a36Sopenharmony_ci
221562306a36Sopenharmony_ci#endif /* __CVMX_POW_H__ */
2216