diff options
Diffstat (limited to 'drivers/usb/gadget/r8a66597-udc.h')
-rw-r--r-- | drivers/usb/gadget/r8a66597-udc.h | 105 |
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 | ||
133 | static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597, | 133 | static 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 | ||
168 | static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597, | 185 | static 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 | ||
203 | static inline void r8a66597_mdfy(struct r8a66597 *r8a66597, | 222 | static inline void r8a66597_mdfy(struct r8a66597 *r8a66597, |