/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id$ * * Copyright (C) 2009 by Karl Kurbjun * Portions Copyright (C) 2007 by Catalin Patulea * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/ #define LOGF_ENABLE #include "system.h" #include "config.h" #include "string.h" #include "usb_ch9.h" #include "usb_core.h" #include "kernel.h" #include "panic.h" #include "usb_drv.h" #include "logf.h" #include "config.h" #include "cpu.h" #include "ata.h" #include "usb.h" #include "usb-target.h" #include "m66591.h" /******************************************************************************* * These are the driver specific defines. ******************************************************************************/ /* This define is primarily intended for testing, using HISPEED all the time * should be acceptable since the defice should down-train if the host does not * support HISPEED. */ #define HISPEED /* Right now sending blocks till the full transfer has completed, this needs to * be fixed so that it does not require a block. (USB_TRAN_LOCK ideally would * not be set). */ #define USB_TRAN_BLOCK /******************************************************************************* * The following functions are all helpers which should not be called directly * from the USB stack. They should only be called by eachother, or the USB * stack visible functions. ******************************************************************************/ static volatile unsigned short * pipe_ctrl_addr(int pipe); static void pipe_handshake(int pipe, int handshake); static void pipe_c_select (int pipe, bool dir); #if !defined(USB_TRAN_BLOCK) static int pipe_buffer_size (int pipe); #endif static int pipe_maxpack_size (int pipe); static void control_received(void); static void transfer_complete(int endpoint); static int mxx_transmit_receive(int endpoint); static int mxx_queue(int endpoint, void * ptr, int length, bool send); struct M66591_epstat { unsigned char dir; /* endpoint direction */ char *buf; /* user buffer to store data */ int length; /* how match data will fit */ volatile int count; /* actual data count */ bool waiting; /* is there data to transfer? */ bool busy; /* has the pipe been requested for use? */ } ; static struct M66591_epstat M66591_eps[USB_NUM_ENDPOINTS]; /* This function is used to return the control address for each pipe */ static volatile unsigned short * pipe_ctrl_addr(int pipe) { if(pipe==0) { return &M66591_DCPCTRL; } else { return &M66591_PIPECTRL1 + (pipe-1); } } /* This function sets the pipe/endpoint handshake */ static void pipe_handshake(int pipe, int handshake) { handshake&=0x03; if(handshake == PIPE_SHAKE_STALL) { if( *(pipe_ctrl_addr(pipe)) & 0x03 ) { *(pipe_ctrl_addr(pipe)) = 0x03; } else { *(pipe_ctrl_addr(pipe)) = 0x02; } } else { *(pipe_ctrl_addr(pipe)) = handshake; } } /* This function chooses the pipe desired and waits the required time before * warites/reads are valid */ static void pipe_c_select (int pipe, bool dir) { M66591_CPORT_CTRL0 = pipe | (1<<10) | (dir<<5); // Wait for the Pipe to be valid; udelay(2); } #if !defined(USB_TRAN_BLOCK) /* This returns the maximum buffer size of each pipe. On this device the size * is fixed. */ static int pipe_buffer_size (int pipe) { switch(pipe) { case 0: return 256; case 1: case 2: return 1024; case 3: case 4: return 512; case 5: case 6: return 64; default: return 0; } } #endif /* This function returns the maximum packet size for each endpoint/pipe. The * max packet size is dependent on whether the device is running High or Full * speed. */ static int pipe_maxpack_size (int pipe) { if( (M66591_HSFS & 0xFF) == 0x03 ) { /* Device is running Highspeed */ switch(pipe) { case 0: /* DCP max packet size is configurable */ return M66591_DCP_MXPKSZ; case 1: case 2: case 3: case 4: return 512; case 5: case 6: return 64; default: return 0; } } else { /* Device is running Full speed */ switch(pipe) { case 0: /* DCP max packet size is configurable */ return M66591_DCP_MXPKSZ; case 1: case 2: case 3: case 4: return 64; case 5: case 6: return 64; default: return 0; } } } /* This is a helper function that is only called from the interupt handler. It * copies the control packet information from the PHY and notifies the stack. */ static void control_received(void) { /* copy setup data from packet */ static struct usb_ctrlrequest temp; memcpy(&temp, (unsigned char*)&M66591_USB_REQ0, 8); logf("mxx: bReqType=0x%02x bReq=0x%02x wVal=0x%04x" " wIdx=0x%04x wLen=0x%04x", temp.bRequestType, temp.bRequest, temp.wValue, temp.wIndex, temp.wLength); /* acknowledge packet recieved (clear valid) */ M66591_INTSTAT_MAIN &= ~(1<<3); usb_core_control_request(&temp); } /* This is a helper function, it is used to notife the stack that a transfer is * done. */ static void transfer_complete(int endpoint) { M66591_INTCFG_EMP &= ~(1 << endpoint); logf("mxx: ep %d transfer complete", endpoint); int temp=M66591_eps[endpoint].dir ? USB_DIR_IN : USB_DIR_OUT; usb_core_transfer_complete(endpoint, temp, 0, M66591_eps[endpoint].length); } /* This is the main transmit routine that is typically called from the interrupt * handler (the queue function calls it in some situations) */ static int mxx_transmit_receive(int endpoint) { logf("mxx: do start"); /* Only the lower 15 bits of the endpoint correlate to the pipe number. * For example pipe 2 will corelate to endpoint 0x82, so the upper bits * need to be masked out. */ endpoint &= 0x7F; int i; /* Used as a loop counter */ int length; /* Used in transfers to determine the amount to send/receive */ bool send=M66591_eps[endpoint].dir; /* This is used as the internal buffer pointer */ unsigned short *ptrs; /* Choose the pipe that data is being transfered on */ pipe_c_select(endpoint, send); /* Check to see if the endpoint is ready and give it some time to become * ready. If it runs out of time exit out as an error. */ i = 0; while (!(M66591_CPORT_CTRL1&(1<<13))) { if (i++ > 100000) { logf("mxx: FIFO %d not ready", endpoint); return -1; } } /* Write to FIFO */ if(send) { int maxpack=pipe_maxpack_size(endpoint); #if defined(USB_TRAN_BLOCK) length = M66591_eps[endpoint].length; #else int bufsize=pipe_buffer_size(endpoint); length=MIN(M66591_eps[endpoint].length, bufsize); #endif /* Calculate the position in the buffer, all transfers should be 2-byte * aligned till the last packet or short packet. */ ptrs = (unsigned short *)(M66591_eps[endpoint].buf + M66591_eps[endpoint].count); /* Start sending data in 16-bit words */ for (i = 0; i < (length>>1); i++) { /* This wait is dangerous in the event that something happens to * the PHY pipe where it never becomes ready again, should probably * add a timeout, and ideally completely remove. */ while(!(M66591_CPORT_CTRL1&(1<<13))){}; M66591_CPORT = *ptrs++; M66591_eps[endpoint].count+=2; } /* If the length is odd, send the last byte after setting the byte width * of the FIFO. */ if(length & 0x01) { /* Unset MBW (8-bit transfer) */ M66591_CPORT_CTRL0 &= ~(1<<10); M66591_CPORT = *((unsigned char *)ptrs - 1); M66591_eps[endpoint].count++; } /* Set BVAL if length is not a multiple of the maximum packet size */ if( (length == 0) || (length % maxpack != 0) ) { logf("mxx: do set BVAL"); M66591_CPORT_CTRL1 |= (1<<15); } /* If the transfer is complete set up interrupts to notify when FIFO is * EMPTY, disable READY and let the handler know that there is nothing * left to transfer on this pipe. */ if(M66591_eps[endpoint].count == M66591_eps[endpoint].length) { /* Enable Empty flag */ M66591_INTCFG_EMP |= 1 << endpoint; /* Disable ready flag */ M66591_INTCFG_RDY &= ~(1 << endpoint); /* Nothing left to transfer */ M66591_eps[endpoint].waiting=false; } else { /* There is still data to transfer, make sure READY is enabled */ M66591_INTCFG_RDY |= 1 << endpoint; } } else { /* Read data from FIFO */ /* Read the number of bytes that the PHY received */ int receive_length=M66591_CPORT_CTRL1 & 0x03FF; /* The number of bytes to actually read is either what's left of the * amount requested, or the amount that the PHY received. Choose the * smaller of the two. */ length = MIN(M66591_eps[endpoint].length - M66591_eps[endpoint].count, receive_length); /* If the length is zero, just clear the buffer as specified in the * datasheet. Otherwise read in the data (in 16-bit pieces */ if(length==0) { /* Set the BCLR bit */ M66591_CPORT_CTRL1 |= 1<<14; } else { /* Set the position in the buffer */ ptrs = (unsigned short *)(M66591_eps[endpoint].buf + M66591_eps[endpoint].count); /* Read in the data (buffer size should be even). The PHY cannot * switch from 16-bit mode to 8-bit mode on an OUT buffer. */ for (i = 0; i < ((length+1)>>1); i++) { *ptrs++ = M66591_CPORT; M66591_eps[endpoint].count+=2; } } /* If the length was odd subtract 1 from the count */ M66591_eps[endpoint].count -= (length&0x01); /* If the requested size of data was received, or the data received was * less than the maximum packet size end the transfer. */ if( (M66591_eps[endpoint].count == M66591_eps[endpoint].length) || (length % pipe_maxpack_size(endpoint)) ) { /* If the host tries to send anything else the FIFO is not ready/ * enabled yet (NAK). */ pipe_handshake(endpoint, PIPE_SHAKE_NAK); /* Tell the interrupt handler that transfer is complete. */ M66591_eps[endpoint].waiting=false; /* Disable ready */ M66591_INTCFG_RDY &= ~(1 << endpoint); /* Let the stack know that the transfer is complete */ if(endpoint!=0) transfer_complete(endpoint); } } logf("mxx: do done ep %d %s len: %d cnt: %d", endpoint, send ? "out" : "in", length, M66591_eps[endpoint].count); return 0; } /* This function is used to start transfers. It is a helper function for the * usb_drv_send_nonblocking, usb_drv_send, and usb_drv_receive functions. */ static int mxx_queue(int endpoint, void * ptr, int length, bool send) { /* Disable IRQs */ int flags = disable_irq_save(); /* Only the lower 15 bits of the endpoint correlate to the pipe number. * For example pipe 2 will corelate to endpoint 0x82, so the upper bits * need to be masked out. */ endpoint &= 0x7F; /* Initialize the enpoint status registers used for the transfer */ M66591_eps[endpoint].buf=ptr; M66591_eps[endpoint].length=length; M66591_eps[endpoint].count=0; M66591_eps[endpoint].dir=send; M66591_eps[endpoint].waiting=true; logf("mxx: queue ep %d %s, len: %d", endpoint, send ? "out" : "in", length); /* Pick the pipe that communications are happening on */ pipe_c_select(endpoint, send); /* All transfers start with a BUF handshake */ pipe_handshake(endpoint, PIPE_SHAKE_BUF); /* This USB PHY takes care of control completion packets by setting the * CCPL bit in EP0 (endpoint 0, or DCP). If the control state is "write no * data tranfer" then we just need to set the CCPL bit (hopefully) * regardless of what the stack said to send. */ int control_state = (M66591_INTSTAT_MAIN & 0x07); if(endpoint==0 && control_state==CTRL_WTND) { logf("mxx: queue ep 0 ctls: 5, set ccpl"); /* Set CCPL */ M66591_DCPCTRL |= 1<<2; } else { /* This is the standard case for transmitting data */ if(send) { /* If the pipe is not ready don't try and send right away; instead * just set the READY interrupt so that the handler can initiate * the transfer. */ if((M66591_CPORT_CTRL1&(1<<13))) { mxx_transmit_receive(endpoint); } else { M66591_INTCFG_RDY |= 1 << endpoint; } if(length==0) { transfer_complete(endpoint); } } else { /* When receiving data, just enable the ready interrupt, the PHY * will trigger it and then the reads can start. */ M66591_INTCFG_RDY |= 1 << endpoint; } } /* Re-enable IRQs */ restore_irq(flags); return 0; } /******************************************************************************* * This is the interrupt handler for this driver. It should be called from the * target interrupt handler routine (eg. GPIO3 on M:Robe 500). ******************************************************************************/ void USB_DEVICE(void) { int pipe_restore=M66591_CPORT_CTRL0; logf("mxx: INT BEGIN tick: %d\n", (int) current_tick); logf("mxx: sMAIN0: 0x%04x, sRDY: 0x%04x", M66591_INTSTAT_MAIN, M66591_INTSTAT_RDY); logf("mxx: sNRDY: 0x%04x, sEMP: 0x%04x", M66591_INTSTAT_NRDY, M66591_INTSTAT_EMP); /* VBUS (connected) interrupt */ while ( M66591_INTSTAT_MAIN & (1<<15) ) { M66591_INTSTAT_MAIN &= ~(1<<15); /* If device is not clocked, interrupt flag must be set manually */ if ( !(M66591_TRN_CTRL & (1<<10)) ) { M66591_INTSTAT_MAIN |= (1<<15); } } /* Resume interrupt: This is not used. Extra logic needs to be added similar * to the VBUS interrupt incase the PHY clock is not running. */ if(M66591_INTSTAT_MAIN & (1<<14)) { M66591_INTSTAT_MAIN &= ~(1<<14); logf("mxx: RESUME"); } /* Device state transition interrupt: Not used, but useful for debugging */ if(M66591_INTSTAT_MAIN & (1<<12)) { M66591_INTSTAT_MAIN &= ~(1<<12); logf("mxx: DEV state CHANGE=%d", ((M66591_INTSTAT_MAIN & (0x07<<4)) >> 4) ); } /* Control transfer stage interrupt */ if(M66591_INTSTAT_MAIN & (1<<11)) { M66591_INTSTAT_MAIN &= ~(1<<11); int control_state = (M66591_INTSTAT_MAIN & 0x07); logf("mxx: CTRT with CTSQ=%d", control_state); switch ( control_state ) { case CTRL_IDLE: transfer_complete(0); break; case CTRL_RTDS: case CTRL_WTDS: case CTRL_WTND: /* If data is not valid stop */ if(!(M66591_INTSTAT_MAIN & (1<<3)) ) { logf("mxx: CTRT interrupt but VALID is false"); break; } control_received(); break; case CTRL_RTSS: case CTRL_WTSS: pipe_handshake(0, PIPE_SHAKE_BUF); M66591_DCPCTRL |= 1<<2; /* Set CCPL */ break; default: logf("mxx: CTRT with unknown CTSQ"); break; } } /* FIFO EMPTY interrupt: when this happens the transfer should be complete. * When the interrupt occurs notify the stack. */ if(M66591_INTSTAT_MAIN & (1<<10)) { int i; logf("mxx: INT EMPTY: 0x%04x", M66591_INTSTAT_EMP); for(i=0; i USB_NUM_ENDPOINTS || M66591_eps[ep].busy == false) return ; flags = disable_irq_save(); logf("mxx: ep %d release", ep); M66591_eps[ep].busy = false; M66591_eps[ep].dir = -1; restore_irq(flags); } /* Periodically called to check if a cable was plugged into the device */ inline int usb_detect(void) { if(M66591_INTSTAT_MAIN&(1<<7)) return USB_INSERTED; else return USB_EXTRACTED; } void usb_enable(bool on) { logf("mxx: %s: %s", __FUNCTION__, on ? "true" : "false"); if (on) usb_core_init(); else usb_core_exit(); } /* This is where the driver stuff starts */ void usb_drv_init(void) { logf("mxx: Device Init"); /* State left behind by m:robe 500i original firmware */ M66591_TRN_CTRL = 0x8001; /* External 48 MHz clock */ M66591_TRN_LNSTAT = 0x0040; /* "Reserved. Set it to '1'." */ M66591_PIN_CFG0 = 0x0000; M66591_PIN_CFG1 = 0x8000; /* Drive Current: 3.3V setting */ M66591_PIN_CFG2 = 0x0000; M66591_INTCFG_MAIN = 0x0000; /* All Interrupts Disable for now */ M66591_INTCFG_OUT = 0x0000; /* Sense is edge, polarity is low */ M66591_INTCFG_RDY = 0x0000; M66591_INTCFG_NRDY = 0x0000; M66591_INTCFG_EMP = 0x0000; M66591_INTSTAT_MAIN = 0; M66591_INTSTAT_RDY = 0; M66591_INTSTAT_NRDY = 0; M66591_INTSTAT_EMP = 0; } /* fully enable driver */ void usb_attach(void) { int i; /* Reset Endpoint states */ for(i=0; i