10aeed3e9SJustin Hibbits /******************************************************************************
20aeed3e9SJustin Hibbits
30aeed3e9SJustin Hibbits � 1995-2003, 2004, 2005-2011 Freescale Semiconductor, Inc.
40aeed3e9SJustin Hibbits All rights reserved.
50aeed3e9SJustin Hibbits
60aeed3e9SJustin Hibbits This is proprietary source code of Freescale Semiconductor Inc.,
70aeed3e9SJustin Hibbits and its use is subject to the NetComm Device Drivers EULA.
80aeed3e9SJustin Hibbits The copyright notice above does not evidence any actual or intended
90aeed3e9SJustin Hibbits publication of such source code.
100aeed3e9SJustin Hibbits
110aeed3e9SJustin Hibbits ALTERNATIVELY, redistribution and use in source and binary forms, with
120aeed3e9SJustin Hibbits or without modification, are permitted provided that the following
130aeed3e9SJustin Hibbits conditions are met:
140aeed3e9SJustin Hibbits * Redistributions of source code must retain the above copyright
150aeed3e9SJustin Hibbits notice, this list of conditions and the following disclaimer.
160aeed3e9SJustin Hibbits * Redistributions in binary form must reproduce the above copyright
170aeed3e9SJustin Hibbits notice, this list of conditions and the following disclaimer in the
180aeed3e9SJustin Hibbits documentation and/or other materials provided with the distribution.
190aeed3e9SJustin Hibbits * Neither the name of Freescale Semiconductor nor the
200aeed3e9SJustin Hibbits names of its contributors may be used to endorse or promote products
210aeed3e9SJustin Hibbits derived from this software without specific prior written permission.
220aeed3e9SJustin Hibbits
230aeed3e9SJustin Hibbits THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
240aeed3e9SJustin Hibbits EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
250aeed3e9SJustin Hibbits WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
260aeed3e9SJustin Hibbits DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
270aeed3e9SJustin Hibbits DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
280aeed3e9SJustin Hibbits (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
290aeed3e9SJustin Hibbits LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
300aeed3e9SJustin Hibbits ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
310aeed3e9SJustin Hibbits (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
320aeed3e9SJustin Hibbits SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
330aeed3e9SJustin Hibbits *
340aeed3e9SJustin Hibbits
350aeed3e9SJustin Hibbits **************************************************************************/
360aeed3e9SJustin Hibbits /******************************************************************************
370aeed3e9SJustin Hibbits @File bman_low.c
380aeed3e9SJustin Hibbits
390aeed3e9SJustin Hibbits @Description BM low-level implementation
400aeed3e9SJustin Hibbits *//***************************************************************************/
41*852ba100SJustin Hibbits #include <sys/cdefs.h>
42*852ba100SJustin Hibbits #include <sys/types.h>
43*852ba100SJustin Hibbits #include <machine/atomic.h>
44*852ba100SJustin Hibbits
450aeed3e9SJustin Hibbits #include "std_ext.h"
460aeed3e9SJustin Hibbits #include "core_ext.h"
470aeed3e9SJustin Hibbits #include "xx_ext.h"
480aeed3e9SJustin Hibbits #include "error_ext.h"
490aeed3e9SJustin Hibbits
500aeed3e9SJustin Hibbits #include "bman_private.h"
510aeed3e9SJustin Hibbits
520aeed3e9SJustin Hibbits
530aeed3e9SJustin Hibbits /***************************/
540aeed3e9SJustin Hibbits /* Portal register assists */
550aeed3e9SJustin Hibbits /***************************/
560aeed3e9SJustin Hibbits
570aeed3e9SJustin Hibbits /* Cache-inhibited register offsets */
58f77405e3SJustin Hibbits #define REG_RCR_PI_CINH 0x0000
59f77405e3SJustin Hibbits #define REG_RCR_CI_CINH 0x0004
60f77405e3SJustin Hibbits #define REG_RCR_ITR 0x0008
61f77405e3SJustin Hibbits #define REG_CFG 0x0100
62f77405e3SJustin Hibbits #define REG_SCN(n) (0x0200 + ((n) << 2))
63f77405e3SJustin Hibbits #define REG_ISR 0x0e00
64f77405e3SJustin Hibbits #define REG_IER 0x0e04
65f77405e3SJustin Hibbits #define REG_ISDR 0x0e08
66f77405e3SJustin Hibbits #define REG_IIR 0x0e0c
670aeed3e9SJustin Hibbits
680aeed3e9SJustin Hibbits /* Cache-enabled register offsets */
69f77405e3SJustin Hibbits #define CL_CR 0x0000
70f77405e3SJustin Hibbits #define CL_RR0 0x0100
71f77405e3SJustin Hibbits #define CL_RR1 0x0140
72f77405e3SJustin Hibbits #define CL_RCR 0x1000
73f77405e3SJustin Hibbits #define CL_RCR_PI_CENA 0x3000
74f77405e3SJustin Hibbits #define CL_RCR_CI_CENA 0x3100
750aeed3e9SJustin Hibbits
760aeed3e9SJustin Hibbits /* The h/w design requires mappings to be size-aligned so that "add"s can be
770aeed3e9SJustin Hibbits * reduced to "or"s. The primitives below do the same for s/w. */
780aeed3e9SJustin Hibbits
ptr_ADD(void * a,uintptr_t b)79f77405e3SJustin Hibbits static __inline__ void *ptr_ADD(void *a, uintptr_t b)
800aeed3e9SJustin Hibbits {
81f77405e3SJustin Hibbits return (void *)((uintptr_t)a + b);
820aeed3e9SJustin Hibbits }
830aeed3e9SJustin Hibbits
840aeed3e9SJustin Hibbits /* Bitwise-OR two pointers */
ptr_OR(void * a,uintptr_t b)85f77405e3SJustin Hibbits static __inline__ void *ptr_OR(void *a, uintptr_t b)
860aeed3e9SJustin Hibbits {
87f77405e3SJustin Hibbits return (void *)((uintptr_t)a | b);
880aeed3e9SJustin Hibbits }
890aeed3e9SJustin Hibbits
900aeed3e9SJustin Hibbits /* Cache-inhibited register access */
__bm_in(struct bm_addr * bm,uintptr_t offset)91f77405e3SJustin Hibbits static __inline__ uint32_t __bm_in(struct bm_addr *bm, uintptr_t offset)
920aeed3e9SJustin Hibbits {
930aeed3e9SJustin Hibbits uint32_t *tmp = (uint32_t *)ptr_ADD(bm->addr_ci, offset);
940aeed3e9SJustin Hibbits return GET_UINT32(*tmp);
950aeed3e9SJustin Hibbits }
__bm_out(struct bm_addr * bm,uintptr_t offset,uint32_t val)96f77405e3SJustin Hibbits static __inline__ void __bm_out(struct bm_addr *bm, uintptr_t offset, uint32_t val)
970aeed3e9SJustin Hibbits {
980aeed3e9SJustin Hibbits uint32_t *tmp = (uint32_t *)ptr_ADD(bm->addr_ci, offset);
990aeed3e9SJustin Hibbits WRITE_UINT32(*tmp, val);
1000aeed3e9SJustin Hibbits }
1010aeed3e9SJustin Hibbits #define bm_in(reg) __bm_in(&portal->addr, REG_##reg)
1020aeed3e9SJustin Hibbits #define bm_out(reg, val) __bm_out(&portal->addr, REG_##reg, val)
1030aeed3e9SJustin Hibbits
1040aeed3e9SJustin Hibbits /* Convert 'n' cachelines to a pointer value for bitwise OR */
1050aeed3e9SJustin Hibbits #define bm_cl(n) (void *)((n) << 6)
1060aeed3e9SJustin Hibbits
1070aeed3e9SJustin Hibbits /* Cache-enabled (index) register access */
__bm_cl_touch_ro(struct bm_addr * bm,uintptr_t offset)108f77405e3SJustin Hibbits static __inline__ void __bm_cl_touch_ro(struct bm_addr *bm, uintptr_t offset)
1090aeed3e9SJustin Hibbits {
1100aeed3e9SJustin Hibbits dcbt_ro(ptr_ADD(bm->addr_ce, offset));
1110aeed3e9SJustin Hibbits }
__bm_cl_touch_rw(struct bm_addr * bm,uintptr_t offset)112f77405e3SJustin Hibbits static __inline__ void __bm_cl_touch_rw(struct bm_addr *bm, uintptr_t offset)
1130aeed3e9SJustin Hibbits {
1140aeed3e9SJustin Hibbits dcbt_rw(ptr_ADD(bm->addr_ce, offset));
1150aeed3e9SJustin Hibbits }
__bm_cl_in(struct bm_addr * bm,uintptr_t offset)116f77405e3SJustin Hibbits static __inline__ uint32_t __bm_cl_in(struct bm_addr *bm, uintptr_t offset)
1170aeed3e9SJustin Hibbits {
1180aeed3e9SJustin Hibbits uint32_t *tmp = (uint32_t *)ptr_ADD(bm->addr_ce, offset);
1190aeed3e9SJustin Hibbits return GET_UINT32(*tmp);
1200aeed3e9SJustin Hibbits }
__bm_cl_out(struct bm_addr * bm,uintptr_t offset,uint32_t val)121f77405e3SJustin Hibbits static __inline__ void __bm_cl_out(struct bm_addr *bm, uintptr_t offset, uint32_t val)
1220aeed3e9SJustin Hibbits {
1230aeed3e9SJustin Hibbits uint32_t *tmp = (uint32_t *)ptr_ADD(bm->addr_ce, offset);
1240aeed3e9SJustin Hibbits WRITE_UINT32(*tmp, val);
1250aeed3e9SJustin Hibbits dcbf(tmp);
1260aeed3e9SJustin Hibbits }
__bm_cl_invalidate(struct bm_addr * bm,uintptr_t offset)127f77405e3SJustin Hibbits static __inline__ void __bm_cl_invalidate(struct bm_addr *bm, uintptr_t offset)
1280aeed3e9SJustin Hibbits {
1290aeed3e9SJustin Hibbits dcbi(ptr_ADD(bm->addr_ce, offset));
1300aeed3e9SJustin Hibbits }
1310aeed3e9SJustin Hibbits #define bm_cl_touch_ro(reg) __bm_cl_touch_ro(&portal->addr, CL_##reg##_CENA)
1320aeed3e9SJustin Hibbits #define bm_cl_touch_rw(reg) __bm_cl_touch_rw(&portal->addr, CL_##reg##_CENA)
1330aeed3e9SJustin Hibbits #define bm_cl_in(reg) __bm_cl_in(&portal->addr, CL_##reg##_CENA)
1340aeed3e9SJustin Hibbits #define bm_cl_out(reg, val) __bm_cl_out(&portal->addr, CL_##reg##_CENA, val)
1350aeed3e9SJustin Hibbits #define bm_cl_invalidate(reg) __bm_cl_invalidate(&portal->addr, CL_##reg##_CENA)
1360aeed3e9SJustin Hibbits
1370aeed3e9SJustin Hibbits /* Cyclic helper for rings. TODO: once we are able to do fine-grain perf
1380aeed3e9SJustin Hibbits * analysis, look at using the "extra" bit in the ring index registers to avoid
1390aeed3e9SJustin Hibbits * cyclic issues. */
cyc_diff(uint8_t ringsize,uint8_t first,uint8_t last)1400aeed3e9SJustin Hibbits static __inline__ uint8_t cyc_diff(uint8_t ringsize, uint8_t first, uint8_t last)
1410aeed3e9SJustin Hibbits {
1420aeed3e9SJustin Hibbits /* 'first' is included, 'last' is excluded */
1430aeed3e9SJustin Hibbits if (first <= last)
1440aeed3e9SJustin Hibbits return (uint8_t)(last - first);
1450aeed3e9SJustin Hibbits return (uint8_t)(ringsize + last - first);
1460aeed3e9SJustin Hibbits }
1470aeed3e9SJustin Hibbits
1480aeed3e9SJustin Hibbits /* --------------- */
1490aeed3e9SJustin Hibbits /* --- RCR API --- */
1500aeed3e9SJustin Hibbits
1510aeed3e9SJustin Hibbits /* It's safer to code in terms of the 'rcr' object than the 'portal' object,
1520aeed3e9SJustin Hibbits * because the latter runs the risk of copy-n-paste errors from other code where
1530aeed3e9SJustin Hibbits * we could manipulate some other structure within 'portal'. */
1540aeed3e9SJustin Hibbits /* #define RCR_API_START() register struct bm_rcr *rcr = &portal->rcr */
1550aeed3e9SJustin Hibbits
1560aeed3e9SJustin Hibbits /* Bit-wise logic to wrap a ring pointer by clearing the "carry bit" */
1570aeed3e9SJustin Hibbits #define RCR_CARRYCLEAR(p) \
1580aeed3e9SJustin Hibbits (void *)((uintptr_t)(p) & (~(uintptr_t)(BM_RCR_SIZE << 6)))
1590aeed3e9SJustin Hibbits
1600aeed3e9SJustin Hibbits /* Bit-wise logic to convert a ring pointer to a ring index */
RCR_PTR2IDX(struct bm_rcr_entry * e)1610aeed3e9SJustin Hibbits static __inline__ uint8_t RCR_PTR2IDX(struct bm_rcr_entry *e)
1620aeed3e9SJustin Hibbits {
163f77405e3SJustin Hibbits return (uint8_t)(((uintptr_t)e >> 6) & (BM_RCR_SIZE - 1));
1640aeed3e9SJustin Hibbits }
1650aeed3e9SJustin Hibbits
1660aeed3e9SJustin Hibbits /* Increment the 'cursor' ring pointer, taking 'vbit' into account */
RCR_INC(struct bm_rcr * rcr)1670aeed3e9SJustin Hibbits static __inline__ void RCR_INC(struct bm_rcr *rcr)
1680aeed3e9SJustin Hibbits {
1690aeed3e9SJustin Hibbits /* NB: this is odd-looking, but experiments show that it generates
1700aeed3e9SJustin Hibbits * fast code with essentially no branching overheads. We increment to
1710aeed3e9SJustin Hibbits * the next RCR pointer and handle overflow and 'vbit'. */
1720aeed3e9SJustin Hibbits struct bm_rcr_entry *partial = rcr->cursor + 1;
1730aeed3e9SJustin Hibbits rcr->cursor = RCR_CARRYCLEAR(partial);
1740aeed3e9SJustin Hibbits if (partial != rcr->cursor)
1750aeed3e9SJustin Hibbits rcr->vbit ^= BM_RCR_VERB_VBIT;
1760aeed3e9SJustin Hibbits }
1770aeed3e9SJustin Hibbits
bm_rcr_init(struct bm_portal * portal,e_BmPortalProduceMode pmode,e_BmPortalRcrConsumeMode cmode)1780aeed3e9SJustin Hibbits t_Error bm_rcr_init(struct bm_portal *portal,
1790aeed3e9SJustin Hibbits e_BmPortalProduceMode pmode,
1800aeed3e9SJustin Hibbits e_BmPortalRcrConsumeMode cmode)
1810aeed3e9SJustin Hibbits {
1820aeed3e9SJustin Hibbits register struct bm_rcr *rcr = &portal->rcr;
1830aeed3e9SJustin Hibbits uint32_t cfg;
1840aeed3e9SJustin Hibbits uint8_t pi;
1850aeed3e9SJustin Hibbits
1860aeed3e9SJustin Hibbits rcr->ring = ptr_ADD(portal->addr.addr_ce, CL_RCR);
1870aeed3e9SJustin Hibbits rcr->ci = (uint8_t)(bm_in(RCR_CI_CINH) & (BM_RCR_SIZE - 1));
1880aeed3e9SJustin Hibbits pi = (uint8_t)(bm_in(RCR_PI_CINH) & (BM_RCR_SIZE - 1));
1890aeed3e9SJustin Hibbits rcr->cursor = rcr->ring + pi;
1900aeed3e9SJustin Hibbits rcr->vbit = (uint8_t)((bm_in(RCR_PI_CINH) & BM_RCR_SIZE) ? BM_RCR_VERB_VBIT : 0);
1910aeed3e9SJustin Hibbits rcr->available = (uint8_t)(BM_RCR_SIZE - 1 - cyc_diff(BM_RCR_SIZE, rcr->ci, pi));
1920aeed3e9SJustin Hibbits rcr->ithresh = (uint8_t)bm_in(RCR_ITR);
1930aeed3e9SJustin Hibbits #ifdef BM_CHECKING
1940aeed3e9SJustin Hibbits rcr->busy = 0;
1950aeed3e9SJustin Hibbits rcr->pmode = pmode;
1960aeed3e9SJustin Hibbits rcr->cmode = cmode;
1970aeed3e9SJustin Hibbits #else
1980aeed3e9SJustin Hibbits UNUSED(cmode);
1990aeed3e9SJustin Hibbits #endif /* BM_CHECKING */
2000aeed3e9SJustin Hibbits cfg = (bm_in(CFG) & 0xffffffe0) | (pmode & 0x3); /* BCSP_CFG::RPM */
2010aeed3e9SJustin Hibbits bm_out(CFG, cfg);
2020aeed3e9SJustin Hibbits return 0;
2030aeed3e9SJustin Hibbits }
2040aeed3e9SJustin Hibbits
bm_rcr_finish(struct bm_portal * portal)2050aeed3e9SJustin Hibbits void bm_rcr_finish(struct bm_portal *portal)
2060aeed3e9SJustin Hibbits {
2070aeed3e9SJustin Hibbits register struct bm_rcr *rcr = &portal->rcr;
2080aeed3e9SJustin Hibbits uint8_t pi = (uint8_t)(bm_in(RCR_PI_CINH) & (BM_RCR_SIZE - 1));
2090aeed3e9SJustin Hibbits uint8_t ci = (uint8_t)(bm_in(RCR_CI_CINH) & (BM_RCR_SIZE - 1));
2100aeed3e9SJustin Hibbits ASSERT_COND(!rcr->busy);
2110aeed3e9SJustin Hibbits if (pi != RCR_PTR2IDX(rcr->cursor))
2120aeed3e9SJustin Hibbits REPORT_ERROR(WARNING, E_INVALID_STATE, ("losing uncommitted RCR entries"));
2130aeed3e9SJustin Hibbits if (ci != rcr->ci)
2140aeed3e9SJustin Hibbits REPORT_ERROR(WARNING, E_INVALID_STATE, ("missing existing RCR completions"));
2150aeed3e9SJustin Hibbits if (rcr->ci != RCR_PTR2IDX(rcr->cursor))
2160aeed3e9SJustin Hibbits REPORT_ERROR(WARNING, E_INVALID_STATE, ("RCR destroyed unquiesced"));
2170aeed3e9SJustin Hibbits }
2180aeed3e9SJustin Hibbits
bm_rcr_start(struct bm_portal * portal)2190aeed3e9SJustin Hibbits struct bm_rcr_entry *bm_rcr_start(struct bm_portal *portal)
2200aeed3e9SJustin Hibbits {
2210aeed3e9SJustin Hibbits register struct bm_rcr *rcr = &portal->rcr;
2220aeed3e9SJustin Hibbits ASSERT_COND(!rcr->busy);
2230aeed3e9SJustin Hibbits if (!rcr->available)
2240aeed3e9SJustin Hibbits return NULL;
2250aeed3e9SJustin Hibbits #ifdef BM_CHECKING
2260aeed3e9SJustin Hibbits rcr->busy = 1;
2270aeed3e9SJustin Hibbits #endif /* BM_CHECKING */
2280aeed3e9SJustin Hibbits dcbz_64(rcr->cursor);
2290aeed3e9SJustin Hibbits return rcr->cursor;
2300aeed3e9SJustin Hibbits }
2310aeed3e9SJustin Hibbits
bm_rcr_abort(struct bm_portal * portal)2320aeed3e9SJustin Hibbits void bm_rcr_abort(struct bm_portal *portal)
2330aeed3e9SJustin Hibbits {
2340aeed3e9SJustin Hibbits register struct bm_rcr *rcr = &portal->rcr;
2350aeed3e9SJustin Hibbits ASSERT_COND(rcr->busy);
2360aeed3e9SJustin Hibbits #ifdef BM_CHECKING
2370aeed3e9SJustin Hibbits rcr->busy = 0;
2380aeed3e9SJustin Hibbits #else
2390aeed3e9SJustin Hibbits UNUSED(rcr);
2400aeed3e9SJustin Hibbits #endif /* BM_CHECKING */
2410aeed3e9SJustin Hibbits }
2420aeed3e9SJustin Hibbits
bm_rcr_pend_and_next(struct bm_portal * portal,uint8_t myverb)2430aeed3e9SJustin Hibbits struct bm_rcr_entry *bm_rcr_pend_and_next(struct bm_portal *portal, uint8_t myverb)
2440aeed3e9SJustin Hibbits {
2450aeed3e9SJustin Hibbits register struct bm_rcr *rcr = &portal->rcr;
2460aeed3e9SJustin Hibbits ASSERT_COND(rcr->busy);
2470aeed3e9SJustin Hibbits ASSERT_COND(rcr->pmode != e_BmPortalPVB);
2480aeed3e9SJustin Hibbits if (rcr->available == 1)
2490aeed3e9SJustin Hibbits return NULL;
2500aeed3e9SJustin Hibbits rcr->cursor->__dont_write_directly__verb = (uint8_t)(myverb | rcr->vbit);
2510aeed3e9SJustin Hibbits dcbf_64(rcr->cursor);
2520aeed3e9SJustin Hibbits RCR_INC(rcr);
2530aeed3e9SJustin Hibbits rcr->available--;
2540aeed3e9SJustin Hibbits dcbz_64(rcr->cursor);
2550aeed3e9SJustin Hibbits return rcr->cursor;
2560aeed3e9SJustin Hibbits }
2570aeed3e9SJustin Hibbits
bm_rcr_pci_commit(struct bm_portal * portal,uint8_t myverb)2580aeed3e9SJustin Hibbits void bm_rcr_pci_commit(struct bm_portal *portal, uint8_t myverb)
2590aeed3e9SJustin Hibbits {
2600aeed3e9SJustin Hibbits register struct bm_rcr *rcr = &portal->rcr;
2610aeed3e9SJustin Hibbits ASSERT_COND(rcr->busy);
2620aeed3e9SJustin Hibbits ASSERT_COND(rcr->pmode == e_BmPortalPCI);
2630aeed3e9SJustin Hibbits rcr->cursor->__dont_write_directly__verb = (uint8_t)(myverb | rcr->vbit);
2640aeed3e9SJustin Hibbits RCR_INC(rcr);
2650aeed3e9SJustin Hibbits rcr->available--;
266*852ba100SJustin Hibbits mb();
2670aeed3e9SJustin Hibbits bm_out(RCR_PI_CINH, RCR_PTR2IDX(rcr->cursor));
2680aeed3e9SJustin Hibbits #ifdef BM_CHECKING
2690aeed3e9SJustin Hibbits rcr->busy = 0;
2700aeed3e9SJustin Hibbits #endif /* BM_CHECKING */
2710aeed3e9SJustin Hibbits }
2720aeed3e9SJustin Hibbits
bm_rcr_pce_prefetch(struct bm_portal * portal)2730aeed3e9SJustin Hibbits void bm_rcr_pce_prefetch(struct bm_portal *portal)
2740aeed3e9SJustin Hibbits {
2750aeed3e9SJustin Hibbits ASSERT_COND(((struct bm_rcr *)&portal->rcr)->pmode == e_BmPortalPCE);
2760aeed3e9SJustin Hibbits bm_cl_invalidate(RCR_PI);
2770aeed3e9SJustin Hibbits bm_cl_touch_rw(RCR_PI);
2780aeed3e9SJustin Hibbits }
2790aeed3e9SJustin Hibbits
bm_rcr_pce_commit(struct bm_portal * portal,uint8_t myverb)2800aeed3e9SJustin Hibbits void bm_rcr_pce_commit(struct bm_portal *portal, uint8_t myverb)
2810aeed3e9SJustin Hibbits {
2820aeed3e9SJustin Hibbits register struct bm_rcr *rcr = &portal->rcr;
2830aeed3e9SJustin Hibbits ASSERT_COND(rcr->busy);
2840aeed3e9SJustin Hibbits ASSERT_COND(rcr->pmode == e_BmPortalPCE);
2850aeed3e9SJustin Hibbits rcr->cursor->__dont_write_directly__verb = (uint8_t)(myverb | rcr->vbit);
2860aeed3e9SJustin Hibbits RCR_INC(rcr);
2870aeed3e9SJustin Hibbits rcr->available--;
288*852ba100SJustin Hibbits wmb();
2890aeed3e9SJustin Hibbits bm_cl_out(RCR_PI, RCR_PTR2IDX(rcr->cursor));
2900aeed3e9SJustin Hibbits #ifdef BM_CHECKING
2910aeed3e9SJustin Hibbits rcr->busy = 0;
2920aeed3e9SJustin Hibbits #endif /* BM_CHECKING */
2930aeed3e9SJustin Hibbits }
2940aeed3e9SJustin Hibbits
bm_rcr_pvb_commit(struct bm_portal * portal,uint8_t myverb)2950aeed3e9SJustin Hibbits void bm_rcr_pvb_commit(struct bm_portal *portal, uint8_t myverb)
2960aeed3e9SJustin Hibbits {
2970aeed3e9SJustin Hibbits register struct bm_rcr *rcr = &portal->rcr;
2980aeed3e9SJustin Hibbits struct bm_rcr_entry *rcursor;
2990aeed3e9SJustin Hibbits ASSERT_COND(rcr->busy);
3000aeed3e9SJustin Hibbits ASSERT_COND(rcr->pmode == e_BmPortalPVB);
301*852ba100SJustin Hibbits rmb();
3020aeed3e9SJustin Hibbits rcursor = rcr->cursor;
3030aeed3e9SJustin Hibbits rcursor->__dont_write_directly__verb = (uint8_t)(myverb | rcr->vbit);
3040aeed3e9SJustin Hibbits dcbf_64(rcursor);
3050aeed3e9SJustin Hibbits RCR_INC(rcr);
3060aeed3e9SJustin Hibbits rcr->available--;
3070aeed3e9SJustin Hibbits #ifdef BM_CHECKING
3080aeed3e9SJustin Hibbits rcr->busy = 0;
3090aeed3e9SJustin Hibbits #endif /* BM_CHECKING */
3100aeed3e9SJustin Hibbits }
3110aeed3e9SJustin Hibbits
3120aeed3e9SJustin Hibbits
bm_rcr_cci_update(struct bm_portal * portal)3130aeed3e9SJustin Hibbits uint8_t bm_rcr_cci_update(struct bm_portal *portal)
3140aeed3e9SJustin Hibbits {
3150aeed3e9SJustin Hibbits register struct bm_rcr *rcr = &portal->rcr;
3160aeed3e9SJustin Hibbits uint8_t diff, old_ci = rcr->ci;
3170aeed3e9SJustin Hibbits ASSERT_COND(rcr->cmode == e_BmPortalRcrCCI);
3180aeed3e9SJustin Hibbits rcr->ci = (uint8_t)(bm_in(RCR_CI_CINH) & (BM_RCR_SIZE - 1));
3190aeed3e9SJustin Hibbits diff = cyc_diff(BM_RCR_SIZE, old_ci, rcr->ci);
3200aeed3e9SJustin Hibbits rcr->available += diff;
3210aeed3e9SJustin Hibbits return diff;
3220aeed3e9SJustin Hibbits }
3230aeed3e9SJustin Hibbits
3240aeed3e9SJustin Hibbits
bm_rcr_cce_prefetch(struct bm_portal * portal)3250aeed3e9SJustin Hibbits void bm_rcr_cce_prefetch(struct bm_portal *portal)
3260aeed3e9SJustin Hibbits {
3270aeed3e9SJustin Hibbits ASSERT_COND(((struct bm_rcr *)&portal->rcr)->cmode == e_BmPortalRcrCCE);
3280aeed3e9SJustin Hibbits bm_cl_touch_ro(RCR_CI);
3290aeed3e9SJustin Hibbits }
3300aeed3e9SJustin Hibbits
3310aeed3e9SJustin Hibbits
bm_rcr_cce_update(struct bm_portal * portal)3320aeed3e9SJustin Hibbits uint8_t bm_rcr_cce_update(struct bm_portal *portal)
3330aeed3e9SJustin Hibbits {
3340aeed3e9SJustin Hibbits register struct bm_rcr *rcr = &portal->rcr;
3350aeed3e9SJustin Hibbits uint8_t diff, old_ci = rcr->ci;
3360aeed3e9SJustin Hibbits ASSERT_COND(rcr->cmode == e_BmPortalRcrCCE);
3370aeed3e9SJustin Hibbits rcr->ci = (uint8_t)(bm_cl_in(RCR_CI) & (BM_RCR_SIZE - 1));
3380aeed3e9SJustin Hibbits bm_cl_invalidate(RCR_CI);
3390aeed3e9SJustin Hibbits diff = cyc_diff(BM_RCR_SIZE, old_ci, rcr->ci);
3400aeed3e9SJustin Hibbits rcr->available += diff;
3410aeed3e9SJustin Hibbits return diff;
3420aeed3e9SJustin Hibbits }
3430aeed3e9SJustin Hibbits
3440aeed3e9SJustin Hibbits
bm_rcr_get_ithresh(struct bm_portal * portal)3450aeed3e9SJustin Hibbits uint8_t bm_rcr_get_ithresh(struct bm_portal *portal)
3460aeed3e9SJustin Hibbits {
3470aeed3e9SJustin Hibbits register struct bm_rcr *rcr = &portal->rcr;
3480aeed3e9SJustin Hibbits return rcr->ithresh;
3490aeed3e9SJustin Hibbits }
3500aeed3e9SJustin Hibbits
3510aeed3e9SJustin Hibbits
bm_rcr_set_ithresh(struct bm_portal * portal,uint8_t ithresh)3520aeed3e9SJustin Hibbits void bm_rcr_set_ithresh(struct bm_portal *portal, uint8_t ithresh)
3530aeed3e9SJustin Hibbits {
3540aeed3e9SJustin Hibbits register struct bm_rcr *rcr = &portal->rcr;
3550aeed3e9SJustin Hibbits rcr->ithresh = ithresh;
3560aeed3e9SJustin Hibbits bm_out(RCR_ITR, ithresh);
3570aeed3e9SJustin Hibbits }
3580aeed3e9SJustin Hibbits
3590aeed3e9SJustin Hibbits
bm_rcr_get_avail(struct bm_portal * portal)3600aeed3e9SJustin Hibbits uint8_t bm_rcr_get_avail(struct bm_portal *portal)
3610aeed3e9SJustin Hibbits {
3620aeed3e9SJustin Hibbits register struct bm_rcr *rcr = &portal->rcr;
3630aeed3e9SJustin Hibbits return rcr->available;
3640aeed3e9SJustin Hibbits }
3650aeed3e9SJustin Hibbits
3660aeed3e9SJustin Hibbits
bm_rcr_get_fill(struct bm_portal * portal)3670aeed3e9SJustin Hibbits uint8_t bm_rcr_get_fill(struct bm_portal *portal)
3680aeed3e9SJustin Hibbits {
3690aeed3e9SJustin Hibbits register struct bm_rcr *rcr = &portal->rcr;
3700aeed3e9SJustin Hibbits return (uint8_t)(BM_RCR_SIZE - 1 - rcr->available);
3710aeed3e9SJustin Hibbits }
3720aeed3e9SJustin Hibbits
3730aeed3e9SJustin Hibbits
3740aeed3e9SJustin Hibbits /* ------------------------------ */
3750aeed3e9SJustin Hibbits /* --- Management command API --- */
3760aeed3e9SJustin Hibbits
3770aeed3e9SJustin Hibbits /* It's safer to code in terms of the 'mc' object than the 'portal' object,
3780aeed3e9SJustin Hibbits * because the latter runs the risk of copy-n-paste errors from other code where
3790aeed3e9SJustin Hibbits * we could manipulate some other structure within 'portal'. */
3800aeed3e9SJustin Hibbits /* #define MC_API_START() register struct bm_mc *mc = &portal->mc */
3810aeed3e9SJustin Hibbits
3820aeed3e9SJustin Hibbits
bm_mc_init(struct bm_portal * portal)3830aeed3e9SJustin Hibbits t_Error bm_mc_init(struct bm_portal *portal)
3840aeed3e9SJustin Hibbits {
3850aeed3e9SJustin Hibbits register struct bm_mc *mc = &portal->mc;
3860aeed3e9SJustin Hibbits mc->cr = ptr_ADD(portal->addr.addr_ce, CL_CR);
3870aeed3e9SJustin Hibbits mc->rr = ptr_ADD(portal->addr.addr_ce, CL_RR0);
3880aeed3e9SJustin Hibbits mc->rridx = (uint8_t)((mc->cr->__dont_write_directly__verb & BM_MCC_VERB_VBIT) ?
3890aeed3e9SJustin Hibbits 0 : 1);
3900aeed3e9SJustin Hibbits mc->vbit = (uint8_t)(mc->rridx ? BM_MCC_VERB_VBIT : 0);
3910aeed3e9SJustin Hibbits #ifdef BM_CHECKING
3920aeed3e9SJustin Hibbits mc->state = mc_idle;
3930aeed3e9SJustin Hibbits #endif /* BM_CHECKING */
3940aeed3e9SJustin Hibbits return 0;
3950aeed3e9SJustin Hibbits }
3960aeed3e9SJustin Hibbits
3970aeed3e9SJustin Hibbits
bm_mc_finish(struct bm_portal * portal)3980aeed3e9SJustin Hibbits void bm_mc_finish(struct bm_portal *portal)
3990aeed3e9SJustin Hibbits {
4000aeed3e9SJustin Hibbits register struct bm_mc *mc = &portal->mc;
4010aeed3e9SJustin Hibbits ASSERT_COND(mc->state == mc_idle);
4020aeed3e9SJustin Hibbits #ifdef BM_CHECKING
4030aeed3e9SJustin Hibbits if (mc->state != mc_idle)
4040aeed3e9SJustin Hibbits REPORT_ERROR(WARNING, E_INVALID_STATE, ("Losing incomplete MC command"));
4050aeed3e9SJustin Hibbits #else
4060aeed3e9SJustin Hibbits UNUSED(mc);
4070aeed3e9SJustin Hibbits #endif /* BM_CHECKING */
4080aeed3e9SJustin Hibbits }
4090aeed3e9SJustin Hibbits
4100aeed3e9SJustin Hibbits
bm_mc_start(struct bm_portal * portal)4110aeed3e9SJustin Hibbits struct bm_mc_command *bm_mc_start(struct bm_portal *portal)
4120aeed3e9SJustin Hibbits {
4130aeed3e9SJustin Hibbits register struct bm_mc *mc = &portal->mc;
4140aeed3e9SJustin Hibbits ASSERT_COND(mc->state == mc_idle);
4150aeed3e9SJustin Hibbits #ifdef BM_CHECKING
4160aeed3e9SJustin Hibbits mc->state = mc_user;
4170aeed3e9SJustin Hibbits #endif /* BM_CHECKING */
4180aeed3e9SJustin Hibbits dcbz_64(mc->cr);
4190aeed3e9SJustin Hibbits return mc->cr;
4200aeed3e9SJustin Hibbits }
4210aeed3e9SJustin Hibbits
4220aeed3e9SJustin Hibbits
bm_mc_abort(struct bm_portal * portal)4230aeed3e9SJustin Hibbits void bm_mc_abort(struct bm_portal *portal)
4240aeed3e9SJustin Hibbits {
4250aeed3e9SJustin Hibbits register struct bm_mc *mc = &portal->mc;
4260aeed3e9SJustin Hibbits ASSERT_COND(mc->state == mc_user);
4270aeed3e9SJustin Hibbits #ifdef BM_CHECKING
4280aeed3e9SJustin Hibbits mc->state = mc_idle;
4290aeed3e9SJustin Hibbits #else
4300aeed3e9SJustin Hibbits UNUSED(mc);
4310aeed3e9SJustin Hibbits #endif /* BM_CHECKING */
4320aeed3e9SJustin Hibbits }
4330aeed3e9SJustin Hibbits
4340aeed3e9SJustin Hibbits
bm_mc_commit(struct bm_portal * portal,uint8_t myverb)4350aeed3e9SJustin Hibbits void bm_mc_commit(struct bm_portal *portal, uint8_t myverb)
4360aeed3e9SJustin Hibbits {
4370aeed3e9SJustin Hibbits register struct bm_mc *mc = &portal->mc;
4380aeed3e9SJustin Hibbits ASSERT_COND(mc->state == mc_user);
439*852ba100SJustin Hibbits rmb();
4400aeed3e9SJustin Hibbits mc->cr->__dont_write_directly__verb = (uint8_t)(myverb | mc->vbit);
4410aeed3e9SJustin Hibbits dcbf_64(mc->cr);
4420aeed3e9SJustin Hibbits dcbit_ro(mc->rr + mc->rridx);
4430aeed3e9SJustin Hibbits #ifdef BM_CHECKING
4440aeed3e9SJustin Hibbits mc->state = mc_hw;
4450aeed3e9SJustin Hibbits #endif /* BM_CHECKING */
4460aeed3e9SJustin Hibbits }
4470aeed3e9SJustin Hibbits
4480aeed3e9SJustin Hibbits
bm_mc_result(struct bm_portal * portal)4490aeed3e9SJustin Hibbits struct bm_mc_result *bm_mc_result(struct bm_portal *portal)
4500aeed3e9SJustin Hibbits {
4510aeed3e9SJustin Hibbits register struct bm_mc *mc = &portal->mc;
4520aeed3e9SJustin Hibbits struct bm_mc_result *rr = mc->rr + mc->rridx;
4530aeed3e9SJustin Hibbits ASSERT_COND(mc->state == mc_hw);
4540aeed3e9SJustin Hibbits /* The inactive response register's verb byte always returns zero until
4550aeed3e9SJustin Hibbits * its command is submitted and completed. This includes the valid-bit,
4560aeed3e9SJustin Hibbits * in case you were wondering... */
4570aeed3e9SJustin Hibbits if (!rr->verb) {
4580aeed3e9SJustin Hibbits dcbit_ro(rr);
4590aeed3e9SJustin Hibbits return NULL;
4600aeed3e9SJustin Hibbits }
4610aeed3e9SJustin Hibbits mc->rridx ^= 1;
4620aeed3e9SJustin Hibbits mc->vbit ^= BM_MCC_VERB_VBIT;
4630aeed3e9SJustin Hibbits #ifdef BM_CHECKING
4640aeed3e9SJustin Hibbits mc->state = mc_idle;
4650aeed3e9SJustin Hibbits #endif /* BM_CHECKING */
4660aeed3e9SJustin Hibbits return rr;
4670aeed3e9SJustin Hibbits }
4680aeed3e9SJustin Hibbits
4690aeed3e9SJustin Hibbits /* ------------------------------------- */
4700aeed3e9SJustin Hibbits /* --- Portal interrupt register API --- */
4710aeed3e9SJustin Hibbits
4720aeed3e9SJustin Hibbits #define SCN_REG(bpid) REG_SCN((bpid) / 32)
4730aeed3e9SJustin Hibbits #define SCN_BIT(bpid) (0x80000000 >> (bpid & 31))
bm_isr_bscn_mask(struct bm_portal * portal,uint8_t bpid,int enable)4740aeed3e9SJustin Hibbits void bm_isr_bscn_mask(struct bm_portal *portal, uint8_t bpid, int enable)
4750aeed3e9SJustin Hibbits {
4760aeed3e9SJustin Hibbits uint32_t val;
4770aeed3e9SJustin Hibbits ASSERT_COND(bpid < BM_MAX_NUM_OF_POOLS);
4780aeed3e9SJustin Hibbits /* REG_SCN for bpid=0..31, REG_SCN+4 for bpid=32..63 */
4790aeed3e9SJustin Hibbits val = __bm_in(&portal->addr, SCN_REG(bpid));
4800aeed3e9SJustin Hibbits if (enable)
4810aeed3e9SJustin Hibbits val |= SCN_BIT(bpid);
4820aeed3e9SJustin Hibbits else
4830aeed3e9SJustin Hibbits val &= ~SCN_BIT(bpid);
4840aeed3e9SJustin Hibbits __bm_out(&portal->addr, SCN_REG(bpid), val);
4850aeed3e9SJustin Hibbits }
4860aeed3e9SJustin Hibbits
4870aeed3e9SJustin Hibbits
__bm_isr_read(struct bm_portal * portal,enum bm_isr_reg n)4880aeed3e9SJustin Hibbits uint32_t __bm_isr_read(struct bm_portal *portal, enum bm_isr_reg n)
4890aeed3e9SJustin Hibbits {
490f77405e3SJustin Hibbits return __bm_in(&portal->addr, REG_ISR + (n << 2));
4910aeed3e9SJustin Hibbits }
4920aeed3e9SJustin Hibbits
4930aeed3e9SJustin Hibbits
__bm_isr_write(struct bm_portal * portal,enum bm_isr_reg n,uint32_t val)4940aeed3e9SJustin Hibbits void __bm_isr_write(struct bm_portal *portal, enum bm_isr_reg n, uint32_t val)
4950aeed3e9SJustin Hibbits {
496f77405e3SJustin Hibbits __bm_out(&portal->addr, REG_ISR + (n << 2), val);
4970aeed3e9SJustin Hibbits }
4980aeed3e9SJustin Hibbits
499