From 4a483bb1bf69a0f0a1bf99aaa9bb47c6f79ab990 Mon Sep 17 00:00:00 2001 From: Karl Kurbjun Date: Mon, 8 Jun 2009 00:19:16 +0000 Subject: 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 --- firmware/SOURCES | 4 +- firmware/drivers/m66591.c | 847 +++++++++++++++++++++ firmware/export/config-mrobe500.h | 16 + firmware/export/config.h | 3 +- firmware/export/m66591.h | 102 +++ firmware/target/arm/tms320dm320/boot.lds | 11 + firmware/target/arm/tms320dm320/crt0.S | 22 +- .../arm/tms320dm320/mrobe-500/powermgmt-mr500.c | 8 +- .../target/arm/tms320dm320/mrobe-500/usb-mr500.c | 74 +- firmware/target/arm/tms320dm320/system-dm320.c | 12 + firmware/target/arm/tms320dm320/system-target.h | 2 + firmware/usb.c | 3 +- 12 files changed, 1048 insertions(+), 56 deletions(-) create mode 100644 firmware/drivers/m66591.c create mode 100644 firmware/export/m66591.h (limited to 'firmware') 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 #ifdef USB_ENABLE_HID usbstack/usb_hid.c #endif -#if CONFIG_USBOTG == USBOTG_ARC +#if CONFIG_USBOTG == USBOTG_M66591 +drivers/m66591.c +#elif CONFIG_USBOTG == USBOTG_ARC target/arm/usb-drv-arc.c #elif CONFIG_USBOTG == USBOTG_ISP1583 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 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: usb-mr500.c 18487 2008-09-10 20:14:22Z bertrik $ + * + * 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. + ******************************************************************************/ +#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. It is + * Currently only setup to support Highspeed mode. + */ +static int pipe_maxpack_size (int pipe) { + 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; + } +} + +/* 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 htat 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 ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: $ + * + * Copyright (C) 2009 by Karl Kurbjun + * + * 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. + * + ****************************************************************************/ + +#include "config.h" + +#define M66591_REG(addr) (*(volatile unsigned short *) \ + ((unsigned char *) M66591_BASE + (addr)) ) + +/* Interrupt handler routine, visible for target handler */ +void USB_DEVICE(void); + +/* Register offsets */ +#define M66591_TRN_CTRL M66591_REG(0x00) /* pg 14 */ +#define M66591_TRN_LNSTAT M66591_REG(0x02) /* pg 16 */ + +#define M66591_HSFS M66591_REG(0x04) /* pg 17 */ +#define M66591_TESTMODE M66591_REG(0x06) /* pg 18 */ + +#define M66591_PIN_CFG0 M66591_REG(0x08) /* pg 19 */ +#define M66591_PIN_CFG1 M66591_REG(0x0A) /* pg 20 */ +#define M66591_PIN_CFG2 M66591_REG(0x0C) /* pg 21 */ + +#define M66591_CPORT M66591_REG(0x14) /* pg 23 */ +#define M66591_DPORT M66591_REG(0x18) /* pg 24 */ + +#define M66591_DCP_CTRLEN M66591_REG(0x26) /* pg 25 */ + +#define M66591_CPORT_CTRL0 M66591_REG(0x28) /* pg 26 */ +#define M66591_CPORT_CTRL1 M66591_REG(0x2C) /* pg 28 */ +#define M66591_CPORT_CTRL2 M66591_REG(0x2E) /* pg 30 */ + +#define M66591_DPORT_CTRL0 M66591_REG(0x30) /* pg 31 */ +#define M66591_DPORT_CTRL1 M66591_REG(0x34) /* pg 34 */ +#define M66591_DPORT_CTRL2 M66591_REG(0x36) /* pg 36 */ + +#define M66591_INTCFG_MAIN M66591_REG(0x40) /* pg 37 */ +#define M66591_INTCFG_OUT M66591_REG(0x42) /* pg 40 */ +#define M66591_INTCFG_RDY M66591_REG(0x44) /* pg 41 */ +#define M66591_INTCFG_NRDY M66591_REG(0x48) /* pg 42 */ +#define M66591_INTCFG_EMP M66591_REG(0x4C) /* pg 43 */ + +#define M66591_INTSTAT_MAIN M66591_REG(0x60) /* pg 44 */ +#define M66591_INTSTAT_RDY M66591_REG(0x64) /* pg 48 */ +#define M66591_INTSTAT_NRDY M66591_REG(0x68) /* pg 50 */ +#define M66591_INTSTAT_EMP M66591_REG(0x6C) /* pg 53 */ + +#define M66591_USB_ADDRESS M66591_REG(0x74) /* pg 56 */ + +#define M66591_USB_REQ0 M66591_REG(0x78) /* pg 57 */ +#define M66591_USB_REQ1 M66591_REG(0x7A) /* pg 58 */ +#define M66591_USB_REQ2 M66591_REG(0x7C) /* pg 59 */ +#define M66591_USB_REQ3 M66591_REG(0x7E) /* pg 60 */ + +#define M66591_DCP_CNTMD M66591_REG(0x82) /* pg 61 */ +#define M66591_DCP_MXPKSZ M66591_REG(0x84) /* pg 62 */ +#define M66591_DCPCTRL M66591_REG(0x88) /* pg 63 */ + +#define M66591_PIPE_CFGSEL M66591_REG(0x8C) /* pg 65 */ +#define M66591_PIPE_CFGWND M66591_REG(0x90) /* pg 66 */ + +#define M66591_PIPECTRL1 M66591_REG(0xA0) /* pg 69 */ +#define M66591_PIPECTRL2 M66591_REG(0xA2) /* pg 69 */ +#define M66591_PIPECTRL3 M66591_REG(0xA4) /* pg 69 */ +#define M66591_PIPECTRL4 M66591_REG(0xA6) /* pg 69 */ +#define M66591_PIPECTRL5 M66591_REG(0xA8) /* pg 71 */ +#define M66591_PIPECTRL6 M66591_REG(0xAA) /* pg 71 */ + +/* These defines are used for CTRL register handshake setup + * They are used on the following registers: + * DCPCTRL and PIPECTRL(1-6) + */ +#define PIPE_SHAKE_NAK 0x00 +#define PIPE_SHAKE_BUF 0x01 +#define PIPE_SHAKE_STALL 0x02 + +/* These defines are used for the control transfer stage status */ +#define CTRL_IDLE 0x00 /* Idle Stage */ +#define CTRL_RTDS 0x01 /* Read transfer data stage */ +#define CTRL_RTSS 0x02 /* Read transfer status stage */ +#define CTRL_WTDS 0x03 /* Write transfer data stage */ +#define CTRL_WTSS 0x04 /* Write transfer status stage */ +#define CTRL_WTND 0x05 /* Write transfer no data stage */ +#define CTRL_TRER 0x06 /* Transmit error stage */ + 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 . += TTB_SIZE; } > DRAM + /* The LCD buffer should be at the end of memory to protect against + * overflowing something else when the YUV blitter is fudging the screen + * size. + */ + .lcdbuffer (NOLOAD) : { _lcdbuf = .; . += LCD_BUFFER_SIZE; } > DRAM + + .lcdbuffer2 (NOLOAD) : + { + _lcdbuf2 = .; + . += LCD_BUFFER_SIZE; + } > DRAM } 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: strhi r5, [r3], #4 bhi 1b #endif -#endif /* !BOOTLOADER,!STUB */ +#endif /* !STUB */ /* Initialise bss section to zero */ @@ -113,26 +113,6 @@ stackmunge: /* Switch to supervisor mode (no IRQ) */ msr cpsr_c, #0xd3 ldr sp, =stackend - -#if defined(BOOTLOADER) && !defined(CREATIVE_ZVx) - /* get the high part of our execute address */ - ldr r2, =0xffffff00 - and r4, pc, r2 - - /* Copy bootloader to safe area - 0x01900000 */ - mov r5, #0x01900000 - ldr r6, = _dataend - sub r0, r6, r5 /* length of loader */ - add r0, r4, r0 /* r0 points to start of loader */ -1: - cmp r5, r6 - ldrcc r2, [r4], #4 - strcc r2, [r5], #4 - bcc 1b - - ldr pc, =start_loc /* jump to the relocated start_loc: */ - -#endif start_loc: 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 @@ #include "tsc2100.h" #include "kernel.h" -unsigned short current_bat2 = 3910; -unsigned short current_aux = 3910; -static unsigned short current_voltage = 3910; +unsigned short current_bat2 = 4200; +unsigned short current_aux = 4200; +static unsigned short current_voltage = 4200; const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = { 3450 @@ -69,7 +69,7 @@ unsigned int battery_adc_voltage(void) current_aux=((short)((int)(aux<<10)/4096*6*2.5)); } - if (TIME_BEFORE(last_tick+2*HZ, current_tick)) + if (TIME_BEFORE(last_tick+2*HZ, current_tick) || last_tick==0) { tsadc=tsc2100_readreg(TSADC_PAGE, TSADC_ADDRESS); 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 @@ * \/ \/ \/ \/ \/ * $Id$ * - * Copyright (C) 2007 by Karl Kurbjun + * Copyright (C) 2007, 2009 by Karl Kurbjun * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -18,42 +18,60 @@ * KIND, either express or implied. * ****************************************************************************/ +#define LOGF_ENABLE #include "config.h" +#include "logf.h" #include "cpu.h" #include "system.h" -#include "kernel.h" -#include "ata.h" -#include "usb.h" -#include "usb-target.h" -#define USB_RST_ASSERT -#define USB_RST_DEASSERT +#include "m66591.h" -#define USB_VPLUS_PWR_ASSERT -#define USB_VPLUS_PWR_DEASSERT +void usb_init_device(void) { + logf("mxx: SOC Init"); -#define USB_UNIT_IS_PRESENT USB_EXTRACTED + /* The EMIF timing that is currently used may not be apropriate when the + * device is boosted. The following values were used with sucess too: + * IO_EMIF_CS4CTRL1 = 0x66AB; + * IO_EMIF_CS4CTRL2 = 0x4220; + */ + IO_EMIF_CS4CTRL1 = 0x2245; + IO_EMIF_CS4CTRL2 = 0x4110; -/* The usb detect is one pin to the cpu active low */ -inline int usb_detect(void) -{ - return USB_UNIT_IS_PRESENT; -} + IO_GIO_DIR0 &= ~(1<<2); + IO_GIO_INV0 &= ~(1<<2); + IO_GIO_FSEL0 &= ~(0x03); + + /* Drive the reset pin low */ + IO_GIO_BITCLR0 = 1<<2; + + /* Wait a bit */ + udelay(3); -void usb_init_device(void) -{ -// ata_enable(true); + /* Release the reset (drive it high) */ + IO_GIO_BITSET0 = 1<<2; + + udelay(300); + + IO_GIO_DIR0 |= 1<<3; + IO_GIO_INV0 &= ~(1<<3); + IO_GIO_IRQPORT |= 1<<3; + + /* Enable the MXX interrupt */ + IO_INTC_EINT1 |= (1<<8); /* IRQ_GIO3 */ } -void usb_enable(bool on) -{ - if (on) - { - USB_VPLUS_PWR_ASSERT; - } - else - { - USB_VPLUS_PWR_DEASSERT; - } +/* This is the initial interupt handler routine for the USB controller */ +void GIO3 (void) { + /* Clear the interrupt, this is critical to do before running the full + * handler otherwise you might miss an interrupt and everything will stop + * working. + * + * The M66591 interrupt line is attached to GPIO3. + */ + IO_INTC_IRQ1 = (1<<8); + + /* Start the full handler which is located in the driver */ + USB_DEVICE(); } + 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 @@ #include "spi.h" #ifdef CREATIVE_ZVx #include "dma-target.h" +#include "usb-mr500.h" #endif #define default_interrupt(name) \ @@ -308,3 +309,14 @@ void set_cpu_frequency(long frequency) } #endif +/* This function is pretty crude. It is not acurate to a usec, but errors on + * longer. + */ +void udelay(int usec) { + volatile int temp=usec*(175000/200); + + while(temp) { + temp--; + } +} + 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 @@ #define CPUFREQ_NORMAL 87500000 #define CPUFREQ_MAX 175000000 +void udelay(int usec); + #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 @@ /* Conditions under which we want the entire driver */ #if !defined(BOOTLOADER) || (CONFIG_CPU == SH7034) || \ (defined(TOSHIBA_GIGABEAT_S) && defined(USE_ROCKBOX_USB) && defined(USB_ENABLE_STORAGE)) || \ - (defined(HAVE_USBSTACK) && (defined(CREATIVE_ZVx) || \ + (defined(HAVE_USBSTACK) && (defined(CREATIVE_ZVx)) || \ + (defined(HAVE_USBSTACK) && (defined(OLYMPUS_MROBE_500)) || \ defined(CPU_TCC77X) || defined(CPU_TCC780X))) || \ (CONFIG_USBOTG == USBOTG_JZ4740) #define USB_FULL_INIT -- cgit v1.2.3