/*
 *******************************************************************************
 *  
 * C64XPLUS Based H.264 BP Encoder
 * 
 * "C64XPLUS Based H.264 BP Encoder" is software module developed on TI's
 *  C64XPLUS based SOCs. This module is capable of compressing a 4:2:0 Raw 
 *  video into a baseline profile bit-stream. Based on ISO/IEC 14496-10. 
 *
 * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ 
 * ALL RIGHTS RESERVED 
 *******************************************************************************
*/
#ifndef C64XREGH
#define C64XREGH

#define MASK_TARGET_WORD    0xffff
#define TARGET_WRD_SZ   CHAR_BIT    
#define BYTES_PER_WORD  TARGET_WRD_SZ/8
#define WORD_SIZE   (CHAR_BIT * sizeof(unsigned int))

#define ONE32   ((int)0x00000001)
#define ZERO32  ((int)0x00000000)

#define MODULE_ID_SFT         24
#define DSP0_MODULE_ID         0
#define DSP1_MODULE_ID         1
#define DSP2_MODULE_ID         2
#define DSP3_MODULE_ID         3
#define DSP4_MODULE_ID         4
#define DSP5_MODULE_ID         5
#define EXT_MEM_MODULE_ID      0xE
#define SHARED_MEM_MODULE_ID   0xF

/* C64xplus registers directly used */
extern cregister volatile unsigned int DNUM;
extern cregister volatile unsigned int TSCL;
extern cregister volatile unsigned int TSCH;
/*----------------------------------------------------------------------------*/
/* MACRO FUNCTIONS                                                            */
/*----------------------------------------------------------------------------*/
#define CONTENTS_OF(addr) \
        (*((volatile unsigned int*)(addr)))

#define LENGTH_TO_BITS(length) \
        (~(0xffffffff << (length)))

/*----------------------------------------------------------------------------*/
/* MACROS to SET, CLEAR and RETURN bits and bitfields in Memory Mapped        */
/* locations using the address of the specified register.                     */
/*----------------------------------------------------------------------------*/

#define REG_READ(addr) \
        (CONTENTS_OF(addr))

#define REG_WRITE(addr,val) \
        (CONTENTS_OF(addr) = (val))

#define MASK_BIT(bit) \
        (1 << (bit))

#define RESET_BIT(addr,bit) \
        (CONTENTS_OF(addr) &= (~MASK_BIT(bit)))

#define GET_BIT(addr,bit) \
        (CONTENTS_OF(addr) & (MASK_BIT(bit)) ? 1 : 0)

#define SET_BIT(addr,bit) \
        (CONTENTS_OF(addr) = (CONTENTS_OF(addr)) | (MASK_BIT(bit)))

#define ASSIGN_BIT_VAL(addr,bit,val) \
        ( (val) ? SET_BIT(addr,bit) : RESET_BIT(addr,bit) )

#define CREATE_FIELD(bit,length) \
        (LENGTH_TO_BITS(length) << (bit))

#define RESET_FIELD(addr,bit,length) \
        ( CONTENTS_OF(addr) &= (~CREATE_FIELD(bit,length)))

#define TRUNCATE(val,bit,length) \
        (((unsigned int)(val) << (bit)) & (CREATE_FIELD(bit, length)))

#define MASK_FIELD(bit,val,length)\
        TRUNCATE(val, bit, length)

#define GET_FIELD(addr,bit,length) \
       ((CONTENTS_OF(addr) & CREATE_FIELD(bit,length)) >> bit)

#define LOAD_FIELD(addr,val,bit,length) \
        (CONTENTS_OF(addr) = CONTENTS_OF(addr) & (~CREATE_FIELD(bit,length)) \
                             |  TRUNCATE(val, bit, length))
              

/******************************************************************************/
/* Memory-mapped Byte Manipulation Macros                                     */
/******************************************************************************/

