openbmc开发-->aspeed-->slave-i2c[ast2400]
前言
- 在使用ast2400从机驱动中,当从机设备在被读取时丢失数据,仅仅在偶数时丢失。故对官方驱动做出相应的修改。
- openbmc开发包的使用、ast2400配置、uboot修改、其他驱动、device-tree等修改见其他文档。
- 首次写博客,速度和文档质量不做保障,只保障代码质量,请各位看客谅解。
ast2400 内核修改启用i2c从机模拟eeprom
> Device Drivers > I2C support
[*] I2C slave support
[*] I2C eeprom slave driver
测试驱动
在linux-aspeed/Documentation/i2c/slave-eeprom-backend.rst手册中有描述如何使用slave EEPROM驱动
注:设备树或者其他信息都可以在Documentation目录下找到对应的描述
注意时间差,aspeed官方驱动在读取时ack应答间隔不一致,会导致数据丢失
读取处理时,接收ASPEED_I2CD_INTR_TX_ACK中断和ASPEED_I2CD_INTR_RX_DONE中断状态分时处里了,
本人理解为ACK的接收同样也应触发接收中断,故将终端状态合并ASPEED_I2CD_INTR_TX_ACK|ASPEED_I2CD_INTR_RX_DONE
并进行统一处理
ast2400 i2c-aspeed.c 驱动修改
以下为修改的函数
static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
{
u32 command, irq_handled = 0;
struct i2c_client *slave = bus->slave;
u8 value;
if (!slave)
return 0;
command = readl(bus->base + ASPEED_I2C_CMD_REG);
/* Slave was requested, restart state machine. */
if (irq_status & ASPEED_I2CD_INTR_SLAVE_MATCH) {
irq_handled |= ASPEED_I2CD_INTR_SLAVE_MATCH;
bus->slave_state = ASPEED_I2C_SLAVE_START;
}
/* Slave is not currently active, irq was for someone else. */
if (bus->slave_state == ASPEED_I2C_SLAVE_INACTIVE)
return irq_handled;
dev_dbg(bus->dev, "slave irq status 0x%08x, cmd 0x%08x\n",
irq_status, command);
/* Slave was sent something. */
if (irq_status & ASPEED_I2CD_INTR_RX_DONE) {
value = readl(bus->base + ASPEED_I2C_BYTE_BUF_REG) >> 8;
/* Handle address frame. */
if (bus->slave_state == ASPEED_I2C_SLAVE_START) {
if (value & 0x1)
bus->slave_state =
ASPEED_I2C_SLAVE_READ_REQUESTED;
else
bus->slave_state =
ASPEED_I2C_SLAVE_WRITE_REQUESTED;
}
irq_handled |= ASPEED_I2CD_INTR_RX_DONE;
}
/* Slave was asked to stop. */
if</