5d486ae4ea8c97882dbfe5e40c3b31db4061f985
1 /*
2 * @file VAYUIpuHalMmu.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 VAYUIPU COREX.
9 *
10 *
11 * ============================================================================
12 *
13 * Copyright (c) 2013-2015, 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 <ti/ipc/MultiProc.h>
63 #include <Bitops.h>
65 /* Module level headers */
66 #include <_ProcDefs.h>
67 #include <Processor.h>
69 /* Hardware Abstraction Layer headers */
70 #include <VAYUIpuHal.h>
71 #include <VAYUIpuHalMmu.h>
72 #include <VAYUIpuEnabler.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 #define MPU_INT_OFFSET 32
92 /*!
93 * @brief Interrupt Id for IPU1 MMU faults
94 */
95 #define MMU_FAULT_INTERRUPT_IPU1 100
96 #define MMU_XBAR_INTERRUPT_IPU1 395
98 /*!
99 * @brief Interrupt Id for IPU2 MMU faults
100 */
101 #define MMU_FAULT_INTERRUPT_IPU2 142
102 #define MMU_XBAR_INTERRUPT_IPU2 396
104 /*!
105 * @brief CAM register field values
106 */
107 #define MMU_CAM_PRESERVE (1 << 3)
108 #define MMU_CAM_VALID (1 << 2)
110 #define IOPTE_SHIFT 12
111 #define IOPTE_SIZE (1 << IOPTE_SHIFT)
112 #define IOPTE_MASK (~(IOPTE_SIZE - 1))
113 #define IOPAGE_MASK IOPTE_MASK
115 #define MMU_SECTION_ADDR_MASK 0xFFF00000
116 #define MMU_SSECTION_ADDR_MASK 0xFF000000
117 #define MMU_PAGE_TABLE_MASK 0xFFFFFC00
118 #define MMU_LARGE_PAGE_MASK 0xFFFF0000
119 #define MMU_SMALL_PAGE_MASK 0xFFFFF000
121 /*!
122 * @brief returns page number based on physical address
123 */
124 #define ti_ipc_phys_to_page(phys) pfn_to_page((phys) >> PAGE_SHIFT)
126 /*!
127 * @brief helper macros
128 */
129 #define SLAVEVIRTADDR(x) ((x)->addr [ProcMgr_AddrType_SlaveVirt])
130 #define SLAVEPHYSADDR(x) ((x)->addr [ProcMgr_AddrType_SlavePhys])
131 #define MASTERPHYSADDR(x) ((x)->addr [ProcMgr_AddrType_MasterPhys])
133 #define MMUPAGE_ALIGN(size, psz) (((size) + psz - 1) & ~(psz -1))
135 /*!
136 * @def CTRL_MODULE_MMR_OFFSET
137 * @brief offset in ctrl module to MMR LOCK reg.
138 */
139 #define CTRL_MODULE_MMR_OFFSET 0x544
141 /*!
142 * @def CTRL_MODULE_MPU_OFFSET
143 * @brief offset in ctrl module to MPU INTs.
144 */
145 #define CTRL_MODULE_MPU_OFFSET 0xA4C
147 /*!
148 * @def CTRL_MODULE_INT_BASE
149 * @brief interrupt num at offset.
150 */
151 #define CTRL_MODULE_INT_BASE 0x8
153 /*!
154 * @def CTRL_MODULE_INT_m_OFFSET
155 * @brief interrupt num at offset.
156 */
157 #define CTRL_MODULE_INT_m_OFFSET(m) CTRL_MODULE_MPU_OFFSET + \
158 ((((m) - CTRL_MODULE_INT_BASE) / 2) * 4) - \
159 (((m) > 131) ? 4 : 0)
161 /*!
162 * @def REG32
163 * @brief Regsiter access method.
164 */
165 #define REG32(x) (*(volatile UInt32 *) (x))
167 /* =============================================================================
168 * Forward declarations of internal functions
169 * =============================================================================
170 */
171 /* Enables the MMU for GEM Module. */
172 Int _VAYUIPU_halMmuEnable (VAYUIPU_HalObject * halObject,
173 UInt32 numMemEntries,
174 ProcMgr_AddrInfo * memTable);
176 /* Disables the MMU for GEM Module. */
177 Int _VAYUIPU_halMmuDisable (VAYUIPU_HalObject * halObject);
179 /* Add entry in TWL. */
180 Int
181 _VAYUIPU_halMmuAddEntry (VAYUIPU_HalObject * halObject,
182 VAYUIPU_HalMmuEntryInfo * entry);
183 /* Add static entries in TWL. */
184 Int
185 _VAYUIPU_halMmuAddStaticEntries (VAYUIPU_HalObject * halObject,
186 UInt32 numMemEntries,
187 ProcMgr_AddrInfo * memTable);
189 /* Delete entry from TLB. */
190 Int
191 _VAYUIPU_halMmuDeleteEntry (VAYUIPU_HalObject * halObject,
192 VAYUIPU_HalMmuEntryInfo * entry);
193 /* Set entry in to TLB. */
194 Int
195 _VAYUIPU_halMmuPteSet (VAYUIPU_HalObject * halObject,
196 VAYUIPU_HalMmuEntryInfo * setPteInfo);
199 /* =============================================================================
200 * APIs called by VAYUIPUPROC module
201 * =============================================================================
202 */
203 /*!
204 * @brief Function to control MMU operations for this slave device.
205 *
206 * @param halObj Pointer to the HAL object
207 * @param cmd MMU control command
208 * @param arg Arguments specific to the MMU control command
209 *
210 * @sa
211 */
212 Int
213 VAYUIPU_halMmuCtrl (Ptr halObj, Processor_MmuCtrlCmd cmd, Ptr args)
214 {
215 Int status = PROCESSOR_SUCCESS;
216 VAYUIPU_HalObject * halObject = NULL;
218 GT_3trace (curTrace, GT_ENTER, "VAYUIPU_halMmuCtrl", halObj, cmd, args);
220 GT_assert (curTrace, (halObj != NULL));
222 halObject = (VAYUIPU_HalObject *) halObj ;
224 switch (cmd) {
225 case Processor_MmuCtrlCmd_Enable:
226 {
227 VAYUIPU_HalMmuCtrlArgs_Enable * enableArgs;
228 enableArgs = (VAYUIPU_HalMmuCtrlArgs_Enable *) args;
229 halObject = (VAYUIPU_HalObject *) halObj;
230 status = _VAYUIPU_halMmuEnable (halObject,
231 enableArgs->numMemEntries,
232 enableArgs->memEntries);
234 #if !defined(IPC_BUILD_OPTIMIZE)
235 if (status < 0) {
236 /*! @retval PROCESSOR_E_FAIL Failed to configure IPU MMU. */
237 status = PROCESSOR_E_FAIL;
238 GT_setFailureReason (curTrace,
239 GT_4CLASS,
240 "VAYUIPU_halMmuCtrl",
241 status,
242 "Failed to configure IPU MMU"
243 "at _VAYUIPU_halMmuEnable");
244 }
245 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
246 }
247 break;
249 case Processor_MmuCtrlCmd_Disable:
250 {
251 /* args are not used. */
252 halObject = (VAYUIPU_HalObject *) halObj;
253 status = _VAYUIPU_halMmuDisable (halObject);
254 #if !defined(IPC_BUILD_OPTIMIZE)
255 if (status < 0) {
256 /*! @retval PROCESSOR_E_FAIL Failed to disable IPU MMU. */
257 status = PROCESSOR_E_FAIL;
258 GT_setFailureReason (curTrace,
259 GT_4CLASS,
260 "VAYUIPU_halMmuCtrl",
261 status,
262 "Failed to disable IPU MMU");
263 }
264 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
265 }
266 break ;
268 case Processor_MmuCtrlCmd_AddEntry:
269 {
270 VAYUIPU_HalMmuCtrlArgs_AddEntry * addEntry;
271 addEntry = (VAYUIPU_HalMmuCtrlArgs_AddEntry *) args;
273 halObject = (VAYUIPU_HalObject *) halObj;
274 /* Add the entry in TLB for new request */
275 //status = _VAYUIPU_halMmuAddEntry (halObject,addEntry) ;
276 #if !defined(IPC_BUILD_OPTIMIZE)
277 if (status < 0) {
278 /*! @retval PROCESSOR_E_FAIL Failed to dynamically add IPU MMU
279 * entry. */
280 status = PROCESSOR_E_FAIL;
281 GT_setFailureReason (curTrace,
282 GT_4CLASS,
283 "VAYUIPU_halMmuCtrl",
284 status,
285 "Failed to dynamically add IPU MMU entry");
286 }
287 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
288 }
289 break;
291 case Processor_MmuCtrlCmd_DeleteEntry:
292 {
293 VAYUIPU_HalMmuCtrlArgs_DeleteEntry * deleteEntry;
294 deleteEntry = (VAYUIPU_HalMmuCtrlArgs_DeleteEntry *) args;
296 halObject = (VAYUIPU_HalObject *) halObj;
297 /* Add the entry in TLB for new request */
298 //status = _VAYUIPU_halMmuDeleteEntry (halObject,deleteEntry);
299 #if !defined(IPC_BUILD_OPTIMIZE)
300 if (status < 0) {
301 /*! @retval PROCESSOR_E_FAIL Failed to dynamically delete IPU
302 * MMU entry */
303 status = PROCESSOR_E_FAIL;
304 GT_setFailureReason (curTrace,
305 GT_4CLASS,
306 "VAYUIPU_halMmuCtrl",
307 status,
308 "Failed to dynamically add IPU MMU entry");
309 }
310 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
311 }
312 break;
314 default:
315 {
316 /*! @retval PROCESSOR_E_INVALIDARG Invalid argument */
317 status = PROCESSOR_E_INVALIDARG;
318 GT_setFailureReason (curTrace,
319 GT_4CLASS,
320 "VAYUIPU_halMmuCtrl",
321 status,
322 "Unsupported MMU ctrl cmd specified");
323 }
324 break;
325 }
327 GT_1trace (curTrace, GT_LEAVE, "VAYUIPU_halMmuCtrl",status);
329 /*! @retval PROCESSOR_SUCCESS Operation successful */
330 return status;
331 }
333 /* =============================================================================
334 * Internal functions
335 * =============================================================================
336 */
337 /*!
338 * @brief Enables and configures the IPU MMU as per provided memory map.
339 *
340 * @param halObject Pointer to the HAL object
341 * @param numMemEntries Number of memory entries in memTable
342 * @param memTable Table of memory entries to be configured
343 *
344 * @sa
345 */
346 Int
347 _VAYUIPU_halMmuAddStaticEntries (VAYUIPU_HalObject * halObject,
348 UInt32 numMemEntries,
349 ProcMgr_AddrInfo * memTable)
350 {
351 Int status = PROCESSOR_SUCCESS;
352 VAYUIPU_HalMmuEntryInfo staticEntry;
353 UInt32 i;
355 GT_3trace (curTrace, GT_ENTER, "_VAYUIPU_halMmuAddStaticEntries",
356 halObject, numMemEntries, memTable);
358 GT_assert (curTrace, (halObject != NULL));
359 /* It is possible that numMemEntries may be 0, if user does not want to
360 * configure any default regions.
361 * memTable may also be NULL.
362 */
364 for (i = 0 ; i < numMemEntries && (status >= 0) ; i++) {
365 /* Configure the TLB */
366 if (memTable [i].size != 0) {
367 staticEntry.slaveVirtAddr =
368 SLAVEVIRTADDR (&memTable [i]);
369 staticEntry.size = memTable[i].size;
370 staticEntry.masterPhyAddr =
371 MASTERPHYSADDR (&memTable [i]);
372 /*TBD : elementSize, endianism, mixedSized are hard
373 * coded now, must be configurable later*/
374 staticEntry.elementSize = MMU_RAM_ELSZ_16;
375 staticEntry.endianism = LITTLE_ENDIAN;
376 staticEntry.mixedSize = MMU_TLBES;
377 status = _VAYUIPU_halMmuAddEntry (halObject,
378 &staticEntry);
379 if (status < 0) {
380 /*! @retval PROCESSOR_E_FAIL Failed to add MMU entry. */
381 status = PROCESSOR_E_FAIL;
382 GT_setFailureReason (curTrace,
383 GT_4CLASS,
384 "_VAYUIPU_halMmuAddStaticEntries",
385 status,
386 "Failed to add MMU entry!");
387 }
388 }
389 }
390 GT_1trace (curTrace, GT_LEAVE, "_VAYUIPU_halMmuAddStaticEntries", status);
392 /*! @retval PROCESSOR_SUCCESS Operation completed successfully. */
393 return status ;
394 }
397 /*!
398 * @brief Function to check and clear the remote proc interrupt
399 *
400 * @param arg Optional argument to the function.
401 *
402 * @sa _VAYUIPU_halMmuInt_isr
403 */
404 static
405 Bool
406 _VAYUIPU_halMmuCheckAndClearFunc (Ptr arg)
407 {
408 VAYUIPU_HalObject * halObject = (VAYUIPU_HalObject *)arg;
409 VAYUIPU_HalMmuObject * mmuObj = &(halObject->mmuObj);
411 /* Check the interrupt status */
412 mmuObj->mmuIrqStatus = REG32(halObject->mmuBase + MMU_MMU_IRQSTATUS_OFFSET);
413 mmuObj->mmuIrqStatus &= MMU_IRQ_MASK;
414 if (!(mmuObj->mmuIrqStatus))
415 return (FALSE);
417 /* Get the fault address. */
418 mmuObj->mmuFaultAddr = REG32(halObject->mmuBase + MMU_MMU_FAULT_AD_OFFSET);
420 /* Print the fault information */
421 GT_0trace (curTrace, GT_4CLASS,
422 "\n****************** IPU-MMU Fault ******************\n");
423 GT_1trace (curTrace, GT_4CLASS,
424 "**** addr: 0x%x\n", mmuObj->mmuFaultAddr);
425 if (mmuObj->mmuIrqStatus & MMU_IRQ_TLBMISS)
426 GT_0trace (curTrace, GT_4CLASS, "**** TLBMISS\n");
427 if (mmuObj->mmuIrqStatus & MMU_IRQ_TRANSLATIONFAULT)
428 GT_0trace (curTrace, GT_4CLASS, "**** TRANSLATIONFAULT\n");
429 if (mmuObj->mmuIrqStatus & MMU_IRQ_EMUMISS)
430 GT_0trace (curTrace, GT_4CLASS, "**** EMUMISS\n");
431 if (mmuObj->mmuIrqStatus & MMU_IRQ_TABLEWALKFAULT)
432 GT_0trace (curTrace, GT_4CLASS, "**** TABLEWALKFAULT\n");
433 if (mmuObj->mmuIrqStatus & MMU_IRQ_MULTIHITFAULT)
434 GT_0trace (curTrace, GT_4CLASS, "**** MULTIHITFAULT\n");
435 GT_0trace (curTrace, GT_4CLASS,
436 "**************************************************\n");
438 /* Clear the interrupt and disable further interrupts. */
439 REG32(halObject->mmuBase + MMU_MMU_IRQENABLE_OFFSET) = 0x0;
440 REG32(halObject->mmuBase + MMU_MMU_IRQSTATUS_OFFSET) = mmuObj->mmuIrqStatus;
442 /* This is not a shared interrupt, so interrupt has always occurred */
443 /*! @retval TRUE Interrupt has occurred. */
444 return (TRUE);
445 }
447 /*!
448 * @brief Interrupt Service Routine for VAYUIPUHalMmu module
449 *
450 * @param arg Optional argument to the function.
451 *
452 * @sa _VAYUIPU_halMmuCheckAndClearFunc
453 */
454 static
455 Bool
456 _VAYUIPU_halMmuInt_isr (Ptr arg)
457 {
458 VAYUIPU_HalObject * halObject = (VAYUIPU_HalObject *)arg;
459 VAYUIPUCORE0PROC_Object * procObject = NULL;
460 Int32 status;
462 GT_1trace (curTrace, GT_ENTER, "_VAYUIPU_halMmuInt_isr", arg);
463 status = VAYUIPUCORE0PROC_open((VAYUIPUCORE0PROC_Handle *)&procObject,
464 halObject->procId);
465 if (status >= 0) {
466 Processor_setState(procObject->procHandle, ProcMgr_State_Mmu_Fault);
467 VAYUIPUCORE0PROC_close((VAYUIPUCORE0PROC_Handle *)&procObject);
468 }
470 GT_1trace (curTrace, GT_LEAVE, "_VAYUIPU_halMmuInt_isr", TRUE);
472 /*! @retval TRUE Interrupt has been handled. */
473 return (TRUE);
474 }
476 /*!
477 * @brief Enables and configures the IPU MMU as per provided memory map.
478 *
479 * @param halObject Pointer to the HAL object
480 * @param numMemEntries Number of memory entries in memTable
481 * @param memTable Table of memory entries to be configured
482 *
483 * @sa
484 */
485 Int
486 _VAYUIPU_halMmuEnable (VAYUIPU_HalObject * halObject,
487 UInt32 numMemEntries,
488 ProcMgr_AddrInfo * memTable)
489 {
490 Int status = PROCESSOR_SUCCESS;
491 VAYUIPU_HalMmuObject * mmuObj;
492 OsalIsr_Params isrParams;
493 UInt32 reg = 0;
494 UInt16 ipu1ProcId = MultiProc_getId("IPU1");
496 GT_3trace (curTrace, GT_ENTER, "_VAYUIPU_halMmuEnable",
497 halObject, numMemEntries, memTable);
499 GT_assert (curTrace, (halObject != NULL));
500 /* It is possible that numMemEntries may be 0, if user does not want to
501 * configure any default regions.
502 * memTable may also be NULL.
503 */
504 mmuObj = &(halObject->mmuObj);
506 /* Program the MMR lock registers to access the SCM
507 * IRQ crossbar register address range */
508 REG32(halObject->ctrlModBase + CTRL_MODULE_MMR_OFFSET) = 0xF757FDC0;
510 /* Program the IntXbar */
511 if (halObject->procId == ipu1ProcId) {
512 reg = REG32(halObject->ctrlModBase +
513 CTRL_MODULE_INT_m_OFFSET(MMU_FAULT_INTERRUPT_IPU1));
514 if ((MMU_FAULT_INTERRUPT_IPU1 - CTRL_MODULE_INT_BASE) % 2) {
515 REG32(halObject->ctrlModBase +
516 CTRL_MODULE_INT_m_OFFSET(MMU_FAULT_INTERRUPT_IPU1)) =
517 (reg & 0x0000FFFF) | (MMU_XBAR_INTERRUPT_IPU1 << 16);
518 }
519 else {
520 REG32(halObject->ctrlModBase +
521 CTRL_MODULE_INT_m_OFFSET(MMU_FAULT_INTERRUPT_IPU1)) =
522 (reg & 0xFFFF0000) | (MMU_XBAR_INTERRUPT_IPU1);
523 }
524 }
525 else {
526 reg = REG32(halObject->ctrlModBase +
527 CTRL_MODULE_INT_m_OFFSET(MMU_FAULT_INTERRUPT_IPU2));
528 if ((MMU_FAULT_INTERRUPT_IPU2 - CTRL_MODULE_INT_BASE) % 2) {
529 REG32(halObject->ctrlModBase +
530 CTRL_MODULE_INT_m_OFFSET(MMU_FAULT_INTERRUPT_IPU2)) =
531 (reg & 0x0000FFFF) | (MMU_XBAR_INTERRUPT_IPU2 << 16);
532 }
533 else {
534 REG32(halObject->ctrlModBase +
535 CTRL_MODULE_INT_m_OFFSET(MMU_FAULT_INTERRUPT_IPU2)) =
536 (reg & 0xFFFF0000) | (MMU_XBAR_INTERRUPT_IPU2);
537 }
538 }
540 /* Create the ISR to listen for MMU Faults */
541 isrParams.sharedInt = FALSE;
542 isrParams.checkAndClearFxn = &_VAYUIPU_halMmuCheckAndClearFunc;
543 isrParams.fxnArgs = halObject;
544 isrParams.intId = (ipu1ProcId == halObject->procId ?
545 MMU_FAULT_INTERRUPT_IPU1 + MPU_INT_OFFSET : MMU_FAULT_INTERRUPT_IPU2 +
546 MPU_INT_OFFSET);
547 mmuObj->isrHandle = OsalIsr_create (&_VAYUIPU_halMmuInt_isr,
548 halObject,
549 &isrParams);
551 #if !defined(IPC_BUILD_OPTIMIZE)
552 if (mmuObj->isrHandle == NULL) {
553 /*! @retval PROCESSOR_E_FAIL Failed at iommu_get. */
554 status = PROCESSOR_E_FAIL;
555 GT_setFailureReason (curTrace,
556 GT_4CLASS,
557 "_VAYUIPU_halMmuEnable",
558 status,
559 "OsalIsr_create failed");
560 }
561 else {
562 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
564 status = OsalIsr_install (mmuObj->isrHandle);
566 #if !defined(IPC_BUILD_OPTIMIZE)
567 if (status < 0) {
568 GT_setFailureReason (curTrace,
569 GT_4CLASS,
570 "_VAYUIPU_halMmuEnable",
571 status,
572 "OsalIsr_install failed");
573 }
574 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
576 if ((status >= 0) && (numMemEntries != 0)) {
577 /* Only statically created entries are being added here. */
578 status = _VAYUIPU_halMmuAddStaticEntries(halObject,
579 numMemEntries,
580 memTable);
581 #if !defined(IPC_BUILD_OPTIMIZE)
582 if (status < 0) {
583 /*! @retval PROCESSOR_E_FAIL Failed at
584 * _VAYUIPU_halMmuAddStaticEntries. */
585 status = PROCESSOR_E_FAIL;
586 GT_setFailureReason (curTrace,
587 GT_4CLASS,
588 "_VAYUIPU_halMmuEnable",
589 status,
590 "_VAYUIPU_halMmuAddStaticEntries failed !");
591 }
592 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
593 }
594 #if !defined(IPC_BUILD_OPTIMIZE)
595 }
596 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
598 GT_1trace (curTrace, GT_LEAVE, "_VAYUIPU_halMmuEnable", status);
600 /*! @retval PROCESSOR_SUCCESS Operation completed successfully. */
601 return status ;
602 }
605 /*!
606 * @brief Disables the IPU MMU.
607 *
608 * @param halObject Pointer to the HAL object
609 *
610 * @sa
611 */
612 Int
613 _VAYUIPU_halMmuDisable (VAYUIPU_HalObject * halObject)
614 {
615 Int status = PROCESSOR_SUCCESS;
616 Int tmpStatus = PROCESSOR_SUCCESS;
617 VAYUIPU_HalMmuObject * mmuObj;
619 GT_1trace (curTrace, GT_ENTER, "_VAYUIPU_halMmuDisable", halObject);
621 GT_assert (curTrace, (halObject != NULL));
622 mmuObj = &(halObject->mmuObj);
624 status = OsalIsr_uninstall (mmuObj->isrHandle);
625 #if !defined(IPC_BUILD_OPTIMIZE)
626 if (status < 0) {
627 GT_setFailureReason (curTrace,
628 GT_4CLASS,
629 "_VAYUIPU_halMmuDisable",
630 status,
631 "OsalIsr_uninstall failed");
632 }
633 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
635 #if !defined(IPC_BUILD_OPTIMIZE)
636 tmpStatus =
637 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
638 OsalIsr_delete (&(mmuObj->isrHandle));
639 #if !defined(IPC_BUILD_OPTIMIZE)
640 if ((status >= 0) && (tmpStatus < 0)) {
641 status = tmpStatus;
642 GT_setFailureReason (curTrace,
643 GT_4CLASS,
644 "_VAYUIPU_halMmuDisable",
645 status,
646 "OsalIsr_delete failed");
647 }
648 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
650 GT_1trace (curTrace, GT_LEAVE, "_VAYUIPU_halMmuDisable", status);
652 /*! @retval PROCESSOR_SUCCESS Operation completed successfully. */
653 return status;
654 }
657 /*!
658 * @brief This function adds an MMU entry for the specfied address and
659 * size.
660 *
661 * @param halObject Pointer to the HAL object
662 * @param entry entry to be added
663 *
664 * @sa
665 */
666 Int
667 _VAYUIPU_halMmuAddEntry (VAYUIPU_HalObject * halObject,
668 VAYUIPU_HalMmuEntryInfo * entry)
669 {
670 Int status = PROCESSOR_SUCCESS;
671 UInt32 * ppgd = NULL;
672 UInt32 * ppte = NULL;
673 VAYUIPU_HalMmuEntryInfo te;
674 VAYUIPU_HalMmuEntryInfo currentEntry;
675 Int32 currentEntrySize;
677 GT_2trace (curTrace, GT_ENTER, "_VAYUIPU_halMmuAddEntry",
678 halObject, entry);
680 GT_assert (curTrace, (halObject != NULL));
681 GT_assert (curTrace, (entry != NULL));
683 /* copy the entry (or entries) */
684 Memory_copy(¤tEntry,
685 entry,
686 sizeof(VAYUIPU_HalMmuEntryInfo));
688 /* Align the addresses to page size */
689 currentEntry.size += (currentEntry.slaveVirtAddr & (PAGE_SIZE_4KB -1));
690 currentEntry.slaveVirtAddr &= ~(PAGE_SIZE_4KB-1);
691 currentEntry.masterPhyAddr &= ~(PAGE_SIZE_4KB-1);
693 /* Align the size as well */
694 currentEntry.size = MMUPAGE_ALIGN(currentEntry.size, PAGE_SIZE_4KB);
695 currentEntrySize = currentEntry.size;
697 /* To find the max. page size with which both PA & VA are
698 * aligned */
699 while ((currentEntrySize != 0) &&
700 (status >= 0)) {
701 if (currentEntrySize >= PAGE_SIZE_16MB
702 && !(currentEntry.slaveVirtAddr & (PAGE_SIZE_16MB - 1))) {
703 currentEntry.size = PAGE_SIZE_16MB;
704 }
705 else if (currentEntrySize >= PAGE_SIZE_1MB
706 && !(currentEntry.slaveVirtAddr & (PAGE_SIZE_1MB - 1))) {
707 currentEntry.size = PAGE_SIZE_1MB;
708 }
709 else if (currentEntrySize >= PAGE_SIZE_64KB
710 && !(currentEntry.slaveVirtAddr & (PAGE_SIZE_64KB - 1))){
711 currentEntry.size = PAGE_SIZE_64KB;
712 }
713 else if (currentEntrySize >= PAGE_SIZE_4KB
714 && !(currentEntry.slaveVirtAddr & (PAGE_SIZE_4KB - 1))){
715 currentEntry.size = PAGE_SIZE_4KB;
716 }
717 else {
718 Osal_printf ("Configuration error: "
719 " MMU entries must be aligned to their"
720 "page size(4KB,"
721 " 64KB, 1MB, or 16MB).\n");
722 Osal_printf ("Since the addresses are not aligned buffer"
723 "of size: %x at address: %x cannot be "
724 "TLB entries\n",
725 currentEntrySize, currentEntry.slaveVirtAddr);
726 /*! @retval VAYUIPUCORE0PROC_E_MMUCONFIG Memory region is not
727 aligned to page size */
728 status = VAYUIPUCORE0PROC_E_MMUCONFIG;
729 GT_setFailureReason (curTrace,
730 GT_4CLASS,
731 "_VAYUIPU_halMmuAddEntry",
732 status,
733 "Memory region is not aligned to page size!");
734 break ;
735 }
737 /* DO NOT put this check under IPC_BUILD_OPTIMIZE */
738 if (status >= 0) {
739 /* Lookup if the entry exists */
740 if (1) {//(!*ppgd || !*ppte) {
741 /* Entry doesnot exists, insert this page */
742 te.size = currentEntry.size;
743 te.slaveVirtAddr = currentEntry.slaveVirtAddr;
744 te.masterPhyAddr = currentEntry.masterPhyAddr;
745 te.elementSize = currentEntry.elementSize;
746 te.endianism = currentEntry.endianism;
747 te.mixedSize = currentEntry.mixedSize;
748 status = _VAYUIPU_halMmuPteSet (halObject, &te);
749 }
750 else if (ppgd && ppte) {
751 if (currentEntry.masterPhyAddr != (*ppte & IOPAGE_MASK)) {
752 /* Entry doesnot exists, insert this page */
753 te.size = currentEntry.size;
754 te.slaveVirtAddr = currentEntry.slaveVirtAddr;
755 te.masterPhyAddr = currentEntry.masterPhyAddr;
756 te.elementSize = currentEntry.elementSize;
757 te.endianism = currentEntry.endianism;
758 te.mixedSize = currentEntry.mixedSize;
759 status = _VAYUIPU_halMmuPteSet (halObject, &te);
760 }
761 }
763 #if !defined(IPC_BUILD_OPTIMIZE)
764 if (status < 0) {
765 GT_setFailureReason (
766 curTrace,
767 GT_4CLASS,
768 "_VAYUIPU_halMmuAddEntry",
769 status,
770 "Failed to in _VAYUIPU_halMmuPteSet!");
771 break;
772 }
773 else {
774 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
775 currentEntrySize -= currentEntry.size;
776 currentEntry.masterPhyAddr += currentEntry.size;
777 currentEntry.slaveVirtAddr += currentEntry.size;
778 #if !defined(IPC_BUILD_OPTIMIZE)
779 }
780 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
781 }
782 }
784 GT_1trace (curTrace, GT_LEAVE, "_VAYUIPU_halMmuAddEntry", status);
786 /*! @retval PROCESSOR_SUCCESS Operation completed successfully. */
787 return status;
788 }
791 /*!
792 * @brief This function deletes an MMU entry for the specfied address and
793 * size.
794 *
795 * @param halObject Pointer to the HAL object
796 * @param slaveVirtAddr IPU virtual address of the memory region
797 * @param size Size of the memory region to be configured
798 * @param isDynamic Is the MMU entry being dynamically added?
799 *
800 * @sa
801 */
802 Int
803 _VAYUIPU_halMmuDeleteEntry (VAYUIPU_HalObject * halObject,
804 VAYUIPU_HalMmuEntryInfo * entry)
805 {
806 Int status = PROCESSOR_SUCCESS;
807 UInt32 * iopgd = NULL;
808 UInt32 currentEntrySize;
809 VAYUIPU_HalMmuEntryInfo currentEntry;
810 VAYUIPU_HalMmuObject * mmuObj;
811 //UInt32 clearBytes = 0;
813 GT_2trace (curTrace, GT_ENTER, "_VAYUIPU_halMmuDeleteEntry",
814 halObject, entry);
816 GT_assert (curTrace, (halObject != NULL));
817 GT_assert (curTrace, (entry != NULL));
818 GT_assert (curTrace, (entry->size != 0));
820 mmuObj = &(halObject->mmuObj);
822 /* copy the entry (or entries) */
823 Memory_copy(¤tEntry,
824 entry,
825 sizeof(VAYUIPU_HalMmuEntryInfo));
827 /* Align the addresses to page size */
828 currentEntry.size += (currentEntry.slaveVirtAddr & (PAGE_SIZE_4KB -1));
829 currentEntry.slaveVirtAddr &= ~(PAGE_SIZE_4KB-1);
831 /* Align the size as well */
832 currentEntry.size = MMUPAGE_ALIGN(currentEntry.size, PAGE_SIZE_4KB);
833 currentEntrySize = currentEntry.size;
835 /* To find the max. page size with which both PA & VA are
836 * aligned */
837 while ((currentEntrySize != 0)
838 && (status >= 0)) {
839 if (currentEntrySize >= PAGE_SIZE_16MB
840 && !(currentEntry.slaveVirtAddr & (PAGE_SIZE_16MB - 1))) {
841 currentEntry.size = PAGE_SIZE_16MB;
842 }
843 else if (currentEntrySize >= PAGE_SIZE_1MB
844 && !(currentEntry.slaveVirtAddr & (PAGE_SIZE_1MB - 1))) {
845 currentEntry.size = PAGE_SIZE_1MB;
846 }
847 else if (currentEntrySize >= PAGE_SIZE_64KB
848 && !(currentEntry.slaveVirtAddr & (PAGE_SIZE_64KB - 1))){
849 currentEntry.size = PAGE_SIZE_64KB;
850 }
851 else if (currentEntrySize >= PAGE_SIZE_4KB
852 && !(currentEntry.slaveVirtAddr & (PAGE_SIZE_4KB - 1))){
853 currentEntry.size = PAGE_SIZE_4KB;
854 }
855 else {
856 Osal_printf ("Configuration error: "
857 " MMU entries must be aligned to their"
858 "page size(4KB,"
859 " 64KB, 1MB, or 16MB).\n");
860 Osal_printf ("Since the addresses are not aligned buffer"
861 "of size: %x at address: %x cannot be "
862 "TLB entries\n",
863 currentEntrySize, currentEntry.slaveVirtAddr);
864 /*! @retval VAYUIPUCORE0PROC_E_MMUCONFIG Memory region is not
865 aligned to page size */
866 status = VAYUIPUCORE0PROC_E_MMUCONFIG;
867 GT_setFailureReason (curTrace,
868 GT_4CLASS,
869 "_VAYUIPU_halMmuAddEntry",
870 status,
871 "Memory region is not aligned to page size!");
872 break ;
873 }
874 /* DO NOT put this check under IPC_BUILD_OPTIMIZE */
875 if (status >= 0) {
876 /* Check every page if exists */
877 //iopgd = iopgd_offset(mmuObj->mmuHandler,
878 // currentEntry.slaveVirtAddr);
880 if (*iopgd) {
881 /* Clear the requested page entry */
882 //clearBytes = iopgtable_clear_entry(mmuObj->mmuHandler,
883 // currentEntry.slaveVirtAddr);
884 }
886 currentEntry.slaveVirtAddr += currentEntry.size;
887 currentEntrySize -= currentEntry.size;
888 }
889 }
891 GT_1trace (curTrace, GT_LEAVE, "_VAYUIPU_halMmuDeleteEntry", status);
893 /*! @retval PROCESSOR_SUCCESS Operation completed successfully. */
894 return status;
895 }
898 static ULONG HAL_MMU_PteAddrL1(const ULONG L1_base, const ULONG va)
899 {
900 ULONG TTB_13_to_7, VA_31_to_20, desc_13_to_0;
902 TTB_13_to_7 = L1_base & (0x7FUL << 13);
903 VA_31_to_20 = va >> (20 - 2); /* Left-shift by 2 here itself */
904 desc_13_to_0 = (TTB_13_to_7 + VA_31_to_20) & (0xFFFUL << 2);
906 return ( (L1_base & 0xFFFFC000) | desc_13_to_0 );
907 }
909 static ULONG HAL_MMU_PteAddrL2(const ULONG L2_base, const ULONG va)
910 {
911 return ( (L2_base & 0xFFFFFC00) | ( (va >> 10) & 0x3FC ) );
912 }
914 #define OUTREG32(x, y) WRITE_REGISTER_ULONG(x, (ULONG)(y))
916 int VAYUIPU_InternalMMU_PteSet (const ULONG pgTblVa,
917 struct iotlb_entry * mapAttrs)
918 {
919 Int status = 0;
920 ULONG pteAddr, pteVal;
921 Int numEntries = 1;
922 ULONG physicalAddr = mapAttrs->pa;
923 ULONG virtualAddr = mapAttrs->da;
925 switch (mapAttrs->pgsz)
926 {
927 case MMU_CAM_PGSZ_4K:
928 pteAddr = HAL_MMU_PteAddrL2(pgTblVa, virtualAddr & MMU_SMALL_PAGE_MASK);
929 pteVal = ( (physicalAddr & MMU_SMALL_PAGE_MASK) |
930 (mapAttrs->endian << 9) |
931 (mapAttrs->elsz << 4) |
932 (mapAttrs->mixed << 11) | 2
933 );
934 break;
936 case MMU_CAM_PGSZ_64K:
937 numEntries = 16;
938 pteAddr = HAL_MMU_PteAddrL2(pgTblVa, virtualAddr & MMU_LARGE_PAGE_MASK);
939 pteVal = ( (physicalAddr & MMU_LARGE_PAGE_MASK) |
940 (mapAttrs->endian << 9) |
941 (mapAttrs->elsz << 4) |
942 (mapAttrs->mixed << 11) | 1
943 );
944 break;
946 case MMU_CAM_PGSZ_1M:
947 pteAddr = HAL_MMU_PteAddrL1(pgTblVa, virtualAddr & MMU_SECTION_ADDR_MASK);
948 pteVal = ( ( ( (physicalAddr & MMU_SECTION_ADDR_MASK) |
949 (mapAttrs->endian << 15) |
950 (mapAttrs->elsz << 10) |
951 (mapAttrs->mixed << 17)) &
952 ~0x40000) | 0x2
953 );
954 break;
956 case MMU_CAM_PGSZ_16M:
957 numEntries = 16;
958 pteAddr = HAL_MMU_PteAddrL1(pgTblVa, virtualAddr & MMU_SSECTION_ADDR_MASK);
959 pteVal = ( ( (physicalAddr & MMU_SSECTION_ADDR_MASK) |
960 (mapAttrs->endian << 15) |
961 (mapAttrs->elsz << 10) |
962 (mapAttrs->mixed << 17)
963 ) | 0x40000 | 0x2
964 );
965 break;
967 default:
968 return -1;
969 }
971 while (--numEntries >= 0)
972 {
973 #ifdef MMUTEST
974 ((ULONG*)pteAddr)[numEntries] = pteVal;
975 #endif
976 }
978 return status;
979 }
981 /*!
982 * @brief Updates entries in table.
983 *
984 * @param refData Argument provided to the ISR registration function
985 *
986 * @sa
987 */
988 Int
989 _VAYUIPU_halMmuPteSet (VAYUIPU_HalObject * halObject,
990 VAYUIPU_HalMmuEntryInfo * setPteInfo)
991 {
992 VAYUIPU_HalMmuObject * mmuObj;
993 struct iotlb_entry tlb_entry;
994 Int status = PROCESSOR_SUCCESS;
996 GT_assert (curTrace, (halObject != NULL));
997 GT_assert (curTrace, (setPteInfo != NULL));
999 mmuObj = &(halObject->mmuObj);
1000 GT_assert(curTrace, (mmuObj != NULL));
1002 switch (setPteInfo->size) {
1003 case PAGE_SIZE_16MB:
1004 tlb_entry.pgsz = MMU_CAM_PGSZ_16M;
1005 break;
1006 case PAGE_SIZE_1MB:
1007 tlb_entry.pgsz = MMU_CAM_PGSZ_1M;
1008 break;
1009 case PAGE_SIZE_64KB:
1010 tlb_entry.pgsz = MMU_CAM_PGSZ_64K;
1011 break;
1012 case PAGE_SIZE_4KB:
1013 tlb_entry.pgsz = MMU_CAM_PGSZ_4K;
1014 break;
1015 default :
1016 status = PROCESSOR_E_INVALIDARG;
1017 /*! @retval PROCESSOR_E_INVALIDARG Invalid Page size passed!. */
1018 GT_setFailureReason (curTrace,
1019 GT_4CLASS,
1020 "_VAYUIPU_halMmuPteSet",
1021 status,
1022 "Invalid Page size passed!");
1023 }
1024 #if !defined(IPC_BUILD_OPTIMIZE)
1025 if (status >= 0) {
1026 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
1027 tlb_entry.prsvd = MMU_CAM_PRESERVE;
1028 tlb_entry.valid = MMU_CAM_VALID;
1029 /*TBD : elsz parameter has to be configured*/
1030 switch (setPteInfo->elementSize) {
1031 case ELEM_SIZE_8BIT:
1032 tlb_entry.elsz = MMU_RAM_ELSZ_8;
1033 break;
1034 case ELEM_SIZE_16BIT:
1035 tlb_entry.elsz = MMU_RAM_ELSZ_16;
1036 break;
1037 case ELEM_SIZE_32BIT:
1038 tlb_entry.elsz = MMU_RAM_ELSZ_32;
1039 break;
1040 case ELEM_SIZE_64BIT:
1041 tlb_entry.elsz = 0x3; /* No translation */
1042 break;
1043 default :
1044 status = PROCESSOR_E_INVALIDARG;
1045 /*! @retval PROCESSOR_E_INVALIDARG Invalid elementSize passed!*/
1046 GT_setFailureReason (curTrace,
1047 GT_4CLASS,
1048 "_VAYUIPU_halMmuPteSet",
1049 status,
1050 "Invalid elementSize passed!");
1051 }
1052 #if !defined(IPC_BUILD_OPTIMIZE)
1053 if (status >= 0) {
1054 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
1055 /*TBD : endian parameter has to configured*/
1056 switch (setPteInfo->endianism) {
1057 case LITTLE_ENDIAN:
1058 tlb_entry.endian = MMU_RAM_ENDIAN_LITTLE;
1059 break;
1060 case BIG_ENDIAN:
1061 tlb_entry.endian = MMU_RAM_ENDIAN_BIG;
1062 break;
1063 default :
1064 status = PROCESSOR_E_INVALIDARG;
1065 /*! @retval PROCESSOR_E_INVALIDARG Invalid endianism
1066 * passed!. */
1067 GT_setFailureReason (curTrace,
1068 GT_4CLASS,
1069 "_VAYUIPU_halMmuPteSet",
1070 status,
1071 "Invalid endianism passed!");
1072 }
1073 #if !defined(IPC_BUILD_OPTIMIZE)
1074 if (status >= 0) {
1075 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
1076 /*TBD : mixed parameter has to configured*/
1077 switch (setPteInfo->mixedSize) {
1078 case MMU_TLBES:
1079 tlb_entry.mixed = MMU_RAM_DEFAULT;
1080 break;
1081 case MMU_CPUES:
1082 tlb_entry.mixed = MMU_RAM_MIXED;
1083 break;
1084 default :
1085 status = PROCESSOR_E_INVALIDARG;
1086 /*! @retval PROCESSOR_E_INVALIDARG Invalid
1087 * mixed size passed!*/
1088 GT_setFailureReason (curTrace,
1089 GT_4CLASS,
1090 "_VAYUIPU_halMmuPteSet",
1091 status,
1092 "Invalid mixed size passed!");
1093 }
1095 tlb_entry.da = setPteInfo->slaveVirtAddr;
1096 tlb_entry.pa = setPteInfo->masterPhyAddr;
1098 if (VAYUIPU_InternalMMU_PteSet(halObject->mmuBase,
1099 &tlb_entry)){
1100 status = PROCESSOR_E_STOREENTERY;
1101 GT_setFailureReason (curTrace,
1102 GT_4CLASS,
1103 "_VAYUIPU_halMmuPteSet",
1104 status,
1105 "iopgtable_store_entry failed!");
1106 }
1107 #if !defined(IPC_BUILD_OPTIMIZE)
1108 }
1109 }
1110 }
1111 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
1113 // GT_1trace (curTrace, GT_LEAVE, "_VAYUIPU_halMmuPteSet", status);
1115 /*! @retval PROCESSOR_SUCCESS Operation completed successfully. */
1116 return status;
1117 }
1120 #if defined (__cplusplus)
1121 }
1122 #endif