#define CSET_BIT(reg,bit) \
((*((volatile unsigned char *)(reg))) |= (MASK_BIT(bit)))

#define CGET_BIT(reg,bit) \
((*((volatile unsigned char *)(reg))) & (MASK_BIT(bit)) ? 1 : 0)

#define CCLR_BIT(reg,bit) \
((*((volatile unsigned char *)(reg))) &= (~MASK_BIT(bit)))

#define CGET_FIELD(reg,bit,length) \
((*((volatile unsigned char *)(reg)) & (MASK_FIELD(bit,length))) >> bit)

#define CLOAD_FIELD(reg,bit,length,val) \
   ((*((volatile unsigned char *)(reg))) = \
((*((volatile unsigned char *)(reg)) & (~MASK_FIELD(bit,length)))) | (val<<bit))

#define CREG_READ(addr) \
(*((unsigned char *)(addr)))

#define CREG_WRITE(addr,val) \
(*((unsigned char *)(addr)) = (val))

/*----------------------------------------------------------------------------*/
/* MACROS to SET, CLEAR and RETURN bits and bitfields in Memory Mapped        */
/* and Non-Memory Mapped using register names.                                */
/*----------------------------------------------------------------------------*/

#define GET_REG(reg) \
        (reg)

#define SET_REG(reg,val) \
        ((reg)= (val))

#define GET_REG_BIT(reg,bit) \
        ((reg) & MASK_BIT(bit) ? 1 : 0)

#define SET_REG_BIT(reg,bit) \
        ((reg) |= MASK_BIT(bit))

#define RESET_REG_BIT(reg,bit) \
        ((reg) &= (~MASK_BIT(bit)))

#define GET_REG_FIELD(reg,bit,length) \
        (reg & CREATE_FIELD(bit,length)) >> bit)

#define LOAD_REG_FIELD(reg,val,bit,length) \
        (reg &= (~CREATE_FIELD(bit,length)) | (val<<bit))

/* Revision identification definitions */
#define CHIPID_6416                 0x0C01

#define CSL_C6416_REVISION_11       0x0011   /* Q.4 format */
#define CSL_C6416_REVISION_UNKNOWN  0xffff



#define   C64X_CCFG_ADDR      0x01840000
#define   C64X_CCFG           (*(volatile unsigned int *)C64X_CCFG_ADDR)

#define   C64X_L1PCFG_ADDR    0x01840020
#define   C64X_L1PCFG         (*(volatile unsigned int *)C64X_L1PCFG_ADDR)

#define   C64X_L1DCFG_ADDR    0x01840040
#define   C64X_L1DCFG         (*(volatile unsigned int *)C64X_L1DCFG_ADDR)

#define   C64X_L2ALLOC0_ADDR  0x01842000  /* L2 allocation register 0 */
#define   C64X_L2ALLOC0       (*(volatile unsigned int *)C64X_L2ALLOC0_ADDR)

#define   C64X_L2ALLOC1_ADDR  0x01842004  /* L2 allocation register 1 */
#define   C64X_L2ALLOC1       (*(volatile unsigned int *)C64X_L2ALLOC1_ADDR)

#define   C64X_L2ALLOC2_ADDR  0x01842008  /* L2 allocation register 2 */
#define   C64X_L2ALLOC2       (*(volatile unsigned int *)C64X_L2ALLOC2_ADDR)

#define   C64X_L2ALLOC3_ADDR  0x0184200C  /* L2 allocation register 3 */
#define   C64X_L2ALLOC3       (*(volatile unsigned int *)C64X_L2ALLOC3_ADDR)

#define   C64X_L2FBAR_ADDR    0x01844000  /* L2 flush base address register  */
#define   C64X_L2FBAR         (*(volatile unsigned int *)C64X_L2FBAR_ADDR) 

#define   C64X_L2FWC_ADDR     0x01844004  /* L2 flush word count register    */
#define   C64X_L2FWC          (*(volatile unsigned int *)C64X_L2FWC_ADDR)

