高通LK阶段使用模拟i2c--附i2c子协议smbus-protocol

来源:互联网 发布:ettercap js 编辑:程序博客网 时间:2024/06/06 03:51

在调试mipi转换芯片的时候总是需要使用i2c对其进行初始化,kernel阶段好办,一般高通平台提供较为完整的i2c操作方法,只需要配置一下i2c地址就可以建立相应的i2c设备。


但是lk阶段就不尽人意了。比如在此案例中,msm8937平台的lk阶段并没有配置i2c接口,只好使用模拟i2c一劳永逸。遂,写了一个简单的模拟i2c读写接口,代码如下,仅供参考学习。已测试可以使用。另外附录i2c子协议smbus-protocol(kernel/msm-3.18/Documentation/i2c/smbus-protocol)。


#include <platform/gpio.h>#include <debug.h>#include <string.h>#include <smem.h>#include <err.h>#include <qtimer.h>//mdelay#define SDA 6                         //定义SDA所对应的GPIO接口编号  #define SCL 7                         //定义SCL所对应的GPIO接口编号  #define OUTP 1                          //表示GPIO接口方向为输出  #define INP 0                           //表示GPIO接口方向为输入  //void gpio_tlmm_config(uint32_t gpio, uint8_t func,uint8_t dir, uint8_t pull,uint8_t drvstr, uint32_t enable)#define  gpio_set_direction(fuck1,fuck2)  gpio_tlmm_config(fuck1, 0, 1, 0, 3, fuck2) //输出#define  gpio_set_val(fuck1,fuck2)   gpio_set_dir(fuck1, 2*fuck2)/* I2C起始条件 */  int i2c_start()  {  //初始化GPIO口  gpio_set_direction(SDA, OUTP);          //设置SDA方向为输出  gpio_set_direction (SCL, OUTP);         //设置SCL方向为输出  gpio_set_val(SCL, 1);                //设置SDA为高电平  udelay(10);gpio_set_val(SDA, 1);                 //设置SCL为高电平  udelay(10);                            //延时  //起始条件  gpio_set_val(SDA, 0);                 //SCL为高电平时,SDA由高变低  udelay(10);  gpio_set_val(SCL, 0); udelay(10);return 0 ;}  /* I2C终止条件 */  void i2c_stop()  {  gpio_set_val(SCL, 0);  udelay(10);gpio_set_direction(SDA, OUTP);  gpio_set_val(SDA, 0);  udelay(10);  gpio_set_val(SCL, 1);             //SCL高电平时,SDA由低变高  udelay(10);gpio_set_val(SDA, 1);udelay(10);}  /*   I2C读取ACK信号(写数据时使用)  返回值 :0表示ACK信号有效;非0表示ACK信号无效  */  unsigned char i2c_read_ack()  {  unsigned char r;  gpio_set_direction(SDA, INP);           //设置SDA方向为输入  gpio_set_val(SCL,1);              // SCL变低udelay(10);r = gpio_status(SDA);                //读取ACK信号  udelay(10);  gpio_set_val(SCL,0);              // SCL变高  udelay(10);  return r;  }  /* I2C发出ACK信号(读数据时使用) */  int i2c_send_ack()  {  gpio_set_direction(SDA, OUTP);          //设置SDA方向为输出  gpio_set_val(SDA, 0);             //发出ACK信号  udelay(10);  gpio_set_val(SCL,1);              // SCL变高  udelay(10);gpio_set_val(SCL,0); udelay(10);  return 0 ;} int i2c_send_noack()  {  gpio_set_direction(SDA, OUTP);          //设置SDA方向为输出  gpio_set_val(SDA, 1);             //发出ACK信号  udelay(10);  gpio_set_val(SCL,1);              // SCL变高  udelay(10);gpio_set_val(SCL,0); udelay(10);  return 0 ;}  /* I2C字节写 */  void i2c_write_byte(unsigned char b)  {  int i;  gpio_set_direction(SDA, OUTP);          //设置SDA方向为输出  for (i=7; i>=0; i--) {udelay(10);gpio_set_val(SDA, !!(b & (1<<i)));udelay(10);gpio_set_val(SCL, 1);             // SCL变低  udelay(10);  gpio_set_val(SCL, 0);             // SCL变高  } udelay(10); //i2c_read_ack();                 //检查目标设备的ACK信号  }  /* I2C字节读 */  unsigned char i2c_read_byte()  {  int i;  unsigned char r = 0;  gpio_set_direction(SDA, INP);           //设置SDA方向为输入  for (i=7; i>=0; i--) {  gpio_set_val(SCL, 1);         // SCL变低  udelay(10);  r = (r <<1) | gpio_status(SDA);      //从高位到低位依次准备数据进行读取  gpio_set_val(SCL, 0);         // SCL变高  udelay(10);  }  //i2c_send_ack();                 //向目标设备发送ACK信号  return r;  }  /*  I2C读操作  addr:目标设备地址  buf:读缓冲区  len:读入字节的长度  */  void i2c_read(unsigned char addr, unsigned char* buf, int len)  {  int i;  unsigned char t;  i2c_start();                        //起始条件,开始数据通信  //发送地址和数据读写方向  t = (addr << 1) | 1;                    //低位为1,表示读数据  i2c_write_byte(t);  //读入数据  for (i=0; i<len; i++)  buf[i] = i2c_read_byte();  i2c_stop();                     //终止条件,结束数据通信  }  /*  I2C写操作  addr:目标设备地址  buf:写缓冲区  len:写入字节的长度  */  void i2c_write (unsigned char addr, unsigned char* buf, int len)  {  int i;  unsigned char t;  i2c_start();                        //起始条件,开始数据通信  //发送地址和数据读写方向  t = (addr << 1) | 0;                    //低位为0,表示写数据  i2c_write_byte(t);  //写入数据  for (i=0; i<len; i++)  i2c_write_byte(buf[i]);  i2c_stop();                     //终止条件,结束数据通信  }  //S Addr Wr [A] Comm [A] S Addr Rd [A] [Data] NA Punsigned char i2c_read_one(unsigned char Slave_addr, unsigned char addr)  {  unsigned char t,val;  i2c_start();                        //起始条件,开始数据通信 //发送地址和数据读写方向  t = (Slave_addr << 1) | 0;                    //低位为0,表示写数据  //dprintf(CRITICAL, "eliot:!!!! Slave_addr w = 0x%x\n",t);i2c_write_byte(t); i2c_read_ack();//dprintf(CRITICAL, "eliot:!!!! ack1= %d\n",i2c_read_ack());//写入数据   i2c_write_byte(addr); i2c_read_ack();//dprintf(CRITICAL, "eliot:!!!! ack2= %d\n",i2c_read_ack());//i2c_stop(); i2c_start(); //发送地址和数据读写方向  t = (Slave_addr << 1) | 1;                    //低位为1,表示读数据 //dprintf(CRITICAL, "eliot:!!!! Slave_addr r = 0x%x\n",t);i2c_write_byte(t); i2c_read_ack();//dprintf(CRITICAL, "eliot:!!!! ack3= %d\n",i2c_read_ack());//读入数据   val = i2c_read_byte();  i2c_send_noack() ;i2c_stop();                     //终止条件,结束数据通信  return val ;}  //S Addr Wr [A] Comm [A] Data [A] Pvoid i2c_write_one(unsigned char addr, unsigned char val)  {  unsigned char t;  unsigned char Slave_addr = 0x2c;i2c_start();                        //起始条件,开始数据通信 //发送地址和数据读写方向  t = (Slave_addr << 1) | 0;                    //低位为0,表示写数据  //dprintf(CRITICAL, "eliot:!!!! Slave_addr w = 0x%x\n",t);i2c_write_byte(t);  i2c_read_ack();//dprintf(CRITICAL, "eliot:!!!! ack= %d\n",i2c_read_ack());//写入数据   i2c_write_byte(addr); i2c_read_ack();//dprintf(CRITICAL, "eliot:!!!! ack= %d\n",i2c_read_ack());i2c_write_byte(val);  i2c_read_ack();//dprintf(CRITICAL, "eliot:!!!! ack= %d\n",i2c_read_ack());i2c_stop();                     //终止条件,结束数据通信  }  

