18c2ecf20Sopenharmony_ci/***********************license start***************
28c2ecf20Sopenharmony_ci * Author: Cavium Networks
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Contact: support@caviumnetworks.com
58c2ecf20Sopenharmony_ci * This file is part of the OCTEON SDK
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Copyright (c) 2003-2008 Cavium Networks
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * This file is free software; you can redistribute it and/or modify
108c2ecf20Sopenharmony_ci * it under the terms of the GNU General Public License, Version 2, as
118c2ecf20Sopenharmony_ci * published by the Free Software Foundation.
128c2ecf20Sopenharmony_ci *
138c2ecf20Sopenharmony_ci * This file is distributed in the hope that it will be useful, but
148c2ecf20Sopenharmony_ci * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
158c2ecf20Sopenharmony_ci * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
168c2ecf20Sopenharmony_ci * NONINFRINGEMENT.  See the GNU General Public License for more
178c2ecf20Sopenharmony_ci * details.
188c2ecf20Sopenharmony_ci *
198c2ecf20Sopenharmony_ci * You should have received a copy of the GNU General Public License
208c2ecf20Sopenharmony_ci * along with this file; if not, write to the Free Software
218c2ecf20Sopenharmony_ci * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
228c2ecf20Sopenharmony_ci * or visit http://www.gnu.org/licenses/.
238c2ecf20Sopenharmony_ci *
248c2ecf20Sopenharmony_ci * This file may also be available under a different license from Cavium.
258c2ecf20Sopenharmony_ci * Contact Cavium Networks for more information
268c2ecf20Sopenharmony_ci ***********************license end**************************************/
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci/*
298c2ecf20Sopenharmony_ci * Support functions for managing command queues used for
308c2ecf20Sopenharmony_ci * various hardware blocks.
318c2ecf20Sopenharmony_ci */
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci#include <linux/kernel.h>
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#include <asm/octeon/octeon.h>
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-config.h>
388c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-fpa.h>
398c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-cmd-queue.h>
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-npei-defs.h>
428c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-pexp-defs.h>
438c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-pko-defs.h>
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci/**
468c2ecf20Sopenharmony_ci * This application uses this pointer to access the global queue
478c2ecf20Sopenharmony_ci * state. It points to a bootmem named block.
488c2ecf20Sopenharmony_ci */
498c2ecf20Sopenharmony_ci__cvmx_cmd_queue_all_state_t *__cvmx_cmd_queue_state_ptr;
508c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(__cvmx_cmd_queue_state_ptr);
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci/**
538c2ecf20Sopenharmony_ci * Initialize the Global queue state pointer.
548c2ecf20Sopenharmony_ci *
558c2ecf20Sopenharmony_ci * Returns CVMX_CMD_QUEUE_SUCCESS or a failure code
568c2ecf20Sopenharmony_ci */
578c2ecf20Sopenharmony_cistatic cvmx_cmd_queue_result_t __cvmx_cmd_queue_init_state_ptr(void)
588c2ecf20Sopenharmony_ci{
598c2ecf20Sopenharmony_ci	char *alloc_name = "cvmx_cmd_queues";
608c2ecf20Sopenharmony_ci#if defined(CONFIG_CAVIUM_RESERVE32) && CONFIG_CAVIUM_RESERVE32
618c2ecf20Sopenharmony_ci	extern uint64_t octeon_reserve32_memory;
628c2ecf20Sopenharmony_ci#endif
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	if (likely(__cvmx_cmd_queue_state_ptr))
658c2ecf20Sopenharmony_ci		return CVMX_CMD_QUEUE_SUCCESS;
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci#if defined(CONFIG_CAVIUM_RESERVE32) && CONFIG_CAVIUM_RESERVE32
688c2ecf20Sopenharmony_ci	if (octeon_reserve32_memory)
698c2ecf20Sopenharmony_ci		__cvmx_cmd_queue_state_ptr =
708c2ecf20Sopenharmony_ci		    cvmx_bootmem_alloc_named_range(sizeof(*__cvmx_cmd_queue_state_ptr),
718c2ecf20Sopenharmony_ci						   octeon_reserve32_memory,
728c2ecf20Sopenharmony_ci						   octeon_reserve32_memory +
738c2ecf20Sopenharmony_ci						   (CONFIG_CAVIUM_RESERVE32 <<
748c2ecf20Sopenharmony_ci						    20) - 1, 128, alloc_name);
758c2ecf20Sopenharmony_ci	else
768c2ecf20Sopenharmony_ci#endif
778c2ecf20Sopenharmony_ci		__cvmx_cmd_queue_state_ptr =
788c2ecf20Sopenharmony_ci		    cvmx_bootmem_alloc_named(sizeof(*__cvmx_cmd_queue_state_ptr),
798c2ecf20Sopenharmony_ci					    128,
808c2ecf20Sopenharmony_ci					    alloc_name);
818c2ecf20Sopenharmony_ci	if (__cvmx_cmd_queue_state_ptr)
828c2ecf20Sopenharmony_ci		memset(__cvmx_cmd_queue_state_ptr, 0,
838c2ecf20Sopenharmony_ci		       sizeof(*__cvmx_cmd_queue_state_ptr));
848c2ecf20Sopenharmony_ci	else {
858c2ecf20Sopenharmony_ci		struct cvmx_bootmem_named_block_desc *block_desc =
868c2ecf20Sopenharmony_ci		    cvmx_bootmem_find_named_block(alloc_name);
878c2ecf20Sopenharmony_ci		if (block_desc)
888c2ecf20Sopenharmony_ci			__cvmx_cmd_queue_state_ptr =
898c2ecf20Sopenharmony_ci			    cvmx_phys_to_ptr(block_desc->base_addr);
908c2ecf20Sopenharmony_ci		else {
918c2ecf20Sopenharmony_ci			cvmx_dprintf
928c2ecf20Sopenharmony_ci			    ("ERROR: cvmx_cmd_queue_initialize: Unable to get named block %s.\n",
938c2ecf20Sopenharmony_ci			     alloc_name);
948c2ecf20Sopenharmony_ci			return CVMX_CMD_QUEUE_NO_MEMORY;
958c2ecf20Sopenharmony_ci		}
968c2ecf20Sopenharmony_ci	}
978c2ecf20Sopenharmony_ci	return CVMX_CMD_QUEUE_SUCCESS;
988c2ecf20Sopenharmony_ci}
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci/**
1018c2ecf20Sopenharmony_ci * Initialize a command queue for use. The initial FPA buffer is
1028c2ecf20Sopenharmony_ci * allocated and the hardware unit is configured to point to the
1038c2ecf20Sopenharmony_ci * new command queue.
1048c2ecf20Sopenharmony_ci *
1058c2ecf20Sopenharmony_ci * @queue_id:  Hardware command queue to initialize.
1068c2ecf20Sopenharmony_ci * @max_depth: Maximum outstanding commands that can be queued.
1078c2ecf20Sopenharmony_ci * @fpa_pool:  FPA pool the command queues should come from.
1088c2ecf20Sopenharmony_ci * @pool_size: Size of each buffer in the FPA pool (bytes)
1098c2ecf20Sopenharmony_ci *
1108c2ecf20Sopenharmony_ci * Returns CVMX_CMD_QUEUE_SUCCESS or a failure code
1118c2ecf20Sopenharmony_ci */
1128c2ecf20Sopenharmony_cicvmx_cmd_queue_result_t cvmx_cmd_queue_initialize(cvmx_cmd_queue_id_t queue_id,
1138c2ecf20Sopenharmony_ci						  int max_depth, int fpa_pool,
1148c2ecf20Sopenharmony_ci						  int pool_size)
1158c2ecf20Sopenharmony_ci{
1168c2ecf20Sopenharmony_ci	__cvmx_cmd_queue_state_t *qstate;
1178c2ecf20Sopenharmony_ci	cvmx_cmd_queue_result_t result = __cvmx_cmd_queue_init_state_ptr();
1188c2ecf20Sopenharmony_ci	if (result != CVMX_CMD_QUEUE_SUCCESS)
1198c2ecf20Sopenharmony_ci		return result;
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	qstate = __cvmx_cmd_queue_get_state(queue_id);
1228c2ecf20Sopenharmony_ci	if (qstate == NULL)
1238c2ecf20Sopenharmony_ci		return CVMX_CMD_QUEUE_INVALID_PARAM;
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci	/*
1268c2ecf20Sopenharmony_ci	 * We artificially limit max_depth to 1<<20 words. It is an
1278c2ecf20Sopenharmony_ci	 * arbitrary limit.
1288c2ecf20Sopenharmony_ci	 */
1298c2ecf20Sopenharmony_ci	if (CVMX_CMD_QUEUE_ENABLE_MAX_DEPTH) {
1308c2ecf20Sopenharmony_ci		if ((max_depth < 0) || (max_depth > 1 << 20))
1318c2ecf20Sopenharmony_ci			return CVMX_CMD_QUEUE_INVALID_PARAM;
1328c2ecf20Sopenharmony_ci	} else if (max_depth != 0)
1338c2ecf20Sopenharmony_ci		return CVMX_CMD_QUEUE_INVALID_PARAM;
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci	if ((fpa_pool < 0) || (fpa_pool > 7))
1368c2ecf20Sopenharmony_ci		return CVMX_CMD_QUEUE_INVALID_PARAM;
1378c2ecf20Sopenharmony_ci	if ((pool_size < 128) || (pool_size > 65536))
1388c2ecf20Sopenharmony_ci		return CVMX_CMD_QUEUE_INVALID_PARAM;
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci	/* See if someone else has already initialized the queue */
1418c2ecf20Sopenharmony_ci	if (qstate->base_ptr_div128) {
1428c2ecf20Sopenharmony_ci		if (max_depth != (int)qstate->max_depth) {
1438c2ecf20Sopenharmony_ci			cvmx_dprintf("ERROR: cvmx_cmd_queue_initialize: "
1448c2ecf20Sopenharmony_ci				"Queue already initialized with different "
1458c2ecf20Sopenharmony_ci				"max_depth (%d).\n",
1468c2ecf20Sopenharmony_ci			     (int)qstate->max_depth);
1478c2ecf20Sopenharmony_ci			return CVMX_CMD_QUEUE_INVALID_PARAM;
1488c2ecf20Sopenharmony_ci		}
1498c2ecf20Sopenharmony_ci		if (fpa_pool != qstate->fpa_pool) {
1508c2ecf20Sopenharmony_ci			cvmx_dprintf("ERROR: cvmx_cmd_queue_initialize: "
1518c2ecf20Sopenharmony_ci				"Queue already initialized with different "
1528c2ecf20Sopenharmony_ci				"FPA pool (%u).\n",
1538c2ecf20Sopenharmony_ci			     qstate->fpa_pool);
1548c2ecf20Sopenharmony_ci			return CVMX_CMD_QUEUE_INVALID_PARAM;
1558c2ecf20Sopenharmony_ci		}
1568c2ecf20Sopenharmony_ci		if ((pool_size >> 3) - 1 != qstate->pool_size_m1) {
1578c2ecf20Sopenharmony_ci			cvmx_dprintf("ERROR: cvmx_cmd_queue_initialize: "
1588c2ecf20Sopenharmony_ci				"Queue already initialized with different "
1598c2ecf20Sopenharmony_ci				"FPA pool size (%u).\n",
1608c2ecf20Sopenharmony_ci			     (qstate->pool_size_m1 + 1) << 3);
1618c2ecf20Sopenharmony_ci			return CVMX_CMD_QUEUE_INVALID_PARAM;
1628c2ecf20Sopenharmony_ci		}
1638c2ecf20Sopenharmony_ci		CVMX_SYNCWS;
1648c2ecf20Sopenharmony_ci		return CVMX_CMD_QUEUE_ALREADY_SETUP;
1658c2ecf20Sopenharmony_ci	} else {
1668c2ecf20Sopenharmony_ci		union cvmx_fpa_ctl_status status;
1678c2ecf20Sopenharmony_ci		void *buffer;
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci		status.u64 = cvmx_read_csr(CVMX_FPA_CTL_STATUS);
1708c2ecf20Sopenharmony_ci		if (!status.s.enb) {
1718c2ecf20Sopenharmony_ci			cvmx_dprintf("ERROR: cvmx_cmd_queue_initialize: "
1728c2ecf20Sopenharmony_ci				     "FPA is not enabled.\n");
1738c2ecf20Sopenharmony_ci			return CVMX_CMD_QUEUE_NO_MEMORY;
1748c2ecf20Sopenharmony_ci		}
1758c2ecf20Sopenharmony_ci		buffer = cvmx_fpa_alloc(fpa_pool);
1768c2ecf20Sopenharmony_ci		if (buffer == NULL) {
1778c2ecf20Sopenharmony_ci			cvmx_dprintf("ERROR: cvmx_cmd_queue_initialize: "
1788c2ecf20Sopenharmony_ci				     "Unable to allocate initial buffer.\n");
1798c2ecf20Sopenharmony_ci			return CVMX_CMD_QUEUE_NO_MEMORY;
1808c2ecf20Sopenharmony_ci		}
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci		memset(qstate, 0, sizeof(*qstate));
1838c2ecf20Sopenharmony_ci		qstate->max_depth = max_depth;
1848c2ecf20Sopenharmony_ci		qstate->fpa_pool = fpa_pool;
1858c2ecf20Sopenharmony_ci		qstate->pool_size_m1 = (pool_size >> 3) - 1;
1868c2ecf20Sopenharmony_ci		qstate->base_ptr_div128 = cvmx_ptr_to_phys(buffer) / 128;
1878c2ecf20Sopenharmony_ci		/*
1888c2ecf20Sopenharmony_ci		 * We zeroed the now serving field so we need to also
1898c2ecf20Sopenharmony_ci		 * zero the ticket.
1908c2ecf20Sopenharmony_ci		 */
1918c2ecf20Sopenharmony_ci		__cvmx_cmd_queue_state_ptr->
1928c2ecf20Sopenharmony_ci		    ticket[__cvmx_cmd_queue_get_index(queue_id)] = 0;
1938c2ecf20Sopenharmony_ci		CVMX_SYNCWS;
1948c2ecf20Sopenharmony_ci		return CVMX_CMD_QUEUE_SUCCESS;
1958c2ecf20Sopenharmony_ci	}
1968c2ecf20Sopenharmony_ci}
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci/**
1998c2ecf20Sopenharmony_ci * Shutdown a queue a free it's command buffers to the FPA. The
2008c2ecf20Sopenharmony_ci * hardware connected to the queue must be stopped before this
2018c2ecf20Sopenharmony_ci * function is called.
2028c2ecf20Sopenharmony_ci *
2038c2ecf20Sopenharmony_ci * @queue_id: Queue to shutdown
2048c2ecf20Sopenharmony_ci *
2058c2ecf20Sopenharmony_ci * Returns CVMX_CMD_QUEUE_SUCCESS or a failure code
2068c2ecf20Sopenharmony_ci */
2078c2ecf20Sopenharmony_cicvmx_cmd_queue_result_t cvmx_cmd_queue_shutdown(cvmx_cmd_queue_id_t queue_id)
2088c2ecf20Sopenharmony_ci{
2098c2ecf20Sopenharmony_ci	__cvmx_cmd_queue_state_t *qptr = __cvmx_cmd_queue_get_state(queue_id);
2108c2ecf20Sopenharmony_ci	if (qptr == NULL) {
2118c2ecf20Sopenharmony_ci		cvmx_dprintf("ERROR: cvmx_cmd_queue_shutdown: Unable to "
2128c2ecf20Sopenharmony_ci			     "get queue information.\n");
2138c2ecf20Sopenharmony_ci		return CVMX_CMD_QUEUE_INVALID_PARAM;
2148c2ecf20Sopenharmony_ci	}
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci	if (cvmx_cmd_queue_length(queue_id) > 0) {
2178c2ecf20Sopenharmony_ci		cvmx_dprintf("ERROR: cvmx_cmd_queue_shutdown: Queue still "
2188c2ecf20Sopenharmony_ci			     "has data in it.\n");
2198c2ecf20Sopenharmony_ci		return CVMX_CMD_QUEUE_FULL;
2208c2ecf20Sopenharmony_ci	}
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	__cvmx_cmd_queue_lock(queue_id, qptr);
2238c2ecf20Sopenharmony_ci	if (qptr->base_ptr_div128) {
2248c2ecf20Sopenharmony_ci		cvmx_fpa_free(cvmx_phys_to_ptr
2258c2ecf20Sopenharmony_ci			      ((uint64_t) qptr->base_ptr_div128 << 7),
2268c2ecf20Sopenharmony_ci			      qptr->fpa_pool, 0);
2278c2ecf20Sopenharmony_ci		qptr->base_ptr_div128 = 0;
2288c2ecf20Sopenharmony_ci	}
2298c2ecf20Sopenharmony_ci	__cvmx_cmd_queue_unlock(qptr);
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	return CVMX_CMD_QUEUE_SUCCESS;
2328c2ecf20Sopenharmony_ci}
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci/**
2358c2ecf20Sopenharmony_ci * Return the number of command words pending in the queue. This
2368c2ecf20Sopenharmony_ci * function may be relatively slow for some hardware units.
2378c2ecf20Sopenharmony_ci *
2388c2ecf20Sopenharmony_ci * @queue_id: Hardware command queue to query
2398c2ecf20Sopenharmony_ci *
2408c2ecf20Sopenharmony_ci * Returns Number of outstanding commands
2418c2ecf20Sopenharmony_ci */
2428c2ecf20Sopenharmony_ciint cvmx_cmd_queue_length(cvmx_cmd_queue_id_t queue_id)
2438c2ecf20Sopenharmony_ci{
2448c2ecf20Sopenharmony_ci	if (CVMX_ENABLE_PARAMETER_CHECKING) {
2458c2ecf20Sopenharmony_ci		if (__cvmx_cmd_queue_get_state(queue_id) == NULL)
2468c2ecf20Sopenharmony_ci			return CVMX_CMD_QUEUE_INVALID_PARAM;
2478c2ecf20Sopenharmony_ci	}
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci	/*
2508c2ecf20Sopenharmony_ci	 * The cast is here so gcc with check that all values in the
2518c2ecf20Sopenharmony_ci	 * cvmx_cmd_queue_id_t enumeration are here.
2528c2ecf20Sopenharmony_ci	 */
2538c2ecf20Sopenharmony_ci	switch ((cvmx_cmd_queue_id_t) (queue_id & 0xff0000)) {
2548c2ecf20Sopenharmony_ci	case CVMX_CMD_QUEUE_PKO_BASE:
2558c2ecf20Sopenharmony_ci		/*
2568c2ecf20Sopenharmony_ci		 * FIXME: Need atomic lock on
2578c2ecf20Sopenharmony_ci		 * CVMX_PKO_REG_READ_IDX. Right now we are normally
2588c2ecf20Sopenharmony_ci		 * called with the queue lock, so that is a SLIGHT
2598c2ecf20Sopenharmony_ci		 * amount of protection.
2608c2ecf20Sopenharmony_ci		 */
2618c2ecf20Sopenharmony_ci		cvmx_write_csr(CVMX_PKO_REG_READ_IDX, queue_id & 0xffff);
2628c2ecf20Sopenharmony_ci		if (OCTEON_IS_MODEL(OCTEON_CN3XXX)) {
2638c2ecf20Sopenharmony_ci			union cvmx_pko_mem_debug9 debug9;
2648c2ecf20Sopenharmony_ci			debug9.u64 = cvmx_read_csr(CVMX_PKO_MEM_DEBUG9);
2658c2ecf20Sopenharmony_ci			return debug9.cn38xx.doorbell;
2668c2ecf20Sopenharmony_ci		} else {
2678c2ecf20Sopenharmony_ci			union cvmx_pko_mem_debug8 debug8;
2688c2ecf20Sopenharmony_ci			debug8.u64 = cvmx_read_csr(CVMX_PKO_MEM_DEBUG8);
2698c2ecf20Sopenharmony_ci			return debug8.cn50xx.doorbell;
2708c2ecf20Sopenharmony_ci		}
2718c2ecf20Sopenharmony_ci	case CVMX_CMD_QUEUE_ZIP:
2728c2ecf20Sopenharmony_ci	case CVMX_CMD_QUEUE_DFA:
2738c2ecf20Sopenharmony_ci	case CVMX_CMD_QUEUE_RAID:
2748c2ecf20Sopenharmony_ci		/* FIXME: Implement other lengths */
2758c2ecf20Sopenharmony_ci		return 0;
2768c2ecf20Sopenharmony_ci	case CVMX_CMD_QUEUE_DMA_BASE:
2778c2ecf20Sopenharmony_ci		{
2788c2ecf20Sopenharmony_ci			union cvmx_npei_dmax_counts dmax_counts;
2798c2ecf20Sopenharmony_ci			dmax_counts.u64 =
2808c2ecf20Sopenharmony_ci			    cvmx_read_csr(CVMX_PEXP_NPEI_DMAX_COUNTS
2818c2ecf20Sopenharmony_ci					  (queue_id & 0x7));
2828c2ecf20Sopenharmony_ci			return dmax_counts.s.dbell;
2838c2ecf20Sopenharmony_ci		}
2848c2ecf20Sopenharmony_ci	case CVMX_CMD_QUEUE_END:
2858c2ecf20Sopenharmony_ci		return CVMX_CMD_QUEUE_INVALID_PARAM;
2868c2ecf20Sopenharmony_ci	}
2878c2ecf20Sopenharmony_ci	return CVMX_CMD_QUEUE_INVALID_PARAM;
2888c2ecf20Sopenharmony_ci}
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci/**
2918c2ecf20Sopenharmony_ci * Return the command buffer to be written to. The purpose of this
2928c2ecf20Sopenharmony_ci * function is to allow CVMX routine access t othe low level buffer
2938c2ecf20Sopenharmony_ci * for initial hardware setup. User applications should not call this
2948c2ecf20Sopenharmony_ci * function directly.
2958c2ecf20Sopenharmony_ci *
2968c2ecf20Sopenharmony_ci * @queue_id: Command queue to query
2978c2ecf20Sopenharmony_ci *
2988c2ecf20Sopenharmony_ci * Returns Command buffer or NULL on failure
2998c2ecf20Sopenharmony_ci */
3008c2ecf20Sopenharmony_civoid *cvmx_cmd_queue_buffer(cvmx_cmd_queue_id_t queue_id)
3018c2ecf20Sopenharmony_ci{
3028c2ecf20Sopenharmony_ci	__cvmx_cmd_queue_state_t *qptr = __cvmx_cmd_queue_get_state(queue_id);
3038c2ecf20Sopenharmony_ci	if (qptr && qptr->base_ptr_div128)
3048c2ecf20Sopenharmony_ci		return cvmx_phys_to_ptr((uint64_t) qptr->base_ptr_div128 << 7);
3058c2ecf20Sopenharmony_ci	else
3068c2ecf20Sopenharmony_ci		return NULL;
3078c2ecf20Sopenharmony_ci}
308