diff options
author | Maurus Cuelenaere <mcuelenaere@gmail.com> | 2008-08-26 21:48:49 +0000 |
---|---|---|
committer | Maurus Cuelenaere <mcuelenaere@gmail.com> | 2008-08-26 21:48:49 +0000 |
commit | 62c4a2838eea24dc41a65e4fc567e386f07c32e4 (patch) | |
tree | 47bd1e837c3f3da5e9cd4156f2fff98526e5b90a /firmware | |
parent | 753350154ea04c8369225b9c1dc1840dc6fcd1d4 (diff) |
Onda VX747:
* Overall cleanup (still needs work)
* Add preliminary USB support
* Add power off support
* Add preliminary MMU handling
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@18348 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/SOURCES | 1 | ||||
-rw-r--r-- | firmware/export/mipsregs.h | 2 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c | 4 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/boot.lds | 48 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/crt0.S | 85 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/kernel-jz4740.c | 8 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/lcd-jz4740.c | 2 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/onda_vx747/sadc-onda_vx747.c | 101 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/system-jz4740.c | 175 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/system-target.h | 2 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/usb-jz4740.c | 1037 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/usb-target.h (renamed from firmware/target/mips/ingenic_jz47xx/onda_vx747/usb-target.h) | 7 |
12 files changed, 1354 insertions, 118 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES index 17545b99a6..24be9e58ae 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -1084,6 +1084,7 @@ target/mips/ingenic_jz47xx/ata-nand-jz4740.c target/mips/ingenic_jz47xx/lcd-jz4740.c target/mips/ingenic_jz47xx/kernel-jz4740.c target/mips/ingenic_jz47xx/system-jz4740.c +target/mips/ingenic_jz47xx/usb-jz4740.c drivers/nand_id.c #endif diff --git a/firmware/export/mipsregs.h b/firmware/export/mipsregs.h index 1247261e69..2ac5202ed6 100644 --- a/firmware/export/mipsregs.h +++ b/firmware/export/mipsregs.h @@ -706,6 +706,8 @@ do { \ #define read_c0_cache() __read_32bit_c0_register($7, 0) /* TX39xx */ #define write_c0_cache(val) __write_32bit_c0_register($7, 0, val) +#define read_c0_badvaddr() __read_32bit_c0_register($8, 0) + #define read_c0_count() __read_32bit_c0_register($9, 0) #define write_c0_count(val) __write_32bit_c0_register($9, 0, val) diff --git a/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c b/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c index c6eb55f0b9..20a7256f82 100644 --- a/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c @@ -42,7 +42,9 @@ #define NANDFLASH_ALE 0x00010000 //PA[16] #define NANDFLASH_BASE 0xB8000000 -#define REG_NAND_DATA (*((volatile unsigned char *)NANDFLASH_BASE)) +#define REG_NAND_DATA8 (*((volatile unsigned char *)NANDFLASH_BASE)) +#define REG_NAND_DATA16 (*((volatile unsigned short *)NANDFLASH_BASE)) +#define REG_NAND_DATA REG_NAND_DATA8 #define REG_NAND_CMD (*((volatile unsigned char *)(NANDFLASH_BASE + NANDFLASH_CLE))) #define REG_NAND_ADDR (*((volatile unsigned char *)(NANDFLASH_BASE + NANDFLASH_ALE))) diff --git a/firmware/target/mips/ingenic_jz47xx/boot.lds b/firmware/target/mips/ingenic_jz47xx/boot.lds index e3ff0c0cd7..0ea8877714 100644 --- a/firmware/target/mips/ingenic_jz47xx/boot.lds +++ b/firmware/target/mips/ingenic_jz47xx/boot.lds @@ -31,6 +31,10 @@ SECTIONS *(.glue_7); *(.glue_7t); *(.rel.dyn); + } > DRAM + + .vectors : + { _vectorsstart = .; KEEP(*(.vectors)) *(.vectors); @@ -69,18 +73,6 @@ SECTIONS . = ALIGN(4); - .stack : - { - *(.stack) - _stackbegin = .; - stackbegin = .; - . += 0x2000; - _stackend = .; - stackend = .; - } > DRAM - - . = ALIGN(4); - .bss : { _edata = .; @@ -91,4 +83,36 @@ SECTIONS *(.scommon*); _end = .; } > DRAM + + .iram IRAMORIG: + { + . = 0x220; /* Vectors take in 0x80000000 -> 0x80000220 */ + _iramstart = .; + *(.icode) + *(.irodata) + *(.idata) + . = ALIGN(0x4); + _iramend = .; + } > IRAM AT> DRAM + + _iramcopy = LOADADDR(.iram); + + .ibss (NOLOAD) : + { + _iedata = .; + *(.ibss) + . = ALIGN(0x4); + _iend = .; + } > IRAM + + .stack : + { + *(.stack) + . = ALIGN(0x4); + _stackbegin = .; + stackbegin = .; + . += 0x2000; + _stackend = .; + stackend = .; + } > IRAM } diff --git a/firmware/target/mips/ingenic_jz47xx/crt0.S b/firmware/target/mips/ingenic_jz47xx/crt0.S index b9ffde3b65..f079b940a1 100644 --- a/firmware/target/mips/ingenic_jz47xx/crt0.S +++ b/firmware/target/mips/ingenic_jz47xx/crt0.S @@ -40,7 +40,7 @@ .text - .set mips3 + .set mips32 .extern system_main @@ -53,28 +53,36 @@ .word 0 /* HACK */ .word 0 /* HACK */ #endif + _start: la ra, _start - //---------------------------------------------------- - // init cp0 registers. - //---------------------------------------------------- + /* + ---------------------------------------------------- + init cp0 registers. + ---------------------------------------------------- + */ mtc0 zero, C0_WATCHLO mtc0 zero, C0_WATCHHI li t0, (M_StatusBEV | M_StatusIM7 | M_StatusIM6 \ | M_StatusIM5 | M_StatusIM4 | M_StatusIM3 \ - | M_StatusIM2 | M_StatusERL) - // BEV = Enable Boot Exception Vectors - // IMx = Interrupt mask - // ERL = Denotes error level + | M_StatusIM2 | M_StatusERL | M_StatusSM) + /* + BEV = Enable Boot Exception Vectors + IMx = Interrupt mask + ERL = Denotes error level + SM = Supervisor Mode + */ mtc0 t0, C0_STATUS li t1, M_CauseIV mtc0 t1, C0_CAUSE - //---------------------------------------------------- - // init caches, assumes a 4way*128set*32byte i/d cache - //---------------------------------------------------- + /* + ---------------------------------------------------- + init caches, assumes a 4way*128set*32byte i/d cache + ---------------------------------------------------- + */ li t0, 3 // enable cache for kseg0 accesses mtc0 t0, C0_CONFIG // CONFIG reg la t0, 0x80000000 // an idx op should use a unmappable address @@ -82,35 +90,70 @@ _start: mtc0 zero, C0_TAGLO // TAGLO reg mtc0 zero, C0_TAGHI // TAGHI reg -_init_cache_loop: +_init_cache_loop: cache 0x8, 0(t0) // index store icache tag cache 0x9, 0(t0) // index store dcache tag bne t0, t1, _init_cache_loop addiu t0, t0, 0x20 // 32 bytes per cache line nop - //---------------------------------------------------- - // Invalidate BTB - //---------------------------------------------------- + /* + ---------------------------------------------------- + Invalidate BTB + ---------------------------------------------------- + */ mfc0 t0, C0_CONFIG nop ori t0, 2 mtc0 t0, C0_CONFIG nop - //---------------------------------------------------- - // clear BSS section - //---------------------------------------------------- + /* + ---------------------------------------------------- + clear BSS section + ---------------------------------------------------- + */ la t0, _edata la t1, _end _init_bss_loop: sw zero, 0(t0) bne t0, t1, _init_bss_loop addiu t0, 4 + +#ifndef BOOTLOADER + /* + ---------------------------------------------------- + clear IBSS section + ---------------------------------------------------- + */ + la t0, _iedata + la t1, _iend +_init_ibss_loop: + sw zero, 0(t0) + bne t0, t1, _init_ibss_loop + addiu t0, 4 + + /* + ---------------------------------------------------- + copy IRAM section + ---------------------------------------------------- + */ + la t0, _iramcopy + la t1, _iramstart + la t2, _iramend +_init_iram_loop: + lw t3, 0(t0) + sw t3, 0(t1) + addiu t1, 4 + bne t1, t2, _init_iram_loop + addiu t0, 4 +#endif - //---------------------------------------------------- - // setup stack, jump to C code - //---------------------------------------------------- + /* + ---------------------------------------------------- + setup stack, jump to C code + ---------------------------------------------------- + */ la sp, stackend la t0, stackbegin li t1, 0xDEADBEEF diff --git a/firmware/target/mips/ingenic_jz47xx/kernel-jz4740.c b/firmware/target/mips/ingenic_jz47xx/kernel-jz4740.c index 29b581dd6b..62176cee24 100644 --- a/firmware/target/mips/ingenic_jz47xx/kernel-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/kernel-jz4740.c @@ -35,6 +35,11 @@ void tick_start(unsigned int interval_in_ms) __tcu_stop_counter(0); __tcu_disable_pwm_output(0); + __tcu_stop_counter(1); + __tcu_disable_pwm_output(1); + __tcu_stop_counter(2); + __tcu_disable_pwm_output(2); + __tcu_clear_full_match_flag(2); __tcu_mask_half_match_irq(0); __tcu_unmask_full_match_irq(0); @@ -58,12 +63,13 @@ void tick_start(unsigned int interval_in_ms) __tcu_start_counter(0); system_enable_irq(IRQ_TCU0); - } /* Interrupt handler */ void TCU0(void) { + __tcu_clear_full_match_flag(0); + int i; /* Run through the list of tick tasks */ diff --git a/firmware/target/mips/ingenic_jz47xx/lcd-jz4740.c b/firmware/target/mips/ingenic_jz47xx/lcd-jz4740.c index ca082781aa..6bb7db8d9b 100644 --- a/firmware/target/mips/ingenic_jz47xx/lcd-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/lcd-jz4740.c @@ -64,7 +64,7 @@ void lcd_update_rect(int x, int y, int width, int height) REG_DMAC_DTAR(0) = 0x130500B0; /* SLCD_FIFO */ REG_DMAC_DTCR(0) = width*height; - REG_DMAC_DCMD(0) = (DMAC_DCMD_SAI | DMAC_DCMD_RDIL_2 | DMAC_DCMD_SWDH_32 /* (1 << 23) | (0 << 16) | (0 << 14) */ + REG_DMAC_DCMD(0) = (DMAC_DCMD_SAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 /* (1 << 23) | (0 << 16) | (0 << 14) */ | DMAC_DCMD_DWDH_16 | DMAC_DCMD_DS_16BIT); /* | (2 << 12) | (3 << 8) */ REG_DMAC_DCCSR(0) = (DMAC_DCCSR_NDES | DMAC_DCCSR_EN); /* (1 << 31) | (1 << 0) */ 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 e937c90bd3..0f11782d3f 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 @@ -36,7 +36,7 @@ #define TS_AD_COUNT 5 #define M_SADC_CFG_SNUM ((TS_AD_COUNT - 1) << SADC_CFG_SNUM_BIT) -#define SADC_CFG_INIT ( \ +#define SADC_CFG_INIT ( \ (2 << SADC_CFG_CLKOUT_NUM_BIT) | \ SADC_CFG_XYZ1Z2 | \ M_SADC_CFG_SNUM | \ @@ -109,6 +109,7 @@ int button_read_device(int *data) unsigned int key = ~(__gpio_get_port(3)); int ret = 0; + if(key & BTN_MASK) { if(key & BTN_VOL_DOWN) @@ -132,10 +133,33 @@ int button_read_device(int *data) return ret; } +/* +static enum touchpad_mode current_mode = TOUCHPAD_POINT; + +static bool touch_available = false; + +static int touchpad_buttons[3][3] = +{ + {BUTTON_TOPLEFT, BUTTON_TOPMIDDLE, BUTTON_TOPRIGHT}, + {BUTTON_MIDLEFT, BUTTON_CENTER, BUTTON_MIDRIGHT}, + {BUTTON_BOTTOMLEFT, BUTTON_BOTTOMMIDDLE, BUTTON_BOTTOMRIGHT} +}; + +void touchpad_set_mode(enum touchpad_mode mode) +{ + current_mode = mode; +} + +enum touchpad_mode touchpad_get_mode(void) +{ + return current_mode; +} + void button_set_touch_available(void) { - return; + touch_available = true; } +*/ /* Interrupt handler */ void SADC(void) @@ -167,51 +191,50 @@ void SADC(void) } if(state & SADC_CTRL_TSRDYM) { - unsigned int dat; - unsigned short xData, yData; - short tsz1Data, tsz2Data; - - dat = REG_SADC_TSDAT; - - xData = (dat >> 0) & 0xfff; - yData = (dat >> 16) & 0xfff; - - dat = REG_SADC_TSDAT; + unsigned int dat; + unsigned short xData, yData; + short tsz1Data, tsz2Data; + + dat = REG_SADC_TSDAT; + + xData = (dat >> 0) & 0xfff; + yData = (dat >> 16) & 0xfff; + + dat = REG_SADC_TSDAT; tsz1Data = (dat >> 0) & 0xfff; - tsz2Data = (dat >> 16) & 0xfff; + tsz2Data = (dat >> 16) & 0xfff; + + if(!pendown_flag) + return ; - if(!pendown_flag) - return ; - - tsz1Data = tsz2Data - tsz1Data; - - if((tsz1Data > 15) || (tsz1Data < -15)) + tsz1Data = tsz2Data - tsz1Data; + + if((tsz1Data > 15) || (tsz1Data < -15)) { - if(x_pos == -1) - x_pos = xData; - else - x_pos = (x_pos + xData) / 2; - - if(y_pos == -1) - y_pos = yData; - else - y_pos = (y_pos + yData) / 2; + if(x_pos == -1) + x_pos = xData; + else + x_pos = (x_pos + xData) / 2; + + if(y_pos == -1) + y_pos = yData; + else + y_pos = (y_pos + yData) / 2; } datacount++; - - if(datacount > TS_AD_COUNT - 1) - { - if(x_pos != -1) - { + + if(datacount > TS_AD_COUNT - 1) + { + if(x_pos != -1) + { stable_x_pos = x_pos; stable_y_pos = y_pos; - x_pos = -1; - y_pos = -1; - } - - datacount = 0; - } + x_pos = -1; + y_pos = -1; + } + datacount = 0; + } } if(state & SADC_CTRL_PBATRDYM) { diff --git a/firmware/target/mips/ingenic_jz47xx/system-jz4740.c b/firmware/target/mips/ingenic_jz47xx/system-jz4740.c index 25b14106c4..8f1c3f5c1a 100644 --- a/firmware/target/mips/ingenic_jz47xx/system-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/system-jz4740.c @@ -269,25 +269,15 @@ static void dis_irq(unsigned int irq) static void ack_irq(unsigned int irq) { - __intc_ack_irq(irq); if ((irq >= IRQ_GPIO_0) && (irq <= IRQ_GPIO_0 + NUM_GPIO)) { __intc_ack_irq(IRQ_GPIO0 - ((irq - IRQ_GPIO_0)>>5)); __gpio_ack_irq(irq - IRQ_GPIO_0); } else if ((irq >= IRQ_DMA_0) && (irq <= IRQ_DMA_0 + NUM_DMA)) - { __intc_ack_irq(IRQ_DMAC); - } else if (irq < 32) - { __intc_ack_irq(irq); - /* TODO: check if really needed */ - if (irq == IRQ_TCU0) - { - __tcu_clear_full_match_flag(0); - } - } } static unsigned long ipl; @@ -296,7 +286,7 @@ static int get_irq_number(void) register int irq = 0; ipl |= REG_INTC_IPR; - + if (ipl == 0) return -1; @@ -341,8 +331,6 @@ void intr_handler(void) ack_irq(irq); if(irq > 0) irqvector[irq-1](); - - return; } #define EXC(x,y) if(_cause == (x)) return (y); @@ -386,7 +374,6 @@ static void detect_clock(void) cfcr = REG_CPM_CPCCR; pllout = (__cpm_get_pllm() + 2)* JZ_EXTAL / (__cpm_get_plln() + 2); iclk = pllout / FR2n[__cpm_get_cdiv()]; - /*printf("EXTAL_CLK = %dM PLL = %d iclk = %d\r\n",EXTAL_CLK / 1000 /1000,pllout,iclk);*/ } void udelay(unsigned int usec) @@ -450,11 +437,11 @@ void sti(void) #define SYNC_WB() __asm__ __volatile__ ("sync") -#define cache_op(op,addr) \ +#define __CACHE_OP(op, addr) \ __asm__ __volatile__( \ " .set noreorder \n" \ " .set mips32\n\t \n" \ - " cache %0, %1 \n" \ + " cache %0, %1 \n" \ " .set mips0 \n" \ " .set reorder \n" \ : \ @@ -462,7 +449,7 @@ void sti(void) void __flush_dcache_line(unsigned long addr) { - cache_op(Hit_Writeback_Inv_D, addr); + __CACHE_OP(Hit_Writeback_Inv_D, addr); SYNC_WB(); } @@ -470,6 +457,7 @@ void __icache_invalidate_all(void) { unsigned int i; +/* do { unsigned long __k0_addr; @@ -484,17 +472,19 @@ void __icache_invalidate_all(void) : "r" (0x20000000) ); } while(0); +*/ asm volatile (".set noreorder \n" ".set mips32 \n" - "mtc0 $0,$28 \n" - "mtc0 $0,$29 \n" + "mtc0 $0, $28 \n" /* TagLo */ + "mtc0 $0, $29 \n" /* TagHi */ ".set mips0 \n" ".set reorder \n" ); for(i=KSEG0; i<KSEG0+CACHE_SIZE; i+=CACHE_LINE_SIZE) - cache_op(Index_Store_Tag_I, i); + __CACHE_OP(Index_Store_Tag_I, i); +/* do { unsigned long __k0_addr; @@ -507,16 +497,17 @@ void __icache_invalidate_all(void) : "=&r" (__k0_addr) ); } while(0); +*/ do { unsigned long tmp; __asm__ __volatile__( ".set mips32 \n" - "mfc0 %0, $16, 7 \n" + "mfc0 %0, $16, 7 \n" /* Config */ "nop \n" "ori %0, 2 \n" - "mtc0 %0, $16, 7 \n" + "mtc0 %0, $16, 7 \n" /* Config */ "nop \n" ".set mips0 \n" : "=&r" (tmp)); @@ -529,20 +520,20 @@ void __dcache_invalidate_all(void) asm volatile (".set noreorder \n" ".set mips32 \n" - "mtc0 $0,$28 \n" - "mtc0 $0,$29 \n" + "mtc0 $0, $28 \n" + "mtc0 $0, $29 \n" ".set mips0 \n" ".set reorder \n" ); for (i=KSEG0; i<KSEG0+CACHE_SIZE; i+=CACHE_LINE_SIZE) - cache_op(Index_Store_Tag_D, i); + __CACHE_OP(Index_Store_Tag_D, i); } void __dcache_writeback_all(void) { unsigned int i; for(i=KSEG0; i<KSEG0+CACHE_SIZE; i+=CACHE_LINE_SIZE) - cache_op(Index_Writeback_Inv_D, i); + __CACHE_OP(Index_Writeback_Inv_D, i); SYNC_WB(); } @@ -559,37 +550,129 @@ void dma_cache_wback_inv(unsigned long addr, unsigned long size) a = addr & ~(dc_lsize - 1); end = (addr + size - 1) & ~(dc_lsize - 1); - while (1) - { + for(; a < end; a += dc_lsize) __flush_dcache_line(a); /* Hit_Writeback_Inv_D */ - if (a == end) - break; - a += dc_lsize; - } } } extern int main(void); -extern unsigned int _vectorsstart; /* see boot.lds/app.lds */ +extern void except_common_entry(void); + +#define mtc0_tlbw_hazard() \ + __asm__ __volatile__( \ + " .set noreorder \n" \ + " nop \n" \ + " nop \n" \ + " nop \n" \ + " nop \n" \ + " nop \n" \ + " nop \n" \ + " .set reorder \n"); + +#define tlbw_use_hazard() \ + __asm__ __volatile__( \ + " .set noreorder \n" \ + " nop \n" \ + " nop \n" \ + " nop \n" \ + " nop \n" \ + " nop \n" \ + " nop \n" \ + " .set reorder \n"); + + +#define PAGE_SHIFT PL_4K +#define PM_DEFAULT_MASK PM_4K +#define UNIQUE_ENTRYHI(idx) (A_K0BASE + ((idx) << (PAGE_SHIFT + 1))) +static void local_flush_tlb_all(void) +{ + unsigned long old_ctx; + int entry; + unsigned int old_irq = disable_irq_save(); + + /* Save old context and create impossible VPN2 value */ + old_ctx = read_c0_entryhi(); + write_c0_entrylo0(0); + write_c0_entrylo1(0); + + /* Blast 'em all away. */ + for(entry = read_c0_wired(); entry < 32; entry++) + { + /* Make sure all entries differ. */ + write_c0_entryhi(UNIQUE_ENTRYHI(entry)); + write_c0_index(entry); + mtc0_tlbw_hazard(); + tlb_write_indexed(); + } + tlbw_use_hazard(); + write_c0_entryhi(old_ctx); + + restore_irq(old_irq); +} + + +static void tlb_init(void) +{ + write_c0_pagemask(PM_DEFAULT_MASK); + write_c0_wired(0); + write_c0_framemask(0); + + local_flush_tlb_all(); +} + +static void tlb_refill_handler(void) +{ +#if 1 + panicf("TLB refill handler! [0x%x] [0x%x]", read_c0_badvaddr(), read_c0_epc()); +#else + __asm__ __volatile__( + "mfc0 k0, C0_BADVADDR\n" + "lui k1, pgdc\n" + "lw k1, pgdc>>16(k0)\n" + "srl k0, k0, 22\n" + "sll k0, k0, 2\n" + "addu k1, k1, k0\n" + "mfc0 k0, C0_CONTEXT\n" + "lw k1, 0(k1)\n" + "andi k0, k0, 0xFFC\n" + "addu k1, k1, k0\n" + "lw k0, 0(k1)\n" + "nop\n" + "mtc0 k0, C0_ENTRYLO0\n" + "mfc0 k1, C0_EPC\n" + "tlbwr\n" + "jr k1\n" + "rfe\n" + ); +#endif +} void system_main(void) { int i; - cli(); - write_c0_status(1 << 28 | 1 << 10); /* Enable CP | Mask interrupt 2 */ - - memcpy((void *)A_K0BASE, (void *)&_vectorsstart, 0x20); - memcpy((void *)(A_K0BASE + 0x180), (void *)&_vectorsstart, 0x20); - memcpy((void *)(A_K0BASE + 0x200), (void *)&_vectorsstart, 0x20); + /* + * 0x0 - Simple TLB refill handler + * 0x100 - Cache error handler + * 0x180 - Exception/Interrupt handler + * 0x200 - Special Exception Interrupt handler (when IV is set in CP0_CAUSE) + */ + memcpy((void *)A_K0BASE, (void *)&tlb_refill_handler, 0x20); + memcpy((void *)(A_K0BASE + 0x100), (void *)&except_common_entry, 0x20); + memcpy((void *)(A_K0BASE + 0x180), (void *)&except_common_entry, 0x20); + memcpy((void *)(A_K0BASE + 0x200), (void *)&except_common_entry, 0x20); __dcache_writeback_all(); __icache_invalidate_all(); + write_c0_status(1 << 28 | 1 << 10 | 1 << 3); /* Enable CP | Mask interrupt 2 | Supervisor mode */ + /* Disable all interrupts */ for(i=0; i<IRQ_MAX; i++) dis_irq(i); + tlb_init(); + sti(); detect_clock(); @@ -609,3 +692,17 @@ void system_reboot(void) while (1); } + +void power_off(void) +{ + /* Put system into hibernate mode */ + __rtc_clear_alarm_flag(); + __rtc_clear_hib_stat_all(); + //__rtc_set_scratch_pattern(0x12345678); + __rtc_enable_alarm_wakeup(); + __rtc_set_hrcr_val(0xfe0); + __rtc_set_hwfcr_val((0xFFFF << 4)); + __rtc_power_down(); + + while(1); +} diff --git a/firmware/target/mips/ingenic_jz47xx/system-target.h b/firmware/target/mips/ingenic_jz47xx/system-target.h index 7d4c28756a..01ba176dd2 100644 --- a/firmware/target/mips/ingenic_jz47xx/system-target.h +++ b/firmware/target/mips/ingenic_jz47xx/system-target.h @@ -99,6 +99,8 @@ void sti(void); void cli(void); void udelay(unsigned int usec); void mdelay(unsigned int msec); +void power_off(void); +void system_reboot(void); #endif /* __SYSTEM_TARGET_H_ */ diff --git a/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c new file mode 100644 index 0000000000..92a2f3b801 --- /dev/null +++ b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c @@ -0,0 +1,1037 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2008 by Maurus Cuelenaere + * + * 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" +#include "system.h" +#include "usb_ch9.h" +#include "usb_drv.h" +#include "usb_core.h" +#include "jz4740.h" +#include "thread.h" + +#if 0 + +#define EP1_INTR_BIT 2 +#define EP_FIFO_NOEMPTY 2 + +#define GPIO_UDC_DETE_PIN (32 * 3 + 6) +#define GPIO_UDC_DETE GPIO_UDC_DETE_PIN +#define IRQ_GPIO_UDC_DETE (IRQ_GPIO_0 + GPIO_UDC_DETE) + +#define IS_CACHE(x) (x < 0xa0000000) + +bool usb_drv_connected(void) +{ + return (__gpio_get_pin(GPIO_UDC_DETE)==1); +} + +int usb_detect(void) +{ + if(__gpio_get_pin(GPIO_UDC_DETE)==1) + return USB_INSERTED; + else + return USB_EXTRACTED; +} + +void usb_init_device(void) +{ + system_enable_irq(IRQ_UDC); + __gpio_as_input(GPIO_UDC_DETE_PIN); + return; +} + +void usb_enable(bool on) +{ + if(on) + usb_core_init(); + else + usb_core_exit(); +} + +void usb_drv_init(void) +{ + /* Set this bit to allow the UDC entering low-power mode when + * there are no actions on the USB bus. + * UDC still works during this bit was set. + */ + //__cpm_stop_udc(); + + __cpm_start_udc(); + + /* 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; +} + +void usb_drv_exit(void) +{ + /* Disable interrupts */ + 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; + + /* Disconnect from usb */ + REG_USB_REG_POWER &= ~USB_POWER_SOFTCONN; + + /* Disable the USB PHY */ + REG_CPM_SCR &= ~CPM_SCR_USBPHY_ENABLE; + + __cpm_stop_udc(); +} + +void usb_drv_set_address(int address) +{ + REG_USB_REG_FADDR = address; +} + +/* Interrupt handler */ +void UDC(void) +{ + +} + +#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 + +u32 Bulk_in_buf[BULK_IN_BUF_SIZE]; +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) + { + 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]; + } + } + else //EP0 + { + tx_size = size; + finished = 0; + memcpy((void *)tx_buf, buf, size); + ep0state = USB_EP0_TX; + } +} + +void HW_GetPKT(int ep, const u8 *buf, 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); +} + +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, + 16 + }, + { + sizeof(USB_EndPointDescriptor), + ENDPOINT_DESCRIPTOR, + (0 << 7) | 1,// endpoint 5 is OUT endpoint + 2, /* bulk */ + 512, /* OUT EP FIFO size */ + 16 + } + } +}; + +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); +} + +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) +{ + 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; + } +} + +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; +} + +static void udc_reset(void) +{ + //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 + { + 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); + break; + case 81: /* interface */ + case 82: /* ep */ + HW_SendPKT(0, "\x00\x00", 2); + break; + } + ep0state=USB_EP0_TX; + break; + case CLEAR_FEATURE: + case SET_CONFIGURATION: + case SET_INTERFACE: + case SET_FEATURE: + break; + } +} + +extern char printfbuf[256]; + +int GET_CUP_INFO_Handle() +{ + HW_SendPKT(0, printfbuf, 64); + udc_state = IDLE; + return 0; +} + +void usbHandleVendorReq(u8 *buf) +{ + int ret_state; + USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf; + switch (dreq->bRequest) { + case 0xAB: + ret_state=GET_CUP_INFO_Handle(); + break; + case 0x12: + HW_SendPKT(0, "TEST", 4); + udc_state = IDLE; + 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) +{ + 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; + } +} + +void EP0_Handler (void) +{ + u8 byCSR0; + +/* Read CSR0 */ + jz_writeb(USB_REG_INDEX, 0); + byCSR0 = jz_readb(USB_REG_CSR0); + +/* Check for SentStall + if sendtall 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; + } + + if (ep0state == USB_EP0_TX) + { + fifo=fifoaddr[0]; + if (tx_size - finished <= 64) + { + udcWriteFifo((u8 *)((u32)tx_buf+finished), + tx_size - finished); + finished = tx_size; + usb_setb(USB_REG_CSR0, USB_CSR0_INPKTRDY); + usb_setb(USB_REG_CSR0, USB_CSR0_DATAEND); //Set dataend! + ep0state=USB_EP0_IDLE; + } else + { + udcWriteFifo((u8 *)((u32)tx_buf+finished), 64); + usb_setb(USB_REG_CSR0, USB_CSR0_INPKTRDY); + finished += 64; + } + } + return; +} + +void EPIN_Handler(u8 EP) +{ + jz_writeb(USB_REG_INDEX, EP); + fifo = fifoaddr[EP]; + + if (Bulk_in_size-Bulk_in_finish==0) + { + Handshake_PKT(); + return; + } + + if (Bulk_in_size - Bulk_in_finish <= fifosize[EP]) + { + udcWriteFifo((u8 *)((u32)Bulk_in_buf+Bulk_in_finish), + Bulk_in_size - Bulk_in_finish); + usb_setw(USB_REG_INCSR, USB_INCSR_INPKTRDY); + Bulk_in_finish = Bulk_in_size; + } else + { + udcWriteFifo((u8 *)((u32)Bulk_in_buf+Bulk_in_finish), + fifosize[EP]); + usb_setw(USB_REG_INCSR, USB_INCSR_INPKTRDY); + Bulk_in_finish += fifosize[EP]; + } +} + +void EPOUT_Handler(u8 EP) +{ + u32 size; + jz_writeb(USB_REG_INDEX, EP); + size = jz_readw(USB_REG_OUTCOUNT); + fifo = fifoaddr[EP]; + udcReadFifo((u8 *)((u32)Bulk_out_buf+Bulk_out_size), size); + usb_clearb(USB_REG_OUTCSR,USB_OUTCSR_OUTPKTRDY); + Bulk_out_size += size; +} + +void UDC(void) +{ + u8 IntrUSB; + u16 IntrIn; + u16 IntrOut; +/* Read interrupt registers */ + IntrUSB = jz_readb(USB_REG_INTRUSB); + IntrIn = jz_readw(USB_REG_INTRIN); + IntrOut = jz_readw(USB_REG_INTROUT); + + if ( IntrUSB == 0 && IntrIn == 0 && IntrOut == 0) + return; + + if (IntrIn & 2) + { + EPIN_Handler(1); + } + if (IntrOut & 2) + { + EPOUT_Handler(1); + } + if (IntrUSB & USB_INTR_RESET) + { + udc_reset(); + } + +/* Check for endpoint 0 interrupt */ + if (IntrIn & USB_INTR_EP0) + { + EP0_Handler(); + } + + IntrIn = jz_readw(USB_REG_INTRIN); + return; +} + +void __udc_start(void) +{ + udc_reset(); + + 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 usb_init_device(void){} + +#endif diff --git a/firmware/target/mips/ingenic_jz47xx/onda_vx747/usb-target.h b/firmware/target/mips/ingenic_jz47xx/usb-target.h index 30893aaaa3..ec700de892 100644 --- a/firmware/target/mips/ingenic_jz47xx/onda_vx747/usb-target.h +++ b/firmware/target/mips/ingenic_jz47xx/usb-target.h @@ -18,9 +18,8 @@ * KIND, either express or implied. * ****************************************************************************/ -#ifndef USB_TARGET_H -#define USB_TARGET_H +#include <stdbool.h> +int usb_detect(void); void usb_init_device(void); - -#endif +bool usb_drv_connected(void); |