我正在尝试将飞思卡尔 imx6 SoC 与 mpu92/65 传感器设备连接。我从 android ( https://github.com/NoelMacwan/Kernel-10.4.1.B.0.101/tree/master/drivers/staging/iio/imu ) 获取了 mpu92/65 设备驱动程序,并对驱动程序和设备树。
设备树修改:
&i2c3{
...
extaccelerometer: mpu9250@68{
compatible = "mpu9250";
reg = <0x68>;
interrupt-parent = <&gpio2>;
interrupts = <9>;
int_config = /bits/ 8 <0x00>;
level_shifter = /bits/ 8 <0>;
orientation = [ 01 00 00 00 01 00 00 00 01 ];
sec_slave_type = <2>;
sec_slave_id = <0x12>;
secondary_i2c_addr = /bits/ 16 <0x0C>;
secondary_orientation = [ 00 01 00 ff 00 00 00 00 01 ];
};
}
inv_mpu_iio 驱动修改:
static void get_platdata(struct device *dev, struct inv_mpu_iio_s *st){
struct device_node *np = dev->of_node;
int i=0;
of_property_read_u8(np, "int_config", &st->plat_data.int_config);
of_property_read_u8(np, "level_shifter", &st->plat_data.level_shifter);
of_property_read_u8_array(np, "orientation", &st->plat_data.orientation,9);
of_property_read_u32(np, "sec_slave_type", &st->plat_data.sec_slave_type);
of_property_read_u32(np, "sec_slave_id", &st->plat_data.sec_slave_id);
of_property_read_u16(np, "secondary_i2c_addr", &st->plat_data.secondary_i2c_addr);
of_property_read_u8_array(np, "secondary_orientation", &st->plat_data.secondary_orientation,9);
}
static int inv_mpu_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
.....
if (client->dev.of_node) {
get_platdata(&client->dev, st);
} else {
st->plat_data = *(struct mpu_platform_data *)dev_get_platdata(&client->dev);
}
.....
}
我已经以上述方式从设备树中检索了平台数据。在探测功能中,我得到了client->irq=0
. 但是我已经提到了设备树中的 IRQ。请有人告诉我我还需要做什么才能提到 gpio2-9 (linux pad) 作为这个 i2c 设备的中断线。
0x68 是 i2c 设备的从地址。驱动程序探测功能正在尝试写入设备以验证最初的芯片类型。因此,从站的数据和地址被发送到适配器驱动程序,在适配器驱动程序启动函数中,对控制和状态寄存器的写入和读取成功执行。
static int i2c_imx_start(struct imx_i2c_struct *i2c_imx)
{
unsigned int temp = 0;
int result;
dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
i2c_imx_set_clk(i2c_imx);
result = clk_prepare_enable(i2c_imx->clk);
if (result)
return result;
imx_i2c_write_reg(i2c_imx->ifdr, i2c_imx, IMX_I2C_IFDR,__func__);
/* Enable I2C controller */
imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR,__func__);
imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode, i2c_imx, IMX_I2C_I2CR,__func__);
/* Wait controller to be stable */
udelay(50);
/* Start I2C transaction */
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
temp |= I2CR_MSTA;
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR,__func__);
result = i2c_imx_bus_busy(i2c_imx, 1);
if (result)
return result;
i2c_imx->stopped = 0;
temp |= I2CR_IIEN | I2CR_MTX | I2CR_TXAK;
temp &= ~I2CR_DMAEN;
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR,__func__);
return result;
}
然后适配器驱动程序写入数据寄存器
imx_i2c_write_reg(msgs->addr << 1, i2c_imx, IMX_I2C_I2DR,__func__);
在此之后生成适配器中断(总线中断得到 i2c3:291)。
static irqreturn_t i2c_imx_isr(int irq, void *dev_id)
{
struct imx_i2c_struct *i2c_imx = dev_id;
unsigned int temp;
printk("irq:%d\n",irq);
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
if (temp & I2SR_IIF) {
/* save status register */
i2c_imx->i2csr = temp;
temp &= ~I2SR_IIF;
printk("temp=%d\n",temp);
temp |= (i2c_imx->hwdata->i2sr_clr_opcode & I2SR_IIF);
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR,__func__);
wake_up(&i2c_imx->queue);
return IRQ_HANDLED;
}
return IRQ_NONE;
}
在读取状态寄存器后的 ISR 中,该值应为162
(最后一位应0
表示已确认),但对于我的设备,我得到此值163
(最后一位为 1,因此未确认)。然后在确认成功函数-EIO
中抛出错误。对于连接到该总线的所有其他设备,写入数据寄存器后的状态寄存器为162
。
我不知道为什么我会得到上述行为。还有一件事是,即使我没有连接设备,启动功能也能够写入和读取状态和控制寄存器。我不确定正在读取和写入哪个状态寄存器。如果我假设这会写入和读取适配器寄存器,那么我是否也可以假设适配器硬件自动读取和写入连接的设备。如果是这样,那么如果我不连接设备,我将如何获得相同的行为?
请帮帮我。