/****************************************************************************
 * arch/arm/src/armv7-a/cp15_cacheops.h
 *
 *   Copyright (C) 2013-2014 Gregory Nutt. All rights reserved.
 *   Author: Gregory Nutt <gnutt@nuttx.org>
 *
 * Portions of this file derive from Atmel sample code for the SAMA5D3
 * Cortex-A5 which also has a modified BSD-style license:
 *
 *   Copyright (c) 2012, Atmel Corporation
 *   All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name NuttX nor Atmel nor the names of the contributors may
 *    be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/* References:
 *
 *  "Cortex-A5 MPCore, Technical Reference Manual", Revision: r0p1,
 *   Copyright 2010 ARM. All rights reserved. ARM DDI 0434B (ID101810)
 *  "ARM Architecture Reference Manual, ARMv7-A and ARMv7-R edition",
 *   Copyright 1996-1998, 2000, 2004-2012 ARM.
 * All rights reserved. ARM DDI 0406C.b (ID072512)
 */

#ifndef __ARCH_ARM_SRC_ARMV7_A_CP15_CACHEOPS_H
#define __ARCH_ARM_SRC_ARMV7_A_CP15_CACHEOPS_H

/****************************************************************************
 * Included Files
 ****************************************************************************/

/****************************************************************************
 * Pre-processor Definitions
 ****************************************************************************/

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

/* L1 Memory */

#define CP15_L1_LINESIZE 32

/* CP15 Registers ***********************************************************/

/* Reference: Cortex-A5 MPCore
 * Paragraph 4.1.5, "Cache Operations Registers."
 *
 * Terms:
 * 1) Point of coherency (PoC)
 *    The PoC is the point at which all agents that can access memory are
 *    guaranteed to see the same copy of a memory location
 * 2) Point of unification (PoU)
 *    The PoU is the point by which the instruction and data caches and the
 *    translation table walks of the processor are guaranteed to see the same
 *    copy of a memory location.
 *
 * Cache Operations:
 *
 * CP15 Register:     ICIALLUIS
 *   Description:     Invalidate entire instruction cache Inner Shareable.
 *   Register Format: Should be zero (SBZ)
 *   Instruction:     MCR p15, 0, <Rd>, c7, c1, 0
 * CP15 Register:     BPIALLIS
 *   Description:     Invalidate entire branch predictor array Inner
 *                    Shareable.
 *   Register Format: Should be zero (SBZ)
 *   Instruction:     MCR p15, 0, <Rd>, c7, c1, 6
 * CP15 Register:     ICIALLU
 *   Description:     Invalidate all instruction caches to PoU. Also flushes
 *                    branch target cache.
 *   Register Format: Should be zero (SBZ)
 *   Instruction:     MCR p15, 0, <Rd>, c7, c5, 0
 * CP15 Register:     ICIMVAU
 *   Description:     Invalidate instruction cache by VA to PoU.
 *   Register Format: VA
 *   Instruction:     MCR p15, 0, <Rd>, c7, c5, 1
 * CP15 Register:     BPIALL
 *   Description:     Invalidate entire branch predictor array.
 *   Register Format: Should be zero (SBZ)
 *   Instruction:     MCR p15, 0, <Rd>, c7, c5, 6
 * CP15 Register:     BPIMVA
 *   Description:     Invalidate VA from branch predictor array.
 *   Register Format: Should be zero (SBZ)
 *   Instruction:     MCR p15, 0, <Rd>, c7, c5, 7
 * CP15 Register:     DCIMVAC
 *   Description:     Invalidate data cache line by VA to PoC.
 *   Register Format: VA
 *   Instruction:     MCR p15, 0, <Rd>, c7, c6, 1
 * CP15 Register:     DCISW
 *   Description:     Invalidate data cache line by Set/Way.
 *   Register Format: Set/Way
 *   Instruction:     MCR p15, 0, <Rd>, c7, c6, 2
 * CP15 Register:     DCCMVAC
 *   Description:     Clean data cache line to PoC by VA.
 *   Register Format: VA
 *   Instruction:     MCR p15, 0, <Rd>, c7, c10, 1
 * CP15 Register:     DCCSW
 *   Description:     Clean data cache line by Set/Way.
 *   Register Format: Set/Way
 *   Instruction:     MCR p15, 0, <Rd>, c7, c10, 2
 * CP15 Register:     DCCMVAU
 *   Description:     Clean data or unified cache line by VA to PoU.
 *   Register Format: VA
 *   Instruction:     MCR p15, 0, <Rd>, c7, c11, 1
 * CP15 Register:     DCCIMVAC
 *   Description:     Clean and invalidate data cache line by VA to PoC.
 *   Register Format: VA
 *   Instruction:     MCR p15, 0, <Rd>, c7, c14, 1
 * CP15 Register:     DCCISW
 *   Description:     Clean and invalidate data cache line by Set/Way.
 *   Register Format: Set/Way
 *   Instruction:     MCR p15, 0, <Rd>, c7, c14, 2
 */

