/***********************************************************************
*
*             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
*
*       ppc_mmu_e300_defs.h
*
*   DESCRIPTION
*
*       This file contains all definitions, structures, etc for the
*       PPC E300 MMU.
*
*   DATA STRUCTURES
*
*       None
*
*   DEPENDENCIES
*
*       None
*
***********************************************************************/

#ifndef     PPC_MMU_E300_DEFS_H
#define     PPC_MMU_E300_DEFS_H

/*********************************************
* Cache definitions
*********************************************/

/* Define core cache availability
   NOTE:  A differentiation is made in ESAL between cache that
          is contained on a processor and cache that is
          inherent as part of a core (L2 vs L1 cache). */
#define     ESAL_CO_CACHE_AVAILABLE                 NU_TRUE

/*********************************************
* Common definitions
*********************************************/

#define     PPC_MMU_E300_VARIANT                    3

/* Sizes, in bytes, of instruction cache for this processor.
   NOTE:  This is the size of the core cache (L1 cache) for this processor. */
#define     ESAL_CO_MEM_ICACHE_SIZE                 (UINT)(CFG_NU_OS_ARCH_PPC_COM_ICACHE_SIZE * 1024)
#define     ESAL_CO_MEM_DCACHE_SIZE                 (UINT)(CFG_NU_OS_ARCH_PPC_COM_DCACHE_SIZE * 1024)

/* Size of cache block */
#define     ESAL_CO_MEM_BLOCK_SIZE                  32

/* Bit offsets for upper bat register */
#define     ESAL_CO_MEM_UBAT_SIZE_OFFSET            2

/* Cache related defines for lower bat register bits */
#define     ESAL_CO_MEM_LBAT_GUARDED_MEM_ENABLE     ESAL_GE_MEM_32BIT_SET(28)
#define     ESAL_CO_MEM_LBAT_WT_CACHE_ENABLE        ESAL_GE_MEM_32BIT_SET(25)
#define     ESAL_CO_MEM_LBAT_NO_CACHE               ESAL_GE_MEM_32BIT_SET(26)
#define     ESAL_CO_MEM_LBAT_WB_CACHE_ENABLE        (ESAL_CO_MEM_LBAT_WT_CACHE_ENABLE|  \
                                                     ESAL_GE_MEM_32BIT_SET(27) |        \
                                                     ESAL_CO_MEM_LBAT_NO_CACHE)
#define     ESAL_CO_MEM_LBAT_IBAT_MASK_BITS         (ESAL_CO_MEM_LBAT_WT_CACHE_ENABLE | \
                                                     ESAL_CO_MEM_LBAT_GUARDED_MEM_ENABLE)

/* Define initial states for upper and lower bat registers */
#define     ESAL_CO_MEM_UBAT_INIT                   ESAL_GE_MEM_32BIT_SET(30)
#define     ESAL_CO_MEM_LBAT_INIT                   ESAL_GE_MEM_32BIT_SET(30)

/* Read Only attribute define for lower bat register bits */
#define     ESAL_CO_MEM_LBAT_READ_ONLY              ESAL_GE_MEM_32BIT_SET(31)

/* Define bits for HID0 register */
#define     ESAL_CO_MEM_HID0_ICACHE_ENABLE          ESAL_GE_MEM_32BIT_SET(16)
#define     ESAL_CO_MEM_HID0_DCACHE_ENABLE          ESAL_GE_MEM_32BIT_SET(17)
#define     ESAL_CO_MEM_HID0_ICACHE_LOCK            ESAL_GE_MEM_32BIT_SET(18)
#define     ESAL_CO_MEM_HID0_DCACHE_LOCK            ESAL_GE_MEM_32BIT_SET(19)
#define     ESAL_CO_MEM_HID0_ICACHE_INVALIDATE      ESAL_GE_MEM_32BIT_SET(20)
#define     ESAL_CO_MEM_HID0_DCACHE_INVALIDATE      ESAL_GE_MEM_32BIT_SET(21)

/* Define bits for HID0 register */
#define     ESAL_CO_MEM_HID2_HBE_ENABLE             ESAL_GE_MEM_32BIT_SET(13)

/* Define bits in MSR register for data and instruction translation */
#define     ESAL_CO_MEM_MSR_IR_BIT                  ESAL_GE_MEM_32BIT_SET(26)
#define     ESAL_CO_MEM_MSR_DR_BIT                  ESAL_GE_MEM_32BIT_SET(27)

