From 4532d145f17e5beb7e921cf459c7f8e27bcd58fd Mon Sep 17 00:00:00 2001 From: Maurus Cuelenaere Date: Fri, 13 Feb 2009 00:45:49 +0000 Subject: Onda VX747: * Add preliminary keymap * Split up generic MIPS stuff from Ingenic specific * Make apps/ compilable * Add SD driver * Fix RTC driver * Add debug screen * Other cleanups/rewrites/fixes git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19993 a1c6a512-1295-4272-9138-f99709370657 --- apps/keymaps/keymap-ondavx747.c | 61 ++ bootloader/ondavx747.c | 4 +- firmware/common/timefuncs.c | 6 + firmware/drivers/rtc/rtc_jz4740.c | 34 +- .../target/mips/ingenic_jz47xx/ata-sd-jz4740.c | 891 ++++++++++++++++++--- firmware/target/mips/ingenic_jz47xx/codec-jz4740.c | 17 + firmware/target/mips/ingenic_jz47xx/crt0.S | 65 +- firmware/target/mips/ingenic_jz47xx/debug-jz4740.c | 39 +- firmware/target/mips/ingenic_jz47xx/debug-target.h | 28 + .../mips/ingenic_jz47xx/onda_vx747/ata-sd-target.h | 14 +- .../onda_vx747/backlight-onda_vx747.c | 10 +- .../ingenic_jz47xx/onda_vx747/backlight-target.h | 2 + .../ingenic_jz47xx/onda_vx747/lcd-onda_vx747.c | 13 +- .../ingenic_jz47xx/onda_vx747/power-onda_vx747.c | 5 + .../ingenic_jz47xx/onda_vx747/sadc-onda_vx747.c | 93 ++- firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c | 3 +- .../target/mips/ingenic_jz47xx/system-jz4740.c | 357 ++------- .../target/mips/ingenic_jz47xx/system-target.h | 43 +- firmware/target/mips/mmu-mips.c | 92 ++- firmware/target/mips/mmu-mips.h | 13 +- 20 files changed, 1249 insertions(+), 541 deletions(-) create mode 100644 apps/keymaps/keymap-ondavx747.c create mode 100644 firmware/target/mips/ingenic_jz47xx/debug-target.h diff --git a/apps/keymaps/keymap-ondavx747.c b/apps/keymaps/keymap-ondavx747.c new file mode 100644 index 0000000000..2e4bb86559 --- /dev/null +++ b/apps/keymaps/keymap-ondavx747.c @@ -0,0 +1,61 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2009 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. + * + ****************************************************************************/ + +/* Button Code Definitions for the Onda VX747 target */ +/* NB: Up/Down/Left/Right are not physical buttons - touchscreen emulation */ + +#include +#include +#include + +#include "config.h" +#include "action.h" +#include "button.h" +#include "settings.h" + +/* + * The format of the list is as follows + * { Action Code, Button code, Prereq button code } + * if there's no need to check the previous button's value, use BUTTON_NONE + * Insert LAST_ITEM_IN_LIST at the end of each mapping + */ + +/*TODO*/ +static const struct button_mapping button_context_standard[] = { + { ACTION_STD_PREV, BUTTON_VOL_DOWN, BUTTON_NONE }, + { ACTION_STD_PREVREPEAT, BUTTON_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_STD_NEXT, BUTTON_VOL_UP, BUTTON_NONE }, + { ACTION_STD_NEXTREPEAT, BUTTON_VOL_UP|BUTTON_REPEAT, BUTTON_NONE }, + + { ACTION_STD_OK, BUTTON_MENU|BUTTON_REL, BUTTON_MENU }, + { ACTION_STD_CANCEL, BUTTON_POWER, BUTTON_NONE }, + + { ACTION_STD_QUICKSCREEN, BUTTON_VOL_UP|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_STD_CONTEXT, BUTTON_MENU|BUTTON_REPEAT, BUTTON_NONE }, + + LAST_ITEM_IN_LIST +}; /* button_context_standard */ + +const struct button_mapping* target_get_context_mapping(int context) +{ + (void)context; + return button_context_standard; +} diff --git a/bootloader/ondavx747.c b/bootloader/ondavx747.c index 354cae42ec..12ab397078 100755 --- a/bootloader/ondavx747.c +++ b/bootloader/ondavx747.c @@ -101,7 +101,7 @@ static void boot_of(void) int main(void) { - int rc; + int rc, dummy; void (*kernel_entry)(void); kernel_init(); @@ -114,7 +114,7 @@ int main(void) reset_screen(); #ifdef HAVE_TOUCHSCREEN - rc = button_read_device(NULL); + rc = button_read_device(&dummy); #else rc = button_read_device(); #endif diff --git a/firmware/common/timefuncs.c b/firmware/common/timefuncs.c index d46b961a8c..53ca5f3c16 100644 --- a/firmware/common/timefuncs.c +++ b/firmware/common/timefuncs.c @@ -104,10 +104,13 @@ int set_time(const struct tm *tm) { #if CONFIG_RTC int rc; +#if CONFIG_RTC != RTC_JZ47XX char rtcbuf[7]; +#endif if (valid_time(tm)) { +#if CONFIG_RTC != RTC_JZ47XX rtcbuf[0]=((tm->tm_sec/10) << 4) | (tm->tm_sec%10); rtcbuf[1]=((tm->tm_min/10) << 4) | (tm->tm_min%10); rtcbuf[2]=((tm->tm_hour/10) << 4) | (tm->tm_hour%10); @@ -122,6 +125,9 @@ int set_time(const struct tm *tm) #endif rc = rtc_write_datetime(rtcbuf); +#else + rc = rtc_write_datetime((unsigned char*)tm); +#endif if (rc < 0) return -1; diff --git a/firmware/drivers/rtc/rtc_jz4740.c b/firmware/drivers/rtc/rtc_jz4740.c index 77e0860cd2..da39b3faf7 100644 --- a/firmware/drivers/rtc/rtc_jz4740.c +++ b/firmware/drivers/rtc/rtc_jz4740.c @@ -28,11 +28,7 @@ #include "jz4740.h" #include "rtc.h" #include "timefuncs.h" - -static unsigned int epoch = 1900; -static const unsigned char days_in_mo[] = { - 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 -}; +#include "logf.h" static const unsigned int yearday[5] = {0, 366, 366+365, 366+365*2, 366+365*3}; static const unsigned int sweekday = 6; @@ -52,8 +48,8 @@ static const unsigned int sum_monthday[13] = { 365 }; -#if 0 -static unsigned int jz_mktime(int year, int mon, int day, int hour, int min, int sec) +static unsigned int jz_mktime(int year, int mon, int day, int hour, int min, + int sec) { unsigned int seccounter; @@ -79,10 +75,9 @@ static unsigned int jz_mktime(int year, int mon, int day, int hour, int min, int return seccounter; } -#endif -static void jz_gettime(unsigned int rtc, int *year, int *mon, int *day, int *hour, - int *min, int *sec, int *weekday) +static void jz_gettime(unsigned int rtc, int *year, int *mon, int *day, + int *hour, int *min, int *sec, int *weekday) { unsigned int tday, tsec, i, tmp; @@ -143,9 +138,9 @@ int rtc_read_datetime(unsigned char* buf) rtc_tm.tm_wday = wday; /* Don't use centry, but start from year 1970 */ rtc_tm.tm_mon = mon; - if ((year += (epoch - 1900)) <= 69) + if (year <= 69) year += 100; - rtc_tm.tm_year = year + 1900; + rtc_tm.tm_year = year; rtc_tm.tm_yday = 0; /* Not implemented for now */ rtc_tm.tm_isdst = -1; /* Not implemented for now */ @@ -156,7 +151,20 @@ int rtc_read_datetime(unsigned char* buf) int rtc_write_datetime(unsigned char* buf) { - (void)buf; + struct tm *rtc_tm = (struct tm*)buf; + unsigned int year, lval; + + year = rtc_tm->tm_year; + /* Don't use centry, but start from year 1970 */ + if (year > 69) + year -= 100; + year += 2000; + + lval = jz_mktime(year, rtc_tm->tm_mon, rtc_tm->tm_mday, rtc_tm->tm_hour, + rtc_tm->tm_min, rtc_tm->tm_sec); + REG_RTC_RSR = lval; + + return 0; } #if 0 diff --git a/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4740.c b/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4740.c index 0b31e8e74d..5d670a8291 100644 --- a/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4740.c @@ -30,16 +30,19 @@ #include "panic.h" #include "debug.h" #include "storage.h" +#include "string.h" static struct wakeup sd_wakeup; +static long last_disk_activity = -1; //#define MMC_DMA_ENABLE #define MMC_DMA_INTERRUPT 0 -#define DEBUG(x...) logf(x); +#define DEBUG(x...) logf(x) -#define MMC_INSERT_STATUS() __gpio_get_pin(MMC_CD_PIN) +#define BLOCK_SIZE 512 +#define MMC_INSERT_STATUS() __gpio_get_pin(MMC_CD_PIN) #define MMC_RESET() __msc_reset() #define MMC_IRQ_MASK() \ @@ -81,49 +84,49 @@ enum mmc_result_t #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 */ +/* 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_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_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 */ +#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 */ +#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_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 */ +#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_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 */ @@ -135,12 +138,12 @@ enum mmc_result_t /* class 8 */ #define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */ -#define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1b */ +#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 */ +#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 @@ -154,6 +157,7 @@ enum mmc_rsp_t RESPONSE_R4 = 6, RESPONSE_R5 = 7, RESPONSE_R6 = 8, + RESPONSE_R7 = 9, }; @@ -196,20 +200,6 @@ enum mmc_rsp_t #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 { @@ -276,7 +266,7 @@ struct mmc_csd 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 */ @@ -323,7 +313,6 @@ typedef struct MMC_INFO 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; @@ -333,8 +322,6 @@ typedef struct MMC_INFO unsigned int erase_unit; } mmc_info; -static mmc_info mmcinfo; - struct mmc_request { int index; /* Slot index - used for CS lines */ @@ -354,6 +341,7 @@ struct mmc_request }; #define MMC_OCR_ARG 0x00ff8000 /* Argument of OCR */ +//#define MMC_OCR_ARG 0x40300000 /*********************************************************************** * MMC Events @@ -363,16 +351,320 @@ struct mmc_request #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 = 1; +static int use_4bit = 1; /* Use 4-bit data bus */ +static int num_6 = 0; +static int sd2_0 = 0; +static mmc_info mmcinfo; + +/************************************************************************** + * Utility functions + **************************************************************************/ + +#define PARSE_U32(_buf,_index) \ + (((unsigned int)_buf[_index]) << 24) | (((unsigned int)_buf[_index+1]) << 16) | \ + (((unsigned int)_buf[_index+2]) << 8) | ((unsigned int)_buf[_index+3]); + +#define PARSE_U16(_buf,_index) \ + (((unsigned short)_buf[_index]) << 8) | ((unsigned short)_buf[_index+1]); + +int mmc_unpack_csd(struct mmc_request *request, struct mmc_csd *csd) +{ + unsigned char *buf = request->response; + int num = 0; + + if (request->result) + return request->result; + + csd->csd_structure = (buf[1] & 0xc0) >> 6; + if (csd->csd_structure) + sd2_0 = 1; + else + sd2_0 = 0; + + switch (csd->csd_structure) { + case 0 : + csd->taac = buf[2]; + csd->nsac = buf[3]; + csd->tran_speed = buf[4]; + csd->ccc = (((unsigned short)buf[5]) << 4) | ((buf[6] & 0xf0) >> 4); + csd->read_bl_len = buf[6] & 0x0f; + /* for support 2GB card*/ + if (csd->read_bl_len >= 10) + { + num = csd->read_bl_len - 9; + csd->read_bl_len = 9; + } + + csd->read_bl_partial = (buf[7] & 0x80) ? 1 : 0; + csd->write_blk_misalign = (buf[7] & 0x40) ? 1 : 0; + csd->read_blk_misalign = (buf[7] & 0x20) ? 1 : 0; + csd->dsr_imp = (buf[7] & 0x10) ? 1 : 0; + csd->c_size = ((((unsigned short)buf[7]) & 0x03) << 10) | (((unsigned short)buf[8]) << 2) | (((unsigned short)buf[9]) & 0xc0) >> 6; + + if (num) + csd->c_size = csd->c_size << num; + + + csd->vdd_r_curr_min = (buf[9] & 0x38) >> 3; + csd->vdd_r_curr_max = buf[9] & 0x07; + csd->vdd_w_curr_min = (buf[10] & 0xe0) >> 5; + csd->vdd_w_curr_max = (buf[10] & 0x1c) >> 2; + csd->c_size_mult = ((buf[10] & 0x03) << 1) | ((buf[11] & 0x80) >> 7); + switch (csd->csd_structure) { + case CSD_STRUCT_VER_1_0: + case CSD_STRUCT_VER_1_1: + csd->erase.v22.sector_size = (buf[11] & 0x7c) >> 2; + csd->erase.v22.erase_grp_size = ((buf[11] & 0x03) << 3) | ((buf[12] & 0xe0) >> 5); + + break; + case CSD_STRUCT_VER_1_2: + default: + csd->erase.v31.erase_grp_size = (buf[11] & 0x7c) >> 2; + csd->erase.v31.erase_grp_mult = ((buf[11] & 0x03) << 3) | ((buf[12] & 0xe0) >> 5); + break; + } + csd->wp_grp_size = buf[12] & 0x1f; + csd->wp_grp_enable = (buf[13] & 0x80) ? 1 : 0; + csd->default_ecc = (buf[13] & 0x60) >> 5; + csd->r2w_factor = (buf[13] & 0x1c) >> 2; + csd->write_bl_len = ((buf[13] & 0x03) << 2) | ((buf[14] & 0xc0) >> 6); + if (csd->write_bl_len >= 10) + csd->write_bl_len = 9; + + csd->write_bl_partial = (buf[14] & 0x20) ? 1 : 0; + csd->file_format_grp = (buf[15] & 0x80) ? 1 : 0; + csd->copy = (buf[15] & 0x40) ? 1 : 0; + csd->perm_write_protect = (buf[15] & 0x20) ? 1 : 0; + csd->tmp_write_protect = (buf[15] & 0x10) ? 1 : 0; + csd->file_format = (buf[15] & 0x0c) >> 2; + csd->ecc = buf[15] & 0x03; + + DEBUG("csd_structure=%d spec_vers=%d taac=%02x nsac=%02x tran_speed=%02x", + csd->csd_structure, csd->spec_vers, + csd->taac, csd->nsac, csd->tran_speed); + DEBUG("ccc=%04x read_bl_len=%d read_bl_partial=%d write_blk_misalign=%d", + csd->ccc, csd->read_bl_len, + csd->read_bl_partial, csd->write_blk_misalign); + DEBUG("read_blk_misalign=%d dsr_imp=%d c_size=%d vdd_r_curr_min=%d", + csd->read_blk_misalign, csd->dsr_imp, + csd->c_size, csd->vdd_r_curr_min); + DEBUG("vdd_r_curr_max=%d vdd_w_curr_min=%d vdd_w_curr_max=%d c_size_mult=%d", + csd->vdd_r_curr_max, csd->vdd_w_curr_min, + csd->vdd_w_curr_max, csd->c_size_mult); + DEBUG("wp_grp_size=%d wp_grp_enable=%d default_ecc=%d r2w_factor=%d", + csd->wp_grp_size, csd->wp_grp_enable, + csd->default_ecc, csd->r2w_factor); + DEBUG("write_bl_len=%d write_bl_partial=%d file_format_grp=%d copy=%d", + csd->write_bl_len, csd->write_bl_partial, + csd->file_format_grp, csd->copy); + DEBUG("perm_write_protect=%d tmp_write_protect=%d file_format=%d ecc=%d", + csd->perm_write_protect, csd->tmp_write_protect, + csd->file_format, csd->ecc); + switch (csd->csd_structure) { + case CSD_STRUCT_VER_1_0: + case CSD_STRUCT_VER_1_1: + DEBUG("V22 sector_size=%d erase_grp_size=%d", + csd->erase.v22.sector_size, + csd->erase.v22.erase_grp_size); + break; + case CSD_STRUCT_VER_1_2: + default: + DEBUG("V31 erase_grp_size=%d erase_grp_mult=%d", + csd->erase.v31.erase_grp_size, + csd->erase.v31.erase_grp_mult); + break; + + } + break; + + case 1 : + csd->taac = 0; + csd->nsac = 0; + csd->tran_speed = buf[4]; + csd->ccc = (((unsigned short)buf[5]) << 4) | ((buf[6] & 0xf0) >> 4); + + csd->read_bl_len = 9; + csd->read_bl_partial = 0; + csd->write_blk_misalign = 0; + csd->read_blk_misalign = 0; + csd->dsr_imp = (buf[7] & 0x10) ? 1 : 0; + csd->c_size = ((((unsigned short)buf[8]) & 0x3f) << 16) | (((unsigned short)buf[9]) << 8) | ((unsigned short)buf[10]) ; + switch (csd->csd_structure) { + case CSD_STRUCT_VER_1_0: + case CSD_STRUCT_VER_1_1: + csd->erase.v22.sector_size = 0x7f; + csd->erase.v22.erase_grp_size = 0; + break; + case CSD_STRUCT_VER_1_2: + default: + csd->erase.v31.erase_grp_size = 0x7f; + csd->erase.v31.erase_grp_mult = 0; + break; + } + csd->wp_grp_size = 0; + csd->wp_grp_enable = 0; + csd->default_ecc = (buf[13] & 0x60) >> 5; + csd->r2w_factor = 4;/* Unused */ + csd->write_bl_len = 9; + + csd->write_bl_partial = 0; + csd->file_format_grp = 0; + csd->copy = (buf[15] & 0x40) ? 1 : 0; + csd->perm_write_protect = (buf[15] & 0x20) ? 1 : 0; + csd->tmp_write_protect = (buf[15] & 0x10) ? 1 : 0; + csd->file_format = 0; + csd->ecc = buf[15] & 0x03; + + DEBUG("csd_structure=%d spec_vers=%d taac=%02x nsac=%02x tran_speed=%02x", + csd->csd_structure, csd->spec_vers, + csd->taac, csd->nsac, csd->tran_speed); + DEBUG("ccc=%04x read_bl_len=%d read_bl_partial=%d write_blk_misalign=%d", + csd->ccc, csd->read_bl_len, + csd->read_bl_partial, csd->write_blk_misalign); + DEBUG("read_blk_misalign=%d dsr_imp=%d c_size=%d vdd_r_curr_min=%d", + csd->read_blk_misalign, csd->dsr_imp, + csd->c_size, csd->vdd_r_curr_min); + DEBUG("vdd_r_curr_max=%d vdd_w_curr_min=%d vdd_w_curr_max=%d c_size_mult=%d", + csd->vdd_r_curr_max, csd->vdd_w_curr_min, + csd->vdd_w_curr_max, csd->c_size_mult); + DEBUG("wp_grp_size=%d wp_grp_enable=%d default_ecc=%d r2w_factor=%d", + csd->wp_grp_size, csd->wp_grp_enable, + csd->default_ecc, csd->r2w_factor); + DEBUG("write_bl_len=%d write_bl_partial=%d file_format_grp=%d copy=%d", + csd->write_bl_len, csd->write_bl_partial, + csd->file_format_grp, csd->copy); + DEBUG("perm_write_protect=%d tmp_write_protect=%d file_format=%d ecc=%d", + csd->perm_write_protect, csd->tmp_write_protect, + csd->file_format, csd->ecc); + switch (csd->csd_structure) { + case CSD_STRUCT_VER_1_0: + case CSD_STRUCT_VER_1_1: + DEBUG("V22 sector_size=%d erase_grp_size=%d", + csd->erase.v22.sector_size, + csd->erase.v22.erase_grp_size); + break; + case CSD_STRUCT_VER_1_2: + default: + DEBUG("V31 erase_grp_size=%d erase_grp_mult=%d", + csd->erase.v31.erase_grp_size, + csd->erase.v31.erase_grp_mult); + break; + } + } + + if (buf[0] != 0x3f) + return MMC_ERROR_HEADER_MISMATCH; + + return 0; +} + +int mmc_unpack_r1(struct mmc_request *request, struct mmc_response_r1 *r1) +{ + unsigned char *buf = request->response; + + if (request->result) + return request->result; + + r1->cmd = buf[0]; + r1->status = PARSE_U32(buf,1); + + DEBUG("mmc_unpack_r1: cmd=%d status=%08x", r1->cmd, r1->status); + + if (R1_STATUS(r1->status)) { + if (r1->status & R1_OUT_OF_RANGE) return MMC_ERROR_OUT_OF_RANGE; + if (r1->status & R1_ADDRESS_ERROR) return MMC_ERROR_ADDRESS; + if (r1->status & R1_BLOCK_LEN_ERROR) return MMC_ERROR_BLOCK_LEN; + if (r1->status & R1_ERASE_SEQ_ERROR) return MMC_ERROR_ERASE_SEQ; + if (r1->status & R1_ERASE_PARAM) return MMC_ERROR_ERASE_PARAM; + if (r1->status & R1_WP_VIOLATION) return MMC_ERROR_WP_VIOLATION; + //if (r1->status & R1_CARD_IS_LOCKED) return MMC_ERROR_CARD_IS_LOCKED; + if (r1->status & R1_LOCK_UNLOCK_FAILED) return MMC_ERROR_LOCK_UNLOCK_FAILED; + if (r1->status & R1_COM_CRC_ERROR) return MMC_ERROR_COM_CRC; + if (r1->status & R1_ILLEGAL_COMMAND) return MMC_ERROR_ILLEGAL_COMMAND; + if (r1->status & R1_CARD_ECC_FAILED) return MMC_ERROR_CARD_ECC_FAILED; + if (r1->status & R1_CC_ERROR) return MMC_ERROR_CC; + if (r1->status & R1_ERROR) return MMC_ERROR_GENERAL; + if (r1->status & R1_UNDERRUN) return MMC_ERROR_UNDERRUN; + if (r1->status & R1_OVERRUN) return MMC_ERROR_OVERRUN; + if (r1->status & R1_CID_CSD_OVERWRITE) return MMC_ERROR_CID_CSD_OVERWRITE; + } + + if (buf[0] != request->cmd) + return MMC_ERROR_HEADER_MISMATCH; + + /* This should be last - it's the least dangerous error */ + + return 0; +} + +int mmc_unpack_scr(struct mmc_request *request, struct mmc_response_r1 *r1, unsigned int *scr) +{ + unsigned char *buf = request->response; + if (request->result) + return request->result; + + *scr = PARSE_U32(buf, 5); /* Save SCR returned by the SD Card */ + return mmc_unpack_r1(request, r1); +} + +int mmc_unpack_r6(struct mmc_request *request, struct mmc_response_r1 *r1, int *rca) +{ + unsigned char *buf = request->response; + + if (request->result) return request->result; + + *rca = PARSE_U16(buf,1); /* Save RCA returned by the SD Card */ + + *(buf+1) = 0; + *(buf+2) = 0; + + return mmc_unpack_r1(request, r1); +} + +int mmc_unpack_cid(struct mmc_request *request, struct mmc_cid *cid) +{ + unsigned char *buf = request->response; + int i; + + if (request->result) return request->result; + + cid->mid = buf[1]; + cid->oid = PARSE_U16(buf,2); + for (i = 0 ; i < 6 ; i++) + cid->pnm[i] = buf[4+i]; + cid->pnm[6] = 0; + cid->prv = buf[10]; + cid->psn = PARSE_U32(buf,11); + cid->mdt = buf[15]; + + DEBUG("mmc_unpack_cid: mid=%d oid=%d pnm=%s prv=%d.%d psn=%08x mdt=%d/%d", + cid->mid, cid->oid, cid->pnm, + (cid->prv>>4), (cid->prv&0xf), + cid->psn, (cid->mdt>>4), (cid->mdt&0xf)+1997); + + if (buf[0] != 0x3f) return MMC_ERROR_HEADER_MISMATCH; + return 0; +} + +int mmc_unpack_r3(struct mmc_request *request, struct mmc_response_r3 *r3) +{ + unsigned char *buf = request->response; + + if (request->result) return request->result; + + r3->ocr = PARSE_U32(buf,1); + DEBUG("mmc_unpack_r3: ocr=%08x", r3->ocr); + + if (buf[0] != 0x3f) return MMC_ERROR_HEADER_MISMATCH; + return 0; +} /* Stop the MMC clock and wait while it happens */ static inline int jz_mmc_stop_clock(void) { - int timeout = 1000; + register int timeout = 1000; - DEBUG("stop MMC clock"); + //DEBUG("stop MMC clock"); REG_MSC_STRPCL = MSC_STRPCL_CLOCK_CONTROL_STOP; while (timeout && (REG_MSC_STAT & MSC_STAT_CLK_EN)) @@ -385,40 +677,26 @@ static inline int jz_mmc_stop_clock(void) } udelay(1); } - DEBUG("clock off time is %d microsec", timeout); + //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; + 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) { + (void)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, + DEBUG("MMC/SD timeout, MSC_STAT 0x%x CMD %d", status, request->cmd); return MMC_ERROR_TIMEOUT; } @@ -428,9 +706,18 @@ static int jz_mmc_check_status(struct mmc_request *request) (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); + DEBUG("MMC/SD CRC error, MSC_STAT 0x%x", status); return MMC_ERROR_CRC; + } + + + /* Checking for FIFO empty */ + /*if(status & MSC_STAT_DATA_FIFO_EMPTY && request->rtype != RESPONSE_NONE) + { + DEBUG("MMC/SD FIFO empty, MSC_STAT 0x%x", status); + return MMC_ERROR_UNDERRUN; + }*/ return MMC_NO_ERROR; } @@ -451,6 +738,7 @@ static void jz_mmc_get_response(struct mmc_request *request) { case RESPONSE_R1: case RESPONSE_R1B: + case RESPONSE_R7: case RESPONSE_R6: case RESPONSE_R3: case RESPONSE_R4: @@ -686,6 +974,20 @@ static int jz_mmc_transmit_data(struct mmc_request *req) 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; +} + /* Set the MMC clock frequency */ static void jz_mmc_set_clock(int sd, unsigned int rate) { @@ -695,19 +997,20 @@ static void jz_mmc_set_clock(int sd, unsigned int rate) jz_mmc_stop_clock(); - if(sd2_0) + if (sd2_0) { - __cpm_select_msc_hs_clk(sd); /* select clock source from CPM */ + __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 */ + __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); } @@ -724,8 +1027,8 @@ static int jz_mmc_exec_cmd(struct mmc_request *request) /* Indicate we have no result yet */ request->result = MMC_NO_RESPONSE; - if (request->cmd == MMC_CIM_RESET) - { + + if (request->cmd == MMC_CIM_RESET) { /* On reset, 1-bit bus width */ use_4bit = 0; @@ -733,19 +1036,11 @@ static int jz_mmc_exec_cmd(struct mmc_request *request) __msc_reset(); /* On reset, drop MMC clock down */ - jz_mmc_set_clock(0, MMC_CLOCK_SLOW); + jz_mmc_set_clock(1, MMC_CLOCK_SLOW); /* On reset, stop MMC clock */ jz_mmc_stop_clock(); } -#if 0 - if (request->cmd == MMC_SEND_OP_COND) - { - DEBUG("Have a MMC card"); - /* always use 1bit for MMC */ - use_4bit = 0; - } -#endif if (request->cmd == SET_BUS_WIDTH) { if (request->arg == 0x2) @@ -764,7 +1059,7 @@ static int jz_mmc_exec_cmd(struct mmc_request *request) jz_mmc_stop_clock(); /* mask all interrupts */ - REG_MSC_IMASK = 0xffff; + //REG_MSC_IMASK = 0xffff; /* clear status */ REG_MSC_IREG = 0xffff; /*open interrupt */ @@ -778,9 +1073,8 @@ static int jz_mmc_exec_cmd(struct mmc_request *request) { /* MMC core extra command */ case MMC_CIM_RESET: - cmdat |= MSC_CMDAT_INIT; /* Initialization sequence sent prior to command */ + cmdat |= MSC_CMDAT_INIT; /* Initialization sequence sent prior to command */ break; - /* bc - broadcast - no response */ case MMC_GO_IDLE_STATE: case MMC_SET_DSR: @@ -854,8 +1148,9 @@ static int jz_mmc_exec_cmd(struct mmc_request *request) break; case RESPONSE_R1B: cmdat |= MSC_CMDAT_BUSY; - /*FALLTHRU*/ + /* FALLTHRU */ case RESPONSE_R1: + case RESPONSE_R7: cmdat |= MSC_CMDAT_RESPONSE_R1; break; case RESPONSE_R2_CID: @@ -964,7 +1259,6 @@ static int jz_mmc_exec_cmd(struct mmc_request *request) /* 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 */ @@ -1027,6 +1321,7 @@ static void jz_mmc_rx_handler(unsigned int arg) void MSC(void) { //wakeup_signal(&sd_wakeup); + logf("MSC interrupt"); } /******************************************************************************************************************* @@ -1037,8 +1332,8 @@ void MSC(void) ********************************************************************************************************************/ static void jz_mmc_hardware_init(void) { - mmc_init_gpio(); /* init GPIO */ __cpm_start_msc(); /* enable mmc clock */ + mmc_init_gpio(); /* init GPIO */ #ifdef MMC_POWER_ON MMC_POWER_ON(); /* turn on power of card */ #endif @@ -1060,7 +1355,7 @@ static void jz_mmc_hardware_init(void) #endif } -static void mmc_send_cmd(struct mmc_request *request, int cmd, unsigned int arg, +static int 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) { @@ -1071,26 +1366,284 @@ static void mmc_send_cmd(struct mmc_request *request, int cmd, unsigned int arg, request->block_len = block_len; request->buffer = buffer; request->cnt = nob * block_len; - logf("mmc_send_cmd: command = %d",cmd); - jz_mmc_exec_cmd(request); + + return jz_mmc_exec_cmd(request); } -static bool inited = false; -int _sd_init(void) +static void mmc_simple_cmd(struct mmc_request *request, int cmd, unsigned int arg, + enum mmc_rsp_t rtype) { + mmc_send_cmd(request, cmd, arg, 0, 0, rtype, NULL); +} + +#define KBPS 1 +#define MBPS 1000 +static unsigned int ts_exp[] = { 100*KBPS, 1*MBPS, 10*MBPS, 100*MBPS, 0, 0, 0, 0 }; +static unsigned int ts_mul[] = { 0, 1000, 1200, 1300, 1500, 2000, 2500, 3000, + 3500, 4000, 4500, 5000, 5500, 6000, 7000, 8000 }; + +unsigned int mmc_tran_speed(unsigned char ts) +{ + unsigned int rate = ts_exp[(ts & 0x7)] * ts_mul[(ts & 0x78) >> 3]; + + if (rate <= 0) + { + DEBUG("mmc_tran_speed: error - unrecognized speed 0x%02x", ts); + return 1; + } + + return rate; +} + +static void mmc_configure_card(void) +{ + unsigned int rate; + + /* Get card info */ + if (sd2_0) + mmcinfo.block_num = (mmcinfo.csd.c_size + 1) << 10; + else + mmcinfo.block_num = (mmcinfo.csd.c_size + 1) * (1 << (mmcinfo.csd.c_size_mult + 2)); + + mmcinfo.block_len = 1 << mmcinfo.csd.read_bl_len; + + /* Fix the clock rate */ + rate = mmc_tran_speed(mmcinfo.csd.tran_speed); + if (rate < MMC_CLOCK_SLOW) + rate = MMC_CLOCK_SLOW; + if (rate > SD_CLOCK_FAST) + rate = SD_CLOCK_FAST; + + DEBUG("mmc_configure_card: block_len=%d block_num=%d rate=%d", mmcinfo.block_len, mmcinfo.block_num, rate); + + jz_mmc_set_clock(1, rate); +} + +#define MMC_INIT_DOING 0 +#define MMC_INIT_PASSED 1 +#define MMC_INIT_FAILED 2 + +static int mmc_init_card_state(struct mmc_request *request) +{ + struct mmc_response_r1 r1; + struct mmc_response_r3 r3; + int retval; + int ocr = 0x40300000; + int limit_41 = 0; + + switch (request->cmd) + { + case MMC_GO_IDLE_STATE: /* No response to parse */ + mmc_simple_cmd(request, SD_SEND_IF_COND, 0x1AA, RESPONSE_R1); + break; + + case SD_SEND_IF_COND: + mmc_simple_cmd(request, MMC_APP_CMD, 0, RESPONSE_R1); + break; + + case MMC_APP_CMD: + retval = mmc_unpack_r1(request, &r1); + if (retval & (limit_41 < 100)) + { + DEBUG("mmc_init_card_state: unable to MMC_APP_CMD error=%d", + retval); + limit_41++; + mmc_simple_cmd(request, SD_SEND_OP_COND, ocr, RESPONSE_R3); + } else if (limit_41 < 100) { + limit_41++; + mmc_simple_cmd(request, SD_SEND_OP_COND, ocr, RESPONSE_R3); + } else{ + /* reset the card to idle*/ + mmc_simple_cmd(request, MMC_GO_IDLE_STATE, 0, RESPONSE_NONE); + } + break; + + case SD_SEND_OP_COND: + retval = mmc_unpack_r3(request, &r3); + if (retval) + { + /* Try MMC card */ + mmc_simple_cmd(request, MMC_SEND_OP_COND, MMC_OCR_ARG, RESPONSE_R3); + break; + } + + DEBUG("mmc_init_card_state: read ocr value = 0x%08x", r3.ocr); + + if(!(r3.ocr & MMC_CARD_BUSY || ocr == 0)){ + udelay(10000); + mmc_simple_cmd(request, MMC_APP_CMD, 0, RESPONSE_R1); + } + else + { + /* Set the data bus width to 4 bits */ + use_4bit = 1; + mmc_simple_cmd(request, MMC_ALL_SEND_CID, 0, RESPONSE_R2_CID); + } + break; + + case MMC_SEND_OP_COND: + retval = mmc_unpack_r3(request, &r3); + if (retval) + { + DEBUG("mmc_init_card_state: failed SEND_OP_COND error=%d", + retval); + return MMC_INIT_FAILED; + } + + DEBUG("mmc_init_card_state: read ocr value = 0x%08x", r3.ocr); + if (!(r3.ocr & MMC_CARD_BUSY)) + mmc_simple_cmd(request, MMC_SEND_OP_COND, MMC_OCR_ARG, RESPONSE_R3); + else + mmc_simple_cmd(request, MMC_ALL_SEND_CID, 0, RESPONSE_R2_CID); + break; + + case MMC_ALL_SEND_CID: + retval = mmc_unpack_cid( request, &mmcinfo.cid ); + + if ( retval && (retval != MMC_ERROR_CRC)) { + DEBUG("mmc_init_card_state: unable to ALL_SEND_CID error=%d", + retval); + return MMC_INIT_FAILED; + } + mmc_simple_cmd(request, MMC_SET_RELATIVE_ADDR, 0, RESPONSE_R6); + break; + + case MMC_SET_RELATIVE_ADDR: + retval = mmc_unpack_r6(request, &r1, &mmcinfo.rca); + mmcinfo.rca = mmcinfo.rca << 16; + DEBUG("mmc_init_card_state: Get RCA from SD: 0x%04x Status: %x", mmcinfo.rca, r1.status); + if (retval) + { + DEBUG("mmc_init_card_state: unable to SET_RELATIVE_ADDR error=%d", + retval); + return MMC_INIT_FAILED; + } + + mmc_simple_cmd(request, MMC_SEND_CSD, mmcinfo.rca, RESPONSE_R2_CSD); + break; + + case MMC_SEND_CSD: + retval = mmc_unpack_csd(request, &mmcinfo.csd); + + DEBUG("SD card is ready"); + + /*FIXME:ignore CRC error for CMD2/CMD9/CMD10 */ + if (retval && (retval != MMC_ERROR_CRC)) + { + DEBUG("mmc_init_card_state: unable to SEND_CSD error=%d", + retval); + return MMC_INIT_FAILED; + } + mmc_configure_card(); + return MMC_INIT_PASSED; + + default: + DEBUG("mmc_init_card_state: error! Illegal last cmd %d", request->cmd); + return MMC_INIT_FAILED; + } + + return MMC_INIT_DOING; +} + +static int mmc_sd_switch(struct mmc_request *request, int mode, int group, + unsigned char value, unsigned char * resp) +{ + unsigned int arg; + + mode = !!mode; + value &= 0xF; + arg = (mode << 31 | 0x00FFFFFF); + arg &= ~(0xF << (group * 4)); + arg |= value << (group * 4); + mmc_send_cmd(request, 6, arg, 1, 64, RESPONSE_R1, resp); + + return 0; +} + +/* + * Fetches and decodes switch information + */ +static int mmc_read_switch(struct mmc_request *request) +{ + unsigned int status[64 / 4]; + + memset((unsigned char *)status, 0, 64); + mmc_sd_switch(request, 0, 0, 1, (unsigned char*) status); + + if (((unsigned char *)status)[13] & 0x02) + return 0; + else + return 1; +} + +/* + * Test if the card supports high-speed mode and, if so, switch to it. + */ +static int mmc_switch_hs(struct mmc_request *request) +{ + unsigned int status[64 / 4]; + + mmc_sd_switch(request, 1, 0, 1, (unsigned char*) status); + return 0; +} + +int mmc_select_card(void) +{ + struct mmc_request request; + struct mmc_response_r1 r1; + int retval; + + mmc_simple_cmd(&request, MMC_SELECT_CARD, mmcinfo.rca, + RESPONSE_R1B); + retval = mmc_unpack_r1(&request, &r1); + if (retval) + return retval; + + if (sd2_0) + { + retval = mmc_read_switch(&request); + if (!retval) + { + mmc_switch_hs(&request); + jz_mmc_set_clock(1, SD_CLOCK_HIGH); + } + } + num_6 = 3; + mmc_simple_cmd(&request, MMC_APP_CMD, mmcinfo.rca, + RESPONSE_R1); + retval = mmc_unpack_r1(&request, &r1); + if (retval) + return retval; + mmc_simple_cmd(&request, SET_BUS_WIDTH, 2, RESPONSE_R1); + retval = mmc_unpack_r1(&request, &r1); + if (retval) + return retval; + + return retval; +} + +int sd_init(void) +{ + int retval; + static bool inited = false; + struct mmc_request init_req; if(!inited) { jz_mmc_hardware_init(); wakeup_init(&sd_wakeup); + num_6 = 0; 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); + mmc_send_cmd(&init_req, MMC_CIM_RESET, 0, 0, 0, RESPONSE_NONE, NULL); + mmc_send_cmd(&init_req, SD_GO_IDLE_STATE, 0, 0, 0, RESPONSE_NONE, NULL); - return 0; + while ((retval = mmc_init_card_state(&init_req)) == MMC_INIT_DOING); + + if (retval == MMC_INIT_PASSED) + return mmc_select_card(); + else + return -1; } bool card_detect_target(void) @@ -1115,27 +1668,150 @@ void card_enable_monitoring_target(bool on) /* TODO */ tCardInfo* card_get_info_target(int card_no) { + (void)card_no; + int i, temp; static tCardInfo card; + static const char mantissa[] = { /* *10 */ + 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80 }; + static const int exponent[] = { /* use varies */ + 1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000 }; + + card.initialized = true; + card.ocr = 0; + for(i=0; i<4; i++) + card.csd[i] = (*((unsigned long*)&mmcinfo.csd+4*i)); + for(i=0; i<4; i++) + card.cid[i] = (*((unsigned long*)&mmcinfo.cid+4*i)); + temp = card_extract_bits(card.csd, 29, 3); + card.speed = mantissa[card_extract_bits(card.csd, 25, 4)] + * exponent[temp > 2 ? 7 : temp + 4]; + card.nsac = 100 * card_extract_bits(card.csd, 16, 8); + temp = card_extract_bits(card.csd, 13, 3); + card.tsac = mantissa[card_extract_bits(card.csd, 9, 4)] + * exponent[temp] / 10; + card.numblocks = mmcinfo.block_num; + card.blocksize = mmcinfo.block_len; return &card; } -/* TODO */ -int _sd_read_sectors(unsigned long start, int count, void* buf) +int sd_read_sectors(IF_MV2(int drive,) unsigned long start, int count, void* buf) { - (void)start; - (void)count; - (void)buf; - return -1; + (void)drive; + struct mmc_request request; + struct mmc_response_r1 r1; + int retval; + + if (!card_detect_target() || count == 0 || start > mmcinfo.block_num) + return -1; + + mmc_simple_cmd(&request, MMC_SEND_STATUS, mmcinfo.rca, RESPONSE_R1); + retval = mmc_unpack_r1(&request, &r1); + if (retval && (retval != MMC_ERROR_STATE_MISMATCH)) + return retval; + + mmc_simple_cmd(&request, MMC_SET_BLOCKLEN, BLOCK_SIZE, RESPONSE_R1); + if ((retval = mmc_unpack_r1(&request, &r1))) + return retval; + + if (sd2_0) + { + mmc_send_cmd(&request, MMC_READ_MULTIPLE_BLOCK, start, + count, BLOCK_SIZE, RESPONSE_R1, buf); + if ((retval = mmc_unpack_r1(&request, &r1))) + return retval; + } + else + { + mmc_send_cmd(&request, MMC_READ_MULTIPLE_BLOCK, + start * BLOCK_SIZE, count, + BLOCK_SIZE, RESPONSE_R1, buf); + if ((retval = mmc_unpack_r1(&request, &r1))) + return retval; + } + + last_disk_activity = current_tick; + + mmc_simple_cmd(&request, MMC_STOP_TRANSMISSION, 0, RESPONSE_R1B); + if ((retval = mmc_unpack_r1(&request, &r1))) + return retval; + + return retval; } -/* TODO */ -int _sd_write_sectors(unsigned long start, int count, const void* buf) +int sd_write_sectors(IF_MV2(int drive,) unsigned long start, int count, const void* buf) { - (void)start; - (void)count; - (void)buf; - return -1; + (void)drive; + struct mmc_request request; + struct mmc_response_r1 r1; + int retval; + + if (!card_detect_target() || count == 0 || start > mmcinfo.block_num) + return -1; + + mmc_simple_cmd(&request, MMC_SEND_STATUS, mmcinfo.rca, RESPONSE_R1); + retval = mmc_unpack_r1(&request, &r1); + if (retval && (retval != MMC_ERROR_STATE_MISMATCH)) + return retval; + + mmc_simple_cmd(&request, MMC_SET_BLOCKLEN, BLOCK_SIZE, RESPONSE_R1); + if ((retval = mmc_unpack_r1(&request, &r1))) + return retval; + + if (sd2_0) + { + mmc_send_cmd(&request, MMC_WRITE_MULTIPLE_BLOCK, start, + count, BLOCK_SIZE, RESPONSE_R1, + (void*)buf); + if ((retval = mmc_unpack_r1(&request, &r1))) + return retval; + } + else + { + mmc_send_cmd(&request, MMC_WRITE_MULTIPLE_BLOCK, + start * BLOCK_SIZE, count, + BLOCK_SIZE, RESPONSE_R1, (void*)buf); + if ((retval = mmc_unpack_r1(&request, &r1))) + return retval; + } + mmc_simple_cmd(&request, MMC_STOP_TRANSMISSION, 0, RESPONSE_R1B); + if ((retval = mmc_unpack_r1(&request, &r1))) + return retval; + + return retval; +} + +void sd_sleep(void) +{ +} + +void sd_spin(void) +{ +} + +long sd_last_disk_activity(void) +{ + return last_disk_activity; +} + +void sd_spindown(int seconds) +{ + (void)seconds; +} + +#ifdef HAVE_HOTSWAP +bool sd_removable(IF_MV_NONVOID(int drive)) +{ + (void)drive; + //return true; + return false; +} +#endif + +bool sd_present(IF_MV_NONVOID(int drive)) +{ + (void)drive; + return (mmcinfo.block_num > 0 && card_detect_target()); } #ifdef STORAGE_GET_INFO @@ -1149,8 +1825,7 @@ void sd_get_info(IF_MV2(int drive,) struct storage_info *info) info->product="SD Storage"; /* blocks count */ - /* TODO: proper amount of sectors! */ - info->num_sectors = 0; - info->sector_size = 512; + info->num_sectors = mmcinfo.block_num; + info->sector_size = mmcinfo.block_len; } #endif diff --git a/firmware/target/mips/ingenic_jz47xx/codec-jz4740.c b/firmware/target/mips/ingenic_jz47xx/codec-jz4740.c index ef8c343035..c76c63dd78 100644 --- a/firmware/target/mips/ingenic_jz47xx/codec-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/codec-jz4740.c @@ -22,6 +22,23 @@ #include "config.h" #include "jz4740.h" #include "system.h" +#include "audiohw.h" + +/* TODO */ +const struct sound_settings_info audiohw_settings[] = { + [SOUND_VOLUME] = {"dB", 0, 1, -73, 6, -20}, + /* HAVE_SW_TONE_CONTROLS */ + [SOUND_BASS] = {"dB", 0, 1, -24, 24, 0}, + [SOUND_TREBLE] = {"dB", 0, 1, -24, 24, 0}, + [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0}, + [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0}, + [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100}, +#ifdef HAVE_RECORDING + [SOUND_LEFT_GAIN] = {"dB", 1, 1, 0, 31, 23}, + [SOUND_RIGHT_GAIN] = {"dB", 1, 1, 0, 31, 23}, + [SOUND_MIC_GAIN] = {"dB", 1, 1, 0, 1, 1}, +#endif +}; static unsigned short codec_volume; static unsigned short codec_base_gain; diff --git a/firmware/target/mips/ingenic_jz47xx/crt0.S b/firmware/target/mips/ingenic_jz47xx/crt0.S index e619022fc8..6ac40c2f52 100644 --- a/firmware/target/mips/ingenic_jz47xx/crt0.S +++ b/firmware/target/mips/ingenic_jz47xx/crt0.S @@ -43,14 +43,16 @@ .set mips32 .extern system_main + .extern main + .global _start - .global _start .section .init.text .set noreorder .set noat #ifdef BOOTLOADER - .word 0 /* Unknown */ + /* These will get filled in scramble */ + .word 0 /* Unknown */ .word 0 /* Filesize */ /* Relocate bootloader */ @@ -64,12 +66,12 @@ _relocate_loop: bne t1, t2, _relocate_loop addiu t0, 4 #endif - + _start: la ra, _start /* ---------------------------------------------------- - init cp0 registers. + Init CP0 registers. ---------------------------------------------------- */ mtc0 zero, C0_WATCHLO @@ -90,21 +92,21 @@ _start: /* ---------------------------------------------------- - init caches, assumes a 4way*128set*32byte i/d cache + Init caches, assumes a 4way*128set*32byte I/D cache ---------------------------------------------------- */ - li t0, 3 // enable cache for kseg0 accesses - mtc0 t0, C0_CONFIG // CONFIG reg - la t0, 0x80000000 // an idx op should use an unmappable address - ori t1, t0, 0x4000 // 16kB cache - mtc0 zero, C0_TAGLO // TAGLO reg - mtc0 zero, C0_TAGHI // TAGHI reg + li t0, 3 # enable cache for kseg0 accesses + mtc0 t0, C0_CONFIG # CONFIG reg + la t0, 0x80000000 # an idx op should use an unmappable address + ori t1, t0, 0x4000 # 16kB cache + mtc0 zero, C0_TAGLO # TAGLO reg + mtc0 zero, C0_TAGHI # TAGHI reg _init_cache_loop: - cache 0x8, 0(t0) // index store icache tag - cache 0x9, 0(t0) // index store dcache tag + cache 0x8, 0(t0) # index store icache tag + cache 0x9, 0(t0) # index store dcache tag bne t0, t1, _init_cache_loop - addiu t0, t0, 0x20 // 32 bytes per cache line + addiu t0, t0, 0x20 # 32 bytes per cache line nop /* @@ -120,7 +122,7 @@ _init_cache_loop: /* ---------------------------------------------------- - clear BSS section + Clear BSS section ---------------------------------------------------- */ la t0, _edata @@ -132,7 +134,7 @@ _init_bss_loop: /* ---------------------------------------------------- - clear IBSS section + Clear IBSS section ---------------------------------------------------- */ la t0, _iedata @@ -144,7 +146,7 @@ _init_ibss_loop: /* ---------------------------------------------------- - copy IRAM section + Copy IRAM section ---------------------------------------------------- */ la t0, _iramcopy @@ -159,7 +161,7 @@ _init_iram_loop: /* ---------------------------------------------------- - setup stack, jump to C code + Setup stack ---------------------------------------------------- */ la sp, stackend @@ -171,7 +173,15 @@ _init_stack_loop: bne t0, sp, _init_stack_loop addiu t0, t0, 4 - la t0, system_main + /* + ---------------------------------------------------- + Jump to C code + ---------------------------------------------------- + */ + la t0, system_main /* Init clocks etc first */ + jalr t0 + nop + la t0, main jr t0 nop @@ -182,11 +192,10 @@ _init_stack_loop: * 0x180 - Exception/Interrupt handler * 0x200 - Special Exception Interrupt handler (when IV is set in CP0_CAUSE) */ - .section .vectors.1, "ax", %progbits - la k0, tlb_refill_handler - jr k0 + la k0, tlb_refill_handler + jr k0 nop .section .vectors.2, "ax", %progbits @@ -235,10 +244,10 @@ real_exception_handler: sw v1, 0x64(sp) sw v0, 0x68(sp) sw $1, 0x6C(sp) - mflo k0 # Move From LO + mflo k0 nop sw k0, 0x70(sp) - mfhi k0 # Move From HI + mfhi k0 nop sw k0, 0x74(sp) mfc0 k0, C0_STATUS # Status register @@ -294,10 +303,10 @@ _int: lw v0, 0x68(sp) lw $1, 0x6C(sp) lw k0, 0x70(sp) - mtlo k0 # Move To LO + mtlo k0 nop lw k0, 0x74(sp) - mthi k0 # Move To HI + mthi k0 nop lw k0, 0x78(sp) nop @@ -360,10 +369,10 @@ _exception: lw v0, 0x68(sp) lw $1, 0x6C(sp) lw k0, 0x70(sp) - mtlo k0 # Move To LO + mtlo k0 nop lw k0, 0x74(sp) - mthi k0 # Move To HI + mthi k0 nop lw k0, 0x78(sp) nop diff --git a/firmware/target/mips/ingenic_jz47xx/debug-jz4740.c b/firmware/target/mips/ingenic_jz47xx/debug-jz4740.c index 648d410cd6..2164f1d323 100644 --- a/firmware/target/mips/ingenic_jz47xx/debug-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/debug-jz4740.c @@ -21,6 +21,29 @@ #include "config.h" #include "jz4740.h" +#include "debug-target.h" +#include +#include +#include "lcd.h" +#include "kernel.h" +#include "font.h" +#include "button.h" + +static int line = 0; +static void printf(const char *format, ...) +{ + int len; + unsigned char *ptr; + char printfbuf[256]; + va_list ap; + va_start(ap, format); + + ptr = printfbuf; + len = vsnprintf(ptr, sizeof(printfbuf), format, ap); + va_end(ap); + + lcd_puts(0, line++, ptr); +} /* * Clock Generation Module @@ -126,6 +149,20 @@ bool __dbg_ports(void) bool __dbg_hw_info(void) { - return false; + int btn = 0, touch; + + lcd_setfont(FONT_SYSFIXED); + while(btn ^ BUTTON_POWER) + { + lcd_clear_display(); + line = 0; + display_clocks(); + display_enabled_clocks(); + btn = button_read_device(&touch); + printf("X: %d Y: %d BTN: 0x%X", touch>>16, touch&0xFFFF, btn); + lcd_update(); + sleep(HZ/16); + } + return true; } diff --git a/firmware/target/mips/ingenic_jz47xx/debug-target.h b/firmware/target/mips/ingenic_jz47xx/debug-target.h new file mode 100644 index 0000000000..f753e6ee6c --- /dev/null +++ b/firmware/target/mips/ingenic_jz47xx/debug-target.h @@ -0,0 +1,28 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2009 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 __DEBUG_TARGET_H_ +#define __DEBUG_TARGET_H_ + +bool __dbg_hw_info(void); +bool __dbg_ports(void); + +#endif /* __DEBUG_TARGET_H_ */ diff --git a/firmware/target/mips/ingenic_jz47xx/onda_vx747/ata-sd-target.h b/firmware/target/mips/ingenic_jz47xx/onda_vx747/ata-sd-target.h index aed2b9cfea..d05690000f 100644 --- a/firmware/target/mips/ingenic_jz47xx/onda_vx747/ata-sd-target.h +++ b/firmware/target/mips/ingenic_jz47xx/onda_vx747/ata-sd-target.h @@ -38,16 +38,20 @@ 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); -#define MMC_CD_PIN (29 + 1 * 32) /* Pin to check card insertion */ +#define MMC_CD_PIN (32*1 + 29) /* Pin to check card insertion */ +#define MSC_D0 (32*3 + 10) +#define MSC_D1 (32*3 + 11) +#define MSC_D2 (32*3 + 12) +#define MSC_CLK (32*3 + 9 ) static inline void mmc_init_gpio(void) { __gpio_as_msc(); __gpio_as_input(MMC_CD_PIN); - //__gpio_enable_pull(32*3+29); - __gpio_enable_pull(32*3+10); - __gpio_enable_pull(32*3+11); - __gpio_enable_pull(32*3+12); + __gpio_enable_pull(MSC_CLK); + __gpio_enable_pull(MSC_D0); + __gpio_enable_pull(MSC_D1); + __gpio_enable_pull(MSC_D2); } #endif diff --git a/firmware/target/mips/ingenic_jz47xx/onda_vx747/backlight-onda_vx747.c b/firmware/target/mips/ingenic_jz47xx/onda_vx747/backlight-onda_vx747.c index 208236ef95..eec48768b2 100644 --- a/firmware/target/mips/ingenic_jz47xx/onda_vx747/backlight-onda_vx747.c +++ b/firmware/target/mips/ingenic_jz47xx/onda_vx747/backlight-onda_vx747.c @@ -35,7 +35,7 @@ static bool backlight_on; static void set_backlight(int val) { -(void)val; + (void)val; } bool _backlight_init(void) @@ -153,3 +153,11 @@ void _backlight_set_brightness(int brightness) set_backlight(brightness); } #endif + +#ifdef HAVE_LCD_SLEEP +/* Turn off LED supply */ +void _backlight_lcd_sleep(void) +{ + set_backlight_off(); +} +#endif diff --git a/firmware/target/mips/ingenic_jz47xx/onda_vx747/backlight-target.h b/firmware/target/mips/ingenic_jz47xx/onda_vx747/backlight-target.h index f3f17f024e..c6647fa9da 100644 --- a/firmware/target/mips/ingenic_jz47xx/onda_vx747/backlight-target.h +++ b/firmware/target/mips/ingenic_jz47xx/onda_vx747/backlight-target.h @@ -29,10 +29,12 @@ #include +/* bool _backlight_init(void); void _backlight_on(void); void _backlight_off(void); void _backlight_set_brightness(int brightness); bool backlight_enabled(void); +*/ #endif /* BACKLIGHT_TARGET_H */ diff --git a/firmware/target/mips/ingenic_jz47xx/onda_vx747/lcd-onda_vx747.c b/firmware/target/mips/ingenic_jz47xx/onda_vx747/lcd-onda_vx747.c index c07a191bbe..cc27a17944 100644 --- a/firmware/target/mips/ingenic_jz47xx/onda_vx747/lcd-onda_vx747.c +++ b/firmware/target/mips/ingenic_jz47xx/onda_vx747/lcd-onda_vx747.c @@ -26,6 +26,7 @@ #define PIN_CS_N (32*1+17) /* Chip select */ #define PIN_RESET_N (32*1+18) /* Reset */ +#define LCD_PCLK (20000000) /* LCD PCLK */ #define my__gpio_as_lcd_16bit() \ do { \ @@ -199,16 +200,15 @@ static void _set_lcd_bus(void) static void _set_lcd_clock(void) { unsigned int val; - int pll_div; __cpm_stop_lcd(); - pll_div = ( REG_CPM_CPCCR & CPM_CPCCR_PCS ); /* clock source, 0:pllout/2 1: pllout */ - pll_div = pll_div ? 1 : 2; - val = ( __cpm_get_pllout()/pll_div ) / __cpm_get_pclk(); + + val = __cpm_get_pllout2() / LCD_PCLK; val--; if ( val > 0x1ff ) val = 0x1ff; /* CPM_LPCDR is too large, set it to 0x1ff */ __cpm_set_pixdiv(val); + __cpm_start_lcd(); } @@ -277,3 +277,8 @@ void lcd_off(void) { _display_off(); } + +void lcd_set_contrast(int val) +{ + (void)val; +} diff --git a/firmware/target/mips/ingenic_jz47xx/onda_vx747/power-onda_vx747.c b/firmware/target/mips/ingenic_jz47xx/onda_vx747/power-onda_vx747.c index 2c77da4ba7..fc77d063f9 100644 --- a/firmware/target/mips/ingenic_jz47xx/onda_vx747/power-onda_vx747.c +++ b/firmware/target/mips/ingenic_jz47xx/onda_vx747/power-onda_vx747.c @@ -42,3 +42,8 @@ void power_init(void) { __gpio_as_input(USB_CHARGER_GPIO); } + +bool charging_state(void) +{ + return 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 cd1da694b0..f750efdf57 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 @@ -26,6 +26,8 @@ #include "button-target.h" #include "powermgmt.h" #include "kernel.h" +#include "backlight.h" +#include "logf.h" #ifdef ONDA_VX747 #define BTN_OFF (1 << 29) @@ -54,15 +56,16 @@ (2 << SADC_CFG_CLKOUT_NUM_BIT) | \ SADC_CFG_XYZ1Z2 | \ SADC_CFG_SNUM | \ - (2 << SADC_CFG_CLKDIV_BIT) | \ + (1 << SADC_CFG_CLKDIV_BIT) | \ SADC_CFG_PBAT_HIGH | \ SADC_CFG_CMD_INT_PEN \ ) static signed int x_pos, y_pos; -static int datacount = 0, cur_touch = 0; -static bool pen_down = false; -static volatile unsigned short bat_val = 0; +static int datacount = 0; +static volatile int cur_touch = 0; +static volatile bool pen_down = false; +static volatile unsigned short bat_val; static struct mutex battery_mtx; static enum touchscreen_mode current_mode = TOUCHSCREEN_POINT; @@ -76,20 +79,20 @@ static const int touchscreen_buttons[3][3] = const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = { /* TODO */ - 3400 + 1400 }; const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] = { /* TODO */ - 3300 + 1300 }; /* 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 }, + { 1300, 3680, 3740, 3760, 3780, 3810, 3870, 3930, 3970, 4070, 4160 }, }; /* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */ @@ -105,23 +108,34 @@ const unsigned short percent_to_volt_charge[11] = /* Returns battery voltage from ADC [millivolts] */ unsigned int battery_adc_voltage(void) { - register unsigned short dummy; + unsigned int val, i; mutex_lock(&battery_mtx); - dummy = REG_SADC_BATDAT; - dummy = REG_SADC_BATDAT; + val = REG_SADC_BATDAT; + val = REG_SADC_BATDAT; - bat_val = 0; REG_SADC_ENA |= SADC_ENA_PBATEN; + for(i=0; i<4; i++) + { + bat_val = 0; + + /* primitive wakeup event */ + while(bat_val == 0) + sleep(0); + + val += bat_val; + } + REG_SADC_ENA &= ~SADC_ENA_PBATEN; + + val /= 4; - /* primitive wakeup event */ - while(bat_val == 0) - yield(); + logf("%d %d %d", val, (val*BATTERY_SCALE_FACTOR)>>12, + (val*0xAAAAAAAB >> 32) >> 1); mutex_unlock(&battery_mtx); - return (bat_val*BATTERY_SCALE_FACTOR)>>12; + return (val*BATTERY_SCALE_FACTOR)>>12; } void button_init_device(void) @@ -135,11 +149,11 @@ void button_init_device(void) system_enable_irq(IRQ_SADC); - REG_SADC_SAMETIME = 350; + REG_SADC_SAMETIME = 10; REG_SADC_WAITTIME = 100; REG_SADC_STATE &= (~REG_SADC_STATE); REG_SADC_CTRL = (~(SADC_CTRL_PENDM | SADC_CTRL_PENUM | SADC_CTRL_TSRDYM | SADC_CTRL_PBATRDYM)); - REG_SADC_ENA = (SADC_ENA_TSEN | SADC_ENA_PBATEN); + REG_SADC_ENA = SADC_ENA_TSEN; #ifdef ONDA_VX747 __gpio_as_input(32*3 + 29); @@ -213,19 +227,24 @@ int button_read_device(int *data) if(tmp & BTN_OFF) ret |= BUTTON_POWER; - if(current_mode == TOUCHSCREEN_BUTTON && cur_touch != 0) - { - int px_x = cur_touch >> 16; - int px_y = cur_touch & 0xFFFF; - ret |= touchscreen_buttons[px_y/(LCD_HEIGHT/3)] - [px_x/(LCD_WIDTH/3)]; - } - else if(pen_down) + if(cur_touch != 0) { - ret |= BUTTON_TOUCH; - if(data != NULL && cur_touch != 0) + if(current_mode == TOUCHSCREEN_BUTTON) + { + int px_x = cur_touch >> 16; + int px_y = cur_touch & 0xFFFF; + ret |= touchscreen_buttons[px_y/(LCD_HEIGHT/3)] + [px_x/(LCD_WIDTH/3)]; + } + else if(pen_down) + { + ret |= BUTTON_TOUCHSCREEN; *data = cur_touch; + } } + + if(ret & BUTTON_TOUCHSCREEN && !is_backlight_on(true)) + *data = 0; return ret; } @@ -299,15 +318,17 @@ void SADC(void) x_pos += xData; y_pos += yData; } + + datacount++; + + if(datacount >= TS_AD_COUNT) + { + cur_touch = touch_to_pixels(x_pos/datacount, y_pos/datacount); + datacount = 0; + } } - - datacount++; - - if(datacount >= TS_AD_COUNT) - { - cur_touch = touch_to_pixels(x_pos/datacount, y_pos/datacount); + else datacount = 0; - } } if(state & SADC_CTRL_PBATRDYM) @@ -316,3 +337,7 @@ void SADC(void) /* Battery AD IRQ */ } } + +void adc_init(void) +{ +} diff --git a/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c b/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c index 1ed36cd312..b649311d13 100644 --- a/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c @@ -113,7 +113,8 @@ size_t pcm_get_bytes_waiting(void) const void * pcm_play_dma_get_peak_buffer(int *count) { /* TODO */ - *count = REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL)>>2; + //*count = REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL)>>2; + *count = 0; return NULL; } diff --git a/firmware/target/mips/ingenic_jz47xx/system-jz4740.c b/firmware/target/mips/ingenic_jz47xx/system-jz4740.c index c0f39a4933..e37f17c73f 100644 --- a/firmware/target/mips/ingenic_jz47xx/system-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/system-jz4740.c @@ -22,11 +22,9 @@ #include "config.h" #include "jz4740.h" #include "mips.h" -#include "mipsregs.h" #include "mmu-mips.h" #include "panic.h" #include "system.h" -#include "string.h" #include "kernel.h" #define NUM_DMA 6 @@ -36,165 +34,40 @@ static int irq; static void UIRQ(void) { - panicf("Unhandled interrupt occurred: %d\n", irq); + panicf("Unhandled interrupt occurred: %d", irq); } -#define default_interrupt(name) \ - extern __attribute__((weak,alias("UIRQ"))) void name (void) - -default_interrupt(I2C); -default_interrupt(EMC); -default_interrupt(UHC); -default_interrupt(UART0); -default_interrupt(SADC); -default_interrupt(MSC); -default_interrupt(RTC); -default_interrupt(SSI); -default_interrupt(CIM); -default_interrupt(AIC); -default_interrupt(ETH); -default_interrupt(TCU2); -default_interrupt(TCU1); -default_interrupt(TCU0); -default_interrupt(UDC); -default_interrupt(IPU); -default_interrupt(LCD); - -default_interrupt(DMA0); -default_interrupt(DMA1); -default_interrupt(DMA2); -default_interrupt(DMA3); -default_interrupt(DMA4); -default_interrupt(DMA5); - -default_interrupt(GPIO0); -default_interrupt(GPIO1); -default_interrupt(GPIO2); -default_interrupt(GPIO3); -default_interrupt(GPIO4); -default_interrupt(GPIO5); -default_interrupt(GPIO6); -default_interrupt(GPIO7); -default_interrupt(GPIO8); -default_interrupt(GPIO9); -default_interrupt(GPIO10); -default_interrupt(GPIO11); -default_interrupt(GPIO12); -default_interrupt(GPIO13); -default_interrupt(GPIO14); -default_interrupt(GPIO15); -default_interrupt(GPIO16); -default_interrupt(GPIO17); -default_interrupt(GPIO18); -default_interrupt(GPIO19); -default_interrupt(GPIO20); -default_interrupt(GPIO21); -default_interrupt(GPIO22); -default_interrupt(GPIO23); -default_interrupt(GPIO24); -default_interrupt(GPIO25); -default_interrupt(GPIO26); -default_interrupt(GPIO27); -default_interrupt(GPIO28); -default_interrupt(GPIO29); -default_interrupt(GPIO30); -default_interrupt(GPIO31); -default_interrupt(GPIO32); -default_interrupt(GPIO33); -default_interrupt(GPIO34); -default_interrupt(GPIO35); -default_interrupt(GPIO36); -default_interrupt(GPIO37); -default_interrupt(GPIO38); -default_interrupt(GPIO39); -default_interrupt(GPIO40); -default_interrupt(GPIO41); -default_interrupt(GPIO42); -default_interrupt(GPIO43); -default_interrupt(GPIO44); -default_interrupt(GPIO45); -default_interrupt(GPIO46); -default_interrupt(GPIO47); -default_interrupt(GPIO48); -default_interrupt(GPIO49); -default_interrupt(GPIO50); -default_interrupt(GPIO51); -default_interrupt(GPIO52); -default_interrupt(GPIO53); -default_interrupt(GPIO54); -default_interrupt(GPIO55); -default_interrupt(GPIO56); -default_interrupt(GPIO57); -default_interrupt(GPIO58); -default_interrupt(GPIO59); -default_interrupt(GPIO60); -default_interrupt(GPIO61); -default_interrupt(GPIO62); -default_interrupt(GPIO63); -default_interrupt(GPIO64); -default_interrupt(GPIO65); -default_interrupt(GPIO66); -default_interrupt(GPIO67); -default_interrupt(GPIO68); -default_interrupt(GPIO69); -default_interrupt(GPIO70); -default_interrupt(GPIO71); -default_interrupt(GPIO72); -default_interrupt(GPIO73); -default_interrupt(GPIO74); -default_interrupt(GPIO75); -default_interrupt(GPIO76); -default_interrupt(GPIO77); -default_interrupt(GPIO78); -default_interrupt(GPIO79); -default_interrupt(GPIO80); -default_interrupt(GPIO81); -default_interrupt(GPIO82); -default_interrupt(GPIO83); -default_interrupt(GPIO84); -default_interrupt(GPIO85); -default_interrupt(GPIO86); -default_interrupt(GPIO87); -default_interrupt(GPIO88); -default_interrupt(GPIO89); -default_interrupt(GPIO90); -default_interrupt(GPIO91); -default_interrupt(GPIO92); -default_interrupt(GPIO93); -default_interrupt(GPIO94); -default_interrupt(GPIO95); -default_interrupt(GPIO96); -default_interrupt(GPIO97); -default_interrupt(GPIO98); -default_interrupt(GPIO99); -default_interrupt(GPIO100); -default_interrupt(GPIO101); -default_interrupt(GPIO102); -default_interrupt(GPIO103); -default_interrupt(GPIO104); -default_interrupt(GPIO105); -default_interrupt(GPIO106); -default_interrupt(GPIO107); -default_interrupt(GPIO108); -default_interrupt(GPIO109); -default_interrupt(GPIO110); -default_interrupt(GPIO111); -default_interrupt(GPIO112); -default_interrupt(GPIO113); -default_interrupt(GPIO114); -default_interrupt(GPIO115); -default_interrupt(GPIO116); -default_interrupt(GPIO117); -default_interrupt(GPIO118); -default_interrupt(GPIO119); -default_interrupt(GPIO120); -default_interrupt(GPIO121); -default_interrupt(GPIO122); -default_interrupt(GPIO123); -default_interrupt(GPIO124); -default_interrupt(GPIO125); -default_interrupt(GPIO126); -default_interrupt(GPIO127); +#define intr(name) extern __attribute__((weak,alias("UIRQ"))) void name (void) + +intr(I2C);intr(EMC);intr(UHC);intr(UART0);intr(SADC);intr(MSC);intr(RTC); +intr(SSI);intr(CIM);intr(AIC);intr(ETH);intr(TCU2);intr(TCU1);intr(TCU0); +intr(UDC);intr(IPU);intr(LCD); + +intr(DMA0);intr(DMA1);intr(DMA2);intr(DMA3);intr(DMA4);intr(DMA5); + +intr(GPIO0);intr(GPIO1);intr(GPIO2);intr(GPIO3);intr(GPIO4);intr(GPIO5); +intr(GPIO6);intr(GPIO7);intr(GPIO8);intr(GPIO9);intr(GPIO10);intr(GPIO11); +intr(GPIO12);intr(GPIO13);intr(GPIO14);intr(GPIO15);intr(GPIO16);intr(GPIO17); +intr(GPIO18);intr(GPIO19);intr(GPIO20);intr(GPIO21);intr(GPIO22);intr(GPIO23); +intr(GPIO24);intr(GPIO25);intr(GPIO26);intr(GPIO27);intr(GPIO28);intr(GPIO29); +intr(GPIO30);intr(GPIO31);intr(GPIO32);intr(GPIO33);intr(GPIO34);intr(GPIO35); +intr(GPIO36);intr(GPIO37);intr(GPIO38);intr(GPIO39);intr(GPIO40);intr(GPIO41); +intr(GPIO42);intr(GPIO43);intr(GPIO44);intr(GPIO45);intr(GPIO46);intr(GPIO47); +intr(GPIO48);intr(GPIO49);intr(GPIO50);intr(GPIO51);intr(GPIO52);intr(GPIO53); +intr(GPIO54);intr(GPIO55);intr(GPIO56);intr(GPIO57);intr(GPIO58);intr(GPIO59); +intr(GPIO60);intr(GPIO61);intr(GPIO62);intr(GPIO63);intr(GPIO64);intr(GPIO65); +intr(GPIO66);intr(GPIO67);intr(GPIO68);intr(GPIO69);intr(GPIO70);intr(GPIO71); +intr(GPIO72);intr(GPIO73);intr(GPIO74);intr(GPIO75);intr(GPIO76);intr(GPIO77); +intr(GPIO78);intr(GPIO79);intr(GPIO80);intr(GPIO81);intr(GPIO82);intr(GPIO83); +intr(GPIO84);intr(GPIO85);intr(GPIO86);intr(GPIO87);intr(GPIO88);intr(GPIO89); +intr(GPIO90);intr(GPIO91);intr(GPIO92);intr(GPIO93);intr(GPIO94);intr(GPIO95); +intr(GPIO96);intr(GPIO97);intr(GPIO98);intr(GPIO99);intr(GPIO100);intr(GPIO101); +intr(GPIO102);intr(GPIO103);intr(GPIO104);intr(GPIO105);intr(GPIO106); +intr(GPIO107);intr(GPIO108);intr(GPIO109);intr(GPIO110);intr(GPIO111); +intr(GPIO112);intr(GPIO113);intr(GPIO114);intr(GPIO115);intr(GPIO116); +intr(GPIO117);intr(GPIO118);intr(GPIO119);intr(GPIO120);intr(GPIO121); +intr(GPIO122);intr(GPIO123);intr(GPIO124);intr(GPIO125);intr(GPIO126); +intr(GPIO127); static void (* const irqvector[])(void) = { @@ -281,17 +154,16 @@ static void ack_irq(unsigned int irq) __intc_ack_irq(irq); } -static unsigned long ipl; static int get_irq_number(void) { - register int irq = 0; + static unsigned long ipl; + register int irq; ipl |= REG_INTC_IPR; if (ipl == 0) return -1; - /* find out the real irq defined in irq_xxx.c */ for (irq = 31; irq >= 0; irq--) if (ipl & (1 << irq)) break; @@ -369,15 +241,14 @@ void exception_handler(void* stack_ptr, unsigned int cause, unsigned int epc) panicf("Exception occurred: %s [0x%08x] at 0x%08x (stack at 0x%08x)", parse_exception(cause), cause, epc, (unsigned int)stack_ptr); } -static unsigned int iclk; -static void detect_clock(void) +void tlb_refill_handler(void) { - iclk = __cpm_get_cclk(); + panicf("TLB refill handler at 0x%08lx! [0x%x]", read_c0_epc(), read_c0_badvaddr()); } void udelay(unsigned int usec) { - unsigned int i = usec * (iclk / 2000000); + unsigned int i = usec * (__cpm_get_cclk() / 2000000); __asm__ __volatile__ ( ".set noreorder \n" "1: \n" @@ -396,135 +267,6 @@ void mdelay(unsigned int msec) udelay(1000); } -/* Core-level interrupt masking */ -void clear_interrupts(void) -{ - register unsigned int t; - t = read_c0_status(); - t &= ~1; - write_c0_status(t); -} - -unsigned int mips_get_sr(void) -{ - return read_c0_status(); -} - -void store_interrupts(void) -{ - register unsigned int t; - t = read_c0_status(); - t |= 1; - t &= ~2; - write_c0_status(t); -} - -#define Index_Invalidate_I 0x00 -#define Index_Writeback_Inv_D 0x01 -#define Index_Load_Tag_I 0x04 -#define Index_Load_Tag_D 0x05 -#define Index_Store_Tag_I 0x08 -#define Index_Store_Tag_D 0x09 -#define Hit_Invalidate_I 0x10 -#define Hit_Invalidate_D 0x11 -#define Hit_Writeback_Inv_D 0x15 -#define Hit_Writeback_I 0x18 -#define Hit_Writeback_D 0x19 - -#define CACHE_SIZE 16*1024 -#define CACHE_LINE_SIZE 32 -#define KSEG0 0x80000000 - -#define SYNC_WB() __asm__ __volatile__ ("sync") - -#define __CACHE_OP(op, addr) \ - __asm__ __volatile__( \ - " .set noreorder \n" \ - " .set mips32\n\t \n" \ - " cache %0, %1 \n" \ - " .set mips0 \n" \ - " .set reorder \n" \ - : \ - : "i" (op), "m" (*(unsigned char *)(addr))) - -void __flush_dcache_line(unsigned long addr) -{ - __CACHE_OP(Hit_Writeback_Inv_D, addr); - SYNC_WB(); -} - -void __icache_invalidate_all(void) -{ - unsigned int i; - - asm volatile (".set noreorder \n" - ".set mips32 \n" - "mtc0 $0, $28 \n" /* TagLo */ - "mtc0 $0, $29 \n" /* TagHi */ - ".set mips0 \n" - ".set reorder \n" - ); - for(i=KSEG0; i= CACHE_SIZE) - __dcache_writeback_all(); - else - { - unsigned long dc_lsize = CACHE_LINE_SIZE; - - a = addr & ~(dc_lsize - 1); - end = (addr + size - 1) & ~(dc_lsize - 1); - for(; a < end; a += dc_lsize) - __flush_dcache_line(a); /* Hit_Writeback_Inv_D */ - } -} - -void tlb_refill_handler(void) -{ - panicf("TLB refill handler at 0x%08lx! [0x%x]", read_c0_epc(), read_c0_badvaddr()); -} - static int dma_count = 0; void dma_enable(void) { @@ -718,9 +460,8 @@ static void sdram_init(void) /* everything is ok now */ } -extern int main(void); -void system_main(void) ICODE_ATTR; -void system_main(void) +/* Gets called *before* main */ +void ICODE_ATTR system_main(void) { int i; @@ -733,24 +474,16 @@ void system_main(void) for(i=0; i> 8) & 0xff) -#define swap32(x) (((x) & 0xff) << 24 | ((x) & 0xff00) << 8 | ((x) & 0xff0000) >> 8 | ((x) >> 24) & 0xff) +#define swap32(x) (((x) & 0xff) << 24 | ((x) & 0xff00) << 8 | \ + ((x) & 0xff0000) >> 8 | ((x) >> 24) & 0xff) #define UNCACHED_ADDRESS(addr) ((unsigned int)(addr) | 0xA0000000) #define UNCACHED_ADDR(x) UNCACHED_ADDRESS((x)) #define PHYSADDR(x) ((x) & 0x1fffffff) -void __dcache_writeback_all(void); -void __dcache_invalidate_all(void); -void __icache_invalidate_all(void); -void __flush_dcache_line(unsigned long addr); -void dma_cache_wback_inv(unsigned long addr, unsigned long size); void system_enable_irq(unsigned int irq); -void store_interrupts(void); -void clear_interrupts(void); void udelay(unsigned int usec); void mdelay(unsigned int msec); void power_off(void); diff --git a/firmware/target/mips/mmu-mips.c b/firmware/target/mips/mmu-mips.c index 570b209e3a..2f7f19d3b3 100644 --- a/firmware/target/mips/mmu-mips.c +++ b/firmware/target/mips/mmu-mips.c @@ -112,7 +112,7 @@ void map_address(unsigned long virtual, unsigned long physical, add_wired_entry(entry0, entry1, entryhi, DEFAULT_PAGE_MASK); } -void tlb_init(void) +void mmu_init(void) { write_c0_pagemask(DEFAULT_PAGE_MASK); write_c0_wired(0); @@ -124,3 +124,93 @@ void tlb_init(void) map_address(0x80004000, 0x80004000, MEM * 0x100000, K_CacheAttrC); */ } + +#define SYNC_WB() __asm__ __volatile__ ("sync") + +#define __CACHE_OP(op, addr) \ + __asm__ __volatile__( \ + " .set noreorder \n" \ + " .set mips32\n\t \n" \ + " cache %0, %1 \n" \ + " .set mips0 \n" \ + " .set reorder \n" \ + : \ + : "i" (op), "m" (*(unsigned char *)(addr))) + +void __flush_dcache_line(unsigned long addr) +{ + __CACHE_OP(DCHitWBInv, addr); + SYNC_WB(); +} + +void __icache_invalidate_all(void) +{ + unsigned int i; + + asm volatile (".set noreorder \n" + ".set mips32 \n" + "mtc0 $0, $28 \n" /* TagLo */ + "mtc0 $0, $29 \n" /* TagHi */ + ".set mips0 \n" + ".set reorder \n" + ); + for(i=A_K0BASE; i= CACHE_SIZE) + __dcache_writeback_all(); + else + { + unsigned long dc_lsize = CACHE_LINE_SIZE; + + a = addr & ~(dc_lsize - 1); + end = (addr + size - 1) & ~(dc_lsize - 1); + for(; a < end; a += dc_lsize) + __flush_dcache_line(a); + } +} diff --git a/firmware/target/mips/mmu-mips.h b/firmware/target/mips/mmu-mips.h index def4196be1..f3d35f606d 100644 --- a/firmware/target/mips/mmu-mips.h +++ b/firmware/target/mips/mmu-mips.h @@ -22,8 +22,19 @@ #ifndef __MMU_MIPS_INCLUDE_H #define __MMU_MIPS_INCLUDE_H +#include "system-target.h" + void map_address(unsigned long virtual, unsigned long physical, unsigned long length, unsigned int cache_flags); -void tlb_init(void); +void mmu_init(void); + +#define HAVE_CPUCACHE_INVALIDATE +//#define HAVE_CPUCACHE_FLUSH + +void __dcache_writeback_all(void); +void __dcache_invalidate_all(void); +void __icache_invalidate_all(void); +void __flush_dcache_line(unsigned long addr); +void dma_cache_wback_inv(unsigned long addr, unsigned long size); #endif /* __MMU_MIPS_INCLUDE_H */ -- cgit v1.2.3