/*******************************************************************************
 * Copyright (c) 2018-2021 Renesas Electronics Corporation. All rights reserved.
 *
 *     RENESAS ELECTRONICS CONFIDENTIAL AND PROPRIETARY
 *
 * This software is provided as reference/sample code under the license
 * agreement between Renesas Electronics Corporation and licensee (the
 * "License Agreement") and shall be treated as specified in the License
 * Agreement.
 * These instructions, statements, and software are the confidential
 * information of Renesas Electronics Corporation. They must be used and
 * modified solely for the purpose for which it was furnished by Renesas
 * Electronics Corporation. All or part of these instructions, statements and
 * software must not be reproduced nor disclosed to any third party in any
 * form, unless permitted by the License Agreement.
 *
 * THIS SOFTWARE IS PROVIDED BY RENESAS ELEOCTRONICS CORPORATION "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
 * SATISFACTORY QUALITY, ACCURACY, TITLE AND NON-INFRINGEMENT ARE DISCLAIMED.
 * IN NO EVENT SHALL RENESAS ELECTRONICS CORPORATION BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, PUNITIVE, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * 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.
 ******************************************************************************/

/*******************************************************************************
 * DESCRIPTION   : DMA driver
 ******************************************************************************/
/******************************************************************************
 * @file          dma.c
 * - Version      : 0.01
 * @brief         DMA driver.
 * .
 *****************************************************************************/
/******************************************************************************
 * History : DD.MM.YYYY Version  Description
 *         : 03.07.2020 0.01     First Release
 *****************************************************************************/

#include <stdint.h>
#include <mem_io.h>
#include <cpg_register.h>
#include <dma_register.h>
#include <dma.h>
#include <rpc.h>
#include <scif.h>
#include <log.h>
#include <remap_register.h>
#include <wdt.h>


#define RDMOR_INIT              (uint16_t)(0x0301U)
#define RDMOR_HW_INIT           (uint16_t)(0x0000U)
#define RDMTCR_CNT_SHIFT        (6U)
#define RDMCHCR_TRN_MODE        (0x00105409U)
#define RDMCHCR_TE_BIT          (0x00000002U)
#define TE_FLAG                 (0x00000000U)
#define RDMCHCR_CAE_BIT         (0x80000000U)
#define RDMCHCR_CAE_BIT_NOERROR (0x00000000U)

/* fraction mask for 64-byte units */
#define FRACTION_MASK_64_BYTE   (0x0000003FU)
/* fraction mask for 256-byte units */
#define FRACTION_MASK_256_BYTE  (0x000000FFU)

void dma_init(void)
{
    uint32_t reg;

    /* DMA channel clear */
    mem_write32(DMA_RDMCHCLR, ((uint32_t)1U << DMACH));

    /* DMA operation */
    mem_write16(DMA_RDMOR, RDMOR_INIT);
    /* DMA secure control register */
    reg = mem_read32(DMA_RDMSEC);
    reg |= ((uint32_t)1U << DMACH);
    mem_write32(DMA_RDMSEC, reg);
}
/* End of function dma_init(void) */

void load_start(uint32_t dst, uint32_t src, uint32_t len)
{
    if (((dst & FRACTION_MASK_64_BYTE) != 0U) || ((src & FRACTION_MASK_64_BYTE) != 0U))
    {
        /* dst or src are not 64-bit alignment. */
        ERROR("not 64-bit alignment in DMA transfer\n");
        panic;
    }

    /* round up 256 byte alignment */
    len += FRACTION_MASK_256_BYTE;
    len &= (~(uint32_t)(FRACTION_MASK_256_BYTE));

    /* DMA destination address */
    mem_write32(DMA_RDMDAR(DMACH), dst);
    /* DMA source address */
    mem_write32(DMA_RDMSAR(DMACH), src);
    /* DMA 64bytes-unit transfer  count */
    mem_write32(DMA_RDMTCR(DMACH), (len >> RDMTCR_CNT_SHIFT));
    /* DMA channel control */
    mem_write32(DMA_RDMCHCR(DMACH), RDMCHCR_TRN_MODE);
}
/* End of function load_start(uint32_t dst, uint32_t src, uint32_t len) */

void load_end(void)
{
    /* Check end of DMA transfer. */
    do
    {
        /* Reset the timer count of the Window Watchdog Timer.  */
        wdt_restart();

        /* Check error of DMA transfer */
        if ((mem_read32(DMA_RDMCHCR(DMACH)) & RDMCHCR_CAE_BIT) != RDMCHCR_CAE_BIT_NOERROR)
        {
            ERROR("DMA - Channel Address Error\n");
            panic;
        }
    } while ((mem_read32(DMA_RDMCHCR(DMACH)) & RDMCHCR_TE_BIT) == TE_FLAG);

    /* DMA channel clear */
    mem_write32(DMA_RDMCHCLR, ((uint32_t)1U << DMACH));

    rpc_end_state_check();
}
/* End of function load_end(void) */

void dma_release(void)
{
    uint32_t reg;

    /* DMA channel clear */
    mem_write32(DMA_RDMCHCLR, ((uint32_t)1U << DMACH));
    reg = mem_read32(DMA_RDMSEC);
    reg &= (~((uint32_t)1U << DMACH));
    mem_write32(DMA_RDMSEC, reg);
}
/* End of function dma_release(void) */
