
#include "imx8_drv_gpio.h"

static volatile uintptr_t gpio_base_0;
static volatile uintptr_t gpio_base_1;
static volatile uintptr_t gpio_base_2;
static volatile uintptr_t gpio_base_3;
static volatile uintptr_t gpio_base_4;
static volatile uintptr_t gpio_base_5;

static uintptr_t tbase;
static volatile unsigned int cnt;
static int val;
static pthread_t timer_thread;
static struct sigevent event;
static intrspin_t spinner;

char drv_vsr[4] = {93u, 8u, 0u, 9u};

/*GPIO init*/
int imx8_gpio_init(void)
{

	int ret = 0;
	gpio_base_0 = mmap_device_io((size_t)0x10, (uint64_t)IMX_GPIO0_BASE);
	if(gpio_base_0 == MAP_DEVICE_FAILED)
	{
		perror("Can't map device base 0 I/O");
		ret = -1;
	}
	else
	{

	}

	gpio_base_1 = mmap_device_io((size_t)0x10, (uint64_t)IMX_GPIO1_BASE);
	if(gpio_base_1 == MAP_DEVICE_FAILED)
	{
		perror("Can't map device base 1 I/O");
		ret = -1;
	}
	else
	{

	}

	gpio_base_2 = mmap_device_io((size_t)0x10, (uint64_t)IMX_GPIO2_BASE);
	if(gpio_base_2 == MAP_DEVICE_FAILED)
	{
		perror("Can't map device base 2 I/O");
		ret = -1;
	}
	else
	{

	}

	gpio_base_3 = mmap_device_io((size_t)0x10, (uint64_t)IMX_GPIO3_BASE);
	if(gpio_base_3 == MAP_DEVICE_FAILED)
	{
		perror("Can't map device base 3 I/O");
		ret = -1;
	}
	else
	{

	}

	gpio_base_4 = mmap_device_io((size_t)0x10, (uint64_t)IMX_GPIO4_BASE);
	if(gpio_base_4 == MAP_DEVICE_FAILED)
	{
		perror("Can't map device base 4 I/O");
		ret = -1;
	}
	else
	{

	}

	gpio_base_5 = mmap_device_io((size_t)0x10, (uint64_t)IMX_GPIO5_BASE);
	if(gpio_base_5 == MAP_DEVICE_FAILED)
	{
		perror("Can't map device base 5 I/O");
		ret = -1;
	}
	else
	{

	}

	/*input config*/
	out32(gpio_base_0 + IMX_GPIO_GDIR, (in32(gpio_base_0 + IMX_GPIO_GDIR) & ~(0x932000U)));
	out32(gpio_base_3 + IMX_GPIO_GDIR, (in32(gpio_base_3 + IMX_GPIO_GDIR) & ~(0x17fc0000U)));
	out32(gpio_base_4 + IMX_GPIO_GDIR, (in32(gpio_base_4 + IMX_GPIO_GDIR) & ~(0x100006U)));

	out32(gpio_base_4 + IMX_GPIO_GDIR, (in32(gpio_base_4 + IMX_GPIO_GDIR) | (1UL << 12)));
	out32(gpio_base_4 + IMX_GPIO_DR, (in32(gpio_base_4 + IMX_GPIO_DR) | (1UL << 12)));



	/*output config*/
	out32(gpio_base_0 + IMX_GPIO_GDIR, (in32(gpio_base_0 + IMX_GPIO_GDIR) | (0xcc00cc0UL)));


	printf("dirver version : %d,%d,%d,%d\n",drv_vsr[0],drv_vsr[1],drv_vsr[2],drv_vsr[3]);

	return ret;
}


/*This function for switch button*/
int imx8_switch_button(void)
{

	int ret = 0;

	out32(gpio_base_4 + IMX_GPIO_GDIR, (in32(gpio_base_4 + IMX_GPIO_GDIR) | (1UL << 22)));
	out32(gpio_base_4 + IMX_GPIO_GDIR, (in32(gpio_base_4 + IMX_GPIO_GDIR) & ~(1UL << 20)));

	out32(gpio_base_4 + IMX_GPIO_DR, (in32(gpio_base_4 + IMX_GPIO_DR) | (1UL << 22)));
	ret = (uint32_t)(in32(gpio_base_4 + IMX_GPIO_PSR) & (1UL << 20)) >> 20;

	return ret;

}

