diff --git a/Lib/src/ltc2990/i2c_ltc2990_lib.c b/Lib/src/ltc2990/i2c_ltc2990_lib.c deleted file mode 100644 index 090488922db5f5ffc555b151aaf56c6e1ae8a46c..0000000000000000000000000000000000000000 --- a/Lib/src/ltc2990/i2c_ltc2990_lib.c +++ /dev/null @@ -1,294 +0,0 @@ -/****************************************************************************************//** -* \file i2c_ltc2990_lib.c -* -* \brief This file contains the user driver to control the 3 ltc2990 ADC components. -* -* \author MJ/PYD -* \version 0.1 -* \date : 15/03/2016 -* \copyright (c) Copyright CERN for the benefit of the LHCb Collaboration. -* Distributed under the terms of the GNU General Public Licence V3. -* ana.py script is free and open source software. -* -* CHANGELOG -* PYD : 15/03/2016 initial version -* PYD : 16/09/2016 use multiple boards -*//********************************************************************************************/ -#include <stdio.h> -#include <unistd.h> -#include <stdlib.h> - -#include <systemConfig.h> -#include <i2cDriver.h> -#include <ltc2990.h> - -// Temporisation Fernand Raynaud pour basculer entre 2 modes -//TEMPO_FERNAND 0.3 -#define BUS_DELAY 300000 - -// usefull for configuration functions -# define trigger 0x7F - -/***********************************************************************//** - * \fn int setConfig(int dev, int bus, unsigned add, unsigned config) - * \brief Function to configure the component - * - * 1) Apply the configuration - * 2) Déclenchement du trigger : on met nimporte quelle valeur dans - * TRIGGER_REGISTER, par exemple 0x7F - * je dis 0x7F car apparement le bit 7 du TRIGGER_REGISTER reste - * toujours à 0, donc la relecture est erronee... - * - * 3) 13/01/2015 : on met une tempo car lorsque l'on change de mode, - * car on a observé que l'on doit attendre un certain temps - * (au sens etymologique de fernand raynaud...) pour basculer - * - * \param bus : the i2c bus number - * \param add : the component add on the i2c bus - * \param config : the value of the config word - * \return 1 success, 0 error - *//***********************************************************************/ -static int setConfig(int dev, int bus, unsigned add, unsigned config){ - unsigned val = trigger; -// int i2c_writeMem(int bus, unsigned slaveAdd, unsigned regIndex, unsigned *val) - if ( (i2c_writeMem(dev, bus, add, CONTROL_REGISTER_ADDRESS, &config) == -1) - ||(i2c_writeMem(dev, bus, add, TRIGGER_REGISTER_ADDRESS, &val ) == -1) ){ - printf("Configuration is not OK!!!\n"); - return(0); - } - else { - usleep(BUS_DELAY); -// time.sleep(TEMPO_FERNAND) -// printf("Configuration is OK\n"); - return(1); - } -} -/***********************************************************************//** - * \fn int setConfig2TR(int dev, int bus, int add) - * \brief Function to configure the component for 2 differential temperature, - * \brief probes, mode repeat, temperature en Celsius - * - * CONTROL_REGISTER= 0x1D (0001 1101), c'est à dire: - * Mode[2:0] = 101 = TR1,TR2 - * Mode[4:3] = 11 = All Measurements per Mode[2:0], lectures de registres - * fixees sur TR1,TR2 - * Temperature Format = 0 (Temperature reported in Celsius) - * Repeat/Single = 0 (Repeat Acquisition) - * - * \param bus : the i2c bus number - * \param add : the component add on the i2c bus - * \return 1 success, 0 error - *//***********************************************************************/ -int Config2TR(int dev, int bus, int add){ - printf("ltc2990: onfiguration for 2 TR sensor temperature is running....\n"); - return setConfig(dev, bus, add, 0x1D); -} -/***********************************************************************//** - * \fn int setConfig2TR(int bus, int add) - * \brief Function to configure the component for 2 differential tension reading, - * \brief mode repeat, temperature en Celsius - * - * CONTROL_REGISTER= 0x1E (0001 1110), c'est à dire: - * Mode[2:0] = 101 = lecture de V1-V2, V3-V4 - * Mode[4:3] = 11 = All Measurements per Mode[2:0],lectures de registres - * fixees sur V1-V2, V3-V4 - * Temperature Format = 0 = Temperature reported in Celsius - * Repeat/Single = 0 = Repeat Acquisition - * - * \param bus : the i2c bus number - * \param add : the component add on the i2c bus - * \return 1 success, 0 error - *//***********************************************************************/ -int Config2VoltDif(int dev, int bus, int add){ - printf("ltc2990: ltc2990 configuration for 2 differential voltage is running....\n"); - return setConfig(dev, bus, add, 0x1E); -} -/***********************************************************************//** - * \fn int Config4VoltSingleEnded(int bus, int add) - * \brief Function to configure the component to read 4 tensions single ended, - * \brief mode repeat, temperature en Celsius - * - * CONTROL_REGISTER= 0x1F = 0001 1111, c'est à dire: - * Mode[2:0] = 111 = lecture de V1,V2,V3,V4 - * Mode[4:3] = 11 = All Measurements per Mode[2:0],lectures de registres - * fixées sur V1,V2, V3,V4 - * Temperature Format = 0 = Temperature reported in Celsius - * Repeat/Single = 0 = Repeat Acquisition - * - * Note : it is important to select Celsius temp because even in this config - * we read the circuit internal temperature - * - * \param bus : the i2c bus number - * \param add : the component add on the i2c bus - * \return 1 success, 0 error - *//***********************************************************************/ -int Config4VoltSingleEnded(int dev, int bus, int add){ - printf("ltc2990: configuration for 4 single ended voltage is running..\n"); - return setConfig(dev, bus, add, 0x1F); -} - - -/****************************************************************************//** - * \fn int two_comp13(int nb13bits) - * \brief Function to present the right way a complemented to two in 13 bits value, - * - * All temperatures -internal or TR1 or TR2) are in 13bits complemented to 2. - * So we need this conversion function - * - * \return : the converted value - *//*****************************************************************************/ -//static int two_comp13(int nb13bits){ -static unsigned two_comp13(unsigned nb13bits){ - if (nb13bits > 8191){ - printf("ltc2990: ERROR number is greater than 8191!!!\n"); - nb13bits = 8191; - } - if (nb13bits <= 4095) - return(nb13bits); - else - return(nb13bits-8192); -} -/****************************************************************************//** - * \fn int two_comp15(int nb15bits) - * \brief Function to present the right way a complemented to two in 15 bits value, - * - * All single-ended (V1,V2,V3,V4) or differential (V1-V2, V3-V4) tensions - * are in 15bits complemented to 2. - * So we need this conversion function - * - * \return : the converted value - *//*****************************************************************************/ -static int two_comp15(int nb15bits){ - if (nb15bits > 32767){ - printf("ltc2990: ERROR number is greater than 32767!!!\n"); - nb15bits = 32767; - } - if (nb15bits <= 16383) - return(nb15bits); - else - return(nb15bits-32768); -} -/*************************************************************************************************//** - * \fn float ReadTempOrTension(int bus, int add, int msbReg, int lsbReg, int measureType, int inversion) - * \brief Function to read the temperature or tension in the component - * - * We loop reading the MSB register untill bit 7 switch to 1. - * We apply the mask: - * - when temperature reading to extract D8-D12 bits - * - when tension reading D8-D13 and D14 (sign) - * We read the LSB register to concatenate the two words to get the full value - * We then complement the value to 2 and multiply by a constant factor - * - factor = 0.0625 for temp - * - factor = 0.00030518 for tensions - * - * \param bus : the i2c bus number on the board - * \param add : the component i2c address - * \param msbReg : the msb register index - * \param lsbReg : the lsb register index - * \param measureType : type of measure TEMP or VOLT - * \param inversion : for some components the tension is inverted (1 or 0) - * - * \return read value or 0 if failed - *//*************************************************************************************************/ -static float ReadTempOrTension(int dev, int bus, unsigned add, unsigned msbReg, unsigned lsbReg, enum type_measure measureType, int inversion){ - unsigned mask; - int cpt_timeout = 0; - int DataValidBit = 0; - float factor, RSHUNT, LSB_DIFFERENTIAL; - unsigned LocalTempMSB, dataMSB, dataLSB, dataInteger16; - - if (measureType == TEMP){ - mask = 0b11111; - factor = 0.0625; - } - else { - mask = 0b1111111; - factor = 0.00030518; - } -// On divise ensuite par la valeur de la resistance de shunt ( -// supposee egale a 0.003 ohm) pour avoir la valeur du courant IPEX09V - if (inversion == 1){ - RSHUNT = 0.003; - LSB_DIFFERENTIAL = 0.00001942; - factor = LSB_DIFFERENTIAL/RSHUNT; - } - while (!(DataValidBit)){ -// int i2c_readMem(int bus, unsigned slaveAdd, unsigned regIndex, unsigned *val) - if (i2c_readMem(dev, bus, add, msbReg, &LocalTempMSB) != 0){ - printf("ReadTempOrTension : error readihg i2c register\n"); - return(0); - } -// LocalTempMSB = i2c.read(bus, add, msbReg)[1] - DataValidBit = (0b10000000) & LocalTempMSB; - cpt_timeout = cpt_timeout + 1; - if (cpt_timeout > 1000){ - printf("ReadTempOrTension : Error Timeout to read\n"); - break; - } - } - dataMSB = LocalTempMSB & mask; - -// dataLSB = i2c.read(bus, add, lsbReg)[1] - if (i2c_readMem(dev, bus, add, lsbReg, &dataLSB) != 0){ - printf("ReadTempOrTension : error readihg i2c register\n"); - return(0); - } - dataInteger16 = dataMSB*256 + dataLSB; - if (measureType == TEMP){ - return(two_comp13(dataInteger16)*factor); - } - else { - if (inversion == 1) - return (-two_comp15(dataInteger16)*factor); - else - return (two_comp15(dataInteger16)*factor); - } -} - -float ReadLocalTemperature(int dev, int bus, unsigned add){ - enum type_measure temp = TEMP; - return(ReadTempOrTension(dev, bus, add, TINTMSB_REGISTER_ADDRESS, TINTLSB_REGISTER_ADDRESS, temp, 0)); -} - -float ReadTR1(int dev, int bus,unsigned add){ - enum type_measure temp = TEMP; - return(ReadTempOrTension(dev, bus, add, V1MSB_REGISTER_ADDRESS, V1LSB_REGISTER_ADDRESS, temp, 0)); -} - -float ReadTR2(int dev, int bus,unsigned add){ - enum type_measure temp = TEMP; - return (ReadTempOrTension(dev, bus, add, V3MSB_REGISTER_ADDRESS, V3LSB_REGISTER_ADDRESS, temp, 0)); -} - -float ReadV1(int dev, int bus,unsigned add){ - enum type_measure tens = VOLT; - return(ReadTempOrTension(dev, bus, add, V1MSB_REGISTER_ADDRESS, V1LSB_REGISTER_ADDRESS, tens, 0)); -} - -float ReadV2(int dev, int bus,unsigned add){ - enum type_measure tens = VOLT; - return(ReadTempOrTension(dev, bus, add, V2MSB_REGISTER_ADDRESS, V2LSB_REGISTER_ADDRESS, tens, 0)); -} - -float ReadV3(int dev, int bus,unsigned add){ - enum type_measure tens = VOLT; - return(ReadTempOrTension(dev, bus, add, V3MSB_REGISTER_ADDRESS, V3LSB_REGISTER_ADDRESS, tens, 0)); -} - -float ReadV4(int dev, int bus,unsigned add){ - enum type_measure tens = VOLT; - return(ReadTempOrTension(dev, bus, add, V4MSB_REGISTER_ADDRESS, V4LSB_REGISTER_ADDRESS, tens, 0)); -} - -float ReadIPEX09V(int dev, int bus,unsigned add){ -// Entering this function we have to be in read differential tension mode. - enum type_measure tens = VOLT; - return(ReadTempOrTension(dev, bus, add, V1minV2MSB_REGISTER_ADDRESS, V1minV2LSB_REGISTER_ADDRESS, tens, 1)); -} - -float ReadIPEX09VDDA(int dev, int bus,unsigned add){ -// Entering this function we have to be in read differential tension mode. - enum type_measure tens = VOLT; - return (ReadTempOrTension(dev, bus, add, V3minV4MSB_REGISTER_ADDRESS, V3minV4LSB_REGISTER_ADDRESS, tens, 1)); -} - diff --git a/Lib/src/minipods/i2cDriver.c b/Lib/src/minipods/i2cDriver.c new file mode 100644 index 0000000000000000000000000000000000000000..f75267d0e5fc156ab9652514b98cd65d741f9242 --- /dev/null +++ b/Lib/src/minipods/i2cDriver.c @@ -0,0 +1,656 @@ +/****************************************************************************************//** +* \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 + +