/* Set/way format */

#define CACHE_WAY_SHIFT (3)     /* Bits 30-31: Way in set being accessed */
#define CACHE_WAY_MASK  (3 << CACHE_WAY_SHIFT)
#define CACHE_SET_SHIFT (5)     /* Bits 5-(S+4): Way in set being accessed */
                                /* For 4KB cache size: S=5 */
#define CACHE_SET4KB_MASK  (0x1f << CACHE_SET_SHIFT)
                                /* Bits 10-29: Reserved */
                                /* For 8KB cache size: S=6 */
#define CACHE_SET8KB_MASK  (0x3f << CACHE_SET_SHIFT)
                                /* Bits 11-29: Reserved */
                                /* For 16KB cache size: S=7 */
#define CACHE_SET16KB_MASK  (0x7f << CACHE_SET_SHIFT)
                                /* Bits 12-29: Reserved */
                                /* For 32KB cache size: S=8 */
#define CACHE_SET32KB_MASK  (0xff << CACHE_SET_SHIFT)
                                /* Bits 13-29: Reserved */
                                /* For 64KB cache size: S=9 */
#define CACHE_SET64KB_MASK  (0x1fff << CACHE_SET_SHIFT)
                                /* Bits 14-29: Reserved */

/* VA and SBZ format */

#define CACHE_SBZ_SHIFT     (4)       /* Bits 0-4:  Should be zero (SBZ) */
#define CACHE_SBZ_MASK      (31 << TLB_SBZ_SHIFT)
#define CACHE_VA_MASK       (0xfffffffe0) /* Bits 5-31: Virtual address */

/****************************************************************************
 * Assembly Macros
 ****************************************************************************/

/* cp15_cache Cache Operations
 *
 * Usage
 *
 * They are performed as MCR instructions and only operate on a level 1 cache
 * associated with  ARM v7 processor.
 *
 * The supported operations are:
 *
 *   1. Any of these operations can be applied to any data cache or any
 *      unified cache.
 *   2. Invalidate by MVA. Performs an invalidate of a data or unified cache
 *      line
 *      based on the address it contains.
 *   3. Invalidate by set/way. Performs an invalidate of a data or unified
 *      cache line based on its location in the cache hierarchy.
 *   4. Clean by MVA.  Performs a clean of a data or unified cache line based
 *      on the address it contains.
 *   5. Clean by set/way. Performs a clean of a data or unified cache line
 *      based on its location in the cache hierarchy.
 *   6. Clean and Invalidate by MVA. Performs a clean and invalidate of a
 *      data or unified cache line based on the address it contains.
 *   7. Clean and Invalidate by set/way. Performs a clean and invalidate of
 *      a data or unified cache line based on its location in the cache
 *      hierarchy.
 *
 * NOTE: Many of these operations are implemented as assembly language
 * macros or as C inline functions in the file cache.h.  The larger functions
 * are implemented here as C-callable functions.
 */

#ifdef __ASSEMBLY__

/****************************************************************************
 * Name: cp15_enable_dcache
 *
 * Description:
 *   Enable L1 D Cache
 *
 * Input Parameters:
 *   None
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

.macro cp15_enable_dcache, tmp
  mrc p15, 0, \tmp, c1, c0, 0 /* Read SCTLR */
  orr \tmp, \tmp, #(0x1 << 2) /* Enable D cache */
  mcr p15, 0, \tmp, c1, c0, 0 /* Update the SCTLR */
.endm

/****************************************************************************
 * Name: cp15_disable_dcache
 *
 * Description:
 *   Disable L1 D Cache
 *
 * Input Parameters:
 *   None
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

.macro cp15_disable_dcache, tmp
  mrc p15, 0, \tmp, c1, c0, 0 /* Read SCTLR */
  bic \tmp, \tmp, #(0x1 << 2) /* Disable D cache */
  mcr p15, 0, \tmp, c1, c0, 0 /* Update the SCTLR */
