18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
48c2ecf20Sopenharmony_ci * Copyright 2016-2019 NXP
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <asm/cacheflush.h>
98c2ecf20Sopenharmony_ci#include <linux/io.h>
108c2ecf20Sopenharmony_ci#include <linux/slab.h>
118c2ecf20Sopenharmony_ci#include <linux/spinlock.h>
128c2ecf20Sopenharmony_ci#include <soc/fsl/dpaa2-global.h>
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include "qbman-portal.h"
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci/* All QBMan command and result structures use this "valid bit" encoding */
178c2ecf20Sopenharmony_ci#define QB_VALID_BIT ((u32)0x80)
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci/* QBMan portal management command codes */
208c2ecf20Sopenharmony_ci#define QBMAN_MC_ACQUIRE       0x30
218c2ecf20Sopenharmony_ci#define QBMAN_WQCHAN_CONFIGURE 0x46
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci/* CINH register offsets */
248c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_EQCR_PI      0x800
258c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_EQCR_CI	    0x840
268c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_EQAR    0x8c0
278c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_CR_RT        0x900
288c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_VDQCR_RT     0x940
298c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_EQCR_AM_RT   0x980
308c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_RCR_AM_RT    0x9c0
318c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_DQPI    0xa00
328c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_DCAP    0xac0
338c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_SDQCR   0xb00
348c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_EQCR_AM_RT2  0xb40
358c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_RCR_PI       0xc00
368c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_RAR     0xcc0
378c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_ISR     0xe00
388c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_IER     0xe40
398c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_ISDR    0xe80
408c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_IIR     0xec0
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci/* CENA register offsets */
438c2ecf20Sopenharmony_ci#define QBMAN_CENA_SWP_EQCR(n) (0x000 + ((u32)(n) << 6))
448c2ecf20Sopenharmony_ci#define QBMAN_CENA_SWP_DQRR(n) (0x200 + ((u32)(n) << 6))
458c2ecf20Sopenharmony_ci#define QBMAN_CENA_SWP_RCR(n)  (0x400 + ((u32)(n) << 6))
468c2ecf20Sopenharmony_ci#define QBMAN_CENA_SWP_CR      0x600
478c2ecf20Sopenharmony_ci#define QBMAN_CENA_SWP_RR(vb)  (0x700 + ((u32)(vb) >> 1))
488c2ecf20Sopenharmony_ci#define QBMAN_CENA_SWP_VDQCR   0x780
498c2ecf20Sopenharmony_ci#define QBMAN_CENA_SWP_EQCR_CI 0x840
508c2ecf20Sopenharmony_ci#define QBMAN_CENA_SWP_EQCR_CI_MEMBACK 0x1840
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci/* CENA register offsets in memory-backed mode */
538c2ecf20Sopenharmony_ci#define QBMAN_CENA_SWP_DQRR_MEM(n)  (0x800 + ((u32)(n) << 6))
548c2ecf20Sopenharmony_ci#define QBMAN_CENA_SWP_RCR_MEM(n)   (0x1400 + ((u32)(n) << 6))
558c2ecf20Sopenharmony_ci#define QBMAN_CENA_SWP_CR_MEM       0x1600
568c2ecf20Sopenharmony_ci#define QBMAN_CENA_SWP_RR_MEM       0x1680
578c2ecf20Sopenharmony_ci#define QBMAN_CENA_SWP_VDQCR_MEM    0x1780
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci/* Reverse mapping of QBMAN_CENA_SWP_DQRR() */
608c2ecf20Sopenharmony_ci#define QBMAN_IDX_FROM_DQRR(p) (((unsigned long)(p) & 0x1ff) >> 6)
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci/* Define token used to determine if response written to memory is valid */
638c2ecf20Sopenharmony_ci#define QMAN_DQ_TOKEN_VALID 1
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci/* SDQCR attribute codes */
668c2ecf20Sopenharmony_ci#define QB_SDQCR_FC_SHIFT   29
678c2ecf20Sopenharmony_ci#define QB_SDQCR_FC_MASK    0x1
688c2ecf20Sopenharmony_ci#define QB_SDQCR_DCT_SHIFT  24
698c2ecf20Sopenharmony_ci#define QB_SDQCR_DCT_MASK   0x3
708c2ecf20Sopenharmony_ci#define QB_SDQCR_TOK_SHIFT  16
718c2ecf20Sopenharmony_ci#define QB_SDQCR_TOK_MASK   0xff
728c2ecf20Sopenharmony_ci#define QB_SDQCR_SRC_SHIFT  0
738c2ecf20Sopenharmony_ci#define QB_SDQCR_SRC_MASK   0xffff
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci/* opaque token for static dequeues */
768c2ecf20Sopenharmony_ci#define QMAN_SDQCR_TOKEN    0xbb
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci#define QBMAN_EQCR_DCA_IDXMASK          0x0f
798c2ecf20Sopenharmony_ci#define QBMAN_ENQUEUE_FLAG_DCA          (1ULL << 31)
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci#define EQ_DESC_SIZE_WITHOUT_FD 29
828c2ecf20Sopenharmony_ci#define EQ_DESC_SIZE_FD_START 32
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_cienum qbman_sdqcr_dct {
858c2ecf20Sopenharmony_ci	qbman_sdqcr_dct_null = 0,
868c2ecf20Sopenharmony_ci	qbman_sdqcr_dct_prio_ics,
878c2ecf20Sopenharmony_ci	qbman_sdqcr_dct_active_ics,
888c2ecf20Sopenharmony_ci	qbman_sdqcr_dct_active
898c2ecf20Sopenharmony_ci};
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_cienum qbman_sdqcr_fc {
928c2ecf20Sopenharmony_ci	qbman_sdqcr_fc_one = 0,
938c2ecf20Sopenharmony_ci	qbman_sdqcr_fc_up_to_3 = 1
948c2ecf20Sopenharmony_ci};
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci/* Internal Function declaration */
978c2ecf20Sopenharmony_cistatic int qbman_swp_enqueue_direct(struct qbman_swp *s,
988c2ecf20Sopenharmony_ci				    const struct qbman_eq_desc *d,
998c2ecf20Sopenharmony_ci				    const struct dpaa2_fd *fd);
1008c2ecf20Sopenharmony_cistatic int qbman_swp_enqueue_mem_back(struct qbman_swp *s,
1018c2ecf20Sopenharmony_ci				      const struct qbman_eq_desc *d,
1028c2ecf20Sopenharmony_ci				      const struct dpaa2_fd *fd);
1038c2ecf20Sopenharmony_cistatic int qbman_swp_enqueue_multiple_direct(struct qbman_swp *s,
1048c2ecf20Sopenharmony_ci					     const struct qbman_eq_desc *d,
1058c2ecf20Sopenharmony_ci					     const struct dpaa2_fd *fd,
1068c2ecf20Sopenharmony_ci					     uint32_t *flags,
1078c2ecf20Sopenharmony_ci					     int num_frames);
1088c2ecf20Sopenharmony_cistatic int qbman_swp_enqueue_multiple_mem_back(struct qbman_swp *s,
1098c2ecf20Sopenharmony_ci					       const struct qbman_eq_desc *d,
1108c2ecf20Sopenharmony_ci					       const struct dpaa2_fd *fd,
1118c2ecf20Sopenharmony_ci					       uint32_t *flags,
1128c2ecf20Sopenharmony_ci					       int num_frames);
1138c2ecf20Sopenharmony_cistatic int
1148c2ecf20Sopenharmony_ciqbman_swp_enqueue_multiple_desc_direct(struct qbman_swp *s,
1158c2ecf20Sopenharmony_ci				       const struct qbman_eq_desc *d,
1168c2ecf20Sopenharmony_ci				       const struct dpaa2_fd *fd,
1178c2ecf20Sopenharmony_ci				       int num_frames);
1188c2ecf20Sopenharmony_cistatic
1198c2ecf20Sopenharmony_ciint qbman_swp_enqueue_multiple_desc_mem_back(struct qbman_swp *s,
1208c2ecf20Sopenharmony_ci					     const struct qbman_eq_desc *d,
1218c2ecf20Sopenharmony_ci					     const struct dpaa2_fd *fd,
1228c2ecf20Sopenharmony_ci					     int num_frames);
1238c2ecf20Sopenharmony_cistatic int qbman_swp_pull_direct(struct qbman_swp *s,
1248c2ecf20Sopenharmony_ci				 struct qbman_pull_desc *d);
1258c2ecf20Sopenharmony_cistatic int qbman_swp_pull_mem_back(struct qbman_swp *s,
1268c2ecf20Sopenharmony_ci				   struct qbman_pull_desc *d);
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ciconst struct dpaa2_dq *qbman_swp_dqrr_next_direct(struct qbman_swp *s);
1298c2ecf20Sopenharmony_ciconst struct dpaa2_dq *qbman_swp_dqrr_next_mem_back(struct qbman_swp *s);
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_cistatic int qbman_swp_release_direct(struct qbman_swp *s,
1328c2ecf20Sopenharmony_ci				    const struct qbman_release_desc *d,
1338c2ecf20Sopenharmony_ci				    const u64 *buffers,
1348c2ecf20Sopenharmony_ci				    unsigned int num_buffers);
1358c2ecf20Sopenharmony_cistatic int qbman_swp_release_mem_back(struct qbman_swp *s,
1368c2ecf20Sopenharmony_ci				      const struct qbman_release_desc *d,
1378c2ecf20Sopenharmony_ci				      const u64 *buffers,
1388c2ecf20Sopenharmony_ci				      unsigned int num_buffers);
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci/* Function pointers */
1418c2ecf20Sopenharmony_ciint (*qbman_swp_enqueue_ptr)(struct qbman_swp *s,
1428c2ecf20Sopenharmony_ci			     const struct qbman_eq_desc *d,
1438c2ecf20Sopenharmony_ci			     const struct dpaa2_fd *fd)
1448c2ecf20Sopenharmony_ci	= qbman_swp_enqueue_direct;
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ciint (*qbman_swp_enqueue_multiple_ptr)(struct qbman_swp *s,
1478c2ecf20Sopenharmony_ci				      const struct qbman_eq_desc *d,
1488c2ecf20Sopenharmony_ci				      const struct dpaa2_fd *fd,
1498c2ecf20Sopenharmony_ci				      uint32_t *flags,
1508c2ecf20Sopenharmony_ci					     int num_frames)
1518c2ecf20Sopenharmony_ci	= qbman_swp_enqueue_multiple_direct;
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ciint
1548c2ecf20Sopenharmony_ci(*qbman_swp_enqueue_multiple_desc_ptr)(struct qbman_swp *s,
1558c2ecf20Sopenharmony_ci				       const struct qbman_eq_desc *d,
1568c2ecf20Sopenharmony_ci				       const struct dpaa2_fd *fd,
1578c2ecf20Sopenharmony_ci				       int num_frames)
1588c2ecf20Sopenharmony_ci	= qbman_swp_enqueue_multiple_desc_direct;
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ciint (*qbman_swp_pull_ptr)(struct qbman_swp *s, struct qbman_pull_desc *d)
1618c2ecf20Sopenharmony_ci			= qbman_swp_pull_direct;
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ciconst struct dpaa2_dq *(*qbman_swp_dqrr_next_ptr)(struct qbman_swp *s)
1648c2ecf20Sopenharmony_ci			= qbman_swp_dqrr_next_direct;
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ciint (*qbman_swp_release_ptr)(struct qbman_swp *s,
1678c2ecf20Sopenharmony_ci			     const struct qbman_release_desc *d,
1688c2ecf20Sopenharmony_ci			     const u64 *buffers,
1698c2ecf20Sopenharmony_ci			     unsigned int num_buffers)
1708c2ecf20Sopenharmony_ci			= qbman_swp_release_direct;
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci/* Portal Access */
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_cistatic inline u32 qbman_read_register(struct qbman_swp *p, u32 offset)
1758c2ecf20Sopenharmony_ci{
1768c2ecf20Sopenharmony_ci	return readl_relaxed(p->addr_cinh + offset);
1778c2ecf20Sopenharmony_ci}
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_cistatic inline void qbman_write_register(struct qbman_swp *p, u32 offset,
1808c2ecf20Sopenharmony_ci					u32 value)
1818c2ecf20Sopenharmony_ci{
1828c2ecf20Sopenharmony_ci	writel_relaxed(value, p->addr_cinh + offset);
1838c2ecf20Sopenharmony_ci}
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_cistatic inline void *qbman_get_cmd(struct qbman_swp *p, u32 offset)
1868c2ecf20Sopenharmony_ci{
1878c2ecf20Sopenharmony_ci	return p->addr_cena + offset;
1888c2ecf20Sopenharmony_ci}
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci#define QBMAN_CINH_SWP_CFG   0xd00
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci#define SWP_CFG_DQRR_MF_SHIFT 20
1938c2ecf20Sopenharmony_ci#define SWP_CFG_EST_SHIFT     16
1948c2ecf20Sopenharmony_ci#define SWP_CFG_CPBS_SHIFT    15
1958c2ecf20Sopenharmony_ci#define SWP_CFG_WN_SHIFT      14
1968c2ecf20Sopenharmony_ci#define SWP_CFG_RPM_SHIFT     12
1978c2ecf20Sopenharmony_ci#define SWP_CFG_DCM_SHIFT     10
1988c2ecf20Sopenharmony_ci#define SWP_CFG_EPM_SHIFT     8
1998c2ecf20Sopenharmony_ci#define SWP_CFG_VPM_SHIFT     7
2008c2ecf20Sopenharmony_ci#define SWP_CFG_CPM_SHIFT     6
2018c2ecf20Sopenharmony_ci#define SWP_CFG_SD_SHIFT      5
2028c2ecf20Sopenharmony_ci#define SWP_CFG_SP_SHIFT      4
2038c2ecf20Sopenharmony_ci#define SWP_CFG_SE_SHIFT      3
2048c2ecf20Sopenharmony_ci#define SWP_CFG_DP_SHIFT      2
2058c2ecf20Sopenharmony_ci#define SWP_CFG_DE_SHIFT      1
2068c2ecf20Sopenharmony_ci#define SWP_CFG_EP_SHIFT      0
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_cistatic inline u32 qbman_set_swp_cfg(u8 max_fill, u8 wn,	u8 est, u8 rpm, u8 dcm,
2098c2ecf20Sopenharmony_ci				    u8 epm, int sd, int sp, int se,
2108c2ecf20Sopenharmony_ci				    int dp, int de, int ep)
2118c2ecf20Sopenharmony_ci{
2128c2ecf20Sopenharmony_ci	return (max_fill << SWP_CFG_DQRR_MF_SHIFT |
2138c2ecf20Sopenharmony_ci		est << SWP_CFG_EST_SHIFT |
2148c2ecf20Sopenharmony_ci		wn << SWP_CFG_WN_SHIFT |
2158c2ecf20Sopenharmony_ci		rpm << SWP_CFG_RPM_SHIFT |
2168c2ecf20Sopenharmony_ci		dcm << SWP_CFG_DCM_SHIFT |
2178c2ecf20Sopenharmony_ci		epm << SWP_CFG_EPM_SHIFT |
2188c2ecf20Sopenharmony_ci		sd << SWP_CFG_SD_SHIFT |
2198c2ecf20Sopenharmony_ci		sp << SWP_CFG_SP_SHIFT |
2208c2ecf20Sopenharmony_ci		se << SWP_CFG_SE_SHIFT |
2218c2ecf20Sopenharmony_ci		dp << SWP_CFG_DP_SHIFT |
2228c2ecf20Sopenharmony_ci		de << SWP_CFG_DE_SHIFT |
2238c2ecf20Sopenharmony_ci		ep << SWP_CFG_EP_SHIFT);
2248c2ecf20Sopenharmony_ci}
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci#define QMAN_RT_MODE	   0x00000100
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_cistatic inline u8 qm_cyc_diff(u8 ringsize, u8 first, u8 last)
2298c2ecf20Sopenharmony_ci{
2308c2ecf20Sopenharmony_ci	/* 'first' is included, 'last' is excluded */
2318c2ecf20Sopenharmony_ci	if (first <= last)
2328c2ecf20Sopenharmony_ci		return last - first;
2338c2ecf20Sopenharmony_ci	else
2348c2ecf20Sopenharmony_ci		return (2 * ringsize) - (first - last);
2358c2ecf20Sopenharmony_ci}
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci/**
2388c2ecf20Sopenharmony_ci * qbman_swp_init() - Create a functional object representing the given
2398c2ecf20Sopenharmony_ci *                    QBMan portal descriptor.
2408c2ecf20Sopenharmony_ci * @d: the given qbman swp descriptor
2418c2ecf20Sopenharmony_ci *
2428c2ecf20Sopenharmony_ci * Return qbman_swp portal for success, NULL if the object cannot
2438c2ecf20Sopenharmony_ci * be created.
2448c2ecf20Sopenharmony_ci */
2458c2ecf20Sopenharmony_cistruct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d)
2468c2ecf20Sopenharmony_ci{
2478c2ecf20Sopenharmony_ci	struct qbman_swp *p = kzalloc(sizeof(*p), GFP_KERNEL);
2488c2ecf20Sopenharmony_ci	u32 reg;
2498c2ecf20Sopenharmony_ci	u32 mask_size;
2508c2ecf20Sopenharmony_ci	u32 eqcr_pi;
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci	if (!p)
2538c2ecf20Sopenharmony_ci		return NULL;
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	spin_lock_init(&p->access_spinlock);
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	p->desc = d;
2588c2ecf20Sopenharmony_ci	p->mc.valid_bit = QB_VALID_BIT;
2598c2ecf20Sopenharmony_ci	p->sdq = 0;
2608c2ecf20Sopenharmony_ci	p->sdq |= qbman_sdqcr_dct_prio_ics << QB_SDQCR_DCT_SHIFT;
2618c2ecf20Sopenharmony_ci	p->sdq |= qbman_sdqcr_fc_up_to_3 << QB_SDQCR_FC_SHIFT;
2628c2ecf20Sopenharmony_ci	p->sdq |= QMAN_SDQCR_TOKEN << QB_SDQCR_TOK_SHIFT;
2638c2ecf20Sopenharmony_ci	if ((p->desc->qman_version & QMAN_REV_MASK) >= QMAN_REV_5000)
2648c2ecf20Sopenharmony_ci		p->mr.valid_bit = QB_VALID_BIT;
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	atomic_set(&p->vdq.available, 1);
2678c2ecf20Sopenharmony_ci	p->vdq.valid_bit = QB_VALID_BIT;
2688c2ecf20Sopenharmony_ci	p->dqrr.next_idx = 0;
2698c2ecf20Sopenharmony_ci	p->dqrr.valid_bit = QB_VALID_BIT;
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci	if ((p->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_4100) {
2728c2ecf20Sopenharmony_ci		p->dqrr.dqrr_size = 4;
2738c2ecf20Sopenharmony_ci		p->dqrr.reset_bug = 1;
2748c2ecf20Sopenharmony_ci	} else {
2758c2ecf20Sopenharmony_ci		p->dqrr.dqrr_size = 8;
2768c2ecf20Sopenharmony_ci		p->dqrr.reset_bug = 0;
2778c2ecf20Sopenharmony_ci	}
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci	p->addr_cena = d->cena_bar;
2808c2ecf20Sopenharmony_ci	p->addr_cinh = d->cinh_bar;
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	if ((p->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000) {
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci		reg = qbman_set_swp_cfg(p->dqrr.dqrr_size,
2858c2ecf20Sopenharmony_ci			1, /* Writes Non-cacheable */
2868c2ecf20Sopenharmony_ci			0, /* EQCR_CI stashing threshold */
2878c2ecf20Sopenharmony_ci			3, /* RPM: RCR in array mode */
2888c2ecf20Sopenharmony_ci			2, /* DCM: Discrete consumption ack */
2898c2ecf20Sopenharmony_ci			2, /* EPM: EQCR in ring mode */
2908c2ecf20Sopenharmony_ci			1, /* mem stashing drop enable enable */
2918c2ecf20Sopenharmony_ci			1, /* mem stashing priority enable */
2928c2ecf20Sopenharmony_ci			1, /* mem stashing enable */
2938c2ecf20Sopenharmony_ci			1, /* dequeue stashing priority enable */
2948c2ecf20Sopenharmony_ci			0, /* dequeue stashing enable enable */
2958c2ecf20Sopenharmony_ci			0); /* EQCR_CI stashing priority enable */
2968c2ecf20Sopenharmony_ci	} else {
2978c2ecf20Sopenharmony_ci		memset(p->addr_cena, 0, 64 * 1024);
2988c2ecf20Sopenharmony_ci		reg = qbman_set_swp_cfg(p->dqrr.dqrr_size,
2998c2ecf20Sopenharmony_ci			1, /* Writes Non-cacheable */
3008c2ecf20Sopenharmony_ci			1, /* EQCR_CI stashing threshold */
3018c2ecf20Sopenharmony_ci			3, /* RPM: RCR in array mode */
3028c2ecf20Sopenharmony_ci			2, /* DCM: Discrete consumption ack */
3038c2ecf20Sopenharmony_ci			0, /* EPM: EQCR in ring mode */
3048c2ecf20Sopenharmony_ci			1, /* mem stashing drop enable */
3058c2ecf20Sopenharmony_ci			1, /* mem stashing priority enable */
3068c2ecf20Sopenharmony_ci			1, /* mem stashing enable */
3078c2ecf20Sopenharmony_ci			1, /* dequeue stashing priority enable */
3088c2ecf20Sopenharmony_ci			0, /* dequeue stashing enable */
3098c2ecf20Sopenharmony_ci			0); /* EQCR_CI stashing priority enable */
3108c2ecf20Sopenharmony_ci		reg |= 1 << SWP_CFG_CPBS_SHIFT | /* memory-backed mode */
3118c2ecf20Sopenharmony_ci		       1 << SWP_CFG_VPM_SHIFT |  /* VDQCR read triggered mode */
3128c2ecf20Sopenharmony_ci		       1 << SWP_CFG_CPM_SHIFT;   /* CR read triggered mode */
3138c2ecf20Sopenharmony_ci	}
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci	qbman_write_register(p, QBMAN_CINH_SWP_CFG, reg);
3168c2ecf20Sopenharmony_ci	reg = qbman_read_register(p, QBMAN_CINH_SWP_CFG);
3178c2ecf20Sopenharmony_ci	if (!reg) {
3188c2ecf20Sopenharmony_ci		pr_err("qbman: the portal is not enabled!\n");
3198c2ecf20Sopenharmony_ci		kfree(p);
3208c2ecf20Sopenharmony_ci		return NULL;
3218c2ecf20Sopenharmony_ci	}
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ci	if ((p->desc->qman_version & QMAN_REV_MASK) >= QMAN_REV_5000) {
3248c2ecf20Sopenharmony_ci		qbman_write_register(p, QBMAN_CINH_SWP_EQCR_PI, QMAN_RT_MODE);
3258c2ecf20Sopenharmony_ci		qbman_write_register(p, QBMAN_CINH_SWP_RCR_PI, QMAN_RT_MODE);
3268c2ecf20Sopenharmony_ci	}
3278c2ecf20Sopenharmony_ci	/*
3288c2ecf20Sopenharmony_ci	 * SDQCR needs to be initialized to 0 when no channels are
3298c2ecf20Sopenharmony_ci	 * being dequeued from or else the QMan HW will indicate an
3308c2ecf20Sopenharmony_ci	 * error.  The values that were calculated above will be
3318c2ecf20Sopenharmony_ci	 * applied when dequeues from a specific channel are enabled.
3328c2ecf20Sopenharmony_ci	 */
3338c2ecf20Sopenharmony_ci	qbman_write_register(p, QBMAN_CINH_SWP_SDQCR, 0);
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ci	p->eqcr.pi_ring_size = 8;
3368c2ecf20Sopenharmony_ci	if ((p->desc->qman_version & QMAN_REV_MASK) >= QMAN_REV_5000) {
3378c2ecf20Sopenharmony_ci		p->eqcr.pi_ring_size = 32;
3388c2ecf20Sopenharmony_ci		qbman_swp_enqueue_ptr =
3398c2ecf20Sopenharmony_ci			qbman_swp_enqueue_mem_back;
3408c2ecf20Sopenharmony_ci		qbman_swp_enqueue_multiple_ptr =
3418c2ecf20Sopenharmony_ci			qbman_swp_enqueue_multiple_mem_back;
3428c2ecf20Sopenharmony_ci		qbman_swp_enqueue_multiple_desc_ptr =
3438c2ecf20Sopenharmony_ci			qbman_swp_enqueue_multiple_desc_mem_back;
3448c2ecf20Sopenharmony_ci		qbman_swp_pull_ptr = qbman_swp_pull_mem_back;
3458c2ecf20Sopenharmony_ci		qbman_swp_dqrr_next_ptr = qbman_swp_dqrr_next_mem_back;
3468c2ecf20Sopenharmony_ci		qbman_swp_release_ptr = qbman_swp_release_mem_back;
3478c2ecf20Sopenharmony_ci	}
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci	for (mask_size = p->eqcr.pi_ring_size; mask_size > 0; mask_size >>= 1)
3508c2ecf20Sopenharmony_ci		p->eqcr.pi_ci_mask = (p->eqcr.pi_ci_mask << 1) + 1;
3518c2ecf20Sopenharmony_ci	eqcr_pi = qbman_read_register(p, QBMAN_CINH_SWP_EQCR_PI);
3528c2ecf20Sopenharmony_ci	p->eqcr.pi = eqcr_pi & p->eqcr.pi_ci_mask;
3538c2ecf20Sopenharmony_ci	p->eqcr.pi_vb = eqcr_pi & QB_VALID_BIT;
3548c2ecf20Sopenharmony_ci	p->eqcr.ci = qbman_read_register(p, QBMAN_CINH_SWP_EQCR_CI)
3558c2ecf20Sopenharmony_ci			& p->eqcr.pi_ci_mask;
3568c2ecf20Sopenharmony_ci	p->eqcr.available = p->eqcr.pi_ring_size;
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci	return p;
3598c2ecf20Sopenharmony_ci}
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci/**
3628c2ecf20Sopenharmony_ci * qbman_swp_finish() - Create and destroy a functional object representing
3638c2ecf20Sopenharmony_ci *                      the given QBMan portal descriptor.
3648c2ecf20Sopenharmony_ci * @p: the qbman_swp object to be destroyed
3658c2ecf20Sopenharmony_ci */
3668c2ecf20Sopenharmony_civoid qbman_swp_finish(struct qbman_swp *p)
3678c2ecf20Sopenharmony_ci{
3688c2ecf20Sopenharmony_ci	kfree(p);
3698c2ecf20Sopenharmony_ci}
3708c2ecf20Sopenharmony_ci
3718c2ecf20Sopenharmony_ci/**
3728c2ecf20Sopenharmony_ci * qbman_swp_interrupt_read_status()
3738c2ecf20Sopenharmony_ci * @p: the given software portal
3748c2ecf20Sopenharmony_ci *
3758c2ecf20Sopenharmony_ci * Return the value in the SWP_ISR register.
3768c2ecf20Sopenharmony_ci */
3778c2ecf20Sopenharmony_ciu32 qbman_swp_interrupt_read_status(struct qbman_swp *p)
3788c2ecf20Sopenharmony_ci{
3798c2ecf20Sopenharmony_ci	return qbman_read_register(p, QBMAN_CINH_SWP_ISR);
3808c2ecf20Sopenharmony_ci}
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci/**
3838c2ecf20Sopenharmony_ci * qbman_swp_interrupt_clear_status()
3848c2ecf20Sopenharmony_ci * @p: the given software portal
3858c2ecf20Sopenharmony_ci * @mask: The mask to clear in SWP_ISR register
3868c2ecf20Sopenharmony_ci */
3878c2ecf20Sopenharmony_civoid qbman_swp_interrupt_clear_status(struct qbman_swp *p, u32 mask)
3888c2ecf20Sopenharmony_ci{
3898c2ecf20Sopenharmony_ci	qbman_write_register(p, QBMAN_CINH_SWP_ISR, mask);
3908c2ecf20Sopenharmony_ci}
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci/**
3938c2ecf20Sopenharmony_ci * qbman_swp_interrupt_get_trigger() - read interrupt enable register
3948c2ecf20Sopenharmony_ci * @p: the given software portal
3958c2ecf20Sopenharmony_ci *
3968c2ecf20Sopenharmony_ci * Return the value in the SWP_IER register.
3978c2ecf20Sopenharmony_ci */
3988c2ecf20Sopenharmony_ciu32 qbman_swp_interrupt_get_trigger(struct qbman_swp *p)
3998c2ecf20Sopenharmony_ci{
4008c2ecf20Sopenharmony_ci	return qbman_read_register(p, QBMAN_CINH_SWP_IER);
4018c2ecf20Sopenharmony_ci}
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_ci/**
4048c2ecf20Sopenharmony_ci * qbman_swp_interrupt_set_trigger() - enable interrupts for a swp
4058c2ecf20Sopenharmony_ci * @p: the given software portal
4068c2ecf20Sopenharmony_ci * @mask: The mask of bits to enable in SWP_IER
4078c2ecf20Sopenharmony_ci */
4088c2ecf20Sopenharmony_civoid qbman_swp_interrupt_set_trigger(struct qbman_swp *p, u32 mask)
4098c2ecf20Sopenharmony_ci{
4108c2ecf20Sopenharmony_ci	qbman_write_register(p, QBMAN_CINH_SWP_IER, mask);
4118c2ecf20Sopenharmony_ci}
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci/**
4148c2ecf20Sopenharmony_ci * qbman_swp_interrupt_get_inhibit() - read interrupt mask register
4158c2ecf20Sopenharmony_ci * @p: the given software portal object
4168c2ecf20Sopenharmony_ci *
4178c2ecf20Sopenharmony_ci * Return the value in the SWP_IIR register.
4188c2ecf20Sopenharmony_ci */
4198c2ecf20Sopenharmony_ciint qbman_swp_interrupt_get_inhibit(struct qbman_swp *p)
4208c2ecf20Sopenharmony_ci{
4218c2ecf20Sopenharmony_ci	return qbman_read_register(p, QBMAN_CINH_SWP_IIR);
4228c2ecf20Sopenharmony_ci}
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_ci/**
4258c2ecf20Sopenharmony_ci * qbman_swp_interrupt_set_inhibit() - write interrupt mask register
4268c2ecf20Sopenharmony_ci * @p: the given software portal object
4278c2ecf20Sopenharmony_ci * @mask: The mask to set in SWP_IIR register
4288c2ecf20Sopenharmony_ci */
4298c2ecf20Sopenharmony_civoid qbman_swp_interrupt_set_inhibit(struct qbman_swp *p, int inhibit)
4308c2ecf20Sopenharmony_ci{
4318c2ecf20Sopenharmony_ci	qbman_write_register(p, QBMAN_CINH_SWP_IIR, inhibit ? 0xffffffff : 0);
4328c2ecf20Sopenharmony_ci}
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_ci/*
4358c2ecf20Sopenharmony_ci * Different management commands all use this common base layer of code to issue
4368c2ecf20Sopenharmony_ci * commands and poll for results.
4378c2ecf20Sopenharmony_ci */
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci/*
4408c2ecf20Sopenharmony_ci * Returns a pointer to where the caller should fill in their management command
4418c2ecf20Sopenharmony_ci * (caller should ignore the verb byte)
4428c2ecf20Sopenharmony_ci */
4438c2ecf20Sopenharmony_civoid *qbman_swp_mc_start(struct qbman_swp *p)
4448c2ecf20Sopenharmony_ci{
4458c2ecf20Sopenharmony_ci	if ((p->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000)
4468c2ecf20Sopenharmony_ci		return qbman_get_cmd(p, QBMAN_CENA_SWP_CR);
4478c2ecf20Sopenharmony_ci	else
4488c2ecf20Sopenharmony_ci		return qbman_get_cmd(p, QBMAN_CENA_SWP_CR_MEM);
4498c2ecf20Sopenharmony_ci}
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_ci/*
4528c2ecf20Sopenharmony_ci * Commits merges in the caller-supplied command verb (which should not include
4538c2ecf20Sopenharmony_ci * the valid-bit) and submits the command to hardware
4548c2ecf20Sopenharmony_ci */
4558c2ecf20Sopenharmony_civoid qbman_swp_mc_submit(struct qbman_swp *p, void *cmd, u8 cmd_verb)
4568c2ecf20Sopenharmony_ci{
4578c2ecf20Sopenharmony_ci	u8 *v = cmd;
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ci	if ((p->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000) {
4608c2ecf20Sopenharmony_ci		dma_wmb();
4618c2ecf20Sopenharmony_ci		*v = cmd_verb | p->mc.valid_bit;
4628c2ecf20Sopenharmony_ci	} else {
4638c2ecf20Sopenharmony_ci		*v = cmd_verb | p->mc.valid_bit;
4648c2ecf20Sopenharmony_ci		dma_wmb();
4658c2ecf20Sopenharmony_ci		qbman_write_register(p, QBMAN_CINH_SWP_CR_RT, QMAN_RT_MODE);
4668c2ecf20Sopenharmony_ci	}
4678c2ecf20Sopenharmony_ci}
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci/*
4708c2ecf20Sopenharmony_ci * Checks for a completed response (returns non-NULL if only if the response
4718c2ecf20Sopenharmony_ci * is complete).
4728c2ecf20Sopenharmony_ci */
4738c2ecf20Sopenharmony_civoid *qbman_swp_mc_result(struct qbman_swp *p)
4748c2ecf20Sopenharmony_ci{
4758c2ecf20Sopenharmony_ci	u32 *ret, verb;
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci	if ((p->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000) {
4788c2ecf20Sopenharmony_ci		ret = qbman_get_cmd(p, QBMAN_CENA_SWP_RR(p->mc.valid_bit));
4798c2ecf20Sopenharmony_ci		/* Remove the valid-bit - command completed if the rest
4808c2ecf20Sopenharmony_ci		 * is non-zero.
4818c2ecf20Sopenharmony_ci		 */
4828c2ecf20Sopenharmony_ci		verb = ret[0] & ~QB_VALID_BIT;
4838c2ecf20Sopenharmony_ci		if (!verb)
4848c2ecf20Sopenharmony_ci			return NULL;
4858c2ecf20Sopenharmony_ci		p->mc.valid_bit ^= QB_VALID_BIT;
4868c2ecf20Sopenharmony_ci	} else {
4878c2ecf20Sopenharmony_ci		ret = qbman_get_cmd(p, QBMAN_CENA_SWP_RR_MEM);
4888c2ecf20Sopenharmony_ci		/* Command completed if the valid bit is toggled */
4898c2ecf20Sopenharmony_ci		if (p->mr.valid_bit != (ret[0] & QB_VALID_BIT))
4908c2ecf20Sopenharmony_ci			return NULL;
4918c2ecf20Sopenharmony_ci		/* Command completed if the rest is non-zero */
4928c2ecf20Sopenharmony_ci		verb = ret[0] & ~QB_VALID_BIT;
4938c2ecf20Sopenharmony_ci		if (!verb)
4948c2ecf20Sopenharmony_ci			return NULL;
4958c2ecf20Sopenharmony_ci		p->mr.valid_bit ^= QB_VALID_BIT;
4968c2ecf20Sopenharmony_ci	}
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci	return ret;
4998c2ecf20Sopenharmony_ci}
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_ci#define QB_ENQUEUE_CMD_OPTIONS_SHIFT    0
5028c2ecf20Sopenharmony_cienum qb_enqueue_commands {
5038c2ecf20Sopenharmony_ci	enqueue_empty = 0,
5048c2ecf20Sopenharmony_ci	enqueue_response_always = 1,
5058c2ecf20Sopenharmony_ci	enqueue_rejects_to_fq = 2
5068c2ecf20Sopenharmony_ci};
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci#define QB_ENQUEUE_CMD_ORP_ENABLE_SHIFT      2
5098c2ecf20Sopenharmony_ci#define QB_ENQUEUE_CMD_IRQ_ON_DISPATCH_SHIFT 3
5108c2ecf20Sopenharmony_ci#define QB_ENQUEUE_CMD_TARGET_TYPE_SHIFT     4
5118c2ecf20Sopenharmony_ci#define QB_ENQUEUE_CMD_DCA_EN_SHIFT          7
5128c2ecf20Sopenharmony_ci
5138c2ecf20Sopenharmony_ci/**
5148c2ecf20Sopenharmony_ci * qbman_eq_desc_clear() - Clear the contents of a descriptor to
5158c2ecf20Sopenharmony_ci *                         default/starting state.
5168c2ecf20Sopenharmony_ci */
5178c2ecf20Sopenharmony_civoid qbman_eq_desc_clear(struct qbman_eq_desc *d)
5188c2ecf20Sopenharmony_ci{
5198c2ecf20Sopenharmony_ci	memset(d, 0, sizeof(*d));
5208c2ecf20Sopenharmony_ci}
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci/**
5238c2ecf20Sopenharmony_ci * qbman_eq_desc_set_no_orp() - Set enqueue descriptor without orp
5248c2ecf20Sopenharmony_ci * @d:                the enqueue descriptor.
5258c2ecf20Sopenharmony_ci * @response_success: 1 = enqueue with response always; 0 = enqueue with
5268c2ecf20Sopenharmony_ci *                    rejections returned on a FQ.
5278c2ecf20Sopenharmony_ci */
5288c2ecf20Sopenharmony_civoid qbman_eq_desc_set_no_orp(struct qbman_eq_desc *d, int respond_success)
5298c2ecf20Sopenharmony_ci{
5308c2ecf20Sopenharmony_ci	d->verb &= ~(1 << QB_ENQUEUE_CMD_ORP_ENABLE_SHIFT);
5318c2ecf20Sopenharmony_ci	if (respond_success)
5328c2ecf20Sopenharmony_ci		d->verb |= enqueue_response_always;
5338c2ecf20Sopenharmony_ci	else
5348c2ecf20Sopenharmony_ci		d->verb |= enqueue_rejects_to_fq;
5358c2ecf20Sopenharmony_ci}
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_ci/*
5388c2ecf20Sopenharmony_ci * Exactly one of the following descriptor "targets" should be set. (Calling any
5398c2ecf20Sopenharmony_ci * one of these will replace the effect of any prior call to one of these.)
5408c2ecf20Sopenharmony_ci *   -enqueue to a frame queue
5418c2ecf20Sopenharmony_ci *   -enqueue to a queuing destination
5428c2ecf20Sopenharmony_ci */
5438c2ecf20Sopenharmony_ci
5448c2ecf20Sopenharmony_ci/**
5458c2ecf20Sopenharmony_ci * qbman_eq_desc_set_fq() - set the FQ for the enqueue command
5468c2ecf20Sopenharmony_ci * @d:    the enqueue descriptor
5478c2ecf20Sopenharmony_ci * @fqid: the id of the frame queue to be enqueued
5488c2ecf20Sopenharmony_ci */
5498c2ecf20Sopenharmony_civoid qbman_eq_desc_set_fq(struct qbman_eq_desc *d, u32 fqid)
5508c2ecf20Sopenharmony_ci{
5518c2ecf20Sopenharmony_ci	d->verb &= ~(1 << QB_ENQUEUE_CMD_TARGET_TYPE_SHIFT);
5528c2ecf20Sopenharmony_ci	d->tgtid = cpu_to_le32(fqid);
5538c2ecf20Sopenharmony_ci}
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_ci/**
5568c2ecf20Sopenharmony_ci * qbman_eq_desc_set_qd() - Set Queuing Destination for the enqueue command
5578c2ecf20Sopenharmony_ci * @d:       the enqueue descriptor
5588c2ecf20Sopenharmony_ci * @qdid:    the id of the queuing destination to be enqueued
5598c2ecf20Sopenharmony_ci * @qd_bin:  the queuing destination bin
5608c2ecf20Sopenharmony_ci * @qd_prio: the queuing destination priority
5618c2ecf20Sopenharmony_ci */
5628c2ecf20Sopenharmony_civoid qbman_eq_desc_set_qd(struct qbman_eq_desc *d, u32 qdid,
5638c2ecf20Sopenharmony_ci			  u32 qd_bin, u32 qd_prio)
5648c2ecf20Sopenharmony_ci{
5658c2ecf20Sopenharmony_ci	d->verb |= 1 << QB_ENQUEUE_CMD_TARGET_TYPE_SHIFT;
5668c2ecf20Sopenharmony_ci	d->tgtid = cpu_to_le32(qdid);
5678c2ecf20Sopenharmony_ci	d->qdbin = cpu_to_le16(qd_bin);
5688c2ecf20Sopenharmony_ci	d->qpri = qd_prio;
5698c2ecf20Sopenharmony_ci}
5708c2ecf20Sopenharmony_ci
5718c2ecf20Sopenharmony_ci#define EQAR_IDX(eqar)     ((eqar) & 0x7)
5728c2ecf20Sopenharmony_ci#define EQAR_VB(eqar)      ((eqar) & 0x80)
5738c2ecf20Sopenharmony_ci#define EQAR_SUCCESS(eqar) ((eqar) & 0x100)
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_ci#define QB_RT_BIT ((u32)0x100)
5768c2ecf20Sopenharmony_ci/**
5778c2ecf20Sopenharmony_ci * qbman_swp_enqueue_direct() - Issue an enqueue command
5788c2ecf20Sopenharmony_ci * @s:  the software portal used for enqueue
5798c2ecf20Sopenharmony_ci * @d:  the enqueue descriptor
5808c2ecf20Sopenharmony_ci * @fd: the frame descriptor to be enqueued
5818c2ecf20Sopenharmony_ci *
5828c2ecf20Sopenharmony_ci * Please note that 'fd' should only be NULL if the "action" of the
5838c2ecf20Sopenharmony_ci * descriptor is "orp_hole" or "orp_nesn".
5848c2ecf20Sopenharmony_ci *
5858c2ecf20Sopenharmony_ci * Return 0 for successful enqueue, -EBUSY if the EQCR is not ready.
5868c2ecf20Sopenharmony_ci */
5878c2ecf20Sopenharmony_cistatic
5888c2ecf20Sopenharmony_ciint qbman_swp_enqueue_direct(struct qbman_swp *s,
5898c2ecf20Sopenharmony_ci			     const struct qbman_eq_desc *d,
5908c2ecf20Sopenharmony_ci			     const struct dpaa2_fd *fd)
5918c2ecf20Sopenharmony_ci{
5928c2ecf20Sopenharmony_ci	int flags = 0;
5938c2ecf20Sopenharmony_ci	int ret = qbman_swp_enqueue_multiple_direct(s, d, fd, &flags, 1);
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci	if (ret >= 0)
5968c2ecf20Sopenharmony_ci		ret = 0;
5978c2ecf20Sopenharmony_ci	else
5988c2ecf20Sopenharmony_ci		ret = -EBUSY;
5998c2ecf20Sopenharmony_ci	return  ret;
6008c2ecf20Sopenharmony_ci}
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci/**
6038c2ecf20Sopenharmony_ci * qbman_swp_enqueue_mem_back() - Issue an enqueue command
6048c2ecf20Sopenharmony_ci * @s:  the software portal used for enqueue
6058c2ecf20Sopenharmony_ci * @d:  the enqueue descriptor
6068c2ecf20Sopenharmony_ci * @fd: the frame descriptor to be enqueued
6078c2ecf20Sopenharmony_ci *
6088c2ecf20Sopenharmony_ci * Please note that 'fd' should only be NULL if the "action" of the
6098c2ecf20Sopenharmony_ci * descriptor is "orp_hole" or "orp_nesn".
6108c2ecf20Sopenharmony_ci *
6118c2ecf20Sopenharmony_ci * Return 0 for successful enqueue, -EBUSY if the EQCR is not ready.
6128c2ecf20Sopenharmony_ci */
6138c2ecf20Sopenharmony_cistatic
6148c2ecf20Sopenharmony_ciint qbman_swp_enqueue_mem_back(struct qbman_swp *s,
6158c2ecf20Sopenharmony_ci			       const struct qbman_eq_desc *d,
6168c2ecf20Sopenharmony_ci			       const struct dpaa2_fd *fd)
6178c2ecf20Sopenharmony_ci{
6188c2ecf20Sopenharmony_ci	int flags = 0;
6198c2ecf20Sopenharmony_ci	int ret = qbman_swp_enqueue_multiple_mem_back(s, d, fd, &flags, 1);
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_ci	if (ret >= 0)
6228c2ecf20Sopenharmony_ci		ret = 0;
6238c2ecf20Sopenharmony_ci	else
6248c2ecf20Sopenharmony_ci		ret = -EBUSY;
6258c2ecf20Sopenharmony_ci	return  ret;
6268c2ecf20Sopenharmony_ci}
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_ci/**
6298c2ecf20Sopenharmony_ci * qbman_swp_enqueue_multiple_direct() - Issue a multi enqueue command
6308c2ecf20Sopenharmony_ci * using one enqueue descriptor
6318c2ecf20Sopenharmony_ci * @s:  the software portal used for enqueue
6328c2ecf20Sopenharmony_ci * @d:  the enqueue descriptor
6338c2ecf20Sopenharmony_ci * @fd: table pointer of frame descriptor table to be enqueued
6348c2ecf20Sopenharmony_ci * @flags: table pointer of QBMAN_ENQUEUE_FLAG_DCA flags, not used if NULL
6358c2ecf20Sopenharmony_ci * @num_frames: number of fd to be enqueued
6368c2ecf20Sopenharmony_ci *
6378c2ecf20Sopenharmony_ci * Return the number of fd enqueued, or a negative error number.
6388c2ecf20Sopenharmony_ci */
6398c2ecf20Sopenharmony_cistatic
6408c2ecf20Sopenharmony_ciint qbman_swp_enqueue_multiple_direct(struct qbman_swp *s,
6418c2ecf20Sopenharmony_ci				      const struct qbman_eq_desc *d,
6428c2ecf20Sopenharmony_ci				      const struct dpaa2_fd *fd,
6438c2ecf20Sopenharmony_ci				      uint32_t *flags,
6448c2ecf20Sopenharmony_ci				      int num_frames)
6458c2ecf20Sopenharmony_ci{
6468c2ecf20Sopenharmony_ci	uint32_t *p = NULL;
6478c2ecf20Sopenharmony_ci	const uint32_t *cl = (uint32_t *)d;
6488c2ecf20Sopenharmony_ci	uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask;
6498c2ecf20Sopenharmony_ci	int i, num_enqueued = 0;
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_ci	spin_lock(&s->access_spinlock);
6528c2ecf20Sopenharmony_ci	half_mask = (s->eqcr.pi_ci_mask>>1);
6538c2ecf20Sopenharmony_ci	full_mask = s->eqcr.pi_ci_mask;
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_ci	if (!s->eqcr.available) {
6568c2ecf20Sopenharmony_ci		eqcr_ci = s->eqcr.ci;
6578c2ecf20Sopenharmony_ci		p = s->addr_cena + QBMAN_CENA_SWP_EQCR_CI;
6588c2ecf20Sopenharmony_ci		s->eqcr.ci = qbman_read_register(s, QBMAN_CINH_SWP_EQCR_CI);
6598c2ecf20Sopenharmony_ci		s->eqcr.ci &= full_mask;
6608c2ecf20Sopenharmony_ci
6618c2ecf20Sopenharmony_ci		s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size,
6628c2ecf20Sopenharmony_ci					eqcr_ci, s->eqcr.ci);
6638c2ecf20Sopenharmony_ci		if (!s->eqcr.available) {
6648c2ecf20Sopenharmony_ci			spin_unlock(&s->access_spinlock);
6658c2ecf20Sopenharmony_ci			return 0;
6668c2ecf20Sopenharmony_ci		}
6678c2ecf20Sopenharmony_ci	}
6688c2ecf20Sopenharmony_ci
6698c2ecf20Sopenharmony_ci	eqcr_pi = s->eqcr.pi;
6708c2ecf20Sopenharmony_ci	num_enqueued = (s->eqcr.available < num_frames) ?
6718c2ecf20Sopenharmony_ci			s->eqcr.available : num_frames;
6728c2ecf20Sopenharmony_ci	s->eqcr.available -= num_enqueued;
6738c2ecf20Sopenharmony_ci	/* Fill in the EQCR ring */
6748c2ecf20Sopenharmony_ci	for (i = 0; i < num_enqueued; i++) {
6758c2ecf20Sopenharmony_ci		p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
6768c2ecf20Sopenharmony_ci		/* Skip copying the verb */
6778c2ecf20Sopenharmony_ci		memcpy(&p[1], &cl[1], EQ_DESC_SIZE_WITHOUT_FD - 1);
6788c2ecf20Sopenharmony_ci		memcpy(&p[EQ_DESC_SIZE_FD_START/sizeof(uint32_t)],
6798c2ecf20Sopenharmony_ci		       &fd[i], sizeof(*fd));
6808c2ecf20Sopenharmony_ci		eqcr_pi++;
6818c2ecf20Sopenharmony_ci	}
6828c2ecf20Sopenharmony_ci
6838c2ecf20Sopenharmony_ci	dma_wmb();
6848c2ecf20Sopenharmony_ci
6858c2ecf20Sopenharmony_ci	/* Set the verb byte, have to substitute in the valid-bit */
6868c2ecf20Sopenharmony_ci	eqcr_pi = s->eqcr.pi;
6878c2ecf20Sopenharmony_ci	for (i = 0; i < num_enqueued; i++) {
6888c2ecf20Sopenharmony_ci		p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
6898c2ecf20Sopenharmony_ci		p[0] = cl[0] | s->eqcr.pi_vb;
6908c2ecf20Sopenharmony_ci		if (flags && (flags[i] & QBMAN_ENQUEUE_FLAG_DCA)) {
6918c2ecf20Sopenharmony_ci			struct qbman_eq_desc *d = (struct qbman_eq_desc *)p;
6928c2ecf20Sopenharmony_ci
6938c2ecf20Sopenharmony_ci			d->dca = (1 << QB_ENQUEUE_CMD_DCA_EN_SHIFT) |
6948c2ecf20Sopenharmony_ci				((flags[i]) & QBMAN_EQCR_DCA_IDXMASK);
6958c2ecf20Sopenharmony_ci		}
6968c2ecf20Sopenharmony_ci		eqcr_pi++;
6978c2ecf20Sopenharmony_ci		if (!(eqcr_pi & half_mask))
6988c2ecf20Sopenharmony_ci			s->eqcr.pi_vb ^= QB_VALID_BIT;
6998c2ecf20Sopenharmony_ci	}
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_ci	/* Flush all the cacheline without load/store in between */
7028c2ecf20Sopenharmony_ci	eqcr_pi = s->eqcr.pi;
7038c2ecf20Sopenharmony_ci	for (i = 0; i < num_enqueued; i++)
7048c2ecf20Sopenharmony_ci		eqcr_pi++;
7058c2ecf20Sopenharmony_ci	s->eqcr.pi = eqcr_pi & full_mask;
7068c2ecf20Sopenharmony_ci	spin_unlock(&s->access_spinlock);
7078c2ecf20Sopenharmony_ci
7088c2ecf20Sopenharmony_ci	return num_enqueued;
7098c2ecf20Sopenharmony_ci}
7108c2ecf20Sopenharmony_ci
7118c2ecf20Sopenharmony_ci/**
7128c2ecf20Sopenharmony_ci * qbman_swp_enqueue_multiple_mem_back() - Issue a multi enqueue command
7138c2ecf20Sopenharmony_ci * using one enqueue descriptor
7148c2ecf20Sopenharmony_ci * @s:  the software portal used for enqueue
7158c2ecf20Sopenharmony_ci * @d:  the enqueue descriptor
7168c2ecf20Sopenharmony_ci * @fd: table pointer of frame descriptor table to be enqueued
7178c2ecf20Sopenharmony_ci * @flags: table pointer of QBMAN_ENQUEUE_FLAG_DCA flags, not used if NULL
7188c2ecf20Sopenharmony_ci * @num_frames: number of fd to be enqueued
7198c2ecf20Sopenharmony_ci *
7208c2ecf20Sopenharmony_ci * Return the number of fd enqueued, or a negative error number.
7218c2ecf20Sopenharmony_ci */
7228c2ecf20Sopenharmony_cistatic
7238c2ecf20Sopenharmony_ciint qbman_swp_enqueue_multiple_mem_back(struct qbman_swp *s,
7248c2ecf20Sopenharmony_ci					const struct qbman_eq_desc *d,
7258c2ecf20Sopenharmony_ci					const struct dpaa2_fd *fd,
7268c2ecf20Sopenharmony_ci					uint32_t *flags,
7278c2ecf20Sopenharmony_ci					int num_frames)
7288c2ecf20Sopenharmony_ci{
7298c2ecf20Sopenharmony_ci	uint32_t *p = NULL;
7308c2ecf20Sopenharmony_ci	const uint32_t *cl = (uint32_t *)(d);
7318c2ecf20Sopenharmony_ci	uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask;
7328c2ecf20Sopenharmony_ci	int i, num_enqueued = 0;
7338c2ecf20Sopenharmony_ci	unsigned long irq_flags;
7348c2ecf20Sopenharmony_ci
7358c2ecf20Sopenharmony_ci	spin_lock_irqsave(&s->access_spinlock, irq_flags);
7368c2ecf20Sopenharmony_ci
7378c2ecf20Sopenharmony_ci	half_mask = (s->eqcr.pi_ci_mask>>1);
7388c2ecf20Sopenharmony_ci	full_mask = s->eqcr.pi_ci_mask;
7398c2ecf20Sopenharmony_ci	if (!s->eqcr.available) {
7408c2ecf20Sopenharmony_ci		eqcr_ci = s->eqcr.ci;
7418c2ecf20Sopenharmony_ci		p = s->addr_cena + QBMAN_CENA_SWP_EQCR_CI_MEMBACK;
7428c2ecf20Sopenharmony_ci		s->eqcr.ci = *p & full_mask;
7438c2ecf20Sopenharmony_ci		s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size,
7448c2ecf20Sopenharmony_ci					eqcr_ci, s->eqcr.ci);
7458c2ecf20Sopenharmony_ci		if (!s->eqcr.available) {
7468c2ecf20Sopenharmony_ci			spin_unlock_irqrestore(&s->access_spinlock, irq_flags);
7478c2ecf20Sopenharmony_ci			return 0;
7488c2ecf20Sopenharmony_ci		}
7498c2ecf20Sopenharmony_ci	}
7508c2ecf20Sopenharmony_ci
7518c2ecf20Sopenharmony_ci	eqcr_pi = s->eqcr.pi;
7528c2ecf20Sopenharmony_ci	num_enqueued = (s->eqcr.available < num_frames) ?
7538c2ecf20Sopenharmony_ci			s->eqcr.available : num_frames;
7548c2ecf20Sopenharmony_ci	s->eqcr.available -= num_enqueued;
7558c2ecf20Sopenharmony_ci	/* Fill in the EQCR ring */
7568c2ecf20Sopenharmony_ci	for (i = 0; i < num_enqueued; i++) {
7578c2ecf20Sopenharmony_ci		p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
7588c2ecf20Sopenharmony_ci		/* Skip copying the verb */
7598c2ecf20Sopenharmony_ci		memcpy(&p[1], &cl[1], EQ_DESC_SIZE_WITHOUT_FD - 1);
7608c2ecf20Sopenharmony_ci		memcpy(&p[EQ_DESC_SIZE_FD_START/sizeof(uint32_t)],
7618c2ecf20Sopenharmony_ci		       &fd[i], sizeof(*fd));
7628c2ecf20Sopenharmony_ci		eqcr_pi++;
7638c2ecf20Sopenharmony_ci	}
7648c2ecf20Sopenharmony_ci
7658c2ecf20Sopenharmony_ci	/* Set the verb byte, have to substitute in the valid-bit */
7668c2ecf20Sopenharmony_ci	eqcr_pi = s->eqcr.pi;
7678c2ecf20Sopenharmony_ci	for (i = 0; i < num_enqueued; i++) {
7688c2ecf20Sopenharmony_ci		p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
7698c2ecf20Sopenharmony_ci		p[0] = cl[0] | s->eqcr.pi_vb;
7708c2ecf20Sopenharmony_ci		if (flags && (flags[i] & QBMAN_ENQUEUE_FLAG_DCA)) {
7718c2ecf20Sopenharmony_ci			struct qbman_eq_desc *d = (struct qbman_eq_desc *)p;
7728c2ecf20Sopenharmony_ci
7738c2ecf20Sopenharmony_ci			d->dca = (1 << QB_ENQUEUE_CMD_DCA_EN_SHIFT) |
7748c2ecf20Sopenharmony_ci				((flags[i]) & QBMAN_EQCR_DCA_IDXMASK);
7758c2ecf20Sopenharmony_ci		}
7768c2ecf20Sopenharmony_ci		eqcr_pi++;
7778c2ecf20Sopenharmony_ci		if (!(eqcr_pi & half_mask))
7788c2ecf20Sopenharmony_ci			s->eqcr.pi_vb ^= QB_VALID_BIT;
7798c2ecf20Sopenharmony_ci	}
7808c2ecf20Sopenharmony_ci	s->eqcr.pi = eqcr_pi & full_mask;
7818c2ecf20Sopenharmony_ci
7828c2ecf20Sopenharmony_ci	dma_wmb();
7838c2ecf20Sopenharmony_ci	qbman_write_register(s, QBMAN_CINH_SWP_EQCR_PI,
7848c2ecf20Sopenharmony_ci				(QB_RT_BIT)|(s->eqcr.pi)|s->eqcr.pi_vb);
7858c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&s->access_spinlock, irq_flags);
7868c2ecf20Sopenharmony_ci
7878c2ecf20Sopenharmony_ci	return num_enqueued;
7888c2ecf20Sopenharmony_ci}
7898c2ecf20Sopenharmony_ci
7908c2ecf20Sopenharmony_ci/**
7918c2ecf20Sopenharmony_ci * qbman_swp_enqueue_multiple_desc_direct() - Issue a multi enqueue command
7928c2ecf20Sopenharmony_ci * using multiple enqueue descriptor
7938c2ecf20Sopenharmony_ci * @s:  the software portal used for enqueue
7948c2ecf20Sopenharmony_ci * @d:  table of minimal enqueue descriptor
7958c2ecf20Sopenharmony_ci * @fd: table pointer of frame descriptor table to be enqueued
7968c2ecf20Sopenharmony_ci * @num_frames: number of fd to be enqueued
7978c2ecf20Sopenharmony_ci *
7988c2ecf20Sopenharmony_ci * Return the number of fd enqueued, or a negative error number.
7998c2ecf20Sopenharmony_ci */
8008c2ecf20Sopenharmony_cistatic
8018c2ecf20Sopenharmony_ciint qbman_swp_enqueue_multiple_desc_direct(struct qbman_swp *s,
8028c2ecf20Sopenharmony_ci					   const struct qbman_eq_desc *d,
8038c2ecf20Sopenharmony_ci					   const struct dpaa2_fd *fd,
8048c2ecf20Sopenharmony_ci					   int num_frames)
8058c2ecf20Sopenharmony_ci{
8068c2ecf20Sopenharmony_ci	uint32_t *p;
8078c2ecf20Sopenharmony_ci	const uint32_t *cl;
8088c2ecf20Sopenharmony_ci	uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask;
8098c2ecf20Sopenharmony_ci	int i, num_enqueued = 0;
8108c2ecf20Sopenharmony_ci
8118c2ecf20Sopenharmony_ci	half_mask = (s->eqcr.pi_ci_mask>>1);
8128c2ecf20Sopenharmony_ci	full_mask = s->eqcr.pi_ci_mask;
8138c2ecf20Sopenharmony_ci	if (!s->eqcr.available) {
8148c2ecf20Sopenharmony_ci		eqcr_ci = s->eqcr.ci;
8158c2ecf20Sopenharmony_ci		p = s->addr_cena + QBMAN_CENA_SWP_EQCR_CI;
8168c2ecf20Sopenharmony_ci		s->eqcr.ci = qbman_read_register(s, QBMAN_CINH_SWP_EQCR_CI);
8178c2ecf20Sopenharmony_ci		s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size,
8188c2ecf20Sopenharmony_ci					eqcr_ci, s->eqcr.ci);
8198c2ecf20Sopenharmony_ci		if (!s->eqcr.available)
8208c2ecf20Sopenharmony_ci			return 0;
8218c2ecf20Sopenharmony_ci	}
8228c2ecf20Sopenharmony_ci
8238c2ecf20Sopenharmony_ci	eqcr_pi = s->eqcr.pi;
8248c2ecf20Sopenharmony_ci	num_enqueued = (s->eqcr.available < num_frames) ?
8258c2ecf20Sopenharmony_ci			s->eqcr.available : num_frames;
8268c2ecf20Sopenharmony_ci	s->eqcr.available -= num_enqueued;
8278c2ecf20Sopenharmony_ci	/* Fill in the EQCR ring */
8288c2ecf20Sopenharmony_ci	for (i = 0; i < num_enqueued; i++) {
8298c2ecf20Sopenharmony_ci		p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
8308c2ecf20Sopenharmony_ci		cl = (uint32_t *)(&d[i]);
8318c2ecf20Sopenharmony_ci		/* Skip copying the verb */
8328c2ecf20Sopenharmony_ci		memcpy(&p[1], &cl[1], EQ_DESC_SIZE_WITHOUT_FD - 1);
8338c2ecf20Sopenharmony_ci		memcpy(&p[EQ_DESC_SIZE_FD_START/sizeof(uint32_t)],
8348c2ecf20Sopenharmony_ci		       &fd[i], sizeof(*fd));
8358c2ecf20Sopenharmony_ci		eqcr_pi++;
8368c2ecf20Sopenharmony_ci	}
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_ci	dma_wmb();
8398c2ecf20Sopenharmony_ci
8408c2ecf20Sopenharmony_ci	/* Set the verb byte, have to substitute in the valid-bit */
8418c2ecf20Sopenharmony_ci	eqcr_pi = s->eqcr.pi;
8428c2ecf20Sopenharmony_ci	for (i = 0; i < num_enqueued; i++) {
8438c2ecf20Sopenharmony_ci		p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
8448c2ecf20Sopenharmony_ci		cl = (uint32_t *)(&d[i]);
8458c2ecf20Sopenharmony_ci		p[0] = cl[0] | s->eqcr.pi_vb;
8468c2ecf20Sopenharmony_ci		eqcr_pi++;
8478c2ecf20Sopenharmony_ci		if (!(eqcr_pi & half_mask))
8488c2ecf20Sopenharmony_ci			s->eqcr.pi_vb ^= QB_VALID_BIT;
8498c2ecf20Sopenharmony_ci	}
8508c2ecf20Sopenharmony_ci
8518c2ecf20Sopenharmony_ci	/* Flush all the cacheline without load/store in between */
8528c2ecf20Sopenharmony_ci	eqcr_pi = s->eqcr.pi;
8538c2ecf20Sopenharmony_ci	for (i = 0; i < num_enqueued; i++)
8548c2ecf20Sopenharmony_ci		eqcr_pi++;
8558c2ecf20Sopenharmony_ci	s->eqcr.pi = eqcr_pi & full_mask;
8568c2ecf20Sopenharmony_ci
8578c2ecf20Sopenharmony_ci	return num_enqueued;
8588c2ecf20Sopenharmony_ci}
8598c2ecf20Sopenharmony_ci
8608c2ecf20Sopenharmony_ci/**
8618c2ecf20Sopenharmony_ci * qbman_swp_enqueue_multiple_desc_mem_back() - Issue a multi enqueue command
8628c2ecf20Sopenharmony_ci * using multiple enqueue descriptor
8638c2ecf20Sopenharmony_ci * @s:  the software portal used for enqueue
8648c2ecf20Sopenharmony_ci * @d:  table of minimal enqueue descriptor
8658c2ecf20Sopenharmony_ci * @fd: table pointer of frame descriptor table to be enqueued
8668c2ecf20Sopenharmony_ci * @num_frames: number of fd to be enqueued
8678c2ecf20Sopenharmony_ci *
8688c2ecf20Sopenharmony_ci * Return the number of fd enqueued, or a negative error number.
8698c2ecf20Sopenharmony_ci */
8708c2ecf20Sopenharmony_cistatic
8718c2ecf20Sopenharmony_ciint qbman_swp_enqueue_multiple_desc_mem_back(struct qbman_swp *s,
8728c2ecf20Sopenharmony_ci					   const struct qbman_eq_desc *d,
8738c2ecf20Sopenharmony_ci					   const struct dpaa2_fd *fd,
8748c2ecf20Sopenharmony_ci					   int num_frames)
8758c2ecf20Sopenharmony_ci{
8768c2ecf20Sopenharmony_ci	uint32_t *p;
8778c2ecf20Sopenharmony_ci	const uint32_t *cl;
8788c2ecf20Sopenharmony_ci	uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask;
8798c2ecf20Sopenharmony_ci	int i, num_enqueued = 0;
8808c2ecf20Sopenharmony_ci
8818c2ecf20Sopenharmony_ci	half_mask = (s->eqcr.pi_ci_mask>>1);
8828c2ecf20Sopenharmony_ci	full_mask = s->eqcr.pi_ci_mask;
8838c2ecf20Sopenharmony_ci	if (!s->eqcr.available) {
8848c2ecf20Sopenharmony_ci		eqcr_ci = s->eqcr.ci;
8858c2ecf20Sopenharmony_ci		p = s->addr_cena + QBMAN_CENA_SWP_EQCR_CI_MEMBACK;
8868c2ecf20Sopenharmony_ci		s->eqcr.ci = *p & full_mask;
8878c2ecf20Sopenharmony_ci		s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size,
8888c2ecf20Sopenharmony_ci					eqcr_ci, s->eqcr.ci);
8898c2ecf20Sopenharmony_ci		if (!s->eqcr.available)
8908c2ecf20Sopenharmony_ci			return 0;
8918c2ecf20Sopenharmony_ci	}
8928c2ecf20Sopenharmony_ci
8938c2ecf20Sopenharmony_ci	eqcr_pi = s->eqcr.pi;
8948c2ecf20Sopenharmony_ci	num_enqueued = (s->eqcr.available < num_frames) ?
8958c2ecf20Sopenharmony_ci			s->eqcr.available : num_frames;
8968c2ecf20Sopenharmony_ci	s->eqcr.available -= num_enqueued;
8978c2ecf20Sopenharmony_ci	/* Fill in the EQCR ring */
8988c2ecf20Sopenharmony_ci	for (i = 0; i < num_enqueued; i++) {
8998c2ecf20Sopenharmony_ci		p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
9008c2ecf20Sopenharmony_ci		cl = (uint32_t *)(&d[i]);
9018c2ecf20Sopenharmony_ci		/* Skip copying the verb */
9028c2ecf20Sopenharmony_ci		memcpy(&p[1], &cl[1], EQ_DESC_SIZE_WITHOUT_FD - 1);
9038c2ecf20Sopenharmony_ci		memcpy(&p[EQ_DESC_SIZE_FD_START/sizeof(uint32_t)],
9048c2ecf20Sopenharmony_ci		       &fd[i], sizeof(*fd));
9058c2ecf20Sopenharmony_ci		eqcr_pi++;
9068c2ecf20Sopenharmony_ci	}
9078c2ecf20Sopenharmony_ci
9088c2ecf20Sopenharmony_ci	/* Set the verb byte, have to substitute in the valid-bit */
9098c2ecf20Sopenharmony_ci	eqcr_pi = s->eqcr.pi;
9108c2ecf20Sopenharmony_ci	for (i = 0; i < num_enqueued; i++) {
9118c2ecf20Sopenharmony_ci		p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
9128c2ecf20Sopenharmony_ci		cl = (uint32_t *)(&d[i]);
9138c2ecf20Sopenharmony_ci		p[0] = cl[0] | s->eqcr.pi_vb;
9148c2ecf20Sopenharmony_ci		eqcr_pi++;
9158c2ecf20Sopenharmony_ci		if (!(eqcr_pi & half_mask))
9168c2ecf20Sopenharmony_ci			s->eqcr.pi_vb ^= QB_VALID_BIT;
9178c2ecf20Sopenharmony_ci	}
9188c2ecf20Sopenharmony_ci
9198c2ecf20Sopenharmony_ci	s->eqcr.pi = eqcr_pi & full_mask;
9208c2ecf20Sopenharmony_ci
9218c2ecf20Sopenharmony_ci	dma_wmb();
9228c2ecf20Sopenharmony_ci	qbman_write_register(s, QBMAN_CINH_SWP_EQCR_PI,
9238c2ecf20Sopenharmony_ci				(QB_RT_BIT)|(s->eqcr.pi)|s->eqcr.pi_vb);
9248c2ecf20Sopenharmony_ci
9258c2ecf20Sopenharmony_ci	return num_enqueued;
9268c2ecf20Sopenharmony_ci}
9278c2ecf20Sopenharmony_ci
9288c2ecf20Sopenharmony_ci/* Static (push) dequeue */
9298c2ecf20Sopenharmony_ci
9308c2ecf20Sopenharmony_ci/**
9318c2ecf20Sopenharmony_ci * qbman_swp_push_get() - Get the push dequeue setup
9328c2ecf20Sopenharmony_ci * @p:           the software portal object
9338c2ecf20Sopenharmony_ci * @channel_idx: the channel index to query
9348c2ecf20Sopenharmony_ci * @enabled:     returned boolean to show whether the push dequeue is enabled
9358c2ecf20Sopenharmony_ci *               for the given channel
9368c2ecf20Sopenharmony_ci */
9378c2ecf20Sopenharmony_civoid qbman_swp_push_get(struct qbman_swp *s, u8 channel_idx, int *enabled)
9388c2ecf20Sopenharmony_ci{
9398c2ecf20Sopenharmony_ci	u16 src = (s->sdq >> QB_SDQCR_SRC_SHIFT) & QB_SDQCR_SRC_MASK;
9408c2ecf20Sopenharmony_ci
9418c2ecf20Sopenharmony_ci	WARN_ON(channel_idx > 15);
9428c2ecf20Sopenharmony_ci	*enabled = src | (1 << channel_idx);
9438c2ecf20Sopenharmony_ci}
9448c2ecf20Sopenharmony_ci
9458c2ecf20Sopenharmony_ci/**
9468c2ecf20Sopenharmony_ci * qbman_swp_push_set() - Enable or disable push dequeue
9478c2ecf20Sopenharmony_ci * @p:           the software portal object
9488c2ecf20Sopenharmony_ci * @channel_idx: the channel index (0 to 15)
9498c2ecf20Sopenharmony_ci * @enable:      enable or disable push dequeue
9508c2ecf20Sopenharmony_ci */
9518c2ecf20Sopenharmony_civoid qbman_swp_push_set(struct qbman_swp *s, u8 channel_idx, int enable)
9528c2ecf20Sopenharmony_ci{
9538c2ecf20Sopenharmony_ci	u16 dqsrc;
9548c2ecf20Sopenharmony_ci
9558c2ecf20Sopenharmony_ci	WARN_ON(channel_idx > 15);
9568c2ecf20Sopenharmony_ci	if (enable)
9578c2ecf20Sopenharmony_ci		s->sdq |= 1 << channel_idx;
9588c2ecf20Sopenharmony_ci	else
9598c2ecf20Sopenharmony_ci		s->sdq &= ~(1 << channel_idx);
9608c2ecf20Sopenharmony_ci
9618c2ecf20Sopenharmony_ci	/* Read make the complete src map.  If no channels are enabled
9628c2ecf20Sopenharmony_ci	 * the SDQCR must be 0 or else QMan will assert errors
9638c2ecf20Sopenharmony_ci	 */
9648c2ecf20Sopenharmony_ci	dqsrc = (s->sdq >> QB_SDQCR_SRC_SHIFT) & QB_SDQCR_SRC_MASK;
9658c2ecf20Sopenharmony_ci	if (dqsrc != 0)
9668c2ecf20Sopenharmony_ci		qbman_write_register(s, QBMAN_CINH_SWP_SDQCR, s->sdq);
9678c2ecf20Sopenharmony_ci	else
9688c2ecf20Sopenharmony_ci		qbman_write_register(s, QBMAN_CINH_SWP_SDQCR, 0);
9698c2ecf20Sopenharmony_ci}
9708c2ecf20Sopenharmony_ci
9718c2ecf20Sopenharmony_ci#define QB_VDQCR_VERB_DCT_SHIFT    0
9728c2ecf20Sopenharmony_ci#define QB_VDQCR_VERB_DT_SHIFT     2
9738c2ecf20Sopenharmony_ci#define QB_VDQCR_VERB_RLS_SHIFT    4
9748c2ecf20Sopenharmony_ci#define QB_VDQCR_VERB_WAE_SHIFT    5
9758c2ecf20Sopenharmony_ci
9768c2ecf20Sopenharmony_cienum qb_pull_dt_e {
9778c2ecf20Sopenharmony_ci	qb_pull_dt_channel,
9788c2ecf20Sopenharmony_ci	qb_pull_dt_workqueue,
9798c2ecf20Sopenharmony_ci	qb_pull_dt_framequeue
9808c2ecf20Sopenharmony_ci};
9818c2ecf20Sopenharmony_ci
9828c2ecf20Sopenharmony_ci/**
9838c2ecf20Sopenharmony_ci * qbman_pull_desc_clear() - Clear the contents of a descriptor to
9848c2ecf20Sopenharmony_ci *                           default/starting state
9858c2ecf20Sopenharmony_ci * @d: the pull dequeue descriptor to be cleared
9868c2ecf20Sopenharmony_ci */
9878c2ecf20Sopenharmony_civoid qbman_pull_desc_clear(struct qbman_pull_desc *d)
9888c2ecf20Sopenharmony_ci{
9898c2ecf20Sopenharmony_ci	memset(d, 0, sizeof(*d));
9908c2ecf20Sopenharmony_ci}
9918c2ecf20Sopenharmony_ci
9928c2ecf20Sopenharmony_ci/**
9938c2ecf20Sopenharmony_ci * qbman_pull_desc_set_storage()- Set the pull dequeue storage
9948c2ecf20Sopenharmony_ci * @d:            the pull dequeue descriptor to be set
9958c2ecf20Sopenharmony_ci * @storage:      the pointer of the memory to store the dequeue result
9968c2ecf20Sopenharmony_ci * @storage_phys: the physical address of the storage memory
9978c2ecf20Sopenharmony_ci * @stash:        to indicate whether write allocate is enabled
9988c2ecf20Sopenharmony_ci *
9998c2ecf20Sopenharmony_ci * If not called, or if called with 'storage' as NULL, the result pull dequeues
10008c2ecf20Sopenharmony_ci * will produce results to DQRR. If 'storage' is non-NULL, then results are
10018c2ecf20Sopenharmony_ci * produced to the given memory location (using the DMA address which
10028c2ecf20Sopenharmony_ci * the caller provides in 'storage_phys'), and 'stash' controls whether or not
10038c2ecf20Sopenharmony_ci * those writes to main-memory express a cache-warming attribute.
10048c2ecf20Sopenharmony_ci */
10058c2ecf20Sopenharmony_civoid qbman_pull_desc_set_storage(struct qbman_pull_desc *d,
10068c2ecf20Sopenharmony_ci				 struct dpaa2_dq *storage,
10078c2ecf20Sopenharmony_ci				 dma_addr_t storage_phys,
10088c2ecf20Sopenharmony_ci				 int stash)
10098c2ecf20Sopenharmony_ci{
10108c2ecf20Sopenharmony_ci	/* save the virtual address */
10118c2ecf20Sopenharmony_ci	d->rsp_addr_virt = (u64)(uintptr_t)storage;
10128c2ecf20Sopenharmony_ci
10138c2ecf20Sopenharmony_ci	if (!storage) {
10148c2ecf20Sopenharmony_ci		d->verb &= ~(1 << QB_VDQCR_VERB_RLS_SHIFT);
10158c2ecf20Sopenharmony_ci		return;
10168c2ecf20Sopenharmony_ci	}
10178c2ecf20Sopenharmony_ci	d->verb |= 1 << QB_VDQCR_VERB_RLS_SHIFT;
10188c2ecf20Sopenharmony_ci	if (stash)
10198c2ecf20Sopenharmony_ci		d->verb |= 1 << QB_VDQCR_VERB_WAE_SHIFT;
10208c2ecf20Sopenharmony_ci	else
10218c2ecf20Sopenharmony_ci		d->verb &= ~(1 << QB_VDQCR_VERB_WAE_SHIFT);
10228c2ecf20Sopenharmony_ci
10238c2ecf20Sopenharmony_ci	d->rsp_addr = cpu_to_le64(storage_phys);
10248c2ecf20Sopenharmony_ci}
10258c2ecf20Sopenharmony_ci
10268c2ecf20Sopenharmony_ci/**
10278c2ecf20Sopenharmony_ci * qbman_pull_desc_set_numframes() - Set the number of frames to be dequeued
10288c2ecf20Sopenharmony_ci * @d:         the pull dequeue descriptor to be set
10298c2ecf20Sopenharmony_ci * @numframes: number of frames to be set, must be between 1 and 16, inclusive
10308c2ecf20Sopenharmony_ci */
10318c2ecf20Sopenharmony_civoid qbman_pull_desc_set_numframes(struct qbman_pull_desc *d, u8 numframes)
10328c2ecf20Sopenharmony_ci{
10338c2ecf20Sopenharmony_ci	d->numf = numframes - 1;
10348c2ecf20Sopenharmony_ci}
10358c2ecf20Sopenharmony_ci
10368c2ecf20Sopenharmony_ci/*
10378c2ecf20Sopenharmony_ci * Exactly one of the following descriptor "actions" should be set. (Calling any
10388c2ecf20Sopenharmony_ci * one of these will replace the effect of any prior call to one of these.)
10398c2ecf20Sopenharmony_ci * - pull dequeue from the given frame queue (FQ)
10408c2ecf20Sopenharmony_ci * - pull dequeue from any FQ in the given work queue (WQ)
10418c2ecf20Sopenharmony_ci * - pull dequeue from any FQ in any WQ in the given channel
10428c2ecf20Sopenharmony_ci */
10438c2ecf20Sopenharmony_ci
10448c2ecf20Sopenharmony_ci/**
10458c2ecf20Sopenharmony_ci * qbman_pull_desc_set_fq() - Set fqid from which the dequeue command dequeues
10468c2ecf20Sopenharmony_ci * @fqid: the frame queue index of the given FQ
10478c2ecf20Sopenharmony_ci */
10488c2ecf20Sopenharmony_civoid qbman_pull_desc_set_fq(struct qbman_pull_desc *d, u32 fqid)
10498c2ecf20Sopenharmony_ci{
10508c2ecf20Sopenharmony_ci	d->verb |= 1 << QB_VDQCR_VERB_DCT_SHIFT;
10518c2ecf20Sopenharmony_ci	d->verb |= qb_pull_dt_framequeue << QB_VDQCR_VERB_DT_SHIFT;
10528c2ecf20Sopenharmony_ci	d->dq_src = cpu_to_le32(fqid);
10538c2ecf20Sopenharmony_ci}
10548c2ecf20Sopenharmony_ci
10558c2ecf20Sopenharmony_ci/**
10568c2ecf20Sopenharmony_ci * qbman_pull_desc_set_wq() - Set wqid from which the dequeue command dequeues
10578c2ecf20Sopenharmony_ci * @wqid: composed of channel id and wqid within the channel
10588c2ecf20Sopenharmony_ci * @dct:  the dequeue command type
10598c2ecf20Sopenharmony_ci */
10608c2ecf20Sopenharmony_civoid qbman_pull_desc_set_wq(struct qbman_pull_desc *d, u32 wqid,
10618c2ecf20Sopenharmony_ci			    enum qbman_pull_type_e dct)
10628c2ecf20Sopenharmony_ci{
10638c2ecf20Sopenharmony_ci	d->verb |= dct << QB_VDQCR_VERB_DCT_SHIFT;
10648c2ecf20Sopenharmony_ci	d->verb |= qb_pull_dt_workqueue << QB_VDQCR_VERB_DT_SHIFT;
10658c2ecf20Sopenharmony_ci	d->dq_src = cpu_to_le32(wqid);
10668c2ecf20Sopenharmony_ci}
10678c2ecf20Sopenharmony_ci
10688c2ecf20Sopenharmony_ci/**
10698c2ecf20Sopenharmony_ci * qbman_pull_desc_set_channel() - Set channelid from which the dequeue command
10708c2ecf20Sopenharmony_ci *                                 dequeues
10718c2ecf20Sopenharmony_ci * @chid: the channel id to be dequeued
10728c2ecf20Sopenharmony_ci * @dct:  the dequeue command type
10738c2ecf20Sopenharmony_ci */
10748c2ecf20Sopenharmony_civoid qbman_pull_desc_set_channel(struct qbman_pull_desc *d, u32 chid,
10758c2ecf20Sopenharmony_ci				 enum qbman_pull_type_e dct)
10768c2ecf20Sopenharmony_ci{
10778c2ecf20Sopenharmony_ci	d->verb |= dct << QB_VDQCR_VERB_DCT_SHIFT;
10788c2ecf20Sopenharmony_ci	d->verb |= qb_pull_dt_channel << QB_VDQCR_VERB_DT_SHIFT;
10798c2ecf20Sopenharmony_ci	d->dq_src = cpu_to_le32(chid);
10808c2ecf20Sopenharmony_ci}
10818c2ecf20Sopenharmony_ci
10828c2ecf20Sopenharmony_ci/**
10838c2ecf20Sopenharmony_ci * qbman_swp_pull_direct() - Issue the pull dequeue command
10848c2ecf20Sopenharmony_ci * @s: the software portal object
10858c2ecf20Sopenharmony_ci * @d: the software portal descriptor which has been configured with
10868c2ecf20Sopenharmony_ci *     the set of qbman_pull_desc_set_*() calls
10878c2ecf20Sopenharmony_ci *
10888c2ecf20Sopenharmony_ci * Return 0 for success, and -EBUSY if the software portal is not ready
10898c2ecf20Sopenharmony_ci * to do pull dequeue.
10908c2ecf20Sopenharmony_ci */
10918c2ecf20Sopenharmony_cistatic
10928c2ecf20Sopenharmony_ciint qbman_swp_pull_direct(struct qbman_swp *s, struct qbman_pull_desc *d)
10938c2ecf20Sopenharmony_ci{
10948c2ecf20Sopenharmony_ci	struct qbman_pull_desc *p;
10958c2ecf20Sopenharmony_ci
10968c2ecf20Sopenharmony_ci	if (!atomic_dec_and_test(&s->vdq.available)) {
10978c2ecf20Sopenharmony_ci		atomic_inc(&s->vdq.available);
10988c2ecf20Sopenharmony_ci		return -EBUSY;
10998c2ecf20Sopenharmony_ci	}
11008c2ecf20Sopenharmony_ci	s->vdq.storage = (void *)(uintptr_t)d->rsp_addr_virt;
11018c2ecf20Sopenharmony_ci	if ((s->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000)
11028c2ecf20Sopenharmony_ci		p = qbman_get_cmd(s, QBMAN_CENA_SWP_VDQCR);
11038c2ecf20Sopenharmony_ci	else
11048c2ecf20Sopenharmony_ci		p = qbman_get_cmd(s, QBMAN_CENA_SWP_VDQCR_MEM);
11058c2ecf20Sopenharmony_ci	p->numf = d->numf;
11068c2ecf20Sopenharmony_ci	p->tok = QMAN_DQ_TOKEN_VALID;
11078c2ecf20Sopenharmony_ci	p->dq_src = d->dq_src;
11088c2ecf20Sopenharmony_ci	p->rsp_addr = d->rsp_addr;
11098c2ecf20Sopenharmony_ci	p->rsp_addr_virt = d->rsp_addr_virt;
11108c2ecf20Sopenharmony_ci	dma_wmb();
11118c2ecf20Sopenharmony_ci	/* Set the verb byte, have to substitute in the valid-bit */
11128c2ecf20Sopenharmony_ci	p->verb = d->verb | s->vdq.valid_bit;
11138c2ecf20Sopenharmony_ci	s->vdq.valid_bit ^= QB_VALID_BIT;
11148c2ecf20Sopenharmony_ci
11158c2ecf20Sopenharmony_ci	return 0;
11168c2ecf20Sopenharmony_ci}
11178c2ecf20Sopenharmony_ci
11188c2ecf20Sopenharmony_ci/**
11198c2ecf20Sopenharmony_ci * qbman_swp_pull_mem_back() - Issue the pull dequeue command
11208c2ecf20Sopenharmony_ci * @s: the software portal object
11218c2ecf20Sopenharmony_ci * @d: the software portal descriptor which has been configured with
11228c2ecf20Sopenharmony_ci *     the set of qbman_pull_desc_set_*() calls
11238c2ecf20Sopenharmony_ci *
11248c2ecf20Sopenharmony_ci * Return 0 for success, and -EBUSY if the software portal is not ready
11258c2ecf20Sopenharmony_ci * to do pull dequeue.
11268c2ecf20Sopenharmony_ci */
11278c2ecf20Sopenharmony_cistatic
11288c2ecf20Sopenharmony_ciint qbman_swp_pull_mem_back(struct qbman_swp *s, struct qbman_pull_desc *d)
11298c2ecf20Sopenharmony_ci{
11308c2ecf20Sopenharmony_ci	struct qbman_pull_desc *p;
11318c2ecf20Sopenharmony_ci
11328c2ecf20Sopenharmony_ci	if (!atomic_dec_and_test(&s->vdq.available)) {
11338c2ecf20Sopenharmony_ci		atomic_inc(&s->vdq.available);
11348c2ecf20Sopenharmony_ci		return -EBUSY;
11358c2ecf20Sopenharmony_ci	}
11368c2ecf20Sopenharmony_ci	s->vdq.storage = (void *)(uintptr_t)d->rsp_addr_virt;
11378c2ecf20Sopenharmony_ci	if ((s->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000)
11388c2ecf20Sopenharmony_ci		p = qbman_get_cmd(s, QBMAN_CENA_SWP_VDQCR);
11398c2ecf20Sopenharmony_ci	else
11408c2ecf20Sopenharmony_ci		p = qbman_get_cmd(s, QBMAN_CENA_SWP_VDQCR_MEM);
11418c2ecf20Sopenharmony_ci	p->numf = d->numf;
11428c2ecf20Sopenharmony_ci	p->tok = QMAN_DQ_TOKEN_VALID;
11438c2ecf20Sopenharmony_ci	p->dq_src = d->dq_src;
11448c2ecf20Sopenharmony_ci	p->rsp_addr = d->rsp_addr;
11458c2ecf20Sopenharmony_ci	p->rsp_addr_virt = d->rsp_addr_virt;
11468c2ecf20Sopenharmony_ci
11478c2ecf20Sopenharmony_ci	/* Set the verb byte, have to substitute in the valid-bit */
11488c2ecf20Sopenharmony_ci	p->verb = d->verb | s->vdq.valid_bit;
11498c2ecf20Sopenharmony_ci	s->vdq.valid_bit ^= QB_VALID_BIT;
11508c2ecf20Sopenharmony_ci	dma_wmb();
11518c2ecf20Sopenharmony_ci	qbman_write_register(s, QBMAN_CINH_SWP_VDQCR_RT, QMAN_RT_MODE);
11528c2ecf20Sopenharmony_ci
11538c2ecf20Sopenharmony_ci	return 0;
11548c2ecf20Sopenharmony_ci}
11558c2ecf20Sopenharmony_ci
11568c2ecf20Sopenharmony_ci#define QMAN_DQRR_PI_MASK   0xf
11578c2ecf20Sopenharmony_ci
11588c2ecf20Sopenharmony_ci/**
11598c2ecf20Sopenharmony_ci * qbman_swp_dqrr_next_direct() - Get an valid DQRR entry
11608c2ecf20Sopenharmony_ci * @s: the software portal object
11618c2ecf20Sopenharmony_ci *
11628c2ecf20Sopenharmony_ci * Return NULL if there are no unconsumed DQRR entries. Return a DQRR entry
11638c2ecf20Sopenharmony_ci * only once, so repeated calls can return a sequence of DQRR entries, without
11648c2ecf20Sopenharmony_ci * requiring they be consumed immediately or in any particular order.
11658c2ecf20Sopenharmony_ci */
11668c2ecf20Sopenharmony_ciconst struct dpaa2_dq *qbman_swp_dqrr_next_direct(struct qbman_swp *s)
11678c2ecf20Sopenharmony_ci{
11688c2ecf20Sopenharmony_ci	u32 verb;
11698c2ecf20Sopenharmony_ci	u32 response_verb;
11708c2ecf20Sopenharmony_ci	u32 flags;
11718c2ecf20Sopenharmony_ci	struct dpaa2_dq *p;
11728c2ecf20Sopenharmony_ci
11738c2ecf20Sopenharmony_ci	/* Before using valid-bit to detect if something is there, we have to
11748c2ecf20Sopenharmony_ci	 * handle the case of the DQRR reset bug...
11758c2ecf20Sopenharmony_ci	 */
11768c2ecf20Sopenharmony_ci	if (unlikely(s->dqrr.reset_bug)) {
11778c2ecf20Sopenharmony_ci		/*
11788c2ecf20Sopenharmony_ci		 * We pick up new entries by cache-inhibited producer index,
11798c2ecf20Sopenharmony_ci		 * which means that a non-coherent mapping would require us to
11808c2ecf20Sopenharmony_ci		 * invalidate and read *only* once that PI has indicated that
11818c2ecf20Sopenharmony_ci		 * there's an entry here. The first trip around the DQRR ring
11828c2ecf20Sopenharmony_ci		 * will be much less efficient than all subsequent trips around
11838c2ecf20Sopenharmony_ci		 * it...
11848c2ecf20Sopenharmony_ci		 */
11858c2ecf20Sopenharmony_ci		u8 pi = qbman_read_register(s, QBMAN_CINH_SWP_DQPI) &
11868c2ecf20Sopenharmony_ci			QMAN_DQRR_PI_MASK;
11878c2ecf20Sopenharmony_ci
11888c2ecf20Sopenharmony_ci		/* there are new entries if pi != next_idx */
11898c2ecf20Sopenharmony_ci		if (pi == s->dqrr.next_idx)
11908c2ecf20Sopenharmony_ci			return NULL;
11918c2ecf20Sopenharmony_ci
11928c2ecf20Sopenharmony_ci		/*
11938c2ecf20Sopenharmony_ci		 * if next_idx is/was the last ring index, and 'pi' is
11948c2ecf20Sopenharmony_ci		 * different, we can disable the workaround as all the ring
11958c2ecf20Sopenharmony_ci		 * entries have now been DMA'd to so valid-bit checking is
11968c2ecf20Sopenharmony_ci		 * repaired. Note: this logic needs to be based on next_idx
11978c2ecf20Sopenharmony_ci		 * (which increments one at a time), rather than on pi (which
11988c2ecf20Sopenharmony_ci		 * can burst and wrap-around between our snapshots of it).
11998c2ecf20Sopenharmony_ci		 */
12008c2ecf20Sopenharmony_ci		if (s->dqrr.next_idx == (s->dqrr.dqrr_size - 1)) {
12018c2ecf20Sopenharmony_ci			pr_debug("next_idx=%d, pi=%d, clear reset bug\n",
12028c2ecf20Sopenharmony_ci				 s->dqrr.next_idx, pi);
12038c2ecf20Sopenharmony_ci			s->dqrr.reset_bug = 0;
12048c2ecf20Sopenharmony_ci		}
12058c2ecf20Sopenharmony_ci		prefetch(qbman_get_cmd(s,
12068c2ecf20Sopenharmony_ci				       QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)));
12078c2ecf20Sopenharmony_ci	}
12088c2ecf20Sopenharmony_ci
12098c2ecf20Sopenharmony_ci	p = qbman_get_cmd(s, QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx));
12108c2ecf20Sopenharmony_ci	verb = p->dq.verb;
12118c2ecf20Sopenharmony_ci
12128c2ecf20Sopenharmony_ci	/*
12138c2ecf20Sopenharmony_ci	 * If the valid-bit isn't of the expected polarity, nothing there. Note,
12148c2ecf20Sopenharmony_ci	 * in the DQRR reset bug workaround, we shouldn't need to skip these
12158c2ecf20Sopenharmony_ci	 * check, because we've already determined that a new entry is available
12168c2ecf20Sopenharmony_ci	 * and we've invalidated the cacheline before reading it, so the
12178c2ecf20Sopenharmony_ci	 * valid-bit behaviour is repaired and should tell us what we already
12188c2ecf20Sopenharmony_ci	 * knew from reading PI.
12198c2ecf20Sopenharmony_ci	 */
12208c2ecf20Sopenharmony_ci	if ((verb & QB_VALID_BIT) != s->dqrr.valid_bit) {
12218c2ecf20Sopenharmony_ci		prefetch(qbman_get_cmd(s,
12228c2ecf20Sopenharmony_ci				       QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)));
12238c2ecf20Sopenharmony_ci		return NULL;
12248c2ecf20Sopenharmony_ci	}
12258c2ecf20Sopenharmony_ci	/*
12268c2ecf20Sopenharmony_ci	 * There's something there. Move "next_idx" attention to the next ring
12278c2ecf20Sopenharmony_ci	 * entry (and prefetch it) before returning what we found.
12288c2ecf20Sopenharmony_ci	 */
12298c2ecf20Sopenharmony_ci	s->dqrr.next_idx++;
12308c2ecf20Sopenharmony_ci	s->dqrr.next_idx &= s->dqrr.dqrr_size - 1; /* Wrap around */
12318c2ecf20Sopenharmony_ci	if (!s->dqrr.next_idx)
12328c2ecf20Sopenharmony_ci		s->dqrr.valid_bit ^= QB_VALID_BIT;
12338c2ecf20Sopenharmony_ci
12348c2ecf20Sopenharmony_ci	/*
12358c2ecf20Sopenharmony_ci	 * If this is the final response to a volatile dequeue command
12368c2ecf20Sopenharmony_ci	 * indicate that the vdq is available
12378c2ecf20Sopenharmony_ci	 */
12388c2ecf20Sopenharmony_ci	flags = p->dq.stat;
12398c2ecf20Sopenharmony_ci	response_verb = verb & QBMAN_RESULT_MASK;
12408c2ecf20Sopenharmony_ci	if ((response_verb == QBMAN_RESULT_DQ) &&
12418c2ecf20Sopenharmony_ci	    (flags & DPAA2_DQ_STAT_VOLATILE) &&
12428c2ecf20Sopenharmony_ci	    (flags & DPAA2_DQ_STAT_EXPIRED))
12438c2ecf20Sopenharmony_ci		atomic_inc(&s->vdq.available);
12448c2ecf20Sopenharmony_ci
12458c2ecf20Sopenharmony_ci	prefetch(qbman_get_cmd(s, QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)));
12468c2ecf20Sopenharmony_ci
12478c2ecf20Sopenharmony_ci	return p;
12488c2ecf20Sopenharmony_ci}
12498c2ecf20Sopenharmony_ci
12508c2ecf20Sopenharmony_ci/**
12518c2ecf20Sopenharmony_ci * qbman_swp_dqrr_next_mem_back() - Get an valid DQRR entry
12528c2ecf20Sopenharmony_ci * @s: the software portal object
12538c2ecf20Sopenharmony_ci *
12548c2ecf20Sopenharmony_ci * Return NULL if there are no unconsumed DQRR entries. Return a DQRR entry
12558c2ecf20Sopenharmony_ci * only once, so repeated calls can return a sequence of DQRR entries, without
12568c2ecf20Sopenharmony_ci * requiring they be consumed immediately or in any particular order.
12578c2ecf20Sopenharmony_ci */
12588c2ecf20Sopenharmony_ciconst struct dpaa2_dq *qbman_swp_dqrr_next_mem_back(struct qbman_swp *s)
12598c2ecf20Sopenharmony_ci{
12608c2ecf20Sopenharmony_ci	u32 verb;
12618c2ecf20Sopenharmony_ci	u32 response_verb;
12628c2ecf20Sopenharmony_ci	u32 flags;
12638c2ecf20Sopenharmony_ci	struct dpaa2_dq *p;
12648c2ecf20Sopenharmony_ci
12658c2ecf20Sopenharmony_ci	/* Before using valid-bit to detect if something is there, we have to
12668c2ecf20Sopenharmony_ci	 * handle the case of the DQRR reset bug...
12678c2ecf20Sopenharmony_ci	 */
12688c2ecf20Sopenharmony_ci	if (unlikely(s->dqrr.reset_bug)) {
12698c2ecf20Sopenharmony_ci		/*
12708c2ecf20Sopenharmony_ci		 * We pick up new entries by cache-inhibited producer index,
12718c2ecf20Sopenharmony_ci		 * which means that a non-coherent mapping would require us to
12728c2ecf20Sopenharmony_ci		 * invalidate and read *only* once that PI has indicated that
12738c2ecf20Sopenharmony_ci		 * there's an entry here. The first trip around the DQRR ring
12748c2ecf20Sopenharmony_ci		 * will be much less efficient than all subsequent trips around
12758c2ecf20Sopenharmony_ci		 * it...
12768c2ecf20Sopenharmony_ci		 */
12778c2ecf20Sopenharmony_ci		u8 pi = qbman_read_register(s, QBMAN_CINH_SWP_DQPI) &
12788c2ecf20Sopenharmony_ci			QMAN_DQRR_PI_MASK;
12798c2ecf20Sopenharmony_ci
12808c2ecf20Sopenharmony_ci		/* there are new entries if pi != next_idx */
12818c2ecf20Sopenharmony_ci		if (pi == s->dqrr.next_idx)
12828c2ecf20Sopenharmony_ci			return NULL;
12838c2ecf20Sopenharmony_ci
12848c2ecf20Sopenharmony_ci		/*
12858c2ecf20Sopenharmony_ci		 * if next_idx is/was the last ring index, and 'pi' is
12868c2ecf20Sopenharmony_ci		 * different, we can disable the workaround as all the ring
12878c2ecf20Sopenharmony_ci		 * entries have now been DMA'd to so valid-bit checking is
12888c2ecf20Sopenharmony_ci		 * repaired. Note: this logic needs to be based on next_idx
12898c2ecf20Sopenharmony_ci		 * (which increments one at a time), rather than on pi (which
12908c2ecf20Sopenharmony_ci		 * can burst and wrap-around between our snapshots of it).
12918c2ecf20Sopenharmony_ci		 */
12928c2ecf20Sopenharmony_ci		if (s->dqrr.next_idx == (s->dqrr.dqrr_size - 1)) {
12938c2ecf20Sopenharmony_ci			pr_debug("next_idx=%d, pi=%d, clear reset bug\n",
12948c2ecf20Sopenharmony_ci				 s->dqrr.next_idx, pi);
12958c2ecf20Sopenharmony_ci			s->dqrr.reset_bug = 0;
12968c2ecf20Sopenharmony_ci		}
12978c2ecf20Sopenharmony_ci		prefetch(qbman_get_cmd(s,
12988c2ecf20Sopenharmony_ci				       QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)));
12998c2ecf20Sopenharmony_ci	}
13008c2ecf20Sopenharmony_ci
13018c2ecf20Sopenharmony_ci	p = qbman_get_cmd(s, QBMAN_CENA_SWP_DQRR_MEM(s->dqrr.next_idx));
13028c2ecf20Sopenharmony_ci	verb = p->dq.verb;
13038c2ecf20Sopenharmony_ci
13048c2ecf20Sopenharmony_ci	/*
13058c2ecf20Sopenharmony_ci	 * If the valid-bit isn't of the expected polarity, nothing there. Note,
13068c2ecf20Sopenharmony_ci	 * in the DQRR reset bug workaround, we shouldn't need to skip these
13078c2ecf20Sopenharmony_ci	 * check, because we've already determined that a new entry is available
13088c2ecf20Sopenharmony_ci	 * and we've invalidated the cacheline before reading it, so the
13098c2ecf20Sopenharmony_ci	 * valid-bit behaviour is repaired and should tell us what we already
13108c2ecf20Sopenharmony_ci	 * knew from reading PI.
13118c2ecf20Sopenharmony_ci	 */
13128c2ecf20Sopenharmony_ci	if ((verb & QB_VALID_BIT) != s->dqrr.valid_bit) {
13138c2ecf20Sopenharmony_ci		prefetch(qbman_get_cmd(s,
13148c2ecf20Sopenharmony_ci				       QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)));
13158c2ecf20Sopenharmony_ci		return NULL;
13168c2ecf20Sopenharmony_ci	}
13178c2ecf20Sopenharmony_ci	/*
13188c2ecf20Sopenharmony_ci	 * There's something there. Move "next_idx" attention to the next ring
13198c2ecf20Sopenharmony_ci	 * entry (and prefetch it) before returning what we found.
13208c2ecf20Sopenharmony_ci	 */
13218c2ecf20Sopenharmony_ci	s->dqrr.next_idx++;
13228c2ecf20Sopenharmony_ci	s->dqrr.next_idx &= s->dqrr.dqrr_size - 1; /* Wrap around */
13238c2ecf20Sopenharmony_ci	if (!s->dqrr.next_idx)
13248c2ecf20Sopenharmony_ci		s->dqrr.valid_bit ^= QB_VALID_BIT;
13258c2ecf20Sopenharmony_ci
13268c2ecf20Sopenharmony_ci	/*
13278c2ecf20Sopenharmony_ci	 * If this is the final response to a volatile dequeue command
13288c2ecf20Sopenharmony_ci	 * indicate that the vdq is available
13298c2ecf20Sopenharmony_ci	 */
13308c2ecf20Sopenharmony_ci	flags = p->dq.stat;
13318c2ecf20Sopenharmony_ci	response_verb = verb & QBMAN_RESULT_MASK;
13328c2ecf20Sopenharmony_ci	if ((response_verb == QBMAN_RESULT_DQ) &&
13338c2ecf20Sopenharmony_ci	    (flags & DPAA2_DQ_STAT_VOLATILE) &&
13348c2ecf20Sopenharmony_ci	    (flags & DPAA2_DQ_STAT_EXPIRED))
13358c2ecf20Sopenharmony_ci		atomic_inc(&s->vdq.available);
13368c2ecf20Sopenharmony_ci
13378c2ecf20Sopenharmony_ci	prefetch(qbman_get_cmd(s, QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)));
13388c2ecf20Sopenharmony_ci
13398c2ecf20Sopenharmony_ci	return p;
13408c2ecf20Sopenharmony_ci}
13418c2ecf20Sopenharmony_ci
13428c2ecf20Sopenharmony_ci/**
13438c2ecf20Sopenharmony_ci * qbman_swp_dqrr_consume() -  Consume DQRR entries previously returned from
13448c2ecf20Sopenharmony_ci *                             qbman_swp_dqrr_next().
13458c2ecf20Sopenharmony_ci * @s: the software portal object
13468c2ecf20Sopenharmony_ci * @dq: the DQRR entry to be consumed
13478c2ecf20Sopenharmony_ci */
13488c2ecf20Sopenharmony_civoid qbman_swp_dqrr_consume(struct qbman_swp *s, const struct dpaa2_dq *dq)
13498c2ecf20Sopenharmony_ci{
13508c2ecf20Sopenharmony_ci	qbman_write_register(s, QBMAN_CINH_SWP_DCAP, QBMAN_IDX_FROM_DQRR(dq));
13518c2ecf20Sopenharmony_ci}
13528c2ecf20Sopenharmony_ci
13538c2ecf20Sopenharmony_ci/**
13548c2ecf20Sopenharmony_ci * qbman_result_has_new_result() - Check and get the dequeue response from the
13558c2ecf20Sopenharmony_ci *                                 dq storage memory set in pull dequeue command
13568c2ecf20Sopenharmony_ci * @s: the software portal object
13578c2ecf20Sopenharmony_ci * @dq: the dequeue result read from the memory
13588c2ecf20Sopenharmony_ci *
13598c2ecf20Sopenharmony_ci * Return 1 for getting a valid dequeue result, or 0 for not getting a valid
13608c2ecf20Sopenharmony_ci * dequeue result.
13618c2ecf20Sopenharmony_ci *
13628c2ecf20Sopenharmony_ci * Only used for user-provided storage of dequeue results, not DQRR. For
13638c2ecf20Sopenharmony_ci * efficiency purposes, the driver will perform any required endianness
13648c2ecf20Sopenharmony_ci * conversion to ensure that the user's dequeue result storage is in host-endian
13658c2ecf20Sopenharmony_ci * format. As such, once the user has called qbman_result_has_new_result() and
13668c2ecf20Sopenharmony_ci * been returned a valid dequeue result, they should not call it again on
13678c2ecf20Sopenharmony_ci * the same memory location (except of course if another dequeue command has
13688c2ecf20Sopenharmony_ci * been executed to produce a new result to that location).
13698c2ecf20Sopenharmony_ci */
13708c2ecf20Sopenharmony_ciint qbman_result_has_new_result(struct qbman_swp *s, const struct dpaa2_dq *dq)
13718c2ecf20Sopenharmony_ci{
13728c2ecf20Sopenharmony_ci	if (dq->dq.tok != QMAN_DQ_TOKEN_VALID)
13738c2ecf20Sopenharmony_ci		return 0;
13748c2ecf20Sopenharmony_ci
13758c2ecf20Sopenharmony_ci	/*
13768c2ecf20Sopenharmony_ci	 * Set token to be 0 so we will detect change back to 1
13778c2ecf20Sopenharmony_ci	 * next time the looping is traversed. Const is cast away here
13788c2ecf20Sopenharmony_ci	 * as we want users to treat the dequeue responses as read only.
13798c2ecf20Sopenharmony_ci	 */
13808c2ecf20Sopenharmony_ci	((struct dpaa2_dq *)dq)->dq.tok = 0;
13818c2ecf20Sopenharmony_ci
13828c2ecf20Sopenharmony_ci	/*
13838c2ecf20Sopenharmony_ci	 * Determine whether VDQCR is available based on whether the
13848c2ecf20Sopenharmony_ci	 * current result is sitting in the first storage location of
13858c2ecf20Sopenharmony_ci	 * the busy command.
13868c2ecf20Sopenharmony_ci	 */
13878c2ecf20Sopenharmony_ci	if (s->vdq.storage == dq) {
13888c2ecf20Sopenharmony_ci		s->vdq.storage = NULL;
13898c2ecf20Sopenharmony_ci		atomic_inc(&s->vdq.available);
13908c2ecf20Sopenharmony_ci	}
13918c2ecf20Sopenharmony_ci
13928c2ecf20Sopenharmony_ci	return 1;
13938c2ecf20Sopenharmony_ci}
13948c2ecf20Sopenharmony_ci
13958c2ecf20Sopenharmony_ci/**
13968c2ecf20Sopenharmony_ci * qbman_release_desc_clear() - Clear the contents of a descriptor to
13978c2ecf20Sopenharmony_ci *                              default/starting state.
13988c2ecf20Sopenharmony_ci */
13998c2ecf20Sopenharmony_civoid qbman_release_desc_clear(struct qbman_release_desc *d)
14008c2ecf20Sopenharmony_ci{
14018c2ecf20Sopenharmony_ci	memset(d, 0, sizeof(*d));
14028c2ecf20Sopenharmony_ci	d->verb = 1 << 5; /* Release Command Valid */
14038c2ecf20Sopenharmony_ci}
14048c2ecf20Sopenharmony_ci
14058c2ecf20Sopenharmony_ci/**
14068c2ecf20Sopenharmony_ci * qbman_release_desc_set_bpid() - Set the ID of the buffer pool to release to
14078c2ecf20Sopenharmony_ci */
14088c2ecf20Sopenharmony_civoid qbman_release_desc_set_bpid(struct qbman_release_desc *d, u16 bpid)
14098c2ecf20Sopenharmony_ci{
14108c2ecf20Sopenharmony_ci	d->bpid = cpu_to_le16(bpid);
14118c2ecf20Sopenharmony_ci}
14128c2ecf20Sopenharmony_ci
14138c2ecf20Sopenharmony_ci/**
14148c2ecf20Sopenharmony_ci * qbman_release_desc_set_rcdi() - Determines whether or not the portal's RCDI
14158c2ecf20Sopenharmony_ci * interrupt source should be asserted after the release command is completed.
14168c2ecf20Sopenharmony_ci */
14178c2ecf20Sopenharmony_civoid qbman_release_desc_set_rcdi(struct qbman_release_desc *d, int enable)
14188c2ecf20Sopenharmony_ci{
14198c2ecf20Sopenharmony_ci	if (enable)
14208c2ecf20Sopenharmony_ci		d->verb |= 1 << 6;
14218c2ecf20Sopenharmony_ci	else
14228c2ecf20Sopenharmony_ci		d->verb &= ~(1 << 6);
14238c2ecf20Sopenharmony_ci}
14248c2ecf20Sopenharmony_ci
14258c2ecf20Sopenharmony_ci#define RAR_IDX(rar)     ((rar) & 0x7)
14268c2ecf20Sopenharmony_ci#define RAR_VB(rar)      ((rar) & 0x80)
14278c2ecf20Sopenharmony_ci#define RAR_SUCCESS(rar) ((rar) & 0x100)
14288c2ecf20Sopenharmony_ci
14298c2ecf20Sopenharmony_ci/**
14308c2ecf20Sopenharmony_ci * qbman_swp_release_direct() - Issue a buffer release command
14318c2ecf20Sopenharmony_ci * @s:           the software portal object
14328c2ecf20Sopenharmony_ci * @d:           the release descriptor
14338c2ecf20Sopenharmony_ci * @buffers:     a pointer pointing to the buffer address to be released
14348c2ecf20Sopenharmony_ci * @num_buffers: number of buffers to be released,  must be less than 8
14358c2ecf20Sopenharmony_ci *
14368c2ecf20Sopenharmony_ci * Return 0 for success, -EBUSY if the release command ring is not ready.
14378c2ecf20Sopenharmony_ci */
14388c2ecf20Sopenharmony_ciint qbman_swp_release_direct(struct qbman_swp *s,
14398c2ecf20Sopenharmony_ci			     const struct qbman_release_desc *d,
14408c2ecf20Sopenharmony_ci			     const u64 *buffers, unsigned int num_buffers)
14418c2ecf20Sopenharmony_ci{
14428c2ecf20Sopenharmony_ci	int i;
14438c2ecf20Sopenharmony_ci	struct qbman_release_desc *p;
14448c2ecf20Sopenharmony_ci	u32 rar;
14458c2ecf20Sopenharmony_ci
14468c2ecf20Sopenharmony_ci	if (!num_buffers || (num_buffers > 7))
14478c2ecf20Sopenharmony_ci		return -EINVAL;
14488c2ecf20Sopenharmony_ci
14498c2ecf20Sopenharmony_ci	rar = qbman_read_register(s, QBMAN_CINH_SWP_RAR);
14508c2ecf20Sopenharmony_ci	if (!RAR_SUCCESS(rar))
14518c2ecf20Sopenharmony_ci		return -EBUSY;
14528c2ecf20Sopenharmony_ci
14538c2ecf20Sopenharmony_ci	/* Start the release command */
14548c2ecf20Sopenharmony_ci	p = qbman_get_cmd(s, QBMAN_CENA_SWP_RCR(RAR_IDX(rar)));
14558c2ecf20Sopenharmony_ci
14568c2ecf20Sopenharmony_ci	/* Copy the caller's buffer pointers to the command */
14578c2ecf20Sopenharmony_ci	for (i = 0; i < num_buffers; i++)
14588c2ecf20Sopenharmony_ci		p->buf[i] = cpu_to_le64(buffers[i]);
14598c2ecf20Sopenharmony_ci	p->bpid = d->bpid;
14608c2ecf20Sopenharmony_ci
14618c2ecf20Sopenharmony_ci	/*
14628c2ecf20Sopenharmony_ci	 * Set the verb byte, have to substitute in the valid-bit
14638c2ecf20Sopenharmony_ci	 * and the number of buffers.
14648c2ecf20Sopenharmony_ci	 */
14658c2ecf20Sopenharmony_ci	dma_wmb();
14668c2ecf20Sopenharmony_ci	p->verb = d->verb | RAR_VB(rar) | num_buffers;
14678c2ecf20Sopenharmony_ci
14688c2ecf20Sopenharmony_ci	return 0;
14698c2ecf20Sopenharmony_ci}
14708c2ecf20Sopenharmony_ci
14718c2ecf20Sopenharmony_ci/**
14728c2ecf20Sopenharmony_ci * qbman_swp_release_mem_back() - Issue a buffer release command
14738c2ecf20Sopenharmony_ci * @s:           the software portal object
14748c2ecf20Sopenharmony_ci * @d:           the release descriptor
14758c2ecf20Sopenharmony_ci * @buffers:     a pointer pointing to the buffer address to be released
14768c2ecf20Sopenharmony_ci * @num_buffers: number of buffers to be released,  must be less than 8
14778c2ecf20Sopenharmony_ci *
14788c2ecf20Sopenharmony_ci * Return 0 for success, -EBUSY if the release command ring is not ready.
14798c2ecf20Sopenharmony_ci */
14808c2ecf20Sopenharmony_ciint qbman_swp_release_mem_back(struct qbman_swp *s,
14818c2ecf20Sopenharmony_ci			       const struct qbman_release_desc *d,
14828c2ecf20Sopenharmony_ci			       const u64 *buffers, unsigned int num_buffers)
14838c2ecf20Sopenharmony_ci{
14848c2ecf20Sopenharmony_ci	int i;
14858c2ecf20Sopenharmony_ci	struct qbman_release_desc *p;
14868c2ecf20Sopenharmony_ci	u32 rar;
14878c2ecf20Sopenharmony_ci
14888c2ecf20Sopenharmony_ci	if (!num_buffers || (num_buffers > 7))
14898c2ecf20Sopenharmony_ci		return -EINVAL;
14908c2ecf20Sopenharmony_ci
14918c2ecf20Sopenharmony_ci	rar = qbman_read_register(s, QBMAN_CINH_SWP_RAR);
14928c2ecf20Sopenharmony_ci	if (!RAR_SUCCESS(rar))
14938c2ecf20Sopenharmony_ci		return -EBUSY;
14948c2ecf20Sopenharmony_ci
14958c2ecf20Sopenharmony_ci	/* Start the release command */
14968c2ecf20Sopenharmony_ci	p = qbman_get_cmd(s, QBMAN_CENA_SWP_RCR_MEM(RAR_IDX(rar)));
14978c2ecf20Sopenharmony_ci
14988c2ecf20Sopenharmony_ci	/* Copy the caller's buffer pointers to the command */
14998c2ecf20Sopenharmony_ci	for (i = 0; i < num_buffers; i++)
15008c2ecf20Sopenharmony_ci		p->buf[i] = cpu_to_le64(buffers[i]);
15018c2ecf20Sopenharmony_ci	p->bpid = d->bpid;
15028c2ecf20Sopenharmony_ci
15038c2ecf20Sopenharmony_ci	p->verb = d->verb | RAR_VB(rar) | num_buffers;
15048c2ecf20Sopenharmony_ci	dma_wmb();
15058c2ecf20Sopenharmony_ci	qbman_write_register(s, QBMAN_CINH_SWP_RCR_AM_RT +
15068c2ecf20Sopenharmony_ci			     RAR_IDX(rar)  * 4, QMAN_RT_MODE);
15078c2ecf20Sopenharmony_ci
15088c2ecf20Sopenharmony_ci	return 0;
15098c2ecf20Sopenharmony_ci}
15108c2ecf20Sopenharmony_ci
15118c2ecf20Sopenharmony_cistruct qbman_acquire_desc {
15128c2ecf20Sopenharmony_ci	u8 verb;
15138c2ecf20Sopenharmony_ci	u8 reserved;
15148c2ecf20Sopenharmony_ci	__le16 bpid;
15158c2ecf20Sopenharmony_ci	u8 num;
15168c2ecf20Sopenharmony_ci	u8 reserved2[59];
15178c2ecf20Sopenharmony_ci};
15188c2ecf20Sopenharmony_ci
15198c2ecf20Sopenharmony_cistruct qbman_acquire_rslt {
15208c2ecf20Sopenharmony_ci	u8 verb;
15218c2ecf20Sopenharmony_ci	u8 rslt;
15228c2ecf20Sopenharmony_ci	__le16 reserved;
15238c2ecf20Sopenharmony_ci	u8 num;
15248c2ecf20Sopenharmony_ci	u8 reserved2[3];
15258c2ecf20Sopenharmony_ci	__le64 buf[7];
15268c2ecf20Sopenharmony_ci};
15278c2ecf20Sopenharmony_ci
15288c2ecf20Sopenharmony_ci/**
15298c2ecf20Sopenharmony_ci * qbman_swp_acquire() - Issue a buffer acquire command
15308c2ecf20Sopenharmony_ci * @s:           the software portal object
15318c2ecf20Sopenharmony_ci * @bpid:        the buffer pool index
15328c2ecf20Sopenharmony_ci * @buffers:     a pointer pointing to the acquired buffer addresses
15338c2ecf20Sopenharmony_ci * @num_buffers: number of buffers to be acquired, must be less than 8
15348c2ecf20Sopenharmony_ci *
15358c2ecf20Sopenharmony_ci * Return 0 for success, or negative error code if the acquire command
15368c2ecf20Sopenharmony_ci * fails.
15378c2ecf20Sopenharmony_ci */
15388c2ecf20Sopenharmony_ciint qbman_swp_acquire(struct qbman_swp *s, u16 bpid, u64 *buffers,
15398c2ecf20Sopenharmony_ci		      unsigned int num_buffers)
15408c2ecf20Sopenharmony_ci{
15418c2ecf20Sopenharmony_ci	struct qbman_acquire_desc *p;
15428c2ecf20Sopenharmony_ci	struct qbman_acquire_rslt *r;
15438c2ecf20Sopenharmony_ci	int i;
15448c2ecf20Sopenharmony_ci
15458c2ecf20Sopenharmony_ci	if (!num_buffers || (num_buffers > 7))
15468c2ecf20Sopenharmony_ci		return -EINVAL;
15478c2ecf20Sopenharmony_ci
15488c2ecf20Sopenharmony_ci	/* Start the management command */
15498c2ecf20Sopenharmony_ci	p = qbman_swp_mc_start(s);
15508c2ecf20Sopenharmony_ci
15518c2ecf20Sopenharmony_ci	if (!p)
15528c2ecf20Sopenharmony_ci		return -EBUSY;
15538c2ecf20Sopenharmony_ci
15548c2ecf20Sopenharmony_ci	/* Encode the caller-provided attributes */
15558c2ecf20Sopenharmony_ci	p->bpid = cpu_to_le16(bpid);
15568c2ecf20Sopenharmony_ci	p->num = num_buffers;
15578c2ecf20Sopenharmony_ci
15588c2ecf20Sopenharmony_ci	/* Complete the management command */
15598c2ecf20Sopenharmony_ci	r = qbman_swp_mc_complete(s, p, QBMAN_MC_ACQUIRE);
15608c2ecf20Sopenharmony_ci	if (unlikely(!r)) {
15618c2ecf20Sopenharmony_ci		pr_err("qbman: acquire from BPID %d failed, no response\n",
15628c2ecf20Sopenharmony_ci		       bpid);
15638c2ecf20Sopenharmony_ci		return -EIO;
15648c2ecf20Sopenharmony_ci	}
15658c2ecf20Sopenharmony_ci
15668c2ecf20Sopenharmony_ci	/* Decode the outcome */
15678c2ecf20Sopenharmony_ci	WARN_ON((r->verb & 0x7f) != QBMAN_MC_ACQUIRE);
15688c2ecf20Sopenharmony_ci
15698c2ecf20Sopenharmony_ci	/* Determine success or failure */
15708c2ecf20Sopenharmony_ci	if (unlikely(r->rslt != QBMAN_MC_RSLT_OK)) {
15718c2ecf20Sopenharmony_ci		pr_err("qbman: acquire from BPID 0x%x failed, code=0x%02x\n",
15728c2ecf20Sopenharmony_ci		       bpid, r->rslt);
15738c2ecf20Sopenharmony_ci		return -EIO;
15748c2ecf20Sopenharmony_ci	}
15758c2ecf20Sopenharmony_ci
15768c2ecf20Sopenharmony_ci	WARN_ON(r->num > num_buffers);
15778c2ecf20Sopenharmony_ci
15788c2ecf20Sopenharmony_ci	/* Copy the acquired buffers to the caller's array */
15798c2ecf20Sopenharmony_ci	for (i = 0; i < r->num; i++)
15808c2ecf20Sopenharmony_ci		buffers[i] = le64_to_cpu(r->buf[i]);
15818c2ecf20Sopenharmony_ci
15828c2ecf20Sopenharmony_ci	return (int)r->num;
15838c2ecf20Sopenharmony_ci}
15848c2ecf20Sopenharmony_ci
15858c2ecf20Sopenharmony_cistruct qbman_alt_fq_state_desc {
15868c2ecf20Sopenharmony_ci	u8 verb;
15878c2ecf20Sopenharmony_ci	u8 reserved[3];
15888c2ecf20Sopenharmony_ci	__le32 fqid;
15898c2ecf20Sopenharmony_ci	u8 reserved2[56];
15908c2ecf20Sopenharmony_ci};
15918c2ecf20Sopenharmony_ci
15928c2ecf20Sopenharmony_cistruct qbman_alt_fq_state_rslt {
15938c2ecf20Sopenharmony_ci	u8 verb;
15948c2ecf20Sopenharmony_ci	u8 rslt;
15958c2ecf20Sopenharmony_ci	u8 reserved[62];
15968c2ecf20Sopenharmony_ci};
15978c2ecf20Sopenharmony_ci
15988c2ecf20Sopenharmony_ci#define ALT_FQ_FQID_MASK 0x00FFFFFF
15998c2ecf20Sopenharmony_ci
16008c2ecf20Sopenharmony_ciint qbman_swp_alt_fq_state(struct qbman_swp *s, u32 fqid,
16018c2ecf20Sopenharmony_ci			   u8 alt_fq_verb)
16028c2ecf20Sopenharmony_ci{
16038c2ecf20Sopenharmony_ci	struct qbman_alt_fq_state_desc *p;
16048c2ecf20Sopenharmony_ci	struct qbman_alt_fq_state_rslt *r;
16058c2ecf20Sopenharmony_ci
16068c2ecf20Sopenharmony_ci	/* Start the management command */
16078c2ecf20Sopenharmony_ci	p = qbman_swp_mc_start(s);
16088c2ecf20Sopenharmony_ci	if (!p)
16098c2ecf20Sopenharmony_ci		return -EBUSY;
16108c2ecf20Sopenharmony_ci
16118c2ecf20Sopenharmony_ci	p->fqid = cpu_to_le32(fqid & ALT_FQ_FQID_MASK);
16128c2ecf20Sopenharmony_ci
16138c2ecf20Sopenharmony_ci	/* Complete the management command */
16148c2ecf20Sopenharmony_ci	r = qbman_swp_mc_complete(s, p, alt_fq_verb);
16158c2ecf20Sopenharmony_ci	if (unlikely(!r)) {
16168c2ecf20Sopenharmony_ci		pr_err("qbman: mgmt cmd failed, no response (verb=0x%x)\n",
16178c2ecf20Sopenharmony_ci		       alt_fq_verb);
16188c2ecf20Sopenharmony_ci		return -EIO;
16198c2ecf20Sopenharmony_ci	}
16208c2ecf20Sopenharmony_ci
16218c2ecf20Sopenharmony_ci	/* Decode the outcome */
16228c2ecf20Sopenharmony_ci	WARN_ON((r->verb & QBMAN_RESULT_MASK) != alt_fq_verb);
16238c2ecf20Sopenharmony_ci
16248c2ecf20Sopenharmony_ci	/* Determine success or failure */
16258c2ecf20Sopenharmony_ci	if (unlikely(r->rslt != QBMAN_MC_RSLT_OK)) {
16268c2ecf20Sopenharmony_ci		pr_err("qbman: ALT FQID %d failed: verb = 0x%08x code = 0x%02x\n",
16278c2ecf20Sopenharmony_ci		       fqid, r->verb, r->rslt);
16288c2ecf20Sopenharmony_ci		return -EIO;
16298c2ecf20Sopenharmony_ci	}
16308c2ecf20Sopenharmony_ci
16318c2ecf20Sopenharmony_ci	return 0;
16328c2ecf20Sopenharmony_ci}
16338c2ecf20Sopenharmony_ci
16348c2ecf20Sopenharmony_cistruct qbman_cdan_ctrl_desc {
16358c2ecf20Sopenharmony_ci	u8 verb;
16368c2ecf20Sopenharmony_ci	u8 reserved;
16378c2ecf20Sopenharmony_ci	__le16 ch;
16388c2ecf20Sopenharmony_ci	u8 we;
16398c2ecf20Sopenharmony_ci	u8 ctrl;
16408c2ecf20Sopenharmony_ci	__le16 reserved2;
16418c2ecf20Sopenharmony_ci	__le64 cdan_ctx;
16428c2ecf20Sopenharmony_ci	u8 reserved3[48];
16438c2ecf20Sopenharmony_ci
16448c2ecf20Sopenharmony_ci};
16458c2ecf20Sopenharmony_ci
16468c2ecf20Sopenharmony_cistruct qbman_cdan_ctrl_rslt {
16478c2ecf20Sopenharmony_ci	u8 verb;
16488c2ecf20Sopenharmony_ci	u8 rslt;
16498c2ecf20Sopenharmony_ci	__le16 ch;
16508c2ecf20Sopenharmony_ci	u8 reserved[60];
16518c2ecf20Sopenharmony_ci};
16528c2ecf20Sopenharmony_ci
16538c2ecf20Sopenharmony_ciint qbman_swp_CDAN_set(struct qbman_swp *s, u16 channelid,
16548c2ecf20Sopenharmony_ci		       u8 we_mask, u8 cdan_en,
16558c2ecf20Sopenharmony_ci		       u64 ctx)
16568c2ecf20Sopenharmony_ci{
16578c2ecf20Sopenharmony_ci	struct qbman_cdan_ctrl_desc *p = NULL;
16588c2ecf20Sopenharmony_ci	struct qbman_cdan_ctrl_rslt *r = NULL;
16598c2ecf20Sopenharmony_ci
16608c2ecf20Sopenharmony_ci	/* Start the management command */
16618c2ecf20Sopenharmony_ci	p = qbman_swp_mc_start(s);
16628c2ecf20Sopenharmony_ci	if (!p)
16638c2ecf20Sopenharmony_ci		return -EBUSY;
16648c2ecf20Sopenharmony_ci
16658c2ecf20Sopenharmony_ci	/* Encode the caller-provided attributes */
16668c2ecf20Sopenharmony_ci	p->ch = cpu_to_le16(channelid);
16678c2ecf20Sopenharmony_ci	p->we = we_mask;
16688c2ecf20Sopenharmony_ci	if (cdan_en)
16698c2ecf20Sopenharmony_ci		p->ctrl = 1;
16708c2ecf20Sopenharmony_ci	else
16718c2ecf20Sopenharmony_ci		p->ctrl = 0;
16728c2ecf20Sopenharmony_ci	p->cdan_ctx = cpu_to_le64(ctx);
16738c2ecf20Sopenharmony_ci
16748c2ecf20Sopenharmony_ci	/* Complete the management command */
16758c2ecf20Sopenharmony_ci	r = qbman_swp_mc_complete(s, p, QBMAN_WQCHAN_CONFIGURE);
16768c2ecf20Sopenharmony_ci	if (unlikely(!r)) {
16778c2ecf20Sopenharmony_ci		pr_err("qbman: wqchan config failed, no response\n");
16788c2ecf20Sopenharmony_ci		return -EIO;
16798c2ecf20Sopenharmony_ci	}
16808c2ecf20Sopenharmony_ci
16818c2ecf20Sopenharmony_ci	WARN_ON((r->verb & 0x7f) != QBMAN_WQCHAN_CONFIGURE);
16828c2ecf20Sopenharmony_ci
16838c2ecf20Sopenharmony_ci	/* Determine success or failure */
16848c2ecf20Sopenharmony_ci	if (unlikely(r->rslt != QBMAN_MC_RSLT_OK)) {
16858c2ecf20Sopenharmony_ci		pr_err("qbman: CDAN cQID %d failed: code = 0x%02x\n",
16868c2ecf20Sopenharmony_ci		       channelid, r->rslt);
16878c2ecf20Sopenharmony_ci		return -EIO;
16888c2ecf20Sopenharmony_ci	}
16898c2ecf20Sopenharmony_ci
16908c2ecf20Sopenharmony_ci	return 0;
16918c2ecf20Sopenharmony_ci}
16928c2ecf20Sopenharmony_ci
16938c2ecf20Sopenharmony_ci#define QBMAN_RESPONSE_VERB_MASK	0x7f
16948c2ecf20Sopenharmony_ci#define QBMAN_FQ_QUERY_NP		0x45
16958c2ecf20Sopenharmony_ci#define QBMAN_BP_QUERY			0x32
16968c2ecf20Sopenharmony_ci
16978c2ecf20Sopenharmony_cistruct qbman_fq_query_desc {
16988c2ecf20Sopenharmony_ci	u8 verb;
16998c2ecf20Sopenharmony_ci	u8 reserved[3];
17008c2ecf20Sopenharmony_ci	__le32 fqid;
17018c2ecf20Sopenharmony_ci	u8 reserved2[56];
17028c2ecf20Sopenharmony_ci};
17038c2ecf20Sopenharmony_ci
17048c2ecf20Sopenharmony_ciint qbman_fq_query_state(struct qbman_swp *s, u32 fqid,
17058c2ecf20Sopenharmony_ci			 struct qbman_fq_query_np_rslt *r)
17068c2ecf20Sopenharmony_ci{
17078c2ecf20Sopenharmony_ci	struct qbman_fq_query_desc *p;
17088c2ecf20Sopenharmony_ci	void *resp;
17098c2ecf20Sopenharmony_ci
17108c2ecf20Sopenharmony_ci	p = (struct qbman_fq_query_desc *)qbman_swp_mc_start(s);
17118c2ecf20Sopenharmony_ci	if (!p)
17128c2ecf20Sopenharmony_ci		return -EBUSY;
17138c2ecf20Sopenharmony_ci
17148c2ecf20Sopenharmony_ci	/* FQID is a 24 bit value */
17158c2ecf20Sopenharmony_ci	p->fqid = cpu_to_le32(fqid & 0x00FFFFFF);
17168c2ecf20Sopenharmony_ci	resp = qbman_swp_mc_complete(s, p, QBMAN_FQ_QUERY_NP);
17178c2ecf20Sopenharmony_ci	if (!resp) {
17188c2ecf20Sopenharmony_ci		pr_err("qbman: Query FQID %d NP fields failed, no response\n",
17198c2ecf20Sopenharmony_ci		       fqid);
17208c2ecf20Sopenharmony_ci		return -EIO;
17218c2ecf20Sopenharmony_ci	}
17228c2ecf20Sopenharmony_ci	*r = *(struct qbman_fq_query_np_rslt *)resp;
17238c2ecf20Sopenharmony_ci	/* Decode the outcome */
17248c2ecf20Sopenharmony_ci	WARN_ON((r->verb & QBMAN_RESPONSE_VERB_MASK) != QBMAN_FQ_QUERY_NP);
17258c2ecf20Sopenharmony_ci
17268c2ecf20Sopenharmony_ci	/* Determine success or failure */
17278c2ecf20Sopenharmony_ci	if (r->rslt != QBMAN_MC_RSLT_OK) {
17288c2ecf20Sopenharmony_ci		pr_err("Query NP fields of FQID 0x%x failed, code=0x%02x\n",
17298c2ecf20Sopenharmony_ci		       p->fqid, r->rslt);
17308c2ecf20Sopenharmony_ci		return -EIO;
17318c2ecf20Sopenharmony_ci	}
17328c2ecf20Sopenharmony_ci
17338c2ecf20Sopenharmony_ci	return 0;
17348c2ecf20Sopenharmony_ci}
17358c2ecf20Sopenharmony_ci
17368c2ecf20Sopenharmony_ciu32 qbman_fq_state_frame_count(const struct qbman_fq_query_np_rslt *r)
17378c2ecf20Sopenharmony_ci{
17388c2ecf20Sopenharmony_ci	return (le32_to_cpu(r->frm_cnt) & 0x00FFFFFF);
17398c2ecf20Sopenharmony_ci}
17408c2ecf20Sopenharmony_ci
17418c2ecf20Sopenharmony_ciu32 qbman_fq_state_byte_count(const struct qbman_fq_query_np_rslt *r)
17428c2ecf20Sopenharmony_ci{
17438c2ecf20Sopenharmony_ci	return le32_to_cpu(r->byte_cnt);
17448c2ecf20Sopenharmony_ci}
17458c2ecf20Sopenharmony_ci
17468c2ecf20Sopenharmony_cistruct qbman_bp_query_desc {
17478c2ecf20Sopenharmony_ci	u8 verb;
17488c2ecf20Sopenharmony_ci	u8 reserved;
17498c2ecf20Sopenharmony_ci	__le16 bpid;
17508c2ecf20Sopenharmony_ci	u8 reserved2[60];
17518c2ecf20Sopenharmony_ci};
17528c2ecf20Sopenharmony_ci
17538c2ecf20Sopenharmony_ciint qbman_bp_query(struct qbman_swp *s, u16 bpid,
17548c2ecf20Sopenharmony_ci		   struct qbman_bp_query_rslt *r)
17558c2ecf20Sopenharmony_ci{
17568c2ecf20Sopenharmony_ci	struct qbman_bp_query_desc *p;
17578c2ecf20Sopenharmony_ci	void *resp;
17588c2ecf20Sopenharmony_ci
17598c2ecf20Sopenharmony_ci	p = (struct qbman_bp_query_desc *)qbman_swp_mc_start(s);
17608c2ecf20Sopenharmony_ci	if (!p)
17618c2ecf20Sopenharmony_ci		return -EBUSY;
17628c2ecf20Sopenharmony_ci
17638c2ecf20Sopenharmony_ci	p->bpid = cpu_to_le16(bpid);
17648c2ecf20Sopenharmony_ci	resp = qbman_swp_mc_complete(s, p, QBMAN_BP_QUERY);
17658c2ecf20Sopenharmony_ci	if (!resp) {
17668c2ecf20Sopenharmony_ci		pr_err("qbman: Query BPID %d fields failed, no response\n",
17678c2ecf20Sopenharmony_ci		       bpid);
17688c2ecf20Sopenharmony_ci		return -EIO;
17698c2ecf20Sopenharmony_ci	}
17708c2ecf20Sopenharmony_ci	*r = *(struct qbman_bp_query_rslt *)resp;
17718c2ecf20Sopenharmony_ci	/* Decode the outcome */
17728c2ecf20Sopenharmony_ci	WARN_ON((r->verb & QBMAN_RESPONSE_VERB_MASK) != QBMAN_BP_QUERY);
17738c2ecf20Sopenharmony_ci
17748c2ecf20Sopenharmony_ci	/* Determine success or failure */
17758c2ecf20Sopenharmony_ci	if (r->rslt != QBMAN_MC_RSLT_OK) {
17768c2ecf20Sopenharmony_ci		pr_err("Query fields of BPID 0x%x failed, code=0x%02x\n",
17778c2ecf20Sopenharmony_ci		       bpid, r->rslt);
17788c2ecf20Sopenharmony_ci		return -EIO;
17798c2ecf20Sopenharmony_ci	}
17808c2ecf20Sopenharmony_ci
17818c2ecf20Sopenharmony_ci	return 0;
17828c2ecf20Sopenharmony_ci}
17838c2ecf20Sopenharmony_ci
17848c2ecf20Sopenharmony_ciu32 qbman_bp_info_num_free_bufs(struct qbman_bp_query_rslt *a)
17858c2ecf20Sopenharmony_ci{
17868c2ecf20Sopenharmony_ci	return le32_to_cpu(a->fill);
17878c2ecf20Sopenharmony_ci}
1788