// SPDX-License-Identifier: GPL-2.0 /* * xhci-plat.c - xHCI host controller driver platform Bus Glue. * * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com * Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de> * * A lot of code borrowed from the Linux xHCI driver.
*/
/* * Not all platforms have clks so it is not an error if the * clock do not exist.
*/
xhci->reg_clk = devm_clk_get_optional(&pdev->dev, "reg"); if (IS_ERR(xhci->reg_clk)) {
ret = PTR_ERR(xhci->reg_clk); goto put_hcd;
}
xhci->clk = devm_clk_get_optional(&pdev->dev, NULL); if (IS_ERR(xhci->clk)) {
ret = PTR_ERR(xhci->clk); goto put_hcd;
}
xhci->reset = devm_reset_control_array_get_optional_shared(&pdev->dev); if (IS_ERR(xhci->reset)) {
ret = PTR_ERR(xhci->reset); goto put_hcd;
}
ret = reset_control_deassert(xhci->reset); if (ret) goto put_hcd;
ret = clk_prepare_enable(xhci->reg_clk); if (ret) goto err_reset;
ret = clk_prepare_enable(xhci->clk); if (ret) goto disable_reg_clk;
if (priv_match) {
priv = hcd_to_xhci_priv(hcd); /* Just copy data for now */
*priv = *priv_match;
}
device_set_wakeup_capable(&pdev->dev, true);
xhci->main_hcd = hcd;
/* imod_interval is the interrupt moderation value in nanoseconds. */
xhci->imod_interval = 40000;
/* Iterate over all parent nodes for finding quirks */ for (tmpdev = &pdev->dev; tmpdev; tmpdev = tmpdev->parent) {
if (device_property_read_bool(tmpdev, "usb2-lpm-disable"))
xhci->quirks |= XHCI_HW_LPM_DISABLE;
if (device_property_read_bool(tmpdev, "usb3-lpm-capable"))
xhci->quirks |= XHCI_LPM_SUPPORT;
if (device_property_read_bool(tmpdev, "quirk-broken-port-ped"))
xhci->quirks |= XHCI_BROKEN_PORT_PED;
if (device_property_read_bool(tmpdev, "xhci-sg-trb-cache-size-quirk"))
xhci->quirks |= XHCI_SG_TRB_CACHE_SIZE_QUIRK;
if (device_property_read_bool(tmpdev, "write-64-hi-lo-quirk"))
xhci->quirks |= XHCI_WRITE_64_HI_LO;
if (device_property_read_bool(tmpdev, "xhci-missing-cas-quirk"))
xhci->quirks |= XHCI_MISSING_CAS;
if (device_property_read_bool(tmpdev, "xhci-skip-phy-init-quirk"))
xhci->quirks |= XHCI_SKIP_PHY_INIT;
/* * sysdev must point to a device that is known to the system firmware * or PCI hardware. We handle these three cases here: * 1. xhci_plat comes from firmware * 2. xhci_plat is child of a device from firmware (dwc3-plat) * 3. xhci_plat is grandchild of a pci device (dwc3-pci)
*/ for (sysdev = &pdev->dev; sysdev; sysdev = sysdev->parent) { if (is_of_node(sysdev->fwnode) ||
is_acpi_device_node(sysdev->fwnode)) break; elseif (dev_is_pci(sysdev)) break;
}
if (!sysdev)
sysdev = &pdev->dev;
if (WARN_ON(!sysdev->dma_mask)) { /* Platform did not initialize dma_mask */
ret = dma_coerce_mask_and_coherent(sysdev, DMA_BIT_MASK(64)); if (ret) return ret;
}
if (pdev->dev.of_node)
priv_match = of_device_get_match_data(&pdev->dev); else
priv_match = dev_get_platdata(&pdev->dev);
if (pm_runtime_suspended(dev))
pm_runtime_resume(dev);
ret = xhci_priv_suspend_quirk(hcd); if (ret) return ret; /* * xhci_suspend() needs `do_wakeup` to know whether host is allowed * to do wakeup during suspend.
*/
ret = xhci_suspend(xhci, device_may_wakeup(dev)); if (ret) return ret;
if (!device_may_wakeup(dev) && (xhci->quirks & XHCI_SUSPEND_RESUME_CLKS)) {
clk_disable_unprepare(xhci->clk);
clk_disable_unprepare(xhci->reg_clk);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.