rst = devm_reset_control_get_shared(dev, "usb"); if (IS_ERR(rst)) {
dev_err(dev, "can't get ehci reset: %pe\n", rst); return PTR_ERR(rst);
}
phy_np = of_parse_phandle(dev->of_node, "nvidia,phy", 0); if (!phy_np) return -ENOENT;
/* * The 1st USB controller contains some UTMI pad registers that are * global for all the controllers on the chip. Those registers are * also cleared when reset is asserted to the 1st controller.
*/
rst_utmi = of_reset_control_get_shared(phy_np, "utmi-pads"); if (IS_ERR(rst_utmi)) {
dev_warn(dev, "can't get utmi-pads reset from the PHY\n");
dev_warn(dev, "continuing, but please update your DT\n");
} else { /* * PHY driver performs UTMI-pads reset in a case of a * non-legacy DT.
*/
reset_control_put(rst_utmi);
}
of_node_put(phy_np);
/* reset control is shared, hence initialize it first */
err = reset_control_deassert(rst); if (err) return err;
err = reset_control_assert(rst); if (err) return err;
udelay(1);
err = reset_control_deassert(rst); if (err) return err;
/* * Here we have to do Port Reset at most twice for * Port Enable bit to be set.
*/ for (i = 0; i < 2; i++) {
temp = ehci_readl(ehci, portsc_reg);
temp |= PORT_RESET;
ehci_writel(ehci, temp, portsc_reg);
fsleep(10000);
temp &= ~PORT_RESET;
ehci_writel(ehci, temp, portsc_reg);
fsleep(1000);
tries = 100; do {
fsleep(1000); /* * Up to this point, Port Enable bit is * expected to be set after 2 ms waiting. * USB1 usually takes extra 45 ms, for safety, * we take 100 ms as timeout.
*/
temp = ehci_readl(ehci, portsc_reg);
} while (!(temp & PORT_PE) && tries--); if (temp & PORT_PE) break;
} if (i == 2)
retval = -ETIMEDOUT;
/* * Clear Connect Status Change bit if it's set. * We can't clear PORT_PEC. It will also cause PORT_PE to be cleared.
*/ if (temp & PORT_CSC)
ehci_writel(ehci, PORT_CSC, portsc_reg);
/* * Write to clear any interrupt status bits that might be set * during port reset.
*/
temp = ehci_readl(ehci, &ehci->regs->status);
ehci_writel(ehci, temp, &ehci->regs->status);
switch (typeReq) { case SetPortFeature: if (wValue != USB_PORT_FEAT_RESET || !usb->needs_double_reset) break;
/* for USB1 port we need to issue Port Reset twice internally */
retval = tegra_usb_internal_port_reset(ehci, status_reg, flags);
*done = true; break;
}
return retval;
}
staticvoid tegra_usb_enter_lpm(struct ci_hdrc *ci, bool enable)
{ /* * Touching any register which belongs to AHB clock domain will * hang CPU if USB controller is put into low power mode because * AHB USB clock is gated on Tegra in the LPM. * * Tegra PHY has a separate register for checking the clock status * and usb_phy_set_suspend() takes care of gating/ungating the clocks * and restoring the PHY state on Tegra. Hence DEVLC/PORTSC registers * shouldn't be touched directly by the CI driver.
*/
usb_phy_set_suspend(ci->usb_phy, enable);
}
usb = devm_kzalloc(&pdev->dev, sizeof(*usb), GFP_KERNEL); if (!usb) return -ENOMEM;
platform_set_drvdata(pdev, usb);
soc = of_device_get_match_data(&pdev->dev); if (!soc) {
dev_err(&pdev->dev, "failed to match OF data\n"); return -EINVAL;
}
usb->phy = devm_usb_get_phy_by_phandle(&pdev->dev, "nvidia,phy", 0); if (IS_ERR(usb->phy)) return dev_err_probe(&pdev->dev, PTR_ERR(usb->phy), "failed to get PHY");
usb->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(usb->clk)) return dev_err_probe(&pdev->dev, PTR_ERR(usb->clk), "failed to get clock");
err = devm_tegra_core_dev_init_opp_table_common(&pdev->dev); if (err) return err;
pm_runtime_enable(&pdev->dev);
err = pm_runtime_resume_and_get(&pdev->dev); if (err) return err;
if (device_property_present(&pdev->dev, "nvidia,needs-double-reset"))
usb->needs_double_reset = true;
err = tegra_usb_reset_controller(&pdev->dev); if (err) {
dev_err_probe(&pdev->dev, err, "failed to reset controller"); goto fail_power_off;
}
/* * USB controller registers shouldn't be touched before PHY is * initialized, otherwise CPU will hang because clocks are gated. * PHY driver controls gating of internal USB clocks on Tegra.
*/
err = usb_phy_init(usb->phy); if (err) goto fail_power_off;
/* Tegra PHY driver currently doesn't support LPM for ULPI */ if (of_usb_get_phy_mode(pdev->dev.of_node) == USBPHY_INTERFACE_MODE_ULPI)
usb->data.flags &= ~CI_HDRC_SUPPORTS_RUNTIME_PM;
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.