
#include "imx8_drv_i2c.h"

static int fd_i2c_1;
static int fd_i2c_8;
static int fd_sc;
static imx_dcmd_sc_misc_temp_t	cpu_temp;

int16_t temperature_read(int fd, uint8_t reg, uint8_t slave_addr)
{

	uint8_t v1, v2;
	uint16_t val = (uint16_t)0;
	struct send_recv
	{
		i2c_sendrecv_t hdr;
		uint8_t buf[2];
	} read;

	read.buf[0] = reg ;
	read.hdr.send_len = (uint32_t)1;
	read.hdr.recv_len = (uint32_t)2;

	read.hdr.slave.addr = slave_addr;
	read.hdr.slave.fmt = (uint32_t)I2C_ADDRFMT_7BIT;
	read.hdr.stop = (uint32_t)1;

	if((devctl(fd, DCMD_I2C_SENDRECV, (void *)&read, sizeof(read),(int *)NULL)) > 0)
	{
		perror("Failed to read to temp ! ");
	}
	else
	{

	}

	v1 = read.buf[0];
	v2 = read.buf[1];

	if(slave_addr == (uint8_t)0x48)
	{
		val = (v1 << 4) | (v2 >> 4);
	}
	else
	{

	}

	if(slave_addr == (uint8_t)0x49)
	{
		val = v2 | (uint16_t)((uint16_t)v1 << 8);
	}
	else
	{

	}
	return val;
}


int eeprom_read_data(int fd, uint32_t regaddr, uint8_t rx_buf[],uint32_t len,uint8_t slave_addr)
{

	int i = 0,ret = 0;

	struct send_recv
	{
		i2c_sendrecv_t hdr;
		uint8_t buf[128];
	} eeprom_read;

	/* Read the Registers Current Value */
	eeprom_read.buf[0] = (uint8_t)((regaddr >> 8) & 0xFFUL);
	eeprom_read.buf[1] = (uint8_t)(regaddr & 0xFFUL);

	eeprom_read.hdr.send_len = (uint32_t)2;
	eeprom_read.hdr.recv_len = (uint32_t)len ;

	eeprom_read.hdr.slave.addr = slave_addr;
	eeprom_read.hdr.slave.fmt = (uint32_t)I2C_ADDRFMT_7BIT;
	eeprom_read.hdr.stop = (uint32_t)1;

	ret = devctl(fd, (uint32_t)DCMD_I2C_SENDRECV, (void*)&eeprom_read,sizeof(eeprom_read),(int *)NULL);

	if(ret > 0)
	{

	}
	else
	{

	}

	for(i = 0; i < (int32_t)len; i++)
	{
		rx_buf[i] = eeprom_read.buf[i];
	}

	return ret;
}

int eeprom_write_data(int fd, uint32_t regaddr, uint8_t tx_buf[],uint32_t len,uint8_t slave_addr)
{

	int ret = 0,i = 0;

	struct send_recv
	{
		i2c_sendrecv_t hdr;
		uint8_t buf[2 + 128];
	} eeprom_write;

	/*Read the Registers Current Value */
	eeprom_write.buf[0] = (uint8_t)((regaddr >> 8) & 0xFFUL);
	eeprom_write.buf[1] = (uint8_t)(regaddr & 0xFFUL);

	for(i = 0; i < (int32_t)len; i++)
	{
		eeprom_write.buf[2 + i] = tx_buf[i];
	}

	eeprom_write.hdr.send_len = (uint32_t)2 + len;
	eeprom_write.hdr.recv_len = (uint32_t)0;

	eeprom_write.hdr.slave.addr = slave_addr;
	eeprom_write.hdr.slave.fmt = (uint32_t)I2C_ADDRFMT_7BIT;
	eeprom_write.hdr.stop = (uint32_t)1;

	ret = devctl(fd, (uint32_t)DCMD_I2C_SENDRECV, &eeprom_write, sizeof(eeprom_write),NULL);

	if(ret > 0)
	{

	}
	else
	{

	}

	return ret;
}


