/*******************************************************************************
 * Copyright (c) 2018 Renesas Electronics Corporation. All rights reserved.
 *
 * DESCRIPTION   : Time wait driver
 ******************************************************************************/

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

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

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

#define	OSTM0_BASE	(0xFFFEE000UL)
#define	OSTM0CMP	(*(volatile uint32_t*)(OSTM0_BASE))
#define	OSTM0CNT	(*(volatile uint32_t*)(OSTM0_BASE + 0x4UL))
#define	OSTM0TE		(*(volatile uint8_t*)(OSTM0_BASE + 0x10UL))
#define	OSTM0TS		(*(volatile uint8_t*)(OSTM0_BASE + 0x14UL))
#define	OSTM0TT		(*(volatile uint8_t*)(OSTM0_BASE + 0x18UL))
#define	OSTM0CTL	(*(volatile uint8_t*)(OSTM0_BASE + 0x20L))
#define	OSTM0EMU	(*(volatile uint32_t*)(OSTM0_BASE + 0x24L))

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

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

/************************************************************************************************/
/*	Prototypes																					*/
/************************************************************************************************/
static void start_microtimer(uint32_t val);
static void stop_microtimer(void);

static void start_microtimer(uint32_t val)
{
	OSTM0TT = OSTM0TT_TT;
	OSTM0CMP = val;
	OSTM0CTL = OSTM0CTL_MD10;
	OSTM0TS = OSTM0TS_TS;
}

static void stop_microtimer(void)
{
	OSTM0TT = OSTM0TT_TT;
}

void micro_wait(uint32_t count_us)
{
	uint32_t val;

	if (count_us == 0) {
		return;
	}
	val = count_us * OSTM0CMP_MICRO_VALUE;
	start_microtimer(val);

	while (1) {
		if (INTICUOSTM0 & INTCR_RF) {
			INTICUOSTM0 &= (uint16_t)(~INTCR_RF);
			stop_microtimer();
			break;
		}

	}
}

