summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
-rw-r--r--drivers/usb/gadget/arcotg_udc.c15
-rw-r--r--drivers/usb/gadget/inode.c115
-rw-r--r--include/linux/fsl_devices.h1
-rw-r--r--include/linux/usb/fsl_xcvr.h8
9 files changed, 279 insertions, 15 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);
diff --git a/drivers/usb/gadget/arcotg_udc.c b/drivers/usb/gadget/arcotg_udc.c
index 82415d27fe95..47bad5979edd 100644
--- a/drivers/usb/gadget/arcotg_udc.c
+++ b/drivers/usb/gadget/arcotg_udc.c
@@ -1743,6 +1743,21 @@ static void setup_received_irq(struct arcotg_udc *udc,
}
if (!handled) {
+ /*!
+ * 0x66 - Device_Reset_Request of Still Image Capture Device,
+ * 0x22 - SET_CONTROL_LINE_STATE of Communication Device
+ */
+ if (setup->bRequest == 0x66 || setup->bRequest == 0x22) {
+ udc->ep0_dir = USB_DIR_IN;
+ udc->driver->setup(&udc->gadget,
+ &udc->local_setup_buff);
+ udc->ep0_state = WAIT_FOR_OUT_STATUS;
+ return;
+ }
+ /* 0x65 - Get_Extended_Event_Data of Still Image Capture Device */
+ if (setup->bRequest == 0x65)
+ return;
+
if (udc->driver->setup(&udc->gadget, &udc->local_setup_buff)
!= 0) {
Ep0Stall(udc);
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 47ef8bd58a00..7b79792ffa5b 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -39,6 +39,8 @@
#include <linux/usb/gadgetfs.h>
#include <linux/usb/gadget.h>
+#include <linux/delay.h>
+#include <linux/time.h>
/*
* The gadgetfs API maps each endpoint to a file descriptor so that you
@@ -80,6 +82,9 @@ MODULE_DESCRIPTION (DRIVER_DESC);
MODULE_AUTHOR ("David Brownell");
MODULE_LICENSE ("GPL");
+/* Cancel IO, To store the bulkin and bulkout ep data. */
+static struct ep_data *gp_ep_bulkin_data;
+static struct ep_data *gp_ep_bulkout_data;
/*----------------------------------------------------------------------*/
@@ -266,6 +271,10 @@ static const char *CHIP;
#define INFO(dev,fmt,args...) \
xprintk(dev , KERN_INFO , fmt , ## args)
+/* Cancel IO */
+static int mtp_ctrl_cmd;
+static int gbCancelFlag;
+static unsigned long mtptimestamp;
/*----------------------------------------------------------------------*/
@@ -276,6 +285,17 @@ static const char *CHIP;
* precise FIFO status when recovering from cancellation.
*/
+/* Cancel IO */
+static void cancel_io_process(void *data)
+{
+ if (gp_ep_bulkout_data->req->status == -EINPROGRESS)
+ usb_ep_dequeue(gp_ep_bulkout_data->ep, gp_ep_bulkout_data->req);
+
+ if (gp_ep_bulkin_data->req->status == -EINPROGRESS)
+ usb_ep_dequeue(gp_ep_bulkin_data->ep, gp_ep_bulkin_data->req);
+}
+static DECLARE_DELAYED_WORK(cancel_work, cancel_io_process);
+
static void epio_complete (struct usb_ep *ep, struct usb_request *req)
{
struct ep_data *epdata = ep->driver_data;
@@ -872,10 +892,13 @@ ep_open (struct inode *inode, struct file *fd)
{
struct ep_data *data = inode->i_private;
int value = -EBUSY;
+ char *epin = "ep1in";
+ char *epout = "ep1out";
if (down_interruptible (&data->lock) != 0)
return -EINTR;
spin_lock_irq (&data->dev->lock);
+
if (data->dev->state == STATE_DEV_UNBOUND)
value = -ENOENT;
else if (data->state == STATE_EP_DISABLED) {
@@ -884,9 +907,16 @@ ep_open (struct inode *inode, struct file *fd)
get_ep (data);
fd->private_data = data;
VDEBUG (data->dev, "%s ready\n", data->name);
+ /* Cancel IO */
+ if (0 == strcmp(data->name, epin))
+ gp_ep_bulkin_data = fd->private_data;
+
+ if (0 == strcmp(data->name, epout))
+ gp_ep_bulkout_data = fd->private_data;
} else
DBG (data->dev, "%s state %d\n",
data->name, data->state);
+
spin_unlock_irq (&data->dev->lock);
up (&data->lock);
return value;
@@ -998,7 +1028,7 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr)
retval = -EL2HLT;
dev->state = STATE_DEV_CONNECTED;
- } else if (len == 0) { /* ack SET_CONFIGURATION etc */
+ } else if (len == 0) { /* ack SET_CONFIGURATION etc */
struct usb_ep *ep = dev->gadget->ep0;
struct usb_request *req = dev->req;
@@ -1019,7 +1049,7 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr)
usb_gadget_vbus_draw(dev->gadget, 2 * power);
}
- } else { /* collect OUT data */
+ } else { /* collect OUT data */
if ((fd->f_flags & O_NONBLOCK) != 0
&& !dev->setup_out_ready) {
retval = -EAGAIN;
@@ -1044,11 +1074,15 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr)
retval = -EIO;
else {
len = min (len, (size_t)dev->req->actual);
-// FIXME don't call this with the spinlock held ...
+/* FIXME don't call this with the spinlock held ... */
if (copy_to_user (buf, dev->req->buf, len))
retval = -EFAULT;
+ else
+ /* Bug of Cancel IO 6 bytes read. */
+ retval = len;
clean_req (dev->gadget->ep0, dev->req);
/* NOTE userspace can't yet choose to stall */
+ dev->state = STATE_DEV_CONNECTED; /* Cancel IO */
}
}
goto done;
@@ -1062,6 +1096,12 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr)
len -= len % sizeof (struct usb_gadgetfs_event);
dev->usermode_setup = 1;
+ /* Cancel IO, signal abort blocked IO. */
+ if (mtp_ctrl_cmd == 1) {
+ mtp_ctrl_cmd = 0;
+ schedule_delayed_work(&cancel_work, HZ / 100);
+ }
+
scan:
/* return queued events right away */
if (dev->ev_next != 0) {
@@ -1386,6 +1426,16 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
struct usb_gadgetfs_event *event;
u16 w_value = le16_to_cpu(ctrl->wValue);
u16 w_length = le16_to_cpu(ctrl->wLength);
+ struct timeval tv;
+
+ /* Cancel IO */
+ if (0x67 == ctrl->bRequest && 1 == gbCancelFlag
+ && dev->state == STATE_DEV_SETUP)
+ dev->state = STATE_DEV_CONNECTED;
+
+ if (0x67 == ctrl->bRequest && 2 == mtp_ctrl_cmd
+ && dev->state == STATE_DEV_SETUP)
+ dev->state = STATE_DEV_CONNECTED;
spin_lock (&dev->lock);
dev->setup_abort = 0;
@@ -1413,6 +1463,11 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
*/
} else if (dev->state == STATE_DEV_SETUP)
dev->setup_abort = 1;
+ /*Cancel IO */
+ if (mtp_ctrl_cmd == 1 && gbCancelFlag == 1 && dev->setup_abort == 1) {
+ INFO(dev, "0x64->setup\n");
+ dev->setup_abort = 0;
+ }
req->buf = dev->rbuf;
req->dma = DMA_ADDR_INVALID;
@@ -1438,7 +1493,7 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
make_qualifier (dev);
break;
case USB_DT_OTHER_SPEED_CONFIG:
- // FALLTHROUGH
+ /* FALLTHROUGH */
#endif
case USB_DT_CONFIG:
value = config_buf (dev,
@@ -1545,11 +1600,63 @@ delegate:
/* we can't currently stall these */
dev->setup_can_stall = 0;
}
+ /* Cancel IO */
+ if (0x67 == ctrl->bRequest && 1 == gbCancelFlag) {
+ gbCancelFlag = 0;
+
+ setup_req(gadget->ep0, dev->req, 4);
+ *(unsigned long *)dev->req->buf = 0x20190004;
+ usb_ep_queue(gadget->ep0, dev->req, GFP_ATOMIC);
+
+ spin_unlock(&dev->lock);
+ return 0;
+ }
+ if (ctrl->bRequest == 0x67 && mtp_ctrl_cmd == 2) {
+ /* get status */
+ mtp_ctrl_cmd = 0;
+ }
/* state changes when reader collects event */
event = next_event (dev, GADGETFS_SETUP);
event->u.setup = *ctrl;
+ /* Cancel IO */
+ if (0x64 == ctrl->bRequest) {
+ mtp_ctrl_cmd = 1;
+ gbCancelFlag = 1;
+
+ /* get the timestamp */
+ do_gettimeofday(&tv);
+ mtptimestamp = tv.tv_usec;
+ event->u.setup.wValue =
+ (unsigned short)tv.tv_usec;
+ }
+ if (0x66 == ctrl->bRequest) {
+ /* get the timestamp */
+ do_gettimeofday(&tv);
+ mtptimestamp = tv.tv_usec;
+ event->u.setup.wValue =
+ (unsigned short)tv.tv_usec;
+ }
+
ep0_readable (dev);
+ /* Reset request. */
+ if (ctrl->bRequest == 0x66) { /* reset ,send ZLP */
+ mtp_ctrl_cmd = 2;
+
+ if (gp_ep_bulkout_data->req->status ==
+ -EINPROGRESS) {
+ usb_ep_dequeue(gp_ep_bulkout_data->ep,
+ gp_ep_bulkout_data->req);
+ }
+ if (gp_ep_bulkin_data->req->status ==
+ -EINPROGRESS) {
+ usb_ep_dequeue(gp_ep_bulkin_data->ep,
+ gp_ep_bulkin_data->req);
+ }
+ }
+ if (ctrl->bRequest == 0x65)
+ pr_debug("i:0x65,not supported\n");
+
spin_unlock (&dev->lock);
return 0;
}
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
index f1195d70cbfd..031d88517ba9 100644
--- a/include/linux/fsl_devices.h
+++ b/include/linux/fsl_devices.h
@@ -123,6 +123,7 @@ struct fsl_usb2_platform_data {
int does_otg;
unsigned power_budget; /* for hcd->power_budget */
struct fsl_xcvr_ops *xcvr_ops;
+ struct fsl_xcvr_power *xcvr_pwr;
int (*gpio_usb_active) (void);
void (*gpio_usb_inactive) (void);
};
diff --git a/include/linux/usb/fsl_xcvr.h b/include/linux/usb/fsl_xcvr.h
index ea4a11d4242e..b15990a9808c 100644
--- a/include/linux/usb/fsl_xcvr.h
+++ b/include/linux/usb/fsl_xcvr.h
@@ -1,5 +1,7 @@
#ifndef __LINUX_USB_FSL_XCVR_H
#define __LINUX_USB_FSL_XCVR_H
+#include <linux/platform_device.h>
+#include <linux/regulator/regulator.h>
/**
* @name: transceiver name
* @xcvr_type: one of PORTSC_PTS_{UTMI,SERIAL,ULPI}
@@ -15,10 +17,16 @@ struct fsl_xcvr_ops {
void (*init) (struct fsl_xcvr_ops * ops);
void (*uninit) (struct fsl_xcvr_ops * ops);
+ void (*suspend) (struct fsl_xcvr_ops *ops);
void (*set_host) (void);
void (*set_device) (void);
void (*set_vbus_power) (u32 * view, int on);
void (*set_remote_wakeup) (u32 * view);
};
+struct fsl_xcvr_power {
+ struct platform_device *usb_pdev;
+ struct regulator *regu1;
+ struct regulator *regu2;
+};
#endif