diff options
author | Jun Li <r65092@freescale.com> | 2008-03-05 13:07:34 +0800 |
---|---|---|
committer | Daniel Schaeffer <daniel.schaeffer@timesys.com> | 2008-08-25 15:20:41 -0400 |
commit | 3bb34e6ac73ffcf58cdaa3f988cc84268b32b3c2 (patch) | |
tree | 9856fab200175a3669408f5f52242600d3127827 /arch | |
parent | 0844a8934f378cec24892cab393f798b7bba1381 (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_defconfig | 2 | ||||
-rw-r--r-- | arch/arm/mach-mx3/mx3_3stack_gpio.c | 23 | ||||
-rw-r--r-- | arch/arm/mach-mx3/usb.c | 40 | ||||
-rw-r--r-- | arch/arm/plat-mxc/isp1504xc.c | 28 | ||||
-rw-r--r-- | arch/arm/plat-mxc/usb_common.c | 62 |
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); |