#define   C64X_L2CBAR_ADDR    0x01844010  /* L2 clean base address register  */
#define   C64X_L2CBAR         (*(volatile unsigned int *)C64X_L2CBAR_ADDR)

#define   C64X_L2CWC_ADDR     0x01844014  /* L2 clean word count register    */
#define   C64X_L2CWC          (*(volatile unsigned int *)C64X_L2CWC_ADDR)

#define   C64X_L1PFBAR_ADDR   0x01844020  /* L1P flush base address register */
#define   C64X_L1PFBAR        (*(volatile unsigned int *)C64X_L1PFBAR_ADDR) 

#define   C64X_L1PFWC_ADDR    0x01844024  /* L1P flush word count register   */
#define   C64X_L1PFWC         (*(volatile unsigned int *)C64X_L1PFWC_ADDR)

#define   C64X_L1DFBAR_ADDR   0x01844030  /* L1D flush base address register */
#define   C64X_L1DFBAR        (*(volatile unsigned int *)C64X_L1DFBAR_ADDR)

#define   C64X_L1DFWC_ADDR    0x01844034  /* L1D flush word count register   */
#define   C64X_L1DFWC         (*(volatile unsigned int *)C64X_L1DFWC_ADDR)

#define   C64X_L2FLUSH_ADDR   0x01845000  /* L2 flush register               */
#define   C64X_L2FLUSH        (*(volatile unsigned int *)C64X_L2FLUSH_ADDR)

#define   C64X_L2WBCLEAN_ADDR   0x01845004  /* L2 clean register             */
#define   C64X_L2WBCLEAN        (*(volatile unsigned int *)C64X_L2WBCLEAN_ADDR)

#define   C64X_L1PCLEAN_ADDR   0x01845028  /* L1P clean register             */
#define   C64X_L1PCLEAN        (*(volatile unsigned int *)C64X_L1PCLEAN_ADDR)

#define   C64X_L1DWBCLEAN_ADDR   0x01845044  
                                /* L1D WRITEBACK Invalidate clean register   */
#define   C64X_L1DWBCLEAN      (*(volatile unsigned int *)C64X_L1DWBCLEAN_ADDR)


/* Defines the psooible L2 Modes of operation */
#define    L2MODE0KCACHE        0x000
#define    L2MODE32KCACHE       0x001
#define    L2MODE64KCACHE       0x002
#define    L2MODE128KCACHE      0x003
#define    L2MODE256KCACHE      0x007

#define CACHE_L2_LINESIZE       128
#define CACHE_L1D_LINESIZE      64
#define CACHE_L1P_LINESIZE      32


/***********************************************************************/
/* Define bit fields for Cache Configuration registers                 */
/***********************************************************************/
#define    C64X_CCFG_L2MODE             0
#define    C64X_CCFG_L2MODE_SZ          3

#define    C64X_CCFG_IP                 8
#define    C64X_CCFG_IP_SZ              1

#define    C64X_CCFG_ID                 9
#define    C64X_CCFG_ID_SZ              1

#define    C64X_CCFG_P                  29
#define    C64X_CCFG_P_SZ               3

/***********************************************************************/
/* Define bit fields for L1P Cache Configuration registers             */
/**********************************************************************/
#define    C64X_L1PCFG_MODE             0
#define    C64X_L1PCFG_MODE_SZ          3

/***********************************************************************/
/* Define bit fields for L1D Cache Configuration registers             */
/***********************************************************************/
#define    C64X_L1DCFG_MODE             0
#define    C64X_L1DCFG_MODE_SZ          3

/***********************************************************************/
/* Define bit fields for Memory Attribute    registers                 */
/***********************************************************************/
#define    C64X_MAR_CE                   0
#define    C64X_MAR_CE_SZ                1

/***********************************************************************/
/* Define bit fields for L2 Clean   register                           */
/***********************************************************************/
#define    C64X_L2CLEAN_C                0
#define    C64X_L2CLEAN_C_SZ             1 