/*read boardid function*/
unsigned char imx8_read_boardID(void)
{
	unsigned char id = 0U;
	out32(gpio_base_3 + IMX_GPIO_GDIR, (uint32_t)(in32(gpio_base_3 + IMX_GPIO_GDIR) & ~((0xFFUL << 18))));

	id |= (uint8_t)(((in32(gpio_base_3 + IMX_GPIO_PSR) & (1UL << 18)) >> 18) << 7);
	id |= (uint8_t)(((in32(gpio_base_3 + IMX_GPIO_PSR) & (1UL << 19)) >> 19) << 6);
	id |= (uint8_t)(((in32(gpio_base_3 + IMX_GPIO_PSR) & (1UL << 20)) >> 20) << 5);
	id |= (uint8_t)(((in32(gpio_base_3 + IMX_GPIO_PSR) & (1UL << 21)) >> 21) << 4);

	id |= (uint8_t)(((in32(gpio_base_3 + IMX_GPIO_PSR) & (1UL << 22)) >> 22) << 3);
	id |= (uint8_t)(((in32(gpio_base_3 + IMX_GPIO_PSR) & (1UL << 23)) >> 23) << 2);
	id |= (uint8_t)(((in32(gpio_base_3 + IMX_GPIO_PSR) & (1UL << 24)) >> 24) << 1);
	id |= (uint8_t)(((in32(gpio_base_3 + IMX_GPIO_PSR) & (1UL << 25)) >> 25));

	return id;
}

/*input collect*/
int imx8_input_collect(int channel)
{
	ThreadCtl (_NTO_TCTL_IO, 0);
	int value = 0;
#if 0
	out32(gpio_base_0 + IMX_GPIO_GDIR, (in32(gpio_base_0 + IMX_GPIO_GDIR) & ~(0x932000U)));
	out32(gpio_base_3 + IMX_GPIO_GDIR, (in32(gpio_base_3 + IMX_GPIO_GDIR) & ~(0x17fc0000U)));
	out32(gpio_base_4 + IMX_GPIO_GDIR, (in32(gpio_base_4 + IMX_GPIO_GDIR) & ~(0x100006U)));

	out32(gpio_base_4 + IMX_GPIO_GDIR, (in32(gpio_base_4 + IMX_GPIO_GDIR) | (1UL << 12)));
	out32(gpio_base_4 + IMX_GPIO_DR, (in32(gpio_base_4 + IMX_GPIO_DR) | (1UL << 12)));
#endif

	InterruptLock( &spinner );

	if(1 == channel)
	{
		value = (in32(gpio_base_0 + IMX_GPIO_PSR) & (uint32_t)(1UL << 8)) >> 8;
	}
	else if(2 == channel)
	{
		value = (in32(gpio_base_0 + IMX_GPIO_PSR) & (uint32_t)(1UL << 9)) >> 9;
	}
	else if(3 == channel)
	{
		value = (in32(gpio_base_0 + IMX_GPIO_PSR) & (uint32_t)(1UL << 12)) >> 12;
	}
	else if(4 == channel)
	{
		value = (in32(gpio_base_0 + IMX_GPIO_PSR) & (uint32_t)(1UL << 13)) >> 13;
	}
	else if(5 == channel)
	{
		value = (in32(gpio_base_4 + IMX_GPIO_PSR) & (uint32_t)(1UL << 1)) >> 1;
	}
	else if(6 == channel)
	{
		value = (in32(gpio_base_4 + IMX_GPIO_PSR) & (uint32_t)(1UL << 2)) >> 2;
	}
	else if(7 == channel)
	{
		value = (in32(gpio_base_3 + IMX_GPIO_PSR) & (uint32_t)(1UL << 26)) >> 26;
	}
	else if(8 == channel)
	{
		value = (in32(gpio_base_3 + IMX_GPIO_PSR) & (uint32_t)(1UL << 28)) >> 28;
	}
	else if(9 == channel)
	{
		value = (in32(gpio_base_0 + IMX_GPIO_PSR) & (uint32_t)(1UL << 19)) >> 19;
	}
	else if(10 == channel)
	{
		value = (in32(gpio_base_0 + IMX_GPIO_PSR) & (uint32_t)(1UL << 16)) >> 16;
	}
	else
	{
		perror("input error channel start 1 to 10");
		value =  -1;
	}

	InterruptUnlock( &spinner );
	return value;
}