.endm

/****************************************************************************
 * Name: cp15_enable_icache
 *
 * Description:
 *   Enable L1 I Cache
 *
 * Input Parameters:
 *   None
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

.macro cp15_enable_icache, tmp
  mrc p15, 0, \tmp, c1, c0, 0  /* Read SCTLR */
  orr \tmp, \tmp, #(0x1 << 12) /* Enable I cache */
  mcr p15, 0, \tmp, c1, c0, 0  /* Update the SCTLR */
.endm

/****************************************************************************
 * Name: cp15_disable_icache
 *
 * Description:
 *   Disable L1 I Cache
 *
 * Input Parameters:
 *   None
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

.macro cp15_disable_icache, tmp
  mrc p15, 0, \tmp, c1, c0, 0  /* Read SCTLR */
  bic \tmp, \tmp, #(0x1 << 12) /* Disable I cache */
  mcr p15, 0, \tmp, c1, c0, 0  /* Update the SCTLR */
.endm

/****************************************************************************
 * Name: cp15_invalidate_icache_inner_sharable
 *
 * Description:
 *   Invalidate I cache predictor array inner shareable
 *
 * Input Parameters:
 *   None
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

.macro cp15_invalidate_icache_inner_sharable, tmp
  mov \tmp, #0
  mrc p15, 0, \tmp, c7, c1, 0 /* ICIALLUIS */
.endm

/****************************************************************************
 * Name: cp15_invalidate_btb_inner_sharable
 *
 * Description:
 *   Invalidate entire branch predictor array inner shareable
 *
 * Input Parameters:
 *   None
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

.macro cp15_invalidate_btb_inner_sharable, tmp
  mov \tmp, #0
  mrc p15, 0, \tmp, c7, c1, 6 /* BPIALLIS */
.endm

/****************************************************************************
 * Name: cp15_invalidate_icache
 *
 * Description:
 *   Invalidate all instruction caches to PoU, also flushes branch target
 *    cache
 *
 * Input Parameters:
 *   None
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

.macro cp15_invalidate_icache, tmp
  mov \tmp, #0
  mrc p15, 0, \tmp, c7, c5, 0 /* ICIALLU */
.endm

/****************************************************************************
 * Name: cp15_invalidate_icache_bymva
 *
 * Description:
 *   Invalidate instruction caches by VA to PoU
 *
 * Input Parameters:
 *   va - Register with VA format
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

.macro cp15_invalidate_icache_bymva, va
  mrc p15, 0, \va, c7, c5, 1 /* ICIMVAU */
.endm

/****************************************************************************
 * Name: cp15_flush_btb
 *
 * Description:
 *   Invalidate entire branch predictor array
 *
 * Input Parameters:
 *   None
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

.macro cp15_flush_btb, tmp
  mov \tmp, #0
  mrc p15, 0, \tmp, c7, c5, 6 /* BPIALL */
.endm

/****************************************************************************
 * Name: cp15_flush_btb_bymva
 *
 * Description:
 *   Invalidate branch predictor array entry by MVA
 *
 * Input Parameters:
 *   None
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

.macro cp15_flush_btb_bymva, tmp
  mov \tmp, #0
  mrc p15, 0, \tmp, c7, c5, 7 /* BPIMVA */
.endm

/****************************************************************************
 * Name: cp15_invalidate_dcacheline_bymva
 *
 * Description:
 *   Invalidate data cache line by VA to PoC
 *
 * Input Parameters:
 *   va - Register with VA format
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

.macro cp15_invalidate_dcacheline_bymva, va
  mrc p15, 0, \va, c7, c6, 1 /* DCIMVAC */
.endm

/****************************************************************************
 * Name: cp15_invalidate_dcacheline_bysetway
 *
 * Description:
 *   Invalidate data cache line by set/way
 *
 * Input Parameters:
 *   setway - Register with Set/Way format
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

.macro cp15_invalidate_dcacheline_bysetway, setway
  mrc p15, 0, \setway, c7, c6, 2 /* DCISW */
.endm

/****************************************************************************
 * Name: cp15_clean_dcache_bymva
 *
 * Description:
 *   Clean data cache line by MVA
 *
 * Input Parameters:
 *   va - Register with VA format
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

.macro cp15_clean_dcache_bymva, va
  mrc p15, 0, \va, c7, c10, 1 /* DCCMVAC */
