summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaurus Cuelenaere <mcuelenaere@gmail.com>2008-11-05 00:24:46 +0000
committerMaurus Cuelenaere <mcuelenaere@gmail.com>2008-11-05 00:24:46 +0000
commit4af26e7e98b6d4b2e1c94a54ad7ca02d55bb04cc (patch)
tree9b6fb2c6f016982c8b7cb79ba7aa94f4f57f99ba
parent0711c795e628b49431987861b9f535516c74abac (diff)
downloadrockbox-4af26e7e98b6d4b2e1c94a54ad7ca02d55bb04cc.zip
rockbox-4af26e7e98b6d4b2e1c94a54ad7ca02d55bb04cc.tar.gz
rockbox-4af26e7e98b6d4b2e1c94a54ad7ca02d55bb04cc.tar.bz2
rockbox-4af26e7e98b6d4b2e1c94a54ad7ca02d55bb04cc.tar.xz
Onda VX747:
* Commit (premature) SD, USB & audio drivers * Fix ramdisk.c mistake * Add battery readout git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19011 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/SOURCES6
-rw-r--r--firmware/drivers/ramdisk.c2
-rw-r--r--firmware/export/config-ondavx747.h6
-rw-r--r--firmware/target/mips/ingenic_jz47xx/ata-jz4740.c104
-rw-r--r--firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c156
-rw-r--r--firmware/target/mips/ingenic_jz47xx/ata-nand-target.h28
-rw-r--r--firmware/target/mips/ingenic_jz47xx/ata-sd-jz4740.c1168
-rw-r--r--firmware/target/mips/ingenic_jz47xx/ata-sd-target.h39
-rw-r--r--firmware/target/mips/ingenic_jz47xx/codec-jz4740.c280
-rw-r--r--firmware/target/mips/ingenic_jz47xx/onda_vx747/sadc-onda_vx747.c54
-rw-r--r--firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c164
-rw-r--r--firmware/target/mips/ingenic_jz47xx/usb-jz4740.c1635
12 files changed, 2936 insertions, 706 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index f299d51..33386f8 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -1157,9 +1157,13 @@ drivers/qt1106.c
#endif /* MEIZU_M3 */
#if CONFIG_CPU==JZ4732
+target/mips/ingenic_jz47xx/ata-jz4740.c
target/mips/ingenic_jz47xx/ata-nand-jz4740.c
-target/mips/ingenic_jz47xx/lcd-jz4740.c
+target/mips/ingenic_jz47xx/ata-sd-jz4740.c
+target/mips/ingenic_jz47xx/codec-jz4740.c
target/mips/ingenic_jz47xx/kernel-jz4740.c
+target/mips/ingenic_jz47xx/lcd-jz4740.c
+target/mips/ingenic_jz47xx/pcm-jz4740.c
target/mips/ingenic_jz47xx/system-jz4740.c
target/mips/ingenic_jz47xx/usb-jz4740.c
drivers/nand_id.c
diff --git a/firmware/drivers/ramdisk.c b/firmware/drivers/ramdisk.c
index 0a3e991..266d3ea 100644
--- a/firmware/drivers/ramdisk.c
+++ b/firmware/drivers/ramdisk.c
@@ -84,7 +84,7 @@ void ramdisk_spindown(int seconds)
(void)seconds;
}
#ifdef STORAGE_GET_INFO
-void ramdisk_get_info(struct storage_info *info)
+void ramdisk_get_info(IF_MV2(int drive,) struct storage_info *info)
{
/* firmware version */
info->revision="0.00";
diff --git a/firmware/export/config-ondavx747.h b/firmware/export/config-ondavx747.h
index e52b387..3d7628f 100644
--- a/firmware/export/config-ondavx747.h
+++ b/firmware/export/config-ondavx747.h
@@ -37,7 +37,7 @@
#define HAVE_HOTSWAP
//#define CONFIG_STORAGE (STORAGE_NAND | STORAGE_SD)
-#define CONFIG_STORAGE STORAGE_NAND /* Multivolume currently handled at firmware/target/ level */
+#define CONFIG_STORAGE STORAGE_RAMDISK /* Multivolume currently handled at firmware/target/ level */
#define CONFIG_NAND NAND_CC
@@ -156,10 +156,10 @@
#define BOOTFILE "rockbox." BOOTFILE_EXT
#define BOOTDIR "/.rockbox"
-/*#define CONFIG_USBOTG USBOTG_INGENIC
+#define CONFIG_USBOTG USBOTG_INGENIC
#define HAVE_USBSTACK
#define USB_VENDOR_ID 0x041e
-#define USB_PRODUCT_ID 0x4133*/
+#define USB_PRODUCT_ID 0x4133
#include <stdbool.h> /* HACKY */
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 0000000..dd14a4c
--- /dev/null
+++ b/firmware/target/mips/ingenic_jz47xx/ata-jz4740.c
@@ -0,0 +1,104 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2008 by Maurus Cuelenaere
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "config.h"
+#include "ata.h"
+#include "ata-sd-target.h"
+#include "ata-nand-target.h"
+#include "panic.h"
+
+int ata_read_sectors(IF_MV2(int drive,) unsigned long start, int count, void* buf)
+{
+ switch(drive)
+ {
+ case 0:
+ return nand_read_sectors(start, count, buf);
+ case 1:
+ return sd_read_sectors(start, count, buf);
+ default:
+ panicf("ata_read_sectors: Drive %d unhandled!", drive);
+ return -1;
+ }
+}
+
+int ata_write_sectors(IF_MV2(int drive,) unsigned long start, int count, const void* buf)
+{
+ switch(drive)
+ {
+ case 0:
+ return nand_write_sectors(start, count, buf);
+ case 1:
+ return sd_write_sectors(start, count, buf);
+ default:
+ panicf("ata_write_sectors: Drive %d unhandled!", drive);
+ return -1;
+ }
+}
+
+int ata_init(void)
+{
+ if(sd_init() != 0)
+ return -1;
+ if(nand_init() != 0)
+ return -2;
+
+ return 0;
+}
+
+void ata_spindown(int seconds)
+{
+ /* null */
+ (void)seconds;
+}
+
+bool ata_disk_is_active(void)
+{
+ /* null */
+ return false;
+}
+
+void ata_sleep(void)
+{
+ /* null */
+}
+
+void ata_spin(void)
+{
+ /* null */
+}
+
+int ata_hard_reset(void)
+{
+ /* null */
+ return 0;
+}
+
+int ata_soft_reset(void)
+{
+ /* null */
+ return 0;
+}
+
+void ata_enable(bool on)
+{
+ /* null - flash controller is enabled/disabled as needed. */
+ (void)on;
+}
diff --git a/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c b/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c
index a41a622..7a937bf 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 @@
#include "config.h"
#include "jz4740.h"
#include "ata.h"
+#include "ata-nand-target.h"
#include "nand_id.h"
#include "system.h"
#include "panic.h"
@@ -29,31 +30,31 @@
/*
* Standard NAND flash commands
*/
-#define NAND_CMD_READ0 0
-#define NAND_CMD_READ1 1
+#define NAND_CMD_READ0 0
+#define NAND_CMD_READ1 1
#define NAND_CMD_RNDOUT 5
-#define NAND_CMD_PAGEPROG 0x10
-#define NAND_CMD_READOOB 0x50
+#define NAND_CMD_PAGEPROG 0x10
+#define NAND_CMD_READOOB 0x50
#define NAND_CMD_ERASE1 0x60
#define NAND_CMD_STATUS 0x70
-#define NAND_CMD_STATUS_MULTI 0x71
-#define NAND_CMD_SEQIN 0x80
-#define NAND_CMD_RNDIN 0x85
+#define NAND_CMD_STATUS_MULTI 0x71
+#define NAND_CMD_SEQIN 0x80
+#define NAND_CMD_RNDIN 0x85
#define NAND_CMD_READID 0x90
#define NAND_CMD_ERASE2 0xd0
-#define NAND_CMD_RESET 0xff
+#define NAND_CMD_RESET 0xff
/* Extended commands for large page devices */
#define NAND_CMD_READSTART 0x30
-#define NAND_CMD_RNDOUTSTART 0xE0
-#define NAND_CMD_CACHEDPROG 0x15
+#define NAND_CMD_RNDOUTSTART 0xE0
+#define NAND_CMD_CACHEDPROG 0x15
/* Status bits */
-#define NAND_STATUS_FAIL 0x01
+#define NAND_STATUS_FAIL 0x01
#define NAND_STATUS_FAIL_N1 0x02
-#define NAND_STATUS_TRUE_READY 0x20
-#define NAND_STATUS_READY 0x40
-#define NAND_STATUS_WP 0x80
+#define NAND_STATUS_TRUE_READY 0x20
+#define NAND_STATUS_READY 0x40
+#define NAND_STATUS_WP 0x80
/*
* NAND parameter struct
@@ -81,21 +82,21 @@ struct nand_param
#define NAND_COMMPORT 0xb8008000
#define ECC_BLOCK 512
-#define ECC_POS 6
-#define PAR_SIZE 9
+#define ECC_POS 6
+#define PAR_SIZE 9
-#define __nand_cmd(n) (REG8(NAND_COMMPORT) = (n))
-#define __nand_addr(n) (REG8(NAND_ADDRPORT) = (n))
-#define __nand_data8() REG8(NAND_DATAPORT)
-#define __nand_data16() REG16(NAND_DATAPORT)
+#define __nand_cmd(n) (REG8(NAND_COMMPORT) = (n))
+#define __nand_addr(n) (REG8(NAND_ADDRPORT) = (n))
+#define __nand_data8() REG8(NAND_DATAPORT)
+#define __nand_data16() REG16(NAND_DATAPORT)
#define __nand_enable() (REG_EMC_NFCSR |= EMC_NFCSR_NFE1 | EMC_NFCSR_NFCE1)
-#define __nand_disable() (REG_EMC_NFCSR &= ~(EMC_NFCSR_NFCE1))
+#define __nand_disable() (REG_EMC_NFCSR &= ~(EMC_NFCSR_NFCE1))
#define __nand_ecc_rs_encoding() \
(REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST | EMC_NFECR_RS | EMC_NFECR_RS_ENCODING)
#define __nand_ecc_rs_decoding() \
(REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST | EMC_NFECR_RS | EMC_NFECR_RS_DECODING)
-#define __nand_ecc_disable() (REG_EMC_NFECR &= ~EMC_NFECR_ECCE)
+#define __nand_ecc_disable() (REG_EMC_NFECR &= ~EMC_NFECR_ECCE)
#define __nand_ecc_encode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_ENCF))
#define __nand_ecc_decode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_DECF))
@@ -104,14 +105,14 @@ struct nand_param
static struct nand_info* chip_info = NULL;
static struct nand_param internal_param;
-static inline void nand_wait_ready(void)
+static inline void jz_nand_wait_ready(void)
{
unsigned int timeout = 1000;
while ((REG_GPIO_PXPIN(2) & 0x40000000) && timeout--);
while (!(REG_GPIO_PXPIN(2) & 0x40000000));
}
-static inline void nand_read_buf16(void *buf, int count)
+static inline void jz_nand_read_buf16(void *buf, int count)
{
int i;
unsigned short *p = (unsigned short *)buf;
@@ -120,7 +121,7 @@ static inline void nand_read_buf16(void *buf, int count)
*p++ = __nand_data16();
}
-static inline void nand_read_buf8(void *buf, int count)
+static inline void jz_nand_read_buf8(void *buf, int count)
{
int i;
unsigned char *p = (unsigned char *)buf;
@@ -129,18 +130,53 @@ static inline void nand_read_buf8(void *buf, int count)
*p++ = __nand_data8();
}
-static inline void nand_read_buf(void *buf, int count, int bw)
+static void jz_nand_write_dma(void *source, unsigned int len, int bw)
+{
+ if(((unsigned int)source < 0xa0000000) && len)
+ dma_cache_wback_inv((unsigned long)source, len);
+
+ REG_DMAC_DCCSR(DMA_NAND_CHANNEL) = 0;
+ REG_DMAC_DSAR(DMA_NAND_CHANNEL) = PHYSADDR((unsigned long)source);
+ REG_DMAC_DTAR(DMA_NAND_CHANNEL) = PHYSADDR((unsigned long)NAND_DATAPORT);
+ REG_DMAC_DTCR(DMA_NAND_CHANNEL) = len / 16;
+ REG_DMAC_DRSR(DMA_NAND_CHANNEL) = DMAC_DRSR_RS_AUTO;
+ REG_DMAC_DCMD(DMA_NAND_CHANNEL) = (DMAC_DCMD_SAI| DMAC_DCMD_DAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DS_16BYTE |
+ (bw == 8 ? DMAC_DCMD_DWDH_8 : DMAC_DCMD_DWDH_16));
+
+ REG_DMAC_DCCSR(DMA_NAND_CHANNEL) = (DMAC_DCCSR_EN | DMAC_DCCSR_NDES);
+ while( REG_DMAC_DTCR(DMA_NAND_CHANNEL) )
+ yield();
+}
+
+static void jz_nand_read_dma(void *target, unsigned int len, int bw)
+{
+ if(((unsigned int)target < 0xa0000000) && len)
+ dma_cache_wback_inv((unsigned long)target, len);
+
+ REG_DMAC_DCCSR(DMA_NAND_CHANNEL) = 0;
+ REG_DMAC_DSAR(DMA_NAND_CHANNEL) = PHYSADDR((unsigned long)NAND_DATAPORT);
+ REG_DMAC_DTAR(DMA_NAND_CHANNEL) = PHYSADDR((unsigned long)target);
+ REG_DMAC_DTCR(DMA_NAND_CHANNEL) = len / 4;
+ REG_DMAC_DRSR(DMA_NAND_CHANNEL) = DMAC_DRSR_RS_AUTO;
+ REG_DMAC_DCMD(DMA_NAND_CHANNEL) = (DMAC_DCMD_SAI| DMAC_DCMD_DAI | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BIT |
+ (bw == 8 ? DMAC_DCMD_SWDH_8 : DMAC_DCMD_SWDH_16));
+ REG_DMAC_DCCSR(DMA_NAND_CHANNEL) = (DMAC_DCCSR_EN | DMAC_DCCSR_NDES);
+ while( REG_DMAC_DTCR(DMA_NAND_CHANNEL) )
+ yield();
+}
+
+static inline void jz_nand_read_buf(void *buf, int count, int bw)
{
if (bw == 8)
- nand_read_buf8(buf, count);
+ jz_nand_read_dma(buf, count, 8);
else
- nand_read_buf16(buf, count);
+ jz_nand_read_dma(buf, count, 16);
}
/*
* Correct 1~9-bit errors in 512-bytes data
*/
-static void rs_correct(unsigned char *dat, int idx, int mask)
+static void jz_rs_correct(unsigned char *dat, int idx, int mask)
{
int i, j;
unsigned short d, d1, dm;
@@ -172,7 +208,7 @@ static void rs_correct(unsigned char *dat, int idx, int mask)
/*
* Read oob
*/
-static int nand_read_oob(int page_addr, unsigned char *buf, int size)
+static int jz_nand_read_oob(int page_addr, unsigned char *buf, int size)
{
struct nand_param *nandp = &internal_param;
int page_size, row_cycle, bus_width;
@@ -210,10 +246,10 @@ static int nand_read_oob(int page_addr, unsigned char *buf, int size)
__nand_cmd(NAND_CMD_READSTART);
/* Wait for device ready */
- nand_wait_ready();
+ jz_nand_wait_ready();
/* Read oob data */
- nand_read_buf(buf, size, bus_width);
+ jz_nand_read_buf(buf, size, bus_width);
return 0;
}
@@ -228,7 +264,7 @@ static int nand_read_oob(int page_addr, unsigned char *buf, int size)
* page - page number within a block: 0, 1, 2, ...
* dst - pointer to target buffer
*/
-static int nand_read_page(int block, int page, unsigned char *dst)
+static int jz_nand_read_page(int block, int page, unsigned char *dst)
{
struct nand_param *nandp = &internal_param;
int page_size, oob_size, page_per_block;
@@ -248,7 +284,7 @@ static int nand_read_page(int block, int page, unsigned char *dst)
/*
* Read oob data
*/
- nand_read_oob(page_addr, oob_buf, oob_size);
+ jz_nand_read_oob(page_addr, oob_buf, oob_size);
/*
* Read page data
@@ -273,7 +309,7 @@ static int nand_read_page(int block, int page, unsigned char *dst)
__nand_cmd(NAND_CMD_READSTART);
/* Wait for device ready */
- nand_wait_ready();
+ jz_nand_wait_ready();
/* Read page data */
data_buf = dst;
@@ -290,7 +326,7 @@ static int nand_read_page(int block, int page, unsigned char *dst)
__nand_ecc_rs_decoding();
/* Read data */
- nand_read_buf((void *)data_buf, ECC_BLOCK, bus_width);
+ jz_nand_read_buf((void *)data_buf, ECC_BLOCK, bus_width);
/* Set PAR values */
for (j = 0; j < PAR_SIZE; j++)
@@ -310,8 +346,10 @@ static int nand_read_page(int block, int page, unsigned char *dst)
if (stat & EMC_NFINTS_ERR)
{
/* Error occurred */
- if (stat & EMC_NFINTS_UNCOR) {
+ if (stat & EMC_NFINTS_UNCOR)
+ {
/* Uncorrectable error occurred */
+ panicf("Uncorrectable ECC error at NAND page 0x%x block 0x%x", page, block);
}
else
{
@@ -323,19 +361,19 @@ static int nand_read_page(int block, int page, unsigned char *dst)
case 4:
index = (REG_EMC_NFERR3 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
mask = (REG_EMC_NFERR3 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
- rs_correct(data_buf, index, mask);
+ jz_rs_correct(data_buf, index, mask);
case 3:
index = (REG_EMC_NFERR2 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
mask = (REG_EMC_NFERR2 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
- rs_correct(data_buf, index, mask);
+ jz_rs_correct(data_buf, index, mask);
case 2:
index = (REG_EMC_NFERR1 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
mask = (REG_EMC_NFERR1 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
- rs_correct(data_buf, index, mask);
+ jz_rs_correct(data_buf, index, mask);
case 1:
index = (REG_EMC_NFERR0 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
mask = (REG_EMC_NFERR0 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
- rs_correct(data_buf, index, mask);
+ jz_rs_correct(data_buf, index, mask);
break;
default:
break;
@@ -352,7 +390,7 @@ static int nand_read_page(int block, int page, unsigned char *dst)
/*
* Enable NAND controller
*/
-static void nand_enable(void)
+static void jz_nand_enable(void)
{
__nand_enable();
@@ -362,16 +400,16 @@ static void nand_enable(void)
/*
* Disable NAND controller
*/
-static void nand_disable(void)
+static void jz_nand_disable(void)
{
__nand_disable();
}
-int nand_init(void)
+static int jz_nand_init(void)
{
unsigned char cData[5];
- nand_enable();
+ jz_nand_enable();
__nand_cmd(NAND_CMD_READID);
__nand_addr(NAND_CMD_READ0);
@@ -386,7 +424,7 @@ int nand_init(void)
{
panicf("Unknown NAND flash chip: 0x%x 0x%x 0x%x 0x%x 0x%x", cData[0],
cData[1], cData[2], cData[3], cData[4]);
- return -1;
+ return -1; /* panicf() doesn't return though */
}
internal_param.bus_width = 8;
@@ -400,23 +438,39 @@ int nand_init(void)
void jz_nand_read(int block, int page, unsigned char *buf)
{
- nand_read_page(block, page, buf);
+ jz_nand_read_page(block, page, buf);
}
-int nand_read_sectors(IF_MV2(int drive,) unsigned long start, int count, void* buf)
+static bool inited = false;
+int nand_init(void)
+{
+ int res = 0;
+
+ if(!inited)
+ {
+ res = jz_nand_init();
+ inited = true;
+ }
+
+ return res;
+}
+
+/* TODO */
+int nand_read_sectors(unsigned long start, int count, void* buf)
{
(void)start;
(void)count;
(void)buf;
- return 0;
+ return -1;
}
-int nand_write_sectors(IF_MV2(int drive,) unsigned long start, int count, const void* buf)
+/* TODO */
+int nand_write_sectors(unsigned long start, int count, const void* buf)
{
(void)start;
(void)count;
(void)buf;
- return 0;
+ return -1;
}
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 0000000..c8b2376
--- /dev/null
+++ b/firmware/target/mips/ingenic_jz47xx/ata-nand-target.h
@@ -0,0 +1,28 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2008 by Maurus Cuelenaere
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef ATA_NAND_TARGET_H
+#define ATA_NAND_TARGET_H
+
+int nand_read_sectors(unsigned long start, int count, void* buf);
+int nand_write_sectors(unsigned long start, int count, const void* buf);
+int nand_init(void);
+
+#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 0000000..ccd7163
--- /dev/null
+++ b/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4740.c
@@ -0,0 +1,1168 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2008 by Maurus Cuelenaere
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "config.h"
+#include "jz4740.h"
+#include "ata.h"
+#include "ata-sd-target.h"
+#include "system.h"
+#include "kernel.h"
+#include "panic.h"
+#include "debug.h"
+
+static struct wakeup sd_wakeup;
+
+//#define MMC_DMA_ENABLE
+#define MMC_DMA_INTERRUPT 0
+
+//#define DEBUG(x...) DEBUGF(x);
+#define DEBUG(x...) printf(x);
+
+#define MMC_CD_PIN (29 + 1 * 32) /* Pin to check card insertion */
+#define MMC_POWER_PIN (30 + 1 * 32) /* Pin to enable/disable card power */
+//#define MMC_PW_PIN (14 + 3 * 32) /* Pin to check protect card */
+
+#define MMC_POWER_OFF() \
+do { \
+ __gpio_set_pin(MMC_POWER_PIN); \
+} while (0)
+
+#define MMC_POWER_ON() \
+do { \
+ __gpio_clear_pin(MMC_POWER_PIN); \
+} while (0)
+
+#define MMC_INSERT_STATUS() __gpio_get_pin(MMC_CD_PIN)
+
+#define MMC_RESET() __msc_reset()
+
+#define MMC_IRQ_MASK() \
+do { \
+ REG_MSC_IMASK = 0xffff; \
+ REG_MSC_IREG = 0xffff; \
+} while (0)
+
+static inline void mmc_init_gpio(void)
+{
+ __gpio_as_msc();
+#ifdef MMC_POWER_PIN
+ __gpio_as_output(MMC_POWER_PIN);
+ __gpio_disable_pull(MMC_POWER_PIN);
+ __gpio_set_pin(MMC_POWER_PIN);
+#endif
+#ifdef MMC_CD_PIN
+ __gpio_as_input(MMC_CD_PIN);
+ __gpio_disable_pull(MMC_CD_PIN);
+#endif
+#ifdef MMC_PW_PIN
+ __gpio_as_input(MMC_PW_PIN);
+ __gpio_disable_pull(MMC_PW_PIN);
+#endif
+}
+
+/* Error codes */
+enum mmc_result_t
+{
+ MMC_NO_RESPONSE = -1,
+ MMC_NO_ERROR = 0,
+ MMC_ERROR_OUT_OF_RANGE,
+ MMC_ERROR_ADDRESS,
+ MMC_ERROR_BLOCK_LEN,
+ MMC_ERROR_ERASE_SEQ,
+ MMC_ERROR_ERASE_PARAM,
+ MMC_ERROR_WP_VIOLATION,
+ MMC_ERROR_CARD_IS_LOCKED,
+ MMC_ERROR_LOCK_UNLOCK_FAILED,
+ MMC_ERROR_COM_CRC,
+ MMC_ERROR_ILLEGAL_COMMAND,
+ MMC_ERROR_CARD_ECC_FAILED,
+ MMC_ERROR_CC,
+ MMC_ERROR_GENERAL,
+ MMC_ERROR_UNDERRUN,
+ MMC_ERROR_OVERRUN,
+ MMC_ERROR_CID_CSD_OVERWRITE,
+ MMC_ERROR_STATE_MISMATCH,
+ MMC_ERROR_HEADER_MISMATCH,
+ MMC_ERROR_TIMEOUT,
+ MMC_ERROR_CRC,
+ MMC_ERROR_DRIVER_FAILURE,
+};
+
+/* Standard MMC/SD clock speeds */
+#define MMC_CLOCK_SLOW 400000 /* 400 kHz for initial setup */
+#define MMC_CLOCK_FAST 20000000 /* 20 MHz for maximum for normal operation */
+#define SD_CLOCK_FAST 24000000 /* 24 MHz for SD Cards */
+#define SD_CLOCK_HIGH 48000000 /* 48 MHz for SD Cards */
+
+/* Extra MMC commands for state control */
+/* Use negative numbers to disambiguate */
+#define MMC_CIM_RESET -1
+
+/* Standard MMC commands (3.1) type argument response */
+ /* class 1 */
+#define MMC_GO_IDLE_STATE 0 /* bc */
+#define MMC_SEND_OP_COND 1 /* bcr [31:0] OCR R3 */
+#define MMC_ALL_SEND_CID 2 /* bcr R2 */
+#define MMC_SET_RELATIVE_ADDR 3 /* ac [31:16] RCA R1 */
+#define MMC_SET_DSR 4 /* bc [31:16] RCA */
+#define MMC_SELECT_CARD 7 /* ac [31:16] RCA R1 */
+#define MMC_SEND_CSD 9 /* ac [31:16] RCA R2 */
+#define MMC_SEND_CID 10 /* ac [31:16] RCA R2 */
+#define MMC_READ_DAT_UNTIL_STOP 11 /* adtc [31:0] dadr R1 */
+#define MMC_STOP_TRANSMISSION 12 /* ac R1b */
+#define MMC_SEND_STATUS 13 /* ac [31:16] RCA R1 */
+#define MMC_GO_INACTIVE_STATE 15 /* ac [31:16] RCA */
+
+ /* class 2 */
+#define MMC_SET_BLOCKLEN 16 /* ac [31:0] block len R1 */
+#define MMC_READ_SINGLE_BLOCK 17 /* adtc [31:0] data addr R1 */
+#define MMC_READ_MULTIPLE_BLOCK 18 /* adtc [31:0] data addr R1 */
+
+ /* class 3 */
+#define MMC_WRITE_DAT_UNTIL_STOP 20 /* adtc [31:0] data addr R1 */
+
+ /* class 4 */
+#define MMC_SET_BLOCK_COUNT 23 /* adtc [31:0] data addr R1 */
+#define MMC_WRITE_BLOCK 24 /* adtc [31:0] data addr R1 */
+#define MMC_WRITE_MULTIPLE_BLOCK 25 /* adtc R1 */
+#define MMC_PROGRAM_CID 26 /* adtc R1 */
+#define MMC_PROGRAM_CSD 27 /* adtc R1 */
+
+ /* class 6 */
+#define MMC_SET_WRITE_PROT 28 /* ac [31:0] data addr R1b */
+#define MMC_CLR_WRITE_PROT 29 /* ac [31:0] data addr R1b */
+#define MMC_SEND_WRITE_PROT 30 /* adtc [31:0] wpdata addr R1 */
+
+ /* class 5 */
+#define MMC_ERASE_GROUP_START 35 /* ac [31:0] data addr R1 */
+#define MMC_ERASE_GROUP_END 36 /* ac [31:0] data addr R1 */
+#define MMC_ERASE 37 /* ac R1b */
+
+ /* class 9 */
+#define MMC_FAST_IO 39 /* ac <Complex> R4 */
+#define MMC_GO_IRQ_STATE 40 /* bcr R5 */
+
+ /* class 7 */
+#define MMC_LOCK_UNLOCK 42 /* adtc R1b */
+
+ /* class 8 */
+#define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */
+#define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1b */
+
+ /* SD class */
+#define SD_SEND_OP_COND 41 /* bcr [31:0] OCR R3 */
+#define SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */
+#define SEND_SCR 51 /* adtc [31:0] staff R1 */
+
+/* Don't change the order of these; they are used in dispatch tables */
+enum mmc_rsp_t
+{
+ RESPONSE_NONE = 0,
+ RESPONSE_R1 = 1,
+ RESPONSE_R1B = 2,
+ RESPONSE_R2_CID = 3,
+ RESPONSE_R2_CSD = 4,
+ RESPONSE_R3 = 5,
+ RESPONSE_R4 = 6,
+ RESPONSE_R5 = 7,
+ RESPONSE_R6 = 8,
+};
+
+
+/*
+ MMC status in R1
+ Type
+ e : error bit
+ s : status bit
+ r : detected and set for the actual command response
+ x : detected and set during command execution. the host must poll
+ the card by sending status command in order to read these bits.
+ Clear condition
+ a : according to the card state
+ b : always related to the previous command. Reception of
+ a valid command will clear it (with a delay of one command)
+ c : clear by read
+ */
+
+#define R1_OUT_OF_RANGE (1 << 31) /* er, c */
+#define R1_ADDRESS_ERROR (1 << 30) /* erx, c */
+#define R1_BLOCK_LEN_ERROR (1 << 29) /* er, c */
+#define R1_ERASE_SEQ_ERROR (1 << 28) /* er, c */
+#define R1_ERASE_PARAM (1 << 27) /* ex, c */
+#define R1_WP_VIOLATION (1 << 26) /* erx, c */
+#define R1_CARD_IS_LOCKED (1 << 25) /* sx, a */
+#define R1_LOCK_UNLOCK_FAILED (1 << 24) /* erx, c */
+#define R1_COM_CRC_ERROR (1 << 23) /* er, b */
+#define R1_ILLEGAL_COMMAND (1 << 22) /* er, b */
+#define R1_CARD_ECC_FAILED (1 << 21) /* ex, c */
+#define R1_CC_ERROR (1 << 20) /* erx, c */
+#define R1_ERROR (1 << 19) /* erx, c */
+#define R1_UNDERRUN (1 << 18) /* ex, c */
+#define R1_OVERRUN (1 << 17) /* ex, c */
+#define R1_CID_CSD_OVERWRITE (1 << 16) /* erx, c, CID/CSD overwrite */
+#define R1_WP_ERASE_SKIP (1 << 15) /* sx, c */
+#define R1_CARD_ECC_DISABLED (1 << 14) /* sx, a */
+#define R1_ERASE_RESET (1 << 13) /* sr, c */
+#define R1_STATUS(x) (x & 0xFFFFE000)
+#define R1_CURRENT_STATE(x) ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */
+#define R1_READY_FOR_DATA (1 << 8) /* sx, a */
+#define R1_APP_CMD (1 << 7) /* sr, c */
+
+enum card_state
+{
+ CARD_STATE_EMPTY = -1,
+ CARD_STATE_IDLE = 0,
+ CARD_STATE_READY = 1,
+ CARD_STATE_IDENT = 2,
+ CARD_STATE_STBY = 3,
+ CARD_STATE_TRAN = 4,
+ CARD_STATE_DATA = 5,
+ CARD_STATE_RCV = 6,
+ CARD_STATE_PRG = 7,
+ CARD_STATE_DIS = 8,
+};
+
+/* These are unpacked versions of the actual responses */
+struct mmc_response_r1
+{
+ unsigned char cmd;
+ unsigned int status;
+};
+
+struct mmc_cid
+{
+ unsigned char mid;
+ unsigned short oid;
+ unsigned char pnm[7]; /* Product name (we null-terminate) */
+ unsigned char prv;
+ unsigned int psn;
+ unsigned char mdt;
+};
+
+struct mmc_csd
+{
+ unsigned char csd_structure;
+ unsigned char spec_vers;
+ unsigned char taac;
+ unsigned char nsac;
+ unsigned char tran_speed;
+ unsigned short ccc;
+ unsigned char read_bl_len;
+ unsigned char read_bl_partial;
+ unsigned char write_blk_misalign;
+ unsigned char read_blk_misalign;
+ unsigned char dsr_imp;
+ unsigned short c_size;
+ unsigned char vdd_r_curr_min;
+ unsigned char vdd_r_curr_max;
+ unsigned char vdd_w_curr_min;
+ unsigned char vdd_w_curr_max;
+ unsigned char c_size_mult;
+ union
+ {
+ struct /* MMC system specification version 3.1 */
+ {
+ unsigned char erase_grp_size;
+ unsigned char erase_grp_mult;
+ } v31;
+ struct /* MMC system specification version 2.2 */
+ {
+ unsigned char sector_size;
+ unsigned char erase_grp_size;
+ } v22;
+ } erase;
+ unsigned char wp_grp_size;
+ unsigned char wp_grp_enable;
+ unsigned char default_ecc;
+ unsigned char r2w_factor;
+ unsigned char write_bl_len;
+ unsigned char write_bl_partial;
+ unsigned char file_format_grp;
+ unsigned char copy;
+ unsigned char perm_write_protect;
+ unsigned char tmp_write_protect;
+ unsigned char file_format;
+ unsigned char ecc;
+};
+
+struct mmc_response_r3
+{
+ unsigned int ocr;
+};
+
+#define MMC_VDD_145_150 0x00000001 /* VDD voltage 1.45 - 1.50 */
+#define MMC_VDD_150_155 0x00000002 /* VDD voltage 1.50 - 1.55 */
+#define MMC_VDD_155_160 0x00000004 /* VDD voltage 1.55 - 1.60 */
+#define MMC_VDD_160_165 0x00000008 /* VDD voltage 1.60 - 1.65 */
+#define MMC_VDD_165_170 0x00000010 /* VDD voltage 1.65 - 1.70 */
+#define MMC_VDD_17_18 0x00000020 /* VDD voltage 1.7 - 1.8 */
+#define MMC_VDD_18_19 0x00000040 /* VDD voltage 1.8 - 1.9 */
+#define MMC_VDD_19_20 0x00000080 /* VDD voltage 1.9 - 2.0 */
+#define MMC_VDD_20_21 0x00000100 /* VDD voltage 2.0 ~ 2.1 */
+#define MMC_VDD_21_22 0x00000200 /* VDD voltage 2.1 ~ 2.2 */
+#define MMC_VDD_22_23 0x00000400 /* VDD voltage 2.2 ~ 2.3 */
+#define MMC_VDD_23_24 0x00000800 /* VDD voltage 2.3 ~ 2.4 */
+#define MMC_VDD_24_25 0x00001000 /* VDD voltage 2.4 ~ 2.5 */
+#define MMC_VDD_25_26 0x00002000 /* VDD voltage 2.5 ~ 2.6 */
+#define MMC_VDD_26_27 0x00004000 /* VDD voltage 2.6 ~ 2.7 */
+#define MMC_VDD_27_28 0x00008000 /* VDD voltage 2.7 ~ 2.8 */
+#define MMC_VDD_28_29 0x00010000 /* VDD voltage 2.8 ~ 2.9 */
+#define MMC_VDD_29_30 0x00020000 /* VDD voltage 2.9 ~ 3.0 */
+#define MMC_VDD_30_31 0x00040000 /* VDD voltage 3.0 ~ 3.1 */
+#define MMC_VDD_31_32 0x00080000 /* VDD voltage 3.1 ~ 3.2 */
+#define MMC_VDD_32_33 0x00100000 /* VDD voltage 3.2 ~ 3.3 */
+#define MMC_VDD_33_34 0x00200000 /* VDD voltage 3.3 ~ 3.4 */
+#define MMC_VDD_34_35 0x00400000 /* VDD voltage 3.4 ~ 3.5 */
+#define MMC_VDD_35_36 0x00800000 /* VDD voltage 3.5 ~ 3.6 */
+#define MMC_CARD_BUSY 0x80000000 /* Card Power up status bit */
+
+
+/* CSD field definitions */
+#define CSD_STRUCT_VER_1_0 0 /* Valid for system specification 1.0 - 1.2 */
+#define CSD_STRUCT_VER_1_1 1 /* Valid for system specification 1.4 - 2.2 */
+#define CSD_STRUCT_VER_1_2 2 /* Valid for system specification 3.1 */
+
+#define CSD_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.2 */
+#define CSD_SPEC_VER_1 1 /* Implements system specification 1.4 */
+#define CSD_SPEC_VER_2 2 /* Implements system specification 2.0 - 2.2 */
+#define CSD_SPEC_VER_3 3 /* Implements system specification 3.1 */
+
+/* the information structure of MMC/SD Card */
+typedef struct MMC_INFO
+{
+ int id; /* Card index */
+ int sd; /* MMC or SD card */
+ int rca; /* RCA */
+ unsigned int scr; /* SCR 63:32*/
+ int flags; /* Ejected, inserted */
+ enum card_state state; /* empty, ident, ready, whatever */
+
+ /* Card specific information */
+ struct mmc_cid cid;
+ struct mmc_csd csd;
+ unsigned int block_num;
+ unsigned int block_len;
+ unsigned int erase_unit;
+} mmc_info;
+
+static mmc_info mmcinfo;
+
+struct mmc_request
+{
+ int index; /* Slot index - used for CS lines */
+ int cmd; /* Command to send */
+ unsigned int arg; /* Argument to send */
+ enum mmc_rsp_t rtype; /* Response type expected */
+
+ /* Data transfer (these may be modified at the low level) */
+ unsigned short nob; /* Number of blocks to transfer*/
+ unsigned short block_len; /* Block length */
+ unsigned char *buffer; /* Data buffer */
+ unsigned int cnt; /* Data length, for PIO */
+
+ /* Results */
+ unsigned char response[18]; /* Buffer to store response - CRC is optional */
+ enum mmc_result_t result;
+};
+
+#define MMC_OCR_ARG 0x00ff8000 /* Argument of OCR */
+
+/***********************************************************************
+ * MMC Events
+ */
+#define MMC_EVENT_NONE 0x00 /* No events */
+#define MMC_EVENT_RX_DATA_DONE 0x01 /* Rx data done */
+#define MMC_EVENT_TX_DATA_DONE 0x02 /* Tx data done */
+#define MMC_EVENT_PROG_DONE 0x04 /* Programming is done */
+
+static int use_4bit; /* Use 4-bit data bus */
+static int num_6;
+static int sd2_0;
+
+/* Stop the MMC clock and wait while it happens */
+static inline int jz_mmc_stop_clock(void)
+{
+ int timeout = 1000;
+
+ DEBUG("stop MMC clock");
+ REG_MSC_STRPCL = MSC_STRPCL_CLOCK_CONTROL_STOP;
+
+ while (timeout && (REG_MSC_STAT & MSC_STAT_CLK_EN))
+ {
+ timeout--;
+ if (timeout == 0)
+ {
+ DEBUG("Timeout on stop clock waiting");
+ return MMC_ERROR_TIMEOUT;
+ }
+ udelay(1);
+ }
+ DEBUG("clock off time is %d microsec", timeout);
+ return MMC_NO_ERROR;
+}
+
+/* Start the MMC clock and operation */
+static inline int jz_mmc_start_clock(void)
+{
+ REG_MSC_STRPCL =
+ MSC_STRPCL_CLOCK_CONTROL_START | MSC_STRPCL_START_OP;
+ return MMC_NO_ERROR;
+}
+
+static inline unsigned int jz_mmc_calc_clkrt(int is_sd, unsigned int rate)
+{
+ unsigned int clkrt;
+ unsigned int clk_src = is_sd ? 24000000 : 20000000;
+
+ clkrt = 0;
+ while (rate < clk_src)
+ {
+ clkrt++;
+ clk_src >>= 1;
+ }
+ return clkrt;
+}
+
+static int jz_mmc_check_status(struct mmc_request *request)
+{
+ unsigned int status = REG_MSC_STAT;
+
+ /* Checking for response or data timeout */
+ if (status & (MSC_STAT_TIME_OUT_RES | MSC_STAT_TIME_OUT_READ))
+ {
+ DEBUG("MMC/SD timeout, MMC_STAT 0x%x CMD %d", status,
+ request->cmd);
+ return MMC_ERROR_TIMEOUT;
+ }
+
+ /* Checking for CRC error */
+ if (status &
+ (MSC_STAT_CRC_READ_ERROR | MSC_STAT_CRC_WRITE_ERROR |
+ MSC_STAT_CRC_RES_ERR))
+ {
+ DEBUG("MMC/CD CRC error, MMC_STAT 0x%x", status);
+ return MMC_ERROR_CRC;
+ }
+
+ return MMC_NO_ERROR;
+}
+
+/* Obtain response to the command and store it to response buffer */
+static void jz_mmc_get_response(struct mmc_request *request)
+{
+ int i;
+ unsigned char *buf;
+ unsigned int data;
+
+ DEBUG("fetch response for request %d, cmd %d", request->rtype,
+ request->cmd);
+ buf = request->response;
+ request->result = MMC_NO_ERROR;
+
+ switch (request->rtype)
+ {
+ case RESPONSE_R1:
+ case RESPONSE_R1B:
+ case RESPONSE_R6:
+ case RESPONSE_R3:
+ case RESPONSE_R4:
+ case RESPONSE_R5:
+ {
+ data = REG_MSC_RES;
+ buf[0] = (data >> 8) & 0xff;
+ buf[1] = data & 0xff;
+ data = REG_MSC_RES;
+ buf[2] = (data >> 8) & 0xff;
+ buf[3] = data & 0xff;
+ data = REG_MSC_RES;
+ buf[4] = data & 0xff;
+
+ DEBUG("request %d, response [%02x %02x %02x %02x %02x]",
+ request->rtype, buf[0], buf[1], buf[2],
+ buf[3], buf[4]);
+ break;
+ }
+ case RESPONSE_R2_CID:
+ case RESPONSE_R2_CSD:
+ {
+ for (i = 0; i < 16; i += 2)
+ {
+ data = REG_MSC_RES;
+ buf[i] = (data >> 8) & 0xff;
+ buf[i + 1] = data & 0xff;
+ }
+ DEBUG("request %d, response [", request->rtype);
+ break;
+ }
+ case RESPONSE_NONE:
+ DEBUG("No response");
+ break;
+
+ default:
+ DEBUG("unhandled response type for request %d",
+ request->rtype);
+ break;
+ }
+}
+
+#ifdef MMC_DMA_ENABLE
+static int jz_mmc_receive_data_dma(struct mmc_request *req)
+{
+ int ch = RX_DMA_CHANNEL;
+ unsigned int size = req->block_len * req->nob;
+ unsigned char err = 0;
+
+ /* flush dcache */
+ dma_cache_wback_inv((unsigned long) req->buffer, size);
+ /* setup dma channel */
+ REG_DMAC_DSAR(ch) = PHYSADDR(MSC_RXFIFO); /* DMA source addr */
+ REG_DMAC_DTAR(ch) = PHYSADDR((unsigned long) req->buffer); /* DMA dest addr */
+ REG_DMAC_DTCR(ch) = (size + 3) / 4; /* DMA transfer count */
+ REG_DMAC_DRSR(ch) = DMAC_DRSR_RS_MSCIN; /* DMA request type */
+
+#if MMC_DMA_INTERRUPT
+ REG_DMAC_DCMD(ch) =
+ DMAC_DCMD_DAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 |
+ DMAC_DCMD_DS_32BIT | DMAC_DCMD_TIE;
+ REG_DMAC_DCCSR(ch) = DMAC_DCCSR_EN | DMAC_DCCSR_NDES;
+ OSSemPend(mmc_dma_rx_sem, 100, &err);
+#else
+ REG_DMAC_DCMD(ch) =
+ DMAC_DCMD_DAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 |
+ DMAC_DCMD_DS_32BIT;
+ REG_DMAC_DCCSR(ch) = DMAC_DCCSR_EN | DMAC_DCCSR_NDES;
+ while (REG_DMAC_DTCR(ch));
+#endif
+/* clear status and disable channel */
+ REG_DMAC_DCCSR(ch) = 0;
+#if MMC_DMA_INTERRUPT
+ return (err == OS_NO_ERR);
+#else
+ return 0;
+#endif
+}
+
+static int jz_mmc_transmit_data_dma(struct mmc_request *req)
+{
+ int ch = TX_DMA_CHANNEL;
+ unsigned int size = req->block_len * req->nob;
+ unsigned char err = 0;
+
+ /* flush dcache */
+ dma_cache_wback_inv((unsigned long) req->buffer, size);
+ /* setup dma channel */
+ REG_DMAC_DSAR(ch) = PHYSADDR((unsigned long) req->buffer); /* DMA source addr */
+ REG_DMAC_DTAR(ch) = PHYSADDR(MSC_TXFIFO); /* DMA dest addr */
+ REG_DMAC_DTCR(ch) = (size + 3) / 4; /* DMA transfer count */
+ REG_DMAC_DRSR(ch) = DMAC_DRSR_RS_MSCOUT; /* DMA request type */
+
+#if MMC_DMA_INTERRUPT
+ REG_DMAC_DCMD(ch) =
+ DMAC_DCMD_SAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 |
+ DMAC_DCMD_DS_32BIT | DMAC_DCMD_TIE;
+ REG_DMAC_DCCSR(ch) = DMAC_DCCSR_EN | DMAC_DCCSR_NDES;
+ OSSemPend(mmc_dma_tx_sem, 100, &err);
+#else
+ REG_DMAC_DCMD(ch) =
+ DMAC_DCMD_SAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 |
+ DMAC_DCMD_DS_32BIT;
+ REG_DMAC_DCCSR(ch) = DMAC_DCCSR_EN | DMAC_DCCSR_NDES;
+ /* wait for dma completion */
+ while (REG_DMAC_DTCR(ch));
+#endif
+ /* clear status and disable channel */
+ REG_DMAC_DCCSR(ch) = 0;
+#if MMC_DMA_INTERRUPT
+ return (err == OS_NO_ERR);
+#else
+ return 0;
+#endif
+}
+
+#endif /* MMC_DMA_ENABLE */
+
+static int jz_mmc_receive_data(struct mmc_request *req)
+{
+ unsigned int nob = req->nob;
+ unsigned int wblocklen = (unsigned int) (req->block_len + 3) >> 2; /* length in word */
+ unsigned char *buf = req->buffer;
+ unsigned int *wbuf = (unsigned int *) buf;
+ unsigned int waligned = (((unsigned int) buf & 0x3) == 0); /* word aligned ? */
+ unsigned int stat, timeout, data, cnt;
+
+ for (; nob >= 1; nob--)
+ {
+ timeout = 0x3FFFFFF;
+
+ while (timeout)
+ {
+ timeout--;
+ stat = REG_MSC_STAT;
+
+ if (stat & MSC_STAT_TIME_OUT_READ)
+ return MMC_ERROR_TIMEOUT;
+ else if (stat & MSC_STAT_CRC_READ_ERROR)
+ return MMC_ERROR_CRC;
+ else if (!(stat & MSC_STAT_DATA_FIFO_EMPTY)
+ || (stat & MSC_STAT_DATA_FIFO_AFULL)) {
+ /* Ready to read data */
+ break;
+ }
+
+ udelay(1);
+ }
+
+ if (!timeout)
+ return MMC_ERROR_TIMEOUT;
+
+ /* Read data from RXFIFO. It could be FULL or PARTIAL FULL */
+ DEBUG("Receive Data = %d", wblocklen);
+ cnt = wblocklen;
+ while (cnt)
+ {
+ data = REG_MSC_RXFIFO;
+ if (waligned)
+ *wbuf++ = data;
+ else
+ {
+ *buf++ = (unsigned char) (data >> 0);
+ *buf++ = (unsigned char) (data >> 8);
+ *buf++ = (unsigned char) (data >> 16);
+ *buf++ = (unsigned char) (data >> 24);
+ }
+ cnt--;
+ while (cnt
+ && (REG_MSC_STAT &
+ MSC_STAT_DATA_FIFO_EMPTY));
+ }
+ }
+
+ return MMC_NO_ERROR;
+}
+
+static int jz_mmc_transmit_data(struct mmc_request *req)
+{
+ unsigned int nob = req->nob;
+ unsigned int wblocklen = (unsigned int) (req->block_len + 3) >> 2; /* length in word */
+ unsigned char *buf = req->buffer;
+ unsigned int *wbuf = (unsigned int *) buf;
+ unsigned int waligned = (((unsigned int) buf & 0x3) == 0); /* word aligned ? */
+ unsigned int stat, timeout, data, cnt;
+
+ for (; nob >= 1; nob--)
+ {
+ timeout = 0x3FFFFFF;
+
+ while (timeout)
+ {
+ timeout--;
+ stat = REG_MSC_STAT;
+
+ if (stat &
+ (MSC_STAT_CRC_WRITE_ERROR |
+ MSC_STAT_CRC_WRITE_ERROR_NOSTS))
+ return MMC_ERROR_CRC;
+ else if (!(stat & MSC_STAT_DATA_FIFO_FULL))
+ {
+ /* Ready to write data */
+ break;
+ }
+
+ udelay(1);
+ }
+
+ if (!timeout)
+ return MMC_ERROR_TIMEOUT;
+
+ /* Write data to TXFIFO */
+ cnt = wblocklen;
+ while (cnt)
+ {
+ while (REG_MSC_STAT & MSC_STAT_DATA_FIFO_FULL);
+
+ if (waligned)
+ REG_MSC_TXFIFO = *wbuf++;
+ else
+ {
+ data = *buf++;
+ data |= *buf++ << 8;
+ data |= *buf++ << 16;
+ data |= *buf++ << 24;
+ REG_MSC_TXFIFO = data;
+ }
+
+ cnt--;
+ }
+ }
+
+ return MMC_NO_ERROR;
+}
+
+/* Set the MMC clock frequency */
+static void jz_mmc_set_clock(int sd, unsigned int rate)
+{
+ int clkrt = 0;
+
+ sd = sd ? 1 : 0;
+
+ jz_mmc_stop_clock();
+
+ if(sd2_0)
+ {
+ __cpm_select_msc_hs_clk(sd); /* select clock source from CPM */
+ REG_CPM_CPCCR |= CPM_CPCCR_CE;
+ REG_MSC_CLKRT = 0;
+ }
+ else
+ {
+ __cpm_select_msc_clk(sd); /* select clock source from CPM */
+ REG_CPM_CPCCR |= CPM_CPCCR_CE;
+ clkrt = jz_mmc_calc_clkrt(sd, rate);
+ REG_MSC_CLKRT = clkrt;
+ }
+ DEBUG("set clock to %u Hz is_sd=%d clkrt=%d", rate, sd, clkrt);
+}
+
+/********************************************************************************************************************
+** Name: int jz_mmc_exec_cmd()
+** Function: send command to the card, and get a response
+** Input: struct mmc_request *req: MMC/SD request
+** Output: 0: right >0: error code
+********************************************************************************************************************/
+static int jz_mmc_exec_cmd(struct mmc_request *request)
+{
+ unsigned int cmdat = 0, events = 0;
+ int retval, timeout = 0x3fffff;
+
+ /* Indicate we have no result yet */
+ request->result = MMC_NO_RESPONSE;
+ if (request->cmd == MMC_CIM_RESET)
+ {
+ /* On reset, 1-bit bus width */
+ use_4bit = 0;
+
+ /* Reset MMC/SD controller */
+ __msc_reset();
+
+ /* On reset, drop MMC clock down */
+ jz_mmc_set_clock(0, MMC_CLOCK_SLOW);
+
+ /* On reset, stop MMC clock */
+ jz_mmc_stop_clock();
+ }
+ if (request->cmd == MMC_SEND_OP_COND)
+ {
+ DEBUG("Have a MMC card");
+ /* always use 1bit for MMC */
+ use_4bit = 0;
+ }
+ if (request->cmd == SET_BUS_WIDTH)
+ {
+ if (request->arg == 0x2)
+ {
+ DEBUG("Use 4-bit bus width");
+ use_4bit = 1;
+ }
+ else
+ {
+ DEBUG("Use 1-bit bus width");
+ use_4bit = 0;
+ }
+ }
+
+ /* stop clock */
+ jz_mmc_stop_clock();
+
+ /* mask all interrupts */
+ //REG_MSC_IMASK = 0xffff;
+ /* clear status */
+ REG_MSC_IREG = 0xffff;
+ /*open interrupt */
+ REG_MSC_IMASK = (~7);
+ /* use 4-bit bus width when possible */
+ if (use_4bit)
+ cmdat |= MSC_CMDAT_BUS_WIDTH_4BIT;
+
+ /* Set command type and events */
+ switch (request->cmd)
+ {
+ /* MMC core extra command */
+ case MMC_CIM_RESET:
+ cmdat |= MSC_CMDAT_INIT; /* Initialization sequence sent prior to command */
+ break;
+
+ /* bc - broadcast - no response */
+ case MMC_GO_IDLE_STATE:
+ case MMC_SET_DSR:
+ break;
+
+ /* bcr - broadcast with response */
+ case MMC_SEND_OP_COND:
+ case MMC_ALL_SEND_CID:
+
+ case MMC_GO_IRQ_STATE:
+ break;
+
+ /* adtc - addressed with data transfer */
+ case MMC_READ_DAT_UNTIL_STOP:
+ case MMC_READ_SINGLE_BLOCK:
+ case MMC_READ_MULTIPLE_BLOCK:
+ case SEND_SCR:
+#if defined(MMC_DMA_ENABLE)
+ cmdat |=
+ MSC_CMDAT_DATA_EN | MSC_CMDAT_READ | MSC_CMDAT_DMA_EN;
+#else
+ cmdat |= MSC_CMDAT_DATA_EN | MSC_CMDAT_READ;
+#endif
+ events = MMC_EVENT_RX_DATA_DONE;
+ break;
+
+ case 6:
+ if (num_6 < 2)
+ {
+
+#if defined(MMC_DMA_ENABLE)
+ cmdat |=
+ MSC_CMDAT_DATA_EN | MSC_CMDAT_READ |
+ MSC_CMDAT_DMA_EN;
+#else
+ cmdat |= MSC_CMDAT_DATA_EN | MSC_CMDAT_READ;
+#endif
+ events = MMC_EVENT_RX_DATA_DONE;
+ }
+ break;
+
+ case MMC_WRITE_DAT_UNTIL_STOP:
+ case MMC_WRITE_BLOCK:
+ case MMC_WRITE_MULTIPLE_BLOCK:
+ case MMC_PROGRAM_CID:
+ case MMC_PROGRAM_CSD:
+ case MMC_SEND_WRITE_PROT:
+ case MMC_GEN_CMD:
+ case MMC_LOCK_UNLOCK:
+#if defined(MMC_DMA_ENABLE)
+ cmdat |=
+ MSC_CMDAT_DATA_EN | MSC_CMDAT_WRITE | MSC_CMDAT_DMA_EN;
+#else
+ cmdat |= MSC_CMDAT_DATA_EN | MSC_CMDAT_WRITE;
+#endif
+ events = MMC_EVENT_TX_DATA_DONE | MMC_EVENT_PROG_DONE;
+ break;
+
+ case MMC_STOP_TRANSMISSION:
+ events = MMC_EVENT_PROG_DONE;
+ break;
+
+ /* ac - no data transfer */
+ default:
+ break;
+ }
+
+ /* Set response type */
+ switch (request->rtype)
+ {
+ case RESPONSE_NONE:
+ break;
+ case RESPONSE_R1B:
+ cmdat |= MSC_CMDAT_BUSY;
+ /*FALLTHRU*/
+ case RESPONSE_R1:
+ cmdat |= MSC_CMDAT_RESPONSE_R1;
+ break;
+ case RESPONSE_R2_CID:
+ case RESPONSE_R2_CSD:
+ cmdat |= MSC_CMDAT_RESPONSE_R2;
+ break;
+ case RESPONSE_R3:
+ cmdat |= MSC_CMDAT_RESPONSE_R3;
+ break;
+ case RESPONSE_R4:
+ cmdat |= MSC_CMDAT_RESPONSE_R4;
+ break;
+ case RESPONSE_R5:
+ cmdat |= MSC_CMDAT_RESPONSE_R5;
+ break;
+ case RESPONSE_R6:
+ cmdat |= MSC_CMDAT_RESPONSE_R6;
+ break;
+ default:
+ break;
+ }
+
+ /* Set command index */
+ if (request->cmd == MMC_CIM_RESET)
+ REG_MSC_CMD = MMC_GO_IDLE_STATE;
+ else
+ REG_MSC_CMD = request->cmd;
+
+ /* Set argument */
+ REG_MSC_ARG = request->arg;
+
+ /* Set block length and nob */
+ if (request->cmd == SEND_SCR)
+ { /* get SCR from DataFIFO */
+ REG_MSC_BLKLEN = 8;
+ REG_MSC_NOB = 1;
+ }
+ else
+ {
+ REG_MSC_BLKLEN = request->block_len;
+ REG_MSC_NOB = request->nob;
+ }
+
+ /* Set command */
+ REG_MSC_CMDAT = cmdat;
+
+ DEBUG("Send cmd %d cmdat: %x arg: %x resp %d", request->cmd,
+ cmdat, request->arg, request->rtype);
+
+ /* Start MMC/SD clock and send command to card */
+ jz_mmc_start_clock();
+
+ /* Wait for command completion */
+ //__intc_unmask_irq(IRQ_MSC);
+ //wakeup_wait(&sd_wakeup, 100);
+ while (timeout-- && !(REG_MSC_STAT & MSC_STAT_END_CMD_RES));
+
+
+ if (timeout == 0)
+ return MMC_ERROR_TIMEOUT;
+
+ REG_MSC_IREG = MSC_IREG_END_CMD_RES; /* clear flag */
+
+ /* Check for status */
+ retval = jz_mmc_check_status(request);
+ if (retval)
+ return retval;
+
+ /* Complete command with no response */
+ if (request->rtype == RESPONSE_NONE)
+ return MMC_NO_ERROR;
+
+ /* Get response */
+ jz_mmc_get_response(request);
+
+ /* Start data operation */
+ if (events & (MMC_EVENT_RX_DATA_DONE | MMC_EVENT_TX_DATA_DONE))
+ {
+ if (events & MMC_EVENT_RX_DATA_DONE)
+ {
+ if (request->cmd == SEND_SCR)
+ {
+ /* SD card returns SCR register as data.
+ MMC core expect it in the response buffer,
+ after normal response. */
+ request->buffer =
+ (unsigned char *) ((unsigned int) request->response + 5);
+ }
+#ifdef MMC_DMA_ENABLE
+ jz_mmc_receive_data_dma(request);
+#else
+ jz_mmc_receive_data(request);
+#endif
+ }
+
+ if (events & MMC_EVENT_TX_DATA_DONE)
+ {
+#ifdef MMC_DMA_ENABLE
+ jz_mmc_transmit_data_dma(request);
+#else
+ jz_mmc_transmit_data(request);
+#endif
+ }
+ //__intc_unmask_irq(IRQ_MSC);
+ //wakeup_wait(&sd_wakeup, 100);
+ /* Wait for Data Done */
+ while (!(REG_MSC_IREG & MSC_IREG_DATA_TRAN_DONE));
+ REG_MSC_IREG = MSC_IREG_DATA_TRAN_DONE; /* clear status */
+
+ }
+
+ /* Wait for Prog Done event */
+ if (events & MMC_EVENT_PROG_DONE)
+ {
+ //__intc_unmask_irq(IRQ_MSC);
+ //wakeup_wait(&sd_wakeup, 100);
+ while (!(REG_MSC_IREG & MSC_IREG_PRG_DONE));
+ REG_MSC_IREG = MSC_IREG_PRG_DONE; /* clear status */
+ }
+
+ /* Command completed */
+
+ return MMC_NO_ERROR; /* return successfully */
+}
+
+/*******************************************************************************************************************
+** Name: int mmc_chkcard()
+** Function: check whether card is insert entirely
+** Input: NULL
+** Output: 1: insert entirely 0: not insert entirely
+********************************************************************************************************************/
+static int jz_mmc_chkcard(void)
+{
+ if (MMC_INSERT_STATUS() == 0)
+ return 1; /* insert entirely */
+ else
+ return 0; /* not insert entirely */
+}
+
+#if MMC_DMA_INTERRUPT
+static void jz_mmc_tx_handler(unsigned int arg)
+{
+ if (__dmac_channel_address_error_detected(arg))
+ {
+ DEBUG("%s: DMAC address error.", __FUNCTION__);
+ __dmac_channel_clear_address_error(arg);
+ }
+ if (__dmac_channel_transmit_end_detected(arg))
+ {
+
+ __dmac_channel_clear_transmit_end(arg);
+ OSSemPost(mmc_dma_tx_sem);
+ }
+}
+
+static void jz_mmc_rx_handler(unsigned int arg)
+{
+ if (__dmac_channel_address_error_detected(arg))
+ {
+ DEBUG("%s: DMAC address error.", __FUNCTION__);
+ __dmac_channel_clear_address_error(arg);
+ }
+ if (__dmac_channel_transmit_end_detected(arg))
+ {
+ __dmac_channel_clear_transmit_end(arg);
+ OSSemPost(mmc_dma_rx_sem);
+ }
+}
+#endif
+
+/* MSC interrupt handler */
+void MSC(void)
+{
+ //wakeup_signal(&sd_wakeup);
+}
+
+/*******************************************************************************************************************
+** Name: void mmc_hardware_init()
+** Function: initialize the hardware condiction that access sd card
+** Input: NULL
+** Output: NULL
+********************************************************************************************************************/
+static void jz_mmc_hardware_init(void)
+{
+ mmc_init_gpio(); /* init GPIO */
+ MMC_POWER_ON(); /* turn on power of card */
+ MMC_RESET(); /* reset mmc/sd controller */
+ MMC_IRQ_MASK(); /* mask all IRQs */
+ jz_mmc_stop_clock(); /* stop MMC/SD clock */
+#ifdef MMC_DMA_ENABLE
+ __cpm_start_dmac();
+ __dmac_enable_module();
+// REG_DMAC_DMACR = DMAC_DMACR_DME;
+#if MMC_DMA_INTERRUPT
+ mmc_dma_rx_sem = OSSemCreate(0);
+ mmc_dma_tx_sem = OSSemCreate(0);
+ request_irq(IRQ_DMA_0 + RX_DMA_CHANNEL, jz_mmc_rx_handler,
+ RX_DMA_CHANNEL);
+ request_irq(IRQ_DMA_0 + TX_DMA_CHANNEL, jz_mmc_tx_handler,
+ TX_DMA_CHANNEL);
+#endif
+#endif
+}
+
+static void mmc_send_cmd(struct mmc_request *request, int cmd, unsigned int arg,
+ unsigned short nob, unsigned short block_len,
+ enum mmc_rsp_t rtype, unsigned char* buffer)
+{
+ request->cmd = cmd;
+ request->arg = arg;
+ request->rtype = rtype;
+ request->nob = nob;
+ request->block_len = block_len;
+ request->buffer = buffer;
+ request->cnt = nob * block_len;
+ printf("mmc_send_cmd: command = %d",cmd);
+ jz_mmc_exec_cmd(request);
+}
+
+static bool inited = false;
+int sd_init(void)
+{
+ if(!inited)
+ {
+ jz_mmc_hardware_init();
+ wakeup_init(&sd_wakeup);
+ inited = true;
+ }
+
+ struct mmc_request test;
+ //mmc_send_cmd(&test, MMC_CIM_RESET, 0, 0, 0, RESPONSE_NONE, NULL);
+ mmc_send_cmd(&test, MMC_GO_IDLE_STATE, 0, 0, 0, RESPONSE_NONE, NULL);
+ mmc_send_cmd(&test, SD_SEND_OP_COND, MMC_OCR_ARG, 0, 0, RESPONSE_R3, NULL);
+
+ return 0;
+}
+
+bool card_detect_target(void)
+{
+ return jz_mmc_chkcard() == 1;
+}
+
+#ifdef HAVE_HOTSWAP
+void card_enable_monitoring_target(bool on)
+{
+ if(on)
+ {
+
+ }
+ else
+ {
+
+ }
+}
+#endif
+
+/* TODO */
+tCardInfo* card_get_info_target(int card_no)
+{
+ static tCardInfo card;
+
+ return &card;
+}
+
+/* TODO */
+int sd_read_sectors(unsigned long start, int count, void* buf)
+{
+ (void)start;
+ (void)count;
+ (void)buf;
+ return -1;
+}
+
+/* TODO */
+int sd_write_sectors(unsigned long start, int count, const void* buf)
+{
+ (void)start;
+ (void)count;
+ (void)buf;
+ return -1;
+}
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 0000000..f788fd6
--- /dev/null
+++ b/firmware/target/mips/ingenic_jz47xx/ata-sd-target.h
@@ -0,0 +1,39 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2008 by Maurus Cuelenaere
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef ATA_SD_TARGET_H
+#define ATA_SD_TARGET_H
+
+#include "inttypes.h"
+#include "hotswap.h"
+
+tCardInfo *card_get_info_target(int card_no);
+bool card_detect_target(void);
+
+#ifdef HAVE_HOTSWAP
+void card_enable_monitoring_target(bool on);
+void microsd_int(void); /* ??? */
+#endif
+
+int sd_read_sectors(unsigned long start, int count, void* buf);
+int sd_write_sectors(unsigned long start, int count, const void* buf);
+int sd_init(void);
+
+#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 0000000..6c3ed8c
--- /dev/null
+++ b/firmware/target/mips/ingenic_jz47xx/codec-jz4740.c
@@ -0,0 +1,280 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2008 by Maurus Cuelenaere
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "config.h"
+#include "jz4740.h"
+
+static unsigned short codec_volume;
+static unsigned short codec_base_gain;
+static unsigned short codec_mic_gain;
+static bool HP_on_off_flag;
+static int HP_register_value;
+static int IS_WRITE_PCM;
+
+static void i2s_codec_clear(void)
+{
+ REG_ICDC_CDCCR1 = (ICDC_CDCCR1_SW2ON | ICDC_CDCCR1_PDVR | ICDC_CDCCR1_PDVRA | ICDC_CDCCR1_VRCGL |
+ ICDC_CDCCR1_VRCGH | ICDC_CDCCR1_HPOV0 | ICDC_CDCCR1_PDHPM | ICDC_CDCCR1_PDHP |
+ ICDC_CDCCR1_SUSPD | ICDC_CDCCR1_RST);
+}
+
+static void i2s_codec_init(void)
+{
+ __aic_select_i2s();
+ __i2s_internal_codec();
+
+ __aic_enable();
+
+ __i2s_set_oss_sample_size(16);
+
+ REG_ICDC_CDCCR1 = (ICDC_CDCCR1_SW2ON | ICDC_CDCCR1_PDVR | ICDC_CDCCR1_PDVRA | ICDC_CDCCR1_VRCGL |
+ ICDC_CDCCR1_VRCGH | ICDC_CDCCR1_HPOV0 | ICDC_CDCCR1_PDHPM | ICDC_CDCCR1_PDHP |
+ ICDC_CDCCR1_SUSPD | ICDC_CDCCR1_RST); /* reset */
+ udelay(10);
+ REG_ICDC_CDCCR1 = (ICDC_CDCCR1_SW2ON | ICDC_CDCCR1_PDVR | ICDC_CDCCR1_PDVRA | ICDC_CDCCR1_VRCGL |
+ ICDC_CDCCR1_VRCGH | ICDC_CDCCR1_HPOV0 | ICDC_CDCCR1_PDHPM | ICDC_CDCCR1_PDHP |
+ ICDC_CDCCR1_SUSPD | ICDC_CDCCR1_RST);
+ //REG_ICDC_CDCCR2 = (ICDC_CDCCR2_AINVOL(ICDC_CDCCR2_AINVOL_DB(0)) | ICDC_CDCCR2_SMPR(ICDC_CDCCR2_SMPR_48) |
+ REG_ICDC_CDCCR2 = (ICDC_CDCCR2_AINVOL(23) | ICDC_CDCCR2_SMPR(ICDC_CDCCR2_SMPR_48) |
+ ICDC_CDCCR2_HPVOL(ICDC_CDCCR2_HPVOL_6));
+ HP_on_off_flag = 0; /* HP is off */
+}
+
+static void i2s_codec_set_mic(unsigned short v) /* 0 <= v <= 100 */
+{
+ v = v & 0xff;
+ if(v < 0)
+ v = 0;
+ if(v > 100)
+ v = 100;
+ codec_mic_gain = 31 * v/100;
+
+ REG_ICDC_CDCCR2 = ((REG_ICDC_CDCCR2 & ~(0x1f << 16)) | (codec_mic_gain << 16));
+}
+
+static void i2s_codec_set_bass(unsigned short v) /* 0 <= v <= 100 */
+{
+ v = v & 0xff;
+ if(v < 0)
+ v = 0;
+ if(v > 100)
+ v = 100;
+
+ if(v < 25)
+ codec_base_gain = 0;
+ if(v >= 25 && v < 50)
+ codec_base_gain = 1;
+ if(v >= 50 && v < 75)
+ codec_base_gain = 2;
+ if(v >= 75 && v <= 100)
+ codec_base_gain = 3;
+
+ REG_ICDC_CDCCR2 = ((REG_ICDC_CDCCR2 & ~(0x3 << 4)) | (codec_base_gain << 4));
+}
+
+static void i2s_codec_set_volume(unsigned short v) /* 0 <= v <= 100 */
+{
+ v = v & 0xff;
+ if(v < 0)
+ v = 0;
+ if(v > 100)
+ v = 100;
+
+ if(v < 25)
+ codec_volume = 0;
+ if(v >= 25 && v < 50)
+ codec_volume = 1;
+ if(v >= 50 && v < 75)
+ codec_volume = 2;
+ if(v >= 75 && v <= 100)
+ codec_volume = 3;
+
+ REG_ICDC_CDCCR2 = ((REG_ICDC_CDCCR2 & ~(0x3)) | codec_volume);
+}
+
+static unsigned short i2s_codec_get_bass(void)
+{
+ unsigned short val;
+ int ret;
+ if(codec_base_gain == 0)
+ val = 0;
+ if(codec_base_gain == 1)
+ val = 25;
+ if(codec_base_gain == 2)
+ val = 50;
+ if(codec_base_gain == 3)
+ val = 75;
+
+ ret = val << 8;
+ val = val | ret;
+}
+
+static unsigned short i2s_codec_get_mic(void)
+{
+ unsigned short val;
+ int ret;
+ val = 100 * codec_mic_gain / 31;
+ ret = val << 8;
+ val = val | ret;
+}
+
+static unsigned short i2s_codec_get_volume(void)
+{
+ unsigned short val;
+ int ret;
+
+ if(codec_volume == 0)
+ val = 0;
+ if(codec_volume == 1)
+ val = 25;
+ if(codec_volume == 2)
+ val = 50;
+ if(codec_volume == 3)
+ val = 75;
+
+ ret = val << 8;
+ val = val | ret;
+ return val;
+}
+
+static void i2s_codec_set_samplerate(unsigned short rate)
+{
+ unsigned short speed = 0;
+ unsigned short val = 0;
+
+ switch (rate)
+ {
+ case 8000:
+ speed = 0;
+ break;
+ case 11025:
+ speed = 1;
+ break;
+ case 12000:
+ speed = 2;
+ break;
+ case 16000:
+ speed = 3;
+ break;
+ case 22050:
+ speed = 4;
+ break;
+ case 24000:
+ speed = 5;
+ break;
+ case 32000:
+ speed = 6;
+ break;
+ case 44100:
+ speed = 7;
+ break;
+ case 48000:
+ speed = 8;
+ break;
+ default:
+ break;
+ }
+ REG_ICDC_CDCCR2 |= 0x00000f00;
+ speed = speed << 8;
+
+ speed |= 0xfffff0ff;
+ REG_ICDC_CDCCR2 &= speed;
+}
+
+static void HP_turn_on(void)
+{
+ //see 1.3.4.1
+
+ REG_ICDC_CDCCR1 &= ~(ICDC_CDCCR1_SUSPD | ICDC_CDCCR1_RST); //set suspend 0
+
+ mdelay(15);
+ REG_ICDC_CDCCR1 &= ~(ICDC_CDCCR1_PDVR | ICDC_CDCCR1_VRCGL | ICDC_CDCCR1_VRCGH);
+ REG_ICDC_CDCCR1 |= (ICDC_CDCCR1_EDAC | ICDC_CDCCR1_HPCG);
+
+ mdelay(600);
+ REG_ICDC_CDCCR1 &= ~(ICDC_CDCCR1_PDVRA | ICDC_CDCCR1_HPCG | ICDC_CDCCR1_PDHPM | ICDC_CDCCR1_PDHP);
+
+ mdelay(2);
+ HP_register_value = REG_ICDC_CDCCR1;
+
+ //see 1.3.4.2
+ /*REG_ICDC_CDCCR1 &= 0xfffffffc;
+ mdelay(7);
+ REG_ICDC_CDCCR1 |= 0x00040400;
+ mdelay(15);
+ REG_ICDC_CDCCR1 &= 0xfffbfbff;
+ udelay(500);
+ REG_ICDC_CDCCR1 &= 0xffe5fcff;
+ REG_ICDC_CDCCR1 |= 0x01000000;
+ mdelay(400);
+ REG_ICDC_CDCCR1 &= 0xfffeffff;
+ mdelay(7);
+ HP_register_value = REG_ICDC_CDCCR1;*/
+
+ //see 1.3.4.3
+
+}
+
+
+static void HP_turn_off(void)
+{
+ //see 1.3.4.1
+ mdelay(2);
+ REG_ICDC_CDCCR1 = HP_register_value;
+ REG_ICDC_CDCCR1 |= 0x001b0300;
+ REG_ICDC_CDCCR1 &= 0xfeffffff;
+
+ mdelay(15);
+ REG_ICDC_CDCCR1 |= 0x00000002;//set suspend 1
+
+ //see 1.3.4.2
+ /*mdelay(4);
+ REG_ICDC_CDCCR1 = HP_register_value;
+ REG_ICDC_CDCCR1 |= 0x001b0300;
+ REG_ICDC_CDCCR1 &= 0xfeffffff;
+ mdelay(4);
+ REG_ICDC_CDCCR1 |= 0x00000400;
+ mdelay(15);
+ REG_ICDC_CDCCR1 &= 0xfffffdff;
+ mdelay(7);
+ REG_ICDC_CDCCR1 |= 0x00000002;*/
+
+ //see 1.3.4.3
+
+}
+
+void audiohw_mute(bool mute)
+{
+ if(mute)
+ REG_ICDC_CDCCR1 |= ICDC_CDCCR1_HPMUTE;
+ else
+ REG_ICDC_CDCCR1 &= ~ICDC_CDCCR1_HPMUTE;
+}
+
+void audiohw_preinit(void)
+{
+ i2s_reset();
+}
+
+void audiohw_postinit(void)
+{
+ audiohw_mute(false);
+}
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 0f1cfca..64ea861 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 @@
#include "jz4740.h"
#include "button.h"
#include "button-target.h"
+#include "powermgmt.h"
#define BTN_OFF (1 << 29)
#define BTN_VOL_DOWN (1 << 27)
@@ -49,15 +50,61 @@
static short x_pos = -1, y_pos = -1, datacount = 0;
static bool pen_down = false;
static int cur_touch = 0;
+static unsigned short bat_val = 0;
static enum touchscreen_mode current_mode = TOUCHSCREEN_POINT;
-static int touchscreen_buttons[3][3] =
+static const int touchscreen_buttons[3][3] =
{
{BUTTON_TOPLEFT, BUTTON_TOPMIDDLE, BUTTON_TOPRIGHT},
{BUTTON_MIDLEFT, BUTTON_CENTER, BUTTON_MIDRIGHT},
{BUTTON_BOTTOMLEFT, BUTTON_BOTTOMMIDDLE, BUTTON_BOTTOMRIGHT}
};
+const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] =
+{
+ /* TODO */
+ 3400
+};
+
+const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] =
+{
+ /* TODO */
+ 3300
+};
+
+/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */
+const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
+{
+ /* TODO */
+ { 3300, 3680, 3740, 3760, 3780, 3810, 3870, 3930, 3970, 4070, 4160 },
+};
+
+/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */
+const unsigned short percent_to_volt_charge[11] =
+{
+ /* TODO */
+ 3300, 3680, 3740, 3760, 3780, 3810, 3870, 3930, 3970, 4070, 4160
+};
+
+/* VBAT = (BDATA/4096) * 7.5V */
+#define BATTERY_SCALE_FACTOR 7500
+
+/* Returns battery voltage from ADC [millivolts] */
+unsigned int battery_adc_voltage(void)
+{
+ register unsigned short dummy;
+ dummy = REG_SADC_BATDAT;
+ dummy = REG_SADC_BATDAT;
+
+ bat_val = 0;
+ REG_SADC_ENA |= SADC_ENA_PBATEN;
+
+ while(bat_val == 0)
+ yield();
+
+ return (bat_val*BATTERY_SCALE_FACTOR)>>12;
+}
+
void button_init_device(void)
{
REG_SADC_ENA = 0;
@@ -72,8 +119,8 @@ void button_init_device(void)
REG_SADC_SAMETIME = 350;
REG_SADC_WAITTIME = 100;
REG_SADC_STATE &= (~REG_SADC_STATE);
- REG_SADC_CTRL &= (~(SADC_CTRL_PENDM | SADC_CTRL_PENUM | SADC_CTRL_TSRDYM));
- REG_SADC_ENA = SADC_ENA_TSEN; //| SADC_ENA_PBATEN | SADC_ENA_SADCINEN);
+ REG_SADC_CTRL = (~(SADC_CTRL_PENDM | SADC_CTRL_PENUM | SADC_CTRL_TSRDYM | SADC_CTRL_PBATRDYM));
+ REG_SADC_ENA = (SADC_ENA_TSEN | SADC_ENA_PBATEN);
__gpio_as_input(32*3 + 29);
__gpio_as_input(32*3 + 27);
@@ -231,6 +278,7 @@ void SADC(void)
}
if(state & SADC_CTRL_PBATRDYM)
{
+ bat_val = REG_SADC_BATDAT;
/* Battery AD IRQ */
}
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 0000000..a5cc61b
--- /dev/null
+++ b/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c
@@ -0,0 +1,164 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2008 by Maurus Cuelenaere
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "system.h"
+#include "kernel.h"
+#include "logf.h"
+#include "audio.h"
+#include "sound.h"
+#include "pcm.h"
+#include "jz4740.h"
+
+/****************************************************************************
+ ** Playback DMA transfer
+ **/
+
+void pcm_postinit(void)
+{
+ audiohw_postinit(); /* implemented not for all codecs */
+ pcm_apply_settings();
+}
+
+const void * pcm_play_dma_get_peak_buffer(int *count)
+{
+ /* TODO */
+ *count = 0;
+ return NULL;
+}
+
+void pcm_play_dma_init(void)
+{
+ /* TODO */
+
+ /* Initialize default register values. */
+ audiohw_init();
+
+ /* Power on */
+ audiohw_enable_output(true);
+
+ /* Unmute the master channel (DAC should be at zero point now). */
+ audiohw_mute(false);
+}
+
+void pcm_apply_settings(void)
+{
+ /* TODO */
+}
+
+void pcm_set_frequency(unsigned int frequency)
+{
+ (void) frequency;
+ /* TODO */
+}
+
+static void play_start_pcm(void)
+{
+ pcm_apply_settings();
+
+ /* TODO */
+}
+
+static void play_stop_pcm(void)
+{
+ /* TODO */
+}
+
+void pcm_play_dma_start(const void *addr, size_t size)
+{
+ (void)addr;
+ (void)size;
+ /* TODO */
+
+ play_start_pcm();
+}
+
+void pcm_play_dma_stop(void)
+{
+ play_stop_pcm();
+
+ /* TODO */
+}
+
+void pcm_play_lock(void)
+{
+ /* TODO */
+}
+
+void pcm_play_unlock(void)
+{
+ /* TODO */
+}
+
+void pcm_play_dma_pause(bool pause)
+{
+ if(pause)
+ play_stop_pcm();
+ else
+ play_start_pcm();
+
+}
+
+size_t pcm_get_bytes_waiting(void)
+{
+ /* TODO */
+ return 0;
+}
+
+#ifdef HAVE_RECORDING
+/* TODO */
+void pcm_rec_dma_init(void)
+{
+}
+
+void pcm_rec_dma_close(void)
+{
+}
+
+void pcm_rec_dma_start(void *addr, size_t size)
+{
+ (void) addr;
+ (void) size;
+}
+
+void pcm_rec_dma_stop(void)
+{
+}
+
+void pcm_rec_lock(void)
+{
+}
+
+void pcm_rec_unlock(void)
+{
+}
+
+const void * pcm_rec_dma_get_peak_buffer(int *count)
+{
+ *count = 0;
+ return NULL;
+}
+
+void pcm_record_more(void *start, size_t size)
+{
+ (void) start;
+ (void) size;
+}
+#endif
diff --git a/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c
index 2121d3e..7cefdad 100644
--- a/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c
+++ b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c
@@ -20,6 +20,7 @@
****************************************************************************/
#include "config.h"
+#include "string.h"
#include "system.h"
#include "usb_ch9.h"
#include "usb_drv.h"
@@ -27,7 +28,7 @@
#include "jz4740.h"
#include "thread.h"
-#if 0
+#if 1
#define EP1_INTR_BIT 2
#define EP_FIFO_NOEMPTY 2
@@ -38,14 +39,327 @@
#define IS_CACHE(x) (x < 0xa0000000)
+#define USB_EP0_IDLE 0
+#define USB_EP0_RX 1
+#define USB_EP0_TX 2
+
+enum ep_type
+{
+ ep_control, ep_bulk, ep_interrupt
+};
+
+struct usb_endpoint
+{
+ void *buf;
+ unsigned int length;
+ void *ptr;
+
+ const enum ep_type type;
+ const bool use_dma;
+ const bool in;
+
+ const void *fifo_addr;
+ unsigned short fifo_size;
+};
+
+static unsigned char ep0_rx_buf[64];
+static unsigned char ep0_tx_buf[64];
+static unsigned char ep0state = USB_EP0_IDLE;
+static struct usb_endpoint endpoints[] =
+{
+ /* buf length ptr type use_dma in fifo_addr fifo_size */
+ {&ep0_rx_buf, 0, &ep0_rx_buf, ep_control, false, true, (void*)USB_FIFO_EP0, 64 },
+ {&ep0_tx_buf, 0, &ep0_tx_buf, ep_control, false, false, (void*)USB_FIFO_EP0, 64 },
+ {NULL, 0, NULL, ep_bulk, true, true, (void*)USB_FIFO_EP1, 512},
+ {NULL, 0, NULL, ep_bulk, true, false, (void*)USB_FIFO_EP1, 512},
+ {NULL, 0, NULL, ep_interrupt, false, true, (void*)USB_FIFO_EP2, 64 }
+};
+
+static inline void select_endpoint(int ep)
+{
+ REG_USB_REG_INDEX = ep;
+}
+
+static void readFIFO(struct usb_endpoint *ep, unsigned int size)
+{
+ unsigned int *d = (unsigned int *)ep->ptr;
+ unsigned int s;
+ s = (size + 3) >> 2;
+ while (s--)
+ *d++ = REG32(ep->fifo_addr);
+}
+
+static void writeFIFO(struct usb_endpoint *ep, unsigned int size)
+{
+ unsigned int *d = (unsigned int *)ep->ptr;
+ unsigned char *c;
+ int s, q;
+
+ if (size > 0)
+ {
+ s = size >> 2;
+ while (s--)
+ REG32(ep->fifo_addr) = *d++;
+
+ q = size & 3;
+ if (q)
+ {
+ c = (unsigned char *)d;
+ while (q--)
+ REG8(ep->fifo_addr) = *c++;
+ }
+ }
+}
+
+static void sendPKT(int ep_nr, const unsigned char* ptr, unsigned int size)
+{
+ struct usb_endpoint *ep = &endpoints[ep_nr];
+
+ if (ep_nr != 0)
+ {
+ ep->buf = (void*)ptr;
+ ep->ptr = (void*)ptr;
+ ep->length = size;
+ select_endpoint(ep_nr);
+ if (size <= ep->fifo_size)
+ {
+ writeFIFO(ep, size);
+ REG_USB_REG_INCSR |= USB_INCSR_INPKTRDY;
+ ep->ptr = ep->buf + size;
+ }
+ else
+ {
+ writeFIFO(ep, ep->fifo_size);
+ REG_USB_REG_INCSR |= USB_INCSR_INPKTRDY;
+ ep->ptr += ep->fifo_size;
+ }
+ }
+ else /* EP0 */
+ {
+ ep->length = size;
+ ep->ptr = ep->buf;
+ memcpy(ep->buf, ptr, size);
+ ep0state = USB_EP0_TX;
+ }
+}
+
+static void getPKT(int ep_nr, const unsigned char *ptr, unsigned int size)
+{
+ struct usb_endpoint *ep = &endpoints[ep_nr];
+
+ memcpy((void*)ptr, ep->ptr, size);
+ if (ep->length > size)
+ ep->length -= size;
+ else
+ {
+ size = ep->length;
+ ep->length = 0;
+ }
+
+ ep->ptr += size;
+}
+
+static void EP0_handler(void)
+{
+ unsigned char csr0;
+
+ /* Read CSR0 */
+ select_endpoint(0);
+ csr0 = REG_USB_REG_CSR0;
+
+ /* Check for SentStall
+ if sentstall is set, clear the sentstall bit
+ */
+ if (csr0 & USB_CSR0_SENTSTALL)
+ {
+ REG_USB_REG_CSR0 = csr0 & ~USB_CSR0_SENTSTALL;
+ ep0state = USB_EP0_IDLE;
+ return;
+ }
+
+ /* Check for SetupEnd */
+ if (csr0 & USB_CSR0_SETUPEND)
+ {
+ REG_USB_REG_CSR0 |= USB_CSR0_SVDSETUPEND;
+ ep0state = USB_EP0_IDLE;
+ return;
+ }
+
+ /* Call relevant routines for endpoint 0 state */
+ if (ep0state == USB_EP0_IDLE)
+ {
+ if (csr0 & USB_CSR0_OUTPKTRDY) /* There is data in the fifo */
+ {
+ readFIFO(&endpoints[0], 8);
+ REG_USB_REG_CSR0 |= USB_CSR0_SVDOUTPKTRDY; /* clear OUTRD bit */
+ usb_core_control_request((struct usb_ctrlrequest*)endpoints[0].buf);
+ }
+ endpoints[0].length = 0;
+ endpoints[0].ptr = endpoints[0].buf;
+ }
+
+ if (ep0state == USB_EP0_TX)
+ {
+ if ((&endpoints[1].ptr - &endpoints[1].buf) <= endpoints[1].fifo_size)
+ {
+ writeFIFO(&endpoints[1], (&endpoints[1].ptr - &endpoints[1].buf));
+ endpoints[1].ptr = &endpoints[1].buf + endpoints[1].length;
+ REG_USB_REG_CSR0 |= (USB_CSR0_INPKTRDY | USB_CSR0_DATAEND); /* Set data end! */
+ ep0state = USB_EP0_IDLE;
+ }
+ else
+ {
+ writeFIFO(&endpoints[1], endpoints[1].fifo_size);
+ REG_USB_REG_CSR0 |= USB_CSR0_INPKTRDY;
+ endpoints[1].ptr += endpoints[1].fifo_size;
+ }
+ }
+}
+
+static void setup_endpoint(struct usb_endpoint *ep)
+{
+ ep->ptr = ep->buf;
+ ep->length = 0;
+
+ if(ep->in)
+ {
+ if(ep->type == ep_bulk)
+ {
+ register int size;
+
+ if((REG_USB_REG_POWER & USB_POWER_HSMODE) == 0)
+ size = 64;
+ else
+ size = 512;
+
+ REG_USB_REG_INMAXP = size;
+ ep->fifo_size = size;
+ }
+ else
+ REG_USB_REG_INMAXP = ep->fifo_size;
+
+ REG_USB_REG_INCSR = 0x2048;
+ }
+ else
+ {
+ REG_USB_REG_OUTMAXP = ep->fifo_size;
+ REG_USB_REG_OUTCSR = 0x0090;
+ }
+}
+
+static void udc_reset(void)
+{
+ register int i;
+
+ /* data init */
+ ep0state = USB_EP0_IDLE;
+
+ /* Disable interrupts */
+ REG_USB_REG_INTRINE = 0;
+ REG_USB_REG_INTROUTE = 0;
+ REG_USB_REG_INTRUSBE = 0;
+
+ REG_USB_REG_FADDR = 0;
+ REG_USB_REG_POWER = 0x60; /* High speed */
+
+ select_endpoint(0);
+ REG_USB_REG_CSR0 = 0xC0;
+
+ for(i=1; i<3; i++)
+ {
+ select_endpoint(i);
+ setup_endpoint(&endpoints[i]);
+ }
+
+ /* enable intr */
+ REG_USB_REG_INTRINE = 0x3;
+ REG_USB_REG_INTROUTE = 0x2;
+ REG_USB_REG_INTRUSBE = 0x4;
+}
+
+/* Interrupt handler */
+void UDC(void)
+{
+ /* Read interrupt registers */
+ unsigned char intrUSB = REG_USB_REG_INTRUSB & 0x07; /* Mask SOF */
+ unsigned short intrIn = REG_USB_REG_INTRIN;
+ unsigned short intrOut = REG_USB_REG_INTROUT;
+ unsigned char intrDMA = REG_USB_REG_INTR;
+
+ if(intrUSB == 0 && intrIn == 0 && intrOut == 0 && intrDMA == 0)
+ return;
+
+ /* EPIN & EPOUT are all handled in DMA */
+ if(intrIn & USB_INTR_EP0)
+ EP0_handler();
+ if(intrUSB & USB_INTR_RESET)
+ udc_reset();
+ if(intrUSB & USB_INTR_SUSPEND);
+ if(intrUSB & USB_INTR_RESUME);
+ if(intrDMA & USB_INTR_DMA_BULKIN)
+ {
+ usb_core_transfer_complete(((REG_USB_REG_CNTL1 >> 4) & 0xF) | USB_DIR_IN, USB_DIR_IN, 0, 0);
+ }
+ if(intrDMA & USB_INTR_DMA_BULKOUT)
+ {
+ usb_core_transfer_complete(((REG_USB_REG_CNTL2 >> 4) & 0xF) | USB_DIR_OUT, USB_DIR_OUT, 0, 0);
+ }
+}
+
+bool usb_drv_stalled(int endpoint, bool in)
+{
+ select_endpoint(endpoint);
+
+ if(endpoint == 0)
+ return (REG_USB_REG_CSR0 & USB_CSR0_SENDSTALL) != 0;
+ else
+ {
+ if(in)
+ return (REG_USB_REG_INCSR & USB_INCSR_SENDSTALL) != 0;
+ else
+ return (REG_USB_REG_OUTCSR & USB_OUTCSR_SENDSTALL) != 0;
+ }
+}
+
+void usb_drv_stall(int endpoint, bool stall, bool in)
+{
+ select_endpoint(endpoint);
+
+ if(endpoint == 0)
+ {
+ if(stall)
+ REG_USB_REG_CSR0 |= USB_CSR0_SENDSTALL;
+ else
+ REG_USB_REG_CSR0 &= ~USB_CSR0_SENDSTALL;
+ }
+ else
+ {
+ if(in)
+ {
+ if(stall)
+ REG_USB_REG_INCSR |= USB_INCSR_SENDSTALL;
+ else
+ REG_USB_REG_INCSR &= ~USB_INCSR_SENDSTALL;
+ }
+ else
+ {
+ if(stall)
+ REG_USB_REG_OUTCSR |= USB_OUTCSR_SENDSTALL;
+ else
+ REG_USB_REG_OUTCSR &= ~USB_OUTCSR_SENDSTALL;
+ }
+ }
+}
+
+
bool usb_drv_connected(void)
{
- return (__gpio_get_pin(GPIO_UDC_DETE)==1);
+ return __gpio_get_pin(GPIO_UDC_DETE) == 1;
}
int usb_detect(void)
{
- if(__gpio_get_pin(GPIO_UDC_DETE)==1)
+ if(__gpio_get_pin(GPIO_UDC_DETE) == 1)
return USB_INSERTED;
else
return USB_EXTRACTED;
@@ -68,49 +382,51 @@ void usb_enable(bool on)
void usb_drv_init(void)
{
- /* Set this bit to allow the UDC entering low-power mode when
- * there are no actions on the USB bus.
- * UDC still works during this bit was set.
- */
- //__cpm_stop_udc();
+ /* Set this bit to allow the UDC entering low-power mode when
+ * there are no actions on the USB bus.
+ * UDC still works during this bit was set.
+ */
+ //__cpm_stop_udc();
__cpm_start_udc();
- /* Enable the USB PHY */
- REG_CPM_SCR |= CPM_SCR_USBPHY_ENABLE;
+ /* Enable the USB PHY */
+ REG_CPM_SCR |= CPM_SCR_USBPHY_ENABLE;
- /* Disable interrupts */
- REG_USB_REG_INTRINE = 0;
- REG_USB_REG_INTROUTE = 0;
- REG_USB_REG_INTRUSBE = 0;
+ /* Disable interrupts */
+ REG_USB_REG_INTRINE = 0;
+ REG_USB_REG_INTROUTE = 0;
+ REG_USB_REG_INTRUSBE = 0;
- /* Enable interrupts */
- REG_USB_REG_INTRINE |= USB_INTR_EP0;
- REG_USB_REG_INTRUSBE |= USB_INTR_RESET;
+ /* Enable interrupts */
+ REG_USB_REG_INTRINE |= USB_INTR_EP0;
+ REG_USB_REG_INTRUSBE |= USB_INTR_RESET;
- /* Enable SUSPEND */
- /* usb_setb(USB_REG_POWER, USB_POWER_SUSPENDM); */
+ /* Enable SUSPEND */
+ /* usb_setb(USB_REG_POWER, USB_POWER_SUSPENDM); */
- /* Enable HS Mode */
+ /* Enable HS Mode */
REG_USB_REG_POWER |= USB_POWER_HSENAB;
- /* Let host detect UDC:
- * Software must write a 1 to the PMR:USB_POWER_SOFTCONN bit to turn this
- * transistor on and pull the USBDP pin HIGH.
- */
- REG_USB_REG_POWER |= USB_POWER_SOFTCONN;
+ /* Let host detect UDC:
+ * Software must write a 1 to the PMR:USB_POWER_SOFTCONN bit to turn this
+ * transistor on and pull the USBDP pin HIGH.
+ */
+ REG_USB_REG_POWER |= USB_POWER_SOFTCONN;
+
+ udc_reset();
}
void usb_drv_exit(void)
{
- /* Disable interrupts */
- REG_USB_REG_INTRINE = 0;
- REG_USB_REG_INTROUTE = 0;
- REG_USB_REG_INTRUSBE = 0;
-
- /* Disable DMA */
- REG_USB_REG_CNTL1 = 0;
- REG_USB_REG_CNTL2 = 0;
+ /* Disable interrupts */
+ REG_USB_REG_INTRINE = 0;
+ REG_USB_REG_INTROUTE = 0;
+ REG_USB_REG_INTRUSBE = 0;
+
+ /* Disable DMA */
+ REG_USB_REG_CNTL1 = 0;
+ REG_USB_REG_CNTL2 = 0;
/* Disconnect from usb */
REG_USB_REG_POWER &= ~USB_POWER_SOFTCONN;
@@ -126,253 +442,248 @@ void usb_drv_set_address(int address)
REG_USB_REG_FADDR = address;
}
-/* Interrupt handler */
-void UDC(void)
-{
-
-}
#else
//------------------------------------------
#ifndef u8
-#define u8 unsigned char
+#define u8 unsigned char
#endif
#ifndef u16
-#define u16 unsigned short
+#define u16 unsigned short
#endif
#ifndef u32
-#define u32 unsigned int
+#define u32 unsigned int
#endif
#ifndef s8
-#define s8 char
+#define s8 char
#endif
#ifndef s16
-#define s16 short
+#define s16 short
#endif
#ifndef s32
-#define s32 int
+#define s32 int
#endif
extern int usbdebug;
enum USB_ENDPOINT_TYPE
{
- ENDPOINT_TYPE_CONTROL,
- /* Typically used to configure a device when attached to the host.
- * It may also be used for other device specific purposes, including
- * control of other pipes on the device.
- */
- ENDPOINT_TYPE_ISOCHRONOUS,
- /* Typically used for applications which need guaranteed speed.
- * Isochronous transfer is fast but with possible data loss. A typical
- * use is audio data which requires a constant data rate.
- */
- ENDPOINT_TYPE_BULK,
- /* Typically used by devices that generate or consume data in relatively
- * large and bursty quantities. Bulk transfer has wide dynamic latitude
- * in transmission constraints. It can use all remaining available bandwidth,
- * but with no guarantees on bandwidth or latency. Since the USB bus is
- * normally not very busy, there is typically 90% or more of the bandwidth
- * available for USB transfers.
- */
- ENDPOINT_TYPE_INTERRUPT
- /* Typically used by devices that need guaranteed quick responses
- * (bounded latency).
- */
+ ENDPOINT_TYPE_CONTROL,
+ /* Typically used to configure a device when attached to the host.
+ * It may also be used for other device specific purposes, including
+ * control of other pipes on the device.
+ */
+ ENDPOINT_TYPE_ISOCHRONOUS,
+ /* Typically used for applications which need guaranteed speed.
+ * Isochronous transfer is fast but with possible data loss. A typical
+ * use is audio data which requires a constant data rate.
+ */
+ ENDPOINT_TYPE_BULK,
+ /* Typically used by devices that generate or consume data in relatively
+ * large and bursty quantities. Bulk transfer has wide dynamic latitude
+ * in transmission constraints. It can use all remaining available bandwidth,
+ * but with no guarantees on bandwidth or latency. Since the USB bus is
+ * normally not very busy, there is typically 90% or more of the bandwidth
+ * available for USB transfers.
+ */
+ ENDPOINT_TYPE_INTERRUPT
+ /* Typically used by devices that need guaranteed quick responses
+ * (bounded latency).
+ */
};
enum USB_STANDARD_REQUEST_CODE {
- GET_STATUS,
- CLEAR_FEATURE,
- SET_FEATURE = 3,
- SET_ADDRESS = 5,
- GET_DESCRIPTOR,
- SET_DESCRIPTOR,
- GET_CONFIGURATION,
- SET_CONFIGURATION,
- GET_INTERFACE,
- SET_INTERFACE,
- SYNCH_FRAME
+ GET_STATUS,
+ CLEAR_FEATURE,
+ SET_FEATURE = 3,
+ SET_ADDRESS = 5,
+ GET_DESCRIPTOR,
+ SET_DESCRIPTOR,
+ GET_CONFIGURATION,
+ SET_CONFIGURATION,
+ GET_INTERFACE,
+ SET_INTERFACE,
+ SYNCH_FRAME
};
enum USB_DESCRIPTOR_TYPE {
- DEVICE_DESCRIPTOR = 1,
- CONFIGURATION_DESCRIPTOR,
- STRING_DESCRIPTOR,
- INTERFACE_DESCRIPTOR,
- ENDPOINT_DESCRIPTOR,
- DEVICE_QUALIFIER_DESCRIPTOR,
- OTHER_SPEED_CONFIGURATION_DESCRIPTOR,
- INTERFACE_POWER1_DESCRIPTOR
+ DEVICE_DESCRIPTOR = 1,
+ CONFIGURATION_DESCRIPTOR,
+ STRING_DESCRIPTOR,
+ INTERFACE_DESCRIPTOR,
+ ENDPOINT_DESCRIPTOR,
+ DEVICE_QUALIFIER_DESCRIPTOR,
+ OTHER_SPEED_CONFIGURATION_DESCRIPTOR,
+ INTERFACE_POWER1_DESCRIPTOR
};
enum USB_FEATURE_SELECTOR {
- ENDPOINT_HALT,
- DEVICE_REMOTE_WAKEUP,
- TEST_MODE
+ ENDPOINT_HALT,
+ DEVICE_REMOTE_WAKEUP,
+ TEST_MODE
};
enum USB_CLASS_CODE {
- CLASS_DEVICE,
- CLASS_AUDIO,
- CLASS_COMM_AND_CDC_CONTROL,
- CLASS_HID,
- CLASS_PHYSICAL = 0x05,
- CLASS_STILL_IMAGING,
- CLASS_PRINTER,
- CLASS_MASS_STORAGE,
- CLASS_HUB,
- CLASS_CDC_DATA,
- CLASS_SMART_CARD,
- CLASS_CONTENT_SECURITY = 0x0d,
- CLASS_VIDEO,
- CLASS_DIAGNOSTIC_DEVICE = 0xdc,
- CLASS_WIRELESS_CONTROLLER = 0xe0,
- CLASS_MISCELLANEOUS = 0xef,
- CLASS_APP_SPECIFIC = 0xfe,
- CLASS_VENDOR_SPECIFIC = 0xff
+ CLASS_DEVICE,
+ CLASS_AUDIO,
+ CLASS_COMM_AND_CDC_CONTROL,
+ CLASS_HID,
+ CLASS_PHYSICAL = 0x05,
+ CLASS_STILL_IMAGING,
+ CLASS_PRINTER,
+ CLASS_MASS_STORAGE,
+ CLASS_HUB,
+ CLASS_CDC_DATA,
+ CLASS_SMART_CARD,
+ CLASS_CONTENT_SECURITY = 0x0d,
+ CLASS_VIDEO,
+ CLASS_DIAGNOSTIC_DEVICE = 0xdc,
+ CLASS_WIRELESS_CONTROLLER = 0xe0,
+ CLASS_MISCELLANEOUS = 0xef,
+ CLASS_APP_SPECIFIC = 0xfe,
+ CLASS_VENDOR_SPECIFIC = 0xff
};
typedef struct {
- u8 bmRequestType;
- u8 bRequest;
- u16 wValue;
- u16 wIndex;
- u16 wLength;
+ u8 bmRequestType;
+ u8 bRequest;
+ u16 wValue;
+ u16 wIndex;
+ u16 wLength;
} __attribute__ ((packed)) USB_DeviceRequest;
typedef struct {
- u8 bLength;
- u8 bDescriptorType;
- u16 bcdUSB;
- u8 bDeviceClass;
- u8 bDeviceSubClass;
- u8 bDeviceProtocol;
- u8 bMaxPacketSize0;
- u16 idVendor;
- u16 idProduct;
- u16 bcdDevice;
- u8 iManufacturer;
- u8 iProduct;
- u8 iSerialNumber;
- u8 bNumConfigurations;
+ u8 bLength;
+ u8 bDescriptorType;
+ u16 bcdUSB;
+ u8 bDeviceClass;
+ u8 bDeviceSubClass;
+ u8 bDeviceProtocol;
+ u8 bMaxPacketSize0;
+ u16 idVendor;
+ u16 idProduct;
+ u16 bcdDevice;
+ u8 iManufacturer;
+ u8 iProduct;
+ u8 iSerialNumber;
+ u8 bNumConfigurations;
} __attribute__ ((packed)) USB_DeviceDescriptor;
typedef struct {
- u8 bLength;
- u8 bDescriptorType;
- u16 bcdUSB;
- u8 bDeviceClass;
- u8 bDeviceSubClass;
- u8 bDeviceProtocol;
- u8 bMaxPacketSize0;
- u8 bNumConfigurations;
- u8 bReserved;
+ u8 bLength;
+ u8 bDescriptorType;
+ u16 bcdUSB;
+ u8 bDeviceClass;
+ u8 bDeviceSubClass;
+ u8 bDeviceProtocol;
+ u8 bMaxPacketSize0;
+ u8 bNumConfigurations;
+ u8 bReserved;
} __attribute__ ((packed)) USB_DeviceQualifierDescriptor;
typedef struct {
- u8 bLength;
- u8 bDescriptorType;
- u16 wTotalLength;
- u8 bNumInterfaces;
- u8 bConfigurationValue;
- u8 iConfiguration;
- u8 bmAttributes;
- u8 MaxPower;
+ u8 bLength;
+ u8 bDescriptorType;
+ u16 wTotalLength;
+ u8 bNumInterfaces;
+ u8 bConfigurationValue;
+ u8 iConfiguration;
+ u8 bmAttributes;
+ u8 MaxPower;
} __attribute__ ((packed)) USB_ConfigDescriptor;
typedef struct {
- u8 bLength;
- u8 bDescriptorType;
- u16 wTotalLength;
- u8 bNumInterfaces;
- u8 bConfigurationValue;
- u8 iConfiguration;
- u8 bmAttributes;
- u8 bMaxPower;
+ u8 bLength;
+ u8 bDescriptorType;
+ u16 wTotalLength;
+ u8 bNumInterfaces;
+ u8 bConfigurationValue;
+ u8 iConfiguration;
+ u8 bmAttributes;
+ u8 bMaxPower;
} __attribute__ ((packed)) USB_OtherSpeedConfigDescriptor;
typedef struct {
- u8 bLength;
- u8 bDescriptorType;
- u8 bInterfaceNumber;
- u8 bAlternateSetting;
- u8 bNumEndpoints;
- u8 bInterfaceClass;
- u8 bInterfaceSubClass;
- u8 bInterfaceProtocol;
- u8 iInterface;
+ u8 bLength;
+ u8 bDescriptorType;
+ u8 bInterfaceNumber;
+ u8 bAlternateSetting;
+ u8 bNumEndpoints;
+ u8 bInterfaceClass;
+ u8 bInterfaceSubClass;
+ u8 bInterfaceProtocol;
+ u8 iInterface;
} __attribute__ ((packed)) USB_InterfaceDescriptor;
typedef struct {
- u8 bLegth;
- u8 bDescriptorType;
- u8 bEndpointAddress;
- u8 bmAttributes;
- u16 wMaxPacketSize;
- u8 bInterval;
+ u8 bLegth;
+ u8 bDescriptorType;
+ u8 bEndpointAddress;
+ u8 bmAttributes;
+ u16 wMaxPacketSize;
+ u8 bInterval;
} __attribute__ ((packed)) USB_EndPointDescriptor;
typedef struct {
- u8 bLength;
- u8 bDescriptorType;
- u16 SomeDesriptor[1];
+ u8 bLength;
+ u8 bDescriptorType;
+ u16 SomeDesriptor[1];
} __attribute__ ((packed)) USB_StringDescriptor;
//------------------------------------------
-#define MAX_EP0_SIZE 64
-#define MAX_EP1_SIZE 512
+#define MAX_EP0_SIZE 64
+#define MAX_EP1_SIZE 512
#define USB_HS 0
#define USB_FS 1
#define USB_LS 2
//definitions of EP0
-#define USB_EP0_IDLE 0
-#define USB_EP0_RX 1
-#define USB_EP0_TX 2
+#define USB_EP0_IDLE 0
+#define USB_EP0_RX 1
+#define USB_EP0_TX 2
/* Define maximum packet size for endpoint 0 */
-#define M_EP0_MAXP 64
+#define M_EP0_MAXP 64
/* Endpoint 0 status structure */
static __inline__ void usb_setb(u32 port, u8 val)
{
- volatile u8 *ioport = (volatile u8 *)(port);
- *ioport = (*ioport) | val;
+ volatile u8 *ioport = (volatile u8 *)(port);
+ *ioport = (*ioport) | val;
}
static __inline__ void usb_clearb(u32 port, u8 val)
{
- volatile u8 *ioport = (volatile u8 *)(port);
- *ioport = (*ioport) & ~val;
+ volatile u8 *ioport = (volatile u8 *)(port);
+ *ioport = (*ioport) & ~val;
}
static __inline__ void usb_setw(u32 port, u16 val)
{
- volatile u16 *ioport = (volatile u16 *)(port);
- *ioport = (*ioport) | val;
+ volatile u16 *ioport = (volatile u16 *)(port);
+ *ioport = (*ioport) | val;
}
static __inline__ void usb_clearw(u32 port, u16 val)
{
- volatile u16 *ioport = (volatile u16 *)(port);
- *ioport = (*ioport) & ~val;
+ volatile u16 *ioport = (volatile u16 *)(port);
+ *ioport = (*ioport) & ~val;
}
//---------------------------------
#define BULK_OUT_BUF_SIZE 0x20000 //buffer size :
@@ -380,118 +691,118 @@ static __inline__ void usb_clearw(u32 port, u16 val)
enum UDC_STATE
{
- IDLE,
- BULK_IN,
- BULK_OUT
+ IDLE,
+ BULK_IN,
+ BULK_OUT
};
enum USB_JZ4740_REQUEST //add for USB_BOOT
{
- VR_GET_CUP_INFO = 0,
- VR_SET_DATA_ADDERSS,
- VR_SET_DATA_LENGTH,
- VR_FLUSH_CACHES,
- VR_PROGRAM_START1,
- VR_PROGRAM_START2,
- VR_NOR_OPS,
- VR_NAND_OPS,
- VR_SDRAM_OPS,
- VR_CONFIGRATION
+ VR_GET_CUP_INFO = 0,
+ VR_SET_DATA_ADDERSS,
+ VR_SET_DATA_LENGTH,
+ VR_FLUSH_CACHES,
+ VR_PROGRAM_START1,
+ VR_PROGRAM_START2,
+ VR_NOR_OPS,
+ VR_NAND_OPS,
+ VR_SDRAM_OPS,
+ VR_CONFIGRATION
};
enum NOR_OPS_TYPE
{
- NOR_INIT = 0,
- NOR_QUERY,
- NOR_WRITE,
- NOR_ERASE_CHIP,
- NOR_ERASE_SECTOR
+ NOR_INIT = 0,
+ NOR_QUERY,
+ NOR_WRITE,
+ NOR_ERASE_CHIP,
+ NOR_ERASE_SECTOR
};
enum NOR_FLASH_TYPE
{
- NOR_AM29 = 0,
- NOR_SST28,
- NOR_SST39x16,
- NOR_SST39x8
+ NOR_AM29 = 0,
+ NOR_SST28,
+ NOR_SST39x16,
+ NOR_SST39x8
};
enum NAND_OPS_TYPE
{
- NAND_QUERY = 0,
- NAND_INIT,
- NAND_MARK_BAD,
- NAND_READ_OOB,
- NAND_READ_RAW,
- NAND_ERASE,
- NAND_READ,
- NAND_PROGRAM,
- NAND_READ_TO_RAM
+ NAND_QUERY = 0,
+ NAND_INIT,
+ NAND_MARK_BAD,
+ NAND_READ_OOB,
+ NAND_READ_RAW,
+ NAND_ERASE,
+ NAND_READ,
+ NAND_PROGRAM,
+ NAND_READ_TO_RAM
};
enum SDRAM_OPS_TYPE
{
- SDRAM_LOAD,
+ SDRAM_LOAD,
};
enum DATA_STRUCTURE_OB
{
- DS_flash_info ,
- DS_hand
+ DS_flash_info ,
+ DS_hand
};
/*typedef enum _USB_BOOT_STATUS
{
- USB_NO_ERR =0 ,
- GET_CPU_INFO_ERR,
- SET_DATA_ADDRESS_ERR,
- SET_DATA_LENGTH_ERR,
- FLUSH_CAHCES_ERR,
- PROGRAM_START1_ERR,
- PROGRAM_START2_ERR,
- NOR_OPS_ERR,
- NAND_OPS_ERR,
- NOR_FLASHTYPE_ERR,
- OPS_NOTSUPPORT_ERR
+ USB_NO_ERR =0 ,
+ GET_CPU_INFO_ERR,
+ SET_DATA_ADDRESS_ERR,
+ SET_DATA_LENGTH_ERR,
+ FLUSH_CAHCES_ERR,
+ PROGRAM_START1_ERR,
+ PROGRAM_START2_ERR,
+ NOR_OPS_ERR,
+ NAND_OPS_ERR,
+ NOR_FLASHTYPE_ERR,
+ OPS_NOTSUPPORT_ERR
}USB_BOOT_STATUS;*/
enum OPTION
{
- OOB_ECC,
- OOB_NO_ECC,
- NO_OOB,
+ OOB_ECC,
+ OOB_NO_ECC,
+ NO_OOB,
};
//-------------------------
static inline void jz_writeb(u32 address, u8 value)
{
- *((volatile u8 *)address) = value;
+ *((volatile u8 *)address) = value;
}
static inline void jz_writew(u32 address, u16 value)
{
- *((volatile u16 *)address) = value;
+ *((volatile u16 *)address) = value;
}
static inline void jz_writel(u32 address, u32 value)
{
- *((volatile u32 *)address) = value;
+ *((volatile u32 *)address) = value;
}
static inline u8 jz_readb(u32 address)
{
- return *((volatile u8 *)address);
+ return *((volatile u8 *)address);
}
static inline u16 jz_readw(u32 address)
{
- return *((volatile u16 *)address);
+ return *((volatile u16 *)address);
}
static inline u32 jz_readl(u32 address)
{
- return *((volatile u32 *)address);
+ return *((volatile u32 *)address);
}
//---------------------------
@@ -510,530 +821,560 @@ static u8 ep0state,USB_Version;
static u32 fifoaddr[] =
{
- TXFIFOEP0, TXFIFOEP0+4 ,TXFIFOEP0+8
+ TXFIFOEP0, TXFIFOEP0+4 ,TXFIFOEP0+8
};
static u32 fifosize[] = {
- MAX_EP0_SIZE, MAX_EP1_SIZE
+ MAX_EP0_SIZE, MAX_EP1_SIZE
};
static void udcReadFifo(u8 *ptr, int size)
{
- u32 *d = (u32 *)ptr;
- int s;
- s = (size + 3) >> 2;
- while (s--)
- *d++ = REG32(fifo);
+ u32 *d = (u32 *)ptr;
+ int s;
+ s = (size + 3) >> 2;
+ while (s--)
+ *d++ = REG32(fifo);
}
static void udcWriteFifo(u8 *ptr, int size)
{
- u32 *d = (u32 *)ptr;
- u8 *c;
- int s, q;
-
- if (size > 0) {
- s = size >> 2;
- while (s--)
- REG32(fifo) = *d++;
- q = size & 3;
- if (q) {
- c = (u8 *)d;
- while (q--)
- REG8(fifo) = *c++;
- }
- }
+ u32 *d = (u32 *)ptr;
+ u8 *c;
+ int s, q;
+
+ if (size > 0) {
+ s = size >> 2;
+ while (s--)
+ REG32(fifo) = *d++;
+ q = size & 3;
+ if (q) {
+ c = (u8 *)d;
+ while (q--)
+ REG8(fifo) = *c++;
+ }
+ }
}
void HW_SendPKT(int ep, const u8 *buf, int size)
{
- fifo = fifoaddr[ep];
-
- if (ep!=0)
- {
- Bulk_in_size = size;
- Bulk_in_finish = 0;
- jz_writeb(USB_REG_INDEX, ep);
- if (Bulk_in_size - Bulk_in_finish <= fifosize[ep])
- {
- udcWriteFifo((u8 *)((u32)buf+Bulk_in_finish),
- Bulk_in_size - Bulk_in_finish);
- usb_setb(USB_REG_INCSR, USB_INCSR_INPKTRDY);
- Bulk_in_finish = Bulk_in_size;
- }
+ fifo = fifoaddr[ep];
+
+ if (ep!=0)
+ {
+ Bulk_in_size = size;
+ Bulk_in_finish = 0;
+ jz_writeb(USB_REG_INDEX, ep);
+ if (Bulk_in_size - Bulk_in_finish <= fifosize[ep])
+ {
+ udcWriteFifo((u8 *)((u32)buf+Bulk_in_finish),
+ Bulk_in_size - Bulk_in_finish);
+ usb_setb(USB_REG_INCSR, USB_INCSR_INPKTRDY);
+ Bulk_in_finish = Bulk_in_size;
+ }
else
- {
- udcWriteFifo((u8 *)((u32)buf+Bulk_in_finish),
- fifosize[ep]);
- usb_setb(USB_REG_INCSR, USB_INCSR_INPKTRDY);
- Bulk_in_finish += fifosize[ep];
+ {
+ udcWriteFifo((u8 *)((u32)buf+Bulk_in_finish),
+ fifosize[ep]);
+ usb_setb(USB_REG_INCSR, USB_INCSR_INPKTRDY);
+ Bulk_in_finish += fifosize[ep];
Bulk_in_buf = (u8*)buf;
- }
- }
- else //EP0
- {
- tx_size = size;
- finished = 0;
- memcpy((void *)tx_buf, buf, size);
- ep0state = USB_EP0_TX;
- }
+ }
+ }
+ else //EP0
+ {
+ tx_size = size;
+ finished = 0;
+ memcpy((void *)tx_buf, buf, size);
+ ep0state = USB_EP0_TX;
+ }
+}
+
+void HW_GetPKT(int ep, const u8 *buf, unsigned int size)
+{
+ memcpy((void *)buf, (u8 *)rx_buf, size);
+ fifo = fifoaddr[ep];
+ if (rx_size > size)
+ rx_size -= size;
+ else
+ {
+ size = rx_size;
+ rx_size = 0;
+ }
+ memcpy((u8 *)rx_buf, (u8 *)((u32)rx_buf+size), rx_size);
+}
+
+void Enable_DMA(u8* buf, u32 length)
+{
+ dma_cache_wback_inv((u32)buf, length);
+ jz_writeb(USB_REG_INDEX, 1);
+ usb_setw(USB_REG_INCSR, 0x9400);
+ usb_clearw(USB_REG_INTRINE, 0x2); //disable OUT intr
+ jz_writel(USB_REG_ADDR1, (u32)buf);
+ jz_writel(USB_REG_COUNT1, length);
+ jz_writel(USB_REG_CNTL1, 0x001f);
}
-void HW_GetPKT(int ep, const u8 *buf, int size)
-{
- memcpy((void *)buf, (u8 *)rx_buf, size);
- fifo = fifoaddr[ep];
- if (rx_size > size)
- rx_size -= size;
- else {
- size = rx_size;
- rx_size = 0;
- }
- memcpy((u8 *)rx_buf, (u8 *)((u32)rx_buf+size), rx_size);
+void Disable_DMA(void)
+{
+ jz_writeb(USB_REG_INDEX, 1);
+ usb_clearw(USB_REG_INCSR, 0x9400);
+ usb_setw(USB_REG_INTRINE, 0x2); //Enable OUT intr
}
static USB_DeviceDescriptor devDesc =
{
- sizeof(USB_DeviceDescriptor),
- DEVICE_DESCRIPTOR, //1
- 0x0200, //Version 2.0
- 0xff, //Vendor spec class
- 0xff,
- 0xff,
- 64, /* Ep0 FIFO size */
- 0x601a, //vendor ID
- 0xDEAD, //Product ID
- 0xffff,
- 0x00,
- 0x00,
- 0x00,
- 0x01
+ sizeof(USB_DeviceDescriptor),
+ DEVICE_DESCRIPTOR, //1
+ 0x0200, //Version 2.0
+ 0xff, //Vendor spec class
+ 0xff,
+ 0xff,
+ 64, /* Ep0 FIFO size */
+ 0x601a, //vendor ID
+ 0xDEAD, //Product ID
+ 0xffff,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x01
};
-#define CONFIG_DESCRIPTOR_LEN (sizeof(USB_ConfigDescriptor) + \
- sizeof(USB_InterfaceDescriptor) + \
- sizeof(USB_EndPointDescriptor) * 2)
+#define CONFIG_DESCRIPTOR_LEN (sizeof(USB_ConfigDescriptor) + \
+ sizeof(USB_InterfaceDescriptor) + \
+ sizeof(USB_EndPointDescriptor) * 2)
static struct {
- USB_ConfigDescriptor configuration_descriptor;
- USB_InterfaceDescriptor interface_descritor;
- USB_EndPointDescriptor endpoint_descriptor[2];
+ USB_ConfigDescriptor configuration_descriptor;
+ USB_InterfaceDescriptor interface_descritor;
+ USB_EndPointDescriptor endpoint_descriptor[2];
} __attribute__ ((packed)) confDesc = {
- {
- sizeof(USB_ConfigDescriptor),
- CONFIGURATION_DESCRIPTOR,
- CONFIG_DESCRIPTOR_LEN,
- 0x01,
- 0x01,
- 0x00,
- 0xc0, // Self Powered, no remote wakeup
- 0x64 // Maximum power consumption 2000 mA
- },
- {
- sizeof(USB_InterfaceDescriptor),
- INTERFACE_DESCRIPTOR,
- 0x00,
- 0x00,
- 0x02, /* ep number */
- 0xff,
- 0xff,
- 0xff,
- 0x00
- },
- {
- {
- sizeof(USB_EndPointDescriptor),
- ENDPOINT_DESCRIPTOR,
- (1 << 7) | 1,// endpoint 2 is IN endpoint
- 2, /* bulk */
- 512,
- 0
- },
- {
- sizeof(USB_EndPointDescriptor),
- ENDPOINT_DESCRIPTOR,
- (0 << 7) | 1,// endpoint 5 is OUT endpoint
- 2, /* bulk */
- 512, /* OUT EP FIFO size */
- 0
- }
- }
+ {
+ sizeof(USB_ConfigDescriptor),
+ CONFIGURATION_DESCRIPTOR,
+ CONFIG_DESCRIPTOR_LEN,
+ 0x01,
+ 0x01,
+ 0x00,
+ 0xc0, // Self Powered, no remote wakeup
+ 0x64 // Maximum power consumption 2000 mA
+ },
+ {
+ sizeof(USB_InterfaceDescriptor),
+ INTERFACE_DESCRIPTOR,
+ 0x00,
+ 0x00,
+ 0x02, /* ep number */
+ 0xff,
+ 0xff,
+ 0xff,
+ 0x00
+ },
+ {
+ {
+ sizeof(USB_EndPointDescriptor),
+ ENDPOINT_DESCRIPTOR,
+ (1 << 7) | 1,// endpoint 2 is IN endpoint
+ 2, /* bulk */
+ 512,
+ 0
+ },
+ {
+ sizeof(USB_EndPointDescriptor),
+ ENDPOINT_DESCRIPTOR,
+ (0 << 7) | 1,// endpoint 5 is OUT endpoint
+ 2, /* bulk */
+ 512, /* OUT EP FIFO size */
+ 0
+ }
+ }
};
void sendDevDescString(int size)
{
- u16 str_ret[13] = {
- 0x031a,//0x1a=26 byte
- 0x0041,
- 0x0030,
- 0x0030,
- 0x0041,
- 0x0030,
- 0x0030,
- 0x0041,
- 0x0030,
- 0x0030,
- 0x0041,
- 0x0030,
- 0x0030
- };
- if(size >= 26)
- size = 26;
- str_ret[0] = (0x0300 | size);
- HW_SendPKT(0, (u8 *)str_ret,size);
+ u16 str_ret[13] = {
+ 0x031a,//0x1a=26 byte
+ 0x0041,
+ 0x0030,
+ 0x0030,
+ 0x0041,
+ 0x0030,
+ 0x0030,
+ 0x0041,
+ 0x0030,
+ 0x0030,
+ 0x0041,
+ 0x0030,
+ 0x0030
+ };
+ if(size >= 26)
+ size = 26;
+ str_ret[0] = (0x0300 | size);
+ HW_SendPKT(0, (u8 *)str_ret,size);
}
void sendDevDesc(int size)
{
switch (size) {
- case 18:
- HW_SendPKT(0, (u8 *)&devDesc, sizeof(devDesc));
- break;
- default:
- HW_SendPKT(0, (u8 *)&devDesc, 8);
- break;
- }
+ case 18:
+ HW_SendPKT(0, (u8 *)&devDesc, sizeof(devDesc));
+ break;
+ default:
+ HW_SendPKT(0, (u8 *)&devDesc, 8);
+ break;
+ }
}
void sendConfDesc(int size)
{
- switch (size) {
- case 9:
- HW_SendPKT(0, (u8 *)&confDesc, 9);
- break;
- case 8:
- HW_SendPKT(0, (u8 *)&confDesc, 8);
- break;
- default:
- HW_SendPKT(0, (u8 *)&confDesc, sizeof(confDesc));
- break;
- }
+ switch (size) {
+ case 9:
+ HW_SendPKT(0, (u8 *)&confDesc, 9);
+ break;
+ case 8:
+ HW_SendPKT(0, (u8 *)&confDesc, 8);
+ break;
+ default:
+ HW_SendPKT(0, (u8 *)&confDesc, sizeof(confDesc));
+ break;
+ }
}
void EP0_init(u32 out, u32 out_size, u32 in, u32 in_size)
{
- confDesc.endpoint_descriptor[0].bEndpointAddress = (1<<7) | in;
- confDesc.endpoint_descriptor[0].wMaxPacketSize = in_size;
- confDesc.endpoint_descriptor[1].bEndpointAddress = (0<<7) | out;
- confDesc.endpoint_descriptor[1].wMaxPacketSize = out_size;
+ confDesc.endpoint_descriptor[0].bEndpointAddress = (1<<7) | in;
+ confDesc.endpoint_descriptor[0].wMaxPacketSize = in_size;
+ confDesc.endpoint_descriptor[1].bEndpointAddress = (0<<7) | out;
+ confDesc.endpoint_descriptor[1].wMaxPacketSize = out_size;
}
static void udc_reset(void)
{
- //data init
- ep0state = USB_EP0_IDLE;
- Bulk_in_size = 0;
- Bulk_in_finish = 0;
- Bulk_out_size = 0;
- udc_state = IDLE;
- tx_size = 0;
- rx_size = 0;
- finished = 0;
- /* Enable the USB PHY */
-// REG_CPM_SCR |= CPM_SCR_USBPHY_ENABLE;
- /* Disable interrupts */
- jz_writew(USB_REG_INTRINE, 0);
- jz_writew(USB_REG_INTROUTE, 0);
- jz_writeb(USB_REG_INTRUSBE, 0);
- jz_writeb(USB_REG_FADDR,0);
- jz_writeb(USB_REG_POWER,0x60); //High speed
- jz_writeb(USB_REG_INDEX,0);
- jz_writeb(USB_REG_CSR0,0xc0);
- jz_writeb(USB_REG_INDEX,1);
- jz_writew(USB_REG_INMAXP,512);
- jz_writew(USB_REG_INCSR,0x2048);
- jz_writeb(USB_REG_INDEX,1);
- jz_writew(USB_REG_OUTMAXP,512);
- jz_writew(USB_REG_OUTCSR,0x0090);
- jz_writew(USB_REG_INTRINE,0x3); //enable intr
- jz_writew(USB_REG_INTROUTE,0x2);
- jz_writeb(USB_REG_INTRUSBE,0x4);
-
- if ((jz_readb(USB_REG_POWER)&0x10)==0)
- {
- jz_writeb(USB_REG_INDEX,1);
- jz_writew(USB_REG_INMAXP,64);
- jz_writew(USB_REG_INCSR,0x2048);
- jz_writeb(USB_REG_INDEX,1);
- jz_writew(USB_REG_OUTMAXP,64);
- jz_writew(USB_REG_OUTCSR,0x0090);
- USB_Version=USB_FS;
- fifosize[1]=64;
- EP0_init(1,64,1,64);
- }
- else
- {
- jz_writeb(USB_REG_INDEX,1);
- jz_writew(USB_REG_INMAXP,512);
- jz_writew(USB_REG_INCSR,0x2048);
- jz_writeb(USB_REG_INDEX,1);
- jz_writew(USB_REG_OUTMAXP,512);
- jz_writew(USB_REG_OUTCSR,0x0090);
- USB_Version=USB_HS;
- fifosize[1]=512;
- EP0_init(1,512,1,512);
- }
+ //data init
+ ep0state = USB_EP0_IDLE;
+ Bulk_in_size = 0;
+ Bulk_in_finish = 0;
+ Bulk_out_size = 0;
+ udc_state = IDLE;
+ tx_size = 0;
+ rx_size = 0;
+ finished = 0;
+ /* Enable the USB PHY */
+// REG_CPM_SCR |= CPM_SCR_USBPHY_ENABLE;
+ /* Disable interrupts */
+ jz_writew(USB_REG_INTRINE, 0);
+ jz_writew(USB_REG_INTROUTE, 0);
+ jz_writeb(USB_REG_INTRUSBE, 0);
+ jz_writeb(USB_REG_FADDR,0);
+ jz_writeb(USB_REG_POWER,0x60); //High speed
+ jz_writeb(USB_REG_INDEX,0);
+ jz_writeb(USB_REG_CSR0,0xc0);
+ jz_writeb(USB_REG_INDEX,1);
+ jz_writew(USB_REG_INMAXP,512);
+ jz_writew(USB_REG_INCSR,0x2048);
+ jz_writeb(USB_REG_INDEX,1);
+ jz_writew(USB_REG_OUTMAXP,512);
+ jz_writew(USB_REG_OUTCSR,0x0090);
+ jz_writew(USB_REG_INTRINE,0x3); //enable intr
+ jz_writew(USB_REG_INTROUTE,0x2);
+ jz_writeb(USB_REG_INTRUSBE,0x4);
+
+ if ((jz_readb(USB_REG_POWER)&0x10)==0)
+ {
+ jz_writeb(USB_REG_INDEX,1);
+ jz_writew(USB_REG_INMAXP,64);
+ jz_writew(USB_REG_INCSR,0x2048);
+ jz_writeb(USB_REG_INDEX,1);
+ jz_writew(USB_REG_OUTMAXP,64);
+ jz_writew(USB_REG_OUTCSR,0x0090);
+ USB_Version=USB_FS;
+ fifosize[1]=64;
+ EP0_init(1,64,1,64);
+ }
+ else
+ {
+ jz_writeb(USB_REG_INDEX,1);
+ jz_writew(USB_REG_INMAXP,512);
+ jz_writew(USB_REG_INCSR,0x2048);
+ jz_writeb(USB_REG_INDEX,1);
+ jz_writew(USB_REG_OUTMAXP,512);
+ jz_writew(USB_REG_OUTCSR,0x0090);
+ USB_Version=USB_HS;
+ fifosize[1]=512;
+ EP0_init(1,512,1,512);
+ }
}
void usbHandleStandDevReq(u8 *buf)
{
- USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf;
- switch (dreq->bRequest) {
- case GET_DESCRIPTOR:
- if (dreq->bmRequestType == 0x80) /* Dev2Host */
- switch(dreq->wValue >> 8)
- {
- case DEVICE_DESCRIPTOR:
- sendDevDesc(dreq->wLength);
- break;
- case CONFIGURATION_DESCRIPTOR:
- sendConfDesc(dreq->wLength);
- break;
- case STRING_DESCRIPTOR:
- if (dreq->wLength == 0x02)
- HW_SendPKT(0, "\x04\x03", 2);
- else
- sendDevDescString(dreq->wLength);
- //HW_SendPKT(0, "\x04\x03\x09\x04", 2);
- break;
- }
- ep0state=USB_EP0_TX;
-
- break;
- case SET_ADDRESS:
- jz_writeb(USB_REG_FADDR,dreq->wValue);
- break;
- case GET_STATUS:
- switch (dreq->bmRequestType) {
- case 80: /* device */
- HW_SendPKT(0, "\x01\x00", 2);
- break;
- case 81: /* interface */
- case 82: /* ep */
- HW_SendPKT(0, "\x00\x00", 2);
- break;
- }
- ep0state=USB_EP0_TX;
- break;
- case CLEAR_FEATURE:
- case SET_CONFIGURATION:
- case SET_INTERFACE:
- case SET_FEATURE:
- break;
- }
+ USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf;
+ switch (dreq->bRequest) {
+ case GET_DESCRIPTOR:
+ if (dreq->bmRequestType == 0x80) /* Dev2Host */
+ switch(dreq->wValue >> 8)
+ {
+ case DEVICE_DESCRIPTOR:
+ sendDevDesc(dreq->wLength);
+ break;
+ case CONFIGURATION_DESCRIPTOR:
+ sendConfDesc(dreq->wLength);
+ break;
+ case STRING_DESCRIPTOR:
+ if (dreq->wLength == 0x02)
+ HW_SendPKT(0, "\x04\x03", 2);
+ else
+ sendDevDescString(dreq->wLength);
+ //HW_SendPKT(0, "\x04\x03\x09\x04", 2);
+ break;
+ }
+ ep0state=USB_EP0_TX;
+
+ break;
+ case SET_ADDRESS:
+ jz_writeb(USB_REG_FADDR,dreq->wValue);
+ break;
+ case GET_STATUS:
+ switch (dreq->bmRequestType) {
+ case 80: /* device */
+ HW_SendPKT(0, "\x01\x00", 2);
+ break;
+ case 81: /* interface */
+ case 82: /* ep */
+ HW_SendPKT(0, "\x00\x00", 2);
+ break;
+ }
+ ep0state=USB_EP0_TX;
+ break;
+ case CLEAR_FEATURE:
+ case SET_CONFIGURATION:
+ case SET_INTERFACE:
+ case SET_FEATURE:
+ break;
+ }
}
unsigned char nandbuffer[4096];
+extern void jz_nand_read(int block, int page, unsigned char *buf);
void usbHandleVendorReq(u8 *buf)
{
- USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf;
- switch (dreq->bRequest)
+ USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf;
+ switch (dreq->bRequest)
{
case 0xB0:
memset(&nandbuffer, 0, 4096);
- jz_nand_read(dreq->wValue, dreq->wIndex, &nandbuffer);
+ jz_nand_read(dreq->wValue, dreq->wIndex, nandbuffer);
//printf("Read block %d page %d", dreq->wValue, dreq->wIndex);
udc_state = IDLE;
break;
- case 0xAB:
- HW_SendPKT(1, nandbuffer, 4096);
+ case 0xAB:
+ Enable_DMA(nandbuffer, 4096);
+ //HW_SendPKT(1, nandbuffer, 4096);
//printf("Send data");
- //udc_state = BULK_OUT;
- break;
+ //udc_state = BULK_OUT;
+ break;
case 0x12:
- HW_SendPKT(0, "TEST", 4);
+ HW_SendPKT(0, "TEST", 4);
//printf("Send test");
- udc_state = IDLE;
+ udc_state = IDLE;
break;
- }
+ }
}
void Handshake_PKT(void)
{
- if (udc_state!=IDLE)
- {
- HW_SendPKT(1,(u8 *)handshake_PKT,sizeof(handshake_PKT));
- udc_state = IDLE;
- }
+ if (udc_state!=IDLE)
+ {
+ HW_SendPKT(1,(u8 *)handshake_PKT,sizeof(handshake_PKT));
+ udc_state = IDLE;
+ }
}
void usbHandleDevReq(u8 *buf)
{
- switch ((buf[0] & (3 << 5)) >> 5) {
- case 0: /* Standard request */
- usbHandleStandDevReq(buf);
- break;
- case 1: /* Class request */
- break;
- case 2: /* Vendor request */
- usbHandleVendorReq(buf);
- break;
- }
+ switch ((buf[0] & (3 << 5)) >> 5) {
+ case 0: /* Standard request */
+ usbHandleStandDevReq(buf);
+ break;
+ case 1: /* Class request */
+ break;
+ case 2: /* Vendor request */
+ usbHandleVendorReq(buf);
+ break;
+ }
}
void EP0_Handler (void)
{
- u8 byCSR0;
+ u8 byCSR0;
/* Read CSR0 */
- jz_writeb(USB_REG_INDEX, 0);
- byCSR0 = jz_readb(USB_REG_CSR0);
+ jz_writeb(USB_REG_INDEX, 0);
+ byCSR0 = jz_readb(USB_REG_CSR0);
/* Check for SentStall
if sendstall is set ,clear the sendstall bit*/
- if (byCSR0 & USB_CSR0_SENTSTALL)
- {
- jz_writeb(USB_REG_CSR0, (byCSR0 & ~USB_CSR0_SENDSTALL));
- ep0state = USB_EP0_IDLE;
- return;
- }
+ if (byCSR0 & USB_CSR0_SENTSTALL)
+ {
+ jz_writeb(USB_REG_CSR0, (byCSR0 & ~USB_CSR0_SENDSTALL));
+ ep0state = USB_EP0_IDLE;
+ return;
+ }
/* Check for SetupEnd */
- if (byCSR0 & USB_CSR0_SETUPEND)
- {
- jz_writeb(USB_REG_CSR0, (byCSR0 | USB_CSR0_SVDSETUPEND));
- ep0state = USB_EP0_IDLE;
- return;
- }
+ if (byCSR0 & USB_CSR0_SETUPEND)
+ {
+ jz_writeb(USB_REG_CSR0, (byCSR0 | USB_CSR0_SVDSETUPEND));
+ ep0state = USB_EP0_IDLE;
+ return;
+ }
/* Call relevant routines for endpoint 0 state */
- if (ep0state == USB_EP0_IDLE)
- {
- if (byCSR0 & USB_CSR0_OUTPKTRDY) //There are datas in fifo
- {
- USB_DeviceRequest *dreq;
- fifo=fifoaddr[0];
- udcReadFifo((u8 *)rx_buf, sizeof(USB_DeviceRequest));
- usb_setb(USB_REG_CSR0, 0x48);//clear OUTRD bit
- dreq = (USB_DeviceRequest *)rx_buf;
- usbHandleDevReq((u8 *)rx_buf);
- }
- rx_size = 0;
- }
-
- if (ep0state == USB_EP0_TX)
- {
- fifo=fifoaddr[0];
- if (tx_size - finished <= 64)
- {
- udcWriteFifo((u8 *)((u32)tx_buf+finished),
- tx_size - finished);
- finished = tx_size;
- usb_setb(USB_REG_CSR0, USB_CSR0_INPKTRDY);
- usb_setb(USB_REG_CSR0, USB_CSR0_DATAEND); //Set dataend!
- ep0state=USB_EP0_IDLE;
- } else
- {
- udcWriteFifo((u8 *)((u32)tx_buf+finished), 64);
- usb_setb(USB_REG_CSR0, USB_CSR0_INPKTRDY);
- finished += 64;
- }
- }
- return;
+ if (ep0state == USB_EP0_IDLE)
+ {
+ if (byCSR0 & USB_CSR0_OUTPKTRDY) //There are datas in fifo
+ {
+ USB_DeviceRequest *dreq;
+ fifo=fifoaddr[0];
+ udcReadFifo((u8 *)rx_buf, sizeof(USB_DeviceRequest));
+ usb_setb(USB_REG_CSR0, 0x48);//clear OUTRD bit
+ dreq = (USB_DeviceRequest *)rx_buf;
+ usbHandleDevReq((u8 *)rx_buf);
+ }
+ rx_size = 0;
+ }
+
+ if (ep0state == USB_EP0_TX)
+ {
+ fifo=fifoaddr[0];
+ if (tx_size - finished <= 64)
+ {
+ udcWriteFifo((u8 *)((u32)tx_buf+finished),
+ tx_size - finished);
+ finished = tx_size;
+ usb_setb(USB_REG_CSR0, USB_CSR0_INPKTRDY);
+ usb_setb(USB_REG_CSR0, USB_CSR0_DATAEND); //Set dataend!
+ ep0state=USB_EP0_IDLE;
+ } else
+ {
+ udcWriteFifo((u8 *)((u32)tx_buf+finished), 64);
+ usb_setb(USB_REG_CSR0, USB_CSR0_INPKTRDY);
+ finished += 64;
+ }
+ }
+ return;
}
void EPIN_Handler(u8 EP)
{
- jz_writeb(USB_REG_INDEX, EP);
- fifo = fifoaddr[EP];
-
- if (Bulk_in_size-Bulk_in_finish==0)
- {
- Handshake_PKT();
- return;
- }
-
- if (Bulk_in_size - Bulk_in_finish <= fifosize[EP])
- {
- udcWriteFifo((u8 *)((u32)Bulk_in_buf+Bulk_in_finish),
- Bulk_in_size - Bulk_in_finish);
- usb_setw(USB_REG_INCSR, USB_INCSR_INPKTRDY);
- Bulk_in_finish = Bulk_in_size;
- }
+ jz_writeb(USB_REG_INDEX, EP);
+ fifo = fifoaddr[EP];
+
+ if (Bulk_in_size-Bulk_in_finish==0)
+ {
+ Handshake_PKT();
+ return;
+ }
+
+ if (Bulk_in_size - Bulk_in_finish <= fifosize[EP])
+ {
+ udcWriteFifo((u8 *)((u32)Bulk_in_buf+Bulk_in_finish),
+ Bulk_in_size - Bulk_in_finish);
+ usb_setw(USB_REG_INCSR, USB_INCSR_INPKTRDY);
+ Bulk_in_finish = Bulk_in_size;
+ }
else
- {
- udcWriteFifo((u8 *)((u32)Bulk_in_buf+Bulk_in_finish),
- fifosize[EP]);
- usb_setw(USB_REG_INCSR, USB_INCSR_INPKTRDY);
- Bulk_in_finish += fifosize[EP];
- }
+ {
+ udcWriteFifo((u8 *)((u32)Bulk_in_buf+Bulk_in_finish),
+ fifosize[EP]);
+ usb_setw(USB_REG_INCSR, USB_INCSR_INPKTRDY);
+ Bulk_in_finish += fifosize[EP];
+ }
}
void EPOUT_Handler(u8 EP)
{
- u32 size;
- jz_writeb(USB_REG_INDEX, EP);
- size = jz_readw(USB_REG_OUTCOUNT);
- fifo = fifoaddr[EP];
- udcReadFifo((u8 *)((u32)Bulk_out_buf+Bulk_out_size), size);
- usb_clearb(USB_REG_OUTCSR,USB_OUTCSR_OUTPKTRDY);
- Bulk_out_size += size;
+ u32 size;
+ jz_writeb(USB_REG_INDEX, EP);
+ size = jz_readw(USB_REG_OUTCOUNT);
+ fifo = fifoaddr[EP];
+ udcReadFifo((u8 *)((u32)Bulk_out_buf+Bulk_out_size), size);
+ usb_clearb(USB_REG_OUTCSR,USB_OUTCSR_OUTPKTRDY);
+ Bulk_out_size += size;
}
void UDC(void)
{
- u8 IntrUSB;
- u16 IntrIn;
- u16 IntrOut;
+ u8 IntrUSB;
+ u16 IntrIn;
+ u16 IntrOut;
+ u16 IntrDMA;
/* Read interrupt registers */
- IntrUSB = jz_readb(USB_REG_INTRUSB);
- IntrIn = jz_readw(USB_REG_INTRIN);
- IntrOut = jz_readw(USB_REG_INTROUT);
-
- if ( IntrUSB == 0 && IntrIn == 0 && IntrOut == 0)
- return;
-
- if (IntrIn & 2)
- {
- EPIN_Handler(1);
- }
- if (IntrOut & 2)
- {
- EPOUT_Handler(1);
- }
- if (IntrUSB & USB_INTR_RESET)
- {
- udc_reset();
- }
+ IntrUSB = jz_readb(USB_REG_INTRUSB);
+ IntrIn = jz_readw(USB_REG_INTRIN);
+ IntrOut = jz_readw(USB_REG_INTROUT);
+ IntrDMA = jz_readb(USB_REG_INTR);
+
+ if ( IntrUSB == 0 && IntrIn == 0 && IntrOut == 0)
+ return;
+
+ if (IntrIn & 2)
+ {
+ EPIN_Handler(1);
+ }
+ if (IntrOut & 2)
+ {
+ EPOUT_Handler(1);
+ }
+ if (IntrUSB & USB_INTR_RESET)
+ {
+ udc_reset();
+ }
/* Check for endpoint 0 interrupt */
- if (IntrIn & USB_INTR_EP0)
- {
- EP0_Handler();
- }
+ if (IntrIn & USB_INTR_EP0)
+ {
+ EP0_Handler();
+ }
- IntrIn = jz_readw(USB_REG_INTRIN);
- return;
+ if (IntrDMA & 0x1) //channel 1 :OUT
+ {
+ if (tx_size > 0 && tx_size % fifosize[1] != 0)
+ {
+ jz_writeb(USB_REG_INDEX, 1);
+ usb_clearb(USB_REG_INCSR, USB_INCSR_INPKTRDY);
+ }
+ Disable_DMA();
+ }
}
void __udc_start(void)
{
udc_reset();
- ep0state = USB_EP0_IDLE;
- Bulk_in_size = 0;
- Bulk_in_finish = 0;
- Bulk_out_size = 0;
- udc_state = IDLE;
- tx_size = 0;
- rx_size = 0;
- finished = 0;
-
- if ((jz_readb(USB_REG_POWER)&0x10)==0)
- {
- USB_Version=USB_FS;
- fifosize[1]=64;
- EP0_init(1,64,1,64);
- }
- else
- {
- USB_Version=USB_HS;
- fifosize[1]=512;
- EP0_init(1,512,1,512);
- }
-
- USB_Version=USB_HS;
+ ep0state = USB_EP0_IDLE;
+ Bulk_in_size = 0;
+ Bulk_in_finish = 0;
+ Bulk_out_size = 0;
+ udc_state = IDLE;
+ tx_size = 0;
+ rx_size = 0;
+ finished = 0;
+
+ if ((jz_readb(USB_REG_POWER)&0x10)==0)
+ {
+ USB_Version=USB_FS;
+ fifosize[1]=64;
+ EP0_init(1,64,1,64);
+ }
+ else
+ {
+ USB_Version=USB_HS;
+ fifosize[1]=512;
+ EP0_init(1,512,1,512);
+ }
+
+ USB_Version=USB_HS;
system_enable_irq(IRQ_UDC);
}