/* SPR Register definitions */
#define     ESAL_CO_MEM_HID0_REG                    1008
#define     ESAL_CO_MEM_HID2_REG                    1011
#define     ESAL_CO_MEM_IBAT0U_REG                  ESAL_TS_RTE_IBAT0U
#define     ESAL_CO_MEM_IBAT0L_REG                  ESAL_TS_RTE_IBAT0L
#define     ESAL_CO_MEM_IBAT1U_REG                  ESAL_TS_RTE_IBAT1U
#define     ESAL_CO_MEM_IBAT1L_REG                  ESAL_TS_RTE_IBAT1L
#define     ESAL_CO_MEM_IBAT2U_REG                  ESAL_TS_RTE_IBAT2U
#define     ESAL_CO_MEM_IBAT2L_REG                  ESAL_TS_RTE_IBAT2L
#define     ESAL_CO_MEM_IBAT3U_REG                  ESAL_TS_RTE_IBAT3U
#define     ESAL_CO_MEM_IBAT3L_REG                  ESAL_TS_RTE_IBAT3L
#define     ESAL_CO_MEM_DBAT0U_REG                  ESAL_TS_RTE_DBAT0U
#define     ESAL_CO_MEM_DBAT0L_REG                  ESAL_TS_RTE_DBAT0L
#define     ESAL_CO_MEM_DBAT1U_REG                  ESAL_TS_RTE_DBAT1U
#define     ESAL_CO_MEM_DBAT1L_REG                  ESAL_TS_RTE_DBAT1L
#define     ESAL_CO_MEM_DBAT2U_REG                  ESAL_TS_RTE_DBAT2U
#define     ESAL_CO_MEM_DBAT2L_REG                  ESAL_TS_RTE_DBAT2L
#define     ESAL_CO_MEM_DBAT3U_REG                  ESAL_TS_RTE_DBAT3U
#define     ESAL_CO_MEM_DBAT3L_REG                  ESAL_TS_RTE_DBAT3L
#define     ESAL_CO_MEM_IBAT4U_REG                  560
#define     ESAL_CO_MEM_IBAT4L_REG                  561
#define     ESAL_CO_MEM_IBAT5U_REG                  562
#define     ESAL_CO_MEM_IBAT5L_REG                  563
#define     ESAL_CO_MEM_IBAT6U_REG                  564
#define     ESAL_CO_MEM_IBAT6L_REG                  565
#define     ESAL_CO_MEM_IBAT7U_REG                  566
#define     ESAL_CO_MEM_IBAT7L_REG                  567
#define     ESAL_CO_MEM_DBAT4U_REG                  568
#define     ESAL_CO_MEM_DBAT4L_REG                  569
#define     ESAL_CO_MEM_DBAT5U_REG                  570
#define     ESAL_CO_MEM_DBAT5L_REG                  571
#define     ESAL_CO_MEM_DBAT6U_REG                  572
#define     ESAL_CO_MEM_DBAT6L_REG                  573
#define     ESAL_CO_MEM_DBAT7U_REG                  574
#define     ESAL_CO_MEM_DBAT7L_REG                  575

#if (ESAL_CO_CACHE_AVAILABLE == NU_TRUE)

/* This macro invalidates all of the cache at the core level. */
#define         ESAL_CO_MEM_CACHE_ALL_INVALIDATE()                          \
                {                                                           \
                    INT     hid0_val;                                       \
                    INT     hid0_temp;                                      \
                                                                            \
                    /* Read HID0 read */                                    \
                    ESAL_TS_RTE_SPR_READ(ESAL_CO_MEM_HID0_REG, &hid0_temp); \
                    hid0_val = hid0_temp;                                   \
                    hid0_temp |= (ESAL_CO_MEM_HID0_ICACHE_INVALIDATE |      \
                                  ESAL_CO_MEM_HID0_DCACHE_INVALIDATE);      \
                                                                            \
                    /* Execute invalidate in HID0 reg. */                   \
                    ESAL_TS_RTE_SPR_WRITE(ESAL_CO_MEM_HID0_REG, hid0_temp); \
                    ESAL_TS_RTE_SYNC_EXECUTE();                             \
                    ESAL_TS_RTE_ISYNC_EXECUTE();                            \
                                                                            \
                    /* Set to previous HID0 register. */                    \
                    ESAL_TS_RTE_SPR_WRITE(ESAL_CO_MEM_HID0_REG, hid0_val);  \
                                                                            \
                    /* Execute sync instructions */                         \
                    ESAL_TS_RTE_SYNC_EXECUTE();                             \
                    ESAL_TS_RTE_ISYNC_EXECUTE();                            \
                }

