/****************************************************************************************//**
* \file				i2cDriver.c
*
* \brief This unit is a simple driver library for I2C bus based on the Open-Core I2C-master.
* 
* \author PYD : 12/6/2013
* \version 0.1
* \date 12/6/2013

* PYD : 12/6/2013 initial version
* PYD : 01/10/2018 remove code for ES12 and ES3 versions
*//******************************************************************************************/
#include <stdio.h>
#include <error.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define offsetReg(r) (r*4)

//========================= SYSTEM CONFIGURATION =================================
#include <systemConfig.h>
#include <ecs.h>
//================================================================================
//                 USER ORIENTED PROCEDURES FOR EXTERNAL USE
#include <i2cDriver.h>
//===============================================================================
//#define I2C_FREQ      0xc7 ;#(199dec) value for 100MHz clock to match 100kHz SCL
//#define I2C_FREQ      0x31 ;#(49dec) value for 100MHz clock to match 400kHz SCL
//#define I2C_FREQ      0x18 ;#(24dec) value for 100MHz clock to match 800kHz SCL

// addresses of I2C registers (start at 0xa40 in qsys)
#define I2C_PRELOREG  0x0
#define I2C_PREHIREG  0x1
#define I2C_CTRLREG   0x2
#define I2C_TSMTREG   0x3
#define I2C_RCVREG    0x3
#define I2C_CMDREG    0x4
#define I2C_STATREG   0x4

// Control register
#define I2C_ENA      0x80 
#define I2C_DIS      0x00 
// Command register bits 
#define I2C_STA      0x80 
#define I2C_STO      0x40 
#define I2C_RD       0x20 
#define I2C_WR       0x10 
#define I2C_NACK     0x08 
#define I2C_IACK     0x01 
// Status register bits
#define I2C_TIP      0x02 
#define I2C_BUSY     0x40

/***********************************************************************//**
 * \fn int unsigned I2C_MakeAvagoAdd(compNb)
 * \brief Function to build a device address
 *
 * For TX(pair) the address is 0101hjkx (hjk is hard add) (x is 1=R 0=W)
 *
 * For RX(odd) the address is 0110hjkx (hjk is hard add) (x is 1=R 0=W)
 *
 * NOTE the x is added in Read/Write function
 *
 * \return the I2c address
 *//***********************************************************************/
/*
static unsigned i2c_MakeAvagoAdd(int compNb) {
	unsigned i2cAdd;
// partern 0 +   0101/TX or 0110/RX + fixAdd on 3digits
	if (compNb%2)
		i2cAdd = 5<<3;
	else
		i2cAdd = 6<<3;
	i2cAdd = i2cAdd + compNb;

	return(i2cAdd);
}
*/

unsigned lastSetInCLK[MAX_DEV];
unsigned LastSetSCLfreq[MAX_DEV];

static int getBusBase(int bus){
	switch(bus){
		case I2C_BUS_TEMPERATURES:
			return(I2C_BUS_BASE_TEMPERATURES);
		break;
		case I2C_BUS_PLL_CLEANER1:
			return(I2C_BUS_BASE_PLL_CLEANER1);
		break;
		case I2C_BUS_PLL_CLEANER2:
			return(I2C_BUS_BASE_PLL_CLEANER2);
		break;
		case I2C_BUS_PLL_TFC:
			return(I2C_BUS_BASE_PLL_TFC);
		break;
		case I2C_BUS_SFP1:
			return(I2C_BUS_BASE_SFP1);
		break;
		case I2C_BUS_SFP2:
			return(I2C_BUS_BASE_SFP2);
		break;
		case I2C_BUS_MINIPODS:
			return(I2C_BUS_BASE_MINIPODS);
		break;
		case I2C_BUS_TEMP_MEZZANINE:
			return(I2C_BUS_BASE_TEMP_MEZZANINE);
		break;
		case I2C_BUS_CURRENT1:
			return(I2C_BUS_BASE_CURRENT1);
		break;
		case I2C_BUS_CURRENT2:
			return(I2C_BUS_BASE_CURRENT2);
		break;
		case I2C_BUS_FANOUT:
		    return(I2C_BUS_BASE_FANOUT);
                break;
		case I2C_BUS_FPGA_EEPROM:
		    return(I2C_BUS_BASE_FPGA_EEPROM);
		default:
			printf("ERROR: unknown i2c bus number %d in file %s line %d\n",bus,__FILE__,__LINE__);
			return(99);
	}
}
 /***********************************************************************//**
 * \fn void i2c_enable(int dev, int bus)
 * \brief Function to activate the i2c-opencore IP.
 * \param dev: the board number
 * \param bus: the target i2c bus number
 *//***********************************************************************/
