//  Copyright (C) 2016, mituhiromatuura all right reserved.

#include <kernel.h>
#include <t_syslog.h>
#include <t_stdlib.h>
#include "syssvc/serial.h"
#include "syssvc/syslog.h"
#include "kernel_cfg.h"
#include "iodefine.h"

#include "gpio.h"
#include "mfs.h"
#include "i2c.h"

void init_i2c(int ch, int port)
{
	int scl_port	= sck2gpio[ch][port][0];
	int scl_bit		= sck2gpio[ch][port][1];
	int sda_port	= sot2gpio[ch][port][0];
	int sda_bit		= sot2gpio[ch][port][1];

	gpio_pfr_set(scl_port, scl_bit, 1);
	gpio_pfr_set(sda_port, sda_bit, 1);

	gpio_ade_set(scl_port, scl_bit, 0);
	gpio_ade_set(sda_port, sda_bit, 0);

	if(4 > ch)
	{
		*(v32_t *)GPIO_EPFR(7) &= ~((3       <<(ch*6+4+4))|(3       <<(ch*6+2+4)));
		*(v32_t *)GPIO_EPFR(7) |=  (((port+1)<<(ch*6+4+4))|((port+1)<<(ch*6+2+4)));
	}
	else
	{
		*(v32_t *)GPIO_EPFR(8) &= ~((3       <<((ch-4)*6+4+4))|(3       <<((ch-4)*6+2+4)));
		*(v32_t *)GPIO_EPFR(8) |=  (((port+1)<<((ch-4)*6+4+4))|((port+1)<<((ch-4)*6+2+4)));
	}

	*(v8_t *)(MFS_ISMK(ch)) &= ~MFS_ISMK_BIT_EN;
	*(v8_t *)(MFS_SMR(ch)) = MFS_SMR_BIT_MD_I2C;
	*(v16_t *)(MFS_BGR0(ch)) = (80000000 + 400000/2) / 400000 - 1;
	*(v8_t *)(MFS_ISBA(ch)) = 0;
	*(v8_t *)(MFS_ISMK(ch)) |= MFS_ISMK_BIT_EN;

	return;
}

void i2c_send_start(int ch, unsigned char data)
{
	while(!((*(v8_t *)MFS_SSR(ch)) & MFS_SSR_BIT_TDRE));

	*(v8_t *)(MFS_TDR(ch)) = data;
	*(v8_t *)(MFS_IBCR(ch)) |= MFS_IBCR_BIT_MSS;

	return;
}

void i2c_send_stop(int ch, unsigned char data)
{
	while(!((*(v8_t *)MFS_SSR(ch)) & MFS_SSR_BIT_TDRE));

	*(v8_t *)(MFS_TDR(ch)) = data;

	while(!((*(v8_t *)MFS_IBCR(ch)) & MFS_IBCR_BIT_INT));
	*(v8_t *)(MFS_IBCR(ch)) &= ~MFS_IBCR_BIT_MSS;
	while((*(v8_t *)MFS_IBCR(ch)) & MFS_IBCR_BIT_SCC);

	return;
}

void i2c_send_restart(int ch, unsigned char data)
{
	while(!((*(v8_t *)MFS_SSR(ch)) & MFS_SSR_BIT_TDRE));

	*(v8_t *)(MFS_TDR(ch)) = data;
	*(v8_t *)(MFS_IBCR(ch)) |= (MFS_IBCR_BIT_MSS | MFS_IBCR_BIT_SCC);

	return;
}

char i2c_recv(int ch)
{
	while(!((*(v8_t *)MFS_SSR(ch)) & MFS_SSR_BIT_TDRE));

	*(v8_t *)(MFS_TDR(ch)) = 0;
	*(v8_t *)(MFS_IBCR(ch)) |= MFS_IBCR_BIT_MSS;

	while(!((*(v8_t *)MFS_IBCR(ch)) & MFS_IBCR_BIT_INT));
	*(v8_t *)(MFS_IBCR(ch)) &= ~MFS_IBCR_BIT_MSS;
	while((*(v8_t *)MFS_IBCR(ch)) & MFS_IBCR_BIT_SCC);

	return *(char *)(MFS_TDR(ch));
}
