aboutsummaryrefslogtreecommitdiffstats
path: root/usb
diff options
authorGreg Kroah-Hartman <gregkh@suse.de>2009-03-19 20:54:08 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2009-03-19 20:54:08 -0700
commit70b19ef9d8fddf33471b81ec98b1fe60af5d535a (patch)
treeb0d24db1f3011454b8afd2a8c1f0724244dc028e /usb
parent78f45e0b908f2f3c79c6445b936105e9423942fd (diff)
downloadpatches-70b19ef9d8fddf33471b81ec98b1fe60af5d535a.tar.gz
more patches
Diffstat (limited to 'usb')
-rw-r--r--usb/usb-gadget-composite-device-level-suspend-resume-hooks.patch85
-rw-r--r--usb/usb-r8a66597-hcd-suspend-resume-support.patch184
2 files changed, 269 insertions, 0 deletions
diff --git a/usb/usb-gadget-composite-device-level-suspend-resume-hooks.patch b/usb/usb-gadget-composite-device-level-suspend-resume-hooks.patch
new file mode 100644
index 00000000000000..02fbbdee2a55db
--- /dev/null
+++ b/usb/usb-gadget-composite-device-level-suspend-resume-hooks.patch
@@ -0,0 +1,85 @@
+From david-b@pacbell.net Thu Mar 19 20:32:29 2009
+From: David Brownell <david-b@pacbell.net>
+Date: Thu, 19 Mar 2009 14:14:17 -0700
+Subject: USB: gadget: composite device-level suspend/resume hooks
+To: Greg KH <greg@kroah.com>
+Cc: Felipe Balbi <felipe.balbi@nokia.com>
+Message-ID: <200903191414.17132.david-b@pacbell.net>
+Content-Disposition: inline
+
+
+From: David Brownell <dbrownell@users.sourceforge.net>
+
+Address one open question in the composite gadget framework:
+Yes, we should have device-level suspend/resume callbacks
+in addition to the function-level ones. We have at least one
+scenario (with gadget zero in OTG test mode) that's awkward
+to handle without it.
+
+Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
+Cc: Felipe Balbi <felipe.balbi@nokia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/gadget/composite.c | 8 ++++++--
+ include/linux/usb/composite.h | 8 ++++++++
+ 2 files changed, 14 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/gadget/composite.c
++++ b/drivers/usb/gadget/composite.c
+@@ -1014,7 +1014,7 @@ composite_suspend(struct usb_gadget *gad
+ struct usb_composite_dev *cdev = get_gadget_data(gadget);
+ struct usb_function *f;
+
+- /* REVISIT: should we have config and device level
++ /* REVISIT: should we have config level
+ * suspend/resume callbacks?
+ */
+ DBG(cdev, "suspend\n");
+@@ -1024,6 +1024,8 @@ composite_suspend(struct usb_gadget *gad
+ f->suspend(f);
+ }
+ }
++ if (composite->suspend)
++ composite->suspend(cdev);
+ }
+
+ static void
+@@ -1032,10 +1034,12 @@ composite_resume(struct usb_gadget *gadg
+ struct usb_composite_dev *cdev = get_gadget_data(gadget);
+ struct usb_function *f;
+
+- /* REVISIT: should we have config and device level
++ /* REVISIT: should we have config level
+ * suspend/resume callbacks?
+ */
+ DBG(cdev, "resume\n");
++ if (composite->resume)
++ composite->resume(cdev);
+ if (cdev->config) {
+ list_for_each_entry(f, &cdev->config->functions, list) {
+ if (f->resume)
+--- a/include/linux/usb/composite.h
++++ b/include/linux/usb/composite.h
+@@ -244,6 +244,10 @@ int usb_add_config(struct usb_composite_
+ * value; it should return zero on successful initialization.
+ * @unbind: Reverses @bind(); called as a side effect of unregistering
+ * this driver.
++ * @suspend: Notifies when the host stops sending USB traffic,
++ * after function notifications
++ * @resume: Notifies configuration when the host restarts USB traffic,
++ * before function notifications
+ *
+ * Devices default to reporting self powered operation. Devices which rely
+ * on bus powered operation should report this in their @bind() method.
+@@ -268,6 +272,10 @@ struct usb_composite_driver {
+
+ int (*bind)(struct usb_composite_dev *);
+ int (*unbind)(struct usb_composite_dev *);
++
++ /* global suspend hooks */
++ void (*suspend)(struct usb_composite_dev *);
++ void (*resume)(struct usb_composite_dev *);
+ };
+
+ extern int usb_composite_register(struct usb_composite_driver *);
diff --git a/usb/usb-r8a66597-hcd-suspend-resume-support.patch b/usb/usb-r8a66597-hcd-suspend-resume-support.patch
new file mode 100644
index 00000000000000..5252fd83819196
--- /dev/null
+++ b/usb/usb-r8a66597-hcd-suspend-resume-support.patch
@@ -0,0 +1,184 @@
+From shimoda.yoshihiro@renesas.com Thu Mar 19 20:31:31 2009
+From: Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
+Date: Thu, 19 Mar 2009 14:18:15 +0900
+Subject: USB: r8a66597-hcd: suspend/resume support
+To: greg@kroah.com
+Message-ID: <49C1D597.6010206@renesas.com>
+
+
+Fix the problem that system cannot suspend.
+
+Signed-off-by: Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/r8a66597-hcd.c | 101 +++++++++++++++++++++++++++++++++++++++-
+ drivers/usb/host/r8a66597.h | 2
+ 2 files changed, 102 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/host/r8a66597.h
++++ b/drivers/usb/host/r8a66597.h
+@@ -504,6 +504,8 @@ struct r8a66597 {
+
+ struct list_head child_device;
+ unsigned long child_connect_map[4];
++
++ unsigned bus_suspended:1;
+ };
+
+ static inline struct r8a66597 *hcd_to_r8a66597(struct usb_hcd *hcd)
+--- a/drivers/usb/host/r8a66597-hcd.c
++++ b/drivers/usb/host/r8a66597-hcd.c
+@@ -1013,6 +1013,9 @@ static void r8a66597_check_syssts(struct
+
+ r8a66597_write(r8a66597, ~DTCH, get_intsts_reg(port));
+ r8a66597_bset(r8a66597, DTCHE, get_intenb_reg(port));
++
++ if (r8a66597->bus_suspended)
++ usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597));
+ }
+
+ /* this function must be called with interrupt disabled */
+@@ -1614,6 +1617,11 @@ static irqreturn_t r8a66597_irq(struct u
+ r8a66597_bclr(r8a66597, DTCHE, INTENB2);
+ r8a66597_usb_disconnect(r8a66597, 1);
+ }
++ if (mask2 & BCHG) {
++ r8a66597_write(r8a66597, ~BCHG, INTSTS2);
++ r8a66597_bclr(r8a66597, BCHGE, INTENB2);
++ usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597));
++ }
+ }
+
+ if (mask1) {
+@@ -1629,6 +1637,12 @@ static irqreturn_t r8a66597_irq(struct u
+ r8a66597_bclr(r8a66597, DTCHE, INTENB1);
+ r8a66597_usb_disconnect(r8a66597, 0);
+ }
++ if (mask1 & BCHG) {
++ r8a66597_write(r8a66597, ~BCHG, INTSTS1);
++ r8a66597_bclr(r8a66597, BCHGE, INTENB1);
++ usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597));
++ }
++
+ if (mask1 & SIGN) {
+ r8a66597_write(r8a66597, ~SIGN, INTSTS1);
+ status = get_urb_error(r8a66597, 0);
+@@ -2140,7 +2154,7 @@ static int r8a66597_hub_control(struct u
+
+ switch (wValue) {
+ case USB_PORT_FEAT_ENABLE:
+- rh->port &= (1 << USB_PORT_FEAT_POWER);
++ rh->port &= ~(1 << USB_PORT_FEAT_POWER);
+ break;
+ case USB_PORT_FEAT_SUSPEND:
+ break;
+@@ -2212,6 +2226,68 @@ error:
+ return ret;
+ }
+
++#if defined(CONFIG_PM)
++static int r8a66597_bus_suspend(struct usb_hcd *hcd)
++{
++ struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
++ int port;
++
++ dbg("%s", __func__);
++
++ for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) {
++ struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
++ unsigned long dvstctr_reg = get_dvstctr_reg(port);
++
++ if (!(rh->port & (1 << USB_PORT_FEAT_ENABLE)))
++ continue;
++
++ dbg("suspend port = %d", port);
++ r8a66597_bclr(r8a66597, UACT, dvstctr_reg); /* suspend */
++ rh->port |= 1 << USB_PORT_FEAT_SUSPEND;
++
++ if (rh->dev->udev->do_remote_wakeup) {
++ msleep(3); /* waiting last SOF */
++ r8a66597_bset(r8a66597, RWUPE, dvstctr_reg);
++ r8a66597_write(r8a66597, ~BCHG, get_intsts_reg(port));
++ r8a66597_bset(r8a66597, BCHGE, get_intenb_reg(port));
++ }
++ }
++
++ r8a66597->bus_suspended = 1;
++
++ return 0;
++}
++
++static int r8a66597_bus_resume(struct usb_hcd *hcd)
++{
++ struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
++ int port;
++
++ dbg("%s", __func__);
++
++ for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) {
++ struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
++ unsigned long dvstctr_reg = get_dvstctr_reg(port);
++
++ if (!(rh->port & (1 << USB_PORT_FEAT_SUSPEND)))
++ continue;
++
++ dbg("resume port = %d", port);
++ rh->port &= ~(1 << USB_PORT_FEAT_SUSPEND);
++ rh->port |= 1 << USB_PORT_FEAT_C_SUSPEND;
++ r8a66597_mdfy(r8a66597, RESUME, RESUME | UACT, dvstctr_reg);
++ msleep(50);
++ r8a66597_mdfy(r8a66597, UACT, RESUME | UACT, dvstctr_reg);
++ }
++
++ return 0;
++
++}
++#else
++#define r8a66597_bus_suspend NULL
++#define r8a66597_bus_resume NULL
++#endif
++
+ static struct hc_driver r8a66597_hc_driver = {
+ .description = hcd_name,
+ .hcd_priv_size = sizeof(struct r8a66597),
+@@ -2242,16 +2318,39 @@ static struct hc_driver r8a66597_hc_driv
+ */
+ .hub_status_data = r8a66597_hub_status_data,
+ .hub_control = r8a66597_hub_control,
++ .bus_suspend = r8a66597_bus_suspend,
++ .bus_resume = r8a66597_bus_resume,
+ };
+
+ #if defined(CONFIG_PM)
+ static int r8a66597_suspend(struct platform_device *pdev, pm_message_t state)
+ {
++ struct r8a66597 *r8a66597 = dev_get_drvdata(&pdev->dev);
++ int port;
++
++ dbg("%s", __func__);
++
++ disable_controller(r8a66597);
++
++ for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) {
++ struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
++
++ rh->port = 0x00000000;
++ }
++
+ return 0;
+ }
+
+ static int r8a66597_resume(struct platform_device *pdev)
+ {
++ struct r8a66597 *r8a66597 = dev_get_drvdata(&pdev->dev);
++ struct usb_hcd *hcd = r8a66597_to_hcd(r8a66597);
++
++ dbg("%s", __func__);
++
++ enable_controller(r8a66597);
++ usb_root_hub_lost_power(hcd->self.root_hub);
++
+ return 0;
+ }
+ #else /* if defined(CONFIG_PM) */