/* This macro invalidates all of the instruction cache at the core level. */
#define         ESAL_CO_MEM_ICACHE_ALL_INVALIDATE()                         \
                {                                                           \
                    INT     hid0_val;                                       \
                    INT     hid0_temp;                                      \
                                                                            \
                    /* Read HID0 read */                                    \
                    ESAL_TS_RTE_SPR_READ(ESAL_CO_MEM_HID0_REG, &hid0_temp); \
                    hid0_val = hid0_temp;                                   \
                    hid0_temp |= ESAL_CO_MEM_HID0_ICACHE_INVALIDATE;        \
                                                                            \
                    /* Execute invalidate in HID0 reg. */                   \
                    ESAL_TS_RTE_SPR_WRITE(ESAL_CO_MEM_HID0_REG, hid0_temp); \
                    ESAL_TS_RTE_SYNC_EXECUTE();                             \
                    ESAL_TS_RTE_ISYNC_EXECUTE();                            \
                                                                            \
                    /* Set to previous HID0 register. */                    \
                    ESAL_TS_RTE_SPR_WRITE(ESAL_CO_MEM_HID0_REG, hid0_val);  \
                                                                            \
                    /* Execute sync instructions */                         \
                    ESAL_TS_RTE_SYNC_EXECUTE();                             \
                    ESAL_TS_RTE_ISYNC_EXECUTE();                            \
                }

/* This macro invalidates all of the data cache at the core level. */
#define         ESAL_CO_MEM_DCACHE_ALL_INVALIDATE()                         \
                {                                                           \
                    INT     hid0_val;                                       \
                    INT     hid0_temp;                                      \
                                                                            \
                    /* Read HID0 read */                                    \
                    ESAL_TS_RTE_SPR_READ(ESAL_CO_MEM_HID0_REG, &hid0_temp); \
                    hid0_val = hid0_temp;                                   \
                    hid0_temp |= ESAL_CO_MEM_HID0_DCACHE_INVALIDATE;        \
                                                                            \
                    /* Execute invalidate in HID0 reg. */                   \
                    ESAL_TS_RTE_SPR_WRITE(ESAL_CO_MEM_HID0_REG, hid0_temp); \
                    ESAL_TS_RTE_SYNC_EXECUTE();                             \
                    ESAL_TS_RTE_ISYNC_EXECUTE();                            \
                                                                            \
                    /* Set to previous HID0 register. */                    \
                    ESAL_TS_RTE_SPR_WRITE(ESAL_CO_MEM_HID0_REG, hid0_val);  \
                                                                            \
                    /* Execute sync instructions */                         \
                    ESAL_TS_RTE_SYNC_EXECUTE();                             \
                    ESAL_TS_RTE_ISYNC_EXECUTE();                            \
                }

/* This macro invalidates all instruction cache for the specified address
   range at the core level. */
#define         ESAL_CO_MEM_ICACHE_INVALIDATE(addr, size)                   \
                {                                                           \
                    INT     cache_block = 0;                                \
                                                                            \
                    do                                                      \
                    {                                                       \
                        /* Execute data block invalidate. */                \
                        ESAL_TS_RTE_ICBI_EXECUTE(addr, cache_block);        \
                                                                            \
                        /* Execute sync instructions */                     \
                        ESAL_TS_RTE_SYNC_EXECUTE();                         \
                        ESAL_TS_RTE_ISYNC_EXECUTE();                        \
                                                                            \
                        /* Go to next cache block. */                       \
                        cache_block += ESAL_CO_MEM_BLOCK_SIZE;              \
                                                                            \
                    } while(cache_block < size);                            \
                }

/* This macro invalidates all data cache for the specified address
   range at the core level. */