/*********************************************************************/
/* REGISTER CONFIGURATION  BIT and BITFIELD values                   */
/*********************************************************************/
/* L2 Clean Register */
#define    CLEAN_ON         1
#define    CLEAN_OFF        0

/* MAR Register */
#define    CACHE_ENABLE      1
#define    CACHE_DISABLE     0

/********* Macro Definitions **************************************/
#define L2CLEAN_SET()         (SET_BIT(C64X_L2WBCLEAN_ADDR,C64X_L2CLEAN_C)) 
#define L2CLEAN_GET()         (GET_BIT(C64X_L2WBCLEAN_ADDR,C64X_L2CLEAN_C))  

#define CCFG_L2MODE_SET(l2mode) \
        LOAD_FIELD(C64X_CCFG_ADDR,l2mode,C64X_CCFG_L2MODE,C64X_CCFG_L2MODE_SZ)
#define CCFG_L2MODE_GET()       \
        (GET_FIELD (C64X_CCFG_ADDR,C64X_CCFG_L2MODE,C64X_CCFG_L2MODE_SZ))

#define L1DCFG_MODE_SET(mode) \
        LOAD_FIELD(C64X_L1DCFG_ADDR,mode,C64X_L1DCFG_MODE,C64X_L1DCFG_MODE_SZ)
#define L1DCFG_MODE_GET()     \
        (GET_FIELD (C64X_L1DCFG_ADDR,C64X_L1DCFG_MODE,C64X_L1DCFG_MODE_SZ))

#define L1PCFG_MODE_SET(mode) \
        LOAD_FIELD(C64X_L1PCFG_ADDR,mode,C64X_L1PCFG_MODE,C64X_L1PCFG_MODE_SZ)
#define L1PCFG_MODE_GET()     \
        (GET_FIELD (C64X_L1PCFG_ADDR,C64X_L1PCFG_MODE,C64X_L1PCFG_MODE_SZ))


#define C64X_EMIFB_CE0_1_ENABLE() (SET_BIT(C64X_EMIFB_CE0_1_ADDR,C64X_MAR_CE))
#define C64X_EMIFA_CE0_1_ENABLE() (SET_BIT(C64X_EMIFA_CE0_1_ADDR,C64X_MAR_CE))