static void i2c_enable(int dev, int bus) {
	unsigned cval = I2C_ENA;

	ecs_iowrI2c_slow( dev, getBusBase(bus)+  (I2C_CTRLREG*4), &cval);
}
/***********************************************************************//**
 * \fn void i2c_disable(int dev,int bus)
 * \param dev: the board number
 * \brief Function to deactivate the i2c-opencore IP.
 * \param bus: the target i2c bus number
 *//***********************************************************************/
static void i2c_disable(int dev,int bus) {
	unsigned cval = I2C_DIS;

	ecs_iowrI2c_slow( dev, getBusBase(bus)+  (I2C_CTRLREG*4), &cval);		
}
/***********************************************************************//**
 * \fn void i2c_stop(int dev,int bus)
 * \param dev: the board number
 * \brief Function to generate the stop condition on the i2c bus.
 * \param bus: the target i2c bus number
 *//***********************************************************************/
static void i2c_stop(int dev, int bus) {
	unsigned cval = I2C_STO;

	ecs_iowrI2c_slow( dev, getBusBase(bus)+  (I2C_CMDREG*4), &cval);	
}

/****************************************************************************//**
 * \fn void i2c_setSpeed(int dev, int bus, int value)
 * \brief Function to program the prescale the SCL clock line. Should be called
 *        before the I2C use.
 * \param dev: the board number
 * \param   bus: the target i2c bus number
 * \param value: the value to write in the prescale register
 *//**************************************************************************/
static void i2c_setSpeed(int dev, int bus, int value ) {
	unsigned cval = value>>8;
	int 	 base = getBusBase(bus);

	ecs_iowrI2c_slow(dev, base + (I2C_PREHIREG*4), &cval);
	cval =value & 0xFF;
	ecs_iowrI2c_slow(dev, base + (I2C_PRELOREG*4), &cval);
}
/****************************************************************************//**
 * \fn int i2c_init(int dev, int bus, unsigned inCLK, unsigned SCLfreq)
 * \brief Function to open access to i2c opencore and set speed
 * \      if it is specified
 * \param dev: the board number
 * \param     bus: the target i2c bus number
 * \param   inCLK: the input system clock ferquency in Hz
 * \param SCLfreq: the target SCL clock frequency in Hz
 * \return 0 success,-1 error
 *//**************************************************************************/
int i2c_init(int dev, int bus, unsigned inCLK, unsigned SCLfreq) {
	long int prescale;

//	printf("Simulation init with clock %d fequency %d \n",inCLK, SCLfreq); return(0);

	if (ecs_openLli(dev)<0){
		printf("ERROR: Can't init I2C\n");
		return(-1);
	}
	i2c_stop(dev, bus);
	i2c_disable(dev, bus);
	i2c_enable(dev, bus);
	// set prescale register
	if (inCLK!=0 && SCLfreq !=0){
		prescale = (inCLK/(5*SCLfreq))-1;
//		printf("PYD i2c i2c_init() bus %d applied speed is %ld\n", bus, prescale);
		i2c_setSpeed(dev, bus, prescale);
        	lastSetInCLK[dev] = inCLK;
        	LastSetSCLfreq[dev] = SCLfreq;
	}
	return(0);
}

