diff options
-rw-r--r-- | firmware/export/jz4740.h | 32 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c | 12 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/codec-jz4740.c | 60 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/lcd-jz4740.c | 32 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/onda_vx747/sadc-onda_vx747.c | 55 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/onda_vx747/usb-target.h | 20 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c | 47 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/system-jz4740.c | 2 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/system-target.h | 3 | ||||
-rw-r--r-- | 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 @@ | |||
2339 | #define USB_REG_TESTMODE (USB_BASE + 0x0f) /* USB test mode 8-bit */ | 2339 | #define USB_REG_TESTMODE (USB_BASE + 0x0f) /* USB test mode 8-bit */ |
2340 | 2340 | ||
2341 | #define USB_REG_CSR0 (USB_BASE + 0x12) /* EP0 CSR 8-bit */ | 2341 | #define USB_REG_CSR0 (USB_BASE + 0x12) /* EP0 CSR 8-bit */ |
2342 | #define USB_REG_COUNT0 (USB_BASE + 0x18) /* bytes in EP0 FIFO 16-bit */ | ||
2342 | #define USB_REG_INMAXP (USB_BASE + 0x10) /* EP1-2 IN Max Pkt Size 16-bit */ | 2343 | #define USB_REG_INMAXP (USB_BASE + 0x10) /* EP1-2 IN Max Pkt Size 16-bit */ |
2343 | #define USB_REG_INCSR (USB_BASE + 0x12) /* EP1-2 IN CSR LSB 8/16bit */ | 2344 | #define USB_REG_INCSR (USB_BASE + 0x12) /* EP1-2 IN CSR LSB 8/16bit */ |
2344 | #define USB_REG_INCSRH (USB_BASE + 0x13) /* EP1-2 IN CSR MSB 8-bit */ | 2345 | #define USB_REG_INCSRH (USB_BASE + 0x13) /* EP1-2 IN CSR MSB 8-bit */ |
@@ -2375,6 +2376,7 @@ | |||
2375 | #define REG_USB_REG_TESTMODE REG8(USB_REG_TESTMODE) | 2376 | #define REG_USB_REG_TESTMODE REG8(USB_REG_TESTMODE) |
2376 | 2377 | ||
2377 | #define REG_USB_REG_CSR0 REG8(USB_REG_CSR0) | 2378 | #define REG_USB_REG_CSR0 REG8(USB_REG_CSR0) |
2379 | #define REG_USB_REG_COUNT0 REG16(USB_REG_COUNT0) | ||
2378 | #define REG_USB_REG_INMAXP REG16(USB_REG_INMAXP) | 2380 | #define REG_USB_REG_INMAXP REG16(USB_REG_INMAXP) |
2379 | #define REG_USB_REG_INCSR REG16(USB_REG_INCSR) | 2381 | #define REG_USB_REG_INCSR REG16(USB_REG_INCSR) |
2380 | #define REG_USB_REG_INCSRH REG8(USB_REG_INCSRH) | 2382 | #define REG_USB_REG_INCSRH REG8(USB_REG_INCSRH) |
@@ -2395,6 +2397,9 @@ | |||
2395 | #define REG_USB_REG_ADDR2 REG32(USB_REG_ADDR2) | 2397 | #define REG_USB_REG_ADDR2 REG32(USB_REG_ADDR2) |
2396 | #define REG_USB_REG_COUNT2 REG32(USB_REG_COUNT2) | 2398 | #define REG_USB_REG_COUNT2 REG32(USB_REG_COUNT2) |
2397 | 2399 | ||
2400 | #define REG_USB_REG_EPINFO REG16(USB_REG_EPINFO) | ||
2401 | #define REG_USB_REG_RAMINFO REG8(USB_REG_RAMINFO) | ||
2402 | |||
2398 | 2403 | ||
2399 | /* Power register bit masks */ | 2404 | /* Power register bit masks */ |
2400 | #define USB_POWER_SUSPENDM 0x01 | 2405 | #define USB_POWER_SUSPENDM 0x01 |
@@ -2414,6 +2419,8 @@ | |||
2414 | #define USB_INTR_OUTEP1 0x0002 | 2419 | #define USB_INTR_OUTEP1 0x0002 |
2415 | #define USB_INTR_OUTEP2 0x0004 | 2420 | #define USB_INTR_OUTEP2 0x0004 |
2416 | 2421 | ||
2422 | #define USB_INTR_EP(n) (n*2) | ||
2423 | |||
2417 | /* CSR0 bit masks */ | 2424 | /* CSR0 bit masks */ |
2418 | #define USB_CSR0_OUTPKTRDY 0x01 | 2425 | #define USB_CSR0_OUTPKTRDY 0x01 |
2419 | #define USB_CSR0_INPKTRDY 0x02 | 2426 | #define USB_CSR0_INPKTRDY 0x02 |
@@ -2425,11 +2432,11 @@ | |||
2425 | #define USB_CSR0_SVDSETUPEND 0x80 | 2432 | #define USB_CSR0_SVDSETUPEND 0x80 |
2426 | 2433 | ||
2427 | /* Endpoint CSR register bits */ | 2434 | /* Endpoint CSR register bits */ |
2428 | #define USB_INCSRH_AUTOSET 0x80 | 2435 | #define USB_INCSRH_AUTOSET 0x8000 |
2429 | #define USB_INCSRH_ISO 0x40 | 2436 | #define USB_INCSRH_ISO 0x4000 |
2430 | #define USB_INCSRH_MODE 0x20 | 2437 | #define USB_INCSRH_MODE 0x2000 |
2431 | #define USB_INCSRH_DMAREQENAB 0x10 | 2438 | #define USB_INCSRH_DMAREQENAB 0x1000 |
2432 | #define USB_INCSRH_DMAREQMODE 0x04 | 2439 | #define USB_INCSRH_DMAREQMODE 0x0400 |
2433 | #define USB_INCSR_CDT 0x40 | 2440 | #define USB_INCSR_CDT 0x40 |
2434 | #define USB_INCSR_SENTSTALL 0x20 | 2441 | #define USB_INCSR_SENTSTALL 0x20 |
2435 | #define USB_INCSR_SENDSTALL 0x10 | 2442 | #define USB_INCSR_SENDSTALL 0x10 |
@@ -2437,11 +2444,11 @@ | |||
2437 | #define USB_INCSR_UNDERRUN 0x04 | 2444 | #define USB_INCSR_UNDERRUN 0x04 |
2438 | #define USB_INCSR_FFNOTEMPT 0x02 | 2445 | #define USB_INCSR_FFNOTEMPT 0x02 |
2439 | #define USB_INCSR_INPKTRDY 0x01 | 2446 | #define USB_INCSR_INPKTRDY 0x01 |
2440 | #define USB_OUTCSRH_AUTOCLR 0x80 | 2447 | #define USB_OUTCSRH_AUTOCLR 0x8000 |
2441 | #define USB_OUTCSRH_ISO 0x40 | 2448 | #define USB_OUTCSRH_ISO 0x4000 |
2442 | #define USB_OUTCSRH_DMAREQENAB 0x20 | 2449 | #define USB_OUTCSRH_DMAREQENAB 0x2000 |
2443 | #define USB_OUTCSRH_DNYT 0x10 | 2450 | #define USB_OUTCSRH_DNYT 0x1000 |
2444 | #define USB_OUTCSRH_DMAREQMODE 0x08 | 2451 | #define USB_OUTCSRH_DMAREQMODE 0x0800 |
2445 | #define USB_OUTCSR_CDT 0x80 | 2452 | #define USB_OUTCSR_CDT 0x80 |
2446 | #define USB_OUTCSR_SENTSTALL 0x40 | 2453 | #define USB_OUTCSR_SENTSTALL 0x40 |
2447 | #define USB_OUTCSR_SENDSTALL 0x20 | 2454 | #define USB_OUTCSR_SENDSTALL 0x20 |
@@ -2456,6 +2463,11 @@ | |||
2456 | #define USB_TEST_J 0x02 | 2463 | #define USB_TEST_J 0x02 |
2457 | #define USB_TEST_K 0x04 | 2464 | #define USB_TEST_K 0x04 |
2458 | #define USB_TEST_PACKET 0x08 | 2465 | #define USB_TEST_PACKET 0x08 |
2466 | #define USB_TEST_FORCE_HS 0x10 | ||
2467 | #define USB_TEST_FORCE_FS 0x20 | ||
2468 | #define USB_TEST_ALL ( USB_TEST_SE0NAK | USB_TEST_J \ | ||
2469 | | USB_TEST_K | USB_TEST_PACKET \ | ||
2470 | | USB_TEST_FORCE_HS | USB_TEST_FORCE_FS) | ||
2459 | 2471 | ||
2460 | /* DMA control bits */ | 2472 | /* DMA control bits */ |
2461 | #define USB_CNTL_ENA 0x01 | 2473 | #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 @@ | |||
26 | #include "nand_id.h" | 26 | #include "nand_id.h" |
27 | #include "system.h" | 27 | #include "system.h" |
28 | #include "panic.h" | 28 | #include "panic.h" |
29 | #include "kernel.h" | ||
29 | 30 | ||
30 | /* | 31 | /* |
31 | * Standard NAND flash commands | 32 | * Standard NAND flash commands |
@@ -104,6 +105,7 @@ struct nand_param | |||
104 | 105 | ||
105 | static struct nand_info* chip_info = NULL; | 106 | static struct nand_info* chip_info = NULL; |
106 | static struct nand_param internal_param; | 107 | static struct nand_param internal_param; |
108 | static struct mutex nand_mtx; | ||
107 | 109 | ||
108 | static inline void jz_nand_wait_ready(void) | 110 | static inline void jz_nand_wait_ready(void) |
109 | { | 111 | { |
@@ -132,6 +134,8 @@ static inline void jz_nand_read_buf8(void *buf, int count) | |||
132 | 134 | ||
133 | static void jz_nand_write_dma(void *source, unsigned int len, int bw) | 135 | static void jz_nand_write_dma(void *source, unsigned int len, int bw) |
134 | { | 136 | { |
137 | mutex_lock(&nand_mtx); | ||
138 | |||
135 | if(((unsigned int)source < 0xa0000000) && len) | 139 | if(((unsigned int)source < 0xa0000000) && len) |
136 | dma_cache_wback_inv((unsigned long)source, len); | 140 | dma_cache_wback_inv((unsigned long)source, len); |
137 | 141 | ||
@@ -146,10 +150,14 @@ static void jz_nand_write_dma(void *source, unsigned int len, int bw) | |||
146 | REG_DMAC_DCCSR(DMA_NAND_CHANNEL) = (DMAC_DCCSR_EN | DMAC_DCCSR_NDES); | 150 | REG_DMAC_DCCSR(DMA_NAND_CHANNEL) = (DMAC_DCCSR_EN | DMAC_DCCSR_NDES); |
147 | while( REG_DMAC_DTCR(DMA_NAND_CHANNEL) ) | 151 | while( REG_DMAC_DTCR(DMA_NAND_CHANNEL) ) |
148 | yield(); | 152 | yield(); |
153 | |||
154 | mutex_unlock(&nand_mtx); | ||
149 | } | 155 | } |
150 | 156 | ||
151 | static void jz_nand_read_dma(void *target, unsigned int len, int bw) | 157 | static void jz_nand_read_dma(void *target, unsigned int len, int bw) |
152 | { | 158 | { |
159 | mutex_lock(&nand_mtx); | ||
160 | |||
153 | if(((unsigned int)target < 0xa0000000) && len) | 161 | if(((unsigned int)target < 0xa0000000) && len) |
154 | dma_cache_wback_inv((unsigned long)target, len); | 162 | dma_cache_wback_inv((unsigned long)target, len); |
155 | 163 | ||
@@ -163,6 +171,8 @@ static void jz_nand_read_dma(void *target, unsigned int len, int bw) | |||
163 | REG_DMAC_DCCSR(DMA_NAND_CHANNEL) = (DMAC_DCCSR_EN | DMAC_DCCSR_NDES); | 171 | REG_DMAC_DCCSR(DMA_NAND_CHANNEL) = (DMAC_DCCSR_EN | DMAC_DCCSR_NDES); |
164 | while( REG_DMAC_DTCR(DMA_NAND_CHANNEL) ) | 172 | while( REG_DMAC_DTCR(DMA_NAND_CHANNEL) ) |
165 | yield(); | 173 | yield(); |
174 | |||
175 | mutex_unlock(&nand_mtx); | ||
166 | } | 176 | } |
167 | 177 | ||
168 | static inline void jz_nand_read_buf(void *buf, int count, int bw) | 178 | static inline void jz_nand_read_buf(void *buf, int count, int bw) |
@@ -433,6 +443,8 @@ static int jz_nand_init(void) | |||
433 | internal_param.oob_size = chip_info->page_size/32; | 443 | internal_param.oob_size = chip_info->page_size/32; |
434 | internal_param.page_per_block = chip_info->pages_per_block; | 444 | internal_param.page_per_block = chip_info->pages_per_block; |
435 | 445 | ||
446 | mutex_init(&nand_mtx); | ||
447 | |||
436 | return 0; | 448 | return 0; |
437 | } | 449 | } |
438 | 450 | ||
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 @@ | |||
21 | 21 | ||
22 | #include "config.h" | 22 | #include "config.h" |
23 | #include "jz4740.h" | 23 | #include "jz4740.h" |
24 | #include "system.h" | ||
24 | 25 | ||
25 | static unsigned short codec_volume; | 26 | static unsigned short codec_volume; |
26 | static unsigned short codec_base_gain; | 27 | static unsigned short codec_base_gain; |
@@ -29,6 +30,8 @@ static bool HP_on_off_flag; | |||
29 | static int HP_register_value; | 30 | static int HP_register_value; |
30 | static int IS_WRITE_PCM; | 31 | static int IS_WRITE_PCM; |
31 | 32 | ||
33 | static void i2s_codec_set_samplerate(unsigned short rate); | ||
34 | |||
32 | static void i2s_codec_clear(void) | 35 | static void i2s_codec_clear(void) |
33 | { | 36 | { |
34 | REG_ICDC_CDCCR1 = (ICDC_CDCCR1_SW2ON | ICDC_CDCCR1_PDVR | ICDC_CDCCR1_PDVRA | ICDC_CDCCR1_VRCGL | | 37 | 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) | |||
38 | 41 | ||
39 | static void i2s_codec_init(void) | 42 | static void i2s_codec_init(void) |
40 | { | 43 | { |
44 | __aic_enable(); | ||
45 | |||
41 | __aic_select_i2s(); | 46 | __aic_select_i2s(); |
42 | __i2s_internal_codec(); | 47 | __i2s_internal_codec(); |
43 | 48 | ||
44 | __aic_enable(); | ||
45 | |||
46 | __i2s_set_oss_sample_size(16); | 49 | __i2s_set_oss_sample_size(16); |
47 | 50 | ||
48 | REG_ICDC_CDCCR1 = (ICDC_CDCCR1_SW2ON | ICDC_CDCCR1_PDVR | ICDC_CDCCR1_PDVRA | ICDC_CDCCR1_VRCGL | | 51 | 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) | |||
55 | //REG_ICDC_CDCCR2 = (ICDC_CDCCR2_AINVOL(ICDC_CDCCR2_AINVOL_DB(0)) | ICDC_CDCCR2_SMPR(ICDC_CDCCR2_SMPR_48) | | 58 | //REG_ICDC_CDCCR2 = (ICDC_CDCCR2_AINVOL(ICDC_CDCCR2_AINVOL_DB(0)) | ICDC_CDCCR2_SMPR(ICDC_CDCCR2_SMPR_48) | |
56 | REG_ICDC_CDCCR2 = (ICDC_CDCCR2_AINVOL(23) | ICDC_CDCCR2_SMPR(ICDC_CDCCR2_SMPR_48) | | 59 | REG_ICDC_CDCCR2 = (ICDC_CDCCR2_AINVOL(23) | ICDC_CDCCR2_SMPR(ICDC_CDCCR2_SMPR_48) | |
57 | ICDC_CDCCR2_HPVOL(ICDC_CDCCR2_HPVOL_6)); | 60 | ICDC_CDCCR2_HPVOL(ICDC_CDCCR2_HPVOL_6)); |
61 | |||
62 | REG_ICDC_CDCCR1 &= 0xfffffffc; | ||
63 | |||
64 | mdelay(15); | ||
65 | REG_ICDC_CDCCR1 &= 0xffecffff; | ||
66 | REG_ICDC_CDCCR1 |= (ICDC_CDCCR1_EDAC | ICDC_CDCCR1_HPCG); | ||
67 | |||
68 | mdelay(600); | ||
69 | REG_ICDC_CDCCR1 &= 0xfff7ecff; | ||
70 | |||
71 | mdelay(2); | ||
72 | |||
73 | /* CDCCR1.ELININ=0, CDCCR1.EMIC=0, CDCCR1.EADC=0, CDCCR1.SW1ON=0, CDCCR1.EDAC=1, CDCCR1.SW2ON=1, CDCCR1.HPMUTE=0 */ | ||
74 | REG_ICDC_CDCCR1 = (REG_ICDC_CDCCR1 & ~((1 << 29) | (1 << 28) | (1 << 26) | (1 << 27) | (1 << 14))) | ((1 << 24) | (1 << 25)); | ||
75 | |||
76 | REG_ICDC_CDCCR2 = ((REG_ICDC_CDCCR2 & ~(0x3)) | 3); | ||
77 | |||
78 | i2s_codec_set_samplerate(44100); | ||
79 | |||
58 | HP_on_off_flag = 0; /* HP is off */ | 80 | HP_on_off_flag = 0; /* HP is off */ |
59 | } | 81 | } |
60 | 82 | ||
61 | static void i2s_codec_set_mic(unsigned short v) /* 0 <= v <= 100 */ | 83 | static void i2s_codec_set_mic(unsigned short v) /* 0 <= v <= 100 */ |
62 | { | 84 | { |
63 | v = v & 0xff; | 85 | v &= 0xff; |
64 | if(v < 0) | 86 | |
65 | v = 0; | ||
66 | if(v > 100) | 87 | if(v > 100) |
67 | v = 100; | 88 | v = 100; |
68 | codec_mic_gain = 31 * v/100; | 89 | codec_mic_gain = 31 * v/100; |
@@ -72,9 +93,8 @@ static void i2s_codec_set_mic(unsigned short v) /* 0 <= v <= 100 */ | |||
72 | 93 | ||
73 | static void i2s_codec_set_bass(unsigned short v) /* 0 <= v <= 100 */ | 94 | static void i2s_codec_set_bass(unsigned short v) /* 0 <= v <= 100 */ |
74 | { | 95 | { |
75 | v = v & 0xff; | 96 | v &= 0xff; |
76 | if(v < 0) | 97 | |
77 | v = 0; | ||
78 | if(v > 100) | 98 | if(v > 100) |
79 | v = 100; | 99 | v = 100; |
80 | 100 | ||
@@ -92,9 +112,8 @@ static void i2s_codec_set_bass(unsigned short v) /* 0 <= v <= 100 */ | |||
92 | 112 | ||
93 | static void i2s_codec_set_volume(unsigned short v) /* 0 <= v <= 100 */ | 113 | static void i2s_codec_set_volume(unsigned short v) /* 0 <= v <= 100 */ |
94 | { | 114 | { |
95 | v = v & 0xff; | 115 | v &= 0xff; |
96 | if(v < 0) | 116 | |
97 | v = 0; | ||
98 | if(v > 100) | 117 | if(v > 100) |
99 | v = 100; | 118 | v = 100; |
100 | 119 | ||
@@ -114,6 +133,7 @@ static unsigned short i2s_codec_get_bass(void) | |||
114 | { | 133 | { |
115 | unsigned short val; | 134 | unsigned short val; |
116 | int ret; | 135 | int ret; |
136 | |||
117 | if(codec_base_gain == 0) | 137 | if(codec_base_gain == 0) |
118 | val = 0; | 138 | val = 0; |
119 | if(codec_base_gain == 1) | 139 | if(codec_base_gain == 1) |
@@ -124,7 +144,9 @@ static unsigned short i2s_codec_get_bass(void) | |||
124 | val = 75; | 144 | val = 75; |
125 | 145 | ||
126 | ret = val << 8; | 146 | ret = val << 8; |
127 | val = val | ret; | 147 | val |= ret; |
148 | |||
149 | return val; | ||
128 | } | 150 | } |
129 | 151 | ||
130 | static unsigned short i2s_codec_get_mic(void) | 152 | static unsigned short i2s_codec_get_mic(void) |
@@ -133,7 +155,9 @@ static unsigned short i2s_codec_get_mic(void) | |||
133 | int ret; | 155 | int ret; |
134 | val = 100 * codec_mic_gain / 31; | 156 | val = 100 * codec_mic_gain / 31; |
135 | ret = val << 8; | 157 | ret = val << 8; |
136 | val = val | ret; | 158 | val |= ret; |
159 | |||
160 | return val; | ||
137 | } | 161 | } |
138 | 162 | ||
139 | static unsigned short i2s_codec_get_volume(void) | 163 | static unsigned short i2s_codec_get_volume(void) |
@@ -151,7 +175,8 @@ static unsigned short i2s_codec_get_volume(void) | |||
151 | val = 75; | 175 | val = 75; |
152 | 176 | ||
153 | ret = val << 8; | 177 | ret = val << 8; |
154 | val = val | ret; | 178 | val |= ret; |
179 | |||
155 | return val; | 180 | return val; |
156 | } | 181 | } |
157 | 182 | ||
@@ -271,10 +296,15 @@ void audiohw_mute(bool mute) | |||
271 | 296 | ||
272 | void audiohw_preinit(void) | 297 | void audiohw_preinit(void) |
273 | { | 298 | { |
274 | i2s_reset(); | 299 | i2s_codec_init(); |
275 | } | 300 | } |
276 | 301 | ||
277 | void audiohw_postinit(void) | 302 | void audiohw_postinit(void) |
278 | { | 303 | { |
279 | audiohw_mute(false); | 304 | audiohw_mute(false); |
280 | } | 305 | } |
306 | |||
307 | void audiohw_init(void) | ||
308 | { | ||
309 | |||
310 | } | ||
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 @@ | |||
26 | #include "system.h" | 26 | #include "system.h" |
27 | #include "kernel.h" | 27 | #include "kernel.h" |
28 | 28 | ||
29 | static volatile bool _lcd_on = false; | 29 | static volatile bool lcd_is_on = false; |
30 | static volatile bool lcd_poweroff = false; | ||
31 | static struct mutex lcd_mtx; | 30 | static struct mutex lcd_mtx; |
32 | 31 | ||
33 | /* LCD init */ | 32 | /* LCD init */ |
34 | void lcd_init_device(void) | 33 | void lcd_init_device(void) |
35 | { | 34 | { |
36 | lcd_init_controller(); | 35 | lcd_init_controller(); |
37 | _lcd_on = true; | 36 | lcd_is_on = true; |
38 | mutex_init(&lcd_mtx); | 37 | mutex_init(&lcd_mtx); |
39 | } | 38 | } |
40 | 39 | ||
@@ -48,16 +47,16 @@ void lcd_enable(bool state) | |||
48 | else | 47 | else |
49 | lcd_off(); | 48 | lcd_off(); |
50 | 49 | ||
51 | _lcd_on = state; | 50 | lcd_is_on = state; |
52 | } | 51 | } |
53 | 52 | ||
54 | bool lcd_enabled(void) | 53 | bool lcd_enabled(void) |
55 | { | 54 | { |
56 | return _lcd_on; | 55 | return lcd_is_on; |
57 | } | 56 | } |
58 | 57 | ||
59 | /* Don't switch threads when in interrupt mode! */ | 58 | /* Don't switch threads when in interrupt mode! */ |
60 | static void lcd_lock(void) | 59 | static inline void lcd_lock(void) |
61 | { | 60 | { |
62 | if(LIKELY(!in_interrupt_mode())) | 61 | if(LIKELY(!in_interrupt_mode())) |
63 | mutex_lock(&lcd_mtx); | 62 | mutex_lock(&lcd_mtx); |
@@ -65,10 +64,19 @@ static void lcd_lock(void) | |||
65 | while( !(REG_DMAC_DCCSR(DMA_LCD_CHANNEL) & DMAC_DCCSR_TT)); | 64 | while( !(REG_DMAC_DCCSR(DMA_LCD_CHANNEL) & DMAC_DCCSR_TT)); |
66 | } | 65 | } |
67 | 66 | ||
68 | static void lcd_unlock(void) | 67 | static inline void lcd_unlock(void) |
69 | { | 68 | { |
70 | if(LIKELY(!in_interrupt_mode())) | 69 | if(LIKELY(!in_interrupt_mode())) |
71 | mutex_unlock(&lcd_mtx); | 70 | mutex_unlock(&lcd_mtx); |
71 | } | ||
72 | |||
73 | static inline void lcd_wait(void) | ||
74 | { | ||
75 | if(LIKELY(!in_interrupt_mode())) | ||
76 | { | ||
77 | while( !(REG_DMAC_DCCSR(DMA_LCD_CHANNEL) & DMAC_DCCSR_TT) ) | ||
78 | yield(); | ||
79 | } | ||
72 | else | 80 | else |
73 | while( !(REG_DMAC_DCCSR(DMA_LCD_CHANNEL) & DMAC_DCCSR_TT)); | 81 | while( !(REG_DMAC_DCCSR(DMA_LCD_CHANNEL) & DMAC_DCCSR_TT)); |
74 | } | 82 | } |
@@ -98,13 +106,7 @@ void lcd_update_rect(int x, int y, int width, int height) | |||
98 | REG_SLCD_CTRL |= SLCD_CTRL_DMA_EN; | 106 | REG_SLCD_CTRL |= SLCD_CTRL_DMA_EN; |
99 | REG_DMAC_DCCSR(DMA_LCD_CHANNEL) |= DMAC_DCCSR_EN; | 107 | REG_DMAC_DCCSR(DMA_LCD_CHANNEL) |= DMAC_DCCSR_EN; |
100 | 108 | ||
101 | if(LIKELY(!in_interrupt_mode())) | 109 | lcd_wait(); |
102 | { | ||
103 | while( !(REG_DMAC_DCCSR(DMA_LCD_CHANNEL) & DMAC_DCCSR_TT) ) | ||
104 | yield(); | ||
105 | } | ||
106 | else | ||
107 | while( !(REG_DMAC_DCCSR(DMA_LCD_CHANNEL) & DMAC_DCCSR_TT)); | ||
108 | 110 | ||
109 | REG_DMAC_DCCSR(DMA_LCD_CHANNEL) &= ~DMAC_DCCSR_EN; | 111 | REG_DMAC_DCCSR(DMA_LCD_CHANNEL) &= ~DMAC_DCCSR_EN; |
110 | 112 | ||
@@ -119,7 +121,7 @@ void lcd_update_rect(int x, int y, int width, int height) | |||
119 | This must be called after all other LCD functions that change the display. */ | 121 | This must be called after all other LCD functions that change the display. */ |
120 | void lcd_update(void) | 122 | void lcd_update(void) |
121 | { | 123 | { |
122 | if (!_lcd_on) | 124 | if (!lcd_is_on) |
123 | return; | 125 | return; |
124 | 126 | ||
125 | lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); | 127 | 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 @@ | |||
25 | #include "button.h" | 25 | #include "button.h" |
26 | #include "button-target.h" | 26 | #include "button-target.h" |
27 | #include "powermgmt.h" | 27 | #include "powermgmt.h" |
28 | #include "kernel.h" | ||
28 | 29 | ||
29 | #define BTN_OFF (1 << 29) | 30 | #define BTN_OFF (1 << 29) |
30 | #define BTN_VOL_DOWN (1 << 27) | 31 | #define BTN_VOL_DOWN (1 << 27) |
@@ -36,21 +37,22 @@ | |||
36 | 37 | ||
37 | 38 | ||
38 | #define TS_AD_COUNT 5 | 39 | #define TS_AD_COUNT 5 |
39 | #define M_SADC_CFG_SNUM ((TS_AD_COUNT - 1) << SADC_CFG_SNUM_BIT) | 40 | #define SADC_CFG_SNUM ((TS_AD_COUNT - 1) << SADC_CFG_SNUM_BIT) |
40 | 41 | ||
41 | #define SADC_CFG_INIT ( \ | 42 | #define SADC_CFG_INIT ( \ |
42 | (2 << SADC_CFG_CLKOUT_NUM_BIT) | \ | 43 | (2 << SADC_CFG_CLKOUT_NUM_BIT) | \ |
43 | SADC_CFG_XYZ1Z2 | \ | 44 | SADC_CFG_XYZ1Z2 | \ |
44 | M_SADC_CFG_SNUM | \ | 45 | SADC_CFG_SNUM | \ |
45 | (2 << SADC_CFG_CLKDIV_BIT) | \ | 46 | (2 << SADC_CFG_CLKDIV_BIT) | \ |
46 | SADC_CFG_PBAT_HIGH | \ | 47 | SADC_CFG_PBAT_HIGH | \ |
47 | SADC_CFG_CMD_INT_PEN \ | 48 | SADC_CFG_CMD_INT_PEN \ |
48 | ) | 49 | ) |
49 | 50 | ||
50 | static short x_pos = -1, y_pos = -1, datacount = 0; | 51 | static signed int x_pos, y_pos; |
52 | static int datacount = 0, cur_touch = 0; | ||
51 | static bool pen_down = false; | 53 | static bool pen_down = false; |
52 | static int cur_touch = 0; | 54 | static volatile unsigned short bat_val = 0; |
53 | static unsigned short bat_val = 0; | 55 | static struct mutex battery_mtx; |
54 | 56 | ||
55 | static enum touchscreen_mode current_mode = TOUCHSCREEN_POINT; | 57 | static enum touchscreen_mode current_mode = TOUCHSCREEN_POINT; |
56 | static const int touchscreen_buttons[3][3] = | 58 | static const int touchscreen_buttons[3][3] = |
@@ -93,15 +95,21 @@ const unsigned short percent_to_volt_charge[11] = | |||
93 | unsigned int battery_adc_voltage(void) | 95 | unsigned int battery_adc_voltage(void) |
94 | { | 96 | { |
95 | register unsigned short dummy; | 97 | register unsigned short dummy; |
98 | |||
99 | mutex_lock(&battery_mtx); | ||
100 | |||
96 | dummy = REG_SADC_BATDAT; | 101 | dummy = REG_SADC_BATDAT; |
97 | dummy = REG_SADC_BATDAT; | 102 | dummy = REG_SADC_BATDAT; |
98 | 103 | ||
99 | bat_val = 0; | 104 | bat_val = 0; |
100 | REG_SADC_ENA |= SADC_ENA_PBATEN; | 105 | REG_SADC_ENA |= SADC_ENA_PBATEN; |
101 | 106 | ||
107 | /* Primitive wakeup event */ | ||
102 | while(bat_val == 0) | 108 | while(bat_val == 0) |
103 | yield(); | 109 | yield(); |
104 | 110 | ||
111 | mutex_unlock(&battery_mtx); | ||
112 | |||
105 | return (bat_val*BATTERY_SCALE_FACTOR)>>12; | 113 | return (bat_val*BATTERY_SCALE_FACTOR)>>12; |
106 | } | 114 | } |
107 | 115 | ||
@@ -127,6 +135,8 @@ void button_init_device(void) | |||
127 | __gpio_as_input(32*3 + 16); | 135 | __gpio_as_input(32*3 + 16); |
128 | __gpio_as_input(32*3 + 1); | 136 | __gpio_as_input(32*3 + 1); |
129 | __gpio_as_input(32*3 + 0); | 137 | __gpio_as_input(32*3 + 0); |
138 | |||
139 | mutex_init(&battery_mtx); | ||
130 | } | 140 | } |
131 | 141 | ||
132 | static int touch_to_pixels(short x, short y) | 142 | static int touch_to_pixels(short x, short y) |
@@ -162,6 +172,7 @@ int button_read_device(int *data) | |||
162 | { | 172 | { |
163 | int ret = 0, tmp; | 173 | int ret = 0, tmp; |
164 | 174 | ||
175 | /* Filter button events out if HOLD button is pressed at firmware/ level */ | ||
165 | if((~REG_GPIO_PXPIN(3)) & BTN_HOLD) | 176 | if((~REG_GPIO_PXPIN(3)) & BTN_HOLD) |
166 | return 0; | 177 | return 0; |
167 | 178 | ||
@@ -186,7 +197,7 @@ int button_read_device(int *data) | |||
186 | else if(pen_down) | 197 | else if(pen_down) |
187 | { | 198 | { |
188 | ret |= BUTTON_TOUCH; | 199 | ret |= BUTTON_TOUCH; |
189 | if(data != NULL) | 200 | if(data != NULL && cur_touch != 0) |
190 | *data = cur_touch; | 201 | *data = cur_touch; |
191 | } | 202 | } |
192 | 203 | ||
@@ -226,18 +237,16 @@ void SADC(void) | |||
226 | REG_SADC_CTRL &= (~SADC_CTRL_PENDM ); | 237 | REG_SADC_CTRL &= (~SADC_CTRL_PENDM ); |
227 | REG_SADC_CTRL |= SADC_CTRL_PENUM; | 238 | REG_SADC_CTRL |= SADC_CTRL_PENUM; |
228 | pen_down = false; | 239 | pen_down = false; |
229 | x_pos = -1; | 240 | datacount = 0; |
230 | y_pos = -1; | ||
231 | cur_touch = 0; | 241 | cur_touch = 0; |
232 | } | 242 | } |
233 | if(state & SADC_CTRL_TSRDYM) | 243 | if(state & SADC_CTRL_TSRDYM) |
234 | { | 244 | { |
235 | unsigned int dat; | 245 | unsigned int dat; |
236 | unsigned short xData, yData; | 246 | unsigned short xData, yData; |
237 | short tsz1Data, tsz2Data; | 247 | signed short tsz1Data, tsz2Data; |
238 | 248 | ||
239 | dat = REG_SADC_TSDAT; | 249 | dat = REG_SADC_TSDAT; |
240 | |||
241 | xData = (dat >> 0) & 0xFFF; | 250 | xData = (dat >> 0) & 0xFFF; |
242 | yData = (dat >> 16) & 0xFFF; | 251 | yData = (dat >> 16) & 0xFFF; |
243 | 252 | ||
@@ -245,34 +254,30 @@ void SADC(void) | |||
245 | tsz1Data = (dat >> 0) & 0xFFF; | 254 | tsz1Data = (dat >> 0) & 0xFFF; |
246 | tsz2Data = (dat >> 16) & 0xFFF; | 255 | tsz2Data = (dat >> 16) & 0xFFF; |
247 | 256 | ||
248 | if( !pen_down ) | 257 | if(!pen_down) |
249 | return; | 258 | return; |
250 | 259 | ||
251 | tsz1Data = tsz2Data - tsz1Data; | 260 | tsz1Data = tsz2Data - tsz1Data; |
252 | 261 | ||
253 | if((tsz1Data > 15) || (tsz1Data < -15)) | 262 | if((tsz1Data > 100) || (tsz1Data < -100)) |
254 | { | 263 | { |
255 | if(x_pos == -1) | 264 | if(datacount == 0) |
265 | { | ||
256 | x_pos = xData; | 266 | x_pos = xData; |
257 | else | ||
258 | x_pos = (x_pos + xData) / 2; | ||
259 | |||
260 | if(y_pos == -1) | ||
261 | y_pos = yData; | 267 | y_pos = yData; |
268 | } | ||
262 | else | 269 | else |
263 | y_pos = (y_pos + yData) / 2; | 270 | { |
271 | x_pos += xData; | ||
272 | y_pos += yData; | ||
273 | } | ||
264 | } | 274 | } |
265 | 275 | ||
266 | datacount++; | 276 | datacount++; |
267 | 277 | ||
268 | if(datacount > TS_AD_COUNT - 1) | 278 | if(datacount >= TS_AD_COUNT) |
269 | { | 279 | { |
270 | if(x_pos != -1) | 280 | cur_touch = touch_to_pixels(x_pos/datacount, y_pos/datacount); |
271 | { | ||
272 | cur_touch = touch_to_pixels(x_pos, y_pos); | ||
273 | x_pos = -1; | ||
274 | y_pos = -1; | ||
275 | } | ||
276 | datacount = 0; | 281 | datacount = 0; |
277 | } | 282 | } |
278 | } | 283 | } |
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 @@ | |||
24 | 24 | ||
25 | #include "config.h" | 25 | #include "config.h" |
26 | 26 | ||
27 | #define __gpio_as_usb_detect() \ | ||
28 | do { \ | ||
29 | REG_GPIO_PXFUNS(3) = 0x10000000; \ | ||
30 | REG_GPIO_PXSELS(3) = 0x10000000; \ | ||
31 | REG_GPIO_PXPES(3) = 0x10000000; \ | ||
32 | } while (0) | ||
33 | |||
34 | #define GPIO_UDC_DETE (32 * 3 + 28) | 27 | #define GPIO_UDC_DETE (32 * 3 + 28) |
35 | #define IRQ_GPIO_UDC_DETE (IRQ_GPIO_0 + GPIO_UDC_DETE) | 28 | #define IRQ_GPIO_UDC_DETE (IRQ_GPIO_0 + GPIO_UDC_DETE) |
36 | 29 | ||
37 | static inline void usb_init_gpio(void) | 30 | #define USB_INIT_GPIO() \ |
38 | { | 31 | { \ |
39 | __gpio_as_usb_detect(); | 32 | REG_GPIO_PXFUNS(3) = 0x10000000; \ |
40 | system_enable_irq(IRQ_UDC); | 33 | REG_GPIO_PXSELS(3) = 0x10000000; \ |
41 | __gpio_as_input(GPIO_UDC_DETE); | 34 | REG_GPIO_PXPES(3) = 0x10000000; \ |
35 | __gpio_as_input(GPIO_UDC_DETE); \ | ||
42 | } | 36 | } |
43 | 37 | ||
38 | #define USB_DRV_CONNECTED() (__gpio_get_pin(GPIO_UDC_DETE) == 1) | ||
39 | |||
44 | int usb_detect(void); | 40 | int usb_detect(void); |
45 | void usb_init_device(void); | 41 | void usb_init_device(void); |
46 | bool usb_drv_connected(void); | 42 | 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 @@ | |||
27 | #include "pcm.h" | 27 | #include "pcm.h" |
28 | #include "jz4740.h" | 28 | #include "jz4740.h" |
29 | 29 | ||
30 | |||
30 | /**************************************************************************** | 31 | /**************************************************************************** |
31 | ** Playback DMA transfer | 32 | ** Playback DMA transfer |
32 | **/ | 33 | **/ |
33 | 34 | ||
34 | void pcm_postinit(void) | 35 | void pcm_postinit(void) |
35 | { | 36 | { |
36 | audiohw_postinit(); /* implemented not for all codecs */ | 37 | audiohw_postinit(); |
37 | pcm_apply_settings(); | 38 | pcm_apply_settings(); |
38 | } | 39 | } |
39 | 40 | ||
@@ -61,29 +62,55 @@ void pcm_set_frequency(unsigned int frequency) | |||
61 | { | 62 | { |
62 | (void) frequency; | 63 | (void) frequency; |
63 | /* TODO */ | 64 | /* TODO */ |
65 | |||
66 | /* | ||
67 | __i2s_set_oss_sample_size(frequency); | ||
68 | i2s_codec_set_samplerate(frequency); | ||
69 | */ | ||
64 | } | 70 | } |
65 | 71 | ||
66 | static void play_start_pcm(void) | 72 | static void play_start_pcm(void) |
67 | { | 73 | { |
68 | pcm_apply_settings(); | 74 | pcm_apply_settings(); |
69 | 75 | ||
70 | /* TODO */ | 76 | __aic_enable_transmit_dma(); |
77 | __aic_enable_replay(); | ||
78 | |||
79 | REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) |= DMAC_DCCSR_EN; | ||
71 | } | 80 | } |
72 | 81 | ||
73 | static void play_stop_pcm(void) | 82 | static void play_stop_pcm(void) |
74 | { | 83 | { |
75 | /* TODO */ | 84 | REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) = (REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) | DMAC_DCCSR_HLT) & ~DMAC_DCCSR_EN; |
85 | |||
86 | __aic_disable_transmit_dma(); | ||
87 | __aic_disable_replay(); | ||
76 | } | 88 | } |
77 | 89 | ||
78 | void pcm_play_dma_start(const void *addr, size_t size) | 90 | void pcm_play_dma_start(const void *addr, size_t size) |
79 | { | 91 | { |
80 | (void)addr; | 92 | REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) = 0; |
81 | (void)size; | 93 | REG_DMAC_DSAR(DMA_AIC_TX_CHANNEL) = PHYSADDR((unsigned long)addr); |
82 | /* TODO */ | 94 | REG_DMAC_DTAR(DMA_AIC_TX_CHANNEL) = PHYSADDR((unsigned long)AIC_DR); |
95 | REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL) = size; | ||
96 | REG_DMAC_DRSR(DMA_AIC_TX_CHANNEL) = DMAC_DRSR_RS_AICOUT; | ||
97 | 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 | ||
98 | | DMAC_DCMD_TIE); | ||
83 | 99 | ||
84 | play_start_pcm(); | 100 | play_start_pcm(); |
85 | } | 101 | } |
86 | 102 | ||
103 | void DMA_CALLBACK(DMA_AIC_TX_CHANNEL)(void) | ||
104 | { | ||
105 | if( REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) & DMAC_DCCSR_TT ) | ||
106 | __aic_disable_transmit_dma(); | ||
107 | } | ||
108 | |||
109 | size_t pcm_get_bytes_waiting(void) | ||
110 | { | ||
111 | return REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL); | ||
112 | } | ||
113 | |||
87 | void pcm_play_dma_stop(void) | 114 | void pcm_play_dma_stop(void) |
88 | { | 115 | { |
89 | play_stop_pcm(); | 116 | play_stop_pcm(); |
@@ -110,12 +137,6 @@ void pcm_play_dma_pause(bool pause) | |||
110 | 137 | ||
111 | } | 138 | } |
112 | 139 | ||
113 | size_t pcm_get_bytes_waiting(void) | ||
114 | { | ||
115 | /* TODO */ | ||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | #ifdef HAVE_RECORDING | 140 | #ifdef HAVE_RECORDING |
120 | /* TODO */ | 141 | /* TODO */ |
121 | void pcm_rec_dma_init(void) | 142 | 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) | |||
372 | } | 372 | } |
373 | 373 | ||
374 | void exception_handler(void* stack_ptr, unsigned int cause, unsigned int epc) | 374 | void exception_handler(void* stack_ptr, unsigned int cause, unsigned int epc) |
375 | { | 375 | { |
376 | panicf("Exception occurred: %s [0x%08x] at 0x%08x (stack at 0x%08x)", parse_exception(cause), cause, epc, (unsigned int)stack_ptr); | 376 | panicf("Exception occurred: %s [0x%08x] at 0x%08x (stack at 0x%08x)", parse_exception(cause), cause, epc, (unsigned int)stack_ptr); |
377 | } | 377 | } |
378 | 378 | ||
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); | |||
108 | #define DMA_USB_CHANNEL 2 | 108 | #define DMA_USB_CHANNEL 2 |
109 | #define DMA_AIC_TX_CHANNEL 3 | 109 | #define DMA_AIC_TX_CHANNEL 3 |
110 | 110 | ||
111 | #define XDMA_CALLBACK(n) DMA ## n | ||
112 | #define DMA_CALLBACK(n) XDMA_CALLBACK(n) | ||
113 | |||
111 | #endif /* __SYSTEM_TARGET_H_ */ | 114 | #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 @@ | |||
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | 21 | ||
22 | #include "config.h" | 22 | #include "config.h" |
23 | #include "string.h" | ||
24 | #include "system.h" | 23 | #include "system.h" |
25 | #include "usb_ch9.h" | 24 | #include "usb_ch9.h" |
26 | #include "usb_drv.h" | 25 | #include "usb_drv.h" |
@@ -29,16 +28,18 @@ | |||
29 | #include "jz4740.h" | 28 | #include "jz4740.h" |
30 | #include "thread.h" | 29 | #include "thread.h" |
31 | 30 | ||
32 | #if 1 | 31 | //#define DEBUGF printf |
32 | #define DEBUGF | ||
33 | 33 | ||
34 | #define EP1_INTR_BIT 2 | 34 | #define USB_EP0_IDLE 0 |
35 | #define EP_FIFO_NOEMPTY 2 | 35 | #define USB_EP0_RX 1 |
36 | #define USB_EP0_TX 2 | ||
36 | 37 | ||
37 | #define IS_CACHE(x) (x < 0xa0000000) | 38 | #define EP_BUF_LEFT(ep) (ep->length - ep->sent) |
38 | 39 | #define EP_PTR(ep) ((void*)((unsigned int)ep->buf + ep->sent)) | |
39 | #define USB_EP0_IDLE 0 | 40 | #define EP_NUMBER(ep) (((int)ep - (int)&endpoints[0])/sizeof(struct usb_endpoint)) |
40 | #define USB_EP0_RX 1 | 41 | #define TOTAL_EP() (sizeof(endpoints)/sizeof(struct usb_endpoint)) |
41 | #define USB_EP0_TX 2 | 42 | #define EP_IS_IN(ep) (EP_NUMBER(ep)%2) |
42 | 43 | ||
43 | enum ep_type | 44 | enum ep_type |
44 | { | 45 | { |
@@ -49,27 +50,29 @@ struct usb_endpoint | |||
49 | { | 50 | { |
50 | void *buf; | 51 | void *buf; |
51 | unsigned int length; | 52 | unsigned int length; |
52 | void *ptr; | 53 | union |
54 | { | ||
55 | unsigned int sent; | ||
56 | unsigned int received; | ||
57 | }; | ||
53 | 58 | ||
54 | const enum ep_type type; | 59 | const enum ep_type type; |
55 | const bool use_dma; | 60 | const bool use_dma; |
56 | const bool in; | ||
57 | 61 | ||
58 | const void *fifo_addr; | 62 | const unsigned int fifo_addr; |
59 | unsigned short fifo_size; | 63 | unsigned short fifo_size; |
60 | }; | 64 | }; |
61 | 65 | ||
62 | static unsigned char ep0_rx_buf[64]; | 66 | static unsigned char ep0_rx_buf[64]; |
63 | static unsigned char ep0_tx_buf[64]; | ||
64 | static unsigned char ep0state = USB_EP0_IDLE; | 67 | static unsigned char ep0state = USB_EP0_IDLE; |
65 | static struct usb_endpoint endpoints[] = | 68 | static struct usb_endpoint endpoints[] = |
66 | { | 69 | { |
67 | /* buf length ptr type use_dma in fifo_addr fifo_size */ | 70 | /* buf length sent type use_dma fifo_addr fifo_size */ |
68 | {&ep0_rx_buf, 0, &ep0_rx_buf, ep_control, false, true, (void*)USB_FIFO_EP0, 64 }, | 71 | {&ep0_rx_buf, 0, {0}, ep_control, false, USB_FIFO_EP0, 64 }, |
69 | {&ep0_tx_buf, 0, &ep0_tx_buf, ep_control, false, false, (void*)USB_FIFO_EP0, 64 }, | 72 | {NULL, 0, {0}, ep_control, false, USB_FIFO_EP0, 64 }, |
70 | {NULL, 0, NULL, ep_bulk, true, true, (void*)USB_FIFO_EP1, 512}, | 73 | {NULL, 0, {0}, ep_bulk, true, USB_FIFO_EP1, 512}, |
71 | {NULL, 0, NULL, ep_bulk, true, false, (void*)USB_FIFO_EP1, 512}, | 74 | {NULL, 0, {0}, ep_bulk, true, USB_FIFO_EP1, 512}, |
72 | {NULL, 0, NULL, ep_interrupt, false, true, (void*)USB_FIFO_EP2, 64 } | 75 | {NULL, 0, {0}, ep_interrupt, false, USB_FIFO_EP2, 64 } |
73 | }; | 76 | }; |
74 | 77 | ||
75 | static inline void select_endpoint(int ep) | 78 | static inline void select_endpoint(int ep) |
@@ -78,103 +81,109 @@ static inline void select_endpoint(int ep) | |||
78 | } | 81 | } |
79 | 82 | ||
80 | static void readFIFO(struct usb_endpoint *ep, unsigned int size) | 83 | static void readFIFO(struct usb_endpoint *ep, unsigned int size) |
81 | { | 84 | { |
82 | unsigned int *d = (unsigned int *)ep->ptr; | 85 | DEBUGF("readFIFO(EP%d, %d)", EP_NUMBER(ep), size); |
83 | unsigned int s; | 86 | |
84 | s = (size + 3) >> 2; | 87 | register unsigned char *ptr = (unsigned char*)EP_PTR(ep); |
85 | while (s--) | 88 | register unsigned int *ptr32 = (unsigned int*)ptr; |
86 | *d++ = REG32(ep->fifo_addr); | 89 | register unsigned int s = size / 4; |
90 | register unsigned int x; | ||
91 | |||
92 | if(size > 0) | ||
93 | { | ||
94 | if( ((int)ptr & 3) == 0 ) | ||
95 | { | ||
96 | while(s--) | ||
97 | *ptr32++ = REG32(ep->fifo_addr); | ||
98 | |||
99 | ptr = (unsigned char*)ptr32; | ||
100 | } | ||
101 | else | ||
102 | { | ||
103 | while(s--) | ||
104 | { | ||
105 | x = REG32(ep->fifo_addr); | ||
106 | *ptr++ = (x >> 0) & 0xff; | ||
107 | *ptr++ = (x >> 8) & 0xff; | ||
108 | *ptr++ = (x >> 16) & 0xff; | ||
109 | *ptr++ = (x >> 24) & 0xff; | ||
110 | } | ||
111 | } | ||
112 | |||
113 | s = size & 3; | ||
114 | while(s--) | ||
115 | *ptr++ = REG8(ep->fifo_addr); | ||
116 | } | ||
87 | } | 117 | } |
88 | 118 | ||
89 | static void writeFIFO(struct usb_endpoint *ep, unsigned int size) | 119 | static void writeFIFO(struct usb_endpoint *ep, unsigned int size) |
90 | { | 120 | { |
91 | unsigned int *d = (unsigned int *)ep->ptr; | 121 | DEBUGF("writeFIFO(EP%d, %d)", EP_NUMBER(ep), size); |
92 | unsigned char *c; | 122 | |
93 | int s, q; | 123 | register unsigned int *d = (unsigned int *)EP_PTR(ep); |
124 | register unsigned char *c; | ||
125 | register int s; | ||
94 | 126 | ||
95 | if (size > 0) | 127 | if (size > 0) |
96 | { | 128 | { |
97 | s = size >> 2; | 129 | s = size >> 2; |
98 | while (s--) | 130 | while (s--) |
99 | REG32(ep->fifo_addr) = *d++; | 131 | REG32(ep->fifo_addr) = *d++; |
100 | 132 | ||
101 | q = size & 3; | 133 | if ( (s = size & 3) ) |
102 | if (q) | ||
103 | { | 134 | { |
104 | c = (unsigned char *)d; | 135 | c = (unsigned char *)d; |
105 | while (q--) | 136 | while (s--) |
106 | REG8(ep->fifo_addr) = *c++; | 137 | REG8(ep->fifo_addr) = *c++; |
107 | } | 138 | } |
108 | } | ||
109 | } | ||
110 | |||
111 | static void sendPKT(int ep_nr, const unsigned char* ptr, unsigned int size) | ||
112 | { | ||
113 | struct usb_endpoint *ep = &endpoints[ep_nr]; | ||
114 | |||
115 | if (ep_nr != 0) | ||
116 | { | ||
117 | ep->buf = (void*)ptr; | ||
118 | ep->ptr = (void*)ptr; | ||
119 | ep->length = size; | ||
120 | select_endpoint(ep_nr); | ||
121 | if (size <= ep->fifo_size) | ||
122 | { | ||
123 | writeFIFO(ep, size); | ||
124 | REG_USB_REG_INCSR |= USB_INCSR_INPKTRDY; | ||
125 | ep->ptr = ep->buf + size; | ||
126 | } | ||
127 | else | ||
128 | { | ||
129 | writeFIFO(ep, ep->fifo_size); | ||
130 | REG_USB_REG_INCSR |= USB_INCSR_INPKTRDY; | ||
131 | ep->ptr += ep->fifo_size; | ||
132 | } | ||
133 | } | ||
134 | else /* EP0 */ | ||
135 | { | ||
136 | ep->length = size; | ||
137 | ep->ptr = ep->buf; | ||
138 | memcpy(ep->buf, ptr, size); | ||
139 | ep0state = USB_EP0_TX; | ||
140 | } | 139 | } |
141 | } | 140 | } |
142 | 141 | ||
143 | static void getPKT(int ep_nr, const unsigned char *ptr, unsigned int size) | 142 | static void EP0_send(void) |
144 | { | 143 | { |
145 | struct usb_endpoint *ep = &endpoints[ep_nr]; | 144 | register struct usb_endpoint* ep = &endpoints[1]; |
145 | register unsigned int length; | ||
146 | 146 | ||
147 | memcpy((void*)ptr, ep->ptr, size); | 147 | if(ep->sent == 0) |
148 | if (ep->length > size) | 148 | length = (ep->length <= ep->fifo_size ? ep->length : ep->fifo_size); |
149 | ep->length -= size; | ||
150 | else | 149 | else |
150 | length = (EP_BUF_LEFT(ep) <= ep->fifo_size ? EP_BUF_LEFT(ep) : ep->fifo_size); | ||
151 | |||
152 | writeFIFO(ep, length); | ||
153 | ep->sent += length; | ||
154 | |||
155 | if(ep->sent >= ep->length) | ||
151 | { | 156 | { |
152 | size = ep->length; | 157 | REG_USB_REG_CSR0 |= (USB_CSR0_INPKTRDY | USB_CSR0_DATAEND); /* Set data end! */ |
153 | ep->length = 0; | 158 | ep0state = USB_EP0_IDLE; |
154 | } | 159 | } |
155 | 160 | else | |
156 | ep->ptr += size; | 161 | REG_USB_REG_CSR0 |= USB_CSR0_INPKTRDY; |
157 | } | 162 | } |
158 | 163 | ||
159 | static void EP0_handler(void) | 164 | static void EP0_handler(void) |
160 | { | 165 | { |
161 | unsigned char csr0; | 166 | register unsigned char csr0; |
162 | 167 | ||
163 | /* Read CSR0 */ | 168 | /* Read CSR0 */ |
164 | select_endpoint(0); | 169 | select_endpoint(0); |
165 | csr0 = REG_USB_REG_CSR0; | 170 | csr0 = REG_USB_REG_CSR0; |
166 | 171 | ||
167 | /* Check for SentStall | 172 | /* Check for SentStall: |
168 | if sentstall is set, clear the sentstall bit | 173 | This bit is set when a STALL handshake is transmitted. The CPU should clear this bit. |
169 | */ | 174 | */ |
170 | if (csr0 & USB_CSR0_SENTSTALL) | 175 | if (csr0 & USB_CSR0_SENTSTALL) |
171 | { | 176 | { |
172 | REG_USB_REG_CSR0 = csr0 & ~USB_CSR0_SENTSTALL; | 177 | REG_USB_REG_CSR0 &= ~USB_CSR0_SENTSTALL; |
173 | ep0state = USB_EP0_IDLE; | 178 | ep0state = USB_EP0_IDLE; |
174 | return; | 179 | return; |
175 | } | 180 | } |
176 | 181 | ||
177 | /* Check for SetupEnd */ | 182 | /* Check for SetupEnd: |
183 | This bit will be set when a control transaction ends before the DataEnd bit has been set. | ||
184 | An interrupt will be generated and the FIFO flushed at this time. | ||
185 | The bit is cleared by the CPU writing a 1 to the ServicedSetupEnd bit. | ||
186 | */ | ||
178 | if (csr0 & USB_CSR0_SETUPEND) | 187 | if (csr0 & USB_CSR0_SETUPEND) |
179 | { | 188 | { |
180 | REG_USB_REG_CSR0 |= USB_CSR0_SVDSETUPEND; | 189 | REG_USB_REG_CSR0 |= USB_CSR0_SVDSETUPEND; |
@@ -187,38 +196,21 @@ static void EP0_handler(void) | |||
187 | { | 196 | { |
188 | if (csr0 & USB_CSR0_OUTPKTRDY) /* There is data in the fifo */ | 197 | if (csr0 & USB_CSR0_OUTPKTRDY) /* There is data in the fifo */ |
189 | { | 198 | { |
190 | readFIFO(&endpoints[0], 8); | 199 | readFIFO(&endpoints[0], REG_USB_REG_COUNT0); |
191 | REG_USB_REG_CSR0 |= USB_CSR0_SVDOUTPKTRDY; /* clear OUTRD bit */ | 200 | REG_USB_REG_CSR0 |= USB_CSR0_SVDOUTPKTRDY; /* clear OUTPKTRDY bit */ |
192 | usb_core_control_request((struct usb_ctrlrequest*)endpoints[0].buf); | 201 | usb_core_control_request((struct usb_ctrlrequest*)endpoints[0].buf); |
193 | } | 202 | } |
194 | endpoints[0].length = 0; | ||
195 | endpoints[0].ptr = endpoints[0].buf; | ||
196 | } | ||
197 | |||
198 | if (ep0state == USB_EP0_TX) | ||
199 | { | ||
200 | if ((&endpoints[1].ptr - &endpoints[1].buf) <= endpoints[1].fifo_size) | ||
201 | { | ||
202 | writeFIFO(&endpoints[1], (&endpoints[1].ptr - &endpoints[1].buf)); | ||
203 | endpoints[1].ptr = &endpoints[1].buf + endpoints[1].length; | ||
204 | REG_USB_REG_CSR0 |= (USB_CSR0_INPKTRDY | USB_CSR0_DATAEND); /* Set data end! */ | ||
205 | ep0state = USB_EP0_IDLE; | ||
206 | } | ||
207 | else | ||
208 | { | ||
209 | writeFIFO(&endpoints[1], endpoints[1].fifo_size); | ||
210 | REG_USB_REG_CSR0 |= USB_CSR0_INPKTRDY; | ||
211 | endpoints[1].ptr += endpoints[1].fifo_size; | ||
212 | } | ||
213 | } | 203 | } |
204 | else if (ep0state == USB_EP0_TX) | ||
205 | EP0_send(); | ||
214 | } | 206 | } |
215 | 207 | ||
216 | static void setup_endpoint(struct usb_endpoint *ep) | 208 | static void setup_endpoint(struct usb_endpoint *ep) |
217 | { | 209 | { |
218 | ep->ptr = ep->buf; | 210 | ep->sent = 0; |
219 | ep->length = 0; | 211 | ep->length = 0; |
220 | 212 | ||
221 | if(ep->in) | 213 | if(EP_IS_IN(ep)) |
222 | { | 214 | { |
223 | if(ep->type == ep_bulk) | 215 | if(ep->type == ep_bulk) |
224 | { | 216 | { |
@@ -235,53 +227,66 @@ static void setup_endpoint(struct usb_endpoint *ep) | |||
235 | else | 227 | else |
236 | REG_USB_REG_INMAXP = ep->fifo_size; | 228 | REG_USB_REG_INMAXP = ep->fifo_size; |
237 | 229 | ||
238 | REG_USB_REG_INCSR = 0x2048; | 230 | REG_USB_REG_INCSR = (USB_INCSR_FF | USB_INCSR_CDT | USB_INCSRH_MODE); |
231 | REG_USB_REG_INTRINE |= USB_INTR_EP(EP_NUMBER(ep)); | ||
239 | } | 232 | } |
240 | else | 233 | else |
241 | { | 234 | { |
242 | REG_USB_REG_OUTMAXP = ep->fifo_size; | 235 | REG_USB_REG_OUTMAXP = ep->fifo_size; |
243 | REG_USB_REG_OUTCSR = 0x0090; | 236 | REG_USB_REG_OUTCSR = (USB_OUTCSR_FF | USB_OUTCSR_CDT); |
237 | REG_USB_REG_INTROUTE |= USB_INTR_EP(EP_NUMBER(ep)); | ||
244 | } | 238 | } |
245 | } | 239 | } |
246 | 240 | ||
247 | static void udc_reset(void) | 241 | static void udc_reset(void) |
248 | { | 242 | { |
249 | register int i; | 243 | DEBUGF("udc_reset"); |
244 | |||
245 | register unsigned int i; | ||
250 | 246 | ||
251 | /* data init */ | 247 | /* data init */ |
252 | ep0state = USB_EP0_IDLE; | 248 | ep0state = USB_EP0_IDLE; |
253 | 249 | ||
254 | /* Disable interrupts */ | 250 | /* Disable interrupts */ |
255 | REG_USB_REG_INTRINE = 0; | 251 | REG_USB_REG_INTRINE = 0; |
256 | REG_USB_REG_INTROUTE = 0; | 252 | REG_USB_REG_INTROUTE = 0; |
257 | REG_USB_REG_INTRUSBE = 0; | 253 | REG_USB_REG_INTRUSBE = 0; |
258 | 254 | ||
255 | /* Disable DMA */ | ||
256 | REG_USB_REG_CNTL1 = 0; | ||
257 | REG_USB_REG_CNTL2 = 0; | ||
258 | |||
259 | /* Reset address */ | ||
259 | REG_USB_REG_FADDR = 0; | 260 | REG_USB_REG_FADDR = 0; |
260 | REG_USB_REG_POWER = 0x60; /* High speed */ | 261 | //REG_USB_REG_POWER = (USB_POWER_SOFTCONN | USB_POWER_HSENAB); /* High speed and softconnect */ |
262 | REG_USB_REG_POWER = USB_POWER_SOFTCONN; | ||
263 | /* Enable SUSPEND */ | ||
264 | /* REG_USB_REG_POWER |= USB_POWER_SUSPENDM; */ | ||
261 | 265 | ||
262 | select_endpoint(0); | 266 | select_endpoint(0); |
263 | REG_USB_REG_CSR0 = 0xC0; | 267 | REG_USB_REG_CSR0 = (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_SVDSETUPEND); |
264 | 268 | ||
265 | for(i=1; i<3; i++) | 269 | for(i=2; i<TOTAL_EP(); i++) /* Skip EP0 */ |
266 | { | 270 | { |
267 | select_endpoint(i); | 271 | select_endpoint(i); |
268 | setup_endpoint(&endpoints[i]); | 272 | setup_endpoint(&endpoints[i]); |
269 | } | 273 | } |
270 | 274 | ||
271 | /* enable intr */ | 275 | /* Enable interrupts */ |
272 | REG_USB_REG_INTRINE = 0x3; | 276 | REG_USB_REG_INTRINE |= USB_INTR_EP0; |
273 | REG_USB_REG_INTROUTE = 0x2; | 277 | REG_USB_REG_INTRUSBE |= USB_INTR_RESET; |
274 | REG_USB_REG_INTRUSBE = 0x4; | 278 | |
279 | usb_core_bus_reset(); | ||
275 | } | 280 | } |
276 | 281 | ||
277 | /* Interrupt handler */ | 282 | /* Interrupt handler */ |
278 | void UDC(void) | 283 | void UDC(void) |
279 | { | 284 | { |
280 | /* Read interrupt registers */ | 285 | /* Read interrupt registers */ |
281 | unsigned char intrUSB = REG_USB_REG_INTRUSB & 0x07; /* Mask SOF */ | 286 | register unsigned char intrUSB = REG_USB_REG_INTRUSB & 0x07; /* Mask SOF */ |
282 | unsigned short intrIn = REG_USB_REG_INTRIN; | 287 | register unsigned short intrIn = REG_USB_REG_INTRIN; |
283 | unsigned short intrOut = REG_USB_REG_INTROUT; | 288 | register unsigned short intrOut = REG_USB_REG_INTROUT; |
284 | unsigned char intrDMA = REG_USB_REG_INTR; | 289 | register unsigned char intrDMA = REG_USB_REG_INTR; |
285 | 290 | ||
286 | if(intrUSB == 0 && intrIn == 0 && intrOut == 0 && intrDMA == 0) | 291 | if(intrUSB == 0 && intrIn == 0 && intrOut == 0 && intrDMA == 0) |
287 | return; | 292 | return; |
@@ -295,16 +300,20 @@ void UDC(void) | |||
295 | if(intrUSB & USB_INTR_RESUME); | 300 | if(intrUSB & USB_INTR_RESUME); |
296 | if(intrDMA & USB_INTR_DMA_BULKIN) | 301 | if(intrDMA & USB_INTR_DMA_BULKIN) |
297 | { | 302 | { |
303 | DEBUGF("DMA_BULKIN %d", ((REG_USB_REG_CNTL1 >> 4) & 0xF)); | ||
298 | usb_core_transfer_complete(((REG_USB_REG_CNTL1 >> 4) & 0xF) | USB_DIR_IN, USB_DIR_IN, 0, 0); | 304 | usb_core_transfer_complete(((REG_USB_REG_CNTL1 >> 4) & 0xF) | USB_DIR_IN, USB_DIR_IN, 0, 0); |
299 | } | 305 | } |
300 | if(intrDMA & USB_INTR_DMA_BULKOUT) | 306 | if(intrDMA & USB_INTR_DMA_BULKOUT) |
301 | { | 307 | { |
308 | DEBUGF("DMA_BULKOUT %d", ((REG_USB_REG_CNTL2 >> 4) & 0xF)); | ||
302 | usb_core_transfer_complete(((REG_USB_REG_CNTL2 >> 4) & 0xF) | USB_DIR_OUT, USB_DIR_OUT, 0, 0); | 309 | usb_core_transfer_complete(((REG_USB_REG_CNTL2 >> 4) & 0xF) | USB_DIR_OUT, USB_DIR_OUT, 0, 0); |
303 | } | 310 | } |
304 | } | 311 | } |
305 | 312 | ||
306 | bool usb_drv_stalled(int endpoint, bool in) | 313 | bool usb_drv_stalled(int endpoint, bool in) |
307 | { | 314 | { |
315 | DEBUGF("usb_drv_stalled(%d, %s)", endpoint, in?"IN":"OUT"); | ||
316 | |||
308 | select_endpoint(endpoint); | 317 | select_endpoint(endpoint); |
309 | 318 | ||
310 | if(endpoint == 0) | 319 | if(endpoint == 0) |
@@ -320,6 +329,8 @@ bool usb_drv_stalled(int endpoint, bool in) | |||
320 | 329 | ||
321 | void usb_drv_stall(int endpoint, bool stall, bool in) | 330 | void usb_drv_stall(int endpoint, bool stall, bool in) |
322 | { | 331 | { |
332 | DEBUGF("usb_drv_stall(%d,%s,%s)", endpoint, stall?"y":"n", in?"IN":"OUT"); | ||
333 | |||
323 | select_endpoint(endpoint); | 334 | select_endpoint(endpoint); |
324 | 335 | ||
325 | if(endpoint == 0) | 336 | if(endpoint == 0) |
@@ -348,23 +359,20 @@ void usb_drv_stall(int endpoint, bool stall, bool in) | |||
348 | } | 359 | } |
349 | } | 360 | } |
350 | 361 | ||
351 | |||
352 | bool usb_drv_connected(void) | 362 | bool usb_drv_connected(void) |
353 | { | 363 | { |
354 | return __gpio_get_pin(GPIO_UDC_DETE) == 1; | 364 | return USB_DRV_CONNECTED(); |
355 | } | 365 | } |
356 | 366 | ||
357 | int usb_detect(void) | 367 | int usb_detect(void) |
358 | { | 368 | { |
359 | if(usb_drv_connected()) | 369 | return usb_drv_connected() ? USB_INSERTED : USB_EXTRACTED; |
360 | return USB_INSERTED; | ||
361 | else | ||
362 | return USB_EXTRACTED; | ||
363 | } | 370 | } |
364 | 371 | ||
365 | void usb_init_device(void) | 372 | void usb_init_device(void) |
366 | { | 373 | { |
367 | usb_init_gpio(); | 374 | USB_INIT_GPIO(); |
375 | system_enable_irq(IRQ_UDC); | ||
368 | } | 376 | } |
369 | 377 | ||
370 | void usb_enable(bool on) | 378 | void usb_enable(bool on) |
@@ -387,27 +395,6 @@ void usb_drv_init(void) | |||
387 | 395 | ||
388 | /* Enable the USB PHY */ | 396 | /* Enable the USB PHY */ |
389 | REG_CPM_SCR |= CPM_SCR_USBPHY_ENABLE; | 397 | REG_CPM_SCR |= CPM_SCR_USBPHY_ENABLE; |
390 | |||
391 | /* Disable interrupts */ | ||
392 | REG_USB_REG_INTRINE = 0; | ||
393 | REG_USB_REG_INTROUTE = 0; | ||
394 | REG_USB_REG_INTRUSBE = 0; | ||
395 | |||
396 | /* Enable interrupts */ | ||
397 | REG_USB_REG_INTRINE |= USB_INTR_EP0; | ||
398 | REG_USB_REG_INTRUSBE |= USB_INTR_RESET; | ||
399 | |||
400 | /* Enable SUSPEND */ | ||
401 | /* usb_setb(USB_REG_POWER, USB_POWER_SUSPENDM); */ | ||
402 | |||
403 | /* Enable HS Mode */ | ||
404 | REG_USB_REG_POWER |= USB_POWER_HSENAB; | ||
405 | |||
406 | /* Let host detect UDC: | ||
407 | * Software must write a 1 to the PMR:USB_POWER_SOFTCONN bit to turn this | ||
408 | * transistor on and pull the USBDP pin HIGH. | ||
409 | */ | ||
410 | REG_USB_REG_POWER |= USB_POWER_SOFTCONN; | ||
411 | 398 | ||
412 | udc_reset(); | 399 | udc_reset(); |
413 | } | 400 | } |
@@ -434,984 +421,94 @@ void usb_drv_exit(void) | |||
434 | 421 | ||
435 | void usb_drv_set_address(int address) | 422 | void usb_drv_set_address(int address) |
436 | { | 423 | { |
424 | DEBUGF("set adr: 0x%x", address); | ||
425 | |||
437 | REG_USB_REG_FADDR = address; | 426 | REG_USB_REG_FADDR = address; |
438 | } | 427 | } |
439 | 428 | ||
440 | int usb_drv_send(int endpoint, void* ptr, int length) | 429 | int usb_drv_send(int endpoint, void* ptr, int length) |
441 | { | 430 | { |
442 | return 0; | 431 | DEBUGF("usb_drv_send(%d, 0x%x, %d)", endpoint, (int)ptr, length); |
443 | } | ||
444 | |||
445 | int usb_drv_recv(int endpoint, void* ptr, int length) | ||
446 | { | ||
447 | return 0; | ||
448 | } | ||
449 | 432 | ||
450 | void usb_drv_set_test_mode(int mode) | 433 | if(endpoint == EP_CONTROL && ptr == NULL && length == 0) /* ACK request */ |
451 | { | 434 | return 0; |
452 | |||
453 | } | ||
454 | |||
455 | int usb_drv_port_speed(void) | ||
456 | { | ||
457 | return ((REG_USB_REG_POWER & USB_POWER_HSMODE) != 0) ? 1 : 0; | ||
458 | } | ||
459 | |||
460 | void usb_drv_cancel_all_transfers(void) | ||
461 | { | ||
462 | int i; | ||
463 | for(i=0; i<5; i++) | ||
464 | { | ||
465 | endpoints[i].ptr = endpoints[i].buf; | ||
466 | endpoints[i].length = 0; | ||
467 | } | ||
468 | } | ||
469 | |||
470 | void usb_drv_release_endpoint(int ep) | ||
471 | { | ||
472 | 435 | ||
473 | } | 436 | if(endpoint == EP_CONTROL) |
474 | |||
475 | #else | ||
476 | |||
477 | //------------------------------------------ | ||
478 | #ifndef u8 | ||
479 | #define u8 unsigned char | ||
480 | #endif | ||
481 | |||
482 | #ifndef u16 | ||
483 | #define u16 unsigned short | ||
484 | #endif | ||
485 | |||
486 | #ifndef u32 | ||
487 | #define u32 unsigned int | ||
488 | #endif | ||
489 | |||
490 | #ifndef s8 | ||
491 | #define s8 char | ||
492 | #endif | ||
493 | |||
494 | #ifndef s16 | ||
495 | #define s16 short | ||
496 | #endif | ||
497 | |||
498 | #ifndef s32 | ||
499 | #define s32 int | ||
500 | #endif | ||
501 | |||
502 | extern int usbdebug; | ||
503 | |||
504 | enum USB_ENDPOINT_TYPE | ||
505 | { | ||
506 | ENDPOINT_TYPE_CONTROL, | ||
507 | /* Typically used to configure a device when attached to the host. | ||
508 | * It may also be used for other device specific purposes, including | ||
509 | * control of other pipes on the device. | ||
510 | */ | ||
511 | ENDPOINT_TYPE_ISOCHRONOUS, | ||
512 | /* Typically used for applications which need guaranteed speed. | ||
513 | * Isochronous transfer is fast but with possible data loss. A typical | ||
514 | * use is audio data which requires a constant data rate. | ||
515 | */ | ||
516 | ENDPOINT_TYPE_BULK, | ||
517 | /* Typically used by devices that generate or consume data in relatively | ||
518 | * large and bursty quantities. Bulk transfer has wide dynamic latitude | ||
519 | * in transmission constraints. It can use all remaining available bandwidth, | ||
520 | * but with no guarantees on bandwidth or latency. Since the USB bus is | ||
521 | * normally not very busy, there is typically 90% or more of the bandwidth | ||
522 | * available for USB transfers. | ||
523 | */ | ||
524 | ENDPOINT_TYPE_INTERRUPT | ||
525 | /* Typically used by devices that need guaranteed quick responses | ||
526 | * (bounded latency). | ||
527 | */ | ||
528 | }; | ||
529 | |||
530 | |||
531 | enum USB_STANDARD_REQUEST_CODE { | ||
532 | GET_STATUS, | ||
533 | CLEAR_FEATURE, | ||
534 | SET_FEATURE = 3, | ||
535 | SET_ADDRESS = 5, | ||
536 | GET_DESCRIPTOR, | ||
537 | SET_DESCRIPTOR, | ||
538 | GET_CONFIGURATION, | ||
539 | SET_CONFIGURATION, | ||
540 | GET_INTERFACE, | ||
541 | SET_INTERFACE, | ||
542 | SYNCH_FRAME | ||
543 | }; | ||
544 | |||
545 | |||
546 | enum USB_DESCRIPTOR_TYPE { | ||
547 | DEVICE_DESCRIPTOR = 1, | ||
548 | CONFIGURATION_DESCRIPTOR, | ||
549 | STRING_DESCRIPTOR, | ||
550 | INTERFACE_DESCRIPTOR, | ||
551 | ENDPOINT_DESCRIPTOR, | ||
552 | DEVICE_QUALIFIER_DESCRIPTOR, | ||
553 | OTHER_SPEED_CONFIGURATION_DESCRIPTOR, | ||
554 | INTERFACE_POWER1_DESCRIPTOR | ||
555 | }; | ||
556 | |||
557 | |||
558 | enum USB_FEATURE_SELECTOR { | ||
559 | ENDPOINT_HALT, | ||
560 | DEVICE_REMOTE_WAKEUP, | ||
561 | TEST_MODE | ||
562 | }; | ||
563 | |||
564 | enum USB_CLASS_CODE { | ||
565 | CLASS_DEVICE, | ||
566 | CLASS_AUDIO, | ||
567 | CLASS_COMM_AND_CDC_CONTROL, | ||
568 | CLASS_HID, | ||
569 | CLASS_PHYSICAL = 0x05, | ||
570 | CLASS_STILL_IMAGING, | ||
571 | CLASS_PRINTER, | ||
572 | CLASS_MASS_STORAGE, | ||
573 | CLASS_HUB, | ||
574 | CLASS_CDC_DATA, | ||
575 | CLASS_SMART_CARD, | ||
576 | CLASS_CONTENT_SECURITY = 0x0d, | ||
577 | CLASS_VIDEO, | ||
578 | CLASS_DIAGNOSTIC_DEVICE = 0xdc, | ||
579 | CLASS_WIRELESS_CONTROLLER = 0xe0, | ||
580 | CLASS_MISCELLANEOUS = 0xef, | ||
581 | CLASS_APP_SPECIFIC = 0xfe, | ||
582 | CLASS_VENDOR_SPECIFIC = 0xff | ||
583 | }; | ||
584 | |||
585 | |||
586 | typedef struct { | ||
587 | u8 bmRequestType; | ||
588 | u8 bRequest; | ||
589 | u16 wValue; | ||
590 | u16 wIndex; | ||
591 | u16 wLength; | ||
592 | } __attribute__ ((packed)) USB_DeviceRequest; | ||
593 | |||
594 | |||
595 | typedef struct { | ||
596 | u8 bLength; | ||
597 | u8 bDescriptorType; | ||
598 | u16 bcdUSB; | ||
599 | u8 bDeviceClass; | ||
600 | u8 bDeviceSubClass; | ||
601 | u8 bDeviceProtocol; | ||
602 | u8 bMaxPacketSize0; | ||
603 | u16 idVendor; | ||
604 | u16 idProduct; | ||
605 | u16 bcdDevice; | ||
606 | u8 iManufacturer; | ||
607 | u8 iProduct; | ||
608 | u8 iSerialNumber; | ||
609 | u8 bNumConfigurations; | ||
610 | } __attribute__ ((packed)) USB_DeviceDescriptor; | ||
611 | |||
612 | |||
613 | typedef struct { | ||
614 | u8 bLength; | ||
615 | u8 bDescriptorType; | ||
616 | u16 bcdUSB; | ||
617 | u8 bDeviceClass; | ||
618 | u8 bDeviceSubClass; | ||
619 | u8 bDeviceProtocol; | ||
620 | u8 bMaxPacketSize0; | ||
621 | u8 bNumConfigurations; | ||
622 | u8 bReserved; | ||
623 | } __attribute__ ((packed)) USB_DeviceQualifierDescriptor; | ||
624 | |||
625 | |||
626 | typedef struct { | ||
627 | u8 bLength; | ||
628 | u8 bDescriptorType; | ||
629 | u16 wTotalLength; | ||
630 | u8 bNumInterfaces; | ||
631 | u8 bConfigurationValue; | ||
632 | u8 iConfiguration; | ||
633 | u8 bmAttributes; | ||
634 | u8 MaxPower; | ||
635 | } __attribute__ ((packed)) USB_ConfigDescriptor; | ||
636 | |||
637 | |||
638 | typedef struct { | ||
639 | u8 bLength; | ||
640 | u8 bDescriptorType; | ||
641 | u16 wTotalLength; | ||
642 | u8 bNumInterfaces; | ||
643 | u8 bConfigurationValue; | ||
644 | u8 iConfiguration; | ||
645 | u8 bmAttributes; | ||
646 | u8 bMaxPower; | ||
647 | } __attribute__ ((packed)) USB_OtherSpeedConfigDescriptor; | ||
648 | |||
649 | |||
650 | typedef struct { | ||
651 | u8 bLength; | ||
652 | u8 bDescriptorType; | ||
653 | u8 bInterfaceNumber; | ||
654 | u8 bAlternateSetting; | ||
655 | u8 bNumEndpoints; | ||
656 | u8 bInterfaceClass; | ||
657 | u8 bInterfaceSubClass; | ||
658 | u8 bInterfaceProtocol; | ||
659 | u8 iInterface; | ||
660 | } __attribute__ ((packed)) USB_InterfaceDescriptor; | ||
661 | |||
662 | |||
663 | typedef struct { | ||
664 | u8 bLegth; | ||
665 | u8 bDescriptorType; | ||
666 | u8 bEndpointAddress; | ||
667 | u8 bmAttributes; | ||
668 | u16 wMaxPacketSize; | ||
669 | u8 bInterval; | ||
670 | } __attribute__ ((packed)) USB_EndPointDescriptor; | ||
671 | |||
672 | |||
673 | typedef struct { | ||
674 | u8 bLength; | ||
675 | u8 bDescriptorType; | ||
676 | u16 SomeDesriptor[1]; | ||
677 | } __attribute__ ((packed)) USB_StringDescriptor; | ||
678 | //------------------------------------------ | ||
679 | #define MAX_EP0_SIZE 64 | ||
680 | #define MAX_EP1_SIZE 512 | ||
681 | |||
682 | #define USB_HS 0 | ||
683 | #define USB_FS 1 | ||
684 | #define USB_LS 2 | ||
685 | |||
686 | //definitions of EP0 | ||
687 | #define USB_EP0_IDLE 0 | ||
688 | #define USB_EP0_RX 1 | ||
689 | #define USB_EP0_TX 2 | ||
690 | /* Define maximum packet size for endpoint 0 */ | ||
691 | #define M_EP0_MAXP 64 | ||
692 | /* Endpoint 0 status structure */ | ||
693 | |||
694 | static __inline__ void usb_setb(u32 port, u8 val) | ||
695 | { | ||
696 | volatile u8 *ioport = (volatile u8 *)(port); | ||
697 | *ioport = (*ioport) | val; | ||
698 | } | ||
699 | |||
700 | static __inline__ void usb_clearb(u32 port, u8 val) | ||
701 | { | ||
702 | volatile u8 *ioport = (volatile u8 *)(port); | ||
703 | *ioport = (*ioport) & ~val; | ||
704 | } | ||
705 | |||
706 | static __inline__ void usb_setw(u32 port, u16 val) | ||
707 | { | ||
708 | volatile u16 *ioport = (volatile u16 *)(port); | ||
709 | *ioport = (*ioport) | val; | ||
710 | } | ||
711 | |||
712 | static __inline__ void usb_clearw(u32 port, u16 val) | ||
713 | { | ||
714 | volatile u16 *ioport = (volatile u16 *)(port); | ||
715 | *ioport = (*ioport) & ~val; | ||
716 | } | ||
717 | //--------------------------------- | ||
718 | #define BULK_OUT_BUF_SIZE 0x20000 //buffer size : | ||
719 | #define BULK_IN_BUF_SIZE 0x20000 // too | ||
720 | |||
721 | enum UDC_STATE | ||
722 | { | ||
723 | IDLE, | ||
724 | BULK_IN, | ||
725 | BULK_OUT | ||
726 | }; | ||
727 | |||
728 | enum USB_JZ4740_REQUEST //add for USB_BOOT | ||
729 | { | ||
730 | VR_GET_CUP_INFO = 0, | ||
731 | VR_SET_DATA_ADDERSS, | ||
732 | VR_SET_DATA_LENGTH, | ||
733 | VR_FLUSH_CACHES, | ||
734 | VR_PROGRAM_START1, | ||
735 | VR_PROGRAM_START2, | ||
736 | VR_NOR_OPS, | ||
737 | VR_NAND_OPS, | ||
738 | VR_SDRAM_OPS, | ||
739 | VR_CONFIGRATION | ||
740 | }; | ||
741 | |||
742 | enum NOR_OPS_TYPE | ||
743 | { | ||
744 | NOR_INIT = 0, | ||
745 | NOR_QUERY, | ||
746 | NOR_WRITE, | ||
747 | NOR_ERASE_CHIP, | ||
748 | NOR_ERASE_SECTOR | ||
749 | }; | ||
750 | |||
751 | enum NOR_FLASH_TYPE | ||
752 | { | ||
753 | NOR_AM29 = 0, | ||
754 | NOR_SST28, | ||
755 | NOR_SST39x16, | ||
756 | NOR_SST39x8 | ||
757 | }; | ||
758 | |||
759 | enum NAND_OPS_TYPE | ||
760 | { | ||
761 | NAND_QUERY = 0, | ||
762 | NAND_INIT, | ||
763 | NAND_MARK_BAD, | ||
764 | NAND_READ_OOB, | ||
765 | NAND_READ_RAW, | ||
766 | NAND_ERASE, | ||
767 | NAND_READ, | ||
768 | NAND_PROGRAM, | ||
769 | NAND_READ_TO_RAM | ||
770 | }; | ||
771 | |||
772 | enum SDRAM_OPS_TYPE | ||
773 | { | ||
774 | SDRAM_LOAD, | ||
775 | |||
776 | }; | ||
777 | |||
778 | enum DATA_STRUCTURE_OB | ||
779 | { | ||
780 | DS_flash_info , | ||
781 | DS_hand | ||
782 | }; | ||
783 | |||
784 | |||
785 | /*typedef enum _USB_BOOT_STATUS | ||
786 | { | ||
787 | USB_NO_ERR =0 , | ||
788 | GET_CPU_INFO_ERR, | ||
789 | SET_DATA_ADDRESS_ERR, | ||
790 | SET_DATA_LENGTH_ERR, | ||
791 | FLUSH_CAHCES_ERR, | ||
792 | PROGRAM_START1_ERR, | ||
793 | PROGRAM_START2_ERR, | ||
794 | NOR_OPS_ERR, | ||
795 | NAND_OPS_ERR, | ||
796 | NOR_FLASHTYPE_ERR, | ||
797 | OPS_NOTSUPPORT_ERR | ||
798 | }USB_BOOT_STATUS;*/ | ||
799 | |||
800 | enum OPTION | ||
801 | { | ||
802 | OOB_ECC, | ||
803 | OOB_NO_ECC, | ||
804 | NO_OOB, | ||
805 | }; | ||
806 | //------------------------- | ||
807 | static inline void jz_writeb(u32 address, u8 value) | ||
808 | { | ||
809 | *((volatile u8 *)address) = value; | ||
810 | } | ||
811 | |||
812 | static inline void jz_writew(u32 address, u16 value) | ||
813 | { | ||
814 | *((volatile u16 *)address) = value; | ||
815 | } | ||
816 | |||
817 | static inline void jz_writel(u32 address, u32 value) | ||
818 | { | ||
819 | *((volatile u32 *)address) = value; | ||
820 | } | ||
821 | |||
822 | static inline u8 jz_readb(u32 address) | ||
823 | { | ||
824 | return *((volatile u8 *)address); | ||
825 | } | ||
826 | |||
827 | static inline u16 jz_readw(u32 address) | ||
828 | { | ||
829 | return *((volatile u16 *)address); | ||
830 | } | ||
831 | |||
832 | static inline u32 jz_readl(u32 address) | ||
833 | { | ||
834 | return *((volatile u32 *)address); | ||
835 | } | ||
836 | //--------------------------- | ||
837 | |||
838 | #define TXFIFOEP0 USB_FIFO_EP0 | ||
839 | |||
840 | u8 *Bulk_in_buf; | ||
841 | u32 Bulk_out_buf[BULK_OUT_BUF_SIZE]; | ||
842 | u32 Bulk_in_size,Bulk_in_finish,Bulk_out_size; | ||
843 | u16 handshake_PKT[4]={0,0,0,0}; | ||
844 | u8 udc_state; | ||
845 | |||
846 | static u32 rx_buf[32]; | ||
847 | static u32 tx_buf[32]; | ||
848 | static u32 tx_size, rx_size, finished,fifo; | ||
849 | static u8 ep0state,USB_Version; | ||
850 | |||
851 | static u32 fifoaddr[] = | ||
852 | { | ||
853 | TXFIFOEP0, TXFIFOEP0+4 ,TXFIFOEP0+8 | ||
854 | }; | ||
855 | |||
856 | static u32 fifosize[] = { | ||
857 | MAX_EP0_SIZE, MAX_EP1_SIZE | ||
858 | }; | ||
859 | |||
860 | static void udcReadFifo(u8 *ptr, int size) | ||
861 | { | ||
862 | u32 *d = (u32 *)ptr; | ||
863 | int s; | ||
864 | s = (size + 3) >> 2; | ||
865 | while (s--) | ||
866 | *d++ = REG32(fifo); | ||
867 | } | ||
868 | |||
869 | static void udcWriteFifo(u8 *ptr, int size) | ||
870 | { | ||
871 | u32 *d = (u32 *)ptr; | ||
872 | u8 *c; | ||
873 | int s, q; | ||
874 | |||
875 | if (size > 0) { | ||
876 | s = size >> 2; | ||
877 | while (s--) | ||
878 | REG32(fifo) = *d++; | ||
879 | q = size & 3; | ||
880 | if (q) { | ||
881 | c = (u8 *)d; | ||
882 | while (q--) | ||
883 | REG8(fifo) = *c++; | ||
884 | } | ||
885 | } | ||
886 | } | ||
887 | |||
888 | void HW_SendPKT(int ep, const u8 *buf, int size) | ||
889 | { | ||
890 | fifo = fifoaddr[ep]; | ||
891 | |||
892 | if (ep!=0) | ||
893 | { | 437 | { |
894 | Bulk_in_size = size; | 438 | endpoints[1].buf = ptr; |
895 | Bulk_in_finish = 0; | 439 | endpoints[1].sent = 0; |
896 | jz_writeb(USB_REG_INDEX, ep); | 440 | endpoints[1].length = length; |
897 | if (Bulk_in_size - Bulk_in_finish <= fifosize[ep]) | 441 | ep0state = USB_EP0_TX; |
898 | { | 442 | EP0_send(); |
899 | udcWriteFifo((u8 *)((u32)buf+Bulk_in_finish), | 443 | return 0; |
900 | Bulk_in_size - Bulk_in_finish); | ||
901 | usb_setb(USB_REG_INCSR, USB_INCSR_INPKTRDY); | ||
902 | Bulk_in_finish = Bulk_in_size; | ||
903 | } | ||
904 | else | ||
905 | { | ||
906 | udcWriteFifo((u8 *)((u32)buf+Bulk_in_finish), | ||
907 | fifosize[ep]); | ||
908 | usb_setb(USB_REG_INCSR, USB_INCSR_INPKTRDY); | ||
909 | Bulk_in_finish += fifosize[ep]; | ||
910 | Bulk_in_buf = (u8*)buf; | ||
911 | } | ||
912 | } | ||
913 | else //EP0 | ||
914 | { | ||
915 | tx_size = size; | ||
916 | finished = 0; | ||
917 | memcpy((void *)tx_buf, buf, size); | ||
918 | ep0state = USB_EP0_TX; | ||
919 | } | 444 | } |
920 | } | ||
921 | |||
922 | void HW_GetPKT(int ep, const u8 *buf, unsigned int size) | ||
923 | { | ||
924 | memcpy((void *)buf, (u8 *)rx_buf, size); | ||
925 | fifo = fifoaddr[ep]; | ||
926 | if (rx_size > size) | ||
927 | rx_size -= size; | ||
928 | else | 445 | else |
929 | { | 446 | return 0; |
930 | size = rx_size; | ||
931 | rx_size = 0; | ||
932 | } | ||
933 | memcpy((u8 *)rx_buf, (u8 *)((u32)rx_buf+size), rx_size); | ||
934 | } | ||
935 | |||
936 | void Enable_DMA(u8* buf, u32 length) | ||
937 | { | ||
938 | dma_cache_wback_inv((u32)buf, length); | ||
939 | jz_writeb(USB_REG_INDEX, 1); | ||
940 | usb_setw(USB_REG_INCSR, 0x9400); | ||
941 | usb_clearw(USB_REG_INTRINE, 0x2); //disable OUT intr | ||
942 | jz_writel(USB_REG_ADDR1, (u32)buf); | ||
943 | jz_writel(USB_REG_COUNT1, length); | ||
944 | jz_writel(USB_REG_CNTL1, 0x001f); | ||
945 | } | ||
946 | |||
947 | void Disable_DMA(void) | ||
948 | { | ||
949 | jz_writeb(USB_REG_INDEX, 1); | ||
950 | usb_clearw(USB_REG_INCSR, 0x9400); | ||
951 | usb_setw(USB_REG_INTRINE, 0x2); //Enable OUT intr | ||
952 | } | ||
953 | |||
954 | static USB_DeviceDescriptor devDesc = | ||
955 | { | ||
956 | sizeof(USB_DeviceDescriptor), | ||
957 | DEVICE_DESCRIPTOR, //1 | ||
958 | 0x0200, //Version 2.0 | ||
959 | 0xff, //Vendor spec class | ||
960 | 0xff, | ||
961 | 0xff, | ||
962 | 64, /* Ep0 FIFO size */ | ||
963 | 0x601a, //vendor ID | ||
964 | 0xDEAD, //Product ID | ||
965 | 0xffff, | ||
966 | 0x00, | ||
967 | 0x00, | ||
968 | 0x00, | ||
969 | 0x01 | ||
970 | }; | ||
971 | |||
972 | #define CONFIG_DESCRIPTOR_LEN (sizeof(USB_ConfigDescriptor) + \ | ||
973 | sizeof(USB_InterfaceDescriptor) + \ | ||
974 | sizeof(USB_EndPointDescriptor) * 2) | ||
975 | |||
976 | static struct { | ||
977 | USB_ConfigDescriptor configuration_descriptor; | ||
978 | USB_InterfaceDescriptor interface_descritor; | ||
979 | USB_EndPointDescriptor endpoint_descriptor[2]; | ||
980 | } __attribute__ ((packed)) confDesc = { | ||
981 | { | ||
982 | sizeof(USB_ConfigDescriptor), | ||
983 | CONFIGURATION_DESCRIPTOR, | ||
984 | CONFIG_DESCRIPTOR_LEN, | ||
985 | 0x01, | ||
986 | 0x01, | ||
987 | 0x00, | ||
988 | 0xc0, // Self Powered, no remote wakeup | ||
989 | 0x64 // Maximum power consumption 2000 mA | ||
990 | }, | ||
991 | { | ||
992 | sizeof(USB_InterfaceDescriptor), | ||
993 | INTERFACE_DESCRIPTOR, | ||
994 | 0x00, | ||
995 | 0x00, | ||
996 | 0x02, /* ep number */ | ||
997 | 0xff, | ||
998 | 0xff, | ||
999 | 0xff, | ||
1000 | 0x00 | ||
1001 | }, | ||
1002 | { | ||
1003 | { | ||
1004 | sizeof(USB_EndPointDescriptor), | ||
1005 | ENDPOINT_DESCRIPTOR, | ||
1006 | (1 << 7) | 1,// endpoint 2 is IN endpoint | ||
1007 | 2, /* bulk */ | ||
1008 | 512, | ||
1009 | 0 | ||
1010 | }, | ||
1011 | { | ||
1012 | sizeof(USB_EndPointDescriptor), | ||
1013 | ENDPOINT_DESCRIPTOR, | ||
1014 | (0 << 7) | 1,// endpoint 5 is OUT endpoint | ||
1015 | 2, /* bulk */ | ||
1016 | 512, /* OUT EP FIFO size */ | ||
1017 | 0 | ||
1018 | } | ||
1019 | } | ||
1020 | }; | ||
1021 | |||
1022 | void sendDevDescString(int size) | ||
1023 | { | ||
1024 | u16 str_ret[13] = { | ||
1025 | 0x031a,//0x1a=26 byte | ||
1026 | 0x0041, | ||
1027 | 0x0030, | ||
1028 | 0x0030, | ||
1029 | 0x0041, | ||
1030 | 0x0030, | ||
1031 | 0x0030, | ||
1032 | 0x0041, | ||
1033 | 0x0030, | ||
1034 | 0x0030, | ||
1035 | 0x0041, | ||
1036 | 0x0030, | ||
1037 | 0x0030 | ||
1038 | }; | ||
1039 | if(size >= 26) | ||
1040 | size = 26; | ||
1041 | str_ret[0] = (0x0300 | size); | ||
1042 | HW_SendPKT(0, (u8 *)str_ret,size); | ||
1043 | } | 447 | } |
1044 | 448 | ||
1045 | void sendDevDesc(int size) | 449 | int usb_drv_recv(int endpoint, void* ptr, int length) |
1046 | { | ||
1047 | switch (size) { | ||
1048 | case 18: | ||
1049 | HW_SendPKT(0, (u8 *)&devDesc, sizeof(devDesc)); | ||
1050 | break; | ||
1051 | default: | ||
1052 | HW_SendPKT(0, (u8 *)&devDesc, 8); | ||
1053 | break; | ||
1054 | } | ||
1055 | } | ||
1056 | |||
1057 | void sendConfDesc(int size) | ||
1058 | { | 450 | { |
1059 | switch (size) { | 451 | DEBUGF("usb_drv_recv(%d, 0x%x, %d)", endpoint, (int)ptr, length); |
1060 | case 9: | ||
1061 | HW_SendPKT(0, (u8 *)&confDesc, 9); | ||
1062 | break; | ||
1063 | case 8: | ||
1064 | HW_SendPKT(0, (u8 *)&confDesc, 8); | ||
1065 | break; | ||
1066 | default: | ||
1067 | HW_SendPKT(0, (u8 *)&confDesc, sizeof(confDesc)); | ||
1068 | break; | ||
1069 | } | ||
1070 | } | ||
1071 | 452 | ||
1072 | void EP0_init(u32 out, u32 out_size, u32 in, u32 in_size) | 453 | if(endpoint == EP_CONTROL && ptr == NULL && length == 0) /* ACK request */ |
1073 | { | 454 | return 0; |
1074 | confDesc.endpoint_descriptor[0].bEndpointAddress = (1<<7) | in; | 455 | |
1075 | confDesc.endpoint_descriptor[0].wMaxPacketSize = in_size; | 456 | return -1; |
1076 | confDesc.endpoint_descriptor[1].bEndpointAddress = (0<<7) | out; | ||
1077 | confDesc.endpoint_descriptor[1].wMaxPacketSize = out_size; | ||
1078 | } | 457 | } |
1079 | 458 | ||
1080 | static void udc_reset(void) | 459 | void usb_drv_set_test_mode(int mode) |
1081 | { | 460 | { |
1082 | //data init | 461 | switch(mode) |
1083 | ep0state = USB_EP0_IDLE; | ||
1084 | Bulk_in_size = 0; | ||
1085 | Bulk_in_finish = 0; | ||
1086 | Bulk_out_size = 0; | ||
1087 | udc_state = IDLE; | ||
1088 | tx_size = 0; | ||
1089 | rx_size = 0; | ||
1090 | finished = 0; | ||
1091 | /* Enable the USB PHY */ | ||
1092 | // REG_CPM_SCR |= CPM_SCR_USBPHY_ENABLE; | ||
1093 | /* Disable interrupts */ | ||
1094 | jz_writew(USB_REG_INTRINE, 0); | ||
1095 | jz_writew(USB_REG_INTROUTE, 0); | ||
1096 | jz_writeb(USB_REG_INTRUSBE, 0); | ||
1097 | jz_writeb(USB_REG_FADDR,0); | ||
1098 | jz_writeb(USB_REG_POWER,0x60); //High speed | ||
1099 | jz_writeb(USB_REG_INDEX,0); | ||
1100 | jz_writeb(USB_REG_CSR0,0xc0); | ||
1101 | jz_writeb(USB_REG_INDEX,1); | ||
1102 | jz_writew(USB_REG_INMAXP,512); | ||
1103 | jz_writew(USB_REG_INCSR,0x2048); | ||
1104 | jz_writeb(USB_REG_INDEX,1); | ||
1105 | jz_writew(USB_REG_OUTMAXP,512); | ||
1106 | jz_writew(USB_REG_OUTCSR,0x0090); | ||
1107 | jz_writew(USB_REG_INTRINE,0x3); //enable intr | ||
1108 | jz_writew(USB_REG_INTROUTE,0x2); | ||
1109 | jz_writeb(USB_REG_INTRUSBE,0x4); | ||
1110 | |||
1111 | if ((jz_readb(USB_REG_POWER)&0x10)==0) | ||
1112 | { | ||
1113 | jz_writeb(USB_REG_INDEX,1); | ||
1114 | jz_writew(USB_REG_INMAXP,64); | ||
1115 | jz_writew(USB_REG_INCSR,0x2048); | ||
1116 | jz_writeb(USB_REG_INDEX,1); | ||
1117 | jz_writew(USB_REG_OUTMAXP,64); | ||
1118 | jz_writew(USB_REG_OUTCSR,0x0090); | ||
1119 | USB_Version=USB_FS; | ||
1120 | fifosize[1]=64; | ||
1121 | EP0_init(1,64,1,64); | ||
1122 | } | ||
1123 | else | ||
1124 | { | 462 | { |
1125 | jz_writeb(USB_REG_INDEX,1); | 463 | case 0: |
1126 | jz_writew(USB_REG_INMAXP,512); | 464 | REG_USB_REG_TESTMODE &= ~USB_TEST_ALL; |
1127 | jz_writew(USB_REG_INCSR,0x2048); | ||
1128 | jz_writeb(USB_REG_INDEX,1); | ||
1129 | jz_writew(USB_REG_OUTMAXP,512); | ||
1130 | jz_writew(USB_REG_OUTCSR,0x0090); | ||
1131 | USB_Version=USB_HS; | ||
1132 | fifosize[1]=512; | ||
1133 | EP0_init(1,512,1,512); | ||
1134 | } | ||
1135 | |||
1136 | } | ||
1137 | |||
1138 | void usbHandleStandDevReq(u8 *buf) | ||
1139 | { | ||
1140 | USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf; | ||
1141 | switch (dreq->bRequest) { | ||
1142 | case GET_DESCRIPTOR: | ||
1143 | if (dreq->bmRequestType == 0x80) /* Dev2Host */ | ||
1144 | switch(dreq->wValue >> 8) | ||
1145 | { | ||
1146 | case DEVICE_DESCRIPTOR: | ||
1147 | sendDevDesc(dreq->wLength); | ||
1148 | break; | ||
1149 | case CONFIGURATION_DESCRIPTOR: | ||
1150 | sendConfDesc(dreq->wLength); | ||
1151 | break; | ||
1152 | case STRING_DESCRIPTOR: | ||
1153 | if (dreq->wLength == 0x02) | ||
1154 | HW_SendPKT(0, "\x04\x03", 2); | ||
1155 | else | ||
1156 | sendDevDescString(dreq->wLength); | ||
1157 | //HW_SendPKT(0, "\x04\x03\x09\x04", 2); | ||
1158 | break; | ||
1159 | } | ||
1160 | ep0state=USB_EP0_TX; | ||
1161 | |||
1162 | break; | ||
1163 | case SET_ADDRESS: | ||
1164 | jz_writeb(USB_REG_FADDR,dreq->wValue); | ||
1165 | break; | ||
1166 | case GET_STATUS: | ||
1167 | switch (dreq->bmRequestType) { | ||
1168 | case 80: /* device */ | ||
1169 | HW_SendPKT(0, "\x01\x00", 2); | ||
1170 | break; | 465 | break; |
1171 | case 81: /* interface */ | 466 | case 1: |
1172 | case 82: /* ep */ | 467 | REG_USB_REG_TESTMODE |= USB_TEST_J; |
1173 | HW_SendPKT(0, "\x00\x00", 2); | ||
1174 | break; | 468 | break; |
1175 | } | 469 | case 2: |
1176 | ep0state=USB_EP0_TX; | 470 | REG_USB_REG_TESTMODE |= USB_TEST_K; |
1177 | break; | ||
1178 | case CLEAR_FEATURE: | ||
1179 | case SET_CONFIGURATION: | ||
1180 | case SET_INTERFACE: | ||
1181 | case SET_FEATURE: | ||
1182 | break; | ||
1183 | } | ||
1184 | } | ||
1185 | |||
1186 | unsigned char nandbuffer[4096]; | ||
1187 | extern void jz_nand_read(int block, int page, unsigned char *buf); | ||
1188 | |||
1189 | void usbHandleVendorReq(u8 *buf) | ||
1190 | { | ||
1191 | USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf; | ||
1192 | switch (dreq->bRequest) | ||
1193 | { | ||
1194 | case 0xB0: | ||
1195 | memset(&nandbuffer, 0, 4096); | ||
1196 | jz_nand_read(dreq->wValue, dreq->wIndex, nandbuffer); | ||
1197 | //printf("Read block %d page %d", dreq->wValue, dreq->wIndex); | ||
1198 | udc_state = IDLE; | ||
1199 | break; | 471 | break; |
1200 | case 0xAB: | 472 | case 3: |
1201 | Enable_DMA(nandbuffer, 4096); | 473 | REG_USB_REG_TESTMODE |= USB_TEST_SE0NAK; |
1202 | //HW_SendPKT(1, nandbuffer, 4096); | ||
1203 | //printf("Send data"); | ||
1204 | //udc_state = BULK_OUT; | ||
1205 | break; | 474 | break; |
1206 | case 0x12: | 475 | case 4: |
1207 | HW_SendPKT(0, "TEST", 4); | 476 | REG_USB_REG_TESTMODE |= USB_TEST_PACKET; |
1208 | //printf("Send test"); | ||
1209 | udc_state = IDLE; | ||
1210 | break; | 477 | break; |
1211 | } | 478 | } |
1212 | } | 479 | } |
1213 | 480 | ||
1214 | void Handshake_PKT(void) | 481 | int usb_drv_port_speed(void) |
1215 | { | ||
1216 | if (udc_state!=IDLE) | ||
1217 | { | ||
1218 | HW_SendPKT(1,(u8 *)handshake_PKT,sizeof(handshake_PKT)); | ||
1219 | udc_state = IDLE; | ||
1220 | } | ||
1221 | } | ||
1222 | |||
1223 | void usbHandleDevReq(u8 *buf) | ||
1224 | { | 482 | { |
1225 | switch ((buf[0] & (3 << 5)) >> 5) { | 483 | return ((REG_USB_REG_POWER & USB_POWER_HSMODE) != 0) ? 1 : 0; |
1226 | case 0: /* Standard request */ | ||
1227 | usbHandleStandDevReq(buf); | ||
1228 | break; | ||
1229 | case 1: /* Class request */ | ||
1230 | break; | ||
1231 | case 2: /* Vendor request */ | ||
1232 | usbHandleVendorReq(buf); | ||
1233 | break; | ||
1234 | } | ||
1235 | } | 484 | } |
1236 | 485 | ||
1237 | void EP0_Handler (void) | 486 | void usb_drv_cancel_all_transfers(void) |
1238 | { | 487 | { |
1239 | u8 byCSR0; | 488 | DEBUGF("usb_drv_cancel_all_transfers()"); |
1240 | |||
1241 | /* Read CSR0 */ | ||
1242 | jz_writeb(USB_REG_INDEX, 0); | ||
1243 | byCSR0 = jz_readb(USB_REG_CSR0); | ||
1244 | |||
1245 | /* Check for SentStall | ||
1246 | if sendstall is set ,clear the sendstall bit*/ | ||
1247 | if (byCSR0 & USB_CSR0_SENTSTALL) | ||
1248 | { | ||
1249 | jz_writeb(USB_REG_CSR0, (byCSR0 & ~USB_CSR0_SENDSTALL)); | ||
1250 | ep0state = USB_EP0_IDLE; | ||
1251 | return; | ||
1252 | } | ||
1253 | |||
1254 | /* Check for SetupEnd */ | ||
1255 | if (byCSR0 & USB_CSR0_SETUPEND) | ||
1256 | { | ||
1257 | jz_writeb(USB_REG_CSR0, (byCSR0 | USB_CSR0_SVDSETUPEND)); | ||
1258 | ep0state = USB_EP0_IDLE; | ||
1259 | return; | ||
1260 | } | ||
1261 | /* Call relevant routines for endpoint 0 state */ | ||
1262 | if (ep0state == USB_EP0_IDLE) | ||
1263 | { | ||
1264 | if (byCSR0 & USB_CSR0_OUTPKTRDY) //There are datas in fifo | ||
1265 | { | ||
1266 | USB_DeviceRequest *dreq; | ||
1267 | fifo=fifoaddr[0]; | ||
1268 | udcReadFifo((u8 *)rx_buf, sizeof(USB_DeviceRequest)); | ||
1269 | usb_setb(USB_REG_CSR0, 0x48);//clear OUTRD bit | ||
1270 | dreq = (USB_DeviceRequest *)rx_buf; | ||
1271 | usbHandleDevReq((u8 *)rx_buf); | ||
1272 | } | ||
1273 | rx_size = 0; | ||
1274 | } | ||
1275 | 489 | ||
1276 | if (ep0state == USB_EP0_TX) | 490 | unsigned int i; |
491 | for(i=0; i<TOTAL_EP(); i++) | ||
1277 | { | 492 | { |
1278 | fifo=fifoaddr[0]; | 493 | endpoints[i].sent = 0; |
1279 | if (tx_size - finished <= 64) | 494 | endpoints[i].length = 0; |
1280 | { | 495 | /* TODO: flush FIFO's ? */ |
1281 | udcWriteFifo((u8 *)((u32)tx_buf+finished), | ||
1282 | tx_size - finished); | ||
1283 | finished = tx_size; | ||
1284 | usb_setb(USB_REG_CSR0, USB_CSR0_INPKTRDY); | ||
1285 | usb_setb(USB_REG_CSR0, USB_CSR0_DATAEND); //Set dataend! | ||
1286 | ep0state=USB_EP0_IDLE; | ||
1287 | } else | ||
1288 | { | ||
1289 | udcWriteFifo((u8 *)((u32)tx_buf+finished), 64); | ||
1290 | usb_setb(USB_REG_CSR0, USB_CSR0_INPKTRDY); | ||
1291 | finished += 64; | ||
1292 | } | ||
1293 | } | ||
1294 | return; | ||
1295 | } | ||
1296 | |||
1297 | void EPIN_Handler(u8 EP) | ||
1298 | { | ||
1299 | jz_writeb(USB_REG_INDEX, EP); | ||
1300 | fifo = fifoaddr[EP]; | ||
1301 | |||
1302 | if (Bulk_in_size-Bulk_in_finish==0) | ||
1303 | { | ||
1304 | Handshake_PKT(); | ||
1305 | return; | ||
1306 | } | ||
1307 | |||
1308 | if (Bulk_in_size - Bulk_in_finish <= fifosize[EP]) | ||
1309 | { | ||
1310 | udcWriteFifo((u8 *)((u32)Bulk_in_buf+Bulk_in_finish), | ||
1311 | Bulk_in_size - Bulk_in_finish); | ||
1312 | usb_setw(USB_REG_INCSR, USB_INCSR_INPKTRDY); | ||
1313 | Bulk_in_finish = Bulk_in_size; | ||
1314 | } | ||
1315 | else | ||
1316 | { | ||
1317 | udcWriteFifo((u8 *)((u32)Bulk_in_buf+Bulk_in_finish), | ||
1318 | fifosize[EP]); | ||
1319 | usb_setw(USB_REG_INCSR, USB_INCSR_INPKTRDY); | ||
1320 | Bulk_in_finish += fifosize[EP]; | ||
1321 | } | ||
1322 | } | ||
1323 | |||
1324 | void EPOUT_Handler(u8 EP) | ||
1325 | { | ||
1326 | u32 size; | ||
1327 | jz_writeb(USB_REG_INDEX, EP); | ||
1328 | size = jz_readw(USB_REG_OUTCOUNT); | ||
1329 | fifo = fifoaddr[EP]; | ||
1330 | udcReadFifo((u8 *)((u32)Bulk_out_buf+Bulk_out_size), size); | ||
1331 | usb_clearb(USB_REG_OUTCSR,USB_OUTCSR_OUTPKTRDY); | ||
1332 | Bulk_out_size += size; | ||
1333 | } | ||
1334 | |||
1335 | void UDC(void) | ||
1336 | { | ||
1337 | u8 IntrUSB; | ||
1338 | u16 IntrIn; | ||
1339 | u16 IntrOut; | ||
1340 | u16 IntrDMA; | ||
1341 | /* Read interrupt registers */ | ||
1342 | IntrUSB = jz_readb(USB_REG_INTRUSB); | ||
1343 | IntrIn = jz_readw(USB_REG_INTRIN); | ||
1344 | IntrOut = jz_readw(USB_REG_INTROUT); | ||
1345 | IntrDMA = jz_readb(USB_REG_INTR); | ||
1346 | |||
1347 | if ( IntrUSB == 0 && IntrIn == 0 && IntrOut == 0) | ||
1348 | return; | ||
1349 | |||
1350 | if (IntrIn & 2) | ||
1351 | { | ||
1352 | EPIN_Handler(1); | ||
1353 | } | ||
1354 | if (IntrOut & 2) | ||
1355 | { | ||
1356 | EPOUT_Handler(1); | ||
1357 | } | ||
1358 | if (IntrUSB & USB_INTR_RESET) | ||
1359 | { | ||
1360 | udc_reset(); | ||
1361 | } | ||
1362 | |||
1363 | /* Check for endpoint 0 interrupt */ | ||
1364 | if (IntrIn & USB_INTR_EP0) | ||
1365 | { | ||
1366 | EP0_Handler(); | ||
1367 | } | ||
1368 | |||
1369 | if (IntrDMA & 0x1) //channel 1 :OUT | ||
1370 | { | ||
1371 | if (tx_size > 0 && tx_size % fifosize[1] != 0) | ||
1372 | { | ||
1373 | jz_writeb(USB_REG_INDEX, 1); | ||
1374 | usb_clearb(USB_REG_INCSR, USB_INCSR_INPKTRDY); | ||
1375 | } | ||
1376 | Disable_DMA(); | ||
1377 | } | 496 | } |
497 | |||
498 | ep0state = USB_EP0_IDLE; | ||
1378 | } | 499 | } |
1379 | 500 | ||
1380 | void __udc_start(void) | 501 | void usb_drv_release_endpoint(int ep) |
1381 | { | 502 | { |
1382 | udc_reset(); | 503 | //DEBUGF("usb_drv_release_endpoint(%d)", ep); |
1383 | 504 | ||
1384 | ep0state = USB_EP0_IDLE; | 505 | (void)ep; |
1385 | Bulk_in_size = 0; | ||
1386 | Bulk_in_finish = 0; | ||
1387 | Bulk_out_size = 0; | ||
1388 | udc_state = IDLE; | ||
1389 | tx_size = 0; | ||
1390 | rx_size = 0; | ||
1391 | finished = 0; | ||
1392 | |||
1393 | if ((jz_readb(USB_REG_POWER)&0x10)==0) | ||
1394 | { | ||
1395 | USB_Version=USB_FS; | ||
1396 | fifosize[1]=64; | ||
1397 | EP0_init(1,64,1,64); | ||
1398 | } | ||
1399 | else | ||
1400 | { | ||
1401 | USB_Version=USB_HS; | ||
1402 | fifosize[1]=512; | ||
1403 | EP0_init(1,512,1,512); | ||
1404 | } | ||
1405 | |||
1406 | USB_Version=USB_HS; | ||
1407 | system_enable_irq(IRQ_UDC); | ||
1408 | } | 506 | } |
1409 | 507 | ||
1410 | void usb_init_device(void) | 508 | int usb_drv_request_endpoint(int dir) |
1411 | { | 509 | { |
1412 | REG_USB_REG_POWER &= ~USB_POWER_SOFTCONN; | 510 | DEBUGF("usb_drv_request_endpoint(%d)", dir); |
1413 | REG_USB_REG_POWER |= USB_POWER_SOFTCONN; | 511 | |
1414 | __udc_start(); | 512 | (void)dir; |
513 | return -1; | ||
1415 | } | 514 | } |
1416 | |||
1417 | #endif | ||