#define CACHE_ROUND_TO_LINESIZE(CACHE,ELCNT,ELSIZE)          \
        ((CACHE_##CACHE##_LINESIZE *                           \
          ((ELCNT)*(ELSIZE)/CACHE_##CACHE##_LINESIZE) + 1) /   \
           (ELSIZE))

#define CACHE_ALIGN_L2_INVALIDATE_BASEADDR(ADDR)             \
        ((ADDR) & 0xFFFFFF80) 

#define HAL_L1P_CACHE_0K               0x0
#define HAL_L1P_CACHE_4K               0x1 
#define HAL_L1P_CACHE_8K               0x2
#define HAL_L1P_CACHE_16K              0x3
#define HAL_L1P_CACHE_32K              0x4

#define HAL_L1D_CACHE_0K               0x0
#define HAL_L1D_CACHE_4K               0x1 
#define HAL_L1D_CACHE_8K               0x2
#define HAL_L1D_CACHE_16K              0x3
#define HAL_L1D_CACHE_32K              0x4

#define HAL_L2_CACHE_0K                0x0
#define HAL_L2_CACHE_32K               0x1 
#define HAL_L2_CACHE_64K               0x2
#define HAL_L2_CACHE_128K              0x3
#define HAL_L2_CACHE_256K              0x7

/*******************************************/
#define   C64X_L2WBCLEAN_ADDR   0x01845004  /* L2 clean register              */
#define   C64X_L2WBCLEAN        (*(volatile unsigned int *)C64X_L2WBCLEAN_ADDR)
#define   C64X_L1DWBCLEAN_ADDR   0x01845044  
                                    /* L1D WRITEBACK Invalidate clean register */
#define   C64X_L1DWBCLEAN        (*(volatile unsigned int *)C64X_L1DWBCLEAN_ADDR)
/*******************************************/
#define CCFG_L2MODE_SET(l2mode) \
        LOAD_FIELD(C64X_CCFG_ADDR,l2mode,C64X_CCFG_L2MODE,C64X_CCFG_L2MODE_SZ)
#define CCFG_L2MODE_GET()      \
        (GET_FIELD (C64X_CCFG_ADDR,C64X_CCFG_L2MODE,C64X_CCFG_L2MODE_SZ))
#define L1DCFG_MODE_SET(mode) \
        LOAD_FIELD(C64X_L1DCFG_ADDR,mode,C64X_L1DCFG_MODE,C64X_L1DCFG_MODE_SZ)
#define L1DCFG_MODE_GET()    \
        (GET_FIELD (C64X_L1DCFG_ADDR,C64X_L1DCFG_MODE,C64X_L1DCFG_MODE_SZ))
#define L1PCFG_MODE_SET(mode) \
        LOAD_FIELD(C64X_L1PCFG_ADDR,mode,C64X_L1PCFG_MODE,C64X_L1PCFG_MODE_SZ)
#define L1PCFG_MODE_GET()     \
        (GET_FIELD (C64X_L1PCFG_ADDR,C64X_L1PCFG_MODE,C64X_L1PCFG_MODE_SZ))
#define L2CLEAN_SET()         (SET_BIT(C64X_L2WBCLEAN_ADDR,C64X_L2CLEAN_C))

#define DEVICE_UMC_MAR_BASE     0x1848000
#define CSL_UMC_MAR_WRITE(x, v) \
          *((volatile unsigned int *)(DEVICE_UMC_MAR_BASE + ((x)*4))) = (v)
/*******************************************/
#define HAL_MAR_REGS {  224, 225, 226, 227, 228, 229, 230, 231,\
                       232, 233, 234, 235, 236, 237, 238, 239, -1 \
                     }
#ifdef MCORE_SCALING_ENABLED
#define HAL_MAR_VALS {   0,   0,   0,   0,   0,   0,   0,   0,\
                         0,   0,   0,   0,   0,   0,   0,   0,  0 \
                     }
#else
#define HAL_MAR_VALS {   1,   1,   1,   1,   1,   1,   1,   1, \
                         1,   0,   0,   0,   0,   0,   0,   0,  0  \
                     }
