1
1

Initial dump from Zyxel

This commit is contained in:
2026-04-17 17:00:52 +02:00
commit 81fec250f4
23116 changed files with 5231237 additions and 0 deletions
@@ -0,0 +1,54 @@
#
# (C) Copyright 2000-2005
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
#
# 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$(SOC).a
COBJS = timer.o serial.o bsp.o training.o mdma.o
SOBJS = lowlevel_init.o reset.o
all: $(obj).depend $(LIB)
training.o: training.c training100.c training100_new.c training1000.c
$(CC) $(CFLAGS) -fpic -c -o $@ $<
bsp.o: bsp.c
$(CC) $(CFLAGS) -fpic -c -o $@ $<
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS))
SOBJS := $(addprefix $(obj),$(SOBJS))
$(LIB): $(obj).depend $(OBJS) $(SOBJS)
$(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS)
#########################################################################
# defines $(obj).depend target
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
#########################################################################
@@ -0,0 +1,66 @@
/*
* Copyright (C) 2006 Mindspeed Technologies Inc.
*
* 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 <common.h>
#include <asm/hardware.h>
#include <asm/arch/bsp.h>
#if defined(CONFIG_COMCERTO_900)
#include "bsp900.c"
#elif defined(CONFIG_COMCERTO_100)
#include "bsp100.c"
#elif defined(CONFIG_COMCERTO_1000)
#include "bsp1000.c"
#else
#error "No Architecture selected!!@"
#endif
#if defined(CONFIG_M8326XG) || defined(CONFIG_M8325XG) || defined(CONFIG_M8324XG)
extern unsigned char comcerto_part_no[8];
#define FPP_ENABLED 1 /* Default Mode is FPP Enabled */
#define FPP_DISABLED 0 /* FPP Enabled */
#if defined(CONFIG_NOFPP_MODE)
#define FPP_MODE FPP_DISABLED
#endif
#if !defined(CONFIG_NOFPP_MODE)
#define FPP_MODE FPP_ENABLED
#endif
void arch_preboot_os(void)
{
char buf[256];
char partno[32];
char fppmode[32];
char *cmdline = getenv ("bootargs");
sprintf (partno, " partno=%s", comcerto_part_no);
sprintf (fppmode, " fppmode=%d", FPP_MODE);
if (cmdline) {
strcpy(buf, cmdline);
strcat(buf, partno);
strcat(buf, fppmode);
} else {
strcpy(buf, partno);
strcat(buf, fppmode);
}
setenv ("bootargs", buf);
}
#endif
@@ -0,0 +1,494 @@
/*
* Copyright (C) 2007 Mindspeed Technologies Inc.
*
* 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 <common.h>
#include <asm/hardware.h>
static void config_board1(void);
static void config_board2(void);
static void config_board3(void);
static void config_board4(void);
static void config_board5(void);
static void config_board6(void);
static void config_board7(void);
static void config_board8(void);
static void config_board9(void);
static void config_board10(void);
void SoC_Check_Device(void)
{
// This should run on a M821xx SoC, let's check it
u32 devicetype = __le32_to_cpu((*(volatile u32*)(GPIO_DEVID_REG)) & __cpu_to_le32(0xFFFF));
if (devicetype != 0x150)
{
//error wrong device
// TODO: what should we do?
}
}
void SoC_APB_setup(void)
{
// Setting APB Bus Wait states to 1, set post write
(*(volatile u32*)(APB_ACCESS_WS_REG)) = __cpu_to_le32(0x40);
}
void SoC_ARAM_setup(void)
{
// disable pipeline mode in ARAM
(*(volatile u32*)(MEMCORE_BASEADDR+0x18)) = __cpu_to_le32(1);
}
void SoC_AHB_setup(void)
{
// enable all 6 masters for ARAM
(*(volatile u32*)(ASA_ARAM_TC_CR_REG)) = __cpu_to_le32(ASA_TC_REQIDMAEN | ASA_TC_REQTDMEN |ASA_TC_REQIPSECUSBEN |ASA_TC_REQARM0EN | ASA_TC_REQARM1EN |ASA_TC_REQMDMAEN);
// enable all 6 masters for EBUS
(*(volatile u32*)(ASA_EBUS_TC_CR_REG)) = __cpu_to_le32(ASA_TC_REQIDMAEN | ASA_TC_REQTDMEN |ASA_TC_REQIPSECUSBEN |ASA_TC_REQARM0EN | ASA_TC_REQARM1EN |ASA_TC_REQMDMAEN);
}
void SoC_PLL_init(void)
{
HAL_set_amba_clk(CFG_HZ_CLOCK);
HAL_set_arm_clk(CFG_ARM_CLOCK);
// set PUI
*(volatile u32*)(CLKCORE_CLKDIV_CNTRL) &= __cpu_to_le32(~(0x1F << PUI_CLKDIV_RATIO_SHIFT));
*(volatile u32*)(CLKCORE_CLKDIV_CNTRL) |= __cpu_to_le32(((CFG_ARM_CLOCK / 25000000) << PUI_CLKDIV_RATIO_SHIFT));
*(volatile u32*)(CLKCORE_CLKDIV_CNTRL) &= __cpu_to_le32(~PUI_CLKDIV_BYPASS);
// set pci divider and switch to ref clk
// *(volatile u32*)(CLKCORE_CLKDIV_CNTRL) &= ~(0x1F << PCI_CLKDIV_RATIO_SHIFT);/
// *(volatile u32*)(CLKCORE_CLKDIV_CNTRL) |= ((CFG_HZ_CLOCK / 33000000) << PCI_CLKDIV_RATIO_SHIFT);
// *(volatile u32*)(CLKCORE_CLKDIV_CNTRL) &= ~PCI_CLKDIV_BYPASS;
}
static void apply_ddr_setting(u32 board_config)
{
u8 do_training = 0;
switch (board_config) {
case BOARD_CFG_1:
config_board1();
break;
case BOARD_CFG_2:
config_board2();
break;
case BOARD_CFG_3:
config_board3();
break;
case BOARD_CFG_4:
config_board4();
do_training = 1;
break;
case BOARD_CFG_5:
config_board5();
do_training = 1;
break;
case BOARD_CFG_6:
config_board6();
break;
case BOARD_CFG_7:
config_board7();
break;
case BOARD_CFG_8:
config_board8();
break;
case BOARD_CFG_9:
config_board9(); /* Packet IAD C50 */
do_training = 1;
break;
case BOARD_CFG_10:
config_board10(); /* Router C50 */
break;
}
#ifdef DDR_TRAINING
if (do_training)
start_training(); /* training to find optimal ODT values (run from L1 cache) */
#endif
}
void SoC_mem_init(u32 board_config)
{
volatile u32 delay_count;
u32 ddr_size;
// Get the right amount of DDR the board is populated with
ddr_size = get_ddr_size();
// Memory setup register
*(volatile u32*)(MEMORY_MAX_ADDR) = __cpu_to_le32((ddr_size - 1) + MEMORY_BASE_ADDR);
// disbale ROM remap
*(volatile u32*)(MEMORY_CR) = __cpu_to_le32(0);
// Take DDR controller out of reset
*(volatile u32*)(BLOCK_RESET_REG) |= __cpu_to_le32(DDR_RST);
// 20 ops delay
delay_count = 20;
while(delay_count--);
//Apply DENALI DDR configuration according to the board
apply_ddr_setting(board_config);
}
void SoC_nand_init(void)
{
// TODO: verify timings
// Configure CS4 - 8 bits - NAND
*(volatile u32*)(EX_CS4_CFG_REG) = __cpu_to_le32(EX_MEM_BUS_8 | EX_NAND_MODE);
// timings (CSw = 9, RE WE 9),
*(volatile u32*)(EX_CS4_TMG1_REG) = __cpu_to_le32(9 | 9<<16 | 9<<24) ;
*(volatile u32*)(EX_CSEN_REG) |= __cpu_to_le32(EX_CS4_EN);
}
/*
* SoC_gpio_cfg - configure GPIO pins as input or output pins
*
* gpio - gpio pin
*
* mode - gpio pin mode
* GPIO_TYPE_OUTPUT = output
* GPIO_TYPE_INPUT = input
*
*/
int SoC_gpio_cfg(int gpio, int mode)
{
if ((gpio < 0) || (gpio > 31))
goto err;
switch (mode) {
case GPIO_TYPE_INPUT:
default:
*(volatile u32 *) GPIO_OE_REG &= __cpu_to_le32(~(1 << gpio));
break;
case GPIO_TYPE_OUTPUT:
*(volatile u32 *) GPIO_OE_REG |= __cpu_to_le32(1 << gpio);
break;
}
return 0;
err:
return -1;
}
static void config_board1(void)
{
u64 wr_dqs_shift = 0x40;
*(volatile u64*)(DENALI_CTL_00_DATA) = __cpu_to_le64((u64)DENALI_CTL_00_VAL_CFG1);
*(volatile u64*)(DENALI_CTL_01_DATA) = __cpu_to_le64((u64)DENALI_CTL_01_VAL_CFG1);
*(volatile u64*)(DENALI_CTL_02_DATA) = __cpu_to_le64((u64)DENALI_CTL_02_VAL_CFG1);
*(volatile u64*)(DENALI_CTL_03_DATA) = __cpu_to_le64((u64)DENALI_CTL_03_VAL_CFG1);
*(volatile u64*)(DENALI_CTL_04_DATA) = __cpu_to_le64((u64)DENALI_CTL_04_VAL_CFG1);
*(volatile u64*)(DENALI_CTL_05_DATA) = __cpu_to_le64((u64)DENALI_CTL_05_VAL_CFG1);
*(volatile u64*)(DENALI_CTL_06_DATA) = __cpu_to_le64((u64)DENALI_CTL_06_VAL_CFG1);
*(volatile u64*)(DENALI_CTL_07_DATA) = __cpu_to_le64((u64)DENALI_CTL_07_VAL_CFG1);
*(volatile u64*)(DENALI_CTL_08_DATA) = __cpu_to_le64((u64)DENALI_CTL_08_VAL_CFG1);
*(volatile u64*)(DENALI_CTL_09_DATA) = __cpu_to_le64((u64)DENALI_CTL_09_VAL_CFG1);
*(volatile u64*)(DENALI_CTL_10_DATA) = __cpu_to_le64((u64)DENALI_CTL_10_VAL_CFG1);
*(volatile u64*)(DENALI_CTL_11_DATA) = __cpu_to_le64((u64)DENALI_CTL_11_VAL_CFG1);
*(volatile u64*)(DENALI_CTL_12_DATA) = __cpu_to_le64((u64)DENALI_CTL_12_VAL_CFG1);
*(volatile u64*)(DENALI_CTL_13_DATA) = __cpu_to_le64((u64)DENALI_CTL_13_VAL_CFG1);
*(volatile u64*)(DENALI_CTL_14_DATA) = __cpu_to_le64((u64)DENALI_CTL_14_VAL_CFG1);
*(volatile u64*)(DENALI_CTL_15_DATA) = __cpu_to_le64((u64)DENALI_CTL_15_VAL_CFG1);
*(volatile u64*)(DENALI_CTL_16_DATA) = __cpu_to_le64((u64)DENALI_CTL_16_VAL_CFG1);
*(volatile u64*)(DENALI_CTL_17_DATA) = __cpu_to_le64((u64)DENALI_CTL_17_VAL_CFG1);
*(volatile u64*)(DENALI_CTL_18_DATA) = __cpu_to_le64((u64)DENALI_CTL_18_VAL_CFG1);
*(volatile u64*)(DENALI_CTL_19_DATA) = __cpu_to_le64((u64)DENALI_CTL_19_VAL_CFG1);
*(volatile u64*)(DENALI_CTL_20_DATA) = __cpu_to_le64((u64)DENALI_CTL_20_VAL_CFG1);
// start DDRC
*(volatile u64*)(DENALI_CTL_02_DATA) = __cpu_to_le64((u64)DENALI_CTL_02_VAL_CFG1 | (1LL << 32));
//wait int_status[2] (DRAM init complete)
while(( *(volatile u32*)(DENALI_CTL_08_DATA+4) & __cpu_to_le32(0x040000)) == 0);
*(volatile u64*)(DENALI_CTL_11_DATA) = __cpu_to_le64(((u64)DENALI_CTL_11_VAL_CFG1 & ~(0x00007F0000000000LL)) | (wr_dqs_shift << 40));
}
static void config_board2(void)
{
u64 wr_dqs_shift = 0x40;
*(volatile u64*)(DENALI_CTL_00_DATA) = __cpu_to_le64((u64)DENALI_CTL_00_VAL_CFG2);
*(volatile u64*)(DENALI_CTL_01_DATA) = __cpu_to_le64((u64)DENALI_CTL_01_VAL_CFG2);
*(volatile u64*)(DENALI_CTL_02_DATA) = __cpu_to_le64((u64)DENALI_CTL_02_VAL_CFG2);
*(volatile u64*)(DENALI_CTL_03_DATA) = __cpu_to_le64((u64)DENALI_CTL_03_VAL_CFG2);
*(volatile u64*)(DENALI_CTL_04_DATA) = __cpu_to_le64((u64)DENALI_CTL_04_VAL_CFG2);
*(volatile u64*)(DENALI_CTL_05_DATA) = __cpu_to_le64((u64)DENALI_CTL_05_VAL_CFG2);
*(volatile u64*)(DENALI_CTL_06_DATA) = __cpu_to_le64((u64)DENALI_CTL_06_VAL_CFG2);
*(volatile u64*)(DENALI_CTL_07_DATA) = __cpu_to_le64((u64)DENALI_CTL_07_VAL_CFG2);
*(volatile u64*)(DENALI_CTL_08_DATA) = __cpu_to_le64((u64)DENALI_CTL_08_VAL_CFG2);
*(volatile u64*)(DENALI_CTL_09_DATA) = __cpu_to_le64((u64)DENALI_CTL_09_VAL_CFG2);
*(volatile u64*)(DENALI_CTL_10_DATA) = __cpu_to_le64((u64)DENALI_CTL_10_VAL_CFG2);
*(volatile u64*)(DENALI_CTL_11_DATA) = __cpu_to_le64((u64)DENALI_CTL_11_VAL_CFG2);
*(volatile u64*)(DENALI_CTL_12_DATA) = __cpu_to_le64((u64)DENALI_CTL_12_VAL_CFG2);
*(volatile u64*)(DENALI_CTL_13_DATA) = __cpu_to_le64((u64)DENALI_CTL_13_VAL_CFG2);
*(volatile u64*)(DENALI_CTL_14_DATA) = __cpu_to_le64((u64)DENALI_CTL_14_VAL_CFG2);
*(volatile u64*)(DENALI_CTL_15_DATA) = __cpu_to_le64((u64)DENALI_CTL_15_VAL_CFG2);
*(volatile u64*)(DENALI_CTL_16_DATA) = __cpu_to_le64((u64)DENALI_CTL_16_VAL_CFG2);
*(volatile u64*)(DENALI_CTL_17_DATA) = __cpu_to_le64((u64)DENALI_CTL_17_VAL_CFG2);
*(volatile u64*)(DENALI_CTL_18_DATA) = __cpu_to_le64((u64)DENALI_CTL_18_VAL_CFG2);
*(volatile u64*)(DENALI_CTL_19_DATA) = __cpu_to_le64((u64)DENALI_CTL_19_VAL_CFG2);
*(volatile u64*)(DENALI_CTL_20_DATA) = __cpu_to_le64((u64)DENALI_CTL_20_VAL_CFG2);
// start DDRC
*(volatile u64*)(DENALI_CTL_02_DATA) = __cpu_to_le64((u64)DENALI_CTL_02_VAL_CFG2 | (1LL << 32));
//wait int_status[2] (DRAM init complete)
while(( *(volatile u32*)(DENALI_CTL_08_DATA+4) & __cpu_to_le32(0x040000)) == 0);
*(volatile u64*)(DENALI_CTL_11_DATA) = __cpu_to_le64(((u64)DENALI_CTL_11_VAL_CFG2 & ~(0x00007F0000000000LL)) | (wr_dqs_shift << 40));
}
static void config_board3(void)
{
u64 wr_dqs_shift = 0x40;
*(volatile u64*)(DENALI_CTL_00_DATA) = __cpu_to_le64((u64)DENALI_CTL_00_VAL_CFG3);
*(volatile u64*)(DENALI_CTL_01_DATA) = __cpu_to_le64((u64)DENALI_CTL_01_VAL_CFG3);
*(volatile u64*)(DENALI_CTL_02_DATA) = __cpu_to_le64((u64)DENALI_CTL_02_VAL_CFG3);
*(volatile u64*)(DENALI_CTL_03_DATA) = __cpu_to_le64((u64)DENALI_CTL_03_VAL_CFG3);
*(volatile u64*)(DENALI_CTL_04_DATA) = __cpu_to_le64((u64)DENALI_CTL_04_VAL_CFG3);
*(volatile u64*)(DENALI_CTL_05_DATA) = __cpu_to_le64((u64)DENALI_CTL_05_VAL_CFG3);
*(volatile u64*)(DENALI_CTL_06_DATA) = __cpu_to_le64((u64)DENALI_CTL_06_VAL_CFG3);
*(volatile u64*)(DENALI_CTL_07_DATA) = __cpu_to_le64((u64)DENALI_CTL_07_VAL_CFG3);
*(volatile u64*)(DENALI_CTL_08_DATA) = __cpu_to_le64((u64)DENALI_CTL_08_VAL_CFG3);
*(volatile u64*)(DENALI_CTL_09_DATA) = __cpu_to_le64((u64)DENALI_CTL_09_VAL_CFG3);
*(volatile u64*)(DENALI_CTL_10_DATA) = __cpu_to_le64((u64)DENALI_CTL_10_VAL_CFG3);
*(volatile u64*)(DENALI_CTL_11_DATA) = __cpu_to_le64((u64)DENALI_CTL_11_VAL_CFG3);
*(volatile u64*)(DENALI_CTL_12_DATA) = __cpu_to_le64((u64)DENALI_CTL_12_VAL_CFG3);
*(volatile u64*)(DENALI_CTL_13_DATA) = __cpu_to_le64((u64)DENALI_CTL_13_VAL_CFG3);
*(volatile u64*)(DENALI_CTL_14_DATA) = __cpu_to_le64((u64)DENALI_CTL_14_VAL_CFG3);
*(volatile u64*)(DENALI_CTL_15_DATA) = __cpu_to_le64((u64)DENALI_CTL_15_VAL_CFG3);
*(volatile u64*)(DENALI_CTL_16_DATA) = __cpu_to_le64((u64)DENALI_CTL_16_VAL_CFG3);
*(volatile u64*)(DENALI_CTL_17_DATA) = __cpu_to_le64((u64)DENALI_CTL_17_VAL_CFG3);
*(volatile u64*)(DENALI_CTL_18_DATA) = __cpu_to_le64((u64)DENALI_CTL_18_VAL_CFG3);
*(volatile u64*)(DENALI_CTL_19_DATA) = __cpu_to_le64((u64)DENALI_CTL_19_VAL_CFG3);
*(volatile u64*)(DENALI_CTL_20_DATA) = __cpu_to_le64((u64)DENALI_CTL_20_VAL_CFG3);
// start DDRC
*(volatile u64*)(DENALI_CTL_02_DATA) = __cpu_to_le64((u64)DENALI_CTL_02_VAL_CFG3 | (1LL << 32));
//wait int_status[2] (DRAM init complete)
while(( *(volatile u32*)(DENALI_CTL_08_DATA+4) & __cpu_to_le32(0x040000)) == 0);
*(volatile u64*)(DENALI_CTL_11_DATA) = __cpu_to_le64(((u64)DENALI_CTL_11_VAL_CFG3 & ~(0x00007F0000000000LL)) | (wr_dqs_shift << 40));
}
static void config_board4(void)
{
u64 wr_dqs_shift = 0x40;
*(volatile u64*)(DENALI_CTL_00_DATA) = __cpu_to_le64((u64)DENALI_CTL_00_VAL_CFG4);
*(volatile u64*)(DENALI_CTL_01_DATA) = __cpu_to_le64((u64)DENALI_CTL_01_VAL_CFG4);
*(volatile u64*)(DENALI_CTL_02_DATA) = __cpu_to_le64((u64)DENALI_CTL_02_VAL_CFG4);
*(volatile u64*)(DENALI_CTL_03_DATA) = __cpu_to_le64((u64)DENALI_CTL_03_VAL_CFG4);
*(volatile u64*)(DENALI_CTL_04_DATA) = __cpu_to_le64((u64)DENALI_CTL_04_VAL_CFG4);
*(volatile u64*)(DENALI_CTL_05_DATA) = __cpu_to_le64((u64)DENALI_CTL_05_VAL_CFG4);
*(volatile u64*)(DENALI_CTL_06_DATA) = __cpu_to_le64((u64)DENALI_CTL_06_VAL_CFG4);
*(volatile u64*)(DENALI_CTL_07_DATA) = __cpu_to_le64((u64)DENALI_CTL_07_VAL_CFG4);
*(volatile u64*)(DENALI_CTL_08_DATA) = __cpu_to_le64((u64)DENALI_CTL_08_VAL_CFG4);
*(volatile u64*)(DENALI_CTL_09_DATA) = __cpu_to_le64((u64)DENALI_CTL_09_VAL_CFG4);
*(volatile u64*)(DENALI_CTL_10_DATA) = __cpu_to_le64((u64)DENALI_CTL_10_VAL_CFG4);
*(volatile u64*)(DENALI_CTL_11_DATA) = __cpu_to_le64((u64)DENALI_CTL_11_VAL_CFG4);
*(volatile u64*)(DENALI_CTL_12_DATA) = __cpu_to_le64((u64)DENALI_CTL_12_VAL_CFG4);
*(volatile u64*)(DENALI_CTL_13_DATA) = __cpu_to_le64((u64)DENALI_CTL_13_VAL_CFG4);
*(volatile u64*)(DENALI_CTL_14_DATA) = __cpu_to_le64((u64)DENALI_CTL_14_VAL_CFG4);
*(volatile u64*)(DENALI_CTL_15_DATA) = __cpu_to_le64((u64)DENALI_CTL_15_VAL_CFG4);
*(volatile u64*)(DENALI_CTL_16_DATA) = __cpu_to_le64((u64)DENALI_CTL_16_VAL_CFG4);
*(volatile u64*)(DENALI_CTL_17_DATA) = __cpu_to_le64((u64)DENALI_CTL_17_VAL_CFG4);
*(volatile u64*)(DENALI_CTL_18_DATA) = __cpu_to_le64((u64)DENALI_CTL_18_VAL_CFG4);
*(volatile u64*)(DENALI_CTL_19_DATA) = __cpu_to_le64((u64)DENALI_CTL_19_VAL_CFG4);
*(volatile u64*)(DENALI_CTL_20_DATA) = __cpu_to_le64((u64)DENALI_CTL_20_VAL_CFG4);
// start DDRC
*(volatile u64*)(DENALI_CTL_02_DATA) = __cpu_to_le64((u64)DENALI_CTL_02_VAL_CFG4 | (1LL << 32));
//wait int_status[2] (DRAM init complete)
while(( *(volatile u32*)(DENALI_CTL_08_DATA+4) & __cpu_to_le32(0x040000)) == 0);
*(volatile u64*)(DENALI_CTL_11_DATA) = __cpu_to_le64(((u64)DENALI_CTL_11_VAL_CFG4 & ~(0x00007F0000000000LL)) | (wr_dqs_shift << 40));
}
static void config_board5(void)
{
u64 wr_dqs_shift = 0x40;
*(volatile u64*)(DENALI_CTL_00_DATA) = __cpu_to_le64((u64)DENALI_CTL_00_VAL_CFG5);
*(volatile u64*)(DENALI_CTL_01_DATA) = __cpu_to_le64((u64)DENALI_CTL_01_VAL_CFG5);
*(volatile u64*)(DENALI_CTL_02_DATA) = __cpu_to_le64((u64)DENALI_CTL_02_VAL_CFG5);
*(volatile u64*)(DENALI_CTL_03_DATA) = __cpu_to_le64((u64)DENALI_CTL_03_VAL_CFG5);
*(volatile u64*)(DENALI_CTL_04_DATA) = __cpu_to_le64((u64)DENALI_CTL_04_VAL_CFG5);
*(volatile u64*)(DENALI_CTL_05_DATA) = __cpu_to_le64((u64)DENALI_CTL_05_VAL_CFG5);
*(volatile u64*)(DENALI_CTL_06_DATA) = __cpu_to_le64((u64)DENALI_CTL_06_VAL_CFG5);
*(volatile u64*)(DENALI_CTL_07_DATA) = __cpu_to_le64((u64)DENALI_CTL_07_VAL_CFG5);
*(volatile u64*)(DENALI_CTL_08_DATA) = __cpu_to_le64((u64)DENALI_CTL_08_VAL_CFG5);
*(volatile u64*)(DENALI_CTL_09_DATA) = __cpu_to_le64((u64)DENALI_CTL_09_VAL_CFG5);
*(volatile u64*)(DENALI_CTL_10_DATA) = __cpu_to_le64((u64)DENALI_CTL_10_VAL_CFG5);
*(volatile u64*)(DENALI_CTL_11_DATA) = __cpu_to_le64((u64)DENALI_CTL_11_VAL_CFG5);
*(volatile u64*)(DENALI_CTL_12_DATA) = __cpu_to_le64((u64)DENALI_CTL_12_VAL_CFG5);
*(volatile u64*)(DENALI_CTL_13_DATA) = __cpu_to_le64((u64)DENALI_CTL_13_VAL_CFG5);
*(volatile u64*)(DENALI_CTL_14_DATA) = __cpu_to_le64((u64)DENALI_CTL_14_VAL_CFG5);
*(volatile u64*)(DENALI_CTL_15_DATA) = __cpu_to_le64((u64)DENALI_CTL_15_VAL_CFG5);
*(volatile u64*)(DENALI_CTL_16_DATA) = __cpu_to_le64((u64)DENALI_CTL_16_VAL_CFG5);
*(volatile u64*)(DENALI_CTL_17_DATA) = __cpu_to_le64((u64)DENALI_CTL_17_VAL_CFG5);
*(volatile u64*)(DENALI_CTL_18_DATA) = __cpu_to_le64((u64)DENALI_CTL_18_VAL_CFG5);
*(volatile u64*)(DENALI_CTL_19_DATA) = __cpu_to_le64((u64)DENALI_CTL_19_VAL_CFG5);
*(volatile u64*)(DENALI_CTL_20_DATA) = __cpu_to_le64((u64)DENALI_CTL_20_VAL_CFG5);
// start DDRC
*(volatile u64*)(DENALI_CTL_02_DATA) = __cpu_to_le64((u64)DENALI_CTL_02_VAL_CFG5 | (1LL << 32));
//wait int_status[2] (DRAM init complete)
while(( *(volatile u32*)(DENALI_CTL_08_DATA+4) & __cpu_to_le32(0x040000)) == 0);
*(volatile u64*)(DENALI_CTL_11_DATA) = __cpu_to_le64(((u64)DENALI_CTL_11_VAL_CFG5 & ~(0x00007F0000000000LL)) | (wr_dqs_shift << 40));
}
static void config_board6(void)
{
u64 wr_dqs_shift = 0x40;
*(volatile u64*)(DENALI_CTL_00_DATA) = __cpu_to_le64((u64)DENALI_CTL_00_VAL_CFG6);
*(volatile u64*)(DENALI_CTL_01_DATA) = __cpu_to_le64((u64)DENALI_CTL_01_VAL_CFG6);
*(volatile u64*)(DENALI_CTL_02_DATA) = __cpu_to_le64((u64)DENALI_CTL_02_VAL_CFG6);
*(volatile u64*)(DENALI_CTL_03_DATA) = __cpu_to_le64((u64)DENALI_CTL_03_VAL_CFG6);
*(volatile u64*)(DENALI_CTL_04_DATA) = __cpu_to_le64((u64)DENALI_CTL_04_VAL_CFG6);
*(volatile u64*)(DENALI_CTL_05_DATA) = __cpu_to_le64((u64)DENALI_CTL_05_VAL_CFG6);
*(volatile u64*)(DENALI_CTL_06_DATA) = __cpu_to_le64((u64)DENALI_CTL_06_VAL_CFG6);
*(volatile u64*)(DENALI_CTL_07_DATA) = __cpu_to_le64((u64)DENALI_CTL_07_VAL_CFG6);
*(volatile u64*)(DENALI_CTL_08_DATA) = __cpu_to_le64((u64)DENALI_CTL_08_VAL_CFG6);
*(volatile u64*)(DENALI_CTL_09_DATA) = __cpu_to_le64((u64)DENALI_CTL_09_VAL_CFG6);
*(volatile u64*)(DENALI_CTL_10_DATA) = __cpu_to_le64((u64)DENALI_CTL_10_VAL_CFG6);
*(volatile u64*)(DENALI_CTL_11_DATA) = __cpu_to_le64((u64)DENALI_CTL_11_VAL_CFG6);
*(volatile u64*)(DENALI_CTL_12_DATA) = __cpu_to_le64((u64)DENALI_CTL_12_VAL_CFG6);
*(volatile u64*)(DENALI_CTL_13_DATA) = __cpu_to_le64((u64)DENALI_CTL_13_VAL_CFG6);
*(volatile u64*)(DENALI_CTL_14_DATA) = __cpu_to_le64((u64)DENALI_CTL_14_VAL_CFG6);
*(volatile u64*)(DENALI_CTL_15_DATA) = __cpu_to_le64((u64)DENALI_CTL_15_VAL_CFG6);
*(volatile u64*)(DENALI_CTL_16_DATA) = __cpu_to_le64((u64)DENALI_CTL_16_VAL_CFG6);
*(volatile u64*)(DENALI_CTL_17_DATA) = __cpu_to_le64((u64)DENALI_CTL_17_VAL_CFG6);
*(volatile u64*)(DENALI_CTL_18_DATA) = __cpu_to_le64((u64)DENALI_CTL_18_VAL_CFG6);
*(volatile u64*)(DENALI_CTL_19_DATA) = __cpu_to_le64((u64)DENALI_CTL_19_VAL_CFG6);
*(volatile u64*)(DENALI_CTL_20_DATA) = __cpu_to_le64((u64)DENALI_CTL_20_VAL_CFG6);
// start DDRC
*(volatile u64*)(DENALI_CTL_02_DATA) = __cpu_to_le64((u64)DENALI_CTL_02_VAL_CFG6 | (1LL << 32));
//wait int_status[2] (DRAM init complete)
while(( *(volatile u32*)(DENALI_CTL_08_DATA+4) & __cpu_to_le32(0x040000)) == 0);
*(volatile u64*)(DENALI_CTL_11_DATA) = __cpu_to_le64(((u64)DENALI_CTL_11_VAL_CFG6 & ~(0x00007F0000000000LL)) | (wr_dqs_shift << 40));
}
static void config_board7(void)
{
config_board5(); /* config 7 is same as config 5 */
}
static void config_board8(void)
{
/* Dali MoCA EVMs have same memory subsystem as PacketIAD EVM */
config_board4();
}
/* Similar to Config #4 (Packet IAD) */
static void config_board9(void)
{
u64 wr_dqs_shift = 0x40;
*(volatile u64*)(DENALI_CTL_00_DATA) = __cpu_to_le64((u64)DENALI_CTL_00_VAL_CFG4);
*(volatile u64*)(DENALI_CTL_01_DATA) = __cpu_to_le64((u64)DENALI_CTL_01_VAL_CFG4);
*(volatile u64*)(DENALI_CTL_02_DATA) = __cpu_to_le64((u64)DENALI_CTL_02_VAL_CFG4);
*(volatile u64*)(DENALI_CTL_03_DATA) = __cpu_to_le64((u64)DENALI_CTL_03_VAL_CFG4);
*(volatile u64*)(DENALI_CTL_04_DATA) = __cpu_to_le64((u64)DENALI_CTL_04_VAL_CFG4);
*(volatile u64*)(DENALI_CTL_05_DATA) = __cpu_to_le64((u64)DENALI_CTL_05_VAL_CFG4);
*(volatile u64*)(DENALI_CTL_06_DATA) = __cpu_to_le64((u64)DENALI_CTL_06_VAL_CFG4);
*(volatile u64*)(DENALI_CTL_07_DATA) = __cpu_to_le64((u64)DENALI_CTL_07_VAL_CFG4_C50);
*(volatile u64*)(DENALI_CTL_08_DATA) = __cpu_to_le64((u64)DENALI_CTL_08_VAL_CFG4_C50);
*(volatile u64*)(DENALI_CTL_09_DATA) = __cpu_to_le64((u64)DENALI_CTL_09_VAL_CFG4);
*(volatile u64*)(DENALI_CTL_10_DATA) = __cpu_to_le64((u64)DENALI_CTL_10_VAL_CFG4);
*(volatile u64*)(DENALI_CTL_11_DATA) = __cpu_to_le64((u64)DENALI_CTL_11_VAL_CFG4_C50);
*(volatile u64*)(DENALI_CTL_12_DATA) = __cpu_to_le64((u64)DENALI_CTL_12_VAL_CFG4_C50);
*(volatile u64*)(DENALI_CTL_13_DATA) = __cpu_to_le64((u64)DENALI_CTL_13_VAL_CFG4);
*(volatile u64*)(DENALI_CTL_14_DATA) = __cpu_to_le64((u64)DENALI_CTL_14_VAL_CFG4);
*(volatile u64*)(DENALI_CTL_15_DATA) = __cpu_to_le64((u64)DENALI_CTL_15_VAL_CFG4_C50);
*(volatile u64*)(DENALI_CTL_16_DATA) = __cpu_to_le64((u64)DENALI_CTL_16_VAL_CFG4_C50);
*(volatile u64*)(DENALI_CTL_17_DATA) = __cpu_to_le64((u64)DENALI_CTL_17_VAL_CFG4);
*(volatile u64*)(DENALI_CTL_18_DATA) = __cpu_to_le64((u64)DENALI_CTL_18_VAL_CFG4_C50);
*(volatile u64*)(DENALI_CTL_19_DATA) = __cpu_to_le64((u64)DENALI_CTL_19_VAL_CFG4_C50);
*(volatile u64*)(DENALI_CTL_20_DATA) = __cpu_to_le64((u64)DENALI_CTL_20_VAL_CFG4_C50);
// start DDRC
*(volatile u64*)(DENALI_CTL_02_DATA) = __cpu_to_le64((u64)DENALI_CTL_02_VAL_CFG4 | (1LL << 32));
//wait int_status[2] (DRAM init complete)
while(( *(volatile u32*)(DENALI_CTL_08_DATA+4) & __cpu_to_le32(0x040000)) == 0);
*(volatile u64*)(DENALI_CTL_11_DATA) = __cpu_to_le64(((u64)DENALI_CTL_11_VAL_CFG4_C50 & ~(0x00007F0000000000LL)) | (wr_dqs_shift << 40));
}
/* Board cfg 10 is defined for C50 Router EVM */
static void config_board10(void)
{
u64 wr_dqs_shift = 0x40;
*(volatile u64*)(DENALI_CTL_00_DATA) = __cpu_to_le64((u64)DENALI_CTL_00_VAL_CFG10);
*(volatile u64*)(DENALI_CTL_01_DATA) = __cpu_to_le64((u64)DENALI_CTL_01_VAL_CFG10);
*(volatile u64*)(DENALI_CTL_02_DATA) = __cpu_to_le64((u64)DENALI_CTL_02_VAL_CFG10);
*(volatile u64*)(DENALI_CTL_03_DATA) = __cpu_to_le64((u64)DENALI_CTL_03_VAL_CFG10);
*(volatile u64*)(DENALI_CTL_04_DATA) = __cpu_to_le64((u64)DENALI_CTL_04_VAL_CFG10);
*(volatile u64*)(DENALI_CTL_05_DATA) = __cpu_to_le64((u64)DENALI_CTL_05_VAL_CFG10);
*(volatile u64*)(DENALI_CTL_06_DATA) = __cpu_to_le64((u64)DENALI_CTL_06_VAL_CFG10);
*(volatile u64*)(DENALI_CTL_07_DATA) = __cpu_to_le64((u64)DENALI_CTL_07_VAL_CFG10);
*(volatile u64*)(DENALI_CTL_08_DATA) = __cpu_to_le64((u64)DENALI_CTL_08_VAL_CFG10);
*(volatile u64*)(DENALI_CTL_09_DATA) = __cpu_to_le64((u64)DENALI_CTL_09_VAL_CFG10);
*(volatile u64*)(DENALI_CTL_10_DATA) = __cpu_to_le64((u64)DENALI_CTL_10_VAL_CFG10);
*(volatile u64*)(DENALI_CTL_11_DATA) = __cpu_to_le64((u64)DENALI_CTL_11_VAL_CFG10);
*(volatile u64*)(DENALI_CTL_12_DATA) = __cpu_to_le64((u64)DENALI_CTL_12_VAL_CFG10);
*(volatile u64*)(DENALI_CTL_13_DATA) = __cpu_to_le64((u64)DENALI_CTL_13_VAL_CFG10);
*(volatile u64*)(DENALI_CTL_14_DATA) = __cpu_to_le64((u64)DENALI_CTL_14_VAL_CFG10);
*(volatile u64*)(DENALI_CTL_15_DATA) = __cpu_to_le64((u64)DENALI_CTL_15_VAL_CFG10);
*(volatile u64*)(DENALI_CTL_16_DATA) = __cpu_to_le64((u64)DENALI_CTL_16_VAL_CFG10);
*(volatile u64*)(DENALI_CTL_17_DATA) = __cpu_to_le64((u64)DENALI_CTL_17_VAL_CFG10);
*(volatile u64*)(DENALI_CTL_18_DATA) = __cpu_to_le64((u64)DENALI_CTL_18_VAL_CFG10);
*(volatile u64*)(DENALI_CTL_19_DATA) = __cpu_to_le64((u64)DENALI_CTL_19_VAL_CFG10);
*(volatile u64*)(DENALI_CTL_20_DATA) = __cpu_to_le64((u64)DENALI_CTL_20_VAL_CFG10);
// start DDRC
*(volatile u64*)(DENALI_CTL_02_DATA) = __cpu_to_le64((u64)DENALI_CTL_02_VAL_CFG10 | (1LL << 32));
//wait int_status[2] (DRAM init complete)
while(( *(volatile u32*)(DENALI_CTL_08_DATA+4) & __cpu_to_le32(0x040000)) == 0);
*(volatile u64*)(DENALI_CTL_11_DATA) = __cpu_to_le64(((u64)DENALI_CTL_11_VAL_CFG10 & ~(0x00007F0000000000LL)) | (wr_dqs_shift << 40));
}
@@ -0,0 +1,162 @@
/*
* Copyright (C) 2007-2008 Mindspeed Technologies Inc.
*
* 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 <common.h>
#include <asm/hardware.h>
u32 CFG_HZ_CLOCK; /* Allow for AHB clock frequency to be chosen at run time */
void SoC_Check_Device(void)
{
// This should run on a M83xxx SoC, let's check it
u32 devicetype = __le32_to_cpu((*(volatile u32*)(GPIO_DEVID_REG)) & __cpu_to_le32(0xFFFF));
if (devicetype != 0x170)
{
//error wrong device
// TODO: what should we do?
}
}
void SoC_APB_setup(void)
{
// Setting APB Bus Wait states to 0, set post write
*(volatile u32*)(APB_ACCESS_WS_REG) = __cpu_to_le32(0x40);
}
void SoC_ARAM_setup(void)
{
// enable ARAM collision detection
// read mod write to set bit 2 to enable. Keep default of 32 byte mask
*(volatile u32*)(MEMCORE_BASEADDR+0x4) |= __cpu_to_le32(4);
// disable ARAM pipeline mode
*(volatile u32*)(MEMCORE_BASEADDR+0x38) = __cpu_to_le32(0);
// set ARAM port/fbp priority to 1
*(volatile u32*)(MEMCORE_BASEADDR+0x0C) = __cpu_to_le32(3);
}
void SoC_AHB_setup(void)
{
// DDR size 512MB, starting from 80000000
*(volatile u32*) AHB_HIGHMEM_ADDR_TRANSLATION = __cpu_to_le32(0x9FFF); //(AHB_BASEADDR + 0x04)
// Disable REMAP (Low Mem region is mapped to DDR base)
*(volatile u32*) AHB_LOWMEM_REMAP_CTRL = __cpu_to_le32(0x0); //(AHB_BASEADDR + 0x00)
// 2nd stage level muxs are configured to round-robin
*(volatile u32*) AHB_STAGE2_ARBITER_CFG = __cpu_to_le32(0x0); //(AHB_BASEADDR + 0x08)
}
void SoC_PLL_init(int cfg)
{
struct c1000_cfg_clk c1000_cfg_clk_table[] =
{
[CFG_CLK_650_187_375] = {650000000, 3, 4, 750000000, 2, 2, 250000000, 3, 8, 0, 650000000, 0, 187500000, 375000000, 250000000}, /* M8326x, 375MHz */
[CFG_CLK_600_165_330] = {600000000, 1, 4, 660000000, 1, 4, 250000000, 3, 8, 0, 600000000, 0, 165000000, 330000000, 110000000}, /* M83160 */
[CFG_CLK_534_178_330] = {660000000, 1, 4, 534000000, 1, 4, 250000000, 3, 8, 1, 534000000, 1, 178000000, 330000000, 178000000}, /* M8325x */
[CFG_CLK_450_165_330] = {450000000, 1, 4, 660000000, 1, 4, 250000000, 3, 8, 0, 450000000, 0, 165000000, 330000000, 110000000}, /* M8324x */
[CFG_CLK_400_165_330] = {400000000, 2, 6, 660000000, 1, 4, 250000000, 3, 8, 0, 400000000, 0, 165000000, 330000000, 110000000}, /* M83240 */
[CFG_CLK_650_200_200] = {650000000, 3, 4, 800000000, 3, 2, 250000000, 3, 8, 0, 650000000, 0, 200000000, 200000000, 266666666}, /* M8326x, 200MHz */
[CFG_CLK_650_187_325] = {650000000, 3, 4, 750000000, 2, 2, 250000000, 3, 8, 0, 650000000, 1, 187500000, 325000000, 250000000}, /* Asic */
[CFG_CLK_610_186_372] = {610000000, 3, 4, 744000000, 2, 2, 250000000, 3, 8, 0, 610000000, 0, 186000000, 372000000, 248000000} /* Asic */
};
struct c1000_cfg_clk *cfg_clk = &c1000_cfg_clk_table[cfg];
// *(volatile u32*)(GPIO_ARM_MEMORY_SENSE_REGS) = __cpu_to_le32(0x1B6DB6DB); /* Margin = 3 */
//*(volatile u32*)(GPIO_ARM_MEMORY_SENSE_REGS) = __cpu_to_le32(0x24924924); /* Margin = 4 */
*(volatile u32*)(GPIO_ARM_MEMORY_SENSE_REGS) = __cpu_to_le32(0x2DB6DB6D); /* Margin = 5 */
// Make sure DDR controller is reset
*(volatile u32*)(CLKCORE_BLK_RESET) &= __cpu_to_le32(~(BLK_RESET_DDR_REF_RESET_N | BLK_RESET_DDR_AHB_RESET_N));
HAL_all_pll_bypass();
// Take DDR controller out of reset
*(volatile u32*)(CLKCORE_BLK_RESET) |= __cpu_to_le32(BLK_RESET_DDR_REF_RESET_N | BLK_RESET_DDR_AHB_RESET_N);
HAL_set_arm_pll(cfg_clk->arm_pll, cfg_clk->arm_pll_nr, cfg_clk->arm_pll_od);
HAL_set_ahb_pll(cfg_clk->ahb_pll, cfg_clk->ahb_pll_nr, cfg_clk->ahb_pll_od);
HAL_set_phy_pll(cfg_clk->phy_pll, cfg_clk->phy_pll_nr, cfg_clk->phy_pll_od);
HAL_set_arm_clk(cfg_clk->arm_clk, cfg_clk->arm_clk, cfg_clk->arm_from_sclk2);
HAL_set_ahb_ddr_clk(cfg_clk->ahb_clk, cfg_clk->ddr_clk, cfg_clk->ddr_from_fclk);
HAL_set_phy_gem_clk(CFG_GEM0_CLOCK, CFG_GEM1_CLOCK, CFG_PHY_CLOCK);
HAL_set_ipsec_clk(cfg_clk->ipsec_clk);
HAL_all_pll_remove_bypass();
}
void SoC_nand_init(void)
{
// TODO: verify timings
// Configure CS4 - 8 bits - NAND
*(volatile u32*)(EX_CS4_CFG_REG) = __cpu_to_le32(EX_MEM_BUS_8 | EX_NAND_MODE);
// timings (CSw = 9, RE WE 9),
*(volatile u32*)(EX_CS4_TMG1_REG) = __cpu_to_le32(9 | 9<<16 | 9<<24) ;
*(volatile u32*)(EX_CSEN_REG) |= __cpu_to_le32(EX_CS4_EN);
}
/*
* SoC_gpio_cfg - configure GPIO pins as input or output pins
*
* gpio - gpio pin
*
* mode - gpio pin mode
* GPIO_TYPE_OUTPUT = output
* GPIO_TYPE_INPUT = input
*
*/
int SoC_gpio_cfg(int gpio, int mode)
{
if ((gpio < 0) || (gpio > 31))
goto err;
switch (mode) {
case GPIO_TYPE_INPUT:
default:
*(volatile u32 *) GPIO_OE_REG &= __cpu_to_le32(~(1 << gpio));
break;
case GPIO_TYPE_OUTPUT:
*(volatile u32 *) GPIO_OE_REG |= __cpu_to_le32(1 << gpio);
break;
}
return 0;
err:
return -1;
}
void arm_write64(u64 data,volatile u64 *p)
{
int *tptr = &data;
register int reg_0 __asm__ ("r3");
register int reg_1 __asm__ ("r4");
__asm__ __volatile__ (
"ldmia %0, {%1,%2} \n\t"
: "+r" (tptr), "=r" (reg_0), "=r" (reg_1)
);
__asm__ __volatile__ (
"stmia %0, {%1,%2} \n\t"
: "+r" (p), "=r" (reg_0), "=r" (reg_1)
);
}
@@ -0,0 +1,129 @@
#include <common.h>
#include <asm/arch/hardware.h>
#include <asm/arch/scc.h>
void SoC_Check_Device(void)
{
// This should run on a M829xx SoC, let's check it
u32 devicetype = *(volatile u32*)(0x1008002C);
if(devicetype != 0x140)
{
//error wrong device
// TODO: what should we do?
}
}
void SoC_PLL_init(void)
{
//sys_write_control(CR_M | CR_V | CR_ASYNC);
u32 i = 0;//CR_M | CR_V | CR_ASYNC;
/* turn off I/D-cache */
asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
i |= (CR_ASYNC);
asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
HAL_set_amba_clk(133000000);
HAL_set_arm_clk(450000000);
}
//void SoC_mem_init(int controller, int base, int length)
void SoC_mem_init(void)
{
#if 0
//*(volatile u32*)(0x10080010) = 0xD2db;
//*(volatile u32*)(0x1008001c) = 0x42;
//*(volatile u32*)(0x10080014) = 0xEA;
*(volatile u32*)(0x10080010) = 0xD4E3;
// Configure SDRAM CFG2
*(volatile u32*)(0x10080014) = 0x00EA;
//Configure SDRAM REFRESH
*(volatile u32*)(0x10080018) = 0x0820;
//Configure SDRAM PWRON
*(volatile u32*)(0x1008001C) = 0x682B;
*(volatile u32*)(0x10060000) = 0xF;
*(volatile u32*)(0x1006000C) = 5;
#else
if (1)//controller == 0)
{
//matisse only have one SDRAM controller so the first param is useless
// The following settings is based on a SDRAM with clock rate 133 MHz and speed grade -7
// Configure SDRAM CFG1
*(volatile u32*)(0x10080010) = 0xD4E3;
// Configure SDRAM CFG2
*(volatile u32*)(0x10080014) = 0x00EA;
//Configure SDRAM REFRESH
*(volatile u32*)(0x10080018) = 0x0820;
//Configure SDRAM PWRON
*(volatile u32*)(0x1008001C) = 0x682B;
#if 0
// The following settings is based on a DDR-SDRAM with clock rate 133 MHz and speed grade -75z
// Configure SDRAM CFG1
*(volatile u32*)(0x10080010) = 0xD6DA;
// Configure SDRAM CFG2
*(volatile u32*)(0x10080014) = 0x03EA;
//Configure SDRAM REFRESH
*(volatile u32*)(0x10080018) = 0x0820;
//Configure SDRAM PWRON
*(volatile u32*)(0x1008001C) = 0x682B;
#endif
if (PHYS_SDRAM > (128*0x100000)) { // high memory
*(volatile u32*)(0x10060000) = (PHYS_SDRAM >>20)<<4;
*(volatile u32*)(0x10060010) = (PHYS_SDRAM >>27);
}
else {
*(volatile u32*)(0x10060000) = (PHYS_SDRAM >>16)<<4;
}
switch (/*length*/PHYS_SDRAM_SIZE/0x100000)
{
case 8:
*(volatile u32*)(0x10060000) |= 0xB;
break;
case 16:
*(volatile u32*)(0x10060000) |= 0xC;
break;
case 32:
*(volatile u32*)(0x10060000) |= 0xD;
break;
case 64:
*(volatile u32*)(0x10060000) |= 0xE;
break;
case 128:
*(volatile u32*)(0x10060000) |= 0xF;
break;
}
// Enable Chip select 0
//*(volatile u32*)(0x1006000C) |= 0x1;
//*(volatile u32*)(0x1006000C) = 0xC;
if (PHYS_SDRAM > (128*0x100000)) // high memory : do ARAM remap to have memory @0x00000000
*(volatile u32*)(0x1006000C) = 0x115;
else
*(volatile u32*)(0x1006000C) = 0x05;
}
#endif
}
void SoC_flash_init(void)
{
// Configure SDRAM CFG1
*(volatile u32*)(0x10060004) = 0x0010000b;
//*(volatile u32*)(0x10060014) = 0x10;
*(volatile u32*)(0x10060014) = 0;
*(volatile u32*)(0x10080004) = 0x0D92;
*(volatile u32*)(0x1006000C) |= 2;
}
void SoC_nand_init(void)
{
*(volatile u32*)(0x1008000C) = 0x0492;
*(volatile u32*)(0x1006000C) |= 8;
}
@@ -0,0 +1,48 @@
#
# (C) Copyright 2002
# Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
#
# 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
#
#PLATFORM_RELFLAGS := -fno-strict-aliasing $(filter-out -msoft-float, $(PLATFORM_RELFLAGS))
PLATFORM_RELFLAGS := $(filter-out -msoft-float, $(PLATFORM_RELFLAGS))
ifdef BE8_MODE
PLATFORM_RELFLAGS += -mbig-endian -O4 -DBE8_MODE
else
PLATFORM_RELFLAGS += -msoft-float
endif
# Make ARMv5 to allow more compilers to work, even though its v6.
#PLATFORM_CPPFLAGS += -march=armv5
PLATFORM_CPPFLAGS := $(filter-out -march=%, $(PLATFORM_CPPFLAGS)) -march=armv6j
ifdef BE8_MODE
PLATFORM_CPPFLAGS += -mbig-endian
PLATFORM_LDFLAGS += --be8 -EB
endif
# =========================================================================
#
# Supply options according to compiler version
#
# =========================================================================
PLATFORM_RELFLAGS +=$(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,))
@@ -0,0 +1,40 @@
/*
* SOC specific setup info
*
*
* 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 <config.h>
#include <version.h>
#include <asm/arch/hardware.h>
.globl lowlevel_init
lowlevel_init:
ldr sp, TMP_STACK /* set up a temporary stack */
stmdb sp!, {ip, lr}
bl bsp_init /* go setup pll, memory */
ldmia sp!, {ip, pc} /* restore registers and return to caller */
/* the literal pools origin */
.ltorg
TMP_STACK:
.word CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET
@@ -0,0 +1,184 @@
/*
* (C) Copyright Mindspeed Technologies Inc.
*
* 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 <common.h>
#include <asm/hardware.h>
#include <asm/arch/bsp.h>
#if defined(CONFIG_COMCERTO_1000)
#define MDMA_GBL_CTRL_CFG *((volatile u32 *)(MDMA_BASEADDR + 0x0))
#define MDMA_TX1_PATH_HEAD *((volatile u32 *)(MDMA_BASEADDR + 0x4))
#define MDMA_TX1_PATH_CTR *((volatile u32 *)(MDMA_BASEADDR + 0x8))
#define MDMA_RX1_PATH_HEAD *((volatile u32 *)(MDMA_BASEADDR + 0x14))
#define MDMA_RX1_PATH_CTR *((volatile u32 *)(MDMA_BASEADDR + 0x18))
#define MDMA_INT_MASK_REG *((volatile u32 *)(MDMA_BASEADDR + 0x28))
#define MDMA_INT_STATUS_REG0 *((volatile u32 *)(MDMA_BASEADDR + 0x2c))
#define MDMA_INT_STATUS_REG1 *((volatile u32 *)(MDMA_BASEADDR + 0x30))
typedef struct mdma_desc_s
{
u32 dataBufAddr;
u32 control;
u32 msg1;
u32 msg2;
} mdma_desc_t;
/*****************************************************************************
* Function: mdma_memcpy
* Desction:
* Implemenation of memcpy function using MDMA.
* No CRC mechanism supported in C1K.
* Paramters:
* src: Source address
* dst: Destination address
* len: length of the data to be copied.
* crc: Not used
*****************************************************************************/
int mdma_memcpy(void *src, void *dst, int len, unsigned int *crc)
{
u32 stat;
int i;
unsigned char temp1[64];
unsigned char temp2[64];
//descriptor memset to zero
for(i=0; i < 64; i++)
{
temp1[i] = 0;
temp2[i] = 0;
}
len = len - (len % 8);
//Disable MDMA
MDMA_GBL_CTRL_CFG = __cpu_to_le32(0);
//Make it 16byte align
mdma_desc_t *txDesc = (mdma_desc_t *)(((u32)(temp1 + 16)) & ~0xf);
mdma_desc_t *rxDesc = (mdma_desc_t *)(((u32)(temp2 + 16)) & ~0xf);
txDesc->dataBufAddr = __cpu_to_le32((u32)src);
txDesc->control = __cpu_to_le32((u32)(0x41002000 | (len & 0x1fff)));
txDesc->msg1 = txDesc->msg2 = __cpu_to_le32(0);
MDMA_TX1_PATH_HEAD = __cpu_to_le32((u32)txDesc);
MDMA_TX1_PATH_CTR = __cpu_to_le32(1);
rxDesc->dataBufAddr = __cpu_to_le32((u32)dst);
rxDesc->control = __cpu_to_le32((u32)(0x41002000 | (len & 0x1fff)));
rxDesc->msg1 = rxDesc->msg2 = __cpu_to_le32(0);
MDMA_RX1_PATH_HEAD = __cpu_to_le32((u32)rxDesc);
MDMA_RX1_PATH_CTR = __cpu_to_le32(1);
MDMA_INT_MASK_REG = __cpu_to_le32(0);
MDMA_GBL_CTRL_CFG = __cpu_to_le32(1); //Enable MDMA
/* wait until dma done */
while((stat = __le32_to_cpu(MDMA_RX1_PATH_CTR)) != 0);
//Memcpy done, disable MDMA
MDMA_GBL_CTRL_CFG = __cpu_to_le32(0);
return 0;
}
#elif defined(CONFIG_COMCERTO_100)
#define MDMA_MMFIFO_START *((volatile u32 *)(MDMA_BASEADDR + 0x100))
#define MDMA_MMFIFO_HEADPTR *((volatile u32 *)(MDMA_BASEADDR + 0x104))
#define MDMA_MMFIFO_LOCK_TSFR_SIZE *((volatile u32 *)(MDMA_BASEADDR + 0x108))
#define MDMA_MMFIFO_SOFT_RESET *((volatile u32 *)(MDMA_BASEADDR + 0x120))
#define MDMA_FIFOMM_START *((volatile u32 *)(MDMA_BASEADDR + 0x180))
#define MDMA_FIFOMM_HEADPTR *((volatile u32 *)(MDMA_BASEADDR + 0x184))
#define MDMA_FIFOMM_LOCK_TSFR_SIZE *((volatile u32 *)(MDMA_BASEADDR + 0x188))
#define MDMA_FIFOMM_SOFT_RESET *((volatile u32 *)(MDMA_BASEADDR + 0x1A0))
typedef struct mdma_bPtr_s
{
u32 Bpointer;
u32 Bcontrol;
}mdma_bPtr_t;
typedef struct mdma_Fdesc_s
{
u32 Fnext;
u32 Fsystem;
u32 Fstatus;
u32 Fcontrol;
mdma_bPtr_t Bdesc;
}mdma_Fdesc_t;
int mdma_memcpy(void *src, void *dst, int len, unsigned int *crc)
{
unsigned char temp1[64];
unsigned char temp2[64];
volatile unsigned int val;
int i;
//Make it 16byte align
mdma_Fdesc_t *mmfifo = (mdma_Fdesc_t *)(((u32)(temp1 + 16)) & ~0xf);
mdma_Fdesc_t *fifomm = (mdma_Fdesc_t *)(((u32)(temp2 + 16)) & ~0xf);
//descriptor memset to zero
for(i=0; i < 64; i++)
{
temp1[i] = 0;
temp2[i] = 0;
}
/* memory to FIFO */
mmfifo->Fnext = __cpu_to_le32(0x0);
mmfifo->Fsystem = __cpu_to_le32(0);
mmfifo->Fstatus = __cpu_to_le32(0);
mmfifo->Fcontrol = __cpu_to_le32(0x83);
mmfifo->Bdesc.Bpointer = __cpu_to_le32((u32)src);
mmfifo->Bdesc.Bcontrol = __cpu_to_le32((0x10000 | (len & 0xffff)));
/* FIFO to memory */
fifomm->Fnext = __cpu_to_le32(0x0);
fifomm->Fsystem = __cpu_to_le32(0x0);
fifomm->Fstatus = __cpu_to_le32(0x0);
fifomm->Fcontrol = __cpu_to_le32(0x83);
fifomm->Bdesc.Bpointer = __cpu_to_le32((u32)dst);
fifomm->Bdesc.Bcontrol = __cpu_to_le32(len & 0xffff);
MDMA_MMFIFO_SOFT_RESET = __cpu_to_le32(1);
MDMA_FIFOMM_SOFT_RESET = __cpu_to_le32(1);
MDMA_MMFIFO_HEADPTR = __cpu_to_le32((u32)mmfifo);
MDMA_MMFIFO_LOCK_TSFR_SIZE = __cpu_to_le32(64);
MDMA_FIFOMM_HEADPTR = __cpu_to_le32((u32)fifomm);
MDMA_FIFOMM_LOCK_TSFR_SIZE = __cpu_to_le32(64);
MDMA_MMFIFO_START = __cpu_to_le32(0x1);
MDMA_FIFOMM_START = __cpu_to_le32(0x1);
while ((val = __le32_to_cpu(mmfifo->Fstatus)) == 0);
while ((val = __le32_to_cpu(fifomm->Fstatus)) == 0);
/* Return the CRC value */
*crc = __le32_to_cpu(fifomm->Fsystem);
return 0;
}
#endif
@@ -0,0 +1,42 @@
/*
* armboot - Startup Code for OMP2420/ARM1136 CPU-core
*
* Copyright (c) 2004 Texas Instruments <r-woodruff2@ti.com>
*
* Copyright (c) 2001 Marius Gröger <mag@sysgo.de>
* Copyright (c) 2002 Alex Züpke <azu@sysgo.de>
* Copyright (c) 2002 Gary Jennejohn <garyj@denx.de>
* Copyright (c) 2003 Richard Woodruff <r-woodruff2@ti.com>
* Copyright (c) 2003 Kshitij <kshitij@ti.com>
*
* 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 <asm/hardware.h>
.globl reset_cpu
reset_cpu:
ldr r1, rstctl /* get addr for global reset reg */
mov r3, #0x2 /* full reset pll+mpu */
str r3, [r1] /* force reset */
mov r0, r0
_loop_forever:
b _loop_forever
rstctl:
.word PM_RSTCTRL_WKUP
@@ -0,0 +1,219 @@
/*
* (C) Copyright 2006
* Mindspeed Technologies
*
* 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 <common.h>
#include <asm/io.h>
#include <asm/arch/hardware.h>
#include <asm/arch/bsp.h>
#include <asm/byteorder.h>
#if !defined(CONFIG_UART0) && !defined(CONFIG_UART1)
#error must define one of CONFIG_UART0 or CONFIG_UART1
#endif
typedef struct tagUART16550REGS {
volatile u32 data; // Receive/Transmit data register
volatile u32 ier; // Interrupt Enable register
volatile u32 iir_fcr;// Interrupt Identity register / FIFO Control register
volatile u32 lcr; // Line Control register
volatile u32 mcr; // Modem Control register
volatile u32 lsr; // Line Status register
volatile u32 msr; // Modem Status register
volatile u32 sr; // Scratch register
} UART16550REGS, *PUART16550REGS;
typedef struct tagUART16550DLREGS {
volatile u32 dll; // Divisor Latch (Low)
volatile u32 dlh; // Divisor Latch (High)
} UART16550DLREGS, *PUART16550DLREGS;
#define LCR_CHAR_LEN_5 0x00 /* default */
#define LCR_CHAR_LEN_6 0x01
#define LCR_CHAR_LEN_7 0x02
#define LCR_CHAR_LEN_8 0x03
#define LCR_ONE_STOP 0x00 /* One stop bit! - default */
#define LCR_TWO_STOP 0x04 /* Two stop bit! */
#define LCR_PEN 0x08 /* Parity Enable */
#define LCR_PARITY_NONE 0x00
#define LCR_EPS 0x10 /* Even Parity Select */
#define LCR_PS 0x20 /* Enable Parity Stuff */
#define LCR_SBRK 0x40 /* Start Break */
#define LCR_PSB 0x80 /* Parity Stuff Bit */
#define LCR_DLAB 0x80 /* UART 16550 Divisor Latch Assess */
#define LSR_FIFOE (1 << 7) /* FIFO Error Status */
#define LSR_TEMT (1 << 6) /* Transmitter Empty */
#define LSR_TDRQ (1 << 5) /* Transmit Data Request */
#define LSR_BI (1 << 4) /* Break Interrupt */
#define LSR_FE (1 << 3) /* Framing Error */
#define LSR_PE (1 << 2) /* Parity Error */
#define LSR_OE (1 << 1) /* Overrun Error */
#define LSR_DR (1 << 0) /* Data Ready */
#define IER_DMAE (1 << 7) /* DMA Requests Enable */
#define IER_UUE (1 << 6) /* UART Unit Enable */
#define IER_NRZE (1 << 5) /* NRZ coding Enable */
#define IER_RTIOE (1 << 4) /* Receiver Time Out Interrupt Enable */
#define IER_MIE (1 << 3) /* Modem Interrupt Enable */
#define IER_RLSE (1 << 2) /* Receiver Line Status Interrupt Enable */
#define IER_TIE (1 << 1) /* Transmit Data request Interrupt Enable */
#define IER_RAVIE (1 << 0) /* Receiver Data Available Interrupt Enable */
#define IIR_FIFOES1 (1 << 7) /* FIFO Mode Enable Status */
#define IIR_FIFOES0 (1 << 6) /* FIFO Mode Enable Status */
#define IIR_TOD (1 << 3) /* Time Out Detected */
#define IIR_IID2 (1 << 2) /* Interrupt Source Encoded */
#define IIR_IID1 (1 << 1) /* Interrupt Source Encoded */
#define IIR_IP (1 << 0) /* Interrupt Pending (active low) */
/* UART 16550 FIFO Control Register */
#define FCR_FIFOEN 0x01
#define FCR_RCVRRES 0x02
#define FCR_XMITRES 0x04
/* Interrupt Enable Register */
// UART 16550
#define IER_RXTH 0x01 // Enable Received Data Available Interrupt
#define IER_TXTH 0x02 // Enable Transmitter Empty Interrupt
#ifdef CONFIG_UART0
#if defined(CONFIG_COMCERTO_100)
static void EnableUART0(void)
{
u32 temp;
do {
temp = *(volatile u32 *)GPIO_IOCTRL_REG | __cpu_to_le32(GPIO_IOCTRL_UART0); // enable UART0
*(volatile u32 *)GPIO_LOCK_REG = __cpu_to_le32(0x55555555); // remove lock
*(volatile u32 *)GPIO_IOCTRL_REG = temp; // write to ctrl reg
} while (*(volatile u32 *)GPIO_IOCTRL_REG != temp);
}
#endif
#else
#if defined(CONFIG_COMCERTO_100)
static void EnableUART1(void)
{
u32 temp;
do {
temp = *(volatile u32 *)GPIO_IOCTRL_REG | __cpu_to_le32(GPIO_IOCTRL_UART1); // enable UART1
*(volatile u32 *)GPIO_LOCK_REG = __cpu_to_le32(0x55555555); // remove lock
*(volatile u32 *)GPIO_IOCTRL_REG = temp; // write to ctrl reg
} while (*(volatile u32 *)GPIO_IOCTRL_REG != temp);
}
#else
static void EnableUART1(void)
{
*(volatile u32 *)GPIO_PIN_SELECT_REG |= __cpu_to_le32(GPIO_PIN_SELECT_UART1); // enable UART1
}
#endif
#endif
void serial_setbrg (void)
{
int baudrate = CONFIG_BAUDRATE;
unsigned int reg = 0;
unsigned int clk = HAL_get_amba_clk();
#ifdef CONFIG_UART0
PUART16550REGS uart = (PUART16550REGS) UART0_BASEADDR;
PUART16550DLREGS uart_dl = (PUART16550DLREGS) UART0_BASEADDR;
#else
PUART16550REGS uart = (PUART16550REGS) UART1_BASEADDR;
PUART16550DLREGS uart_dl = (PUART16550DLREGS) UART1_BASEADDR;
#endif
//if ((baudrate = gd->baudrate) <= 0)
// baudrate = CONFIG_BAUDRATE;
reg = clk / (baudrate * 16);
uart->lcr |= __cpu_to_le32(LCR_DLAB); // Enable Divisor Latch access
uart_dl->dll = __cpu_to_le32(reg & 0xFF); // Set Divisor Latch Low
uart_dl->dlh = __cpu_to_le32((reg >> 8) & 0xFF); // Set Divisor Latch high
uart->lcr &= __cpu_to_le32(~LCR_DLAB); // Disable Divisor Latch access
}
int serial_init (void)
{
#ifdef CONFIG_UART0
PUART16550REGS uart = (PUART16550REGS) UART0_BASEADDR;
#else
PUART16550REGS uart = (PUART16550REGS) UART1_BASEADDR;
#endif
#ifdef CONFIG_UART1
EnableUART1();
#elif defined(CONFIG_COMCERTO_100)
EnableUART0();
#endif
serial_setbrg ();
uart->lcr = __cpu_to_le32(LCR_ONE_STOP | LCR_CHAR_LEN_8);
uart->iir_fcr = __cpu_to_le32(FCR_XMITRES | FCR_RCVRRES | FCR_FIFOEN); // Reset, FIFO
uart->ier = __cpu_to_le32(IER_UUE); /* Enable FFUART */
return (0);
}
void serial_putc (const char c)
{
#ifdef CONFIG_UART0
PUART16550REGS uart = (PUART16550REGS) UART0_BASEADDR;
#else
PUART16550REGS uart = (PUART16550REGS) UART1_BASEADDR;
#endif
/* wait for room in the tx FIFO on FFUART */
while ((uart->lsr & __cpu_to_le32(LSR_TEMT))==0) ;
uart->data = __cpu_to_le32(c);
if (c == '\n')
serial_putc ('\r');
}
void serial_puts (const char *s)
{
while (*s) {
serial_putc (*s++);
}
}
int serial_getc (void)
{
#ifdef CONFIG_UART0
PUART16550REGS uart = (PUART16550REGS) UART0_BASEADDR;
#else
PUART16550REGS uart = (PUART16550REGS) UART1_BASEADDR;
#endif
while ((uart->lsr & __cpu_to_le32(LSR_DR)) == 0);
return (char)__le32_to_cpu(uart->data & __cpu_to_le32(0xff));
}
int serial_tstc (void)
{
#ifdef CONFIG_UART0
PUART16550REGS uart = (PUART16550REGS) UART0_BASEADDR;
#else
PUART16550REGS uart = (PUART16550REGS) UART1_BASEADDR;
#endif
return __le32_to_cpu(uart->lsr & __cpu_to_le32(LSR_DR));
}
@@ -0,0 +1,154 @@
/*
* (C) Copyright 2006
* Mindspeed Technologies, Inc. <www.mindspeed.com>
*
* 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 <common.h>
#include <asm/arch/hardware.h>
#include <asm/arch/bsp.h>
#include <asm/byteorder.h>
#define TIMER_LOAD_VAL 0xffffffff
#define CLOCK_COUNT_PER_USEC (CFG_HZ_CLOCK / 1000 / 1000)
#define USEC_PER_TICK (1000 * 1000 / CONFIG_SYS_HZ)
#define READ_TIMER (__le32_to_cpu((*(volatile u32 *)TIMER0_CURR_COUNT)))
static ulong ts_count, ts_usec;
static ulong lastinc;
int timer_init(void)
{
*(volatile u32 *)TIMER0_CNTR_REG = __cpu_to_le32(TIMER_LOAD_VAL);
lastinc = 0;
ts_count = 0;
ts_usec = 0;
return (0);
}
void reset_timer_masked (void)
{
lastinc = READ_TIMER;
ts_count = 0;
ts_usec = 0;
}
void reset_timer (void)
{
reset_timer_masked ();
}
/* Returns usecs since last timer reset */
ulong get_timer_raw (void)
{
ulong step;
ulong now = READ_TIMER;
if (now > lastinc) {
/* normal mode */
step = now - lastinc;
} else {
/* we have an overflow ... */
step = (TIMER_LOAD_VAL - lastinc) + now;
}
lastinc = now;
ts_count += step % CLOCK_COUNT_PER_USEC;
ts_usec += step / CLOCK_COUNT_PER_USEC;
if (ts_count >= CLOCK_COUNT_PER_USEC) {
ts_usec += ts_count / CLOCK_COUNT_PER_USEC;
ts_count %= CLOCK_COUNT_PER_USEC;
}
return ts_usec;
}
/* Returns tick count since last timer reset */
ulong get_timer_masked (void)
{
return get_timer_raw() / USEC_PER_TICK;
}
ulong get_timer (ulong base)
{
return get_timer_masked () - base;
}
void udelay_masked (unsigned long usec)
{
ulong endtime = get_timer_raw () + usec;
while (get_timer_raw () < endtime)
;
}
void udelay (unsigned long usec)
{
udelay_masked(usec);
}
/*
* This function is derived from PowerPC code (read timebase as long long).
* On ARM it just returns the timer value.
*/
unsigned long long get_ticks(void)
{
return get_timer(0);
}
/*
* This function is derived from PowerPC code (timebase clock frequency).
* On ARM it returns the number of timer ticks per second.
*/
ulong get_tbclk (void)
{
ulong tbclk;
tbclk = CONFIG_SYS_HZ;
return tbclk;
}
/*
*
*/
void reset_cpu (ulong ignored)
{
/* set the timeout value */
*(volatile u32 *)TIMER_WDT_HIGH_BOUND = __cpu_to_le32(0x1);
/* enable watchdog timer */
*(volatile u32 *)TIMER_WDT_CONTROL = __cpu_to_le32(0x1);
while (1) ;
}
/*
* timer without interrupts
*/
void set_timer (ulong t)
{
ts_count = 0;
ts_usec = t * USEC_PER_TICK;
}
@@ -0,0 +1,35 @@
/*
* (C) Copyright Mindspeed Technologies Inc.
*
* 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 <common.h>
#include <asm/hardware.h>
#include <asm/arch/bsp.h>
#if defined(CONFIG_COMCERTO_100)
#if defined(NEW_DDR_TRAINING)
#include "training100_new.c" /* new ddr training */
#else
#include "training100.c" /* old ddr training */
#endif
#elif defined(CONFIG_COMCERTO_1000)
#include "training1000.c"
#else
#error "No Architecture selected!!@"
#endif
@@ -0,0 +1,744 @@
/*
* (C) Copyright Mindspeed Technologies Inc.
*
* 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 <common.h>
#include <asm/hardware.h>
extern u32* __training_data_start;
typedef struct {
unsigned char rd0;
unsigned char rd1;
unsigned char rd2;
unsigned char rd3;
} dll_rd;
u32 wr_loop(u8 dqs_index, u32 find_median);
dll_rd DLL_check(u8 dqs_index, u8 wr_index, u32 find_median);
u32 wr_rd_transaction(u32 transaction_size, u32 i, u8 dqs_index, u8 wr_index,u8 rd_index, u32 mask);
u32 actual_transaction(u32 transaction_size, u32 i, u32 mask, u32 ddr_addr, u32 dll_num);
u32 get_dll(u32 i);
u32 get_max_addr_space_bit(void);
void training_gbl_init(void);
u32 find_best(void);
u32 ddr_addr_offset;
u32 max_addr_space_bit;
u8 byte_list[16];
u16 half_word_list[16];
u32 word_list[16];
u64 dword_list[16];
u32 byte_mask[4];
u32 max_addr_bit_list[15];
#define SZ_1K 0x400
#define SZ_1M 0x100000
#define SZ_4K SZ_1K * 4
#define SZ_8K SZ_1K * 8
#define SZ_16K SZ_1K * 16
#define SZ_32K SZ_1K * 32
#define SZ_64K SZ_1K * 64
#define SZ_128K SZ_1K * 128
#define SZ_8M SZ_1M * 8
#define SZ_16M SZ_1M * 16
#define SZ_32M SZ_1M * 32
#define SZ_64M SZ_1M * 64
#define ADDR_JUMP_SIZE SZ_128K
void start_training(void)
{
//initialize global data
training_gbl_init();
//start DDR training
find_best();
}
void training_gbl_init(void)
{
u8 i = 0;
u8 __byte_list[16] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x19, 0x2a, 0x3b, 0x4c, 0x5d, 0x6e, 0x7f};
u16 __half_word_list[16] = {0x0000, 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x0888, 0x1999, 0x2aaa, 0x3bbb, 0x4ccc, 0x5ddd, 0x6eee, 0x7fff};
u32 __word_list[16] = {0x00000000, 0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555, 0x66666666, 0x77777777, 0x08888888, 0x19999999, 0x2aaaaaaa, 0x3bbbbbbb, 0x4ccccccc, 0x5ddddddd, 0x6eeeeeee, 0x7fffffff};
u64 __dword_list[16] = {0x0000000000000000LL, 0x1111111111111111LL, 0x2222222222222222LL, 0x3333333333333333LL, 0x4444444444444444LL, 0x5555555555555555LL, 0x6666666666666666LL, 0x7777777777777777LL, 0x0888888888888888LL, 0x1999999999999999LL, 0x2aaaaaaaaaaaaaaaLL, 0x3bbbbbbbbbbbbbbbLL, 0x4cccccccccccccccLL, 0x5dddddddddddddddLL, 0x6eeeeeeeeeeeeeeeLL, 0x7fffffffffffffffLL};
u32 __byte_mask[4] = {0xff,0xff00,0xff0000,0xff000000};
u32 __max_addr_bit_list[15] = {0x00100000, 0x00200000, 0x00400000, 0x00800000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000};
u32 __ddr_addr_offset = 0;
u32 __max_addr_space_bit = 0;
// remap global data to internal memory
ddr_addr_offset = (u32)&__training_data_start;
max_addr_space_bit = (u32)(&__training_data_start + sizeof(ddr_addr_offset));
byte_list[i] = (u8)(&__training_data_start + sizeof(max_addr_space_bit));
half_word_list[i] = (u16)(&__training_data_start + sizeof(byte_list));
word_list[i] = (u32)(&__training_data_start + sizeof(half_word_list));
dword_list[i] = (u64)(&__training_data_start + sizeof(word_list));
ddr_addr_offset = __ddr_addr_offset;
max_addr_space_bit = __max_addr_space_bit;
for (i = 0; i < 16; i++)
{
byte_list[i] = __byte_list[i];
half_word_list[i] = __half_word_list[i];
word_list[i] = __word_list[i];
dword_list[i] = __dword_list[i];
}
for (i = 0; i < 4; i++)
byte_mask[i] = __byte_mask[i];
for (i = 0; i < 15; i++)
max_addr_bit_list[i] = __max_addr_bit_list[i];
}
u32 find_best(void)
{
u8 dqs_ind = FAILURE; // dqs indication initialize to failure
u8 dqs_min_val = UNSET, dqs_max_val = UNSET, dqs_median = UNSET;
u8 dqs_index;
u8 wr_median_val, rd_median, rslt= FAILURE;
u32 i;
u32 wr_rslt = FAILURE;
u32 dll_num;
register int reg_0 __asm__ ("r3");
register int reg_1 __asm__ ("r4");
u32 max_mem_reg;
u64 *dst, *src;
dll_rd rd;
ddr_addr_offset = 0; // init
if ((__le64_to_cpu(*(&CS_MAP)) & 0x3) == 3) {
max_addr_space_bit = get_max_addr_space_bit();
}
for(dqs_index = LOW_DQS_OUT; dqs_index <= HIGH_DQS_OUT; dqs_index++) {// DQS loop
wr_rslt = wr_loop(dqs_index, 0);
// set min/max values;
if (wr_rslt == FAILURE) {
if ((dqs_min_val != UNSET) && (dqs_min_val==(dqs_index-1))) {
dqs_min_val = UNSET;
}
if ((dqs_min_val!=UNSET) && (dqs_max_val==UNSET)){
dqs_max_val = dqs_index-1;
break;
}
} else { // SUCCESS
if (dqs_min_val==UNSET) {
dqs_min_val = dqs_index;
dqs_ind = SUCCESS;
}
}
}
if (dqs_ind == FAILURE) {
wr_median_val = HIGH_DQS_OUT;
dqs_median = HIGH_WR_DQS;
rd.rd0 = HIGH_RD0;
rd.rd1 = HIGH_RD1;
rd.rd2 = HIGH_RD2;
rd.rd3 = HIGH_RD3;
DENALI_WR_DQS = wr_median_val;
DENALI_DQS_OUT = dqs_median;
DENALI_DQS_DELAY0 = rd.rd0;
DENALI_DQS_DELAY1 = rd.rd1;
DENALI_DQS_DELAY2 = rd.rd2;
DENALI_DQS_DELAY3 = rd.rd3;
return 0xffff;
} else { //SUCCESS
if ((dqs_min_val!=UNSET) && (dqs_max_val==UNSET)){
dqs_max_val = dqs_index-1;
}
dqs_median = (dqs_min_val + dqs_max_val)/2;
}
// end procedure
wr_median_val = wr_loop(dqs_median,1);
rd = DLL_check(dqs_median,wr_median_val,1);
if ((rd.rd0==0) || (rd.rd1==0) || (rd.rd2==0) || (rd.rd3==0)) {
wr_median_val = HIGH_DQS_OUT;
dqs_median = HIGH_WR_DQS;
rd.rd0 = HIGH_RD0;
rd.rd1 = HIGH_RD1;
rd.rd2 = HIGH_RD2;
rd.rd3 = HIGH_RD3;
DENALI_WR_DQS = wr_median_val;
DENALI_DQS_OUT = dqs_median;
DENALI_DQS_DELAY0 = rd.rd0;
DENALI_DQS_DELAY1 = rd.rd1;
DENALI_DQS_DELAY2 = rd.rd2;
DENALI_DQS_DELAY3 = rd.rd3;
return 0xffff; // failure
}
//configure median values
DENALI_WR_DQS = wr_median_val;
DENALI_DQS_OUT = dqs_median;
DENALI_DQS_DELAY0 = rd.rd0;
DENALI_DQS_DELAY1 = rd.rd1;
DENALI_DQS_DELAY2 = rd.rd2;
DENALI_DQS_DELAY3 = rd.rd3;
max_mem_reg = __le64_to_cpu(*(&AHB_MAX_MEM_REG)) & (0x80000000 - ADDR_JUMP_SIZE);
i=0;
while (ddr_addr_offset<max_mem_reg) {
i+=1;
if ((i&0xc)==0) {
rd_median = rd.rd0;
dll_num=0;
} else if ((i&0xc)==1) {
rd_median = rd.rd1;
dll_num=1;
} else if ((i&0xc)==2) {
rd_median = rd.rd2;
dll_num=2;
} else {
rd_median = rd.rd3;
dll_num=3;
}
if ((__le64_to_cpu(*(&REDUC)&0x1)==1) && ((dll_num==2) || (dll_num==3))) {
//REDUC
//half datapath mode in which DLL2 and 3 are not used.
continue;
}
switch (i & 0x3) {
case 0:
rslt = wr_rd_transaction(BYTE_SZ, dll_num, dqs_median, wr_median_val, rd_median,0);
break;
case 1:
rslt = wr_rd_transaction(HALF_WORD, dll_num, dqs_median, wr_median_val, rd_median,0);
break;
case 2:
rslt = wr_rd_transaction(WORD, dll_num, dqs_median, wr_median_val, rd_median,0);
break;
case 3:
rslt = wr_rd_transaction(DOUBLE_WORD, dll_num, dqs_median, wr_median_val, rd_median,0);
break;
};
if (rslt == FAILURE) {
wr_median_val = HIGH_DQS_OUT;
dqs_median = HIGH_WR_DQS;
rd.rd0 = HIGH_RD0;
rd.rd1 = HIGH_RD1;
rd.rd2 = HIGH_RD2;
rd.rd3 = HIGH_RD3;
DENALI_WR_DQS = wr_median_val;
DENALI_DQS_OUT = dqs_median;
DENALI_DQS_DELAY0 = rd.rd0;
DENALI_DQS_DELAY1 = rd.rd1;
DENALI_DQS_DELAY2 = rd.rd2;
DENALI_DQS_DELAY3 = rd.rd3;
return 0xffff;
}
};
//*** burst ***
for (i=0;i<16;i++) {
src = &dword_list[i];
dst = 0;
__asm__ __volatile__ ("ldmia %0, {%1,%2}" \
: "+r" (src), "=r" (reg_0), "=r" (reg_1) \
);
__asm__ __volatile__ ("stmia %0, {%1,%2}" \
: "+r" (dst), "=r" (reg_0), "=r" (reg_1) \
);
if (*src!=*dst) {
wr_median_val = HIGH_DQS_OUT;
dqs_median = HIGH_WR_DQS;
rd.rd0 = HIGH_RD0;
rd.rd1 = HIGH_RD1;
rd.rd2 = HIGH_RD2;
rd.rd3 = HIGH_RD3;
DENALI_WR_DQS = wr_median_val;
DENALI_DQS_OUT = dqs_median;
DENALI_DQS_DELAY0 = rd.rd0;
DENALI_DQS_DELAY1 = rd.rd1;
DENALI_DQS_DELAY2 = rd.rd2;
DENALI_DQS_DELAY3 = rd.rd3;
return 0xffff; //failure
}
}
return SUCCESS;
}
u32 get_max_addr_space_bit(void) {
u32 max_mem_reg;
max_mem_reg = __le32_to_cpu(*(&AHB_MAX_MEM_REG));
if ((max_mem_reg & 0x40000000) != 0) {
return 31;
} else if ((max_mem_reg & 0x20000000) != 0) {
return 30;
} else if ((max_mem_reg & 0x10000000) != 0) {
return 29;
} else if ((max_mem_reg & 0x08000000) != 0) {
return 28;
} else if ((max_mem_reg & 0x04000000) != 0) {
return 27;
} else if ((max_mem_reg & 0x02000000) != 0) {
return 26;
} else if ((max_mem_reg & 0x01000000) != 0) {
return 25;
} else if ((max_mem_reg & 0x00800000) != 0) {
return 24;
} else if ((max_mem_reg & 0x00400000) != 0) {
return 23;
} else if ((max_mem_reg & 0x00200000) != 0) {
return 22;
} else if ((max_mem_reg & 0x00100000) != 0) {
return 21;
};
return 0;
}
u32 wr_loop(u8 dqs_index, u32 find_median) {
u8 wr_index;
u32 rd_rslt = FAILURE; // rd indication initialize to failure: Failure or Success
u8 wr_min_val = UNSET , wr_max_val = UNSET;
u8 wr_median_val = FAILURE;
dll_rd rd;
for(wr_index = LOW_WR_DQS; wr_index <= HIGH_WR_DQS; wr_index++) { /* WR loop */
rd = DLL_check(dqs_index, wr_index,find_median);
rd_rslt = ((rd.rd0>0) && (rd.rd1>0) && (rd.rd2>0) && (rd.rd3>0)) ? SUCCESS : FAILURE;
if (rd_rslt == FAILURE) {
if (find_median == 1) {
if ((wr_min_val != UNSET) && (wr_min_val==(wr_index-1))) {
wr_min_val = UNSET;
}
if ((wr_min_val!=UNSET) && (wr_max_val==UNSET)) {
wr_max_val = wr_index-1;
}
if ((wr_min_val!=UNSET) && (wr_max_val!=UNSET)) {
wr_median_val = (wr_min_val+wr_max_val)/2;
return wr_median_val;
}
}
} else { // SUCCESS
if (find_median == 1) {
if (wr_min_val==UNSET) {
wr_min_val = wr_index;
}
} else {
return SUCCESS;
}
}
}
if (find_median == 1) {
if ((wr_min_val!=UNSET) && (wr_max_val==UNSET)) {
wr_max_val = wr_index-1;
wr_median_val = (wr_min_val+wr_max_val)/2;
}
};
return wr_median_val;
}
dll_rd DLL_check(u8 dqs_index, u8 wr_index, u32 find_median) {
u32 transaction_size;
u32 rslt = FAILURE, dll0_rslt = FAILURE, dll1_rslt = FAILURE, dll2_rslt = FAILURE, dll3_rslt = FAILURE;
u8 rd_index;
u32 i;
dll_rd rd;
u8 rd0_min_val=UNSET, rd1_min_val=UNSET, rd2_min_val=UNSET, rd3_min_val=UNSET;
u8 rd0_max_val=UNSET, rd1_max_val=UNSET, rd2_max_val=UNSET, rd3_max_val=UNSET;
u8 rd0_median=UNSET, rd1_median=UNSET, rd2_median=UNSET, rd3_median=UNSET;
// byte order per DLL
///////////////////////
// 0 1 2 3
// 4 5 6 7
// DLL0 DLL1 DLL2 DLL4
/////////// DLL0 //////////////
for (rd_index = LOW_RD0; rd_index <= HIGH_RD0; rd_index++) {
transaction_size = BYTE_SZ; // byte (8 bits)
for(i = 0; i <= 15; i=i+4){
rslt = wr_rd_transaction(transaction_size, i, dqs_index,wr_index,rd_index,1);
if (rslt == FAILURE) continue;
else if (rslt == SUCCESS) break;
}
if (rslt == SUCCESS) { // only for SUCCESS continue checking for the next transaction width
transaction_size = DOUBLE_WORD; // double-word (64 bits)
for(i = 0; i <= 15; i=i+16){
rslt = wr_rd_transaction(transaction_size, i, dqs_index,wr_index,rd_index,1);
if (rslt == FAILURE) continue;
else if (rslt == SUCCESS) break;
}// end of transaction_size DOUBLE_WORD
} // end of transaction_size BYTE_SZ
// find results of dll run
if (find_median == 1) {
if (rslt == FAILURE) {
if ((rd0_min_val != UNSET) && (rd0_min_val==(rd_index-1))) {
rd0_min_val = UNSET;
}
if ((rd0_min_val != UNSET) && (rd0_max_val == UNSET)) {
rd0_max_val = rd_index-1;
dll0_rslt = SUCCESS;
break;
}
} else if (rslt == SUCCESS) {
if (rd0_min_val == UNSET) {
rd0_min_val = rd_index;
}
}
} else {
if (rslt == FAILURE) continue;
else if (rslt == SUCCESS) break;// one SUCCESS is enough when no median calculation is needed
} // dll0 median
} // DLL0
if (rslt == SUCCESS) dll0_rslt = SUCCESS;
if (find_median == 1) {
if ((rd0_min_val != UNSET) && (rd0_max_val == UNSET)) {
rd0_max_val = rd_index-1;
}
rd0_median = (rd0_min_val + rd0_max_val)/2;
}
/////////// DLL1 //////////////
for (rd_index = LOW_RD1; rd_index <= HIGH_RD1; rd_index++) {
transaction_size = BYTE_SZ; // byte (8 bits)
for(i = 1; i <= 15; i=i+4){
rslt = wr_rd_transaction(transaction_size, i, dqs_index,wr_index,rd_index,1);
if (rslt == FAILURE) continue;
else if (rslt == SUCCESS) break;
}
if (rslt == SUCCESS) { // only for SUCCESS continue checking for the next transaction width
transaction_size = DOUBLE_WORD; // double-word (64 bits)
for(i = 1; i <= 15; i=i+16){
rslt = wr_rd_transaction(transaction_size, i, dqs_index,wr_index,rd_index,1);
if (rslt == FAILURE) continue;
else if (rslt == SUCCESS) break;
}// end of transaction_size DOUBLE_WORD
} // end of transaction_size BYTE_SZ
// find results of dll run
if (find_median == 1) {
if (rslt == FAILURE) {
if ((rd1_min_val != UNSET) && (rd1_min_val==(rd_index-1))) {
rd1_min_val = UNSET;
}
if ((rd1_min_val != UNSET) && (rd1_max_val == UNSET)) {
rd1_max_val = rd_index-1;
dll1_rslt = SUCCESS;
break;
}
} else if (rslt == SUCCESS) {
if (rd1_min_val == UNSET) {
rd1_min_val = rd_index;
}
}
} else {
if (rslt == FAILURE) continue;
else if (rslt == SUCCESS) break;// one SUCCESS is enough when no median calculation is needed
} // dll1 median
} // DLL1
if (rslt == SUCCESS) dll1_rslt = SUCCESS;
if (find_median == 1) {
if ((rd1_min_val != UNSET) && (rd1_max_val == UNSET)) {
rd1_max_val = rd_index-1;
}
rd1_median = (rd1_min_val + rd1_max_val)/2;
}
if ((__le64_to_cpu(*(&REDUC))&0x1)==1) {
dll2_rslt = SUCCESS;
dll3_rslt = SUCCESS;
} else {
/////////// DLL2 //////////////
for (rd_index = LOW_RD2; rd_index <= HIGH_RD2; rd_index++) {
transaction_size = BYTE_SZ; // byte (8 bits)
for(i = 2; i <= 15; i=i+4){
rslt = wr_rd_transaction(transaction_size, i, dqs_index,wr_index,rd_index,1);
if (rslt == FAILURE) continue;
else if (rslt == SUCCESS) break;
}
if (rslt == SUCCESS) { // only for SUCCESS continue checking for the next transaction width
transaction_size = DOUBLE_WORD; // double-word (64 bits)
for(i = 2; i <= 15; i=i+16){
rslt = wr_rd_transaction(transaction_size, i, dqs_index,wr_index,rd_index,1);
if (rslt == FAILURE) continue;
else if (rslt == SUCCESS) break;
}// end of transaction_size DOUBLE_WORD
} // end of transaction_size BYTE_SZ
// find results of dll run
if (find_median == 1) {
if (rslt == FAILURE) {
if ((rd2_min_val != UNSET) && (rd2_min_val==(rd_index-1))) {
rd2_min_val = UNSET;
}
if ((rd2_min_val != UNSET) && (rd2_max_val == UNSET)) {
rd2_max_val = rd_index-1;
dll2_rslt = SUCCESS;
break;
}
} else if (rslt == SUCCESS) {
if (rd2_min_val == UNSET) {
rd2_min_val = rd_index;
}
}
} else {
if (rslt == FAILURE) continue;
else if (rslt == SUCCESS) break;// one SUCCESS is enough when no median calculation is needed
} // dll2 median
} // DLL2
if (rslt == SUCCESS) dll2_rslt = SUCCESS;
if (find_median == 1) {
if ((rd2_min_val != UNSET) && (rd2_max_val == UNSET)) {
rd2_max_val = rd_index-1;
}
rd2_median = (rd2_min_val + rd2_max_val)/2;
}
/////////// DLL3 //////////////
for (rd_index = LOW_RD3; rd_index <= HIGH_RD3; rd_index++) {
transaction_size = BYTE_SZ; // byte (8 bits)
for(i = 3; i <= 15; i=i+4){
rslt = wr_rd_transaction(transaction_size, i, dqs_index,wr_index,rd_index,1);
if (rslt == FAILURE) continue;
else if (rslt == SUCCESS) break;
}
if (rslt == SUCCESS) { // only for SUCCESS continue checking for the next transaction width
transaction_size = DOUBLE_WORD; // double-word (64 bits)
for(i = 3; i <= 15; i=i+16){
rslt = wr_rd_transaction(transaction_size, i, dqs_index,wr_index,rd_index,1);
if (rslt == FAILURE) continue;
else if (rslt == SUCCESS) break;
}// end of transaction_size DOUBLE_WORD
} // end of transaction_size BYTE_SZ
// find results of dll run
if (find_median == 1) {
if (rslt == FAILURE) {
if ((rd3_min_val != UNSET) && (rd3_min_val==(rd_index-1))) {
rd3_min_val = UNSET;
}
if ((rd3_min_val != UNSET) && (rd3_max_val == UNSET)) {
rd3_max_val = rd_index-1;
dll3_rslt = SUCCESS;
break;
}
} else if (rslt == SUCCESS) {
if (rd3_min_val == UNSET) {
rd3_min_val = rd_index;
}
}
} else {
if (rslt == FAILURE) continue;
else if (rslt == SUCCESS) break;// one SUCCESS is enough when no median calculation is needed
} // dll3 median
} // DLL3
if (rslt == SUCCESS) dll3_rslt = SUCCESS;
if (find_median == 1) {
if ((rd3_min_val != UNSET) && (rd3_max_val == UNSET)) {
rd3_max_val = rd_index-1;
}
rd3_median = (rd3_min_val + rd3_max_val)/2;
}
}; // REDUC
// all dll found a success values for current dqs and wr values.
// For initialization: 0s indicates Failure
rd.rd0 = 0;
rd.rd1 = 0;
rd.rd2 = 0;
rd.rd3 = 0;
if ((dll0_rslt & dll1_rslt & dll2_rslt & dll3_rslt & 0x1) == 1) {//return SUCCESS;
if (find_median == 1) {
rd.rd0 = rd0_median;
rd.rd1 = rd1_median;
rd.rd2 = rd2_median;
rd.rd3 = rd3_median;
} else {
// 1s indicates Success
rd.rd0 = 1;
rd.rd1 = 1;
rd.rd2 = 1;
rd.rd3 = 1;
}
}
return rd; // 0s indicate Failure
}
u32 wr_rd_transaction(u32 transaction_size, u32 i, u8 dqs_index, u8 wr_index, u8 rd_index, u32 mask) {
u32 dll_num;
u32 ddr_addr, limit_addr;
// set values for current transaction
DENALI_WR_DQS = wr_index;
DENALI_DQS_OUT = dqs_index;
dll_num = get_dll(i);
switch (dll_num) {
case 0:DENALI_DQS_DELAY0 = rd_index;break;
case 1:DENALI_DQS_DELAY1 = rd_index;break;
case 2:DENALI_DQS_DELAY2 = rd_index;break;
case 3:DENALI_DQS_DELAY3 = rd_index;break;
};
limit_addr = __le64_to_cpu(*(&AHB_MAX_MEM_REG)) & 0x7fffffff;
ddr_addr_offset = (ddr_addr_offset + ADDR_JUMP_SIZE) & limit_addr; // limit the address space to ahb configured value.
// the address is shifted by 8 to ensure 64 byte transaction in region.
// 0x80000000 + dll_num + offset *2^ (0 for byte, 1 for half word , 2 for word, 3 for double word.)
if ((__le64_to_cpu(*(&CS_MAP)) & 0x3) == 3) {
ddr_addr = ddr_addr_offset;
// default cs#0
ddr_addr &= (~(max_addr_bit_list[max_addr_space_bit-21]));
if (actual_transaction(transaction_size, i, mask, ddr_addr, dll_num) == SUCCESS) {
// set cs#1
ddr_addr |= max_addr_bit_list[max_addr_space_bit-21];
return actual_transaction(transaction_size, i, mask, ddr_addr, dll_num);
} else {
return FAILURE;
}
} else {
return actual_transaction(transaction_size, i, mask, ddr_addr_offset, dll_num);
}
}
u32 get_dll(u32 i) {
u32 rslt=0;
switch (i) {
case 0: case 4: case 8: case 12 : rslt = 0;break;
case 1: case 5: case 9: case 13 : rslt = 1;break;
case 2: case 6: case 10: case 14: rslt = 2;break;
case 3: case 7: case 11: case 15: rslt = 3;break;
};
return rslt;
}
u32 actual_transaction(u32 transaction_size, u32 i, u32 mask, u32 ddr_addr, u32 dll_num) {
u32 rslt = FAILURE;
// per transaction width, write and read transaction.
switch (transaction_size) {
case BYTE_SZ:
if (mask == 1) {
*(&WRITE_VAL_U8+i+ddr_addr) = 0x00;
*(&WRITE_VAL_U8+i+0x10+ddr_addr) = 0xaa;
*(&WRITE_VAL_U8+i+0x20+ddr_addr) = 0x55;
if (((*(&WRITE_VAL_U8+i+ddr_addr)) & 0xff)==0x00) {
if (((*(&WRITE_VAL_U8+i+0x10+ddr_addr)) & 0xff)==0xaa) {
if (((*(&WRITE_VAL_U8+i+0x20+ddr_addr)) & 0xff)==0x55) {
rslt = SUCCESS; // per dll
}
}
}
*(&WRITE_VAL_U8+i+ddr_addr) = 0;//clear
*(&WRITE_VAL_U8+i+0x10+ddr_addr) = 0;//clear
*(&WRITE_VAL_U8+i+0x20+ddr_addr) = 0;//clear
} else {
*(&WRITE_VAL_U8+ddr_addr) = 0x00;
*(&WRITE_VAL_U8+0x10+ddr_addr) = 0xaa;
*(&WRITE_VAL_U8+0x20+ddr_addr) = 0x55;
if (*(&WRITE_VAL_U8+ddr_addr) == 0x00) {
if (*(&WRITE_VAL_U8+0x10+ddr_addr) == 0xaa) {
if (*(&WRITE_VAL_U8+0x20+ddr_addr) == 0x55) {
rslt = SUCCESS;
}
}
}
*(&WRITE_VAL_U8+ddr_addr) = 0; //clear
*(&WRITE_VAL_U8+i+0x10+ddr_addr) = 0;//clear
*(&WRITE_VAL_U8+i+0x20+ddr_addr) = 0;//clear
}
break;
case HALF_WORD: // no masking option
*(&WRITE_VAL_U16+ddr_addr) = __cpu_to_le16(0x0000);
*(&WRITE_VAL_U16+0x10+ddr_addr) = __cpu_to_le16(0xaaaa);
*(&WRITE_VAL_U16+0x20+ddr_addr) = __cpu_to_le16(0x5555);
if (__le16_to_cpu(*(&WRITE_VAL_U16+ddr_addr)) == 0x0000) {
if (__le16_to_cpu(*(&WRITE_VAL_U16+0x10+ddr_addr)) == 0xaaaa) {
if (__le16_to_cpu(*(&WRITE_VAL_U16+0x20+ddr_addr)) == 0x5555) {
rslt = SUCCESS;
}
}
}
*(&WRITE_VAL_U16+ddr_addr) = __cpu_to_le16(0); //clear
*(&WRITE_VAL_U16+i+0x10+ddr_addr) = __cpu_to_le16(0);//clear
*(&WRITE_VAL_U16+i+0x20+ddr_addr) = __cpu_to_le16(0);//clear
break;
case WORD:// no masking option
*(&WRITE_VAL_U32+ddr_addr) = __cpu_to_le32(0x00000000);
*(&WRITE_VAL_U32+0x10+ddr_addr) = __cpu_to_le32(0xaaaaaaaa);
*(&WRITE_VAL_U32+0x20+ddr_addr) = __cpu_to_le32(0x55555555);
if (__le32_to_cpu(*(&WRITE_VAL_U32+ddr_addr)) == 0x00000000) {
if (__le32_to_cpu(*(&WRITE_VAL_U32+0x10+ddr_addr)) == 0xaaaaaaaa) {
if (__le32_to_cpu(*(&WRITE_VAL_U32+0x20+ddr_addr)) == 0x55555555) {
rslt = SUCCESS;
}
}
}
*(&WRITE_VAL_U32+ddr_addr) = __cpu_to_le32(0); //clear
*(&WRITE_VAL_U32+0x10+ddr_addr) = __cpu_to_le32(0); //clear
*(&WRITE_VAL_U32+0x20+ddr_addr) = __cpu_to_le32(0); //clear
break;
case DOUBLE_WORD: // no masking : full 64 bits
*(&WRITE_VAL_U64+ddr_addr) = __cpu_to_le64(0x0000000000000000LL);
*(&WRITE_VAL_U64+0x10+ddr_addr) = __cpu_to_le64(0x2aaaaaaaaaaaaaaaLL);
*(&WRITE_VAL_U64+0x20+ddr_addr) = __cpu_to_le64(0x5555555555555555LL);
if (__le64_to_cpu(*(&WRITE_VAL_U64+ddr_addr)) == 0x0000000000000000LL) {
if (__le64_to_cpu(*(&WRITE_VAL_U64+0x10+ddr_addr)) == 0x2aaaaaaaaaaaaaaaLL) {
if (__le64_to_cpu(*(&WRITE_VAL_U64+0x20+ddr_addr)) == 0x5555555555555555LL) {
rslt = SUCCESS;
}
}
}
*(&WRITE_VAL_U64+ddr_addr) = __cpu_to_le64(0); //clear
*(&WRITE_VAL_U64+0x10+ddr_addr) = __cpu_to_le64(0); //clear
*(&WRITE_VAL_U64+0x20+ddr_addr) = __cpu_to_le64(0); //clear
break;
}; // switch transaction_size
return rslt;
}
@@ -0,0 +1,786 @@
/*
* (C) Copyright Mindspeed Technologies Inc.
*
* 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 <common.h>
#include <asm/hardware.h>
#include <asm/arch/bsp.h>
//#define DDR_TRAINING_MODE_DEBUG_PRINTS 1
#undef DDR_TRAINING_MODE_DEBUG_PRINTS
#define SZ_1K 0x400
#define SZ_128K (SZ_1K * 128)
#define ADDR_JUMP_SIZE SZ_128K
#define MT_ADDR1_DST (DDR_BASEADDR + 0xff00)
#define MT_ADDR2_DST (DDR_BASEADDR + (PHYS_SDRAM_SIZE >> 1) + 0xff00)
/* Controller register defines used in training */
#define DENALI_WR_DQS_DELAY0 *((volatile u8 *)(DDR_CONFIG_BASEADDR + 0x11B))
#define DENALI_WR_DQS_DELAY1 *((volatile u8 *)(DDR_CONFIG_BASEADDR + 0x11C))
#define DENALI_WR_DQS_DELAY2 *((volatile u8 *)(DDR_CONFIG_BASEADDR + 0x11D))
#define DENALI_WR_DQS_DELAY3 *((volatile u8 *)(DDR_CONFIG_BASEADDR + 0x11E))
#define DENALI_SW_LEVELING_START *((volatile u8 *)(DDR_CONFIG_BASEADDR + 0x278))
#define DENALI_SW_LEVELING_MODE *((volatile u8 *)(DDR_CONFIG_BASEADDR + 0x279))
#define DENALI_SW_LEVELING_LOAD *((volatile u8 *)(DDR_CONFIG_BASEADDR + 0x276))
#define DENALI_DLL_MADJ0 *((volatile u8 *)(DDR_CONFIG_BASEADDR + 0x148))
#define DENALI_DLL_ADJ0 *((volatile u8 *)(DDR_CONFIG_BASEADDR + 0x149))
#define DENALI_DLL_ADJ1_DS0 *((volatile u8 *)(DDR_CONFIG_BASEADDR + 0x14A))
#define DENALI_DLL_ADJ1_DS1 *((volatile u8 *)(DDR_CONFIG_BASEADDR + 0x14E))
#define DENALI_DLL_ADJ1_DS2 *((volatile u8 *)(DDR_CONFIG_BASEADDR + 0x152))
#define DENALI_DLL_ADJ1_DS3 *((volatile u8 *)(DDR_CONFIG_BASEADDR + 0x156))
#define DENALI_DLL_ADJ0_DS0 *((volatile u8 *)(DDR_CONFIG_BASEADDR + 0x149))
#define DENALI_DLL_ADJ0_DS1 *((volatile u8 *)(DDR_CONFIG_BASEADDR + 0x14D))
#define DENALI_DLL_ADJ0_DS2 *((volatile u8 *)(DDR_CONFIG_BASEADDR + 0x151))
#define DENALI_DLL_ADJ0_DS3 *((volatile u8 *)(DDR_CONFIG_BASEADDR + 0x155))
#define DENALI_DLL_ADJ3_DS0 *((volatile u8 *)(DDR_CONFIG_BASEADDR + 0x159))
#define DENALI_DLL_ADJ3_DS1 *((volatile u8 *)(DDR_CONFIG_BASEADDR + 0x15D))
#define DENALI_DLL_ADJ3_DS2 *((volatile u8 *)(DDR_CONFIG_BASEADDR + 0x161))
#define DENALI_DLL_ADJ3_DS3 *((volatile u8 *)(DDR_CONFIG_BASEADDR + 0x165))
static u8 do_wr_rd_transaction(u32 ddr_addr_offset, u64*, u32*, u16 mode);
static int mdma_test(u64 *);
extern void arm_write64(u64 data,volatile u64 *p);
extern int mdma_memcpy(void *src, void *dst, int len, unsigned int *crc);
extern int serial_init(void);
extern void serial_puts(const char *s);
extern void serial_putc(const char c);
typedef struct adj2_ds_s
{
u8 win_start;
u8 win_end;
u8 win;
u8 gWin;
u8 gWin_start;
u8 gWin_end;
u8 inx;
}adj2_ds_t;
typedef struct adj2_val_s
{
adj2_ds_t ds0;
adj2_ds_t ds1;
adj2_ds_t ds2;
adj2_ds_t ds3;
}adj2_val_t;
#ifdef DDR_TRAINING_MODE_DEBUG_PRINTS
/* use to print only byte */
static char *simple_itoa1(unsigned int i, char *s)
{
char local[5];
char *p = &local[4];
*p-- = '\0';
i = i & 0xff;
do {
*p-- = '0' + i % 10;
i /= 10;
} while (i > 0);
memcpy(s, p+1, 4);
return s;
}
#endif
static void adj2_dsx_calculate_window(u8 result, u8 dll_val, u8 dqs_index, adj2_ds_t *adj2)
{
u8 win;
#ifdef DDR_TRAINING_MODE_DEBUG_PRINTS
char s[5];
u8 dsx = 0;
#endif
if (!result) /* success */
{
/* its first time success, start counting from here */
if (adj2->win_start == 0)
{
adj2->win_start = adj2->win_end = dll_val;
}
else {
adj2->win_end++;
/* close the window, if we reach the end point of adj1 range */
if (dll_val == ADJ1_MAX_VAL) {
win = (adj2->win_end - adj2->win_start) + 1;
if (adj2->win < win)
adj2->win = win;
/* is this window bigger than the previous one, then take it */
if (adj2->gWin < win)
{
adj2->gWin = win;
adj2->gWin_start = adj2->win_start;
adj2->gWin_end = adj2->win_end;
adj2->inx = dqs_index;
}
}
}
}
else /* failure */
{
if (adj2->win_start == 0)
{
//window not yet started, so nothing to do
}
else
{
//this window ends here,calculate window size
win = (adj2->win_end - adj2->win_start) + 1;
#ifdef DDR_TRAINING_MODE_DEBUG_PRINTS
serial_putc('\n');
if (result & 0x1)
dsx = 0;
else if (result & 0x2)
dsx = 1;
else if (result & 0x4)
dsx = 2;
else if (result & 0x8)
dsx = 3;
serial_putc('[');
serial_puts("ds");
serial_puts(simple_itoa1(dsx,s));
serial_putc(':');
serial_puts(simple_itoa1(adj2->win_start,s));
serial_putc('-');
serial_puts(simple_itoa1(adj2->win_end,s));
serial_putc('=');
serial_puts(simple_itoa1(win,s));
serial_putc(']');
#endif
if (adj2->win < win)
{
adj2->win = win;
}
//is this window bigger than the previous one, then take it
if (adj2->gWin < win)
{
adj2->gWin = win;
adj2->gWin_start = adj2->win_start;
adj2->gWin_end = adj2->win_end;
adj2->inx = dqs_index;
}
/* reset window pointer to measure next window */
adj2->win_start = adj2->win_end = 0;
}
} /* failure */
return;
}
/* for basing on adj2 min value logic support */
static int get_adj2_adjusted_value(unsigned int *adj2_dsx, adj2_val_t *adj2, u16 ddr16bit_mode)
{
u8 i, adj2_val;
u16 ds, shift;
u8 win_start, win_end, win;
u8 gwin_start, gwin_end, gwin;
#ifdef DDR_TRAINING_MODE_DEBUG_PRINTS
unsigned char s[5];
#endif
for(ds=0; ds < 4; ds++) {
if ((ds == 2) && (ddr16bit_mode))
goto done;
shift = ds * 8;
win_start = win_end = win = 0;
gwin_start = gwin_end = gwin = 0;
#ifdef DDR_TRAINING_MODE_DEBUG_PRINTS
serial_puts("ds");
serial_puts(simple_itoa1(ds, s));
serial_putc('\n');
#endif
for(i=ADJ2_MIN_VAL; i <= ADJ2_MAX_VAL; i++) {
adj2_val = (u8)((adj2_dsx[i] >> shift) & 0xff);
/* if, adj2 val is accepted */
if (adj2_val >= ADJ1_MIN_ACCEPTED_WINDOW) {
if (win_start == 0) {
win_start = win_end = i;
}
else {
win_end++;
/* close the window, if we reach the end of adj2 range */
if (i == ADJ2_MAX_VAL) {
win = win_end - win_start + 1;
if (gwin < win) {
gwin = win;
gwin_start = win_start;
gwin_end = win_end;
}
#ifdef DDR_TRAINING_MODE_DEBUG_PRINTS
serial_puts(simple_itoa1(win_start, s));
serial_putc('-');
serial_puts(simple_itoa1(win_end, s));
serial_putc('=');
serial_puts(simple_itoa1(win, s));
serial_putc('\n');
#endif
}
}
}
else {
/* if (win_start == 0) do nothing */
if (win_start != 0) {
win = win_end - win_start + 1;
if (gwin < win) {
gwin = win;
gwin_start = win_start;
gwin_end = win_end;
}
#ifdef DDR_TRAINING_MODE_DEBUG_PRINTS
serial_puts(simple_itoa1(win_start, s));
serial_putc('-');
serial_puts(simple_itoa1(win_end, s));
serial_putc('=');
serial_puts(simple_itoa1(win, s));
serial_putc('\n');
#endif
win_start = win_end = 0;
}
}
} /* end of for (adj2 for a given ds) */
/* check for adj2 range size */
if (gwin < ADJ2_MIN_ACCEPTED_RANGE) {
return -1;
}
else if (gwin < ADJ2_ACCEPTED_RANGE) {
serial_puts("\nWARNING - DDR Training results may be Marginal\n");
}
switch (ds) {
case 0 :
adj2->ds0.inx = (gwin_start + gwin_end) >> 1;
adj2->ds0.gWin = adj2_dsx[adj2->ds0.inx] & 0xff;
break;
case 1 :
adj2->ds1.inx = (gwin_start + gwin_end) >> 1;
adj2->ds1.gWin = (adj2_dsx[adj2->ds1.inx] & 0xff00) >> 8;
break;
case 2 :
adj2->ds2.inx = (gwin_start + gwin_end) >> 1;
adj2->ds2.gWin = (adj2_dsx[adj2->ds2.inx] & 0xff0000) >> 16;
break;
case 3:
adj2->ds3.inx = (gwin_start + gwin_end) >> 1;
adj2->ds3.gWin = (adj2_dsx[adj2->ds3.inx] & 0xff000000) >> 24;
default:
break;
}
} /* end of for(ds) */
done:
if (ddr16bit_mode) {
if ((adj2->ds0.gWin < ADJ1_ACCEPTED_WINDOW) || (adj2->ds1.gWin < ADJ1_ACCEPTED_WINDOW)) {
goto warning;
}
}
else {
if ((adj2->ds0.gWin < ADJ1_ACCEPTED_WINDOW) || (adj2->ds1.gWin < ADJ1_ACCEPTED_WINDOW) ||
(adj2->ds2.gWin < ADJ1_ACCEPTED_WINDOW) || (adj2->ds3.gWin < ADJ1_ACCEPTED_WINDOW)) {
goto warning;
}
}
return 0;
warning:
serial_puts("\nWARNING - DDR Training results may be Marginal\n");
return 0;
}
/* re-calculate the win_start and win_end values for the choosen adj2 */
void recalculate_adj1_window(u8 ddr16bit_mode, adj2_val_t *adj2,
u64 *dword_list, u32 *word_list)
{
u8 dll_val;
u8 ds;
u32 result;
u32 dqs_index;
u32 ddr_addr_offset = 0;
u64 dqs_value;
/* Reset window pointers */
adj2->ds0.win_start = adj2->ds0.win_end = 0;
adj2->ds1.win_start = adj2->ds1.win_end = 0;
adj2->ds2.win_start = adj2->ds2.win_end = 0;
adj2->ds3.win_start = adj2->ds3.win_end = 0;
adj2->ds0.win = 0;
adj2->ds1.win = 0;
adj2->ds2.win = 0;
adj2->ds3.win = 0;
adj2->ds0.gWin = 0;
adj2->ds1.gWin = 0;
adj2->ds2.gWin = 0;
adj2->ds3.gWin = 0;
for(ds = 0; ds < 4; ds++) {
if ((ds == 2) && (ddr16bit_mode))
return;
if (ds == 0)
dqs_index = adj2->ds0.inx;
else if (ds == 1)
dqs_index = adj2->ds1.inx;
else if (ds == 2)
dqs_index = adj2->ds2.inx;
else if (ds == 3)
dqs_index = adj2->ds3.inx;
/* Configure the WRLVL_DELAY_X values */
if (ddr16bit_mode) {
dqs_value = __le64_to_cpu((*(volatile u64*)(DENALI_CTL_35_DATA))) & 0xffffff0000ffffffULL;
dqs_value |= (u64)(((u64)dqs_index << 24) | ((u64)dqs_index << 32) );
}
else {
dqs_value = __le64_to_cpu((*(volatile u64*)(DENALI_CTL_35_DATA))) & 0xff00000000ffffffULL;
dqs_value |= (u64)(((u64)dqs_index << 24) | ((u64)dqs_index << 32) | ((u64)dqs_index << 40) | ((u64)dqs_index << 48));
}
arm_write64(dqs_value, (volatile u64 *)DENALI_CTL_35_DATA); //should be 64bit write
//set sw leveling mode
*(volatile u64*)(DENALI_CTL_67_DATA) = __cpu_to_le64((u64)DENALI_CTL_67_VAL_CFG1 | (1LL << 8));
//sw leveling load
*(volatile u64*)(DENALI_CTL_66_DATA) = __cpu_to_le64((u64)DENALI_CTL_66_VAL_CFG1 | (1LL << 48));
//reset sw leveling mode
*(volatile u64*)(DENALI_CTL_67_DATA) = __cpu_to_le64((u64)DENALI_CTL_67_VAL_CFG1);
/* Looping through ADJ_1 range */
for (dll_val = ADJ1_MIN_VAL; dll_val <= ADJ1_MAX_VAL; dll_val++)
{
/* Configure dll write click adj-1 values */
DENALI_DLL_ADJ1_DS0 = (u8)dll_val;
DENALI_DLL_ADJ1_DS1 = (u8)dll_val;
if (!ddr16bit_mode) {
DENALI_DLL_ADJ1_DS2 = (u8)dll_val;
DENALI_DLL_ADJ1_DS3 = (u8)dll_val;
}
result = do_wr_rd_transaction(ddr_addr_offset,dword_list,word_list, ddr16bit_mode);
ddr_addr_offset = (ddr_addr_offset + ADDR_JUMP_SIZE) & (PHYS_SDRAM_SIZE -1);
if (ds == 0)
adj2_dsx_calculate_window((result & 0x1), dll_val, adj2->ds0.inx, &adj2->ds0);
else if (ds == 1)
adj2_dsx_calculate_window((result & 0x2), dll_val, adj2->ds1.inx, &adj2->ds1);
else if (ds == 2)
adj2_dsx_calculate_window((result & 0x4), dll_val, adj2->ds2.inx, &adj2->ds2);
else if (ds == 3)
adj2_dsx_calculate_window((result & 0x8), dll_val, adj2->ds3.inx, &adj2->ds3);
} /* for loop from dll min to max (ADJ_1) */
} /* for each ds */
return;
}
/* find the a bigger dll clk window for the given dqs value */
/* find a dll wr clk window for a given dqs_index,
* this function updates the global dll and dqs values, if its finds any bigger window
* than previous window, and then finally it configures the identified dqs and dll values
* to DDR controller */
void start_training(void)
{
u32 word_list[16] = { 0xffffffff, 0x00000000, 0x12345678, 0x9abcdef0,
0xf7f70202, 0xdfdf2020, 0x80407fbf, 0x08040204,
0x8080fdfd, 0x0808dfdf, 0xa5a55a5a, 0x5a5aa5a5,
0xaaaa5555, 0x5555aaaa, 0x0000ffff, 0x0000ffff};
u64 dword_list[16] = {0xffffffff00000000ULL, 0xffffffff00000000ULL,
0x1234567876543210ULL, 0x0123456789abcdefULL,
0xf7f7f7f702020202ULL, 0xdfdfdfdf20202020ULL,
0x804020107fbfdfefULL, 0x0804020110204080ULL,
0x80808080fdfdfdfdULL, 0x08080808dfdfdfdfULL,
0xa5a5a5a55a5a5a5aULL, 0x5a5a5a5aa5a5a5a5ULL,
0xaaaaaaaa55555555ULL, 0x55555555aaaaaaaaULL,
0x00000000ffffffffULL, 0x00000000ffffffffULL
};
u8 dll_val;
u8 result;
u8 dqs_index;
u32 ddr_addr_offset = 0;
u64 dqs_value;
adj2_val_t adj2;
u16 ddr16bit_mode = 0;
unsigned char sb[] = "\nDDR Training";
unsigned char sd[] = "Done";
unsigned char sf[] = "Fail";
#ifdef DDR_TRAINING_MODE_DEBUG_PRINTS
unsigned char adj2_s[] = "\nAdj2:";
char s[5];
u8 i;
#endif
unsigned int adj2_dsx[256];
/* Init of UART will be done later through main init sequence,
* so doing init twice does it make any harm????, I think NO */
serial_init();
serial_puts(sb);
/* check for 16bit mode */
if(__le64_to_cpu(*(volatile u64*)(DENALI_CTL_18_DATA)) & 0x0000000001000000ULL)
ddr16bit_mode = 1;
adj2.ds0.gWin = 0;
adj2.ds1.gWin = 0;
adj2.ds2.gWin = 0;
adj2.ds3.gWin = 0;
/* Looping through ADJ_2 range */
for(dqs_index = ADJ2_MIN_VAL; dqs_index <= ADJ2_MAX_VAL; dqs_index++)
{
#ifdef DDR_TRAINING_MODE_DEBUG_PRINTS
serial_puts(adj2_s);
serial_puts(simple_itoa1(dqs_index, s));
serial_putc(':');
#endif
serial_putc('.');
/* Configure the WRLVL_DELAY_X values */
if (ddr16bit_mode) {
dqs_value = __le64_to_cpu((*(volatile u64*)(DENALI_CTL_35_DATA))) & 0xffffff0000ffffffULL;
dqs_value |= (u64)(((u64)dqs_index << 24) | ((u64)dqs_index << 32) );
}
else {
dqs_value = __le64_to_cpu((*(volatile u64*)(DENALI_CTL_35_DATA))) & 0xff00000000ffffffULL;
dqs_value |= (u64)(((u64)dqs_index << 24) | ((u64)dqs_index << 32) | ((u64)dqs_index << 40) | ((u64)dqs_index << 48));
}
arm_write64(dqs_value, (volatile u64 *)DENALI_CTL_35_DATA); //should be 64bit write
//set sw leveling mode
*(volatile u64*)(DENALI_CTL_67_DATA) = __cpu_to_le64((u64)DENALI_CTL_67_VAL_CFG1 | (1LL << 8));
//sw leveling load
*(volatile u64*)(DENALI_CTL_66_DATA) = __cpu_to_le64((u64)DENALI_CTL_66_VAL_CFG1 | (1LL << 48));
//reset sw leveling mode
*(volatile u64*)(DENALI_CTL_67_DATA) = __cpu_to_le64((u64)DENALI_CTL_67_VAL_CFG1);
/* Reset window pointers */
adj2.ds0.win_start = adj2.ds0.win_end = 0;
adj2.ds1.win_start = adj2.ds1.win_end = 0;
adj2.ds2.win_start = adj2.ds2.win_end = 0;
adj2.ds3.win_start = adj2.ds3.win_end = 0;
adj2.ds0.win = 0;
adj2.ds1.win = 0;
adj2.ds2.win = 0;
adj2.ds3.win = 0;
/* Looping through ADJ_1 range */
for (dll_val = ADJ1_MIN_VAL; dll_val <= ADJ1_MAX_VAL; dll_val++)
{
/* Configure dll write click adj-1 values */
DENALI_DLL_ADJ1_DS0 = (u8)dll_val;
DENALI_DLL_ADJ1_DS1 = (u8)dll_val;
if (!ddr16bit_mode) {
DENALI_DLL_ADJ1_DS2 = (u8)dll_val;
DENALI_DLL_ADJ1_DS3 = (u8)dll_val;
}
result = do_wr_rd_transaction(ddr_addr_offset,dword_list,word_list, ddr16bit_mode);
ddr_addr_offset = (ddr_addr_offset + ADDR_JUMP_SIZE) & (PHYS_SDRAM_SIZE -1);
adj2_dsx_calculate_window((result & 0x1), dll_val, dqs_index, &adj2.ds0);
adj2_dsx_calculate_window((result & 0x2), dll_val, dqs_index, &adj2.ds1);
if (!ddr16bit_mode) {
adj2_dsx_calculate_window((result & 0x4), dll_val, dqs_index, &adj2.ds2);
adj2_dsx_calculate_window((result & 0x8), dll_val, dqs_index, &adj2.ds3);
}
} /* for loop from dll min to max (ADJ_1) */
/* store the adj2 win values */
if (ddr16bit_mode)
adj2_dsx[dqs_index] = (adj2.ds1.win << 8) | (adj2.ds0.win);
else
adj2_dsx[dqs_index] = (adj2.ds3.win << 24) | (adj2.ds2.win << 16) | (adj2.ds1.win << 8) | (adj2.ds0.win);
} //End of ADJ_2
#ifdef DDR_TRAINING_MODE_DEBUG_PRINTS
serial_putc('\n');
serial_puts(simple_itoa1(adj2.ds0.gWin,s));
serial_putc('-');
serial_puts(simple_itoa1(adj2.ds0.inx,s));
serial_putc('\n');
serial_puts(simple_itoa1(adj2.ds1.gWin,s));
serial_putc('-');
serial_puts(simple_itoa1(adj2.ds1.inx,s));
serial_putc('\n');
if (!ddr16bit_mode) {
serial_puts(simple_itoa1(adj2.ds2.gWin,s));
serial_putc('-');
serial_puts(simple_itoa1(adj2.ds2.inx,s));
serial_putc('\n');
serial_puts(simple_itoa1(adj2.ds3.gWin,s));
serial_putc('-');
serial_puts(simple_itoa1(adj2.ds3.inx,s));
serial_putc('-');
}
serial_putc('\n');
/* ds0 */
for (i=ADJ2_MIN_VAL; i <= ADJ2_MAX_VAL; i++) {
serial_puts(simple_itoa1((adj2_dsx[i] & 0xff),s));
serial_putc(',');
}
serial_putc('\n');
/* ds1 */
serial_putc('\n');
for (i=ADJ2_MIN_VAL; i <= ADJ2_MAX_VAL; i++) {
serial_puts(simple_itoa1((adj2_dsx[i] & 0xff00) >> 8,s));
serial_putc(',');
}
serial_putc('\n');
if (!ddr16bit_mode) {
/* ds2 */
serial_putc('\n');
for (i=ADJ2_MIN_VAL; i <= ADJ2_MAX_VAL; i++) {
serial_puts(simple_itoa1((adj2_dsx[i] & 0xff0000) >> 16,s));
serial_putc(',');
}
serial_putc('\n');
/* ds3 */
serial_putc('\n');
for (i=ADJ2_MIN_VAL; i <= ADJ2_MAX_VAL; i++) {
serial_puts(simple_itoa1((adj2_dsx[i] & 0xff000000) >> 24,s));
serial_putc(',');
}
serial_putc('\n');
}
#endif
if (get_adj2_adjusted_value(adj2_dsx, &adj2, ddr16bit_mode) < 0)
goto error;
#ifdef DDR_TRAINING_MODE_DEBUG_PRINTS
serial_puts(simple_itoa1(adj2.ds0.gWin,s));
serial_putc('-');
serial_puts(simple_itoa1(adj2.ds0.inx,s));
serial_putc('\n');
serial_puts(simple_itoa1(adj2.ds1.gWin,s));
serial_putc('-');
serial_puts(simple_itoa1(adj2.ds1.inx,s));
serial_putc('\n');
if (!ddr16bit_mode) {
serial_puts(simple_itoa1(adj2.ds2.gWin,s));
serial_putc('-');
serial_puts(simple_itoa1(adj2.ds2.inx,s));
serial_putc('\n');
serial_puts(simple_itoa1(adj2.ds3.gWin,s));
serial_putc('-');
serial_puts(simple_itoa1(adj2.ds3.inx,s));
serial_putc('-');
}
#endif
recalculate_adj1_window(ddr16bit_mode, &adj2, dword_list, word_list);
/* Configure the WRLVL_DELAY_X values (ADJ_2) */
if (ddr16bit_mode) {
dqs_value = __le64_to_cpu((*(volatile u64*)(DENALI_CTL_35_DATA))) & 0xffffff0000ffffffULL;
dqs_value |= (u64)(((u64)(adj2.ds0.inx) << 24) |
((u64)(adj2.ds1.inx) << 32));
}
else {
dqs_value = __le64_to_cpu((*(volatile u64*)(DENALI_CTL_35_DATA))) & 0xff00000000ffffffULL;
dqs_value |= (u64)(((u64)(adj2.ds0.inx) << 24) |
((u64)(adj2.ds1.inx) << 32) |
((u64)(adj2.ds2.inx) << 40) |
((u64)(adj2.ds3.inx) << 48));
}
arm_write64(dqs_value, (volatile u64 *)DENALI_CTL_35_DATA); //should be 64bit write
//set sw leveling mode
*(volatile u64*)(DENALI_CTL_67_DATA) = __cpu_to_le64((u64)DENALI_CTL_67_VAL_CFG1 | (1LL << 8));
//sw leveling load
*(volatile u64*)(DENALI_CTL_66_DATA) = __cpu_to_le64((u64)DENALI_CTL_66_VAL_CFG1 | (1LL << 48));
//reset sw leveling mode
*(volatile u64*)(DENALI_CTL_67_DATA) = __cpu_to_le64((u64)DENALI_CTL_67_VAL_CFG1);
/* Configure wr_clk ADJ_1 */
DENALI_DLL_ADJ1_DS0 = (u8)((adj2.ds0.gWin_start + adj2.ds0.gWin_end) >> 1);
DENALI_DLL_ADJ1_DS1 = (u8)((adj2.ds1.gWin_start + adj2.ds1.gWin_end) >> 1);
if (!ddr16bit_mode) {
DENALI_DLL_ADJ1_DS2 = (u8)((adj2.ds2.gWin_start + adj2.ds2.gWin_end) >> 1);
DENALI_DLL_ADJ1_DS3 = (u8)((adj2.ds3.gWin_start + adj2.ds3.gWin_end) >> 1);
}
/* training verification using MDMA transfers */
if (mdma_test(dword_list))
{
goto error;
}
serial_puts(sd);
return;
error:
serial_puts(sf);
//watch dog reset
//*(volatile unsigned int *)TIMER_WDT_HIGH_BOUND = 1;
//*(volatile unsigned int *)TIMER_WDT_CONTROL = 1;
while(1);
return;
}
static u8 do_wr_rd_transaction(u32 ddr_address_offset, u64 *dword_list, u32 *word, u16 ddr16bit_mode)
{
u8 j;
register int reg_0 __asm__ ("r3");
register int reg_1 __asm__ ("r4");
u64 *src, *dst;
u32 read_val;
u8 ret_val = 0;
ddr_address_offset &= ~0x3;
/* Do 64bit wr+rd */
dst = (u64 *)(DDR_BASEADDR+ddr_address_offset);
src = dword_list;
for(j=0; j < 16; j++)
{
__asm__ __volatile__ ("ldmia %0, {%1,%2}" \
: "+r" (src), "=r" (reg_0), "=r" (reg_1) \
);
__asm__ __volatile__ ("stmia %0, {%1,%2}" \
: "+r" (dst), "=r" (reg_0), "=r" (reg_1) \
);
if ((*src & 0x000000ff000000ffLL) != (*dst & 0x000000ff000000ffLL))
{
ret_val |= 1;
}
if ((*src & 0x0000ff000000ff00LL) != (*dst & 0x0000ff000000ff00LL))
{
ret_val |= 1 << 1;
}
if (!ddr16bit_mode) {
if ((*src & 0x00ff000000ff0000LL) != (*dst & 0x00ff000000ff0000LL))
{
ret_val |= 1 << 2;
}
if ((*src & 0xff000000ff000000LL) != (*dst & 0xff000000ff000000LL))
{
ret_val |= 1 << 3;
}
}
*dst = __cpu_to_le64(0); //clear location
dst++;
src++;
}
/* Do 32bit wr+rd */
for (j=0; j < 16; j++)
{
*(((volatile u32 *)(DDR_BASEADDR+ddr_address_offset)) + j) = __cpu_to_le32(*word);
read_val = __le32_to_cpu(*(((volatile u32 *)(DDR_BASEADDR+ddr_address_offset)) + j));
if ((read_val & 0x000000FF) != (*word & 0x000000ff))
{
ret_val |= 1;
}
if ((read_val & 0x0000ff00) != (*word & 0x0000ff00))
{
ret_val |= 1 << 1;
}
if (!ddr16bit_mode) {
if ((read_val & 0x00ff0000) != (*word & 0x00ff0000))
{
ret_val |= 1 << 2;
}
if ((read_val & 0xff000000) != (*word & 0xff000000))
{
ret_val |= 1 << 3;
}
}
*(((volatile u32 *)(DDR_BASEADDR+ddr_address_offset)) + j) = __cpu_to_le32(0); //clear location
word++;
ddr_address_offset = (ddr_address_offset + ADDR_JUMP_SIZE) & (PHYS_SDRAM_SIZE -1);
}
return ret_val;
}
/*
* On success returns 0
*/
static int mdma_test(u64 *dword_list)
{
int ii,j;
unsigned int *mdma_data = (u32 *)0x81000000;
unsigned int *ddr_dst;
unsigned int data_len[] = {1024, 1032, 1048, 1064};
/* init mdma data, at this point we are sure that 32bit wr/rd operations are good */
u32 *dataPtr = (u32 *)dword_list;
for(j=0; j < 9; j++)
{
for(ii=0; ii < 32; ii++)
mdma_data[32*j + ii] = __cpu_to_le32(dataPtr[ii]);
}
for(j=0; j < 4; j++)
{
ddr_dst = (unsigned int *)((j % 2) ? MT_ADDR1_DST : MT_ADDR2_DST);
dataPtr = mdma_data;
mdma_memcpy((void *)mdma_data, (void *)ddr_dst, data_len[j], NULL);
for(ii=0; ii < data_len[j] >> 2; ii++)
if (__le32_to_cpu(*dataPtr++) != __le32_to_cpu(*ddr_dst++))
return 1;
}
return 0; //MDMA test pass
}
@@ -0,0 +1,423 @@
/*
* (C) Copyright Mindspeed Technologies Inc.
*
* 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 <common.h>
#include <asm/hardware.h>
#include <asm/arch/bsp.h>
#define SZ_1K 0x400
#define SZ_128K (SZ_1K * 128)
#define ADDR_JUMP_SIZE SZ_128K
#define MIN_VALID_WINDOW_SIZE 5
#define NO_OF_PATTERNS 16
#define WQS_START 0x30
#define WQS_END 0x60
#define DOS_START 0x55
#define DOS_END 0x75
#define DDD_START 0x9
#define DDD_END 0x30
static int do_wr_rd_verify(u64 *);
u32 do_wr_rd_transaction(u32, u32*, u64*);
u32 do_wr_rd_transaction64(u32 ddr_address_offset, u64*);
extern int serial_init(void);
extern void serial_puts(const char *s);
extern void serial_putc(const char c);
#if 0
/* belongs in utility.c */
static char *simple_itoa(unsigned int i)
{
/* 21 digits plus null terminator, good for 64-bit or smaller ints */
static char local[22];
char *p = &local[21];
*p-- = '\0';
do {
*p-- = '0' + i % 10;
i /= 10;
} while (i > 0);
return p + 1;
}
#endif
extern int mdma_memcpy(void *src, void *dst, int len, unsigned int *crc);
/*
* On success returns 0
*/
static int mdma_test(u64 *dword_list)
{
int ii,j;
unsigned int *mdma_data = (u32 *)0x81000000;
unsigned int ddr_tmp = 0x80002000;
unsigned int ddr_dst;
unsigned int crc1, crc2;
unsigned short data_len[] = {1024, 1032, 1048, 1064};
/* init mdma data, at this point we are sure that 32bit wr/rd operations are good */
u32 *dataPtr = (u32 *)dword_list;
for(j=0; j < 9; j++)
{
for(ii=0; ii < 32; ii++)
mdma_data[32*j + ii] = __cpu_to_le32(dataPtr[ii]);
}
for(ii=0; ii < 4; ii++)
{
ddr_dst = (ii % 2) ? 0x8000ff00 : 0x8300ff00;
//CRC for write
mdma_memcpy((void *)mdma_data, (void *)ddr_dst, data_len[ii], &crc1);
//CRC for read
mdma_memcpy((void *)ddr_dst, (void *)ddr_tmp, data_len[ii], &crc2);
if(crc1 != crc2)
return 1;
}
return 0; //MDMA test pass
}
/************************************************************************
* Function: start_training
* Description:
* Do the DDR training and configures the best values.
* No return value
************************************************************************/
void start_training(void)
{
u32 word_list[NO_OF_PATTERNS] = { 0xffffffff, 0x00000000, 0x12345678, 0x9abcdef0,
0xf7f70202, 0xdfdf2020, 0x80407fbf, 0x08040204,
0x8080fdfd, 0x0808dfdf, 0xa5a55a5a, 0x5a5aa5a5,
0xaaaa5555, 0x5555aaaa, 0x0000ffff, 0x0000ffff};
u64 dword_list[NO_OF_PATTERNS] = {0xffffffff00000000ULL, 0xffffffff00000000ULL,
0x1234567876543210ULL, 0x0123456789abcdefULL,
0xf7f7f7f702020202ULL, 0xdfdfdfdf20202020ULL,
0x804020107fbfdfefULL, 0x0804020110204080ULL,
0x80808080fdfdfdfdULL, 0x08080808dfdfdfdfULL,
0xa5a5a5a55a5a5a5aULL, 0x5a5a5a5aa5a5a5a5ULL,
0xaaaaaaaa55555555ULL, 0x55555555aaaaaaaaULL,
0x00000000ffffffffULL, 0x00000000ffffffffULL
};
unsigned char gbl_wqs_Vstart, gbl_wqs_Vend, cfg_wqs_Vstart, cfg_wqs_Vend, wqs_inx, wqs_Vstart;
unsigned char gbl_dos,cfg_dos, dos_inx;
unsigned char gbl_ddd_Vstart,gbl_ddd_Vend, ddd_Vstart, ddd_inx,ddd_median;
int result;
u32 ddr_addr_offset = 0xff00;
unsigned char sb[] = "DDR Training";
unsigned char sf[] = "Fail";
unsigned char sd[] = "Done";
unsigned char ch = '.';
/* Init of UART will be done later through main init sequence,
* so doing init twice does it make any harm????, I think NO */
serial_init();
serial_puts(sb);
gbl_ddd_Vstart = gbl_ddd_Vend = ddd_Vstart = 0;
cfg_wqs_Vstart = cfg_wqs_Vend = 0;
gbl_dos = cfg_dos = 0;
for(ddd_inx = DDD_START; ddd_inx <= DDD_END; ddd_inx++)
{
serial_putc(ch);
gbl_wqs_Vend = gbl_wqs_Vstart = 0;
/* Configure DDD value */
DENALI_DQS_DELAY0 = ddd_inx;
DENALI_DQS_DELAY1 = ddd_inx;
DENALI_DQS_DELAY2 = ddd_inx;
DENALI_DQS_DELAY3 = ddd_inx;
for (dos_inx = DOS_START; dos_inx <= DOS_END; dos_inx++)
{
/* configure DOS value */
DENALI_DQS_OUT = dos_inx;
wqs_Vstart = 0;
for (wqs_inx = WQS_START; wqs_inx <= WQS_END; wqs_inx++)
{
/* Configure WQS value */
DENALI_WR_DQS = wqs_inx;
result = do_wr_rd_transaction(ddr_addr_offset,word_list, dword_list);
ddr_addr_offset = (ddr_addr_offset + ADDR_JUMP_SIZE) & (PHYS_SDRAM_SIZE - 1);
if (result)
{ //result == FAIL
/* check is this a window closing */
if (wqs_Vstart == 0)
{ //No valid window started
//Do nothing
}
else
{ //end of a valid window
if ((wqs_inx - wqs_Vstart) > (gbl_wqs_Vend - gbl_wqs_Vstart))
{
gbl_wqs_Vstart = wqs_Vstart;
gbl_wqs_Vend = wqs_inx;
gbl_dos = dos_inx;
}
//else Do nothing
//{
//}
wqs_Vstart = 0;
}
}
else
{ //results == SUCCESS
if (wqs_Vstart == 0)
{ //check is this a begining of valid window
wqs_Vstart = wqs_inx;
}
//else
//{
//Do nothing
//}
}
} //wqs_loop end
} //dos_loop end
if ((gbl_wqs_Vend - gbl_wqs_Vstart) > MIN_VALID_WINDOW_SIZE)
{ //accepted window range
if (ddd_Vstart == 0)
{ //valid ddd window not yet started
ddd_Vstart = ddd_inx;
}
//else
//{
//do nothing
//}
}
else
{
if (ddd_Vstart == 0)
{ //no accepted window range & no accepted window started till now
//Do nothing
}
else
{
if ((gbl_ddd_Vend - gbl_ddd_Vstart) < (ddd_inx - ddd_Vstart))
{
gbl_ddd_Vend = ddd_inx;
gbl_ddd_Vstart = ddd_Vstart;
}
//else
//{
//Do nothing
//}
ddd_Vstart = 0;
}
}
if ( (gbl_wqs_Vend - gbl_wqs_Vstart) > (cfg_wqs_Vend - cfg_wqs_Vstart))
{
cfg_wqs_Vend = gbl_wqs_Vend;
cfg_wqs_Vstart = gbl_wqs_Vstart;
cfg_dos = gbl_dos;
}
} //ddd_loop end
if ((cfg_wqs_Vend - cfg_wqs_Vstart) < MIN_VALID_WINDOW_SIZE)
{
serial_puts(sf);
while(1);
}
ddd_median = (gbl_ddd_Vend + gbl_ddd_Vstart) >> 1;
DENALI_DQS_DELAY0 = ddd_median;
DENALI_DQS_DELAY1 = ddd_median;
DENALI_DQS_DELAY2 = ddd_median;
DENALI_DQS_DELAY3 = ddd_median;
DENALI_DQS_OUT = cfg_dos;
DENALI_WR_DQS = (cfg_wqs_Vend + cfg_wqs_Vstart) >> 1;
/* Do verify the training values */
/* 8Bit,16bit,32bit,64bit wr/rd */
result = do_wr_rd_verify(dword_list);
/* MDMA wr/rd */
if (!result)
result = mdma_test(dword_list);
if (result)
{
serial_puts(sf);
while(1);
}
serial_puts(sd);
return;
}
u32 do_wr_rd_transaction(u32 ddr_addr_offset, u32 *word, u64 *dword_list)
{
u32 i;
/* Do 64bit wr+rd */
if (do_wr_rd_transaction64(ddr_addr_offset,dword_list))
return 1; //failure
/* Do 32bit wr+rd */
for (i=0; i < NO_OF_PATTERNS; i++)
{
*((volatile u32 *)(DDR_BASEADDR + ddr_addr_offset) + i) = __cpu_to_le32(*word);
if (__le32_to_cpu(*((volatile u32 *)(DDR_BASEADDR + ddr_addr_offset) + i)) != *word)
{
//reassign to zero
*((volatile u32 *)(DDR_BASEADDR + ddr_addr_offset) + i) = __cpu_to_le32(0);
return 1; //failure
}
word++;
//reassign to zero
*((volatile u32 *)(DDR_BASEADDR + ddr_addr_offset) + i) = __cpu_to_le32(0);
}
return 0; //success
}
u32 do_wr_rd_transaction64(u32 ddr_address_offset, u64 *dword_list)
{
u8 j;
register int reg_0 __asm__ ("r3");
register int reg_1 __asm__ ("r4");
u64 *src,*dst,*dval;
u64 dword_store[NO_OF_PATTERNS];
/* 64bit burst write */
dst = ((volatile u64 *) (DDR_BASEADDR + ddr_address_offset));
src = dword_list;
for(j=0; j < NO_OF_PATTERNS; j++)
{
__asm__ __volatile__ ("ldmia %0, {%1,%2}" \
: "+r" (src), "=r" (reg_0), "=r" (reg_1) \
);
__asm__ __volatile__ ("stmia %0, {%1,%2}" \
: "+r" (dst), "=r" (reg_0), "=r" (reg_1) \
);
if (*src != (*dst))
return 0x1;
src++;
dst++;
}
/* 64bit burst read 16 times */
src = ((u64 *)(DDR_BASEADDR + ddr_address_offset));
dst = dword_store;
dval = dword_list;
for(j=0; j < NO_OF_PATTERNS; j++)
{
__asm__ __volatile__ ("ldmia %0, {%1,%2}" \
: "+r" (src), "=r" (reg_0), "=r" (reg_1) \
);
__asm__ __volatile__ ("stmia %0, {%1,%2}" \
: "+r" (dst), "=r" (reg_0), "=r" (reg_1) \
);
if (*dval != *dst)
{
//reassign to zero
*src = __cpu_to_le64(0x0ULL);
return 0x1;
}
//reassign to zero
*src = __cpu_to_le64(0x0ULL);
src++;
dst++;
dval++;
}
return 0;
}
static int do_wr_rd_verify(u64 *dword_list)
{
u8 i;
u32 ddr_addr_offset = 0xffff00;
u8 *list8 = (u8 *)dword_list;
u16 *list16 = (u16 *)dword_list;
u32 *list32 = (u32 *)dword_list;
u64 *src_aram, *dst_ddr;
register int reg_0 __asm__ ("r3");
register int reg_1 __asm__ ("r4");
src_aram = dword_list;
dst_ddr = ((u64 *)(DDR_BASEADDR + ddr_addr_offset));
for (i=0; i < NO_OF_PATTERNS; i++)
{
//8bit
*((volatile u8 *)(DDR_BASEADDR + ddr_addr_offset) + i) = *(list8+i);
if (*((volatile u8 *)(DDR_BASEADDR + ddr_addr_offset) + i) != *(list8+i))
return 0x1;
//16bit
*((volatile u16 *)(DDR_BASEADDR + ddr_addr_offset) + i) = __cpu_to_le16(*(list16+i));
if (__le16_to_cpu(*((volatile u16 *)(DDR_BASEADDR + ddr_addr_offset) + i)) != *(list16+i))
return 0x1;
//32bit
*((volatile u32 *)(DDR_BASEADDR + ddr_addr_offset) + i) = __cpu_to_le32(*(list32+i));
if (__le32_to_cpu(*((volatile u32 *)(DDR_BASEADDR + ddr_addr_offset) + i)) != *(list32+i))
return 0x1;
//64bit
__asm__ __volatile__ ("ldmia %0, {%1,%2}" \
: "+r" (src_aram), "=r" (reg_0), "=r" (reg_1) \
);
__asm__ __volatile__ ("stmia %0, {%1,%2}" \
: "+r" (dst_ddr), "=r" (reg_0), "=r" (reg_1) \
);
if (*src_aram != (*dst_ddr))
return 0x1;
dst_ddr++;
src_aram++;
ddr_addr_offset = (ddr_addr_offset + ADDR_JUMP_SIZE) & (PHYS_SDRAM_SIZE - 1);
}
return 0;
}