/****************************************************************************//**
 * \fn int i2c_getInit(int dev, int bus, unsigned &inCLK, unsigned &SCLfreq)
 * \brief Read the last values in the prescale of the SCL clock line. 
 *
 * \param dev: the board number
 * \param     bus: the target i2c bus number
 * \param   inCLK: the system clock ferquency in Hz
 * \param SCLfreq: the target SCL clock frequency in Hz
 *//**************************************************************************/
void i2c_getInit(int dev, int bus, unsigned *inCLK, unsigned *SCLfreq) {
	*inCLK = lastSetInCLK[dev];
	*SCLfreq = LastSetSCLfreq[dev];
}
/***********************************************************************************//**
 * \fn int _waitTIP()
 * \brief function to wait for the status register TIP bit value 0 "transfer complete"
 *
 * \param     dev: the borad number
 * \param     bus: the target i2c bus number       
 * \return 0 success,-1 error
 *//********************************************************************************/
static int i2c_waitTIP(int dev, int bus) {
	unsigned val, step = 0;
	int 	 base = getBusBase(bus);
	while(1){
      usleep(10); //MJ POUR TEMPO_FERNAND LE 12 SEPT 2017
//		printf("step %d\n", step);
		step = step + 1;
		if(ecs_iordI2c_slow(dev, base + (I2C_STATREG*4), &val)==0){
//			printf("PYD status 0x%x\n", val);
			if ((val & I2C_TIP) == 0){ //transfer complete
				return(0);
			} else { // transfer in progress
				if (step > 500){
					printf("ERROR: timeout in i2c_waitTIP()\n");
					return(-1);
				} else {
					usleep(10);
//					printf("PYD wait %d\n", step);
//					for (i=0; i<loop; i++) dum++;
				}
			}
		} else { // read error
			printf("i2c_waitTIP firmware level read error KO\n");
			return(-1);
		}
	}//while
}

/***********************************************************************//**
 * \fn int i2c_readMem(int dev, int bus, unsigned slaveAdd, unsigned regIndex, unsigned *val)
 * \brief Function to read one single register
 *     
 * \param     dev: the board number
 * \param      bus: the target i2c bus number          
 * \param slaveAdd: the address of the device to write in the I2C space
 * \param regIndex: the number of the register in the component
 * \param val     : a pointer to receive the read value
 * \return 0 success,-1 error
 *//***********************************************************************/
