From 94537f954e67d44fdd9703c062c4ee53599e0e74 Mon Sep 17 00:00:00 2001 From: Michael Sevakis Date: Sun, 8 Feb 2009 22:32:41 +0000 Subject: Gigabeat S: Implement an SDMA API and use it in the PCM driver. Some other miscellaneous adjustments to recording and PCM buffer to accomodate use of physical addresses and cache coherency. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19949 a1c6a512-1295-4272-9138-f99709370657 --- firmware/SOURCES | 2 +- firmware/export/config-gigabeat-s.h | 2 + firmware/export/imx31l.h | 151 +++ firmware/export/pcm.h | 4 + firmware/pcm.c | 3 +- firmware/target/arm/imx31/debug-imx31.c | 4 + .../target/arm/imx31/gigabeat-s/clkctl-imx31.c | 18 +- .../target/arm/imx31/gigabeat-s/clkctl-imx31.h | 3 + firmware/target/arm/imx31/gigabeat-s/dma_start.c | 8 - .../target/arm/imx31/gigabeat-s/kernel-imx31.c | 4 + firmware/target/arm/imx31/gigabeat-s/mmu-imx31.c | 21 +- firmware/target/arm/imx31/gigabeat-s/mmu-imx31.h | 2 + firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c | 366 +++++-- .../target/arm/imx31/gigabeat-s/system-imx31.c | 24 + .../target/arm/imx31/gigabeat-s/system-target.h | 2 + firmware/target/arm/imx31/sdma-imx31.c | 807 +++++++++++++++ firmware/target/arm/imx31/sdma-imx31.h | 225 +++++ firmware/target/arm/imx31/sdma_script_code.h | 1060 ++++++++++++++++++++ firmware/target/arm/imx31/sdma_struct.h | 426 ++++++++ 19 files changed, 2994 insertions(+), 138 deletions(-) delete mode 100644 firmware/target/arm/imx31/gigabeat-s/dma_start.c create mode 100644 firmware/target/arm/imx31/sdma-imx31.c create mode 100644 firmware/target/arm/imx31/sdma-imx31.h create mode 100644 firmware/target/arm/imx31/sdma_script_code.h create mode 100644 firmware/target/arm/imx31/sdma_struct.h (limited to 'firmware') diff --git a/firmware/SOURCES b/firmware/SOURCES index 67a6a8a93a..0073b41f9f 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -756,7 +756,6 @@ target/arm/imx31/gigabeat-s/avic-imx31.c target/arm/imx31/gigabeat-s/backlight-imx31.c target/arm/imx31/gigabeat-s/button-imx31.c target/arm/imx31/gigabeat-s/clkctl-imx31.c -target/arm/imx31/gigabeat-s/dma_start.c target/arm/imx31/gigabeat-s/gpio-gigabeat-s.c target/arm/imx31/gigabeat-s/gpio-imx31.c target/arm/imx31/gigabeat-s/kernel-imx31.c @@ -773,6 +772,7 @@ target/arm/imx31/gigabeat-s/system-imx31.c target/arm/imx31/gigabeat-s/usb-imx31.c target/arm/imx31/gigabeat-s/wmcodec-imx31.c #ifndef BOOTLOADER +target/arm/imx31/sdma-imx31.c target/arm/imx31/gigabeat-s/audio-gigabeat-s.c target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c target/arm/imx31/gigabeat-s/headphone-gigabeat-s.c diff --git a/firmware/export/config-gigabeat-s.h b/firmware/export/config-gigabeat-s.h index 6b993b6082..e5654fe0a2 100644 --- a/firmware/export/config-gigabeat-s.h +++ b/firmware/export/config-gigabeat-s.h @@ -214,6 +214,8 @@ /* Define this if you have adjustable CPU frequency */ /* #define HAVE_ADJUSTABLE_CPU_FREQ */ +#define HAVE_PCM_DMA_ADDRESS + #define BOOTFILE_EXT "gigabeat" #define BOOTFILE "rockbox." BOOTFILE_EXT #define BOOTDIR "/.rockbox" diff --git a/firmware/export/imx31l.h b/firmware/export/imx31l.h index e31f30f1b0..cdae29f158 100755 --- a/firmware/export/imx31l.h +++ b/firmware/export/imx31l.h @@ -118,6 +118,22 @@ #define WDOG1_BASE_ADDR WDOG_BASE_ADDR #define CRM_MCU_BASE_ADDR CCM_BASE_ADDR +/* IIM */ +#define IIM_PREV (*(REG32_PTR_T)(IIM_BASE_ADDR + 0x20)) + #define IIM_PREV_SIG (0x1f << 3) + #define IIM_PREV_SIG_IMX31 (0x01 << 3) /* i.MX31 */ +#define IIM_SREV (*(REG32_PTR_T)(IIM_BASE_ADDR + 0x24)) + #define IIM_SREV_SREV (0xff << 0) + #define IIM_SREV_1_0 0x00 /* i.MX31/L 1.0, L38W */ + #define IIM_SREV_1_1 0x10 /* i.MX31 1.1, 2L38W */ + #define IIM_SREV_1_1L 0x11 /* i.MX31L 1.1, 2L38W */ + #define IIM_SREV_1_15 0x12 /* i.MX31 1.15, 2L38W/3L38W */ + #define IIM_SREV_1_15L 0x13 /* i.MX31L 1.15, 2L38W/3L38W */ + #define IIM_SREV_1_2 0x14 /* i.MX31 1.2, 3L38W, M45G */ + #define IIM_SREV_1_2L 0x15 /* i.MX31L 1.2, 3L38W, M45G */ + #define IIM_SREV_2_0_1 0x28 /* i.MX31 2.0/2.0.1, M91E */ + #define IIM_SREV_2_0_1L 0x29 /* i.MX31L 2.0/2.0.1, M91E */ + /* IOMUXC */ #define IOMUXC_(o) (*(REG32_PTR_T)(IOMUXC_BASE_ADDR+(o))) @@ -1618,6 +1634,141 @@ #define EUARTUTS_RXFULL (1 << 3) // RxFIFO full #define EUARTUTS_SOFTRST (1 << 0) // Software reset +/* SDMA */ +#define SDMA_MC0PTR (*(REG32_PTR_T)(SDMA_BASE_ADDR + 0x000)) +#define SDMA_INTR (*(REG32_PTR_T)(SDMA_BASE_ADDR + 0x004)) +#define SDMA_STOP_STAT (*(REG32_PTR_T)(SDMA_BASE_ADDR + 0x008)) +#define SDMA_HSTART (*(REG32_PTR_T)(SDMA_BASE_ADDR + 0x00C)) +#define SDMA_EVTOVR (*(REG32_PTR_T)(SDMA_BASE_ADDR + 0x010)) +#define SDMA_DSPOVR (*(REG32_PTR_T)(SDMA_BASE_ADDR + 0x014)) +#define SDMA_HOSTOVR (*(REG32_PTR_T)(SDMA_BASE_ADDR + 0x018)) +#define SDMA_EVTPEND (*(REG32_PTR_T)(SDMA_BASE_ADDR + 0x01C)) +#define SDMA_DSPENBL (*(REG32_PTR_T)(SDMA_BASE_ADDR + 0x020)) +#define SDMA_RESET (*(REG32_PTR_T)(SDMA_BASE_ADDR + 0x024)) +#define SDMA_EVTERR (*(REG32_PTR_T)(SDMA_BASE_ADDR + 0x028)) +#define SDMA_INTRMSK (*(REG32_PTR_T)(SDMA_BASE_ADDR + 0x02C)) +#define SDMA_PSW (*(REG32_PTR_T)(SDMA_BASE_ADDR + 0x030)) +#define SDMA_EVTERRDBG (*(REG32_PTR_T)(SDMA_BASE_ADDR + 0x034)) +#define SDMA_CONFIG (*(REG32_PTR_T)(SDMA_BASE_ADDR + 0x038)) +#define SDMA_ONCE_ENB (*(REG32_PTR_T)(SDMA_BASE_ADDR + 0x040)) +#define SDMA_ONCE_DATA (*(REG32_PTR_T)(SDMA_BASE_ADDR + 0x044)) +#define SDMA_ONCE_INSTR (*(REG32_PTR_T)(SDMA_BASE_ADDR + 0x048)) +#define SDMA_ONCE_STAT (*(REG32_PTR_T)(SDMA_BASE_ADDR + 0x04C)) +#define SDMA_ONCE_CMD (*(REG32_PTR_T)(SDMA_BASE_ADDR + 0x050)) +#define SDMA_EVT_MIRROR (*(REG32_PTR_T)(SDMA_BASE_ADDR + 0x054)) +#define SDMA_ILLINSTADDR (*(REG32_PTR_T)(SDMA_BASE_ADDR + 0x058)) +#define SDMA_CHN0ADDR (*(REG32_PTR_T)(SDMA_BASE_ADDR + 0x05C)) +#define SDMA_ONCE_RTB (*(REG32_PTR_T)(SDMA_BASE_ADDR + 0x060)) +#define SDMA_XTRIG_CONF1 (*(REG32_PTR_T)(SDMA_BASE_ADDR + 0x070)) +#define SDMA_XTRIG_CONF2 (*(REG32_PTR_T)(SDMA_BASE_ADDR + 0x074)) + +/* SDMA_CHNENBL: 0x080 - 0x0FC */ +#define SDMA_CHNENBL(n) (((REG32_PTR_T)(SDMA_BASE_ADDR + 0x080))[n]) /* 0..31 */ + +/* SDMA_CHNPRI: 0x100 - 0x17C */ +#define SDMA_CHNPRI(n) (((REG32_PTR_T)(SDMA_BASE_ADDR + 0x100))[n]) /* 0..31 */ + +#define SDMA_ONCE_COUNT (*(REG32_PTR_T)(SDMA_BASE_ADDR + 0x200)) +#define SDMA_ONCE_ECTL (*(REG32_PTR_T)(SDMA_BASE_ADDR + 0x204)) +#define SDMA_ONCE_EAA (*(REG32_PTR_T)(SDMA_BASE_ADDR + 0x208)) +#define SDMA_ONCE_EAB (*(REG32_PTR_T)(SDMA_BASE_ADDR + 0x20C)) +#define SDMA_ONCE_EAM (*(REG32_PTR_T)(SDMA_BASE_ADDR + 0x210)) +#define SDMA_ONCE_ED (*(REG32_PTR_T)(SDMA_BASE_ADDR + 0x214)) +#define SDMA_ONCE_EDM (*(REG32_PTR_T)(SDMA_BASE_ADDR + 0x218)) +#define SDMA_ONCE_PCMATCH (*(REG32_PTR_T)(SDMA_BASE_ADDR + 0x21C)) + +/* SDMA_RESET */ +#define SDMA_RESET_RESCHED (0x1 << 1) +#define SDMA_RESET_RESET (0x1 << 0) + +/* SDMA_PSW */ +#define SDMA_PSW_NCP (0x7 << 13) +#define SDMA_PSW_NCR (0x1f << 8) +#define SDMA_PSW_CCP (0x7 << 5) +#define SDMA_PSW_CCR (0x1f << 0) + +/* SDMA_CONFIG */ +#define SDMA_CONFIG_DSPDMA (0x1 << 12) +#define SDMA_CONFIG_RTDOBS (0x1 << 11) +#define SDMA_CONFIG_ACR (0x1 << 4) +#define SDMA_CONFIG_CSM (0x3 << 0) + #define SDMA_CONFIG_CSM_STATIC (0x0 << 0) + #define SDMA_CONFIG_CSM_DYNAMIC_LOW_POWER (0x1 << 0) + #define SDMA_CONFIG_CSM_DYNAMIC_NO_LOOP (0x2 << 0) + #define SDMA_CONFIG_CSM_DYNAMIC (0x3 << 0) + +/* SDMA_ONCE_ENB */ +#define SDMA_ONCE_ENB_ENB (0x1 << 0) + +/* SDMA_ONCE_STAT */ +#define SDMA_ONCE_STAT_PST (0xf << 12) + #define SDMA_ONCE_STAT_PST_PROGRAM (0x0 << 12) + #define SDMA_ONCE_STAT_PST_DATA (0x1 << 12) + #define SDMA_ONCE_STAT_PST_CHANGE_OF_FLOW (0x2 << 12) + #define SDMA_ONCE_STAT_PST_CHANGE_OF_FLOW_IN_LOOP (0x3 << 12) + #define SDMA_ONCE_STAT_PST_DEBUG (0x4 << 12) + #define SDMA_ONCE_STAT_PST_FUNCTIONAL_UNIT (0x5 << 12) + #define SDMA_ONCE_STAT_PST_SLEEP (0x6 << 12) + #define SDMA_ONCE_STAT_PST_SAVE (0x7 << 12) + #define SDMA_ONCE_STAT_PST_PROGRAM_IN_SLEEP (0x8 << 12) + #define SDMA_ONCE_STAT_PST_DATA_IN_SLEEP (0x9 << 12) + #define SDMA_ONCE_STAT_PST_CHANGE_OF_FLOW_IN_SLEEP (0xa << 12) + #define SDMA_ONCE_STAT_PST_CHANGE_OF_FLOW_IN_LOOP_IN_SLEEP (0xb << 12) + #define SDMA_ONCE_STAT_PST_DEBUG_IN_SLEEP (0xc << 12) + #define SDMA_ONCE_STAT_PST_FUNCTIONAL_UNIT_IN_SLEEP (0xd << 12) + #define SDMA_ONCE_STAT_PST_SLEEP_AFTER_RESET (0xe << 12) + #define SDMA_ONCE_STAT_PST_RESTORE (0xf << 12) +#define SDMA_ONCE_STAT_RCV (0x1 << 11) +#define SDMA_ONCE_STAT_EDR (0x1 << 10) +#define SDMA_ONCE_STAT_ODR (0x1 << 9) +#define SDMA_ONCE_STAT_SWB (0x1 << 8) +#define SDMA_ONCE_STAT_MST (0x1 << 7) +#define SDMA_ONCE_STAT_ECDR (0x7 << 0) + #define SDMA_ONCE_STAT_ECDR_MATCHED_ADDRA_COND (0x1 << 0) + #define SDMA_ONCE_STAT_ECDR_MATCHED_ADDRB_COND (0x1 << 1) + #define SDMA_ONCE_STAT_ECDR_MATCHED_DATA_COND (0x1 << 2) + +/* SDMA_ONCE_CMD */ +#define SDMA_ONCE_CMD_RSTATUS 0x0 +#define SDMA_ONCE_CMD_DMOV 0x1 +#define SDMA_ONCE_CMD_EXEC_ONCE 0x2 +#define SDMA_ONCE_CMD_RUN_CORE 0x3 +#define SDMA_ONCE_CMD_EXEC_CORE 0x4 +#define SDMA_ONCE_CMD_DEBUG_RQST 0x5 +#define SDMA_ONCE_CMD_RBUFFER 0x6 +/* 7-15 reserved */ + +/* SDMA_CHN0ADDR */ +#define SDMA_CHN0ADDR_SMSZ (0x1 << 14) +/* 13:0 = 0x0050 by default (std. boot code) */ + +/* SDMA_EVT_MIRROR */ +#define SDMA_EVT_MIRROR_EVENTS(n) (0x1 << (n)) + +/* SDMA_XTRIG_CONF1 */ +#define SDMA_XTRIG_CONF1_CNF3 (0x1 << 30) +#define SDMA_XTRIG_CONF1_NUM3 (0x1f << 24) +#define SDMA_XTRIG_CONF1_CNF2 (0x1 << 22) +#define SDMA_XTRIG_CONF1_NUM2 (0x1f << 16) +#define SDMA_XTRIG_CONF1_CNF1 (0x1 << 14) +#define SDMA_XTRIG_CONF1_NUM1 (0x1f << 8) +#define SDMA_XTRIG_CONF1_CNF0 (0x1 << 6) +#define SDMA_XTRIG_CONF1_NUM0 (0x1f << 0) + +/* SDMA_XTRIG_CONF2 */ +#define SDMA_XTRIG_CONF2_CNF7 (0x1 << 30) +#define SDMA_XTRIG_CONF2_NUM7 (0x1f << 24) +#define SDMA_XTRIG_CONF2_CNF6 (0x1 << 22) +#define SDMA_XTRIG_CONF2_NUM6 (0x1f << 16) +#define SDMA_XTRIG_CONF2_CNF5 (0x1 << 14) +#define SDMA_XTRIG_CONF2_NUM5 (0x1f << 8) +#define SDMA_XTRIG_CONF2_CNF4 (0x1 << 6) +#define SDMA_XTRIG_CONF2_NUM4 (0x1f << 0) + +/* SDMA_CHNENBL(n) */ +#define SDMA_CHNENBL_ENBL(n) (0x1 << (n)) + + #define L2CC_ENABLED /* Assuming 26MHz input clock */ diff --git a/firmware/export/pcm.h b/firmware/export/pcm.h index 053f954767..444e0c9c09 100644 --- a/firmware/export/pcm.h +++ b/firmware/export/pcm.h @@ -90,6 +90,10 @@ extern unsigned long pcm_curr_sampr; extern unsigned long pcm_sampr; extern int pcm_fsel; +#ifdef HAVE_PCM_DMA_ADDRESS +void * pcm_dma_addr(void *addr); +#endif + /* the registered callback function to ask for more mp3 data */ extern volatile pcm_more_callback_type pcm_callback_for_more; extern volatile bool pcm_playing; diff --git a/firmware/pcm.c b/firmware/pcm.c index 38204f883b..bc7ec0282a 100644 --- a/firmware/pcm.c +++ b/firmware/pcm.c @@ -53,6 +53,7 @@ * ==Playback/Recording== * Semi-private - * pcm_dma_apply_settings + * pcm_dma_addr * * ==Recording== * Public - @@ -65,7 +66,7 @@ * pcm_rec_dma_stop * pcm_rec_dma_get_peak_buffer * Data Read/Written within TSP - - * pcm_rec_peak_addr (R) + * pcm_rec_peak_addr (R/W) * pcm_callback_more_ready (R) * pcm_recording (R) * diff --git a/firmware/target/arm/imx31/debug-imx31.c b/firmware/target/arm/imx31/debug-imx31.c index b72390cb63..ad436ea231 100644 --- a/firmware/target/arm/imx31/debug-imx31.c +++ b/firmware/target/arm/imx31/debug-imx31.c @@ -46,6 +46,10 @@ bool __dbg_hw_info(void) while (1) { line = 0; + snprintf(buf, sizeof (buf), "Sys Rev Code: 0x%02X", + iim_system_rev()); + lcd_puts(0, line++, buf); line++; + mpctl = CLKCTL_MPCTL; spctl = CLKCTL_SPCTL; upctl = CLKCTL_UPCTL; diff --git a/firmware/target/arm/imx31/gigabeat-s/clkctl-imx31.c b/firmware/target/arm/imx31/gigabeat-s/clkctl-imx31.c index 784a3f6586..df592deecb 100644 --- a/firmware/target/arm/imx31/gigabeat-s/clkctl-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/clkctl-imx31.c @@ -24,6 +24,11 @@ #include "cpu.h" #include "clkctl-imx31.h" +unsigned int imx31_get_src_pll(void) +{ + return (CLKCTL_PMCR0 & 0xC0000000) == 0 ? PLL_SERIAL : PLL_MCU; +} + void imx31_clkctl_module_clock_gating(enum IMX31_CG_LIST cg, enum IMX31_CG_MODES mode) { @@ -72,8 +77,8 @@ unsigned int imx31_clkctl_get_pll(enum IMX31_PLLS pll) unsigned int imx31_clkctl_get_ipg_clk(void) { - unsigned int pll = imx31_clkctl_get_pll((CLKCTL_PMCR0 & 0xC0000000) == 0 ? - PLL_SERIAL : PLL_MCU); + unsigned int pllnum = imx31_get_src_pll(); + unsigned int pll = imx31_clkctl_get_pll(pllnum); uint32_t reg = CLKCTL_PDR0; unsigned int max_pdf = ((reg >> 3) & 0x7) + 1; unsigned int ipg_pdf = ((reg >> 6) & 0x3) + 1; @@ -81,6 +86,15 @@ unsigned int imx31_clkctl_get_ipg_clk(void) return pll / (max_pdf * ipg_pdf); } +unsigned int imx31_clkctl_get_ahb_clk(void) +{ + unsigned int pllnum = imx31_get_src_pll(); + unsigned int pll = imx31_clkctl_get_pll(pllnum); + unsigned int max_pdf = ((CLKCTL_PDR0 >> 3) & 0x7) + 1; + + return pll / max_pdf; +} + unsigned int imx31_clkctl_get_ata_clk(void) { return imx31_clkctl_get_ipg_clk(); diff --git a/firmware/target/arm/imx31/gigabeat-s/clkctl-imx31.h b/firmware/target/arm/imx31/gigabeat-s/clkctl-imx31.h index 8d7f7dbb77..bd8f89a15b 100644 --- a/firmware/target/arm/imx31/gigabeat-s/clkctl-imx31.h +++ b/firmware/target/arm/imx31/gigabeat-s/clkctl-imx31.h @@ -105,6 +105,9 @@ unsigned int imx31_clkctl_get_pll(enum IMX31_PLLS pll); /* Return ipg_clk in HZ */ unsigned int imx31_clkctl_get_ipg_clk(void); +/* Return ahb_clk in HZ */ +unsigned int imx31_clkctl_get_ahb_clk(void); + /* Return the ATA frequency in HZ */ unsigned int imx31_clkctl_get_ata_clk(void); diff --git a/firmware/target/arm/imx31/gigabeat-s/dma_start.c b/firmware/target/arm/imx31/gigabeat-s/dma_start.c deleted file mode 100644 index c1ab6c15cb..0000000000 --- a/firmware/target/arm/imx31/gigabeat-s/dma_start.c +++ /dev/null @@ -1,8 +0,0 @@ -#include - -void dma_start(const void* addr, size_t size) { - (void) addr; - (void) size; - //TODO: -} - diff --git a/firmware/target/arm/imx31/gigabeat-s/kernel-imx31.c b/firmware/target/arm/imx31/gigabeat-s/kernel-imx31.c index 3d7c577e3c..ff0c47abc2 100644 --- a/firmware/target/arm/imx31/gigabeat-s/kernel-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/kernel-imx31.c @@ -24,6 +24,7 @@ #include "spi-imx31.h" #include "mc13783.h" #include "clkctl-imx31.h" +#include "sdma-imx31.h" #include "kernel.h" #include "thread.h" @@ -64,6 +65,9 @@ void tick_start(unsigned int interval_in_ms) void kernel_device_init(void) { +#ifndef BOOTLOADER + sdma_init(); +#endif spi_init(); mc13783_init(); } diff --git a/firmware/target/arm/imx31/gigabeat-s/mmu-imx31.c b/firmware/target/arm/imx31/gigabeat-s/mmu-imx31.c index 05de50c269..920a8c9fd3 100644 --- a/firmware/target/arm/imx31/gigabeat-s/mmu-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/mmu-imx31.c @@ -22,21 +22,12 @@ #include "mmu-imx31.h" #include "mmu-arm.h" -void memory_init(void) { -#if 0 - ttb_init(); - set_page_tables(); - enable_mmu(); -#endif +unsigned long addr_virt_to_phys(unsigned long addr) +{ + return addr | CSD0_BASE_ADDR; } -void set_page_tables() { -#if 0 - map_section(0, 0, 0x1000, CACHE_NONE); /* map every memory region to itself */ - /*This pa *might* change*/ - map_section(0x80000000, 0, 64, CACHE_ALL); /* map RAM to 0 and enable caching for it */ - map_section((int)FRAME1, (int)FRAME1, 1, BUFFERED); /* enable buffered writing for the framebuffer */ - map_section((int)FRAME2, (int)FRAME2, 1, BUFFERED); -#endif +unsigned long addr_phys_to_virt(unsigned long addr) +{ + return addr & ~CSD0_BASE_ADDR; } - diff --git a/firmware/target/arm/imx31/gigabeat-s/mmu-imx31.h b/firmware/target/arm/imx31/gigabeat-s/mmu-imx31.h index 930048c59b..c66a3d941d 100644 --- a/firmware/target/arm/imx31/gigabeat-s/mmu-imx31.h +++ b/firmware/target/arm/imx31/gigabeat-s/mmu-imx31.h @@ -23,5 +23,7 @@ void memory_init(void); void set_page_tables(void); +unsigned long addr_virt_to_phys(unsigned long addr); +unsigned long addr_phys_to_virt(unsigned long addr); #endif /* MMU_IMX31_H */ diff --git a/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c b/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c index f53d98aee9..60801262b4 100644 --- a/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c @@ -23,78 +23,93 @@ #include "kernel.h" #include "audio.h" #include "sound.h" -#include "avic-imx31.h" #include "clkctl-imx31.h" +#include "sdma-imx31.h" +#include "mmu-imx31.h" -/* This isn't DMA-based at the moment and is handled like Portal Player but - * will suffice for starters. */ +#define DMA_PLAY_CH_NUM 2 +#define DMA_REC_CH_NUM 1 + +static struct buffer_descriptor dma_play_bd DEVBSS_ATTR; +static struct channel_descriptor dma_play_cd DEVBSS_ATTR; struct dma_data { - uint16_t *p; - size_t size; int locked; + int callback_pending; /* DMA interrupt happened while locked */ int state; }; static struct dma_data dma_play_data = { /* Initialize to a locked, stopped state */ - .p = NULL, - .size = 0, .locked = 0, + .callback_pending = 0, .state = 0 }; -void pcm_play_lock(void) +static void play_dma_callback(void) { - if (++dma_play_data.locked == 1) + unsigned char *start; + size_t size; + pcm_more_callback_type get_more = pcm_callback_for_more; + + if (dma_play_data.locked) { - /* Atomically disable transmit interrupt */ - imx31_regclr32(&SSI_SIER1, SSI_SIER_TIE); + /* Callback is locked out */ + dma_play_data.callback_pending = 1; + return; } -} -void pcm_play_unlock(void) -{ - if (--dma_play_data.locked == 0 && dma_play_data.state != 0) + if (get_more == NULL || (get_more(&start, &size), size == 0)) { - /* Atomically enable transmit interrupt */ - imx31_regset32(&SSI_SIER1, SSI_SIER_TIE); + /* Callback missing or no more DMA to do */ + pcm_play_dma_stop(); + pcm_play_dma_stopped_callback(); + } + else + { + start = (void*)(((unsigned long)start + 3) & ~3); + size &= ~3; + + /* Flush any pending cache writes */ + clean_dcache_range(start, size); + dma_play_bd.buf_addr = (void *)addr_virt_to_phys((unsigned long)start); + dma_play_bd.mode.count = size; + dma_play_bd.mode.command = TRANSFER_16BIT; + dma_play_bd.mode.status = BD_DONE | BD_WRAP | BD_INTR; + sdma_channel_run(DMA_PLAY_CH_NUM); } } -static void __attribute__((interrupt("IRQ"))) SSI1_HANDLER(void) +void pcm_play_lock(void) { - register pcm_more_callback_type get_more; + if (++dma_play_data.locked == 1) + imx31_regclr32(&SSI_SIER1, SSI_SIER_TDMAE); +} - do +void pcm_play_unlock(void) +{ + if (--dma_play_data.locked == 0 && dma_play_data.state != 0) { - while (dma_play_data.size > 0) + bool pending = false; + int oldstatus = disable_irq_save(); + + if (dma_play_data.callback_pending) { - if (SSI_SFCSR_TFCNT0r(SSI_SFCSR1) > 6) - { - return; - } - SSI_STX0_1 = *dma_play_data.p++; - SSI_STX0_1 = *dma_play_data.p++; - dma_play_data.size -= 4; + pending = true; + dma_play_data.callback_pending = 0; } - /* p is empty, get some more data */ - get_more = pcm_callback_for_more; + SSI_SIER1 |= SSI_SIER_TDMAE; + restore_irq(oldstatus); - if (get_more) - { - get_more((unsigned char **)&dma_play_data.p, - &dma_play_data.size); - } + /* Should an interrupt be forced instead? The upper pcm layer can + * call producer's callback in thread context so technically this is + * acceptable. */ + if (pending) + play_dma_callback(); } - while (dma_play_data.size > 0); - - /* No more data, so disable the FIFO/interrupt */ - pcm_play_dma_stop(); - pcm_play_dma_stopped_callback(); } void pcm_dma_apply_settings(void) @@ -104,6 +119,17 @@ void pcm_dma_apply_settings(void) void pcm_play_dma_init(void) { + /* Init channel information */ + dma_play_cd.bd_count = 1; + dma_play_cd.callback = play_dma_callback; + dma_play_cd.shp_addr = SDMA_PER_ADDR_SSI1_TX1; + dma_play_cd.wml = SDMA_SSI_TXFIFO_WML*2; + dma_play_cd.per_type = SDMA_PER_SSI; + dma_play_cd.tran_type = SDMA_TRAN_EMI_2_PER; + dma_play_cd.event_id1 = SDMA_REQ_SSI1_TX1; + + sdma_channel_init(DMA_PLAY_CH_NUM, &dma_play_cd, &dma_play_bd); + imx31_clkctl_module_clock_gating(CG_SSI1, CGM_ON_ALL); imx31_clkctl_module_clock_gating(CG_SSI2, CGM_ON_ALL); @@ -111,8 +137,8 @@ void pcm_play_dma_init(void) SSI_SCR2 &= ~SSI_SCR_SSIEN; SSI_SCR1 &= ~SSI_SCR_SSIEN; - SSI_SIER1 = SSI_SIER_TFE0; /* TX0 can issue an interrupt */ - SSI_SIER2 = SSI_SIER_RFF0; /* RX0 can issue an interrupt */ + SSI_SIER1 = 0; + SSI_SIER2 = 0; /* Set up audio mux */ @@ -155,8 +181,9 @@ void pcm_play_dma_init(void) SSI_STCCR1 = SSI_STRCCR_WL16 | SSI_STRCCR_DCw(2-1) | SSI_STRCCR_PMw(4-1); - /* Transmit low watermark - 2 samples in FIFO */ - SSI_SFCSR1 = SSI_SFCSR_TFWM1w(1) | SSI_SFCSR_TFWM0w(2); + /* Transmit low watermark */ + SSI_SFCSR1 = (SSI_SFCSR1 & ~SSI_SFCSR_TFWM0) | + SSI_SFCSR_TFWM0w(8-SDMA_SSI_TXFIFO_WML); SSI_STMSK1 = 0; /* SSI2 - provides MCLK to codec. Receives data from codec. */ @@ -186,8 +213,9 @@ void pcm_play_dma_init(void) SSI_SRCCR2 = SSI_STRCCR_WL16 | SSI_STRCCR_DCw(2-1) | SSI_STRCCR_PMw(4-1); - /* Receive high watermark - 6 samples in FIFO */ - SSI_SFCSR2 = SSI_SFCSR_RFWM1w(8) | SSI_SFCSR_RFWM0w(6); + /* Receive high watermark */ + SSI_SFCSR2 = (SSI_SFCSR2 & ~SSI_SFCSR_RFWM0) | + SSI_SFCSR_RFWM0w(SDMA_SSI_RXFIFO_WML); SSI_SRMSK2 = 0; /* Enable SSI2 (codec clock) */ @@ -199,7 +227,6 @@ void pcm_play_dma_init(void) void pcm_postinit(void) { audiohw_postinit(); - avic_enable_int(SSI1, IRQ, 8, SSI1_HANDLER); } static void play_start_pcm(void) @@ -207,32 +234,23 @@ static void play_start_pcm(void) /* Stop transmission (if in progress) */ SSI_SCR1 &= ~SSI_SCR_TE; - /* Enable interrupt on unlock */ - dma_play_data.state = 1; - - /* Fill the FIFO or start when data is used up */ SSI_SCR1 |= SSI_SCR_SSIEN; /* Enable SSI */ SSI_STCR1 |= SSI_STCR_TFEN0; /* Enable TX FIFO */ - while (1) - { - if (SSI_SFCSR_TFCNT0r(SSI_SFCSR1) > 6 || dma_play_data.size == 0) - { - SSI_SCR1 |= SSI_SCR_TE; /* Start transmitting */ - return; - } + dma_play_data.state = 1; /* Enable DMA requests on unlock */ - SSI_STX0_1 = *dma_play_data.p++; - SSI_STX0_1 = *dma_play_data.p++; - dma_play_data.size -= 4; - } + /* Do prefill to prevent swapped channels (see TLSbo61214 in MCIMX31CE). + * No actual solution was offered but this appears to work. */ + SSI_STX0_1 = 0; + SSI_STX0_1 = 0; + SSI_STX0_1 = 0; + SSI_STX0_1 = 0; + + SSI_SCR1 |= SSI_SCR_TE; /* Start transmitting */ } static void play_stop_pcm(void) { - /* Disable interrupt */ - SSI_SIER1 &= ~SSI_SIER_TIE; - /* Wait for FIFO to empty */ while (SSI_SFCSR_TFCNT0r(SSI_SFCSR1) > 0); @@ -240,135 +258,227 @@ static void play_stop_pcm(void) SSI_STCR1 &= ~SSI_STCR_TFEN0; SSI_SCR1 &= ~(SSI_SCR_TE | SSI_SCR_SSIEN); - /* Do not enable interrupt on unlock */ + /* Do not enable DMA requests on unlock */ dma_play_data.state = 0; + dma_play_data.callback_pending = 0; } void pcm_play_dma_start(const void *addr, size_t size) { - dma_play_data.p = (void *)(((uintptr_t)addr + 3) & ~3); - dma_play_data.size = (size & ~3); + sdma_channel_stop(DMA_PLAY_CH_NUM); + + /* Disable transmission */ + SSI_STCR1 &= ~SSI_STCR_TFEN0; + SSI_SCR1 &= ~(SSI_SCR_TE | SSI_SCR_SSIEN); + + addr = (void *)(((unsigned long)addr + 3) & ~3); + size &= ~3; + + clean_dcache_range(addr, size); + dma_play_bd.buf_addr = + (void *)addr_virt_to_phys((unsigned long)(void *)addr); + dma_play_bd.mode.count = size; + dma_play_bd.mode.command = TRANSFER_16BIT; + dma_play_bd.mode.status = BD_DONE | BD_WRAP | BD_INTR; play_start_pcm(); + sdma_channel_start(DMA_PLAY_CH_NUM); } void pcm_play_dma_stop(void) { + sdma_channel_stop(DMA_PLAY_CH_NUM); play_stop_pcm(); - dma_play_data.size = 0; } void pcm_play_dma_pause(bool pause) { if (pause) { + sdma_channel_pause(DMA_PLAY_CH_NUM); play_stop_pcm(); } else { - uint32_t addr = (uint32_t)dma_play_data.p; - dma_play_data.p = (void *)((addr + 2) & ~3); - dma_play_data.size &= ~3; play_start_pcm(); + sdma_channel_run(DMA_PLAY_CH_NUM); } } /* Return the number of bytes waiting - full L-R sample pairs only */ size_t pcm_get_bytes_waiting(void) { - return dma_play_data.size & ~3; + static unsigned long dsa DEVBSS_ATTR; + long offs, size; + int oldstatus; + + /* read burst dma source address register in channel context */ + sdma_read_words(&dsa, CHANNEL_CONTEXT_ADDR(DMA_PLAY_CH_NUM)+0x0b, 1); + + oldstatus = disable_irq_save(); + offs = dsa - (unsigned long)dma_play_bd.buf_addr; + size = dma_play_bd.mode.count; + restore_irq(oldstatus); + + /* Be addresses are coherent (no buffer change during read) */ + if (offs >= 0 && offs < size) + { + return (size - offs) & ~3; + } + + return 0; } /* Return a pointer to the samples and the number of them in *count */ const void * pcm_play_dma_get_peak_buffer(int *count) { - uint32_t addr = (uint32_t)dma_play_data.p; - size_t cnt = dma_play_data.size; - *count = cnt >> 2; - return (void *)((addr + 2) & ~3); + static unsigned long dsa DEVBSS_ATTR; + unsigned long addr; + long offs, size; + int oldstatus; + + /* read burst dma source address register in channel context */ + sdma_read_words(&dsa, CHANNEL_CONTEXT_ADDR(DMA_PLAY_CH_NUM)+0x0b, 1); + + oldstatus = disable_irq_save(); + addr = dsa; + offs = addr - (unsigned long)dma_play_bd.buf_addr; + size = dma_play_bd.mode.count; + restore_irq(oldstatus); + + /* Be addresses are coherent (no buffer change during read) */ + if (offs >= 0 && offs < size) + { + *count = (size - offs) >> 2; + return (void *)((addr + 2) & ~3); + } + + *count = 0; + return NULL; +} + +void * pcm_dma_addr(void *addr) +{ + return (void *)addr_virt_to_phys((unsigned long)addr); } #ifdef HAVE_RECORDING +static struct buffer_descriptor dma_rec_bd DEVBSS_ATTR; +static struct channel_descriptor dma_rec_cd DEVBSS_ATTR; + static struct dma_data dma_rec_data = { /* Initialize to a locked, stopped state */ - .p = NULL, - .size = 0, .locked = 0, .state = 0 }; -static void __attribute__((interrupt("IRQ"))) SSI2_HANDLER(void) +static void rec_dma_callback(void) { - register pcm_more_callback_type2 more_ready; + pcm_more_callback_type2 more_ready; + int status = 0; - while (dma_rec_data.size > 0) + if (dma_rec_data.locked) { - if (SSI_SFCSR_RFCNT0r(SSI_SFCSR2) < 2) - return; - - *dma_rec_data.p++ = SSI_SRX0_2; - *dma_rec_data.p++ = SSI_SRX0_2; - dma_rec_data.size -= 4; + dma_rec_data.callback_pending = 1; + return; /* Callback is locked out */ } + if (dma_rec_bd.mode.status & BD_RROR) + status = DMA_REC_ERROR_DMA; + more_ready = pcm_callback_more_ready; - if (more_ready == NULL || more_ready(0) < 0) { - /* Finished recording */ - pcm_rec_dma_stop(); - pcm_rec_dma_stopped_callback(); + if (more_ready != NULL && more_ready(status) >= 0) + { + sdma_channel_run(DMA_REC_CH_NUM); + return; } + + /* Finished recording */ + pcm_rec_dma_stop(); + pcm_rec_dma_stopped_callback(); } void pcm_rec_lock(void) { if (++dma_rec_data.locked == 1) - { - /* Atomically disable receive interrupt */ - imx31_regclr32(&SSI_SIER2, SSI_SIER_RIE); - } + imx31_regclr32(&SSI_SIER2, SSI_SIER_RDMAE); } void pcm_rec_unlock(void) { if (--dma_rec_data.locked == 0 && dma_rec_data.state != 0) { - /* Atomically enable receive interrupt */ - imx31_regset32(&SSI_SIER2, SSI_SIER_RIE); + bool pending = false; + int oldstatus = disable_irq_save(); + + if (dma_rec_data.callback_pending) + { + pending = true; + dma_rec_data.callback_pending = 0; + } + + SSI_SIER2 |= SSI_SIER_RDMAE; + restore_irq(oldstatus); + + /* Should an interrupt be forced instead? The upper pcm layer can + * call consumer's callback in thread context so technically this is + * acceptable. */ + if (pending) + rec_dma_callback(); } } void pcm_record_more(void *start, size_t size) { - pcm_rec_peak_addr = start; /* Start peaking at dest */ - dma_rec_data.p = start; /* Start of RX buffer */ - dma_rec_data.size = size; /* Bytes to transfer */ + start = (void *)(((unsigned long)start + 3) & ~3); + size &= ~3; + + /* Write back and invalidate - buffer must be coherent */ + invalidate_dcache_range(start, size); + + start = (void *)addr_virt_to_phys((unsigned long)start); + + pcm_rec_peak_addr = start; + dma_rec_bd.buf_addr = start; + dma_rec_bd.mode.count = size; + dma_rec_bd.mode.command = TRANSFER_16BIT; + dma_rec_bd.mode.status = BD_DONE | BD_WRAP | BD_INTR; } void pcm_rec_dma_stop(void) { /* Stop receiving data */ + sdma_channel_stop(DMA_REC_CH_NUM); + + imx31_regclr32(&SSI_SIER2, SSI_SIER_RDMAE); + SSI_SCR2 &= ~SSI_SCR_RE; /* Disable RX */ SSI_SRCR2 &= ~SSI_SRCR_RFEN0; /* Disable RX FIFO */ dma_rec_data.state = 0; - - avic_disable_int(SSI2); + dma_rec_data.callback_pending = 0; } void pcm_rec_dma_start(void *addr, size_t size) { pcm_rec_dma_stop(); + addr = (void *)(((unsigned long)addr + 3) & ~3); + size &= ~3; + + invalidate_dcache_range(addr, size); + + addr = (void *)addr_virt_to_phys((unsigned long)addr); pcm_rec_peak_addr = addr; - dma_rec_data.p = addr; - dma_rec_data.size = size; + dma_rec_bd.buf_addr = addr; + dma_rec_bd.mode.count = size; + dma_rec_bd.mode.command = TRANSFER_16BIT; + dma_rec_bd.mode.status = BD_DONE | BD_WRAP | BD_INTR; dma_rec_data.state = 1; - avic_enable_int(SSI2, IRQ, 9, SSI2_HANDLER); - SSI_SRCR2 |= SSI_SRCR_RFEN0; /* Enable RX FIFO */ /* Ensure clear FIFO */ @@ -377,24 +487,58 @@ void pcm_rec_dma_start(void *addr, size_t size) /* Enable receive */ SSI_SCR2 |= SSI_SCR_RE; + + sdma_channel_start(DMA_REC_CH_NUM); } void pcm_rec_dma_close(void) { pcm_rec_dma_stop(); + sdma_channel_close(DMA_REC_CH_NUM); } void pcm_rec_dma_init(void) { pcm_rec_dma_stop(); + + /* Init channel information */ + dma_rec_cd.bd_count = 1; + dma_rec_cd.callback = rec_dma_callback; + dma_rec_cd.shp_addr = SDMA_PER_ADDR_SSI2_RX1; + dma_rec_cd.wml = SDMA_SSI_RXFIFO_WML*2; + dma_rec_cd.per_type = SDMA_PER_SSI; + dma_rec_cd.tran_type = SDMA_TRAN_PER_2_EMI; + dma_rec_cd.event_id1 = SDMA_REQ_SSI2_RX1; + + sdma_channel_init(DMA_REC_CH_NUM, &dma_rec_cd, &dma_rec_bd); } const void * pcm_rec_dma_get_peak_buffer(int *count) { - unsigned long addr = (uint32_t)pcm_rec_peak_addr; - unsigned long end = (uint32_t)dma_rec_data.p; - *count = (end >> 2) - (addr >> 2); - return (void *)(addr & ~3); + static unsigned long pda DEVBSS_ATTR; + unsigned long buf, addr, end, bufend; + int oldstatus; + + /* read burst dma destination address register in channel context */ + sdma_read_words(&pda, CHANNEL_CONTEXT_ADDR(DMA_REC_CH_NUM)+0x0a, 1); + + oldstatus = disable_irq_save(); + end = pda; + buf = (unsigned long)dma_rec_bd.buf_addr; + addr = (unsigned long)pcm_rec_peak_addr; + bufend = buf + dma_rec_bd.mode.count; + restore_irq(oldstatus); + + /* Be addresses are coherent (no buffer change during read) */ + if (addr >= buf && addr < bufend && + end >= buf && end < bufend) + { + *count = (end >> 2) - (addr >> 2); + return (void *)(addr & ~3); + } + + *count = 0; + return NULL; } #endif /* HAVE_RECORDING */ diff --git a/firmware/target/arm/imx31/gigabeat-s/system-imx31.c b/firmware/target/arm/imx31/gigabeat-s/system-imx31.c index cb265af0a3..b3f0fd66c9 100644 --- a/firmware/target/arm/imx31/gigabeat-s/system-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/system-imx31.c @@ -32,6 +32,28 @@ #include "clkctl-imx31.h" #include "mc13783.h" +static unsigned long product_rev; +static unsigned long system_rev; + +/** IC revision info routines **/ +unsigned int iim_system_rev(void) +{ + return system_rev & IIM_SREV_SREV; +} + +unsigned int iim_prod_rev(void) +{ + return product_rev; +} + +static void iim_init(void) +{ + /* Initialize the IC revision info (required by SDMA) */ + imx31_clkctl_module_clock_gating(CG_IIM, CGM_ON_ALL); + product_rev = IIM_PREV; + system_rev = IIM_SREV; +} + /** Watchdog timer routines **/ /* Initialize the watchdog timer */ @@ -155,6 +177,8 @@ void system_init(void) /* MCR WFI enables wait mode */ CLKCTL_CCMR &= ~(3 << 14); + iim_init(); + imx31_regset32(&SDHC1_CLOCK_CONTROL, STOP_CLK); imx31_regset32(&SDHC2_CLOCK_CONTROL, STOP_CLK); imx31_regset32(&RNGA_CONTROL, RNGA_CONTROL_SLEEP); diff --git a/firmware/target/arm/imx31/gigabeat-s/system-target.h b/firmware/target/arm/imx31/gigabeat-s/system-target.h index c7797e43c9..ae50ec4c78 100644 --- a/firmware/target/arm/imx31/gigabeat-s/system-target.h +++ b/firmware/target/arm/imx31/gigabeat-s/system-target.h @@ -43,6 +43,8 @@ void watchdog_service(void); void gpt_start(void); void gpt_stop(void); +unsigned int iim_system_rev(void); + /* Prepare for transition to firmware */ void system_prepare_fw_start(void); void tick_stop(void); diff --git a/firmware/target/arm/imx31/sdma-imx31.c b/firmware/target/arm/imx31/sdma-imx31.c new file mode 100644 index 0000000000..f845ed18d8 --- /dev/null +++ b/firmware/target/arm/imx31/sdma-imx31.c @@ -0,0 +1,807 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2009 by Michael Sevakis + * + * 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 "system.h" +#include +#include "logf.h" +#include "panic.h" +#include "clkctl-imx31.h" +#include "avic-imx31.h" +#include "sdma_struct.h" +#include "sdma-imx31.h" +#include "sdma_script_code.h" +#include "mmu-imx31.h" + +/* Most of the code in here is based upon the Linux BSP provided by Freescale + * Copyright 2004-2008 Freescale Semiconductor, Inc. All Rights Reserved. */ + +/* Cut down to bare bones essentials */ + +/* Script information that depends on system revision */ +static struct sdma_script_start_addrs script_info; +/* Mask of channels with callback enabled */ +static unsigned long sdma_enabled_ints = 0; +/* One channel control block per channel in physically mapped device RAM */ +static struct channel_control_block ccb_array[CH_NUM] DEVBSS_ATTR; +/* Channel 0 (command channel) data */ +static struct buffer_descriptor_extd c0_buffer_desc DEVBSS_ATTR; + +/* All SDMA channel interrupts are handled here. + * Dispatches lower channel numbers first (prioritized by SDMA API callers + * who specify the desired channel number). + */ +static void __attribute__((interrupt("IRQ"))) SDMA_HANDLER(void) +{ + unsigned long pending = SDMA_INTR; + + SDMA_INTR = pending; /* Ack all ints */ + pending &= sdma_enabled_ints; /* Only dispatch ints with callback */ + + while (1) + { + unsigned int channel; + + if (pending == 0) + break; /* No bits set */ + + channel = find_first_set_bit(pending); + + pending &= ~(1ul << channel); + + /* Call callback (required if using an interrupt) */ + ccb_array[channel].channel_desc->callback(); + } +} + +/* Initialize script information based upon the system revision */ +static void init_script_info(void) +{ + if (iim_system_rev() == IIM_SREV_1_0) + { + /* Channel script info */ + script_info.app_2_mcu_addr = app_2_mcu_ADDR_1; + script_info.ap_2_ap_addr = ap_2_ap_ADDR_1; + script_info.ap_2_bp_addr = -1; + script_info.bp_2_ap_addr = -1; + script_info.loopback_on_dsp_side_addr = -1; + script_info.mcu_2_app_addr = mcu_2_app_ADDR_1; + script_info.mcu_2_shp_addr = mcu_2_shp_ADDR_1; + script_info.mcu_interrupt_only_addr = -1; + script_info.shp_2_mcu_addr = shp_2_mcu_ADDR_1; + script_info.uartsh_2_mcu_addr = uartsh_2_mcu_ADDR_1; + script_info.uart_2_mcu_addr = uart_2_mcu_ADDR_1; + script_info.dptc_dvfs_addr = dptc_dvfs_ADDR_1; + script_info.firi_2_mcu_addr = firi_2_mcu_ADDR_1; + script_info.firi_2_per_addr = -1; + script_info.mshc_2_mcu_addr = mshc_2_mcu_ADDR_1; + script_info.per_2_app_addr = -1; + script_info.per_2_firi_addr = -1; + script_info.per_2_shp_addr = -1; + script_info.mcu_2_ata_addr = mcu_2_ata_ADDR_1; + script_info.mcu_2_firi_addr = mcu_2_firi_ADDR_1; + script_info.mcu_2_mshc_addr = mcu_2_mshc_ADDR_1; + script_info.ata_2_mcu_addr = ata_2_mcu_ADDR_1; + script_info.uartsh_2_per_addr = -1; + script_info.shp_2_per_addr = -1; + script_info.uart_2_per_addr = -1; + script_info.app_2_per_addr = -1; + /* Main code block info */ + script_info.ram_code_size = RAM_CODE_SIZE_1; + script_info.ram_code_start_addr = RAM_CODE_START_ADDR_1; + script_info.mcu_start_addr = (unsigned long)sdma_code_1; + } + else + { + /* Channel script info */ + script_info.app_2_mcu_addr = app_2_mcu_patched_ADDR_2; + script_info.ap_2_ap_addr = ap_2_ap_ADDR_2; + script_info.ap_2_bp_addr = ap_2_bp_ADDR_2; + script_info.bp_2_ap_addr = bp_2_ap_ADDR_2; + script_info.loopback_on_dsp_side_addr = -1; + script_info.mcu_2_app_addr = mcu_2_app_ADDR_2; + script_info.mcu_2_shp_addr = mcu_2_shp_patched_ADDR_2; + script_info.mcu_interrupt_only_addr = -1; + script_info.shp_2_mcu_addr = shp_2_mcu_patched_ADDR_2; + script_info.uartsh_2_mcu_addr = uartsh_2_mcu_patched_ADDR_2; + script_info.uart_2_mcu_addr = uart_2_mcu_patched_ADDR_2; + script_info.dptc_dvfs_addr = -1; + script_info.firi_2_mcu_addr = firi_2_mcu_ADDR_2; + script_info.firi_2_per_addr = -1; + script_info.mshc_2_mcu_addr = -1; + script_info.per_2_app_addr = -1; + script_info.per_2_firi_addr = -1; + script_info.per_2_shp_addr = per_2_shp_ADDR_2; + script_info.mcu_2_ata_addr = mcu_2_ata_ADDR_2; + script_info.mcu_2_firi_addr = mcu_2_firi_ADDR_2; + script_info.mcu_2_mshc_addr = -1; + script_info.ata_2_mcu_addr = ata_2_mcu_ADDR_2; + script_info.uartsh_2_per_addr = -1; + script_info.shp_2_per_addr = shp_2_per_ADDR_2; + script_info.uart_2_per_addr = -1; + script_info.app_2_per_addr = -1; + /* Main code block info */ + script_info.ram_code_size = RAM_CODE_SIZE_2; + script_info.ram_code_start_addr = RAM_CODE_START_ADDR_2; + script_info.mcu_start_addr = (unsigned long)sdma_code_2; + } +} + +/* Return pc of SDMA script in SDMA halfword space according to peripheral + * and transfer type */ +static unsigned long get_script_pc(unsigned int peripheral_type, + unsigned int transfer_type) +{ + unsigned long res = (unsigned short)-1; + + switch (peripheral_type) + { + case SDMA_PER_MEMORY: + switch (transfer_type) + { + case SDMA_TRAN_EMI_2_INT: + case SDMA_TRAN_EMI_2_EMI: + case SDMA_TRAN_INT_2_EMI: + res = script_info.ap_2_ap_addr; + break; + default: + break; + } + break; + +#if 0 /* Not using this */ + case SDMA_PER_DSP: + switch (transfer_type) + { + case SDMA_TRAN_EMI_2_DSP: + res = script_info.ap_2_bp_addr; + break; + case SDMA_TRAN_DSP_2_EMI: + res = script_info.bp_2_ap_addr; + break; + case SDMA_TRAN_DSP_2_EMI_LOOP: + res = script_info.loopback_on_dsp_side_addr; + break; + case SDMA_TRAN_EMI_2_DSP_LOOP: + res = script_info.mcu_interrupt_only_addr; + break; + default: + break; + } + break; +#endif + +#if 0 /* Not using this */ + case SDMA_PER_FIRI: + switch (transfer_type) + { + case SDMA_TRAN_PER_2_INT: + res = script_info.firi_2_per_addr; + break; + case SDMA_TRAN_PER_2_EMI: + res = script_info.firi_2_mcu_addr; + break; + case SDMA_TRAN_INT_2_PER: + res = script_info.per_2_firi_addr; + break; + case SDMA_TRAN_EMI_2_PER: + res = script_info.mcu_2_firi_addr; + break; + default: + break; + } + break; +#endif + +#if 0 /* Not using this */ + case SDMA_PER_UART: + switch (transfer_type) + { + case SDMA_TRAN_PER_2_INT: + res = script_info.uart_2_per_addr; + break; + case SDMA_TRAN_PER_2_EMI: + res = script_info.uart_2_mcu_addr; + break; + case SDMA_TRAN_INT_2_PER: + res = script_info.per_2_app_addr; + break; + case SDMA_TRAN_EMI_2_PER: + res = script_info.mcu_2_app_addr; + break; + default: + break; + } + break; +#endif + +#if 0 /* Not using this */ + case SDMA_PER_UART_SP: + switch (transfer_type) + { + case SDMA_TRAN_PER_2_INT: + res = script_info.uartsh_2_per_addr; + break; + case SDMA_TRAN_PER_2_EMI: + res = script_info.uartsh_2_mcu_addr; + break; + case SDMA_TRAN_INT_2_PER: + res = script_info.per_2_shp_addr; + break; + case SDMA_TRAN_EMI_2_PER: + res = script_info.mcu_2_shp_addr; + break; + default: + break; + } + break; +#endif + + case SDMA_PER_ATA: + switch (transfer_type) + { + case SDMA_TRAN_PER_2_EMI: + res = script_info.ata_2_mcu_addr; + break; + case SDMA_TRAN_EMI_2_PER: + res = script_info.mcu_2_ata_addr; + break; + default: + break; + } + break; + + case SDMA_PER_CSPI: + case SDMA_PER_EXT: + case SDMA_PER_SSI: + switch (transfer_type) + { + case SDMA_TRAN_PER_2_INT: + res = script_info.app_2_per_addr; + break; + case SDMA_TRAN_PER_2_EMI: + res = script_info.app_2_mcu_addr; + break; + case SDMA_TRAN_INT_2_PER: + res = script_info.per_2_app_addr; + break; + case SDMA_TRAN_EMI_2_PER: + res = script_info.mcu_2_app_addr; + break; + default: + break; + } + break; + +#if 0 /* Not using this */ + case SDMA_PER_MMC: + case SDMA_PER_SDHC: +#endif + case SDMA_PER_SSI_SP: + case SDMA_PER_CSPI_SP: + switch (transfer_type) + { + case SDMA_TRAN_PER_2_INT: + res = script_info.shp_2_per_addr; + break; + case SDMA_TRAN_PER_2_EMI: + res = script_info.shp_2_mcu_addr; + break; + case SDMA_TRAN_INT_2_PER: + res = script_info.per_2_shp_addr; + break; + case SDMA_TRAN_EMI_2_PER: + res = script_info.mcu_2_shp_addr; + break; + default: + break; + } + + case SDMA_PER_MSHC: + switch (transfer_type) + { + case SDMA_TRAN_PER_2_EMI: + res = script_info.mshc_2_mcu_addr; + break; + case SDMA_TRAN_EMI_2_PER: + res = script_info.mcu_2_mshc_addr; + break; + default: + break; + } + + case SDMA_PER_CCM: + switch (transfer_type) + { + case SDMA_TRAN_PER_2_EMI: + res = script_info.dptc_dvfs_addr; + break; + default: + break; + } + } + + if (res == (unsigned short)-1) + { + logf("SDMA script not found\n"); + } + + return res; +} + +static unsigned int get_config(unsigned int transfer_type) +{ + unsigned int res = -1; + + switch (transfer_type) + { + case SDMA_TRAN_PER_2_INT: + case SDMA_TRAN_PER_2_EMI: + case SDMA_TRAN_INT_2_PER: + case SDMA_TRAN_EMI_2_PER: + /* + * Peripheral <------> Memory + * evtOvr = 0 mcuOvr = 0 dspOvr = 1 + */ + res = CH_OWNSHP_MCU | CH_OWNSHP_EVT; + break; + +#if 0 /* Not using this */ + case SDMA_TRAN_DSP_2_PER: + res = 0; + break; + case SDMA_TRAN_EMI_2_DSP: + case SDMA_TRAN_INT_2_DSP: + case SDMA_TRAN_DSP_2_INT: + case SDMA_TRAN_DSP_2_EMI: + case SDMA_TRAN_DSP_2_DSP: + /* + * DSP <-----------> Memory + * evtOvr = 1 mcuOvr = 0 dspOvr = 0 + */ + res = CH_OWNSHP_MCU | CH_OWNSHP_DSP; + break; +#endif + + case SDMA_TRAN_EMI_2_INT: + case SDMA_TRAN_EMI_2_EMI: + case SDMA_TRAN_INT_2_INT: + case SDMA_TRAN_INT_2_EMI: +#if 0 /* Not using this */ + case SDMA_TRAN_DSP_2_EMI_LOOP: + case SDMA_TRAN_EMI_2_DSP_LOOP: +#endif + /* evtOvr = 1 mcuOvr = 0 dspOvr = 1 */ + res = CH_OWNSHP_MCU; + break; + +#if 0 /* Not using this */ + case SDMA_TRAN_PER_2_DSP: + /* evtOvr = 0 mcuOvr = 1 dspOvr = 0 */ + res = CH_OWNSHP_DSP | CH_OWNSHP_EVT; + break; +#endif + + default: + break; + } + + return res; +} + +/* Fill the buffer descriptor with the values given in parameter. + * Expects physical addresses. */ +static inline void set_buffer_descriptor( + struct buffer_descriptor *bd_p, + unsigned int command, /* C0_* command or transfer size */ + unsigned int status, /* BD_* flags */ + unsigned int count, /* Size of buffer to transfer */ + void *buf_addr, /* Buffer to transfer */ + void *buf_addr_ext) +{ + bd_p->mode.command = command; + bd_p->mode.status = status; + bd_p->mode.count = count; + bd_p->buf_addr = buf_addr; + if (status & BD_EXTD) + ((struct buffer_descriptor_extd *)bd_p)->buf_addr_ext = buf_addr_ext; +} + +/* Configure channel ownership */ +static void set_channel_ownership(unsigned int channel, unsigned int config) +{ + unsigned long bit = 1ul << channel; + + /* DSP side */ +#if 0 /* Not using this */ + imx31_regmod32(&SDMA_DSPOVR, (config & CH_OWNSHP_DSP) ? 0 : bit, bit); +#endif + /* Event */ + imx31_regmod32(&SDMA_EVTOVR, (config & CH_OWNSHP_EVT) ? 0 : bit, bit); + /* MCU side */ + imx31_regmod32(&SDMA_HOSTOVR, (config & CH_OWNSHP_MCU) ? 0 : bit, bit); +} + +static bool setup_channel(struct channel_control_block *ccb_p) +{ + static struct context_data context_buffer DEVBSS_ATTR; + struct channel_descriptor *cd_p; + unsigned int channel_cfg; + unsigned int channel; + unsigned long pc; + + memset(&context_buffer, 0x00, sizeof (context_buffer)); + + channel = ccb_p - ccb_array; + cd_p = ccb_p->channel_desc; + + /* Obtain script start address for perihperal and transfer type */ + pc = get_script_pc(cd_p->per_type, cd_p->tran_type); + + if (pc == (unsigned short)-1) + return false; /* Failed to find a script */ + + context_buffer.channel_state.pc = pc; + + if (cd_p->per_type != SDMA_PER_MEMORY && cd_p->per_type != SDMA_PER_DSP) + { + /* Set peripheral DMA request mask for this channel */ + context_buffer.event_mask1 = 1ul << cd_p->event_id1; + + if (cd_p->per_type == SDMA_PER_ATA) + { + /* ATA has two */ + context_buffer.event_mask2 = 1ul << cd_p->event_id2; + } + + context_buffer.shp_addr = cd_p->shp_addr; + context_buffer.wml = cd_p->wml; + } + else + { + context_buffer.wml = SDMA_PER_ADDR_SDRAM; + } + + /* Send channel context to SDMA core */ + clean_dcache_range(&context_buffer, sizeof (context_buffer)); + sdma_write_words((unsigned long *)&context_buffer, + CHANNEL_CONTEXT_ADDR(channel), + sizeof (context_buffer)/4); + + if (cd_p->is_setup != 0) + return true; /* No more to do */ + + /* Obtain channel ownership configuration */ + channel_cfg = get_config(cd_p->tran_type); + + if (channel_cfg == (unsigned int)-1) + return false; + + /* Set who owns it and thus can activate it */ + set_channel_ownership(channel, channel_cfg); + + if (channel_cfg & CH_OWNSHP_EVT) + { + /* Set event ID to channel activation bitmapping */ + imx31_regset32(&SDMA_CHNENBL(cd_p->event_id1), 1ul << channel); + + if (cd_p->per_type == SDMA_PER_ATA) + { + /* ATA has two */ + imx31_regset32(&SDMA_CHNENBL(cd_p->event_id2), 1ul << channel); + } + } + + cd_p->is_setup = 1; + + return true; +} + +/** Public routines **/ +void sdma_init(void) +{ + imx31_clkctl_module_clock_gating(CG_SDMA, CGM_ON_RUN_WAIT); + int i; + unsigned long acr; + + /* Reset the controller */ + SDMA_RESET |= SDMA_RESET_RESET; + while (SDMA_RESET & SDMA_RESET_RESET); + + init_script_info(); + + /* No channel enabled, all priorities 0 */ + for (i = 0; i < CH_NUM; i++) + { + SDMA_CHNENBL(i) = 0; + SDMA_CHNPRI(i) = 0; + } + + /* Ensure no ints pending */ + SDMA_INTR = 0xffffffff; + + /* Nobody owns any channel (yet) */ + SDMA_HOSTOVR = 0xffffffff; + SDMA_DSPOVR = 0xffffffff; + SDMA_EVTOVR = 0xffffffff; + + SDMA_MC0PTR = 0x00000000; + + /* 32-word channel contexts, use default bootscript address */ + SDMA_CHN0ADDR = SDMA_CHN0ADDR_SMSZ | 0x0050; + + avic_enable_int(SDMA, IRQ, 8, SDMA_HANDLER); + + /* SDMA core must run at the proper frequency based upon the AHB/IPG ratio */ + acr = (imx31_clkctl_get_ahb_clk() / imx31_clkctl_get_ipg_clk()) < 2 ? + SDMA_CONFIG_ACR : 0; + + /* No dsp, no debug + * Static context switching - TLSbo86520L SW Workaround for SDMA Chnl0 + * access issue */ + SDMA_CONFIG = acr; + + /* Tell SDMA where the host channel table is */ + SDMA_MC0PTR = (unsigned long)ccb_array; + + ccb_array[0].status.opened_init = 1; + ccb_array[0].curr_bd_ptr = &c0_buffer_desc.bd; + ccb_array[0].base_bd_ptr = &c0_buffer_desc.bd; + ccb_array[0].channel_desc = NULL; /* No channel descriptor */ + + /* Command channel owned by AP */ + set_channel_ownership(0, CH_OWNSHP_MCU); + + sdma_channel_set_priority(0, 1); + + /* Load SDMA script code */ + set_buffer_descriptor(&c0_buffer_desc.bd, + C0_SETPM, + BD_DONE | BD_WRAP | BD_EXTD, + script_info.ram_code_size, + (void *)addr_virt_to_phys(script_info.mcu_start_addr), + (void *)(unsigned long)script_info.ram_code_start_addr); + + SDMA_HSTART = 1ul; + sdma_channel_wait_nonblocking(0); + + /* No dsp, no debug, dynamic context switching */ + SDMA_CONFIG = acr | SDMA_CONFIG_CSM_DYNAMIC; +} + +/* Busy wait for a channel to complete */ +void sdma_channel_wait_nonblocking(unsigned int channel) +{ + unsigned long mask; + + if (channel >= CH_NUM) + return; + + if (ccb_array[channel].status.opened_init == 0) + return; + + mask = 1ul << channel; + while (SDMA_STOP_STAT & mask); +} + +/* Set a new channel priority */ +void sdma_channel_set_priority(unsigned int channel, unsigned int priority) +{ + if (channel >= CH_NUM || priority > MAX_CH_PRIORITY) + return; + + if (ccb_array[channel].status.opened_init == 0) + return; + + SDMA_CHNPRI(channel) = priority; +} + +/* Start a channel cold - resets execution to start of script */ +void sdma_channel_start(unsigned int channel) +{ + struct channel_control_block *ccb_p; + + if (channel == 0 || channel >= CH_NUM) + return; + + ccb_p = &ccb_array[channel]; + + if (ccb_p->status.opened_init == 0) + return; + + if (!setup_channel(ccb_p)) + return; + + SDMA_HSTART = 1ul << channel; +} + +/* Resume or start execution on a channel */ +void sdma_channel_run(unsigned int channel) +{ + if (channel == 0 || channel >= CH_NUM) + return; + + if (ccb_array[channel].status.opened_init == 0) + return; + + SDMA_HSTART = 1ul << channel; +} + +/* Pause a running channel - can be resumed */ +void sdma_channel_pause(unsigned int channel) +{ + if (channel == 0 || channel >= CH_NUM) + return; + + if (ccb_array[channel].status.opened_init == 0) + return; + + SDMA_STOP_STAT = 1ul << channel; +} + +/* Stop a channel from executing - cannot be resumed */ +void sdma_channel_stop(unsigned int channel) +{ + struct channel_control_block *ccb_p; + unsigned long chmsk; + unsigned long intmsk; + int oldstatus; + int i; + + if (channel == 0 || channel >= CH_NUM) + return; + + ccb_p = &ccb_array[channel]; + + if (ccb_p->status.opened_init == 0) + return; + + chmsk = 1ul << channel; + + /* Lock callback */ + oldstatus = disable_irq_save(); + intmsk = sdma_enabled_ints; + sdma_enabled_ints &= ~chmsk; + restore_irq(oldstatus); + + /* Stop execution */ + for (i = ccb_p->channel_desc->bd_count - 1; i >= 0; i--) + ccb_p->base_bd_ptr[i].mode.status &= ~BD_DONE; + + SDMA_STOP_STAT = chmsk; + while (SDMA_STOP_STAT & chmsk); + + /* Unlock callback if it was set */ + if (intmsk & chmsk) + imx31_regset32(&sdma_enabled_ints, chmsk); + + logf("SDMA ch closed: %d", channel); +} + +bool sdma_channel_init(unsigned int channel, + struct channel_descriptor *cd_p, + struct buffer_descriptor *base_bd_p) +{ + struct channel_control_block *ccb_p; + + if (channel == 0 || channel >= CH_NUM || + cd_p == NULL || base_bd_p == NULL) + return false; + + ccb_p = &ccb_array[channel]; + + /* If initialized already, should close first then init. */ + if (ccb_p->status.opened_init != 0) + return false; + + /* Initialize channel control block. */ + ccb_p->curr_bd_ptr = base_bd_p; + ccb_p->base_bd_ptr = base_bd_p; + ccb_p->channel_desc = cd_p; + ccb_p->status.error = 0; + ccb_p->status.opened_init = 1; + ccb_p->status.state_direction = 0; + ccb_p->status.execute = 0; + + /* Finish any channel descriptor inits. */ + cd_p->ccb_ptr = ccb_p; + cd_p->is_setup = 0; + + /* Do an initial setup now. */ + if (!setup_channel(ccb_p)) + { + logf("SDMA ch init failed: %d", channel); + cd_p->ccb_ptr = NULL; + memset(ccb_p, 0x00, sizeof (struct channel_control_block)); + return false; + } + + /* Enable interrupt if a callback is specified. */ + if (cd_p->callback != NULL) + imx31_regset32(&sdma_enabled_ints, 1ul << channel); + + /* Minimum schedulable = 1 */ + sdma_channel_set_priority(channel, 1); + + logf("SDMA ch initialized: %d", channel); + return true; +} + +void sdma_channel_close(unsigned int channel) +{ + struct channel_control_block *ccb_p; + int i; + + if (channel == 0 || channel >= CH_NUM) + return; + + ccb_p = &ccb_array[channel]; + + /* Block callbacks (if not initialized, it won't be set). */ + imx31_regclr32(&sdma_enabled_ints, 1ul << channel); + + if (ccb_p->status.opened_init == 0) + return; + + /* Stop the channel if running */ + for (i = ccb_p->channel_desc->bd_count - 1; i >= 0; i--) + ccb_p->base_bd_ptr[i].mode.status &= ~BD_DONE; + + sdma_channel_stop(channel); + + /* No ownership */ + set_channel_ownership(channel, 0); + + /* Cannot schedule it again */ + sdma_channel_set_priority(channel, 0); + + /* Reset channel control block entry */ + memset(ccb_p, 0x00, sizeof (struct channel_control_block)); +} + +/* Write 32-bit words to SDMA core memory. Host endian->SDMA endian. */ +void sdma_write_words(const unsigned long *buf, unsigned long start, int count) +{ + /* Setup buffer descriptor with channel 0 command */ + set_buffer_descriptor(&c0_buffer_desc.bd, + C0_SETDM, + BD_DONE | BD_WRAP | BD_EXTD, + count, + (void *)addr_virt_to_phys((unsigned long)buf), + (void *)start); + + SDMA_HSTART = 1ul; + sdma_channel_wait_nonblocking(0); +} + +/* Read 32-bit words from SDMA core memory. SDMA endian->host endian. */ +void sdma_read_words(unsigned long *buf, unsigned long start, int count) +{ + /* Setup buffer descriptor with channel 0 command */ + set_buffer_descriptor(&c0_buffer_desc.bd, + C0_GETDM, + BD_DONE | BD_WRAP | BD_EXTD, + count, + (void *)addr_virt_to_phys((unsigned long)buf), + (void *)start); + + SDMA_HSTART = 1ul; + sdma_channel_wait_nonblocking(0); +} diff --git a/firmware/target/arm/imx31/sdma-imx31.h b/firmware/target/arm/imx31/sdma-imx31.h new file mode 100644 index 0000000000..fa8195198b --- /dev/null +++ b/firmware/target/arm/imx31/sdma-imx31.h @@ -0,0 +1,225 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2009 by Michael Sevakis + * + * 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 SDMA_IMX31_H +#define SDMA_IMX31_H + +/* Much of the code in here is based upon the Linux BSP provided by Freescale + * Copyright 2004-2008 Freescale Semiconductor, Inc. All Rights Reserved. */ + +/* Peripheral and transfer type - used to select the proper SDMA channel + * script to execute. */ +enum SDMA_PERIPHERAL_TYPE +{ + __SDMA_PER_FIRST = -1, + SDMA_PER_MEMORY, + SDMA_PER_DSP, + SDMA_PER_FIRI, + SDMA_PER_UART, + SDMA_PER_UART_SP, /* Shared */ + SDMA_PER_ATA, + SDMA_PER_CSPI, + SDMA_PER_EXT, + SDMA_PER_SSI, + SDMA_PER_SSI_SP, /* Shared */ + SDMA_PER_MMC, + SDMA_PER_SDHC, + SDMA_PER_CSPI_SP, /* Shared */ + SDMA_PER_MSHC, + SDMA_PER_MSHC_SP, /* Shared */ + SDMA_PER_CCM, + SDMA_PER_ASRC, + SDMA_PER_ESAI, + SDMA_PER_SIM, + SDMA_PER_SPDIF, + SDMA_PER_IPU_MEMORY, +}; + +enum SDMA_TRANSFER_TYPE +{ + __SDMA_TRAN_FIRST = -1, + SDMA_TRAN_INT_2_INT, + SDMA_TRAN_EMI_2_INT, + SDMA_TRAN_EMI_2_EMI, + SDMA_TRAN_INT_2_EMI, + + SDMA_TRAN_INT_2_DSP, + SDMA_TRAN_DSP_2_INT, + SDMA_TRAN_DSP_2_DSP, + SDMA_TRAN_DSP_2_PER, + SDMA_TRAN_PER_2_DSP, + SDMA_TRAN_EMI_2_DSP, + SDMA_TRAN_DSP_2_EMI, + SDMA_TRAN_DSP_2_EMI_LOOP, + SDMA_TRAN_EMI_2_DSP_LOOP, + + SDMA_TRAN_PER_2_INT, + SDMA_TRAN_PER_2_EMI, + SDMA_TRAN_INT_2_PER, + SDMA_TRAN_EMI_2_PER, +}; + +/* 2.3 - Smart Direct Memory Access (SDMA) Events, Table 2-5 */ +/* These are indexes into the SDMA_CHNENBL register array (each a bitmask + * determining which channels are triggered by requests). */ +enum SDMA_REQUEST_TYPE +{ + SDMA_REQ_EXT0 = 0, /* Extern DMA request from MCU1_0 */ + SDMA_REQ_CCM = 1, /* DVFS/DPTC event (ccm_dvfs_sdma_int) */ + SDMA_REQ_ATA_TX_END = 2, /* ata_txfer_end_alarm (event_id) */ + SDMA_REQ_ATA_TX = 3, /* ata_tx_fifo_alarm (event_id2) */ + SDMA_REQ_ATA_RX = 4, /* ata_rcv_fifo_alarm (event_id2) */ + SDMA_REQ_SIM = 5, /* */ + SDMA_REQ_CSPI2_RX = 6, /* DMA Rx request */ + SDMA_REQ_CSPI2_TX = 7, /* DMA Tx request */ + SDMA_REQ_CSPI1_RX = 8, /* DMA Rx request of CSPI */ + SDMA_REQ_UART3_RX = 8, /* DMA Rx request RxFIFO of UART3 */ + SDMA_REQ_CSPI1_TX = 9, /* DMA Tx request of CSPI */ + SDMA_REQ_UART3_TX = 9, /* DMA Tx request TxFIFO of UART3 */ + SDMA_REQ_CSPI3_RX = 10, /* RxFIFO or CSPI3 Rx request */ + SDMA_REQ_UART5_RX = 10, /* RxFIFO or CSPI3 Rx request */ + SDMA_REQ_CSPI3_TX = 11, /* TxFIFO or CSPI3 Tx request */ + SDMA_REQ_UART5_TX = 11, /* TxFIFO or CSPI3 Tx request */ + SDMA_REQ_UART4_RX = 12, /* RxFIFO */ + SDMA_REQ_UART4_TX = 13, /* TxFIFO */ + SDMA_REQ_EXT2 = 14, /* External DMA request from MCU1_2 or from + MBX (Graphic accelerator) */ + SDMA_REQ_EXT1 = 15, /* External request from MCU1_1 */ + SDMA_REQ_FIRI_RX = 16, /* DMA request of FIR's receiver FIFO + controlled by the pgp_firi signal + from the IOMUXC PGP register */ + SDMA_REQ_UART2_RX = 16, /* RxFIFO of UART2 */ + SDMA_REQ_FIRI_TX = 17, /* DMA request of FIR's transmitter + FIFO controled by the pgp_firi signal + the IOMUXC PGP register */ + SDMA_REQ_UART2_TX = 17, /* TxFIFO of UART2 */ + SDMA_REQ_UART1_RX = 18, /* RxFIFO */ + SDMA_REQ_UART1_TX = 19, /* TxFIFO */ + SDMA_REQ_MMC1 = 20, /* MMC DMA request */ + SDMA_REQ_SDHC1 = 20, /* SDHC1 DMA request */ + SDMA_REQ_MSHC1 = 20, /* MSHC1 DMA request */ + SDMA_REQ_MMC2 = 21, /* MMC DMA request */ + SDMA_REQ_SDHC2 = 21, /* SDHC2 DMA request */ + SDMA_REQ_MSHC2 = 21, /* MSHC2 DMA request */ + SDMA_REQ_SSI2_RX2 = 22, /* SSI #2 receive 2 DMA request (SRX1_2) */ + SDMA_REQ_SSI2_TX2 = 23, /* SSI #2 transmit 2 DMA request (STX1_2) */ + SDMA_REQ_SSI2_RX1 = 24, /* SSI #2 receive 1 DMA request (SRX0_2) */ + SDMA_REQ_SSI2_TX1 = 25, /* SSI #2 transmit 1 DMA request (STX0_2) */ + SDMA_REQ_SSI1_RX2 = 26, /* SSI #1 receive 2 DMA request (SRX1_1) */ + SDMA_REQ_SSI1_TX2 = 27, /* SSI #1 transmit 2 DMA request (STX1_1) */ + SDMA_REQ_SSI1_RX1 = 28, /* SSI #1 receive 1 DMA request (SRX1_0) */ + SDMA_REQ_SSI1_TX1 = 29, /* SSI #1 transmit 1 DMA request (STX1_0) */ + SDMA_REQ_NFC = 30, /* NAND-flash controller */ + SDMA_REQ_IPU = 31, /* IPU source (defaults to IPU at reset) */ + SDMA_REQ_ECT = 31, /* ECT source */ +}; + +/* Addresses for peripheral DMA transfers */ +enum SDMA_PER_ADDR +{ + SDMA_PER_ADDR_SDRAM = SDRAM_BASE_ADDR, /* memory */ + SDMA_PER_ADDR_CCM = CCM_BASE_ADDR+0x00, /* CCMR */ + /* ATA */ + SDMA_PER_ADDR_ATA_TX = ATA_DMA_BASE_ADDR+0x18, + SDMA_PER_ADDR_ATA_RX = ATA_DMA_BASE_ADDR, +#if 0 + SDMA_PER_ADDR_ATA_TX16 = + SDMA_PER_ADDR_ATA_RX16 = +#endif +#if 0 + SDMA_PER_ADDR_SIM = +#endif + /* CSPI2 */ + SDMA_PER_ADDR_CSPI2_RX = CSPI2_BASE_ADDR+0x00, /* RXDATA2 */ + SDMA_PER_ADDR_CSPI2_TX = CSPI2_BASE_ADDR+0x04, /* TXDATA2 */ + /* CSPI1 */ + SDMA_PER_ADDR_CSPI1_RX = CSPI1_BASE_ADDR+0x00, /* RXDATA1 */ + SDMA_PER_ADDR_CSPI1_TX = CSPI1_BASE_ADDR+0x04, /* TXDATA1 */ + /* UART3 */ + SDMA_PER_ADDR_UART3_RX = UART3_BASE_ADDR+0x00, /* URXD3 */ + SDMA_PER_ADDR_UART3_TX = UART3_BASE_ADDR+0x40, /* UTXD3 */ + /* CSPI3 */ + SDMA_PER_ADDR_CSPI3_RX = CSPI3_BASE_ADDR+0x00, /* RXDATA3 */ + SDMA_PER_ADDR_CSPI3_TX = CSPI3_BASE_ADDR+0x04, /* TXDATA3 */ + /* UART5 */ + SDMA_PER_ADDR_UART5_RX = UART5_BASE_ADDR+0x00, /* URXD5 */ + SDMA_PER_ADDR_UART5_TX = UART5_BASE_ADDR+0x40, /* UTXD5 */ + /* UART4 */ + SDMA_PER_ADDR_UART4_RX = UART4_BASE_ADDR+0x00, /* URXD4 */ + SDMA_PER_ADDR_UART4_TX = UART4_BASE_ADDR+0x40, /* UTXD4 */ + /* FIRI */ + SDMA_PER_ADDR_FIRI_RX = FIRI_BASE_ADDR+0x18, /* Receiver FIFO */ + SDMA_PER_ADDR_FIRI_TX = FIRI_BASE_ADDR+0x14, /* Transmitter FIFO */ + /* UART2 */ + SDMA_PER_ADDR_UART2_RX = UART2_BASE_ADDR+0x00, /* URXD2 */ + SDMA_PER_ADDR_UART2_TX = UART2_BASE_ADDR+0x40, /* UTXD2 */ + /* UART1 */ + SDMA_PER_ADDR_UART1_RX = UART1_BASE_ADDR+0x00, /* URXD1 */ + SDMA_PER_ADDR_UART1_TX = UART1_BASE_ADDR+0x40, /* UTXD1 */ + SDMA_PER_ADDR_MMC_SDHC1 = MMC_SDHC1_BASE_ADDR+0x38, /* BUFFER_ACCESS */ + SDMA_PER_ADDR_MMC_SDHC2 = MMC_SDHC2_BASE_ADDR+0x38, /* BUFFER_ACCESS */ +#if 0 + SDMA_PER_ADDR_MSHC1 = + SDMA_PER_ADDR_MSHC2 = +#endif + /* SSI2 */ + SDMA_PER_ADDR_SSI2_RX2 = SSI2_BASE_ADDR+0x0C, /* SRX1_2 */ + SDMA_PER_ADDR_SSI2_TX2 = SSI2_BASE_ADDR+0x04, /* STX1_2 */ + SDMA_PER_ADDR_SSI2_RX1 = SSI2_BASE_ADDR+0x08, /* SRX0_2 */ + SDMA_PER_ADDR_SSI2_TX1 = SSI2_BASE_ADDR+0x00, /* STX0_2 */ + /* SSI1 */ + SDMA_PER_ADDR_SSI1_RX2 = SSI1_BASE_ADDR+0x0C, /* SRX1_1 */ + SDMA_PER_ADDR_SSI1_TX2 = SSI1_BASE_ADDR+0x04, /* STX1_1 */ + SDMA_PER_ADDR_SSI1_RX1 = SSI1_BASE_ADDR+0x08, /* SRX0_1 */ + SDMA_PER_ADDR_SSI1_TX1 = SSI1_BASE_ADDR+0x00, /* STX0_1 */ +#if 0 + SDMA_PER_ADDR_NFC = + SDMA_PER_ADDR_IPU = + SDMA_PER_ADDR_ECT = +#endif +}; + +/* DMA driver defines */ +#define SDMA_SDHC_MMC_WML 16 +#define SDMA_SDHC_SD_WML 64 +#define SDMA_SSI_TXFIFO_WML 4 /* Four samples written per channel activation */ +#define SDMA_SSI_RXFIFO_WML 6 /* Six samples read per channel activation */ +#define SDMA_FIRI_WML 16 + +#define SDMA_ATA_WML 32 /* DMA watermark level in bytes */ +#define SDMA_ATA_BD_NR (512/3/4) /* Number of BDs per channel */ + +#include "sdma_struct.h" + +void sdma_init(void); +void sdma_read_words(unsigned long *buf, unsigned long start, int count); +void sdma_write_words(const unsigned long *buf, unsigned long start, int count); +void sdma_channel_set_priority(unsigned int channel, unsigned int priority); +void sdma_channel_start(unsigned int channel); +void sdma_channel_run(unsigned int channel); +void sdma_channel_pause(unsigned int channel); +void sdma_channel_stop(unsigned int channel); +void sdma_channel_wait_nonblocking(unsigned int channel); +bool sdma_channel_init(unsigned int channel, + struct channel_descriptor *cd_p, + struct buffer_descriptor *base_bd_p); +void sdma_channel_close(unsigned int channel); + +#endif /* SDMA_IMX31_H */ diff --git a/firmware/target/arm/imx31/sdma_script_code.h b/firmware/target/arm/imx31/sdma_script_code.h new file mode 100644 index 0000000000..b80c39534b --- /dev/null +++ b/firmware/target/arm/imx31/sdma_script_code.h @@ -0,0 +1,1060 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2009 by Michael Sevakis + * + * 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. + * + ****************************************************************************/ + +/* + * Taken from from the Linux BSP provided by Freescale. + * Copyright 2004-2008 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* This header contains both versions 1 and 2 of SDMA code */ + +#ifndef __SDMA_SCRIPT_CODE_H__ +#define __SDMA_SCRIPT_CODE_H__ +/*! +* Following define start address of start script +*/ +#define start_ADDR_1 0 +/*! +* Following define size of start script +*/ +#define start_SIZE_1 21 + +/*! +* Following define start address of core script +*/ +#define core_ADDR_1 80 +/*! +* Following define size of core script +*/ +#define core_SIZE_1 152 + +/*! +* Following define start address of common script +*/ +#define common_ADDR_1 232 +/*! +* Following define size of common script +*/ +#define common_SIZE_1 191 + +/*! +* Following define start address of burst_copy script +*/ +#define burst_copy_ADDR_1 423 +/*! +* Following define size of burst_copy script +*/ +#define burst_copy_SIZE_1 87 + +/*! +* Following define start address of dsp_2_burst script +*/ +#define dsp_2_burst_ADDR_1 510 +/*! +* Following define size of dsp_2_burst script +*/ +#define dsp_2_burst_SIZE_1 24 + +/*! +* Following define start address of burst_2_dsp script +*/ +#define burst_2_dsp_ADDR_1 534 +/*! +* Following define size of burst_2_dsp script +*/ +#define burst_2_dsp_SIZE_1 24 + +/*! +* Following define start address of dsp_copy script +*/ +#define dsp_copy_ADDR_1 558 +/*! +* Following define size of dsp_copy script +*/ +#define dsp_copy_SIZE_1 86 + +/*! +* Following define start address of mcu_2_mcu script +*/ +#define mcu_2_mcu_ADDR_1 644 +/*! +* Following define size of mcu_2_mcu script +*/ +#define mcu_2_mcu_SIZE_1 79 + +/*! +* Following define start address of mcu_2_per script +*/ +#define mcu_2_per_ADDR_1 723 +/*! +* Following define size of mcu_2_per script +*/ +#define mcu_2_per_SIZE_1 88 + +/*! +* Following define start address of test script +*/ +#define test_ADDR_1 811 +/*! +* Following define size of test script +*/ +#define test_SIZE_1 63 + +/*! +* Following define start address of mcu_2_dsp script +*/ +#define mcu_2_dsp_ADDR_1 874 +/*! +* Following define size of mcu_2_dsp script +*/ +#define mcu_2_dsp_SIZE_1 30 + +/*! +* Following define start address of mcu_2_dsp_2buf script +*/ +#define mcu_2_dsp_2buf_ADDR_1 904 +/*! +* Following define size of mcu_2_dsp_2buf script +*/ +#define mcu_2_dsp_2buf_SIZE_1 113 + +/*! +* Following define start address of dsp_2_mcu script +*/ +#define dsp_2_mcu_ADDR_1 1017 +/*! +* Following define size of dsp_2_mcu script +*/ +#define dsp_2_mcu_SIZE_1 30 + +/*! +* Following define start address of dsp_2_mcu_2buf script +*/ +#define dsp_2_mcu_2buf_ADDR_1 1047 +/*! +* Following define size of dsp_2_mcu_2buf script +*/ +#define dsp_2_mcu_2buf_SIZE_1 113 + +/*! +* Following define start address of dsp_2_dsp script +*/ +#define dsp_2_dsp_ADDR_1 1160 +/*! +* Following define size of dsp_2_dsp script +*/ +#define dsp_2_dsp_SIZE_1 64 + +/*! +* Following define start address of per_2_mcu script +*/ +#define per_2_mcu_ADDR_1 1224 +/*! +* Following define size of per_2_mcu script +*/ +#define per_2_mcu_SIZE_1 121 + +/*! +* Following define start address of dsp_2_per_2buf script +*/ +#define dsp_2_per_2buf_ADDR_1 1345 +/*! +* Following define size of dsp_2_per_2buf script +*/ +#define dsp_2_per_2buf_SIZE_1 164 + +/*! +* Following define start address of per_2_dsp_2buf script +*/ +#define per_2_dsp_2buf_ADDR_1 1509 +/*! +* Following define size of per_2_dsp_2buf script +*/ +#define per_2_dsp_2buf_SIZE_1 168 + +/*! +* Following define start address of per_2_per script +*/ +#define per_2_per_ADDR_1 1677 +/*! +* Following define size of per_2_per script +*/ +#define per_2_per_SIZE_1 67 + +/*! +* Following define start address of error_dsp script +*/ +#define error_dsp_ADDR_1 1744 +/*! +* Following define size of error_dsp script +*/ +#define error_dsp_SIZE_1 34 + +/*! +* Following define start address of ap_2_ap script +*/ +#define ap_2_ap_ADDR_1 6144 +/*! +* Following define size of ap_2_ap script +*/ +#define ap_2_ap_SIZE_1 294 + +/*! +* Following define start address of app_2_mcu script +*/ +#define app_2_mcu_ADDR_1 6438 +/*! +* Following define size of app_2_mcu script +*/ +#define app_2_mcu_SIZE_1 101 + +/*! +* Following define start address of ata_2_mcu script +*/ +#define ata_2_mcu_ADDR_1 6539 +/*! +* Following define size of ata_2_mcu script +*/ +#define ata_2_mcu_SIZE_1 110 + +/*! +* Following define start address of dptc_dvfs script +*/ +#define dptc_dvfs_ADDR_1 6649 +/*! +* Following define size of dptc_dvfs script +*/ +#define dptc_dvfs_SIZE_1 274 + +/*! +* Following define start address of error script +*/ +#define error_ADDR_1 6923 +/*! +* Following define size of error script +*/ +#define error_SIZE_1 73 + +/*! +* Following define start address of firi_2_mcu script +*/ +#define firi_2_mcu_ADDR_1 6996 +/*! +* Following define size of firi_2_mcu script +*/ +#define firi_2_mcu_SIZE_1 114 + +/*! +* Following define start address of mcu_2_app script +*/ +#define mcu_2_app_ADDR_1 7110 +/*! +* Following define size of mcu_2_app script +*/ +#define mcu_2_app_SIZE_1 127 + +/*! +* Following define start address of mcu_2_ata script +*/ +#define mcu_2_ata_ADDR_1 7237 +/*! +* Following define size of mcu_2_ata script +*/ +#define mcu_2_ata_SIZE_1 87 + +/*! +* Following define start address of mcu_2_firi script +*/ +#define mcu_2_firi_ADDR_1 7324 +/*! +* Following define size of mcu_2_firi script +*/ +#define mcu_2_firi_SIZE_1 77 + +/*! +* Following define start address of mcu_2_mshc script +*/ +#define mcu_2_mshc_ADDR_1 7401 +/*! +* Following define size of mcu_2_mshc script +*/ +#define mcu_2_mshc_SIZE_1 48 + +/*! +* Following define start address of mcu_2_shp script +*/ +#define mcu_2_shp_ADDR_1 7449 +/*! +* Following define size of mcu_2_shp script +*/ +#define mcu_2_shp_SIZE_1 123 + +/*! +* Following define start address of mshc_2_mcu script +*/ +#define mshc_2_mcu_ADDR_1 7572 +/*! +* Following define size of mshc_2_mcu script +*/ +#define mshc_2_mcu_SIZE_1 60 + +/*! +* Following define start address of shp_2_mcu script +*/ +#define shp_2_mcu_ADDR_1 7632 +/*! +* Following define size of shp_2_mcu script +*/ +#define shp_2_mcu_SIZE_1 101 + +/*! +* Following define start address of uart_2_mcu script +*/ +#define uart_2_mcu_ADDR_1 7733 +/*! +* Following define size of uart_2_mcu script +*/ +#define uart_2_mcu_SIZE_1 105 + +/*! +* Following define start address of uartsh_2_mcu script +*/ +#define uartsh_2_mcu_ADDR_1 7838 +/*! +* Following define size of uartsh_2_mcu script +*/ +#define uartsh_2_mcu_SIZE_1 98 + +/*! +* Following define the start address of sdma ram +*/ + +#define RAM_CODE_START_ADDR_1 6144 +/*! +* Following define the size of sdma ram +*/ +#define RAM_CODE_SIZE_1 1792 + +/*! + * Code download for i.MX system revision = 1.0 + */ +static __attribute__((aligned(4))) const short sdma_code_1[RAM_CODE_SIZE_1] = +{ + 0xc0ec, 0x7d59, 0x0970, 0x0111, 0x5111, 0x5ad1, 0x5bd9, 0xc0fe, + 0x5ce1, 0x7d02, 0x0200, 0x9806, 0x08ff, 0x0011, 0x28ff, 0x00bc, + 0x05df, 0x7d4b, 0x06df, 0x7d2f, 0x6dc5, 0x6ed5, 0x5ef1, 0x0288, + 0xd81a, 0x9854, 0x0b04, 0x00d3, 0x7d20, 0x06a5, 0x3e03, 0x3d03, + 0x03a5, 0x3b03, 0x008b, 0x058b, 0x7802, 0x63d8, 0x0000, 0x7e72, + 0x63ff, 0x7e70, 0x02a5, 0x008a, 0x4e00, 0x7d01, 0x983d, 0x6dcf, + 0x6edf, 0x0015, 0x0015, 0x7802, 0x63d8, 0x0000, 0x7e63, 0x63ff, + 0x7e61, 0x3a03, 0x008a, 0x6dcd, 0x6edd, 0x7801, 0x63d8, 0x7e5a, + 0x63ff, 0x7e58, 0x0006, 0x6dc5, 0x6e07, 0x5ef1, 0x0288, 0xd8f7, + 0x7e02, 0x7f04, 0x9854, 0x0007, 0x68cc, 0x6b28, 0x54e1, 0x0089, + 0xdb13, 0x0188, 0x5ce1, 0x9854, 0x52d1, 0x53d9, 0x54e1, 0xc10d, + 0x7dad, 0x0200, 0x9800, 0x0200, 0x9800, 0x06df, 0x7d06, 0x6d23, + 0x6ed5, 0x5ef1, 0x0288, 0xd8cd, 0x9854, 0x5ef1, 0x6e07, 0x6d03, + 0x0b04, 0x00d3, 0x7d59, 0x06a5, 0x3e03, 0x3d03, 0x4d00, 0x7d09, + 0x03a5, 0x00a3, 0x0588, 0x008b, 0xd8c9, 0x7ed8, 0x620c, 0x7ed6, + 0x008d, 0x4e00, 0x7c25, 0x0a20, 0x00da, 0x7c22, 0x6503, 0x3d1f, + 0x02a5, 0x00a2, 0x0215, 0x0215, 0x6a18, 0x6a28, 0x7fc7, 0x0a20, + 0x0b08, 0x00da, 0x7c06, 0x6b18, 0x6b28, 0x7fc0, 0x0000, 0x2020, + 0x9889, 0x0688, 0x0015, 0x0015, 0x6818, 0x6828, 0x7fb7, 0x98c2, + 0x0007, 0x6a0c, 0x54e1, 0x0089, 0xdb0f, 0x0188, 0x5ce1, 0x9854, + 0x0b04, 0x00d3, 0x7d21, 0x0389, 0x1b12, 0x048b, 0x0688, 0x0015, + 0x0015, 0x0588, 0x038c, 0x0a08, 0x05da, 0x008d, 0x7c01, 0x008a, + 0x05a0, 0x7803, 0x620b, 0x5a03, 0x1b01, 0x7e98, 0x008b, 0x00a4, + 0x038c, 0x7803, 0x5203, 0x6a0b, 0x1b01, 0x6a28, 0x7f8f, 0x0000, + 0x4d00, 0x7ce8, 0x008e, 0x3803, 0xd8c9, 0x7e88, 0x620c, 0x7e86, + 0x9854, 0x7802, 0x6209, 0x6a29, 0x0006, 0x3e03, 0x4e00, 0x7d11, + 0x0b04, 0x03a6, 0x02db, 0x7d01, 0x038a, 0x02a3, 0x048a, 0x008b, + 0x7802, 0x6329, 0x6bc8, 0x7ebc, 0x63c8, 0x7ebc, 0x008c, 0x4800, + 0x7d15, 0x0488, 0x0015, 0x0015, 0x6edf, 0x7803, 0x632b, 0x6bc8, + 0x0000, 0x7eae, 0x63c8, 0x7eae, 0x008c, 0x3803, 0x6edd, 0x7803, + 0x6329, 0x6bc8, 0x0000, 0x7ea4, 0x63c8, 0x7ea4, 0x0006, 0x3d03, + 0x4d00, 0x7d0e, 0x0b04, 0x03a5, 0x02db, 0x7d01, 0x038a, 0x02a3, + 0x048a, 0x008b, 0x7802, 0x63c8, 0x6b09, 0x7e1e, 0x7f1e, 0x008c, + 0x0488, 0x0015, 0x0015, 0x6dcf, 0x0288, 0x008a, 0x0d08, 0x02dd, + 0x7c01, 0x008d, 0x7802, 0x63c8, 0x6b0b, 0x7e0e, 0x6b28, 0x7f0d, + 0x0000, 0x02dd, 0x7c02, 0x2208, 0x990d, 0x008c, 0x3803, 0x65c0, + 0x6dc5, 0x7802, 0x63c8, 0x6b09, 0x6b28, 0x0006, 0x0870, 0x0011, + 0x5010, 0xc0ec, 0x7d5e, 0x5ac0, 0x5bc8, 0x5ef8, 0xc0fe, 0x56f8, + 0x7d02, 0x0200, 0x992c, 0x6ec3, 0x6d07, 0x5df0, 0x0dff, 0x0511, + 0x1dff, 0x05bc, 0x4d00, 0x7d44, 0x0b70, 0x0311, 0x522b, 0x5313, + 0x02b9, 0x4a00, 0x7c04, 0x6a28, 0x7f3a, 0x0400, 0x993c, 0x008f, + 0x00d5, 0x7d01, 0x008d, 0x05a0, 0x0a03, 0x0212, 0x02bc, 0x0210, + 0x4a00, 0x7d1c, 0x4a02, 0x7d20, 0x4a01, 0x7d23, 0x0b70, 0x0311, + 0x53eb, 0x62c8, 0x7e24, 0x0360, 0x7d02, 0x0210, 0x0212, 0x6a09, + 0x7f1e, 0x0212, 0x6a09, 0x7f1b, 0x0212, 0x6a09, 0x7f18, 0x2003, + 0x4800, 0x7cef, 0x0b70, 0x0311, 0x5313, 0x997d, 0x0015, 0x0015, + 0x7802, 0x62c8, 0x6a0b, 0x997c, 0x0015, 0x7802, 0x62c8, 0x6a0a, + 0x997c, 0x7802, 0x62c8, 0x6a09, 0x7c02, 0x0000, 0x993a, 0xdb13, + 0x6a28, 0x7ffd, 0x008b, 0x52c3, 0x53cb, 0xc10d, 0x7da5, 0x0200, + 0x992c, 0x0200, 0x9929, 0xc19d, 0xc0ec, 0x7d69, 0x0c70, 0x0411, + 0x5414, 0x5ac4, 0x028c, 0x58da, 0x5efa, 0xc0fe, 0x56fa, 0x7d02, + 0x0200, 0x9994, 0x6d07, 0x5bca, 0x5cd2, 0x0bff, 0x0311, 0x1bff, + 0x04bb, 0x0415, 0x53da, 0x4c00, 0x7d47, 0x0a70, 0x0211, 0x552a, + 0x5212, 0x008d, 0x00bb, 0x4800, 0x7c07, 0x05b9, 0x4d00, 0x7c13, + 0x6928, 0x7f2d, 0x0400, 0x99a5, 0x008f, 0x0015, 0x04d8, 0x7d01, + 0x008c, 0x04a0, 0x0015, 0x7802, 0x55c6, 0x6d0b, 0x7e29, 0x6d28, + 0x7f1e, 0x0000, 0x99a3, 0x1e20, 0x5506, 0x2620, 0x008d, 0x0560, + 0x7c08, 0x065f, 0x55c6, 0x063f, 0x7e1b, 0x6d0a, 0x7f10, 0x4c00, + 0x7d1b, 0x04d8, 0x7d02, 0x008c, 0x0020, 0x04a0, 0x0015, 0x7802, + 0x55c6, 0x6d0b, 0x7e0d, 0x6d28, 0x7f02, 0x0000, 0x99ec, 0x0007, + 0x680c, 0x6d0c, 0x6507, 0x6d07, 0x6d2b, 0x6d28, 0x0007, 0x680c, + 0x0007, 0x54d2, 0x0454, 0x99ef, 0x6928, 0x7ff1, 0x54d2, 0x008a, + 0x52c0, 0x53c8, 0xc10d, 0x0288, 0x7d9f, 0x0200, 0x9994, 0x0200, + 0x998c, 0xc0ec, 0x7d72, 0x0800, 0x0970, 0x0111, 0x5111, 0x5ac1, + 0x5bc9, 0x028e, 0xc0fe, 0x068a, 0x7c6a, 0x5dd9, 0x5ce1, 0x0bff, + 0x0311, 0x1bff, 0x03bc, 0x5bd1, 0x1a5c, 0x6ac3, 0x63c8, 0x0363, + 0x7c05, 0x036f, 0x7d27, 0x0374, 0x7c7a, 0x9a71, 0xdb04, 0x3c06, + 0x4c00, 0x7df7, 0x028f, 0x1a04, 0x6a23, 0x620b, 0x6f23, 0x301f, + 0x00aa, 0x0462, 0x7c04, 0x4a00, 0x7d0b, 0x2001, 0x9a30, 0x048a, + 0x620b, 0x2201, 0x1c01, 0x1801, 0x02dc, 0x7d02, 0x301f, 0x00aa, + 0x048f, 0x1c04, 0x6c07, 0x0488, 0x3c1f, 0x6c2b, 0x0045, 0x028e, + 0x1a5c, 0x9a11, 0x058f, 0x1d0c, 0x6d23, 0x650b, 0x007d, 0x7c01, + 0x1d08, 0x007c, 0x7c01, 0x1d04, 0x6d23, 0x650b, 0x0488, 0x3c1f, + 0x0417, 0x0417, 0x0417, 0x0417, 0x059c, 0x6d23, 0x028e, 0x1a34, + 0x6ad7, 0x0488, 0x0804, 0x7802, 0x650b, 0x6dc8, 0x008c, 0x1a28, + 0x6ad7, 0x63c8, 0x034c, 0x6bc8, 0x54d1, 0x4c00, 0x7d06, 0x0065, + 0x7c02, 0x0101, 0x0025, 0x0400, 0x9a0d, 0x52c1, 0x53c9, 0x54e1, + 0x0453, 0xc10d, 0x7d95, 0x0200, 0x9a00, 0x0200, 0x99f9, 0x0200, + 0x9a00, 0x55d9, 0x6d07, 0x54d1, 0x058a, 0x2508, 0x6dc7, 0x0373, + 0x7c03, 0x65c8, 0x6d0b, 0x2408, 0x0372, 0x7c04, 0x65c8, 0x6d0b, + 0x2408, 0x9a86, 0x6cce, 0x65c8, 0x6d0a, 0x2404, 0x6d28, 0x6507, + 0x5dd9, 0x5cd1, 0x6ad7, 0x6ae3, 0x63c8, 0x0334, 0x6bc8, 0x0370, + 0x7ca9, 0x0c60, 0x0411, 0x04bb, 0x4c00, 0x7da4, 0x0410, 0x1c30, + 0x0410, 0x04bb, 0x046d, 0x7d0a, 0x047d, 0x7c03, 0x047c, 0x7c01, + 0x9a3a, 0x003b, 0x003a, 0x0039, 0x0058, 0x9ab5, 0x047d, 0x7d03, + 0x047c, 0x7d01, 0x9a3a, 0x005b, 0xdaf9, 0x1d18, 0x6d23, 0x650b, + 0x0510, 0x003a, 0x0039, 0x0038, 0x00ad, 0xdb04, 0x0c30, 0x0410, + 0x04bb, 0x003c, 0x003d, 0x00ac, 0xdaf9, 0x007b, 0x7c04, 0x003d, + 0x003c, 0x1d0c, 0x9ad6, 0x048f, 0x1c14, 0x6c23, 0x640b, 0x4401, + 0x7d04, 0x005d, 0x005c, 0x1d0c, 0x9ad6, 0x0310, 0x3b30, 0x4b30, + 0x7d01, 0x1b10, 0x0310, 0x003d, 0x003c, 0x00ab, 0x6ad7, 0x63c8, + 0x6d23, 0x650b, 0x0560, 0x7d03, 0x005e, 0xdaed, 0x9a3a, 0x003e, + 0x0c80, 0x0410, 0x0394, 0xdaed, 0x640b, 0x037f, 0x7d02, 0x1a14, + 0x9aea, 0x1a0c, 0x6ad7, 0x6cc8, 0x9a3a, 0x0c7f, 0x0410, 0x03b4, + 0x04b8, 0x03ac, 0x640b, 0x6bc8, 0x028e, 0x1a04, 0x6ad7, 0x6cc8, + 0x0006, 0x058f, 0x1d08, 0x6d23, 0x650b, 0x007d, 0x7c01, 0x1d38, + 0x007c, 0x7c01, 0x1d1c, 0x0006, 0x048b, 0x042c, 0x0454, 0x042b, + 0x6ad7, 0x6cc8, 0x0006, 0x0007, 0x684c, 0x6144, 0x9b1c, 0x0007, + 0x68cc, 0x61d0, 0x9b1c, 0x0007, 0x680c, 0x680c, 0x6107, 0x6907, + 0x692b, 0x6928, 0x0007, 0x680c, 0x0d70, 0x0511, 0x5515, 0x55f5, + 0x01a5, 0x0dff, 0x0512, 0x1dff, 0x0512, 0x04bd, 0x0499, 0x0454, + 0x0006, 0x08ff, 0x0011, 0x28ff, 0x0006, 0x038c, 0x0eff, 0x0611, + 0x2eff, 0x03b6, 0x0006, 0x53d6, 0x0398, 0x5bd6, 0x53ee, 0x0398, + 0x5bee, 0x0006, 0x52de, 0x53e6, 0x54ee, 0x0498, 0x0454, 0x0006, + 0x50f6, 0x52c6, 0x53ce, 0x54d6, 0x0498, 0x0454, 0x0006, 0x6207, + 0x0b70, 0x0311, 0x5013, 0x55f0, 0x02a5, 0x0bff, 0x0312, 0x1bff, + 0x0312, 0x04bb, 0x049a, 0x0006, 0x1e10, 0x0870, 0x0011, 0x5010, + 0xc0ec, 0x7d39, 0x5ac0, 0x5bc8, 0x5ef8, 0xc0fe, 0x56f8, 0x7d02, + 0x0200, 0x9b5b, 0x6d07, 0x5df0, 0x0dff, 0x0511, 0x1dff, 0x05bc, + 0x4d00, 0x7d17, 0x6ec3, 0x62c8, 0x7e28, 0x0264, 0x7d08, 0x0b70, + 0x0311, 0x522b, 0x02b9, 0x4a00, 0x7c18, 0x0400, 0x9b6a, 0x0212, + 0x3aff, 0x008a, 0x05d8, 0x7d01, 0x008d, 0x0a10, 0x6ed3, 0x6ac8, + 0xdba5, 0x6a28, 0x7f17, 0x0b70, 0x0311, 0x5013, 0xdbbd, 0x52c0, + 0x53c8, 0xc10d, 0x7dd0, 0x0200, 0x9b5b, 0x008f, 0x00d5, 0x7d01, + 0x008d, 0xdba5, 0x9b68, 0x0200, 0x9b58, 0x0007, 0x68cc, 0x6a28, + 0x7f01, 0x9ba3, 0x0007, 0x6a0c, 0x6a0c, 0x6207, 0x6a07, 0x6a2b, + 0x6a28, 0x0007, 0x680c, 0x0454, 0x9b81, 0x05a0, 0x1e08, 0x6ec3, + 0x0388, 0x3b03, 0x0015, 0x0015, 0x7802, 0x62c8, 0x6a0b, 0x7ee5, + 0x6a28, 0x7fe8, 0x0000, 0x6ec1, 0x008b, 0x7802, 0x62c8, 0x6a09, + 0x7edc, 0x6a28, 0x7fdf, 0x2608, 0x0006, 0x55f0, 0x6207, 0x02a5, + 0x0dff, 0x0511, 0x1dff, 0x04b5, 0x049a, 0x0006, 0x0870, 0x0011, + 0x5010, 0xc0ec, 0x7d78, 0x5ac0, 0x5bc8, 0x5ef8, 0xc0fe, 0x56f8, + 0x7d02, 0x0200, 0x9bcc, 0x6d03, 0x6ed3, 0x0dff, 0x0511, 0x1dff, + 0x05bc, 0x5df8, 0x4d00, 0x7d5e, 0x0b70, 0x0311, 0x522b, 0x5313, + 0x02b9, 0x4a00, 0x7c04, 0x62ff, 0x7e3f, 0x0400, 0x9bdc, 0x008f, + 0x00d5, 0x7d01, 0x008d, 0x05a0, 0x5ddb, 0x0d03, 0x0512, 0x05bc, + 0x0510, 0x5dd3, 0x4d00, 0x7d27, 0x4d02, 0x7d20, 0x4d01, 0x7d1a, + 0x0b70, 0x0311, 0x53eb, 0x0360, 0x7d05, 0x6509, 0x7e25, 0x620a, + 0x7e23, 0x9c06, 0x620a, 0x7e20, 0x6509, 0x7e1e, 0x0512, 0x0512, + 0x02ad, 0x6ac8, 0x7f19, 0x2003, 0x4800, 0x7ced, 0x0b70, 0x0311, + 0x5313, 0x9c21, 0x7802, 0x6209, 0x6ac8, 0x9c20, 0x0015, 0x7802, + 0x620a, 0x6ac8, 0x9c20, 0x0015, 0x0015, 0x7802, 0x620b, 0x6ac8, + 0x7c03, 0x0000, 0x55db, 0x9bda, 0x0007, 0x68cc, 0x680c, 0x55d3, + 0x4d00, 0x7d03, 0x4d02, 0x7d02, 0x9c2f, 0x0017, 0x0017, 0x55db, + 0x009d, 0x55fb, 0x05a0, 0x08ff, 0x0011, 0x18ff, 0x0010, 0x04b8, + 0x04ad, 0x0454, 0x62ff, 0x7ee8, 0x008b, 0x52c0, 0x53c8, 0xc10d, + 0x7d8b, 0x0200, 0x9bcc, 0x0200, 0x9bc9, 0xc19d, 0xc0ec, 0x7d52, + 0x0c70, 0x0411, 0x5414, 0x5ac4, 0x028c, 0x58da, 0x5efa, 0xc0fe, + 0x56fa, 0x7d02, 0x0200, 0x9c4e, 0x6d03, 0x5bca, 0x5cd2, 0x0bff, + 0x0311, 0x1bff, 0x04bb, 0x0415, 0x53da, 0x0a70, 0x0211, 0x4c00, + 0x7d28, 0x552a, 0x05bb, 0x4d00, 0x7c02, 0x0400, 0x9c61, 0x4c01, + 0x7d0f, 0x008f, 0x0015, 0x04d8, 0x7d01, 0x008c, 0x0020, 0x04a0, + 0x0015, 0x7802, 0x650b, 0x5d06, 0x0000, 0x7e0c, 0x7f0d, 0x9c5f, + 0x650a, 0x7e08, 0x008d, 0x0011, 0x0010, 0x05a8, 0x065f, 0x5d06, + 0x063f, 0x7f02, 0x0007, 0x680c, 0x0007, 0x5012, 0x54d0, 0x0454, + 0x9c8b, 0x5012, 0x54d0, 0x0473, 0x7c06, 0x552a, 0x05b9, 0x4d00, + 0x7c02, 0x0400, 0x9c8d, 0x52c0, 0x53c8, 0xc10d, 0x0288, 0x7db6, + 0x0200, 0x9c4e, 0x0200, 0x9c46, 0x0870, 0x0011, 0x5010, 0xc0ec, + 0x7d46, 0x5ac0, 0x5bc8, 0x5ef8, 0xc0fe, 0x56f8, 0x7d02, 0x0200, + 0x9ca2, 0x0b70, 0x0311, 0x6ed3, 0x6d03, 0x0dff, 0x0511, 0x1dff, + 0x05bc, 0x4d00, 0x7d2b, 0x522b, 0x02b9, 0x4a00, 0x7c04, 0x62c8, + 0x7e1f, 0x0400, 0x9cb3, 0x008f, 0x00d5, 0x7d01, 0x008d, 0x05a0, + 0x0060, 0x7c05, 0x6edd, 0x6209, 0x7e16, 0x6ac8, 0x7f11, 0x0015, + 0x0060, 0x7c05, 0x6ede, 0x620a, 0x7e0e, 0x6ac8, 0x7f09, 0x6edf, + 0x0015, 0x7802, 0x620b, 0x6ac8, 0x0000, 0x7e05, 0x7f01, 0x9cb1, + 0x0007, 0x68cc, 0x9cdd, 0x0007, 0x6a0c, 0x0454, 0x62c8, 0x7ef8, + 0x5013, 0x52c0, 0x53c8, 0xc10d, 0x7dbd, 0x0200, 0x9ca2, 0x0200, + 0x9c9f, 0xc19d, 0x0870, 0x0011, 0xc0ec, 0x7d29, 0x5010, 0x5ac0, + 0x5ef8, 0xc0fe, 0x56f8, 0x7d02, 0x0200, 0x9cf0, 0x0870, 0x0011, + 0x6d03, 0x0dff, 0x0511, 0x1dff, 0x05bc, 0x4d00, 0x7d12, 0x5228, + 0x02b9, 0x4a00, 0x7c02, 0x0400, 0x9cff, 0x620b, 0x7e06, 0x5a06, + 0x7f06, 0x0000, 0x2504, 0x7d05, 0x9cff, 0x0007, 0x680c, 0x0007, + 0x0454, 0x5010, 0x52c0, 0xc10d, 0x7ddb, 0x0200, 0x9cf0, 0x0200, + 0x9cec, 0xc19d, 0x0870, 0x0011, 0xc0ec, 0x7d74, 0x5010, 0x5ac0, + 0x5bc8, 0x5ef8, 0xc0fe, 0x56f8, 0x7d02, 0x0200, 0x9d20, 0x6d03, + 0x0d03, 0x0512, 0x05bc, 0x0510, 0x5dd0, 0x0dff, 0x0511, 0x1dff, + 0x05bc, 0x5df8, 0x4d00, 0x7d57, 0x0a70, 0x0211, 0x532a, 0x5212, + 0x03b9, 0x4b00, 0x7c02, 0x0400, 0x9d34, 0x008f, 0x05d8, 0x7d01, + 0x008d, 0x05a0, 0x5dda, 0x55d2, 0x4d00, 0x7d27, 0x4d02, 0x7d20, + 0x4d01, 0x7d1a, 0x0a70, 0x0211, 0x52ea, 0x0260, 0x7d05, 0x6509, + 0x7e25, 0x630a, 0x7e23, 0x9d58, 0x630a, 0x7e20, 0x6509, 0x7e1e, + 0x0512, 0x0512, 0x03ad, 0x5b06, 0x7f19, 0x2003, 0x4800, 0x7ced, + 0x0a70, 0x0211, 0x5212, 0x9d73, 0x7802, 0x6309, 0x5b06, 0x9d72, + 0x0015, 0x7802, 0x630a, 0x5b06, 0x9d72, 0x0015, 0x0015, 0x7802, + 0x630b, 0x5b06, 0x7c03, 0x55da, 0x0000, 0x9d32, 0x0007, 0x680c, + 0x55d2, 0x4d00, 0x7d03, 0x4d02, 0x7d02, 0x9d80, 0x0017, 0x0017, + 0x55da, 0x009d, 0x55fa, 0x05a0, 0x08ff, 0x0011, 0x18ff, 0x0010, + 0x04b8, 0x04ad, 0x0454, 0x008a, 0x52c0, 0x53c8, 0xc10d, 0x7d90, + 0x0200, 0x9d20, 0x0200, 0x9d1c, 0xc19d, 0x0870, 0x0011, 0xc0ec, + 0x7d35, 0x5010, 0x5ac0, 0x5ef8, 0xc0fe, 0x56f8, 0x7d02, 0x0200, + 0x9d9b, 0x0870, 0x0011, 0x6d07, 0x0dff, 0x0511, 0x1dff, 0x05bc, + 0x4d00, 0x7d1c, 0x5228, 0x02b9, 0x4a00, 0x7c04, 0x6928, 0x7f0b, + 0x0400, 0x9daa, 0x5206, 0x7e10, 0x6a0b, 0x6928, 0x7f04, 0x0000, + 0x2504, 0x7d0c, 0x9daa, 0x0007, 0x680c, 0x680c, 0x6207, 0x6a07, + 0x6a2b, 0x6a28, 0x0007, 0x680c, 0x0007, 0x0454, 0x6928, 0x7ff3, + 0x5010, 0x52c0, 0xc10d, 0x7dcf, 0x0200, 0x9d9b, 0x0200, 0x9d97, + 0xc19d, 0x0870, 0x0011, 0xc0ec, 0x7d5e, 0x5010, 0x5ac0, 0x5bc8, + 0x5ef8, 0xc0fe, 0x56f8, 0x7d02, 0x0200, 0x9dd7, 0x6d07, 0x5df0, + 0x0dff, 0x0511, 0x1dff, 0x05bc, 0x4d00, 0x7d44, 0x0a70, 0x0211, + 0x532a, 0x5212, 0x03b9, 0x4b00, 0x7c04, 0x6a28, 0x7f3a, 0x0400, + 0x9de6, 0x008f, 0x05d8, 0x7d01, 0x008d, 0x05a0, 0x0b03, 0x0312, + 0x03bc, 0x0310, 0x4b00, 0x7d1c, 0x4b02, 0x7d20, 0x4b01, 0x7d23, + 0x0a70, 0x0211, 0x52ea, 0x5306, 0x7e24, 0x0260, 0x7d02, 0x0310, + 0x0312, 0x6b09, 0x7f1e, 0x0312, 0x6b09, 0x7f1b, 0x0312, 0x6b09, + 0x7f18, 0x2003, 0x4800, 0x7cef, 0x0a70, 0x0211, 0x5212, 0x9e27, + 0x0015, 0x0015, 0x7802, 0x5306, 0x6b0b, 0x9e26, 0x0015, 0x7802, + 0x5306, 0x6b0a, 0x9e26, 0x7802, 0x5306, 0x6b09, 0x7c02, 0x0000, + 0x9de4, 0xdb13, 0x6928, 0x7ffd, 0x008a, 0x52c0, 0x53c8, 0xc10d, + 0x7da6, 0x0200, 0x9dd7, 0x0200, 0x9dd3, 0x0870, 0x0011, 0x5010, + 0xc0ec, 0x7d5b, 0x5ac0, 0x5bc8, 0x5ef8, 0xc0fe, 0x56f8, 0x7d02, + 0x0200, 0x9e3b, 0x0b70, 0x0311, 0x6ec3, 0x6d07, 0x5df0, 0x0dff, + 0x0511, 0x1dff, 0x05bc, 0x4d00, 0x7d3d, 0x522b, 0x02b9, 0x4a00, + 0x7c04, 0x6a28, 0x7f33, 0x0400, 0x9e4d, 0x028e, 0x1a94, 0x6ac3, + 0x62c8, 0x0269, 0x7d1b, 0x1e94, 0x6ec3, 0x6ed3, 0x62c8, 0x0248, + 0x6ac8, 0x2694, 0x6ec3, 0x62c8, 0x026e, 0x7d31, 0x6a09, 0x7f1e, + 0x2501, 0x4d00, 0x7d1f, 0x028e, 0x1a98, 0x6ac3, 0x62c8, 0x6ec3, + 0x0260, 0x7df1, 0x6a28, 0x7f12, 0xdb47, 0x9e8c, 0x6ee3, 0x008f, + 0x2001, 0x00d5, 0x7d01, 0x008d, 0x05a0, 0x62c8, 0x026e, 0x7d17, + 0x6a09, 0x7f04, 0x2001, 0x7cf9, 0x0000, 0x9e4b, 0x0289, 0xdb13, + 0x018a, 0x9e9b, 0x6a28, 0x7ffa, 0x0b70, 0x0311, 0x5013, 0x52c0, + 0x53c8, 0xc10d, 0x7da8, 0x0200, 0x9e3b, 0x0200, 0x9e38, 0x6a28, + 0x7fed, 0xdb47, 0x9e9b, 0x0458, 0x0454, 0x9e8c, 0xc19d, 0x0870, + 0x0011, 0xc0ec, 0x7d54, 0x5010, 0x5ac0, 0x5bc8, 0x5ef8, 0xc0fe, + 0x56f8, 0x7d02, 0x0200, 0x9ea5, 0x0b70, 0x0311, 0x6d07, 0x5df0, + 0x0dff, 0x0511, 0x1dff, 0x05bc, 0x4d00, 0x7d36, 0x522b, 0x02b9, + 0x4a00, 0x7c04, 0x6928, 0x7f2c, 0x0400, 0x9eb6, 0x028e, 0x1a94, + 0x5202, 0x0269, 0x7d16, 0x1e94, 0x5206, 0x0248, 0x5a06, 0x2694, + 0x5206, 0x026e, 0x7d2e, 0x6a09, 0x7f1b, 0x2501, 0x4d00, 0x7d1c, + 0x028e, 0x1a98, 0x5202, 0x0260, 0x7df3, 0x6a28, 0x7f11, 0xdb47, + 0x9eee, 0x008f, 0x2001, 0x00d5, 0x7d01, 0x008d, 0x05a0, 0x5206, + 0x026e, 0x7d17, 0x6a09, 0x7f04, 0x2001, 0x7cf9, 0x0000, 0x9eb4, + 0x0289, 0xdb13, 0x018a, 0x9efd, 0x6928, 0x7ffa, 0x0b70, 0x0311, + 0x5013, 0x52c0, 0x53c8, 0xc10d, 0x7db0, 0x0200, 0x9ea5, 0x0200, + 0x9ea1, 0x6a28, 0x7fed, 0xdb47, 0x9efd, 0x0458, 0x0454, 0x9eee +}; + +/* REV 2 */ +/*! +* Following define start address of signature script +*/ +#define signature_ADDR_2 1023 +/*! +* Following define size of signature script +*/ +#define signature_SIZE_2 1 + +/*! +* Following define start address of start script +*/ +#define start_ADDR_2 0 +/*! +* Following define size of start script +*/ +#define start_SIZE_2 20 + +/*! +* Following define start address of core script +*/ +#define core_ADDR_2 80 +/*! +* Following define size of core script +*/ +#define core_SIZE_2 152 + +/*! +* Following define start address of common script +*/ +#define common_ADDR_2 232 +/*! +* Following define size of common script +*/ +#define common_SIZE_2 191 + +/*! +* Following define start address of ap_2_ap script +*/ +#define ap_2_ap_ADDR_2 423 +/*! +* Following define size of ap_2_ap script +*/ +#define ap_2_ap_SIZE_2 294 + +/*! +* Following define start address of bp_2_bp script +*/ +#define bp_2_bp_ADDR_2 717 +/*! +* Following define size of bp_2_bp script +*/ +#define bp_2_bp_SIZE_2 112 + +/*! +* Following define start address of ap_2_bp script +*/ +#define ap_2_bp_ADDR_2 829 +/*! +* Following define size of ap_2_bp script +*/ +#define ap_2_bp_SIZE_2 200 + +/*! +* Following define start address of bp_2_ap script +*/ +#define bp_2_ap_ADDR_2 1029 +/*! +* Following define size of bp_2_ap script +*/ +#define bp_2_ap_SIZE_2 223 + +/*! +* Following define start address of app_2_mcu script +*/ +#define app_2_mcu_ADDR_2 1252 +/*! +* Following define size of app_2_mcu script +*/ +#define app_2_mcu_SIZE_2 101 + +/*! +* Following define start address of mcu_2_app script +*/ +#define mcu_2_app_ADDR_2 1353 +/*! +* Following define size of mcu_2_app script +*/ +#define mcu_2_app_SIZE_2 127 + +/*! +* Following define start address of uart_2_mcu script +*/ +#define uart_2_mcu_ADDR_2 1480 +/*! +* Following define size of uart_2_mcu script +*/ +#define uart_2_mcu_SIZE_2 105 + +/*! +* Following define start address of uartsh_2_mcu script +*/ +#define uartsh_2_mcu_ADDR_2 1585 +/*! +* Following define size of uartsh_2_mcu script +*/ +#define uartsh_2_mcu_SIZE_2 98 + +/*! +* Following define start address of mcu_2_shp script +*/ +#define mcu_2_shp_ADDR_2 1683 +/*! +* Following define size of mcu_2_shp script +*/ +#define mcu_2_shp_SIZE_2 123 + +/*! +* Following define start address of shp_2_mcu script +*/ +#define shp_2_mcu_ADDR_2 1806 +/*! +* Following define size of shp_2_mcu script +*/ +#define shp_2_mcu_SIZE_2 101 + +/*! +* Following define start address of error script +*/ +#define error_ADDR_2 1907 +/*! +* Following define size of error script +*/ +#define error_SIZE_2 73 + +/*! +* Following define start address of test script +*/ +#define test_ADDR_2 1980 +/*! +* Following define size of test script +*/ +#define test_SIZE_2 63 + +/*! +* SDMA RAM scripts start addresses and sizes +*/ + +/*! +* Following define start address of app_2_mcu_patched script +*/ +#define app_2_mcu_patched_ADDR_2 6144 +/*! +* Following define size of app_2_mcu_patched script +*/ +#define app_2_mcu_patched_SIZE_2 104 + +/*! +* Following define start address of ata_2_mcu script +*/ +#define ata_2_mcu_ADDR_2 6248 +/*! +* Following define size of ata_2_mcu script +*/ +#define ata_2_mcu_SIZE_2 110 + +/*! +* Following define start address of firi_2_mcu script +*/ +#define firi_2_mcu_ADDR_2 6358 +/*! +* Following define size of firi_2_mcu script +*/ +#define firi_2_mcu_SIZE_2 114 + +/*! +* Following define start address of mcu_2_app_patched script +*/ +#define mcu_2_app_patched_ADDR_2 6472 +/*! +* Following define size of mcu_2_app_patched script +*/ +#define mcu_2_app_patched_SIZE_2 129 + +/*! +* Following define start address of mcu_2_ata script +*/ +#define mcu_2_ata_ADDR_2 6601 +/*! +* Following define size of mcu_2_ata script +*/ +#define mcu_2_ata_SIZE_2 87 +/*! +* Following define start address of mcu_2_firi script +*/ +#define mcu_2_firi_ADDR_2 6688 +/*! +* Following define size of mcu_2_firi script +*/ +#define mcu_2_firi_SIZE_2 77 +/*! +* Following define start address of mcu_2_shp_patched script +*/ +#define mcu_2_shp_patched_ADDR_2 6765 +/*! +* Following define size of mcu_2_shp_patched script +*/ +#define mcu_2_shp_patched_SIZE_2 125 + +/*! +* Following define start address of per_2_shp script +*/ +#define per_2_shp_ADDR_2 6890 +/*! +* Following define size of per_2_shp script +*/ +#define per_2_shp_SIZE_2 131 + +/*! +* Following define start address of shp_2_mcu_patched script +*/ +#define shp_2_mcu_patched_ADDR_2 7021 +/*! +* Following define size of shp_2_mcu_patched script +*/ +#define shp_2_mcu_patched_SIZE_2 104 + +/*! +* Following define start address of shp_2_per script +*/ +#define shp_2_per_ADDR_2 7125 +/*! +* Following define size of shp_2_per script +*/ +#define shp_2_per_SIZE_2 106 +/*! +* Following define start address of uart_2_mcu_patched script +*/ +#define uart_2_mcu_patched_ADDR_2 7231 +/*! +* Following define size of uart_2_mcu_patched script +*/ +#define uart_2_mcu_patched_SIZE_2 106 + +/*! +* Following define start address of uartsh_2_mcu_patched script +*/ +#define uartsh_2_mcu_patched_ADDR_2 7337 +/*! +* Following define size of uartsh_2_mcu_patched script +*/ +#define uartsh_2_mcu_patched_SIZE_2 99 + +/*! +* Following define the start address of sdma ram +*/ + +#define RAM_CODE_START_ADDR_2 6144 +/*! +* Following define the size of sdma ram +*/ +#define RAM_CODE_SIZE_2 1292 + +/*! + * Code download for i.MX system revision > 1.0 + */ +static __attribute__((aligned(4))) const short sdma_code_2[RAM_CODE_SIZE_2] = +{ + 0x0870, 0x0011, 0x5010, 0xc0ec, 0x7d61, 0x5ac0, 0x5bc8, 0x5ef8, + 0xc0fe, 0x56f8, 0x7d02, 0x0200, 0x9806, 0x6ec3, 0x6d07, 0x5df0, + 0x0dff, 0x0511, 0x1dff, 0x05bc, 0x4d00, 0x7d45, 0x0b70, 0x0311, + 0x522b, 0x5313, 0x02b9, 0x4a00, 0x7c04, 0x6a28, 0x7f3b, 0x0400, + 0x9816, 0x008f, 0x00d5, 0x7d01, 0x008d, 0x05a0, 0x0a03, 0x0212, + 0x02bc, 0x0210, 0x4a00, 0x7d1c, 0x4a02, 0x7d20, 0x4a01, 0x7d23, + 0x0b70, 0x0311, 0x53eb, 0x62c8, 0x7e25, 0x0360, 0x7d02, 0x0210, + 0x0212, 0x6a09, 0x7f1f, 0x0212, 0x6a09, 0x7f1c, 0x0212, 0x6a09, + 0x7f19, 0x2003, 0x4800, 0x7cef, 0x0b70, 0x0311, 0x5313, 0x9857, + 0x0015, 0x0015, 0x7802, 0x62c8, 0x6a0b, 0x9856, 0x0015, 0x7802, + 0x62c8, 0x6a0a, 0x9856, 0x7802, 0x62c8, 0x6a09, 0x7c03, 0x6a28, + 0x0000, 0x9814, 0xc77b, 0x6a28, 0x7ffd, 0x0870, 0x0011, 0x5010, + 0x52c0, 0x53c8, 0xc10d, 0x7da2, 0x0200, 0x9806, 0x0200, 0x9803, + 0xc19d, 0xc0ec, 0x7d69, 0x0c70, 0x0411, 0x5414, 0x5ac4, 0x028c, + 0x58da, 0x5efa, 0xc0fe, 0x56fa, 0x7d02, 0x0200, 0x9871, 0x6d07, + 0x5bca, 0x5cd2, 0x0bff, 0x0311, 0x1bff, 0x04bb, 0x0415, 0x53da, + 0x4c00, 0x7d47, 0x0a70, 0x0211, 0x552a, 0x5212, 0x008d, 0x00bb, + 0x4800, 0x7c07, 0x05b9, 0x4d00, 0x7c13, 0x6928, 0x7f2d, 0x0400, + 0x9882, 0x008f, 0x0015, 0x04d8, 0x7d01, 0x008c, 0x04a0, 0x0015, + 0x7802, 0x55c6, 0x6d0b, 0x7e29, 0x6d28, 0x7f1e, 0x0000, 0x9880, + 0x1e20, 0x5506, 0x2620, 0x008d, 0x0560, 0x7c08, 0x065f, 0x55c6, + 0x063f, 0x7e1b, 0x6d0a, 0x7f10, 0x4c00, 0x7d1b, 0x04d8, 0x7d02, + 0x008c, 0x0020, 0x04a0, 0x0015, 0x7802, 0x55c6, 0x6d0b, 0x7e0d, + 0x6d28, 0x7f02, 0x0000, 0x98c9, 0x0007, 0x680c, 0x6d0c, 0x6507, + 0x6d07, 0x6d2b, 0x6d28, 0x0007, 0x680c, 0x0007, 0x54d2, 0x0454, + 0x98cc, 0x6928, 0x7ff1, 0x54d2, 0x008a, 0x52c0, 0x53c8, 0xc10d, + 0x0288, 0x7d9f, 0x0200, 0x9871, 0x0200, 0x9869, 0x1e10, 0x0870, + 0x0011, 0x5010, 0xc0ec, 0x7d39, 0x5ac0, 0x5bc8, 0x5ef8, 0xc0fe, + 0x56f8, 0x7d02, 0x0200, 0x98dd, 0x6d07, 0x5df0, 0x0dff, 0x0511, + 0x1dff, 0x05bc, 0x4d00, 0x7d17, 0x6ec3, 0x62c8, 0x7e28, 0x0264, + 0x7d08, 0x0b70, 0x0311, 0x522b, 0x02b9, 0x4a00, 0x7c18, 0x0400, + 0x98ec, 0x0212, 0x3aff, 0x008a, 0x05d8, 0x7d01, 0x008d, 0x0a10, + 0x6ed3, 0x6ac8, 0xd927, 0x6a28, 0x7f17, 0x0b70, 0x0311, 0x5013, + 0xd93f, 0x52c0, 0x53c8, 0xc10d, 0x7dd0, 0x0200, 0x98dd, 0x008f, + 0x00d5, 0x7d01, 0x008d, 0xd927, 0x98ea, 0x0200, 0x98da, 0x0007, + 0x68cc, 0x6a28, 0x7f01, 0x9925, 0x0007, 0x6a0c, 0x6a0c, 0x6207, + 0x6a07, 0x6a2b, 0x6a28, 0x0007, 0x680c, 0x0454, 0x9903, 0x05a0, + 0x1e08, 0x6ec3, 0x0388, 0x3b03, 0x0015, 0x0015, 0x7802, 0x62c8, + 0x6a0b, 0x7ee5, 0x6a28, 0x7fe8, 0x0000, 0x6ec1, 0x008b, 0x7802, + 0x62c8, 0x6a09, 0x7edc, 0x6a28, 0x7fdf, 0x2608, 0x0006, 0x55f0, + 0x6207, 0x02a5, 0x0dff, 0x0511, 0x1dff, 0x04b5, 0x049a, 0x0006, + 0x0870, 0x0011, 0x5010, 0xc0ec, 0x7d7a, 0x5ac0, 0x5bc8, 0x5ef8, + 0xc0fe, 0x56f8, 0x7d02, 0x0200, 0x994e, 0x6d03, 0x6ed3, 0x0dff, + 0x0511, 0x1dff, 0x05bc, 0x5df8, 0x4d00, 0x7d5e, 0x0b70, 0x0311, + 0x522b, 0x5313, 0x02b9, 0x4a00, 0x7c04, 0x62ff, 0x7e3f, 0x0400, + 0x995e, 0x008f, 0x00d5, 0x7d01, 0x008d, 0x05a0, 0x5ddb, 0x0d03, + 0x0512, 0x05bc, 0x0510, 0x5dd3, 0x4d00, 0x7d27, 0x4d02, 0x7d20, + 0x4d01, 0x7d1a, 0x0b70, 0x0311, 0x53eb, 0x0360, 0x7d05, 0x6509, + 0x7e25, 0x620a, 0x7e23, 0x9988, 0x620a, 0x7e20, 0x6509, 0x7e1e, + 0x0512, 0x0512, 0x02ad, 0x6ac8, 0x7f19, 0x2003, 0x4800, 0x7ced, + 0x0b70, 0x0311, 0x5313, 0x99a3, 0x7802, 0x6209, 0x6ac8, 0x99a2, + 0x0015, 0x7802, 0x620a, 0x6ac8, 0x99a2, 0x0015, 0x0015, 0x7802, + 0x620b, 0x6ac8, 0x7c03, 0x0000, 0x55db, 0x995c, 0x0007, 0x68cc, + 0x680c, 0x55d3, 0x4d00, 0x7d03, 0x4d02, 0x7d02, 0x99b1, 0x0017, + 0x0017, 0x55db, 0x009d, 0x55fb, 0x05a0, 0x08ff, 0x0011, 0x18ff, + 0x0010, 0x04b8, 0x04ad, 0x0454, 0x62ff, 0x7ee8, 0x0870, 0x0011, + 0x5010, 0x52c0, 0x53c8, 0xc10d, 0x7d89, 0x0200, 0x994e, 0x0200, + 0x994b, 0xc19d, 0xc0ec, 0x7d52, 0x0c70, 0x0411, 0x5414, 0x5ac4, + 0x028c, 0x58da, 0x5efa, 0xc0fe, 0x56fa, 0x7d02, 0x0200, 0x99d2, + 0x6d03, 0x5bca, 0x5cd2, 0x0bff, 0x0311, 0x1bff, 0x04bb, 0x0415, + 0x53da, 0x0a70, 0x0211, 0x4c00, 0x7d28, 0x552a, 0x05bb, 0x4d00, + 0x7c02, 0x0400, 0x99e5, 0x4c01, 0x7d0f, 0x008f, 0x0015, 0x04d8, + 0x7d01, 0x008c, 0x0020, 0x04a0, 0x0015, 0x7802, 0x650b, 0x5d06, + 0x0000, 0x7e0c, 0x7f0d, 0x99e3, 0x650a, 0x7e08, 0x008d, 0x0011, + 0x0010, 0x05a8, 0x065f, 0x5d06, 0x063f, 0x7f02, 0x0007, 0x680c, + 0x0007, 0x5012, 0x54d0, 0x0454, 0x9a0f, 0x5012, 0x54d0, 0x0473, + 0x7c06, 0x552a, 0x05b9, 0x4d00, 0x7c02, 0x0400, 0x9a11, 0x52c0, + 0x53c8, 0xc10d, 0x0288, 0x7db6, 0x0200, 0x99d2, 0x0200, 0x99ca, + 0x0870, 0x0011, 0x5010, 0xc0ec, 0x7d46, 0x5ac0, 0x5bc8, 0x5ef8, + 0xc0fe, 0x56f8, 0x7d02, 0x0200, 0x9a26, 0x0b70, 0x0311, 0x6ed3, + 0x6d03, 0x0dff, 0x0511, 0x1dff, 0x05bc, 0x4d00, 0x7d2b, 0x522b, + 0x02b9, 0x4a00, 0x7c04, 0x62c8, 0x7e1f, 0x0400, 0x9a37, 0x008f, + 0x00d5, 0x7d01, 0x008d, 0x05a0, 0x0060, 0x7c05, 0x6edd, 0x6209, + 0x7e16, 0x6ac8, 0x7f11, 0x0015, 0x0060, 0x7c05, 0x6ede, 0x620a, + 0x7e0e, 0x6ac8, 0x7f09, 0x6edf, 0x0015, 0x7802, 0x620b, 0x6ac8, + 0x0000, 0x7e05, 0x7f01, 0x9a35, 0x0007, 0x68cc, 0x9a61, 0x0007, + 0x6a0c, 0x0454, 0x62c8, 0x7ef8, 0x5013, 0x52c0, 0x53c8, 0xc10d, + 0x7dbd, 0x0200, 0x9a26, 0x0200, 0x9a23, 0xc19d, 0x0870, 0x0011, + 0xc0ec, 0x7d76, 0x5010, 0x5ac0, 0x5bc8, 0x5ef8, 0xc0fe, 0x56f8, + 0x7d02, 0x0200, 0x9a74, 0x6d03, 0x0d03, 0x0512, 0x05bc, 0x0510, + 0x5dd0, 0x0dff, 0x0511, 0x1dff, 0x05bc, 0x5df8, 0x4d00, 0x7d57, + 0x0a70, 0x0211, 0x532a, 0x5212, 0x03b9, 0x4b00, 0x7c02, 0x0400, + 0x9a88, 0x008f, 0x05d8, 0x7d01, 0x008d, 0x05a0, 0x5dda, 0x55d2, + 0x4d00, 0x7d27, 0x4d02, 0x7d20, 0x4d01, 0x7d1a, 0x0a70, 0x0211, + 0x52ea, 0x0260, 0x7d05, 0x6509, 0x7e25, 0x630a, 0x7e23, 0x9aac, + 0x630a, 0x7e20, 0x6509, 0x7e1e, 0x0512, 0x0512, 0x03ad, 0x5b06, + 0x7f19, 0x2003, 0x4800, 0x7ced, 0x0a70, 0x0211, 0x5212, 0x9ac7, + 0x7802, 0x6309, 0x5b06, 0x9ac6, 0x0015, 0x7802, 0x630a, 0x5b06, + 0x9ac6, 0x0015, 0x0015, 0x7802, 0x630b, 0x5b06, 0x7c03, 0x55da, + 0x0000, 0x9a86, 0x0007, 0x680c, 0x55d2, 0x4d00, 0x7d03, 0x4d02, + 0x7d02, 0x9ad4, 0x0017, 0x0017, 0x55da, 0x009d, 0x55fa, 0x05a0, + 0x08ff, 0x0011, 0x18ff, 0x0010, 0x04b8, 0x04ad, 0x0454, 0x0870, + 0x0011, 0x5010, 0x52c0, 0x53c8, 0xc10d, 0x7d8e, 0x0200, 0x9a74, + 0x0200, 0x9a70, 0xc19d, 0x0870, 0x0011, 0xc0ec, 0x7d7c, 0x5010, + 0x5ac0, 0x5bc8, 0x5ef8, 0xc0fe, 0x56f8, 0x7d02, 0x0200, 0x9af1, + 0x6dc5, 0x0d03, 0x0512, 0x05bc, 0x0510, 0x5dd0, 0x0dff, 0x0511, + 0x1dff, 0x05bc, 0x5df8, 0x4d00, 0x7d5d, 0x0a70, 0x0211, 0x532a, + 0x5212, 0x03b9, 0x4b00, 0x7c02, 0x0400, 0x9b05, 0x008f, 0x05d8, + 0x7d01, 0x008d, 0x05a0, 0x5dda, 0x55d2, 0x4d00, 0x7d2c, 0x4d02, + 0x7d24, 0x4d01, 0x7d1e, 0x59e2, 0x0a70, 0x0211, 0x52ea, 0x61c8, + 0x7e2c, 0x63c8, 0x7e2a, 0x65c8, 0x7e28, 0x0260, 0x7d03, 0x0112, + 0x0112, 0x9b2c, 0x0512, 0x0512, 0x0311, 0x03a9, 0x03ad, 0x5b06, + 0x7f1c, 0x2003, 0x4800, 0x7ceb, 0x0a70, 0x0211, 0x5212, 0x51e2, + 0x9b4a, 0x7802, 0x63c8, 0x5b06, 0x9b49, 0x6dce, 0x0015, 0x7802, + 0x63c8, 0x5b06, 0x9b49, 0x6dcf, 0x0015, 0x0015, 0x7802, 0x63c8, + 0x5b06, 0x7c03, 0x55da, 0x0000, 0x9b03, 0x0007, 0x68ff, 0x55d2, + 0x4d00, 0x7d03, 0x4d02, 0x7d02, 0x9b57, 0x0017, 0x0017, 0x55da, + 0x009d, 0x55fa, 0x05a0, 0x08ff, 0x0011, 0x18ff, 0x0010, 0x04b8, + 0x04ad, 0x0454, 0x0870, 0x0011, 0x5010, 0x52c0, 0x53c8, 0xc10d, + 0x7d88, 0x0200, 0x9af1, 0x0200, 0x9aed, 0xc19d, 0x0870, 0x0011, + 0xc0ec, 0x7d61, 0x5010, 0x5ac0, 0x5bc8, 0x5ef8, 0xc0fe, 0x56f8, + 0x7d02, 0x0200, 0x9b74, 0x6d07, 0x5df0, 0x0dff, 0x0511, 0x1dff, + 0x05bc, 0x4d00, 0x7d45, 0x0a70, 0x0211, 0x532a, 0x5212, 0x03b9, + 0x4b00, 0x7c04, 0x6a28, 0x7f3b, 0x0400, 0x9b83, 0x008f, 0x05d8, + 0x7d01, 0x008d, 0x05a0, 0x0b03, 0x0312, 0x03bc, 0x0310, 0x4b00, + 0x7d1c, 0x4b02, 0x7d20, 0x4b01, 0x7d23, 0x0a70, 0x0211, 0x52ea, + 0x5306, 0x7e25, 0x0260, 0x7d02, 0x0310, 0x0312, 0x6b09, 0x7f1f, + 0x0312, 0x6b09, 0x7f1c, 0x0312, 0x6b09, 0x7f19, 0x2003, 0x4800, + 0x7cef, 0x0a70, 0x0211, 0x5212, 0x9bc4, 0x0015, 0x0015, 0x7802, + 0x5306, 0x6b0b, 0x9bc3, 0x0015, 0x7802, 0x5306, 0x6b0a, 0x9bc3, + 0x7802, 0x5306, 0x6b09, 0x7c03, 0x6b28, 0x0000, 0x9b81, 0xc77b, + 0x6928, 0x7ffd, 0x0870, 0x0011, 0x5010, 0x52c0, 0x53c8, 0xc10d, + 0x7da3, 0x0200, 0x9b74, 0x0200, 0x9b70, 0xc19d, 0x0870, 0x0011, + 0xc0ec, 0x7d63, 0x5010, 0x5ac0, 0x5bc8, 0x5ef8, 0xc0fe, 0x56f8, + 0x7d02, 0x0200, 0x9bdc, 0x6dd7, 0x5df0, 0x0dff, 0x0511, 0x1dff, + 0x05bc, 0x4d00, 0x7d47, 0x0a70, 0x0211, 0x532a, 0x5212, 0x03b9, + 0x4b00, 0x7c04, 0x63c8, 0x7e3d, 0x0400, 0x9beb, 0x008f, 0x05d8, + 0x7d01, 0x008d, 0x05a0, 0x0b03, 0x0312, 0x03bc, 0x0310, 0x4b00, + 0x7d28, 0x4b02, 0x7d20, 0x4b01, 0x7d19, 0x6ddd, 0x0a70, 0x0211, + 0x52ea, 0x5306, 0x7e26, 0x0260, 0x7d02, 0x0310, 0x0312, 0x6bc8, + 0x7f20, 0x0312, 0x6bc8, 0x7f1d, 0x0312, 0x6bc8, 0x7f1a, 0x2003, + 0x4800, 0x7cef, 0x0a70, 0x0211, 0x5212, 0x9c2f, 0x6ddd, 0x7802, + 0x5306, 0x6bc8, 0x9c2e, 0x6dde, 0x0015, 0x7802, 0x5306, 0x6bc8, + 0x9c2e, 0x0015, 0x0015, 0x7802, 0x5306, 0x6bc8, 0x7c02, 0x0000, + 0x9be9, 0xc777, 0x63c8, 0x7efd, 0x0870, 0x0011, 0x5010, 0x52c0, + 0x53c8, 0xc10d, 0x7da1, 0x0200, 0x9bdc, 0x0200, 0x9bd8, 0x0870, + 0x0011, 0x5010, 0xc0ec, 0x7d5c, 0x5ac0, 0x5bc8, 0x5ef8, 0xc0fe, + 0x56f8, 0x7d02, 0x0200, 0x9c45, 0x0b70, 0x0311, 0x6ec3, 0x6d07, + 0x5df0, 0x0dff, 0x0511, 0x1dff, 0x05bc, 0x4d00, 0x7d3e, 0x522b, + 0x02b9, 0x4a00, 0x7c04, 0x6a28, 0x7f34, 0x0400, 0x9c57, 0x028e, + 0x1a94, 0x6ac3, 0x62c8, 0x0269, 0x7d1b, 0x1e94, 0x6ec3, 0x6ed3, + 0x62c8, 0x0248, 0x6ac8, 0x2694, 0x6ec3, 0x62c8, 0x026e, 0x7d32, + 0x6a09, 0x7f1f, 0x2501, 0x4d00, 0x7d20, 0x028e, 0x1a98, 0x6ac3, + 0x62c8, 0x6ec3, 0x0260, 0x7df1, 0x6a28, 0x7f13, 0xc7af, 0x9c97, + 0x6ee3, 0x008f, 0x2001, 0x00d5, 0x7d01, 0x008d, 0x05a0, 0x62c8, + 0x026e, 0x7d18, 0x6a09, 0x7f05, 0x2001, 0x7cf9, 0x6a28, 0x0000, + 0x9c55, 0x0289, 0xc77b, 0x018a, 0x9ca6, 0x6a28, 0x7ffa, 0x0b70, + 0x0311, 0x5013, 0x52c0, 0x53c8, 0xc10d, 0x7da7, 0x0200, 0x9c45, + 0x0200, 0x9c42, 0x6a28, 0x7fed, 0xc7af, 0x9ca6, 0x0458, 0x0454, + 0x9c97, 0xc19d, 0x0870, 0x0011, 0xc0ec, 0x7d55, 0x5010, 0x5ac0, + 0x5bc8, 0x5ef8, 0xc0fe, 0x56f8, 0x7d02, 0x0200, 0x9cb0, 0x0b70, + 0x0311, 0x6d07, 0x5df0, 0x0dff, 0x0511, 0x1dff, 0x05bc, 0x4d00, + 0x7d37, 0x522b, 0x02b9, 0x4a00, 0x7c04, 0x6928, 0x7f2d, 0x0400, + 0x9cc1, 0x028e, 0x1a94, 0x5202, 0x0269, 0x7d16, 0x1e94, 0x5206, + 0x0248, 0x5a06, 0x2694, 0x5206, 0x026e, 0x7d2f, 0x6a09, 0x7f1c, + 0x2501, 0x4d00, 0x7d1d, 0x028e, 0x1a98, 0x5202, 0x0260, 0x7df3, + 0x6a28, 0x7f12, 0xc7af, 0x9cfa, 0x008f, 0x2001, 0x00d5, 0x7d01, + 0x008d, 0x05a0, 0x5206, 0x026e, 0x7d18, 0x6a09, 0x7f05, 0x2001, + 0x7cf9, 0x6a28, 0x0000, 0x9cbf, 0x0289, 0xc77b, 0x018a, 0x9d09, + 0x6928, 0x7ffa, 0x0b70, 0x0311, 0x5013, 0x52c0, 0x53c8, 0xc10d, + 0x7daf, 0x0200, 0x9cb0, 0x0200, 0x9cac, 0x6a28, 0x7fed, 0xc7af, + 0x9d09, 0x0458, 0x0454, 0x9cfa +}; + +/*! + * Structure containing script addresses. + */ +struct sdma_script_start_addrs +{ + /* SDMA code script info - in halfword SDMA memory space */ + unsigned short ap_2_ap_addr; + unsigned short ap_2_bp_addr; + unsigned short bp_2_ap_addr; + unsigned short loopback_on_dsp_side_addr; + unsigned short mcu_interrupt_only_addr; + unsigned short firi_2_per_addr; + unsigned short firi_2_mcu_addr; + unsigned short per_2_firi_addr; + unsigned short mcu_2_firi_addr; + unsigned short uart_2_per_addr; + unsigned short uart_2_mcu_addr; + unsigned short per_2_app_addr; + unsigned short mcu_2_app_addr; + unsigned short uartsh_2_per_addr; + unsigned short uartsh_2_mcu_addr; + unsigned short per_2_shp_addr; + unsigned short mcu_2_shp_addr; + unsigned short ata_2_mcu_addr; + unsigned short mcu_2_ata_addr; + unsigned short app_2_per_addr; + unsigned short app_2_mcu_addr; + unsigned short shp_2_per_addr; + unsigned short shp_2_mcu_addr; + unsigned short mshc_2_mcu_addr; + unsigned short mcu_2_mshc_addr; + unsigned short dptc_dvfs_addr; + /* SDMA script code info */ + /* address where ram code starts (in SDMA halfword space) */ + unsigned short ram_code_start_addr; + /* size of the ram code (in halfwords) */ + unsigned short ram_code_size; + /* RAM image address on AP */ + unsigned long mcu_start_addr; +}; +#endif /*__SDMA_SCRIPT_CODE_H__ */ diff --git a/firmware/target/arm/imx31/sdma_struct.h b/firmware/target/arm/imx31/sdma_struct.h new file mode 100644 index 0000000000..22aabcbdb4 --- /dev/null +++ b/firmware/target/arm/imx31/sdma_struct.h @@ -0,0 +1,426 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2009 by Michael Sevakis + * + * 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. + * + ****************************************************************************/ + +/* Largely taken from sdmaStruct.h from the Linux BSP provided by Freescale. + * Copyright 2007-2008 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* Other information gleaned from RE-ing the BSP and SDMA code */ + +#ifndef SDMA_STRUCT_H +#define SDMA_STRUCT_H + +/** + * Number of channels + */ +#define CH_NUM 32 + +/** + * Ownership + */ +#define CH_OWNSHP_EVT (1 << 0) +#define CH_OWNSHP_MCU (1 << 1) +#if 0 +#define CH_OWNSHP_DSP (1 << 2) +#endif + +/** + * Channel contexts management + */ + +/* Contexts for each channel begin here within SDMA core */ +#define CHANNEL_CONTEXT_BASE_ADDR 0x800 +/* Compute SDMA address where context for a channel is stored */ +#define CHANNEL_CONTEXT_ADDR(channel) \ + (CHANNEL_CONTEXT_BASE_ADDR+sizeof(struct context_data)/4*(channel)) + +/** + * Error bit set in the CCB status field by the SDMA, + * in setbd routine, in case of a transfer error + */ +#define DATA_ERROR (1 << 28) /* BD_RROR set on last buffer descriptor */ +#define DATA_FAULT (1 << 29) /* A source or destination fault occured */ + +/** + * Buffer descriptor status values. + */ +#define BD_DONE 0x01 /* Set by host, cleared when SDMA has finished with + this BD */ +#define BD_WRAP 0x02 /* If set in last descriptor, allows circular buffer + * structure. curr_bd_ptr will be reset to base_bd_ptr + */ +#define BD_CONT 0x04 /* If set, more descriptors follow (multi-buffer) */ +#define BD_INTR 0x08 /* Interrupt when transfer complete */ +#define BD_RROR 0x10 /* Error during BD processing (set by SDMA) */ +#define BD_LAST 0x20 /* Set by SDMA ap_2_bp and bp_2_ap scripts. + TODO: determine function */ +#define BD_EXTD 0x80 /* Use extended buffer address (indicates BD is 12 + bytes instead of 8) */ + +/** + * Buffer descriptor channel 0 commands. + */ +#define C0_SETCTX 0x07 /* Write context for a channel (ch# = BD command [7:3]) */ +#define C0_GETCTX 0x03 /* Read context for a channel (ch# = BD command [7:3]) */ +#define C0_SETDM 0x01 /* Write 32-bit words to SDMA memory */ +#define C0_GETDM 0x02 /* Read 32-bit words from SDMA memory */ +#define C0_SETPM 0x04 /* Write 16-bit halfwords to SDMA memory */ +#define C0_GETPM 0x08 /* Read 16-bit halfwords from SDMA memory */ + +/* Treated the same as those above */ +#define C0_ADDR 0x01 +#define C0_LOAD 0x02 +#define C0_DUMP 0x03 + +/** + * Transfer sizes, encoded in the BD command field (when not a C0_ command). + */ +#define TRANSFER_32BIT 0x00 +#define TRANSFER_8BIT 0x01 +#define TRANSFER_16BIT 0x02 +#define TRANSFER_24BIT 0x03 + +/** + * Change endianness indicator in the BD command field + */ +#define CHANGE_ENDIANNESS 0x80 + +/** + * Size in bytes of struct buffer_descriptor + */ +#define SDMA_BD_SIZE 8 +#define SDMA_EXTENDED_BD_SIZE 12 +#define BD_NUMBER 4 + +/** + * Channel interrupt policy + */ +#define DEFAULT_POLL 0 +#define CALLBACK_ISR 1 +/** + * Channel status + */ +#define UNINITIALIZED 0 +#define INITIALIZED 1 + +/** + * IoCtl particular values + */ +#define SET_BIT_ALL 0xFFFFFFFF +#define BD_NUM_OFFSET 16 +#define BD_NUM_MASK 0xFFFF0000 + +/** + * Maximum values for IoCtl calls, used in high or middle level calls + */ +#define MAX_BD_NUM 256 +#define MAX_BD_SIZE 65536 +#define MAX_BLOCKING 2 +#define MAX_SYNCH 2 +#define MAX_OWNERSHIP 8 +#define MAX_CH_PRIORITY 8 +#define MAX_TRUST 2 +#define MAX_WML 256 + + +/** + * Default values for channel descriptor - nobody owns the channel + */ +#define CD_DEFAULT_OWNERSHIP 7 + +#if 0 /* IPC not used */ +/** + * Data Node descriptor status values. + */ +#define DND_END_OF_FRAME 0x80 +#define DND_END_OF_XFER 0x40 +#define DND_DONE 0x20 +#define DND_UNUSED 0x01 + +/** + * IPCV2 descriptor status values. + */ +#define BD_IPCV2_END_OF_FRAME 0x40 + +#define IPCV2_MAX_NODES 50 + +/** + * User Type Section + */ + +/** + * Command/Mode/Count of buffer descriptors + */ +struct mode_count_ipcv2 +{ + unsigned long count : 16; /* size of the buffer pointed by this BD */ + unsigned long reserved : 8; /* reserved */ + unsigned long status : 8; /* L, E, D bits stored here */ +}; + +/** + * Data Node descriptor - IPCv2 + * (differentiated between evolutions of SDMA) + */ +struct data_node_descriptor +{ + struct mode_count_ipcv2 mode; /* command, status and count */ + void* buffer_addr; /* address of the buffer described */ +}; + +struct mode_count_ipcv1_v2 +{ + unsigned long count : 16; /* size of the buffer pointed by this BD */ + unsigned long status : 8; /* E,R,I,C,W,D status bits stored here */ + unsigned long reserved : 7; + unsigned long endianness : 1; +}; + +/** + * Buffer descriptor + * (differentiated between evolutions of SDMA) + */ +struct buffer_descriptor_ipcv1_v2 +{ + struct mode_count_ipcv1_v2 mode; /* command, status and count */ + void *buffer_addr; /* address of the buffer described */ + void *ext_buffer_addr; /* extended buffer address */ +}; +#endif /* No IPC */ + +/** + * Mode/Count of data node descriptors - IPCv2 + */ +struct mode_count +{ + unsigned long count : 16; /* size of the buffer pointed by this BD */ + unsigned long status : 8; /* E,R,I,C,W,D status bits stored here: + * SDMA r/w */ + unsigned long command : 8; /* channel 0 command or transfer size */ +}; + + +/** + * Buffer descriptor - describes each buffer in a DMA transfer. + * (differentiated between evolutions of SDMA) + */ +/* (mode.status & BD_EXTD) == 0 (8 bytes) */ +struct buffer_descriptor +{ + volatile struct mode_count mode; /* command, status and count: SDMA r/w */ + void *buf_addr; /* address of the buffer described: SDMA r */ +}; + +/* (mode.status & BD_EXTD) != 0 (12 bytes) */ +struct buffer_descriptor_extd +{ + struct buffer_descriptor bd; + void *buf_addr_ext; /* extended buffer address described (r6): SDMA r */ +}; + +#if 0 /* A different one is defined for Rockbox use - this has too much. + * See below. */ +struct channel_control_block; +struct channel_descriptor; +/** + * Channel Descriptor + */ +struct channel_descriptor +{ + unsigned char channel_number; /* stores the channel number */ + unsigned char buffer_desc_count; /* number of BD's allocated + for this channel */ + unsigned short buffer_per_desc_size; /* size (in bytes) of buffer + descriptors' data buffers */ + unsigned long blocking : 3; /* polling/ callback method + selection */ + unsigned long callback_synch : 1; /* (iapi) blocking / non blocking + feature selection */ + unsigned long ownership : 3; /* ownership of the channel + (host+dedicated+event) */ + unsigned long priority : 3; /* reflects the SDMA channel + priority register */ + unsigned long trust : 1; /* trusted buffers or kernel + allocated */ + unsigned long use_data_size : 1; /* (iapi) indicates if the dataSize + field is meaningfull */ + unsigned long data_size : 2; /* (iapi->BD) data transfer + size - 8,16,24 or 32 bits*/ + unsigned long force_close : 1; /* If TRUE, close channel even + with BD owned by SDMA*/ + unsigned long script_id : 7; /* number of the script */ + unsigned long watermark_level : 10; /* (greg) Watermark level for the + peripheral access */ + unsigned long event_mask1; /* (greg) First Event mask */ + unsigned long event_mask2; /* (greg) Second Event mask */ + unsigned long shp_addr; /* (greg) Address of the peripheral + or its fifo when needed */ + void (* callback)(struct channel_descriptor *); /* pointer to the + callback function (or NULL) */ + struct channel_control_block *ccb_ptr; /* pointer to the channel control + block associated to this + channel */ +}; +#endif + +/* Only what we need, members sorted by size, no code-bloating bitfields */ +struct channel_descriptor +{ + unsigned int bd_count; /* number of BD's allocated + for this channel */ + struct channel_control_block *ccb_ptr; /* pointer to the channel control + block associated to this + channel */ + void (* callback)(void); /* pointer to the + callback function (or NULL) */ + unsigned long shp_addr; /* (greg) Address of the peripheral + or its fifo when needed */ + unsigned short wml; /* (greg) Watermark level for the + peripheral access */ + unsigned char per_type; /* Peripheral type */ + unsigned char tran_type; /* Transfer type */ + unsigned char event_id1; /* DMA request ID */ + unsigned char event_id2; /* DMA request ID 2 */ + unsigned char is_setup; /* Channel setup has been done */ +}; + +/** + * Channel Status + */ +struct channel_status +{ + unsigned long unused : 28; + unsigned long error : 1; /* Last BD triggered an error: + SDMA r/w */ + unsigned long opened_init : 1; /* Channel is initialized: + SDMA r/w */ + unsigned long state_direction : 1; /* SDMA is reading/writing (as seen + from channel owner core) */ + unsigned long execute : 1; /* Channel is being processed + (started) or not */ +}; + +/** + * Channel control Block + * SDMA ROM code expects these are 16-bytes each in an array + * (MC0PTR + 16*CCR) + */ +struct channel_control_block +{ + /* current buffer descriptor processed: SDMA r/w */ + struct buffer_descriptor * volatile curr_bd_ptr; + /* first element of buffer descriptor array: SDMA r */ + struct buffer_descriptor *base_bd_ptr; + /* pointer to the channel descriptor: SDMA ignored */ + struct channel_descriptor *channel_desc; + /* open/close ; started/stopped ; read/write: SDMA r/w */ + volatile struct channel_status status; +}; + +/** + * Channel context structure. + */ + +/* Channel state bits on SDMA core side */ +struct state_registers +{ + /* Offset 0 */ + unsigned long pc : 14; /* program counter */ + unsigned long unused0 : 1; + unsigned long t : 1; /* test bit: status of arithmetic & test + instruction */ + unsigned long rpc : 14; /* return program counter */ + unsigned long unused1 : 1; + unsigned long sf : 1; /* source fault while loading data */ + /* Offset 1 */ + unsigned long spc : 14; /* loop start program counter */ + unsigned long unused2 : 1; + unsigned long df : 1; /* destination falut while storing data */ + unsigned long epc : 14; /* loop end program counter */ + unsigned long lm : 2; /* loop mode */ +}; + +/* Context data saved for every channel on the SDMA core. This is 32 words + * long which is specified in the SDMA initialization on the AP side. The + * SDMA scripts utilize the scratch space. */ +struct context_data +{ + struct state_registers channel_state; /* channel state bits */ + union + { + unsigned long r[8]; /* general registers (r0-r7) */ + struct /* script usage of said when + setting contexts */ + { + unsigned long event_mask2; /* 08h */ + unsigned long event_mask1; /* 0Ch */ + unsigned long r2; /* 10h */ + unsigned long r3; /* 14h */ + unsigned long r4; /* 18h */ + unsigned long r5; /* 1Ch */ + unsigned long shp_addr; /* 20h */ + unsigned long wml; /* 24h */ + }; + }; + unsigned long mda; /* burst dma destination address register */ + unsigned long msa; /* burst dma source address register */ + unsigned long ms; /* burst dma status register */ + unsigned long md; /* burst dma data register */ + unsigned long pda; /* peripheral dma destination address register */ + unsigned long psa; /* peripheral dma source address register */ + unsigned long ps; /* peripheral dma status register */ + unsigned long pd; /* peripheral dma data register */ + unsigned long ca; /* CRC polynomial register */ + unsigned long cs; /* CRC accumulator register */ + unsigned long dda; /* dedicated core destination address register */ + unsigned long dsa; /* dedicated core source address register */ + unsigned long ds; /* dedicated core status register */ + unsigned long dd; /* dedicated core data register */ + unsigned long scratch[8]; /* channel context scratch RAM */ +}; + +/** + * This structure holds the necessary data for the assignment in the + * dynamic channel-script association + */ +struct script_data +{ + unsigned long load_address; /* start address of the script */ + unsigned long wml; /* parameters for the channel descriptor */ + unsigned long shp_addr; /* shared peripheral base address */ + unsigned long event_mask1; /* first event mask */ + unsigned long event_mask2; /* second event mask */ +}; + +/** + * This structure holds the the useful bits of the CONFIG register + */ +struct configs_data +{ + unsigned long dspdma : 1; /* indicates if the DSPDMA is used */ + unsigned long rtdobs : 1; /* indicates if Real-Time Debug pins are + enabled */ + unsigned long acr : 1; /* indicates if AHB freq /core freq = 2 or 1 */ + unsigned long csm : 2; /* indicates which context switch mode is + selected */ +}; + +#endif /* SDMA_STRUCT_H */ -- cgit v1.2.3