usb 的event 和 io 信息的enqueue & deuqueue

  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);

        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);
        //分配event buf的dma地址

        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;
                }
                //将event buf 的dma 物理地址写入寄存器
                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);
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值