162306a36Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
462306a36Sopenharmony_ci * Copyright 2016-2019 NXP
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <asm/cacheflush.h>
962306a36Sopenharmony_ci#include <linux/io.h>
1062306a36Sopenharmony_ci#include <linux/slab.h>
1162306a36Sopenharmony_ci#include <linux/spinlock.h>
1262306a36Sopenharmony_ci#include <soc/fsl/dpaa2-global.h>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#include "qbman-portal.h"
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci/* All QBMan command and result structures use this "valid bit" encoding */
1762306a36Sopenharmony_ci#define QB_VALID_BIT ((u32)0x80)
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci/* QBMan portal management command codes */
2062306a36Sopenharmony_ci#define QBMAN_MC_ACQUIRE       0x30
2162306a36Sopenharmony_ci#define QBMAN_WQCHAN_CONFIGURE 0x46
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci/* CINH register offsets */
2462306a36Sopenharmony_ci#define QBMAN_CINH_SWP_EQCR_PI      0x800
2562306a36Sopenharmony_ci#define QBMAN_CINH_SWP_EQCR_CI	    0x840
2662306a36Sopenharmony_ci#define QBMAN_CINH_SWP_EQAR    0x8c0
2762306a36Sopenharmony_ci#define QBMAN_CINH_SWP_CR_RT        0x900
2862306a36Sopenharmony_ci#define QBMAN_CINH_SWP_VDQCR_RT     0x940
2962306a36Sopenharmony_ci#define QBMAN_CINH_SWP_EQCR_AM_RT   0x980
3062306a36Sopenharmony_ci#define QBMAN_CINH_SWP_RCR_AM_RT    0x9c0
3162306a36Sopenharmony_ci#define QBMAN_CINH_SWP_DQPI    0xa00
3262306a36Sopenharmony_ci#define QBMAN_CINH_SWP_DQRR_ITR     0xa80
3362306a36Sopenharmony_ci#define QBMAN_CINH_SWP_DCAP    0xac0
3462306a36Sopenharmony_ci#define QBMAN_CINH_SWP_SDQCR   0xb00
3562306a36Sopenharmony_ci#define QBMAN_CINH_SWP_EQCR_AM_RT2  0xb40
3662306a36Sopenharmony_ci#define QBMAN_CINH_SWP_RCR_PI       0xc00
3762306a36Sopenharmony_ci#define QBMAN_CINH_SWP_RAR     0xcc0
3862306a36Sopenharmony_ci#define QBMAN_CINH_SWP_ISR     0xe00
3962306a36Sopenharmony_ci#define QBMAN_CINH_SWP_IER     0xe40
4062306a36Sopenharmony_ci#define QBMAN_CINH_SWP_ISDR    0xe80
4162306a36Sopenharmony_ci#define QBMAN_CINH_SWP_IIR     0xec0
4262306a36Sopenharmony_ci#define QBMAN_CINH_SWP_ITPR    0xf40
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci/* CENA register offsets */
4562306a36Sopenharmony_ci#define QBMAN_CENA_SWP_EQCR(n) (0x000 + ((u32)(n) << 6))
4662306a36Sopenharmony_ci#define QBMAN_CENA_SWP_DQRR(n) (0x200 + ((u32)(n) << 6))
4762306a36Sopenharmony_ci#define QBMAN_CENA_SWP_RCR(n)  (0x400 + ((u32)(n) << 6))
4862306a36Sopenharmony_ci#define QBMAN_CENA_SWP_CR      0x600
4962306a36Sopenharmony_ci#define QBMAN_CENA_SWP_RR(vb)  (0x700 + ((u32)(vb) >> 1))
5062306a36Sopenharmony_ci#define QBMAN_CENA_SWP_VDQCR   0x780
5162306a36Sopenharmony_ci#define QBMAN_CENA_SWP_EQCR_CI 0x840
5262306a36Sopenharmony_ci#define QBMAN_CENA_SWP_EQCR_CI_MEMBACK 0x1840
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci/* CENA register offsets in memory-backed mode */
5562306a36Sopenharmony_ci#define QBMAN_CENA_SWP_DQRR_MEM(n)  (0x800 + ((u32)(n) << 6))
5662306a36Sopenharmony_ci#define QBMAN_CENA_SWP_RCR_MEM(n)   (0x1400 + ((u32)(n) << 6))
5762306a36Sopenharmony_ci#define QBMAN_CENA_SWP_CR_MEM       0x1600
5862306a36Sopenharmony_ci#define QBMAN_CENA_SWP_RR_MEM       0x1680
5962306a36Sopenharmony_ci#define QBMAN_CENA_SWP_VDQCR_MEM    0x1780
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci/* Reverse mapping of QBMAN_CENA_SWP_DQRR() */
6262306a36Sopenharmony_ci#define QBMAN_IDX_FROM_DQRR(p) (((unsigned long)(p) & 0x1ff) >> 6)
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci/* Define token used to determine if response written to memory is valid */
6562306a36Sopenharmony_ci#define QMAN_DQ_TOKEN_VALID 1
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci/* SDQCR attribute codes */
6862306a36Sopenharmony_ci#define QB_SDQCR_FC_SHIFT   29
6962306a36Sopenharmony_ci#define QB_SDQCR_FC_MASK    0x1
7062306a36Sopenharmony_ci#define QB_SDQCR_DCT_SHIFT  24
7162306a36Sopenharmony_ci#define QB_SDQCR_DCT_MASK   0x3
7262306a36Sopenharmony_ci#define QB_SDQCR_TOK_SHIFT  16
7362306a36Sopenharmony_ci#define QB_SDQCR_TOK_MASK   0xff
7462306a36Sopenharmony_ci#define QB_SDQCR_SRC_SHIFT  0
7562306a36Sopenharmony_ci#define QB_SDQCR_SRC_MASK   0xffff
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci/* opaque token for static dequeues */
7862306a36Sopenharmony_ci#define QMAN_SDQCR_TOKEN    0xbb
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci#define QBMAN_EQCR_DCA_IDXMASK          0x0f
8162306a36Sopenharmony_ci#define QBMAN_ENQUEUE_FLAG_DCA          (1ULL << 31)
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci#define EQ_DESC_SIZE_WITHOUT_FD 29
8462306a36Sopenharmony_ci#define EQ_DESC_SIZE_FD_START 32
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_cienum qbman_sdqcr_dct {
8762306a36Sopenharmony_ci	qbman_sdqcr_dct_null = 0,
8862306a36Sopenharmony_ci	qbman_sdqcr_dct_prio_ics,
8962306a36Sopenharmony_ci	qbman_sdqcr_dct_active_ics,
9062306a36Sopenharmony_ci	qbman_sdqcr_dct_active
9162306a36Sopenharmony_ci};
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_cienum qbman_sdqcr_fc {
9462306a36Sopenharmony_ci	qbman_sdqcr_fc_one = 0,
9562306a36Sopenharmony_ci	qbman_sdqcr_fc_up_to_3 = 1
9662306a36Sopenharmony_ci};
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci/* Internal Function declaration */
9962306a36Sopenharmony_cistatic int qbman_swp_enqueue_direct(struct qbman_swp *s,
10062306a36Sopenharmony_ci				    const struct qbman_eq_desc *d,
10162306a36Sopenharmony_ci				    const struct dpaa2_fd *fd);
10262306a36Sopenharmony_cistatic int qbman_swp_enqueue_mem_back(struct qbman_swp *s,
10362306a36Sopenharmony_ci				      const struct qbman_eq_desc *d,
10462306a36Sopenharmony_ci				      const struct dpaa2_fd *fd);
10562306a36Sopenharmony_cistatic int qbman_swp_enqueue_multiple_direct(struct qbman_swp *s,
10662306a36Sopenharmony_ci					     const struct qbman_eq_desc *d,
10762306a36Sopenharmony_ci					     const struct dpaa2_fd *fd,
10862306a36Sopenharmony_ci					     uint32_t *flags,
10962306a36Sopenharmony_ci					     int num_frames);
11062306a36Sopenharmony_cistatic int qbman_swp_enqueue_multiple_mem_back(struct qbman_swp *s,
11162306a36Sopenharmony_ci					       const struct qbman_eq_desc *d,
11262306a36Sopenharmony_ci					       const struct dpaa2_fd *fd,
11362306a36Sopenharmony_ci					       uint32_t *flags,
11462306a36Sopenharmony_ci					       int num_frames);
11562306a36Sopenharmony_cistatic int
11662306a36Sopenharmony_ciqbman_swp_enqueue_multiple_desc_direct(struct qbman_swp *s,
11762306a36Sopenharmony_ci				       const struct qbman_eq_desc *d,
11862306a36Sopenharmony_ci				       const struct dpaa2_fd *fd,
11962306a36Sopenharmony_ci				       int num_frames);
12062306a36Sopenharmony_cistatic
12162306a36Sopenharmony_ciint qbman_swp_enqueue_multiple_desc_mem_back(struct qbman_swp *s,
12262306a36Sopenharmony_ci					     const struct qbman_eq_desc *d,
12362306a36Sopenharmony_ci					     const struct dpaa2_fd *fd,
12462306a36Sopenharmony_ci					     int num_frames);
12562306a36Sopenharmony_cistatic int qbman_swp_pull_direct(struct qbman_swp *s,
12662306a36Sopenharmony_ci				 struct qbman_pull_desc *d);
12762306a36Sopenharmony_cistatic int qbman_swp_pull_mem_back(struct qbman_swp *s,
12862306a36Sopenharmony_ci				   struct qbman_pull_desc *d);
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ciconst struct dpaa2_dq *qbman_swp_dqrr_next_direct(struct qbman_swp *s);
13162306a36Sopenharmony_ciconst struct dpaa2_dq *qbman_swp_dqrr_next_mem_back(struct qbman_swp *s);
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_cistatic int qbman_swp_release_direct(struct qbman_swp *s,
13462306a36Sopenharmony_ci				    const struct qbman_release_desc *d,
13562306a36Sopenharmony_ci				    const u64 *buffers,
13662306a36Sopenharmony_ci				    unsigned int num_buffers);
13762306a36Sopenharmony_cistatic int qbman_swp_release_mem_back(struct qbman_swp *s,
13862306a36Sopenharmony_ci				      const struct qbman_release_desc *d,
13962306a36Sopenharmony_ci				      const u64 *buffers,
14062306a36Sopenharmony_ci				      unsigned int num_buffers);
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci/* Function pointers */
14362306a36Sopenharmony_ciint (*qbman_swp_enqueue_ptr)(struct qbman_swp *s,
14462306a36Sopenharmony_ci			     const struct qbman_eq_desc *d,
14562306a36Sopenharmony_ci			     const struct dpaa2_fd *fd)
14662306a36Sopenharmony_ci	= qbman_swp_enqueue_direct;
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ciint (*qbman_swp_enqueue_multiple_ptr)(struct qbman_swp *s,
14962306a36Sopenharmony_ci				      const struct qbman_eq_desc *d,
15062306a36Sopenharmony_ci				      const struct dpaa2_fd *fd,
15162306a36Sopenharmony_ci				      uint32_t *flags,
15262306a36Sopenharmony_ci					     int num_frames)
15362306a36Sopenharmony_ci	= qbman_swp_enqueue_multiple_direct;
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ciint
15662306a36Sopenharmony_ci(*qbman_swp_enqueue_multiple_desc_ptr)(struct qbman_swp *s,
15762306a36Sopenharmony_ci				       const struct qbman_eq_desc *d,
15862306a36Sopenharmony_ci				       const struct dpaa2_fd *fd,
15962306a36Sopenharmony_ci				       int num_frames)
16062306a36Sopenharmony_ci	= qbman_swp_enqueue_multiple_desc_direct;
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ciint (*qbman_swp_pull_ptr)(struct qbman_swp *s, struct qbman_pull_desc *d)
16362306a36Sopenharmony_ci			= qbman_swp_pull_direct;
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ciconst struct dpaa2_dq *(*qbman_swp_dqrr_next_ptr)(struct qbman_swp *s)
16662306a36Sopenharmony_ci			= qbman_swp_dqrr_next_direct;
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ciint (*qbman_swp_release_ptr)(struct qbman_swp *s,
16962306a36Sopenharmony_ci			     const struct qbman_release_desc *d,
17062306a36Sopenharmony_ci			     const u64 *buffers,
17162306a36Sopenharmony_ci			     unsigned int num_buffers)
17262306a36Sopenharmony_ci			= qbman_swp_release_direct;
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci/* Portal Access */
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_cistatic inline u32 qbman_read_register(struct qbman_swp *p, u32 offset)
17762306a36Sopenharmony_ci{
17862306a36Sopenharmony_ci	return readl_relaxed(p->addr_cinh + offset);
17962306a36Sopenharmony_ci}
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_cistatic inline void qbman_write_register(struct qbman_swp *p, u32 offset,
18262306a36Sopenharmony_ci					u32 value)
18362306a36Sopenharmony_ci{
18462306a36Sopenharmony_ci	writel_relaxed(value, p->addr_cinh + offset);
18562306a36Sopenharmony_ci}
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_cistatic inline void *qbman_get_cmd(struct qbman_swp *p, u32 offset)
18862306a36Sopenharmony_ci{
18962306a36Sopenharmony_ci	return p->addr_cena + offset;
19062306a36Sopenharmony_ci}
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci#define QBMAN_CINH_SWP_CFG   0xd00
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci#define SWP_CFG_DQRR_MF_SHIFT 20
19562306a36Sopenharmony_ci#define SWP_CFG_EST_SHIFT     16
19662306a36Sopenharmony_ci#define SWP_CFG_CPBS_SHIFT    15
19762306a36Sopenharmony_ci#define SWP_CFG_WN_SHIFT      14
19862306a36Sopenharmony_ci#define SWP_CFG_RPM_SHIFT     12
19962306a36Sopenharmony_ci#define SWP_CFG_DCM_SHIFT     10
20062306a36Sopenharmony_ci#define SWP_CFG_EPM_SHIFT     8
20162306a36Sopenharmony_ci#define SWP_CFG_VPM_SHIFT     7
20262306a36Sopenharmony_ci#define SWP_CFG_CPM_SHIFT     6
20362306a36Sopenharmony_ci#define SWP_CFG_SD_SHIFT      5
20462306a36Sopenharmony_ci#define SWP_CFG_SP_SHIFT      4
20562306a36Sopenharmony_ci#define SWP_CFG_SE_SHIFT      3
20662306a36Sopenharmony_ci#define SWP_CFG_DP_SHIFT      2
20762306a36Sopenharmony_ci#define SWP_CFG_DE_SHIFT      1
20862306a36Sopenharmony_ci#define SWP_CFG_EP_SHIFT      0
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_cistatic inline u32 qbman_set_swp_cfg(u8 max_fill, u8 wn,	u8 est, u8 rpm, u8 dcm,
21162306a36Sopenharmony_ci				    u8 epm, int sd, int sp, int se,
21262306a36Sopenharmony_ci				    int dp, int de, int ep)
21362306a36Sopenharmony_ci{
21462306a36Sopenharmony_ci	return (max_fill << SWP_CFG_DQRR_MF_SHIFT |
21562306a36Sopenharmony_ci		est << SWP_CFG_EST_SHIFT |
21662306a36Sopenharmony_ci		wn << SWP_CFG_WN_SHIFT |
21762306a36Sopenharmony_ci		rpm << SWP_CFG_RPM_SHIFT |
21862306a36Sopenharmony_ci		dcm << SWP_CFG_DCM_SHIFT |
21962306a36Sopenharmony_ci		epm << SWP_CFG_EPM_SHIFT |
22062306a36Sopenharmony_ci		sd << SWP_CFG_SD_SHIFT |
22162306a36Sopenharmony_ci		sp << SWP_CFG_SP_SHIFT |
22262306a36Sopenharmony_ci		se << SWP_CFG_SE_SHIFT |
22362306a36Sopenharmony_ci		dp << SWP_CFG_DP_SHIFT |
22462306a36Sopenharmony_ci		de << SWP_CFG_DE_SHIFT |
22562306a36Sopenharmony_ci		ep << SWP_CFG_EP_SHIFT);
22662306a36Sopenharmony_ci}
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci#define QMAN_RT_MODE	   0x00000100
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_cistatic inline u8 qm_cyc_diff(u8 ringsize, u8 first, u8 last)
23162306a36Sopenharmony_ci{
23262306a36Sopenharmony_ci	/* 'first' is included, 'last' is excluded */
23362306a36Sopenharmony_ci	if (first <= last)
23462306a36Sopenharmony_ci		return last - first;
23562306a36Sopenharmony_ci	else
23662306a36Sopenharmony_ci		return (2 * ringsize) - (first - last);
23762306a36Sopenharmony_ci}
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci/**
24062306a36Sopenharmony_ci * qbman_swp_init() - Create a functional object representing the given
24162306a36Sopenharmony_ci *                    QBMan portal descriptor.
24262306a36Sopenharmony_ci * @d: the given qbman swp descriptor
24362306a36Sopenharmony_ci *
24462306a36Sopenharmony_ci * Return qbman_swp portal for success, NULL if the object cannot
24562306a36Sopenharmony_ci * be created.
24662306a36Sopenharmony_ci */
24762306a36Sopenharmony_cistruct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d)
24862306a36Sopenharmony_ci{
24962306a36Sopenharmony_ci	struct qbman_swp *p = kzalloc(sizeof(*p), GFP_KERNEL);
25062306a36Sopenharmony_ci	u32 reg;
25162306a36Sopenharmony_ci	u32 mask_size;
25262306a36Sopenharmony_ci	u32 eqcr_pi;
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci	if (!p)
25562306a36Sopenharmony_ci		return NULL;
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci	spin_lock_init(&p->access_spinlock);
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci	p->desc = d;
26062306a36Sopenharmony_ci	p->mc.valid_bit = QB_VALID_BIT;
26162306a36Sopenharmony_ci	p->sdq = 0;
26262306a36Sopenharmony_ci	p->sdq |= qbman_sdqcr_dct_prio_ics << QB_SDQCR_DCT_SHIFT;
26362306a36Sopenharmony_ci	p->sdq |= qbman_sdqcr_fc_up_to_3 << QB_SDQCR_FC_SHIFT;
26462306a36Sopenharmony_ci	p->sdq |= QMAN_SDQCR_TOKEN << QB_SDQCR_TOK_SHIFT;
26562306a36Sopenharmony_ci	if ((p->desc->qman_version & QMAN_REV_MASK) >= QMAN_REV_5000)
26662306a36Sopenharmony_ci		p->mr.valid_bit = QB_VALID_BIT;
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci	atomic_set(&p->vdq.available, 1);
26962306a36Sopenharmony_ci	p->vdq.valid_bit = QB_VALID_BIT;
27062306a36Sopenharmony_ci	p->dqrr.next_idx = 0;
27162306a36Sopenharmony_ci	p->dqrr.valid_bit = QB_VALID_BIT;
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci	if ((p->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_4100) {
27462306a36Sopenharmony_ci		p->dqrr.dqrr_size = 4;
27562306a36Sopenharmony_ci		p->dqrr.reset_bug = 1;
27662306a36Sopenharmony_ci	} else {
27762306a36Sopenharmony_ci		p->dqrr.dqrr_size = 8;
27862306a36Sopenharmony_ci		p->dqrr.reset_bug = 0;
27962306a36Sopenharmony_ci	}
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci	p->addr_cena = d->cena_bar;
28262306a36Sopenharmony_ci	p->addr_cinh = d->cinh_bar;
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	if ((p->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000) {
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci		reg = qbman_set_swp_cfg(p->dqrr.dqrr_size,
28762306a36Sopenharmony_ci			1, /* Writes Non-cacheable */
28862306a36Sopenharmony_ci			0, /* EQCR_CI stashing threshold */
28962306a36Sopenharmony_ci			3, /* RPM: RCR in array mode */
29062306a36Sopenharmony_ci			2, /* DCM: Discrete consumption ack */
29162306a36Sopenharmony_ci			2, /* EPM: EQCR in ring mode */
29262306a36Sopenharmony_ci			1, /* mem stashing drop enable enable */
29362306a36Sopenharmony_ci			1, /* mem stashing priority enable */
29462306a36Sopenharmony_ci			1, /* mem stashing enable */
29562306a36Sopenharmony_ci			1, /* dequeue stashing priority enable */
29662306a36Sopenharmony_ci			0, /* dequeue stashing enable enable */
29762306a36Sopenharmony_ci			0); /* EQCR_CI stashing priority enable */
29862306a36Sopenharmony_ci	} else {
29962306a36Sopenharmony_ci		memset(p->addr_cena, 0, 64 * 1024);
30062306a36Sopenharmony_ci		reg = qbman_set_swp_cfg(p->dqrr.dqrr_size,
30162306a36Sopenharmony_ci			1, /* Writes Non-cacheable */
30262306a36Sopenharmony_ci			1, /* EQCR_CI stashing threshold */
30362306a36Sopenharmony_ci			3, /* RPM: RCR in array mode */
30462306a36Sopenharmony_ci			2, /* DCM: Discrete consumption ack */
30562306a36Sopenharmony_ci			0, /* EPM: EQCR in ring mode */
30662306a36Sopenharmony_ci			1, /* mem stashing drop enable */
30762306a36Sopenharmony_ci			1, /* mem stashing priority enable */
30862306a36Sopenharmony_ci			1, /* mem stashing enable */
30962306a36Sopenharmony_ci			1, /* dequeue stashing priority enable */
31062306a36Sopenharmony_ci			0, /* dequeue stashing enable */
31162306a36Sopenharmony_ci			0); /* EQCR_CI stashing priority enable */
31262306a36Sopenharmony_ci		reg |= 1 << SWP_CFG_CPBS_SHIFT | /* memory-backed mode */
31362306a36Sopenharmony_ci		       1 << SWP_CFG_VPM_SHIFT |  /* VDQCR read triggered mode */
31462306a36Sopenharmony_ci		       1 << SWP_CFG_CPM_SHIFT;   /* CR read triggered mode */
31562306a36Sopenharmony_ci	}
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci	qbman_write_register(p, QBMAN_CINH_SWP_CFG, reg);
31862306a36Sopenharmony_ci	reg = qbman_read_register(p, QBMAN_CINH_SWP_CFG);
31962306a36Sopenharmony_ci	if (!reg) {
32062306a36Sopenharmony_ci		pr_err("qbman: the portal is not enabled!\n");
32162306a36Sopenharmony_ci		kfree(p);
32262306a36Sopenharmony_ci		return NULL;
32362306a36Sopenharmony_ci	}
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci	if ((p->desc->qman_version & QMAN_REV_MASK) >= QMAN_REV_5000) {
32662306a36Sopenharmony_ci		qbman_write_register(p, QBMAN_CINH_SWP_EQCR_PI, QMAN_RT_MODE);
32762306a36Sopenharmony_ci		qbman_write_register(p, QBMAN_CINH_SWP_RCR_PI, QMAN_RT_MODE);
32862306a36Sopenharmony_ci	}
32962306a36Sopenharmony_ci	/*
33062306a36Sopenharmony_ci	 * SDQCR needs to be initialized to 0 when no channels are
33162306a36Sopenharmony_ci	 * being dequeued from or else the QMan HW will indicate an
33262306a36Sopenharmony_ci	 * error.  The values that were calculated above will be
33362306a36Sopenharmony_ci	 * applied when dequeues from a specific channel are enabled.
33462306a36Sopenharmony_ci	 */
33562306a36Sopenharmony_ci	qbman_write_register(p, QBMAN_CINH_SWP_SDQCR, 0);
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci	p->eqcr.pi_ring_size = 8;
33862306a36Sopenharmony_ci	if ((p->desc->qman_version & QMAN_REV_MASK) >= QMAN_REV_5000) {
33962306a36Sopenharmony_ci		p->eqcr.pi_ring_size = 32;
34062306a36Sopenharmony_ci		qbman_swp_enqueue_ptr =
34162306a36Sopenharmony_ci			qbman_swp_enqueue_mem_back;
34262306a36Sopenharmony_ci		qbman_swp_enqueue_multiple_ptr =
34362306a36Sopenharmony_ci			qbman_swp_enqueue_multiple_mem_back;
34462306a36Sopenharmony_ci		qbman_swp_enqueue_multiple_desc_ptr =
34562306a36Sopenharmony_ci			qbman_swp_enqueue_multiple_desc_mem_back;
34662306a36Sopenharmony_ci		qbman_swp_pull_ptr = qbman_swp_pull_mem_back;
34762306a36Sopenharmony_ci		qbman_swp_dqrr_next_ptr = qbman_swp_dqrr_next_mem_back;
34862306a36Sopenharmony_ci		qbman_swp_release_ptr = qbman_swp_release_mem_back;
34962306a36Sopenharmony_ci	}
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci	for (mask_size = p->eqcr.pi_ring_size; mask_size > 0; mask_size >>= 1)
35262306a36Sopenharmony_ci		p->eqcr.pi_ci_mask = (p->eqcr.pi_ci_mask << 1) + 1;
35362306a36Sopenharmony_ci	eqcr_pi = qbman_read_register(p, QBMAN_CINH_SWP_EQCR_PI);
35462306a36Sopenharmony_ci	p->eqcr.pi = eqcr_pi & p->eqcr.pi_ci_mask;
35562306a36Sopenharmony_ci	p->eqcr.pi_vb = eqcr_pi & QB_VALID_BIT;
35662306a36Sopenharmony_ci	p->eqcr.ci = qbman_read_register(p, QBMAN_CINH_SWP_EQCR_CI)
35762306a36Sopenharmony_ci			& p->eqcr.pi_ci_mask;
35862306a36Sopenharmony_ci	p->eqcr.available = p->eqcr.pi_ring_size;
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci	/* Initialize the software portal with a irq timeout period of 0us */
36162306a36Sopenharmony_ci	qbman_swp_set_irq_coalescing(p, p->dqrr.dqrr_size - 1, 0);
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci	return p;
36462306a36Sopenharmony_ci}
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci/**
36762306a36Sopenharmony_ci * qbman_swp_finish() - Create and destroy a functional object representing
36862306a36Sopenharmony_ci *                      the given QBMan portal descriptor.
36962306a36Sopenharmony_ci * @p: the qbman_swp object to be destroyed
37062306a36Sopenharmony_ci */
37162306a36Sopenharmony_civoid qbman_swp_finish(struct qbman_swp *p)
37262306a36Sopenharmony_ci{
37362306a36Sopenharmony_ci	kfree(p);
37462306a36Sopenharmony_ci}
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_ci/**
37762306a36Sopenharmony_ci * qbman_swp_interrupt_read_status()
37862306a36Sopenharmony_ci * @p: the given software portal
37962306a36Sopenharmony_ci *
38062306a36Sopenharmony_ci * Return the value in the SWP_ISR register.
38162306a36Sopenharmony_ci */
38262306a36Sopenharmony_ciu32 qbman_swp_interrupt_read_status(struct qbman_swp *p)
38362306a36Sopenharmony_ci{
38462306a36Sopenharmony_ci	return qbman_read_register(p, QBMAN_CINH_SWP_ISR);
38562306a36Sopenharmony_ci}
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci/**
38862306a36Sopenharmony_ci * qbman_swp_interrupt_clear_status()
38962306a36Sopenharmony_ci * @p: the given software portal
39062306a36Sopenharmony_ci * @mask: The mask to clear in SWP_ISR register
39162306a36Sopenharmony_ci */
39262306a36Sopenharmony_civoid qbman_swp_interrupt_clear_status(struct qbman_swp *p, u32 mask)
39362306a36Sopenharmony_ci{
39462306a36Sopenharmony_ci	qbman_write_register(p, QBMAN_CINH_SWP_ISR, mask);
39562306a36Sopenharmony_ci}
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci/**
39862306a36Sopenharmony_ci * qbman_swp_interrupt_get_trigger() - read interrupt enable register
39962306a36Sopenharmony_ci * @p: the given software portal
40062306a36Sopenharmony_ci *
40162306a36Sopenharmony_ci * Return the value in the SWP_IER register.
40262306a36Sopenharmony_ci */
40362306a36Sopenharmony_ciu32 qbman_swp_interrupt_get_trigger(struct qbman_swp *p)
40462306a36Sopenharmony_ci{
40562306a36Sopenharmony_ci	return qbman_read_register(p, QBMAN_CINH_SWP_IER);
40662306a36Sopenharmony_ci}
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ci/**
40962306a36Sopenharmony_ci * qbman_swp_interrupt_set_trigger() - enable interrupts for a swp
41062306a36Sopenharmony_ci * @p: the given software portal
41162306a36Sopenharmony_ci * @mask: The mask of bits to enable in SWP_IER
41262306a36Sopenharmony_ci */
41362306a36Sopenharmony_civoid qbman_swp_interrupt_set_trigger(struct qbman_swp *p, u32 mask)
41462306a36Sopenharmony_ci{
41562306a36Sopenharmony_ci	qbman_write_register(p, QBMAN_CINH_SWP_IER, mask);
41662306a36Sopenharmony_ci}
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci/**
41962306a36Sopenharmony_ci * qbman_swp_interrupt_get_inhibit() - read interrupt mask register
42062306a36Sopenharmony_ci * @p: the given software portal object
42162306a36Sopenharmony_ci *
42262306a36Sopenharmony_ci * Return the value in the SWP_IIR register.
42362306a36Sopenharmony_ci */
42462306a36Sopenharmony_ciint qbman_swp_interrupt_get_inhibit(struct qbman_swp *p)
42562306a36Sopenharmony_ci{
42662306a36Sopenharmony_ci	return qbman_read_register(p, QBMAN_CINH_SWP_IIR);
42762306a36Sopenharmony_ci}
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci/**
43062306a36Sopenharmony_ci * qbman_swp_interrupt_set_inhibit() - write interrupt mask register
43162306a36Sopenharmony_ci * @p: the given software portal object
43262306a36Sopenharmony_ci * @inhibit: whether to inhibit the IRQs
43362306a36Sopenharmony_ci */
43462306a36Sopenharmony_civoid qbman_swp_interrupt_set_inhibit(struct qbman_swp *p, int inhibit)
43562306a36Sopenharmony_ci{
43662306a36Sopenharmony_ci	qbman_write_register(p, QBMAN_CINH_SWP_IIR, inhibit ? 0xffffffff : 0);
43762306a36Sopenharmony_ci}
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci/*
44062306a36Sopenharmony_ci * Different management commands all use this common base layer of code to issue
44162306a36Sopenharmony_ci * commands and poll for results.
44262306a36Sopenharmony_ci */
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ci/*
44562306a36Sopenharmony_ci * Returns a pointer to where the caller should fill in their management command
44662306a36Sopenharmony_ci * (caller should ignore the verb byte)
44762306a36Sopenharmony_ci */
44862306a36Sopenharmony_civoid *qbman_swp_mc_start(struct qbman_swp *p)
44962306a36Sopenharmony_ci{
45062306a36Sopenharmony_ci	if ((p->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000)
45162306a36Sopenharmony_ci		return qbman_get_cmd(p, QBMAN_CENA_SWP_CR);
45262306a36Sopenharmony_ci	else
45362306a36Sopenharmony_ci		return qbman_get_cmd(p, QBMAN_CENA_SWP_CR_MEM);
45462306a36Sopenharmony_ci}
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_ci/*
45762306a36Sopenharmony_ci * Commits merges in the caller-supplied command verb (which should not include
45862306a36Sopenharmony_ci * the valid-bit) and submits the command to hardware
45962306a36Sopenharmony_ci */
46062306a36Sopenharmony_civoid qbman_swp_mc_submit(struct qbman_swp *p, void *cmd, u8 cmd_verb)
46162306a36Sopenharmony_ci{
46262306a36Sopenharmony_ci	u8 *v = cmd;
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci	if ((p->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000) {
46562306a36Sopenharmony_ci		dma_wmb();
46662306a36Sopenharmony_ci		*v = cmd_verb | p->mc.valid_bit;
46762306a36Sopenharmony_ci	} else {
46862306a36Sopenharmony_ci		*v = cmd_verb | p->mc.valid_bit;
46962306a36Sopenharmony_ci		dma_wmb();
47062306a36Sopenharmony_ci		qbman_write_register(p, QBMAN_CINH_SWP_CR_RT, QMAN_RT_MODE);
47162306a36Sopenharmony_ci	}
47262306a36Sopenharmony_ci}
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_ci/*
47562306a36Sopenharmony_ci * Checks for a completed response (returns non-NULL if only if the response
47662306a36Sopenharmony_ci * is complete).
47762306a36Sopenharmony_ci */
47862306a36Sopenharmony_civoid *qbman_swp_mc_result(struct qbman_swp *p)
47962306a36Sopenharmony_ci{
48062306a36Sopenharmony_ci	u32 *ret, verb;
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci	if ((p->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000) {
48362306a36Sopenharmony_ci		ret = qbman_get_cmd(p, QBMAN_CENA_SWP_RR(p->mc.valid_bit));
48462306a36Sopenharmony_ci		/* Remove the valid-bit - command completed if the rest
48562306a36Sopenharmony_ci		 * is non-zero.
48662306a36Sopenharmony_ci		 */
48762306a36Sopenharmony_ci		verb = ret[0] & ~QB_VALID_BIT;
48862306a36Sopenharmony_ci		if (!verb)
48962306a36Sopenharmony_ci			return NULL;
49062306a36Sopenharmony_ci		p->mc.valid_bit ^= QB_VALID_BIT;
49162306a36Sopenharmony_ci	} else {
49262306a36Sopenharmony_ci		ret = qbman_get_cmd(p, QBMAN_CENA_SWP_RR_MEM);
49362306a36Sopenharmony_ci		/* Command completed if the valid bit is toggled */
49462306a36Sopenharmony_ci		if (p->mr.valid_bit != (ret[0] & QB_VALID_BIT))
49562306a36Sopenharmony_ci			return NULL;
49662306a36Sopenharmony_ci		/* Command completed if the rest is non-zero */
49762306a36Sopenharmony_ci		verb = ret[0] & ~QB_VALID_BIT;
49862306a36Sopenharmony_ci		if (!verb)
49962306a36Sopenharmony_ci			return NULL;
50062306a36Sopenharmony_ci		p->mr.valid_bit ^= QB_VALID_BIT;
50162306a36Sopenharmony_ci	}
50262306a36Sopenharmony_ci
50362306a36Sopenharmony_ci	return ret;
50462306a36Sopenharmony_ci}
50562306a36Sopenharmony_ci
50662306a36Sopenharmony_ci#define QB_ENQUEUE_CMD_OPTIONS_SHIFT    0
50762306a36Sopenharmony_cienum qb_enqueue_commands {
50862306a36Sopenharmony_ci	enqueue_empty = 0,
50962306a36Sopenharmony_ci	enqueue_response_always = 1,
51062306a36Sopenharmony_ci	enqueue_rejects_to_fq = 2
51162306a36Sopenharmony_ci};
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci#define QB_ENQUEUE_CMD_ORP_ENABLE_SHIFT      2
51462306a36Sopenharmony_ci#define QB_ENQUEUE_CMD_IRQ_ON_DISPATCH_SHIFT 3
51562306a36Sopenharmony_ci#define QB_ENQUEUE_CMD_TARGET_TYPE_SHIFT     4
51662306a36Sopenharmony_ci#define QB_ENQUEUE_CMD_DCA_EN_SHIFT          7
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_ci/*
51962306a36Sopenharmony_ci * qbman_eq_desc_clear() - Clear the contents of a descriptor to
52062306a36Sopenharmony_ci *                         default/starting state.
52162306a36Sopenharmony_ci */
52262306a36Sopenharmony_civoid qbman_eq_desc_clear(struct qbman_eq_desc *d)
52362306a36Sopenharmony_ci{
52462306a36Sopenharmony_ci	memset(d, 0, sizeof(*d));
52562306a36Sopenharmony_ci}
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ci/**
52862306a36Sopenharmony_ci * qbman_eq_desc_set_no_orp() - Set enqueue descriptor without orp
52962306a36Sopenharmony_ci * @d:                the enqueue descriptor.
53062306a36Sopenharmony_ci * @respond_success:  1 = enqueue with response always; 0 = enqueue with
53162306a36Sopenharmony_ci *                    rejections returned on a FQ.
53262306a36Sopenharmony_ci */
53362306a36Sopenharmony_civoid qbman_eq_desc_set_no_orp(struct qbman_eq_desc *d, int respond_success)
53462306a36Sopenharmony_ci{
53562306a36Sopenharmony_ci	d->verb &= ~(1 << QB_ENQUEUE_CMD_ORP_ENABLE_SHIFT);
53662306a36Sopenharmony_ci	if (respond_success)
53762306a36Sopenharmony_ci		d->verb |= enqueue_response_always;
53862306a36Sopenharmony_ci	else
53962306a36Sopenharmony_ci		d->verb |= enqueue_rejects_to_fq;
54062306a36Sopenharmony_ci}
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ci/*
54362306a36Sopenharmony_ci * Exactly one of the following descriptor "targets" should be set. (Calling any
54462306a36Sopenharmony_ci * one of these will replace the effect of any prior call to one of these.)
54562306a36Sopenharmony_ci *   -enqueue to a frame queue
54662306a36Sopenharmony_ci *   -enqueue to a queuing destination
54762306a36Sopenharmony_ci */
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_ci/**
55062306a36Sopenharmony_ci * qbman_eq_desc_set_fq() - set the FQ for the enqueue command
55162306a36Sopenharmony_ci * @d:    the enqueue descriptor
55262306a36Sopenharmony_ci * @fqid: the id of the frame queue to be enqueued
55362306a36Sopenharmony_ci */
55462306a36Sopenharmony_civoid qbman_eq_desc_set_fq(struct qbman_eq_desc *d, u32 fqid)
55562306a36Sopenharmony_ci{
55662306a36Sopenharmony_ci	d->verb &= ~(1 << QB_ENQUEUE_CMD_TARGET_TYPE_SHIFT);
55762306a36Sopenharmony_ci	d->tgtid = cpu_to_le32(fqid);
55862306a36Sopenharmony_ci}
55962306a36Sopenharmony_ci
56062306a36Sopenharmony_ci/**
56162306a36Sopenharmony_ci * qbman_eq_desc_set_qd() - Set Queuing Destination for the enqueue command
56262306a36Sopenharmony_ci * @d:       the enqueue descriptor
56362306a36Sopenharmony_ci * @qdid:    the id of the queuing destination to be enqueued
56462306a36Sopenharmony_ci * @qd_bin:  the queuing destination bin
56562306a36Sopenharmony_ci * @qd_prio: the queuing destination priority
56662306a36Sopenharmony_ci */
56762306a36Sopenharmony_civoid qbman_eq_desc_set_qd(struct qbman_eq_desc *d, u32 qdid,
56862306a36Sopenharmony_ci			  u32 qd_bin, u32 qd_prio)
56962306a36Sopenharmony_ci{
57062306a36Sopenharmony_ci	d->verb |= 1 << QB_ENQUEUE_CMD_TARGET_TYPE_SHIFT;
57162306a36Sopenharmony_ci	d->tgtid = cpu_to_le32(qdid);
57262306a36Sopenharmony_ci	d->qdbin = cpu_to_le16(qd_bin);
57362306a36Sopenharmony_ci	d->qpri = qd_prio;
57462306a36Sopenharmony_ci}
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_ci#define EQAR_IDX(eqar)     ((eqar) & 0x7)
57762306a36Sopenharmony_ci#define EQAR_VB(eqar)      ((eqar) & 0x80)
57862306a36Sopenharmony_ci#define EQAR_SUCCESS(eqar) ((eqar) & 0x100)
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_ci#define QB_RT_BIT ((u32)0x100)
58162306a36Sopenharmony_ci/**
58262306a36Sopenharmony_ci * qbman_swp_enqueue_direct() - Issue an enqueue command
58362306a36Sopenharmony_ci * @s:  the software portal used for enqueue
58462306a36Sopenharmony_ci * @d:  the enqueue descriptor
58562306a36Sopenharmony_ci * @fd: the frame descriptor to be enqueued
58662306a36Sopenharmony_ci *
58762306a36Sopenharmony_ci * Please note that 'fd' should only be NULL if the "action" of the
58862306a36Sopenharmony_ci * descriptor is "orp_hole" or "orp_nesn".
58962306a36Sopenharmony_ci *
59062306a36Sopenharmony_ci * Return 0 for successful enqueue, -EBUSY if the EQCR is not ready.
59162306a36Sopenharmony_ci */
59262306a36Sopenharmony_cistatic
59362306a36Sopenharmony_ciint qbman_swp_enqueue_direct(struct qbman_swp *s,
59462306a36Sopenharmony_ci			     const struct qbman_eq_desc *d,
59562306a36Sopenharmony_ci			     const struct dpaa2_fd *fd)
59662306a36Sopenharmony_ci{
59762306a36Sopenharmony_ci	int flags = 0;
59862306a36Sopenharmony_ci	int ret = qbman_swp_enqueue_multiple_direct(s, d, fd, &flags, 1);
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci	if (ret >= 0)
60162306a36Sopenharmony_ci		ret = 0;
60262306a36Sopenharmony_ci	else
60362306a36Sopenharmony_ci		ret = -EBUSY;
60462306a36Sopenharmony_ci	return  ret;
60562306a36Sopenharmony_ci}
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_ci/**
60862306a36Sopenharmony_ci * qbman_swp_enqueue_mem_back() - Issue an enqueue command
60962306a36Sopenharmony_ci * @s:  the software portal used for enqueue
61062306a36Sopenharmony_ci * @d:  the enqueue descriptor
61162306a36Sopenharmony_ci * @fd: the frame descriptor to be enqueued
61262306a36Sopenharmony_ci *
61362306a36Sopenharmony_ci * Please note that 'fd' should only be NULL if the "action" of the
61462306a36Sopenharmony_ci * descriptor is "orp_hole" or "orp_nesn".
61562306a36Sopenharmony_ci *
61662306a36Sopenharmony_ci * Return 0 for successful enqueue, -EBUSY if the EQCR is not ready.
61762306a36Sopenharmony_ci */
61862306a36Sopenharmony_cistatic
61962306a36Sopenharmony_ciint qbman_swp_enqueue_mem_back(struct qbman_swp *s,
62062306a36Sopenharmony_ci			       const struct qbman_eq_desc *d,
62162306a36Sopenharmony_ci			       const struct dpaa2_fd *fd)
62262306a36Sopenharmony_ci{
62362306a36Sopenharmony_ci	int flags = 0;
62462306a36Sopenharmony_ci	int ret = qbman_swp_enqueue_multiple_mem_back(s, d, fd, &flags, 1);
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_ci	if (ret >= 0)
62762306a36Sopenharmony_ci		ret = 0;
62862306a36Sopenharmony_ci	else
62962306a36Sopenharmony_ci		ret = -EBUSY;
63062306a36Sopenharmony_ci	return  ret;
63162306a36Sopenharmony_ci}
63262306a36Sopenharmony_ci
63362306a36Sopenharmony_ci/**
63462306a36Sopenharmony_ci * qbman_swp_enqueue_multiple_direct() - Issue a multi enqueue command
63562306a36Sopenharmony_ci * using one enqueue descriptor
63662306a36Sopenharmony_ci * @s:  the software portal used for enqueue
63762306a36Sopenharmony_ci * @d:  the enqueue descriptor
63862306a36Sopenharmony_ci * @fd: table pointer of frame descriptor table to be enqueued
63962306a36Sopenharmony_ci * @flags: table pointer of QBMAN_ENQUEUE_FLAG_DCA flags, not used if NULL
64062306a36Sopenharmony_ci * @num_frames: number of fd to be enqueued
64162306a36Sopenharmony_ci *
64262306a36Sopenharmony_ci * Return the number of fd enqueued, or a negative error number.
64362306a36Sopenharmony_ci */
64462306a36Sopenharmony_cistatic
64562306a36Sopenharmony_ciint qbman_swp_enqueue_multiple_direct(struct qbman_swp *s,
64662306a36Sopenharmony_ci				      const struct qbman_eq_desc *d,
64762306a36Sopenharmony_ci				      const struct dpaa2_fd *fd,
64862306a36Sopenharmony_ci				      uint32_t *flags,
64962306a36Sopenharmony_ci				      int num_frames)
65062306a36Sopenharmony_ci{
65162306a36Sopenharmony_ci	uint32_t *p = NULL;
65262306a36Sopenharmony_ci	const uint32_t *cl = (uint32_t *)d;
65362306a36Sopenharmony_ci	uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask;
65462306a36Sopenharmony_ci	int i, num_enqueued = 0;
65562306a36Sopenharmony_ci
65662306a36Sopenharmony_ci	spin_lock(&s->access_spinlock);
65762306a36Sopenharmony_ci	half_mask = (s->eqcr.pi_ci_mask>>1);
65862306a36Sopenharmony_ci	full_mask = s->eqcr.pi_ci_mask;
65962306a36Sopenharmony_ci
66062306a36Sopenharmony_ci	if (!s->eqcr.available) {
66162306a36Sopenharmony_ci		eqcr_ci = s->eqcr.ci;
66262306a36Sopenharmony_ci		p = s->addr_cena + QBMAN_CENA_SWP_EQCR_CI;
66362306a36Sopenharmony_ci		s->eqcr.ci = qbman_read_register(s, QBMAN_CINH_SWP_EQCR_CI);
66462306a36Sopenharmony_ci		s->eqcr.ci &= full_mask;
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_ci		s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size,
66762306a36Sopenharmony_ci					eqcr_ci, s->eqcr.ci);
66862306a36Sopenharmony_ci		if (!s->eqcr.available) {
66962306a36Sopenharmony_ci			spin_unlock(&s->access_spinlock);
67062306a36Sopenharmony_ci			return 0;
67162306a36Sopenharmony_ci		}
67262306a36Sopenharmony_ci	}
67362306a36Sopenharmony_ci
67462306a36Sopenharmony_ci	eqcr_pi = s->eqcr.pi;
67562306a36Sopenharmony_ci	num_enqueued = (s->eqcr.available < num_frames) ?
67662306a36Sopenharmony_ci			s->eqcr.available : num_frames;
67762306a36Sopenharmony_ci	s->eqcr.available -= num_enqueued;
67862306a36Sopenharmony_ci	/* Fill in the EQCR ring */
67962306a36Sopenharmony_ci	for (i = 0; i < num_enqueued; i++) {
68062306a36Sopenharmony_ci		p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
68162306a36Sopenharmony_ci		/* Skip copying the verb */
68262306a36Sopenharmony_ci		memcpy(&p[1], &cl[1], EQ_DESC_SIZE_WITHOUT_FD - 1);
68362306a36Sopenharmony_ci		memcpy(&p[EQ_DESC_SIZE_FD_START/sizeof(uint32_t)],
68462306a36Sopenharmony_ci		       &fd[i], sizeof(*fd));
68562306a36Sopenharmony_ci		eqcr_pi++;
68662306a36Sopenharmony_ci	}
68762306a36Sopenharmony_ci
68862306a36Sopenharmony_ci	dma_wmb();
68962306a36Sopenharmony_ci
69062306a36Sopenharmony_ci	/* Set the verb byte, have to substitute in the valid-bit */
69162306a36Sopenharmony_ci	eqcr_pi = s->eqcr.pi;
69262306a36Sopenharmony_ci	for (i = 0; i < num_enqueued; i++) {
69362306a36Sopenharmony_ci		p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
69462306a36Sopenharmony_ci		p[0] = cl[0] | s->eqcr.pi_vb;
69562306a36Sopenharmony_ci		if (flags && (flags[i] & QBMAN_ENQUEUE_FLAG_DCA)) {
69662306a36Sopenharmony_ci			struct qbman_eq_desc *eq_desc = (struct qbman_eq_desc *)p;
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_ci			eq_desc->dca = (1 << QB_ENQUEUE_CMD_DCA_EN_SHIFT) |
69962306a36Sopenharmony_ci				((flags[i]) & QBMAN_EQCR_DCA_IDXMASK);
70062306a36Sopenharmony_ci		}
70162306a36Sopenharmony_ci		eqcr_pi++;
70262306a36Sopenharmony_ci		if (!(eqcr_pi & half_mask))
70362306a36Sopenharmony_ci			s->eqcr.pi_vb ^= QB_VALID_BIT;
70462306a36Sopenharmony_ci	}
70562306a36Sopenharmony_ci
70662306a36Sopenharmony_ci	/* Flush all the cacheline without load/store in between */
70762306a36Sopenharmony_ci	eqcr_pi = s->eqcr.pi;
70862306a36Sopenharmony_ci	for (i = 0; i < num_enqueued; i++)
70962306a36Sopenharmony_ci		eqcr_pi++;
71062306a36Sopenharmony_ci	s->eqcr.pi = eqcr_pi & full_mask;
71162306a36Sopenharmony_ci	spin_unlock(&s->access_spinlock);
71262306a36Sopenharmony_ci
71362306a36Sopenharmony_ci	return num_enqueued;
71462306a36Sopenharmony_ci}
71562306a36Sopenharmony_ci
71662306a36Sopenharmony_ci/**
71762306a36Sopenharmony_ci * qbman_swp_enqueue_multiple_mem_back() - Issue a multi enqueue command
71862306a36Sopenharmony_ci * using one enqueue descriptor
71962306a36Sopenharmony_ci * @s:  the software portal used for enqueue
72062306a36Sopenharmony_ci * @d:  the enqueue descriptor
72162306a36Sopenharmony_ci * @fd: table pointer of frame descriptor table to be enqueued
72262306a36Sopenharmony_ci * @flags: table pointer of QBMAN_ENQUEUE_FLAG_DCA flags, not used if NULL
72362306a36Sopenharmony_ci * @num_frames: number of fd to be enqueued
72462306a36Sopenharmony_ci *
72562306a36Sopenharmony_ci * Return the number of fd enqueued, or a negative error number.
72662306a36Sopenharmony_ci */
72762306a36Sopenharmony_cistatic
72862306a36Sopenharmony_ciint qbman_swp_enqueue_multiple_mem_back(struct qbman_swp *s,
72962306a36Sopenharmony_ci					const struct qbman_eq_desc *d,
73062306a36Sopenharmony_ci					const struct dpaa2_fd *fd,
73162306a36Sopenharmony_ci					uint32_t *flags,
73262306a36Sopenharmony_ci					int num_frames)
73362306a36Sopenharmony_ci{
73462306a36Sopenharmony_ci	uint32_t *p = NULL;
73562306a36Sopenharmony_ci	const uint32_t *cl = (uint32_t *)(d);
73662306a36Sopenharmony_ci	uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask;
73762306a36Sopenharmony_ci	int i, num_enqueued = 0;
73862306a36Sopenharmony_ci	unsigned long irq_flags;
73962306a36Sopenharmony_ci
74062306a36Sopenharmony_ci	spin_lock_irqsave(&s->access_spinlock, irq_flags);
74162306a36Sopenharmony_ci
74262306a36Sopenharmony_ci	half_mask = (s->eqcr.pi_ci_mask>>1);
74362306a36Sopenharmony_ci	full_mask = s->eqcr.pi_ci_mask;
74462306a36Sopenharmony_ci	if (!s->eqcr.available) {
74562306a36Sopenharmony_ci		eqcr_ci = s->eqcr.ci;
74662306a36Sopenharmony_ci		s->eqcr.ci = qbman_read_register(s, QBMAN_CINH_SWP_EQCR_CI);
74762306a36Sopenharmony_ci		s->eqcr.ci &= full_mask;
74862306a36Sopenharmony_ci		s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size,
74962306a36Sopenharmony_ci					eqcr_ci, s->eqcr.ci);
75062306a36Sopenharmony_ci		if (!s->eqcr.available) {
75162306a36Sopenharmony_ci			spin_unlock_irqrestore(&s->access_spinlock, irq_flags);
75262306a36Sopenharmony_ci			return 0;
75362306a36Sopenharmony_ci		}
75462306a36Sopenharmony_ci	}
75562306a36Sopenharmony_ci
75662306a36Sopenharmony_ci	eqcr_pi = s->eqcr.pi;
75762306a36Sopenharmony_ci	num_enqueued = (s->eqcr.available < num_frames) ?
75862306a36Sopenharmony_ci			s->eqcr.available : num_frames;
75962306a36Sopenharmony_ci	s->eqcr.available -= num_enqueued;
76062306a36Sopenharmony_ci	/* Fill in the EQCR ring */
76162306a36Sopenharmony_ci	for (i = 0; i < num_enqueued; i++) {
76262306a36Sopenharmony_ci		p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
76362306a36Sopenharmony_ci		/* Skip copying the verb */
76462306a36Sopenharmony_ci		memcpy(&p[1], &cl[1], EQ_DESC_SIZE_WITHOUT_FD - 1);
76562306a36Sopenharmony_ci		memcpy(&p[EQ_DESC_SIZE_FD_START/sizeof(uint32_t)],
76662306a36Sopenharmony_ci		       &fd[i], sizeof(*fd));
76762306a36Sopenharmony_ci		eqcr_pi++;
76862306a36Sopenharmony_ci	}
76962306a36Sopenharmony_ci
77062306a36Sopenharmony_ci	/* Set the verb byte, have to substitute in the valid-bit */
77162306a36Sopenharmony_ci	eqcr_pi = s->eqcr.pi;
77262306a36Sopenharmony_ci	for (i = 0; i < num_enqueued; i++) {
77362306a36Sopenharmony_ci		p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
77462306a36Sopenharmony_ci		p[0] = cl[0] | s->eqcr.pi_vb;
77562306a36Sopenharmony_ci		if (flags && (flags[i] & QBMAN_ENQUEUE_FLAG_DCA)) {
77662306a36Sopenharmony_ci			struct qbman_eq_desc *eq_desc = (struct qbman_eq_desc *)p;
77762306a36Sopenharmony_ci
77862306a36Sopenharmony_ci			eq_desc->dca = (1 << QB_ENQUEUE_CMD_DCA_EN_SHIFT) |
77962306a36Sopenharmony_ci				((flags[i]) & QBMAN_EQCR_DCA_IDXMASK);
78062306a36Sopenharmony_ci		}
78162306a36Sopenharmony_ci		eqcr_pi++;
78262306a36Sopenharmony_ci		if (!(eqcr_pi & half_mask))
78362306a36Sopenharmony_ci			s->eqcr.pi_vb ^= QB_VALID_BIT;
78462306a36Sopenharmony_ci	}
78562306a36Sopenharmony_ci	s->eqcr.pi = eqcr_pi & full_mask;
78662306a36Sopenharmony_ci
78762306a36Sopenharmony_ci	dma_wmb();
78862306a36Sopenharmony_ci	qbman_write_register(s, QBMAN_CINH_SWP_EQCR_PI,
78962306a36Sopenharmony_ci				(QB_RT_BIT)|(s->eqcr.pi)|s->eqcr.pi_vb);
79062306a36Sopenharmony_ci	spin_unlock_irqrestore(&s->access_spinlock, irq_flags);
79162306a36Sopenharmony_ci
79262306a36Sopenharmony_ci	return num_enqueued;
79362306a36Sopenharmony_ci}
79462306a36Sopenharmony_ci
79562306a36Sopenharmony_ci/**
79662306a36Sopenharmony_ci * qbman_swp_enqueue_multiple_desc_direct() - Issue a multi enqueue command
79762306a36Sopenharmony_ci * using multiple enqueue descriptor
79862306a36Sopenharmony_ci * @s:  the software portal used for enqueue
79962306a36Sopenharmony_ci * @d:  table of minimal enqueue descriptor
80062306a36Sopenharmony_ci * @fd: table pointer of frame descriptor table to be enqueued
80162306a36Sopenharmony_ci * @num_frames: number of fd to be enqueued
80262306a36Sopenharmony_ci *
80362306a36Sopenharmony_ci * Return the number of fd enqueued, or a negative error number.
80462306a36Sopenharmony_ci */
80562306a36Sopenharmony_cistatic
80662306a36Sopenharmony_ciint qbman_swp_enqueue_multiple_desc_direct(struct qbman_swp *s,
80762306a36Sopenharmony_ci					   const struct qbman_eq_desc *d,
80862306a36Sopenharmony_ci					   const struct dpaa2_fd *fd,
80962306a36Sopenharmony_ci					   int num_frames)
81062306a36Sopenharmony_ci{
81162306a36Sopenharmony_ci	uint32_t *p;
81262306a36Sopenharmony_ci	const uint32_t *cl;
81362306a36Sopenharmony_ci	uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask;
81462306a36Sopenharmony_ci	int i, num_enqueued = 0;
81562306a36Sopenharmony_ci
81662306a36Sopenharmony_ci	half_mask = (s->eqcr.pi_ci_mask>>1);
81762306a36Sopenharmony_ci	full_mask = s->eqcr.pi_ci_mask;
81862306a36Sopenharmony_ci	if (!s->eqcr.available) {
81962306a36Sopenharmony_ci		eqcr_ci = s->eqcr.ci;
82062306a36Sopenharmony_ci		p = s->addr_cena + QBMAN_CENA_SWP_EQCR_CI;
82162306a36Sopenharmony_ci		s->eqcr.ci = qbman_read_register(s, QBMAN_CINH_SWP_EQCR_CI);
82262306a36Sopenharmony_ci		s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size,
82362306a36Sopenharmony_ci					eqcr_ci, s->eqcr.ci);
82462306a36Sopenharmony_ci		if (!s->eqcr.available)
82562306a36Sopenharmony_ci			return 0;
82662306a36Sopenharmony_ci	}
82762306a36Sopenharmony_ci
82862306a36Sopenharmony_ci	eqcr_pi = s->eqcr.pi;
82962306a36Sopenharmony_ci	num_enqueued = (s->eqcr.available < num_frames) ?
83062306a36Sopenharmony_ci			s->eqcr.available : num_frames;
83162306a36Sopenharmony_ci	s->eqcr.available -= num_enqueued;
83262306a36Sopenharmony_ci	/* Fill in the EQCR ring */
83362306a36Sopenharmony_ci	for (i = 0; i < num_enqueued; i++) {
83462306a36Sopenharmony_ci		p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
83562306a36Sopenharmony_ci		cl = (uint32_t *)(&d[i]);
83662306a36Sopenharmony_ci		/* Skip copying the verb */
83762306a36Sopenharmony_ci		memcpy(&p[1], &cl[1], EQ_DESC_SIZE_WITHOUT_FD - 1);
83862306a36Sopenharmony_ci		memcpy(&p[EQ_DESC_SIZE_FD_START/sizeof(uint32_t)],
83962306a36Sopenharmony_ci		       &fd[i], sizeof(*fd));
84062306a36Sopenharmony_ci		eqcr_pi++;
84162306a36Sopenharmony_ci	}
84262306a36Sopenharmony_ci
84362306a36Sopenharmony_ci	dma_wmb();
84462306a36Sopenharmony_ci
84562306a36Sopenharmony_ci	/* Set the verb byte, have to substitute in the valid-bit */
84662306a36Sopenharmony_ci	eqcr_pi = s->eqcr.pi;
84762306a36Sopenharmony_ci	for (i = 0; i < num_enqueued; i++) {
84862306a36Sopenharmony_ci		p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
84962306a36Sopenharmony_ci		cl = (uint32_t *)(&d[i]);
85062306a36Sopenharmony_ci		p[0] = cl[0] | s->eqcr.pi_vb;
85162306a36Sopenharmony_ci		eqcr_pi++;
85262306a36Sopenharmony_ci		if (!(eqcr_pi & half_mask))
85362306a36Sopenharmony_ci			s->eqcr.pi_vb ^= QB_VALID_BIT;
85462306a36Sopenharmony_ci	}
85562306a36Sopenharmony_ci
85662306a36Sopenharmony_ci	/* Flush all the cacheline without load/store in between */
85762306a36Sopenharmony_ci	eqcr_pi = s->eqcr.pi;
85862306a36Sopenharmony_ci	for (i = 0; i < num_enqueued; i++)
85962306a36Sopenharmony_ci		eqcr_pi++;
86062306a36Sopenharmony_ci	s->eqcr.pi = eqcr_pi & full_mask;
86162306a36Sopenharmony_ci
86262306a36Sopenharmony_ci	return num_enqueued;
86362306a36Sopenharmony_ci}
86462306a36Sopenharmony_ci
86562306a36Sopenharmony_ci/**
86662306a36Sopenharmony_ci * qbman_swp_enqueue_multiple_desc_mem_back() - Issue a multi enqueue command
86762306a36Sopenharmony_ci * using multiple enqueue descriptor
86862306a36Sopenharmony_ci * @s:  the software portal used for enqueue
86962306a36Sopenharmony_ci * @d:  table of minimal enqueue descriptor
87062306a36Sopenharmony_ci * @fd: table pointer of frame descriptor table to be enqueued
87162306a36Sopenharmony_ci * @num_frames: number of fd to be enqueued
87262306a36Sopenharmony_ci *
87362306a36Sopenharmony_ci * Return the number of fd enqueued, or a negative error number.
87462306a36Sopenharmony_ci */
87562306a36Sopenharmony_cistatic
87662306a36Sopenharmony_ciint qbman_swp_enqueue_multiple_desc_mem_back(struct qbman_swp *s,
87762306a36Sopenharmony_ci					   const struct qbman_eq_desc *d,
87862306a36Sopenharmony_ci					   const struct dpaa2_fd *fd,
87962306a36Sopenharmony_ci					   int num_frames)
88062306a36Sopenharmony_ci{
88162306a36Sopenharmony_ci	uint32_t *p;
88262306a36Sopenharmony_ci	const uint32_t *cl;
88362306a36Sopenharmony_ci	uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask;
88462306a36Sopenharmony_ci	int i, num_enqueued = 0;
88562306a36Sopenharmony_ci
88662306a36Sopenharmony_ci	half_mask = (s->eqcr.pi_ci_mask>>1);
88762306a36Sopenharmony_ci	full_mask = s->eqcr.pi_ci_mask;
88862306a36Sopenharmony_ci	if (!s->eqcr.available) {
88962306a36Sopenharmony_ci		eqcr_ci = s->eqcr.ci;
89062306a36Sopenharmony_ci		s->eqcr.ci = qbman_read_register(s, QBMAN_CINH_SWP_EQCR_CI);
89162306a36Sopenharmony_ci		s->eqcr.ci &= full_mask;
89262306a36Sopenharmony_ci		s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size,
89362306a36Sopenharmony_ci					eqcr_ci, s->eqcr.ci);
89462306a36Sopenharmony_ci		if (!s->eqcr.available)
89562306a36Sopenharmony_ci			return 0;
89662306a36Sopenharmony_ci	}
89762306a36Sopenharmony_ci
89862306a36Sopenharmony_ci	eqcr_pi = s->eqcr.pi;
89962306a36Sopenharmony_ci	num_enqueued = (s->eqcr.available < num_frames) ?
90062306a36Sopenharmony_ci			s->eqcr.available : num_frames;
90162306a36Sopenharmony_ci	s->eqcr.available -= num_enqueued;
90262306a36Sopenharmony_ci	/* Fill in the EQCR ring */
90362306a36Sopenharmony_ci	for (i = 0; i < num_enqueued; i++) {
90462306a36Sopenharmony_ci		p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
90562306a36Sopenharmony_ci		cl = (uint32_t *)(&d[i]);
90662306a36Sopenharmony_ci		/* Skip copying the verb */
90762306a36Sopenharmony_ci		memcpy(&p[1], &cl[1], EQ_DESC_SIZE_WITHOUT_FD - 1);
90862306a36Sopenharmony_ci		memcpy(&p[EQ_DESC_SIZE_FD_START/sizeof(uint32_t)],
90962306a36Sopenharmony_ci		       &fd[i], sizeof(*fd));
91062306a36Sopenharmony_ci		eqcr_pi++;
91162306a36Sopenharmony_ci	}
91262306a36Sopenharmony_ci
91362306a36Sopenharmony_ci	/* Set the verb byte, have to substitute in the valid-bit */
91462306a36Sopenharmony_ci	eqcr_pi = s->eqcr.pi;
91562306a36Sopenharmony_ci	for (i = 0; i < num_enqueued; i++) {
91662306a36Sopenharmony_ci		p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
91762306a36Sopenharmony_ci		cl = (uint32_t *)(&d[i]);
91862306a36Sopenharmony_ci		p[0] = cl[0] | s->eqcr.pi_vb;
91962306a36Sopenharmony_ci		eqcr_pi++;
92062306a36Sopenharmony_ci		if (!(eqcr_pi & half_mask))
92162306a36Sopenharmony_ci			s->eqcr.pi_vb ^= QB_VALID_BIT;
92262306a36Sopenharmony_ci	}
92362306a36Sopenharmony_ci
92462306a36Sopenharmony_ci	s->eqcr.pi = eqcr_pi & full_mask;
92562306a36Sopenharmony_ci
92662306a36Sopenharmony_ci	dma_wmb();
92762306a36Sopenharmony_ci	qbman_write_register(s, QBMAN_CINH_SWP_EQCR_PI,
92862306a36Sopenharmony_ci				(QB_RT_BIT)|(s->eqcr.pi)|s->eqcr.pi_vb);
92962306a36Sopenharmony_ci
93062306a36Sopenharmony_ci	return num_enqueued;
93162306a36Sopenharmony_ci}
93262306a36Sopenharmony_ci
93362306a36Sopenharmony_ci/* Static (push) dequeue */
93462306a36Sopenharmony_ci
93562306a36Sopenharmony_ci/**
93662306a36Sopenharmony_ci * qbman_swp_push_get() - Get the push dequeue setup
93762306a36Sopenharmony_ci * @s:           the software portal object
93862306a36Sopenharmony_ci * @channel_idx: the channel index to query
93962306a36Sopenharmony_ci * @enabled:     returned boolean to show whether the push dequeue is enabled
94062306a36Sopenharmony_ci *               for the given channel
94162306a36Sopenharmony_ci */
94262306a36Sopenharmony_civoid qbman_swp_push_get(struct qbman_swp *s, u8 channel_idx, int *enabled)
94362306a36Sopenharmony_ci{
94462306a36Sopenharmony_ci	u16 src = (s->sdq >> QB_SDQCR_SRC_SHIFT) & QB_SDQCR_SRC_MASK;
94562306a36Sopenharmony_ci
94662306a36Sopenharmony_ci	WARN_ON(channel_idx > 15);
94762306a36Sopenharmony_ci	*enabled = src | (1 << channel_idx);
94862306a36Sopenharmony_ci}
94962306a36Sopenharmony_ci
95062306a36Sopenharmony_ci/**
95162306a36Sopenharmony_ci * qbman_swp_push_set() - Enable or disable push dequeue
95262306a36Sopenharmony_ci * @s:           the software portal object
95362306a36Sopenharmony_ci * @channel_idx: the channel index (0 to 15)
95462306a36Sopenharmony_ci * @enable:      enable or disable push dequeue
95562306a36Sopenharmony_ci */
95662306a36Sopenharmony_civoid qbman_swp_push_set(struct qbman_swp *s, u8 channel_idx, int enable)
95762306a36Sopenharmony_ci{
95862306a36Sopenharmony_ci	u16 dqsrc;
95962306a36Sopenharmony_ci
96062306a36Sopenharmony_ci	WARN_ON(channel_idx > 15);
96162306a36Sopenharmony_ci	if (enable)
96262306a36Sopenharmony_ci		s->sdq |= 1 << channel_idx;
96362306a36Sopenharmony_ci	else
96462306a36Sopenharmony_ci		s->sdq &= ~(1 << channel_idx);
96562306a36Sopenharmony_ci
96662306a36Sopenharmony_ci	/* Read make the complete src map.  If no channels are enabled
96762306a36Sopenharmony_ci	 * the SDQCR must be 0 or else QMan will assert errors
96862306a36Sopenharmony_ci	 */
96962306a36Sopenharmony_ci	dqsrc = (s->sdq >> QB_SDQCR_SRC_SHIFT) & QB_SDQCR_SRC_MASK;
97062306a36Sopenharmony_ci	if (dqsrc != 0)
97162306a36Sopenharmony_ci		qbman_write_register(s, QBMAN_CINH_SWP_SDQCR, s->sdq);
97262306a36Sopenharmony_ci	else
97362306a36Sopenharmony_ci		qbman_write_register(s, QBMAN_CINH_SWP_SDQCR, 0);
97462306a36Sopenharmony_ci}
97562306a36Sopenharmony_ci
97662306a36Sopenharmony_ci#define QB_VDQCR_VERB_DCT_SHIFT    0
97762306a36Sopenharmony_ci#define QB_VDQCR_VERB_DT_SHIFT     2
97862306a36Sopenharmony_ci#define QB_VDQCR_VERB_RLS_SHIFT    4
97962306a36Sopenharmony_ci#define QB_VDQCR_VERB_WAE_SHIFT    5
98062306a36Sopenharmony_ci
98162306a36Sopenharmony_cienum qb_pull_dt_e {
98262306a36Sopenharmony_ci	qb_pull_dt_channel,
98362306a36Sopenharmony_ci	qb_pull_dt_workqueue,
98462306a36Sopenharmony_ci	qb_pull_dt_framequeue
98562306a36Sopenharmony_ci};
98662306a36Sopenharmony_ci
98762306a36Sopenharmony_ci/**
98862306a36Sopenharmony_ci * qbman_pull_desc_clear() - Clear the contents of a descriptor to
98962306a36Sopenharmony_ci *                           default/starting state
99062306a36Sopenharmony_ci * @d: the pull dequeue descriptor to be cleared
99162306a36Sopenharmony_ci */
99262306a36Sopenharmony_civoid qbman_pull_desc_clear(struct qbman_pull_desc *d)
99362306a36Sopenharmony_ci{
99462306a36Sopenharmony_ci	memset(d, 0, sizeof(*d));
99562306a36Sopenharmony_ci}
99662306a36Sopenharmony_ci
99762306a36Sopenharmony_ci/**
99862306a36Sopenharmony_ci * qbman_pull_desc_set_storage()- Set the pull dequeue storage
99962306a36Sopenharmony_ci * @d:            the pull dequeue descriptor to be set
100062306a36Sopenharmony_ci * @storage:      the pointer of the memory to store the dequeue result
100162306a36Sopenharmony_ci * @storage_phys: the physical address of the storage memory
100262306a36Sopenharmony_ci * @stash:        to indicate whether write allocate is enabled
100362306a36Sopenharmony_ci *
100462306a36Sopenharmony_ci * If not called, or if called with 'storage' as NULL, the result pull dequeues
100562306a36Sopenharmony_ci * will produce results to DQRR. If 'storage' is non-NULL, then results are
100662306a36Sopenharmony_ci * produced to the given memory location (using the DMA address which
100762306a36Sopenharmony_ci * the caller provides in 'storage_phys'), and 'stash' controls whether or not
100862306a36Sopenharmony_ci * those writes to main-memory express a cache-warming attribute.
100962306a36Sopenharmony_ci */
101062306a36Sopenharmony_civoid qbman_pull_desc_set_storage(struct qbman_pull_desc *d,
101162306a36Sopenharmony_ci				 struct dpaa2_dq *storage,
101262306a36Sopenharmony_ci				 dma_addr_t storage_phys,
101362306a36Sopenharmony_ci				 int stash)
101462306a36Sopenharmony_ci{
101562306a36Sopenharmony_ci	/* save the virtual address */
101662306a36Sopenharmony_ci	d->rsp_addr_virt = (u64)(uintptr_t)storage;
101762306a36Sopenharmony_ci
101862306a36Sopenharmony_ci	if (!storage) {
101962306a36Sopenharmony_ci		d->verb &= ~(1 << QB_VDQCR_VERB_RLS_SHIFT);
102062306a36Sopenharmony_ci		return;
102162306a36Sopenharmony_ci	}
102262306a36Sopenharmony_ci	d->verb |= 1 << QB_VDQCR_VERB_RLS_SHIFT;
102362306a36Sopenharmony_ci	if (stash)
102462306a36Sopenharmony_ci		d->verb |= 1 << QB_VDQCR_VERB_WAE_SHIFT;
102562306a36Sopenharmony_ci	else
102662306a36Sopenharmony_ci		d->verb &= ~(1 << QB_VDQCR_VERB_WAE_SHIFT);
102762306a36Sopenharmony_ci
102862306a36Sopenharmony_ci	d->rsp_addr = cpu_to_le64(storage_phys);
102962306a36Sopenharmony_ci}
103062306a36Sopenharmony_ci
103162306a36Sopenharmony_ci/**
103262306a36Sopenharmony_ci * qbman_pull_desc_set_numframes() - Set the number of frames to be dequeued
103362306a36Sopenharmony_ci * @d:         the pull dequeue descriptor to be set
103462306a36Sopenharmony_ci * @numframes: number of frames to be set, must be between 1 and 16, inclusive
103562306a36Sopenharmony_ci */
103662306a36Sopenharmony_civoid qbman_pull_desc_set_numframes(struct qbman_pull_desc *d, u8 numframes)
103762306a36Sopenharmony_ci{
103862306a36Sopenharmony_ci	d->numf = numframes - 1;
103962306a36Sopenharmony_ci}
104062306a36Sopenharmony_ci
104162306a36Sopenharmony_ci/*
104262306a36Sopenharmony_ci * Exactly one of the following descriptor "actions" should be set. (Calling any
104362306a36Sopenharmony_ci * one of these will replace the effect of any prior call to one of these.)
104462306a36Sopenharmony_ci * - pull dequeue from the given frame queue (FQ)
104562306a36Sopenharmony_ci * - pull dequeue from any FQ in the given work queue (WQ)
104662306a36Sopenharmony_ci * - pull dequeue from any FQ in any WQ in the given channel
104762306a36Sopenharmony_ci */
104862306a36Sopenharmony_ci
104962306a36Sopenharmony_ci/**
105062306a36Sopenharmony_ci * qbman_pull_desc_set_fq() - Set fqid from which the dequeue command dequeues
105162306a36Sopenharmony_ci * @d:    the pull dequeue descriptor to be set
105262306a36Sopenharmony_ci * @fqid: the frame queue index of the given FQ
105362306a36Sopenharmony_ci */
105462306a36Sopenharmony_civoid qbman_pull_desc_set_fq(struct qbman_pull_desc *d, u32 fqid)
105562306a36Sopenharmony_ci{
105662306a36Sopenharmony_ci	d->verb |= 1 << QB_VDQCR_VERB_DCT_SHIFT;
105762306a36Sopenharmony_ci	d->verb |= qb_pull_dt_framequeue << QB_VDQCR_VERB_DT_SHIFT;
105862306a36Sopenharmony_ci	d->dq_src = cpu_to_le32(fqid);
105962306a36Sopenharmony_ci}
106062306a36Sopenharmony_ci
106162306a36Sopenharmony_ci/**
106262306a36Sopenharmony_ci * qbman_pull_desc_set_wq() - Set wqid from which the dequeue command dequeues
106362306a36Sopenharmony_ci * @d:    the pull dequeue descriptor to be set
106462306a36Sopenharmony_ci * @wqid: composed of channel id and wqid within the channel
106562306a36Sopenharmony_ci * @dct:  the dequeue command type
106662306a36Sopenharmony_ci */
106762306a36Sopenharmony_civoid qbman_pull_desc_set_wq(struct qbman_pull_desc *d, u32 wqid,
106862306a36Sopenharmony_ci			    enum qbman_pull_type_e dct)
106962306a36Sopenharmony_ci{
107062306a36Sopenharmony_ci	d->verb |= dct << QB_VDQCR_VERB_DCT_SHIFT;
107162306a36Sopenharmony_ci	d->verb |= qb_pull_dt_workqueue << QB_VDQCR_VERB_DT_SHIFT;
107262306a36Sopenharmony_ci	d->dq_src = cpu_to_le32(wqid);
107362306a36Sopenharmony_ci}
107462306a36Sopenharmony_ci
107562306a36Sopenharmony_ci/**
107662306a36Sopenharmony_ci * qbman_pull_desc_set_channel() - Set channelid from which the dequeue command
107762306a36Sopenharmony_ci *                                 dequeues
107862306a36Sopenharmony_ci * @d:    the pull dequeue descriptor to be set
107962306a36Sopenharmony_ci * @chid: the channel id to be dequeued
108062306a36Sopenharmony_ci * @dct:  the dequeue command type
108162306a36Sopenharmony_ci */
108262306a36Sopenharmony_civoid qbman_pull_desc_set_channel(struct qbman_pull_desc *d, u32 chid,
108362306a36Sopenharmony_ci				 enum qbman_pull_type_e dct)
108462306a36Sopenharmony_ci{
108562306a36Sopenharmony_ci	d->verb |= dct << QB_VDQCR_VERB_DCT_SHIFT;
108662306a36Sopenharmony_ci	d->verb |= qb_pull_dt_channel << QB_VDQCR_VERB_DT_SHIFT;
108762306a36Sopenharmony_ci	d->dq_src = cpu_to_le32(chid);
108862306a36Sopenharmony_ci}
108962306a36Sopenharmony_ci
109062306a36Sopenharmony_ci/**
109162306a36Sopenharmony_ci * qbman_swp_pull_direct() - Issue the pull dequeue command
109262306a36Sopenharmony_ci * @s: the software portal object
109362306a36Sopenharmony_ci * @d: the software portal descriptor which has been configured with
109462306a36Sopenharmony_ci *     the set of qbman_pull_desc_set_*() calls
109562306a36Sopenharmony_ci *
109662306a36Sopenharmony_ci * Return 0 for success, and -EBUSY if the software portal is not ready
109762306a36Sopenharmony_ci * to do pull dequeue.
109862306a36Sopenharmony_ci */
109962306a36Sopenharmony_cistatic
110062306a36Sopenharmony_ciint qbman_swp_pull_direct(struct qbman_swp *s, struct qbman_pull_desc *d)
110162306a36Sopenharmony_ci{
110262306a36Sopenharmony_ci	struct qbman_pull_desc *p;
110362306a36Sopenharmony_ci
110462306a36Sopenharmony_ci	if (!atomic_dec_and_test(&s->vdq.available)) {
110562306a36Sopenharmony_ci		atomic_inc(&s->vdq.available);
110662306a36Sopenharmony_ci		return -EBUSY;
110762306a36Sopenharmony_ci	}
110862306a36Sopenharmony_ci	s->vdq.storage = (void *)(uintptr_t)d->rsp_addr_virt;
110962306a36Sopenharmony_ci	if ((s->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000)
111062306a36Sopenharmony_ci		p = qbman_get_cmd(s, QBMAN_CENA_SWP_VDQCR);
111162306a36Sopenharmony_ci	else
111262306a36Sopenharmony_ci		p = qbman_get_cmd(s, QBMAN_CENA_SWP_VDQCR_MEM);
111362306a36Sopenharmony_ci	p->numf = d->numf;
111462306a36Sopenharmony_ci	p->tok = QMAN_DQ_TOKEN_VALID;
111562306a36Sopenharmony_ci	p->dq_src = d->dq_src;
111662306a36Sopenharmony_ci	p->rsp_addr = d->rsp_addr;
111762306a36Sopenharmony_ci	p->rsp_addr_virt = d->rsp_addr_virt;
111862306a36Sopenharmony_ci	dma_wmb();
111962306a36Sopenharmony_ci	/* Set the verb byte, have to substitute in the valid-bit */
112062306a36Sopenharmony_ci	p->verb = d->verb | s->vdq.valid_bit;
112162306a36Sopenharmony_ci	s->vdq.valid_bit ^= QB_VALID_BIT;
112262306a36Sopenharmony_ci
112362306a36Sopenharmony_ci	return 0;
112462306a36Sopenharmony_ci}
112562306a36Sopenharmony_ci
112662306a36Sopenharmony_ci/**
112762306a36Sopenharmony_ci * qbman_swp_pull_mem_back() - Issue the pull dequeue command
112862306a36Sopenharmony_ci * @s: the software portal object
112962306a36Sopenharmony_ci * @d: the software portal descriptor which has been configured with
113062306a36Sopenharmony_ci *     the set of qbman_pull_desc_set_*() calls
113162306a36Sopenharmony_ci *
113262306a36Sopenharmony_ci * Return 0 for success, and -EBUSY if the software portal is not ready
113362306a36Sopenharmony_ci * to do pull dequeue.
113462306a36Sopenharmony_ci */
113562306a36Sopenharmony_cistatic
113662306a36Sopenharmony_ciint qbman_swp_pull_mem_back(struct qbman_swp *s, struct qbman_pull_desc *d)
113762306a36Sopenharmony_ci{
113862306a36Sopenharmony_ci	struct qbman_pull_desc *p;
113962306a36Sopenharmony_ci
114062306a36Sopenharmony_ci	if (!atomic_dec_and_test(&s->vdq.available)) {
114162306a36Sopenharmony_ci		atomic_inc(&s->vdq.available);
114262306a36Sopenharmony_ci		return -EBUSY;
114362306a36Sopenharmony_ci	}
114462306a36Sopenharmony_ci	s->vdq.storage = (void *)(uintptr_t)d->rsp_addr_virt;
114562306a36Sopenharmony_ci	if ((s->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000)
114662306a36Sopenharmony_ci		p = qbman_get_cmd(s, QBMAN_CENA_SWP_VDQCR);
114762306a36Sopenharmony_ci	else
114862306a36Sopenharmony_ci		p = qbman_get_cmd(s, QBMAN_CENA_SWP_VDQCR_MEM);
114962306a36Sopenharmony_ci	p->numf = d->numf;
115062306a36Sopenharmony_ci	p->tok = QMAN_DQ_TOKEN_VALID;
115162306a36Sopenharmony_ci	p->dq_src = d->dq_src;
115262306a36Sopenharmony_ci	p->rsp_addr = d->rsp_addr;
115362306a36Sopenharmony_ci	p->rsp_addr_virt = d->rsp_addr_virt;
115462306a36Sopenharmony_ci
115562306a36Sopenharmony_ci	/* Set the verb byte, have to substitute in the valid-bit */
115662306a36Sopenharmony_ci	p->verb = d->verb | s->vdq.valid_bit;
115762306a36Sopenharmony_ci	s->vdq.valid_bit ^= QB_VALID_BIT;
115862306a36Sopenharmony_ci	dma_wmb();
115962306a36Sopenharmony_ci	qbman_write_register(s, QBMAN_CINH_SWP_VDQCR_RT, QMAN_RT_MODE);
116062306a36Sopenharmony_ci
116162306a36Sopenharmony_ci	return 0;
116262306a36Sopenharmony_ci}
116362306a36Sopenharmony_ci
116462306a36Sopenharmony_ci#define QMAN_DQRR_PI_MASK   0xf
116562306a36Sopenharmony_ci
116662306a36Sopenharmony_ci/**
116762306a36Sopenharmony_ci * qbman_swp_dqrr_next_direct() - Get an valid DQRR entry
116862306a36Sopenharmony_ci * @s: the software portal object
116962306a36Sopenharmony_ci *
117062306a36Sopenharmony_ci * Return NULL if there are no unconsumed DQRR entries. Return a DQRR entry
117162306a36Sopenharmony_ci * only once, so repeated calls can return a sequence of DQRR entries, without
117262306a36Sopenharmony_ci * requiring they be consumed immediately or in any particular order.
117362306a36Sopenharmony_ci */
117462306a36Sopenharmony_ciconst struct dpaa2_dq *qbman_swp_dqrr_next_direct(struct qbman_swp *s)
117562306a36Sopenharmony_ci{
117662306a36Sopenharmony_ci	u32 verb;
117762306a36Sopenharmony_ci	u32 response_verb;
117862306a36Sopenharmony_ci	u32 flags;
117962306a36Sopenharmony_ci	struct dpaa2_dq *p;
118062306a36Sopenharmony_ci
118162306a36Sopenharmony_ci	/* Before using valid-bit to detect if something is there, we have to
118262306a36Sopenharmony_ci	 * handle the case of the DQRR reset bug...
118362306a36Sopenharmony_ci	 */
118462306a36Sopenharmony_ci	if (unlikely(s->dqrr.reset_bug)) {
118562306a36Sopenharmony_ci		/*
118662306a36Sopenharmony_ci		 * We pick up new entries by cache-inhibited producer index,
118762306a36Sopenharmony_ci		 * which means that a non-coherent mapping would require us to
118862306a36Sopenharmony_ci		 * invalidate and read *only* once that PI has indicated that
118962306a36Sopenharmony_ci		 * there's an entry here. The first trip around the DQRR ring
119062306a36Sopenharmony_ci		 * will be much less efficient than all subsequent trips around
119162306a36Sopenharmony_ci		 * it...
119262306a36Sopenharmony_ci		 */
119362306a36Sopenharmony_ci		u8 pi = qbman_read_register(s, QBMAN_CINH_SWP_DQPI) &
119462306a36Sopenharmony_ci			QMAN_DQRR_PI_MASK;
119562306a36Sopenharmony_ci
119662306a36Sopenharmony_ci		/* there are new entries if pi != next_idx */
119762306a36Sopenharmony_ci		if (pi == s->dqrr.next_idx)
119862306a36Sopenharmony_ci			return NULL;
119962306a36Sopenharmony_ci
120062306a36Sopenharmony_ci		/*
120162306a36Sopenharmony_ci		 * if next_idx is/was the last ring index, and 'pi' is
120262306a36Sopenharmony_ci		 * different, we can disable the workaround as all the ring
120362306a36Sopenharmony_ci		 * entries have now been DMA'd to so valid-bit checking is
120462306a36Sopenharmony_ci		 * repaired. Note: this logic needs to be based on next_idx
120562306a36Sopenharmony_ci		 * (which increments one at a time), rather than on pi (which
120662306a36Sopenharmony_ci		 * can burst and wrap-around between our snapshots of it).
120762306a36Sopenharmony_ci		 */
120862306a36Sopenharmony_ci		if (s->dqrr.next_idx == (s->dqrr.dqrr_size - 1)) {
120962306a36Sopenharmony_ci			pr_debug("next_idx=%d, pi=%d, clear reset bug\n",
121062306a36Sopenharmony_ci				 s->dqrr.next_idx, pi);
121162306a36Sopenharmony_ci			s->dqrr.reset_bug = 0;
121262306a36Sopenharmony_ci		}
121362306a36Sopenharmony_ci		prefetch(qbman_get_cmd(s,
121462306a36Sopenharmony_ci				       QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)));
121562306a36Sopenharmony_ci	}
121662306a36Sopenharmony_ci
121762306a36Sopenharmony_ci	p = qbman_get_cmd(s, QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx));
121862306a36Sopenharmony_ci	verb = p->dq.verb;
121962306a36Sopenharmony_ci
122062306a36Sopenharmony_ci	/*
122162306a36Sopenharmony_ci	 * If the valid-bit isn't of the expected polarity, nothing there. Note,
122262306a36Sopenharmony_ci	 * in the DQRR reset bug workaround, we shouldn't need to skip these
122362306a36Sopenharmony_ci	 * check, because we've already determined that a new entry is available
122462306a36Sopenharmony_ci	 * and we've invalidated the cacheline before reading it, so the
122562306a36Sopenharmony_ci	 * valid-bit behaviour is repaired and should tell us what we already
122662306a36Sopenharmony_ci	 * knew from reading PI.
122762306a36Sopenharmony_ci	 */
122862306a36Sopenharmony_ci	if ((verb & QB_VALID_BIT) != s->dqrr.valid_bit) {
122962306a36Sopenharmony_ci		prefetch(qbman_get_cmd(s,
123062306a36Sopenharmony_ci				       QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)));
123162306a36Sopenharmony_ci		return NULL;
123262306a36Sopenharmony_ci	}
123362306a36Sopenharmony_ci	/*
123462306a36Sopenharmony_ci	 * There's something there. Move "next_idx" attention to the next ring
123562306a36Sopenharmony_ci	 * entry (and prefetch it) before returning what we found.
123662306a36Sopenharmony_ci	 */
123762306a36Sopenharmony_ci	s->dqrr.next_idx++;
123862306a36Sopenharmony_ci	s->dqrr.next_idx &= s->dqrr.dqrr_size - 1; /* Wrap around */
123962306a36Sopenharmony_ci	if (!s->dqrr.next_idx)
124062306a36Sopenharmony_ci		s->dqrr.valid_bit ^= QB_VALID_BIT;
124162306a36Sopenharmony_ci
124262306a36Sopenharmony_ci	/*
124362306a36Sopenharmony_ci	 * If this is the final response to a volatile dequeue command
124462306a36Sopenharmony_ci	 * indicate that the vdq is available
124562306a36Sopenharmony_ci	 */
124662306a36Sopenharmony_ci	flags = p->dq.stat;
124762306a36Sopenharmony_ci	response_verb = verb & QBMAN_RESULT_MASK;
124862306a36Sopenharmony_ci	if ((response_verb == QBMAN_RESULT_DQ) &&
124962306a36Sopenharmony_ci	    (flags & DPAA2_DQ_STAT_VOLATILE) &&
125062306a36Sopenharmony_ci	    (flags & DPAA2_DQ_STAT_EXPIRED))
125162306a36Sopenharmony_ci		atomic_inc(&s->vdq.available);
125262306a36Sopenharmony_ci
125362306a36Sopenharmony_ci	prefetch(qbman_get_cmd(s, QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)));
125462306a36Sopenharmony_ci
125562306a36Sopenharmony_ci	return p;
125662306a36Sopenharmony_ci}
125762306a36Sopenharmony_ci
125862306a36Sopenharmony_ci/**
125962306a36Sopenharmony_ci * qbman_swp_dqrr_next_mem_back() - Get an valid DQRR entry
126062306a36Sopenharmony_ci * @s: the software portal object
126162306a36Sopenharmony_ci *
126262306a36Sopenharmony_ci * Return NULL if there are no unconsumed DQRR entries. Return a DQRR entry
126362306a36Sopenharmony_ci * only once, so repeated calls can return a sequence of DQRR entries, without
126462306a36Sopenharmony_ci * requiring they be consumed immediately or in any particular order.
126562306a36Sopenharmony_ci */
126662306a36Sopenharmony_ciconst struct dpaa2_dq *qbman_swp_dqrr_next_mem_back(struct qbman_swp *s)
126762306a36Sopenharmony_ci{
126862306a36Sopenharmony_ci	u32 verb;
126962306a36Sopenharmony_ci	u32 response_verb;
127062306a36Sopenharmony_ci	u32 flags;
127162306a36Sopenharmony_ci	struct dpaa2_dq *p;
127262306a36Sopenharmony_ci
127362306a36Sopenharmony_ci	/* Before using valid-bit to detect if something is there, we have to
127462306a36Sopenharmony_ci	 * handle the case of the DQRR reset bug...
127562306a36Sopenharmony_ci	 */
127662306a36Sopenharmony_ci	if (unlikely(s->dqrr.reset_bug)) {
127762306a36Sopenharmony_ci		/*
127862306a36Sopenharmony_ci		 * We pick up new entries by cache-inhibited producer index,
127962306a36Sopenharmony_ci		 * which means that a non-coherent mapping would require us to
128062306a36Sopenharmony_ci		 * invalidate and read *only* once that PI has indicated that
128162306a36Sopenharmony_ci		 * there's an entry here. The first trip around the DQRR ring
128262306a36Sopenharmony_ci		 * will be much less efficient than all subsequent trips around
128362306a36Sopenharmony_ci		 * it...
128462306a36Sopenharmony_ci		 */
128562306a36Sopenharmony_ci		u8 pi = qbman_read_register(s, QBMAN_CINH_SWP_DQPI) &
128662306a36Sopenharmony_ci			QMAN_DQRR_PI_MASK;
128762306a36Sopenharmony_ci
128862306a36Sopenharmony_ci		/* there are new entries if pi != next_idx */
128962306a36Sopenharmony_ci		if (pi == s->dqrr.next_idx)
129062306a36Sopenharmony_ci			return NULL;
129162306a36Sopenharmony_ci
129262306a36Sopenharmony_ci		/*
129362306a36Sopenharmony_ci		 * if next_idx is/was the last ring index, and 'pi' is
129462306a36Sopenharmony_ci		 * different, we can disable the workaround as all the ring
129562306a36Sopenharmony_ci		 * entries have now been DMA'd to so valid-bit checking is
129662306a36Sopenharmony_ci		 * repaired. Note: this logic needs to be based on next_idx
129762306a36Sopenharmony_ci		 * (which increments one at a time), rather than on pi (which
129862306a36Sopenharmony_ci		 * can burst and wrap-around between our snapshots of it).
129962306a36Sopenharmony_ci		 */
130062306a36Sopenharmony_ci		if (s->dqrr.next_idx == (s->dqrr.dqrr_size - 1)) {
130162306a36Sopenharmony_ci			pr_debug("next_idx=%d, pi=%d, clear reset bug\n",
130262306a36Sopenharmony_ci				 s->dqrr.next_idx, pi);
130362306a36Sopenharmony_ci			s->dqrr.reset_bug = 0;
130462306a36Sopenharmony_ci		}
130562306a36Sopenharmony_ci		prefetch(qbman_get_cmd(s,
130662306a36Sopenharmony_ci				       QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)));
130762306a36Sopenharmony_ci	}
130862306a36Sopenharmony_ci
130962306a36Sopenharmony_ci	p = qbman_get_cmd(s, QBMAN_CENA_SWP_DQRR_MEM(s->dqrr.next_idx));
131062306a36Sopenharmony_ci	verb = p->dq.verb;
131162306a36Sopenharmony_ci
131262306a36Sopenharmony_ci	/*
131362306a36Sopenharmony_ci	 * If the valid-bit isn't of the expected polarity, nothing there. Note,
131462306a36Sopenharmony_ci	 * in the DQRR reset bug workaround, we shouldn't need to skip these
131562306a36Sopenharmony_ci	 * check, because we've already determined that a new entry is available
131662306a36Sopenharmony_ci	 * and we've invalidated the cacheline before reading it, so the
131762306a36Sopenharmony_ci	 * valid-bit behaviour is repaired and should tell us what we already
131862306a36Sopenharmony_ci	 * knew from reading PI.
131962306a36Sopenharmony_ci	 */
132062306a36Sopenharmony_ci	if ((verb & QB_VALID_BIT) != s->dqrr.valid_bit) {
132162306a36Sopenharmony_ci		prefetch(qbman_get_cmd(s,
132262306a36Sopenharmony_ci				       QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)));
132362306a36Sopenharmony_ci		return NULL;
132462306a36Sopenharmony_ci	}
132562306a36Sopenharmony_ci	/*
132662306a36Sopenharmony_ci	 * There's something there. Move "next_idx" attention to the next ring
132762306a36Sopenharmony_ci	 * entry (and prefetch it) before returning what we found.
132862306a36Sopenharmony_ci	 */
132962306a36Sopenharmony_ci	s->dqrr.next_idx++;
133062306a36Sopenharmony_ci	s->dqrr.next_idx &= s->dqrr.dqrr_size - 1; /* Wrap around */
133162306a36Sopenharmony_ci	if (!s->dqrr.next_idx)
133262306a36Sopenharmony_ci		s->dqrr.valid_bit ^= QB_VALID_BIT;
133362306a36Sopenharmony_ci
133462306a36Sopenharmony_ci	/*
133562306a36Sopenharmony_ci	 * If this is the final response to a volatile dequeue command
133662306a36Sopenharmony_ci	 * indicate that the vdq is available
133762306a36Sopenharmony_ci	 */
133862306a36Sopenharmony_ci	flags = p->dq.stat;
133962306a36Sopenharmony_ci	response_verb = verb & QBMAN_RESULT_MASK;
134062306a36Sopenharmony_ci	if ((response_verb == QBMAN_RESULT_DQ) &&
134162306a36Sopenharmony_ci	    (flags & DPAA2_DQ_STAT_VOLATILE) &&
134262306a36Sopenharmony_ci	    (flags & DPAA2_DQ_STAT_EXPIRED))
134362306a36Sopenharmony_ci		atomic_inc(&s->vdq.available);
134462306a36Sopenharmony_ci
134562306a36Sopenharmony_ci	prefetch(qbman_get_cmd(s, QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)));
134662306a36Sopenharmony_ci
134762306a36Sopenharmony_ci	return p;
134862306a36Sopenharmony_ci}
134962306a36Sopenharmony_ci
135062306a36Sopenharmony_ci/**
135162306a36Sopenharmony_ci * qbman_swp_dqrr_consume() -  Consume DQRR entries previously returned from
135262306a36Sopenharmony_ci *                             qbman_swp_dqrr_next().
135362306a36Sopenharmony_ci * @s: the software portal object
135462306a36Sopenharmony_ci * @dq: the DQRR entry to be consumed
135562306a36Sopenharmony_ci */
135662306a36Sopenharmony_civoid qbman_swp_dqrr_consume(struct qbman_swp *s, const struct dpaa2_dq *dq)
135762306a36Sopenharmony_ci{
135862306a36Sopenharmony_ci	qbman_write_register(s, QBMAN_CINH_SWP_DCAP, QBMAN_IDX_FROM_DQRR(dq));
135962306a36Sopenharmony_ci}
136062306a36Sopenharmony_ci
136162306a36Sopenharmony_ci/**
136262306a36Sopenharmony_ci * qbman_result_has_new_result() - Check and get the dequeue response from the
136362306a36Sopenharmony_ci *                                 dq storage memory set in pull dequeue command
136462306a36Sopenharmony_ci * @s: the software portal object
136562306a36Sopenharmony_ci * @dq: the dequeue result read from the memory
136662306a36Sopenharmony_ci *
136762306a36Sopenharmony_ci * Return 1 for getting a valid dequeue result, or 0 for not getting a valid
136862306a36Sopenharmony_ci * dequeue result.
136962306a36Sopenharmony_ci *
137062306a36Sopenharmony_ci * Only used for user-provided storage of dequeue results, not DQRR. For
137162306a36Sopenharmony_ci * efficiency purposes, the driver will perform any required endianness
137262306a36Sopenharmony_ci * conversion to ensure that the user's dequeue result storage is in host-endian
137362306a36Sopenharmony_ci * format. As such, once the user has called qbman_result_has_new_result() and
137462306a36Sopenharmony_ci * been returned a valid dequeue result, they should not call it again on
137562306a36Sopenharmony_ci * the same memory location (except of course if another dequeue command has
137662306a36Sopenharmony_ci * been executed to produce a new result to that location).
137762306a36Sopenharmony_ci */
137862306a36Sopenharmony_ciint qbman_result_has_new_result(struct qbman_swp *s, const struct dpaa2_dq *dq)
137962306a36Sopenharmony_ci{
138062306a36Sopenharmony_ci	if (dq->dq.tok != QMAN_DQ_TOKEN_VALID)
138162306a36Sopenharmony_ci		return 0;
138262306a36Sopenharmony_ci
138362306a36Sopenharmony_ci	/*
138462306a36Sopenharmony_ci	 * Set token to be 0 so we will detect change back to 1
138562306a36Sopenharmony_ci	 * next time the looping is traversed. Const is cast away here
138662306a36Sopenharmony_ci	 * as we want users to treat the dequeue responses as read only.
138762306a36Sopenharmony_ci	 */
138862306a36Sopenharmony_ci	((struct dpaa2_dq *)dq)->dq.tok = 0;
138962306a36Sopenharmony_ci
139062306a36Sopenharmony_ci	/*
139162306a36Sopenharmony_ci	 * Determine whether VDQCR is available based on whether the
139262306a36Sopenharmony_ci	 * current result is sitting in the first storage location of
139362306a36Sopenharmony_ci	 * the busy command.
139462306a36Sopenharmony_ci	 */
139562306a36Sopenharmony_ci	if (s->vdq.storage == dq) {
139662306a36Sopenharmony_ci		s->vdq.storage = NULL;
139762306a36Sopenharmony_ci		atomic_inc(&s->vdq.available);
139862306a36Sopenharmony_ci	}
139962306a36Sopenharmony_ci
140062306a36Sopenharmony_ci	return 1;
140162306a36Sopenharmony_ci}
140262306a36Sopenharmony_ci
140362306a36Sopenharmony_ci/**
140462306a36Sopenharmony_ci * qbman_release_desc_clear() - Clear the contents of a descriptor to
140562306a36Sopenharmony_ci *                              default/starting state.
140662306a36Sopenharmony_ci * @d: the pull dequeue descriptor to be cleared
140762306a36Sopenharmony_ci */
140862306a36Sopenharmony_civoid qbman_release_desc_clear(struct qbman_release_desc *d)
140962306a36Sopenharmony_ci{
141062306a36Sopenharmony_ci	memset(d, 0, sizeof(*d));
141162306a36Sopenharmony_ci	d->verb = 1 << 5; /* Release Command Valid */
141262306a36Sopenharmony_ci}
141362306a36Sopenharmony_ci
141462306a36Sopenharmony_ci/**
141562306a36Sopenharmony_ci * qbman_release_desc_set_bpid() - Set the ID of the buffer pool to release to
141662306a36Sopenharmony_ci * @d:    the pull dequeue descriptor to be set
141762306a36Sopenharmony_ci * @bpid: the bpid value to be set
141862306a36Sopenharmony_ci */
141962306a36Sopenharmony_civoid qbman_release_desc_set_bpid(struct qbman_release_desc *d, u16 bpid)
142062306a36Sopenharmony_ci{
142162306a36Sopenharmony_ci	d->bpid = cpu_to_le16(bpid);
142262306a36Sopenharmony_ci}
142362306a36Sopenharmony_ci
142462306a36Sopenharmony_ci/**
142562306a36Sopenharmony_ci * qbman_release_desc_set_rcdi() - Determines whether or not the portal's RCDI
142662306a36Sopenharmony_ci * interrupt source should be asserted after the release command is completed.
142762306a36Sopenharmony_ci * @d:      the pull dequeue descriptor to be set
142862306a36Sopenharmony_ci * @enable: enable (1) or disable (0) value
142962306a36Sopenharmony_ci */
143062306a36Sopenharmony_civoid qbman_release_desc_set_rcdi(struct qbman_release_desc *d, int enable)
143162306a36Sopenharmony_ci{
143262306a36Sopenharmony_ci	if (enable)
143362306a36Sopenharmony_ci		d->verb |= 1 << 6;
143462306a36Sopenharmony_ci	else
143562306a36Sopenharmony_ci		d->verb &= ~(1 << 6);
143662306a36Sopenharmony_ci}
143762306a36Sopenharmony_ci
143862306a36Sopenharmony_ci#define RAR_IDX(rar)     ((rar) & 0x7)
143962306a36Sopenharmony_ci#define RAR_VB(rar)      ((rar) & 0x80)
144062306a36Sopenharmony_ci#define RAR_SUCCESS(rar) ((rar) & 0x100)
144162306a36Sopenharmony_ci
144262306a36Sopenharmony_ci/**
144362306a36Sopenharmony_ci * qbman_swp_release_direct() - Issue a buffer release command
144462306a36Sopenharmony_ci * @s:           the software portal object
144562306a36Sopenharmony_ci * @d:           the release descriptor
144662306a36Sopenharmony_ci * @buffers:     a pointer pointing to the buffer address to be released
144762306a36Sopenharmony_ci * @num_buffers: number of buffers to be released,  must be less than 8
144862306a36Sopenharmony_ci *
144962306a36Sopenharmony_ci * Return 0 for success, -EBUSY if the release command ring is not ready.
145062306a36Sopenharmony_ci */
145162306a36Sopenharmony_ciint qbman_swp_release_direct(struct qbman_swp *s,
145262306a36Sopenharmony_ci			     const struct qbman_release_desc *d,
145362306a36Sopenharmony_ci			     const u64 *buffers, unsigned int num_buffers)
145462306a36Sopenharmony_ci{
145562306a36Sopenharmony_ci	int i;
145662306a36Sopenharmony_ci	struct qbman_release_desc *p;
145762306a36Sopenharmony_ci	u32 rar;
145862306a36Sopenharmony_ci
145962306a36Sopenharmony_ci	if (!num_buffers || (num_buffers > 7))
146062306a36Sopenharmony_ci		return -EINVAL;
146162306a36Sopenharmony_ci
146262306a36Sopenharmony_ci	rar = qbman_read_register(s, QBMAN_CINH_SWP_RAR);
146362306a36Sopenharmony_ci	if (!RAR_SUCCESS(rar))
146462306a36Sopenharmony_ci		return -EBUSY;
146562306a36Sopenharmony_ci
146662306a36Sopenharmony_ci	/* Start the release command */
146762306a36Sopenharmony_ci	p = qbman_get_cmd(s, QBMAN_CENA_SWP_RCR(RAR_IDX(rar)));
146862306a36Sopenharmony_ci
146962306a36Sopenharmony_ci	/* Copy the caller's buffer pointers to the command */
147062306a36Sopenharmony_ci	for (i = 0; i < num_buffers; i++)
147162306a36Sopenharmony_ci		p->buf[i] = cpu_to_le64(buffers[i]);
147262306a36Sopenharmony_ci	p->bpid = d->bpid;
147362306a36Sopenharmony_ci
147462306a36Sopenharmony_ci	/*
147562306a36Sopenharmony_ci	 * Set the verb byte, have to substitute in the valid-bit
147662306a36Sopenharmony_ci	 * and the number of buffers.
147762306a36Sopenharmony_ci	 */
147862306a36Sopenharmony_ci	dma_wmb();
147962306a36Sopenharmony_ci	p->verb = d->verb | RAR_VB(rar) | num_buffers;
148062306a36Sopenharmony_ci
148162306a36Sopenharmony_ci	return 0;
148262306a36Sopenharmony_ci}
148362306a36Sopenharmony_ci
148462306a36Sopenharmony_ci/**
148562306a36Sopenharmony_ci * qbman_swp_release_mem_back() - Issue a buffer release command
148662306a36Sopenharmony_ci * @s:           the software portal object
148762306a36Sopenharmony_ci * @d:           the release descriptor
148862306a36Sopenharmony_ci * @buffers:     a pointer pointing to the buffer address to be released
148962306a36Sopenharmony_ci * @num_buffers: number of buffers to be released,  must be less than 8
149062306a36Sopenharmony_ci *
149162306a36Sopenharmony_ci * Return 0 for success, -EBUSY if the release command ring is not ready.
149262306a36Sopenharmony_ci */
149362306a36Sopenharmony_ciint qbman_swp_release_mem_back(struct qbman_swp *s,
149462306a36Sopenharmony_ci			       const struct qbman_release_desc *d,
149562306a36Sopenharmony_ci			       const u64 *buffers, unsigned int num_buffers)
149662306a36Sopenharmony_ci{
149762306a36Sopenharmony_ci	int i;
149862306a36Sopenharmony_ci	struct qbman_release_desc *p;
149962306a36Sopenharmony_ci	u32 rar;
150062306a36Sopenharmony_ci
150162306a36Sopenharmony_ci	if (!num_buffers || (num_buffers > 7))
150262306a36Sopenharmony_ci		return -EINVAL;
150362306a36Sopenharmony_ci
150462306a36Sopenharmony_ci	rar = qbman_read_register(s, QBMAN_CINH_SWP_RAR);
150562306a36Sopenharmony_ci	if (!RAR_SUCCESS(rar))
150662306a36Sopenharmony_ci		return -EBUSY;
150762306a36Sopenharmony_ci
150862306a36Sopenharmony_ci	/* Start the release command */
150962306a36Sopenharmony_ci	p = qbman_get_cmd(s, QBMAN_CENA_SWP_RCR_MEM(RAR_IDX(rar)));
151062306a36Sopenharmony_ci
151162306a36Sopenharmony_ci	/* Copy the caller's buffer pointers to the command */
151262306a36Sopenharmony_ci	for (i = 0; i < num_buffers; i++)
151362306a36Sopenharmony_ci		p->buf[i] = cpu_to_le64(buffers[i]);
151462306a36Sopenharmony_ci	p->bpid = d->bpid;
151562306a36Sopenharmony_ci
151662306a36Sopenharmony_ci	p->verb = d->verb | RAR_VB(rar) | num_buffers;
151762306a36Sopenharmony_ci	dma_wmb();
151862306a36Sopenharmony_ci	qbman_write_register(s, QBMAN_CINH_SWP_RCR_AM_RT +
151962306a36Sopenharmony_ci			     RAR_IDX(rar)  * 4, QMAN_RT_MODE);
152062306a36Sopenharmony_ci
152162306a36Sopenharmony_ci	return 0;
152262306a36Sopenharmony_ci}
152362306a36Sopenharmony_ci
152462306a36Sopenharmony_cistruct qbman_acquire_desc {
152562306a36Sopenharmony_ci	u8 verb;
152662306a36Sopenharmony_ci	u8 reserved;
152762306a36Sopenharmony_ci	__le16 bpid;
152862306a36Sopenharmony_ci	u8 num;
152962306a36Sopenharmony_ci	u8 reserved2[59];
153062306a36Sopenharmony_ci};
153162306a36Sopenharmony_ci
153262306a36Sopenharmony_cistruct qbman_acquire_rslt {
153362306a36Sopenharmony_ci	u8 verb;
153462306a36Sopenharmony_ci	u8 rslt;
153562306a36Sopenharmony_ci	__le16 reserved;
153662306a36Sopenharmony_ci	u8 num;
153762306a36Sopenharmony_ci	u8 reserved2[3];
153862306a36Sopenharmony_ci	__le64 buf[7];
153962306a36Sopenharmony_ci};
154062306a36Sopenharmony_ci
154162306a36Sopenharmony_ci/**
154262306a36Sopenharmony_ci * qbman_swp_acquire() - Issue a buffer acquire command
154362306a36Sopenharmony_ci * @s:           the software portal object
154462306a36Sopenharmony_ci * @bpid:        the buffer pool index
154562306a36Sopenharmony_ci * @buffers:     a pointer pointing to the acquired buffer addresses
154662306a36Sopenharmony_ci * @num_buffers: number of buffers to be acquired, must be less than 8
154762306a36Sopenharmony_ci *
154862306a36Sopenharmony_ci * Return 0 for success, or negative error code if the acquire command
154962306a36Sopenharmony_ci * fails.
155062306a36Sopenharmony_ci */
155162306a36Sopenharmony_ciint qbman_swp_acquire(struct qbman_swp *s, u16 bpid, u64 *buffers,
155262306a36Sopenharmony_ci		      unsigned int num_buffers)
155362306a36Sopenharmony_ci{
155462306a36Sopenharmony_ci	struct qbman_acquire_desc *p;
155562306a36Sopenharmony_ci	struct qbman_acquire_rslt *r;
155662306a36Sopenharmony_ci	int i;
155762306a36Sopenharmony_ci
155862306a36Sopenharmony_ci	if (!num_buffers || (num_buffers > 7))
155962306a36Sopenharmony_ci		return -EINVAL;
156062306a36Sopenharmony_ci
156162306a36Sopenharmony_ci	/* Start the management command */
156262306a36Sopenharmony_ci	p = qbman_swp_mc_start(s);
156362306a36Sopenharmony_ci
156462306a36Sopenharmony_ci	if (!p)
156562306a36Sopenharmony_ci		return -EBUSY;
156662306a36Sopenharmony_ci
156762306a36Sopenharmony_ci	/* Encode the caller-provided attributes */
156862306a36Sopenharmony_ci	p->bpid = cpu_to_le16(bpid);
156962306a36Sopenharmony_ci	p->num = num_buffers;
157062306a36Sopenharmony_ci
157162306a36Sopenharmony_ci	/* Complete the management command */
157262306a36Sopenharmony_ci	r = qbman_swp_mc_complete(s, p, QBMAN_MC_ACQUIRE);
157362306a36Sopenharmony_ci	if (unlikely(!r)) {
157462306a36Sopenharmony_ci		pr_err("qbman: acquire from BPID %d failed, no response\n",
157562306a36Sopenharmony_ci		       bpid);
157662306a36Sopenharmony_ci		return -EIO;
157762306a36Sopenharmony_ci	}
157862306a36Sopenharmony_ci
157962306a36Sopenharmony_ci	/* Decode the outcome */
158062306a36Sopenharmony_ci	WARN_ON((r->verb & 0x7f) != QBMAN_MC_ACQUIRE);
158162306a36Sopenharmony_ci
158262306a36Sopenharmony_ci	/* Determine success or failure */
158362306a36Sopenharmony_ci	if (unlikely(r->rslt != QBMAN_MC_RSLT_OK)) {
158462306a36Sopenharmony_ci		pr_err("qbman: acquire from BPID 0x%x failed, code=0x%02x\n",
158562306a36Sopenharmony_ci		       bpid, r->rslt);
158662306a36Sopenharmony_ci		return -EIO;
158762306a36Sopenharmony_ci	}
158862306a36Sopenharmony_ci
158962306a36Sopenharmony_ci	WARN_ON(r->num > num_buffers);
159062306a36Sopenharmony_ci
159162306a36Sopenharmony_ci	/* Copy the acquired buffers to the caller's array */
159262306a36Sopenharmony_ci	for (i = 0; i < r->num; i++)
159362306a36Sopenharmony_ci		buffers[i] = le64_to_cpu(r->buf[i]);
159462306a36Sopenharmony_ci
159562306a36Sopenharmony_ci	return (int)r->num;
159662306a36Sopenharmony_ci}
159762306a36Sopenharmony_ci
159862306a36Sopenharmony_cistruct qbman_alt_fq_state_desc {
159962306a36Sopenharmony_ci	u8 verb;
160062306a36Sopenharmony_ci	u8 reserved[3];
160162306a36Sopenharmony_ci	__le32 fqid;
160262306a36Sopenharmony_ci	u8 reserved2[56];
160362306a36Sopenharmony_ci};
160462306a36Sopenharmony_ci
160562306a36Sopenharmony_cistruct qbman_alt_fq_state_rslt {
160662306a36Sopenharmony_ci	u8 verb;
160762306a36Sopenharmony_ci	u8 rslt;
160862306a36Sopenharmony_ci	u8 reserved[62];
160962306a36Sopenharmony_ci};
161062306a36Sopenharmony_ci
161162306a36Sopenharmony_ci#define ALT_FQ_FQID_MASK 0x00FFFFFF
161262306a36Sopenharmony_ci
161362306a36Sopenharmony_ciint qbman_swp_alt_fq_state(struct qbman_swp *s, u32 fqid,
161462306a36Sopenharmony_ci			   u8 alt_fq_verb)
161562306a36Sopenharmony_ci{
161662306a36Sopenharmony_ci	struct qbman_alt_fq_state_desc *p;
161762306a36Sopenharmony_ci	struct qbman_alt_fq_state_rslt *r;
161862306a36Sopenharmony_ci
161962306a36Sopenharmony_ci	/* Start the management command */
162062306a36Sopenharmony_ci	p = qbman_swp_mc_start(s);
162162306a36Sopenharmony_ci	if (!p)
162262306a36Sopenharmony_ci		return -EBUSY;
162362306a36Sopenharmony_ci
162462306a36Sopenharmony_ci	p->fqid = cpu_to_le32(fqid & ALT_FQ_FQID_MASK);
162562306a36Sopenharmony_ci
162662306a36Sopenharmony_ci	/* Complete the management command */
162762306a36Sopenharmony_ci	r = qbman_swp_mc_complete(s, p, alt_fq_verb);
162862306a36Sopenharmony_ci	if (unlikely(!r)) {
162962306a36Sopenharmony_ci		pr_err("qbman: mgmt cmd failed, no response (verb=0x%x)\n",
163062306a36Sopenharmony_ci		       alt_fq_verb);
163162306a36Sopenharmony_ci		return -EIO;
163262306a36Sopenharmony_ci	}
163362306a36Sopenharmony_ci
163462306a36Sopenharmony_ci	/* Decode the outcome */
163562306a36Sopenharmony_ci	WARN_ON((r->verb & QBMAN_RESULT_MASK) != alt_fq_verb);
163662306a36Sopenharmony_ci
163762306a36Sopenharmony_ci	/* Determine success or failure */
163862306a36Sopenharmony_ci	if (unlikely(r->rslt != QBMAN_MC_RSLT_OK)) {
163962306a36Sopenharmony_ci		pr_err("qbman: ALT FQID %d failed: verb = 0x%08x code = 0x%02x\n",
164062306a36Sopenharmony_ci		       fqid, r->verb, r->rslt);
164162306a36Sopenharmony_ci		return -EIO;
164262306a36Sopenharmony_ci	}
164362306a36Sopenharmony_ci
164462306a36Sopenharmony_ci	return 0;
164562306a36Sopenharmony_ci}
164662306a36Sopenharmony_ci
164762306a36Sopenharmony_cistruct qbman_cdan_ctrl_desc {
164862306a36Sopenharmony_ci	u8 verb;
164962306a36Sopenharmony_ci	u8 reserved;
165062306a36Sopenharmony_ci	__le16 ch;
165162306a36Sopenharmony_ci	u8 we;
165262306a36Sopenharmony_ci	u8 ctrl;
165362306a36Sopenharmony_ci	__le16 reserved2;
165462306a36Sopenharmony_ci	__le64 cdan_ctx;
165562306a36Sopenharmony_ci	u8 reserved3[48];
165662306a36Sopenharmony_ci
165762306a36Sopenharmony_ci};
165862306a36Sopenharmony_ci
165962306a36Sopenharmony_cistruct qbman_cdan_ctrl_rslt {
166062306a36Sopenharmony_ci	u8 verb;
166162306a36Sopenharmony_ci	u8 rslt;
166262306a36Sopenharmony_ci	__le16 ch;
166362306a36Sopenharmony_ci	u8 reserved[60];
166462306a36Sopenharmony_ci};
166562306a36Sopenharmony_ci
166662306a36Sopenharmony_ciint qbman_swp_CDAN_set(struct qbman_swp *s, u16 channelid,
166762306a36Sopenharmony_ci		       u8 we_mask, u8 cdan_en,
166862306a36Sopenharmony_ci		       u64 ctx)
166962306a36Sopenharmony_ci{
167062306a36Sopenharmony_ci	struct qbman_cdan_ctrl_desc *p = NULL;
167162306a36Sopenharmony_ci	struct qbman_cdan_ctrl_rslt *r = NULL;
167262306a36Sopenharmony_ci
167362306a36Sopenharmony_ci	/* Start the management command */
167462306a36Sopenharmony_ci	p = qbman_swp_mc_start(s);
167562306a36Sopenharmony_ci	if (!p)
167662306a36Sopenharmony_ci		return -EBUSY;
167762306a36Sopenharmony_ci
167862306a36Sopenharmony_ci	/* Encode the caller-provided attributes */
167962306a36Sopenharmony_ci	p->ch = cpu_to_le16(channelid);
168062306a36Sopenharmony_ci	p->we = we_mask;
168162306a36Sopenharmony_ci	if (cdan_en)
168262306a36Sopenharmony_ci		p->ctrl = 1;
168362306a36Sopenharmony_ci	else
168462306a36Sopenharmony_ci		p->ctrl = 0;
168562306a36Sopenharmony_ci	p->cdan_ctx = cpu_to_le64(ctx);
168662306a36Sopenharmony_ci
168762306a36Sopenharmony_ci	/* Complete the management command */
168862306a36Sopenharmony_ci	r = qbman_swp_mc_complete(s, p, QBMAN_WQCHAN_CONFIGURE);
168962306a36Sopenharmony_ci	if (unlikely(!r)) {
169062306a36Sopenharmony_ci		pr_err("qbman: wqchan config failed, no response\n");
169162306a36Sopenharmony_ci		return -EIO;
169262306a36Sopenharmony_ci	}
169362306a36Sopenharmony_ci
169462306a36Sopenharmony_ci	WARN_ON((r->verb & 0x7f) != QBMAN_WQCHAN_CONFIGURE);
169562306a36Sopenharmony_ci
169662306a36Sopenharmony_ci	/* Determine success or failure */
169762306a36Sopenharmony_ci	if (unlikely(r->rslt != QBMAN_MC_RSLT_OK)) {
169862306a36Sopenharmony_ci		pr_err("qbman: CDAN cQID %d failed: code = 0x%02x\n",
169962306a36Sopenharmony_ci		       channelid, r->rslt);
170062306a36Sopenharmony_ci		return -EIO;
170162306a36Sopenharmony_ci	}
170262306a36Sopenharmony_ci
170362306a36Sopenharmony_ci	return 0;
170462306a36Sopenharmony_ci}
170562306a36Sopenharmony_ci
170662306a36Sopenharmony_ci#define QBMAN_RESPONSE_VERB_MASK	0x7f
170762306a36Sopenharmony_ci#define QBMAN_FQ_QUERY_NP		0x45
170862306a36Sopenharmony_ci#define QBMAN_BP_QUERY			0x32
170962306a36Sopenharmony_ci
171062306a36Sopenharmony_cistruct qbman_fq_query_desc {
171162306a36Sopenharmony_ci	u8 verb;
171262306a36Sopenharmony_ci	u8 reserved[3];
171362306a36Sopenharmony_ci	__le32 fqid;
171462306a36Sopenharmony_ci	u8 reserved2[56];
171562306a36Sopenharmony_ci};
171662306a36Sopenharmony_ci
171762306a36Sopenharmony_ciint qbman_fq_query_state(struct qbman_swp *s, u32 fqid,
171862306a36Sopenharmony_ci			 struct qbman_fq_query_np_rslt *r)
171962306a36Sopenharmony_ci{
172062306a36Sopenharmony_ci	struct qbman_fq_query_desc *p;
172162306a36Sopenharmony_ci	void *resp;
172262306a36Sopenharmony_ci
172362306a36Sopenharmony_ci	p = (struct qbman_fq_query_desc *)qbman_swp_mc_start(s);
172462306a36Sopenharmony_ci	if (!p)
172562306a36Sopenharmony_ci		return -EBUSY;
172662306a36Sopenharmony_ci
172762306a36Sopenharmony_ci	/* FQID is a 24 bit value */
172862306a36Sopenharmony_ci	p->fqid = cpu_to_le32(fqid & 0x00FFFFFF);
172962306a36Sopenharmony_ci	resp = qbman_swp_mc_complete(s, p, QBMAN_FQ_QUERY_NP);
173062306a36Sopenharmony_ci	if (!resp) {
173162306a36Sopenharmony_ci		pr_err("qbman: Query FQID %d NP fields failed, no response\n",
173262306a36Sopenharmony_ci		       fqid);
173362306a36Sopenharmony_ci		return -EIO;
173462306a36Sopenharmony_ci	}
173562306a36Sopenharmony_ci	*r = *(struct qbman_fq_query_np_rslt *)resp;
173662306a36Sopenharmony_ci	/* Decode the outcome */
173762306a36Sopenharmony_ci	WARN_ON((r->verb & QBMAN_RESPONSE_VERB_MASK) != QBMAN_FQ_QUERY_NP);
173862306a36Sopenharmony_ci
173962306a36Sopenharmony_ci	/* Determine success or failure */
174062306a36Sopenharmony_ci	if (r->rslt != QBMAN_MC_RSLT_OK) {
174162306a36Sopenharmony_ci		pr_err("Query NP fields of FQID 0x%x failed, code=0x%02x\n",
174262306a36Sopenharmony_ci		       p->fqid, r->rslt);
174362306a36Sopenharmony_ci		return -EIO;
174462306a36Sopenharmony_ci	}
174562306a36Sopenharmony_ci
174662306a36Sopenharmony_ci	return 0;
174762306a36Sopenharmony_ci}
174862306a36Sopenharmony_ci
174962306a36Sopenharmony_ciu32 qbman_fq_state_frame_count(const struct qbman_fq_query_np_rslt *r)
175062306a36Sopenharmony_ci{
175162306a36Sopenharmony_ci	return (le32_to_cpu(r->frm_cnt) & 0x00FFFFFF);
175262306a36Sopenharmony_ci}
175362306a36Sopenharmony_ci
175462306a36Sopenharmony_ciu32 qbman_fq_state_byte_count(const struct qbman_fq_query_np_rslt *r)
175562306a36Sopenharmony_ci{
175662306a36Sopenharmony_ci	return le32_to_cpu(r->byte_cnt);
175762306a36Sopenharmony_ci}
175862306a36Sopenharmony_ci
175962306a36Sopenharmony_cistruct qbman_bp_query_desc {
176062306a36Sopenharmony_ci	u8 verb;
176162306a36Sopenharmony_ci	u8 reserved;
176262306a36Sopenharmony_ci	__le16 bpid;
176362306a36Sopenharmony_ci	u8 reserved2[60];
176462306a36Sopenharmony_ci};
176562306a36Sopenharmony_ci
176662306a36Sopenharmony_ciint qbman_bp_query(struct qbman_swp *s, u16 bpid,
176762306a36Sopenharmony_ci		   struct qbman_bp_query_rslt *r)
176862306a36Sopenharmony_ci{
176962306a36Sopenharmony_ci	struct qbman_bp_query_desc *p;
177062306a36Sopenharmony_ci	void *resp;
177162306a36Sopenharmony_ci
177262306a36Sopenharmony_ci	p = (struct qbman_bp_query_desc *)qbman_swp_mc_start(s);
177362306a36Sopenharmony_ci	if (!p)
177462306a36Sopenharmony_ci		return -EBUSY;
177562306a36Sopenharmony_ci
177662306a36Sopenharmony_ci	p->bpid = cpu_to_le16(bpid);
177762306a36Sopenharmony_ci	resp = qbman_swp_mc_complete(s, p, QBMAN_BP_QUERY);
177862306a36Sopenharmony_ci	if (!resp) {
177962306a36Sopenharmony_ci		pr_err("qbman: Query BPID %d fields failed, no response\n",
178062306a36Sopenharmony_ci		       bpid);
178162306a36Sopenharmony_ci		return -EIO;
178262306a36Sopenharmony_ci	}
178362306a36Sopenharmony_ci	*r = *(struct qbman_bp_query_rslt *)resp;
178462306a36Sopenharmony_ci	/* Decode the outcome */
178562306a36Sopenharmony_ci	WARN_ON((r->verb & QBMAN_RESPONSE_VERB_MASK) != QBMAN_BP_QUERY);
178662306a36Sopenharmony_ci
178762306a36Sopenharmony_ci	/* Determine success or failure */
178862306a36Sopenharmony_ci	if (r->rslt != QBMAN_MC_RSLT_OK) {
178962306a36Sopenharmony_ci		pr_err("Query fields of BPID 0x%x failed, code=0x%02x\n",
179062306a36Sopenharmony_ci		       bpid, r->rslt);
179162306a36Sopenharmony_ci		return -EIO;
179262306a36Sopenharmony_ci	}
179362306a36Sopenharmony_ci
179462306a36Sopenharmony_ci	return 0;
179562306a36Sopenharmony_ci}
179662306a36Sopenharmony_ci
179762306a36Sopenharmony_ciu32 qbman_bp_info_num_free_bufs(struct qbman_bp_query_rslt *a)
179862306a36Sopenharmony_ci{
179962306a36Sopenharmony_ci	return le32_to_cpu(a->fill);
180062306a36Sopenharmony_ci}
180162306a36Sopenharmony_ci
180262306a36Sopenharmony_ci/**
180362306a36Sopenharmony_ci * qbman_swp_set_irq_coalescing() - Set new IRQ coalescing values
180462306a36Sopenharmony_ci * @p: the software portal object
180562306a36Sopenharmony_ci * @irq_threshold: interrupt threshold
180662306a36Sopenharmony_ci * @irq_holdoff: interrupt holdoff (timeout) period in us
180762306a36Sopenharmony_ci *
180862306a36Sopenharmony_ci * Return 0 for success, or negative error code on error.
180962306a36Sopenharmony_ci */
181062306a36Sopenharmony_ciint qbman_swp_set_irq_coalescing(struct qbman_swp *p, u32 irq_threshold,
181162306a36Sopenharmony_ci				 u32 irq_holdoff)
181262306a36Sopenharmony_ci{
181362306a36Sopenharmony_ci	u32 itp, max_holdoff;
181462306a36Sopenharmony_ci
181562306a36Sopenharmony_ci	/* Convert irq_holdoff value from usecs to 256 QBMAN clock cycles
181662306a36Sopenharmony_ci	 * increments. This depends on the QBMAN internal frequency.
181762306a36Sopenharmony_ci	 */
181862306a36Sopenharmony_ci	itp = (irq_holdoff * 1000) / p->desc->qman_256_cycles_per_ns;
181962306a36Sopenharmony_ci	if (itp > 4096) {
182062306a36Sopenharmony_ci		max_holdoff = (p->desc->qman_256_cycles_per_ns * 4096) / 1000;
182162306a36Sopenharmony_ci		pr_err("irq_holdoff must be <= %uus\n", max_holdoff);
182262306a36Sopenharmony_ci		return -EINVAL;
182362306a36Sopenharmony_ci	}
182462306a36Sopenharmony_ci
182562306a36Sopenharmony_ci	if (irq_threshold >= p->dqrr.dqrr_size) {
182662306a36Sopenharmony_ci		pr_err("irq_threshold must be < %u\n", p->dqrr.dqrr_size - 1);
182762306a36Sopenharmony_ci		return -EINVAL;
182862306a36Sopenharmony_ci	}
182962306a36Sopenharmony_ci
183062306a36Sopenharmony_ci	p->irq_threshold = irq_threshold;
183162306a36Sopenharmony_ci	p->irq_holdoff = irq_holdoff;
183262306a36Sopenharmony_ci
183362306a36Sopenharmony_ci	qbman_write_register(p, QBMAN_CINH_SWP_DQRR_ITR, irq_threshold);
183462306a36Sopenharmony_ci	qbman_write_register(p, QBMAN_CINH_SWP_ITPR, itp);
183562306a36Sopenharmony_ci
183662306a36Sopenharmony_ci	return 0;
183762306a36Sopenharmony_ci}
183862306a36Sopenharmony_ci
183962306a36Sopenharmony_ci/**
184062306a36Sopenharmony_ci * qbman_swp_get_irq_coalescing() - Get the current IRQ coalescing parameters
184162306a36Sopenharmony_ci * @p: the software portal object
184262306a36Sopenharmony_ci * @irq_threshold: interrupt threshold (an IRQ is generated when there are more
184362306a36Sopenharmony_ci * DQRR entries in the portal than the threshold)
184462306a36Sopenharmony_ci * @irq_holdoff: interrupt holdoff (timeout) period in us
184562306a36Sopenharmony_ci */
184662306a36Sopenharmony_civoid qbman_swp_get_irq_coalescing(struct qbman_swp *p, u32 *irq_threshold,
184762306a36Sopenharmony_ci				  u32 *irq_holdoff)
184862306a36Sopenharmony_ci{
184962306a36Sopenharmony_ci	if (irq_threshold)
185062306a36Sopenharmony_ci		*irq_threshold = p->irq_threshold;
185162306a36Sopenharmony_ci	if (irq_holdoff)
185262306a36Sopenharmony_ci		*irq_holdoff = p->irq_holdoff;
185362306a36Sopenharmony_ci}
1854