dwc3 DR_MODE 处理初始化 OTG gadget

 dwc3控制器是怎么处理otg-优快云博客

dwc3_probe


static int dwc3_probe(struct platform_device *pdev)
{
        struct device           *dev = &pdev->dev;
        struct resource         *res, dwc_res;
        struct dwc3             *dwc;

        int                     ret;

        void __iomem            *regs;
        int                     irq;
        char                    dma_ipc_log_ctx_name[40];

        if (count >= DWC_CTRL_COUNT) {
                dev_err(dev, "Err dwc instance %d >= %d available\n",
                                        count, DWC_CTRL_COUNT);
                ret = -EINVAL;
                return ret;
        }

        dwc = devm_kzalloc(dev, sizeof(*dwc), GFP_KERNEL);
        if (!dwc)
                return -ENOMEM;

        dwc->dev = dev;
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
                dev_err(dev, "missing memory resource\n");
                return -ENODEV;
        }

        dwc->reg_phys = res->start;
        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;

        irq = platform_get_irq(to_platform_device(dwc->dev), 0);

        ret = devm_request_irq(dev, irq, dwc3_interrupt, IRQF_SHARED, "dwc3",
                        dwc);
        if (ret) {
                dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
                                irq, ret);
                return -ENODEV;
        }

        if (notify_event)
                /* will be enabled in dwc3_msm_resume() */
                disable_irq(irq);

        dwc->irq = irq;
        /*
         * Request memory region but exclude xHCI regs,
         * since it will be requested by the xhci-plat driver.
         */
        dwc_res = *res;
        dwc_res.start += DWC3_GLOBALS_REGS_START;

        regs = devm_ioremap_resource(dev, &dwc_res);
        if (IS_ERR(regs))
                return PTR_ERR(regs);

        dwc->dwc_wq = alloc_ordered_workqueue("dwc_wq", WQ_HIGHPRI);
        if (!dwc->dwc_wq) {
                dev_err(dev,
                        "%s: Unable to create workqueue dwc_wq\n", __func__);
                goto err0;
        }

        INIT_WORK(&dwc->bh_work, dwc3_bh_work);
        dwc->regs       = regs;
        dwc->regs_size  = resource_size(&dwc_res);
      //解析dtsi 

        dwc3_get_properties(dwc);

        dwc->reset = devm_reset_control_array_get(dev, true, true);
        if (IS_ERR(dwc->reset))
                return PTR_ERR(dwc->reset);

        if (dev->of_node) {
                ret = devm_clk_bulk_get_all(dev, &dwc->clks);
                if (ret == -EPROBE_DEFER)
                        goto err0;
                /*
                 * Clocks are optional, but new DT platforms should support all
                 * clocks as required by the DT-binding.
                 */
                if (ret < 0)
                        dwc->num_clks = 0;
                else
                        dwc->num_clks = ret;

        }

        ret = dwc3_extract_num_phys(dwc);
        if (ret) {
                dev_err(dwc->dev, "Unable to extract number of PHYs\n");
                goto err0;
        }

        dwc->usb2_phy = devm_kzalloc(dwc->dev,
                sizeof(*dwc->usb2_phy) * dwc->num_hsphy, GFP_KERNEL);

        dwc->usb3_phy = devm_kzalloc(dwc->dev,
                sizeof(*dwc->usb3_phy) * dwc->num_ssphy, GFP_KERNEL);

        ret = reset_control_deassert(dwc->reset);
        if (ret)
                goto err0;

        ret = clk_bulk_prepare_enable(dwc->num_clks, dwc->clks);
        if (ret)
                goto assert_reset;

        platform_set_drvdata(pdev, dwc);

        init_waitqueue_head(&dwc->wait_linkstate);
        spin_lock_init(&dwc->lock);

        pm_runtime_no_callbacks(dev);
        pm_runtime_set_active(dev);
        if (dwc->enable_bus_suspend) {
                pm_runtime_set_autosuspend_delay(dev,
                        DWC3_DEFAULT_AUTOSUSPEND_DELAY);
                pm_runtime_use_autosuspend(dev);
        }
        pm_runtime_enable(dev);
        pm_runtime_forbid(dev);

        ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE);
        if (ret) {
                dev_err(dwc->dev, "failed to allocate event buffers\n");
                ret = -ENOMEM;
                goto err1;
        }

        ret = dwc3_alloc_scratch_buffers(dwc);
        if (ret)
                goto err2;

        dwc3_debugfs_init(dwc);
        if (!notify_event) {
                ret = dwc3_core_init(dwc);
                if (ret) {
                        if (ret != -EPROBE_DEFER)
                                dev_err(dev, "failed to initialize core: %d\n",
                                                ret);
                        goto err3;
                }

                ret = dwc3_event_buffers_setup(dwc);
                if (ret) {
                        dev_err(dwc->dev, "failed to setup event buffers\n");
                        goto err3;
                }

                ret = dwc3_core_init_mode(dwc);
                if (ret) {
                        dwc3_event_buffers_cleanup(dwc);
                        goto err3;
                }
        } else if (dwc->dr_mode == USB_DR_MODE_OTG ||
                dwc->dr_mode == USB_DR_MODE_PERIPHERAL) {
                ret = dwc3_gadget_init(dwc);
                if (ret) {
                        dev_err(dwc->dev, "gadget init failed %d\n", ret);
                        goto err3;
                }
        }

        dwc->dwc_ipc_log_ctxt = ipc_log_context_create(NUM_LOG_PAGES,
                                        dev_name(dwc->dev), 0);
        if (!dwc->dwc_ipc_log_ctxt)
                dev_dbg(dwc->dev, "ipc_log_ctxt is not available\n");
        snprintf(dma_ipc_log_ctx_name, sizeof(dma_ipc_log_ctx_name),
                                        "%s.ep_events", dev_name(dwc->dev));
        dwc->dwc_dma_ipc_log_ctxt = ipc_log_context_create(2 * NUM_LOG_PAGES,
                                                dma_ipc_log_ctx_name, 0);
        if (!dwc->dwc_dma_ipc_log_ctxt)
                dev_dbg(dwc->dev, "ipc_log_ctxt for ep_events is not available\n");

        dwc3_instance[count] = dwc;
        dwc->index = count;
        count++;

        pm_runtime_allow(dev);
        return 0;

