diff options
author | Aidan MacDonald <amachronic@protonmail.com> | 2021-02-27 22:08:58 +0000 |
---|---|---|
committer | Aidan MacDonald <amachronic@protonmail.com> | 2021-03-28 00:01:37 +0000 |
commit | 3ec66893e377b088c1284d2d23adb2aeea6d7965 (patch) | |
tree | b647717f83ad56b15dc42cfdef5d04d68cd9bd6b | |
parent | 83fcbedc65f4b9ae7e491ecf6f07c0af4b245f74 (diff) | |
download | rockbox-3ec66893e3.tar.gz rockbox-3ec66893e3.zip |
New port: FiiO M3K on bare metal
Change-Id: I7517e7d5459e129dcfc9465c6fbd708619888fbe
143 files changed, 16585 insertions, 24 deletions
diff --git a/.gitignore b/.gitignore index 35cde028b5..6e22d4dcf8 100644 --- a/.gitignore +++ b/.gitignore @@ -118,6 +118,7 @@ __pycache__ /tools/mknkboot /tools/mktccboot /tools/mkzenboot +/tools/mkspl-x1000 /tools/iaudio_bl_flash.c /tools/iaudio_bl_flash.h /tools/.vagrant diff --git a/apps/SOURCES b/apps/SOURCES index 62291bb992..80133ebd27 100644 --- a/apps/SOURCES +++ b/apps/SOURCES @@ -302,6 +302,8 @@ keymaps/keymap-xduoox3ii.c keymaps/keymap-xduoox20.c #elif CONFIG_KEYPAD == FIIO_M3K_LINUX_PAD keymaps/keymap-fiiom3klinux.c +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +keymaps/keymap-fiiom3k.c #elif CONFIG_KEYPAD == EROSQ_PAD keymaps/keymap-erosq.c #endif diff --git a/apps/debug_menu.c b/apps/debug_menu.c index 9bbbfaec99..f7e179b040 100644 --- a/apps/debug_menu.c +++ b/apps/debug_menu.c @@ -126,6 +126,10 @@ #include "bootdata.h" #endif +#ifdef FIIO_M3K +#include "installer.h" +#endif + static const char* threads_getname(int selected_item, void *data, char *buffer, size_t buffer_len) { @@ -2491,6 +2495,52 @@ static bool dbg_boot_data(void) } #endif /* defined(HAVE_BOOTDATA) && !defined(SIMULATOR) */ +#ifdef FIIO_M3K +/* Note: this is temporary and should NOT be merged, ensure it is removed */ +static int fiio_debug_menu_action_callback(int action, struct gui_synclist *lists) +{ + if(action == ACTION_REDRAW) { + simplelist_set_line_count(0); + simplelist_addline("Back to menu"); + simplelist_addline("Install bootloader"); + simplelist_addline("Dump bootloader"); + action = ACTION_REDRAW; + } + + if(action == ACTION_STD_OK) { + int sel = gui_synclist_get_sel_pos(lists); + int rc = 0; + switch(sel) { + case 1: + rc = install_bootloader("/boot.install"); + break; + case 2: + rc = dump_bootloader("/boot.dump"); + break; + default: + break; + } + + if(sel == 1 || sel == 2) { + const char* msg = installer_strerror(rc); + splashf(3*HZ, "(%d) %s", rc, msg); + } + + action = ACTION_STD_CANCEL; + } + + return action; +} + +static bool dbg_fiio_menu(void) +{ + struct simplelist_info info; + simplelist_info_init(&info, "FiiO debug menu", 3, NULL); + info.action_callback = fiio_debug_menu_action_callback; + return simplelist_show_list(&info); +} +#endif + /****** The menu *********/ static const struct { unsigned char *desc; /* string or ID */ @@ -2598,6 +2648,9 @@ static const struct { #if defined(HAVE_BOOTDATA) && !defined(SIMULATOR) {"Boot data", dbg_boot_data }, #endif +#ifdef FIIO_M3K + {"FiiO debug menu", dbg_fiio_menu}, +#endif }; static int menu_action_callback(int btn, struct gui_synclist *lists) diff --git a/apps/features.txt b/apps/features.txt index 282f5e6a6d..4e7f986057 100644 --- a/apps/features.txt +++ b/apps/features.txt @@ -182,10 +182,15 @@ depth_3d #endif /* This should be AUDIOHW_HAVE_FILTER_ROLL_OFF but that is only defined later */ -#if defined(DX50) || defined(HAVE_DF1704_CODEC) || defined(HAVE_PCM1792_CODEC) || defined(HAVE_CS4398) || defined(HAVE_WM8740) || defined(HAVE_ES9018) || defined(HAVE_XDUOO_LINUX_CODEC) || defined(HAVE_FIIO_LINUX_CODEC) +#if defined(DX50) || defined(HAVE_DF1704_CODEC) || defined(HAVE_PCM1792_CODEC) || defined(HAVE_CS4398) || defined(HAVE_WM8740) || defined(HAVE_ES9018) || defined(HAVE_XDUOO_LINUX_CODEC) || defined(HAVE_FIIO_LINUX_CODEC) || defined(HAVE_AK4376) filter_roll_off #endif +/* This should be AUDIOHW_HAVE_POWER_MODE but that is not defined yet */ +#if defined(HAVE_AK4376) +dac_power_mode +#endif + #if defined(HAVE_ES9018) es9018 #endif diff --git a/apps/gui/option_select.h b/apps/gui/option_select.h index 7ca9a4ebbb..476e7b81bd 100644 --- a/apps/gui/option_select.h +++ b/apps/gui/option_select.h @@ -25,7 +25,7 @@ #include "screen_access.h" #include "settings.h" -#if defined (HAVE_SCROLLWHEEL) +#if defined (HAVE_SCROLLWHEEL) && !defined(FIIO_M3K) /* Define this if your target makes sense to have smaller values at the top of the list increasing down the list */ #define ASCENDING_INT_SETTINGS diff --git a/apps/keymaps/keymap-fiiom3k.c b/apps/keymaps/keymap-fiiom3k.c new file mode 100644 index 0000000000..e562443227 --- /dev/null +++ b/apps/keymaps/keymap-fiiom3k.c @@ -0,0 +1,219 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 FiiO M3K target */ + +#include "config.h" +#include "action.h" +#include "button.h" +#include "settings.h" + +/* {Action Code, Button code, Prereq button code } */ + +static const struct button_mapping button_context_standard[] = { + {ACTION_STD_PREV, BUTTON_UP, BUTTON_NONE}, + {ACTION_STD_PREVREPEAT, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE}, + {ACTION_STD_NEXT, BUTTON_DOWN, BUTTON_NONE}, + {ACTION_STD_NEXTREPEAT, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE}, + {ACTION_STD_PREV, BUTTON_SCROLL_BACK, BUTTON_NONE}, + {ACTION_STD_PREVREPEAT, BUTTON_SCROLL_BACK|BUTTON_REPEAT, BUTTON_NONE}, + {ACTION_STD_NEXT, BUTTON_SCROLL_FWD, BUTTON_NONE}, + {ACTION_STD_NEXTREPEAT, BUTTON_SCROLL_FWD|BUTTON_REPEAT, BUTTON_NONE}, + {ACTION_STD_OK, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT}, + {ACTION_STD_CANCEL, BUTTON_BACK|BUTTON_REL, BUTTON_BACK}, + {ACTION_STD_CONTEXT, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_SELECT}, + {ACTION_STD_CONTEXT, BUTTON_MENU|BUTTON_REL, BUTTON_MENU}, + {ACTION_STD_MENU, BUTTON_BACK|BUTTON_REPEAT, BUTTON_BACK}, + {ACTION_STD_QUICKSCREEN, BUTTON_MENU|BUTTON_REPEAT, BUTTON_MENU}, + {ACTION_STD_KEYLOCK, BUTTON_POWER|BUTTON_REL, BUTTON_POWER}, + {ACTION_STD_HOTKEY, BUTTON_PLAY|BUTTON_REL, BUTTON_PLAY}, + LAST_ITEM_IN_LIST +}; /* button_context_standard */ + +static const struct button_mapping button_context_wps[] = { + {ACTION_WPS_PLAY, BUTTON_PLAY|BUTTON_REL, BUTTON_PLAY}, + {ACTION_WPS_PLAY, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT}, + {ACTION_WPS_STOP, BUTTON_POWER|BUTTON_REPEAT, BUTTON_POWER}, + {ACTION_WPS_VOLUP, BUTTON_VOL_UP, BUTTON_NONE}, + {ACTION_WPS_VOLUP, BUTTON_VOL_UP|BUTTON_REPEAT, BUTTON_NONE}, + {ACTION_WPS_VOLDOWN, BUTTON_VOL_DOWN, BUTTON_NONE}, + {ACTION_WPS_VOLDOWN, BUTTON_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE}, + {ACTION_WPS_SKIPNEXT, BUTTON_RIGHT|BUTTON_REL, BUTTON_RIGHT}, + {ACTION_WPS_SKIPPREV, BUTTON_LEFT|BUTTON_REL, BUTTON_LEFT}, + {ACTION_WPS_SEEKFWD, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE}, + {ACTION_WPS_STOPSEEK, BUTTON_RIGHT|BUTTON_REL, BUTTON_RIGHT|BUTTON_REPEAT}, + {ACTION_WPS_SEEKBACK, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE}, + {ACTION_WPS_STOPSEEK, BUTTON_LEFT|BUTTON_REL, BUTTON_LEFT|BUTTON_REPEAT}, + {ACTION_WPS_BROWSE, BUTTON_BACK|BUTTON_REPEAT, BUTTON_BACK}, + {ACTION_WPS_MENU, BUTTON_BACK|BUTTON_REL, BUTTON_BACK}, + {ACTION_WPS_CONTEXT, BUTTON_MENU|BUTTON_REL, BUTTON_MENU}, + {ACTION_WPS_QUICKSCREEN, BUTTON_MENU|BUTTON_REPEAT, BUTTON_MENU}, + {ACTION_STD_KEYLOCK, BUTTON_POWER|BUTTON_REL, BUTTON_POWER}, + {ACTION_WPS_HOTKEY, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_PLAY}, + {ACTION_WPS_VIEW_PLAYLIST, BUTTON_SCROLL_FWD, BUTTON_NONE}, + {ACTION_WPS_VIEW_PLAYLIST, BUTTON_SCROLL_BACK, BUTTON_NONE}, + {ACTION_WPS_ABSETA_PREVDIR, BUTTON_UP|BUTTON_REPEAT, BUTTON_UP}, + {ACTION_WPS_ABSETB_NEXTDIR, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_DOWN}, + {ACTION_WPS_ABRESET, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_SELECT}, + LAST_ITEM_IN_LIST +}; /* button_context_wps */ + +static const struct button_mapping button_context_tree[] = { + {ACTION_TREE_STOP, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_PLAY}, + {ACTION_TREE_WPS, BUTTON_BACK|BUTTON_REPEAT, BUTTON_BACK}, + LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_LIST) +}; /* button_context_tree */ + +static const struct button_mapping button_context_list[] = { + {ACTION_LISTTREE_PGUP, BUTTON_LEFT, BUTTON_NONE}, + {ACTION_LISTTREE_PGUP, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE}, + {ACTION_LISTTREE_PGDOWN, BUTTON_RIGHT, BUTTON_NONE}, + {ACTION_LISTTREE_PGDOWN, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE}, + {ACTION_LIST_VOLUP, BUTTON_VOL_UP, BUTTON_NONE}, + {ACTION_LIST_VOLUP, BUTTON_VOL_UP|BUTTON_REPEAT, BUTTON_NONE}, + {ACTION_LIST_VOLDOWN, BUTTON_VOL_DOWN, BUTTON_NONE}, + {ACTION_LIST_VOLDOWN, BUTTON_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE}, + LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) +}; /* button_context_list */ + +static const struct button_mapping button_context_settings[] = { + {ACTION_SETTINGS_INC, BUTTON_UP, BUTTON_NONE}, + {ACTION_SETTINGS_INCREPEAT, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE}, + {ACTION_SETTINGS_INC, BUTTON_SCROLL_BACK, BUTTON_NONE}, + {ACTION_SETTINGS_INCREPEAT, BUTTON_SCROLL_BACK|BUTTON_REPEAT, BUTTON_NONE}, + {ACTION_SETTINGS_INCBIGSTEP, BUTTON_VOL_UP, BUTTON_NONE}, + {ACTION_SETTINGS_DEC, BUTTON_DOWN, BUTTON_NONE}, + {ACTION_SETTINGS_DECREPEAT, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE}, + {ACTION_SETTINGS_DEC, BUTTON_SCROLL_FWD, BUTTON_NONE}, + {ACTION_SETTINGS_DECREPEAT, BUTTON_SCROLL_FWD|BUTTON_REPEAT, BUTTON_NONE}, + {ACTION_SETTINGS_DECBIGSTEP, BUTTON_VOL_DOWN, BUTTON_NONE}, + {ACTION_SETTINGS_RESET, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_SELECT}, + {ACTION_STD_NEXT, BUTTON_RIGHT, BUTTON_NONE}, + {ACTION_STD_NEXTREPEAT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE}, + {ACTION_STD_PREV, BUTTON_LEFT, BUTTON_NONE}, + {ACTION_STD_PREVREPEAT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE}, + LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) +}; /* button_context_settings */ + +static const struct button_mapping button_context_settings_eq[] = { + {ACTION_SETTINGS_INC, BUTTON_RIGHT, BUTTON_NONE}, + {ACTION_SETTINGS_INCREPEAT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE}, + {ACTION_SETTINGS_INCBIGSTEP, BUTTON_VOL_UP, BUTTON_NONE}, + {ACTION_SETTINGS_DEC, BUTTON_LEFT, BUTTON_NONE}, + {ACTION_SETTINGS_DECREPEAT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE}, + {ACTION_SETTINGS_DECBIGSTEP, BUTTON_VOL_DOWN, BUTTON_NONE}, + LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) +}; /* button_context_settings_eq */ + +static const struct button_mapping button_context_quickscreen[] = { + {ACTION_QS_TOP, BUTTON_UP, BUTTON_NONE}, + {ACTION_QS_DOWN, BUTTON_DOWN, BUTTON_NONE}, + {ACTION_QS_LEFT, BUTTON_LEFT, BUTTON_NONE}, + {ACTION_QS_RIGHT, BUTTON_RIGHT, BUTTON_NONE}, + {ACTION_QS_VOLUP, BUTTON_VOL_UP, BUTTON_NONE}, + {ACTION_QS_VOLDOWN, BUTTON_VOL_DOWN, BUTTON_NONE}, + {ACTION_STD_CANCEL, BUTTON_SELECT, BUTTON_NONE}, + {ACTION_STD_CANCEL, BUTTON_POWER, BUTTON_NONE}, + {ACTION_STD_CANCEL, BUTTON_BACK, BUTTON_NONE}, + LAST_ITEM_IN_LIST +}; /* button_context_quickscreen */ + +static const struct button_mapping button_context_pitchscreen[] = { + {ACTION_PS_INC_SMALL, BUTTON_UP, BUTTON_NONE}, + {ACTION_PS_INC_SMALL, BUTTON_SCROLL_BACK, BUTTON_NONE}, + {ACTION_PS_INC_BIG, BUTTON_VOL_UP, BUTTON_NONE}, + {ACTION_PS_DEC_SMALL, BUTTON_DOWN, BUTTON_NONE}, + {ACTION_PS_DEC_SMALL, BUTTON_SCROLL_FWD, BUTTON_NONE}, + {ACTION_PS_DEC_BIG, BUTTON_VOL_DOWN, BUTTON_NONE}, + {ACTION_PS_NUDGE_LEFT, BUTTON_LEFT, BUTTON_NONE}, + {ACTION_PS_NUDGE_RIGHT, BUTTON_RIGHT, BUTTON_NONE}, + {ACTION_PS_NUDGE_LEFTOFF, BUTTON_LEFT|BUTTON_REL, BUTTON_NONE}, + {ACTION_PS_NUDGE_RIGHTOFF, BUTTON_RIGHT|BUTTON_REL, BUTTON_NONE}, + {ACTION_PS_TOGGLE_MODE, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT}, + {ACTION_PS_RESET, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_SELECT}, + {ACTION_PS_EXIT, BUTTON_POWER, BUTTON_NONE}, + {ACTION_PS_FASTER, BUTTON_BACK, BUTTON_NONE}, + {ACTION_PS_SLOWER, BUTTON_MENU, BUTTON_NONE}, + LAST_ITEM_IN_LIST +}; /* button_context_pitchscreen */ + +static const struct button_mapping button_context_yesnoscreen[] = { + {ACTION_YESNO_ACCEPT, BUTTON_PLAY, BUTTON_NONE}, + {ACTION_YESNO_ACCEPT, BUTTON_SELECT, BUTTON_NONE}, + {ACTION_STD_CANCEL, BUTTON_BACK, BUTTON_NONE}, + {ACTION_STD_CANCEL, BUTTON_POWER, BUTTON_NONE}, + LAST_ITEM_IN_LIST +}; /* button_context_yesnoscreen */ + +static const struct button_mapping button_context_keyboard[] = { + {ACTION_KBD_UP, BUTTON_UP, BUTTON_NONE}, + {ACTION_KBD_DOWN, BUTTON_DOWN, BUTTON_NONE}, + {ACTION_KBD_LEFT, BUTTON_LEFT, BUTTON_NONE}, + {ACTION_KBD_RIGHT, BUTTON_RIGHT, BUTTON_NONE}, + {ACTION_KBD_UP, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE}, + {ACTION_KBD_DOWN, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE}, + {ACTION_KBD_LEFT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE}, + {ACTION_KBD_RIGHT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE}, + {ACTION_KBD_SELECT, BUTTON_SELECT, BUTTON_NONE}, + {ACTION_KBD_BACKSPACE, BUTTON_BACK, BUTTON_NONE}, + {ACTION_KBD_BACKSPACE, BUTTON_BACK|BUTTON_REPEAT, BUTTON_NONE}, + {ACTION_KBD_DONE, BUTTON_PLAY, BUTTON_NONE}, + {ACTION_KBD_ABORT, BUTTON_POWER, BUTTON_NONE}, + {ACTION_KBD_PAGE_FLIP, BUTTON_MENU, BUTTON_NONE}, + {ACTION_KBD_CURSOR_LEFT, BUTTON_VOL_DOWN, BUTTON_NONE}, + {ACTION_KBD_CURSOR_LEFT, BUTTON_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE}, + {ACTION_KBD_CURSOR_RIGHT, BUTTON_VOL_UP, BUTTON_NONE}, + {ACTION_KBD_CURSOR_RIGHT, BUTTON_VOL_UP|BUTTON_REPEAT, BUTTON_NONE}, + LAST_ITEM_IN_LIST +}; /* button_context_keyboard */ + +const struct button_mapping* get_context_mapping(int context) +{ + switch (context) + { + default: + case CONTEXT_STD: + return button_context_standard; + case CONTEXT_WPS: + return button_context_wps; + case CONTEXT_TREE: + case CONTEXT_MAINMENU: + case CONTEXT_BOOKMARKSCREEN: + return button_context_tree; + case CONTEXT_LIST: + return button_context_list; + case CONTEXT_SETTINGS: + case CONTEXT_SETTINGS_TIME: + case CONTEXT_SETTINGS_RECTRIGGER: + return button_context_settings; + case CONTEXT_SETTINGS_EQ: + case CONTEXT_SETTINGS_COLOURCHOOSER: + return button_context_settings_eq; + case CONTEXT_QUICKSCREEN: + return button_context_quickscreen; + case CONTEXT_PITCHSCREEN: + return button_context_pitchscreen; + case CONTEXT_YESNOSCREEN: + return button_context_yesnoscreen; + case CONTEXT_KEYBOARD: + return button_context_keyboard; + } +} diff --git a/apps/lang/english-us.lang b/apps/lang/english-us.lang index d64a6c8777..5a1c4cdf8c 100644 --- a/apps/lang/english-us.lang +++ b/apps/lang/english-us.lang @@ -9611,15 +9611,15 @@ user: core <source> *: none - gigabeatfx,sansafuzeplus: "Touchpad Sensitivity" + gigabeatfx,sansafuzeplus,fiiom3k: "Touchpad Sensitivity" </source> <dest> *: none - gigabeatfx,sansafuzeplus: "Touchpad Sensitivity" + gigabeatfx,sansafuzeplus,fiiom3k: "Touchpad Sensitivity" </dest> <voice> *: none - gigabeatfx,sansafuzeplus: "Touchpad Sensitivity" + gigabeatfx,sansafuzeplus,fiiom3k: "Touchpad Sensitivity" </voice> </phrase> <phrase> diff --git a/apps/lang/english.lang b/apps/lang/english.lang index 52d943f75e..327584c4f6 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang @@ -9702,15 +9702,15 @@ user: core <source> *: none - gigabeatfx,sansafuzeplus: "Touchpad Sensitivity" + gigabeatfx,sansafuzeplus,fiiom3k: "Touchpad Sensitivity" </source> <dest> *: none - gigabeatfx,sansafuzeplus: "Touchpad Sensitivity" + gigabeatfx,sansafuzeplus,fiiom3k: "Touchpad Sensitivity" </dest> <voice> *: none - gigabeatfx,sansafuzeplus: "Touchpad Sensitivity" + gigabeatfx,sansafuzeplus,fiiom3k: "Touchpad Sensitivity" </voice> </phrase> <phrase> diff --git a/apps/plugins/battery_bench.c b/apps/plugins/battery_bench.c index dc22489b15..f8269f5c3b 100644 --- a/apps/plugins/battery_bench.c +++ b/apps/plugins/battery_bench.c @@ -242,6 +242,12 @@ #define BATTERY_OFF_TXT "Power" #define BATTERY_ON_TXT "Menu - start" +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define BATTERY_ON BUTTON_PLAY +#define BATTERY_OFF BUTTON_POWER +#define BATTERY_ON_TXT "Play" +#define BATTERY_OFF_TXT "Power" + #else #error "No keymap defined!" #endif diff --git a/apps/plugins/blackjack.c b/apps/plugins/blackjack.c index f434784a5f..0667c31ef6 100644 --- a/apps/plugins/blackjack.c +++ b/apps/plugins/blackjack.c @@ -607,6 +607,22 @@ enum { #define BJACK_RIGHT BUTTON_SCROLL_FWD #define BJACK_LEFT BUTTON_SCROLL_BACK +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define BJACK_SELECT_NAME "SELECT" +#define BJACK_STAY_NAME "PLAY" +#define BJACK_QUIT_NAME "POWER" +#define BJACK_DOUBLE_NAME "MENU" +#define BJACK_SELECT BUTTON_SELECT +#define BJACK_QUIT BUTTON_POWER +#define BJACK_MAX BUTTON_VOL_UP +#define BJACK_MIN BUTTON_VOL_DOWN +#define BJACK_STAY BUTTON_PLAY +#define BJACK_DOUBLEDOWN BUTTON_MENU +#define BJACK_UP BUTTON_UP +#define BJACK_DOWN BUTTON_DOWN +#define BJACK_RIGHT BUTTON_RIGHT +#define BJACK_LEFT BUTTON_LEFT + #else #error No keymap defined! #endif diff --git a/apps/plugins/brickmania.c b/apps/plugins/brickmania.c index 70ad58a908..92f8d4d161 100644 --- a/apps/plugins/brickmania.c +++ b/apps/plugins/brickmania.c @@ -342,6 +342,14 @@ CONFIG_KEYPAD == SANSA_CONNECT_PAD #define UP BUTTON_PREV #define DOWN BUTTON_NEXT +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define QUIT BUTTON_POWER +#define LEFT BUTTON_LEFT +#define RIGHT BUTTON_RIGHT +#define SELECT BUTTON_PLAY +#define UP BUTTON_UP +#define DOWN BUTTON_DOWN + #else #error No keymap defined! #endif diff --git a/apps/plugins/calculator.c b/apps/plugins/calculator.c index 46d9da6149..4d1b6fa594 100644 --- a/apps/plugins/calculator.c +++ b/apps/plugins/calculator.c @@ -536,6 +536,16 @@ F3: equal to "=" #define CALCULATOR_CALC BUTTON_MENU #define CALCULATOR_CLEAR BUTTON_BACK +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define CALCULATOR_LEFT BUTTON_LEFT +#define CALCULATOR_RIGHT BUTTON_RIGHT +#define CALCULATOR_UP BUTTON_UP +#define CALCULATOR_DOWN BUTTON_DOWN +#define CALCULATOR_QUIT BUTTON_POWER +#define CALCULATOR_INPUT BUTTON_PLAY +#define CALCULATOR_CALC BUTTON_MENU +#define CALCULATOR_CLEAR BUTTON_BACK + #else #error No keymap defined! #endif diff --git a/apps/plugins/calendar.c b/apps/plugins/calendar.c index b52a62328f..54173fde1c 100644 --- a/apps/plugins/calendar.c +++ b/apps/plugins/calendar.c @@ -421,6 +421,16 @@ #define CALENDAR_NEXT_MONTH BUTTON_VOL_UP #define CALENDAR_PREV_MONTH BUTTON_VOL_DOWN +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define CALENDAR_QUIT BUTTON_POWER +#define CALENDAR_SELECT BUTTON_SELECT +#define CALENDAR_NEXT_WEEK BUTTON_DOWN +#define CALENDAR_PREV_WEEK BUTTON_UP +#define CALENDAR_NEXT_DAY BUTTON_LEFT +#define CALENDAR_PREV_DAY BUTTON_RIGHT +#define CALENDAR_NEXT_MONTH BUTTON_VOL_UP +#define CALENDAR_PREV_MONTH BUTTON_VOL_DOWN + #else #error "No keypad setting." #endif diff --git a/apps/plugins/chessbox/chessbox_pgn.h b/apps/plugins/chessbox/chessbox_pgn.h index aacc2ba412..5bfce10ec5 100644 --- a/apps/plugins/chessbox/chessbox_pgn.h +++ b/apps/plugins/chessbox/chessbox_pgn.h @@ -581,6 +581,20 @@ #define CB_SCROLL_LEFT (BUTTON_SCROLL_BACK|BUTTON_REPEAT) #define CB_SCROLL_RIGHT (BUTTON_SCROLL_FWD|BUTTON_REPEAT) +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define CB_SELECT BUTTON_SELECT +#define CB_UP BUTTON_UP +#define CB_DOWN BUTTON_DOWN +#define CB_LEFT BUTTON_LEFT +#define CB_RIGHT BUTTON_RIGHT +#define CB_PLAY BUTTON_PLAY +#define CB_MENU BUTTON_MENU +#define CB_LEVEL BUTTON_BACK +#define CB_SCROLL_UP (BUTTON_UP|BUTTON_REPEAT) +#define CB_SCROLL_DOWN (BUTTON_DOWN|BUTTON_REPEAT) +#define CB_SCROLL_LEFT (BUTTON_LEFT|BUTTON_REPEAT) +#define CB_SCROLL_RIGHT (BUTTON_RIGHT|BUTTON_REPEAT) + #else #error No keymap defined! #endif diff --git a/apps/plugins/chessclock.c b/apps/plugins/chessclock.c index 9b933cdcd4..9a30dee984 100644 --- a/apps/plugins/chessclock.c +++ b/apps/plugins/chessclock.c @@ -406,6 +406,16 @@ #define CHC_SETTINGS_OK BUTTON_PLAY #define CHC_SETTINGS_CANCEL BUTTON_POWER +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define CHC_QUIT BUTTON_POWER +#define CHC_STARTSTOP BUTTON_PLAY +#define CHC_RESET BUTTON_BACK +#define CHC_MENU BUTTON_MENU +#define CHC_SETTINGS_INC BUTTON_UP +#define CHC_SETTINGS_DEC BUTTON_DOWN +#define CHC_SETTINGS_OK BUTTON_SELECT +#define CHC_SETTINGS_CANCEL BUTTON_POWER + #else #error No keymap defined! #endif diff --git a/apps/plugins/chip8.c b/apps/plugins/chip8.c index dde6faaccf..31866acd10 100644 --- a/apps/plugins/chip8.c +++ b/apps/plugins/chip8.c @@ -1283,6 +1283,14 @@ CONFIG_KEYPAD == MROBE500_PAD #define CHIP8_KEY6 BUTTON_BACK #define CHIP8_KEY8 BUTTON_PREV +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define CHIP8_OFF BUTTON_POWER +#define CHIP8_KEY2 BUTTON_MENU +#define CHIP8_KEY4 BUTTON_LEFT +#define CHIP8_KEY5 BUTTON_SELECT +#define CHIP8_KEY6 BUTTON_RIGHT +#define CHIP8_KEY8 BUTTON_BACK + #else #error No keymap defined! #endif diff --git a/apps/plugins/chopper.c b/apps/plugins/chopper.c index 23b32150da..ab8f7b5540 100644 --- a/apps/plugins/chopper.c +++ b/apps/plugins/chopper.c @@ -203,6 +203,11 @@ CONFIG_KEYPAD == MROBE500_PAD #define ACTION BUTTON_PLAY #define ACTIONTEXT "PLAY" +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define QUIT BUTTON_POWER +#define ACTION BUTTON_PLAY +#define ACTIONTEXT "PLAY" + #elif !defined(HAVE_TOUCHSCREEN) #error No keymap defined! #endif diff --git a/apps/plugins/clix.c b/apps/plugins/clix.c index eb0e0d1a59..f1f21f6312 100644 --- a/apps/plugins/clix.c +++ b/apps/plugins/clix.c @@ -316,6 +316,14 @@ #define CLIX_BUTTON_RIGHT BUTTON_SCROLL_FWD #define CLIX_BUTTON_CLICK BUTTON_PLAY +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define CLIX_BUTTON_QUIT BUTTON_POWER +#define CLIX_BUTTON_UP BUTTON_UP +#define CLIX_BUTTON_DOWN BUTTON_DOWN +#define CLIX_BUTTON_LEFT BUTTON_LEFT +#define CLIX_BUTTON_RIGHT BUTTON_RIGHT +#define CLIX_BUTTON_CLICK BUTTON_SELECT + #else #error "no keymap" #endif diff --git a/apps/plugins/cube.c b/apps/plugins/cube.c index b84a2636cb..6587fdcb65 100644 --- a/apps/plugins/cube.c +++ b/apps/plugins/cube.c @@ -410,6 +410,16 @@ #define CUBE_PAUSE BUTTON_BACK #define CUBE_HIGHSPEED BUTTON_PLAY +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define CUBE_QUIT BUTTON_POWER +#define CUBE_NEXT BUTTON_RIGHT +#define CUBE_PREV BUTTON_LEFT +#define CUBE_INC BUTTON_SCROLL_FWD +#define CUBE_DEC BUTTON_SCROLL_BACK +#define CUBE_MODE BUTTON_MENU +#define CUBE_PAUSE BUTTON_PLAY +#define CUBE_HIGHSPEED BUTTON_BACK + #else #error No keymap defined! #endif diff --git a/apps/plugins/doom/i_video.c b/apps/plugins/doom/i_video.c index 233c1cac8f..bb04194acc 100644 --- a/apps/plugins/doom/i_video.c +++ b/apps/plugins/doom/i_video.c @@ -612,6 +612,18 @@ void I_ShutdownGraphics(void) #define DOOMBUTTON_WEAPON BUTTON_VOL_UP #define DOOMBUTTON_MAP BUTTON_VOL_DOWN +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define DOOMBUTTON_UP BUTTON_UP +#define DOOMBUTTON_DOWN BUTTON_DOWN +#define DOOMBUTTON_LEFT BUTTON_LEFT +#define DOOMBUTTON_RIGHT BUTTON_RIGHT +#define DOOMBUTTON_SHOOT BUTTON_SELECT +#define DOOMBUTTON_OPEN BUTTON_PLAY +#define DOOMBUTTON_ESC BUTTON_POWER +#define DOOMBUTTON_ENTER BUTTON_SELECT +#define DOOMBUTTON_WEAPON BUTTON_VOL_UP +#define DOOMBUTTON_MAP BUTTON_VOL_DOWN + #else #error Keymap not defined! #endif diff --git a/apps/plugins/flipit.c b/apps/plugins/flipit.c index 4a6e64a5be..f6fb059f91 100644 --- a/apps/plugins/flipit.c +++ b/apps/plugins/flipit.c @@ -484,6 +484,18 @@ #define FLIPIT_STEP_BY_STEP BUTTON_VOL_UP #define FLIPIT_TOGGLE BUTTON_PLAY +#elif CONFIG_KEYPAD == FIIO_M3K_PAD + +#define FLIPIT_LEFT BUTTON_LEFT +#define FLIPIT_RIGHT BUTTON_RIGHT +#define FLIPIT_UP BUTTON_UP +#define FLIPIT_DOWN BUTTON_DOWN +#define FLIPIT_QUIT BUTTON_POWER +#define FLIPIT_SHUFFLE BUTTON_PLAY +#define FLIPIT_SOLVE BUTTON_VOL_DOWN +#define FLIPIT_STEP_BY_STEP BUTTON_VOL_UP +#define FLIPIT_TOGGLE BUTTON_SELECT + #else #error No keymap defined! #endif diff --git a/apps/plugins/fractals/fractal.h b/apps/plugins/fractals/fractal.h index 55bd513fe0..28172aed9f 100644 --- a/apps/plugins/fractals/fractal.h +++ b/apps/plugins/fractals/fractal.h @@ -506,6 +506,18 @@ #define FRACTAL_PRECISION_DEC BUTTON_BACK #define FRACTAL_RESET BUTTON_PLAY +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define FRACTAL_QUIT BUTTON_POWER +#define FRACTAL_UP BUTTON_UP +#define FRACTAL_DOWN BUTTON_DOWN +#define FRACTAL_LEFT BUTTON_LEFT +#define FRACTAL_RIGHT BUTTON_RIGHT +#define FRACTAL_ZOOM_IN BUTTON_VOL_UP +#define FRACTAL_ZOOM_OUT BUTTON_VOL_DOWN +#define FRACTAL_PRECISION_INC BUTTON_MENU +#define FRACTAL_PRECISION_DEC BUTTON_BACK +#define FRACTAL_RESET BUTTON_PLAY + #else #error No keymap defined! #endif diff --git a/apps/plugins/goban/goban.h b/apps/plugins/goban/goban.h index 375588c7d8..9f1a200cc2 100644 --- a/apps/plugins/goban/goban.h +++ b/apps/plugins/goban/goban.h @@ -492,6 +492,18 @@ #define GBN_BUTTON_CONTEXT BUTTON_MENU | BUTTON_REPEAT #define GBN_BUTTON_NEXT_VAR BUTTON_BACK +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define GBN_BUTTON_UP BUTTON_UP +#define GBN_BUTTON_DOWN BUTTON_DOWN +#define GBN_BUTTON_LEFT BUTTON_LEFT +#define GBN_BUTTON_RIGHT BUTTON_RIGHT +#define GBN_BUTTON_RETREAT BUTTON_VOL_DOWN +#define GBN_BUTTON_ADVANCE BUTTON_VOL_UP +#define GBN_BUTTON_MENU BUTTON_MENU +#define GBN_BUTTON_PLAY BUTTON_PLAY +#define GBN_BUTTON_CONTEXT (BUTTON_SELECT|BUTTON_REPEAT) +#define GBN_BUTTON_NEXT_VAR BUTTON_BACK + #else #error Unsupported keypad #endif diff --git a/apps/plugins/imageviewer/imageviewer_button.h b/apps/plugins/imageviewer/imageviewer_button.h index 221ea3380e..cfb9a2969b 100644 --- a/apps/plugins/imageviewer/imageviewer_button.h +++ b/apps/plugins/imageviewer/imageviewer_button.h @@ -536,6 +536,20 @@ #define IMGVIEW_MENU BUTTON_MENU #define IMGVIEW_SLIDE_SHOW BUTTON_BACK +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define IMGVIEW_ZOOM_IN BUTTON_VOL_UP +#define IMGVIEW_ZOOM_OUT BUTTON_VOL_DOWN +#define IMGVIEW_UP BUTTON_UP +#define IMGVIEW_DOWN BUTTON_DOWN +#define IMGVIEW_LEFT BUTTON_LEFT +#define IMGVIEW_RIGHT BUTTON_RIGHT +#define IMGVIEW_NEXT BUTTON_BACK +#define IMGVIEW_NEXT_REPEAT (BUTTON_BACK|BUTTON_REPEAT) +#define IMGVIEW_PREVIOUS BUTTON_MENU +#define IMGVIEW_PREVIOUS_REPEAT (BUTTON_MENU|BUTTON_REPEAT) +#define IMGVIEW_MENU BUTTON_POWER +#define IMGVIEW_SLIDE_SHOW BUTTON_PLAY + #else #error No keymap defined! #endif diff --git a/apps/plugins/invadrox.c b/apps/plugins/invadrox.c index 21bba6d9d4..8b0519d9d0 100644 --- a/apps/plugins/invadrox.c +++ b/apps/plugins/invadrox.c @@ -296,6 +296,13 @@ CONFIG_KEYPAD == MROBE500_PAD #define RIGHT BUTTON_SCROLL_FWD #define FIRE BUTTON_PLAY +#elif CONFIG_KEYPAD == FIIO_M3K_PAD + +#define QUIT BUTTON_POWER +#define LEFT BUTTON_LEFT +#define RIGHT BUTTON_RIGHT +#define FIRE BUTTON_SELECT + #else #error INVADROX: Unsupported keypad #endif diff --git a/apps/plugins/jewels.c b/apps/plugins/jewels.c index 928cd78c95..83a44eea02 100644 --- a/apps/plugins/jewels.c +++ b/apps/plugins/jewels.c @@ -387,6 +387,15 @@ CONFIG_KEYPAD == MROBE500_PAD #define HK_SELECT "PLAY" #define HK_CANCEL "BACK" +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define JEWELS_UP BUTTON_UP +#define JEWELS_DOWN BUTTON_DOWN +#define JEWELS_LEFT BUTTON_LEFT +#define JEWELS_RIGHT BUTTON_RIGHT +#define JEWELS_SELECT BUTTON_SELECT +#define JEWELS_CANCEL BUTTON_BACK +#define HK_SELECT "SELECT" +#define HK_CANCEL "BACK" #else #error No keymap defined! diff --git a/apps/plugins/lib/keymaps.h b/apps/plugins/lib/keymaps.h index b0667b13cc..b660d4d85e 100644 --- a/apps/plugins/lib/keymaps.h +++ b/apps/plugins/lib/keymaps.h @@ -247,6 +247,14 @@ #define BTN_FIRE BUTTON_PLAY #define BTN_PAUSE BUTTON_POWER +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define BTN_UP BUTTON_UP +#define BTN_DOWN BUTTON_DOWN +#define BTN_LEFT BUTTON_LEFT +#define BTN_RIGHT BUTTON_RIGHT +#define BTN_FIRE BUTTON_SELECT +#define BTN_PAUSE BUTTON_POWER + #else #error Unsupported keypad #endif diff --git a/apps/plugins/lib/pluginlib_actions.c b/apps/plugins/lib/pluginlib_actions.c index 4b5a0a4505..b1bcd06ee6 100644 --- a/apps/plugins/lib/pluginlib_actions.c +++ b/apps/plugins/lib/pluginlib_actions.c @@ -269,6 +269,15 @@ const struct button_mapping pla_main_ctx[] = { PLA_DOWN_REPEAT, BUTTON_NEXT|BUTTON_REPEAT, BUTTON_NONE }, { PLA_LEFT_REPEAT, BUTTON_HOME|BUTTON_REPEAT, BUTTON_NONE }, { PLA_RIGHT_REPEAT, BUTTON_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE }, +#elif (CONFIG_KEYPAD == FIIO_M3K_PAD) + { PLA_UP, BUTTON_UP, BUTTON_NONE }, + { PLA_DOWN, BUTTON_DOWN, BUTTON_NONE }, + { PLA_LEFT, BUTTON_LEFT, BUTTON_NONE }, + { PLA_RIGHT, BUTTON_RIGHT, BUTTON_NONE }, + { PLA_UP_REPEAT, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, + { PLA_DOWN_REPEAT, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, + { PLA_LEFT_REPEAT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, + { PLA_RIGHT_REPEAT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, #else # ifndef HAVE_TOUCHSCREEN # error pluginlib_actions: No directions defined @@ -506,6 +515,12 @@ const struct button_mapping pla_main_ctx[] = {PLA_SELECT, BUTTON_PLAY, BUTTON_NONE}, {PLA_SELECT_REL, BUTTON_PLAY|BUTTON_REL, BUTTON_PLAY}, {PLA_SELECT_REPEAT, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_NONE}, +#elif (CONFIG_KEYPAD == FIIO_M3K_PAD) + {PLA_CANCEL, BUTTON_BACK, BUTTON_NONE}, + {PLA_EXIT, BUTTON_POWER, BUTTON_NONE}, + {PLA_SELECT, BUTTON_SELECT, BUTTON_NONE}, + {PLA_SELECT_REL, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT}, + {PLA_SELECT_REPEAT, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_NONE}, #else # ifndef HAVE_TOUCHSCREEN # error pluginlib_actions: No actions defined diff --git a/apps/plugins/midi/midiplay.c b/apps/plugins/midi/midiplay.c index 7dde947e1c..f07cdd4dcf 100644 --- a/apps/plugins/midi/midiplay.c +++ b/apps/plugins/midi/midiplay.c @@ -325,6 +325,14 @@ #define MIDI_VOL_DOWN BUTTON_VOL_DOWN #define MIDI_PLAYPAUSE BUTTON_PLAY +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define MIDI_QUIT BUTTON_POWER +#define MIDI_FFWD BUTTON_LEFT +#define MIDI_REWIND BUTTON_RIGHT +#define MIDI_VOL_UP BUTTON_VOL_UP +#define MIDI_VOL_DOWN BUTTON_VOL_DOWN +#define MIDI_PLAYPAUSE BUTTON_PLAY + #else #error No keymap defined! #endif diff --git a/apps/plugins/minesweeper.c b/apps/plugins/minesweeper.c index 590ea56d08..19a6b99f12 100644 --- a/apps/plugins/minesweeper.c +++ b/apps/plugins/minesweeper.c @@ -432,6 +432,17 @@ CONFIG_KEYPAD == MROBE500_PAD # define MINESWP_DISCOVER (BUTTON_PLAY | BUTTON_REPEAT) # define MINESWP_INFO BUTTON_VOL_UP +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +# define MINESWP_LEFT BUTTON_LEFT +# define MINESWP_RIGHT BUTTON_RIGHT +# define MINESWP_UP BUTTON_UP +# define MINESWP_DOWN BUTTON_DOWN +# define MINESWP_QUIT BUTTON_POWER +# define MINESWP_TOGGLE_PRE BUTTON_SELECT +# define MINESWP_TOGGLE (BUTTON_SELECT|BUTTON_REL) +# define MINESWP_DISCOVER (BUTTON_SELECT|BUTTON_REPEAT) +# define MINESWP_INFO BUTTON_MENU + #else #error No keymap defined! #endif diff --git a/apps/plugins/mp3_encoder.c b/apps/plugins/mp3_encoder.c index 244265b250..7c5084529b 100644 --- a/apps/plugins/mp3_encoder.c +++ b/apps/plugins/mp3_encoder.c @@ -2580,6 +2580,12 @@ CONFIG_KEYPAD == MROBE500_PAD #define MP3ENC_DONE BUTTON_POWER #define MP3ENC_SELECT BUTTON_PLAY +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define MP3ENC_PREV BUTTON_LEFT +#define MP3ENC_NEXT BUTTON_RIGHT +#define MP3ENC_DONE BUTTON_POWER +#define MP3ENC_SELECT BUTTON_SELECT + #else #error No keymap defined! #endif diff --git a/apps/plugins/mpegplayer/mpeg_settings.c b/apps/plugins/mpegplayer/mpeg_settings.c index 44c72dd853..d59797eaa7 100644 --- a/apps/plugins/mpegplayer/mpeg_settings.c +++ b/apps/plugins/mpegplayer/mpeg_settings.c @@ -354,6 +354,14 @@ struct mpeg_settings settings; #define MPEG_START_TIME_DOWN BUTTON_NEXT #define MPEG_START_TIME_EXIT BUTTON_POWER +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define MPEG_START_TIME_SELECT BUTTON_SELECT +#define MPEG_START_TIME_LEFT BUTTON_LEFT +#define MPEG_START_TIME_RIGHT BUTTON_RIGHT +#define MPEG_START_TIME_UP BUTTON_UP +#define MPEG_START_TIME_DOWN BUTTON_DOWN +#define MPEG_START_TIME_EXIT BUTTON_POWER + #else #error No keymap defined! #endif diff --git a/apps/plugins/mpegplayer/mpegplayer.c b/apps/plugins/mpegplayer/mpegplayer.c index 81b6d37857..6b18e4fa3a 100644 --- a/apps/plugins/mpegplayer/mpegplayer.c +++ b/apps/plugins/mpegplayer/mpegplayer.c @@ -486,6 +486,15 @@ CONFIG_KEYPAD == SANSA_M200_PAD #define MPEG_RW BUTTON_PREV #define MPEG_FF BUTTON_NEXT +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define MPEG_MENU BUTTON_MENU +#define MPEG_STOP BUTTON_POWER +#define MPEG_PAUSE BUTTON_PLAY +#define MPEG_VOLDOWN BUTTON_VOL_DOWN +#define MPEG_VOLUP BUTTON_VOL_UP +#define MPEG_RW BUTTON_LEFT +#define MPEG_FF BUTTON_RIGHT + #else #error No keymap defined! #endif diff --git a/apps/plugins/oscilloscope.c b/apps/plugins/oscilloscope.c index d50de7f2a0..881295d6ab 100644 --- a/apps/plugins/oscilloscope.c +++ b/apps/plugins/oscilloscope.c @@ -537,6 +537,17 @@ #define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP #define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define OSCILLOSCOPE_QUIT BUTTON_POWER +#define OSCILLOSCOPE_DRAWMODE BUTTON_MENU +#define OSCILLOSCOPE_ADVMODE BUTTON_PLAY +#define OSCILLOSCOPE_ORIENTATION BUTTON_BACK +#define OSCILLOSCOPE_PAUSE BUTTON_SELECT +#define OSCILLOSCOPE_SPEED_UP BUTTON_SCROLL_BACK +#define OSCILLOSCOPE_SPEED_DOWN BUTTON_SCROLL_FWD +#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP +#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN + #else #error No keymap defined! #endif diff --git a/apps/plugins/pacbox/pacbox.h b/apps/plugins/pacbox/pacbox.h index 48196146a7..c1a1c6b9e5 100644 --- a/apps/plugins/pacbox/pacbox.h +++ b/apps/plugins/pacbox/pacbox.h @@ -401,6 +401,15 @@ #define PACMAN_1UP BUTTON_VOL_UP #define PACMAN_COIN BUTTON_PLAY +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define PACMAN_UP BUTTON_UP +#define PACMAN_DOWN BUTTON_DOWN +#define PACMAN_LEFT BUTTON_LEFT +#define PACMAN_RIGHT BUTTON_RIGHT +#define PACMAN_MENU BUTTON_MENU +#define PACMAN_1UP BUTTON_VOL_UP +#define PACMAN_COIN BUTTON_PLAY + #else #error Keymap not defined! diff --git a/apps/plugins/pegbox.c b/apps/plugins/pegbox.c index e16cf2921e..498aa36357 100644 --- a/apps/plugins/pegbox.c +++ b/apps/plugins/pegbox.c @@ -711,6 +711,23 @@ CONFIG_KEYPAD == MROBE500_PAD #define LVL_UP_TEXT "VOL+" #define LVL_DOWN_TEXT "VOL-" +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define PEGBOX_SELECT BUTTON_SELECT +#define PEGBOX_QUIT BUTTON_POWER +#define PEGBOX_RESTART BUTTON_BACK +#define PEGBOX_LVL_UP BUTTON_VOL_UP +#define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN +#define PEGBOX_UP BUTTON_UP +#define PEGBOX_DOWN BUTTON_DOWN +#define PEGBOX_RIGHT BUTTON_RIGHT +#define PEGBOX_LEFT BUTTON_LEFT + +#define SELECT_TEXT "SELECT" +#define QUIT_TEXT "POWER" +#define RESTART_TEXT "BACK" +#define LVL_UP_TEXT "VOL+" +#define LVL_DOWN_TEXT "VOL-" + #else #error "Unsupported keymap!" #endif diff --git a/apps/plugins/plugin.lds b/apps/plugins/plugin.lds index 25ff4a461b..5931b6b0a5 100644 --- a/apps/plugins/plugin.lds +++ b/apps/plugins/plugin.lds @@ -76,6 +76,10 @@ OUTPUT_FORMAT(elf32-littlemips) #elif CONFIG_CPU==IMX233 #include "cpu.h" #define DRAMSIZE (DRAM_SIZE - PLUGIN_BUFFER_SIZE - CODEC_SIZE - FRAME_SIZE - TTB_SIZE) +#elif CONFIG_CPU==X1000 +#include "config.h" +#undef STUBOFFSET +#define STUBOFFSET 0x4000 #endif /* default to full RAM (minus codecs&plugins) unless specified otherwise */ @@ -174,6 +178,11 @@ OUTPUT_FORMAT(elf32-littlemips) #define IRAMSIZE 0 /* The bit of IRAM that is available is used in the core */ +#elif CONFIG_CPU == X1000 +#define DRAMORIG (0x80000000 + STUBOFFSET) +#define IRAM DRAM +#define IRAMSIZE 0 + #elif CONFIG_CPU == RK27XX #define DRAMORIG 0x60000000 #define IRAM DRAM diff --git a/apps/plugins/pong.c b/apps/plugins/pong.c index 4df4db66bb..b06789af6b 100644 --- a/apps/plugins/pong.c +++ b/apps/plugins/pong.c @@ -325,6 +325,13 @@ CONFIG_KEYPAD == MROBE500_PAD #define PONG_RIGHT_UP BUTTON_PREV #define PONG_RIGHT_DOWN BUTTON_NEXT +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define PONG_QUIT BUTTON_POWER +#define PONG_PAUSE BUTTON_PLAY +#define PONG_LEFT_UP BUTTON_MENU +#define PONG_LEFT_DOWN BUTTON_LEFT +#define PONG_RIGHT_UP BUTTON_BACK +#define PONG_RIGHT_DOWN BUTTON_RIGHT #else #error No keymap defined! diff --git a/apps/plugins/reversi/reversi-gui.h b/apps/plugins/reversi/reversi-gui.h index c94ca59179..fd60b23927 100644 --- a/apps/plugins/reversi/reversi-gui.h +++ b/apps/plugins/reversi/reversi-gui.h @@ -361,6 +361,15 @@ #define REVERSI_BUTTON_MAKE_MOVE BUTTON_PLAY #define REVERSI_BUTTON_MENU BUTTON_MENU +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define REVERSI_BUTTON_QUIT BUTTON_POWER +#define REVERSI_BUTTON_UP BUTTON_UP +#define REVERSI_BUTTON_DOWN BUTTON_DOWN +#define REVERSI_BUTTON_LEFT BUTTON_LEFT +#define REVERSI_BUTTON_RIGHT BUTTON_RIGHT +#define REVERSI_BUTTON_MAKE_MOVE BUTTON_SELECT +#define REVERSI_BUTTON_MENU BUTTON_MENU + #else #error No keymap defined! #endif diff --git a/apps/plugins/rockblox.c b/apps/plugins/rockblox.c index 7958818a8e..9c36f8f62f 100644 --- a/apps/plugins/rockblox.c +++ b/apps/plugins/rockblox.c @@ -477,6 +477,16 @@ #define ROCKBLOX_DROP BUTTON_PLAY #define ROCKBLOX_RESTART BUTTON_BACK +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define ROCKBLOX_OFF BUTTON_POWER +#define ROCKBLOX_ROTATE_CCW BUTTON_UP +#define ROCKBLOX_ROTATE_CW BUTTON_DOWN +#define ROCKBLOX_DOWN BUTTON_SELECT +#define ROCKBLOX_LEFT BUTTON_LEFT +#define ROCKBLOX_RIGHT BUTTON_RIGHT +#define ROCKBLOX_DROP BUTTON_PLAY +#define ROCKBLOX_RESTART BUTTON_BACK + #else #error No keymap defined! #endif diff --git a/apps/plugins/rockboy/rockboy.c b/apps/plugins/rockboy/rockboy.c index 1f65b780a6..6dd010961e 100644 --- a/apps/plugins/rockboy/rockboy.c +++ b/apps/plugins/rockboy/rockboy.c @@ -467,6 +467,17 @@ static void setoptions (void) options.SELECT = BUTTON_VOL_UP; options.MENU = BUTTON_POWER; +#elif CONFIG_KEYPAD == FIIO_M3K_PAD + options.UP = BUTTON_UP; + options.DOWN = BUTTON_DOWN; + options.LEFT = BUTTON_LEFT; + options.RIGHT = BUTTON_RIGHT; + options.A = BUTTON_MENU; + options.B = BUTTON_BACK; + options.START = BUTTON_VOL_DOWN; + options.SELECT = BUTTON_VOL_UP; + options.MENU = BUTTON_POWER; + #else #error No Keymap Defined! #endif diff --git a/apps/plugins/rockpaint.c b/apps/plugins/rockpaint.c index e2b1f2a3e3..0d3211d4d2 100644 --- a/apps/plugins/rockpaint.c +++ b/apps/plugins/rockpaint.c @@ -393,6 +393,17 @@ #define ROCKPAINT_LEFT BUTTON_HOME #define ROCKPAINT_RIGHT BUTTON_VOL_DOWN +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define ROCKPAINT_QUIT BUTTON_POWER +#define ROCKPAINT_DRAW BUTTON_SELECT +#define ROCKPAINT_MENU BUTTON_MENU +#define ROCKPAINT_TOOLBAR BUTTON_VOL_UP +#define ROCKPAINT_TOOLBAR2 BUTTON_VOL_DOWN +#define ROCKPAINT_UP BUTTON_UP +#define ROCKPAINT_DOWN BUTTON_DOWN +#define ROCKPAINT_LEFT BUTTON_LEFT +#define ROCKPAINT_RIGHT BUTTON_RIGHT + #else #error "Please define keys for this keypad" #endif diff --git a/apps/plugins/sliding_puzzle.c b/apps/plugins/sliding_puzzle.c index dec400c079..d1820b2f50 100644 --- a/apps/plugins/sliding_puzzle.c +++ b/apps/plugins/sliding_puzzle.c @@ -348,6 +348,14 @@ CONFIG_KEYPAD == MROBE500_PAD #define PUZZLE_SHUFFLE BUTTON_BACK #define PUZZLE_PICTURE BUTTON_PLAY +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define PUZZLE_QUIT BUTTON_POWER +#define PUZZLE_LEFT BUTTON_LEFT +#define PUZZLE_RIGHT BUTTON_RIGHT +#define PUZZLE_UP BUTTON_UP +#define PUZZLE_DOWN BUTTON_DOWN +#define PUZZLE_SHUFFLE BUTTON_BACK +#define PUZZLE_PICTURE BUTTON_PLAY #else #error No keymap defined! diff --git a/apps/plugins/snake.c b/apps/plugins/snake.c index c5c28eba6e..459d345fa2 100644 --- a/apps/plugins/snake.c +++ b/apps/plugins/snake.c @@ -305,6 +305,14 @@ dir is the current direction of the snake - 0=up, 1=right, 2=down, 3=left; #define SNAKE_DOWN BUTTON_NEXT #define SNAKE_PLAYPAUSE BUTTON_PLAY +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define SNAKE_QUIT BUTTON_POWER +#define SNAKE_LEFT BUTTON_LEFT +#define SNAKE_RIGHT BUTTON_RIGHT +#define SNAKE_UP BUTTON_UP +#define SNAKE_DOWN BUTTON_DOWN +#define SNAKE_PLAYPAUSE BUTTON_PLAY + #else #error No keymap defined! #endif diff --git a/apps/plugins/snake2.c b/apps/plugins/snake2.c index fcc1790a13..1536840daf 100644 --- a/apps/plugins/snake2.c +++ b/apps/plugins/snake2.c @@ -437,6 +437,15 @@ CONFIG_KEYPAD == MROBE500_PAD #define SNAKE2_PLAYPAUSE BUTTON_PLAY #define SNAKE2_PLAYPAUSE_TEXT "PLAY" +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define SNAKE2_LEFT BUTTON_LEFT +#define SNAKE2_RIGHT BUTTON_RIGHT +#define SNAKE2_UP BUTTON_UP +#define SNAKE2_DOWN BUTTON_DOWN +#define SNAKE2_QUIT BUTTON_POWER +#define SNAKE2_PLAYPAUSE BUTTON_PLAY +#define SNAKE2_PLAYPAUSE_TEXT "PLAY" + #else #error No keymap defined! #endif diff --git a/apps/plugins/sokoban.c b/apps/plugins/sokoban.c index 2dcea7546f..9d57d7428c 100644 --- a/apps/plugins/sokoban.c +++ b/apps/plugins/sokoban.c @@ -695,6 +695,21 @@ #define BUTTON_SAVE BUTTON_PLAY #define BUTTON_SAVE_NAME "PLAY" +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define SOKOBAN_LEFT BUTTON_LEFT +#define SOKOBAN_RIGHT BUTTON_RIGHT +#define SOKOBAN_UP BUTTON_UP +#define SOKOBAN_DOWN BUTTON_DOWN +#define SOKOBAN_MENU BUTTON_MENU +#define SOKOBAN_UNDO BUTTON_VOL_DOWN +#define SOKOBAN_REDO BUTTON_VOL_UP +#define SOKOBAN_LEVEL_DOWN (BUTTON_PLAY|BUTTON_VOL_DOWN) +#define SOKOBAN_LEVEL_UP (BUTTON_PLAY|BUTTON_VOL_UP) +#define SOKOBAN_LEVEL_REPEAT (BUTTON_PLAY|BUTTON_POWER) +#define SOKOBAN_PAUSE BUTTON_SELECT +#define BUTTON_SAVE BUTTON_BACK +#define BUTTON_SAVE_NAME "BACK" + #else #error No keymap defined! #endif diff --git a/apps/plugins/solitaire.c b/apps/plugins/solitaire.c index d14c608396..2d737df678 100644 --- a/apps/plugins/solitaire.c +++ b/apps/plugins/solitaire.c @@ -722,6 +722,25 @@ CONFIG_KEYPAD == MROBE500_PAD # define HK_CUR2STACK "DBL PLAY" # define HK_REM2STACK "NEXT" +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +# define SOL_QUIT BUTTON_POWER +# define SOL_UP BUTTON_UP +# define SOL_DOWN BUTTON_DOWN +# define SOL_LEFT BUTTON_LEFT +# define SOL_RIGHT BUTTON_RIGHT +# define SOL_MOVE_PRE BUTTON_SELECT +# define SOL_MOVE (BUTTON_SELECT|BUTTON_REL) +# define SOL_DRAW BUTTON_PLAY +# define SOL_REM2CUR BUTTON_VOL_DOWN +# define SOL_CUR2STACK_PRE BUTTON_SELECT +# define SOL_CUR2STACK (BUTTON_SELECT|BUTTON_REPEAT) +# define SOL_REM2STACK BUTTON_VOL_UP +# define HK_MOVE "SELECT" +# define HK_DRAW "PLAY" +# define HK_REM2CUR "VOL-" +# define HK_CUR2STACK "HOLD SELECT" +# define HK_REM2STACK "VOL+" + #else #error No keymap defined! #endif diff --git a/apps/plugins/spacerocks.c b/apps/plugins/spacerocks.c index 608f3ee512..2d39c26b3d 100644 --- a/apps/plugins/spacerocks.c +++ b/apps/plugins/spacerocks.c @@ -363,6 +363,15 @@ #define AST_RIGHT BUTTON_SCROLL_FWD #define AST_FIRE BUTTON_BACK +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define AST_PAUSE BUTTON_MENU +#define AST_QUIT BUTTON_POWER +#define AST_THRUST BUTTON_SELECT +#define AST_HYPERSPACE BUTTON_BACK +#define AST_LEFT BUTTON_LEFT +#define AST_RIGHT BUTTON_RIGHT +#define AST_FIRE BUTTON_PLAY + #else #error No keymap defined! #endif diff --git a/apps/plugins/star.c b/apps/plugins/star.c index 9de5032699..c186474ae3 100644 --- a/apps/plugins/star.c +++ b/apps/plugins/star.c @@ -652,6 +652,22 @@ #define STAR_LEVEL_DOWN_NAME "VOL DN" #define STAR_LEVEL_REPEAT_NAME "BACK" +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define STAR_QUIT BUTTON_POWER +#define STAR_LEFT BUTTON_LEFT +#define STAR_RIGHT BUTTON_RIGHT +#define STAR_UP BUTTON_UP +#define STAR_DOWN BUTTON_DOWN +#define STAR_TOGGLE_CONTROL BUTTON_PLAY +#define STAR_LEVEL_UP BUTTON_VOL_UP +#define STAR_LEVEL_DOWN BUTTON_VOL_DOWN +#define STAR_LEVEL_REPEAT BUTTON_BACK +#define STAR_TOGGLE_CONTROL_NAME "PLAY" +#define STAR_QUIT_NAME "POWER" +#define STAR_LEVEL_UP_NAME "VOL+" +#define STAR_LEVEL_DOWN_NAME "VOL-" +#define STAR_LEVEL_REPEAT_NAME "BACK" + #else #error No keymap defined! #endif diff --git a/apps/plugins/stopwatch.c b/apps/plugins/stopwatch.c index 82e6fba5c6..5259d0d616 100644 --- a/apps/plugins/stopwatch.c +++ b/apps/plugins/stopwatch.c @@ -309,6 +309,14 @@ #define STOPWATCH_SCROLL_UP BUTTON_SCROLL_FWD #define STOPWATCH_SCROLL_DOWN BUTTON_SCROLL_BACK +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define STOPWATCH_QUIT BUTTON_POWER +#define STOPWATCH_START_STOP BUTTON_PLAY +#define STOPWATCH_RESET_TIMER BUTTON_BACK +#define STOPWATCH_LAP_TIMER BUTTON_SELECT +#define STOPWATCH_SCROLL_UP BUTTON_SCROLL_BACK +#define STOPWATCH_SCROLL_DOWN BUTTON_SCROLL_FWD + #else #error No keymap defined! #endif diff --git a/apps/plugins/sudoku/sudoku.h b/apps/plugins/sudoku/sudoku.h index de3802d9bc..6ee3eb33ee 100644 --- a/apps/plugins/sudoku/sudoku.h +++ b/apps/plugins/sudoku/sudoku.h @@ -459,6 +459,17 @@ #define SUDOKU_BUTTON_MENU (BUTTON_MENU | BUTTON_REL) #define SUDOKU_BUTTON_POSSIBLE BUTTON_BACK +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define SUDOKU_BUTTON_QUIT BUTTON_POWER +#define SUDOKU_BUTTON_UP BUTTON_UP +#define SUDOKU_BUTTON_DOWN BUTTON_DOWN +#define SUDOKU_BUTTON_LEFT BUTTON_LEFT +#define SUDOKU_BUTTON_RIGHT BUTTON_RIGHT +#define SUDOKU_BUTTON_TOGGLEBACK BUTTON_VOL_DOWN +#define SUDOKU_BUTTON_TOGGLE BUTTON_VOL_UP +#define SUDOKU_BUTTON_MENU BUTTON_MENU +#define SUDOKU_BUTTON_POSSIBLE BUTTON_BACK + #else #error No keymap defined! #endif diff --git a/apps/plugins/text_viewer/tv_button.h b/apps/plugins/text_viewer/tv_button.h index ba71201cda..bea8f829ef 100644 --- a/apps/plugins/text_viewer/tv_button.h +++ b/apps/plugins/text_viewer/tv_button.h @@ -583,6 +583,18 @@ #define TV_LINE_DOWN (BUTTON_POWER | BUTTON_VOL_DOWN) #define TV_BOOKMARK (BUTTON_POWER | BUTTON_PLAY) +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define TV_QUIT BUTTON_POWER +#define TV_SCROLL_UP BUTTON_VOL_UP +#define TV_SCROLL_DOWN BUTTON_VOL_DOWN +#define TV_SCREEN_LEFT BUTTON_LEFT +#define TV_SCREEN_RIGHT BUTTON_RIGHT +#define TV_MENU BUTTON_MENU +#define TV_AUTOSCROLL BUTTON_SELECT +#define TV_LINE_UP BUTTON_SCROLL_BACK +#define TV_LINE_DOWN BUTTON_SCROLL_FWD +#define TV_BOOKMARK BUTTON_PLAY + #else #error No keymap defined! #endif diff --git a/apps/plugins/vu_meter.c b/apps/plugins/vu_meter.c index 629294ce7f..e24ad8dcdc 100644 --- a/apps/plugins/vu_meter.c +++ b/apps/plugins/vu_meter.c @@ -441,6 +441,17 @@ #define LABEL_MENU "MENU" #define LABEL_VOLUME "VOL UP/DN" +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define VUMETER_QUIT BUTTON_POWER +#define VUMETER_HELP BUTTON_BACK +#define VUMETER_MENU BUTTON_MENU +#define VUMETER_UP BUTTON_VOL_UP +#define VUMETER_DOWN BUTTON_VOL_DOWN +#define LABEL_HELP "BACK" +#define LABEL_QUIT "POWER" +#define LABEL_MENU "MENU" +#define LABEL_VOLUME "VOL+/VOL-" + #else #error No keymap defined! #endif diff --git a/apps/plugins/wormlet.c b/apps/plugins/wormlet.c index d3db768535..d76f6a7d5a 100644 --- a/apps/plugins/wormlet.c +++ b/apps/plugins/wormlet.c @@ -398,6 +398,15 @@ CONFIG_KEYPAD == MROBE500_PAD #define BTN_QUIT BUTTON_POWER #define BTN_STOPRESET BUTTON_BACK +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define BTN_DIR_UP BUTTON_UP +#define BTN_DIR_DOWN BUTTON_DOWN +#define BTN_DIR_LEFT BUTTON_LEFT +#define BTN_DIR_RIGHT BUTTON_RIGHT +#define BTN_STARTPAUSE BUTTON_PLAY +#define BTN_QUIT BUTTON_POWER +#define BTN_STOPRESET BUTTON_BACK + #else #error No keymap defined! #endif diff --git a/apps/plugins/xobox.c b/apps/plugins/xobox.c index e04ecc225d..36aae071cb 100644 --- a/apps/plugins/xobox.c +++ b/apps/plugins/xobox.c @@ -351,6 +351,15 @@ CONFIG_KEYPAD == MROBE500_PAD #define DOWN BUTTON_NEXT #define PAUSE BUTTON_PLAY +#elif CONFIG_KEYPAD == FIIO_M3K_PAD + +#define QUIT BUTTON_POWER +#define LEFT BUTTON_LEFT +#define RIGHT BUTTON_RIGHT +#define UP BUTTON_UP +#define DOWN BUTTON_DOWN +#define PAUSE BUTTON_PLAY + #else #error "No keymap defined!" #endif diff --git a/apps/plugins/zxbox/keymaps.h b/apps/plugins/zxbox/keymaps.h index e62c33c157..dbebc3b1d9 100644 --- a/apps/plugins/zxbox/keymaps.h +++ b/apps/plugins/zxbox/keymaps.h @@ -298,6 +298,14 @@ #define ZX_UP BUTTON_PREV #define ZX_DOWN BUTTON_NEXT +#elif CONFIG_KEYPAD == FIIO_M3K_PAD +#define ZX_SELECT BUTTON_SELECT +#define ZX_MENU BUTTON_MENU +#define ZX_LEFT BUTTON_LEFT +#define ZX_RIGHT BUTTON_RIGHT +#define ZX_UP BUTTON_UP +#define ZX_DOWN BUTTON_DOWN + #else #error Keymap not defined! diff --git a/apps/plugins/zxbox/zxbox_keyb.c b/apps/plugins/zxbox/zxbox_keyb.c index 6237ded8c1..dd517e01e7 100644 --- a/apps/plugins/zxbox/zxbox_keyb.c +++ b/apps/plugins/zxbox/zxbox_keyb.c @@ -293,6 +293,15 @@ #define KBD_UP BUTTON_PREV #define KBD_DOWN BUTTON_NEXT +#elif CONFIG_KEYPAD == FIIO_M3K_PAD + +#define KBD_SELECT BUTTON_SELECT +#define KBD_ABORT BUTTON_BACK +#define KBD_LEFT BUTTON_LEFT +#define KBD_RIGHT BUTTON_RIGHT +#define KBD_UP BUTTON_UP +#define KBD_DOWN BUTTON_DOWN + #endif #ifdef HAVE_TOUCHSCREEN diff --git a/bootloader/SOURCES b/bootloader/SOURCES index 3c9a3068ad..db9e05644c 100644 --- a/bootloader/SOURCES +++ b/bootloader/SOURCES @@ -89,4 +89,11 @@ show_logo.c #elif defined(SANSA_CONNECT) sansaconnect.c show_logo.c +#elif defined(FIIO_M3K) +#ifdef BOOTLOADER_SPL +x1000-spl.c +fiiom3k-spl.c +#else +fiiom3k.c +#endif #endif diff --git a/bootloader/fiiom3k-spl.c b/bootloader/fiiom3k-spl.c new file mode 100644 index 0000000000..ec532d5789 --- /dev/null +++ b/bootloader/fiiom3k-spl.c @@ -0,0 +1,204 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 "nand-x1000.h" +#include "gpio-x1000.h" +#include "mmu-mips.h" +#include <string.h> + +/* "fiio" in little endian */ +#define BOOTMAGIC 0x6f696966 + +/* Argument structure needed by Linux */ +struct linux_kargs { + void* arg0; + void* arg1; +}; + +#define LINUX_KARGSADDR 0x80004000 + +static const char recovery_cmdline[] = "mem=xxM@0x0\ + no_console_suspend\ + console=ttyS2,115200n8\ + lpj=5009408\ + ip=off"; + +static const char normal_cmdline[] = "mem=64M@0x0\ + no_console_suspend\ + console=ttyS2,115200n8\ + lpj=5009408\ + ip=off\ + init=/linuxrc\ + ubi.mtd=3\ + root=ubi0:rootfs\ + ubi.mtd=4\ + rootfstype=ubifs\ + rw\ + loglevel=8"; + +#define BOOTOPTION_ROCKBOX 0 +#define BOOTOPTION_FIIOLINUX 1 +#define BOOTOPTION_RECOVERY 2 +#define NUM_BOOTOPTIONS 3 + +static const struct bootoption { + uint32_t nand_addr; + uint32_t nand_size; + unsigned long load_addr; + unsigned long exec_addr; + const char* cmdline; +} boot_options[NUM_BOOTOPTIONS] = { + { + /* Rockbox: the first unused NAND page is 26 KiB in, and the + * remainder of the block is unused, giving us 102 KiB to use. + */ + .nand_addr = 0x6800, + .nand_size = 0x19800, + .load_addr = 0x80003ff8, /* first 8 bytes are bootloader ID */ + .exec_addr = 0x80004000, + .cmdline = NULL, + }, + { + /* Original firmware */ + .nand_addr = 0x20000, + .nand_size = 0x400000, + .load_addr = 0x80efffc0, + .exec_addr = 0x80f00000, + .cmdline = normal_cmdline, + }, + { + /* Recovery image */ + .nand_addr = 0x420000, + .nand_size = 0x500000, + .load_addr = 0x80efffc0, + .exec_addr = 0x80f00000, + .cmdline = recovery_cmdline, + }, +}; + +/* Simple diagnostic if something goes wrong -- a little nicer than wondering + * what's going on when the machine hangs + */ +void die(void) +{ + const int pin = (1 << 24); + + /* Turn on button light */ + jz_clr(GPIO_INT(GPIO_C), pin); + jz_set(GPIO_MSK(GPIO_C), pin); + jz_clr(GPIO_PAT1(GPIO_C), pin); + jz_set(GPIO_PAT0(GPIO_C), pin); + + while(1) { + /* Turn it off */ + mdelay(100); + jz_set(GPIO_PAT0(GPIO_C), pin); + + /* Turn it on */ + mdelay(100); + jz_clr(GPIO_PAT0(GPIO_C), pin); + } +} + +/* Boot select button state must remain stable for this duration + * before the choice will be accepted. Currently 100ms. + */ +#define BTN_STABLE_TIME (100 * (X1000_EXCLK_FREQ / 4000)) + +int get_boot_option(void) +{ + const uint32_t pinmask = (1 << 17) | (1 << 19); + + uint32_t pin = 1, lastpin = 0; + uint32_t deadline = 0; + + /* Configure the button GPIOs as inputs */ + gpio_config(GPIO_A, pinmask, GPIO_INPUT); + + /* Poll the pins for a short duration to detect a keypress */ + do { + lastpin = pin; + pin = ~REG_GPIO_PIN(GPIO_A) & pinmask; + if(pin != lastpin) { + /* This will always be set on the first iteration */ + deadline = __ost_read32() + BTN_STABLE_TIME; + } + } while(__ost_read32() < deadline); + + /* Play button boots original firmware */ + if(pin == (1 << 17)) + return BOOTOPTION_FIIOLINUX; + + /* Volume up boots recovery */ + if(pin == (1 << 19)) + return BOOTOPTION_RECOVERY; + + /* Default is to boot Rockbox */ + return BOOTOPTION_ROCKBOX; +} + +void spl_main(void) +{ + /* Get user boot option */ + int booti = get_boot_option(); + const struct bootoption* opt = &boot_options[booti]; + + /* Load selected firmware from flash */ + if(nand_open()) + die(); + if(nand_read_bytes(opt->nand_addr, opt->nand_size, (void*)opt->load_addr)) + die(); + + if(booti == BOOTOPTION_ROCKBOX) { + /* If bootloader is not installed, return back to boot ROM. + * Also read in the first eraseblock of NAND flash so it can be + * dumped back over USB. + */ + if(*(unsigned*)(opt->load_addr + 4) != BOOTMAGIC) { + nand_read_bytes(0, 128 * 1024, (void*)0x80000000); + commit_discard_idcache(); + return; + } + } else { + /* TODO: Linux boot not implemented yet + * + * - Have to initialize UART2, as it's used for the serial console + * - Must initialize APLL and change clocks over + * - There are some other clocks which need to be initialized + * - We should turn off OST since the OF SPL does not turn it on + */ + die(); + } + + if(boot_options[booti].cmdline) { + /* Handle Linux command line arguments */ + struct linux_kargs* kargs = (struct linux_kargs*)LINUX_KARGSADDR; + kargs->arg0 = 0; + kargs->arg1 = (void*)boot_options[booti].cmdline; + } + + /* Flush caches and jump to address */ + void* execaddr = (void*)opt->exec_addr; + commit_discard_idcache(); + __asm__ __volatile__ ("jr %0" :: "r"(execaddr)); + __builtin_unreachable(); +} diff --git a/bootloader/fiiom3k.c b/bootloader/fiiom3k.c new file mode 100644 index 0000000000..6108a37efc --- /dev/null +++ b/bootloader/fiiom3k.c @@ -0,0 +1,96 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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/kernel-internal.h" +#include "i2c.h" +#include "power.h" +#include "lcd.h" +#include "backlight.h" +#include "button.h" +#include "storage.h" +#include "file_internal.h" +#include "disk.h" +#include "rb-loader.h" +#include "loader_strerror.h" + +/* Load address where the binary needs to be placed */ +extern unsigned char loadaddress[]; + +/* Fixed buffer to contain the loaded binary in memory */ +extern unsigned char loadbuffer[]; +extern unsigned char loadbufferend[]; +#define MAX_LOAD_SIZE (loadbufferend - loadbuffer) + +void exec(void* dst, const void* src, int bytes) + __attribute__((noreturn, section(".icode"))); + +void exec(void* dst, const void* src, int bytes) +{ + memcpy(dst, src, bytes); + commit_discard_idcache(); + __asm__ __volatile__ ("jr %0" :: "r"(dst)); + __builtin_unreachable(); +} + +static void error(const char* msg) +{ + /* Initialization of the LCD/buttons only if needed */ + lcd_init(); + backlight_init(); + button_init(); + + lcd_clear_display(); + lcd_puts(0, 0, msg); + lcd_puts(0, 2, "Press POWER to power off"); + lcd_update(); + + while(button_get(true) != BUTTON_POWER); + power_off(); +} + +void main(void) +{ + system_init(); + kernel_init(); + i2c_init(); + power_init(); + enable_irq(); + + if(storage_init() < 0) + error("Storage initialization failed"); + + filesystem_init(); + + if(!storage_present(0)) + error("No SD card present"); + + if(disk_mount_all() <= 0) + error("Unable to mount filesystem"); + + int loadsize = load_firmware(loadbuffer, BOOTFILE, MAX_LOAD_SIZE); + if(loadsize <= 0) + error(loader_strerror(loadsize)); + + disable_irq(); + + exec(loadaddress, loadbuffer, loadsize); +} diff --git a/bootloader/x1000-spl.c b/bootloader/x1000-spl.c new file mode 100644 index 0000000000..1c780a9843 --- /dev/null +++ b/bootloader/x1000-spl.c @@ -0,0 +1,230 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 "clk-x1000.h" +#include "x1000/cpm.h" +#include "x1000/ost.h" +#include "x1000/ddrc.h" +#include "x1000/ddrc_apb.h" +#include "x1000/ddrphy.h" + +#ifdef FIIO_M3K +# define DDR_USE_AUTOSR 1 +# define DDR_NEED_BYPASS 1 +# define DDR_MEMORYSIZE 64 +#else +# error "Please add DDR definitions for new target!" +#endif + +#define hang() do { } while(1) + +/* Target-specific routine to load & execute the Rockbox bootloader */ +extern void spl_main(void); + +/* Note: This is based purely on disassembly of the SPL from the FiiO M3K. + * The code there is somewhat generic and corresponds roughly to Ingenic's + * U-Boot code, but isn't entirely the same. + * + * I converted all the runtime conditionals to compile-time ones in order to + * save code space, since they should be constant for any given target. + * + * I haven't bothered to decode all the register fields. Some of the values + * written are going to bits documented as "Reserved" by Ingenic, but their + * documentation doesn't seem completely reliable, so either these are bits + * which _do_ have a purpose, or they're only defined on other Ingenic CPUs. + * + * The DDR PHY registers appear to be from Synopsys "PHY Utility Block Lite". + * These aren't documented by Ingenic, but the addresses and names can be found + * in their U-Boot code. + */ +static void ddr_init(void) +{ + REG_CPM_DRCG = 0x73; + mdelay(3); + REG_CPM_DRCG = 0x71; + mdelay(3); + REG_DDRC_APB_PHYRST_CFG = 0x1a00001; + mdelay(3); + REG_DDRC_APB_PHYRST_CFG = 0; + mdelay(3); + REG_DDRC_CTRL = 0xf00000; + mdelay(3); + REG_DDRC_CTRL = 0; + mdelay(3); + + REG_DDRC_CFG = 0xa468a6c; + REG_DDRC_CTRL = 2; + REG_DDRPHY_DTAR = 0x150000; + REG_DDRPHY_DCR = 0; + REG_DDRPHY_MR0 = 0x42; + REG_DDRPHY_MR2 = 0x98; + REG_DDRPHY_PTR0 = 0x21000a; + REG_DDRPHY_PTR1 = 0xa09c40; + REG_DDRPHY_PTR2 = 0x280014; + REG_DDRPHY_DTPR0 = 0x1a69444a; + REG_DDRPHY_DTPR1 = 0x180090; + REG_DDRPHY_DTPR2 = 0x1ff99428; + REG_DDRPHY_DXGCR(0) = 0x90881; + REG_DDRPHY_DXGCR(1) = 0x90881; + REG_DDRPHY_DXGCR(2) = 0x90e80; + REG_DDRPHY_DXGCR(3) = 0x90e80; + REG_DDRPHY_PGCR = 0x1042e03; + REG_DDRPHY_ACIOCR = 0x30c00813; + REG_DDRPHY_DXCCR = 0x4912; + + int i = 10000; + while(i > 0 && REG_DDRPHY_PGSR != 7 && REG_DDRPHY_PGSR != 0x1f) + i -= 1; + if(i == 0) + hang(); + +#if DDR_NEED_BYPASS + REG_DDRPHY_ACDLLCR = 0x80000000; + REG_DDRPHY_DSGCR &= ~0x10; + REG_DDRPHY_DLLGCR |= 0x800000; + REG_DDRPHY_PIR = 0x20020041; +#else + REG_DDRPHY_PIR = 0x41; +#endif + + while(i > 0 && REG_DDRPHY_PGSR != 0xf && REG_DDRPHY_PGSR != 0x1f) + i -= 1; + if(i == 0) + hang(); + + REG_DDRC_APB_PHYRST_CFG = 0x400000; + mdelay(3); + REG_DDRC_APB_PHYRST_CFG = 0; + mdelay(3); + + REG_DDRC_CFG = 0xa468aec; + REG_DDRC_CTRL = 2; +#if DDR_NEED_BYPASS + REG_DDRPHY_PIR = 0x20020081; +#else + REG_DDRPHY_PIR = 0x85; +#endif + + i = 500000; + while(REG_DDRPHY_PGSR != 0x1f) { + if(REG_DDRPHY_PGSR & 0x70) + break; + i -= 1; + } + + if(i == 0) + hang(); + + if((REG_DDRPHY_PGSR & 0x60) != 0 && REG_DDRPHY_PGSR != 0) + hang(); + + REG_DDRC_CTRL = 0; + REG_DDRC_CTRL = 10; + REG_DDRC_CTRL = 0; + REG_DDRC_CFG = 0xa468a6c; + REG_DDRC_TIMING1 = 0x2050501; + REG_DDRC_TIMING2 = 0x4090404; + REG_DDRC_TIMING3 = 0x2704030d; + REG_DDRC_TIMING4 = 0xb7a0251; + REG_DDRC_TIMING5 = 0xff090200; + REG_DDRC_TIMING6 = 0xa0a0202; +#if DDR_MEMORYSIZE == 64 + REG_DDRC_MMAP0 = 0x20fc; + REG_DDRC_MMAP1 = 0x2400; +#elif DDR_MEMORYSIZE == 32 + REG_DDRC_MMAP0 = 0x20fe; + REG_DDRC_MMAP1 = 0x2200; +#else +# error "Unsupported DDR_MEMORYSIZE" +#endif + REG_DDRC_CTRL = 10; + REG_DDRC_REFCNT = 0x2f0003; + REG_DDRC_CTRL = 0xc91e; + +#if DDR_MEMORYSIZE == 64 + REG_DDRC_REMAP1 = 0x03020c0b; + REG_DDRC_REMAP2 = 0x07060504; + REG_DDRC_REMAP3 = 0x000a0908; + REG_DDRC_REMAP4 = 0x0f0e0d01; + REG_DDRC_REMAP5 = 0x13121110; +#elif DDR_MEMORYSIZE == 32 + REG_DDRC_REMAP1 = 0x03020b0a; + REG_DDRC_REMAP2 = 0x07060504; + REG_DDRC_REMAP3 = 0x01000908; + REG_DDRC_REMAP4 = 0x0f0e0d0c; + REG_DDRC_REMAP5 = 0x13121110; +#else +# error "Unsupported DDR_MEMORYSIZE" +#endif + + REG_DDRC_STATUS &= ~0x40; + +#if DDR_USE_AUTOSR +#if DDR_NEED_BYPASS + jz_writef(CPM_DDRCDR, GATE_EN(1)); + REG_DDRC_APB_CLKSTP_CFG = 0x9000000f; +#else + REG_DDRC_DLP = 0; +#endif +#endif + + REG_DDRC_AUTOSR_EN = DDR_USE_AUTOSR; +} + +void main(void) +{ + /* from original firmware SPL */ + REG_CPM_PSWC0ST = 0x00; + REG_CPM_PSWC1ST = 0x10; + REG_CPM_PSWC2ST = 0x18; + REG_CPM_PSWC3ST = 0x08; + + /* enable MPLL */ +#if X1000_EXCLK_FREQ == 24000000 + /* 24 * (24+1) = 600 MHz */ + jz_writef(CPM_MPCR, ENABLE(1), BS(1), PLLN(0), PLLM(24), PLLOD(0)); +#elif X1000_EXCLK_FREQ == 26000000 + /* 26 * (22+1) = 598 MHz */ + jz_writef(CPM_MPCR, ENABLE(1), BS(1), PLLN(0), PLLM(22), PLLOD(0)); +#else +# error "unknown EXCLK frequency" +#endif + while(jz_readf(CPM_MPCR, ON) == 0); + + /* set DDR clock to MPLL/3 = 200 MHz */ + jz_writef(CPM_CLKGR, DDR(0)); + clk_set_ddr(X1000_CLK_MPLL, 3); + + /* start OST so we can use mdelay/udelay */ + jz_writef(CPM_CLKGR, OST(0)); + jz_writef(OST_CTRL, PRESCALE2_V(BY_4)); + jz_writef(OST_CLEAR, OST2(1)); + jz_write(OST_2CNTH, 0); + jz_write(OST_2CNTL, 0); + jz_setf(OST_ENABLE, OST2); + + /* init DDR memory */ + ddr_init(); + + /* jump to the target's main routine */ + spl_main(); +} diff --git a/firmware/SOURCES b/firmware/SOURCES index 236933bdb7..3a42381003 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -398,6 +398,8 @@ drivers/rtc/rtc_tcc77x.c drivers/rtc/rtc_jz4740.c #elif (CONFIG_RTC == RTC_JZ4760) drivers/rtc/rtc_jz4760.c +#elif (CONFIG_RTC == RTC_X1000) +drivers/rtc/rtc_x1000.c #elif (CONFIG_RTC == RTC_S35390A) drivers/rtc/rtc_s35390a.c #elif (CONFIG_RTC == RTC_S35380A) @@ -488,6 +490,8 @@ drivers/audio/as3514.c drivers/audio/tlv320.c #elif defined(HAVE_AK4537) drivers/audio/ak4537.c +#elif defined(HAVE_AK4376) +drivers/audio/ak4376.c #elif defined(HAVE_UDA1341) drivers/audio/uda1341.c #elif defined(HAVE_CS42L55) @@ -1721,6 +1725,30 @@ target/mips/ingenic_jz47xx/pcm-jz4760.c drivers/nand_id.c #endif /* CONFIG_CPU == JZ4760B */ +#if CONFIG_CPU == X1000 +target/mips/ingenic_x1000/crt0.S +target/mips/ingenic_x1000/aic-x1000.c +target/mips/ingenic_x1000/clk-x1000.c +target/mips/ingenic_x1000/debug-x1000.c +target/mips/ingenic_x1000/dma-x1000.c +target/mips/ingenic_x1000/gpio-x1000.c +target/mips/ingenic_x1000/i2c-x1000.c +target/mips/ingenic_x1000/kernel-x1000.c +target/mips/ingenic_x1000/lcd-x1000.c +target/mips/ingenic_x1000/nand-x1000.c +target/mips/ingenic_x1000/pcm-x1000.c +target/mips/ingenic_x1000/pwm-x1000.c +target/mips/ingenic_x1000/sfc-x1000.c +target/mips/ingenic_x1000/system-x1000.c +target/mips/ingenic_x1000/timer-x1000.c +#if (CONFIG_STORAGE & (STORAGE_SD|STORAGE_MMC|STORAGE_ATA)) +target/mips/ingenic_x1000/msc-x1000.c +#endif +#if (CONFIG_STORAGE & STORAGE_SD) +target/mips/ingenic_x1000/sd-x1000.c +#endif +#endif /* CONFIG_CPU == X1000 */ + #if defined(ONDA_VX747) || defined(ONDA_VX747P) || defined(ONDA_VX777) target/mips/ingenic_jz47xx/onda_vx747/backlight-onda_vx7X7.c target/mips/ingenic_jz47xx/onda_vx747/lcd-onda_vx747.c @@ -1744,6 +1772,16 @@ target/mips/ingenic_jz47xx/xduoo_x3/power-xduoo_x3.c target/mips/ingenic_jz47xx/xduoo_x3/sadc-xduoo_x3.c #endif /* XDUOO_X3 */ +#if defined(FIIO_M3K) +target/mips/ingenic_x1000/fiiom3k/audiohw-fiiom3k.c +target/mips/ingenic_x1000/fiiom3k/backlight-fiiom3k.c +target/mips/ingenic_x1000/fiiom3k/button-fiiom3k.c +target/mips/ingenic_x1000/fiiom3k/installer-fiiom3k.c +target/mips/ingenic_x1000/fiiom3k/lcd-fiiom3k.c +target/mips/ingenic_x1000/fiiom3k/nand-fiiom3k.c +target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c +#endif /* FIIO_M3K */ + #if defined(LYRE_PROTO1) target/arm/at91sam/lyre_proto1/adc-lyre_proto1.c target/arm/at91sam/lyre_proto1/backlight-lyre_proto1.c @@ -1969,6 +2007,10 @@ drivers/touchpad.c drivers/i2c-async.c #endif +#ifdef HAVE_AXP173 +drivers/axp173.c +#endif + /* firmware/kernel section */ #ifdef HAVE_CORELOCK_OBJECT kernel/corelock.c diff --git a/firmware/drivers/audio/ak4376.c b/firmware/drivers/audio/ak4376.c new file mode 100644 index 0000000000..494bbabfa4 --- /dev/null +++ b/firmware/drivers/audio/ak4376.c @@ -0,0 +1,274 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 "audiohw.h" +#include "sound.h" +#include "panic.h" +#include "pcm_sampr.h" +#include "pcm_sw_volume.h" +#include "system.h" +#include "i2c-async.h" + +#ifndef HAVE_SW_VOLUME_CONTROL +# error "AK4376 requires HAVE_SW_VOLUME_CONTROL!" +#endif + +/* NOTE: At present, only the FiiO M3K uses this driver so the handling of + * the clock / audio interface is limited to I2S slave, 16-bit samples, with + * DAC master clock provided directly on the MCLK input pin, fitting the + * clock setup of the M3K. + * + * Feel free to expand upon this if another target ever needs this driver. + */ + +/* Converts HW_FREQ_XX constants to register values */ +static const int ak4376_fsel_to_hw[] = { + HW_HAVE_192_(AK4376_FS_192,) + HW_HAVE_176_(AK4376_FS_176,) + HW_HAVE_96_(AK4376_FS_96,) + HW_HAVE_88_(AK4376_FS_88,) + HW_HAVE_64_(AK4376_FS_64,) + HW_HAVE_48_(AK4376_FS_48,) + HW_HAVE_44_(AK4376_FS_44,) + HW_HAVE_32_(AK4376_FS_32,) + HW_HAVE_24_(AK4376_FS_24,) + HW_HAVE_22_(AK4376_FS_22,) + HW_HAVE_16_(AK4376_FS_16,) + HW_HAVE_12_(AK4376_FS_12,) + HW_HAVE_11_(AK4376_FS_11,) + HW_HAVE_8_(AK4376_FS_8,) +}; + +static struct ak4376 { + int fsel; + int low_mode; + int regs[AK4376_NUM_REGS]; +} ak4376; + +void ak4376_init(void) +{ + /* Initialize DAC state */ + ak4376.fsel = HW_FREQ_48; + ak4376.low_mode = 0; + for(int i = 0; i < AK4376_NUM_REGS; ++i) + ak4376.regs[i] = -1; + + /* Initial reset after power-on */ + ak4376_set_pdn_pin(0); + mdelay(1); + ak4376_set_pdn_pin(1); + mdelay(1); + + static const int init_config[] = { + /* Ensure HPRHZ, HPLHZ are 0 */ + AK4376_REG_OUTPUT_MODE, 0x00, + /* Mute all volume controls */ + AK4376_REG_MIXER, 0x00, + AK4376_REG_LCH_VOLUME, 0x80, + AK4376_REG_RCH_VOLUME, 0x00, + AK4376_REG_AMP_VOLUME, 0x00, + /* Clock source = MCLK, divider = 1 */ + AK4376_REG_DAC_CLK_SRC, 0x00, + AK4376_REG_DAC_CLK_DIV, 0x00, + /* I2S slave mode, 16-bit samples */ + AK4376_REG_AUDIO_IF_FMT, 0x03, + /* Recommended by datasheet */ + AK4376_REG_ADJUST1, 0x20, + AK4376_REG_ADJUST2, 0x05, + /* Power controls */ + AK4376_REG_PWR2, 0x33, + AK4376_REG_PWR3, 0x01, + AK4376_REG_PWR4, 0x03, + }; + + /* Write initial configuration prior to power-up */ + for(size_t i = 0; i < ARRAYLEN(init_config); i += 2) + ak4376_write(init_config[i], init_config[i+1]); + + /* Initial frequency setting, also handles DAC/amp power-up */ + audiohw_set_frequency(HW_FREQ_48); +} + +void ak4376_close(void) +{ + /* Shut off power */ + ak4376_write(AK4376_REG_PWR3, 0x00); + ak4376_write(AK4376_REG_PWR4, 0x00); + ak4376_write(AK4376_REG_PWR2, 0x00); + + /* PDN pin low */ + ak4376_set_pdn_pin(0); +} + +void ak4376_write(int reg, int value) +{ + /* Ensure value is sensible and differs from the last set value */ + if((value & 0xff) == value && ak4376.regs[reg] != value) { + int r = i2c_reg_write1(AK4376_BUS, AK4376_ADDR, reg, value); + if(r == I2C_STATUS_OK) + ak4376.regs[reg] = value; + else + ak4376.regs[reg] = -1; + } +} + +int ak4376_read(int reg) +{ + /* Only read from I2C if we don't already know the value */ + if(ak4376.regs[reg] < 0) + ak4376.regs[reg] = i2c_reg_read1(AK4376_BUS, AK4376_ADDR, reg); + + return ak4376.regs[reg]; +} + +static int round_step_up(int x, int step) +{ + int rem = x % step; + if(rem > 0) + rem -= step; + return x - rem; +} + +static void calc_volumes(int vol, int* mix, int* dig, int* sw) +{ + /* Mixer can divide by 2, which gives an extra -6 dB adjustment */ + if(vol < AK4376_DIG_VOLUME_MIN) { + *mix |= AK4376_MIX_HALF; + vol += 60; + } + + *dig = round_step_up(vol, AK4376_DIG_VOLUME_STEP); + *dig = MIN(*dig, AK4376_DIG_VOLUME_MAX); + *dig = MAX(*dig, AK4376_DIG_VOLUME_MIN); + vol -= *dig; + + /* Seems that this is the allowable range for software volume */ + *sw = MIN(vol, 60); + *sw = MAX(*sw, -730); + vol -= *sw; +} + +static int dig_vol_to_hw(int vol) +{ + if(vol < AK4376_DIG_VOLUME_MIN) return 0; + if(vol > AK4376_DIG_VOLUME_MAX) return 31; + return (vol - AK4376_DIG_VOLUME_MIN) / AK4376_DIG_VOLUME_STEP + 1; +} + +static int amp_vol_to_hw(int vol) +{ + if(vol < AK4376_AMP_VOLUME_MIN) return 0; + if(vol > AK4376_AMP_VOLUME_MAX) return 14; + return (vol - AK4376_AMP_VOLUME_MIN) / AK4376_AMP_VOLUME_STEP + 1; +} + +void audiohw_set_volume(int vol_l, int vol_r) +{ + int amp; + int mix_l = AK4376_MIX_LCH, dig_l, sw_l; + int mix_r = AK4376_MIX_RCH, dig_r, sw_r; + + if(vol_l <= AK4376_MIN_VOLUME && vol_r <= AK4376_MIN_VOLUME) { + /* Special case for full mute */ + amp = AK4376_AMP_VOLUME_MUTE; + dig_l = dig_r = AK4376_DIG_VOLUME_MUTE; + sw_l = sw_r = PCM_MUTE_LEVEL; + } else { + /* Amp is a mono control -- calculate based on the loudest channel. + * The quieter channel then gets reduced more by digital controls. */ + amp = round_step_up(MAX(vol_l, vol_r), AK4376_AMP_VOLUME_STEP); + amp = MIN(amp, AK4376_AMP_VOLUME_MAX); + amp = MAX(amp, AK4376_AMP_VOLUME_MIN); + + /* Other controls are stereo */ + calc_volumes(vol_l - amp, &mix_l, &dig_l, &sw_l); + calc_volumes(vol_r - amp, &mix_r, &dig_r, &sw_r); + } + + ak4376_write(AK4376_REG_MIXER, (mix_l & 0xf) | ((mix_r & 0xf) << 4)); + ak4376_write(AK4376_REG_LCH_VOLUME, dig_vol_to_hw(dig_l) | (1 << 7)); + ak4376_write(AK4376_REG_RCH_VOLUME, dig_vol_to_hw(dig_r)); + ak4376_write(AK4376_REG_AMP_VOLUME, amp_vol_to_hw(amp)); + pcm_set_master_volume(sw_l, sw_r); +} + +void audiohw_set_filter_roll_off(int val) +{ + int reg = ak4376_read(AK4376_REG_FILTER); + reg &= ~0xc0; + reg |= (val & 3) << 6; + ak4376_write(AK4376_REG_FILTER, reg); +} + +void audiohw_set_frequency(int fsel) +{ + /* Determine master clock multiplier */ + int mult = ak4376_set_mclk_freq(fsel, false); + + /* Calculate clock mode for frequency. Multipliers of 32/64 are only + * for rates >= 256 KHz which are not supported by Rockbox, so they + * are commented out -- but they're in the correct place. */ + int clock_mode = ak4376_fsel_to_hw[fsel]; + switch(mult) { + /* case 32: */ + case 256: + break; + /* case 64: */ + case 512: + clock_mode |= 0x20; + break; + case 1024: + clock_mode |= 0x40; + break; + case 128: + clock_mode |= 0x60; + break; + default: + panicf("ak4376: bad master clock multiple %d", mult); + return; + } + + /* Handle the DSMLP bit in the MODE_CTRL register */ + int mode_ctrl = 0x00; + if(ak4376.low_mode || hw_freq_sampr[fsel] <= SAMPR_12) + mode_ctrl |= 0x40; + + /* Program the new settings */ + ak4376_write(AK4376_REG_CLOCK_MODE, clock_mode); + ak4376_write(AK4376_REG_MODE_CTRL, mode_ctrl); + ak4376_write(AK4376_REG_PWR3, ak4376.low_mode ? 0x11 : 0x01); + + /* Enable the master clock */ + ak4376_set_mclk_freq(fsel, true); + + /* Remember the frequency */ + ak4376.fsel = fsel; +} + +void audiohw_set_power_mode(int mode) +{ + /* This is handled via audiohw_set_frequency() since changing LPMODE + * bit requires power-down/power-up & changing other bits as well */ + if(ak4376.low_mode != mode) { + ak4376.low_mode = mode; + audiohw_set_frequency(ak4376.fsel); + } +} diff --git a/firmware/drivers/axp173.c b/firmware/drivers/axp173.c new file mode 100644 index 0000000000..22417650fc --- /dev/null +++ b/firmware/drivers/axp173.c @@ -0,0 +1,419 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 "axp173.h" +#include "power.h" +#include "i2c-async.h" + +/* Headers for the debug menu */ +#ifndef BOOTLOADER +# include "action.h" +# include "list.h" +# include <stdio.h> +#endif + +static const struct axp173_adc_info { + uint8_t reg; + uint8_t en_reg; + uint8_t en_bit; +} axp173_adc_info[NUM_ADC_CHANNELS] = { + {0x56, 0x82, 5}, /* ACIN_VOLTAGE */ + {0x58, 0x82, 4}, /* ACIN_CURRENT */ + {0x5a, 0x82, 3}, /* VBUS_VOLTAGE */ + {0x5c, 0x82, 2}, /* VBUS_CURRENT */ + {0x5e, 0x83, 7}, /* INTERNAL_TEMP */ + {0x62, 0x82, 1}, /* TS_INPUT */ + {0x78, 0x82, 7}, /* BATTERY_VOLTAGE */ + {0x7a, 0x82, 6}, /* CHARGE_CURRENT */ + {0x7c, 0x82, 6}, /* DISCHARGE_CURRENT */ + {0x7e, 0x82, 1}, /* APS_VOLTAGE */ + {0x70, 0xff, 0}, /* BATTERY_POWER */ +}; + +static struct axp173 { + int adc_enable; +} axp173; + +static void axp173_init_enabled_adcs(void) +{ + axp173.adc_enable = 0; + + /* Read enabled ADCs from the hardware */ + uint8_t regs[2]; + int rc = i2c_reg_read(AXP173_BUS, AXP173_ADDR, 0x82, 2, ®s[0]); + if(rc != I2C_STATUS_OK) + return; + + /* Parse registers to set ADC enable bits */ + const struct axp173_adc_info* info = axp173_adc_info; + for(int i = 0; i < NUM_ADC_CHANNELS; ++i) { + if(info[i].en_reg == 0xff) + continue; + + if(regs[info[i].en_reg - 0x82] & info[i].en_bit) + axp173.adc_enable |= 1 << i; + } + + /* Handle battery power ADC */ + if((axp173.adc_enable & (1 << ADC_BATTERY_VOLTAGE)) && + (axp173.adc_enable & (1 << ADC_DISCHARGE_CURRENT))) { + axp173.adc_enable |= (1 << ADC_BATTERY_POWER); + } +} + +void axp173_init(void) +{ + axp173_init_enabled_adcs(); + + /* We need discharge current ADC to reliably poll for a full battery */ + int bits = axp173.adc_enable; + bits |= (1 << ADC_DISCHARGE_CURRENT); + axp173_adc_set_enabled(bits); +} + +/* TODO: this can STILL indicate some false positives! */ +int axp173_battery_status(void) +{ + int r = i2c_reg_read1(AXP173_BUS, AXP173_ADDR, 0x00); + if(r >= 0) { + /* Charging bit indicates we're currently charging */ + if((r & 0x04) != 0) + return AXP173_BATT_CHARGING; + + /* Not plugged in means we're discharging */ + if((r & 0xf0) == 0) + return AXP173_BATT_DISCHARGING; + } else { + /* Report discharging if we can't find out power status */ + return AXP173_BATT_DISCHARGING; + } + + /* If the battery is full and not in use, the charging bit will be 0, + * there will be an external power source, AND the discharge current + * will be zero. Seems to rule out all false positives. */ + int d = axp173_adc_read_raw(ADC_DISCHARGE_CURRENT); + if(d == 0) + return AXP173_BATT_FULL; + + return AXP173_BATT_DISCHARGING; +} + +int axp173_input_status(void) +{ +#ifdef HAVE_BATTERY_SWITCH + int input_status = 0; +#else + int input_status = AXP173_INPUT_BATTERY; +#endif + + int r = i2c_reg_read1(AXP173_BUS, AXP173_ADDR, 0x00); + if(r < 0) + return input_status; + + /* Check for AC input */ + if(r & 0x80) + input_status |= AXP173_INPUT_AC; + + /* Only report USB if ACIN and VBUS are not shorted */ + if((r & 0x20) != 0 && (r & 0x02) == 0) + input_status |= AXP173_INPUT_USB; + +#ifdef HAVE_BATTERY_SWITCH + /* Check for battery presence if target defines it as removable */ + r = i2c_reg_read1(AXP173_BUS, AXP173_ADDR, 0x01); + if(r >= 0 && (r & 0x20) != 0) + input_status |= AXP173_INPUT_BATTERY; +#endif + + return input_status; +} + +int axp173_adc_read(int adc) +{ + int value = axp173_adc_read_raw(adc); + if(value == INT_MIN) + return INT_MIN; + + return axp173_adc_conv_raw(adc, value); +} + +int axp173_adc_read_raw(int adc) +{ + /* Don't give a reading if the ADC is not enabled */ + if((axp173.adc_enable & (1 << adc)) == 0) + return INT_MIN; + + /* Read the ADC */ + uint8_t buf[3]; + int count = (adc == ADC_BATTERY_POWER) ? 3 : 2; + uint8_t reg = axp173_adc_info[adc].reg; + int rc = i2c_reg_read(AXP173_BUS, AXP173_ADDR, reg, count, &buf[0]); + if(rc != I2C_STATUS_OK) + return INT_MIN; + + /* Parse the value */ + if(adc == ADC_BATTERY_POWER) + return (buf[0] << 16) | (buf[1] << 8) | buf[2]; + else if(adc == ADC_CHARGE_CURRENT || adc == ADC_DISCHARGE_CURRENT) + return (buf[0] << 5) | (buf[1] & 0x1f); + else + return (buf[0] << 4) | (buf[1] & 0xf); +} + +int axp173_adc_conv_raw(int adc, int value) +{ + switch(adc) { + case ADC_ACIN_VOLTAGE: + case ADC_VBUS_VOLTAGE: + /* 0 mV ... 6.9615 mV, step 1.7 mV */ + return value * 17 / 10; + case ADC_ACIN_CURRENT: + /* 0 mA ... 2.5594 A, step 0.625 mA */ + return value * 5 / 8; + case ADC_VBUS_CURRENT: + /* 0 mA ... 1.5356 A, step 0.375 mA */ + return value * 3 / 8; + case ADC_INTERNAL_TEMP: + /* -144.7 C ... 264.8 C, step 0.1 C */ + return value - 1447; + case ADC_TS_INPUT: + /* 0 mV ... 3.276 V, step 0.8 mV */ + return value * 4 / 5; + case ADC_BATTERY_VOLTAGE: + /* 0 mV ... 4.5045 V, step 1.1 mV */ + return value * 11 / 10; + case ADC_CHARGE_CURRENT: + case ADC_DISCHARGE_CURRENT: + /* 0 mA to 4.095 A, step 0.5 mA */ + return value / 2; + case ADC_APS_VOLTAGE: + /* 0 mV to 5.733 V, step 1.4 mV */ + return value * 7 / 5; + case ADC_BATTERY_POWER: + /* 0 uW to 23.6404 W, step 0.55 uW */ + return value * 11 / 20; + default: + /* Shouldn't happen */ + return INT_MIN; + } +} + +int axp173_adc_get_enabled(void) +{ + return axp173.adc_enable; +} + +void axp173_adc_set_enabled(int adc_bits) +{ + /* Ignore no-op */ + if(adc_bits == axp173.adc_enable) + return; + + /* Compute the new register values */ + const struct axp173_adc_info* info = axp173_adc_info; + uint8_t regs[2] = {0, 0}; + for(int i = 0; i < NUM_ADC_CHANNELS; ++i) { + if(info[i].en_reg == 0xff) + continue; + + if(adc_bits & (1 << i)) + regs[info[i].en_reg - 0x82] |= 1 << info[i].en_bit; + } + + /* These ADCs share an enable bit */ + if(adc_bits & ((1 << ADC_CHARGE_CURRENT)|(1 << ADC_DISCHARGE_CURRENT))) { + adc_bits |= (1 << ADC_CHARGE_CURRENT); + adc_bits |= (1 << ADC_DISCHARGE_CURRENT); + } + + /* Enable required bits for battery power ADC */ + if(adc_bits & (1 << ADC_BATTERY_POWER)) { + regs[0] |= 1 << info[ADC_DISCHARGE_CURRENT].en_bit; + regs[0] |= 1 << info[ADC_BATTERY_VOLTAGE].en_bit; + } + + /* Update the configuration */ + i2c_reg_write(AXP173_BUS, AXP173_ADDR, 0x82, 2, ®s[0]); + axp173.adc_enable = adc_bits; +} + +int axp173_adc_get_rate(void) +{ + int r = i2c_reg_read1(AXP173_BUS, AXP173_ADDR, 0x84); + if(r < 0) + return AXP173_ADC_RATE_100HZ; /* an arbitrary value */ + + return (r >> 6) & 3; +} + +void axp173_adc_set_rate(int rate) +{ + i2c_reg_modify1(AXP173_BUS, AXP173_ADDR, 0x84, + 0xc0, (rate & 3) << 6, NULL); +} + +static uint32_t axp173_cc_parse(const uint8_t* buf) +{ + return ((uint32_t)buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; +} + +void axp173_cc_read(uint32_t* charge, uint32_t* discharge) +{ + uint8_t buf[8]; + int rc = i2c_reg_read(AXP173_BUS, AXP173_ADDR, 0xb0, 8, &buf[0]); + if(rc != I2C_STATUS_OK) { + if(charge) + *charge = 0; + if(discharge) + *discharge = 0; + return; + } + + if(charge) + *charge = axp173_cc_parse(&buf[0]); + if(discharge) + *discharge = axp173_cc_parse(&buf[4]); +} + +void axp173_cc_clear(void) +{ + i2c_reg_setbit1(AXP173_BUS, AXP173_ADDR, 0xb8, 5, 1, NULL); +} + +void axp173_cc_enable(bool en) +{ + i2c_reg_setbit1(AXP173_BUS, AXP173_ADDR, 0xb8, 7, en ? 1 : 0, NULL); +} + +#ifndef BOOTLOADER +#define AXP173_DEBUG_BATTERY_STATUS 0 +#define AXP173_DEBUG_INPUT_STATUS 1 +#define AXP173_DEBUG_ADC_RATE 2 +#define AXP173_DEBUG_FIRST_ADC 3 +#define AXP173_DEBUG_ENTRIES (AXP173_DEBUG_FIRST_ADC + NUM_ADC_CHANNELS) + +static int axp173_debug_menu_cb(int action, struct gui_synclist* lists) +{ + (void)lists; + + if(action == ACTION_NONE) + action = ACTION_REDRAW; + + return action; +} + +static const char* axp173_debug_menu_get_name(int item, void* data, + char* buf, size_t buflen) +{ + (void)data; + + static const char* const adc_names[] = { + "V_acin", "I_acin", "V_vbus", "I_vbus", "T_int", + "V_ts", "V_batt", "I_chrg", "I_dchg", "V_aps", "P_batt" + }; + + static const char* const adc_units[] = { + "mV", "mA", "mV", "mA", "C", "mV", "mV", "mA", "mA", "mV", "uW", + }; + + int adc = item - AXP173_DEBUG_FIRST_ADC; + if(item >= AXP173_DEBUG_FIRST_ADC && adc < NUM_ADC_CHANNELS) { + int raw_value = axp173_adc_read_raw(adc); + if(raw_value == INT_MIN) { + snprintf(buf, buflen, "%s: [Disabled]", adc_names[adc]); + return buf; + } + + int value = axp173_adc_conv_raw(adc, raw_value); + if(adc == ADC_INTERNAL_TEMP) { + snprintf(buf, buflen, "%s: %d.%d %s", adc_names[adc], + value/10, value%10, adc_units[adc]); + } else { + snprintf(buf, buflen, "%s: %d %s", adc_names[adc], + value, adc_units[adc]); + } + + return buf; + } + + switch(item) { + case AXP173_DEBUG_BATTERY_STATUS: { + switch(axp173_battery_status()) { + case AXP173_BATT_FULL: + return "Battery: Full"; + case AXP173_BATT_CHARGING: + return "Battery: Charging"; + case AXP173_BATT_DISCHARGING: + return "Battery: Discharging"; + default: + return "Battery: Unknown"; + } + } break; + + case AXP173_DEBUG_INPUT_STATUS: { + int s = axp173_input_status(); + const char* ac = (s & AXP173_INPUT_AC) ? " AC" : ""; + const char* usb = (s & AXP173_INPUT_USB) ? " USB" : ""; + const char* batt = (s & AXP173_INPUT_BATTERY) ? " Battery" : ""; + snprintf(buf, buflen, "Inputs:%s%s%s", ac, usb, batt); + return buf; + } break; + + case AXP173_DEBUG_ADC_RATE: { + int rate = 25 << axp173_adc_get_rate(); + snprintf(buf, buflen, "ADC sample rate: %d Hz", rate); + return buf; + } break; + + default: + return "---"; + } +} + +bool axp173_debug_menu(void) +{ + struct simplelist_info info; + simplelist_info_init(&info, "AXP173 debug", AXP173_DEBUG_ENTRIES, NULL); + info.action_callback = axp173_debug_menu_cb; + info.get_name = axp173_debug_menu_get_name; + return simplelist_show_list(&info); +} +#endif /* !BOOTLOADER */ + +/* This is basically the only valid implementation, so define it here */ +unsigned int power_input_status(void) +{ + unsigned int state = 0; + int input_status = axp173_input_status(); + + if(input_status & AXP173_INPUT_AC) + state |= POWER_INPUT_MAIN_CHARGER; + + if(input_status & AXP173_INPUT_USB) + state |= POWER_INPUT_USB_CHARGER; + +#ifdef HAVE_BATTERY_SWITCH + if(input_status & AXP173_INPUT_BATTERY) + state |= POWER_INPUT_BATTERY; +#endif + + return state; +} diff --git a/firmware/drivers/rtc/rtc_x1000.c b/firmware/drivers/rtc/rtc_x1000.c new file mode 100644 index 0000000000..1d3a5484e9 --- /dev/null +++ b/firmware/drivers/rtc/rtc_x1000.c @@ -0,0 +1,104 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * Based mainly on rtc_jz4760.c, + * Copyright (C) 2016 by Roman Stolyarov + * + * 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 "rtc.h" +#include "x1000/rtc.h" +#include <stdint.h> + +/* 4 byte magic number 'RTCV' */ +#define RTCV 0x52544356 + +/* expected RTC clock frequency */ +#define NC1HZ_EXPECTED (32768 - 1) + +static void rtc_write_reg(uint32_t addr, uint32_t value) +{ + while(jz_readf(RTC_CR, WRDY) == 0); + REG_RTC_WENR = 0xa55a; + while(jz_readf(RTC_WENR, WEN) == 0); + while(jz_readf(RTC_CR, WRDY) == 0); + (*(volatile uint32_t*)addr) = value; + while(jz_readf(RTC_CR, WRDY) == 0); +} + +void rtc_init(void) +{ + /* Check if we totally lost power and need to reset the RTC */ + if(REG_RTC_HSPR != RTCV || jz_readf(RTC_GR, NC1HZ) != NC1HZ_EXPECTED) { + rtc_write_reg(JA_RTC_GR, NC1HZ_EXPECTED); + rtc_write_reg(JA_RTC_HWFCR, 3200); + rtc_write_reg(JA_RTC_HRCR, 2048); + rtc_write_reg(JA_RTC_SR, 1546300800); /* 01/01/2019 */ + rtc_write_reg(JA_RTC_CR, 1); + rtc_write_reg(JA_RTC_HSPR, RTCV); + } + + rtc_write_reg(JA_RTC_HWRSR, 0); +} + +int rtc_read_datetime(struct tm* tm) +{ + time_t time = REG_RTC_SR; + gmtime_r(&time, tm); + return 1; +} + +int rtc_write_datetime(const struct tm* tm) +{ + time_t time = mktime((struct tm*)tm); + rtc_write_reg(JA_RTC_SR, time); + return 1; +} + +#ifdef HAVE_RTC_ALARM +/* TODO: implement the RTC alarm */ + +void rtc_set_alarm(int h, int m) +{ + (void)h; + (void)m; +} + +void rtc_get_alarm(int* h, int* m) +{ + (void)h; + (void)m; +} + +void rtc_enable_alarm(bool enable) +{ + (void)enable; +} + +bool rtc_check_alarm_started(bool release_alarm) +{ + (void)release_alarm; + return false; +} + +bool rtc_check_alarm_flag(void) +{ + return false; +} +#endif diff --git a/firmware/export/ak4376.h b/firmware/export/ak4376.h new file mode 100644 index 0000000000..eb06755e92 --- /dev/null +++ b/firmware/export/ak4376.h @@ -0,0 +1,152 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 __AK4376_H__ +#define __AK4376_H__ + +#define AUDIOHW_CAPS (FILTER_ROLL_OFF_CAP|POWER_MODE_CAP) +#define AUDIOHW_HAVE_SHORT2_ROLL_OFF + +#define AK4376_MIN_VOLUME (-890) +#define AK4376_MAX_VOLUME 150 + +AUDIOHW_SETTING(VOLUME, "dB", 1, 5, AK4376_MIN_VOLUME, AK4376_MAX_VOLUME, -200) +AUDIOHW_SETTING(FILTER_ROLL_OFF, "", 0, 1, 0, 3, 0) +AUDIOHW_SETTING(POWER_MODE, "", 0, 1, 0, 1, 0) + +/* Register addresses */ +#define AK4376_REG_PWR1 0x00 +#define AK4376_REG_PWR2 0x01 +#define AK4376_REG_PWR3 0x02 +#define AK4376_REG_PWR4 0x03 +#define AK4376_REG_OUTPUT_MODE 0x04 +#define AK4376_REG_CLOCK_MODE 0x05 +#define AK4376_REG_FILTER 0x06 +#define AK4376_REG_MIXER 0x07 +#define AK4376_REG_LCH_VOLUME 0x0b +#define AK4376_REG_RCH_VOLUME 0x0c +#define AK4376_REG_AMP_VOLUME 0x0d +#define AK4376_REG_PLL_CLK_SRC 0x0e +#define AK4376_REG_PLL_REF_DIV1 0x0f +#define AK4376_REG_PLL_REF_DIV2 0x10 +#define AK4376_REG_PLL_FB_DIV1 0x11 +#define AK4376_REG_PLL_FB_DIV2 0x12 +#define AK4376_REG_DAC_CLK_SRC 0x13 +#define AK4376_REG_DAC_CLK_DIV 0x14 +#define AK4376_REG_AUDIO_IF_FMT 0x15 +#define AK4376_REG_CHIP_ID 0x21 +#define AK4376_REG_MODE_CTRL 0x24 +#define AK4376_REG_ADJUST1 0x26 +#define AK4376_REG_ADJUST2 0x2a +#define AK4376_NUM_REGS 0x2b + +/* Mixer controls, simply OR them together. + * LCH = add LCH signal to output + * RCH = add RCH signal to output + * HALF = multiply output by 1/2 + * INVERT = invert the output after everything else + */ +#define AK4376_MIX_MUTE 0 +#define AK4376_MIX_LCH 1 +#define AK4376_MIX_RCH 2 +#define AK4376_MIX_HALF 4 +#define AK4376_MIX_INVERT 8 + +/* Min/max digital volumes in units of dB/10 */ +#define AK4376_DIG_VOLUME_MIN (-120) +#define AK4376_DIG_VOLUME_MAX 30 +#define AK4376_DIG_VOLUME_STEP 5 +#define AK4376_DIG_VOLUME_MUTE (AK4376_DIG_VOLUME_MIN - 1) + +/* Min/max headphone amp volumes in units of dB/10 */ +#define AK4376_AMP_VOLUME_MIN (-200) +#define AK4376_AMP_VOLUME_MAX 60 +#define AK4376_AMP_VOLUME_STEP 20 +#define AK4376_AMP_VOLUME_MUTE (AK4376_AMP_VOLUME_MIN - 1) + +/* Digital filters */ +#define AK4376_FILTER_SHARP 0 +#define AK4376_FILTER_SLOW 1 +#define AK4376_FILTER_SHORT_SHARP 2 +#define AK4376_FILTER_SHORT_SLOW 3 + +/* Frequency selection */ +#define AK4376_FS_8 0 +#define AK4376_FS_11 1 +#define AK4376_FS_12 2 +#define AK4376_FS_16 4 +#define AK4376_FS_22 5 +#define AK4376_FS_24 6 +#define AK4376_FS_32 8 +#define AK4376_FS_44 9 +#define AK4376_FS_48 10 +#define AK4376_FS_64 12 +#define AK4376_FS_88 13 +#define AK4376_FS_96 14 +#define AK4376_FS_176 17 +#define AK4376_FS_192 18 + +/* Functions to power on / off the DAC which should be called from + * the target's audiohw_init() / audiohw_close() implementation. + */ +extern void ak4376_init(void); +extern void ak4376_close(void); + +/* Register read/write. Cached to avoid redundant reads/writes. */ +extern void ak4376_write(int reg, int value); +extern int ak4376_read(int reg); + +/* Target-specific function to set the PDN pin level. */ +extern void ak4376_set_pdn_pin(int level); + +/* Target-specific function to control the external master clock frequency. + * This is called by the ak4376's audiohw implementation when switching to + * or from a frequency that is configured to use this clock source. + * + * - hw_freq is the new sample rate -- one of the HW_FREQ_XX constants. + * - enabled is true if clock should be output, false if not. + * + * The return value is the master clock rate as a multiple of the sampling + * frequency. The allowed multiples depend on the sampling frequency, shown + * in the table below. + * + * +-----------+------------------------+ + * | frequency | master clock rate | + * +-----------+------------------------+ + * | 8 - 24 | 256fs / 512fs / 1024fs | + * | 32 - 48 | 256fs / 512fs | + * | 64 - 96 | 256fs | + * | 128 - 192 | 128fs | + * +-----------+------------------------+ + * + * For example, at 48 KHz you could return either 256 or 512 depending on + * the rate you decided to actually use. + * + * You need to return a valid master multiplier for supported frequencies + * even when enabled = false, since the driver needs to know the multiplier + * _before_ enabling the clock. + * + * For unsupported frequencies you don't need to return a valid master + * multiplier, because the DAC doesn't need the return value in such cases. + */ +extern int ak4376_set_mclk_freq(int hw_freq, bool enabled); + +#endif /* __AK4376_H__ */ diff --git a/firmware/export/audiohw.h b/firmware/export/audiohw.h index d862c977db..ceafc6ebf7 100644 --- a/firmware/export/audiohw.h +++ b/firmware/export/audiohw.h @@ -194,6 +194,8 @@ struct sound_settings_info #include "jz4740-codec.h" #elif defined(HAVE_AK4537) #include "ak4537.h" +#elif defined(HAVE_AK4376) +#include "ak4376.h" #elif defined(HAVE_RK27XX_CODEC) #include "rk27xx_codec.h" #elif defined(HAVE_AIC3X) diff --git a/firmware/export/axp173.h b/firmware/export/axp173.h new file mode 100644 index 0000000000..60519138e1 --- /dev/null +++ b/firmware/export/axp173.h @@ -0,0 +1,94 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 __AXP173_H__ +#define __AXP173_H__ + +#include <stdbool.h> +#include <stdint.h> + +#define ADC_ACIN_VOLTAGE 0 +#define ADC_ACIN_CURRENT 1 +#define ADC_VBUS_VOLTAGE 2 +#define ADC_VBUS_CURRENT 3 +#define ADC_INTERNAL_TEMP 4 +#define ADC_TS_INPUT 5 +#define ADC_BATTERY_VOLTAGE 6 +#define ADC_CHARGE_CURRENT 7 +#define ADC_DISCHARGE_CURRENT 8 +#define ADC_APS_VOLTAGE 9 +#define ADC_BATTERY_POWER 10 +#define NUM_ADC_CHANNELS 11 + +/* ADC sampling rates */ +#define AXP173_ADC_RATE_25HZ 0 +#define AXP173_ADC_RATE_50HZ 1 +#define AXP173_ADC_RATE_100HZ 2 +#define AXP173_ADC_RATE_200HZ 3 + +/* Return values of axp173_battery_status() */ +#define AXP173_BATT_DISCHARGING 0 +#define AXP173_BATT_CHARGING 1 +#define AXP173_BATT_FULL 2 + +/* Bits returned by axp173_input_status() */ +#define AXP173_INPUT_AC (1 << 0) +#define AXP173_INPUT_USB (1 << 1) +#define AXP173_INPUT_BATTERY (1 << 2) +#define AXP173_INPUT_EXTERNAL (AXP173_INPUT_AC|AXP173_INPUT_USB) + +/* Must be called from power_init() to initialize the driver state */ +extern void axp173_init(void); + +/* Basic battery and power supply status */ +extern int axp173_battery_status(void); +extern int axp173_input_status(void); + +/* ADC access -- ADCs which are not enabled will return INT_MIN if read. + * The output of axp173_adc_read() is normalized to appropriate units: + * + * - for voltages, the scale is millivolts + * - for currents, the scale is milliamps + * - for temperatures, the scale is tenths of a degree Celsius + * - for power, the scale is microwatts + * + * See the comment in axp173_adc_conv_raw() for raw value precision/scale. + */ +extern int axp173_adc_read(int adc); +extern int axp173_adc_read_raw(int adc); +extern int axp173_adc_conv_raw(int adc, int value); +extern int axp173_adc_get_enabled(void); +extern void axp173_adc_set_enabled(int adc_bits); +extern int axp173_adc_get_rate(void); +extern void axp173_adc_set_rate(int rate); + +/* - axp173_cc_read() reads the coulomb counters + * - axp173_cc_clear() resets both counters to zero + * - axp173_cc_enable() will stop/start the counters running + */ +extern void axp173_cc_read(uint32_t* charge, uint32_t* discharge); +extern void axp173_cc_clear(void); +extern void axp173_cc_enable(bool en); + +/* Debug menu */ +extern bool axp173_debug_menu(void); + +#endif /* __AXP173_H__ */ diff --git a/firmware/export/config.h b/firmware/export/config.h index e35d407372..db1c589043 100644 --- a/firmware/export/config.h +++ b/firmware/export/config.h @@ -82,6 +82,7 @@ #define AS3525v2 35252 #define IMX233 233 #define RK27XX 2700 +#define X1000 1000 /* platforms * bit fields to allow PLATFORM_HOSTED to be OR'ed e.g. with a @@ -165,6 +166,7 @@ #define XDUOO_X20_PAD 70 #define FIIO_M3K_LINUX_PAD 71 #define EROSQ_PAD 72 +#define FIIO_M3K_PAD 73 /* CONFIG_REMOTE_KEYPAD */ #define H100_REMOTE 1 @@ -281,6 +283,7 @@ #define LCD_IHIFI770 66 /* as used by IHIFI 770 */ #define LCD_IHIFI770C 67 /* as used by IHIFI 770C */ #define LCD_IHIFI800 68 /* as used by IHIFI 800 */ +#define LCD_FIIOM3K 69 /* as used by the FiiO M3K */ /* LCD_PIXELFORMAT */ #define HORIZONTAL_PACKING 1 @@ -320,6 +323,7 @@ Lyre prototype 1 */ #define I2C_S5L8702 16 /* Same as S5L8700, but with two channels */ #define I2C_IMX233 17 #define I2C_RK27XX 18 +#define I2C_X1000 19 /* CONFIG_LED */ #define LED_REAL 1 /* SW controlled LED (Archos recorders, player) */ @@ -356,6 +360,7 @@ Lyre prototype 1 */ #define RTC_IMX233 20 #define RTC_STM41T62 21 /* ST M41T62 */ #define RTC_JZ4760 22 /* Ingenic Jz4760 */ +#define RTC_X1000 23 /* Ingenic X1000 */ /* USB On-the-go */ #define USBOTG_M66591 6591 /* M:Robe 500 */ @@ -605,6 +610,8 @@ Lyre prototype 1 */ #include "config/xduoox20.h" #elif defined(FIIO_M3K_LINUX) #include "config/fiiom3klinux.h" +#elif defined(FIIO_M3K) +#include "config/fiiom3k.h" #elif defined(EROS_Q) #include "config/aigoerosq.h" #else diff --git a/firmware/export/config/fiiom3k.h b/firmware/export/config/fiiom3k.h new file mode 100644 index 0000000000..68186d7aaf --- /dev/null +++ b/firmware/export/config/fiiom3k.h @@ -0,0 +1,116 @@ +/* RoLo-related defines */ +#define MODEL_NAME "FiiO M3K" +#define MODEL_NUMBER 114 +#define BOOTFILE_EXT "m3k" +#define BOOTFILE "rockbox." BOOTFILE_EXT +#define BOOTDIR "/.rockbox" +#define FIRMWARE_OFFSET_FILE_CRC 0 +#define FIRMWARE_OFFSET_FILE_DATA 8 + +/* CPU defines */ +#define CONFIG_CPU X1000 +#define X1000_EXCLK_FREQ 24000000 +#define TIMER_FREQ X1000_EXCLK_FREQ +#define CPU_FREQ 1008000000 +#define CPUFREQ_MAX CPU_FREQ +/* TODO: figure out if this does in fact affect power consumption. */ +#define CPUFREQ_DEFAULT (CPUFREQ_MAX/4) +#define CPUFREQ_NORMAL (CPUFREQ_MAX/4) +#define HAVE_ADJUSTABLE_CPU_FREQ +#define HAVE_GUI_BOOST + +/* Kernel defines */ +#define INCLUDE_TIMEOUT_API +#define HAVE_SEMAPHORE_OBJECTS + +/* Drivers */ +#define HAVE_I2C_ASYNC + +/* Buffer for plugins and codecs. */ +#define PLUGIN_BUFFER_SIZE 0x200000 /* 2 MiB */ +#define CODEC_SIZE 0x100000 /* 1 MiB */ + +/* LCD defines */ +#define CONFIG_LCD LCD_FIIOM3K +#define LCD_WIDTH 240 +#define LCD_HEIGHT 320 +#define LCD_DEPTH 16 +#define LCD_PIXELFORMAT RGB565 +#define LCD_DPI 200 +#define HAVE_LCD_COLOR +#define HAVE_LCD_BITMAP +#define HAVE_LCD_ENABLE +#define LCD_X1000_FASTSLEEP + +/* Backlight defines */ +#define HAVE_BACKLIGHT +#define HAVE_BACKLIGHT_BRIGHTNESS +#define HAVE_BUTTON_LIGHT +#define HAVE_BUTTONLIGHT_BRIGHTNESS +#define MIN_BRIGHTNESS_SETTING 1 +#define MAX_BRIGHTNESS_SETTING 100 +#define BRIGHTNESS_STEP 5 +#define DEFAULT_BRIGHTNESS_SETTING 70 +#define CONFIG_BACKLIGHT_FADING BACKLIGHT_FADING_SW_SETTING + +/* Codec / audio hardware defines */ +#define HW_SAMPR_CAPS SAMPR_CAP_ALL_192 +#define HAVE_AK4376 +#define HAVE_SW_TONE_CONTROLS +#define HAVE_SW_VOLUME_CONTROL + +/* TODO: Need to implement recording */ + +/* Button defines */ +#define CONFIG_KEYPAD FIIO_M3K_PAD +#define HAVE_HEADPHONE_DETECTION +#define HAVE_TOUCHPAD +#define HAVE_TOUCHPAD_SENSITIVITY_SETTING +#define MIN_TOUCHPAD_SENSITIVITY_SETTING (-25) +#define MAX_TOUCHPAD_SENSITIVITY_SETTING (25) +#define DEFAULT_TOUCHPAD_SENSITIVITY_SETTING (0) +#define HAVE_SCROLLWHEEL +/* #define HAVE_WHEEL_ACCELERATION */ +/* #define WHEEL_ACCELERATION */ +/* #define WHEEL_ACCEL_START */ + +/* Storage defines */ +#define CONFIG_STORAGE STORAGE_SD +#define HAVE_HOTSWAP +#define HAVE_HOTSWAP_STORAGE_AS_MAIN +#define HAVE_MULTIDRIVE +#define NUM_DRIVES 1 +#define STORAGE_WANTS_ALIGN +#define STORAGE_NEEDS_BOUNCE_BUFFER + +/* RTC settings */ +#define CONFIG_RTC RTC_X1000 +/* TODO: implement HAVE_RTC_ALARM */ + +/* Power management */ +#define HAVE_AXP173 +#define CONFIG_BATTERY_MEASURE VOLTAGE_MEASURE +#define CONFIG_CHARGING CHARGING_MONITOR +#define HAVE_SW_POWEROFF +#define HAVE_POWEROFF_WHILE_CHARGING + +/* Only one battery type */ +#define BATTERY_CAPACITY_DEFAULT 1100 +#define BATTERY_CAPACITY_MIN 1100 +#define BATTERY_CAPACITY_MAX 1100 +#define BATTERY_CAPACITY_INC 0 +#define BATTERY_TYPES_COUNT 1 + +/* USB is still TODO. */ +#define USB_NONE + +/* Rockbox capabilities */ +#define HAVE_FAT16SUPPORT +#define HAVE_ALBUMART +#define HAVE_BMP_SCALING +#define HAVE_JPEG +#define HAVE_TAGCACHE +#define HAVE_VOLUME_IN_LIST +#define HAVE_QUICKSCREEN +#define HAVE_HOTKEY +#define AB_REPEAT_ENABLE diff --git a/firmware/export/installer.h b/firmware/export/installer.h new file mode 100644 index 0000000000..802798618d --- /dev/null +++ b/firmware/export/installer.h @@ -0,0 +1,31 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 _INSTALLER_H_ +#define _INSTALLER_H_ + +/* Provisional interface for installing/dumping a bootloader */ + +extern int install_bootloader(const char* path); +extern int dump_bootloader(const char* path); +extern const char* installer_strerror(int rc); + +#endif /* _INSTALLER_H_ */ diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c index 3b56242b21..a05e0aeb68 100644 --- a/firmware/powermgmt.c +++ b/firmware/powermgmt.c @@ -131,7 +131,8 @@ static int battery_type = 0; /* Power history: power_history[0] is the newest sample */ unsigned short power_history[POWER_HISTORY_LEN] = {0}; -#if (CONFIG_CPU == JZ4732) || (CONFIG_CPU == JZ4760B) || (CONFIG_PLATFORM & PLATFORM_HOSTED) +#if (CONFIG_CPU == JZ4732) || (CONFIG_CPU == JZ4760B) || \ + (CONFIG_CPU == X1000) || (CONFIG_PLATFORM & PLATFORM_HOSTED) static char power_stack[DEFAULT_STACK_SIZE + POWERMGMT_DEBUG_STACK]; #else static char power_stack[DEFAULT_STACK_SIZE/2 + POWERMGMT_DEBUG_STACK]; diff --git a/firmware/target/mips/ingenic_x1000/aic-x1000.c b/firmware/target/mips/ingenic_x1000/aic-x1000.c new file mode 100644 index 0000000000..a0e509d3b6 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/aic-x1000.c @@ -0,0 +1,119 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 "aic-x1000.h" +#include "gpio-x1000.h" +#include "x1000/aic.h" +#include "x1000/cpm.h" + +/* Given a rational number m/n < 1, find its representation as a continued + * fraction [0; a1, a2, a3, ..., a_k]. At most "cnt" terms are calculated + * and written out to "buf". Returns the number of terms written; the result + * is complete if this value is less than "cnt", and may be incomplete if it + * is equal to "cnt". (Note the leading zero term is not written to "buf".) + */ +static unsigned cf_derive(unsigned m, unsigned n, unsigned* buf, unsigned cnt) +{ + unsigned wrote = 0; + unsigned a = m / n; + while(cnt--) { + unsigned tmp = n; + n = m - n * a; + if(n == 0) + break; + + m = tmp; + a = m / n; + *buf++ = a; + wrote++; + } + + return wrote; +} + +/* Given a finite continued fraction [0; buf[0], buf[1], ..., buf[count-1]], + * calculate the rational number m/n which it represents. Returns m and n. + * If count is zero, then m and n are undefined. + */ +static void cf_expand(const unsigned* buf, unsigned count, + unsigned* m, unsigned* n) +{ + if(count == 0) + return; + + unsigned i = count - 1; + unsigned mx = 1, nx = buf[i]; + while(i--) { + unsigned tmp = nx; + nx = mx + buf[i] * nx; + mx = tmp; + } + + *m = mx; + *n = nx; +} + +int aic_i2s_set_mclk(x1000_clk_t clksrc, unsigned fs, unsigned mult) +{ + /* get the input clock rate */ + uint32_t src_freq = clk_get(clksrc); + + /* reject invalid parameters */ + if(mult % 64 != 0) + return -1; + + if(clksrc == X1000_EXCLK_FREQ) { + if(mult != 0) + return -1; + + jz_writef(AIC_I2SCR, STPBK(1)); + jz_writef(CPM_I2SCDR, CS(0), CE(0)); + REG_AIC_I2SDIV = X1000_EXCLK_FREQ / 64 / fs; + } else { + if(mult == 0) + return -1; + if(fs*mult > src_freq) + return -1; + + /* calculate best rational approximation that fits our constraints */ + unsigned m = 0, n = 0; + unsigned buf[16]; + unsigned cnt = cf_derive(fs*mult, src_freq, &buf[0], 16); + do { + cf_expand(&buf[0], cnt, &m, &n); + cnt -= 1; + } while(cnt > 0 && (m > 512 || n > 8192) && (n >= 2*m)); + + /* wrong values */ + if(cnt == 0 || n == 0 || m == 0) + return -1; + + jz_writef(AIC_I2SCR, STPBK(1)); + jz_writef(CPM_I2SCDR, PCS(clksrc == X1000_CLK_MPLL ? 1 : 0), + CS(1), CE(1), DIV_M(m), DIV_N(n)); + jz_write(CPM_I2SCDR1, REG_CPM_I2SCDR1); + REG_AIC_I2SDIV = (mult / 64) - 1; + } + + jz_writef(AIC_I2SCR, STPBK(0)); + return 0; +} diff --git a/firmware/target/mips/ingenic_x1000/aic-x1000.h b/firmware/target/mips/ingenic_x1000/aic-x1000.h new file mode 100644 index 0000000000..eda0f80f04 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/aic-x1000.h @@ -0,0 +1,46 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 __AIC_X1000_H__ +#define __AIC_X1000_H__ + +#include "clk-x1000.h" +#include <stdbool.h> + +/* Set frequency of I2S master clock supplied by AIC. Has no use if an + * external DAC is supplying the master clock. Must be called with the + * bit clock disabled. + * + * - clksrc can be one of EXCLK, SCLK_A, MPLL. + * - This function does not modify PLL settings. It's the caller's job + * to ensure the PLL is configured and runing. + * - fs is the audio sampling frequency (8 KHz - 192 KHz) + * - mult is multiplied by fs to get the master clock rate. + * - mult must be a multiple of 64 due to AIC bit clock requirements. + * - Note: EXCLK bypasses the decimal divider so it is not very flexible. + * If using EXCLK you must set mult=0. If EXCLK is not a multiple of + * the bit clock (= 64*fs), then the clock rate will be inaccurate. + * + * Returns zero on success and nonzero if the frequency is not achievable. + */ +extern int aic_i2s_set_mclk(x1000_clk_t clksrc, unsigned fs, unsigned mult); + +#endif /* __AIC_X1000_H__ */ diff --git a/firmware/target/mips/ingenic_x1000/app.lds b/firmware/target/mips/ingenic_x1000/app.lds new file mode 100644 index 0000000000..0f6352b8ee --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/app.lds @@ -0,0 +1,119 @@ +#include "config.h" + +OUTPUT_FORMAT("elf32-littlemips") +OUTPUT_ARCH(MIPS) +ENTRY(_start) +STARTUP(target/mips/ingenic_x1000/crt0.o) + +/* Stub area is used for loading new firmware via RoLo */ +#define STUBSIZE 0x4000 +#define SDRAM_ORIG 0x80000000 + +/* IRAM contains stub, DRAM contains main app */ +#define IRAMORIG SDRAM_ORIG +#define IRAMSIZE STUBSIZE +#define DRAMORIG (SDRAM_ORIG + STUBSIZE) +#define DRAMSIZE (MEMORYSIZE * 0x100000 - STUBSIZE) + +/* End of the audio buffer, where the codec buffer starts */ +#define ENDAUDIOADDR (DRAMORIG + DRAMSIZE - PLUGIN_BUFFER_SIZE - CODEC_SIZE) + +/* Where the codec buffer ends, and the plugin buffer starts */ +#define ENDCODECADDR (ENDAUDIOADDR + CODEC_SIZE) + +MEMORY +{ + IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE + DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE +} + +SECTIONS +{ + .text : + { + loadaddress = .; + _loadaddress = .; + *(.init.text); + *(.text*); + } > DRAM + + . = ALIGN(4); + .rodata : + { + *(.rodata*); + } > DRAM + + . = ALIGN(4); + .data : + { + *(.data*); + *(.sdata*); + } > DRAM + + .iram IRAMORIG: AT (_bssbegin) + { + _iramstart = .; + . = 0x000; /* TLB refill */ + KEEP(*(.vectors.1)); + . = 0x100; /* Cache error */ + KEEP(*(.vectors.2)); + . = 0x180; /* General exception */ + KEEP(*(.vectors.3)); + . = 0x200; /* Interrupt */ + KEEP(*(.vectors.4)); + KEEP(*(.vectors)); + + *(.icode); + *(.irodata); + *(.idata); + _iramend = .; + } > IRAM + _iramcopy = LOADADDR(.iram); + + . = ALIGN(4); + .stack (NOLOAD) : + { + *(.stack); + stackbegin = .; + . += 0x1E00; + stackend = .; + _irqstackbegin = .; + . += 0x300; + _irqstackend = .; + } > IRAM + + .bss (NOLOAD) : + { + _bssbegin = .; + *(.sbss*); + *(.bss*); + *(COMMON); + *(.scommon*); + _bssend = .; + _end = .; + } > DRAM + +#ifdef BOOTLOADER + . = ALIGN(4); + loadbuffer = .; + . += 0x100000 * 4; /* Allow 4 MiB for the rockbox binary */ + loadbufferend = .; +#else + + .audiobuf : + { + . = ALIGN(4); /* XXX might need more alignment here */ + audiobuffer = .; + } > DRAM + + audiobufend = ENDAUDIOADDR; + codecbuf = ENDAUDIOADDR; + pluginbuf = ENDCODECADDR; +#endif + + /DISCARD/ : + { + *(.eh_frame); + *(.rel.dyn); + } +} diff --git a/firmware/target/mips/ingenic_x1000/boot.lds b/firmware/target/mips/ingenic_x1000/boot.lds new file mode 100644 index 0000000000..81468a95fc --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/boot.lds @@ -0,0 +1,5 @@ +#ifdef BOOTLOADER_SPL +# include "spl.lds" +#else +# include "app.lds" +#endif diff --git a/firmware/target/mips/ingenic_x1000/clk-x1000.c b/firmware/target/mips/ingenic_x1000/clk-x1000.c new file mode 100644 index 0000000000..390d9722ac --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/clk-x1000.c @@ -0,0 +1,258 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 "clk-x1000.h" +#include "x1000/cpm.h" +#include "x1000/msc.h" +#include "x1000/aic.h" + +static uint32_t pll_get(uint32_t pllreg, uint32_t onbit) +{ + if((pllreg & (1 << onbit)) == 0) + return 0; + + /* Both PLL registers share the same layout of N/M/OD bits. + * The max multiplier is 128 and max EXCLK is 26 MHz, so the + * multiplication should fit within 32 bits without overflow. + */ + uint32_t rate = X1000_EXCLK_FREQ; + rate *= jz_vreadf(pllreg, CPM_APCR, PLLM) + 1; + rate /= jz_vreadf(pllreg, CPM_APCR, PLLN) + 1; + rate >>= jz_vreadf(pllreg, CPM_APCR, PLLOD); + return rate; +} + +static uint32_t sclk_a_get(void) +{ + switch(jz_readf(CPM_CCR, SEL_SRC)) { + case 1: return X1000_EXCLK_FREQ; + case 2: return clk_get(X1000_CLK_APLL); + default: return 0; + } +} + +static uint32_t ccr_get(uint32_t selbit, uint32_t divbit) +{ + uint32_t reg = REG_CPM_CCR; + uint32_t sel = (reg >> selbit) & 0x3; + uint32_t div = (reg >> divbit) & 0xf; + + switch(sel) { + case 1: return clk_get(X1000_CLK_SCLK_A) / (div + 1); + case 2: return clk_get(X1000_CLK_MPLL) / (div + 1); + default: return 0; + } +} + +static uint32_t ddr_get(void) +{ + uint32_t reg = REG_CPM_DDRCDR; + uint32_t div = jz_vreadf(reg, CPM_DDRCDR, CLKDIV); + + switch(jz_vreadf(reg, CPM_DDRCDR, CLKSRC)) { + case 1: return clk_get(X1000_CLK_SCLK_A) / (div + 1); + case 2: return clk_get(X1000_CLK_MPLL) / (div + 1); + default: return 0; + } +} + +static uint32_t lcd_get(void) +{ + if(jz_readf(CPM_CLKGR, LCD)) + return 0; + + uint32_t reg = REG_CPM_LPCDR; + uint32_t rate; + switch(jz_vreadf(reg, CPM_LPCDR, CLKSRC)) { + case 0: rate = clk_get(X1000_CLK_SCLK_A); break; + case 1: rate = clk_get(X1000_CLK_MPLL); break; + default: return 0; + } + + rate /= jz_vreadf(reg, CPM_LPCDR, CLKDIV) + 1; + return rate; +} + +static uint32_t msc_get(int msc) +{ + if((msc == 0 && jz_readf(CPM_CLKGR, MSC0)) || + (msc == 1 && jz_readf(CPM_CLKGR, MSC1))) + return 0; + + uint32_t reg = REG_CPM_MSC0CDR; + uint32_t rate; + switch(jz_vreadf(reg, CPM_MSC0CDR, CLKSRC)) { + case 0: rate = clk_get(X1000_CLK_SCLK_A); break; + case 1: rate = clk_get(X1000_CLK_MPLL); break; + default: return 0; + } + + uint32_t div; + if(msc == 0) + div = jz_readf(CPM_MSC0CDR, CLKDIV); + else + div = jz_readf(CPM_MSC1CDR, CLKDIV); + + rate /= 2 * (div + 1); + rate >>= REG_MSC_CLKRT(msc); + return rate; +} + +static uint32_t i2s_mclk_get(void) +{ + if(jz_readf(CPM_CLKGR, AIC)) + return 0; + + uint32_t reg = REG_CPM_I2SCDR; + unsigned long long rate; + if(jz_vreadf(reg, CPM_I2SCDR, CS) == 0) + rate = X1000_EXCLK_FREQ; + else { + if(jz_vreadf(reg, CPM_I2SCDR, PCS) == 0) + rate = clk_get(X1000_CLK_SCLK_A); + else + rate = clk_get(X1000_CLK_MPLL); + + rate *= jz_vreadf(reg, CPM_I2SCDR, DIV_M); + rate /= jz_vreadf(reg, CPM_I2SCDR, DIV_N); + } + + /* Clamp invalid setting to 32 bits */ + if(rate > 0xffffffffull) + rate = 0xffffffff; + + return rate; +} + +static uint32_t i2s_bclk_get(void) +{ + return i2s_mclk_get() / (REG_AIC_I2SDIV + 1); +} + +static uint32_t sfc_get(void) +{ + if(jz_readf(CPM_CLKGR, SFC)) + return 0; + + uint32_t reg = REG_CPM_SSICDR; + uint32_t rate; + if(jz_vreadf(reg, CPM_SSICDR, SFC_CS) == 0) + rate = clk_get(X1000_CLK_SCLK_A); + else + rate = clk_get(X1000_CLK_MPLL); + + rate /= jz_vreadf(reg, CPM_SSICDR, CLKDIV) + 1; + return rate; +} + +uint32_t clk_get(x1000_clk_t clk) +{ + switch(clk) { + case X1000_CLK_EXCLK: return X1000_EXCLK_FREQ; + case X1000_CLK_APLL: return pll_get(REG_CPM_APCR, BP_CPM_APCR_ON); + case X1000_CLK_MPLL: return pll_get(REG_CPM_MPCR, BP_CPM_MPCR_ON); + case X1000_CLK_SCLK_A: return sclk_a_get(); + case X1000_CLK_CPU: return ccr_get(BP_CPM_CCR_SEL_CPLL, BP_CPM_CCR_CDIV); + case X1000_CLK_L2CACHE: return ccr_get(BP_CPM_CCR_SEL_CPLL, BP_CPM_CCR_L2DIV); + case X1000_CLK_AHB0: return ccr_get(BP_CPM_CCR_SEL_H0PLL, BP_CPM_CCR_H0DIV); + case X1000_CLK_AHB2: return ccr_get(BP_CPM_CCR_SEL_H2PLL, BP_CPM_CCR_H2DIV); + case X1000_CLK_PCLK: return ccr_get(BP_CPM_CCR_SEL_H2PLL, BP_CPM_CCR_PDIV); + case X1000_CLK_DDR: return ddr_get(); + case X1000_CLK_LCD: return lcd_get(); + case X1000_CLK_MSC0: return msc_get(0); + case X1000_CLK_MSC1: return msc_get(1); + case X1000_CLK_I2S_MCLK: return i2s_mclk_get(); + case X1000_CLK_I2S_BCLK: return i2s_bclk_get(); + case X1000_CLK_SFC: return sfc_get(); + default: return 0; + } +} + +const char* clk_get_name(x1000_clk_t clk) +{ + switch(clk) { +#define CASE(x) case X1000_CLK_##x: return #x + CASE(EXCLK); + CASE(APLL); + CASE(MPLL); + CASE(SCLK_A); + CASE(CPU); + CASE(L2CACHE); + CASE(AHB0); + CASE(AHB2); + CASE(PCLK); + CASE(DDR); + CASE(LCD); + CASE(MSC0); + CASE(MSC1); + CASE(I2S_MCLK); + CASE(I2S_BCLK); + CASE(SFC); +#undef CASE + default: + return "NONE"; + } +} + +#define CCR_MUX_BITS jz_orm(CPM_CCR, SEL_SRC, SEL_CPLL, SEL_H0PLL, SEL_H2PLL) +#define CSR_MUX_BITS jz_orm(CPM_CSR, SRC_MUX, CPU_MUX, AHB0_MUX, AHB2_MUX) +#define CSR_DIV_BITS jz_orm(CPM_CSR, H2DIV_BUSY, H0DIV_BUSY, CDIV_BUSY) + +void clk_set_ccr_mux(uint32_t muxbits) +{ + /* Set new mux configuration */ + uint32_t reg = REG_CPM_CCR; + reg &= ~CCR_MUX_BITS; + reg |= muxbits & CCR_MUX_BITS; + REG_CPM_CCR = reg; + + /* Wait for mux change to complete */ + while((REG_CPM_CSR & CSR_MUX_BITS) != CSR_MUX_BITS); +} + +void clk_set_ccr_div(int cpu, int l2, int ahb0, int ahb2, int pclk) +{ + /* Set new divider configuration */ + jz_writef(CPM_CCR, CDIV(cpu - 1), L2DIV(l2 - 1), + H0DIV(ahb0 - 1), H2DIV(ahb2 - 1), PDIV(pclk - 1), + CE_CPU(1), CE_AHB0(1), CE_AHB2(1)); + + /* Wait until divider change completes */ + while(REG_CPM_CSR & CSR_DIV_BITS); + + /* Disable CE bits after change */ + jz_writef(CPM_CCR, CE_CPU(0), CE_AHB0(0), CE_AHB2(0)); +} + +void clk_set_ddr(x1000_clk_t src, uint32_t div) +{ + /* Write new configuration */ + jz_writef(CPM_DDRCDR, CE(1), CLKDIV(div - 1), + CLKSRC(src == X1000_CLK_MPLL ? 2 : 1)); + + /* Wait until mux and divider change are complete */ + while(jz_readf(CPM_CSR, DDR_MUX) == 0); + while(jz_readf(CPM_DDRCDR, BUSY)); + + /* Disable CE bit after change */ + jz_writef(CPM_DDRCDR, CE(0)); +} diff --git a/firmware/target/mips/ingenic_x1000/clk-x1000.h b/firmware/target/mips/ingenic_x1000/clk-x1000.h new file mode 100644 index 0000000000..76413b90d2 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/clk-x1000.h @@ -0,0 +1,82 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 __CLK_X1000_H__ +#define __CLK_X1000_H__ + +#include <stdint.h> +#include "x1000/cpm.h" + +/* Used as arguments to clk_set_ccr_mux() */ +#define CLKMUX_SCLK_A(x) jz_orf(CPM_CCR, SEL_SRC_V(x)) +#define CLKMUX_CPU(x) jz_orf(CPM_CCR, SEL_CPLL_V(x)) +#define CLKMUX_AHB0(x) jz_orf(CPM_CCR, SEL_H0PLL_V(x)) +#define CLKMUX_AHB2(x) jz_orf(CPM_CCR, SEL_H2PLL_V(x)) + +typedef enum x1000_clk_t { + X1000_CLK_EXCLK, + X1000_CLK_APLL, + X1000_CLK_MPLL, + X1000_CLK_SCLK_A, + X1000_CLK_CPU, + X1000_CLK_L2CACHE, + X1000_CLK_AHB0, + X1000_CLK_AHB2, + X1000_CLK_PCLK, + X1000_CLK_DDR, + X1000_CLK_LCD, + X1000_CLK_MSC0, + X1000_CLK_MSC1, + X1000_CLK_I2S_MCLK, + X1000_CLK_I2S_BCLK, + X1000_CLK_SFC, + X1000_CLK_COUNT, +} x1000_clk_t; + +/* Calculate the current frequency of a clock */ +extern uint32_t clk_get(x1000_clk_t clk); + +/* Get the name of a clock for debug purposes */ +extern const char* clk_get_name(x1000_clk_t clk); + +/* Sets system clock multiplexers */ +extern void clk_set_ccr_mux(uint32_t muxbits); + +/* Sets system clock dividers */ +extern void clk_set_ccr_div(int cpu, int l2, int ahb0, int ahb2, int pclk); + +/* Sets DDR clock source and divider */ +extern void clk_set_ddr(x1000_clk_t src, uint32_t div); + +/* Returns the smallest n such that infreq/n <= outfreq */ +inline uint32_t clk_calc_div(uint32_t infreq, uint32_t outfreq) +{ + return (infreq + (outfreq - 1)) / outfreq; +} + +/* Returns the smallest n such that (infreq >> n) <= outfreq */ +inline uint32_t clk_calc_shift(uint32_t infreq, uint32_t outfreq) +{ + uint32_t div = clk_calc_div(infreq, outfreq); + return __builtin_clz(div) ^ 31; +} + +#endif /* __CLK_X1000_H__ */ diff --git a/firmware/target/mips/ingenic_x1000/crt0.S b/firmware/target/mips/ingenic_x1000/crt0.S new file mode 100644 index 0000000000..b717f96692 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/crt0.S @@ -0,0 +1,265 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 "mips.h" + + .text + .extern main + .global _start + + .set push + .set mips32 + .set noreorder + .set noat + + .section .init.text + +_start: + /* Clear data watchpoint */ + mtc0 zero, C0_WATCHLO + mtc0 zero, C0_WATCHHI + + /* Set BEV, ERL, mask interrupts */ + li v0, 0x40fc04 + mtc0 v0, C0_Status + + /* Set Cause_IV to 1 (use special interrupt vector) */ + li v0, M_CauseIV + mtc0 v0, C0_Cause + + /* Set CPU_MODE and BUS_MODE to 1 in CPM_OPCR (Ingenic does this) */ + lui v0, 0xb000 + lw v1, 0x24(v0) + ori v1, v1, 0x22 + sw v1, 0x24(v0) + + /* Enable kseg0 cacheability */ + li v0, 3 + mtc0 v0, C0_Config + nop + + /* According to ingenic: "enable idx-store-data cache insn" */ + li v0, 0x20000000 + mtc0 v0, C0_ErrCtl + + /* Cache init */ + li v0, 0x80000000 + ori v1, v0, 0x4000 + mtc0 zero, C0_TAGLO + mtc0 zero, C0_TAGHI +_cache_loop: + cache ICIndexStTag, 0(v0) + cache DCIndexStTag, 0(v0) + addiu v0, v0, 32 + bne v0, v1, _cache_loop + nop + + /* Invalidate BTB */ + mfc0 v0, C0_Config, 7 + nop + ori v0, v0, 2 + mtc0 v0, C0_Config, 7 + nop + +#ifndef BOOTLOADER_SPL + /* Copy IRAM from BSS to low memory. */ + la t0, _iramcopy + la t1, _iramstart + la t2, _iramend +_iram_loop: + lw t3, 0(t0) + addiu t1, 4 + addiu t0, 4 + bne t1, t2, _iram_loop + sw t3, -4(t1) +#endif + + /* Clear the BSS segment (needed to zero-initialize C static values) */ + la t0, _bssbegin + la t1, _bssend + beq t0, t1, _bss_done +_bss_loop: + addiu t0, 4 + bne t0, t1, _bss_loop + sw zero, -4(t0) +_bss_done: + +#ifndef BOOTLOADER_SPL + /* Set stack pointer and clear the stack */ + la sp, stackend + la t0, stackbegin + li t1, 0xDEADBEEF +_stack_loop: + addiu t0, 4 + bne t0, sp, _stack_loop + sw t1, -4(t0) + + /* Clear the IRQ stack */ + la k0, _irqstackend + la t0, _irqstackbegin +_irqstack_loop: + addiu t0, 4 + bne t0, k0, _irqstack_loop + sw t1, -4(t0) +#endif + + /* Jump to C code */ + j main + nop + +#ifndef BOOTLOADER_SPL + /* Exception entry points */ + .section .vectors.1, "ax", %progbits + j tlb_refill_handler + nop + + .section .vectors.2, "ax", %progbits + j real_exception_handler + nop + + .section .vectors.3, "ax", %progbits + j real_exception_handler + nop + + .section .vectors.4, "ax", %progbits + j real_exception_handler + nop + + .section .vectors, "ax", %progbits +real_exception_handler: + move k0, sp + la sp, _irqstackend + addiu sp, -0x84 + sw k0, 0x80(sp) + sw ra, 0x00(sp) + sw fp, 0x04(sp) + sw gp, 0x08(sp) + sw t9, 0x0c(sp) + sw t8, 0x10(sp) + sw s7, 0x14(sp) + sw s6, 0x18(sp) + sw s5, 0x1c(sp) + sw s4, 0x20(sp) + sw s3, 0x24(sp) + sw s2, 0x28(sp) + sw s1, 0x2c(sp) + sw s0, 0x30(sp) + sw t7, 0x34(sp) + sw t6, 0x38(sp) + sw t5, 0x3c(sp) + sw t4, 0x40(sp) + sw t3, 0x44(sp) + sw t2, 0x48(sp) + sw t1, 0x4c(sp) + sw t0, 0x50(sp) + sw a3, 0x54(sp) + sw a2, 0x58(sp) + sw a1, 0x5c(sp) + sw a0, 0x60(sp) + sw v1, 0x64(sp) + sw v0, 0x68(sp) + sw $1, 0x6c(sp) + mflo k0 + nop + sw k0, 0x70(sp) + mfhi k0 + nop + sw k0, 0x74(sp) + mfc0 k0, C0_STATUS + nop + nop + nop + sw k0, 0x78(sp) + mfc0 k0, C0_EPC + nop + nop + nop + sw k0, 0x7c(sp) + + li k1, M_CauseExcCode + mfc0 a0, C0_CAUSE + and k0, a0, k1 + bnez k0, _exception + nop + jal intr_handler + nop + j _exception_return + +_exception: + mfc0 a1, C0_EPC + nop + nop + nop + jal exception_handler + move a2, sp + +_exception_return: + lw ra, 0x00(sp) + lw fp, 0x04(sp) + lw gp, 0x08(sp) + lw t9, 0x0c(sp) + lw t8, 0x10(sp) + lw s7, 0x14(sp) + lw s6, 0x18(sp) + lw s5, 0x1c(sp) + lw s4, 0x20(sp) + lw s3, 0x24(sp) + lw s2, 0x28(sp) + lw s1, 0x2c(sp) + lw s0, 0x30(sp) + lw t7, 0x34(sp) + lw t6, 0x38(sp) + lw t5, 0x3c(sp) + lw t4, 0x40(sp) + lw t3, 0x44(sp) + lw t2, 0x48(sp) + lw t1, 0x4c(sp) + lw t0, 0x50(sp) + lw a3, 0x54(sp) + lw a2, 0x58(sp) + lw a1, 0x5c(sp) + lw a0, 0x60(sp) + lw v1, 0x64(sp) + lw v0, 0x68(sp) + lw $1, 0x6c(sp) + lw k0, 0x70(sp) + mtlo k0 + nop + lw k0, 0x74(sp) + mthi k0 + nop + lw k0, 0x78(sp) + mtc0 k0, C0_STATUS + nop + nop + nop + lw k0, 0x7c(sp) + mtc0 k0, C0_EPC + nop + nop + nop + lw sp, 0x80(sp) + eret + nop +#endif + + .set pop diff --git a/firmware/target/mips/ingenic_x1000/debug-x1000.c b/firmware/target/mips/ingenic_x1000/debug-x1000.c new file mode 100644 index 0000000000..fed586691c --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/debug-x1000.c @@ -0,0 +1,215 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 BOOTLOADER +#include "system.h" +#include "kernel.h" +#include "button.h" +#include "lcd.h" +#include "font.h" +#include "action.h" +#include "list.h" + +#include "clk-x1000.h" +#include "gpio-x1000.h" + +static bool dbg_clocks(void) +{ + do { + lcd_clear_display(); + int line = 0; + for(int i = 0; i < X1000_CLK_COUNT; ++i) { + uint32_t hz = clk_get(i); + uint32_t khz = hz / 1000; + uint32_t mhz = khz / 1000; + lcd_putsf(2, line++, "%8s %4u,%03u,%03u Hz", clk_get_name(i), + mhz, (khz - mhz*1000), (hz - khz*1000)); + } + + lcd_update(); + } while(get_action(CONTEXT_STD, HZ) != ACTION_STD_CANCEL); + + return false; +} + +static void dbg_gpios_show_state(void) +{ + const char portname[] = "ABCD"; + for(int i = 0; i < 4; ++i) + lcd_putsf(0, i, "GPIO %c: %08x", portname[i], REG_GPIO_PIN(i)); +} + +static void dbg_gpios_show_config(void) +{ + const char portname[] = "ABCD"; + int line = 0; + for(int i = 0; i < 4; ++i) { + uint32_t intr = REG_GPIO_INT(i); + uint32_t mask = REG_GPIO_MSK(i); + uint32_t pat0 = REG_GPIO_PAT0(i); + uint32_t pat1 = REG_GPIO_PAT1(i); + lcd_putsf(0, line++, "GPIO %c", portname[i]); + lcd_putsf(2, line++, " int %08lx", intr); + lcd_putsf(2, line++, " msk %08lx", mask); + lcd_putsf(2, line++, "pat0 %08lx", pat0); + lcd_putsf(2, line++, "pat1 %08lx", pat1); + line++; + } +} + +static bool dbg_gpios(void) +{ + enum { STATE, CONFIG, NUM_SCREENS }; + const int timeouts[NUM_SCREENS] = { 1, HZ }; + int screen = STATE; + + while(1) { + lcd_clear_display(); + switch(screen) { + case CONFIG: + dbg_gpios_show_config(); + break; + case STATE: + dbg_gpios_show_state(); + break; + } + + lcd_update(); + + switch(get_action(CONTEXT_STD, timeouts[screen])) { + case ACTION_STD_CANCEL: + return false; + case ACTION_STD_PREV: + case ACTION_STD_PREVREPEAT: + screen -= 1; + if(screen < 0) + screen = NUM_SCREENS - 1; + break; + case ACTION_STD_NEXT: + case ACTION_STD_NEXTREPEAT: + screen += 1; + if(screen >= NUM_SCREENS) + screen = 0; + break; + default: + break; + } + } + + return false; +} + +extern volatile unsigned aic_tx_underruns; + +static bool dbg_audio(void) +{ + do { + lcd_clear_display(); + lcd_putsf(0, 0, "TX underruns: %u", aic_tx_underruns); + lcd_update(); + } while(get_action(CONTEXT_STD, HZ) != ACTION_STD_CANCEL); + + return false; +} + +static bool dbg_cpuidle(void) +{ + do { + lcd_clear_display(); + lcd_putsf(0, 0, "CPU idle time: %d.%01d%%", + __cpu_idle_cur/10, __cpu_idle_cur%10); + lcd_putsf(0, 1, "CPU frequency: %d.%03d MHz", + FREQ/1000000, (FREQ%1000000)/1000); + lcd_update(); + } while(get_action(CONTEXT_STD, HZ) != ACTION_STD_CANCEL); + + return false; +} + +#ifdef FIIO_M3K +extern bool dbg_fiiom3k_touchpad(void); +extern bool axp173_debug_menu(void); +#endif + +/* Menu definition */ +static const struct { + const char* name; + bool(*function)(void); +} menuitems[] = { + {"Clocks", &dbg_clocks}, + {"GPIOs", &dbg_gpios}, + {"CPU idle", &dbg_cpuidle}, + {"Audio", &dbg_audio}, +#ifdef FIIO_M3K + {"Touchpad", &dbg_fiiom3k_touchpad}, + {"Power stats", &axp173_debug_menu}, +#endif +}; + +static int hw_info_menu_action_cb(int btn, struct gui_synclist* lists) +{ + if(btn == ACTION_STD_OK) { + int sel = gui_synclist_get_sel_pos(lists); + FOR_NB_SCREENS(i) + viewportmanager_theme_enable(i, false, NULL); + + lcd_setfont(FONT_SYSFIXED); + lcd_set_foreground(LCD_WHITE); + lcd_set_background(LCD_BLACK); + + if(menuitems[sel].function()) + btn = SYS_USB_CONNECTED; + else + btn = ACTION_REDRAW; + + lcd_setfont(FONT_UI); + + FOR_NB_SCREENS(i) + viewportmanager_theme_undo(i, false); + } + + return btn; +} + +static const char* hw_info_menu_get_name(int item, void* data, + char* buffer, size_t buffer_len) +{ + (void)buffer; + (void)buffer_len; + (void)data; + return menuitems[item].name; +} + +bool dbg_hw_info(void) +{ + struct simplelist_info info; + simplelist_info_init(&info, MODEL_NAME " debug menu", + ARRAYLEN(menuitems), NULL); + info.action_callback = hw_info_menu_action_cb; + info.get_name = hw_info_menu_get_name; + return simplelist_show_list(&info); +} + +bool dbg_ports(void) +{ + return false; +} +#endif diff --git a/firmware/target/mips/ingenic_x1000/dma-x1000.c b/firmware/target/mips/ingenic_x1000/dma-x1000.c new file mode 100644 index 0000000000..28fd328a85 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/dma-x1000.c @@ -0,0 +1,91 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 "dma-x1000.h" +#include "irq-x1000.h" +#include "x1000/cpm.h" +#include "panic.h" + +static dma_cb_func dma_callbacks[DMA_NUM_USED_CHANNELS]; + +static void dma_no_cb(int event) +{ + (void)event; + panicf("Unhandled DMA channel interrupt"); +} + +void dma_init(void) +{ + for(int i = 0; i < DMA_NUM_USED_CHANNELS; ++i) + dma_callbacks[i] = dma_no_cb; + + jz_writef(CPM_CLKGR, PDMA(0)); + jz_writef(DMA_CTRL, ENABLE(1), HALT(0), AR(0)); + jz_writef(DMA_CTRL, FMSC(1), FSSI(1), FTSSI(1), FUART(1), FAIC(1)); + system_enable_irq(IRQ_PDMA); + system_enable_irq(IRQ_PDMAD); +} + +void dma_set_callback(int chn, dma_cb_func cb) +{ + dma_callbacks[chn] = cb != NULL ? cb : dma_no_cb; +} + +void PDMA(void) +{ + /* This is called when the last descriptor completes, or if the + * channel hits an error. + */ + unsigned pending = REG_DMA_IRQP; + for(int i = 0; i < DMA_NUM_USED_CHANNELS; ++i) { + if((pending & (1 << i)) == 0) + continue; + + int evt; + if(REG_DMA_CHN_CS(i) & jz_orm(DMA_CHN_CS, AR, HLT)) + evt = DMA_EVENT_ERROR; + else + evt = DMA_EVENT_COMPLETE; + + REG_DMA_CHN_CS(i) = 0; + dma_callbacks[i](evt); + } + + /* Clear any errors and clear interrupts */ + jz_writef(DMA_CTRL, HALT(0), AR(0)); + REG_DMA_IRQP = 0; +} + +void PDMAD(void) +{ + /* Called when TIE is set on a non-final descriptor */ + unsigned pending = REG_DMA_DIP; + for(int i = 0; i < DMA_NUM_USED_CHANNELS; ++i) { + if((pending & (1 << i)) == 0) + continue; + + dma_callbacks[i](DMA_EVENT_INTERRUPT); + } + + /* This does not operate like other clear registers */ + REG_DMA_DIC &= ~pending; +} diff --git a/firmware/target/mips/ingenic_x1000/dma-x1000.h b/firmware/target/mips/ingenic_x1000/dma-x1000.h new file mode 100644 index 0000000000..d836a0cf54 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/dma-x1000.h @@ -0,0 +1,69 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 __DMA_X1000_H__ +#define __DMA_X1000_H__ + +#include "x1000/dma.h" +#include "x1000/dma_chn.h" +#include <stdint.h> + +/* Events passed to DMA callbacks */ +#define DMA_EVENT_NONE 0 /* Not used by DMA code but can be used as + * a sentinel value to indicate "no event" */ +#define DMA_EVENT_INTERRUPT 1 /* Interrupt on a non-final descriptor */ +#define DMA_EVENT_COMPLETE 2 /* Completed the final descriptor */ +#define DMA_EVENT_ERROR 3 /* Some kind of error occurred */ + +/* All DMA channels which use interrupts must be statically defined here. + * The channel numbering should be contiguous, and lower channel numbers + * will have lower interrupt latency because they're serviced first. + * + * Channels >= DMA_NUM_USED_CHANNELS will NOT have interrupts serviced! + * Due to the possibility of address error interrupts that can occur even + * if no interrupts are requested on the channel, the unallocated channels + * cannot be used safely. + */ +#define DMA_CHANNEL_AUDIO 0 +#define DMA_CHANNEL_FBCOPY 1 +#define DMA_NUM_USED_CHANNELS 2 + +struct dma_desc { + uint32_t cm; /* meaning and layout same as DMA_CHN_CM */ + uint32_t sa; /* source address */ + uint32_t ta; /* target address */ + uint32_t tc; /* low 24 bits: transfer count + * upper 8 bits: offset to next descriptor + */ + uint32_t sd; /* same as DMA_CHN_SD */ + uint32_t rt; /* request type, same as DMA_CHN_RT */ + uint32_t pad0; + uint32_t pad1; +} __attribute__((aligned(32))); + +typedef struct dma_desc dma_desc; + +typedef void(*dma_cb_func)(int event); + +extern void dma_init(void); +extern void dma_set_callback(int chn, dma_cb_func cb); + +#endif /* __DMA_X1000_H__ */ diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/adc-target.h b/firmware/target/mips/ingenic_x1000/fiiom3k/adc-target.h new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/fiiom3k/adc-target.h diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/audiohw-fiiom3k.c b/firmware/target/mips/ingenic_x1000/fiiom3k/audiohw-fiiom3k.c new file mode 100644 index 0000000000..2f43809523 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/fiiom3k/audiohw-fiiom3k.c @@ -0,0 +1,81 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 "audiohw.h" +#include "system.h" +#include "pcm_sampr.h" +#include "logf.h" +#include "aic-x1000.h" +#include "i2c-x1000.h" +#include "gpio-x1000.h" +#include "x1000/aic.h" +#include "x1000/cpm.h" + +void audiohw_init(void) +{ + /* Configure AIC for I2S operation */ + jz_writef(CPM_CLKGR, AIC(0)); + gpio_config(GPIO_B, 0x1f, GPIO_DEVICE(1)); + jz_writef(AIC_I2SCR, STPBK(1)); + + /* Operate as I2S master, use external codec */ + jz_writef(AIC_CFG, AUSEL(1), ICDC(0), BCKD(1), SYNCD(1), LSMP(1)); + jz_writef(AIC_I2SCR, ESCLK(1), AMSL(0)); + + /* Stereo audio, packed 16 bit samples */ + jz_writef(AIC_CCR, PACK16(1), CHANNEL(1), OSS(1)); + + /* Initialize DAC */ + i2c_x1000_set_freq(AK4376_BUS, I2C_FREQ_400K); + ak4376_init(); +} + +void audiohw_postinit(void) +{ +} + +void audiohw_close(void) +{ + ak4376_close(); +} + +void ak4376_set_pdn_pin(int level) +{ + gpio_config(GPIO_A, 1 << 16, GPIO_OUTPUT(level ? 1 : 0)); +} + +int ak4376_set_mclk_freq(int hw_freq, bool enabled) +{ + /* Get the multiplier */ + int freq = hw_freq_sampr[hw_freq]; + int mult = freq >= SAMPR_176 ? 128 : 256; + + if(enabled) { + /* Set the new frequency; clock is enabled afterward */ + if(aic_i2s_set_mclk(X1000_CLK_SCLK_A, freq, mult)) + logf("WARNING: unachievable audio rate %d x %d!?", freq, mult); + } else { + /* Shut off the clock */ + jz_writef(AIC_I2SCR, STPBK(1)); + } + + return mult; +} diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/backlight-fiiom3k.c b/firmware/target/mips/ingenic_x1000/fiiom3k/backlight-fiiom3k.c new file mode 100644 index 0000000000..f02fcaaee8 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/fiiom3k/backlight-fiiom3k.c @@ -0,0 +1,88 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 "backlight.h" +#include "backlight-target.h" +#include "lcd.h" +#include "pwm-x1000.h" + +#define BL_LCD_CHN 0 +#define BL_LCD_PERIOD 33000 + +#define BL_BTN_CHN 4 +#define BL_BTN_PERIOD 100000 + +static int backlight_calc_duty(int period, int min_duty, int brightness) +{ + return min_duty + (period - min_duty) * brightness / MAX_BRIGHTNESS_SETTING; +} + +bool backlight_hw_init(void) +{ + pwm_init(BL_LCD_CHN); + pwm_init(BL_BTN_CHN); + pwm_enable(BL_LCD_CHN); + pwm_enable(BL_BTN_CHN); + backlight_hw_brightness(MAX_BRIGHTNESS_SETTING); + buttonlight_hw_brightness(MAX_BRIGHTNESS_SETTING); + /* TODO: avoid buttonlight flicker when powering up the machine */ + return true; +} + +void backlight_hw_on(void) +{ + pwm_enable(BL_LCD_CHN); +#ifdef HAVE_LCD_ENABLE + lcd_enable(true); +#endif +} + +void backlight_hw_off(void) +{ + pwm_disable(BL_LCD_CHN); +#ifdef HAVE_LCD_ENABLE + lcd_enable(false); +#endif +} + +void backlight_hw_brightness(int brightness) +{ + int duty_ns = backlight_calc_duty(BL_LCD_PERIOD, 0, brightness); + pwm_set_period(BL_LCD_CHN, BL_LCD_PERIOD, duty_ns); +} + +void buttonlight_hw_on(void) +{ + pwm_enable(BL_BTN_CHN); +} + +void buttonlight_hw_off(void) +{ + pwm_disable(BL_BTN_CHN); +} + +void buttonlight_hw_brightness(int brightness) +{ + /* Duty cycle below 11% seems to turn the buttonlight off entirely, + * so we need to rescale the range */ + int duty_ns = backlight_calc_duty(BL_BTN_PERIOD, BL_BTN_PERIOD*11/100, brightness); + pwm_set_period(BL_BTN_CHN, BL_BTN_PERIOD, duty_ns); +} diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/backlight-target.h b/firmware/target/mips/ingenic_x1000/fiiom3k/backlight-target.h new file mode 100644 index 0000000000..791a013c32 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/fiiom3k/backlight-target.h @@ -0,0 +1,37 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 __BACKLIGHT_TARGET_H__ +#define __BACKLIGHT_TARGET_H__ + +#include <stdbool.h> + +extern bool backlight_hw_init(void); + +extern void backlight_hw_on(void); +extern void backlight_hw_off(void); +extern void backlight_hw_brightness(int brightness); + +extern void buttonlight_hw_on(void); +extern void buttonlight_hw_off(void); +extern void buttonlight_hw_brightness(int brightness); + +#endif /* __BACKLIGHT_TARGET_H__ */ diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/button-fiiom3k.c b/firmware/target/mips/ingenic_x1000/fiiom3k/button-fiiom3k.c new file mode 100644 index 0000000000..db5ece10b0 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/fiiom3k/button-fiiom3k.c @@ -0,0 +1,503 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 "button.h" +#include "kernel.h" +#include "backlight.h" +#include "panic.h" +#include "lcd.h" +#include "gpio-x1000.h" +#include "i2c-x1000.h" +#include <string.h> +#include <stdbool.h> + +#ifndef BOOTLOADER +# include "font.h" +#endif + +#define FT_RST_PIN (1 << 15) +#define FT_INT_PIN (1 << 12) +#define ft_interrupt GPIOB12 + +/* Touch event types */ +#define EVENT_NONE (-1) +#define EVENT_PRESS 0 +#define EVENT_RELEASE 1 +#define EVENT_CONTACT 2 + +/* FSM states */ +#define STATE_IDLE 0 +#define STATE_PRESS 1 +#define STATE_REPORT 2 +#define STATE_SCROLL_PRESS 3 +#define STATE_SCROLLING 4 + +/* Assume there's no active touch if no event is reported in this time */ +#define AUTORELEASE_TIME (10000 * OST_TICKS_PER_US) + +/* If there's no significant motion on the scrollbar for this time, + * then report it as a button press instead */ +#define SCROLL_PRESS_TIME (100000 * OST_TICKS_PER_US) + +/* If a press on the scrollbar moves more than this during SCROLL_PRESS_TIME, + * then we enter scrolling mode. */ +#define MIN_SCROLL_THRESH 15 + +/* If OST tick a is after OST tick b, then returns the number of ticks + * in the interval between a and b; otherwise undefined. */ +#define TICKS_SINCE(a, b) ((a) - (b)) + +/* Number of touch samples to smooth before reading */ +#define TOUCH_SAMPLES 3 + +static struct ft_driver { + int i2c_cookie; + i2c_descriptor i2c_desc; + uint8_t raw_data[6]; + bool active; + + /* Number of pixels squared which must be moved before + * a scrollbar pulse is generated */ + int scroll_thresh_sqr; +} ftd; + +static struct ft_state_machine { + /* Current button state, used by button_read_device() */ + int buttons; + + /* FSM state */ + int state; + + /* Time of the last touch event, as 32-bit OST timestamp. The kernel + * tick is simply too low-resolution to work reliably, especially as + * we handle touchpad events asynchronously. */ + uint32_t last_event_t; + + /* Time of entering the SCROLL_PRESS state, used to differentiate + * between a press, hold, or scrolling motion */ + uint32_t scroll_press_t; + + /* Number of CONTACT events sampled in the PRESS state. + * Must reach TOUCH_SAMPLES before we move forward. */ + int samples; + + /* Filter for smoothing touch points */ + int sum_x, sum_y; + + /* Position of the original touch */ + int orig_x, orig_y; + + /* Current touch position */ + int cur_x, cur_y; +} fsm; + +static int touch_to_button(int x, int y) +{ + if(x == 900) { + /* Right strip */ + if(y == 80) + return BUTTON_BACK; + else if(y == 240) + return BUTTON_RIGHT; + else + return 0; + } else if(x < 80) { + /* Left strip */ + if(y < 80) + return BUTTON_MENU; + else if(y > 190) + return BUTTON_LEFT; + else + return 0; + } else { + /* Middle strip */ + if(y < 100) + return BUTTON_UP; + else if(y > 220) + return BUTTON_DOWN; + else + return BUTTON_SELECT; + } +} + +static bool ft_accum_touch(uint32_t t, int tx, int ty) +{ + /* Record event time */ + fsm.last_event_t = t; + + if(fsm.samples < TOUCH_SAMPLES) { + /* Continue "priming" the filter */ + fsm.sum_x += tx; + fsm.sum_y += ty; + fsm.samples += 1; + + /* Return if filter is not ready */ + if(fsm.samples < TOUCH_SAMPLES) + return false; + } else { + /* Update filter */ + fsm.sum_x += tx - fsm.sum_x / TOUCH_SAMPLES; + fsm.sum_y += ty - fsm.sum_y / TOUCH_SAMPLES; + } + + /* Filter is ready, so read the point */ + fsm.cur_x = fsm.sum_x / TOUCH_SAMPLES; + fsm.cur_y = fsm.sum_y / TOUCH_SAMPLES; + return true; +} + +static void ft_go_idle(void) +{ + /* Null out the touch state */ + fsm.buttons = 0; + fsm.samples = 0; + fsm.sum_x = fsm.sum_y = 0; + fsm.state = STATE_IDLE; +} + +static void ft_start_report(void) +{ + /* Report the button bit */ + fsm.buttons = touch_to_button(fsm.cur_x, fsm.cur_y); + fsm.orig_x = fsm.cur_x; + fsm.orig_y = fsm.cur_y; + fsm.state = STATE_REPORT; +} + +static void ft_start_report_or_scroll(void) +{ + ft_start_report(); + + /* If the press occurs on the scrollbar, then we need to + * wait an additional delay before reporting it in case + * this is the beginning of a scrolling motion */ + if(fsm.buttons & (BUTTON_UP|BUTTON_DOWN|BUTTON_SELECT)) { + fsm.buttons = 0; + fsm.scroll_press_t = __ost_read32(); + fsm.state = STATE_SCROLL_PRESS; + } +} + +static void ft_step_state(uint32_t t, int evt, int tx, int ty) +{ + /* Generate a release event automatically in case we missed it */ + if(evt == EVENT_NONE) { + if(TICKS_SINCE(t, fsm.last_event_t) >= AUTORELEASE_TIME) { + evt = EVENT_RELEASE; + tx = fsm.cur_x; + ty = fsm.cur_y; + } + } + + switch(fsm.state) { + case STATE_IDLE: { + if(evt == EVENT_PRESS || evt == EVENT_CONTACT) { + /* Move to REPORT or PRESS state */ + if(ft_accum_touch(t, tx, ty)) + ft_start_report_or_scroll(); + else + fsm.state = STATE_PRESS; + } + } break; + + case STATE_PRESS: { + if(evt == EVENT_RELEASE) { + /* Ignore if the number of samples is too low */ + ft_go_idle(); + } else if(evt == EVENT_PRESS || evt == EVENT_CONTACT) { + /* Accumulate the touch position in the filter */ + if(ft_accum_touch(t, tx, ty)) + ft_start_report_or_scroll(); + } + } break; + + case STATE_REPORT: { + if(evt == EVENT_RELEASE) + ft_go_idle(); + else if(evt == EVENT_PRESS || evt == EVENT_CONTACT) + ft_accum_touch(t, tx, ty); + } break; + + case STATE_SCROLL_PRESS: { + if(evt == EVENT_RELEASE) { + /* This _should_ synthesize a button press. + * + * - ft_start_report() will set the button bit based on the + * current touch position and enter the REPORT state, which + * will automatically hold the bit high + * + * - The next button_read_device() will see the button bit + * and report it back to Rockbox, then step the FSM with + * EVENT_NONE. + * + * - The EVENT_NONE stepping will eventually autogenerate a + * RELEASE event and restore the button state back to 0 + * + * - There's a small logic hole in the REPORT state which + * could cause it to miss an immediately repeated PRESS + * that occurs before the autorelease timeout kicks in. + * FIXME: We might want to special-case that. + */ + ft_start_report(); + break; + } + + if(evt == EVENT_PRESS || evt == EVENT_CONTACT) + ft_accum_touch(t, tx, ty); + + int dx = fsm.cur_x - fsm.orig_x; + int dy = fsm.cur_y - fsm.orig_y; + int dp = (dx*dx) + (dy*dy); + if(dp >= MIN_SCROLL_THRESH*MIN_SCROLL_THRESH) { + /* Significant motion: enter SCROLLING state */ + fsm.state = STATE_SCROLLING; + } else if(TICKS_SINCE(t, fsm.scroll_press_t) >= SCROLL_PRESS_TIME) { + /* No significant motion: report it as a press */ + fsm.cur_x = fsm.orig_x; + fsm.cur_y = fsm.orig_y; + ft_start_report(); + } + } break; + + case STATE_SCROLLING: { + if(evt == EVENT_RELEASE) { + ft_go_idle(); + break; + } + + if(evt == EVENT_PRESS || evt == EVENT_CONTACT) + ft_accum_touch(t, tx, ty); + + int dx = fsm.cur_x - fsm.orig_x; + int dy = fsm.cur_y - fsm.orig_y; + int dp = (dx*dx) + (dy*dy); + if(dp >= ftd.scroll_thresh_sqr) { + if(dy < 0) { + queue_post(&button_queue, BUTTON_SCROLL_BACK, 0); + } else { + queue_post(&button_queue, BUTTON_SCROLL_FWD, 0); + } + + /* Poke the backlight */ + backlight_on(); + buttonlight_on(); + + fsm.orig_x = fsm.cur_x; + fsm.orig_y = fsm.cur_y; + } + } break; + + default: + panicf("ft6x06: unhandled state"); + break; + } +} + +static void ft_i2c_callback(int status, i2c_descriptor* desc) +{ + (void)desc; + if(status != I2C_STATUS_OK) + return; + + /* The panel is oriented such that its X axis is vertical, + * so swap the axes for reporting */ + int evt = ftd.raw_data[1] >> 6; + int ty = ftd.raw_data[2] | ((ftd.raw_data[1] & 0xf) << 8); + int tx = ftd.raw_data[4] | ((ftd.raw_data[3] & 0xf) << 8); + + /* TODO: convert the touch positions to linear positions. + * + * Points reported by the touch controller are distorted and non-linear, + * ideally we'd like to correct these values. There's more precision in + * the middle of the touchpad than on the edges, so scrolling feels slow + * in the middle and faster near the edge. + */ + + ft_step_state(__ost_read32(), evt, tx, ty); +} + +void ft_interrupt(void) +{ + /* We don't care if this fails */ + i2c_async_queue(FT6x06_BUS, TIMEOUT_NOBLOCK, I2C_Q_ONCE, + ftd.i2c_cookie, &ftd.i2c_desc); +} + +static void ft_init(void) +{ + /* Initialize the driver state */ + ftd.i2c_cookie = i2c_async_reserve_cookies(FT6x06_BUS, 1); + ftd.i2c_desc.slave_addr = FT6x06_ADDR; + ftd.i2c_desc.bus_cond = I2C_START | I2C_STOP; + ftd.i2c_desc.tran_mode = I2C_READ; + ftd.i2c_desc.buffer[0] = &ftd.raw_data[5]; + ftd.i2c_desc.count[0] = 1; + ftd.i2c_desc.buffer[1] = &ftd.raw_data[0]; + ftd.i2c_desc.count[1] = 5; + ftd.i2c_desc.callback = ft_i2c_callback; + ftd.i2c_desc.arg = 0; + ftd.i2c_desc.next = NULL; + ftd.raw_data[5] = 0x02; + ftd.active = true; + touchpad_set_sensitivity(DEFAULT_TOUCHPAD_SENSITIVITY_SETTING); + + /* Initialize the state machine */ + fsm.buttons = 0; + fsm.state = STATE_IDLE; + fsm.last_event_t = 0; + fsm.scroll_press_t = 0; + fsm.samples = 0; + fsm.sum_x = fsm.sum_y = 0; + fsm.orig_x = fsm.orig_y = 0; + fsm.cur_x = fsm.cur_y = 0; + + /* Bring up I2C bus */ + i2c_x1000_set_freq(FT6x06_BUS, I2C_FREQ_400K); + + /* Reset chip */ + gpio_config(GPIO_B, FT_RST_PIN|FT_INT_PIN, GPIO_OUTPUT(0)); + mdelay(5); + gpio_out_level(GPIO_B, FT_RST_PIN, 1); + gpio_config(GPIO_B, FT_INT_PIN, GPIO_IRQ_EDGE(0)); + gpio_enable_irq(GPIO_B, FT_INT_PIN); +} + +void touchpad_set_sensitivity(int level) +{ + int pixels = 40; + pixels -= level; + ftd.scroll_thresh_sqr = pixels * pixels; +} + +void touchpad_enable_device(bool en) +{ + i2c_reg_write1(FT6x06_BUS, FT6x06_ADDR, 0xa5, en ? 0 : 3); + ftd.active = en; +} + +/* Value of headphone detect register */ +static uint8_t hp_detect_reg = 0x00; + +/* Interval to poll the register */ +#define HPD_POLL_TIME (HZ/2) + +static int hp_detect_tmo_cb(struct timeout* tmo) +{ + i2c_descriptor* d = (i2c_descriptor*)tmo->data; + i2c_async_queue(AXP173_BUS, TIMEOUT_NOBLOCK, I2C_Q_ADD, 0, d); + return HPD_POLL_TIME; +} + +static void hp_detect_init(void) +{ + static struct timeout tmo; + static const uint8_t gpio_reg = 0x94; + static i2c_descriptor desc = { + .slave_addr = AXP173_ADDR, + .bus_cond = I2C_START | I2C_STOP, + .tran_mode = I2C_READ, + .buffer[0] = (void*)&gpio_reg, + .count[0] = 1, + .buffer[1] = &hp_detect_reg, + .count[1] = 1, + .callback = NULL, + .arg = 0, + .next = NULL, + }; + + /* Headphone detect is wired to an undocumented GPIO on the AXP173. + * This sets it to input mode so we can see the pin state. */ + i2c_reg_write1(AXP173_BUS, AXP173_ADDR, 0x93, 0x01); + + /* Get an initial reading before startup */ + int r = i2c_reg_read1(AXP173_BUS, AXP173_ADDR, gpio_reg); + if(r >= 0) + hp_detect_reg = r; + + /* Poll the register every second */ + timeout_register(&tmo, &hp_detect_tmo_cb, HPD_POLL_TIME, (intptr_t)&desc); +} + +/* Rockbox interface */ +void button_init_device(void) +{ + /* Configure physical button GPIOs */ + gpio_config(GPIO_A, (1 << 17) | (1 << 19), GPIO_INPUT); + gpio_config(GPIO_B, (1 << 28) | (1 << 31), GPIO_INPUT); + + /* Initialize touchpad */ + ft_init(); + + /* Set up headphone detect polling */ + hp_detect_init(); +} + +int button_read_device(void) +{ + int r = fsm.buttons; + ft_step_state(__ost_read32(), EVENT_NONE, 0, 0); + + /* Read GPIOs for physical buttons */ + uint32_t a = REG_GPIO_PIN(GPIO_A); + uint32_t b = REG_GPIO_PIN(GPIO_B); + + /* All buttons are active low */ + if((a & (1 << 17)) == 0) r |= BUTTON_PLAY; + if((a & (1 << 19)) == 0) r |= BUTTON_VOL_UP; + if((b & (1 << 28)) == 0) r |= BUTTON_VOL_DOWN; + if((b & (1 << 31)) == 0) r |= BUTTON_POWER; + + return r; +} + +bool headphones_inserted() +{ + return hp_detect_reg & 0x40 ? true : false; +} + +#ifndef BOOTLOADER +static int getbtn(void) +{ + int btn; + do { + btn = button_get_w_tmo(1); + } while(btn & (BUTTON_REL|BUTTON_REPEAT)); + return btn; +} + +bool dbg_fiiom3k_touchpad(void) +{ + static const char* fsm_statenames[] = { + "IDLE", "PRESS", "REPORT", "SCROLL_PRESS", "SCROLLING" + }; + + do { + int line = 0; + lcd_clear_display(); + lcd_putsf(0, line++, "state: %s", fsm_statenames[fsm.state]); + lcd_putsf(0, line++, "button: %08x", fsm.buttons); + lcd_putsf(0, line++, "pos x: %4d orig x: %4d", fsm.cur_x, fsm.orig_x); + lcd_putsf(0, line++, "pos y: %4d orig y: %4d", fsm.cur_y, fsm.orig_y); + lcd_update(); + } while(getbtn() != BUTTON_POWER); + return false; +} +#endif diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/button-target.h b/firmware/target/mips/ingenic_x1000/fiiom3k/button-target.h new file mode 100644 index 0000000000..f75a43242d --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/fiiom3k/button-target.h @@ -0,0 +1,54 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 __BUTTON_TARGET_H__ +#define __BUTTON_TARGET_H__ + +#include <stdbool.h> + +#define BUTTON_POWER 0x00000001 +#define BUTTON_PLAY 0x00000002 +#define BUTTON_VOL_UP 0x00000004 +#define BUTTON_VOL_DOWN 0x00000008 +#define BUTTON_UP 0x00000010 +#define BUTTON_DOWN 0x00000020 +#define BUTTON_LEFT 0x00000040 +#define BUTTON_RIGHT 0x00000080 +#define BUTTON_SELECT 0x00000100 +#define BUTTON_BACK 0x00000200 +#define BUTTON_MENU 0x00000400 +#define BUTTON_SCROLL_FWD 0x00000800 +#define BUTTON_SCROLL_BACK 0x00001000 + +#define BUTTON_MAIN (BUTTON_POWER|BUTTON_VOL_UP|BUTTON_VOL_DOWN|\ + BUTTON_PLAY|BUTTON_TOUCHPAD) + +#define BUTTON_TOUCHPAD (BUTTON_UP|BUTTON_DOWN|BUTTON_LEFT|BUTTON_RIGHT|\ + BUTTON_SELECT|BUTTON_BACK|BUTTON_MENU|\ + BUTTON_SCROLL_FWD|BUTTON_SCROLL_BACK) + +#define POWEROFF_BUTTON BUTTON_POWER +#define POWEROFF_COUNT 30 + +extern void touchpad_set_sensitivity(int level); +extern void touchpad_enable_device(bool en); + +#endif /* __BUTTON_TARGET_H__ */ diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/i2c-target.h b/firmware/target/mips/ingenic_x1000/fiiom3k/i2c-target.h new file mode 100644 index 0000000000..a389d2af42 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/fiiom3k/i2c-target.h @@ -0,0 +1,37 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 __I2C_TARGET_H__ +#define __I2C_TARGET_H__ + +#define I2C_ASYNC_BUS_COUNT 3 +#define I2C_ASYNC_QUEUE_SIZE 4 + +#define AK4376_BUS 0 +#define AK4376_ADDR 0x10 + +#define FT6x06_BUS 1 +#define FT6x06_ADDR 0x38 + +#define AXP173_BUS 2 +#define AXP173_ADDR 0x34 + +#endif /* __I2C_TARGET_H__ */ diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/installer-fiiom3k.c b/firmware/target/mips/ingenic_x1000/fiiom3k/installer-fiiom3k.c new file mode 100644 index 0000000000..c794da4000 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/fiiom3k/installer-fiiom3k.c @@ -0,0 +1,195 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 "installer.h" +#include "nand-x1000.h" +#include "core_alloc.h" +#include "file.h" + +#define INSTALL_SUCCESS 0 +#define ERR_FLASH_OPEN_FAILED (-1) +#define ERR_FLASH_ENABLE_WP_FAILED (-2) +#define ERR_FLASH_DISABLE_WP_FAILED (-3) +#define ERR_FLASH_ERASE_FAILED (-4) +#define ERR_FLASH_WRITE_FAILED (-5) +#define ERR_FLASH_READ_FAILED (-6) +#define ERR_OUT_OF_MEMORY (-7) +#define ERR_CANNOT_READ_FILE (-8) +#define ERR_CANNOT_WRITE_FILE (-9) +#define ERR_WRONG_SIZE (-10) + +#define BOOT_IMAGE_SIZE (128 * 1024) + +static int install_from_buffer(const void* buf) +{ + if(nand_open()) + return ERR_FLASH_OPEN_FAILED; + + int status = INSTALL_SUCCESS; + + if(nand_enable_writes(true)) { + status = ERR_FLASH_DISABLE_WP_FAILED; + goto _exit; + } + + if(nand_erase_block(0)) { + status = ERR_FLASH_ERASE_FAILED; + goto _exit; + } + + if(nand_write_bytes(0, BOOT_IMAGE_SIZE, buf)) { + status = ERR_FLASH_WRITE_FAILED; + goto _exit; + } + + if(nand_enable_writes(false)) { + status = ERR_FLASH_ENABLE_WP_FAILED; + goto _exit; + } + + _exit: + nand_close(); + return status; +} + +static int dump_to_buffer(void* buf) +{ + if(nand_open()) + return ERR_FLASH_OPEN_FAILED; + + int status = INSTALL_SUCCESS; + + if(nand_read_bytes(0, BOOT_IMAGE_SIZE, buf)) { + status = ERR_FLASH_READ_FAILED; + goto _exit; + } + + _exit: + nand_close(); + return status; +} + +int install_bootloader(const char* path) +{ + /* Allocate memory to hold image */ + int handle = core_alloc("boot_image", BOOT_IMAGE_SIZE); + if(handle < 0) + return ERR_OUT_OF_MEMORY; + + int status = INSTALL_SUCCESS; + void* buffer = core_get_data(handle); + + /* Open the boot image */ + int fd = open(path, O_RDONLY); + if(fd < 0) { + status = ERR_CANNOT_READ_FILE; + goto _exit; + } + + /* Check file size */ + off_t fsize = filesize(fd); + if(fsize != BOOT_IMAGE_SIZE) { + status = ERR_WRONG_SIZE; + goto _exit; + } + + /* Read the file into the buffer */ + ssize_t cnt = read(fd, buffer, BOOT_IMAGE_SIZE); + if(cnt != BOOT_IMAGE_SIZE) { + status = ERR_CANNOT_READ_FILE; + goto _exit; + } + + /* Perform the installation */ + status = install_from_buffer(buffer); + + _exit: + if(fd >= 0) + close(fd); + core_free(handle); + return status; +} + +/* Dump the current bootloader to a file */ +int dump_bootloader(const char* path) +{ + /* Allocate memory to hold image */ + int handle = core_alloc("boot_image", BOOT_IMAGE_SIZE); + if(handle < 0) + return -1; + + /* Read data from flash */ + int fd = -1; + void* buffer = core_get_data(handle); + int status = dump_to_buffer(buffer); + if(status) + goto _exit; + + /* Open file */ + fd = open(path, O_CREAT|O_TRUNC|O_WRONLY); + if(fd < 0) { + status = ERR_CANNOT_WRITE_FILE; + goto _exit; + } + + /* Write data to file */ + ssize_t cnt = write(fd, buffer, BOOT_IMAGE_SIZE); + if(cnt != BOOT_IMAGE_SIZE) { + status = ERR_CANNOT_WRITE_FILE; + goto _exit; + } + + _exit: + if(fd >= 0) + close(fd); + core_free(handle); + return status; +} + +const char* installer_strerror(int rc) +{ + switch(rc) { + case INSTALL_SUCCESS: + return "Success"; + case ERR_FLASH_OPEN_FAILED: + return "Can't open flash device"; + case ERR_FLASH_ENABLE_WP_FAILED: + return "Couldn't re-enable write protect"; + case ERR_FLASH_DISABLE_WP_FAILED: + return "Can't disable write protect"; + case ERR_FLASH_ERASE_FAILED: + return "Flash erase failed"; + case ERR_FLASH_WRITE_FAILED: + return "Flash write error"; + case ERR_FLASH_READ_FAILED: + return "Flash read error"; + case ERR_OUT_OF_MEMORY: + return "Out of memory"; + case ERR_CANNOT_READ_FILE: + return "Error reading file"; + case ERR_CANNOT_WRITE_FILE: + return "Error writing file"; + case ERR_WRONG_SIZE: + return "Wrong file size"; + default: + return "Unknown error"; + } +} diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/lcd-fiiom3k.c b/firmware/target/mips/ingenic_x1000/fiiom3k/lcd-fiiom3k.c new file mode 100644 index 0000000000..96f794d7df --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/fiiom3k/lcd-fiiom3k.c @@ -0,0 +1,192 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 "lcd.h" +#include "kernel.h" +#include "lcd-x1000.h" +#include "gpio-x1000.h" +#include "system.h" + +#define CS_PIN (1 << 18) +#define RD_PIN (1 << 16) + +static const uint32_t fiio_lcd_cmd_enable[] = { + /* Software reset */ + LCD_INSTR_CMD, 0x01, + LCD_INSTR_UDELAY, 120000, + /* Sleep out */ + LCD_INSTR_CMD, 0x11, + LCD_INSTR_UDELAY, 5000, + /* Memory access order */ + LCD_INSTR_CMD, 0x36, + LCD_INSTR_DAT, 0x00, + /* Row and column address set */ + LCD_INSTR_CMD, 0x2a, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, (LCD_WIDTH >> 8) & 0xff, + LCD_INSTR_DAT, (LCD_WIDTH & 0xff), + LCD_INSTR_CMD, 0x2b, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, (LCD_HEIGHT >> 8) & 0xff, + LCD_INSTR_DAT, (LCD_HEIGHT & 0xff), + /* Interface pixel format */ + LCD_INSTR_CMD, 0x3a, + LCD_INSTR_DAT, 0x05, + /* Enable display inversion */ + LCD_INSTR_CMD, 0x21, + /* Porch setting */ + LCD_INSTR_CMD, 0xb2, + LCD_INSTR_DAT, 0x0c, + LCD_INSTR_DAT, 0x0c, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, 0x33, + LCD_INSTR_DAT, 0x33, + /* Gate control */ + LCD_INSTR_CMD, 0xb7, + LCD_INSTR_DAT, 0x35, + /* VCOM setting */ + LCD_INSTR_CMD, 0xbb, + LCD_INSTR_DAT, 0x1f, + /* Backlight control 5 */ + LCD_INSTR_CMD, 0xbc, + LCD_INSTR_DAT, 0xec, + /* Backlight control 6 */ + LCD_INSTR_CMD, 0xbd, + LCD_INSTR_DAT, 0xfe, + /* Voltage settings */ + LCD_INSTR_CMD, 0xc2, + LCD_INSTR_DAT, 0x01, + LCD_INSTR_CMD, 0xc3, + LCD_INSTR_DAT, 0x19, + LCD_INSTR_CMD, 0xc4, + LCD_INSTR_DAT, 0x20, + /* Frame rate control */ + LCD_INSTR_CMD, 0xc6, + LCD_INSTR_DAT, 0x0f, /* = 60 fps */ + /* Power control 1 */ + LCD_INSTR_CMD, 0xd0, + LCD_INSTR_DAT, 0xa4, + LCD_INSTR_DAT, 0xa1, + /* d6 Unknown */ + LCD_INSTR_CMD, 0xd6, + LCD_INSTR_DAT, 0xa1, + /* Positive gamma correction */ + LCD_INSTR_CMD, 0xe0, + LCD_INSTR_DAT, 0xd0, + LCD_INSTR_DAT, 0x06, + LCD_INSTR_DAT, 0x0c, + LCD_INSTR_DAT, 0x0a, + LCD_INSTR_DAT, 0x09, + LCD_INSTR_DAT, 0x0a, + LCD_INSTR_DAT, 0x32, + LCD_INSTR_DAT, 0x33, + LCD_INSTR_DAT, 0x49, + LCD_INSTR_DAT, 0x19, + LCD_INSTR_DAT, 0x14, + LCD_INSTR_DAT, 0x15, + LCD_INSTR_DAT, 0x2b, + LCD_INSTR_DAT, 0x34, + /* Negative gamma correction */ + LCD_INSTR_CMD, 0xe1, + LCD_INSTR_DAT, 0xd0, + LCD_INSTR_DAT, 0x06, + LCD_INSTR_DAT, 0x0c, + LCD_INSTR_DAT, 0x0a, + LCD_INSTR_DAT, 0x09, + LCD_INSTR_DAT, 0x11, + LCD_INSTR_DAT, 0x37, + LCD_INSTR_DAT, 0x33, + LCD_INSTR_DAT, 0x49, + LCD_INSTR_DAT, 0x19, + LCD_INSTR_DAT, 0x14, + LCD_INSTR_DAT, 0x15, + LCD_INSTR_DAT, 0x2d, + LCD_INSTR_DAT, 0x34, + /* Tearing effect line ON, mode=0 (vsync signal) */ + LCD_INSTR_CMD, 0x35, + LCD_INSTR_DAT, 0x00, + /* Display ON */ + LCD_INSTR_CMD, 0x29, + LCD_INSTR_END, +}; + +static const uint32_t fiio_lcd_cmd_sleep[] = { + /* Display OFF */ + LCD_INSTR_CMD, 0x28, + /* Sleep IN */ + LCD_INSTR_CMD, 0x10, + LCD_INSTR_UDELAY, 5000, + LCD_INSTR_END, +}; + +static const uint32_t fiio_lcd_cmd_wake[] = { + /* Sleep OUT */ + LCD_INSTR_CMD, 0x11, + LCD_INSTR_UDELAY, 5000, + /* Display ON */ + LCD_INSTR_CMD, 0x29, + LCD_INSTR_END, +}; + +static const uint8_t __attribute__((aligned(64))) + fiio_lcd_dma_wr_cmd[] = {0x00, 0x00, 0x00, 0x2c}; + +const struct lcd_tgt_config lcd_tgt_config = { + .bus_width = 16, + .cmd_width = 8, + .use_6800_mode = 0, + .use_serial = 0, + .clk_polarity = 0, + .dc_polarity = 0, + .wr_polarity = 1, + .te_enable = 1, + .te_polarity = 1, + .te_narrow = 0, + .dma_wr_cmd_buf = &fiio_lcd_dma_wr_cmd, + .dma_wr_cmd_size = sizeof(fiio_lcd_dma_wr_cmd), +}; + +void lcd_tgt_enable(bool enable) +{ + if(enable) { + gpio_config(GPIO_A, 0xffff, GPIO_DEVICE(1)); + gpio_config(GPIO_B, 0x1f << 16, GPIO_DEVICE(1)); + gpio_config(GPIO_B, CS_PIN|RD_PIN, GPIO_OUTPUT(1)); + mdelay(5); + gpio_out_level(GPIO_B, CS_PIN, 0); + lcd_set_clock(X1000_CLK_SCLK_A, 30000000); + lcd_exec_commands(&fiio_lcd_cmd_enable[0]); + } else { + lcd_exec_commands(&fiio_lcd_cmd_sleep[0]); + mdelay(115); /* ensure we wait a total of 120ms before power off */ + gpio_config(GPIO_B, CS_PIN|RD_PIN, 0); + } +} + +void lcd_tgt_sleep(bool sleep) +{ + if(sleep) + lcd_exec_commands(&fiio_lcd_cmd_sleep[0]); + else + lcd_exec_commands(&fiio_lcd_cmd_wake[0]); +} diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/nand-fiiom3k.c b/firmware/target/mips/ingenic_x1000/fiiom3k/nand-fiiom3k.c new file mode 100644 index 0000000000..7c8a306bae --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/fiiom3k/nand-fiiom3k.c @@ -0,0 +1,53 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 "nand-x1000.h" +#include "nand-target.h" +#include "sfc-x1000.h" + +/* Unbelievably FiiO has completely disabled the use of ECC for this chip + * in their Linux kernel, even though it has perfectly good spare areas. + * There's no internal ECC either. + * + * Using nanddump to read the spare areas reveals they're filled with 0xff, + * and the publicly released Linux source has the ecc_strength set to 0. + */ +static const nand_chip_data ato25d1ga = { + .name = "ATO25D1GA", + .mf_id = 0x9b, + .dev_id = 0x12, + .dev_conf = NAND_INIT_SFC_DEV_CONF, + /* XXX: datasheet says 104 MHz but FiiO seems to run this at 150 MHz. + * Didn't find any issues doing this so might as well keep the behavior. + */ + .clock_freq = NAND_INIT_CLOCK_SPEED, + .block_size = 64, + .page_size = 2048, + .spare_size = 64, + .rowaddr_width = 3, + .coladdr_width = 2, + .flags = NANDCHIP_FLAG_QUAD, +}; + +const nand_chip_desc target_nand_chip_descs[] = { + {&ato25d1ga, &nand_chip_ops_std}, + {NULL, NULL}, +}; diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/nand-target.h b/firmware/target/mips/ingenic_x1000/fiiom3k/nand-target.h new file mode 100644 index 0000000000..26a8b840c9 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/fiiom3k/nand-target.h @@ -0,0 +1,42 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 __NAND_TARGET_H__ +#define __NAND_TARGET_H__ + +/* The max page size (main + spare) of all NAND chips used by this target */ +#define NAND_MAX_PAGE_SIZE (2048 + 64) + +/* The clock source to use for the SFC controller. Note the SPL has special + * handling which ignores this choice, so it only applies to bootloader & app. + */ +#define NAND_CLOCK_SOURCE X1000_CLK_SCLK_A + +/* The clock speed to use for the SFC controller during chip identification */ +#define NAND_INIT_CLOCK_SPEED 150000000 + +/* Initial value to program SFC_DEV_CONF register with */ +#define NAND_INIT_SFC_DEV_CONF \ + jz_orf(SFC_DEV_CONF, CE_DL(1), HOLD_DL(1), WP_DL(1), \ + CPHA(0), CPOL(0), TSH(7), TSETUP(0), THOLD(0), \ + STA_TYPE_V(1BYTE), CMD_TYPE_V(8BITS), SMP_DELAY(1)) + +#endif /* __NAND_TARGET_H__ */ diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c b/firmware/target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c new file mode 100644 index 0000000000..3eb3146d97 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c @@ -0,0 +1,97 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 "power.h" +#include "adc.h" +#include "system.h" +#include "kernel.h" +#include "axp173.h" +#include "i2c-x1000.h" +#include "gpio-x1000.h" + +const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = +{ + 3470 +}; + +/* the OF shuts down at this voltage */ +const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] = +{ + 3400 +}; + +/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */ +const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] = +{ + { 3400, 3639, 3697, 3723, 3757, 3786, 3836, 3906, 3980, 4050, 4159 } +}; + +/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */ +const unsigned short const percent_to_volt_charge[11] = +{ + 3485, 3780, 3836, 3857, 3890, 3930, 3986, 4062, 4158, 4185, 4196 +}; + +#define AXP173_IRQ_PORT GPIO_B +#define AXP173_IRQ_PIN (1 << 10) + +void power_init(void) +{ + /* Initialize driver */ + i2c_x1000_set_freq(2, I2C_FREQ_400K); + axp173_init(); + + /* Set lowest sample rate */ + axp173_adc_set_rate(AXP173_ADC_RATE_25HZ); + + /* Ensure battery voltage ADC is enabled */ + int bits = axp173_adc_get_enabled(); + bits |= (1 << ADC_BATTERY_VOLTAGE); + axp173_adc_set_enabled(bits); + + /* Turn on all power outputs */ + i2c_reg_modify1(AXP173_BUS, AXP173_ADDR, 0x12, 0, 0x5f, NULL); + i2c_reg_modify1(AXP173_BUS, AXP173_ADDR, 0x80, 0, 0xc0, NULL); + + /* Short delay to give power outputs time to stabilize */ + mdelay(5); +} + +void adc_init(void) +{ +} + +void power_off(void) +{ + /* Set the shutdown bit */ + i2c_reg_setbit1(AXP173_BUS, AXP173_ADDR, 0x32, 7, 1, NULL); + while(1); +} + +bool charging_state(void) +{ + return axp173_battery_status() == AXP173_BATT_CHARGING; +} + +int _battery_voltage(void) +{ + return axp173_adc_read(ADC_BATTERY_VOLTAGE); +} diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/powermgmt-target.h b/firmware/target/mips/ingenic_x1000/fiiom3k/powermgmt-target.h new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/fiiom3k/powermgmt-target.h diff --git a/firmware/target/mips/ingenic_x1000/gpio-x1000.c b/firmware/target/mips/ingenic_x1000/gpio-x1000.c new file mode 100644 index 0000000000..a47865e397 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/gpio-x1000.c @@ -0,0 +1,84 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 "gpio-x1000.h" +#include "kernel.h" + +#ifndef BOOTLOADER_SPL +struct mutex gpio_z_mutex; +#endif + +void gpio_init(void) +{ +#ifndef BOOTLOADER_SPL + mutex_init(&gpio_z_mutex); +#endif + + /* Set all pins to input state */ + for(int i = 0; i < 4; ++i) { + jz_clr(GPIO_INT(GPIO_Z), 0xffffffff); + jz_set(GPIO_MSK(GPIO_Z), 0xffffffff); + jz_set(GPIO_PAT1(GPIO_Z), 0xffffffff); + jz_clr(GPIO_PAT0(GPIO_Z), 0xffffffff); + REG_GPIO_Z_GID2LD = i; + } + + /* Clear flag and disable pull resistor */ + for(int i = 0; i < 4; ++i) { + jz_clr(GPIO_FLAG(i), 0xffffffff); + jz_set(GPIO_PULL(i), 0xffffffff); + } +} + +void gpio_lock(void) +{ +#ifndef BOOTLOADER_SPL + mutex_lock(&gpio_z_mutex); +#endif +} + +void gpio_unlock(void) +{ +#ifndef BOOTLOADER_SPL + mutex_unlock(&gpio_z_mutex); +#endif +} + +void gpio_config(int port, unsigned pinmask, int func) +{ + unsigned intr = REG_GPIO_INT(port); + unsigned mask = REG_GPIO_MSK(port); + unsigned pat1 = REG_GPIO_PAT1(port); + unsigned pat0 = REG_GPIO_PAT0(port); + + gpio_lock(); + if(func & 8) jz_set(GPIO_INT(GPIO_Z), (intr & pinmask) ^ pinmask); + else jz_clr(GPIO_INT(GPIO_Z), (~intr & pinmask) ^ pinmask); + if(func & 4) jz_set(GPIO_MSK(GPIO_Z), (mask & pinmask) ^ pinmask); + else jz_clr(GPIO_MSK(GPIO_Z), (~mask & pinmask) ^ pinmask); + if(func & 2) jz_set(GPIO_PAT1(GPIO_Z), (pat1 & pinmask) ^ pinmask); + else jz_clr(GPIO_PAT1(GPIO_Z), (~pat1 & pinmask) ^ pinmask); + if(func & 1) jz_set(GPIO_PAT0(GPIO_Z), (pat0 & pinmask) ^ pinmask); + else jz_clr(GPIO_PAT0(GPIO_Z), (~pat0 & pinmask) ^ pinmask); + REG_GPIO_Z_GID2LD = port; + gpio_unlock(); + gpio_set_pull(port, pinmask, func & 16); +} diff --git a/firmware/target/mips/ingenic_x1000/gpio-x1000.h b/firmware/target/mips/ingenic_x1000/gpio-x1000.h new file mode 100644 index 0000000000..f1a65b37b5 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/gpio-x1000.h @@ -0,0 +1,110 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 __GPIO_X1000_H__ +#define __GPIO_X1000_H__ + +/* GPIO API + * -------- + * + * To assign a new function to a GPIO, call gpio_config(). This uses the + * hardware's GPIO Z facility to atomically most GPIO registers at once, + * so it can be used to make any state transition safely. Since GPIO Z is + * protected by a mutex, you can't call gpio_config() from interrupt context. + * + * If you need to use GPIO Z directly, then use gpio_lock() and gpio_unlock() + * to acquire the mutex. + * + * Depending on the current GPIO state, certain state transitions are safe to + * perform without locking, as they only change one register: + * + * - for pins in GPIO_OUTPUT state: + * - use gpio_out_level() to change the output level + * + * - for pins in GPIO_IRQ_LEVEL or GPIO_IRQ_EDGE state: + * - use gpio_irq_level() to change the trigger level + * - use gpio_irq_mask() to mask/unmask the IRQ + * + * - for pins in GPIO_DEVICE or GPIO_INPUT state: + * - no special transitions allowed + * + * - in all states: + * - use gpio_set_pull() to change the pull-up/pull-down state + */ + +#include "x1000/gpio.h" + +/* GPIO port numbers */ +#define GPIO_A 0 +#define GPIO_B 1 +#define GPIO_C 2 +#define GPIO_D 3 +#define GPIO_Z 7 + +/* GPIO function bits */ +#define GPIO_F_PULL 16 +#define GPIO_F_INT 8 +#define GPIO_F_MASK 4 +#define GPIO_F_PAT1 2 +#define GPIO_F_PAT0 1 + +/* GPIO function numbers */ +#define GPIO_DEVICE(i) ((i)&3) +#define GPIO_OUTPUT(i) (0x4|((i)&1)) +#define GPIO_INPUT 0x16 +#define GPIO_IRQ_LEVEL(i) (0x1c|((i)&1)) +#define GPIO_IRQ_EDGE(i) (0x1e|((i)&1)) + +extern void gpio_init(void); +extern void gpio_lock(void); +extern void gpio_unlock(void); +extern void gpio_config(int port, unsigned pinmask, int func); + +static inline void gpio_out_level(int port, unsigned pinmask, int level) +{ + if(level) + jz_set(GPIO_PAT0(port), pinmask); + else + jz_clr(GPIO_PAT0(port), pinmask); +} + +#define gpio_irq_level gpio_out_level + +static inline void gpio_irq_mask(int port, unsigned pinmask, int masked) +{ + if(masked) + jz_set(GPIO_MSK(port), pinmask); + else + jz_clr(GPIO_MSK(port), pinmask); +} + +#define gpio_enable_irq(port, pinmask) gpio_irq_mask((port), (pinmask), 0) +#define gpio_disable_irq(port, pinmask) gpio_irq_mask((port), (pinmask), 1) + +static inline void gpio_set_pull(int port, unsigned pinmask, int state) +{ + if(state) + jz_set(GPIO_PULL(port), pinmask); + else + jz_clr(GPIO_PULL(port), pinmask); +} + +#endif /* __GPIO_X1000_H__ */ diff --git a/firmware/target/mips/ingenic_x1000/i2c-x1000.c b/firmware/target/mips/ingenic_x1000/i2c-x1000.c new file mode 100644 index 0000000000..8bf606227b --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/i2c-x1000.c @@ -0,0 +1,478 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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. + * + ****************************************************************************/ + +/* #define LOGF_ENABLE */ +#include "i2c-x1000.h" +#include "system.h" +#include "kernel.h" +#include "panic.h" +#include "logf.h" +#include "gpio-x1000.h" +#include "clk-x1000.h" +#include "irq-x1000.h" +#include "x1000/i2c.h" +#include "x1000/cpm.h" + +#if I2C_ASYNC_BUS_COUNT != 3 +# error "Wrong I2C_ASYNC_BUS_COUNT (should be 3)" +#endif + +#define FIFO_SIZE 64 /* Size of data FIFOs */ +#define FIFO_TX_THRESH 16 /* Wake up when TX FIFO gets to this level */ +#define FIFO_RX_SLACK 2 /* Slack space to leave, avoids RX FIFO overflow */ + +typedef struct i2c_x1000_bus { + /* Hardware channel, this is just equal to i2c-async bus number. */ + int chn; + + /* Buffer/count usage depends on what phase the bus is processing: + * + * - Phase1: writing out descriptor's buffer[0] for both READs and WRITEs. + * - Phase2: writing out descriptor's buffer[1] for WRITEs, or issuing a + * series of read requests for READs. + * + * In phase1, buffer[1] and count[1] are equal to the descriptor's copy. + * buffer[0] and count[0] get incremented/decremented as we send bytes. + * Phase1 is only visited if we actually need to send bytes; if there + * would be no data in this phase then __i2c_async_submit() sets up the + * driver to go directly to phase2. + * + * Phase2 begins after phase1 writes out its last byte, or if phase1 was + * skipped at submit time. For WRITEs phase2 is identical to phase1 so we + * copy over buffer[1] and count[1] to buffer[0] and count[0], and zero + * out buffer[1] and count[1]. + * + * For READs phase2 sets buffer[0] to NULL and count[0] equal to count[1]. + * Now count[0] counts the number of bytes left to request, and count[1] + * counts the number of bytes left to receive. i2c_x1000_fifo_write() sees + * that buffer[0] is NULL and sends read requests instead of data bytes. + * buffer[1] is advanced by i2c_x1000_fifo_read() we receive bytes. + */ + unsigned char* buffer[2]; + int count[2]; + bool phase1; + + /* Copied fields from descriptor */ + uint8_t bus_cond; + uint8_t tran_mode; + + /* Counter to keep track of when to send end conditions */ + int byte_cnt; + int byte_cnt_end; + + /* Current bus frequency, used to calculate timeout durations */ + long freq; + + /* Timeout to reset the bus in case of buggy devices */ + struct timeout tmo; + + /* Flag used to indicate a reset is processing */ + int resetting; +} i2c_x1000_bus; + +static i2c_x1000_bus i2c_x1000_busses[3]; + +static void i2c_x1000_fifo_write(i2c_x1000_bus* bus) +{ + int tx_free, tx_n; + + /* Get free space in FIFO */ + tx_free = FIFO_SIZE - REG_I2C_TXFLR(bus->chn); + + _again: + /* Leave some slack space when reading. If we submit a full FIFO's worth + * of read requests, there's a small chance that a byte "on the wire" is + * unaccounted for and causes an RX FIFO overrun. Slack space is meant to + * avoid this situation. + */ + if(bus->tran_mode == I2C_READ) { + tx_free -= FIFO_RX_SLACK; + if(tx_free <= 0) + goto _end; + } + + /* Calculate number of bytes needed to send/request */ + tx_n = MIN(tx_free, bus->count[0]); + + /* Account for bytes we're about to send/request */ + bus->count[0] -= tx_n; + tx_free -= tx_n; + + for(; tx_n > 0; --tx_n) { + bus->byte_cnt += 1; + + /* Read data byte or set read request bit */ + uint32_t dc = bus->buffer[0] ? *bus->buffer[0]++ : jz_orm(I2C_DC, CMD); + + /* Check for first byte & apply RESTART. + * Note the HW handles RESTART automatically when changing the + * direction of the transfer, so we don't need to check for that. + */ + if(bus->byte_cnt == 1 && (bus->bus_cond & I2C_RESTART)) + dc |= jz_orm(I2C_DC, RESTART); + + /* Check for last byte & apply STOP */ + if(bus->byte_cnt == bus->byte_cnt_end && (bus->bus_cond & I2C_STOP)) + dc |= jz_orm(I2C_DC, STOP); + + /* Add entry to FIFO */ + REG_I2C_DC(bus->chn) = dc; + } + + /* FIFO full and current phase still has data to send. + * Configure interrupt to fire when there's a good amount of free space. + */ + if(bus->count[0] > 0) { + _end: + REG_I2C_TXTL(bus->chn) = FIFO_TX_THRESH; + jz_writef(I2C_INTMSK(bus->chn), TXEMP(1), RXFL(0)); + return; + } + + /* Advance to second phase if needed */ + if(bus->phase1 && bus->count[1] > 0) { + bus->buffer[0] = bus->tran_mode == I2C_WRITE ? bus->buffer[1] : NULL; + bus->count[0] = bus->count[1]; + bus->phase1 = false; + + /* Submit further data if possible; else wait for TX space */ + if(tx_free > 0) + goto _again; + else + goto _end; + } + + /* All phases are done. Now we just need to wake up when the whole + * operation is complete, either by waiting for TX to drain or RX to + * fill to the appropriate level. */ + if(bus->tran_mode == I2C_WRITE) { + REG_I2C_TXTL(bus->chn) = 0; + jz_writef(I2C_INTMSK(bus->chn), TXEMP(1), RXFL(0)); + } else { + REG_I2C_RXTL(bus->chn) = bus->count[1] - 1; + jz_writef(I2C_INTMSK(bus->chn), TXEMP(0), RXFL(1)); + } +} + +static void i2c_x1000_fifo_read(i2c_x1000_bus* bus) +{ + /* Get number of bytes in the RX FIFO */ + int rx_n = REG_I2C_RXFLR(bus->chn); + + /* Shouldn't happen, but check just in case */ + if(rx_n > bus->count[1]) { + panicf("i2c_x1000(%d): expected %d bytes in RX fifo, got %d", + bus->chn, bus->count[1], rx_n); + } + + /* Fill buffer with data from FIFO */ + bus->count[1] -= rx_n; + for(; rx_n != 0; --rx_n) { + *bus->buffer[1]++ = jz_readf(I2C_DC(bus->chn), DAT); + } +} + +static void i2c_x1000_interrupt(i2c_x1000_bus* bus) +{ + int intr = REG_I2C_INTST(bus->chn); + int status = I2C_STATUS_OK; + + /* Bus error; we can't prevent this from happening. As I understand + * it, we cannot get a TXABT when the bus is idle, so it should be + * safe to leave this interrupt unmasked all the time. + */ + if(intr & jz_orm(I2C_INTST, TXABT)) { + logf("i2c_x1000(%d): got TXABT (%08lx)", + bus->chn, REG_I2C_ABTSRC(bus->chn)); + + REG_I2C_CTXABT(bus->chn); + status = I2C_STATUS_ERROR; + goto _done; + } + + /* FIFO errors shouldn't occur unless driver did something dumb */ + if(intr & jz_orm(I2C_INTST, RXUF, TXOF, RXOF)) { +#if 1 + panicf("i2c_x1000(%d): fifo error (%08x)", bus->chn, intr); +#else + /* This is how the error condition would be cleared */ + REG_I2C_CTXOF(bus->chn); + REG_I2C_CRXOF(bus->chn); + REG_I2C_CRXUF(bus->chn); + status = I2C_STATUS_ERROR; + goto _done; +#endif + } + + /* Read from FIFO on reads, and check if we have sent/received + * the expected amount of data. If so, complete the descriptor. */ + if(bus->tran_mode == I2C_READ) { + i2c_x1000_fifo_read(bus); + if(bus->count[1] == 0) + goto _done; + } else if(bus->count[0] == 0) { + goto _done; + } + + /* Still need to send or request data -- issue commands to FIFO */ + i2c_x1000_fifo_write(bus); + return; + + _done: + jz_writef(I2C_INTMSK(bus->chn), TXEMP(0), RXFL(0)); + timeout_cancel(&bus->tmo); + __i2c_async_complete_callback(bus->chn, status); +} + +void I2C0(void) +{ + i2c_x1000_interrupt(&i2c_x1000_busses[0]); +} + +void I2C1(void) +{ + i2c_x1000_interrupt(&i2c_x1000_busses[1]); +} + +void I2C2(void) +{ + i2c_x1000_interrupt(&i2c_x1000_busses[2]); +} + +static int i2c_x1000_bus_timeout(struct timeout* tmo) +{ + /* Buggy device is preventing the operation from completing, so we + * can't do much except reset the bus and hope for the best. Device + * drivers can aid us by detecting the TIMEOUT status we return and + * resetting the device to get it out of a bugged state. */ + + i2c_x1000_bus* bus = (i2c_x1000_bus*)tmo->data; + switch(bus->resetting) { + default: + /* Start of reset. Disable the controller */ + REG_I2C_INTMSK(bus->chn) = 0; + bus->resetting = 1; + jz_writef(I2C_ENABLE(bus->chn), ACTIVE(0)); + return 1; + case 1: + /* Check if controller is disabled yet */ + if(jz_readf(I2C_ENBST(bus->chn), ACTIVE)) + return 1; + + /* Wait 10 ms after disabling to give time for bus to clear */ + bus->resetting = 2; + return HZ/100; + case 2: + /* Re-enable the controller */ + bus->resetting = 3; + jz_writef(I2C_ENABLE(bus->chn), ACTIVE(1)); + return 1; + case 3: + /* Check that controller is enabled */ + if(jz_readf(I2C_ENBST(bus->chn), ACTIVE) == 0) + return 1; + + /* Reset complete */ + bus->resetting = 0; + jz_overwritef(I2C_INTMSK(bus->chn), RXFL(0), TXEMP(0), + TXABT(1), TXOF(1), RXOF(1), RXUF(1)); + __i2c_async_complete_callback(bus->chn, I2C_STATUS_TIMEOUT); + return 0; + } +} + +void __i2c_async_submit(int busnr, i2c_descriptor* desc) +{ + i2c_x1000_bus* bus = &i2c_x1000_busses[busnr]; + + if(desc->tran_mode == I2C_READ) { + if(desc->count[0] > 0) { + /* Handle initial write as phase1 */ + bus->buffer[0] = desc->buffer[0]; + bus->count[0] = desc->count[0]; + bus->phase1 = true; + } else { + /* No initial write, skip directly to phase2 */ + bus->buffer[0] = NULL; + bus->count[0] = desc->count[1]; + bus->phase1 = false; + } + + /* Set buffer/count for phase2 read */ + bus->buffer[1] = desc->buffer[1]; + bus->count[1] = desc->count[1]; + } else { + /* Writes always have to have buffer[0] populated; buffer[1] is + * allowed to be NULL (and thus count[1] = 0). This matches our + * phase logic so no need for anything special + */ + bus->buffer[0] = desc->buffer[0]; + bus->count[0] = desc->count[0]; + bus->buffer[1] = desc->buffer[1]; + bus->count[1] = desc->count[1]; + bus->phase1 = true; + } + + /* Save bus condition and transfer mode */ + bus->bus_cond = desc->bus_cond; + bus->tran_mode = desc->tran_mode; + + /* Byte counter is used to check for first and last byte and apply + * the requested end mode */ + bus->byte_cnt = 0; + bus->byte_cnt_end = desc->count[0] + desc->count[1]; + + /* Ensure interrupts are cleared */ + REG_I2C_CINT(busnr); + + /* Program target address */ + jz_overwritef(I2C_TAR(busnr), ADDR(desc->slave_addr & ~I2C_10BIT_ADDR), + 10BITS(desc->slave_addr & I2C_10BIT_ADDR ? 1 : 0)); + + /* Do the initial FIFO fill; this sets up the needed interrupts. */ + i2c_x1000_fifo_write(bus); + + /* Software timeout to deal with buggy slave devices that pull the bus + * high forever and leave us hanging. Use 100ms + whatever time should + * be needed to handle data transmission. Account for 9 bits per byte + * because of the ACKs necessary after each byte. + */ + long ticks = (HZ/10) + (HZ * 9 * bus->byte_cnt_end / bus->freq); + timeout_register(&bus->tmo, i2c_x1000_bus_timeout, ticks, (intptr_t)bus); +} + +void i2c_init(void) +{ + /* Initialize core */ + __i2c_async_init(); + + /* Initialize our bus data structures */ + for(int i = 0; i < 3; ++i) { + i2c_x1000_busses[i].chn = i; + i2c_x1000_busses[i].freq = 0; + i2c_x1000_busses[i].resetting = 0; + } +} + +/* Stuff only required during initialization is below, basically the same as + * the old driver except for how the IRQs are initially set up. */ + +static const struct { + int port; + unsigned pins; + int func; +} i2c_x1000_gpio_data[] = { + {GPIO_B, 3 << 23, GPIO_DEVICE(0)}, + {GPIO_C, 3 << 26, GPIO_DEVICE(0)}, + /* Note: I2C1 is also on the following pins (normally used by LCD) */ + /* {GPIO_A, 3 << 0, GPIO_DEVICE(2)}, */ + {GPIO_D, 3 << 0, GPIO_DEVICE(1)}, +}; + +static void i2c_x1000_gate(int chn, int gate) +{ + switch(chn) { + case 0: jz_writef(CPM_CLKGR, I2C0(gate)); break; + case 1: jz_writef(CPM_CLKGR, I2C1(gate)); break; + case 2: jz_writef(CPM_CLKGR, I2C2(gate)); break; + default: break; + } +} + +static void i2c_x1000_enable(int chn) +{ + /* Enable controller */ + jz_writef(I2C_ENABLE(chn), ACTIVE(1)); + while(jz_readf(I2C_ENBST(chn), ACTIVE) == 0); + + /* Set up interrutpts */ + jz_overwritef(I2C_INTMSK(chn), RXFL(0), TXEMP(0), + TXABT(1), TXOF(1), RXOF(1), RXUF(1)); + system_enable_irq(IRQ_I2C(chn)); +} + +static void i2c_x1000_disable(int chn) +{ + /* Disable interrupts */ + system_disable_irq(IRQ_I2C(chn)); + REG_I2C_INTMSK(chn) = 0; + + /* Disable controller */ + jz_writef(I2C_ENABLE(chn), ACTIVE(0)); + while(jz_readf(I2C_ENBST(chn), ACTIVE)); +} + +void i2c_x1000_set_freq(int chn, int freq) +{ + /* Store frequency */ + i2c_x1000_busses[chn].freq = freq; + + /* Disable the channel if previously active */ + i2c_x1000_gate(chn, 0); + if(jz_readf(I2C_ENBST(chn), ACTIVE) == 1) + i2c_x1000_disable(chn); + + /* Request to shut down the channel */ + if(freq == 0) { + i2c_x1000_gate(chn, 1); + return; + } + + /* Calculate timing parameters */ + unsigned pclk = clk_get(X1000_CLK_PCLK); + unsigned t_SU_DAT = pclk / (freq * 8); + unsigned t_HD_DAT = pclk / (freq * 12); + unsigned t_LOW = pclk / (freq * 2); + unsigned t_HIGH = pclk / (freq * 2); + if(t_SU_DAT > 1) t_SU_DAT -= 1; + if(t_SU_DAT > 255) t_SU_DAT = 255; + if(t_SU_DAT == 0) t_SU_DAT = 0; + if(t_HD_DAT > 0xffff) t_HD_DAT = 0xfff; + if(t_LOW < 8) t_LOW = 8; + if(t_HIGH < 6) t_HIGH = 6; + + /* Control register setting */ + unsigned reg = jz_orf(I2C_CON, SLVDIS(1), RESTART(1), MD(1)); + if(freq <= I2C_FREQ_100K) + reg |= jz_orf(I2C_CON, SPEED_V(100K)); + else + reg |= jz_orf(I2C_CON, SPEED_V(400K)); + + /* Write the new controller settings */ + jz_write(I2C_CON(chn), reg); + jz_write(I2C_SDASU(chn), t_SU_DAT); + jz_write(I2C_SDAHD(chn), t_HD_DAT); + if(freq <= I2C_FREQ_100K) { + jz_write(I2C_SLCNT(chn), t_LOW); + jz_write(I2C_SHCNT(chn), t_HIGH); + } else { + jz_write(I2C_FLCNT(chn), t_LOW); + jz_write(I2C_FHCNT(chn), t_HIGH); + } + + /* Claim pins */ + gpio_config(i2c_x1000_gpio_data[chn].port, + i2c_x1000_gpio_data[chn].pins, + i2c_x1000_gpio_data[chn].func); + + /* Enable the controller */ + i2c_x1000_enable(chn); +} diff --git a/firmware/target/mips/ingenic_x1000/i2c-x1000.h b/firmware/target/mips/ingenic_x1000/i2c-x1000.h new file mode 100644 index 0000000000..e76624d511 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/i2c-x1000.h @@ -0,0 +1,44 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 __I2C_X1000_H__ +#define __I2C_X1000_H__ + +#include "i2c-async.h" + +#define I2C_FREQ_100K 100000 +#define I2C_FREQ_400K 400000 + +extern void i2c_init(void); + +/* Configure the I2C controller prior to use. + * + * - freq: frequency of SCL, should be <= 400 KHz and >= 25 KHz + * - use I2C_FREQ_100K for 100 KHz + * - use I2C_FREQ_400K for 400 Khz + * - use 0 to disable the controller completely + * - frequencies below 25 KHz will violate timing constraints + * + * TODO: move this to the i2c-async API, it's simple enough + */ +extern void i2c_x1000_set_freq(int chn, int freq); + +#endif /* __I2C_X1000_H__ */ diff --git a/firmware/target/mips/ingenic_x1000/irq-x1000.h b/firmware/target/mips/ingenic_x1000/irq-x1000.h new file mode 100644 index 0000000000..849e436dcf --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/irq-x1000.h @@ -0,0 +1,115 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 __IRQ_X1000_H__ +#define __IRQ_X1000_H__ + +/* INTC(0) interrupts */ +#define IRQ0_DMIC 0 +#define IRQ0_AIC 1 +#define IRQ0_SFC 7 +#define IRQ0_SSI 8 +#define IRQ0_PDMA 10 +#define IRQ0_PDMAD 11 +#define IRQ0_GPIO3 14 +#define IRQ0_GPIO2 15 +#define IRQ0_GPIO1 16 +#define IRQ0_GPIO0 17 +#define IRQ0_OTG 21 +#define IRQ0_AES 23 +#define IRQ0_TCU2 25 +#define IRQ0_TCU1 26 +#define IRQ0_TCU0 27 +#define IRQ0_CIM 30 +#define IRQ0_LCD 31 + +/* INTC(1) interrupts */ +#define IRQ1_RTC 0 +#define IRQ1_MSC1 4 +#define IRQ1_MSC0 5 +#define IRQ1_SCC 6 +#define IRQ1_PCM 8 +#define IRQ1_HARB2 12 +#define IRQ1_HARB0 14 +#define IRQ1_CPM 15 +#define IRQ1_UART2 17 +#define IRQ1_UART1 18 +#define IRQ1_UART0 19 +#define IRQ1_DDR 20 +#define IRQ1_EFUSE 22 +#define IRQ1_MAC 23 +#define IRQ1_I2C2 26 +#define IRQ1_I2C1 27 +#define IRQ1_I2C0 28 +#define IRQ1_I2C(c) (28 - (c)) +#define IRQ1_PDMAM 29 +#define IRQ1_JPEG 30 + +/* Unified IRQ numbers */ +#define IRQ_DMIC IRQ0_DMIC +#define IRQ_AIC IRQ0_AIC +#define IRQ_SFC IRQ0_SFC +#define IRQ_SSI IRQ0_SSI +#define IRQ_PDMA IRQ0_PDMA +#define IRQ_PDMAD IRQ0_PDMAD +#define IRQ_GPIO3 IRQ0_GPIO3 +#define IRQ_GPIO2 IRQ0_GPIO2 +#define IRQ_GPIO1 IRQ0_GPIO1 +#define IRQ_GPIO0 IRQ0_GPIO0 +#define IRQ_OTG IRQ0_OTG +#define IRQ_AES IRQ0_AES +#define IRQ_TCU2 IRQ0_TCU2 +#define IRQ_TCU1 IRQ0_TCU1 +#define IRQ_TCU0 IRQ0_TCU0 +#define IRQ_CIM IRQ0_CIM +#define IRQ_LCD IRQ0_LCD +#define IRQ_RTC (32+IRQ1_RTC) +#define IRQ_MSC1 (32+IRQ1_MSC1) +#define IRQ_MSC0 (32+IRQ1_MSC0) +#define IRQ_SCC (32+IRQ1_SCC) +#define IRQ_PCM (32+IRQ1_PCM) +#define IRQ_HARB2 (32+IRQ1_HARB2) +#define IRQ_HARB0 (32+IRQ1_HARB0) +#define IRQ_CPM (32+IRQ1_CPM) +#define IRQ_UART2 (32+IRQ1_UART2) +#define IRQ_UART1 (32+IRQ1_UART1) +#define IRQ_UART0 (32+IRQ1_UART0) +#define IRQ_DDR (32+IRQ1_DDR) +#define IRQ_EFUSE (32+IRQ1_EFUSE) +#define IRQ_MAC (32+IRQ1_MAC) +#define IRQ_I2C2 (32+IRQ1_I2C2) +#define IRQ_I2C1 (32+IRQ1_I2C1) +#define IRQ_I2C0 (32+IRQ1_I2C0) +#define IRQ_I2C(c) (32+IRQ1_I2C(c)) +#define IRQ_PDMAM (32+IRQ1_PDMAM) +#define IRQ_JPEG (32+IRQ1_JPEG) +#define IRQ_GPIO(port, pin) (64 + 32*(port) + (pin)) + +#define IRQ_IS_GROUP0(irq) (((irq) & 0xffffff20) == 0x00) +#define IRQ_IS_GROUP1(irq) (((irq) & 0xffffff20) == 0x20) +#define IRQ_IS_GPIO(irq) ((irq) >= 64) + +#define IRQ_TO_GROUP0(irq) (irq) +#define IRQ_TO_GROUP1(irq) ((irq) - 32) +#define IRQ_TO_GPIO_PORT(irq) (((irq) - 64) >> 5) +#define IRQ_TO_GPIO_PIN(irq) (((irq) - 64) & 0x1f) + +#endif /* __IRQ_X1000_H__ */ diff --git a/firmware/target/mips/ingenic_x1000/kernel-x1000.c b/firmware/target/mips/ingenic_x1000/kernel-x1000.c new file mode 100644 index 0000000000..c8105a3446 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/kernel-x1000.c @@ -0,0 +1,74 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 "kernel.h" +#include "system.h" +#include "x1000/ost.h" + +/* TODO: implement a CPU frequency switching policy based on CPU utilization + * + * The basic assumption is that the workload consumes a fixed number of CPU + * cycles per second on average (= utilization), so we can set the frequency + * based on that value. Audio playback should fit this usage pattern well, so + * it's a good fit for Rockbox. + * + * It's easier to understand in terms of fluid flow -- we need to keep + * a reservoir of water topped up, CPU frequency is the inflow rate, and + * CPU utilization is the outflow rate. The goal is to avoid running dry + * and minimize the inflow rate. + * + * The only tricky part here is handing usage spikes -- CPU frequency has to + * increase faster than utilization or there's a risk of audio dropouts. + * + * Rockbox CPU boost could be used as a hint to scale up frequency faster. + * If that's not necessary to get good results, HAVE_ADJUSTABLE_CPU_FREQ can + * be disabled entirely. + */ + +#define CPU_IDLE_SAMPLES 100 + +void tick_start(unsigned interval_in_ms) +{ + jz_writef(OST_CTRL, PRESCALE1_V(BY_16)); + jz_write(OST_1DFR, interval_in_ms*(X1000_EXCLK_FREQ/16000)); + jz_write(OST_1CNT, 0); + jz_write(OST_1FLG, 0); + jz_write(OST_1MSK, 0); + jz_setf(OST_ENABLE, OST1); +} + +void OST(void) +{ + /* CPU idle time accounting */ + uint32_t now = __ost_read32(); + uint32_t div = now - __cpu_idle_reftick; + if(div != 0) { + uint32_t fraction = 1000 * __cpu_idle_ticks / div; + __cpu_idle_avg += fraction - __cpu_idle_avg / CPU_IDLE_SAMPLES; + __cpu_idle_cur = __cpu_idle_avg / CPU_IDLE_SAMPLES; + __cpu_idle_ticks = 0; + __cpu_idle_reftick = now; + } + + /* Call regular kernel tick */ + jz_write(OST_1FLG, 0); + call_tick_tasks(); +} diff --git a/firmware/target/mips/ingenic_x1000/lcd-x1000.c b/firmware/target/mips/ingenic_x1000/lcd-x1000.c new file mode 100644 index 0000000000..aadf93c8ff --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/lcd-x1000.c @@ -0,0 +1,477 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 "lcd.h" +#include "system.h" +#include "kernel.h" +#include "lcd-x1000.h" +#include "dma-x1000.h" +#include "irq-x1000.h" +#include "x1000/lcd.h" +#include "x1000/cpm.h" +#include <stdint.h> +#include <string.h> + +#define LCD_DMA_CMD_SOFINT (1 << 31) +#define LCD_DMA_CMD_EOFINT (1 << 30) +#define LCD_DMA_CMD_COMMAND (1 << 29) +#define LCD_DMA_CMD_FRM_EN (1 << 26) + +#define LCD_DMA_CNT_BPP_15BIT ((4 << 27)|(1<<30)) +#define LCD_DMA_CNT_BPP_16BIT (4 << 27) +#define LCD_DMA_CNT_BPP_18BIT_OR_24BIT (5 << 27) + +struct lcd_dma_desc { + uint32_t da; /* Next descriptor address */ + uint32_t sa; /* Source buffer address */ + uint32_t fid; /* Frame ID */ + uint32_t cmd; /* Command bits */ + uint32_t osz; /* OFFSIZE register */ + uint32_t pw; /* page width */ + uint32_t cnt; /* CNUM / CPOS, depending on LCD_DMA_CMD_COMMAND bit */ + uint32_t fsz; /* Frame size (set to 0 for commands) */ +} __attribute__((aligned(32))); + +/* We need two descriptors, one for framebuffer write command and one for + * frame data. Even if no command is needed we need a dummy command descriptor + * with cnt=0, or the hardware will refuse to transfer the frame data. + * + * First descriptor always has to be a command (lcd_dma_desc[0] here) or + * the hardware will give up. + */ +static struct lcd_dma_desc lcd_dma_desc[2]; + +/* Shadow copy of main framebuffer, needed to avoid tearing */ +static fb_data shadowfb[LCD_HEIGHT*LCD_WIDTH] __attribute__((aligned(64))); + +/* Signals DMA copy to shadow FB is done */ +static volatile int fbcopy_done; + +/* True if we're in sleep mode */ +static bool lcd_sleeping = false; + +/* Check if running with interrupts disabled (eg: panic screen) */ +#define lcd_panic_mode \ + UNLIKELY((read_c0_status() & 1) == 0) + +static void lcd_init_controller(const struct lcd_tgt_config* cfg) +{ + /* Set MCFG/MCFG_NEW according to target interface settings */ + unsigned mcfg = 0, mcfg_new = 0; + + switch(cfg->cmd_width) { + case 8: mcfg |= BF_LCD_MCFG_CWIDTH_V(8BIT); break; + case 9: mcfg |= BF_LCD_MCFG_CWIDTH_V(16BIT_OR_9BIT); break; + case 16: mcfg |= BF_LCD_MCFG_CWIDTH_V(16BIT_OR_9BIT); break; + case 18: mcfg |= BF_LCD_MCFG_CWIDTH_V(18BIT); break; + case 24: mcfg |= BF_LCD_MCFG_CWIDTH_V(24BIT); break; + default: break; + } + + if(cfg->cmd_width == 9) + mcfg_new |= BM_LCD_MCFG_NEW_CMD_9BIT; + + switch(cfg->bus_width) { + case 8: mcfg_new |= BF_LCD_MCFG_NEW_DWIDTH_V(8BIT); break; + case 9: mcfg_new |= BF_LCD_MCFG_NEW_DWIDTH_V(9BIT); break; + case 16: mcfg_new |= BF_LCD_MCFG_NEW_DWIDTH_V(16BIT); break; + case 18: mcfg_new |= BF_LCD_MCFG_NEW_DWIDTH_V(18BIT); break; + case 24: mcfg_new |= BF_LCD_MCFG_NEW_DWIDTH_V(24BIT); break; + default: break; + } + + if(lcd_tgt_config.use_serial) + mcfg_new |= jz_orf(LCD_MCFG_NEW, DTYPE_V(SERIAL), CTYPE_V(SERIAL)); + else + mcfg_new |= jz_orf(LCD_MCFG_NEW, DTYPE_V(PARALLEL), CTYPE_V(PARALLEL)); + + jz_vwritef(mcfg_new, LCD_MCFG_NEW, + 6800_MODE(lcd_tgt_config.use_6800_mode), + CSPLY(lcd_tgt_config.wr_polarity ? 0 : 1), + RSPLY(lcd_tgt_config.dc_polarity), + CLKPLY(lcd_tgt_config.clk_polarity)); + + /* Program the configuration. Note we cannot enable TE signal at + * this stage, because the panel will need to be configured first. + */ + jz_write(LCD_MCFG, mcfg); + jz_write(LCD_MCFG_NEW, mcfg_new); + jz_writef(LCD_MCTRL, NARROW_TE(0), TE_INV(0), NOT_USE_TE(1), + DCSI_SEL(0), MIPI_SLCD(0), FAST_MODE(1), GATE_MASK(0), + DMA_MODE(1), DMA_START(0), DMA_TX_EN(0)); + jz_writef(LCD_WTIME, DHTIME(0), DLTIME(0), CHTIME(0), CLTIME(0)); + jz_writef(LCD_TASH, TAH(0), TAS(0)); + jz_write(LCD_SMWT, 0); + + /* DMA settings */ + jz_writef(LCD_CTRL, BURST_V(64WORD), + EOFM(1), SOFM(0), IFUM(0), QDM(0), + BEDN(0), PEDN(0), ENABLE(0)); + jz_write(LCD_DAH, LCD_WIDTH); + jz_write(LCD_DAV, LCD_HEIGHT); +} + +static void lcd_fbcopy_dma_cb(int evt); + +static void lcd_init_descriptors(const struct lcd_tgt_config* cfg) +{ + struct lcd_dma_desc* desc = &lcd_dma_desc[0]; + int cmdsize = cfg->dma_wr_cmd_size / 4; + + /* Set up the command descriptor */ + desc[0].da = PHYSADDR(&desc[1]); + desc[0].sa = PHYSADDR(cfg->dma_wr_cmd_buf); + desc[0].fid = 0xc0; + desc[0].cmd = LCD_DMA_CMD_COMMAND | cmdsize; + desc[0].osz = 0; + desc[0].pw = 0; + desc[0].fsz = 0; + switch(cfg->cmd_width) { + case 8: desc[0].cnt = 4*cmdsize; break; + case 9: + case 16: desc[0].cnt = 2*cmdsize; break; + case 18: + case 24: desc[0].cnt = cmdsize; break; + default: break; + } + + /* Set up the frame descriptor */ + desc[1].da = PHYSADDR(&desc[0]); + desc[1].sa = PHYSADDR(shadowfb); + desc[1].fid = 0xf0; + desc[1].cmd = LCD_DMA_CMD_EOFINT | LCD_DMA_CMD_FRM_EN | + (LCD_WIDTH * LCD_HEIGHT * sizeof(fb_data) / 4); + desc[1].osz = 0; + desc[1].pw = 0; + desc[1].fsz = (LCD_WIDTH - 1) | ((LCD_HEIGHT - 1) << 12); +#if LCD_DEPTH == 16 + desc[1].cnt = LCD_DMA_CNT_BPP_16BIT; +#elif LCD_DEPTH == 24 + desc[1].cnt = LCD_DMA_CNT_BPP_18BIT_OR_24BIT; +#else +# error "unsupported LCD bit depth" +#endif + + /* Commit LCD DMA descriptors */ + commit_dcache_range(&desc[0], 2*sizeof(struct lcd_dma_desc)); + + /* Set fbcopy channel callback */ + dma_set_callback(DMA_CHANNEL_FBCOPY, lcd_fbcopy_dma_cb); +} + +static void lcd_fbcopy_dma_cb(int evt) +{ + (void)evt; + fbcopy_done = 1; +} + +static void lcd_fbcopy_dma_run(dma_desc* d) +{ + if(lcd_panic_mode) { + /* Can't use DMA if interrupts are off, so just do a memcpy(). + * Doesn't need to be efficient, since AFAIK the panic screen is + * the only place that can update the LCD with interrupts disabled. */ + memcpy(shadowfb, FBADDR(0, 0), LCD_WIDTH*LCD_HEIGHT*sizeof(fb_data)); + commit_dcache(); + return; + } + + commit_dcache_range(d, sizeof(struct dma_desc)); + + /* Start the transfer */ + fbcopy_done = 0; + REG_DMA_CHN_DA(DMA_CHANNEL_FBCOPY) = PHYSADDR(d); + jz_writef(DMA_CHN_CS(DMA_CHANNEL_FBCOPY), DES8(1), NDES(0)); + jz_set(DMA_DB, 1 << DMA_CHANNEL_FBCOPY); + jz_writef(DMA_CHN_CS(DMA_CHANNEL_FBCOPY), CTE(1)); + + while(!fbcopy_done); +} + +static void lcd_fbcopy_dma_full(void) +{ + dma_desc d; + d.cm = jz_orf(DMA_CHN_CM, SAI(1), DAI(1), RDIL(9), + SP_V(32BIT), DP_V(32BIT), TSZ_V(AUTO), + STDE(0), TIE(1), LINK(0)); + d.sa = PHYSADDR(FBADDR(0, 0)); + d.ta = PHYSADDR(shadowfb); + d.tc = LCD_WIDTH * LCD_HEIGHT * sizeof(fb_data); + d.sd = 0; + d.rt = jz_orf(DMA_CHN_RT, TYPE_V(AUTO)); + d.pad0 = 0; + d.pad1 = 0; + lcd_fbcopy_dma_run(&d); +} + +/* NOTE: DMA stride mode can only transfer up to 255 blocks at once. + * + * - for LCD_STRIDEFORMAT == VERTICAL_STRIDE, keep width <= 255 + * - for LCD_STRIDEFORMAT == HORIZONTAL_STRIDE, keep height <= 255 + */ +static void lcd_fbcopy_dma_partial1(int x, int y, int width, int height) +{ + int stride = STRIDE_MAIN(LCD_WIDTH - width, LCD_HEIGHT - height); + + dma_desc d; + d.cm = jz_orf(DMA_CHN_CM, SAI(1), DAI(1), RDIL(9), + SP_V(32BIT), DP_V(32BIT), TSZ_V(AUTO), + STDE(stride ? 1 : 0), TIE(1), LINK(0)); + d.sa = PHYSADDR(FBADDR(x, y)); + d.ta = PHYSADDR(&shadowfb[STRIDE_MAIN(y * LCD_WIDTH + x, + x * LCD_HEIGHT + y)]); + d.rt = jz_orf(DMA_CHN_RT, TYPE_V(AUTO)); + d.pad0 = 0; + d.pad1 = 0; + + if(stride) { + stride *= sizeof(fb_data); + d.sd = (stride << 16) | stride; + d.tc = (STRIDE_MAIN(height, width) << 16) | + (STRIDE_MAIN(width, height) * sizeof(fb_data)); + } else { + d.sd = 0; + d.tc = width * height * sizeof(fb_data); + } + + lcd_fbcopy_dma_run(&d); +} + +#if STRIDE_MAIN(LCD_HEIGHT, LCD_WIDTH) > 255 +static void lcd_fbcopy_dma_partial(int x, int y, int width, int height) +{ + do { + int count = MIN(STRIDE_MAIN(height, width), 255); + + lcd_fbcopy_dma_partial1(x, y, STRIDE_MAIN(width, count), + STRIDE_MAIN(count, height)); + + STRIDE_MAIN(height, width) -= count; + STRIDE_MAIN(y, x) += count; + } while(STRIDE_MAIN(height, width) != 0); +} +#else +# define lcd_fbcopy_dma_partial lcd_fbcopy_dma_partial1 +#endif + +static void lcd_dma_start(void) +{ + /* Set format conversion bit, seems necessary for DMA mode */ + jz_writef(LCD_MCFG_NEW, FMT_CONV(1)); + + /* Program vsync configuration */ + jz_writef(LCD_MCTRL, NARROW_TE(lcd_tgt_config.te_narrow), + TE_INV(lcd_tgt_config.te_polarity ? 0 : 1), + NOT_USE_TE(lcd_tgt_config.te_enable ? 0 : 1)); + + /* Begin DMA transfer. Need to start a dummy frame or else we will + * not be able to pass lcd_wait_frame() at the first lcd_update(). */ + jz_write(LCD_STATE, 0); + jz_write(LCD_DA, PHYSADDR(&lcd_dma_desc[0])); + jz_writef(LCD_MCTRL, DMA_MODE(1), DMA_START(1), DMA_TX_EN(1)); + jz_writef(LCD_CTRL, ENABLE(1)); +} + +static void lcd_dma_stop(void) +{ + /* Stop the DMA transfer */ + jz_writef(LCD_CTRL, ENABLE(0)); + jz_writef(LCD_MCTRL, DMA_TX_EN(0)); + + /* Wait for disable to take effect */ + while(jz_readf(LCD_STATE, QD) == 0); + jz_writef(LCD_STATE, QD(0)); + + /* Clear format conversion bit, disable vsync */ + jz_writef(LCD_MCFG_NEW, FMT_CONV(0)); + jz_writef(LCD_MCTRL, NARROW_TE(0), TE_INV(0), NOT_USE_TE(1)); +} + +static bool lcd_wait_frame(void) +{ + /* Bail out if DMA is not enabled */ + int irq = disable_irq_save(); + int bit = jz_readf(LCD_CTRL, ENABLE); + restore_irq(irq); + if(!bit) + return false; + + /* Usual case -- wait for EOF, wait for FIFO to drain, clear EOF */ + while(jz_readf(LCD_STATE, EOF) == 0); + while(jz_readf(LCD_MSTATE, BUSY)); + jz_writef(LCD_STATE, EOF(0)); + return true; +} + +static void lcd_send(uint32_t d) +{ + while(jz_readf(LCD_MSTATE, BUSY)); + REG_LCD_MDATA = d; +} + +void lcd_set_clock(x1000_clk_t clk, uint32_t freq) +{ + uint32_t in_freq = clk_get(clk); + uint32_t div = clk_calc_div(in_freq, freq); + + jz_writef(CPM_LPCDR, CE(1), CLKDIV(div - 1), + CLKSRC(clk == X1000_CLK_MPLL ? 1 : 0)); + while(jz_readf(CPM_LPCDR, BUSY)); + jz_writef(CPM_LPCDR, CE(0)); +} + +void lcd_exec_commands(const uint32_t* cmdseq) +{ + while(*cmdseq != LCD_INSTR_END) { + uint32_t instr = *cmdseq++; + uint32_t d = 0; + switch(instr) { + case LCD_INSTR_CMD: + d = jz_orf(LCD_MDATA, TYPE_V(CMD)); + /* fallthrough */ + + case LCD_INSTR_DAT: + d |= *cmdseq++; + lcd_send(d); + break; + + case LCD_INSTR_UDELAY: + udelay(*cmdseq++); + break; + + default: + break; + } + } +} + +void lcd_init_device(void) +{ + jz_writef(CPM_CLKGR, LCD(0)); + + lcd_init_controller(&lcd_tgt_config); + lcd_init_descriptors(&lcd_tgt_config); + + lcd_tgt_enable(true); + + lcd_dma_start(); +} + +#ifdef HAVE_LCD_SHUTDOWN +void lcd_shutdown(void) +{ + if(lcd_sleeping) + lcd_tgt_sleep(false); + else if(jz_readf(LCD_CTRL, ENABLE)) + lcd_dma_stop(); + + lcd_tgt_enable(false); + jz_writef(CPM_CLKGR, LCD(1)); +} +#endif + +#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) +bool lcd_active(void) +{ + return jz_readf(LCD_CTRL, ENABLE); +} + +void lcd_enable(bool en) +{ + /* Must disable IRQs to turn off the running LCD */ + int irq = disable_irq_save(); + int bit = jz_readf(LCD_CTRL, ENABLE); + if(bit && !en) + lcd_dma_stop(); + restore_irq(irq); + + /* Deal with sleep mode */ +#ifdef LCD_X1000_FASTSLEEP + if(bit && !en) { + lcd_tgt_sleep(true); + lcd_sleeping = true; + } else +#endif + if(!bit && en && lcd_sleeping) { + lcd_tgt_sleep(false); + lcd_sleeping = false; + } + + /* Handle turning the LCD back on */ + if(!bit && en) + lcd_dma_start(); +} +#endif + +#if defined(HAVE_LCD_SLEEP) +#if defined(LCD_X1000_FASTSLEEP) +# error "Do not define HAVE_LCD_SLEEP if target has LCD_X1000_FASTSLEEP" +#endif + +void lcd_sleep(void) +{ + if(!lcd_sleeping) { + lcd_enable(false); + lcd_tgt_sleep(true); + lcd_sleeping = true; + } +} +#endif + +void lcd_update(void) +{ + if(!lcd_wait_frame()) + return; + + commit_dcache(); + lcd_fbcopy_dma_full(); + jz_writef(LCD_MCTRL, DMA_START(1), DMA_MODE(1)); +} + +void lcd_update_rect(int x, int y, int width, int height) +{ + /* Clamp the coordinates */ + if(x < 0) { + width += x; + x = 0; + } + + if(y < 0) { + height += y; + y = 0; + } + + if(width > LCD_WIDTH - x) + width = LCD_WIDTH - x; + + if(height > LCD_HEIGHT - y) + height = LCD_HEIGHT - y; + + if(width < 0 || height < 0) + return; + + if(!lcd_wait_frame()) + return; + + commit_dcache(); + lcd_fbcopy_dma_partial(x, y, width, height); + jz_writef(LCD_MCTRL, DMA_START(1), DMA_MODE(1)); +} diff --git a/firmware/target/mips/ingenic_x1000/lcd-x1000.h b/firmware/target/mips/ingenic_x1000/lcd-x1000.h new file mode 100644 index 0000000000..96085ac207 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/lcd-x1000.h @@ -0,0 +1,110 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 __LCD_X1000_H__ +#define __LCD_X1000_H__ + +/* NOTICE: if adding LCD support for a new X1000 target, please take a look + * at the implementation in case there's any difficulties; there may be some + * parts that need adjusting. The X1000 LCD interface is poorly documented + * and it might be necessary to change some settings by trial and error to + * match the panel. */ + +#include "clk-x1000.h" +#include <stdbool.h> + +#define LCD_INSTR_CMD 0 +#define LCD_INSTR_DAT 1 +#define LCD_INSTR_UDELAY 2 +#define LCD_INSTR_END 3 + +struct lcd_tgt_config { + /* Data bus width, in bits */ + int bus_width: 8; + + /* Command bus width, in bits */ + int cmd_width: 8; + + /* 1 = use 6800 timings, 0 = use 8080 timings */ + int use_6800_mode: 1; + + /* 1 = serial interface, 0 = parallel interface */ + int use_serial: 1; + + /* Clock active edge: 0 = falling edge, 1 = rising edge */ + int clk_polarity: 1; + + /* DC pin levels: 1 = data high, command low; 0 = data low, command high */ + int dc_polarity: 1; + + /* WR pin level during idle: 1 = keep high; 0 = keep low */ + int wr_polarity: 1; + + /* 1 to enable vsync, so DMA transfer is synchronized with TE signal */ + int te_enable: 1; + + /* Active level of TE signal: 1 = high, 0 = low */ + int te_polarity: 1; + + /* 1 = support narrow TE signal (<=3 pixel clocks); 0 = don't support */ + int te_narrow: 1; + + /* Commands used to initiate a framebuffer write. Buffer must be + * aligned to 64-byte boundary and size must be a multiple of 4, + * regardless of the command bus width. */ + const void* dma_wr_cmd_buf; + size_t dma_wr_cmd_size; +}; + +/* Static configuration for the target's LCD, must be defined by target. */ +extern const struct lcd_tgt_config lcd_tgt_config; + +/* Set the pixel clock. Valid clock sources are SCLK_A and MPLL. */ +extern void lcd_set_clock(x1000_clk_t clksrc, uint32_t freq); + +/* Execute a sequence of LCD commands. Should only be called from + * lcd_tgt_ctl_enable() and lcd_tgt_ctl_sleep(). + * + * The array should be a list of pairs (instr, arg), with LCD_INSTR_END + * as the last entry. + * + * - LCD_INSTR_CMD, cmd: issue command write of 'cmd' + * - LCD_INSTR_DAT, dat: issue data write of 'dat' + * - LCD_INSTR_UDELAY, us: call udelay(us) + */ +extern void lcd_exec_commands(const uint32_t* cmdseq); + +/* Enable/disable the LCD controller. + * + * - On enabling: power on the LCD, set the pixel clock with lcd_set_clock(), + * and use lcd_exec_commands() to send any needed initialization commands. + * + * - On disabling: use lcd_exec_commands() to send shutdown commands to the + * controller and disable the LCD power supply. + */ +extern void lcd_tgt_enable(bool on); + +/* Enter or exit sleep mode to save power, normally by sending the necessary + * commands with lcd_exec_commands(). + */ +extern void lcd_tgt_sleep(bool sleep); + +#endif /* __LCD_X1000_H__ */ diff --git a/firmware/target/mips/ingenic_x1000/msc-x1000.c b/firmware/target/mips/ingenic_x1000/msc-x1000.c new file mode 100644 index 0000000000..62aa76988c --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/msc-x1000.c @@ -0,0 +1,904 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 "panic.h" +#include "msc-x1000.h" +#include "gpio-x1000.h" +#include "irq-x1000.h" +#include "clk-x1000.h" +#include "x1000/msc.h" +#include "x1000/cpm.h" +#include <string.h> +#include <stddef.h> + +/* #define LOGF_ENABLE */ +#include "logf.h" + +/* TODO - this needs some auditing to better handle errors + * + * There should be a clearer code path involving errors. Especially we should + * ensure that removing the card always resets the driver to a sane state. + */ + +static const msc_config msc_configs[] = { +#ifdef FIIO_M3K +#define MSC_CLOCK_SOURCE X1000_CLK_SCLK_A +#define msc0_cd_interrupt GPIOB06 + { + .msc_nr = 0, + .msc_type = MSC_TYPE_SD, + .bus_width = 4, + .label = "microSD", + .cd_gpio = {GPIO_B, 1 << 6, 0}, + }, +#else +# error "Please add X1000 MSC config" +#endif + {.msc_nr = -1}, +}; + +static const msc_config* msc_lookup_config(int msc) +{ + for(int i = 0; i < MSC_COUNT; ++i) + if(msc_configs[i].msc_nr == msc) + return &msc_configs[i]; + return NULL; +} + +static msc_drv msc_drivers[MSC_COUNT]; + +/* --------------------------------------------------------------------------- + * Initialization + */ + +static void msc_gate_clock(int msc, bool gate) +{ + int bit; + if(msc == 0) + bit = BM_CPM_CLKGR_MSC0; + else + bit = BM_CPM_CLKGR_MSC1; + + if(gate) + REG_CPM_CLKGR |= bit; + else + REG_CPM_CLKGR &= ~bit; +} + +static void msc_init_one(msc_drv* d, int msc) +{ + /* Lookup config */ + d->drive_nr = -1; + d->config = msc_lookup_config(msc); + if(!d->config) { + d->msc_nr = -1; + return; + } + + /* Initialize driver state */ + d->msc_nr = msc; + d->driver_flags = 0; + d->clk_status = 0; + d->cmdat_def = jz_orf(MSC_CMDAT, RTRG_V(GE32), TTRG_V(LE32)); + d->req = NULL; + d->iflag_done = 0; + d->card_present = 1; + d->req_running = 0; + mutex_init(&d->lock); + semaphore_init(&d->cmd_done, 1, 0); + + /* Ensure correct clock source */ + jz_writef(CPM_MSC0CDR, CE(1), CLKDIV(0), + CLKSRC(MSC_CLOCK_SOURCE == X1000_CLK_MPLL ? 1 : 0)); + while(jz_readf(CPM_MSC0CDR, BUSY)); + jz_writef(CPM_MSC0CDR, CE(0)); + + /* Initialize the hardware */ + msc_gate_clock(msc, false); + msc_full_reset(d); + system_enable_irq(msc == 0 ? IRQ_MSC0 : IRQ_MSC1); + + /* Configure bus pins */ + int port, device; + unsigned pins; + if(msc == 0) { + port = GPIO_A; + device = 1; + switch(d->config->bus_width) { + case 8: pins = 0x3ff << 16; break; + case 4: pins = 0x03f << 20; break; + case 1: pins = 0x007 << 23; break; + default: pins = 0; break; + } + } else { + port = GPIO_C; + device = 0; + switch(d->config->bus_width) { + case 4: pins = 0x3f; break; + case 1: pins = 0x07; break; + default: pins = 0; break; + } + } + + gpio_config(port, pins, GPIO_DEVICE(device)); + + /* Setup the card detect IRQ */ + if(d->config->cd_gpio.pin) { + port = d->config->cd_gpio.port; + pins = d->config->cd_gpio.pin; + int level = (REG_GPIO_PIN(port) & pins) ? 1 : 0; + if(level != d->config->cd_gpio.active_level) + d->card_present = 0; + + gpio_config(port, pins, GPIO_IRQ_EDGE(level ? 0 : 1)); + gpio_enable_irq(port, pins); + } +} + +void msc_init(void) +{ + /* Only do this once -- each storage subsystem calls us in its init */ + static bool done = false; + if(done) + return; + done = true; + + /* Set up each MSC driver according to msc_configs */ + for(int i = 0; i < MSC_COUNT; ++i) + msc_init_one(&msc_drivers[i], i); +} + +msc_drv* msc_get(int type, int index) +{ + for(int i = 0, m = 0; i < MSC_COUNT; ++i) { + if(msc_drivers[i].config == NULL) + continue; + if(type == MSC_TYPE_ANY || msc_drivers[i].config->msc_type == type) + if(index == m++) + return &msc_drivers[i]; + } + + return NULL; +} + +msc_drv* msc_get_by_drive(int drive_nr) +{ + for(int i = 0; i < MSC_COUNT; ++i) + if(msc_drivers[i].drive_nr == drive_nr) + return &msc_drivers[i]; + return NULL; +} + +void msc_lock(msc_drv* d) +{ + mutex_lock(&d->lock); +} + +void msc_unlock(msc_drv* d) +{ + mutex_unlock(&d->lock); +} + +void msc_full_reset(msc_drv* d) +{ + msc_lock(d); + msc_set_clock_mode(d, MSC_CLK_AUTOMATIC); + msc_set_speed(d, MSC_SPEED_INIT); + msc_set_width(d, 1); + msc_ctl_reset(d); + d->driver_flags = 0; + memset(&d->cardinfo, 0, sizeof(tCardInfo)); + msc_unlock(d); +} + +bool msc_card_detect(msc_drv* d) +{ + if(!d->config->cd_gpio.pin) + return true; + + int l = REG_GPIO_PIN(d->config->cd_gpio.port) & d->config->cd_gpio.pin; + l = l ? 1 : 0; + return l == d->config->cd_gpio.active_level; +} + +/* --------------------------------------------------------------------------- + * Controller API + */ + +void msc_ctl_reset(msc_drv* d) +{ + /* Ingenic code suggests a reset changes clkrt */ + int clkrt = REG_MSC_CLKRT(d->msc_nr); + + /* Send reset -- bit is NOT self clearing */ + jz_overwritef(MSC_CTRL(d->msc_nr), RESET(1)); + udelay(100); + jz_writef(MSC_CTRL(d->msc_nr), RESET(0)); + + /* Verify reset in the status register */ + long deadline = current_tick + HZ; + while(jz_readf(MSC_STAT(d->msc_nr), IS_RESETTING) && + current_tick < deadline) { + sleep(1); + } + + /* Ensure the clock state is as expected */ + if(d->clk_status & MSC_CLKST_AUTO) + jz_writef(MSC_LPM(d->msc_nr), ENABLE(1)); + else if(d->clk_status & MSC_CLKST_ENABLE) + jz_overwritef(MSC_CTRL(d->msc_nr), CLOCK_V(START)); + else + jz_overwritef(MSC_CTRL(d->msc_nr), CLOCK_V(STOP)); + + /* Clear and mask interrupts */ + REG_MSC_IMASK(d->msc_nr) = 0xffffffff; + REG_MSC_IFLAG(d->msc_nr) = 0xffffffff; + + /* Restore clkrt */ + REG_MSC_CLKRT(d->msc_nr) = clkrt; +} + +void msc_set_clock_mode(msc_drv* d, int mode) +{ + int cur_mode = (d->clk_status & MSC_CLKST_AUTO) ? MSC_CLK_AUTOMATIC + : MSC_CLK_MANUAL; + if(mode == cur_mode) + return; + + d->clk_status &= ~MSC_CLKST_ENABLE; + if(mode == MSC_CLK_AUTOMATIC) { + d->clk_status |= MSC_CLKST_AUTO; + jz_writef(MSC_CTRL(d->msc_nr), CLOCK_V(STOP)); + jz_writef(MSC_LPM(d->msc_nr), ENABLE(1)); + } else { + d->clk_status &= ~MSC_CLKST_AUTO; + jz_writef(MSC_LPM(d->msc_nr), ENABLE(0)); + jz_writef(MSC_CTRL(d->msc_nr), CLOCK_V(STOP)); + } +} + +void msc_enable_clock(msc_drv* d, bool enable) +{ + if(d->clk_status & MSC_CLKST_AUTO) + return; + + bool is_enabled = (d->clk_status & MSC_CLKST_ENABLE); + if(enable == is_enabled) + return; + + if(enable) { + jz_writef(MSC_CTRL(d->msc_nr), CLOCK_V(START)); + d->clk_status |= MSC_CLKST_ENABLE; + } else { + jz_writef(MSC_CTRL(d->msc_nr), CLOCK_V(STOP)); + d->clk_status &= ~MSC_CLKST_ENABLE; + } +} + +void msc_set_speed(msc_drv* d, int rate) +{ + /* Shut down clock while we change frequencies */ + if(d->clk_status & MSC_CLKST_ENABLE) + jz_writef(MSC_CTRL(d->msc_nr), CLOCK_V(STOP)); + + /* Wait for clock to go idle */ + while(jz_readf(MSC_STAT(d->msc_nr), CLOCK_EN)) + sleep(1); + + /* freq1 is output by MSCxDIV; freq2 is output by MSC_CLKRT */ + uint32_t freq1 = rate; + uint32_t freq2 = rate; + if(freq1 < MSC_SPEED_FAST) + freq1 = MSC_SPEED_FAST; + + /* Handle MSCxDIV */ + uint32_t src_freq = clk_get(MSC_CLOCK_SOURCE) / 2; + uint32_t div = clk_calc_div(src_freq, freq1); + if(d->msc_nr == 0) { + jz_writef(CPM_MSC0CDR, CE(1), CLKDIV(div - 1)); + while(jz_readf(CPM_MSC0CDR, BUSY)); + jz_writef(CPM_MSC0CDR, CE(0)); + } else { + jz_writef(CPM_MSC1CDR, CE(1), CLKDIV(div - 1)); + while(jz_readf(CPM_MSC1CDR, BUSY)); + jz_writef(CPM_MSC1CDR, CE(0)); + } + + /* Handle MSC_CLKRT */ + uint32_t clkrt = clk_calc_shift(src_freq/div, freq2); + REG_MSC_CLKRT(d->msc_nr) = clkrt; + + /* Handle frequency dependent timing settings + * TODO - these settings might be SD specific... + */ + uint32_t out_freq = (src_freq/div) >> clkrt; + if(out_freq > MSC_SPEED_FAST) { + jz_writef(MSC_LPM(d->msc_nr), + DRV_SEL_V(RISE_EDGE_DELAY_QTR_PHASE), + SMP_SEL_V(RISE_EDGE_DELAYED)); + } else { + jz_writef(MSC_LPM(d->msc_nr), + DRV_SEL_V(FALL_EDGE), + SMP_SEL_V(RISE_EDGE)); + } + + /* Restart clock if it was running before */ + if(d->clk_status & MSC_CLKST_ENABLE) + jz_writef(MSC_CTRL(d->msc_nr), CLOCK_V(START)); +} + +void msc_set_width(msc_drv* d, int width) +{ + /* Bus width is controlled per command with MSC_CMDAT. */ + if(width == 8) + jz_vwritef(d->cmdat_def, MSC_CMDAT, BUS_WIDTH_V(8BIT)); + else if(width == 4) + jz_vwritef(d->cmdat_def, MSC_CMDAT, BUS_WIDTH_V(4BIT)); + else + jz_vwritef(d->cmdat_def, MSC_CMDAT, BUS_WIDTH_V(1BIT)); +} + +/* --------------------------------------------------------------------------- + * Request API + */ + +/* Note -- this must only be called with IRQs disabled */ +static void msc_finish_request(msc_drv* d, int status) +{ + REG_MSC_IMASK(d->msc_nr) = 0xffffffff; + REG_MSC_IFLAG(d->msc_nr) = 0xffffffff; + if(d->req->flags & MSC_RF_DATA) + jz_writef(MSC_DMAC(d->msc_nr), ENABLE(0)); + + d->req->status = status; + d->req_running = 0; + d->iflag_done = 0; + timeout_cancel(&d->cmd_tmo); + semaphore_release(&d->cmd_done); +} + +static int msc_req_timeout(struct timeout* tmo) +{ + msc_drv* d = (msc_drv*)tmo->data; + msc_async_abort(d, MSC_REQ_LOCKUP); + return 0; +} + +void msc_async_start(msc_drv* d, msc_req* r) +{ + /* Determined needed cmdat and interrupts */ + unsigned cmdat = d->cmdat_def; + d->iflag_done = jz_orm(MSC_IFLAG, END_CMD_RES); + + cmdat |= jz_orf(MSC_CMDAT, RESP_FMT(r->resptype & ~MSC_RESP_BUSY)); + if(r->resptype & MSC_RESP_BUSY) + cmdat |= jz_orm(MSC_CMDAT, BUSY); + + if(r->flags & MSC_RF_INIT) + cmdat |= jz_orm(MSC_CMDAT, INIT); + + if(r->flags & MSC_RF_DATA) { + cmdat |= jz_orm(MSC_CMDAT, DATA_EN); + if(r->flags & MSC_RF_PROG) + d->iflag_done = jz_orm(MSC_IFLAG, WR_ALL_DONE); + else + d->iflag_done = jz_orm(MSC_IFLAG, DMA_DATA_DONE); + } + + if(r->flags & MSC_RF_WRITE) + cmdat |= jz_orm(MSC_CMDAT, WRITE_READ); + + if(r->flags & MSC_RF_AUTO_CMD12) + cmdat |= jz_orm(MSC_CMDAT, AUTO_CMD12); + + if(r->flags & MSC_RF_ABORT) + cmdat |= jz_orm(MSC_CMDAT, IO_ABORT); + + unsigned imask = jz_orm(MSC_IMASK, + CRC_RES_ERROR, CRC_READ_ERROR, CRC_WRITE_ERROR, + TIME_OUT_RES, TIME_OUT_READ, END_CMD_RES); + imask |= d->iflag_done; + + /* Program the controller */ + if(r->flags & MSC_RF_DATA) { + REG_MSC_NOB(d->msc_nr) = r->nr_blocks; + REG_MSC_BLKLEN(d->msc_nr) = r->block_len; + } + + REG_MSC_CMD(d->msc_nr) = r->command; + REG_MSC_ARG(d->msc_nr) = r->argument; + REG_MSC_CMDAT(d->msc_nr) = cmdat; + + REG_MSC_IFLAG(d->msc_nr) = imask; + REG_MSC_IMASK(d->msc_nr) &= ~imask; + + if(r->flags & MSC_RF_DATA) { + d->dma_desc.nda = 0; + d->dma_desc.mem = PHYSADDR(r->data); + d->dma_desc.len = r->nr_blocks * r->block_len; + d->dma_desc.cmd = 2; /* ID=0, ENDI=1, LINK=0 */ + commit_dcache_range(&d->dma_desc, sizeof(d->dma_desc)); + + if(r->flags & MSC_RF_WRITE) + commit_dcache_range(r->data, d->dma_desc.len); + else + discard_dcache_range(r->data, d->dma_desc.len); + + /* TODO - should use MODE_SEL bit? what value of INCR? */ + unsigned long addr_off = ((unsigned long)r->data) & 3; + jz_writef(MSC_DMAC(d->msc_nr), MODE_SEL(0), INCR(0), DMASEL(0), + ALIGN_EN(addr_off != 0 ? 1 : 0), ADDR_OFFSET(addr_off)); + REG_MSC_DMANDA(d->msc_nr) = PHYSADDR(&d->dma_desc); + } + + /* Begin processing */ + d->req = r; + d->req_running = 1; + jz_writef(MSC_CTRL(d->msc_nr), START_OP(1)); + if(r->flags & MSC_RF_DATA) + jz_writef(MSC_DMAC(d->msc_nr), ENABLE(1)); + + /* TODO: calculate a suitable lower value for the lockup timeout. + * + * The SD spec defines timings based on the number of blocks transferred, + * see sec. 4.6.2 "Read, write, and erase timeout conditions". This should + * reduce the long delays which happen if errors occur. + * + * Also need to check if registers MSC_RDTO / MSC_RESTO are correctly set. + */ + timeout_register(&d->cmd_tmo, msc_req_timeout, 10*HZ, (intptr_t)d); +} + +void msc_async_abort(msc_drv* d, int status) +{ + int irq = disable_irq_save(); + if(d->req_running) { + logf("msc%d: async abort status:%d", d->msc_nr, status); + msc_finish_request(d, status); + } + + restore_irq(irq); +} + +int msc_async_wait(msc_drv* d, int timeout) +{ + if(semaphore_wait(&d->cmd_done, timeout) == OBJ_WAIT_TIMEDOUT) + return MSC_REQ_INCOMPLETE; + + return d->req->status; +} + +int msc_request(msc_drv* d, msc_req* r) +{ + msc_async_start(d, r); + return msc_async_wait(d, TIMEOUT_BLOCK); +} + +/* --------------------------------------------------------------------------- + * Command response handling + */ + +static void msc_read_response(msc_drv* d) +{ + unsigned res = REG_MSC_RES(d->msc_nr); + unsigned dat; + switch(d->req->resptype) { + case MSC_RESP_R1: + case MSC_RESP_R1B: + case MSC_RESP_R3: + case MSC_RESP_R6: + case MSC_RESP_R7: + dat = res << 24; + res = REG_MSC_RES(d->msc_nr); + dat |= res << 8; + res = REG_MSC_RES(d->msc_nr); + dat |= res & 0xff; + d->req->response[0] = dat; + break; + + case MSC_RESP_R2: + for(int i = 0; i < 4; ++i) { + dat = res << 24; + res = REG_MSC_RES(d->msc_nr); + dat |= res << 8; + res = REG_MSC_RES(d->msc_nr); + dat |= res >> 8; + d->req->response[i] = dat; + } + + break; + + default: + return; + } +} + +static int msc_check_sd_response(msc_drv* d) +{ + if(d->req->resptype == MSC_RESP_R1 || + d->req->resptype == MSC_RESP_R1B) { + if(d->req->response[0] & SD_R1_CARD_ERROR) { + logf("msc%d: R1 card error: %08x", d->msc_nr, d->req->response[0]); + return MSC_REQ_CARD_ERR; + } + } + + return MSC_REQ_SUCCESS; +} + +static int msc_check_response(msc_drv* d) +{ + switch(d->config->msc_type) { + case MSC_TYPE_SD: + return msc_check_sd_response(d); + default: + /* TODO - implement msc_check_response for MMC and CE-ATA */ + return 0; + } +} + +/* --------------------------------------------------------------------------- + * Interrupt handlers + */ + +static void msc_interrupt(msc_drv* d) +{ + const unsigned tmo_bits = jz_orm(MSC_IFLAG, TIME_OUT_READ, TIME_OUT_RES); + const unsigned crc_bits = jz_orm(MSC_IFLAG, CRC_RES_ERROR, + CRC_READ_ERROR, CRC_WRITE_ERROR); + const unsigned err_bits = tmo_bits | crc_bits; + + unsigned iflag = REG_MSC_IFLAG(d->msc_nr) & ~REG_MSC_IMASK(d->msc_nr); + bool handled = false; + + /* In case card was removed */ + if(!msc_card_detect(d)) { + msc_finish_request(d, MSC_REQ_EXTRACTED); + return; + } + + /* Check for errors */ + if(iflag & err_bits) { + int st; + if(iflag & crc_bits) + st = MSC_REQ_CRC_ERR; + else if(iflag & tmo_bits) + st = MSC_REQ_TIMEOUT; + else + st = MSC_REQ_ERROR; + + msc_finish_request(d, st); + return; + } + + /* Read and check the command response */ + if(iflag & BM_MSC_IFLAG_END_CMD_RES) { + msc_read_response(d); + int st = msc_check_response(d); + if(st == MSC_REQ_SUCCESS) { + jz_writef(MSC_IMASK(d->msc_nr), END_CMD_RES(1)); + jz_overwritef(MSC_IFLAG(d->msc_nr), END_CMD_RES(1)); + handled = true; + } else { + msc_finish_request(d, st); + return; + } + } + + /* Check if the "done" interrupt is signaled */ + if(iflag & d->iflag_done) { + /* Discard after DMA in case of hardware cache prefetching. + * Only needed for read operations. + */ + if((d->req->flags & MSC_RF_DATA) != 0 && + (d->req->flags & MSC_RF_WRITE) == 0) { + discard_dcache_range(d->req->data, + d->req->block_len * d->req->nr_blocks); + } + + msc_finish_request(d, MSC_REQ_SUCCESS); + return; + } + + if(!handled) { + panicf("msc%d: irq bug! iflag:%08x raw_iflag:%08lx imask:%08lx", + d->msc_nr, iflag, REG_MSC_IFLAG(d->msc_nr), REG_MSC_IMASK(d->msc_nr)); + } +} + +static int msc_cd_callback(struct timeout* tmo) +{ + msc_drv* d = (msc_drv*)tmo->data; + + /* If card is still present we assume the card is properly inserted */ + if(msc_card_detect(d)) { + d->card_present = 1; + queue_broadcast(SYS_HOTSWAP_INSERTED, d->drive_nr); + } + + return 0; +} + +static void msc_cd_interrupt(msc_drv* d) +{ + if(!msc_card_detect(d)) { + /* Immediately abort and notify when removing a card */ + msc_async_abort(d, MSC_REQ_EXTRACTED); + if(d->card_present) { + d->card_present = 0; + queue_broadcast(SYS_HOTSWAP_EXTRACTED, d->drive_nr); + } + } else { + /* Timer to debounce input */ + timeout_register(&d->cd_tmo, msc_cd_callback, HZ/4, (intptr_t)d); + } + + /* Invert the IRQ */ + REG_GPIO_PAT0(d->config->cd_gpio.port) ^= d->config->cd_gpio.pin; +} + +void MSC0(void) +{ + msc_interrupt(&msc_drivers[0]); +} + +void MSC1(void) +{ + msc_interrupt(&msc_drivers[1]); +} + +#ifdef msc0_cd_interrupt +void msc0_cd_interrupt(void) +{ + msc_cd_interrupt(&msc_drivers[0]); +} +#endif + +#ifdef msc1_cd_interrupt +void msc1_cd_interrupt(void) +{ + msc_cd_interrupt(&msc_drivers[1]); +} +#endif + +/* --------------------------------------------------------------------------- + * SD command helpers + */ + +int msc_cmd_exec(msc_drv* d, msc_req* r) +{ + int status = msc_request(d, r); + if(status == MSC_REQ_SUCCESS) + return status; + else if(status == MSC_REQ_LOCKUP || status == MSC_REQ_EXTRACTED) + d->driver_flags |= MSC_DF_ERRSTATE; + else if(r->flags & (MSC_RF_ERR_CMD12|MSC_RF_AUTO_CMD12)) { + /* After an error, the controller does not automatically issue CMD12, + * so we need to send it if it's needed, as required by the SD spec. + */ + msc_req nreq = {0}; + nreq.command = SD_STOP_TRANSMISSION; + nreq.resptype = MSC_RESP_R1B; + nreq.flags = MSC_RF_ABORT; + logf("msc%d: cmd%d error, sending cmd12", d->msc_nr, r->command); + if(msc_cmd_exec(d, &nreq)) + d->driver_flags |= MSC_DF_ERRSTATE; + } + + logf("msc%d: err:%d, cmd%d, arg:%x", d->msc_nr, status, + r->command, r->argument); + return status; +} + +int msc_app_cmd_exec(msc_drv* d, msc_req* r) +{ + msc_req areq = {0}; + areq.command = SD_APP_CMD; + areq.argument = d->cardinfo.rca; + areq.resptype = MSC_RESP_R1; + if(msc_cmd_exec(d, &areq)) + return areq.status; + + /* Verify that CMD55 was accepted */ + if((areq.response[0] & (1 << 5)) == 0) + return MSC_REQ_ERROR; + + return msc_cmd_exec(d, r); +} + +int msc_cmd_go_idle_state(msc_drv* d) +{ + msc_req req = {0}; + req.command = SD_GO_IDLE_STATE; + req.resptype = MSC_RESP_NONE; + req.flags = MSC_RF_INIT; + return msc_cmd_exec(d, &req); +} + +int msc_cmd_send_if_cond(msc_drv* d) +{ + msc_req req = {0}; + req.command = SD_SEND_IF_COND; + req.argument = 0x1aa; + req.resptype = MSC_RESP_R7; + + /* TODO - Check if SEND_IF_COND timeout is really an error + * IIRC, this can occur if the card isn't HCS (old cards < 2 GiB). + */ + if(msc_cmd_exec(d, &req)) + return req.status; + + /* Set HCS bit if the card responds correctly */ + if((req.response[0] & 0xff) == 0xaa) + d->driver_flags |= MSC_DF_HCS_CARD; + + return MSC_REQ_SUCCESS; +} + +int msc_cmd_app_op_cond(msc_drv* d) +{ + msc_req req = {0}; + req.command = SD_APP_OP_COND; + req.argument = 0x00300000; /* 3.4 - 3.6 V */ + req.resptype = MSC_RESP_R3; + if(d->driver_flags & MSC_DF_HCS_CARD) + req.argument |= (1 << 30); + + int timeout = 2 * HZ; + do { + if(msc_app_cmd_exec(d, &req)) + return req.status; + if(req.response[0] & (1 << 31)) + break; + sleep(1); + } while(--timeout > 0); + + if(timeout == 0) + return MSC_REQ_TIMEOUT; + + return MSC_REQ_SUCCESS; +} + +int msc_cmd_all_send_cid(msc_drv* d) +{ + msc_req req = {0}; + req.command = SD_ALL_SEND_CID; + req.resptype = MSC_RESP_R2; + if(msc_cmd_exec(d, &req)) + return req.status; + + for(int i = 0; i < 4; ++i) + d->cardinfo.cid[i] = req.response[i]; + + return MSC_REQ_SUCCESS; +} + +int msc_cmd_send_rca(msc_drv* d) +{ + msc_req req = {0}; + req.command = SD_SEND_RELATIVE_ADDR; + req.resptype = MSC_RESP_R6; + if(msc_cmd_exec(d, &req)) + return req.status; + + d->cardinfo.rca = req.response[0] & 0xffff0000; + return MSC_REQ_SUCCESS; +} + +int msc_cmd_send_csd(msc_drv* d) +{ + msc_req req = {0}; + req.command = SD_SEND_CSD; + req.argument = d->cardinfo.rca; + req.resptype = MSC_RESP_R2; + if(msc_cmd_exec(d, &req)) + return req.status; + + for(int i = 0; i < 4; ++i) + d->cardinfo.csd[i] = req.response[i]; + sd_parse_csd(&d->cardinfo); + + if((req.response[0] >> 30) == 1) + d->driver_flags |= MSC_DF_V2_CARD; + + return 0; +} + +int msc_cmd_select_card(msc_drv* d) +{ + msc_req req = {0}; + req.command = SD_SELECT_CARD; + req.argument = d->cardinfo.rca; + req.resptype = MSC_RESP_R1B; + return msc_cmd_exec(d, &req); +} + +int msc_cmd_set_bus_width(msc_drv* d, int width) +{ + /* TODO - must we check bus width is supported in the cardinfo? */ + msc_req req = {0}; + req.command = SD_SET_BUS_WIDTH; + req.resptype = MSC_RESP_R1; + switch(width) { + case 1: req.argument = 0; break; + case 4: req.argument = 2; break; + default: return MSC_REQ_ERROR; + } + + if(msc_app_cmd_exec(d, &req)) + return req.status; + + msc_set_width(d, width); + return MSC_REQ_SUCCESS; +} + +int msc_cmd_set_clr_card_detect(msc_drv* d, int arg) +{ + msc_req req = {0}; + req.command = SD_SET_CLR_CARD_DETECT; + req.argument = arg; + req.resptype = MSC_RESP_R1; + return msc_app_cmd_exec(d, &req); +} + +int msc_cmd_switch_freq(msc_drv* d) +{ + /* If card doesn't support High Speed, we don't need to send a command */ + if((d->driver_flags & MSC_DF_V2_CARD) == 0) { + msc_set_speed(d, MSC_SPEED_FAST); + return MSC_REQ_SUCCESS; + } + + /* Try switching to High Speed (50 MHz) */ + char buffer[64] CACHEALIGN_ATTR; + msc_req req = {0}; + req.command = SD_SWITCH_FUNC; + req.argument = 0x80fffff1; + req.resptype = MSC_RESP_R1; + req.flags = MSC_RF_DATA; + req.data = &buffer[0]; + req.block_len = 64; + req.nr_blocks = 1; + if(msc_cmd_exec(d, &req)) + return req.status; + + msc_set_speed(d, MSC_SPEED_HIGH); + return MSC_REQ_SUCCESS; +} + +int msc_cmd_send_status(msc_drv* d) +{ + msc_req req = {0}; + req.command = SD_SEND_STATUS; + req.argument = d->cardinfo.rca; + req.resptype = MSC_RESP_R1; + return msc_cmd_exec(d, &req); +} + +int msc_cmd_set_block_len(msc_drv* d, unsigned len) +{ + msc_req req = {0}; + req.command = SD_SET_BLOCKLEN; + req.argument = len; + req.resptype = MSC_RESP_R1; + return msc_cmd_exec(d, &req); +} diff --git a/firmware/target/mips/ingenic_x1000/msc-x1000.h b/firmware/target/mips/ingenic_x1000/msc-x1000.h new file mode 100644 index 0000000000..53a5b301f0 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/msc-x1000.h @@ -0,0 +1,186 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 __MSC_X1000_H__ +#define __MSC_X1000_H__ + +#include "kernel.h" +#include "sdmmc.h" +#include <stdbool.h> + +/* Number of MSC controllers */ +#define MSC_COUNT 2 + +/* Media types */ +#define MSC_TYPE_SD 0 +#define MSC_TYPE_MMC 1 +#define MSC_TYPE_ATA 2 +#define MSC_TYPE_ANY 3 + +/* Clock modes */ +#define MSC_CLK_MANUAL 0 +#define MSC_CLK_AUTOMATIC 1 + +/* Clock status bits */ +#define MSC_CLKST_ENABLE (1 << 0) +#define MSC_CLKST_AUTO (1 << 1) + +/* Driver flags */ +#define MSC_DF_ERRSTATE (1 << 0) +#define MSC_DF_READY (1 << 1) +#define MSC_DF_HCS_CARD (1 << 2) +#define MSC_DF_V2_CARD (1 << 3) + +/* Request status codes */ +#define MSC_REQ_SUCCESS 0 +#define MSC_REQ_CRC_ERR 1 +#define MSC_REQ_CARD_ERR 2 +#define MSC_REQ_TIMEOUT 3 +#define MSC_REQ_EXTRACTED 4 +#define MSC_REQ_LOCKUP 5 +#define MSC_REQ_ERROR 6 +#define MSC_REQ_INCOMPLETE (-1) + +/* Response types */ +#define MSC_RESP_NONE 0 +#define MSC_RESP_BUSY (1 << 7) +#define MSC_RESP_R1 1 +#define MSC_RESP_R1B (MSC_RESP_R1|MSC_RESP_BUSY) +#define MSC_RESP_R2 2 +#define MSC_RESP_R3 3 +#define MSC_RESP_R6 6 +#define MSC_RESP_R7 7 + +/* Request flags */ +#define MSC_RF_INIT (1 << 0) +#define MSC_RF_ERR_CMD12 (1 << 1) +#define MSC_RF_AUTO_CMD12 (1 << 2) +#define MSC_RF_PROG (1 << 3) +#define MSC_RF_DATA (1 << 4) +#define MSC_RF_WRITE (1 << 5) +#define MSC_RF_ABORT (1 << 6) + +/* Clock speeds */ +#define MSC_SPEED_INIT 400000 +#define MSC_SPEED_FAST 25000000 +#define MSC_SPEED_HIGH 50000000 + +typedef struct msc_gpio_data { + int port; + int pin; + int active_level; +} msc_gpio_data; + +typedef struct msc_config { + int msc_nr; + int msc_type; + int bus_width; + const char* label; + struct msc_gpio_data cd_gpio; +} msc_config; + +typedef struct msc_req { + /* Filled by caller */ + int command; + unsigned argument; + int resptype; + int flags; + void* data; + unsigned nr_blocks; + unsigned block_len; + + /* Filled by driver */ + volatile unsigned response[4]; + volatile int status; +} msc_req; + +struct sd_dma_desc { + unsigned nda; + unsigned mem; + unsigned len; + unsigned cmd; +} __attribute__((aligned(16))); + +typedef struct msc_drv { + int msc_nr; + int drive_nr; + const msc_config* config; + + int driver_flags; + int clk_status; + unsigned cmdat_def; + msc_req* req; + unsigned iflag_done; + + volatile int req_running; + volatile int card_present; + + struct mutex lock; + struct semaphore cmd_done; + struct timeout cmd_tmo; + struct timeout cd_tmo; + struct sd_dma_desc dma_desc; + + tCardInfo cardinfo; +} msc_drv; + +/* Driver initialization, etc */ +extern void msc_init(void); +extern msc_drv* msc_get(int type, int index); +extern msc_drv* msc_get_by_drive(int drive_nr); + +extern void msc_lock(msc_drv* d); +extern void msc_unlock(msc_drv* d); +extern void msc_full_reset(msc_drv* d); +extern bool msc_card_detect(msc_drv* d); + +/* Controller API */ +extern void msc_ctl_reset(msc_drv* d); +extern void msc_set_clock_mode(msc_drv* d, int mode); +extern void msc_enable_clock(msc_drv* d, bool enable); +extern void msc_set_speed(msc_drv* d, int rate); +extern void msc_set_width(msc_drv* d, int width); + +/* Request API */ +extern void msc_async_start(msc_drv* d, msc_req* r); +extern void msc_async_abort(msc_drv* d, int status); +extern int msc_async_wait(msc_drv* d, int timeout); +extern int msc_request(msc_drv* d, msc_req* r); + +/* Command helpers; note these are written with SD in mind + * and should be reviewed before using them for MMC / CE-ATA + */ +extern int msc_cmd_exec(msc_drv* d, msc_req* r); +extern int msc_app_cmd_exec(msc_drv* d, msc_req* r); +extern int msc_cmd_go_idle_state(msc_drv* d); +extern int msc_cmd_send_if_cond(msc_drv* d); +extern int msc_cmd_app_op_cond(msc_drv* d); +extern int msc_cmd_all_send_cid(msc_drv* d); +extern int msc_cmd_send_rca(msc_drv* d); +extern int msc_cmd_send_csd(msc_drv* d); +extern int msc_cmd_select_card(msc_drv* d); +extern int msc_cmd_set_bus_width(msc_drv* d, int width); +extern int msc_cmd_set_clr_card_detect(msc_drv* d, int arg); +extern int msc_cmd_switch_freq(msc_drv* d); +extern int msc_cmd_send_status(msc_drv* d); +extern int msc_cmd_set_block_len(msc_drv* d, unsigned len); + +#endif /* __MSC_X1000_H__ */ diff --git a/firmware/target/mips/ingenic_x1000/nand-x1000.c b/firmware/target/mips/ingenic_x1000/nand-x1000.c new file mode 100644 index 0000000000..54a1d11d95 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/nand-x1000.c @@ -0,0 +1,500 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 "nand-x1000.h" +#include "nand-target.h" +#include "sfc-x1000.h" +#include "system.h" +#include <string.h> + +#if !defined(NAND_MAX_PAGE_SIZE) || \ + !defined(NAND_INIT_SFC_DEV_CONF) || \ + !defined(NAND_INIT_CLOCK_SPEED) +# error "Target needs to specify NAND driver parameters" +#endif + +/* Must be at least as big as a cacheline */ +#define NAND_AUX_BUFFER_SIZE CACHEALIGN_SIZE + +/* Writes have been enabled */ +#define NAND_DRV_FLAG_WRITEABLE 0x01 + +/* Defined by target */ +extern const nand_chip_desc target_nand_chip_descs[]; + +/* Globals for the driver + * TODO: get rid of pagebuffer in the SPL to save code size + */ +static unsigned char pagebuffer[NAND_MAX_PAGE_SIZE] CACHEALIGN_ATTR; +static unsigned char auxbuffer[NAND_AUX_BUFFER_SIZE] CACHEALIGN_ATTR; +static nand_drv nand_driver; + +static void nand_drv_reset(nand_drv* d) +{ + d->chip_ops = NULL; + d->chip_data = NULL; + d->pagebuf = &pagebuffer[0]; + d->auxbuf = &auxbuffer[0]; + d->raw_page_size = 0; + d->flags = 0; +} + +/* Driver code */ +int nand_open(void) +{ + sfc_init(); + sfc_lock(); + + /* Reset driver state */ + nand_drv_reset(&nand_driver); + + /* Init hardware */ + sfc_open(); + sfc_set_dev_conf(NAND_INIT_SFC_DEV_CONF); + sfc_set_clock(NAND_CLOCK_SOURCE, NAND_INIT_CLOCK_SPEED); + + /* Identify NAND chip */ + int status = 0; + int nandid = nandcmd_read_id(&nand_driver); + if(nandid < 0) { + status = -1; + goto _err; + } + + unsigned char mf_id = nandid >> 8; + unsigned char dev_id = nandid & 0xff; + const nand_chip_desc* desc = &target_nand_chip_descs[0]; + while(1) { + if(desc->data == NULL || desc->ops == NULL) { + status = -1; + goto _err; + } + + if(desc->data->mf_id == mf_id && desc->data->dev_id == dev_id) + break; + } + + /* Fill driver parameters */ + nand_driver.chip_ops = desc->ops; + nand_driver.chip_data = desc->data; + nand_driver.raw_page_size = desc->data->page_size + desc->data->spare_size; + + /* Configure hardware and run init op */ + sfc_set_dev_conf(desc->data->dev_conf); + sfc_set_clock(NAND_CLOCK_SOURCE, desc->data->clock_freq); + + if(desc->ops->open(&nand_driver) < 0) { + status = -1; + goto _err; + } + + _exit: + sfc_unlock(); + return status; + _err: + nand_drv_reset(&nand_driver); + sfc_close(); + goto _exit; +} + +void nand_close(void) +{ + sfc_lock(); + nand_driver.chip_ops->close(&nand_driver); + nand_drv_reset(&nand_driver); + sfc_close(); + sfc_unlock(); +} + +int nand_enable_writes(bool en) +{ + sfc_lock(); + + int st = nand_driver.chip_ops->set_wp_enable(&nand_driver, en); + if(st >= 0) { + if(en) + nand_driver.flags |= NAND_DRV_FLAG_WRITEABLE; + else + nand_driver.flags &= ~NAND_DRV_FLAG_WRITEABLE; + } + + sfc_unlock(); + return st; +} + +extern int nand_read_bytes(uint32_t byteaddr, int count, void* buf) +{ + if(count <= 0) + return 0; + + nand_drv* d = &nand_driver; + uint32_t rowaddr = byteaddr / d->chip_data->page_size; + uint32_t coladdr = byteaddr % d->chip_data->page_size; + unsigned char* dstbuf = (unsigned char*)buf; + int status = 0; + + sfc_lock(); + do { + if(d->chip_ops->read_page(d, rowaddr, d->pagebuf) < 0) { + status = -1; + goto _end; + } + + if(d->chip_ops->ecc_read(d, d->pagebuf) < 0) { + status = -1; + goto _end; + } + + int amount = d->chip_data->page_size - coladdr; + if(amount > count) + amount = count; + + memcpy(dstbuf, d->pagebuf, amount); + dstbuf += amount; + count -= amount; + rowaddr += 1; + coladdr = 0; + } while(count > 0); + + _end: + sfc_unlock(); + return status; +} + +int nand_write_bytes(uint32_t byteaddr, int count, const void* buf) +{ + nand_drv* d = &nand_driver; + + if((d->flags & NAND_DRV_FLAG_WRITEABLE) == 0) + return -1; + + if(count <= 0) + return 0; + + uint32_t rowaddr = byteaddr / d->chip_data->page_size; + uint32_t coladdr = byteaddr % d->chip_data->page_size; + + /* Only support whole page writes right now */ + if(coladdr != 0) + return -1; + if(count % d->chip_data->page_size) + return -1; + + const unsigned char* srcbuf = (const unsigned char*)buf; + int status = 0; + + sfc_lock(); + do { + memcpy(d->pagebuf, srcbuf, d->chip_data->page_size); + d->chip_ops->ecc_write(d, d->pagebuf); + + if(d->chip_ops->write_page(d, rowaddr, d->pagebuf) < 0) { + status = -1; + goto _end; + } + + rowaddr += 1; + srcbuf += d->chip_data->page_size; + count -= d->chip_data->page_size; + } while(count > 0); + + _end: + sfc_unlock(); + return status; +} + +int nand_erase_block(uint32_t byteaddr) +{ + nand_drv* d = &nand_driver; + + if((d->flags & NAND_DRV_FLAG_WRITEABLE) == 0) + return -1; + + /* Ensure address is aligned to a block boundary */ + uint32_t blockaddr = byteaddr / d->chip_data->page_size; + if(blockaddr % d->chip_data->block_size) + return -1; + + int status = 0; + sfc_lock(); + + if(d->chip_ops->erase_block(d, blockaddr)) { + status = -1; + goto _end; + } + + _end: + sfc_unlock(); + return status; +} + +int nandcmd_read_id(nand_drv* d) +{ + sfc_op op = {0}; + op.command = NAND_CMD_READ_ID; + op.flags = SFC_FLAG_READ; + op.addr_bytes = 1; + op.addr_lo = 0; + op.data_bytes = 2; + op.buffer = d->auxbuf; + if(sfc_exec(&op)) + return -1; + + return (d->auxbuf[0] << 8) | d->auxbuf[1]; +} + +int nandcmd_write_enable(nand_drv* d) +{ + (void)d; + + sfc_op op = {0}; + op.command = NAND_CMD_WRITE_ENABLE; + if(sfc_exec(&op)) + return -1; + + return 0; +} + +int nandcmd_get_feature(nand_drv* d, int reg) +{ + sfc_op op = {0}; + op.command = NAND_CMD_GET_FEATURE; + op.flags = SFC_FLAG_READ; + op.addr_bytes = 1; + op.addr_lo = reg & 0xff; + op.data_bytes = 1; + op.buffer = d->auxbuf; + if(sfc_exec(&op)) + return -1; + + return d->auxbuf[0]; +} + +int nandcmd_set_feature(nand_drv* d, int reg, int val) +{ + sfc_op op = {0}; + op.command = NAND_CMD_SET_FEATURE; + op.flags = SFC_FLAG_READ; + op.addr_bytes = 1; + op.addr_lo = reg & 0xff; + op.data_bytes = 1; + op.buffer = d->auxbuf; + d->auxbuf[0] = val & 0xff; + if(sfc_exec(&op)) + return -1; + + return 0; +} + +int nandcmd_page_read_to_cache(nand_drv* d, uint32_t rowaddr) +{ + sfc_op op = {0}; + op.command = NAND_CMD_PAGE_READ_TO_CACHE; + op.addr_bytes = d->chip_data->rowaddr_width; + op.addr_lo = rowaddr; + if(sfc_exec(&op)) + return -1; + + return 0; +} + +int nandcmd_read_from_cache(nand_drv* d, unsigned char* buf) +{ + sfc_op op = {0}; + if(d->chip_data->flags & NANDCHIP_FLAG_QUAD) { + op.command = NAND_CMD_READ_FROM_CACHEx4; + op.mode = SFC_MODE_QUAD_IO; + } else { + op.command = NAND_CMD_READ_FROM_CACHE; + op.mode = SFC_MODE_STANDARD; + } + + op.flags = SFC_FLAG_READ; + op.addr_bytes = d->chip_data->coladdr_width; + op.addr_lo = 0; + op.dummy_bits = 8; + op.data_bytes = d->raw_page_size; + op.buffer = buf; + if(sfc_exec(&op)) + return -1; + + return 0; +} + +int nandcmd_program_load(nand_drv* d, const unsigned char* buf) +{ + sfc_op op = {0}; + if(d->chip_data->flags & NANDCHIP_FLAG_QUAD) { + op.command = NAND_CMD_PROGRAM_LOADx4; + op.mode = SFC_MODE_QUAD_IO; + } else { + op.command = NAND_CMD_PROGRAM_LOAD; + op.mode = SFC_MODE_STANDARD; + } + + op.flags = SFC_FLAG_WRITE; + op.addr_bytes = d->chip_data->coladdr_width; + op.addr_lo = 0; + op.data_bytes = d->raw_page_size; + op.buffer = (void*)buf; + if(sfc_exec(&op)) + return -1; + + return 0; +} + +int nandcmd_program_execute(nand_drv* d, uint32_t rowaddr) +{ + sfc_op op = {0}; + op.command = NAND_CMD_PROGRAM_EXECUTE; + op.addr_bytes = d->chip_data->rowaddr_width; + op.addr_lo = rowaddr; + if(sfc_exec(&op)) + return -1; + + return 0; +} + +int nandcmd_block_erase(nand_drv* d, uint32_t blockaddr) +{ + sfc_op op = {0}; + op.command = NAND_CMD_BLOCK_ERASE; + op.addr_bytes = d->chip_data->rowaddr_width; + op.addr_lo = blockaddr; + if(sfc_exec(&op)) + return 01; + + return 0; +} + +const nand_chip_ops nand_chip_ops_std = { + .open = nandop_std_open, + .close = nandop_std_close, + .read_page = nandop_std_read_page, + .write_page = nandop_std_write_page, + .erase_block = nandop_std_erase_block, + .set_wp_enable = nandop_std_set_wp_enable, + .ecc_read = nandop_ecc_none_read, + .ecc_write = nandop_ecc_none_write, +}; + +/* Helper needed by other ops */ +static int nandop_std_wait_status(nand_drv* d, int errbit) +{ + int reg; + do { + reg = nandcmd_get_feature(d, NAND_FREG_STATUS); + if(reg < 0) + return -1; + } while(reg & NAND_FREG_STATUS_OIP); + + if(reg & errbit) + return -1; + + return reg; +} + +int nandop_std_open(nand_drv* d) +{ + (void)d; + return 0; +} + +void nandop_std_close(nand_drv* d) +{ + (void)d; +} + +int nandop_std_read_page(nand_drv* d, uint32_t rowaddr, unsigned char* buf) +{ + if(nandcmd_page_read_to_cache(d, rowaddr) < 0) + return -1; + if(nandop_std_wait_status(d, 0) < 0) + return -1; + if(nandcmd_read_from_cache(d, buf) < 0) + return -1; + + return 0; +} + +int nandop_std_write_page(nand_drv* d, uint32_t rowaddr, const unsigned char* buf) +{ + if(nandcmd_write_enable(d) < 0) + return -1; + if(nandcmd_program_load(d, buf) < 0) + return -1; + if(nandcmd_program_execute(d, rowaddr) < 0) + return -1; + if(nandop_std_wait_status(d, NAND_FREG_STATUS_P_FAIL) < 0) + return -1; + + return 0; +} + +int nandop_std_erase_block(nand_drv* d, uint32_t blockaddr) +{ + if(nandcmd_write_enable(d) < 0) + return -1; + if(nandcmd_block_erase(d, blockaddr) < 0) + return -1; + if(nandop_std_wait_status(d, NAND_FREG_STATUS_E_FAIL) < 0) + return -1; + + return 0; +} + +int nandop_std_set_wp_enable(nand_drv* d, bool en) +{ + int val = nandcmd_get_feature(d, NAND_FREG_PROTECTION); + if(val < 0) + return -1; + + if(en) { + val &= ~NAND_FREG_PROTECTION_ALLBP; + if(d->chip_data->flags & NANDCHIP_FLAG_USE_BRWD) + val &= ~NAND_FREG_PROTECTION_BRWD; + } else { + val |= NAND_FREG_PROTECTION_ALLBP; + if(d->chip_data->flags & NANDCHIP_FLAG_USE_BRWD) + val |= NAND_FREG_PROTECTION_BRWD; + } + + sfc_set_wp_enable(false); + int status = nandcmd_set_feature(d, NAND_FREG_PROTECTION, val); + sfc_set_wp_enable(true); + + if(status < 0) + return -1; + + return 0; +} + +int nandop_ecc_none_read(nand_drv* d, unsigned char* buf) +{ + (void)d; + (void)buf; + return 0; +} + +void nandop_ecc_none_write(nand_drv* d, unsigned char* buf) +{ + memset(&buf[d->chip_data->page_size], 0xff, d->chip_data->spare_size); +} diff --git a/firmware/target/mips/ingenic_x1000/nand-x1000.h b/firmware/target/mips/ingenic_x1000/nand-x1000.h new file mode 100644 index 0000000000..865feb38c5 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/nand-x1000.h @@ -0,0 +1,213 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 __NAND_X1000_H__ +#define __NAND_X1000_H__ + +/* NOTE: this is a very minimal API designed only to support a bootloader. + * Not suitable for general data storage. It doesn't have proper support for + * partial page writes, access to spare area, etc, which are all necessary + * for an effective flash translation layer. + */ + +#include <stdint.h> +#include <stdbool.h> +#include <stddef.h> + +/* Chip supports quad I/O for page read/write */ +#define NANDCHIP_FLAG_QUAD 0x01 + +/* Set/clear the BRWD bit when enabling/disabling write protection */ +#define NANDCHIP_FLAG_USE_BRWD 0x02 + +typedef struct nand_drv nand_drv; + +/* Defines some static information about a NAND chip */ +typedef struct nand_chip_data { + const char* name; /* Name for debugging purposes */ + uint8_t mf_id; /* Manufacturer ID */ + uint8_t dev_id; /* Device ID */ + uint8_t rowaddr_width; /* Number of bytes in row addresses */ + uint8_t coladdr_width; /* Number of bytes in column addresses */ + uint32_t dev_conf; /* Value to write to SFC_DEV_CONF register */ + uint32_t clock_freq; /* Frequency to switch to after identification */ + uint32_t block_size; /* Number of pages per eraseblock */ + uint32_t page_size; /* Number of data bytes per page */ + uint32_t spare_size; /* Number of spare bytes per page */ + int flags; /* Various flags */ +} nand_chip_data; + +/* Defines high-level operations used to implement the public API. + * Chips may need to override operations if the default ones aren't suitable. + * + * Negative return codes return an error, while zero or positive codes are + * considered successful. This allows a function to return meaningful data, + * if applicable. + */ +typedef struct nand_chip_ops { + /* Called once after identifying the chip */ + int(*open)(nand_drv* d); + + /* Called once when the driver is closed */ + void(*close)(nand_drv* d); + + /* Read or write a complete page including both main and spare areas. */ + int(*read_page)(nand_drv* d, uint32_t rowaddr, unsigned char* buf); + int(*write_page)(nand_drv* d, uint32_t rowaddr, const unsigned char* buf); + + /* Erase a block. */ + int(*erase_block)(nand_drv* d, uint32_t blockaddr); + + /* Enable or disable the chip's write protection. */ + int(*set_wp_enable)(nand_drv* d, bool en); + + /* Perform error correction and detection on a raw page (main + spare). + * Return the number of errors detected and corrected, or a negative value + * if errors were detected but could not be corrected. + */ + int(*ecc_read)(nand_drv* d, unsigned char* buf); + + /* Generate ECC data for a page. The buffer main area is already filled + * and this function should write ECC data into the spare area. + */ + void(*ecc_write)(nand_drv* d, unsigned char* buf); +} nand_chip_ops; + +/* Struct used to list all supported NAND chips in an array */ +typedef struct nand_chip_desc { + const nand_chip_data* data; + const nand_chip_ops* ops; +} nand_chip_desc; + +/* NAND driver structure. It can be accessed by chip ops, but they must not + * modify any fields except for "auxbuf", which is a small buffer that can + * be used for commands that need to read/write small amounts of data: often + * needed for polling status, etc. + */ +struct nand_drv { + const nand_chip_ops* chip_ops; + const nand_chip_data* chip_data; + unsigned char* pagebuf; + unsigned char* auxbuf; + uint32_t raw_page_size; + int flags; +}; + +/* Note: sfc_init() must be called prior to nand_open() */ +extern int nand_open(void); +extern void nand_close(void); + +/* Controls device-side write protection registers as well as software lock. + * Erase and program operations will fail unless you first enable writes. + */ +extern int nand_enable_writes(bool en); + +/* Byte-based NAND operations */ +extern int nand_read_bytes(uint32_t byteaddr, int count, void* buf); +extern int nand_write_bytes(uint32_t byteaddr, int count, const void* buf); +extern int nand_erase_block(uint32_t byteaddr); + +/* NAND command numbers */ +#define NAND_CMD_READ_ID 0x9f +#define NAND_CMD_WRITE_ENABLE 0x06 +#define NAND_CMD_GET_FEATURE 0x0f +#define NAND_CMD_SET_FEATURE 0x1f +#define NAND_CMD_PAGE_READ_TO_CACHE 0x13 +#define NAND_CMD_READ_FROM_CACHE 0x0b +#define NAND_CMD_READ_FROM_CACHEx4 0x6b +#define NAND_CMD_PROGRAM_LOAD 0x02 +#define NAND_CMD_PROGRAM_LOADx4 0x32 +#define NAND_CMD_PROGRAM_EXECUTE 0x10 +#define NAND_CMD_BLOCK_ERASE 0xd8 + +/* NAND device register addresses for GET_FEATURE / SET_FEATURE */ +#define NAND_FREG_PROTECTION 0xa0 +#define NAND_FREG_FEATURE 0xb0 +#define NAND_FREG_STATUS 0xc0 + +/* Protection register bits */ +#define NAND_FREG_PROTECTION_BRWD 0x80 +#define NAND_FREG_PROTECTION_BP2 0x20 +#define NAND_FREG_PROTECTION_BP1 0x10 +#define NAND_FREG_PROTECTION_BP0 0x80 +/* Mask of BP bits 0-2 */ +#define NAND_FREG_PROTECTION_ALLBP (0x38) + +/* Feature register bits */ +#define NAND_FREG_FEATURE_QE 0x01 + +/* Status register bits */ +#define NAND_FREG_STATUS_OIP 0x01 +#define NAND_FREG_STATUS_WEL 0x02 +#define NAND_FREG_STATUS_E_FAIL 0x04 +#define NAND_FREG_STATUS_P_FAIL 0x08 + +/* Standard implementations for low-level NAND commands. I'm not aware of any + * actual standard governing these, but it seems many vendors follow the same + * command numbering, status bits, and behavior so these implementations should + * work across a wide variety of chips. + * + * If adding a new NAND chip which only has a minor deviation from these + * standard implementations, consider adding a flag and modifying these + * functions to change their behavior based on the flag, instead of writing + * a whole new implementation. + * + * None of these functions are directly called by the high-level driver code, + * except for nandcmd_std_read_id(). They can be used to implement higher-level + * functions in a device's "nand_chip_ops". + */ +extern int nandcmd_read_id(nand_drv* d); +extern int nandcmd_write_enable(nand_drv* d); +extern int nandcmd_get_feature(nand_drv* d, int reg); +extern int nandcmd_set_feature(nand_drv* d, int reg, int val); +extern int nandcmd_page_read_to_cache(nand_drv* d, uint32_t rowaddr); +extern int nandcmd_read_from_cache(nand_drv* d, unsigned char* buf); +extern int nandcmd_program_load(nand_drv* d, const unsigned char* buf); +extern int nandcmd_program_execute(nand_drv* d, uint32_t rowaddr); +extern int nandcmd_block_erase(nand_drv* d, uint32_t blockaddr); + +/* Table filled with all the standard operations for chips which don't + * need to override any operations. + */ +extern const nand_chip_ops nand_chip_ops_std; + +/* Standard NAND chip ops based on the standard "nandcmd" functions. + * + * Same advice applies here as there: if it's possible to support minor + * chip variations with a flag, modify these functions to do so. + */ +extern int nandop_std_open(nand_drv* d); +extern void nandop_std_close(nand_drv* d); +extern int nandop_std_read_page(nand_drv* d, uint32_t rowaddr, unsigned char* buf); +extern int nandop_std_write_page(nand_drv* d, uint32_t rowaddr, const unsigned char* buf); +extern int nandop_std_erase_block(nand_drv* d, uint32_t blockaddr); +extern int nandop_std_set_wp_enable(nand_drv* d, bool en); + +/* The default ECC implementation is a no-op: reads always succeed without + * reporting errors and writes will fill the spare area with '0xff' bytes. + * + * For chips that support internal ECC, this often works because the chip will + * ignore writes to the ECC areas. + */ +extern int nandop_ecc_none_read(nand_drv* d, unsigned char* buf); +extern void nandop_ecc_none_write(nand_drv* d, unsigned char* buf); + +#endif /* __NAND_X1000_H__ */ diff --git a/firmware/target/mips/ingenic_x1000/pcm-x1000.c b/firmware/target/mips/ingenic_x1000/pcm-x1000.c new file mode 100644 index 0000000000..9ae6f5a956 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/pcm-x1000.c @@ -0,0 +1,165 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 "audiohw.h" +#include "pcm.h" +#include "pcm-internal.h" +#include "panic.h" +#include "dma-x1000.h" +#include "irq-x1000.h" +#include "x1000/aic.h" + +#define AIC_STATE_STOPPED 0 +#define AIC_STATE_PLAYING 1 + +volatile unsigned aic_tx_underruns = 0; + +static int aic_state = AIC_STATE_STOPPED; + +static int aic_lock = 0; +static volatile int aic_dma_pending_event = DMA_EVENT_NONE; + +static dma_desc aic_dma_desc; + +static void pcm_dma_int_cb(int event); + +void pcm_play_dma_init(void) +{ + /* Let the target initialize its hardware and setup the AIC */ + audiohw_init(); + + /* Set DMA callback */ + dma_set_callback(DMA_CHANNEL_AUDIO, pcm_dma_int_cb); + + /* Program FIFO threshold -- DMA settings must match */ + jz_writef(AIC_CFG, TFTH(16)); + + /* Ensure all playback is disabled */ + jz_writef(AIC_CCR, ERPL(0)); + + /* Enable the controller */ + jz_writef(AIC_CFG, ENABLE(1)); + + /* Enable interrupts */ + system_enable_irq(IRQ_AIC); +} + +void pcm_play_dma_postinit(void) +{ + audiohw_postinit(); +} + +void pcm_dma_apply_settings(void) +{ + audiohw_set_frequency(pcm_fsel); +} + +static void pcm_dma_start(const void* addr, size_t size) +{ + aic_dma_desc.cm = jz_orf(DMA_CHN_CM, SAI(1), DAI(0), RDIL(9), + SP_V(32BIT), DP_V(32BIT), TSZ_V(AUTO), + STDE(0), TIE(1), LINK(0)); + aic_dma_desc.sa = PHYSADDR(addr); + aic_dma_desc.ta = PHYSADDR(JA_AIC_DR); + aic_dma_desc.tc = size; + aic_dma_desc.sd = 0; + aic_dma_desc.rt = jz_orf(DMA_CHN_RT, TYPE_V(I2S_TX)); + aic_dma_desc.pad0 = 0; + aic_dma_desc.pad1 = 0; + + commit_dcache_range(&aic_dma_desc, sizeof(dma_desc)); + commit_dcache_range(addr, size); + + REG_DMA_CHN_DA(DMA_CHANNEL_AUDIO) = PHYSADDR(&aic_dma_desc); + jz_writef(DMA_CHN_CS(DMA_CHANNEL_AUDIO), DES8(1), NDES(0)); + jz_set(DMA_DB, 1 << DMA_CHANNEL_AUDIO); + jz_writef(DMA_CHN_CS(DMA_CHANNEL_AUDIO), CTE(1)); + + pcm_play_dma_status_callback(PCM_DMAST_STARTED); +} + +static void pcm_dma_handle_event(int event) +{ + if(event == DMA_EVENT_COMPLETE) { + const void* addr; + size_t size; + if(pcm_play_dma_complete_callback(PCM_DMAST_OK, &addr, &size)) + pcm_dma_start(addr, size); + } else if(event == DMA_EVENT_NONE) { + /* ignored, so callers don't need to check for this */ + } else { + pcm_play_dma_status_callback(PCM_DMAST_ERR_DMA); + } +} + +static void pcm_dma_int_cb(int event) +{ + if(aic_lock) { + aic_dma_pending_event = event; + return; + } else { + pcm_dma_handle_event(event); + } +} + +void pcm_play_dma_start(const void* addr, size_t size) +{ + aic_dma_pending_event = DMA_EVENT_NONE; + aic_state = AIC_STATE_PLAYING; + + pcm_dma_start(addr, size); + jz_writef(AIC_CCR, TDMS(1), ETUR(1), ERPL(1)); +} + +void pcm_play_dma_stop(void) +{ + jz_writef(AIC_CCR, TDMS(0), ETUR(0), ERPL(0)); + jz_writef(AIC_CCR, TFLUSH(1)); + + aic_dma_pending_event = DMA_EVENT_NONE; + aic_state = AIC_STATE_STOPPED; +} + +void pcm_play_lock(void) +{ + ++aic_lock; +} + +void pcm_play_unlock(void) +{ + int irq = disable_irq_save(); + if(--aic_lock == 0 && aic_state == AIC_STATE_PLAYING) { + pcm_dma_handle_event(aic_dma_pending_event); + aic_dma_pending_event = DMA_EVENT_NONE; + } + + restore_irq(irq); +} + +void AIC(void) +{ + if(jz_readf(AIC_SR, TUR)) { + aic_tx_underruns += 1; + jz_writef(AIC_SR, TUR(0)); + } +} diff --git a/firmware/target/mips/ingenic_x1000/pwm-x1000.c b/firmware/target/mips/ingenic_x1000/pwm-x1000.c new file mode 100644 index 0000000000..37d2856c1a --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/pwm-x1000.c @@ -0,0 +1,170 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 "pwm-x1000.h" +#include "clk-x1000.h" +#include "gpio-x1000.h" +#include "system.h" +#include "kernel.h" +#include "x1000/tcu.h" + +struct pwm_gpio_data { + int port; + unsigned pin; + int func; +}; + +struct pwm_state { + struct pwm_gpio_data gpio; + int period_ns; + int duty_ns; + int full_ticks; + int half_ticks; + int prescaler; +}; + +static struct pwm_state pwm_state[] = { + {{GPIO_C, 1 << 25, GPIO_DEVICE(0)}, -1, -1, -1, -1, -1}, + {{GPIO_C, 1 << 26, GPIO_DEVICE(1)}, -1, -1, -1, -1, -1}, + {{GPIO_C, 1 << 27, GPIO_DEVICE(1)}, -1, -1, -1, -1, -1}, + {{GPIO_B, 1 << 6, GPIO_DEVICE(2)}, -1, -1, -1, -1, -1}, + {{GPIO_C, 1 << 24, GPIO_DEVICE(0)}, -1, -1, -1, -1, -1}, +}; + +void pwm_init(int chn) +{ + /* clear cached state */ + struct pwm_state* st = &pwm_state[chn]; + st->period_ns = -1; + st->duty_ns = -1; + st->full_ticks = -1; + st->prescaler = -1; + st->prescaler = -1; + + /* clear GPIO and disable timer */ + gpio_config(st->gpio.port, st->gpio.pin, GPIO_OUTPUT(0)); + jz_clr(TCU_STOP, 1 << chn); + jz_clr(TCU_ENABLE, 1 << chn); + jz_set(TCU_STOP, 1 << chn); +} + +void pwm_set_period(int chn, int period_ns, int duty_ns) +{ + struct pwm_state* st = &pwm_state[chn]; + unsigned long long tmp; + int full_ticks = st->full_ticks; + int half_ticks = st->half_ticks; + int prescaler = st->prescaler; + + if(period_ns != st->period_ns) { + /* calculate full tick period and prescaler */ + tmp = clk_get(X1000_CLK_PCLK) / 1000000; + tmp *= period_ns; + tmp /= 1000; + + prescaler = 0; + while(tmp > 0xffff && prescaler < 5) { + tmp /= 4; + prescaler += 1; + } + + full_ticks = (tmp > 0xffff) ? 0xffff : tmp; + st->period_ns = period_ns; + } + + if(duty_ns != st->duty_ns) { + /* calculate half tick value */ + tmp = full_ticks; + tmp *= duty_ns; + tmp /= period_ns; + + half_ticks = (tmp > 0xffff) ? 0xffff : tmp; + if(half_ticks >= full_ticks) + half_ticks = full_ticks - 1; + st->duty_ns = duty_ns; + } + + /* need to clear STOP bit to access timer unit registers */ + int was_stopped = !!(jz_read(TCU_STOP) & (1 << chn)); + if(was_stopped) + jz_clr(TCU_STOP, 1 << chn); + + /* check if timer is currently running */ + int was_enabled = !!(jz_read(TCU_ENABLE) & (1 << chn)); + int enabled = was_enabled; + + if(prescaler != st->prescaler) { + /* must disable timer to change these settings */ + if(was_enabled) { + jz_clr(TCU_ENABLE, 1 << chn); + enabled = 0; + } + + jz_overwritef(TCU_CTRL(chn), SHUTDOWN_V(GRACEFUL), INIT_LVL(0), + PWM_EN(1), PRESCALE(prescaler), SOURCE_V(PCLK)); + REG_TCU_COUNT(chn) = 0; + st->prescaler = prescaler; + } + + if(full_ticks != st->full_ticks || half_ticks != st->half_ticks) { + if(enabled) { + /* avoid changing PWM settings in the middle of a cycle */ + unsigned cmp = REG_TCU_CMP_FULL(chn) - 1; + long deadline = current_tick + 3; + while(REG_TCU_COUNT(chn) < cmp + && TIME_BEFORE(current_tick, deadline)); + } + + /* these can be changed while the timer is running */ + REG_TCU_CMP_FULL(chn) = full_ticks; + REG_TCU_CMP_HALF(chn) = full_ticks - half_ticks; + st->full_ticks = full_ticks; + st->half_ticks = half_ticks; + } + + /* restore the enable/stop state */ + if(was_enabled && !enabled) + jz_set(TCU_ENABLE, 1 << chn); + if(was_stopped) + jz_set(TCU_STOP, 1 << chn); +} + +void pwm_enable(int chn) +{ + /* Start timer */ + jz_clr(TCU_STOP, 1 << chn); + jz_set(TCU_ENABLE, 1 << chn); + + /* Configure GPIO function */ + struct pwm_state* st = &pwm_state[chn]; + gpio_config(st->gpio.port, st->gpio.pin, st->gpio.func); +} + +void pwm_disable(int chn) +{ + /* Set GPIO to output 0 */ + struct pwm_state* st = &pwm_state[chn]; + gpio_config(st->gpio.port, st->gpio.pin, GPIO_OUTPUT(0)); + + /* Stop timer */ + jz_clr(TCU_ENABLE, 1 << chn); + jz_set(TCU_STOP, 1 << chn); +} diff --git a/firmware/target/mips/ingenic_x1000/pwm-x1000.h b/firmware/target/mips/ingenic_x1000/pwm-x1000.h new file mode 100644 index 0000000000..0cea266d63 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/pwm-x1000.h @@ -0,0 +1,47 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 __PWM_X1000_H__ +#define __PWM_X1000_H__ + +/* Usage: + * - There are 5 PWM channels (0-4) corresponding to TCUs 0-4 + * - Call pwm_init(n) before using channel n + * - Call pwm_set_period() to change the period and duty cycle at any time + * - Call pwm_enable() and pwm_disable() to turn the output on and off + * - Don't allow two threads to control the same channel at the same time + * - Don't call pwm_init(), pwm_enable(), or pwm_disable() from an interrupt + * + * After calling pwm_init(), the channel is essentially in a disabled state so + * you will need to call pwm_set_period() and then pwm_enable() to turn it on. + * Don't alter the channel's TCU or GPIO pin state after calling pwm_init(). + * + * After calling pwm_disable(), it is safe to use the channel's TCU or GPIO pin + * for some other purpose, but you must call pwm_init() before you can use the + * channel as PWM output again. + */ + +extern void pwm_init(int chn); +extern void pwm_set_period(int chn, int period_ns, int duty_ns); +extern void pwm_enable(int chn); +extern void pwm_disable(int chn); + +#endif /* __PWM_X1000_H__ */ diff --git a/firmware/target/mips/ingenic_x1000/sd-x1000.c b/firmware/target/mips/ingenic_x1000/sd-x1000.c new file mode 100644 index 0000000000..7fba617ce3 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/sd-x1000.c @@ -0,0 +1,236 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 "storage.h" +#include "sdmmc.h" +#include "sd.h" +#include "msc-x1000.h" +#include <string.h> + +/* #define LOGF_ENABLE */ +#include "logf.h" + +static msc_drv* sd_to_msc[MSC_COUNT]; +static long _sd_last_disk_activity = 0; + +static int sd_init_card(msc_drv* d) +{ + int s; + if(s = msc_cmd_go_idle_state(d)) return -100 - s; + if(s = msc_cmd_send_if_cond(d)) return -110 - s; + if(s = msc_cmd_app_op_cond(d)) return -120 - s; + if(s = msc_cmd_all_send_cid(d)) return -130 - s; + if(s = msc_cmd_send_rca(d)) return -140 - s; + if(s = msc_cmd_send_csd(d)) return -150 - s; + if(s = msc_cmd_select_card(d)) return -160 - s; + if(s = msc_cmd_set_clr_card_detect(d, 0)) return -170 - s; + if(s = msc_cmd_set_bus_width(d, 4)) return -180 - s; + if(s = msc_cmd_switch_freq(d)) return -190 - s; + d->driver_flags |= MSC_DF_READY; + d->cardinfo.initialized = 1; + return 0; +} + +static int sd_transfer(msc_drv* d, bool write, + unsigned long start, int count, void* buf) +{ + int status = -1; + + msc_lock(d); + if(!d->card_present) + goto _exit; + + /* Hopefully puts the driver into a working state */ + if(d->driver_flags & MSC_DF_ERRSTATE) { + logf("MSC%d: attempting to reset after ERRSTATE", d->msc_nr); + msc_full_reset(d); + } + + /* Init card if needed */ + if((d->driver_flags & MSC_DF_READY) == 0) { + if(status = sd_init_card(d)) { + logf("MSC%d: card init failed (code %d)", d->msc_nr, status); + d->driver_flags |= MSC_DF_ERRSTATE; + d->cardinfo.initialized = status; + goto _exit; + } + } + + /* Ensure parameters are within range */ + if(count < 1) + goto _exit; + if(start + count > d->cardinfo.numblocks) + goto _exit; + + do { + /* We can only do 65536 blocks at a time */ + int xfer_count = count > 0xffff ? 0xffff : count; + + /* Set block length. I think this is only necessary for non-HCS cards. + * HCS cards always use 512 bytes so we shouldn't need it. + */ + if((d->driver_flags & MSC_DF_HCS_CARD) == 0) + if(status = msc_cmd_set_block_len(d, SD_BLOCK_SIZE)) + goto _exit; + + /* TODO - look into using CMD23 to improve transfer performance. + * This specifies the number of blocks ahead of time, instead of + * relying on CMD12 to stop transmission. CMD12 is still needed + * in the event of errors though. + */ + msc_req req = {0}; + req.data = buf; + req.nr_blocks = xfer_count; + req.block_len = SD_BLOCK_SIZE; + req.resptype = MSC_RESP_R1; + req.flags = MSC_RF_DATA; + if(xfer_count > 1) + req.flags |= MSC_RF_AUTO_CMD12; + if(write) { + req.command = xfer_count == 1 ? SD_WRITE_BLOCK + : SD_WRITE_MULTIPLE_BLOCK; + req.flags |= MSC_RF_PROG | MSC_RF_WRITE; + } else { + req.command = xfer_count == 1 ? SD_READ_SINGLE_BLOCK + : SD_READ_MULTIPLE_BLOCK; + } + + if(d->driver_flags & MSC_DF_V2_CARD) + req.argument = start; + else + req.argument = start * SD_BLOCK_SIZE; + + if(status = msc_cmd_exec(d, &req)) + goto _exit; + + /* TODO - properly handle reading the last block of the SD card + * This is likely to fail if we're reading near the end because + * the SD card will try to read past the last sector and then + * signal an error. So we need to ignore that error, but only if + * it was expected to occur. (See SD spec sec. 4.3.3, "Block Read") + */ + if(status = msc_cmd_send_status(d)) + goto _exit; + + /* Advance the buffer and adjust start/count */ + buf += xfer_count * SD_BLOCK_SIZE; + start += xfer_count; + count -= xfer_count; + } while(count > 0); + + _exit: + msc_unlock(d); + return status; +} + +int sd_read_sectors(IF_MD(int drive,) unsigned long start, + int count, void* buf) +{ + return sd_transfer(sd_to_msc[IF_MD_DRV(drive)], false, + start, count, buf); +} + +int sd_write_sectors(IF_MD(int drive,) unsigned long start, + int count, const void* buf) +{ + return sd_transfer(sd_to_msc[IF_MD_DRV(drive)], true, + start, count, (void*)buf); +} + +tCardInfo* card_get_info_target(int card_nr) +{ + /* Defensive measures */ + if(card_nr < 0 || card_nr >= MSC_COUNT || sd_to_msc[card_nr] == NULL) { + static tCardInfo null_info = { 0 }; + return &null_info; + } + + return &sd_to_msc[card_nr]->cardinfo; +} + +int sd_event(long id, intptr_t data) +{ + if(id == SYS_HOTSWAP_EXTRACTED) { + msc_drv* d = msc_get_by_drive(data); + if(d) + msc_full_reset(d); + return 0; + } else { + return storage_event_default_handler(id, data, _sd_last_disk_activity, + STORAGE_SD); + } +} + +long sd_last_disk_activity(void) +{ + return _sd_last_disk_activity; +} + +bool sd_present(IF_MD_NONVOID(int drive)) +{ + /* Seems that volume_properties() in firmware/common/disk.c may pass + * drive = -1 when the SD card is not inserted, so just return false. + */ + if(drive < 0) + return false; + + return sd_to_msc[IF_MD_DRV(drive)]->card_present; +} + +bool sd_removable(IF_MD_NONVOID(int drive)) +{ + /* Same reason as sd_present() */ + if(drive < 0) + return false; + + return sd_to_msc[IF_MD_DRV(drive)]->config->cd_gpio.pin != 0; +} + +#ifndef CONFIG_STORAGE_MULTI +static +#endif +int sd_num_drives(int first_drive) +{ + int n = 0; + for(; n < MSC_COUNT; ++n) { + msc_drv* d = msc_get(MSC_TYPE_SD, n); + if(d == NULL) + break; + + d->drive_nr = first_drive + n; + sd_to_msc[n] = d; + } + + for(int i = n; i < MSC_COUNT; ++i) + sd_to_msc[i] = NULL; + + return n; +} + +int sd_init(void) +{ + msc_init(); +#ifndef CONFIG_STORAGE_MULTI + sd_num_drives(0); +#endif + + return 0; +} diff --git a/firmware/target/mips/ingenic_x1000/sfc-x1000.c b/firmware/target/mips/ingenic_x1000/sfc-x1000.c new file mode 100644 index 0000000000..9537cdc035 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/sfc-x1000.c @@ -0,0 +1,298 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 "panic.h" +#include "sfc-x1000.h" +#include "gpio-x1000.h" +#include "irq-x1000.h" +#include "x1000/sfc.h" +#include "x1000/cpm.h" + +#ifndef BOOTLOADER_SPL +/* DMA only works once the system is properly booted */ +# define NEED_SFC_DMA +#endif + +#if defined(BOOTLOADER_SPL) +# if X1000_EXCLK_FREQ == 24000000 +# define FIXED_CLK_FREQ 600000000 +# define FIXED_CLK_SRC X1000_CLK_MPLL +# elif X1000_EXCLK_FREQ == 26000000 +# define FIXED_CLK_FREQ 598000000 +# define FIXED_CLK_SRC X1000_CLK_MPLL +# else +# error "bad EXCLK freq" +# endif +#endif + +#define FIFO_THRESH 31 + +#define SFC_STATUS_PENDING (-1) + +#ifdef NEED_SFC_DMA +static struct mutex sfc_mutex; +static struct semaphore sfc_sema; +static struct timeout sfc_lockup_tmo; +static bool sfc_inited = false; +static volatile int sfc_status; +#else +# define sfc_status SFC_STATUS_OK +#endif + +void sfc_init(void) +{ +#ifdef NEED_SFC_DMA + if(sfc_inited) + return; + + mutex_init(&sfc_mutex); + semaphore_init(&sfc_sema, 1, 0); + sfc_inited = true; +#endif +} + +void sfc_lock(void) +{ +#ifdef NEED_SFC_DMA + mutex_lock(&sfc_mutex); +#endif +} + +void sfc_unlock(void) +{ +#ifdef NEED_SFC_DMA + mutex_unlock(&sfc_mutex); +#endif +} + +void sfc_open(void) +{ + gpio_config(GPIO_A, 0x3f << 26, GPIO_DEVICE(1)); + jz_writef(CPM_CLKGR, SFC(0)); + jz_writef(SFC_GLB, OP_MODE_V(SLAVE), PHASE_NUM(1), + THRESHOLD(FIFO_THRESH), WP_EN(1)); + REG_SFC_CGE = 0; + REG_SFC_INTC = 0x1f; + REG_SFC_MEM_ADDR = 0; + +#ifdef NEED_SFC_DMA + jz_writef(SFC_GLB, OP_MODE_V(DMA), BURST_MD_V(INCR32)); + system_enable_irq(IRQ_SFC); +#endif +} + +void sfc_close(void) +{ +#ifdef NEED_SFC_DMA + system_disable_irq(IRQ_SFC); +#endif + + REG_SFC_CGE = 0x1f; + jz_writef(CPM_CLKGR, SFC(1)); +} + +void sfc_set_clock(x1000_clk_t clksrc, uint32_t freq) +{ + uint32_t in_freq; +#ifdef FIXED_CLK_FREQ + /* Small optimization to save code space in SPL by not polling clock */ + clksrc = FIXED_CLK_SRC; + in_freq = FIXED_CLK_FREQ; +#else + in_freq = clk_get(clksrc); +#endif + + uint32_t div = clk_calc_div(in_freq, freq); + jz_writef(CPM_SSICDR, CE(1), CLKDIV(div - 1), + SFC_CS(clksrc == X1000_CLK_MPLL ? 1 : 0)); + while(jz_readf(CPM_SSICDR, BUSY)); + jz_writef(CPM_SSICDR, CE(0)); +} + +#ifdef NEED_SFC_DMA +static int sfc_lockup_tmo_cb(struct timeout* tmo) +{ + (void)tmo; + + int irq = disable_irq_save(); + if(sfc_status == SFC_STATUS_PENDING) { + sfc_status = SFC_STATUS_LOCKUP; + jz_overwritef(SFC_TRIG, STOP(1)); + semaphore_release(&sfc_sema); + } + + restore_irq(irq); + return 0; +} + +static void sfc_wait_end(void) +{ + semaphore_wait(&sfc_sema, TIMEOUT_BLOCK); +} + +void SFC(void) +{ + unsigned sr = REG_SFC_SR & ~REG_SFC_INTC; + + if(jz_vreadf(sr, SFC_SR, OVER)) { + jz_overwritef(SFC_SCR, CLR_OVER(1)); + sfc_status = SFC_STATUS_OVERFLOW; + } else if(jz_vreadf(sr, SFC_SR, UNDER)) { + jz_overwritef(SFC_SCR, CLR_UNDER(1)); + sfc_status = SFC_STATUS_UNDERFLOW; + } else if(jz_vreadf(sr, SFC_SR, END)) { + jz_overwritef(SFC_SCR, CLR_END(1)); + sfc_status = SFC_STATUS_OK; + } else { + panicf("SFC IRQ bug"); + return; + } + + /* Not sure this is wholly correct */ + if(sfc_status != SFC_STATUS_OK) + jz_overwritef(SFC_TRIG, STOP(1)); + + REG_SFC_INTC = 0x1f; + semaphore_release(&sfc_sema); +} +#else +/* Note the X1000 is *very* picky about how the SFC FIFOs are accessed + * so please do NOT try to rearrange the code without testing it first! + */ + +void sfc_fifo_read(unsigned* buffer, int data_bytes) +{ + int data_words = (data_bytes + 3) / 4; + while(data_words > 0) { + if(jz_readf(SFC_SR, RREQ)) { + jz_overwritef(SFC_SCR, CLR_RREQ(1)); + + int amount = data_words > FIFO_THRESH ? FIFO_THRESH : data_words; + data_words -= amount; + while(amount > 0) { + *buffer++ = REG_SFC_DATA; + amount -= 1; + } + } + } +} + +void sfc_fifo_write(const unsigned* buffer, int data_bytes) +{ + int data_words = (data_bytes + 3) / 4; + while(data_words > 0) { + if(jz_readf(SFC_SR, TREQ)) { + jz_overwritef(SFC_SCR, CLR_TREQ(1)); + + int amount = data_words > FIFO_THRESH ? FIFO_THRESH : data_words; + data_words -= amount; + while(amount > 0) { + REG_SFC_DATA = *buffer++; + amount -= 1; + } + } + } +} + +static void sfc_wait_end(void) +{ + while(jz_readf(SFC_SR, END) == 0); + jz_overwritef(SFC_SCR, CLR_TREQ(1)); +} + +#endif /* NEED_SFC_DMA */ + +int sfc_exec(const sfc_op* op) +{ +#ifdef NEED_SFC_DMA + uint32_t intc_clear = jz_orm(SFC_INTC, MSK_END); +#endif + + if(op->flags & (SFC_FLAG_READ|SFC_FLAG_WRITE)) { + jz_writef(SFC_TRAN_CONF(0), DATA_EN(1)); + REG_SFC_TRAN_LENGTH = op->data_bytes; +#ifdef NEED_SFC_DMA + REG_SFC_MEM_ADDR = PHYSADDR(op->buffer); +#endif + + if(op->flags & SFC_FLAG_READ) + { + jz_writef(SFC_GLB, TRAN_DIR_V(READ)); +#ifdef NEED_SFC_DMA + discard_dcache_range(op->buffer, op->data_bytes); + intc_clear |= jz_orm(SFC_INTC, MSK_OVER); +#endif + } + else + { + jz_writef(SFC_GLB, TRAN_DIR_V(WRITE)); +#ifdef NEED_SFC_DMA + commit_dcache_range(op->buffer, op->data_bytes); + intc_clear |= jz_orm(SFC_INTC, MSK_UNDER); +#endif + } + } else { + jz_writef(SFC_TRAN_CONF(0), DATA_EN(0)); + REG_SFC_TRAN_LENGTH = 0; +#ifdef NEED_SFC_DMA + REG_SFC_MEM_ADDR = 0; +#endif + } + + bool dummy_first = (op->flags & SFC_FLAG_DUMMYFIRST) != 0; + jz_writef(SFC_TRAN_CONF(0), + MODE(op->mode), POLL_EN(0), + ADDR_WIDTH(op->addr_bytes), + PHASE_FMT(dummy_first ? 1 : 0), + DUMMY_BITS(op->dummy_bits), + COMMAND(op->command), CMD_EN(1)); + + REG_SFC_DEV_ADDR(0) = op->addr_lo; + REG_SFC_DEV_PLUS(0) = op->addr_hi; + +#ifdef NEED_SFC_DMA + sfc_status = SFC_STATUS_PENDING; + timeout_register(&sfc_lockup_tmo, sfc_lockup_tmo_cb, 10*HZ, 0); + REG_SFC_SCR = 0x1f; + REG_SFC_INTC &= ~intc_clear; +#endif + + jz_overwritef(SFC_TRIG, FLUSH(1)); + jz_overwritef(SFC_TRIG, START(1)); + +#ifndef NEED_SFC_DMA + if(op->flags & SFC_FLAG_READ) + sfc_fifo_read((unsigned*)op->buffer, op->data_bytes); + if(op->flags & SFC_FLAG_WRITE) + sfc_fifo_write((const unsigned*)op->buffer, op->data_bytes); +#endif + + sfc_wait_end(); + +#ifdef NEED_SFC_DMA + if(op->flags & SFC_FLAG_READ) + discard_dcache_range(op->buffer, op->data_bytes); +#endif + + return sfc_status; +} diff --git a/firmware/target/mips/ingenic_x1000/sfc-x1000.h b/firmware/target/mips/ingenic_x1000/sfc-x1000.h new file mode 100644 index 0000000000..283f171697 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/sfc-x1000.h @@ -0,0 +1,105 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 <stdint.h> +#include <stdbool.h> +#include "clk-x1000.h" +#include "x1000/sfc.h" + +/* SPI flash controller interface -- this is a low-level driver upon which + * you can build NAND/NOR flash drivers. The main function is sfc_exec(), + * used to issue commands, transfer data, etc. + */ + +#define SFC_FLAG_READ 0x01 /* Read data */ +#define SFC_FLAG_WRITE 0x02 /* Write data */ +#define SFC_FLAG_DUMMYFIRST 0x04 /* Do dummy bits before sending address. + * Default is dummy bits after address. + */ + +/* SPI transfer mode. If in doubt, check with the X1000 manual and confirm + * the transfer format is what you expect. + */ +#define SFC_MODE_STANDARD 0 +#define SFC_MODE_DUAL_IN_DUAL_OUT 1 +#define SFC_MODE_DUAL_IO 2 +#define SFC_MODE_FULL_DUAL_IO 3 +#define SFC_MODE_QUAD_IN_QUAD_OUT 4 +#define SFC_MODE_QUAD_IO 5 +#define SFC_MODE_FULL_QUAD_IO 6 + +/* Return status codes for sfc_exec() */ +#define SFC_STATUS_OK 0 +#define SFC_STATUS_OVERFLOW 1 +#define SFC_STATUS_UNDERFLOW 2 +#define SFC_STATUS_LOCKUP 3 + +typedef struct sfc_op { + int command; /* Command number */ + int mode; /* SPI transfer mode */ + int flags; /* Flags for this op */ + int addr_bytes; /* Number of address bytes */ + int dummy_bits; /* Number of dummy bits (yes: bits, not bytes) */ + uint32_t addr_lo; /* Lower 32 bits of address */ + uint32_t addr_hi; /* Upper 32 bits of address */ + int data_bytes; /* Number of data bytes to read/write */ + void* buffer; /* Data buffer -- MUST be word-aligned */ +} sfc_op; + +/* One-time driver init for mutexes/etc needed for handling interrupts. + * This can be safely called multiple times; only the first call will + * actually perform the init. + */ +extern void sfc_init(void); + +/* Controller mutex -- lock before touching the driver */ +extern void sfc_lock(void); +extern void sfc_unlock(void); + +/* Open/close the driver. The driver must be open in order to do operations. + * Closing the driver shuts off the hardware; the driver can be re-opened at + * a later time when it's needed again. + * + * After opening the driver, you must also program a valid device configuration + * and clock rate using sfc_set_dev_conf() and sfc_set_clock(). + */ +extern void sfc_open(void); +extern void sfc_close(void); + +/* These functions can be called at any time while the driver is open, but + * must not be called while there is an operation in progress. It's the + * caller's job to ensure the configuration will work with the device and + * be capable of reading back data correctly. + * + * - sfc_set_dev_conf() writes its argument to the SFC_DEV_CONF register. + * - sfc_set_wp_enable() sets the state of the write-protect pin (WP). + * - sfc_set_clock() sets the controller clock frequency (in Hz). + */ +#define sfc_set_dev_conf(dev_conf) \ + do { REG_SFC_DEV_CONF = (dev_conf); } while(0) + +#define sfc_set_wp_enable(en) \ + jz_writef(SFC_GLB, WP_EN((en) ? 1 : 0)) + +extern void sfc_set_clock(x1000_clk_t clksrc, uint32_t freq); + +/* Execute an operation. Returns zero on success, nonzero on failure. */ +extern int sfc_exec(const sfc_op* op); diff --git a/firmware/target/mips/ingenic_x1000/spl.lds b/firmware/target/mips/ingenic_x1000/spl.lds new file mode 100644 index 0000000000..2a0b6b3eaa --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/spl.lds @@ -0,0 +1,47 @@ +#include "config.h" + +OUTPUT_FORMAT("elf32-littlemips") +OUTPUT_ARCH(MIPS) +ENTRY(_start) +STARTUP(target/mips/ingenic_x1000/crt0.o) + +/* TCSM is 16 KiB and is mapped starting at address 0xf4000000. + * + * The SPL is loaded to TCSM + 0x1000. The area below that is stack space. + * The first 2 KiB of SPL is just headers. The code begins at TCSM + 0x1800. + * The maskrom will jump to that address (via jalr) after loading the SPL. + */ +MEMORY { TCSM : ORIGIN = 0xf4001800, LENGTH = 0x2800 } + +SECTIONS +{ + .text : + { + *(.init.text); + *(.text*); + } > TCSM + + . = ALIGN(4); + .rodata : + { + *(.rodata*); + } > TCSM + + . = ALIGN(4); + .data : + { + *(.data*); + *(.sdata*); + } > TCSM + + . = ALIGN(4); + .bss (NOLOAD) : + { + _bssbegin = .; + *(.sbss*); + *(.bss*); + *(COMMON); + *(.scommon*); + _bssend = .; + } > TCSM +} diff --git a/firmware/target/mips/ingenic_x1000/system-target.h b/firmware/target/mips/ingenic_x1000/system-target.h new file mode 100644 index 0000000000..a2f0a6ff70 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/system-target.h @@ -0,0 +1,148 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 __SYSTEM_TARGET_H__ +#define __SYSTEM_TARGET_H__ + +/* For the sake of system.h CACHEALIGN macros. + * We need this to align DMA buffers, etc. + */ +#define CACHEALIGN_BITS 5 +#define CACHE_SIZE (16*1024) + +#include "mmu-mips.h" +#include "mipsregs.h" +#include "mipsr2-endian.h" +#include <stdint.h> + +/* Get physical address for DMA */ +#define PHYSADDR(addr) (((unsigned long)(addr)) & 0x1fffffff) + +#define HIGHEST_IRQ_LEVEL 0 + +/* Rockbox API */ +#define enable_irq() set_c0_status(ST0_IE) +#define disable_irq() clear_c0_status(ST0_IE) +#define disable_irq_save() set_irq_level(0) +#define restore_irq(arg) write_c0_status(arg) + +static inline int set_irq_level(int lev) +{ + unsigned reg, oldreg; + reg = oldreg = read_c0_status(); + if(lev) + reg |= ST0_IE; + else + reg &= ~ST0_IE; + + write_c0_status(reg); + return oldreg; +} + +/* CPU idle stats, updated each kernel tick in kernel-x1000.c */ +extern int __cpu_idle_avg; +extern int __cpu_idle_cur; +extern uint32_t __cpu_idle_ticks; +extern uint32_t __cpu_idle_reftick; + +static inline uint32_t __ost_read32(void); +static inline void core_sleep(void) +{ + uint32_t t1 = __ost_read32(); + + __asm__ __volatile__( + ".set push\n\t" + ".set mips32r2\n\t" + "mfc0 $8, $12\n\t" + "move $9, $8\n\t" + "la $10, 0x8000000\n\t" + "or $8, $10\n\t" + "mtc0 $8, $12\n\t" + "wait\n\t" + "mtc0 $9, $12\n\t" + ".set pop\n\t" + ::: "t0", "t1", "t2"); + + uint32_t t2 = __ost_read32(); + __cpu_idle_ticks += t2 - t1; + + enable_irq(); +} + +/* IRQ control */ +extern void system_enable_irq(int irq); +extern void system_disable_irq(int irq); + +/* Simple delay API */ +#define OST_FREQUENCY (X1000_EXCLK_FREQ / 4) +#define OST_TICKS_PER_US (OST_FREQUENCY / 1000000) +#define MAX_OST_DELAY_ARG 0x7fffffff +#define MAX_UDELAY_ARG (MAX_OST_DELAY_ARG / OST_TICKS_PER_US) +#define MAX_MDELAY_ARG (MAX_UDELAY_ARG / 1000) + +/* Macros adapted from include/linux/delay.h, + * Copyright (C) 1993 Linus Torvalds + * + * These optimize away all calculations to compile time for the common case + * of small constant arguments, reducing to a single __ost_delay() call. + */ + +#define udelay(n) \ + ((__builtin_constant_p(n) && (n) <= MAX_UDELAY_ARG) ? \ + __ost_delay((n) * OST_TICKS_PER_US) : __udelay((n))) + +#define mdelay(n) \ + ((__builtin_constant_p(n) && (n) <= MAX_MDELAY_ARG) ? \ + __ost_delay((n) * 1000 * OST_TICKS_PER_US) : __mdelay((n))) + +/* Slow path implementations which handle their full argument range by + * looping and calling __ost_delay() repeatedly. + */ +extern void __udelay(uint32_t us); +extern void __mdelay(uint32_t ms); + +/* Read full 64-bit OST counter value; this requires disabling IRQs + * to safely read the counter. + */ +extern uint64_t __ost_read64(void); + +static inline uint32_t __ost_read32(void) +{ + /* Read OST_2CNTL using raw address to avoid exposing internal headers. + * The 64-bit counter is read with IRQs disabled and since threads are + * not pre-emptive in Rockbox we won't trash anybody's 64-bit read by + * reading the low count without locking. + */ + return *(const volatile uint32_t*)0xb2000020; +} + +/* NOTE: it is required that count < MAX_OST_DELAY_ARG, this is to provide + * some slack in the 32-bit counter so we can reliably detect the timeout. + */ +static inline void __ost_delay(uint32_t count) +{ + /* Add one to ensure we delay for at least the time given */ + count += 1; + uint32_t start = __ost_read32(); + while(__ost_read32() - start < count); +} + +#endif /* __SYSTEM_TARGET_H__ */ diff --git a/firmware/target/mips/ingenic_x1000/system-x1000.c b/firmware/target/mips/ingenic_x1000/system-x1000.c new file mode 100644 index 0000000000..54513cffb2 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/system-x1000.c @@ -0,0 +1,418 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 "mips.h" +#include "panic.h" +#include "button.h" +#include "gpio-x1000.h" +#include "dma-x1000.h" +#include "irq-x1000.h" +#include "clk-x1000.h" +#include "x1000/cpm.h" +#include "x1000/ost.h" +#include "x1000/tcu.h" +#include "x1000/wdt.h" +#include "x1000/intc.h" +#include "x1000/msc.h" +#include "x1000/aic.h" + +int __cpu_idle_avg = 0; +int __cpu_idle_cur = 0; +uint32_t __cpu_idle_ticks = 0; +uint32_t __cpu_idle_reftick = 0; + +static void system_init_clk(void) +{ + /* Gate all clocks except CPU/bus/memory/RTC */ + REG_CPM_CLKGR = ~jz_orm(CPM_CLKGR, CPU_BIT, DDR, AHB0, APB0, RTC); + + /* Switch to EXCLK */ + clk_set_ccr_mux(CLKMUX_SCLK_A(EXCLK) | CLKMUX_CPU(SCLK_A) | + CLKMUX_AHB0(SCLK_A) | CLKMUX_AHB2(SCLK_A)); + clk_set_ccr_div(1, 1, 1, 1, 1); + +#ifdef FIIO_M3K + /* Nominal clock configuration + * --------------------------- + * APLL at 1 GHz, MPLL disabled + * CPU at 1 GHz, L2 cache at 500 MHz + * AHB0 and AHB2 at 200 MHz + * PCLK at 100 MHz + * DDR at 200 MHz + */ + jz_writef(CPM_APCR, BS(1), PLLM(41), PLLN(0), PLLOD(0), ENABLE(1)); + while(jz_readf(CPM_APCR, ON) == 0); + + clk_set_ccr_div(1, 2, 5, 5, 10); + clk_set_ccr_mux(CLKMUX_SCLK_A(APLL) | CLKMUX_CPU(SCLK_A) | + CLKMUX_AHB0(SCLK_A) | CLKMUX_AHB2(SCLK_A)); + clk_set_ddr(X1000_CLK_SCLK_A, 5); + + /* Shut off MPLL, since nobody should be using it now */ + jz_writef(CPM_MPCR, ENABLE(0)); +#else +# error "Please define system clock configuration for target" +#endif +} + +/* Prepare the CPU to process interrupts, but don't enable them yet */ +static void system_init_irq(void) +{ + /* Mask all interrupts */ + jz_set(INTC_MSK(0), 0xffffffff); + jz_set(INTC_MSK(1), 0xffffffff); + + /* It's safe to unmask these unconditionally */ + jz_clr(INTC_MSK(0), (1 << IRQ0_GPIO0) | (1 << IRQ0_GPIO1) | + (1 << IRQ0_GPIO2) | (1 << IRQ0_GPIO3) | + (1 << IRQ0_TCU1)); + + /* Setup CP0 registers */ + write_c0_status(M_StatusCU0 | M_StatusIM2 | M_StatusIM3); + write_c0_cause(M_CauseIV); +} + +/* First thing called from Rockbox main() */ +void system_init(void) +{ + /* Setup system clocks */ + system_init_clk(); + + /* Ungate timers and turn them all off by default */ + jz_writef(CPM_CLKGR, TCU(0), OST(0)); + jz_clrf(OST_ENABLE, OST1, OST2); + jz_write(OST_1MSK, 1); + jz_write(OST_1FLG, 0); + jz_clr(TCU_ENABLE, 0x80ff); + jz_set(TCU_MASK, 0xff10ff); + jz_clr(TCU_FLAG, 0xff10ff); + jz_set(TCU_STOP, 0x180ff); + + /* Start OST2, needed for delay timer */ + jz_writef(OST_CTRL, PRESCALE2_V(BY_4)); + jz_writef(OST_CLEAR, OST2(1)); + jz_write(OST_2CNTH, 0); + jz_write(OST_2CNTL, 0); + jz_setf(OST_ENABLE, OST2); + + /* Ensure CPU sleep mode is IDLE and not SLEEP */ + jz_writef(CPM_LCR, LPM_V(IDLE)); + + /* All other init */ + gpio_init(); + system_init_irq(); + dma_init(); + mmu_init(); +} + +#ifdef HAVE_ADJUSTABLE_CPU_FREQ +void set_cpu_frequency(long tgt_freq) +{ + /* Clamp target frequency to "sane" values */ + if(tgt_freq < 0) tgt_freq = 0; + if(tgt_freq > CPU_FREQ) tgt_freq = CPU_FREQ; + + /* Find out input clock */ + uint32_t in_freq; + switch(jz_readf(CPM_CCR, SEL_CPLL)) { + case 1: in_freq = clk_get(X1000_CLK_SCLK_A); break; + case 2: in_freq = clk_get(X1000_CLK_MPLL); break; + default: return; + } + + /* Clamp to valid range */ + if(tgt_freq < 1) + tgt_freq = 1; + if(tgt_freq > (long)in_freq) + tgt_freq = in_freq; + + /* Calculate CPU clock divider */ + uint32_t cdiv = clk_calc_div(in_freq, tgt_freq); + if(cdiv > 16) cdiv = 16; + if(cdiv < 1) cdiv = 1; + + /* Calculate L2 cache clock. */ + uint32_t l2div = cdiv; + if(cdiv == 1) + l2div = 2; + + /* Change CPU/L2 frequency */ + jz_writef(CPM_CCR, CE_CPU(1), L2DIV(l2div - 1), CDIV(cdiv - 1)); + while(jz_readf(CPM_CSR, CDIV_BUSY)); + jz_writef(CPM_CCR, CE_CPU(0)); + + /* Update value for Rockbox */ + cpu_frequency = in_freq / cdiv; +} +#endif + +void system_reboot(void) +{ + jz_clr(TCU_STOP, 0x10000); + jz_writef(WDT_CTRL, PRESCALE_V(BY_4), SOURCE_V(EXT)); + jz_write(WDT_COUNT, 0); + jz_write(WDT_DATA, X1000_EXCLK_FREQ / 1000); + jz_write(WDT_ENABLE, 1); + while(1); +} + +int system_memory_guard(int mode) +{ + /* unused */ + (void)mode; + return 0; +} + +/* Simple delay API -- slow path functions */ + +void __udelay(uint32_t us) +{ + while(us > MAX_UDELAY_ARG) { + __ost_delay(MAX_UDELAY_ARG * OST_TICKS_PER_US); + us -= MAX_UDELAY_ARG; + } + + __ost_delay(us * OST_TICKS_PER_US); +} + +void __mdelay(uint32_t ms) +{ + while(ms > MAX_MDELAY_ARG) { + __ost_delay(MAX_MDELAY_ARG * 1000 * OST_TICKS_PER_US); + ms -= MAX_MDELAY_ARG; + } + + __ost_delay(ms * 1000 * OST_TICKS_PER_US); +} + +uint64_t __ost_read64(void) +{ + int irq = disable_irq_save(); + uint64_t lcnt = REG_OST_2CNTL; + uint64_t hcnt = REG_OST_2CNTHB; + restore_irq(irq); + return (hcnt << 32) | lcnt; +} + +/* IRQ handling */ +static int irq = 0; +static unsigned ipr0 = 0, ipr1 = 0; + +static void UIRQ(void) +{ + panicf("Unhandled interrupt occurred: %d", irq); +} + +#define intr(name) extern __attribute__((weak, alias("UIRQ"))) void name(void) + +/* Main interrupts */ +intr(DMIC); intr(AIC); intr(SFC); intr(SSI0); intr(OTG); intr(AES); +intr(TCU2); intr(TCU1); intr(TCU0); intr(CIM); intr(LCD); intr(RTC); +intr(MSC1); intr(MSC0); intr(SCC); intr(PCM0); intr(HARB2); intr(HARB0); +intr(CPM); intr(UART2); intr(UART1); intr(UART0); intr(DDR); intr(EFUSE); +intr(MAC); intr(I2C2); intr(I2C1); intr(I2C0); intr(JPEG); +intr(PDMA); intr(PDMAD); intr(PDMAM); +/* GPIO A - 32 pins */ +intr(GPIOA00); intr(GPIOA01); intr(GPIOA02); intr(GPIOA03); intr(GPIOA04); +intr(GPIOA05); intr(GPIOA06); intr(GPIOA07); intr(GPIOA08); intr(GPIOA09); +intr(GPIOA10); intr(GPIOA11); intr(GPIOA12); intr(GPIOA13); intr(GPIOA14); +intr(GPIOA15); intr(GPIOA16); intr(GPIOA17); intr(GPIOA18); intr(GPIOA19); +intr(GPIOA20); intr(GPIOA21); intr(GPIOA22); intr(GPIOA23); intr(GPIOA24); +intr(GPIOA25); intr(GPIOA26); intr(GPIOA27); intr(GPIOA28); intr(GPIOA29); +intr(GPIOA30); intr(GPIOA31); +/* GPIO B - 32 pins */ +intr(GPIOB00); intr(GPIOB01); intr(GPIOB02); intr(GPIOB03); intr(GPIOB04); +intr(GPIOB05); intr(GPIOB06); intr(GPIOB07); intr(GPIOB08); intr(GPIOB09); +intr(GPIOB10); intr(GPIOB11); intr(GPIOB12); intr(GPIOB13); intr(GPIOB14); +intr(GPIOB15); intr(GPIOB16); intr(GPIOB17); intr(GPIOB18); intr(GPIOB19); +intr(GPIOB20); intr(GPIOB21); intr(GPIOB22); intr(GPIOB23); intr(GPIOB24); +intr(GPIOB25); intr(GPIOB26); intr(GPIOB27); intr(GPIOB28); intr(GPIOB29); +intr(GPIOB30); intr(GPIOB31); +/* GPIO C - 26 pins */ +intr(GPIOC00); intr(GPIOC01); intr(GPIOC02); intr(GPIOC03); intr(GPIOC04); +intr(GPIOC05); intr(GPIOC06); intr(GPIOC07); intr(GPIOC08); intr(GPIOC09); +intr(GPIOC10); intr(GPIOC11); intr(GPIOC12); intr(GPIOC13); intr(GPIOC14); +intr(GPIOC15); intr(GPIOC16); intr(GPIOC17); intr(GPIOC18); intr(GPIOC19); +intr(GPIOC20); intr(GPIOC21); intr(GPIOC22); intr(GPIOC23); intr(GPIOC24); +intr(GPIOC25); +/* GPIO D - 6 pins */ +intr(GPIOD00); intr(GPIOD01); intr(GPIOD02); intr(GPIOD03); intr(GPIOD04); +intr(GPIOD05); + +/* OST interrupt -- has no IRQ number since it's got special handling */ +intr(OST); + +#undef intr + +static void(*const irqvector[])(void) = { + /* ICSR0: 0 - 31 */ + DMIC, AIC, UIRQ, UIRQ, UIRQ, UIRQ, UIRQ, SFC, + SSI0, UIRQ, PDMA, PDMAD, UIRQ, UIRQ, UIRQ, UIRQ, + UIRQ, UIRQ, UIRQ, UIRQ, UIRQ, OTG, UIRQ, AES, + UIRQ, TCU2, TCU1, TCU0, UIRQ, UIRQ, CIM, LCD, + /* ICSR1: 32 - 63 */ + RTC, UIRQ, UIRQ, UIRQ, MSC1, MSC0, SCC, UIRQ, + PCM0, UIRQ, UIRQ, UIRQ, HARB2, UIRQ, HARB0, CPM, + UIRQ, UART2, UART1, UART0, DDR, UIRQ, EFUSE, MAC, + UIRQ, UIRQ, I2C2, I2C1, I2C0, PDMAM, JPEG, UIRQ, + /* GPIO A: 64 - 95 */ + GPIOA00, GPIOA01, GPIOA02, GPIOA03, GPIOA04, GPIOA05, GPIOA06, GPIOA07, + GPIOA08, GPIOA09, GPIOA10, GPIOA11, GPIOA12, GPIOA13, GPIOA14, GPIOA15, + GPIOA16, GPIOA17, GPIOA18, GPIOA19, GPIOA20, GPIOA21, GPIOA22, GPIOA23, + GPIOA24, GPIOA25, GPIOA26, GPIOA27, GPIOA28, GPIOA29, GPIOA30, GPIOA31, + /* GPIO B: 96 - 127 */ + GPIOB00, GPIOB01, GPIOB02, GPIOB03, GPIOB04, GPIOB05, GPIOB06, GPIOB07, + GPIOB08, GPIOB09, GPIOB10, GPIOB11, GPIOB12, GPIOB13, GPIOB14, GPIOB15, + GPIOB16, GPIOB17, GPIOB18, GPIOB19, GPIOB20, GPIOB21, GPIOB22, GPIOB23, + GPIOB24, GPIOB25, GPIOB26, GPIOB27, GPIOB28, GPIOB29, GPIOB30, GPIOB31, + /* GPIO C: 128 - 159 */ + GPIOC00, GPIOC01, GPIOC02, GPIOC03, GPIOC04, GPIOC05, GPIOC06, GPIOC07, + GPIOC08, GPIOC09, GPIOC10, GPIOC11, GPIOC12, GPIOC13, GPIOC14, GPIOC15, + GPIOC16, GPIOC17, GPIOC18, GPIOC19, GPIOC20, GPIOC21, GPIOC22, GPIOC23, + GPIOC24, GPIOC25, UIRQ, UIRQ, UIRQ, UIRQ, UIRQ, UIRQ, + /* GPIO D: 160 - 165 */ + GPIOD00, GPIOD01, GPIOD02, GPIOD03, GPIOD04, GPIOD05, +}; + +void system_enable_irq(int irq) +{ + if(IRQ_IS_GROUP0(irq)) { + jz_clr(INTC_MSK(0), 1 << IRQ_TO_GROUP0(irq)); + } else if(IRQ_IS_GROUP1(irq)) { + jz_clr(INTC_MSK(1), 1 << IRQ_TO_GROUP1(irq)); + } +} + +void system_disable_irq(int irq) +{ + if(IRQ_IS_GROUP0(irq)) { + jz_set(INTC_MSK(0), 1 << IRQ_TO_GROUP0(irq)); + } else if(IRQ_IS_GROUP1(irq)) { + jz_set(INTC_MSK(1), 1 << IRQ_TO_GROUP1(irq)); + } +} + +static int vector_gpio_irq(int port) +{ + int n = find_first_set_bit(REG_GPIO_FLAG(port)); + if(n & 32) + return -1; + + jz_clr(GPIO_FLAG(port), 1 << n); + return IRQ_GPIO(port, n); +} + +static int vector_irq(void) +{ + int n = find_first_set_bit(ipr0); + if(n & 32) { + n = find_first_set_bit(ipr1); + if(n & 32) + return -1; + ipr1 &= ~(1 << n); + n += 32; + } else { + ipr0 &= ~(1 << n); + } + + switch(n) { + case IRQ0_GPIO0: n = vector_gpio_irq(GPIO_A); break; + case IRQ0_GPIO1: n = vector_gpio_irq(GPIO_B); break; + case IRQ0_GPIO2: n = vector_gpio_irq(GPIO_C); break; + case IRQ0_GPIO3: n = vector_gpio_irq(GPIO_D); break; + default: break; + } + + return n; +} + +void intr_handler(unsigned cause) +{ + /* OST interrupt is handled separately */ + if(cause & M_CauseIP3) { + OST(); + return; + } + + /* Gather pending interrupts */ + ipr0 |= REG_INTC_PND(0); + ipr1 |= REG_INTC_PND(1); + + /* Process and dispatch interrupt */ + irq = vector_irq(); + if(irq < 0) + return; + + irqvector[irq](); +} + +void tlb_refill_handler(void) +{ + panicf("TLB refill handler at 0x%08lx! [0x%x]", + read_c0_epc(), read_c0_badvaddr()); +} + +#define EXC(x,y) case (x): return (y); +static char* parse_exception(unsigned cause) +{ + switch(cause & M_CauseExcCode) + { + EXC(EXC_INT, "Interrupt"); + EXC(EXC_MOD, "TLB Modified"); + EXC(EXC_TLBL, "TLB Exception (Load or Ifetch)"); + EXC(EXC_ADEL, "Address Error (Load or Ifetch)"); + EXC(EXC_ADES, "Address Error (Store)"); + EXC(EXC_TLBS, "TLB Exception (Store)"); + EXC(EXC_IBE, "Instruction Bus Error"); + EXC(EXC_DBE, "Data Bus Error"); + EXC(EXC_SYS, "Syscall"); + EXC(EXC_BP, "Breakpoint"); + EXC(EXC_RI, "Reserved Instruction"); + EXC(EXC_CPU, "Coprocessor Unusable"); + EXC(EXC_OV, "Overflow"); + EXC(EXC_TR, "Trap Instruction"); + EXC(EXC_FPE, "Floating Point Exception"); + EXC(EXC_C2E, "COP2 Exception"); + EXC(EXC_MDMX, "MDMX Exception"); + EXC(EXC_WATCH, "Watch Exception"); + EXC(EXC_MCHECK, "Machine Check Exception"); + EXC(EXC_CacheErr, "Cache error caused re-entry to Debug Mode"); + default: + return 0; + } +} +#undef EXC + +void exception_handler(unsigned cause, unsigned epc, unsigned stack_ptr) +{ + panicf("Exception occurred: %s [0x%08x] at 0x%08x (stack at 0x%08x)", + parse_exception(cause), read_c0_badvaddr(), epc, stack_ptr); +} + +void system_exception_wait(void) +{ +#ifdef FIIO_M3K + while(button_read_device() != (BUTTON_POWER|BUTTON_VOL_DOWN)); +#else + while(1); +#endif +} diff --git a/firmware/target/mips/ingenic_x1000/timer-x1000.c b/firmware/target/mips/ingenic_x1000/timer-x1000.c new file mode 100644 index 0000000000..de97cbb3a3 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/timer-x1000.c @@ -0,0 +1,85 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 "timer.h" +#include "x1000/tcu.h" + +#define TIMER_CHN 5 + +bool timer_set(long cycles, bool start) +{ + if(cycles <= 0) + return false; + + /* Calculate timer interval */ + unsigned long counter = cycles; + unsigned prescale = 0; + while(counter > 0xffff && prescale < 5) { + counter /= 4; + prescale += 1; + } + + /* Duration too long */ + if(counter > 0xffff) + return false; + + /* Unregister old function */ + if(start && pfn_unregister) { + pfn_unregister(); + pfn_unregister = 0; + } + + /* Configure the timer */ + jz_clr(TCU_STOP, 1 << TIMER_CHN); + jz_clr(TCU_ENABLE, 1 << TIMER_CHN); + jz_overwritef(TCU_CTRL(TIMER_CHN), SOURCE_V(EXT), PRESCALE(prescale)); + jz_write(TCU_CMP_FULL(TIMER_CHN), counter); + jz_write(TCU_CMP_HALF(TIMER_CHN), 0); + jz_clr(TCU_FLAG, 1 << TIMER_CHN); + jz_clr(TCU_MASK, 1 << TIMER_CHN); + + if(start) + return timer_start(); + else + return true; +} + +bool timer_start(void) +{ + jz_set(TCU_ENABLE, 1 << TIMER_CHN); + return true; +} + +void timer_stop(void) +{ + jz_clr(TCU_ENABLE, 1 << TIMER_CHN); + jz_set(TCU_MASK, 1 << TIMER_CHN); + jz_clr(TCU_FLAG, 1 << TIMER_CHN); + jz_set(TCU_STOP, 1 << TIMER_CHN); +} + +void TCU1(void) +{ + jz_clr(TCU_FLAG, 1 << TIMER_CHN); + + if(pfn_timer) + pfn_timer(); +} diff --git a/firmware/target/mips/ingenic_x1000/x1000/aic.h b/firmware/target/mips/ingenic_x1000/x1000/aic.h new file mode 100644 index 0000000000..e9c68511d7 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/x1000/aic.h @@ -0,0 +1,359 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * This file was automatically generated by headergen, DO NOT EDIT it. + * headergen version: 3.0.0 + * x1000 version: 1.0 + * x1000 authors: Aidan MacDonald + * + * Copyright (C) 2015 by the authors + * + * 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 __HEADERGEN_AIC_H__ +#define __HEADERGEN_AIC_H__ + +#include "macro.h" + +#define REG_AIC_CFG jz_reg(AIC_CFG) +#define JA_AIC_CFG (0xb0020000 + 0x0) +#define JT_AIC_CFG JIO_32_RW +#define JN_AIC_CFG AIC_CFG +#define JI_AIC_CFG +#define BP_AIC_CFG_RFTH 24 +#define BM_AIC_CFG_RFTH 0xf000000 +#define BF_AIC_CFG_RFTH(v) (((v) & 0xf) << 24) +#define BFM_AIC_CFG_RFTH(v) BM_AIC_CFG_RFTH +#define BF_AIC_CFG_RFTH_V(e) BF_AIC_CFG_RFTH(BV_AIC_CFG_RFTH__##e) +#define BFM_AIC_CFG_RFTH_V(v) BM_AIC_CFG_RFTH +#define BP_AIC_CFG_TFTH 16 +#define BM_AIC_CFG_TFTH 0x1f0000 +#define BF_AIC_CFG_TFTH(v) (((v) & 0x1f) << 16) +#define BFM_AIC_CFG_TFTH(v) BM_AIC_CFG_TFTH +#define BF_AIC_CFG_TFTH_V(e) BF_AIC_CFG_TFTH(BV_AIC_CFG_TFTH__##e) +#define BFM_AIC_CFG_TFTH_V(v) BM_AIC_CFG_TFTH +#define BP_AIC_CFG_MSB 12 +#define BM_AIC_CFG_MSB 0x1000 +#define BF_AIC_CFG_MSB(v) (((v) & 0x1) << 12) +#define BFM_AIC_CFG_MSB(v) BM_AIC_CFG_MSB +#define BF_AIC_CFG_MSB_V(e) BF_AIC_CFG_MSB(BV_AIC_CFG_MSB__##e) +#define BFM_AIC_CFG_MSB_V(v) BM_AIC_CFG_MSB +#define BP_AIC_CFG_IBCKD 10 +#define BM_AIC_CFG_IBCKD 0x400 +#define BF_AIC_CFG_IBCKD(v) (((v) & 0x1) << 10) +#define BFM_AIC_CFG_IBCKD(v) BM_AIC_CFG_IBCKD +#define BF_AIC_CFG_IBCKD_V(e) BF_AIC_CFG_IBCKD(BV_AIC_CFG_IBCKD__##e) +#define BFM_AIC_CFG_IBCKD_V(v) BM_AIC_CFG_IBCKD +#define BP_AIC_CFG_ISYNCD 9 +#define BM_AIC_CFG_ISYNCD 0x200 +#define BF_AIC_CFG_ISYNCD(v) (((v) & 0x1) << 9) +#define BFM_AIC_CFG_ISYNCD(v) BM_AIC_CFG_ISYNCD +#define BF_AIC_CFG_ISYNCD_V(e) BF_AIC_CFG_ISYNCD(BV_AIC_CFG_ISYNCD__##e) +#define BFM_AIC_CFG_ISYNCD_V(v) BM_AIC_CFG_ISYNCD +#define BP_AIC_CFG_DMODE 8 +#define BM_AIC_CFG_DMODE 0x100 +#define BF_AIC_CFG_DMODE(v) (((v) & 0x1) << 8) +#define BFM_AIC_CFG_DMODE(v) BM_AIC_CFG_DMODE +#define BF_AIC_CFG_DMODE_V(e) BF_AIC_CFG_DMODE(BV_AIC_CFG_DMODE__##e) +#define BFM_AIC_CFG_DMODE_V(v) BM_AIC_CFG_DMODE +#define BP_AIC_CFG_CDC_SLAVE 7 +#define BM_AIC_CFG_CDC_SLAVE 0x80 +#define BF_AIC_CFG_CDC_SLAVE(v) (((v) & 0x1) << 7) +#define BFM_AIC_CFG_CDC_SLAVE(v) BM_AIC_CFG_CDC_SLAVE +#define BF_AIC_CFG_CDC_SLAVE_V(e) BF_AIC_CFG_CDC_SLAVE(BV_AIC_CFG_CDC_SLAVE__##e) +#define BFM_AIC_CFG_CDC_SLAVE_V(v) BM_AIC_CFG_CDC_SLAVE +#define BP_AIC_CFG_LSMP 6 +#define BM_AIC_CFG_LSMP 0x40 +#define BF_AIC_CFG_LSMP(v) (((v) & 0x1) << 6) +#define BFM_AIC_CFG_LSMP(v) BM_AIC_CFG_LSMP +#define BF_AIC_CFG_LSMP_V(e) BF_AIC_CFG_LSMP(BV_AIC_CFG_LSMP__##e) +#define BFM_AIC_CFG_LSMP_V(v) BM_AIC_CFG_LSMP +#define BP_AIC_CFG_ICDC 5 +#define BM_AIC_CFG_ICDC 0x20 +#define BF_AIC_CFG_ICDC(v) (((v) & 0x1) << 5) +#define BFM_AIC_CFG_ICDC(v) BM_AIC_CFG_ICDC +#define BF_AIC_CFG_ICDC_V(e) BF_AIC_CFG_ICDC(BV_AIC_CFG_ICDC__##e) +#define BFM_AIC_CFG_ICDC_V(v) BM_AIC_CFG_ICDC +#define BP_AIC_CFG_AUSEL 4 +#define BM_AIC_CFG_AUSEL 0x10 +#define BF_AIC_CFG_AUSEL(v) (((v) & 0x1) << 4) +#define BFM_AIC_CFG_AUSEL(v) BM_AIC_CFG_AUSEL +#define BF_AIC_CFG_AUSEL_V(e) BF_AIC_CFG_AUSEL(BV_AIC_CFG_AUSEL__##e) +#define BFM_AIC_CFG_AUSEL_V(v) BM_AIC_CFG_AUSEL +#define BP_AIC_CFG_RST 3 +#define BM_AIC_CFG_RST 0x8 +#define BF_AIC_CFG_RST(v) (((v) & 0x1) << 3) +#define BFM_AIC_CFG_RST(v) BM_AIC_CFG_RST +#define BF_AIC_CFG_RST_V(e) BF_AIC_CFG_RST(BV_AIC_CFG_RST__##e) +#define BFM_AIC_CFG_RST_V(v) BM_AIC_CFG_RST +#define BP_AIC_CFG_BCKD 2 +#define BM_AIC_CFG_BCKD 0x4 +#define BF_AIC_CFG_BCKD(v) (((v) & 0x1) << 2) +#define BFM_AIC_CFG_BCKD(v) BM_AIC_CFG_BCKD +#define BF_AIC_CFG_BCKD_V(e) BF_AIC_CFG_BCKD(BV_AIC_CFG_BCKD__##e) +#define BFM_AIC_CFG_BCKD_V(v) BM_AIC_CFG_BCKD +#define BP_AIC_CFG_SYNCD 1 +#define BM_AIC_CFG_SYNCD 0x2 +#define BF_AIC_CFG_SYNCD(v) (((v) & 0x1) << 1) +#define BFM_AIC_CFG_SYNCD(v) BM_AIC_CFG_SYNCD +#define BF_AIC_CFG_SYNCD_V(e) BF_AIC_CFG_SYNCD(BV_AIC_CFG_SYNCD__##e) +#define BFM_AIC_CFG_SYNCD_V(v) BM_AIC_CFG_SYNCD +#define BP_AIC_CFG_ENABLE 0 +#define BM_AIC_CFG_ENABLE 0x1 +#define BF_AIC_CFG_ENABLE(v) (((v) & 0x1) << 0) +#define BFM_AIC_CFG_ENABLE(v) BM_AIC_CFG_ENABLE +#define BF_AIC_CFG_ENABLE_V(e) BF_AIC_CFG_ENABLE(BV_AIC_CFG_ENABLE__##e) +#define BFM_AIC_CFG_ENABLE_V(v) BM_AIC_CFG_ENABLE + +#define REG_AIC_CCR jz_reg(AIC_CCR) +#define JA_AIC_CCR (0xb0020000 + 0x4) +#define JT_AIC_CCR JIO_32_RW +#define JN_AIC_CCR AIC_CCR +#define JI_AIC_CCR +#define BP_AIC_CCR_CHANNEL 24 +#define BM_AIC_CCR_CHANNEL 0x7000000 +#define BF_AIC_CCR_CHANNEL(v) (((v) & 0x7) << 24) +#define BFM_AIC_CCR_CHANNEL(v) BM_AIC_CCR_CHANNEL +#define BF_AIC_CCR_CHANNEL_V(e) BF_AIC_CCR_CHANNEL(BV_AIC_CCR_CHANNEL__##e) +#define BFM_AIC_CCR_CHANNEL_V(v) BM_AIC_CCR_CHANNEL +#define BP_AIC_CCR_OSS 19 +#define BM_AIC_CCR_OSS 0x380000 +#define BF_AIC_CCR_OSS(v) (((v) & 0x7) << 19) +#define BFM_AIC_CCR_OSS(v) BM_AIC_CCR_OSS +#define BF_AIC_CCR_OSS_V(e) BF_AIC_CCR_OSS(BV_AIC_CCR_OSS__##e) +#define BFM_AIC_CCR_OSS_V(v) BM_AIC_CCR_OSS +#define BP_AIC_CCR_ISS 16 +#define BM_AIC_CCR_ISS 0x70000 +#define BF_AIC_CCR_ISS(v) (((v) & 0x7) << 16) +#define BFM_AIC_CCR_ISS(v) BM_AIC_CCR_ISS +#define BF_AIC_CCR_ISS_V(e) BF_AIC_CCR_ISS(BV_AIC_CCR_ISS__##e) +#define BFM_AIC_CCR_ISS_V(v) BM_AIC_CCR_ISS +#define BP_AIC_CCR_PACK16 28 +#define BM_AIC_CCR_PACK16 0x10000000 +#define BF_AIC_CCR_PACK16(v) (((v) & 0x1) << 28) +#define BFM_AIC_CCR_PACK16(v) BM_AIC_CCR_PACK16 +#define BF_AIC_CCR_PACK16_V(e) BF_AIC_CCR_PACK16(BV_AIC_CCR_PACK16__##e) +#define BFM_AIC_CCR_PACK16_V(v) BM_AIC_CCR_PACK16 +#define BP_AIC_CCR_RDMS 15 +#define BM_AIC_CCR_RDMS 0x8000 +#define BF_AIC_CCR_RDMS(v) (((v) & 0x1) << 15) +#define BFM_AIC_CCR_RDMS(v) BM_AIC_CCR_RDMS +#define BF_AIC_CCR_RDMS_V(e) BF_AIC_CCR_RDMS(BV_AIC_CCR_RDMS__##e) +#define BFM_AIC_CCR_RDMS_V(v) BM_AIC_CCR_RDMS +#define BP_AIC_CCR_TDMS 14 +#define BM_AIC_CCR_TDMS 0x4000 +#define BF_AIC_CCR_TDMS(v) (((v) & 0x1) << 14) +#define BFM_AIC_CCR_TDMS(v) BM_AIC_CCR_TDMS +#define BF_AIC_CCR_TDMS_V(e) BF_AIC_CCR_TDMS(BV_AIC_CCR_TDMS__##e) +#define BFM_AIC_CCR_TDMS_V(v) BM_AIC_CCR_TDMS +#define BP_AIC_CCR_M2S 11 +#define BM_AIC_CCR_M2S 0x800 +#define BF_AIC_CCR_M2S(v) (((v) & 0x1) << 11) +#define BFM_AIC_CCR_M2S(v) BM_AIC_CCR_M2S +#define BF_AIC_CCR_M2S_V(e) BF_AIC_CCR_M2S(BV_AIC_CCR_M2S__##e) +#define BFM_AIC_CCR_M2S_V(v) BM_AIC_CCR_M2S +#define BP_AIC_CCR_ENDSW 10 +#define BM_AIC_CCR_ENDSW 0x400 +#define BF_AIC_CCR_ENDSW(v) (((v) & 0x1) << 10) +#define BFM_AIC_CCR_ENDSW(v) BM_AIC_CCR_ENDSW +#define BF_AIC_CCR_ENDSW_V(e) BF_AIC_CCR_ENDSW(BV_AIC_CCR_ENDSW__##e) +#define BFM_AIC_CCR_ENDSW_V(v) BM_AIC_CCR_ENDSW +#define BP_AIC_CCR_ASVTSU 9 +#define BM_AIC_CCR_ASVTSU 0x200 +#define BF_AIC_CCR_ASVTSU(v) (((v) & 0x1) << 9) +#define BFM_AIC_CCR_ASVTSU(v) BM_AIC_CCR_ASVTSU +#define BF_AIC_CCR_ASVTSU_V(e) BF_AIC_CCR_ASVTSU(BV_AIC_CCR_ASVTSU__##e) +#define BFM_AIC_CCR_ASVTSU_V(v) BM_AIC_CCR_ASVTSU +#define BP_AIC_CCR_TFLUSH 8 +#define BM_AIC_CCR_TFLUSH 0x100 +#define BF_AIC_CCR_TFLUSH(v) (((v) & 0x1) << 8) +#define BFM_AIC_CCR_TFLUSH(v) BM_AIC_CCR_TFLUSH +#define BF_AIC_CCR_TFLUSH_V(e) BF_AIC_CCR_TFLUSH(BV_AIC_CCR_TFLUSH__##e) +#define BFM_AIC_CCR_TFLUSH_V(v) BM_AIC_CCR_TFLUSH +#define BP_AIC_CCR_RFLUSH 7 +#define BM_AIC_CCR_RFLUSH 0x80 +#define BF_AIC_CCR_RFLUSH(v) (((v) & 0x1) << 7) +#define BFM_AIC_CCR_RFLUSH(v) BM_AIC_CCR_RFLUSH +#define BF_AIC_CCR_RFLUSH_V(e) BF_AIC_CCR_RFLUSH(BV_AIC_CCR_RFLUSH__##e) +#define BFM_AIC_CCR_RFLUSH_V(v) BM_AIC_CCR_RFLUSH +#define BP_AIC_CCR_EROR 6 +#define BM_AIC_CCR_EROR 0x40 +#define BF_AIC_CCR_EROR(v) (((v) & 0x1) << 6) +#define BFM_AIC_CCR_EROR(v) BM_AIC_CCR_EROR +#define BF_AIC_CCR_EROR_V(e) BF_AIC_CCR_EROR(BV_AIC_CCR_EROR__##e) +#define BFM_AIC_CCR_EROR_V(v) BM_AIC_CCR_EROR +#define BP_AIC_CCR_ETUR 5 +#define BM_AIC_CCR_ETUR 0x20 +#define BF_AIC_CCR_ETUR(v) (((v) & 0x1) << 5) +#define BFM_AIC_CCR_ETUR(v) BM_AIC_CCR_ETUR +#define BF_AIC_CCR_ETUR_V(e) BF_AIC_CCR_ETUR(BV_AIC_CCR_ETUR__##e) +#define BFM_AIC_CCR_ETUR_V(v) BM_AIC_CCR_ETUR +#define BP_AIC_CCR_ERFS 4 +#define BM_AIC_CCR_ERFS 0x10 +#define BF_AIC_CCR_ERFS(v) (((v) & 0x1) << 4) +#define BFM_AIC_CCR_ERFS(v) BM_AIC_CCR_ERFS +#define BF_AIC_CCR_ERFS_V(e) BF_AIC_CCR_ERFS(BV_AIC_CCR_ERFS__##e) +#define BFM_AIC_CCR_ERFS_V(v) BM_AIC_CCR_ERFS +#define BP_AIC_CCR_ETFS 3 +#define BM_AIC_CCR_ETFS 0x8 +#define BF_AIC_CCR_ETFS(v) (((v) & 0x1) << 3) +#define BFM_AIC_CCR_ETFS(v) BM_AIC_CCR_ETFS +#define BF_AIC_CCR_ETFS_V(e) BF_AIC_CCR_ETFS(BV_AIC_CCR_ETFS__##e) +#define BFM_AIC_CCR_ETFS_V(v) BM_AIC_CCR_ETFS +#define BP_AIC_CCR_ENLBF 2 +#define BM_AIC_CCR_ENLBF 0x4 +#define BF_AIC_CCR_ENLBF(v) (((v) & 0x1) << 2) +#define BFM_AIC_CCR_ENLBF(v) BM_AIC_CCR_ENLBF +#define BF_AIC_CCR_ENLBF_V(e) BF_AIC_CCR_ENLBF(BV_AIC_CCR_ENLBF__##e) +#define BFM_AIC_CCR_ENLBF_V(v) BM_AIC_CCR_ENLBF +#define BP_AIC_CCR_ERPL 1 +#define BM_AIC_CCR_ERPL 0x2 +#define BF_AIC_CCR_ERPL(v) (((v) & 0x1) << 1) +#define BFM_AIC_CCR_ERPL(v) BM_AIC_CCR_ERPL +#define BF_AIC_CCR_ERPL_V(e) BF_AIC_CCR_ERPL(BV_AIC_CCR_ERPL__##e) +#define BFM_AIC_CCR_ERPL_V(v) BM_AIC_CCR_ERPL +#define BP_AIC_CCR_EREC 0 +#define BM_AIC_CCR_EREC 0x1 +#define BF_AIC_CCR_EREC(v) (((v) & 0x1) << 0) +#define BFM_AIC_CCR_EREC(v) BM_AIC_CCR_EREC +#define BF_AIC_CCR_EREC_V(e) BF_AIC_CCR_EREC(BV_AIC_CCR_EREC__##e) +#define BFM_AIC_CCR_EREC_V(v) BM_AIC_CCR_EREC + +#define REG_AIC_I2SCR jz_reg(AIC_I2SCR) +#define JA_AIC_I2SCR (0xb0020000 + 0x10) +#define JT_AIC_I2SCR JIO_32_RW +#define JN_AIC_I2SCR AIC_I2SCR +#define JI_AIC_I2SCR +#define BP_AIC_I2SCR_RFIRST 17 +#define BM_AIC_I2SCR_RFIRST 0x20000 +#define BF_AIC_I2SCR_RFIRST(v) (((v) & 0x1) << 17) +#define BFM_AIC_I2SCR_RFIRST(v) BM_AIC_I2SCR_RFIRST +#define BF_AIC_I2SCR_RFIRST_V(e) BF_AIC_I2SCR_RFIRST(BV_AIC_I2SCR_RFIRST__##e) +#define BFM_AIC_I2SCR_RFIRST_V(v) BM_AIC_I2SCR_RFIRST +#define BP_AIC_I2SCR_SWLH 16 +#define BM_AIC_I2SCR_SWLH 0x10000 +#define BF_AIC_I2SCR_SWLH(v) (((v) & 0x1) << 16) +#define BFM_AIC_I2SCR_SWLH(v) BM_AIC_I2SCR_SWLH +#define BF_AIC_I2SCR_SWLH_V(e) BF_AIC_I2SCR_SWLH(BV_AIC_I2SCR_SWLH__##e) +#define BFM_AIC_I2SCR_SWLH_V(v) BM_AIC_I2SCR_SWLH +#define BP_AIC_I2SCR_ISTPBK 13 +#define BM_AIC_I2SCR_ISTPBK 0x2000 +#define BF_AIC_I2SCR_ISTPBK(v) (((v) & 0x1) << 13) +#define BFM_AIC_I2SCR_ISTPBK(v) BM_AIC_I2SCR_ISTPBK +#define BF_AIC_I2SCR_ISTPBK_V(e) BF_AIC_I2SCR_ISTPBK(BV_AIC_I2SCR_ISTPBK__##e) +#define BFM_AIC_I2SCR_ISTPBK_V(v) BM_AIC_I2SCR_ISTPBK +#define BP_AIC_I2SCR_STPBK 12 +#define BM_AIC_I2SCR_STPBK 0x1000 +#define BF_AIC_I2SCR_STPBK(v) (((v) & 0x1) << 12) +#define BFM_AIC_I2SCR_STPBK(v) BM_AIC_I2SCR_STPBK +#define BF_AIC_I2SCR_STPBK_V(e) BF_AIC_I2SCR_STPBK(BV_AIC_I2SCR_STPBK__##e) +#define BFM_AIC_I2SCR_STPBK_V(v) BM_AIC_I2SCR_STPBK +#define BP_AIC_I2SCR_ESCLK 4 +#define BM_AIC_I2SCR_ESCLK 0x10 +#define BF_AIC_I2SCR_ESCLK(v) (((v) & 0x1) << 4) +#define BFM_AIC_I2SCR_ESCLK(v) BM_AIC_I2SCR_ESCLK +#define BF_AIC_I2SCR_ESCLK_V(e) BF_AIC_I2SCR_ESCLK(BV_AIC_I2SCR_ESCLK__##e) +#define BFM_AIC_I2SCR_ESCLK_V(v) BM_AIC_I2SCR_ESCLK +#define BP_AIC_I2SCR_AMSL 0 +#define BM_AIC_I2SCR_AMSL 0x1 +#define BF_AIC_I2SCR_AMSL(v) (((v) & 0x1) << 0) +#define BFM_AIC_I2SCR_AMSL(v) BM_AIC_I2SCR_AMSL +#define BF_AIC_I2SCR_AMSL_V(e) BF_AIC_I2SCR_AMSL(BV_AIC_I2SCR_AMSL__##e) +#define BFM_AIC_I2SCR_AMSL_V(v) BM_AIC_I2SCR_AMSL + +#define REG_AIC_SR jz_reg(AIC_SR) +#define JA_AIC_SR (0xb0020000 + 0x14) +#define JT_AIC_SR JIO_32_RW +#define JN_AIC_SR AIC_SR +#define JI_AIC_SR +#define BP_AIC_SR_RFL 24 +#define BM_AIC_SR_RFL 0x3f000000 +#define BF_AIC_SR_RFL(v) (((v) & 0x3f) << 24) +#define BFM_AIC_SR_RFL(v) BM_AIC_SR_RFL +#define BF_AIC_SR_RFL_V(e) BF_AIC_SR_RFL(BV_AIC_SR_RFL__##e) +#define BFM_AIC_SR_RFL_V(v) BM_AIC_SR_RFL +#define BP_AIC_SR_TFL 8 +#define BM_AIC_SR_TFL 0x3f00 +#define BF_AIC_SR_TFL(v) (((v) & 0x3f) << 8) +#define BFM_AIC_SR_TFL(v) BM_AIC_SR_TFL +#define BF_AIC_SR_TFL_V(e) BF_AIC_SR_TFL(BV_AIC_SR_TFL__##e) +#define BFM_AIC_SR_TFL_V(v) BM_AIC_SR_TFL +#define BP_AIC_SR_ROR 6 +#define BM_AIC_SR_ROR 0x40 +#define BF_AIC_SR_ROR(v) (((v) & 0x1) << 6) +#define BFM_AIC_SR_ROR(v) BM_AIC_SR_ROR +#define BF_AIC_SR_ROR_V(e) BF_AIC_SR_ROR(BV_AIC_SR_ROR__##e) +#define BFM_AIC_SR_ROR_V(v) BM_AIC_SR_ROR +#define BP_AIC_SR_TUR 5 +#define BM_AIC_SR_TUR 0x20 +#define BF_AIC_SR_TUR(v) (((v) & 0x1) << 5) +#define BFM_AIC_SR_TUR(v) BM_AIC_SR_TUR +#define BF_AIC_SR_TUR_V(e) BF_AIC_SR_TUR(BV_AIC_SR_TUR__##e) +#define BFM_AIC_SR_TUR_V(v) BM_AIC_SR_TUR +#define BP_AIC_SR_RFS 4 +#define BM_AIC_SR_RFS 0x10 +#define BF_AIC_SR_RFS(v) (((v) & 0x1) << 4) +#define BFM_AIC_SR_RFS(v) BM_AIC_SR_RFS +#define BF_AIC_SR_RFS_V(e) BF_AIC_SR_RFS(BV_AIC_SR_RFS__##e) +#define BFM_AIC_SR_RFS_V(v) BM_AIC_SR_RFS +#define BP_AIC_SR_TFS 3 +#define BM_AIC_SR_TFS 0x8 +#define BF_AIC_SR_TFS(v) (((v) & 0x1) << 3) +#define BFM_AIC_SR_TFS(v) BM_AIC_SR_TFS +#define BF_AIC_SR_TFS_V(e) BF_AIC_SR_TFS(BV_AIC_SR_TFS__##e) +#define BFM_AIC_SR_TFS_V(v) BM_AIC_SR_TFS + +#define REG_AIC_I2SSR jz_reg(AIC_I2SSR) +#define JA_AIC_I2SSR (0xb0020000 + 0x1c) +#define JT_AIC_I2SSR JIO_32_RW +#define JN_AIC_I2SSR AIC_I2SSR +#define JI_AIC_I2SSR +#define BP_AIC_I2SSR_CHBSY 5 +#define BM_AIC_I2SSR_CHBSY 0x20 +#define BF_AIC_I2SSR_CHBSY(v) (((v) & 0x1) << 5) +#define BFM_AIC_I2SSR_CHBSY(v) BM_AIC_I2SSR_CHBSY +#define BF_AIC_I2SSR_CHBSY_V(e) BF_AIC_I2SSR_CHBSY(BV_AIC_I2SSR_CHBSY__##e) +#define BFM_AIC_I2SSR_CHBSY_V(v) BM_AIC_I2SSR_CHBSY +#define BP_AIC_I2SSR_TBSY 4 +#define BM_AIC_I2SSR_TBSY 0x10 +#define BF_AIC_I2SSR_TBSY(v) (((v) & 0x1) << 4) +#define BFM_AIC_I2SSR_TBSY(v) BM_AIC_I2SSR_TBSY +#define BF_AIC_I2SSR_TBSY_V(e) BF_AIC_I2SSR_TBSY(BV_AIC_I2SSR_TBSY__##e) +#define BFM_AIC_I2SSR_TBSY_V(v) BM_AIC_I2SSR_TBSY +#define BP_AIC_I2SSR_RBSY 3 +#define BM_AIC_I2SSR_RBSY 0x8 +#define BF_AIC_I2SSR_RBSY(v) (((v) & 0x1) << 3) +#define BFM_AIC_I2SSR_RBSY(v) BM_AIC_I2SSR_RBSY +#define BF_AIC_I2SSR_RBSY_V(e) BF_AIC_I2SSR_RBSY(BV_AIC_I2SSR_RBSY__##e) +#define BFM_AIC_I2SSR_RBSY_V(v) BM_AIC_I2SSR_RBSY +#define BP_AIC_I2SSR_BSY 2 +#define BM_AIC_I2SSR_BSY 0x4 +#define BF_AIC_I2SSR_BSY(v) (((v) & 0x1) << 2) +#define BFM_AIC_I2SSR_BSY(v) BM_AIC_I2SSR_BSY +#define BF_AIC_I2SSR_BSY_V(e) BF_AIC_I2SSR_BSY(BV_AIC_I2SSR_BSY__##e) +#define BFM_AIC_I2SSR_BSY_V(v) BM_AIC_I2SSR_BSY + +#define REG_AIC_I2SDIV jz_reg(AIC_I2SDIV) +#define JA_AIC_I2SDIV (0xb0020000 + 0x30) +#define JT_AIC_I2SDIV JIO_32_RW +#define JN_AIC_I2SDIV AIC_I2SDIV +#define JI_AIC_I2SDIV + +#define REG_AIC_DR jz_reg(AIC_DR) +#define JA_AIC_DR (0xb0020000 + 0x34) +#define JT_AIC_DR JIO_32_RW +#define JN_AIC_DR AIC_DR +#define JI_AIC_DR + +#endif /* __HEADERGEN_AIC_H__*/ diff --git a/firmware/target/mips/ingenic_x1000/x1000/cpm.h b/firmware/target/mips/ingenic_x1000/x1000/cpm.h new file mode 100644 index 0000000000..752d270f20 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/x1000/cpm.h @@ -0,0 +1,896 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * This file was automatically generated by headergen, DO NOT EDIT it. + * headergen version: 3.0.0 + * x1000 version: 1.0 + * x1000 authors: Aidan MacDonald + * + * Copyright (C) 2015 by the authors + * + * 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 __HEADERGEN_CPM_H__ +#define __HEADERGEN_CPM_H__ + +#include "macro.h" + +#define REG_CPM_CCR jz_reg(CPM_CCR) +#define JA_CPM_CCR (0xb0000000 + 0x0) +#define JT_CPM_CCR JIO_32_RW +#define JN_CPM_CCR CPM_CCR +#define JI_CPM_CCR +#define BP_CPM_CCR_SEL_SRC 30 +#define BM_CPM_CCR_SEL_SRC 0xc0000000 +#define BV_CPM_CCR_SEL_SRC__STOP 0x0 +#define BV_CPM_CCR_SEL_SRC__EXCLK 0x1 +#define BV_CPM_CCR_SEL_SRC__APLL 0x2 +#define BF_CPM_CCR_SEL_SRC(v) (((v) & 0x3) << 30) +#define BFM_CPM_CCR_SEL_SRC(v) BM_CPM_CCR_SEL_SRC +#define BF_CPM_CCR_SEL_SRC_V(e) BF_CPM_CCR_SEL_SRC(BV_CPM_CCR_SEL_SRC__##e) +#define BFM_CPM_CCR_SEL_SRC_V(v) BM_CPM_CCR_SEL_SRC +#define BP_CPM_CCR_SEL_CPLL 28 +#define BM_CPM_CCR_SEL_CPLL 0x30000000 +#define BV_CPM_CCR_SEL_CPLL__STOP 0x0 +#define BV_CPM_CCR_SEL_CPLL__SCLK_A 0x1 +#define BV_CPM_CCR_SEL_CPLL__MPLL 0x2 +#define BF_CPM_CCR_SEL_CPLL(v) (((v) & 0x3) << 28) +#define BFM_CPM_CCR_SEL_CPLL(v) BM_CPM_CCR_SEL_CPLL +#define BF_CPM_CCR_SEL_CPLL_V(e) BF_CPM_CCR_SEL_CPLL(BV_CPM_CCR_SEL_CPLL__##e) +#define BFM_CPM_CCR_SEL_CPLL_V(v) BM_CPM_CCR_SEL_CPLL +#define BP_CPM_CCR_SEL_H0PLL 26 +#define BM_CPM_CCR_SEL_H0PLL 0xc000000 +#define BV_CPM_CCR_SEL_H0PLL__STOP 0x0 +#define BV_CPM_CCR_SEL_H0PLL__SCLK_A 0x1 +#define BV_CPM_CCR_SEL_H0PLL__MPLL 0x2 +#define BF_CPM_CCR_SEL_H0PLL(v) (((v) & 0x3) << 26) +#define BFM_CPM_CCR_SEL_H0PLL(v) BM_CPM_CCR_SEL_H0PLL +#define BF_CPM_CCR_SEL_H0PLL_V(e) BF_CPM_CCR_SEL_H0PLL(BV_CPM_CCR_SEL_H0PLL__##e) +#define BFM_CPM_CCR_SEL_H0PLL_V(v) BM_CPM_CCR_SEL_H0PLL +#define BP_CPM_CCR_SEL_H2PLL 24 +#define BM_CPM_CCR_SEL_H2PLL 0x3000000 +#define BV_CPM_CCR_SEL_H2PLL__STOP 0x0 +#define BV_CPM_CCR_SEL_H2PLL__SCLK_A 0x1 +#define BV_CPM_CCR_SEL_H2PLL__MPLL 0x2 +#define BF_CPM_CCR_SEL_H2PLL(v) (((v) & 0x3) << 24) +#define BFM_CPM_CCR_SEL_H2PLL(v) BM_CPM_CCR_SEL_H2PLL +#define BF_CPM_CCR_SEL_H2PLL_V(e) BF_CPM_CCR_SEL_H2PLL(BV_CPM_CCR_SEL_H2PLL__##e) +#define BFM_CPM_CCR_SEL_H2PLL_V(v) BM_CPM_CCR_SEL_H2PLL +#define BP_CPM_CCR_PDIV 16 +#define BM_CPM_CCR_PDIV 0xf0000 +#define BF_CPM_CCR_PDIV(v) (((v) & 0xf) << 16) +#define BFM_CPM_CCR_PDIV(v) BM_CPM_CCR_PDIV +#define BF_CPM_CCR_PDIV_V(e) BF_CPM_CCR_PDIV(BV_CPM_CCR_PDIV__##e) +#define BFM_CPM_CCR_PDIV_V(v) BM_CPM_CCR_PDIV +#define BP_CPM_CCR_H2DIV 12 +#define BM_CPM_CCR_H2DIV 0xf000 +#define BF_CPM_CCR_H2DIV(v) (((v) & 0xf) << 12) +#define BFM_CPM_CCR_H2DIV(v) BM_CPM_CCR_H2DIV +#define BF_CPM_CCR_H2DIV_V(e) BF_CPM_CCR_H2DIV(BV_CPM_CCR_H2DIV__##e) +#define BFM_CPM_CCR_H2DIV_V(v) BM_CPM_CCR_H2DIV +#define BP_CPM_CCR_H0DIV 8 +#define BM_CPM_CCR_H0DIV 0xf00 +#define BF_CPM_CCR_H0DIV(v) (((v) & 0xf) << 8) +#define BFM_CPM_CCR_H0DIV(v) BM_CPM_CCR_H0DIV +#define BF_CPM_CCR_H0DIV_V(e) BF_CPM_CCR_H0DIV(BV_CPM_CCR_H0DIV__##e) +#define BFM_CPM_CCR_H0DIV_V(v) BM_CPM_CCR_H0DIV +#define BP_CPM_CCR_L2DIV 4 +#define BM_CPM_CCR_L2DIV 0xf0 +#define BF_CPM_CCR_L2DIV(v) (((v) & 0xf) << 4) +#define BFM_CPM_CCR_L2DIV(v) BM_CPM_CCR_L2DIV +#define BF_CPM_CCR_L2DIV_V(e) BF_CPM_CCR_L2DIV(BV_CPM_CCR_L2DIV__##e) +#define BFM_CPM_CCR_L2DIV_V(v) BM_CPM_CCR_L2DIV +#define BP_CPM_CCR_CDIV 0 +#define BM_CPM_CCR_CDIV 0xf +#define BF_CPM_CCR_CDIV(v) (((v) & 0xf) << 0) +#define BFM_CPM_CCR_CDIV(v) BM_CPM_CCR_CDIV +#define BF_CPM_CCR_CDIV_V(e) BF_CPM_CCR_CDIV(BV_CPM_CCR_CDIV__##e) +#define BFM_CPM_CCR_CDIV_V(v) BM_CPM_CCR_CDIV +#define BP_CPM_CCR_GATE_SCLKA 23 +#define BM_CPM_CCR_GATE_SCLKA 0x800000 +#define BF_CPM_CCR_GATE_SCLKA(v) (((v) & 0x1) << 23) +#define BFM_CPM_CCR_GATE_SCLKA(v) BM_CPM_CCR_GATE_SCLKA +#define BF_CPM_CCR_GATE_SCLKA_V(e) BF_CPM_CCR_GATE_SCLKA(BV_CPM_CCR_GATE_SCLKA__##e) +#define BFM_CPM_CCR_GATE_SCLKA_V(v) BM_CPM_CCR_GATE_SCLKA +#define BP_CPM_CCR_CE_CPU 22 +#define BM_CPM_CCR_CE_CPU 0x400000 +#define BF_CPM_CCR_CE_CPU(v) (((v) & 0x1) << 22) +#define BFM_CPM_CCR_CE_CPU(v) BM_CPM_CCR_CE_CPU +#define BF_CPM_CCR_CE_CPU_V(e) BF_CPM_CCR_CE_CPU(BV_CPM_CCR_CE_CPU__##e) +#define BFM_CPM_CCR_CE_CPU_V(v) BM_CPM_CCR_CE_CPU +#define BP_CPM_CCR_CE_AHB0 21 +#define BM_CPM_CCR_CE_AHB0 0x200000 +#define BF_CPM_CCR_CE_AHB0(v) (((v) & 0x1) << 21) +#define BFM_CPM_CCR_CE_AHB0(v) BM_CPM_CCR_CE_AHB0 +#define BF_CPM_CCR_CE_AHB0_V(e) BF_CPM_CCR_CE_AHB0(BV_CPM_CCR_CE_AHB0__##e) +#define BFM_CPM_CCR_CE_AHB0_V(v) BM_CPM_CCR_CE_AHB0 +#define BP_CPM_CCR_CE_AHB2 20 +#define BM_CPM_CCR_CE_AHB2 0x100000 +#define BF_CPM_CCR_CE_AHB2(v) (((v) & 0x1) << 20) +#define BFM_CPM_CCR_CE_AHB2(v) BM_CPM_CCR_CE_AHB2 +#define BF_CPM_CCR_CE_AHB2_V(e) BF_CPM_CCR_CE_AHB2(BV_CPM_CCR_CE_AHB2__##e) +#define BFM_CPM_CCR_CE_AHB2_V(v) BM_CPM_CCR_CE_AHB2 + +#define REG_CPM_CSR jz_reg(CPM_CSR) +#define JA_CPM_CSR (0xb0000000 + 0xd4) +#define JT_CPM_CSR JIO_32_RW +#define JN_CPM_CSR CPM_CSR +#define JI_CPM_CSR +#define BP_CPM_CSR_SRC_MUX 31 +#define BM_CPM_CSR_SRC_MUX 0x80000000 +#define BF_CPM_CSR_SRC_MUX(v) (((v) & 0x1) << 31) +#define BFM_CPM_CSR_SRC_MUX(v) BM_CPM_CSR_SRC_MUX +#define BF_CPM_CSR_SRC_MUX_V(e) BF_CPM_CSR_SRC_MUX(BV_CPM_CSR_SRC_MUX__##e) +#define BFM_CPM_CSR_SRC_MUX_V(v) BM_CPM_CSR_SRC_MUX +#define BP_CPM_CSR_CPU_MUX 30 +#define BM_CPM_CSR_CPU_MUX 0x40000000 +#define BF_CPM_CSR_CPU_MUX(v) (((v) & 0x1) << 30) +#define BFM_CPM_CSR_CPU_MUX(v) BM_CPM_CSR_CPU_MUX +#define BF_CPM_CSR_CPU_MUX_V(e) BF_CPM_CSR_CPU_MUX(BV_CPM_CSR_CPU_MUX__##e) +#define BFM_CPM_CSR_CPU_MUX_V(v) BM_CPM_CSR_CPU_MUX +#define BP_CPM_CSR_AHB0_MUX 29 +#define BM_CPM_CSR_AHB0_MUX 0x20000000 +#define BF_CPM_CSR_AHB0_MUX(v) (((v) & 0x1) << 29) +#define BFM_CPM_CSR_AHB0_MUX(v) BM_CPM_CSR_AHB0_MUX +#define BF_CPM_CSR_AHB0_MUX_V(e) BF_CPM_CSR_AHB0_MUX(BV_CPM_CSR_AHB0_MUX__##e) +#define BFM_CPM_CSR_AHB0_MUX_V(v) BM_CPM_CSR_AHB0_MUX +#define BP_CPM_CSR_AHB2_MUX 28 +#define BM_CPM_CSR_AHB2_MUX 0x10000000 +#define BF_CPM_CSR_AHB2_MUX(v) (((v) & 0x1) << 28) +#define BFM_CPM_CSR_AHB2_MUX(v) BM_CPM_CSR_AHB2_MUX +#define BF_CPM_CSR_AHB2_MUX_V(e) BF_CPM_CSR_AHB2_MUX(BV_CPM_CSR_AHB2_MUX__##e) +#define BFM_CPM_CSR_AHB2_MUX_V(v) BM_CPM_CSR_AHB2_MUX +#define BP_CPM_CSR_DDR_MUX 27 +#define BM_CPM_CSR_DDR_MUX 0x8000000 +#define BF_CPM_CSR_DDR_MUX(v) (((v) & 0x1) << 27) +#define BFM_CPM_CSR_DDR_MUX(v) BM_CPM_CSR_DDR_MUX +#define BF_CPM_CSR_DDR_MUX_V(e) BF_CPM_CSR_DDR_MUX(BV_CPM_CSR_DDR_MUX__##e) +#define BFM_CPM_CSR_DDR_MUX_V(v) BM_CPM_CSR_DDR_MUX +#define BP_CPM_CSR_H2DIV_BUSY 2 +#define BM_CPM_CSR_H2DIV_BUSY 0x4 +#define BF_CPM_CSR_H2DIV_BUSY(v) (((v) & 0x1) << 2) +#define BFM_CPM_CSR_H2DIV_BUSY(v) BM_CPM_CSR_H2DIV_BUSY +#define BF_CPM_CSR_H2DIV_BUSY_V(e) BF_CPM_CSR_H2DIV_BUSY(BV_CPM_CSR_H2DIV_BUSY__##e) +#define BFM_CPM_CSR_H2DIV_BUSY_V(v) BM_CPM_CSR_H2DIV_BUSY +#define BP_CPM_CSR_H0DIV_BUSY 1 +#define BM_CPM_CSR_H0DIV_BUSY 0x2 +#define BF_CPM_CSR_H0DIV_BUSY(v) (((v) & 0x1) << 1) +#define BFM_CPM_CSR_H0DIV_BUSY(v) BM_CPM_CSR_H0DIV_BUSY +#define BF_CPM_CSR_H0DIV_BUSY_V(e) BF_CPM_CSR_H0DIV_BUSY(BV_CPM_CSR_H0DIV_BUSY__##e) +#define BFM_CPM_CSR_H0DIV_BUSY_V(v) BM_CPM_CSR_H0DIV_BUSY +#define BP_CPM_CSR_CDIV_BUSY 0 +#define BM_CPM_CSR_CDIV_BUSY 0x1 +#define BF_CPM_CSR_CDIV_BUSY(v) (((v) & 0x1) << 0) +#define BFM_CPM_CSR_CDIV_BUSY(v) BM_CPM_CSR_CDIV_BUSY +#define BF_CPM_CSR_CDIV_BUSY_V(e) BF_CPM_CSR_CDIV_BUSY(BV_CPM_CSR_CDIV_BUSY__##e) +#define BFM_CPM_CSR_CDIV_BUSY_V(v) BM_CPM_CSR_CDIV_BUSY + +#define REG_CPM_DDRCDR jz_reg(CPM_DDRCDR) +#define JA_CPM_DDRCDR (0xb0000000 + 0x2c) +#define JT_CPM_DDRCDR JIO_32_RW +#define JN_CPM_DDRCDR CPM_DDRCDR +#define JI_CPM_DDRCDR +#define BP_CPM_DDRCDR_CLKSRC 30 +#define BM_CPM_DDRCDR_CLKSRC 0xc0000000 +#define BV_CPM_DDRCDR_CLKSRC__STOP 0x0 +#define BV_CPM_DDRCDR_CLKSRC__SCLK_A 0x1 +#define BV_CPM_DDRCDR_CLKSRC__MPLL 0x2 +#define BF_CPM_DDRCDR_CLKSRC(v) (((v) & 0x3) << 30) +#define BFM_CPM_DDRCDR_CLKSRC(v) BM_CPM_DDRCDR_CLKSRC +#define BF_CPM_DDRCDR_CLKSRC_V(e) BF_CPM_DDRCDR_CLKSRC(BV_CPM_DDRCDR_CLKSRC__##e) +#define BFM_CPM_DDRCDR_CLKSRC_V(v) BM_CPM_DDRCDR_CLKSRC +#define BP_CPM_DDRCDR_CLKDIV 0 +#define BM_CPM_DDRCDR_CLKDIV 0xf +#define BF_CPM_DDRCDR_CLKDIV(v) (((v) & 0xf) << 0) +#define BFM_CPM_DDRCDR_CLKDIV(v) BM_CPM_DDRCDR_CLKDIV +#define BF_CPM_DDRCDR_CLKDIV_V(e) BF_CPM_DDRCDR_CLKDIV(BV_CPM_DDRCDR_CLKDIV__##e) +#define BFM_CPM_DDRCDR_CLKDIV_V(v) BM_CPM_DDRCDR_CLKDIV +#define BP_CPM_DDRCDR_CE 29 +#define BM_CPM_DDRCDR_CE 0x20000000 +#define BF_CPM_DDRCDR_CE(v) (((v) & 0x1) << 29) +#define BFM_CPM_DDRCDR_CE(v) BM_CPM_DDRCDR_CE +#define BF_CPM_DDRCDR_CE_V(e) BF_CPM_DDRCDR_CE(BV_CPM_DDRCDR_CE__##e) +#define BFM_CPM_DDRCDR_CE_V(v) BM_CPM_DDRCDR_CE +#define BP_CPM_DDRCDR_BUSY 28 +#define BM_CPM_DDRCDR_BUSY 0x10000000 +#define BF_CPM_DDRCDR_BUSY(v) (((v) & 0x1) << 28) +#define BFM_CPM_DDRCDR_BUSY(v) BM_CPM_DDRCDR_BUSY +#define BF_CPM_DDRCDR_BUSY_V(e) BF_CPM_DDRCDR_BUSY(BV_CPM_DDRCDR_BUSY__##e) +#define BFM_CPM_DDRCDR_BUSY_V(v) BM_CPM_DDRCDR_BUSY +#define BP_CPM_DDRCDR_STOP 27 +#define BM_CPM_DDRCDR_STOP 0x8000000 +#define BF_CPM_DDRCDR_STOP(v) (((v) & 0x1) << 27) +#define BFM_CPM_DDRCDR_STOP(v) BM_CPM_DDRCDR_STOP +#define BF_CPM_DDRCDR_STOP_V(e) BF_CPM_DDRCDR_STOP(BV_CPM_DDRCDR_STOP__##e) +#define BFM_CPM_DDRCDR_STOP_V(v) BM_CPM_DDRCDR_STOP +#define BP_CPM_DDRCDR_GATE_EN 26 +#define BM_CPM_DDRCDR_GATE_EN 0x4000000 +#define BF_CPM_DDRCDR_GATE_EN(v) (((v) & 0x1) << 26) +#define BFM_CPM_DDRCDR_GATE_EN(v) BM_CPM_DDRCDR_GATE_EN +#define BF_CPM_DDRCDR_GATE_EN_V(e) BF_CPM_DDRCDR_GATE_EN(BV_CPM_DDRCDR_GATE_EN__##e) +#define BFM_CPM_DDRCDR_GATE_EN_V(v) BM_CPM_DDRCDR_GATE_EN +#define BP_CPM_DDRCDR_CHANGE_EN 25 +#define BM_CPM_DDRCDR_CHANGE_EN 0x2000000 +#define BF_CPM_DDRCDR_CHANGE_EN(v) (((v) & 0x1) << 25) +#define BFM_CPM_DDRCDR_CHANGE_EN(v) BM_CPM_DDRCDR_CHANGE_EN +#define BF_CPM_DDRCDR_CHANGE_EN_V(e) BF_CPM_DDRCDR_CHANGE_EN(BV_CPM_DDRCDR_CHANGE_EN__##e) +#define BFM_CPM_DDRCDR_CHANGE_EN_V(v) BM_CPM_DDRCDR_CHANGE_EN +#define BP_CPM_DDRCDR_FLAG 24 +#define BM_CPM_DDRCDR_FLAG 0x1000000 +#define BF_CPM_DDRCDR_FLAG(v) (((v) & 0x1) << 24) +#define BFM_CPM_DDRCDR_FLAG(v) BM_CPM_DDRCDR_FLAG +#define BF_CPM_DDRCDR_FLAG_V(e) BF_CPM_DDRCDR_FLAG(BV_CPM_DDRCDR_FLAG__##e) +#define BFM_CPM_DDRCDR_FLAG_V(v) BM_CPM_DDRCDR_FLAG + +#define REG_CPM_I2SCDR jz_reg(CPM_I2SCDR) +#define JA_CPM_I2SCDR (0xb0000000 + 0x60) +#define JT_CPM_I2SCDR JIO_32_RW +#define JN_CPM_I2SCDR CPM_I2SCDR +#define JI_CPM_I2SCDR +#define BP_CPM_I2SCDR_DIV_M 13 +#define BM_CPM_I2SCDR_DIV_M 0x3fe000 +#define BF_CPM_I2SCDR_DIV_M(v) (((v) & 0x1ff) << 13) +#define BFM_CPM_I2SCDR_DIV_M(v) BM_CPM_I2SCDR_DIV_M +#define BF_CPM_I2SCDR_DIV_M_V(e) BF_CPM_I2SCDR_DIV_M(BV_CPM_I2SCDR_DIV_M__##e) +#define BFM_CPM_I2SCDR_DIV_M_V(v) BM_CPM_I2SCDR_DIV_M +#define BP_CPM_I2SCDR_DIV_N 0 +#define BM_CPM_I2SCDR_DIV_N 0x1fff +#define BF_CPM_I2SCDR_DIV_N(v) (((v) & 0x1fff) << 0) +#define BFM_CPM_I2SCDR_DIV_N(v) BM_CPM_I2SCDR_DIV_N +#define BF_CPM_I2SCDR_DIV_N_V(e) BF_CPM_I2SCDR_DIV_N(BV_CPM_I2SCDR_DIV_N__##e) +#define BFM_CPM_I2SCDR_DIV_N_V(v) BM_CPM_I2SCDR_DIV_N +#define BP_CPM_I2SCDR_PCS 31 +#define BM_CPM_I2SCDR_PCS 0x80000000 +#define BV_CPM_I2SCDR_PCS__SCLK_A 0x0 +#define BV_CPM_I2SCDR_PCS__MPLL 0x1 +#define BF_CPM_I2SCDR_PCS(v) (((v) & 0x1) << 31) +#define BFM_CPM_I2SCDR_PCS(v) BM_CPM_I2SCDR_PCS +#define BF_CPM_I2SCDR_PCS_V(e) BF_CPM_I2SCDR_PCS(BV_CPM_I2SCDR_PCS__##e) +#define BFM_CPM_I2SCDR_PCS_V(v) BM_CPM_I2SCDR_PCS +#define BP_CPM_I2SCDR_CS 30 +#define BM_CPM_I2SCDR_CS 0x40000000 +#define BV_CPM_I2SCDR_CS__EXCLK 0x0 +#define BV_CPM_I2SCDR_CS__PLL 0x1 +#define BF_CPM_I2SCDR_CS(v) (((v) & 0x1) << 30) +#define BFM_CPM_I2SCDR_CS(v) BM_CPM_I2SCDR_CS +#define BF_CPM_I2SCDR_CS_V(e) BF_CPM_I2SCDR_CS(BV_CPM_I2SCDR_CS__##e) +#define BFM_CPM_I2SCDR_CS_V(v) BM_CPM_I2SCDR_CS +#define BP_CPM_I2SCDR_CE 29 +#define BM_CPM_I2SCDR_CE 0x20000000 +#define BF_CPM_I2SCDR_CE(v) (((v) & 0x1) << 29) +#define BFM_CPM_I2SCDR_CE(v) BM_CPM_I2SCDR_CE +#define BF_CPM_I2SCDR_CE_V(e) BF_CPM_I2SCDR_CE(BV_CPM_I2SCDR_CE__##e) +#define BFM_CPM_I2SCDR_CE_V(v) BM_CPM_I2SCDR_CE + +#define REG_CPM_I2SCDR1 jz_reg(CPM_I2SCDR1) +#define JA_CPM_I2SCDR1 (0xb0000000 + 0x70) +#define JT_CPM_I2SCDR1 JIO_32_RW +#define JN_CPM_I2SCDR1 CPM_I2SCDR1 +#define JI_CPM_I2SCDR1 + +#define REG_CPM_LPCDR jz_reg(CPM_LPCDR) +#define JA_CPM_LPCDR (0xb0000000 + 0x64) +#define JT_CPM_LPCDR JIO_32_RW +#define JN_CPM_LPCDR CPM_LPCDR +#define JI_CPM_LPCDR +#define BP_CPM_LPCDR_CLKDIV 0 +#define BM_CPM_LPCDR_CLKDIV 0xff +#define BF_CPM_LPCDR_CLKDIV(v) (((v) & 0xff) << 0) +#define BFM_CPM_LPCDR_CLKDIV(v) BM_CPM_LPCDR_CLKDIV +#define BF_CPM_LPCDR_CLKDIV_V(e) BF_CPM_LPCDR_CLKDIV(BV_CPM_LPCDR_CLKDIV__##e) +#define BFM_CPM_LPCDR_CLKDIV_V(v) BM_CPM_LPCDR_CLKDIV +#define BP_CPM_LPCDR_CLKSRC 31 +#define BM_CPM_LPCDR_CLKSRC 0x80000000 +#define BV_CPM_LPCDR_CLKSRC__SCLK_A 0x0 +#define BV_CPM_LPCDR_CLKSRC__MPLL 0x1 +#define BF_CPM_LPCDR_CLKSRC(v) (((v) & 0x1) << 31) +#define BFM_CPM_LPCDR_CLKSRC(v) BM_CPM_LPCDR_CLKSRC +#define BF_CPM_LPCDR_CLKSRC_V(e) BF_CPM_LPCDR_CLKSRC(BV_CPM_LPCDR_CLKSRC__##e) +#define BFM_CPM_LPCDR_CLKSRC_V(v) BM_CPM_LPCDR_CLKSRC +#define BP_CPM_LPCDR_CE 28 +#define BM_CPM_LPCDR_CE 0x10000000 +#define BF_CPM_LPCDR_CE(v) (((v) & 0x1) << 28) +#define BFM_CPM_LPCDR_CE(v) BM_CPM_LPCDR_CE +#define BF_CPM_LPCDR_CE_V(e) BF_CPM_LPCDR_CE(BV_CPM_LPCDR_CE__##e) +#define BFM_CPM_LPCDR_CE_V(v) BM_CPM_LPCDR_CE +#define BP_CPM_LPCDR_BUSY 27 +#define BM_CPM_LPCDR_BUSY 0x8000000 +#define BF_CPM_LPCDR_BUSY(v) (((v) & 0x1) << 27) +#define BFM_CPM_LPCDR_BUSY(v) BM_CPM_LPCDR_BUSY +#define BF_CPM_LPCDR_BUSY_V(e) BF_CPM_LPCDR_BUSY(BV_CPM_LPCDR_BUSY__##e) +#define BFM_CPM_LPCDR_BUSY_V(v) BM_CPM_LPCDR_BUSY +#define BP_CPM_LPCDR_STOP 26 +#define BM_CPM_LPCDR_STOP 0x4000000 +#define BF_CPM_LPCDR_STOP(v) (((v) & 0x1) << 26) +#define BFM_CPM_LPCDR_STOP(v) BM_CPM_LPCDR_STOP +#define BF_CPM_LPCDR_STOP_V(e) BF_CPM_LPCDR_STOP(BV_CPM_LPCDR_STOP__##e) +#define BFM_CPM_LPCDR_STOP_V(v) BM_CPM_LPCDR_STOP + +#define REG_CPM_MSC0CDR jz_reg(CPM_MSC0CDR) +#define JA_CPM_MSC0CDR (0xb0000000 + 0x68) +#define JT_CPM_MSC0CDR JIO_32_RW +#define JN_CPM_MSC0CDR CPM_MSC0CDR +#define JI_CPM_MSC0CDR +#define BP_CPM_MSC0CDR_CLKDIV 0 +#define BM_CPM_MSC0CDR_CLKDIV 0xff +#define BF_CPM_MSC0CDR_CLKDIV(v) (((v) & 0xff) << 0) +#define BFM_CPM_MSC0CDR_CLKDIV(v) BM_CPM_MSC0CDR_CLKDIV +#define BF_CPM_MSC0CDR_CLKDIV_V(e) BF_CPM_MSC0CDR_CLKDIV(BV_CPM_MSC0CDR_CLKDIV__##e) +#define BFM_CPM_MSC0CDR_CLKDIV_V(v) BM_CPM_MSC0CDR_CLKDIV +#define BP_CPM_MSC0CDR_CLKSRC 31 +#define BM_CPM_MSC0CDR_CLKSRC 0x80000000 +#define BV_CPM_MSC0CDR_CLKSRC__SCLK_A 0x0 +#define BV_CPM_MSC0CDR_CLKSRC__MPLL 0x1 +#define BF_CPM_MSC0CDR_CLKSRC(v) (((v) & 0x1) << 31) +#define BFM_CPM_MSC0CDR_CLKSRC(v) BM_CPM_MSC0CDR_CLKSRC +#define BF_CPM_MSC0CDR_CLKSRC_V(e) BF_CPM_MSC0CDR_CLKSRC(BV_CPM_MSC0CDR_CLKSRC__##e) +#define BFM_CPM_MSC0CDR_CLKSRC_V(v) BM_CPM_MSC0CDR_CLKSRC +#define BP_CPM_MSC0CDR_CE 29 +#define BM_CPM_MSC0CDR_CE 0x20000000 +#define BF_CPM_MSC0CDR_CE(v) (((v) & 0x1) << 29) +#define BFM_CPM_MSC0CDR_CE(v) BM_CPM_MSC0CDR_CE +#define BF_CPM_MSC0CDR_CE_V(e) BF_CPM_MSC0CDR_CE(BV_CPM_MSC0CDR_CE__##e) +#define BFM_CPM_MSC0CDR_CE_V(v) BM_CPM_MSC0CDR_CE +#define BP_CPM_MSC0CDR_BUSY 28 +#define BM_CPM_MSC0CDR_BUSY 0x10000000 +#define BF_CPM_MSC0CDR_BUSY(v) (((v) & 0x1) << 28) +#define BFM_CPM_MSC0CDR_BUSY(v) BM_CPM_MSC0CDR_BUSY +#define BF_CPM_MSC0CDR_BUSY_V(e) BF_CPM_MSC0CDR_BUSY(BV_CPM_MSC0CDR_BUSY__##e) +#define BFM_CPM_MSC0CDR_BUSY_V(v) BM_CPM_MSC0CDR_BUSY +#define BP_CPM_MSC0CDR_STOP 27 +#define BM_CPM_MSC0CDR_STOP 0x8000000 +#define BF_CPM_MSC0CDR_STOP(v) (((v) & 0x1) << 27) +#define BFM_CPM_MSC0CDR_STOP(v) BM_CPM_MSC0CDR_STOP +#define BF_CPM_MSC0CDR_STOP_V(e) BF_CPM_MSC0CDR_STOP(BV_CPM_MSC0CDR_STOP__##e) +#define BFM_CPM_MSC0CDR_STOP_V(v) BM_CPM_MSC0CDR_STOP +#define BP_CPM_MSC0CDR_S_CLK0_SEL 15 +#define BM_CPM_MSC0CDR_S_CLK0_SEL 0x8000 +#define BV_CPM_MSC0CDR_S_CLK0_SEL__90DEG 0x0 +#define BV_CPM_MSC0CDR_S_CLK0_SEL__180DEG 0x1 +#define BF_CPM_MSC0CDR_S_CLK0_SEL(v) (((v) & 0x1) << 15) +#define BFM_CPM_MSC0CDR_S_CLK0_SEL(v) BM_CPM_MSC0CDR_S_CLK0_SEL +#define BF_CPM_MSC0CDR_S_CLK0_SEL_V(e) BF_CPM_MSC0CDR_S_CLK0_SEL(BV_CPM_MSC0CDR_S_CLK0_SEL__##e) +#define BFM_CPM_MSC0CDR_S_CLK0_SEL_V(v) BM_CPM_MSC0CDR_S_CLK0_SEL + +#define REG_CPM_MSC1CDR jz_reg(CPM_MSC1CDR) +#define JA_CPM_MSC1CDR (0xb0000000 + 0xa4) +#define JT_CPM_MSC1CDR JIO_32_RW +#define JN_CPM_MSC1CDR CPM_MSC1CDR +#define JI_CPM_MSC1CDR +#define BP_CPM_MSC1CDR_CLKDIV 0 +#define BM_CPM_MSC1CDR_CLKDIV 0xff +#define BF_CPM_MSC1CDR_CLKDIV(v) (((v) & 0xff) << 0) +#define BFM_CPM_MSC1CDR_CLKDIV(v) BM_CPM_MSC1CDR_CLKDIV +#define BF_CPM_MSC1CDR_CLKDIV_V(e) BF_CPM_MSC1CDR_CLKDIV(BV_CPM_MSC1CDR_CLKDIV__##e) +#define BFM_CPM_MSC1CDR_CLKDIV_V(v) BM_CPM_MSC1CDR_CLKDIV +#define BP_CPM_MSC1CDR_CE 29 +#define BM_CPM_MSC1CDR_CE 0x20000000 +#define BF_CPM_MSC1CDR_CE(v) (((v) & 0x1) << 29) +#define BFM_CPM_MSC1CDR_CE(v) BM_CPM_MSC1CDR_CE +#define BF_CPM_MSC1CDR_CE_V(e) BF_CPM_MSC1CDR_CE(BV_CPM_MSC1CDR_CE__##e) +#define BFM_CPM_MSC1CDR_CE_V(v) BM_CPM_MSC1CDR_CE +#define BP_CPM_MSC1CDR_BUSY 28 +#define BM_CPM_MSC1CDR_BUSY 0x10000000 +#define BF_CPM_MSC1CDR_BUSY(v) (((v) & 0x1) << 28) +#define BFM_CPM_MSC1CDR_BUSY(v) BM_CPM_MSC1CDR_BUSY +#define BF_CPM_MSC1CDR_BUSY_V(e) BF_CPM_MSC1CDR_BUSY(BV_CPM_MSC1CDR_BUSY__##e) +#define BFM_CPM_MSC1CDR_BUSY_V(v) BM_CPM_MSC1CDR_BUSY +#define BP_CPM_MSC1CDR_STOP 27 +#define BM_CPM_MSC1CDR_STOP 0x8000000 +#define BF_CPM_MSC1CDR_STOP(v) (((v) & 0x1) << 27) +#define BFM_CPM_MSC1CDR_STOP(v) BM_CPM_MSC1CDR_STOP +#define BF_CPM_MSC1CDR_STOP_V(e) BF_CPM_MSC1CDR_STOP(BV_CPM_MSC1CDR_STOP__##e) +#define BFM_CPM_MSC1CDR_STOP_V(v) BM_CPM_MSC1CDR_STOP +#define BP_CPM_MSC1CDR_S_CLK1_SEL 15 +#define BM_CPM_MSC1CDR_S_CLK1_SEL 0x8000 +#define BV_CPM_MSC1CDR_S_CLK1_SEL__90DEG 0x0 +#define BV_CPM_MSC1CDR_S_CLK1_SEL__180DEG 0x1 +#define BF_CPM_MSC1CDR_S_CLK1_SEL(v) (((v) & 0x1) << 15) +#define BFM_CPM_MSC1CDR_S_CLK1_SEL(v) BM_CPM_MSC1CDR_S_CLK1_SEL +#define BF_CPM_MSC1CDR_S_CLK1_SEL_V(e) BF_CPM_MSC1CDR_S_CLK1_SEL(BV_CPM_MSC1CDR_S_CLK1_SEL__##e) +#define BFM_CPM_MSC1CDR_S_CLK1_SEL_V(v) BM_CPM_MSC1CDR_S_CLK1_SEL + +#define REG_CPM_SSICDR jz_reg(CPM_SSICDR) +#define JA_CPM_SSICDR (0xb0000000 + 0x74) +#define JT_CPM_SSICDR JIO_32_RW +#define JN_CPM_SSICDR CPM_SSICDR +#define JI_CPM_SSICDR +#define BP_CPM_SSICDR_CLKDIV 0 +#define BM_CPM_SSICDR_CLKDIV 0xff +#define BF_CPM_SSICDR_CLKDIV(v) (((v) & 0xff) << 0) +#define BFM_CPM_SSICDR_CLKDIV(v) BM_CPM_SSICDR_CLKDIV +#define BF_CPM_SSICDR_CLKDIV_V(e) BF_CPM_SSICDR_CLKDIV(BV_CPM_SSICDR_CLKDIV__##e) +#define BFM_CPM_SSICDR_CLKDIV_V(v) BM_CPM_SSICDR_CLKDIV +#define BP_CPM_SSICDR_SFC_CS 31 +#define BM_CPM_SSICDR_SFC_CS 0x80000000 +#define BV_CPM_SSICDR_SFC_CS__SCLK_A 0x0 +#define BV_CPM_SSICDR_SFC_CS__MPLL 0x1 +#define BF_CPM_SSICDR_SFC_CS(v) (((v) & 0x1) << 31) +#define BFM_CPM_SSICDR_SFC_CS(v) BM_CPM_SSICDR_SFC_CS +#define BF_CPM_SSICDR_SFC_CS_V(e) BF_CPM_SSICDR_SFC_CS(BV_CPM_SSICDR_SFC_CS__##e) +#define BFM_CPM_SSICDR_SFC_CS_V(v) BM_CPM_SSICDR_SFC_CS +#define BP_CPM_SSICDR_SSI_CS 30 +#define BM_CPM_SSICDR_SSI_CS 0x40000000 +#define BV_CPM_SSICDR_SSI_CS__EXCLK 0x0 +#define BV_CPM_SSICDR_SSI_CS__HALF_SFC 0x1 +#define BF_CPM_SSICDR_SSI_CS(v) (((v) & 0x1) << 30) +#define BFM_CPM_SSICDR_SSI_CS(v) BM_CPM_SSICDR_SSI_CS +#define BF_CPM_SSICDR_SSI_CS_V(e) BF_CPM_SSICDR_SSI_CS(BV_CPM_SSICDR_SSI_CS__##e) +#define BFM_CPM_SSICDR_SSI_CS_V(v) BM_CPM_SSICDR_SSI_CS +#define BP_CPM_SSICDR_CE 29 +#define BM_CPM_SSICDR_CE 0x20000000 +#define BF_CPM_SSICDR_CE(v) (((v) & 0x1) << 29) +#define BFM_CPM_SSICDR_CE(v) BM_CPM_SSICDR_CE +#define BF_CPM_SSICDR_CE_V(e) BF_CPM_SSICDR_CE(BV_CPM_SSICDR_CE__##e) +#define BFM_CPM_SSICDR_CE_V(v) BM_CPM_SSICDR_CE +#define BP_CPM_SSICDR_BUSY 28 +#define BM_CPM_SSICDR_BUSY 0x10000000 +#define BF_CPM_SSICDR_BUSY(v) (((v) & 0x1) << 28) +#define BFM_CPM_SSICDR_BUSY(v) BM_CPM_SSICDR_BUSY +#define BF_CPM_SSICDR_BUSY_V(e) BF_CPM_SSICDR_BUSY(BV_CPM_SSICDR_BUSY__##e) +#define BFM_CPM_SSICDR_BUSY_V(v) BM_CPM_SSICDR_BUSY +#define BP_CPM_SSICDR_STOP 27 +#define BM_CPM_SSICDR_STOP 0x8000000 +#define BF_CPM_SSICDR_STOP(v) (((v) & 0x1) << 27) +#define BFM_CPM_SSICDR_STOP(v) BM_CPM_SSICDR_STOP +#define BF_CPM_SSICDR_STOP_V(e) BF_CPM_SSICDR_STOP(BV_CPM_SSICDR_STOP__##e) +#define BFM_CPM_SSICDR_STOP_V(v) BM_CPM_SSICDR_STOP + +#define REG_CPM_DRCG jz_reg(CPM_DRCG) +#define JA_CPM_DRCG (0xb0000000 + 0xd0) +#define JT_CPM_DRCG JIO_32_RW +#define JN_CPM_DRCG CPM_DRCG +#define JI_CPM_DRCG + +#define REG_CPM_APCR jz_reg(CPM_APCR) +#define JA_CPM_APCR (0xb0000000 + 0x10) +#define JT_CPM_APCR JIO_32_RW +#define JN_CPM_APCR CPM_APCR +#define JI_CPM_APCR +#define BP_CPM_APCR_PLLM 24 +#define BM_CPM_APCR_PLLM 0x7f000000 +#define BF_CPM_APCR_PLLM(v) (((v) & 0x7f) << 24) +#define BFM_CPM_APCR_PLLM(v) BM_CPM_APCR_PLLM +#define BF_CPM_APCR_PLLM_V(e) BF_CPM_APCR_PLLM(BV_CPM_APCR_PLLM__##e) +#define BFM_CPM_APCR_PLLM_V(v) BM_CPM_APCR_PLLM +#define BP_CPM_APCR_PLLN 18 +#define BM_CPM_APCR_PLLN 0x7c0000 +#define BF_CPM_APCR_PLLN(v) (((v) & 0x1f) << 18) +#define BFM_CPM_APCR_PLLN(v) BM_CPM_APCR_PLLN +#define BF_CPM_APCR_PLLN_V(e) BF_CPM_APCR_PLLN(BV_CPM_APCR_PLLN__##e) +#define BFM_CPM_APCR_PLLN_V(v) BM_CPM_APCR_PLLN +#define BP_CPM_APCR_PLLOD 16 +#define BM_CPM_APCR_PLLOD 0x30000 +#define BF_CPM_APCR_PLLOD(v) (((v) & 0x3) << 16) +#define BFM_CPM_APCR_PLLOD(v) BM_CPM_APCR_PLLOD +#define BF_CPM_APCR_PLLOD_V(e) BF_CPM_APCR_PLLOD(BV_CPM_APCR_PLLOD__##e) +#define BFM_CPM_APCR_PLLOD_V(v) BM_CPM_APCR_PLLOD +#define BP_CPM_APCR_PLLST 0 +#define BM_CPM_APCR_PLLST 0xff +#define BF_CPM_APCR_PLLST(v) (((v) & 0xff) << 0) +#define BFM_CPM_APCR_PLLST(v) BM_CPM_APCR_PLLST +#define BF_CPM_APCR_PLLST_V(e) BF_CPM_APCR_PLLST(BV_CPM_APCR_PLLST__##e) +#define BFM_CPM_APCR_PLLST_V(v) BM_CPM_APCR_PLLST +#define BP_CPM_APCR_BS 31 +#define BM_CPM_APCR_BS 0x80000000 +#define BF_CPM_APCR_BS(v) (((v) & 0x1) << 31) +#define BFM_CPM_APCR_BS(v) BM_CPM_APCR_BS +#define BF_CPM_APCR_BS_V(e) BF_CPM_APCR_BS(BV_CPM_APCR_BS__##e) +#define BFM_CPM_APCR_BS_V(v) BM_CPM_APCR_BS +#define BP_CPM_APCR_LOCK 15 +#define BM_CPM_APCR_LOCK 0x8000 +#define BF_CPM_APCR_LOCK(v) (((v) & 0x1) << 15) +#define BFM_CPM_APCR_LOCK(v) BM_CPM_APCR_LOCK +#define BF_CPM_APCR_LOCK_V(e) BF_CPM_APCR_LOCK(BV_CPM_APCR_LOCK__##e) +#define BFM_CPM_APCR_LOCK_V(v) BM_CPM_APCR_LOCK +#define BP_CPM_APCR_ON 10 +#define BM_CPM_APCR_ON 0x400 +#define BF_CPM_APCR_ON(v) (((v) & 0x1) << 10) +#define BFM_CPM_APCR_ON(v) BM_CPM_APCR_ON +#define BF_CPM_APCR_ON_V(e) BF_CPM_APCR_ON(BV_CPM_APCR_ON__##e) +#define BFM_CPM_APCR_ON_V(v) BM_CPM_APCR_ON +#define BP_CPM_APCR_BYPASS 9 +#define BM_CPM_APCR_BYPASS 0x200 +#define BF_CPM_APCR_BYPASS(v) (((v) & 0x1) << 9) +#define BFM_CPM_APCR_BYPASS(v) BM_CPM_APCR_BYPASS +#define BF_CPM_APCR_BYPASS_V(e) BF_CPM_APCR_BYPASS(BV_CPM_APCR_BYPASS__##e) +#define BFM_CPM_APCR_BYPASS_V(v) BM_CPM_APCR_BYPASS +#define BP_CPM_APCR_ENABLE 8 +#define BM_CPM_APCR_ENABLE 0x100 +#define BF_CPM_APCR_ENABLE(v) (((v) & 0x1) << 8) +#define BFM_CPM_APCR_ENABLE(v) BM_CPM_APCR_ENABLE +#define BF_CPM_APCR_ENABLE_V(e) BF_CPM_APCR_ENABLE(BV_CPM_APCR_ENABLE__##e) +#define BFM_CPM_APCR_ENABLE_V(v) BM_CPM_APCR_ENABLE + +#define REG_CPM_MPCR jz_reg(CPM_MPCR) +#define JA_CPM_MPCR (0xb0000000 + 0x14) +#define JT_CPM_MPCR JIO_32_RW +#define JN_CPM_MPCR CPM_MPCR +#define JI_CPM_MPCR +#define BP_CPM_MPCR_PLLM 24 +#define BM_CPM_MPCR_PLLM 0x7f000000 +#define BF_CPM_MPCR_PLLM(v) (((v) & 0x7f) << 24) +#define BFM_CPM_MPCR_PLLM(v) BM_CPM_MPCR_PLLM +#define BF_CPM_MPCR_PLLM_V(e) BF_CPM_MPCR_PLLM(BV_CPM_MPCR_PLLM__##e) +#define BFM_CPM_MPCR_PLLM_V(v) BM_CPM_MPCR_PLLM +#define BP_CPM_MPCR_PLLN 18 +#define BM_CPM_MPCR_PLLN 0x7c0000 +#define BF_CPM_MPCR_PLLN(v) (((v) & 0x1f) << 18) +#define BFM_CPM_MPCR_PLLN(v) BM_CPM_MPCR_PLLN +#define BF_CPM_MPCR_PLLN_V(e) BF_CPM_MPCR_PLLN(BV_CPM_MPCR_PLLN__##e) +#define BFM_CPM_MPCR_PLLN_V(v) BM_CPM_MPCR_PLLN +#define BP_CPM_MPCR_PLLOD 16 +#define BM_CPM_MPCR_PLLOD 0x30000 +#define BF_CPM_MPCR_PLLOD(v) (((v) & 0x3) << 16) +#define BFM_CPM_MPCR_PLLOD(v) BM_CPM_MPCR_PLLOD +#define BF_CPM_MPCR_PLLOD_V(e) BF_CPM_MPCR_PLLOD(BV_CPM_MPCR_PLLOD__##e) +#define BFM_CPM_MPCR_PLLOD_V(v) BM_CPM_MPCR_PLLOD +#define BP_CPM_MPCR_BS 31 +#define BM_CPM_MPCR_BS 0x80000000 +#define BF_CPM_MPCR_BS(v) (((v) & 0x1) << 31) +#define BFM_CPM_MPCR_BS(v) BM_CPM_MPCR_BS +#define BF_CPM_MPCR_BS_V(e) BF_CPM_MPCR_BS(BV_CPM_MPCR_BS__##e) +#define BFM_CPM_MPCR_BS_V(v) BM_CPM_MPCR_BS +#define BP_CPM_MPCR_ENABLE 7 +#define BM_CPM_MPCR_ENABLE 0x80 +#define BF_CPM_MPCR_ENABLE(v) (((v) & 0x1) << 7) +#define BFM_CPM_MPCR_ENABLE(v) BM_CPM_MPCR_ENABLE +#define BF_CPM_MPCR_ENABLE_V(e) BF_CPM_MPCR_ENABLE(BV_CPM_MPCR_ENABLE__##e) +#define BFM_CPM_MPCR_ENABLE_V(v) BM_CPM_MPCR_ENABLE +#define BP_CPM_MPCR_BYPASS 6 +#define BM_CPM_MPCR_BYPASS 0x40 +#define BF_CPM_MPCR_BYPASS(v) (((v) & 0x1) << 6) +#define BFM_CPM_MPCR_BYPASS(v) BM_CPM_MPCR_BYPASS +#define BF_CPM_MPCR_BYPASS_V(e) BF_CPM_MPCR_BYPASS(BV_CPM_MPCR_BYPASS__##e) +#define BFM_CPM_MPCR_BYPASS_V(v) BM_CPM_MPCR_BYPASS +#define BP_CPM_MPCR_LOCK 1 +#define BM_CPM_MPCR_LOCK 0x2 +#define BF_CPM_MPCR_LOCK(v) (((v) & 0x1) << 1) +#define BFM_CPM_MPCR_LOCK(v) BM_CPM_MPCR_LOCK +#define BF_CPM_MPCR_LOCK_V(e) BF_CPM_MPCR_LOCK(BV_CPM_MPCR_LOCK__##e) +#define BFM_CPM_MPCR_LOCK_V(v) BM_CPM_MPCR_LOCK +#define BP_CPM_MPCR_ON 0 +#define BM_CPM_MPCR_ON 0x1 +#define BF_CPM_MPCR_ON(v) (((v) & 0x1) << 0) +#define BFM_CPM_MPCR_ON(v) BM_CPM_MPCR_ON +#define BF_CPM_MPCR_ON_V(e) BF_CPM_MPCR_ON(BV_CPM_MPCR_ON__##e) +#define BFM_CPM_MPCR_ON_V(v) BM_CPM_MPCR_ON + +#define REG_CPM_LCR jz_reg(CPM_LCR) +#define JA_CPM_LCR (0xb0000000 + 0x4) +#define JT_CPM_LCR JIO_32_RW +#define JN_CPM_LCR CPM_LCR +#define JI_CPM_LCR +#define BP_CPM_LCR_PST 8 +#define BM_CPM_LCR_PST 0xfff00 +#define BF_CPM_LCR_PST(v) (((v) & 0xfff) << 8) +#define BFM_CPM_LCR_PST(v) BM_CPM_LCR_PST +#define BF_CPM_LCR_PST_V(e) BF_CPM_LCR_PST(BV_CPM_LCR_PST__##e) +#define BFM_CPM_LCR_PST_V(v) BM_CPM_LCR_PST +#define BP_CPM_LCR_LPM 0 +#define BM_CPM_LCR_LPM 0x3 +#define BV_CPM_LCR_LPM__IDLE 0x0 +#define BV_CPM_LCR_LPM__SLEEP 0x1 +#define BF_CPM_LCR_LPM(v) (((v) & 0x3) << 0) +#define BFM_CPM_LCR_LPM(v) BM_CPM_LCR_LPM +#define BF_CPM_LCR_LPM_V(e) BF_CPM_LCR_LPM(BV_CPM_LCR_LPM__##e) +#define BFM_CPM_LCR_LPM_V(v) BM_CPM_LCR_LPM + +#define REG_CPM_PSWC0ST jz_reg(CPM_PSWC0ST) +#define JA_CPM_PSWC0ST (0xb0000000 + 0x90) +#define JT_CPM_PSWC0ST JIO_32_RW +#define JN_CPM_PSWC0ST CPM_PSWC0ST +#define JI_CPM_PSWC0ST + +#define REG_CPM_PSWC1ST jz_reg(CPM_PSWC1ST) +#define JA_CPM_PSWC1ST (0xb0000000 + 0x94) +#define JT_CPM_PSWC1ST JIO_32_RW +#define JN_CPM_PSWC1ST CPM_PSWC1ST +#define JI_CPM_PSWC1ST + +#define REG_CPM_PSWC2ST jz_reg(CPM_PSWC2ST) +#define JA_CPM_PSWC2ST (0xb0000000 + 0x98) +#define JT_CPM_PSWC2ST JIO_32_RW +#define JN_CPM_PSWC2ST CPM_PSWC2ST +#define JI_CPM_PSWC2ST + +#define REG_CPM_PSWC3ST jz_reg(CPM_PSWC3ST) +#define JA_CPM_PSWC3ST (0xb0000000 + 0x9c) +#define JT_CPM_PSWC3ST JIO_32_RW +#define JN_CPM_PSWC3ST CPM_PSWC3ST +#define JI_CPM_PSWC3ST + +#define REG_CPM_CLKGR jz_reg(CPM_CLKGR) +#define JA_CPM_CLKGR (0xb0000000 + 0x20) +#define JT_CPM_CLKGR JIO_32_RW +#define JN_CPM_CLKGR CPM_CLKGR +#define JI_CPM_CLKGR +#define BP_CPM_CLKGR_DDR 31 +#define BM_CPM_CLKGR_DDR 0x80000000 +#define BF_CPM_CLKGR_DDR(v) (((v) & 0x1) << 31) +#define BFM_CPM_CLKGR_DDR(v) BM_CPM_CLKGR_DDR +#define BF_CPM_CLKGR_DDR_V(e) BF_CPM_CLKGR_DDR(BV_CPM_CLKGR_DDR__##e) +#define BFM_CPM_CLKGR_DDR_V(v) BM_CPM_CLKGR_DDR +#define BP_CPM_CLKGR_CPU_BIT 30 +#define BM_CPM_CLKGR_CPU_BIT 0x40000000 +#define BF_CPM_CLKGR_CPU_BIT(v) (((v) & 0x1) << 30) +#define BFM_CPM_CLKGR_CPU_BIT(v) BM_CPM_CLKGR_CPU_BIT +#define BF_CPM_CLKGR_CPU_BIT_V(e) BF_CPM_CLKGR_CPU_BIT(BV_CPM_CLKGR_CPU_BIT__##e) +#define BFM_CPM_CLKGR_CPU_BIT_V(v) BM_CPM_CLKGR_CPU_BIT +#define BP_CPM_CLKGR_AHB0 29 +#define BM_CPM_CLKGR_AHB0 0x20000000 +#define BF_CPM_CLKGR_AHB0(v) (((v) & 0x1) << 29) +#define BFM_CPM_CLKGR_AHB0(v) BM_CPM_CLKGR_AHB0 +#define BF_CPM_CLKGR_AHB0_V(e) BF_CPM_CLKGR_AHB0(BV_CPM_CLKGR_AHB0__##e) +#define BFM_CPM_CLKGR_AHB0_V(v) BM_CPM_CLKGR_AHB0 +#define BP_CPM_CLKGR_APB0 28 +#define BM_CPM_CLKGR_APB0 0x10000000 +#define BF_CPM_CLKGR_APB0(v) (((v) & 0x1) << 28) +#define BFM_CPM_CLKGR_APB0(v) BM_CPM_CLKGR_APB0 +#define BF_CPM_CLKGR_APB0_V(e) BF_CPM_CLKGR_APB0(BV_CPM_CLKGR_APB0__##e) +#define BFM_CPM_CLKGR_APB0_V(v) BM_CPM_CLKGR_APB0 +#define BP_CPM_CLKGR_RTC 27 +#define BM_CPM_CLKGR_RTC 0x8000000 +#define BF_CPM_CLKGR_RTC(v) (((v) & 0x1) << 27) +#define BFM_CPM_CLKGR_RTC(v) BM_CPM_CLKGR_RTC +#define BF_CPM_CLKGR_RTC_V(e) BF_CPM_CLKGR_RTC(BV_CPM_CLKGR_RTC__##e) +#define BFM_CPM_CLKGR_RTC_V(v) BM_CPM_CLKGR_RTC +#define BP_CPM_CLKGR_PCM 26 +#define BM_CPM_CLKGR_PCM 0x4000000 +#define BF_CPM_CLKGR_PCM(v) (((v) & 0x1) << 26) +#define BFM_CPM_CLKGR_PCM(v) BM_CPM_CLKGR_PCM +#define BF_CPM_CLKGR_PCM_V(e) BF_CPM_CLKGR_PCM(BV_CPM_CLKGR_PCM__##e) +#define BFM_CPM_CLKGR_PCM_V(v) BM_CPM_CLKGR_PCM +#define BP_CPM_CLKGR_MAC 25 +#define BM_CPM_CLKGR_MAC 0x2000000 +#define BF_CPM_CLKGR_MAC(v) (((v) & 0x1) << 25) +#define BFM_CPM_CLKGR_MAC(v) BM_CPM_CLKGR_MAC +#define BF_CPM_CLKGR_MAC_V(e) BF_CPM_CLKGR_MAC(BV_CPM_CLKGR_MAC__##e) +#define BFM_CPM_CLKGR_MAC_V(v) BM_CPM_CLKGR_MAC +#define BP_CPM_CLKGR_AES 24 +#define BM_CPM_CLKGR_AES 0x1000000 +#define BF_CPM_CLKGR_AES(v) (((v) & 0x1) << 24) +#define BFM_CPM_CLKGR_AES(v) BM_CPM_CLKGR_AES +#define BF_CPM_CLKGR_AES_V(e) BF_CPM_CLKGR_AES(BV_CPM_CLKGR_AES__##e) +#define BFM_CPM_CLKGR_AES_V(v) BM_CPM_CLKGR_AES +#define BP_CPM_CLKGR_LCD 23 +#define BM_CPM_CLKGR_LCD 0x800000 +#define BF_CPM_CLKGR_LCD(v) (((v) & 0x1) << 23) +#define BFM_CPM_CLKGR_LCD(v) BM_CPM_CLKGR_LCD +#define BF_CPM_CLKGR_LCD_V(e) BF_CPM_CLKGR_LCD(BV_CPM_CLKGR_LCD__##e) +#define BFM_CPM_CLKGR_LCD_V(v) BM_CPM_CLKGR_LCD +#define BP_CPM_CLKGR_CIM 22 +#define BM_CPM_CLKGR_CIM 0x400000 +#define BF_CPM_CLKGR_CIM(v) (((v) & 0x1) << 22) +#define BFM_CPM_CLKGR_CIM(v) BM_CPM_CLKGR_CIM +#define BF_CPM_CLKGR_CIM_V(e) BF_CPM_CLKGR_CIM(BV_CPM_CLKGR_CIM__##e) +#define BFM_CPM_CLKGR_CIM_V(v) BM_CPM_CLKGR_CIM +#define BP_CPM_CLKGR_PDMA 21 +#define BM_CPM_CLKGR_PDMA 0x200000 +#define BF_CPM_CLKGR_PDMA(v) (((v) & 0x1) << 21) +#define BFM_CPM_CLKGR_PDMA(v) BM_CPM_CLKGR_PDMA +#define BF_CPM_CLKGR_PDMA_V(e) BF_CPM_CLKGR_PDMA(BV_CPM_CLKGR_PDMA__##e) +#define BFM_CPM_CLKGR_PDMA_V(v) BM_CPM_CLKGR_PDMA +#define BP_CPM_CLKGR_OST 20 +#define BM_CPM_CLKGR_OST 0x100000 +#define BF_CPM_CLKGR_OST(v) (((v) & 0x1) << 20) +#define BFM_CPM_CLKGR_OST(v) BM_CPM_CLKGR_OST +#define BF_CPM_CLKGR_OST_V(e) BF_CPM_CLKGR_OST(BV_CPM_CLKGR_OST__##e) +#define BFM_CPM_CLKGR_OST_V(v) BM_CPM_CLKGR_OST +#define BP_CPM_CLKGR_SSI 19 +#define BM_CPM_CLKGR_SSI 0x80000 +#define BF_CPM_CLKGR_SSI(v) (((v) & 0x1) << 19) +#define BFM_CPM_CLKGR_SSI(v) BM_CPM_CLKGR_SSI +#define BF_CPM_CLKGR_SSI_V(e) BF_CPM_CLKGR_SSI(BV_CPM_CLKGR_SSI__##e) +#define BFM_CPM_CLKGR_SSI_V(v) BM_CPM_CLKGR_SSI +#define BP_CPM_CLKGR_TCU 18 +#define BM_CPM_CLKGR_TCU 0x40000 +#define BF_CPM_CLKGR_TCU(v) (((v) & 0x1) << 18) +#define BFM_CPM_CLKGR_TCU(v) BM_CPM_CLKGR_TCU +#define BF_CPM_CLKGR_TCU_V(e) BF_CPM_CLKGR_TCU(BV_CPM_CLKGR_TCU__##e) +#define BFM_CPM_CLKGR_TCU_V(v) BM_CPM_CLKGR_TCU +#define BP_CPM_CLKGR_DMIC 17 +#define BM_CPM_CLKGR_DMIC 0x20000 +#define BF_CPM_CLKGR_DMIC(v) (((v) & 0x1) << 17) +#define BFM_CPM_CLKGR_DMIC(v) BM_CPM_CLKGR_DMIC +#define BF_CPM_CLKGR_DMIC_V(e) BF_CPM_CLKGR_DMIC(BV_CPM_CLKGR_DMIC__##e) +#define BFM_CPM_CLKGR_DMIC_V(v) BM_CPM_CLKGR_DMIC +#define BP_CPM_CLKGR_UART2 16 +#define BM_CPM_CLKGR_UART2 0x10000 +#define BF_CPM_CLKGR_UART2(v) (((v) & 0x1) << 16) +#define BFM_CPM_CLKGR_UART2(v) BM_CPM_CLKGR_UART2 +#define BF_CPM_CLKGR_UART2_V(e) BF_CPM_CLKGR_UART2(BV_CPM_CLKGR_UART2__##e) +#define BFM_CPM_CLKGR_UART2_V(v) BM_CPM_CLKGR_UART2 +#define BP_CPM_CLKGR_UART1 15 +#define BM_CPM_CLKGR_UART1 0x8000 +#define BF_CPM_CLKGR_UART1(v) (((v) & 0x1) << 15) +#define BFM_CPM_CLKGR_UART1(v) BM_CPM_CLKGR_UART1 +#define BF_CPM_CLKGR_UART1_V(e) BF_CPM_CLKGR_UART1(BV_CPM_CLKGR_UART1__##e) +#define BFM_CPM_CLKGR_UART1_V(v) BM_CPM_CLKGR_UART1 +#define BP_CPM_CLKGR_UART0 14 +#define BM_CPM_CLKGR_UART0 0x4000 +#define BF_CPM_CLKGR_UART0(v) (((v) & 0x1) << 14) +#define BFM_CPM_CLKGR_UART0(v) BM_CPM_CLKGR_UART0 +#define BF_CPM_CLKGR_UART0_V(e) BF_CPM_CLKGR_UART0(BV_CPM_CLKGR_UART0__##e) +#define BFM_CPM_CLKGR_UART0_V(v) BM_CPM_CLKGR_UART0 +#define BP_CPM_CLKGR_JPEG 12 +#define BM_CPM_CLKGR_JPEG 0x1000 +#define BF_CPM_CLKGR_JPEG(v) (((v) & 0x1) << 12) +#define BFM_CPM_CLKGR_JPEG(v) BM_CPM_CLKGR_JPEG +#define BF_CPM_CLKGR_JPEG_V(e) BF_CPM_CLKGR_JPEG(BV_CPM_CLKGR_JPEG__##e) +#define BFM_CPM_CLKGR_JPEG_V(v) BM_CPM_CLKGR_JPEG +#define BP_CPM_CLKGR_AIC 11 +#define BM_CPM_CLKGR_AIC 0x800 +#define BF_CPM_CLKGR_AIC(v) (((v) & 0x1) << 11) +#define BFM_CPM_CLKGR_AIC(v) BM_CPM_CLKGR_AIC +#define BF_CPM_CLKGR_AIC_V(e) BF_CPM_CLKGR_AIC(BV_CPM_CLKGR_AIC__##e) +#define BFM_CPM_CLKGR_AIC_V(v) BM_CPM_CLKGR_AIC +#define BP_CPM_CLKGR_I2C2 9 +#define BM_CPM_CLKGR_I2C2 0x200 +#define BF_CPM_CLKGR_I2C2(v) (((v) & 0x1) << 9) +#define BFM_CPM_CLKGR_I2C2(v) BM_CPM_CLKGR_I2C2 +#define BF_CPM_CLKGR_I2C2_V(e) BF_CPM_CLKGR_I2C2(BV_CPM_CLKGR_I2C2__##e) +#define BFM_CPM_CLKGR_I2C2_V(v) BM_CPM_CLKGR_I2C2 +#define BP_CPM_CLKGR_I2C1 8 +#define BM_CPM_CLKGR_I2C1 0x100 +#define BF_CPM_CLKGR_I2C1(v) (((v) & 0x1) << 8) +#define BFM_CPM_CLKGR_I2C1(v) BM_CPM_CLKGR_I2C1 +#define BF_CPM_CLKGR_I2C1_V(e) BF_CPM_CLKGR_I2C1(BV_CPM_CLKGR_I2C1__##e) +#define BFM_CPM_CLKGR_I2C1_V(v) BM_CPM_CLKGR_I2C1 +#define BP_CPM_CLKGR_I2C0 7 +#define BM_CPM_CLKGR_I2C0 0x80 +#define BF_CPM_CLKGR_I2C0(v) (((v) & 0x1) << 7) +#define BFM_CPM_CLKGR_I2C0(v) BM_CPM_CLKGR_I2C0 +#define BF_CPM_CLKGR_I2C0_V(e) BF_CPM_CLKGR_I2C0(BV_CPM_CLKGR_I2C0__##e) +#define BFM_CPM_CLKGR_I2C0_V(v) BM_CPM_CLKGR_I2C0 +#define BP_CPM_CLKGR_SCC 6 +#define BM_CPM_CLKGR_SCC 0x40 +#define BF_CPM_CLKGR_SCC(v) (((v) & 0x1) << 6) +#define BFM_CPM_CLKGR_SCC(v) BM_CPM_CLKGR_SCC +#define BF_CPM_CLKGR_SCC_V(e) BF_CPM_CLKGR_SCC(BV_CPM_CLKGR_SCC__##e) +#define BFM_CPM_CLKGR_SCC_V(v) BM_CPM_CLKGR_SCC +#define BP_CPM_CLKGR_MSC1 5 +#define BM_CPM_CLKGR_MSC1 0x20 +#define BF_CPM_CLKGR_MSC1(v) (((v) & 0x1) << 5) +#define BFM_CPM_CLKGR_MSC1(v) BM_CPM_CLKGR_MSC1 +#define BF_CPM_CLKGR_MSC1_V(e) BF_CPM_CLKGR_MSC1(BV_CPM_CLKGR_MSC1__##e) +#define BFM_CPM_CLKGR_MSC1_V(v) BM_CPM_CLKGR_MSC1 +#define BP_CPM_CLKGR_MSC0 4 +#define BM_CPM_CLKGR_MSC0 0x10 +#define BF_CPM_CLKGR_MSC0(v) (((v) & 0x1) << 4) +#define BFM_CPM_CLKGR_MSC0(v) BM_CPM_CLKGR_MSC0 +#define BF_CPM_CLKGR_MSC0_V(e) BF_CPM_CLKGR_MSC0(BV_CPM_CLKGR_MSC0__##e) +#define BFM_CPM_CLKGR_MSC0_V(v) BM_CPM_CLKGR_MSC0 +#define BP_CPM_CLKGR_OTG 3 +#define BM_CPM_CLKGR_OTG 0x8 +#define BF_CPM_CLKGR_OTG(v) (((v) & 0x1) << 3) +#define BFM_CPM_CLKGR_OTG(v) BM_CPM_CLKGR_OTG +#define BF_CPM_CLKGR_OTG_V(e) BF_CPM_CLKGR_OTG(BV_CPM_CLKGR_OTG__##e) +#define BFM_CPM_CLKGR_OTG_V(v) BM_CPM_CLKGR_OTG +#define BP_CPM_CLKGR_SFC 2 +#define BM_CPM_CLKGR_SFC 0x4 +#define BF_CPM_CLKGR_SFC(v) (((v) & 0x1) << 2) +#define BFM_CPM_CLKGR_SFC(v) BM_CPM_CLKGR_SFC +#define BF_CPM_CLKGR_SFC_V(e) BF_CPM_CLKGR_SFC(BV_CPM_CLKGR_SFC__##e) +#define BFM_CPM_CLKGR_SFC_V(v) BM_CPM_CLKGR_SFC +#define BP_CPM_CLKGR_EFUSE 1 +#define BM_CPM_CLKGR_EFUSE 0x2 +#define BF_CPM_CLKGR_EFUSE(v) (((v) & 0x1) << 1) +#define BFM_CPM_CLKGR_EFUSE(v) BM_CPM_CLKGR_EFUSE +#define BF_CPM_CLKGR_EFUSE_V(e) BF_CPM_CLKGR_EFUSE(BV_CPM_CLKGR_EFUSE__##e) +#define BFM_CPM_CLKGR_EFUSE_V(v) BM_CPM_CLKGR_EFUSE + +#define REG_CPM_OPCR jz_reg(CPM_OPCR) +#define JA_CPM_OPCR (0xb0000000 + 0x24) +#define JT_CPM_OPCR JIO_32_RW +#define JN_CPM_OPCR CPM_OPCR +#define JI_CPM_OPCR +#define BP_CPM_OPCR_O1ST 8 +#define BM_CPM_OPCR_O1ST 0xfff00 +#define BF_CPM_OPCR_O1ST(v) (((v) & 0xfff) << 8) +#define BFM_CPM_OPCR_O1ST(v) BM_CPM_OPCR_O1ST +#define BF_CPM_OPCR_O1ST_V(e) BF_CPM_OPCR_O1ST(BV_CPM_OPCR_O1ST__##e) +#define BFM_CPM_OPCR_O1ST_V(v) BM_CPM_OPCR_O1ST +#define BP_CPM_OPCR_IDLE_DIS 31 +#define BM_CPM_OPCR_IDLE_DIS 0x80000000 +#define BF_CPM_OPCR_IDLE_DIS(v) (((v) & 0x1) << 31) +#define BFM_CPM_OPCR_IDLE_DIS(v) BM_CPM_OPCR_IDLE_DIS +#define BF_CPM_OPCR_IDLE_DIS_V(e) BF_CPM_OPCR_IDLE_DIS(BV_CPM_OPCR_IDLE_DIS__##e) +#define BFM_CPM_OPCR_IDLE_DIS_V(v) BM_CPM_OPCR_IDLE_DIS +#define BP_CPM_OPCR_MASK_INT 30 +#define BM_CPM_OPCR_MASK_INT 0x40000000 +#define BF_CPM_OPCR_MASK_INT(v) (((v) & 0x1) << 30) +#define BFM_CPM_OPCR_MASK_INT(v) BM_CPM_OPCR_MASK_INT +#define BF_CPM_OPCR_MASK_INT_V(e) BF_CPM_OPCR_MASK_INT(BV_CPM_OPCR_MASK_INT__##e) +#define BFM_CPM_OPCR_MASK_INT_V(v) BM_CPM_OPCR_MASK_INT +#define BP_CPM_OPCR_MASK_VPU 29 +#define BM_CPM_OPCR_MASK_VPU 0x20000000 +#define BF_CPM_OPCR_MASK_VPU(v) (((v) & 0x1) << 29) +#define BFM_CPM_OPCR_MASK_VPU(v) BM_CPM_OPCR_MASK_VPU +#define BF_CPM_OPCR_MASK_VPU_V(e) BF_CPM_OPCR_MASK_VPU(BV_CPM_OPCR_MASK_VPU__##e) +#define BFM_CPM_OPCR_MASK_VPU_V(v) BM_CPM_OPCR_MASK_VPU +#define BP_CPM_OPCR_GATE_SCLK_A_BUS 28 +#define BM_CPM_OPCR_GATE_SCLK_A_BUS 0x10000000 +#define BF_CPM_OPCR_GATE_SCLK_A_BUS(v) (((v) & 0x1) << 28) +#define BFM_CPM_OPCR_GATE_SCLK_A_BUS(v) BM_CPM_OPCR_GATE_SCLK_A_BUS +#define BF_CPM_OPCR_GATE_SCLK_A_BUS_V(e) BF_CPM_OPCR_GATE_SCLK_A_BUS(BV_CPM_OPCR_GATE_SCLK_A_BUS__##e) +#define BFM_CPM_OPCR_GATE_SCLK_A_BUS_V(v) BM_CPM_OPCR_GATE_SCLK_A_BUS +#define BP_CPM_OPCR_L2C_PD 25 +#define BM_CPM_OPCR_L2C_PD 0x2000000 +#define BF_CPM_OPCR_L2C_PD(v) (((v) & 0x1) << 25) +#define BFM_CPM_OPCR_L2C_PD(v) BM_CPM_OPCR_L2C_PD +#define BF_CPM_OPCR_L2C_PD_V(e) BF_CPM_OPCR_L2C_PD(BV_CPM_OPCR_L2C_PD__##e) +#define BFM_CPM_OPCR_L2C_PD_V(v) BM_CPM_OPCR_L2C_PD +#define BP_CPM_OPCR_REQ_MODE 24 +#define BM_CPM_OPCR_REQ_MODE 0x1000000 +#define BF_CPM_OPCR_REQ_MODE(v) (((v) & 0x1) << 24) +#define BFM_CPM_OPCR_REQ_MODE(v) BM_CPM_OPCR_REQ_MODE +#define BF_CPM_OPCR_REQ_MODE_V(e) BF_CPM_OPCR_REQ_MODE(BV_CPM_OPCR_REQ_MODE__##e) +#define BFM_CPM_OPCR_REQ_MODE_V(v) BM_CPM_OPCR_REQ_MODE +#define BP_CPM_OPCR_GATE_USBPHY_CLK 23 +#define BM_CPM_OPCR_GATE_USBPHY_CLK 0x800000 +#define BF_CPM_OPCR_GATE_USBPHY_CLK(v) (((v) & 0x1) << 23) +#define BFM_CPM_OPCR_GATE_USBPHY_CLK(v) BM_CPM_OPCR_GATE_USBPHY_CLK +#define BF_CPM_OPCR_GATE_USBPHY_CLK_V(e) BF_CPM_OPCR_GATE_USBPHY_CLK(BV_CPM_OPCR_GATE_USBPHY_CLK__##e) +#define BFM_CPM_OPCR_GATE_USBPHY_CLK_V(v) BM_CPM_OPCR_GATE_USBPHY_CLK +#define BP_CPM_OPCR_DIS_STOP_MUX 22 +#define BM_CPM_OPCR_DIS_STOP_MUX 0x400000 +#define BF_CPM_OPCR_DIS_STOP_MUX(v) (((v) & 0x1) << 22) +#define BFM_CPM_OPCR_DIS_STOP_MUX(v) BM_CPM_OPCR_DIS_STOP_MUX +#define BF_CPM_OPCR_DIS_STOP_MUX_V(e) BF_CPM_OPCR_DIS_STOP_MUX(BV_CPM_OPCR_DIS_STOP_MUX__##e) +#define BFM_CPM_OPCR_DIS_STOP_MUX_V(v) BM_CPM_OPCR_DIS_STOP_MUX +#define BP_CPM_OPCR_SPENDN0 7 +#define BM_CPM_OPCR_SPENDN0 0x80 +#define BF_CPM_OPCR_SPENDN0(v) (((v) & 0x1) << 7) +#define BFM_CPM_OPCR_SPENDN0(v) BM_CPM_OPCR_SPENDN0 +#define BF_CPM_OPCR_SPENDN0_V(e) BF_CPM_OPCR_SPENDN0(BV_CPM_OPCR_SPENDN0__##e) +#define BFM_CPM_OPCR_SPENDN0_V(v) BM_CPM_OPCR_SPENDN0 +#define BP_CPM_OPCR_SPENDN1 6 +#define BM_CPM_OPCR_SPENDN1 0x40 +#define BF_CPM_OPCR_SPENDN1(v) (((v) & 0x1) << 6) +#define BFM_CPM_OPCR_SPENDN1(v) BM_CPM_OPCR_SPENDN1 +#define BF_CPM_OPCR_SPENDN1_V(e) BF_CPM_OPCR_SPENDN1(BV_CPM_OPCR_SPENDN1__##e) +#define BFM_CPM_OPCR_SPENDN1_V(v) BM_CPM_OPCR_SPENDN1 +#define BP_CPM_OPCR_CPU_MODE 5 +#define BM_CPM_OPCR_CPU_MODE 0x20 +#define BF_CPM_OPCR_CPU_MODE(v) (((v) & 0x1) << 5) +#define BFM_CPM_OPCR_CPU_MODE(v) BM_CPM_OPCR_CPU_MODE +#define BF_CPM_OPCR_CPU_MODE_V(e) BF_CPM_OPCR_CPU_MODE(BV_CPM_OPCR_CPU_MODE__##e) +#define BFM_CPM_OPCR_CPU_MODE_V(v) BM_CPM_OPCR_CPU_MODE +#define BP_CPM_OPCR_O1SE 4 +#define BM_CPM_OPCR_O1SE 0x10 +#define BF_CPM_OPCR_O1SE(v) (((v) & 0x1) << 4) +#define BFM_CPM_OPCR_O1SE(v) BM_CPM_OPCR_O1SE +#define BF_CPM_OPCR_O1SE_V(e) BF_CPM_OPCR_O1SE(BV_CPM_OPCR_O1SE__##e) +#define BFM_CPM_OPCR_O1SE_V(v) BM_CPM_OPCR_O1SE +#define BP_CPM_OPCR_PD 3 +#define BM_CPM_OPCR_PD 0x8 +#define BF_CPM_OPCR_PD(v) (((v) & 0x1) << 3) +#define BFM_CPM_OPCR_PD(v) BM_CPM_OPCR_PD +#define BF_CPM_OPCR_PD_V(e) BF_CPM_OPCR_PD(BV_CPM_OPCR_PD__##e) +#define BFM_CPM_OPCR_PD_V(v) BM_CPM_OPCR_PD +#define BP_CPM_OPCR_ERCS 2 +#define BM_CPM_OPCR_ERCS 0x4 +#define BF_CPM_OPCR_ERCS(v) (((v) & 0x1) << 2) +#define BFM_CPM_OPCR_ERCS(v) BM_CPM_OPCR_ERCS +#define BF_CPM_OPCR_ERCS_V(e) BF_CPM_OPCR_ERCS(BV_CPM_OPCR_ERCS__##e) +#define BFM_CPM_OPCR_ERCS_V(v) BM_CPM_OPCR_ERCS +#define BP_CPM_OPCR_BUS_MODE 1 +#define BM_CPM_OPCR_BUS_MODE 0x2 +#define BF_CPM_OPCR_BUS_MODE(v) (((v) & 0x1) << 1) +#define BFM_CPM_OPCR_BUS_MODE(v) BM_CPM_OPCR_BUS_MODE +#define BF_CPM_OPCR_BUS_MODE_V(e) BF_CPM_OPCR_BUS_MODE(BV_CPM_OPCR_BUS_MODE__##e) +#define BFM_CPM_OPCR_BUS_MODE_V(v) BM_CPM_OPCR_BUS_MODE + +#endif /* __HEADERGEN_CPM_H__*/ diff --git a/firmware/target/mips/ingenic_x1000/x1000/ddrc.h b/firmware/target/mips/ingenic_x1000/x1000/ddrc.h new file mode 100644 index 0000000000..f482969a4e --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/x1000/ddrc.h @@ -0,0 +1,149 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * This file was automatically generated by headergen, DO NOT EDIT it. + * headergen version: 3.0.0 + * x1000 version: 1.0 + * x1000 authors: Aidan MacDonald + * + * Copyright (C) 2015 by the authors + * + * 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 __HEADERGEN_DDRC_H__ +#define __HEADERGEN_DDRC_H__ + +#include "macro.h" + +#define REG_DDRC_STATUS jz_reg(DDRC_STATUS) +#define JA_DDRC_STATUS (0xb34f0000 + 0x0) +#define JT_DDRC_STATUS JIO_32_RW +#define JN_DDRC_STATUS DDRC_STATUS +#define JI_DDRC_STATUS + +#define REG_DDRC_CFG jz_reg(DDRC_CFG) +#define JA_DDRC_CFG (0xb34f0000 + 0x4) +#define JT_DDRC_CFG JIO_32_RW +#define JN_DDRC_CFG DDRC_CFG +#define JI_DDRC_CFG + +#define REG_DDRC_CTRL jz_reg(DDRC_CTRL) +#define JA_DDRC_CTRL (0xb34f0000 + 0x8) +#define JT_DDRC_CTRL JIO_32_RW +#define JN_DDRC_CTRL DDRC_CTRL +#define JI_DDRC_CTRL + +#define REG_DDRC_TIMING1 jz_reg(DDRC_TIMING1) +#define JA_DDRC_TIMING1 (0xb34f0000 + 0x60) +#define JT_DDRC_TIMING1 JIO_32_RW +#define JN_DDRC_TIMING1 DDRC_TIMING1 +#define JI_DDRC_TIMING1 + +#define REG_DDRC_TIMING2 jz_reg(DDRC_TIMING2) +#define JA_DDRC_TIMING2 (0xb34f0000 + 0x64) +#define JT_DDRC_TIMING2 JIO_32_RW +#define JN_DDRC_TIMING2 DDRC_TIMING2 +#define JI_DDRC_TIMING2 + +#define REG_DDRC_TIMING3 jz_reg(DDRC_TIMING3) +#define JA_DDRC_TIMING3 (0xb34f0000 + 0x68) +#define JT_DDRC_TIMING3 JIO_32_RW +#define JN_DDRC_TIMING3 DDRC_TIMING3 +#define JI_DDRC_TIMING3 + +#define REG_DDRC_TIMING4 jz_reg(DDRC_TIMING4) +#define JA_DDRC_TIMING4 (0xb34f0000 + 0x6c) +#define JT_DDRC_TIMING4 JIO_32_RW +#define JN_DDRC_TIMING4 DDRC_TIMING4 +#define JI_DDRC_TIMING4 + +#define REG_DDRC_TIMING5 jz_reg(DDRC_TIMING5) +#define JA_DDRC_TIMING5 (0xb34f0000 + 0x70) +#define JT_DDRC_TIMING5 JIO_32_RW +#define JN_DDRC_TIMING5 DDRC_TIMING5 +#define JI_DDRC_TIMING5 + +#define REG_DDRC_TIMING6 jz_reg(DDRC_TIMING6) +#define JA_DDRC_TIMING6 (0xb34f0000 + 0x74) +#define JT_DDRC_TIMING6 JIO_32_RW +#define JN_DDRC_TIMING6 DDRC_TIMING6 +#define JI_DDRC_TIMING6 + +#define REG_DDRC_REFCNT jz_reg(DDRC_REFCNT) +#define JA_DDRC_REFCNT (0xb34f0000 + 0x18) +#define JT_DDRC_REFCNT JIO_32_RW +#define JN_DDRC_REFCNT DDRC_REFCNT +#define JI_DDRC_REFCNT + +#define REG_DDRC_MMAP0 jz_reg(DDRC_MMAP0) +#define JA_DDRC_MMAP0 (0xb34f0000 + 0x24) +#define JT_DDRC_MMAP0 JIO_32_RW +#define JN_DDRC_MMAP0 DDRC_MMAP0 +#define JI_DDRC_MMAP0 + +#define REG_DDRC_MMAP1 jz_reg(DDRC_MMAP1) +#define JA_DDRC_MMAP1 (0xb34f0000 + 0x28) +#define JT_DDRC_MMAP1 JIO_32_RW +#define JN_DDRC_MMAP1 DDRC_MMAP1 +#define JI_DDRC_MMAP1 + +#define REG_DDRC_DLP jz_reg(DDRC_DLP) +#define JA_DDRC_DLP (0xb34f0000 + 0xbc) +#define JT_DDRC_DLP JIO_32_RW +#define JN_DDRC_DLP DDRC_DLP +#define JI_DDRC_DLP + +#define REG_DDRC_REMAP1 jz_reg(DDRC_REMAP1) +#define JA_DDRC_REMAP1 (0xb34f0000 + 0x9c) +#define JT_DDRC_REMAP1 JIO_32_RW +#define JN_DDRC_REMAP1 DDRC_REMAP1 +#define JI_DDRC_REMAP1 + +#define REG_DDRC_REMAP2 jz_reg(DDRC_REMAP2) +#define JA_DDRC_REMAP2 (0xb34f0000 + 0xa0) +#define JT_DDRC_REMAP2 JIO_32_RW +#define JN_DDRC_REMAP2 DDRC_REMAP2 +#define JI_DDRC_REMAP2 + +#define REG_DDRC_REMAP3 jz_reg(DDRC_REMAP3) +#define JA_DDRC_REMAP3 (0xb34f0000 + 0xa4) +#define JT_DDRC_REMAP3 JIO_32_RW +#define JN_DDRC_REMAP3 DDRC_REMAP3 +#define JI_DDRC_REMAP3 + +#define REG_DDRC_REMAP4 jz_reg(DDRC_REMAP4) +#define JA_DDRC_REMAP4 (0xb34f0000 + 0xa8) +#define JT_DDRC_REMAP4 JIO_32_RW +#define JN_DDRC_REMAP4 DDRC_REMAP4 +#define JI_DDRC_REMAP4 + +#define REG_DDRC_REMAP5 jz_reg(DDRC_REMAP5) +#define JA_DDRC_REMAP5 (0xb34f0000 + 0xac) +#define JT_DDRC_REMAP5 JIO_32_RW +#define JN_DDRC_REMAP5 DDRC_REMAP5 +#define JI_DDRC_REMAP5 + +#define REG_DDRC_AUTOSR_CNT jz_reg(DDRC_AUTOSR_CNT) +#define JA_DDRC_AUTOSR_CNT (0xb34f0000 + 0x308) +#define JT_DDRC_AUTOSR_CNT JIO_32_RW +#define JN_DDRC_AUTOSR_CNT DDRC_AUTOSR_CNT +#define JI_DDRC_AUTOSR_CNT + +#define REG_DDRC_AUTOSR_EN jz_reg(DDRC_AUTOSR_EN) +#define JA_DDRC_AUTOSR_EN (0xb34f0000 + 0x304) +#define JT_DDRC_AUTOSR_EN JIO_32_RW +#define JN_DDRC_AUTOSR_EN DDRC_AUTOSR_EN +#define JI_DDRC_AUTOSR_EN + +#endif /* __HEADERGEN_DDRC_H__*/ diff --git a/firmware/target/mips/ingenic_x1000/x1000/ddrc_apb.h b/firmware/target/mips/ingenic_x1000/x1000/ddrc_apb.h new file mode 100644 index 0000000000..bcb880624f --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/x1000/ddrc_apb.h @@ -0,0 +1,41 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * This file was automatically generated by headergen, DO NOT EDIT it. + * headergen version: 3.0.0 + * x1000 version: 1.0 + * x1000 authors: Aidan MacDonald + * + * Copyright (C) 2015 by the authors + * + * 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 __HEADERGEN_DDRC_APB_H__ +#define __HEADERGEN_DDRC_APB_H__ + +#include "macro.h" + +#define REG_DDRC_APB_CLKSTP_CFG jz_reg(DDRC_APB_CLKSTP_CFG) +#define JA_DDRC_APB_CLKSTP_CFG (0xb3012000 + 0x68) +#define JT_DDRC_APB_CLKSTP_CFG JIO_32_RW +#define JN_DDRC_APB_CLKSTP_CFG DDRC_APB_CLKSTP_CFG +#define JI_DDRC_APB_CLKSTP_CFG + +#define REG_DDRC_APB_PHYRST_CFG jz_reg(DDRC_APB_PHYRST_CFG) +#define JA_DDRC_APB_PHYRST_CFG (0xb3012000 + 0x80) +#define JT_DDRC_APB_PHYRST_CFG JIO_32_RW +#define JN_DDRC_APB_PHYRST_CFG DDRC_APB_PHYRST_CFG +#define JI_DDRC_APB_PHYRST_CFG + +#endif /* __HEADERGEN_DDRC_APB_H__*/ diff --git a/firmware/target/mips/ingenic_x1000/x1000/ddrphy.h b/firmware/target/mips/ingenic_x1000/x1000/ddrphy.h new file mode 100644 index 0000000000..2ac0563090 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/x1000/ddrphy.h @@ -0,0 +1,155 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * This file was automatically generated by headergen, DO NOT EDIT it. + * headergen version: 3.0.0 + * x1000 version: 1.0 + * x1000 authors: Aidan MacDonald + * + * Copyright (C) 2015 by the authors + * + * 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 __HEADERGEN_DDRPHY_H__ +#define __HEADERGEN_DDRPHY_H__ + +#include "macro.h" + +#define REG_DDRPHY_PIR jz_reg(DDRPHY_PIR) +#define JA_DDRPHY_PIR (0xb3011000 + 0x4) +#define JT_DDRPHY_PIR JIO_32_RW +#define JN_DDRPHY_PIR DDRPHY_PIR +#define JI_DDRPHY_PIR + +#define REG_DDRPHY_PGCR jz_reg(DDRPHY_PGCR) +#define JA_DDRPHY_PGCR (0xb3011000 + 0x8) +#define JT_DDRPHY_PGCR JIO_32_RW +#define JN_DDRPHY_PGCR DDRPHY_PGCR +#define JI_DDRPHY_PGCR + +#define REG_DDRPHY_PGSR jz_reg(DDRPHY_PGSR) +#define JA_DDRPHY_PGSR (0xb3011000 + 0xc) +#define JT_DDRPHY_PGSR JIO_32_RW +#define JN_DDRPHY_PGSR DDRPHY_PGSR +#define JI_DDRPHY_PGSR + +#define REG_DDRPHY_DLLGCR jz_reg(DDRPHY_DLLGCR) +#define JA_DDRPHY_DLLGCR (0xb3011000 + 0x10) +#define JT_DDRPHY_DLLGCR JIO_32_RW +#define JN_DDRPHY_DLLGCR DDRPHY_DLLGCR +#define JI_DDRPHY_DLLGCR + +#define REG_DDRPHY_ACDLLCR jz_reg(DDRPHY_ACDLLCR) +#define JA_DDRPHY_ACDLLCR (0xb3011000 + 0x14) +#define JT_DDRPHY_ACDLLCR JIO_32_RW +#define JN_DDRPHY_ACDLLCR DDRPHY_ACDLLCR +#define JI_DDRPHY_ACDLLCR + +#define REG_DDRPHY_PTR0 jz_reg(DDRPHY_PTR0) +#define JA_DDRPHY_PTR0 (0xb3011000 + 0x18) +#define JT_DDRPHY_PTR0 JIO_32_RW +#define JN_DDRPHY_PTR0 DDRPHY_PTR0 +#define JI_DDRPHY_PTR0 + +#define REG_DDRPHY_PTR1 jz_reg(DDRPHY_PTR1) +#define JA_DDRPHY_PTR1 (0xb3011000 + 0x1c) +#define JT_DDRPHY_PTR1 JIO_32_RW +#define JN_DDRPHY_PTR1 DDRPHY_PTR1 +#define JI_DDRPHY_PTR1 + +#define REG_DDRPHY_PTR2 jz_reg(DDRPHY_PTR2) +#define JA_DDRPHY_PTR2 (0xb3011000 + 0x20) +#define JT_DDRPHY_PTR2 JIO_32_RW +#define JN_DDRPHY_PTR2 DDRPHY_PTR2 +#define JI_DDRPHY_PTR2 + +#define REG_DDRPHY_ACIOCR jz_reg(DDRPHY_ACIOCR) +#define JA_DDRPHY_ACIOCR (0xb3011000 + 0x24) +#define JT_DDRPHY_ACIOCR JIO_32_RW +#define JN_DDRPHY_ACIOCR DDRPHY_ACIOCR +#define JI_DDRPHY_ACIOCR + +#define REG_DDRPHY_DXCCR jz_reg(DDRPHY_DXCCR) +#define JA_DDRPHY_DXCCR (0xb3011000 + 0x28) +#define JT_DDRPHY_DXCCR JIO_32_RW +#define JN_DDRPHY_DXCCR DDRPHY_DXCCR +#define JI_DDRPHY_DXCCR + +#define REG_DDRPHY_DSGCR jz_reg(DDRPHY_DSGCR) +#define JA_DDRPHY_DSGCR (0xb3011000 + 0x2c) +#define JT_DDRPHY_DSGCR JIO_32_RW +#define JN_DDRPHY_DSGCR DDRPHY_DSGCR +#define JI_DDRPHY_DSGCR + +#define REG_DDRPHY_DCR jz_reg(DDRPHY_DCR) +#define JA_DDRPHY_DCR (0xb3011000 + 0x30) +#define JT_DDRPHY_DCR JIO_32_RW +#define JN_DDRPHY_DCR DDRPHY_DCR +#define JI_DDRPHY_DCR + +#define REG_DDRPHY_DTPR0 jz_reg(DDRPHY_DTPR0) +#define JA_DDRPHY_DTPR0 (0xb3011000 + 0x34) +#define JT_DDRPHY_DTPR0 JIO_32_RW +#define JN_DDRPHY_DTPR0 DDRPHY_DTPR0 +#define JI_DDRPHY_DTPR0 + +#define REG_DDRPHY_DTPR1 jz_reg(DDRPHY_DTPR1) +#define JA_DDRPHY_DTPR1 (0xb3011000 + 0x38) +#define JT_DDRPHY_DTPR1 JIO_32_RW +#define JN_DDRPHY_DTPR1 DDRPHY_DTPR1 +#define JI_DDRPHY_DTPR1 + +#define REG_DDRPHY_DTPR2 jz_reg(DDRPHY_DTPR2) +#define JA_DDRPHY_DTPR2 (0xb3011000 + 0x3c) +#define JT_DDRPHY_DTPR2 JIO_32_RW +#define JN_DDRPHY_DTPR2 DDRPHY_DTPR2 +#define JI_DDRPHY_DTPR2 + +#define REG_DDRPHY_MR0 jz_reg(DDRPHY_MR0) +#define JA_DDRPHY_MR0 (0xb3011000 + 0x40) +#define JT_DDRPHY_MR0 JIO_32_RW +#define JN_DDRPHY_MR0 DDRPHY_MR0 +#define JI_DDRPHY_MR0 + +#define REG_DDRPHY_MR1 jz_reg(DDRPHY_MR1) +#define JA_DDRPHY_MR1 (0xb3011000 + 0x44) +#define JT_DDRPHY_MR1 JIO_32_RW +#define JN_DDRPHY_MR1 DDRPHY_MR1 +#define JI_DDRPHY_MR1 + +#define REG_DDRPHY_MR2 jz_reg(DDRPHY_MR2) +#define JA_DDRPHY_MR2 (0xb3011000 + 0x48) +#define JT_DDRPHY_MR2 JIO_32_RW +#define JN_DDRPHY_MR2 DDRPHY_MR2 +#define JI_DDRPHY_MR2 + +#define REG_DDRPHY_MR3 jz_reg(DDRPHY_MR3) +#define JA_DDRPHY_MR3 (0xb3011000 + 0x4c) +#define JT_DDRPHY_MR3 JIO_32_RW +#define JN_DDRPHY_MR3 DDRPHY_MR3 +#define JI_DDRPHY_MR3 + +#define REG_DDRPHY_DTAR jz_reg(DDRPHY_DTAR) +#define JA_DDRPHY_DTAR (0xb3011000 + 0x54) +#define JT_DDRPHY_DTAR JIO_32_RW +#define JN_DDRPHY_DTAR DDRPHY_DTAR +#define JI_DDRPHY_DTAR + +#define REG_DDRPHY_DXGCR(_n1) jz_reg(DDRPHY_DXGCR(_n1)) +#define JA_DDRPHY_DXGCR(_n1) (0xb3011000 + 0x1c0 + (_n1) * 0x40) +#define JT_DDRPHY_DXGCR(_n1) JIO_32_RW +#define JN_DDRPHY_DXGCR(_n1) DDRPHY_DXGCR +#define JI_DDRPHY_DXGCR(_n1) (_n1) + +#endif /* __HEADERGEN_DDRPHY_H__*/ diff --git a/firmware/target/mips/ingenic_x1000/x1000/dma.h b/firmware/target/mips/ingenic_x1000/x1000/dma.h new file mode 100644 index 0000000000..516c6e6849 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/x1000/dma.h @@ -0,0 +1,112 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * This file was automatically generated by headergen, DO NOT EDIT it. + * headergen version: 3.0.0 + * x1000 version: 1.0 + * x1000 authors: Aidan MacDonald + * + * Copyright (C) 2015 by the authors + * + * 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 __HEADERGEN_DMA_H__ +#define __HEADERGEN_DMA_H__ + +#include "macro.h" + +#define REG_DMA_CTRL jz_reg(DMA_CTRL) +#define JA_DMA_CTRL (0xb3421000 + 0x0) +#define JT_DMA_CTRL JIO_32_RW +#define JN_DMA_CTRL DMA_CTRL +#define JI_DMA_CTRL +#define BP_DMA_CTRL_FMSC 31 +#define BM_DMA_CTRL_FMSC 0x80000000 +#define BF_DMA_CTRL_FMSC(v) (((v) & 0x1) << 31) +#define BFM_DMA_CTRL_FMSC(v) BM_DMA_CTRL_FMSC +#define BF_DMA_CTRL_FMSC_V(e) BF_DMA_CTRL_FMSC(BV_DMA_CTRL_FMSC__##e) +#define BFM_DMA_CTRL_FMSC_V(v) BM_DMA_CTRL_FMSC +#define BP_DMA_CTRL_FSSI 30 +#define BM_DMA_CTRL_FSSI 0x40000000 +#define BF_DMA_CTRL_FSSI(v) (((v) & 0x1) << 30) +#define BFM_DMA_CTRL_FSSI(v) BM_DMA_CTRL_FSSI +#define BF_DMA_CTRL_FSSI_V(e) BF_DMA_CTRL_FSSI(BV_DMA_CTRL_FSSI__##e) +#define BFM_DMA_CTRL_FSSI_V(v) BM_DMA_CTRL_FSSI +#define BP_DMA_CTRL_FTSSI 29 +#define BM_DMA_CTRL_FTSSI 0x20000000 +#define BF_DMA_CTRL_FTSSI(v) (((v) & 0x1) << 29) +#define BFM_DMA_CTRL_FTSSI(v) BM_DMA_CTRL_FTSSI +#define BF_DMA_CTRL_FTSSI_V(e) BF_DMA_CTRL_FTSSI(BV_DMA_CTRL_FTSSI__##e) +#define BFM_DMA_CTRL_FTSSI_V(v) BM_DMA_CTRL_FTSSI +#define BP_DMA_CTRL_FUART 28 +#define BM_DMA_CTRL_FUART 0x10000000 +#define BF_DMA_CTRL_FUART(v) (((v) & 0x1) << 28) +#define BFM_DMA_CTRL_FUART(v) BM_DMA_CTRL_FUART +#define BF_DMA_CTRL_FUART_V(e) BF_DMA_CTRL_FUART(BV_DMA_CTRL_FUART__##e) +#define BFM_DMA_CTRL_FUART_V(v) BM_DMA_CTRL_FUART +#define BP_DMA_CTRL_FAIC 27 +#define BM_DMA_CTRL_FAIC 0x8000000 +#define BF_DMA_CTRL_FAIC(v) (((v) & 0x1) << 27) +#define BFM_DMA_CTRL_FAIC(v) BM_DMA_CTRL_FAIC +#define BF_DMA_CTRL_FAIC_V(e) BF_DMA_CTRL_FAIC(BV_DMA_CTRL_FAIC__##e) +#define BFM_DMA_CTRL_FAIC_V(v) BM_DMA_CTRL_FAIC +#define BP_DMA_CTRL_HALT 3 +#define BM_DMA_CTRL_HALT 0x8 +#define BF_DMA_CTRL_HALT(v) (((v) & 0x1) << 3) +#define BFM_DMA_CTRL_HALT(v) BM_DMA_CTRL_HALT +#define BF_DMA_CTRL_HALT_V(e) BF_DMA_CTRL_HALT(BV_DMA_CTRL_HALT__##e) +#define BFM_DMA_CTRL_HALT_V(v) BM_DMA_CTRL_HALT +#define BP_DMA_CTRL_AR 2 +#define BM_DMA_CTRL_AR 0x4 +#define BF_DMA_CTRL_AR(v) (((v) & 0x1) << 2) +#define BFM_DMA_CTRL_AR(v) BM_DMA_CTRL_AR +#define BF_DMA_CTRL_AR_V(e) BF_DMA_CTRL_AR(BV_DMA_CTRL_AR__##e) +#define BFM_DMA_CTRL_AR_V(v) BM_DMA_CTRL_AR +#define BP_DMA_CTRL_ENABLE 0 +#define BM_DMA_CTRL_ENABLE 0x1 +#define BF_DMA_CTRL_ENABLE(v) (((v) & 0x1) << 0) +#define BFM_DMA_CTRL_ENABLE(v) BM_DMA_CTRL_ENABLE +#define BF_DMA_CTRL_ENABLE_V(e) BF_DMA_CTRL_ENABLE(BV_DMA_CTRL_ENABLE__##e) +#define BFM_DMA_CTRL_ENABLE_V(v) BM_DMA_CTRL_ENABLE + +#define REG_DMA_IRQP jz_reg(DMA_IRQP) +#define JA_DMA_IRQP (0xb3421000 + 0x4) +#define JT_DMA_IRQP JIO_32_RW +#define JN_DMA_IRQP DMA_IRQP +#define JI_DMA_IRQP + +#define REG_DMA_DB jz_reg(DMA_DB) +#define JA_DMA_DB (0xb3421000 + 0x8) +#define JT_DMA_DB JIO_32_RW +#define JN_DMA_DB DMA_DB +#define JI_DMA_DB +#define REG_DMA_DB_SET jz_reg(DMA_DB_SET) +#define JA_DMA_DB_SET (JA_DMA_DB + 0x4) +#define JT_DMA_DB_SET JIO_32_WO +#define JN_DMA_DB_SET DMA_DB +#define JI_DMA_DB_SET + +#define REG_DMA_DIP jz_reg(DMA_DIP) +#define JA_DMA_DIP (0xb3421000 + 0x10) +#define JT_DMA_DIP JIO_32_RW +#define JN_DMA_DIP DMA_DIP +#define JI_DMA_DIP + +#define REG_DMA_DIC jz_reg(DMA_DIC) +#define JA_DMA_DIC (0xb3421000 + 0x14) +#define JT_DMA_DIC JIO_32_RW +#define JN_DMA_DIC DMA_DIC +#define JI_DMA_DIC + +#endif /* __HEADERGEN_DMA_H__*/ diff --git a/firmware/target/mips/ingenic_x1000/x1000/dma_chn.h b/firmware/target/mips/ingenic_x1000/x1000/dma_chn.h new file mode 100644 index 0000000000..56eb2a8cc1 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/x1000/dma_chn.h @@ -0,0 +1,253 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * This file was automatically generated by headergen, DO NOT EDIT it. + * headergen version: 3.0.0 + * x1000 version: 1.0 + * x1000 authors: Aidan MacDonald + * + * Copyright (C) 2015 by the authors + * + * 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 __HEADERGEN_DMA_CHN_H__ +#define __HEADERGEN_DMA_CHN_H__ + +#include "macro.h" + +#define REG_DMA_CHN_SA(_n1) jz_reg(DMA_CHN_SA(_n1)) +#define JA_DMA_CHN_SA(_n1) (0xb3420000 + (_n1) * 0x20 + 0x0) +#define JT_DMA_CHN_SA(_n1) JIO_32_RW +#define JN_DMA_CHN_SA(_n1) DMA_CHN_SA +#define JI_DMA_CHN_SA(_n1) (_n1) + +#define REG_DMA_CHN_TA(_n1) jz_reg(DMA_CHN_TA(_n1)) +#define JA_DMA_CHN_TA(_n1) (0xb3420000 + (_n1) * 0x20 + 0x4) +#define JT_DMA_CHN_TA(_n1) JIO_32_RW +#define JN_DMA_CHN_TA(_n1) DMA_CHN_TA +#define JI_DMA_CHN_TA(_n1) (_n1) + +#define REG_DMA_CHN_TC(_n1) jz_reg(DMA_CHN_TC(_n1)) +#define JA_DMA_CHN_TC(_n1) (0xb3420000 + (_n1) * 0x20 + 0x8) +#define JT_DMA_CHN_TC(_n1) JIO_32_RW +#define JN_DMA_CHN_TC(_n1) DMA_CHN_TC +#define JI_DMA_CHN_TC(_n1) (_n1) +#define BP_DMA_CHN_TC_DOA 24 +#define BM_DMA_CHN_TC_DOA 0xff000000 +#define BF_DMA_CHN_TC_DOA(v) (((v) & 0xff) << 24) +#define BFM_DMA_CHN_TC_DOA(v) BM_DMA_CHN_TC_DOA +#define BF_DMA_CHN_TC_DOA_V(e) BF_DMA_CHN_TC_DOA(BV_DMA_CHN_TC_DOA__##e) +#define BFM_DMA_CHN_TC_DOA_V(v) BM_DMA_CHN_TC_DOA +#define BP_DMA_CHN_TC_CNT 0 +#define BM_DMA_CHN_TC_CNT 0xffffff +#define BF_DMA_CHN_TC_CNT(v) (((v) & 0xffffff) << 0) +#define BFM_DMA_CHN_TC_CNT(v) BM_DMA_CHN_TC_CNT +#define BF_DMA_CHN_TC_CNT_V(e) BF_DMA_CHN_TC_CNT(BV_DMA_CHN_TC_CNT__##e) +#define BFM_DMA_CHN_TC_CNT_V(v) BM_DMA_CHN_TC_CNT + +#define REG_DMA_CHN_RT(_n1) jz_reg(DMA_CHN_RT(_n1)) +#define JA_DMA_CHN_RT(_n1) (0xb3420000 + (_n1) * 0x20 + 0xc) +#define JT_DMA_CHN_RT(_n1) JIO_32_RW +#define JN_DMA_CHN_RT(_n1) DMA_CHN_RT +#define JI_DMA_CHN_RT(_n1) (_n1) +#define BP_DMA_CHN_RT_TYPE 0 +#define BM_DMA_CHN_RT_TYPE 0x3f +#define BV_DMA_CHN_RT_TYPE__DMIC_RX 0x5 +#define BV_DMA_CHN_RT_TYPE__I2S_TX 0x6 +#define BV_DMA_CHN_RT_TYPE__I2S_RX 0x7 +#define BV_DMA_CHN_RT_TYPE__AUTO 0x8 +#define BV_DMA_CHN_RT_TYPE__UART2_TX 0x10 +#define BV_DMA_CHN_RT_TYPE__UART2_RX 0x11 +#define BV_DMA_CHN_RT_TYPE__UART1_TX 0x12 +#define BV_DMA_CHN_RT_TYPE__UART1_RX 0x13 +#define BV_DMA_CHN_RT_TYPE__UART0_TX 0x14 +#define BV_DMA_CHN_RT_TYPE__UART0_RX 0x15 +#define BV_DMA_CHN_RT_TYPE__SSI_TX 0x16 +#define BV_DMA_CHN_RT_TYPE__SSI_RX 0x17 +#define BV_DMA_CHN_RT_TYPE__MSC0_TX 0x1a +#define BV_DMA_CHN_RT_TYPE__MSC0_RX 0x1b +#define BV_DMA_CHN_RT_TYPE__MSC1_TX 0x1c +#define BV_DMA_CHN_RT_TYPE__MSC1_RX 0x1d +#define BV_DMA_CHN_RT_TYPE__PCM_TX 0x20 +#define BV_DMA_CHN_RT_TYPE__PCM_RX 0x21 +#define BV_DMA_CHN_RT_TYPE__I2C0_TX 0x24 +#define BV_DMA_CHN_RT_TYPE__I2C0_RX 0x25 +#define BV_DMA_CHN_RT_TYPE__I2C1_TX 0x26 +#define BV_DMA_CHN_RT_TYPE__I2C1_RX 0x27 +#define BV_DMA_CHN_RT_TYPE__I2C2_TX 0x28 +#define BV_DMA_CHN_RT_TYPE__I2C2_RX 0x29 +#define BF_DMA_CHN_RT_TYPE(v) (((v) & 0x3f) << 0) +#define BFM_DMA_CHN_RT_TYPE(v) BM_DMA_CHN_RT_TYPE +#define BF_DMA_CHN_RT_TYPE_V(e) BF_DMA_CHN_RT_TYPE(BV_DMA_CHN_RT_TYPE__##e) +#define BFM_DMA_CHN_RT_TYPE_V(v) BM_DMA_CHN_RT_TYPE + +#define REG_DMA_CHN_CS(_n1) jz_reg(DMA_CHN_CS(_n1)) +#define JA_DMA_CHN_CS(_n1) (0xb3420000 + (_n1) * 0x20 + 0x10) +#define JT_DMA_CHN_CS(_n1) JIO_32_RW +#define JN_DMA_CHN_CS(_n1) DMA_CHN_CS +#define JI_DMA_CHN_CS(_n1) (_n1) +#define BP_DMA_CHN_CS_CDOA 8 +#define BM_DMA_CHN_CS_CDOA 0xff00 +#define BF_DMA_CHN_CS_CDOA(v) (((v) & 0xff) << 8) +#define BFM_DMA_CHN_CS_CDOA(v) BM_DMA_CHN_CS_CDOA +#define BF_DMA_CHN_CS_CDOA_V(e) BF_DMA_CHN_CS_CDOA(BV_DMA_CHN_CS_CDOA__##e) +#define BFM_DMA_CHN_CS_CDOA_V(v) BM_DMA_CHN_CS_CDOA +#define BP_DMA_CHN_CS_NDES 31 +#define BM_DMA_CHN_CS_NDES 0x80000000 +#define BF_DMA_CHN_CS_NDES(v) (((v) & 0x1) << 31) +#define BFM_DMA_CHN_CS_NDES(v) BM_DMA_CHN_CS_NDES +#define BF_DMA_CHN_CS_NDES_V(e) BF_DMA_CHN_CS_NDES(BV_DMA_CHN_CS_NDES__##e) +#define BFM_DMA_CHN_CS_NDES_V(v) BM_DMA_CHN_CS_NDES +#define BP_DMA_CHN_CS_DES8 30 +#define BM_DMA_CHN_CS_DES8 0x40000000 +#define BF_DMA_CHN_CS_DES8(v) (((v) & 0x1) << 30) +#define BFM_DMA_CHN_CS_DES8(v) BM_DMA_CHN_CS_DES8 +#define BF_DMA_CHN_CS_DES8_V(e) BF_DMA_CHN_CS_DES8(BV_DMA_CHN_CS_DES8__##e) +#define BFM_DMA_CHN_CS_DES8_V(v) BM_DMA_CHN_CS_DES8 +#define BP_DMA_CHN_CS_AR 4 +#define BM_DMA_CHN_CS_AR 0x10 +#define BF_DMA_CHN_CS_AR(v) (((v) & 0x1) << 4) +#define BFM_DMA_CHN_CS_AR(v) BM_DMA_CHN_CS_AR +#define BF_DMA_CHN_CS_AR_V(e) BF_DMA_CHN_CS_AR(BV_DMA_CHN_CS_AR__##e) +#define BFM_DMA_CHN_CS_AR_V(v) BM_DMA_CHN_CS_AR +#define BP_DMA_CHN_CS_TT 3 +#define BM_DMA_CHN_CS_TT 0x8 +#define BF_DMA_CHN_CS_TT(v) (((v) & 0x1) << 3) +#define BFM_DMA_CHN_CS_TT(v) BM_DMA_CHN_CS_TT +#define BF_DMA_CHN_CS_TT_V(e) BF_DMA_CHN_CS_TT(BV_DMA_CHN_CS_TT__##e) +#define BFM_DMA_CHN_CS_TT_V(v) BM_DMA_CHN_CS_TT +#define BP_DMA_CHN_CS_HLT 2 +#define BM_DMA_CHN_CS_HLT 0x4 +#define BF_DMA_CHN_CS_HLT(v) (((v) & 0x1) << 2) +#define BFM_DMA_CHN_CS_HLT(v) BM_DMA_CHN_CS_HLT +#define BF_DMA_CHN_CS_HLT_V(e) BF_DMA_CHN_CS_HLT(BV_DMA_CHN_CS_HLT__##e) +#define BFM_DMA_CHN_CS_HLT_V(v) BM_DMA_CHN_CS_HLT +#define BP_DMA_CHN_CS_CTE 0 +#define BM_DMA_CHN_CS_CTE 0x1 +#define BF_DMA_CHN_CS_CTE(v) (((v) & 0x1) << 0) +#define BFM_DMA_CHN_CS_CTE(v) BM_DMA_CHN_CS_CTE +#define BF_DMA_CHN_CS_CTE_V(e) BF_DMA_CHN_CS_CTE(BV_DMA_CHN_CS_CTE__##e) +#define BFM_DMA_CHN_CS_CTE_V(v) BM_DMA_CHN_CS_CTE + +#define REG_DMA_CHN_CM(_n1) jz_reg(DMA_CHN_CM(_n1)) +#define JA_DMA_CHN_CM(_n1) (0xb3420000 + (_n1) * 0x20 + 0x14) +#define JT_DMA_CHN_CM(_n1) JIO_32_RW +#define JN_DMA_CHN_CM(_n1) DMA_CHN_CM +#define JI_DMA_CHN_CM(_n1) (_n1) +#define BP_DMA_CHN_CM_RDIL 16 +#define BM_DMA_CHN_CM_RDIL 0xf0000 +#define BF_DMA_CHN_CM_RDIL(v) (((v) & 0xf) << 16) +#define BFM_DMA_CHN_CM_RDIL(v) BM_DMA_CHN_CM_RDIL +#define BF_DMA_CHN_CM_RDIL_V(e) BF_DMA_CHN_CM_RDIL(BV_DMA_CHN_CM_RDIL__##e) +#define BFM_DMA_CHN_CM_RDIL_V(v) BM_DMA_CHN_CM_RDIL +#define BP_DMA_CHN_CM_SP 14 +#define BM_DMA_CHN_CM_SP 0xc000 +#define BV_DMA_CHN_CM_SP__32BIT 0x0 +#define BV_DMA_CHN_CM_SP__8BIT 0x1 +#define BV_DMA_CHN_CM_SP__16BIT 0x2 +#define BF_DMA_CHN_CM_SP(v) (((v) & 0x3) << 14) +#define BFM_DMA_CHN_CM_SP(v) BM_DMA_CHN_CM_SP +#define BF_DMA_CHN_CM_SP_V(e) BF_DMA_CHN_CM_SP(BV_DMA_CHN_CM_SP__##e) +#define BFM_DMA_CHN_CM_SP_V(v) BM_DMA_CHN_CM_SP +#define BP_DMA_CHN_CM_DP 12 +#define BM_DMA_CHN_CM_DP 0x3000 +#define BV_DMA_CHN_CM_DP__32BIT 0x0 +#define BV_DMA_CHN_CM_DP__8BIT 0x1 +#define BV_DMA_CHN_CM_DP__16BIT 0x2 +#define BF_DMA_CHN_CM_DP(v) (((v) & 0x3) << 12) +#define BFM_DMA_CHN_CM_DP(v) BM_DMA_CHN_CM_DP +#define BF_DMA_CHN_CM_DP_V(e) BF_DMA_CHN_CM_DP(BV_DMA_CHN_CM_DP__##e) +#define BFM_DMA_CHN_CM_DP_V(v) BM_DMA_CHN_CM_DP +#define BP_DMA_CHN_CM_TSZ 8 +#define BM_DMA_CHN_CM_TSZ 0x700 +#define BV_DMA_CHN_CM_TSZ__32BIT 0x0 +#define BV_DMA_CHN_CM_TSZ__8BIT 0x1 +#define BV_DMA_CHN_CM_TSZ__16BIT 0x2 +#define BV_DMA_CHN_CM_TSZ__16BYTE 0x3 +#define BV_DMA_CHN_CM_TSZ__32BYTE 0x4 +#define BV_DMA_CHN_CM_TSZ__64BYTE 0x5 +#define BV_DMA_CHN_CM_TSZ__128BYTE 0x6 +#define BV_DMA_CHN_CM_TSZ__AUTO 0x7 +#define BF_DMA_CHN_CM_TSZ(v) (((v) & 0x7) << 8) +#define BFM_DMA_CHN_CM_TSZ(v) BM_DMA_CHN_CM_TSZ +#define BF_DMA_CHN_CM_TSZ_V(e) BF_DMA_CHN_CM_TSZ(BV_DMA_CHN_CM_TSZ__##e) +#define BFM_DMA_CHN_CM_TSZ_V(v) BM_DMA_CHN_CM_TSZ +#define BP_DMA_CHN_CM_SAI 23 +#define BM_DMA_CHN_CM_SAI 0x800000 +#define BF_DMA_CHN_CM_SAI(v) (((v) & 0x1) << 23) +#define BFM_DMA_CHN_CM_SAI(v) BM_DMA_CHN_CM_SAI +#define BF_DMA_CHN_CM_SAI_V(e) BF_DMA_CHN_CM_SAI(BV_DMA_CHN_CM_SAI__##e) +#define BFM_DMA_CHN_CM_SAI_V(v) BM_DMA_CHN_CM_SAI +#define BP_DMA_CHN_CM_DAI 22 +#define BM_DMA_CHN_CM_DAI 0x400000 +#define BF_DMA_CHN_CM_DAI(v) (((v) & 0x1) << 22) +#define BFM_DMA_CHN_CM_DAI(v) BM_DMA_CHN_CM_DAI +#define BF_DMA_CHN_CM_DAI_V(e) BF_DMA_CHN_CM_DAI(BV_DMA_CHN_CM_DAI__##e) +#define BFM_DMA_CHN_CM_DAI_V(v) BM_DMA_CHN_CM_DAI +#define BP_DMA_CHN_CM_STDE 2 +#define BM_DMA_CHN_CM_STDE 0x4 +#define BF_DMA_CHN_CM_STDE(v) (((v) & 0x1) << 2) +#define BFM_DMA_CHN_CM_STDE(v) BM_DMA_CHN_CM_STDE +#define BF_DMA_CHN_CM_STDE_V(e) BF_DMA_CHN_CM_STDE(BV_DMA_CHN_CM_STDE__##e) +#define BFM_DMA_CHN_CM_STDE_V(v) BM_DMA_CHN_CM_STDE +#define BP_DMA_CHN_CM_TIE 1 +#define BM_DMA_CHN_CM_TIE 0x2 +#define BF_DMA_CHN_CM_TIE(v) (((v) & 0x1) << 1) +#define BFM_DMA_CHN_CM_TIE(v) BM_DMA_CHN_CM_TIE +#define BF_DMA_CHN_CM_TIE_V(e) BF_DMA_CHN_CM_TIE(BV_DMA_CHN_CM_TIE__##e) +#define BFM_DMA_CHN_CM_TIE_V(v) BM_DMA_CHN_CM_TIE +#define BP_DMA_CHN_CM_LINK 0 +#define BM_DMA_CHN_CM_LINK 0x1 +#define BF_DMA_CHN_CM_LINK(v) (((v) & 0x1) << 0) +#define BFM_DMA_CHN_CM_LINK(v) BM_DMA_CHN_CM_LINK +#define BF_DMA_CHN_CM_LINK_V(e) BF_DMA_CHN_CM_LINK(BV_DMA_CHN_CM_LINK__##e) +#define BFM_DMA_CHN_CM_LINK_V(v) BM_DMA_CHN_CM_LINK + +#define REG_DMA_CHN_DA(_n1) jz_reg(DMA_CHN_DA(_n1)) +#define JA_DMA_CHN_DA(_n1) (0xb3420000 + (_n1) * 0x20 + 0x18) +#define JT_DMA_CHN_DA(_n1) JIO_32_RW +#define JN_DMA_CHN_DA(_n1) DMA_CHN_DA +#define JI_DMA_CHN_DA(_n1) (_n1) +#define BP_DMA_CHN_DA_DBA 12 +#define BM_DMA_CHN_DA_DBA 0xfffff000 +#define BF_DMA_CHN_DA_DBA(v) (((v) & 0xfffff) << 12) +#define BFM_DMA_CHN_DA_DBA(v) BM_DMA_CHN_DA_DBA +#define BF_DMA_CHN_DA_DBA_V(e) BF_DMA_CHN_DA_DBA(BV_DMA_CHN_DA_DBA__##e) +#define BFM_DMA_CHN_DA_DBA_V(v) BM_DMA_CHN_DA_DBA +#define BP_DMA_CHN_DA_DOA 4 +#define BM_DMA_CHN_DA_DOA 0xff0 +#define BF_DMA_CHN_DA_DOA(v) (((v) & 0xff) << 4) +#define BFM_DMA_CHN_DA_DOA(v) BM_DMA_CHN_DA_DOA +#define BF_DMA_CHN_DA_DOA_V(e) BF_DMA_CHN_DA_DOA(BV_DMA_CHN_DA_DOA__##e) +#define BFM_DMA_CHN_DA_DOA_V(v) BM_DMA_CHN_DA_DOA + +#define REG_DMA_CHN_SD(_n1) jz_reg(DMA_CHN_SD(_n1)) +#define JA_DMA_CHN_SD(_n1) (0xb3420000 + (_n1) * 0x20 + 0x1c) +#define JT_DMA_CHN_SD(_n1) JIO_32_RW +#define JN_DMA_CHN_SD(_n1) DMA_CHN_SD +#define JI_DMA_CHN_SD(_n1) (_n1) +#define BP_DMA_CHN_SD_TSD 16 +#define BM_DMA_CHN_SD_TSD 0xffff0000 +#define BF_DMA_CHN_SD_TSD(v) (((v) & 0xffff) << 16) +#define BFM_DMA_CHN_SD_TSD(v) BM_DMA_CHN_SD_TSD +#define BF_DMA_CHN_SD_TSD_V(e) BF_DMA_CHN_SD_TSD(BV_DMA_CHN_SD_TSD__##e) +#define BFM_DMA_CHN_SD_TSD_V(v) BM_DMA_CHN_SD_TSD +#define BP_DMA_CHN_SD_SSD 0 +#define BM_DMA_CHN_SD_SSD 0xffff +#define BF_DMA_CHN_SD_SSD(v) (((v) & 0xffff) << 0) +#define BFM_DMA_CHN_SD_SSD(v) BM_DMA_CHN_SD_SSD +#define BF_DMA_CHN_SD_SSD_V(e) BF_DMA_CHN_SD_SSD(BV_DMA_CHN_SD_SSD__##e) +#define BFM_DMA_CHN_SD_SSD_V(v) BM_DMA_CHN_SD_SSD + +#endif /* __HEADERGEN_DMA_CHN_H__*/ diff --git a/firmware/target/mips/ingenic_x1000/x1000/gpio.h b/firmware/target/mips/ingenic_x1000/x1000/gpio.h new file mode 100644 index 0000000000..6bba343cf6 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/x1000/gpio.h @@ -0,0 +1,196 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * This file was automatically generated by headergen, DO NOT EDIT it. + * headergen version: 3.0.0 + * x1000 version: 1.0 + * x1000 authors: Aidan MacDonald + * + * Copyright (C) 2015 by the authors + * + * 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 __HEADERGEN_GPIO_H__ +#define __HEADERGEN_GPIO_H__ + +#include "macro.h" + +#define REG_GPIO_C_GLITCH_CFG0 jz_reg(GPIO_C_GLITCH_CFG0) +#define JA_GPIO_C_GLITCH_CFG0 (0xb0010000 + 0x200 + 0x800) +#define JT_GPIO_C_GLITCH_CFG0 JIO_32_RW +#define JN_GPIO_C_GLITCH_CFG0 GPIO_C_GLITCH_CFG0 +#define JI_GPIO_C_GLITCH_CFG0 +#define REG_GPIO_C_GLITCH_CFG0_SET jz_reg(GPIO_C_GLITCH_CFG0_SET) +#define JA_GPIO_C_GLITCH_CFG0_SET (JA_GPIO_C_GLITCH_CFG0 + 0x4) +#define JT_GPIO_C_GLITCH_CFG0_SET JIO_32_WO +#define JN_GPIO_C_GLITCH_CFG0_SET GPIO_C_GLITCH_CFG0 +#define JI_GPIO_C_GLITCH_CFG0_SET +#define REG_GPIO_C_GLITCH_CFG0_CLR jz_reg(GPIO_C_GLITCH_CFG0_CLR) +#define JA_GPIO_C_GLITCH_CFG0_CLR (JA_GPIO_C_GLITCH_CFG0 + 0x8) +#define JT_GPIO_C_GLITCH_CFG0_CLR JIO_32_WO +#define JN_GPIO_C_GLITCH_CFG0_CLR GPIO_C_GLITCH_CFG0 +#define JI_GPIO_C_GLITCH_CFG0_CLR + +#define REG_GPIO_C_GLITCH_CFG1 jz_reg(GPIO_C_GLITCH_CFG1) +#define JA_GPIO_C_GLITCH_CFG1 (0xb0010000 + 0x200 + 0x810) +#define JT_GPIO_C_GLITCH_CFG1 JIO_32_RW +#define JN_GPIO_C_GLITCH_CFG1 GPIO_C_GLITCH_CFG1 +#define JI_GPIO_C_GLITCH_CFG1 +#define REG_GPIO_C_GLITCH_CFG1_SET jz_reg(GPIO_C_GLITCH_CFG1_SET) +#define JA_GPIO_C_GLITCH_CFG1_SET (JA_GPIO_C_GLITCH_CFG1 + 0x4) +#define JT_GPIO_C_GLITCH_CFG1_SET JIO_32_WO +#define JN_GPIO_C_GLITCH_CFG1_SET GPIO_C_GLITCH_CFG1 +#define JI_GPIO_C_GLITCH_CFG1_SET +#define REG_GPIO_C_GLITCH_CFG1_CLR jz_reg(GPIO_C_GLITCH_CFG1_CLR) +#define JA_GPIO_C_GLITCH_CFG1_CLR (JA_GPIO_C_GLITCH_CFG1 + 0x8) +#define JT_GPIO_C_GLITCH_CFG1_CLR JIO_32_WO +#define JN_GPIO_C_GLITCH_CFG1_CLR GPIO_C_GLITCH_CFG1 +#define JI_GPIO_C_GLITCH_CFG1_CLR + +#define REG_GPIO_C_GLITCH_CFG2 jz_reg(GPIO_C_GLITCH_CFG2) +#define JA_GPIO_C_GLITCH_CFG2 (0xb0010000 + 0x200 + 0x820) +#define JT_GPIO_C_GLITCH_CFG2 JIO_32_RW +#define JN_GPIO_C_GLITCH_CFG2 GPIO_C_GLITCH_CFG2 +#define JI_GPIO_C_GLITCH_CFG2 +#define REG_GPIO_C_GLITCH_CFG2_SET jz_reg(GPIO_C_GLITCH_CFG2_SET) +#define JA_GPIO_C_GLITCH_CFG2_SET (JA_GPIO_C_GLITCH_CFG2 + 0x4) +#define JT_GPIO_C_GLITCH_CFG2_SET JIO_32_WO +#define JN_GPIO_C_GLITCH_CFG2_SET GPIO_C_GLITCH_CFG2 +#define JI_GPIO_C_GLITCH_CFG2_SET +#define REG_GPIO_C_GLITCH_CFG2_CLR jz_reg(GPIO_C_GLITCH_CFG2_CLR) +#define JA_GPIO_C_GLITCH_CFG2_CLR (JA_GPIO_C_GLITCH_CFG2 + 0x8) +#define JT_GPIO_C_GLITCH_CFG2_CLR JIO_32_WO +#define JN_GPIO_C_GLITCH_CFG2_CLR GPIO_C_GLITCH_CFG2 +#define JI_GPIO_C_GLITCH_CFG2_CLR + +#define REG_GPIO_C_GLITCH_CFG3 jz_reg(GPIO_C_GLITCH_CFG3) +#define JA_GPIO_C_GLITCH_CFG3 (0xb0010000 + 0x200 + 0x830) +#define JT_GPIO_C_GLITCH_CFG3 JIO_32_RW +#define JN_GPIO_C_GLITCH_CFG3 GPIO_C_GLITCH_CFG3 +#define JI_GPIO_C_GLITCH_CFG3 +#define REG_GPIO_C_GLITCH_CFG3_SET jz_reg(GPIO_C_GLITCH_CFG3_SET) +#define JA_GPIO_C_GLITCH_CFG3_SET (JA_GPIO_C_GLITCH_CFG3 + 0x4) +#define JT_GPIO_C_GLITCH_CFG3_SET JIO_32_WO +#define JN_GPIO_C_GLITCH_CFG3_SET GPIO_C_GLITCH_CFG3 +#define JI_GPIO_C_GLITCH_CFG3_SET +#define REG_GPIO_C_GLITCH_CFG3_CLR jz_reg(GPIO_C_GLITCH_CFG3_CLR) +#define JA_GPIO_C_GLITCH_CFG3_CLR (JA_GPIO_C_GLITCH_CFG3 + 0x8) +#define JT_GPIO_C_GLITCH_CFG3_CLR JIO_32_WO +#define JN_GPIO_C_GLITCH_CFG3_CLR GPIO_C_GLITCH_CFG3 +#define JI_GPIO_C_GLITCH_CFG3_CLR + +#define REG_GPIO_PIN(_n1) jz_reg(GPIO_PIN(_n1)) +#define JA_GPIO_PIN(_n1) (0xb0010000 + 0x0 + (_n1) * 0x100) +#define JT_GPIO_PIN(_n1) JIO_32_RW +#define JN_GPIO_PIN(_n1) GPIO_PIN +#define JI_GPIO_PIN(_n1) (_n1) + +#define REG_GPIO_INT(_n1) jz_reg(GPIO_INT(_n1)) +#define JA_GPIO_INT(_n1) (0xb0010000 + 0x10 + (_n1) * 0x100) +#define JT_GPIO_INT(_n1) JIO_32_RW +#define JN_GPIO_INT(_n1) GPIO_INT +#define JI_GPIO_INT(_n1) (_n1) +#define REG_GPIO_INT_SET(_n1) jz_reg(GPIO_INT_SET(_n1)) +#define JA_GPIO_INT_SET(_n1) (JA_GPIO_INT(_n1) + 0x4) +#define JT_GPIO_INT_SET(_n1) JIO_32_WO +#define JN_GPIO_INT_SET(_n1) GPIO_INT +#define JI_GPIO_INT_SET(_n1) (_n1) +#define REG_GPIO_INT_CLR(_n1) jz_reg(GPIO_INT_CLR(_n1)) +#define JA_GPIO_INT_CLR(_n1) (JA_GPIO_INT(_n1) + 0x8) +#define JT_GPIO_INT_CLR(_n1) JIO_32_WO +#define JN_GPIO_INT_CLR(_n1) GPIO_INT +#define JI_GPIO_INT_CLR(_n1) (_n1) + +#define REG_GPIO_MSK(_n1) jz_reg(GPIO_MSK(_n1)) +#define JA_GPIO_MSK(_n1) (0xb0010000 + 0x20 + (_n1) * 0x100) +#define JT_GPIO_MSK(_n1) JIO_32_RW +#define JN_GPIO_MSK(_n1) GPIO_MSK +#define JI_GPIO_MSK(_n1) (_n1) +#define REG_GPIO_MSK_SET(_n1) jz_reg(GPIO_MSK_SET(_n1)) +#define JA_GPIO_MSK_SET(_n1) (JA_GPIO_MSK(_n1) + 0x4) +#define JT_GPIO_MSK_SET(_n1) JIO_32_WO +#define JN_GPIO_MSK_SET(_n1) GPIO_MSK +#define JI_GPIO_MSK_SET(_n1) (_n1) +#define REG_GPIO_MSK_CLR(_n1) jz_reg(GPIO_MSK_CLR(_n1)) +#define JA_GPIO_MSK_CLR(_n1) (JA_GPIO_MSK(_n1) + 0x8) +#define JT_GPIO_MSK_CLR(_n1) JIO_32_WO +#define JN_GPIO_MSK_CLR(_n1) GPIO_MSK +#define JI_GPIO_MSK_CLR(_n1) (_n1) + +#define REG_GPIO_PAT1(_n1) jz_reg(GPIO_PAT1(_n1)) +#define JA_GPIO_PAT1(_n1) (0xb0010000 + 0x30 + (_n1) * 0x100) +#define JT_GPIO_PAT1(_n1) JIO_32_RW +#define JN_GPIO_PAT1(_n1) GPIO_PAT1 +#define JI_GPIO_PAT1(_n1) (_n1) +#define REG_GPIO_PAT1_SET(_n1) jz_reg(GPIO_PAT1_SET(_n1)) +#define JA_GPIO_PAT1_SET(_n1) (JA_GPIO_PAT1(_n1) + 0x4) +#define JT_GPIO_PAT1_SET(_n1) JIO_32_WO +#define JN_GPIO_PAT1_SET(_n1) GPIO_PAT1 +#define JI_GPIO_PAT1_SET(_n1) (_n1) +#define REG_GPIO_PAT1_CLR(_n1) jz_reg(GPIO_PAT1_CLR(_n1)) +#define JA_GPIO_PAT1_CLR(_n1) (JA_GPIO_PAT1(_n1) + 0x8) +#define JT_GPIO_PAT1_CLR(_n1) JIO_32_WO +#define JN_GPIO_PAT1_CLR(_n1) GPIO_PAT1 +#define JI_GPIO_PAT1_CLR(_n1) (_n1) + +#define REG_GPIO_PAT0(_n1) jz_reg(GPIO_PAT0(_n1)) +#define JA_GPIO_PAT0(_n1) (0xb0010000 + 0x40 + (_n1) * 0x100) +#define JT_GPIO_PAT0(_n1) JIO_32_RW +#define JN_GPIO_PAT0(_n1) GPIO_PAT0 +#define JI_GPIO_PAT0(_n1) (_n1) +#define REG_GPIO_PAT0_SET(_n1) jz_reg(GPIO_PAT0_SET(_n1)) +#define JA_GPIO_PAT0_SET(_n1) (JA_GPIO_PAT0(_n1) + 0x4) +#define JT_GPIO_PAT0_SET(_n1) JIO_32_WO +#define JN_GPIO_PAT0_SET(_n1) GPIO_PAT0 +#define JI_GPIO_PAT0_SET(_n1) (_n1) +#define REG_GPIO_PAT0_CLR(_n1) jz_reg(GPIO_PAT0_CLR(_n1)) +#define JA_GPIO_PAT0_CLR(_n1) (JA_GPIO_PAT0(_n1) + 0x8) +#define JT_GPIO_PAT0_CLR(_n1) JIO_32_WO +#define JN_GPIO_PAT0_CLR(_n1) GPIO_PAT0 +#define JI_GPIO_PAT0_CLR(_n1) (_n1) + +#define REG_GPIO_FLAG(_n1) jz_reg(GPIO_FLAG(_n1)) +#define JA_GPIO_FLAG(_n1) (0xb0010000 + 0x50 + (_n1) * 0x100) +#define JT_GPIO_FLAG(_n1) JIO_32_RW +#define JN_GPIO_FLAG(_n1) GPIO_FLAG +#define JI_GPIO_FLAG(_n1) (_n1) +#define REG_GPIO_FLAG_CLR(_n1) jz_reg(GPIO_FLAG_CLR(_n1)) +#define JA_GPIO_FLAG_CLR(_n1) (JA_GPIO_FLAG(_n1) + 0x8) +#define JT_GPIO_FLAG_CLR(_n1) JIO_32_WO +#define JN_GPIO_FLAG_CLR(_n1) GPIO_FLAG +#define JI_GPIO_FLAG_CLR(_n1) (_n1) + +#define REG_GPIO_PULL(_n1) jz_reg(GPIO_PULL(_n1)) +#define JA_GPIO_PULL(_n1) (0xb0010000 + 0x70 + (_n1) * 0x100) +#define JT_GPIO_PULL(_n1) JIO_32_RW +#define JN_GPIO_PULL(_n1) GPIO_PULL +#define JI_GPIO_PULL(_n1) (_n1) +#define REG_GPIO_PULL_SET(_n1) jz_reg(GPIO_PULL_SET(_n1)) +#define JA_GPIO_PULL_SET(_n1) (JA_GPIO_PULL(_n1) + 0x4) +#define JT_GPIO_PULL_SET(_n1) JIO_32_WO +#define JN_GPIO_PULL_SET(_n1) GPIO_PULL +#define JI_GPIO_PULL_SET(_n1) (_n1) +#define REG_GPIO_PULL_CLR(_n1) jz_reg(GPIO_PULL_CLR(_n1)) +#define JA_GPIO_PULL_CLR(_n1) (JA_GPIO_PULL(_n1) + 0x8) +#define JT_GPIO_PULL_CLR(_n1) JIO_32_WO +#define JN_GPIO_PULL_CLR(_n1) GPIO_PULL +#define JI_GPIO_PULL_CLR(_n1) (_n1) + +#define REG_GPIO_Z_GID2LD jz_reg(GPIO_Z_GID2LD) +#define JA_GPIO_Z_GID2LD (0xb0010000 + 0x7f0) +#define JT_GPIO_Z_GID2LD JIO_32_RW +#define JN_GPIO_Z_GID2LD GPIO_Z_GID2LD +#define JI_GPIO_Z_GID2LD + +#endif /* __HEADERGEN_GPIO_H__*/ diff --git a/firmware/target/mips/ingenic_x1000/x1000/i2c.h b/firmware/target/mips/ingenic_x1000/x1000/i2c.h new file mode 100644 index 0000000000..29f24bf82e --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/x1000/i2c.h @@ -0,0 +1,625 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * This file was automatically generated by headergen, DO NOT EDIT it. + * headergen version: 3.0.0 + * x1000 version: 1.0 + * x1000 authors: Aidan MacDonald + * + * Copyright (C) 2015 by the authors + * + * 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 __HEADERGEN_I2C_H__ +#define __HEADERGEN_I2C_H__ + +#include "macro.h" + +#define REG_I2C_CON(_n1) jz_reg(I2C_CON(_n1)) +#define JA_I2C_CON(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x0) +#define JT_I2C_CON(_n1) JIO_32_RW +#define JN_I2C_CON(_n1) I2C_CON +#define JI_I2C_CON(_n1) (_n1) +#define BP_I2C_CON_SPEED 1 +#define BM_I2C_CON_SPEED 0x6 +#define BV_I2C_CON_SPEED__100K 0x1 +#define BV_I2C_CON_SPEED__400K 0x2 +#define BF_I2C_CON_SPEED(v) (((v) & 0x3) << 1) +#define BFM_I2C_CON_SPEED(v) BM_I2C_CON_SPEED +#define BF_I2C_CON_SPEED_V(e) BF_I2C_CON_SPEED(BV_I2C_CON_SPEED__##e) +#define BFM_I2C_CON_SPEED_V(v) BM_I2C_CON_SPEED +#define BP_I2C_CON_SLVDIS 6 +#define BM_I2C_CON_SLVDIS 0x40 +#define BF_I2C_CON_SLVDIS(v) (((v) & 0x1) << 6) +#define BFM_I2C_CON_SLVDIS(v) BM_I2C_CON_SLVDIS +#define BF_I2C_CON_SLVDIS_V(e) BF_I2C_CON_SLVDIS(BV_I2C_CON_SLVDIS__##e) +#define BFM_I2C_CON_SLVDIS_V(v) BM_I2C_CON_SLVDIS +#define BP_I2C_CON_RESTART 5 +#define BM_I2C_CON_RESTART 0x20 +#define BF_I2C_CON_RESTART(v) (((v) & 0x1) << 5) +#define BFM_I2C_CON_RESTART(v) BM_I2C_CON_RESTART +#define BF_I2C_CON_RESTART_V(e) BF_I2C_CON_RESTART(BV_I2C_CON_RESTART__##e) +#define BFM_I2C_CON_RESTART_V(v) BM_I2C_CON_RESTART +#define BP_I2C_CON_MATP 4 +#define BM_I2C_CON_MATP 0x10 +#define BF_I2C_CON_MATP(v) (((v) & 0x1) << 4) +#define BFM_I2C_CON_MATP(v) BM_I2C_CON_MATP +#define BF_I2C_CON_MATP_V(e) BF_I2C_CON_MATP(BV_I2C_CON_MATP__##e) +#define BFM_I2C_CON_MATP_V(v) BM_I2C_CON_MATP +#define BP_I2C_CON_SATP 3 +#define BM_I2C_CON_SATP 0x8 +#define BF_I2C_CON_SATP(v) (((v) & 0x1) << 3) +#define BFM_I2C_CON_SATP(v) BM_I2C_CON_SATP +#define BF_I2C_CON_SATP_V(e) BF_I2C_CON_SATP(BV_I2C_CON_SATP__##e) +#define BFM_I2C_CON_SATP_V(v) BM_I2C_CON_SATP +#define BP_I2C_CON_MD 0 +#define BM_I2C_CON_MD 0x1 +#define BF_I2C_CON_MD(v) (((v) & 0x1) << 0) +#define BFM_I2C_CON_MD(v) BM_I2C_CON_MD +#define BF_I2C_CON_MD_V(e) BF_I2C_CON_MD(BV_I2C_CON_MD__##e) +#define BFM_I2C_CON_MD_V(v) BM_I2C_CON_MD + +#define REG_I2C_DC(_n1) jz_reg(I2C_DC(_n1)) +#define JA_I2C_DC(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x10) +#define JT_I2C_DC(_n1) JIO_32_RW +#define JN_I2C_DC(_n1) I2C_DC +#define JI_I2C_DC(_n1) (_n1) +#define BP_I2C_DC_DAT 0 +#define BM_I2C_DC_DAT 0xff +#define BF_I2C_DC_DAT(v) (((v) & 0xff) << 0) +#define BFM_I2C_DC_DAT(v) BM_I2C_DC_DAT +#define BF_I2C_DC_DAT_V(e) BF_I2C_DC_DAT(BV_I2C_DC_DAT__##e) +#define BFM_I2C_DC_DAT_V(v) BM_I2C_DC_DAT +#define BP_I2C_DC_RESTART 10 +#define BM_I2C_DC_RESTART 0x400 +#define BF_I2C_DC_RESTART(v) (((v) & 0x1) << 10) +#define BFM_I2C_DC_RESTART(v) BM_I2C_DC_RESTART +#define BF_I2C_DC_RESTART_V(e) BF_I2C_DC_RESTART(BV_I2C_DC_RESTART__##e) +#define BFM_I2C_DC_RESTART_V(v) BM_I2C_DC_RESTART +#define BP_I2C_DC_STOP 9 +#define BM_I2C_DC_STOP 0x200 +#define BF_I2C_DC_STOP(v) (((v) & 0x1) << 9) +#define BFM_I2C_DC_STOP(v) BM_I2C_DC_STOP +#define BF_I2C_DC_STOP_V(e) BF_I2C_DC_STOP(BV_I2C_DC_STOP__##e) +#define BFM_I2C_DC_STOP_V(v) BM_I2C_DC_STOP +#define BP_I2C_DC_CMD 8 +#define BM_I2C_DC_CMD 0x100 +#define BF_I2C_DC_CMD(v) (((v) & 0x1) << 8) +#define BFM_I2C_DC_CMD(v) BM_I2C_DC_CMD +#define BF_I2C_DC_CMD_V(e) BF_I2C_DC_CMD(BV_I2C_DC_CMD__##e) +#define BFM_I2C_DC_CMD_V(v) BM_I2C_DC_CMD + +#define REG_I2C_INTST(_n1) jz_reg(I2C_INTST(_n1)) +#define JA_I2C_INTST(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x2c) +#define JT_I2C_INTST(_n1) JIO_32_RW +#define JN_I2C_INTST(_n1) I2C_INTST +#define JI_I2C_INTST(_n1) (_n1) +#define BP_I2C_INTST_GC 11 +#define BM_I2C_INTST_GC 0x800 +#define BF_I2C_INTST_GC(v) (((v) & 0x1) << 11) +#define BFM_I2C_INTST_GC(v) BM_I2C_INTST_GC +#define BF_I2C_INTST_GC_V(e) BF_I2C_INTST_GC(BV_I2C_INTST_GC__##e) +#define BFM_I2C_INTST_GC_V(v) BM_I2C_INTST_GC +#define BP_I2C_INTST_STT 10 +#define BM_I2C_INTST_STT 0x400 +#define BF_I2C_INTST_STT(v) (((v) & 0x1) << 10) +#define BFM_I2C_INTST_STT(v) BM_I2C_INTST_STT +#define BF_I2C_INTST_STT_V(e) BF_I2C_INTST_STT(BV_I2C_INTST_STT__##e) +#define BFM_I2C_INTST_STT_V(v) BM_I2C_INTST_STT +#define BP_I2C_INTST_STP 9 +#define BM_I2C_INTST_STP 0x200 +#define BF_I2C_INTST_STP(v) (((v) & 0x1) << 9) +#define BFM_I2C_INTST_STP(v) BM_I2C_INTST_STP +#define BF_I2C_INTST_STP_V(e) BF_I2C_INTST_STP(BV_I2C_INTST_STP__##e) +#define BFM_I2C_INTST_STP_V(v) BM_I2C_INTST_STP +#define BP_I2C_INTST_ACT 8 +#define BM_I2C_INTST_ACT 0x100 +#define BF_I2C_INTST_ACT(v) (((v) & 0x1) << 8) +#define BFM_I2C_INTST_ACT(v) BM_I2C_INTST_ACT +#define BF_I2C_INTST_ACT_V(e) BF_I2C_INTST_ACT(BV_I2C_INTST_ACT__##e) +#define BFM_I2C_INTST_ACT_V(v) BM_I2C_INTST_ACT +#define BP_I2C_INTST_RXDN 7 +#define BM_I2C_INTST_RXDN 0x80 +#define BF_I2C_INTST_RXDN(v) (((v) & 0x1) << 7) +#define BFM_I2C_INTST_RXDN(v) BM_I2C_INTST_RXDN +#define BF_I2C_INTST_RXDN_V(e) BF_I2C_INTST_RXDN(BV_I2C_INTST_RXDN__##e) +#define BFM_I2C_INTST_RXDN_V(v) BM_I2C_INTST_RXDN +#define BP_I2C_INTST_TXABT 6 +#define BM_I2C_INTST_TXABT 0x40 +#define BF_I2C_INTST_TXABT(v) (((v) & 0x1) << 6) +#define BFM_I2C_INTST_TXABT(v) BM_I2C_INTST_TXABT +#define BF_I2C_INTST_TXABT_V(e) BF_I2C_INTST_TXABT(BV_I2C_INTST_TXABT__##e) +#define BFM_I2C_INTST_TXABT_V(v) BM_I2C_INTST_TXABT +#define BP_I2C_INTST_RDREQ 5 +#define BM_I2C_INTST_RDREQ 0x20 +#define BF_I2C_INTST_RDREQ(v) (((v) & 0x1) << 5) +#define BFM_I2C_INTST_RDREQ(v) BM_I2C_INTST_RDREQ +#define BF_I2C_INTST_RDREQ_V(e) BF_I2C_INTST_RDREQ(BV_I2C_INTST_RDREQ__##e) +#define BFM_I2C_INTST_RDREQ_V(v) BM_I2C_INTST_RDREQ +#define BP_I2C_INTST_TXEMP 4 +#define BM_I2C_INTST_TXEMP 0x10 +#define BF_I2C_INTST_TXEMP(v) (((v) & 0x1) << 4) +#define BFM_I2C_INTST_TXEMP(v) BM_I2C_INTST_TXEMP +#define BF_I2C_INTST_TXEMP_V(e) BF_I2C_INTST_TXEMP(BV_I2C_INTST_TXEMP__##e) +#define BFM_I2C_INTST_TXEMP_V(v) BM_I2C_INTST_TXEMP +#define BP_I2C_INTST_TXOF 3 +#define BM_I2C_INTST_TXOF 0x8 +#define BF_I2C_INTST_TXOF(v) (((v) & 0x1) << 3) +#define BFM_I2C_INTST_TXOF(v) BM_I2C_INTST_TXOF +#define BF_I2C_INTST_TXOF_V(e) BF_I2C_INTST_TXOF(BV_I2C_INTST_TXOF__##e) +#define BFM_I2C_INTST_TXOF_V(v) BM_I2C_INTST_TXOF +#define BP_I2C_INTST_RXFL 2 +#define BM_I2C_INTST_RXFL 0x4 +#define BF_I2C_INTST_RXFL(v) (((v) & 0x1) << 2) +#define BFM_I2C_INTST_RXFL(v) BM_I2C_INTST_RXFL +#define BF_I2C_INTST_RXFL_V(e) BF_I2C_INTST_RXFL(BV_I2C_INTST_RXFL__##e) +#define BFM_I2C_INTST_RXFL_V(v) BM_I2C_INTST_RXFL +#define BP_I2C_INTST_RXOF 1 +#define BM_I2C_INTST_RXOF 0x2 +#define BF_I2C_INTST_RXOF(v) (((v) & 0x1) << 1) +#define BFM_I2C_INTST_RXOF(v) BM_I2C_INTST_RXOF +#define BF_I2C_INTST_RXOF_V(e) BF_I2C_INTST_RXOF(BV_I2C_INTST_RXOF__##e) +#define BFM_I2C_INTST_RXOF_V(v) BM_I2C_INTST_RXOF +#define BP_I2C_INTST_RXUF 0 +#define BM_I2C_INTST_RXUF 0x1 +#define BF_I2C_INTST_RXUF(v) (((v) & 0x1) << 0) +#define BFM_I2C_INTST_RXUF(v) BM_I2C_INTST_RXUF +#define BF_I2C_INTST_RXUF_V(e) BF_I2C_INTST_RXUF(BV_I2C_INTST_RXUF__##e) +#define BFM_I2C_INTST_RXUF_V(v) BM_I2C_INTST_RXUF + +#define REG_I2C_INTMSK(_n1) jz_reg(I2C_INTMSK(_n1)) +#define JA_I2C_INTMSK(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x30) +#define JT_I2C_INTMSK(_n1) JIO_32_RW +#define JN_I2C_INTMSK(_n1) I2C_INTMSK +#define JI_I2C_INTMSK(_n1) (_n1) +#define BP_I2C_INTMSK_GC 11 +#define BM_I2C_INTMSK_GC 0x800 +#define BF_I2C_INTMSK_GC(v) (((v) & 0x1) << 11) +#define BFM_I2C_INTMSK_GC(v) BM_I2C_INTMSK_GC +#define BF_I2C_INTMSK_GC_V(e) BF_I2C_INTMSK_GC(BV_I2C_INTMSK_GC__##e) +#define BFM_I2C_INTMSK_GC_V(v) BM_I2C_INTMSK_GC +#define BP_I2C_INTMSK_STT 10 +#define BM_I2C_INTMSK_STT 0x400 +#define BF_I2C_INTMSK_STT(v) (((v) & 0x1) << 10) +#define BFM_I2C_INTMSK_STT(v) BM_I2C_INTMSK_STT +#define BF_I2C_INTMSK_STT_V(e) BF_I2C_INTMSK_STT(BV_I2C_INTMSK_STT__##e) +#define BFM_I2C_INTMSK_STT_V(v) BM_I2C_INTMSK_STT +#define BP_I2C_INTMSK_STP 9 +#define BM_I2C_INTMSK_STP 0x200 +#define BF_I2C_INTMSK_STP(v) (((v) & 0x1) << 9) +#define BFM_I2C_INTMSK_STP(v) BM_I2C_INTMSK_STP +#define BF_I2C_INTMSK_STP_V(e) BF_I2C_INTMSK_STP(BV_I2C_INTMSK_STP__##e) +#define BFM_I2C_INTMSK_STP_V(v) BM_I2C_INTMSK_STP +#define BP_I2C_INTMSK_ACT 8 +#define BM_I2C_INTMSK_ACT 0x100 +#define BF_I2C_INTMSK_ACT(v) (((v) & 0x1) << 8) +#define BFM_I2C_INTMSK_ACT(v) BM_I2C_INTMSK_ACT +#define BF_I2C_INTMSK_ACT_V(e) BF_I2C_INTMSK_ACT(BV_I2C_INTMSK_ACT__##e) +#define BFM_I2C_INTMSK_ACT_V(v) BM_I2C_INTMSK_ACT +#define BP_I2C_INTMSK_RXDN 7 +#define BM_I2C_INTMSK_RXDN 0x80 +#define BF_I2C_INTMSK_RXDN(v) (((v) & 0x1) << 7) +#define BFM_I2C_INTMSK_RXDN(v) BM_I2C_INTMSK_RXDN +#define BF_I2C_INTMSK_RXDN_V(e) BF_I2C_INTMSK_RXDN(BV_I2C_INTMSK_RXDN__##e) +#define BFM_I2C_INTMSK_RXDN_V(v) BM_I2C_INTMSK_RXDN +#define BP_I2C_INTMSK_TXABT 6 +#define BM_I2C_INTMSK_TXABT 0x40 +#define BF_I2C_INTMSK_TXABT(v) (((v) & 0x1) << 6) +#define BFM_I2C_INTMSK_TXABT(v) BM_I2C_INTMSK_TXABT +#define BF_I2C_INTMSK_TXABT_V(e) BF_I2C_INTMSK_TXABT(BV_I2C_INTMSK_TXABT__##e) +#define BFM_I2C_INTMSK_TXABT_V(v) BM_I2C_INTMSK_TXABT +#define BP_I2C_INTMSK_RDREQ 5 +#define BM_I2C_INTMSK_RDREQ 0x20 +#define BF_I2C_INTMSK_RDREQ(v) (((v) & 0x1) << 5) +#define BFM_I2C_INTMSK_RDREQ(v) BM_I2C_INTMSK_RDREQ +#define BF_I2C_INTMSK_RDREQ_V(e) BF_I2C_INTMSK_RDREQ(BV_I2C_INTMSK_RDREQ__##e) +#define BFM_I2C_INTMSK_RDREQ_V(v) BM_I2C_INTMSK_RDREQ +#define BP_I2C_INTMSK_TXEMP 4 +#define BM_I2C_INTMSK_TXEMP 0x10 +#define BF_I2C_INTMSK_TXEMP(v) (((v) & 0x1) << 4) +#define BFM_I2C_INTMSK_TXEMP(v) BM_I2C_INTMSK_TXEMP +#define BF_I2C_INTMSK_TXEMP_V(e) BF_I2C_INTMSK_TXEMP(BV_I2C_INTMSK_TXEMP__##e) +#define BFM_I2C_INTMSK_TXEMP_V(v) BM_I2C_INTMSK_TXEMP +#define BP_I2C_INTMSK_TXOF 3 +#define BM_I2C_INTMSK_TXOF 0x8 +#define BF_I2C_INTMSK_TXOF(v) (((v) & 0x1) << 3) +#define BFM_I2C_INTMSK_TXOF(v) BM_I2C_INTMSK_TXOF +#define BF_I2C_INTMSK_TXOF_V(e) BF_I2C_INTMSK_TXOF(BV_I2C_INTMSK_TXOF__##e) +#define BFM_I2C_INTMSK_TXOF_V(v) BM_I2C_INTMSK_TXOF +#define BP_I2C_INTMSK_RXFL 2 +#define BM_I2C_INTMSK_RXFL 0x4 +#define BF_I2C_INTMSK_RXFL(v) (((v) & 0x1) << 2) +#define BFM_I2C_INTMSK_RXFL(v) BM_I2C_INTMSK_RXFL +#define BF_I2C_INTMSK_RXFL_V(e) BF_I2C_INTMSK_RXFL(BV_I2C_INTMSK_RXFL__##e) +#define BFM_I2C_INTMSK_RXFL_V(v) BM_I2C_INTMSK_RXFL +#define BP_I2C_INTMSK_RXOF 1 +#define BM_I2C_INTMSK_RXOF 0x2 +#define BF_I2C_INTMSK_RXOF(v) (((v) & 0x1) << 1) +#define BFM_I2C_INTMSK_RXOF(v) BM_I2C_INTMSK_RXOF +#define BF_I2C_INTMSK_RXOF_V(e) BF_I2C_INTMSK_RXOF(BV_I2C_INTMSK_RXOF__##e) +#define BFM_I2C_INTMSK_RXOF_V(v) BM_I2C_INTMSK_RXOF +#define BP_I2C_INTMSK_RXUF 0 +#define BM_I2C_INTMSK_RXUF 0x1 +#define BF_I2C_INTMSK_RXUF(v) (((v) & 0x1) << 0) +#define BFM_I2C_INTMSK_RXUF(v) BM_I2C_INTMSK_RXUF +#define BF_I2C_INTMSK_RXUF_V(e) BF_I2C_INTMSK_RXUF(BV_I2C_INTMSK_RXUF__##e) +#define BFM_I2C_INTMSK_RXUF_V(v) BM_I2C_INTMSK_RXUF + +#define REG_I2C_RINTST(_n1) jz_reg(I2C_RINTST(_n1)) +#define JA_I2C_RINTST(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x34) +#define JT_I2C_RINTST(_n1) JIO_32_RW +#define JN_I2C_RINTST(_n1) I2C_RINTST +#define JI_I2C_RINTST(_n1) (_n1) +#define BP_I2C_RINTST_GC 11 +#define BM_I2C_RINTST_GC 0x800 +#define BF_I2C_RINTST_GC(v) (((v) & 0x1) << 11) +#define BFM_I2C_RINTST_GC(v) BM_I2C_RINTST_GC +#define BF_I2C_RINTST_GC_V(e) BF_I2C_RINTST_GC(BV_I2C_RINTST_GC__##e) +#define BFM_I2C_RINTST_GC_V(v) BM_I2C_RINTST_GC +#define BP_I2C_RINTST_STT 10 +#define BM_I2C_RINTST_STT 0x400 +#define BF_I2C_RINTST_STT(v) (((v) & 0x1) << 10) +#define BFM_I2C_RINTST_STT(v) BM_I2C_RINTST_STT +#define BF_I2C_RINTST_STT_V(e) BF_I2C_RINTST_STT(BV_I2C_RINTST_STT__##e) +#define BFM_I2C_RINTST_STT_V(v) BM_I2C_RINTST_STT +#define BP_I2C_RINTST_STP 9 +#define BM_I2C_RINTST_STP 0x200 +#define BF_I2C_RINTST_STP(v) (((v) & 0x1) << 9) +#define BFM_I2C_RINTST_STP(v) BM_I2C_RINTST_STP +#define BF_I2C_RINTST_STP_V(e) BF_I2C_RINTST_STP(BV_I2C_RINTST_STP__##e) +#define BFM_I2C_RINTST_STP_V(v) BM_I2C_RINTST_STP +#define BP_I2C_RINTST_ACT 8 +#define BM_I2C_RINTST_ACT 0x100 +#define BF_I2C_RINTST_ACT(v) (((v) & 0x1) << 8) +#define BFM_I2C_RINTST_ACT(v) BM_I2C_RINTST_ACT +#define BF_I2C_RINTST_ACT_V(e) BF_I2C_RINTST_ACT(BV_I2C_RINTST_ACT__##e) +#define BFM_I2C_RINTST_ACT_V(v) BM_I2C_RINTST_ACT +#define BP_I2C_RINTST_RXDN 7 +#define BM_I2C_RINTST_RXDN 0x80 +#define BF_I2C_RINTST_RXDN(v) (((v) & 0x1) << 7) +#define BFM_I2C_RINTST_RXDN(v) BM_I2C_RINTST_RXDN +#define BF_I2C_RINTST_RXDN_V(e) BF_I2C_RINTST_RXDN(BV_I2C_RINTST_RXDN__##e) +#define BFM_I2C_RINTST_RXDN_V(v) BM_I2C_RINTST_RXDN +#define BP_I2C_RINTST_TXABT 6 +#define BM_I2C_RINTST_TXABT 0x40 +#define BF_I2C_RINTST_TXABT(v) (((v) & 0x1) << 6) +#define BFM_I2C_RINTST_TXABT(v) BM_I2C_RINTST_TXABT +#define BF_I2C_RINTST_TXABT_V(e) BF_I2C_RINTST_TXABT(BV_I2C_RINTST_TXABT__##e) +#define BFM_I2C_RINTST_TXABT_V(v) BM_I2C_RINTST_TXABT +#define BP_I2C_RINTST_RDREQ 5 +#define BM_I2C_RINTST_RDREQ 0x20 +#define BF_I2C_RINTST_RDREQ(v) (((v) & 0x1) << 5) +#define BFM_I2C_RINTST_RDREQ(v) BM_I2C_RINTST_RDREQ +#define BF_I2C_RINTST_RDREQ_V(e) BF_I2C_RINTST_RDREQ(BV_I2C_RINTST_RDREQ__##e) +#define BFM_I2C_RINTST_RDREQ_V(v) BM_I2C_RINTST_RDREQ +#define BP_I2C_RINTST_TXEMP 4 +#define BM_I2C_RINTST_TXEMP 0x10 +#define BF_I2C_RINTST_TXEMP(v) (((v) & 0x1) << 4) +#define BFM_I2C_RINTST_TXEMP(v) BM_I2C_RINTST_TXEMP +#define BF_I2C_RINTST_TXEMP_V(e) BF_I2C_RINTST_TXEMP(BV_I2C_RINTST_TXEMP__##e) +#define BFM_I2C_RINTST_TXEMP_V(v) BM_I2C_RINTST_TXEMP +#define BP_I2C_RINTST_TXOF 3 +#define BM_I2C_RINTST_TXOF 0x8 +#define BF_I2C_RINTST_TXOF(v) (((v) & 0x1) << 3) +#define BFM_I2C_RINTST_TXOF(v) BM_I2C_RINTST_TXOF +#define BF_I2C_RINTST_TXOF_V(e) BF_I2C_RINTST_TXOF(BV_I2C_RINTST_TXOF__##e) +#define BFM_I2C_RINTST_TXOF_V(v) BM_I2C_RINTST_TXOF +#define BP_I2C_RINTST_RXFL 2 +#define BM_I2C_RINTST_RXFL 0x4 +#define BF_I2C_RINTST_RXFL(v) (((v) & 0x1) << 2) +#define BFM_I2C_RINTST_RXFL(v) BM_I2C_RINTST_RXFL +#define BF_I2C_RINTST_RXFL_V(e) BF_I2C_RINTST_RXFL(BV_I2C_RINTST_RXFL__##e) +#define BFM_I2C_RINTST_RXFL_V(v) BM_I2C_RINTST_RXFL +#define BP_I2C_RINTST_RXOF 1 +#define BM_I2C_RINTST_RXOF 0x2 +#define BF_I2C_RINTST_RXOF(v) (((v) & 0x1) << 1) +#define BFM_I2C_RINTST_RXOF(v) BM_I2C_RINTST_RXOF +#define BF_I2C_RINTST_RXOF_V(e) BF_I2C_RINTST_RXOF(BV_I2C_RINTST_RXOF__##e) +#define BFM_I2C_RINTST_RXOF_V(v) BM_I2C_RINTST_RXOF +#define BP_I2C_RINTST_RXUF 0 +#define BM_I2C_RINTST_RXUF 0x1 +#define BF_I2C_RINTST_RXUF(v) (((v) & 0x1) << 0) +#define BFM_I2C_RINTST_RXUF(v) BM_I2C_RINTST_RXUF +#define BF_I2C_RINTST_RXUF_V(e) BF_I2C_RINTST_RXUF(BV_I2C_RINTST_RXUF__##e) +#define BFM_I2C_RINTST_RXUF_V(v) BM_I2C_RINTST_RXUF + +#define REG_I2C_ENABLE(_n1) jz_reg(I2C_ENABLE(_n1)) +#define JA_I2C_ENABLE(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x6c) +#define JT_I2C_ENABLE(_n1) JIO_32_RW +#define JN_I2C_ENABLE(_n1) I2C_ENABLE +#define JI_I2C_ENABLE(_n1) (_n1) +#define BP_I2C_ENABLE_ABORT 1 +#define BM_I2C_ENABLE_ABORT 0x2 +#define BF_I2C_ENABLE_ABORT(v) (((v) & 0x1) << 1) +#define BFM_I2C_ENABLE_ABORT(v) BM_I2C_ENABLE_ABORT +#define BF_I2C_ENABLE_ABORT_V(e) BF_I2C_ENABLE_ABORT(BV_I2C_ENABLE_ABORT__##e) +#define BFM_I2C_ENABLE_ABORT_V(v) BM_I2C_ENABLE_ABORT +#define BP_I2C_ENABLE_ACTIVE 0 +#define BM_I2C_ENABLE_ACTIVE 0x1 +#define BF_I2C_ENABLE_ACTIVE(v) (((v) & 0x1) << 0) +#define BFM_I2C_ENABLE_ACTIVE(v) BM_I2C_ENABLE_ACTIVE +#define BF_I2C_ENABLE_ACTIVE_V(e) BF_I2C_ENABLE_ACTIVE(BV_I2C_ENABLE_ACTIVE__##e) +#define BFM_I2C_ENABLE_ACTIVE_V(v) BM_I2C_ENABLE_ACTIVE + +#define REG_I2C_STATUS(_n1) jz_reg(I2C_STATUS(_n1)) +#define JA_I2C_STATUS(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x70) +#define JT_I2C_STATUS(_n1) JIO_32_RW +#define JN_I2C_STATUS(_n1) I2C_STATUS +#define JI_I2C_STATUS(_n1) (_n1) +#define BP_I2C_STATUS_SLVACT 6 +#define BM_I2C_STATUS_SLVACT 0x40 +#define BF_I2C_STATUS_SLVACT(v) (((v) & 0x1) << 6) +#define BFM_I2C_STATUS_SLVACT(v) BM_I2C_STATUS_SLVACT +#define BF_I2C_STATUS_SLVACT_V(e) BF_I2C_STATUS_SLVACT(BV_I2C_STATUS_SLVACT__##e) +#define BFM_I2C_STATUS_SLVACT_V(v) BM_I2C_STATUS_SLVACT +#define BP_I2C_STATUS_MSTACT 5 +#define BM_I2C_STATUS_MSTACT 0x20 +#define BF_I2C_STATUS_MSTACT(v) (((v) & 0x1) << 5) +#define BFM_I2C_STATUS_MSTACT(v) BM_I2C_STATUS_MSTACT +#define BF_I2C_STATUS_MSTACT_V(e) BF_I2C_STATUS_MSTACT(BV_I2C_STATUS_MSTACT__##e) +#define BFM_I2C_STATUS_MSTACT_V(v) BM_I2C_STATUS_MSTACT +#define BP_I2C_STATUS_RFF 4 +#define BM_I2C_STATUS_RFF 0x10 +#define BF_I2C_STATUS_RFF(v) (((v) & 0x1) << 4) +#define BFM_I2C_STATUS_RFF(v) BM_I2C_STATUS_RFF +#define BF_I2C_STATUS_RFF_V(e) BF_I2C_STATUS_RFF(BV_I2C_STATUS_RFF__##e) +#define BFM_I2C_STATUS_RFF_V(v) BM_I2C_STATUS_RFF +#define BP_I2C_STATUS_RFNE 3 +#define BM_I2C_STATUS_RFNE 0x8 +#define BF_I2C_STATUS_RFNE(v) (((v) & 0x1) << 3) +#define BFM_I2C_STATUS_RFNE(v) BM_I2C_STATUS_RFNE +#define BF_I2C_STATUS_RFNE_V(e) BF_I2C_STATUS_RFNE(BV_I2C_STATUS_RFNE__##e) +#define BFM_I2C_STATUS_RFNE_V(v) BM_I2C_STATUS_RFNE +#define BP_I2C_STATUS_TFE 2 +#define BM_I2C_STATUS_TFE 0x4 +#define BF_I2C_STATUS_TFE(v) (((v) & 0x1) << 2) +#define BFM_I2C_STATUS_TFE(v) BM_I2C_STATUS_TFE +#define BF_I2C_STATUS_TFE_V(e) BF_I2C_STATUS_TFE(BV_I2C_STATUS_TFE__##e) +#define BFM_I2C_STATUS_TFE_V(v) BM_I2C_STATUS_TFE +#define BP_I2C_STATUS_TFNF 1 +#define BM_I2C_STATUS_TFNF 0x2 +#define BF_I2C_STATUS_TFNF(v) (((v) & 0x1) << 1) +#define BFM_I2C_STATUS_TFNF(v) BM_I2C_STATUS_TFNF +#define BF_I2C_STATUS_TFNF_V(e) BF_I2C_STATUS_TFNF(BV_I2C_STATUS_TFNF__##e) +#define BFM_I2C_STATUS_TFNF_V(v) BM_I2C_STATUS_TFNF +#define BP_I2C_STATUS_ACT 0 +#define BM_I2C_STATUS_ACT 0x1 +#define BF_I2C_STATUS_ACT(v) (((v) & 0x1) << 0) +#define BFM_I2C_STATUS_ACT(v) BM_I2C_STATUS_ACT +#define BF_I2C_STATUS_ACT_V(e) BF_I2C_STATUS_ACT(BV_I2C_STATUS_ACT__##e) +#define BFM_I2C_STATUS_ACT_V(v) BM_I2C_STATUS_ACT + +#define REG_I2C_ENBST(_n1) jz_reg(I2C_ENBST(_n1)) +#define JA_I2C_ENBST(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x9c) +#define JT_I2C_ENBST(_n1) JIO_32_RW +#define JN_I2C_ENBST(_n1) I2C_ENBST +#define JI_I2C_ENBST(_n1) (_n1) +#define BP_I2C_ENBST_SLVRDLST 2 +#define BM_I2C_ENBST_SLVRDLST 0x4 +#define BF_I2C_ENBST_SLVRDLST(v) (((v) & 0x1) << 2) +#define BFM_I2C_ENBST_SLVRDLST(v) BM_I2C_ENBST_SLVRDLST +#define BF_I2C_ENBST_SLVRDLST_V(e) BF_I2C_ENBST_SLVRDLST(BV_I2C_ENBST_SLVRDLST__##e) +#define BFM_I2C_ENBST_SLVRDLST_V(v) BM_I2C_ENBST_SLVRDLST +#define BP_I2C_ENBST_SLVDISB 1 +#define BM_I2C_ENBST_SLVDISB 0x2 +#define BF_I2C_ENBST_SLVDISB(v) (((v) & 0x1) << 1) +#define BFM_I2C_ENBST_SLVDISB(v) BM_I2C_ENBST_SLVDISB +#define BF_I2C_ENBST_SLVDISB_V(e) BF_I2C_ENBST_SLVDISB(BV_I2C_ENBST_SLVDISB__##e) +#define BFM_I2C_ENBST_SLVDISB_V(v) BM_I2C_ENBST_SLVDISB +#define BP_I2C_ENBST_ACTIVE 0 +#define BM_I2C_ENBST_ACTIVE 0x1 +#define BF_I2C_ENBST_ACTIVE(v) (((v) & 0x1) << 0) +#define BFM_I2C_ENBST_ACTIVE(v) BM_I2C_ENBST_ACTIVE +#define BF_I2C_ENBST_ACTIVE_V(e) BF_I2C_ENBST_ACTIVE(BV_I2C_ENBST_ACTIVE__##e) +#define BFM_I2C_ENBST_ACTIVE_V(v) BM_I2C_ENBST_ACTIVE + +#define REG_I2C_TAR(_n1) jz_reg(I2C_TAR(_n1)) +#define JA_I2C_TAR(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x4) +#define JT_I2C_TAR(_n1) JIO_32_RW +#define JN_I2C_TAR(_n1) I2C_TAR +#define JI_I2C_TAR(_n1) (_n1) +#define BP_I2C_TAR_ADDR 0 +#define BM_I2C_TAR_ADDR 0x3ff +#define BF_I2C_TAR_ADDR(v) (((v) & 0x3ff) << 0) +#define BFM_I2C_TAR_ADDR(v) BM_I2C_TAR_ADDR +#define BF_I2C_TAR_ADDR_V(e) BF_I2C_TAR_ADDR(BV_I2C_TAR_ADDR__##e) +#define BFM_I2C_TAR_ADDR_V(v) BM_I2C_TAR_ADDR +#define BP_I2C_TAR_10BITS 12 +#define BM_I2C_TAR_10BITS 0x1000 +#define BF_I2C_TAR_10BITS(v) (((v) & 0x1) << 12) +#define BFM_I2C_TAR_10BITS(v) BM_I2C_TAR_10BITS +#define BF_I2C_TAR_10BITS_V(e) BF_I2C_TAR_10BITS(BV_I2C_TAR_10BITS__##e) +#define BFM_I2C_TAR_10BITS_V(v) BM_I2C_TAR_10BITS +#define BP_I2C_TAR_SPECIAL 11 +#define BM_I2C_TAR_SPECIAL 0x800 +#define BF_I2C_TAR_SPECIAL(v) (((v) & 0x1) << 11) +#define BFM_I2C_TAR_SPECIAL(v) BM_I2C_TAR_SPECIAL +#define BF_I2C_TAR_SPECIAL_V(e) BF_I2C_TAR_SPECIAL(BV_I2C_TAR_SPECIAL__##e) +#define BFM_I2C_TAR_SPECIAL_V(v) BM_I2C_TAR_SPECIAL +#define BP_I2C_TAR_GC_OR_START 10 +#define BM_I2C_TAR_GC_OR_START 0x400 +#define BF_I2C_TAR_GC_OR_START(v) (((v) & 0x1) << 10) +#define BFM_I2C_TAR_GC_OR_START(v) BM_I2C_TAR_GC_OR_START +#define BF_I2C_TAR_GC_OR_START_V(e) BF_I2C_TAR_GC_OR_START(BV_I2C_TAR_GC_OR_START__##e) +#define BFM_I2C_TAR_GC_OR_START_V(v) BM_I2C_TAR_GC_OR_START + +#define REG_I2C_SAR(_n1) jz_reg(I2C_SAR(_n1)) +#define JA_I2C_SAR(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x8) +#define JT_I2C_SAR(_n1) JIO_32_RW +#define JN_I2C_SAR(_n1) I2C_SAR +#define JI_I2C_SAR(_n1) (_n1) + +#define REG_I2C_SHCNT(_n1) jz_reg(I2C_SHCNT(_n1)) +#define JA_I2C_SHCNT(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x14) +#define JT_I2C_SHCNT(_n1) JIO_32_RW +#define JN_I2C_SHCNT(_n1) I2C_SHCNT +#define JI_I2C_SHCNT(_n1) (_n1) + +#define REG_I2C_SLCNT(_n1) jz_reg(I2C_SLCNT(_n1)) +#define JA_I2C_SLCNT(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x18) +#define JT_I2C_SLCNT(_n1) JIO_32_RW +#define JN_I2C_SLCNT(_n1) I2C_SLCNT +#define JI_I2C_SLCNT(_n1) (_n1) + +#define REG_I2C_FHCNT(_n1) jz_reg(I2C_FHCNT(_n1)) +#define JA_I2C_FHCNT(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x1c) +#define JT_I2C_FHCNT(_n1) JIO_32_RW +#define JN_I2C_FHCNT(_n1) I2C_FHCNT +#define JI_I2C_FHCNT(_n1) (_n1) + +#define REG_I2C_FLCNT(_n1) jz_reg(I2C_FLCNT(_n1)) +#define JA_I2C_FLCNT(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x20) +#define JT_I2C_FLCNT(_n1) JIO_32_RW +#define JN_I2C_FLCNT(_n1) I2C_FLCNT +#define JI_I2C_FLCNT(_n1) (_n1) + +#define REG_I2C_RXTL(_n1) jz_reg(I2C_RXTL(_n1)) +#define JA_I2C_RXTL(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x38) +#define JT_I2C_RXTL(_n1) JIO_32_RW +#define JN_I2C_RXTL(_n1) I2C_RXTL +#define JI_I2C_RXTL(_n1) (_n1) + +#define REG_I2C_TXTL(_n1) jz_reg(I2C_TXTL(_n1)) +#define JA_I2C_TXTL(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x3c) +#define JT_I2C_TXTL(_n1) JIO_32_RW +#define JN_I2C_TXTL(_n1) I2C_TXTL +#define JI_I2C_TXTL(_n1) (_n1) + +#define REG_I2C_TXFLR(_n1) jz_reg(I2C_TXFLR(_n1)) +#define JA_I2C_TXFLR(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x74) +#define JT_I2C_TXFLR(_n1) JIO_32_RW +#define JN_I2C_TXFLR(_n1) I2C_TXFLR +#define JI_I2C_TXFLR(_n1) (_n1) + +#define REG_I2C_RXFLR(_n1) jz_reg(I2C_RXFLR(_n1)) +#define JA_I2C_RXFLR(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x78) +#define JT_I2C_RXFLR(_n1) JIO_32_RW +#define JN_I2C_RXFLR(_n1) I2C_RXFLR +#define JI_I2C_RXFLR(_n1) (_n1) + +#define REG_I2C_SDAHD(_n1) jz_reg(I2C_SDAHD(_n1)) +#define JA_I2C_SDAHD(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x7c) +#define JT_I2C_SDAHD(_n1) JIO_32_RW +#define JN_I2C_SDAHD(_n1) I2C_SDAHD +#define JI_I2C_SDAHD(_n1) (_n1) + +#define REG_I2C_ABTSRC(_n1) jz_reg(I2C_ABTSRC(_n1)) +#define JA_I2C_ABTSRC(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x80) +#define JT_I2C_ABTSRC(_n1) JIO_32_RW +#define JN_I2C_ABTSRC(_n1) I2C_ABTSRC +#define JI_I2C_ABTSRC(_n1) (_n1) + +#define REG_I2C_DMACR(_n1) jz_reg(I2C_DMACR(_n1)) +#define JA_I2C_DMACR(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x88) +#define JT_I2C_DMACR(_n1) JIO_32_RW +#define JN_I2C_DMACR(_n1) I2C_DMACR +#define JI_I2C_DMACR(_n1) (_n1) + +#define REG_I2C_DMATDLR(_n1) jz_reg(I2C_DMATDLR(_n1)) +#define JA_I2C_DMATDLR(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x8c) +#define JT_I2C_DMATDLR(_n1) JIO_32_RW +#define JN_I2C_DMATDLR(_n1) I2C_DMATDLR +#define JI_I2C_DMATDLR(_n1) (_n1) + +#define REG_I2C_DMARDLR(_n1) jz_reg(I2C_DMARDLR(_n1)) +#define JA_I2C_DMARDLR(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x90) +#define JT_I2C_DMARDLR(_n1) JIO_32_RW +#define JN_I2C_DMARDLR(_n1) I2C_DMARDLR +#define JI_I2C_DMARDLR(_n1) (_n1) + +#define REG_I2C_SDASU(_n1) jz_reg(I2C_SDASU(_n1)) +#define JA_I2C_SDASU(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x94) +#define JT_I2C_SDASU(_n1) JIO_32_RW +#define JN_I2C_SDASU(_n1) I2C_SDASU +#define JI_I2C_SDASU(_n1) (_n1) + +#define REG_I2C_ACKGC(_n1) jz_reg(I2C_ACKGC(_n1)) +#define JA_I2C_ACKGC(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x98) +#define JT_I2C_ACKGC(_n1) JIO_32_RW +#define JN_I2C_ACKGC(_n1) I2C_ACKGC +#define JI_I2C_ACKGC(_n1) (_n1) + +#define REG_I2C_FLT(_n1) jz_reg(I2C_FLT(_n1)) +#define JA_I2C_FLT(_n1) (0xb0050000 + (_n1) * 0x1000 + 0xa0) +#define JT_I2C_FLT(_n1) JIO_32_RW +#define JN_I2C_FLT(_n1) I2C_FLT +#define JI_I2C_FLT(_n1) (_n1) + +#define REG_I2C_CINT(_n1) jz_reg(I2C_CINT(_n1)) +#define JA_I2C_CINT(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x40) +#define JT_I2C_CINT(_n1) JIO_32_RW +#define JN_I2C_CINT(_n1) I2C_CINT +#define JI_I2C_CINT(_n1) (_n1) + +#define REG_I2C_CRXUF(_n1) jz_reg(I2C_CRXUF(_n1)) +#define JA_I2C_CRXUF(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x44) +#define JT_I2C_CRXUF(_n1) JIO_32_RW +#define JN_I2C_CRXUF(_n1) I2C_CRXUF +#define JI_I2C_CRXUF(_n1) (_n1) + +#define REG_I2C_CRXOF(_n1) jz_reg(I2C_CRXOF(_n1)) +#define JA_I2C_CRXOF(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x48) +#define JT_I2C_CRXOF(_n1) JIO_32_RW +#define JN_I2C_CRXOF(_n1) I2C_CRXOF +#define JI_I2C_CRXOF(_n1) (_n1) + +#define REG_I2C_CTXOF(_n1) jz_reg(I2C_CTXOF(_n1)) +#define JA_I2C_CTXOF(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x4c) +#define JT_I2C_CTXOF(_n1) JIO_32_RW +#define JN_I2C_CTXOF(_n1) I2C_CTXOF +#define JI_I2C_CTXOF(_n1) (_n1) + +#define REG_I2C_CRXREQ(_n1) jz_reg(I2C_CRXREQ(_n1)) +#define JA_I2C_CRXREQ(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x50) +#define JT_I2C_CRXREQ(_n1) JIO_32_RW +#define JN_I2C_CRXREQ(_n1) I2C_CRXREQ +#define JI_I2C_CRXREQ(_n1) (_n1) + +#define REG_I2C_CTXABT(_n1) jz_reg(I2C_CTXABT(_n1)) +#define JA_I2C_CTXABT(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x54) +#define JT_I2C_CTXABT(_n1) JIO_32_RW +#define JN_I2C_CTXABT(_n1) I2C_CTXABT +#define JI_I2C_CTXABT(_n1) (_n1) + +#define REG_I2C_CRXDN(_n1) jz_reg(I2C_CRXDN(_n1)) +#define JA_I2C_CRXDN(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x58) +#define JT_I2C_CRXDN(_n1) JIO_32_RW +#define JN_I2C_CRXDN(_n1) I2C_CRXDN +#define JI_I2C_CRXDN(_n1) (_n1) + +#define REG_I2C_CACT(_n1) jz_reg(I2C_CACT(_n1)) +#define JA_I2C_CACT(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x5c) +#define JT_I2C_CACT(_n1) JIO_32_RW +#define JN_I2C_CACT(_n1) I2C_CACT +#define JI_I2C_CACT(_n1) (_n1) + +#define REG_I2C_CSTP(_n1) jz_reg(I2C_CSTP(_n1)) +#define JA_I2C_CSTP(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x60) +#define JT_I2C_CSTP(_n1) JIO_32_RW +#define JN_I2C_CSTP(_n1) I2C_CSTP +#define JI_I2C_CSTP(_n1) (_n1) + +#define REG_I2C_CSTT(_n1) jz_reg(I2C_CSTT(_n1)) +#define JA_I2C_CSTT(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x64) +#define JT_I2C_CSTT(_n1) JIO_32_RW +#define JN_I2C_CSTT(_n1) I2C_CSTT +#define JI_I2C_CSTT(_n1) (_n1) + +#define REG_I2C_CGC(_n1) jz_reg(I2C_CGC(_n1)) +#define JA_I2C_CGC(_n1) (0xb0050000 + (_n1) * 0x1000 + 0x68) +#define JT_I2C_CGC(_n1) JIO_32_RW +#define JN_I2C_CGC(_n1) I2C_CGC +#define JI_I2C_CGC(_n1) (_n1) + +#endif /* __HEADERGEN_I2C_H__*/ diff --git a/firmware/target/mips/ingenic_x1000/x1000/intc.h b/firmware/target/mips/ingenic_x1000/x1000/intc.h new file mode 100644 index 0000000000..37fbf33fb6 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/x1000/intc.h @@ -0,0 +1,57 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * This file was automatically generated by headergen, DO NOT EDIT it. + * headergen version: 3.0.0 + * x1000 version: 1.0 + * x1000 authors: Aidan MacDonald + * + * Copyright (C) 2015 by the authors + * + * 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 __HEADERGEN_INTC_H__ +#define __HEADERGEN_INTC_H__ + +#include "macro.h" + +#define REG_INTC_SRC(_n1) jz_reg(INTC_SRC(_n1)) +#define JA_INTC_SRC(_n1) (0xb0001000 + 0x0 + (_n1) * 0x20) +#define JT_INTC_SRC(_n1) JIO_32_RW +#define JN_INTC_SRC(_n1) INTC_SRC +#define JI_INTC_SRC(_n1) (_n1) + +#define REG_INTC_MSK(_n1) jz_reg(INTC_MSK(_n1)) +#define JA_INTC_MSK(_n1) (0xb0001000 + 0x4 + (_n1) * 0x20) +#define JT_INTC_MSK(_n1) JIO_32_RW +#define JN_INTC_MSK(_n1) INTC_MSK +#define JI_INTC_MSK(_n1) (_n1) +#define REG_INTC_MSK_SET(_n1) jz_reg(INTC_MSK_SET(_n1)) +#define JA_INTC_MSK_SET(_n1) (JA_INTC_MSK(_n1) + 0x4) +#define JT_INTC_MSK_SET(_n1) JIO_32_WO +#define JN_INTC_MSK_SET(_n1) INTC_MSK +#define JI_INTC_MSK_SET(_n1) (_n1) +#define REG_INTC_MSK_CLR(_n1) jz_reg(INTC_MSK_CLR(_n1)) +#define JA_INTC_MSK_CLR(_n1) (JA_INTC_MSK(_n1) + 0x8) +#define JT_INTC_MSK_CLR(_n1) JIO_32_WO +#define JN_INTC_MSK_CLR(_n1) INTC_MSK +#define JI_INTC_MSK_CLR(_n1) (_n1) + +#define REG_INTC_PND(_n1) jz_reg(INTC_PND(_n1)) +#define JA_INTC_PND(_n1) (0xb0001000 + 0x10 + (_n1) * 0x20) +#define JT_INTC_PND(_n1) JIO_32_RW +#define JN_INTC_PND(_n1) INTC_PND +#define JI_INTC_PND(_n1) (_n1) + +#endif /* __HEADERGEN_INTC_H__*/ diff --git a/firmware/target/mips/ingenic_x1000/x1000/lcd.h b/firmware/target/mips/ingenic_x1000/x1000/lcd.h new file mode 100644 index 0000000000..d4c1fe1878 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/x1000/lcd.h @@ -0,0 +1,446 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * This file was automatically generated by headergen, DO NOT EDIT it. + * headergen version: 3.0.0 + * x1000 version: 1.0 + * x1000 authors: Aidan MacDonald + * + * Copyright (C) 2015 by the authors + * + * 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 __HEADERGEN_LCD_H__ +#define __HEADERGEN_LCD_H__ + +#include "macro.h" + +#define REG_LCD_CFG jz_reg(LCD_CFG) +#define JA_LCD_CFG (0xb3050000 + 0x0) +#define JT_LCD_CFG JIO_32_RW +#define JN_LCD_CFG LCD_CFG +#define JI_LCD_CFG +#define BP_LCD_CFG_INVDAT 17 +#define BM_LCD_CFG_INVDAT 0x20000 +#define BF_LCD_CFG_INVDAT(v) (((v) & 0x1) << 17) +#define BFM_LCD_CFG_INVDAT(v) BM_LCD_CFG_INVDAT +#define BF_LCD_CFG_INVDAT_V(e) BF_LCD_CFG_INVDAT(BV_LCD_CFG_INVDAT__##e) +#define BFM_LCD_CFG_INVDAT_V(v) BM_LCD_CFG_INVDAT + +#define REG_LCD_CTRL jz_reg(LCD_CTRL) +#define JA_LCD_CTRL (0xb3050000 + 0x30) +#define JT_LCD_CTRL JIO_32_RW +#define JN_LCD_CTRL LCD_CTRL +#define JI_LCD_CTRL +#define BP_LCD_CTRL_BURST 28 +#define BM_LCD_CTRL_BURST 0x70000000 +#define BV_LCD_CTRL_BURST__4WORD 0x0 +#define BV_LCD_CTRL_BURST__8WORD 0x1 +#define BV_LCD_CTRL_BURST__16WORD 0x2 +#define BV_LCD_CTRL_BURST__32WORD 0x3 +#define BV_LCD_CTRL_BURST__64WORD 0x4 +#define BF_LCD_CTRL_BURST(v) (((v) & 0x7) << 28) +#define BFM_LCD_CTRL_BURST(v) BM_LCD_CTRL_BURST +#define BF_LCD_CTRL_BURST_V(e) BF_LCD_CTRL_BURST(BV_LCD_CTRL_BURST__##e) +#define BFM_LCD_CTRL_BURST_V(v) BM_LCD_CTRL_BURST +#define BP_LCD_CTRL_BPP 0 +#define BM_LCD_CTRL_BPP 0x7 +#define BV_LCD_CTRL_BPP__15BIT_OR_16BIT 0x4 +#define BV_LCD_CTRL_BPP__18BIT_OR_24BIT 0x5 +#define BV_LCD_CTRL_BPP__24BIT_COMPRESSED 0x6 +#define BV_LCD_CTRL_BPP__30BIT 0x7 +#define BF_LCD_CTRL_BPP(v) (((v) & 0x7) << 0) +#define BFM_LCD_CTRL_BPP(v) BM_LCD_CTRL_BPP +#define BF_LCD_CTRL_BPP_V(e) BF_LCD_CTRL_BPP(BV_LCD_CTRL_BPP__##e) +#define BFM_LCD_CTRL_BPP_V(v) BM_LCD_CTRL_BPP +#define BP_LCD_CTRL_EOFM 13 +#define BM_LCD_CTRL_EOFM 0x2000 +#define BF_LCD_CTRL_EOFM(v) (((v) & 0x1) << 13) +#define BFM_LCD_CTRL_EOFM(v) BM_LCD_CTRL_EOFM +#define BF_LCD_CTRL_EOFM_V(e) BF_LCD_CTRL_EOFM(BV_LCD_CTRL_EOFM__##e) +#define BFM_LCD_CTRL_EOFM_V(v) BM_LCD_CTRL_EOFM +#define BP_LCD_CTRL_SOFM 12 +#define BM_LCD_CTRL_SOFM 0x1000 +#define BF_LCD_CTRL_SOFM(v) (((v) & 0x1) << 12) +#define BFM_LCD_CTRL_SOFM(v) BM_LCD_CTRL_SOFM +#define BF_LCD_CTRL_SOFM_V(e) BF_LCD_CTRL_SOFM(BV_LCD_CTRL_SOFM__##e) +#define BFM_LCD_CTRL_SOFM_V(v) BM_LCD_CTRL_SOFM +#define BP_LCD_CTRL_IFUM 10 +#define BM_LCD_CTRL_IFUM 0x400 +#define BF_LCD_CTRL_IFUM(v) (((v) & 0x1) << 10) +#define BFM_LCD_CTRL_IFUM(v) BM_LCD_CTRL_IFUM +#define BF_LCD_CTRL_IFUM_V(e) BF_LCD_CTRL_IFUM(BV_LCD_CTRL_IFUM__##e) +#define BFM_LCD_CTRL_IFUM_V(v) BM_LCD_CTRL_IFUM +#define BP_LCD_CTRL_QDM 7 +#define BM_LCD_CTRL_QDM 0x80 +#define BF_LCD_CTRL_QDM(v) (((v) & 0x1) << 7) +#define BFM_LCD_CTRL_QDM(v) BM_LCD_CTRL_QDM +#define BF_LCD_CTRL_QDM_V(e) BF_LCD_CTRL_QDM(BV_LCD_CTRL_QDM__##e) +#define BFM_LCD_CTRL_QDM_V(v) BM_LCD_CTRL_QDM +#define BP_LCD_CTRL_BEDN 6 +#define BM_LCD_CTRL_BEDN 0x40 +#define BF_LCD_CTRL_BEDN(v) (((v) & 0x1) << 6) +#define BFM_LCD_CTRL_BEDN(v) BM_LCD_CTRL_BEDN +#define BF_LCD_CTRL_BEDN_V(e) BF_LCD_CTRL_BEDN(BV_LCD_CTRL_BEDN__##e) +#define BFM_LCD_CTRL_BEDN_V(v) BM_LCD_CTRL_BEDN +#define BP_LCD_CTRL_PEDN 5 +#define BM_LCD_CTRL_PEDN 0x20 +#define BF_LCD_CTRL_PEDN(v) (((v) & 0x1) << 5) +#define BFM_LCD_CTRL_PEDN(v) BM_LCD_CTRL_PEDN +#define BF_LCD_CTRL_PEDN_V(e) BF_LCD_CTRL_PEDN(BV_LCD_CTRL_PEDN__##e) +#define BFM_LCD_CTRL_PEDN_V(v) BM_LCD_CTRL_PEDN +#define BP_LCD_CTRL_ENABLE 3 +#define BM_LCD_CTRL_ENABLE 0x8 +#define BF_LCD_CTRL_ENABLE(v) (((v) & 0x1) << 3) +#define BFM_LCD_CTRL_ENABLE(v) BM_LCD_CTRL_ENABLE +#define BF_LCD_CTRL_ENABLE_V(e) BF_LCD_CTRL_ENABLE(BV_LCD_CTRL_ENABLE__##e) +#define BFM_LCD_CTRL_ENABLE_V(v) BM_LCD_CTRL_ENABLE + +#define REG_LCD_STATE jz_reg(LCD_STATE) +#define JA_LCD_STATE (0xb3050000 + 0x34) +#define JT_LCD_STATE JIO_32_RW +#define JN_LCD_STATE LCD_STATE +#define JI_LCD_STATE +#define BP_LCD_STATE_QD 7 +#define BM_LCD_STATE_QD 0x80 +#define BF_LCD_STATE_QD(v) (((v) & 0x1) << 7) +#define BFM_LCD_STATE_QD(v) BM_LCD_STATE_QD +#define BF_LCD_STATE_QD_V(e) BF_LCD_STATE_QD(BV_LCD_STATE_QD__##e) +#define BFM_LCD_STATE_QD_V(v) BM_LCD_STATE_QD +#define BP_LCD_STATE_EOF 5 +#define BM_LCD_STATE_EOF 0x20 +#define BF_LCD_STATE_EOF(v) (((v) & 0x1) << 5) +#define BFM_LCD_STATE_EOF(v) BM_LCD_STATE_EOF +#define BF_LCD_STATE_EOF_V(e) BF_LCD_STATE_EOF(BV_LCD_STATE_EOF__##e) +#define BFM_LCD_STATE_EOF_V(v) BM_LCD_STATE_EOF +#define BP_LCD_STATE_SOF 4 +#define BM_LCD_STATE_SOF 0x10 +#define BF_LCD_STATE_SOF(v) (((v) & 0x1) << 4) +#define BFM_LCD_STATE_SOF(v) BM_LCD_STATE_SOF +#define BF_LCD_STATE_SOF_V(e) BF_LCD_STATE_SOF(BV_LCD_STATE_SOF__##e) +#define BFM_LCD_STATE_SOF_V(v) BM_LCD_STATE_SOF +#define BP_LCD_STATE_IFU 2 +#define BM_LCD_STATE_IFU 0x4 +#define BF_LCD_STATE_IFU(v) (((v) & 0x1) << 2) +#define BFM_LCD_STATE_IFU(v) BM_LCD_STATE_IFU +#define BF_LCD_STATE_IFU_V(e) BF_LCD_STATE_IFU(BV_LCD_STATE_IFU__##e) +#define BFM_LCD_STATE_IFU_V(v) BM_LCD_STATE_IFU + +#define REG_LCD_OSDCTRL jz_reg(LCD_OSDCTRL) +#define JA_LCD_OSDCTRL (0xb3050000 + 0x104) +#define JT_LCD_OSDCTRL JIO_32_RW +#define JN_LCD_OSDCTRL LCD_OSDCTRL +#define JI_LCD_OSDCTRL + +#define REG_LCD_BGC jz_reg(LCD_BGC) +#define JA_LCD_BGC (0xb3050000 + 0x10c) +#define JT_LCD_BGC JIO_32_RW +#define JN_LCD_BGC LCD_BGC +#define JI_LCD_BGC + +#define REG_LCD_DAH jz_reg(LCD_DAH) +#define JA_LCD_DAH (0xb3050000 + 0x10) +#define JT_LCD_DAH JIO_32_RW +#define JN_LCD_DAH LCD_DAH +#define JI_LCD_DAH + +#define REG_LCD_DAV jz_reg(LCD_DAV) +#define JA_LCD_DAV (0xb3050000 + 0x14) +#define JT_LCD_DAV JIO_32_RW +#define JN_LCD_DAV LCD_DAV +#define JI_LCD_DAV + +#define REG_LCD_VAT jz_reg(LCD_VAT) +#define JA_LCD_VAT (0xb3050000 + 0xc) +#define JT_LCD_VAT JIO_32_RW +#define JN_LCD_VAT LCD_VAT +#define JI_LCD_VAT + +#define REG_LCD_VSYNC jz_reg(LCD_VSYNC) +#define JA_LCD_VSYNC (0xb3050000 + 0x4) +#define JT_LCD_VSYNC JIO_32_RW +#define JN_LCD_VSYNC LCD_VSYNC +#define JI_LCD_VSYNC + +#define REG_LCD_HSYNC jz_reg(LCD_HSYNC) +#define JA_LCD_HSYNC (0xb3050000 + 0x8) +#define JT_LCD_HSYNC JIO_32_RW +#define JN_LCD_HSYNC LCD_HSYNC +#define JI_LCD_HSYNC + +#define REG_LCD_IID jz_reg(LCD_IID) +#define JA_LCD_IID (0xb3050000 + 0x38) +#define JT_LCD_IID JIO_32_RW +#define JN_LCD_IID LCD_IID +#define JI_LCD_IID + +#define REG_LCD_DA jz_reg(LCD_DA) +#define JA_LCD_DA (0xb3050000 + 0x40) +#define JT_LCD_DA JIO_32_RW +#define JN_LCD_DA LCD_DA +#define JI_LCD_DA + +#define REG_LCD_MCFG jz_reg(LCD_MCFG) +#define JA_LCD_MCFG (0xb3050000 + 0xa0) +#define JT_LCD_MCFG JIO_32_RW +#define JN_LCD_MCFG LCD_MCFG +#define JI_LCD_MCFG +#define BP_LCD_MCFG_CWIDTH 8 +#define BM_LCD_MCFG_CWIDTH 0x300 +#define BV_LCD_MCFG_CWIDTH__16BIT_OR_9BIT 0x0 +#define BV_LCD_MCFG_CWIDTH__8BIT 0x1 +#define BV_LCD_MCFG_CWIDTH__18BIT 0x2 +#define BV_LCD_MCFG_CWIDTH__24BIT 0x3 +#define BF_LCD_MCFG_CWIDTH(v) (((v) & 0x3) << 8) +#define BFM_LCD_MCFG_CWIDTH(v) BM_LCD_MCFG_CWIDTH +#define BF_LCD_MCFG_CWIDTH_V(e) BF_LCD_MCFG_CWIDTH(BV_LCD_MCFG_CWIDTH__##e) +#define BFM_LCD_MCFG_CWIDTH_V(v) BM_LCD_MCFG_CWIDTH + +#define REG_LCD_MCFG_NEW jz_reg(LCD_MCFG_NEW) +#define JA_LCD_MCFG_NEW (0xb3050000 + 0xb8) +#define JT_LCD_MCFG_NEW JIO_32_RW +#define JN_LCD_MCFG_NEW LCD_MCFG_NEW +#define JI_LCD_MCFG_NEW +#define BP_LCD_MCFG_NEW_DWIDTH 13 +#define BM_LCD_MCFG_NEW_DWIDTH 0xe000 +#define BV_LCD_MCFG_NEW_DWIDTH__8BIT 0x0 +#define BV_LCD_MCFG_NEW_DWIDTH__9BIT 0x1 +#define BV_LCD_MCFG_NEW_DWIDTH__16BIT 0x2 +#define BV_LCD_MCFG_NEW_DWIDTH__18BIT 0x3 +#define BV_LCD_MCFG_NEW_DWIDTH__24BIT 0x4 +#define BF_LCD_MCFG_NEW_DWIDTH(v) (((v) & 0x7) << 13) +#define BFM_LCD_MCFG_NEW_DWIDTH(v) BM_LCD_MCFG_NEW_DWIDTH +#define BF_LCD_MCFG_NEW_DWIDTH_V(e) BF_LCD_MCFG_NEW_DWIDTH(BV_LCD_MCFG_NEW_DWIDTH__##e) +#define BFM_LCD_MCFG_NEW_DWIDTH_V(v) BM_LCD_MCFG_NEW_DWIDTH +#define BP_LCD_MCFG_NEW_DTIMES 8 +#define BM_LCD_MCFG_NEW_DTIMES 0x300 +#define BV_LCD_MCFG_NEW_DTIMES__1TIME 0x0 +#define BV_LCD_MCFG_NEW_DTIMES__2TIME 0x1 +#define BV_LCD_MCFG_NEW_DTIMES__3TIME 0x2 +#define BF_LCD_MCFG_NEW_DTIMES(v) (((v) & 0x3) << 8) +#define BFM_LCD_MCFG_NEW_DTIMES(v) BM_LCD_MCFG_NEW_DTIMES +#define BF_LCD_MCFG_NEW_DTIMES_V(e) BF_LCD_MCFG_NEW_DTIMES(BV_LCD_MCFG_NEW_DTIMES__##e) +#define BFM_LCD_MCFG_NEW_DTIMES_V(v) BM_LCD_MCFG_NEW_DTIMES +#define BP_LCD_MCFG_NEW_6800_MODE 11 +#define BM_LCD_MCFG_NEW_6800_MODE 0x800 +#define BF_LCD_MCFG_NEW_6800_MODE(v) (((v) & 0x1) << 11) +#define BFM_LCD_MCFG_NEW_6800_MODE(v) BM_LCD_MCFG_NEW_6800_MODE +#define BF_LCD_MCFG_NEW_6800_MODE_V(e) BF_LCD_MCFG_NEW_6800_MODE(BV_LCD_MCFG_NEW_6800_MODE__##e) +#define BFM_LCD_MCFG_NEW_6800_MODE_V(v) BM_LCD_MCFG_NEW_6800_MODE +#define BP_LCD_MCFG_NEW_CMD_9BIT 10 +#define BM_LCD_MCFG_NEW_CMD_9BIT 0x400 +#define BF_LCD_MCFG_NEW_CMD_9BIT(v) (((v) & 0x1) << 10) +#define BFM_LCD_MCFG_NEW_CMD_9BIT(v) BM_LCD_MCFG_NEW_CMD_9BIT +#define BF_LCD_MCFG_NEW_CMD_9BIT_V(e) BF_LCD_MCFG_NEW_CMD_9BIT(BV_LCD_MCFG_NEW_CMD_9BIT__##e) +#define BFM_LCD_MCFG_NEW_CMD_9BIT_V(v) BM_LCD_MCFG_NEW_CMD_9BIT +#define BP_LCD_MCFG_NEW_CSPLY 5 +#define BM_LCD_MCFG_NEW_CSPLY 0x20 +#define BF_LCD_MCFG_NEW_CSPLY(v) (((v) & 0x1) << 5) +#define BFM_LCD_MCFG_NEW_CSPLY(v) BM_LCD_MCFG_NEW_CSPLY +#define BF_LCD_MCFG_NEW_CSPLY_V(e) BF_LCD_MCFG_NEW_CSPLY(BV_LCD_MCFG_NEW_CSPLY__##e) +#define BFM_LCD_MCFG_NEW_CSPLY_V(v) BM_LCD_MCFG_NEW_CSPLY +#define BP_LCD_MCFG_NEW_RSPLY 4 +#define BM_LCD_MCFG_NEW_RSPLY 0x10 +#define BF_LCD_MCFG_NEW_RSPLY(v) (((v) & 0x1) << 4) +#define BFM_LCD_MCFG_NEW_RSPLY(v) BM_LCD_MCFG_NEW_RSPLY +#define BF_LCD_MCFG_NEW_RSPLY_V(e) BF_LCD_MCFG_NEW_RSPLY(BV_LCD_MCFG_NEW_RSPLY__##e) +#define BFM_LCD_MCFG_NEW_RSPLY_V(v) BM_LCD_MCFG_NEW_RSPLY +#define BP_LCD_MCFG_NEW_CLKPLY 3 +#define BM_LCD_MCFG_NEW_CLKPLY 0x8 +#define BF_LCD_MCFG_NEW_CLKPLY(v) (((v) & 0x1) << 3) +#define BFM_LCD_MCFG_NEW_CLKPLY(v) BM_LCD_MCFG_NEW_CLKPLY +#define BF_LCD_MCFG_NEW_CLKPLY_V(e) BF_LCD_MCFG_NEW_CLKPLY(BV_LCD_MCFG_NEW_CLKPLY__##e) +#define BFM_LCD_MCFG_NEW_CLKPLY_V(v) BM_LCD_MCFG_NEW_CLKPLY +#define BP_LCD_MCFG_NEW_DTYPE 2 +#define BM_LCD_MCFG_NEW_DTYPE 0x4 +#define BV_LCD_MCFG_NEW_DTYPE__SERIAL 0x1 +#define BV_LCD_MCFG_NEW_DTYPE__PARALLEL 0x0 +#define BF_LCD_MCFG_NEW_DTYPE(v) (((v) & 0x1) << 2) +#define BFM_LCD_MCFG_NEW_DTYPE(v) BM_LCD_MCFG_NEW_DTYPE +#define BF_LCD_MCFG_NEW_DTYPE_V(e) BF_LCD_MCFG_NEW_DTYPE(BV_LCD_MCFG_NEW_DTYPE__##e) +#define BFM_LCD_MCFG_NEW_DTYPE_V(v) BM_LCD_MCFG_NEW_DTYPE +#define BP_LCD_MCFG_NEW_CTYPE 1 +#define BM_LCD_MCFG_NEW_CTYPE 0x2 +#define BV_LCD_MCFG_NEW_CTYPE__SERIAL 0x1 +#define BV_LCD_MCFG_NEW_CTYPE__PARALLEL 0x0 +#define BF_LCD_MCFG_NEW_CTYPE(v) (((v) & 0x1) << 1) +#define BFM_LCD_MCFG_NEW_CTYPE(v) BM_LCD_MCFG_NEW_CTYPE +#define BF_LCD_MCFG_NEW_CTYPE_V(e) BF_LCD_MCFG_NEW_CTYPE(BV_LCD_MCFG_NEW_CTYPE__##e) +#define BFM_LCD_MCFG_NEW_CTYPE_V(v) BM_LCD_MCFG_NEW_CTYPE +#define BP_LCD_MCFG_NEW_FMT_CONV 0 +#define BM_LCD_MCFG_NEW_FMT_CONV 0x1 +#define BF_LCD_MCFG_NEW_FMT_CONV(v) (((v) & 0x1) << 0) +#define BFM_LCD_MCFG_NEW_FMT_CONV(v) BM_LCD_MCFG_NEW_FMT_CONV +#define BF_LCD_MCFG_NEW_FMT_CONV_V(e) BF_LCD_MCFG_NEW_FMT_CONV(BV_LCD_MCFG_NEW_FMT_CONV__##e) +#define BFM_LCD_MCFG_NEW_FMT_CONV_V(v) BM_LCD_MCFG_NEW_FMT_CONV + +#define REG_LCD_MCTRL jz_reg(LCD_MCTRL) +#define JA_LCD_MCTRL (0xb3050000 + 0xa4) +#define JT_LCD_MCTRL JIO_32_RW +#define JN_LCD_MCTRL LCD_MCTRL +#define JI_LCD_MCTRL +#define BP_LCD_MCTRL_NARROW_TE 10 +#define BM_LCD_MCTRL_NARROW_TE 0x400 +#define BF_LCD_MCTRL_NARROW_TE(v) (((v) & 0x1) << 10) +#define BFM_LCD_MCTRL_NARROW_TE(v) BM_LCD_MCTRL_NARROW_TE +#define BF_LCD_MCTRL_NARROW_TE_V(e) BF_LCD_MCTRL_NARROW_TE(BV_LCD_MCTRL_NARROW_TE__##e) +#define BFM_LCD_MCTRL_NARROW_TE_V(v) BM_LCD_MCTRL_NARROW_TE +#define BP_LCD_MCTRL_TE_INV 9 +#define BM_LCD_MCTRL_TE_INV 0x200 +#define BF_LCD_MCTRL_TE_INV(v) (((v) & 0x1) << 9) +#define BFM_LCD_MCTRL_TE_INV(v) BM_LCD_MCTRL_TE_INV +#define BF_LCD_MCTRL_TE_INV_V(e) BF_LCD_MCTRL_TE_INV(BV_LCD_MCTRL_TE_INV__##e) +#define BFM_LCD_MCTRL_TE_INV_V(v) BM_LCD_MCTRL_TE_INV +#define BP_LCD_MCTRL_NOT_USE_TE 8 +#define BM_LCD_MCTRL_NOT_USE_TE 0x100 +#define BF_LCD_MCTRL_NOT_USE_TE(v) (((v) & 0x1) << 8) +#define BFM_LCD_MCTRL_NOT_USE_TE(v) BM_LCD_MCTRL_NOT_USE_TE +#define BF_LCD_MCTRL_NOT_USE_TE_V(e) BF_LCD_MCTRL_NOT_USE_TE(BV_LCD_MCTRL_NOT_USE_TE__##e) +#define BFM_LCD_MCTRL_NOT_USE_TE_V(v) BM_LCD_MCTRL_NOT_USE_TE +#define BP_LCD_MCTRL_DCSI_SEL 7 +#define BM_LCD_MCTRL_DCSI_SEL 0x80 +#define BF_LCD_MCTRL_DCSI_SEL(v) (((v) & 0x1) << 7) +#define BFM_LCD_MCTRL_DCSI_SEL(v) BM_LCD_MCTRL_DCSI_SEL +#define BF_LCD_MCTRL_DCSI_SEL_V(e) BF_LCD_MCTRL_DCSI_SEL(BV_LCD_MCTRL_DCSI_SEL__##e) +#define BFM_LCD_MCTRL_DCSI_SEL_V(v) BM_LCD_MCTRL_DCSI_SEL +#define BP_LCD_MCTRL_MIPI_SLCD 6 +#define BM_LCD_MCTRL_MIPI_SLCD 0x40 +#define BF_LCD_MCTRL_MIPI_SLCD(v) (((v) & 0x1) << 6) +#define BFM_LCD_MCTRL_MIPI_SLCD(v) BM_LCD_MCTRL_MIPI_SLCD +#define BF_LCD_MCTRL_MIPI_SLCD_V(e) BF_LCD_MCTRL_MIPI_SLCD(BV_LCD_MCTRL_MIPI_SLCD__##e) +#define BFM_LCD_MCTRL_MIPI_SLCD_V(v) BM_LCD_MCTRL_MIPI_SLCD +#define BP_LCD_MCTRL_FAST_MODE 4 +#define BM_LCD_MCTRL_FAST_MODE 0x10 +#define BF_LCD_MCTRL_FAST_MODE(v) (((v) & 0x1) << 4) +#define BFM_LCD_MCTRL_FAST_MODE(v) BM_LCD_MCTRL_FAST_MODE +#define BF_LCD_MCTRL_FAST_MODE_V(e) BF_LCD_MCTRL_FAST_MODE(BV_LCD_MCTRL_FAST_MODE__##e) +#define BFM_LCD_MCTRL_FAST_MODE_V(v) BM_LCD_MCTRL_FAST_MODE +#define BP_LCD_MCTRL_GATE_MASK 3 +#define BM_LCD_MCTRL_GATE_MASK 0x8 +#define BF_LCD_MCTRL_GATE_MASK(v) (((v) & 0x1) << 3) +#define BFM_LCD_MCTRL_GATE_MASK(v) BM_LCD_MCTRL_GATE_MASK +#define BF_LCD_MCTRL_GATE_MASK_V(e) BF_LCD_MCTRL_GATE_MASK(BV_LCD_MCTRL_GATE_MASK__##e) +#define BFM_LCD_MCTRL_GATE_MASK_V(v) BM_LCD_MCTRL_GATE_MASK +#define BP_LCD_MCTRL_DMA_MODE 2 +#define BM_LCD_MCTRL_DMA_MODE 0x4 +#define BF_LCD_MCTRL_DMA_MODE(v) (((v) & 0x1) << 2) +#define BFM_LCD_MCTRL_DMA_MODE(v) BM_LCD_MCTRL_DMA_MODE +#define BF_LCD_MCTRL_DMA_MODE_V(e) BF_LCD_MCTRL_DMA_MODE(BV_LCD_MCTRL_DMA_MODE__##e) +#define BFM_LCD_MCTRL_DMA_MODE_V(v) BM_LCD_MCTRL_DMA_MODE +#define BP_LCD_MCTRL_DMA_START 1 +#define BM_LCD_MCTRL_DMA_START 0x2 +#define BF_LCD_MCTRL_DMA_START(v) (((v) & 0x1) << 1) +#define BFM_LCD_MCTRL_DMA_START(v) BM_LCD_MCTRL_DMA_START +#define BF_LCD_MCTRL_DMA_START_V(e) BF_LCD_MCTRL_DMA_START(BV_LCD_MCTRL_DMA_START__##e) +#define BFM_LCD_MCTRL_DMA_START_V(v) BM_LCD_MCTRL_DMA_START +#define BP_LCD_MCTRL_DMA_TX_EN 0 +#define BM_LCD_MCTRL_DMA_TX_EN 0x1 +#define BF_LCD_MCTRL_DMA_TX_EN(v) (((v) & 0x1) << 0) +#define BFM_LCD_MCTRL_DMA_TX_EN(v) BM_LCD_MCTRL_DMA_TX_EN +#define BF_LCD_MCTRL_DMA_TX_EN_V(e) BF_LCD_MCTRL_DMA_TX_EN(BV_LCD_MCTRL_DMA_TX_EN__##e) +#define BFM_LCD_MCTRL_DMA_TX_EN_V(v) BM_LCD_MCTRL_DMA_TX_EN + +#define REG_LCD_MSTATE jz_reg(LCD_MSTATE) +#define JA_LCD_MSTATE (0xb3050000 + 0xa8) +#define JT_LCD_MSTATE JIO_32_RW +#define JN_LCD_MSTATE LCD_MSTATE +#define JI_LCD_MSTATE +#define BP_LCD_MSTATE_LCD_ID 16 +#define BM_LCD_MSTATE_LCD_ID 0xffff0000 +#define BF_LCD_MSTATE_LCD_ID(v) (((v) & 0xffff) << 16) +#define BFM_LCD_MSTATE_LCD_ID(v) BM_LCD_MSTATE_LCD_ID +#define BF_LCD_MSTATE_LCD_ID_V(e) BF_LCD_MSTATE_LCD_ID(BV_LCD_MSTATE_LCD_ID__##e) +#define BFM_LCD_MSTATE_LCD_ID_V(v) BM_LCD_MSTATE_LCD_ID +#define BP_LCD_MSTATE_BUSY 0 +#define BM_LCD_MSTATE_BUSY 0x1 +#define BF_LCD_MSTATE_BUSY(v) (((v) & 0x1) << 0) +#define BFM_LCD_MSTATE_BUSY(v) BM_LCD_MSTATE_BUSY +#define BF_LCD_MSTATE_BUSY_V(e) BF_LCD_MSTATE_BUSY(BV_LCD_MSTATE_BUSY__##e) +#define BFM_LCD_MSTATE_BUSY_V(v) BM_LCD_MSTATE_BUSY + +#define REG_LCD_MDATA jz_reg(LCD_MDATA) +#define JA_LCD_MDATA (0xb3050000 + 0xac) +#define JT_LCD_MDATA JIO_32_RW +#define JN_LCD_MDATA LCD_MDATA +#define JI_LCD_MDATA +#define BP_LCD_MDATA_TYPE 30 +#define BM_LCD_MDATA_TYPE 0xc0000000 +#define BV_LCD_MDATA_TYPE__CMD 0x1 +#define BV_LCD_MDATA_TYPE__DAT 0x0 +#define BF_LCD_MDATA_TYPE(v) (((v) & 0x3) << 30) +#define BFM_LCD_MDATA_TYPE(v) BM_LCD_MDATA_TYPE +#define BF_LCD_MDATA_TYPE_V(e) BF_LCD_MDATA_TYPE(BV_LCD_MDATA_TYPE__##e) +#define BFM_LCD_MDATA_TYPE_V(v) BM_LCD_MDATA_TYPE +#define BP_LCD_MDATA_DATA 0 +#define BM_LCD_MDATA_DATA 0xffffff +#define BF_LCD_MDATA_DATA(v) (((v) & 0xffffff) << 0) +#define BFM_LCD_MDATA_DATA(v) BM_LCD_MDATA_DATA +#define BF_LCD_MDATA_DATA_V(e) BF_LCD_MDATA_DATA(BV_LCD_MDATA_DATA__##e) +#define BFM_LCD_MDATA_DATA_V(v) BM_LCD_MDATA_DATA + +#define REG_LCD_WTIME jz_reg(LCD_WTIME) +#define JA_LCD_WTIME (0xb3050000 + 0xb0) +#define JT_LCD_WTIME JIO_32_RW +#define JN_LCD_WTIME LCD_WTIME +#define JI_LCD_WTIME +#define BP_LCD_WTIME_DHTIME 24 +#define BM_LCD_WTIME_DHTIME 0xff000000 +#define BF_LCD_WTIME_DHTIME(v) (((v) & 0xff) << 24) +#define BFM_LCD_WTIME_DHTIME(v) BM_LCD_WTIME_DHTIME +#define BF_LCD_WTIME_DHTIME_V(e) BF_LCD_WTIME_DHTIME(BV_LCD_WTIME_DHTIME__##e) +#define BFM_LCD_WTIME_DHTIME_V(v) BM_LCD_WTIME_DHTIME +#define BP_LCD_WTIME_DLTIME 16 +#define BM_LCD_WTIME_DLTIME 0xff0000 +#define BF_LCD_WTIME_DLTIME(v) (((v) & 0xff) << 16) +#define BFM_LCD_WTIME_DLTIME(v) BM_LCD_WTIME_DLTIME +#define BF_LCD_WTIME_DLTIME_V(e) BF_LCD_WTIME_DLTIME(BV_LCD_WTIME_DLTIME__##e) +#define BFM_LCD_WTIME_DLTIME_V(v) BM_LCD_WTIME_DLTIME +#define BP_LCD_WTIME_CHTIME 8 +#define BM_LCD_WTIME_CHTIME 0xff00 +#define BF_LCD_WTIME_CHTIME(v) (((v) & 0xff) << 8) +#define BFM_LCD_WTIME_CHTIME(v) BM_LCD_WTIME_CHTIME +#define BF_LCD_WTIME_CHTIME_V(e) BF_LCD_WTIME_CHTIME(BV_LCD_WTIME_CHTIME__##e) +#define BFM_LCD_WTIME_CHTIME_V(v) BM_LCD_WTIME_CHTIME +#define BP_LCD_WTIME_CLTIME 0 +#define BM_LCD_WTIME_CLTIME 0xff +#define BF_LCD_WTIME_CLTIME(v) (((v) & 0xff) << 0) +#define BFM_LCD_WTIME_CLTIME(v) BM_LCD_WTIME_CLTIME +#define BF_LCD_WTIME_CLTIME_V(e) BF_LCD_WTIME_CLTIME(BV_LCD_WTIME_CLTIME__##e) +#define BFM_LCD_WTIME_CLTIME_V(v) BM_LCD_WTIME_CLTIME + +#define REG_LCD_TASH jz_reg(LCD_TASH) +#define JA_LCD_TASH (0xb3050000 + 0xb4) +#define JT_LCD_TASH JIO_32_RW +#define JN_LCD_TASH LCD_TASH +#define JI_LCD_TASH +#define BP_LCD_TASH_TAH 8 +#define BM_LCD_TASH_TAH 0xff00 +#define BF_LCD_TASH_TAH(v) (((v) & 0xff) << 8) +#define BFM_LCD_TASH_TAH(v) BM_LCD_TASH_TAH +#define BF_LCD_TASH_TAH_V(e) BF_LCD_TASH_TAH(BV_LCD_TASH_TAH__##e) +#define BFM_LCD_TASH_TAH_V(v) BM_LCD_TASH_TAH +#define BP_LCD_TASH_TAS 0 +#define BM_LCD_TASH_TAS 0xff +#define BF_LCD_TASH_TAS(v) (((v) & 0xff) << 0) +#define BFM_LCD_TASH_TAS(v) BM_LCD_TASH_TAS +#define BF_LCD_TASH_TAS_V(e) BF_LCD_TASH_TAS(BV_LCD_TASH_TAS__##e) +#define BFM_LCD_TASH_TAS_V(v) BM_LCD_TASH_TAS + +#define REG_LCD_SMWT jz_reg(LCD_SMWT) +#define JA_LCD_SMWT (0xb3050000 + 0xbc) +#define JT_LCD_SMWT JIO_32_RW +#define JN_LCD_SMWT LCD_SMWT +#define JI_LCD_SMWT + +#endif /* __HEADERGEN_LCD_H__*/ diff --git a/firmware/target/mips/ingenic_x1000/x1000/macro.h b/firmware/target/mips/ingenic_x1000/x1000/macro.h new file mode 100644 index 0000000000..bfe8708a91 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/x1000/macro.h @@ -0,0 +1,356 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * This file was automatically generated by headergen, DO NOT EDIT it. + * headergen version: 3.0.0 + * + * Copyright (C) 2015 by the authors + * + * 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 __HEADERGEN_MACRO_H__ +#define __HEADERGEN_MACRO_H__ + +#include <stdint.h> + +#define __VAR_OR1(prefix, suffix) \ + (prefix##suffix) +#define __VAR_OR2(pre, s1, s2) \ + (__VAR_OR1(pre, s1) | __VAR_OR1(pre, s2)) +#define __VAR_OR3(pre, s1, s2, s3) \ + (__VAR_OR1(pre, s1) | __VAR_OR2(pre, s2, s3)) +#define __VAR_OR4(pre, s1, s2, s3, s4) \ + (__VAR_OR2(pre, s1, s2) | __VAR_OR2(pre, s3, s4)) +#define __VAR_OR5(pre, s1, s2, s3, s4, s5) \ + (__VAR_OR2(pre, s1, s2) | __VAR_OR3(pre, s3, s4, s5)) +#define __VAR_OR6(pre, s1, s2, s3, s4, s5, s6) \ + (__VAR_OR3(pre, s1, s2, s3) | __VAR_OR3(pre, s4, s5, s6)) +#define __VAR_OR7(pre, s1, s2, s3, s4, s5, s6, s7) \ + (__VAR_OR3(pre, s1, s2, s3) | __VAR_OR4(pre, s4, s5, s6, s7)) +#define __VAR_OR8(pre, s1, s2, s3, s4, s5, s6, s7, s8) \ + (__VAR_OR4(pre, s1, s2, s3, s4) | __VAR_OR4(pre, s5, s6, s7, s8)) +#define __VAR_OR9(pre, s1, s2, s3, s4, s5, s6, s7, s8, s9) \ + (__VAR_OR4(pre, s1, s2, s3, s4) | __VAR_OR5(pre, s5, s6, s7, s8, s9)) +#define __VAR_OR10(pre, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10) \ + (__VAR_OR5(pre, s1, s2, s3, s4, s5) | __VAR_OR5(pre, s6, s7, s8, s9, s10)) +#define __VAR_OR11(pre, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11) \ + (__VAR_OR5(pre, s1, s2, s3, s4, s5) | __VAR_OR6(pre, s6, s7, s8, s9, s10, s11)) +#define __VAR_OR12(pre, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12) \ + (__VAR_OR6(pre, s1, s2, s3, s4, s5, s6) | __VAR_OR6(pre, s7, s8, s9, s10, s11, s12)) +#define __VAR_OR13(pre, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13) \ + (__VAR_OR6(pre, s1, s2, s3, s4, s5, s6) | __VAR_OR7(pre, s7, s8, s9, s10, s11, s12, s13)) + +#define __VAR_NARGS(...) __VAR_NARGS_(__VA_ARGS__, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1) +#define __VAR_NARGS_(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, N, ...) N + +#define __VAR_EXPAND(macro, prefix, ...) __VAR_EXPAND_(macro, __VAR_NARGS(__VA_ARGS__), prefix, __VA_ARGS__) +#define __VAR_EXPAND_(macro, cnt, prefix, ...) __VAR_EXPAND__(macro, cnt, prefix, __VA_ARGS__) +#define __VAR_EXPAND__(macro, cnt, prefix, ...) __VAR_EXPAND___(macro##cnt, prefix, __VA_ARGS__) +#define __VAR_EXPAND___(macro, prefix, ...) macro(prefix, __VA_ARGS__) + +#define JIO_8_RO(op, name, ...) JIO_8_RO_##op(name, __VA_ARGS__) +#define JIO_8_RO_RD(name, ...) (*(const volatile uint8_t *)(JA_##name)) +#define JIO_8_RO_WR(name, val) _Static_assert(0, #name " is read-only") +#define JIO_8_RO_RMW(name, vand, vor) _Static_assert(0, #name " is read-only") +#define JIO_8_RO_VAR(name, ...) (*(const volatile uint8_t *)(JA_##name)) + +#define JIO_16_RO(op, name, ...) JIO_16_RO_##op(name, __VA_ARGS__) +#define JIO_16_RO_RD(name, ...) (*(const volatile uint16_t *)(JA_##name)) +#define JIO_16_RO_WR(name, val) _Static_assert(0, #name " is read-only") +#define JIO_16_RO_RMW(name, vand, vor) _Static_assert(0, #name " is read-only") +#define JIO_16_RO_VAR(name, ...) (*(const volatile uint16_t *)(JA_##name)) + +#define JIO_32_RO(op, name, ...) JIO_32_RO_##op(name, __VA_ARGS__) +#define JIO_32_RO_RD(name, ...) (*(const volatile uint32_t *)(JA_##name)) +#define JIO_32_RO_WR(name, val) _Static_assert(0, #name " is read-only") +#define JIO_32_RO_RMW(name, vand, vor) _Static_assert(0, #name " is read-only") +#define JIO_32_RO_VAR(name, ...) (*(const volatile uint32_t *)(JA_##name)) + +#define JIO_8_RW(op, name, ...) JIO_8_RW_##op(name, __VA_ARGS__) +#define JIO_8_RW_RD(name, ...) (*(volatile uint8_t *)(JA_##name)) +#define JIO_8_RW_WR(name, val) (*(volatile uint8_t *)(JA_##name)) = (val) +#define JIO_8_RW_RMW(name, vand, vor) JIO_8_RW_WR(name, (JIO_8_RW_RD(name) & (vand)) | (vor)) +#define JIO_8_RW_VAR(name, ...) (*(volatile uint8_t *)(JA_##name)) + +#define JIO_16_RW(op, name, ...) JIO_16_RW_##op(name, __VA_ARGS__) +#define JIO_16_RW_RD(name, ...) (*(volatile uint16_t *)(JA_##name)) +#define JIO_16_RW_WR(name, val) (*(volatile uint16_t *)(JA_##name)) = (val) +#define JIO_16_RW_RMW(name, vand, vor) JIO_16_RW_WR(name, (JIO_16_RW_RD(name) & (vand)) | (vor)) +#define JIO_16_RW_VAR(name, ...) (*(volatile uint16_t *)(JA_##name)) + +#define JIO_32_RW(op, name, ...) JIO_32_RW_##op(name, __VA_ARGS__) +#define JIO_32_RW_RD(name, ...) (*(volatile uint32_t *)(JA_##name)) +#define JIO_32_RW_WR(name, val) (*(volatile uint32_t *)(JA_##name)) = (val) +#define JIO_32_RW_RMW(name, vand, vor) JIO_32_RW_WR(name, (JIO_32_RW_RD(name) & (vand)) | (vor)) +#define JIO_32_RW_VAR(name, ...) (*(volatile uint32_t *)(JA_##name)) + +#define JIO_8_WO(op, name, ...) JIO_8_WO_##op(name, __VA_ARGS__) +#define JIO_8_WO_RD(name, ...) ({_Static_assert(0, #name " is write-only"); 0;}) +#define JIO_8_WO_WR(name, val) (*(volatile uint8_t *)(JA_##name)) = (val) +#define JIO_8_WO_RMW(name, vand, vor) JIO_8_WO_WR(name, vor) +#define JIO_8_WO_VAR(name, ...) (*(volatile uint8_t *)(JA_##name)) + +#define JIO_16_WO(op, name, ...) JIO_16_WO_##op(name, __VA_ARGS__) +#define JIO_16_WO_RD(name, ...) ({_Static_assert(0, #name " is write-only"); 0;}) +#define JIO_16_WO_WR(name, val) (*(volatile uint16_t *)(JA_##name)) = (val) +#define JIO_16_WO_RMW(name, vand, vor) JIO_16_WO_WR(name, vor) +#define JIO_16_WO_VAR(name, ...) (*(volatile uint16_t *)(JA_##name)) + +#define JIO_32_WO(op, name, ...) JIO_32_WO_##op(name, __VA_ARGS__) +#define JIO_32_WO_RD(name, ...) ({_Static_assert(0, #name " is write-only"); 0;}) +#define JIO_32_WO_WR(name, val) (*(volatile uint32_t *)(JA_##name)) = (val) +#define JIO_32_WO_RMW(name, vand, vor) JIO_32_WO_WR(name, vor) +#define JIO_32_WO_VAR(name, ...) (*(volatile uint32_t *)(JA_##name)) + + +/** __jz_variant + * + * usage: __jz_variant(register, variant_prefix, variant_postfix) + * + * effect: expands to register variant given as argument + * note: internal usage + * note: register must be fully qualified if indexed + * + * example: __jz_variant(ICOLL_CTRL, , _SET) + * example: __jz_variant(ICOLL_ENABLE(3), , _CLR) + */ +#define __jz_variant(name, varp, vars) __jz_variant_(JN_##name, JI_##name, varp, vars) +#define __jz_variant_(...) __jz_variant__(__VA_ARGS__) +#define __jz_variant__(name, index, varp, vars) varp##name##vars index + +/** jz_orf + * + * usage: jz_orf(register, f1(v1), f2(v2), ...) + * + * effect: expands to the register value where each field fi has value vi. + * Informally: reg_f1(v1) | reg_f2(v2) | ... + * note: enumerated values for fields can be obtained by using the syntax: + * f1_V(name) + * + * example: jz_orf(ICOLL_CTRL, SFTRST(1), CLKGATE(0), TZ_LOCK_V(UNLOCKED)) + */ +#define jz_orf(reg, ...) __VAR_EXPAND(__VAR_OR, BF_##reg##_, __VA_ARGS__) + +/** __jz_orfm + * + * usage: __jz_orfm(register, f1(v1), f2(v2), ...) + * + * effect: expands to the register value where each field fi has maximum value (vi is ignored). + * note: internal usage + * + * example: __jz_orfm(ICOLL_CTRL, SFTRST(1), CLKGATE(0), TZ_LOCK_V(UNLOCKED)) + */ +#define __jz_orfm(reg, ...) __VAR_EXPAND(__VAR_OR, BFM_##reg##_, __VA_ARGS__) + +/** jz_orm + * + * usage: jz_orm(register, f1, f2, ...) + * + * effect: expands to the register value where each field fi is set to its maximum value. + * Informally: reg_f1_mask | reg_f2_mask | ... + * + * example: jz_orm(ICOLL_CTRL, SFTRST, CLKGATE) + */ +#define jz_orm(reg, ...) __VAR_EXPAND(__VAR_OR, BM_##reg##_, __VA_ARGS__) + + +/** jz_read + * + * usage: jz_read(register) + * + * effect: read a register and return its value + * note: register must be fully qualified if indexed + * + * example: jz_read(ICOLL_STATUS) + * jz_read(ICOLL_ENABLE(42)) + */ +#define jz_read(name) JT_##name(RD, name) + +/** jz_vreadf + * + * usage: jz_vreadf(value, register, field) + * + * effect: given a register value, return the value of a particular field + * note: this macro does NOT read any register + * + * example: jz_vreadf(0xc0000000, ICOLL_CTRL, SFTRST) + * jz_vreadf(0x46ff, ICOLL_ENABLE, CPU0_PRIO) + */ +#define jz_vreadf(val, name, field) (((val) & BM_##name##_##field) >> BP_##name##_##field) + +/** jz_readf + * + * usage: jz_readf(register, field) + * + * effect: read a register and return the value of a particular field + * note: register must be fully qualified if indexed + * + * example: jz_readf(ICOLL_CTRL, SFTRST) + * jz_readf(ICOLL_ENABLE(3), CPU0_PRIO) + */ +#define jz_readf(name, field) jz_readf_(jz_read(name), JN_##name, field) +#define jz_readf_(...) jz_vreadf(__VA_ARGS__) + +/** jz_write + * + * usage: jz_write(register, value) + * + * effect: write a register + * note: register must be fully qualified if indexed + * + * example: jz_write(ICOLL_CTRL, 0x42) + * jz_write(ICOLL_ENABLE_SET(3), 0x37) + */ +#define jz_write(name, val) JT_##name(WR, name, val) + +/** jz_writef + * + * usage: jz_writef(register, f1(v1), f2(v2), ...) + * + * effect: change the register value so that field fi has value vi + * note: register must be fully qualified if indexed + * note: this macro may perform a read-modify-write + * + * example: jz_writef(ICOLL_CTRL, SFTRST(1), CLKGATE(0), TZ_LOCK_V(UNLOCKED)) + * jz_writef(ICOLL_ENABLE(3), CPU0_PRIO(1), CPU0_TYPE_V(FIQ)) + */ +#define jz_writef(name, ...) jz_writef_(name, JN_##name, __VA_ARGS__) +#define jz_writef_(name, name2, ...) JT_##name(RMW, name, ~__jz_orfm(name2, __VA_ARGS__), jz_orf(name2, __VA_ARGS__)) + +/** jz_overwritef + * + * usage: jz_overwritef(register, f1(v1), f2(v2), ...) + * + * effect: change the register value so that field fi has value vi and other fields have value zero + * thus this macro is equivalent to: + * jz_write(register, jz_orf(register, f1(v1), ...)) + * note: register must be fully qualified if indexed + * note: this macro will overwrite the register (it is NOT a read-modify-write) + * + * example: jz_overwritef(ICOLL_CTRL, SFTRST(1), CLKGATE(0), TZ_LOCK_V(UNLOCKED)) + * jz_overwritef(ICOLL_ENABLE(3), CPU0_PRIO(1), CPU0_TYPE_V(FIQ)) + */ +#define jz_overwritef(name, ...) jz_overwritef_(name, JN_##name, __VA_ARGS__) +#define jz_overwritef_(name, name2, ...) JT_##name(WR, name, jz_orf(name2, __VA_ARGS__)) + +/** jz_vwritef + * + * usage: jz_vwritef(var, register, f1(v1), f2(v2), ...) + * + * effect: change the variable value so that field fi has value vi + * note: this macro will perform a read-modify-write + * + * example: jz_vwritef(var, ICOLL_CTRL, SFTRST(1), CLKGATE(0), TZ_LOCK_V(UNLOCKED)) + * jz_vwritef(var, ICOLL_ENABLE, CPU0_PRIO(1), CPU0_TYPE_V(FIQ)) + */ +#define jz_vwritef(var, name, ...) (var) = jz_orf(name, __VA_ARGS__) | (~__jz_orfm(name, __VA_ARGS__) & (var)) + +/** jz_setf + * + * usage: jz_setf(register, f1, f2, ...) + * + * effect: change the register value so that field fi has maximum value + * IMPORTANT: this macro performs a write to the set variant of the register + * note: register must be fully qualified if indexed + * + * example: jz_setf(ICOLL_CTRL, SFTRST, CLKGATE) + * jz_setf(ICOLL_ENABLE(3), CPU0_PRIO, CPU0_TYPE) + */ +#define jz_setf(name, ...) jz_setf_(__jz_variant(name, , _SET), JN_##name, __VA_ARGS__) +#define jz_setf_(name, name2, ...) jz_write(name, jz_orm(name2, __VA_ARGS__)) + +/** jz_clrf + * + * usage: jz_clrf(register, f1, f2, ...) + * + * effect: change the register value so that field fi has value zero + * IMPORTANT: this macro performs a write to the clr variant of the register + * note: register must be fully qualified if indexed + * + * example: jz_clrf(ICOLL_CTRL, SFTRST, CLKGATE) + * jz_clrf(ICOLL_ENABLE(3), CPU0_PRIO, CPU0_TYPE) + */ +#define jz_clrf(name, ...) jz_clrf_(__jz_variant(name, , _CLR), JN_##name, __VA_ARGS__) +#define jz_clrf_(name, name2, ...) jz_write(name, jz_orm(name2, __VA_ARGS__)) + +/** jz_set + * + * usage: jz_set(register, set_value) + * + * effect: set some bits using set variant + * note: register must be fully qualified if indexed + * + * example: jz_set(ICOLL_CTRL, 0x42) + * jz_set(ICOLL_ENABLE(3), 0x37) + */ +#define jz_set(name, sval) jz_set_(__jz_variant(name, , _SET), sval) +#define jz_set_(sname, sval) jz_write(sname, sval) + +/** jz_clr + * + * usage: jz_clr(register, clr_value) + * + * effect: clear some bits using clr variant + * note: register must be fully qualified if indexed + * + * example: jz_clr(ICOLL_CTRL, 0x42) + * jz_clr(ICOLL_ENABLE(3), 0x37) + */ +#define jz_clr(name, cval) jz_clr_(__jz_variant(name, , _CLR), cval) +#define jz_clr_(cname, cval) jz_write(cname, cval) + +/** jz_cs + * + * usage: jz_cs(register, clear_value, set_value) + * + * effect: clear some bits using clr variant and then set some using set variant + * note: register must be fully qualified if indexed + * + * example: jz_cs(ICOLL_CTRL, 0xff, 0x42) + * jz_cs(ICOLL_ENABLE(3), 0xff, 0x37) + */ +#define jz_cs(name, cval, sval) jz_cs_(__jz_variant(name, , _CLR), __jz_variant(name, , _SET), cval, sval) +#define jz_cs_(cname, sname, cval, sval) do { jz_write(cname, cval); jz_write(sname, sval); } while(0) + +/** jz_csf + * + * usage: jz_csf(register, f1(v1), f2(v2), ...) + * + * effect: change the register value so that field fi has value vi using clr and set variants + * note: register must be fully qualified if indexed + * note: this macro will NOT perform a read-modify-write and is thus safer + * IMPORTANT: this macro will set some fields to 0 temporarily, make sure this is acceptable + * + * example: jz_csf(ICOLL_CTRL, SFTRST(1), CLKGATE(0), TZ_LOCK_V(UNLOCKED)) + * jz_csf(ICOLL_ENABLE(3), CPU0_PRIO(1), CPU0_TYPE_V(FIQ)) + */ +#define jz_csf(name, ...) jz_csf_(name, JN_##name, __VA_ARGS__) +#define jz_csf_(name, name2, ...) jz_cs(name, __jz_orfm(name2, __VA_ARGS__), jz_orf(name2, __VA_ARGS__)) + +/** jz_reg + * + * usage: jz_reg(register) + * + * effect: return a variable-like expression that can be read/written + * note: register must be fully qualified if indexed + * note: read-only registers will yield a constant expression + * + * example: unsigned x = jz_reg(ICOLL_STATUS) + * unsigned x = jz_reg(ICOLL_ENABLE(42)) + * jz_reg(ICOLL_ENABLE(42)) = 64 + */ +#define jz_reg(name) JT_##name(VAR, name) + + +#endif /* __HEADERGEN_MACRO_H__*/ diff --git a/firmware/target/mips/ingenic_x1000/x1000/msc.h b/firmware/target/mips/ingenic_x1000/x1000/msc.h new file mode 100644 index 0000000000..762b4b1461 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/x1000/msc.h @@ -0,0 +1,824 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * This file was automatically generated by headergen, DO NOT EDIT it. + * headergen version: 3.0.0 + * x1000 version: 1.0 + * x1000 authors: Aidan MacDonald + * + * Copyright (C) 2015 by the authors + * + * 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 __HEADERGEN_MSC_H__ +#define __HEADERGEN_MSC_H__ + +#include "macro.h" + +#define REG_MSC_CTRL(_n1) jz_reg(MSC_CTRL(_n1)) +#define JA_MSC_CTRL(_n1) (0xb3450000 + (_n1) * 0x10000 + 0x0) +#define JT_MSC_CTRL(_n1) JIO_32_RW +#define JN_MSC_CTRL(_n1) MSC_CTRL +#define JI_MSC_CTRL(_n1) (_n1) +#define BP_MSC_CTRL_CLOCK 0 +#define BM_MSC_CTRL_CLOCK 0x3 +#define BV_MSC_CTRL_CLOCK__DO_NOTHING 0x0 +#define BV_MSC_CTRL_CLOCK__STOP 0x1 +#define BV_MSC_CTRL_CLOCK__START 0x2 +#define BF_MSC_CTRL_CLOCK(v) (((v) & 0x3) << 0) +#define BFM_MSC_CTRL_CLOCK(v) BM_MSC_CTRL_CLOCK +#define BF_MSC_CTRL_CLOCK_V(e) BF_MSC_CTRL_CLOCK(BV_MSC_CTRL_CLOCK__##e) +#define BFM_MSC_CTRL_CLOCK_V(v) BM_MSC_CTRL_CLOCK +#define BP_MSC_CTRL_SEND_CCSD 15 +#define BM_MSC_CTRL_SEND_CCSD 0x8000 +#define BF_MSC_CTRL_SEND_CCSD(v) (((v) & 0x1) << 15) +#define BFM_MSC_CTRL_SEND_CCSD(v) BM_MSC_CTRL_SEND_CCSD +#define BF_MSC_CTRL_SEND_CCSD_V(e) BF_MSC_CTRL_SEND_CCSD(BV_MSC_CTRL_SEND_CCSD__##e) +#define BFM_MSC_CTRL_SEND_CCSD_V(v) BM_MSC_CTRL_SEND_CCSD +#define BP_MSC_CTRL_SEND_AS_CCSD 14 +#define BM_MSC_CTRL_SEND_AS_CCSD 0x4000 +#define BF_MSC_CTRL_SEND_AS_CCSD(v) (((v) & 0x1) << 14) +#define BFM_MSC_CTRL_SEND_AS_CCSD(v) BM_MSC_CTRL_SEND_AS_CCSD +#define BF_MSC_CTRL_SEND_AS_CCSD_V(e) BF_MSC_CTRL_SEND_AS_CCSD(BV_MSC_CTRL_SEND_AS_CCSD__##e) +#define BFM_MSC_CTRL_SEND_AS_CCSD_V(v) BM_MSC_CTRL_SEND_AS_CCSD +#define BP_MSC_CTRL_EXIT_MULTIPLE 7 +#define BM_MSC_CTRL_EXIT_MULTIPLE 0x80 +#define BF_MSC_CTRL_EXIT_MULTIPLE(v) (((v) & 0x1) << 7) +#define BFM_MSC_CTRL_EXIT_MULTIPLE(v) BM_MSC_CTRL_EXIT_MULTIPLE +#define BF_MSC_CTRL_EXIT_MULTIPLE_V(e) BF_MSC_CTRL_EXIT_MULTIPLE(BV_MSC_CTRL_EXIT_MULTIPLE__##e) +#define BFM_MSC_CTRL_EXIT_MULTIPLE_V(v) BM_MSC_CTRL_EXIT_MULTIPLE +#define BP_MSC_CTRL_EXIT_TRANSFER 6 +#define BM_MSC_CTRL_EXIT_TRANSFER 0x40 +#define BF_MSC_CTRL_EXIT_TRANSFER(v) (((v) & 0x1) << 6) +#define BFM_MSC_CTRL_EXIT_TRANSFER(v) BM_MSC_CTRL_EXIT_TRANSFER +#define BF_MSC_CTRL_EXIT_TRANSFER_V(e) BF_MSC_CTRL_EXIT_TRANSFER(BV_MSC_CTRL_EXIT_TRANSFER__##e) +#define BFM_MSC_CTRL_EXIT_TRANSFER_V(v) BM_MSC_CTRL_EXIT_TRANSFER +#define BP_MSC_CTRL_START_READ_WAIT 5 +#define BM_MSC_CTRL_START_READ_WAIT 0x20 +#define BF_MSC_CTRL_START_READ_WAIT(v) (((v) & 0x1) << 5) +#define BFM_MSC_CTRL_START_READ_WAIT(v) BM_MSC_CTRL_START_READ_WAIT +#define BF_MSC_CTRL_START_READ_WAIT_V(e) BF_MSC_CTRL_START_READ_WAIT(BV_MSC_CTRL_START_READ_WAIT__##e) +#define BFM_MSC_CTRL_START_READ_WAIT_V(v) BM_MSC_CTRL_START_READ_WAIT +#define BP_MSC_CTRL_STOP_READ_WAIT 4 +#define BM_MSC_CTRL_STOP_READ_WAIT 0x10 +#define BF_MSC_CTRL_STOP_READ_WAIT(v) (((v) & 0x1) << 4) +#define BFM_MSC_CTRL_STOP_READ_WAIT(v) BM_MSC_CTRL_STOP_READ_WAIT +#define BF_MSC_CTRL_STOP_READ_WAIT_V(e) BF_MSC_CTRL_STOP_READ_WAIT(BV_MSC_CTRL_STOP_READ_WAIT__##e) +#define BFM_MSC_CTRL_STOP_READ_WAIT_V(v) BM_MSC_CTRL_STOP_READ_WAIT +#define BP_MSC_CTRL_RESET 3 +#define BM_MSC_CTRL_RESET 0x8 +#define BF_MSC_CTRL_RESET(v) (((v) & 0x1) << 3) +#define BFM_MSC_CTRL_RESET(v) BM_MSC_CTRL_RESET +#define BF_MSC_CTRL_RESET_V(e) BF_MSC_CTRL_RESET(BV_MSC_CTRL_RESET__##e) +#define BFM_MSC_CTRL_RESET_V(v) BM_MSC_CTRL_RESET +#define BP_MSC_CTRL_START_OP 2 +#define BM_MSC_CTRL_START_OP 0x4 +#define BF_MSC_CTRL_START_OP(v) (((v) & 0x1) << 2) +#define BFM_MSC_CTRL_START_OP(v) BM_MSC_CTRL_START_OP +#define BF_MSC_CTRL_START_OP_V(e) BF_MSC_CTRL_START_OP(BV_MSC_CTRL_START_OP__##e) +#define BFM_MSC_CTRL_START_OP_V(v) BM_MSC_CTRL_START_OP + +#define REG_MSC_STAT(_n1) jz_reg(MSC_STAT(_n1)) +#define JA_MSC_STAT(_n1) (0xb3450000 + (_n1) * 0x10000 + 0x4) +#define JT_MSC_STAT(_n1) JIO_32_RW +#define JN_MSC_STAT(_n1) MSC_STAT +#define JI_MSC_STAT(_n1) (_n1) +#define BP_MSC_STAT_PINS 24 +#define BM_MSC_STAT_PINS 0x1f000000 +#define BF_MSC_STAT_PINS(v) (((v) & 0x1f) << 24) +#define BFM_MSC_STAT_PINS(v) BM_MSC_STAT_PINS +#define BF_MSC_STAT_PINS_V(e) BF_MSC_STAT_PINS(BV_MSC_STAT_PINS__##e) +#define BFM_MSC_STAT_PINS_V(v) BM_MSC_STAT_PINS +#define BP_MSC_STAT_CRC_WRITE_ERROR 2 +#define BM_MSC_STAT_CRC_WRITE_ERROR 0xc +#define BV_MSC_STAT_CRC_WRITE_ERROR__NONE 0x0 +#define BV_MSC_STAT_CRC_WRITE_ERROR__BADDATA 0x1 +#define BV_MSC_STAT_CRC_WRITE_ERROR__NOCRC 0x2 +#define BF_MSC_STAT_CRC_WRITE_ERROR(v) (((v) & 0x3) << 2) +#define BFM_MSC_STAT_CRC_WRITE_ERROR(v) BM_MSC_STAT_CRC_WRITE_ERROR +#define BF_MSC_STAT_CRC_WRITE_ERROR_V(e) BF_MSC_STAT_CRC_WRITE_ERROR(BV_MSC_STAT_CRC_WRITE_ERROR__##e) +#define BFM_MSC_STAT_CRC_WRITE_ERROR_V(v) BM_MSC_STAT_CRC_WRITE_ERROR +#define BP_MSC_STAT_AUTO_CMD12_DONE 31 +#define BM_MSC_STAT_AUTO_CMD12_DONE 0x80000000 +#define BF_MSC_STAT_AUTO_CMD12_DONE(v) (((v) & 0x1) << 31) +#define BFM_MSC_STAT_AUTO_CMD12_DONE(v) BM_MSC_STAT_AUTO_CMD12_DONE +#define BF_MSC_STAT_AUTO_CMD12_DONE_V(e) BF_MSC_STAT_AUTO_CMD12_DONE(BV_MSC_STAT_AUTO_CMD12_DONE__##e) +#define BFM_MSC_STAT_AUTO_CMD12_DONE_V(v) BM_MSC_STAT_AUTO_CMD12_DONE +#define BP_MSC_STAT_BCE 20 +#define BM_MSC_STAT_BCE 0x100000 +#define BF_MSC_STAT_BCE(v) (((v) & 0x1) << 20) +#define BFM_MSC_STAT_BCE(v) BM_MSC_STAT_BCE +#define BF_MSC_STAT_BCE_V(e) BF_MSC_STAT_BCE(BV_MSC_STAT_BCE__##e) +#define BFM_MSC_STAT_BCE_V(v) BM_MSC_STAT_BCE +#define BP_MSC_STAT_BDE 19 +#define BM_MSC_STAT_BDE 0x80000 +#define BF_MSC_STAT_BDE(v) (((v) & 0x1) << 19) +#define BFM_MSC_STAT_BDE(v) BM_MSC_STAT_BDE +#define BF_MSC_STAT_BDE_V(e) BF_MSC_STAT_BDE(BV_MSC_STAT_BDE__##e) +#define BFM_MSC_STAT_BDE_V(v) BM_MSC_STAT_BDE +#define BP_MSC_STAT_BAE 18 +#define BM_MSC_STAT_BAE 0x40000 +#define BF_MSC_STAT_BAE(v) (((v) & 0x1) << 18) +#define BFM_MSC_STAT_BAE(v) BM_MSC_STAT_BAE +#define BF_MSC_STAT_BAE_V(e) BF_MSC_STAT_BAE(BV_MSC_STAT_BAE__##e) +#define BFM_MSC_STAT_BAE_V(v) BM_MSC_STAT_BAE +#define BP_MSC_STAT_BAR 17 +#define BM_MSC_STAT_BAR 0x20000 +#define BF_MSC_STAT_BAR(v) (((v) & 0x1) << 17) +#define BFM_MSC_STAT_BAR(v) BM_MSC_STAT_BAR +#define BF_MSC_STAT_BAR_V(e) BF_MSC_STAT_BAR(BV_MSC_STAT_BAR__##e) +#define BFM_MSC_STAT_BAR_V(v) BM_MSC_STAT_BAR +#define BP_MSC_STAT_DMAEND 16 +#define BM_MSC_STAT_DMAEND 0x10000 +#define BF_MSC_STAT_DMAEND(v) (((v) & 0x1) << 16) +#define BFM_MSC_STAT_DMAEND(v) BM_MSC_STAT_DMAEND +#define BF_MSC_STAT_DMAEND_V(e) BF_MSC_STAT_DMAEND(BV_MSC_STAT_DMAEND__##e) +#define BFM_MSC_STAT_DMAEND_V(v) BM_MSC_STAT_DMAEND +#define BP_MSC_STAT_IS_RESETTING 15 +#define BM_MSC_STAT_IS_RESETTING 0x8000 +#define BF_MSC_STAT_IS_RESETTING(v) (((v) & 0x1) << 15) +#define BFM_MSC_STAT_IS_RESETTING(v) BM_MSC_STAT_IS_RESETTING +#define BF_MSC_STAT_IS_RESETTING_V(e) BF_MSC_STAT_IS_RESETTING(BV_MSC_STAT_IS_RESETTING__##e) +#define BFM_MSC_STAT_IS_RESETTING_V(v) BM_MSC_STAT_IS_RESETTING +#define BP_MSC_STAT_SDIO_INT_ACTIVE 14 +#define BM_MSC_STAT_SDIO_INT_ACTIVE 0x4000 +#define BF_MSC_STAT_SDIO_INT_ACTIVE(v) (((v) & 0x1) << 14) +#define BFM_MSC_STAT_SDIO_INT_ACTIVE(v) BM_MSC_STAT_SDIO_INT_ACTIVE +#define BF_MSC_STAT_SDIO_INT_ACTIVE_V(e) BF_MSC_STAT_SDIO_INT_ACTIVE(BV_MSC_STAT_SDIO_INT_ACTIVE__##e) +#define BFM_MSC_STAT_SDIO_INT_ACTIVE_V(v) BM_MSC_STAT_SDIO_INT_ACTIVE +#define BP_MSC_STAT_PROG_DONE 13 +#define BM_MSC_STAT_PROG_DONE 0x2000 +#define BF_MSC_STAT_PROG_DONE(v) (((v) & 0x1) << 13) +#define BFM_MSC_STAT_PROG_DONE(v) BM_MSC_STAT_PROG_DONE +#define BF_MSC_STAT_PROG_DONE_V(e) BF_MSC_STAT_PROG_DONE(BV_MSC_STAT_PROG_DONE__##e) +#define BFM_MSC_STAT_PROG_DONE_V(v) BM_MSC_STAT_PROG_DONE +#define BP_MSC_STAT_DATA_TRAN_DONE 12 +#define BM_MSC_STAT_DATA_TRAN_DONE 0x1000 +#define BF_MSC_STAT_DATA_TRAN_DONE(v) (((v) & 0x1) << 12) +#define BFM_MSC_STAT_DATA_TRAN_DONE(v) BM_MSC_STAT_DATA_TRAN_DONE +#define BF_MSC_STAT_DATA_TRAN_DONE_V(e) BF_MSC_STAT_DATA_TRAN_DONE(BV_MSC_STAT_DATA_TRAN_DONE__##e) +#define BFM_MSC_STAT_DATA_TRAN_DONE_V(v) BM_MSC_STAT_DATA_TRAN_DONE +#define BP_MSC_STAT_END_CMD_RES 11 +#define BM_MSC_STAT_END_CMD_RES 0x800 +#define BF_MSC_STAT_END_CMD_RES(v) (((v) & 0x1) << 11) +#define BFM_MSC_STAT_END_CMD_RES(v) BM_MSC_STAT_END_CMD_RES +#define BF_MSC_STAT_END_CMD_RES_V(e) BF_MSC_STAT_END_CMD_RES(BV_MSC_STAT_END_CMD_RES__##e) +#define BFM_MSC_STAT_END_CMD_RES_V(v) BM_MSC_STAT_END_CMD_RES +#define BP_MSC_STAT_DATA_FIFO_AFULL 10 +#define BM_MSC_STAT_DATA_FIFO_AFULL 0x400 +#define BF_MSC_STAT_DATA_FIFO_AFULL(v) (((v) & 0x1) << 10) +#define BFM_MSC_STAT_DATA_FIFO_AFULL(v) BM_MSC_STAT_DATA_FIFO_AFULL +#define BF_MSC_STAT_DATA_FIFO_AFULL_V(e) BF_MSC_STAT_DATA_FIFO_AFULL(BV_MSC_STAT_DATA_FIFO_AFULL__##e) +#define BFM_MSC_STAT_DATA_FIFO_AFULL_V(v) BM_MSC_STAT_DATA_FIFO_AFULL +#define BP_MSC_STAT_IS_READ_WAIT 9 +#define BM_MSC_STAT_IS_READ_WAIT 0x200 +#define BF_MSC_STAT_IS_READ_WAIT(v) (((v) & 0x1) << 9) +#define BFM_MSC_STAT_IS_READ_WAIT(v) BM_MSC_STAT_IS_READ_WAIT +#define BF_MSC_STAT_IS_READ_WAIT_V(e) BF_MSC_STAT_IS_READ_WAIT(BV_MSC_STAT_IS_READ_WAIT__##e) +#define BFM_MSC_STAT_IS_READ_WAIT_V(v) BM_MSC_STAT_IS_READ_WAIT +#define BP_MSC_STAT_CLOCK_EN 8 +#define BM_MSC_STAT_CLOCK_EN 0x100 +#define BF_MSC_STAT_CLOCK_EN(v) (((v) & 0x1) << 8) +#define BFM_MSC_STAT_CLOCK_EN(v) BM_MSC_STAT_CLOCK_EN +#define BF_MSC_STAT_CLOCK_EN_V(e) BF_MSC_STAT_CLOCK_EN(BV_MSC_STAT_CLOCK_EN__##e) +#define BFM_MSC_STAT_CLOCK_EN_V(v) BM_MSC_STAT_CLOCK_EN +#define BP_MSC_STAT_DATA_FIFO_FULL 7 +#define BM_MSC_STAT_DATA_FIFO_FULL 0x80 +#define BF_MSC_STAT_DATA_FIFO_FULL(v) (((v) & 0x1) << 7) +#define BFM_MSC_STAT_DATA_FIFO_FULL(v) BM_MSC_STAT_DATA_FIFO_FULL +#define BF_MSC_STAT_DATA_FIFO_FULL_V(e) BF_MSC_STAT_DATA_FIFO_FULL(BV_MSC_STAT_DATA_FIFO_FULL__##e) +#define BFM_MSC_STAT_DATA_FIFO_FULL_V(v) BM_MSC_STAT_DATA_FIFO_FULL +#define BP_MSC_STAT_DATA_FIFO_EMPTY 6 +#define BM_MSC_STAT_DATA_FIFO_EMPTY 0x40 +#define BF_MSC_STAT_DATA_FIFO_EMPTY(v) (((v) & 0x1) << 6) +#define BFM_MSC_STAT_DATA_FIFO_EMPTY(v) BM_MSC_STAT_DATA_FIFO_EMPTY +#define BF_MSC_STAT_DATA_FIFO_EMPTY_V(e) BF_MSC_STAT_DATA_FIFO_EMPTY(BV_MSC_STAT_DATA_FIFO_EMPTY__##e) +#define BFM_MSC_STAT_DATA_FIFO_EMPTY_V(v) BM_MSC_STAT_DATA_FIFO_EMPTY +#define BP_MSC_STAT_CRC_RES_ERROR 5 +#define BM_MSC_STAT_CRC_RES_ERROR 0x20 +#define BF_MSC_STAT_CRC_RES_ERROR(v) (((v) & 0x1) << 5) +#define BFM_MSC_STAT_CRC_RES_ERROR(v) BM_MSC_STAT_CRC_RES_ERROR +#define BF_MSC_STAT_CRC_RES_ERROR_V(e) BF_MSC_STAT_CRC_RES_ERROR(BV_MSC_STAT_CRC_RES_ERROR__##e) +#define BFM_MSC_STAT_CRC_RES_ERROR_V(v) BM_MSC_STAT_CRC_RES_ERROR +#define BP_MSC_STAT_CRC_READ_ERROR 4 +#define BM_MSC_STAT_CRC_READ_ERROR 0x10 +#define BF_MSC_STAT_CRC_READ_ERROR(v) (((v) & 0x1) << 4) +#define BFM_MSC_STAT_CRC_READ_ERROR(v) BM_MSC_STAT_CRC_READ_ERROR +#define BF_MSC_STAT_CRC_READ_ERROR_V(e) BF_MSC_STAT_CRC_READ_ERROR(BV_MSC_STAT_CRC_READ_ERROR__##e) +#define BFM_MSC_STAT_CRC_READ_ERROR_V(v) BM_MSC_STAT_CRC_READ_ERROR +#define BP_MSC_STAT_TIME_OUT_RES 1 +#define BM_MSC_STAT_TIME_OUT_RES 0x2 +#define BF_MSC_STAT_TIME_OUT_RES(v) (((v) & 0x1) << 1) +#define BFM_MSC_STAT_TIME_OUT_RES(v) BM_MSC_STAT_TIME_OUT_RES +#define BF_MSC_STAT_TIME_OUT_RES_V(e) BF_MSC_STAT_TIME_OUT_RES(BV_MSC_STAT_TIME_OUT_RES__##e) +#define BFM_MSC_STAT_TIME_OUT_RES_V(v) BM_MSC_STAT_TIME_OUT_RES +#define BP_MSC_STAT_TIME_OUT_READ 0 +#define BM_MSC_STAT_TIME_OUT_READ 0x1 +#define BF_MSC_STAT_TIME_OUT_READ(v) (((v) & 0x1) << 0) +#define BFM_MSC_STAT_TIME_OUT_READ(v) BM_MSC_STAT_TIME_OUT_READ +#define BF_MSC_STAT_TIME_OUT_READ_V(e) BF_MSC_STAT_TIME_OUT_READ(BV_MSC_STAT_TIME_OUT_READ__##e) +#define BFM_MSC_STAT_TIME_OUT_READ_V(v) BM_MSC_STAT_TIME_OUT_READ + +#define REG_MSC_CMDAT(_n1) jz_reg(MSC_CMDAT(_n1)) +#define JA_MSC_CMDAT(_n1) (0xb3450000 + (_n1) * 0x10000 + 0xc) +#define JT_MSC_CMDAT(_n1) JIO_32_RW +#define JN_MSC_CMDAT(_n1) MSC_CMDAT +#define JI_MSC_CMDAT(_n1) (_n1) +#define BP_MSC_CMDAT_RTRG 14 +#define BM_MSC_CMDAT_RTRG 0xc000 +#define BV_MSC_CMDAT_RTRG__GE16 0x0 +#define BV_MSC_CMDAT_RTRG__GE32 0x1 +#define BV_MSC_CMDAT_RTRG__GE64 0x2 +#define BV_MSC_CMDAT_RTRG__GE96 0x3 +#define BF_MSC_CMDAT_RTRG(v) (((v) & 0x3) << 14) +#define BFM_MSC_CMDAT_RTRG(v) BM_MSC_CMDAT_RTRG +#define BF_MSC_CMDAT_RTRG_V(e) BF_MSC_CMDAT_RTRG(BV_MSC_CMDAT_RTRG__##e) +#define BFM_MSC_CMDAT_RTRG_V(v) BM_MSC_CMDAT_RTRG +#define BP_MSC_CMDAT_TTRG 12 +#define BM_MSC_CMDAT_TTRG 0x3000 +#define BV_MSC_CMDAT_TTRG__LE16 0x0 +#define BV_MSC_CMDAT_TTRG__LE32 0x1 +#define BV_MSC_CMDAT_TTRG__LE64 0x2 +#define BV_MSC_CMDAT_TTRG__LE96 0x3 +#define BF_MSC_CMDAT_TTRG(v) (((v) & 0x3) << 12) +#define BFM_MSC_CMDAT_TTRG(v) BM_MSC_CMDAT_TTRG +#define BF_MSC_CMDAT_TTRG_V(e) BF_MSC_CMDAT_TTRG(BV_MSC_CMDAT_TTRG__##e) +#define BFM_MSC_CMDAT_TTRG_V(v) BM_MSC_CMDAT_TTRG +#define BP_MSC_CMDAT_BUS_WIDTH 9 +#define BM_MSC_CMDAT_BUS_WIDTH 0x600 +#define BV_MSC_CMDAT_BUS_WIDTH__1BIT 0x0 +#define BV_MSC_CMDAT_BUS_WIDTH__4BIT 0x2 +#define BV_MSC_CMDAT_BUS_WIDTH__8BIT 0x3 +#define BF_MSC_CMDAT_BUS_WIDTH(v) (((v) & 0x3) << 9) +#define BFM_MSC_CMDAT_BUS_WIDTH(v) BM_MSC_CMDAT_BUS_WIDTH +#define BF_MSC_CMDAT_BUS_WIDTH_V(e) BF_MSC_CMDAT_BUS_WIDTH(BV_MSC_CMDAT_BUS_WIDTH__##e) +#define BFM_MSC_CMDAT_BUS_WIDTH_V(v) BM_MSC_CMDAT_BUS_WIDTH +#define BP_MSC_CMDAT_RESP_FMT 0 +#define BM_MSC_CMDAT_RESP_FMT 0x7 +#define BF_MSC_CMDAT_RESP_FMT(v) (((v) & 0x7) << 0) +#define BFM_MSC_CMDAT_RESP_FMT(v) BM_MSC_CMDAT_RESP_FMT +#define BF_MSC_CMDAT_RESP_FMT_V(e) BF_MSC_CMDAT_RESP_FMT(BV_MSC_CMDAT_RESP_FMT__##e) +#define BFM_MSC_CMDAT_RESP_FMT_V(v) BM_MSC_CMDAT_RESP_FMT +#define BP_MSC_CMDAT_CCS_EXPECTED 31 +#define BM_MSC_CMDAT_CCS_EXPECTED 0x80000000 +#define BF_MSC_CMDAT_CCS_EXPECTED(v) (((v) & 0x1) << 31) +#define BFM_MSC_CMDAT_CCS_EXPECTED(v) BM_MSC_CMDAT_CCS_EXPECTED +#define BF_MSC_CMDAT_CCS_EXPECTED_V(e) BF_MSC_CMDAT_CCS_EXPECTED(BV_MSC_CMDAT_CCS_EXPECTED__##e) +#define BFM_MSC_CMDAT_CCS_EXPECTED_V(v) BM_MSC_CMDAT_CCS_EXPECTED +#define BP_MSC_CMDAT_READ_CEATA 30 +#define BM_MSC_CMDAT_READ_CEATA 0x40000000 +#define BF_MSC_CMDAT_READ_CEATA(v) (((v) & 0x1) << 30) +#define BFM_MSC_CMDAT_READ_CEATA(v) BM_MSC_CMDAT_READ_CEATA +#define BF_MSC_CMDAT_READ_CEATA_V(e) BF_MSC_CMDAT_READ_CEATA(BV_MSC_CMDAT_READ_CEATA__##e) +#define BFM_MSC_CMDAT_READ_CEATA_V(v) BM_MSC_CMDAT_READ_CEATA +#define BP_MSC_CMDAT_DIS_BOOT 27 +#define BM_MSC_CMDAT_DIS_BOOT 0x8000000 +#define BF_MSC_CMDAT_DIS_BOOT(v) (((v) & 0x1) << 27) +#define BFM_MSC_CMDAT_DIS_BOOT(v) BM_MSC_CMDAT_DIS_BOOT +#define BF_MSC_CMDAT_DIS_BOOT_V(e) BF_MSC_CMDAT_DIS_BOOT(BV_MSC_CMDAT_DIS_BOOT__##e) +#define BFM_MSC_CMDAT_DIS_BOOT_V(v) BM_MSC_CMDAT_DIS_BOOT +#define BP_MSC_CMDAT_EXP_BOOT_ACK 25 +#define BM_MSC_CMDAT_EXP_BOOT_ACK 0x2000000 +#define BF_MSC_CMDAT_EXP_BOOT_ACK(v) (((v) & 0x1) << 25) +#define BFM_MSC_CMDAT_EXP_BOOT_ACK(v) BM_MSC_CMDAT_EXP_BOOT_ACK +#define BF_MSC_CMDAT_EXP_BOOT_ACK_V(e) BF_MSC_CMDAT_EXP_BOOT_ACK(BV_MSC_CMDAT_EXP_BOOT_ACK__##e) +#define BFM_MSC_CMDAT_EXP_BOOT_ACK_V(v) BM_MSC_CMDAT_EXP_BOOT_ACK +#define BP_MSC_CMDAT_BOOT_MODE 24 +#define BM_MSC_CMDAT_BOOT_MODE 0x1000000 +#define BF_MSC_CMDAT_BOOT_MODE(v) (((v) & 0x1) << 24) +#define BFM_MSC_CMDAT_BOOT_MODE(v) BM_MSC_CMDAT_BOOT_MODE +#define BF_MSC_CMDAT_BOOT_MODE_V(e) BF_MSC_CMDAT_BOOT_MODE(BV_MSC_CMDAT_BOOT_MODE__##e) +#define BFM_MSC_CMDAT_BOOT_MODE_V(v) BM_MSC_CMDAT_BOOT_MODE +#define BP_MSC_CMDAT_SDIO_PRDT 17 +#define BM_MSC_CMDAT_SDIO_PRDT 0x20000 +#define BF_MSC_CMDAT_SDIO_PRDT(v) (((v) & 0x1) << 17) +#define BFM_MSC_CMDAT_SDIO_PRDT(v) BM_MSC_CMDAT_SDIO_PRDT +#define BF_MSC_CMDAT_SDIO_PRDT_V(e) BF_MSC_CMDAT_SDIO_PRDT(BV_MSC_CMDAT_SDIO_PRDT__##e) +#define BFM_MSC_CMDAT_SDIO_PRDT_V(v) BM_MSC_CMDAT_SDIO_PRDT +#define BP_MSC_CMDAT_AUTO_CMD12 16 +#define BM_MSC_CMDAT_AUTO_CMD12 0x10000 +#define BF_MSC_CMDAT_AUTO_CMD12(v) (((v) & 0x1) << 16) +#define BFM_MSC_CMDAT_AUTO_CMD12(v) BM_MSC_CMDAT_AUTO_CMD12 +#define BF_MSC_CMDAT_AUTO_CMD12_V(e) BF_MSC_CMDAT_AUTO_CMD12(BV_MSC_CMDAT_AUTO_CMD12__##e) +#define BFM_MSC_CMDAT_AUTO_CMD12_V(v) BM_MSC_CMDAT_AUTO_CMD12 +#define BP_MSC_CMDAT_IO_ABORT 11 +#define BM_MSC_CMDAT_IO_ABORT 0x800 +#define BF_MSC_CMDAT_IO_ABORT(v) (((v) & 0x1) << 11) +#define BFM_MSC_CMDAT_IO_ABORT(v) BM_MSC_CMDAT_IO_ABORT +#define BF_MSC_CMDAT_IO_ABORT_V(e) BF_MSC_CMDAT_IO_ABORT(BV_MSC_CMDAT_IO_ABORT__##e) +#define BFM_MSC_CMDAT_IO_ABORT_V(v) BM_MSC_CMDAT_IO_ABORT +#define BP_MSC_CMDAT_INIT 7 +#define BM_MSC_CMDAT_INIT 0x80 +#define BF_MSC_CMDAT_INIT(v) (((v) & 0x1) << 7) +#define BFM_MSC_CMDAT_INIT(v) BM_MSC_CMDAT_INIT +#define BF_MSC_CMDAT_INIT_V(e) BF_MSC_CMDAT_INIT(BV_MSC_CMDAT_INIT__##e) +#define BFM_MSC_CMDAT_INIT_V(v) BM_MSC_CMDAT_INIT +#define BP_MSC_CMDAT_BUSY 6 +#define BM_MSC_CMDAT_BUSY 0x40 +#define BF_MSC_CMDAT_BUSY(v) (((v) & 0x1) << 6) +#define BFM_MSC_CMDAT_BUSY(v) BM_MSC_CMDAT_BUSY +#define BF_MSC_CMDAT_BUSY_V(e) BF_MSC_CMDAT_BUSY(BV_MSC_CMDAT_BUSY__##e) +#define BFM_MSC_CMDAT_BUSY_V(v) BM_MSC_CMDAT_BUSY +#define BP_MSC_CMDAT_STREAM_BLOCK 5 +#define BM_MSC_CMDAT_STREAM_BLOCK 0x20 +#define BF_MSC_CMDAT_STREAM_BLOCK(v) (((v) & 0x1) << 5) +#define BFM_MSC_CMDAT_STREAM_BLOCK(v) BM_MSC_CMDAT_STREAM_BLOCK +#define BF_MSC_CMDAT_STREAM_BLOCK_V(e) BF_MSC_CMDAT_STREAM_BLOCK(BV_MSC_CMDAT_STREAM_BLOCK__##e) +#define BFM_MSC_CMDAT_STREAM_BLOCK_V(v) BM_MSC_CMDAT_STREAM_BLOCK +#define BP_MSC_CMDAT_WRITE_READ 4 +#define BM_MSC_CMDAT_WRITE_READ 0x10 +#define BF_MSC_CMDAT_WRITE_READ(v) (((v) & 0x1) << 4) +#define BFM_MSC_CMDAT_WRITE_READ(v) BM_MSC_CMDAT_WRITE_READ +#define BF_MSC_CMDAT_WRITE_READ_V(e) BF_MSC_CMDAT_WRITE_READ(BV_MSC_CMDAT_WRITE_READ__##e) +#define BFM_MSC_CMDAT_WRITE_READ_V(v) BM_MSC_CMDAT_WRITE_READ +#define BP_MSC_CMDAT_DATA_EN 3 +#define BM_MSC_CMDAT_DATA_EN 0x8 +#define BF_MSC_CMDAT_DATA_EN(v) (((v) & 0x1) << 3) +#define BFM_MSC_CMDAT_DATA_EN(v) BM_MSC_CMDAT_DATA_EN +#define BF_MSC_CMDAT_DATA_EN_V(e) BF_MSC_CMDAT_DATA_EN(BV_MSC_CMDAT_DATA_EN__##e) +#define BFM_MSC_CMDAT_DATA_EN_V(v) BM_MSC_CMDAT_DATA_EN + +#define REG_MSC_IMASK(_n1) jz_reg(MSC_IMASK(_n1)) +#define JA_MSC_IMASK(_n1) (0xb3450000 + (_n1) * 0x10000 + 0x24) +#define JT_MSC_IMASK(_n1) JIO_32_RW +#define JN_MSC_IMASK(_n1) MSC_IMASK +#define JI_MSC_IMASK(_n1) (_n1) +#define BP_MSC_IMASK_PINS 24 +#define BM_MSC_IMASK_PINS 0x1f000000 +#define BF_MSC_IMASK_PINS(v) (((v) & 0x1f) << 24) +#define BFM_MSC_IMASK_PINS(v) BM_MSC_IMASK_PINS +#define BF_MSC_IMASK_PINS_V(e) BF_MSC_IMASK_PINS(BV_MSC_IMASK_PINS__##e) +#define BFM_MSC_IMASK_PINS_V(v) BM_MSC_IMASK_PINS +#define BP_MSC_IMASK_DMA_DATA_DONE 31 +#define BM_MSC_IMASK_DMA_DATA_DONE 0x80000000 +#define BF_MSC_IMASK_DMA_DATA_DONE(v) (((v) & 0x1) << 31) +#define BFM_MSC_IMASK_DMA_DATA_DONE(v) BM_MSC_IMASK_DMA_DATA_DONE +#define BF_MSC_IMASK_DMA_DATA_DONE_V(e) BF_MSC_IMASK_DMA_DATA_DONE(BV_MSC_IMASK_DMA_DATA_DONE__##e) +#define BFM_MSC_IMASK_DMA_DATA_DONE_V(v) BM_MSC_IMASK_DMA_DATA_DONE +#define BP_MSC_IMASK_WR_ALL_DONE 23 +#define BM_MSC_IMASK_WR_ALL_DONE 0x800000 +#define BF_MSC_IMASK_WR_ALL_DONE(v) (((v) & 0x1) << 23) +#define BFM_MSC_IMASK_WR_ALL_DONE(v) BM_MSC_IMASK_WR_ALL_DONE +#define BF_MSC_IMASK_WR_ALL_DONE_V(e) BF_MSC_IMASK_WR_ALL_DONE(BV_MSC_IMASK_WR_ALL_DONE__##e) +#define BFM_MSC_IMASK_WR_ALL_DONE_V(v) BM_MSC_IMASK_WR_ALL_DONE +#define BP_MSC_IMASK_BCE 20 +#define BM_MSC_IMASK_BCE 0x100000 +#define BF_MSC_IMASK_BCE(v) (((v) & 0x1) << 20) +#define BFM_MSC_IMASK_BCE(v) BM_MSC_IMASK_BCE +#define BF_MSC_IMASK_BCE_V(e) BF_MSC_IMASK_BCE(BV_MSC_IMASK_BCE__##e) +#define BFM_MSC_IMASK_BCE_V(v) BM_MSC_IMASK_BCE +#define BP_MSC_IMASK_BDE 19 +#define BM_MSC_IMASK_BDE 0x80000 +#define BF_MSC_IMASK_BDE(v) (((v) & 0x1) << 19) +#define BFM_MSC_IMASK_BDE(v) BM_MSC_IMASK_BDE +#define BF_MSC_IMASK_BDE_V(e) BF_MSC_IMASK_BDE(BV_MSC_IMASK_BDE__##e) +#define BFM_MSC_IMASK_BDE_V(v) BM_MSC_IMASK_BDE +#define BP_MSC_IMASK_BAE 18 +#define BM_MSC_IMASK_BAE 0x40000 +#define BF_MSC_IMASK_BAE(v) (((v) & 0x1) << 18) +#define BFM_MSC_IMASK_BAE(v) BM_MSC_IMASK_BAE +#define BF_MSC_IMASK_BAE_V(e) BF_MSC_IMASK_BAE(BV_MSC_IMASK_BAE__##e) +#define BFM_MSC_IMASK_BAE_V(v) BM_MSC_IMASK_BAE +#define BP_MSC_IMASK_BAR 17 +#define BM_MSC_IMASK_BAR 0x20000 +#define BF_MSC_IMASK_BAR(v) (((v) & 0x1) << 17) +#define BFM_MSC_IMASK_BAR(v) BM_MSC_IMASK_BAR +#define BF_MSC_IMASK_BAR_V(e) BF_MSC_IMASK_BAR(BV_MSC_IMASK_BAR__##e) +#define BFM_MSC_IMASK_BAR_V(v) BM_MSC_IMASK_BAR +#define BP_MSC_IMASK_DMAEND 16 +#define BM_MSC_IMASK_DMAEND 0x10000 +#define BF_MSC_IMASK_DMAEND(v) (((v) & 0x1) << 16) +#define BFM_MSC_IMASK_DMAEND(v) BM_MSC_IMASK_DMAEND +#define BF_MSC_IMASK_DMAEND_V(e) BF_MSC_IMASK_DMAEND(BV_MSC_IMASK_DMAEND__##e) +#define BFM_MSC_IMASK_DMAEND_V(v) BM_MSC_IMASK_DMAEND +#define BP_MSC_IMASK_AUTO_CMD12_DONE 15 +#define BM_MSC_IMASK_AUTO_CMD12_DONE 0x8000 +#define BF_MSC_IMASK_AUTO_CMD12_DONE(v) (((v) & 0x1) << 15) +#define BFM_MSC_IMASK_AUTO_CMD12_DONE(v) BM_MSC_IMASK_AUTO_CMD12_DONE +#define BF_MSC_IMASK_AUTO_CMD12_DONE_V(e) BF_MSC_IMASK_AUTO_CMD12_DONE(BV_MSC_IMASK_AUTO_CMD12_DONE__##e) +#define BFM_MSC_IMASK_AUTO_CMD12_DONE_V(v) BM_MSC_IMASK_AUTO_CMD12_DONE +#define BP_MSC_IMASK_DATA_FIFO_FULL 14 +#define BM_MSC_IMASK_DATA_FIFO_FULL 0x4000 +#define BF_MSC_IMASK_DATA_FIFO_FULL(v) (((v) & 0x1) << 14) +#define BFM_MSC_IMASK_DATA_FIFO_FULL(v) BM_MSC_IMASK_DATA_FIFO_FULL +#define BF_MSC_IMASK_DATA_FIFO_FULL_V(e) BF_MSC_IMASK_DATA_FIFO_FULL(BV_MSC_IMASK_DATA_FIFO_FULL__##e) +#define BFM_MSC_IMASK_DATA_FIFO_FULL_V(v) BM_MSC_IMASK_DATA_FIFO_FULL +#define BP_MSC_IMASK_DATA_FIFO_EMPTY 13 +#define BM_MSC_IMASK_DATA_FIFO_EMPTY 0x2000 +#define BF_MSC_IMASK_DATA_FIFO_EMPTY(v) (((v) & 0x1) << 13) +#define BFM_MSC_IMASK_DATA_FIFO_EMPTY(v) BM_MSC_IMASK_DATA_FIFO_EMPTY +#define BF_MSC_IMASK_DATA_FIFO_EMPTY_V(e) BF_MSC_IMASK_DATA_FIFO_EMPTY(BV_MSC_IMASK_DATA_FIFO_EMPTY__##e) +#define BFM_MSC_IMASK_DATA_FIFO_EMPTY_V(v) BM_MSC_IMASK_DATA_FIFO_EMPTY +#define BP_MSC_IMASK_CRC_RES_ERROR 12 +#define BM_MSC_IMASK_CRC_RES_ERROR 0x1000 +#define BF_MSC_IMASK_CRC_RES_ERROR(v) (((v) & 0x1) << 12) +#define BFM_MSC_IMASK_CRC_RES_ERROR(v) BM_MSC_IMASK_CRC_RES_ERROR +#define BF_MSC_IMASK_CRC_RES_ERROR_V(e) BF_MSC_IMASK_CRC_RES_ERROR(BV_MSC_IMASK_CRC_RES_ERROR__##e) +#define BFM_MSC_IMASK_CRC_RES_ERROR_V(v) BM_MSC_IMASK_CRC_RES_ERROR +#define BP_MSC_IMASK_CRC_READ_ERROR 11 +#define BM_MSC_IMASK_CRC_READ_ERROR 0x800 +#define BF_MSC_IMASK_CRC_READ_ERROR(v) (((v) & 0x1) << 11) +#define BFM_MSC_IMASK_CRC_READ_ERROR(v) BM_MSC_IMASK_CRC_READ_ERROR +#define BF_MSC_IMASK_CRC_READ_ERROR_V(e) BF_MSC_IMASK_CRC_READ_ERROR(BV_MSC_IMASK_CRC_READ_ERROR__##e) +#define BFM_MSC_IMASK_CRC_READ_ERROR_V(v) BM_MSC_IMASK_CRC_READ_ERROR +#define BP_MSC_IMASK_CRC_WRITE_ERROR 10 +#define BM_MSC_IMASK_CRC_WRITE_ERROR 0x400 +#define BF_MSC_IMASK_CRC_WRITE_ERROR(v) (((v) & 0x1) << 10) +#define BFM_MSC_IMASK_CRC_WRITE_ERROR(v) BM_MSC_IMASK_CRC_WRITE_ERROR +#define BF_MSC_IMASK_CRC_WRITE_ERROR_V(e) BF_MSC_IMASK_CRC_WRITE_ERROR(BV_MSC_IMASK_CRC_WRITE_ERROR__##e) +#define BFM_MSC_IMASK_CRC_WRITE_ERROR_V(v) BM_MSC_IMASK_CRC_WRITE_ERROR +#define BP_MSC_IMASK_TIME_OUT_RES 9 +#define BM_MSC_IMASK_TIME_OUT_RES 0x200 +#define BF_MSC_IMASK_TIME_OUT_RES(v) (((v) & 0x1) << 9) +#define BFM_MSC_IMASK_TIME_OUT_RES(v) BM_MSC_IMASK_TIME_OUT_RES +#define BF_MSC_IMASK_TIME_OUT_RES_V(e) BF_MSC_IMASK_TIME_OUT_RES(BV_MSC_IMASK_TIME_OUT_RES__##e) +#define BFM_MSC_IMASK_TIME_OUT_RES_V(v) BM_MSC_IMASK_TIME_OUT_RES +#define BP_MSC_IMASK_TIME_OUT_READ 8 +#define BM_MSC_IMASK_TIME_OUT_READ 0x100 +#define BF_MSC_IMASK_TIME_OUT_READ(v) (((v) & 0x1) << 8) +#define BFM_MSC_IMASK_TIME_OUT_READ(v) BM_MSC_IMASK_TIME_OUT_READ +#define BF_MSC_IMASK_TIME_OUT_READ_V(e) BF_MSC_IMASK_TIME_OUT_READ(BV_MSC_IMASK_TIME_OUT_READ__##e) +#define BFM_MSC_IMASK_TIME_OUT_READ_V(v) BM_MSC_IMASK_TIME_OUT_READ +#define BP_MSC_IMASK_SDIO 7 +#define BM_MSC_IMASK_SDIO 0x80 +#define BF_MSC_IMASK_SDIO(v) (((v) & 0x1) << 7) +#define BFM_MSC_IMASK_SDIO(v) BM_MSC_IMASK_SDIO +#define BF_MSC_IMASK_SDIO_V(e) BF_MSC_IMASK_SDIO(BV_MSC_IMASK_SDIO__##e) +#define BFM_MSC_IMASK_SDIO_V(v) BM_MSC_IMASK_SDIO +#define BP_MSC_IMASK_TXFIFO_WR_REQ 6 +#define BM_MSC_IMASK_TXFIFO_WR_REQ 0x40 +#define BF_MSC_IMASK_TXFIFO_WR_REQ(v) (((v) & 0x1) << 6) +#define BFM_MSC_IMASK_TXFIFO_WR_REQ(v) BM_MSC_IMASK_TXFIFO_WR_REQ +#define BF_MSC_IMASK_TXFIFO_WR_REQ_V(e) BF_MSC_IMASK_TXFIFO_WR_REQ(BV_MSC_IMASK_TXFIFO_WR_REQ__##e) +#define BFM_MSC_IMASK_TXFIFO_WR_REQ_V(v) BM_MSC_IMASK_TXFIFO_WR_REQ +#define BP_MSC_IMASK_RXFIFO_RD_REQ 5 +#define BM_MSC_IMASK_RXFIFO_RD_REQ 0x20 +#define BF_MSC_IMASK_RXFIFO_RD_REQ(v) (((v) & 0x1) << 5) +#define BFM_MSC_IMASK_RXFIFO_RD_REQ(v) BM_MSC_IMASK_RXFIFO_RD_REQ +#define BF_MSC_IMASK_RXFIFO_RD_REQ_V(e) BF_MSC_IMASK_RXFIFO_RD_REQ(BV_MSC_IMASK_RXFIFO_RD_REQ__##e) +#define BFM_MSC_IMASK_RXFIFO_RD_REQ_V(v) BM_MSC_IMASK_RXFIFO_RD_REQ +#define BP_MSC_IMASK_END_CMD_RES 2 +#define BM_MSC_IMASK_END_CMD_RES 0x4 +#define BF_MSC_IMASK_END_CMD_RES(v) (((v) & 0x1) << 2) +#define BFM_MSC_IMASK_END_CMD_RES(v) BM_MSC_IMASK_END_CMD_RES +#define BF_MSC_IMASK_END_CMD_RES_V(e) BF_MSC_IMASK_END_CMD_RES(BV_MSC_IMASK_END_CMD_RES__##e) +#define BFM_MSC_IMASK_END_CMD_RES_V(v) BM_MSC_IMASK_END_CMD_RES +#define BP_MSC_IMASK_PROG_DONE 1 +#define BM_MSC_IMASK_PROG_DONE 0x2 +#define BF_MSC_IMASK_PROG_DONE(v) (((v) & 0x1) << 1) +#define BFM_MSC_IMASK_PROG_DONE(v) BM_MSC_IMASK_PROG_DONE +#define BF_MSC_IMASK_PROG_DONE_V(e) BF_MSC_IMASK_PROG_DONE(BV_MSC_IMASK_PROG_DONE__##e) +#define BFM_MSC_IMASK_PROG_DONE_V(v) BM_MSC_IMASK_PROG_DONE +#define BP_MSC_IMASK_DATA_TRAN_DONE 0 +#define BM_MSC_IMASK_DATA_TRAN_DONE 0x1 +#define BF_MSC_IMASK_DATA_TRAN_DONE(v) (((v) & 0x1) << 0) +#define BFM_MSC_IMASK_DATA_TRAN_DONE(v) BM_MSC_IMASK_DATA_TRAN_DONE +#define BF_MSC_IMASK_DATA_TRAN_DONE_V(e) BF_MSC_IMASK_DATA_TRAN_DONE(BV_MSC_IMASK_DATA_TRAN_DONE__##e) +#define BFM_MSC_IMASK_DATA_TRAN_DONE_V(v) BM_MSC_IMASK_DATA_TRAN_DONE + +#define REG_MSC_IFLAG(_n1) jz_reg(MSC_IFLAG(_n1)) +#define JA_MSC_IFLAG(_n1) (0xb3450000 + (_n1) * 0x10000 + 0x28) +#define JT_MSC_IFLAG(_n1) JIO_32_RW +#define JN_MSC_IFLAG(_n1) MSC_IFLAG +#define JI_MSC_IFLAG(_n1) (_n1) +#define BP_MSC_IFLAG_PINS 24 +#define BM_MSC_IFLAG_PINS 0x1f000000 +#define BF_MSC_IFLAG_PINS(v) (((v) & 0x1f) << 24) +#define BFM_MSC_IFLAG_PINS(v) BM_MSC_IFLAG_PINS +#define BF_MSC_IFLAG_PINS_V(e) BF_MSC_IFLAG_PINS(BV_MSC_IFLAG_PINS__##e) +#define BFM_MSC_IFLAG_PINS_V(v) BM_MSC_IFLAG_PINS +#define BP_MSC_IFLAG_DMA_DATA_DONE 31 +#define BM_MSC_IFLAG_DMA_DATA_DONE 0x80000000 +#define BF_MSC_IFLAG_DMA_DATA_DONE(v) (((v) & 0x1) << 31) +#define BFM_MSC_IFLAG_DMA_DATA_DONE(v) BM_MSC_IFLAG_DMA_DATA_DONE +#define BF_MSC_IFLAG_DMA_DATA_DONE_V(e) BF_MSC_IFLAG_DMA_DATA_DONE(BV_MSC_IFLAG_DMA_DATA_DONE__##e) +#define BFM_MSC_IFLAG_DMA_DATA_DONE_V(v) BM_MSC_IFLAG_DMA_DATA_DONE +#define BP_MSC_IFLAG_WR_ALL_DONE 23 +#define BM_MSC_IFLAG_WR_ALL_DONE 0x800000 +#define BF_MSC_IFLAG_WR_ALL_DONE(v) (((v) & 0x1) << 23) +#define BFM_MSC_IFLAG_WR_ALL_DONE(v) BM_MSC_IFLAG_WR_ALL_DONE +#define BF_MSC_IFLAG_WR_ALL_DONE_V(e) BF_MSC_IFLAG_WR_ALL_DONE(BV_MSC_IFLAG_WR_ALL_DONE__##e) +#define BFM_MSC_IFLAG_WR_ALL_DONE_V(v) BM_MSC_IFLAG_WR_ALL_DONE +#define BP_MSC_IFLAG_BCE 20 +#define BM_MSC_IFLAG_BCE 0x100000 +#define BF_MSC_IFLAG_BCE(v) (((v) & 0x1) << 20) +#define BFM_MSC_IFLAG_BCE(v) BM_MSC_IFLAG_BCE +#define BF_MSC_IFLAG_BCE_V(e) BF_MSC_IFLAG_BCE(BV_MSC_IFLAG_BCE__##e) +#define BFM_MSC_IFLAG_BCE_V(v) BM_MSC_IFLAG_BCE +#define BP_MSC_IFLAG_BDE 19 +#define BM_MSC_IFLAG_BDE 0x80000 +#define BF_MSC_IFLAG_BDE(v) (((v) & 0x1) << 19) +#define BFM_MSC_IFLAG_BDE(v) BM_MSC_IFLAG_BDE +#define BF_MSC_IFLAG_BDE_V(e) BF_MSC_IFLAG_BDE(BV_MSC_IFLAG_BDE__##e) +#define BFM_MSC_IFLAG_BDE_V(v) BM_MSC_IFLAG_BDE +#define BP_MSC_IFLAG_BAE 18 +#define BM_MSC_IFLAG_BAE 0x40000 +#define BF_MSC_IFLAG_BAE(v) (((v) & 0x1) << 18) +#define BFM_MSC_IFLAG_BAE(v) BM_MSC_IFLAG_BAE +#define BF_MSC_IFLAG_BAE_V(e) BF_MSC_IFLAG_BAE(BV_MSC_IFLAG_BAE__##e) +#define BFM_MSC_IFLAG_BAE_V(v) BM_MSC_IFLAG_BAE +#define BP_MSC_IFLAG_BAR 17 +#define BM_MSC_IFLAG_BAR 0x20000 +#define BF_MSC_IFLAG_BAR(v) (((v) & 0x1) << 17) +#define BFM_MSC_IFLAG_BAR(v) BM_MSC_IFLAG_BAR +#define BF_MSC_IFLAG_BAR_V(e) BF_MSC_IFLAG_BAR(BV_MSC_IFLAG_BAR__##e) +#define BFM_MSC_IFLAG_BAR_V(v) BM_MSC_IFLAG_BAR +#define BP_MSC_IFLAG_DMAEND 16 +#define BM_MSC_IFLAG_DMAEND 0x10000 +#define BF_MSC_IFLAG_DMAEND(v) (((v) & 0x1) << 16) +#define BFM_MSC_IFLAG_DMAEND(v) BM_MSC_IFLAG_DMAEND +#define BF_MSC_IFLAG_DMAEND_V(e) BF_MSC_IFLAG_DMAEND(BV_MSC_IFLAG_DMAEND__##e) +#define BFM_MSC_IFLAG_DMAEND_V(v) BM_MSC_IFLAG_DMAEND +#define BP_MSC_IFLAG_AUTO_CMD12_DONE 15 +#define BM_MSC_IFLAG_AUTO_CMD12_DONE 0x8000 +#define BF_MSC_IFLAG_AUTO_CMD12_DONE(v) (((v) & 0x1) << 15) +#define BFM_MSC_IFLAG_AUTO_CMD12_DONE(v) BM_MSC_IFLAG_AUTO_CMD12_DONE +#define BF_MSC_IFLAG_AUTO_CMD12_DONE_V(e) BF_MSC_IFLAG_AUTO_CMD12_DONE(BV_MSC_IFLAG_AUTO_CMD12_DONE__##e) +#define BFM_MSC_IFLAG_AUTO_CMD12_DONE_V(v) BM_MSC_IFLAG_AUTO_CMD12_DONE +#define BP_MSC_IFLAG_DATA_FIFO_FULL 14 +#define BM_MSC_IFLAG_DATA_FIFO_FULL 0x4000 +#define BF_MSC_IFLAG_DATA_FIFO_FULL(v) (((v) & 0x1) << 14) +#define BFM_MSC_IFLAG_DATA_FIFO_FULL(v) BM_MSC_IFLAG_DATA_FIFO_FULL +#define BF_MSC_IFLAG_DATA_FIFO_FULL_V(e) BF_MSC_IFLAG_DATA_FIFO_FULL(BV_MSC_IFLAG_DATA_FIFO_FULL__##e) +#define BFM_MSC_IFLAG_DATA_FIFO_FULL_V(v) BM_MSC_IFLAG_DATA_FIFO_FULL +#define BP_MSC_IFLAG_DATA_FIFO_EMPTY 13 +#define BM_MSC_IFLAG_DATA_FIFO_EMPTY 0x2000 +#define BF_MSC_IFLAG_DATA_FIFO_EMPTY(v) (((v) & 0x1) << 13) +#define BFM_MSC_IFLAG_DATA_FIFO_EMPTY(v) BM_MSC_IFLAG_DATA_FIFO_EMPTY +#define BF_MSC_IFLAG_DATA_FIFO_EMPTY_V(e) BF_MSC_IFLAG_DATA_FIFO_EMPTY(BV_MSC_IFLAG_DATA_FIFO_EMPTY__##e) +#define BFM_MSC_IFLAG_DATA_FIFO_EMPTY_V(v) BM_MSC_IFLAG_DATA_FIFO_EMPTY +#define BP_MSC_IFLAG_CRC_RES_ERROR 12 +#define BM_MSC_IFLAG_CRC_RES_ERROR 0x1000 +#define BF_MSC_IFLAG_CRC_RES_ERROR(v) (((v) & 0x1) << 12) +#define BFM_MSC_IFLAG_CRC_RES_ERROR(v) BM_MSC_IFLAG_CRC_RES_ERROR +#define BF_MSC_IFLAG_CRC_RES_ERROR_V(e) BF_MSC_IFLAG_CRC_RES_ERROR(BV_MSC_IFLAG_CRC_RES_ERROR__##e) +#define BFM_MSC_IFLAG_CRC_RES_ERROR_V(v) BM_MSC_IFLAG_CRC_RES_ERROR +#define BP_MSC_IFLAG_CRC_READ_ERROR 11 +#define BM_MSC_IFLAG_CRC_READ_ERROR 0x800 +#define BF_MSC_IFLAG_CRC_READ_ERROR(v) (((v) & 0x1) << 11) +#define BFM_MSC_IFLAG_CRC_READ_ERROR(v) BM_MSC_IFLAG_CRC_READ_ERROR +#define BF_MSC_IFLAG_CRC_READ_ERROR_V(e) BF_MSC_IFLAG_CRC_READ_ERROR(BV_MSC_IFLAG_CRC_READ_ERROR__##e) +#define BFM_MSC_IFLAG_CRC_READ_ERROR_V(v) BM_MSC_IFLAG_CRC_READ_ERROR +#define BP_MSC_IFLAG_CRC_WRITE_ERROR 10 +#define BM_MSC_IFLAG_CRC_WRITE_ERROR 0x400 +#define BF_MSC_IFLAG_CRC_WRITE_ERROR(v) (((v) & 0x1) << 10) +#define BFM_MSC_IFLAG_CRC_WRITE_ERROR(v) BM_MSC_IFLAG_CRC_WRITE_ERROR +#define BF_MSC_IFLAG_CRC_WRITE_ERROR_V(e) BF_MSC_IFLAG_CRC_WRITE_ERROR(BV_MSC_IFLAG_CRC_WRITE_ERROR__##e) +#define BFM_MSC_IFLAG_CRC_WRITE_ERROR_V(v) BM_MSC_IFLAG_CRC_WRITE_ERROR +#define BP_MSC_IFLAG_TIME_OUT_RES 9 +#define BM_MSC_IFLAG_TIME_OUT_RES 0x200 +#define BF_MSC_IFLAG_TIME_OUT_RES(v) (((v) & 0x1) << 9) +#define BFM_MSC_IFLAG_TIME_OUT_RES(v) BM_MSC_IFLAG_TIME_OUT_RES +#define BF_MSC_IFLAG_TIME_OUT_RES_V(e) BF_MSC_IFLAG_TIME_OUT_RES(BV_MSC_IFLAG_TIME_OUT_RES__##e) +#define BFM_MSC_IFLAG_TIME_OUT_RES_V(v) BM_MSC_IFLAG_TIME_OUT_RES +#define BP_MSC_IFLAG_TIME_OUT_READ 8 +#define BM_MSC_IFLAG_TIME_OUT_READ 0x100 +#define BF_MSC_IFLAG_TIME_OUT_READ(v) (((v) & 0x1) << 8) +#define BFM_MSC_IFLAG_TIME_OUT_READ(v) BM_MSC_IFLAG_TIME_OUT_READ +#define BF_MSC_IFLAG_TIME_OUT_READ_V(e) BF_MSC_IFLAG_TIME_OUT_READ(BV_MSC_IFLAG_TIME_OUT_READ__##e) +#define BFM_MSC_IFLAG_TIME_OUT_READ_V(v) BM_MSC_IFLAG_TIME_OUT_READ +#define BP_MSC_IFLAG_SDIO 7 +#define BM_MSC_IFLAG_SDIO 0x80 +#define BF_MSC_IFLAG_SDIO(v) (((v) & 0x1) << 7) +#define BFM_MSC_IFLAG_SDIO(v) BM_MSC_IFLAG_SDIO +#define BF_MSC_IFLAG_SDIO_V(e) BF_MSC_IFLAG_SDIO(BV_MSC_IFLAG_SDIO__##e) +#define BFM_MSC_IFLAG_SDIO_V(v) BM_MSC_IFLAG_SDIO +#define BP_MSC_IFLAG_TXFIFO_WR_REQ 6 +#define BM_MSC_IFLAG_TXFIFO_WR_REQ 0x40 +#define BF_MSC_IFLAG_TXFIFO_WR_REQ(v) (((v) & 0x1) << 6) +#define BFM_MSC_IFLAG_TXFIFO_WR_REQ(v) BM_MSC_IFLAG_TXFIFO_WR_REQ +#define BF_MSC_IFLAG_TXFIFO_WR_REQ_V(e) BF_MSC_IFLAG_TXFIFO_WR_REQ(BV_MSC_IFLAG_TXFIFO_WR_REQ__##e) +#define BFM_MSC_IFLAG_TXFIFO_WR_REQ_V(v) BM_MSC_IFLAG_TXFIFO_WR_REQ +#define BP_MSC_IFLAG_RXFIFO_RD_REQ 5 +#define BM_MSC_IFLAG_RXFIFO_RD_REQ 0x20 +#define BF_MSC_IFLAG_RXFIFO_RD_REQ(v) (((v) & 0x1) << 5) +#define BFM_MSC_IFLAG_RXFIFO_RD_REQ(v) BM_MSC_IFLAG_RXFIFO_RD_REQ +#define BF_MSC_IFLAG_RXFIFO_RD_REQ_V(e) BF_MSC_IFLAG_RXFIFO_RD_REQ(BV_MSC_IFLAG_RXFIFO_RD_REQ__##e) +#define BFM_MSC_IFLAG_RXFIFO_RD_REQ_V(v) BM_MSC_IFLAG_RXFIFO_RD_REQ +#define BP_MSC_IFLAG_END_CMD_RES 2 +#define BM_MSC_IFLAG_END_CMD_RES 0x4 +#define BF_MSC_IFLAG_END_CMD_RES(v) (((v) & 0x1) << 2) +#define BFM_MSC_IFLAG_END_CMD_RES(v) BM_MSC_IFLAG_END_CMD_RES +#define BF_MSC_IFLAG_END_CMD_RES_V(e) BF_MSC_IFLAG_END_CMD_RES(BV_MSC_IFLAG_END_CMD_RES__##e) +#define BFM_MSC_IFLAG_END_CMD_RES_V(v) BM_MSC_IFLAG_END_CMD_RES +#define BP_MSC_IFLAG_PROG_DONE 1 +#define BM_MSC_IFLAG_PROG_DONE 0x2 +#define BF_MSC_IFLAG_PROG_DONE(v) (((v) & 0x1) << 1) +#define BFM_MSC_IFLAG_PROG_DONE(v) BM_MSC_IFLAG_PROG_DONE +#define BF_MSC_IFLAG_PROG_DONE_V(e) BF_MSC_IFLAG_PROG_DONE(BV_MSC_IFLAG_PROG_DONE__##e) +#define BFM_MSC_IFLAG_PROG_DONE_V(v) BM_MSC_IFLAG_PROG_DONE +#define BP_MSC_IFLAG_DATA_TRAN_DONE 0 +#define BM_MSC_IFLAG_DATA_TRAN_DONE 0x1 +#define BF_MSC_IFLAG_DATA_TRAN_DONE(v) (((v) & 0x1) << 0) +#define BFM_MSC_IFLAG_DATA_TRAN_DONE(v) BM_MSC_IFLAG_DATA_TRAN_DONE +#define BF_MSC_IFLAG_DATA_TRAN_DONE_V(e) BF_MSC_IFLAG_DATA_TRAN_DONE(BV_MSC_IFLAG_DATA_TRAN_DONE__##e) +#define BFM_MSC_IFLAG_DATA_TRAN_DONE_V(v) BM_MSC_IFLAG_DATA_TRAN_DONE + +#define REG_MSC_LPM(_n1) jz_reg(MSC_LPM(_n1)) +#define JA_MSC_LPM(_n1) (0xb3450000 + (_n1) * 0x10000 + 0x40) +#define JT_MSC_LPM(_n1) JIO_32_RW +#define JN_MSC_LPM(_n1) MSC_LPM +#define JI_MSC_LPM(_n1) (_n1) +#define BP_MSC_LPM_DRV_SEL 30 +#define BM_MSC_LPM_DRV_SEL 0xc0000000 +#define BV_MSC_LPM_DRV_SEL__FALL_EDGE 0x0 +#define BV_MSC_LPM_DRV_SEL__RISE_EDGE_DELAY_1NS 0x1 +#define BV_MSC_LPM_DRV_SEL__RISE_EDGE_DELAY_QTR_PHASE 0x2 +#define BF_MSC_LPM_DRV_SEL(v) (((v) & 0x3) << 30) +#define BFM_MSC_LPM_DRV_SEL(v) BM_MSC_LPM_DRV_SEL +#define BF_MSC_LPM_DRV_SEL_V(e) BF_MSC_LPM_DRV_SEL(BV_MSC_LPM_DRV_SEL__##e) +#define BFM_MSC_LPM_DRV_SEL_V(v) BM_MSC_LPM_DRV_SEL +#define BP_MSC_LPM_SMP_SEL 28 +#define BM_MSC_LPM_SMP_SEL 0x30000000 +#define BV_MSC_LPM_SMP_SEL__RISE_EDGE 0x0 +#define BV_MSC_LPM_SMP_SEL__RISE_EDGE_DELAYED 0x1 +#define BF_MSC_LPM_SMP_SEL(v) (((v) & 0x3) << 28) +#define BFM_MSC_LPM_SMP_SEL(v) BM_MSC_LPM_SMP_SEL +#define BF_MSC_LPM_SMP_SEL_V(e) BF_MSC_LPM_SMP_SEL(BV_MSC_LPM_SMP_SEL__##e) +#define BFM_MSC_LPM_SMP_SEL_V(v) BM_MSC_LPM_SMP_SEL +#define BP_MSC_LPM_ENABLE 0 +#define BM_MSC_LPM_ENABLE 0x1 +#define BF_MSC_LPM_ENABLE(v) (((v) & 0x1) << 0) +#define BFM_MSC_LPM_ENABLE(v) BM_MSC_LPM_ENABLE +#define BF_MSC_LPM_ENABLE_V(e) BF_MSC_LPM_ENABLE(BV_MSC_LPM_ENABLE__##e) +#define BFM_MSC_LPM_ENABLE_V(v) BM_MSC_LPM_ENABLE + +#define REG_MSC_DMAC(_n1) jz_reg(MSC_DMAC(_n1)) +#define JA_MSC_DMAC(_n1) (0xb3450000 + (_n1) * 0x10000 + 0x44) +#define JT_MSC_DMAC(_n1) JIO_32_RW +#define JN_MSC_DMAC(_n1) MSC_DMAC +#define JI_MSC_DMAC(_n1) (_n1) +#define BP_MSC_DMAC_ADDR_OFFSET 5 +#define BM_MSC_DMAC_ADDR_OFFSET 0x60 +#define BF_MSC_DMAC_ADDR_OFFSET(v) (((v) & 0x3) << 5) +#define BFM_MSC_DMAC_ADDR_OFFSET(v) BM_MSC_DMAC_ADDR_OFFSET +#define BF_MSC_DMAC_ADDR_OFFSET_V(e) BF_MSC_DMAC_ADDR_OFFSET(BV_MSC_DMAC_ADDR_OFFSET__##e) +#define BFM_MSC_DMAC_ADDR_OFFSET_V(v) BM_MSC_DMAC_ADDR_OFFSET +#define BP_MSC_DMAC_INCR 2 +#define BM_MSC_DMAC_INCR 0xc +#define BF_MSC_DMAC_INCR(v) (((v) & 0x3) << 2) +#define BFM_MSC_DMAC_INCR(v) BM_MSC_DMAC_INCR +#define BF_MSC_DMAC_INCR_V(e) BF_MSC_DMAC_INCR(BV_MSC_DMAC_INCR__##e) +#define BFM_MSC_DMAC_INCR_V(v) BM_MSC_DMAC_INCR +#define BP_MSC_DMAC_MODE_SEL 7 +#define BM_MSC_DMAC_MODE_SEL 0x80 +#define BF_MSC_DMAC_MODE_SEL(v) (((v) & 0x1) << 7) +#define BFM_MSC_DMAC_MODE_SEL(v) BM_MSC_DMAC_MODE_SEL +#define BF_MSC_DMAC_MODE_SEL_V(e) BF_MSC_DMAC_MODE_SEL(BV_MSC_DMAC_MODE_SEL__##e) +#define BFM_MSC_DMAC_MODE_SEL_V(v) BM_MSC_DMAC_MODE_SEL +#define BP_MSC_DMAC_ALIGN_EN 4 +#define BM_MSC_DMAC_ALIGN_EN 0x10 +#define BF_MSC_DMAC_ALIGN_EN(v) (((v) & 0x1) << 4) +#define BFM_MSC_DMAC_ALIGN_EN(v) BM_MSC_DMAC_ALIGN_EN +#define BF_MSC_DMAC_ALIGN_EN_V(e) BF_MSC_DMAC_ALIGN_EN(BV_MSC_DMAC_ALIGN_EN__##e) +#define BFM_MSC_DMAC_ALIGN_EN_V(v) BM_MSC_DMAC_ALIGN_EN +#define BP_MSC_DMAC_DMASEL 1 +#define BM_MSC_DMAC_DMASEL 0x2 +#define BF_MSC_DMAC_DMASEL(v) (((v) & 0x1) << 1) +#define BFM_MSC_DMAC_DMASEL(v) BM_MSC_DMAC_DMASEL +#define BF_MSC_DMAC_DMASEL_V(e) BF_MSC_DMAC_DMASEL(BV_MSC_DMAC_DMASEL__##e) +#define BFM_MSC_DMAC_DMASEL_V(v) BM_MSC_DMAC_DMASEL +#define BP_MSC_DMAC_ENABLE 0 +#define BM_MSC_DMAC_ENABLE 0x1 +#define BF_MSC_DMAC_ENABLE(v) (((v) & 0x1) << 0) +#define BFM_MSC_DMAC_ENABLE(v) BM_MSC_DMAC_ENABLE +#define BF_MSC_DMAC_ENABLE_V(e) BF_MSC_DMAC_ENABLE(BV_MSC_DMAC_ENABLE__##e) +#define BFM_MSC_DMAC_ENABLE_V(v) BM_MSC_DMAC_ENABLE + +#define REG_MSC_CTRL2(_n1) jz_reg(MSC_CTRL2(_n1)) +#define JA_MSC_CTRL2(_n1) (0xb3450000 + (_n1) * 0x10000 + 0x58) +#define JT_MSC_CTRL2(_n1) JIO_32_RW +#define JN_MSC_CTRL2(_n1) MSC_CTRL2 +#define JI_MSC_CTRL2(_n1) (_n1) +#define BP_MSC_CTRL2_PIN_INT_POLARITY 24 +#define BM_MSC_CTRL2_PIN_INT_POLARITY 0x1f000000 +#define BF_MSC_CTRL2_PIN_INT_POLARITY(v) (((v) & 0x1f) << 24) +#define BFM_MSC_CTRL2_PIN_INT_POLARITY(v) BM_MSC_CTRL2_PIN_INT_POLARITY +#define BF_MSC_CTRL2_PIN_INT_POLARITY_V(e) BF_MSC_CTRL2_PIN_INT_POLARITY(BV_MSC_CTRL2_PIN_INT_POLARITY__##e) +#define BFM_MSC_CTRL2_PIN_INT_POLARITY_V(v) BM_MSC_CTRL2_PIN_INT_POLARITY +#define BP_MSC_CTRL2_SPEED 0 +#define BM_MSC_CTRL2_SPEED 0x7 +#define BV_MSC_CTRL2_SPEED__DEFAULT 0x0 +#define BV_MSC_CTRL2_SPEED__HIGHSPEED 0x1 +#define BV_MSC_CTRL2_SPEED__SDR12 0x2 +#define BV_MSC_CTRL2_SPEED__SDR25 0x3 +#define BV_MSC_CTRL2_SPEED__SDR50 0x4 +#define BF_MSC_CTRL2_SPEED(v) (((v) & 0x7) << 0) +#define BFM_MSC_CTRL2_SPEED(v) BM_MSC_CTRL2_SPEED +#define BF_MSC_CTRL2_SPEED_V(e) BF_MSC_CTRL2_SPEED(BV_MSC_CTRL2_SPEED__##e) +#define BFM_MSC_CTRL2_SPEED_V(v) BM_MSC_CTRL2_SPEED +#define BP_MSC_CTRL2_STPRM 4 +#define BM_MSC_CTRL2_STPRM 0x10 +#define BF_MSC_CTRL2_STPRM(v) (((v) & 0x1) << 4) +#define BFM_MSC_CTRL2_STPRM(v) BM_MSC_CTRL2_STPRM +#define BF_MSC_CTRL2_STPRM_V(e) BF_MSC_CTRL2_STPRM(BV_MSC_CTRL2_STPRM__##e) +#define BFM_MSC_CTRL2_STPRM_V(v) BM_MSC_CTRL2_STPRM + +#define REG_MSC_CLKRT(_n1) jz_reg(MSC_CLKRT(_n1)) +#define JA_MSC_CLKRT(_n1) (0xb3450000 + (_n1) * 0x10000 + 0x8) +#define JT_MSC_CLKRT(_n1) JIO_32_RW +#define JN_MSC_CLKRT(_n1) MSC_CLKRT +#define JI_MSC_CLKRT(_n1) (_n1) + +#define REG_MSC_RESTO(_n1) jz_reg(MSC_RESTO(_n1)) +#define JA_MSC_RESTO(_n1) (0xb3450000 + (_n1) * 0x10000 + 0x10) +#define JT_MSC_RESTO(_n1) JIO_32_RW +#define JN_MSC_RESTO(_n1) MSC_RESTO +#define JI_MSC_RESTO(_n1) (_n1) + +#define REG_MSC_RDTO(_n1) jz_reg(MSC_RDTO(_n1)) +#define JA_MSC_RDTO(_n1) (0xb3450000 + (_n1) * 0x10000 + 0x14) +#define JT_MSC_RDTO(_n1) JIO_32_RW +#define JN_MSC_RDTO(_n1) MSC_RDTO +#define JI_MSC_RDTO(_n1) (_n1) + +#define REG_MSC_BLKLEN(_n1) jz_reg(MSC_BLKLEN(_n1)) +#define JA_MSC_BLKLEN(_n1) (0xb3450000 + (_n1) * 0x10000 + 0x18) +#define JT_MSC_BLKLEN(_n1) JIO_32_RW +#define JN_MSC_BLKLEN(_n1) MSC_BLKLEN +#define JI_MSC_BLKLEN(_n1) (_n1) + +#define REG_MSC_NOB(_n1) jz_reg(MSC_NOB(_n1)) +#define JA_MSC_NOB(_n1) (0xb3450000 + (_n1) * 0x10000 + 0x1c) +#define JT_MSC_NOB(_n1) JIO_32_RW +#define JN_MSC_NOB(_n1) MSC_NOB +#define JI_MSC_NOB(_n1) (_n1) + +#define REG_MSC_SNOB(_n1) jz_reg(MSC_SNOB(_n1)) +#define JA_MSC_SNOB(_n1) (0xb3450000 + (_n1) * 0x10000 + 0x20) +#define JT_MSC_SNOB(_n1) JIO_32_RW +#define JN_MSC_SNOB(_n1) MSC_SNOB +#define JI_MSC_SNOB(_n1) (_n1) + +#define REG_MSC_CMD(_n1) jz_reg(MSC_CMD(_n1)) +#define JA_MSC_CMD(_n1) (0xb3450000 + (_n1) * 0x10000 + 0x2c) +#define JT_MSC_CMD(_n1) JIO_32_RW +#define JN_MSC_CMD(_n1) MSC_CMD +#define JI_MSC_CMD(_n1) (_n1) + +#define REG_MSC_ARG(_n1) jz_reg(MSC_ARG(_n1)) +#define JA_MSC_ARG(_n1) (0xb3450000 + (_n1) * 0x10000 + 0x30) +#define JT_MSC_ARG(_n1) JIO_32_RW +#define JN_MSC_ARG(_n1) MSC_ARG +#define JI_MSC_ARG(_n1) (_n1) + +#define REG_MSC_RES(_n1) jz_reg(MSC_RES(_n1)) +#define JA_MSC_RES(_n1) (0xb3450000 + (_n1) * 0x10000 + 0x34) +#define JT_MSC_RES(_n1) JIO_32_RW +#define JN_MSC_RES(_n1) MSC_RES +#define JI_MSC_RES(_n1) (_n1) + +#define REG_MSC_RXFIFO(_n1) jz_reg(MSC_RXFIFO(_n1)) +#define JA_MSC_RXFIFO(_n1) (0xb3450000 + (_n1) * 0x10000 + 0x38) +#define JT_MSC_RXFIFO(_n1) JIO_32_RW +#define JN_MSC_RXFIFO(_n1) MSC_RXFIFO +#define JI_MSC_RXFIFO(_n1) (_n1) + +#define REG_MSC_TXFIFO(_n1) jz_reg(MSC_TXFIFO(_n1)) +#define JA_MSC_TXFIFO(_n1) (0xb3450000 + (_n1) * 0x10000 + 0x3c) +#define JT_MSC_TXFIFO(_n1) JIO_32_RW +#define JN_MSC_TXFIFO(_n1) MSC_TXFIFO +#define JI_MSC_TXFIFO(_n1) (_n1) + +#define REG_MSC_DMANDA(_n1) jz_reg(MSC_DMANDA(_n1)) +#define JA_MSC_DMANDA(_n1) (0xb3450000 + (_n1) * 0x10000 + 0x48) +#define JT_MSC_DMANDA(_n1) JIO_32_RW +#define JN_MSC_DMANDA(_n1) MSC_DMANDA +#define JI_MSC_DMANDA(_n1) (_n1) + +#define REG_MSC_DMADA(_n1) jz_reg(MSC_DMADA(_n1)) +#define JA_MSC_DMADA(_n1) (0xb3450000 + (_n1) * 0x10000 + 0x4c) +#define JT_MSC_DMADA(_n1) JIO_32_RW +#define JN_MSC_DMADA(_n1) MSC_DMADA +#define JI_MSC_DMADA(_n1) (_n1) + +#define REG_MSC_DMALEN(_n1) jz_reg(MSC_DMALEN(_n1)) +#define JA_MSC_DMALEN(_n1) (0xb3450000 + (_n1) * 0x10000 + 0x50) +#define JT_MSC_DMALEN(_n1) JIO_32_RW +#define JN_MSC_DMALEN(_n1) MSC_DMALEN +#define JI_MSC_DMALEN(_n1) (_n1) + +#define REG_MSC_DMACMD(_n1) jz_reg(MSC_DMACMD(_n1)) +#define JA_MSC_DMACMD(_n1) (0xb3450000 + (_n1) * 0x10000 + 0x54) +#define JT_MSC_DMACMD(_n1) JIO_32_RW +#define JN_MSC_DMACMD(_n1) MSC_DMACMD +#define JI_MSC_DMACMD(_n1) (_n1) + +#define REG_MSC_RTCNT(_n1) jz_reg(MSC_RTCNT(_n1)) +#define JA_MSC_RTCNT(_n1) (0xb3450000 + (_n1) * 0x10000 + 0x5c) +#define JT_MSC_RTCNT(_n1) JIO_32_RW +#define JN_MSC_RTCNT(_n1) MSC_RTCNT +#define JI_MSC_RTCNT(_n1) (_n1) + +#endif /* __HEADERGEN_MSC_H__*/ diff --git a/firmware/target/mips/ingenic_x1000/x1000/ost.h b/firmware/target/mips/ingenic_x1000/x1000/ost.h new file mode 100644 index 0000000000..8f2619e0e7 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/x1000/ost.h @@ -0,0 +1,141 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * This file was automatically generated by headergen, DO NOT EDIT it. + * headergen version: 3.0.0 + * x1000 version: 1.0 + * x1000 authors: Aidan MacDonald + * + * Copyright (C) 2015 by the authors + * + * 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 __HEADERGEN_OST_H__ +#define __HEADERGEN_OST_H__ + +#include "macro.h" + +#define REG_OST_CTRL jz_reg(OST_CTRL) +#define JA_OST_CTRL (0xb2000000 + 0x0) +#define JT_OST_CTRL JIO_32_RW +#define JN_OST_CTRL OST_CTRL +#define JI_OST_CTRL +#define BP_OST_CTRL_PRESCALE2 3 +#define BM_OST_CTRL_PRESCALE2 0x38 +#define BV_OST_CTRL_PRESCALE2__BY_1 0x0 +#define BV_OST_CTRL_PRESCALE2__BY_4 0x1 +#define BV_OST_CTRL_PRESCALE2__BY_16 0x2 +#define BF_OST_CTRL_PRESCALE2(v) (((v) & 0x7) << 3) +#define BFM_OST_CTRL_PRESCALE2(v) BM_OST_CTRL_PRESCALE2 +#define BF_OST_CTRL_PRESCALE2_V(e) BF_OST_CTRL_PRESCALE2(BV_OST_CTRL_PRESCALE2__##e) +#define BFM_OST_CTRL_PRESCALE2_V(v) BM_OST_CTRL_PRESCALE2 +#define BP_OST_CTRL_PRESCALE1 0 +#define BM_OST_CTRL_PRESCALE1 0x7 +#define BV_OST_CTRL_PRESCALE1__BY_1 0x0 +#define BV_OST_CTRL_PRESCALE1__BY_4 0x1 +#define BV_OST_CTRL_PRESCALE1__BY_16 0x2 +#define BF_OST_CTRL_PRESCALE1(v) (((v) & 0x7) << 0) +#define BFM_OST_CTRL_PRESCALE1(v) BM_OST_CTRL_PRESCALE1 +#define BF_OST_CTRL_PRESCALE1_V(e) BF_OST_CTRL_PRESCALE1(BV_OST_CTRL_PRESCALE1__##e) +#define BFM_OST_CTRL_PRESCALE1_V(v) BM_OST_CTRL_PRESCALE1 + +#define REG_OST_ENABLE jz_reg(OST_ENABLE) +#define JA_OST_ENABLE (0xb2000000 + 0x4) +#define JT_OST_ENABLE JIO_32_RW +#define JN_OST_ENABLE OST_ENABLE +#define JI_OST_ENABLE +#define REG_OST_ENABLE_SET jz_reg(OST_ENABLE_SET) +#define JA_OST_ENABLE_SET (JA_OST_ENABLE + 0x30) +#define JT_OST_ENABLE_SET JIO_32_WO +#define JN_OST_ENABLE_SET OST_ENABLE +#define JI_OST_ENABLE_SET +#define REG_OST_ENABLE_CLR jz_reg(OST_ENABLE_CLR) +#define JA_OST_ENABLE_CLR (JA_OST_ENABLE + 0x34) +#define JT_OST_ENABLE_CLR JIO_32_WO +#define JN_OST_ENABLE_CLR OST_ENABLE +#define JI_OST_ENABLE_CLR +#define BP_OST_ENABLE_OST1 0 +#define BM_OST_ENABLE_OST1 0x1 +#define BF_OST_ENABLE_OST1(v) (((v) & 0x1) << 0) +#define BFM_OST_ENABLE_OST1(v) BM_OST_ENABLE_OST1 +#define BF_OST_ENABLE_OST1_V(e) BF_OST_ENABLE_OST1(BV_OST_ENABLE_OST1__##e) +#define BFM_OST_ENABLE_OST1_V(v) BM_OST_ENABLE_OST1 +#define BP_OST_ENABLE_OST2 1 +#define BM_OST_ENABLE_OST2 0x2 +#define BF_OST_ENABLE_OST2(v) (((v) & 0x1) << 1) +#define BFM_OST_ENABLE_OST2(v) BM_OST_ENABLE_OST2 +#define BF_OST_ENABLE_OST2_V(e) BF_OST_ENABLE_OST2(BV_OST_ENABLE_OST2__##e) +#define BFM_OST_ENABLE_OST2_V(v) BM_OST_ENABLE_OST2 + +#define REG_OST_CLEAR jz_reg(OST_CLEAR) +#define JA_OST_CLEAR (0xb2000000 + 0x8) +#define JT_OST_CLEAR JIO_32_RW +#define JN_OST_CLEAR OST_CLEAR +#define JI_OST_CLEAR +#define BP_OST_CLEAR_OST1 0 +#define BM_OST_CLEAR_OST1 0x1 +#define BF_OST_CLEAR_OST1(v) (((v) & 0x1) << 0) +#define BFM_OST_CLEAR_OST1(v) BM_OST_CLEAR_OST1 +#define BF_OST_CLEAR_OST1_V(e) BF_OST_CLEAR_OST1(BV_OST_CLEAR_OST1__##e) +#define BFM_OST_CLEAR_OST1_V(v) BM_OST_CLEAR_OST1 +#define BP_OST_CLEAR_OST2 1 +#define BM_OST_CLEAR_OST2 0x2 +#define BF_OST_CLEAR_OST2(v) (((v) & 0x1) << 1) +#define BFM_OST_CLEAR_OST2(v) BM_OST_CLEAR_OST2 +#define BF_OST_CLEAR_OST2_V(e) BF_OST_CLEAR_OST2(BV_OST_CLEAR_OST2__##e) +#define BFM_OST_CLEAR_OST2_V(v) BM_OST_CLEAR_OST2 + +#define REG_OST_1FLG jz_reg(OST_1FLG) +#define JA_OST_1FLG (0xb2000000 + 0xc) +#define JT_OST_1FLG JIO_32_RW +#define JN_OST_1FLG OST_1FLG +#define JI_OST_1FLG + +#define REG_OST_1MSK jz_reg(OST_1MSK) +#define JA_OST_1MSK (0xb2000000 + 0x10) +#define JT_OST_1MSK JIO_32_RW +#define JN_OST_1MSK OST_1MSK +#define JI_OST_1MSK + +#define REG_OST_1DFR jz_reg(OST_1DFR) +#define JA_OST_1DFR (0xb2000000 + 0x14) +#define JT_OST_1DFR JIO_32_RW +#define JN_OST_1DFR OST_1DFR +#define JI_OST_1DFR + +#define REG_OST_1CNT jz_reg(OST_1CNT) +#define JA_OST_1CNT (0xb2000000 + 0x18) +#define JT_OST_1CNT JIO_32_RW +#define JN_OST_1CNT OST_1CNT +#define JI_OST_1CNT + +#define REG_OST_2CNTH jz_reg(OST_2CNTH) +#define JA_OST_2CNTH (0xb2000000 + 0x1c) +#define JT_OST_2CNTH JIO_32_RW +#define JN_OST_2CNTH OST_2CNTH +#define JI_OST_2CNTH + +#define REG_OST_2CNTL jz_reg(OST_2CNTL) +#define JA_OST_2CNTL (0xb2000000 + 0x20) +#define JT_OST_2CNTL JIO_32_RW +#define JN_OST_2CNTL OST_2CNTL +#define JI_OST_2CNTL + +#define REG_OST_2CNTHB jz_reg(OST_2CNTHB) +#define JA_OST_2CNTHB (0xb2000000 + 0x24) +#define JT_OST_2CNTHB JIO_32_RW +#define JN_OST_2CNTHB OST_2CNTHB +#define JI_OST_2CNTHB + +#endif /* __HEADERGEN_OST_H__*/ diff --git a/firmware/target/mips/ingenic_x1000/x1000/rtc.h b/firmware/target/mips/ingenic_x1000/x1000/rtc.h new file mode 100644 index 0000000000..38f82e7d0d --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/x1000/rtc.h @@ -0,0 +1,221 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * This file was automatically generated by headergen, DO NOT EDIT it. + * headergen version: 3.0.0 + * x1000 version: 1.0 + * x1000 authors: Aidan MacDonald + * + * Copyright (C) 2015 by the authors + * + * 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 __HEADERGEN_RTC_H__ +#define __HEADERGEN_RTC_H__ + +#include "macro.h" + +#define REG_RTC_CR jz_reg(RTC_CR) +#define JA_RTC_CR (0xb0003000 + 0x0) +#define JT_RTC_CR JIO_32_RW +#define JN_RTC_CR RTC_CR +#define JI_RTC_CR +#define BP_RTC_CR_WRDY 7 +#define BM_RTC_CR_WRDY 0x80 +#define BF_RTC_CR_WRDY(v) (((v) & 0x1) << 7) +#define BFM_RTC_CR_WRDY(v) BM_RTC_CR_WRDY +#define BF_RTC_CR_WRDY_V(e) BF_RTC_CR_WRDY(BV_RTC_CR_WRDY__##e) +#define BFM_RTC_CR_WRDY_V(v) BM_RTC_CR_WRDY +#define BP_RTC_CR_1HZ 6 +#define BM_RTC_CR_1HZ 0x40 +#define BF_RTC_CR_1HZ(v) (((v) & 0x1) << 6) +#define BFM_RTC_CR_1HZ(v) BM_RTC_CR_1HZ +#define BF_RTC_CR_1HZ_V(e) BF_RTC_CR_1HZ(BV_RTC_CR_1HZ__##e) +#define BFM_RTC_CR_1HZ_V(v) BM_RTC_CR_1HZ +#define BP_RTC_CR_1HZIE 5 +#define BM_RTC_CR_1HZIE 0x20 +#define BF_RTC_CR_1HZIE(v) (((v) & 0x1) << 5) +#define BFM_RTC_CR_1HZIE(v) BM_RTC_CR_1HZIE +#define BF_RTC_CR_1HZIE_V(e) BF_RTC_CR_1HZIE(BV_RTC_CR_1HZIE__##e) +#define BFM_RTC_CR_1HZIE_V(v) BM_RTC_CR_1HZIE +#define BP_RTC_CR_AF 4 +#define BM_RTC_CR_AF 0x10 +#define BF_RTC_CR_AF(v) (((v) & 0x1) << 4) +#define BFM_RTC_CR_AF(v) BM_RTC_CR_AF +#define BF_RTC_CR_AF_V(e) BF_RTC_CR_AF(BV_RTC_CR_AF__##e) +#define BFM_RTC_CR_AF_V(v) BM_RTC_CR_AF +#define BP_RTC_CR_AIE 3 +#define BM_RTC_CR_AIE 0x8 +#define BF_RTC_CR_AIE(v) (((v) & 0x1) << 3) +#define BFM_RTC_CR_AIE(v) BM_RTC_CR_AIE +#define BF_RTC_CR_AIE_V(e) BF_RTC_CR_AIE(BV_RTC_CR_AIE__##e) +#define BFM_RTC_CR_AIE_V(v) BM_RTC_CR_AIE +#define BP_RTC_CR_AE 2 +#define BM_RTC_CR_AE 0x4 +#define BF_RTC_CR_AE(v) (((v) & 0x1) << 2) +#define BFM_RTC_CR_AE(v) BM_RTC_CR_AE +#define BF_RTC_CR_AE_V(e) BF_RTC_CR_AE(BV_RTC_CR_AE__##e) +#define BFM_RTC_CR_AE_V(v) BM_RTC_CR_AE +#define BP_RTC_CR_SELEXC 1 +#define BM_RTC_CR_SELEXC 0x2 +#define BF_RTC_CR_SELEXC(v) (((v) & 0x1) << 1) +#define BFM_RTC_CR_SELEXC(v) BM_RTC_CR_SELEXC +#define BF_RTC_CR_SELEXC_V(e) BF_RTC_CR_SELEXC(BV_RTC_CR_SELEXC__##e) +#define BFM_RTC_CR_SELEXC_V(v) BM_RTC_CR_SELEXC +#define BP_RTC_CR_ENABLE 0 +#define BM_RTC_CR_ENABLE 0x1 +#define BF_RTC_CR_ENABLE(v) (((v) & 0x1) << 0) +#define BFM_RTC_CR_ENABLE(v) BM_RTC_CR_ENABLE +#define BF_RTC_CR_ENABLE_V(e) BF_RTC_CR_ENABLE(BV_RTC_CR_ENABLE__##e) +#define BFM_RTC_CR_ENABLE_V(v) BM_RTC_CR_ENABLE + +#define REG_RTC_SR jz_reg(RTC_SR) +#define JA_RTC_SR (0xb0003000 + 0x4) +#define JT_RTC_SR JIO_32_RW +#define JN_RTC_SR RTC_SR +#define JI_RTC_SR + +#define REG_RTC_SAR jz_reg(RTC_SAR) +#define JA_RTC_SAR (0xb0003000 + 0x8) +#define JT_RTC_SAR JIO_32_RW +#define JN_RTC_SAR RTC_SAR +#define JI_RTC_SAR + +#define REG_RTC_GR jz_reg(RTC_GR) +#define JA_RTC_GR (0xb0003000 + 0xc) +#define JT_RTC_GR JIO_32_RW +#define JN_RTC_GR RTC_GR +#define JI_RTC_GR +#define BP_RTC_GR_ADJC 16 +#define BM_RTC_GR_ADJC 0x3ff0000 +#define BF_RTC_GR_ADJC(v) (((v) & 0x3ff) << 16) +#define BFM_RTC_GR_ADJC(v) BM_RTC_GR_ADJC +#d |