summaryrefslogtreecommitdiff
path: root/firmware/drivers/m66591.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers/m66591.c')
-rw-r--r--firmware/drivers/m66591.c188
1 files changed, 124 insertions, 64 deletions
diff --git a/firmware/drivers/m66591.c b/firmware/drivers/m66591.c
index 2ce121a263..1197485cd2 100644
--- a/firmware/drivers/m66591.c
+++ b/firmware/drivers/m66591.c
@@ -19,7 +19,7 @@
19 * KIND, either express or implied. 19 * KIND, either express or implied.
20 * 20 *
21 ****************************************************************************/ 21 ****************************************************************************/
22#define LOGF_ENABLE 22//#define LOGF_ENABLE
23 23
24#include "system.h" 24#include "system.h"
25#include "config.h" 25#include "config.h"
@@ -47,9 +47,10 @@
47 */ 47 */
48#define HISPEED 48#define HISPEED
49 49
50/* Right now sending blocks till the full transfer has completed, this needs to 50/* Right now sending blocks till the full transfer has completed. The driver
51 * be fixed so that it does not require a block. (USB_TRAN_LOCK ideally would 51 * will work without USB_TRAN_BLOCK set, but it is more than 50% slower.
52 * not be set). 52 * The driver is more "Proper" without USB_TRAN_BLOCK defined so if you start
53 * having freezeups or trouble using USB undefine this option.
53 */ 54 */
54#define USB_TRAN_BLOCK 55#define USB_TRAN_BLOCK
55 56
@@ -69,7 +70,8 @@ static int pipe_maxpack_size (int pipe);
69static void control_received(void); 70static void control_received(void);
70static void transfer_complete(int endpoint); 71static void transfer_complete(int endpoint);
71static int mxx_transmit_receive(int endpoint); 72static int mxx_transmit_receive(int endpoint);
72static int mxx_queue(int endpoint, void * ptr, int length, bool send); 73static int mxx_queue(int endpoint, void * ptr, int length, bool send,
74 bool wait);
73 75
74struct M66591_epstat { 76struct M66591_epstat {
75 unsigned char dir; /* endpoint direction */ 77 unsigned char dir; /* endpoint direction */
@@ -91,6 +93,15 @@ static volatile unsigned short * pipe_ctrl_addr(int pipe) {
91 } 93 }
92} 94}
93 95
96static void pipe_init(int pipe) {
97 volatile unsigned short *pipe_cfg;
98 pipe_cfg = pipe_ctrl_addr(pipe);
99
100 *pipe_cfg |= 1<<9; /* ACLR */
101 *pipe_cfg &= ~(1<<9); /* Force de-assertion */
102 *pipe_cfg |= 1<<8; /* SQCLR */
103}
104
94/* This function sets the pipe/endpoint handshake */ 105/* This function sets the pipe/endpoint handshake */
95static void pipe_handshake(int pipe, int handshake) { 106static void pipe_handshake(int pipe, int handshake) {
96 handshake&=0x03; 107 handshake&=0x03;
@@ -125,7 +136,10 @@ static int pipe_buffer_size (int pipe) {
125 return 256; 136 return 256;
126 case 1: 137 case 1:
127 case 2: 138 case 2:
128 return 1024; 139 if(M66591_PIPE_CFGWND & (1<<9) )
140 return 1024;
141 else
142 return 512;
129 case 3: 143 case 3:
130 case 4: 144 case 4:
131 return 512; 145 return 512;
@@ -206,7 +220,7 @@ static void transfer_complete(int endpoint) {
206 logf("mxx: ep %d transfer complete", endpoint); 220 logf("mxx: ep %d transfer complete", endpoint);
207 int temp=M66591_eps[endpoint].dir ? USB_DIR_IN : USB_DIR_OUT; 221 int temp=M66591_eps[endpoint].dir ? USB_DIR_IN : USB_DIR_OUT;
208 usb_core_transfer_complete(endpoint, temp, 0, 222 usb_core_transfer_complete(endpoint, temp, 0,
209 M66591_eps[endpoint].length); 223 M66591_eps[endpoint].count);
210} 224}
211 225
212/* This is the main transmit routine that is typically called from the interrupt 226/* This is the main transmit routine that is typically called from the interrupt
@@ -250,7 +264,8 @@ static int mxx_transmit_receive(int endpoint) {
250 length = M66591_eps[endpoint].length; 264 length = M66591_eps[endpoint].length;
251#else 265#else
252 int bufsize=pipe_buffer_size(endpoint); 266 int bufsize=pipe_buffer_size(endpoint);
253 length=MIN(M66591_eps[endpoint].length, bufsize); 267 length=MIN(M66591_eps[endpoint].length - M66591_eps[endpoint].count,
268 bufsize);
254#endif 269#endif
255 270
256 /* Calculate the position in the buffer, all transfers should be 2-byte 271 /* Calculate the position in the buffer, all transfers should be 2-byte
@@ -259,32 +274,70 @@ static int mxx_transmit_receive(int endpoint) {
259 ptrs = (unsigned short *)(M66591_eps[endpoint].buf 274 ptrs = (unsigned short *)(M66591_eps[endpoint].buf
260 + M66591_eps[endpoint].count); 275 + M66591_eps[endpoint].count);
261 276
262 /* Start sending data in 16-bit words */ 277 /* Check if the buffer is alligned */
263 for (i = 0; i < (length>>1); i++) { 278 if( LIKELY(((int)ptrs) & 0x01) == 0 )
264 /* This wait is dangerous in the event that something happens to 279 {
265 * the PHY pipe where it never becomes ready again, should probably 280 /* Start sending data in 16-bit words (fast) */
266 * add a timeout, and ideally completely remove. 281 for (i = 0; i < (length>>1); i++) {
267 */ 282#if defined(USB_TRAN_BLOCK)
268 while(!(M66591_CPORT_CTRL1&(1<<13))){}; 283 /* This wait is dangerous in the event that something happens
284 * to the PHY pipe where it never becomes ready again, should
285 * probably add a timeout, and ideally completely remove.
286 */
287 while(!(M66591_CPORT_CTRL1&(1<<13))){};
288#endif
269 289
270 M66591_CPORT = *ptrs++; 290 M66591_CPORT = *ptrs++;
271 M66591_eps[endpoint].count+=2; 291 M66591_eps[endpoint].count+=2;
272 } 292 }
273 293
274 /* If the length is odd, send the last byte after setting the byte width 294 /* If the length is odd, send the last byte after setting the byte
275 * of the FIFO. 295 * width of the FIFO.
276 */ 296 */
277 if(length & 0x01) { 297 if(length & 0x01) {
278 /* Unset MBW (8-bit transfer) */ 298 /* Unset MBW (8-bit transfer) */
279 M66591_CPORT_CTRL0 &= ~(1<<10); 299 M66591_CPORT_CTRL0 &= ~(1<<10);
280 M66591_CPORT = *((unsigned char *)ptrs - 1); 300 M66591_CPORT = *((unsigned char *)ptrs);
281 M66591_eps[endpoint].count++; 301 M66591_eps[endpoint].count++;
302 }
282 } 303 }
283 304 else
284 /* Set BVAL if length is not a multiple of the maximum packet size */ 305 {
285 if( (length == 0) || (length % maxpack != 0) ) { 306 /* The buffer is mis-aligned - data needs to be organized first.
286 logf("mxx: do set BVAL"); 307 * This is slower than the above method.
287 M66591_CPORT_CTRL1 |= (1<<15); 308 */
309 unsigned short sbuf;
310 unsigned char *ptrc = (unsigned char*)ptrs;
311
312 /* Start sending data in 16-bit words */
313 for (i = 0; i < (length>>1); i++) {
314#if defined(USB_TRAN_BLOCK)
315 /* This wait is dangerous in the event that something happens
316 * to the PHY pipe where it never becomes ready again, should
317 * probably add a timeout, and ideally completely remove.
318 */
319 while(!(M66591_CPORT_CTRL1&(1<<13))){};
320#endif
321
322 /* These are mis-aligned accesses so the data nees to be
323 * arranged.
324 */
325 sbuf = (*(ptrc+1) << 8) | *ptrc;
326 ptrc += 2;
327
328 M66591_CPORT = sbuf;
329 M66591_eps[endpoint].count+=2;
330 }
331
332 /* If the length is odd, send the last byte after setting the byte
333 * width of the FIFO.
334 */
335 if(length & 0x01) {
336 /* Unset MBW (8-bit transfer) */
337 M66591_CPORT_CTRL0 &= ~(1<<10);
338 M66591_CPORT = *ptrc;
339 M66591_eps[endpoint].count++;
340 }
288 } 341 }
289 342
290 /* If the transfer is complete set up interrupts to notify when FIFO is 343 /* If the transfer is complete set up interrupts to notify when FIFO is
@@ -302,6 +355,12 @@ static int mxx_transmit_receive(int endpoint) {
302 /* There is still data to transfer, make sure READY is enabled */ 355 /* There is still data to transfer, make sure READY is enabled */
303 M66591_INTCFG_RDY |= 1 << endpoint; 356 M66591_INTCFG_RDY |= 1 << endpoint;
304 } 357 }
358
359 /* Set BVAL if length is not a multiple of the maximum packet size */
360 if( (length == 0) || (length % maxpack != 0) ) {
361 logf("mxx: do set BVAL");
362 M66591_CPORT_CTRL1 |= (1<<15) | ((length == 0) << 14);
363 }
305 } else { 364 } else {
306 /* Read data from FIFO */ 365 /* Read data from FIFO */
307 366
@@ -366,8 +425,17 @@ static int mxx_transmit_receive(int endpoint) {
366 425
367/* This function is used to start transfers. It is a helper function for the 426/* This function is used to start transfers. It is a helper function for the
368 * usb_drv_send_nonblocking, usb_drv_send, and usb_drv_receive functions. 427 * usb_drv_send_nonblocking, usb_drv_send, and usb_drv_receive functions.
428 *
429 * The functionality for wait needs to be added. Currently the driver is
430 * always used in a blocking mode(USB_TRAN_BLOCK) so it is not required.
369 */ 431 */
370static int mxx_queue(int endpoint, void * ptr, int length, bool send) { 432static int mxx_queue(int endpoint, void * ptr, int length, bool send,
433 bool wait)
434{
435#if defined(USB_TRAN_BLOCK) && !defined(LOGF_ENABLE)
436 (void) wait;
437#endif
438
371 /* Disable IRQs */ 439 /* Disable IRQs */
372 int flags = disable_irq_save(); 440 int flags = disable_irq_save();
373 441
@@ -384,7 +452,8 @@ static int mxx_queue(int endpoint, void * ptr, int length, bool send) {
384 M66591_eps[endpoint].dir=send; 452 M66591_eps[endpoint].dir=send;
385 M66591_eps[endpoint].waiting=true; 453 M66591_eps[endpoint].waiting=true;
386 454
387 logf("mxx: queue ep %d %s, len: %d", endpoint, send ? "out" : "in", length); 455 logf("mxx: queue ep %d %s, len: %d, wait: %d",
456 endpoint, send ? "out" : "in", length, wait);
388 457
389 /* Pick the pipe that communications are happening on */ 458 /* Pick the pipe that communications are happening on */
390 pipe_c_select(endpoint, send); 459 pipe_c_select(endpoint, send);
@@ -436,9 +505,10 @@ static int mxx_queue(int endpoint, void * ptr, int length, bool send) {
436 * This is the interrupt handler for this driver. It should be called from the 505 * This is the interrupt handler for this driver. It should be called from the
437 * target interrupt handler routine (eg. GPIO3 on M:Robe 500). 506 * target interrupt handler routine (eg. GPIO3 on M:Robe 500).
438 ******************************************************************************/ 507 ******************************************************************************/
508void USB_DEVICE(void) __attribute__ ((section(".icode")));
439void USB_DEVICE(void) { 509void USB_DEVICE(void) {
440 int pipe_restore=M66591_CPORT_CTRL0; 510 int pipe_restore=M66591_CPORT_CTRL0;
441 logf("mxx: INT BEGIN tick: %d\n", (int) current_tick); 511 logf("\nmxx: INT BEGIN tick: %d", (int) current_tick);
442 512
443 logf("mxx: sMAIN0: 0x%04x, sRDY: 0x%04x", 513 logf("mxx: sMAIN0: 0x%04x, sRDY: 0x%04x",
444 M66591_INTSTAT_MAIN, M66591_INTSTAT_RDY); 514 M66591_INTSTAT_MAIN, M66591_INTSTAT_RDY);
@@ -548,7 +618,7 @@ void USB_DEVICE(void) {
548 618
549 /* Restore the pipe state before the interrupt occured */ 619 /* Restore the pipe state before the interrupt occured */
550 M66591_CPORT_CTRL0=pipe_restore; 620 M66591_CPORT_CTRL0=pipe_restore;
551 logf("\nmxx: INT END"); 621 logf("mxx: INT END\n");
552} 622}
553 623
554/******************************************************************************* 624/*******************************************************************************
@@ -576,7 +646,7 @@ int usb_drv_request_endpoint(int type, int dir) {
576 646
577 if (type == USB_ENDPOINT_XFER_BULK) { 647 if (type == USB_ENDPOINT_XFER_BULK) {
578 /* Enable double buffer mode (only used for ep 1 and 2) */ 648 /* Enable double buffer mode (only used for ep 1 and 2) */
579 pipecfg |= 1<<9; 649 pipecfg |= 1<<9 | 1<<8;
580 650
581 /* Bulk endpoints must be between 1 and 4 inclusive */ 651 /* Bulk endpoints must be between 1 and 4 inclusive */
582 ep=1; 652 ep=1;
@@ -591,6 +661,8 @@ int usb_drv_request_endpoint(int type, int dir) {
591 } else if (type == USB_ENDPOINT_XFER_INT) { 661 } else if (type == USB_ENDPOINT_XFER_INT) {
592 ep=5; 662 ep=5;
593 663
664 pipecfg |= 1<<13;
665
594 while(M66591_eps[ep].busy && ep++<7); 666 while(M66591_eps[ep].busy && ep++<7);
595 667
596 /* If this reached 7 the endpoints were all busy */ 668 /* If this reached 7 the endpoints were all busy */
@@ -612,14 +684,16 @@ int usb_drv_request_endpoint(int type, int dir) {
612 684
613 M66591_PIPE_CFGSEL=ep; 685 M66591_PIPE_CFGSEL=ep;
614 686
615 /* Enable pipe (15) and continuous transfer mode (8) */ 687 /* Enable pipe (15) */
616 pipecfg |= 1<<15 | 1<<8; 688 pipecfg |= 1<<15;
617 689
618 pipe_handshake(ep, PIPE_SHAKE_NAK); 690 pipe_handshake(ep, PIPE_SHAKE_NAK);
619 691
620 /* Setup the flags */ 692 /* Setup the flags */
621 M66591_PIPE_CFGWND=pipecfg; 693 M66591_PIPE_CFGWND=pipecfg;
622 694
695 pipe_init(ep);
696
623 logf("mxx: ep req ep#: %d config: 0x%04x", ep, M66591_PIPE_CFGWND); 697 logf("mxx: ep req ep#: %d config: 0x%04x", ep, M66591_PIPE_CFGWND);
624 698
625 return ep | dir; 699 return ep | dir;
@@ -664,24 +738,13 @@ void usb_enable(bool on) {
664void usb_drv_init(void) { 738void usb_drv_init(void) {
665 logf("mxx: Device Init"); 739 logf("mxx: Device Init");
666 740
667 /* State left behind by m:robe 500i original firmware */
668 M66591_TRN_CTRL = 0x8001; /* External 48 MHz clock */
669 M66591_TRN_LNSTAT = 0x0040; /* "Reserved. Set it to '1'." */
670
671 M66591_PIN_CFG0 = 0x0000;
672 M66591_PIN_CFG1 = 0x8000; /* Drive Current: 3.3V setting */ 741 M66591_PIN_CFG1 = 0x8000; /* Drive Current: 3.3V setting */
673 M66591_PIN_CFG2 = 0x0000; 742 M66591_PIN_CFG2 = 0x0000;
674 743
675 M66591_INTCFG_MAIN = 0x0000; /* All Interrupts Disable for now */ 744 M66591_TRN_CTRL = 0x8000; /* External 48 MHz clock */
676 M66591_INTCFG_OUT = 0x0000; /* Sense is edge, polarity is low */ 745 M66591_TRN_CTRL |=0x0001;
677 M66591_INTCFG_RDY = 0x0000; 746
678 M66591_INTCFG_NRDY = 0x0000; 747 M66591_INTCFG_MAIN |=0x8000; /* Enable VBUS interrupt */
679 M66591_INTCFG_EMP = 0x0000;
680
681 M66591_INTSTAT_MAIN = 0;
682 M66591_INTSTAT_RDY = 0;
683 M66591_INTSTAT_NRDY = 0;
684 M66591_INTSTAT_EMP = 0;
685} 748}
686 749
687/* fully enable driver */ 750/* fully enable driver */
@@ -713,17 +776,17 @@ void usb_attach(void) {
713 M66591_TRN_CTRL &= ~(1<<7); 776 M66591_TRN_CTRL &= ~(1<<7);
714#endif 777#endif
715 778
716 /* Enable oscillation buffer */ 779 /* Enable oscillation buffer XCKE */
717 M66591_TRN_CTRL |= (1<<13); 780 M66591_TRN_CTRL |= (1<<13);
718 781
719 udelay(1500); 782 udelay(1500);
720 783
721 /* Enable reference clock, PLL */ 784 /* Enable reference clock, PLL RCKE */
722 M66591_TRN_CTRL |= (3<<11); 785 M66591_TRN_CTRL |= (3<<11);
723 786
724 udelay(9); 787 udelay(9);
725 788
726 /* Enable internal clock supply */ 789 /* Enable internal clock supply SCKE */
727 M66591_TRN_CTRL |= (1<<10); 790 M66591_TRN_CTRL |= (1<<10);
728 791
729 /* Disable PIPE ready interrupts */ 792 /* Disable PIPE ready interrupts */
@@ -744,7 +807,7 @@ void usb_attach(void) {
744 M66591_DCP_CNTMD |= (1<<8); 807 M66591_DCP_CNTMD |= (1<<8);
745 808
746 /* Set the threshold that the PHY will automatically transmit from EP0 */ 809 /* Set the threshold that the PHY will automatically transmit from EP0 */
747 M66591_DCP_CTRLEN = 128; 810 M66591_DCP_CTRLEN = 256;
748 811
749 pipe_handshake(0, PIPE_SHAKE_NAK); 812 pipe_handshake(0, PIPE_SHAKE_NAK);
750 813
@@ -793,8 +856,7 @@ void usb_drv_exit(void) {
793 */ 856 */
794int usb_drv_send_nonblocking(int endpoint, void* ptr, int length) 857int usb_drv_send_nonblocking(int endpoint, void* ptr, int length)
795{ 858{
796 /* The last arguement for queue specifies the dir of data (true==send) */ 859 return mxx_queue(endpoint, ptr, length, true, false);
797 return mxx_queue(endpoint, ptr, length, true);
798} 860}
799 861
800/* This function begins a transmit (on an IN endpoint), it does not block 862/* This function begins a transmit (on an IN endpoint), it does not block
@@ -802,8 +864,7 @@ int usb_drv_send_nonblocking(int endpoint, void* ptr, int length)
802 */ 864 */
803int usb_drv_send(int endpoint, void* ptr, int length) 865int usb_drv_send(int endpoint, void* ptr, int length)
804{ 866{
805 /* The last arguement for queue specifies the dir of data (true==send) */ 867 return mxx_queue(endpoint, ptr, length, true, true);
806 return mxx_queue(endpoint, ptr, length, true);
807} 868}
808 869
809/* This function begins a receive (on an OUT endpoint), it should not block 870/* This function begins a receive (on an OUT endpoint), it should not block
@@ -811,8 +872,7 @@ int usb_drv_send(int endpoint, void* ptr, int length)
811 */ 872 */
812int usb_drv_recv(int endpoint, void* ptr, int length) 873int usb_drv_recv(int endpoint, void* ptr, int length)
813{ 874{
814 /* Last arguement for queue specifies the dir of data (false==receive) */ 875 return mxx_queue(endpoint, ptr, length, false, false);
815 return mxx_queue(endpoint, ptr, length, false);
816} 876}
817 877
818/* This function checks the reset handshake speed status 878/* This function checks the reset handshake speed status