]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - processor-sdk/pdk.git/blob - packages/ti/drv/udma/src/udma_ring_lcdma.c
f6a4f23d5be84e6f59b1728f5075b8630305c418
[processor-sdk/pdk.git] / packages / ti / drv / udma / src / udma_ring_lcdma.c
1 /*
2  *  Copyright (c) Texas Instruments Incorporated 2018
3  *
4  *  Redistribution and use in source and binary forms, with or without
5  *  modification, are permitted provided that the following conditions
6  *  are met:
7  *
8  *    Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  *
11  *    Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the
14  *    distribution.
15  *
16  *    Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
33 /**
34  *  \file udma_ring.c
35  *
36  *  \brief File containing the UDMA driver ring related APIs.
37  *
38  */
40 /* ========================================================================== */
41 /*                             Include Files                                  */
42 /* ========================================================================== */
44 #include <ti/drv/udma/src/udma_priv.h>
46 /* ========================================================================== */
47 /*                           Macros & Typedefs                                */
48 /* ========================================================================== */
50 /** \brief Max number of door bell ring that can be performed at one go */
51 #define UDMA_RING_MAX_DB_RING_CNT       (CSL_LCDMA_RINGACC_MAX_DB_RING_CNT)
53 /* ========================================================================== */
54 /*                         Structure Declarations                             */
55 /* ========================================================================== */
57 /* None */
59 /* ========================================================================== */
60 /*                          Function Declarations                             */
61 /* ========================================================================== */
63 /* None */
65 /* ========================================================================== */
66 /*                            Global Variables                                */
67 /* ========================================================================== */
69 /* None */
71 /* ========================================================================== */
72 /*                          Function Definitions                              */
73 /* ========================================================================== */
75 void Udma_ringSetCfgLcdma(Udma_DrvHandle drvHandle,
76                           Udma_RingHandle ringHandle,
77                           const Udma_RingPrms *ringPrms)
78 {
79     uint32_t            addrHi, addrLo /*, elemSize*/;
80     CSL_LcdmaRingaccRingCfg *lcdmaRingCfg;
82     /* Configure ring object */
83     Udma_assert(drvHandle, drvHandle->lcdmaRaRegs.pRingCfgRegs != NULL_PTR);
84     Udma_assert(drvHandle, drvHandle->lcdmaRaRegs.pRingRtRegs != NULL_PTR);
85     Udma_assert(drvHandle, ringHandle->ringNum < 303U);//from AM64x DMSS Spec, need to be updated once CSL changes.
86     ringHandle->pLcdmaCfgRegs =
87         &drvHandle->lcdmaRaRegs.pRingCfgRegs->RING[ringHandle->ringNum];
88     ringHandle->pLcdmaRtRegs  =
89         &drvHandle->lcdmaRaRegs.pRingRtRegs->RING[ringHandle->ringNum];
91     lcdmaRingCfg = &ringHandle->lcdmaCfg;
92     if(NULL_PTR != ringPrms)
93     {
94         lcdmaRingCfg->virtBase       = (void *) ringPrms->ringMem;
95         lcdmaRingCfg->physBase       =
96             Udma_virtToPhyFxn(ringPrms->ringMem, drvHandle, (Udma_ChHandle) NULL_PTR);
97         lcdmaRingCfg->mode           = ringPrms->mode;
98         lcdmaRingCfg->elCnt          = ringPrms->elemCnt;
99         /* CSL expects ring size in bytes */
100         lcdmaRingCfg->elSz           = ((uint32_t) 1U << (ringPrms->elemSize + 2U));
101     }
102     else
103     {
104         /* Init CSL ring object */
105         lcdmaRingCfg = &ringHandle->lcdmaCfg;
106         addrHi = CSL_REG32_FEXT(&ringHandle->pLcdmaCfgRegs->BA_HI, LCDMA_RINGACC_RING_CFG_RING_BA_HI_ADDR_HI);
107         addrLo = CSL_REG32_FEXT(&ringHandle->pLcdmaCfgRegs->BA_LO, LCDMA_RINGACC_RING_CFG_RING_BA_LO_ADDR_LO);
108         lcdmaRingCfg->physBase       = (uint64_t)((((uint64_t) addrHi) << 32UL) |
109                                             ((uint64_t) addrLo));
110         lcdmaRingCfg->virtBase       = Udma_phyToVirtFxn(lcdmaRingCfg->physBase, drvHandle, (Udma_ChHandle) NULL_PTR);
111         lcdmaRingCfg->mode           = CSL_REG32_FEXT(&ringHandle->pLcdmaCfgRegs->SIZE, LCDMA_RINGACC_RING_CFG_RING_SIZE_QMODE);
112         lcdmaRingCfg->elCnt          = CSL_REG32_FEXT(&ringHandle->pLcdmaCfgRegs->SIZE, LCDMA_RINGACC_RING_CFG_RING_SIZE_ELCNT);
113         /* CSL expects ring size in bytes; ring_elsize for AM64x is hardcoded as 1=8bytes*/
114         lcdmaRingCfg->elSz           = (uint32_t) 8U;
115     }
116     
117     lcdmaRingCfg->credChkSecure  = 0U;
118     lcdmaRingCfg->credSecure     = 0U;
119     lcdmaRingCfg->credPriv       = 0U;
120     lcdmaRingCfg->credPrivId     = CSL_LCDMA_RINGACC_CRED_PASSTHRU;
121     lcdmaRingCfg->credVirtId     = CSL_LCDMA_RINGACC_CRED_PASSTHRU;
122     CSL_lcdma_ringaccInitRingObj(ringHandle->ringNum, lcdmaRingCfg);
124 #if (UDMA_SOC_CFG_PROXY_PRESENT == 1)
125     ringHandle->proxyAddr =
126         CSL_proxyGetDataAddr(
127             &drvHandle->proxyCfg,
128             drvHandle->proxyTargetNumRing,
129             drvHandle->initPrms.rmInitPrms.proxyThreadNum,
130             lcdmaRingCfg->elSz);
131 #endif
133     return;
136 void Udma_ringHandleClearRegsLcdma(Udma_RingHandle ringHandle)
138     ringHandle->pLcdmaCfgRegs   = (volatile CSL_lcdma_ringacc_ring_cfgRegs_RING *) NULL_PTR;
139     ringHandle->pLcdmaRtRegs    = (volatile CSL_lcdma_ringacc_ringrtRegs_ring *) NULL_PTR;
142 int32_t Udma_ringQueueRawLcdma(Udma_DrvHandle  drvHandle, Udma_RingHandle ringHandle, uint64_t phyDescMem)
144     int32_t         retVal = UDMA_SOK;
146     if(TISCI_MSG_VALUE_RM_RING_MODE_RING == ringHandle->lcdmaCfg.mode)
147     {
148         /* Use direct memory access for RING mode */
149         retVal = CSL_lcdma_ringaccPush64(
150             &ringHandle->drvHandle->lcdmaRaRegs,
151             &ringHandle->lcdmaCfg,
152             (uint64_t) phyDescMem,
153             &Udma_lcdmaRingaccMemOps);
154     }
155     else
156     {
157 #if (UDMA_SOC_CFG_PROXY_PRESENT == 1)
158         /* Use proxy for other modes, if available */
159         retVal = Udma_ringProxyQueueRaw(ringHandle, drvHandle, phyDescMem);
160 #else
161         retVal = CSL_lcdma_ringaccPush64x32(
162             &ringHandle->drvHandle->lcdmaRaRegs,
163             &ringHandle->lcdmaCfg,
164             (uint64_t) phyDescMem,
165             &Udma_lcdmaRingaccMemOps);
166 #endif
167     }
169     return (retVal);
172 int32_t Udma_ringDequeueRawLcdma(Udma_DrvHandle  drvHandle, Udma_RingHandle ringHandle, uint64_t *phyDescMem)
174     int32_t         retVal = UDMA_SOK, cslRetVal;
176     if(TISCI_MSG_VALUE_RM_RING_MODE_RING == ringHandle->lcdmaCfg.mode)
177     {
178         /* Use direct memory access for RING mode */
179         cslRetVal = CSL_lcdma_ringaccPop64(
180                 &ringHandle->drvHandle->lcdmaRaRegs,
181                 &ringHandle->lcdmaCfg,
182                 phyDescMem,
183                 &Udma_lcdmaRingaccMemOps);
184         if(0 != cslRetVal)
185         {
186             retVal = UDMA_ETIMEOUT;
187         }
188     }
189     else
190     {
191 #if (UDMA_SOC_CFG_PROXY_PRESENT == 1)
192         /* Use proxy for other modes, if available */
193         retVal = Udma_ringProxyDequeueRaw(ringHandle, drvHandle, phyDescMem);
194 #else
195         cslRetVal = CSL_lcdma_ringaccPop64x32(
196                 &ringHandle->drvHandle->lcdmaRaRegs,
197                 &ringHandle->lcdmaCfg,
198                 phyDescMem,
199                 &Udma_lcdmaRingaccMemOps);
200         if(0 != cslRetVal)
201         {
202             retVal = UDMA_ETIMEOUT;
203         }
204 #endif
205     }
207     return (retVal);
210 int32_t Udma_ringFlushRawLcdma(Udma_DrvHandle drvHandle, Udma_RingHandle ringHandle, uint64_t *phyDescMem)
212     int32_t         retVal = UDMA_SOK, cslRetVal;
214     cslRetVal = CSL_lcdma_ringaccPop64x32(
215             &ringHandle->drvHandle->lcdmaRaRegs,
216             &ringHandle->lcdmaCfg,
217             phyDescMem,
218             &Udma_lcdmaRingaccMemOps);
219     if(0 != cslRetVal)
220     {
221         retVal = UDMA_ETIMEOUT;
222     }
223     return (retVal);
226 void Udma_ringPrimeLcdma(Udma_RingHandle ringHandle, uint64_t phyDescMem)
228     volatile uint64_t        *ringPtr;
229     CSL_LcdmaRingaccRingCfg  *pLcdmaRing;
230     uintptr_t                 tempPtr;
232     pLcdmaRing = &ringHandle->lcdmaCfg;
233     tempPtr = (uintptr_t)(pLcdmaRing->wrIdx * pLcdmaRing->elSz) +
234               (uintptr_t)pLcdmaRing->virtBase;
235     ringPtr = (volatile uint64_t *)(tempPtr);
236     *ringPtr = phyDescMem;
238     /* Book keeping */
239     pLcdmaRing->wrIdx++;
240     if(pLcdmaRing->wrIdx >= pLcdmaRing->elCnt)
241     {
242         pLcdmaRing->wrIdx = 0U;
243     }
244     pLcdmaRing->wrOcc++;
246     return;
249 void Udma_ringPrimeReadLcdma(Udma_RingHandle ringHandle, uint64_t *phyDescMem)
251     volatile uint64_t        *ringPtr;
252     CSL_LcdmaRingaccRingCfg  *pLcdmaRing;
253     uintptr_t                 tempPtr;
255     pLcdmaRing = &ringHandle->lcdmaCfg;
256     tempPtr = (uintptr_t)(pLcdmaRing->rdIdx * pLcdmaRing->elSz) +
257               (uintptr_t)pLcdmaRing->virtBase;
258     ringPtr = (volatile uint64_t *)(tempPtr);
259     *phyDescMem = *ringPtr;
261     if (*phyDescMem != 0U)
262     {
263         /* Book keeping */
264         pLcdmaRing->rdIdx++;
265         if(pLcdmaRing->rdIdx >= pLcdmaRing->elCnt)
266         {
267             pLcdmaRing->rdIdx = 0U;
268         }
269         pLcdmaRing->rdOcc--;
270         pLcdmaRing->wrOcc--;
271     }
274 void Udma_ringSetDoorBellLcdma(Udma_RingHandle ringHandle, int32_t count)
276     uint32_t    regVal;
277     int32_t     thisDbRingCnt;
279     /* count will be positive when ring elements are queued into the ring */
280     if (count >= 0)
281     {
282         while(count != 0)
283         {
284             if(count < UDMA_RING_MAX_DB_RING_CNT)
285             {
286                 thisDbRingCnt = count;
287                 regVal = CSL_FMK(LCDMA_RINGACC_RINGRT_RING_FDB_CNT, (uint32_t)thisDbRingCnt);
288             }
289             else
290             {
291                 thisDbRingCnt = UDMA_RING_MAX_DB_RING_CNT;
292                 regVal = CSL_FMK(LCDMA_RINGACC_RINGRT_RING_FDB_CNT, (uint32_t)thisDbRingCnt);
293             }
294             CSL_REG32_WR(&ringHandle->pLcdmaRtRegs->FDB, regVal);
295             count -= thisDbRingCnt;
296         }
297     }
299     /* count will be negative when ring elements are dequeued from the ring */
300     else
301     {
302         while(count != 0)
303         {
304             if(count > (-1 * (int32_t)UDMA_RING_MAX_DB_RING_CNT))
305             {
306                 thisDbRingCnt = count;
307                 regVal = CSL_FMK(LCDMA_RINGACC_RINGRT_RING_RDB_CNT, (uint32_t)thisDbRingCnt);
308             }
309             else
310             {
311                 thisDbRingCnt = (-1 * (int32_t)UDMA_RING_MAX_DB_RING_CNT);
312                 regVal = CSL_FMK(LCDMA_RINGACC_RINGRT_RING_RDB_CNT, (uint32_t)thisDbRingCnt);
313             }
314             CSL_REG32_WR(&ringHandle->pLcdmaRtRegs->RDB, regVal);
315             count -= thisDbRingCnt;
316         }
317     }
319     return;
322 void *Udma_ringGetMemPtrLcdma(Udma_RingHandle ringHandle)
324     void   *ringMem = NULL_PTR;
326     if((NULL_PTR != ringHandle) && (UDMA_INIT_DONE == ringHandle->ringInitDone))
327     {
328         ringMem = ringHandle->lcdmaCfg.virtBase;
329     }
331     return (ringMem);
334 uint32_t Udma_ringGetModeLcdma(Udma_RingHandle ringHandle)
336     uint32_t ringMode = CSL_LCDMA_RINGACC_RING_MODE_INVALID;
338     if((NULL_PTR != ringHandle) && (UDMA_INIT_DONE == ringHandle->ringInitDone))
339     {
340         ringMode = ringHandle->lcdmaCfg.mode;
341     }
343     return (ringMode);
346 uint32_t Udma_ringGetElementCntLcdma(Udma_RingHandle ringHandle)
348     uint32_t size = 0U;
350     if((NULL_PTR != ringHandle) && (UDMA_INIT_DONE == ringHandle->ringInitDone))
351     {
352         size = ringHandle->lcdmaCfg.elCnt;
353     }
355     return (size);
358 uint32_t Udma_ringGetForwardRingOccLcdma(Udma_RingHandle ringHandle)
360     uint32_t occ = 0U;
362     if((NULL_PTR != ringHandle) && (UDMA_INIT_DONE == ringHandle->ringInitDone))
363     {
364         occ = CSL_lcdma_ringaccGetForwardRingOcc(&ringHandle->drvHandle->lcdmaRaRegs,
365                                                  ringHandle->ringNum,
366                                                  ringHandle->lcdmaCfg.mode);
367     }
369     return (occ);
372 uint32_t Udma_ringGetReverseRingOccLcdma(Udma_RingHandle ringHandle)
374     uint32_t occ = 0U;
376     if((NULL_PTR != ringHandle) && (UDMA_INIT_DONE == ringHandle->ringInitDone))
377     {
378         occ = CSL_lcdma_ringaccGetReverseRingOcc(&ringHandle->drvHandle->lcdmaRaRegs,
379                                                  ringHandle->ringNum,
380                                                  ringHandle->lcdmaCfg.mode);
381     }
383     return (occ);
386 uint32_t Udma_ringGetWrIdxLcdma(Udma_RingHandle ringHandle)
388     uint32_t idx = 0U;
390     if((NULL_PTR != ringHandle) && (UDMA_INIT_DONE == ringHandle->ringInitDone))
391     {
392         idx = ringHandle->lcdmaCfg.wrIdx;
393     }
395     return (idx);
398 uint32_t Udma_ringGetRdIdxLcdma(Udma_RingHandle ringHandle)
400     uint32_t idx = 0U;
402     if((NULL_PTR != ringHandle) && (UDMA_INIT_DONE == ringHandle->ringInitDone))
403     {
404         idx = ringHandle->lcdmaCfg.rdIdx;
405     }
407     return (idx);