aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-10-09 12:34:52 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-10-09 12:34:52 -0400
commit1442138372d19907473cfc82c37e8dd7c3359034 (patch)
treed2ee2a1ddc5e608034e273b246269ebd696c410e /drivers/usb
parent902ff186114b50c859c46ac762d4b1e6223991d3 (diff)
parenta2767cfb1d9d97c3f861743f1ad595a80b75ec99 (diff)
Merge branch 'sh/for-2.6.32' of git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6
* 'sh/for-2.6.32' of git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6: sh: Don't allocate smaller sized mappings on every iteration sh: Try PMB mapping based on physical address, not mapping size sh: Plug PMB alloc memory leak sh: Sprinkle __uses_jump_to_uncached sh: enable sleep state LEDs on Ecovec24 usb: r8a66597-udc unaligned fifo fix sh: mach-ecovec24: Document DS2 switch settings. sh: Build fix: export __movmem sh: Disable unaligned kernel access printks by default. sh: mach-ecovec24: modify 1st MTD area to read only sh: mach-ecovec24: Add TouchScreen support sh: magicpanelr2 and dreamcast can use the generic I/O base. sh: Don't enable interrupts in the page fault path sh: Set the default I/O port base to P2SEG. sh: Handle ioport_map() cases for >= P1SEG addresses.
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/gadget/r8a66597-udc.h105
1 files changed, 62 insertions, 43 deletions
diff --git a/drivers/usb/gadget/r8a66597-udc.h b/drivers/usb/gadget/r8a66597-udc.h
index 03087e7b9190..9a537aa07968 100644
--- a/drivers/usb/gadget/r8a66597-udc.h
+++ b/drivers/usb/gadget/r8a66597-udc.h
@@ -131,31 +131,48 @@ static inline u16 r8a66597_read(struct r8a66597 *r8a66597, unsigned long offset)
131} 131}
132 132
133static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597, 133static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
134 unsigned long offset, u16 *buf, 134 unsigned long offset,
135 unsigned char *buf,
135 int len) 136 int len)
136{ 137{
138 unsigned long fifoaddr = r8a66597->reg + offset;
139 unsigned int data;
140 int i;
141
137 if (r8a66597->pdata->on_chip) { 142 if (r8a66597->pdata->on_chip) {
138 unsigned long fifoaddr = r8a66597->reg + offset; 143 /* 32-bit accesses for on_chip controllers */
139 unsigned long count; 144
140 union { 145 /* aligned buf case */
141 unsigned long dword; 146 if (len >= 4 && !((unsigned long)buf & 0x03)) {
142 unsigned char byte[4]; 147 insl(fifoaddr, buf, len / 4);
143 } data; 148 buf += len & ~0x03;
144 unsigned char *pb; 149 len &= 0x03;
145 int i; 150 }
146 151
147 count = len / 4; 152 /* unaligned buf case */
148 insl(fifoaddr, buf, count); 153 for (i = 0; i < len; i++) {
149 154 if (!(i & 0x03))
150 if (len & 0x00000003) { 155 data = inl(fifoaddr);
151 data.dword = inl(fifoaddr); 156
152 pb = (unsigned char *)buf + count * 4; 157 buf[i] = (data >> ((i & 0x03) * 8)) & 0xff;
153 for (i = 0; i < (len & 0x00000003); i++)
154 pb[i] = data.byte[i];
155 } 158 }
156 } else { 159 } else {
157 len = (len + 1) / 2; 160 /* 16-bit accesses for external controllers */
158 insw(r8a66597->reg + offset, buf, len); 161
162 /* aligned buf case */
163 if (len >= 2 && !((unsigned long)buf & 0x01)) {
164 insw(fifoaddr, buf, len / 2);
165 buf += len & ~0x01;
166 len &= 0x01;
167 }
168
169 /* unaligned buf case */
170 for (i = 0; i < len; i++) {
171 if (!(i & 0x01))
172 data = inw(fifoaddr);
173
174 buf[i] = (data >> ((i & 0x01) * 8)) & 0xff;
175 }
159 } 176 }
160} 177}
161 178
@@ -166,38 +183,40 @@ static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val,
166} 183}
167 184
168static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597, 185static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
169 unsigned long offset, u16 *buf, 186 unsigned long offset,
187 unsigned char *buf,
170 int len) 188 int len)
171{ 189{
172 unsigned long fifoaddr = r8a66597->reg + offset; 190 unsigned long fifoaddr = r8a66597->reg + offset;
191 int adj = 0;
192 int i;
173 193
174 if (r8a66597->pdata->on_chip) { 194 if (r8a66597->pdata->on_chip) {
175 unsigned long count; 195 /* 32-bit access only if buf is 32-bit aligned */
176 unsigned char *pb; 196 if (len >= 4 && !((unsigned long)buf & 0x03)) {
177 int i; 197 outsl(fifoaddr, buf, len / 4);
178 198 buf += len & ~0x03;
179 count = len / 4; 199 len &= 0x03;
180 outsl(fifoaddr, buf, count);
181
182 if (len & 0x00000003) {
183 pb = (unsigned char *)buf + count * 4;
184 for (i = 0; i < (len & 0x00000003); i++) {
185 if (r8a66597_read(r8a66597, CFIFOSEL) & BIGEND)
186 outb(pb[i], fifoaddr + i);
187 else
188 outb(pb[i], fifoaddr + 3 - i);
189 }
190 } 200 }
191 } else { 201 } else {
192 int odd = len & 0x0001; 202 /* 16-bit access only if buf is 16-bit aligned */
193 203 if (len >= 2 && !((unsigned long)buf & 0x01)) {
194 len = len / 2; 204 outsw(fifoaddr, buf, len / 2);
195 outsw(fifoaddr, buf, len); 205 buf += len & ~0x01;
196 if (unlikely(odd)) { 206 len &= 0x01;
197 buf = &buf[len];
198 outb((unsigned char)*buf, fifoaddr);
199 } 207 }
200 } 208 }
209
210 /* adjust fifo address in the little endian case */
211 if (!(r8a66597_read(r8a66597, CFIFOSEL) & BIGEND)) {
212 if (r8a66597->pdata->on_chip)
213 adj = 0x03; /* 32-bit wide */
214 else
215 adj = 0x01; /* 16-bit wide */
216 }
217
218 for (i = 0; i < len; i++)
219 outb(buf[i], fifoaddr + adj - (i & adj));
201} 220}
202 221
203static inline void r8a66597_mdfy(struct r8a66597 *r8a66597, 222static inline void r8a66597_mdfy(struct r8a66597 *r8a66597,