/*
 * Filename: eeprom_read.c
 *
 * Function:
 *
 * demonstrate accesses to the i2c WR eeprom on the sis1160
 *
 * Author:			TF
 * Date:			09.02.2018
 * Last modified:	09.02.2018
 *
 * -------------------------------------------
 *
 * SIS Struck Innovative Systeme GmbH
 *
 * Harksheider Straße 102a
 * 22399 Hamburg
 *
 * Tel. +49 (0)40 60 87 305 0
 * Fax	+49 (0)40 60 87 305 20
 *
 * http://www.struck.de
 *
 * (c) 2018
 */

#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <linux/fs.h>

#include "sis1100_var.h"

#define I2C_BUSY				0x80000000UL
#define I2C_READ_BYTE			0x2000UL
#define I2C_WRITE_BYTE			0x1000UL
#define I2C_STOP				0x800UL
#define I2C_REPEATSTART			0x400UL
#define I2C_START				0x200UL
#define I2C_ACK					0x100UL
#define I2C_DATA_MASK			0xFFUL
#define I2C_DATA_POS			0UL

#define I2C_DIR_READ			1
#define I2C_DIR_WRITE			0


typedef struct {
	uint32_t offset;
	uint32_t data;
	uint32_t error;
}sis1100_reg_t;


int sis1100_control_read(int device, uint32_t offset, uint32_t *data);
int sis1100_control_write(int device, uint32_t offset, uint32_t data);

int sis1100_i2c_start(int device, uint32_t base);
int sis1100_i2c_busy_wait(int device, uint32_t base);
int sis1100_i2c_stop(int device, uint32_t base);
int sis1100_i2c_read_data(int device, uint32_t base, uint8_t *data, uint8_t ack);
int sis1100_i2c_write_data(int device, uint32_t base, uint8_t data, uint8_t *ack);

//int sis1100_eeprom_read();
//int sis1100_eeprom_wite();


/*
 *
 */
int main(int argc, char **argv) {

	int fp;
	uint32_t ret, data;

	if(argc != 3){
		printf("usage: %s [device] [offset]\n", argv[0]);
		return -1;
	}

	fp = open(argv[1], O_RDWR);
		if(fp < 0){
			printf("can't open device %s\n", argv[1]);
			return -1;
	}

	ret = sis1100_control_read(fp, 0x0, &data);
	printf("Data[%d]: %x\n", ret, data);


	close(fp);

	return EXIT_SUCCESS;
}

/*
 *
 */
int sis1100_i2c_start(int device, uint32_t base){

	if(sis1100_control_write(device, base, I2C_START)){
		return -1;
	}

	return sis1100_i2c_busy_wait(device, base);
}

/*
 *
 */
int sis1100_i2c_read_data(int device, uint32_t base, uint8_t *data, uint8_t ack){

	uint32_t reg;

	// integrate ack bit into read command
	reg = I2C_READ_BYTE | (ack ? I2C_ACK : 0);
	rc = common_writeRegister(dev, base, reg);
	if (API_ERR(rc)) {
		return rc;
	}

	return 0;
}

/*
 *
 */
int sis1100_i2c_write_data(int device, uint32_t base, uint8_t data, uint8_t *ack){

	uint32_t reg;

	// start byte transmission
	reg = I2C_WRITE_BYTE | data;
	if(sis1100_control_write(device, base, reg)){
		return -1;
	}

	// wait for logic to finish
	if(i2c_busy_wait(device, base)){
		return -1;
	}

	// read ACK/NACK from ip
	if(sis1100_control_read(device, base, &reg)){
		return -1;
	}

	// return the ACK/NACK
	*ack = reg & I2C_ACK ? 1 : 0;

	return 0;
}

/*
 *
 */
int sis1100_i2c_busy_wait(int device, uint32_t base){

	uint32_t reg;

	do{
		if(sis1100_control_read(device, base, &reg)){
			return -1;
		}

		if(reg & I2C_BUSY){
			usleep(1);
		}

	}while(reg & I2C_BUSY);

	return 0;
}

/*
 *
 */
int sis1100_i2c_stop(int device, uint32_t base){

	if(sis1100_control_write(device, base, I2C_STOP)){
		return -1;
	}

	return sis1100_i2c_busy_wait(device, base);
}



/*
 *
 */
int sis1100_control_read(int device, uint32_t offset, uint32_t *data){

	sis1100_reg_t reg;
	reg.offset = offset;

	ioctl(device, SIS1100_CTRL_READ, &reg);

	*data = reg.data;

	return reg.error;
}

/*
 *
 */
int sis1100_control_write(int device, uint32_t offset, uint32_t data){

	sis1100_reg_t reg;
	reg.offset 	= offset;
	reg.data	= data;

	ioctl(device, SIS1100_CTRL_WRITE, &reg);

	return reg.error;
}