#endif
/*******************************************/
void halCacheConfig(int l1pmode, int l1dmode, int l2mode)
{
short mregs[] = HAL_MAR_REGS;
short mvals[] = HAL_MAR_VALS;
short i;

      /* if the cache size in incresed,              */
      /*   DMA/copy any needed data from affected range*/
      /* write the desired cache mode to L1DMODE field in L1DCFG */
      L1DCFG_MODE_SET(l1dmode);
      /* read back L1DCFG. thsi stalls the cpu until the         */
      /* mode change is complete                                 */
      while(L1DCFG_MODE_GET() != l1dmode); 
      /* if the cache size in incresed, DMA/copy any needed      */
      /* data from affected range                                */
      /* write the desired cache mode to L1DMODE field in L1DCFG */
      L1PCFG_MODE_SET(l1pmode);
      /* read back L1DCFG. thsi stalls the cpu until the mode    */
      /*   change is complete                                    */
      while(L1PCFG_MODE_GET() != l1pmode); 

      L2CLEAN_SET(); /* Clean L2 */
      while(L2CLEAN_GET() != CLEAN_OFF); /* Wait Till clean is completed */
      /* configure L2 cache by writing to CCFG */
      CCFG_L2MODE_SET(l2mode);
      while(CCFG_L2MODE_GET() != l2mode); /* Force CCFG modification via
                                             read from CCFG. */

      for(i = 0; mregs[i] >= 0; i++) {
         CSL_UMC_MAR_WRITE (mregs[i], mvals[i]);
	  }
}
/*******************************************/
void halCacheWbInvalidate(void)
{
  int reg;
      C64X_L1DWBCLEAN = 1;
     /* Stall while the write back occurs */
      do  {
        reg = C64X_L1DWBCLEAN;
      } while (reg & 1);

      C64X_L2WBCLEAN = 1;
     /* Stall while the write back occurs */
      do  {
        reg = C64X_L2WBCLEAN;
      } while (reg & 1);
}
/*******************************************/          
void hal_cache_writeback_invalidate (void *base, unsigned int length, int block)
{
   volatile unsigned int *L2WIBAR = (unsigned int *)0x1844010;
   volatile unsigned int *L2WIWC = (unsigned int *)0x1844014;
   unsigned int base_masked = ((unsigned int)base) & (~0x7f);
   unsigned int word_length = (length + 0x7f) >> 2;

   if(word_length >= 0x10000)
   {
     for(;;); /* Works up to 64kW/256 kbytes*/
   }

   *L2WIBAR = base_masked;
   *L2WIWC  = word_length;
   if(block)
   {
     while(*L2WIWC);
   }
}
/*******************************************/          
void hal_cache_writeback (void *base, unsigned int length, int block)
{
   volatile unsigned int *L2WBAR = (unsigned int *)0x1844000;
   volatile unsigned int *L2WWC = (unsigned int *)0x1844004;
   unsigned int base_masked = ((unsigned int)base) & (~0x7f);
   unsigned int word_length = (length + 0x7f) >> 2;

   if(word_length >= 0x10000)
   {
     for(;;); /* Works up to 64kW/256kbytes*/
   }

   *L2WBAR = base_masked;
   *L2WWC  = word_length;
   if(block)
   {
     while(*L2WWC);
   }
}
/***********************************************/
void hal_cache_invalidate (void *base, unsigned int length, int block)
{
   volatile unsigned int *L2IBAR = (unsigned int *)0x1844018;
   volatile unsigned int *L2IWC = (unsigned int *)0x184401C;
   unsigned int base_masked = ((unsigned int)base) & (~0x7f);
   unsigned int word_length = (length + 0x7f) >> 2;
   
   if(word_length >= 0x10000)
   {
     for(;;); /* Works up to 64kW*/
   }

   *L2IBAR = base_masked;
   *L2IWC  = word_length;
   if(block)
   {
     while(*L2IWC);
   }
}
/*----------------------------------------------------------------------------*/
/* C6486 specific intercore mail box register array                           */
/*----------------------------------------------------------------------------*/
static inline void IPC_mail_setbit (int bitpos, int dst_addr)
{ /* Intercore communication function: set IPC register bit */
volatile XDAS_UInt32 *ipcgr = (XDAS_UInt32 *)0x02A80540;
  ipcgr[dst_addr] = 0x00000010 << bitpos;
}
/*----------------------------------------------------------------------------*/
static inline void IPC_mail_resetbit (int bitpos, int dst_addr)
{ /* Intercore communication function: clear IPC register bit */
volatile XDAS_UInt32 *ipcar = (XDAS_UInt32 *)0x02A80580;
  ipcar[dst_addr] = 0x00000010 << bitpos;
}
/*----------------------------------------------------------------------------*/
static inline XDAS_UInt32 IPC_mail_readbit (int bitpos, int dst_addr)
{ /* Intercore communication function: read IPC register bit */
volatile XDAS_UInt32 *ipcar = (XDAS_UInt32 *)0x02A80580;
XDAS_UInt32 ipc_reg = ipcar[dst_addr];
  return (ipc_reg & (0x00000010 << bitpos) ? 1 : 0);
}
/*----------------------------------------------------------------------------*/
#endif
/*C64xreg.h - nothing past this point*/
