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