📄 i2c.c
字号:
/****************************** MX1 I2C / iMagic Driver*******************************/#include <asm/hardware.h>#include <asm/arch/AT91RM9200_TWI.h>#include <asm/arch/pio.h>#include <asm/delay.h>#include "i2c.h"//#include <asm/arch/at91rm9200dk.h>//#define I2C_CLKDIV 0x17 //(100kbps for 96MHz BCLK)#define I2C_CLKDIV 0x13// Sensor Slave Address#define UDA1380_ADD (0x30/2)//#define UDA1380_ADD (0x34/2)#if 10#define PDEBUG printk#else#define PDEBUG#endifvoid UDA1380_SetTwiClock(unsigned int mck_khz){ int sclock; /* Here, CKDIV = 1 and CHDIV=CLDIV ==> CLDIV = CHDIV = 1/4*((Fmclk/FTWI) -6) */ sclock = (10 * mck_khz / 400); if (sclock % 10 >= 5) sclock = (sclock / 10) - 5; else sclock = (sclock / 10) - 6; sclock = (sclock + (4 - sclock % 4)) >> 2; // div 4 ((AT91PS_TWI) AT91C_VA_BASE_TWI)->TWI_CWGR = 0x00010000 | sclock | (sclock << 8);}void port_init_I2C(void){ AT91PS_TWI twi = (AT91PS_TWI) AT91C_VA_BASE_TWI; struct at91_i2c_local *device; int rc; AT91_CfgPIO_TWI();#if 10/*reset 1380*/ AT91_SYS->PIOB_PER = AT91C_PB2_TD0; AT91_SYS->PIOB_OER = AT91C_PB2_TD0; AT91_SYS->PIOB_OWER = AT91C_PB2_TD0; AT91_SYS->PIOB_SODR = AT91C_PB2_TD0; udelay(1000); AT91_SYS->PIOB_CODR = AT91C_PB2_TD0; udelay(1000); AT91_SYS->PIOB_ODSR &= ~AT91C_PB2_TD0; udelay(1000); udelay(1000);#endif twi->TWI_IDR = 0x1c7; /* Disable all interrupts */ //twi->TWI_IDR = (unsigned int) -1; /* Disable all interrupts */ twi->TWI_CR = AT91C_TWI_SWRST; /* Reset peripheral */ twi->TWI_CR = AT91C_TWI_MSEN;// | AT91C_TWI_SVDIS; /* Set Master mode */ /* Here, CKDIV = 1 and CHDIV=CLDIV ==> CLDIV = CHDIV = 1/4*((Fmclk/FTWI) -6) */ // Set TWI Clock Waveform Generator Register UDA1380_SetTwiClock(900000); // MCK in KHz = 60000 KHz// twi->TWI_CWGR = AT91C_TWI_CKDIV1 | AT91C_TWI_CLDIV3 | (AT91C_TWI_CLDIV3 << 8);// printk("twi->TWI_CWGR = %x\n",// AT91C_TWI_CKDIV1 | AT91C_TWI_CLDIV3 | (AT91C_TWI_CLDIV3 << 8));/*enable timer for i2c*/ AT91_SYS->PMC_PCER = 1 << AT91C_ID_TWI; /* enable peripheral clock */ return;}int I2C_write(char reg_address, unsigned short data_out, int length){ AT91PS_TWI twi = (AT91PS_TWI) AT91C_VA_BASE_TWI; unsigned char *buf = &data_out; int m = 0 , n = 0;// PDEBUG("data to write : buf[0]=%x,buf[1]=%x\n", buf[0], buf[1]); ((AT91PS_TWI) AT91C_VA_BASE_TWI)->TWI_MMR = (AT91C_TWI_MREAD & 0x0) | AT91C_TWI_IADRSZ_1_BYTE | ((UDA1380_ADD << 16) & AT91C_TWI_DADR); ((AT91PS_TWI) AT91C_VA_BASE_TWI)->TWI_IADR = (unsigned int) reg_address; twi->TWI_CR = AT91C_TWI_START; while (length--) { twi->TWI_THR = *buf++; if (!length) twi->TWI_CR = AT91C_TWI_STOP; do { m++; if(m > 1000) { printk("Iic write error!\n"); return 0; } udelay(10); } while (!(twi->TWI_SR & AT91C_TWI_TXRDY)); } /* Wait until transfer is finished */ do { n++; if(n > 1000) { printk("Iic write error!\n"); return 0; } udelay(10); } while (!(twi->TWI_SR & AT91C_TWI_TXCOMP));}/*length should be 2,when read one single register*/int I2C_read(char reg_address, unsigned short *data_in, int length){ int Status, nb_trial, i; unsigned int initial_timeout; unsigned char msb, lsb; unsigned char *buf = data_in; int k = 0 , l = 0 ; AT91PS_TWI twi = (AT91PS_TWI) AT91C_VA_BASE_TWI; ((AT91PS_TWI) AT91C_VA_BASE_TWI)->TWI_MMR = (AT91C_TWI_MREAD) | AT91C_TWI_IADRSZ_1_BYTE | ((UDA1380_ADD << 16) & AT91C_TWI_DADR); ((AT91PS_TWI) AT91C_VA_BASE_TWI)->TWI_IADR = (unsigned int) reg_address; ((AT91PS_TWI) AT91C_VA_BASE_TWI)->TWI_CR = (unsigned int) (AT91C_TWI_START); while (length--) { if (!length) twi->TWI_CR = AT91C_TWI_STOP; /* Wait until transfer is finished */ do{ k++; if(k > 1000) { printk("Iic read error!\n"); return 0; } udelay(10); } while (!(twi->TWI_SR & AT91C_TWI_RXRDY)); *buf++ = twi->TWI_RHR; } do { l++; if(l > 1000) { printk("Iic read error!\n"); return 0; } udelay(10); } while (!(twi->TWI_SR & AT91C_TWI_TXCOMP));}// Test on I2C channel//// Read / write one of the register// compare and verify if the data is correct//unsigned int I2C_test(void){ unsigned int rdata = 0; unsigned int wdata = 0; unsigned int tmpdata = 0; port_init_I2C();/* I2C_read(0x00,&rdata,2); PDEBUG("0x00 init value=%x\n",rdata); I2C_write(0x00,0x0607,2); I2C_read(0x00,&rdata,2); PDEBUG("0x00 is set to=%x\n",rdata);*/ I2C_read(0x12,&rdata,2); PDEBUG("0x12 init value=%x\n",rdata); I2C_write(0x12,0x1562,2); I2C_read(0x12,&rdata,2); PDEBUG("0x12 is set to=%x\n",rdata);#if 0 wdata = 0x55aa; //least 10 bits can be R/W udelay(1000); I2C_write(0x11, wdata, 2); udelay(1000); I2C_read(0x11, &rdata, 2); PDEBUG("rdata: %x\n", rdata); if (rdata == wdata) { printk("I2C test OK\n"); } else { printk("I2C test FAIL\n"); } I2C_write(0x10, tmpdata, 2); I2C_read(0x10, &rdata, 2); PDEBUG("Recover to: %x\n", rdata);#endif return 0; //OK}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -