• Home
  • Raw
  • Download

Lines Matching +full:sdm845 +full:- +full:dwc3

1 // SPDX-License-Identifier: GPL-2.0
4 * Inspired by dwc3-of-simple.c
11 #include <linux/clk-provider.h>
44 struct platform_device *dwc3; member
91 dwc3_qcom_setbits(qcom->qscratch_base, QSCRATCH_SS_PHY_CTRL, in dwc3_qcom_vbus_overrride_enable()
93 dwc3_qcom_setbits(qcom->qscratch_base, QSCRATCH_HS_PHY_CTRL, in dwc3_qcom_vbus_overrride_enable()
96 dwc3_qcom_clrbits(qcom->qscratch_base, QSCRATCH_SS_PHY_CTRL, in dwc3_qcom_vbus_overrride_enable()
98 dwc3_qcom_clrbits(qcom->qscratch_base, QSCRATCH_HS_PHY_CTRL, in dwc3_qcom_vbus_overrride_enable()
110 qcom->mode = event ? USB_DR_MODE_PERIPHERAL : USB_DR_MODE_HOST; in dwc3_qcom_vbus_notifier()
122 qcom->mode = event ? USB_DR_MODE_HOST : USB_DR_MODE_PERIPHERAL; in dwc3_qcom_host_notifier()
129 struct device *dev = qcom->dev; in dwc3_qcom_register_extcon()
133 if (!of_property_read_bool(dev->of_node, "extcon")) in dwc3_qcom_register_extcon()
136 qcom->edev = extcon_get_edev_by_phandle(dev, 0); in dwc3_qcom_register_extcon()
137 if (IS_ERR(qcom->edev)) in dwc3_qcom_register_extcon()
138 return PTR_ERR(qcom->edev); in dwc3_qcom_register_extcon()
140 qcom->vbus_nb.notifier_call = dwc3_qcom_vbus_notifier; in dwc3_qcom_register_extcon()
142 qcom->host_edev = extcon_get_edev_by_phandle(dev, 1); in dwc3_qcom_register_extcon()
143 if (IS_ERR(qcom->host_edev)) in dwc3_qcom_register_extcon()
144 qcom->host_edev = NULL; in dwc3_qcom_register_extcon()
146 ret = devm_extcon_register_notifier(dev, qcom->edev, EXTCON_USB, in dwc3_qcom_register_extcon()
147 &qcom->vbus_nb); in dwc3_qcom_register_extcon()
153 if (qcom->host_edev) in dwc3_qcom_register_extcon()
154 host_edev = qcom->host_edev; in dwc3_qcom_register_extcon()
156 host_edev = qcom->edev; in dwc3_qcom_register_extcon()
158 qcom->host_nb.notifier_call = dwc3_qcom_host_notifier; in dwc3_qcom_register_extcon()
160 &qcom->host_nb); in dwc3_qcom_register_extcon()
167 if (extcon_get_state(qcom->edev, EXTCON_USB) || in dwc3_qcom_register_extcon()
169 dwc3_qcom_vbus_notifier(&qcom->vbus_nb, true, qcom->edev); in dwc3_qcom_register_extcon()
171 dwc3_qcom_vbus_notifier(&qcom->vbus_nb, false, qcom->edev); in dwc3_qcom_register_extcon()
178 if (qcom->hs_phy_irq) { in dwc3_qcom_disable_interrupts()
179 disable_irq_wake(qcom->hs_phy_irq); in dwc3_qcom_disable_interrupts()
180 disable_irq_nosync(qcom->hs_phy_irq); in dwc3_qcom_disable_interrupts()
183 if (qcom->dp_hs_phy_irq) { in dwc3_qcom_disable_interrupts()
184 disable_irq_wake(qcom->dp_hs_phy_irq); in dwc3_qcom_disable_interrupts()
185 disable_irq_nosync(qcom->dp_hs_phy_irq); in dwc3_qcom_disable_interrupts()
188 if (qcom->dm_hs_phy_irq) { in dwc3_qcom_disable_interrupts()
189 disable_irq_wake(qcom->dm_hs_phy_irq); in dwc3_qcom_disable_interrupts()
190 disable_irq_nosync(qcom->dm_hs_phy_irq); in dwc3_qcom_disable_interrupts()
193 if (qcom->ss_phy_irq) { in dwc3_qcom_disable_interrupts()
194 disable_irq_wake(qcom->ss_phy_irq); in dwc3_qcom_disable_interrupts()
195 disable_irq_nosync(qcom->ss_phy_irq); in dwc3_qcom_disable_interrupts()
201 if (qcom->hs_phy_irq) { in dwc3_qcom_enable_interrupts()
202 enable_irq(qcom->hs_phy_irq); in dwc3_qcom_enable_interrupts()
203 enable_irq_wake(qcom->hs_phy_irq); in dwc3_qcom_enable_interrupts()
206 if (qcom->dp_hs_phy_irq) { in dwc3_qcom_enable_interrupts()
207 enable_irq(qcom->dp_hs_phy_irq); in dwc3_qcom_enable_interrupts()
208 enable_irq_wake(qcom->dp_hs_phy_irq); in dwc3_qcom_enable_interrupts()
211 if (qcom->dm_hs_phy_irq) { in dwc3_qcom_enable_interrupts()
212 enable_irq(qcom->dm_hs_phy_irq); in dwc3_qcom_enable_interrupts()
213 enable_irq_wake(qcom->dm_hs_phy_irq); in dwc3_qcom_enable_interrupts()
216 if (qcom->ss_phy_irq) { in dwc3_qcom_enable_interrupts()
217 enable_irq(qcom->ss_phy_irq); in dwc3_qcom_enable_interrupts()
218 enable_irq_wake(qcom->ss_phy_irq); in dwc3_qcom_enable_interrupts()
227 if (qcom->is_suspended) in dwc3_qcom_suspend()
230 val = readl(qcom->qscratch_base + PWR_EVNT_IRQ_STAT_REG); in dwc3_qcom_suspend()
232 dev_err(qcom->dev, "HS-PHY not in L2\n"); in dwc3_qcom_suspend()
234 for (i = qcom->num_clocks - 1; i >= 0; i--) in dwc3_qcom_suspend()
235 clk_disable_unprepare(qcom->clks[i]); in dwc3_qcom_suspend()
237 qcom->is_suspended = true; in dwc3_qcom_suspend()
248 if (!qcom->is_suspended) in dwc3_qcom_resume()
253 for (i = 0; i < qcom->num_clocks; i++) { in dwc3_qcom_resume()
254 ret = clk_prepare_enable(qcom->clks[i]); in dwc3_qcom_resume()
256 while (--i >= 0) in dwc3_qcom_resume()
257 clk_disable_unprepare(qcom->clks[i]); in dwc3_qcom_resume()
263 dwc3_qcom_setbits(qcom->qscratch_base, PWR_EVNT_IRQ_STAT_REG, in dwc3_qcom_resume()
266 qcom->is_suspended = false; in dwc3_qcom_resume()
274 struct dwc3 *dwc = platform_get_drvdata(qcom->dwc3); in qcom_dwc3_resume_irq()
277 if (qcom->pm_suspended) in qcom_dwc3_resume_irq()
280 if (dwc->xhci) in qcom_dwc3_resume_irq()
281 pm_runtime_resume(&dwc->xhci->dev); in qcom_dwc3_resume_irq()
288 /* Configure dwc3 to use UTMI clock as PIPE clock not present */ in dwc3_qcom_select_utmi_clk()
289 dwc3_qcom_setbits(qcom->qscratch_base, QSCRATCH_GENERAL_CFG, in dwc3_qcom_select_utmi_clk()
294 dwc3_qcom_setbits(qcom->qscratch_base, QSCRATCH_GENERAL_CFG, in dwc3_qcom_select_utmi_clk()
299 dwc3_qcom_clrbits(qcom->qscratch_base, QSCRATCH_GENERAL_CFG, in dwc3_qcom_select_utmi_clk()
312 ret = devm_request_threaded_irq(qcom->dev, irq, NULL, in dwc3_qcom_setup_irq()
317 dev_err(qcom->dev, "hs_phy_irq failed: %d\n", ret); in dwc3_qcom_setup_irq()
320 qcom->hs_phy_irq = irq; in dwc3_qcom_setup_irq()
326 ret = devm_request_threaded_irq(qcom->dev, irq, NULL, in dwc3_qcom_setup_irq()
331 dev_err(qcom->dev, "dp_hs_phy_irq failed: %d\n", ret); in dwc3_qcom_setup_irq()
334 qcom->dp_hs_phy_irq = irq; in dwc3_qcom_setup_irq()
340 ret = devm_request_threaded_irq(qcom->dev, irq, NULL, in dwc3_qcom_setup_irq()
345 dev_err(qcom->dev, "dm_hs_phy_irq failed: %d\n", ret); in dwc3_qcom_setup_irq()
348 qcom->dm_hs_phy_irq = irq; in dwc3_qcom_setup_irq()
354 ret = devm_request_threaded_irq(qcom->dev, irq, NULL, in dwc3_qcom_setup_irq()
359 dev_err(qcom->dev, "ss_phy_irq failed: %d\n", ret); in dwc3_qcom_setup_irq()
362 qcom->ss_phy_irq = irq; in dwc3_qcom_setup_irq()
370 struct device *dev = qcom->dev; in dwc3_qcom_clk_init()
371 struct device_node *np = dev->of_node; in dwc3_qcom_clk_init()
374 qcom->num_clocks = count; in dwc3_qcom_clk_init()
379 qcom->clks = devm_kcalloc(dev, qcom->num_clocks, in dwc3_qcom_clk_init()
381 if (!qcom->clks) in dwc3_qcom_clk_init()
382 return -ENOMEM; in dwc3_qcom_clk_init()
384 for (i = 0; i < qcom->num_clocks; i++) { in dwc3_qcom_clk_init()
390 while (--i >= 0) in dwc3_qcom_clk_init()
391 clk_put(qcom->clks[i]); in dwc3_qcom_clk_init()
397 while (--i >= 0) { in dwc3_qcom_clk_init()
398 clk_disable_unprepare(qcom->clks[i]); in dwc3_qcom_clk_init()
399 clk_put(qcom->clks[i]); in dwc3_qcom_clk_init()
406 qcom->clks[i] = clk; in dwc3_qcom_clk_init()
414 struct device_node *np = pdev->dev.of_node, *dwc3_np; in dwc3_qcom_probe()
415 struct device *dev = &pdev->dev; in dwc3_qcom_probe()
421 qcom = devm_kzalloc(&pdev->dev, sizeof(*qcom), GFP_KERNEL); in dwc3_qcom_probe()
423 return -ENOMEM; in dwc3_qcom_probe()
426 qcom->dev = &pdev->dev; in dwc3_qcom_probe()
428 qcom->resets = devm_reset_control_array_get_optional_exclusive(dev); in dwc3_qcom_probe()
429 if (IS_ERR(qcom->resets)) { in dwc3_qcom_probe()
430 ret = PTR_ERR(qcom->resets); in dwc3_qcom_probe()
431 dev_err(&pdev->dev, "failed to get resets, err=%d\n", ret); in dwc3_qcom_probe()
435 ret = reset_control_assert(qcom->resets); in dwc3_qcom_probe()
437 dev_err(&pdev->dev, "failed to assert resets, err=%d\n", ret); in dwc3_qcom_probe()
443 ret = reset_control_deassert(qcom->resets); in dwc3_qcom_probe()
445 dev_err(&pdev->dev, "failed to deassert resets, err=%d\n", ret); in dwc3_qcom_probe()
450 "clocks", "#clock-cells")); in dwc3_qcom_probe()
457 qcom->qscratch_base = devm_ioremap_resource(dev, res); in dwc3_qcom_probe()
458 if (IS_ERR(qcom->qscratch_base)) { in dwc3_qcom_probe()
460 ret = PTR_ERR(qcom->qscratch_base); in dwc3_qcom_probe()
468 dwc3_np = of_get_child_by_name(np, "dwc3"); in dwc3_qcom_probe()
470 dev_err(dev, "failed to find dwc3 core child\n"); in dwc3_qcom_probe()
471 ret = -ENODEV; in dwc3_qcom_probe()
476 * Disable pipe_clk requirement if specified. Used when dwc3 in dwc3_qcom_probe()
480 "qcom,select-utmi-as-pipe-clk"); in dwc3_qcom_probe()
486 dev_err(dev, "failed to register dwc3 core - %d\n", ret); in dwc3_qcom_probe()
490 qcom->dwc3 = of_find_device_by_node(dwc3_np); in dwc3_qcom_probe()
491 if (!qcom->dwc3) { in dwc3_qcom_probe()
492 dev_err(&pdev->dev, "failed to get dwc3 platform device\n"); in dwc3_qcom_probe()
493 ret = -ENODEV; in dwc3_qcom_probe()
497 qcom->mode = usb_get_dr_mode(&qcom->dwc3->dev); in dwc3_qcom_probe()
500 if (qcom->mode == USB_DR_MODE_PERIPHERAL) in dwc3_qcom_probe()
508 device_init_wakeup(&pdev->dev, 1); in dwc3_qcom_probe()
509 qcom->is_suspended = false; in dwc3_qcom_probe()
517 of_platform_depopulate(&pdev->dev); in dwc3_qcom_probe()
519 for (i = qcom->num_clocks - 1; i >= 0; i--) { in dwc3_qcom_probe()
520 clk_disable_unprepare(qcom->clks[i]); in dwc3_qcom_probe()
521 clk_put(qcom->clks[i]); in dwc3_qcom_probe()
524 reset_control_assert(qcom->resets); in dwc3_qcom_probe()
532 struct device *dev = &pdev->dev; in dwc3_qcom_remove()
537 for (i = qcom->num_clocks - 1; i >= 0; i--) { in dwc3_qcom_remove()
538 clk_disable_unprepare(qcom->clks[i]); in dwc3_qcom_remove()
539 clk_put(qcom->clks[i]); in dwc3_qcom_remove()
541 qcom->num_clocks = 0; in dwc3_qcom_remove()
543 reset_control_assert(qcom->resets); in dwc3_qcom_remove()
558 qcom->pm_suspended = true; in dwc3_qcom_pm_suspend()
570 qcom->pm_suspended = false; in dwc3_qcom_pm_resume()
596 { .compatible = "qcom,dwc3" },
597 { .compatible = "qcom,msm8996-dwc3" },
598 { .compatible = "qcom,sdm845-dwc3" },
607 .name = "dwc3-qcom",
616 MODULE_DESCRIPTION("DesignWare DWC3 QCOM Glue Driver");