int i2c_readMem(int dev, int bus, unsigned slaveAdd, unsigned regIndex, unsigned *val) {
	unsigned cval;
	int 	 base = getBusBase(bus);

	// generate start command 
	// write $slaveAdd (slaveAdd+WR bit) in transmitReg
	//
	// printf("PYD bus=%d i2c_readMem() at base 0x%x subadd 0x%x register %d\n", bus, base, slaveAdd, regIndex);
//	printf("Simulation\n"); *val=0x55; return(0);

	cval = slaveAdd<<1; 
	ecs_iowrI2c_slow(dev, base +  (I2C_TSMTREG*4), &cval);
	// set STA bit and WR bit in commandReg
	cval = I2C_STA | I2C_WR;
	ecs_iowrI2c_slow(dev, base +  (I2C_CMDREG*4), &cval);
	// wait fir TIP flaf in statusReg
	if ( i2c_waitTIP(dev, bus) != 0) 
			return(-1);
	// read statusReg to verify RxACK=0
	ecs_iordI2c_slow(dev, base +  (I2C_STATREG*4), &cval);
	if ((cval & I2C_NACK) == I2C_NACK){
		printf("ERROR: bus=%d i2c_readMem() first transaction slave address not acknowledge in I2C_Write\n",bus);
		return(-1);
	}
	//
	// write $regIndex in transmitReg
	//
	cval = regIndex;
	ecs_iowrI2c_slow(dev, base +  (I2C_TSMTREG*4), &cval);
	// set WR bit in commandReg
	cval = I2C_WR;
	ecs_iowrI2c_slow(dev, base +  (I2C_CMDREG*4), &cval);
	// wait fir TIP flaf in statusReg
	if ( i2c_waitTIP(dev, bus) != 0)
			return(-1);
	// read statusReg to verify RxACK=0
	ecs_iordI2c_slow(dev, base +  (I2C_STATREG*4), &cval);
	if ((cval & I2C_NACK) == I2C_NACK){
		printf("ERROR:bus %d i2c_readMem() second transaction slave address not acknowledge in I2C_Write\n",bus);
		return(-1);
	}
	//
	// write $slaveAdd (slaveAdd+RD bit) in transmitReg
	//
	cval = slaveAdd<<1 | 1;
	ecs_iowrI2c_slow(dev, base +  (I2C_TSMTREG*4), &cval);	
	// set STA bit and WR bit in commandReg
	cval = I2C_STA | I2C_WR;
	ecs_iowrI2c_slow(dev, base +  (I2C_CMDREG*4), &cval);
	// wait fir TIP flaf in statusReg
	if ( i2c_waitTIP(dev, bus) != 0)
			return(-1);
	// read statusReg to verify RxACK=0
	if ((cval & I2C_NACK) == I2C_NACK){
		printf("ERROR: bus %d i2c_readMem() third transaction slave address not acknowledge in I2C_Write\n",bus);
		return(-1);
	}
	//
	// set RD bit, set ACK bit =1(NACK) set STO bit in commandReg
	//
	cval = I2C_RD | I2C_NACK | I2C_STO;
	ecs_iowrI2c_slow(dev, base +  (I2C_CMDREG*4), &cval);
	// wait for TIP flag in statusReg
	if ( i2c_waitTIP(dev, bus) != 0)
			return(-1);	
	return( ecs_iordI2c_slow(dev, base +  (I2C_RCVREG*4), val) );
}
/***********************************************************************//**
 * \fn int i2c_writeMem(int dev, int bus, unsigned slaveAdd, unsigned regIndex, unsigned *val)
 * \brief Function to write a value in a register
 *     
 * \param     dev: the board number
 * \param      bus: the target i2c bus number      
 * \param slaveAdd: the address of the device to write in the I2C space
 * \param regIndex: the number of the register in the component
 * \param val     : a pointer to the value to write
 * \return 0 success,-1 error
 *//***********************************************************************/
int i2c_writeMem(int dev, int bus, unsigned slaveAdd, unsigned regIndex, unsigned *val){
	unsigned cval;
	int 	 base = getBusBase(bus);

	// generate start command 
//	printf("bus %d i2c_writeMem() at add 0x%x register %d val %x\n", bus, slaveAdd, regIndex, *val);
//	printf("Simulation\n"); return(0);
	// write $slaveAdd (slaveAdd+WR bit) in transmitReg
	cval = slaveAdd<<1; 
	ecs_iowrI2c_slow(dev, base +  (I2C_TSMTREG*4), &cval);
	// set STA bit and WR bit in commandReg
	cval = I2C_STA | I2C_WR;
	ecs_iowrI2c_slow(dev, base +  (I2C_CMDREG*4), &cval);
	// wait fir TIP flaf in statusReg
	if ( i2c_waitTIP(dev, bus) != 0) 
			return(-1);
	// read statusReg to verify RxACK=0
	ecs_iordI2c_slow(dev, base +  (I2C_STATREG*4), &cval);
	if ((cval & I2C_NACK) == I2C_NACK){
		printf("ERROR: bus %d slave address not acknowledge in I2C_Write\n",bus);
		return(-1);
	}
	//
	// write $regIndex in transmitReg
	//
	cval = regIndex;
	ecs_iowrI2c_slow(dev, base +  (I2C_TSMTREG*4), &cval);
	// set WR bit in commandReg
	cval = I2C_WR;
	ecs_iowrI2c_slow(dev, base +  (I2C_CMDREG*4), &cval);
	// wait fir TIP flaf in statusReg
	if ( i2c_waitTIP(dev, bus) != 0) 
			return(-1);
	// read statusReg to verify RxACK=0
	ecs_iordI2c_slow(dev, base +  (I2C_STATREG*4), &cval);
	if ((cval & I2C_NACK) == I2C_NACK){
		printf("ERROR: bus %d slave address not acknowledge in I2C_Write\n",bus);
		return(-1);
	}
	//
	// write $slaveAdd (slaveAdd+RD bit) in transmitReg
	//
	ecs_iowrI2c_slow(dev, base +  (I2C_TSMTREG*4), val);	
	// set STA bit and WR bit in commandReg
	cval = I2C_STO | I2C_WR;
	ecs_iowrI2c_slow(dev, base +  (I2C_CMDREG*4), &cval);	
	// wait fir TIP flaf in statusReg
	if ( i2c_waitTIP(dev, bus) != 0) 
			return(-1);
return(0);
}
/***********************************************************************//**
 * \fn int i2c_multReadMemInit(int dev, int bus, unsigned slaveAdd, unsigned regIndex)
 * \brief Function to initialize a multiread sequence from slave at
 *        i2c address slaveAdd starting at device internal register regIndex
 *       
 * \param     dev: the board number
 * \param      bus: the target i2c bus number    
 * \param slaveAdd: the address of the device to read from in the I2C space
 * \param regIndex: the number of the first register in the sequence to read
 * \return 0 success,-1 error
 *//***********************************************************************/
