diff options
author | Ramneek Mehresh <ramneek.mehresh@freescale.com> | 2012-03-20 06:05:50 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-04-18 22:46:42 +0200 |
commit | 58c559e6509f276d0afb4621b2122e994e70160c (patch) | |
tree | a283772f0748cb6dd63d236851ecd20b3f89b780 /drivers/usb/host | |
parent | USB: add EOPNOTSUPP to usb_translate_errors (diff) | |
download | linux-58c559e6509f276d0afb4621b2122e994e70160c.tar.xz linux-58c559e6509f276d0afb4621b2122e994e70160c.zip |
fsl/usb: Add controller version based ULPI and UTMI phy support
Add support for ULPI and UTMI PHYs based on usb controller
version info read from device-tree
Example of USB Controller versioning info:
Version 1.2 and below : MPC8536, MPC8315, etc
Version 1.6 : P1020, P1010, P2020, P5020, etc
Version 2.2 : PSC9131, PSC9132, P3060, etc
No changes for non-DT users
Signed-off-by: Ramneek Mehresh <ramneek.mehresh@freescale.com>
Acked-by: Li Yang <leoli@freescale.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/ehci-fsl.c | 35 | ||||
-rw-r--r-- | drivers/usb/host/ehci-fsl.h | 13 | ||||
-rw-r--r-- | drivers/usb/host/fsl-mph-dr-of.c | 41 |
3 files changed, 81 insertions, 8 deletions
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 3e7345172e03..653e577ab3ee 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -1,6 +1,6 @@ /* * Copyright 2005-2009 MontaVista Software, Inc. - * Copyright 2008 Freescale Semiconductor, Inc. + * Copyright 2008,2012 Freescale Semiconductor, Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -211,19 +211,32 @@ static void usb_hcd_fsl_remove(struct usb_hcd *hcd, usb_put_hcd(hcd); } -static void ehci_fsl_setup_phy(struct ehci_hcd *ehci, +static void ehci_fsl_setup_phy(struct usb_hcd *hcd, enum fsl_usb2_phy_modes phy_mode, unsigned int port_offset) { - u32 portsc; - struct usb_hcd *hcd = ehci_to_hcd(ehci); + u32 portsc, temp; + struct ehci_hcd *ehci = hcd_to_ehci(hcd); void __iomem *non_ehci = hcd->regs; + struct device *dev = hcd->self.controller; + struct fsl_usb2_platform_data *pdata = dev->platform_data; + + if (pdata->controller_ver < 0) { + dev_warn(hcd->self.controller, "Could not get controller version\n"); + return; + } 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: + if (pdata->controller_ver) { + /* controller version 1.6 or above */ + temp = in_be32(non_ehci + FSL_SOC_USB_CTRL); + out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | + USB_CTRL_USB_EN | ULPI_PHY_CLK_SEL); + } portsc |= PORT_PTS_ULPI; break; case FSL_USB2_PHY_SERIAL: @@ -233,6 +246,14 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci, portsc |= PORT_PTS_PTW; /* fall through */ case FSL_USB2_PHY_UTMI: + if (pdata->controller_ver) { + /* controller version 1.6 or above */ + temp = in_be32(non_ehci + FSL_SOC_USB_CTRL); + out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | + UTMI_PHY_EN | USB_CTRL_USB_EN); + mdelay(FSL_UTMI_PHY_DLY); /* Delay for UTMI PHY CLK to + become stable - 10ms*/ + } /* enable UTMI PHY */ setbits32(non_ehci + FSL_SOC_USB_CTRL, CTRL_UTMI_PHY_EN); portsc |= PORT_PTS_UTMI; @@ -271,7 +292,7 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci) if ((pdata->operating_mode == FSL_USB2_DR_HOST) || (pdata->operating_mode == FSL_USB2_DR_OTG)) - ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0); + ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0); if (pdata->operating_mode == FSL_USB2_MPH_HOST) { unsigned int chip, rev, svr; @@ -285,9 +306,9 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci) ehci->has_fsl_port_bug = 1; if (pdata->port_enables & FSL_USB2_PORT0_ENABLED) - ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0); + ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0); if (pdata->port_enables & FSL_USB2_PORT1_ENABLED) - ehci_fsl_setup_phy(ehci, pdata->phy_mode, 1); + ehci_fsl_setup_phy(hcd, pdata->phy_mode, 1); } if (pdata->have_sysif_regs) { diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h index 863fb0c080d7..88403684d10b 100644 --- a/drivers/usb/host/ehci-fsl.h +++ b/drivers/usb/host/ehci-fsl.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2005-2010 Freescale Semiconductor, Inc. +/* Copyright (C) 2005-2010,2012 Freescale Semiconductor, Inc. * Copyright (c) 2005 MontaVista Software * * This program is free software; you can redistribute it and/or modify it @@ -50,4 +50,15 @@ #define CTRL_UTMI_PHY_EN (1<<9) #define CTRL_PHY_CLK_VALID (1 << 17) #define SNOOP_SIZE_2GB 0x1e + +/* control Register Bit Masks */ +#define ULPI_INT_EN (1<<0) +#define WU_INT_EN (1<<1) +#define USB_CTRL_USB_EN (1<<2) +#define LINE_STATE_FILTER__EN (1<<3) +#define KEEP_OTG_ON (1<<4) +#define OTG_PORT (1<<5) +#define PLL_RESET (1<<8) +#define UTMI_PHY_EN (1<<9) +#define ULPI_PHY_CLK_SEL (1<<10) #endif /* _EHCI_FSL_H */ diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c index ab333ac6071d..22ff6b3a676f 100644 --- a/drivers/usb/host/fsl-mph-dr-of.c +++ b/drivers/usb/host/fsl-mph-dr-of.c @@ -119,6 +119,39 @@ error: static const struct of_device_id fsl_usb2_mph_dr_of_match[]; +static int usb_get_ver_info(struct device_node *np) +{ + int ver = -1; + + /* + * returns 1 for usb controller version 1.6 + * returns 2 for usb controller version 2.2 + * returns 0 otherwise + */ + if (of_device_is_compatible(np, "fsl-usb2-dr")) { + if (of_device_is_compatible(np, "fsl-usb2-dr-v1.6")) + ver = FSL_USB_VER_1_6; + else if (of_device_is_compatible(np, "fsl-usb2-dr-v2.2")) + ver = FSL_USB_VER_2_2; + else /* for previous controller versions */ + ver = FSL_USB_VER_OLD; + + if (ver > -1) + return ver; + } + + if (of_device_is_compatible(np, "fsl-usb2-mph")) { + if (of_device_is_compatible(np, "fsl-usb2-mph-v1.6")) + ver = FSL_USB_VER_1_6; + else if (of_device_is_compatible(np, "fsl-usb2-mph-v2.2")) + ver = FSL_USB_VER_2_2; + else /* for previous controller versions */ + ver = FSL_USB_VER_OLD; + } + + return ver; +} + static int __devinit fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev) { struct device_node *np = ofdev->dev.of_node; @@ -166,6 +199,14 @@ static int __devinit fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev) prop = of_get_property(np, "phy_type", NULL); pdata->phy_mode = determine_usb_phy(prop); + pdata->controller_ver = usb_get_ver_info(np); + + if (pdata->have_sysif_regs) { + if (pdata->controller_ver < 0) { + dev_warn(&ofdev->dev, "Could not get controller version\n"); + return -ENODEV; + } + } for (i = 0; i < ARRAY_SIZE(dev_data->drivers); i++) { if (!dev_data->drivers[i]) |