summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaurus Cuelenaere <mcuelenaere@gmail.com>2008-12-31 18:15:24 +0000
committerMaurus Cuelenaere <mcuelenaere@gmail.com>2008-12-31 18:15:24 +0000
commit5bf0cf59102f6a0fa812d7f60f954b5cc9ab834a (patch)
tree410a1436005800874a2ff3939e2671b972901f97
parenta2e80d573ca83a66b3aacdf9fe966c9528918c15 (diff)
downloadrockbox-5bf0cf59102f6a0fa812d7f60f954b5cc9ab834a.tar.gz
rockbox-5bf0cf59102f6a0fa812d7f60f954b5cc9ab834a.zip
Ingenic Jz4740:
* Fix compiling * More USB work git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19628 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/export/jz4740.h18
-rw-r--r--firmware/target/mips/ingenic_jz47xx/usb-jz4740.c87
2 files changed, 71 insertions, 34 deletions
diff --git a/firmware/export/jz4740.h b/firmware/export/jz4740.h
index 4b6008a9ac..409d1d5a6a 100644
--- a/firmware/export/jz4740.h
+++ b/firmware/export/jz4740.h
@@ -5102,32 +5102,32 @@ struct Ration2m
5102#define W_COEF_MSK 0xFF 5102#define W_COEF_MSK 0xFF
5103 5103
5104// function about REG_CTRL 5104// function about REG_CTRL
5105#define stop_ipu(IPU_V_BASE) \ 5105#define IPU_STOP_IPU(IPU_V_BASE) \
5106 REG32(IPU_V_BASE + REG_CTRL) &= ~IPU_EN; 5106 REG32(IPU_V_BASE + REG_CTRL) &= ~IPU_EN;
5107 5107
5108#define run_ipu(IPU_V_BASE) \ 5108#define IPU_RUN_IPU(IPU_V_BASE) \
5109 REG32(IPU_V_BASE + REG_CTRL) |= IPU_EN; 5109 REG32(IPU_V_BASE + REG_CTRL) |= IPU_EN;
5110 5110
5111#define reset_ipu(IPU_V_BASE) \ 5111#define IPU_RESET_IPU(IPU_V_BASE) \
5112 REG32(IPU_V_BASE + REG_CTRL) |= IPU_RESET; 5112 REG32(IPU_V_BASE + REG_CTRL) |= IPU_RESET;
5113 5113
5114#define disable_irq(IPU_V_BASE) \ 5114#define IPU_DISABLE_IRQ(IPU_V_BASE) \
5115 REG32(IPU_V_BASE + REG_CTRL) &= ~FM_IRQ_EN; 5115 REG32(IPU_V_BASE + REG_CTRL) &= ~FM_IRQ_EN;
5116 5116
5117#define disable_rsize(IPU_V_BASE) \ 5117#define IPU_DISABLE_RSIZE(IPU_V_BASE) \
5118 REG32(IPU_V_BASE + REG_CTRL) &= ~RSZ_EN; 5118 REG32(IPU_V_BASE + REG_CTRL) &= ~RSZ_EN;
5119 5119
5120#define enable_rsize(IPU_V_BASE) \ 5120#define IPU_ENABLE_RSIZE(IPU_V_BASE) \
5121 REG32(IPU_V_BASE + REG_CTRL) |= RSZ_EN; 5121 REG32(IPU_V_BASE + REG_CTRL) |= RSZ_EN;
5122 5122
5123#define ipu_is_enable(IPU_V_BASE) \ 5123#define IPU_IS_ENABLED(IPU_V_BASE) \
5124 (REG32(IPU_V_BASE + REG_CTRL) & IPU_EN) 5124 (REG32(IPU_V_BASE + REG_CTRL) & IPU_EN)
5125 5125
5126// function about REG_STATUS 5126// function about REG_STATUS
5127#define clear_end_flag(IPU_V_BASE) \ 5127#define IPU_CLEAR_END_FLAG(IPU_V_BASE) \
5128 REG32(IPU_V_BASE + REG_STATUS) &= ~OUT_END; 5128 REG32(IPU_V_BASE + REG_STATUS) &= ~OUT_END;
5129 5129
5130#define polling_end_flag(IPU_V_BASE) \ 5130#define IPU_POLLING_END_FLAG(IPU_V_BASE) \
5131 (REG32(IPU_V_BASE + REG_STATUS) & OUT_END) 5131 (REG32(IPU_V_BASE + REG_STATUS) & OUT_END)
5132 5132
5133/* parameter 5133/* parameter
diff --git a/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c
index eda3fb3b88..cc8d5afa20 100644
--- a/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c
+++ b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c
@@ -30,6 +30,12 @@
30#include "jz4740.h" 30#include "jz4740.h"
31#include "thread.h" 31#include "thread.h"
32 32
33/*
34 The Jz4740 USB controller is called MUSBHSFC in the datasheet.
35 It also seems to be a more generic controller, with support for
36 up to 15 endpoints (the Jz4740 only has 3).
37*/
38
33#define USB_EP0_IDLE 0 39#define USB_EP0_IDLE 0
34#define USB_EP0_RX 1 40#define USB_EP0_RX 1
35#define USB_EP0_TX 2 41#define USB_EP0_TX 2
@@ -162,13 +168,16 @@ static void flushFIFO(struct usb_endpoint *ep)
162 168
163static void EP0_send(void) 169static void EP0_send(void)
164{ 170{
165 register struct usb_endpoint* ep = &endpoints[1]; 171 struct usb_endpoint* ep = &endpoints[1];
166 register unsigned int length; 172 unsigned int length;
173 unsigned char csr0;
174
175 select_endpoint(0);
176 csr0 = REG_USB_REG_CSR0;
167 177
168 if(ep->length == 0) 178 if(ep->length == 0)
169 { 179 {
170 select_endpoint(0); 180 REG_USB_REG_CSR0 = (csr0 | USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND);
171 REG_USB_REG_CSR0 |= (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND);
172 return; 181 return;
173 } 182 }
174 183
@@ -177,22 +186,22 @@ static void EP0_send(void)
177 else 186 else
178 length = (EP_BUF_LEFT(ep) <= ep->fifo_size ? EP_BUF_LEFT(ep) : ep->fifo_size); 187 length = (EP_BUF_LEFT(ep) <= ep->fifo_size ? EP_BUF_LEFT(ep) : ep->fifo_size);
179 188
180 select_endpoint(0);
181 writeFIFO(ep, length); 189 writeFIFO(ep, length);
182 ep->sent += length; 190 ep->sent += length;
183 191
184 if(ep->sent >= ep->length) 192 if(ep->sent >= ep->length)
185 { 193 {
186 REG_USB_REG_CSR0 |= (USB_CSR0_INPKTRDY | USB_CSR0_DATAEND); /* Set data end! */ 194 REG_USB_REG_CSR0 = (csr0 | USB_CSR0_INPKTRDY | USB_CSR0_DATAEND); /* Set data end! */
187 ep0state = USB_EP0_IDLE; 195 ep0state = USB_EP0_IDLE;
188 } 196 }
189 else 197 else
190 REG_USB_REG_CSR0 |= USB_CSR0_INPKTRDY; 198 REG_USB_REG_CSR0 = (csr0 | USB_CSR0_INPKTRDY);
191} 199}
192 200
193static void EP0_handler(void) 201static void EP0_handler(void)
194{ 202{
195logf("EP0_handler"); 203 logf("EP0_handler");
204
196 register unsigned char csr0; 205 register unsigned char csr0;
197 206
198 /* Read CSR0 */ 207 /* Read CSR0 */
@@ -204,7 +213,7 @@ logf("EP0_handler");
204 */ 213 */
205 if (csr0 & USB_CSR0_SENTSTALL) 214 if (csr0 & USB_CSR0_SENTSTALL)
206 { 215 {
207 REG_USB_REG_CSR0 &= ~USB_CSR0_SENTSTALL; 216 REG_USB_REG_CSR0 = csr0 & ~USB_CSR0_SENTSTALL;
208 ep0state = USB_EP0_IDLE; 217 ep0state = USB_EP0_IDLE;
209 return; 218 return;
210 } 219 }
@@ -214,20 +223,20 @@ logf("EP0_handler");
214 An interrupt will be generated and the FIFO flushed at this time. 223 An interrupt will be generated and the FIFO flushed at this time.
215 The bit is cleared by the CPU writing a 1 to the ServicedSetupEnd bit. 224 The bit is cleared by the CPU writing a 1 to the ServicedSetupEnd bit.
216 */ 225 */
217 if (csr0 & USB_CSR0_SETUPEND) 226 if (csr0 & USB_CSR0_SETUPEND)
218 { 227 {
219 REG_USB_REG_CSR0 |= USB_CSR0_SVDSETUPEND; 228 REG_USB_REG_CSR0 = csr0 | USB_CSR0_SVDSETUPEND;
220 ep0state = USB_EP0_IDLE; 229 ep0state = USB_EP0_IDLE;
221 return; 230 return;
222 } 231 }
223 232
224 /* Call relevant routines for endpoint 0 state */ 233 /* Call relevant routines for endpoint 0 state */
225 if (ep0state == USB_EP0_IDLE) 234 if (ep0state == USB_EP0_IDLE)
226 { 235 {
227 if (csr0 & USB_CSR0_OUTPKTRDY) /* There is data in the fifo */ 236 if(csr0 & USB_CSR0_OUTPKTRDY) /* There is data in the fifo */
228 { 237 {
229 readFIFO(&endpoints[0], REG_USB_REG_COUNT0); 238 readFIFO(&endpoints[0], REG_USB_REG_COUNT0);
230 REG_USB_REG_CSR0 |= USB_CSR0_SVDOUTPKTRDY; /* clear OUTPKTRDY bit */ 239 REG_USB_REG_CSR0 = csr0 | USB_CSR0_SVDOUTPKTRDY; /* clear OUTPKTRDY bit */
231 usb_core_control_request((struct usb_ctrlrequest*)endpoints[0].buf); 240 usb_core_control_request((struct usb_ctrlrequest*)endpoints[0].buf);
232 } 241 }
233 } 242 }
@@ -237,14 +246,15 @@ logf("EP0_handler");
237 246
238static void EPIN_handler(unsigned int endpoint) 247static void EPIN_handler(unsigned int endpoint)
239{ 248{
240logf("EPIN_handler(%d)", endpoint); 249 logf("EPIN_handler(%d)", endpoint);
250
241 struct usb_endpoint* ep = &endpoints[endpoint*2+1]; 251 struct usb_endpoint* ep = &endpoints[endpoint*2+1];
242 unsigned int length, csr; 252 unsigned int length, csr;
243 253
244 select_endpoint(endpoint); 254 select_endpoint(endpoint);
245 csr = REG_USB_REG_INCSR; 255 csr = REG_USB_REG_INCSR;
246 256
247 if(ep->length == 0) 257 if(ep->buf == NULL || ep->length == 0)
248 { 258 {
249 REG_USB_REG_INCSR = csr | USB_INCSR_INPKTRDY; 259 REG_USB_REG_INCSR = csr | USB_INCSR_INPKTRDY;
250 return; 260 return;
@@ -266,19 +276,25 @@ logf("EPIN_handler(%d)", endpoint);
266 276
267 REG_USB_REG_INCSR = csr | USB_INCSR_INPKTRDY; 277 REG_USB_REG_INCSR = csr | USB_INCSR_INPKTRDY;
268 if(ep->sent >= ep->length) 278 if(ep->sent >= ep->length)
269 usb_core_transfer_complete(endpoint|USB_DIR_IN, USB_DIR_IN, 0, ep->sent); 279 {
280 usb_core_transfer_complete(endpoint, USB_DIR_IN, 0, ep->sent);
281 ep->sent = 0;
282 ep->length = 0;
283 ep->buf = NULL;
284 }
270} 285}
271 286
272static void EPOUT_handler(unsigned int endpoint) 287static void EPOUT_handler(unsigned int endpoint)
273{ 288{
274logf("EPOUT_handler(%d)", endpoint); 289 logf("EPOUT_handler(%d)", endpoint);
290
275 struct usb_endpoint* ep = &endpoints[endpoint*2]; 291 struct usb_endpoint* ep = &endpoints[endpoint*2];
276 unsigned int size, csr; 292 unsigned int size, csr;
277 293
278 select_endpoint(endpoint); 294 select_endpoint(endpoint);
279 csr = REG_USB_REG_OUTCSR; 295 csr = REG_USB_REG_OUTCSR;
280 296
281 if(ep->buf == NULL && ep->length == 0) 297 if(ep->buf == NULL || ep->length == 0)
282 { 298 {
283 REG_USB_REG_OUTCSR = csr & ~USB_OUTCSR_OUTPKTRDY; 299 REG_USB_REG_OUTCSR = csr & ~USB_OUTCSR_OUTPKTRDY;
284 return; 300 return;
@@ -291,16 +307,21 @@ logf("EPOUT_handler(%d)", endpoint);
291 } 307 }
292 308
293 size = REG_USB_REG_OUTCOUNT; 309 size = REG_USB_REG_OUTCOUNT;
294 ep->received += size;
295 310
296 readFIFO(ep, size); 311 readFIFO(ep, size);
312 ep->received += size;
297 313
298 REG_USB_REG_OUTCSR = csr & ~USB_OUTCSR_OUTPKTRDY; 314 REG_USB_REG_OUTCSR = csr & ~USB_OUTCSR_OUTPKTRDY;
299 315
300 logf("received: %d length: %d", ep->received, ep->length); 316 logf("received: %d length: %d", ep->received, ep->length);
301 317
302 //if(ep->received >= ep->length) 318 if(size < ep->fifo_size || ep->received >= ep->length)
303 usb_core_transfer_complete(endpoint|USB_DIR_OUT, USB_DIR_OUT, 0, ep->received); 319 {
320 usb_core_transfer_complete(endpoint, USB_DIR_OUT, 0, ep->received);
321 ep->received = 0;
322 ep->length = 0;
323 ep->buf = NULL;
324 }
304} 325}
305 326
306static void setup_endpoint(struct usb_endpoint *ep) 327static void setup_endpoint(struct usb_endpoint *ep)
@@ -351,6 +372,17 @@ static void setup_endpoint(struct usb_endpoint *ep)
351 372
352static void udc_reset(void) 373static void udc_reset(void)
353{ 374{
375 /* From the datasheet:
376
377 When a reset condition is detected on the USB, the controller performs the following actions:
378 * Sets FAddr to 0.
379 * Sets Index to 0.
380 * Flushes all endpoint FIFOs.
381 * Clears all control/status registers.
382 * Enables all endpoint interrupts.
383 * Generates a Reset interrupt.
384 */
385
354 logf("udc_reset()"); 386 logf("udc_reset()");
355 387
356 register unsigned int i; 388 register unsigned int i;
@@ -371,8 +403,7 @@ static void udc_reset(void)
371 REG_USB_REG_FADDR = 0; 403 REG_USB_REG_FADDR = 0;
372 404
373 /* High speed and softconnect */ 405 /* High speed and softconnect */
374 //REG_USB_REG_POWER = (USB_POWER_SOFTCONN | USB_POWER_HSENAB); 406 REG_USB_REG_POWER = (USB_POWER_SOFTCONN | USB_POWER_HSENAB);
375 REG_USB_REG_POWER = USB_POWER_SOFTCONN;
376 407
377 /* Enable SUSPEND */ 408 /* Enable SUSPEND */
378 /* REG_USB_REG_POWER |= USB_POWER_SUSPENDM; */ 409 /* REG_USB_REG_POWER |= USB_POWER_SUSPENDM; */
@@ -560,6 +591,9 @@ int usb_drv_send(int endpoint, void* ptr, int length)
560 591
561 logf("usb_drv_send(%d, 0x%x, %d)", endpoint, (int)ptr, length); 592 logf("usb_drv_send(%d, 0x%x, %d)", endpoint, (int)ptr, length);
562 593
594 if(endpoint == EP_CONTROL && ptr == NULL && length == 0)
595 return 0; /* ACK request, handled by the USB controller */
596
563 if(endpoint == EP_CONTROL) 597 if(endpoint == EP_CONTROL)
564 { 598 {
565 flags = disable_irq_save(); 599 flags = disable_irq_save();
@@ -657,9 +691,12 @@ void usb_drv_cancel_all_transfers(void)
657 691
658 unsigned int i, flags; 692 unsigned int i, flags;
659 flags = disable_irq_save(); 693 flags = disable_irq_save();
660 694
661 for(i=0; i<TOTAL_EP(); i++) 695 for(i=0; i<TOTAL_EP(); i++)
662 { 696 {
697 if(i > 2)
698 endpoints[i].buf = NULL;
699
663 endpoints[i].sent = 0; 700 endpoints[i].sent = 0;
664 endpoints[i].length = 0; 701 endpoints[i].length = 0;
665 702