162306a36Sopenharmony_ci/* Copyright 2008 - 2016 Freescale Semiconductor, Inc. 262306a36Sopenharmony_ci * 362306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 462306a36Sopenharmony_ci * modification, are permitted provided that the following conditions are met: 562306a36Sopenharmony_ci * * Redistributions of source code must retain the above copyright 662306a36Sopenharmony_ci * notice, this list of conditions and the following disclaimer. 762306a36Sopenharmony_ci * * Redistributions in binary form must reproduce the above copyright 862306a36Sopenharmony_ci * notice, this list of conditions and the following disclaimer in the 962306a36Sopenharmony_ci * documentation and/or other materials provided with the distribution. 1062306a36Sopenharmony_ci * * Neither the name of Freescale Semiconductor nor the 1162306a36Sopenharmony_ci * names of its contributors may be used to endorse or promote products 1262306a36Sopenharmony_ci * derived from this software without specific prior written permission. 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * ALTERNATIVELY, this software may be distributed under the terms of the 1562306a36Sopenharmony_ci * GNU General Public License ("GPL") as published by the Free Software 1662306a36Sopenharmony_ci * Foundation, either version 2 of that License or (at your option) any 1762306a36Sopenharmony_ci * later version. 1862306a36Sopenharmony_ci * 1962306a36Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY 2062306a36Sopenharmony_ci * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 2162306a36Sopenharmony_ci * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 2262306a36Sopenharmony_ci * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY 2362306a36Sopenharmony_ci * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 2462306a36Sopenharmony_ci * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 2562306a36Sopenharmony_ci * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 2662306a36Sopenharmony_ci * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2762306a36Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 2862306a36Sopenharmony_ci * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2962306a36Sopenharmony_ci */ 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#include "bman_priv.h" 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#define IRQNAME "BMan portal %d" 3462306a36Sopenharmony_ci#define MAX_IRQNAME 16 /* big enough for "BMan portal %d" */ 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci/* Portal register assists */ 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#if defined(CONFIG_ARM) || defined(CONFIG_ARM64) 3962306a36Sopenharmony_ci/* Cache-inhibited register offsets */ 4062306a36Sopenharmony_ci#define BM_REG_RCR_PI_CINH 0x3000 4162306a36Sopenharmony_ci#define BM_REG_RCR_CI_CINH 0x3100 4262306a36Sopenharmony_ci#define BM_REG_RCR_ITR 0x3200 4362306a36Sopenharmony_ci#define BM_REG_CFG 0x3300 4462306a36Sopenharmony_ci#define BM_REG_SCN(n) (0x3400 + ((n) << 6)) 4562306a36Sopenharmony_ci#define BM_REG_ISR 0x3e00 4662306a36Sopenharmony_ci#define BM_REG_IER 0x3e40 4762306a36Sopenharmony_ci#define BM_REG_ISDR 0x3e80 4862306a36Sopenharmony_ci#define BM_REG_IIR 0x3ec0 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci/* Cache-enabled register offsets */ 5162306a36Sopenharmony_ci#define BM_CL_CR 0x0000 5262306a36Sopenharmony_ci#define BM_CL_RR0 0x0100 5362306a36Sopenharmony_ci#define BM_CL_RR1 0x0140 5462306a36Sopenharmony_ci#define BM_CL_RCR 0x1000 5562306a36Sopenharmony_ci#define BM_CL_RCR_PI_CENA 0x3000 5662306a36Sopenharmony_ci#define BM_CL_RCR_CI_CENA 0x3100 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci#else 5962306a36Sopenharmony_ci/* Cache-inhibited register offsets */ 6062306a36Sopenharmony_ci#define BM_REG_RCR_PI_CINH 0x0000 6162306a36Sopenharmony_ci#define BM_REG_RCR_CI_CINH 0x0004 6262306a36Sopenharmony_ci#define BM_REG_RCR_ITR 0x0008 6362306a36Sopenharmony_ci#define BM_REG_CFG 0x0100 6462306a36Sopenharmony_ci#define BM_REG_SCN(n) (0x0200 + ((n) << 2)) 6562306a36Sopenharmony_ci#define BM_REG_ISR 0x0e00 6662306a36Sopenharmony_ci#define BM_REG_IER 0x0e04 6762306a36Sopenharmony_ci#define BM_REG_ISDR 0x0e08 6862306a36Sopenharmony_ci#define BM_REG_IIR 0x0e0c 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci/* Cache-enabled register offsets */ 7162306a36Sopenharmony_ci#define BM_CL_CR 0x0000 7262306a36Sopenharmony_ci#define BM_CL_RR0 0x0100 7362306a36Sopenharmony_ci#define BM_CL_RR1 0x0140 7462306a36Sopenharmony_ci#define BM_CL_RCR 0x1000 7562306a36Sopenharmony_ci#define BM_CL_RCR_PI_CENA 0x3000 7662306a36Sopenharmony_ci#define BM_CL_RCR_CI_CENA 0x3100 7762306a36Sopenharmony_ci#endif 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci/* 8062306a36Sopenharmony_ci * Portal modes. 8162306a36Sopenharmony_ci * Enum types; 8262306a36Sopenharmony_ci * pmode == production mode 8362306a36Sopenharmony_ci * cmode == consumption mode, 8462306a36Sopenharmony_ci * Enum values use 3 letter codes. First letter matches the portal mode, 8562306a36Sopenharmony_ci * remaining two letters indicate; 8662306a36Sopenharmony_ci * ci == cache-inhibited portal register 8762306a36Sopenharmony_ci * ce == cache-enabled portal register 8862306a36Sopenharmony_ci * vb == in-band valid-bit (cache-enabled) 8962306a36Sopenharmony_ci */ 9062306a36Sopenharmony_cienum bm_rcr_pmode { /* matches BCSP_CFG::RPM */ 9162306a36Sopenharmony_ci bm_rcr_pci = 0, /* PI index, cache-inhibited */ 9262306a36Sopenharmony_ci bm_rcr_pce = 1, /* PI index, cache-enabled */ 9362306a36Sopenharmony_ci bm_rcr_pvb = 2 /* valid-bit */ 9462306a36Sopenharmony_ci}; 9562306a36Sopenharmony_cienum bm_rcr_cmode { /* s/w-only */ 9662306a36Sopenharmony_ci bm_rcr_cci, /* CI index, cache-inhibited */ 9762306a36Sopenharmony_ci bm_rcr_cce /* CI index, cache-enabled */ 9862306a36Sopenharmony_ci}; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci/* --- Portal structures --- */ 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci#define BM_RCR_SIZE 8 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci/* Release Command */ 10662306a36Sopenharmony_cistruct bm_rcr_entry { 10762306a36Sopenharmony_ci union { 10862306a36Sopenharmony_ci struct { 10962306a36Sopenharmony_ci u8 _ncw_verb; /* writes to this are non-coherent */ 11062306a36Sopenharmony_ci u8 bpid; /* used with BM_RCR_VERB_CMD_BPID_SINGLE */ 11162306a36Sopenharmony_ci u8 __reserved1[62]; 11262306a36Sopenharmony_ci }; 11362306a36Sopenharmony_ci struct bm_buffer bufs[8]; 11462306a36Sopenharmony_ci }; 11562306a36Sopenharmony_ci}; 11662306a36Sopenharmony_ci#define BM_RCR_VERB_VBIT 0x80 11762306a36Sopenharmony_ci#define BM_RCR_VERB_CMD_MASK 0x70 /* one of two values; */ 11862306a36Sopenharmony_ci#define BM_RCR_VERB_CMD_BPID_SINGLE 0x20 11962306a36Sopenharmony_ci#define BM_RCR_VERB_CMD_BPID_MULTI 0x30 12062306a36Sopenharmony_ci#define BM_RCR_VERB_BUFCOUNT_MASK 0x0f /* values 1..8 */ 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_cistruct bm_rcr { 12362306a36Sopenharmony_ci struct bm_rcr_entry *ring, *cursor; 12462306a36Sopenharmony_ci u8 ci, available, ithresh, vbit; 12562306a36Sopenharmony_ci#ifdef CONFIG_FSL_DPAA_CHECKING 12662306a36Sopenharmony_ci u32 busy; 12762306a36Sopenharmony_ci enum bm_rcr_pmode pmode; 12862306a36Sopenharmony_ci enum bm_rcr_cmode cmode; 12962306a36Sopenharmony_ci#endif 13062306a36Sopenharmony_ci}; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci/* MC (Management Command) command */ 13362306a36Sopenharmony_cistruct bm_mc_command { 13462306a36Sopenharmony_ci u8 _ncw_verb; /* writes to this are non-coherent */ 13562306a36Sopenharmony_ci u8 bpid; /* used by acquire command */ 13662306a36Sopenharmony_ci u8 __reserved[62]; 13762306a36Sopenharmony_ci}; 13862306a36Sopenharmony_ci#define BM_MCC_VERB_VBIT 0x80 13962306a36Sopenharmony_ci#define BM_MCC_VERB_CMD_MASK 0x70 /* where the verb contains; */ 14062306a36Sopenharmony_ci#define BM_MCC_VERB_CMD_ACQUIRE 0x10 14162306a36Sopenharmony_ci#define BM_MCC_VERB_CMD_QUERY 0x40 14262306a36Sopenharmony_ci#define BM_MCC_VERB_ACQUIRE_BUFCOUNT 0x0f /* values 1..8 go here */ 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci/* MC result, Acquire and Query Response */ 14562306a36Sopenharmony_ciunion bm_mc_result { 14662306a36Sopenharmony_ci struct { 14762306a36Sopenharmony_ci u8 verb; 14862306a36Sopenharmony_ci u8 bpid; 14962306a36Sopenharmony_ci u8 __reserved[62]; 15062306a36Sopenharmony_ci }; 15162306a36Sopenharmony_ci struct bm_buffer bufs[8]; 15262306a36Sopenharmony_ci}; 15362306a36Sopenharmony_ci#define BM_MCR_VERB_VBIT 0x80 15462306a36Sopenharmony_ci#define BM_MCR_VERB_CMD_MASK BM_MCC_VERB_CMD_MASK 15562306a36Sopenharmony_ci#define BM_MCR_VERB_CMD_ACQUIRE BM_MCC_VERB_CMD_ACQUIRE 15662306a36Sopenharmony_ci#define BM_MCR_VERB_CMD_QUERY BM_MCC_VERB_CMD_QUERY 15762306a36Sopenharmony_ci#define BM_MCR_VERB_CMD_ERR_INVALID 0x60 15862306a36Sopenharmony_ci#define BM_MCR_VERB_CMD_ERR_ECC 0x70 15962306a36Sopenharmony_ci#define BM_MCR_VERB_ACQUIRE_BUFCOUNT BM_MCC_VERB_ACQUIRE_BUFCOUNT /* 0..8 */ 16062306a36Sopenharmony_ci#define BM_MCR_TIMEOUT 10000 /* us */ 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_cistruct bm_mc { 16362306a36Sopenharmony_ci struct bm_mc_command *cr; 16462306a36Sopenharmony_ci union bm_mc_result *rr; 16562306a36Sopenharmony_ci u8 rridx, vbit; 16662306a36Sopenharmony_ci#ifdef CONFIG_FSL_DPAA_CHECKING 16762306a36Sopenharmony_ci enum { 16862306a36Sopenharmony_ci /* Can only be _mc_start()ed */ 16962306a36Sopenharmony_ci mc_idle, 17062306a36Sopenharmony_ci /* Can only be _mc_commit()ed or _mc_abort()ed */ 17162306a36Sopenharmony_ci mc_user, 17262306a36Sopenharmony_ci /* Can only be _mc_retry()ed */ 17362306a36Sopenharmony_ci mc_hw 17462306a36Sopenharmony_ci } state; 17562306a36Sopenharmony_ci#endif 17662306a36Sopenharmony_ci}; 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_cistruct bm_addr { 17962306a36Sopenharmony_ci void *ce; /* cache-enabled */ 18062306a36Sopenharmony_ci __be32 *ce_be; /* Same as above but for direct access */ 18162306a36Sopenharmony_ci void __iomem *ci; /* cache-inhibited */ 18262306a36Sopenharmony_ci}; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_cistruct bm_portal { 18562306a36Sopenharmony_ci struct bm_addr addr; 18662306a36Sopenharmony_ci struct bm_rcr rcr; 18762306a36Sopenharmony_ci struct bm_mc mc; 18862306a36Sopenharmony_ci} ____cacheline_aligned; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci/* Cache-inhibited register access. */ 19162306a36Sopenharmony_cistatic inline u32 bm_in(struct bm_portal *p, u32 offset) 19262306a36Sopenharmony_ci{ 19362306a36Sopenharmony_ci return ioread32be(p->addr.ci + offset); 19462306a36Sopenharmony_ci} 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_cistatic inline void bm_out(struct bm_portal *p, u32 offset, u32 val) 19762306a36Sopenharmony_ci{ 19862306a36Sopenharmony_ci iowrite32be(val, p->addr.ci + offset); 19962306a36Sopenharmony_ci} 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci/* Cache Enabled Portal Access */ 20262306a36Sopenharmony_cistatic inline void bm_cl_invalidate(struct bm_portal *p, u32 offset) 20362306a36Sopenharmony_ci{ 20462306a36Sopenharmony_ci dpaa_invalidate(p->addr.ce + offset); 20562306a36Sopenharmony_ci} 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_cistatic inline void bm_cl_touch_ro(struct bm_portal *p, u32 offset) 20862306a36Sopenharmony_ci{ 20962306a36Sopenharmony_ci dpaa_touch_ro(p->addr.ce + offset); 21062306a36Sopenharmony_ci} 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_cistatic inline u32 bm_ce_in(struct bm_portal *p, u32 offset) 21362306a36Sopenharmony_ci{ 21462306a36Sopenharmony_ci return be32_to_cpu(*(p->addr.ce_be + (offset/4))); 21562306a36Sopenharmony_ci} 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_cistruct bman_portal { 21862306a36Sopenharmony_ci struct bm_portal p; 21962306a36Sopenharmony_ci /* interrupt sources processed by portal_isr(), configurable */ 22062306a36Sopenharmony_ci unsigned long irq_sources; 22162306a36Sopenharmony_ci /* probing time config params for cpu-affine portals */ 22262306a36Sopenharmony_ci const struct bm_portal_config *config; 22362306a36Sopenharmony_ci char irqname[MAX_IRQNAME]; 22462306a36Sopenharmony_ci}; 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_cistatic cpumask_t affine_mask; 22762306a36Sopenharmony_cistatic DEFINE_SPINLOCK(affine_mask_lock); 22862306a36Sopenharmony_cistatic DEFINE_PER_CPU(struct bman_portal, bman_affine_portal); 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_cistatic inline struct bman_portal *get_affine_portal(void) 23162306a36Sopenharmony_ci{ 23262306a36Sopenharmony_ci return &get_cpu_var(bman_affine_portal); 23362306a36Sopenharmony_ci} 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_cistatic inline void put_affine_portal(void) 23662306a36Sopenharmony_ci{ 23762306a36Sopenharmony_ci put_cpu_var(bman_affine_portal); 23862306a36Sopenharmony_ci} 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci/* 24162306a36Sopenharmony_ci * This object type refers to a pool, it isn't *the* pool. There may be 24262306a36Sopenharmony_ci * more than one such object per BMan buffer pool, eg. if different users of the 24362306a36Sopenharmony_ci * pool are operating via different portals. 24462306a36Sopenharmony_ci */ 24562306a36Sopenharmony_cistruct bman_pool { 24662306a36Sopenharmony_ci /* index of the buffer pool to encapsulate (0-63) */ 24762306a36Sopenharmony_ci u32 bpid; 24862306a36Sopenharmony_ci /* Used for hash-table admin when using depletion notifications. */ 24962306a36Sopenharmony_ci struct bman_portal *portal; 25062306a36Sopenharmony_ci struct bman_pool *next; 25162306a36Sopenharmony_ci}; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_cistatic u32 poll_portal_slow(struct bman_portal *p, u32 is); 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_cistatic irqreturn_t portal_isr(int irq, void *ptr) 25662306a36Sopenharmony_ci{ 25762306a36Sopenharmony_ci struct bman_portal *p = ptr; 25862306a36Sopenharmony_ci struct bm_portal *portal = &p->p; 25962306a36Sopenharmony_ci u32 clear = p->irq_sources; 26062306a36Sopenharmony_ci u32 is = bm_in(portal, BM_REG_ISR) & p->irq_sources; 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci if (unlikely(!is)) 26362306a36Sopenharmony_ci return IRQ_NONE; 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci clear |= poll_portal_slow(p, is); 26662306a36Sopenharmony_ci bm_out(portal, BM_REG_ISR, clear); 26762306a36Sopenharmony_ci return IRQ_HANDLED; 26862306a36Sopenharmony_ci} 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci/* --- RCR API --- */ 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci#define RCR_SHIFT ilog2(sizeof(struct bm_rcr_entry)) 27362306a36Sopenharmony_ci#define RCR_CARRY (uintptr_t)(BM_RCR_SIZE << RCR_SHIFT) 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci/* Bit-wise logic to wrap a ring pointer by clearing the "carry bit" */ 27662306a36Sopenharmony_cistatic struct bm_rcr_entry *rcr_carryclear(struct bm_rcr_entry *p) 27762306a36Sopenharmony_ci{ 27862306a36Sopenharmony_ci uintptr_t addr = (uintptr_t)p; 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci addr &= ~RCR_CARRY; 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci return (struct bm_rcr_entry *)addr; 28362306a36Sopenharmony_ci} 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci#ifdef CONFIG_FSL_DPAA_CHECKING 28662306a36Sopenharmony_ci/* Bit-wise logic to convert a ring pointer to a ring index */ 28762306a36Sopenharmony_cistatic int rcr_ptr2idx(struct bm_rcr_entry *e) 28862306a36Sopenharmony_ci{ 28962306a36Sopenharmony_ci return ((uintptr_t)e >> RCR_SHIFT) & (BM_RCR_SIZE - 1); 29062306a36Sopenharmony_ci} 29162306a36Sopenharmony_ci#endif 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci/* Increment the 'cursor' ring pointer, taking 'vbit' into account */ 29462306a36Sopenharmony_cistatic inline void rcr_inc(struct bm_rcr *rcr) 29562306a36Sopenharmony_ci{ 29662306a36Sopenharmony_ci /* increment to the next RCR pointer and handle overflow and 'vbit' */ 29762306a36Sopenharmony_ci struct bm_rcr_entry *partial = rcr->cursor + 1; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci rcr->cursor = rcr_carryclear(partial); 30062306a36Sopenharmony_ci if (partial != rcr->cursor) 30162306a36Sopenharmony_ci rcr->vbit ^= BM_RCR_VERB_VBIT; 30262306a36Sopenharmony_ci} 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_cistatic int bm_rcr_get_avail(struct bm_portal *portal) 30562306a36Sopenharmony_ci{ 30662306a36Sopenharmony_ci struct bm_rcr *rcr = &portal->rcr; 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci return rcr->available; 30962306a36Sopenharmony_ci} 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_cistatic int bm_rcr_get_fill(struct bm_portal *portal) 31262306a36Sopenharmony_ci{ 31362306a36Sopenharmony_ci struct bm_rcr *rcr = &portal->rcr; 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci return BM_RCR_SIZE - 1 - rcr->available; 31662306a36Sopenharmony_ci} 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_cistatic void bm_rcr_set_ithresh(struct bm_portal *portal, u8 ithresh) 31962306a36Sopenharmony_ci{ 32062306a36Sopenharmony_ci struct bm_rcr *rcr = &portal->rcr; 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci rcr->ithresh = ithresh; 32362306a36Sopenharmony_ci bm_out(portal, BM_REG_RCR_ITR, ithresh); 32462306a36Sopenharmony_ci} 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_cistatic void bm_rcr_cce_prefetch(struct bm_portal *portal) 32762306a36Sopenharmony_ci{ 32862306a36Sopenharmony_ci __maybe_unused struct bm_rcr *rcr = &portal->rcr; 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci DPAA_ASSERT(rcr->cmode == bm_rcr_cce); 33162306a36Sopenharmony_ci bm_cl_touch_ro(portal, BM_CL_RCR_CI_CENA); 33262306a36Sopenharmony_ci} 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_cistatic u8 bm_rcr_cce_update(struct bm_portal *portal) 33562306a36Sopenharmony_ci{ 33662306a36Sopenharmony_ci struct bm_rcr *rcr = &portal->rcr; 33762306a36Sopenharmony_ci u8 diff, old_ci = rcr->ci; 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci DPAA_ASSERT(rcr->cmode == bm_rcr_cce); 34062306a36Sopenharmony_ci rcr->ci = bm_ce_in(portal, BM_CL_RCR_CI_CENA) & (BM_RCR_SIZE - 1); 34162306a36Sopenharmony_ci bm_cl_invalidate(portal, BM_CL_RCR_CI_CENA); 34262306a36Sopenharmony_ci diff = dpaa_cyc_diff(BM_RCR_SIZE, old_ci, rcr->ci); 34362306a36Sopenharmony_ci rcr->available += diff; 34462306a36Sopenharmony_ci return diff; 34562306a36Sopenharmony_ci} 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_cistatic inline struct bm_rcr_entry *bm_rcr_start(struct bm_portal *portal) 34862306a36Sopenharmony_ci{ 34962306a36Sopenharmony_ci struct bm_rcr *rcr = &portal->rcr; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci DPAA_ASSERT(!rcr->busy); 35262306a36Sopenharmony_ci if (!rcr->available) 35362306a36Sopenharmony_ci return NULL; 35462306a36Sopenharmony_ci#ifdef CONFIG_FSL_DPAA_CHECKING 35562306a36Sopenharmony_ci rcr->busy = 1; 35662306a36Sopenharmony_ci#endif 35762306a36Sopenharmony_ci dpaa_zero(rcr->cursor); 35862306a36Sopenharmony_ci return rcr->cursor; 35962306a36Sopenharmony_ci} 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_cistatic inline void bm_rcr_pvb_commit(struct bm_portal *portal, u8 myverb) 36262306a36Sopenharmony_ci{ 36362306a36Sopenharmony_ci struct bm_rcr *rcr = &portal->rcr; 36462306a36Sopenharmony_ci struct bm_rcr_entry *rcursor; 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci DPAA_ASSERT(rcr->busy); 36762306a36Sopenharmony_ci DPAA_ASSERT(rcr->pmode == bm_rcr_pvb); 36862306a36Sopenharmony_ci DPAA_ASSERT(rcr->available >= 1); 36962306a36Sopenharmony_ci dma_wmb(); 37062306a36Sopenharmony_ci rcursor = rcr->cursor; 37162306a36Sopenharmony_ci rcursor->_ncw_verb = myverb | rcr->vbit; 37262306a36Sopenharmony_ci dpaa_flush(rcursor); 37362306a36Sopenharmony_ci rcr_inc(rcr); 37462306a36Sopenharmony_ci rcr->available--; 37562306a36Sopenharmony_ci#ifdef CONFIG_FSL_DPAA_CHECKING 37662306a36Sopenharmony_ci rcr->busy = 0; 37762306a36Sopenharmony_ci#endif 37862306a36Sopenharmony_ci} 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_cistatic int bm_rcr_init(struct bm_portal *portal, enum bm_rcr_pmode pmode, 38162306a36Sopenharmony_ci enum bm_rcr_cmode cmode) 38262306a36Sopenharmony_ci{ 38362306a36Sopenharmony_ci struct bm_rcr *rcr = &portal->rcr; 38462306a36Sopenharmony_ci u32 cfg; 38562306a36Sopenharmony_ci u8 pi; 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci rcr->ring = portal->addr.ce + BM_CL_RCR; 38862306a36Sopenharmony_ci rcr->ci = bm_in(portal, BM_REG_RCR_CI_CINH) & (BM_RCR_SIZE - 1); 38962306a36Sopenharmony_ci pi = bm_in(portal, BM_REG_RCR_PI_CINH) & (BM_RCR_SIZE - 1); 39062306a36Sopenharmony_ci rcr->cursor = rcr->ring + pi; 39162306a36Sopenharmony_ci rcr->vbit = (bm_in(portal, BM_REG_RCR_PI_CINH) & BM_RCR_SIZE) ? 39262306a36Sopenharmony_ci BM_RCR_VERB_VBIT : 0; 39362306a36Sopenharmony_ci rcr->available = BM_RCR_SIZE - 1 39462306a36Sopenharmony_ci - dpaa_cyc_diff(BM_RCR_SIZE, rcr->ci, pi); 39562306a36Sopenharmony_ci rcr->ithresh = bm_in(portal, BM_REG_RCR_ITR); 39662306a36Sopenharmony_ci#ifdef CONFIG_FSL_DPAA_CHECKING 39762306a36Sopenharmony_ci rcr->busy = 0; 39862306a36Sopenharmony_ci rcr->pmode = pmode; 39962306a36Sopenharmony_ci rcr->cmode = cmode; 40062306a36Sopenharmony_ci#endif 40162306a36Sopenharmony_ci cfg = (bm_in(portal, BM_REG_CFG) & 0xffffffe0) 40262306a36Sopenharmony_ci | (pmode & 0x3); /* BCSP_CFG::RPM */ 40362306a36Sopenharmony_ci bm_out(portal, BM_REG_CFG, cfg); 40462306a36Sopenharmony_ci return 0; 40562306a36Sopenharmony_ci} 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_cistatic void bm_rcr_finish(struct bm_portal *portal) 40862306a36Sopenharmony_ci{ 40962306a36Sopenharmony_ci#ifdef CONFIG_FSL_DPAA_CHECKING 41062306a36Sopenharmony_ci struct bm_rcr *rcr = &portal->rcr; 41162306a36Sopenharmony_ci int i; 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci DPAA_ASSERT(!rcr->busy); 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci i = bm_in(portal, BM_REG_RCR_PI_CINH) & (BM_RCR_SIZE - 1); 41662306a36Sopenharmony_ci if (i != rcr_ptr2idx(rcr->cursor)) 41762306a36Sopenharmony_ci pr_crit("losing uncommitted RCR entries\n"); 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci i = bm_in(portal, BM_REG_RCR_CI_CINH) & (BM_RCR_SIZE - 1); 42062306a36Sopenharmony_ci if (i != rcr->ci) 42162306a36Sopenharmony_ci pr_crit("missing existing RCR completions\n"); 42262306a36Sopenharmony_ci if (rcr->ci != rcr_ptr2idx(rcr->cursor)) 42362306a36Sopenharmony_ci pr_crit("RCR destroyed unquiesced\n"); 42462306a36Sopenharmony_ci#endif 42562306a36Sopenharmony_ci} 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci/* --- Management command API --- */ 42862306a36Sopenharmony_cistatic int bm_mc_init(struct bm_portal *portal) 42962306a36Sopenharmony_ci{ 43062306a36Sopenharmony_ci struct bm_mc *mc = &portal->mc; 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci mc->cr = portal->addr.ce + BM_CL_CR; 43362306a36Sopenharmony_ci mc->rr = portal->addr.ce + BM_CL_RR0; 43462306a36Sopenharmony_ci mc->rridx = (mc->cr->_ncw_verb & BM_MCC_VERB_VBIT) ? 43562306a36Sopenharmony_ci 0 : 1; 43662306a36Sopenharmony_ci mc->vbit = mc->rridx ? BM_MCC_VERB_VBIT : 0; 43762306a36Sopenharmony_ci#ifdef CONFIG_FSL_DPAA_CHECKING 43862306a36Sopenharmony_ci mc->state = mc_idle; 43962306a36Sopenharmony_ci#endif 44062306a36Sopenharmony_ci return 0; 44162306a36Sopenharmony_ci} 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_cistatic void bm_mc_finish(struct bm_portal *portal) 44462306a36Sopenharmony_ci{ 44562306a36Sopenharmony_ci#ifdef CONFIG_FSL_DPAA_CHECKING 44662306a36Sopenharmony_ci struct bm_mc *mc = &portal->mc; 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci DPAA_ASSERT(mc->state == mc_idle); 44962306a36Sopenharmony_ci if (mc->state != mc_idle) 45062306a36Sopenharmony_ci pr_crit("Losing incomplete MC command\n"); 45162306a36Sopenharmony_ci#endif 45262306a36Sopenharmony_ci} 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_cistatic inline struct bm_mc_command *bm_mc_start(struct bm_portal *portal) 45562306a36Sopenharmony_ci{ 45662306a36Sopenharmony_ci struct bm_mc *mc = &portal->mc; 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci DPAA_ASSERT(mc->state == mc_idle); 45962306a36Sopenharmony_ci#ifdef CONFIG_FSL_DPAA_CHECKING 46062306a36Sopenharmony_ci mc->state = mc_user; 46162306a36Sopenharmony_ci#endif 46262306a36Sopenharmony_ci dpaa_zero(mc->cr); 46362306a36Sopenharmony_ci return mc->cr; 46462306a36Sopenharmony_ci} 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_cistatic inline void bm_mc_commit(struct bm_portal *portal, u8 myverb) 46762306a36Sopenharmony_ci{ 46862306a36Sopenharmony_ci struct bm_mc *mc = &portal->mc; 46962306a36Sopenharmony_ci union bm_mc_result *rr = mc->rr + mc->rridx; 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci DPAA_ASSERT(mc->state == mc_user); 47262306a36Sopenharmony_ci dma_wmb(); 47362306a36Sopenharmony_ci mc->cr->_ncw_verb = myverb | mc->vbit; 47462306a36Sopenharmony_ci dpaa_flush(mc->cr); 47562306a36Sopenharmony_ci dpaa_invalidate_touch_ro(rr); 47662306a36Sopenharmony_ci#ifdef CONFIG_FSL_DPAA_CHECKING 47762306a36Sopenharmony_ci mc->state = mc_hw; 47862306a36Sopenharmony_ci#endif 47962306a36Sopenharmony_ci} 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_cistatic inline union bm_mc_result *bm_mc_result(struct bm_portal *portal) 48262306a36Sopenharmony_ci{ 48362306a36Sopenharmony_ci struct bm_mc *mc = &portal->mc; 48462306a36Sopenharmony_ci union bm_mc_result *rr = mc->rr + mc->rridx; 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci DPAA_ASSERT(mc->state == mc_hw); 48762306a36Sopenharmony_ci /* 48862306a36Sopenharmony_ci * The inactive response register's verb byte always returns zero until 48962306a36Sopenharmony_ci * its command is submitted and completed. This includes the valid-bit, 49062306a36Sopenharmony_ci * in case you were wondering... 49162306a36Sopenharmony_ci */ 49262306a36Sopenharmony_ci if (!rr->verb) { 49362306a36Sopenharmony_ci dpaa_invalidate_touch_ro(rr); 49462306a36Sopenharmony_ci return NULL; 49562306a36Sopenharmony_ci } 49662306a36Sopenharmony_ci mc->rridx ^= 1; 49762306a36Sopenharmony_ci mc->vbit ^= BM_MCC_VERB_VBIT; 49862306a36Sopenharmony_ci#ifdef CONFIG_FSL_DPAA_CHECKING 49962306a36Sopenharmony_ci mc->state = mc_idle; 50062306a36Sopenharmony_ci#endif 50162306a36Sopenharmony_ci return rr; 50262306a36Sopenharmony_ci} 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_cistatic inline int bm_mc_result_timeout(struct bm_portal *portal, 50562306a36Sopenharmony_ci union bm_mc_result **mcr) 50662306a36Sopenharmony_ci{ 50762306a36Sopenharmony_ci int timeout = BM_MCR_TIMEOUT; 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci do { 51062306a36Sopenharmony_ci *mcr = bm_mc_result(portal); 51162306a36Sopenharmony_ci if (*mcr) 51262306a36Sopenharmony_ci break; 51362306a36Sopenharmony_ci udelay(1); 51462306a36Sopenharmony_ci } while (--timeout); 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci return timeout; 51762306a36Sopenharmony_ci} 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci/* Disable all BSCN interrupts for the portal */ 52062306a36Sopenharmony_cistatic void bm_isr_bscn_disable(struct bm_portal *portal) 52162306a36Sopenharmony_ci{ 52262306a36Sopenharmony_ci bm_out(portal, BM_REG_SCN(0), 0); 52362306a36Sopenharmony_ci bm_out(portal, BM_REG_SCN(1), 0); 52462306a36Sopenharmony_ci} 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_cistatic int bman_create_portal(struct bman_portal *portal, 52762306a36Sopenharmony_ci const struct bm_portal_config *c) 52862306a36Sopenharmony_ci{ 52962306a36Sopenharmony_ci struct bm_portal *p; 53062306a36Sopenharmony_ci int ret; 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ci p = &portal->p; 53362306a36Sopenharmony_ci /* 53462306a36Sopenharmony_ci * prep the low-level portal struct with the mapped addresses from the 53562306a36Sopenharmony_ci * config, everything that follows depends on it and "config" is more 53662306a36Sopenharmony_ci * for (de)reference... 53762306a36Sopenharmony_ci */ 53862306a36Sopenharmony_ci p->addr.ce = c->addr_virt_ce; 53962306a36Sopenharmony_ci p->addr.ce_be = c->addr_virt_ce; 54062306a36Sopenharmony_ci p->addr.ci = c->addr_virt_ci; 54162306a36Sopenharmony_ci if (bm_rcr_init(p, bm_rcr_pvb, bm_rcr_cce)) { 54262306a36Sopenharmony_ci dev_err(c->dev, "RCR initialisation failed\n"); 54362306a36Sopenharmony_ci goto fail_rcr; 54462306a36Sopenharmony_ci } 54562306a36Sopenharmony_ci if (bm_mc_init(p)) { 54662306a36Sopenharmony_ci dev_err(c->dev, "MC initialisation failed\n"); 54762306a36Sopenharmony_ci goto fail_mc; 54862306a36Sopenharmony_ci } 54962306a36Sopenharmony_ci /* 55062306a36Sopenharmony_ci * Default to all BPIDs disabled, we enable as required at 55162306a36Sopenharmony_ci * run-time. 55262306a36Sopenharmony_ci */ 55362306a36Sopenharmony_ci bm_isr_bscn_disable(p); 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci /* Write-to-clear any stale interrupt status bits */ 55662306a36Sopenharmony_ci bm_out(p, BM_REG_ISDR, 0xffffffff); 55762306a36Sopenharmony_ci portal->irq_sources = 0; 55862306a36Sopenharmony_ci bm_out(p, BM_REG_IER, 0); 55962306a36Sopenharmony_ci bm_out(p, BM_REG_ISR, 0xffffffff); 56062306a36Sopenharmony_ci snprintf(portal->irqname, MAX_IRQNAME, IRQNAME, c->cpu); 56162306a36Sopenharmony_ci if (request_irq(c->irq, portal_isr, 0, portal->irqname, portal)) { 56262306a36Sopenharmony_ci dev_err(c->dev, "request_irq() failed\n"); 56362306a36Sopenharmony_ci goto fail_irq; 56462306a36Sopenharmony_ci } 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci if (dpaa_set_portal_irq_affinity(c->dev, c->irq, c->cpu)) 56762306a36Sopenharmony_ci goto fail_affinity; 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci /* Need RCR to be empty before continuing */ 57062306a36Sopenharmony_ci ret = bm_rcr_get_fill(p); 57162306a36Sopenharmony_ci if (ret) { 57262306a36Sopenharmony_ci dev_err(c->dev, "RCR unclean\n"); 57362306a36Sopenharmony_ci goto fail_rcr_empty; 57462306a36Sopenharmony_ci } 57562306a36Sopenharmony_ci /* Success */ 57662306a36Sopenharmony_ci portal->config = c; 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci bm_out(p, BM_REG_ISDR, 0); 57962306a36Sopenharmony_ci bm_out(p, BM_REG_IIR, 0); 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci return 0; 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_cifail_rcr_empty: 58462306a36Sopenharmony_cifail_affinity: 58562306a36Sopenharmony_ci free_irq(c->irq, portal); 58662306a36Sopenharmony_cifail_irq: 58762306a36Sopenharmony_ci bm_mc_finish(p); 58862306a36Sopenharmony_cifail_mc: 58962306a36Sopenharmony_ci bm_rcr_finish(p); 59062306a36Sopenharmony_cifail_rcr: 59162306a36Sopenharmony_ci return -EIO; 59262306a36Sopenharmony_ci} 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_cistruct bman_portal *bman_create_affine_portal(const struct bm_portal_config *c) 59562306a36Sopenharmony_ci{ 59662306a36Sopenharmony_ci struct bman_portal *portal; 59762306a36Sopenharmony_ci int err; 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci portal = &per_cpu(bman_affine_portal, c->cpu); 60062306a36Sopenharmony_ci err = bman_create_portal(portal, c); 60162306a36Sopenharmony_ci if (err) 60262306a36Sopenharmony_ci return NULL; 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci spin_lock(&affine_mask_lock); 60562306a36Sopenharmony_ci cpumask_set_cpu(c->cpu, &affine_mask); 60662306a36Sopenharmony_ci spin_unlock(&affine_mask_lock); 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci return portal; 60962306a36Sopenharmony_ci} 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_cistatic u32 poll_portal_slow(struct bman_portal *p, u32 is) 61262306a36Sopenharmony_ci{ 61362306a36Sopenharmony_ci u32 ret = is; 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_ci if (is & BM_PIRQ_RCRI) { 61662306a36Sopenharmony_ci bm_rcr_cce_update(&p->p); 61762306a36Sopenharmony_ci bm_rcr_set_ithresh(&p->p, 0); 61862306a36Sopenharmony_ci bm_out(&p->p, BM_REG_ISR, BM_PIRQ_RCRI); 61962306a36Sopenharmony_ci is &= ~BM_PIRQ_RCRI; 62062306a36Sopenharmony_ci } 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci /* There should be no status register bits left undefined */ 62362306a36Sopenharmony_ci DPAA_ASSERT(!is); 62462306a36Sopenharmony_ci return ret; 62562306a36Sopenharmony_ci} 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ciint bman_p_irqsource_add(struct bman_portal *p, u32 bits) 62862306a36Sopenharmony_ci{ 62962306a36Sopenharmony_ci unsigned long irqflags; 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci local_irq_save(irqflags); 63262306a36Sopenharmony_ci p->irq_sources |= bits & BM_PIRQ_VISIBLE; 63362306a36Sopenharmony_ci bm_out(&p->p, BM_REG_IER, p->irq_sources); 63462306a36Sopenharmony_ci local_irq_restore(irqflags); 63562306a36Sopenharmony_ci return 0; 63662306a36Sopenharmony_ci} 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ciint bm_shutdown_pool(u32 bpid) 63962306a36Sopenharmony_ci{ 64062306a36Sopenharmony_ci int err = 0; 64162306a36Sopenharmony_ci struct bm_mc_command *bm_cmd; 64262306a36Sopenharmony_ci union bm_mc_result *bm_res; 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_ci struct bman_portal *p = get_affine_portal(); 64662306a36Sopenharmony_ci while (1) { 64762306a36Sopenharmony_ci /* Acquire buffers until empty */ 64862306a36Sopenharmony_ci bm_cmd = bm_mc_start(&p->p); 64962306a36Sopenharmony_ci bm_cmd->bpid = bpid; 65062306a36Sopenharmony_ci bm_mc_commit(&p->p, BM_MCC_VERB_CMD_ACQUIRE | 1); 65162306a36Sopenharmony_ci if (!bm_mc_result_timeout(&p->p, &bm_res)) { 65262306a36Sopenharmony_ci pr_crit("BMan Acquire Command timedout\n"); 65362306a36Sopenharmony_ci err = -ETIMEDOUT; 65462306a36Sopenharmony_ci goto done; 65562306a36Sopenharmony_ci } 65662306a36Sopenharmony_ci if (!(bm_res->verb & BM_MCR_VERB_ACQUIRE_BUFCOUNT)) { 65762306a36Sopenharmony_ci /* Pool is empty */ 65862306a36Sopenharmony_ci goto done; 65962306a36Sopenharmony_ci } 66062306a36Sopenharmony_ci } 66162306a36Sopenharmony_cidone: 66262306a36Sopenharmony_ci put_affine_portal(); 66362306a36Sopenharmony_ci return err; 66462306a36Sopenharmony_ci} 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_cistruct gen_pool *bm_bpalloc; 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_cistatic int bm_alloc_bpid_range(u32 *result, u32 count) 66962306a36Sopenharmony_ci{ 67062306a36Sopenharmony_ci unsigned long addr; 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci addr = gen_pool_alloc(bm_bpalloc, count); 67362306a36Sopenharmony_ci if (!addr) 67462306a36Sopenharmony_ci return -ENOMEM; 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_ci *result = addr & ~DPAA_GENALLOC_OFF; 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_ci return 0; 67962306a36Sopenharmony_ci} 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_cistatic int bm_release_bpid(u32 bpid) 68262306a36Sopenharmony_ci{ 68362306a36Sopenharmony_ci int ret; 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_ci ret = bm_shutdown_pool(bpid); 68662306a36Sopenharmony_ci if (ret) { 68762306a36Sopenharmony_ci pr_debug("BPID %d leaked\n", bpid); 68862306a36Sopenharmony_ci return ret; 68962306a36Sopenharmony_ci } 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci gen_pool_free(bm_bpalloc, bpid | DPAA_GENALLOC_OFF, 1); 69262306a36Sopenharmony_ci return 0; 69362306a36Sopenharmony_ci} 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_cistruct bman_pool *bman_new_pool(void) 69662306a36Sopenharmony_ci{ 69762306a36Sopenharmony_ci struct bman_pool *pool = NULL; 69862306a36Sopenharmony_ci u32 bpid; 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci if (bm_alloc_bpid_range(&bpid, 1)) 70162306a36Sopenharmony_ci return NULL; 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_ci pool = kmalloc(sizeof(*pool), GFP_KERNEL); 70462306a36Sopenharmony_ci if (!pool) 70562306a36Sopenharmony_ci goto err; 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci pool->bpid = bpid; 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_ci return pool; 71062306a36Sopenharmony_cierr: 71162306a36Sopenharmony_ci bm_release_bpid(bpid); 71262306a36Sopenharmony_ci return NULL; 71362306a36Sopenharmony_ci} 71462306a36Sopenharmony_ciEXPORT_SYMBOL(bman_new_pool); 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_civoid bman_free_pool(struct bman_pool *pool) 71762306a36Sopenharmony_ci{ 71862306a36Sopenharmony_ci bm_release_bpid(pool->bpid); 71962306a36Sopenharmony_ci 72062306a36Sopenharmony_ci kfree(pool); 72162306a36Sopenharmony_ci} 72262306a36Sopenharmony_ciEXPORT_SYMBOL(bman_free_pool); 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ciint bman_get_bpid(const struct bman_pool *pool) 72562306a36Sopenharmony_ci{ 72662306a36Sopenharmony_ci return pool->bpid; 72762306a36Sopenharmony_ci} 72862306a36Sopenharmony_ciEXPORT_SYMBOL(bman_get_bpid); 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_cistatic void update_rcr_ci(struct bman_portal *p, int avail) 73162306a36Sopenharmony_ci{ 73262306a36Sopenharmony_ci if (avail) 73362306a36Sopenharmony_ci bm_rcr_cce_prefetch(&p->p); 73462306a36Sopenharmony_ci else 73562306a36Sopenharmony_ci bm_rcr_cce_update(&p->p); 73662306a36Sopenharmony_ci} 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ciint bman_release(struct bman_pool *pool, const struct bm_buffer *bufs, u8 num) 73962306a36Sopenharmony_ci{ 74062306a36Sopenharmony_ci struct bman_portal *p; 74162306a36Sopenharmony_ci struct bm_rcr_entry *r; 74262306a36Sopenharmony_ci unsigned long irqflags; 74362306a36Sopenharmony_ci int avail, timeout = 1000; /* 1ms */ 74462306a36Sopenharmony_ci int i = num - 1; 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_ci DPAA_ASSERT(num > 0 && num <= 8); 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_ci do { 74962306a36Sopenharmony_ci p = get_affine_portal(); 75062306a36Sopenharmony_ci local_irq_save(irqflags); 75162306a36Sopenharmony_ci avail = bm_rcr_get_avail(&p->p); 75262306a36Sopenharmony_ci if (avail < 2) 75362306a36Sopenharmony_ci update_rcr_ci(p, avail); 75462306a36Sopenharmony_ci r = bm_rcr_start(&p->p); 75562306a36Sopenharmony_ci local_irq_restore(irqflags); 75662306a36Sopenharmony_ci put_affine_portal(); 75762306a36Sopenharmony_ci if (likely(r)) 75862306a36Sopenharmony_ci break; 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_ci udelay(1); 76162306a36Sopenharmony_ci } while (--timeout); 76262306a36Sopenharmony_ci 76362306a36Sopenharmony_ci if (unlikely(!timeout)) 76462306a36Sopenharmony_ci return -ETIMEDOUT; 76562306a36Sopenharmony_ci 76662306a36Sopenharmony_ci p = get_affine_portal(); 76762306a36Sopenharmony_ci local_irq_save(irqflags); 76862306a36Sopenharmony_ci /* 76962306a36Sopenharmony_ci * we can copy all but the first entry, as this can trigger badness 77062306a36Sopenharmony_ci * with the valid-bit 77162306a36Sopenharmony_ci */ 77262306a36Sopenharmony_ci bm_buffer_set64(r->bufs, bm_buffer_get64(bufs)); 77362306a36Sopenharmony_ci bm_buffer_set_bpid(r->bufs, pool->bpid); 77462306a36Sopenharmony_ci if (i) 77562306a36Sopenharmony_ci memcpy(&r->bufs[1], &bufs[1], i * sizeof(bufs[0])); 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci bm_rcr_pvb_commit(&p->p, BM_RCR_VERB_CMD_BPID_SINGLE | 77862306a36Sopenharmony_ci (num & BM_RCR_VERB_BUFCOUNT_MASK)); 77962306a36Sopenharmony_ci 78062306a36Sopenharmony_ci local_irq_restore(irqflags); 78162306a36Sopenharmony_ci put_affine_portal(); 78262306a36Sopenharmony_ci return 0; 78362306a36Sopenharmony_ci} 78462306a36Sopenharmony_ciEXPORT_SYMBOL(bman_release); 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ciint bman_acquire(struct bman_pool *pool, struct bm_buffer *bufs, u8 num) 78762306a36Sopenharmony_ci{ 78862306a36Sopenharmony_ci struct bman_portal *p = get_affine_portal(); 78962306a36Sopenharmony_ci struct bm_mc_command *mcc; 79062306a36Sopenharmony_ci union bm_mc_result *mcr; 79162306a36Sopenharmony_ci int ret; 79262306a36Sopenharmony_ci 79362306a36Sopenharmony_ci DPAA_ASSERT(num > 0 && num <= 8); 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_ci mcc = bm_mc_start(&p->p); 79662306a36Sopenharmony_ci mcc->bpid = pool->bpid; 79762306a36Sopenharmony_ci bm_mc_commit(&p->p, BM_MCC_VERB_CMD_ACQUIRE | 79862306a36Sopenharmony_ci (num & BM_MCC_VERB_ACQUIRE_BUFCOUNT)); 79962306a36Sopenharmony_ci if (!bm_mc_result_timeout(&p->p, &mcr)) { 80062306a36Sopenharmony_ci put_affine_portal(); 80162306a36Sopenharmony_ci pr_crit("BMan Acquire Timeout\n"); 80262306a36Sopenharmony_ci return -ETIMEDOUT; 80362306a36Sopenharmony_ci } 80462306a36Sopenharmony_ci ret = mcr->verb & BM_MCR_VERB_ACQUIRE_BUFCOUNT; 80562306a36Sopenharmony_ci if (bufs) 80662306a36Sopenharmony_ci memcpy(&bufs[0], &mcr->bufs[0], num * sizeof(bufs[0])); 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_ci put_affine_portal(); 80962306a36Sopenharmony_ci if (ret != num) 81062306a36Sopenharmony_ci ret = -ENOMEM; 81162306a36Sopenharmony_ci return ret; 81262306a36Sopenharmony_ci} 81362306a36Sopenharmony_ciEXPORT_SYMBOL(bman_acquire); 81462306a36Sopenharmony_ci 81562306a36Sopenharmony_ciconst struct bm_portal_config * 81662306a36Sopenharmony_cibman_get_bm_portal_config(const struct bman_portal *portal) 81762306a36Sopenharmony_ci{ 81862306a36Sopenharmony_ci return portal->config; 81962306a36Sopenharmony_ci} 820