// SPDX-License-Identifier: GPL-2.0+ /* * Copyright 2005-2009 MontaVista Software, Inc. * Copyright 2008,2012,2015 Freescale Semiconductor, Inc. * * Ported to 834x by Randy Vinson <rvinson@mvista.com> using code provided * by Hunter Wu. * Power Management support by Dave Liu <daveliu@freescale.com>, * Jerry Huang <Chang-Ming.Huang@freescale.com> and * Anton Vorontsov <avorontsov@ru.mvista.com>.
*/
/* configure so an HC device and id are always provided */ /* always called with process context; sleeping is OK */
/* * fsl_ehci_drv_probe - initialize FSL-based HCDs * @pdev: USB Host Controller being probed * * Context: task context, might sleep * * Allocates basic resources for this USB host controller.
*/ staticint fsl_ehci_drv_probe(struct platform_device *pdev)
{ struct fsl_usb2_platform_data *pdata; struct usb_hcd *hcd; struct resource *res; int irq; int retval;
u32 tmp;
pr_debug("initializing FSL-SOC USB Controller\n");
/* Need platform data for setup */
pdata = dev_get_platdata(&pdev->dev); if (!pdata) {
dev_err(&pdev->dev, "No platform data for %s.\n", dev_name(&pdev->dev)); return -ENODEV;
}
/* * This is a host mode driver, verify that we're supposed to be * in host mode.
*/ if (!((pdata->operating_mode == FSL_USB2_DR_HOST) ||
(pdata->operating_mode == FSL_USB2_MPH_HOST) ||
(pdata->operating_mode == FSL_USB2_DR_OTG))) {
dev_err(&pdev->dev, "Non Host Mode configured for %s. Wrong driver linked.\n",
dev_name(&pdev->dev)); return -ENODEV;
}
irq = platform_get_irq(pdev, 0); if (irq < 0) return irq;
/* Set USB_EN bit to select ULPI phy for USB controller version 2.5 */ if (pdata->controller_ver == FSL_USB_VER_2_5 &&
pdata->phy_mode == FSL_USB2_PHY_ULPI)
iowrite32be(USB_CTRL_USB_EN, hcd->regs + FSL_SOC_USB_CTRL);
/* * Enable UTMI phy and program PTS field in UTMI mode before asserting * controller reset for USB Controller version 2.5
*/ if (pdata->has_fsl_erratum_a007792) {
tmp = ioread32be(hcd->regs + FSL_SOC_USB_CTRL);
tmp &= ~CONTROL_REGISTER_W1C_MASK;
tmp |= CTRL_UTMI_PHY_EN;
iowrite32be(tmp, hcd->regs + FSL_SOC_USB_CTRL);
switch (phy_mode) { case FSL_USB2_PHY_ULPI: if (pdata->have_sysif_regs && pdata->controller_ver) { /* controller version 1.6 or above */ /* turn off UTMI PHY first */
tmp = ioread32be(non_ehci + FSL_SOC_USB_CTRL);
tmp &= ~(CONTROL_REGISTER_W1C_MASK | UTMI_PHY_EN);
iowrite32be(tmp, non_ehci + FSL_SOC_USB_CTRL);
/* then turn on ULPI and enable USB controller */
tmp = ioread32be(non_ehci + FSL_SOC_USB_CTRL);
tmp &= ~CONTROL_REGISTER_W1C_MASK;
tmp |= ULPI_PHY_CLK_SEL | USB_CTRL_USB_EN;
iowrite32be(tmp, non_ehci + FSL_SOC_USB_CTRL);
}
portsc |= PORT_PTS_ULPI; break; case FSL_USB2_PHY_SERIAL:
portsc |= PORT_PTS_SERIAL; break; case FSL_USB2_PHY_UTMI_WIDE:
portsc |= PORT_PTS_PTW;
fallthrough; case FSL_USB2_PHY_UTMI: /* Presence of this node "has_fsl_erratum_a006918" * in device-tree is used to stop USB controller * initialization in Linux
*/ if (pdata->has_fsl_erratum_a006918) {
dev_warn(dev, "USB PHY clock invalid\n"); return -EINVAL;
}
fallthrough; case FSL_USB2_PHY_UTMI_DUAL: /* PHY_CLK_VALID bit is de-featured from all controller * versions below 2.4 and is to be checked only for * internal UTMI phy
*/ if (pdata->controller_ver > FSL_USB_VER_2_4 &&
pdata->have_sysif_regs && !usb_phy_clk_valid(hcd)) {
dev_err(dev, "USB PHY clock invalid\n"); return -EINVAL;
}
if (pdata->have_sysif_regs && pdata->controller_ver) { /* controller version 1.6 or above */
tmp = ioread32be(non_ehci + FSL_SOC_USB_CTRL);
tmp &= ~CONTROL_REGISTER_W1C_MASK;
tmp |= UTMI_PHY_EN;
iowrite32be(tmp, non_ehci + FSL_SOC_USB_CTRL);
mdelay(FSL_UTMI_PHY_DLY); /* Delay for UTMI PHY CLK to
become stable - 10ms*/
} /* enable UTMI PHY */ if (pdata->have_sysif_regs) {
tmp = ioread32be(non_ehci + FSL_SOC_USB_CTRL);
tmp &= ~CONTROL_REGISTER_W1C_MASK;
tmp |= CTRL_UTMI_PHY_EN;
iowrite32be(tmp, non_ehci + FSL_SOC_USB_CTRL);
}
portsc |= PORT_PTS_UTMI; break; case FSL_USB2_PHY_NONE: break;
}
if (pdata->have_sysif_regs) { /* * Turn on cache snooping hardware, since some PowerPC platforms * wholly rely on hardware to deal with cache coherent
*/
/* Setup Snooping for all the 4GB space */ /* SNOOP1 starts from 0x0, size 2G */
iowrite32be(0x0 | SNOOP_SIZE_2GB,
non_ehci + FSL_SOC_USB_SNOOP1); /* SNOOP2 starts from 0x80000000, size 2G */
iowrite32be(0x80000000 | SNOOP_SIZE_2GB,
non_ehci + FSL_SOC_USB_SNOOP2);
}
/* Deal with USB erratum A-005275 */ if (pdata->has_fsl_erratum_a005275 == 1)
ehci->has_fsl_hs_errata = 1;
if (pdata->has_fsl_erratum_a005697 == 1)
ehci->has_fsl_susp_errata = 1;
if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||
(pdata->operating_mode == FSL_USB2_DR_OTG)) if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0)) return -EINVAL;
if (pdata->operating_mode == FSL_USB2_MPH_HOST) {
/* Deal with USB Erratum #14 on MPC834x Rev 1.0 & 1.1 chips */ if (pdata->has_fsl_erratum_14 == 1)
ehci->has_fsl_port_bug = 1;
if (pdata->port_enables & FSL_USB2_PORT0_ENABLED) if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0)) return -EINVAL;
if (pdata->port_enables & FSL_USB2_PORT1_ENABLED) if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 1)) return -EINVAL;
}
/* called after powerup, by probe or system-pm "wakeup" */ staticint ehci_fsl_reinit(struct ehci_hcd *ehci)
{ if (ehci_fsl_usb_setup(ehci)) return -EINVAL;
return 0;
}
/* called during probe() after chip reset completes */ staticint ehci_fsl_setup(struct usb_hcd *hcd)
{ struct ehci_hcd *ehci = hcd_to_ehci(hcd); int retval; struct fsl_usb2_platform_data *pdata; struct device *dev;
#ifdefined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_85xx) /* * Deal with MPC834X/85XX that need port power to be cycled * after the power fault condition is removed. Otherwise the * state machine does not reflect PORTSC[CSC] correctly.
*/
ehci->need_oc_pp_cycle = 1; #endif
hcd->has_tt = 1;
retval = ehci_setup(hcd); if (retval) return retval;
if (of_device_is_compatible(dev->parent->of_node, "fsl,mpc5121-usb2-dr")) { /* * set SBUSCFG:AHBBRST so that control msgs don't * fail when doing heavy PATA writes.
*/
ehci_writel(ehci, SBUSCFG_INCR8,
hcd->regs + FSL_SOC_USB_SBUSCFG);
}
retval = ehci_fsl_reinit(ehci); return retval;
}
struct ehci_fsl_priv { /* Saved USB PHY settings, need to restore after deep sleep. */
u32 usb_ctrl;
};
/* * If the controller is already suspended, then this must be a * PM suspend. Remember this fact, so that we will leave the * controller suspended at PM resume time.
*/ if (pdata->suspended) {
dev_dbg(dev, "already suspended, leaving early\n");
pdata->already_suspended = 1; return 0;
}
/* clear the W1C bits */
pdata->pm_portsc &= cpu_to_hc32(ehci, ~PORT_RWC_BITS);
pdata->suspended = 1;
/* clear PP to cut power to the port */
tmp = ehci_readl(ehci, &ehci->regs->port_status[0]);
tmp &= ~PORT_POWER;
ehci_writel(ehci, tmp, &ehci->regs->port_status[0]);
/* * If the controller was already suspended at suspend time, * then don't resume it now.
*/ if (pdata->already_suspended) {
dev_dbg(dev, "already suspended, leaving early\n");
pdata->already_suspended = 0; return 0;
}
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.