static int i2c_multReadMemInit(int dev, int bus, unsigned slaveAdd, unsigned regIndex)  {
	unsigned cval;
	int 	 base = getBusBase(bus);

	// generate start command 
	// write $slaveAdd (slaveAdd+WR bit) in transmitReg
	//
//	printf("PYD start i2c_multReadMemInit\n");
	cval = slaveAdd<<1; 
	ecs_iowrI2c_slow(dev, base +  (I2C_TSMTREG*4), &cval);
	// set STA bit and WR bit in commandReg
	cval = I2C_STA | I2C_WR;
	ecs_iowrI2c_slow(dev, base +  (I2C_CMDREG*4), &cval);
//	printf("PYD wait for TIP flag in statusReg\n");
	// wait for TIP flag in statusReg
	if ( i2c_waitTIP(dev, bus) != 0) 
			return(-1);
	// read statusReg to verify RxACK=0
//	printf("PYD read statusReg to verify RxACK=0\n");
	ecs_iordI2c_slow(dev, base +  (I2C_STATREG*4), &cval);
	if ((cval & I2C_NACK) == I2C_NACK){
		printf("ERROR: bus %d slave address not acknowledge in I2C_Write\n",bus);
		return(-1);
	}
	//
	// write $regIndex in transmitReg
	//
//	printf("PYD write $regIndex in transmitReg\n");
	cval = regIndex;
	ecs_iowrI2c_slow(dev, base +  (I2C_TSMTREG*4), &cval);
	// set WR bit in commandReg
	cval = I2C_WR;
	ecs_iowrI2c_slow(dev, base +  (I2C_CMDREG*4), &cval);
	// wait fir TIP flaf in statusReg
	if ( i2c_waitTIP(dev, bus) != 0)
			return(-1);
	// read statusReg to verify RxACK=0
	ecs_iordI2c_slow(dev, base +  (I2C_STATREG*4), &cval);
	if ((cval & I2C_NACK) == I2C_NACK){
		printf("ERROR: bus %d slave address not acknowledge in I2C_Write\n",bus);
		return(-1);
	}
	//
	// write $slaveAdd (slaveAdd+RD bit) in transmitReg
	//
//	printf("PYD write $slaveAdd (slaveAdd+RD bit) in transmitReg\n");
	cval = slaveAdd<<1 | 1;
	ecs_iowrI2c_slow(dev, base +  (I2C_TSMTREG*4), &cval);	
	// set STA bit and WR bit in commandReg
	cval = I2C_STA | I2C_WR;
	ecs_iowrI2c_slow(dev, base +  (I2C_CMDREG*4), &cval);
	// wait fir TIP flaf in statusReg
	if ( i2c_waitTIP(dev, bus) != 0)
			return(-1);
//	printf("PYD end i2c_multReadMemInit\n");
return(0);
}
/******************************************************************************//**
 * \fn int i2c_multReadMem(int dev, int bus, unsigned slaveAdd, unsigned regIndex, int nb)
 * \brief Function to read/print a sequence of nb conscecutive registers from slave at
 *        i2c address slaveAdd starting at device internal register regIndex
 *        Used with nb=1 is a function to read one register value
 *
 * This function allocate the array to store the read data in. The user
 * should free it after use.
 *       
 * \param     dev: the board number
 * \param      bus: the target i2c bus number    
 * \param slaveAdd: the address of the device to read from in the I2C space
 * \param regIndex: the number of the first register in the sequence to read
 * \param nb      : the number of conscecutives registers to read
 * \param data    : a pointer to receive the data array reference
 * \return 0 success,-1 error
 *//******************************************************************************/
