[ipc/ipcdev.git] / qnx / src / ipc3x_dev / ti / syslink / family / hlos / knl / ti81xx / ti81xxdsp / Dm8168DspHalMmu.c
1 /*
2 * @file Dm8168DspHalMmu.c
3 *
4 * @brief Hardware abstraction for Memory Management Unit module.
5 *
6 * This module is responsible for handling slave MMU-related
7 * hardware- specific operations.
8 * The implementation is specific to DM8168DSP.
9 *
10 *
11 * ============================================================================
12 *
13 * Copyright (c) 2008-2012, Texas Instruments Incorporated
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 *
19 * * Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 *
22 * * Redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution.
25 *
26 * * Neither the name of Texas Instruments Incorporated nor the names of
27 * its contributors may be used to endorse or promote products derived
28 * from this software without specific prior written permission.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
31 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
32 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
33 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
34 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
35 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
36 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
37 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
38 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
39 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
40 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 * Contact information for paper mail:
42 * Texas Instruments
43 * Post Office Box 655303
44 * Dallas, Texas 75265
45 * Contact information:
46 * http://www-k.ext.ti.com/sc/technical-support/product-information-centers.htm?
47 * DCMP=TIHomeTracking&HQS=Other+OT+home_d_contact
48 * ============================================================================
49 *
50 */
54 /* Standard headers */
55 #include <ti/syslink/Std.h>
57 /* OSAL and utils headers */
58 #include <ti/syslink/utils/List.h>
59 #include <ti/syslink/utils/Trace.h>
60 #include <ti/syslink/utils/OsalPrint.h>
61 #include <ti/syslink/utils/Memory.h>
62 #include <Bitops.h>
64 /* Module level headers */
65 #include <_ProcDefs.h>
66 #include <Processor.h>
68 /* Hardware Abstraction Layer headers */
69 #include <Dm8168DspHal.h>
70 #include <Dm8168DspHalMmu.h>
71 #include <Dm8168DspPhyShmem.h>
74 #if defined (__cplusplus)
75 extern "C" {
76 #endif
79 /* =============================================================================
80 * Macros and types
81 * =============================================================================
82 */
83 /*!
84 * @brief Defines default mixedSize i.e same types of pages in one segment
85 */
86 #define MMU_RAM_DEFAULT 0
87 /*!
88 * @brief returns page number based on physical address
89 */
90 #define ti_syslink_phys_to_page(phys) pfn_to_page((phys) >> PAGE_SHIFT)
92 /*!
93 * @brief helper macros
94 */
95 #define SLAVEVIRTADDR(x) ((x)->addr [ProcMgr_AddrType_SlaveVirt])
96 #define SLAVEPHYSADDR(x) ((x)->addr [ProcMgr_AddrType_SlavePhys])
97 #define MASTERPHYSADDR(x) ((x)->addr [ProcMgr_AddrType_MasterPhys])
99 #define MMUPAGE_ALIGN(size, psz) (((size) + psz - 1) & ~(psz -1))
101 /* =============================================================================
102 * Forward declarations of internal functions
103 * =============================================================================
104 */
105 #if defined(SYSLINK_BUILDOS_LINUX)
106 /* Enables the MMU for GEM Module. */
107 Int _DM8168DSP_halMmuEnable (DM8168DSP_HalObject * halObject,
108 UInt32 numMemEntries,
109 ProcMgr_AddrInfo * memTable);
111 /* Disables the MMU for GEM Module. */
112 Int _DM8168DSP_halMmuDisable (DM8168DSP_HalObject * halObject);
114 /* Add entry in TWL. */
115 Int
116 _DM8168DSP_halMmuAddEntry (DM8168DSP_HalObject * halObject,
117 DM8168DSP_HalMmuEntryInfo * entry);
118 /* Add static entries in TWL. */
119 Int
120 _DM8168DSP_halMmuAddStaticEntries (DM8168DSP_HalObject * halObject,
121 UInt32 numMemEntries,
122 ProcMgr_AddrInfo * memTable);
124 /* Delete entry from TLB. */
125 Int
126 _DM8168DSP_halMmuDeleteEntry (DM8168DSP_HalObject * halObject,
127 DM8168DSP_HalMmuEntryInfo * entry);
128 /* Set entry in to TLB. */
129 Int
130 _DM8168DSP_halMmuPteSet (DM8168DSP_HalObject * halObject,
131 DM8168DSP_HalMmuEntryInfo * setPteInfo);
132 /* Print page dump */
133 Int
134 _DM8168DSP_badPageDump(UInt32 phyAddr, struct page *pg);
136 /* IOMMU Exported function */
137 extern
138 void
139 iopgtable_lookup_entry (struct iommu *obj, u32 da, u32 **ppgd, u32 **ppte);
140 #endif /* #if defined(SYSLINK_BUILDOS_LINUX) */
142 /* =============================================================================
143 * APIs called by DM8168DSPPROC module
144 * =============================================================================
145 */
146 /*!
147 * @brief Function to control MMU operations for this slave device.
148 *
149 * @param halObj Pointer to the HAL object
150 * @param cmd MMU control command
151 * @param arg Arguments specific to the MMU control command
152 *
153 * @sa
154 */
155 Int
156 DM8168DSP_halMmuCtrl (Ptr halObj, Processor_MmuCtrlCmd cmd, Ptr args)
157 {
158 Int status = PROCESSOR_SUCCESS;
159 #if defined(SYSLINK_BUILDOS_LINUX)
160 DM8168DSP_HalObject * halObject = NULL;
161 #endif /* #if defined(SYSLINK_BUILDOS_LINUX) */
162 GT_3trace (curTrace, GT_ENTER, "DM8168DSP_halMmuCtrl", halObj, cmd, args);
163 #if defined(SYSLINK_BUILDOS_LINUX)
164 GT_assert (curTrace, (halObj != NULL));
166 halObject = (DM8168DSP_HalObject *) halObj ;
168 switch (cmd) {
169 case Processor_MmuCtrlCmd_Enable:
170 {
171 DM8168DSP_HalMmuCtrlArgs_Enable * enableArgs;
172 enableArgs = (DM8168DSP_HalMmuCtrlArgs_Enable *) args;
173 halObject = (DM8168DSP_HalObject *) halObj;
174 status = _DM8168DSP_halMmuEnable (halObject,
175 enableArgs->numMemEntries,
176 enableArgs->memEntries);
178 #if !defined(SYSLINK_BUILD_OPTIMIZE)
179 if (status < 0) {
180 /*! @retval PROCESSOR_E_FAIL Failed to configure DSP MMU. */
181 status = PROCESSOR_E_FAIL;
182 GT_setFailureReason (curTrace,
183 GT_4CLASS,
184 "DM8168DSP_halMmuCtrl",
185 status,
186 "Failed to configure DSP MMU"
187 "at _DM8168DSP_halMmuEnable");
188 }
189 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
190 }
191 break;
193 case Processor_MmuCtrlCmd_Disable:
194 {
195 /* args are not used. */
196 halObject = (DM8168DSP_HalObject *) halObj;
197 status = _DM8168DSP_halMmuDisable (halObject);
198 #if !defined(SYSLINK_BUILD_OPTIMIZE)
199 if (status < 0) {
200 /*! @retval PROCESSOR_E_FAIL Failed to disable DSP MMU. */
201 status = PROCESSOR_E_FAIL;
202 GT_setFailureReason (curTrace,
203 GT_4CLASS,
204 "DM8168DSP_halMmuCtrl",
205 status,
206 "Failed to disable DSP MMU");
207 }
208 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
209 }
210 break ;
212 case Processor_MmuCtrlCmd_AddEntry:
213 {
214 DM8168DSP_HalMmuCtrlArgs_AddEntry * addEntry;
215 addEntry = (DM8168DSP_HalMmuCtrlArgs_AddEntry *) args;
217 halObject = (DM8168DSP_HalObject *) halObj;
218 /* Add the entry in TLB for new request */
219 status = _DM8168DSP_halMmuAddEntry (halObject,addEntry) ;
220 #if !defined(SYSLINK_BUILD_OPTIMIZE)
221 if (status < 0) {
222 /*! @retval PROCESSOR_E_FAIL Failed to dynamically add DSP MMU
223 * entry. */
224 status = PROCESSOR_E_FAIL;
225 GT_setFailureReason (curTrace,
226 GT_4CLASS,
227 "DM8168DSP_halMmuCtrl",
228 status,
229 "Failed to dynamically add DSP MMU entry");
230 }
231 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
232 }
233 break;
235 case Processor_MmuCtrlCmd_DeleteEntry:
236 {
237 DM8168DSP_HalMmuCtrlArgs_DeleteEntry * deleteEntry;
238 deleteEntry = (DM8168DSP_HalMmuCtrlArgs_DeleteEntry *) args;
240 halObject = (DM8168DSP_HalObject *) halObj;
241 /* Add the entry in TLB for new request */
242 status = _DM8168DSP_halMmuDeleteEntry (halObject,deleteEntry);
243 #if !defined(SYSLINK_BUILD_OPTIMIZE)
244 if (status < 0) {
245 /*! @retval PROCESSOR_E_FAIL Failed to dynamically delete DSP
246 * MMU entry */
247 status = PROCESSOR_E_FAIL;
248 GT_setFailureReason (curTrace,
249 GT_4CLASS,
250 "DM8168DSP_halMmuCtrl",
251 status,
252 "Failed to dynamically add DSP MMU entry");
253 }
254 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
255 }
256 break;
258 default:
259 {
260 /*! @retval PROCESSOR_E_INVALIDARG Invalid argument */
261 status = PROCESSOR_E_INVALIDARG;
262 GT_setFailureReason (curTrace,
263 GT_4CLASS,
264 "DM8168DSP_halMmuCtrl",
265 status,
266 "Unsupported MMU ctrl cmd specified");
267 }
268 break;
269 }
270 #endif /* #if defined(SYSLINK_BUILDOS_LINUX) */
271 GT_1trace (curTrace, GT_LEAVE, "DM8168DSP_halMmuCtrl",status);
273 /*! @retval PROCESSOR_SUCCESS Operation successful */
274 return status;
275 }
277 #if defined(SYSLINK_BUILDOS_LINUX)
278 /* =============================================================================
279 * Internal functions
280 * =============================================================================
281 */
282 /*!
283 * @brief Enables and configures the DSP MMU as per provided memory map.
284 *
285 * @param halObject Pointer to the HAL object
286 * @param numMemEntries Number of memory entries in memTable
287 * @param memTable Table of memory entries to be configured
288 *
289 * @sa
290 */
291 Int
292 _DM8168DSP_halMmuAddStaticEntries (DM8168DSP_HalObject * halObject,
293 UInt32 numMemEntries,
294 ProcMgr_AddrInfo * memTable)
295 {
296 Int status = PROCESSOR_SUCCESS;
297 DM8168DSP_HalMmuEntryInfo staticEntry;
298 UInt32 i;
300 GT_3trace (curTrace, GT_ENTER, "_DM8168DSP_halMmuAddStaticEntries",
301 halObject, numMemEntries, memTable);
303 GT_assert (curTrace, (halObject != NULL));
304 /* It is possible that numMemEntries may be 0, if user does not want to
305 * configure any default regions.
306 * memTable may also be NULL.
307 */
309 for (i = 0 ; i < numMemEntries && (status >= 0) ; i++) {
310 if (SLAVEVIRTADDR (&memTable [i]) >= MMU_GLOBAL_MEMORY) {
311 /* Configure the TLB */
312 if (memTable [i].size != 0) {
313 staticEntry.slaveVirtAddr =
314 SLAVEVIRTADDR (&memTable [i]);
315 staticEntry.size = memTable[i].size;
316 staticEntry.masterPhyAddr =
317 MASTERPHYSADDR (&memTable [i]);
318 /*TBD : elementSize, endianism, mixedSized are hard
319 * coded now, must be configurable later*/
320 staticEntry.elementSize = MMU_RAM_ELSZ_16;
321 staticEntry.endianism = LITTLE_ENDIAN;
322 staticEntry.mixedSize = MMU_TLBES;
323 status = _DM8168DSP_halMmuAddEntry (halObject,
324 &staticEntry);
325 if (status < 0) {
326 /*! @retval PROCESSOR_E_FAIL Failed to add MMU entry. */
327 status = PROCESSOR_E_FAIL;
328 GT_setFailureReason (curTrace,
329 GT_4CLASS,
330 "_DM8168DSP_halMmuAddStaticEntries",
331 status,
332 "Failed to add MMU entry!");
333 }
334 }
335 }
336 }
337 GT_1trace (curTrace, GT_LEAVE, "_DM8168DSP_halMmuAddStaticEntries", status);
339 /*! @retval PROCESSOR_SUCCESS Operation completed successfully. */
340 return status ;
341 }
344 /*!
345 * @brief Enables and configures the DSP MMU as per provided memory map.
346 *
347 * @param halObject Pointer to the HAL object
348 * @param numMemEntries Number of memory entries in memTable
349 * @param memTable Table of memory entries to be configured
350 *
351 * @sa
352 */
353 Int
354 _DM8168DSP_halMmuEnable (DM8168DSP_HalObject * halObject,
355 UInt32 numMemEntries,
356 ProcMgr_AddrInfo * memTable)
357 {
358 Int status = PROCESSOR_SUCCESS;
359 DM8168DSP_HalMmuObject * mmuObj;
361 GT_3trace (curTrace, GT_ENTER, "_DM8168DSP_halMmuEnable",
362 halObject, numMemEntries, memTable);
364 GT_assert (curTrace, (halObject != NULL));
365 /* It is possible that numMemEntries may be 0, if user does not want to
366 * configure any default regions.
367 * memTable may also be NULL.
368 */
369 mmuObj = &(halObject->mmuObj);
370 /* Check if dspMmuHandler is alreaday available if yes put it back and get
371 * new one */
372 if(mmuObj->dspMmuHandler)
373 {
374 iommu_put(mmuObj->dspMmuHandler);
375 mmuObj->dspMmuHandler = NULL;
376 }
377 mmuObj->dspMmuHandler = iommu_get("sys");
379 #if !defined(SYSLINK_BUILD_OPTIMIZE)
380 if (IS_ERR(mmuObj->dspMmuHandler)) {
381 /*! @retval PROCESSOR_E_FAIL Failed at iommu_get. */
382 status = PROCESSOR_E_FAIL;
383 GT_setFailureReason (curTrace,
384 GT_4CLASS,
385 "_DM8168DSP_halMmuEnable",
386 status,
387 "iommu_get failed!");
388 }
389 else {
390 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
392 if ((status >= 0) && (numMemEntries != 0)) {
393 /* Only statically created entries are being added here. */
394 status = _DM8168DSP_halMmuAddStaticEntries(halObject,
395 numMemEntries,
396 memTable);
397 #if !defined(SYSLINK_BUILD_OPTIMIZE)
398 if (status < 0) {
399 /*! @retval PROCESSOR_E_FAIL Failed at
400 * _DM8168DSP_halMmuAddStaticEntries. */
401 status = PROCESSOR_E_FAIL;
402 GT_setFailureReason (curTrace,
403 GT_4CLASS,
404 "_DM8168DSP_halMmuEnable",
405 status,
406 "_DM8168DSP_halMmuAddStaticEntries failed !");
407 }
408 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
409 }
410 #if !defined(SYSLINK_BUILD_OPTIMIZE)
411 }
412 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
414 GT_1trace (curTrace, GT_LEAVE, "_DM8168DSP_halMmuEnable", status);
416 /*! @retval PROCESSOR_SUCCESS Operation completed successfully. */
417 return status ;
418 }
421 /*!
422 * @brief Disables the DSP MMU.
423 *
424 * @param halObject Pointer to the HAL object
425 *
426 * @sa
427 */
428 Int
429 _DM8168DSP_halMmuDisable (DM8168DSP_HalObject * halObject)
430 {
431 Int status = PROCESSOR_SUCCESS;
432 DM8168DSP_HalMmuObject * mmuObj;
434 GT_1trace (curTrace, GT_ENTER, "_DM8168DSP_halMmuDisable", halObject);
436 GT_assert (curTrace, (halObject != NULL));
437 mmuObj = &(halObject->mmuObj);
439 /*TBD : Delete all added static entries in TWL*/
441 /* Disable iommu. */
442 #if !defined(SYSLINK_BUILD_OPTIMIZE)
443 if(mmuObj->dspMmuHandler == NULL){
444 /*! @retval PROCESSOR_E_FAIL mmuObj->clkHandle is NULL ! */
445 status = PROCESSOR_E_FAIL;
446 GT_setFailureReason (curTrace,
447 GT_4CLASS,
448 "_DM8168DSP_halMmuDisable",
449 status,
450 "dspMmuHandler is NULL !");
451 }
452 else {
453 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
454 iommu_put(mmuObj->dspMmuHandler);
455 mmuObj->dspMmuHandler = NULL;
456 #if !defined(SYSLINK_BUILD_OPTIMIZE)
457 }
458 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
459 GT_1trace (curTrace, GT_LEAVE, "_DM8168DSP_halMmuDisable", status);
461 /*! @retval PROCESSOR_SUCCESS Operation completed successfully. */
462 return status;
463 }
466 /*!
467 * @brief This function adds an MMU entry for the specfied address and
468 * size.
469 *
470 * @param halObject Pointer to the HAL object
471 * @param entry entry to be added
472 *
473 * @sa
474 */
475 Int
476 _DM8168DSP_halMmuAddEntry (DM8168DSP_HalObject * halObject,
477 DM8168DSP_HalMmuEntryInfo * entry)
478 {
479 Int status = PROCESSOR_SUCCESS;
480 UInt32 * ppgd = NULL;
481 UInt32 * ppte = NULL;
482 DM8168DSP_HalMmuEntryInfo te;
483 DM8168DSP_HalMmuEntryInfo currentEntry;
484 Int32 currentEntrySize;
486 GT_2trace (curTrace, GT_ENTER, "_DM8168DSP_halMmuAddEntry",
487 halObject, entry);
489 GT_assert (curTrace, (halObject != NULL));
490 GT_assert (curTrace, (entry != NULL));
492 /* Add the entry (or entries) */
493 Memory_copy(¤tEntry,
494 entry,
495 sizeof(DM8168DSP_HalMmuEntryInfo));
497 /* Align the addresses to page size */
498 currentEntry.size += (currentEntry.slaveVirtAddr & (PAGE_SIZE_4KB -1));
499 currentEntry.slaveVirtAddr &= ~(PAGE_SIZE_4KB-1);
500 currentEntry.masterPhyAddr &= ~(PAGE_SIZE_4KB-1);
502 /* Align the size as well */
503 currentEntry.size = MMUPAGE_ALIGN(currentEntry.size, PAGE_SIZE_4KB);
504 currentEntrySize = currentEntry.size;
506 /* To find the max. page size with which both PA & VA are
507 * aligned */
508 while ((currentEntrySize != 0) &&
509 (status >= 0) &&
510 (currentEntry.slaveVirtAddr > MMU_GLOBAL_MEMORY)) {
511 if (currentEntrySize >= PAGE_SIZE_16MB
512 && !(currentEntry.slaveVirtAddr & (PAGE_SIZE_16MB - 1))) {
513 currentEntry.size = PAGE_SIZE_16MB;
514 }
515 else if (currentEntrySize >= PAGE_SIZE_1MB
516 && !(currentEntry.slaveVirtAddr & (PAGE_SIZE_1MB - 1))) {
517 currentEntry.size = PAGE_SIZE_1MB;
518 }
519 else if (currentEntrySize >= PAGE_SIZE_64KB
520 && !(currentEntry.slaveVirtAddr & (PAGE_SIZE_64KB - 1))){
521 currentEntry.size = PAGE_SIZE_64KB;
522 }
523 else if (currentEntrySize >= PAGE_SIZE_4KB
524 && !(currentEntry.slaveVirtAddr & (PAGE_SIZE_4KB - 1))){
525 currentEntry.size = PAGE_SIZE_4KB;
526 }
527 else {
528 Osal_printf ("Configuration error: "
529 " MMU entries must be aligned to their"
530 "page size(4KB,"
531 " 64KB, 1MB, or 16MB).\n");
532 Osal_printf ("Since the addresses are not aligned buffer"
533 "of size: %x at address: %x cannot be "
534 "TLB entries\n",
535 currentEntrySize, currentEntry.slaveVirtAddr);
536 /*! @retval DM8168DSPPROC_E_MMUCONFIG Memory region is not
537 aligned to page size */
538 status = DM8168DSPPROC_E_MMUCONFIG;
539 GT_setFailureReason (curTrace,
540 GT_4CLASS,
541 "_DM8168DSP_halMmuAddEntry",
542 status,
543 "Memory region is not aligned to page size!");
544 break ;
545 }
547 /* DO NOT put this check under SYSLINK_BUILD_OPTIMIZE */
548 if (status >= 0) {
549 /* Check every page if exists */
550 iopgtable_lookup_entry (halObject->mmuObj.dspMmuHandler,
551 currentEntry.slaveVirtAddr,
552 (u32 **) &ppgd,
553 (u32 **) &ppte);
555 /* Lookup if the entry exists */
556 if (!ppgd || !ppte) {
557 /* Entry doesnot exists, insert this page */
558 te.size = currentEntry.size;
559 te.slaveVirtAddr = currentEntry.slaveVirtAddr;
560 te.masterPhyAddr = currentEntry.masterPhyAddr;
561 te.elementSize = currentEntry.elementSize;
562 te.endianism = currentEntry.endianism;
563 te.mixedSize = currentEntry.mixedSize;
564 status = _DM8168DSP_halMmuPteSet (halObject, &te);
565 }
566 else if (ppgd && ppte) {
567 if (currentEntry.masterPhyAddr != (*ppte & IOPAGE_MASK)) {
568 /* Entry doesnot exists, insert this page */
569 te.size = currentEntry.size;
570 te.slaveVirtAddr = currentEntry.slaveVirtAddr;
571 te.masterPhyAddr = currentEntry.masterPhyAddr;
572 te.elementSize = currentEntry.elementSize;
573 te.endianism = currentEntry.endianism;
574 te.mixedSize = currentEntry.mixedSize;
575 status = _DM8168DSP_halMmuPteSet (halObject, &te);
576 }
577 }
579 #if !defined(SYSLINK_BUILD_OPTIMIZE)
580 if (status < 0) {
581 GT_setFailureReason (
582 curTrace,
583 GT_4CLASS,
584 "_DM8168DSP_halMmuAddEntry",
585 status,
586 "Failed to in _DM8168DSP_halMmuPteSet!");
587 break;
588 }
589 else {
590 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
591 currentEntrySize -= currentEntry.size;
592 currentEntry.masterPhyAddr += currentEntry.size;
593 currentEntry.slaveVirtAddr += currentEntry.size;
594 #if !defined(SYSLINK_BUILD_OPTIMIZE)
595 }
596 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
597 }
598 }
600 GT_1trace (curTrace, GT_LEAVE, "_DM8168DSP_halMmuAddEntry", status);
602 /*! @retval PROCESSOR_SUCCESS Operation completed successfully. */
603 return status;
604 }
607 /*!
608 * @brief Prints the page dump in case of error.
609 *
610 * @param phyAddr Physical address
611 * @param pg Mapped page
612 *
613 * @sa
614 */
615 Int
616 _DM8168DSP_badPageDump(UInt32 phyAddr, struct page *pg)
617 {
618 Int status = PROCESSOR_SUCCESS;
620 GT_2trace (curTrace, GT_ENTER, "_DM8168DSP_badPageDump",
621 phyAddr, pg);
623 GT_assert (curTrace, (pg != NULL));
625 Osal_printf("Bad page state in process \n"
626 "page:%p flags:0x%0*lx mapping:%p mapcount:%d count:%d\n"
627 "Backtrace:\n",
628 pg, (Int)(2*sizeof(UInt32)),
629 (UInt32)pg->flags, pg->mapping,
630 page_mapcount(pg), page_count(pg));
632 /*! @retval PROCESSOR_SUCCESS Operation completed successfully. */
633 return status;
634 }
637 /*!
638 * @brief This function deletes an MMU entry for the specfied address and
639 * size.
640 *
641 * @param halObject Pointer to the HAL object
642 * @param slaveVirtAddr DSP virtual address of the memory region
643 * @param size Size of the memory region to be configured
644 * @param isDynamic Is the MMU entry being dynamically added?
645 *
646 * @sa
647 */
648 Int
649 _DM8168DSP_halMmuDeleteEntry (DM8168DSP_HalObject * halObject,
650 DM8168DSP_HalMmuEntryInfo * entry)
651 {
652 Int status = PROCESSOR_SUCCESS;
653 UInt32 * iopgd = NULL;
654 UInt32 currentEntrySize;
655 DM8168DSP_HalMmuEntryInfo currentEntry;
656 DM8168DSP_HalMmuObject * mmuObj;
657 UInt32 clearBytes = 0;
659 GT_2trace (curTrace, GT_ENTER, "_DM8168DSP_halMmuDeleteEntry",
660 halObject, entry);
662 GT_assert (curTrace, (halObject != NULL));
663 GT_assert (curTrace, (entry != NULL));
664 GT_assert (curTrace, (entry->size != 0));
666 mmuObj = &(halObject->mmuObj);
668 /* Add the entry (or entries) */
669 Memory_copy(¤tEntry,
670 entry,
671 sizeof(DM8168DSP_HalMmuEntryInfo));
673 /* Align the addresses to page size */
674 currentEntry.size += (currentEntry.slaveVirtAddr & (PAGE_SIZE_4KB -1));
675 currentEntry.slaveVirtAddr &= ~(PAGE_SIZE_4KB-1);
677 /* Align the size as well */
678 currentEntry.size = MMUPAGE_ALIGN(currentEntry.size, PAGE_SIZE_4KB);
679 currentEntrySize = currentEntry.size;
681 /* To find the max. page size with which both PA & VA are
682 * aligned */
683 while ((currentEntrySize != 0)
684 && (status >= 0)
685 && (currentEntry.slaveVirtAddr > MMU_GLOBAL_MEMORY)) {
686 if (currentEntrySize >= PAGE_SIZE_16MB
687 && !(currentEntry.slaveVirtAddr & (PAGE_SIZE_16MB - 1))) {
688 currentEntry.size = PAGE_SIZE_16MB;
689 }
690 else if (currentEntrySize >= PAGE_SIZE_1MB
691 && !(currentEntry.slaveVirtAddr & (PAGE_SIZE_1MB - 1))) {
692 currentEntry.size = PAGE_SIZE_1MB;
693 }
694 else if (currentEntrySize >= PAGE_SIZE_64KB
695 && !(currentEntry.slaveVirtAddr & (PAGE_SIZE_64KB - 1))){
696 currentEntry.size = PAGE_SIZE_64KB;
697 }
698 else if (currentEntrySize >= PAGE_SIZE_4KB
699 && !(currentEntry.slaveVirtAddr & (PAGE_SIZE_4KB - 1))){
700 currentEntry.size = PAGE_SIZE_4KB;
701 }
702 else {
703 Osal_printf ("Configuration error: "
704 " MMU entries must be aligned to their"
705 "page size(4KB,"
706 " 64KB, 1MB, or 16MB).\n");
707 Osal_printf ("Since the addresses are not aligned buffer"
708 "of size: %x at address: %x cannot be "
709 "TLB entries\n",
710 currentEntrySize, currentEntry.slaveVirtAddr);
711 /*! @retval DM8168DSPPROC_E_MMUCONFIG Memory region is not
712 aligned to page size */
713 status = DM8168DSPPROC_E_MMUCONFIG;
714 GT_setFailureReason (curTrace,
715 GT_4CLASS,
716 "_DM8168DSP_halMmuAddEntry",
717 status,
718 "Memory region is not aligned to page size!");
719 break ;
720 }
721 /* DO NOT put this check under SYSLINK_BUILD_OPTIMIZE */
722 if (status >= 0) {
723 /* Check every page if exists */
724 iopgd = iopgd_offset(mmuObj->dspMmuHandler,
725 currentEntry.slaveVirtAddr);
727 if (*iopgd) {
728 /* Clear the requested page entry */
729 clearBytes = iopgtable_clear_entry(mmuObj->dspMmuHandler,
730 currentEntry.slaveVirtAddr);
731 }
733 currentEntry.slaveVirtAddr += currentEntry.size;
734 currentEntrySize -= currentEntry.size;
735 }
736 }
738 GT_1trace (curTrace, GT_LEAVE, "_DM8168DSP_halMmuDeleteEntry", status);
740 /*! @retval PROCESSOR_SUCCESS Operation completed successfully. */
741 return status;
742 }
745 /*!
746 * @brief Updates entries in table.
747 *
748 * @param refData Argument provided to the ISR registration function
749 *
750 * @sa
751 */
752 Int
753 _DM8168DSP_halMmuPteSet (DM8168DSP_HalObject * halObject,
754 DM8168DSP_HalMmuEntryInfo* setPteInfo)
755 {
756 DM8168DSP_HalMmuObject * mmuObj;
757 struct iotlb_entry tlb_entry;
758 Int status = PROCESSOR_SUCCESS;
760 GT_assert (curTrace, (halObject != NULL));
761 GT_assert (curTrace, (setPteInfo != NULL));
763 mmuObj = &(halObject->mmuObj);
764 GT_assert(curTrace, (mmuObj != NULL));
766 switch (setPteInfo->size) {
767 case PAGE_SIZE_16MB:
768 tlb_entry.pgsz = MMU_CAM_PGSZ_16M;
769 break;
770 case PAGE_SIZE_1MB:
771 tlb_entry.pgsz = MMU_CAM_PGSZ_1M;
772 break;
773 case PAGE_SIZE_64KB:
774 tlb_entry.pgsz = MMU_CAM_PGSZ_64K;
775 break;
776 case PAGE_SIZE_4KB:
777 tlb_entry.pgsz = MMU_CAM_PGSZ_4K;
778 break;
779 default :
780 status = PROCESSOR_E_INVALIDARG;
781 /*! @retval PROCESSOR_E_INVALIDARG Invalid Page size passed!. */
782 GT_setFailureReason (curTrace,
783 GT_4CLASS,
784 "_DM8168DSP_halMmuPteSet",
785 status,
786 "Invalid Page size passed!");
787 }
788 #if !defined(SYSLINK_BUILD_OPTIMIZE)
789 if (status >= 0) {
790 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
791 tlb_entry.prsvd = MMU_CAM_PRESERVE;
792 tlb_entry.valid = MMU_CAM_VALID;
793 /*TBD : elsz parameter has to be configured*/
794 switch (setPteInfo->elementSize) {
795 case ELEM_SIZE_8BIT:
796 tlb_entry.elsz = MMU_RAM_ELSZ_8;
797 break;
798 case ELEM_SIZE_16BIT:
799 tlb_entry.elsz = MMU_RAM_ELSZ_16;
800 break;
801 case ELEM_SIZE_32BIT:
802 tlb_entry.elsz = MMU_RAM_ELSZ_32;
803 break;
804 case ELEM_SIZE_64BIT:
805 tlb_entry.elsz = 0x3; /* No translation */
806 break;
807 default :
808 status = PROCESSOR_E_INVALIDARG;
809 /*! @retval PROCESSOR_E_INVALIDARG Invalid elementSize passed!*/
810 GT_setFailureReason (curTrace,
811 GT_4CLASS,
812 "_DM8168DSP_halMmuPteSet",
813 status,
814 "Invalid elementSize passed!");
815 }
816 #if !defined(SYSLINK_BUILD_OPTIMIZE)
817 if (status >= 0) {
818 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
819 /*TBD : endian parameter has to configured*/
820 switch (setPteInfo->endianism) {
821 case LITTLE_ENDIAN:
822 tlb_entry.endian = MMU_RAM_ENDIAN_LITTLE;
823 break;
824 case BIG_ENDIAN:
825 tlb_entry.endian = MMU_RAM_ENDIAN_BIG;
826 break;
827 default :
828 status = PROCESSOR_E_INVALIDARG;
829 /*! @retval PROCESSOR_E_INVALIDARG Invalid endianism
830 * passed!. */
831 GT_setFailureReason (curTrace,
832 GT_4CLASS,
833 "_DM8168DSP_halMmuPteSet",
834 status,
835 "Invalid endianism passed!");
836 }
837 #if !defined(SYSLINK_BUILD_OPTIMIZE)
838 if (status >= 0) {
839 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
840 /*TBD : mixed parameter has to configured*/
841 switch (setPteInfo->mixedSize) {
842 case MMU_TLBES:
843 tlb_entry.mixed = MMU_RAM_DEFAULT;
844 break;
845 case MMU_CPUES:
846 tlb_entry.mixed = MMU_RAM_MIXED;
847 break;
848 default :
849 status = PROCESSOR_E_INVALIDARG;
850 /*! @retval PROCESSOR_E_INVALIDARG Invalid
851 * mixed size passed!*/
852 GT_setFailureReason (curTrace,
853 GT_4CLASS,
854 "_DM8168DSP_halMmuPteSet",
855 status,
856 "Invalid mixed size passed!");
857 }
859 tlb_entry.da = setPteInfo->slaveVirtAddr;
860 tlb_entry.pa = setPteInfo->masterPhyAddr;
862 if (iopgtable_store_entry(mmuObj->dspMmuHandler, &tlb_entry)){
863 status = PROCESSOR_E_STOREENTERY;
864 GT_setFailureReason (curTrace,
865 GT_4CLASS,
866 "_DM8168DSP_halMmuPteSet",
867 status,
868 "iopgtable_store_entry failed!");
869 }
870 #if !defined(SYSLINK_BUILD_OPTIMIZE)
871 }
872 }
873 }
874 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
876 // GT_1trace (curTrace, GT_LEAVE, "_DM8168DSP_halMmuPteSet", status);
878 /*! @retval PROCESSOR_SUCCESS Operation completed successfully. */
879 return status;
880 }
881 #endif /* #if defined(SYSLINK_BUILDOS_LINUX) */
884 #if defined (__cplusplus)
885 }
886 #endif