/*******************************************************************************
 * 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   : Time wait driver
 ******************************************************************************/
/******************************************************************************
 * @file          micro_wait.c
 * - Version      : 0.01
 * @brief         Wait of micro second
 * .
 *****************************************************************************/
/******************************************************************************
 * History : DD.MM.YYYY Version  Description
 *         : 03.07.2020 0.01     First Release
 *****************************************************************************/

#include <stdint.h>
#include <micro_wait.h>
#include <mem_io.h>

/************************************************************************************************/
/*  Definitions                                                                                 */
/************************************************************************************************/

#define INTICUOSTM0     (0xFFFEEA14U)
#define INTCR_RF        (uint16_t)((uint16_t)1U << 12U)
#define INTCR_RF_NO_REQ (uint16_t)((uint16_t)0U << 12U)

#define OSTM0_BASE      (0xFFFEE000U)
#define OSTM0CMP        (OSTM0_BASE)
#define OSTM0CNT        (OSTM0_BASE + 0x0004U)
#define OSTM0TE         (OSTM0_BASE + 0x0010U)
#define OSTM0TS         (OSTM0_BASE + 0x0014U)
#define OSTM0TT         (OSTM0_BASE + 0x0018U)
#define OSTM0CTL        (OSTM0_BASE + 0x0020U)
#define OSTM0EMU        (OSTM0_BASE + 0x0024U)

#define OSTM0TS_TS      (uint8_t)(0x01U)    /* b0:1: Start  */
#define OSTM0TT_TT      (uint8_t)(0x01U)    /* b0:1: Stop   */
#define OSTM0TE_TE      (uint8_t)(0x01U)    /* b0:1: Counter enabled    */
#define OSTM0CMP_MICRO_VALUE    (0x00000190U)   /* PCLK=400MHz(400=0x190 = 1us) */

#define OSTM0CTL_MD10   (uint8_t)(0x02U)    /* b1:1: Free-run compare mode(Start:0 Counting Direction:up)   */
                                            /* b0:0: Interrupts when counting starts are enabled        */

#define MAX_MICRO_WAIT  (10737418U) /* 0xFFFFFFFF / 400 */

void micro_wait(uint32_t count_us)
{
    uint32_t val;
    uint16_t reg;

    if (count_us != 0U)
    {
        /* When the timer count is an argument that exceeds 0xFFFFFFFF */
        if(MAX_MICRO_WAIT < count_us)
        {
            count_us = MAX_MICRO_WAIT;
        }
        val = count_us * OSTM0CMP_MICRO_VALUE;
        /* timer start */
        mem_write8(OSTM0TT, OSTM0TT_TT);
        mem_write32(OSTM0CMP, val);
        mem_write8(OSTM0CTL, OSTM0CTL_MD10);
        mem_write8(OSTM0TS, OSTM0TS_TS);

        while (1)
        {
            reg = mem_read16(INTICUOSTM0);
            if ((reg & (INTCR_RF)) != INTCR_RF_NO_REQ)
            {
                /* timer stop */
                reg = (reg & (uint16_t)(~(INTCR_RF)));
                mem_write16(INTICUOSTM0, reg);
                mem_write8(OSTM0TT, OSTM0TT_TT);
                break;
            }
        }
    }
}
/* End of function micro_wait(uint32_t count_us) */
