diff options
author | Karl Kurbjun <kkurbjun@gmail.com> | 2009-06-08 00:19:16 +0000 |
---|---|---|
committer | Karl Kurbjun <kkurbjun@gmail.com> | 2009-06-08 00:19:16 +0000 |
commit | 4a483bb1bf69a0f0a1bf99aaa9bb47c6f79ab990 (patch) | |
tree | 974333299e937024bcd8b34ab998ceb137011d56 | |
parent | f8a861961582c2809a8267ad0918d9c74072a440 (diff) | |
download | rockbox-4a483bb1bf69a0f0a1bf99aaa9bb47c6f79ab990.tar.gz rockbox-4a483bb1bf69a0f0a1bf99aaa9bb47c6f79ab990.zip |
M:Robe 500: Mostly complete USB driver, supports BULK mode currently and gets about 2 MB/s writes vs 1.1 MB/s on the OF. Mostly tested against Linux, preliminary testing in Windows appears to work. There is currently a bug in the attach process where it only works once per boot that needs to be fixed. There are a few other minor M:Robe 500 changes as well.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21208 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | firmware/SOURCES | 4 | ||||
-rw-r--r-- | firmware/drivers/m66591.c | 847 | ||||
-rw-r--r-- | firmware/export/config-mrobe500.h | 16 | ||||
-rw-r--r-- | firmware/export/config.h | 3 | ||||
-rw-r--r-- | firmware/export/m66591.h | 102 | ||||
-rw-r--r-- | firmware/target/arm/tms320dm320/boot.lds | 11 | ||||
-rwxr-xr-x | firmware/target/arm/tms320dm320/crt0.S | 22 | ||||
-rwxr-xr-x | firmware/target/arm/tms320dm320/mrobe-500/powermgmt-mr500.c | 8 | ||||
-rw-r--r-- | firmware/target/arm/tms320dm320/mrobe-500/usb-mr500.c | 74 | ||||
-rw-r--r-- | firmware/target/arm/tms320dm320/system-dm320.c | 12 | ||||
-rwxr-xr-x | firmware/target/arm/tms320dm320/system-target.h | 2 | ||||
-rw-r--r-- | firmware/usb.c | 3 |
12 files changed, 1048 insertions, 56 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES index 3ee805eedd..f4705d9694 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES | |||
@@ -271,7 +271,9 @@ usbstack/usb_charging_only.c | |||
271 | #ifdef USB_ENABLE_HID | 271 | #ifdef USB_ENABLE_HID |
272 | usbstack/usb_hid.c | 272 | usbstack/usb_hid.c |
273 | #endif | 273 | #endif |
274 | #if CONFIG_USBOTG == USBOTG_ARC | 274 | #if CONFIG_USBOTG == USBOTG_M66591 |
275 | drivers/m66591.c | ||
276 | #elif CONFIG_USBOTG == USBOTG_ARC | ||
275 | target/arm/usb-drv-arc.c | 277 | target/arm/usb-drv-arc.c |
276 | #elif CONFIG_USBOTG == USBOTG_ISP1583 | 278 | #elif CONFIG_USBOTG == USBOTG_ISP1583 |
277 | drivers/isp1583.c | 279 | drivers/isp1583.c |
diff --git a/firmware/drivers/m66591.c b/firmware/drivers/m66591.c new file mode 100644 index 0000000000..9a93985580 --- /dev/null +++ b/firmware/drivers/m66591.c | |||
@@ -0,0 +1,847 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id: usb-mr500.c 18487 2008-09-10 20:14:22Z bertrik $ | ||
9 | * | ||
10 | * Copyright (C) 2009 by Karl Kurbjun | ||
11 | * Portions Copyright (C) 2007 by Catalin Patulea | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License | ||
15 | * as published by the Free Software Foundation; either version 2 | ||
16 | * of the License, or (at your option) any later version. | ||
17 | * | ||
18 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
19 | * KIND, either express or implied. | ||
20 | * | ||
21 | ****************************************************************************/ | ||
22 | #define LOGF_ENABLE | ||
23 | |||
24 | #include "system.h" | ||
25 | #include "config.h" | ||
26 | #include "string.h" | ||
27 | #include "usb_ch9.h" | ||
28 | #include "usb_core.h" | ||
29 | #include "kernel.h" | ||
30 | #include "panic.h" | ||
31 | #include "usb_drv.h" | ||
32 | #include "logf.h" | ||
33 | |||
34 | #include "config.h" | ||
35 | #include "cpu.h" | ||
36 | #include "ata.h" | ||
37 | #include "usb.h" | ||
38 | #include "usb-target.h" | ||
39 | #include "m66591.h" | ||
40 | |||
41 | /******************************************************************************* | ||
42 | * These are the driver specific defines. | ||
43 | ******************************************************************************/ | ||
44 | #define HISPEED | ||
45 | |||
46 | /* Right now sending blocks till the full transfer has completed, this needs to | ||
47 | * be fixed so that it does not require a block. (USB_TRAN_LOCK ideally would | ||
48 | * not be set). | ||
49 | */ | ||
50 | #define USB_TRAN_BLOCK | ||
51 | |||
52 | /******************************************************************************* | ||
53 | * The following functions are all helpers which should not be called directly | ||
54 | * from the USB stack. They should only be called by eachother, or the USB | ||
55 | * stack visible functions. | ||
56 | ******************************************************************************/ | ||
57 | |||
58 | static volatile unsigned short * pipe_ctrl_addr(int pipe); | ||
59 | static void pipe_handshake(int pipe, int handshake); | ||
60 | static void pipe_c_select (int pipe, bool dir); | ||
61 | #if !defined(USB_TRAN_BLOCK) | ||
62 | static int pipe_buffer_size (int pipe); | ||
63 | #endif | ||
64 | static int pipe_maxpack_size (int pipe); | ||
65 | static void control_received(void); | ||
66 | static void transfer_complete(int endpoint); | ||
67 | static int mxx_transmit_receive(int endpoint); | ||
68 | static int mxx_queue(int endpoint, void * ptr, int length, bool send); | ||
69 | |||
70 | struct M66591_epstat { | ||
71 | unsigned char dir; /* endpoint direction */ | ||
72 | char *buf; /* user buffer to store data */ | ||
73 | int length; /* how match data will fit */ | ||
74 | volatile int count; /* actual data count */ | ||
75 | bool waiting; /* is there data to transfer? */ | ||
76 | bool busy; /* has the pipe been requested for use? */ | ||
77 | } ; | ||
78 | |||
79 | static struct M66591_epstat M66591_eps[USB_NUM_ENDPOINTS]; | ||
80 | |||
81 | /* This function is used to return the control address for each pipe */ | ||
82 | static volatile unsigned short * pipe_ctrl_addr(int pipe) { | ||
83 | if(pipe==0) { | ||
84 | return &M66591_DCPCTRL; | ||
85 | } else { | ||
86 | return &M66591_PIPECTRL1 + (pipe-1); | ||
87 | } | ||
88 | } | ||
89 | |||
90 | /* This function sets the pipe/endpoint handshake */ | ||
91 | static void pipe_handshake(int pipe, int handshake) { | ||
92 | handshake&=0x03; | ||
93 | |||
94 | if(handshake == PIPE_SHAKE_STALL) { | ||
95 | if( *(pipe_ctrl_addr(pipe)) & 0x03 ) { | ||
96 | *(pipe_ctrl_addr(pipe)) = 0x03; | ||
97 | } else { | ||
98 | *(pipe_ctrl_addr(pipe)) = 0x02; | ||
99 | } | ||
100 | } else { | ||
101 | *(pipe_ctrl_addr(pipe)) = handshake; | ||
102 | } | ||
103 | } | ||
104 | |||
105 | /* This function chooses the pipe desired and waits the required time before | ||
106 | * warites/reads are valid */ | ||
107 | static void pipe_c_select (int pipe, bool dir) { | ||
108 | M66591_CPORT_CTRL0 = pipe | (1<<10) | (dir<<5); | ||
109 | |||
110 | // Wait for the Pipe to be valid; | ||
111 | udelay(2); | ||
112 | } | ||
113 | |||
114 | #if !defined(USB_TRAN_BLOCK) | ||
115 | /* This returns the maximum buffer size of each pipe. On this device the size | ||
116 | * is fixed. | ||
117 | */ | ||
118 | static int pipe_buffer_size (int pipe) { | ||
119 | switch(pipe) { | ||
120 | case 0: | ||
121 | return 256; | ||
122 | case 1: | ||
123 | case 2: | ||
124 | return 1024; | ||
125 | case 3: | ||
126 | case 4: | ||
127 | return 512; | ||
128 | case 5: | ||
129 | case 6: | ||
130 | return 64; | ||
131 | default: | ||
132 | return 0; | ||
133 | } | ||
134 | } | ||
135 | #endif | ||
136 | |||
137 | /* This function returns the maximum packet size for each endpoint/pipe. It is | ||
138 | * Currently only setup to support Highspeed mode. | ||
139 | */ | ||
140 | static int pipe_maxpack_size (int pipe) { | ||
141 | switch(pipe) { | ||
142 | case 0: | ||
143 | /* DCP max packet size is configurable */ | ||
144 | return M66591_DCP_MXPKSZ; | ||
145 | case 1: | ||
146 | case 2: | ||
147 | case 3: | ||
148 | case 4: | ||
149 | return 512; | ||
150 | case 5: | ||
151 | case 6: | ||
152 | return 64; | ||
153 | default: | ||
154 | return 0; | ||
155 | } | ||
156 | } | ||
157 | |||
158 | /* This is a helper function that is only called from the interupt handler. It | ||
159 | * copies the control packet information from the PHY and notifies the stack. | ||
160 | */ | ||
161 | static void control_received(void) { | ||
162 | /* copy setup data from packet */ | ||
163 | static struct usb_ctrlrequest temp; | ||
164 | |||
165 | memcpy(&temp, (unsigned char*)&M66591_USB_REQ0, 8); | ||
166 | |||
167 | logf("mxx: bReqType=0x%02x bReq=0x%02x wVal=0x%04x" | ||
168 | " wIdx=0x%04x wLen=0x%04x", | ||
169 | temp.bRequestType, temp.bRequest, temp.wValue, | ||
170 | temp.wIndex, temp.wLength); | ||
171 | |||
172 | /* acknowledge packet recieved (clear valid) */ | ||
173 | M66591_INTSTAT_MAIN &= ~(1<<3); | ||
174 | |||
175 | usb_core_control_request(&temp); | ||
176 | } | ||
177 | |||
178 | /* This is a helper function, it is used to notife the stack that a transfer is | ||
179 | * done. | ||
180 | */ | ||
181 | static void transfer_complete(int endpoint) { | ||
182 | M66591_INTCFG_EMP &= ~(1 << endpoint); | ||
183 | logf("mxx: ep %d transfer complete", endpoint); | ||
184 | int temp=M66591_eps[endpoint].dir ? USB_DIR_IN : USB_DIR_OUT; | ||
185 | usb_core_transfer_complete(endpoint, temp, 0, | ||
186 | M66591_eps[endpoint].length); | ||
187 | } | ||
188 | |||
189 | /* This is the main transmit routine that is typically called from the interrupt | ||
190 | * handler (the queue function calls it in some situations) | ||
191 | */ | ||
192 | static int mxx_transmit_receive(int endpoint) { | ||
193 | logf("mxx: do start"); | ||
194 | |||
195 | /* Only the lower 15 bits of the endpoint correlate to the pipe number. | ||
196 | * For example pipe 2 will corelate to endpoint 0x82, so the upper bits | ||
197 | * need to be masked out. | ||
198 | */ | ||
199 | endpoint &= 0x7F; | ||
200 | |||
201 | int i; /* Used as a loop counter */ | ||
202 | int length; /* Used in transfers to determine the amount to send/receive */ | ||
203 | |||
204 | bool send=M66591_eps[endpoint].dir; | ||
205 | |||
206 | /* This is used as the internal buffer pointer */ | ||
207 | unsigned short *ptrs; | ||
208 | |||
209 | /* Choose the pipe that data is being transfered on */ | ||
210 | pipe_c_select(endpoint, send); | ||
211 | |||
212 | /* Check to see if the endpoint is ready and give it some time to become | ||
213 | * ready. If it runs out of time exit out as an error. | ||
214 | */ | ||
215 | i = 0; | ||
216 | while (!(M66591_CPORT_CTRL1&(1<<13))) { | ||
217 | if (i++ > 100000) { | ||
218 | logf("mxx: FIFO %d not ready", endpoint); | ||
219 | return -1; | ||
220 | } | ||
221 | } | ||
222 | |||
223 | /* Write to FIFO */ | ||
224 | if(send) { | ||
225 | int maxpack=pipe_maxpack_size(endpoint); | ||
226 | #if defined(USB_TRAN_BLOCK) | ||
227 | length = M66591_eps[endpoint].length; | ||
228 | #else | ||
229 | int bufsize=pipe_buffer_size(endpoint); | ||
230 | length=MIN(M66591_eps[endpoint].length, bufsize); | ||
231 | #endif | ||
232 | |||
233 | /* Calculate the position in the buffer, all transfers should be 2-byte | ||
234 | * aligned till the last packet or short packet. | ||
235 | */ | ||
236 | ptrs = (unsigned short *)(M66591_eps[endpoint].buf | ||
237 | + M66591_eps[endpoint].count); | ||
238 | |||
239 | /* Start sending data in 16-bit words */ | ||
240 | for (i = 0; i < (length>>1); i++) { | ||
241 | /* This wait is dangerous in the event htat something happens to | ||
242 | * the PHY pipe where it never becomes ready again, should probably | ||
243 | * add a timeout, and ideally completely remove. | ||
244 | */ | ||
245 | while(!(M66591_CPORT_CTRL1&(1<<13))){}; | ||
246 | |||
247 | M66591_CPORT = *ptrs++; | ||
248 | M66591_eps[endpoint].count+=2; | ||
249 | } | ||
250 | |||
251 | /* If the length is odd, send the last byte after setting the byte width | ||
252 | * of the FIFO. | ||
253 | */ | ||
254 | if(length & 0x01) { | ||
255 | /* Unset MBW (8-bit transfer) */ | ||
256 | M66591_CPORT_CTRL0 &= ~(1<<10); | ||
257 | M66591_CPORT = *((unsigned char *)ptrs - 1); | ||
258 | M66591_eps[endpoint].count++; | ||
259 | } | ||
260 | |||
261 | /* Set BVAL if length is not a multiple of the maximum packet size */ | ||
262 | if( (length == 0) || (length % maxpack != 0) ) { | ||
263 | logf("mxx: do set BVAL"); | ||
264 | M66591_CPORT_CTRL1 |= (1<<15); | ||
265 | } | ||
266 | |||
267 | /* If the transfer is complete set up interrupts to notify when FIFO is | ||
268 | * EMPTY, disable READY and let the handler know that there is nothing | ||
269 | * left to transfer on this pipe. | ||
270 | */ | ||
271 | if(M66591_eps[endpoint].count == M66591_eps[endpoint].length) { | ||
272 | /* Enable Empty flag */ | ||
273 | M66591_INTCFG_EMP |= 1 << endpoint; | ||
274 | /* Disable ready flag */ | ||
275 | M66591_INTCFG_RDY &= ~(1 << endpoint); | ||
276 | /* Nothing left to transfer */ | ||
277 | M66591_eps[endpoint].waiting=false; | ||
278 | } else { | ||
279 | /* There is still data to transfer, make sure READY is enabled */ | ||
280 | M66591_INTCFG_RDY |= 1 << endpoint; | ||
281 | } | ||
282 | } else { | ||
283 | /* Read data from FIFO */ | ||
284 | |||
285 | /* Read the number of bytes that the PHY received */ | ||
286 | int receive_length=M66591_CPORT_CTRL1 & 0x03FF; | ||
287 | |||
288 | /* The number of bytes to actually read is either what's left of the | ||
289 | * amount requested, or the amount that the PHY received. Choose the | ||
290 | * smaller of the two. | ||
291 | */ | ||
292 | length = MIN(M66591_eps[endpoint].length - M66591_eps[endpoint].count, | ||
293 | receive_length); | ||
294 | |||
295 | /* If the length is zero, just clear the buffer as specified in the | ||
296 | * datasheet. Otherwise read in the data (in 16-bit pieces */ | ||
297 | if(length==0) { | ||
298 | /* Set the BCLR bit */ | ||
299 | M66591_CPORT_CTRL1 |= 1<<14; | ||
300 | } else { | ||
301 | /* Set the position in the buffer */ | ||
302 | ptrs = (unsigned short *)(M66591_eps[endpoint].buf | ||
303 | + M66591_eps[endpoint].count); | ||
304 | |||
305 | /* Read in the data (buffer size should be even). The PHY cannot | ||
306 | * switch from 16-bit mode to 8-bit mode on an OUT buffer. | ||
307 | */ | ||
308 | for (i = 0; i < ((length+1)>>1); i++) { | ||
309 | *ptrs++ = M66591_CPORT; | ||
310 | M66591_eps[endpoint].count+=2; | ||
311 | } | ||
312 | } | ||
313 | |||
314 | /* If the length was odd subtract 1 from the count */ | ||
315 | M66591_eps[endpoint].count -= (length&0x01); | ||
316 | |||
317 | /* If the requested size of data was received, or the data received was | ||
318 | * less than the maximum packet size end the transfer. | ||
319 | */ | ||
320 | if( (M66591_eps[endpoint].count == M66591_eps[endpoint].length) | ||
321 | || (length % pipe_maxpack_size(endpoint)) ) { | ||
322 | |||
323 | /* If the host tries to send anything else the FIFO is not ready/ | ||
324 | * enabled yet (NAK). | ||
325 | */ | ||
326 | pipe_handshake(endpoint, PIPE_SHAKE_NAK); | ||
327 | /* Tell the interrupt handler that transfer is complete. */ | ||
328 | M66591_eps[endpoint].waiting=false; | ||
329 | /* Disable ready */ | ||
330 | M66591_INTCFG_RDY &= ~(1 << endpoint); | ||
331 | |||
332 | /* Let the stack know that the transfer is complete */ | ||
333 | if(endpoint!=0) | ||
334 | transfer_complete(endpoint); | ||
335 | } | ||
336 | } | ||
337 | |||
338 | logf("mxx: do done ep %d %s len: %d cnt: %d", endpoint, | ||
339 | send ? "out" : "in", length, M66591_eps[endpoint].count); | ||
340 | |||
341 | return 0; | ||
342 | } | ||
343 | |||
344 | /* This function is used to start transfers. It is a helper function for the | ||
345 | * usb_drv_send_nonblocking, usb_drv_send, and usb_drv_receive functions. | ||
346 | */ | ||
347 | static int mxx_queue(int endpoint, void * ptr, int length, bool send) { | ||
348 | /* Disable IRQs */ | ||
349 | int flags = disable_irq_save(); | ||
350 | |||
351 | /* Only the lower 15 bits of the endpoint correlate to the pipe number. | ||
352 | * For example pipe 2 will corelate to endpoint 0x82, so the upper bits | ||
353 | * need to be masked out. | ||
354 | */ | ||
355 | endpoint &= 0x7F; | ||
356 | |||
357 | /* Initialize the enpoint status registers used for the transfer */ | ||
358 | M66591_eps[endpoint].buf=ptr; | ||
359 | M66591_eps[endpoint].length=length; | ||
360 | M66591_eps[endpoint].count=0; | ||
361 | M66591_eps[endpoint].dir=send; | ||
362 | M66591_eps[endpoint].waiting=true; | ||
363 | |||
364 | logf("mxx: queue ep %d %s, len: %d", endpoint, send ? "out" : "in", length); | ||
365 | |||
366 | /* Pick the pipe that communications are happening on */ | ||
367 | pipe_c_select(endpoint, send); | ||
368 | |||
369 | /* All transfers start with a BUF handshake */ | ||
370 | pipe_handshake(endpoint, PIPE_SHAKE_BUF); | ||
371 | |||
372 | /* This USB PHY takes care of control completion packets by setting the | ||
373 | * CCPL bit in EP0 (endpoint 0, or DCP). If the control state is "write no | ||
374 | * data tranfer" then we just need to set the CCPL bit (hopefully) | ||
375 | * regardless of what the stack said to send. | ||
376 | */ | ||
377 | int control_state = (M66591_INTSTAT_MAIN & 0x07); | ||
378 | if(endpoint==0 && control_state==CTRL_WTND) { | ||
379 | logf("mxx: queue ep 0 ctls: 5, set ccpl"); | ||
380 | |||
381 | /* Set CCPL */ | ||
382 | M66591_DCPCTRL |= 1<<2; | ||
383 | } else { | ||
384 | /* This is the standard case for transmitting data */ | ||
385 | if(send) { | ||
386 | /* If the pipe is not ready don't try and send right away; instead | ||
387 | * just set the READY interrupt so that the handler can initiate | ||
388 | * the transfer. | ||
389 | */ | ||
390 | if((M66591_CPORT_CTRL1&(1<<13))) { | ||
391 | mxx_transmit_receive(endpoint); | ||
392 | } else { | ||
393 | M66591_INTCFG_RDY |= 1 << endpoint; | ||
394 | } | ||
395 | |||
396 | if(length==0) { | ||
397 | transfer_complete(endpoint); | ||
398 | } | ||
399 | } else { | ||
400 | /* When receiving data, just enable the ready interrupt, the PHY | ||
401 | * will trigger it and then the reads can start. | ||
402 | */ | ||
403 | M66591_INTCFG_RDY |= 1 << endpoint; | ||
404 | } | ||
405 | } | ||
406 | |||
407 | /* Re-enable IRQs */ | ||
408 | restore_irq(flags); | ||
409 | return 0; | ||
410 | } | ||
411 | |||
412 | /******************************************************************************* | ||
413 | * This is the interrupt handler for this driver. It should be called from the | ||
414 | * target interrupt handler routine (eg. GPIO3 on M:Robe 500). | ||
415 | ******************************************************************************/ | ||
416 | void USB_DEVICE(void) { | ||
417 | int pipe_restore=M66591_CPORT_CTRL0; | ||
418 | logf("mxx: INT BEGIN tick: %d\n", (int) current_tick); | ||
419 | |||
420 | logf("mxx: sMAIN0: 0x%04x, sRDY: 0x%04x", | ||
421 | M66591_INTSTAT_MAIN, M66591_INTSTAT_RDY); | ||
422 | logf("mxx: sNRDY: 0x%04x, sEMP: 0x%04x", | ||
423 | M66591_INTSTAT_NRDY, M66591_INTSTAT_EMP); | ||
424 | |||
425 | /* VBUS (connected) interrupt */ | ||
426 | while ( M66591_INTSTAT_MAIN & (1<<15) ) { | ||
427 | M66591_INTSTAT_MAIN &= ~(1<<15); | ||
428 | |||
429 | /* If device is not clocked, interrupt flag must be set manually */ | ||
430 | if ( !(M66591_TRN_CTRL & (1<<10)) ) { | ||
431 | M66591_INTSTAT_MAIN |= (1<<15); | ||
432 | } | ||
433 | } | ||
434 | |||
435 | /* Resume interrupt: This is not used. Extra logic needs to be added similar | ||
436 | * to the VBUS interrupt incase the PHY clock is not running. | ||
437 | */ | ||
438 | if(M66591_INTSTAT_MAIN & (1<<14)) { | ||
439 | M66591_INTSTAT_MAIN &= ~(1<<14); | ||
440 | logf("mxx: RESUME"); | ||
441 | } | ||
442 | |||
443 | /* Device state transition interrupt: Not used, but useful for debugging */ | ||
444 | if(M66591_INTSTAT_MAIN & (1<<12)) { | ||
445 | M66591_INTSTAT_MAIN &= ~(1<<12); | ||
446 | logf("mxx: DEV state CHANGE=%d", | ||
447 | ((M66591_INTSTAT_MAIN & (0x07<<4)) >> 4) ); | ||
448 | } | ||
449 | |||
450 | /* Control transfer stage interrupt */ | ||
451 | if(M66591_INTSTAT_MAIN & (1<<11)) { | ||
452 | M66591_INTSTAT_MAIN &= ~(1<<11); | ||
453 | int control_state = (M66591_INTSTAT_MAIN & 0x07); | ||
454 | |||
455 | logf("mxx: CTRT with CTSQ=%d", control_state); | ||
456 | |||
457 | switch ( control_state ) { | ||
458 | case CTRL_IDLE: | ||
459 | transfer_complete(0); | ||
460 | break; | ||
461 | case CTRL_RTDS: | ||
462 | case CTRL_WTDS: | ||
463 | case CTRL_WTND: | ||
464 | // If data is not valid stop | ||
465 | if(!(M66591_INTSTAT_MAIN & (1<<3)) ) { | ||
466 | logf("mxx: CTRT interrupt but VALID is false"); | ||
467 | break; | ||
468 | } | ||
469 | control_received(); | ||
470 | break; | ||
471 | case CTRL_RTSS: | ||
472 | case CTRL_WTSS: | ||
473 | pipe_handshake(0, PIPE_SHAKE_BUF); | ||
474 | M66591_DCPCTRL |= 1<<2; // Set CCPL | ||
475 | break; | ||
476 | default: | ||
477 | logf("mxx: CTRT with unknown CTSQ"); | ||
478 | break; | ||
479 | } | ||
480 | } | ||
481 | |||
482 | /* FIFO EMPTY interrupt: when this happens the transfer should be complete. | ||
483 | * When the interrupt occurs notify the stack. | ||
484 | */ | ||
485 | if(M66591_INTSTAT_MAIN & (1<<10)) { | ||
486 | int i; | ||
487 | logf("mxx: INT EMPTY: 0x%04x", M66591_INTSTAT_EMP); | ||
488 | |||
489 | for(i=0; i<USB_NUM_ENDPOINTS; i++) { | ||
490 | if(M66591_INTSTAT_EMP&(1<<i)) { | ||
491 | /* Clear the empty flag */ | ||
492 | M66591_INTSTAT_EMP=~(1<<i); | ||
493 | /* Notify the stack */ | ||
494 | transfer_complete(i); | ||
495 | } | ||
496 | } | ||
497 | } | ||
498 | |||
499 | /* FIFO NOT READY interrupt: This is not used, but included incase the | ||
500 | * interrupt is endabled. | ||
501 | */ | ||
502 | if(M66591_INTSTAT_MAIN & (1<<9)) { | ||
503 | logf("mxx: INT NOT READY: 0x%04x", M66591_INTSTAT_NRDY); | ||
504 | M66591_INTSTAT_NRDY = 0; | ||
505 | } | ||
506 | |||
507 | /* FIFO READY interrupt: This just initiates transfers if they are needed */ | ||
508 | if(M66591_INTSTAT_MAIN & (1<<8)) { | ||
509 | int i; | ||
510 | logf("mxx: INT READY: 0x%04x", M66591_INTSTAT_RDY); | ||
511 | |||
512 | for(i=0; i<USB_NUM_ENDPOINTS; i++) { | ||
513 | /* Was this endpoint ready and waiting */ | ||
514 | if(M66591_INTSTAT_RDY&(1<<i) && M66591_eps[i].waiting) { | ||
515 | /* Clear the ready flag */ | ||
516 | M66591_INTSTAT_RDY=~(1<<i); | ||
517 | /* It was ready and waiting so start a transfer */ | ||
518 | mxx_transmit_receive(i); | ||
519 | } | ||
520 | } | ||
521 | } | ||
522 | |||
523 | /* Make sure that the INTStatus register is completely cleared. */ | ||
524 | M66591_INTSTAT_MAIN = 0; | ||
525 | |||
526 | /* Restore the pipe state before the interrupt occured */ | ||
527 | M66591_CPORT_CTRL0=pipe_restore; | ||
528 | logf("\nmxx: INT END"); | ||
529 | } | ||
530 | |||
531 | /******************************************************************************* | ||
532 | * The following functions are all called by and visible to the USB stack. | ||
533 | ******************************************************************************/ | ||
534 | |||
535 | /* The M55691 handles this automatically, nothing to do */ | ||
536 | void usb_drv_set_address(int address) { | ||
537 | (void) address; | ||
538 | } | ||
539 | |||
540 | /* This function sets the standard test modes, it is not required, but might as | ||
541 | * well implement it since the hardware supports it | ||
542 | */ | ||
543 | void usb_drv_set_test_mode(int mode) { | ||
544 | /* This sets the test bits and assumes that mode is from 0 to 0x04 */ | ||
545 | M66591_TESTMODE &= 0x0007; | ||
546 | M66591_TESTMODE |= mode; | ||
547 | } | ||
548 | |||
549 | /* Request an unused endpoint, support for interrupt endpoints needs addition */ | ||
550 | int usb_drv_request_endpoint(int type, int dir) { | ||
551 | int ep; | ||
552 | int pipecfg = 0; | ||
553 | |||
554 | if (type != USB_ENDPOINT_XFER_BULK) | ||
555 | return -1; | ||
556 | |||
557 | /* The endpoint/pipes are hard coded: This could be more flexible */ | ||
558 | if (dir == USB_DIR_IN) { | ||
559 | pipecfg |= (1<<4); | ||
560 | ep = 2; | ||
561 | } else { | ||
562 | ep = 1; | ||
563 | } | ||
564 | |||
565 | if (!M66591_eps[ep].busy) { | ||
566 | M66591_eps[ep].busy = true; | ||
567 | M66591_eps[ep].dir = dir; | ||
568 | } else { | ||
569 | logf("mxx: ep %d busy", ep); | ||
570 | return -1; | ||
571 | } | ||
572 | |||
573 | M66591_PIPE_CFGSEL=ep; | ||
574 | |||
575 | pipecfg |= 1<<15 | 1<<9 | 1<<8; | ||
576 | |||
577 | pipe_handshake(ep, PIPE_SHAKE_NAK); | ||
578 | |||
579 | // Setup the flags | ||
580 | M66591_PIPE_CFGWND=pipecfg; | ||
581 | |||
582 | logf("mxx: ep req ep#: %d config: 0x%04x", ep, M66591_PIPE_CFGWND); | ||
583 | |||
584 | return ep | dir; | ||
585 | } | ||
586 | |||
587 | /* Used by stack to tell the helper functions that the pipe is not in use */ | ||
588 | void usb_drv_release_endpoint(int ep) { | ||
589 | int flags; | ||
590 | ep &= 0x7f; | ||
591 | |||
592 | if (ep < 1 || ep > USB_NUM_ENDPOINTS || M66591_eps[ep].busy == false) | ||
593 | return ; | ||
594 | |||
595 | flags = disable_irq_save(); | ||
596 | |||
597 | logf("mxx: ep %d release", ep); | ||
598 | |||
599 | M66591_eps[ep].busy = false; | ||
600 | M66591_eps[ep].dir = -1; | ||
601 | |||
602 | restore_irq(flags); | ||
603 | } | ||
604 | |||
605 | /* Periodically called to check if a cable was plugged into the device */ | ||
606 | inline int usb_detect(void) | ||
607 | { | ||
608 | if(M66591_INTSTAT_MAIN&(1<<7)) | ||
609 | return USB_INSERTED; | ||
610 | else | ||
611 | return USB_EXTRACTED; | ||
612 | } | ||
613 | |||
614 | void usb_enable(bool on) { | ||
615 | logf("mxx: %s: %s", __FUNCTION__, on ? "true" : "false"); | ||
616 | if (on) | ||
617 | usb_core_init(); | ||
618 | else | ||
619 | usb_core_exit(); | ||
620 | } | ||
621 | |||
622 | /* This is where the driver stuff starts */ | ||
623 | void usb_drv_init(void) { | ||
624 | logf("mxx: Device Init"); | ||
625 | |||
626 | /* State left behind by m:robe 500i original firmware */ | ||
627 | M66591_TRN_CTRL = 0x8001; /* External 48 MHz clock */ | ||
628 | M66591_TRN_LNSTAT = 0x0040; /* "Reserved. Set it to '1'." */ | ||
629 | |||
630 | M66591_PIN_CFG0 = 0x0000; | ||
631 | M66591_PIN_CFG1 = 0x8000; /* Drive Current: 3.3V setting */ | ||
632 | M66591_PIN_CFG2 = 0x0000; | ||
633 | |||
634 | M66591_INTCFG_MAIN = 0x0000; /* All Interrupts Disable for now */ | ||
635 | M66591_INTCFG_OUT = 0x0000; /* Sense is edge, polarity is low */ | ||
636 | M66591_INTCFG_RDY = 0x0000; | ||
637 | M66591_INTCFG_NRDY = 0x0000; | ||
638 | M66591_INTCFG_EMP = 0x0000; | ||
639 | |||
640 | M66591_INTSTAT_MAIN = 0; | ||
641 | M66591_INTSTAT_RDY = 0; | ||
642 | M66591_INTSTAT_NRDY = 0; | ||
643 | M66591_INTSTAT_EMP = 0; | ||
644 | } | ||
645 | |||
646 | /* fully enable driver */ | ||
647 | void usb_attach(void) { | ||
648 | int i; | ||
649 | |||
650 | /* Reset Endpoint states */ | ||
651 | for(i=0; i<USB_NUM_ENDPOINTS; i++) { | ||
652 | M66591_eps[i].dir = -1; | ||
653 | M66591_eps[i].buf = (char *) 0; | ||
654 | M66591_eps[i].length = 0; | ||
655 | M66591_eps[i].count = 0; | ||
656 | M66591_eps[i].waiting = false; | ||
657 | M66591_eps[i].busy = false; | ||
658 | } | ||
659 | |||
660 | /* Issue a h/w reset */ | ||
661 | usb_init_device(); | ||
662 | usb_drv_init(); | ||
663 | |||
664 | /* USB Attach Process: This follows the flow diagram in the M66591GP | ||
665 | * Reference Manual Rev 1.00, p. 77 */ | ||
666 | |||
667 | #if defined(HISPEED) | ||
668 | /* Run Hi-Speed */ | ||
669 | M66591_TRN_CTRL |= 1<<7; | ||
670 | #else | ||
671 | /* Run Full-Speed */ | ||
672 | M66591_TRN_CTRL &= ~(1<<7); | ||
673 | #endif | ||
674 | |||
675 | /* Enable oscillation buffer */ | ||
676 | M66591_TRN_CTRL |= (1<<13); | ||
677 | |||
678 | udelay(1500); | ||
679 | |||
680 | /* Enable reference clock, PLL */ | ||
681 | M66591_TRN_CTRL |= (3<<11); | ||
682 | |||
683 | udelay(9); | ||
684 | |||
685 | /* Enable internal clock supply */ | ||
686 | M66591_TRN_CTRL |= (1<<10); | ||
687 | |||
688 | /* Disable PIPE ready interrupts */ | ||
689 | M66591_INTCFG_RDY = 0; | ||
690 | |||
691 | /* Disable PIPE not-ready interrupts */ | ||
692 | M66591_INTCFG_NRDY = 0; | ||
693 | |||
694 | /* Disable PIPE empyt/size error interrupts */ | ||
695 | M66591_INTCFG_EMP = 0; | ||
696 | |||
697 | /* Enable all interrupts except NOT READY, RESUME, and VBUS */ | ||
698 | M66591_INTCFG_MAIN = 0x1DFF; | ||
699 | |||
700 | pipe_c_select(0, false); | ||
701 | |||
702 | /* Enable continuous transfer mode on the DCP */ | ||
703 | M66591_DCP_CNTMD |= (1<<8); | ||
704 | |||
705 | /* Set the threshold that the PHY will automatically transmit from EP0 */ | ||
706 | M66591_DCP_CTRLEN = 128; | ||
707 | |||
708 | pipe_handshake(0, PIPE_SHAKE_NAK); | ||
709 | |||
710 | /* Set the Max packet size to 64 */ | ||
711 | M66591_DCP_MXPKSZ = 64; | ||
712 | |||
713 | /* Attach notification to PC (D+ pull-up) */ | ||
714 | M66591_TRN_CTRL |= (1<<4); | ||
715 | |||
716 | logf("mxx: attached"); | ||
717 | } | ||
718 | |||
719 | void usb_drv_exit(void) { | ||
720 | /* USB Detach Process: This follows the flow diagram in the M66591GP | ||
721 | * Reference Manual Rev 1.00, p. 78. | ||
722 | */ | ||
723 | |||
724 | /* Detach notification to PC (disable D+ pull-up) */ | ||
725 | M66591_TRN_CTRL &= ~(1<<4); | ||
726 | |||
727 | /* Software reset */ | ||
728 | M66591_TRN_CTRL &= ~0x01; | ||
729 | |||
730 | /* Disable internal clock supply */ | ||
731 | M66591_TRN_CTRL &= ~(1<<10); | ||
732 | udelay(3); | ||
733 | |||
734 | /* Disable PLL */ | ||
735 | M66591_TRN_CTRL &= ~(1<<11); | ||
736 | udelay(3); | ||
737 | |||
738 | /* Disable internal reference clock */ | ||
739 | M66591_TRN_CTRL &= ~(1<<12); | ||
740 | udelay(3); | ||
741 | |||
742 | /* Disable oscillation buffer, reenable USB operation */ | ||
743 | M66591_TRN_CTRL &= ~(1<<13); | ||
744 | |||
745 | M66591_TRN_CTRL |= 0x01; | ||
746 | |||
747 | logf("mxx: detached"); | ||
748 | } | ||
749 | |||
750 | /* This function begins a transmit (on an IN endpoint), it should not block | ||
751 | * so the actual transmit is done in the interrupt handler. | ||
752 | */ | ||
753 | int usb_drv_send_nonblocking(int endpoint, void* ptr, int length) | ||
754 | { | ||
755 | /* The last arguement for queue specifies the dir of data (true==send) */ | ||
756 | return mxx_queue(endpoint, ptr, length, true); | ||
757 | } | ||
758 | |||
759 | /* This function begins a transmit (on an IN endpoint), it does not block | ||
760 | * so the actual transmit is done in the interrupt handler. | ||
761 | */ | ||
762 | int usb_drv_send(int endpoint, void* ptr, int length) | ||
763 | { | ||
764 | /* The last arguement for queue specifies the dir of data (true==send) */ | ||
765 | return mxx_queue(endpoint, ptr, length, true); | ||
766 | } | ||
767 | |||
768 | /* This function begins a receive (on an OUT endpoint), it should not block | ||
769 | * so the actual receive is done in the interrupt handler. | ||
770 | */ | ||
771 | int usb_drv_recv(int endpoint, void* ptr, int length) | ||
772 | { | ||
773 | /* Last arguement for queue specifies the dir of data (false==receive) */ | ||
774 | return mxx_queue(endpoint, ptr, length, false); | ||
775 | } | ||
776 | |||
777 | /* This function checks the reset handshake speed status | ||
778 | * (Fullspeed or Highspeed) | ||
779 | */ | ||
780 | int usb_drv_port_speed(void) | ||
781 | { | ||
782 | int handshake = (M66591_HSFS & 0xFF); | ||
783 | |||
784 | if( handshake == 0x02) { | ||
785 | return 0; /* Handshook at Full-Speed */ | ||
786 | } else if( handshake == 0x03) { | ||
787 | return 1; /* Handshook at Hi-Speed */ | ||
788 | } else { | ||
789 | return -1; /* Error, handshake may not be complete */ | ||
790 | } | ||
791 | } | ||
792 | |||
793 | /* This function checks if the endpoint is stalled (error). I am not sure what | ||
794 | * the "in" variable is intended for. | ||
795 | */ | ||
796 | bool usb_drv_stalled(int endpoint,bool in) | ||
797 | { | ||
798 | (void) in; | ||
799 | |||
800 | bool stalled = (*(pipe_ctrl_addr(endpoint)) & (0x02)) ? true : false; | ||
801 | |||
802 | logf("mxx: stall?: %s ep: %d", stalled ? "true" : "false", endpoint); | ||
803 | |||
804 | if(stalled) { | ||
805 | return true; | ||
806 | } else { | ||
807 | return false; | ||
808 | } | ||
809 | } | ||
810 | |||
811 | /* This function stalls/unstalls the endpoint. Stalls only happen on error so | ||
812 | * if the endpoint is functioning properly this should not be called. I am | ||
813 | * not sure what the "in" variable is intended for. | ||
814 | */ | ||
815 | void usb_drv_stall(int endpoint, bool stall,bool in) | ||
816 | { | ||
817 | (void) in; | ||
818 | |||
819 | logf("mxx: stall - ep: %d", endpoint); | ||
820 | |||
821 | if(stall) { | ||
822 | /* Stall the pipe (host needs to intervene/error) */ | ||
823 | pipe_handshake(endpoint, PIPE_SHAKE_STALL); | ||
824 | } else { | ||
825 | /* Setting this to a NAK, not sure if it is appropriate */ | ||
826 | pipe_handshake(endpoint, PIPE_SHAKE_NAK); | ||
827 | } | ||
828 | } | ||
829 | |||
830 | /* !!!!!!!!!!This function is likely incomplete!!!!!!!!!!!!!! */ | ||
831 | void usb_drv_cancel_all_transfers(void) | ||
832 | { | ||
833 | int endpoint; | ||
834 | int flags; | ||
835 | |||
836 | logf("mxx: %s", __func__); | ||
837 | |||
838 | flags = disable_irq_save(); | ||
839 | for (endpoint = 0; endpoint < USB_NUM_ENDPOINTS; endpoint++) { | ||
840 | if (M66591_eps[endpoint].buf) { | ||
841 | M66591_eps[endpoint].buf = NULL; | ||
842 | } | ||
843 | } | ||
844 | |||
845 | restore_irq(flags); | ||
846 | } | ||
847 | |||
diff --git a/firmware/export/config-mrobe500.h b/firmware/export/config-mrobe500.h index f9e8d9ebf6..619e3fe8e7 100644 --- a/firmware/export/config-mrobe500.h +++ b/firmware/export/config-mrobe500.h | |||
@@ -35,6 +35,9 @@ | |||
35 | /* define this if you use an ATA controller */ | 35 | /* define this if you use an ATA controller */ |
36 | #define CONFIG_STORAGE STORAGE_ATA | 36 | #define CONFIG_STORAGE STORAGE_ATA |
37 | 37 | ||
38 | /* Define this to add support for ATA DMA */ | ||
39 | //#define HAVE_ATA_DMA | ||
40 | |||
38 | /* define this if you have a bitmap LCD display */ | 41 | /* define this if you have a bitmap LCD display */ |
39 | #define HAVE_LCD_BITMAP | 42 | #define HAVE_LCD_BITMAP |
40 | 43 | ||
@@ -114,6 +117,19 @@ | |||
114 | #define HAVE_TOUCHSCREEN | 117 | #define HAVE_TOUCHSCREEN |
115 | #define HAVE_BUTTON_DATA | 118 | #define HAVE_BUTTON_DATA |
116 | 119 | ||
120 | /* M66591 register base */ | ||
121 | #define M66591_BASE 0x60000000 | ||
122 | |||
123 | /* enable these for the usb stack */ | ||
124 | #define CONFIG_USBOTG USBOTG_M66591 | ||
125 | #define USE_ROCKBOX_USB | ||
126 | #define HAVE_USBSTACK | ||
127 | #define USB_STORAGE | ||
128 | /* usb stack and driver settings */ | ||
129 | #define USB_NUM_ENDPOINTS 7 | ||
130 | #define USB_VENDOR_ID 0x07b4 | ||
131 | #define USB_PRODUCT_ID 0x0281 | ||
132 | |||
117 | /* define this if the target has volume keys which can be used in the lists */ | 133 | /* define this if the target has volume keys which can be used in the lists */ |
118 | #define HAVE_VOLUME_IN_LIST | 134 | #define HAVE_VOLUME_IN_LIST |
119 | 135 | ||
diff --git a/firmware/export/config.h b/firmware/export/config.h index 5cdf46dcfd..696c923bb6 100644 --- a/firmware/export/config.h +++ b/firmware/export/config.h | |||
@@ -250,6 +250,7 @@ Lyre prototype 1*/ | |||
250 | #define RTC_JZ47XX 16 /* Ingenic Jz47XX */ | 250 | #define RTC_JZ47XX 16 /* Ingenic Jz47XX */ |
251 | 251 | ||
252 | /* USB On-the-go */ | 252 | /* USB On-the-go */ |
253 | #define USBOTG_M66591 6591 /* M:Robe 500 */ | ||
253 | #define USBOTG_ISP1362 1362 /* iriver H300 */ | 254 | #define USBOTG_ISP1362 1362 /* iriver H300 */ |
254 | #define USBOTG_ISP1583 1583 /* Creative Zen Vision:M */ | 255 | #define USBOTG_ISP1583 1583 /* Creative Zen Vision:M */ |
255 | #define USBOTG_M5636 5636 /* iAudio X5 */ | 256 | #define USBOTG_M5636 5636 /* iAudio X5 */ |
@@ -775,7 +776,7 @@ Lyre prototype 1*/ | |||
775 | #elif CONFIG_USBOTG == USBOTG_JZ4740 | 776 | #elif CONFIG_USBOTG == USBOTG_JZ4740 |
776 | #define USB_HAS_BULK | 777 | #define USB_HAS_BULK |
777 | #define USB_HAS_INTERRUPT | 778 | #define USB_HAS_INTERRUPT |
778 | #elif defined(CPU_TCC780X) || defined(CPU_TCC77X) | 779 | #elif defined(CPU_TCC780X) || defined(CPU_TCC77X) || defined(MROBE_500) |
779 | #define USB_HAS_BULK | 780 | #define USB_HAS_BULK |
780 | #endif /* CONFIG_USBOTG */ | 781 | #endif /* CONFIG_USBOTG */ |
781 | 782 | ||
diff --git a/firmware/export/m66591.h b/firmware/export/m66591.h new file mode 100644 index 0000000000..db7776e45f --- /dev/null +++ b/firmware/export/m66591.h | |||
@@ -0,0 +1,102 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id: $ | ||
9 | * | ||
10 | * Copyright (C) 2009 by Karl Kurbjun | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #include "config.h" | ||
23 | |||
24 | #define M66591_REG(addr) (*(volatile unsigned short *) \ | ||
25 | ((unsigned char *) M66591_BASE + (addr)) ) | ||
26 | |||
27 | /* Interrupt handler routine, visible for target handler */ | ||
28 | void USB_DEVICE(void); | ||
29 | |||
30 | /* Register offsets */ | ||
31 | #define M66591_TRN_CTRL M66591_REG(0x00) /* pg 14 */ | ||
32 | #define M66591_TRN_LNSTAT M66591_REG(0x02) /* pg 16 */ | ||
33 | |||
34 | #define M66591_HSFS M66591_REG(0x04) /* pg 17 */ | ||
35 | #define M66591_TESTMODE M66591_REG(0x06) /* pg 18 */ | ||
36 | |||
37 | #define M66591_PIN_CFG0 M66591_REG(0x08) /* pg 19 */ | ||
38 | #define M66591_PIN_CFG1 M66591_REG(0x0A) /* pg 20 */ | ||
39 | #define M66591_PIN_CFG2 M66591_REG(0x0C) /* pg 21 */ | ||
40 | |||
41 | #define M66591_CPORT M66591_REG(0x14) /* pg 23 */ | ||
42 | #define M66591_DPORT M66591_REG(0x18) /* pg 24 */ | ||
43 | |||
44 | #define M66591_DCP_CTRLEN M66591_REG(0x26) /* pg 25 */ | ||
45 | |||
46 | #define M66591_CPORT_CTRL0 M66591_REG(0x28) /* pg 26 */ | ||
47 | #define M66591_CPORT_CTRL1 M66591_REG(0x2C) /* pg 28 */ | ||
48 | #define M66591_CPORT_CTRL2 M66591_REG(0x2E) /* pg 30 */ | ||
49 | |||
50 | #define M66591_DPORT_CTRL0 M66591_REG(0x30) /* pg 31 */ | ||
51 | #define M66591_DPORT_CTRL1 M66591_REG(0x34) /* pg 34 */ | ||
52 | #define M66591_DPORT_CTRL2 M66591_REG(0x36) /* pg 36 */ | ||
53 | |||
54 | #define M66591_INTCFG_MAIN M66591_REG(0x40) /* pg 37 */ | ||
55 | #define M66591_INTCFG_OUT M66591_REG(0x42) /* pg 40 */ | ||
56 | #define M66591_INTCFG_RDY M66591_REG(0x44) /* pg 41 */ | ||
57 | #define M66591_INTCFG_NRDY M66591_REG(0x48) /* pg 42 */ | ||
58 | #define M66591_INTCFG_EMP M66591_REG(0x4C) /* pg 43 */ | ||
59 | |||
60 | #define M66591_INTSTAT_MAIN M66591_REG(0x60) /* pg 44 */ | ||
61 | #define M66591_INTSTAT_RDY M66591_REG(0x64) /* pg 48 */ | ||
62 | #define M66591_INTSTAT_NRDY M66591_REG(0x68) /* pg 50 */ | ||
63 | #define M66591_INTSTAT_EMP M66591_REG(0x6C) /* pg 53 */ | ||
64 | |||
65 | #define M66591_USB_ADDRESS M66591_REG(0x74) /* pg 56 */ | ||
66 | |||
67 | #define M66591_USB_REQ0 M66591_REG(0x78) /* pg 57 */ | ||
68 | #define M66591_USB_REQ1 M66591_REG(0x7A) /* pg 58 */ | ||
69 | #define M66591_USB_REQ2 M66591_REG(0x7C) /* pg 59 */ | ||
70 | #define M66591_USB_REQ3 M66591_REG(0x7E) /* pg 60 */ | ||
71 | |||
72 | #define M66591_DCP_CNTMD M66591_REG(0x82) /* pg 61 */ | ||
73 | #define M66591_DCP_MXPKSZ M66591_REG(0x84) /* pg 62 */ | ||
74 | #define M66591_DCPCTRL M66591_REG(0x88) /* pg 63 */ | ||
75 | |||
76 | #define M66591_PIPE_CFGSEL M66591_REG(0x8C) /* pg 65 */ | ||
77 | #define M66591_PIPE_CFGWND M66591_REG(0x90) /* pg 66 */ | ||
78 | |||
79 | #define M66591_PIPECTRL1 M66591_REG(0xA0) /* pg 69 */ | ||
80 | #define M66591_PIPECTRL2 M66591_REG(0xA2) /* pg 69 */ | ||
81 | #define M66591_PIPECTRL3 M66591_REG(0xA4) /* pg 69 */ | ||
82 | #define M66591_PIPECTRL4 M66591_REG(0xA6) /* pg 69 */ | ||
83 | #define M66591_PIPECTRL5 M66591_REG(0xA8) /* pg 71 */ | ||
84 | #define M66591_PIPECTRL6 M66591_REG(0xAA) /* pg 71 */ | ||
85 | |||
86 | /* These defines are used for CTRL register handshake setup | ||
87 | * They are used on the following registers: | ||
88 | * DCPCTRL and PIPECTRL(1-6) | ||
89 | */ | ||
90 | #define PIPE_SHAKE_NAK 0x00 | ||
91 | #define PIPE_SHAKE_BUF 0x01 | ||
92 | #define PIPE_SHAKE_STALL 0x02 | ||
93 | |||
94 | /* These defines are used for the control transfer stage status */ | ||
95 | #define CTRL_IDLE 0x00 /* Idle Stage */ | ||
96 | #define CTRL_RTDS 0x01 /* Read transfer data stage */ | ||
97 | #define CTRL_RTSS 0x02 /* Read transfer status stage */ | ||
98 | #define CTRL_WTDS 0x03 /* Write transfer data stage */ | ||
99 | #define CTRL_WTSS 0x04 /* Write transfer status stage */ | ||
100 | #define CTRL_WTND 0x05 /* Write transfer no data stage */ | ||
101 | #define CTRL_TRER 0x06 /* Transmit error stage */ | ||
102 | |||
diff --git a/firmware/target/arm/tms320dm320/boot.lds b/firmware/target/arm/tms320dm320/boot.lds index ff8203ccd8..0ee6c202a4 100644 --- a/firmware/target/arm/tms320dm320/boot.lds +++ b/firmware/target/arm/tms320dm320/boot.lds | |||
@@ -138,9 +138,20 @@ SECTIONS | |||
138 | . += TTB_SIZE; | 138 | . += TTB_SIZE; |
139 | } > DRAM | 139 | } > DRAM |
140 | 140 | ||
141 | /* The LCD buffer should be at the end of memory to protect against | ||
142 | * overflowing something else when the YUV blitter is fudging the screen | ||
143 | * size. | ||
144 | */ | ||
145 | |||
141 | .lcdbuffer (NOLOAD) : | 146 | .lcdbuffer (NOLOAD) : |
142 | { | 147 | { |
143 | _lcdbuf = .; | 148 | _lcdbuf = .; |
144 | . += LCD_BUFFER_SIZE; | 149 | . += LCD_BUFFER_SIZE; |
145 | } > DRAM | 150 | } > DRAM |
151 | |||
152 | .lcdbuffer2 (NOLOAD) : | ||
153 | { | ||
154 | _lcdbuf2 = .; | ||
155 | . += LCD_BUFFER_SIZE; | ||
156 | } > DRAM | ||
146 | } | 157 | } |
diff --git a/firmware/target/arm/tms320dm320/crt0.S b/firmware/target/arm/tms320dm320/crt0.S index 0243c13971..7c0c27eb74 100755 --- a/firmware/target/arm/tms320dm320/crt0.S +++ b/firmware/target/arm/tms320dm320/crt0.S | |||
@@ -75,7 +75,7 @@ start: | |||
75 | strhi r5, [r3], #4 | 75 | strhi r5, [r3], #4 |
76 | bhi 1b | 76 | bhi 1b |
77 | #endif | 77 | #endif |
78 | #endif /* !BOOTLOADER,!STUB */ | 78 | #endif /* !STUB */ |
79 | 79 | ||
80 | 80 | ||
81 | /* Initialise bss section to zero */ | 81 | /* Initialise bss section to zero */ |
@@ -113,26 +113,6 @@ stackmunge: | |||
113 | /* Switch to supervisor mode (no IRQ) */ | 113 | /* Switch to supervisor mode (no IRQ) */ |
114 | msr cpsr_c, #0xd3 | 114 | msr cpsr_c, #0xd3 |
115 | ldr sp, =stackend | 115 | ldr sp, =stackend |
116 | |||
117 | #if defined(BOOTLOADER) && !defined(CREATIVE_ZVx) | ||
118 | /* get the high part of our execute address */ | ||
119 | ldr r2, =0xffffff00 | ||
120 | and r4, pc, r2 | ||
121 | |||
122 | /* Copy bootloader to safe area - 0x01900000 */ | ||
123 | mov r5, #0x01900000 | ||
124 | ldr r6, = _dataend | ||
125 | sub r0, r6, r5 /* length of loader */ | ||
126 | add r0, r4, r0 /* r0 points to start of loader */ | ||
127 | 1: | ||
128 | cmp r5, r6 | ||
129 | ldrcc r2, [r4], #4 | ||
130 | strcc r2, [r5], #4 | ||
131 | bcc 1b | ||
132 | |||
133 | ldr pc, =start_loc /* jump to the relocated start_loc: */ | ||
134 | |||
135 | #endif | ||
136 | 116 | ||
137 | start_loc: | 117 | start_loc: |
138 | bl main | 118 | bl main |
diff --git a/firmware/target/arm/tms320dm320/mrobe-500/powermgmt-mr500.c b/firmware/target/arm/tms320dm320/mrobe-500/powermgmt-mr500.c index b81c34ac3b..6e361aac15 100755 --- a/firmware/target/arm/tms320dm320/mrobe-500/powermgmt-mr500.c +++ b/firmware/target/arm/tms320dm320/mrobe-500/powermgmt-mr500.c | |||
@@ -25,9 +25,9 @@ | |||
25 | #include "tsc2100.h" | 25 | #include "tsc2100.h" |
26 | #include "kernel.h" | 26 | #include "kernel.h" |
27 | 27 | ||
28 | unsigned short current_bat2 = 3910; | 28 | unsigned short current_bat2 = 4200; |
29 | unsigned short current_aux = 3910; | 29 | unsigned short current_aux = 4200; |
30 | static unsigned short current_voltage = 3910; | 30 | static unsigned short current_voltage = 4200; |
31 | const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = | 31 | const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = |
32 | { | 32 | { |
33 | 3450 | 33 | 3450 |
@@ -69,7 +69,7 @@ unsigned int battery_adc_voltage(void) | |||
69 | current_aux=((short)((int)(aux<<10)/4096*6*2.5)); | 69 | current_aux=((short)((int)(aux<<10)/4096*6*2.5)); |
70 | } | 70 | } |
71 | 71 | ||
72 | if (TIME_BEFORE(last_tick+2*HZ, current_tick)) | 72 | if (TIME_BEFORE(last_tick+2*HZ, current_tick) || last_tick==0) |
73 | { | 73 | { |
74 | tsadc=tsc2100_readreg(TSADC_PAGE, TSADC_ADDRESS); | 74 | tsadc=tsc2100_readreg(TSADC_PAGE, TSADC_ADDRESS); |
75 | 75 | ||
diff --git a/firmware/target/arm/tms320dm320/mrobe-500/usb-mr500.c b/firmware/target/arm/tms320dm320/mrobe-500/usb-mr500.c index 41211c2b47..2e3518868b 100644 --- a/firmware/target/arm/tms320dm320/mrobe-500/usb-mr500.c +++ b/firmware/target/arm/tms320dm320/mrobe-500/usb-mr500.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * \/ \/ \/ \/ \/ | 7 | * \/ \/ \/ \/ \/ |
8 | * $Id$ | 8 | * $Id$ |
9 | * | 9 | * |
10 | * Copyright (C) 2007 by Karl Kurbjun | 10 | * Copyright (C) 2007, 2009 by Karl Kurbjun |
11 | * | 11 | * |
12 | * This program is free software; you can redistribute it and/or | 12 | * This program is free software; you can redistribute it and/or |
13 | * modify it under the terms of the GNU General Public License | 13 | * modify it under the terms of the GNU General Public License |
@@ -18,42 +18,60 @@ | |||
18 | * KIND, either express or implied. | 18 | * KIND, either express or implied. |
19 | * | 19 | * |
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | #define LOGF_ENABLE | ||
21 | 22 | ||
22 | #include "config.h" | 23 | #include "config.h" |
24 | #include "logf.h" | ||
23 | #include "cpu.h" | 25 | #include "cpu.h" |
24 | #include "system.h" | 26 | #include "system.h" |
25 | #include "kernel.h" | ||
26 | #include "ata.h" | ||
27 | #include "usb.h" | ||
28 | #include "usb-target.h" | ||
29 | 27 | ||
30 | #define USB_RST_ASSERT | 28 | #include "m66591.h" |
31 | #define USB_RST_DEASSERT | ||
32 | 29 | ||
33 | #define USB_VPLUS_PWR_ASSERT | 30 | void usb_init_device(void) { |
34 | #define USB_VPLUS_PWR_DEASSERT | 31 | logf("mxx: SOC Init"); |
35 | 32 | ||
36 | #define USB_UNIT_IS_PRESENT USB_EXTRACTED | 33 | /* The EMIF timing that is currently used may not be apropriate when the |
34 | * device is boosted. The following values were used with sucess too: | ||
35 | * IO_EMIF_CS4CTRL1 = 0x66AB; | ||
36 | * IO_EMIF_CS4CTRL2 = 0x4220; | ||
37 | */ | ||
38 | IO_EMIF_CS4CTRL1 = 0x2245; | ||
39 | IO_EMIF_CS4CTRL2 = 0x4110; | ||
37 | 40 | ||
38 | /* The usb detect is one pin to the cpu active low */ | 41 | IO_GIO_DIR0 &= ~(1<<2); |
39 | inline int usb_detect(void) | 42 | IO_GIO_INV0 &= ~(1<<2); |
40 | { | 43 | IO_GIO_FSEL0 &= ~(0x03); |
41 | return USB_UNIT_IS_PRESENT; | 44 | |
42 | } | 45 | /* Drive the reset pin low */ |
46 | IO_GIO_BITCLR0 = 1<<2; | ||
47 | |||
48 | /* Wait a bit */ | ||
49 | udelay(3); | ||
43 | 50 | ||
44 | void usb_init_device(void) | 51 | /* Release the reset (drive it high) */ |
45 | { | 52 | IO_GIO_BITSET0 = 1<<2; |
46 | // ata_enable(true); | 53 | |
54 | udelay(300); | ||
55 | |||
56 | IO_GIO_DIR0 |= 1<<3; | ||
57 | IO_GIO_INV0 &= ~(1<<3); | ||
58 | IO_GIO_IRQPORT |= 1<<3; | ||
59 | |||
60 | /* Enable the MXX interrupt */ | ||
61 | IO_INTC_EINT1 |= (1<<8); /* IRQ_GIO3 */ | ||
47 | } | 62 | } |
48 | 63 | ||
49 | void usb_enable(bool on) | 64 | /* This is the initial interupt handler routine for the USB controller */ |
50 | { | 65 | void GIO3 (void) { |
51 | if (on) | 66 | /* Clear the interrupt, this is critical to do before running the full |
52 | { | 67 | * handler otherwise you might miss an interrupt and everything will stop |
53 | USB_VPLUS_PWR_ASSERT; | 68 | * working. |
54 | } | 69 | * |
55 | else | 70 | * The M66591 interrupt line is attached to GPIO3. |
56 | { | 71 | */ |
57 | USB_VPLUS_PWR_DEASSERT; | 72 | IO_INTC_IRQ1 = (1<<8); |
58 | } | 73 | |
74 | /* Start the full handler which is located in the driver */ | ||
75 | USB_DEVICE(); | ||
59 | } | 76 | } |
77 | |||
diff --git a/firmware/target/arm/tms320dm320/system-dm320.c b/firmware/target/arm/tms320dm320/system-dm320.c index b8c9eee87f..8742f59691 100644 --- a/firmware/target/arm/tms320dm320/system-dm320.c +++ b/firmware/target/arm/tms320dm320/system-dm320.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include "spi.h" | 28 | #include "spi.h" |
29 | #ifdef CREATIVE_ZVx | 29 | #ifdef CREATIVE_ZVx |
30 | #include "dma-target.h" | 30 | #include "dma-target.h" |
31 | #include "usb-mr500.h" | ||
31 | #endif | 32 | #endif |
32 | 33 | ||
33 | #define default_interrupt(name) \ | 34 | #define default_interrupt(name) \ |
@@ -308,3 +309,14 @@ void set_cpu_frequency(long frequency) | |||
308 | } | 309 | } |
309 | #endif | 310 | #endif |
310 | 311 | ||
312 | /* This function is pretty crude. It is not acurate to a usec, but errors on | ||
313 | * longer. | ||
314 | */ | ||
315 | void udelay(int usec) { | ||
316 | volatile int temp=usec*(175000/200); | ||
317 | |||
318 | while(temp) { | ||
319 | temp--; | ||
320 | } | ||
321 | } | ||
322 | |||
diff --git a/firmware/target/arm/tms320dm320/system-target.h b/firmware/target/arm/tms320dm320/system-target.h index 63d314f572..285dd0275f 100755 --- a/firmware/target/arm/tms320dm320/system-target.h +++ b/firmware/target/arm/tms320dm320/system-target.h | |||
@@ -28,4 +28,6 @@ | |||
28 | #define CPUFREQ_NORMAL 87500000 | 28 | #define CPUFREQ_NORMAL 87500000 |
29 | #define CPUFREQ_MAX 175000000 | 29 | #define CPUFREQ_MAX 175000000 |
30 | 30 | ||
31 | void udelay(int usec); | ||
32 | |||
31 | #endif /* SYSTEM_TARGET_H */ | 33 | #endif /* SYSTEM_TARGET_H */ |
diff --git a/firmware/usb.c b/firmware/usb.c index f918f19bc4..07683ce7b1 100644 --- a/firmware/usb.c +++ b/firmware/usb.c | |||
@@ -48,7 +48,8 @@ | |||
48 | /* Conditions under which we want the entire driver */ | 48 | /* Conditions under which we want the entire driver */ |
49 | #if !defined(BOOTLOADER) || (CONFIG_CPU == SH7034) || \ | 49 | #if !defined(BOOTLOADER) || (CONFIG_CPU == SH7034) || \ |
50 | (defined(TOSHIBA_GIGABEAT_S) && defined(USE_ROCKBOX_USB) && defined(USB_ENABLE_STORAGE)) || \ | 50 | (defined(TOSHIBA_GIGABEAT_S) && defined(USE_ROCKBOX_USB) && defined(USB_ENABLE_STORAGE)) || \ |
51 | (defined(HAVE_USBSTACK) && (defined(CREATIVE_ZVx) || \ | 51 | (defined(HAVE_USBSTACK) && (defined(CREATIVE_ZVx)) || \ |
52 | (defined(HAVE_USBSTACK) && (defined(OLYMPUS_MROBE_500)) || \ | ||
52 | defined(CPU_TCC77X) || defined(CPU_TCC780X))) || \ | 53 | defined(CPU_TCC77X) || defined(CPU_TCC780X))) || \ |
53 | (CONFIG_USBOTG == USBOTG_JZ4740) | 54 | (CONFIG_USBOTG == USBOTG_JZ4740) |
54 | #define USB_FULL_INIT | 55 | #define USB_FULL_INIT |