/***********************************************************************
*
*             Copyright 2012 Mentor Graphics Corporation
*                         All Rights Reserved.
*
* THIS WORK CONTAINS TRADE SECRET AND PROPRIETARY INFORMATION WHICH IS
* THE PROPERTY OF MENTOR GRAPHICS CORPORATION OR ITS LICENSORS AND IS
* SUBJECT TO LICENSE TERMS.
*
************************************************************************

************************************************************************
*
*   FILE NAME
*
*       xtensa_mmu.c
*
*   DESCRIPTION
*
*       This file contains the Xtensa architecture MMU functions
*
*   FUNCTIONS
*
*       ESAL_CO_MEM_Cache_Enable            Enable cache for the
*                                           given core
*       ESAL_CO_MEM_Region_Setup            Sets-up a region of memory
*                                           based on specified attributes
*
*   DEPENDENCIES
*
*       esal.h                              Embedded Software
*                                           Abstraction Layer external
*                                           interface
*
***********************************************************************/

/* Include required header files */
#include            "nucleus.h"
#include            "os/kernel/plus/core/inc/esal.h"

#if (ESAL_CO_CACHE_AVAILABLE == NU_TRUE)

/* Local Function prototypes */
VOID    ESAL_CO_MEM_Region_Setup(INT region_num,
                                 UINT32 vrt_addr,
                                 UINT32 phy_addr,
                                 UINT32 size,
                                 ESAL_GE_CACHE_TYPE cache_type,
                                 UINT32 access_type);


/***********************************************************************
*
*   FUNCTION
*
*       ESAL_CO_MEM_Cache_Enable
*
*   DESCRIPTION
*
*       This function initializes the cache as required
*       for the given core.  The memory region data structure
*       (ESAL_DP_MEM_Region_Data) should be utilized to perform
*       this initialization and the cache attributes in this
*       table should be correctly reflected.
*
*   CALLED BY
*
*       ESAL_GE_MEM_Initialize
*
*   CALLS
*
*       ESAL_CO_MEM_Region_Setup
*
*   INPUTS
*
*       avail_mem                           Address of available memory
*
*   OUTPUTS
*
*       VOID *                              Updated available memory
*                                           address
*
***********************************************************************/
VOID    *ESAL_CO_MEM_Cache_Enable(VOID *avail_mem)
{
    INT         region_num;

    /* This is to prevent compiler warnings. */
    NU_UNUSED_PARAM(avail_mem);

    /* Unlock all Data cache lines */
    ESAL_TS_RTE_DCACHE_ALL_UNLOCK();

    /* Unlock all Instruction cache lines */
    ESAL_TS_RTE_ICACHE_ALL_UNLOCK();

    /* Invalidate all Instruction cache lines */
    ESAL_TS_RTE_DCACHE_ALL_INVALIDATE();

    /* Invalidate all Instruction cache lines */
    ESAL_TS_RTE_ICACHE_ALL_INVALIDATE();

    /* Walk through all development platform memory regions defined in table */
    for (region_num = 0; region_num < ESAL_DP_MEM_NUM_REGIONS; region_num++)
    {
        /* Enable caches for this memory section */
        ESAL_CO_MEM_Region_Setup(region_num,
                                 (UINT32)ESAL_DP_MEM_Region_Data[region_num].virtual_start_addr,
                                 (UINT32)ESAL_DP_MEM_Region_Data[region_num].physical_start_addr,
                                 ESAL_DP_MEM_Region_Data[region_num].size,
                                 ESAL_DP_MEM_Region_Data[region_num].cache_type,
                                 ESAL_DP_MEM_Region_Data[region_num].access_type);

    }   /* for loop */

    /* Return updated available memory address */
    return (avail_mem);
}


/***********************************************************************
*
*   FUNCTION
*
*       ESAL_CO_MEM_Region_Setup
*
*   DESCRIPTION
*
*       This function sets-up the region of memory based on the given
*       attributes
*
*   CALLED BY
*
*       ESAL_CO_MEM_Cache_Enable
*
*   CALLS
*
*       None
*
*   INPUTS
*
*       region_num                          Number of region begin setup
*       vrt_addr                            Virtual address of region
*       phy_addr                            Physical address of region
*       size                                Size of region
*       cache_type                          Cache type of region
*       access_type                         Memory access type of region
*
*   OUTPUTS
*
*       None
*
***********************************************************************/
VOID    ESAL_CO_MEM_Region_Setup(INT region_num,
                                 UINT32 vrt_addr,
                                 UINT32 phy_addr,
                                 UINT32 size,
                                 ESAL_GE_CACHE_TYPE cache_type,
                                 UINT32 access_type)
{
    /* This is to prevent compiler warnings. */
    NU_UNUSED_PARAM(region_num);
    NU_UNUSED_PARAM(access_type);

    UINT32 access_mode;

    /* Get PPN bits <31..29> from physcial address */
    phy_addr = ESAL_CO_TLB_PPN_MASK & phy_addr;

    /* Get VPN bits <31..29> from virtual address */
    vrt_addr = ESAL_CO_TLB_VPN_MASK & vrt_addr;

    /* Get Access Mode bits for WxTLB instruction */

    if(cache_type == ESAL_NOCACHE)
    {
        access_mode = ESAL_CO_TLB_BYPASS_CACHE;
    }
    else if(cache_type == ESAL_WRITEBACK)
    {
        access_mode = ESAL_CO_TLB_CACHE_WRBACK;
    }
    else if(cache_type == ESAL_WRITETHROUGH)
    {
        access_mode = ESAL_CO_TLB_CACHE_WRTHRU;
    }

    /* Prepare operand <at> for WxTLB instruction  */
    vrt_addr = vrt_addr | access_mode;

    /* Add TLB entries of instruction and data caches */
    ESAL_TS_RTE_ADD_TLB_ENTRY(vrt_addr, phy_addr);
}

#endif  /* ESAL_CO_CACHE_AVAILABLE == NU_TRUE */

