目录
1.实例分析
a. 设备树实例
b. 驱动实例
2. amba匹配流程
a. 创建amba_device
b. 确定总线以及总线的匹配函数
c. 分析总线的匹配函数
1.实例分析
a. 设备树实例
serial@7e201000 {
compatible = "brcm,bcm2835-pl011\0arm,pl011\0arm,primecell"; //创建amba_device
reg = <0x7e201000 0x200>;
interrupts = <0x02 0x19>;
clocks = <0x03 0x13 0x03 0x14>;
clock-names = "uartclk\0apb_pclk";
arm,primecell-periphid = <0x241011>; // 用于匹配amba_driver 的id_table
cts-event-workaround;
pinctrl-names = "default";
pinctrl-0 = <0x08 0x09>;
status = "okay";
phandle = <0x21>;
};
b. 驱动实例
static const struct amba_id pl011_ids[] = {
{
.id = 0x00041011,
.mask = 0x000fffff,
.data = &vendor_arm,
},
{ 0, 0 },
};static struct amba_driver pl011_driver = {
.drv = {
.name = "uart-pl011",
.pm = &pl011_dev_pm_ops,
.suppress_bind_attrs = IS_BUILTIN(CONFIG_SERIAL_AMBA_PL011),
},
.id_table = pl011_ids,
.probe = pl011_probe,
.remove = pl011_remove,
};
2. amba匹配流程
总结
a.创建amba_device,
并根据设备树的 “arm,primecell-periphid”属性 填充 amba_device 的periphid
b. 使用amba_device 的periphid 去匹配 amba_driver的id_table
a. 创建amba_device
b. 确定总线以及总线的匹配函数
a. 确定总线为 amba_bustype
of_amba_device_create
->amba_device_alloc
->amba_device_initialize
static void amba_device_initialize(struct amba_device *dev, const char *name)
{
...
dev->dev.bus = &amba_bustype;
....
}
b. 确定amba总线的匹配函数为amba_match
struct bus_type amba_bustype = {
...
.match = amba_match,
...
};
c. 分析总线的匹配函数
使用amba_device->periphid 与 amba_driver->id_table数组进行匹配
static int amba_match(struct device *dev, struct device_driver *drv)
{
struct amba_device *pcdev = to_amba_device(dev);
struct amba_driver *pcdrv = to_amba_driver(drv);
/* When driver_override is set, only bind to the matching driver */
if (pcdev->driver_override)
return !strcmp(pcdev->driver_override, drv->name);
return amba_lookup(pcdrv->id_table, pcdev) != NULL;
}
static const struct amba_id *
amba_lookup(const struct amba_id *table, struct amba_device *dev)
{
int ret = 0;
while (table->mask) {
ret = (dev->periphid & table->mask) == table->id;
if (ret)
break;
table++;
}
return ret ? table : NULL;
}