e85d82c9125d9a8e30d8cdd6fb2d2b0bbfe5727c
[ipc/ipcdev.git] / qnx / src / ipc3x_dev / ti / syslink / family / vayu / vayudsp / VAYUDspHalMmu.c
1 /*
2  *  @file   VayuDspHalMmu.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 VAYUDSP.
9  *
10  *
11  *  ============================================================================
12  *
13  *  Copyright (c) 2013, 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 <VAYUDspHal.h>
70 #include <VAYUDspHalMmu.h>
71 #include <VAYUDspPhyShmem.h>
72 #include <VAYUDspEnabler.h>
73 #include <MMUAccInt.h>
76 #if defined (__cplusplus)
77 extern "C" {
78 #endif
81 /* =============================================================================
82  *  Macros and types
83  * =============================================================================
84  */
85 /*!
86  * @brief Defines default mixedSize i.e same types of pages in one segment
87  */
88 #define MMU_RAM_DEFAULT         0
90 /*!
91  *  @brief  Interrupt Id for DSP MMU faults
92  */
93 #define MMU_FAULT_INTERRUPT     60
95 /*!
96  *  @brief  CAM register field values
97  */
98 #define MMU_CAM_PRESERVE          (1 << 3)
99 #define MMU_CAM_VALID             (1 << 2)
101 #define IOPTE_SHIFT     12
102 #define IOPTE_SIZE      (1 << IOPTE_SHIFT)
103 #define IOPTE_MASK      (~(IOPTE_SIZE - 1))
104 #define IOPAGE_MASK     IOPTE_MASK
106 #define MMU_SECTION_ADDR_MASK    0xFFF00000
107 #define MMU_SSECTION_ADDR_MASK   0xFF000000
108 #define MMU_PAGE_TABLE_MASK      0xFFFFFC00
109 #define MMU_LARGE_PAGE_MASK      0xFFFF0000
110 #define MMU_SMALL_PAGE_MASK      0xFFFFF000
112 /*!
113  * @brief returns page number based on physical address
114  */
115 #define ti_syslink_phys_to_page(phys)      pfn_to_page((phys) >> PAGE_SHIFT)
117 /*!
118  * @brief helper macros
119  */
120 #define SLAVEVIRTADDR(x)  ((x)->addr [ProcMgr_AddrType_SlaveVirt])
121 #define SLAVEPHYSADDR(x)  ((x)->addr [ProcMgr_AddrType_SlavePhys])
122 #define MASTERPHYSADDR(x) ((x)->addr [ProcMgr_AddrType_MasterPhys])
124 #define MMUPAGE_ALIGN(size, psz)  (((size) + psz - 1) & ~(psz -1))
126 /*!
127  *  @def    REG32
128  *  @brief  Regsiter access method.
129  */
130 #define REG32(x)        (*(volatile UInt32 *) (x))
132 /* =============================================================================
133  *  Forward declarations of internal functions
134  * =============================================================================
135  */
136 /* Enables the MMU for GEM Module. */
137 Int _VAYUDSP_halMmuEnable (VAYUDSP_HalObject * halObject,
138                             UInt32               numMemEntries,
139                             ProcMgr_AddrInfo *   memTable);
141 /* Disables the MMU for GEM Module. */
142 Int _VAYUDSP_halMmuDisable (VAYUDSP_HalObject * halObject);
144 /* Add entry in TWL. */
145 Int
146 _VAYUDSP_halMmuAddEntry (VAYUDSP_HalObject       * halObject,
147                           VAYUDSP_HalMmuEntryInfo * entry);
148 /* Add static entries in TWL. */
149 Int
150 _VAYUDSP_halMmuAddStaticEntries (VAYUDSP_HalObject * halObject,
151                                   UInt32               numMemEntries,
152                                   ProcMgr_AddrInfo *   memTable);
154 /* Delete entry from TLB. */
155 Int
156 _VAYUDSP_halMmuDeleteEntry (VAYUDSP_HalObject       * halObject,
157                              VAYUDSP_HalMmuEntryInfo * entry);
158 /* Set entry in to TLB. */
159 Int
160 _VAYUDSP_halMmuPteSet (VAYUDSP_HalObject       * halObject,
161                         VAYUDSP_HalMmuEntryInfo * setPteInfo);
164 /* =============================================================================
165  * APIs called by VAYUDSPPROC module
166  * =============================================================================
167  */
168 /*!
169  *  @brief      Function to control MMU operations for this slave device.
170  *
171  *  @param      halObj  Pointer to the HAL object
172  *  @param      cmd     MMU control command
173  *  @param      arg     Arguments specific to the MMU control command
174  *
175  *  @sa
176  */
177 Int
178 VAYUDSP_halMmuCtrl (Ptr halObj, Processor_MmuCtrlCmd cmd, Ptr args)
180         Int                  status     = PROCESSOR_SUCCESS;
181     VAYUDSP_HalObject * halObject  = NULL;
183     GT_3trace (curTrace, GT_ENTER, "VAYUDSP_halMmuCtrl", halObj, cmd, args);
185     GT_assert (curTrace, (halObj != NULL));
187     halObject = (VAYUDSP_HalObject *) halObj ;
189     switch (cmd) {
190         case Processor_MmuCtrlCmd_Enable:
191         {
192             VAYUDSP_HalMmuCtrlArgs_Enable * enableArgs;
193             enableArgs = (VAYUDSP_HalMmuCtrlArgs_Enable *) args;
194             halObject = (VAYUDSP_HalObject *) halObj;
195             status = _VAYUDSP_halMmuEnable (halObject,
196                                              enableArgs->numMemEntries,
197                                              enableArgs->memEntries);
199 #if !defined(SYSLINK_BUILD_OPTIMIZE)
200             if (status < 0) {
201                 /*! @retval PROCESSOR_E_FAIL Failed to configure DSP MMU. */
202                 status = PROCESSOR_E_FAIL;
203                 GT_setFailureReason (curTrace,
204                                      GT_4CLASS,
205                                      "VAYUDSP_halMmuCtrl",
206                                      status,
207                                      "Failed to configure DSP MMU"
208                                      "at _VAYUDSP_halMmuEnable");
209             }
210 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
211         }
212         break;
214         case Processor_MmuCtrlCmd_Disable:
215         {
216             /* args are not used. */
217             halObject = (VAYUDSP_HalObject *) halObj;
218             status = _VAYUDSP_halMmuDisable (halObject);
219 #if !defined(SYSLINK_BUILD_OPTIMIZE)
220             if (status < 0) {
221                 /*! @retval PROCESSOR_E_FAIL Failed to disable DSP MMU. */
222                 status = PROCESSOR_E_FAIL;
223                 GT_setFailureReason (curTrace,
224                                      GT_4CLASS,
225                                      "VAYUDSP_halMmuCtrl",
226                                      status,
227                                      "Failed to disable DSP MMU");
228             }
229 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
230         }
231         break ;
233         case Processor_MmuCtrlCmd_AddEntry:
234         {
235             VAYUDSP_HalMmuCtrlArgs_AddEntry * addEntry;
236             addEntry = (VAYUDSP_HalMmuCtrlArgs_AddEntry *) args;
238             halObject = (VAYUDSP_HalObject *) halObj;
239             /* Add the entry in TLB for new request */
240             //status = _VAYUDSP_halMmuAddEntry (halObject,addEntry) ;
241 #if !defined(SYSLINK_BUILD_OPTIMIZE)
242             if (status < 0) {
243                 /*! @retval PROCESSOR_E_FAIL Failed to dynamically add DSP MMU
244                  *                           entry. */
245                 status = PROCESSOR_E_FAIL;
246                 GT_setFailureReason (curTrace,
247                                      GT_4CLASS,
248                                      "VAYUDSP_halMmuCtrl",
249                                      status,
250                                      "Failed to dynamically add DSP MMU entry");
251             }
252 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
253         }
254         break;
256         case Processor_MmuCtrlCmd_DeleteEntry:
257         {
258             VAYUDSP_HalMmuCtrlArgs_DeleteEntry * deleteEntry;
259             deleteEntry = (VAYUDSP_HalMmuCtrlArgs_DeleteEntry *) args;
261             halObject = (VAYUDSP_HalObject *) halObj;
262             /* Add the entry in TLB for new request */
263             //status = _VAYUDSP_halMmuDeleteEntry (halObject,deleteEntry);
264 #if !defined(SYSLINK_BUILD_OPTIMIZE)
265             if (status < 0) {
266                 /*! @retval PROCESSOR_E_FAIL Failed to dynamically delete DSP
267                  *                           MMU entry  */
268                 status = PROCESSOR_E_FAIL;
269                 GT_setFailureReason (curTrace,
270                                      GT_4CLASS,
271                                      "VAYUDSP_halMmuCtrl",
272                                      status,
273                                      "Failed to dynamically add DSP MMU entry");
274             }
275 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
276         }
277         break;
279         default:
280         {
281             /*! @retval PROCESSOR_E_INVALIDARG Invalid argument */
282             status = PROCESSOR_E_INVALIDARG;
283             GT_setFailureReason (curTrace,
284                                  GT_4CLASS,
285                                  "VAYUDSP_halMmuCtrl",
286                                  status,
287                                  "Unsupported MMU ctrl cmd specified");
288         }
289         break;
290     }
292     GT_1trace (curTrace, GT_LEAVE, "VAYUDSP_halMmuCtrl",status);
294     /*! @retval PROCESSOR_SUCCESS Operation successful */
295     return status;
298 /* =============================================================================
299  * Internal functions
300  * =============================================================================
301  */
302 /*!
303  *  @brief      Enables and configures the DSP MMU as per provided memory map.
304  *
305  *  @param      halObject       Pointer to the HAL object
306  *  @param      numMemEntries   Number of memory entries in memTable
307  *  @param      memTable        Table of memory entries to be configured
308  *
309  *  @sa
310  */
311 Int
312 _VAYUDSP_halMmuAddStaticEntries (VAYUDSP_HalObject * halObject,
313                                   UInt32               numMemEntries,
314                                   ProcMgr_AddrInfo *   memTable)
316     Int                           status    = PROCESSOR_SUCCESS;
317     VAYUDSP_HalMmuEntryInfo      staticEntry;
318     UInt32                        i;
320     GT_3trace (curTrace, GT_ENTER, "_VAYUDSP_halMmuAddStaticEntries",
321                halObject, numMemEntries, memTable);
323     GT_assert (curTrace, (halObject != NULL));
324     /* It is possible that numMemEntries may be 0, if user does not want to
325      * configure any default regions.
326      * memTable may also be NULL.
327      */
329     for (i = 0 ; i < numMemEntries && (status >= 0) ; i++) {
330         /* Configure the TLB */
331         if (memTable [i].size != 0) {
332             staticEntry.slaveVirtAddr =
333                                      SLAVEVIRTADDR (&memTable [i]);
334             staticEntry.size          = memTable[i].size;
335             staticEntry.masterPhyAddr =
336                                      MASTERPHYSADDR (&memTable [i]);
337             /*TBD : elementSize, endianism, mixedSized are hard
338              *      coded now, must be configurable later*/
339             staticEntry.elementSize   = MMU_RAM_ELSZ_16;
340             staticEntry.endianism     = LITTLE_ENDIAN;
341             staticEntry.mixedSize     = MMU_TLBES;
342             status = _VAYUDSP_halMmuAddEntry (halObject,
343                                                &staticEntry);
344             if (status < 0) {
345                 /*! @retval PROCESSOR_E_FAIL Failed to add MMU entry. */
346                 status = PROCESSOR_E_FAIL;
347                 GT_setFailureReason (curTrace,
348                                      GT_4CLASS,
349                                      "_VAYUDSP_halMmuAddStaticEntries",
350                                      status,
351                                      "Failed to add MMU entry!");
352             }
353         }
354     }
355     GT_1trace (curTrace, GT_LEAVE, "_VAYUDSP_halMmuAddStaticEntries", status);
357     /*! @retval PROCESSOR_SUCCESS Operation completed successfully. */
358     return status ;
362 /*!
363  *  @brief      Function to check and clear the remote proc interrupt
364  *
365  *  @param      arg     Optional argument to the function.
366  *
367  *  @sa         _VAYUDSP_halMmuInt_isr
368  */
369 static
370 Bool
371 _VAYUDSP_halMmuCheckAndClearFunc (Ptr arg)
373     VAYUDSP_HalObject * halObject = (VAYUDSP_HalObject *)arg;
374     VAYUDSP_HalMmuObject * mmuObj = &(halObject->mmuObj);
376     /* Check the interrupt status */
377     mmuObj->mmuIrqStatus = REG32(halObject->mmuBase + MMU_MMU_IRQSTATUS_OFFSET);
378     mmuObj->mmuIrqStatus &= MMU_IRQ_MASK;
379     if (!(mmuObj->mmuIrqStatus))
380         return (FALSE);
382     /* Get the fault address. */
383     mmuObj->mmuFaultAddr = REG32(halObject->mmuBase + MMU_MMU_FAULT_AD_OFFSET);
385     /* Print the fault information */
386     GT_0trace (curTrace, GT_4CLASS,
387                "****************** DSP-MMU Fault ******************");
388     GT_1trace (curTrace, GT_4CLASS,
389                "****    addr: 0x%x", mmuObj->mmuFaultAddr);
390     if (mmuObj->mmuIrqStatus & MMU_IRQ_TLBMISS)
391         GT_0trace (curTrace, GT_4CLASS, "****    TLBMISS");
392     if (mmuObj->mmuIrqStatus & MMU_IRQ_TRANSLATIONFAULT)
393         GT_0trace (curTrace, GT_4CLASS, "****    TRANSLATIONFAULT");
394     if (mmuObj->mmuIrqStatus & MMU_IRQ_EMUMISS)
395         GT_0trace (curTrace, GT_4CLASS, "****    EMUMISS");
396     if (mmuObj->mmuIrqStatus & MMU_IRQ_TABLEWALKFAULT)
397         GT_0trace (curTrace, GT_4CLASS, "****    TABLEWALKFAULT");
398     if (mmuObj->mmuIrqStatus & MMU_IRQ_MULTIHITFAULT)
399         GT_0trace (curTrace, GT_4CLASS, "****    MULTIHITFAULT");
400     GT_0trace (curTrace, GT_4CLASS,
401                "**************************************************");
403     /* Clear the interrupt and disable further interrupts. */
404     REG32(halObject->mmuBase + MMU_MMU_IRQENABLE_OFFSET) = 0x0;
405     REG32(halObject->mmuBase + MMU_MMU_IRQSTATUS_OFFSET) = mmuObj->mmuIrqStatus;
407     /* This is not a shared interrupt, so interrupt has always occurred */
408     /*! @retval TRUE Interrupt has occurred. */
409     return (TRUE);
412 /*!
413  *  @brief      Interrupt Service Routine for VAYUDSPHalMmu module
414  *
415  *  @param      arg     Optional argument to the function.
416  *
417  *  @sa         _VAYUDSP_halMmuCheckAndClearFunc
418  */
419 static
420 Bool
421 _VAYUDSP_halMmuInt_isr (Ptr arg)
423     VAYUDSP_HalObject * halObject = (VAYUDSP_HalObject *)arg;
424     VAYUDSPPROC_Object * procObject = NULL;
425     Int32 status;
427     GT_1trace (curTrace, GT_ENTER, "_VAYUDSP_halMmuInt_isr", arg);
428     status = VAYUDSPPROC_open((VAYUDSPPROC_Handle *)&procObject, halObject->procId);
429     if (status >= 0) {
430         Processor_setState(procObject->procHandle, ProcMgr_State_Mmu_Fault);
431         VAYUDSPPROC_close((VAYUDSPPROC_Handle *)&procObject);
432     }
434     GT_1trace (curTrace, GT_LEAVE, "_VAYUDSP_halMmuInt_isr", TRUE);
436     /*! @retval TRUE Interrupt has been handled. */
437     return (TRUE);
440 /*!
441  *  @brief      Enables and configures the DSP MMU as per provided memory map.
442  *
443  *  @param      halObject       Pointer to the HAL object
444  *  @param      numMemEntries   Number of memory entries in memTable
445  *  @param      memTable        Table of memory entries to be configured
446  *
447  *  @sa
448  */
449 Int
450 _VAYUDSP_halMmuEnable (VAYUDSP_HalObject * halObject,
451                        UInt32               numMemEntries,
452                        ProcMgr_AddrInfo *   memTable)
454     Int                           status    = PROCESSOR_SUCCESS;
455     VAYUDSP_HalMmuObject *        mmuObj;
456     OsalIsr_Params                isrParams;
458     GT_3trace (curTrace, GT_ENTER, "_VAYUDSP_halMmuEnable",
459                halObject, numMemEntries, memTable);
461     GT_assert (curTrace, (halObject != NULL));
462     /* It is possible that numMemEntries may be 0, if user does not want to
463      * configure any default regions.
464      * memTable may also be NULL.
465      */
466     mmuObj = &(halObject->mmuObj);
468     /* Create the ISR to listen for MMU Faults */
469     isrParams.sharedInt        = FALSE;
470     isrParams.checkAndClearFxn = &_VAYUDSP_halMmuCheckAndClearFunc;
471     isrParams.fxnArgs          = halObject;
472     isrParams.intId            = MMU_FAULT_INTERRUPT;
473     mmuObj->isrHandle = OsalIsr_create (&_VAYUDSP_halMmuInt_isr,
474                                         halObject,
475                                         &isrParams);
477 #if !defined(SYSLINK_BUILD_OPTIMIZE)
478     if (mmuObj->isrHandle == NULL) {
479         /*! @retval PROCESSOR_E_FAIL OsalIsr_create failed */
480         status = PROCESSOR_E_FAIL;
481         GT_setFailureReason (curTrace,
482                              GT_4CLASS,
483                              "_VAYUDSP_halMmuEnable",
484                              status,
485                              "OsalIsr_create failed");
486     }
487     else {
488 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
490         status = OsalIsr_install (mmuObj->isrHandle);
492 #if !defined(SYSLINK_BUILD_OPTIMIZE)
493         if (status < 0) {
494             GT_setFailureReason (curTrace,
495                                  GT_4CLASS,
496                                  "_VAYUDSP_halMmuEnable",
497                                  status,
498                                  "OsalIsr_install failed");
499         }
500 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
502         if ((status >= 0) && (numMemEntries != 0)) {
503             GT_1trace(curTrace, GT_4CLASS, "_VAYUDSP_halMmuEnable: adding %d entries...", numMemEntries);
505             /* Only statically created entries are being added here. */
506             status = _VAYUDSP_halMmuAddStaticEntries(halObject,
507                                                      numMemEntries,
508                                                      memTable);
509 #if !defined(SYSLINK_BUILD_OPTIMIZE)
510             if (status < 0) {
511                 /*! @retval PROCESSOR_E_FAIL Failed at
512                  *                         _VAYUDSP_halMmuAddStaticEntries. */
513                 status = PROCESSOR_E_FAIL;
514                 GT_setFailureReason (curTrace,
515                                      GT_4CLASS,
516                                      "_VAYUDSP_halMmuEnable",
517                                      status,
518                                      "_VAYUDSP_halMmuAddStaticEntries failed !");
519             }
520 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
521         }
522 #if !defined(SYSLINK_BUILD_OPTIMIZE)
523     }
524 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
526     GT_1trace (curTrace, GT_LEAVE, "_VAYUDSP_halMmuEnable", status);
528     /*! @retval PROCESSOR_SUCCESS Operation completed successfully. */
529     return status ;
533 /*!
534  *  @brief      Disables the DSP MMU.
535  *
536  *  @param      halObject       Pointer to the HAL object
537  *
538  *  @sa
539  */
540 Int
541 _VAYUDSP_halMmuDisable (VAYUDSP_HalObject * halObject)
543     Int                        status    = PROCESSOR_SUCCESS;
544     Int                        tmpStatus = PROCESSOR_SUCCESS;
545     VAYUDSP_HalMmuObject *     mmuObj;
547     GT_1trace (curTrace, GT_ENTER, "_VAYUDSP_halMmuDisable", halObject);
549     GT_assert (curTrace, (halObject != NULL));
550     mmuObj = &(halObject->mmuObj);
552     status = OsalIsr_uninstall (mmuObj->isrHandle);
553 #if !defined(SYSLINK_BUILD_OPTIMIZE)
554     if (status < 0) {
555         GT_setFailureReason (curTrace,
556                              GT_4CLASS,
557                              "_VAYUDSP_halMmuDisable",
558                              status,
559                              "OsalIsr_uninstall failed");
560     }
561 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
563 #if !defined(SYSLINK_BUILD_OPTIMIZE)
564     tmpStatus =
565 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
566         OsalIsr_delete (&(mmuObj->isrHandle));
567 #if !defined(SYSLINK_BUILD_OPTIMIZE)
568     if ((status >= 0) && (tmpStatus < 0)) {
569         status = tmpStatus;
570         GT_setFailureReason (curTrace,
571                              GT_4CLASS,
572                              "_VAYUDSP_halMmuDisable",
573                              status,
574                              "OsalIsr_delete failed");
575     }
576 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
578     GT_1trace (curTrace, GT_LEAVE, "_VAYUDSP_halMmuDisable", status);
580     /*! @retval PROCESSOR_SUCCESS Operation completed successfully. */
581     return status;
585 /*!
586  *  @brief      This function adds an MMU entry for the specfied address and
587  *              size.
588  *
589  *  @param      halObject   Pointer to the HAL object
590  *  @param      entry       entry to be added
591  *
592  *  @sa
593  */
594 Int
595 _VAYUDSP_halMmuAddEntry (VAYUDSP_HalObject       * halObject,
596                          VAYUDSP_HalMmuEntryInfo * entry)
598     Int                         status = PROCESSOR_SUCCESS;
599     UInt32  *                   ppgd = NULL;
600     UInt32  *                   ppte = NULL;
601     VAYUDSP_HalMmuEntryInfo     te;
602     VAYUDSP_HalMmuEntryInfo     currentEntry;
603     Int32                       currentEntrySize;
605     GT_2trace (curTrace, GT_ENTER, "_VAYUDSP_halMmuAddEntry",
606                halObject, entry);
608     GT_assert (curTrace, (halObject != NULL));
609     GT_assert (curTrace, (entry     != NULL));
611     /* Add the entry (or entries) */
612     Memory_copy(&currentEntry,
613                 entry,
614                 sizeof(VAYUDSP_HalMmuEntryInfo));
616     /* Align the addresses to page size */
617     currentEntry.size += (currentEntry.slaveVirtAddr & (PAGE_SIZE_4KB -1));
618     currentEntry.slaveVirtAddr &= ~(PAGE_SIZE_4KB-1);
619     currentEntry.masterPhyAddr &= ~(PAGE_SIZE_4KB-1);
621     /* Align the size as well */
622     currentEntry.size = MMUPAGE_ALIGN(currentEntry.size, PAGE_SIZE_4KB);
623     currentEntrySize = currentEntry.size;
625     /* To find the max. page size with which both PA & VA are
626      * aligned */
627     while ((currentEntrySize != 0) &&
628            (status >= 0)) {
629         if (currentEntrySize >= PAGE_SIZE_16MB
630             && !(currentEntry.slaveVirtAddr & (PAGE_SIZE_16MB - 1))) {
631             currentEntry.size = PAGE_SIZE_16MB;
632         }
633         else if (currentEntrySize >= PAGE_SIZE_1MB
634                  && !(currentEntry.slaveVirtAddr & (PAGE_SIZE_1MB - 1))) {
635             currentEntry.size = PAGE_SIZE_1MB;
636         }
637         else if (currentEntrySize >= PAGE_SIZE_64KB
638                  && !(currentEntry.slaveVirtAddr & (PAGE_SIZE_64KB - 1))){
639             currentEntry.size = PAGE_SIZE_64KB;
640         }
641         else  if (currentEntrySize >= PAGE_SIZE_4KB
642                  && !(currentEntry.slaveVirtAddr & (PAGE_SIZE_4KB - 1))){
643             currentEntry.size = PAGE_SIZE_4KB;
644         }
645         else {
646             Osal_printf ("Configuration error: "
647                          " MMU entries must be aligned to their"
648                          "page size(4KB,"
649                          " 64KB, 1MB, or 16MB).\n");
650             Osal_printf ("Since the addresses are not aligned buffer"
651                          "of size: %x at address: %x cannot be  "
652                          "TLB entries\n",
653                        currentEntrySize, currentEntry.slaveVirtAddr);
654             /*! @retval VAYUDSPPROC_E_MMUCONFIG Memory region is not
655                                                  aligned to page size */
656             status = VAYUDSPPROC_E_MMUCONFIG;
657             GT_setFailureReason (curTrace,
658                               GT_4CLASS,
659                               "_VAYUDSP_halMmuAddEntry",
660                                status,
661                           "Memory region is not aligned to page size!");
662             break ;
663         }
665         /* DO NOT put this check under SYSLINK_BUILD_OPTIMIZE */
666         if (status >= 0) {
667             /* Lookup if the entry exists */
668             if (1) {//(!*ppgd || !*ppte) {
669                 /* Entry doesnot exists, insert this page */
670                 te.size = currentEntry.size;
671                 te.slaveVirtAddr = currentEntry.slaveVirtAddr;
672                 te.masterPhyAddr = currentEntry.masterPhyAddr;
673                 te.elementSize   = currentEntry.elementSize;
674                 te.endianism     = currentEntry.endianism;
675                 te.mixedSize     = currentEntry.mixedSize;
676                 status = _VAYUDSP_halMmuPteSet (halObject, &te);
677             }
678             else if (ppgd && ppte) {
679                 if (currentEntry.masterPhyAddr != (*ppte & IOPAGE_MASK)) {
680                     /* Entry doesnot exists, insert this page */
681                     te.size = currentEntry.size;
682                     te.slaveVirtAddr = currentEntry.slaveVirtAddr;
683                     te.masterPhyAddr = currentEntry.masterPhyAddr;
684                     te.elementSize   = currentEntry.elementSize;
685                     te.endianism     = currentEntry.endianism;
686                     te.mixedSize     = currentEntry.mixedSize;
687                     status = _VAYUDSP_halMmuPteSet (halObject, &te);
688                 }
689             }
691 #if !defined(SYSLINK_BUILD_OPTIMIZE)
692             if (status < 0) {
693                 GT_setFailureReason (
694                                 curTrace,
695                                 GT_4CLASS,
696                                 "_VAYUDSP_halMmuAddEntry",
697                                 status,
698                                 "Failed to in _VAYUDSP_halMmuPteSet!");
699                 break;
700             }
701             else {
702 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
703                 currentEntrySize           -= currentEntry.size;
704                 currentEntry.masterPhyAddr += currentEntry.size;
705                 currentEntry.slaveVirtAddr += currentEntry.size;
706 #if !defined(SYSLINK_BUILD_OPTIMIZE)
707             }
708 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
709         }
710     }
712     GT_1trace (curTrace, GT_LEAVE, "_VAYUDSP_halMmuAddEntry", status);
714     /*! @retval PROCESSOR_SUCCESS Operation completed successfully. */
715     return status;
719 /*!
720  *  @brief      This function deletes an MMU entry for the specfied address and
721  *              size.
722  *
723  *  @param      halObject   Pointer to the HAL object
724  *  @param      slaveVirtAddr DSP virtual address of the memory region
725  *  @param      size        Size of the memory region to be configured
726  *  @param      isDynamic   Is the MMU entry being dynamically added?
727  *
728  *  @sa
729  */
730 Int
731 _VAYUDSP_halMmuDeleteEntry (VAYUDSP_HalObject       * halObject,
732                             VAYUDSP_HalMmuEntryInfo * entry)
734     Int                         status      = PROCESSOR_SUCCESS;
735     UInt32 *                    iopgd       = NULL;
736     UInt32                      currentEntrySize;
737     VAYUDSP_HalMmuEntryInfo     currentEntry;
738     VAYUDSP_HalMmuObject *      mmuObj;
739     //UInt32                      clearBytes = 0;
741     GT_2trace (curTrace, GT_ENTER, "_VAYUDSP_halMmuDeleteEntry",
742                halObject, entry);
744     GT_assert (curTrace, (halObject            != NULL));
745     GT_assert (curTrace, (entry                != NULL));
746     GT_assert (curTrace, (entry->size          != 0));
748     mmuObj = &(halObject->mmuObj);
750     /* Add the entry (or entries) */
751     Memory_copy(&currentEntry,
752                 entry,
753                 sizeof(VAYUDSP_HalMmuEntryInfo));
755     /* Align the addresses to page size */
756     currentEntry.size += (currentEntry.slaveVirtAddr & (PAGE_SIZE_4KB -1));
757     currentEntry.slaveVirtAddr &= ~(PAGE_SIZE_4KB-1);
759     /* Align the size as well */
760     currentEntry.size = MMUPAGE_ALIGN(currentEntry.size, PAGE_SIZE_4KB);
761     currentEntrySize = currentEntry.size;
763     /* To find the max. page size with which both PA & VA are
764      * aligned */
765     while ((currentEntrySize != 0)
766             && (status >= 0)) {
767         if (currentEntrySize >= PAGE_SIZE_16MB
768             && !(currentEntry.slaveVirtAddr & (PAGE_SIZE_16MB - 1))) {
769             currentEntry.size = PAGE_SIZE_16MB;
770         }
771         else if (currentEntrySize >= PAGE_SIZE_1MB
772                  && !(currentEntry.slaveVirtAddr & (PAGE_SIZE_1MB - 1))) {
773             currentEntry.size = PAGE_SIZE_1MB;
774         }
775         else if (currentEntrySize >= PAGE_SIZE_64KB
776                  && !(currentEntry.slaveVirtAddr & (PAGE_SIZE_64KB - 1))){
777             currentEntry.size = PAGE_SIZE_64KB;
778         }
779         else  if (currentEntrySize >= PAGE_SIZE_4KB
780                  && !(currentEntry.slaveVirtAddr & (PAGE_SIZE_4KB - 1))){
781             currentEntry.size = PAGE_SIZE_4KB;
782         }
783         else {
784             Osal_printf ("Configuration error: "
785                          " MMU entries must be aligned to their"
786                          "page size(4KB,"
787                          " 64KB, 1MB, or 16MB).\n");
788             Osal_printf ("Since the addresses are not aligned buffer"
789                          "of size: %x at address: %x cannot be  "
790                          "TLB entries\n",
791                        currentEntrySize, currentEntry.slaveVirtAddr);
792             /*! @retval VAYUDSPPROC_E_MMUCONFIG Memory region is not
793                                                  aligned to page size */
794             status = VAYUDSPPROC_E_MMUCONFIG;
795             GT_setFailureReason (curTrace,
796                               GT_4CLASS,
797                               "_VAYUDSP_halMmuAddEntry",
798                                status,
799                           "Memory region is not aligned to page size!");
800             break ;
801         }
802         /* DO NOT put this check under SYSLINK_BUILD_OPTIMIZE */
803         if (status >= 0) {
804             /* Check every page if exists */
805             //iopgd = iopgd_offset(mmuObj->dspMmuHandler,
806             //                     currentEntry.slaveVirtAddr);
808             if (*iopgd) {
809                 /* Clear the requested page entry */
810                 //clearBytes = iopgtable_clear_entry(mmuObj->dspMmuHandler,
811                 //                      currentEntry.slaveVirtAddr);
812             }
814             currentEntry.slaveVirtAddr += currentEntry.size;
815             currentEntrySize           -= currentEntry.size;
816         }
817     }
819     GT_1trace (curTrace, GT_LEAVE, "_VAYUDSP_halMmuDeleteEntry", status);
821     /*! @retval PROCESSOR_SUCCESS Operation completed successfully. */
822     return status;
826 static ULONG HAL_MMU_PteAddrL1(const ULONG L1_base, const ULONG va)
828     ULONG TTB_13_to_7, VA_31_to_20, desc_13_to_0;
830     TTB_13_to_7  = L1_base & (0x7FUL << 13);
831     VA_31_to_20  = va >> (20 - 2); /* Left-shift by 2 here itself */
832     desc_13_to_0 = (TTB_13_to_7 + VA_31_to_20) & (0xFFFUL << 2);
834     return ( (L1_base & 0xFFFFC000) | desc_13_to_0 );
837 static ULONG HAL_MMU_PteAddrL2(const ULONG L2_base, const ULONG va)
839     return ( (L2_base & 0xFFFFFC00) | ( (va >> 10) & 0x3FC ) );
842 #define OUTREG32(x, y)      WRITE_REGISTER_ULONG(x, (ULONG)(y))
844 int VAYUDSP_InternalMMU_PteSet (const ULONG        pgTblVa,
845                                       struct iotlb_entry    *mapAttrs)
847     Int status = 0;
848     ULONG pteAddr, pteVal;
849     Int  numEntries = 1;
850     ULONG  physicalAddr = mapAttrs->pa;
851     ULONG  virtualAddr  = mapAttrs->da;
853     switch (mapAttrs->pgsz)
854     {
855     case MMU_CAM_PGSZ_4K:
856         pteAddr = HAL_MMU_PteAddrL2(pgTblVa, virtualAddr & MMU_SMALL_PAGE_MASK);
857         pteVal = ( (physicalAddr & MMU_SMALL_PAGE_MASK) |
858                     (mapAttrs->endian << 9) |
859                     (mapAttrs->elsz << 4) |
860                     (mapAttrs->mixed << 11) | 2
861                   );
862         break;
864     case MMU_CAM_PGSZ_64K:
865         numEntries = 16;
866         pteAddr = HAL_MMU_PteAddrL2(pgTblVa, virtualAddr & MMU_LARGE_PAGE_MASK);
867         pteVal = ( (physicalAddr & MMU_LARGE_PAGE_MASK) |
868                     (mapAttrs->endian << 9) |
869                     (mapAttrs->elsz << 4) |
870                     (mapAttrs->mixed << 11) | 1
871                   );
872         break;
874     case MMU_CAM_PGSZ_1M:
875         pteAddr = HAL_MMU_PteAddrL1(pgTblVa, virtualAddr & MMU_SECTION_ADDR_MASK);
876         pteVal = ( ( ( (physicalAddr & MMU_SECTION_ADDR_MASK) |
877                      (mapAttrs->endian << 15) |
878                      (mapAttrs->elsz << 10) |
879                      (mapAttrs->mixed << 17)) &
880                      ~0x40000) | 0x2
881                  );
882         break;
884     case MMU_CAM_PGSZ_16M:
885         numEntries = 16;
886         pteAddr = HAL_MMU_PteAddrL1(pgTblVa, virtualAddr & MMU_SSECTION_ADDR_MASK);
887         pteVal = ( ( (physicalAddr & MMU_SSECTION_ADDR_MASK) |
888                       (mapAttrs->endian << 15) |
889                       (mapAttrs->elsz << 10) |
890                       (mapAttrs->mixed << 17)
891                     ) | 0x40000 | 0x2
892                   );
893         break;
895     default:
896         return -1;
897     }
899     while (--numEntries >= 0)
900     {
901 #ifdef MMUTEST
902         ((ULONG*)pteAddr)[numEntries] = pteVal;
903 #endif
904     }
906     return status;
909 /*!
910  *  @brief      Updates entries in table.
911  *
912  *  @param      refData Argument provided to the ISR registration function
913  *
914  *  @sa
915  */
916 Int
917 _VAYUDSP_halMmuPteSet (VAYUDSP_HalObject *      halObject,
918                        VAYUDSP_HalMmuEntryInfo* setPteInfo)
920     VAYUDSP_HalMmuObject *     mmuObj;
921     struct iotlb_entry tlb_entry;
922     Int    status = PROCESSOR_SUCCESS;
924     GT_assert (curTrace, (halObject  != NULL));
925     GT_assert (curTrace, (setPteInfo != NULL));
927     mmuObj = &(halObject->mmuObj);
928     GT_assert(curTrace, (mmuObj != NULL));
930     switch (setPteInfo->size) {
931         case PAGE_SIZE_16MB:
932              tlb_entry.pgsz = MMU_CAM_PGSZ_16M;
933              break;
934         case PAGE_SIZE_1MB:
935              tlb_entry.pgsz = MMU_CAM_PGSZ_1M;
936              break;
937         case PAGE_SIZE_64KB:
938              tlb_entry.pgsz = MMU_CAM_PGSZ_64K;
939              break;
940         case PAGE_SIZE_4KB:
941              tlb_entry.pgsz = MMU_CAM_PGSZ_4K;
942              break;
943         default :
944             status = PROCESSOR_E_INVALIDARG;
945             /*! @retval PROCESSOR_E_INVALIDARG Invalid Page size passed!. */
946             GT_setFailureReason (curTrace,
947                                  GT_4CLASS,
948                                  "_VAYUDSP_halMmuPteSet",
949                                  status,
950                                  "Invalid Page size passed!");
951     }
952 #if !defined(SYSLINK_BUILD_OPTIMIZE)
953     if (status >= 0) {
954 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
955         tlb_entry.prsvd  = MMU_CAM_PRESERVE;
956         tlb_entry.valid  = MMU_CAM_VALID;
957         /*TBD : elsz parameter has to be configured*/
958         switch (setPteInfo->elementSize) {
959             case ELEM_SIZE_8BIT:
960                  tlb_entry.elsz = MMU_RAM_ELSZ_8;
961                  break;
962             case ELEM_SIZE_16BIT:
963                  tlb_entry.elsz = MMU_RAM_ELSZ_16;
964                  break;
965             case ELEM_SIZE_32BIT:
966                  tlb_entry.elsz = MMU_RAM_ELSZ_32;
967                  break;
968             case ELEM_SIZE_64BIT:
969                  tlb_entry.elsz = 0x3; /* No translation */
970                  break;
971             default :
972                 status = PROCESSOR_E_INVALIDARG;
973                 /*! @retval PROCESSOR_E_INVALIDARG Invalid elementSize passed!*/
974                 GT_setFailureReason (curTrace,
975                                      GT_4CLASS,
976                                      "_VAYUDSP_halMmuPteSet",
977                                      status,
978                                      "Invalid elementSize passed!");
979         }
980 #if !defined(SYSLINK_BUILD_OPTIMIZE)
981         if (status >= 0) {
982 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
983             /*TBD : endian parameter has to configured*/
984             switch (setPteInfo->endianism) {
985                 case LITTLE_ENDIAN:
986                         tlb_entry.endian = MMU_RAM_ENDIAN_LITTLE;
987                         break;
988                 case BIG_ENDIAN:
989                         tlb_entry.endian = MMU_RAM_ENDIAN_BIG;
990                         break;
991                 default :
992                     status = PROCESSOR_E_INVALIDARG;
993                     /*! @retval PROCESSOR_E_INVALIDARG Invalid endianism
994                      *                                 passed!. */
995                     GT_setFailureReason (curTrace,
996                                          GT_4CLASS,
997                                          "_VAYUDSP_halMmuPteSet",
998                                          status,
999                                          "Invalid endianism passed!");
1000             }
1001 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1002             if (status >= 0) {
1003 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1004                 /*TBD : mixed parameter has to configured*/
1005                 switch (setPteInfo->mixedSize) {
1006                     case MMU_TLBES:
1007                             tlb_entry.mixed = MMU_RAM_DEFAULT;
1008                             break;
1009                     case MMU_CPUES:
1010                             tlb_entry.mixed = MMU_RAM_MIXED;
1011                             break;
1012                     default :
1013                         status = PROCESSOR_E_INVALIDARG;
1014                         /*! @retval PROCESSOR_E_INVALIDARG Invalid
1015                          *                                 mixed size passed!*/
1016                         GT_setFailureReason (curTrace,
1017                                              GT_4CLASS,
1018                                              "_VAYUDSP_halMmuPteSet",
1019                                              status,
1020                                              "Invalid mixed size passed!");
1021                 }
1023                 tlb_entry.da = setPteInfo->slaveVirtAddr;
1024                 tlb_entry.pa = setPteInfo->masterPhyAddr;
1026                 if (VAYUDSP_InternalMMU_PteSet(halObject->mmuBase, &tlb_entry)){
1027                     status = PROCESSOR_E_STOREENTERY;
1028                     GT_setFailureReason (curTrace,
1029                             GT_4CLASS,
1030                             "_VAYUDSP_halMmuPteSet",
1031                             status,
1032                             "iopgtable_store_entry failed!");
1033                 }
1034 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1035             }
1036         }
1037     }
1038 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1040 //    GT_1trace (curTrace, GT_LEAVE, "_VAYUDSP_halMmuPteSet", status);
1042     /*! @retval PROCESSOR_SUCCESS Operation completed successfully. */
1043     return status;
1047 #if defined (__cplusplus)
1049 #endif