int imx8_output(int channel, int level)
{

//	out32(gpio_base_0 + IMX_GPIO_GDIR, (in32(gpio_base_0 + IMX_GPIO_GDIR) | (0xcc00cc0UL)));

	ThreadCtl (_NTO_TCTL_IO, 0);

	int ret = 0;

	InterruptLock( &spinner );

	switch(channel)
	{
	case 1:
		if(1 == level)
		{
			out32(gpio_base_0 + IMX_GPIO_DR, (in32(gpio_base_0 + IMX_GPIO_DR) | (1UL << 26)));
			ret = (in32(gpio_base_0 + IMX_GPIO_DR) & (1UL << 26)) >> 26;
		}
		else if(0 == level)
		{
			out32(gpio_base_0 + IMX_GPIO_DR, (in32(gpio_base_0 + IMX_GPIO_DR) & ~(1UL << 26)));
			ret = (in32(gpio_base_0 + IMX_GPIO_DR) & (1UL << 26)) >> 26;
		}
		else
		{
			perror("channel 1 input wrong para level must 1 or 0");
			ret = -1;
		}
		break;

	case 2:
		if(1 == level)
		{

			out32(gpio_base_0 + IMX_GPIO_DR, (in32(gpio_base_0 + IMX_GPIO_DR) | (1UL << 27)));
			ret = (in32(gpio_base_0 + IMX_GPIO_DR) & (1UL << 27)) >> 27;

		}
		else if(0 == level)
		{
			out32(gpio_base_0 + IMX_GPIO_DR, (in32(gpio_base_0 + IMX_GPIO_DR) & ~(1UL << 27)));
			ret = (in32(gpio_base_0 + IMX_GPIO_DR) & (1UL << 27)) >> 27;
		}
		else
		{
			perror("channel 2 input wrong para level must 1 or 0");
			ret = -1;
		}
		break;

	case 3:
		if(1 == level)
		{
			out32(gpio_base_0 + IMX_GPIO_DR, (in32(gpio_base_0 + IMX_GPIO_DR) | (1UL << 10)));
			ret = (in32(gpio_base_0 + IMX_GPIO_DR) & (1UL << 10)) >> 10;
		}
		else if(0 == level)
		{
			out32(gpio_base_0 + IMX_GPIO_DR, (in32(gpio_base_0 + IMX_GPIO_DR) & ~(1UL << 10)));
			ret = (in32(gpio_base_0 + IMX_GPIO_DR) & (1UL << 10)) >> 10;
		}
		else
		{
			perror("channel 3 input wrong para level must 1 or 0");
			ret = -1;
		}
		break;

	case 4:
		if(1 == level)
		{
			out32(gpio_base_0 + IMX_GPIO_DR, (in32(gpio_base_0 + IMX_GPIO_DR) | (1UL << 7)));
			ret = (in32(gpio_base_0 + IMX_GPIO_DR) & (1UL << 7)) >> 7;
		}
		else if(0 == level)
		{
			out32(gpio_base_0 + IMX_GPIO_DR, (in32(gpio_base_0 + IMX_GPIO_DR) & ~(1UL << 7)));
			ret = (in32(gpio_base_0 + IMX_GPIO_DR) & (1UL << 7)) >> 7;
		}
		else
		{
			perror("channel 4 input wrong para level must 1 or 0");
			ret = -1;
		}
		break;

	case 5:
		if(1 == level)
		{
			out32(gpio_base_0 + IMX_GPIO_DR, (in32(gpio_base_0 + IMX_GPIO_DR) | (1UL << 6)));
			ret = (in32(gpio_base_0 + IMX_GPIO_DR) & (1UL << 6)) >> 6;
		}
		else if(0 == level)
		{
			out32(gpio_base_0 + IMX_GPIO_DR, (in32(gpio_base_0 + IMX_GPIO_DR) & ~(1UL << 6)));
			ret = (in32(gpio_base_0 + IMX_GPIO_DR) & (1UL << 6)) >> 6;
		}
		else
		{
			perror("channel 5 input wrong para level must 1 or 0");
			ret = -1;
		}
		break;

	case 6:
		if(1 == level)
		{
			out32(gpio_base_0 + IMX_GPIO_DR, (in32(gpio_base_0 + IMX_GPIO_DR) | (1UL << 11)));
			ret = (in32(gpio_base_0 + IMX_GPIO_DR) & (1UL << 11)) >> 11;
		}
		else if(0 == level)
		{
			out32(gpio_base_0 + IMX_GPIO_DR, (in32(gpio_base_0 + IMX_GPIO_DR) & ~(1UL << 11)));
			ret = (in32(gpio_base_0 + IMX_GPIO_DR) & (1UL << 11)) >> 11;
		}
		else
		{
			perror("channel 6 input wrong para level must 1 or 0");
			ret = -1;
		}
		break;

	case 7:
		if(1 == level)
		{
			out32(gpio_base_0 + IMX_GPIO_DR, (in32(gpio_base_0 + IMX_GPIO_DR) | (1UL << 22)));
			ret = (in32(gpio_base_0 + IMX_GPIO_DR) & (1UL << 22)) >> 22;
		}
		else if(0 == level)
		{
			out32(gpio_base_0 + IMX_GPIO_DR, (in32(gpio_base_0 + IMX_GPIO_DR) & ~(1UL << 22)));
			ret = (in32(gpio_base_0 + IMX_GPIO_DR) & (1UL << 22)) >> 22;
		}
		else
		{
			perror("channel 7 input wrong para level must 1 or 0");
			ret = -1;
		}
		break;

	case 8:
		if(1 == level)
		{
			out32(gpio_base_0 + IMX_GPIO_DR, (in32(gpio_base_0 + IMX_GPIO_DR) | (1UL << 23)));
			ret = (in32(gpio_base_0 + IMX_GPIO_DR) & (1UL << 23)) >> 23;
		}
		else if(0 == level)
		{
			out32(gpio_base_0 + IMX_GPIO_DR, (in32(gpio_base_0 + IMX_GPIO_DR) & ~(1UL << 23)));
			ret = (in32(gpio_base_0 + IMX_GPIO_DR) & (1UL << 23)) >> 23;
		}
		else
		{
			perror("channel 8 input wrong para level must 1 or 0");
			ret = -1;
		}
		break;

	default:
		perror("channel must be 1 to 8\n");
		ret = -1;
		break;
	}

	InterruptUnlock( &spinner );


	return ret;
}


