aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/whci
diff options
context:
space:
mode:
authorDavid Vrabel <david.vrabel@csr.com>2008-10-27 11:42:31 -0400
committerDavid Vrabel <david.vrabel@csr.com>2008-10-28 08:08:46 -0400
commit4d2bea4ca0adb4cebfbf89d34869c74081c42577 (patch)
tree3ed316eca5ab3228e2e01fc4a83c04297becd105 /drivers/usb/host/whci
parentd409f3bf47c5e5ae10601d079204e263bc176bcf (diff)
wusb: do a proper channel stop
When stopping the WUSB channel the host should send Channel Stop IEs giving the WUSB Channel Time of the last MMC. Both WHCI and HWA hosts provide a channel stop command for this. Signed-off-by: David Vrabel <david.vrabel@csr.com>
Diffstat (limited to 'drivers/usb/host/whci')
-rw-r--r--drivers/usb/host/whci/whcd.h2
-rw-r--r--drivers/usb/host/whci/whci-hc.h2
-rw-r--r--drivers/usb/host/whci/wusb.c15
3 files changed, 15 insertions, 4 deletions
diff --git a/drivers/usb/host/whci/whcd.h b/drivers/usb/host/whci/whcd.h
index 1d2a53bd39fd..1bbb8cb6bf80 100644
--- a/drivers/usb/host/whci/whcd.h
+++ b/drivers/usb/host/whci/whcd.h
@@ -136,7 +136,7 @@ int whc_do_gencmd(struct whc *whc, u32 cmd, u32 params, void *addr, size_t len);
136 136
137/* wusb.c */ 137/* wusb.c */
138int whc_wusbhc_start(struct wusbhc *wusbhc); 138int whc_wusbhc_start(struct wusbhc *wusbhc);
139void whc_wusbhc_stop(struct wusbhc *wusbhc); 139void whc_wusbhc_stop(struct wusbhc *wusbhc, int delay);
140int whc_mmcie_add(struct wusbhc *wusbhc, u8 interval, u8 repeat_cnt, 140int whc_mmcie_add(struct wusbhc *wusbhc, u8 interval, u8 repeat_cnt,
141 u8 handle, struct wuie_hdr *wuie); 141 u8 handle, struct wuie_hdr *wuie);
142int whc_mmcie_rm(struct wusbhc *wusbhc, u8 handle); 142int whc_mmcie_rm(struct wusbhc *wusbhc, u8 handle);
diff --git a/drivers/usb/host/whci/whci-hc.h b/drivers/usb/host/whci/whci-hc.h
index bff1eb7a35cf..51df7e313b38 100644
--- a/drivers/usb/host/whci/whci-hc.h
+++ b/drivers/usb/host/whci/whci-hc.h
@@ -410,6 +410,8 @@ struct dn_buf_entry {
410# define WUSBDNTSCTRL_SLOTS(s) ((s) << 0) 410# define WUSBDNTSCTRL_SLOTS(s) ((s) << 0)
411 411
412#define WUSBTIME 0x68 412#define WUSBTIME 0x68
413# define WUSBTIME_CHANNEL_TIME_MASK 0x00ffffff
414
413#define WUSBBPST 0x6c 415#define WUSBBPST 0x6c
414#define WUSBDIBUPDATED 0x70 416#define WUSBDIBUPDATED 0x70
415 417
diff --git a/drivers/usb/host/whci/wusb.c b/drivers/usb/host/whci/wusb.c
index 66e4ddcd961d..2befd475def4 100644
--- a/drivers/usb/host/whci/wusb.c
+++ b/drivers/usb/host/whci/wusb.c
@@ -64,8 +64,9 @@ static int whc_update_di(struct whc *whc, int idx)
64} 64}
65 65
66/* 66/*
67 * WHCI starts and stops MMCs based on there being a valid GTK so 67 * WHCI starts MMCs based on there being a valid GTK so these need
68 * these need only start/stop the asynchronous and periodic schedules. 68 * only start/stop the asynchronous and periodic schedules and send a
69 * channel stop command.
69 */ 70 */
70 71
71int whc_wusbhc_start(struct wusbhc *wusbhc) 72int whc_wusbhc_start(struct wusbhc *wusbhc)
@@ -78,12 +79,20 @@ int whc_wusbhc_start(struct wusbhc *wusbhc)
78 return 0; 79 return 0;
79} 80}
80 81
81void whc_wusbhc_stop(struct wusbhc *wusbhc) 82void whc_wusbhc_stop(struct wusbhc *wusbhc, int delay)
82{ 83{
83 struct whc *whc = wusbhc_to_whc(wusbhc); 84 struct whc *whc = wusbhc_to_whc(wusbhc);
85 u32 stop_time, now_time;
86 int ret;
84 87
85 pzl_stop(whc); 88 pzl_stop(whc);
86 asl_stop(whc); 89 asl_stop(whc);
90
91 now_time = le_readl(whc->base + WUSBTIME) & WUSBTIME_CHANNEL_TIME_MASK;
92 stop_time = (now_time + ((delay * 8) << 7)) & 0x00ffffff;
93 ret = whc_do_gencmd(whc, WUSBGENCMDSTS_CHAN_STOP, stop_time, NULL, 0);
94 if (ret == 0)
95 msleep(delay);
87} 96}
88 97
89int whc_mmcie_add(struct wusbhc *wusbhc, u8 interval, u8 repeat_cnt, 98int whc_mmcie_add(struct wusbhc *wusbhc, u8 interval, u8 repeat_cnt,