diff options
-rw-r--r-- | firmware/SOURCES | 6 | ||||
-rw-r--r-- | firmware/drivers/ramdisk.c | 2 | ||||
-rw-r--r-- | firmware/export/config-ondavx747.h | 6 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/ata-jz4740.c | 104 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c | 156 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/ata-nand-target.h | 28 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/ata-sd-jz4740.c | 1168 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/ata-sd-target.h | 39 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/codec-jz4740.c | 280 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/onda_vx747/sadc-onda_vx747.c | 54 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c | 164 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/usb-jz4740.c | 1635 |
12 files changed, 2936 insertions, 706 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES index f299d51a53..33386f8f82 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES | |||
@@ -1157,9 +1157,13 @@ drivers/qt1106.c | |||
1157 | #endif /* MEIZU_M3 */ | 1157 | #endif /* MEIZU_M3 */ |
1158 | 1158 | ||
1159 | #if CONFIG_CPU==JZ4732 | 1159 | #if CONFIG_CPU==JZ4732 |
1160 | target/mips/ingenic_jz47xx/ata-jz4740.c | ||
1160 | target/mips/ingenic_jz47xx/ata-nand-jz4740.c | 1161 | target/mips/ingenic_jz47xx/ata-nand-jz4740.c |
1161 | target/mips/ingenic_jz47xx/lcd-jz4740.c | 1162 | target/mips/ingenic_jz47xx/ata-sd-jz4740.c |
1163 | target/mips/ingenic_jz47xx/codec-jz4740.c | ||
1162 | target/mips/ingenic_jz47xx/kernel-jz4740.c | 1164 | target/mips/ingenic_jz47xx/kernel-jz4740.c |
1165 | target/mips/ingenic_jz47xx/lcd-jz4740.c | ||
1166 | target/mips/ingenic_jz47xx/pcm-jz4740.c | ||
1163 | target/mips/ingenic_jz47xx/system-jz4740.c | 1167 | target/mips/ingenic_jz47xx/system-jz4740.c |
1164 | target/mips/ingenic_jz47xx/usb-jz4740.c | 1168 | target/mips/ingenic_jz47xx/usb-jz4740.c |
1165 | drivers/nand_id.c | 1169 | drivers/nand_id.c |
diff --git a/firmware/drivers/ramdisk.c b/firmware/drivers/ramdisk.c index 0a3e991382..266d3ea225 100644 --- a/firmware/drivers/ramdisk.c +++ b/firmware/drivers/ramdisk.c | |||
@@ -84,7 +84,7 @@ void ramdisk_spindown(int seconds) | |||
84 | (void)seconds; | 84 | (void)seconds; |
85 | } | 85 | } |
86 | #ifdef STORAGE_GET_INFO | 86 | #ifdef STORAGE_GET_INFO |
87 | void ramdisk_get_info(struct storage_info *info) | 87 | void ramdisk_get_info(IF_MV2(int drive,) struct storage_info *info) |
88 | { | 88 | { |
89 | /* firmware version */ | 89 | /* firmware version */ |
90 | info->revision="0.00"; | 90 | info->revision="0.00"; |
diff --git a/firmware/export/config-ondavx747.h b/firmware/export/config-ondavx747.h index e52b38700c..3d7628fa8f 100644 --- a/firmware/export/config-ondavx747.h +++ b/firmware/export/config-ondavx747.h | |||
@@ -37,7 +37,7 @@ | |||
37 | #define HAVE_HOTSWAP | 37 | #define HAVE_HOTSWAP |
38 | 38 | ||
39 | //#define CONFIG_STORAGE (STORAGE_NAND | STORAGE_SD) | 39 | //#define CONFIG_STORAGE (STORAGE_NAND | STORAGE_SD) |
40 | #define CONFIG_STORAGE STORAGE_NAND /* Multivolume currently handled at firmware/target/ level */ | 40 | #define CONFIG_STORAGE STORAGE_RAMDISK /* Multivolume currently handled at firmware/target/ level */ |
41 | 41 | ||
42 | #define CONFIG_NAND NAND_CC | 42 | #define CONFIG_NAND NAND_CC |
43 | 43 | ||
@@ -156,10 +156,10 @@ | |||
156 | #define BOOTFILE "rockbox." BOOTFILE_EXT | 156 | #define BOOTFILE "rockbox." BOOTFILE_EXT |
157 | #define BOOTDIR "/.rockbox" | 157 | #define BOOTDIR "/.rockbox" |
158 | 158 | ||
159 | /*#define CONFIG_USBOTG USBOTG_INGENIC | 159 | #define CONFIG_USBOTG USBOTG_INGENIC |
160 | #define HAVE_USBSTACK | 160 | #define HAVE_USBSTACK |
161 | #define USB_VENDOR_ID 0x041e | 161 | #define USB_VENDOR_ID 0x041e |
162 | #define USB_PRODUCT_ID 0x4133*/ | 162 | #define USB_PRODUCT_ID 0x4133 |
163 | 163 | ||
164 | #include <stdbool.h> /* HACKY */ | 164 | #include <stdbool.h> /* HACKY */ |
165 | 165 | ||
diff --git a/firmware/target/mips/ingenic_jz47xx/ata-jz4740.c b/firmware/target/mips/ingenic_jz47xx/ata-jz4740.c new file mode 100644 index 0000000000..dd14a4c651 --- /dev/null +++ b/firmware/target/mips/ingenic_jz47xx/ata-jz4740.c | |||
@@ -0,0 +1,104 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2008 by Maurus Cuelenaere | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #include "config.h" | ||
23 | #include "ata.h" | ||
24 | #include "ata-sd-target.h" | ||
25 | #include "ata-nand-target.h" | ||
26 | #include "panic.h" | ||
27 | |||
28 | int ata_read_sectors(IF_MV2(int drive,) unsigned long start, int count, void* buf) | ||
29 | { | ||
30 | switch(drive) | ||
31 | { | ||
32 | case 0: | ||
33 | return nand_read_sectors(start, count, buf); | ||
34 | case 1: | ||
35 | return sd_read_sectors(start, count, buf); | ||
36 | default: | ||
37 | panicf("ata_read_sectors: Drive %d unhandled!", drive); | ||
38 | return -1; | ||
39 | } | ||
40 | } | ||
41 | |||
42 | int ata_write_sectors(IF_MV2(int drive,) unsigned long start, int count, const void* buf) | ||
43 | { | ||
44 | switch(drive) | ||
45 | { | ||
46 | case 0: | ||
47 | return nand_write_sectors(start, count, buf); | ||
48 | case 1: | ||
49 | return sd_write_sectors(start, count, buf); | ||
50 | default: | ||
51 | panicf("ata_write_sectors: Drive %d unhandled!", drive); | ||
52 | return -1; | ||
53 | } | ||
54 | } | ||
55 | |||
56 | int ata_init(void) | ||
57 | { | ||
58 | if(sd_init() != 0) | ||
59 | return -1; | ||
60 | if(nand_init() != 0) | ||
61 | return -2; | ||
62 | |||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | void ata_spindown(int seconds) | ||
67 | { | ||
68 | /* null */ | ||
69 | (void)seconds; | ||
70 | } | ||
71 | |||
72 | bool ata_disk_is_active(void) | ||
73 | { | ||
74 | /* null */ | ||
75 | return false; | ||
76 | } | ||
77 | |||
78 | void ata_sleep(void) | ||
79 | { | ||
80 | /* null */ | ||
81 | } | ||
82 | |||
83 | void ata_spin(void) | ||
84 | { | ||
85 | /* null */ | ||
86 | } | ||
87 | |||
88 | int ata_hard_reset(void) | ||
89 | { | ||
90 | /* null */ | ||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | int ata_soft_reset(void) | ||
95 | { | ||
96 | /* null */ | ||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | void ata_enable(bool on) | ||
101 | { | ||
102 | /* null - flash controller is enabled/disabled as needed. */ | ||
103 | (void)on; | ||
104 | } | ||
diff --git a/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c b/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c index a41a62294a..7a937bf7cf 100644 --- a/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include "config.h" | 22 | #include "config.h" |
23 | #include "jz4740.h" | 23 | #include "jz4740.h" |
24 | #include "ata.h" | 24 | #include "ata.h" |
25 | #include "ata-nand-target.h" | ||
25 | #include "nand_id.h" | 26 | #include "nand_id.h" |
26 | #include "system.h" | 27 | #include "system.h" |
27 | #include "panic.h" | 28 | #include "panic.h" |
@@ -29,31 +30,31 @@ | |||
29 | /* | 30 | /* |
30 | * Standard NAND flash commands | 31 | * Standard NAND flash commands |
31 | */ | 32 | */ |
32 | #define NAND_CMD_READ0 0 | 33 | #define NAND_CMD_READ0 0 |
33 | #define NAND_CMD_READ1 1 | 34 | #define NAND_CMD_READ1 1 |
34 | #define NAND_CMD_RNDOUT 5 | 35 | #define NAND_CMD_RNDOUT 5 |
35 | #define NAND_CMD_PAGEPROG 0x10 | 36 | #define NAND_CMD_PAGEPROG 0x10 |
36 | #define NAND_CMD_READOOB 0x50 | 37 | #define NAND_CMD_READOOB 0x50 |
37 | #define NAND_CMD_ERASE1 0x60 | 38 | #define NAND_CMD_ERASE1 0x60 |
38 | #define NAND_CMD_STATUS 0x70 | 39 | #define NAND_CMD_STATUS 0x70 |
39 | #define NAND_CMD_STATUS_MULTI 0x71 | 40 | #define NAND_CMD_STATUS_MULTI 0x71 |
40 | #define NAND_CMD_SEQIN 0x80 | 41 | #define NAND_CMD_SEQIN 0x80 |
41 | #define NAND_CMD_RNDIN 0x85 | 42 | #define NAND_CMD_RNDIN 0x85 |
42 | #define NAND_CMD_READID 0x90 | 43 | #define NAND_CMD_READID 0x90 |
43 | #define NAND_CMD_ERASE2 0xd0 | 44 | #define NAND_CMD_ERASE2 0xd0 |
44 | #define NAND_CMD_RESET 0xff | 45 | #define NAND_CMD_RESET 0xff |
45 | 46 | ||
46 | /* Extended commands for large page devices */ | 47 | /* Extended commands for large page devices */ |
47 | #define NAND_CMD_READSTART 0x30 | 48 | #define NAND_CMD_READSTART 0x30 |
48 | #define NAND_CMD_RNDOUTSTART 0xE0 | 49 | #define NAND_CMD_RNDOUTSTART 0xE0 |
49 | #define NAND_CMD_CACHEDPROG 0x15 | 50 | #define NAND_CMD_CACHEDPROG 0x15 |
50 | 51 | ||
51 | /* Status bits */ | 52 | /* Status bits */ |
52 | #define NAND_STATUS_FAIL 0x01 | 53 | #define NAND_STATUS_FAIL 0x01 |
53 | #define NAND_STATUS_FAIL_N1 0x02 | 54 | #define NAND_STATUS_FAIL_N1 0x02 |
54 | #define NAND_STATUS_TRUE_READY 0x20 | 55 | #define NAND_STATUS_TRUE_READY 0x20 |
55 | #define NAND_STATUS_READY 0x40 | 56 | #define NAND_STATUS_READY 0x40 |
56 | #define NAND_STATUS_WP 0x80 | 57 | #define NAND_STATUS_WP 0x80 |
57 | 58 | ||
58 | /* | 59 | /* |
59 | * NAND parameter struct | 60 | * NAND parameter struct |
@@ -81,21 +82,21 @@ struct nand_param | |||
81 | #define NAND_COMMPORT 0xb8008000 | 82 | #define NAND_COMMPORT 0xb8008000 |
82 | 83 | ||
83 | #define ECC_BLOCK 512 | 84 | #define ECC_BLOCK 512 |
84 | #define ECC_POS 6 | 85 | #define ECC_POS 6 |
85 | #define PAR_SIZE 9 | 86 | #define PAR_SIZE 9 |
86 | 87 | ||
87 | #define __nand_cmd(n) (REG8(NAND_COMMPORT) = (n)) | 88 | #define __nand_cmd(n) (REG8(NAND_COMMPORT) = (n)) |
88 | #define __nand_addr(n) (REG8(NAND_ADDRPORT) = (n)) | 89 | #define __nand_addr(n) (REG8(NAND_ADDRPORT) = (n)) |
89 | #define __nand_data8() REG8(NAND_DATAPORT) | 90 | #define __nand_data8() REG8(NAND_DATAPORT) |
90 | #define __nand_data16() REG16(NAND_DATAPORT) | 91 | #define __nand_data16() REG16(NAND_DATAPORT) |
91 | 92 | ||
92 | #define __nand_enable() (REG_EMC_NFCSR |= EMC_NFCSR_NFE1 | EMC_NFCSR_NFCE1) | 93 | #define __nand_enable() (REG_EMC_NFCSR |= EMC_NFCSR_NFE1 | EMC_NFCSR_NFCE1) |
93 | #define __nand_disable() (REG_EMC_NFCSR &= ~(EMC_NFCSR_NFCE1)) | 94 | #define __nand_disable() (REG_EMC_NFCSR &= ~(EMC_NFCSR_NFCE1)) |
94 | #define __nand_ecc_rs_encoding() \ | 95 | #define __nand_ecc_rs_encoding() \ |
95 | (REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST | EMC_NFECR_RS | EMC_NFECR_RS_ENCODING) | 96 | (REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST | EMC_NFECR_RS | EMC_NFECR_RS_ENCODING) |
96 | #define __nand_ecc_rs_decoding() \ | 97 | #define __nand_ecc_rs_decoding() \ |
97 | (REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST | EMC_NFECR_RS | EMC_NFECR_RS_DECODING) | 98 | (REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST | EMC_NFECR_RS | EMC_NFECR_RS_DECODING) |
98 | #define __nand_ecc_disable() (REG_EMC_NFECR &= ~EMC_NFECR_ECCE) | 99 | #define __nand_ecc_disable() (REG_EMC_NFECR &= ~EMC_NFECR_ECCE) |
99 | #define __nand_ecc_encode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_ENCF)) | 100 | #define __nand_ecc_encode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_ENCF)) |
100 | #define __nand_ecc_decode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_DECF)) | 101 | #define __nand_ecc_decode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_DECF)) |
101 | 102 | ||
@@ -104,14 +105,14 @@ struct nand_param | |||
104 | static struct nand_info* chip_info = NULL; | 105 | static struct nand_info* chip_info = NULL; |
105 | static struct nand_param internal_param; | 106 | static struct nand_param internal_param; |
106 | 107 | ||
107 | static inline void nand_wait_ready(void) | 108 | static inline void jz_nand_wait_ready(void) |
108 | { | 109 | { |
109 | unsigned int timeout = 1000; | 110 | unsigned int timeout = 1000; |
110 | while ((REG_GPIO_PXPIN(2) & 0x40000000) && timeout--); | 111 | while ((REG_GPIO_PXPIN(2) & 0x40000000) && timeout--); |
111 | while (!(REG_GPIO_PXPIN(2) & 0x40000000)); | 112 | while (!(REG_GPIO_PXPIN(2) & 0x40000000)); |
112 | } | 113 | } |
113 | 114 | ||
114 | static inline void nand_read_buf16(void *buf, int count) | 115 | static inline void jz_nand_read_buf16(void *buf, int count) |
115 | { | 116 | { |
116 | int i; | 117 | int i; |
117 | unsigned short *p = (unsigned short *)buf; | 118 | unsigned short *p = (unsigned short *)buf; |
@@ -120,7 +121,7 @@ static inline void nand_read_buf16(void *buf, int count) | |||
120 | *p++ = __nand_data16(); | 121 | *p++ = __nand_data16(); |
121 | } | 122 | } |
122 | 123 | ||
123 | static inline void nand_read_buf8(void *buf, int count) | 124 | static inline void jz_nand_read_buf8(void *buf, int count) |
124 | { | 125 | { |
125 | int i; | 126 | int i; |
126 | unsigned char *p = (unsigned char *)buf; | 127 | unsigned char *p = (unsigned char *)buf; |
@@ -129,18 +130,53 @@ static inline void nand_read_buf8(void *buf, int count) | |||
129 | *p++ = __nand_data8(); | 130 | *p++ = __nand_data8(); |
130 | } | 131 | } |
131 | 132 | ||
132 | static inline void nand_read_buf(void *buf, int count, int bw) | 133 | static void jz_nand_write_dma(void *source, unsigned int len, int bw) |
134 | { | ||
135 | if(((unsigned int)source < 0xa0000000) && len) | ||
136 | dma_cache_wback_inv((unsigned long)source, len); | ||
137 | |||
138 | REG_DMAC_DCCSR(DMA_NAND_CHANNEL) = 0; | ||
139 | REG_DMAC_DSAR(DMA_NAND_CHANNEL) = PHYSADDR((unsigned long)source); | ||
140 | REG_DMAC_DTAR(DMA_NAND_CHANNEL) = PHYSADDR((unsigned long)NAND_DATAPORT); | ||
141 | REG_DMAC_DTCR(DMA_NAND_CHANNEL) = len / 16; | ||
142 | REG_DMAC_DRSR(DMA_NAND_CHANNEL) = DMAC_DRSR_RS_AUTO; | ||
143 | REG_DMAC_DCMD(DMA_NAND_CHANNEL) = (DMAC_DCMD_SAI| DMAC_DCMD_DAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DS_16BYTE | | ||
144 | (bw == 8 ? DMAC_DCMD_DWDH_8 : DMAC_DCMD_DWDH_16)); | ||
145 | |||
146 | REG_DMAC_DCCSR(DMA_NAND_CHANNEL) = (DMAC_DCCSR_EN | DMAC_DCCSR_NDES); | ||
147 | while( REG_DMAC_DTCR(DMA_NAND_CHANNEL) ) | ||
148 | yield(); | ||
149 | } | ||
150 | |||
151 | static void jz_nand_read_dma(void *target, unsigned int len, int bw) | ||
152 | { | ||
153 | if(((unsigned int)target < 0xa0000000) && len) | ||
154 | dma_cache_wback_inv((unsigned long)target, len); | ||
155 | |||
156 | REG_DMAC_DCCSR(DMA_NAND_CHANNEL) = 0; | ||
157 | REG_DMAC_DSAR(DMA_NAND_CHANNEL) = PHYSADDR((unsigned long)NAND_DATAPORT); | ||
158 | REG_DMAC_DTAR(DMA_NAND_CHANNEL) = PHYSADDR((unsigned long)target); | ||
159 | REG_DMAC_DTCR(DMA_NAND_CHANNEL) = len / 4; | ||
160 | REG_DMAC_DRSR(DMA_NAND_CHANNEL) = DMAC_DRSR_RS_AUTO; | ||
161 | REG_DMAC_DCMD(DMA_NAND_CHANNEL) = (DMAC_DCMD_SAI| DMAC_DCMD_DAI | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BIT | | ||
162 | (bw == 8 ? DMAC_DCMD_SWDH_8 : DMAC_DCMD_SWDH_16)); | ||
163 | REG_DMAC_DCCSR(DMA_NAND_CHANNEL) = (DMAC_DCCSR_EN | DMAC_DCCSR_NDES); | ||
164 | while( REG_DMAC_DTCR(DMA_NAND_CHANNEL) ) | ||
165 | yield(); | ||
166 | } | ||
167 | |||
168 | static inline void jz_nand_read_buf(void *buf, int count, int bw) | ||
133 | { | 169 | { |
134 | if (bw == 8) | 170 | if (bw == 8) |
135 | nand_read_buf8(buf, count); | 171 | jz_nand_read_dma(buf, count, 8); |
136 | else | 172 | else |
137 | nand_read_buf16(buf, count); | 173 | jz_nand_read_dma(buf, count, 16); |
138 | } | 174 | } |
139 | 175 | ||
140 | /* | 176 | /* |
141 | * Correct 1~9-bit errors in 512-bytes data | 177 | * Correct 1~9-bit errors in 512-bytes data |
142 | */ | 178 | */ |
143 | static void rs_correct(unsigned char *dat, int idx, int mask) | 179 | static void jz_rs_correct(unsigned char *dat, int idx, int mask) |
144 | { | 180 | { |
145 | int i, j; | 181 | int i, j; |
146 | unsigned short d, d1, dm; | 182 | unsigned short d, d1, dm; |
@@ -172,7 +208,7 @@ static void rs_correct(unsigned char *dat, int idx, int mask) | |||
172 | /* | 208 | /* |
173 | * Read oob | 209 | * Read oob |
174 | */ | 210 | */ |
175 | static int nand_read_oob(int page_addr, unsigned char *buf, int size) | 211 | static int jz_nand_read_oob(int page_addr, unsigned char *buf, int size) |
176 | { | 212 | { |
177 | struct nand_param *nandp = &internal_param; | 213 | struct nand_param *nandp = &internal_param; |
178 | int page_size, row_cycle, bus_width; | 214 | int page_size, row_cycle, bus_width; |
@@ -210,10 +246,10 @@ static int nand_read_oob(int page_addr, unsigned char *buf, int size) | |||
210 | __nand_cmd(NAND_CMD_READSTART); | 246 | __nand_cmd(NAND_CMD_READSTART); |
211 | 247 | ||
212 | /* Wait for device ready */ | 248 | /* Wait for device ready */ |
213 | nand_wait_ready(); | 249 | jz_nand_wait_ready(); |
214 | 250 | ||
215 | /* Read oob data */ | 251 | /* Read oob data */ |
216 | nand_read_buf(buf, size, bus_width); | 252 | jz_nand_read_buf(buf, size, bus_width); |
217 | 253 | ||
218 | return 0; | 254 | return 0; |
219 | } | 255 | } |
@@ -228,7 +264,7 @@ static int nand_read_oob(int page_addr, unsigned char *buf, int size) | |||
228 | * page - page number within a block: 0, 1, 2, ... | 264 | * page - page number within a block: 0, 1, 2, ... |
229 | * dst - pointer to target buffer | 265 | * dst - pointer to target buffer |
230 | */ | 266 | */ |
231 | static int nand_read_page(int block, int page, unsigned char *dst) | 267 | static int jz_nand_read_page(int block, int page, unsigned char *dst) |
232 | { | 268 | { |
233 | struct nand_param *nandp = &internal_param; | 269 | struct nand_param *nandp = &internal_param; |
234 | int page_size, oob_size, page_per_block; | 270 | int page_size, oob_size, page_per_block; |
@@ -248,7 +284,7 @@ static int nand_read_page(int block, int page, unsigned char *dst) | |||
248 | /* | 284 | /* |
249 | * Read oob data | 285 | * Read oob data |
250 | */ | 286 | */ |
251 | nand_read_oob(page_addr, oob_buf, oob_size); | 287 | jz_nand_read_oob(page_addr, oob_buf, oob_size); |
252 | 288 | ||
253 | /* | 289 | /* |
254 | * Read page data | 290 | * Read page data |
@@ -273,7 +309,7 @@ static int nand_read_page(int block, int page, unsigned char *dst) | |||
273 | __nand_cmd(NAND_CMD_READSTART); | 309 | __nand_cmd(NAND_CMD_READSTART); |
274 | 310 | ||
275 | /* Wait for device ready */ | 311 | /* Wait for device ready */ |
276 | nand_wait_ready(); | 312 | jz_nand_wait_ready(); |
277 | 313 | ||
278 | /* Read page data */ | 314 | /* Read page data */ |
279 | data_buf = dst; | 315 | data_buf = dst; |
@@ -290,7 +326,7 @@ static int nand_read_page(int block, int page, unsigned char *dst) | |||
290 | __nand_ecc_rs_decoding(); | 326 | __nand_ecc_rs_decoding(); |
291 | 327 | ||
292 | /* Read data */ | 328 | /* Read data */ |
293 | nand_read_buf((void *)data_buf, ECC_BLOCK, bus_width); | 329 | jz_nand_read_buf((void *)data_buf, ECC_BLOCK, bus_width); |
294 | 330 | ||
295 | /* Set PAR values */ | 331 | /* Set PAR values */ |
296 | for (j = 0; j < PAR_SIZE; j++) | 332 | for (j = 0; j < PAR_SIZE; j++) |
@@ -310,8 +346,10 @@ static int nand_read_page(int block, int page, unsigned char *dst) | |||
310 | if (stat & EMC_NFINTS_ERR) | 346 | if (stat & EMC_NFINTS_ERR) |
311 | { | 347 | { |
312 | /* Error occurred */ | 348 | /* Error occurred */ |
313 | if (stat & EMC_NFINTS_UNCOR) { | 349 | if (stat & EMC_NFINTS_UNCOR) |
350 | { | ||
314 | /* Uncorrectable error occurred */ | 351 | /* Uncorrectable error occurred */ |
352 | panicf("Uncorrectable ECC error at NAND page 0x%x block 0x%x", page, block); | ||
315 | } | 353 | } |
316 | else | 354 | else |
317 | { | 355 | { |
@@ -323,19 +361,19 @@ static int nand_read_page(int block, int page, unsigned char *dst) | |||
323 | case 4: | 361 | case 4: |
324 | index = (REG_EMC_NFERR3 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT; | 362 | index = (REG_EMC_NFERR3 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT; |
325 | mask = (REG_EMC_NFERR3 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT; | 363 | mask = (REG_EMC_NFERR3 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT; |
326 | rs_correct(data_buf, index, mask); | 364 | jz_rs_correct(data_buf, index, mask); |
327 | case 3: | 365 | case 3: |
328 | index = (REG_EMC_NFERR2 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT; | 366 | index = (REG_EMC_NFERR2 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT; |
329 | mask = (REG_EMC_NFERR2 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT; | 367 | mask = (REG_EMC_NFERR2 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT; |
330 | rs_correct(data_buf, index, mask); | 368 | jz_rs_correct(data_buf, index, mask); |
331 | case 2: | 369 | case 2: |
332 | index = (REG_EMC_NFERR1 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT; | 370 | index = (REG_EMC_NFERR1 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT; |
333 | mask = (REG_EMC_NFERR1 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT; | 371 | mask = (REG_EMC_NFERR1 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT; |
334 | rs_correct(data_buf, index, mask); | 372 | jz_rs_correct(data_buf, index, mask); |
335 | case 1: | 373 | case 1: |
336 | index = (REG_EMC_NFERR0 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT; | 374 | index = (REG_EMC_NFERR0 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT; |
337 | mask = (REG_EMC_NFERR0 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT; | 375 | mask = (REG_EMC_NFERR0 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT; |
338 | rs_correct(data_buf, index, mask); | 376 | jz_rs_correct(data_buf, index, mask); |
339 | break; | 377 | break; |
340 | default: | 378 | default: |
341 | break; | 379 | break; |
@@ -352,7 +390,7 @@ static int nand_read_page(int block, int page, unsigned char *dst) | |||
352 | /* | 390 | /* |
353 | * Enable NAND controller | 391 | * Enable NAND controller |
354 | */ | 392 | */ |
355 | static void nand_enable(void) | 393 | static void jz_nand_enable(void) |
356 | { | 394 | { |
357 | __nand_enable(); | 395 | __nand_enable(); |
358 | 396 | ||
@@ -362,16 +400,16 @@ static void nand_enable(void) | |||
362 | /* | 400 | /* |
363 | * Disable NAND controller | 401 | * Disable NAND controller |
364 | */ | 402 | */ |
365 | static void nand_disable(void) | 403 | static void jz_nand_disable(void) |
366 | { | 404 | { |
367 | __nand_disable(); | 405 | __nand_disable(); |
368 | } | 406 | } |
369 | 407 | ||
370 | int nand_init(void) | 408 | static int jz_nand_init(void) |
371 | { | 409 | { |
372 | unsigned char cData[5]; | 410 | unsigned char cData[5]; |
373 | 411 | ||
374 | nand_enable(); | 412 | jz_nand_enable(); |
375 | 413 | ||
376 | __nand_cmd(NAND_CMD_READID); | 414 | __nand_cmd(NAND_CMD_READID); |
377 | __nand_addr(NAND_CMD_READ0); | 415 | __nand_addr(NAND_CMD_READ0); |
@@ -386,7 +424,7 @@ int nand_init(void) | |||
386 | { | 424 | { |
387 | panicf("Unknown NAND flash chip: 0x%x 0x%x 0x%x 0x%x 0x%x", cData[0], | 425 | panicf("Unknown NAND flash chip: 0x%x 0x%x 0x%x 0x%x 0x%x", cData[0], |
388 | cData[1], cData[2], cData[3], cData[4]); | 426 | cData[1], cData[2], cData[3], cData[4]); |
389 | return -1; | 427 | return -1; /* panicf() doesn't return though */ |
390 | } | 428 | } |
391 | 429 | ||
392 | internal_param.bus_width = 8; | 430 | internal_param.bus_width = 8; |
@@ -400,23 +438,39 @@ int nand_init(void) | |||
400 | 438 | ||
401 | void jz_nand_read(int block, int page, unsigned char *buf) | 439 | void jz_nand_read(int block, int page, unsigned char *buf) |
402 | { | 440 | { |
403 | nand_read_page(block, page, buf); | 441 | jz_nand_read_page(block, page, buf); |
404 | } | 442 | } |
405 | 443 | ||
406 | int nand_read_sectors(IF_MV2(int drive,) unsigned long start, int count, void* buf) | 444 | static bool inited = false; |
445 | int nand_init(void) | ||
446 | { | ||
447 | int res = 0; | ||
448 | |||
449 | if(!inited) | ||
450 | { | ||
451 | res = jz_nand_init(); | ||
452 | inited = true; | ||
453 | } | ||
454 | |||
455 | return res; | ||
456 | } | ||
457 | |||
458 | /* TODO */ | ||
459 | int nand_read_sectors(unsigned long start, int count, void* buf) | ||
407 | { | 460 | { |
408 | (void)start; | 461 | (void)start; |
409 | (void)count; | 462 | (void)count; |
410 | (void)buf; | 463 | (void)buf; |
411 | return 0; | 464 | return -1; |
412 | } | 465 | } |
413 | 466 | ||
414 | int nand_write_sectors(IF_MV2(int drive,) unsigned long start, int count, const void* buf) | 467 | /* TODO */ |
468 | int nand_write_sectors(unsigned long start, int count, const void* buf) | ||
415 | { | 469 | { |
416 | (void)start; | 470 | (void)start; |
417 | (void)count; | 471 | (void)count; |
418 | (void)buf; | 472 | (void)buf; |
419 | return 0; | 473 | return -1; |
420 | } | 474 | } |
421 | 475 | ||
422 | void nand_spindown(int seconds) | 476 | void nand_spindown(int seconds) |
diff --git a/firmware/target/mips/ingenic_jz47xx/ata-nand-target.h b/firmware/target/mips/ingenic_jz47xx/ata-nand-target.h new file mode 100644 index 0000000000..c8b2376e41 --- /dev/null +++ b/firmware/target/mips/ingenic_jz47xx/ata-nand-target.h | |||
@@ -0,0 +1,28 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2008 by Maurus Cuelenaere | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #ifndef ATA_NAND_TARGET_H | ||
22 | #define ATA_NAND_TARGET_H | ||
23 | |||
24 | int nand_read_sectors(unsigned long start, int count, void* buf); | ||
25 | int nand_write_sectors(unsigned long start, int count, const void* buf); | ||
26 | int nand_init(void); | ||
27 | |||
28 | #endif | ||
diff --git a/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4740.c b/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4740.c new file mode 100644 index 0000000000..ccd71630a6 --- /dev/null +++ b/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4740.c | |||
@@ -0,0 +1,1168 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2008 by Maurus Cuelenaere | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #include "config.h" | ||
23 | #include "jz4740.h" | ||
24 | #include "ata.h" | ||
25 | #include "ata-sd-target.h" | ||
26 | #include "system.h" | ||
27 | #include "kernel.h" | ||
28 | #include "panic.h" | ||
29 | #include "debug.h" | ||
30 | |||
31 | static struct wakeup sd_wakeup; | ||
32 | |||
33 | //#define MMC_DMA_ENABLE | ||
34 | #define MMC_DMA_INTERRUPT 0 | ||
35 | |||
36 | //#define DEBUG(x...) DEBUGF(x); | ||
37 | #define DEBUG(x...) printf(x); | ||
38 | |||
39 | #define MMC_CD_PIN (29 + 1 * 32) /* Pin to check card insertion */ | ||
40 | #define MMC_POWER_PIN (30 + 1 * 32) /* Pin to enable/disable card power */ | ||
41 | //#define MMC_PW_PIN (14 + 3 * 32) /* Pin to check protect card */ | ||
42 | |||
43 | #define MMC_POWER_OFF() \ | ||
44 | do { \ | ||
45 | __gpio_set_pin(MMC_POWER_PIN); \ | ||
46 | } while (0) | ||
47 | |||
48 | #define MMC_POWER_ON() \ | ||
49 | do { \ | ||
50 | __gpio_clear_pin(MMC_POWER_PIN); \ | ||
51 | } while (0) | ||
52 | |||
53 | #define MMC_INSERT_STATUS() __gpio_get_pin(MMC_CD_PIN) | ||
54 | |||
55 | #define MMC_RESET() __msc_reset() | ||
56 | |||
57 | #define MMC_IRQ_MASK() \ | ||
58 | do { \ | ||
59 | REG_MSC_IMASK = 0xffff; \ | ||
60 | REG_MSC_IREG = 0xffff; \ | ||
61 | } while (0) | ||
62 | |||
63 | static inline void mmc_init_gpio(void) | ||
64 | { | ||
65 | __gpio_as_msc(); | ||
66 | #ifdef MMC_POWER_PIN | ||
67 | __gpio_as_output(MMC_POWER_PIN); | ||
68 | __gpio_disable_pull(MMC_POWER_PIN); | ||
69 | __gpio_set_pin(MMC_POWER_PIN); | ||
70 | #endif | ||
71 | #ifdef MMC_CD_PIN | ||
72 | __gpio_as_input(MMC_CD_PIN); | ||
73 | __gpio_disable_pull(MMC_CD_PIN); | ||
74 | #endif | ||
75 | #ifdef MMC_PW_PIN | ||
76 | __gpio_as_input(MMC_PW_PIN); | ||
77 | __gpio_disable_pull(MMC_PW_PIN); | ||
78 | #endif | ||
79 | } | ||
80 | |||
81 | /* Error codes */ | ||
82 | enum mmc_result_t | ||
83 | { | ||
84 | MMC_NO_RESPONSE = -1, | ||
85 | MMC_NO_ERROR = 0, | ||
86 | MMC_ERROR_OUT_OF_RANGE, | ||
87 | MMC_ERROR_ADDRESS, | ||
88 | MMC_ERROR_BLOCK_LEN, | ||
89 | MMC_ERROR_ERASE_SEQ, | ||
90 | MMC_ERROR_ERASE_PARAM, | ||
91 | MMC_ERROR_WP_VIOLATION, | ||
92 | MMC_ERROR_CARD_IS_LOCKED, | ||
93 | MMC_ERROR_LOCK_UNLOCK_FAILED, | ||
94 | MMC_ERROR_COM_CRC, | ||
95 | MMC_ERROR_ILLEGAL_COMMAND, | ||
96 | MMC_ERROR_CARD_ECC_FAILED, | ||
97 | MMC_ERROR_CC, | ||
98 | MMC_ERROR_GENERAL, | ||
99 | MMC_ERROR_UNDERRUN, | ||
100 | MMC_ERROR_OVERRUN, | ||
101 | MMC_ERROR_CID_CSD_OVERWRITE, | ||
102 | MMC_ERROR_STATE_MISMATCH, | ||
103 | MMC_ERROR_HEADER_MISMATCH, | ||
104 | MMC_ERROR_TIMEOUT, | ||
105 | MMC_ERROR_CRC, | ||
106 | MMC_ERROR_DRIVER_FAILURE, | ||
107 | }; | ||
108 | |||
109 | /* Standard MMC/SD clock speeds */ | ||
110 | #define MMC_CLOCK_SLOW 400000 /* 400 kHz for initial setup */ | ||
111 | #define MMC_CLOCK_FAST 20000000 /* 20 MHz for maximum for normal operation */ | ||
112 | #define SD_CLOCK_FAST 24000000 /* 24 MHz for SD Cards */ | ||
113 | #define SD_CLOCK_HIGH 48000000 /* 48 MHz for SD Cards */ | ||
114 | |||
115 | /* Extra MMC commands for state control */ | ||
116 | /* Use negative numbers to disambiguate */ | ||
117 | #define MMC_CIM_RESET -1 | ||
118 | |||
119 | /* Standard MMC commands (3.1) type argument response */ | ||
120 | /* class 1 */ | ||
121 | #define MMC_GO_IDLE_STATE 0 /* bc */ | ||
122 | #define MMC_SEND_OP_COND 1 /* bcr [31:0] OCR R3 */ | ||
123 | #define MMC_ALL_SEND_CID 2 /* bcr R2 */ | ||
124 | #define MMC_SET_RELATIVE_ADDR 3 /* ac [31:16] RCA R1 */ | ||
125 | #define MMC_SET_DSR 4 /* bc [31:16] RCA */ | ||
126 | #define MMC_SELECT_CARD 7 /* ac [31:16] RCA R1 */ | ||
127 | #define MMC_SEND_CSD 9 /* ac [31:16] RCA R2 */ | ||
128 | #define MMC_SEND_CID 10 /* ac [31:16] RCA R2 */ | ||
129 | #define MMC_READ_DAT_UNTIL_STOP 11 /* adtc [31:0] dadr R1 */ | ||
130 | #define MMC_STOP_TRANSMISSION 12 /* ac R1b */ | ||
131 | #define MMC_SEND_STATUS 13 /* ac [31:16] RCA R1 */ | ||
132 | #define MMC_GO_INACTIVE_STATE 15 /* ac [31:16] RCA */ | ||
133 | |||
134 | /* class 2 */ | ||
135 | #define MMC_SET_BLOCKLEN 16 /* ac [31:0] block len R1 */ | ||
136 | #define MMC_READ_SINGLE_BLOCK 17 /* adtc [31:0] data addr R1 */ | ||
137 | #define MMC_READ_MULTIPLE_BLOCK 18 /* adtc [31:0] data addr R1 */ | ||
138 | |||
139 | /* class 3 */ | ||
140 | #define MMC_WRITE_DAT_UNTIL_STOP 20 /* adtc [31:0] data addr R1 */ | ||
141 | |||
142 | /* class 4 */ | ||
143 | #define MMC_SET_BLOCK_COUNT 23 /* adtc [31:0] data addr R1 */ | ||
144 | #define MMC_WRITE_BLOCK 24 /* adtc [31:0] data addr R1 */ | ||
145 | #define MMC_WRITE_MULTIPLE_BLOCK 25 /* adtc R1 */ | ||
146 | #define MMC_PROGRAM_CID 26 /* adtc R1 */ | ||
147 | #define MMC_PROGRAM_CSD 27 /* adtc R1 */ | ||
148 | |||
149 | /* class 6 */ | ||
150 | #define MMC_SET_WRITE_PROT 28 /* ac [31:0] data addr R1b */ | ||
151 | #define MMC_CLR_WRITE_PROT 29 /* ac [31:0] data addr R1b */ | ||
152 | #define MMC_SEND_WRITE_PROT 30 /* adtc [31:0] wpdata addr R1 */ | ||
153 | |||
154 | /* class 5 */ | ||
155 | #define MMC_ERASE_GROUP_START 35 /* ac [31:0] data addr R1 */ | ||
156 | #define MMC_ERASE_GROUP_END 36 /* ac [31:0] data addr R1 */ | ||
157 | #define MMC_ERASE 37 /* ac R1b */ | ||
158 | |||
159 | /* class 9 */ | ||
160 | #define MMC_FAST_IO 39 /* ac <Complex> R4 */ | ||
161 | #define MMC_GO_IRQ_STATE 40 /* bcr R5 */ | ||
162 | |||
163 | /* class 7 */ | ||
164 | #define MMC_LOCK_UNLOCK 42 /* adtc R1b */ | ||
165 | |||
166 | /* class 8 */ | ||
167 | #define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */ | ||
168 | #define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1b */ | ||
169 | |||
170 | /* SD class */ | ||
171 | #define SD_SEND_OP_COND 41 /* bcr [31:0] OCR R3 */ | ||
172 | #define SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */ | ||
173 | #define SEND_SCR 51 /* adtc [31:0] staff R1 */ | ||
174 | |||
175 | /* Don't change the order of these; they are used in dispatch tables */ | ||
176 | enum mmc_rsp_t | ||
177 | { | ||
178 | RESPONSE_NONE = 0, | ||
179 | RESPONSE_R1 = 1, | ||
180 | RESPONSE_R1B = 2, | ||
181 | RESPONSE_R2_CID = 3, | ||
182 | RESPONSE_R2_CSD = 4, | ||
183 | RESPONSE_R3 = 5, | ||
184 | RESPONSE_R4 = 6, | ||
185 | RESPONSE_R5 = 7, | ||
186 | RESPONSE_R6 = 8, | ||
187 | }; | ||
188 | |||
189 | |||
190 | /* | ||
191 | MMC status in R1 | ||
192 | Type | ||
193 | e : error bit | ||
194 | s : status bit | ||
195 | r : detected and set for the actual command response | ||
196 | x : detected and set during command execution. the host must poll | ||
197 | the card by sending status command in order to read these bits. | ||
198 | Clear condition | ||
199 | a : according to the card state | ||
200 | b : always related to the previous command. Reception of | ||
201 | a valid command will clear it (with a delay of one command) | ||
202 | c : clear by read | ||
203 | */ | ||
204 | |||
205 | #define R1_OUT_OF_RANGE (1 << 31) /* er, c */ | ||
206 | #define R1_ADDRESS_ERROR (1 << 30) /* erx, c */ | ||
207 | #define R1_BLOCK_LEN_ERROR (1 << 29) /* er, c */ | ||
208 | #define R1_ERASE_SEQ_ERROR (1 << 28) /* er, c */ | ||
209 | #define R1_ERASE_PARAM (1 << 27) /* ex, c */ | ||
210 | #define R1_WP_VIOLATION (1 << 26) /* erx, c */ | ||
211 | #define R1_CARD_IS_LOCKED (1 << 25) /* sx, a */ | ||
212 | #define R1_LOCK_UNLOCK_FAILED (1 << 24) /* erx, c */ | ||
213 | #define R1_COM_CRC_ERROR (1 << 23) /* er, b */ | ||
214 | #define R1_ILLEGAL_COMMAND (1 << 22) /* er, b */ | ||
215 | #define R1_CARD_ECC_FAILED (1 << 21) /* ex, c */ | ||
216 | #define R1_CC_ERROR (1 << 20) /* erx, c */ | ||
217 | #define R1_ERROR (1 << 19) /* erx, c */ | ||
218 | #define R1_UNDERRUN (1 << 18) /* ex, c */ | ||
219 | #define R1_OVERRUN (1 << 17) /* ex, c */ | ||
220 | #define R1_CID_CSD_OVERWRITE (1 << 16) /* erx, c, CID/CSD overwrite */ | ||
221 | #define R1_WP_ERASE_SKIP (1 << 15) /* sx, c */ | ||
222 | #define R1_CARD_ECC_DISABLED (1 << 14) /* sx, a */ | ||
223 | #define R1_ERASE_RESET (1 << 13) /* sr, c */ | ||
224 | #define R1_STATUS(x) (x & 0xFFFFE000) | ||
225 | #define R1_CURRENT_STATE(x) ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */ | ||
226 | #define R1_READY_FOR_DATA (1 << 8) /* sx, a */ | ||
227 | #define R1_APP_CMD (1 << 7) /* sr, c */ | ||
228 | |||
229 | enum card_state | ||
230 | { | ||
231 | CARD_STATE_EMPTY = -1, | ||
232 | CARD_STATE_IDLE = 0, | ||
233 | CARD_STATE_READY = 1, | ||
234 | CARD_STATE_IDENT = 2, | ||
235 | CARD_STATE_STBY = 3, | ||
236 | CARD_STATE_TRAN = 4, | ||
237 | CARD_STATE_DATA = 5, | ||
238 | CARD_STATE_RCV = 6, | ||
239 | CARD_STATE_PRG = 7, | ||
240 | CARD_STATE_DIS = 8, | ||
241 | }; | ||
242 | |||
243 | /* These are unpacked versions of the actual responses */ | ||
244 | struct mmc_response_r1 | ||
245 | { | ||
246 | unsigned char cmd; | ||
247 | unsigned int status; | ||
248 | }; | ||
249 | |||
250 | struct mmc_cid | ||
251 | { | ||
252 | unsigned char mid; | ||
253 | unsigned short oid; | ||
254 | unsigned char pnm[7]; /* Product name (we null-terminate) */ | ||
255 | unsigned char prv; | ||
256 | unsigned int psn; | ||
257 | unsigned char mdt; | ||
258 | }; | ||
259 | |||
260 | struct mmc_csd | ||
261 | { | ||
262 | unsigned char csd_structure; | ||
263 | unsigned char spec_vers; | ||
264 | unsigned char taac; | ||
265 | unsigned char nsac; | ||
266 | unsigned char tran_speed; | ||
267 | unsigned short ccc; | ||
268 | unsigned char read_bl_len; | ||
269 | unsigned char read_bl_partial; | ||
270 | unsigned char write_blk_misalign; | ||
271 | unsigned char read_blk_misalign; | ||
272 | unsigned char dsr_imp; | ||
273 | unsigned short c_size; | ||
274 | unsigned char vdd_r_curr_min; | ||
275 | unsigned char vdd_r_curr_max; | ||
276 | unsigned char vdd_w_curr_min; | ||
277 | unsigned char vdd_w_curr_max; | ||
278 | unsigned char c_size_mult; | ||
279 | union | ||
280 | { | ||
281 | struct /* MMC system specification version 3.1 */ | ||
282 | { | ||
283 | unsigned char erase_grp_size; | ||
284 | unsigned char erase_grp_mult; | ||
285 | } v31; | ||
286 | struct /* MMC system specification version 2.2 */ | ||
287 | { | ||
288 | unsigned char sector_size; | ||
289 | unsigned char erase_grp_size; | ||
290 | } v22; | ||
291 | } erase; | ||
292 | unsigned char wp_grp_size; | ||
293 | unsigned char wp_grp_enable; | ||
294 | unsigned char default_ecc; | ||
295 | unsigned char r2w_factor; | ||
296 | unsigned char write_bl_len; | ||
297 | unsigned char write_bl_partial; | ||
298 | unsigned char file_format_grp; | ||
299 | unsigned char copy; | ||
300 | unsigned char perm_write_protect; | ||
301 | unsigned char tmp_write_protect; | ||
302 | unsigned char file_format; | ||
303 | unsigned char ecc; | ||
304 | }; | ||
305 | |||
306 | struct mmc_response_r3 | ||
307 | { | ||
308 | unsigned int ocr; | ||
309 | }; | ||
310 | |||
311 | #define MMC_VDD_145_150 0x00000001 /* VDD voltage 1.45 - 1.50 */ | ||
312 | #define MMC_VDD_150_155 0x00000002 /* VDD voltage 1.50 - 1.55 */ | ||
313 | #define MMC_VDD_155_160 0x00000004 /* VDD voltage 1.55 - 1.60 */ | ||
314 | #define MMC_VDD_160_165 0x00000008 /* VDD voltage 1.60 - 1.65 */ | ||
315 | #define MMC_VDD_165_170 0x00000010 /* VDD voltage 1.65 - 1.70 */ | ||
316 | #define MMC_VDD_17_18 0x00000020 /* VDD voltage 1.7 - 1.8 */ | ||
317 | #define MMC_VDD_18_19 0x00000040 /* VDD voltage 1.8 - 1.9 */ | ||
318 | #define MMC_VDD_19_20 0x00000080 /* VDD voltage 1.9 - 2.0 */ | ||
319 | #define MMC_VDD_20_21 0x00000100 /* VDD voltage 2.0 ~ 2.1 */ | ||
320 | #define MMC_VDD_21_22 0x00000200 /* VDD voltage 2.1 ~ 2.2 */ | ||
321 | #define MMC_VDD_22_23 0x00000400 /* VDD voltage 2.2 ~ 2.3 */ | ||
322 | #define MMC_VDD_23_24 0x00000800 /* VDD voltage 2.3 ~ 2.4 */ | ||
323 | #define MMC_VDD_24_25 0x00001000 /* VDD voltage 2.4 ~ 2.5 */ | ||
324 | #define MMC_VDD_25_26 0x00002000 /* VDD voltage 2.5 ~ 2.6 */ | ||
325 | #define MMC_VDD_26_27 0x00004000 /* VDD voltage 2.6 ~ 2.7 */ | ||
326 | #define MMC_VDD_27_28 0x00008000 /* VDD voltage 2.7 ~ 2.8 */ | ||
327 | #define MMC_VDD_28_29 0x00010000 /* VDD voltage 2.8 ~ 2.9 */ | ||
328 | #define MMC_VDD_29_30 0x00020000 /* VDD voltage 2.9 ~ 3.0 */ | ||
329 | #define MMC_VDD_30_31 0x00040000 /* VDD voltage 3.0 ~ 3.1 */ | ||
330 | #define MMC_VDD_31_32 0x00080000 /* VDD voltage 3.1 ~ 3.2 */ | ||
331 | #define MMC_VDD_32_33 0x00100000 /* VDD voltage 3.2 ~ 3.3 */ | ||
332 | #define MMC_VDD_33_34 0x00200000 /* VDD voltage 3.3 ~ 3.4 */ | ||
333 | #define MMC_VDD_34_35 0x00400000 /* VDD voltage 3.4 ~ 3.5 */ | ||
334 | #define MMC_VDD_35_36 0x00800000 /* VDD voltage 3.5 ~ 3.6 */ | ||
335 | #define MMC_CARD_BUSY 0x80000000 /* Card Power up status bit */ | ||
336 | |||
337 | |||
338 | /* CSD field definitions */ | ||
339 | #define CSD_STRUCT_VER_1_0 0 /* Valid for system specification 1.0 - 1.2 */ | ||
340 | #define CSD_STRUCT_VER_1_1 1 /* Valid for system specification 1.4 - 2.2 */ | ||
341 | #define CSD_STRUCT_VER_1_2 2 /* Valid for system specification 3.1 */ | ||
342 | |||
343 | #define CSD_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.2 */ | ||
344 | #define CSD_SPEC_VER_1 1 /* Implements system specification 1.4 */ | ||
345 | #define CSD_SPEC_VER_2 2 /* Implements system specification 2.0 - 2.2 */ | ||
346 | #define CSD_SPEC_VER_3 3 /* Implements system specification 3.1 */ | ||
347 | |||
348 | /* the information structure of MMC/SD Card */ | ||
349 | typedef struct MMC_INFO | ||
350 | { | ||
351 | int id; /* Card index */ | ||
352 | int sd; /* MMC or SD card */ | ||
353 | int rca; /* RCA */ | ||
354 | unsigned int scr; /* SCR 63:32*/ | ||
355 | int flags; /* Ejected, inserted */ | ||
356 | enum card_state state; /* empty, ident, ready, whatever */ | ||
357 | |||
358 | /* Card specific information */ | ||
359 | struct mmc_cid cid; | ||
360 | struct mmc_csd csd; | ||
361 | unsigned int block_num; | ||
362 | unsigned int block_len; | ||
363 | unsigned int erase_unit; | ||
364 | } mmc_info; | ||
365 | |||
366 | static mmc_info mmcinfo; | ||
367 | |||
368 | struct mmc_request | ||
369 | { | ||
370 | int index; /* Slot index - used for CS lines */ | ||
371 | int cmd; /* Command to send */ | ||
372 | unsigned int arg; /* Argument to send */ | ||
373 | enum mmc_rsp_t rtype; /* Response type expected */ | ||
374 | |||
375 | /* Data transfer (these may be modified at the low level) */ | ||
376 | unsigned short nob; /* Number of blocks to transfer*/ | ||
377 | unsigned short block_len; /* Block length */ | ||
378 | unsigned char *buffer; /* Data buffer */ | ||
379 | unsigned int cnt; /* Data length, for PIO */ | ||
380 | |||
381 | /* Results */ | ||
382 | unsigned char response[18]; /* Buffer to store response - CRC is optional */ | ||
383 | enum mmc_result_t result; | ||
384 | }; | ||
385 | |||
386 | #define MMC_OCR_ARG 0x00ff8000 /* Argument of OCR */ | ||
387 | |||
388 | /*********************************************************************** | ||
389 | * MMC Events | ||
390 | */ | ||
391 | #define MMC_EVENT_NONE 0x00 /* No events */ | ||
392 | #define MMC_EVENT_RX_DATA_DONE 0x01 /* Rx data done */ | ||
393 | #define MMC_EVENT_TX_DATA_DONE 0x02 /* Tx data done */ | ||
394 | #define MMC_EVENT_PROG_DONE 0x04 /* Programming is done */ | ||
395 | |||
396 | static int use_4bit; /* Use 4-bit data bus */ | ||
397 | static int num_6; | ||
398 | static int sd2_0; | ||
399 | |||
400 | /* Stop the MMC clock and wait while it happens */ | ||
401 | static inline int jz_mmc_stop_clock(void) | ||
402 | { | ||
403 | int timeout = 1000; | ||
404 | |||
405 | DEBUG("stop MMC clock"); | ||
406 | REG_MSC_STRPCL = MSC_STRPCL_CLOCK_CONTROL_STOP; | ||
407 | |||
408 | while (timeout && (REG_MSC_STAT & MSC_STAT_CLK_EN)) | ||
409 | { | ||
410 | timeout--; | ||
411 | if (timeout == 0) | ||
412 | { | ||
413 | DEBUG("Timeout on stop clock waiting"); | ||
414 | return MMC_ERROR_TIMEOUT; | ||
415 | } | ||
416 | udelay(1); | ||
417 | } | ||
418 | DEBUG("clock off time is %d microsec", timeout); | ||
419 | return MMC_NO_ERROR; | ||
420 | } | ||
421 | |||
422 | /* Start the MMC clock and operation */ | ||
423 | static inline int jz_mmc_start_clock(void) | ||
424 | { | ||
425 | REG_MSC_STRPCL = | ||
426 | MSC_STRPCL_CLOCK_CONTROL_START | MSC_STRPCL_START_OP; | ||
427 | return MMC_NO_ERROR; | ||
428 | } | ||
429 | |||
430 | static inline unsigned int jz_mmc_calc_clkrt(int is_sd, unsigned int rate) | ||
431 | { | ||
432 | unsigned int clkrt; | ||
433 | unsigned int clk_src = is_sd ? 24000000 : 20000000; | ||
434 | |||
435 | clkrt = 0; | ||
436 | while (rate < clk_src) | ||
437 | { | ||
438 | clkrt++; | ||
439 | clk_src >>= 1; | ||
440 | } | ||
441 | return clkrt; | ||
442 | } | ||
443 | |||
444 | static int jz_mmc_check_status(struct mmc_request *request) | ||
445 | { | ||
446 | unsigned int status = REG_MSC_STAT; | ||
447 | |||
448 | /* Checking for response or data timeout */ | ||
449 | if (status & (MSC_STAT_TIME_OUT_RES | MSC_STAT_TIME_OUT_READ)) | ||
450 | { | ||
451 | DEBUG("MMC/SD timeout, MMC_STAT 0x%x CMD %d", status, | ||
452 | request->cmd); | ||
453 | return MMC_ERROR_TIMEOUT; | ||
454 | } | ||
455 | |||
456 | /* Checking for CRC error */ | ||
457 | if (status & | ||
458 | (MSC_STAT_CRC_READ_ERROR | MSC_STAT_CRC_WRITE_ERROR | | ||
459 | MSC_STAT_CRC_RES_ERR)) | ||
460 | { | ||
461 | DEBUG("MMC/CD CRC error, MMC_STAT 0x%x", status); | ||
462 | return MMC_ERROR_CRC; | ||
463 | } | ||
464 | |||
465 | return MMC_NO_ERROR; | ||
466 | } | ||
467 | |||
468 | /* Obtain response to the command and store it to response buffer */ | ||
469 | static void jz_mmc_get_response(struct mmc_request *request) | ||
470 | { | ||
471 | int i; | ||
472 | unsigned char *buf; | ||
473 | unsigned int data; | ||
474 | |||
475 | DEBUG("fetch response for request %d, cmd %d", request->rtype, | ||
476 | request->cmd); | ||
477 | buf = request->response; | ||
478 | request->result = MMC_NO_ERROR; | ||
479 | |||
480 | switch (request->rtype) | ||
481 | { | ||
482 | case RESPONSE_R1: | ||
483 | case RESPONSE_R1B: | ||
484 | case RESPONSE_R6: | ||
485 | case RESPONSE_R3: | ||
486 | case RESPONSE_R4: | ||
487 | case RESPONSE_R5: | ||
488 | { | ||
489 | data = REG_MSC_RES; | ||
490 | buf[0] = (data >> 8) & 0xff; | ||
491 | buf[1] = data & 0xff; | ||
492 | data = REG_MSC_RES; | ||
493 | buf[2] = (data >> 8) & 0xff; | ||
494 | buf[3] = data & 0xff; | ||
495 | data = REG_MSC_RES; | ||
496 | buf[4] = data & 0xff; | ||
497 | |||
498 | DEBUG("request %d, response [%02x %02x %02x %02x %02x]", | ||
499 | request->rtype, buf[0], buf[1], buf[2], | ||
500 | buf[3], buf[4]); | ||
501 | break; | ||
502 | } | ||
503 | case RESPONSE_R2_CID: | ||
504 | case RESPONSE_R2_CSD: | ||
505 | { | ||
506 | for (i = 0; i < 16; i += 2) | ||
507 | { | ||
508 | data = REG_MSC_RES; | ||
509 | buf[i] = (data >> 8) & 0xff; | ||
510 | buf[i + 1] = data & 0xff; | ||
511 | } | ||
512 | DEBUG("request %d, response [", request->rtype); | ||
513 | break; | ||
514 | } | ||
515 | case RESPONSE_NONE: | ||
516 | DEBUG("No response"); | ||
517 | break; | ||
518 | |||
519 | default: | ||
520 | DEBUG("unhandled response type for request %d", | ||
521 | request->rtype); | ||
522 | break; | ||
523 | } | ||
524 | } | ||
525 | |||
526 | #ifdef MMC_DMA_ENABLE | ||
527 | static int jz_mmc_receive_data_dma(struct mmc_request *req) | ||
528 | { | ||
529 | int ch = RX_DMA_CHANNEL; | ||
530 | unsigned int size = req->block_len * req->nob; | ||
531 | unsigned char err = 0; | ||
532 | |||
533 | /* flush dcache */ | ||
534 | dma_cache_wback_inv((unsigned long) req->buffer, size); | ||
535 | /* setup dma channel */ | ||
536 | REG_DMAC_DSAR(ch) = PHYSADDR(MSC_RXFIFO); /* DMA source addr */ | ||
537 | REG_DMAC_DTAR(ch) = PHYSADDR((unsigned long) req->buffer); /* DMA dest addr */ | ||
538 | REG_DMAC_DTCR(ch) = (size + 3) / 4; /* DMA transfer count */ | ||
539 | REG_DMAC_DRSR(ch) = DMAC_DRSR_RS_MSCIN; /* DMA request type */ | ||
540 | |||
541 | #if MMC_DMA_INTERRUPT | ||
542 | REG_DMAC_DCMD(ch) = | ||
543 | DMAC_DCMD_DAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | | ||
544 | DMAC_DCMD_DS_32BIT | DMAC_DCMD_TIE; | ||
545 | REG_DMAC_DCCSR(ch) = DMAC_DCCSR_EN | DMAC_DCCSR_NDES; | ||
546 | OSSemPend(mmc_dma_rx_sem, 100, &err); | ||
547 | #else | ||
548 | REG_DMAC_DCMD(ch) = | ||
549 | DMAC_DCMD_DAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | | ||
550 | DMAC_DCMD_DS_32BIT; | ||
551 | REG_DMAC_DCCSR(ch) = DMAC_DCCSR_EN | DMAC_DCCSR_NDES; | ||
552 | while (REG_DMAC_DTCR(ch)); | ||
553 | #endif | ||
554 | /* clear status and disable channel */ | ||
555 | REG_DMAC_DCCSR(ch) = 0; | ||
556 | #if MMC_DMA_INTERRUPT | ||
557 | return (err == OS_NO_ERR); | ||
558 | #else | ||
559 | return 0; | ||
560 | #endif | ||
561 | } | ||
562 | |||
563 | static int jz_mmc_transmit_data_dma(struct mmc_request *req) | ||
564 | { | ||
565 | int ch = TX_DMA_CHANNEL; | ||
566 | unsigned int size = req->block_len * req->nob; | ||
567 | unsigned char err = 0; | ||
568 | |||
569 | /* flush dcache */ | ||
570 | dma_cache_wback_inv((unsigned long) req->buffer, size); | ||
571 | /* setup dma channel */ | ||
572 | REG_DMAC_DSAR(ch) = PHYSADDR((unsigned long) req->buffer); /* DMA source addr */ | ||
573 | REG_DMAC_DTAR(ch) = PHYSADDR(MSC_TXFIFO); /* DMA dest addr */ | ||
574 | REG_DMAC_DTCR(ch) = (size + 3) / 4; /* DMA transfer count */ | ||
575 | REG_DMAC_DRSR(ch) = DMAC_DRSR_RS_MSCOUT; /* DMA request type */ | ||
576 | |||
577 | #if MMC_DMA_INTERRUPT | ||
578 | REG_DMAC_DCMD(ch) = | ||
579 | DMAC_DCMD_SAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | | ||
580 | DMAC_DCMD_DS_32BIT | DMAC_DCMD_TIE; | ||
581 | REG_DMAC_DCCSR(ch) = DMAC_DCCSR_EN | DMAC_DCCSR_NDES; | ||
582 | OSSemPend(mmc_dma_tx_sem, 100, &err); | ||
583 | #else | ||
584 | REG_DMAC_DCMD(ch) = | ||
585 | DMAC_DCMD_SAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | | ||
586 | DMAC_DCMD_DS_32BIT; | ||
587 | REG_DMAC_DCCSR(ch) = DMAC_DCCSR_EN | DMAC_DCCSR_NDES; | ||
588 | /* wait for dma completion */ | ||
589 | while (REG_DMAC_DTCR(ch)); | ||
590 | #endif | ||
591 | /* clear status and disable channel */ | ||
592 | REG_DMAC_DCCSR(ch) = 0; | ||
593 | #if MMC_DMA_INTERRUPT | ||
594 | return (err == OS_NO_ERR); | ||
595 | #else | ||
596 | return 0; | ||
597 | #endif | ||
598 | } | ||
599 | |||
600 | #endif /* MMC_DMA_ENABLE */ | ||
601 | |||
602 | static int jz_mmc_receive_data(struct mmc_request *req) | ||
603 | { | ||
604 | unsigned int nob = req->nob; | ||
605 | unsigned int wblocklen = (unsigned int) (req->block_len + 3) >> 2; /* length in word */ | ||
606 | unsigned char *buf = req->buffer; | ||
607 | unsigned int *wbuf = (unsigned int *) buf; | ||
608 | unsigned int waligned = (((unsigned int) buf & 0x3) == 0); /* word aligned ? */ | ||
609 | unsigned int stat, timeout, data, cnt; | ||
610 | |||
611 | for (; nob >= 1; nob--) | ||
612 | { | ||
613 | timeout = 0x3FFFFFF; | ||
614 | |||
615 | while (timeout) | ||
616 | { | ||
617 | timeout--; | ||
618 | stat = REG_MSC_STAT; | ||
619 | |||
620 | if (stat & MSC_STAT_TIME_OUT_READ) | ||
621 | return MMC_ERROR_TIMEOUT; | ||
622 | else if (stat & MSC_STAT_CRC_READ_ERROR) | ||
623 | return MMC_ERROR_CRC; | ||
624 | else if (!(stat & MSC_STAT_DATA_FIFO_EMPTY) | ||
625 | || (stat & MSC_STAT_DATA_FIFO_AFULL)) { | ||
626 | /* Ready to read data */ | ||
627 | break; | ||
628 | } | ||
629 | |||
630 | udelay(1); | ||
631 | } | ||
632 | |||
633 | if (!timeout) | ||
634 | return MMC_ERROR_TIMEOUT; | ||
635 | |||
636 | /* Read data from RXFIFO. It could be FULL or PARTIAL FULL */ | ||
637 | DEBUG("Receive Data = %d", wblocklen); | ||
638 | cnt = wblocklen; | ||
639 | while (cnt) | ||
640 | { | ||
641 | data = REG_MSC_RXFIFO; | ||
642 | if (waligned) | ||
643 | *wbuf++ = data; | ||
644 | else | ||
645 | { | ||
646 | *buf++ = (unsigned char) (data >> 0); | ||
647 | *buf++ = (unsigned char) (data >> 8); | ||
648 | *buf++ = (unsigned char) (data >> 16); | ||
649 | *buf++ = (unsigned char) (data >> 24); | ||
650 | } | ||
651 | cnt--; | ||
652 | while (cnt | ||
653 | && (REG_MSC_STAT & | ||
654 | MSC_STAT_DATA_FIFO_EMPTY)); | ||
655 | } | ||
656 | } | ||
657 | |||
658 | return MMC_NO_ERROR; | ||
659 | } | ||
660 | |||
661 | static int jz_mmc_transmit_data(struct mmc_request *req) | ||
662 | { | ||
663 | unsigned int nob = req->nob; | ||
664 | unsigned int wblocklen = (unsigned int) (req->block_len + 3) >> 2; /* length in word */ | ||
665 | unsigned char *buf = req->buffer; | ||
666 | unsigned int *wbuf = (unsigned int *) buf; | ||
667 | unsigned int waligned = (((unsigned int) buf & 0x3) == 0); /* word aligned ? */ | ||
668 | unsigned int stat, timeout, data, cnt; | ||
669 | |||
670 | for (; nob >= 1; nob--) | ||
671 | { | ||
672 | timeout = 0x3FFFFFF; | ||
673 | |||
674 | while (timeout) | ||
675 | { | ||
676 | timeout--; | ||
677 | stat = REG_MSC_STAT; | ||
678 | |||
679 | if (stat & | ||
680 | (MSC_STAT_CRC_WRITE_ERROR | | ||
681 | MSC_STAT_CRC_WRITE_ERROR_NOSTS)) | ||
682 | return MMC_ERROR_CRC; | ||
683 | else if (!(stat & MSC_STAT_DATA_FIFO_FULL)) | ||
684 | { | ||
685 | /* Ready to write data */ | ||
686 | break; | ||
687 | } | ||
688 | |||
689 | udelay(1); | ||
690 | } | ||
691 | |||
692 | if (!timeout) | ||
693 | return MMC_ERROR_TIMEOUT; | ||
694 | |||
695 | /* Write data to TXFIFO */ | ||
696 | cnt = wblocklen; | ||
697 | while (cnt) | ||
698 | { | ||
699 | while (REG_MSC_STAT & MSC_STAT_DATA_FIFO_FULL); | ||
700 | |||
701 | if (waligned) | ||
702 | REG_MSC_TXFIFO = *wbuf++; | ||
703 | else | ||
704 | { | ||
705 | data = *buf++; | ||
706 | data |= *buf++ << 8; | ||
707 | data |= *buf++ << 16; | ||
708 | data |= *buf++ << 24; | ||
709 | REG_MSC_TXFIFO = data; | ||
710 | } | ||
711 | |||
712 | cnt--; | ||
713 | } | ||
714 | } | ||
715 | |||
716 | return MMC_NO_ERROR; | ||
717 | } | ||
718 | |||
719 | /* Set the MMC clock frequency */ | ||
720 | static void jz_mmc_set_clock(int sd, unsigned int rate) | ||
721 | { | ||
722 | int clkrt = 0; | ||
723 | |||
724 | sd = sd ? 1 : 0; | ||
725 | |||
726 | jz_mmc_stop_clock(); | ||
727 | |||
728 | if(sd2_0) | ||
729 | { | ||
730 | __cpm_select_msc_hs_clk(sd); /* select clock source from CPM */ | ||
731 | REG_CPM_CPCCR |= CPM_CPCCR_CE; | ||
732 | REG_MSC_CLKRT = 0; | ||
733 | } | ||
734 | else | ||
735 | { | ||
736 | __cpm_select_msc_clk(sd); /* select clock source from CPM */ | ||
737 | REG_CPM_CPCCR |= CPM_CPCCR_CE; | ||
738 | clkrt = jz_mmc_calc_clkrt(sd, rate); | ||
739 | REG_MSC_CLKRT = clkrt; | ||
740 | } | ||
741 | DEBUG("set clock to %u Hz is_sd=%d clkrt=%d", rate, sd, clkrt); | ||
742 | } | ||
743 | |||
744 | /******************************************************************************************************************** | ||
745 | ** Name: int jz_mmc_exec_cmd() | ||
746 | ** Function: send command to the card, and get a response | ||
747 | ** Input: struct mmc_request *req: MMC/SD request | ||
748 | ** Output: 0: right >0: error code | ||
749 | ********************************************************************************************************************/ | ||
750 | static int jz_mmc_exec_cmd(struct mmc_request *request) | ||
751 | { | ||
752 | unsigned int cmdat = 0, events = 0; | ||
753 | int retval, timeout = 0x3fffff; | ||
754 | |||
755 | /* Indicate we have no result yet */ | ||
756 | request->result = MMC_NO_RESPONSE; | ||
757 | if (request->cmd == MMC_CIM_RESET) | ||
758 | { | ||
759 | /* On reset, 1-bit bus width */ | ||
760 | use_4bit = 0; | ||
761 | |||
762 | /* Reset MMC/SD controller */ | ||
763 | __msc_reset(); | ||
764 | |||
765 | /* On reset, drop MMC clock down */ | ||
766 | jz_mmc_set_clock(0, MMC_CLOCK_SLOW); | ||
767 | |||
768 | /* On reset, stop MMC clock */ | ||
769 | jz_mmc_stop_clock(); | ||
770 | } | ||
771 | if (request->cmd == MMC_SEND_OP_COND) | ||
772 | { | ||
773 | DEBUG("Have a MMC card"); | ||
774 | /* always use 1bit for MMC */ | ||
775 | use_4bit = 0; | ||
776 | } | ||
777 | if (request->cmd == SET_BUS_WIDTH) | ||
778 | { | ||
779 | if (request->arg == 0x2) | ||
780 | { | ||
781 | DEBUG("Use 4-bit bus width"); | ||
782 | use_4bit = 1; | ||
783 | } | ||
784 | else | ||
785 | { | ||
786 | DEBUG("Use 1-bit bus width"); | ||
787 | use_4bit = 0; | ||
788 | } | ||
789 | } | ||
790 | |||
791 | /* stop clock */ | ||
792 | jz_mmc_stop_clock(); | ||
793 | |||
794 | /* mask all interrupts */ | ||
795 | //REG_MSC_IMASK = 0xffff; | ||
796 | /* clear status */ | ||
797 | REG_MSC_IREG = 0xffff; | ||
798 | /*open interrupt */ | ||
799 | REG_MSC_IMASK = (~7); | ||
800 | /* use 4-bit bus width when possible */ | ||
801 | if (use_4bit) | ||
802 | cmdat |= MSC_CMDAT_BUS_WIDTH_4BIT; | ||
803 | |||
804 | /* Set command type and events */ | ||
805 | switch (request->cmd) | ||
806 | { | ||
807 | /* MMC core extra command */ | ||
808 | case MMC_CIM_RESET: | ||
809 | cmdat |= MSC_CMDAT_INIT; /* Initialization sequence sent prior to command */ | ||
810 | break; | ||
811 | |||
812 | /* bc - broadcast - no response */ | ||
813 | case MMC_GO_IDLE_STATE: | ||
814 | case MMC_SET_DSR: | ||
815 | break; | ||
816 | |||
817 | /* bcr - broadcast with response */ | ||
818 | case MMC_SEND_OP_COND: | ||
819 | case MMC_ALL_SEND_CID: | ||
820 | |||
821 | case MMC_GO_IRQ_STATE: | ||
822 | break; | ||
823 | |||
824 | /* adtc - addressed with data transfer */ | ||
825 | case MMC_READ_DAT_UNTIL_STOP: | ||
826 | case MMC_READ_SINGLE_BLOCK: | ||
827 | case MMC_READ_MULTIPLE_BLOCK: | ||
828 | case SEND_SCR: | ||
829 | #if defined(MMC_DMA_ENABLE) | ||
830 | cmdat |= | ||
831 | MSC_CMDAT_DATA_EN | MSC_CMDAT_READ | MSC_CMDAT_DMA_EN; | ||
832 | #else | ||
833 | cmdat |= MSC_CMDAT_DATA_EN | MSC_CMDAT_READ; | ||
834 | #endif | ||
835 | events = MMC_EVENT_RX_DATA_DONE; | ||
836 | break; | ||
837 | |||
838 | case 6: | ||
839 | if (num_6 < 2) | ||
840 | { | ||
841 | |||
842 | #if defined(MMC_DMA_ENABLE) | ||
843 | cmdat |= | ||
844 | MSC_CMDAT_DATA_EN | MSC_CMDAT_READ | | ||
845 | MSC_CMDAT_DMA_EN; | ||
846 | #else | ||
847 | cmdat |= MSC_CMDAT_DATA_EN | MSC_CMDAT_READ; | ||
848 | #endif | ||
849 | events = MMC_EVENT_RX_DATA_DONE; | ||
850 | } | ||
851 | break; | ||
852 | |||
853 | case MMC_WRITE_DAT_UNTIL_STOP: | ||
854 | case MMC_WRITE_BLOCK: | ||
855 | case MMC_WRITE_MULTIPLE_BLOCK: | ||
856 | case MMC_PROGRAM_CID: | ||
857 | case MMC_PROGRAM_CSD: | ||
858 | case MMC_SEND_WRITE_PROT: | ||
859 | case MMC_GEN_CMD: | ||
860 | case MMC_LOCK_UNLOCK: | ||
861 | #if defined(MMC_DMA_ENABLE) | ||
862 | cmdat |= | ||
863 | MSC_CMDAT_DATA_EN | MSC_CMDAT_WRITE | MSC_CMDAT_DMA_EN; | ||
864 | #else | ||
865 | cmdat |= MSC_CMDAT_DATA_EN | MSC_CMDAT_WRITE; | ||
866 | #endif | ||
867 | events = MMC_EVENT_TX_DATA_DONE | MMC_EVENT_PROG_DONE; | ||
868 | break; | ||
869 | |||
870 | case MMC_STOP_TRANSMISSION: | ||
871 | events = MMC_EVENT_PROG_DONE; | ||
872 | break; | ||
873 | |||
874 | /* ac - no data transfer */ | ||
875 | default: | ||
876 | break; | ||
877 | } | ||
878 | |||
879 | /* Set response type */ | ||
880 | switch (request->rtype) | ||
881 | { | ||
882 | case RESPONSE_NONE: | ||
883 | break; | ||
884 | case RESPONSE_R1B: | ||
885 | cmdat |= MSC_CMDAT_BUSY; | ||
886 | /*FALLTHRU*/ | ||
887 | case RESPONSE_R1: | ||
888 | cmdat |= MSC_CMDAT_RESPONSE_R1; | ||
889 | break; | ||
890 | case RESPONSE_R2_CID: | ||
891 | case RESPONSE_R2_CSD: | ||
892 | cmdat |= MSC_CMDAT_RESPONSE_R2; | ||
893 | break; | ||
894 | case RESPONSE_R3: | ||
895 | cmdat |= MSC_CMDAT_RESPONSE_R3; | ||
896 | break; | ||
897 | case RESPONSE_R4: | ||
898 | cmdat |= MSC_CMDAT_RESPONSE_R4; | ||
899 | break; | ||
900 | case RESPONSE_R5: | ||
901 | cmdat |= MSC_CMDAT_RESPONSE_R5; | ||
902 | break; | ||
903 | case RESPONSE_R6: | ||
904 | cmdat |= MSC_CMDAT_RESPONSE_R6; | ||
905 | break; | ||
906 | default: | ||
907 | break; | ||
908 | } | ||
909 | |||
910 | /* Set command index */ | ||
911 | if (request->cmd == MMC_CIM_RESET) | ||
912 | REG_MSC_CMD = MMC_GO_IDLE_STATE; | ||
913 | else | ||
914 | REG_MSC_CMD = request->cmd; | ||
915 | |||
916 | /* Set argument */ | ||
917 | REG_MSC_ARG = request->arg; | ||
918 | |||
919 | /* Set block length and nob */ | ||
920 | if (request->cmd == SEND_SCR) | ||
921 | { /* get SCR from DataFIFO */ | ||
922 | REG_MSC_BLKLEN = 8; | ||
923 | REG_MSC_NOB = 1; | ||
924 | } | ||
925 | else | ||
926 | { | ||
927 | REG_MSC_BLKLEN = request->block_len; | ||
928 | REG_MSC_NOB = request->nob; | ||
929 | } | ||
930 | |||
931 | /* Set command */ | ||
932 | REG_MSC_CMDAT = cmdat; | ||
933 | |||
934 | DEBUG("Send cmd %d cmdat: %x arg: %x resp %d", request->cmd, | ||
935 | cmdat, request->arg, request->rtype); | ||
936 | |||
937 | /* Start MMC/SD clock and send command to card */ | ||
938 | jz_mmc_start_clock(); | ||
939 | |||
940 | /* Wait for command completion */ | ||
941 | //__intc_unmask_irq(IRQ_MSC); | ||
942 | //wakeup_wait(&sd_wakeup, 100); | ||
943 | while (timeout-- && !(REG_MSC_STAT & MSC_STAT_END_CMD_RES)); | ||
944 | |||
945 | |||
946 | if (timeout == 0) | ||
947 | return MMC_ERROR_TIMEOUT; | ||
948 | |||
949 | REG_MSC_IREG = MSC_IREG_END_CMD_RES; /* clear flag */ | ||
950 | |||
951 | /* Check for status */ | ||
952 | retval = jz_mmc_check_status(request); | ||
953 | if (retval) | ||
954 | return retval; | ||
955 | |||
956 | /* Complete command with no response */ | ||
957 | if (request->rtype == RESPONSE_NONE) | ||
958 | return MMC_NO_ERROR; | ||
959 | |||
960 | /* Get response */ | ||
961 | jz_mmc_get_response(request); | ||
962 | |||
963 | /* Start data operation */ | ||
964 | if (events & (MMC_EVENT_RX_DATA_DONE | MMC_EVENT_TX_DATA_DONE)) | ||
965 | { | ||
966 | if (events & MMC_EVENT_RX_DATA_DONE) | ||
967 | { | ||
968 | if (request->cmd == SEND_SCR) | ||
969 | { | ||
970 | /* SD card returns SCR register as data. | ||
971 | MMC core expect it in the response buffer, | ||
972 | after normal response. */ | ||
973 | request->buffer = | ||
974 | (unsigned char *) ((unsigned int) request->response + 5); | ||
975 | } | ||
976 | #ifdef MMC_DMA_ENABLE | ||
977 | jz_mmc_receive_data_dma(request); | ||
978 | #else | ||
979 | jz_mmc_receive_data(request); | ||
980 | #endif | ||
981 | } | ||
982 | |||
983 | if (events & MMC_EVENT_TX_DATA_DONE) | ||
984 | { | ||
985 | #ifdef MMC_DMA_ENABLE | ||
986 | jz_mmc_transmit_data_dma(request); | ||
987 | #else | ||
988 | jz_mmc_transmit_data(request); | ||
989 | #endif | ||
990 | } | ||
991 | //__intc_unmask_irq(IRQ_MSC); | ||
992 | //wakeup_wait(&sd_wakeup, 100); | ||
993 | /* Wait for Data Done */ | ||
994 | while (!(REG_MSC_IREG & MSC_IREG_DATA_TRAN_DONE)); | ||
995 | REG_MSC_IREG = MSC_IREG_DATA_TRAN_DONE; /* clear status */ | ||
996 | |||
997 | } | ||
998 | |||
999 | /* Wait for Prog Done event */ | ||
1000 | if (events & MMC_EVENT_PROG_DONE) | ||
1001 | { | ||
1002 | //__intc_unmask_irq(IRQ_MSC); | ||
1003 | //wakeup_wait(&sd_wakeup, 100); | ||
1004 | while (!(REG_MSC_IREG & MSC_IREG_PRG_DONE)); | ||
1005 | REG_MSC_IREG = MSC_IREG_PRG_DONE; /* clear status */ | ||
1006 | } | ||
1007 | |||
1008 | /* Command completed */ | ||
1009 | |||
1010 | return MMC_NO_ERROR; /* return successfully */ | ||
1011 | } | ||
1012 | |||
1013 | /******************************************************************************************************************* | ||
1014 | ** Name: int mmc_chkcard() | ||
1015 | ** Function: check whether card is insert entirely | ||
1016 | ** Input: NULL | ||
1017 | ** Output: 1: insert entirely 0: not insert entirely | ||
1018 | ********************************************************************************************************************/ | ||
1019 | static int jz_mmc_chkcard(void) | ||
1020 | { | ||
1021 | if (MMC_INSERT_STATUS() == 0) | ||
1022 | return 1; /* insert entirely */ | ||
1023 | else | ||
1024 | return 0; /* not insert entirely */ | ||
1025 | } | ||
1026 | |||
1027 | #if MMC_DMA_INTERRUPT | ||
1028 | static void jz_mmc_tx_handler(unsigned int arg) | ||
1029 | { | ||
1030 | if (__dmac_channel_address_error_detected(arg)) | ||
1031 | { | ||
1032 | DEBUG("%s: DMAC address error.", __FUNCTION__); | ||
1033 | __dmac_channel_clear_address_error(arg); | ||
1034 | } | ||
1035 | if (__dmac_channel_transmit_end_detected(arg)) | ||
1036 | { | ||
1037 | |||
1038 | __dmac_channel_clear_transmit_end(arg); | ||
1039 | OSSemPost(mmc_dma_tx_sem); | ||
1040 | } | ||
1041 | } | ||
1042 | |||
1043 | static void jz_mmc_rx_handler(unsigned int arg) | ||
1044 | { | ||
1045 | if (__dmac_channel_address_error_detected(arg)) | ||
1046 | { | ||
1047 | DEBUG("%s: DMAC address error.", __FUNCTION__); | ||
1048 | __dmac_channel_clear_address_error(arg); | ||
1049 | } | ||
1050 | if (__dmac_channel_transmit_end_detected(arg)) | ||
1051 | { | ||
1052 | __dmac_channel_clear_transmit_end(arg); | ||
1053 | OSSemPost(mmc_dma_rx_sem); | ||
1054 | } | ||
1055 | } | ||
1056 | #endif | ||
1057 | |||
1058 | /* MSC interrupt handler */ | ||
1059 | void MSC(void) | ||
1060 | { | ||
1061 | //wakeup_signal(&sd_wakeup); | ||
1062 | } | ||
1063 | |||
1064 | /******************************************************************************************************************* | ||
1065 | ** Name: void mmc_hardware_init() | ||
1066 | ** Function: initialize the hardware condiction that access sd card | ||
1067 | ** Input: NULL | ||
1068 | ** Output: NULL | ||
1069 | ********************************************************************************************************************/ | ||
1070 | static void jz_mmc_hardware_init(void) | ||
1071 | { | ||
1072 | mmc_init_gpio(); /* init GPIO */ | ||
1073 | MMC_POWER_ON(); /* turn on power of card */ | ||
1074 | MMC_RESET(); /* reset mmc/sd controller */ | ||
1075 | MMC_IRQ_MASK(); /* mask all IRQs */ | ||
1076 | jz_mmc_stop_clock(); /* stop MMC/SD clock */ | ||
1077 | #ifdef MMC_DMA_ENABLE | ||
1078 | __cpm_start_dmac(); | ||
1079 | __dmac_enable_module(); | ||
1080 | // REG_DMAC_DMACR = DMAC_DMACR_DME; | ||
1081 | #if MMC_DMA_INTERRUPT | ||
1082 | mmc_dma_rx_sem = OSSemCreate(0); | ||
1083 | mmc_dma_tx_sem = OSSemCreate(0); | ||
1084 | request_irq(IRQ_DMA_0 + RX_DMA_CHANNEL, jz_mmc_rx_handler, | ||
1085 | RX_DMA_CHANNEL); | ||
1086 | request_irq(IRQ_DMA_0 + TX_DMA_CHANNEL, jz_mmc_tx_handler, | ||
1087 | TX_DMA_CHANNEL); | ||
1088 | #endif | ||
1089 | #endif | ||
1090 | } | ||
1091 | |||
1092 | static void mmc_send_cmd(struct mmc_request *request, int cmd, unsigned int arg, | ||
1093 | unsigned short nob, unsigned short block_len, | ||
1094 | enum mmc_rsp_t rtype, unsigned char* buffer) | ||
1095 | { | ||
1096 | request->cmd = cmd; | ||
1097 | request->arg = arg; | ||
1098 | request->rtype = rtype; | ||
1099 | request->nob = nob; | ||
1100 | request->block_len = block_len; | ||
1101 | request->buffer = buffer; | ||
1102 | request->cnt = nob * block_len; | ||
1103 | printf("mmc_send_cmd: command = %d",cmd); | ||
1104 | jz_mmc_exec_cmd(request); | ||
1105 | } | ||
1106 | |||
1107 | static bool inited = false; | ||
1108 | int sd_init(void) | ||
1109 | { | ||
1110 | if(!inited) | ||
1111 | { | ||
1112 | jz_mmc_hardware_init(); | ||
1113 | wakeup_init(&sd_wakeup); | ||
1114 | inited = true; | ||
1115 | } | ||
1116 | |||
1117 | struct mmc_request test; | ||
1118 | //mmc_send_cmd(&test, MMC_CIM_RESET, 0, 0, 0, RESPONSE_NONE, NULL); | ||
1119 | mmc_send_cmd(&test, MMC_GO_IDLE_STATE, 0, 0, 0, RESPONSE_NONE, NULL); | ||
1120 | mmc_send_cmd(&test, SD_SEND_OP_COND, MMC_OCR_ARG, 0, 0, RESPONSE_R3, NULL); | ||
1121 | |||
1122 | return 0; | ||
1123 | } | ||
1124 | |||
1125 | bool card_detect_target(void) | ||
1126 | { | ||
1127 | return jz_mmc_chkcard() == 1; | ||
1128 | } | ||
1129 | |||
1130 | #ifdef HAVE_HOTSWAP | ||
1131 | void card_enable_monitoring_target(bool on) | ||
1132 | { | ||
1133 | if(on) | ||
1134 | { | ||
1135 | |||
1136 | } | ||
1137 | else | ||
1138 | { | ||
1139 | |||
1140 | } | ||
1141 | } | ||
1142 | #endif | ||
1143 | |||
1144 | /* TODO */ | ||
1145 | tCardInfo* card_get_info_target(int card_no) | ||
1146 | { | ||
1147 | static tCardInfo card; | ||
1148 | |||
1149 | return &card; | ||
1150 | } | ||
1151 | |||
1152 | /* TODO */ | ||
1153 | int sd_read_sectors(unsigned long start, int count, void* buf) | ||
1154 | { | ||
1155 | (void)start; | ||
1156 | (void)count; | ||
1157 | (void)buf; | ||
1158 | return -1; | ||
1159 | } | ||
1160 | |||
1161 | /* TODO */ | ||
1162 | int sd_write_sectors(unsigned long start, int count, const void* buf) | ||
1163 | { | ||
1164 | (void)start; | ||
1165 | (void)count; | ||
1166 | (void)buf; | ||
1167 | return -1; | ||
1168 | } | ||
diff --git a/firmware/target/mips/ingenic_jz47xx/ata-sd-target.h b/firmware/target/mips/ingenic_jz47xx/ata-sd-target.h new file mode 100644 index 0000000000..f788fd6a41 --- /dev/null +++ b/firmware/target/mips/ingenic_jz47xx/ata-sd-target.h | |||
@@ -0,0 +1,39 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2008 by Maurus Cuelenaere | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #ifndef ATA_SD_TARGET_H | ||
22 | #define ATA_SD_TARGET_H | ||
23 | |||
24 | #include "inttypes.h" | ||
25 | #include "hotswap.h" | ||
26 | |||
27 | tCardInfo *card_get_info_target(int card_no); | ||
28 | bool card_detect_target(void); | ||
29 | |||
30 | #ifdef HAVE_HOTSWAP | ||
31 | void card_enable_monitoring_target(bool on); | ||
32 | void microsd_int(void); /* ??? */ | ||
33 | #endif | ||
34 | |||
35 | int sd_read_sectors(unsigned long start, int count, void* buf); | ||
36 | int sd_write_sectors(unsigned long start, int count, const void* buf); | ||
37 | int sd_init(void); | ||
38 | |||
39 | #endif | ||
diff --git a/firmware/target/mips/ingenic_jz47xx/codec-jz4740.c b/firmware/target/mips/ingenic_jz47xx/codec-jz4740.c new file mode 100644 index 0000000000..6c3ed8cf2a --- /dev/null +++ b/firmware/target/mips/ingenic_jz47xx/codec-jz4740.c | |||
@@ -0,0 +1,280 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2008 by Maurus Cuelenaere | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #include "config.h" | ||
23 | #include "jz4740.h" | ||
24 | |||
25 | static unsigned short codec_volume; | ||
26 | static unsigned short codec_base_gain; | ||
27 | static unsigned short codec_mic_gain; | ||
28 | static bool HP_on_off_flag; | ||
29 | static int HP_register_value; | ||
30 | static int IS_WRITE_PCM; | ||
31 | |||
32 | static void i2s_codec_clear(void) | ||
33 | { | ||
34 | REG_ICDC_CDCCR1 = (ICDC_CDCCR1_SW2ON | ICDC_CDCCR1_PDVR | ICDC_CDCCR1_PDVRA | ICDC_CDCCR1_VRCGL | | ||
35 | ICDC_CDCCR1_VRCGH | ICDC_CDCCR1_HPOV0 | ICDC_CDCCR1_PDHPM | ICDC_CDCCR1_PDHP | | ||
36 | ICDC_CDCCR1_SUSPD | ICDC_CDCCR1_RST); | ||
37 | } | ||
38 | |||
39 | static void i2s_codec_init(void) | ||
40 | { | ||
41 | __aic_select_i2s(); | ||
42 | __i2s_internal_codec(); | ||
43 | |||
44 | __aic_enable(); | ||
45 | |||
46 | __i2s_set_oss_sample_size(16); | ||
47 | |||
48 | REG_ICDC_CDCCR1 = (ICDC_CDCCR1_SW2ON | ICDC_CDCCR1_PDVR | ICDC_CDCCR1_PDVRA | ICDC_CDCCR1_VRCGL | | ||
49 | ICDC_CDCCR1_VRCGH | ICDC_CDCCR1_HPOV0 | ICDC_CDCCR1_PDHPM | ICDC_CDCCR1_PDHP | | ||
50 | ICDC_CDCCR1_SUSPD | ICDC_CDCCR1_RST); /* reset */ | ||
51 | udelay(10); | ||
52 | REG_ICDC_CDCCR1 = (ICDC_CDCCR1_SW2ON | ICDC_CDCCR1_PDVR | ICDC_CDCCR1_PDVRA | ICDC_CDCCR1_VRCGL | | ||
53 | ICDC_CDCCR1_VRCGH | ICDC_CDCCR1_HPOV0 | ICDC_CDCCR1_PDHPM | ICDC_CDCCR1_PDHP | | ||
54 | ICDC_CDCCR1_SUSPD | ICDC_CDCCR1_RST); | ||
55 | //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) | | ||
57 | ICDC_CDCCR2_HPVOL(ICDC_CDCCR2_HPVOL_6)); | ||
58 | HP_on_off_flag = 0; /* HP is off */ | ||
59 | } | ||
60 | |||
61 | static void i2s_codec_set_mic(unsigned short v) /* 0 <= v <= 100 */ | ||
62 | { | ||
63 | v = v & 0xff; | ||
64 | if(v < 0) | ||
65 | v = 0; | ||
66 | if(v > 100) | ||
67 | v = 100; | ||
68 | codec_mic_gain = 31 * v/100; | ||
69 | |||
70 | REG_ICDC_CDCCR2 = ((REG_ICDC_CDCCR2 & ~(0x1f << 16)) | (codec_mic_gain << 16)); | ||
71 | } | ||
72 | |||
73 | static void i2s_codec_set_bass(unsigned short v) /* 0 <= v <= 100 */ | ||
74 | { | ||
75 | v = v & 0xff; | ||
76 | if(v < 0) | ||
77 | v = 0; | ||
78 | if(v > 100) | ||
79 | v = 100; | ||
80 | |||
81 | if(v < 25) | ||
82 | codec_base_gain = 0; | ||
83 | if(v >= 25 && v < 50) | ||
84 | codec_base_gain = 1; | ||
85 | if(v >= 50 && v < 75) | ||
86 | codec_base_gain = 2; | ||
87 | if(v >= 75 && v <= 100) | ||
88 | codec_base_gain = 3; | ||
89 | |||
90 | REG_ICDC_CDCCR2 = ((REG_ICDC_CDCCR2 & ~(0x3 << 4)) | (codec_base_gain << 4)); | ||
91 | } | ||
92 | |||
93 | static void i2s_codec_set_volume(unsigned short v) /* 0 <= v <= 100 */ | ||
94 | { | ||
95 | v = v & 0xff; | ||
96 | if(v < 0) | ||
97 | v = 0; | ||
98 | if(v > 100) | ||
99 | v = 100; | ||
100 | |||
101 | if(v < 25) | ||
102 | codec_volume = 0; | ||
103 | if(v >= 25 && v < 50) | ||
104 | codec_volume = 1; | ||
105 | if(v >= 50 && v < 75) | ||
106 | codec_volume = 2; | ||
107 | if(v >= 75 && v <= 100) | ||
108 | codec_volume = 3; | ||
109 | |||
110 | REG_ICDC_CDCCR2 = ((REG_ICDC_CDCCR2 & ~(0x3)) | codec_volume); | ||
111 | } | ||
112 | |||
113 | static unsigned short i2s_codec_get_bass(void) | ||
114 | { | ||
115 | unsigned short val; | ||
116 | int ret; | ||
117 | if(codec_base_gain == 0) | ||
118 | val = 0; | ||
119 | if(codec_base_gain == 1) | ||
120 | val = 25; | ||
121 | if(codec_base_gain == 2) | ||
122 | val = 50; | ||
123 | if(codec_base_gain == 3) | ||
124 | val = 75; | ||
125 | |||
126 | ret = val << 8; | ||
127 | val = val | ret; | ||
128 | } | ||
129 | |||
130 | static unsigned short i2s_codec_get_mic(void) | ||
131 | { | ||
132 | unsigned short val; | ||
133 | int ret; | ||
134 | val = 100 * codec_mic_gain / 31; | ||
135 | ret = val << 8; | ||
136 | val = val | ret; | ||
137 | } | ||
138 | |||
139 | static unsigned short i2s_codec_get_volume(void) | ||
140 | { | ||
141 | unsigned short val; | ||
142 | int ret; | ||
143 | |||
144 | if(codec_volume == 0) | ||
145 | val = 0; | ||
146 | if(codec_volume == 1) | ||
147 | val = 25; | ||
148 | if(codec_volume == 2) | ||
149 | val = 50; | ||
150 | if(codec_volume == 3) | ||
151 | val = 75; | ||
152 | |||
153 | ret = val << 8; | ||
154 | val = val | ret; | ||
155 | return val; | ||
156 | } | ||
157 | |||
158 | static void i2s_codec_set_samplerate(unsigned short rate) | ||
159 | { | ||
160 | unsigned short speed = 0; | ||
161 | unsigned short val = 0; | ||
162 | |||
163 | switch (rate) | ||
164 | { | ||
165 | case 8000: | ||
166 | speed = 0; | ||
167 | break; | ||
168 | case 11025: | ||
169 | speed = 1; | ||
170 | break; | ||
171 | case 12000: | ||
172 | speed = 2; | ||
173 | break; | ||
174 | case 16000: | ||
175 | speed = 3; | ||
176 | break; | ||
177 | case 22050: | ||
178 | speed = 4; | ||
179 | break; | ||
180 | case 24000: | ||
181 | speed = 5; | ||
182 | break; | ||
183 | case 32000: | ||
184 | speed = 6; | ||
185 | break; | ||
186 | case 44100: | ||
187 | speed = 7; | ||
188 | break; | ||
189 | case 48000: | ||
190 | speed = 8; | ||
191 | break; | ||
192 | default: | ||
193 | break; | ||
194 | } | ||
195 | REG_ICDC_CDCCR2 |= 0x00000f00; | ||
196 | speed = speed << 8; | ||
197 | |||
198 | speed |= 0xfffff0ff; | ||
199 | REG_ICDC_CDCCR2 &= speed; | ||
200 | } | ||
201 | |||
202 | static void HP_turn_on(void) | ||
203 | { | ||
204 | //see 1.3.4.1 | ||
205 | |||
206 | REG_ICDC_CDCCR1 &= ~(ICDC_CDCCR1_SUSPD | ICDC_CDCCR1_RST); //set suspend 0 | ||
207 | |||
208 | mdelay(15); | ||
209 | REG_ICDC_CDCCR1 &= ~(ICDC_CDCCR1_PDVR | ICDC_CDCCR1_VRCGL | ICDC_CDCCR1_VRCGH); | ||
210 | REG_ICDC_CDCCR1 |= (ICDC_CDCCR1_EDAC | ICDC_CDCCR1_HPCG); | ||
211 | |||
212 | mdelay(600); | ||
213 | REG_ICDC_CDCCR1 &= ~(ICDC_CDCCR1_PDVRA | ICDC_CDCCR1_HPCG | ICDC_CDCCR1_PDHPM | ICDC_CDCCR1_PDHP); | ||
214 | |||
215 | mdelay(2); | ||
216 | HP_register_value = REG_ICDC_CDCCR1; | ||
217 | |||
218 | //see 1.3.4.2 | ||
219 | /*REG_ICDC_CDCCR1 &= 0xfffffffc; | ||
220 | mdelay(7); | ||
221 | REG_ICDC_CDCCR1 |= 0x00040400; | ||
222 | mdelay(15); | ||
223 | REG_ICDC_CDCCR1 &= 0xfffbfbff; | ||
224 | udelay(500); | ||
225 | REG_ICDC_CDCCR1 &= 0xffe5fcff; | ||
226 | REG_ICDC_CDCCR1 |= 0x01000000; | ||
227 | mdelay(400); | ||
228 | REG_ICDC_CDCCR1 &= 0xfffeffff; | ||
229 | mdelay(7); | ||
230 | HP_register_value = REG_ICDC_CDCCR1;*/ | ||
231 | |||
232 | //see 1.3.4.3 | ||
233 | |||
234 | } | ||
235 | |||
236 | |||
237 | static void HP_turn_off(void) | ||
238 | { | ||
239 | //see 1.3.4.1 | ||
240 | mdelay(2); | ||
241 | REG_ICDC_CDCCR1 = HP_register_value; | ||
242 | REG_ICDC_CDCCR1 |= 0x001b0300; | ||
243 | REG_ICDC_CDCCR1 &= 0xfeffffff; | ||
244 | |||
245 | mdelay(15); | ||
246 | REG_ICDC_CDCCR1 |= 0x00000002;//set suspend 1 | ||
247 | |||
248 | //see 1.3.4.2 | ||
249 | /*mdelay(4); | ||
250 | REG_ICDC_CDCCR1 = HP_register_value; | ||
251 | REG_ICDC_CDCCR1 |= 0x001b0300; | ||
252 | REG_ICDC_CDCCR1 &= 0xfeffffff; | ||
253 | mdelay(4); | ||
254 | REG_ICDC_CDCCR1 |= 0x00000400; | ||
255 | mdelay(15); | ||
256 | REG_ICDC_CDCCR1 &= 0xfffffdff; | ||
257 | mdelay(7); | ||
258 | REG_ICDC_CDCCR1 |= 0x00000002;*/ | ||
259 | |||
260 | //see 1.3.4.3 | ||
261 | |||
262 | } | ||
263 | |||
264 | void audiohw_mute(bool mute) | ||
265 | { | ||
266 | if(mute) | ||
267 | REG_ICDC_CDCCR1 |= ICDC_CDCCR1_HPMUTE; | ||
268 | else | ||
269 | REG_ICDC_CDCCR1 &= ~ICDC_CDCCR1_HPMUTE; | ||
270 | } | ||
271 | |||
272 | void audiohw_preinit(void) | ||
273 | { | ||
274 | i2s_reset(); | ||
275 | } | ||
276 | |||
277 | void audiohw_postinit(void) | ||
278 | { | ||
279 | audiohw_mute(false); | ||
280 | } | ||
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 0f1cfca937..64ea86135f 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 | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "jz4740.h" | 24 | #include "jz4740.h" |
25 | #include "button.h" | 25 | #include "button.h" |
26 | #include "button-target.h" | 26 | #include "button-target.h" |
27 | #include "powermgmt.h" | ||
27 | 28 | ||
28 | #define BTN_OFF (1 << 29) | 29 | #define BTN_OFF (1 << 29) |
29 | #define BTN_VOL_DOWN (1 << 27) | 30 | #define BTN_VOL_DOWN (1 << 27) |
@@ -49,15 +50,61 @@ | |||
49 | static short x_pos = -1, y_pos = -1, datacount = 0; | 50 | static short x_pos = -1, y_pos = -1, datacount = 0; |
50 | static bool pen_down = false; | 51 | static bool pen_down = false; |
51 | static int cur_touch = 0; | 52 | static int cur_touch = 0; |
53 | static unsigned short bat_val = 0; | ||
52 | 54 | ||
53 | static enum touchscreen_mode current_mode = TOUCHSCREEN_POINT; | 55 | static enum touchscreen_mode current_mode = TOUCHSCREEN_POINT; |
54 | static int touchscreen_buttons[3][3] = | 56 | static const int touchscreen_buttons[3][3] = |
55 | { | 57 | { |
56 | {BUTTON_TOPLEFT, BUTTON_TOPMIDDLE, BUTTON_TOPRIGHT}, | 58 | {BUTTON_TOPLEFT, BUTTON_TOPMIDDLE, BUTTON_TOPRIGHT}, |
57 | {BUTTON_MIDLEFT, BUTTON_CENTER, BUTTON_MIDRIGHT}, | 59 | {BUTTON_MIDLEFT, BUTTON_CENTER, BUTTON_MIDRIGHT}, |
58 | {BUTTON_BOTTOMLEFT, BUTTON_BOTTOMMIDDLE, BUTTON_BOTTOMRIGHT} | 60 | {BUTTON_BOTTOMLEFT, BUTTON_BOTTOMMIDDLE, BUTTON_BOTTOMRIGHT} |
59 | }; | 61 | }; |
60 | 62 | ||
63 | const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = | ||
64 | { | ||
65 | /* TODO */ | ||
66 | 3400 | ||
67 | }; | ||
68 | |||
69 | const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] = | ||
70 | { | ||
71 | /* TODO */ | ||
72 | 3300 | ||
73 | }; | ||
74 | |||
75 | /* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */ | ||
76 | const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] = | ||
77 | { | ||
78 | /* TODO */ | ||
79 | { 3300, 3680, 3740, 3760, 3780, 3810, 3870, 3930, 3970, 4070, 4160 }, | ||
80 | }; | ||
81 | |||
82 | /* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */ | ||
83 | const unsigned short percent_to_volt_charge[11] = | ||
84 | { | ||
85 | /* TODO */ | ||
86 | 3300, 3680, 3740, 3760, 3780, 3810, 3870, 3930, 3970, 4070, 4160 | ||
87 | }; | ||
88 | |||
89 | /* VBAT = (BDATA/4096) * 7.5V */ | ||
90 | #define BATTERY_SCALE_FACTOR 7500 | ||
91 | |||
92 | /* Returns battery voltage from ADC [millivolts] */ | ||
93 | unsigned int battery_adc_voltage(void) | ||
94 | { | ||
95 | register unsigned short dummy; | ||
96 | dummy = REG_SADC_BATDAT; | ||
97 | dummy = REG_SADC_BATDAT; | ||
98 | |||
99 | bat_val = 0; | ||
100 | REG_SADC_ENA |= SADC_ENA_PBATEN; | ||
101 | |||
102 | while(bat_val == 0) | ||
103 | yield(); | ||
104 | |||
105 | return (bat_val*BATTERY_SCALE_FACTOR)>>12; | ||
106 | } | ||
107 | |||
61 | void button_init_device(void) | 108 | void button_init_device(void) |
62 | { | 109 | { |
63 | REG_SADC_ENA = 0; | 110 | REG_SADC_ENA = 0; |
@@ -72,8 +119,8 @@ void button_init_device(void) | |||
72 | REG_SADC_SAMETIME = 350; | 119 | REG_SADC_SAMETIME = 350; |
73 | REG_SADC_WAITTIME = 100; | 120 | REG_SADC_WAITTIME = 100; |
74 | REG_SADC_STATE &= (~REG_SADC_STATE); | 121 | REG_SADC_STATE &= (~REG_SADC_STATE); |
75 | REG_SADC_CTRL &= (~(SADC_CTRL_PENDM | SADC_CTRL_PENUM | SADC_CTRL_TSRDYM)); | 122 | REG_SADC_CTRL = (~(SADC_CTRL_PENDM | SADC_CTRL_PENUM | SADC_CTRL_TSRDYM | SADC_CTRL_PBATRDYM)); |
76 | REG_SADC_ENA = SADC_ENA_TSEN; //| SADC_ENA_PBATEN | SADC_ENA_SADCINEN); | 123 | REG_SADC_ENA = (SADC_ENA_TSEN | SADC_ENA_PBATEN); |
77 | 124 | ||
78 | __gpio_as_input(32*3 + 29); | 125 | __gpio_as_input(32*3 + 29); |
79 | __gpio_as_input(32*3 + 27); | 126 | __gpio_as_input(32*3 + 27); |
@@ -231,6 +278,7 @@ void SADC(void) | |||
231 | } | 278 | } |
232 | if(state & SADC_CTRL_PBATRDYM) | 279 | if(state & SADC_CTRL_PBATRDYM) |
233 | { | 280 | { |
281 | bat_val = REG_SADC_BATDAT; | ||
234 | /* Battery AD IRQ */ | 282 | /* Battery AD IRQ */ |
235 | } | 283 | } |
236 | if(state & SADC_CTRL_SRDYM) | 284 | if(state & SADC_CTRL_SRDYM) |
diff --git a/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c b/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c new file mode 100644 index 0000000000..a5cc61b844 --- /dev/null +++ b/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c | |||
@@ -0,0 +1,164 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2008 by Maurus Cuelenaere | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #include "system.h" | ||
23 | #include "kernel.h" | ||
24 | #include "logf.h" | ||
25 | #include "audio.h" | ||
26 | #include "sound.h" | ||
27 | #include "pcm.h" | ||
28 | #include "jz4740.h" | ||
29 | |||
30 | /**************************************************************************** | ||
31 | ** Playback DMA transfer | ||
32 | **/ | ||
33 | |||
34 | void pcm_postinit(void) | ||
35 | { | ||
36 | audiohw_postinit(); /* implemented not for all codecs */ | ||
37 | pcm_apply_settings(); | ||
38 | } | ||
39 | |||
40 | const void * pcm_play_dma_get_peak_buffer(int *count) | ||
41 | { | ||
42 | /* TODO */ | ||
43 | *count = 0; | ||
44 | return NULL; | ||
45 | } | ||
46 | |||
47 | void pcm_play_dma_init(void) | ||
48 | { | ||
49 | /* TODO */ | ||
50 | |||
51 | /* Initialize default register values. */ | ||
52 | audiohw_init(); | ||
53 | |||
54 | /* Power on */ | ||
55 | audiohw_enable_output(true); | ||
56 | |||
57 | /* Unmute the master channel (DAC should be at zero point now). */ | ||
58 | audiohw_mute(false); | ||
59 | } | ||
60 | |||
61 | void pcm_apply_settings(void) | ||
62 | { | ||
63 | /* TODO */ | ||
64 | } | ||
65 | |||
66 | void pcm_set_frequency(unsigned int frequency) | ||
67 | { | ||
68 | (void) frequency; | ||
69 | /* TODO */ | ||
70 | } | ||
71 | |||
72 | static void play_start_pcm(void) | ||
73 | { | ||
74 | pcm_apply_settings(); | ||
75 | |||
76 | /* TODO */ | ||
77 | } | ||
78 | |||
79 | static void play_stop_pcm(void) | ||
80 | { | ||
81 | /* TODO */ | ||
82 | } | ||
83 | |||
84 | void pcm_play_dma_start(const void *addr, size_t size) | ||
85 | { | ||
86 | (void)addr; | ||
87 | (void)size; | ||
88 | /* TODO */ | ||
89 | |||
90 | play_start_pcm(); | ||
91 | } | ||
92 | |||
93 | void pcm_play_dma_stop(void) | ||
94 | { | ||
95 | play_stop_pcm(); | ||
96 | |||
97 | /* TODO */ | ||
98 | } | ||
99 | |||
100 | void pcm_play_lock(void) | ||
101 | { | ||
102 | /* TODO */ | ||
103 | } | ||
104 | |||
105 | void pcm_play_unlock(void) | ||
106 | { | ||
107 | /* TODO */ | ||
108 | } | ||
109 | |||
110 | void pcm_play_dma_pause(bool pause) | ||
111 | { | ||
112 | if(pause) | ||
113 | play_stop_pcm(); | ||
114 | else | ||
115 | play_start_pcm(); | ||
116 | |||
117 | } | ||
118 | |||
119 | size_t pcm_get_bytes_waiting(void) | ||
120 | { | ||
121 | /* TODO */ | ||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | #ifdef HAVE_RECORDING | ||
126 | /* TODO */ | ||
127 | void pcm_rec_dma_init(void) | ||
128 | { | ||
129 | } | ||
130 | |||
131 | void pcm_rec_dma_close(void) | ||
132 | { | ||
133 | } | ||
134 | |||
135 | void pcm_rec_dma_start(void *addr, size_t size) | ||
136 | { | ||
137 | (void) addr; | ||
138 | (void) size; | ||
139 | } | ||
140 | |||
141 | void pcm_rec_dma_stop(void) | ||
142 | { | ||
143 | } | ||
144 | |||
145 | void pcm_rec_lock(void) | ||
146 | { | ||
147 | } | ||
148 | |||
149 | void pcm_rec_unlock(void) | ||
150 | { | ||
151 | } | ||
152 | |||
153 | const void * pcm_rec_dma_get_peak_buffer(int *count) | ||
154 | { | ||
155 | *count = 0; | ||
156 | return NULL; | ||
157 | } | ||
158 | |||
159 | void pcm_record_more(void *start, size_t size) | ||
160 | { | ||
161 | (void) start; | ||
162 | (void) size; | ||
163 | } | ||
164 | #endif | ||
diff --git a/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c index 2121d3e4b0..7cefdadbe3 100644 --- a/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c | |||
@@ -20,6 +20,7 @@ | |||
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | 21 | ||
22 | #include "config.h" | 22 | #include "config.h" |
23 | #include "string.h" | ||
23 | #include "system.h" | 24 | #include "system.h" |
24 | #include "usb_ch9.h" | 25 | #include "usb_ch9.h" |
25 | #include "usb_drv.h" | 26 | #include "usb_drv.h" |
@@ -27,7 +28,7 @@ | |||
27 | #include "jz4740.h" | 28 | #include "jz4740.h" |
28 | #include "thread.h" | 29 | #include "thread.h" |
29 | 30 | ||
30 | #if 0 | 31 | #if 1 |
31 | 32 | ||
32 | #define EP1_INTR_BIT 2 | 33 | #define EP1_INTR_BIT 2 |
33 | #define EP_FIFO_NOEMPTY 2 | 34 | #define EP_FIFO_NOEMPTY 2 |
@@ -38,14 +39,327 @@ | |||
38 | 39 | ||
39 | #define IS_CACHE(x) (x < 0xa0000000) | 40 | #define IS_CACHE(x) (x < 0xa0000000) |
40 | 41 | ||
42 | #define USB_EP0_IDLE 0 | ||
43 | #define USB_EP0_RX 1 | ||
44 | #define USB_EP0_TX 2 | ||
45 | |||
46 | enum ep_type | ||
47 | { | ||
48 | ep_control, ep_bulk, ep_interrupt | ||
49 | }; | ||
50 | |||
51 | struct usb_endpoint | ||
52 | { | ||
53 | void *buf; | ||
54 | unsigned int length; | ||
55 | void *ptr; | ||
56 | |||
57 | const enum ep_type type; | ||
58 | const bool use_dma; | ||
59 | const bool in; | ||
60 | |||
61 | const void *fifo_addr; | ||
62 | unsigned short fifo_size; | ||
63 | }; | ||
64 | |||
65 | static unsigned char ep0_rx_buf[64]; | ||
66 | static unsigned char ep0_tx_buf[64]; | ||
67 | static unsigned char ep0state = USB_EP0_IDLE; | ||
68 | static struct usb_endpoint endpoints[] = | ||
69 | { | ||
70 | /* buf length ptr type use_dma in fifo_addr fifo_size */ | ||
71 | {&ep0_rx_buf, 0, &ep0_rx_buf, ep_control, false, true, (void*)USB_FIFO_EP0, 64 }, | ||
72 | {&ep0_tx_buf, 0, &ep0_tx_buf, ep_control, false, false, (void*)USB_FIFO_EP0, 64 }, | ||
73 | {NULL, 0, NULL, ep_bulk, true, true, (void*)USB_FIFO_EP1, 512}, | ||
74 | {NULL, 0, NULL, ep_bulk, true, false, (void*)USB_FIFO_EP1, 512}, | ||
75 | {NULL, 0, NULL, ep_interrupt, false, true, (void*)USB_FIFO_EP2, 64 } | ||
76 | }; | ||
77 | |||
78 | static inline void select_endpoint(int ep) | ||
79 | { | ||
80 | REG_USB_REG_INDEX = ep; | ||
81 | } | ||
82 | |||
83 | static void readFIFO(struct usb_endpoint *ep, unsigned int size) | ||
84 | { | ||
85 | unsigned int *d = (unsigned int *)ep->ptr; | ||
86 | unsigned int s; | ||
87 | s = (size + 3) >> 2; | ||
88 | while (s--) | ||
89 | *d++ = REG32(ep->fifo_addr); | ||
90 | } | ||
91 | |||
92 | static void writeFIFO(struct usb_endpoint *ep, unsigned int size) | ||
93 | { | ||
94 | unsigned int *d = (unsigned int *)ep->ptr; | ||
95 | unsigned char *c; | ||
96 | int s, q; | ||
97 | |||
98 | if (size > 0) | ||
99 | { | ||
100 | s = size >> 2; | ||
101 | while (s--) | ||
102 | REG32(ep->fifo_addr) = *d++; | ||
103 | |||
104 | q = size & 3; | ||
105 | if (q) | ||
106 | { | ||
107 | c = (unsigned char *)d; | ||
108 | while (q--) | ||
109 | REG8(ep->fifo_addr) = *c++; | ||
110 | } | ||
111 | } | ||
112 | } | ||
113 | |||
114 | static void sendPKT(int ep_nr, const unsigned char* ptr, unsigned int size) | ||
115 | { | ||
116 | struct usb_endpoint *ep = &endpoints[ep_nr]; | ||
117 | |||
118 | if (ep_nr != 0) | ||
119 | { | ||
120 | ep->buf = (void*)ptr; | ||
121 | ep->ptr = (void*)ptr; | ||
122 | ep->length = size; | ||
123 | select_endpoint(ep_nr); | ||
124 | if (size <= ep->fifo_size) | ||
125 | { | ||
126 | writeFIFO(ep, size); | ||
127 | REG_USB_REG_INCSR |= USB_INCSR_INPKTRDY; | ||
128 | ep->ptr = ep->buf + size; | ||
129 | } | ||
130 | else | ||
131 | { | ||
132 | writeFIFO(ep, ep->fifo_size); | ||
133 | REG_USB_REG_INCSR |= USB_INCSR_INPKTRDY; | ||
134 | ep->ptr += ep->fifo_size; | ||
135 | } | ||
136 | } | ||
137 | else /* EP0 */ | ||
138 | { | ||
139 | ep->length = size; | ||
140 | ep->ptr = ep->buf; | ||
141 | memcpy(ep->buf, ptr, size); | ||
142 | ep0state = USB_EP0_TX; | ||
143 | } | ||
144 | } | ||
145 | |||
146 | static void getPKT(int ep_nr, const unsigned char *ptr, unsigned int size) | ||
147 | { | ||
148 | struct usb_endpoint *ep = &endpoints[ep_nr]; | ||
149 | |||
150 | memcpy((void*)ptr, ep->ptr, size); | ||
151 | if (ep->length > size) | ||
152 | ep->length -= size; | ||
153 | else | ||
154 | { | ||
155 | size = ep->length; | ||
156 | ep->length = 0; | ||
157 | } | ||
158 | |||
159 | ep->ptr += size; | ||
160 | } | ||
161 | |||
162 | static void EP0_handler(void) | ||
163 | { | ||
164 | unsigned char csr0; | ||
165 | |||
166 | /* Read CSR0 */ | ||
167 | select_endpoint(0); | ||
168 | csr0 = REG_USB_REG_CSR0; | ||
169 | |||
170 | /* Check for SentStall | ||
171 | if sentstall is set, clear the sentstall bit | ||
172 | */ | ||
173 | if (csr0 & USB_CSR0_SENTSTALL) | ||
174 | { | ||
175 | REG_USB_REG_CSR0 = csr0 & ~USB_CSR0_SENTSTALL; | ||
176 | ep0state = USB_EP0_IDLE; | ||
177 | return; | ||
178 | } | ||
179 | |||
180 | /* Check for SetupEnd */ | ||
181 | if (csr0 & USB_CSR0_SETUPEND) | ||
182 | { | ||
183 | REG_USB_REG_CSR0 |= USB_CSR0_SVDSETUPEND; | ||
184 | ep0state = USB_EP0_IDLE; | ||
185 | return; | ||
186 | } | ||
187 | |||
188 | /* Call relevant routines for endpoint 0 state */ | ||
189 | if (ep0state == USB_EP0_IDLE) | ||
190 | { | ||
191 | if (csr0 & USB_CSR0_OUTPKTRDY) /* There is data in the fifo */ | ||
192 | { | ||
193 | readFIFO(&endpoints[0], 8); | ||
194 | REG_USB_REG_CSR0 |= USB_CSR0_SVDOUTPKTRDY; /* clear OUTRD bit */ | ||
195 | usb_core_control_request((struct usb_ctrlrequest*)endpoints[0].buf); | ||
196 | } | ||
197 | endpoints[0].length = 0; | ||
198 | endpoints[0].ptr = endpoints[0].buf; | ||
199 | } | ||
200 | |||
201 | if (ep0state == USB_EP0_TX) | ||
202 | { | ||
203 | if ((&endpoints[1].ptr - &endpoints[1].buf) <= endpoints[1].fifo_size) | ||
204 | { | ||
205 | writeFIFO(&endpoints[1], (&endpoints[1].ptr - &endpoints[1].buf)); | ||
206 | endpoints[1].ptr = &endpoints[1].buf + endpoints[1].length; | ||
207 | REG_USB_REG_CSR0 |= (USB_CSR0_INPKTRDY | USB_CSR0_DATAEND); /* Set data end! */ | ||
208 | ep0state = USB_EP0_IDLE; | ||
209 | } | ||
210 | else | ||
211 | { | ||
212 | writeFIFO(&endpoints[1], endpoints[1].fifo_size); | ||
213 | REG_USB_REG_CSR0 |= USB_CSR0_INPKTRDY; | ||
214 | endpoints[1].ptr += endpoints[1].fifo_size; | ||
215 | } | ||
216 | } | ||
217 | } | ||
218 | |||
219 | static void setup_endpoint(struct usb_endpoint *ep) | ||
220 | { | ||
221 | ep->ptr = ep->buf; | ||
222 | ep->length = 0; | ||
223 | |||
224 | if(ep->in) | ||
225 | { | ||
226 | if(ep->type == ep_bulk) | ||
227 | { | ||
228 | register int size; | ||
229 | |||
230 | if((REG_USB_REG_POWER & USB_POWER_HSMODE) == 0) | ||
231 | size = 64; | ||
232 | else | ||
233 | size = 512; | ||
234 | |||
235 | REG_USB_REG_INMAXP = size; | ||
236 | ep->fifo_size = size; | ||
237 | } | ||
238 | else | ||
239 | REG_USB_REG_INMAXP = ep->fifo_size; | ||
240 | |||
241 | REG_USB_REG_INCSR = 0x2048; | ||
242 | } | ||
243 | else | ||
244 | { | ||
245 | REG_USB_REG_OUTMAXP = ep->fifo_size; | ||
246 | REG_USB_REG_OUTCSR = 0x0090; | ||
247 | } | ||
248 | } | ||
249 | |||
250 | static void udc_reset(void) | ||
251 | { | ||
252 | register int i; | ||
253 | |||
254 | /* data init */ | ||
255 | ep0state = USB_EP0_IDLE; | ||
256 | |||
257 | /* Disable interrupts */ | ||
258 | REG_USB_REG_INTRINE = 0; | ||
259 | REG_USB_REG_INTROUTE = 0; | ||
260 | REG_USB_REG_INTRUSBE = 0; | ||
261 | |||
262 | REG_USB_REG_FADDR = 0; | ||
263 | REG_USB_REG_POWER = 0x60; /* High speed */ | ||
264 | |||
265 | select_endpoint(0); | ||
266 | REG_USB_REG_CSR0 = 0xC0; | ||
267 | |||
268 | for(i=1; i<3; i++) | ||
269 | { | ||
270 | select_endpoint(i); | ||
271 | setup_endpoint(&endpoints[i]); | ||
272 | } | ||
273 | |||
274 | /* enable intr */ | ||
275 | REG_USB_REG_INTRINE = 0x3; | ||
276 | REG_USB_REG_INTROUTE = 0x2; | ||
277 | REG_USB_REG_INTRUSBE = 0x4; | ||
278 | } | ||
279 | |||
280 | /* Interrupt handler */ | ||
281 | void UDC(void) | ||
282 | { | ||
283 | /* Read interrupt registers */ | ||
284 | unsigned char intrUSB = REG_USB_REG_INTRUSB & 0x07; /* Mask SOF */ | ||
285 | unsigned short intrIn = REG_USB_REG_INTRIN; | ||
286 | unsigned short intrOut = REG_USB_REG_INTROUT; | ||
287 | unsigned char intrDMA = REG_USB_REG_INTR; | ||
288 | |||
289 | if(intrUSB == 0 && intrIn == 0 && intrOut == 0 && intrDMA == 0) | ||
290 | return; | ||
291 | |||
292 | /* EPIN & EPOUT are all handled in DMA */ | ||
293 | if(intrIn & USB_INTR_EP0) | ||
294 | EP0_handler(); | ||
295 | if(intrUSB & USB_INTR_RESET) | ||
296 | udc_reset(); | ||
297 | if(intrUSB & USB_INTR_SUSPEND); | ||
298 | if(intrUSB & USB_INTR_RESUME); | ||
299 | if(intrDMA & USB_INTR_DMA_BULKIN) | ||
300 | { | ||
301 | usb_core_transfer_complete(((REG_USB_REG_CNTL1 >> 4) & 0xF) | USB_DIR_IN, USB_DIR_IN, 0, 0); | ||
302 | } | ||
303 | if(intrDMA & USB_INTR_DMA_BULKOUT) | ||
304 | { | ||
305 | usb_core_transfer_complete(((REG_USB_REG_CNTL2 >> 4) & 0xF) | USB_DIR_OUT, USB_DIR_OUT, 0, 0); | ||
306 | } | ||
307 | } | ||
308 | |||
309 | bool usb_drv_stalled(int endpoint, bool in) | ||
310 | { | ||
311 | select_endpoint(endpoint); | ||
312 | |||
313 | if(endpoint == 0) | ||
314 | return (REG_USB_REG_CSR0 & USB_CSR0_SENDSTALL) != 0; | ||
315 | else | ||
316 | { | ||
317 | if(in) | ||
318 | return (REG_USB_REG_INCSR & USB_INCSR_SENDSTALL) != 0; | ||
319 | else | ||
320 | return (REG_USB_REG_OUTCSR & USB_OUTCSR_SENDSTALL) != 0; | ||
321 | } | ||
322 | } | ||
323 | |||
324 | void usb_drv_stall(int endpoint, bool stall, bool in) | ||
325 | { | ||
326 | select_endpoint(endpoint); | ||
327 | |||
328 | if(endpoint == 0) | ||
329 | { | ||
330 | if(stall) | ||
331 | REG_USB_REG_CSR0 |= USB_CSR0_SENDSTALL; | ||
332 | else | ||
333 | REG_USB_REG_CSR0 &= ~USB_CSR0_SENDSTALL; | ||
334 | } | ||
335 | else | ||
336 | { | ||
337 | if(in) | ||
338 | { | ||
339 | if(stall) | ||
340 | REG_USB_REG_INCSR |= USB_INCSR_SENDSTALL; | ||
341 | else | ||
342 | REG_USB_REG_INCSR &= ~USB_INCSR_SENDSTALL; | ||
343 | } | ||
344 | else | ||
345 | { | ||
346 | if(stall) | ||
347 | REG_USB_REG_OUTCSR |= USB_OUTCSR_SENDSTALL; | ||
348 | else | ||
349 | REG_USB_REG_OUTCSR &= ~USB_OUTCSR_SENDSTALL; | ||
350 | } | ||
351 | } | ||
352 | } | ||
353 | |||
354 | |||
41 | bool usb_drv_connected(void) | 355 | bool usb_drv_connected(void) |
42 | { | 356 | { |
43 | return (__gpio_get_pin(GPIO_UDC_DETE)==1); | 357 | return __gpio_get_pin(GPIO_UDC_DETE) == 1; |
44 | } | 358 | } |
45 | 359 | ||
46 | int usb_detect(void) | 360 | int usb_detect(void) |
47 | { | 361 | { |
48 | if(__gpio_get_pin(GPIO_UDC_DETE)==1) | 362 | if(__gpio_get_pin(GPIO_UDC_DETE) == 1) |
49 | return USB_INSERTED; | 363 | return USB_INSERTED; |
50 | else | 364 | else |
51 | return USB_EXTRACTED; | 365 | return USB_EXTRACTED; |
@@ -68,49 +382,51 @@ void usb_enable(bool on) | |||
68 | 382 | ||
69 | void usb_drv_init(void) | 383 | void usb_drv_init(void) |
70 | { | 384 | { |
71 | /* Set this bit to allow the UDC entering low-power mode when | 385 | /* Set this bit to allow the UDC entering low-power mode when |
72 | * there are no actions on the USB bus. | 386 | * there are no actions on the USB bus. |
73 | * UDC still works during this bit was set. | 387 | * UDC still works during this bit was set. |
74 | */ | 388 | */ |
75 | //__cpm_stop_udc(); | 389 | //__cpm_stop_udc(); |
76 | 390 | ||
77 | __cpm_start_udc(); | 391 | __cpm_start_udc(); |
78 | 392 | ||
79 | /* Enable the USB PHY */ | 393 | /* Enable the USB PHY */ |
80 | REG_CPM_SCR |= CPM_SCR_USBPHY_ENABLE; | 394 | REG_CPM_SCR |= CPM_SCR_USBPHY_ENABLE; |
81 | 395 | ||
82 | /* Disable interrupts */ | 396 | /* Disable interrupts */ |
83 | REG_USB_REG_INTRINE = 0; | 397 | REG_USB_REG_INTRINE = 0; |
84 | REG_USB_REG_INTROUTE = 0; | 398 | REG_USB_REG_INTROUTE = 0; |
85 | REG_USB_REG_INTRUSBE = 0; | 399 | REG_USB_REG_INTRUSBE = 0; |
86 | 400 | ||
87 | /* Enable interrupts */ | 401 | /* Enable interrupts */ |
88 | REG_USB_REG_INTRINE |= USB_INTR_EP0; | 402 | REG_USB_REG_INTRINE |= USB_INTR_EP0; |
89 | REG_USB_REG_INTRUSBE |= USB_INTR_RESET; | 403 | REG_USB_REG_INTRUSBE |= USB_INTR_RESET; |
90 | 404 | ||
91 | /* Enable SUSPEND */ | 405 | /* Enable SUSPEND */ |
92 | /* usb_setb(USB_REG_POWER, USB_POWER_SUSPENDM); */ | 406 | /* usb_setb(USB_REG_POWER, USB_POWER_SUSPENDM); */ |
93 | 407 | ||
94 | /* Enable HS Mode */ | 408 | /* Enable HS Mode */ |
95 | REG_USB_REG_POWER |= USB_POWER_HSENAB; | 409 | REG_USB_REG_POWER |= USB_POWER_HSENAB; |
96 | 410 | ||
97 | /* Let host detect UDC: | 411 | /* Let host detect UDC: |
98 | * Software must write a 1 to the PMR:USB_POWER_SOFTCONN bit to turn this | 412 | * Software must write a 1 to the PMR:USB_POWER_SOFTCONN bit to turn this |
99 | * transistor on and pull the USBDP pin HIGH. | 413 | * transistor on and pull the USBDP pin HIGH. |
100 | */ | 414 | */ |
101 | REG_USB_REG_POWER |= USB_POWER_SOFTCONN; | 415 | REG_USB_REG_POWER |= USB_POWER_SOFTCONN; |
416 | |||
417 | udc_reset(); | ||
102 | } | 418 | } |
103 | 419 | ||
104 | void usb_drv_exit(void) | 420 | void usb_drv_exit(void) |
105 | { | 421 | { |
106 | /* Disable interrupts */ | 422 | /* Disable interrupts */ |
107 | REG_USB_REG_INTRINE = 0; | 423 | REG_USB_REG_INTRINE = 0; |
108 | REG_USB_REG_INTROUTE = 0; | 424 | REG_USB_REG_INTROUTE = 0; |
109 | REG_USB_REG_INTRUSBE = 0; | 425 | REG_USB_REG_INTRUSBE = 0; |
110 | 426 | ||
111 | /* Disable DMA */ | 427 | /* Disable DMA */ |
112 | REG_USB_REG_CNTL1 = 0; | 428 | REG_USB_REG_CNTL1 = 0; |
113 | REG_USB_REG_CNTL2 = 0; | 429 | REG_USB_REG_CNTL2 = 0; |
114 | 430 | ||
115 | /* Disconnect from usb */ | 431 | /* Disconnect from usb */ |
116 | REG_USB_REG_POWER &= ~USB_POWER_SOFTCONN; | 432 | REG_USB_REG_POWER &= ~USB_POWER_SOFTCONN; |
@@ -126,253 +442,248 @@ void usb_drv_set_address(int address) | |||
126 | REG_USB_REG_FADDR = address; | 442 | REG_USB_REG_FADDR = address; |
127 | } | 443 | } |
128 | 444 | ||
129 | /* Interrupt handler */ | ||
130 | void UDC(void) | ||
131 | { | ||
132 | |||
133 | } | ||
134 | 445 | ||
135 | #else | 446 | #else |
136 | 447 | ||
137 | //------------------------------------------ | 448 | //------------------------------------------ |
138 | #ifndef u8 | 449 | #ifndef u8 |
139 | #define u8 unsigned char | 450 | #define u8 unsigned char |
140 | #endif | 451 | #endif |
141 | 452 | ||
142 | #ifndef u16 | 453 | #ifndef u16 |
143 | #define u16 unsigned short | 454 | #define u16 unsigned short |
144 | #endif | 455 | #endif |
145 | 456 | ||
146 | #ifndef u32 | 457 | #ifndef u32 |
147 | #define u32 unsigned int | 458 | #define u32 unsigned int |
148 | #endif | 459 | #endif |
149 | 460 | ||
150 | #ifndef s8 | 461 | #ifndef s8 |
151 | #define s8 char | 462 | #define s8 char |
152 | #endif | 463 | #endif |
153 | 464 | ||
154 | #ifndef s16 | 465 | #ifndef s16 |
155 | #define s16 short | 466 | #define s16 short |
156 | #endif | 467 | #endif |
157 | 468 | ||
158 | #ifndef s32 | 469 | #ifndef s32 |
159 | #define s32 int | 470 | #define s32 int |
160 | #endif | 471 | #endif |
161 | 472 | ||
162 | extern int usbdebug; | 473 | extern int usbdebug; |
163 | 474 | ||
164 | enum USB_ENDPOINT_TYPE | 475 | enum USB_ENDPOINT_TYPE |
165 | { | 476 | { |
166 | ENDPOINT_TYPE_CONTROL, | 477 | ENDPOINT_TYPE_CONTROL, |
167 | /* Typically used to configure a device when attached to the host. | 478 | /* Typically used to configure a device when attached to the host. |
168 | * It may also be used for other device specific purposes, including | 479 | * It may also be used for other device specific purposes, including |
169 | * control of other pipes on the device. | 480 | * control of other pipes on the device. |
170 | */ | 481 | */ |
171 | ENDPOINT_TYPE_ISOCHRONOUS, | 482 | ENDPOINT_TYPE_ISOCHRONOUS, |
172 | /* Typically used for applications which need guaranteed speed. | 483 | /* Typically used for applications which need guaranteed speed. |
173 | * Isochronous transfer is fast but with possible data loss. A typical | 484 | * Isochronous transfer is fast but with possible data loss. A typical |
174 | * use is audio data which requires a constant data rate. | 485 | * use is audio data which requires a constant data rate. |
175 | */ | 486 | */ |
176 | ENDPOINT_TYPE_BULK, | 487 | ENDPOINT_TYPE_BULK, |
177 | /* Typically used by devices that generate or consume data in relatively | 488 | /* Typically used by devices that generate or consume data in relatively |
178 | * large and bursty quantities. Bulk transfer has wide dynamic latitude | 489 | * large and bursty quantities. Bulk transfer has wide dynamic latitude |
179 | * in transmission constraints. It can use all remaining available bandwidth, | 490 | * in transmission constraints. It can use all remaining available bandwidth, |
180 | * but with no guarantees on bandwidth or latency. Since the USB bus is | 491 | * but with no guarantees on bandwidth or latency. Since the USB bus is |
181 | * normally not very busy, there is typically 90% or more of the bandwidth | 492 | * normally not very busy, there is typically 90% or more of the bandwidth |
182 | * available for USB transfers. | 493 | * available for USB transfers. |
183 | */ | 494 | */ |
184 | ENDPOINT_TYPE_INTERRUPT | 495 | ENDPOINT_TYPE_INTERRUPT |
185 | /* Typically used by devices that need guaranteed quick responses | 496 | /* Typically used by devices that need guaranteed quick responses |
186 | * (bounded latency). | 497 | * (bounded latency). |
187 | */ | 498 | */ |
188 | }; | 499 | }; |
189 | 500 | ||
190 | 501 | ||
191 | enum USB_STANDARD_REQUEST_CODE { | 502 | enum USB_STANDARD_REQUEST_CODE { |
192 | GET_STATUS, | 503 | GET_STATUS, |
193 | CLEAR_FEATURE, | 504 | CLEAR_FEATURE, |
194 | SET_FEATURE = 3, | 505 | SET_FEATURE = 3, |
195 | SET_ADDRESS = 5, | 506 | SET_ADDRESS = 5, |
196 | GET_DESCRIPTOR, | 507 | GET_DESCRIPTOR, |
197 | SET_DESCRIPTOR, | 508 | SET_DESCRIPTOR, |
198 | GET_CONFIGURATION, | 509 | GET_CONFIGURATION, |
199 | SET_CONFIGURATION, | 510 | SET_CONFIGURATION, |
200 | GET_INTERFACE, | 511 | GET_INTERFACE, |
201 | SET_INTERFACE, | 512 | SET_INTERFACE, |
202 | SYNCH_FRAME | 513 | SYNCH_FRAME |
203 | }; | 514 | }; |
204 | 515 | ||
205 | 516 | ||
206 | enum USB_DESCRIPTOR_TYPE { | 517 | enum USB_DESCRIPTOR_TYPE { |
207 | DEVICE_DESCRIPTOR = 1, | 518 | DEVICE_DESCRIPTOR = 1, |
208 | CONFIGURATION_DESCRIPTOR, | 519 | CONFIGURATION_DESCRIPTOR, |
209 | STRING_DESCRIPTOR, | 520 | STRING_DESCRIPTOR, |
210 | INTERFACE_DESCRIPTOR, | 521 | INTERFACE_DESCRIPTOR, |
211 | ENDPOINT_DESCRIPTOR, | 522 | ENDPOINT_DESCRIPTOR, |
212 | DEVICE_QUALIFIER_DESCRIPTOR, | 523 | DEVICE_QUALIFIER_DESCRIPTOR, |
213 | OTHER_SPEED_CONFIGURATION_DESCRIPTOR, | 524 | OTHER_SPEED_CONFIGURATION_DESCRIPTOR, |
214 | INTERFACE_POWER1_DESCRIPTOR | 525 | INTERFACE_POWER1_DESCRIPTOR |
215 | }; | 526 | }; |
216 | 527 | ||
217 | 528 | ||
218 | enum USB_FEATURE_SELECTOR { | 529 | enum USB_FEATURE_SELECTOR { |
219 | ENDPOINT_HALT, | 530 | ENDPOINT_HALT, |
220 | DEVICE_REMOTE_WAKEUP, | 531 | DEVICE_REMOTE_WAKEUP, |
221 | TEST_MODE | 532 | TEST_MODE |
222 | }; | 533 | }; |
223 | 534 | ||
224 | enum USB_CLASS_CODE { | 535 | enum USB_CLASS_CODE { |
225 | CLASS_DEVICE, | 536 | CLASS_DEVICE, |
226 | CLASS_AUDIO, | 537 | CLASS_AUDIO, |
227 | CLASS_COMM_AND_CDC_CONTROL, | 538 | CLASS_COMM_AND_CDC_CONTROL, |
228 | CLASS_HID, | 539 | CLASS_HID, |
229 | CLASS_PHYSICAL = 0x05, | 540 | CLASS_PHYSICAL = 0x05, |
230 | CLASS_STILL_IMAGING, | 541 | CLASS_STILL_IMAGING, |
231 | CLASS_PRINTER, | 542 | CLASS_PRINTER, |
232 | CLASS_MASS_STORAGE, | 543 | CLASS_MASS_STORAGE, |
233 | CLASS_HUB, | 544 | CLASS_HUB, |
234 | CLASS_CDC_DATA, | 545 | CLASS_CDC_DATA, |
235 | CLASS_SMART_CARD, | 546 | CLASS_SMART_CARD, |
236 | CLASS_CONTENT_SECURITY = 0x0d, | 547 | CLASS_CONTENT_SECURITY = 0x0d, |
237 | CLASS_VIDEO, | 548 | CLASS_VIDEO, |
238 | CLASS_DIAGNOSTIC_DEVICE = 0xdc, | 549 | CLASS_DIAGNOSTIC_DEVICE = 0xdc, |
239 | CLASS_WIRELESS_CONTROLLER = 0xe0, | 550 | CLASS_WIRELESS_CONTROLLER = 0xe0, |
240 | CLASS_MISCELLANEOUS = 0xef, | 551 | CLASS_MISCELLANEOUS = 0xef, |
241 | CLASS_APP_SPECIFIC = 0xfe, | 552 | CLASS_APP_SPECIFIC = 0xfe, |
242 | CLASS_VENDOR_SPECIFIC = 0xff | 553 | CLASS_VENDOR_SPECIFIC = 0xff |
243 | }; | 554 | }; |
244 | 555 | ||
245 | 556 | ||
246 | typedef struct { | 557 | typedef struct { |
247 | u8 bmRequestType; | 558 | u8 bmRequestType; |
248 | u8 bRequest; | 559 | u8 bRequest; |
249 | u16 wValue; | 560 | u16 wValue; |
250 | u16 wIndex; | 561 | u16 wIndex; |
251 | u16 wLength; | 562 | u16 wLength; |
252 | } __attribute__ ((packed)) USB_DeviceRequest; | 563 | } __attribute__ ((packed)) USB_DeviceRequest; |
253 | 564 | ||
254 | 565 | ||
255 | typedef struct { | 566 | typedef struct { |
256 | u8 bLength; | 567 | u8 bLength; |
257 | u8 bDescriptorType; | 568 | u8 bDescriptorType; |
258 | u16 bcdUSB; | 569 | u16 bcdUSB; |
259 | u8 bDeviceClass; | 570 | u8 bDeviceClass; |
260 | u8 bDeviceSubClass; | 571 | u8 bDeviceSubClass; |
261 | u8 bDeviceProtocol; | 572 | u8 bDeviceProtocol; |
262 | u8 bMaxPacketSize0; | 573 | u8 bMaxPacketSize0; |
263 | u16 idVendor; | 574 | u16 idVendor; |
264 | u16 idProduct; | 575 | u16 idProduct; |
265 | u16 bcdDevice; | 576 | u16 bcdDevice; |
266 | u8 iManufacturer; | 577 | u8 iManufacturer; |
267 | u8 iProduct; | 578 | u8 iProduct; |
268 | u8 iSerialNumber; | 579 | u8 iSerialNumber; |
269 | u8 bNumConfigurations; | 580 | u8 bNumConfigurations; |
270 | } __attribute__ ((packed)) USB_DeviceDescriptor; | 581 | } __attribute__ ((packed)) USB_DeviceDescriptor; |
271 | 582 | ||
272 | 583 | ||
273 | typedef struct { | 584 | typedef struct { |
274 | u8 bLength; | 585 | u8 bLength; |
275 | u8 bDescriptorType; | 586 | u8 bDescriptorType; |
276 | u16 bcdUSB; | 587 | u16 bcdUSB; |
277 | u8 bDeviceClass; | 588 | u8 bDeviceClass; |
278 | u8 bDeviceSubClass; | 589 | u8 bDeviceSubClass; |
279 | u8 bDeviceProtocol; | 590 | u8 bDeviceProtocol; |
280 | u8 bMaxPacketSize0; | 591 | u8 bMaxPacketSize0; |
281 | u8 bNumConfigurations; | 592 | u8 bNumConfigurations; |
282 | u8 bReserved; | 593 | u8 bReserved; |
283 | } __attribute__ ((packed)) USB_DeviceQualifierDescriptor; | 594 | } __attribute__ ((packed)) USB_DeviceQualifierDescriptor; |
284 | 595 | ||
285 | 596 | ||
286 | typedef struct { | 597 | typedef struct { |
287 | u8 bLength; | 598 | u8 bLength; |
288 | u8 bDescriptorType; | 599 | u8 bDescriptorType; |
289 | u16 wTotalLength; | 600 | u16 wTotalLength; |
290 | u8 bNumInterfaces; | 601 | u8 bNumInterfaces; |
291 | u8 bConfigurationValue; | 602 | u8 bConfigurationValue; |
292 | u8 iConfiguration; | 603 | u8 iConfiguration; |
293 | u8 bmAttributes; | 604 | u8 bmAttributes; |
294 | u8 MaxPower; | 605 | u8 MaxPower; |
295 | } __attribute__ ((packed)) USB_ConfigDescriptor; | 606 | } __attribute__ ((packed)) USB_ConfigDescriptor; |
296 | 607 | ||
297 | 608 | ||
298 | typedef struct { | 609 | typedef struct { |
299 | u8 bLength; | 610 | u8 bLength; |
300 | u8 bDescriptorType; | 611 | u8 bDescriptorType; |
301 | u16 wTotalLength; | 612 | u16 wTotalLength; |
302 | u8 bNumInterfaces; | 613 | u8 bNumInterfaces; |
303 | u8 bConfigurationValue; | 614 | u8 bConfigurationValue; |
304 | u8 iConfiguration; | 615 | u8 iConfiguration; |
305 | u8 bmAttributes; | 616 | u8 bmAttributes; |
306 | u8 bMaxPower; | 617 | u8 bMaxPower; |
307 | } __attribute__ ((packed)) USB_OtherSpeedConfigDescriptor; | 618 | } __attribute__ ((packed)) USB_OtherSpeedConfigDescriptor; |
308 | 619 | ||
309 | 620 | ||
310 | typedef struct { | 621 | typedef struct { |
311 | u8 bLength; | 622 | u8 bLength; |
312 | u8 bDescriptorType; | 623 | u8 bDescriptorType; |
313 | u8 bInterfaceNumber; | 624 | u8 bInterfaceNumber; |
314 | u8 bAlternateSetting; | 625 | u8 bAlternateSetting; |
315 | u8 bNumEndpoints; | 626 | u8 bNumEndpoints; |
316 | u8 bInterfaceClass; | 627 | u8 bInterfaceClass; |
317 | u8 bInterfaceSubClass; | 628 | u8 bInterfaceSubClass; |
318 | u8 bInterfaceProtocol; | 629 | u8 bInterfaceProtocol; |
319 | u8 iInterface; | 630 | u8 iInterface; |
320 | } __attribute__ ((packed)) USB_InterfaceDescriptor; | 631 | } __attribute__ ((packed)) USB_InterfaceDescriptor; |
321 | 632 | ||
322 | 633 | ||
323 | typedef struct { | 634 | typedef struct { |
324 | u8 bLegth; | 635 | u8 bLegth; |
325 | u8 bDescriptorType; | 636 | u8 bDescriptorType; |
326 | u8 bEndpointAddress; | 637 | u8 bEndpointAddress; |
327 | u8 bmAttributes; | 638 | u8 bmAttributes; |
328 | u16 wMaxPacketSize; | 639 | u16 wMaxPacketSize; |
329 | u8 bInterval; | 640 | u8 bInterval; |
330 | } __attribute__ ((packed)) USB_EndPointDescriptor; | 641 | } __attribute__ ((packed)) USB_EndPointDescriptor; |
331 | 642 | ||
332 | 643 | ||
333 | typedef struct { | 644 | typedef struct { |
334 | u8 bLength; | 645 | u8 bLength; |
335 | u8 bDescriptorType; | 646 | u8 bDescriptorType; |
336 | u16 SomeDesriptor[1]; | 647 | u16 SomeDesriptor[1]; |
337 | } __attribute__ ((packed)) USB_StringDescriptor; | 648 | } __attribute__ ((packed)) USB_StringDescriptor; |
338 | //------------------------------------------ | 649 | //------------------------------------------ |
339 | #define MAX_EP0_SIZE 64 | 650 | #define MAX_EP0_SIZE 64 |
340 | #define MAX_EP1_SIZE 512 | 651 | #define MAX_EP1_SIZE 512 |
341 | 652 | ||
342 | #define USB_HS 0 | 653 | #define USB_HS 0 |
343 | #define USB_FS 1 | 654 | #define USB_FS 1 |
344 | #define USB_LS 2 | 655 | #define USB_LS 2 |
345 | 656 | ||
346 | //definitions of EP0 | 657 | //definitions of EP0 |
347 | #define USB_EP0_IDLE 0 | 658 | #define USB_EP0_IDLE 0 |
348 | #define USB_EP0_RX 1 | 659 | #define USB_EP0_RX 1 |
349 | #define USB_EP0_TX 2 | 660 | #define USB_EP0_TX 2 |
350 | /* Define maximum packet size for endpoint 0 */ | 661 | /* Define maximum packet size for endpoint 0 */ |
351 | #define M_EP0_MAXP 64 | 662 | #define M_EP0_MAXP 64 |
352 | /* Endpoint 0 status structure */ | 663 | /* Endpoint 0 status structure */ |
353 | 664 | ||
354 | static __inline__ void usb_setb(u32 port, u8 val) | 665 | static __inline__ void usb_setb(u32 port, u8 val) |
355 | { | 666 | { |
356 | volatile u8 *ioport = (volatile u8 *)(port); | 667 | volatile u8 *ioport = (volatile u8 *)(port); |
357 | *ioport = (*ioport) | val; | 668 | *ioport = (*ioport) | val; |
358 | } | 669 | } |
359 | 670 | ||
360 | static __inline__ void usb_clearb(u32 port, u8 val) | 671 | static __inline__ void usb_clearb(u32 port, u8 val) |
361 | { | 672 | { |
362 | volatile u8 *ioport = (volatile u8 *)(port); | 673 | volatile u8 *ioport = (volatile u8 *)(port); |
363 | *ioport = (*ioport) & ~val; | 674 | *ioport = (*ioport) & ~val; |
364 | } | 675 | } |
365 | 676 | ||
366 | static __inline__ void usb_setw(u32 port, u16 val) | 677 | static __inline__ void usb_setw(u32 port, u16 val) |
367 | { | 678 | { |
368 | volatile u16 *ioport = (volatile u16 *)(port); | 679 | volatile u16 *ioport = (volatile u16 *)(port); |
369 | *ioport = (*ioport) | val; | 680 | *ioport = (*ioport) | val; |
370 | } | 681 | } |
371 | 682 | ||
372 | static __inline__ void usb_clearw(u32 port, u16 val) | 683 | static __inline__ void usb_clearw(u32 port, u16 val) |
373 | { | 684 | { |
374 | volatile u16 *ioport = (volatile u16 *)(port); | 685 | volatile u16 *ioport = (volatile u16 *)(port); |
375 | *ioport = (*ioport) & ~val; | 686 | *ioport = (*ioport) & ~val; |
376 | } | 687 | } |
377 | //--------------------------------- | 688 | //--------------------------------- |
378 | #define BULK_OUT_BUF_SIZE 0x20000 //buffer size : | 689 | #define BULK_OUT_BUF_SIZE 0x20000 //buffer size : |
@@ -380,118 +691,118 @@ static __inline__ void usb_clearw(u32 port, u16 val) | |||
380 | 691 | ||
381 | enum UDC_STATE | 692 | enum UDC_STATE |
382 | { | 693 | { |
383 | IDLE, | 694 | IDLE, |
384 | BULK_IN, | 695 | BULK_IN, |
385 | BULK_OUT | 696 | BULK_OUT |
386 | }; | 697 | }; |
387 | 698 | ||
388 | enum USB_JZ4740_REQUEST //add for USB_BOOT | 699 | enum USB_JZ4740_REQUEST //add for USB_BOOT |
389 | { | 700 | { |
390 | VR_GET_CUP_INFO = 0, | 701 | VR_GET_CUP_INFO = 0, |
391 | VR_SET_DATA_ADDERSS, | 702 | VR_SET_DATA_ADDERSS, |
392 | VR_SET_DATA_LENGTH, | 703 | VR_SET_DATA_LENGTH, |
393 | VR_FLUSH_CACHES, | 704 | VR_FLUSH_CACHES, |
394 | VR_PROGRAM_START1, | 705 | VR_PROGRAM_START1, |
395 | VR_PROGRAM_START2, | 706 | VR_PROGRAM_START2, |
396 | VR_NOR_OPS, | 707 | VR_NOR_OPS, |
397 | VR_NAND_OPS, | 708 | VR_NAND_OPS, |
398 | VR_SDRAM_OPS, | 709 | VR_SDRAM_OPS, |
399 | VR_CONFIGRATION | 710 | VR_CONFIGRATION |
400 | }; | 711 | }; |
401 | 712 | ||
402 | enum NOR_OPS_TYPE | 713 | enum NOR_OPS_TYPE |
403 | { | 714 | { |
404 | NOR_INIT = 0, | 715 | NOR_INIT = 0, |
405 | NOR_QUERY, | 716 | NOR_QUERY, |
406 | NOR_WRITE, | 717 | NOR_WRITE, |
407 | NOR_ERASE_CHIP, | 718 | NOR_ERASE_CHIP, |
408 | NOR_ERASE_SECTOR | 719 | NOR_ERASE_SECTOR |
409 | }; | 720 | }; |
410 | 721 | ||
411 | enum NOR_FLASH_TYPE | 722 | enum NOR_FLASH_TYPE |
412 | { | 723 | { |
413 | NOR_AM29 = 0, | 724 | NOR_AM29 = 0, |
414 | NOR_SST28, | 725 | NOR_SST28, |
415 | NOR_SST39x16, | 726 | NOR_SST39x16, |
416 | NOR_SST39x8 | 727 | NOR_SST39x8 |
417 | }; | 728 | }; |
418 | 729 | ||
419 | enum NAND_OPS_TYPE | 730 | enum NAND_OPS_TYPE |
420 | { | 731 | { |
421 | NAND_QUERY = 0, | 732 | NAND_QUERY = 0, |
422 | NAND_INIT, | 733 | NAND_INIT, |
423 | NAND_MARK_BAD, | 734 | NAND_MARK_BAD, |
424 | NAND_READ_OOB, | 735 | NAND_READ_OOB, |
425 | NAND_READ_RAW, | 736 | NAND_READ_RAW, |
426 | NAND_ERASE, | 737 | NAND_ERASE, |
427 | NAND_READ, | 738 | NAND_READ, |
428 | NAND_PROGRAM, | 739 | NAND_PROGRAM, |
429 | NAND_READ_TO_RAM | 740 | NAND_READ_TO_RAM |
430 | }; | 741 | }; |
431 | 742 | ||
432 | enum SDRAM_OPS_TYPE | 743 | enum SDRAM_OPS_TYPE |
433 | { | 744 | { |
434 | SDRAM_LOAD, | 745 | SDRAM_LOAD, |
435 | 746 | ||
436 | }; | 747 | }; |
437 | 748 | ||
438 | enum DATA_STRUCTURE_OB | 749 | enum DATA_STRUCTURE_OB |
439 | { | 750 | { |
440 | DS_flash_info , | 751 | DS_flash_info , |
441 | DS_hand | 752 | DS_hand |
442 | }; | 753 | }; |
443 | 754 | ||
444 | 755 | ||
445 | /*typedef enum _USB_BOOT_STATUS | 756 | /*typedef enum _USB_BOOT_STATUS |
446 | { | 757 | { |
447 | USB_NO_ERR =0 , | 758 | USB_NO_ERR =0 , |
448 | GET_CPU_INFO_ERR, | 759 | GET_CPU_INFO_ERR, |
449 | SET_DATA_ADDRESS_ERR, | 760 | SET_DATA_ADDRESS_ERR, |
450 | SET_DATA_LENGTH_ERR, | 761 | SET_DATA_LENGTH_ERR, |
451 | FLUSH_CAHCES_ERR, | 762 | FLUSH_CAHCES_ERR, |
452 | PROGRAM_START1_ERR, | 763 | PROGRAM_START1_ERR, |
453 | PROGRAM_START2_ERR, | 764 | PROGRAM_START2_ERR, |
454 | NOR_OPS_ERR, | 765 | NOR_OPS_ERR, |
455 | NAND_OPS_ERR, | 766 | NAND_OPS_ERR, |
456 | NOR_FLASHTYPE_ERR, | 767 | NOR_FLASHTYPE_ERR, |
457 | OPS_NOTSUPPORT_ERR | 768 | OPS_NOTSUPPORT_ERR |
458 | }USB_BOOT_STATUS;*/ | 769 | }USB_BOOT_STATUS;*/ |
459 | 770 | ||
460 | enum OPTION | 771 | enum OPTION |
461 | { | 772 | { |
462 | OOB_ECC, | 773 | OOB_ECC, |
463 | OOB_NO_ECC, | 774 | OOB_NO_ECC, |
464 | NO_OOB, | 775 | NO_OOB, |
465 | }; | 776 | }; |
466 | //------------------------- | 777 | //------------------------- |
467 | static inline void jz_writeb(u32 address, u8 value) | 778 | static inline void jz_writeb(u32 address, u8 value) |
468 | { | 779 | { |
469 | *((volatile u8 *)address) = value; | 780 | *((volatile u8 *)address) = value; |
470 | } | 781 | } |
471 | 782 | ||
472 | static inline void jz_writew(u32 address, u16 value) | 783 | static inline void jz_writew(u32 address, u16 value) |
473 | { | 784 | { |
474 | *((volatile u16 *)address) = value; | 785 | *((volatile u16 *)address) = value; |
475 | } | 786 | } |
476 | 787 | ||
477 | static inline void jz_writel(u32 address, u32 value) | 788 | static inline void jz_writel(u32 address, u32 value) |
478 | { | 789 | { |
479 | *((volatile u32 *)address) = value; | 790 | *((volatile u32 *)address) = value; |
480 | } | 791 | } |
481 | 792 | ||
482 | static inline u8 jz_readb(u32 address) | 793 | static inline u8 jz_readb(u32 address) |
483 | { | 794 | { |
484 | return *((volatile u8 *)address); | 795 | return *((volatile u8 *)address); |
485 | } | 796 | } |
486 | 797 | ||
487 | static inline u16 jz_readw(u32 address) | 798 | static inline u16 jz_readw(u32 address) |
488 | { | 799 | { |
489 | return *((volatile u16 *)address); | 800 | return *((volatile u16 *)address); |
490 | } | 801 | } |
491 | 802 | ||
492 | static inline u32 jz_readl(u32 address) | 803 | static inline u32 jz_readl(u32 address) |
493 | { | 804 | { |
494 | return *((volatile u32 *)address); | 805 | return *((volatile u32 *)address); |
495 | } | 806 | } |
496 | //--------------------------- | 807 | //--------------------------- |
497 | 808 | ||
@@ -510,530 +821,560 @@ static u8 ep0state,USB_Version; | |||
510 | 821 | ||
511 | static u32 fifoaddr[] = | 822 | static u32 fifoaddr[] = |
512 | { | 823 | { |
513 | TXFIFOEP0, TXFIFOEP0+4 ,TXFIFOEP0+8 | 824 | TXFIFOEP0, TXFIFOEP0+4 ,TXFIFOEP0+8 |
514 | }; | 825 | }; |
515 | 826 | ||
516 | static u32 fifosize[] = { | 827 | static u32 fifosize[] = { |
517 | MAX_EP0_SIZE, MAX_EP1_SIZE | 828 | MAX_EP0_SIZE, MAX_EP1_SIZE |
518 | }; | 829 | }; |
519 | 830 | ||
520 | static void udcReadFifo(u8 *ptr, int size) | 831 | static void udcReadFifo(u8 *ptr, int size) |
521 | { | 832 | { |
522 | u32 *d = (u32 *)ptr; | 833 | u32 *d = (u32 *)ptr; |
523 | int s; | 834 | int s; |
524 | s = (size + 3) >> 2; | 835 | s = (size + 3) >> 2; |
525 | while (s--) | 836 | while (s--) |
526 | *d++ = REG32(fifo); | 837 | *d++ = REG32(fifo); |
527 | } | 838 | } |
528 | 839 | ||
529 | static void udcWriteFifo(u8 *ptr, int size) | 840 | static void udcWriteFifo(u8 *ptr, int size) |
530 | { | 841 | { |
531 | u32 *d = (u32 *)ptr; | 842 | u32 *d = (u32 *)ptr; |
532 | u8 *c; | 843 | u8 *c; |
533 | int s, q; | 844 | int s, q; |
534 | 845 | ||
535 | if (size > 0) { | 846 | if (size > 0) { |
536 | s = size >> 2; | 847 | s = size >> 2; |
537 | while (s--) | 848 | while (s--) |
538 | REG32(fifo) = *d++; | 849 | REG32(fifo) = *d++; |
539 | q = size & 3; | 850 | q = size & 3; |
540 | if (q) { | 851 | if (q) { |
541 | c = (u8 *)d; | 852 | c = (u8 *)d; |
542 | while (q--) | 853 | while (q--) |
543 | REG8(fifo) = *c++; | 854 | REG8(fifo) = *c++; |
544 | } | 855 | } |
545 | } | 856 | } |
546 | } | 857 | } |
547 | 858 | ||
548 | void HW_SendPKT(int ep, const u8 *buf, int size) | 859 | void HW_SendPKT(int ep, const u8 *buf, int size) |
549 | { | 860 | { |
550 | fifo = fifoaddr[ep]; | 861 | fifo = fifoaddr[ep]; |
551 | 862 | ||
552 | if (ep!=0) | 863 | if (ep!=0) |
553 | { | 864 | { |
554 | Bulk_in_size = size; | 865 | Bulk_in_size = size; |
555 | Bulk_in_finish = 0; | 866 | Bulk_in_finish = 0; |
556 | jz_writeb(USB_REG_INDEX, ep); | 867 | jz_writeb(USB_REG_INDEX, ep); |
557 | if (Bulk_in_size - Bulk_in_finish <= fifosize[ep]) | 868 | if (Bulk_in_size - Bulk_in_finish <= fifosize[ep]) |
558 | { | 869 | { |
559 | udcWriteFifo((u8 *)((u32)buf+Bulk_in_finish), | 870 | udcWriteFifo((u8 *)((u32)buf+Bulk_in_finish), |
560 | Bulk_in_size - Bulk_in_finish); | 871 | Bulk_in_size - Bulk_in_finish); |
561 | usb_setb(USB_REG_INCSR, USB_INCSR_INPKTRDY); | 872 | usb_setb(USB_REG_INCSR, USB_INCSR_INPKTRDY); |
562 | Bulk_in_finish = Bulk_in_size; | 873 | Bulk_in_finish = Bulk_in_size; |
563 | } | 874 | } |
564 | else | 875 | else |
565 | { | 876 | { |
566 | udcWriteFifo((u8 *)((u32)buf+Bulk_in_finish), | 877 | udcWriteFifo((u8 *)((u32)buf+Bulk_in_finish), |
567 | fifosize[ep]); | 878 | fifosize[ep]); |
568 | usb_setb(USB_REG_INCSR, USB_INCSR_INPKTRDY); | 879 | usb_setb(USB_REG_INCSR, USB_INCSR_INPKTRDY); |
569 | Bulk_in_finish += fifosize[ep]; | 880 | Bulk_in_finish += fifosize[ep]; |
570 | Bulk_in_buf = (u8*)buf; | 881 | Bulk_in_buf = (u8*)buf; |
571 | } | 882 | } |
572 | } | 883 | } |
573 | else //EP0 | 884 | else //EP0 |
574 | { | 885 | { |
575 | tx_size = size; | 886 | tx_size = size; |
576 | finished = 0; | 887 | finished = 0; |
577 | memcpy((void *)tx_buf, buf, size); | 888 | memcpy((void *)tx_buf, buf, size); |
578 | ep0state = USB_EP0_TX; | 889 | ep0state = USB_EP0_TX; |
579 | } | 890 | } |
891 | } | ||
892 | |||
893 | void HW_GetPKT(int ep, const u8 *buf, unsigned int size) | ||
894 | { | ||
895 | memcpy((void *)buf, (u8 *)rx_buf, size); | ||
896 | fifo = fifoaddr[ep]; | ||
897 | if (rx_size > size) | ||
898 | rx_size -= size; | ||
899 | else | ||
900 | { | ||
901 | size = rx_size; | ||
902 | rx_size = 0; | ||
903 | } | ||
904 | memcpy((u8 *)rx_buf, (u8 *)((u32)rx_buf+size), rx_size); | ||
905 | } | ||
906 | |||
907 | void Enable_DMA(u8* buf, u32 length) | ||
908 | { | ||
909 | dma_cache_wback_inv((u32)buf, length); | ||
910 | jz_writeb(USB_REG_INDEX, 1); | ||
911 | usb_setw(USB_REG_INCSR, 0x9400); | ||
912 | usb_clearw(USB_REG_INTRINE, 0x2); //disable OUT intr | ||
913 | jz_writel(USB_REG_ADDR1, (u32)buf); | ||
914 | jz_writel(USB_REG_COUNT1, length); | ||
915 | jz_writel(USB_REG_CNTL1, 0x001f); | ||
580 | } | 916 | } |
581 | 917 | ||
582 | void HW_GetPKT(int ep, const u8 *buf, int size) | 918 | void Disable_DMA(void) |
583 | { | 919 | { |
584 | memcpy((void *)buf, (u8 *)rx_buf, size); | 920 | jz_writeb(USB_REG_INDEX, 1); |
585 | fifo = fifoaddr[ep]; | 921 | usb_clearw(USB_REG_INCSR, 0x9400); |
586 | if (rx_size > size) | 922 | usb_setw(USB_REG_INTRINE, 0x2); //Enable OUT intr |
587 | rx_size -= size; | ||
588 | else { | ||
589 | size = rx_size; | ||
590 | rx_size = 0; | ||
591 | } | ||
592 | memcpy((u8 *)rx_buf, (u8 *)((u32)rx_buf+size), rx_size); | ||
593 | } | 923 | } |
594 | 924 | ||
595 | static USB_DeviceDescriptor devDesc = | 925 | static USB_DeviceDescriptor devDesc = |
596 | { | 926 | { |
597 | sizeof(USB_DeviceDescriptor), | 927 | sizeof(USB_DeviceDescriptor), |
598 | DEVICE_DESCRIPTOR, //1 | 928 | DEVICE_DESCRIPTOR, //1 |
599 | 0x0200, //Version 2.0 | 929 | 0x0200, //Version 2.0 |
600 | 0xff, //Vendor spec class | 930 | 0xff, //Vendor spec class |
601 | 0xff, | 931 | 0xff, |
602 | 0xff, | 932 | 0xff, |
603 | 64, /* Ep0 FIFO size */ | 933 | 64, /* Ep0 FIFO size */ |
604 | 0x601a, //vendor ID | 934 | 0x601a, //vendor ID |
605 | 0xDEAD, //Product ID | 935 | 0xDEAD, //Product ID |
606 | 0xffff, | 936 | 0xffff, |
607 | 0x00, | 937 | 0x00, |
608 | 0x00, | 938 | 0x00, |
609 | 0x00, | 939 | 0x00, |
610 | 0x01 | 940 | 0x01 |
611 | }; | 941 | }; |
612 | 942 | ||
613 | #define CONFIG_DESCRIPTOR_LEN (sizeof(USB_ConfigDescriptor) + \ | 943 | #define CONFIG_DESCRIPTOR_LEN (sizeof(USB_ConfigDescriptor) + \ |
614 | sizeof(USB_InterfaceDescriptor) + \ | 944 | sizeof(USB_InterfaceDescriptor) + \ |
615 | sizeof(USB_EndPointDescriptor) * 2) | 945 | sizeof(USB_EndPointDescriptor) * 2) |
616 | 946 | ||
617 | static struct { | 947 | static struct { |
618 | USB_ConfigDescriptor configuration_descriptor; | 948 | USB_ConfigDescriptor configuration_descriptor; |
619 | USB_InterfaceDescriptor interface_descritor; | 949 | USB_InterfaceDescriptor interface_descritor; |
620 | USB_EndPointDescriptor endpoint_descriptor[2]; | 950 | USB_EndPointDescriptor endpoint_descriptor[2]; |
621 | } __attribute__ ((packed)) confDesc = { | 951 | } __attribute__ ((packed)) confDesc = { |
622 | { | 952 | { |
623 | sizeof(USB_ConfigDescriptor), | 953 | sizeof(USB_ConfigDescriptor), |
624 | CONFIGURATION_DESCRIPTOR, | 954 | CONFIGURATION_DESCRIPTOR, |
625 | CONFIG_DESCRIPTOR_LEN, | 955 | CONFIG_DESCRIPTOR_LEN, |
626 | 0x01, | 956 | 0x01, |
627 | 0x01, | 957 | 0x01, |
628 | 0x00, | 958 | 0x00, |
629 | 0xc0, // Self Powered, no remote wakeup | 959 | 0xc0, // Self Powered, no remote wakeup |
630 | 0x64 // Maximum power consumption 2000 mA | 960 | 0x64 // Maximum power consumption 2000 mA |
631 | }, | 961 | }, |
632 | { | 962 | { |
633 | sizeof(USB_InterfaceDescriptor), | 963 | sizeof(USB_InterfaceDescriptor), |
634 | INTERFACE_DESCRIPTOR, | 964 | INTERFACE_DESCRIPTOR, |
635 | 0x00, | 965 | 0x00, |
636 | 0x00, | 966 | 0x00, |
637 | 0x02, /* ep number */ | 967 | 0x02, /* ep number */ |
638 | 0xff, | 968 | 0xff, |
639 | 0xff, | 969 | 0xff, |
640 | 0xff, | 970 | 0xff, |
641 | 0x00 | 971 | 0x00 |
642 | }, | 972 | }, |
643 | { | 973 | { |
644 | { | 974 | { |
645 | sizeof(USB_EndPointDescriptor), | 975 | sizeof(USB_EndPointDescriptor), |
646 | ENDPOINT_DESCRIPTOR, | 976 | ENDPOINT_DESCRIPTOR, |
647 | (1 << 7) | 1,// endpoint 2 is IN endpoint | 977 | (1 << 7) | 1,// endpoint 2 is IN endpoint |
648 | 2, /* bulk */ | 978 | 2, /* bulk */ |
649 | 512, | 979 | 512, |
650 | 0 | 980 | 0 |
651 | }, | 981 | }, |
652 | { | 982 | { |
653 | sizeof(USB_EndPointDescriptor), | 983 | sizeof(USB_EndPointDescriptor), |
654 | ENDPOINT_DESCRIPTOR, | 984 | ENDPOINT_DESCRIPTOR, |
655 | (0 << 7) | 1,// endpoint 5 is OUT endpoint | 985 | (0 << 7) | 1,// endpoint 5 is OUT endpoint |
656 | 2, /* bulk */ | 986 | 2, /* bulk */ |
657 | 512, /* OUT EP FIFO size */ | 987 | 512, /* OUT EP FIFO size */ |
658 | 0 | 988 | 0 |
659 | } | 989 | } |
660 | } | 990 | } |
661 | }; | 991 | }; |
662 | 992 | ||
663 | void sendDevDescString(int size) | 993 | void sendDevDescString(int size) |
664 | { | 994 | { |
665 | u16 str_ret[13] = { | 995 | u16 str_ret[13] = { |
666 | 0x031a,//0x1a=26 byte | 996 | 0x031a,//0x1a=26 byte |
667 | 0x0041, | 997 | 0x0041, |
668 | 0x0030, | 998 | 0x0030, |
669 | 0x0030, | 999 | 0x0030, |
670 | 0x0041, | 1000 | 0x0041, |
671 | 0x0030, | 1001 | 0x0030, |
672 | 0x0030, | 1002 | 0x0030, |
673 | 0x0041, | 1003 | 0x0041, |
674 | 0x0030, | 1004 | 0x0030, |
675 | 0x0030, | 1005 | 0x0030, |
676 | 0x0041, | 1006 | 0x0041, |
677 | 0x0030, | 1007 | 0x0030, |
678 | 0x0030 | 1008 | 0x0030 |
679 | }; | 1009 | }; |
680 | if(size >= 26) | 1010 | if(size >= 26) |
681 | size = 26; | 1011 | size = 26; |
682 | str_ret[0] = (0x0300 | size); | 1012 | str_ret[0] = (0x0300 | size); |
683 | HW_SendPKT(0, (u8 *)str_ret,size); | 1013 | HW_SendPKT(0, (u8 *)str_ret,size); |
684 | } | 1014 | } |
685 | 1015 | ||
686 | void sendDevDesc(int size) | 1016 | void sendDevDesc(int size) |
687 | { | 1017 | { |
688 | switch (size) { | 1018 | switch (size) { |
689 | case 18: | 1019 | case 18: |
690 | HW_SendPKT(0, (u8 *)&devDesc, sizeof(devDesc)); | 1020 | HW_SendPKT(0, (u8 *)&devDesc, sizeof(devDesc)); |
691 | break; | 1021 | break; |
692 | default: | 1022 | default: |
693 | HW_SendPKT(0, (u8 *)&devDesc, 8); | 1023 | HW_SendPKT(0, (u8 *)&devDesc, 8); |
694 | break; | 1024 | break; |
695 | } | 1025 | } |
696 | } | 1026 | } |
697 | 1027 | ||
698 | void sendConfDesc(int size) | 1028 | void sendConfDesc(int size) |
699 | { | 1029 | { |
700 | switch (size) { | 1030 | switch (size) { |
701 | case 9: | 1031 | case 9: |
702 | HW_SendPKT(0, (u8 *)&confDesc, 9); | 1032 | HW_SendPKT(0, (u8 *)&confDesc, 9); |
703 | break; | 1033 | break; |
704 | case 8: | 1034 | case 8: |
705 | HW_SendPKT(0, (u8 *)&confDesc, 8); | 1035 | HW_SendPKT(0, (u8 *)&confDesc, 8); |
706 | break; | 1036 | break; |
707 | default: | 1037 | default: |
708 | HW_SendPKT(0, (u8 *)&confDesc, sizeof(confDesc)); | 1038 | HW_SendPKT(0, (u8 *)&confDesc, sizeof(confDesc)); |
709 | break; | 1039 | break; |
710 | } | 1040 | } |
711 | } | 1041 | } |
712 | 1042 | ||
713 | void EP0_init(u32 out, u32 out_size, u32 in, u32 in_size) | 1043 | void EP0_init(u32 out, u32 out_size, u32 in, u32 in_size) |
714 | { | 1044 | { |
715 | confDesc.endpoint_descriptor[0].bEndpointAddress = (1<<7) | in; | 1045 | confDesc.endpoint_descriptor[0].bEndpointAddress = (1<<7) | in; |
716 | confDesc.endpoint_descriptor[0].wMaxPacketSize = in_size; | 1046 | confDesc.endpoint_descriptor[0].wMaxPacketSize = in_size; |
717 | confDesc.endpoint_descriptor[1].bEndpointAddress = (0<<7) | out; | 1047 | confDesc.endpoint_descriptor[1].bEndpointAddress = (0<<7) | out; |
718 | confDesc.endpoint_descriptor[1].wMaxPacketSize = out_size; | 1048 | confDesc.endpoint_descriptor[1].wMaxPacketSize = out_size; |
719 | } | 1049 | } |
720 | 1050 | ||
721 | static void udc_reset(void) | 1051 | static void udc_reset(void) |
722 | { | 1052 | { |
723 | //data init | 1053 | //data init |
724 | ep0state = USB_EP0_IDLE; | 1054 | ep0state = USB_EP0_IDLE; |
725 | Bulk_in_size = 0; | 1055 | Bulk_in_size = 0; |
726 | Bulk_in_finish = 0; | 1056 | Bulk_in_finish = 0; |
727 | Bulk_out_size = 0; | 1057 | Bulk_out_size = 0; |
728 | udc_state = IDLE; | 1058 | udc_state = IDLE; |
729 | tx_size = 0; | 1059 | tx_size = 0; |
730 | rx_size = 0; | 1060 | rx_size = 0; |
731 | finished = 0; | 1061 | finished = 0; |
732 | /* Enable the USB PHY */ | 1062 | /* Enable the USB PHY */ |
733 | // REG_CPM_SCR |= CPM_SCR_USBPHY_ENABLE; | 1063 | // REG_CPM_SCR |= CPM_SCR_USBPHY_ENABLE; |
734 | /* Disable interrupts */ | 1064 | /* Disable interrupts */ |
735 | jz_writew(USB_REG_INTRINE, 0); | 1065 | jz_writew(USB_REG_INTRINE, 0); |
736 | jz_writew(USB_REG_INTROUTE, 0); | 1066 | jz_writew(USB_REG_INTROUTE, 0); |
737 | jz_writeb(USB_REG_INTRUSBE, 0); | 1067 | jz_writeb(USB_REG_INTRUSBE, 0); |
738 | jz_writeb(USB_REG_FADDR,0); | 1068 | jz_writeb(USB_REG_FADDR,0); |
739 | jz_writeb(USB_REG_POWER,0x60); //High speed | 1069 | jz_writeb(USB_REG_POWER,0x60); //High speed |
740 | jz_writeb(USB_REG_INDEX,0); | 1070 | jz_writeb(USB_REG_INDEX,0); |
741 | jz_writeb(USB_REG_CSR0,0xc0); | 1071 | jz_writeb(USB_REG_CSR0,0xc0); |
742 | jz_writeb(USB_REG_INDEX,1); | 1072 | jz_writeb(USB_REG_INDEX,1); |
743 | jz_writew(USB_REG_INMAXP,512); | 1073 | jz_writew(USB_REG_INMAXP,512); |
744 | jz_writew(USB_REG_INCSR,0x2048); | 1074 | jz_writew(USB_REG_INCSR,0x2048); |
745 | jz_writeb(USB_REG_INDEX,1); | 1075 | jz_writeb(USB_REG_INDEX,1); |
746 | jz_writew(USB_REG_OUTMAXP,512); | 1076 | jz_writew(USB_REG_OUTMAXP,512); |
747 | jz_writew(USB_REG_OUTCSR,0x0090); | 1077 | jz_writew(USB_REG_OUTCSR,0x0090); |
748 | jz_writew(USB_REG_INTRINE,0x3); //enable intr | 1078 | jz_writew(USB_REG_INTRINE,0x3); //enable intr |
749 | jz_writew(USB_REG_INTROUTE,0x2); | 1079 | jz_writew(USB_REG_INTROUTE,0x2); |
750 | jz_writeb(USB_REG_INTRUSBE,0x4); | 1080 | jz_writeb(USB_REG_INTRUSBE,0x4); |
751 | 1081 | ||
752 | if ((jz_readb(USB_REG_POWER)&0x10)==0) | 1082 | if ((jz_readb(USB_REG_POWER)&0x10)==0) |
753 | { | 1083 | { |
754 | jz_writeb(USB_REG_INDEX,1); | 1084 | jz_writeb(USB_REG_INDEX,1); |
755 | jz_writew(USB_REG_INMAXP,64); | 1085 | jz_writew(USB_REG_INMAXP,64); |
756 | jz_writew(USB_REG_INCSR,0x2048); | 1086 | jz_writew(USB_REG_INCSR,0x2048); |
757 | jz_writeb(USB_REG_INDEX,1); | 1087 | jz_writeb(USB_REG_INDEX,1); |
758 | jz_writew(USB_REG_OUTMAXP,64); | 1088 | jz_writew(USB_REG_OUTMAXP,64); |
759 | jz_writew(USB_REG_OUTCSR,0x0090); | 1089 | jz_writew(USB_REG_OUTCSR,0x0090); |
760 | USB_Version=USB_FS; | 1090 | USB_Version=USB_FS; |
761 | fifosize[1]=64; | 1091 | fifosize[1]=64; |
762 | EP0_init(1,64,1,64); | 1092 | EP0_init(1,64,1,64); |
763 | } | 1093 | } |
764 | else | 1094 | else |
765 | { | 1095 | { |
766 | jz_writeb(USB_REG_INDEX,1); | 1096 | jz_writeb(USB_REG_INDEX,1); |
767 | jz_writew(USB_REG_INMAXP,512); | 1097 | jz_writew(USB_REG_INMAXP,512); |
768 | jz_writew(USB_REG_INCSR,0x2048); | 1098 | jz_writew(USB_REG_INCSR,0x2048); |
769 | jz_writeb(USB_REG_INDEX,1); | 1099 | jz_writeb(USB_REG_INDEX,1); |
770 | jz_writew(USB_REG_OUTMAXP,512); | 1100 | jz_writew(USB_REG_OUTMAXP,512); |
771 | jz_writew(USB_REG_OUTCSR,0x0090); | 1101 | jz_writew(USB_REG_OUTCSR,0x0090); |
772 | USB_Version=USB_HS; | 1102 | USB_Version=USB_HS; |
773 | fifosize[1]=512; | 1103 | fifosize[1]=512; |
774 | EP0_init(1,512,1,512); | 1104 | EP0_init(1,512,1,512); |
775 | } | 1105 | } |
776 | 1106 | ||
777 | } | 1107 | } |
778 | 1108 | ||
779 | void usbHandleStandDevReq(u8 *buf) | 1109 | void usbHandleStandDevReq(u8 *buf) |
780 | { | 1110 | { |
781 | USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf; | 1111 | USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf; |
782 | switch (dreq->bRequest) { | 1112 | switch (dreq->bRequest) { |
783 | case GET_DESCRIPTOR: | 1113 | case GET_DESCRIPTOR: |
784 | if (dreq->bmRequestType == 0x80) /* Dev2Host */ | 1114 | if (dreq->bmRequestType == 0x80) /* Dev2Host */ |
785 | switch(dreq->wValue >> 8) | 1115 | switch(dreq->wValue >> 8) |
786 | { | 1116 | { |
787 | case DEVICE_DESCRIPTOR: | 1117 | case DEVICE_DESCRIPTOR: |
788 | sendDevDesc(dreq->wLength); | 1118 | sendDevDesc(dreq->wLength); |
789 | break; | 1119 | break; |
790 | case CONFIGURATION_DESCRIPTOR: | 1120 | case CONFIGURATION_DESCRIPTOR: |
791 | sendConfDesc(dreq->wLength); | 1121 | sendConfDesc(dreq->wLength); |
792 | break; | 1122 | break; |
793 | case STRING_DESCRIPTOR: | 1123 | case STRING_DESCRIPTOR: |
794 | if (dreq->wLength == 0x02) | 1124 | if (dreq->wLength == 0x02) |
795 | HW_SendPKT(0, "\x04\x03", 2); | 1125 | HW_SendPKT(0, "\x04\x03", 2); |
796 | else | 1126 | else |
797 | sendDevDescString(dreq->wLength); | 1127 | sendDevDescString(dreq->wLength); |
798 | //HW_SendPKT(0, "\x04\x03\x09\x04", 2); | 1128 | //HW_SendPKT(0, "\x04\x03\x09\x04", 2); |
799 | break; | 1129 | break; |
800 | } | 1130 | } |
801 | ep0state=USB_EP0_TX; | 1131 | ep0state=USB_EP0_TX; |
802 | 1132 | ||
803 | break; | 1133 | break; |
804 | case SET_ADDRESS: | 1134 | case SET_ADDRESS: |
805 | jz_writeb(USB_REG_FADDR,dreq->wValue); | 1135 | jz_writeb(USB_REG_FADDR,dreq->wValue); |
806 | break; | 1136 | break; |
807 | case GET_STATUS: | 1137 | case GET_STATUS: |
808 | switch (dreq->bmRequestType) { | 1138 | switch (dreq->bmRequestType) { |
809 | case 80: /* device */ | 1139 | case 80: /* device */ |
810 | HW_SendPKT(0, "\x01\x00", 2); | 1140 | HW_SendPKT(0, "\x01\x00", 2); |
811 | break; | 1141 | break; |
812 | case 81: /* interface */ | 1142 | case 81: /* interface */ |
813 | case 82: /* ep */ | 1143 | case 82: /* ep */ |
814 | HW_SendPKT(0, "\x00\x00", 2); | 1144 | HW_SendPKT(0, "\x00\x00", 2); |
815 | break; | 1145 | break; |
816 | } | 1146 | } |
817 | ep0state=USB_EP0_TX; | 1147 | ep0state=USB_EP0_TX; |
818 | break; | 1148 | break; |
819 | case CLEAR_FEATURE: | 1149 | case CLEAR_FEATURE: |
820 | case SET_CONFIGURATION: | 1150 | case SET_CONFIGURATION: |
821 | case SET_INTERFACE: | 1151 | case SET_INTERFACE: |
822 | case SET_FEATURE: | 1152 | case SET_FEATURE: |
823 | break; | 1153 | break; |
824 | } | 1154 | } |
825 | } | 1155 | } |
826 | 1156 | ||
827 | unsigned char nandbuffer[4096]; | 1157 | unsigned char nandbuffer[4096]; |
1158 | extern void jz_nand_read(int block, int page, unsigned char *buf); | ||
828 | 1159 | ||
829 | void usbHandleVendorReq(u8 *buf) | 1160 | void usbHandleVendorReq(u8 *buf) |
830 | { | 1161 | { |
831 | USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf; | 1162 | USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf; |
832 | switch (dreq->bRequest) | 1163 | switch (dreq->bRequest) |
833 | { | 1164 | { |
834 | case 0xB0: | 1165 | case 0xB0: |
835 | memset(&nandbuffer, 0, 4096); | 1166 | memset(&nandbuffer, 0, 4096); |
836 | jz_nand_read(dreq->wValue, dreq->wIndex, &nandbuffer); | 1167 | jz_nand_read(dreq->wValue, dreq->wIndex, nandbuffer); |
837 | //printf("Read block %d page %d", dreq->wValue, dreq->wIndex); | 1168 | //printf("Read block %d page %d", dreq->wValue, dreq->wIndex); |
838 | udc_state = IDLE; | 1169 | udc_state = IDLE; |
839 | break; | 1170 | break; |
840 | case 0xAB: | 1171 | case 0xAB: |
841 | HW_SendPKT(1, nandbuffer, 4096); | 1172 | Enable_DMA(nandbuffer, 4096); |
1173 | //HW_SendPKT(1, nandbuffer, 4096); | ||
842 | //printf("Send data"); | 1174 | //printf("Send data"); |
843 | //udc_state = BULK_OUT; | 1175 | //udc_state = BULK_OUT; |
844 | break; | 1176 | break; |
845 | case 0x12: | 1177 | case 0x12: |
846 | HW_SendPKT(0, "TEST", 4); | 1178 | HW_SendPKT(0, "TEST", 4); |
847 | //printf("Send test"); | 1179 | //printf("Send test"); |
848 | udc_state = IDLE; | 1180 | udc_state = IDLE; |
849 | break; | 1181 | break; |
850 | } | 1182 | } |
851 | } | 1183 | } |
852 | 1184 | ||
853 | void Handshake_PKT(void) | 1185 | void Handshake_PKT(void) |
854 | { | 1186 | { |
855 | if (udc_state!=IDLE) | 1187 | if (udc_state!=IDLE) |
856 | { | 1188 | { |
857 | HW_SendPKT(1,(u8 *)handshake_PKT,sizeof(handshake_PKT)); | 1189 | HW_SendPKT(1,(u8 *)handshake_PKT,sizeof(handshake_PKT)); |
858 | udc_state = IDLE; | 1190 | udc_state = IDLE; |
859 | } | 1191 | } |
860 | } | 1192 | } |
861 | 1193 | ||
862 | void usbHandleDevReq(u8 *buf) | 1194 | void usbHandleDevReq(u8 *buf) |
863 | { | 1195 | { |
864 | switch ((buf[0] & (3 << 5)) >> 5) { | 1196 | switch ((buf[0] & (3 << 5)) >> 5) { |
865 | case 0: /* Standard request */ | 1197 | case 0: /* Standard request */ |
866 | usbHandleStandDevReq(buf); | 1198 | usbHandleStandDevReq(buf); |
867 | break; | 1199 | break; |
868 | case 1: /* Class request */ | 1200 | case 1: /* Class request */ |
869 | break; | 1201 | break; |
870 | case 2: /* Vendor request */ | 1202 | case 2: /* Vendor request */ |
871 | usbHandleVendorReq(buf); | 1203 | usbHandleVendorReq(buf); |
872 | break; | 1204 | break; |
873 | } | 1205 | } |
874 | } | 1206 | } |
875 | 1207 | ||
876 | void EP0_Handler (void) | 1208 | void EP0_Handler (void) |
877 | { | 1209 | { |
878 | u8 byCSR0; | 1210 | u8 byCSR0; |
879 | 1211 | ||
880 | /* Read CSR0 */ | 1212 | /* Read CSR0 */ |
881 | jz_writeb(USB_REG_INDEX, 0); | 1213 | jz_writeb(USB_REG_INDEX, 0); |
882 | byCSR0 = jz_readb(USB_REG_CSR0); | 1214 | byCSR0 = jz_readb(USB_REG_CSR0); |
883 | 1215 | ||
884 | /* Check for SentStall | 1216 | /* Check for SentStall |
885 | if sendstall is set ,clear the sendstall bit*/ | 1217 | if sendstall is set ,clear the sendstall bit*/ |
886 | if (byCSR0 & USB_CSR0_SENTSTALL) | 1218 | if (byCSR0 & USB_CSR0_SENTSTALL) |
887 | { | 1219 | { |
888 | jz_writeb(USB_REG_CSR0, (byCSR0 & ~USB_CSR0_SENDSTALL)); | 1220 | jz_writeb(USB_REG_CSR0, (byCSR0 & ~USB_CSR0_SENDSTALL)); |
889 | ep0state = USB_EP0_IDLE; | 1221 | ep0state = USB_EP0_IDLE; |
890 | return; | 1222 | return; |
891 | } | 1223 | } |
892 | 1224 | ||
893 | /* Check for SetupEnd */ | 1225 | /* Check for SetupEnd */ |
894 | if (byCSR0 & USB_CSR0_SETUPEND) | 1226 | if (byCSR0 & USB_CSR0_SETUPEND) |
895 | { | 1227 | { |
896 | jz_writeb(USB_REG_CSR0, (byCSR0 | USB_CSR0_SVDSETUPEND)); | 1228 | jz_writeb(USB_REG_CSR0, (byCSR0 | USB_CSR0_SVDSETUPEND)); |
897 | ep0state = USB_EP0_IDLE; | 1229 | ep0state = USB_EP0_IDLE; |
898 | return; | 1230 | return; |
899 | } | 1231 | } |
900 | /* Call relevant routines for endpoint 0 state */ | 1232 | /* Call relevant routines for endpoint 0 state */ |
901 | if (ep0state == USB_EP0_IDLE) | 1233 | if (ep0state == USB_EP0_IDLE) |
902 | { | 1234 | { |
903 | if (byCSR0 & USB_CSR0_OUTPKTRDY) //There are datas in fifo | 1235 | if (byCSR0 & USB_CSR0_OUTPKTRDY) //There are datas in fifo |
904 | { | 1236 | { |
905 | USB_DeviceRequest *dreq; | 1237 | USB_DeviceRequest *dreq; |
906 | fifo=fifoaddr[0]; | 1238 | fifo=fifoaddr[0]; |
907 | udcReadFifo((u8 *)rx_buf, sizeof(USB_DeviceRequest)); | 1239 | udcReadFifo((u8 *)rx_buf, sizeof(USB_DeviceRequest)); |
908 | usb_setb(USB_REG_CSR0, 0x48);//clear OUTRD bit | 1240 | usb_setb(USB_REG_CSR0, 0x48);//clear OUTRD bit |
909 | dreq = (USB_DeviceRequest *)rx_buf; | 1241 | dreq = (USB_DeviceRequest *)rx_buf; |
910 | usbHandleDevReq((u8 *)rx_buf); | 1242 | usbHandleDevReq((u8 *)rx_buf); |
911 | } | 1243 | } |
912 | rx_size = 0; | 1244 | rx_size = 0; |
913 | } | 1245 | } |
914 | 1246 | ||
915 | if (ep0state == USB_EP0_TX) | 1247 | if (ep0state == USB_EP0_TX) |
916 | { | 1248 | { |
917 | fifo=fifoaddr[0]; | 1249 | fifo=fifoaddr[0]; |
918 | if (tx_size - finished <= 64) | 1250 | if (tx_size - finished <= 64) |
919 | { | 1251 | { |
920 | udcWriteFifo((u8 *)((u32)tx_buf+finished), | 1252 | udcWriteFifo((u8 *)((u32)tx_buf+finished), |
921 | tx_size - finished); | 1253 | tx_size - finished); |
922 | finished = tx_size; | 1254 | finished = tx_size; |
923 | usb_setb(USB_REG_CSR0, USB_CSR0_INPKTRDY); | 1255 | usb_setb(USB_REG_CSR0, USB_CSR0_INPKTRDY); |
924 | usb_setb(USB_REG_CSR0, USB_CSR0_DATAEND); //Set dataend! | 1256 | usb_setb(USB_REG_CSR0, USB_CSR0_DATAEND); //Set dataend! |
925 | ep0state=USB_EP0_IDLE; | 1257 | ep0state=USB_EP0_IDLE; |
926 | } else | 1258 | } else |
927 | { | 1259 | { |
928 | udcWriteFifo((u8 *)((u32)tx_buf+finished), 64); | 1260 | udcWriteFifo((u8 *)((u32)tx_buf+finished), 64); |
929 | usb_setb(USB_REG_CSR0, USB_CSR0_INPKTRDY); | 1261 | usb_setb(USB_REG_CSR0, USB_CSR0_INPKTRDY); |
930 | finished += 64; | 1262 | finished += 64; |
931 | } | 1263 | } |
932 | } | 1264 | } |
933 | return; | 1265 | return; |
934 | } | 1266 | } |
935 | 1267 | ||
936 | void EPIN_Handler(u8 EP) | 1268 | void EPIN_Handler(u8 EP) |
937 | { | 1269 | { |
938 | jz_writeb(USB_REG_INDEX, EP); | 1270 | jz_writeb(USB_REG_INDEX, EP); |
939 | fifo = fifoaddr[EP]; | 1271 | fifo = fifoaddr[EP]; |
940 | 1272 | ||
941 | if (Bulk_in_size-Bulk_in_finish==0) | 1273 | if (Bulk_in_size-Bulk_in_finish==0) |
942 | { | 1274 | { |
943 | Handshake_PKT(); | 1275 | Handshake_PKT(); |
944 | return; | 1276 | return; |
945 | } | 1277 | } |
946 | 1278 | ||
947 | if (Bulk_in_size - Bulk_in_finish <= fifosize[EP]) | 1279 | if (Bulk_in_size - Bulk_in_finish <= fifosize[EP]) |
948 | { | 1280 | { |
949 | udcWriteFifo((u8 *)((u32)Bulk_in_buf+Bulk_in_finish), | 1281 | udcWriteFifo((u8 *)((u32)Bulk_in_buf+Bulk_in_finish), |
950 | Bulk_in_size - Bulk_in_finish); | 1282 | Bulk_in_size - Bulk_in_finish); |
951 | usb_setw(USB_REG_INCSR, USB_INCSR_INPKTRDY); | 1283 | usb_setw(USB_REG_INCSR, USB_INCSR_INPKTRDY); |
952 | Bulk_in_finish = Bulk_in_size; | 1284 | Bulk_in_finish = Bulk_in_size; |
953 | } | 1285 | } |
954 | else | 1286 | else |
955 | { | 1287 | { |
956 | udcWriteFifo((u8 *)((u32)Bulk_in_buf+Bulk_in_finish), | 1288 | udcWriteFifo((u8 *)((u32)Bulk_in_buf+Bulk_in_finish), |
957 | fifosize[EP]); | 1289 | fifosize[EP]); |
958 | usb_setw(USB_REG_INCSR, USB_INCSR_INPKTRDY); | 1290 | usb_setw(USB_REG_INCSR, USB_INCSR_INPKTRDY); |
959 | Bulk_in_finish += fifosize[EP]; | 1291 | Bulk_in_finish += fifosize[EP]; |
960 | } | 1292 | } |
961 | } | 1293 | } |
962 | 1294 | ||
963 | void EPOUT_Handler(u8 EP) | 1295 | void EPOUT_Handler(u8 EP) |
964 | { | 1296 | { |
965 | u32 size; | 1297 | u32 size; |
966 | jz_writeb(USB_REG_INDEX, EP); | 1298 | jz_writeb(USB_REG_INDEX, EP); |
967 | size = jz_readw(USB_REG_OUTCOUNT); | 1299 | size = jz_readw(USB_REG_OUTCOUNT); |
968 | fifo = fifoaddr[EP]; | 1300 | fifo = fifoaddr[EP]; |
969 | udcReadFifo((u8 *)((u32)Bulk_out_buf+Bulk_out_size), size); | 1301 | udcReadFifo((u8 *)((u32)Bulk_out_buf+Bulk_out_size), size); |
970 | usb_clearb(USB_REG_OUTCSR,USB_OUTCSR_OUTPKTRDY); | 1302 | usb_clearb(USB_REG_OUTCSR,USB_OUTCSR_OUTPKTRDY); |
971 | Bulk_out_size += size; | 1303 | Bulk_out_size += size; |
972 | } | 1304 | } |
973 | 1305 | ||
974 | void UDC(void) | 1306 | void UDC(void) |
975 | { | 1307 | { |
976 | u8 IntrUSB; | 1308 | u8 IntrUSB; |
977 | u16 IntrIn; | 1309 | u16 IntrIn; |
978 | u16 IntrOut; | 1310 | u16 IntrOut; |
1311 | u16 IntrDMA; | ||
979 | /* Read interrupt registers */ | 1312 | /* Read interrupt registers */ |
980 | IntrUSB = jz_readb(USB_REG_INTRUSB); | 1313 | IntrUSB = jz_readb(USB_REG_INTRUSB); |
981 | IntrIn = jz_readw(USB_REG_INTRIN); | 1314 | IntrIn = jz_readw(USB_REG_INTRIN); |
982 | IntrOut = jz_readw(USB_REG_INTROUT); | 1315 | IntrOut = jz_readw(USB_REG_INTROUT); |
983 | 1316 | IntrDMA = jz_readb(USB_REG_INTR); | |
984 | if ( IntrUSB == 0 && IntrIn == 0 && IntrOut == 0) | 1317 | |
985 | return; | 1318 | if ( IntrUSB == 0 && IntrIn == 0 && IntrOut == 0) |
986 | 1319 | return; | |
987 | if (IntrIn & 2) | 1320 | |
988 | { | 1321 | if (IntrIn & 2) |
989 | EPIN_Handler(1); | 1322 | { |
990 | } | 1323 | EPIN_Handler(1); |
991 | if (IntrOut & 2) | 1324 | } |
992 | { | 1325 | if (IntrOut & 2) |
993 | EPOUT_Handler(1); | 1326 | { |
994 | } | 1327 | EPOUT_Handler(1); |
995 | if (IntrUSB & USB_INTR_RESET) | 1328 | } |
996 | { | 1329 | if (IntrUSB & USB_INTR_RESET) |
997 | udc_reset(); | 1330 | { |
998 | } | 1331 | udc_reset(); |
1332 | } | ||
999 | 1333 | ||
1000 | /* Check for endpoint 0 interrupt */ | 1334 | /* Check for endpoint 0 interrupt */ |
1001 | if (IntrIn & USB_INTR_EP0) | 1335 | if (IntrIn & USB_INTR_EP0) |
1002 | { | 1336 | { |
1003 | EP0_Handler(); | 1337 | EP0_Handler(); |
1004 | } | 1338 | } |
1005 | 1339 | ||
1006 | IntrIn = jz_readw(USB_REG_INTRIN); | 1340 | if (IntrDMA & 0x1) //channel 1 :OUT |
1007 | return; | 1341 | { |
1342 | if (tx_size > 0 && tx_size % fifosize[1] != 0) | ||
1343 | { | ||
1344 | jz_writeb(USB_REG_INDEX, 1); | ||
1345 | usb_clearb(USB_REG_INCSR, USB_INCSR_INPKTRDY); | ||
1346 | } | ||
1347 | Disable_DMA(); | ||
1348 | } | ||
1008 | } | 1349 | } |
1009 | 1350 | ||
1010 | void __udc_start(void) | 1351 | void __udc_start(void) |
1011 | { | 1352 | { |
1012 | udc_reset(); | 1353 | udc_reset(); |
1013 | 1354 | ||
1014 | ep0state = USB_EP0_IDLE; | 1355 | ep0state = USB_EP0_IDLE; |
1015 | Bulk_in_size = 0; | 1356 | Bulk_in_size = 0; |
1016 | Bulk_in_finish = 0; | 1357 | Bulk_in_finish = 0; |
1017 | Bulk_out_size = 0; | 1358 | Bulk_out_size = 0; |
1018 | udc_state = IDLE; | 1359 | udc_state = IDLE; |
1019 | tx_size = 0; | 1360 | tx_size = 0; |
1020 | rx_size = 0; | 1361 | rx_size = 0; |
1021 | finished = 0; | 1362 | finished = 0; |
1022 | 1363 | ||
1023 | if ((jz_readb(USB_REG_POWER)&0x10)==0) | 1364 | if ((jz_readb(USB_REG_POWER)&0x10)==0) |
1024 | { | 1365 | { |
1025 | USB_Version=USB_FS; | 1366 | USB_Version=USB_FS; |
1026 | fifosize[1]=64; | 1367 | fifosize[1]=64; |
1027 | EP0_init(1,64,1,64); | 1368 | EP0_init(1,64,1,64); |
1028 | } | 1369 | } |
1029 | else | 1370 | else |
1030 | { | 1371 | { |
1031 | USB_Version=USB_HS; | 1372 | USB_Version=USB_HS; |
1032 | fifosize[1]=512; | 1373 | fifosize[1]=512; |
1033 | EP0_init(1,512,1,512); | 1374 | EP0_init(1,512,1,512); |
1034 | } | 1375 | } |
1035 | 1376 | ||
1036 | USB_Version=USB_HS; | 1377 | USB_Version=USB_HS; |
1037 | system_enable_irq(IRQ_UDC); | 1378 | system_enable_irq(IRQ_UDC); |
1038 | } | 1379 | } |
1039 | 1380 | ||