int imx8_i2c_init(void)
{

	fd_i2c_1 = open(I2C_1, O_RDWR);
	if(fd_i2c_1 == -1)
	{
		perror("can't open I2C1\n");
	}
	else
	{

	}

	fd_i2c_8 = open(I2C_8, O_RDWR);
	if(fd_i2c_8 == -1)
	{
		perror("can't open I2C8\n");
	}
	else
	{

	}

	return 0;
}


int imx8_cpu_temp_init(void)
{
	int ret = 0;

	fd_sc = open(SC_TEMP, O_RDWR);

	if(fd_sc == -1)
	{
		ret = -1;
		perror("can't open sc");
	}
	else
	{

	}

	return ret;
}


int imx8_read_cpu_temp(void)
{

	devctl(fd_sc, 0xc00c0557U, &cpu_temp, sizeof(cpu_temp),0);

	return cpu_temp.celsius;
}



/*There are 4 eeproms, one is in board,the other is out board,8R 12R switchboard
 * the first parameter must write EEPROM_IN_BOARD,or EEPROM_OUT_BOARD,define in imx8_drv_i2c.h*/

int imx8_write_eeprom(int board,uint8_t tx_buf[], unsigned int len)
{

	int division = 0,modular = 0,ret = 0;
	int i;
	if((len > (uint32_t)65536) || (len < (uint32_t)0) || (tx_buf == NULL))
	{
		perror("wrong para");
		ret = -1;
	}
	else
	{
		switch(board)
		{
		case EEPROM_IN_BOARD:

			if(len <= (uint32_t)128)
			{
				ret = eeprom_write_data(fd_i2c_1,0x0U,tx_buf,len,(uint8_t)I2C_1_EEPROM_ADDR);
			}
			else
			{

			}

			if(len > (uint32_t)128)
			{

				division = (int)len/128;
				modular = (int)len%128;

				for(i = 0; i < division; i++)
				{
					ret = eeprom_write_data(fd_i2c_1,i * 128,tx_buf + 128 * i,128U,(uint8_t)I2C_1_EEPROM_ADDR);
					ret = (int)delay((uint32_t)5);
				}

				ret = (int)delay((uint32_t)5);

				if(modular > 0)
				{
					ret = eeprom_write_data(fd_i2c_1,division * 128,tx_buf + 128 * division,(uint32_t)modular,(uint8_t)I2C_1_EEPROM_ADDR);
				}
				else
				{

				}
			}
			else
			{

			}

			break;
		case EEPROM_OUT_BOARD:

			if(len <= (uint32_t)128)
			{
				ret = eeprom_write_data(fd_i2c_8,0x0U,tx_buf,len,(uint8_t)I2C_8_EEPROM_ADDR);
			}
			else
			{

			}

			if(len > (uint32_t)128)
			{

				division = (int)len/128;
				modular = (int)len%128;

				for(i = 0; i < division; i++)
				{
					ret = eeprom_write_data(fd_i2c_8,i * 128,tx_buf + 128 * i,128U,(uint8_t)I2C_8_EEPROM_ADDR);
					ret = (int)delay((uint32_t)5);
				}

				ret = (int)delay((uint32_t)5);

				if(modular > 0)
				{
					ret = eeprom_write_data(fd_i2c_8,division * 128,tx_buf + 128 * division,(uint32_t)modular,(uint8_t)I2C_8_EEPROM_ADDR);
				}
				else
				{

				}
			}
			else
			{

			}
			break;

		case EEPROM_8R:

				if(len <= (uint32_t)64)
				{
					ret = eeprom_write_data(fd_i2c_8,0x0U,tx_buf,len,(uint8_t)I2C_8_EEPROM_8R_ADDR);
				}
				else
				{

				}

				if((len > (uint32_t)64) && (len < (uint32_t)32768))
				{

					division = (int)len/64;
					modular = (int)len%64;

					for(i = 0; i < division; i++)
					{
						ret = eeprom_write_data(fd_i2c_8,i * 64,tx_buf + 64 * i,64U,(uint8_t)I2C_8_EEPROM_8R_ADDR);
						ret = (int)delay((uint32_t)5);
					}

					ret = (int)delay((uint32_t)5);

					if(modular > 0)
					{
						ret = eeprom_write_data(fd_i2c_8,division * 64,tx_buf + 64 * division,(uint32_t)modular,(uint8_t)I2C_8_EEPROM_8R_ADDR);
					}
					else
					{

					}
				}
				else
				{
					ret = -1;
				}
				break;

		case EEPROM_12R:

				if(len <= (uint32_t)64)
				{
					ret = eeprom_write_data(fd_i2c_8,0x0U,tx_buf,len,(uint8_t)I2C_8_EEPROM_12R_ADDR);
				}
				else
				{

				}

				if((len > (uint32_t)64) && (len < (uint32_t)32768))
				{

					division = (int)len/64;
					modular = (int)len%64;

					for(i = 0; i < division; i++)
					{
						ret = eeprom_write_data(fd_i2c_8,i * 64,tx_buf + 64 * i,64U,(uint8_t)I2C_8_EEPROM_12R_ADDR);
						ret = (int)delay((uint32_t)5);
					}

					ret = (int)delay((uint32_t)5);

					if(modular > 0)
					{
						ret = eeprom_write_data(fd_i2c_8,division * 64,tx_buf + 64 * division,(uint32_t)modular,(uint8_t)I2C_8_EEPROM_12R_ADDR);
					}
					else
					{

					}
				}
				else
				{
					ret = -1;
				}
				break;

		default:
			perror("board must be EEPROM_IN_BOARD, EEPROM_IN_BOARD, EEPROM_8R, EEPROM_12R");
			ret = -1;
			break;
		}
	}

	return ret;
}

