Loading Documentation/devicetree/bindings/usb/dwc3.txt +1 −0 Original line number Diff line number Diff line Loading @@ -68,6 +68,7 @@ Optional properties: - snps,usb3-u1u2-disable: If present, disable U1U2 low power modes in Superspeed mode - snps,disable-clk-gating: If present, disable controller's internal clock gating. Default it is enabled. - num-gsi-eps: Number of GSI based hardware accelerated endpoints - in addition all properties from usb-xhci.txt from the current directory are supported as well Loading arch/arm64/boot/dts/qcom/sa515m-ccard-usb-ep.dts +3 −0 Original line number Diff line number Diff line Loading @@ -27,3 +27,6 @@ qcom,use-xbl-boot; }; &usb { qcom,num-gsi-evt-buffs = <0x5>; }; drivers/usb/dwc3/core.c +1 −0 Original line number Diff line number Diff line Loading @@ -1169,6 +1169,7 @@ static void dwc3_get_properties(struct dwc3 *dwc) "snps,usb3-u1u2-disable"); dwc->disable_clk_gating = device_property_read_bool(dev, "snps,disable-clk-gating"); device_property_read_u32(dev, "num-gsi-eps", &dwc->num_gsi_eps); dwc->dis_metastability_quirk = device_property_read_bool(dev, "snps,dis_metastability_quirk"); Loading drivers/usb/dwc3/core.h +2 −0 Original line number Diff line number Diff line Loading @@ -994,6 +994,7 @@ struct dwc3_scratchpad_array { * @bh_handled_evt_cnt: no. of events handled by tasklet per interrupt * @bh_dbg_index: index for capturing bh_completion_time and bh_handled_evt_cnt * @last_run_stop: timestamp denoting the last run_stop update * @num_gsi_eps: number of GSI based hardware accelerated endpoints */ struct dwc3 { struct work_struct drd_work; Loading Loading @@ -1212,6 +1213,7 @@ struct dwc3 { bool host_poweroff_in_pm_suspend; int retries_on_error; ktime_t last_run_stop; u32 num_gsi_eps; }; #define work_to_dwc(w) (container_of((w), struct dwc3, drd_work)) Loading drivers/usb/dwc3/dwc3-msm.c +87 −26 Original line number Diff line number Diff line Loading @@ -330,6 +330,9 @@ struct dwc3_msm { u64 dummy_gsi_db; dma_addr_t dummy_gsi_db_dma; struct device_node *dwc3_node; struct property *num_gsi_eps; }; #define USB_HSPHY_3P3_VOL_MIN 3050000 /* uV */ Loading Loading @@ -3599,6 +3602,62 @@ static int dwc_dpdm_cb(struct notifier_block *nb, unsigned long evt, void *p) return NOTIFY_OK; } static int dwc3_msm_populate_gsi_params(struct dwc3_msm *mdwc) { struct device_node *node = mdwc->dev->of_node; struct device *dev = mdwc->dev; struct property *prop = NULL; const void *p_val; void *value; int size = 0; p_val = of_get_property(node, "qcom,num-gsi-evt-buffs", &size); if (!size) { dev_dbg(dev, "GSI EPs not being used\n"); return 0; } of_property_read_u32(node, "qcom,num-gsi-evt-buffs", &mdwc->num_gsi_event_buffers); value = devm_kzalloc(dev, size, GFP_KERNEL); if (!value) return -ENOMEM; memcpy(value, p_val, size); prop = devm_kzalloc(dev, sizeof(*prop), GFP_KERNEL); if (!prop) return -ENOMEM; prop->name = "num-gsi-eps"; prop->value = value; prop->length = size; mdwc->num_gsi_eps = prop; of_get_property(node, "qcom,gsi-reg-offset", &size); if (!size) { dev_err(dev, "err provide qcom,gsi-reg-offset\n"); return -EINVAL; } mdwc->gsi_reg = devm_kzalloc(dev, size, GFP_KERNEL); if (!mdwc->gsi_reg) return -ENOMEM; mdwc->gsi_reg_offset_cnt = (size / sizeof(*mdwc->gsi_reg)); if (mdwc->gsi_reg_offset_cnt != GSI_REG_MAX) { dev_err(dev, "invalid reg offset count\n"); return -EINVAL; } of_property_read_u32_array(dev->of_node, "qcom,gsi-reg-offset", mdwc->gsi_reg, mdwc->gsi_reg_offset_cnt); return 0; } static int dwc3_msm_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node, *dwc3_node; Loading @@ -3606,7 +3665,7 @@ static int dwc3_msm_probe(struct platform_device *pdev) struct dwc3_msm *mdwc; struct dwc3 *dwc; struct resource *res; int ret = 0, size = 0, i; int ret = 0, i; u32 val; unsigned long irq_type; Loading Loading @@ -3768,31 +3827,9 @@ static int dwc3_msm_probe(struct platform_device *pdev) dev_err(&pdev->dev, "unable to read platform data tx fifo size\n"); ret = of_property_read_u32(node, "qcom,num-gsi-evt-buffs", &mdwc->num_gsi_event_buffers); if (mdwc->num_gsi_event_buffers) { of_get_property(node, "qcom,gsi-reg-offset", &size); if (size) { mdwc->gsi_reg = devm_kzalloc(dev, size, GFP_KERNEL); if (!mdwc->gsi_reg) return -ENOMEM; mdwc->gsi_reg_offset_cnt = (size / sizeof(*mdwc->gsi_reg)); if (mdwc->gsi_reg_offset_cnt != GSI_REG_MAX) { dev_err(dev, "invalid reg offset count\n"); return -EINVAL; } of_property_read_u32_array(dev->of_node, "qcom,gsi-reg-offset", mdwc->gsi_reg, mdwc->gsi_reg_offset_cnt); } else { dev_err(dev, "err provide qcom,gsi-reg-offset\n"); return -EINVAL; } } ret = dwc3_msm_populate_gsi_params(mdwc); if (ret) goto err; mdwc->use_pdc_interrupts = of_property_read_bool(node, "qcom,use-pdc-interrupts"); Loading Loading @@ -3823,10 +3860,23 @@ static int dwc3_msm_probe(struct platform_device *pdev) goto uninit_iommu; } if (mdwc->num_gsi_eps) { mdwc->dwc3_node = dwc3_node; ret = of_add_property(dwc3_node, mdwc->num_gsi_eps); if (ret) { dev_err(&pdev->dev, "failed to add 'num-gsi-eps' prop: %d\n", ret); of_node_put(dwc3_node); goto uninit_iommu; } } ret = of_platform_populate(node, NULL, NULL, &pdev->dev); if (ret) { dev_err(&pdev->dev, "failed to add create dwc3 core\n"); if (mdwc->num_gsi_eps) of_remove_property(dwc3_node, mdwc->num_gsi_eps); of_node_put(dwc3_node); goto uninit_iommu; } Loading Loading @@ -3990,6 +4040,11 @@ static int dwc3_msm_probe(struct platform_device *pdev) platform_device_put(mdwc->dwc3); if (mdwc->bus_perf_client) msm_bus_scale_unregister_client(mdwc->bus_perf_client); if (mdwc->num_gsi_eps) { of_node_get(mdwc->dwc3_node); of_remove_property(mdwc->dwc3_node, mdwc->num_gsi_eps); of_node_put(mdwc->dwc3_node); } uninit_iommu: of_platform_depopulate(&pdev->dev); Loading Loading @@ -4048,6 +4103,12 @@ static int dwc3_msm_remove(struct platform_device *pdev) platform_device_put(mdwc->dwc3); of_platform_depopulate(&pdev->dev); if (mdwc->num_gsi_eps) { of_node_get(mdwc->dwc3_node); of_remove_property(mdwc->dwc3_node, mdwc->num_gsi_eps); of_node_put(mdwc->dwc3_node); } pm_runtime_disable(mdwc->dev); pm_runtime_barrier(mdwc->dev); pm_runtime_put_sync(mdwc->dev); Loading Loading
Documentation/devicetree/bindings/usb/dwc3.txt +1 −0 Original line number Diff line number Diff line Loading @@ -68,6 +68,7 @@ Optional properties: - snps,usb3-u1u2-disable: If present, disable U1U2 low power modes in Superspeed mode - snps,disable-clk-gating: If present, disable controller's internal clock gating. Default it is enabled. - num-gsi-eps: Number of GSI based hardware accelerated endpoints - in addition all properties from usb-xhci.txt from the current directory are supported as well Loading
arch/arm64/boot/dts/qcom/sa515m-ccard-usb-ep.dts +3 −0 Original line number Diff line number Diff line Loading @@ -27,3 +27,6 @@ qcom,use-xbl-boot; }; &usb { qcom,num-gsi-evt-buffs = <0x5>; };
drivers/usb/dwc3/core.c +1 −0 Original line number Diff line number Diff line Loading @@ -1169,6 +1169,7 @@ static void dwc3_get_properties(struct dwc3 *dwc) "snps,usb3-u1u2-disable"); dwc->disable_clk_gating = device_property_read_bool(dev, "snps,disable-clk-gating"); device_property_read_u32(dev, "num-gsi-eps", &dwc->num_gsi_eps); dwc->dis_metastability_quirk = device_property_read_bool(dev, "snps,dis_metastability_quirk"); Loading
drivers/usb/dwc3/core.h +2 −0 Original line number Diff line number Diff line Loading @@ -994,6 +994,7 @@ struct dwc3_scratchpad_array { * @bh_handled_evt_cnt: no. of events handled by tasklet per interrupt * @bh_dbg_index: index for capturing bh_completion_time and bh_handled_evt_cnt * @last_run_stop: timestamp denoting the last run_stop update * @num_gsi_eps: number of GSI based hardware accelerated endpoints */ struct dwc3 { struct work_struct drd_work; Loading Loading @@ -1212,6 +1213,7 @@ struct dwc3 { bool host_poweroff_in_pm_suspend; int retries_on_error; ktime_t last_run_stop; u32 num_gsi_eps; }; #define work_to_dwc(w) (container_of((w), struct dwc3, drd_work)) Loading
drivers/usb/dwc3/dwc3-msm.c +87 −26 Original line number Diff line number Diff line Loading @@ -330,6 +330,9 @@ struct dwc3_msm { u64 dummy_gsi_db; dma_addr_t dummy_gsi_db_dma; struct device_node *dwc3_node; struct property *num_gsi_eps; }; #define USB_HSPHY_3P3_VOL_MIN 3050000 /* uV */ Loading Loading @@ -3599,6 +3602,62 @@ static int dwc_dpdm_cb(struct notifier_block *nb, unsigned long evt, void *p) return NOTIFY_OK; } static int dwc3_msm_populate_gsi_params(struct dwc3_msm *mdwc) { struct device_node *node = mdwc->dev->of_node; struct device *dev = mdwc->dev; struct property *prop = NULL; const void *p_val; void *value; int size = 0; p_val = of_get_property(node, "qcom,num-gsi-evt-buffs", &size); if (!size) { dev_dbg(dev, "GSI EPs not being used\n"); return 0; } of_property_read_u32(node, "qcom,num-gsi-evt-buffs", &mdwc->num_gsi_event_buffers); value = devm_kzalloc(dev, size, GFP_KERNEL); if (!value) return -ENOMEM; memcpy(value, p_val, size); prop = devm_kzalloc(dev, sizeof(*prop), GFP_KERNEL); if (!prop) return -ENOMEM; prop->name = "num-gsi-eps"; prop->value = value; prop->length = size; mdwc->num_gsi_eps = prop; of_get_property(node, "qcom,gsi-reg-offset", &size); if (!size) { dev_err(dev, "err provide qcom,gsi-reg-offset\n"); return -EINVAL; } mdwc->gsi_reg = devm_kzalloc(dev, size, GFP_KERNEL); if (!mdwc->gsi_reg) return -ENOMEM; mdwc->gsi_reg_offset_cnt = (size / sizeof(*mdwc->gsi_reg)); if (mdwc->gsi_reg_offset_cnt != GSI_REG_MAX) { dev_err(dev, "invalid reg offset count\n"); return -EINVAL; } of_property_read_u32_array(dev->of_node, "qcom,gsi-reg-offset", mdwc->gsi_reg, mdwc->gsi_reg_offset_cnt); return 0; } static int dwc3_msm_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node, *dwc3_node; Loading @@ -3606,7 +3665,7 @@ static int dwc3_msm_probe(struct platform_device *pdev) struct dwc3_msm *mdwc; struct dwc3 *dwc; struct resource *res; int ret = 0, size = 0, i; int ret = 0, i; u32 val; unsigned long irq_type; Loading Loading @@ -3768,31 +3827,9 @@ static int dwc3_msm_probe(struct platform_device *pdev) dev_err(&pdev->dev, "unable to read platform data tx fifo size\n"); ret = of_property_read_u32(node, "qcom,num-gsi-evt-buffs", &mdwc->num_gsi_event_buffers); if (mdwc->num_gsi_event_buffers) { of_get_property(node, "qcom,gsi-reg-offset", &size); if (size) { mdwc->gsi_reg = devm_kzalloc(dev, size, GFP_KERNEL); if (!mdwc->gsi_reg) return -ENOMEM; mdwc->gsi_reg_offset_cnt = (size / sizeof(*mdwc->gsi_reg)); if (mdwc->gsi_reg_offset_cnt != GSI_REG_MAX) { dev_err(dev, "invalid reg offset count\n"); return -EINVAL; } of_property_read_u32_array(dev->of_node, "qcom,gsi-reg-offset", mdwc->gsi_reg, mdwc->gsi_reg_offset_cnt); } else { dev_err(dev, "err provide qcom,gsi-reg-offset\n"); return -EINVAL; } } ret = dwc3_msm_populate_gsi_params(mdwc); if (ret) goto err; mdwc->use_pdc_interrupts = of_property_read_bool(node, "qcom,use-pdc-interrupts"); Loading Loading @@ -3823,10 +3860,23 @@ static int dwc3_msm_probe(struct platform_device *pdev) goto uninit_iommu; } if (mdwc->num_gsi_eps) { mdwc->dwc3_node = dwc3_node; ret = of_add_property(dwc3_node, mdwc->num_gsi_eps); if (ret) { dev_err(&pdev->dev, "failed to add 'num-gsi-eps' prop: %d\n", ret); of_node_put(dwc3_node); goto uninit_iommu; } } ret = of_platform_populate(node, NULL, NULL, &pdev->dev); if (ret) { dev_err(&pdev->dev, "failed to add create dwc3 core\n"); if (mdwc->num_gsi_eps) of_remove_property(dwc3_node, mdwc->num_gsi_eps); of_node_put(dwc3_node); goto uninit_iommu; } Loading Loading @@ -3990,6 +4040,11 @@ static int dwc3_msm_probe(struct platform_device *pdev) platform_device_put(mdwc->dwc3); if (mdwc->bus_perf_client) msm_bus_scale_unregister_client(mdwc->bus_perf_client); if (mdwc->num_gsi_eps) { of_node_get(mdwc->dwc3_node); of_remove_property(mdwc->dwc3_node, mdwc->num_gsi_eps); of_node_put(mdwc->dwc3_node); } uninit_iommu: of_platform_depopulate(&pdev->dev); Loading Loading @@ -4048,6 +4103,12 @@ static int dwc3_msm_remove(struct platform_device *pdev) platform_device_put(mdwc->dwc3); of_platform_depopulate(&pdev->dev); if (mdwc->num_gsi_eps) { of_node_get(mdwc->dwc3_node); of_remove_property(mdwc->dwc3_node, mdwc->num_gsi_eps); of_node_put(mdwc->dwc3_node); } pm_runtime_disable(mdwc->dev); pm_runtime_barrier(mdwc->dev); pm_runtime_put_sync(mdwc->dev); Loading