diff options
author | Daniel Thompson <daniel.thompson@linaro.org> | 2017-07-31 17:23:07 +0100 |
---|---|---|
committer | Daniel Thompson <daniel.thompson@linaro.org> | 2017-07-31 17:23:07 +0100 |
commit | e5b9b8c8b78096e961f4a45b9d1418e4641f24f9 (patch) | |
tree | a88f532f386376fca6a376e2c362173f971dc144 /board/rda/rda8810h | |
parent | 415d386877df49eb051b85ef74fa59a16dc17c7d (diff) |
Orangepi i96 support (mega patch)rda/v2012.04.01-r0
This is https://github.com/orangepi-xunlong/OrangePiRDA_u-boot
5ee06c1afb7c ("add new patch a patch") as a single patch against
a guestimated upstream version.
This is merely a reference tree for later comparisons.
Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
NOT-Reviewed-by: Daniel Thompson <daniel.thompson@linaro.org>
Diffstat (limited to 'board/rda/rda8810h')
-rw-r--r-- | board/rda/rda8810h/Makefile | 82 | ||||
-rw-r--r-- | board/rda/rda8810h/clock.c | 1329 | ||||
-rw-r--r-- | board/rda/rda8810h/clock_config.c | 149 | ||||
-rw-r--r-- | board/rda/rda8810h/clock_config.h | 132 | ||||
-rw-r--r-- | board/rda/rda8810h/config.mk | 15 | ||||
-rw-r--r-- | board/rda/rda8810h/ddr3.c | 533 | ||||
-rw-r--r-- | board/rda/rda8810h/ddr3.h | 50 | ||||
-rw-r--r-- | board/rda/rda8810h/ddr3_init.h | 101 | ||||
-rw-r--r-- | board/rda/rda8810h/debug.h | 9 | ||||
-rw-r--r-- | board/rda/rda8810h/hal_config.c | 1451 | ||||
-rw-r--r-- | board/rda/rda8810h/u-boot-spl.lds | 35 |
11 files changed, 3886 insertions, 0 deletions
diff --git a/board/rda/rda8810h/Makefile b/board/rda/rda8810h/Makefile new file mode 100644 index 0000000000..7412489b30 --- /dev/null +++ b/board/rda/rda8810h/Makefile @@ -0,0 +1,82 @@ +# +# (C) Copyright 2000, 2001, 2002 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> +# +# See file CREDITS for list of people who contributed to this +# project. +# +# 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 program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)lib$(BOARD).o + +ifdef CONFIG_SPL_BUILD +COBJS-y += clock_config.o clock.o ddr3.o +else +COBJS-$(CONFIG_MACH_RDA8810H) += hal_config.o +endif + +RDA_TARGET_DEF_FILE := $(ANDROID_BUILD_TOP)/$(RDA_TARGET_DEVICE_DIR)/target.def +RDA_GET_MAKEFILE_VAR_FUNC = $(strip $(shell sed -n 's/^[ ]*$(1)[ ]*[?:]\?=\([^\#]\+\)\#*.*$$/\1/p' $(2))) + +NUMBER_OF_SIM := $(call RDA_GET_MAKEFILE_VAR_FUNC,NUMBER_OF_SIM,$(RDA_TARGET_DEF_FILE)) +ifeq ($(NUMBER_OF_SIM),) +$(error Failed to get NUMBER_OF_SIM in $(RDA_TARGET_DEF_FILE)) +endif + +USER_SIM_ORDER := $(call RDA_GET_MAKEFILE_VAR_FUNC,USER_SIM_ORDER,$(RDA_TARGET_DEF_FILE)) +ifeq ($(USER_SIM_ORDER),) +$(error Failed to get USER_SIM_ORDER in $(RDA_TARGET_DEF_FILE)) +endif + +NULL_STRING := +SPACE := ${NULL_STRING} # end of the line +COMMA := , +TGT_SIM_ORDER := $(foreach SIM,$(USER_SIM_ORDER),$(SIM)$(COMMA)) +TGT_SIM_ORDER := $(subst ${SPACE},,${TGT_SIM_ORDER}) + +CPPFLAGS_board/$(BOARDDIR)/hal_config.o += -I$(TOPDIR)/board/$(VENDOR)/common/include -DTGT_SIM_ORDER=$(TGT_SIM_ORDER) -DNUMBER_OF_SIM=$(NUMBER_OF_SIM) + +ifeq ($(strip $(TARGET_TABLET_MODE)),true) +CPPFLAGS_board/$(BOARDDIR)/clock.o += -DTARGET_TABLET_MODE +endif + +COBJS := $(COBJS-y) + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) $(SOBJS) + $(call cmd_link_o_target, $(OBJS) $(SOBJS)) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak *~ .depend + +######################################################################### +# This is for $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/rda/rda8810h/clock.c b/board/rda/rda8810h/clock.c new file mode 100644 index 0000000000..45caa4177d --- /dev/null +++ b/board/rda/rda8810h/clock.c @@ -0,0 +1,1329 @@ +#include <common.h> +#include <errno.h> +#include <asm/arch/rda_iomap.h> +#include <asm/io.h> +#include <asm/arch/reg_sysctrl.h> +#include <asm/arch/hwcfg.h> +#include <asm/arch/ispi.h> +#include <asm/arch/rda_sys.h> +#include "clock_config.h" +#include "debug.h" +#include "ddr3.h" +#include "tgt_ap_clock_config.h" + +#if (PMU_VBUCK1_VAL < 0 || PMU_VBUCK1_VAL > 15) +#error "Invalid PMU_VBUCK1_VAL" +#endif +#if (PMU_VBUCK3_VAL < 0 || PMU_VBUCK3_VAL > 15) +#error "Invalid PMU_VBUCK3_VAL" +#endif +#ifdef PMU_VBUCK4_VAL +#if (PMU_VBUCK4_VAL < 0 || PMU_VBUCK4_VAL > 15) +#error "Invalid PMU_VBUCK4_VAL" +#endif +#endif + +//#define DO_SIMPLE_DDR_TEST +//#define DO_DDR_PLL_DEBUG + +enum { + AP_CPU_CLK_IDX = 0, + AP_BUS_CLK_IDX, + AP_MEM_CLK_IDX, + AP_USB_CLK_IDX, +}; + +static int pll_enabled(int idx) +{ + if ((hwp_sysCtrlAp->Cfg_Pll_Ctrl[idx] & + (SYS_CTRL_AP_AP_PLL_ENABLE_MASK | + SYS_CTRL_AP_AP_PLL_LOCK_RESET_MASK)) == + (SYS_CTRL_AP_AP_PLL_ENABLE_ENABLE | + SYS_CTRL_AP_AP_PLL_LOCK_RESET_NO_RESET)) + return 1; + else + return 0; +} + +static int usb_in_use = 0; + +static void check_usb_usage(void) +{ + unsigned int mask = SYS_CTRL_AP_BUS_SEL_FAST_SLOW | + SYS_CTRL_AP_PLL_LOCKED_BUS_MASK | + SYS_CTRL_AP_PLL_LOCKED_USB_MASK; + unsigned int reg = SYS_CTRL_AP_BUS_SEL_FAST_FAST | + SYS_CTRL_AP_PLL_LOCKED_BUS_LOCKED | + SYS_CTRL_AP_PLL_LOCKED_USB_LOCKED; + + if ((hwp_sysCtrlAp->Sel_Clock & mask) == reg && + pll_enabled(AP_BUS_CLK_IDX) && + pll_enabled(AP_USB_CLK_IDX)) + usb_in_use = 1; + else + usb_in_use = 0; +} + +#ifdef DO_SIMPLE_DDR_TEST + +void mem_test_write(void) +{ + volatile unsigned int *addr; + + printf("write ddr test!!!!!!\n"); + + addr = (volatile unsigned int *)(0x80000000); + while((unsigned int)addr < 0x81000000) + { + *addr = (unsigned int )addr; + addr++; + } +} + +void mem_test_read(void) +{ + volatile unsigned int *addr; + + printf("read ddr!!!!\n"); + + addr = (volatile unsigned int *)(0x80000000); + + while((unsigned int)addr < 0x81000000) + { + if (*addr != (unsigned int)addr){ + int i = 0; + + printf("test error!!!!!, addr = %x\n", (unsigned int)addr); + for (i = 0; i < 80;i++){ + printf("%x ", *(addr + i)); + if ((i % 4) == 0) + printf("\n"); + } + + return; + } + + addr++; + } + printf("test complete!\n"); +} + +#endif /* DO_SIMPLE_DDR_TEST */ + +#ifndef CONFIG_RDA_FPGA + +// PMU bit fields +#define PMU_SET_BITFIELD(dword, bitfield, value) \ + (((dword) & ~(bitfield ## _MASK)) | (bitfield(value))) + +#define RDA_PMU_VBUCK1_BIT_ACT(n) (((n)&0xf)<<12) +#define RDA_PMU_VBUCK1_BIT_ACT_MASK (0xf<<12) +#define RDA_PMU_VBUCK1_BIT_ACT_SHIFT (12) + +#define RDA_PMU_VBUCK4_BIT_ACT_SHIFT (4) +#define RDA_PMU_VBUCK4_BIT_ACT_MASK (0xf<<4) +#define RDA_PMU_VBUCK4_BIT_ACT(n) (((n)&0xf)<<4) + +#define RDA_PMU_VBUCK3_BIT_ACT_SHIFT (12) +#define RDA_PMU_VBUCK3_BIT_ACT_MASK (0xf<<12) +#define RDA_PMU_VBUCK3_BIT_ACT(n) (((n)&0xf)<<12) + +struct pll_freq { + UINT32 freq_mhz; + UINT16 major; + UINT16 minor; + UINT16 with_div; + UINT16 div; +}; + +typedef enum { + PLL_REG_CPU_BASE = 0x00, + PLL_REG_BUS_BASE = 0x20, + PLL_REG_MEM_BASE = 0x60, + PLL_REG_USB_BASE = 0x80, +} PLL_REG_BASE_INDEX_t; + +typedef enum { + PLL_REG_OFFSET_01H = 1, + PLL_REG_OFFSET_02H = 2, + PLL_REG_OFFSET_DIV = 3, + PLL_REG_OFFSET_04H = 4, + PLL_REG_OFFSET_MAJOR = 5, + PLL_REG_OFFSET_MINOR = 6, + PLL_REG_OFFSET_07H = 7, +} PLL_REG_OFFSET_INDEX_t; + +static struct pll_freq pll_freq_table[] = { + /* MHz Major Minor div */ + {1600, 0x7B13, 0xB138, 0, 0x0000}, + {1200, 0x5C4E, 0xC4EC, 0, 0x0000}, + {1000, 0x4BEC, 0x4EC4, 0, 0x0000}, + { 988, 0x4000, 0x0000, 0, 0x0000}, + { 800, 0x3C00, 0x0000, 0, 0x0000}, + { 600, 0x2E27, 0x6274, 0, 0x0000}, + { 533, 0x2900, 0x0000, 1, 0xc797}, + { 519, 0x27EC, 0x4EC4, 1, 0xc797}, + { 500, 0x2676, 0x2762, 1, 0xc797}, + { 480, 0x24EC, 0x4EC4, 0, 0x0000}, + { 455, 0x2300, 0x0000, 1, 0xC297}, + { 416, 0x1FD8, 0x0000, 1, 0xCB97}, + /* 800M div 1, PLL:800M DDR:400M for mem pll only */ + { 400, 0x1F00, 0x0000, 1, 0xCA97}, + { 355, 0x369D, 0x89D8, 1, 0xD597}, + /* 702M div 1, PLL:702M DDR:351M for mem pll only */ + { 351, 0x3600, 0x0000, 1, 0xD297}, + { 333, 0x333B, 0x13B1, 1, 0xD097}, + /* 624M div 1, PLL:624M DDR:312M for mem pll only */ + { 312, 0x3000, 0x0000, 1, 0xD897}, + { 290, 0x2C9D, 0x89D8, 1, 0xE097}, + /* 520M div 1, PLL:520M DDR:260M for mem pll only */ + { 260, 0x2800, 0x0000, 1, 0xE897}, + /* 800M div 2, PLL:400M DDR:200M for mem pll only */ + { 200, 0x3D89, 0xD89C, 1, 0x0006}, + /* DDR:156M for mem pll only */ + { 156, 0x3000, 0x0000, 1, 0x0006}, + /* 800M div 4, PLL:200M DDR:100M for mem pll only */ + { 100, 0x3D89, 0xD89C, 1, 0x0005}, + /* 800M div 8, PLL:100M DDR:50M for mem pll only */ + { 50, 0x3D89, 0xD89C, 1, 0x0004}, +}; + +static const struct clock_config *g_clock_config; + +#ifdef DO_DDR_PLL_DEBUG +static struct clock_config clock_debug_config; +static UINT32 ddrfreq = 400, ddr32bit = 0; +#endif + +static void sys_shutdown_pll(void) +{ + int i; + + hwp_sysCtrlAp->REG_DBG = AP_CTRL_PROTECT_UNLOCK; + + if (usb_in_use) { + hwp_sysCtrlAp->Sel_Clock = SYS_CTRL_AP_SLOW_SEL_RF_RF + | SYS_CTRL_AP_CPU_SEL_FAST_SLOW + | SYS_CTRL_AP_BUS_SEL_FAST_FAST + | SYS_CTRL_AP_TIMER_SEL_FAST_FAST; + } else { + hwp_sysCtrlAp->Sel_Clock = SYS_CTRL_AP_SLOW_SEL_RF_RF + | SYS_CTRL_AP_CPU_SEL_FAST_SLOW + | SYS_CTRL_AP_BUS_SEL_FAST_SLOW + | SYS_CTRL_AP_TIMER_SEL_FAST_FAST; + } + + for (i = 0; i < 3; i++) { + /* In download mode, rom code has been set ap bus*/ + if (usb_in_use) { + if (i == AP_BUS_CLK_IDX) // ap bus + continue; + } + hwp_sysCtrlAp->Cfg_Pll_Ctrl[i] = + SYS_CTRL_AP_AP_PLL_ENABLE_POWER_DOWN | + SYS_CTRL_AP_AP_PLL_LOCK_RESET_RESET; + } +} + +static void sys_setup_pll(void) +{ + int i; + UINT32 mask; + UINT32 locked; + int cnt = 10; //10us, according to IC, the pll must be locked + + hwp_sysCtrlAp->REG_DBG = AP_CTRL_PROTECT_UNLOCK; + + for (i = 0; i < 3; i++) { + /* In download mode, rom code has been set ap bus*/ + if (usb_in_use) { + if (i == AP_BUS_CLK_IDX) // ap bus + continue; + } + + if (AP_MEM_CLK_IDX == i) + hwp_sysCtrlAp->Cfg_Pll_Ctrl[i] = + SYS_CTRL_AP_AP_PLL_ENABLE_ENABLE | + SYS_CTRL_AP_AP_PLL_LOCK_RESET_NO_RESET | + SYS_CTRL_AP_AP_PLL_LOCK_NUM_LOW(1)| + SYS_CTRL_AP_AP_PLL_LOCK_NUM_HIGH(30); + else + hwp_sysCtrlAp->Cfg_Pll_Ctrl[i] = + SYS_CTRL_AP_AP_PLL_ENABLE_ENABLE | + SYS_CTRL_AP_AP_PLL_LOCK_RESET_NO_RESET | + SYS_CTRL_AP_AP_PLL_LOCK_NUM_LOW(6)| + SYS_CTRL_AP_AP_PLL_LOCK_NUM_HIGH(30); + } + + mask = SYS_CTRL_AP_PLL_LOCKED_CPU_MASK + | SYS_CTRL_AP_PLL_LOCKED_BUS_MASK + | SYS_CTRL_AP_PLL_LOCKED_MEM_MASK + //| SYS_CTRL_AP_PLL_LOCKED_USB_MASK + ; + locked = SYS_CTRL_AP_PLL_LOCKED_CPU_LOCKED + | SYS_CTRL_AP_PLL_LOCKED_BUS_LOCKED + | SYS_CTRL_AP_PLL_LOCKED_MEM_LOCKED + //| SYS_CTRL_AP_PLL_LOCKED_USB_LOCKED + ; + + while (((hwp_sysCtrlAp->Sel_Clock & mask) != locked) && cnt) { + udelay(1); + cnt--; + } + if (cnt == 0) { + printf("WARNING, cannot lock cpu/bus/mem pll 0x%08x ", + hwp_sysCtrlAp->Sel_Clock); + printf("but we run anyway ...\n"); + } + + for (i = 0; i < 3; i++) { + hwp_sysCtrlAp->Cfg_Pll_Ctrl[i] |= + SYS_CTRL_AP_AP_PLL_CLK_FAST_ENABLE_ENABLE; + } + + hwp_sysCtrlAp->Sel_Clock = SYS_CTRL_AP_SLOW_SEL_RF_RF + | SYS_CTRL_AP_CPU_SEL_FAST_FAST + | SYS_CTRL_AP_BUS_SEL_FAST_FAST + | SYS_CTRL_AP_TIMER_SEL_FAST_FAST; +} + +static void sys_setup_clk(void) +{ + // Disable some power-consuming clocks +#ifdef CONFIG_VPU_TEST + hwp_sysCtrlAp->Clk_APO_Enable = SYS_CTRL_AP_ENABLE_APOC_VPU; + //hwp_sysCtrlAp->Clk_MEM_Enable = SYS_CTRL_AP_ENABLE_MEM_VPU; +#else + hwp_sysCtrlAp->Clk_APO_Disable = SYS_CTRL_AP_DISABLE_APOC_VPU; + //hwp_sysCtrlAp->Clk_MEM_Disable = SYS_CTRL_AP_DISABLE_MEM_VPU; +#endif + + // Init clock gating mode + hwp_sysCtrlAp->Clk_CPU_Mode = 0; +#ifdef CONFIG_VPU_TEST + hwp_sysCtrlAp->Clk_AXI_Mode = SYS_CTRL_AP_MODE_AXI_DMA_MANUAL | SYS_CTRL_AP_MODE_APB0_CONF_MANUAL; +#else + hwp_sysCtrlAp->Clk_AXI_Mode = SYS_CTRL_AP_MODE_AXI_DMA_MANUAL; +#endif + hwp_sysCtrlAp->Clk_AXIDIV2_Mode = 0; + hwp_sysCtrlAp->Clk_GCG_Mode = SYS_CTRL_AP_MODE_GCG_GOUDA_MANUAL + | SYS_CTRL_AP_MODE_GCG_CAMERA_MANUAL; + hwp_sysCtrlAp->Clk_AHB1_Mode = 0; + hwp_sysCtrlAp->Clk_APB1_Mode = 0; + hwp_sysCtrlAp->Clk_APB2_Mode = 0; +#ifdef CONFIG_VPU_TEST + hwp_sysCtrlAp->Clk_MEM_Mode = SYS_CTRL_AP_MODE_CLK_MEM_MANUAL; +#else + hwp_sysCtrlAp->Clk_MEM_Mode = 0; +#endif + //hwp_sysCtrlAp->Clk_APO_Mode = SYS_CTRL_AP_MODE_APOC_VPU_MANUAL; + + // Init module frequency + hwp_sysCtrlAp->Cfg_Clk_AP_CPU = g_clock_config->CLK_CPU; + hwp_sysCtrlAp->Cfg_Clk_AP_AXI = g_clock_config->CLK_AXI; + hwp_sysCtrlAp->Cfg_Clk_AP_GCG = g_clock_config->CLK_GCG; + + if (!usb_in_use) { + hwp_sysCtrlAp->Cfg_Clk_AP_AHB1 = g_clock_config->CLK_AHB1; + } + + hwp_sysCtrlAp->Cfg_Clk_AP_APB1 = g_clock_config->CLK_APB1; + hwp_sysCtrlAp->Cfg_Clk_AP_APB2 = g_clock_config->CLK_APB2; + hwp_sysCtrlAp->Cfg_Clk_AP_MEM = g_clock_config->CLK_MEM; + hwp_sysCtrlAp->Cfg_Clk_AP_GPU = g_clock_config->CLK_GPU; + hwp_sysCtrlAp->Cfg_Clk_AP_VPU = g_clock_config->CLK_VPU; + hwp_sysCtrlAp->Cfg_Clk_AP_VOC = g_clock_config->CLK_VOC; + hwp_sysCtrlAp->Cfg_Clk_AP_SFLSH = g_clock_config->CLK_SFLSH; +} + +static void print_sys_reg(char *name, UINT32 value) +{ + printf("clk %s = %lx\n", name, value); +} + +static void sys_dump_clk(void) +{ + print_sys_reg("CPU", hwp_sysCtrlAp->Cfg_Clk_AP_CPU); + print_sys_reg("AXI", hwp_sysCtrlAp->Cfg_Clk_AP_AXI); + print_sys_reg("GCG", hwp_sysCtrlAp->Cfg_Clk_AP_GCG); + print_sys_reg("AHB1", hwp_sysCtrlAp->Cfg_Clk_AP_AHB1); + print_sys_reg("APB1", hwp_sysCtrlAp->Cfg_Clk_AP_APB1); + print_sys_reg("APB2", hwp_sysCtrlAp->Cfg_Clk_AP_APB2); + print_sys_reg("MEM", hwp_sysCtrlAp->Cfg_Clk_AP_MEM); + print_sys_reg("GPU", hwp_sysCtrlAp->Cfg_Clk_AP_GPU); + print_sys_reg("VPU", hwp_sysCtrlAp->Cfg_Clk_AP_VPU); + print_sys_reg("VOC", hwp_sysCtrlAp->Cfg_Clk_AP_VOC); + print_sys_reg("SFLSH", hwp_sysCtrlAp->Cfg_Clk_AP_SFLSH); +} + +static int pll_freq_set(UINT32 reg_base, UINT32 freq_mhz) +{ + int i; + struct pll_freq *freq; + unsigned int major, minor; + unsigned short value_02h; + + /* find pll_freq */ + for (i = 0; i < ARRAY_SIZE(pll_freq_table); i++) { + if (pll_freq_table[i].freq_mhz == freq_mhz) + break; + } + if (i >= ARRAY_SIZE(pll_freq_table)) { + printf("pll_freq_set, fail to find freq\n"); + return -1; + } + + freq = &pll_freq_table[i]; + if (freq->with_div && (reg_base == PLL_REG_MEM_BASE)) { + ispi_reg_write(reg_base + PLL_REG_OFFSET_DIV, + freq->div); + // Calculate the real MEM PLL freq + freq_mhz *= (1 << (8 - (freq->div & 0x7))); + } + if (freq_mhz >= 800 || reg_base == PLL_REG_USB_BASE) { + value_02h = 0x0309; + // Div PLL freq by 2 + minor = ((freq->major & 0xFFFF) << 14) | + ((freq->minor >> 2) & 0x3FFF); + minor >>= 1; + // Recalculate the divider + major = (minor >> 14) & 0xFFFF; + minor = (minor << 2) & 0xFFFF; + } else { + value_02h = 0x0209; + major = freq->major; + minor = freq->minor; + } + if (reg_base == PLL_REG_USB_BASE) + value_02h ^= (1 << 8); + ispi_reg_write(reg_base + PLL_REG_OFFSET_02H, value_02h); + ispi_reg_write(reg_base + PLL_REG_OFFSET_MAJOR, major); + ispi_reg_write(reg_base + PLL_REG_OFFSET_MINOR, minor); + ispi_reg_write(reg_base + PLL_REG_OFFSET_07H, 0x0010); + + return 0; +} + +static void pll_setup_freq(void) +{ + pll_freq_set(PLL_REG_CPU_BASE, g_clock_config->PLL_FREQ_CPU); + // Always configure BUS PLL, even when it is being used + pll_freq_set(PLL_REG_BUS_BASE, g_clock_config->PLL_FREQ_BUS); + pll_freq_set(PLL_REG_MEM_BASE, g_clock_config->PLL_FREQ_MEM); + pll_freq_set(PLL_REG_USB_BASE, g_clock_config->PLL_FREQ_USB); +} + +static void print_pll_freq(char *name, UINT32 value) +{ + printf("pll freq %s = %d\n", name, (int)value); +} + +static void sys_dump_pll_freq(void) +{ + print_pll_freq("CPU", g_clock_config->PLL_FREQ_CPU); + print_pll_freq("BUS", g_clock_config->PLL_FREQ_BUS); + print_pll_freq("MEM", g_clock_config->PLL_FREQ_MEM); + //print_pll_freq("USB", g_clock_config->PLL_FREQ_USB); +} + +static void pmu_get_efuse_dcdc(int buckVoltLow[]) +{ + static const u8 setBitCnt[8] = { 0, 1, 1, 2, 1, 2, 2, 3, }; + u16 dcdc; + int i; + + ispi_reg_write(0x51, 0x02ed); + udelay(2000); + ispi_reg_write(0x51, 0x02fd); + dcdc = ispi_reg_read(0x52); + ispi_reg_write(0x51, 0x0200); + + for (i = 0; i < 4; i++) { + buckVoltLow[i] = (setBitCnt[dcdc & 0x7] > 1); + dcdc >>= 3; + } +} + +static void pmu_setup_init(void) +{ + u32 value; + int buck_volt_low[4] = { 0, }; + + rda_nand_iodrive_set(); + +#ifdef CONFIG_RDA_PDL + enable_charger(0); +#endif + + ispi_open(1); + + // Disable vibrator + ispi_reg_write(0x03, 0x9FFF); + // Enable bandgap chopper mode + ispi_reg_write(0x0F, 0x1E90); + // Enable high AC throttling + ispi_reg_write(0x12, 0x1218); +#ifdef TARGET_TABLET_MODE + // Charger current (cc = 6, pre = 7) + ispi_reg_write(0x13, 0x1B70); +#else + // Charger current (cc = 2, pre = 7) + ispi_reg_write(0x13, 0x1970); +#endif + // Vcore DCDC freq + ispi_reg_write(0x2D, 0x96BA); + ispi_reg_write(0x2E, 0x12AA); + // Get efuse dcdc + pmu_get_efuse_dcdc(buck_volt_low); + // Vcore voltage + value = 0x9244; + value = PMU_SET_BITFIELD(value, RDA_PMU_VBUCK1_BIT_ACT, + PMU_VBUCK1_VAL + + ((PMU_VBUCK1_VAL < 15 && buck_volt_low[0]) ? 1 : 0)); + ispi_reg_write(0x2F, value); + // DDR PWM mode + ispi_reg_write(0x0D, 0x92D0); + // DDR voltage + value = 0xAAB5; + value = PMU_SET_BITFIELD(value, RDA_PMU_VBUCK3_BIT_ACT, + PMU_VBUCK3_VAL + + ((PMU_VBUCK3_VAL < 15 && buck_volt_low[2]) ? 1 : 0)); +#ifdef PMU_VBUCK4_VAL + value = PMU_SET_BITFIELD(value, RDA_PMU_VBUCK4_BIT_ACT, + PMU_VBUCK4_VAL + + ((PMU_VBUCK4_VAL < 15 && buck_volt_low[3]) ? 1 : 0)); + value ^= RDA_PMU_VBUCK4_BIT_ACT(8); + // vBuck4 in low voltage range + ispi_reg_write(0x36, 0x6E45); +#else + ispi_reg_write(0x36, 0x6E54); +#endif + ispi_reg_write(0x2A, value); + // DDR power parameters + ispi_reg_write(0x4A, 0x96AA); + ispi_reg_write(0x4B, 0x96AA); + + ispi_open(0); +} + +static void setup_ddr_vtt(int vtt) +{ + printf("setup ddr vtt to %d\n", vtt); + ispi_reg_write(0x69, g_clock_config->DDR_TIMING_069H); +} + +#if 0 +/* + * we initialize usb clock, but this won't cause the usb clock jitter, + * because wo don't setup the usb pll + */ +static void usb_clock_pre_init(void) +{ + ispi_reg_write(0x83, 0x72ef); + ispi_reg_write(0x89, 0x7400); +} +#endif + +static void pll_setup_init(void) +{ + setup_ddr_vtt(DDR_VTT_VAL); + + if (g_clock_config->DDR_CHAN_1_VALID) { + ispi_reg_write(0x100, g_clock_config->DDR_TIMING_100H); + ispi_reg_write(0x101, g_clock_config->DDR_TIMING_101H); + ispi_reg_write(0x102, g_clock_config->DDR_TIMING_102H); + ispi_reg_write(0x103, g_clock_config->DDR_TIMING_103H); + ispi_reg_write(0x104, g_clock_config->DDR_TIMING_104H); + ispi_reg_write(0x105, g_clock_config->DDR_TIMING_105H); + ispi_reg_write(0x106, g_clock_config->DDR_TIMING_106H); + ispi_reg_write(0x107, g_clock_config->DDR_TIMING_107H); + ispi_reg_write(0x108, g_clock_config->DDR_TIMING_108H); + ispi_reg_write(0x109, g_clock_config->DDR_TIMING_109H); + ispi_reg_write(0x10A, g_clock_config->DDR_TIMING_10AH); + ispi_reg_write(0x10B, g_clock_config->DDR_TIMING_10BH); + ispi_reg_write(0x10C, g_clock_config->DDR_TIMING_10CH); + ispi_reg_write(0x10D, g_clock_config->DDR_TIMING_10DH); + ispi_reg_write(0x10E, g_clock_config->DDR_TIMING_10EH); + ispi_reg_write(0x10F, g_clock_config->DDR_TIMING_10FH); + } + + if (g_clock_config->DDR_CHAN_2_VALID) { + ispi_reg_write(0x120, g_clock_config->DDR_TIMING_120H); + ispi_reg_write(0x121, g_clock_config->DDR_TIMING_121H); + ispi_reg_write(0x122, g_clock_config->DDR_TIMING_122H); + ispi_reg_write(0x123, g_clock_config->DDR_TIMING_123H); + ispi_reg_write(0x124, g_clock_config->DDR_TIMING_124H); + ispi_reg_write(0x125, g_clock_config->DDR_TIMING_125H); + ispi_reg_write(0x126, g_clock_config->DDR_TIMING_126H); + ispi_reg_write(0x127, g_clock_config->DDR_TIMING_127H); + ispi_reg_write(0x128, g_clock_config->DDR_TIMING_128H); + ispi_reg_write(0x129, g_clock_config->DDR_TIMING_129H); + ispi_reg_write(0x12A, g_clock_config->DDR_TIMING_12AH); + ispi_reg_write(0x12B, g_clock_config->DDR_TIMING_12BH); + ispi_reg_write(0x12C, g_clock_config->DDR_TIMING_12CH); + ispi_reg_write(0x12D, g_clock_config->DDR_TIMING_12DH); + ispi_reg_write(0x12E, g_clock_config->DDR_TIMING_12EH); + ispi_reg_write(0x12F, g_clock_config->DDR_TIMING_12FH); + } + + if (g_clock_config->DDR_CHAN_3_VALID) { + ispi_reg_write(0x140, g_clock_config->DDR_TIMING_140H); + ispi_reg_write(0x141, g_clock_config->DDR_TIMING_141H); + ispi_reg_write(0x142, g_clock_config->DDR_TIMING_142H); + ispi_reg_write(0x143, g_clock_config->DDR_TIMING_143H); + ispi_reg_write(0x144, g_clock_config->DDR_TIMING_144H); + ispi_reg_write(0x145, g_clock_config->DDR_TIMING_145H); + ispi_reg_write(0x146, g_clock_config->DDR_TIMING_146H); + ispi_reg_write(0x147, g_clock_config->DDR_TIMING_147H); + ispi_reg_write(0x148, g_clock_config->DDR_TIMING_148H); + ispi_reg_write(0x149, g_clock_config->DDR_TIMING_149H); + ispi_reg_write(0x14A, g_clock_config->DDR_TIMING_14AH); + ispi_reg_write(0x14B, g_clock_config->DDR_TIMING_14BH); + ispi_reg_write(0x14C, g_clock_config->DDR_TIMING_14CH); + ispi_reg_write(0x14D, g_clock_config->DDR_TIMING_14DH); + ispi_reg_write(0x14E, g_clock_config->DDR_TIMING_14EH); + ispi_reg_write(0x14F, g_clock_config->DDR_TIMING_14FH); + } + + if (g_clock_config->DDR_CHAN_4_VALID) { + ispi_reg_write(0x160, g_clock_config->DDR_TIMING_160H); + ispi_reg_write(0x161, g_clock_config->DDR_TIMING_161H); + ispi_reg_write(0x162, g_clock_config->DDR_TIMING_162H); + ispi_reg_write(0x163, g_clock_config->DDR_TIMING_163H); + ispi_reg_write(0x164, g_clock_config->DDR_TIMING_164H); + ispi_reg_write(0x165, g_clock_config->DDR_TIMING_165H); + ispi_reg_write(0x166, g_clock_config->DDR_TIMING_166H); + ispi_reg_write(0x167, g_clock_config->DDR_TIMING_167H); + ispi_reg_write(0x168, g_clock_config->DDR_TIMING_168H); + ispi_reg_write(0x169, g_clock_config->DDR_TIMING_169H); + ispi_reg_write(0x16A, g_clock_config->DDR_TIMING_16AH); + ispi_reg_write(0x16B, g_clock_config->DDR_TIMING_16BH); + ispi_reg_write(0x16C, g_clock_config->DDR_TIMING_16CH); + ispi_reg_write(0x16D, g_clock_config->DDR_TIMING_16DH); + ispi_reg_write(0x16E, g_clock_config->DDR_TIMING_16EH); + ispi_reg_write(0x16F, g_clock_config->DDR_TIMING_16FH); + } + + ispi_reg_write(0x180, g_clock_config->DDR_TIMING_180H); + ispi_reg_write(0x181, g_clock_config->DDR_TIMING_181H); + ispi_reg_write(0x182, g_clock_config->DDR_TIMING_182H); + ispi_reg_write(0x183, g_clock_config->DDR_TIMING_183H); + ispi_reg_write(0x184, g_clock_config->DDR_TIMING_184H); + ispi_reg_write(0x185, g_clock_config->DDR_TIMING_185H); + ispi_reg_write(0x186, g_clock_config->DDR_TIMING_186H); + ispi_reg_write(0x187, g_clock_config->DDR_TIMING_187H); + ispi_reg_write(0x188, g_clock_config->DDR_TIMING_188H); + ispi_reg_write(0x189, g_clock_config->DDR_TIMING_189H); + ispi_reg_write(0x18A, g_clock_config->DDR_TIMING_18AH); + ispi_reg_write(0x18B, g_clock_config->DDR_TIMING_18BH); + ispi_reg_write(0x18C, g_clock_config->DDR_TIMING_18CH); + + //usb_clock_pre_init(); + + udelay(5000); +} + +static void pll_setup_mem(void) +{ +} + +static void pll_setup_mem_cal(void) +{ +} + +static void print_pll_reg(UINT32 index, UINT32 value) +{ + printf("pll reg %lx = %lx\n", index, value); +} + +static void pll_dump_reg(void) +{ + print_pll_reg(0x005, ispi_reg_read(0x005)); + print_pll_reg(0x006, ispi_reg_read(0x006)); + print_pll_reg(0x063, ispi_reg_read(0x063)); + print_pll_reg(0x065, ispi_reg_read(0x065)); + print_pll_reg(0x066, ispi_reg_read(0x066)); + print_pll_reg(0x069, ispi_reg_read(0x069)); + + if (g_clock_config->DDR_CHAN_1_VALID) + { + print_pll_reg(0x100, ispi_reg_read(0x100)); + print_pll_reg(0x101, ispi_reg_read(0x101)); + print_pll_reg(0x102, ispi_reg_read(0x102)); + print_pll_reg(0x103, ispi_reg_read(0x103)); + print_pll_reg(0x104, ispi_reg_read(0x104)); + print_pll_reg(0x105, ispi_reg_read(0x105)); + print_pll_reg(0x106, ispi_reg_read(0x106)); + print_pll_reg(0x107, ispi_reg_read(0x107)); + print_pll_reg(0x108, ispi_reg_read(0x108)); + print_pll_reg(0x109, ispi_reg_read(0x109)); + print_pll_reg(0x10A, ispi_reg_read(0x10A)); + print_pll_reg(0x10B, ispi_reg_read(0x10B)); + print_pll_reg(0x10C, ispi_reg_read(0x10C)); + print_pll_reg(0x10D, ispi_reg_read(0x10D)); + print_pll_reg(0x10E, ispi_reg_read(0x10E)); + print_pll_reg(0x10F, ispi_reg_read(0x10F)); + } + + if (g_clock_config->DDR_CHAN_2_VALID) + { + print_pll_reg(0x120, ispi_reg_read(0x120)); + print_pll_reg(0x121, ispi_reg_read(0x121)); + print_pll_reg(0x122, ispi_reg_read(0x122)); + print_pll_reg(0x123, ispi_reg_read(0x123)); + print_pll_reg(0x124, ispi_reg_read(0x124)); + print_pll_reg(0x125, ispi_reg_read(0x125)); + print_pll_reg(0x126, ispi_reg_read(0x126)); + print_pll_reg(0x127, ispi_reg_read(0x127)); + print_pll_reg(0x128, ispi_reg_read(0x128)); + print_pll_reg(0x129, ispi_reg_read(0x129)); + print_pll_reg(0x12A, ispi_reg_read(0x12A)); + print_pll_reg(0x12B, ispi_reg_read(0x12B)); + print_pll_reg(0x12C, ispi_reg_read(0x12C)); + print_pll_reg(0x12D, ispi_reg_read(0x12D)); + print_pll_reg(0x12E, ispi_reg_read(0x12E)); + print_pll_reg(0x12F, ispi_reg_read(0x12F)); + } + + if (g_clock_config->DDR_CHAN_3_VALID) + { + print_pll_reg(0x140, ispi_reg_read(0x140)); + print_pll_reg(0x141, ispi_reg_read(0x141)); + print_pll_reg(0x142, ispi_reg_read(0x142)); + print_pll_reg(0x143, ispi_reg_read(0x143)); + print_pll_reg(0x144, ispi_reg_read(0x144)); + print_pll_reg(0x145, ispi_reg_read(0x145)); + print_pll_reg(0x146, ispi_reg_read(0x146)); + print_pll_reg(0x147, ispi_reg_read(0x147)); + print_pll_reg(0x148, ispi_reg_read(0x148)); + print_pll_reg(0x149, ispi_reg_read(0x149)); + print_pll_reg(0x14A, ispi_reg_read(0x14A)); + print_pll_reg(0x14B, ispi_reg_read(0x14B)); + print_pll_reg(0x14C, ispi_reg_read(0x14C)); + print_pll_reg(0x14D, ispi_reg_read(0x14D)); + print_pll_reg(0x14E, ispi_reg_read(0x14E)); + print_pll_reg(0x14F, ispi_reg_read(0x14F)); + } + + if (g_clock_config->DDR_CHAN_4_VALID) + { + print_pll_reg(0x160, ispi_reg_read(0x160)); + print_pll_reg(0x161, ispi_reg_read(0x161)); + print_pll_reg(0x162, ispi_reg_read(0x162)); + print_pll_reg(0x163, ispi_reg_read(0x163)); + print_pll_reg(0x164, ispi_reg_read(0x164)); + print_pll_reg(0x165, ispi_reg_read(0x165)); + print_pll_reg(0x166, ispi_reg_read(0x166)); + print_pll_reg(0x167, ispi_reg_read(0x167)); + print_pll_reg(0x168, ispi_reg_read(0x168)); + print_pll_reg(0x169, ispi_reg_read(0x169)); + print_pll_reg(0x16A, ispi_reg_read(0x16A)); + print_pll_reg(0x16B, ispi_reg_read(0x16B)); + print_pll_reg(0x16C, ispi_reg_read(0x16C)); + print_pll_reg(0x16D, ispi_reg_read(0x16D)); + print_pll_reg(0x16E, ispi_reg_read(0x16E)); + print_pll_reg(0x16F, ispi_reg_read(0x16F)); + } + + print_pll_reg(0x180, ispi_reg_read(0x180)); + print_pll_reg(0x181, ispi_reg_read(0x181)); + print_pll_reg(0x182, ispi_reg_read(0x182)); + print_pll_reg(0x183, ispi_reg_read(0x183)); + print_pll_reg(0x184, ispi_reg_read(0x184)); + print_pll_reg(0x185, ispi_reg_read(0x185)); + print_pll_reg(0x186, ispi_reg_read(0x186)); + print_pll_reg(0x187, ispi_reg_read(0x187)); + print_pll_reg(0x188, ispi_reg_read(0x188)); + print_pll_reg(0x189, ispi_reg_read(0x189)); + print_pll_reg(0x18A, ispi_reg_read(0x18A)); + print_pll_reg(0x18B, ispi_reg_read(0x18B)); + print_pll_reg(0x18C, ispi_reg_read(0x18C)); +} + +static int clock_save_config(void) +{ + /* save config to nand */ + return 1; +} + +#ifdef DO_DDR_PLL_DEBUG + +static int ddr_get_freq(UINT8 chioce) +{ + switch(chioce) + { + case 1: + return 50; + case 2: + return 100; + case 3: + return 156; + case 4: + return 200; + case 5: + return 290; + case 6: + return 333; + case 7: + return 355; + case 8: + return 400; + case 9: + return 416; + case 10: + return 455; + case 11: + return 519; + case 12: + return 533; + case 13: + return 260; + default: + return -1; + } +} + +static void freq_choose(void) +{ + UINT8 i = 0, buf[3] = {0}, choice = 0; + INT32 freq_temp = 0; + + printf("\nPlese choose the ddr Freq:"); + printf("\n1.50M 2.100M 3.156M 4.200M 5.290M 6.333M 7.355M 8.400M 9.416M 10.455M 11.519M 12.533M 13.260M"); + printf("\nThe number is:"); + + while(1) + { + if (i > 2) + { + printf("\n Sorry, you input is wrong. Please input again:"); + i = 0; + } + buf[i] = serial_getc(); + serial_putc(buf[i]); + + if ( ('\r' == buf[i]) || ('\n' == buf[i])) + { + serial_puts("\n"); + break; + } + + i++; + } + + if (1 == i) + choice = buf[0] - 0x30; + else if (2 == i) + choice = 10*(buf[0] - 0x30) + (buf[1] - 0x30); + else + return; + + freq_temp = ddr_get_freq(choice); + if (-1 == freq_temp ) + printf("\n Sorry, the fre you choose is wrong"); + ddrfreq = freq_temp; +} + +static void data_bits_choose(void) +{ + UINT8 i = 0, buf[2] = {0}; + + printf("\nPlese choose the ddr data bits:"); + printf("\n1.16 2.32"); + printf("\nThe number is:"); + + while(1) + { + buf[i] =serial_getc(); + + if (i == 1) + { + if (('\r' == buf[i]) || ('\n' == buf[i])) + { + if (1 == (buf[0] - 0x30)) + ddr32bit = 0; + else + ddr32bit = 1; + return; + } + else + { + printf("\n Sorry, you input is wrong. Please input again:"); + i = 0; + continue; + } + } + + serial_putc(buf[i]); + + if ((buf[i] - 0x30) > 2 || 0 == (buf[i] - 0x30)) + printf("\n Sorry, you input is wrong. Please input again:"); + else + i++; + } +} + +#if 0 +static void pmu_setup_calibration_voltage(UINT8 vcoreselect) +{ + UINT8 buf[3] = {0}, voltage = 0; + int i = 0; + UINT32 reg_value,temp, regid = 0; + + ispi_open(1); + if (1 == vcoreselect) + { + regid = 0x2f; + printf("\nPlese input vcore voltage(0 ~ 15):"); + } + else + { + regid = 0x2a; + printf("\nPlese input DDR voltage(0 ~ 15):"); + } + + + while(1) + { + if (i > 2) + { + printf("\n Sorry, you input is wrong. Please input again:"); + i = 0; + } + buf[i] = serial_getc(); + serial_putc(buf[i]); + + if ( ('\r' == buf[i]) || ('\n' == buf[i])) + { + printf("\n"); + break; + } + + i++; + } + + if (1 == i) + voltage = buf[0] - 0x30; + else if (2 == i) + voltage = 10*(buf[0] - 0x30) + (buf[1] - 0x30); + else + return; + + temp = (UINT32)voltage; + temp = (temp & 0xf) << 12; + reg_value = ispi_reg_read(regid); + reg_value &= ~(0xf << 12); + reg_value |= temp ; + ispi_reg_write(regid, reg_value); + mdelay(100); +} +#endif + +static void pmu_setup_calibration_voltage(UINT8 vcoreselect) +{ + UINT8 buf[3] = {0}, voltage = 0; + int i = 0; + UINT32 reg_value,temp, regid = 0; + + ispi_open(1); + if (1 == vcoreselect) + { + regid = 0x2f; + printf("\nPlese input vcore voltage(0 ~ 15):"); + } + else + { + regid = 0x2a; + if (2 == vcoreselect) + printf("\nPlese input DDR buck3 voltage(0 ~ 15):"); + else + printf("\nPlese input DDR buck4 voltage(0 ~ 15):"); + } + + while(1) + { + if (i > 2) + { + printf("\n Sorry, you input is wrong. Please input again:"); + i = 0; + } + buf[i] = serial_getc(); + serial_putc(buf[i]); + + if ( ('\r' == buf[i]) || ('\n' == buf[i])) + { + printf("\n"); + break; + } + + i++; + } + + if (1 == i) + voltage = buf[0] - 0x30; + else if (2 == i) + voltage = 10*(buf[0] - 0x30) + (buf[1] - 0x30); + else + return; + + if ((vcoreselect == 1) || (vcoreselect == 2)) + { + temp = (UINT32)voltage; + temp = (temp & 0xf) << 12; + reg_value = ispi_reg_read(regid); + reg_value &= ~(0xf << 12); + reg_value |= temp ; + ispi_reg_write(regid, reg_value); + mdelay(100); + } + else + { + temp = (UINT32)voltage; + temp = (temp & 0xf) << 4; + reg_value = ispi_reg_read(regid); + reg_value &= ~(0xf << 4); + reg_value |= temp ; + reg_value ^= RDA_PMU_VBUCK4_BIT_ACT(8); + ispi_reg_write(regid, reg_value); + ispi_reg_write(0x0D, 0x92D0); + ispi_reg_write(0x4B, 0x96A8); + mdelay(100); + } +} + +static void pmu_buck4_buck3_choose(void) +{ + UINT8 i = 0, buf[2] = {0}; + UINT8 ddr_voltage_source = 0; + + printf("\nPlese choose the ddr voltage:"); + printf("\n1.DDR3L 2.DDR3"); + printf("\nThe number is:"); + + while(1) + { + buf[i] =serial_getc(); + + if (i == 1) + { + if (('\r' == buf[i]) || ('\n' == buf[i])) + { + if (1 == (buf[0] - 0x30)) + ddr_voltage_source =2; + else{ + ddr_voltage_source = 3; + pmu_setup_calibration_voltage(2); + } + pmu_setup_calibration_voltage(ddr_voltage_source); + return; + } + else + { + printf("\n Sorry, you input is wrong. Please input again:"); + i = 0; + continue; + } + } + + serial_putc(buf[i]); + + if ((buf[i] - 0x30) > 2 || 0 == (buf[i] - 0x30)) + printf("\n Sorry, you input is wrong. Please input again:"); + else + i++; + } +} + + +void clock_load_ddr_cal_config(void) +{ + clock_debug_config.PLL_FREQ_MEM = ddrfreq; + if (ddrfreq < 200) + clock_debug_config.DDR_FLAGS |= DDR_FLAGS_DLLOFF; + else + clock_debug_config.DDR_FLAGS &= ~DDR_FLAGS_DLLOFF; + + if (0 == ddr32bit) + { + clock_debug_config.DDR_CHAN_3_VALID = 0; + clock_debug_config.DDR_CHAN_4_VALID = 0; + } + + clock_debug_config.DDR_PARA &= ~DDR_PARA_MEM_BITS_MASK; + if (0 == ddr32bit) + clock_debug_config.DDR_PARA |= DDR_PARA_MEM_BITS(1); + else + clock_debug_config.DDR_PARA |= DDR_PARA_MEM_BITS(2); +} + +static int serial_gets(UINT8 *pstr) +{ + UINT32 length; + + length = 0; + while(1) { + pstr[length] = serial_getc(); + if(pstr[length] == '\r') { + pstr[length] = 0x00; + break; + } + else if( pstr[length] == '\b' ) { + if(length>0) { + length --; + printf("\b"); + } + } + else { + serial_putc(pstr[length]); + length ++; + } + + if(length > 32) + return -1; + } + return length; +} + +UINT32 asc2hex(UINT8 *pstr, UINT8 len) +{ + UINT8 i,ch,mylen; + UINT32 hexvalue; + + for(mylen=0,i=0; i<8; i++) + { + if( pstr[i] == 0 ) + break; + mylen ++; + } + if( len != 0 ) + { + if(mylen>len) + mylen = len; + } + if(mylen>8) + mylen = 8; + + hexvalue = 0; + for (i = 0; i < mylen; i++) + { + hexvalue <<= 4; + ch = *(pstr+i); + if((ch>='0') && (ch<='9')) + hexvalue |= ch - '0'; + else if((ch>='A') && (ch<='F')) + hexvalue |= ch - ('A' - 10); + else if((ch>='a') && (ch<='f')) + hexvalue |= ch - ('a' - 10); + else + ; + } + return(hexvalue); +} + +static int process_cmd(char * cmd) +{ + char cmd_element[3][16] = {{0}}; + char * cmd_temp = cmd; + UINT8 i = 0, cmd_element_num = 0, former_space = 1; + UINT16 reg = 0, reg_value = 0; + + if (NULL == cmd) + return -1; + + while(('\0' != *cmd_temp) && ('\r' != *cmd_temp) && ('\n' != *cmd_temp)) + { + if (' ' == * cmd_temp) + { + if (0 == former_space) + { + former_space = 1; + cmd_element[cmd_element_num][i] = '\0'; + cmd_element_num++; + if (cmd_element_num > 2) + return -1; + + i = 0; + } + } + else + { + former_space = 0; + cmd_element[cmd_element_num][i] = *cmd_temp; + i++; + if (i > 6) + return -1; + } + + cmd_temp++; + } + + cmd_element[cmd_element_num][i] = '\0'; + + if (!strcmp(cmd_element[0], "read")) + { + if (cmd_element_num == 2) + return -1; + if (('0' != cmd_element[1][0]) || ('x' != cmd_element[1][1])) + return -1; + reg = (UINT16)asc2hex((UINT8 *)&cmd_element[1][2], 4); + reg_value = ispi_reg_read(reg); + printf("value = 0x%x", reg_value); + printf("\nddrPll#"); + } + else if (!strcmp(cmd_element[0], "write")) + { + if (cmd_element_num != 2) + return -1; + if (('0' != cmd_element[1][0]) || ('x' != cmd_element[1][1]) + || ('0' != cmd_element[2][0]) || ('x' != cmd_element[2][1])) + return -1; + + reg = (UINT16)asc2hex((UINT8 *)&cmd_element[1][2], 4); + reg_value = (UINT16)asc2hex((UINT8 *)&cmd_element[2][2], 4); + ispi_reg_write(reg, reg_value); + } + else if (!strcmp(cmd_element[0], "finish")) + { + return 1; + } + else if (!strcmp(cmd_element[0], "dump")) + { + pll_dump_reg(); + printf("ddrPll#"); + } + else + { + return -1; + } + + return 0; +} + +static void cmd_input(void) +{ + char cmd[48] = {0}; + int len = 0; + + ispi_open(0); + printf("\nddrPll#"); + while(1) + { + len = serial_gets((UINT8 *)cmd); + printf("\nddrPll#"); + if (len > 0) + { + int result = 0; + + result = process_cmd(cmd); + if (-1 == result) + printf("command error! \nddrPll#"); + else if (1 == result) + break; + else + continue; + } + } + + return; +} + +#endif /* DO_DDR_PLL_DEBUG */ + +int clock_init(void) +{ +#ifdef DO_DDR_PLL_DEBUG + char choice = 'n'; +#endif + + /* First check current usb usage */ + check_usb_usage(); + + printf("Init Clock ...\n"); + g_clock_config = get_default_clock_config(); + + printf("Clock config ver: %d.%d\n", + g_clock_config->VERSION_MAJOR, g_clock_config->VERSION_MINOR); + + pmu_setup_init(); + +#ifdef DO_DDR_PLL_DEBUG + printf("If you want to config the ddr para manully ?(y = yes, n = no) \n"); + choice = serial_getc(); + if (choice == 'y') + { + memcpy(&clock_debug_config, g_clock_config, + sizeof(clock_debug_config)); + g_clock_config = &clock_debug_config; + pmu_setup_calibration_voltage(1); + pmu_buck4_buck3_choose(); + freq_choose(); + data_bits_choose(); + clock_load_ddr_cal_config(); + } +#endif + + sys_shutdown_pll(); + ispi_open(0); + pll_setup_init(); +#ifdef DO_DDR_PLL_DEBUG + if (choice == 'y') + cmd_input(); +#endif + pll_setup_freq(); + sys_setup_pll(); + sys_setup_clk(); + + if (g_clock_config->DDR_CAL) { + printf("Init DDR for ddr_cal\n"); + ddr_init(g_clock_config->DDR_FLAGS, g_clock_config->DDR_PARA); + printf("Done\n"); + pll_setup_mem_cal(); + clock_save_config(); + } else { + pll_setup_mem(); + } + + sys_dump_pll_freq(); + sys_dump_clk(); + pll_dump_reg(); + + printf("Init DDR, flag = 0x%04x, para = 0x%08lx\n", + g_clock_config->DDR_FLAGS, g_clock_config->DDR_PARA); + ddr_init(g_clock_config->DDR_FLAGS, g_clock_config->DDR_PARA); + printf("Done\n"); + + #ifdef DO_SIMPLE_DDR_TEST + mem_test_write(); + mem_test_read(); +#endif + + return 0; +} + +#else /* CONFIG_RDA_FPGA */ + +int clock_init(void) +{ + u16 ddr_flags = DDR_FLAGS_DLLOFF + | DDR_FLAGS_ODT(1) + | DDR_FLAGS_RON(0); + //16bit + u32 ddr_para = DDR_PARA_MEM_BITS(2) + | DDR_PARA_BANK_BITS(3) + | DDR_PARA_ROW_BITS(3) + | DDR_PARA_COL_BITS(1); + + printf("Init DDR\n"); + ddr_init(ddr_flags, ddr_para); + printf("Done\n"); + +#ifdef DO_SIMPLE_DDR_TEST + mem_test_write(); + mem_test_read(); +#endif + + return 0; +} + +#endif /* CONFIG_RDA_FPGA */ + diff --git a/board/rda/rda8810h/clock_config.c b/board/rda/rda8810h/clock_config.c new file mode 100644 index 0000000000..85254c90d7 --- /dev/null +++ b/board/rda/rda8810h/clock_config.c @@ -0,0 +1,149 @@ +#ifndef TARGET_TOOL +#include <common.h> +#include <asm/arch/factory.h> +#include "clock_config.h" +#endif + +#include "ddr3.h" +#include "tgt_ap_clock_config.h" + +static const struct clock_config clock_default_config = { + /* Header */ + 0, // MAGIC; + CLOCK_VER_MAJOR, // VERSION_MAJOR; + CLOCK_VER_MINOR, // VERSION_MINOR; + /* PLL Freqs (MHz) */ + _TGT_AP_PLL_CPU_FREQ, // PLL_FREQ_CPU; /* 05, 06 */ + _TGT_AP_PLL_BUS_FREQ, // PLL_FREQ_BUS; /* 25, 26 */ + _TGT_AP_PLL_MEM_FREQ, // PLL_FREQ_MEM; /* 65, 66 */ + _TGT_AP_PLL_USB_FREQ, // PLL_FREQ_USB; /* 85, 86 */ + /* DDR Cal */ + 0, // DDR_CAL; + /* DDR_FLAGS */ + DDR_FLAGS_ODT(_TGT_AP_DDR_ODT) // 010 -- 120 Ohm +#if (_TGT_AP_DDR_CLOCK < 200) + | DDR_FLAGS_DLLOFF +#endif +#ifdef _TGT_AP_DDR_LOWPWR + | DDR_FLAGS_LOWPWR +#endif + | DDR_FLAGS_RON(_TGT_AP_DDR_RON), // 00 -- 40 Ohm + /* DDR_PARA */ + DDR_PARA_CHIP_BITS(_TGT_AP_DDR_CHIP_BITS) + | DDR_PARA_MEM_BITS(_TGT_AP_DDR_MEM_BITS) + | DDR_PARA_BANK_BITS(_TGT_AP_DDR_BANK_BITS) + | DDR_PARA_ROW_BITS(_TGT_AP_DDR_ROW_BITS ) + | DDR_PARA_COL_BITS(_TGT_AP_DDR_COL_BITS), + + /* AP sysctrl */ + _TGT_AP_CLK_CPU, // CLK_CPU; + _TGT_AP_CLK_AXI, // CLK_AXI; + _TGT_AP_CLK_GCG, // CLK_GCG; + _TGT_AP_CLK_AHB1, // CLK_AHB1; + _TGT_AP_CLK_APB1, // CLK_APB1; + _TGT_AP_CLK_APB2, // CLK_APB2; + _TGT_AP_CLK_MEM, // CLK_MEM; + _TGT_AP_CLK_GPU, // CLK_GPU; + _TGT_AP_CLK_VPU, // CLK_VPU; + _TGT_AP_CLK_VOC, // CLK_VOC; + _TGT_AP_CLK_SFLSH, // CLK_SFLSH; + 0, // RESERVE; + + /* DDR timings, defined in target */ + DDR_CHAN_1_VALID_VAL, // DDR_CHAN_1_VALID; + DDR_TIMING_100H_VAL, // DDR_TIMING_100H; + DDR_TIMING_101H_VAL, // DDR_TIMING_101H; + DDR_TIMING_102H_VAL, // DDR_TIMING_102H; + DDR_TIMING_103H_VAL, // DDR_TIMING_103H; + DDR_TIMING_104H_VAL, // DDR_TIMING_104H; + DDR_TIMING_105H_VAL, // DDR_TIMING_105H; + DDR_TIMING_106H_VAL, // DDR_TIMING_106H; + DDR_TIMING_107H_VAL, // DDR_TIMING_107H; + DDR_TIMING_108H_VAL, // DDR_TIMING_108H; + DDR_TIMING_109H_VAL, // DDR_TIMING_109H; + DDR_TIMING_10AH_VAL, // DDR_TIMING_10AH; + DDR_TIMING_10BH_VAL, // DDR_TIMING_10BH; + DDR_TIMING_10CH_VAL, // DDR_TIMING_10CH; + DDR_TIMING_10DH_VAL, // DDR_TIMING_10DH; + DDR_TIMING_10EH_VAL, // DDR_TIMING_10EH; + DDR_TIMING_10FH_VAL, // DDR_TIMING_10FH; + + DDR_CHAN_2_VALID_VAL, // DDR_CHAN_2_VALID; + DDR_TIMING_120H_VAL, // DDR_TIMING_120H; + DDR_TIMING_121H_VAL, // DDR_TIMING_121H; + DDR_TIMING_122H_VAL, // DDR_TIMING_122H; + DDR_TIMING_123H_VAL, // DDR_TIMING_123H; + DDR_TIMING_124H_VAL, // DDR_TIMING_124H; + DDR_TIMING_125H_VAL, // DDR_TIMING_125H; + DDR_TIMING_126H_VAL, // DDR_TIMING_126H; + DDR_TIMING_127H_VAL, // DDR_TIMING_127H; + DDR_TIMING_128H_VAL, // DDR_TIMING_128H; + DDR_TIMING_129H_VAL, // DDR_TIMING_129H; + DDR_TIMING_12AH_VAL, // DDR_TIMING_12AH; + DDR_TIMING_12BH_VAL, // DDR_TIMING_12BH; + DDR_TIMING_12CH_VAL, // DDR_TIMING_12CH; + DDR_TIMING_12DH_VAL, // DDR_TIMING_12DH; + DDR_TIMING_12EH_VAL, // DDR_TIMING_12EH; + DDR_TIMING_12FH_VAL, // DDR_TIMING_12FH; + + DDR_CHAN_3_VALID_VAL, // DDR_CHAN_3_VALID; + DDR_TIMING_140H_VAL, // DDR_TIMING_140H; + DDR_TIMING_141H_VAL, // DDR_TIMING_141H; + DDR_TIMING_142H_VAL, // DDR_TIMING_142H; + DDR_TIMING_143H_VAL, // DDR_TIMING_143H; + DDR_TIMING_144H_VAL, // DDR_TIMING_144H; + DDR_TIMING_145H_VAL, // DDR_TIMING_145H; + DDR_TIMING_146H_VAL, // DDR_TIMING_146H; + DDR_TIMING_147H_VAL, // DDR_TIMING_147H; + DDR_TIMING_148H_VAL, // DDR_TIMING_148H; + DDR_TIMING_149H_VAL, // DDR_TIMING_149H; + DDR_TIMING_14AH_VAL, // DDR_TIMING_14AH; + DDR_TIMING_14BH_VAL, // DDR_TIMING_14BH; + DDR_TIMING_14CH_VAL, // DDR_TIMING_14CH; + DDR_TIMING_14DH_VAL, // DDR_TIMING_14DH; + DDR_TIMING_14EH_VAL, // DDR_TIMING_14EH; + DDR_TIMING_14FH_VAL, // DDR_TIMING_14FH; + + DDR_CHAN_4_VALID_VAL, // DDR_CHAN_4_VALID; + DDR_TIMING_160H_VAL, // DDR_TIMING_160H; + DDR_TIMING_161H_VAL, // DDR_TIMING_161H; + DDR_TIMING_162H_VAL, // DDR_TIMING_162H; + DDR_TIMING_163H_VAL, // DDR_TIMING_163H; + DDR_TIMING_164H_VAL, // DDR_TIMING_164H; + DDR_TIMING_165H_VAL, // DDR_TIMING_165H; + DDR_TIMING_166H_VAL, // DDR_TIMING_166H; + DDR_TIMING_167H_VAL, // DDR_TIMING_167H; + DDR_TIMING_168H_VAL, // DDR_TIMING_168H; + DDR_TIMING_169H_VAL, // DDR_TIMING_169H; + DDR_TIMING_16AH_VAL, // DDR_TIMING_16AH; + DDR_TIMING_16BH_VAL, // DDR_TIMING_16BH; + DDR_TIMING_16CH_VAL, // DDR_TIMING_16CH; + DDR_TIMING_16DH_VAL, // DDR_TIMING_16DH; + DDR_TIMING_16EH_VAL, // DDR_TIMING_16EH; + DDR_TIMING_16FH_VAL, // DDR_TIMING_16FH; + + DDR_TIMING_180H_VAL, // DDR_TIMING_180H; + DDR_TIMING_181H_VAL, // DDR_TIMING_181H; + DDR_TIMING_182H_VAL, // DDR_TIMING_182H; + DDR_TIMING_183H_VAL, // DDR_TIMING_183H; + DDR_TIMING_184H_VAL, // DDR_TIMING_184H; + DDR_TIMING_185H_VAL, // DDR_TIMING_185H; + DDR_TIMING_186H_VAL, // DDR_TIMING_186H; + DDR_TIMING_187H_VAL, // DDR_TIMING_187H; + DDR_TIMING_188H_VAL, // DDR_TIMING_188H; + DDR_TIMING_189H_VAL, // DDR_TIMING_189H; + DDR_TIMING_18AH_VAL, // DDR_TIMING_18AH; + DDR_TIMING_18BH_VAL, // DDR_TIMING_18BH; + DDR_TIMING_18CH_VAL, // DDR_TIMING_18CH; + DDR_TIMING_069H_VAL // DDR_TIMING_18CH; +}; + +const struct clock_config *get_default_clock_config(void) +{ +#ifndef TARGET_TOOL + BUILD_BUG_ON(sizeof(struct clock_config) > AP_FACTORY_CLOCK_CFG_LEN); +#endif + + return &clock_default_config; +} + diff --git a/board/rda/rda8810h/clock_config.h b/board/rda/rda8810h/clock_config.h new file mode 100644 index 0000000000..3e472df08d --- /dev/null +++ b/board/rda/rda8810h/clock_config.h @@ -0,0 +1,132 @@ +#ifndef __CLOCK_CONFIG_H__ +#define __CLOCK_CONFIG_H__ + +typedef unsigned long UINT32; +typedef unsigned short UINT16; +typedef long INT32; +typedef short INT16; +typedef unsigned char UINT8; +typedef char INT8; + +#define CLOCK_VER_MAJOR 2 +#define CLOCK_VER_MINOR 0 + +struct clock_config { + /* Header */ + UINT32 MAGIC; + UINT16 VERSION_MAJOR; + UINT16 VERSION_MINOR; + /* PLL Freqs (MHz) */ + UINT32 PLL_FREQ_CPU; /* 05, 06 */ + UINT32 PLL_FREQ_BUS; /* 25, 26 */ + UINT32 PLL_FREQ_MEM; /* 65, 66 */ + UINT32 PLL_FREQ_USB; /* 85, 86 */ + /* DDR Flags */ + UINT16 DDR_CAL; + UINT16 DDR_FLAGS; + UINT32 DDR_PARA; + /* AP sysctrl */ + UINT16 CLK_CPU; + UINT16 CLK_AXI; + UINT16 CLK_GCG; + UINT16 CLK_AHB1; + UINT16 CLK_APB1; + UINT16 CLK_APB2; + UINT16 CLK_MEM; + UINT16 CLK_GPU; + UINT16 CLK_VPU; + UINT16 CLK_VOC; + UINT16 CLK_SFLSH; + UINT16 RESERVE; + /* DDR timings */ + UINT16 DDR_CHAN_1_VALID; + UINT16 DDR_TIMING_100H; + UINT16 DDR_TIMING_101H; + UINT16 DDR_TIMING_102H; + UINT16 DDR_TIMING_103H; + UINT16 DDR_TIMING_104H; + UINT16 DDR_TIMING_105H; + UINT16 DDR_TIMING_106H; + UINT16 DDR_TIMING_107H; + UINT16 DDR_TIMING_108H; + UINT16 DDR_TIMING_109H; + UINT16 DDR_TIMING_10AH; + UINT16 DDR_TIMING_10BH; + UINT16 DDR_TIMING_10CH; + UINT16 DDR_TIMING_10DH; + UINT16 DDR_TIMING_10EH; + UINT16 DDR_TIMING_10FH; + + UINT16 DDR_CHAN_2_VALID; + UINT16 DDR_TIMING_120H; + UINT16 DDR_TIMING_121H; + UINT16 DDR_TIMING_122H; + UINT16 DDR_TIMING_123H; + UINT16 DDR_TIMING_124H; + UINT16 DDR_TIMING_125H; + UINT16 DDR_TIMING_126H; + UINT16 DDR_TIMING_127H; + UINT16 DDR_TIMING_128H; + UINT16 DDR_TIMING_129H; + UINT16 DDR_TIMING_12AH; + UINT16 DDR_TIMING_12BH; + UINT16 DDR_TIMING_12CH; + UINT16 DDR_TIMING_12DH; + UINT16 DDR_TIMING_12EH; + UINT16 DDR_TIMING_12FH; + + UINT16 DDR_CHAN_3_VALID; + UINT16 DDR_TIMING_140H; + UINT16 DDR_TIMING_141H; + UINT16 DDR_TIMING_142H; + UINT16 DDR_TIMING_143H; + UINT16 DDR_TIMING_144H; + UINT16 DDR_TIMING_145H; + UINT16 DDR_TIMING_146H; + UINT16 DDR_TIMING_147H; + UINT16 DDR_TIMING_148H; + UINT16 DDR_TIMING_149H; + UINT16 DDR_TIMING_14AH; + UINT16 DDR_TIMING_14BH; + UINT16 DDR_TIMING_14CH; + UINT16 DDR_TIMING_14DH; + UINT16 DDR_TIMING_14EH; + UINT16 DDR_TIMING_14FH; + + UINT16 DDR_CHAN_4_VALID; + UINT16 DDR_TIMING_160H; + UINT16 DDR_TIMING_161H; + UINT16 DDR_TIMING_162H; + UINT16 DDR_TIMING_163H; + UINT16 DDR_TIMING_164H; + UINT16 DDR_TIMING_165H; + UINT16 DDR_TIMING_166H; + UINT16 DDR_TIMING_167H; + UINT16 DDR_TIMING_168H; + UINT16 DDR_TIMING_169H; + UINT16 DDR_TIMING_16AH; + UINT16 DDR_TIMING_16BH; + UINT16 DDR_TIMING_16CH; + UINT16 DDR_TIMING_16DH; + UINT16 DDR_TIMING_16EH; + UINT16 DDR_TIMING_16FH; + + UINT16 DDR_TIMING_180H; + UINT16 DDR_TIMING_181H; + UINT16 DDR_TIMING_182H; + UINT16 DDR_TIMING_183H; + UINT16 DDR_TIMING_184H; + UINT16 DDR_TIMING_185H; + UINT16 DDR_TIMING_186H; + UINT16 DDR_TIMING_187H; + UINT16 DDR_TIMING_188H; + UINT16 DDR_TIMING_189H; + UINT16 DDR_TIMING_18AH; + UINT16 DDR_TIMING_18BH; + UINT16 DDR_TIMING_18CH; + UINT16 DDR_TIMING_069H; +}; + +const struct clock_config *get_default_clock_config(void); + +#endif diff --git a/board/rda/rda8810h/config.mk b/board/rda/rda8810h/config.mk new file mode 100644 index 0000000000..39782ba05e --- /dev/null +++ b/board/rda/rda8810h/config.mk @@ -0,0 +1,15 @@ +# +#the spl code should not exceed the SPL_MAX_SIZE,and if +#the spl don't up to the max size, paddint the last with +#zero(or 0xff?) + +#48kbytes, 48*1024 +#SPL_APPENDING_TO := 48 +#SPL_MAX_SIZE := 49512 + +# space for spl(48KiB) & mtd partition table(4KiB), +# so uboot offset 52KiB(48 + 4). + +SPL_APPENDING_TO := 52 + +CONFIG_SPL_SIGNATURE_CHECK_IMAGE := y diff --git a/board/rda/rda8810h/ddr3.c b/board/rda/rda8810h/ddr3.c new file mode 100644 index 0000000000..a0f49e6efe --- /dev/null +++ b/board/rda/rda8810h/ddr3.c @@ -0,0 +1,533 @@ +#include <common.h> +#include <asm/arch/rda_iomap.h> + +#include "ddr3.h" +#include "ddr3_init.h" +#include "tgt_ap_clock_config.h" + +#pragma GCC push_options +#pragma GCC optimize ("O0") + +#define DDR_TYPE _TGT_AP_DDR_TYPE + +#define DF_DELAY (0x10000) + +#define DMC_REG_BASE RDA_DMC400_BASE +#define PHY_REG_BASE RDA_DDRPHY_BASE + +#define PHY_RDLAT 0 +#define PHYWRDATA 1 +#define STA 3 +#define CLKSEL 4 +#define PSSTART 5 +#define PSDONE 6 +#define LOCKED 6 +#define CTRL_DELAY 7 +#define RDELAY_SEL 8 +#define WDELAY_SEL 9 +#define PHY_RESET 10 +#define RESET_DDR3 11 +#define ODT_DELAY 12 +#define DDR3_USED 13 +#define WRITE_ENABLE_LAT 14 +#define WRITE_DATA_LAT 15 +#define DQOUT_ENABLE_LAT 16 +#define DATA_ODT_ENABLE_REG 20 +#define DATA_WRITE_ENABLE_REG 48 +#define DMC_READY 128 +#define USE_ADDR 129 + +#define ARRAY_NUM(n) (sizeof(n))/(sizeof(n[0])) + +#if (DDR_TYPE == 1) +static dmc_reg_t dmc_reg_cfg[] = { + {T_REFI, 0x186, 0x186}, + {T_RFC, 0x230024, 0x230024}, + {T_RFC, 0x540024, 0x540024}, + {T_MRR, 0x2, 0x2}, + {T_MRW, 0x5, 0x5}, + {T_RCD, 0x8, 0x8}, + {T_RAS, 0x11, 0x11}, + {T_RP, 0x8, 0x8}, + {T_RPALL, 0x9, 0x9}, + {T_RRD, 0x4, 0x4}, + {T_FAW, 0x14, 0x14}, + {T_RTR, 0x4, 0x4}, + {T_RTW, 0xb, 0xb}, + {T_RTP, 0x6, 0x6}, + {T_WR, 0xe, 0xe}, + {T_WTR, 0x4000b, 0x4000b}, + {T_WTR, 0x4000b, 0x4000b}, + {T_WTW, 0x40000, 0x40000}, + {RD_LATENCY, 0x6, 0x6}, + {WR_LATENCY, 0x3, 0x3}, + {T_RDDATA_EN, 0x3, 0x3}, + {T_PHYWRLAT, 0x101, 0x101}, + {T_PHYWRLAT, 0x101, 0x101}, + {T_XP, 0x20003, 0x20003}, + {T_XP, 0x80003, 0x80003}, + {T_ESR, 0x6, 0x6}, + {T_XSR, 0x1000058, 0x1000058}, + {T_XSR, 0x580058, 0x580058}, + {T_SRCKD, 0x5, 0x5}, + {T_CKSRD, 0x5, 0x5}, + {T_ECKD, 0x5, 0x5}, + {T_XCKD, 0x5, 0x5}, + {T_EP, 0x5, 0x5}, + {RDLVL_CTRL, 0x1010, 0x1010}, + {RDLVL_CTRL, 0x1110, 0x1110}, + {RDLVL_CTRL, 0x11110, 0x11110}, + {REFRESH_CTRL, 0x0, 0x0}, + {REFRESH_CTRL, 0x0, 0x0}, + {ECC_CTRL, 0x0, 0x0}, + {ADDR_CTRL, 0x30200, 0x30200}, + {ADDR_CTRL, 0x30200, 0x30200}, + {ADDR_CTRL, 0x30200, 0x30200}, +}; +#elif (DDR_TYPE == 2) +static dmc_reg_t dmc_reg_cfg[] = { + {T_REFI, 0x3f, 0x3f}, + {T_RFC, 0x230024, 0x230024}, + {T_RFC, 0x540024, 0x540024}, + {T_MRR, 0x3f, 0x3f}, + {T_MRW, 0x3f, 0x3f}, + {T_RCD, 0x8, 0x8}, + {T_RAS, 0x11, 0x11}, + {T_RP, 0x8, 0x8}, + {T_RPALL, 0x9, 0x9}, + {T_RRD, 0x4, 0x4}, + {T_FAW, 0x14, 0x14}, + {T_RTR, 0xf, 0xf}, + {T_RTW, 0x1f, 0x1f}, + {T_RTP, 0x6, 0x6}, + {T_WR, 0xe, 0xe}, + {T_WTR, 0x4001f, 0x4001f}, + {T_WTR, 0x4001f, 0x4001f}, + {T_WTW, 0x40000, 0x40000}, + {RD_LATENCY, 0x8, 0x8}, + {WR_LATENCY, 0x4, 0x4}, + {T_RDDATA_EN, 0x8, 0x8}, + {T_PHYWRLAT, 0x103, 0x103}, + {T_PHYWRLAT, 0x103, 0x103}, + {T_XP, 0x20003, 0x20003}, + {T_XP, 0x80003, 0x80003}, + {T_ESR, 0x6, 0x6}, + {T_XSR, 0x1000058, 0x1000058}, + {T_XSR, 0x580058, 0x580058}, + {T_SRCKD, 0x5, 0x5}, + {T_CKSRD, 0x5, 0x5}, + {T_ECKD, 0x5, 0x5}, + {T_XCKD, 0x5, 0x5}, + {T_EP, 0x5, 0x5}, + {RDLVL_CTRL, 0x1010, 0x1010}, + {RDLVL_CTRL, 0x1110, 0x1110}, + {RDLVL_CTRL, 0x11110, 0x11110}, + {REFRESH_CTRL, 0x1, 0x1}, + {ECC_CTRL, 0x0, 0x0}, + {QOSX_CTRL7, 0x0f, 0x0f}, + {TURNAROUND_PRIO,0x1A, 0x1A}, + {HIT_PRIO, 0x1A, 0x1A}, + {ADDR_CTRL, 0x30200, 0x30200}, + {ADDR_CTRL, 0x30200, 0x30200}, + {ADDR_CTRL, 0x30200, 0x30200}, +}; +#elif (DDR_TYPE == 3) +static dmc_reg_t dmc_reg_cfg[] = { + {QOSX_CTRL7, 0x08, 0x08}, + {TURNAROUND_PRIO,0x1A, 0x0}, + {HIT_PRIO, 0x1A, 0x0}, + {T_REFI, 0x186, 0x3f}, + {QUEUE_CTRL, 0xffff, 0x0}, + {T_RFC, 0x23008c, 0x23008c}, + {T_RFC, 0x8c008c, 0x8c008c}, + {T_MRR, 0x4, 0x4}, + {T_MRW, 0xc, 0xc}, + {T_RCD, 0x6, 0x6}, + {T_RAS, 0xf, 0xf}, + {T_RP, 0x6, 0x6}, + {T_RPALL, 0x6, 0x5}, + {T_RRD, 0x4, 0x4}, + {T_FAW, 0x14, 0x14}, + {T_RTR, 0x6, 0x6}, +// {T_RTW, 0x7, 0x6}, + {T_RTW, 0x0c, 0x6},// turn for now + {T_RTW, 0x1f, 0x1f},//for low speed + {T_RTP, 0x4, 0x4}, + {T_WR, 0xf, 0x10}, + {T_WTR, 0x4000d, 0x4000d}, + {T_WTR, 0x6000d, 0x6000f}, +// {T_WTR, 0x6001f, 0x6001f},//for low speed + {T_WTW, 0x60000, 0x60000}, + {RD_LATENCY, 0x5, 0x5}, + {WR_LATENCY, 0x5, 0x5}, + {T_RDDATA_EN, 0x8, 0x3}, + {T_PHYWRLAT, 0x102, 0x102}, + {T_PHYWRLAT, 0x102, 0x103}, + {T_EP, 0x3, 0x3}, + {T_XP, 0x20003, 0x20003}, + {T_XP, 0xa0003, 0xa0003}, + {T_ESR, 0x4, 0x4}, + {T_XSR, 0x1000090, 0x1000090}, + {T_XSR, 0x2000090, 0x2000090}, + {T_SRCKD, 0x5, 0x5}, + {T_CKSRD, 0x5, 0x5}, + {T_ECKD, 0x5, 0x5}, + {T_XCKD, 0x5, 0x5}, + {ECC_CTRL, 0x0, 0x0}, + {ADDR_CTRL, 0x30200, 0x30200}, + {ADDR_CTRL, 0x30200, 0x30200}, + {ADDR_CTRL, 0x30200, 0x30200}, +}; +#else +#error "Wrong DDR Type" +#endif + +void config_ddr_phy(UINT16 flag) +{ + int wait_idle; + UINT16 __attribute__((unused)) dll_off; + + wait_idle = DF_DELAY + 16; + dll_off = flag & DDR_FLAGS_DLLOFF; + + while (wait_idle--); + +#if (DDR_TYPE == 1) + *((volatile UINT32*)(PHY_REG_BASE + CTRL_DELAY * 4)) = 1; + printf("ddr1 phy init done!\n"); +#elif (DDR_TYPE ==2) + *((volatile UINT32*)(PHY_REG_BASE + USE_ADDR * 4)) = 0; + *((volatile UINT32*)(PHY_REG_BASE + DATA_WRITE_ENABLE_REG *4)) = 0xf; + *((volatile UINT32*)(PHY_REG_BASE + DATA_ODT_ENABLE_REG *4)) = 0xf; + *((volatile UINT32*)(PHY_REG_BASE + WRITE_DATA_LAT *4)) = 0x0; + *((volatile UINT32*)(PHY_REG_BASE + WRITE_ENABLE_LAT *4)) = 0x0; + *((volatile UINT32*)(PHY_REG_BASE + WDELAY_SEL *4)) = 0x7; + *((volatile UINT32*)(PHY_REG_BASE + RDELAY_SEL *4)) = 0x6; + *((volatile UINT32*)(PHY_REG_BASE + DQOUT_ENABLE_LAT *4)) = 0x1; + printf("ddr2 phy init done!\n"); +#else + *((volatile UINT32*)(PHY_REG_BASE + DMC_READY *4)) = 0x0; + *((volatile UINT32*)(PHY_REG_BASE + RESET_DDR3 * 4)) = 1; + + if (dll_off) + *((volatile UINT32*)(PHY_REG_BASE + WRITE_DATA_LAT * 4)) = 1; + + *((volatile UINT32*)(PHY_REG_BASE + DDR3_USED * 4)) = 1; + *((volatile UINT32*)(PHY_REG_BASE + WDELAY_SEL * 4)) = 3; + + if (!dll_off){ + *((volatile UINT32*)(PHY_REG_BASE + PHY_RDLAT * 4)) = 7; + *((volatile UINT32*)(PHY_REG_BASE + CTRL_DELAY * 4)) =2; + *((volatile UINT32*)(PHY_REG_BASE + WRITE_ENABLE_LAT * 4)) =2; + *((volatile UINT32*)(PHY_REG_BASE + WRITE_DATA_LAT * 4)) = 3; + *((volatile UINT32*)(PHY_REG_BASE + DQOUT_ENABLE_LAT * 4)) = 3; + }else + *((volatile UINT32*)(PHY_REG_BASE + DQOUT_ENABLE_LAT * 4)) = 1; + + *((volatile UINT32*)(PHY_REG_BASE + DATA_ODT_ENABLE_REG *4)) = 0xf; + *((volatile UINT32*)(PHY_REG_BASE + DATA_WRITE_ENABLE_REG *4)) = 0xf; + + serial_puts("ddr3 phy init done!\n"); +#endif +} + +void config_dmc400(UINT16 flag, UINT32 para) +{ + int i, wait_idle; + UINT32 val, tmp; + volatile UINT32 *addr; + UINT16 __attribute__((unused)) dll_off, lpw, odt, ron; + UINT32 mem_width, col_bits, row_bits, bank_bits; + + dll_off = flag & DDR_FLAGS_DLLOFF; + lpw = flag & DDR_FLAGS_LOWPWR; + odt = (flag & DDR_FLAGS_ODT_MASK) >> DDR_FLAGS_ODT_SHIFT; + ron = (flag & DDR_FLAGS_RON_MASK) >> DDR_FLAGS_RON_SHIFT; + mem_width = (para & DDR_PARA_MEM_BITS_MASK) >> DDR_PARA_MEM_BITS_SHIFT; + bank_bits = (para & DDR_PARA_BANK_BITS_MASK) >> DDR_PARA_BANK_BITS_SHIFT; + row_bits = (para & DDR_PARA_ROW_BITS_MASK) >> DDR_PARA_ROW_BITS_SHIFT; + col_bits = (para & DDR_PARA_COL_BITS_MASK) >> DDR_PARA_COL_BITS_SHIFT; + + + wait_idle = 0x4e; + while (wait_idle--); + + for (i=0; i<ARRAY_NUM(dmc_reg_cfg); i++) { + addr = (volatile UINT32*)(DMC_REG_BASE + dmc_reg_cfg[i].reg_offset); + if (dll_off) + val = dmc_reg_cfg[i].dll_off_val; + else + val = dmc_reg_cfg[i].dll_on_val; + + *addr = val; + wait_idle = 0x5; + while (wait_idle--); + } + +#if (DDR_TYPE == 3) + //config low power control register + if (lpw) { + addr = (volatile UINT32*)(DMC_REG_BASE + LOWPWR_CTRL);//0x20 + *addr = 0x48; + wait_idle = 0x5; + while (wait_idle--); + + addr = (volatile UINT32*)(DMC_REG_BASE + T_ESR);//0x260 + *addr = 0xa; + wait_idle = 0x5; + while (wait_idle--); + + addr = (volatile UINT32*)(DMC_REG_BASE + T_XSR);//0x264 + *addr = 0x200; + wait_idle = 0x5; + while (wait_idle--); + + addr = (volatile UINT32*)(DMC_REG_BASE + T_SRCKD);//0x268 + *addr = 0xa; + wait_idle = 0x5; + while (wait_idle--); + + addr = (volatile UINT32*)(DMC_REG_BASE + T_CKSRD);//0x26C + *addr = 0xa; + wait_idle = 0x5; + while (wait_idle--); + } +#elif (DDR_TYPE == 2) + addr = (volatile UINT32*)(DMC_REG_BASE + LOWPWR_CTRL);//0x20 + *addr = 0x38; + wait_idle = 0x5; + while (wait_idle--); +#endif + + //config format control register + addr = (volatile UINT32*)(DMC_REG_BASE + FORMAT_CTRL); + val = *addr; + val &= ~0xf; + if (mem_width == 2) + val |= 0x2; //for 32bit DDR + else if ((mem_width == 1) || (mem_width == 0)) + val |= 0x1; //for 16bit & 8bit DDR + else + printf("unsupported DDR width: %lx\n", mem_width); + *addr = val; + + printf("format ctrl value: %lx\n", val); + + wait_idle = 0x1d; + while (wait_idle--); + + //config address control register + addr = (volatile UINT32*)(DMC_REG_BASE + ADDR_CTRL); + if (mem_width == 2) + tmp = col_bits; //for 32bit + else if (mem_width == 1) + tmp = col_bits - 1; //for 16bit + else if (mem_width == 0) + tmp = col_bits - 2; //for 8bit + else { + printf("unsupported DDR width: %lx\n", mem_width); + tmp = col_bits; + } + val = (bank_bits << 16) | (row_bits << 8) | tmp; + + *addr = val; + + printf("address ctrl value: %lx\n", val); + wait_idle = 0x5; + while (wait_idle--); + + //config decode control register + addr = (volatile UINT32*)(DMC_REG_BASE + DECODE_CTRL); + tmp = 12 - (8 + col_bits + mem_width); + if (tmp < 8) + val = tmp << 4; + else + printf("unsupported stripe decode: %lx\n", tmp); + *addr = val; + + printf("decode ctrl value: %lx\n", val); + wait_idle = 0x6; + while (wait_idle--); + + wait_idle = DF_DELAY; + while (wait_idle--); + addr = (volatile UINT32*)(DMC_REG_BASE + DIRECT_CMD); + *addr = 0x0; + wait_idle = DF_DELAY + 0x10; + while (wait_idle--); + + addr = (volatile UINT32*)(DMC_REG_BASE + DIRECT_CMD); +#if (DDR_TYPE == 1) + val = 0; +#elif (DDR_TYPE == 2) + val = 0; +#else + //config MR2 + if (dll_off) + val = 0x10020008; + else + val = 0x10020000; +#endif + *addr = val; + wait_idle = DF_DELAY + 0x10; + while (wait_idle--); + + addr = (volatile UINT32*)(DMC_REG_BASE + DIRECT_CMD); +#if (DDR_TYPE == 1) + val = 0x20000000; +#elif (DDR_TYPE == 2) + val = 0x1000003f; +#else + //config MR3 + val = 0x10030000; +#endif + *addr = val; + wait_idle = DF_DELAY + 0x10; + while (wait_idle--); + + addr = (volatile UINT32*)(DMC_REG_BASE + DIRECT_CMD); +#if (DDR_TYPE == 1) + val = 0x30000000; +#elif (DDR_TYPE == 2) + val = 0x1000ff0a; +#else + //config MR1 ODT [9,6,2] RON [5,1] DLLOFF [0] + val = 0x10010000; + val |= (odt & 0x4)<<7 | (odt & 0x2)<<5 | (odt & 0x1)<<2; + val |= (ron & 0x2)<<4 | (ron & 0x1)<<1; + if (dll_off) + val |= 0x1; +#endif + *addr = val; + wait_idle = DF_DELAY + 0x10; + while (wait_idle--); + + addr = (volatile UINT32*)(DMC_REG_BASE + DIRECT_CMD); +#if (DDR_TYPE == 1) + val = 0x30000000; +#elif (DDR_TYPE == 2) + val = 0x10008301; +#else + //config MR0 + val = 0x10000520; +#endif + *addr = val; + wait_idle = DF_DELAY + 0x10; + while (wait_idle--); + + addr = (volatile UINT32*)(DMC_REG_BASE + DIRECT_CMD); +#if (DDR_TYPE == 1) + val = 0x10000033; +#elif (DDR_TYPE == 2) + val = 0x10000602;//0ld 0x10000102 +#else + val = 0x50000400; +#endif + *addr = val; + wait_idle = DF_DELAY + 0x10; + while (wait_idle--); + +#if (DDR_TYPE == 2) + addr = (volatile UINT32*)(DMC_REG_BASE + DIRECT_CMD); + val = 0x10000103;//0ld 0x10000102 + *addr = val; + wait_idle = DF_DELAY + 0x10; + while (wait_idle--); +#endif + + addr = (volatile UINT32*)(DMC_REG_BASE + DIRECT_CMD); +#if (DDR_TYPE == 1) + val = 0x10020000; +#elif (DDR_TYPE == 2) + val = 0x30000000; +#else + val = 0x30000000; +#endif + *addr = val; + wait_idle = DF_DELAY + 0x10; + while (wait_idle--); + +#if (DDR_TYPE == 2) +/* zhangli for MCP */ + addr = (volatile UINT32*)(DMC_REG_BASE + DIRECT_CMD); + *addr = 0x10000103; + wait_idle = DF_DELAY + 0x9; + while (wait_idle--); +#endif + +#if (DDR_TYPE == 2) + addr = (volatile UINT32*)(DMC_REG_BASE + MEMC_CMD); + val = 0x4; + *addr = val; +#endif + + //config ECC control + wait_idle = 0x6; + while (wait_idle--); + addr = (volatile UINT32*)(DMC_REG_BASE + ECC_CTRL); + val = 0x0; + *addr = val; + wait_idle = 0x8; + while (wait_idle--); + + //config MEMC CMD + addr = (volatile UINT32*)(DMC_REG_BASE + MEMC_CMD); + val = 0x3; + *addr = val; + + //READ MEMC STATUS + addr = (volatile UINT32*)(DMC_REG_BASE + MEMC_STATUS); + val = 0; + do { + val = *addr; + //printf("MEMC_STATUS value: %x\n", val); + } while (val != 3); +} + +void axi_prio_init(void) +{ + *(volatile UINT32*)(0x20900100) = 0xaa0000aa; + *(volatile UINT32*)(0x21054100) = 0x00000008; + *(volatile UINT32*)(0x21054104) = 0x00000008; +} + +void axi_outstandings_init(void) +{ + *(volatile UINT32*)(0x2104210C) = 0x00000060; + *(volatile UINT32*)(0x21042110) = 0x00000300; +} + +int ddr_init(UINT16 flags, UINT32 para) +{ + UINT16 dll_off; + UINT32 mem_width; + + axi_prio_init(); + //axi_outstandings_init(); + + dll_off = flags & DDR_FLAGS_DLLOFF; + mem_width = (para & DDR_PARA_MEM_BITS_MASK) >> DDR_PARA_MEM_BITS_SHIFT; + + switch (mem_width) { + case 0: + printf("8bit "); + break; + case 1: + printf("16bit "); + break; + case 2: + printf("32bit "); + break; + } + if (dll_off) + printf("dll-off Mode ...\n"); + else + printf("dll-on Mode ...\n"); + + config_ddr_phy(flags); + config_dmc400(flags, para); + printf("dram init done ...\n"); + + return 0; +} + diff --git a/board/rda/rda8810h/ddr3.h b/board/rda/rda8810h/ddr3.h new file mode 100644 index 0000000000..7481954144 --- /dev/null +++ b/board/rda/rda8810h/ddr3.h @@ -0,0 +1,50 @@ +#ifndef _SYS_DDR3_H_ +#define _SYS_DDR3_H_ + +#include "clock_config.h" + +/* + * defination of ddr flags + */ +/* [Debug] DLL off mode, 0 is dll on mode */ +#define DDR_FLAGS_DLLOFF 0x8000 +/* [Debug] LowSpeed mode*/ +#define DDR_FLAGS_RESERVE 0x4000 +/* DDR LowPower mode */ +#define DDR_FLAGS_LOWPWR 0x2000 +/* ODT: 000--Null 001--60 010--120 011--40 100--20 101--30 */ +#define DDR_FLAGS_ODT(n) (((n)<<0)&0x0007) +#define DDR_FLAGS_ODT_SHIFT 0 +#define DDR_FLAGS_ODT_MASK 0x0007 +/* RON: 00--40 01--30 */ +#define DDR_FLAGS_RON(n) (((n)<<3)&0x0018) +#define DDR_FLAGS_RON_SHIFT 3 +#define DDR_FLAGS_RON_MASK 0x0018 + +/* + * defination of ddr parameters + */ +#define DDR_PARA_CHIP_BITS(n) (((n)<<0)&0x00000003) +#define DDR_PARA_CHIP_BITS_SHIFT 0 +#define DDR_PARA_CHIP_BITS_MASK 0x00000003 +/* memory width 0--8bit 1--16bit 2--32bit */ +#define DDR_PARA_MEM_BITS(n) (((n)<<2)&0x0000000c) +#define DDR_PARA_MEM_BITS_SHIFT 2 +#define DDR_PARA_MEM_BITS_MASK 0x0000000c +/* 2--4banks 3--8banks */ +#define DDR_PARA_BANK_BITS(n) (((n)<<4)&0x000000f0) +#define DDR_PARA_BANK_BITS_SHIFT 4 +#define DDR_PARA_BANK_BITS_MASK 0x000000f0 +/* 2--13rbs 3--14rbs 4--15rbs 5--16rbs */ +#define DDR_PARA_ROW_BITS(n) (((n)<<8)&0x00000f00) +#define DDR_PARA_ROW_BITS_SHIFT 8 +#define DDR_PARA_ROW_BITS_MASK 0x00000f00 +/* 0--8cbs 1--9cbs 2--10cbs 3--11cbs 4--12cbs */ +#define DDR_PARA_COL_BITS(n) (((n)<<12)&0x0000f000) +#define DDR_PARA_COL_BITS_SHIFT 12 +#define DDR_PARA_COL_BITS_MASK 0x0000f000 + +int ddr_init(UINT16 flags, UINT32 para); + +#endif /* _SYS_DDR3_H_ */ + diff --git a/board/rda/rda8810h/ddr3_init.h b/board/rda/rda8810h/ddr3_init.h new file mode 100644 index 0000000000..402375d269 --- /dev/null +++ b/board/rda/rda8810h/ddr3_init.h @@ -0,0 +1,101 @@ +#ifndef _SYS_RAM_INIT_H_ +#define _SYS_RAM_INIT_H_ + +#define MEMC_STATUS 0x000 +#define MEMC_CONFIG 0x004 +#define MEMC_CMD 0x008 +#define ADDR_CTRL 0x010 +#define DECODE_CTRL 0x014 +#define FORMAT_CTRL 0x018 +#define LOWPWR_CTRL 0x020 +#define TURNAROUND_PRIO 0x030 +#define HIT_PRIO 0x034 +//QOS0~QOS15:038~078 +#define QOSX_CTRL 0x038 +#define QOSX_CTRL7 0x058 +#define QOSX_CTRL15 0x078 +#define TIMEOUT_CTRL 0x07C +#define QUEUE_CTRL 0x080 +#define WR_PRIO_CTRL 0x088 +#define WR_PRIO_CTRL2 0x08C +#define RD_PRIO_CTRL 0x090 +#define RD_PRIO_CTRL2 0x094 +#define ACCESS_ADDR_MATCH 0x098 +#define ACCESS_ADDR_MATCH_63_32 0x09C +#define ACCESS_ADDR_MASK 0x0A0 +#define ACCESS_ADDR_MASK_63_32 0x0A4 + +#define CHANNEL_STATUS 0x100 +#define DIRECT_CMD 0x108 +#define MR_DATA 0x110 +#define REFRESH_CTRL 0x120 +#define INTR_CTRL 0x128 +#define INTR_CLR 0x130 +#define INTR_STATUS 0x138 +#define INTR_INFO 0x140 +#define ECC_CTRL 0x148 + +#define T_REFI 0x200 +#define T_RFC 0x204 +#define T_MRR 0x208 +#define T_MRW 0x20C +#define T_RCD 0x218 +#define T_RAS 0x21C +#define T_RP 0x220 +#define T_RPALL 0x224 +#define T_RRD 0x228 +#define T_FAW 0x22C +#define RD_LATENCY 0x230 +#define T_RTR 0x234 +#define T_RTW 0x238 +#define T_RTP 0x23C +#define WR_LATENCY 0x240 +#define T_WR 0x244 +#define T_WTR 0x248 +#define T_WTW 0x24C +#define T_ECKD 0x250 +#define T_XCKD 0x254 +#define T_EP 0x258 +#define T_XP 0x25C +#define T_ESR 0x260 +#define T_XSR 0x264 +#define T_SRCKD 0x268 +#define T_CKSRD 0x26C + +#define T_RDDATA_EN 0x300 +#define T_PHYWRLAT 0x304 +#define RDLVL_CTRL 0x308 +#define RDLVL_DIRECT 0x310 +#define T_RDLVL_EN 0x318 +#define T_RDLVL_RR 0x31C +#define WRLVL_CTRL 0x328 +#define WRLVL_DIRECT 0x330 +#define T_WRLVL_EN 0x338 +#define T_WRLVL_WW 0x33C + +#define PHY_PWR_CTRL 0x348 +#define PHY_UPD_CTRL 0x350 + +#define USER_STATUS 0x400 +#define USER_CONFIG0 0x404 +#define USER_CONFIG1 0x408 + +#define INTEG_CFG 0xE00 +#define INTEG_OUTPUTS 0xE08 + +#define PERIPH_ID_0 0xFE0 +#define PERIPH_ID_1 0xFE4 +#define PERIPH_ID_2 0xFE8 +#define PERIPH_ID_3 0xFEC +#define COMPONENT_ID_0 0xFF0 +#define COMPONENT_ID_1 0xFF4 +#define COMPONENT_ID_2 0xFF8 +#define COMPONENT_ID_3 0xFFC + +typedef struct { + UINT32 reg_offset; + UINT32 dll_on_val; + UINT32 dll_off_val; +} dmc_reg_t; + +#endif /* _SYS_RAM_INIT_H_ */ diff --git a/board/rda/rda8810h/debug.h b/board/rda/rda8810h/debug.h new file mode 100644 index 0000000000..1d4f03bedb --- /dev/null +++ b/board/rda/rda8810h/debug.h @@ -0,0 +1,9 @@ +#ifndef _DEBUG_H_ +#define _DEBUG_H_ + +void print_u8(u8 ch); +void print_u16(u16 data); +void print_u32(u32 data); +void dump_buf(u8 *buf, u32 size); + +#endif /* _DEBUG_H_ */ diff --git a/board/rda/rda8810h/hal_config.c b/board/rda/rda8810h/hal_config.c new file mode 100644 index 0000000000..ade97c4b5a --- /dev/null +++ b/board/rda/rda8810h/hal_config.c @@ -0,0 +1,1451 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright (C) 2013, RDA Microeletronics. // +// All Rights Reserved // +// // +// This source code is the property of RDA Microeletronics and is // +// confidential. Any modification, distribution, reproduction or // +// exploitation of any content of this file is totally forbidden, // +// except with the written permission of RDA Microeletronics. // +// // +//////////////////////////////////////////////////////////////////////////////// +// // +// $HeadURL: http://svn.rdamicro.com/svn/developing1/Sources/chip/branches/8810/hal/8810/src/hal_config.c $ // +// $Author: huazeng $ // +// $Date: 2013-08-31 17:48:58 +0800 (Sat, 31 Aug 2013) $ // +// $Revision: 21005 $ // +// // +//////////////////////////////////////////////////////////////////////////////// +// // +/// @file hal_config.c +/// Implementation of HAL initialization related with the particular instance +/// of the IP. +// // +//////////////////////////////////////////////////////////////////////////////// + +/* uboot */ +#include <common.h> + +/* common */ +#include <asm/arch/rda_iomap.h> +#include <asm/arch/hwcfg.h> +#include <asm/arch/chip_id.h> +#include <asm/arch/cs_types.h> +#include <asm/arch/global_macros.h> +#include <asm/arch/reg_gpio.h> + +/* device */ +#include "hal_sys.h" +#include "halp_sys.h" +#include "halp_gpio.h" +#include "bootp_mode.h" +#include "hal_config.h" +#include "hal_ap_gpio.h" +#include "hal_ap_config.h" +#include <asm/arch/reg_cfg_regs.h> + +/* target */ +#include "tgt_board_cfg.h" +#include "tgt_ap_gpio_setting.h" +#define HAL_ASSERT(cond, fmt, ...) \ + if(!(cond)) { \ + hal_assert(fmt, ##__VA_ARGS__); \ + g_halConfigError = TRUE; \ + } + +//// ============================================================================= +//// GLOBAL VARIABLES +//// ============================================================================= +PRIVATE CONST UINT8 g_halCfgSimOrder[] = { TGT_SIM_ORDER }; +PRIVATE HAL_CFG_CONFIG_T hal_cfg = TGT_HAL_CONFIG; +PRIVATE UINT32 g_bootBootMode = 0; +PRIVATE BOOL g_halConfigError = FALSE; + + +// ============================================================================= +// FUNCTIONS +// ============================================================================= +// HAL_ASSERT +PRIVATE VOID hal_assert(const char *fmt, ...) +{ + va_list args; + puts("\n#-------Board Mux config found error-------#\n"); + va_start(args, fmt); + vprintf(fmt, args); + putc('\n'); + puts("--------------------------------------------\n\n"); + va_end(args); +} + +// ============================================================================= +// hal_BoardSimUsed +// ----------------------------------------------------------------------------- +/// Check whether a SIM card interface is used. +// ============================================================================ +PRIVATE BOOL hal_BoardSimUsed(UINT32 simId) +{ + UINT32 i; + for (i=0; i<ARRAY_SIZE(g_halCfgSimOrder) && i<NUMBER_OF_SIM; i++) + { + if (g_halCfgSimOrder[i] == simId) + { + return TRUE; + } + } + + return FALSE; +} + +#if 0 +// ============================================================================= +// hal_BoardConfigClk32k +// ----------------------------------------------------------------------------- +/// Configure CLK_32K output. +/// @param enable TRUE to configure, and FALSE to disable. +// ============================================================================ +PROTECTED VOID hal_BoardConfigClk32k(BOOL enable) +{ + HAL_ASSERT(g_halCfg->useClk32k == TRUE, "32K clock is not configured"); + + if (enable) + { + // Setup the pin as 32K clock output + hwp_configRegs->Alt_mux_select = + (hwp_configRegs->Alt_mux_select & ~CFG_REGS_GPO_2_MASK) | + CFG_REGS_GPO_2_CLK_32K; + } + else + { + // Setup the pin as GPO (and low ouput has been + // configured in hal_BoardSetup()) + hwp_configRegs->Alt_mux_select = + (hwp_configRegs->Alt_mux_select & ~CFG_REGS_GPO_2_MASK) | + CFG_REGS_GPO_2_GPO_2; + } +} +#endif + +// ============================================================================= +// hal_BoardSetupGeneral +// ----------------------------------------------------------------------------- +/// Apply board dependent configuration to HAL for general purpose +/// @param halCfg Pointer to HAL configuration structure (from the target +/// module). +// ============================================================================ +PROTECTED VOID hal_BoardSetupGeneral(CONST HAL_CFG_CONFIG_T* halCfg) +{ + UINT32 altMux = 0; + UINT32 altMux2 = 0; + + UINT32 availableGpo_A = 0; + + UINT32 availableGpio_C = 0; + UINT32 availableGpio_A = 0; + UINT32 availableGpio_B = 0; + UINT32 availableGpio_D = 0; + UINT32 availableGpio_E = 0; + + UINT32 bootModeGpio_C = 0; + UINT32 bootModeGpio_A = 0; + UINT32 bootModeGpio_B = 0; + UINT32 bootModeGpio_D = 0; + UINT32 bootModeGpio_E = 0; + + UINT32 noConnectMask_C = 0; + UINT32 noConnectMask_A = 0; + UINT32 noConnectMask_B = 0; + UINT32 noConnectMask_D = 0; + UINT32 noConnectMask_E = 0; + + UINT32 gpoClr_A = 0; + +#ifdef CONFIG_RDA_FPGA + + // no muxing, do nothing + // add support for sd card + hwp_configRegs->BB_GPIO_Mode &= ~(0x3F<<9); + +#else // !FPGA + + // GPIOs as boot mode pins + bootModeGpio_C = HAL_GPIO_BIT(1) + | HAL_GPIO_BIT(2) + | HAL_GPIO_BIT(3) + | HAL_GPIO_BIT(4) + | HAL_GPIO_BIT(5); + bootModeGpio_A = HAL_GPIO_BIT(4) + | HAL_GPIO_BIT(5) + | HAL_GPIO_BIT(6) + | HAL_GPIO_BIT(7); + bootModeGpio_B = HAL_GPIO_BIT(0); + bootModeGpio_D = 0; + bootModeGpio_E = 0; + + // Available GPIOs + availableGpio_C |= HAL_GPIO_BIT(0) + | HAL_GPIO_BIT(1) + | HAL_GPIO_BIT(2) + | HAL_GPIO_BIT(3) + | HAL_GPIO_BIT(4) + | HAL_GPIO_BIT(5); + // Volume down/up keys + availableGpio_D |= HAL_GPIO_BIT(5) + | HAL_GPIO_BIT(6); + + // Boot modes + BOOL spiFlashCam = FALSE; + BOOL spiFlashNand = FALSE; + if (g_bootBootMode & BOOT_MODE_BOOT_SPI) + { + if (g_bootBootMode & BOOT_MODE_SPI_PIN_NAND) + { + HAL_ASSERT((g_bootBootMode & BOOT_MODE_BOOT_EMMC), + "Emmc boot pin should be pulled up to boot on SPI flash over NAND pins"); + spiFlashNand = TRUE; + } + else + { + spiFlashCam = TRUE; + } + } + + //UINT32 metalId = rda_metal_id_get(); + UINT32 emmcBootModeMask; + if (1) //metalId < 0x02) + { + emmcBootModeMask = BOOT_MODE_BOOT_EMMC + | BOOT_MODE_BOOT_SPI + | BOOT_MODE_BOOT_SPI_NAND; + } + else + { + emmcBootModeMask = BOOT_MODE_BOOT_EMMC + | BOOT_MODE_BOOT_SPI; + } + if ((g_bootBootMode & emmcBootModeMask) == BOOT_MODE_BOOT_EMMC) + { + // Boot from EMMC + HAL_ASSERT(halCfg->sdmmcCfg.sdmmc3Used, "SDMMC3 (EMMC) should be used"); + } + + if (1) //metalId < 0x02) + { + if ( (g_bootBootMode & (BOOT_MODE_BOOT_SPI|BOOT_MODE_BOOT_SPI_NAND)) + == BOOT_MODE_BOOT_SPI_NAND || + (g_bootBootMode & (BOOT_MODE_BOOT_SPI|BOOT_MODE_NAND_PAGE_SIZE_L)) + == (BOOT_MODE_BOOT_SPI|BOOT_MODE_NAND_PAGE_SIZE_L) + ) + { + // Boot from SDMMC1 + HAL_ASSERT(halCfg->sdmmcCfg.sdmmcUsed, "SDMMC1 should be used"); + } + } + + // For convenience, we do not consider spiFlashCam at present. + // We assume that SPI flash always uses parallel nand pins. +#if 0 + BOOL parallelNandUsed = halCfg->parallelNandUsed; +#else + BOOL parallelNandUsed = !spiFlashNand && !halCfg->sdmmcCfg.sdmmc3Used; +#endif + BOOL nand8_15Cam = FALSE; + BOOL nand8_15Lcd = FALSE; + if ((g_bootBootMode & (BOOT_MODE_BOOT_SPI|BOOT_MODE_BOOT_EMMC)) == 0) + { + HAL_ASSERT(parallelNandUsed, "Parallel NAND should be used"); + } + if (parallelNandUsed) + { + HAL_ASSERT(!spiFlashNand, "SPI flash uses parallel NAND pins"); + HAL_ASSERT(!halCfg->sdmmcCfg.sdmmc3Used, + "SDMMC3 (EMMC) uses parallel NAND pins"); + if ((g_bootBootMode & BOOT_MODE_NAND_8BIT) == 0) + { + if (g_bootBootMode & BOOT_MODE_NAND_HIGH_PIN_CAM) + { + HAL_ASSERT(!spiFlashCam, "SPI flash uses NAND 8-15 bits on cam pins"); + nand8_15Cam = TRUE; + } + else + { + nand8_15Lcd = TRUE; + } + } + } + + if (!parallelNandUsed) + { + availableGpio_D |= HAL_GPIO_BIT(9); + +#ifdef NAND_IO_RECONFIG_WORKROUND + if (spiFlashNand) + {/*GPIO_B:25,26,27,28,29; GPIO_D:4 the output level is inverted*/ + availableGpio_B |= HAL_GPIO_BIT(25) + | HAL_GPIO_BIT(26) + | HAL_GPIO_BIT(27) + | HAL_GPIO_BIT(28) + | HAL_GPIO_BIT(29); + availableGpio_D |= HAL_GPIO_BIT(4); + }else{ + availableGpio_D |= HAL_GPIO_BIT(8); + } +#else + if (!spiFlashNand) + { + availableGpio_B |= HAL_GPIO_BIT(25) + | HAL_GPIO_BIT(26) + | HAL_GPIO_BIT(27) + | HAL_GPIO_BIT(28) + | HAL_GPIO_BIT(29); + availableGpio_D |= HAL_GPIO_BIT(4) + | HAL_GPIO_BIT(8); + } +#endif + + if (!halCfg->sdmmcCfg.sdmmc3Used) + { + availableGpio_D |= HAL_GPIO_BIT(10); + } + } +#ifdef NAND_IO_RECONFIG_WORKROUND + else + {/*GPIO_B:25,26,27,28,29; GPIO_D:4 the output level is inverted*/ + availableGpio_B |= HAL_GPIO_BIT(25) + | HAL_GPIO_BIT(26) + | HAL_GPIO_BIT(27) + | HAL_GPIO_BIT(28) + | HAL_GPIO_BIT(29); + availableGpio_D |= HAL_GPIO_BIT(4); + } +#endif + + CONST HAL_CFG_CAM_T *camCfg = &halCfg->camCfg; + CONST HAL_CFG_CAM_T *cam2Cfg = &halCfg->cam2Cfg; + CONST HAL_LCD_MODE_T lcdMode = halCfg->goudaCfg.lcdMode; + + // LCD + if (lcdMode == HAL_LCD_MODE_PARALLEL_16BIT) + { + /* Check LCD 8-15 bits */ + HAL_ASSERT(!nand8_15Lcd, "NAND uses LCD 8-15 bits"); + HAL_ASSERT(!halCfg->goudaCfg.lcd8_23Cam2, "Parallel LCD 8-5 bits should use NAND pins only"); + altMux |= CFG_REGS_LCD_MODE_PARALLEL_16BIT; + } + else if (lcdMode == HAL_LCD_MODE_DSI) + { + altMux |= CFG_REGS_LCD_MODE_DSI; + availableGpio_A |= HAL_GPIO_BIT(22) + | HAL_GPIO_BIT(23); + } + else if (lcdMode == HAL_LCD_MODE_RGB_16BIT || + lcdMode == HAL_LCD_MODE_RGB_18BIT || + lcdMode == HAL_LCD_MODE_RGB_24BIT) + { + /* Check LCD 8-15 bits */ + if (halCfg->goudaCfg.lcd8_23Cam2) + { + HAL_ASSERT(!(cam2Cfg->camUsed || cam2Cfg->cam1Used), + "Camera2 uses LCD 8-15 bits"); + altMux2 |= CFG_REGS_RGB_CAM_2_ENABLE; + } + else + { + HAL_ASSERT(!nand8_15Lcd, "NAND uses LCD 8-15 bits"); + } + if (lcdMode == HAL_LCD_MODE_RGB_18BIT || + lcdMode == HAL_LCD_MODE_RGB_24BIT) + { + /* Check LCD 16-23 bits */ + if (lcdMode == HAL_LCD_MODE_RGB_18BIT && halCfg->goudaCfg.lcd16_17Cs) + { + HAL_ASSERT(!halCfg->goudaCfg.lcd16_23Cam, + "LCD 16-17 bits have been configured on camera pins"); + HAL_ASSERT(!(halCfg->goudaCfg.cs0Used || halCfg->goudaCfg.cs1Used), + "LCD CS 0/1 use LCD 16-17 bits"); + altMux2 |= CFG_REGS_LCD_RGB_17_16_LCD_DATA; + } + else if (halCfg->goudaCfg.lcd8_23Cam2) + { + HAL_ASSERT(!halCfg->goudaCfg.lcd16_23Cam, + "LCD 16-23 bits have been configured on camera pins"); + HAL_ASSERT(halCfg->goudaCfg.lcd16_17Cs, + "LCD 16-17 bits should use LCD CS 0/1"); + HAL_ASSERT(!(halCfg->goudaCfg.cs0Used || halCfg->goudaCfg.cs1Used), + "LCD CS 0/1 use LCD 16-17 bits"); + HAL_ASSERT(!(cam2Cfg->camUsed || cam2Cfg->cam1Used), + "Camera2 uses LCD 18-23 bits"); + altMux2 |= CFG_REGS_LCD_RGB_17_16_LCD_DATA; + altMux2 |= CFG_REGS_RGB_CAM_2_ENABLE; + } + else if (halCfg->goudaCfg.lcd16_23Cam) + { + HAL_ASSERT(!(halCfg->goudaCfg.lcd16_17Cs || halCfg->goudaCfg.lcd8_23Cam2), + "LCD 16-23 bits have been configured on LCD CS 0/1 and camera2 pins"); + HAL_ASSERT( + !(camCfg->camMode == HAL_CAM_MODE_PARALLEL && + (camCfg->camUsed || camCfg->cam1Used)), + "Parallel camera uses LCD 16-23 bits"); + HAL_ASSERT( + !(halCfg->i2cCfg.i2c2Used && halCfg->i2cCfg.i2c2PinsCam), + "I2C2 uses LCD 22-23 bits"); + HAL_ASSERT(!spiFlashCam, "SPI flash uses LCD 16-21 bits"); + HAL_ASSERT(!nand8_15Cam, "NAND uses LCD 16-23 bits"); + HAL_ASSERT( + !(camCfg->camMode == HAL_CAM_MODE_CSI && + ((camCfg->camUsed && camCfg->camCsiId == HAL_CAM_CSI_1) || + (camCfg->cam1Used && camCfg->cam1CsiId == HAL_CAM_CSI_1))), + "Camera CSI1 uses LCD 16-21 bits"); + altMux |= CFG_REGS_RGB_CAM_ENABLE; + } + else + { + HAL_ASSERT(!parallelNandUsed, "NAND uses LCD 16-23 bits"); + HAL_ASSERT(!halCfg->sdmmcCfg.sdmmc3Used, "SDMMC3 uses LCD 16-23 bits"); + altMux |= CFG_REGS_RGB_CAM_DISABLE; + } + } + altMux |= CFG_REGS_LCD_MODE_RGB_24BIT; + } + else if (lcdMode == HAL_LCD_MODE_SPI) + { + HAL_ASSERT(!(halCfg->goudaCfg.cs0Used || halCfg->goudaCfg.cs1Used), + "LCD CS 0/1 use SPI LCD pins"); + HAL_ASSERT((halCfg->usedGpo_A & (HAL_GPO_BIT(3)|HAL_GPO_BIT(4))) == 0, + "GPO 3/4 use SPI LCD pins"); + altMux |= CFG_REGS_SPI_LCD_SPI_LCD; + availableGpio_A |= HAL_GPIO_BIT(18) + | HAL_GPIO_BIT(19) + | HAL_GPIO_BIT(20) + | HAL_GPIO_BIT(21); + } + else + { + HAL_ASSERT(FALSE, "Lcd mode not defined!"); + } + + if (lcdMode == HAL_LCD_MODE_DSI || + lcdMode == HAL_LCD_MODE_SPI || + ((lcdMode == HAL_LCD_MODE_RGB_16BIT || + lcdMode == HAL_LCD_MODE_RGB_18BIT || + lcdMode == HAL_LCD_MODE_RGB_24BIT) && + halCfg->goudaCfg.lcd8_23Cam2)) + { + if (!nand8_15Lcd) + { + availableGpio_A |= HAL_GPIO_BIT(24) + | HAL_GPIO_BIT(25) + | HAL_GPIO_BIT(26) + | HAL_GPIO_BIT(27) + | HAL_GPIO_BIT(28) + | HAL_GPIO_BIT(29) + | HAL_GPIO_BIT(30) + | HAL_GPIO_BIT(31); + } + } + + if (halCfg->goudaCfg.cs0Used) + { + altMux |= CFG_REGS_GPO_4_LCD_CS_0; + } + else + { + altMux |= CFG_REGS_GPO_4_GPO_4; + availableGpo_A |= HAL_GPO_BIT(4); + } + + if (halCfg->goudaCfg.cs1Used) + { + altMux |= CFG_REGS_GPO_3_LCD_CS_1; + } + else + { + altMux |= CFG_REGS_GPO_3_GPO_3; + availableGpo_A |= HAL_GPO_BIT(3); + } + + // I2C + if (!halCfg->i2cCfg.i2cUsed) + { + availableGpio_B |= HAL_GPIO_BIT(30) + | HAL_GPIO_BIT(31); + } + + if (halCfg->i2cCfg.i2c2Used) + { + if (halCfg->i2cCfg.i2c2PinsCam) + { + if (camCfg->camUsed) + { + HAL_ASSERT(camCfg->camPdnRemap == GPIO_NONE && + camCfg->camRstRemap == GPIO_NONE, + "Cam uses PDN/RST pins"); + } + if (camCfg->cam1Used) + { + HAL_ASSERT(camCfg->cam1PdnRemap == GPIO_NONE && + camCfg->cam1RstRemap == GPIO_NONE, + "Cam1 uses PDN/RST pins"); + } + HAL_ASSERT(!nand8_15Cam, "NAND uses cam PDN/RST pins"); + availableGpio_A |= HAL_GPIO_BIT(0) + | HAL_GPIO_BIT(1); + altMux |= CFG_REGS_CAM_I2C2_I2C2; + } + else + { + // I2C2 does not use cam pins + altMux |= CFG_REGS_CAM_I2C2_CAM; + } + } + else + { + // I2C2 does not use cam pins + altMux |= CFG_REGS_CAM_I2C2_CAM; + availableGpio_A |= HAL_GPIO_BIT(0) + | HAL_GPIO_BIT(1); + } + + if (halCfg->i2cCfg.i2c3Used) + { + HAL_ASSERT((halCfg->keyOutMask & 0x18) == 0, "Keyout 3/4 use I2C3 pins"); + altMux |= CFG_REGS_KEYOUT_3_4_I2C3; + } + else + { + altMux |= CFG_REGS_KEYOUT_3_4_KEYOUT_3_4; + if ((halCfg->keyOutMask & 0x8) == 0) + { + availableGpio_B |= HAL_GPIO_BIT(6); + } + if ((halCfg->keyOutMask & 0x10) == 0) + { + availableGpio_B |= HAL_GPIO_BIT(7); + } + } + + if (halCfg->i2cCfg.modemI2cUsed) + { + HAL_ASSERT(!halCfg->emacUsed, "EMAC uses modem I2C pins"); + } + else + { + if (!halCfg->emacUsed) + { + availableGpio_E |= HAL_GPIO_BIT(0) + | HAL_GPIO_BIT(1); + } + } + + // Camera + if (camCfg->camUsed || camCfg->cam1Used) + { + if(camCfg->camMode == HAL_CAM_MODE_PARALLEL) + { + HAL_ASSERT(!spiFlashCam, "SPI flash uses cam pins"); + HAL_ASSERT(!nand8_15Cam, "NAND 8-15 bits use cam pins"); + altMux |= CFG_REGS_CSI2_PARALLEL_CAM; + availableGpio_B |= HAL_GPIO_BIT(24); + } + else if (camCfg->camMode == HAL_CAM_MODE_SPI) + { + altMux |= CFG_REGS_CSI2_SPI_CAM; + availableGpio_B |= HAL_GPIO_BIT(14); + if (!(spiFlashCam || nand8_15Cam || + (lcdMode == HAL_LCD_MODE_RGB_24BIT && + halCfg->goudaCfg.lcd16_23Cam) + ) + ) + { + availableGpio_B |= HAL_GPIO_BIT(13) + | HAL_GPIO_BIT(20) + | HAL_GPIO_BIT(21) + | HAL_GPIO_BIT(22) + | HAL_GPIO_BIT(23) + | HAL_GPIO_BIT(24); + } + } + else if (camCfg->camMode == HAL_CAM_MODE_CSI) + { + if ((camCfg->camUsed && camCfg->camCsiId == HAL_CAM_CSI_1) || + (camCfg->cam1Used && camCfg->cam1CsiId == HAL_CAM_CSI_1)) + { + HAL_ASSERT(!spiFlashCam, "SPI flash uses CSI1 pins"); + HAL_ASSERT(!nand8_15Cam, "NAND 8-15 bits use CSI1 pins"); + } + else + { + // CSI1 is unused + if (!(spiFlashCam || nand8_15Cam || + (lcdMode == HAL_LCD_MODE_RGB_24BIT && + halCfg->goudaCfg.lcd16_23Cam) + ) + ) + { + availableGpio_B |= HAL_GPIO_BIT(13) + | HAL_GPIO_BIT(20) + | HAL_GPIO_BIT(21) + | HAL_GPIO_BIT(22) + | HAL_GPIO_BIT(23) + | HAL_GPIO_BIT(24); + } + } + altMux |= CFG_REGS_CSI2_CSI2; + // If CSI2 is unused + if (!((camCfg->camUsed && camCfg->camCsiId == HAL_CAM_CSI_2) || + (camCfg->cam1Used && camCfg->cam1CsiId == HAL_CAM_CSI_2))) + { + availableGpio_B |= HAL_GPIO_BIT(14) + | HAL_GPIO_BIT(15) + | HAL_GPIO_BIT(16) + | HAL_GPIO_BIT(17) + | HAL_GPIO_BIT(18) + | HAL_GPIO_BIT(19); + } + } + else + { + HAL_ASSERT(FALSE, "Invalid cam mode: %d", camCfg->camMode); + } + + // Cam PDN/RST pins + if (!(nand8_15Cam || + (lcdMode == HAL_LCD_MODE_RGB_24BIT && halCfg->goudaCfg.lcd16_23Cam) || + (halCfg->i2cCfg.i2c2Used && halCfg->i2cCfg.i2c2PinsCam) + ) + ) + { + if (!((camCfg->camUsed && camCfg->camRstRemap == GPIO_NONE) || + (camCfg->cam1Used && camCfg->cam1RstRemap == GPIO_NONE))) + { + availableGpio_B |= HAL_GPIO_BIT(10); + } + if (!((camCfg->camUsed && camCfg->camPdnRemap == GPIO_NONE) || + (camCfg->cam1Used && camCfg->cam1PdnRemap == GPIO_NONE))) + { + availableGpio_B |= HAL_GPIO_BIT(11); + } + } + } + else // cam is unused + { + availableGpio_B |= HAL_GPIO_BIT(12) + | HAL_GPIO_BIT(14) + | HAL_GPIO_BIT(15) + | HAL_GPIO_BIT(16) + | HAL_GPIO_BIT(17) + | HAL_GPIO_BIT(18) + | HAL_GPIO_BIT(19); + if (!(nand8_15Cam || + (lcdMode == HAL_LCD_MODE_RGB_24BIT && halCfg->goudaCfg.lcd16_23Cam) || + (halCfg->i2cCfg.i2c2Used && halCfg->i2cCfg.i2c2PinsCam) + ) + ) + { + availableGpio_B |= HAL_GPIO_BIT(10) + | HAL_GPIO_BIT(11); + } + if (!(spiFlashCam || nand8_15Cam || + (lcdMode == HAL_LCD_MODE_RGB_24BIT && halCfg->goudaCfg.lcd16_23Cam) + ) + ) + { + availableGpio_B |= HAL_GPIO_BIT(13) + | HAL_GPIO_BIT(20) + | HAL_GPIO_BIT(21) + | HAL_GPIO_BIT(22) + | HAL_GPIO_BIT(23) + | HAL_GPIO_BIT(24); + } + } + + // Camera2 + if (cam2Cfg->camUsed || cam2Cfg->cam1Used) + { + if(cam2Cfg->camMode == HAL_CAM_MODE_PARALLEL) + { + altMux2 |= CFG_REGS_CSI2_2_PARALLEL_CAM; + } + else if (cam2Cfg->camMode == HAL_CAM_MODE_SPI) + { + altMux2 |= CFG_REGS_CSI2_2_SPI_CAM; + availableGpio_E |= HAL_GPIO_BIT(4) + | HAL_GPIO_BIT(5) + | HAL_GPIO_BIT(6) + | HAL_GPIO_BIT(12) + | HAL_GPIO_BIT(13) + | HAL_GPIO_BIT(14) + | HAL_GPIO_BIT(15); + } + else if (cam2Cfg->camMode == HAL_CAM_MODE_CSI) + { + if ((cam2Cfg->camUsed && (cam2Cfg->camCsiId == HAL_CAM_CSI_1 || + cam2Cfg->camCsiId == HAL_CAM_CSI_2)) || + (cam2Cfg->cam1Used && (cam2Cfg->cam1CsiId == HAL_CAM_CSI_1 || + cam2Cfg->cam1CsiId == HAL_CAM_CSI_2))) + { + altMux2 |= CFG_REGS_CSI2_2_CSI2; + } + else + { + availableGpio_E |= HAL_GPIO_BIT(4) + | HAL_GPIO_BIT(5) + | HAL_GPIO_BIT(6) + | HAL_GPIO_BIT(7) + | HAL_GPIO_BIT(8) + | HAL_GPIO_BIT(9) + | HAL_GPIO_BIT(10) + | HAL_GPIO_BIT(11) + | HAL_GPIO_BIT(12) + | HAL_GPIO_BIT(13) + | HAL_GPIO_BIT(14) + | HAL_GPIO_BIT(15); + } + } + else + { + HAL_ASSERT(FALSE, "Invalid cam2 mode: %d", cam2Cfg->camMode); + } + + // Cam2 PDN/RST pins + if (!((cam2Cfg->camUsed && cam2Cfg->camRstRemap == GPIO_NONE) || + (cam2Cfg->cam1Used && cam2Cfg->cam1RstRemap == GPIO_NONE))) + { + availableGpio_E |= HAL_GPIO_BIT(2); + } + if (!((cam2Cfg->camUsed && cam2Cfg->camPdnRemap == GPIO_NONE) || + (cam2Cfg->cam1Used && cam2Cfg->cam1PdnRemap == GPIO_NONE) || + (altMux2 & CFG_REGS_CSI2_2_CSI2))) + { + availableGpio_E |= HAL_GPIO_BIT(3); + } + } + else // cam2 is unused + { + if (!((lcdMode == HAL_LCD_MODE_RGB_16BIT || + lcdMode == HAL_LCD_MODE_RGB_18BIT || + lcdMode == HAL_LCD_MODE_RGB_24BIT) && + halCfg->goudaCfg.lcd8_23Cam2)) + { + availableGpio_E |= HAL_GPIO_BIT(2) + | HAL_GPIO_BIT(3) + | HAL_GPIO_BIT(4) + | HAL_GPIO_BIT(5) + | HAL_GPIO_BIT(6) + | HAL_GPIO_BIT(7) + | HAL_GPIO_BIT(8) + | HAL_GPIO_BIT(9) + | HAL_GPIO_BIT(10) + | HAL_GPIO_BIT(11) + | HAL_GPIO_BIT(12) + | HAL_GPIO_BIT(13) + | HAL_GPIO_BIT(14) + | HAL_GPIO_BIT(15); + } + } + + // UART 1 Pin configuration + switch (halCfg->uartCfg[0]) + { + case HAL_UART_CONFIG_NONE: + altMux |= CFG_REGS_KEYOUT_7_KEYOUT_7; + availableGpio_C |= HAL_GPIO_BIT(6); + availableGpio_A |= HAL_GPIO_BIT(14); + if ((halCfg->keyInMask & 0x80) == 0) + { + availableGpio_A |= HAL_GPIO_BIT(15); + } + if ((halCfg->keyInMask & 0x80) == 0) + { + availableGpio_A |= HAL_GPIO_BIT(16); + } + break; + case HAL_UART_CONFIG_DATA: + // use UART1 TXD, RXD + altMux |= CFG_REGS_KEYOUT_7_KEYOUT_7; + if ((halCfg->keyInMask & 0x80) == 0) + { + availableGpio_A |= HAL_GPIO_BIT(15); + } + if ((halCfg->keyInMask & 0x80) == 0) + { + availableGpio_A |= HAL_GPIO_BIT(16); + } + break; + case HAL_UART_CONFIG_FLOWCONTROL: + // use UART1 TXD, RXD, CTS, RTS + HAL_ASSERT((halCfg->keyInMask & 0x80) == 0, "Keyin 7 uses UART1 CTS"); + HAL_ASSERT((halCfg->keyOutMask & 0x80) == 0, "Keyout 7 uses UART1 RTS"); + altMux |= CFG_REGS_KEYOUT_7_UART1_RTS; + break; + case HAL_UART_CONFIG_MODEM: + // use UART1 TXD, RXD, CTS, RTS, RI, DSR, DCD, DTR + HAL_ASSERT((halCfg->keyInMask & 0x80) == 0, "Keyin 7 uses UART1 CTS"); + HAL_ASSERT((halCfg->keyOutMask & 0x80) == 0, "Keyout 7 uses UART1 RTS"); + HAL_ASSERT(!halCfg->hostUartUsed, "Host UART uses UART1 DCD/DTR"); + HAL_ASSERT(halCfg->uartCfg[1] == HAL_UART_CONFIG_NONE, + "UART 2 must be unused to use UART1 Modem lines."); + HAL_ASSERT((halCfg->keyInMask & 0x40) == 0, "Keyin 6 uses UART1 DSR"); + HAL_ASSERT((halCfg->keyOutMask & 0x40) == 0, "Keyout 6 uses UART1 RI"); + altMux |= CFG_REGS_KEYOUT_7_UART1_RTS + | CFG_REGS_UART1_8LINE_UART1_8_LINE; + break; + default: + HAL_ASSERT(FALSE, + "Invalid Uart 1 Configuration (%d).", + halCfg->uartCfg[0]); + break; + } + + // Host UART + if (halCfg->hostUartUsed) + { + HAL_ASSERT(halCfg->uartCfg[1] == HAL_UART_CONFIG_NONE, + "UART2 uses host UART RXD/TXD."); + } + + // UART 2 Pin configuration + switch (halCfg->uartCfg[1]) + { + case HAL_UART_CONFIG_NONE: + altMux |= CFG_REGS_UART2_HOST_UART + | CFG_REGS_KEYOUT_6_KEYOUT_6; + if (halCfg->uartCfg[0] != HAL_UART_CONFIG_MODEM) + { + availableGpio_C |= HAL_GPIO_BIT(7) + | HAL_GPIO_BIT(8); + } + if ((halCfg->keyInMask & 0x40) == 0) + { + availableGpio_B |= HAL_GPIO_BIT(8); + } + if ((halCfg->keyOutMask & 0x40) == 0) + { + availableGpio_B |= HAL_GPIO_BIT(9); + } + break; + case HAL_UART_CONFIG_DATA: + // use UART2 TXD, RXD + altMux |= CFG_REGS_UART2_UART2 + | CFG_REGS_KEYOUT_6_KEYOUT_6; + if ((halCfg->keyInMask & 0x40) == 0) + { + availableGpio_B |= HAL_GPIO_BIT(8); + } + if ((halCfg->keyOutMask & 0x40) == 0) + { + availableGpio_B |= HAL_GPIO_BIT(9); + } + break; + case HAL_UART_CONFIG_FLOWCONTROL: + // use UART2 TXD, RXD, CTS, RTS + HAL_ASSERT((halCfg->keyInMask & 0x40) == 0, "Keyin 6 uses UART2 CTS"); + HAL_ASSERT((halCfg->keyOutMask & 0x40) == 0, "Keyout 6 uses UART2 RTS"); + altMux |= CFG_REGS_UART2_UART2 + | CFG_REGS_KEYOUT_6_UART2_RTS; + break; + case HAL_UART_CONFIG_MODEM: + default: + HAL_ASSERT(FALSE, + "Invalid Uart2 Configuration (%d).", + halCfg->uartCfg[1]); + break; + } + + // UART 3 Pin configuration + switch (halCfg->uartCfg[2]) + { + case HAL_UART_CONFIG_NONE: + availableGpio_D |= HAL_GPIO_BIT(0) + | HAL_GPIO_BIT(1) + | HAL_GPIO_BIT(2) + | HAL_GPIO_BIT(3); + break; + case HAL_UART_CONFIG_DATA: + // use UART3 TXD, RXD + availableGpio_D |= HAL_GPIO_BIT(2) + | HAL_GPIO_BIT(3); + break; + case HAL_UART_CONFIG_FLOWCONTROL: + // use UART3 TXD, RXD, CTS, RTS + break; + case HAL_UART_CONFIG_MODEM: + default: + HAL_ASSERT(FALSE, + "Invalid Uart3 Configuration (%d).", + halCfg->uartCfg[2]); + break; + } + + // I2S + altMux |= CFG_REGS_DAI_I2S; + if (halCfg->i2sCfg.di0Used || halCfg->i2sCfg.di1Used || + halCfg->i2sCfg.di2Used || halCfg->i2sCfg.doUsed) + { + if (!halCfg->i2sCfg.di0Used) + { + availableGpio_A |= HAL_GPIO_BIT(11); + } + if (!halCfg->i2sCfg.di1Used) + { + availableGpio_A |= HAL_GPIO_BIT(12); + } + if (halCfg->i2sCfg.di2Used) + { + HAL_ASSERT((halCfg->keyInMask & 0x4) == 0, "Keyin 2 uses I2S DI2"); + altMux |= CFG_REGS_I2S_DI_2_I2S_DI_2; + } + else + { + altMux |= CFG_REGS_I2S_DI_2_KEYIN_2; + if ((halCfg->keyInMask & 0x4) == 0) + { + availableGpio_B |= HAL_GPIO_BIT(2); + } + } + if (!halCfg->i2sCfg.doUsed) + { + availableGpio_A |= HAL_GPIO_BIT(13); + } + } + else + { + availableGpio_A |= HAL_GPIO_BIT(9) + | HAL_GPIO_BIT(10) + | HAL_GPIO_BIT(11) + | HAL_GPIO_BIT(12) + | HAL_GPIO_BIT(13); + } + + // I2S2 + if (halCfg->i2s2Cfg.di0Used || halCfg->i2s2Cfg.di1Used || + halCfg->i2s2Cfg.di2Used || halCfg->i2s2Cfg.doUsed) + { + HAL_ASSERT(!halCfg->emacUsed, "EMAC uses I2S2 pins"); + if (!halCfg->i2s2Cfg.di0Used) + { + availableGpio_D |= HAL_GPIO_BIT(13); + } + if (!halCfg->i2s2Cfg.di1Used) + { + availableGpio_D |= HAL_GPIO_BIT(14); + } + if (!halCfg->i2s2Cfg.doUsed) + { + availableGpio_D |= HAL_GPIO_BIT(15); + } + } + else + { + availableGpio_D |= HAL_GPIO_BIT(11) + | HAL_GPIO_BIT(12) + | HAL_GPIO_BIT(13) + | HAL_GPIO_BIT(14) + | HAL_GPIO_BIT(15); + } + + // LPS CO1 + if (halCfg->useLpsCo1) + { + HAL_ASSERT((halCfg->keyInMask & 0x10) == 0, "Keyin 4 uses LPS_CO1"); + altMux |= CFG_REGS_LPSCO_1_LPSCO_1; + } + else + { + altMux |= CFG_REGS_LPSCO_1_KEYIN_4; + if ((halCfg->keyInMask & 0x10) == 0) + { + availableGpio_A |= HAL_GPIO_BIT(7); + } + } + + // TCO + if (halCfg->usedTco & 0x1) + { + HAL_ASSERT((halCfg->keyOutMask & 0x1) == 0, "Keyout 0 uses TCO0"); + altMux |= CFG_REGS_TCO_0_TCO_0; + } + else + { + altMux |= CFG_REGS_TCO_0_KEYOUT_0; + if ((halCfg->keyOutMask & 0x1) == 0) + { + availableGpio_B |= HAL_GPIO_BIT(3); + } + } + + if (halCfg->usedTco & 0x2) + { + HAL_ASSERT((halCfg->keyOutMask & 0x2) == 0, "Keyout 1 uses TCO1"); + altMux |= CFG_REGS_TCO_1_TCO_1; + } + else + { + altMux |= CFG_REGS_TCO_1_KEYOUT_1; + if ((halCfg->keyOutMask & 0x2) == 0) + { + availableGpio_B |= HAL_GPIO_BIT(4); + } + } + + if (halCfg->usedTco & 0x4) + { + HAL_ASSERT((halCfg->keyOutMask & 0x4) == 0, "Keyout 2 uses TCO2"); + altMux |= CFG_REGS_TCO_2_TCO_2; + } + else + { + altMux |= CFG_REGS_TCO_2_KEYOUT_2; + if ((halCfg->keyOutMask & 0x4) == 0) + { + availableGpio_B |= HAL_GPIO_BIT(5); + } + } + + // PWM + if (halCfg->pwmCfg.pwtUsed) + { + HAL_ASSERT((halCfg->keyInMask & 0x20) == 0, "Keyin 5 uses PWT"); + altMux |= CFG_REGS_GPO_0_PWT; + } + else if (halCfg->keyInMask & 0x20) + { + altMux |= CFG_REGS_GPO_0_KEYIN_5; + } + else + { + altMux |= CFG_REGS_GPO_0_GPO_0; + availableGpo_A |= HAL_GPO_BIT(0); + } + + if (halCfg->pwmCfg.lpgUsed) + { + HAL_ASSERT((halCfg->keyOutMask & 0x20) == 0, "Keyout 5 uses LPG"); + altMux |= CFG_REGS_GPO_1_LPG; + } + else if (halCfg->keyOutMask & 0x20) + { + altMux |= CFG_REGS_GPO_1_KEYOUT_5; + } + else + { + altMux |= CFG_REGS_GPO_1_GPO_1; + availableGpo_A |= HAL_GPO_BIT(1); + } + + if (halCfg->pwmCfg.pwl1Used) + { + HAL_ASSERT(!halCfg->useClk32k, "Clk 32k uses PWL1"); + altMux |= CFG_REGS_GPO_2_PWL_1; + } + else if (halCfg->useClk32k) + { + // Default to GPO low output + // 32K clock will be enabled per request + //altMux |= CFG_REGS_GPO_2_CLK_32K; + altMux |= CFG_REGS_GPO_2_GPO_2; + } + else + { + altMux |= CFG_REGS_GPO_2_GPO_2; + availableGpo_A |= HAL_GPO_BIT(2); + } + + // Clock out and host clock + if (halCfg->clkOutUsed) + { + HAL_ASSERT(!halCfg->hostClkUsed, "HST_CLK uses CLK_OUT pin"); + altMux |= CFG_REGS_CLK_OUT_CLK_OUT; + } + else if (halCfg->hostClkUsed) + { + altMux |= CFG_REGS_CLK_OUT_HST_CLK; + } + else + { + altMux |= CFG_REGS_CLK_OUT_HST_CLK; + availableGpo_A |= HAL_GPO_BIT(8); + } + + // SPI + if (halCfg->spiCfg[0].cs0Used || halCfg->spiCfg[0].cs1Used || + halCfg->spiCfg[0].cs2Used) + { + HAL_ASSERT(!(halCfg->modemSpiCfg[0].cs0Used || + halCfg->modemSpiCfg[0].cs1Used || + halCfg->modemSpiCfg[0].cs2Used), "Modem SPI1 is in use"); + altMux |= CFG_REGS_AP_SPI1_AP_SPI1; + if (!halCfg->spiCfg[0].cs0Used) + { + availableGpio_C |= HAL_GPIO_BIT(22); + } + if (!halCfg->spiCfg[0].cs1Used) + { + availableGpio_A |= HAL_GPIO_BIT(17); + } + if (halCfg->spiCfg[0].cs2Used) + { + HAL_ASSERT((halCfg->keyInMask & 0x2) == 0, "Keyin 1 uses SPI1 CS2"); + altMux |= CFG_REGS_SPI1_CS_2_SPI1_CS_2; + } + else + { + altMux |= CFG_REGS_SPI1_CS_2_KEYIN_1; + if ((halCfg->keyInMask & 0x2) == 0) + { + availableGpio_B |= HAL_GPIO_BIT(1); + } + } + if (!halCfg->spiCfg[0].di0Used) + { + availableGpio_C |= HAL_GPIO_BIT(23); + } + if (!halCfg->spiCfg[0].di1Used) + { + availableGpio_C |= HAL_GPIO_BIT(24); + } + } + else // AP SPI1 unused + { + altMux |= CFG_REGS_AP_SPI1_BB_SPI1; + if (halCfg->modemSpiCfg[0].cs0Used || halCfg->modemSpiCfg[0].cs1Used || + halCfg->modemSpiCfg[0].cs2Used) + { + if (!halCfg->modemSpiCfg[0].cs0Used) + { + availableGpio_C |= HAL_GPIO_BIT(22); + } + if (!halCfg->modemSpiCfg[0].cs1Used) + { + availableGpio_A |= HAL_GPIO_BIT(17); + } + if (!halCfg->modemSpiCfg[0].di0Used) + { + availableGpio_C |= HAL_GPIO_BIT(23); + } + if (!halCfg->modemSpiCfg[0].di1Used) + { + availableGpio_C |= HAL_GPIO_BIT(24); + } + } + else + { + availableGpio_A |= HAL_GPIO_BIT(17); + availableGpio_C |= HAL_GPIO_BIT(21) + | HAL_GPIO_BIT(22) + | HAL_GPIO_BIT(23) + | HAL_GPIO_BIT(24); + if ((halCfg->keyInMask & 0x2) == 0) + { + availableGpio_B |= HAL_GPIO_BIT(1); + } + } + } + if (halCfg->spiCfg[1].cs0Used || halCfg->spiCfg[1].cs1Used) + { + if (!halCfg->spiCfg[1].cs0Used) + { + availableGpio_A |= HAL_GPIO_BIT(5); + } + if (halCfg->spiCfg[1].cs1Used) + { + HAL_ASSERT((halCfg->keyInMask & 0x8) == 0, "Keyin 3 uses SPI2 CS1"); + altMux |= CFG_REGS_KEYIN_3_SPI2_CS_1; + } + else + { + altMux |= CFG_REGS_KEYIN_3_KEYIN_3; + if ((halCfg->keyInMask & 0x8) == 0) + { + availableGpio_A |= HAL_GPIO_BIT(6); + } + } + if (!halCfg->spiCfg[1].di0Used) + { + availableGpio_A |= HAL_GPIO_BIT(3); + } + if (!halCfg->spiCfg[1].di1Used) + { + availableGpio_A |= HAL_GPIO_BIT(4); + } + } + else // AP SPI2 unused + { + availableGpio_A |= HAL_GPIO_BIT(2) + | HAL_GPIO_BIT(3) + | HAL_GPIO_BIT(4) + | HAL_GPIO_BIT(5); + if ((halCfg->keyInMask & 0x8) == 0) + { + availableGpio_A |= HAL_GPIO_BIT(6); + } + } + + // Standalone keyin/out + if ((halCfg->keyInMask & 0x1) == 0) + { + availableGpio_B |= HAL_GPIO_BIT(0); + } + + // SDMMC + if (!halCfg->sdmmcCfg.sdmmcUsed) + { + availableGpio_C |= HAL_GPIO_BIT(9) + | HAL_GPIO_BIT(10) + | HAL_GPIO_BIT(11) + | HAL_GPIO_BIT(12) + | HAL_GPIO_BIT(13) + | HAL_GPIO_BIT(14); + } + if (!halCfg->sdmmcCfg.sdmmc2Used) + { + availableGpio_C |= HAL_GPIO_BIT(15) + | HAL_GPIO_BIT(16); + if (!halCfg->sdio2Uart1Used) + { + availableGpio_C |= HAL_GPIO_BIT(17) + | HAL_GPIO_BIT(18) + | HAL_GPIO_BIT(19) + | HAL_GPIO_BIT(20); + } + } + HAL_ASSERT(!(parallelNandUsed && halCfg->sdmmcCfg.sdmmc3Used), + "Parallel NAND uses SDMMC3 pins"); + + // SDIO2_UART1 + if (halCfg->sdio2Uart1Used) + { + HAL_ASSERT(halCfg->uartCfg[0] == HAL_UART_CONFIG_NONE, + "UART1 has been configured on UART1 pins"); + altMux2 |= CFG_REGS_UART1_SDIO2_UART1; + } + else + { + altMux2 |= CFG_REGS_UART1_SDIO2_SDIO2; + } + + // EMAC + if (halCfg->emacUsed) + { + altMux2 |= CFG_REGS_MAC_EN_ENABLE; + } + else + { + altMux2 |= CFG_REGS_MAC_EN_DISABLE; + } + + // SIM + if (!hal_BoardSimUsed(2)) + { + availableGpio_C |= HAL_GPIO_BIT(25) + | HAL_GPIO_BIT(26) + | HAL_GPIO_BIT(27); + } + + if (hal_BoardSimUsed(3)) + { + HAL_ASSERT(!halCfg->emacUsed, "EMAC uses SIM3 pins"); + } + else + { + if (!halCfg->emacUsed) + { + availableGpio_C |= HAL_GPIO_BIT(28) + | HAL_GPIO_BIT(29) + | HAL_GPIO_BIT(30); + } + } + + UINT32 gpioMask; + // GPIO_C mask check + gpioMask = ~availableGpio_C & halCfg->usedGpio_C; + HAL_ASSERT(gpioMask == 0, + "Some used GPIO C are not available (0x%x)", + gpioMask); + gpioMask = ~availableGpio_C & halCfg->noConnectGpio_C; + HAL_ASSERT(gpioMask == 0, + "Some GPIO C declared as not connected are not available (0x%x)", + gpioMask); + gpioMask = halCfg->usedGpio_C & halCfg->noConnectGpio_C; + HAL_ASSERT(gpioMask == 0, + "Some GPIO C declared as not connected are used (0x%x)", + gpioMask); +#ifdef CHECK_GPIO_ALT_FUNC + gpioMask = availableGpio_C & + (~halCfg->usedGpio_C & ~halCfg->noConnectGpio_C); + HAL_ASSERT(gpioMask == 0, + "Some available GPIO C declared as alt function (0x%x)", + gpioMask); +#endif + + // GPIO_A mask check + gpioMask = ~availableGpio_A & halCfg->usedGpio_A; + HAL_ASSERT(gpioMask == 0, + "Some used GPIO A are not available (0x%x)", + gpioMask); + gpioMask = ~availableGpio_A & halCfg->noConnectGpio_A; + HAL_ASSERT(gpioMask == 0, + "Some GPIO A declared as not connected are not available (0x%x)", + gpioMask); + gpioMask = halCfg->usedGpio_A & halCfg->noConnectGpio_A; + HAL_ASSERT(gpioMask == 0, + "Some GPIO A declared as not connected are used (0x%x)", + gpioMask); +#ifdef CHECK_GPIO_ALT_FUNC + gpioMask = availableGpio_A & + (~halCfg->usedGpio_A & ~halCfg->noConnectGpio_A); + HAL_ASSERT(gpioMask == 0, + "Some available GPIO A declared as alt function (0x%x)", + gpioMask); +#endif + + // GPIO_B mask check + gpioMask = ~availableGpio_B & halCfg->usedGpio_B; + HAL_ASSERT(gpioMask == 0, + "Some used GPIO B are not available (0x%x)", + gpioMask); + gpioMask = ~availableGpio_B & halCfg->noConnectGpio_B; + HAL_ASSERT(gpioMask == 0, + "Some GPIO B declared as not connected are not available (0x%x)", + gpioMask); + gpioMask = halCfg->usedGpio_B & halCfg->noConnectGpio_B; + HAL_ASSERT(gpioMask == 0, + "Some GPIO B declared as not connected are used (0x%x)", + gpioMask); +#ifdef CHECK_GPIO_ALT_FUNC + gpioMask = availableGpio_B & + (~halCfg->usedGpio_B & ~halCfg->noConnectGpio_B); + HAL_ASSERT(gpioMask == 0, + "Some available GPIO B declared as alt function (0x%x)", + gpioMask); +#endif + + // GPIO_D mask check + gpioMask = ~availableGpio_D & halCfg->usedGpio_D; + HAL_ASSERT(gpioMask == 0, + "Some used GPIO D are not available (0x%x)", + gpioMask); + gpioMask = ~availableGpio_D & halCfg->noConnectGpio_D; + HAL_ASSERT(gpioMask == 0, + "Some GPIO D declared as not connected are not available (0x%x)", + gpioMask); + gpioMask = halCfg->usedGpio_D & halCfg->noConnectGpio_D; + HAL_ASSERT(gpioMask == 0, + "Some GPIO D declared as not connected are used (0x%x)", + gpioMask); +#ifdef CHECK_GPIO_ALT_FUNC + gpioMask = availableGpio_D & + (~halCfg->usedGpio_D & ~halCfg->noConnectGpio_D); + HAL_ASSERT(gpioMask == 0, + "Some available GPIO D declared as alt function (0x%x)", + gpioMask); +#endif + + // GPIO_E mask check + gpioMask = ~availableGpio_E & halCfg->usedGpio_E; + HAL_ASSERT(gpioMask == 0, + "Some used GPIO E are not available (0x%x)", + gpioMask); + gpioMask = ~availableGpio_E & halCfg->noConnectGpio_E; + HAL_ASSERT(gpioMask == 0, + "Some GPIO E declared as not connected are not available (0x%x)", + gpioMask); + gpioMask = halCfg->usedGpio_E & halCfg->noConnectGpio_E; + HAL_ASSERT(gpioMask == 0, + "Some GPIO E declared as not connected are used (0x%x)", + gpioMask); +#ifdef CHECK_GPIO_ALT_FUNC + gpioMask = availableGpio_E & + (~halCfg->usedGpio_E & ~halCfg->noConnectGpio_E); + HAL_ASSERT(gpioMask == 0, + "Some available GPIO E declared as alt function (0x%x)", + gpioMask); +#endif + + // GPO_A mask check + gpioMask = ~availableGpo_A & halCfg->usedGpo_A; + HAL_ASSERT(gpioMask == 0, + "Some used GPO A are not available (0x%x)", + gpioMask); + +#endif // !FPGA + + // Set IO drive + hwp_configRegs->IO_Drive1_Select = halCfg->ioDrive.select1; + hwp_configRegs->IO_Drive2_Select = halCfg->ioDrive.select2; + + // Set the not connected ones as output and drive 0 + // But keep boot mode GPIOs as input to avoid current leakage + noConnectMask_C = halCfg->noConnectGpio_C & ~bootModeGpio_C; + noConnectMask_A = halCfg->noConnectGpio_A & ~bootModeGpio_A; + noConnectMask_B = halCfg->noConnectGpio_B & ~bootModeGpio_B; + noConnectMask_D = halCfg->noConnectGpio_D & ~bootModeGpio_D; + noConnectMask_E = halCfg->noConnectGpio_E & ~bootModeGpio_E; + + hwp_gpio->gpio_clr = noConnectMask_C; + hwp_gpio->gpio_oen_set_out = noConnectMask_C; + + hwp_apGpioA->gpio_clr = noConnectMask_A; + hwp_apGpioA->gpio_oen_set_out = noConnectMask_A; + + hwp_apGpioB->gpio_clr = noConnectMask_B; + hwp_apGpioB->gpio_oen_set_out = noConnectMask_B; + + hwp_apGpioD->gpio_clr = noConnectMask_D; + hwp_apGpioD->gpio_oen_set_out = noConnectMask_D; + + hwp_apGpioE->gpio_clr = noConnectMask_E; + hwp_apGpioE->gpio_oen_set_out = noConnectMask_E; + + // Init GPO_A values + gpoClr_A = availableGpo_A; + if (halCfg->useClk32k) + { + // Init 32K clock pin to low (by setting up GPO) + gpoClr_A |= HAL_GPO_BIT(2); + } +#ifdef _TGT_AP_GPIO_USBID_CTRL + // if GPO_1 used for usb id, it should be high + gpoClr_A &= ~(HAL_GPO_BIT(1)); +#endif + hwp_apGpioA->gpo_clr = gpoClr_A; + + // Configure MUX after initializing all the GPO pins + // (GPIO pins are in input mode by default) + + // Set GPIO mode + hwp_configRegs->BB_GPIO_Mode = availableGpio_C; + hwp_configRegs->AP_GPIO_A_Mode = availableGpio_A; + hwp_configRegs->AP_GPIO_B_Mode = availableGpio_B; + hwp_configRegs->AP_GPIO_D_Mode = availableGpio_D; + hwp_configRegs->AP_GPIO_E_Mode = availableGpio_E; + // Set Alt Mux configuration + hwp_configRegs->Alt_mux_select = altMux; + hwp_configRegs->Alt_mux_select2 = altMux2; + + // -------------------------------------------------- + // As of now, all connected GPIOs, which are as GPIO + // or not used at all but connected are configured as + // GPIOs in input mode, except for Gouda reset pins + // -------------------------------------------------- + +} + + +// ============================================================================= +// hal_BoardSetup +// ----------------------------------------------------------------------------- +/// Apply board dependent configuration to HAL +/// @param halCfg Pointer to HAL configuration structure (from the target +/// module). +// ============================================================================ +//PROTECTED VOID hal_BoardSetup(CONST HAL_CFG_CONFIG_T* halCfg) +PUBLIC INT32 hal_BoardSetup(INT8 run_mode) +{ + g_bootBootMode = rda_hwcfg_get(); + hal_BoardSetupGeneral(&hal_cfg); + + if(g_halConfigError) + return CMD_RET_FAILURE; + else + return CMD_RET_SUCCESS; +} diff --git a/board/rda/rda8810h/u-boot-spl.lds b/board/rda/rda8810h/u-boot-spl.lds new file mode 100644 index 0000000000..afe35fd2a8 --- /dev/null +++ b/board/rda/rda8810h/u-boot-spl.lds @@ -0,0 +1,35 @@ +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00100100; + . = ALIGN(4); + .text : + { + __start = .; + arch/arm/cpu/armv7/start.o (.text) + *(.text) + } + . = ALIGN(4); + .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } + . = ALIGN(4); + .data : { + *(.data) + } + . = ALIGN(4); + . = .; + . = ALIGN(4); + __image_copy_end = .; + _end = .; + .bss : + { + . = ALIGN(4); + __bss_start = .; + *(.bss*) + . = ALIGN(4); + __bss_end__ = .; + ASSERT((ABSOLUTE(__bss_end__) < 0x00110000), \ + "too big data in spl, don't exceed intrenal ram"); + } +} |