diff options
author | Enrico Scholz <enrico.scholz@sigma-chemnitz.de> | 2008-07-17 14:09:30 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-08-13 20:32:53 -0400 |
commit | 3f02a957d5eb0eeb01207a799086f2b347077f71 (patch) | |
tree | 1e163aaabe6b260a168ab3c4744066d471f75fb4 /drivers/usb/host | |
parent | a36c27dfd1003e6d6842fe77faaf868e3e6e9062 (diff) |
usb: ISP1760: improve pre-fetch timing
ISP1760 requires a delay of 90ns between programming the address and
reading the data. Current driver solves this by a mdelay(1) which is
very heavy weighted and slow. This patch applies the workaround from
the ISP1760 FAQ by using two different banks for PTD and payload data
and using a common wait for them. This wait is done by an additional
ISP1760 access (whose timing constraints guarantee the 90ns delay).
This improves speed when reading from an USB stick from:
$ time dd if=/dev/sda of=/dev/zero bs=65536 count=1638
real 1m 15.43s
user 0m 0.44s
sys 0m 39.46s
to
$ time dd if=/dev/sda of=/dev/zero bs=65536 count=1638
real 0m 18.53s
user 0m 0.16s
sys 0m 12.97s
[bigeasy@linutronix.de: fixed comment formating, moved define into
header file, obey 80 char rule]
Signed-off-by: Enrico Scholz <enrico.scholz@sigma-chemnitz.de>
Signed-off-by: Sebastian Siewior <bigeasy@linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/isp1760-hcd.c | 44 | ||||
-rw-r--r-- | drivers/usb/host/isp1760-hcd.h | 2 |
2 files changed, 33 insertions, 13 deletions
diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index db5f4f5c7a10..e209b3b709d6 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c | |||
@@ -126,9 +126,8 @@ static void isp1760_writel(const unsigned int val, __u32 __iomem *regs) | |||
126 | * doesn't quite work because some people have to enforce 32-bit access | 126 | * doesn't quite work because some people have to enforce 32-bit access |
127 | */ | 127 | */ |
128 | static void priv_read_copy(struct isp1760_hcd *priv, u32 *src, | 128 | static void priv_read_copy(struct isp1760_hcd *priv, u32 *src, |
129 | __u32 __iomem *dst, u32 offset, u32 len) | 129 | __u32 __iomem *dst, u32 len) |
130 | { | 130 | { |
131 | struct usb_hcd *hcd = priv_to_hcd(priv); | ||
132 | u32 val; | 131 | u32 val; |
133 | u8 *buff8; | 132 | u8 *buff8; |
134 | 133 | ||
@@ -136,11 +135,6 @@ static void priv_read_copy(struct isp1760_hcd *priv, u32 *src, | |||
136 | printk(KERN_ERR "ERROR: buffer: %p len: %d\n", src, len); | 135 | printk(KERN_ERR "ERROR: buffer: %p len: %d\n", src, len); |
137 | return; | 136 | return; |
138 | } | 137 | } |
139 | isp1760_writel(offset, hcd->regs + HC_MEMORY_REG); | ||
140 | /* XXX | ||
141 | * 90nsec delay, the spec says something how this could be avoided. | ||
142 | */ | ||
143 | mdelay(1); | ||
144 | 138 | ||
145 | while (len >= 4) { | 139 | while (len >= 4) { |
146 | *src = __raw_readl(dst); | 140 | *src = __raw_readl(dst); |
@@ -987,8 +981,20 @@ static void do_atl_int(struct usb_hcd *usb_hcd) | |||
987 | printk(KERN_ERR "qh is 0\n"); | 981 | printk(KERN_ERR "qh is 0\n"); |
988 | continue; | 982 | continue; |
989 | } | 983 | } |
990 | priv_read_copy(priv, (u32 *)&ptd, usb_hcd->regs + atl_regs, | 984 | isp1760_writel(atl_regs + ISP_BANK(0), usb_hcd->regs + |
991 | atl_regs, sizeof(ptd)); | 985 | HC_MEMORY_REG); |
986 | isp1760_writel(payload + ISP_BANK(1), usb_hcd->regs + | ||
987 | HC_MEMORY_REG); | ||
988 | /* | ||
989 | * write bank1 address twice to ensure the 90ns delay (time | ||
990 | * between BANK0 write and the priv_read_copy() call is at | ||
991 | * least 3*t_WHWL + 2*t_w11 = 3*25ns + 2*17ns = 92ns) | ||
992 | */ | ||
993 | isp1760_writel(payload + ISP_BANK(1), usb_hcd->regs + | ||
994 | HC_MEMORY_REG); | ||
995 | |||
996 | priv_read_copy(priv, (u32 *)&ptd, usb_hcd->regs + atl_regs + | ||
997 | ISP_BANK(0), sizeof(ptd)); | ||
992 | 998 | ||
993 | dw1 = le32_to_cpu(ptd.dw1); | 999 | dw1 = le32_to_cpu(ptd.dw1); |
994 | dw2 = le32_to_cpu(ptd.dw2); | 1000 | dw2 = le32_to_cpu(ptd.dw2); |
@@ -1091,7 +1097,7 @@ static void do_atl_int(struct usb_hcd *usb_hcd) | |||
1091 | case IN_PID: | 1097 | case IN_PID: |
1092 | priv_read_copy(priv, | 1098 | priv_read_copy(priv, |
1093 | priv->atl_ints[queue_entry].data_buffer, | 1099 | priv->atl_ints[queue_entry].data_buffer, |
1094 | usb_hcd->regs + payload, payload, | 1100 | usb_hcd->regs + payload + ISP_BANK(1), |
1095 | length); | 1101 | length); |
1096 | 1102 | ||
1097 | case OUT_PID: | 1103 | case OUT_PID: |
@@ -1206,8 +1212,20 @@ static void do_intl_int(struct usb_hcd *usb_hcd) | |||
1206 | continue; | 1212 | continue; |
1207 | } | 1213 | } |
1208 | 1214 | ||
1209 | priv_read_copy(priv, (u32 *)&ptd, usb_hcd->regs + int_regs, | 1215 | isp1760_writel(int_regs + ISP_BANK(0), usb_hcd->regs + |
1210 | int_regs, sizeof(ptd)); | 1216 | HC_MEMORY_REG); |
1217 | isp1760_writel(payload + ISP_BANK(1), usb_hcd->regs + | ||
1218 | HC_MEMORY_REG); | ||
1219 | /* | ||
1220 | * write bank1 address twice to ensure the 90ns delay (time | ||
1221 | * between BANK0 write and the priv_read_copy() call is at | ||
1222 | * least 3*t_WHWL + 2*t_w11 = 3*25ns + 2*17ns = 92ns) | ||
1223 | */ | ||
1224 | isp1760_writel(payload + ISP_BANK(1), usb_hcd->regs + | ||
1225 | HC_MEMORY_REG); | ||
1226 | |||
1227 | priv_read_copy(priv, (u32 *)&ptd, usb_hcd->regs + int_regs + | ||
1228 | ISP_BANK(0), sizeof(ptd)); | ||
1211 | dw1 = le32_to_cpu(ptd.dw1); | 1229 | dw1 = le32_to_cpu(ptd.dw1); |
1212 | dw3 = le32_to_cpu(ptd.dw3); | 1230 | dw3 = le32_to_cpu(ptd.dw3); |
1213 | check_int_err_status(le32_to_cpu(ptd.dw4)); | 1231 | check_int_err_status(le32_to_cpu(ptd.dw4)); |
@@ -1242,7 +1260,7 @@ static void do_intl_int(struct usb_hcd *usb_hcd) | |||
1242 | case IN_PID: | 1260 | case IN_PID: |
1243 | priv_read_copy(priv, | 1261 | priv_read_copy(priv, |
1244 | priv->int_ints[queue_entry].data_buffer, | 1262 | priv->int_ints[queue_entry].data_buffer, |
1245 | usb_hcd->regs + payload , payload, | 1263 | usb_hcd->regs + payload + ISP_BANK(1), |
1246 | length); | 1264 | length); |
1247 | case OUT_PID: | 1265 | case OUT_PID: |
1248 | 1266 | ||
diff --git a/drivers/usb/host/isp1760-hcd.h b/drivers/usb/host/isp1760-hcd.h index 6473dd86993c..3c61cd51cbb8 100644 --- a/drivers/usb/host/isp1760-hcd.h +++ b/drivers/usb/host/isp1760-hcd.h | |||
@@ -54,6 +54,8 @@ void deinit_kmem_cache(void); | |||
54 | #define BUFFER_MAP 0x7 | 54 | #define BUFFER_MAP 0x7 |
55 | 55 | ||
56 | #define HC_MEMORY_REG 0x33c | 56 | #define HC_MEMORY_REG 0x33c |
57 | #define ISP_BANK(x) ((x) << 16) | ||
58 | |||
57 | #define HC_PORT1_CTRL 0x374 | 59 | #define HC_PORT1_CTRL 0x374 |
58 | #define PORT1_POWER (3 << 3) | 60 | #define PORT1_POWER (3 << 3) |
59 | #define PORT1_INIT1 (1 << 7) | 61 | #define PORT1_INIT1 (1 << 7) |