Lines Matching +full:assert +full:- +full:falling +full:- +full:edge
1 // SPDX-License-Identifier: GPL-2.0
4 * Inspired by dwc3-of-simple.c
121 * TODO: Make the in-core role switching code invoke dwc3_qcom_vbus_override_enable(),
122 * validate that the in-core extcon support is functional, and drop extcon
128 dwc3_qcom_setbits(qcom->qscratch_base, QSCRATCH_SS_PHY_CTRL, in dwc3_qcom_vbus_override_enable()
130 dwc3_qcom_setbits(qcom->qscratch_base, QSCRATCH_HS_PHY_CTRL, in dwc3_qcom_vbus_override_enable()
133 dwc3_qcom_clrbits(qcom->qscratch_base, QSCRATCH_SS_PHY_CTRL, in dwc3_qcom_vbus_override_enable()
135 dwc3_qcom_clrbits(qcom->qscratch_base, QSCRATCH_HS_PHY_CTRL, in dwc3_qcom_vbus_override_enable()
147 qcom->mode = event ? USB_DR_MODE_PERIPHERAL : USB_DR_MODE_HOST; in dwc3_qcom_vbus_notifier()
159 qcom->mode = event ? USB_DR_MODE_HOST : USB_DR_MODE_PERIPHERAL; in dwc3_qcom_host_notifier()
166 struct device *dev = qcom->dev; in dwc3_qcom_register_extcon()
170 if (!of_property_present(dev->of_node, "extcon")) in dwc3_qcom_register_extcon()
173 qcom->edev = extcon_get_edev_by_phandle(dev, 0); in dwc3_qcom_register_extcon()
174 if (IS_ERR(qcom->edev)) in dwc3_qcom_register_extcon()
175 return dev_err_probe(dev, PTR_ERR(qcom->edev), in dwc3_qcom_register_extcon()
178 qcom->vbus_nb.notifier_call = dwc3_qcom_vbus_notifier; in dwc3_qcom_register_extcon()
180 qcom->host_edev = extcon_get_edev_by_phandle(dev, 1); in dwc3_qcom_register_extcon()
181 if (IS_ERR(qcom->host_edev)) in dwc3_qcom_register_extcon()
182 qcom->host_edev = NULL; in dwc3_qcom_register_extcon()
184 ret = devm_extcon_register_notifier(dev, qcom->edev, EXTCON_USB, in dwc3_qcom_register_extcon()
185 &qcom->vbus_nb); in dwc3_qcom_register_extcon()
191 if (qcom->host_edev) in dwc3_qcom_register_extcon()
192 host_edev = qcom->host_edev; in dwc3_qcom_register_extcon()
194 host_edev = qcom->edev; in dwc3_qcom_register_extcon()
196 qcom->host_nb.notifier_call = dwc3_qcom_host_notifier; in dwc3_qcom_register_extcon()
198 &qcom->host_nb); in dwc3_qcom_register_extcon()
205 if (extcon_get_state(qcom->edev, EXTCON_USB) || in dwc3_qcom_register_extcon()
207 dwc3_qcom_vbus_notifier(&qcom->vbus_nb, true, qcom->edev); in dwc3_qcom_register_extcon()
209 dwc3_qcom_vbus_notifier(&qcom->vbus_nb, false, qcom->edev); in dwc3_qcom_register_extcon()
218 ret = icc_enable(qcom->icc_path_ddr); in dwc3_qcom_interconnect_enable()
222 ret = icc_enable(qcom->icc_path_apps); in dwc3_qcom_interconnect_enable()
224 icc_disable(qcom->icc_path_ddr); in dwc3_qcom_interconnect_enable()
233 ret = icc_disable(qcom->icc_path_ddr); in dwc3_qcom_interconnect_disable()
237 ret = icc_disable(qcom->icc_path_apps); in dwc3_qcom_interconnect_disable()
239 icc_enable(qcom->icc_path_ddr); in dwc3_qcom_interconnect_disable()
245 * dwc3_qcom_interconnect_init() - Get interconnect path handles
253 struct device *dev = qcom->dev; in dwc3_qcom_interconnect_init()
256 qcom->icc_path_ddr = of_icc_get(dev, "usb-ddr"); in dwc3_qcom_interconnect_init()
257 if (IS_ERR(qcom->icc_path_ddr)) { in dwc3_qcom_interconnect_init()
258 return dev_err_probe(dev, PTR_ERR(qcom->icc_path_ddr), in dwc3_qcom_interconnect_init()
259 "failed to get usb-ddr path\n"); in dwc3_qcom_interconnect_init()
262 qcom->icc_path_apps = of_icc_get(dev, "apps-usb"); in dwc3_qcom_interconnect_init()
263 if (IS_ERR(qcom->icc_path_apps)) { in dwc3_qcom_interconnect_init()
264 ret = dev_err_probe(dev, PTR_ERR(qcom->icc_path_apps), in dwc3_qcom_interconnect_init()
265 "failed to get apps-usb path\n"); in dwc3_qcom_interconnect_init()
269 max_speed = usb_get_maximum_speed(qcom->dwc.dev); in dwc3_qcom_interconnect_init()
271 ret = icc_set_bw(qcom->icc_path_ddr, in dwc3_qcom_interconnect_init()
274 ret = icc_set_bw(qcom->icc_path_ddr, in dwc3_qcom_interconnect_init()
278 dev_err(dev, "failed to set bandwidth for usb-ddr path: %d\n", ret); in dwc3_qcom_interconnect_init()
282 ret = icc_set_bw(qcom->icc_path_apps, APPS_USB_AVG_BW, APPS_USB_PEAK_BW); in dwc3_qcom_interconnect_init()
284 dev_err(dev, "failed to set bandwidth for apps-usb path: %d\n", ret); in dwc3_qcom_interconnect_init()
291 icc_put(qcom->icc_path_apps); in dwc3_qcom_interconnect_init()
293 icc_put(qcom->icc_path_ddr); in dwc3_qcom_interconnect_init()
298 * dwc3_qcom_interconnect_exit() - Release interconnect path handles
305 icc_put(qcom->icc_path_ddr); in dwc3_qcom_interconnect_exit()
306 icc_put(qcom->icc_path_apps); in dwc3_qcom_interconnect_exit()
312 return qcom->dwc.xhci; in dwc3_qcom_is_host()
319 struct dwc3 *dwc = &qcom->dwc; in dwc3_qcom_read_usb2_speed()
324 hcd = platform_get_drvdata(dwc->xhci); in dwc3_qcom_read_usb2_speed()
327 udev = usb_hub_find_child(hcd->self.root_hub, port_index + 1); in dwc3_qcom_read_usb2_speed()
334 return udev->speed; in dwc3_qcom_read_usb2_speed()
360 dwc3_qcom_disable_wakeup_irq(port->qusb2_phy_irq); in dwc3_qcom_disable_port_interrupts()
362 if (port->usb2_speed == USB_SPEED_LOW) { in dwc3_qcom_disable_port_interrupts()
363 dwc3_qcom_disable_wakeup_irq(port->dm_hs_phy_irq); in dwc3_qcom_disable_port_interrupts()
364 } else if ((port->usb2_speed == USB_SPEED_HIGH) || in dwc3_qcom_disable_port_interrupts()
365 (port->usb2_speed == USB_SPEED_FULL)) { in dwc3_qcom_disable_port_interrupts()
366 dwc3_qcom_disable_wakeup_irq(port->dp_hs_phy_irq); in dwc3_qcom_disable_port_interrupts()
368 dwc3_qcom_disable_wakeup_irq(port->dp_hs_phy_irq); in dwc3_qcom_disable_port_interrupts()
369 dwc3_qcom_disable_wakeup_irq(port->dm_hs_phy_irq); in dwc3_qcom_disable_port_interrupts()
372 dwc3_qcom_disable_wakeup_irq(port->ss_phy_irq); in dwc3_qcom_disable_port_interrupts()
377 dwc3_qcom_enable_wakeup_irq(port->qusb2_phy_irq, 0); in dwc3_qcom_enable_port_interrupts()
382 * as falling edge to detect both disconnect and remote wakeup scenarios. When in dwc3_qcom_enable_port_interrupts()
383 * LS device is connected, configure DM line as falling edge to detect both in dwc3_qcom_enable_port_interrupts()
385 * DP and DM lines as rising edge to detect HS/HS/LS device connect scenario. in dwc3_qcom_enable_port_interrupts()
388 if (port->usb2_speed == USB_SPEED_LOW) { in dwc3_qcom_enable_port_interrupts()
389 dwc3_qcom_enable_wakeup_irq(port->dm_hs_phy_irq, in dwc3_qcom_enable_port_interrupts()
391 } else if ((port->usb2_speed == USB_SPEED_HIGH) || in dwc3_qcom_enable_port_interrupts()
392 (port->usb2_speed == USB_SPEED_FULL)) { in dwc3_qcom_enable_port_interrupts()
393 dwc3_qcom_enable_wakeup_irq(port->dp_hs_phy_irq, in dwc3_qcom_enable_port_interrupts()
396 dwc3_qcom_enable_wakeup_irq(port->dp_hs_phy_irq, in dwc3_qcom_enable_port_interrupts()
398 dwc3_qcom_enable_wakeup_irq(port->dm_hs_phy_irq, in dwc3_qcom_enable_port_interrupts()
402 dwc3_qcom_enable_wakeup_irq(port->ss_phy_irq, 0); in dwc3_qcom_enable_port_interrupts()
409 for (i = 0; i < qcom->num_ports; i++) in dwc3_qcom_disable_interrupts()
410 dwc3_qcom_disable_port_interrupts(&qcom->ports[i]); in dwc3_qcom_disable_interrupts()
417 for (i = 0; i < qcom->num_ports; i++) in dwc3_qcom_enable_interrupts()
418 dwc3_qcom_enable_port_interrupts(&qcom->ports[i]); in dwc3_qcom_enable_interrupts()
426 if (qcom->is_suspended) in dwc3_qcom_suspend()
429 for (i = 0; i < qcom->num_ports; i++) { in dwc3_qcom_suspend()
430 val = readl(qcom->qscratch_base + pwr_evnt_irq_stat_reg[i]); in dwc3_qcom_suspend()
432 dev_err(qcom->dev, "port-%d HS-PHY not in L2\n", i + 1); in dwc3_qcom_suspend()
434 clk_bulk_disable_unprepare(qcom->num_clocks, qcom->clks); in dwc3_qcom_suspend()
438 dev_warn(qcom->dev, "failed to disable interconnect: %d\n", ret); in dwc3_qcom_suspend()
445 for (i = 0; i < qcom->num_ports; i++) in dwc3_qcom_suspend()
446 qcom->ports[i].usb2_speed = dwc3_qcom_read_usb2_speed(qcom, i); in dwc3_qcom_suspend()
450 qcom->is_suspended = true; in dwc3_qcom_suspend()
460 if (!qcom->is_suspended) in dwc3_qcom_resume()
466 ret = clk_bulk_prepare_enable(qcom->num_clocks, qcom->clks); in dwc3_qcom_resume()
472 dev_warn(qcom->dev, "failed to enable interconnect: %d\n", ret); in dwc3_qcom_resume()
475 for (i = 0; i < qcom->num_ports; i++) { in dwc3_qcom_resume()
476 dwc3_qcom_setbits(qcom->qscratch_base, in dwc3_qcom_resume()
481 qcom->is_suspended = false; in dwc3_qcom_resume()
489 struct dwc3 *dwc = &qcom->dwc; in qcom_dwc3_resume_irq()
492 if (qcom->pm_suspended) in qcom_dwc3_resume_irq()
500 pm_runtime_resume(&dwc->xhci->dev); in qcom_dwc3_resume_irq()
508 dwc3_qcom_setbits(qcom->qscratch_base, QSCRATCH_GENERAL_CFG, in dwc3_qcom_select_utmi_clk()
513 dwc3_qcom_setbits(qcom->qscratch_base, QSCRATCH_GENERAL_CFG, in dwc3_qcom_select_utmi_clk()
518 dwc3_qcom_clrbits(qcom->qscratch_base, QSCRATCH_GENERAL_CFG, in dwc3_qcom_select_utmi_clk()
528 ret = devm_request_threaded_irq(qcom->dev, irq, NULL, in dwc3_qcom_request_irq()
533 dev_err(qcom->dev, "failed to request irq %s: %d\n", name, ret); in dwc3_qcom_request_irq()
547 irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "dp_hs_phy_%d", port_index + 1); in dwc3_qcom_setup_port_irq()
549 irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "dp_hs_phy_irq"); in dwc3_qcom_setup_port_irq()
551 return -ENOMEM; in dwc3_qcom_setup_port_irq()
558 qcom->ports[port_index].dp_hs_phy_irq = irq; in dwc3_qcom_setup_port_irq()
562 irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "dm_hs_phy_%d", port_index + 1); in dwc3_qcom_setup_port_irq()
564 irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "dm_hs_phy_irq"); in dwc3_qcom_setup_port_irq()
566 return -ENOMEM; in dwc3_qcom_setup_port_irq()
573 qcom->ports[port_index].dm_hs_phy_irq = irq; in dwc3_qcom_setup_port_irq()
577 irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "ss_phy_%d", port_index + 1); in dwc3_qcom_setup_port_irq()
579 irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "ss_phy_irq"); in dwc3_qcom_setup_port_irq()
581 return -ENOMEM; in dwc3_qcom_setup_port_irq()
588 qcom->ports[port_index].ss_phy_irq = irq; in dwc3_qcom_setup_port_irq()
599 qcom->ports[port_index].qusb2_phy_irq = irq; in dwc3_qcom_setup_port_irq()
620 return port_num - 1; in dwc3_qcom_find_num_ports()
632 qcom->num_ports = dwc3_qcom_find_num_ports(pdev); in dwc3_qcom_setup_irq()
633 is_multiport = (qcom->num_ports > 1); in dwc3_qcom_setup_irq()
635 for (i = 0; i < qcom->num_ports; i++) { in dwc3_qcom_setup_irq()
647 struct device *dev = &pdev->dev; in dwc3_qcom_probe()
655 qcom = devm_kzalloc(&pdev->dev, sizeof(*qcom), GFP_KERNEL); in dwc3_qcom_probe()
657 return -ENOMEM; in dwc3_qcom_probe()
659 qcom->dev = &pdev->dev; in dwc3_qcom_probe()
661 qcom->resets = devm_reset_control_array_get_optional_exclusive(dev); in dwc3_qcom_probe()
662 if (IS_ERR(qcom->resets)) { in dwc3_qcom_probe()
663 return dev_err_probe(&pdev->dev, PTR_ERR(qcom->resets), in dwc3_qcom_probe()
667 ret = devm_clk_bulk_get_all(&pdev->dev, &qcom->clks); in dwc3_qcom_probe()
670 qcom->num_clocks = ret; in dwc3_qcom_probe()
672 ret = reset_control_assert(qcom->resets); in dwc3_qcom_probe()
674 dev_err(&pdev->dev, "failed to assert resets, err=%d\n", ret); in dwc3_qcom_probe()
680 ret = reset_control_deassert(qcom->resets); in dwc3_qcom_probe()
682 dev_err(&pdev->dev, "failed to deassert resets, err=%d\n", ret); in dwc3_qcom_probe()
686 ret = clk_bulk_prepare_enable(qcom->num_clocks, qcom->clks); in dwc3_qcom_probe()
692 ret = -EINVAL; in dwc3_qcom_probe()
698 qcom->qscratch_base = devm_ioremap(dev, res.end, SDM845_QSCRATCH_SIZE); in dwc3_qcom_probe()
699 if (!qcom->qscratch_base) { in dwc3_qcom_probe()
701 ret = -ENOMEM; in dwc3_qcom_probe()
716 "qcom,select-utmi-as-pipe-clk"); in dwc3_qcom_probe()
720 qcom->dwc.dev = dev; in dwc3_qcom_probe()
721 probe_data.dwc = &qcom->dwc; in dwc3_qcom_probe()
734 qcom->mode = usb_get_dr_mode(dev); in dwc3_qcom_probe()
737 if (qcom->mode != USB_DR_MODE_HOST) in dwc3_qcom_probe()
745 wakeup_source = of_property_read_bool(dev->of_node, "wakeup-source"); in dwc3_qcom_probe()
746 device_init_wakeup(&pdev->dev, wakeup_source); in dwc3_qcom_probe()
748 qcom->is_suspended = false; in dwc3_qcom_probe()
755 dwc3_core_remove(&qcom->dwc); in dwc3_qcom_probe()
757 clk_bulk_disable_unprepare(qcom->num_clocks, qcom->clks); in dwc3_qcom_probe()
759 reset_control_assert(qcom->resets); in dwc3_qcom_probe()
769 dwc3_core_remove(&qcom->dwc); in dwc3_qcom_remove()
771 clk_bulk_disable_unprepare(qcom->num_clocks, qcom->clks); in dwc3_qcom_remove()
774 reset_control_assert(qcom->resets); in dwc3_qcom_remove()
784 ret = dwc3_pm_suspend(&qcom->dwc); in dwc3_qcom_pm_suspend()
792 qcom->pm_suspended = true; in dwc3_qcom_pm_suspend()
808 qcom->pm_suspended = false; in dwc3_qcom_pm_resume()
810 ret = dwc3_pm_resume(&qcom->dwc); in dwc3_qcom_pm_resume()
837 ret = dwc3_runtime_suspend(&qcom->dwc); in dwc3_qcom_runtime_suspend()
854 return dwc3_runtime_resume(&qcom->dwc); in dwc3_qcom_runtime_resume()
871 { .compatible = "qcom,snps-dwc3" },
880 .name = "dwc3-qcom",