/*Input RED, GREEN or OFF,control by cpu1 and cpu2*/
int imx8_led_REA_REB(int light)
{

	int ret = 0;

	out32(gpio_base_5 + IMX_GPIO_GDIR, (in32(gpio_base_5 + IMX_GPIO_GDIR) | (1UL << 26) | (1UL << 27)));

	if(light == RED)
	{
		out32(gpio_base_5 + IMX_GPIO_DR, ((in32(gpio_base_5 + IMX_GPIO_DR) & ~(1UL << 26)) | (1UL << 27)));
	}
	else if(light == GREEN)
	{
		out32(gpio_base_5 + IMX_GPIO_DR, ((in32(gpio_base_5 + IMX_GPIO_DR) | (1UL << 26) )& ~(1UL << 27)));
	}
	else if(light == OFF)
	{
		out32(gpio_base_5 + IMX_GPIO_DR, (in32(gpio_base_5 + IMX_GPIO_DR) & ~(0x3UL << 26)));
	}
	else
	{
		perror("input wrong pare please input GREEN ,RED or OFF");
		ret = -1;
	}
	return ret;
}

/*Input RED, GREEN or OFF, control by cpu1*/
int imx8_led_R_E(int light)
{
	int ret = 0;
	out32(gpio_base_5 + IMX_GPIO_GDIR, (in32(gpio_base_5 + IMX_GPIO_GDIR) | (1UL << 28) | (1UL << 29)));

	if(light == GREEN)
	{
		out32(gpio_base_5 + IMX_GPIO_DR, ((in32(gpio_base_5 + IMX_GPIO_DR) & ~(1UL << 28)) | (1UL << 29)));
	}
	else if(light == RED)
	{
		out32(gpio_base_5 + IMX_GPIO_DR, ((in32(gpio_base_5 + IMX_GPIO_DR) | (1UL << 28) )& ~(1UL << 29)));
	}
	else if(light == OFF)
	{
		out32(gpio_base_5 + IMX_GPIO_DR, (in32(gpio_base_5 + IMX_GPIO_DR) & ~(0x3UL << 28)));
	}
	else
	{
		perror("input wrong pare please input GREEN , RED or OFF\n");
		ret = -1;
	}

	return ret;
}