int imx8_read_eeprom(int board,uint8_t rx_buf[], unsigned int len)
{

	int division = 0,modular = 0,ret = 0;
	int i;
	if((len > (uint32_t)65536) || (len < (uint32_t)0) || (rx_buf == NULL))
	{
		perror("wrong para");
		ret = -1;
	}
	else
	{
		switch(board)
		{
		case EEPROM_IN_BOARD:

			if(len <= (uint32_t)128)
			{
				ret = eeprom_read_data(fd_i2c_1,0x0U,rx_buf,len,(uint8_t)I2C_1_EEPROM_ADDR);
			}
			else
			{

			}

			if(len > (uint32_t)128)
			{

				division = (int)len/128;
				modular = (int)len%128;

				for(i = 0; i < division; i++)
				{
					ret = eeprom_read_data(fd_i2c_1,i * 128,rx_buf + 128 * i,128U,(uint8_t)I2C_1_EEPROM_ADDR);
				}

				if(modular > 0)
				{
					ret = eeprom_read_data(fd_i2c_1,division * 128,rx_buf + 128 * division,(uint32_t)modular,(uint8_t)I2C_1_EEPROM_ADDR);
				}
				else
				{

				}
			}
			else
			{

			}

			break;
		case EEPROM_OUT_BOARD:

			if(len <= (uint32_t)128)
			{
				ret = eeprom_read_data(fd_i2c_8,0x0U,rx_buf,len,(uint8_t)I2C_8_EEPROM_ADDR);
			}
			else
			{

			}

			if(len > (uint32_t)128)
			{

				division = (int)len/128;
				modular = (int)len%128;

				for(i = 0; i < division; i++)
				{
					ret = eeprom_read_data(fd_i2c_8,i * 128,rx_buf + 128 * i,128U,(uint8_t)I2C_8_EEPROM_ADDR);
				}

				if(modular > 0)
				{
					ret = eeprom_read_data(fd_i2c_8,division * 128,rx_buf + 128 * division,(uint32_t)modular,(uint8_t)I2C_8_EEPROM_ADDR);
				}
				else
				{

				}

			}
			else
			{

			}
			break;

		case EEPROM_8R:

			if(len <= (uint32_t)64)
			{
				ret = eeprom_read_data(fd_i2c_8,0x0U,rx_buf,len,(uint8_t)I2C_8_EEPROM_8R_ADDR);
			}
			else
			{

			}

			if((len > (uint32_t)64) && (len < (uint32_t)32768))
			{

				division = (int)len/64;
				modular = (int)len%64;

				for(i = 0; i < division; i++)
				{
					ret = eeprom_read_data(fd_i2c_8,i * 64,rx_buf + 64 * i,64U,(uint8_t)I2C_8_EEPROM_8R_ADDR);
				}

				if(modular > 0)
				{
					ret = eeprom_read_data(fd_i2c_8,division * 64,rx_buf + 64 * division,(uint32_t)modular,(uint8_t)I2C_8_EEPROM_8R_ADDR);
				}
				else
				{

				}

			}
			else
			{
				ret = -1;
			}
			break;

		case EEPROM_12R:

			if(len <= (uint32_t)64)
			{
				ret = eeprom_read_data(fd_i2c_8,0x0U,rx_buf,len,(uint8_t)I2C_8_EEPROM_12R_ADDR);
			}
			else
			{

			}

			if((len > (uint32_t)64) && (len < (uint32_t)32768))
			{

				division = (int)len/64;
				modular = (int)len%64;

				for(i = 0; i < division; i++)
				{
					ret = eeprom_read_data(fd_i2c_8,i * 64,rx_buf + 64 * i,64U,(uint8_t)I2C_8_EEPROM_12R_ADDR);
				}

				if(modular > 0)
				{
					ret = eeprom_read_data(fd_i2c_8,division * 64,rx_buf + 64 * division,(uint32_t)modular,(uint8_t)I2C_8_EEPROM_12R_ADDR);
				}
				else
				{

				}

			}
			else
			{
				ret = -1;
			}
			break;

		default:
			perror("board must be EEPROM_IN_BOARD, EEPROM_IN_BOARD, EEPROM_8R, EEPROM_12R");
			ret = -1;
			break;
		}
	}


	return ret;
}



