18c2ecf20Sopenharmony_ci/* Copyright 2008 - 2016 Freescale Semiconductor, Inc. 28c2ecf20Sopenharmony_ci * 38c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 48c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions are met: 58c2ecf20Sopenharmony_ci * * Redistributions of source code must retain the above copyright 68c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer. 78c2ecf20Sopenharmony_ci * * Redistributions in binary form must reproduce the above copyright 88c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer in the 98c2ecf20Sopenharmony_ci * documentation and/or other materials provided with the distribution. 108c2ecf20Sopenharmony_ci * * Neither the name of Freescale Semiconductor nor the 118c2ecf20Sopenharmony_ci * names of its contributors may be used to endorse or promote products 128c2ecf20Sopenharmony_ci * derived from this software without specific prior written permission. 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * ALTERNATIVELY, this software may be distributed under the terms of the 158c2ecf20Sopenharmony_ci * GNU General Public License ("GPL") as published by the Free Software 168c2ecf20Sopenharmony_ci * Foundation, either version 2 of that License or (at your option) any 178c2ecf20Sopenharmony_ci * later version. 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY 208c2ecf20Sopenharmony_ci * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 218c2ecf20Sopenharmony_ci * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 228c2ecf20Sopenharmony_ci * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY 238c2ecf20Sopenharmony_ci * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 248c2ecf20Sopenharmony_ci * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 258c2ecf20Sopenharmony_ci * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 268c2ecf20Sopenharmony_ci * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 278c2ecf20Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 288c2ecf20Sopenharmony_ci * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 298c2ecf20Sopenharmony_ci */ 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci#include "bman_priv.h" 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#define IRQNAME "BMan portal %d" 348c2ecf20Sopenharmony_ci#define MAX_IRQNAME 16 /* big enough for "BMan portal %d" */ 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci/* Portal register assists */ 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci#if defined(CONFIG_ARM) || defined(CONFIG_ARM64) 398c2ecf20Sopenharmony_ci/* Cache-inhibited register offsets */ 408c2ecf20Sopenharmony_ci#define BM_REG_RCR_PI_CINH 0x3000 418c2ecf20Sopenharmony_ci#define BM_REG_RCR_CI_CINH 0x3100 428c2ecf20Sopenharmony_ci#define BM_REG_RCR_ITR 0x3200 438c2ecf20Sopenharmony_ci#define BM_REG_CFG 0x3300 448c2ecf20Sopenharmony_ci#define BM_REG_SCN(n) (0x3400 + ((n) << 6)) 458c2ecf20Sopenharmony_ci#define BM_REG_ISR 0x3e00 468c2ecf20Sopenharmony_ci#define BM_REG_IER 0x3e40 478c2ecf20Sopenharmony_ci#define BM_REG_ISDR 0x3e80 488c2ecf20Sopenharmony_ci#define BM_REG_IIR 0x3ec0 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci/* Cache-enabled register offsets */ 518c2ecf20Sopenharmony_ci#define BM_CL_CR 0x0000 528c2ecf20Sopenharmony_ci#define BM_CL_RR0 0x0100 538c2ecf20Sopenharmony_ci#define BM_CL_RR1 0x0140 548c2ecf20Sopenharmony_ci#define BM_CL_RCR 0x1000 558c2ecf20Sopenharmony_ci#define BM_CL_RCR_PI_CENA 0x3000 568c2ecf20Sopenharmony_ci#define BM_CL_RCR_CI_CENA 0x3100 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci#else 598c2ecf20Sopenharmony_ci/* Cache-inhibited register offsets */ 608c2ecf20Sopenharmony_ci#define BM_REG_RCR_PI_CINH 0x0000 618c2ecf20Sopenharmony_ci#define BM_REG_RCR_CI_CINH 0x0004 628c2ecf20Sopenharmony_ci#define BM_REG_RCR_ITR 0x0008 638c2ecf20Sopenharmony_ci#define BM_REG_CFG 0x0100 648c2ecf20Sopenharmony_ci#define BM_REG_SCN(n) (0x0200 + ((n) << 2)) 658c2ecf20Sopenharmony_ci#define BM_REG_ISR 0x0e00 668c2ecf20Sopenharmony_ci#define BM_REG_IER 0x0e04 678c2ecf20Sopenharmony_ci#define BM_REG_ISDR 0x0e08 688c2ecf20Sopenharmony_ci#define BM_REG_IIR 0x0e0c 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci/* Cache-enabled register offsets */ 718c2ecf20Sopenharmony_ci#define BM_CL_CR 0x0000 728c2ecf20Sopenharmony_ci#define BM_CL_RR0 0x0100 738c2ecf20Sopenharmony_ci#define BM_CL_RR1 0x0140 748c2ecf20Sopenharmony_ci#define BM_CL_RCR 0x1000 758c2ecf20Sopenharmony_ci#define BM_CL_RCR_PI_CENA 0x3000 768c2ecf20Sopenharmony_ci#define BM_CL_RCR_CI_CENA 0x3100 778c2ecf20Sopenharmony_ci#endif 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci/* 808c2ecf20Sopenharmony_ci * Portal modes. 818c2ecf20Sopenharmony_ci * Enum types; 828c2ecf20Sopenharmony_ci * pmode == production mode 838c2ecf20Sopenharmony_ci * cmode == consumption mode, 848c2ecf20Sopenharmony_ci * Enum values use 3 letter codes. First letter matches the portal mode, 858c2ecf20Sopenharmony_ci * remaining two letters indicate; 868c2ecf20Sopenharmony_ci * ci == cache-inhibited portal register 878c2ecf20Sopenharmony_ci * ce == cache-enabled portal register 888c2ecf20Sopenharmony_ci * vb == in-band valid-bit (cache-enabled) 898c2ecf20Sopenharmony_ci */ 908c2ecf20Sopenharmony_cienum bm_rcr_pmode { /* matches BCSP_CFG::RPM */ 918c2ecf20Sopenharmony_ci bm_rcr_pci = 0, /* PI index, cache-inhibited */ 928c2ecf20Sopenharmony_ci bm_rcr_pce = 1, /* PI index, cache-enabled */ 938c2ecf20Sopenharmony_ci bm_rcr_pvb = 2 /* valid-bit */ 948c2ecf20Sopenharmony_ci}; 958c2ecf20Sopenharmony_cienum bm_rcr_cmode { /* s/w-only */ 968c2ecf20Sopenharmony_ci bm_rcr_cci, /* CI index, cache-inhibited */ 978c2ecf20Sopenharmony_ci bm_rcr_cce /* CI index, cache-enabled */ 988c2ecf20Sopenharmony_ci}; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci/* --- Portal structures --- */ 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci#define BM_RCR_SIZE 8 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci/* Release Command */ 1068c2ecf20Sopenharmony_cistruct bm_rcr_entry { 1078c2ecf20Sopenharmony_ci union { 1088c2ecf20Sopenharmony_ci struct { 1098c2ecf20Sopenharmony_ci u8 _ncw_verb; /* writes to this are non-coherent */ 1108c2ecf20Sopenharmony_ci u8 bpid; /* used with BM_RCR_VERB_CMD_BPID_SINGLE */ 1118c2ecf20Sopenharmony_ci u8 __reserved1[62]; 1128c2ecf20Sopenharmony_ci }; 1138c2ecf20Sopenharmony_ci struct bm_buffer bufs[8]; 1148c2ecf20Sopenharmony_ci }; 1158c2ecf20Sopenharmony_ci}; 1168c2ecf20Sopenharmony_ci#define BM_RCR_VERB_VBIT 0x80 1178c2ecf20Sopenharmony_ci#define BM_RCR_VERB_CMD_MASK 0x70 /* one of two values; */ 1188c2ecf20Sopenharmony_ci#define BM_RCR_VERB_CMD_BPID_SINGLE 0x20 1198c2ecf20Sopenharmony_ci#define BM_RCR_VERB_CMD_BPID_MULTI 0x30 1208c2ecf20Sopenharmony_ci#define BM_RCR_VERB_BUFCOUNT_MASK 0x0f /* values 1..8 */ 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_cistruct bm_rcr { 1238c2ecf20Sopenharmony_ci struct bm_rcr_entry *ring, *cursor; 1248c2ecf20Sopenharmony_ci u8 ci, available, ithresh, vbit; 1258c2ecf20Sopenharmony_ci#ifdef CONFIG_FSL_DPAA_CHECKING 1268c2ecf20Sopenharmony_ci u32 busy; 1278c2ecf20Sopenharmony_ci enum bm_rcr_pmode pmode; 1288c2ecf20Sopenharmony_ci enum bm_rcr_cmode cmode; 1298c2ecf20Sopenharmony_ci#endif 1308c2ecf20Sopenharmony_ci}; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci/* MC (Management Command) command */ 1338c2ecf20Sopenharmony_cistruct bm_mc_command { 1348c2ecf20Sopenharmony_ci u8 _ncw_verb; /* writes to this are non-coherent */ 1358c2ecf20Sopenharmony_ci u8 bpid; /* used by acquire command */ 1368c2ecf20Sopenharmony_ci u8 __reserved[62]; 1378c2ecf20Sopenharmony_ci}; 1388c2ecf20Sopenharmony_ci#define BM_MCC_VERB_VBIT 0x80 1398c2ecf20Sopenharmony_ci#define BM_MCC_VERB_CMD_MASK 0x70 /* where the verb contains; */ 1408c2ecf20Sopenharmony_ci#define BM_MCC_VERB_CMD_ACQUIRE 0x10 1418c2ecf20Sopenharmony_ci#define BM_MCC_VERB_CMD_QUERY 0x40 1428c2ecf20Sopenharmony_ci#define BM_MCC_VERB_ACQUIRE_BUFCOUNT 0x0f /* values 1..8 go here */ 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci/* MC result, Acquire and Query Response */ 1458c2ecf20Sopenharmony_ciunion bm_mc_result { 1468c2ecf20Sopenharmony_ci struct { 1478c2ecf20Sopenharmony_ci u8 verb; 1488c2ecf20Sopenharmony_ci u8 bpid; 1498c2ecf20Sopenharmony_ci u8 __reserved[62]; 1508c2ecf20Sopenharmony_ci }; 1518c2ecf20Sopenharmony_ci struct bm_buffer bufs[8]; 1528c2ecf20Sopenharmony_ci}; 1538c2ecf20Sopenharmony_ci#define BM_MCR_VERB_VBIT 0x80 1548c2ecf20Sopenharmony_ci#define BM_MCR_VERB_CMD_MASK BM_MCC_VERB_CMD_MASK 1558c2ecf20Sopenharmony_ci#define BM_MCR_VERB_CMD_ACQUIRE BM_MCC_VERB_CMD_ACQUIRE 1568c2ecf20Sopenharmony_ci#define BM_MCR_VERB_CMD_QUERY BM_MCC_VERB_CMD_QUERY 1578c2ecf20Sopenharmony_ci#define BM_MCR_VERB_CMD_ERR_INVALID 0x60 1588c2ecf20Sopenharmony_ci#define BM_MCR_VERB_CMD_ERR_ECC 0x70 1598c2ecf20Sopenharmony_ci#define BM_MCR_VERB_ACQUIRE_BUFCOUNT BM_MCC_VERB_ACQUIRE_BUFCOUNT /* 0..8 */ 1608c2ecf20Sopenharmony_ci#define BM_MCR_TIMEOUT 10000 /* us */ 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_cistruct bm_mc { 1638c2ecf20Sopenharmony_ci struct bm_mc_command *cr; 1648c2ecf20Sopenharmony_ci union bm_mc_result *rr; 1658c2ecf20Sopenharmony_ci u8 rridx, vbit; 1668c2ecf20Sopenharmony_ci#ifdef CONFIG_FSL_DPAA_CHECKING 1678c2ecf20Sopenharmony_ci enum { 1688c2ecf20Sopenharmony_ci /* Can only be _mc_start()ed */ 1698c2ecf20Sopenharmony_ci mc_idle, 1708c2ecf20Sopenharmony_ci /* Can only be _mc_commit()ed or _mc_abort()ed */ 1718c2ecf20Sopenharmony_ci mc_user, 1728c2ecf20Sopenharmony_ci /* Can only be _mc_retry()ed */ 1738c2ecf20Sopenharmony_ci mc_hw 1748c2ecf20Sopenharmony_ci } state; 1758c2ecf20Sopenharmony_ci#endif 1768c2ecf20Sopenharmony_ci}; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_cistruct bm_addr { 1798c2ecf20Sopenharmony_ci void *ce; /* cache-enabled */ 1808c2ecf20Sopenharmony_ci __be32 *ce_be; /* Same as above but for direct access */ 1818c2ecf20Sopenharmony_ci void __iomem *ci; /* cache-inhibited */ 1828c2ecf20Sopenharmony_ci}; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_cistruct bm_portal { 1858c2ecf20Sopenharmony_ci struct bm_addr addr; 1868c2ecf20Sopenharmony_ci struct bm_rcr rcr; 1878c2ecf20Sopenharmony_ci struct bm_mc mc; 1888c2ecf20Sopenharmony_ci} ____cacheline_aligned; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci/* Cache-inhibited register access. */ 1918c2ecf20Sopenharmony_cistatic inline u32 bm_in(struct bm_portal *p, u32 offset) 1928c2ecf20Sopenharmony_ci{ 1938c2ecf20Sopenharmony_ci return ioread32be(p->addr.ci + offset); 1948c2ecf20Sopenharmony_ci} 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_cistatic inline void bm_out(struct bm_portal *p, u32 offset, u32 val) 1978c2ecf20Sopenharmony_ci{ 1988c2ecf20Sopenharmony_ci iowrite32be(val, p->addr.ci + offset); 1998c2ecf20Sopenharmony_ci} 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci/* Cache Enabled Portal Access */ 2028c2ecf20Sopenharmony_cistatic inline void bm_cl_invalidate(struct bm_portal *p, u32 offset) 2038c2ecf20Sopenharmony_ci{ 2048c2ecf20Sopenharmony_ci dpaa_invalidate(p->addr.ce + offset); 2058c2ecf20Sopenharmony_ci} 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_cistatic inline void bm_cl_touch_ro(struct bm_portal *p, u32 offset) 2088c2ecf20Sopenharmony_ci{ 2098c2ecf20Sopenharmony_ci dpaa_touch_ro(p->addr.ce + offset); 2108c2ecf20Sopenharmony_ci} 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_cistatic inline u32 bm_ce_in(struct bm_portal *p, u32 offset) 2138c2ecf20Sopenharmony_ci{ 2148c2ecf20Sopenharmony_ci return be32_to_cpu(*(p->addr.ce_be + (offset/4))); 2158c2ecf20Sopenharmony_ci} 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_cistruct bman_portal { 2188c2ecf20Sopenharmony_ci struct bm_portal p; 2198c2ecf20Sopenharmony_ci /* interrupt sources processed by portal_isr(), configurable */ 2208c2ecf20Sopenharmony_ci unsigned long irq_sources; 2218c2ecf20Sopenharmony_ci /* probing time config params for cpu-affine portals */ 2228c2ecf20Sopenharmony_ci const struct bm_portal_config *config; 2238c2ecf20Sopenharmony_ci char irqname[MAX_IRQNAME]; 2248c2ecf20Sopenharmony_ci}; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_cistatic cpumask_t affine_mask; 2278c2ecf20Sopenharmony_cistatic DEFINE_SPINLOCK(affine_mask_lock); 2288c2ecf20Sopenharmony_cistatic DEFINE_PER_CPU(struct bman_portal, bman_affine_portal); 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_cistatic inline struct bman_portal *get_affine_portal(void) 2318c2ecf20Sopenharmony_ci{ 2328c2ecf20Sopenharmony_ci return &get_cpu_var(bman_affine_portal); 2338c2ecf20Sopenharmony_ci} 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_cistatic inline void put_affine_portal(void) 2368c2ecf20Sopenharmony_ci{ 2378c2ecf20Sopenharmony_ci put_cpu_var(bman_affine_portal); 2388c2ecf20Sopenharmony_ci} 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci/* 2418c2ecf20Sopenharmony_ci * This object type refers to a pool, it isn't *the* pool. There may be 2428c2ecf20Sopenharmony_ci * more than one such object per BMan buffer pool, eg. if different users of the 2438c2ecf20Sopenharmony_ci * pool are operating via different portals. 2448c2ecf20Sopenharmony_ci */ 2458c2ecf20Sopenharmony_cistruct bman_pool { 2468c2ecf20Sopenharmony_ci /* index of the buffer pool to encapsulate (0-63) */ 2478c2ecf20Sopenharmony_ci u32 bpid; 2488c2ecf20Sopenharmony_ci /* Used for hash-table admin when using depletion notifications. */ 2498c2ecf20Sopenharmony_ci struct bman_portal *portal; 2508c2ecf20Sopenharmony_ci struct bman_pool *next; 2518c2ecf20Sopenharmony_ci}; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_cistatic u32 poll_portal_slow(struct bman_portal *p, u32 is); 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_cistatic irqreturn_t portal_isr(int irq, void *ptr) 2568c2ecf20Sopenharmony_ci{ 2578c2ecf20Sopenharmony_ci struct bman_portal *p = ptr; 2588c2ecf20Sopenharmony_ci struct bm_portal *portal = &p->p; 2598c2ecf20Sopenharmony_ci u32 clear = p->irq_sources; 2608c2ecf20Sopenharmony_ci u32 is = bm_in(portal, BM_REG_ISR) & p->irq_sources; 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci if (unlikely(!is)) 2638c2ecf20Sopenharmony_ci return IRQ_NONE; 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci clear |= poll_portal_slow(p, is); 2668c2ecf20Sopenharmony_ci bm_out(portal, BM_REG_ISR, clear); 2678c2ecf20Sopenharmony_ci return IRQ_HANDLED; 2688c2ecf20Sopenharmony_ci} 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci/* --- RCR API --- */ 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci#define RCR_SHIFT ilog2(sizeof(struct bm_rcr_entry)) 2738c2ecf20Sopenharmony_ci#define RCR_CARRY (uintptr_t)(BM_RCR_SIZE << RCR_SHIFT) 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci/* Bit-wise logic to wrap a ring pointer by clearing the "carry bit" */ 2768c2ecf20Sopenharmony_cistatic struct bm_rcr_entry *rcr_carryclear(struct bm_rcr_entry *p) 2778c2ecf20Sopenharmony_ci{ 2788c2ecf20Sopenharmony_ci uintptr_t addr = (uintptr_t)p; 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci addr &= ~RCR_CARRY; 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci return (struct bm_rcr_entry *)addr; 2838c2ecf20Sopenharmony_ci} 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci#ifdef CONFIG_FSL_DPAA_CHECKING 2868c2ecf20Sopenharmony_ci/* Bit-wise logic to convert a ring pointer to a ring index */ 2878c2ecf20Sopenharmony_cistatic int rcr_ptr2idx(struct bm_rcr_entry *e) 2888c2ecf20Sopenharmony_ci{ 2898c2ecf20Sopenharmony_ci return ((uintptr_t)e >> RCR_SHIFT) & (BM_RCR_SIZE - 1); 2908c2ecf20Sopenharmony_ci} 2918c2ecf20Sopenharmony_ci#endif 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci/* Increment the 'cursor' ring pointer, taking 'vbit' into account */ 2948c2ecf20Sopenharmony_cistatic inline void rcr_inc(struct bm_rcr *rcr) 2958c2ecf20Sopenharmony_ci{ 2968c2ecf20Sopenharmony_ci /* increment to the next RCR pointer and handle overflow and 'vbit' */ 2978c2ecf20Sopenharmony_ci struct bm_rcr_entry *partial = rcr->cursor + 1; 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci rcr->cursor = rcr_carryclear(partial); 3008c2ecf20Sopenharmony_ci if (partial != rcr->cursor) 3018c2ecf20Sopenharmony_ci rcr->vbit ^= BM_RCR_VERB_VBIT; 3028c2ecf20Sopenharmony_ci} 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_cistatic int bm_rcr_get_avail(struct bm_portal *portal) 3058c2ecf20Sopenharmony_ci{ 3068c2ecf20Sopenharmony_ci struct bm_rcr *rcr = &portal->rcr; 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci return rcr->available; 3098c2ecf20Sopenharmony_ci} 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_cistatic int bm_rcr_get_fill(struct bm_portal *portal) 3128c2ecf20Sopenharmony_ci{ 3138c2ecf20Sopenharmony_ci struct bm_rcr *rcr = &portal->rcr; 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci return BM_RCR_SIZE - 1 - rcr->available; 3168c2ecf20Sopenharmony_ci} 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_cistatic void bm_rcr_set_ithresh(struct bm_portal *portal, u8 ithresh) 3198c2ecf20Sopenharmony_ci{ 3208c2ecf20Sopenharmony_ci struct bm_rcr *rcr = &portal->rcr; 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci rcr->ithresh = ithresh; 3238c2ecf20Sopenharmony_ci bm_out(portal, BM_REG_RCR_ITR, ithresh); 3248c2ecf20Sopenharmony_ci} 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_cistatic void bm_rcr_cce_prefetch(struct bm_portal *portal) 3278c2ecf20Sopenharmony_ci{ 3288c2ecf20Sopenharmony_ci __maybe_unused struct bm_rcr *rcr = &portal->rcr; 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci DPAA_ASSERT(rcr->cmode == bm_rcr_cce); 3318c2ecf20Sopenharmony_ci bm_cl_touch_ro(portal, BM_CL_RCR_CI_CENA); 3328c2ecf20Sopenharmony_ci} 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_cistatic u8 bm_rcr_cce_update(struct bm_portal *portal) 3358c2ecf20Sopenharmony_ci{ 3368c2ecf20Sopenharmony_ci struct bm_rcr *rcr = &portal->rcr; 3378c2ecf20Sopenharmony_ci u8 diff, old_ci = rcr->ci; 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci DPAA_ASSERT(rcr->cmode == bm_rcr_cce); 3408c2ecf20Sopenharmony_ci rcr->ci = bm_ce_in(portal, BM_CL_RCR_CI_CENA) & (BM_RCR_SIZE - 1); 3418c2ecf20Sopenharmony_ci bm_cl_invalidate(portal, BM_CL_RCR_CI_CENA); 3428c2ecf20Sopenharmony_ci diff = dpaa_cyc_diff(BM_RCR_SIZE, old_ci, rcr->ci); 3438c2ecf20Sopenharmony_ci rcr->available += diff; 3448c2ecf20Sopenharmony_ci return diff; 3458c2ecf20Sopenharmony_ci} 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_cistatic inline struct bm_rcr_entry *bm_rcr_start(struct bm_portal *portal) 3488c2ecf20Sopenharmony_ci{ 3498c2ecf20Sopenharmony_ci struct bm_rcr *rcr = &portal->rcr; 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci DPAA_ASSERT(!rcr->busy); 3528c2ecf20Sopenharmony_ci if (!rcr->available) 3538c2ecf20Sopenharmony_ci return NULL; 3548c2ecf20Sopenharmony_ci#ifdef CONFIG_FSL_DPAA_CHECKING 3558c2ecf20Sopenharmony_ci rcr->busy = 1; 3568c2ecf20Sopenharmony_ci#endif 3578c2ecf20Sopenharmony_ci dpaa_zero(rcr->cursor); 3588c2ecf20Sopenharmony_ci return rcr->cursor; 3598c2ecf20Sopenharmony_ci} 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_cistatic inline void bm_rcr_pvb_commit(struct bm_portal *portal, u8 myverb) 3628c2ecf20Sopenharmony_ci{ 3638c2ecf20Sopenharmony_ci struct bm_rcr *rcr = &portal->rcr; 3648c2ecf20Sopenharmony_ci struct bm_rcr_entry *rcursor; 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci DPAA_ASSERT(rcr->busy); 3678c2ecf20Sopenharmony_ci DPAA_ASSERT(rcr->pmode == bm_rcr_pvb); 3688c2ecf20Sopenharmony_ci DPAA_ASSERT(rcr->available >= 1); 3698c2ecf20Sopenharmony_ci dma_wmb(); 3708c2ecf20Sopenharmony_ci rcursor = rcr->cursor; 3718c2ecf20Sopenharmony_ci rcursor->_ncw_verb = myverb | rcr->vbit; 3728c2ecf20Sopenharmony_ci dpaa_flush(rcursor); 3738c2ecf20Sopenharmony_ci rcr_inc(rcr); 3748c2ecf20Sopenharmony_ci rcr->available--; 3758c2ecf20Sopenharmony_ci#ifdef CONFIG_FSL_DPAA_CHECKING 3768c2ecf20Sopenharmony_ci rcr->busy = 0; 3778c2ecf20Sopenharmony_ci#endif 3788c2ecf20Sopenharmony_ci} 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_cistatic int bm_rcr_init(struct bm_portal *portal, enum bm_rcr_pmode pmode, 3818c2ecf20Sopenharmony_ci enum bm_rcr_cmode cmode) 3828c2ecf20Sopenharmony_ci{ 3838c2ecf20Sopenharmony_ci struct bm_rcr *rcr = &portal->rcr; 3848c2ecf20Sopenharmony_ci u32 cfg; 3858c2ecf20Sopenharmony_ci u8 pi; 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci rcr->ring = portal->addr.ce + BM_CL_RCR; 3888c2ecf20Sopenharmony_ci rcr->ci = bm_in(portal, BM_REG_RCR_CI_CINH) & (BM_RCR_SIZE - 1); 3898c2ecf20Sopenharmony_ci pi = bm_in(portal, BM_REG_RCR_PI_CINH) & (BM_RCR_SIZE - 1); 3908c2ecf20Sopenharmony_ci rcr->cursor = rcr->ring + pi; 3918c2ecf20Sopenharmony_ci rcr->vbit = (bm_in(portal, BM_REG_RCR_PI_CINH) & BM_RCR_SIZE) ? 3928c2ecf20Sopenharmony_ci BM_RCR_VERB_VBIT : 0; 3938c2ecf20Sopenharmony_ci rcr->available = BM_RCR_SIZE - 1 3948c2ecf20Sopenharmony_ci - dpaa_cyc_diff(BM_RCR_SIZE, rcr->ci, pi); 3958c2ecf20Sopenharmony_ci rcr->ithresh = bm_in(portal, BM_REG_RCR_ITR); 3968c2ecf20Sopenharmony_ci#ifdef CONFIG_FSL_DPAA_CHECKING 3978c2ecf20Sopenharmony_ci rcr->busy = 0; 3988c2ecf20Sopenharmony_ci rcr->pmode = pmode; 3998c2ecf20Sopenharmony_ci rcr->cmode = cmode; 4008c2ecf20Sopenharmony_ci#endif 4018c2ecf20Sopenharmony_ci cfg = (bm_in(portal, BM_REG_CFG) & 0xffffffe0) 4028c2ecf20Sopenharmony_ci | (pmode & 0x3); /* BCSP_CFG::RPM */ 4038c2ecf20Sopenharmony_ci bm_out(portal, BM_REG_CFG, cfg); 4048c2ecf20Sopenharmony_ci return 0; 4058c2ecf20Sopenharmony_ci} 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_cistatic void bm_rcr_finish(struct bm_portal *portal) 4088c2ecf20Sopenharmony_ci{ 4098c2ecf20Sopenharmony_ci#ifdef CONFIG_FSL_DPAA_CHECKING 4108c2ecf20Sopenharmony_ci struct bm_rcr *rcr = &portal->rcr; 4118c2ecf20Sopenharmony_ci int i; 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci DPAA_ASSERT(!rcr->busy); 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci i = bm_in(portal, BM_REG_RCR_PI_CINH) & (BM_RCR_SIZE - 1); 4168c2ecf20Sopenharmony_ci if (i != rcr_ptr2idx(rcr->cursor)) 4178c2ecf20Sopenharmony_ci pr_crit("losing uncommitted RCR entries\n"); 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci i = bm_in(portal, BM_REG_RCR_CI_CINH) & (BM_RCR_SIZE - 1); 4208c2ecf20Sopenharmony_ci if (i != rcr->ci) 4218c2ecf20Sopenharmony_ci pr_crit("missing existing RCR completions\n"); 4228c2ecf20Sopenharmony_ci if (rcr->ci != rcr_ptr2idx(rcr->cursor)) 4238c2ecf20Sopenharmony_ci pr_crit("RCR destroyed unquiesced\n"); 4248c2ecf20Sopenharmony_ci#endif 4258c2ecf20Sopenharmony_ci} 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci/* --- Management command API --- */ 4288c2ecf20Sopenharmony_cistatic int bm_mc_init(struct bm_portal *portal) 4298c2ecf20Sopenharmony_ci{ 4308c2ecf20Sopenharmony_ci struct bm_mc *mc = &portal->mc; 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci mc->cr = portal->addr.ce + BM_CL_CR; 4338c2ecf20Sopenharmony_ci mc->rr = portal->addr.ce + BM_CL_RR0; 4348c2ecf20Sopenharmony_ci mc->rridx = (mc->cr->_ncw_verb & BM_MCC_VERB_VBIT) ? 4358c2ecf20Sopenharmony_ci 0 : 1; 4368c2ecf20Sopenharmony_ci mc->vbit = mc->rridx ? BM_MCC_VERB_VBIT : 0; 4378c2ecf20Sopenharmony_ci#ifdef CONFIG_FSL_DPAA_CHECKING 4388c2ecf20Sopenharmony_ci mc->state = mc_idle; 4398c2ecf20Sopenharmony_ci#endif 4408c2ecf20Sopenharmony_ci return 0; 4418c2ecf20Sopenharmony_ci} 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_cistatic void bm_mc_finish(struct bm_portal *portal) 4448c2ecf20Sopenharmony_ci{ 4458c2ecf20Sopenharmony_ci#ifdef CONFIG_FSL_DPAA_CHECKING 4468c2ecf20Sopenharmony_ci struct bm_mc *mc = &portal->mc; 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci DPAA_ASSERT(mc->state == mc_idle); 4498c2ecf20Sopenharmony_ci if (mc->state != mc_idle) 4508c2ecf20Sopenharmony_ci pr_crit("Losing incomplete MC command\n"); 4518c2ecf20Sopenharmony_ci#endif 4528c2ecf20Sopenharmony_ci} 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_cistatic inline struct bm_mc_command *bm_mc_start(struct bm_portal *portal) 4558c2ecf20Sopenharmony_ci{ 4568c2ecf20Sopenharmony_ci struct bm_mc *mc = &portal->mc; 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ci DPAA_ASSERT(mc->state == mc_idle); 4598c2ecf20Sopenharmony_ci#ifdef CONFIG_FSL_DPAA_CHECKING 4608c2ecf20Sopenharmony_ci mc->state = mc_user; 4618c2ecf20Sopenharmony_ci#endif 4628c2ecf20Sopenharmony_ci dpaa_zero(mc->cr); 4638c2ecf20Sopenharmony_ci return mc->cr; 4648c2ecf20Sopenharmony_ci} 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_cistatic inline void bm_mc_commit(struct bm_portal *portal, u8 myverb) 4678c2ecf20Sopenharmony_ci{ 4688c2ecf20Sopenharmony_ci struct bm_mc *mc = &portal->mc; 4698c2ecf20Sopenharmony_ci union bm_mc_result *rr = mc->rr + mc->rridx; 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci DPAA_ASSERT(mc->state == mc_user); 4728c2ecf20Sopenharmony_ci dma_wmb(); 4738c2ecf20Sopenharmony_ci mc->cr->_ncw_verb = myverb | mc->vbit; 4748c2ecf20Sopenharmony_ci dpaa_flush(mc->cr); 4758c2ecf20Sopenharmony_ci dpaa_invalidate_touch_ro(rr); 4768c2ecf20Sopenharmony_ci#ifdef CONFIG_FSL_DPAA_CHECKING 4778c2ecf20Sopenharmony_ci mc->state = mc_hw; 4788c2ecf20Sopenharmony_ci#endif 4798c2ecf20Sopenharmony_ci} 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_cistatic inline union bm_mc_result *bm_mc_result(struct bm_portal *portal) 4828c2ecf20Sopenharmony_ci{ 4838c2ecf20Sopenharmony_ci struct bm_mc *mc = &portal->mc; 4848c2ecf20Sopenharmony_ci union bm_mc_result *rr = mc->rr + mc->rridx; 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ci DPAA_ASSERT(mc->state == mc_hw); 4878c2ecf20Sopenharmony_ci /* 4888c2ecf20Sopenharmony_ci * The inactive response register's verb byte always returns zero until 4898c2ecf20Sopenharmony_ci * its command is submitted and completed. This includes the valid-bit, 4908c2ecf20Sopenharmony_ci * in case you were wondering... 4918c2ecf20Sopenharmony_ci */ 4928c2ecf20Sopenharmony_ci if (!rr->verb) { 4938c2ecf20Sopenharmony_ci dpaa_invalidate_touch_ro(rr); 4948c2ecf20Sopenharmony_ci return NULL; 4958c2ecf20Sopenharmony_ci } 4968c2ecf20Sopenharmony_ci mc->rridx ^= 1; 4978c2ecf20Sopenharmony_ci mc->vbit ^= BM_MCC_VERB_VBIT; 4988c2ecf20Sopenharmony_ci#ifdef CONFIG_FSL_DPAA_CHECKING 4998c2ecf20Sopenharmony_ci mc->state = mc_idle; 5008c2ecf20Sopenharmony_ci#endif 5018c2ecf20Sopenharmony_ci return rr; 5028c2ecf20Sopenharmony_ci} 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_cistatic inline int bm_mc_result_timeout(struct bm_portal *portal, 5058c2ecf20Sopenharmony_ci union bm_mc_result **mcr) 5068c2ecf20Sopenharmony_ci{ 5078c2ecf20Sopenharmony_ci int timeout = BM_MCR_TIMEOUT; 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci do { 5108c2ecf20Sopenharmony_ci *mcr = bm_mc_result(portal); 5118c2ecf20Sopenharmony_ci if (*mcr) 5128c2ecf20Sopenharmony_ci break; 5138c2ecf20Sopenharmony_ci udelay(1); 5148c2ecf20Sopenharmony_ci } while (--timeout); 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ci return timeout; 5178c2ecf20Sopenharmony_ci} 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_ci/* Disable all BSCN interrupts for the portal */ 5208c2ecf20Sopenharmony_cistatic void bm_isr_bscn_disable(struct bm_portal *portal) 5218c2ecf20Sopenharmony_ci{ 5228c2ecf20Sopenharmony_ci bm_out(portal, BM_REG_SCN(0), 0); 5238c2ecf20Sopenharmony_ci bm_out(portal, BM_REG_SCN(1), 0); 5248c2ecf20Sopenharmony_ci} 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_cistatic int bman_create_portal(struct bman_portal *portal, 5278c2ecf20Sopenharmony_ci const struct bm_portal_config *c) 5288c2ecf20Sopenharmony_ci{ 5298c2ecf20Sopenharmony_ci struct bm_portal *p; 5308c2ecf20Sopenharmony_ci int ret; 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci p = &portal->p; 5338c2ecf20Sopenharmony_ci /* 5348c2ecf20Sopenharmony_ci * prep the low-level portal struct with the mapped addresses from the 5358c2ecf20Sopenharmony_ci * config, everything that follows depends on it and "config" is more 5368c2ecf20Sopenharmony_ci * for (de)reference... 5378c2ecf20Sopenharmony_ci */ 5388c2ecf20Sopenharmony_ci p->addr.ce = c->addr_virt_ce; 5398c2ecf20Sopenharmony_ci p->addr.ce_be = c->addr_virt_ce; 5408c2ecf20Sopenharmony_ci p->addr.ci = c->addr_virt_ci; 5418c2ecf20Sopenharmony_ci if (bm_rcr_init(p, bm_rcr_pvb, bm_rcr_cce)) { 5428c2ecf20Sopenharmony_ci dev_err(c->dev, "RCR initialisation failed\n"); 5438c2ecf20Sopenharmony_ci goto fail_rcr; 5448c2ecf20Sopenharmony_ci } 5458c2ecf20Sopenharmony_ci if (bm_mc_init(p)) { 5468c2ecf20Sopenharmony_ci dev_err(c->dev, "MC initialisation failed\n"); 5478c2ecf20Sopenharmony_ci goto fail_mc; 5488c2ecf20Sopenharmony_ci } 5498c2ecf20Sopenharmony_ci /* 5508c2ecf20Sopenharmony_ci * Default to all BPIDs disabled, we enable as required at 5518c2ecf20Sopenharmony_ci * run-time. 5528c2ecf20Sopenharmony_ci */ 5538c2ecf20Sopenharmony_ci bm_isr_bscn_disable(p); 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci /* Write-to-clear any stale interrupt status bits */ 5568c2ecf20Sopenharmony_ci bm_out(p, BM_REG_ISDR, 0xffffffff); 5578c2ecf20Sopenharmony_ci portal->irq_sources = 0; 5588c2ecf20Sopenharmony_ci bm_out(p, BM_REG_IER, 0); 5598c2ecf20Sopenharmony_ci bm_out(p, BM_REG_ISR, 0xffffffff); 5608c2ecf20Sopenharmony_ci snprintf(portal->irqname, MAX_IRQNAME, IRQNAME, c->cpu); 5618c2ecf20Sopenharmony_ci if (request_irq(c->irq, portal_isr, 0, portal->irqname, portal)) { 5628c2ecf20Sopenharmony_ci dev_err(c->dev, "request_irq() failed\n"); 5638c2ecf20Sopenharmony_ci goto fail_irq; 5648c2ecf20Sopenharmony_ci } 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_ci if (dpaa_set_portal_irq_affinity(c->dev, c->irq, c->cpu)) 5678c2ecf20Sopenharmony_ci goto fail_affinity; 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci /* Need RCR to be empty before continuing */ 5708c2ecf20Sopenharmony_ci ret = bm_rcr_get_fill(p); 5718c2ecf20Sopenharmony_ci if (ret) { 5728c2ecf20Sopenharmony_ci dev_err(c->dev, "RCR unclean\n"); 5738c2ecf20Sopenharmony_ci goto fail_rcr_empty; 5748c2ecf20Sopenharmony_ci } 5758c2ecf20Sopenharmony_ci /* Success */ 5768c2ecf20Sopenharmony_ci portal->config = c; 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci bm_out(p, BM_REG_ISDR, 0); 5798c2ecf20Sopenharmony_ci bm_out(p, BM_REG_IIR, 0); 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci return 0; 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_cifail_rcr_empty: 5848c2ecf20Sopenharmony_cifail_affinity: 5858c2ecf20Sopenharmony_ci free_irq(c->irq, portal); 5868c2ecf20Sopenharmony_cifail_irq: 5878c2ecf20Sopenharmony_ci bm_mc_finish(p); 5888c2ecf20Sopenharmony_cifail_mc: 5898c2ecf20Sopenharmony_ci bm_rcr_finish(p); 5908c2ecf20Sopenharmony_cifail_rcr: 5918c2ecf20Sopenharmony_ci return -EIO; 5928c2ecf20Sopenharmony_ci} 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_cistruct bman_portal *bman_create_affine_portal(const struct bm_portal_config *c) 5958c2ecf20Sopenharmony_ci{ 5968c2ecf20Sopenharmony_ci struct bman_portal *portal; 5978c2ecf20Sopenharmony_ci int err; 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci portal = &per_cpu(bman_affine_portal, c->cpu); 6008c2ecf20Sopenharmony_ci err = bman_create_portal(portal, c); 6018c2ecf20Sopenharmony_ci if (err) 6028c2ecf20Sopenharmony_ci return NULL; 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci spin_lock(&affine_mask_lock); 6058c2ecf20Sopenharmony_ci cpumask_set_cpu(c->cpu, &affine_mask); 6068c2ecf20Sopenharmony_ci spin_unlock(&affine_mask_lock); 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci return portal; 6098c2ecf20Sopenharmony_ci} 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_cistatic u32 poll_portal_slow(struct bman_portal *p, u32 is) 6128c2ecf20Sopenharmony_ci{ 6138c2ecf20Sopenharmony_ci u32 ret = is; 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci if (is & BM_PIRQ_RCRI) { 6168c2ecf20Sopenharmony_ci bm_rcr_cce_update(&p->p); 6178c2ecf20Sopenharmony_ci bm_rcr_set_ithresh(&p->p, 0); 6188c2ecf20Sopenharmony_ci bm_out(&p->p, BM_REG_ISR, BM_PIRQ_RCRI); 6198c2ecf20Sopenharmony_ci is &= ~BM_PIRQ_RCRI; 6208c2ecf20Sopenharmony_ci } 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci /* There should be no status register bits left undefined */ 6238c2ecf20Sopenharmony_ci DPAA_ASSERT(!is); 6248c2ecf20Sopenharmony_ci return ret; 6258c2ecf20Sopenharmony_ci} 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ciint bman_p_irqsource_add(struct bman_portal *p, u32 bits) 6288c2ecf20Sopenharmony_ci{ 6298c2ecf20Sopenharmony_ci unsigned long irqflags; 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci local_irq_save(irqflags); 6328c2ecf20Sopenharmony_ci p->irq_sources |= bits & BM_PIRQ_VISIBLE; 6338c2ecf20Sopenharmony_ci bm_out(&p->p, BM_REG_IER, p->irq_sources); 6348c2ecf20Sopenharmony_ci local_irq_restore(irqflags); 6358c2ecf20Sopenharmony_ci return 0; 6368c2ecf20Sopenharmony_ci} 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ciint bm_shutdown_pool(u32 bpid) 6398c2ecf20Sopenharmony_ci{ 6408c2ecf20Sopenharmony_ci int err = 0; 6418c2ecf20Sopenharmony_ci struct bm_mc_command *bm_cmd; 6428c2ecf20Sopenharmony_ci union bm_mc_result *bm_res; 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci struct bman_portal *p = get_affine_portal(); 6468c2ecf20Sopenharmony_ci while (1) { 6478c2ecf20Sopenharmony_ci /* Acquire buffers until empty */ 6488c2ecf20Sopenharmony_ci bm_cmd = bm_mc_start(&p->p); 6498c2ecf20Sopenharmony_ci bm_cmd->bpid = bpid; 6508c2ecf20Sopenharmony_ci bm_mc_commit(&p->p, BM_MCC_VERB_CMD_ACQUIRE | 1); 6518c2ecf20Sopenharmony_ci if (!bm_mc_result_timeout(&p->p, &bm_res)) { 6528c2ecf20Sopenharmony_ci pr_crit("BMan Acquire Command timedout\n"); 6538c2ecf20Sopenharmony_ci err = -ETIMEDOUT; 6548c2ecf20Sopenharmony_ci goto done; 6558c2ecf20Sopenharmony_ci } 6568c2ecf20Sopenharmony_ci if (!(bm_res->verb & BM_MCR_VERB_ACQUIRE_BUFCOUNT)) { 6578c2ecf20Sopenharmony_ci /* Pool is empty */ 6588c2ecf20Sopenharmony_ci goto done; 6598c2ecf20Sopenharmony_ci } 6608c2ecf20Sopenharmony_ci } 6618c2ecf20Sopenharmony_cidone: 6628c2ecf20Sopenharmony_ci put_affine_portal(); 6638c2ecf20Sopenharmony_ci return err; 6648c2ecf20Sopenharmony_ci} 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_cistruct gen_pool *bm_bpalloc; 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_cistatic int bm_alloc_bpid_range(u32 *result, u32 count) 6698c2ecf20Sopenharmony_ci{ 6708c2ecf20Sopenharmony_ci unsigned long addr; 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_ci addr = gen_pool_alloc(bm_bpalloc, count); 6738c2ecf20Sopenharmony_ci if (!addr) 6748c2ecf20Sopenharmony_ci return -ENOMEM; 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci *result = addr & ~DPAA_GENALLOC_OFF; 6778c2ecf20Sopenharmony_ci 6788c2ecf20Sopenharmony_ci return 0; 6798c2ecf20Sopenharmony_ci} 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_cistatic int bm_release_bpid(u32 bpid) 6828c2ecf20Sopenharmony_ci{ 6838c2ecf20Sopenharmony_ci int ret; 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_ci ret = bm_shutdown_pool(bpid); 6868c2ecf20Sopenharmony_ci if (ret) { 6878c2ecf20Sopenharmony_ci pr_debug("BPID %d leaked\n", bpid); 6888c2ecf20Sopenharmony_ci return ret; 6898c2ecf20Sopenharmony_ci } 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci gen_pool_free(bm_bpalloc, bpid | DPAA_GENALLOC_OFF, 1); 6928c2ecf20Sopenharmony_ci return 0; 6938c2ecf20Sopenharmony_ci} 6948c2ecf20Sopenharmony_ci 6958c2ecf20Sopenharmony_cistruct bman_pool *bman_new_pool(void) 6968c2ecf20Sopenharmony_ci{ 6978c2ecf20Sopenharmony_ci struct bman_pool *pool = NULL; 6988c2ecf20Sopenharmony_ci u32 bpid; 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci if (bm_alloc_bpid_range(&bpid, 1)) 7018c2ecf20Sopenharmony_ci return NULL; 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci pool = kmalloc(sizeof(*pool), GFP_KERNEL); 7048c2ecf20Sopenharmony_ci if (!pool) 7058c2ecf20Sopenharmony_ci goto err; 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_ci pool->bpid = bpid; 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_ci return pool; 7108c2ecf20Sopenharmony_cierr: 7118c2ecf20Sopenharmony_ci bm_release_bpid(bpid); 7128c2ecf20Sopenharmony_ci kfree(pool); 7138c2ecf20Sopenharmony_ci return NULL; 7148c2ecf20Sopenharmony_ci} 7158c2ecf20Sopenharmony_ciEXPORT_SYMBOL(bman_new_pool); 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_civoid bman_free_pool(struct bman_pool *pool) 7188c2ecf20Sopenharmony_ci{ 7198c2ecf20Sopenharmony_ci bm_release_bpid(pool->bpid); 7208c2ecf20Sopenharmony_ci 7218c2ecf20Sopenharmony_ci kfree(pool); 7228c2ecf20Sopenharmony_ci} 7238c2ecf20Sopenharmony_ciEXPORT_SYMBOL(bman_free_pool); 7248c2ecf20Sopenharmony_ci 7258c2ecf20Sopenharmony_ciint bman_get_bpid(const struct bman_pool *pool) 7268c2ecf20Sopenharmony_ci{ 7278c2ecf20Sopenharmony_ci return pool->bpid; 7288c2ecf20Sopenharmony_ci} 7298c2ecf20Sopenharmony_ciEXPORT_SYMBOL(bman_get_bpid); 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_cistatic void update_rcr_ci(struct bman_portal *p, int avail) 7328c2ecf20Sopenharmony_ci{ 7338c2ecf20Sopenharmony_ci if (avail) 7348c2ecf20Sopenharmony_ci bm_rcr_cce_prefetch(&p->p); 7358c2ecf20Sopenharmony_ci else 7368c2ecf20Sopenharmony_ci bm_rcr_cce_update(&p->p); 7378c2ecf20Sopenharmony_ci} 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ciint bman_release(struct bman_pool *pool, const struct bm_buffer *bufs, u8 num) 7408c2ecf20Sopenharmony_ci{ 7418c2ecf20Sopenharmony_ci struct bman_portal *p; 7428c2ecf20Sopenharmony_ci struct bm_rcr_entry *r; 7438c2ecf20Sopenharmony_ci unsigned long irqflags; 7448c2ecf20Sopenharmony_ci int avail, timeout = 1000; /* 1ms */ 7458c2ecf20Sopenharmony_ci int i = num - 1; 7468c2ecf20Sopenharmony_ci 7478c2ecf20Sopenharmony_ci DPAA_ASSERT(num > 0 && num <= 8); 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci do { 7508c2ecf20Sopenharmony_ci p = get_affine_portal(); 7518c2ecf20Sopenharmony_ci local_irq_save(irqflags); 7528c2ecf20Sopenharmony_ci avail = bm_rcr_get_avail(&p->p); 7538c2ecf20Sopenharmony_ci if (avail < 2) 7548c2ecf20Sopenharmony_ci update_rcr_ci(p, avail); 7558c2ecf20Sopenharmony_ci r = bm_rcr_start(&p->p); 7568c2ecf20Sopenharmony_ci local_irq_restore(irqflags); 7578c2ecf20Sopenharmony_ci put_affine_portal(); 7588c2ecf20Sopenharmony_ci if (likely(r)) 7598c2ecf20Sopenharmony_ci break; 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci udelay(1); 7628c2ecf20Sopenharmony_ci } while (--timeout); 7638c2ecf20Sopenharmony_ci 7648c2ecf20Sopenharmony_ci if (unlikely(!timeout)) 7658c2ecf20Sopenharmony_ci return -ETIMEDOUT; 7668c2ecf20Sopenharmony_ci 7678c2ecf20Sopenharmony_ci p = get_affine_portal(); 7688c2ecf20Sopenharmony_ci local_irq_save(irqflags); 7698c2ecf20Sopenharmony_ci /* 7708c2ecf20Sopenharmony_ci * we can copy all but the first entry, as this can trigger badness 7718c2ecf20Sopenharmony_ci * with the valid-bit 7728c2ecf20Sopenharmony_ci */ 7738c2ecf20Sopenharmony_ci bm_buffer_set64(r->bufs, bm_buffer_get64(bufs)); 7748c2ecf20Sopenharmony_ci bm_buffer_set_bpid(r->bufs, pool->bpid); 7758c2ecf20Sopenharmony_ci if (i) 7768c2ecf20Sopenharmony_ci memcpy(&r->bufs[1], &bufs[1], i * sizeof(bufs[0])); 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_ci bm_rcr_pvb_commit(&p->p, BM_RCR_VERB_CMD_BPID_SINGLE | 7798c2ecf20Sopenharmony_ci (num & BM_RCR_VERB_BUFCOUNT_MASK)); 7808c2ecf20Sopenharmony_ci 7818c2ecf20Sopenharmony_ci local_irq_restore(irqflags); 7828c2ecf20Sopenharmony_ci put_affine_portal(); 7838c2ecf20Sopenharmony_ci return 0; 7848c2ecf20Sopenharmony_ci} 7858c2ecf20Sopenharmony_ciEXPORT_SYMBOL(bman_release); 7868c2ecf20Sopenharmony_ci 7878c2ecf20Sopenharmony_ciint bman_acquire(struct bman_pool *pool, struct bm_buffer *bufs, u8 num) 7888c2ecf20Sopenharmony_ci{ 7898c2ecf20Sopenharmony_ci struct bman_portal *p = get_affine_portal(); 7908c2ecf20Sopenharmony_ci struct bm_mc_command *mcc; 7918c2ecf20Sopenharmony_ci union bm_mc_result *mcr; 7928c2ecf20Sopenharmony_ci int ret; 7938c2ecf20Sopenharmony_ci 7948c2ecf20Sopenharmony_ci DPAA_ASSERT(num > 0 && num <= 8); 7958c2ecf20Sopenharmony_ci 7968c2ecf20Sopenharmony_ci mcc = bm_mc_start(&p->p); 7978c2ecf20Sopenharmony_ci mcc->bpid = pool->bpid; 7988c2ecf20Sopenharmony_ci bm_mc_commit(&p->p, BM_MCC_VERB_CMD_ACQUIRE | 7998c2ecf20Sopenharmony_ci (num & BM_MCC_VERB_ACQUIRE_BUFCOUNT)); 8008c2ecf20Sopenharmony_ci if (!bm_mc_result_timeout(&p->p, &mcr)) { 8018c2ecf20Sopenharmony_ci put_affine_portal(); 8028c2ecf20Sopenharmony_ci pr_crit("BMan Acquire Timeout\n"); 8038c2ecf20Sopenharmony_ci return -ETIMEDOUT; 8048c2ecf20Sopenharmony_ci } 8058c2ecf20Sopenharmony_ci ret = mcr->verb & BM_MCR_VERB_ACQUIRE_BUFCOUNT; 8068c2ecf20Sopenharmony_ci if (bufs) 8078c2ecf20Sopenharmony_ci memcpy(&bufs[0], &mcr->bufs[0], num * sizeof(bufs[0])); 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci put_affine_portal(); 8108c2ecf20Sopenharmony_ci if (ret != num) 8118c2ecf20Sopenharmony_ci ret = -ENOMEM; 8128c2ecf20Sopenharmony_ci return ret; 8138c2ecf20Sopenharmony_ci} 8148c2ecf20Sopenharmony_ciEXPORT_SYMBOL(bman_acquire); 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_ciconst struct bm_portal_config * 8178c2ecf20Sopenharmony_cibman_get_bm_portal_config(const struct bman_portal *portal) 8188c2ecf20Sopenharmony_ci{ 8198c2ecf20Sopenharmony_ci return portal->config; 8208c2ecf20Sopenharmony_ci} 821