summaryrefslogtreecommitdiff
path: root/drivers/usb/host/ehci-fsl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/ehci-fsl.c')
-rw-r--r--drivers/usb/host/ehci-fsl.c99
1 files changed, 71 insertions, 28 deletions
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 8600317bd60b..86e42892016d 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -116,13 +116,33 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
goto err3;
}
- /* Enable USB controller */
- temp = in_be32(hcd->regs + 0x500);
- out_be32(hcd->regs + 0x500, temp | 0x4);
+ pdata->regs = hcd->regs;
- /* Set to Host mode */
- temp = in_le32(hcd->regs + 0x1a8);
- out_le32(hcd->regs + 0x1a8, temp | 0x3);
+ /*
+ * do platform specific init: check the clock, grab/config pins, etc.
+ */
+ if (pdata->init && pdata->init(pdev)) {
+ retval = -ENODEV;
+ goto err3;
+ }
+
+ /*
+ * Check if it is MPC5121 SoC, otherwise set pdata->have_sysif_regs
+ * flag for 83xx or 8536 system interface registers.
+ */
+ if (pdata->big_endian_mmio)
+ temp = in_be32(hcd->regs + FSL_SOC_USB_ID);
+ else
+ temp = in_le32(hcd->regs + FSL_SOC_USB_ID);
+
+ if ((temp & ID_MSK) != (~((temp & NID_MSK) >> 8) & ID_MSK))
+ pdata->have_sysif_regs = 1;
+
+ /* Enable USB controller, 83xx or 8536 */
+ if (pdata->have_sysif_regs)
+ setbits32(hcd->regs + FSL_SOC_USB_CTRL, 0x4);
+
+ /* Don't need to set host mode here. It will be done by tdi_reset() */
retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
if (retval != 0)
@@ -137,6 +157,8 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
usb_put_hcd(hcd);
err1:
dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), retval);
+ if (pdata->exit)
+ pdata->exit(pdev);
return retval;
}
@@ -154,17 +176,30 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
static void usb_hcd_fsl_remove(struct usb_hcd *hcd,
struct platform_device *pdev)
{
+ struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+
usb_remove_hcd(hcd);
+
+ /*
+ * do platform specific un-initialization:
+ * release iomux pins, disable clock, etc.
+ */
+ if (pdata->exit)
+ pdata->exit(pdev);
iounmap(hcd->regs);
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
usb_put_hcd(hcd);
}
-static void mpc83xx_setup_phy(struct ehci_hcd *ehci,
- enum fsl_usb2_phy_modes phy_mode,
- unsigned int port_offset)
+static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,
+ enum fsl_usb2_phy_modes phy_mode,
+ unsigned int port_offset)
{
- u32 portsc = 0;
+ u32 portsc;
+
+ portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]);
+ portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW);
+
switch (phy_mode) {
case FSL_USB2_PHY_ULPI:
portsc |= PORT_PTS_ULPI;
@@ -184,20 +219,21 @@ static void mpc83xx_setup_phy(struct ehci_hcd *ehci,
ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]);
}
-static void mpc83xx_usb_setup(struct usb_hcd *hcd)
+static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
{
- struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ struct usb_hcd *hcd = ehci_to_hcd(ehci);
struct fsl_usb2_platform_data *pdata;
void __iomem *non_ehci = hcd->regs;
u32 temp;
- pdata =
- (struct fsl_usb2_platform_data *)hcd->self.controller->
- platform_data;
+ pdata = hcd->self.controller->platform_data;
+
/* Enable PHY interface in the control reg. */
- temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
- out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004);
- out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b);
+ if (pdata->have_sysif_regs) {
+ temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
+ out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004);
+ out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b);
+ }
#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
/*
@@ -214,7 +250,7 @@ static void mpc83xx_usb_setup(struct usb_hcd *hcd)
if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||
(pdata->operating_mode == FSL_USB2_DR_OTG))
- mpc83xx_setup_phy(ehci, pdata->phy_mode, 0);
+ ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0);
if (pdata->operating_mode == FSL_USB2_MPH_HOST) {
unsigned int chip, rev, svr;
@@ -228,25 +264,27 @@ static void mpc83xx_usb_setup(struct usb_hcd *hcd)
ehci->has_fsl_port_bug = 1;
if (pdata->port_enables & FSL_USB2_PORT0_ENABLED)
- mpc83xx_setup_phy(ehci, pdata->phy_mode, 0);
+ ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0);
if (pdata->port_enables & FSL_USB2_PORT1_ENABLED)
- mpc83xx_setup_phy(ehci, pdata->phy_mode, 1);
+ ehci_fsl_setup_phy(ehci, pdata->phy_mode, 1);
}
+ if (pdata->have_sysif_regs) {
#ifdef CONFIG_PPC_85xx
- out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008);
- out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080);
+ out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008);
+ out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080);
#else
- out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c);
- out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040);
+ out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c);
+ out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040);
#endif
- out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);
+ out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);
+ }
}
/* called after powerup, by probe or system-pm "wakeup" */
static int ehci_fsl_reinit(struct ehci_hcd *ehci)
{
- mpc83xx_usb_setup(ehci_to_hcd(ehci));
+ ehci_fsl_usb_setup(ehci);
ehci_port_power(ehci, 0);
return 0;
@@ -257,6 +295,11 @@ static int ehci_fsl_setup(struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
int retval;
+ struct fsl_usb2_platform_data *pdata;
+
+ pdata = hcd->self.controller->platform_data;
+ ehci->big_endian_desc = pdata->big_endian_desc;
+ ehci->big_endian_mmio = pdata->big_endian_mmio;
/* EHCI registers start at offset 0x100 */
ehci->caps = hcd->regs + 0x100;
@@ -370,7 +413,7 @@ static const struct hc_driver ehci_fsl_hc_driver = {
* generic hardware linkage
*/
.irq = ehci_irq,
- .flags = HCD_USB2,
+ .flags = HCD_USB2 | HCD_MEMORY,
/*
* basic lifecycle operations