MFI调试记录

1. 背景

连接IOS设备,车机发起ipod连接后,上层从MFI芯片的0x30和0x31地址读取鉴权数据失败,mfi驱动log如下:

libipod : CIpodChip::recv, (reg = 0x30) ERROR(errno = 107) !
libipod : CIpodChip::recv, (reg = 0x31) ERROR(errno = 107) !

2.分析

errno 107 : Transport endpoint is not connected
#define ENOTCONN 107 /* Transport endpoint is not connected */

3. 确认以下几件事:

3.1 MFI芯片的设备地址、读写地址设置是否正确?
I2C设备的写地址 = I2C设备地址 << 1
I2C设备的读地址 = (I2C设备地址 << 1) + 1

MFI驱动代码中的设备地址、读写地址设置是对的。

3.2 i2c设备节点是不是固定为I2C-12?

通过i2c tools去探测各个I2C总线上的设备发现,MFI芯片对应地址并非对应I2C-12;

分析I2C驱动框架可知,在设备树中不指定I2C别名的情况下,I2C控制器的注册ID(即I2C-12中的12)是从所有使能的I2C控制设备树节点中最大的ID为基准往后动态分配的,所以MFI芯片对应的I2C控制注册后的节点名不是固定的。

示例如下:

aliases {   
	i2c7 = &i2c_audio;
}

如果所有设备树配置中只配置了一个I2C别名如上,那么其他未设置别名的I2C控制器注册以后就是I2C-8、I2C-9、I2C-10······依次按顺序命名。

4. 解决方案

将MFI设备地址注册ID固定为0,即i2c-0,在aliases 节点中做如下处理即可:

aliases {   
		i2c0 = &i2c_mfi;
            ······
}

关于aliases的详细介绍可以参考博客《aliases节点分析》。

5. 附录

I2C控制器节点动态注册,代码分析如下:

int i2c_add_adapter(struct i2c_adapter *adapter)
{
	struct device *dev = &adapter->dev;
	int id;
 
	if (dev->of_node) {
//获取与这个device_node对应的alias_prop的id。如果以 i2c2 = &i2c2;节点为例,这里得到的id就是2
		id = of_alias_get_id(dev->of_node, "i2c");
		if (id >= 0) {
			adapter->nr = id;
			return __i2c_add_numbered_adapter(adapter);
		}
	}
 //否则动态分配ID并注册,其中__i2c_first_dynamic_bus_num是动态申请ID的基准
	id = idr_alloc(&i2c_adapter_idr, adapter,
		       __i2c_first_dynamic_bus_num, 0, GFP_KERNEL);
 
	adapter->nr = id;
	return i2c_register_adapter(adapter);
}

//__i2c_first_dynamic_bus_num变量是在i2c_init中赋值的
static int __init i2c_init(void)
{
	int retval;
//从所有设备树配置中获取i2c别名中最大的ID值retval 
	retval = of_alias_get_highest_id("i2c");

	down_write(&__i2c_board_lock);
	if (retval >= __i2c_first_dynamic_bus_num)
		__i2c_first_dynamic_bus_num = retval + 1;//赋值
	up_write(&__i2c_board_lock);
    ······
}    

猜你喜欢

转载自blog.csdn.net/qq_41076734/article/details/129009807