summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/SOURCES1
-rw-r--r--firmware/export/config-ondavx747.h20
-rw-r--r--firmware/export/config-ondavx747p.h9
-rw-r--r--firmware/export/config-ondavx767.h9
-rw-r--r--firmware/export/jz4740.h72
-rw-r--r--firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c105
-rw-r--r--firmware/target/mips/ingenic_jz47xx/ata-sd-jz4740.c36
-rw-r--r--firmware/target/mips/ingenic_jz47xx/lcd-jz4740.c2
-rw-r--r--firmware/target/mips/ingenic_jz47xx/onda_vx747/ata-sd-target.h19
-rw-r--r--firmware/target/mips/ingenic_jz47xx/onda_vx747/usb-target.h14
-rw-r--r--firmware/target/mips/ingenic_jz47xx/system-jz4740.c101
-rw-r--r--firmware/target/mips/ingenic_jz47xx/usb-jz4740.c138
-rw-r--r--firmware/target/mips/mmu-mips.c125
-rw-r--r--firmware/target/mips/mmu-mips.h28
14 files changed, 449 insertions, 230 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 3f558566f8..7169a669e8 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -408,6 +408,7 @@ common/memmove.c
408common/memset.c 408common/memset.c
409common/memset16.c 409common/memset16.c
410common/strlen.c 410common/strlen.c
411target/mips/mmu-mips.c
411#if CONFIG_CPU==JZ4732 412#if CONFIG_CPU==JZ4732
412target/mips/ingenic_jz47xx/crt0.S 413target/mips/ingenic_jz47xx/crt0.S
413#endif /* CONFIG_CPU == JZ4732 */ 414#endif /* CONFIG_CPU == JZ4732 */
diff --git a/firmware/export/config-ondavx747.h b/firmware/export/config-ondavx747.h
index 2fe0564e71..d4badf89cd 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_RAMDISK /* Multivolume currently handled at firmware/target/ level */ 40#define CONFIG_STORAGE STORAGE_NAND /* Multivolume currently handled at firmware/target/ level */
41 41
42#define CONFIG_NAND NAND_CC 42#define CONFIG_NAND NAND_CC
43 43
@@ -144,7 +144,7 @@
144#define __BACKLIGHT_INIT 144#define __BACKLIGHT_INIT
145 145
146/* Offset ( in the firmware file's header ) to the file CRC */ 146/* Offset ( in the firmware file's header ) to the file CRC */
147#define FIRMWARE_OFFSET_FILE_CRC 0 147#define FIRMWARE_OFFSET_FILE_CRC 0
148 148
149/* Offset ( in the firmware file's header ) to the real data */ 149/* Offset ( in the firmware file's header ) to the real data */
150#define FIRMWARE_OFFSET_FILE_DATA 8 150#define FIRMWARE_OFFSET_FILE_DATA 8
@@ -153,12 +153,18 @@
153/* #define HAVE_ADJUSTABLE_CPU_FREQ */ 153/* #define HAVE_ADJUSTABLE_CPU_FREQ */
154 154
155#define BOOTFILE_EXT "vx747" 155#define BOOTFILE_EXT "vx747"
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_JZ4740 159#define CONFIG_USBOTG USBOTG_JZ4740
160#define HAVE_USBSTACK 160#define HAVE_USBSTACK
161#define USB_VENDOR_ID 0x07C4 161#define USE_ROCKBOX_USB
162#define USB_PRODUCT_ID 0xA4A5 162#define USB_VENDOR_ID 0x07C4
163#define USB_PRODUCT_ID 0xA4A5
164#define USB_NUM_ENDPOINTS 3
165/* This needs to be 2048 byte aligned, but USB_QHARRAY_ATTR should take care
166 * of that */
167#define USB_QHARRAY_ATTR __attribute__((section(".qharray"),nocommon,aligned(4)))
168#define USB_DEVBSS_ATTR IBSS_ATTR
163 169
164#endif 170#endif
diff --git a/firmware/export/config-ondavx747p.h b/firmware/export/config-ondavx747p.h
index 5c4d3e7aea..2cd06d3323 100644
--- a/firmware/export/config-ondavx747p.h
+++ b/firmware/export/config-ondavx747p.h
@@ -158,7 +158,12 @@
158 158
159#define CONFIG_USBOTG USBOTG_JZ4740 159#define CONFIG_USBOTG USBOTG_JZ4740
160#define HAVE_USBSTACK 160#define HAVE_USBSTACK
161#define USB_VENDOR_ID 0x041e 161#define USB_VENDOR_ID 0x07C4
162#define USB_PRODUCT_ID 0x4133 162#define USB_PRODUCT_ID 0xA4A5
163#define USB_NUM_ENDPOINTS 3
164/* This needs to be 2048 byte aligned, but USB_QHARRAY_ATTR should take care
165 * of that */
166#define USB_QHARRAY_ATTR __attribute__((section(".qharray"),nocommon,aligned(4)))
167#define USB_DEVBSS_ATTR IBSS_ATTR
163 168
164#endif 169#endif
diff --git a/firmware/export/config-ondavx767.h b/firmware/export/config-ondavx767.h
index 7216ef0d35..cb44de9e6e 100644
--- a/firmware/export/config-ondavx767.h
+++ b/firmware/export/config-ondavx767.h
@@ -156,7 +156,12 @@
156 156
157#define CONFIG_USBOTG USBOTG_JZ4740 157#define CONFIG_USBOTG USBOTG_JZ4740
158#define HAVE_USBSTACK 158#define HAVE_USBSTACK
159#define USB_VENDOR_ID 0x041e 159#define USB_VENDOR_ID 0x07C4
160#define USB_PRODUCT_ID 0x4133 160#define USB_PRODUCT_ID 0xA4A5
161#define USB_NUM_ENDPOINTS 3
162/* This needs to be 2048 byte aligned, but USB_QHARRAY_ATTR should take care
163 * of that */
164#define USB_QHARRAY_ATTR __attribute__((section(".qharray"),nocommon,aligned(4)))
165#define USB_DEVBSS_ATTR IBSS_ATTR
161 166
162#endif 167#endif
diff --git a/firmware/export/jz4740.h b/firmware/export/jz4740.h
index 409d1d5a6a..aa31a229f9 100644
--- a/firmware/export/jz4740.h
+++ b/firmware/export/jz4740.h
@@ -2105,57 +2105,57 @@
2105 *************************************************************************/ 2105 *************************************************************************/
2106 2106
2107#define SLCD_CFG (SLCD_BASE + 0xA0) /* SLCD Configure Register */ 2107#define SLCD_CFG (SLCD_BASE + 0xA0) /* SLCD Configure Register */
2108#define SLCD_CTRL (SLCD_BASE + 0xA4) /* SLCD Control Register */ 2108#define SLCD_CTRL (SLCD_BASE + 0xA4) /* SLCD Control Register */
2109#define SLCD_STATE (SLCD_BASE + 0xA8) /* SLCD Status Register */ 2109#define SLCD_STATE (SLCD_BASE + 0xA8) /* SLCD Status Register */
2110#define SLCD_DATA (SLCD_BASE + 0xAC) /* SLCD Data Register */ 2110#define SLCD_DATA (SLCD_BASE + 0xAC) /* SLCD Data Register */
2111#define SLCD_FIFO (SLCD_BASE + 0xB0) /* SLCD FIFO Register */ 2111#define SLCD_FIFO (SLCD_BASE + 0xB0) /* SLCD FIFO Register */
2112 2112
2113#define REG_SLCD_CFG REG32(SLCD_CFG) 2113#define REG_SLCD_CFG REG32(SLCD_CFG)
2114#define REG_SLCD_CTRL REG8(SLCD_CTRL) 2114#define REG_SLCD_CTRL REG8(SLCD_CTRL)
2115#define REG_SLCD_STATE REG8(SLCD_STATE) 2115#define REG_SLCD_STATE REG8(SLCD_STATE)
2116#define REG_SLCD_DATA REG32(SLCD_DATA) 2116#define REG_SLCD_DATA REG32(SLCD_DATA)
2117#define REG_SLCD_FIFO REG32(SLCD_FIFO) 2117#define REG_SLCD_FIFO REG32(SLCD_FIFO)
2118 2118
2119/* SLCD Configure Register */ 2119/* SLCD Configure Register */
2120#define SLCD_CFG_BURST_BIT 14 2120#define SLCD_CFG_BURST_BIT 14
2121#define SLCD_CFG_BURST_MASK (0x3 << SLCD_CFG_BURST_BIT) 2121#define SLCD_CFG_BURST_MASK (0x3 << SLCD_CFG_BURST_BIT)
2122 #define SLCD_CFG_BURST_4_WORD (0 << SLCD_CFG_BURST_BIT) 2122 #define SLCD_CFG_BURST_4_WORD (0 << SLCD_CFG_BURST_BIT)
2123 #define SLCD_CFG_BURST_8_WORD (1 << SLCD_CFG_BURST_BIT) 2123 #define SLCD_CFG_BURST_8_WORD (1 << SLCD_CFG_BURST_BIT)
2124#define SLCD_CFG_DWIDTH_BIT 10 2124#define SLCD_CFG_DWIDTH_BIT 10
2125#define SLCD_CFG_DWIDTH_MASK (0x7 << SLCD_CFG_DWIDTH_BIT) 2125#define SLCD_CFG_DWIDTH_MASK (0x7 << SLCD_CFG_DWIDTH_BIT)
2126 #define SLCD_CFG_DWIDTH_18 (0 << SLCD_CFG_DWIDTH_BIT) 2126 #define SLCD_CFG_DWIDTH_18 (0 << SLCD_CFG_DWIDTH_BIT)
2127 #define SLCD_CFG_DWIDTH_16 (1 << SLCD_CFG_DWIDTH_BIT) 2127 #define SLCD_CFG_DWIDTH_16 (1 << SLCD_CFG_DWIDTH_BIT)
2128 #define SLCD_CFG_DWIDTH_8_x3 (2 << SLCD_CFG_DWIDTH_BIT) 2128 #define SLCD_CFG_DWIDTH_8_x3 (2 << SLCD_CFG_DWIDTH_BIT)
2129 #define SLCD_CFG_DWIDTH_8_x2 (3 << SLCD_CFG_DWIDTH_BIT) 2129 #define SLCD_CFG_DWIDTH_8_x2 (3 << SLCD_CFG_DWIDTH_BIT)
2130 #define SLCD_CFG_DWIDTH_8_x1 (4 << SLCD_CFG_DWIDTH_BIT) 2130 #define SLCD_CFG_DWIDTH_8_x1 (4 << SLCD_CFG_DWIDTH_BIT)
2131 #define SLCD_CFG_DWIDTH_9_x2 (7 << SLCD_CFG_DWIDTH_BIT) 2131 #define SLCD_CFG_DWIDTH_9_x2 (7 << SLCD_CFG_DWIDTH_BIT)
2132#define SLCD_CFG_CWIDTH_BIT 8 2132#define SLCD_CFG_CWIDTH_BIT 8
2133#define SLCD_CFG_CWIDTH_MASK (0x3 << SLCD_CFG_CWIDTH_BIT) 2133#define SLCD_CFG_CWIDTH_MASK (0x3 << SLCD_CFG_CWIDTH_BIT)
2134 #define SLCD_CFG_CWIDTH_16BIT (0 << SLCD_CFG_CWIDTH_BIT) 2134 #define SLCD_CFG_CWIDTH_16BIT (0 << SLCD_CFG_CWIDTH_BIT)
2135 #define SLCD_CFG_CWIDTH_8BIT (1 << SLCD_CFG_CWIDTH_BIT) 2135 #define SLCD_CFG_CWIDTH_8BIT (1 << SLCD_CFG_CWIDTH_BIT)
2136 #define SLCD_CFG_CWIDTH_18BIT (2 << SLCD_CFG_CWIDTH_BIT) 2136 #define SLCD_CFG_CWIDTH_18BIT (2 << SLCD_CFG_CWIDTH_BIT)
2137#define SLCD_CFG_CS_ACTIVE_LOW (0 << 4) 2137#define SLCD_CFG_CS_ACTIVE_LOW (0 << 4)
2138#define SLCD_CFG_CS_ACTIVE_HIGH (1 << 4) 2138#define SLCD_CFG_CS_ACTIVE_HIGH (1 << 4)
2139#define SLCD_CFG_RS_CMD_LOW (0 << 3) 2139#define SLCD_CFG_RS_CMD_LOW (0 << 3)
2140#define SLCD_CFG_RS_CMD_HIGH (1 << 3) 2140#define SLCD_CFG_RS_CMD_HIGH (1 << 3)
2141#define SLCD_CFG_CLK_ACTIVE_FALLING (0 << 1) 2141#define SLCD_CFG_CLK_ACTIVE_FALLING (0 << 1)
2142#define SLCD_CFG_CLK_ACTIVE_RISING (1 << 1) 2142#define SLCD_CFG_CLK_ACTIVE_RISING (1 << 1)
2143#define SLCD_CFG_TYPE_PARALLEL (0 << 0) 2143#define SLCD_CFG_TYPE_PARALLEL (0 << 0)
2144#define SLCD_CFG_TYPE_SERIAL (1 << 0) 2144#define SLCD_CFG_TYPE_SERIAL (1 << 0)
2145 2145
2146/* SLCD Control Register */ 2146/* SLCD Control Register */
2147#define SLCD_CTRL_DMA_EN (1 << 0) 2147#define SLCD_CTRL_DMA_EN (1 << 0)
2148 2148
2149/* SLCD Status Register */ 2149/* SLCD Status Register */
2150#define SLCD_STATE_BUSY (1 << 0) 2150#define SLCD_STATE_BUSY (1 << 0)
2151 2151
2152/* SLCD Data Register */ 2152/* SLCD Data Register */
2153#define SLCD_DATA_RS_DATA (0 << 31) 2153#define SLCD_DATA_RS_DATA (0 << 31)
2154#define SLCD_DATA_RS_COMMAND (1 << 31) 2154#define SLCD_DATA_RS_COMMAND (1 << 31)
2155 2155
2156/* SLCD FIFO Register */ 2156/* SLCD FIFO Register */
2157#define SLCD_FIFO_RS_DATA (0 << 31) 2157#define SLCD_FIFO_RS_DATA (0 << 31)
2158#define SLCD_FIFO_RS_COMMAND (1 << 31) 2158#define SLCD_FIFO_RS_COMMAND (1 << 31)
2159 2159
2160 2160
2161/************************************************************************* 2161/*************************************************************************
diff --git a/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c b/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c
index a4b4a86a55..4a36b069f9 100644
--- a/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c
+++ b/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c
@@ -22,11 +22,14 @@
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 "ata-nand-target.h" /* TODO */
26#include "nand_id.h" 26#include "nand_id.h"
27#include "system.h" 27#include "system.h"
28#include "panic.h" 28#include "panic.h"
29#include "kernel.h" 29#include "kernel.h"
30#include "storage.h"
31#include "buffer.h"
32#include "string.h"
30 33
31/* 34/*
32 * Standard NAND flash commands 35 * Standard NAND flash commands
@@ -65,8 +68,8 @@ struct nand_param
65 unsigned int bus_width; /* data bus width: 8-bit/16-bit */ 68 unsigned int bus_width; /* data bus width: 8-bit/16-bit */
66 unsigned int row_cycle; /* row address cycles: 2/3 */ 69 unsigned int row_cycle; /* row address cycles: 2/3 */
67 unsigned int page_size; /* page size in bytes: 512/2048 */ 70 unsigned int page_size; /* page size in bytes: 512/2048 */
68 unsigned int oob_size; /* oob size in bytes: 16/64 */ 71 unsigned int oob_size; /* oob size in bytes: 16/64 */
69 unsigned int page_per_block; /* pages per block: 32/64/128 */ 72 unsigned int page_per_block; /* pages per block: 32/64/128 */
70}; 73};
71 74
72/* 75/*
@@ -106,6 +109,8 @@ struct nand_param
106static struct nand_info* chip_info = NULL; 109static struct nand_info* chip_info = NULL;
107static struct nand_param internal_param; 110static struct nand_param internal_param;
108static struct mutex nand_mtx; 111static struct mutex nand_mtx;
112static struct wakeup nand_wkup;
113static unsigned char temp_page[4096]; /* Max page size */
109 114
110static inline void jz_nand_wait_ready(void) 115static inline void jz_nand_wait_ready(void)
111{ 116{
@@ -141,7 +146,7 @@ static void jz_nand_write_dma(void *source, unsigned int len, int bw)
141 146
142 dma_enable(); 147 dma_enable();
143 148
144 REG_DMAC_DCCSR(DMA_NAND_CHANNEL) = 0; 149 REG_DMAC_DCCSR(DMA_NAND_CHANNEL) = DMAC_DCCSR_NDES;
145 REG_DMAC_DSAR(DMA_NAND_CHANNEL) = PHYSADDR((unsigned long)source); 150 REG_DMAC_DSAR(DMA_NAND_CHANNEL) = PHYSADDR((unsigned long)source);
146 REG_DMAC_DTAR(DMA_NAND_CHANNEL) = PHYSADDR((unsigned long)NAND_DATAPORT); 151 REG_DMAC_DTAR(DMA_NAND_CHANNEL) = PHYSADDR((unsigned long)NAND_DATAPORT);
147 REG_DMAC_DTCR(DMA_NAND_CHANNEL) = len / 16; 152 REG_DMAC_DTCR(DMA_NAND_CHANNEL) = len / 16;
@@ -149,9 +154,14 @@ static void jz_nand_write_dma(void *source, unsigned int len, int bw)
149 REG_DMAC_DCMD(DMA_NAND_CHANNEL) = (DMAC_DCMD_SAI| DMAC_DCMD_DAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DS_16BYTE | 154 REG_DMAC_DCMD(DMA_NAND_CHANNEL) = (DMAC_DCMD_SAI| DMAC_DCMD_DAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DS_16BYTE |
150 (bw == 8 ? DMAC_DCMD_DWDH_8 : DMAC_DCMD_DWDH_16)); 155 (bw == 8 ? DMAC_DCMD_DWDH_8 : DMAC_DCMD_DWDH_16));
151 156
152 REG_DMAC_DCCSR(DMA_NAND_CHANNEL) = (DMAC_DCCSR_EN | DMAC_DCCSR_NDES); 157 REG_DMAC_DCCSR(DMA_NAND_CHANNEL) |= DMAC_DCCSR_EN; /* Enable DMA channel */
158#if 1
153 while( REG_DMAC_DTCR(DMA_NAND_CHANNEL) ) 159 while( REG_DMAC_DTCR(DMA_NAND_CHANNEL) )
154 yield(); 160 yield();
161#else
162 REG_DMAC_DCMD(DMA_NAND_CHANNEL) |= DMAC_DCMD_TIE; /* Enable DMA interrupt */
163 wakeup_wait(&nand_wkup, TIMEOUT_BLOCK);
164#endif
155 165
156 dma_disable(); 166 dma_disable();
157 167
@@ -167,22 +177,44 @@ static void jz_nand_read_dma(void *target, unsigned int len, int bw)
167 177
168 dma_enable(); 178 dma_enable();
169 179
170 REG_DMAC_DCCSR(DMA_NAND_CHANNEL) = 0; 180 REG_DMAC_DCCSR(DMA_NAND_CHANNEL) = DMAC_DCCSR_NDES;
171 REG_DMAC_DSAR(DMA_NAND_CHANNEL) = PHYSADDR((unsigned long)NAND_DATAPORT); 181 REG_DMAC_DSAR(DMA_NAND_CHANNEL) = PHYSADDR((unsigned long)NAND_DATAPORT);
172 REG_DMAC_DTAR(DMA_NAND_CHANNEL) = PHYSADDR((unsigned long)target); 182 REG_DMAC_DTAR(DMA_NAND_CHANNEL) = PHYSADDR((unsigned long)target);
173 REG_DMAC_DTCR(DMA_NAND_CHANNEL) = len / 4; 183 REG_DMAC_DTCR(DMA_NAND_CHANNEL) = len / 4;
174 REG_DMAC_DRSR(DMA_NAND_CHANNEL) = DMAC_DRSR_RS_AUTO; 184 REG_DMAC_DRSR(DMA_NAND_CHANNEL) = DMAC_DRSR_RS_AUTO;
175 REG_DMAC_DCMD(DMA_NAND_CHANNEL) = (DMAC_DCMD_SAI| DMAC_DCMD_DAI | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BIT | 185 REG_DMAC_DCMD(DMA_NAND_CHANNEL) = (DMAC_DCMD_SAI| DMAC_DCMD_DAI | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BIT |
176 (bw == 8 ? DMAC_DCMD_SWDH_8 : DMAC_DCMD_SWDH_16)); 186 (bw == 8 ? DMAC_DCMD_SWDH_8 : DMAC_DCMD_SWDH_16));
177 REG_DMAC_DCCSR(DMA_NAND_CHANNEL) = (DMAC_DCCSR_EN | DMAC_DCCSR_NDES); 187 REG_DMAC_DCCSR(DMA_NAND_CHANNEL) |= DMAC_DCCSR_EN; /* Enable DMA channel */
188#if 1
178 while( REG_DMAC_DTCR(DMA_NAND_CHANNEL) ) 189 while( REG_DMAC_DTCR(DMA_NAND_CHANNEL) )
179 yield(); 190 yield();
191#else
192 REG_DMAC_DCMD(DMA_NAND_CHANNEL) |= DMAC_DCMD_TIE; /* Enable DMA interrupt */
193 wakeup_wait(&nand_wkup, TIMEOUT_BLOCK);
194#endif
180 195
181 dma_disable(); 196 dma_disable();
182 197
183 mutex_unlock(&nand_mtx); 198 mutex_unlock(&nand_mtx);
184} 199}
185 200
201void DMA_CALLBACK(DMA_NAND_CHANNEL)(void)
202{
203 if (REG_DMAC_DCCSR(DMA_NAND_CHANNEL) & DMAC_DCCSR_HLT)
204 REG_DMAC_DCCSR(DMA_NAND_CHANNEL) &= ~DMAC_DCCSR_HLT;
205
206 if (REG_DMAC_DCCSR(DMA_NAND_CHANNEL) & DMAC_DCCSR_AR)
207 REG_DMAC_DCCSR(DMA_NAND_CHANNEL) &= ~DMAC_DCCSR_AR;
208
209 if (REG_DMAC_DCCSR(DMA_NAND_CHANNEL) & DMAC_DCCSR_CT)
210 REG_DMAC_DCCSR(DMA_NAND_CHANNEL) &= ~DMAC_DCCSR_CT;
211
212 if (REG_DMAC_DCCSR(DMA_NAND_CHANNEL) & DMAC_DCCSR_TT)
213 REG_DMAC_DCCSR(DMA_NAND_CHANNEL) &= ~DMAC_DCCSR_TT;
214
215 wakeup_signal(&nand_wkup);
216}
217
186static inline void jz_nand_read_buf(void *buf, int count, int bw) 218static inline void jz_nand_read_buf(void *buf, int count, int bw)
187{ 219{
188 if (bw == 8) 220 if (bw == 8)
@@ -368,6 +400,7 @@ static int jz_nand_read_page(int block, int page, unsigned char *dst)
368 { 400 {
369 /* Uncorrectable error occurred */ 401 /* Uncorrectable error occurred */
370 panicf("Uncorrectable ECC error at NAND page 0x%x block 0x%x", page, block); 402 panicf("Uncorrectable ECC error at NAND page 0x%x block 0x%x", page, block);
403 return -1;
371 } 404 }
372 else 405 else
373 { 406 {
@@ -451,16 +484,9 @@ static int jz_nand_init(void)
451 internal_param.oob_size = chip_info->page_size/32; 484 internal_param.oob_size = chip_info->page_size/32;
452 internal_param.page_per_block = chip_info->pages_per_block; 485 internal_param.page_per_block = chip_info->pages_per_block;
453 486
454 mutex_init(&nand_mtx);
455
456 return 0; 487 return 0;
457} 488}
458 489
459void jz_nand_read(int block, int page, unsigned char *buf)
460{
461 jz_nand_read_page(block, page, buf);
462}
463
464static bool inited = false; 490static bool inited = false;
465int nand_init(void) 491int nand_init(void)
466{ 492{
@@ -469,23 +495,41 @@ int nand_init(void)
469 if(!inited) 495 if(!inited)
470 { 496 {
471 res = jz_nand_init(); 497 res = jz_nand_init();
498 mutex_init(&nand_mtx);
499 wakeup_init(&nand_wkup);
500
472 inited = true; 501 inited = true;
473 } 502 }
474 503
475 return res; 504 return res;
476} 505}
477 506
478/* TODO */ 507int nand_read_sectors(IF_MV2(int drive,) unsigned long start, int count, void* buf)
479int nand_read_sectors(unsigned long start, int count, void* buf)
480{ 508{
481 (void)start; 509 int i, ret = 0;
482 (void)count; 510
483 (void)buf; 511 start *= 512;
484 return -1; 512 count *= 512;
513
514 if(count <= chip_info->page_size)
515 {
516 ret = jz_nand_read_page(start % (chip_info->page_size * chip_info->pages_per_block), start % chip_info->page_size, temp_page);
517 memcpy(buf, temp_page, count);
518 return ret;
519 }
520 else
521 {
522 for(i=0; i<count && ret == 0; i+=chip_info->page_size)
523 {
524 ret = jz_nand_read_page((start+i) % (chip_info->page_size * chip_info->pages_per_block), (start+i) % chip_info->page_size, temp_page);
525 memcpy(buf+i, temp_page, (count-i < chip_info->page_size ? count-i : chip_info->page_size));
526 }
527 return ret;
528 }
485} 529}
486 530
487/* TODO */ 531/* TODO */
488int nand_write_sectors(unsigned long start, int count, const void* buf) 532int nand_write_sectors(IF_MV2(int drive,) unsigned long start, int count, const void* buf)
489{ 533{
490 (void)start; 534 (void)start;
491 (void)count; 535 (void)count;
@@ -526,3 +570,20 @@ void nand_enable(bool on)
526 /* null - flash controller is enabled/disabled as needed. */ 570 /* null - flash controller is enabled/disabled as needed. */
527 (void)on; 571 (void)on;
528} 572}
573
574#ifdef STORAGE_GET_INFO
575void nand_get_info(IF_MV2(int drive,) struct storage_info *info)
576{
577 (void)drive;
578 /* firmware version */
579 info->revision="0.00";
580
581 info->vendor="Rockbox";
582 info->product="NAND Storage";
583
584 /* blocks count */
585 /* TODO: proper amount of sectors! */
586 info->num_sectors = (chip_info->page_size / 512) * chip_info->pages_per_block * chip_info->blocks_per_bank;
587 info->sector_size = 512;
588}
589#endif
diff --git a/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4740.c b/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4740.c
index 22e274b4d1..3bb9a27007 100644
--- a/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4740.c
+++ b/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4740.c
@@ -23,31 +23,20 @@
23#include "jz4740.h" 23#include "jz4740.h"
24#include "ata.h" 24#include "ata.h"
25#include "ata-sd-target.h" 25#include "ata-sd-target.h"
26#include "logf.h"
26#include "sd.h" 27#include "sd.h"
27#include "system.h" 28#include "system.h"
28#include "kernel.h" 29#include "kernel.h"
29#include "panic.h" 30#include "panic.h"
30#include "debug.h" 31#include "debug.h"
32#include "storage.h"
31 33
32static struct wakeup sd_wakeup; 34static struct wakeup sd_wakeup;
33 35
34//#define MMC_DMA_ENABLE 36//#define MMC_DMA_ENABLE
35#define MMC_DMA_INTERRUPT 0 37#define MMC_DMA_INTERRUPT 0
36 38
37//#define DEBUG(x...) DEBUGF(x); 39#define DEBUG(x...) logf(x);
38#define DEBUG(x...) printf(x);
39
40#ifdef MMC_POWER_PIN
41#define MMC_POWER_OFF() \
42do { \
43 __gpio_set_pin(MMC_POWER_PIN); \
44} while (0)
45
46#define MMC_POWER_ON() \
47do { \
48 __gpio_clear_pin(MMC_POWER_PIN); \
49} while (0)
50#endif
51 40
52#ifdef MMC_CD_PIN 41#ifdef MMC_CD_PIN
53#define MMC_INSERT_STATUS() __gpio_get_pin(MMC_CD_PIN) 42#define MMC_INSERT_STATUS() __gpio_get_pin(MMC_CD_PIN)
@@ -1088,7 +1077,7 @@ static void mmc_send_cmd(struct mmc_request *request, int cmd, unsigned int arg,
1088 request->block_len = block_len; 1077 request->block_len = block_len;
1089 request->buffer = buffer; 1078 request->buffer = buffer;
1090 request->cnt = nob * block_len; 1079 request->cnt = nob * block_len;
1091 printf("mmc_send_cmd: command = %d",cmd); 1080 logf("mmc_send_cmd: command = %d",cmd);
1092 jz_mmc_exec_cmd(request); 1081 jz_mmc_exec_cmd(request);
1093} 1082}
1094 1083
@@ -1154,3 +1143,20 @@ int _sd_write_sectors(unsigned long start, int count, const void* buf)
1154 (void)buf; 1143 (void)buf;
1155 return -1; 1144 return -1;
1156} 1145}
1146
1147#ifdef STORAGE_GET_INFO
1148void sd_get_info(IF_MV2(int drive,) struct storage_info *info)
1149{
1150 (void)drive;
1151 /* firmware version */
1152 info->revision="0.00";
1153
1154 info->vendor="Rockbox";
1155 info->product="SD Storage";
1156
1157 /* blocks count */
1158 /* TODO: proper amount of sectors! */
1159 info->num_sectors = 0;
1160 info->sector_size = 512;
1161}
1162#endif
diff --git a/firmware/target/mips/ingenic_jz47xx/lcd-jz4740.c b/firmware/target/mips/ingenic_jz47xx/lcd-jz4740.c
index 8112c21147..cc2c84c6b4 100644
--- a/firmware/target/mips/ingenic_jz47xx/lcd-jz4740.c
+++ b/firmware/target/mips/ingenic_jz47xx/lcd-jz4740.c
@@ -103,7 +103,7 @@ void lcd_update_rect(int x, int y, int width, int height)
103 REG_DMAC_DCCSR(DMA_LCD_CHANNEL) |= DMAC_DCCSR_EN; /* Enable DMA channel */ 103 REG_DMAC_DCCSR(DMA_LCD_CHANNEL) |= DMAC_DCCSR_EN; /* Enable DMA channel */
104 REG_DMAC_DCMD(DMA_LCD_CHANNEL) |= DMAC_DCMD_TIE; /* Enable DMA interrupt */ 104 REG_DMAC_DCMD(DMA_LCD_CHANNEL) |= DMAC_DCMD_TIE; /* Enable DMA interrupt */
105 105
106 wakeup_wait(&lcd_wkup, TIMEOUT_BLOCK); 106 wakeup_wait(&lcd_wkup, TIMEOUT_BLOCK); /* Sleeping in lcd_update() should be safe */
107 107
108 REG_DMAC_DCCSR(DMA_LCD_CHANNEL) &= ~DMAC_DCCSR_EN; /* Disable DMA channel */ 108 REG_DMAC_DCCSR(DMA_LCD_CHANNEL) &= ~DMAC_DCCSR_EN; /* Disable DMA channel */
109 109
diff --git a/firmware/target/mips/ingenic_jz47xx/onda_vx747/ata-sd-target.h b/firmware/target/mips/ingenic_jz47xx/onda_vx747/ata-sd-target.h
index cc6bd8a773..ba324c1dcb 100644
--- a/firmware/target/mips/ingenic_jz47xx/onda_vx747/ata-sd-target.h
+++ b/firmware/target/mips/ingenic_jz47xx/onda_vx747/ata-sd-target.h
@@ -39,13 +39,28 @@ int _sd_write_sectors(unsigned long start, int count, const void* buf);
39int _sd_init(void); 39int _sd_init(void);
40 40
41#define MMC_CD_PIN (29 + 1 * 32) /* Pin to check card insertion */ 41#define MMC_CD_PIN (29 + 1 * 32) /* Pin to check card insertion */
42//#define MMC_POWER_PIN (30 + 1 * 32) /* Pin to enable/disable card power */ 42//#define MMC_POWER_PIN (22 + 2 * 32) /* Pin to enable/disable card power */
43//#define MMC_PW_PIN (14 + 3 * 32) /* Pin to check protect card */ 43
44#ifdef MMC_POWER_PIN
45#define MMC_POWER_OFF() \
46do { \
47 __gpio_clear_pin(MMC_POWER_PIN); \
48} while (0)
49
50#define MMC_POWER_ON() \
51do { \
52 __gpio_set_pin(MMC_POWER_PIN); \
53} while (0)
54#endif
44 55
45static inline void mmc_init_gpio(void) 56static inline void mmc_init_gpio(void)
46{ 57{
47 __gpio_as_msc(); 58 __gpio_as_msc();
48 __gpio_as_input(MMC_CD_PIN); 59 __gpio_as_input(MMC_CD_PIN);
60#ifdef MMC_POWER_PIN
61 __gpio_as_func0(MMC_POWER_PIN);
62 __gpio_as_output(MMC_POWER_PIN);
63#endif
49 __gpio_enable_pull(32*3+29); 64 __gpio_enable_pull(32*3+29);
50 __gpio_enable_pull(32*3+10); 65 __gpio_enable_pull(32*3+10);
51 __gpio_enable_pull(32*3+11); 66 __gpio_enable_pull(32*3+11);
diff --git a/firmware/target/mips/ingenic_jz47xx/onda_vx747/usb-target.h b/firmware/target/mips/ingenic_jz47xx/onda_vx747/usb-target.h
index 09b563fd14..fbb14b7ac4 100644
--- a/firmware/target/mips/ingenic_jz47xx/onda_vx747/usb-target.h
+++ b/firmware/target/mips/ingenic_jz47xx/onda_vx747/usb-target.h
@@ -26,17 +26,19 @@
26 26
27#define GPIO_UDC_DETE (32 * 3 + 28) 27#define GPIO_UDC_DETE (32 * 3 + 28)
28#define IRQ_GPIO_UDC_DETE (IRQ_GPIO_0 + GPIO_UDC_DETE) 28#define IRQ_GPIO_UDC_DETE (IRQ_GPIO_0 + GPIO_UDC_DETE)
29#define USB_GPIO_IRQ GPIO124
29 30
30#define USB_INIT_GPIO() \ 31#define USB_INIT_GPIO() \
31{ \ 32{ \
32 REG_GPIO_PXFUNS(3) = 0x10000000; \ 33 REG_GPIO_PXPES(3) = 0x10000000; \
33 REG_GPIO_PXSELS(3) = 0x10000000; \ 34 __gpio_as_irq_rise_edge(GPIO_UDC_DETE); \
34 REG_GPIO_PXPES(3) = 0x10000000; \
35 __gpio_as_input(GPIO_UDC_DETE); \
36} 35}
37 36
38#define USB_DRV_CONNECTED() (__gpio_get_pin(GPIO_UDC_DETE) == 1) 37#define USB_DRV_CONNECTED() (__gpio_get_pin(GPIO_UDC_DETE) == 1)
39 38
39/* Connect by events, not by tick polling */
40#define USB_STATUS_BY_EVENT
41
40int usb_detect(void); 42int usb_detect(void);
41void usb_init_device(void); 43void usb_init_device(void);
42bool usb_drv_connected(void); 44bool usb_drv_connected(void);
diff --git a/firmware/target/mips/ingenic_jz47xx/system-jz4740.c b/firmware/target/mips/ingenic_jz47xx/system-jz4740.c
index 033b42214b..9c7f83530f 100644
--- a/firmware/target/mips/ingenic_jz47xx/system-jz4740.c
+++ b/firmware/target/mips/ingenic_jz47xx/system-jz4740.c
@@ -23,6 +23,7 @@
23#include "jz4740.h" 23#include "jz4740.h"
24#include "mips.h" 24#include "mips.h"
25#include "mipsregs.h" 25#include "mipsregs.h"
26#include "mmu-mips.h"
26#include "panic.h" 27#include "panic.h"
27#include "system.h" 28#include "system.h"
28#include "string.h" 29#include "string.h"
@@ -524,106 +525,6 @@ void dma_cache_wback_inv(unsigned long addr, unsigned long size)
524 } 525 }
525} 526}
526 527
527#define BARRIER \
528 __asm__ __volatile__( \
529 " .set noreorder \n" \
530 " nop \n" \
531 " nop \n" \
532 " nop \n" \
533 " nop \n" \
534 " nop \n" \
535 " nop \n" \
536 " .set reorder \n");
537
538#define DEFAULT_PAGE_SHIFT PL_4K
539#define DEFAULT_PAGE_MASK PM_4K
540#define UNIQUE_ENTRYHI(idx, ps) (A_K0BASE + ((idx) << (ps + 1)))
541#define ASID_MASK M_EntryHiASID
542#define VPN2_SHIFT S_EntryHiVPN2
543#define PFN_SHIFT S_EntryLoPFN
544#define PFN_MASK 0xffffff
545static void local_flush_tlb_all(void)
546{
547 unsigned long old_ctx;
548 int entry;
549 unsigned int old_irq = disable_irq_save();
550
551 /* Save old context and create impossible VPN2 value */
552 old_ctx = read_c0_entryhi();
553 write_c0_entrylo0(0);
554 write_c0_entrylo1(0);
555 BARRIER;
556
557 /* Blast 'em all away. */
558 for(entry = 0; entry < 32; entry++)
559 {
560 /* Make sure all entries differ. */
561 write_c0_entryhi(UNIQUE_ENTRYHI(entry, DEFAULT_PAGE_SHIFT));
562 write_c0_index(entry);
563 BARRIER;
564 tlb_write_indexed();
565 }
566 BARRIER;
567 write_c0_entryhi(old_ctx);
568
569 restore_irq(old_irq);
570}
571
572static void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
573 unsigned long entryhi, unsigned long pagemask)
574{
575 unsigned long wired;
576 unsigned long old_pagemask;
577 unsigned long old_ctx;
578 unsigned int old_irq = disable_irq_save();
579
580 old_ctx = read_c0_entryhi() & ASID_MASK;
581 old_pagemask = read_c0_pagemask();
582 wired = read_c0_wired();
583 write_c0_wired(wired + 1);
584 write_c0_index(wired);
585 BARRIER;
586 write_c0_pagemask(pagemask);
587 write_c0_entryhi(entryhi);
588 write_c0_entrylo0(entrylo0);
589 write_c0_entrylo1(entrylo1);
590 BARRIER;
591 tlb_write_indexed();
592 BARRIER;
593
594 write_c0_entryhi(old_ctx);
595 BARRIER;
596 write_c0_pagemask(old_pagemask);
597 local_flush_tlb_all();
598 restore_irq(old_irq);
599}
600
601static void map_address(unsigned long virtual, unsigned long physical, unsigned long length)
602{
603 unsigned long entry0 = (physical & PFN_MASK) << PFN_SHIFT;
604 unsigned long entry1 = ((physical+length) & PFN_MASK) << PFN_SHIFT;
605 unsigned long entryhi = virtual & ~VPN2_SHIFT;
606
607 entry0 |= (M_EntryLoG | M_EntryLoV | (K_CacheAttrC << S_EntryLoC) );
608 entry1 |= (M_EntryLoG | M_EntryLoV | (K_CacheAttrC << S_EntryLoC) );
609
610 add_wired_entry(entry0, entry1, entryhi, DEFAULT_PAGE_MASK);
611}
612
613
614static void tlb_init(void)
615{
616 write_c0_pagemask(DEFAULT_PAGE_MASK);
617 write_c0_wired(0);
618 write_c0_framemask(0);
619
620 local_flush_tlb_all();
621/*
622 map_address(0x80000000, 0x80000000, 0x4000);
623 map_address(0x80004000, 0x80004000, MEM * 0x100000);
624*/
625}
626
627void tlb_refill_handler(void) 528void tlb_refill_handler(void)
628{ 529{
629 panicf("TLB refill handler at 0x%08lx! [0x%x]", read_c0_epc(), read_c0_badvaddr()); 530 panicf("TLB refill handler at 0x%08lx! [0x%x]", read_c0_epc(), read_c0_badvaddr());
diff --git a/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c
index 0916a9414a..7bd0ba4ae5 100644
--- a/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c
+++ b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c
@@ -60,9 +60,11 @@ struct usb_endpoint
60 unsigned int sent; 60 unsigned int sent;
61 unsigned int received; 61 unsigned int received;
62 }; 62 };
63 bool busy;
63 64
64 const enum ep_type type; 65 const enum ep_type type;
65 const bool use_dma; 66 const bool use_dma;
67 bool wait;
66 68
67 const unsigned int fifo_addr; 69 const unsigned int fifo_addr;
68 unsigned short fifo_size; 70 unsigned short fifo_size;
@@ -71,13 +73,14 @@ struct usb_endpoint
71static unsigned char ep0_rx_buf[64]; 73static unsigned char ep0_rx_buf[64];
72static unsigned char ep0state = USB_EP0_IDLE; 74static unsigned char ep0state = USB_EP0_IDLE;
73static struct usb_endpoint endpoints[] = 75static struct usb_endpoint endpoints[] =
74{/* buf length sent type use_dma fifo_addr fifo_size */ 76{/* buf length sent busy type use_dma wait fifo_addr fifo_size */
75 {&ep0_rx_buf, 0, {0}, ep_control, false, USB_FIFO_EP0, 64 }, 77 {&ep0_rx_buf, 0, {0}, false, ep_control, false, false, USB_FIFO_EP0, 64 },
76 {NULL, 0, {0}, ep_control, false, USB_FIFO_EP0, 64 }, 78 {NULL, 0, {0}, false, ep_control, false, false, USB_FIFO_EP0, 64 },
77 {NULL, 0, {0}, ep_bulk, false, USB_FIFO_EP1, 512}, 79 {NULL, 0, {0}, false, ep_bulk, false, false, USB_FIFO_EP1, 512},
78 {NULL, 0, {0}, ep_bulk, false, USB_FIFO_EP1, 512}, 80 {NULL, 0, {0}, false, ep_bulk, false, false, USB_FIFO_EP1, 512},
79 {NULL, 0, {0}, ep_interrupt, false, USB_FIFO_EP2, 64 } 81 {NULL, 0, {0}, false, ep_interrupt, false, false, USB_FIFO_EP2, 64 }
80}; 82};
83static struct wakeup ep_wkup[TOTAL_EP()];
81 84
82static inline void select_endpoint(int ep) 85static inline void select_endpoint(int ep)
83{ 86{
@@ -167,13 +170,14 @@ static void EP0_send(void)
167 struct usb_endpoint* ep = &endpoints[1]; 170 struct usb_endpoint* ep = &endpoints[1];
168 unsigned int length; 171 unsigned int length;
169 unsigned char csr0; 172 unsigned char csr0;
170 173
171 select_endpoint(0); 174 select_endpoint(0);
172 csr0 = REG_USB_REG_CSR0; 175 csr0 = REG_USB_REG_CSR0;
173 176
174 if(ep->length == 0) 177 if(ep->length == 0)
175 { 178 {
176 REG_USB_REG_CSR0 = (csr0 | USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND); 179 //REG_USB_REG_CSR0 = (csr0 | USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND);
180 REG_USB_REG_CSR0 = (csr0 | USB_CSR0_SVDOUTPKTRDY);
177 return; 181 return;
178 } 182 }
179 183
@@ -189,6 +193,8 @@ static void EP0_send(void)
189 { 193 {
190 REG_USB_REG_CSR0 = (csr0 | USB_CSR0_INPKTRDY | USB_CSR0_DATAEND); /* Set data end! */ 194 REG_USB_REG_CSR0 = (csr0 | USB_CSR0_INPKTRDY | USB_CSR0_DATAEND); /* Set data end! */
191 ep0state = USB_EP0_IDLE; 195 ep0state = USB_EP0_IDLE;
196 if(ep->wait)
197 wakeup_signal(&ep_wkup[1]);
192 } 198 }
193 else 199 else
194 REG_USB_REG_CSR0 = (csr0 | USB_CSR0_INPKTRDY); 200 REG_USB_REG_CSR0 = (csr0 | USB_CSR0_INPKTRDY);
@@ -199,7 +205,7 @@ static void EP0_handler(void)
199 logf("EP0_handler"); 205 logf("EP0_handler");
200 206
201 unsigned char csr0; 207 unsigned char csr0;
202 208
203 /* Read CSR0 */ 209 /* Read CSR0 */
204 select_endpoint(0); 210 select_endpoint(0);
205 csr0 = REG_USB_REG_CSR0; 211 csr0 = REG_USB_REG_CSR0;
@@ -229,11 +235,13 @@ static void EP0_handler(void)
229 /* Call relevant routines for endpoint 0 state */ 235 /* Call relevant routines for endpoint 0 state */
230 if(ep0state == USB_EP0_IDLE) 236 if(ep0state == USB_EP0_IDLE)
231 { 237 {
232 if(csr0 & USB_CSR0_OUTPKTRDY) /* There is data in the fifo */ 238 if(csr0 & USB_CSR0_OUTPKTRDY) /* There is a packet in the fifo */
233 { 239 {
234 readFIFO(&endpoints[0], REG_USB_REG_COUNT0); 240 readFIFO(&endpoints[0], REG_USB_REG_COUNT0);
235 REG_USB_REG_CSR0 = csr0 | USB_CSR0_SVDOUTPKTRDY; /* clear OUTPKTRDY bit */ 241 REG_USB_REG_CSR0 = csr0 | USB_CSR0_SVDOUTPKTRDY; /* clear OUTPKTRDY bit */
236 usb_core_control_request((struct usb_ctrlrequest*)endpoints[0].buf); 242 usb_core_control_request((struct usb_ctrlrequest*)endpoints[0].buf);
243 if(endpoints[0].wait)
244 wakeup_signal(&ep_wkup[0]);
237 } 245 }
238 } 246 }
239 else if(ep0state == USB_EP0_TX) 247 else if(ep0state == USB_EP0_TX)
@@ -249,7 +257,7 @@ static void EPIN_handler(unsigned int endpoint)
249 csr = REG_USB_REG_INCSR; 257 csr = REG_USB_REG_INCSR;
250 logf("EPIN_handler(%d): 0x%x", endpoint, csr); 258 logf("EPIN_handler(%d): 0x%x", endpoint, csr);
251 259
252 if(ep->buf == NULL || ep->length == 0) 260 if(!ep->busy)
253 return; 261 return;
254 262
255 if(csr & USB_INCSR_SENTSTALL) 263 if(csr & USB_INCSR_SENTSTALL)
@@ -258,15 +266,19 @@ static void EPIN_handler(unsigned int endpoint)
258 return; 266 return;
259 } 267 }
260 268
269#if 0
261 if(ep->use_dma == true) 270 if(ep->use_dma == true)
262 return; 271 return;
272#endif
263 273
264 if(csr & USB_INCSR_FFNOTEMPT) 274 if(csr & USB_INCSR_FFNOTEMPT)
265 { 275 {
266 logf("FIFO is not empty!"); 276 logf("FIFO is not empty!: 0x%x", csr);
267 return; 277 return;
268 } 278 }
269 279
280 logf("EP%d: %d -> %d", endpoint, ep->sent, ep->length);
281
270 if(ep->sent == 0) 282 if(ep->sent == 0)
271 length = (ep->length <= ep->fifo_size ? ep->length : ep->fifo_size); 283 length = (ep->length <= ep->fifo_size ? ep->length : ep->fifo_size);
272 else 284 else
@@ -279,9 +291,13 @@ static void EPIN_handler(unsigned int endpoint)
279 if(ep->sent >= ep->length) 291 if(ep->sent >= ep->length)
280 { 292 {
281 usb_core_transfer_complete(endpoint, USB_DIR_IN, 0, ep->sent); 293 usb_core_transfer_complete(endpoint, USB_DIR_IN, 0, ep->sent);
294 if(ep->wait)
295 wakeup_signal(&ep_wkup[endpoint*2+1]);
296 logf("sent complete");
282 ep->sent = 0; 297 ep->sent = 0;
283 ep->length = 0; 298 ep->length = 0;
284 ep->buf = NULL; 299 ep->buf = NULL;
300 ep->busy = false;
285 } 301 }
286} 302}
287 303
@@ -289,36 +305,44 @@ static void EPOUT_handler(unsigned int endpoint)
289{ 305{
290 struct usb_endpoint* ep = &endpoints[endpoint*2]; 306 struct usb_endpoint* ep = &endpoints[endpoint*2];
291 unsigned int size, csr; 307 unsigned int size, csr;
292 308
293 select_endpoint(endpoint); 309 select_endpoint(endpoint);
294 csr = REG_USB_REG_OUTCSR; 310 csr = REG_USB_REG_OUTCSR;
295 logf("EPOUT_handler(%d): 0x%x", endpoint, csr); 311 logf("EPOUT_handler(%d): 0x%x", endpoint, csr);
296 312
297 if(ep->buf == NULL || ep->length == 0) 313 if(!ep->busy)
298 return; 314 return;
299 315
300 if(csr & USB_OUTCSR_SENTSTALL) 316 if(csr & USB_OUTCSR_SENTSTALL)
301 { 317 {
318 logf("stall sent, flushing fifo..");
319 flushFIFO(ep);
302 REG_USB_REG_OUTCSR = csr & ~USB_OUTCSR_SENTSTALL; 320 REG_USB_REG_OUTCSR = csr & ~USB_OUTCSR_SENTSTALL;
303 return; 321 return;
304 } 322 }
305 323
306 size = REG_USB_REG_OUTCOUNT; 324 if(csr & USB_OUTCSR_OUTPKTRDY) /* There is a packet in the fifo */
307
308 readFIFO(ep, size);
309 ep->received += size;
310
311 REG_USB_REG_OUTCSR = csr & ~USB_OUTCSR_OUTPKTRDY;
312
313 logf("received: %d length: %d", ep->received, ep->length);
314
315 if(size < ep->fifo_size || ep->received >= ep->length)
316 { 325 {
317 usb_core_transfer_complete(endpoint, USB_DIR_OUT, 0, ep->received); 326 size = REG_USB_REG_OUTCOUNT;
318 logf("receive transfer_complete"); 327
319 ep->received = 0; 328 readFIFO(ep, size);
320 ep->length = 0; 329 ep->received += size;
321 ep->buf = NULL; 330
331 REG_USB_REG_OUTCSR = csr & ~USB_OUTCSR_OUTPKTRDY;
332
333 logf("received: %d max length: %d", ep->received, ep->length);
334
335 if(size < ep->fifo_size || ep->received >= ep->length)
336 {
337 usb_core_transfer_complete(endpoint, USB_DIR_OUT, 0, ep->received);
338 if(ep->wait)
339 wakeup_signal(&ep_wkup[endpoint*2]);
340 logf("receive transfer_complete");
341 ep->received = 0;
342 ep->length = 0;
343 ep->buf = NULL;
344 ep->busy = false;
345 }
322 } 346 }
323} 347}
324 348
@@ -330,6 +354,9 @@ static void setup_endpoint(struct usb_endpoint *ep)
330 354
331 select_endpoint(EP_NUMBER2(ep)); 355 select_endpoint(EP_NUMBER2(ep));
332 356
357 ep->busy = false;
358 ep->wait = false;
359
333 if(ep->type == ep_bulk) 360 if(ep->type == ep_bulk)
334 { 361 {
335 if(REG_USB_REG_POWER & USB_POWER_HSMODE) 362 if(REG_USB_REG_POWER & USB_POWER_HSMODE)
@@ -474,11 +501,13 @@ void UDC(void)
474 501
475bool usb_drv_stalled(int endpoint, bool in) 502bool usb_drv_stalled(int endpoint, bool in)
476{ 503{
504 endpoint &= 0x7F;
505
477 logf("usb_drv_stalled(%d, %s)", endpoint, in?"IN":"OUT"); 506 logf("usb_drv_stalled(%d, %s)", endpoint, in?"IN":"OUT");
478 507
479 select_endpoint(endpoint & 0x7F); 508 select_endpoint(endpoint);
480 509
481 if(endpoint == 0) 510 if(endpoint == EP_CONTROL)
482 return (REG_USB_REG_CSR0 & USB_CSR0_SENDSTALL) != 0; 511 return (REG_USB_REG_CSR0 & USB_CSR0_SENDSTALL) != 0;
483 else 512 else
484 { 513 {
@@ -491,6 +520,8 @@ bool usb_drv_stalled(int endpoint, bool in)
491 520
492void usb_drv_stall(int endpoint, bool stall, bool in) 521void usb_drv_stall(int endpoint, bool stall, bool in)
493{ 522{
523 endpoint &= 0x7F;
524
494 logf("usb_drv_stall(%d,%s,%s)", endpoint, stall?"Y":"N", in?"IN":"OUT"); 525 logf("usb_drv_stall(%d,%s,%s)", endpoint, stall?"Y":"N", in?"IN":"OUT");
495 526
496 select_endpoint(endpoint); 527 select_endpoint(endpoint);
@@ -533,10 +564,25 @@ int usb_detect(void)
533 564
534void usb_init_device(void) 565void usb_init_device(void)
535{ 566{
567 unsigned int i;
568
536 USB_INIT_GPIO(); 569 USB_INIT_GPIO();
570#ifdef USB_GPIO_IRQ
571 system_enable_irq(IRQ_GPIO_UDC_DETE);
572#endif
537 system_enable_irq(IRQ_UDC); 573 system_enable_irq(IRQ_UDC);
574
575 for(i=0; i<TOTAL_EP(); i++)
576 wakeup_init(&ep_wkup[i]);
538} 577}
539 578
579#ifdef USB_GPIO_IRQ
580void USB_GPIO_IRQ(void)
581{
582 usb_status_event(usb_detect());
583}
584#endif
585
540void usb_enable(bool on) 586void usb_enable(bool on)
541{ 587{
542 if(on) 588 if(on)
@@ -545,6 +591,11 @@ void usb_enable(bool on)
545 usb_core_exit(); 591 usb_core_exit();
546} 592}
547 593
594void usb_attach(void)
595{
596 usb_enable(true);
597}
598
548void usb_drv_init(void) 599void usb_drv_init(void)
549{ 600{
550 logf("usb_drv_init()"); 601 logf("usb_drv_init()");
@@ -591,7 +642,7 @@ void usb_drv_set_address(int address)
591 REG_USB_REG_FADDR = address; 642 REG_USB_REG_FADDR = address;
592} 643}
593 644
594int usb_drv_send(int endpoint, void* ptr, int length) 645int usb_drv_send_nonblocking(int endpoint, void* ptr, int length)
595{ 646{
596 int flags; 647 int flags;
597 endpoint &= 0x7F; 648 endpoint &= 0x7F;
@@ -619,6 +670,7 @@ int usb_drv_send(int endpoint, void* ptr, int length)
619 endpoints[endpoint*2+1].buf = ptr; 670 endpoints[endpoint*2+1].buf = ptr;
620 endpoints[endpoint*2+1].sent = 0; 671 endpoints[endpoint*2+1].sent = 0;
621 endpoints[endpoint*2+1].length = length; 672 endpoints[endpoint*2+1].length = length;
673 endpoints[endpoint*2+1].busy = true;
622#if 0 674#if 0
623 select_endpoint(endpoint); 675 select_endpoint(endpoint);
624 676
@@ -626,7 +678,6 @@ int usb_drv_send(int endpoint, void* ptr, int length)
626 REG_USB_REG_COUNT2 = length; 678 REG_USB_REG_COUNT2 = length;
627 REG_USB_REG_CNTL2 = (USB_CNTL_INTR_EN | USB_CNTL_MODE_1 | USB_CNTL_DIR_IN | USB_CNTL_ENA); 679 REG_USB_REG_CNTL2 = (USB_CNTL_INTR_EN | USB_CNTL_MODE_1 | USB_CNTL_DIR_IN | USB_CNTL_ENA);
628#else 680#else
629
630 EPIN_handler(endpoint); 681 EPIN_handler(endpoint);
631#endif 682#endif
632 restore_irq(flags); 683 restore_irq(flags);
@@ -634,9 +685,20 @@ int usb_drv_send(int endpoint, void* ptr, int length)
634 } 685 }
635} 686}
636 687
637int usb_drv_send_nonblocking(int endpoint, void* ptr, int length) 688int usb_drv_send(int endpoint, void* ptr, int length)
638{ 689{
639 return usb_drv_send(endpoint, ptr, length); 690 int ret;
691 endpoint &= 0x7F;
692
693 if(endpoint == EP_CONTROL && ptr == NULL && length == 0)
694 return 0; /* ACK request, handled by the USB controller */
695
696 endpoints[endpoint*2+1].wait = true;
697 ret = usb_drv_send_nonblocking(endpoint, ptr, length);
698 wakeup_wait(&ep_wkup[endpoint*2+1], TIMEOUT_BLOCK);
699 endpoints[endpoint*2+1].wait = false;
700
701 return ret;
640} 702}
641 703
642int usb_drv_recv(int endpoint, void* ptr, int length) 704int usb_drv_recv(int endpoint, void* ptr, int length)
@@ -654,7 +716,9 @@ int usb_drv_recv(int endpoint, void* ptr, int length)
654 endpoints[endpoint*2].buf = ptr; 716 endpoints[endpoint*2].buf = ptr;
655 endpoints[endpoint*2].received = 0; 717 endpoints[endpoint*2].received = 0;
656 endpoints[endpoint*2].length = length; 718 endpoints[endpoint*2].length = length;
719 endpoints[endpoint*2].busy = true;
657 restore_irq(flags); 720 restore_irq(flags);
721
658 return 0; 722 return 0;
659 } 723 }
660} 724}
diff --git a/firmware/target/mips/mmu-mips.c b/firmware/target/mips/mmu-mips.c
new file mode 100644
index 0000000000..3c1b932325
--- /dev/null
+++ b/firmware/target/mips/mmu-mips.c
@@ -0,0 +1,125 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2009 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 "mips.h"
24#include "mipsregs.h"
25#include "system.h"
26#include "mmu-mips.h"
27
28#define BARRIER \
29 __asm__ __volatile__( \
30 " .set noreorder \n" \
31 " nop \n" \
32 " nop \n" \
33 " nop \n" \
34 " nop \n" \
35 " nop \n" \
36 " nop \n" \
37 " .set reorder \n");
38
39#define DEFAULT_PAGE_SHIFT PL_4K
40#define DEFAULT_PAGE_MASK PM_4K
41#define UNIQUE_ENTRYHI(idx, ps) (A_K0BASE + ((idx) << (ps + 1)))
42#define ASID_MASK M_EntryHiASID
43#define VPN2_SHIFT S_EntryHiVPN2
44#define PFN_SHIFT S_EntryLoPFN
45#define PFN_MASK 0xffffff
46static void local_flush_tlb_all(void)
47{
48 unsigned long old_ctx;
49 int entry;
50 unsigned int old_irq = disable_irq_save();
51
52 /* Save old context and create impossible VPN2 value */
53 old_ctx = read_c0_entryhi();
54 write_c0_entrylo0(0);
55 write_c0_entrylo1(0);
56 BARRIER;
57
58 /* Blast 'em all away. */
59 for(entry = 0; entry < 32; entry++)
60 {
61 /* Make sure all entries differ. */
62 write_c0_entryhi(UNIQUE_ENTRYHI(entry, DEFAULT_PAGE_SHIFT));
63 write_c0_index(entry);
64 BARRIER;
65 tlb_write_indexed();
66 }
67 BARRIER;
68 write_c0_entryhi(old_ctx);
69
70 restore_irq(old_irq);
71}
72
73static void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
74 unsigned long entryhi, unsigned long pagemask)
75{
76 unsigned long wired;
77 unsigned long old_pagemask;
78 unsigned long old_ctx;
79 unsigned int old_irq = disable_irq_save();
80
81 old_ctx = read_c0_entryhi() & ASID_MASK;
82 old_pagemask = read_c0_pagemask();
83 wired = read_c0_wired();
84 write_c0_wired(wired + 1);
85 write_c0_index(wired);
86 BARRIER;
87 write_c0_pagemask(pagemask);
88 write_c0_entryhi(entryhi);
89 write_c0_entrylo0(entrylo0);
90 write_c0_entrylo1(entrylo1);
91 BARRIER;
92 tlb_write_indexed();
93 BARRIER;
94
95 write_c0_entryhi(old_ctx);
96 BARRIER;
97 write_c0_pagemask(old_pagemask);
98 local_flush_tlb_all();
99 restore_irq(old_irq);
100}
101
102void map_address(unsigned long virtual, unsigned long physical, unsigned long length)
103{
104 unsigned long entry0 = (physical & PFN_MASK) << PFN_SHIFT;
105 unsigned long entry1 = ((physical+length) & PFN_MASK) << PFN_SHIFT;
106 unsigned long entryhi = virtual & ~VPN2_SHIFT;
107
108 entry0 |= (M_EntryLoG | M_EntryLoV | (K_CacheAttrC << S_EntryLoC) );
109 entry1 |= (M_EntryLoG | M_EntryLoV | (K_CacheAttrC << S_EntryLoC) );
110
111 add_wired_entry(entry0, entry1, entryhi, DEFAULT_PAGE_MASK);
112}
113
114void tlb_init(void)
115{
116 write_c0_pagemask(DEFAULT_PAGE_MASK);
117 write_c0_wired(0);
118 write_c0_framemask(0);
119
120 local_flush_tlb_all();
121/*
122 map_address(0x80000000, 0x80000000, 0x4000);
123 map_address(0x80004000, 0x80004000, MEM * 0x100000);
124*/
125}
diff --git a/firmware/target/mips/mmu-mips.h b/firmware/target/mips/mmu-mips.h
new file mode 100644
index 0000000000..1670d57f1c
--- /dev/null
+++ b/firmware/target/mips/mmu-mips.h
@@ -0,0 +1,28 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2009 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#ifndef __MMU_MIPS_INCLUDE_H
23#define __MMU_MIPS_INCLUDE_H
24
25void map_address(unsigned long virtual, unsigned long physical, unsigned long length);
26void tlb_init(void);
27
28#endif /* __MMU_MIPS_INCLUDE_H */