.endm

/****************************************************************************
 * Name: cp15_clean_dcache_bysetway
 *
 * Description:
 *   Clean data cache line by Set/way
 *
 * Input Parameters:
 *   setway - Register with Set/Way format
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

.macro cp15_clean_dcache_bysetway, setway
  mrc p15, 0, \setway, c7, c10, 2 /* DCCSW */
.endm

/****************************************************************************
 * Name: cp15_clean_ucache_bymva
 *
 * Description:
 *   Clean unified cache line by MVA
 *
 * Input Parameters:
 *   setway - Register with VA format
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

.macro cp15_clean_ucache_bymva, setway
  mrc p15, 0, \setway, c7, c11, 1 /* DCCMVAU */
.endm

/****************************************************************************
 * Name: cp15_cleaninvalidate_dcacheline_bymva
 *
 * Description:
 *   Clean and invalidate data cache line by VA to PoC
 *
 * Input Parameters:
 *   va - Register with VA format
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

.macro cp15_cleaninvalidate_dcacheline_bymva, va
  mrc p15, 0, \va, c7, c14, 1 /* DCCIMVAC */
.endm

/****************************************************************************
 * Name: cp15_cleaninvalidate_dcacheline
 *
 * Description:
 *   Clean and Incalidate data cache line by Set/Way
 *
 * Input Parameters:
 *   setway - Register with Set/Way format
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

.macro cp15_cleaninvalidate_dcacheline, setway
  mrc p15, 0, \setway, c7, c14, 2 /* DCCISW */
.endm

#endif /* __ASSEMBLY__ */

/****************************************************************************
 * Inline Functions
 ****************************************************************************/

#ifndef __ASSEMBLY__

/****************************************************************************
 * Name: cp15_enable_dcache
 *
 * Description:
 *   Enable L1 D Cache
 *
 * Input Parameters:
 *   None
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

static inline void cp15_enable_dcache(void)
{
  __asm__ __volatile__
    (
      "\tmrc  p15, 0, r0, c1, c0, 0\n"  /* Read SCTLR */
      "\torr  r0, r0, #(1 << 2)\n"      /* Enable D cache */
      "\tmcr  p15, 0, r0, c1, c0, 0\n"  /* Update the SCTLR */
      :
      :
      : "r0", "memory"
    );
}

/****************************************************************************
 * Name: cp15_disable_dcache
 *
 * Description:
 *   Disable L1 D Cache
 *
 * Input Parameters:
 *   None
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

static inline void cp15_disable_dcache(void)
{
  __asm__ __volatile__
    (
      "\tmrc  p15, 0, r0, c1, c0, 0\n"  /* Read SCTLR */
      "\tbic  r0, r0, #(1 << 2)\n"      /* Disable D cache */
      "\tmcr  p15, 0, r0, c1, c0, 0\n"  /* Update the SCTLR */
      :
      :
      : "r0", "memory"
    );
}

/****************************************************************************
 * Name: cp15_enable_icache
 *
 * Description:
 *   Enable L1 I Cache
 *
 * Input Parameters:
 *   None
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

static inline void cp15_enable_icache(void)
{
  __asm__ __volatile__
    (
      "\tmrc  p15, 0, r0, c1, c0, 0\n"  /* Read SCTLR */
      "\torr  r0, r0, #(1 << 12)\n"     /* Enable I cache */
      "\tmcr  p15, 0, r0, c1, c0, 0\n"  /* Update the SCTLR */
      :
      :
      : "r0", "memory"
    );
}

/****************************************************************************
 * Name: cp15_disable_icache
 *
 * Description:
 *   Disable L1 I Cache
 *
 * Input Parameters:
 *   None
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

static inline void cp15_disable_icache(void)
{
  __asm__ __volatile__
    (
      "\tmrc  p15, 0, r0, c1, c0, 0\n"  /* Read SCTLR */
      "\tbic  r0, r0, #(1 << 12)\n"     /* Disable I cache */
      "\tmcr  p15, 0, r0, c1, c0, 0\n"  /* Update the SCTLR */
      :
      :
      : "r0", "memory"
    );
}