/*Input YELLOW, GREEN or OFF,control by cpu1*/
int imx8_led_M_S(int light)
{

	int ret = 0;

	out32(gpio_base_2 + IMX_GPIO_GDIR, (in32(gpio_base_2 + IMX_GPIO_GDIR) | (1UL << 14) | (1UL << 15)));

	if(light == YELLOW)
	{
		out32(gpio_base_2 + IMX_GPIO_DR, ((in32(gpio_base_2 + IMX_GPIO_DR) & ~(1UL << 14)) | (1UL << 15)));
	}
	else if(light == GREEN)
	{
		out32(gpio_base_2 + IMX_GPIO_DR, ((in32(gpio_base_2 + IMX_GPIO_DR) | (1UL << 14) )& ~(1UL << 15)));
	}
	else if(light == OFF)
	{
		out32(gpio_base_2 + IMX_GPIO_DR, (in32(gpio_base_2 + IMX_GPIO_DR) & ~(0x3UL << 14)));
	}
	else
	{
		perror("input wrong pare please input GREEN , YELLOW or OFF\n");
		ret = -1;
	}
	return ret;
}



/*return 0 means cpu 0*/
unsigned int imx8_read_cpuid(void)
{
	out32(gpio_base_5 + IMX_GPIO_GDIR, (in32(gpio_base_5 + IMX_GPIO_GDIR) & ~(1UL << 25)));
	return (in32(gpio_base_5 + IMX_GPIO_PSR) & (uint32_t)(1UL << 25)) >> 25;
}

/*input 1 : enable, input 0 : disable*/
int imx8_dcdc_1_ctrl(int level)
{
	int ret = 0;

	out32(gpio_base_1 + IMX_GPIO_GDIR, (in32(gpio_base_1 + IMX_GPIO_GDIR) | (1UL << 10) ));

	if(0 == level)
	{
		out32(gpio_base_1 + IMX_GPIO_DR, (in32(gpio_base_1 + IMX_GPIO_DR) & ~(1UL << 10)));
	}
	else if(1 == level)
	{
		out32(gpio_base_1 + IMX_GPIO_DR, (in32(gpio_base_1 + IMX_GPIO_DR) | (1UL << 10)));
	}
	else
	{
		perror("input wrong level please input 1 or 0");
		ret = -1;
	}
	return ret;
}

/*input 1 : enable, input 0 : disable*/
int imx8_dcdc_2_ctrl(int level)
{
	int ret = 0;

	out32(gpio_base_5 + IMX_GPIO_GDIR, (in32(gpio_base_5 + IMX_GPIO_GDIR) | (1UL << 20) ));

	if(0 == level)
	{
		out32(gpio_base_5 + IMX_GPIO_DR, (in32(gpio_base_5 + IMX_GPIO_DR) & ~(1UL << 20)));
	}
	else if(1 == level)
	{
		out32(gpio_base_5 + IMX_GPIO_DR, (in32(gpio_base_5 + IMX_GPIO_DR) | (1UL << 20)));
	}
	else
	{
		perror("input wrong level please input 1 or 0");
		ret = -1;
	}
	return ret;
}


