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 | |
| 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>
| -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) |
