uboot在init_dm中会扫描dtb和代码中driver进行匹配,匹配成功就调用driver驱动进行bind
以dwc3为例进行介绍
usb0: usb0@ff9d0000 {
#address-cells = <2>;
#size-cells = <2>;
status = "disabled";
compatible = "xlnx,zynqmp-dwc3"; //匹配的compatible
reg = <0x0 0xff9d0000 0x0 0x100>;
clock-names = "bus_clk", "ref_clk";
power-domains = <&pd_usb0>;
ranges;
nvmem-cells = <&soc_revision>;
nvmem-cell-names = "soc_revision";
dwc3_0: dwc3@fe200000 {
compatible = "snps,dwc3";
status = "disabled";
reg = <0x0 0xfe200000 0x0 0x40000>;
interrupt-parent = <&gic>;
interrupts = <0 65 4>, <0 69 4>;
#stream-id-cells = <1>;
iommus = <&smmu 0x860>;
snps,quirk-frame-length-adjustment = <0x20>;
snps,refclk_fladj;
snps,enable_guctl1_resume_quirk;
snps,enable_guctl1_ipd_quirk;
snps,xhci-stream-quirk;
/* dma-coherent; */
};
};
usb1: usb1@ff9e0000 {
#address-cells = <2>;
#size-cells = <2>;
status = "disabled";
compatible = "xlnx,zynqmp-dwc3";
reg = <0x0 0xff9e0000 0x0 0x100>;
clock-names = "bus_clk", "ref_clk";
power-domains = <&pd_usb1>;
ranges;
nvmem-cells = <&soc_revision>;
nvmem-cell-names = "soc_revision";
dwc3_1: dwc3@fe300000 {
compatible = "snps,dwc3";
status = "disabled";
reg = <0x0 0xfe300000 0x0 0x40000>;
interrupt-parent = <&gic>;
interrupts = <0 70 4>, <0 74 4>;
#stream-id-cells = <1>;
iommus = <&smmu 0x861>;
snps,quirk-frame-length-adjustment = <0x20>;
snps,refclk_fladj;
snps,enable_guctl1_resume_quirk;
snps,enable_guctl1_ipd_quirk;
snps,xhci-stream-quirk;
/* dma-coherent; */
};
};
drivers\usb\dwc3\dwc3-generic.c
用于match的compatible
static const struct udevice_id dwc3_generic_ids[] = {
{ .compatible = "xlnx,zynqmp-dwc3" },
{ }
};
定义了driver
U_BOOT_DRIVER(dwc3_generic_wrapper) = {
.name = "dwc3-generic-wrapper",
.id = UCLASS_MISC,
.of_match = dwc3_generic_ids,
.bind = dwc3_generic_bind,
};
compatible = “xlnx,zynqmp-dwc3” ,dts和driver匹配成功,定义driver->bind,即dwc3_generic_bind
static int dwc3_generic_bind(struct udevice *parent)
{
const void *fdt = gd->fdt_blob;
int node;
int ret;
遍历dts中usb device,一个soc可能包含多个usb控制器
for (node = fdt_first_subnode(fdt, parent->of_offset); node > 0;
node = fdt_next_subnode(fdt, node)) {
const char *name = fdt_get_name(fdt, node, NULL);
enum usb_dr_mode dr_mode;
struct udevice *dev;
debug("%s: subnode name: %s\n", __func__, name);
if (strncmp(name, "dwc3@", 4))
continue;
dr_mode = usb_get_dr_mode(node);
//usb 控制器模式,device模式或主机模式
switch (dr_mode) {
case USB_DR_MODE_PERIPHERAL://device模式
case USB_DR_MODE_OTG://otg模式
//进一步进行device和driver匹配,驱动name为 "dwc3-generic-peripheral",
ret = device_bind_driver_to_node(parent,
"dwc3-generic-peripheral",
name, node, &dev);
break;
case USB_DR_MODE_HOST:
debug("%s: dr_mode: HOST\n", __func__);
ret = device_bind_driver_to_node(parent,
"dwc3-generic-host",
name, node, &dev);
break;
default:
break;
};
}
return 0;
}
device_bind_driver_to_node–》device_bind–》device_bind_common:匹配了device和驱动,调用uclass-bind和driver bind。
"dwc3-generic-peripheral"驱动
U_BOOT_DRIVER(dwc3_generic_peripheral) = {
.name = "dwc3-generic-peripheral",
.id = UCLASS_USB_DEV_GENERIC,
.ofdata_to_platdata = dwc3_generic_peripheral_ofdata_to_platdata,
.probe = dwc3_generic_peripheral_probe,
.remove = dwc3_generic_peripheral_remove,
.bind = dwc3_generic_peripheral_bind,
.platdata_auto_alloc_size = sizeof(struct usb_platdata),
.priv_auto_alloc_size = sizeof(struct dwc3),
.flags = DM_FLAG_ALLOC_PRIV_DMA,
};
dwc3_generic_peripheral_bind–》device_probe–》dev->drv->probe》dwc3_generic_peripheral_probe
调用了dwc3_generic_peripheral_probe–》dwc3_init进行dwc3初始化
–》dwc3_core_init_mode–》dwc3_gadget_init–》usb_add_gadget_udc
初始了gadget功能,并向udc core注册。
具体初始化过程不再描述。
完成了底层usb device和驱动初始化,上层抽象功能在进行初始化,比如,网络,鼠标等等。
以fastboot为例,分析function驱动初始注册。
f_fastboot.c
DECLARE_GADGET_BIND_CALLBACK(usb_dnl_fastboot, fastboot_add);
声明定义了g_dnl_bind_callback 结构的fastboot function功能。
/*
* @usb_fname: unescaped USB function name
* @callback_ptr: bind callback, one per function name
*/
#define DECLARE_GADGET_BIND_CALLBACK(usb_fname, callback_ptr) \
ll_entry_declare(struct g_dnl_bind_callback, \
__usb_function_name_##usb_fname, \
g_dnl_bind_callbacks) = { \
.usb_function_name = #usb_fname, \
.fptr = callback_ptr \
}
typedef int (*g_dnl_bind_callback_f)(struct usb_configuration *);
/* used in Gadget downloader callback linker list */
struct g_dnl_bind_callback {
const char *usb_function_name;
g_dnl_bind_callback_f fptr;
};
do_fastboot中调用注册了fastboot驱动,
do_fastboot--》g_dnl_register("usb_dnl_fastboot");--》
g_dnl_driver.name = name;
usb_composite_register(&g_dnl_driver);--》
composite = driver;
usb_gadget_register_driver(&composite_driver);
--》usb_gadget_probe_driver
找到一个udc,前面usb初始化已经向usb core注册了udc
list_for_each_entry(udc, &udc_list, list) {
/* For now we take the first one */
if (!udc->driver)
goto found;
}
ret = udc_bind_to_driver(udc, driver);
---》
driver->bind(udc->gadget); 回调g_dnl_bind
usb_gadget_udc_start(udc); 开启usb func功能,触发usb device和usb host交互
usb_gadget_connect(udc->gadget);
g_dnl_bind–》g_dnl_config_register
一些usb 设备的config
config->label = name;
config->bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER;
config->bConfigurationValue = CONFIGURATION_NUMBER;
config->iConfiguration = STRING_USBDOWN;
config->bind = g_dnl_do_config;
usb_add_config--》config->bind(config);--》 g_dnl_do_config
static int g_dnl_do_config(struct usb_configuration *c)
{
const char *s = c->cdev->driver->name;
struct g_dnl_bind_callback *callback = g_dnl_bind_callback_first();
for (; callback != g_dnl_bind_callback_end(); callback++)
if (!strcmp(s, callback->usb_function_name))
return callback->fptr(c); //回调所有dnl类型的function功能
return -ENODEV;
}
--》fastboot_add进行functiong功能注册
以上过程就是function对应设备接口,配置和端点注册过程
static inline int usb_gadget_udc_start(struct usb_udc *udc)
{
return udc->gadget->ops->udc_start(udc->gadget, udc->driver);
}
fastboot_add功能添加
static int fastboot_add(struct usb_configuration *c)
{
struct f_fastboot *f_fb = fastboot_func;
int status;
debug("%s: cdev: 0x%p\n", __func__, c->cdev);
if (!f_fb) {
f_fb = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*f_fb));
if (!f_fb)
return -ENOMEM;
fastboot_func = f_fb;
memset(f_fb, 0, sizeof(*f_fb));
}
f_fb->usb_function.name = "f_fastboot";
f_fb->usb_function.bind = fastboot_bind;
f_fb->usb_function.unbind = fastboot_unbind;
f_fb->usb_function.set_alt = fastboot_set_alt;
f_fb->usb_function.disable = fastboot_disable;
f_fb->usb_function.strings = fastboot_strings;
status = usb_add_function(c, &f_fb->usb_function);
return status;
}
在接口配置设置时回调f_fb->usb_function.set_alt = fastboot_set_alt;
fastboot_set_alt中配置了端点回调函数,并且使能了端点。
f_fb->out_req->complete = rx_handler_command; 从host接收到usb包,回调函数
f_fb->in_req->complete = fastboot_complete; 发送一个usb包,回调函数
rx_handler_command中解析接收到usb数据,并匹配是否含有定义的fastboot协议命令
static void rx_handler_command(struct usb_ep *ep, struct usb_request *req)
{
char *cmdbuf = req->buf;
void (*func_cb)(struct usb_ep *ep, struct usb_request *req) = NULL;
int i;
匹配命令
for (i = 0; i < ARRAY_SIZE(cmd_dispatch_info); i++) {
if (!strcmp_l1(cmd_dispatch_info[i].cmd, cmdbuf)) {
func_cb = cmd_dispatch_info[i].cb;
break;
}
}
if (req->actual < req->length) {
u8 *buf = (u8 *)req->buf;
buf[req->actual] = 0;
func_cb(ep, req); //处理命令
}
*cmdbuf = '\0';
req->actual = 0;
usb_ep_queue(ep, req, 0);
}
static const struct cmd_dispatch_info cmd_dispatch_info[] = {
{
.cmd = "reboot",
.cb = cb_reboot,
}, {
.cmd = "getvar:",
.cb = cb_getvar,
}, {
.cmd = "download:",
.cb = cb_download,
}, {
.cmd = "boot",
.cb = cb_boot,
}, {
.cmd = "continue",
.cb = cb_continue,
},
#ifdef CONFIG_FASTBOOT_FLASH
{
.cmd = "flash",
.cb = cb_flash,
}, {
.cmd = "erase",
.cb = cb_erase,
},
#endif
{
.cmd = "oem",
.cb = cb_oem,
},
};
上一节分析了fastboot功能的注册。
命令fastboot触发fastboot功能进行初始化注册,并继续后续处理。
U_BOOT_CMD(
fastboot, 2, 1, do_fastboot,
"use USB Fastboot protocol",
"\n"
" - run as a fastboot usb device"
);
static int do_fastboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
{
int controller_index;
char *usb_controller;
int ret;
if (argc < 2)
return CMD_RET_USAGE;
usb_controller = argv[1];
controller_index = simple_strtoul(usb_controller, NULL, 0);
ret = board_usb_init(controller_index, USB_INIT_DEVICE);
if (ret) {
error("USB init failed: %d", ret);
return CMD_RET_FAILURE;
}
g_dnl_clear_detach();
ret = g_dnl_register("usb_dnl_fastboot");
if (ret)
return ret;
if (!g_dnl_board_usb_cable_connected()) {
puts("\rUSB cable not detected.\n" \
"Command exit.\n");
ret = CMD_RET_FAILURE;
goto exit;
}
前面注册usb fastboot驱动
下面是和host交互命令处理
while (1) {
if (g_dnl_detach())
break;
if (ctrlc())
break;
usb_gadget_handle_interrupts(controller_index); 中断处理,处理event buf,回调上面的out_req->complete和in_req->complete
}
ret = CMD_RET_SUCCESS;
return ret;
}