/*return 1 means normal, 0 means Overvoltage*/
unsigned int imx8_Safe_gate_overvoltage_state_1(void)
{
	out32(gpio_base_1 + IMX_GPIO_GDIR, (in32(gpio_base_1 + IMX_GPIO_GDIR) & ~(1UL << 20)));
	return (in32(gpio_base_1 + IMX_GPIO_PSR) & (uint32_t)(1UL << 20)) >> 20;
}

/*return 1 means normal, 0 means Overvoltage*/
unsigned int imx8_Safe_gate_undervoltage_state_1(void)
{
	out32(gpio_base_1 + IMX_GPIO_GDIR, (in32(gpio_base_1 + IMX_GPIO_GDIR) & ~(1UL << 6)));
	return (in32(gpio_base_1 + IMX_GPIO_PSR) & (uint32_t)(1UL << 6)) >> 6;
}

/*return 1 means normal, 0 means Overvoltage*/
unsigned int imx8_Safe_gate_overvoltage_state_2(void)
{
	out32(gpio_base_2 + IMX_GPIO_GDIR, (in32(gpio_base_2 + IMX_GPIO_GDIR) & ~(1UL << 29)));
	return (in32(gpio_base_2 + IMX_GPIO_PSR) & (uint32_t)(1UL << 29)) >> 29;
}

/*return 1 means normal, 0 means Overvoltage*/
unsigned int imx8_Safe_gate_undervoltage_state_2(void)
{
	out32(gpio_base_5 + IMX_GPIO_GDIR, (in32(gpio_base_5 + IMX_GPIO_GDIR) & ~(1UL << 19)));
	return (in32(gpio_base_5 + IMX_GPIO_PSR) & (uint32_t)(1UL << 19)) >> 19;
}


/*return 1 means on, return 0 means off*/
unsigned int imx8_ethernet_switch_state_1_1(void)
{
	out32(gpio_base_2 + IMX_GPIO_GDIR, (in32(gpio_base_2 + IMX_GPIO_GDIR) & ~(1UL << 22)));
	return (in32(gpio_base_2 + IMX_GPIO_PSR) & (uint32_t)(1UL << 22)) >> 22;
}

/*return 1 means on, return 0 means off*/
unsigned int imx8_ethernet_switch_state_1_2(void)
{
	out32(gpio_base_2 + IMX_GPIO_GDIR, (in32(gpio_base_2 + IMX_GPIO_GDIR) & ~(1UL << 23)));
	return (in32(gpio_base_2 + IMX_GPIO_PSR) & (uint32_t)(1UL << 23)) >> 23;
}

/*return 1 means on, return 0 means off*/
unsigned int imx8_ethernet_switch_state_2_1(void)
{
	out32(gpio_base_2 + IMX_GPIO_GDIR, (in32(gpio_base_2 + IMX_GPIO_GDIR) & ~(1UL << 25)));
	return (in32(gpio_base_2 + IMX_GPIO_PSR) & (uint32_t)(1UL << 25)) >> 25;
}

/*return 1 means on, return 0 means off*/
unsigned int imx8_ethernet_switch_state_2_2(void)
{
	out32(gpio_base_2 + IMX_GPIO_GDIR, (in32(gpio_base_2 + IMX_GPIO_GDIR) & ~(1UL << 31)));
	return (in32(gpio_base_2 + IMX_GPIO_PSR) & (uint32_t)(1UL << 31)) >> 31;
}

/*------------------------------------------------------------*/


/*return 1 means 24V normal*/
unsigned int imx8_24V_voltage_state(void)
{
	out32(gpio_base_1 + IMX_GPIO_GDIR, (in32(gpio_base_1 + IMX_GPIO_GDIR) & ~(1UL << 7)));
	return (in32(gpio_base_1 + IMX_GPIO_PSR) & (uint32_t)(1UL << 7)) >> 7;
}


/*------------------------------------------------------------*/

/*return 1 means 5V 3.3V normal*/
unsigned int imx8_5V_overvoltage_state(void)
{
	out32(gpio_base_0 + IMX_GPIO_GDIR, (in32(gpio_base_0 + IMX_GPIO_GDIR) & ~(1UL << 2)));
	return (in32(gpio_base_0 + IMX_GPIO_PSR) & (uint32_t)(1UL << 2)) >> 2;
}