int i2c_multReadMem(int dev, int bus, unsigned slaveAdd, unsigned regIndex, int nb, unsigned **data) {
	unsigned cval;
	int i;
	unsigned *bloc;

	int 	 base = getBusBase(bus);

	if (i2c_multReadMemInit(dev, bus, slaveAdd, regIndex) != 0)
			return(-1);
	bloc = malloc(nb*sizeof(unsigned));
	if (bloc==0){
		perror("Can't malloc in i2c_multReadMem()\n");
		return(-1);
	}
/*	printf("Reading bytes at slave add 0x%x (%d) starting at internal address 0x%x (%d)\n", 
						slaveAdd, slaveAdd, regIndex, regIndex);
*/
	// Read and display values
	cval = I2C_RD;
//	printf("PYD read loop\n");
	for (i=0; i<(nb-1); i++){
		ecs_iowrI2c_slow(dev, base +  (I2C_CMDREG*4), &cval);
		// wait for TIP flag in statusReg
		if ( i2c_waitTIP(dev, bus) != 0)
			return(-1);
		ecs_iordI2c_slow(dev, base +  (I2C_RCVREG*4), &bloc[i]);
//		printf("PYD 0x%x ");
	}
//	printf("PYD\n");

	// last byte to transfer
	cval = I2C_RD | I2C_NACK | I2C_STO;
	ecs_iowrI2c_slow(dev, base +  (I2C_CMDREG*4), &cval);
	// wait for TIP flag in statusReg
		if ( i2c_waitTIP(dev, bus) != 0)
			return(-1);
	ecs_iordI2c_slow(dev, base +  (I2C_RCVREG*4), &bloc[nb-1]);
	*data = bloc;
	return(0);
}

