summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorJun Li <r65092@freescale.com>2008-03-05 13:07:34 +0800
committerDaniel Schaeffer <daniel.schaeffer@timesys.com>2008-08-25 15:20:41 -0400
commit3bb34e6ac73ffcf58cdaa3f988cc84268b32b3c2 (patch)
tree9856fab200175a3669408f5f52242600d3127827 /arch
parent0844a8934f378cec24892cab393f798b7bba1381 (diff)
ENGR00064728 MX31 3DS USB Patch
The patch for USB changes on mx31 3stack board: USBOTG, USBHOST,ISP1504 Signed-off-by: Jun Li <r65092@freescale.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/configs/imx31_3stack_defconfig2
-rw-r--r--arch/arm/mach-mx3/mx3_3stack_gpio.c23
-rw-r--r--arch/arm/mach-mx3/usb.c40
-rw-r--r--arch/arm/plat-mxc/isp1504xc.c28
-rw-r--r--arch/arm/plat-mxc/usb_common.c62
5 files changed, 144 insertions, 11 deletions
diff --git a/arch/arm/configs/imx31_3stack_defconfig b/arch/arm/configs/imx31_3stack_defconfig
index b530e6c067a5..3fae2b6b9497 100644
--- a/arch/arm/configs/imx31_3stack_defconfig
+++ b/arch/arm/configs/imx31_3stack_defconfig
@@ -1085,7 +1085,7 @@ CONFIG_USB_SUSPEND=y
#
CONFIG_USB_EHCI_HCD=m
CONFIG_USB_EHCI_ARC=y
-CONFIG_USB_EHCI_ARC_H1=y
+CONFIG_USB_EHCI_ARC_H1= is not set
CONFIG_USB_EHCI_ARC_H2=y
CONFIG_USB_EHCI_ARC_OTG=y
CONFIG_USB_EHCI_ARC_OTGHS=y
diff --git a/arch/arm/mach-mx3/mx3_3stack_gpio.c b/arch/arm/mach-mx3/mx3_3stack_gpio.c
index 74be84030873..b3a390e3b514 100644
--- a/arch/arm/mach-mx3/mx3_3stack_gpio.c
+++ b/arch/arm/mach-mx3/mx3_3stack_gpio.c
@@ -1003,6 +1003,13 @@ int gpio_usbh2_active(void)
(PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST));
mxc_iomux_set_pad(MX31_PIN_PC_RW_B,
(PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST));
+
+ mxc_request_iomux(MX31_PIN_USB_BYP, OUTPUTCONFIG_GPIO,
+ INPUTCONFIG_NONE);
+ mxc_set_gpio_direction(MX31_PIN_USB_BYP, 0);
+ mxc_set_gpio_dataout(MX31_PIN_USB_BYP, 0);
+ mdelay(1);
+ mxc_set_gpio_dataout(MX31_PIN_USB_BYP, 1);
return 0;
}
@@ -1060,6 +1067,9 @@ void gpio_usbh2_inactive(void)
OUTPUTCONFIG_GPIO, INPUTCONFIG_NONE);
mxc_free_iomux(MX31_PIN_PC_RW_B, /* USBH2_DATA7 */
OUTPUTCONFIG_GPIO, INPUTCONFIG_NONE);
+
+ mxc_free_iomux(MX31_PIN_USB_BYP, /* USBH2 PHY reset */
+ OUTPUTCONFIG_GPIO, INPUTCONFIG_NONE);
}
EXPORT_SYMBOL(gpio_usbh2_inactive);
@@ -1120,6 +1130,15 @@ int gpio_usbotg_hs_active(void)
(PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST));
mxc_iomux_set_pad(MX31_PIN_USBOTG_STP,
(PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST));
+
+ /* reset transceiver */
+ mxc_request_iomux(MX31_PIN_USB_PWR, OUTPUTCONFIG_GPIO,
+ INPUTCONFIG_GPIO);
+ mxc_set_gpio_direction(MX31_PIN_USB_PWR, 0);
+ mxc_set_gpio_dataout(MX31_PIN_USB_PWR, 0);
+ mdelay(1);
+ mxc_set_gpio_dataout(MX31_PIN_USB_PWR, 1);
+
return 0;
}
@@ -1127,8 +1146,8 @@ EXPORT_SYMBOL(gpio_usbotg_hs_active);
void gpio_usbotg_hs_inactive(void)
{
- /* Do nothing as pins doesn't have/support GPIO mode */
-
+ mxc_free_iomux(MX31_PIN_USB_PWR, OUTPUTCONFIG_GPIO,
+ INPUTCONFIG_GPIO);
}
EXPORT_SYMBOL(gpio_usbotg_hs_inactive);
diff --git a/arch/arm/mach-mx3/usb.c b/arch/arm/mach-mx3/usb.c
index 412d988b4ae2..d7183500cd0f 100644
--- a/arch/arm/mach-mx3/usb.c
+++ b/arch/arm/mach-mx3/usb.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2005-2008 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
@@ -37,6 +37,8 @@
#include <linux/fsl_devices.h>
#include <linux/usb/fsl_xcvr.h>
#include <linux/usb/otg.h>
+#include <linux/regulator/regulator.h>
+#include <linux/delay.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -103,7 +105,7 @@ static struct fsl_usb2_platform_data usbh2_config = {
.platform_uninit = fsl_usb_host_uninit,
.usbmode = (u32) &UH2_USBMODE,
.viewport = (u32) &UH2_ULPIVIEW,
- .power_budget = 150, /* 150 mA max power */
+ .power_budget = 250, /* 250 mA max power */
.gpio_usb_active = gpio_usbh2_active,
.gpio_usb_inactive = gpio_usbh2_inactive,
.transceiver = "isp1504",
@@ -120,6 +122,38 @@ static struct resource usbh2_resources[] = {
.flags = IORESOURCE_IRQ,
},
};
+
+void usbh2_get_xcvr_power(struct device *dev)
+{
+ struct regulator *usbh2_regux;
+
+ usbh2_regux = regulator_get(dev, "GPO1");
+ regulator_enable(usbh2_regux);
+ ((struct fsl_usb2_platform_data *)dev->platform_data)->
+ xcvr_pwr->regu1 = usbh2_regux;
+
+ usbh2_regux = regulator_get(dev, "GPO3");
+ regulator_enable(usbh2_regux);
+ ((struct fsl_usb2_platform_data *)dev->platform_data)->
+ xcvr_pwr->regu2 = usbh2_regux;
+}
+EXPORT_SYMBOL(usbh2_get_xcvr_power);
+
+void usbh2_put_xcvr_power(struct device *dev)
+{
+ struct regulator *usbh2_regux;
+
+ usbh2_regux = ((struct fsl_usb2_platform_data *)dev->
+ platform_data)->xcvr_pwr->regu2;
+ regulator_disable(usbh2_regux);
+ regulator_put(usbh2_regux, dev);
+
+ usbh2_regux = ((struct fsl_usb2_platform_data *)dev->
+ platform_data)->xcvr_pwr->regu1;
+ regulator_disable(usbh2_regux);
+ regulator_put(usbh2_regux, dev);
+}
+EXPORT_SYMBOL(usbh2_put_xcvr_power);
/* *INDENT-ON* */
#endif
@@ -165,7 +199,7 @@ static struct fsl_usb2_platform_data mxc_isp1504_config = {
.usbmode = (u32) &UOG_USBMODE,
.viewport = (u32) &UOG_ULPIVIEW,
.does_otg = 1,
- .power_budget = 150, /* 150 mA max power */
+ .power_budget = 250, /* 250 mA max power */
.gpio_usb_active = gpio_usbotg_hs_active,
.gpio_usb_inactive = gpio_usbotg_hs_inactive,
.transceiver = "isp1504",
diff --git a/arch/arm/plat-mxc/isp1504xc.c b/arch/arm/plat-mxc/isp1504xc.c
index bd975824aee4..c0f43172328d 100644
--- a/arch/arm/plat-mxc/isp1504xc.c
+++ b/arch/arm/plat-mxc/isp1504xc.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2005-2008 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
@@ -21,12 +21,14 @@
#include <asm/hardware.h>
#include <asm/arch/arc_otg.h>
+#include <asm/mach-types.h>
/* ISP 1504 register addresses */
#define ISP1504_VID_LOW 0x00 /* Vendor ID low */
#define ISP1504_VID_HIGH 0x01 /* Vendor ID high */
#define ISP1504_PID_LOW 0x02 /* Product ID low */
#define ISP1504_PID_HIGH 0x03 /* Product ID high */
+#define ISP1504_FUNC 0x04 /* Function Control */
#define ISP1504_ITFCTL 0x07 /* Interface Control */
#define ISP1504_OTGCTL 0x0A /* OTG Control */
@@ -44,6 +46,12 @@
#define DP_PULL_DOWN (1 << 1) /* enable DP Pull Down */
#define ID_PULL_UP (1 << 0) /* enable ID Pull Up */
+/* 1504 OTG Function Control Register bits */
+#define SUSPENDM (1 << 6) /* places the PHY into
+ low-power mode */
+#define DRV_RESET (1 << 5) /* Active HIGH transceiver
+ reset */
+
/*!
* read ULPI register 'reg' thru VIEWPORT register 'view'
*
@@ -123,7 +131,8 @@ extern int gpio_usbotg_hs_active(void);
static void isp1508_fix(u32 * view)
{
- gpio_usbotg_hs_active();
+ if (!machine_is_mx31_3ds())
+ gpio_usbotg_hs_active();
/* Set bits IND_PASS_THRU and IND_COMPL */
isp1504_set(0x60, ISP1504_ITFCTL, view);
@@ -199,11 +208,21 @@ static void isp1504_uninit(struct fsl_xcvr_ops *this)
pr_debug("%s:\n", __FUNCTION__);
}
+static void isp1504_suspend(struct fsl_xcvr_ops *this)
+{
+ pr_debug("%s\n", __func__);
+
+ /* send suspend command */
+ isp1504_clear(SUSPENDM, ISP1504_FUNC, &UOG_ULPIVIEW);
+ pr_debug("%s.\n", __func__);
+}
+
static struct fsl_xcvr_ops isp1504_ops = {
.name = "isp1504",
.xcvr_type = PORTSC_PTS_ULPI,
.init = isp1504_init,
.uninit = isp1504_uninit,
+ .suspend = isp1504_suspend,
.set_host = NULL,
.set_device = NULL,
.set_vbus_power = isp1504_set_vbus_power,
@@ -211,6 +230,7 @@ static struct fsl_xcvr_ops isp1504_ops = {
};
extern void fsl_usb_xcvr_register(struct fsl_xcvr_ops *xcvr_ops);
+extern int fsl_usb_xcvr_suspend(struct fsl_xcvr_ops *xcvr_ops);
static int __init isp1504xc_init(void)
{
@@ -218,6 +238,10 @@ static int __init isp1504xc_init(void)
fsl_usb_xcvr_register(&isp1504_ops);
+ /* suspend isp1504 */
+ if (fsl_usb_xcvr_suspend(&isp1504_ops))
+ pr_debug("%s: failed to suspend isp1504\n", __func__);
+
return 0;
}
diff --git a/arch/arm/plat-mxc/usb_common.c b/arch/arm/plat-mxc/usb_common.c
index 578a3dcee394..7abbc8694d52 100644
--- a/arch/arm/plat-mxc/usb_common.c
+++ b/arch/arm/plat-mxc/usb_common.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2004-2008 Freescale Semiconductor, Inc. All Rights Reserved.
*
* otg_{get,set}_transceiver() are from arm/plat-omap/usb.c.
* which is Copyright (C) 2004 Texas Instruments, Inc.
@@ -40,7 +40,9 @@
#include <linux/fsl_devices.h>
#include <linux/usb/otg.h>
#include <linux/usb/fsl_xcvr.h>
+#include <linux/regulator/regulator.h>
#include <asm/arch/arc_otg.h>
+#include <asm/mach-types.h>
#define MXC_NUMBER_USB_TRANSCEIVER 6
struct fsl_xcvr_ops *g_xc_ops[MXC_NUMBER_USB_TRANSCEIVER] = { NULL };
@@ -320,13 +322,16 @@ static void usbh2_set_ulpi_xcvr(void)
UCTRL_H2DT | /* disable H2 TLL */
UCTRL_H2PM; /* power mask */
- UH2_PORTSC1 &= ~PORTSC_PTS_MASK; /* set ULPI xcvr */
- UH2_PORTSC1 |= PORTSC_PTS_ULPI;
+ /* set ULPI xcvr */
+ UH2_PORTSC1 = (UH2_PORTSC1 & (~PORTSC_PTS_MASK)) | PORTSC_PTS_ULPI;
/* Turn off the usbpll for ulpi tranceivers */
clk_disable(usb_clk);
}
+extern void usbh2_get_xcvr_power(struct device *dev);
+extern void usbh2_put_xcvr_power(struct device *dev);
+
int fsl_usb_host_init(struct platform_device *pdev)
{
struct fsl_usb2_platform_data *pdata;
@@ -349,6 +354,17 @@ int fsl_usb_host_init(struct platform_device *pdev)
if (fsl_check_usbclk() != 0)
return -EINVAL;
+ /* set host2 usb phy usb3317 power supply for imx31 3 stack */
+ if ((pdata->xcvr_type == PORTSC_PTS_ULPI) && (machine_is_mx31_3ds())) {
+ pdata->xcvr_pwr =
+ kmalloc(sizeof(struct fsl_xcvr_power), GFP_KERNEL);
+ if (!(pdata->xcvr_pwr))
+ return -ENOMEM;
+
+ pdata->xcvr_pwr->usb_pdev = pdev;
+ usbh2_get_xcvr_power(&(pdev->dev));
+ }
+
pr_debug("%s: grab pins\n", __FUNCTION__);
if (pdata->gpio_usb_active())
return -EINVAL;
@@ -392,6 +408,11 @@ void fsl_usb_host_uninit(struct fsl_usb2_platform_data *pdata)
pdata->gpio_usb_inactive();
if (pdata->xcvr_type == PORTSC_PTS_SERIAL)
clk_disable(usb_clk);
+ else if ((pdata->xcvr_type == PORTSC_PTS_ULPI)
+ && (machine_is_mx31_3ds())) {
+ usbh2_put_xcvr_power(&(pdata->xcvr_pwr->usb_pdev->dev));
+ kfree(pdata->xcvr_pwr);
+ }
}
EXPORT_SYMBOL(fsl_usb_host_uninit);
@@ -490,6 +511,35 @@ static void otg_set_ulpi_xcvr(void)
clk_disable(usb_clk);
}
+extern int gpio_usbotg_hs_active(void);
+extern int gpio_usbotg_hs_inactive(void);
+
+int fsl_usb_xcvr_suspend(struct fsl_xcvr_ops *xcvr_ops)
+{
+ if (!machine_is_mx31_3ds())
+ return -ECANCELED;
+
+ if (xcvr_ops->xcvr_type == PORTSC_PTS_ULPI) {
+ if (fsl_check_usbclk() != 0)
+ return -EINVAL;
+ if (gpio_usbotg_hs_active())
+ return -EINVAL;
+ clk_enable(usb_clk);
+
+ otg_set_ulpi_xcvr();
+
+ if (xcvr_ops->suspend)
+ /* suspend transceiver */
+ xcvr_ops->suspend(xcvr_ops);
+
+ gpio_usbotg_hs_inactive();
+ clk_disable(usb_clk);
+ }
+ return 0;
+}
+
+EXPORT_SYMBOL(fsl_usb_xcvr_suspend);
+
static int otg_used = 0;
int usbotg_init(struct platform_device *pdev)
@@ -566,6 +616,12 @@ void usbotg_uninit(struct fsl_usb2_platform_data *pdata)
pdata->regs = NULL;
pdata->r_start = pdata->r_len = 0;
+ if (machine_is_mx31_3ds()) {
+ if (pdata->xcvr_ops && pdata->xcvr_ops->suspend)
+ pdata->xcvr_ops->suspend(pdata->xcvr_ops);
+ clk_disable(usb_clk);
+ }
+
pdata->gpio_usb_inactive();
if (pdata->xcvr_type == PORTSC_PTS_SERIAL)
clk_disable(usb_clk);