/*return 1 means 5V 3.3V normal*/
unsigned int imx8_5V_undervoltage_state(void)
{
	out32(gpio_base_5 + IMX_GPIO_GDIR, (in32(gpio_base_5 + IMX_GPIO_GDIR) & ~(1UL << 23)));
	return (in32(gpio_base_5 + IMX_GPIO_PSR) & (uint32_t)(1UL << 23)) >> 23;
}

/*-------------------------- power-off ethernet----------------------------*/

int imx8_safty_ethernet_off(void)
{

	int ret = 0;

    ret = imx8_dcdc_1_ctrl(0);
    ret = imx8_dcdc_2_ctrl(0);


	out32(gpio_base_0 + IMX_GPIO_GDIR, (in32(gpio_base_0 + IMX_GPIO_GDIR) & ~(1UL << 4)));
	out32(gpio_base_3 + IMX_GPIO_GDIR, (in32(gpio_base_3 + IMX_GPIO_GDIR) & ~(1UL << 14)));

	out32(gpio_base_0 + IMX_GPIO_DR, (in32(gpio_base_0 + IMX_GPIO_DR) &  ~(1UL << 4)));
	out32(gpio_base_3 + IMX_GPIO_DR, (in32(gpio_base_3 + IMX_GPIO_DR) &  ~(1UL << 14)));

	return ret;
}


/*timer irq function*/
const struct sigevent *handler (void *not_used, int id)
{

	cnt++;

	if((cnt%(uint32_t)2) == (uint32_t)0)
	{
		out32(gpio_base_0 + IMX_GPIO_DR, (in32(gpio_base_0 + IMX_GPIO_DR) | (1UL << 4)));
		out32(gpio_base_3 + IMX_GPIO_DR, (in32(gpio_base_3 + IMX_GPIO_DR) | (1UL << 14)));
	}
	else
	{
		out32(gpio_base_0 + IMX_GPIO_DR, (in32(gpio_base_0 + IMX_GPIO_DR) & ~(1UL << 4)));
		out32(gpio_base_3 + IMX_GPIO_DR, (in32(gpio_base_3 + IMX_GPIO_DR) & ~(1UL << 14)));
	}

    out32(tbase + GPT_SR, 0x1U);
    return &event;

}


/*timer pthread*/
void* timer( void * arg)
{
	int ret = 0;

    ret = ThreadCtl (_NTO_TCTL_IO, 0);
    SIGEV_INTR_INIT (&event);

    ret = imx8_dcdc_1_ctrl(1);
    ret = imx8_dcdc_2_ctrl(1);

	out32(gpio_base_0 + IMX_GPIO_GDIR, (in32(gpio_base_0 + IMX_GPIO_GDIR) |  (1UL << 4)));
	out32(gpio_base_3 + IMX_GPIO_GDIR, (in32(gpio_base_3 + IMX_GPIO_GDIR) |  (1UL << 14)));

	val = InterruptAttach(IMX_GPT0_IRQ, handler, NULL, 0,_NTO_INTR_FLAGS_TRK_MSK );

    out32(tbase + GPT_CR, (uint32_t)0x20000142);
    out32(tbase + GPT_PR, (uint32_t)0x7002);
    out32(tbase + GPT_SR, (uint32_t)0x3f);
    out32(tbase + GPT_IR, (uint32_t)0);
    out32(tbase , (uint32_t)0x20000543);
    out32(tbase + GPT_IR, (uint32_t)0x21);
    out32(tbase + GPT_OCR1, (uint32_t)0x3e);


    while(1)
    {
		ret = InterruptWait(0, 0);
		ret = InterruptUnmask(IMX_GPT0_IRQ, val);
    }
}

/*create 8khz timer*/
int imx8_create_timer_pthread(void)
{
	int ret = 0;

	tbase = mmap_device_io((size_t)0x1000, (uint64_t)IMX_GPT0_BASE);
	if(tbase == MAP_DEVICE_FAILED)
	{
		perror("Can't map timer device I/O");
		ret = -1;
	}
	else
	{

	}

    ret = pthread_create(&timer_thread, NULL, timer, NULL);
    return ret;
}


