在调试mipi转换芯片的时候总是需要使用i2c对其进行初始化,kernel阶段好办,一般高通平台提供较为完整的i2c操作方法,只需要配置一下i2c地址就可以建立相应的i2c设备。
但是lk阶段就不尽人意了。比如在此案例中,msm8937平台的lk阶段并没有配置i2c接口,只好使用模拟i2c一劳永逸。遂,写了一个简单的模拟i2c读写接口,代码如下,仅供参考学习。已测试可以使用。另外附录i2c子协议smbus-protocol(kernel/msm-3.18/Documentation/i2c/smbus-protocol)。
#include
#include
#include
#include
#include
#include //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<=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
smbus-protocol
SMBus Protocol Summary
======================
The following is a summary of the SMBus protocol. It applies to
all revisions of the protocol (1.0, 1.1, and 2.0).
Certain protocol features which are not supported by
this 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 use
only 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 SMBus
commands if at all possible (if the device uses only that subset of the
I2C protocol). This makes it possible to use the device driver on both
SMBus adapters and I2C adapters (the SMBus command set is automatically
translated to I2C on I2C adapters, but plain I2C commands can not be
handled at all on most pure SMBus adapters).
Below is a list of SMBus protocol operations, and the functions executing
them. Note that the names used in the SMBus protocol specifications usually
don't match these function names. For some of the operations which pass a
single data byte, the functions using SMBus protocol operation names execute
a different protocol operation entirely.
Each transaction type corresponds to a functionality flag. Before calling a
transaction function, a device driver should always check (just once) for
the corresponding functionality flag to ensure that the underlying I2C
adapter supports the transaction in question. See
for the details.
Key to symbols
==============
S (1 bit) : Start bit
P (1 bit) : Stop bit
Rd/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] P
Functionality flag: I2C_FUNC_SMBUS_QUICK
SMBus Receive Byte: i2c_smbus_read_byte()
==========================================
This reads a single byte from a device, without specifying a device
register. Some devices are so simple that this interface is enough; for
others, it is a shorthand if you want to read the same register as in
the previous SMBus command.
S Addr Rd [A] [Data] NA P
Functionality flag: I2C_FUNC_SMBUS_READ_BYTE
SMBus Send Byte: i2c_smbus_write_byte()
========================================
This operation is the reverse of Receive Byte: it sends a single byte
to a device. See Receive Byte for more information.
S Addr Wr [A] Data [A] P
Functionality flag: I2C_FUNC_SMBUS_WRITE_BYTE
SMBus 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 P
Functionality flag: I2C_FUNC_SMBUS_READ_BYTE_DATA
SMBus Read Word: i2c_smbus_read_word_data()
============================================
This operation is very like Read Byte; again, data is read from a
device, from a designated register that is specified through the Comm
byte. 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 P
Functionality flag: I2C_FUNC_SMBUS_READ_WORD_DATA
Note the convenience function i2c_smbus_read_word_swapped is
available for reads where the two data bytes are the other way
around (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. The
register is specified through the Comm byte. This is the opposite of
the Read Byte operation.
S Addr Wr [A] Comm [A] Data [A] P
Functionality flag: I2C_FUNC_SMBUS_WRITE_BYTE_DATA
SMBus Write Word: i2c_smbus_write_word_data()
==============================================
This is the opposite of the Read Word operation. 16 bits
of data is written to a device, to the designated register that is
specified through the Comm byte.
S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] P
Functionality flag: I2C_FUNC_SMBUS_WRITE_WORD_DATA
Note the convenience function i2c_smbus_write_word_swapped is
available for writes where the two data bytes are the other way
around (not SMBus compliant, but very popular.)
SMBus Process Call:
===================
This command selects a device register (through the Comm byte), sends
16 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 P
Functionality flag: I2C_FUNC_SMBUS_PROC_CALL
SMBus 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 amount
of 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 P
Functionality flag: I2C_FUNC_SMBUS_READ_BLOCK_DATA
SMBus 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 the
Comm 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] P
Functionality flag: I2C_FUNC_SMBUS_WRITE_BLOCK_DATA
SMBus Block Write - Block Read Process Call
===========================================
SMBus Block Write - Block Read Process Call was introduced in
Revision 2.0 of the specification.
This command selects a device register (through the Comm byte), sends
1 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 P
Functionality flag: I2C_FUNC_SMBUS_BLOCK_PROC_CALL
SMBus Host Notify
=================
This command is sent from a SMBus device acting as a master to the
SMBus host acting as a slave.
It is the same form as Write Word, with the command code replaced by the
alerting 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, immediately
before the terminating STOP.
Address Resolution Protocol (ARP)
=================================
The Address Resolution Protocol was introduced in Revision 2.0 of
the specification. It is a higher-layer protocol which uses the
messages above.
ARP adds device enumeration and dynamic address assignment to
the protocol. All ARP communications use slave address 0x61 and
require 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 a
single interrupt pin on the SMBus master, while still allowing the master
to 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 the
SMBus 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 transferred
but 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 P
Functionality flag: I2C_FUNC_SMBUS_READ_I2C_BLOCK
I2C 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 the
Comm byte. Note that command lengths of 0, 2, or more bytes are
supported as they are indistinguishable from data.
S Addr Wr [A] Comm [A] Data [A] Data [A] ... [A] Data [A] P
Functionality flag: I2C_FUNC_SMBUS_WRITE_I2C_BLOCK