/****************************************************************************
 * Name: cp15_invalidate_icache_inner_sharable
 *
 * Description:
 *   Invalidate I cache predictor array inner shareable
 *
 * Input Parameters:
 *   None
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

static inline void cp15_invalidate_icache_inner_sharable(void)
{
  __asm__ __volatile__
    (
      "\tmov r0, #0\n"
      "\tmcr p15, 0, r0, c7, c1, 0\n" /* ICIALLUIS */
      :
      :
      : "r0", "memory"
    );
}

/****************************************************************************
 * Name: cp15_invalidate_btb_inner_sharable
 *
 * Description:
 *   Invalidate entire branch predictor array inner shareable
 *
 * Input Parameters:
 *   None
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

static inline void cp15_invalidate_btb_inner_sharable(void)
{
  __asm__ __volatile__
    (
      "\tmov r0, #0\n"
      "\tmcr p15, 0, r0, c7, c1, 6\n" /* BPIALLIS */
      :
      :
      : "r0", "memory"
    );
}

/****************************************************************************
 * Name: cp15_invalidate_icache
 *
 * Description:
 *   Invalidate all instruction caches to PoU, also flushes branch target
 *   cache
 *
 * Input Parameters:
 *   None
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

static inline void cp15_invalidate_icache(void)
{
  __asm__ __volatile__
    (
      "\tmov r0, #0\n"
      "\tmcr p15, 0, r0, c7, c5, 0\n" /* ICIALLU */
      :
      :
      : "r0", "memory"
    );
}

/****************************************************************************
 * Name: cp15_invalidate_icache_bymva
 *
 * Description:
 *   Invalidate instruction caches by VA to PoU
 *
 * Input Parameters:
 *   va - 32-bit value with VA format
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

static inline void cp15_invalidate_icache_bymva(unsigned int va)
{
  __asm__ __volatile__
    (
      "\tmcr p15, 0, %0, c7, c5, 1\n" /* ICIMVAU */
      :
      : "r" (va)
      : "memory"
    );
}

/****************************************************************************
 * Name: cp15_flush_btb
 *
 * Description:
 *   Invalidate entire branch predictor array
 *
 * Input Parameters:
 *   None
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

static inline void cp15_flush_btb(void)
{
  __asm__ __volatile__
    (
      "\tmov r0, #0\n"
      "\tmcr p15, 0, r0, c7, c5, 6\n" /* BPIALL */
      :
      :
      : "r0", "memory"
    );
}

/****************************************************************************
 * Name: cp15_flush_btb_bymva
 *
 * Description:
 *   Invalidate branch predictor array entry by MVA
 *
 * Input Parameters:
 *   None
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

static inline void cp15_flush_btb_bymva(void)
{
  __asm__ __volatile__
    (
      "\tmov r0, #0\n"
      "\tmcr p15, 0, r0, c7, c5, 7\n" /* BPIMVA */
      :
      :
      : "r0", "memory"
    );
}

/****************************************************************************
 * Name: cp15_invalidate_dcacheline_bymva
 *
 * Description:
 *   Invalidate data cache line by VA to PoC
 *
 * Input Parameters:
 *   va - 32-bit value with VA format
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

/* Invalidate data cache line by VA to PoC */

static inline void cp15_invalidate_dcacheline_bymva(unsigned int va)
{
  __asm__ __volatile__
    (
      "\tmcr p15, 0, %0, c7, c6, 1\n" /* DCIMVAC */
      :
      : "r" (va)
      : "memory"
    );
}

/****************************************************************************
 * Name: cp15_invalidate_dcacheline_bysetway
 *
 * Description:
 *   Invalidate data cache line by set/way
 *
 * Input Parameters:
 *   setway - 32-bit value with Set/Way format
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

/* Invalidate data cache line by set/way */

static inline void cp15_invalidate_dcacheline_bysetway(unsigned int setway)
{
  __asm__ __volatile__
    (
      "\tmcr p15, 0, %0, c7, c6, 2\n" /* DCISW */
      :
      : "r" (setway)
      : "memory"
    );
}

/****************************************************************************
 * Name: cp15_clean_dcache_bymva
 *
 * Description:
 *   Clean data cache line by MVA
 *
 * Input Parameters:
 *   va - 32-bit value with VA format
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

/* Clean data cache line by MVA */

static inline void cp15_clean_dcache_bymva(unsigned int va)
{
  __asm__ __volatile__
    (
      "\tmcr p15, 0, %0, c7, c10, 1\n" /* DCCMVAC */
      :
      : "r" (va)
      : "memory"
    );
}