/************************************************************************/
/*25% timer irq function*/
const struct sigevent *handler_25 (void *not_used, int id)
{

	cnt++;

	InterruptLock( &spinner );

	if((cnt%(uint32_t)4) == (uint32_t)0)
	{
		out32(gpio_base_0 + IMX_GPIO_DR, (in32(gpio_base_0 + IMX_GPIO_DR) | (1UL << 4)));
		out32(gpio_base_3 + IMX_GPIO_DR, (in32(gpio_base_3 + IMX_GPIO_DR) | (1UL << 14)));
	}
	else
	{
		out32(gpio_base_0 + IMX_GPIO_DR, (in32(gpio_base_0 + IMX_GPIO_DR) & ~(1UL << 4)));
		out32(gpio_base_3 + IMX_GPIO_DR, (in32(gpio_base_3 + IMX_GPIO_DR) & ~(1UL << 14)));
	}

	InterruptUnlock( &spinner );

    out32(tbase + GPT_SR, 0x1U);
    return &event;

}


/*25% timer pthread*/
void* timer_25( void * arg)
{
	int ret = 0;

    ret = ThreadCtl (_NTO_TCTL_IO, 0);
    SIGEV_INTR_INIT (&event);

    ret = imx8_dcdc_1_ctrl(1);
    ret = imx8_dcdc_2_ctrl(1);

	out32(gpio_base_0 + IMX_GPIO_GDIR, (in32(gpio_base_0 + IMX_GPIO_GDIR) |  (1UL << 4)));
	out32(gpio_base_3 + IMX_GPIO_GDIR, (in32(gpio_base_3 + IMX_GPIO_GDIR) |  (1UL << 14)));

	val = InterruptAttach(IMX_GPT0_IRQ, handler_25, NULL, 0,_NTO_INTR_FLAGS_TRK_MSK );

    out32(tbase + GPT_CR, (uint32_t)0x20000142);

    out32(tbase + GPT_PR, (uint32_t)0x3002);

    out32(tbase + GPT_SR, (uint32_t)0x3f);
    out32(tbase + GPT_IR, (uint32_t)0);
    out32(tbase , (uint32_t)0x20000543);
    out32(tbase + GPT_IR, (uint32_t)0x21);
    out32(tbase + GPT_OCR1, (uint32_t)0x3e);


    while(1)
    {
		ret = InterruptWait(0, 0);
		ret = InterruptUnmask(IMX_GPT0_IRQ, val);
    }


}

/*create 25% 8khz timer*/
int imx8_create_timer_pthread_25(void)
{
	int ret = 0;

	tbase = mmap_device_io((size_t)0x1000, (uint64_t)IMX_GPT0_BASE);
	if(tbase == MAP_DEVICE_FAILED)
	{
		perror("Can't map timer device I/O");
		ret = -1;
	}
	else
	{

	}

    ret = pthread_create(&timer_thread, NULL, timer_25, NULL);

    return ret;
}
/************************************************************************/


int imx8_gpio_release(void)
{
	int ret = 0;
	ret = munmap_device_io(gpio_base_0, 0x10UL);
	if(ret > 0)
	{
		ret = -1;
		perror("munmap_device_io failed");
	}
	else
	{

	}

	ret = munmap_device_io(gpio_base_1, 0x10UL);
	if(ret > 0)
	{
		ret = -1;
		perror("munmap_device_io failed");
	}
	else
	{

	}

	ret = munmap_device_io(gpio_base_2, 0x10UL);
	if(ret > 0)
	{
		ret = -1;
		perror("munmap_device_io failed");
	}
	else
	{

	}

	ret = munmap_device_io(gpio_base_3, 0x10UL);
	if(ret > 0)
	{
		ret = -1;
		perror("munmap_device_io failed");
	}
	else
	{

	}

	ret = munmap_device_io(gpio_base_4, 0x10UL);
	if(ret > 0)
	{
		ret = -1;
		perror("munmap_device_io failed");
	}
	else
	{

	}

	ret = munmap_device_io(gpio_base_5, 0x10UL);
	if(ret > 0)
	{
		ret = -1;
		perror("munmap_device_io failed");
	}
	else
	{

	}

	return ret;
}