smbus-protocol

SMBus Protocol Summary======================The following is a summary of the SMBus protocol. It applies toall revisions of the protocol (1.0, 1.1, and 2.0).Certain protocol features which are not supported bythis package are briefly described at the end of this document.Some adapters understand only the SMBus (System Management Bus) protocol,which is a subset from the I2C protocol. Fortunately, many devices useonly the same subset, which makes it possible to put them on an SMBus.If you write a driver for some I2C device, please try to use the SMBuscommands if at all possible (if the device uses only that subset of theI2C protocol). This makes it possible to use the device driver on bothSMBus adapters and I2C adapters (the SMBus command set is automaticallytranslated to I2C on I2C adapters, but plain I2C commands can not behandled at all on most pure SMBus adapters).Below is a list of SMBus protocol operations, and the functions executingthem.  Note that the names used in the SMBus protocol specifications usuallydon't match these function names.  For some of the operations which pass asingle data byte, the functions using SMBus protocol operation names executea different protocol operation entirely.Each transaction type corresponds to a functionality flag. Before calling atransaction function, a device driver should always check (just once) forthe corresponding functionality flag to ensure that the underlying I2Cadapter supports the transaction in question. See<file:Documentation/i2c/functionality> for the details.Key to symbols==============S     (1 bit) : Start bitP     (1 bit) : Stop bitRd/Wr (1 bit) : Read/Write bit. Rd equals 1, Wr equals 0.A, NA (1 bit) : Accept and reverse accept bit. Addr  (7 bits): I2C 7 bit address. Note that this can be expanded as usual to                 get a 10 bit I2C address.Comm  (8 bits): Command byte, a data byte which often selects a register on                the device.Data  (8 bits): A plain data byte. Sometimes, I write DataLow, DataHigh                for 16 bit data.Count (8 bits): A data byte containing the length of a block operation.[..]: Data sent by I2C device, as opposed to data sent by the host adapter.SMBus Quick Command===================This sends a single bit to the device, at the place of the Rd/Wr bit.A Addr Rd/Wr [A] PFunctionality flag: I2C_FUNC_SMBUS_QUICKSMBus Receive Byte:  i2c_smbus_read_byte()==========================================This reads a single byte from a device, without specifying a deviceregister. Some devices are so simple that this interface is enough; forothers, it is a shorthand if you want to read the same register as inthe previous SMBus command.S Addr Rd [A] [Data] NA PFunctionality flag: I2C_FUNC_SMBUS_READ_BYTESMBus Send Byte:  i2c_smbus_write_byte()========================================This operation is the reverse of Receive Byte: it sends a single byteto a device.  See Receive Byte for more information.S Addr Wr [A] Data [A] PFunctionality flag: I2C_FUNC_SMBUS_WRITE_BYTESMBus Read Byte:  i2c_smbus_read_byte_data()============================================This reads a single byte from a device, from a designated register.The register is specified through the Comm byte.S Addr Wr [A] Comm [A] S Addr Rd [A] [Data] NA PFunctionality flag: I2C_FUNC_SMBUS_READ_BYTE_DATASMBus Read Word:  i2c_smbus_read_word_data()============================================This operation is very like Read Byte; again, data is read from adevice, from a designated register that is specified through the Commbyte. But this time, the data is a complete word (16 bits).S Addr Wr [A] Comm [A] S Addr Rd [A] [DataLow] A [DataHigh] NA PFunctionality flag: I2C_FUNC_SMBUS_READ_WORD_DATANote the convenience function i2c_smbus_read_word_swapped isavailable for reads where the two data bytes are the other wayaround (not SMBus compliant, but very popular.)SMBus Write Byte:  i2c_smbus_write_byte_data()==============================================This writes a single byte to a device, to a designated register. Theregister is specified through the Comm byte. This is the opposite ofthe Read Byte operation.S Addr Wr [A] Comm [A] Data [A] PFunctionality flag: I2C_FUNC_SMBUS_WRITE_BYTE_DATASMBus Write Word:  i2c_smbus_write_word_data()==============================================This is the opposite of the Read Word operation. 16 bitsof data is written to a device, to the designated register that isspecified through the Comm byte. S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] PFunctionality flag: I2C_FUNC_SMBUS_WRITE_WORD_DATANote the convenience function i2c_smbus_write_word_swapped isavailable for writes where the two data bytes are the other wayaround (not SMBus compliant, but very popular.)SMBus Process Call:===================This command selects a device register (through the Comm byte), sends16 bits of data to it, and reads 16 bits of data in return.S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A]                              S Addr Rd [A] [DataLow] A [DataHigh] NA PFunctionality flag: I2C_FUNC_SMBUS_PROC_CALLSMBus Block Read:  i2c_smbus_read_block_data()==============================================This command reads a block of up to 32 bytes from a device, from a designated register that is specified through the Comm byte. The amountof data is specified by the device in the Count byte.S Addr Wr [A] Comm [A]            S Addr Rd [A] [Count] A [Data] A [Data] A ... A [Data] NA PFunctionality flag: I2C_FUNC_SMBUS_READ_BLOCK_DATASMBus Block Write:  i2c_smbus_write_block_data()================================================The opposite of the Block Read command, this writes up to 32 bytes to a device, to a designated register that is specified through theComm byte. The amount of data is specified in the Count byte.S Addr Wr [A] Comm [A] Count [A] Data [A] Data [A] ... [A] Data [A] PFunctionality flag: I2C_FUNC_SMBUS_WRITE_BLOCK_DATASMBus Block Write - Block Read Process Call===========================================SMBus Block Write - Block Read Process Call was introduced inRevision 2.0 of the specification.This command selects a device register (through the Comm byte), sends1 to 31 bytes of data to it, and reads 1 to 31 bytes of data in return.S Addr Wr [A] Comm [A] Count [A] Data [A] ...                             S Addr Rd [A] [Count] A [Data] ... A PFunctionality flag: I2C_FUNC_SMBUS_BLOCK_PROC_CALLSMBus Host Notify=================This command is sent from a SMBus device acting as a master to theSMBus host acting as a slave.It is the same form as Write Word, with the command code replaced by thealerting device's address.[S] [HostAddr] [Wr] A [DevAddr] A [DataLow] A [DataHigh] A [P]Packet Error Checking (PEC)===========================Packet Error Checking was introduced in Revision 1.1 of the specification.PEC adds a CRC-8 error-checking byte to transfers using it, immediatelybefore the terminating STOP.Address Resolution Protocol (ARP)=================================The Address Resolution Protocol was introduced in Revision 2.0 ofthe specification. It is a higher-layer protocol which uses themessages above.ARP adds device enumeration and dynamic address assignment tothe protocol. All ARP communications use slave address 0x61 andrequire PEC checksums.SMBus Alert===========SMBus Alert was introduced in Revision 1.0 of the specification.The SMBus alert protocol allows several SMBus slave devices to share asingle interrupt pin on the SMBus master, while still allowing the masterto know which slave triggered the interrupt.This is implemented the following way in the Linux kernel:* I2C bus drivers which support SMBus alert should call  i2c_setup_smbus_alert() to setup SMBus alert support.* I2C drivers for devices which can trigger SMBus alerts should implement  the optional alert() callback.I2C Block Transactions======================The following I2C block transactions are supported by theSMBus layer and are described here for completeness.They are *NOT* defined by the SMBus specification.I2C block transactions do not limit the number of bytes transferredbut the SMBus layer places a limit of 32 bytes.I2C Block Read:  i2c_smbus_read_i2c_block_data()================================================This command reads a block of bytes from a device, from a designated register that is specified through the Comm byte.S Addr Wr [A] Comm [A]            S Addr Rd [A] [Data] A [Data] A ... A [Data] NA PFunctionality flag: I2C_FUNC_SMBUS_READ_I2C_BLOCKI2C Block Write:  i2c_smbus_write_i2c_block_data()==================================================The opposite of the Block Read command, this writes bytes to a device, to a designated register that is specified through theComm byte. Note that command lengths of 0, 2, or more bytes aresupported as they are indistinguishable from data.S Addr Wr [A] Comm [A] Data [A] Data [A] ... [A] Data [A] PFunctionality flag: I2C_FUNC_SMBUS_WRITE_I2C_BLOCK




原创粉丝点击