int imx8_write_fram(uint8_t tx_buf[], unsigned int len)
{

	int division = 0,modular = 0,ret = 0;
	int i;
	if(len > (uint32_t)32768)
	{
		perror("FRAM write than 32KB\n");
		ret = -1;
	}
	else
	{

	}

	if(len <= (uint32_t)128)
	{
		ret = eeprom_write_data(fd_i2c_1,0x0U,tx_buf,len,(uint8_t)I2C_1_FRAM_ADDR);
	}
	else
	{

	}

	if(len > (uint32_t)128)
	{

		division = (int)len/128;
		modular = (int)len%128;

		for(i = 0; i < division; i++)
		{
			ret = eeprom_write_data(fd_i2c_1,i * 128,tx_buf + 128 * i,128U,(uint8_t)I2C_1_FRAM_ADDR);
			ret = (int)delay((uint32_t)5);
		}

		ret = (int)delay((uint32_t)5);

		if(modular > 0)
		{
			ret = eeprom_write_data(fd_i2c_1,division * 128,tx_buf + 128 * division,(uint32_t)modular,(uint8_t)I2C_1_FRAM_ADDR);
		}
		else
		{

		}

	}

	return ret;
}



int imx8_read_fram(uint8_t rx_buf[], unsigned int len)
{

	int division = 0,modular = 0,ret = 0;
	int i;
	if(len > (uint32_t)32768)
	{
		perror("FRAM read than 32KB\n");
		ret = -1;
	}
	else
	{

	}

	if(len <= (uint32_t)128)
	{
		ret = eeprom_read_data(fd_i2c_1,0x0U,rx_buf,len,(uint8_t)I2C_1_FRAM_ADDR);
	}
	else
	{

	}

	if(len > (uint32_t)128)
	{

		division = (int)len/128;
		modular = (int)len%128;

		for(i = 0; i < division; i++)
		{
			ret = eeprom_read_data(fd_i2c_1,i * 128,rx_buf + 128 * i,128U,(uint8_t)I2C_1_FRAM_ADDR);
		}

		if(modular > 0)
		{
			ret = eeprom_read_data(fd_i2c_1,division * 128,rx_buf + 128 * division,(uint32_t)modular,(uint8_t)I2C_1_FRAM_ADDR);
		}
		else
		{

		}

	}
	else
	{

	}

	return ret;
}


