f6a4f23d5be84e6f59b1728f5075b8630305c418
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 }
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;
134 }
136 void Udma_ringHandleClearRegsLcdma(Udma_RingHandle ringHandle)
137 {
138 ringHandle->pLcdmaCfgRegs = (volatile CSL_lcdma_ringacc_ring_cfgRegs_RING *) NULL_PTR;
139 ringHandle->pLcdmaRtRegs = (volatile CSL_lcdma_ringacc_ringrtRegs_ring *) NULL_PTR;
140 }
142 int32_t Udma_ringQueueRawLcdma(Udma_DrvHandle drvHandle, Udma_RingHandle ringHandle, uint64_t phyDescMem)
143 {
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);
170 }
172 int32_t Udma_ringDequeueRawLcdma(Udma_DrvHandle drvHandle, Udma_RingHandle ringHandle, uint64_t *phyDescMem)
173 {
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);
208 }
210 int32_t Udma_ringFlushRawLcdma(Udma_DrvHandle drvHandle, Udma_RingHandle ringHandle, uint64_t *phyDescMem)
211 {
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);
224 }
226 void Udma_ringPrimeLcdma(Udma_RingHandle ringHandle, uint64_t phyDescMem)
227 {
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;
247 }
249 void Udma_ringPrimeReadLcdma(Udma_RingHandle ringHandle, uint64_t *phyDescMem)
250 {
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 }
272 }
274 void Udma_ringSetDoorBellLcdma(Udma_RingHandle ringHandle, int32_t count)
275 {
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;
320 }
322 void *Udma_ringGetMemPtrLcdma(Udma_RingHandle ringHandle)
323 {
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);
332 }
334 uint32_t Udma_ringGetModeLcdma(Udma_RingHandle ringHandle)
335 {
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);
344 }
346 uint32_t Udma_ringGetElementCntLcdma(Udma_RingHandle ringHandle)
347 {
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);
356 }
358 uint32_t Udma_ringGetForwardRingOccLcdma(Udma_RingHandle ringHandle)
359 {
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);
370 }
372 uint32_t Udma_ringGetReverseRingOccLcdma(Udma_RingHandle ringHandle)
373 {
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);
384 }
386 uint32_t Udma_ringGetWrIdxLcdma(Udma_RingHandle ringHandle)
387 {
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);
396 }
398 uint32_t Udma_ringGetRdIdxLcdma(Udma_RingHandle ringHandle)
399 {
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);
408 }