#define         ESAL_CO_MEM_DCACHE_INVALIDATE(addr, size)                   \
                {                                                           \
                    INT     cache_block = 0;                                \
                                                                            \
                    do                                                      \
                    {                                                       \
                        /* Execute data block invalidate. */                \
                        ESAL_TS_RTE_DCBI_EXECUTE(addr, cache_block);        \
                                                                            \
                        /* Execute sync instructions */                     \
                        ESAL_TS_RTE_SYNC_EXECUTE();                         \
                        ESAL_TS_RTE_ISYNC_EXECUTE();                        \
                                                                            \
                        /* Go to next cache block. */                       \
                        cache_block += ESAL_CO_MEM_BLOCK_SIZE;              \
                                                                            \
                    } while(cache_block < size);                            \
                }

/* This macro flushes all data cache to physical memory (writeback cache)
   and invalidates all data cache entries at the core level. */
#define         ESAL_CO_MEM_DCACHE_ALL_FLUSH_INVAL()                            \
                {                                                               \
                    /* Flush and invalidate entire data cache */                \
                    ESAL_CO_MEM_DCACHE_FLUSH_INVAL(0, ESAL_CO_MEM_DCACHE_SIZE); \
                }

/* This macro flushes all data cache to physical memory (writeback cache)
   for the given address range, then invalidates all data cache entries
   at the core level. */
#define         ESAL_CO_MEM_DCACHE_FLUSH_INVAL(addr, size)                  \
                {                                                           \
                    INT     cache_block = 0;                                \
                                                                            \
                    do                                                      \
                    {                                                       \
                        /* Execute data block flush. */                     \
                        ESAL_TS_RTE_DCBF_EXECUTE(addr, cache_block);        \
                                                                            \
                        /* Execute sync instructions */                     \
                        ESAL_TS_RTE_SYNC_EXECUTE();                         \
                        ESAL_TS_RTE_ISYNC_EXECUTE();                        \
                                                                            \
                        /* Execute data block invalidate. */                \
                        ESAL_TS_RTE_DCBI_EXECUTE(addr, cache_block);        \
                                                                            \
                        /* Execute sync instructions */                     \
                        ESAL_TS_RTE_SYNC_EXECUTE();                         \
                        ESAL_TS_RTE_ISYNC_EXECUTE();                        \
                                                                            \
                        /* Go to next cache block. */                       \
                        cache_block += ESAL_CO_MEM_BLOCK_SIZE;              \
                                                                            \
                    } while(cache_block < size);                            \
                }

/* This macro disables instruction and data cache */
#define         ESAL_CO_MEM_CACHE_DISABLE()                                 \
                {                                                           \
                    INT     hid0_val;                                       \
                                                                            \
                    /* Get current HID0. */                                 \
                    ESAL_TS_RTE_SPR_READ(ESAL_CO_MEM_HID0_REG, &hid0_val);  \
                                                                            \
                    /* Clear instruction / data cache enable bits */        \
                    hid0_val &= ~(ESAL_CO_MEM_HID0_ICACHE_ENABLE | ESAL_CO_MEM_HID0_DCACHE_ENABLE); \
                                                                            \
                    /* Set new HID0 register value */                       \
                    ESAL_TS_RTE_SPR_WRITE(ESAL_CO_MEM_HID0_REG, hid0_val);  \
                    ESAL_TS_RTE_ISYNC_EXECUTE();                            \
                    ESAL_TS_RTE_SYNC_EXECUTE();                             \
                }

#endif  /* ESAL_CO_CACHE_AVAILABLE == NU_TRUE */

/*********************************************
* PPC E300 Architecture MMU definitions
*********************************************/

/* This macro disables the MMU */
#define ESAL_AR_MMU_DISABLE()                                               \
    {                                                                       \
        UINT32  temp32;                                                     \
                                                                            \
        /* Get current MSR value */                                         \
        ESAL_TS_RTE_MSR_READ(&temp32);                                      \
                                                                            \
        /* Disable instruction (IR) and data (DR) address translation */    \
        temp32 &= ~(ESAL_CO_MEM_MSR_IR_BIT | ESAL_CO_MEM_MSR_DR_BIT);       \
                                                                            \
        /* Set new MSR value */                                             \
        ESAL_TS_RTE_MSR_WRITE(temp32);                                      \
        ESAL_TS_RTE_ISYNC_EXECUTE();                                        \
    }

#endif  /* PPC_MMU_E300_DEFS_H */
