1296177Sjhibbits/****************************************************************************** 2296177Sjhibbits 3296177Sjhibbits � 1995-2003, 2004, 2005-2011 Freescale Semiconductor, Inc. 4296177Sjhibbits All rights reserved. 5296177Sjhibbits 6296177Sjhibbits This is proprietary source code of Freescale Semiconductor Inc., 7296177Sjhibbits and its use is subject to the NetComm Device Drivers EULA. 8296177Sjhibbits The copyright notice above does not evidence any actual or intended 9296177Sjhibbits publication of such source code. 10296177Sjhibbits 11296177Sjhibbits ALTERNATIVELY, redistribution and use in source and binary forms, with 12296177Sjhibbits or without modification, are permitted provided that the following 13296177Sjhibbits conditions are met: 14296177Sjhibbits * Redistributions of source code must retain the above copyright 15296177Sjhibbits notice, this list of conditions and the following disclaimer. 16296177Sjhibbits * Redistributions in binary form must reproduce the above copyright 17296177Sjhibbits notice, this list of conditions and the following disclaimer in the 18296177Sjhibbits documentation and/or other materials provided with the distribution. 19296177Sjhibbits * Neither the name of Freescale Semiconductor nor the 20296177Sjhibbits names of its contributors may be used to endorse or promote products 21296177Sjhibbits derived from this software without specific prior written permission. 22296177Sjhibbits 23296177Sjhibbits THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY 24296177Sjhibbits EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 25296177Sjhibbits WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 26296177Sjhibbits DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY 27296177Sjhibbits DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 28296177Sjhibbits (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29296177Sjhibbits LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 30296177Sjhibbits ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31296177Sjhibbits (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32296177Sjhibbits SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33296177Sjhibbits * 34296177Sjhibbits 35296177Sjhibbits **************************************************************************/ 36296177Sjhibbits/****************************************************************************** 37296177Sjhibbits @File bman_low.c 38296177Sjhibbits 39296177Sjhibbits @Description BM low-level implementation 40296177Sjhibbits*//***************************************************************************/ 41296177Sjhibbits#include "std_ext.h" 42296177Sjhibbits#include "core_ext.h" 43296177Sjhibbits#include "xx_ext.h" 44296177Sjhibbits#include "error_ext.h" 45296177Sjhibbits 46296177Sjhibbits#include "bman_private.h" 47296177Sjhibbits 48296177Sjhibbits 49296177Sjhibbits/***************************/ 50296177Sjhibbits/* Portal register assists */ 51296177Sjhibbits/***************************/ 52296177Sjhibbits 53296177Sjhibbits/* Cache-inhibited register offsets */ 54296177Sjhibbits#define REG_RCR_PI_CINH (void *)0x0000 55296177Sjhibbits#define REG_RCR_CI_CINH (void *)0x0004 56296177Sjhibbits#define REG_RCR_ITR (void *)0x0008 57296177Sjhibbits#define REG_CFG (void *)0x0100 58296177Sjhibbits#define REG_SCN(n) ((void *)(0x0200 + ((n) << 2))) 59296177Sjhibbits#define REG_ISR (void *)0x0e00 60296177Sjhibbits#define REG_IER (void *)0x0e04 61296177Sjhibbits#define REG_ISDR (void *)0x0e08 62296177Sjhibbits#define REG_IIR (void *)0x0e0c 63296177Sjhibbits 64296177Sjhibbits/* Cache-enabled register offsets */ 65296177Sjhibbits#define CL_CR (void *)0x0000 66296177Sjhibbits#define CL_RR0 (void *)0x0100 67296177Sjhibbits#define CL_RR1 (void *)0x0140 68296177Sjhibbits#define CL_RCR (void *)0x1000 69296177Sjhibbits#define CL_RCR_PI_CENA (void *)0x3000 70296177Sjhibbits#define CL_RCR_CI_CENA (void *)0x3100 71296177Sjhibbits 72296177Sjhibbits/* The h/w design requires mappings to be size-aligned so that "add"s can be 73296177Sjhibbits * reduced to "or"s. The primitives below do the same for s/w. */ 74296177Sjhibbits 75296177Sjhibbitsstatic __inline__ void *ptr_ADD(void *a, void *b) 76296177Sjhibbits{ 77296177Sjhibbits return (void *)((uintptr_t)a + (uintptr_t)b); 78296177Sjhibbits} 79296177Sjhibbits 80296177Sjhibbits/* Bitwise-OR two pointers */ 81296177Sjhibbitsstatic __inline__ void *ptr_OR(void *a, void *b) 82296177Sjhibbits{ 83296177Sjhibbits return (void *)((uintptr_t)a | (uintptr_t)b); 84296177Sjhibbits} 85296177Sjhibbits 86296177Sjhibbits/* Cache-inhibited register access */ 87296177Sjhibbitsstatic __inline__ uint32_t __bm_in(struct bm_addr *bm, void *offset) 88296177Sjhibbits{ 89296177Sjhibbits uint32_t *tmp = (uint32_t *)ptr_ADD(bm->addr_ci, offset); 90296177Sjhibbits return GET_UINT32(*tmp); 91296177Sjhibbits} 92296177Sjhibbitsstatic __inline__ void __bm_out(struct bm_addr *bm, void *offset, uint32_t val) 93296177Sjhibbits{ 94296177Sjhibbits uint32_t *tmp = (uint32_t *)ptr_ADD(bm->addr_ci, offset); 95296177Sjhibbits WRITE_UINT32(*tmp, val); 96296177Sjhibbits} 97296177Sjhibbits#define bm_in(reg) __bm_in(&portal->addr, REG_##reg) 98296177Sjhibbits#define bm_out(reg, val) __bm_out(&portal->addr, REG_##reg, val) 99296177Sjhibbits 100296177Sjhibbits/* Convert 'n' cachelines to a pointer value for bitwise OR */ 101296177Sjhibbits#define bm_cl(n) (void *)((n) << 6) 102296177Sjhibbits 103296177Sjhibbits/* Cache-enabled (index) register access */ 104296177Sjhibbitsstatic __inline__ void __bm_cl_touch_ro(struct bm_addr *bm, void *offset) 105296177Sjhibbits{ 106296177Sjhibbits dcbt_ro(ptr_ADD(bm->addr_ce, offset)); 107296177Sjhibbits} 108296177Sjhibbitsstatic __inline__ void __bm_cl_touch_rw(struct bm_addr *bm, void *offset) 109296177Sjhibbits{ 110296177Sjhibbits dcbt_rw(ptr_ADD(bm->addr_ce, offset)); 111296177Sjhibbits} 112296177Sjhibbitsstatic __inline__ uint32_t __bm_cl_in(struct bm_addr *bm, void *offset) 113296177Sjhibbits{ 114296177Sjhibbits uint32_t *tmp = (uint32_t *)ptr_ADD(bm->addr_ce, offset); 115296177Sjhibbits return GET_UINT32(*tmp); 116296177Sjhibbits} 117296177Sjhibbitsstatic __inline__ void __bm_cl_out(struct bm_addr *bm, void *offset, uint32_t val) 118296177Sjhibbits{ 119296177Sjhibbits uint32_t *tmp = (uint32_t *)ptr_ADD(bm->addr_ce, offset); 120296177Sjhibbits WRITE_UINT32(*tmp, val); 121296177Sjhibbits dcbf(tmp); 122296177Sjhibbits} 123296177Sjhibbitsstatic __inline__ void __bm_cl_invalidate(struct bm_addr *bm, void *offset) 124296177Sjhibbits{ 125296177Sjhibbits dcbi(ptr_ADD(bm->addr_ce, offset)); 126296177Sjhibbits} 127296177Sjhibbits#define bm_cl_touch_ro(reg) __bm_cl_touch_ro(&portal->addr, CL_##reg##_CENA) 128296177Sjhibbits#define bm_cl_touch_rw(reg) __bm_cl_touch_rw(&portal->addr, CL_##reg##_CENA) 129296177Sjhibbits#define bm_cl_in(reg) __bm_cl_in(&portal->addr, CL_##reg##_CENA) 130296177Sjhibbits#define bm_cl_out(reg, val) __bm_cl_out(&portal->addr, CL_##reg##_CENA, val) 131296177Sjhibbits#define bm_cl_invalidate(reg) __bm_cl_invalidate(&portal->addr, CL_##reg##_CENA) 132296177Sjhibbits 133296177Sjhibbits/* Cyclic helper for rings. TODO: once we are able to do fine-grain perf 134296177Sjhibbits * analysis, look at using the "extra" bit in the ring index registers to avoid 135296177Sjhibbits * cyclic issues. */ 136296177Sjhibbitsstatic __inline__ uint8_t cyc_diff(uint8_t ringsize, uint8_t first, uint8_t last) 137296177Sjhibbits{ 138296177Sjhibbits /* 'first' is included, 'last' is excluded */ 139296177Sjhibbits if (first <= last) 140296177Sjhibbits return (uint8_t)(last - first); 141296177Sjhibbits return (uint8_t)(ringsize + last - first); 142296177Sjhibbits} 143296177Sjhibbits 144296177Sjhibbits/* --------------- */ 145296177Sjhibbits/* --- RCR API --- */ 146296177Sjhibbits 147296177Sjhibbits/* It's safer to code in terms of the 'rcr' object than the 'portal' object, 148296177Sjhibbits * because the latter runs the risk of copy-n-paste errors from other code where 149296177Sjhibbits * we could manipulate some other structure within 'portal'. */ 150296177Sjhibbits/* #define RCR_API_START() register struct bm_rcr *rcr = &portal->rcr */ 151296177Sjhibbits 152296177Sjhibbits/* Bit-wise logic to wrap a ring pointer by clearing the "carry bit" */ 153296177Sjhibbits#define RCR_CARRYCLEAR(p) \ 154296177Sjhibbits (void *)((uintptr_t)(p) & (~(uintptr_t)(BM_RCR_SIZE << 6))) 155296177Sjhibbits 156296177Sjhibbits/* Bit-wise logic to convert a ring pointer to a ring index */ 157296177Sjhibbitsstatic __inline__ uint8_t RCR_PTR2IDX(struct bm_rcr_entry *e) 158296177Sjhibbits{ 159296177Sjhibbits return (uint8_t)(((uint32_t)e >> 6) & (BM_RCR_SIZE - 1)); 160296177Sjhibbits} 161296177Sjhibbits 162296177Sjhibbits/* Increment the 'cursor' ring pointer, taking 'vbit' into account */ 163296177Sjhibbitsstatic __inline__ void RCR_INC(struct bm_rcr *rcr) 164296177Sjhibbits{ 165296177Sjhibbits /* NB: this is odd-looking, but experiments show that it generates 166296177Sjhibbits * fast code with essentially no branching overheads. We increment to 167296177Sjhibbits * the next RCR pointer and handle overflow and 'vbit'. */ 168296177Sjhibbits struct bm_rcr_entry *partial = rcr->cursor + 1; 169296177Sjhibbits rcr->cursor = RCR_CARRYCLEAR(partial); 170296177Sjhibbits if (partial != rcr->cursor) 171296177Sjhibbits rcr->vbit ^= BM_RCR_VERB_VBIT; 172296177Sjhibbits} 173296177Sjhibbits 174296177Sjhibbitst_Error bm_rcr_init(struct bm_portal *portal, 175296177Sjhibbits e_BmPortalProduceMode pmode, 176296177Sjhibbits e_BmPortalRcrConsumeMode cmode) 177296177Sjhibbits{ 178296177Sjhibbits register struct bm_rcr *rcr = &portal->rcr; 179296177Sjhibbits uint32_t cfg; 180296177Sjhibbits uint8_t pi; 181296177Sjhibbits 182296177Sjhibbits rcr->ring = ptr_ADD(portal->addr.addr_ce, CL_RCR); 183296177Sjhibbits rcr->ci = (uint8_t)(bm_in(RCR_CI_CINH) & (BM_RCR_SIZE - 1)); 184296177Sjhibbits pi = (uint8_t)(bm_in(RCR_PI_CINH) & (BM_RCR_SIZE - 1)); 185296177Sjhibbits rcr->cursor = rcr->ring + pi; 186296177Sjhibbits rcr->vbit = (uint8_t)((bm_in(RCR_PI_CINH) & BM_RCR_SIZE) ? BM_RCR_VERB_VBIT : 0); 187296177Sjhibbits rcr->available = (uint8_t)(BM_RCR_SIZE - 1 - cyc_diff(BM_RCR_SIZE, rcr->ci, pi)); 188296177Sjhibbits rcr->ithresh = (uint8_t)bm_in(RCR_ITR); 189296177Sjhibbits#ifdef BM_CHECKING 190296177Sjhibbits rcr->busy = 0; 191296177Sjhibbits rcr->pmode = pmode; 192296177Sjhibbits rcr->cmode = cmode; 193296177Sjhibbits#else 194296177Sjhibbits UNUSED(cmode); 195296177Sjhibbits#endif /* BM_CHECKING */ 196296177Sjhibbits cfg = (bm_in(CFG) & 0xffffffe0) | (pmode & 0x3); /* BCSP_CFG::RPM */ 197296177Sjhibbits bm_out(CFG, cfg); 198296177Sjhibbits return 0; 199296177Sjhibbits} 200296177Sjhibbits 201296177Sjhibbitsvoid bm_rcr_finish(struct bm_portal *portal) 202296177Sjhibbits{ 203296177Sjhibbits register struct bm_rcr *rcr = &portal->rcr; 204296177Sjhibbits uint8_t pi = (uint8_t)(bm_in(RCR_PI_CINH) & (BM_RCR_SIZE - 1)); 205296177Sjhibbits uint8_t ci = (uint8_t)(bm_in(RCR_CI_CINH) & (BM_RCR_SIZE - 1)); 206296177Sjhibbits ASSERT_COND(!rcr->busy); 207296177Sjhibbits if (pi != RCR_PTR2IDX(rcr->cursor)) 208296177Sjhibbits REPORT_ERROR(WARNING, E_INVALID_STATE, ("losing uncommitted RCR entries")); 209296177Sjhibbits if (ci != rcr->ci) 210296177Sjhibbits REPORT_ERROR(WARNING, E_INVALID_STATE, ("missing existing RCR completions")); 211296177Sjhibbits if (rcr->ci != RCR_PTR2IDX(rcr->cursor)) 212296177Sjhibbits REPORT_ERROR(WARNING, E_INVALID_STATE, ("RCR destroyed unquiesced")); 213296177Sjhibbits} 214296177Sjhibbits 215296177Sjhibbitsstruct bm_rcr_entry *bm_rcr_start(struct bm_portal *portal) 216296177Sjhibbits{ 217296177Sjhibbits register struct bm_rcr *rcr = &portal->rcr; 218296177Sjhibbits ASSERT_COND(!rcr->busy); 219296177Sjhibbits if (!rcr->available) 220296177Sjhibbits return NULL; 221296177Sjhibbits#ifdef BM_CHECKING 222296177Sjhibbits rcr->busy = 1; 223296177Sjhibbits#endif /* BM_CHECKING */ 224296177Sjhibbits dcbz_64(rcr->cursor); 225296177Sjhibbits return rcr->cursor; 226296177Sjhibbits} 227296177Sjhibbits 228296177Sjhibbitsvoid bm_rcr_abort(struct bm_portal *portal) 229296177Sjhibbits{ 230296177Sjhibbits register struct bm_rcr *rcr = &portal->rcr; 231296177Sjhibbits ASSERT_COND(rcr->busy); 232296177Sjhibbits#ifdef BM_CHECKING 233296177Sjhibbits rcr->busy = 0; 234296177Sjhibbits#else 235296177Sjhibbits UNUSED(rcr); 236296177Sjhibbits#endif /* BM_CHECKING */ 237296177Sjhibbits} 238296177Sjhibbits 239296177Sjhibbitsstruct bm_rcr_entry *bm_rcr_pend_and_next(struct bm_portal *portal, uint8_t myverb) 240296177Sjhibbits{ 241296177Sjhibbits register struct bm_rcr *rcr = &portal->rcr; 242296177Sjhibbits ASSERT_COND(rcr->busy); 243296177Sjhibbits ASSERT_COND(rcr->pmode != e_BmPortalPVB); 244296177Sjhibbits if (rcr->available == 1) 245296177Sjhibbits return NULL; 246296177Sjhibbits rcr->cursor->__dont_write_directly__verb = (uint8_t)(myverb | rcr->vbit); 247296177Sjhibbits dcbf_64(rcr->cursor); 248296177Sjhibbits RCR_INC(rcr); 249296177Sjhibbits rcr->available--; 250296177Sjhibbits dcbz_64(rcr->cursor); 251296177Sjhibbits return rcr->cursor; 252296177Sjhibbits} 253296177Sjhibbits 254296177Sjhibbitsvoid bm_rcr_pci_commit(struct bm_portal *portal, uint8_t myverb) 255296177Sjhibbits{ 256296177Sjhibbits register struct bm_rcr *rcr = &portal->rcr; 257296177Sjhibbits ASSERT_COND(rcr->busy); 258296177Sjhibbits ASSERT_COND(rcr->pmode == e_BmPortalPCI); 259296177Sjhibbits rcr->cursor->__dont_write_directly__verb = (uint8_t)(myverb | rcr->vbit); 260296177Sjhibbits RCR_INC(rcr); 261296177Sjhibbits rcr->available--; 262296177Sjhibbits hwsync(); 263296177Sjhibbits bm_out(RCR_PI_CINH, RCR_PTR2IDX(rcr->cursor)); 264296177Sjhibbits#ifdef BM_CHECKING 265296177Sjhibbits rcr->busy = 0; 266296177Sjhibbits#endif /* BM_CHECKING */ 267296177Sjhibbits} 268296177Sjhibbits 269296177Sjhibbitsvoid bm_rcr_pce_prefetch(struct bm_portal *portal) 270296177Sjhibbits{ 271296177Sjhibbits ASSERT_COND(((struct bm_rcr *)&portal->rcr)->pmode == e_BmPortalPCE); 272296177Sjhibbits bm_cl_invalidate(RCR_PI); 273296177Sjhibbits bm_cl_touch_rw(RCR_PI); 274296177Sjhibbits} 275296177Sjhibbits 276296177Sjhibbitsvoid bm_rcr_pce_commit(struct bm_portal *portal, uint8_t myverb) 277296177Sjhibbits{ 278296177Sjhibbits register struct bm_rcr *rcr = &portal->rcr; 279296177Sjhibbits ASSERT_COND(rcr->busy); 280296177Sjhibbits ASSERT_COND(rcr->pmode == e_BmPortalPCE); 281296177Sjhibbits rcr->cursor->__dont_write_directly__verb = (uint8_t)(myverb | rcr->vbit); 282296177Sjhibbits RCR_INC(rcr); 283296177Sjhibbits rcr->available--; 284296177Sjhibbits lwsync(); 285296177Sjhibbits bm_cl_out(RCR_PI, RCR_PTR2IDX(rcr->cursor)); 286296177Sjhibbits#ifdef BM_CHECKING 287296177Sjhibbits rcr->busy = 0; 288296177Sjhibbits#endif /* BM_CHECKING */ 289296177Sjhibbits} 290296177Sjhibbits 291296177Sjhibbitsvoid bm_rcr_pvb_commit(struct bm_portal *portal, uint8_t myverb) 292296177Sjhibbits{ 293296177Sjhibbits register struct bm_rcr *rcr = &portal->rcr; 294296177Sjhibbits struct bm_rcr_entry *rcursor; 295296177Sjhibbits ASSERT_COND(rcr->busy); 296296177Sjhibbits ASSERT_COND(rcr->pmode == e_BmPortalPVB); 297296177Sjhibbits lwsync(); 298296177Sjhibbits rcursor = rcr->cursor; 299296177Sjhibbits rcursor->__dont_write_directly__verb = (uint8_t)(myverb | rcr->vbit); 300296177Sjhibbits dcbf_64(rcursor); 301296177Sjhibbits RCR_INC(rcr); 302296177Sjhibbits rcr->available--; 303296177Sjhibbits#ifdef BM_CHECKING 304296177Sjhibbits rcr->busy = 0; 305296177Sjhibbits#endif /* BM_CHECKING */ 306296177Sjhibbits} 307296177Sjhibbits 308296177Sjhibbits 309296177Sjhibbitsuint8_t bm_rcr_cci_update(struct bm_portal *portal) 310296177Sjhibbits{ 311296177Sjhibbits register struct bm_rcr *rcr = &portal->rcr; 312296177Sjhibbits uint8_t diff, old_ci = rcr->ci; 313296177Sjhibbits ASSERT_COND(rcr->cmode == e_BmPortalRcrCCI); 314296177Sjhibbits rcr->ci = (uint8_t)(bm_in(RCR_CI_CINH) & (BM_RCR_SIZE - 1)); 315296177Sjhibbits diff = cyc_diff(BM_RCR_SIZE, old_ci, rcr->ci); 316296177Sjhibbits rcr->available += diff; 317296177Sjhibbits return diff; 318296177Sjhibbits} 319296177Sjhibbits 320296177Sjhibbits 321296177Sjhibbitsvoid bm_rcr_cce_prefetch(struct bm_portal *portal) 322296177Sjhibbits{ 323296177Sjhibbits ASSERT_COND(((struct bm_rcr *)&portal->rcr)->cmode == e_BmPortalRcrCCE); 324296177Sjhibbits bm_cl_touch_ro(RCR_CI); 325296177Sjhibbits} 326296177Sjhibbits 327296177Sjhibbits 328296177Sjhibbitsuint8_t bm_rcr_cce_update(struct bm_portal *portal) 329296177Sjhibbits{ 330296177Sjhibbits register struct bm_rcr *rcr = &portal->rcr; 331296177Sjhibbits uint8_t diff, old_ci = rcr->ci; 332296177Sjhibbits ASSERT_COND(rcr->cmode == e_BmPortalRcrCCE); 333296177Sjhibbits rcr->ci = (uint8_t)(bm_cl_in(RCR_CI) & (BM_RCR_SIZE - 1)); 334296177Sjhibbits bm_cl_invalidate(RCR_CI); 335296177Sjhibbits diff = cyc_diff(BM_RCR_SIZE, old_ci, rcr->ci); 336296177Sjhibbits rcr->available += diff; 337296177Sjhibbits return diff; 338296177Sjhibbits} 339296177Sjhibbits 340296177Sjhibbits 341296177Sjhibbitsuint8_t bm_rcr_get_ithresh(struct bm_portal *portal) 342296177Sjhibbits{ 343296177Sjhibbits register struct bm_rcr *rcr = &portal->rcr; 344296177Sjhibbits return rcr->ithresh; 345296177Sjhibbits} 346296177Sjhibbits 347296177Sjhibbits 348296177Sjhibbitsvoid bm_rcr_set_ithresh(struct bm_portal *portal, uint8_t ithresh) 349296177Sjhibbits{ 350296177Sjhibbits register struct bm_rcr *rcr = &portal->rcr; 351296177Sjhibbits rcr->ithresh = ithresh; 352296177Sjhibbits bm_out(RCR_ITR, ithresh); 353296177Sjhibbits} 354296177Sjhibbits 355296177Sjhibbits 356296177Sjhibbitsuint8_t bm_rcr_get_avail(struct bm_portal *portal) 357296177Sjhibbits{ 358296177Sjhibbits register struct bm_rcr *rcr = &portal->rcr; 359296177Sjhibbits return rcr->available; 360296177Sjhibbits} 361296177Sjhibbits 362296177Sjhibbits 363296177Sjhibbitsuint8_t bm_rcr_get_fill(struct bm_portal *portal) 364296177Sjhibbits{ 365296177Sjhibbits register struct bm_rcr *rcr = &portal->rcr; 366296177Sjhibbits return (uint8_t)(BM_RCR_SIZE - 1 - rcr->available); 367296177Sjhibbits} 368296177Sjhibbits 369296177Sjhibbits 370296177Sjhibbits/* ------------------------------ */ 371296177Sjhibbits/* --- Management command API --- */ 372296177Sjhibbits 373296177Sjhibbits/* It's safer to code in terms of the 'mc' object than the 'portal' object, 374296177Sjhibbits * because the latter runs the risk of copy-n-paste errors from other code where 375296177Sjhibbits * we could manipulate some other structure within 'portal'. */ 376296177Sjhibbits/* #define MC_API_START() register struct bm_mc *mc = &portal->mc */ 377296177Sjhibbits 378296177Sjhibbits 379296177Sjhibbitst_Error bm_mc_init(struct bm_portal *portal) 380296177Sjhibbits{ 381296177Sjhibbits register struct bm_mc *mc = &portal->mc; 382296177Sjhibbits mc->cr = ptr_ADD(portal->addr.addr_ce, CL_CR); 383296177Sjhibbits mc->rr = ptr_ADD(portal->addr.addr_ce, CL_RR0); 384296177Sjhibbits mc->rridx = (uint8_t)((mc->cr->__dont_write_directly__verb & BM_MCC_VERB_VBIT) ? 385296177Sjhibbits 0 : 1); 386296177Sjhibbits mc->vbit = (uint8_t)(mc->rridx ? BM_MCC_VERB_VBIT : 0); 387296177Sjhibbits#ifdef BM_CHECKING 388296177Sjhibbits mc->state = mc_idle; 389296177Sjhibbits#endif /* BM_CHECKING */ 390296177Sjhibbits return 0; 391296177Sjhibbits} 392296177Sjhibbits 393296177Sjhibbits 394296177Sjhibbitsvoid bm_mc_finish(struct bm_portal *portal) 395296177Sjhibbits{ 396296177Sjhibbits register struct bm_mc *mc = &portal->mc; 397296177Sjhibbits ASSERT_COND(mc->state == mc_idle); 398296177Sjhibbits#ifdef BM_CHECKING 399296177Sjhibbits if (mc->state != mc_idle) 400296177Sjhibbits REPORT_ERROR(WARNING, E_INVALID_STATE, ("Losing incomplete MC command")); 401296177Sjhibbits#else 402296177Sjhibbits UNUSED(mc); 403296177Sjhibbits#endif /* BM_CHECKING */ 404296177Sjhibbits} 405296177Sjhibbits 406296177Sjhibbits 407296177Sjhibbitsstruct bm_mc_command *bm_mc_start(struct bm_portal *portal) 408296177Sjhibbits{ 409296177Sjhibbits register struct bm_mc *mc = &portal->mc; 410296177Sjhibbits ASSERT_COND(mc->state == mc_idle); 411296177Sjhibbits#ifdef BM_CHECKING 412296177Sjhibbits mc->state = mc_user; 413296177Sjhibbits#endif /* BM_CHECKING */ 414296177Sjhibbits dcbz_64(mc->cr); 415296177Sjhibbits return mc->cr; 416296177Sjhibbits} 417296177Sjhibbits 418296177Sjhibbits 419296177Sjhibbitsvoid bm_mc_abort(struct bm_portal *portal) 420296177Sjhibbits{ 421296177Sjhibbits register struct bm_mc *mc = &portal->mc; 422296177Sjhibbits ASSERT_COND(mc->state == mc_user); 423296177Sjhibbits#ifdef BM_CHECKING 424296177Sjhibbits mc->state = mc_idle; 425296177Sjhibbits#else 426296177Sjhibbits UNUSED(mc); 427296177Sjhibbits#endif /* BM_CHECKING */ 428296177Sjhibbits} 429296177Sjhibbits 430296177Sjhibbits 431296177Sjhibbitsvoid bm_mc_commit(struct bm_portal *portal, uint8_t myverb) 432296177Sjhibbits{ 433296177Sjhibbits register struct bm_mc *mc = &portal->mc; 434296177Sjhibbits ASSERT_COND(mc->state == mc_user); 435296177Sjhibbits lwsync(); 436296177Sjhibbits mc->cr->__dont_write_directly__verb = (uint8_t)(myverb | mc->vbit); 437296177Sjhibbits dcbf_64(mc->cr); 438296177Sjhibbits dcbit_ro(mc->rr + mc->rridx); 439296177Sjhibbits#ifdef BM_CHECKING 440296177Sjhibbits mc->state = mc_hw; 441296177Sjhibbits#endif /* BM_CHECKING */ 442296177Sjhibbits} 443296177Sjhibbits 444296177Sjhibbits 445296177Sjhibbitsstruct bm_mc_result *bm_mc_result(struct bm_portal *portal) 446296177Sjhibbits{ 447296177Sjhibbits register struct bm_mc *mc = &portal->mc; 448296177Sjhibbits struct bm_mc_result *rr = mc->rr + mc->rridx; 449296177Sjhibbits ASSERT_COND(mc->state == mc_hw); 450296177Sjhibbits /* The inactive response register's verb byte always returns zero until 451296177Sjhibbits * its command is submitted and completed. This includes the valid-bit, 452296177Sjhibbits * in case you were wondering... */ 453296177Sjhibbits if (!rr->verb) { 454296177Sjhibbits dcbit_ro(rr); 455296177Sjhibbits return NULL; 456296177Sjhibbits } 457296177Sjhibbits mc->rridx ^= 1; 458296177Sjhibbits mc->vbit ^= BM_MCC_VERB_VBIT; 459296177Sjhibbits#ifdef BM_CHECKING 460296177Sjhibbits mc->state = mc_idle; 461296177Sjhibbits#endif /* BM_CHECKING */ 462296177Sjhibbits return rr; 463296177Sjhibbits} 464296177Sjhibbits 465296177Sjhibbits/* ------------------------------------- */ 466296177Sjhibbits/* --- Portal interrupt register API --- */ 467296177Sjhibbits 468296177Sjhibbits#define SCN_REG(bpid) REG_SCN((bpid) / 32) 469296177Sjhibbits#define SCN_BIT(bpid) (0x80000000 >> (bpid & 31)) 470296177Sjhibbitsvoid bm_isr_bscn_mask(struct bm_portal *portal, uint8_t bpid, int enable) 471296177Sjhibbits{ 472296177Sjhibbits uint32_t val; 473296177Sjhibbits ASSERT_COND(bpid < BM_MAX_NUM_OF_POOLS); 474296177Sjhibbits /* REG_SCN for bpid=0..31, REG_SCN+4 for bpid=32..63 */ 475296177Sjhibbits val = __bm_in(&portal->addr, SCN_REG(bpid)); 476296177Sjhibbits if (enable) 477296177Sjhibbits val |= SCN_BIT(bpid); 478296177Sjhibbits else 479296177Sjhibbits val &= ~SCN_BIT(bpid); 480296177Sjhibbits __bm_out(&portal->addr, SCN_REG(bpid), val); 481296177Sjhibbits} 482296177Sjhibbits 483296177Sjhibbits 484296177Sjhibbitsuint32_t __bm_isr_read(struct bm_portal *portal, enum bm_isr_reg n) 485296177Sjhibbits{ 486296177Sjhibbits return __bm_in(&portal->addr, PTR_MOVE(REG_ISR, (n << 2))); 487296177Sjhibbits} 488296177Sjhibbits 489296177Sjhibbits 490296177Sjhibbitsvoid __bm_isr_write(struct bm_portal *portal, enum bm_isr_reg n, uint32_t val) 491296177Sjhibbits{ 492296177Sjhibbits __bm_out(&portal->addr, PTR_MOVE(REG_ISR, (n << 2)), val); 493296177Sjhibbits} 494296177Sjhibbits 495