static uint16_t ina3321_read(int fd, uint8_t reg)
{

	uint8_t v1, v2;
	uint16_t result = 0;
	struct send_recv
	{
		i2c_sendrecv_t hdr;
		uint8_t buf[2];
	} ina3321_rd;


	ina3321_rd.buf[0] = reg ;
	ina3321_rd.hdr.send_len = (uint32_t)1;
	ina3321_rd.hdr.recv_len = (uint32_t)2;

	ina3321_rd.hdr.slave.addr = (uint8_t)I2C_8_INA3321_ADDR;
	ina3321_rd.hdr.slave.fmt = (uint32_t)I2C_ADDRFMT_7BIT;
	ina3321_rd.hdr.stop = (uint32_t)1;


	if (devctl(fd, DCMD_I2C_SENDRECV, &ina3321_rd, sizeof(ina3321_rd),NULL))
	{
		perror("Failed to read to ina3321\n");
		result = -1;
	}
	else
	{

	}

	v1 = ina3321_rd.buf[0];
	v2 = ina3321_rd.buf[1];
	result = v2 | (uint16_t)((uint16_t)v1 << 8);

	return result;
}


int imx8_read_ina3221(struct ina3221* ina3221)
{

	int ret = 0;
	if(ina3221 == NULL)
	{
		ret = -1;
	}
	else
	{
		ina3221->channel_1_shunt = (ina3321_read(fd_i2c_8,(uint8_t)0x1) >> 3) * 4;
		ina3221->channel_2_shunt = (ina3321_read(fd_i2c_8,(uint8_t)0x3) >> 3) * 4;
		ina3221->channel_3_shunt = (ina3321_read(fd_i2c_8,(uint8_t)0x5) >> 3) * 4;
		ina3221->channel_1_bus = (float)(ina3321_read(fd_i2c_8,(uint8_t)0x2) >> 3) * 8 / 1000;
		ina3221->channel_2_bus = (float)(ina3321_read(fd_i2c_8,(uint8_t)0x4) >> 3) * 8 / 1000;
		ina3221->channel_3_bus = (float)(ina3321_read(fd_i2c_8,(uint8_t)0x6) >> 3) * 8 / 1000;
	}

	return ret;
}

double imx8_read_tmp117(void)
{
	return (double)temperature_read(fd_i2c_8,(uint8_t)0,(uint8_t)I2C_8_TMP117_ADDR) * 0.0078125;
}

double imx8_read_tmp112(void)
{

	uint16_t temp;
	double value;

	temp = temperature_read(fd_i2c_1,(uint8_t)0,(uint8_t)I2C_1_TMP112_ADDR);

	if((temp & 0x800u) == 0x800u)
	{
		temp <<= 4;
		value = (double)(((short int)temp * 0.0625) / 16);
	}
	else
	{
		value = (double)temp * 0.0625;
	}


	return value;
}

/*i2c release*/
int imx8_release_i2c(void)
{
	int ret = 0;
	ret = close (fd_i2c_1);
	ret = close (fd_i2c_8);
	return ret;
}




