forked from len0rd/rockbox
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
This commit is contained in:
parent
0711c795e6
commit
4af26e7e98
12 changed files with 2927 additions and 697 deletions
|
@ -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
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
104
firmware/target/mips/ingenic_jz47xx/ata-jz4740.c
Normal file
104
firmware/target/mips/ingenic_jz47xx/ata-jz4740.c
Normal file
|
@ -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;
|
||||
}
|
|
@ -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"
|
||||
|
@ -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)
|
||||
|
|
28
firmware/target/mips/ingenic_jz47xx/ata-nand-target.h
Normal file
28
firmware/target/mips/ingenic_jz47xx/ata-nand-target.h
Normal file
|
@ -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
|
1168
firmware/target/mips/ingenic_jz47xx/ata-sd-jz4740.c
Normal file
1168
firmware/target/mips/ingenic_jz47xx/ata-sd-jz4740.c
Normal file
File diff suppressed because it is too large
Load diff
39
firmware/target/mips/ingenic_jz47xx/ata-sd-target.h
Normal file
39
firmware/target/mips/ingenic_jz47xx/ata-sd-target.h
Normal file
|
@ -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
|
280
firmware/target/mips/ingenic_jz47xx/codec-jz4740.c
Normal file
280
firmware/target/mips/ingenic_jz47xx/codec-jz4740.c
Normal file
|
@ -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);
|
||||
}
|
|
@ -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)
|
||||
|
|
164
firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c
Normal file
164
firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c
Normal file
|
@ -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
|
|
@ -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,9 +39,322 @@
|
|||
|
||||
#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)
|
||||
|
@ -99,6 +413,8 @@ void usb_drv_init(void)
|
|||
* transistor on and pull the USBDP pin HIGH.
|
||||
*/
|
||||
REG_USB_REG_POWER |= USB_POWER_SOFTCONN;
|
||||
|
||||
udc_reset();
|
||||
}
|
||||
|
||||
void usb_drv_exit(void)
|
||||
|
@ -126,11 +442,6 @@ void usb_drv_set_address(int address)
|
|||
REG_USB_REG_FADDR = address;
|
||||
}
|
||||
|
||||
/* Interrupt handler */
|
||||
void UDC(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
|
@ -579,19 +890,38 @@ void HW_SendPKT(int ep, const u8 *buf, int size)
|
|||
}
|
||||
}
|
||||
|
||||
void HW_GetPKT(int ep, const u8 *buf, int size)
|
||||
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 {
|
||||
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 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),
|
||||
|
@ -825,6 +1155,7 @@ void usbHandleStandDevReq(u8 *buf)
|
|||
}
|
||||
|
||||
unsigned char nandbuffer[4096];
|
||||
extern void jz_nand_read(int block, int page, unsigned char *buf);
|
||||
|
||||
void usbHandleVendorReq(u8 *buf)
|
||||
{
|
||||
|
@ -833,12 +1164,13 @@ void usbHandleVendorReq(u8 *buf)
|
|||
{
|
||||
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);
|
||||
Enable_DMA(nandbuffer, 4096);
|
||||
//HW_SendPKT(1, nandbuffer, 4096);
|
||||
//printf("Send data");
|
||||
//udc_state = BULK_OUT;
|
||||
break;
|
||||
|
@ -976,10 +1308,12 @@ void UDC(void)
|
|||
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);
|
||||
IntrDMA = jz_readb(USB_REG_INTR);
|
||||
|
||||
if ( IntrUSB == 0 && IntrIn == 0 && IntrOut == 0)
|
||||
return;
|
||||
|
@ -1003,8 +1337,15 @@ void UDC(void)
|
|||
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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue