linux dwc3 usb驱动分析
基于linux 4.9内核源码:drivers/usb/dw3/core.c主要完成DesignWare USB3.0 Controller phy初始化,以及模式选择。static struct platform_driver dwc3_driver = {.probe= dwc3_probe,.remove= dwc3_remove,.driver= {.name = "dwc3",...
·
基于linux 4.9内核
源码:
drivers/usb/dw3/core.c
主要完成DesignWare USB3.0 Controller phy初始化,以及模式选择。
static struct platform_driver dwc3_driver = {
.probe = dwc3_probe,
.remove = dwc3_remove,
.driver = {
.name = "dwc3",
.of_match_table = of_match_ptr(of_dwc3_match),
.acpi_match_table = ACPI_PTR(dwc3_acpi_match),
.pm = &dwc3_dev_pm_ops,
},
};
static int dwc3_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct resource *res;
struct dwc3 *dwc;
。。。
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); //获取资源
if (!res) {
dev_err(dev, "missing memory resource\n");
return -ENODEV;
}
dwc->xhci_resources[0].start = res->start;
dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
DWC3_XHCI_REGS_END;
dwc->xhci_resources[0].flags = res->flags;
dwc->xhci_resources[0].name = res->name;
res->start += DWC3_GLOBALS_REGS_START;
/*
* Request memory region but exclude xHCI regs,
* since it will be requested by the xhci-plat driver.
*/
regs = devm_ioremap_resource(dev, res); //获取内存空间
dwc->regs = regs;
dwc->regs_size = resource_size(res);
/* default to highest possible threshold */
lpm_nyet_threshold = 0xf;
/* default to -3.5dB de-emphasis */
tx_de_emphasis = 1;
/*
* default to assert utmi_sleep_n and use maximum allowed HIRD
* threshold value of 0b1100
*/
hird_threshold = 12;
//获取默认值,有些是从dts中读取的
dwc->maximum_speed = usb_get_maximum_speed(dev);
dwc->dr_mode = usb_get_dr_mode(dev);
dwc->hsphy_mode = of_usb_get_phy_mode(dev->of_node);
dwc->has_lpm_erratum = device_property_read_bool(dev,
"snps,has-lpm-erratum");
device_property_read_u8(dev, "snps,lpm-nyet-threshold",
&lpm_nyet_threshold);
dwc->is_utmi_l1_suspend = device_property_read_bool(dev,
"snps,is-utmi-l1-suspend");
device_property_read_u8(dev, "snps,hird-threshold",
&hird_threshold);
dwc->usb3_lpm_capable = device_property_read_bool(dev,
"snps,usb3_lpm_capable");
dwc->disable_scramble_quirk = device_property_read_bool(dev,
"snps,disable_scramble_quirk");
dwc->u2exit_lfps_quirk = device_property_read_bool(dev,
"snps,u2exit_lfps_quirk");
dwc->u2ss_inp3_quirk = device_property_read_bool(dev,
"snps,u2ss_inp3_quirk");
dwc->req_p1p2p3_quirk = device_property_read_bool(dev,
"snps,req_p1p2p3_quirk");
dwc->del_p1p2p3_quirk = device_property_read_bool(dev,
"snps,del_p1p2p3_quirk");
dwc->del_phy_power_chg_quirk = device_property_read_bool(dev,
"snps,del_phy_power_chg_quirk");
dwc->lfps_filter_quirk = device_property_read_bool(dev,
"snps,lfps_filter_quirk");
dwc->rx_detect_poll_quirk = device_property_read_bool(dev,
"snps,rx_detect_poll_quirk");
dwc->dis_u3_susphy_quirk = device_property_read_bool(dev,
"snps,dis_u3_susphy_quirk");
dwc->dis_u2_susphy_quirk = device_property_read_bool(dev,
"snps,dis_u2_susphy_quirk");
dwc->dis_enblslpm_quirk = device_property_read_bool(dev,
"snps,dis_enblslpm_quirk");
dwc->dis_rxdet_inp3_quirk = device_property_read_bool(dev,
"snps,dis_rxdet_inp3_quirk");
dwc->dis_u2_freeclk_exists_quirk = device_property_read_bool(dev,
"snps,dis-u2-freeclk-exists-quirk");
dwc->dis_del_phy_power_chg_quirk = device_property_read_bool(dev,
"snps,dis-del-phy-power-chg-quirk");
dwc->tx_de_emphasis_quirk = device_property_read_bool(dev,
"snps,tx_de_emphasis_quirk");
device_property_read_u8(dev, "snps,tx_de_emphasis",
&tx_de_emphasis);
device_property_read_string(dev, "snps,hsphy_interface",
&dwc->hsphy_interface);
device_property_read_u32(dev, "snps,quirk-frame-length-adjustment",
&dwc->fladj);
dwc->lpm_nyet_threshold = lpm_nyet_threshold;
dwc->tx_de_emphasis = tx_de_emphasis;
dwc->hird_threshold = hird_threshold
| (dwc->is_utmi_l1_suspend << 4);
platform_set_drvdata(pdev, dwc);
dwc3_cache_hwparams(dwc);
ret = dwc3_core_get_phy(dwc);
pm_runtime_set_active(dev);
pm_runtime_use_autosuspend(dev);
pm_runtime_set_autosuspend_delay(dev, DWC3_DEFAULT_AUTOSUSPEND_DELAY);
pm_runtime_enable(dev);
ret = pm_runtime_get_sync(dev);
pm_runtime_forbid(dev);
ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); //分配event buf空间
//获取usb mode(dr_mode),otg、host或者device
ret = dwc3_get_dr_mode(dwc);
ret = dwc3_alloc_scratch_buffers(dwc); //分配暂存缓冲区
ret = dwc3_core_init(dwc); //初始化PHY,获取模式
。。。
ret = dwc3_core_init_mode(dwc); //根据mode,分别初始化gadget,host和otg
dwc3_debugfs_init(dwc);
pm_runtime_put(dev);
。。。。。。
return ret;
}
我们看看dwc3_core_init@core.c做了什么?
static int dwc3_core_init(struct dwc3 *dwc)
{
u32 hwparams4 = dwc->hwparams.hwparams4;
u32 reg;
int ret;
。。。。。。
/* issue device SoftReset too */
//软复位
ret = dwc3_soft_reset(dwc);
//初始化phy后如果是device设备再次软复位,host设置直接返回
ret = dwc3_core_soft_reset(dwc);
ret = dwc3_phy_setup(dwc); //PHY接口初始化
。。。
dwc3_core_num_eps(dwc); //获取in,out端点数
ret = dwc3_setup_scratch_buffers(dwc);
if (ret)
goto err1;
/* Adjust Frame Length */
dwc3_frame_length_adjustment(dwc);
usb_phy_set_suspend(dwc->usb2_phy, 0);
usb_phy_set_suspend(dwc->usb3_phy, 0);
ret = phy_power_on(dwc->usb2_generic_phy);
ret = phy_power_on(dwc->usb3_generic_phy); //phy 上电
ret = dwc3_event_buffers_setup(dwc);
if (ret) {
dev_err(dwc->dev, "failed to setup event buffers\n");
goto err4;
}
switch (dwc->dr_mode) { //设置dr模式
case USB_DR_MODE_PERIPHERAL:
dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
break;
case USB_DR_MODE_HOST:
dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST);
break;
case USB_DR_MODE_OTG:
dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
break;
default:
dev_warn(dwc->dev, "Unsupported mode %d\n", dwc->dr_mode);
break;
}
。。。
return ret;
}
dwc3_core_init_mode分别根据不同的模式,调用不同的初始化函数:
static int dwc3_core_init_mode(struct dwc3 *dwc)
{
struct device *dev = dwc->dev;
int ret;
switch (dwc->dr_mode) {
case USB_DR_MODE_PERIPHERAL: //gadget模式
ret = dwc3_gadget_init(dwc);
break;
case USB_DR_MODE_HOST: //主机模式
ret = dwc3_host_init(dwc);
break;
case USB_DR_MODE_OTG: //otg模式
ret = dwc3_host_init(dwc);
ret = dwc3_gadget_init(dwc);
break;
}
return 0;
}
更多推荐
已为社区贡献2条内容
所有评论(0)