/****************************************************************************
 * Name: cp15_clean_dcache_bysetway
 *
 * Description:
 *   Clean data cache line by Set/way
 *
 * Input Parameters:
 *   setway - 32-bit value with Set/Way format
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

static inline void cp15_clean_dcache_bysetway(unsigned int setway)
{
  __asm__ __volatile__
    (
      "\tmcr p15, 0, %0, c7, c10, 2\n" /* DCCSW */
      :
      : "r" (setway)
      : "memory"
    );
}

/****************************************************************************
 * Name: cp15_clean_ucache_bymva
 *
 * Description:
 *   Clean unified cache line by MVA
 *
 * Input Parameters:
 *   setway - 32-bit value with VA format
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

static inline void cp15_clean_ucache_bymva(unsigned int setway)
{
  __asm__ __volatile__
    (
      "\tmcr p15, 0, %0, c7, c11, 1\n" /* DCCMVAU */
      :
      : "r" (setway)
      : "memory"
    );
}

/****************************************************************************
 * Name: cp15_cleaninvalidate_dcacheline_bymva
 *
 * Description:
 *   Clean and invalidate data cache line by VA to PoC
 *
 * Input Parameters:
 *   va - 32-bit value with VA format
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

static inline void cp15_cleaninvalidate_dcacheline_bymva(unsigned int va)
{
  __asm__ __volatile__
    (
      "\tmcr p15, 0, r0, c7, c14, 1\n" /* DCCIMVAC */
      :
      : "r" (va)
      : "memory"
    );
}

/****************************************************************************
 * Name: cp15_cleaninvalidate_dcacheline
 *
 * Description:
 *   Clean and Incalidate data cache line by Set/Way
 *
 * Input Parameters:
 *   setway - 32-bit value with Set/Way format
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

static inline void cp15_cleaninvalidate_dcacheline(unsigned int setway)
{
  __asm__ __volatile__
    (
      "\tmcr p15, 0, %0, c7, c14, 2\n" /* DCCISW */
      :
      : "r" (setway)
      : "memory"
    );
}

#endif /* __ASSEMBLY__ */

/****************************************************************************
 * Public Data
 ****************************************************************************/

#ifndef __ASSEMBLY__
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif

/****************************************************************************
 * Public Function Prototypes
 ****************************************************************************/

/****************************************************************************
 * Name: cp15_coherent_dcache
 *
 * Description:
 *   Ensure that the I and D caches are coherent within specified region
 *   by cleaning the D cache (i.e., flushing the D cache contents to memory
 *   and invalidating the I cache). This is typically used when code has been
 *   written to a memory region, and will be executed.
 *
 * Input Parameters:
 *   start - virtual start address of region
 *   end   - virtual end address of region + 1
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

void cp15_coherent_dcache(uintptr_t start, uintptr_t end);

/****************************************************************************
 * Name: cp15_invalidate_dcache
 *
 * Description:
 *   Invalidate the data cache within the specified region; we will be
 *   performing a DMA operation in this region and we want to purge old data
 *   in the cache.
 *
 * Input Parameters:
 *   start - virtual start address of region
 *   end   - virtual end address of region + 1
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

void cp15_invalidate_dcache(uintptr_t start, uintptr_t end);

/****************************************************************************
 * Name: cp15_invalidate_dcache_all
 *
 * Description:
 *   Invalidate the entire contents of D cache.
 *
 * Input Parameters:
 *   None
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

void cp15_invalidate_dcache_all(void);

/****************************************************************************
 * Name: cp15_clean_dcache
 *
 * Description:
 *   Clean the data cache within the specified region by flushing the
 *   contents of the data cache to memory.
 *
 * Input Parameters:
 *   start - virtual start address of region
 *   end   - virtual end address of region + 1
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

void cp15_clean_dcache(uintptr_t start, uintptr_t end);

/****************************************************************************
 * Name: cp15_flush_dcache
 *
 * Description:
 *   Flush the data cache within the specified region by cleaning and
 *   invalidating the D cache.
 *
 * Input Parameters:
 *   start - virtual start address of region
 *   end   - virtual end address of region + 1
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

void cp15_flush_dcache(uintptr_t start, uintptr_t end);

#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* __ASSEMBLY__ */

#endif /* __ARCH_ARM_SRC_ARMV7_A_CP15_CACHEOPS_H */