#ifdef MAIN_DRIVER
int main(){
	unsigned          val, i2cAdd;
	unsigned          cval[3];
	int               i, loop;
	unsigned val1[]   = { 0x4, 0x5, 0xc0 };
	unsigned val2[]   = { 0xa, 0xb, 0x00 };
	unsigned i2cAddTab[] = {0x28, 0x31, 0x2A, 0x33, 0x2C, 0x35};
	unsigned *data;
	int base;
	int dev = 0;

	if (ecs_openLli(dev) != 0){
		perror("Can't access i2c ocore\n");
		exit(0);
	}
	printf("TEST on PCIe access to ocore regsiters\n");
	printf("======================================\n");
	base = I2C_BASE_0;

	// raw test for pcie access to opencore registers
	ecs_iordI2c(dev, base +  (I2C_PRELOREG*4), &cval[0]);
	ecs_iordI2c(dev, base +  (I2C_PREHIREG*4), &cval[1]);
	ecs_iordI2c(dev, base +  (I2C_CTRLREG*4),  &cval[2]);
	printf("Before ...\n");
	for (i=0; i<3; i++)
		printf("Ox%x ", cval[i]);
	printf("\n");
	
	ecs_iowrI2c(dev, base +  (I2C_PRELOREG*4), &val1[0]);
	ecs_iowrI2c(dev, base +  (I2C_PREHIREG*4), &val1[1]);
	ecs_iowrI2c(dev, base +  (I2C_CTRLREG*4),  &val1[2]);
	printf("After first loop ... should be equal\n");
	ecs_iordI2c(dev, base +  (I2C_PRELOREG*4), &cval[0]);
	ecs_iordI2c(dev, base +  (I2C_PREHIREG*4), &cval[1]);
	ecs_iordI2c(dev, base +  (I2C_CTRLREG*4),  &cval[2]);
	for (i=0; i<3; i++)
		printf(" Ox%x =?= 0x%x |", cval[i], val1[i]);
	printf("\n");
	
	exit(0);
	
	ecs_iowrI2c(dev, base +  (I2C_PRELOREG*4), &val2[0]);
	ecs_iowrI2c(dev, base +  (I2C_PREHIREG*4), &val2[1]);
	ecs_iowrI2c(dev, base +  (I2C_CTRLREG*4),  &val2[2]);
	printf("After second loop ... should be equal\n");
	ecs_iordI2c(dev, base +  (I2C_PRELOREG*4), &cval[0]);
	ecs_iordI2c(dev, base +  (I2C_PREHIREG*4), &cval[1]);
	ecs_iordI2c(dev, base +  (I2C_CTRLREG*4),  &cval[2]);
	for (i=0; i<3; i++)
		printf("Ox%x =?= 0x%x |", cval[i], val2[i]);
	printf("\n");

	printf("\nTEST on I2C access to avago registers\n");
	printf("=====================================\n");
	// init and set address for TX 0
//	i2c_init(dev, 100000000, 100000); // for TCL/TK because jtag master set this clock
	i2c_init(dev, 125000000, 100000); // fast clock with PCI
//	i2c_init(dev, 62500000, 100000); // slow clock with PCI
	// set i2c address of avago number 0 (a TX)
	printf("Select avago number 0 (a TX) as target\n");
	i2cAdd = 5<<3; // comp 0 TX

	printf("Read register 0 should be 0x00 ---> read ");
	val = 0xaa;
	i2c_readMem(dev, i2cAdd, 0, &val);
	printf("(0x%x)\n", val);
	
	
	printf("Write NULL in page select register\n");
	val = 0; // select page 0
	i2c_writeMem(dev, i2cAdd, 127, &val);
	printf("Read read page select register should be NULL ---> read ");
	val = 0xaa;
	i2c_readMem(dev, i2cAdd, 127, &val);
	printf("(0x%x)\n", val);
	
	printf("Write 1 in page select register\n");
	val = 1; // select page 0
	i2c_writeMem(dev, i2cAdd, 127, &val);
	printf("Read read page select register should be 1 ---> read ");
	val = 0xaa;
	i2c_readMem(dev, i2cAdd, 127, &val);
	printf("(0x%x)\n", val);
	
	printf("Write NULL in page select register\n");
	val = 0; // select page 0
	i2c_writeMem(dev, i2cAdd, 127, &val);
	printf("Read read page select register should be NULL ---> read ");
	val = 0xaa;
	i2c_readMem(dev, i2cAdd, 127, &val);
	printf("(0x%x)\n", val);
	
	printf("Write 0xff in register 94 squelch\n");
	val = 0xff; // select page 0
	i2c_writeMem(dev, i2cAdd, 94, &val);
	printf("Read squelch ---> read ");
	val = 0xaa;
	i2c_readMem(dev, i2cAdd, 94, &val);
	printf("(0x%x)\n", val);
	
	printf("Write 0xff in register 95 squelch\n");
	val = 0xff; // select page 0
	i2c_writeMem(dev, i2cAdd, 95, &val);
	printf("Read squelch ---> read ");
	val = 0xaa;
	i2c_readMem(dev, i2cAdd, 95, &val);
	printf("(0x%x)\n", val);
	
	printf("Read Vendor Name\n");
	loop = 16;
	// test to read vendor name at reg 152 to 167 (16bytes)
	// in module at address 0
	for (i=0; i<loop; i++){
		val = 1;
		i2c_readMem(dev, i2cAdd, 152+i, &val);
//		printf("0x%x %c ", val, (char)val);
		printf("%c", (char)val);
	}
	printf("\n");

	i2c_multReadMem(dev, i2cAdd, 152, 16, &data);
	for (i=0; i<loop; i++)
		printf("%c", (char)data[i]);
	printf("\n");

return(0);
}
#endif