From a119c44c7ec7a383dafbb391f052aaade0b6c981 Mon Sep 17 00:00:00 2001 From: Maurus Cuelenaere Date: Thu, 4 Dec 2008 18:26:19 +0000 Subject: Ingenic targets: * Clean up codec & PCM + functional changes * LCD: Don't wait on DMAC in lcd_unlock() * SADC: add battery mutex + other changes * NAND: add mutex * USB rework (still not working) git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19327 a1c6a512-1295-4272-9138-f99709370657 --- firmware/export/jz4740.h | 32 +- .../target/mips/ingenic_jz47xx/ata-nand-jz4740.c | 12 + firmware/target/mips/ingenic_jz47xx/codec-jz4740.c | 60 +- firmware/target/mips/ingenic_jz47xx/lcd-jz4740.c | 32 +- .../ingenic_jz47xx/onda_vx747/sadc-onda_vx747.c | 55 +- .../mips/ingenic_jz47xx/onda_vx747/usb-target.h | 20 +- firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c | 47 +- .../target/mips/ingenic_jz47xx/system-jz4740.c | 2 +- .../target/mips/ingenic_jz47xx/system-target.h | 3 + firmware/target/mips/ingenic_jz47xx/usb-jz4740.c | 1267 +++----------------- 10 files changed, 354 insertions(+), 1176 deletions(-) diff --git a/firmware/export/jz4740.h b/firmware/export/jz4740.h index 55c0ac7b1d..505248a67a 100644 --- a/firmware/export/jz4740.h +++ b/firmware/export/jz4740.h @@ -2339,6 +2339,7 @@ #define USB_REG_TESTMODE (USB_BASE + 0x0f) /* USB test mode 8-bit */ #define USB_REG_CSR0 (USB_BASE + 0x12) /* EP0 CSR 8-bit */ +#define USB_REG_COUNT0 (USB_BASE + 0x18) /* bytes in EP0 FIFO 16-bit */ #define USB_REG_INMAXP (USB_BASE + 0x10) /* EP1-2 IN Max Pkt Size 16-bit */ #define USB_REG_INCSR (USB_BASE + 0x12) /* EP1-2 IN CSR LSB 8/16bit */ #define USB_REG_INCSRH (USB_BASE + 0x13) /* EP1-2 IN CSR MSB 8-bit */ @@ -2375,6 +2376,7 @@ #define REG_USB_REG_TESTMODE REG8(USB_REG_TESTMODE) #define REG_USB_REG_CSR0 REG8(USB_REG_CSR0) +#define REG_USB_REG_COUNT0 REG16(USB_REG_COUNT0) #define REG_USB_REG_INMAXP REG16(USB_REG_INMAXP) #define REG_USB_REG_INCSR REG16(USB_REG_INCSR) #define REG_USB_REG_INCSRH REG8(USB_REG_INCSRH) @@ -2395,6 +2397,9 @@ #define REG_USB_REG_ADDR2 REG32(USB_REG_ADDR2) #define REG_USB_REG_COUNT2 REG32(USB_REG_COUNT2) +#define REG_USB_REG_EPINFO REG16(USB_REG_EPINFO) +#define REG_USB_REG_RAMINFO REG8(USB_REG_RAMINFO) + /* Power register bit masks */ #define USB_POWER_SUSPENDM 0x01 @@ -2414,6 +2419,8 @@ #define USB_INTR_OUTEP1 0x0002 #define USB_INTR_OUTEP2 0x0004 +#define USB_INTR_EP(n) (n*2) + /* CSR0 bit masks */ #define USB_CSR0_OUTPKTRDY 0x01 #define USB_CSR0_INPKTRDY 0x02 @@ -2425,11 +2432,11 @@ #define USB_CSR0_SVDSETUPEND 0x80 /* Endpoint CSR register bits */ -#define USB_INCSRH_AUTOSET 0x80 -#define USB_INCSRH_ISO 0x40 -#define USB_INCSRH_MODE 0x20 -#define USB_INCSRH_DMAREQENAB 0x10 -#define USB_INCSRH_DMAREQMODE 0x04 +#define USB_INCSRH_AUTOSET 0x8000 +#define USB_INCSRH_ISO 0x4000 +#define USB_INCSRH_MODE 0x2000 +#define USB_INCSRH_DMAREQENAB 0x1000 +#define USB_INCSRH_DMAREQMODE 0x0400 #define USB_INCSR_CDT 0x40 #define USB_INCSR_SENTSTALL 0x20 #define USB_INCSR_SENDSTALL 0x10 @@ -2437,11 +2444,11 @@ #define USB_INCSR_UNDERRUN 0x04 #define USB_INCSR_FFNOTEMPT 0x02 #define USB_INCSR_INPKTRDY 0x01 -#define USB_OUTCSRH_AUTOCLR 0x80 -#define USB_OUTCSRH_ISO 0x40 -#define USB_OUTCSRH_DMAREQENAB 0x20 -#define USB_OUTCSRH_DNYT 0x10 -#define USB_OUTCSRH_DMAREQMODE 0x08 +#define USB_OUTCSRH_AUTOCLR 0x8000 +#define USB_OUTCSRH_ISO 0x4000 +#define USB_OUTCSRH_DMAREQENAB 0x2000 +#define USB_OUTCSRH_DNYT 0x1000 +#define USB_OUTCSRH_DMAREQMODE 0x0800 #define USB_OUTCSR_CDT 0x80 #define USB_OUTCSR_SENTSTALL 0x40 #define USB_OUTCSR_SENDSTALL 0x20 @@ -2456,6 +2463,11 @@ #define USB_TEST_J 0x02 #define USB_TEST_K 0x04 #define USB_TEST_PACKET 0x08 +#define USB_TEST_FORCE_HS 0x10 +#define USB_TEST_FORCE_FS 0x20 +#define USB_TEST_ALL ( USB_TEST_SE0NAK | USB_TEST_J \ + | USB_TEST_K | USB_TEST_PACKET \ + | USB_TEST_FORCE_HS | USB_TEST_FORCE_FS) /* DMA control bits */ #define USB_CNTL_ENA 0x01 diff --git a/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c b/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c index 7a937bf7cf..979a9067d3 100644 --- a/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c @@ -26,6 +26,7 @@ #include "nand_id.h" #include "system.h" #include "panic.h" +#include "kernel.h" /* * Standard NAND flash commands @@ -104,6 +105,7 @@ struct nand_param static struct nand_info* chip_info = NULL; static struct nand_param internal_param; +static struct mutex nand_mtx; static inline void jz_nand_wait_ready(void) { @@ -132,6 +134,8 @@ static inline void jz_nand_read_buf8(void *buf, int count) static void jz_nand_write_dma(void *source, unsigned int len, int bw) { + mutex_lock(&nand_mtx); + if(((unsigned int)source < 0xa0000000) && len) dma_cache_wback_inv((unsigned long)source, len); @@ -146,10 +150,14 @@ static void jz_nand_write_dma(void *source, unsigned int len, int bw) REG_DMAC_DCCSR(DMA_NAND_CHANNEL) = (DMAC_DCCSR_EN | DMAC_DCCSR_NDES); while( REG_DMAC_DTCR(DMA_NAND_CHANNEL) ) yield(); + + mutex_unlock(&nand_mtx); } static void jz_nand_read_dma(void *target, unsigned int len, int bw) { + mutex_lock(&nand_mtx); + if(((unsigned int)target < 0xa0000000) && len) dma_cache_wback_inv((unsigned long)target, len); @@ -163,6 +171,8 @@ static void jz_nand_read_dma(void *target, unsigned int len, int bw) REG_DMAC_DCCSR(DMA_NAND_CHANNEL) = (DMAC_DCCSR_EN | DMAC_DCCSR_NDES); while( REG_DMAC_DTCR(DMA_NAND_CHANNEL) ) yield(); + + mutex_unlock(&nand_mtx); } static inline void jz_nand_read_buf(void *buf, int count, int bw) @@ -433,6 +443,8 @@ static int jz_nand_init(void) internal_param.oob_size = chip_info->page_size/32; internal_param.page_per_block = chip_info->pages_per_block; + mutex_init(&nand_mtx); + return 0; } diff --git a/firmware/target/mips/ingenic_jz47xx/codec-jz4740.c b/firmware/target/mips/ingenic_jz47xx/codec-jz4740.c index 6c3ed8cf2a..dec343a0da 100644 --- a/firmware/target/mips/ingenic_jz47xx/codec-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/codec-jz4740.c @@ -21,6 +21,7 @@ #include "config.h" #include "jz4740.h" +#include "system.h" static unsigned short codec_volume; static unsigned short codec_base_gain; @@ -29,6 +30,8 @@ static bool HP_on_off_flag; static int HP_register_value; static int IS_WRITE_PCM; +static void i2s_codec_set_samplerate(unsigned short rate); + static void i2s_codec_clear(void) { REG_ICDC_CDCCR1 = (ICDC_CDCCR1_SW2ON | ICDC_CDCCR1_PDVR | ICDC_CDCCR1_PDVRA | ICDC_CDCCR1_VRCGL | @@ -38,11 +41,11 @@ static void i2s_codec_clear(void) static void i2s_codec_init(void) { + __aic_enable(); + __aic_select_i2s(); __i2s_internal_codec(); - __aic_enable(); - __i2s_set_oss_sample_size(16); REG_ICDC_CDCCR1 = (ICDC_CDCCR1_SW2ON | ICDC_CDCCR1_PDVR | ICDC_CDCCR1_PDVRA | ICDC_CDCCR1_VRCGL | @@ -55,14 +58,32 @@ static void i2s_codec_init(void) //REG_ICDC_CDCCR2 = (ICDC_CDCCR2_AINVOL(ICDC_CDCCR2_AINVOL_DB(0)) | ICDC_CDCCR2_SMPR(ICDC_CDCCR2_SMPR_48) | REG_ICDC_CDCCR2 = (ICDC_CDCCR2_AINVOL(23) | ICDC_CDCCR2_SMPR(ICDC_CDCCR2_SMPR_48) | ICDC_CDCCR2_HPVOL(ICDC_CDCCR2_HPVOL_6)); + + REG_ICDC_CDCCR1 &= 0xfffffffc; + + mdelay(15); + REG_ICDC_CDCCR1 &= 0xffecffff; + REG_ICDC_CDCCR1 |= (ICDC_CDCCR1_EDAC | ICDC_CDCCR1_HPCG); + + mdelay(600); + REG_ICDC_CDCCR1 &= 0xfff7ecff; + + mdelay(2); + + /* CDCCR1.ELININ=0, CDCCR1.EMIC=0, CDCCR1.EADC=0, CDCCR1.SW1ON=0, CDCCR1.EDAC=1, CDCCR1.SW2ON=1, CDCCR1.HPMUTE=0 */ + REG_ICDC_CDCCR1 = (REG_ICDC_CDCCR1 & ~((1 << 29) | (1 << 28) | (1 << 26) | (1 << 27) | (1 << 14))) | ((1 << 24) | (1 << 25)); + + REG_ICDC_CDCCR2 = ((REG_ICDC_CDCCR2 & ~(0x3)) | 3); + + i2s_codec_set_samplerate(44100); + HP_on_off_flag = 0; /* HP is off */ } static void i2s_codec_set_mic(unsigned short v) /* 0 <= v <= 100 */ { - v = v & 0xff; - if(v < 0) - v = 0; + v &= 0xff; + if(v > 100) v = 100; codec_mic_gain = 31 * v/100; @@ -72,9 +93,8 @@ static void i2s_codec_set_mic(unsigned short v) /* 0 <= v <= 100 */ static void i2s_codec_set_bass(unsigned short v) /* 0 <= v <= 100 */ { - v = v & 0xff; - if(v < 0) - v = 0; + v &= 0xff; + if(v > 100) v = 100; @@ -92,9 +112,8 @@ static void i2s_codec_set_bass(unsigned short v) /* 0 <= v <= 100 */ static void i2s_codec_set_volume(unsigned short v) /* 0 <= v <= 100 */ { - v = v & 0xff; - if(v < 0) - v = 0; + v &= 0xff; + if(v > 100) v = 100; @@ -114,6 +133,7 @@ static unsigned short i2s_codec_get_bass(void) { unsigned short val; int ret; + if(codec_base_gain == 0) val = 0; if(codec_base_gain == 1) @@ -124,7 +144,9 @@ static unsigned short i2s_codec_get_bass(void) val = 75; ret = val << 8; - val = val | ret; + val |= ret; + + return val; } static unsigned short i2s_codec_get_mic(void) @@ -133,7 +155,9 @@ static unsigned short i2s_codec_get_mic(void) int ret; val = 100 * codec_mic_gain / 31; ret = val << 8; - val = val | ret; + val |= ret; + + return val; } static unsigned short i2s_codec_get_volume(void) @@ -151,7 +175,8 @@ static unsigned short i2s_codec_get_volume(void) val = 75; ret = val << 8; - val = val | ret; + val |= ret; + return val; } @@ -271,10 +296,15 @@ void audiohw_mute(bool mute) void audiohw_preinit(void) { - i2s_reset(); + i2s_codec_init(); } void audiohw_postinit(void) { audiohw_mute(false); } + +void audiohw_init(void) +{ + +} diff --git a/firmware/target/mips/ingenic_jz47xx/lcd-jz4740.c b/firmware/target/mips/ingenic_jz47xx/lcd-jz4740.c index f45ffc0349..1401bf8a3f 100644 --- a/firmware/target/mips/ingenic_jz47xx/lcd-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/lcd-jz4740.c @@ -26,15 +26,14 @@ #include "system.h" #include "kernel.h" -static volatile bool _lcd_on = false; -static volatile bool lcd_poweroff = false; +static volatile bool lcd_is_on = false; static struct mutex lcd_mtx; /* LCD init */ void lcd_init_device(void) { lcd_init_controller(); - _lcd_on = true; + lcd_is_on = true; mutex_init(&lcd_mtx); } @@ -48,16 +47,16 @@ void lcd_enable(bool state) else lcd_off(); - _lcd_on = state; + lcd_is_on = state; } bool lcd_enabled(void) { - return _lcd_on; + return lcd_is_on; } /* Don't switch threads when in interrupt mode! */ -static void lcd_lock(void) +static inline void lcd_lock(void) { if(LIKELY(!in_interrupt_mode())) mutex_lock(&lcd_mtx); @@ -65,10 +64,19 @@ static void lcd_lock(void) while( !(REG_DMAC_DCCSR(DMA_LCD_CHANNEL) & DMAC_DCCSR_TT)); } -static void lcd_unlock(void) +static inline void lcd_unlock(void) { if(LIKELY(!in_interrupt_mode())) mutex_unlock(&lcd_mtx); +} + +static inline void lcd_wait(void) +{ + if(LIKELY(!in_interrupt_mode())) + { + while( !(REG_DMAC_DCCSR(DMA_LCD_CHANNEL) & DMAC_DCCSR_TT) ) + yield(); + } else while( !(REG_DMAC_DCCSR(DMA_LCD_CHANNEL) & DMAC_DCCSR_TT)); } @@ -98,13 +106,7 @@ void lcd_update_rect(int x, int y, int width, int height) REG_SLCD_CTRL |= SLCD_CTRL_DMA_EN; REG_DMAC_DCCSR(DMA_LCD_CHANNEL) |= DMAC_DCCSR_EN; - if(LIKELY(!in_interrupt_mode())) - { - while( !(REG_DMAC_DCCSR(DMA_LCD_CHANNEL) & DMAC_DCCSR_TT) ) - yield(); - } - else - while( !(REG_DMAC_DCCSR(DMA_LCD_CHANNEL) & DMAC_DCCSR_TT)); + lcd_wait(); REG_DMAC_DCCSR(DMA_LCD_CHANNEL) &= ~DMAC_DCCSR_EN; @@ -119,7 +121,7 @@ void lcd_update_rect(int x, int y, int width, int height) This must be called after all other LCD functions that change the display. */ void lcd_update(void) { - if (!_lcd_on) + if (!lcd_is_on) return; lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); diff --git a/firmware/target/mips/ingenic_jz47xx/onda_vx747/sadc-onda_vx747.c b/firmware/target/mips/ingenic_jz47xx/onda_vx747/sadc-onda_vx747.c index 64ea86135f..2624eb3d82 100644 --- a/firmware/target/mips/ingenic_jz47xx/onda_vx747/sadc-onda_vx747.c +++ b/firmware/target/mips/ingenic_jz47xx/onda_vx747/sadc-onda_vx747.c @@ -25,6 +25,7 @@ #include "button.h" #include "button-target.h" #include "powermgmt.h" +#include "kernel.h" #define BTN_OFF (1 << 29) #define BTN_VOL_DOWN (1 << 27) @@ -36,21 +37,22 @@ #define TS_AD_COUNT 5 -#define M_SADC_CFG_SNUM ((TS_AD_COUNT - 1) << SADC_CFG_SNUM_BIT) +#define SADC_CFG_SNUM ((TS_AD_COUNT - 1) << SADC_CFG_SNUM_BIT) #define SADC_CFG_INIT ( \ (2 << SADC_CFG_CLKOUT_NUM_BIT) | \ SADC_CFG_XYZ1Z2 | \ - M_SADC_CFG_SNUM | \ + SADC_CFG_SNUM | \ (2 << SADC_CFG_CLKDIV_BIT) | \ SADC_CFG_PBAT_HIGH | \ SADC_CFG_CMD_INT_PEN \ ) -static short x_pos = -1, y_pos = -1, datacount = 0; +static signed int x_pos, y_pos; +static int datacount = 0, cur_touch = 0; static bool pen_down = false; -static int cur_touch = 0; -static unsigned short bat_val = 0; +static volatile unsigned short bat_val = 0; +static struct mutex battery_mtx; static enum touchscreen_mode current_mode = TOUCHSCREEN_POINT; static const int touchscreen_buttons[3][3] = @@ -93,15 +95,21 @@ const unsigned short percent_to_volt_charge[11] = unsigned int battery_adc_voltage(void) { register unsigned short dummy; + + mutex_lock(&battery_mtx); + dummy = REG_SADC_BATDAT; dummy = REG_SADC_BATDAT; bat_val = 0; REG_SADC_ENA |= SADC_ENA_PBATEN; + /* Primitive wakeup event */ while(bat_val == 0) yield(); + mutex_unlock(&battery_mtx); + return (bat_val*BATTERY_SCALE_FACTOR)>>12; } @@ -127,6 +135,8 @@ void button_init_device(void) __gpio_as_input(32*3 + 16); __gpio_as_input(32*3 + 1); __gpio_as_input(32*3 + 0); + + mutex_init(&battery_mtx); } static int touch_to_pixels(short x, short y) @@ -162,6 +172,7 @@ int button_read_device(int *data) { int ret = 0, tmp; + /* Filter button events out if HOLD button is pressed at firmware/ level */ if((~REG_GPIO_PXPIN(3)) & BTN_HOLD) return 0; @@ -186,7 +197,7 @@ int button_read_device(int *data) else if(pen_down) { ret |= BUTTON_TOUCH; - if(data != NULL) + if(data != NULL && cur_touch != 0) *data = cur_touch; } @@ -226,18 +237,16 @@ void SADC(void) REG_SADC_CTRL &= (~SADC_CTRL_PENDM ); REG_SADC_CTRL |= SADC_CTRL_PENUM; pen_down = false; - x_pos = -1; - y_pos = -1; + datacount = 0; cur_touch = 0; } if(state & SADC_CTRL_TSRDYM) { unsigned int dat; unsigned short xData, yData; - short tsz1Data, tsz2Data; + signed short tsz1Data, tsz2Data; dat = REG_SADC_TSDAT; - xData = (dat >> 0) & 0xFFF; yData = (dat >> 16) & 0xFFF; @@ -245,34 +254,30 @@ void SADC(void) tsz1Data = (dat >> 0) & 0xFFF; tsz2Data = (dat >> 16) & 0xFFF; - if( !pen_down ) + if(!pen_down) return; tsz1Data = tsz2Data - tsz1Data; - if((tsz1Data > 15) || (tsz1Data < -15)) + if((tsz1Data > 100) || (tsz1Data < -100)) { - if(x_pos == -1) + if(datacount == 0) + { x_pos = xData; - else - x_pos = (x_pos + xData) / 2; - - if(y_pos == -1) y_pos = yData; + } else - y_pos = (y_pos + yData) / 2; + { + x_pos += xData; + y_pos += yData; + } } datacount++; - if(datacount > TS_AD_COUNT - 1) + if(datacount >= TS_AD_COUNT) { - if(x_pos != -1) - { - cur_touch = touch_to_pixels(x_pos, y_pos); - x_pos = -1; - y_pos = -1; - } + cur_touch = touch_to_pixels(x_pos/datacount, y_pos/datacount); datacount = 0; } } diff --git a/firmware/target/mips/ingenic_jz47xx/onda_vx747/usb-target.h b/firmware/target/mips/ingenic_jz47xx/onda_vx747/usb-target.h index c681bdaa12..09b563fd14 100644 --- a/firmware/target/mips/ingenic_jz47xx/onda_vx747/usb-target.h +++ b/firmware/target/mips/ingenic_jz47xx/onda_vx747/usb-target.h @@ -24,23 +24,19 @@ #include "config.h" -#define __gpio_as_usb_detect() \ -do { \ - REG_GPIO_PXFUNS(3) = 0x10000000; \ - REG_GPIO_PXSELS(3) = 0x10000000; \ - REG_GPIO_PXPES(3) = 0x10000000; \ -} while (0) - #define GPIO_UDC_DETE (32 * 3 + 28) #define IRQ_GPIO_UDC_DETE (IRQ_GPIO_0 + GPIO_UDC_DETE) -static inline void usb_init_gpio(void) -{ - __gpio_as_usb_detect(); - system_enable_irq(IRQ_UDC); - __gpio_as_input(GPIO_UDC_DETE); +#define USB_INIT_GPIO() \ +{ \ + REG_GPIO_PXFUNS(3) = 0x10000000; \ + REG_GPIO_PXSELS(3) = 0x10000000; \ + REG_GPIO_PXPES(3) = 0x10000000; \ + __gpio_as_input(GPIO_UDC_DETE); \ } +#define USB_DRV_CONNECTED() (__gpio_get_pin(GPIO_UDC_DETE) == 1) + int usb_detect(void); void usb_init_device(void); bool usb_drv_connected(void); diff --git a/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c b/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c index 0343723493..5549ce4dbf 100644 --- a/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c @@ -27,13 +27,14 @@ #include "pcm.h" #include "jz4740.h" + /**************************************************************************** ** Playback DMA transfer **/ void pcm_postinit(void) { - audiohw_postinit(); /* implemented not for all codecs */ + audiohw_postinit(); pcm_apply_settings(); } @@ -61,29 +62,55 @@ void pcm_set_frequency(unsigned int frequency) { (void) frequency; /* TODO */ + + /* + __i2s_set_oss_sample_size(frequency); + i2s_codec_set_samplerate(frequency); + */ } static void play_start_pcm(void) { pcm_apply_settings(); - - /* TODO */ + + __aic_enable_transmit_dma(); + __aic_enable_replay(); + + REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) |= DMAC_DCCSR_EN; } static void play_stop_pcm(void) { - /* TODO */ + REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) = (REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) | DMAC_DCCSR_HLT) & ~DMAC_DCCSR_EN; + + __aic_disable_transmit_dma(); + __aic_disable_replay(); } void pcm_play_dma_start(const void *addr, size_t size) { - (void)addr; - (void)size; - /* TODO */ + REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) = 0; + REG_DMAC_DSAR(DMA_AIC_TX_CHANNEL) = PHYSADDR((unsigned long)addr); + REG_DMAC_DTAR(DMA_AIC_TX_CHANNEL) = PHYSADDR((unsigned long)AIC_DR); + REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL) = size; + REG_DMAC_DRSR(DMA_AIC_TX_CHANNEL) = DMAC_DRSR_RS_AICOUT; + REG_DMAC_DCMD(DMA_AIC_TX_CHANNEL) = ( DMAC_DCMD_SAI| DMAC_DCMD_DAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DS_32BIT | DMAC_DCMD_DWDH_32 + | DMAC_DCMD_TIE); play_start_pcm(); } +void DMA_CALLBACK(DMA_AIC_TX_CHANNEL)(void) +{ + if( REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) & DMAC_DCCSR_TT ) + __aic_disable_transmit_dma(); +} + +size_t pcm_get_bytes_waiting(void) +{ + return REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL); +} + void pcm_play_dma_stop(void) { play_stop_pcm(); @@ -110,12 +137,6 @@ void pcm_play_dma_pause(bool pause) } -size_t pcm_get_bytes_waiting(void) -{ - /* TODO */ - return 0; -} - #ifdef HAVE_RECORDING /* TODO */ void pcm_rec_dma_init(void) diff --git a/firmware/target/mips/ingenic_jz47xx/system-jz4740.c b/firmware/target/mips/ingenic_jz47xx/system-jz4740.c index 10741024a9..f733582d70 100644 --- a/firmware/target/mips/ingenic_jz47xx/system-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/system-jz4740.c @@ -372,7 +372,7 @@ static char* parse_exception(unsigned int cause) } void exception_handler(void* stack_ptr, unsigned int cause, unsigned int epc) -{ +{ panicf("Exception occurred: %s [0x%08x] at 0x%08x (stack at 0x%08x)", parse_exception(cause), cause, epc, (unsigned int)stack_ptr); } diff --git a/firmware/target/mips/ingenic_jz47xx/system-target.h b/firmware/target/mips/ingenic_jz47xx/system-target.h index 6ab5d02135..a8133140fa 100644 --- a/firmware/target/mips/ingenic_jz47xx/system-target.h +++ b/firmware/target/mips/ingenic_jz47xx/system-target.h @@ -108,4 +108,7 @@ bool in_interrupt_mode(void); #define DMA_USB_CHANNEL 2 #define DMA_AIC_TX_CHANNEL 3 +#define XDMA_CALLBACK(n) DMA ## n +#define DMA_CALLBACK(n) XDMA_CALLBACK(n) + #endif /* __SYSTEM_TARGET_H_ */ diff --git a/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c index f0b4eb4694..83dedfdd48 100644 --- a/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c @@ -20,7 +20,6 @@ ****************************************************************************/ #include "config.h" -#include "string.h" #include "system.h" #include "usb_ch9.h" #include "usb_drv.h" @@ -29,16 +28,18 @@ #include "jz4740.h" #include "thread.h" -#if 1 +//#define DEBUGF printf +#define DEBUGF -#define EP1_INTR_BIT 2 -#define EP_FIFO_NOEMPTY 2 +#define USB_EP0_IDLE 0 +#define USB_EP0_RX 1 +#define USB_EP0_TX 2 -#define IS_CACHE(x) (x < 0xa0000000) - -#define USB_EP0_IDLE 0 -#define USB_EP0_RX 1 -#define USB_EP0_TX 2 +#define EP_BUF_LEFT(ep) (ep->length - ep->sent) +#define EP_PTR(ep) ((void*)((unsigned int)ep->buf + ep->sent)) +#define EP_NUMBER(ep) (((int)ep - (int)&endpoints[0])/sizeof(struct usb_endpoint)) +#define TOTAL_EP() (sizeof(endpoints)/sizeof(struct usb_endpoint)) +#define EP_IS_IN(ep) (EP_NUMBER(ep)%2) enum ep_type { @@ -49,27 +50,29 @@ struct usb_endpoint { void *buf; unsigned int length; - void *ptr; + union + { + unsigned int sent; + unsigned int received; + }; const enum ep_type type; const bool use_dma; - const bool in; - const void *fifo_addr; + const unsigned int fifo_addr; unsigned short fifo_size; }; static unsigned char ep0_rx_buf[64]; -static unsigned char ep0_tx_buf[64]; static unsigned char ep0state = USB_EP0_IDLE; static struct usb_endpoint endpoints[] = { - /* buf length ptr type use_dma in fifo_addr fifo_size */ - {&ep0_rx_buf, 0, &ep0_rx_buf, ep_control, false, true, (void*)USB_FIFO_EP0, 64 }, - {&ep0_tx_buf, 0, &ep0_tx_buf, ep_control, false, false, (void*)USB_FIFO_EP0, 64 }, - {NULL, 0, NULL, ep_bulk, true, true, (void*)USB_FIFO_EP1, 512}, - {NULL, 0, NULL, ep_bulk, true, false, (void*)USB_FIFO_EP1, 512}, - {NULL, 0, NULL, ep_interrupt, false, true, (void*)USB_FIFO_EP2, 64 } + /* buf length sent type use_dma fifo_addr fifo_size */ + {&ep0_rx_buf, 0, {0}, ep_control, false, USB_FIFO_EP0, 64 }, + {NULL, 0, {0}, ep_control, false, USB_FIFO_EP0, 64 }, + {NULL, 0, {0}, ep_bulk, true, USB_FIFO_EP1, 512}, + {NULL, 0, {0}, ep_bulk, true, USB_FIFO_EP1, 512}, + {NULL, 0, {0}, ep_interrupt, false, USB_FIFO_EP2, 64 } }; static inline void select_endpoint(int ep) @@ -78,103 +81,109 @@ static inline void select_endpoint(int ep) } static void readFIFO(struct usb_endpoint *ep, unsigned int size) -{ - unsigned int *d = (unsigned int *)ep->ptr; - unsigned int s; - s = (size + 3) >> 2; - while (s--) - *d++ = REG32(ep->fifo_addr); +{ + DEBUGF("readFIFO(EP%d, %d)", EP_NUMBER(ep), size); + + register unsigned char *ptr = (unsigned char*)EP_PTR(ep); + register unsigned int *ptr32 = (unsigned int*)ptr; + register unsigned int s = size / 4; + register unsigned int x; + + if(size > 0) + { + if( ((int)ptr & 3) == 0 ) + { + while(s--) + *ptr32++ = REG32(ep->fifo_addr); + + ptr = (unsigned char*)ptr32; + } + else + { + while(s--) + { + x = REG32(ep->fifo_addr); + *ptr++ = (x >> 0) & 0xff; + *ptr++ = (x >> 8) & 0xff; + *ptr++ = (x >> 16) & 0xff; + *ptr++ = (x >> 24) & 0xff; + } + } + + s = size & 3; + while(s--) + *ptr++ = REG8(ep->fifo_addr); + } } static void writeFIFO(struct usb_endpoint *ep, unsigned int size) -{ - unsigned int *d = (unsigned int *)ep->ptr; - unsigned char *c; - int s, q; +{ + DEBUGF("writeFIFO(EP%d, %d)", EP_NUMBER(ep), size); + + register unsigned int *d = (unsigned int *)EP_PTR(ep); + register unsigned char *c; + register int s; if (size > 0) { s = size >> 2; while (s--) REG32(ep->fifo_addr) = *d++; - - q = size & 3; - if (q) + + if ( (s = size & 3) ) { c = (unsigned char *)d; - while (q--) + while (s--) REG8(ep->fifo_addr) = *c++; } - } -} - -static void sendPKT(int ep_nr, const unsigned char* ptr, unsigned int size) -{ - struct usb_endpoint *ep = &endpoints[ep_nr]; - - if (ep_nr != 0) - { - ep->buf = (void*)ptr; - ep->ptr = (void*)ptr; - ep->length = size; - select_endpoint(ep_nr); - if (size <= ep->fifo_size) - { - writeFIFO(ep, size); - REG_USB_REG_INCSR |= USB_INCSR_INPKTRDY; - ep->ptr = ep->buf + size; - } - else - { - writeFIFO(ep, ep->fifo_size); - REG_USB_REG_INCSR |= USB_INCSR_INPKTRDY; - ep->ptr += ep->fifo_size; - } - } - else /* EP0 */ - { - ep->length = size; - ep->ptr = ep->buf; - memcpy(ep->buf, ptr, size); - ep0state = USB_EP0_TX; } } -static void getPKT(int ep_nr, const unsigned char *ptr, unsigned int size) +static void EP0_send(void) { - struct usb_endpoint *ep = &endpoints[ep_nr]; + register struct usb_endpoint* ep = &endpoints[1]; + register unsigned int length; - memcpy((void*)ptr, ep->ptr, size); - if (ep->length > size) - ep->length -= size; + if(ep->sent == 0) + length = (ep->length <= ep->fifo_size ? ep->length : ep->fifo_size); else + length = (EP_BUF_LEFT(ep) <= ep->fifo_size ? EP_BUF_LEFT(ep) : ep->fifo_size); + + writeFIFO(ep, length); + ep->sent += length; + + if(ep->sent >= ep->length) { - size = ep->length; - ep->length = 0; + REG_USB_REG_CSR0 |= (USB_CSR0_INPKTRDY | USB_CSR0_DATAEND); /* Set data end! */ + ep0state = USB_EP0_IDLE; } - - ep->ptr += size; + else + REG_USB_REG_CSR0 |= USB_CSR0_INPKTRDY; } static void EP0_handler(void) { - unsigned char csr0; + register unsigned char csr0; /* Read CSR0 */ select_endpoint(0); csr0 = REG_USB_REG_CSR0; - /* Check for SentStall - if sentstall is set, clear the sentstall bit + /* Check for SentStall: + This bit is set when a STALL handshake is transmitted. The CPU should clear this bit. */ if (csr0 & USB_CSR0_SENTSTALL) { - REG_USB_REG_CSR0 = csr0 & ~USB_CSR0_SENTSTALL; + REG_USB_REG_CSR0 &= ~USB_CSR0_SENTSTALL; ep0state = USB_EP0_IDLE; return; } - /* Check for SetupEnd */ + /* Check for SetupEnd: + This bit will be set when a control transaction ends before the DataEnd bit has been set. + An interrupt will be generated and the FIFO flushed at this time. + The bit is cleared by the CPU writing a 1 to the ServicedSetupEnd bit. + */ if (csr0 & USB_CSR0_SETUPEND) { REG_USB_REG_CSR0 |= USB_CSR0_SVDSETUPEND; @@ -187,38 +196,21 @@ static void EP0_handler(void) { if (csr0 & USB_CSR0_OUTPKTRDY) /* There is data in the fifo */ { - readFIFO(&endpoints[0], 8); - REG_USB_REG_CSR0 |= USB_CSR0_SVDOUTPKTRDY; /* clear OUTRD bit */ + readFIFO(&endpoints[0], REG_USB_REG_COUNT0); + REG_USB_REG_CSR0 |= USB_CSR0_SVDOUTPKTRDY; /* clear OUTPKTRDY bit */ usb_core_control_request((struct usb_ctrlrequest*)endpoints[0].buf); } - endpoints[0].length = 0; - endpoints[0].ptr = endpoints[0].buf; - } - - if (ep0state == USB_EP0_TX) - { - if ((&endpoints[1].ptr - &endpoints[1].buf) <= endpoints[1].fifo_size) - { - writeFIFO(&endpoints[1], (&endpoints[1].ptr - &endpoints[1].buf)); - endpoints[1].ptr = &endpoints[1].buf + endpoints[1].length; - REG_USB_REG_CSR0 |= (USB_CSR0_INPKTRDY | USB_CSR0_DATAEND); /* Set data end! */ - ep0state = USB_EP0_IDLE; - } - else - { - writeFIFO(&endpoints[1], endpoints[1].fifo_size); - REG_USB_REG_CSR0 |= USB_CSR0_INPKTRDY; - endpoints[1].ptr += endpoints[1].fifo_size; - } } + else if (ep0state == USB_EP0_TX) + EP0_send(); } static void setup_endpoint(struct usb_endpoint *ep) { - ep->ptr = ep->buf; + ep->sent = 0; ep->length = 0; - if(ep->in) + if(EP_IS_IN(ep)) { if(ep->type == ep_bulk) { @@ -235,53 +227,66 @@ static void setup_endpoint(struct usb_endpoint *ep) else REG_USB_REG_INMAXP = ep->fifo_size; - REG_USB_REG_INCSR = 0x2048; + REG_USB_REG_INCSR = (USB_INCSR_FF | USB_INCSR_CDT | USB_INCSRH_MODE); + REG_USB_REG_INTRINE |= USB_INTR_EP(EP_NUMBER(ep)); } else { REG_USB_REG_OUTMAXP = ep->fifo_size; - REG_USB_REG_OUTCSR = 0x0090; + REG_USB_REG_OUTCSR = (USB_OUTCSR_FF | USB_OUTCSR_CDT); + REG_USB_REG_INTROUTE |= USB_INTR_EP(EP_NUMBER(ep)); } } static void udc_reset(void) { - register int i; + DEBUGF("udc_reset"); + + register unsigned int i; /* data init */ ep0state = USB_EP0_IDLE; /* Disable interrupts */ - REG_USB_REG_INTRINE = 0; + REG_USB_REG_INTRINE = 0; REG_USB_REG_INTROUTE = 0; REG_USB_REG_INTRUSBE = 0; + /* Disable DMA */ + REG_USB_REG_CNTL1 = 0; + REG_USB_REG_CNTL2 = 0; + + /* Reset address */ REG_USB_REG_FADDR = 0; - REG_USB_REG_POWER = 0x60; /* High speed */ + //REG_USB_REG_POWER = (USB_POWER_SOFTCONN | USB_POWER_HSENAB); /* High speed and softconnect */ + REG_USB_REG_POWER = USB_POWER_SOFTCONN; + /* Enable SUSPEND */ + /* REG_USB_REG_POWER |= USB_POWER_SUSPENDM; */ select_endpoint(0); - REG_USB_REG_CSR0 = 0xC0; + REG_USB_REG_CSR0 = (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_SVDSETUPEND); - for(i=1; i<3; i++) + for(i=2; i> 4) & 0xF)); usb_core_transfer_complete(((REG_USB_REG_CNTL1 >> 4) & 0xF) | USB_DIR_IN, USB_DIR_IN, 0, 0); } if(intrDMA & USB_INTR_DMA_BULKOUT) { + DEBUGF("DMA_BULKOUT %d", ((REG_USB_REG_CNTL2 >> 4) & 0xF)); usb_core_transfer_complete(((REG_USB_REG_CNTL2 >> 4) & 0xF) | USB_DIR_OUT, USB_DIR_OUT, 0, 0); } } bool usb_drv_stalled(int endpoint, bool in) { + DEBUGF("usb_drv_stalled(%d, %s)", endpoint, in?"IN":"OUT"); + select_endpoint(endpoint); if(endpoint == 0) @@ -320,6 +329,8 @@ bool usb_drv_stalled(int endpoint, bool in) void usb_drv_stall(int endpoint, bool stall, bool in) { + DEBUGF("usb_drv_stall(%d,%s,%s)", endpoint, stall?"y":"n", in?"IN":"OUT"); + select_endpoint(endpoint); if(endpoint == 0) @@ -348,23 +359,20 @@ void usb_drv_stall(int endpoint, bool stall, bool in) } } - bool usb_drv_connected(void) { - return __gpio_get_pin(GPIO_UDC_DETE) == 1; + return USB_DRV_CONNECTED(); } int usb_detect(void) { - if(usb_drv_connected()) - return USB_INSERTED; - else - return USB_EXTRACTED; + return usb_drv_connected() ? USB_INSERTED : USB_EXTRACTED; } void usb_init_device(void) { - usb_init_gpio(); + USB_INIT_GPIO(); + system_enable_irq(IRQ_UDC); } void usb_enable(bool on) @@ -387,27 +395,6 @@ void usb_drv_init(void) /* Enable the USB PHY */ REG_CPM_SCR |= CPM_SCR_USBPHY_ENABLE; - - /* Disable interrupts */ - REG_USB_REG_INTRINE = 0; - REG_USB_REG_INTROUTE = 0; - REG_USB_REG_INTRUSBE = 0; - - /* Enable interrupts */ - REG_USB_REG_INTRINE |= USB_INTR_EP0; - REG_USB_REG_INTRUSBE |= USB_INTR_RESET; - - /* Enable SUSPEND */ - /* usb_setb(USB_REG_POWER, USB_POWER_SUSPENDM); */ - - /* Enable HS Mode */ - REG_USB_REG_POWER |= USB_POWER_HSENAB; - - /* Let host detect UDC: - * Software must write a 1 to the PMR:USB_POWER_SOFTCONN bit to turn this - * transistor on and pull the USBDP pin HIGH. - */ - REG_USB_REG_POWER |= USB_POWER_SOFTCONN; udc_reset(); } @@ -434,984 +421,94 @@ void usb_drv_exit(void) void usb_drv_set_address(int address) { + DEBUGF("set adr: 0x%x", address); + REG_USB_REG_FADDR = address; } int usb_drv_send(int endpoint, void* ptr, int length) { - return 0; -} - -int usb_drv_recv(int endpoint, void* ptr, int length) -{ - return 0; -} + DEBUGF("usb_drv_send(%d, 0x%x, %d)", endpoint, (int)ptr, length); -void usb_drv_set_test_mode(int mode) -{ - -} - -int usb_drv_port_speed(void) -{ - return ((REG_USB_REG_POWER & USB_POWER_HSMODE) != 0) ? 1 : 0; -} - -void usb_drv_cancel_all_transfers(void) -{ - int i; - for(i=0; i<5; i++) - { - endpoints[i].ptr = endpoints[i].buf; - endpoints[i].length = 0; - } -} - -void usb_drv_release_endpoint(int ep) -{ + if(endpoint == EP_CONTROL && ptr == NULL && length == 0) /* ACK request */ + return 0; -} - -#else - -//------------------------------------------ -#ifndef u8 -#define u8 unsigned char -#endif - -#ifndef u16 -#define u16 unsigned short -#endif - -#ifndef u32 -#define u32 unsigned int -#endif - -#ifndef s8 -#define s8 char -#endif - -#ifndef s16 -#define s16 short -#endif - -#ifndef s32 -#define s32 int -#endif - -extern int usbdebug; - -enum USB_ENDPOINT_TYPE -{ - ENDPOINT_TYPE_CONTROL, - /* Typically used to configure a device when attached to the host. - * It may also be used for other device specific purposes, including - * control of other pipes on the device. - */ - ENDPOINT_TYPE_ISOCHRONOUS, - /* Typically used for applications which need guaranteed speed. - * Isochronous transfer is fast but with possible data loss. A typical - * use is audio data which requires a constant data rate. - */ - ENDPOINT_TYPE_BULK, - /* Typically used by devices that generate or consume data in relatively - * large and bursty quantities. Bulk transfer has wide dynamic latitude - * in transmission constraints. It can use all remaining available bandwidth, - * but with no guarantees on bandwidth or latency. Since the USB bus is - * normally not very busy, there is typically 90% or more of the bandwidth - * available for USB transfers. - */ - ENDPOINT_TYPE_INTERRUPT - /* Typically used by devices that need guaranteed quick responses - * (bounded latency). - */ -}; - - -enum USB_STANDARD_REQUEST_CODE { - GET_STATUS, - CLEAR_FEATURE, - SET_FEATURE = 3, - SET_ADDRESS = 5, - GET_DESCRIPTOR, - SET_DESCRIPTOR, - GET_CONFIGURATION, - SET_CONFIGURATION, - GET_INTERFACE, - SET_INTERFACE, - SYNCH_FRAME -}; - - -enum USB_DESCRIPTOR_TYPE { - DEVICE_DESCRIPTOR = 1, - CONFIGURATION_DESCRIPTOR, - STRING_DESCRIPTOR, - INTERFACE_DESCRIPTOR, - ENDPOINT_DESCRIPTOR, - DEVICE_QUALIFIER_DESCRIPTOR, - OTHER_SPEED_CONFIGURATION_DESCRIPTOR, - INTERFACE_POWER1_DESCRIPTOR -}; - - -enum USB_FEATURE_SELECTOR { - ENDPOINT_HALT, - DEVICE_REMOTE_WAKEUP, - TEST_MODE -}; - -enum USB_CLASS_CODE { - CLASS_DEVICE, - CLASS_AUDIO, - CLASS_COMM_AND_CDC_CONTROL, - CLASS_HID, - CLASS_PHYSICAL = 0x05, - CLASS_STILL_IMAGING, - CLASS_PRINTER, - CLASS_MASS_STORAGE, - CLASS_HUB, - CLASS_CDC_DATA, - CLASS_SMART_CARD, - CLASS_CONTENT_SECURITY = 0x0d, - CLASS_VIDEO, - CLASS_DIAGNOSTIC_DEVICE = 0xdc, - CLASS_WIRELESS_CONTROLLER = 0xe0, - CLASS_MISCELLANEOUS = 0xef, - CLASS_APP_SPECIFIC = 0xfe, - CLASS_VENDOR_SPECIFIC = 0xff -}; - - -typedef struct { - u8 bmRequestType; - u8 bRequest; - u16 wValue; - u16 wIndex; - u16 wLength; -} __attribute__ ((packed)) USB_DeviceRequest; - - -typedef struct { - u8 bLength; - u8 bDescriptorType; - u16 bcdUSB; - u8 bDeviceClass; - u8 bDeviceSubClass; - u8 bDeviceProtocol; - u8 bMaxPacketSize0; - u16 idVendor; - u16 idProduct; - u16 bcdDevice; - u8 iManufacturer; - u8 iProduct; - u8 iSerialNumber; - u8 bNumConfigurations; -} __attribute__ ((packed)) USB_DeviceDescriptor; - - -typedef struct { - u8 bLength; - u8 bDescriptorType; - u16 bcdUSB; - u8 bDeviceClass; - u8 bDeviceSubClass; - u8 bDeviceProtocol; - u8 bMaxPacketSize0; - u8 bNumConfigurations; - u8 bReserved; -} __attribute__ ((packed)) USB_DeviceQualifierDescriptor; - - -typedef struct { - u8 bLength; - u8 bDescriptorType; - u16 wTotalLength; - u8 bNumInterfaces; - u8 bConfigurationValue; - u8 iConfiguration; - u8 bmAttributes; - u8 MaxPower; -} __attribute__ ((packed)) USB_ConfigDescriptor; - - -typedef struct { - u8 bLength; - u8 bDescriptorType; - u16 wTotalLength; - u8 bNumInterfaces; - u8 bConfigurationValue; - u8 iConfiguration; - u8 bmAttributes; - u8 bMaxPower; -} __attribute__ ((packed)) USB_OtherSpeedConfigDescriptor; - - -typedef struct { - u8 bLength; - u8 bDescriptorType; - u8 bInterfaceNumber; - u8 bAlternateSetting; - u8 bNumEndpoints; - u8 bInterfaceClass; - u8 bInterfaceSubClass; - u8 bInterfaceProtocol; - u8 iInterface; -} __attribute__ ((packed)) USB_InterfaceDescriptor; - - -typedef struct { - u8 bLegth; - u8 bDescriptorType; - u8 bEndpointAddress; - u8 bmAttributes; - u16 wMaxPacketSize; - u8 bInterval; -} __attribute__ ((packed)) USB_EndPointDescriptor; - - -typedef struct { - u8 bLength; - u8 bDescriptorType; - u16 SomeDesriptor[1]; -} __attribute__ ((packed)) USB_StringDescriptor; -//------------------------------------------ -#define MAX_EP0_SIZE 64 -#define MAX_EP1_SIZE 512 - -#define USB_HS 0 -#define USB_FS 1 -#define USB_LS 2 - -//definitions of EP0 -#define USB_EP0_IDLE 0 -#define USB_EP0_RX 1 -#define USB_EP0_TX 2 -/* Define maximum packet size for endpoint 0 */ -#define M_EP0_MAXP 64 -/* Endpoint 0 status structure */ - -static __inline__ void usb_setb(u32 port, u8 val) -{ - volatile u8 *ioport = (volatile u8 *)(port); - *ioport = (*ioport) | val; -} - -static __inline__ void usb_clearb(u32 port, u8 val) -{ - volatile u8 *ioport = (volatile u8 *)(port); - *ioport = (*ioport) & ~val; -} - -static __inline__ void usb_setw(u32 port, u16 val) -{ - volatile u16 *ioport = (volatile u16 *)(port); - *ioport = (*ioport) | val; -} - -static __inline__ void usb_clearw(u32 port, u16 val) -{ - volatile u16 *ioport = (volatile u16 *)(port); - *ioport = (*ioport) & ~val; -} -//--------------------------------- -#define BULK_OUT_BUF_SIZE 0x20000 //buffer size : -#define BULK_IN_BUF_SIZE 0x20000 // too - -enum UDC_STATE -{ - IDLE, - BULK_IN, - BULK_OUT -}; - -enum USB_JZ4740_REQUEST //add for USB_BOOT -{ - VR_GET_CUP_INFO = 0, - VR_SET_DATA_ADDERSS, - VR_SET_DATA_LENGTH, - VR_FLUSH_CACHES, - VR_PROGRAM_START1, - VR_PROGRAM_START2, - VR_NOR_OPS, - VR_NAND_OPS, - VR_SDRAM_OPS, - VR_CONFIGRATION -}; - -enum NOR_OPS_TYPE -{ - NOR_INIT = 0, - NOR_QUERY, - NOR_WRITE, - NOR_ERASE_CHIP, - NOR_ERASE_SECTOR -}; - -enum NOR_FLASH_TYPE -{ - NOR_AM29 = 0, - NOR_SST28, - NOR_SST39x16, - NOR_SST39x8 -}; - -enum NAND_OPS_TYPE -{ - NAND_QUERY = 0, - NAND_INIT, - NAND_MARK_BAD, - NAND_READ_OOB, - NAND_READ_RAW, - NAND_ERASE, - NAND_READ, - NAND_PROGRAM, - NAND_READ_TO_RAM -}; - -enum SDRAM_OPS_TYPE -{ - SDRAM_LOAD, - -}; - -enum DATA_STRUCTURE_OB -{ - DS_flash_info , - DS_hand -}; - - -/*typedef enum _USB_BOOT_STATUS -{ - USB_NO_ERR =0 , - GET_CPU_INFO_ERR, - SET_DATA_ADDRESS_ERR, - SET_DATA_LENGTH_ERR, - FLUSH_CAHCES_ERR, - PROGRAM_START1_ERR, - PROGRAM_START2_ERR, - NOR_OPS_ERR, - NAND_OPS_ERR, - NOR_FLASHTYPE_ERR, - OPS_NOTSUPPORT_ERR -}USB_BOOT_STATUS;*/ - -enum OPTION -{ - OOB_ECC, - OOB_NO_ECC, - NO_OOB, -}; -//------------------------- -static inline void jz_writeb(u32 address, u8 value) -{ - *((volatile u8 *)address) = value; -} - -static inline void jz_writew(u32 address, u16 value) -{ - *((volatile u16 *)address) = value; -} - -static inline void jz_writel(u32 address, u32 value) -{ - *((volatile u32 *)address) = value; -} - -static inline u8 jz_readb(u32 address) -{ - return *((volatile u8 *)address); -} - -static inline u16 jz_readw(u32 address) -{ - return *((volatile u16 *)address); -} - -static inline u32 jz_readl(u32 address) -{ - return *((volatile u32 *)address); -} -//--------------------------- - -#define TXFIFOEP0 USB_FIFO_EP0 - -u8 *Bulk_in_buf; -u32 Bulk_out_buf[BULK_OUT_BUF_SIZE]; -u32 Bulk_in_size,Bulk_in_finish,Bulk_out_size; -u16 handshake_PKT[4]={0,0,0,0}; -u8 udc_state; - -static u32 rx_buf[32]; -static u32 tx_buf[32]; -static u32 tx_size, rx_size, finished,fifo; -static u8 ep0state,USB_Version; - -static u32 fifoaddr[] = -{ - TXFIFOEP0, TXFIFOEP0+4 ,TXFIFOEP0+8 -}; - -static u32 fifosize[] = { - MAX_EP0_SIZE, MAX_EP1_SIZE -}; - -static void udcReadFifo(u8 *ptr, int size) -{ - u32 *d = (u32 *)ptr; - int s; - s = (size + 3) >> 2; - while (s--) - *d++ = REG32(fifo); -} - -static void udcWriteFifo(u8 *ptr, int size) -{ - u32 *d = (u32 *)ptr; - u8 *c; - int s, q; - - if (size > 0) { - s = size >> 2; - while (s--) - REG32(fifo) = *d++; - q = size & 3; - if (q) { - c = (u8 *)d; - while (q--) - REG8(fifo) = *c++; - } - } -} - -void HW_SendPKT(int ep, const u8 *buf, int size) -{ - fifo = fifoaddr[ep]; - - if (ep!=0) + if(endpoint == EP_CONTROL) { - Bulk_in_size = size; - Bulk_in_finish = 0; - jz_writeb(USB_REG_INDEX, ep); - if (Bulk_in_size - Bulk_in_finish <= fifosize[ep]) - { - udcWriteFifo((u8 *)((u32)buf+Bulk_in_finish), - Bulk_in_size - Bulk_in_finish); - usb_setb(USB_REG_INCSR, USB_INCSR_INPKTRDY); - Bulk_in_finish = Bulk_in_size; - } - else - { - udcWriteFifo((u8 *)((u32)buf+Bulk_in_finish), - fifosize[ep]); - usb_setb(USB_REG_INCSR, USB_INCSR_INPKTRDY); - Bulk_in_finish += fifosize[ep]; - Bulk_in_buf = (u8*)buf; - } - } - else //EP0 - { - tx_size = size; - finished = 0; - memcpy((void *)tx_buf, buf, size); - ep0state = USB_EP0_TX; + endpoints[1].buf = ptr; + endpoints[1].sent = 0; + endpoints[1].length = length; + ep0state = USB_EP0_TX; + EP0_send(); + return 0; } -} - -void HW_GetPKT(int ep, const u8 *buf, unsigned int size) -{ - memcpy((void *)buf, (u8 *)rx_buf, size); - fifo = fifoaddr[ep]; - if (rx_size > size) - rx_size -= size; else - { - size = rx_size; - rx_size = 0; - } - memcpy((u8 *)rx_buf, (u8 *)((u32)rx_buf+size), rx_size); -} - -void Enable_DMA(u8* buf, u32 length) -{ - dma_cache_wback_inv((u32)buf, length); - jz_writeb(USB_REG_INDEX, 1); - usb_setw(USB_REG_INCSR, 0x9400); - usb_clearw(USB_REG_INTRINE, 0x2); //disable OUT intr - jz_writel(USB_REG_ADDR1, (u32)buf); - jz_writel(USB_REG_COUNT1, length); - jz_writel(USB_REG_CNTL1, 0x001f); -} - -void Disable_DMA(void) -{ - jz_writeb(USB_REG_INDEX, 1); - usb_clearw(USB_REG_INCSR, 0x9400); - usb_setw(USB_REG_INTRINE, 0x2); //Enable OUT intr -} - -static USB_DeviceDescriptor devDesc = -{ - sizeof(USB_DeviceDescriptor), - DEVICE_DESCRIPTOR, //1 - 0x0200, //Version 2.0 - 0xff, //Vendor spec class - 0xff, - 0xff, - 64, /* Ep0 FIFO size */ - 0x601a, //vendor ID - 0xDEAD, //Product ID - 0xffff, - 0x00, - 0x00, - 0x00, - 0x01 -}; - -#define CONFIG_DESCRIPTOR_LEN (sizeof(USB_ConfigDescriptor) + \ - sizeof(USB_InterfaceDescriptor) + \ - sizeof(USB_EndPointDescriptor) * 2) - -static struct { - USB_ConfigDescriptor configuration_descriptor; - USB_InterfaceDescriptor interface_descritor; - USB_EndPointDescriptor endpoint_descriptor[2]; -} __attribute__ ((packed)) confDesc = { - { - sizeof(USB_ConfigDescriptor), - CONFIGURATION_DESCRIPTOR, - CONFIG_DESCRIPTOR_LEN, - 0x01, - 0x01, - 0x00, - 0xc0, // Self Powered, no remote wakeup - 0x64 // Maximum power consumption 2000 mA - }, - { - sizeof(USB_InterfaceDescriptor), - INTERFACE_DESCRIPTOR, - 0x00, - 0x00, - 0x02, /* ep number */ - 0xff, - 0xff, - 0xff, - 0x00 - }, - { - { - sizeof(USB_EndPointDescriptor), - ENDPOINT_DESCRIPTOR, - (1 << 7) | 1,// endpoint 2 is IN endpoint - 2, /* bulk */ - 512, - 0 - }, - { - sizeof(USB_EndPointDescriptor), - ENDPOINT_DESCRIPTOR, - (0 << 7) | 1,// endpoint 5 is OUT endpoint - 2, /* bulk */ - 512, /* OUT EP FIFO size */ - 0 - } - } -}; - -void sendDevDescString(int size) -{ - u16 str_ret[13] = { - 0x031a,//0x1a=26 byte - 0x0041, - 0x0030, - 0x0030, - 0x0041, - 0x0030, - 0x0030, - 0x0041, - 0x0030, - 0x0030, - 0x0041, - 0x0030, - 0x0030 - }; - if(size >= 26) - size = 26; - str_ret[0] = (0x0300 | size); - HW_SendPKT(0, (u8 *)str_ret,size); + return 0; } -void sendDevDesc(int size) -{ - switch (size) { - case 18: - HW_SendPKT(0, (u8 *)&devDesc, sizeof(devDesc)); - break; - default: - HW_SendPKT(0, (u8 *)&devDesc, 8); - break; - } -} - -void sendConfDesc(int size) +int usb_drv_recv(int endpoint, void* ptr, int length) { - switch (size) { - case 9: - HW_SendPKT(0, (u8 *)&confDesc, 9); - break; - case 8: - HW_SendPKT(0, (u8 *)&confDesc, 8); - break; - default: - HW_SendPKT(0, (u8 *)&confDesc, sizeof(confDesc)); - break; - } -} + DEBUGF("usb_drv_recv(%d, 0x%x, %d)", endpoint, (int)ptr, length); -void EP0_init(u32 out, u32 out_size, u32 in, u32 in_size) -{ - confDesc.endpoint_descriptor[0].bEndpointAddress = (1<<7) | in; - confDesc.endpoint_descriptor[0].wMaxPacketSize = in_size; - confDesc.endpoint_descriptor[1].bEndpointAddress = (0<<7) | out; - confDesc.endpoint_descriptor[1].wMaxPacketSize = out_size; + if(endpoint == EP_CONTROL && ptr == NULL && length == 0) /* ACK request */ + return 0; + + return -1; } -static void udc_reset(void) +void usb_drv_set_test_mode(int mode) { - //data init - ep0state = USB_EP0_IDLE; - Bulk_in_size = 0; - Bulk_in_finish = 0; - Bulk_out_size = 0; - udc_state = IDLE; - tx_size = 0; - rx_size = 0; - finished = 0; - /* Enable the USB PHY */ -// REG_CPM_SCR |= CPM_SCR_USBPHY_ENABLE; - /* Disable interrupts */ - jz_writew(USB_REG_INTRINE, 0); - jz_writew(USB_REG_INTROUTE, 0); - jz_writeb(USB_REG_INTRUSBE, 0); - jz_writeb(USB_REG_FADDR,0); - jz_writeb(USB_REG_POWER,0x60); //High speed - jz_writeb(USB_REG_INDEX,0); - jz_writeb(USB_REG_CSR0,0xc0); - jz_writeb(USB_REG_INDEX,1); - jz_writew(USB_REG_INMAXP,512); - jz_writew(USB_REG_INCSR,0x2048); - jz_writeb(USB_REG_INDEX,1); - jz_writew(USB_REG_OUTMAXP,512); - jz_writew(USB_REG_OUTCSR,0x0090); - jz_writew(USB_REG_INTRINE,0x3); //enable intr - jz_writew(USB_REG_INTROUTE,0x2); - jz_writeb(USB_REG_INTRUSBE,0x4); - - if ((jz_readb(USB_REG_POWER)&0x10)==0) - { - jz_writeb(USB_REG_INDEX,1); - jz_writew(USB_REG_INMAXP,64); - jz_writew(USB_REG_INCSR,0x2048); - jz_writeb(USB_REG_INDEX,1); - jz_writew(USB_REG_OUTMAXP,64); - jz_writew(USB_REG_OUTCSR,0x0090); - USB_Version=USB_FS; - fifosize[1]=64; - EP0_init(1,64,1,64); - } - else + switch(mode) { - jz_writeb(USB_REG_INDEX,1); - jz_writew(USB_REG_INMAXP,512); - jz_writew(USB_REG_INCSR,0x2048); - jz_writeb(USB_REG_INDEX,1); - jz_writew(USB_REG_OUTMAXP,512); - jz_writew(USB_REG_OUTCSR,0x0090); - USB_Version=USB_HS; - fifosize[1]=512; - EP0_init(1,512,1,512); - } - -} - -void usbHandleStandDevReq(u8 *buf) -{ - USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf; - switch (dreq->bRequest) { - case GET_DESCRIPTOR: - if (dreq->bmRequestType == 0x80) /* Dev2Host */ - switch(dreq->wValue >> 8) - { - case DEVICE_DESCRIPTOR: - sendDevDesc(dreq->wLength); - break; - case CONFIGURATION_DESCRIPTOR: - sendConfDesc(dreq->wLength); - break; - case STRING_DESCRIPTOR: - if (dreq->wLength == 0x02) - HW_SendPKT(0, "\x04\x03", 2); - else - sendDevDescString(dreq->wLength); - //HW_SendPKT(0, "\x04\x03\x09\x04", 2); - break; - } - ep0state=USB_EP0_TX; - - break; - case SET_ADDRESS: - jz_writeb(USB_REG_FADDR,dreq->wValue); - break; - case GET_STATUS: - switch (dreq->bmRequestType) { - case 80: /* device */ - HW_SendPKT(0, "\x01\x00", 2); + case 0: + REG_USB_REG_TESTMODE &= ~USB_TEST_ALL; break; - case 81: /* interface */ - case 82: /* ep */ - HW_SendPKT(0, "\x00\x00", 2); + case 1: + REG_USB_REG_TESTMODE |= USB_TEST_J; break; - } - ep0state=USB_EP0_TX; - break; - case CLEAR_FEATURE: - case SET_CONFIGURATION: - case SET_INTERFACE: - case SET_FEATURE: - break; - } -} - -unsigned char nandbuffer[4096]; -extern void jz_nand_read(int block, int page, unsigned char *buf); - -void usbHandleVendorReq(u8 *buf) -{ - USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf; - switch (dreq->bRequest) - { - case 0xB0: - memset(&nandbuffer, 0, 4096); - jz_nand_read(dreq->wValue, dreq->wIndex, nandbuffer); - //printf("Read block %d page %d", dreq->wValue, dreq->wIndex); - udc_state = IDLE; + case 2: + REG_USB_REG_TESTMODE |= USB_TEST_K; break; - case 0xAB: - Enable_DMA(nandbuffer, 4096); - //HW_SendPKT(1, nandbuffer, 4096); - //printf("Send data"); - //udc_state = BULK_OUT; + case 3: + REG_USB_REG_TESTMODE |= USB_TEST_SE0NAK; break; - case 0x12: - HW_SendPKT(0, "TEST", 4); - //printf("Send test"); - udc_state = IDLE; + case 4: + REG_USB_REG_TESTMODE |= USB_TEST_PACKET; break; } } -void Handshake_PKT(void) -{ - if (udc_state!=IDLE) - { - HW_SendPKT(1,(u8 *)handshake_PKT,sizeof(handshake_PKT)); - udc_state = IDLE; - } -} - -void usbHandleDevReq(u8 *buf) +int usb_drv_port_speed(void) { - switch ((buf[0] & (3 << 5)) >> 5) { - case 0: /* Standard request */ - usbHandleStandDevReq(buf); - break; - case 1: /* Class request */ - break; - case 2: /* Vendor request */ - usbHandleVendorReq(buf); - break; - } + return ((REG_USB_REG_POWER & USB_POWER_HSMODE) != 0) ? 1 : 0; } -void EP0_Handler (void) +void usb_drv_cancel_all_transfers(void) { - u8 byCSR0; - -/* Read CSR0 */ - jz_writeb(USB_REG_INDEX, 0); - byCSR0 = jz_readb(USB_REG_CSR0); - -/* Check for SentStall - if sendstall is set ,clear the sendstall bit*/ - if (byCSR0 & USB_CSR0_SENTSTALL) - { - jz_writeb(USB_REG_CSR0, (byCSR0 & ~USB_CSR0_SENDSTALL)); - ep0state = USB_EP0_IDLE; - return; - } - -/* Check for SetupEnd */ - if (byCSR0 & USB_CSR0_SETUPEND) - { - jz_writeb(USB_REG_CSR0, (byCSR0 | USB_CSR0_SVDSETUPEND)); - ep0state = USB_EP0_IDLE; - return; - } -/* Call relevant routines for endpoint 0 state */ - if (ep0state == USB_EP0_IDLE) - { - if (byCSR0 & USB_CSR0_OUTPKTRDY) //There are datas in fifo - { - USB_DeviceRequest *dreq; - fifo=fifoaddr[0]; - udcReadFifo((u8 *)rx_buf, sizeof(USB_DeviceRequest)); - usb_setb(USB_REG_CSR0, 0x48);//clear OUTRD bit - dreq = (USB_DeviceRequest *)rx_buf; - usbHandleDevReq((u8 *)rx_buf); - } - rx_size = 0; - } + DEBUGF("usb_drv_cancel_all_transfers()"); - if (ep0state == USB_EP0_TX) + unsigned int i; + for(i=0; i 0 && tx_size % fifosize[1] != 0) - { - jz_writeb(USB_REG_INDEX, 1); - usb_clearb(USB_REG_INCSR, USB_INCSR_INPKTRDY); - } - Disable_DMA(); + endpoints[i].sent = 0; + endpoints[i].length = 0; + /* TODO: flush FIFO's ? */ } + + ep0state = USB_EP0_IDLE; } -void __udc_start(void) +void usb_drv_release_endpoint(int ep) { - udc_reset(); + //DEBUGF("usb_drv_release_endpoint(%d)", ep); - ep0state = USB_EP0_IDLE; - Bulk_in_size = 0; - Bulk_in_finish = 0; - Bulk_out_size = 0; - udc_state = IDLE; - tx_size = 0; - rx_size = 0; - finished = 0; - - if ((jz_readb(USB_REG_POWER)&0x10)==0) - { - USB_Version=USB_FS; - fifosize[1]=64; - EP0_init(1,64,1,64); - } - else - { - USB_Version=USB_HS; - fifosize[1]=512; - EP0_init(1,512,1,512); - } - - USB_Version=USB_HS; - system_enable_irq(IRQ_UDC); + (void)ep; } -void usb_init_device(void) +int usb_drv_request_endpoint(int dir) { - REG_USB_REG_POWER &= ~USB_POWER_SOFTCONN; - REG_USB_REG_POWER |= USB_POWER_SOFTCONN; - __udc_start(); + DEBUGF("usb_drv_request_endpoint(%d)", dir); + + (void)dir; + return -1; } - -#endif -- cgit v1.2.3