err3:
        dwc3_debugfs_exit(dwc);
        dwc3_free_scratch_buffers(dwc);
err2:
        dwc3_free_event_buffers(dwc);
err1:
        pm_runtime_allow(&pdev->dev);
        pm_runtime_disable(&pdev->dev);

        clk_bulk_disable_unprepare(dwc->num_clks, dwc->clks);
assert_reset:
        reset_control_assert(dwc->reset);
        destroy_workqueue(dwc->dwc_wq);
err0:
        return ret;
}

 dwc3_core_init_mode dtsi 配置dr_mode = USB_DR_MODE_OTG

static int __maybe_unused dwc3_core_init_mode(struct dwc3 *dwc)
{
        struct device *dev = dwc->dev;
        int ret;

        switch (dwc->dr_mode) {
        case USB_DR_MODE_PERIPHERAL:
                dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE);

                if (dwc->usb2_phy[0])
                        otg_set_vbus(dwc->usb2_phy[0]->otg, false);
                phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_DEVICE);
                phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_DEVICE);

                ret = dwc3_gadget_init(dwc);
                if (ret) {
                        if (ret != -EPROBE_DEFER)
                                dev_err(dev, "failed to initialize gadget\n");
                        return ret;
                }

                dwc->vbus_active = true;
                break;
        case USB_DR_MODE_HOST:
                dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST);

                if (dwc->usb2_phy[0])
                        otg_set_vbus(dwc->usb2_phy[0]->otg, true);
                phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST);
                phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_HOST);

                ret = dwc3_host_init(dwc);
                if (ret) {
                        if (ret != -EPROB
这段代码定义了一个名为 `dwc3_notify_event` 的枚举类型,用于表示 DWC3(DesignWare USB 3.0 超级速度 USB 控制器)的不同通知事件。这些事件用于在 DWC3 控制器的驱动程序中进行事件处理和通信。 下面是每个枚举值的含义和可能的用途: - `DWC3_CONTROLLER_ERROR_EVENT`:表示控制器错误事件,用于处理控制器发生错误的情况。 - `DWC3_CONTROLLER_RESET_EVENT`:表示控制器复位事件,用于处理控制器复位操作。 - `DWC3_CORE_PM_SUSPEND_EVENT`:表示核心挂起事件,用于处理 USB 核心的挂起操作。 - `DWC3_CORE_PM_RESUME_EVENT`:表示核心恢复事件,用于处理 USB 核心的恢复操作。 - `DWC3_CONTROLLER_CONNDONE_EVENT`:表示连接完成事件,用于处理 DWC3 控制器连接完成后的操作。 - `DWC3_CONTROLLER_NOTIFY_OTG_EVENT`:表示 OTG(On-The-Go)通知事件,用于处理 OTG 相关的通知。 - `DWC3_CONTROLLER_SET_CURRENT_DRAW_EVENT`:表示设置当前电流消耗事件,用于设置 DWC3 控制器的当前电流消耗。 - `DWC3_CONTROLLER_NOTIFY_DISABLE_UPDXFER`:表示禁用更新传输事件,用于禁用传输更新。 - `DWC3_CONTROLLER_PULLUP`:表示上拉事件,用于处理 USB 接口的上拉操作。 此外,还有一些与 USB GSI(Generic SuperSpeed Inter-Chip)事件缓冲区相关的通知事件: - `DWC3_GSI_EVT_BUF_ALLOC`:表示事件缓冲区分配事件。 - `DWC3_GSI_EVT_BUF_SETUP`:表示事件缓冲区设置事件。 - `DWC3_GSI_EVT_BUF_CLEANUP`:表示事件缓冲区清理事件。 - `DWC3_GSI_EVT_BUF_CLEAR`:表示事件缓冲区清除事件。 - `DWC3_GSI_EVT_BUF_FREE`:表示事件缓冲区释放事件。 最后,`DWC3_CONTROLLER_NOTIFY_CLEAR_DB` 表示清除数据包通知。 这些枚举值用于在 DWC3 控制器的驱动程序中标识和处理不同的通知事件。具体的使用和含义可能因驱动程序实现和配置而有所不同,需要查阅相关的文档或源代码来了解其具体用法和上下文。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值