[U-Boot] [PATCH V7 1/3] Initial support for Marvell Orion5x SoC

This patch adds support for the Marvell Orion5x SoC. It has no use alone, and must be followed by a patch to add Orion5x support for serial, then support for the ED Mini V2, an Orion5x-based product from LaCie.
Signed-off-by: Albert Aribaud albert.aribaud@free.fr --- Patchset history
V1: Initial monolithic patch. V2: split in three patches : orion, serial, edmini; checkpatch'ed, with only 6 errors, in patch 1/3, all 6 errors being false positives. V3: useless GPIO and MPP programming support removed; low level init added/CONFIG_SKIP_LOW_LEVEL_INIT removed. V4: all files licensed GPLv2-only removed; RAM bank size detection now uses get_ram_size(). V5: Replaced macros by C structs in dram code. Removed compilation warnings in dram code. Added comments to legacy flash definitions. Split low level init code into SoC- and Chip-specifics. V6: Set copyright dates to 2010, and put standard GPL notice mentioning Marvell's copyright on *_lowlevel_init.S files. V7: Moved GPIO and MPP init code in SoC arch_misc_init() in C. lowlevel_init.S now only contains DRAM init code.
Patch 1 checkpatched with 0 errors and 1 spurious warning. Patches 2 and 3 checkpatched with 0 errors and 0 warnings.
arch/arm/cpu/arm926ejs/orion5x/Makefile | 55 +++++ arch/arm/cpu/arm926ejs/orion5x/cpu.c | 271 ++++++++++++++++++++++ arch/arm/cpu/arm926ejs/orion5x/dram.c | 64 +++++ arch/arm/cpu/arm926ejs/orion5x/lowlevel_init.S | 293 ++++++++++++++++++++++++ arch/arm/cpu/arm926ejs/orion5x/timer.c | 181 +++++++++++++++ arch/arm/include/asm/arch-orion5x/cpu.h | 203 ++++++++++++++++ arch/arm/include/asm/arch-orion5x/mv88f5182.h | 40 ++++ arch/arm/include/asm/arch-orion5x/orion5x.h | 69 ++++++ 8 files changed, 1176 insertions(+), 0 deletions(-) create mode 100644 arch/arm/cpu/arm926ejs/orion5x/Makefile create mode 100644 arch/arm/cpu/arm926ejs/orion5x/cpu.c create mode 100644 arch/arm/cpu/arm926ejs/orion5x/dram.c create mode 100644 arch/arm/cpu/arm926ejs/orion5x/lowlevel_init.S create mode 100644 arch/arm/cpu/arm926ejs/orion5x/timer.c create mode 100644 arch/arm/include/asm/arch-orion5x/cpu.h create mode 100644 arch/arm/include/asm/arch-orion5x/mv88f5182.h create mode 100644 arch/arm/include/asm/arch-orion5x/orion5x.h
diff --git a/arch/arm/cpu/arm926ejs/orion5x/Makefile b/arch/arm/cpu/arm926ejs/orion5x/Makefile new file mode 100644 index 0000000..11f4141 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/orion5x/Makefile @@ -0,0 +1,55 @@ +# +# Copyright (C) 2010 Albert ARIBAUD albert.aribaud@free.fr +# +# Based on original Kirkwood support which is +# (C) Copyright 2009 +# Marvell Semiconductor <www.marvell.com> +# Written-by: Prafulla Wadaskar prafulla@marvell.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., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)lib$(SOC).a + +COBJS-y = cpu.o +COBJS-y += dram.o +COBJS-y += timer.o + +ifndef CONFIG_SKIP_LOWLEVEL_INIT +SOBJS := lowlevel_init.o +endif + +SRCS := $(SOBJS:.o=.S) $(COBJS-y:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS-y)) + +all: $(obj).depend $(LIB) + +$(LIB): $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/arch/arm/cpu/arm926ejs/orion5x/cpu.c b/arch/arm/cpu/arm926ejs/orion5x/cpu.c new file mode 100644 index 0000000..807174a --- /dev/null +++ b/arch/arm/cpu/arm926ejs/orion5x/cpu.c @@ -0,0 +1,271 @@ +/* + * Copyright (C) 2010 Albert ARIBAUD albert.aribaud@free.fr + * + * Based on original Kirkwood support which is + * (C) Copyright 2009 + * Marvell Semiconductor <www.marvell.com> + * Written-by: Prafulla Wadaskar prafulla@marvell.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., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include <common.h> +#include <netdev.h> +#include <asm/cache.h> +#include <u-boot/md5.h> +#include <asm/arch/orion5x.h> +#include <hush.h> + +#define BUFLEN 16 + +void reset_cpu(unsigned long ignored) +{ + struct orion5x_cpu_registers *cpureg = + (struct orion5x_cpu_registers *)ORION5X_CPU_REG_BASE; + + writel(readl(&cpureg->rstoutn_mask) | (1 << 2), + &cpureg->rstoutn_mask); + writel(readl(&cpureg->sys_soft_rst) | 1, + &cpureg->sys_soft_rst); + while (1) + ; +} + +/* + * Window Size + * Used with the Base register to set the address window size and location. + * Must be programmed from LSB to MSB as sequence of ones followed by + * sequence of zeros. The number of ones specifies the size of the window in + * 64 KByte granularity (e.g., a value of 0x00FF specifies 256 = 16 MByte). + * NOTE: A value of 0x0 specifies 64-KByte size. + */ +unsigned int orion5x_winctrl_calcsize(unsigned int sizeval) +{ + int i; + unsigned int j = 0; + u32 val = sizeval >> 1; + + for (i = 0; val > 0x10000; i++) { + j |= (1 << i); + val = val >> 1; + } + return 0x0000ffff & j; +} + +/* + * orion5x_config_adr_windows - Configure address Windows + * + * There are 8 address windows supported by Orion5x Soc to addess different + * devices. Each window can be configured for size, BAR and remap addr + * Below configuration is standard for most of the cases + * + * If remap function not used, remap_lo must be set as base + * + * Reference Documentation: + * Mbus-L to Mbus Bridge Registers Configuration. + * (Sec 25.1 and 25.3 of Datasheet) + */ +int orion5x_config_adr_windows(void) +{ + struct orion5x_win_registers *winregs = + (struct orion5x_win_registers *)ORION5X_CPU_WIN_BASE; + + /* Window 0: PCIE MEM address space */ + writel(ORION5X_CPU_WIN_CTRL_DATA(ORION5X_DEFSZ_PCIE_MEM, + ORION5X_TARGET_PCIE, ORION5X_ATTR_PCIE_MEM, + ORION5X_WIN_ENABLE), &winregs[0].ctrl); + writel(ORION5X_DEFADR_PCIE_MEM, &winregs[0].base); + writel(ORION5X_DEFADR_PCIE_MEM_REMAP_LO, &winregs[0].remap_lo); + writel(ORION5X_DEFADR_PCIE_MEM_REMAP_HI, &winregs[0].remap_hi); + + /* Window 1: PCIE IO address space */ + writel(ORION5X_CPU_WIN_CTRL_DATA(ORION5X_DEFSZ_PCIE_IO, + ORION5X_TARGET_PCIE, ORION5X_ATTR_PCIE_IO, + ORION5X_WIN_ENABLE), &winregs[1].ctrl); + writel(ORION5X_DEFADR_PCIE_IO, &winregs[1].base); + writel(ORION5X_DEFADR_PCIE_IO_REMAP_LO, &winregs[1].remap_lo); + writel(ORION5X_DEFADR_PCIE_IO_REMAP_HI, &winregs[1].remap_hi); + + /* Window 2: PCI MEM address space */ + writel(ORION5X_CPU_WIN_CTRL_DATA(ORION5X_DEFSZ_PCI_MEM, + ORION5X_TARGET_PCI, ORION5X_ATTR_PCI_MEM, + ORION5X_WIN_ENABLE), &winregs[2].ctrl); + writel(ORION5X_DEFADR_PCI_MEM, &winregs[2].base); + + /* Window 3: PCI IO address space */ + writel(ORION5X_CPU_WIN_CTRL_DATA(ORION5X_DEFSZ_PCI_IO, + ORION5X_TARGET_PCI, ORION5X_ATTR_PCI_IO, + ORION5X_WIN_ENABLE), &winregs[3].ctrl); + writel(ORION5X_DEFADR_PCI_IO, &winregs[3].base); + + /* Window 4: DEV_CS0 address space */ + writel(ORION5X_CPU_WIN_CTRL_DATA(ORION5X_DEFSZ_DEV_CS0, + ORION5X_TARGET_DEVICE, ORION5X_ATTR_DEV_CS0, + ORION5X_WIN_ENABLE), &winregs[4].ctrl); + writel(ORION5X_DEFADR_DEV_CS0, &winregs[4].base); + + /* Window 5: DEV_CS1 address space */ + writel(ORION5X_CPU_WIN_CTRL_DATA(ORION5X_DEFSZ_DEV_CS1, + ORION5X_TARGET_DEVICE, ORION5X_ATTR_DEV_CS1, + ORION5X_WIN_ENABLE), &winregs[5].ctrl); + writel(ORION5X_DEFADR_DEV_CS1, &winregs[5].base); + + /* Window 6: DEV_CS2 address space */ + writel(ORION5X_CPU_WIN_CTRL_DATA(ORION5X_DEFSZ_DEV_CS2, + ORION5X_TARGET_DEVICE, ORION5X_ATTR_DEV_CS2, + ORION5X_WIN_ENABLE), &winregs[6].ctrl); + writel(ORION5X_DEFADR_DEV_CS2, &winregs[6].base); + + /* Window 7: BOOT Memory address space */ + writel(ORION5X_CPU_WIN_CTRL_DATA(ORION5X_DEFSZ_BOOTROM, + ORION5X_TARGET_DEVICE, ORION5X_ATTR_BOOTROM, + ORION5X_WIN_ENABLE), &winregs[7].ctrl); + writel(ORION5X_DEFADR_BOOTROM, &winregs[7].base); + + return 0; +} + +/* + * Orion5x identification is done through PCIE space. + */ + +u32 orion5x_device_id(void) +{ + return readl(PCIE_DEV_ID_OFF) >> 16; +} + +u32 orion5x_device_rev(void) +{ + return readl(PCIE_DEV_REV_OFF) & 0xff; +} + +#if defined(CONFIG_DISPLAY_CPUINFO) + +/* Display device and revision IDs. + * This function must cover all known device/revision + * combinations, not only the one for which u-boot is + * compiled; this way, one can identify actual HW in + * case of a mismatch. + */ +int print_cpuinfo(void) +{ + char dev_str[] = "0x0000"; + char rev_str[] = "0x00"; + char *dev_name = NULL; + char *rev_name = NULL; + + u32 dev = orion5x_device_id(); + u32 rev = orion5x_device_rev(); + + if (dev == MV88F5181_DEV_ID) { + dev_name = "MV88F5181"; + if (rev == MV88F5181_REV_B1) + rev_name = "B1"; + else if (rev == MV88F5181L_REV_A1) { + dev_name = "MV88F5181L"; + rev_name = "A1"; + } else if (rev == MV88F5181L_REV_A0) { + dev_name = "MV88F5181L"; + rev_name = "A0"; + } + } else if (dev == MV88F5182_DEV_ID) { + dev_name = "MV88F5182"; + if (rev == MV88F5182_REV_A2) + rev_name = "A2"; + } else if (dev == MV88F5281_DEV_ID) { + dev_name = "MV88F5281"; + if (rev == MV88F5281_REV_D2) + rev_name = "D2"; + else if (rev == MV88F5281_REV_D1) + rev_name = "D1"; + else if (rev == MV88F5281_REV_D0) + rev_name = "D0"; + } else if (dev == MV88F6183_DEV_ID) { + dev_name = "MV88F6183"; + if (rev == MV88F6183_REV_B0) + rev_name = "B0"; + } + if (dev_name == NULL) { + sprintf(dev_str, "0x%04x", dev); + dev_name = dev_str; + } + if (rev_name == NULL) { + sprintf(rev_str, "0x%02x", rev); + rev_name = rev_str; + } + + printf("SoC: Orion5x %s-%s\n", dev_name, rev_name); + + return 0; +} +#endif /* CONFIG_DISPLAY_CPUINFO */ + +#ifdef CONFIG_ARCH_CPU_INIT +int arch_cpu_init(void) +{ + /* Enable and invalidate L2 cache in write through mode */ + invalidate_l2_cache(); + + orion5x_config_adr_windows(); + + return 0; +} +#endif /* CONFIG_ARCH_CPU_INIT */ + +/* + * SOC specific misc init + */ +#if defined(CONFIG_ARCH_MISC_INIT) +int arch_misc_init(void) +{ + u32 temp; + + /*CPU streaming & write allocate */ + temp = readfr_extra_feature_reg(); + temp &= ~(1 << 28); /* disable wr alloc */ + writefr_extra_feature_reg(temp); + + temp = readfr_extra_feature_reg(); + temp &= ~(1 << 29); /* streaming disabled */ + writefr_extra_feature_reg(temp); + + /* L2Cache settings */ + temp = readfr_extra_feature_reg(); + /* Disable L2C pre fetch - Set bit 24 */ + temp |= (1 << 24); + /* enable L2C - Set bit 22 */ + temp |= (1 << 22); + writefr_extra_feature_reg(temp); + + icache_enable(); + /* Change reset vector to address 0x0 */ + temp = get_cr(); + set_cr(temp & ~CR_V); + + /* Set CPIOs and MPPs - values provided by board + include file */ +/* + writel(ORION5X_MPP_BASE+0x00, ORION5X_MPP0_7); + writel(ORION5X_MPP_BASE+0x04, ORION5X_MPP8_15); + writel(ORION5X_MPP_BASE+0x50, ORION5X_MPP16_23); + writel(ORION5X_GPIO_BASE+0x04, ORION5X_GPIO_OUT_ENABLE); +*/ + return 0; +} +#endif /* CONFIG_ARCH_MISC_INIT */ diff --git a/arch/arm/cpu/arm926ejs/orion5x/dram.c b/arch/arm/cpu/arm926ejs/orion5x/dram.c new file mode 100644 index 0000000..c719798 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/orion5x/dram.c @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2010 Albert ARIBAUD albert.aribaud@free.fr + * + * Based on original Kirkwood support which is + * (C) Copyright 2009 + * Marvell Semiconductor <www.marvell.com> + * Written-by: Prafulla Wadaskar prafulla@marvell.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., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include <common.h> +#include <config.h> +#include <asm/arch/orion5x.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* + * orion5x_sdram_bar - reads SDRAM Base Address Register + */ +u32 orion5x_sdram_bar(enum memory_bank bank) +{ + struct orion5x_ddr_addr_decode_registers *winregs = + (struct orion5x_ddr_addr_decode_registers *) + ORION5X_CPU_WIN_BASE; + + u32 result = 0; + u32 enable = 0x01 & winregs[bank].size; + + if ((!enable) || (bank > BANK3)) + return 0; + + result = winregs[bank].base; + return result; +} + +int dram_init(void) +{ + int i; + + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + gd->bd->bi_dram[i].start = orion5x_sdram_bar(i); + gd->bd->bi_dram[i].size = get_ram_size( + (volatile long *) (gd->bd->bi_dram[i].start), + CONFIG_MAX_RAM_BANK_SIZE); + } + return 0; +} diff --git a/arch/arm/cpu/arm926ejs/orion5x/lowlevel_init.S b/arch/arm/cpu/arm926ejs/orion5x/lowlevel_init.S new file mode 100644 index 0000000..b0e15f6 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/orion5x/lowlevel_init.S @@ -0,0 +1,293 @@ +/* + * Copyright (C) 2010 Albert ARIBAUD albert.aribaud@free.fr + * + * (C) Copyright 2009 + * Marvell Semiconductor <www.marvell.com> + * Written-by: Prafulla Wadaskar prafulla@marvell.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., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include <config.h> +#include "asm/arch/orion5x.h" + +/* + * Configuration values for SDRAM access setup + */ + +#define SDRAM_CONFIG 0x3148400 +#define SDRAM_MODE 0x62 +#define SDRAM_CONTROL 0x4041000 +#define SDRAM_TIME_CTRL_LOW 0x11602220 +#define SDRAM_TIME_CTRL_HI 0x40c +#define SDRAM_OPEN_PAGE_EN 0x0 +/* DDR 1 2x 32M NANYA NT5DS16M16CS-6K ==> 64MB */ +#define SDRAM_BANK0_SIZE 0x3ff0001 +#define SDRAM_ADDR_CTRL 0x10 + +#define SDRAM_OP_NOP 0x05 +#define SDRAM_OP_SETMODE 0x03 + +#define SDRAM_PAD_CTRL_WR_EN 0x80000000 +#define SDRAM_PAD_CTRL_TUNE_EN 0x00010000 +#define SDRAM_PAD_CTRL_DRVN_MASK 0x0000003f +#define SDRAM_PAD_CTRL_DRVP_MASK 0x00000fc0 + +/* + * For Guideline MEM-3 - Drive Strength value + */ + +#define DDR1_PAD_STRENGTH_DEFAULT 0x00001000 +#define SDRAM_PAD_CTRL_DRV_STR_MASK 0x00003000 + +/* + * For Guideline MEM-4 - DQS Reference Delay Tuning + */ + +#define MSAR_ARMDDRCLCK_MASK 0x000000f0 +#define MSAR_ARMDDRCLCK_H_MASK 0x00000100 + +#define MSAR_ARMDDRCLCK_333_167 0x00000000 +#define MSAR_ARMDDRCLCK_500_167 0x00000030 +#define MSAR_ARMDDRCLCK_667_167 0x00000060 +#define MSAR_ARMDDRCLCK_400_200_1 0x000001E0 +#define MSAR_ARMDDRCLCK_400_200 0x00000010 +#define MSAR_ARMDDRCLCK_600_200 0x00000050 +#define MSAR_ARMDDRCLCK_800_200 0x00000070 + +#define FTDLL_DDR1_166MHZ 0x0047F001 + +#define FTDLL_DDR1_200MHZ 0x0044D001 + +/* + * Low-level init happens right after start.S has switched to SVC32, + * flushed and disabled caches and disabled MMU. We're still running + * from the boot chip select, so the first thing we should do is set + * up RAM for us to relocate into. + */ + +.globl lowlevel_init + +lowlevel_init: + + /* Use 'r4 as the base for internal register accesses */ + ldr r4, =ORION5X_REGS_PHY_BASE + + /* move internal registers from the default 0xD0000000 + * to their intended location, defined by SoC */ + ldr r3, =0xD0000000 + add r3, r3, #0x20000 + str r4, [r3, #0x80] + + /* Use R3 as the base for DRAM registers */ + add r3, r4, #0x01000 + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + str r6, [r3, #0x480] + + /* Use R3 as the base for PCI registers */ + add r3, r4, #0x31000 + + /* Disable arbiter */ + ldr r6, =0x00000030 + str r6, [r3, #0xd00] + + /* Use R3 as the base for DRAM registers */ + add r3, r4, #0x01000 + + /* set all dram windows to 0 */ + mov r6, #0 + str r6, [r3, #0x504] + str r6, [r3, #0x50C] + str r6, [r3, #0x514] + str r6, [r3, #0x51C] + + /* 1) Configure SDRAM */ + ldr r6, =SDRAM_CONFIG + str r6, [r3, #0x400] + + /* 2) Set SDRAM Control reg */ + ldr r6, =SDRAM_CONTROL + str r6, [r3, #0x404] + + /* 3) Write SDRAM address control register */ + ldr r6, =SDRAM_ADDR_CTRL + str r6, [r3, #0x410] + + /* 4) Write SDRAM bank 0 size register */ + ldr r6, =SDRAM_BANK0_SIZE + str r6, [r3, #0x504] + /* keep other banks disabled */ + + /* 5) Write SDRAM open pages control register */ + ldr r6, =SDRAM_OPEN_PAGE_EN + str r6, [r3, #0x414] + + /* 6) Write SDRAM timing Low register */ + ldr r6, =SDRAM_TIME_CTRL_LOW + str r6, [r3, #0x408] + + /* 7) Write SDRAM timing High register */ + ldr r6, =SDRAM_TIME_CTRL_HI + str r6, [r3, #0x40C] + + /* 8) Write SDRAM mode register */ + /* The CPU must not attempt to change the SDRAM Mode register setting */ + /* prior to DRAM controller completion of the DRAM initialization */ + /* sequence. To guarantee this restriction, it is recommended that */ + /* the CPU sets the SDRAM Operation register to NOP command, performs */ + /* read polling until the register is back in Normal operation value, */ + /* and then sets SDRAM Mode register to its new value. */ + + /* 8.1 write 'nop' to SDRAM operation */ + ldr r6, =SDRAM_OP_NOP + str r6, [r3, #0x418] + + /* 8.2 poll SDRAM operation until back in 'normal' mode. */ +1: + ldr r6, [r3, #0x418] + cmp r6, #0 + bne 1b + + /* 8.3 Now its safe to write new value to SDRAM Mode register */ + ldr r6, =SDRAM_MODE + str r6, [r3, #0x41C] + + /* 8.4 Set new mode */ + ldr r6, =SDRAM_OP_SETMODE + str r6, [r3, #0x418] + + /* 8.5 poll SDRAM operation until back in 'normal' mode. */ +2: + ldr r6, [r3, #0x418] + cmp r6, #0 + bne 2b + + /* DDR SDRAM Address/Control Pads Calibration */ + ldr r6, [r3, #0x4C0] + + /* Set Bit [31] to make the register writable */ + orr r6, r6, #SDRAM_PAD_CTRL_WR_EN + str r6, [r3, #0x4C0] + + bic r6, r6, #SDRAM_PAD_CTRL_WR_EN + bic r6, r6, #SDRAM_PAD_CTRL_TUNE_EN + bic r6, r6, #SDRAM_PAD_CTRL_DRVN_MASK + bic r6, r6, #SDRAM_PAD_CTRL_DRVP_MASK + + /* Get the final N locked value of driving strength [22:17] */ + mov r1, r6 + mov r1, r1, LSL #9 + mov r1, r1, LSR #26 /* r1[5:0]<DrvN> = r3[22:17]<LockN> */ + orr r1, r1, r1, LSL #6 /* r1[11:6]<DrvP> = r1[5:0]<DrvN> */ + + /* Write to both <DrvN> bits [5:0] and <DrvP> bits [11:6] */ + orr r6, r6, r1 + str r6, [r3, #0x4C0] + + /* DDR SDRAM Data Pads Calibration */ + ldr r6, [r3, #0x4C4] + + /* Set Bit [31] to make the register writable */ + orr r6, r6, #SDRAM_PAD_CTRL_WR_EN + str r6, [r3, #0x4C4] + + bic r6, r6, #SDRAM_PAD_CTRL_WR_EN + bic r6, r6, #SDRAM_PAD_CTRL_TUNE_EN + bic r6, r6, #SDRAM_PAD_CTRL_DRVN_MASK + bic r6, r6, #SDRAM_PAD_CTRL_DRVP_MASK + + /* Get the final N locked value of driving strength [22:17] */ + mov r1, r6 + mov r1, r1, LSL #9 + mov r1, r1, LSR #26 + orr r1, r1, r1, LSL #6 /* r1[5:0] = r3[22:17]<LockN> */ + + /* Write to both <DrvN> bits [5:0] and <DrvP> bits [11:6] */ + orr r6, r6, r1 + + str r6, [r3, #0x4C4] + + /* Implement Guideline (GL# MEM-3) Drive Strength Value */ + /* Relevant for: 88F5181-A1/B0/B1 and 88F5281-A0/B0 */ + + ldr r1, =DDR1_PAD_STRENGTH_DEFAULT + + /* Enable writes to DDR SDRAM Addr/Ctrl Pads Calibration register */ + ldr r6, [r3, #0x4C0] + orr r6, r6, #SDRAM_PAD_CTRL_WR_EN + str r6, [r3, #0x4C0] + + /* Correct strength and disable writes again */ + bic r6, r6, #SDRAM_PAD_CTRL_WR_EN + bic r6, r6, #SDRAM_PAD_CTRL_DRV_STR_MASK + orr r6, r6, r1 + str r6, [r3, #0x4C0] + + /* Enable writes to DDR SDRAM Data Pads Calibration register */ + ldr r6, [r3, #0x4C4] + orr r6, r6, #SDRAM_PAD_CTRL_WR_EN + str r6, [r3, #0x4C4] + + /* Correct strength and disable writes again */ + bic r6, r6, #SDRAM_PAD_CTRL_DRV_STR_MASK + bic r6, r6, #SDRAM_PAD_CTRL_WR_EN + orr r6, r6, r1 + str r6, [r3, #0x4C4] + + /* Implement Guideline (GL# MEM-4) DQS Reference Delay Tuning */ + /* Relevant for: 88F5181-A1/B0/B1 and 88F5281-A0/B0 */ + + /* Get the "sample on reset" register for the DDR frequancy */ + ldr r3, =0x10000 + ldr r6, [r3, #0x010] + ldr r1, =MSAR_ARMDDRCLCK_MASK + and r1, r6, r1 + + ldr r6, =FTDLL_DDR1_166MHZ + cmp r1, #MSAR_ARMDDRCLCK_333_167 + beq 3f + cmp r1, #MSAR_ARMDDRCLCK_500_167 + beq 3f + cmp r1, #MSAR_ARMDDRCLCK_667_167 + beq 3f + + ldr r6, =FTDLL_DDR1_200MHZ + cmp r1, #MSAR_ARMDDRCLCK_400_200_1 + beq 3f + cmp r1, #MSAR_ARMDDRCLCK_400_200 + beq 3f + cmp r1, #MSAR_ARMDDRCLCK_600_200 + beq 3f + cmp r1, #MSAR_ARMDDRCLCK_800_200 + beq 3f + + ldr r6, =0 + +3: + /* Use R3 as the base for DRAM registers */ + add r3, r4, #0x01000 + + ldr r2, [r3, #0x484] + orr r2, r2, r6 + str r2, [r3, #0x484] + + /* Return to U-boot via saved link register */ + mov pc, lr diff --git a/arch/arm/cpu/arm926ejs/orion5x/timer.c b/arch/arm/cpu/arm926ejs/orion5x/timer.c new file mode 100644 index 0000000..115448f --- /dev/null +++ b/arch/arm/cpu/arm926ejs/orion5x/timer.c @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2010 Albert ARIBAUD albert.aribaud@free.fr + * + * Based on original Kirkwood support which is + * Copyright (C) Marvell International Ltd. and its affiliates + * Written-by: Prafulla Wadaskar prafulla@marvell.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., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include <common.h> +#include <asm/arch/orion5x.h> + +#define UBOOT_CNTR 0 /* counter to use for uboot timer */ + +/* Timer reload and current value registers */ +struct orion5x_tmr_val { + u32 reload; /* Timer reload reg */ + u32 val; /* Timer value reg */ +}; + +/* Timer registers */ +struct orion5x_tmr_registers { + u32 ctrl; /* Timer control reg */ + u32 pad[3]; + struct orion5x_tmr_val tmr[2]; + u32 wdt_reload; + u32 wdt_val; +}; + +struct orion5x_tmr_registers *orion5x_tmr_regs = + (struct orion5x_tmr_registers *)ORION5X_TIMER_BASE; + +/* + * ARM Timers Registers Map + */ +#define CNTMR_CTRL_REG (&orion5x_tmr_regs->ctrl) +#define CNTMR_RELOAD_REG(tmrnum) (&orion5x_tmr_regs->tmr[tmrnum].reload) +#define CNTMR_VAL_REG(tmrnum) (&orion5x_tmr_regs->tmr[tmrnum].val) + +/* + * ARM Timers Control Register + * CPU_TIMERS_CTRL_REG (CTCR) + */ +#define CTCR_ARM_TIMER_EN_OFFS(cntr) (cntr * 2) +#define CTCR_ARM_TIMER_EN_MASK(cntr) (1 << CTCR_ARM_TIMER_EN_OFFS) +#define CTCR_ARM_TIMER_EN(cntr) (1 << CTCR_ARM_TIMER_EN_OFFS(cntr)) +#define CTCR_ARM_TIMER_DIS(cntr) (0 << CTCR_ARM_TIMER_EN_OFFS(cntr)) + +#define CTCR_ARM_TIMER_AUTO_OFFS(cntr) ((cntr * 2) + 1) +#define CTCR_ARM_TIMER_AUTO_MASK(cntr) (1 << 1) +#define CTCR_ARM_TIMER_AUTO_EN(cntr) (1 << CTCR_ARM_TIMER_AUTO_OFFS(cntr)) +#define CTCR_ARM_TIMER_AUTO_DIS(cntr) (0 << CTCR_ARM_TIMER_AUTO_OFFS(cntr)) + +/* + * ARM Timer\Watchdog Reload Register + * CNTMR_RELOAD_REG (TRR) + */ +#define TRG_ARM_TIMER_REL_OFFS 0 +#define TRG_ARM_TIMER_REL_MASK 0xffffffff + +/* + * ARM Timer\Watchdog Register + * CNTMR_VAL_REG (TVRG) + */ +#define TVR_ARM_TIMER_OFFS 0 +#define TVR_ARM_TIMER_MASK 0xffffffff +#define TVR_ARM_TIMER_MAX 0xffffffff +#define TIMER_LOAD_VAL 0xffffffff + +static inline ulong read_timer(void) +{ + return readl(CNTMR_VAL_REG(UBOOT_CNTR)) + / (CONFIG_SYS_TCLK / 1000); +} + +static ulong timestamp; +static ulong lastdec; + +void reset_timer_masked(void) +{ + /* reset time */ + lastdec = read_timer(); + timestamp = 0; +} + +ulong get_timer_masked(void) +{ + ulong now = read_timer(); + + if (lastdec >= now) { + /* normal mode */ + timestamp += lastdec - now; + } else { + /* we have an overflow ... */ + timestamp += lastdec + + (TIMER_LOAD_VAL / (CONFIG_SYS_TCLK / 1000)) - now; + } + lastdec = now; + + return timestamp; +} + +void reset_timer(void) +{ + reset_timer_masked(); +} + +ulong get_timer(ulong base) +{ + return get_timer_masked() - base; +} + +void set_timer(ulong t) +{ + timestamp = t; +} + +static inline ulong uboot_cntr_val(void) +{ + return readl(CNTMR_VAL_REG(UBOOT_CNTR)); +} + +void __udelay(unsigned long usec) +{ + uint current; + ulong delayticks; + + current = uboot_cntr_val(); + delayticks = (usec * (CONFIG_SYS_TCLK / 1000000)); + + if (current < delayticks) { + delayticks -= current; + while (uboot_cntr_val() < current) + ; + while ((TIMER_LOAD_VAL - delayticks) < uboot_cntr_val()) + ; + } else { + while (uboot_cntr_val() > (current - delayticks)) + ; + } +} + +/* + * init the counter + */ +int timer_init(void) +{ + unsigned int cntmrctrl; + + /* load value into timer */ + writel(TIMER_LOAD_VAL, CNTMR_RELOAD_REG(UBOOT_CNTR)); + writel(TIMER_LOAD_VAL, CNTMR_VAL_REG(UBOOT_CNTR)); + + /* enable timer in auto reload mode */ + cntmrctrl = readl(CNTMR_CTRL_REG); + cntmrctrl |= CTCR_ARM_TIMER_EN(UBOOT_CNTR); + cntmrctrl |= CTCR_ARM_TIMER_AUTO_EN(UBOOT_CNTR); + writel(cntmrctrl, CNTMR_CTRL_REG); + + /* init the timestamp and lastdec value */ + reset_timer_masked(); + + return 0; +} diff --git a/arch/arm/include/asm/arch-orion5x/cpu.h b/arch/arm/include/asm/arch-orion5x/cpu.h new file mode 100644 index 0000000..22e2dd3 --- /dev/null +++ b/arch/arm/include/asm/arch-orion5x/cpu.h @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2010 Albert ARIBAUD albert.aribaud@free.fr + * + * Based on original Kirorion5x_ood support which is + * (C) Copyright 2009 + * Marvell Semiconductor <www.marvell.com> + * Written-by: Prafulla Wadaskar prafulla@marvell.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., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#ifndef _ORION5X_CPU_H +#define _ORION5X_CPU_H + +#include <asm/system.h> + +#ifndef __ASSEMBLY__ + +#define ORION5X_CPU_WIN_CTRL_DATA(size, target, attr, en) (en | (target << 4) \ + | (attr << 8) | (orion5x_winctrl_calcsize(size) << 16)) + +#define ORION5XGBE_PORT_SERIAL_CONTROL1_REG(_x) \ + ((_x ? ORION5X_EGIGA0_BASE : ORION5X_EGIGA1_BASE) + 0x44c) + +enum memory_bank { + BANK0, + BANK1, + BANK2, + BANK3 +}; + +enum orion5x_cpu_winen { + ORION5X_WIN_DISABLE, + ORION5X_WIN_ENABLE +}; + +enum orion5x_cpu_target { + ORION5X_TARGET_DRAM = 0, + ORION5X_TARGET_DEVICE = 1, + ORION5X_TARGET_PCI = 3, + ORION5X_TARGET_PCIE = 4, + ORION5X_TARGET_SASRAM = 9 +}; + +enum orion5x_cpu_attrib { + ORION5X_ATTR_DRAM_CS0 = 0x0e, + ORION5X_ATTR_DRAM_CS1 = 0x0d, + ORION5X_ATTR_DRAM_CS2 = 0x0b, + ORION5X_ATTR_DRAM_CS3 = 0x07, + ORION5X_ATTR_PCI_MEM = 0x59, + ORION5X_ATTR_PCI_IO = 0x51, + ORION5X_ATTR_PCIE_MEM = 0x59, + ORION5X_ATTR_PCIE_IO = 0x51, + ORION5X_ATTR_SASRAM = 0x00, + ORION5X_ATTR_DEV_CS0 = 0x1e, + ORION5X_ATTR_DEV_CS1 = 0x1d, + ORION5X_ATTR_DEV_CS2 = 0x1b, + ORION5X_ATTR_BOOTROM = 0x0f +}; + +/* + * Default Device Address MAP BAR values + */ +#define ORION5X_DEFADR_PCIE_MEM 0x90000000 +#define ORION5X_DEFADR_PCIE_MEM_REMAP_LO 0x90000000 +#define ORION5X_DEFADR_PCIE_MEM_REMAP_HI 0 +#define ORION5X_DEFSZ_PCIE_MEM (128*1024*1024) + +#define ORION5X_DEFADR_PCIE_IO 0xf0000000 +#define ORION5X_DEFADR_PCIE_IO_REMAP_LO 0x90000000 +#define ORION5X_DEFADR_PCIE_IO_REMAP_HI 0 +#define ORION5X_DEFSZ_PCIE_IO (64*1024) + +#define ORION5X_DEFADR_PCI_MEM 0x98000000 +#define ORION5X_DEFSZ_PCI_MEM (128*1024*1024) + +#define ORION5X_DEFADR_PCI_IO 0xf0100000 +#define ORION5X_DEFSZ_PCI_IO (64*1024) + +#define ORION5X_DEFADR_DEV_CS0 0xfa000000 +#define ORION5X_DEFSZ_DEV_CS0 (2*1024*1024) + +#define ORION5X_DEFADR_DEV_CS1 0xf8000000 +#define ORION5X_DEFSZ_DEV_CS1 (32*1024*1024) + +#define ORION5X_DEFADR_DEV_CS2 0xfa800000 +#define ORION5X_DEFSZ_DEV_CS2 (1*1024*1024) + +#define ORION5X_DEFADR_BOOTROM 0xFFF80000 +#define ORION5X_DEFSZ_BOOTROM (512*1024) + +/* + * PCIE registers are used for SoC device ID and revision + */ +#define PCIE_DEV_ID_OFF (ORION5X_REG_PCIE_BASE + 0x0000) +#define PCIE_DEV_REV_OFF (ORION5X_REG_PCIE_BASE + 0x0008) + +/* + * The following definitions are intended for identifying + * the real device and revision on which u-boot is running + * even if it was compiled only for a specific one. Thus, + * these constants must not be considered chip-specific. + */ + +/* Orion-1 (88F5181) and Orion-VoIP (88F5181L) */ +#define MV88F5181_DEV_ID 0x5181 +#define MV88F5181_REV_B1 3 +#define MV88F5181L_REV_A0 8 +#define MV88F5181L_REV_A1 9 +/* Orion-NAS (88F5182) */ +#define MV88F5182_DEV_ID 0x5182 +#define MV88F5182_REV_A2 2 +/* Orion-2 (88F5281) */ +#define MV88F5281_DEV_ID 0x5281 +#define MV88F5281_REV_D0 4 +#define MV88F5281_REV_D1 5 +#define MV88F5281_REV_D2 6 +/* Orion-1-90 (88F6183) */ +#define MV88F6183_DEV_ID 0x6183 +#define MV88F6183_REV_B0 3 + +/* + * read feroceon core extra feature register + * using co-proc instruction + */ +static inline unsigned int readfr_extra_feature_reg(void) +{ + unsigned int val; + asm volatile ("mrc p15, 1, %0, c15, c1, 0 @ readfr exfr" : "=r" + (val) : : "cc"); + return val; +} + +/* + * write feroceon core extra feature register + * using co-proc instruction + */ +static inline void writefr_extra_feature_reg(unsigned int val) +{ + asm volatile ("mcr p15, 1, %0, c15, c1, 0 @ writefr exfr" : : "r" + (val) : "cc"); + isb(); +} + +/* + * AHB to Mbus Bridge Registers + * Source: 88F5182 User Manual, Appendix A, section A.4 + * Note: only windows 0 and 1 have remap capability. + */ +struct orion5x_win_registers { + u32 ctrl; + u32 base; + u32 remap_lo; + u32 remap_hi; +}; + +/* + * CPU control and status Registers + * Source: 88F5182 User Manual, Appendix A, section A.4 + */ +struct orion5x_cpu_registers { + u32 config; /*0x20100 */ + u32 ctrl_stat; /*0x20104 */ + u32 rstoutn_mask; /* 0x20108 */ + u32 sys_soft_rst; /* 0x2010C */ + u32 ahb_mbus_cause_irq; /* 0x20110 */ + u32 ahb_mbus_mask_irq; /* 0x20114 */ +}; + +/* + * DDR SDRAM Controller Address Decode Registers + * Source: 88F5182 User Manual, Appendix A, section A.5.1 + */ +struct orion5x_ddr_addr_decode_registers { + u32 base; + u32 size; +}; + +/* + * functions + */ +void reset_cpu(unsigned long ignored); +u32 orion5x_device_id(void); +u32 orion5x_device_rev(void); +unsigned int orion5x_winctrl_calcsize(unsigned int sizeval); +#endif /* __ASSEMBLY__ */ +#endif /* _ORION5X_CPU_H */ diff --git a/arch/arm/include/asm/arch-orion5x/mv88f5182.h b/arch/arm/include/asm/arch-orion5x/mv88f5182.h new file mode 100644 index 0000000..86ba08d --- /dev/null +++ b/arch/arm/include/asm/arch-orion5x/mv88f5182.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2010 Albert ARIBAUD albert.aribaud@free.fr + * + * Based on original Kirkwood 88F6182 support which is + * (C) Copyright 2009 + * Marvell Semiconductor <www.marvell.com> + * Written-by: Prafulla Wadaskar prafulla@marvell.com + * + * Header file for Feroceon CPU core 88F5182 SOC. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#ifndef _CONFIG_88F5182_H +#define _CONFIG_88F5182_H + +/* SOC specific definitions */ +#define F88F5182_REGS_PHYS_BASE 0xf1000000 +#define ORION5X_REGS_PHY_BASE F88F5182_REGS_PHYS_BASE + +/* TCLK Core Clock defination */ +#define CONFIG_SYS_TCLK 166000000 /* 166MHz */ + +#endif /* _CONFIG_88F5182_H */ diff --git a/arch/arm/include/asm/arch-orion5x/orion5x.h b/arch/arm/include/asm/arch-orion5x/orion5x.h new file mode 100644 index 0000000..4008c84 --- /dev/null +++ b/arch/arm/include/asm/arch-orion5x/orion5x.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2010 Albert ARIBAUD albert.aribaud@free.fr + * + * Based on original Kirkwood support which is + * (C) Copyright 2009 + * Marvell Semiconductor <www.marvell.com> + * Written-by: Prafulla Wadaskar prafulla@marvell.com + * + * Header file for Marvell's Orion SoC with Feroceon CPU core. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#ifndef _ASM_ARCH_ORION5X_H +#define _ASM_ARCH_ORION5X_H + +#ifndef __ASSEMBLY__ +#include <asm/types.h> +#include <asm/io.h> +#endif /* __ASSEMBLY__ */ + +#if defined(CONFIG_FEROCEON) +#include <asm/arch/cpu.h> + +/* SOC specific definations */ +#define ORION5X_REGISTER(x) (ORION5X_REGS_PHY_BASE + x) + +/* Documented registers */ +#define ORION5X_TWSI_BASE (ORION5X_REGISTER(0x11000)) +#define ORION5X_UART0_BASE (ORION5X_REGISTER(0x12000)) +#define ORION5X_UART1_BASE (ORION5X_REGISTER(0x12100)) +#define ORION5X_MPP_BASE (ORION5X_REGISTER(0x10000)) +#define ORION5X_GPIO_BASE (ORION5X_REGISTER(0x10100)) +#define ORION5X_CPU_WIN_BASE (ORION5X_REGISTER(0x20000)) +#define ORION5X_CPU_REG_BASE (ORION5X_REGISTER(0x20100)) +#define ORION5X_TIMER_BASE (ORION5X_REGISTER(0x20300)) +#define ORION5X_REG_PCI_BASE (ORION5X_REGISTER(0x30000)) +#define ORION5X_REG_PCIE_BASE (ORION5X_REGISTER(0x40000)) +#define ORION5X_USB20_PORT0_BASE (ORION5X_REGISTER(0x50000)) +#define ORION5X_USB20_PORT1_BASE (ORION5X_REGISTER(0xA0000)) +#define ORION5X_EGIGA_BASE (ORION5X_REGISTER(0x72000)) + +#define CONFIG_MAX_RAM_BANK_SIZE (64*1024*1024) + +/* include here SoC variants. 5181, 5281, 6183 should go here when + adding support for them, and this comment should then be updated. */ +#if defined(CONFIG_88F5182) +#include <asm/arch/mv88f5182.h> +#else +#error "SOC Name not defined" +#endif +#endif /* CONFIG_FEROCEON */ +#endif /* _ASM_ARCH_ORION5X_H */

Hi Albert
I am OOO for next four days, I will try to provide feedback earliest possible
Regards.. Prafulla . .
-----Original Message----- From: u-boot-bounces@lists.denx.de [mailto:u-boot-bounces@lists.denx.de] On Behalf Of Albert Aribaud Sent: Thursday, June 10, 2010 2:20 AM To: u-boot@lists.denx.de Subject: [U-Boot] [PATCH V7 1/3] Initial support for Marvell Orion5x SoC
This patch adds support for the Marvell Orion5x SoC. It has no use alone, and must be followed by a patch to add Orion5x support for serial, then support for the ED Mini V2, an Orion5x-based product from LaCie.
Signed-off-by: Albert Aribaud albert.aribaud@free.fr
Patchset history
V1: Initial monolithic patch. V2: split in three patches : orion, serial, edmini; checkpatch'ed, with only 6 errors, in patch 1/3, all 6 errors being false positives. V3: useless GPIO and MPP programming support removed; low level init added/CONFIG_SKIP_LOW_LEVEL_INIT removed. V4: all files licensed GPLv2-only removed; RAM bank size detection now uses get_ram_size(). V5: Replaced macros by C structs in dram code. Removed compilation warnings in dram code. Added comments to legacy flash definitions. Split low level init code into SoC- and Chip-specifics. V6: Set copyright dates to 2010, and put standard GPL notice mentioning Marvell's copyright on *_lowlevel_init.S files. V7: Moved GPIO and MPP init code in SoC arch_misc_init() in C. lowlevel_init.S now only contains DRAM init code.
Patch 1 checkpatched with 0 errors and 1 spurious warning. Patches 2 and 3 checkpatched with 0 errors and 0 warnings.
arch/arm/cpu/arm926ejs/orion5x/Makefile | 55 +++++ arch/arm/cpu/arm926ejs/orion5x/cpu.c | 271 ++++++++++++++++++++++ arch/arm/cpu/arm926ejs/orion5x/dram.c | 64 +++++ arch/arm/cpu/arm926ejs/orion5x/lowlevel_init.S | 293 ++++++++++++++++++++++++ arch/arm/cpu/arm926ejs/orion5x/timer.c | 181 +++++++++++++++ arch/arm/include/asm/arch-orion5x/cpu.h | 203 ++++++++++++++++ arch/arm/include/asm/arch-orion5x/mv88f5182.h | 40 ++++ arch/arm/include/asm/arch-orion5x/orion5x.h | 69 ++++++ 8 files changed, 1176 insertions(+), 0 deletions(-) create mode 100644 arch/arm/cpu/arm926ejs/orion5x/Makefile create mode 100644 arch/arm/cpu/arm926ejs/orion5x/cpu.c create mode 100644 arch/arm/cpu/arm926ejs/orion5x/dram.c create mode 100644 arch/arm/cpu/arm926ejs/orion5x/lowlevel_init.S create mode 100644 arch/arm/cpu/arm926ejs/orion5x/timer.c create mode 100644 arch/arm/include/asm/arch-orion5x/cpu.h create mode 100644 arch/arm/include/asm/arch-orion5x/mv88f5182.h create mode 100644 arch/arm/include/asm/arch-orion5x/orion5x.h
diff --git a/arch/arm/cpu/arm926ejs/orion5x/Makefile b/arch/arm/cpu/arm926ejs/orion5x/Makefile new file mode 100644 index 0000000..11f4141 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/orion5x/Makefile @@ -0,0 +1,55 @@ +# +# Copyright (C) 2010 Albert ARIBAUD albert.aribaud@free.fr +# +# Based on original Kirkwood support which is +# (C) Copyright 2009 +# Marvell Semiconductor <www.marvell.com> +# Written-by: Prafulla Wadaskar prafulla@marvell.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., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA +#
+include $(TOPDIR)/config.mk
+LIB = $(obj)lib$(SOC).a
+COBJS-y = cpu.o +COBJS-y += dram.o +COBJS-y += timer.o
+ifndef CONFIG_SKIP_LOWLEVEL_INIT +SOBJS := lowlevel_init.o +endif
+SRCS := $(SOBJS:.o=.S) $(COBJS-y:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS-y))
+all: $(obj).depend $(LIB)
+$(LIB): $(OBJS)
$(AR) $(ARFLAGS) $@ $(OBJS)
+############################################################# ############
+# defines $(obj).depend target +include $(SRCTREE)/rules.mk
+sinclude $(obj).depend
+############################################################# ############ diff --git a/arch/arm/cpu/arm926ejs/orion5x/cpu.c b/arch/arm/cpu/arm926ejs/orion5x/cpu.c new file mode 100644 index 0000000..807174a --- /dev/null +++ b/arch/arm/cpu/arm926ejs/orion5x/cpu.c @@ -0,0 +1,271 @@ +/*
- Copyright (C) 2010 Albert ARIBAUD albert.aribaud@free.fr
- Based on original Kirkwood support which is
- (C) Copyright 2009
- Marvell Semiconductor <www.marvell.com>
- Written-by: Prafulla Wadaskar prafulla@marvell.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., 51 Franklin Street, Fifth Floor, Boston,
- MA 02110-1301 USA
- */
+#include <common.h> +#include <netdev.h> +#include <asm/cache.h> +#include <u-boot/md5.h> +#include <asm/arch/orion5x.h> +#include <hush.h>
+#define BUFLEN 16
+void reset_cpu(unsigned long ignored) +{
struct orion5x_cpu_registers *cpureg =
(struct orion5x_cpu_registers *)ORION5X_CPU_REG_BASE;
writel(readl(&cpureg->rstoutn_mask) | (1 << 2),
&cpureg->rstoutn_mask);
writel(readl(&cpureg->sys_soft_rst) | 1,
&cpureg->sys_soft_rst);
while (1)
;
+}
+/*
- Window Size
- Used with the Base register to set the address window
size and location.
- Must be programmed from LSB to MSB as sequence of ones followed by
- sequence of zeros. The number of ones specifies the size
of the window in
- 64 KByte granularity (e.g., a value of 0x00FF specifies
256 = 16 MByte).
- NOTE: A value of 0x0 specifies 64-KByte size.
- */
+unsigned int orion5x_winctrl_calcsize(unsigned int sizeval) +{
int i;
unsigned int j = 0;
u32 val = sizeval >> 1;
for (i = 0; val > 0x10000; i++) {
j |= (1 << i);
val = val >> 1;
}
return 0x0000ffff & j;
+}
+/*
- orion5x_config_adr_windows - Configure address Windows
- There are 8 address windows supported by Orion5x Soc to
addess different
- devices. Each window can be configured for size, BAR and
remap addr
- Below configuration is standard for most of the cases
- If remap function not used, remap_lo must be set as base
- Reference Documentation:
- Mbus-L to Mbus Bridge Registers Configuration.
- (Sec 25.1 and 25.3 of Datasheet)
- */
+int orion5x_config_adr_windows(void) +{
struct orion5x_win_registers *winregs =
(struct orion5x_win_registers *)ORION5X_CPU_WIN_BASE;
/* Window 0: PCIE MEM address space */
writel(ORION5X_CPU_WIN_CTRL_DATA(ORION5X_DEFSZ_PCIE_MEM,
ORION5X_TARGET_PCIE, ORION5X_ATTR_PCIE_MEM,
ORION5X_WIN_ENABLE), &winregs[0].ctrl);
writel(ORION5X_DEFADR_PCIE_MEM, &winregs[0].base);
writel(ORION5X_DEFADR_PCIE_MEM_REMAP_LO, &winregs[0].remap_lo);
writel(ORION5X_DEFADR_PCIE_MEM_REMAP_HI, &winregs[0].remap_hi);
/* Window 1: PCIE IO address space */
writel(ORION5X_CPU_WIN_CTRL_DATA(ORION5X_DEFSZ_PCIE_IO,
ORION5X_TARGET_PCIE, ORION5X_ATTR_PCIE_IO,
ORION5X_WIN_ENABLE), &winregs[1].ctrl);
writel(ORION5X_DEFADR_PCIE_IO, &winregs[1].base);
writel(ORION5X_DEFADR_PCIE_IO_REMAP_LO, &winregs[1].remap_lo);
writel(ORION5X_DEFADR_PCIE_IO_REMAP_HI, &winregs[1].remap_hi);
/* Window 2: PCI MEM address space */
writel(ORION5X_CPU_WIN_CTRL_DATA(ORION5X_DEFSZ_PCI_MEM,
ORION5X_TARGET_PCI, ORION5X_ATTR_PCI_MEM,
ORION5X_WIN_ENABLE), &winregs[2].ctrl);
writel(ORION5X_DEFADR_PCI_MEM, &winregs[2].base);
/* Window 3: PCI IO address space */
writel(ORION5X_CPU_WIN_CTRL_DATA(ORION5X_DEFSZ_PCI_IO,
ORION5X_TARGET_PCI, ORION5X_ATTR_PCI_IO,
ORION5X_WIN_ENABLE), &winregs[3].ctrl);
writel(ORION5X_DEFADR_PCI_IO, &winregs[3].base);
/* Window 4: DEV_CS0 address space */
writel(ORION5X_CPU_WIN_CTRL_DATA(ORION5X_DEFSZ_DEV_CS0,
ORION5X_TARGET_DEVICE, ORION5X_ATTR_DEV_CS0,
ORION5X_WIN_ENABLE), &winregs[4].ctrl);
writel(ORION5X_DEFADR_DEV_CS0, &winregs[4].base);
/* Window 5: DEV_CS1 address space */
writel(ORION5X_CPU_WIN_CTRL_DATA(ORION5X_DEFSZ_DEV_CS1,
ORION5X_TARGET_DEVICE, ORION5X_ATTR_DEV_CS1,
ORION5X_WIN_ENABLE), &winregs[5].ctrl);
writel(ORION5X_DEFADR_DEV_CS1, &winregs[5].base);
/* Window 6: DEV_CS2 address space */
writel(ORION5X_CPU_WIN_CTRL_DATA(ORION5X_DEFSZ_DEV_CS2,
ORION5X_TARGET_DEVICE, ORION5X_ATTR_DEV_CS2,
ORION5X_WIN_ENABLE), &winregs[6].ctrl);
writel(ORION5X_DEFADR_DEV_CS2, &winregs[6].base);
/* Window 7: BOOT Memory address space */
writel(ORION5X_CPU_WIN_CTRL_DATA(ORION5X_DEFSZ_BOOTROM,
ORION5X_TARGET_DEVICE, ORION5X_ATTR_BOOTROM,
ORION5X_WIN_ENABLE), &winregs[7].ctrl);
writel(ORION5X_DEFADR_BOOTROM, &winregs[7].base);
return 0;
+}
+/*
- Orion5x identification is done through PCIE space.
- */
+u32 orion5x_device_id(void) +{
return readl(PCIE_DEV_ID_OFF) >> 16;
+}
+u32 orion5x_device_rev(void) +{
return readl(PCIE_DEV_REV_OFF) & 0xff;
+}
+#if defined(CONFIG_DISPLAY_CPUINFO)
+/* Display device and revision IDs.
- This function must cover all known device/revision
- combinations, not only the one for which u-boot is
- compiled; this way, one can identify actual HW in
- case of a mismatch.
- */
+int print_cpuinfo(void) +{
char dev_str[] = "0x0000";
char rev_str[] = "0x00";
char *dev_name = NULL;
char *rev_name = NULL;
u32 dev = orion5x_device_id();
u32 rev = orion5x_device_rev();
if (dev == MV88F5181_DEV_ID) {
dev_name = "MV88F5181";
if (rev == MV88F5181_REV_B1)
rev_name = "B1";
else if (rev == MV88F5181L_REV_A1) {
dev_name = "MV88F5181L";
rev_name = "A1";
} else if (rev == MV88F5181L_REV_A0) {
dev_name = "MV88F5181L";
rev_name = "A0";
}
} else if (dev == MV88F5182_DEV_ID) {
dev_name = "MV88F5182";
if (rev == MV88F5182_REV_A2)
rev_name = "A2";
} else if (dev == MV88F5281_DEV_ID) {
dev_name = "MV88F5281";
if (rev == MV88F5281_REV_D2)
rev_name = "D2";
else if (rev == MV88F5281_REV_D1)
rev_name = "D1";
else if (rev == MV88F5281_REV_D0)
rev_name = "D0";
} else if (dev == MV88F6183_DEV_ID) {
dev_name = "MV88F6183";
if (rev == MV88F6183_REV_B0)
rev_name = "B0";
}
if (dev_name == NULL) {
sprintf(dev_str, "0x%04x", dev);
dev_name = dev_str;
}
if (rev_name == NULL) {
sprintf(rev_str, "0x%02x", rev);
rev_name = rev_str;
}
printf("SoC: Orion5x %s-%s\n", dev_name, rev_name);
return 0;
+} +#endif /* CONFIG_DISPLAY_CPUINFO */
+#ifdef CONFIG_ARCH_CPU_INIT +int arch_cpu_init(void) +{
/* Enable and invalidate L2 cache in write through mode */
invalidate_l2_cache();
orion5x_config_adr_windows();
return 0;
+} +#endif /* CONFIG_ARCH_CPU_INIT */
+/*
- SOC specific misc init
- */
+#if defined(CONFIG_ARCH_MISC_INIT) +int arch_misc_init(void) +{
u32 temp;
/*CPU streaming & write allocate */
temp = readfr_extra_feature_reg();
temp &= ~(1 << 28); /* disable wr alloc */
writefr_extra_feature_reg(temp);
temp = readfr_extra_feature_reg();
temp &= ~(1 << 29); /* streaming disabled */
writefr_extra_feature_reg(temp);
/* L2Cache settings */
temp = readfr_extra_feature_reg();
/* Disable L2C pre fetch - Set bit 24 */
temp |= (1 << 24);
/* enable L2C - Set bit 22 */
temp |= (1 << 22);
writefr_extra_feature_reg(temp);
icache_enable();
/* Change reset vector to address 0x0 */
temp = get_cr();
set_cr(temp & ~CR_V);
/* Set CPIOs and MPPs - values provided by board
include file */
+/*
writel(ORION5X_MPP_BASE+0x00, ORION5X_MPP0_7);
writel(ORION5X_MPP_BASE+0x04, ORION5X_MPP8_15);
writel(ORION5X_MPP_BASE+0x50, ORION5X_MPP16_23);
writel(ORION5X_GPIO_BASE+0x04, ORION5X_GPIO_OUT_ENABLE);
+*/
return 0;
+} +#endif /* CONFIG_ARCH_MISC_INIT */ diff --git a/arch/arm/cpu/arm926ejs/orion5x/dram.c b/arch/arm/cpu/arm926ejs/orion5x/dram.c new file mode 100644 index 0000000..c719798 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/orion5x/dram.c @@ -0,0 +1,64 @@ +/*
- Copyright (C) 2010 Albert ARIBAUD albert.aribaud@free.fr
- Based on original Kirkwood support which is
- (C) Copyright 2009
- Marvell Semiconductor <www.marvell.com>
- Written-by: Prafulla Wadaskar prafulla@marvell.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., 51 Franklin Street, Fifth Floor, Boston,
- MA 02110-1301 USA
- */
+#include <common.h> +#include <config.h> +#include <asm/arch/orion5x.h>
+DECLARE_GLOBAL_DATA_PTR;
+/*
- orion5x_sdram_bar - reads SDRAM Base Address Register
- */
+u32 orion5x_sdram_bar(enum memory_bank bank) +{
struct orion5x_ddr_addr_decode_registers *winregs =
(struct orion5x_ddr_addr_decode_registers *)
ORION5X_CPU_WIN_BASE;
u32 result = 0;
u32 enable = 0x01 & winregs[bank].size;
if ((!enable) || (bank > BANK3))
return 0;
result = winregs[bank].base;
return result;
+}
+int dram_init(void) +{
int i;
for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
gd->bd->bi_dram[i].start = orion5x_sdram_bar(i);
gd->bd->bi_dram[i].size = get_ram_size(
(volatile long *) (gd->bd->bi_dram[i].start),
CONFIG_MAX_RAM_BANK_SIZE);
}
return 0;
+} diff --git a/arch/arm/cpu/arm926ejs/orion5x/lowlevel_init.S b/arch/arm/cpu/arm926ejs/orion5x/lowlevel_init.S new file mode 100644 index 0000000..b0e15f6 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/orion5x/lowlevel_init.S @@ -0,0 +1,293 @@ +/*
- Copyright (C) 2010 Albert ARIBAUD albert.aribaud@free.fr
- (C) Copyright 2009
- Marvell Semiconductor <www.marvell.com>
- Written-by: Prafulla Wadaskar prafulla@marvell.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., 51 Franklin Street, Fifth Floor, Boston,
- MA 02110-1301 USA
- */
+#include <config.h> +#include "asm/arch/orion5x.h"
+/*
- Configuration values for SDRAM access setup
- */
+#define SDRAM_CONFIG 0x3148400 +#define SDRAM_MODE 0x62 +#define SDRAM_CONTROL 0x4041000 +#define SDRAM_TIME_CTRL_LOW 0x11602220 +#define SDRAM_TIME_CTRL_HI 0x40c +#define SDRAM_OPEN_PAGE_EN 0x0 +/* DDR 1 2x 32M NANYA NT5DS16M16CS-6K ==> 64MB */ +#define SDRAM_BANK0_SIZE 0x3ff0001 +#define SDRAM_ADDR_CTRL 0x10
+#define SDRAM_OP_NOP 0x05 +#define SDRAM_OP_SETMODE 0x03
+#define SDRAM_PAD_CTRL_WR_EN 0x80000000 +#define SDRAM_PAD_CTRL_TUNE_EN 0x00010000 +#define SDRAM_PAD_CTRL_DRVN_MASK 0x0000003f +#define SDRAM_PAD_CTRL_DRVP_MASK 0x00000fc0
+/*
- For Guideline MEM-3 - Drive Strength value
- */
+#define DDR1_PAD_STRENGTH_DEFAULT 0x00001000 +#define SDRAM_PAD_CTRL_DRV_STR_MASK 0x00003000
+/*
- For Guideline MEM-4 - DQS Reference Delay Tuning
- */
+#define MSAR_ARMDDRCLCK_MASK 0x000000f0 +#define MSAR_ARMDDRCLCK_H_MASK 0x00000100
+#define MSAR_ARMDDRCLCK_333_167 0x00000000 +#define MSAR_ARMDDRCLCK_500_167 0x00000030 +#define MSAR_ARMDDRCLCK_667_167 0x00000060 +#define MSAR_ARMDDRCLCK_400_200_1 0x000001E0 +#define MSAR_ARMDDRCLCK_400_200 0x00000010 +#define MSAR_ARMDDRCLCK_600_200 0x00000050 +#define MSAR_ARMDDRCLCK_800_200 0x00000070
+#define FTDLL_DDR1_166MHZ 0x0047F001
+#define FTDLL_DDR1_200MHZ 0x0044D001
+/*
- Low-level init happens right after start.S has switched to SVC32,
- flushed and disabled caches and disabled MMU. We're still running
- from the boot chip select, so the first thing we should do is set
- up RAM for us to relocate into.
- */
+.globl lowlevel_init
+lowlevel_init:
/* Use 'r4 as the base for internal register accesses */
ldr r4, =ORION5X_REGS_PHY_BASE
/* move internal registers from the default 0xD0000000
* to their intended location, defined by SoC */
ldr r3, =0xD0000000
add r3, r3, #0x20000
str r4, [r3, #0x80]
/* Use R3 as the base for DRAM registers */
add r3, r4, #0x01000
/*DDR SDRAM Initialization Control */
ldr r6, =0x00000001
str r6, [r3, #0x480]
/* Use R3 as the base for PCI registers */
add r3, r4, #0x31000
/* Disable arbiter */
ldr r6, =0x00000030
str r6, [r3, #0xd00]
/* Use R3 as the base for DRAM registers */
add r3, r4, #0x01000
/* set all dram windows to 0 */
mov r6, #0
str r6, [r3, #0x504]
str r6, [r3, #0x50C]
str r6, [r3, #0x514]
str r6, [r3, #0x51C]
/* 1) Configure SDRAM */
ldr r6, =SDRAM_CONFIG
str r6, [r3, #0x400]
/* 2) Set SDRAM Control reg */
ldr r6, =SDRAM_CONTROL
str r6, [r3, #0x404]
/* 3) Write SDRAM address control register */
ldr r6, =SDRAM_ADDR_CTRL
str r6, [r3, #0x410]
/* 4) Write SDRAM bank 0 size register */
ldr r6, =SDRAM_BANK0_SIZE
str r6, [r3, #0x504]
/* keep other banks disabled */
/* 5) Write SDRAM open pages control register */
ldr r6, =SDRAM_OPEN_PAGE_EN
str r6, [r3, #0x414]
/* 6) Write SDRAM timing Low register */
ldr r6, =SDRAM_TIME_CTRL_LOW
str r6, [r3, #0x408]
/* 7) Write SDRAM timing High register */
ldr r6, =SDRAM_TIME_CTRL_HI
str r6, [r3, #0x40C]
/* 8) Write SDRAM mode register */
/* The CPU must not attempt to change the SDRAM Mode
register setting */
/* prior to DRAM controller completion of the DRAM
initialization */
/* sequence. To guarantee this restriction, it is
recommended that */
/* the CPU sets the SDRAM Operation register to NOP
command, performs */
/* read polling until the register is back in Normal
operation value, */
/* and then sets SDRAM Mode register to its new
value. */
/* 8.1 write 'nop' to SDRAM operation */
ldr r6, =SDRAM_OP_NOP
str r6, [r3, #0x418]
/* 8.2 poll SDRAM operation until back in 'normal' mode. */
+1:
ldr r6, [r3, #0x418]
cmp r6, #0
bne 1b
/* 8.3 Now its safe to write new value to SDRAM Mode
register */
ldr r6, =SDRAM_MODE
str r6, [r3, #0x41C]
/* 8.4 Set new mode */
ldr r6, =SDRAM_OP_SETMODE
str r6, [r3, #0x418]
/* 8.5 poll SDRAM operation until back in 'normal' mode. */
+2:
ldr r6, [r3, #0x418]
cmp r6, #0
bne 2b
/* DDR SDRAM Address/Control Pads Calibration */
ldr r6, [r3, #0x4C0]
/* Set Bit [31] to make the register writable */
orr r6, r6, #SDRAM_PAD_CTRL_WR_EN
str r6, [r3, #0x4C0]
bic r6, r6, #SDRAM_PAD_CTRL_WR_EN
bic r6, r6, #SDRAM_PAD_CTRL_TUNE_EN
bic r6, r6, #SDRAM_PAD_CTRL_DRVN_MASK
bic r6, r6, #SDRAM_PAD_CTRL_DRVP_MASK
/* Get the final N locked value of driving strength
[22:17] */
mov r1, r6
mov r1, r1, LSL #9
mov r1, r1, LSR #26 /* r1[5:0]<DrvN> =
r3[22:17]<LockN> */
orr r1, r1, r1, LSL #6 /* r1[11:6]<DrvP> =
r1[5:0]<DrvN> */
/* Write to both <DrvN> bits [5:0] and <DrvP> bits
[11:6] */
orr r6, r6, r1
str r6, [r3, #0x4C0]
/* DDR SDRAM Data Pads Calibration */
ldr r6, [r3, #0x4C4]
/* Set Bit [31] to make the register writable */
orr r6, r6, #SDRAM_PAD_CTRL_WR_EN
str r6, [r3, #0x4C4]
bic r6, r6, #SDRAM_PAD_CTRL_WR_EN
bic r6, r6, #SDRAM_PAD_CTRL_TUNE_EN
bic r6, r6, #SDRAM_PAD_CTRL_DRVN_MASK
bic r6, r6, #SDRAM_PAD_CTRL_DRVP_MASK
/* Get the final N locked value of driving strength
[22:17] */
mov r1, r6
mov r1, r1, LSL #9
mov r1, r1, LSR #26
orr r1, r1, r1, LSL #6 /* r1[5:0] = r3[22:17]<LockN> */
/* Write to both <DrvN> bits [5:0] and <DrvP> bits
[11:6] */
orr r6, r6, r1
str r6, [r3, #0x4C4]
/* Implement Guideline (GL# MEM-3) Drive Strength
Value */
/* Relevant for: 88F5181-A1/B0/B1 and 88F5281-A0/B0 */
ldr r1, =DDR1_PAD_STRENGTH_DEFAULT
/* Enable writes to DDR SDRAM Addr/Ctrl Pads
Calibration register */
ldr r6, [r3, #0x4C0]
orr r6, r6, #SDRAM_PAD_CTRL_WR_EN
str r6, [r3, #0x4C0]
/* Correct strength and disable writes again */
bic r6, r6, #SDRAM_PAD_CTRL_WR_EN
bic r6, r6, #SDRAM_PAD_CTRL_DRV_STR_MASK
orr r6, r6, r1
str r6, [r3, #0x4C0]
/* Enable writes to DDR SDRAM Data Pads Calibration register */
ldr r6, [r3, #0x4C4]
orr r6, r6, #SDRAM_PAD_CTRL_WR_EN
str r6, [r3, #0x4C4]
/* Correct strength and disable writes again */
bic r6, r6, #SDRAM_PAD_CTRL_DRV_STR_MASK
bic r6, r6, #SDRAM_PAD_CTRL_WR_EN
orr r6, r6, r1
str r6, [r3, #0x4C4]
/* Implement Guideline (GL# MEM-4) DQS Reference
Delay Tuning */
/* Relevant for: 88F5181-A1/B0/B1 and 88F5281-A0/B0 */
/* Get the "sample on reset" register for the DDR
frequancy */
ldr r3, =0x10000
ldr r6, [r3, #0x010]
ldr r1, =MSAR_ARMDDRCLCK_MASK
and r1, r6, r1
ldr r6, =FTDLL_DDR1_166MHZ
cmp r1, #MSAR_ARMDDRCLCK_333_167
beq 3f
cmp r1, #MSAR_ARMDDRCLCK_500_167
beq 3f
cmp r1, #MSAR_ARMDDRCLCK_667_167
beq 3f
ldr r6, =FTDLL_DDR1_200MHZ
cmp r1, #MSAR_ARMDDRCLCK_400_200_1
beq 3f
cmp r1, #MSAR_ARMDDRCLCK_400_200
beq 3f
cmp r1, #MSAR_ARMDDRCLCK_600_200
beq 3f
cmp r1, #MSAR_ARMDDRCLCK_800_200
beq 3f
ldr r6, =0
+3:
/* Use R3 as the base for DRAM registers */
add r3, r4, #0x01000
ldr r2, [r3, #0x484]
orr r2, r2, r6
str r2, [r3, #0x484]
/* Return to U-boot via saved link register */
mov pc, lr
diff --git a/arch/arm/cpu/arm926ejs/orion5x/timer.c b/arch/arm/cpu/arm926ejs/orion5x/timer.c new file mode 100644 index 0000000..115448f --- /dev/null +++ b/arch/arm/cpu/arm926ejs/orion5x/timer.c @@ -0,0 +1,181 @@ +/*
- Copyright (C) 2010 Albert ARIBAUD albert.aribaud@free.fr
- Based on original Kirkwood support which is
- Copyright (C) Marvell International Ltd. and its affiliates
- Written-by: Prafulla Wadaskar prafulla@marvell.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., 51 Franklin Street, Fifth Floor, Boston,
- MA 02110-1301 USA
- */
+#include <common.h> +#include <asm/arch/orion5x.h>
+#define UBOOT_CNTR 0 /* counter to use for uboot timer */
+/* Timer reload and current value registers */ +struct orion5x_tmr_val {
u32 reload; /* Timer reload reg */
u32 val; /* Timer value reg */
+};
+/* Timer registers */ +struct orion5x_tmr_registers {
u32 ctrl; /* Timer control reg */
u32 pad[3];
struct orion5x_tmr_val tmr[2];
u32 wdt_reload;
u32 wdt_val;
+};
+struct orion5x_tmr_registers *orion5x_tmr_regs =
(struct orion5x_tmr_registers *)ORION5X_TIMER_BASE;
+/*
- ARM Timers Registers Map
- */
+#define CNTMR_CTRL_REG (&orion5x_tmr_regs->ctrl) +#define CNTMR_RELOAD_REG(tmrnum) (&orion5x_tmr_regs->tmr[tmrnum].reload) +#define CNTMR_VAL_REG(tmrnum) (&orion5x_tmr_regs->tmr[tmrnum].val)
+/*
- ARM Timers Control Register
- CPU_TIMERS_CTRL_REG (CTCR)
- */
+#define CTCR_ARM_TIMER_EN_OFFS(cntr) (cntr * 2) +#define CTCR_ARM_TIMER_EN_MASK(cntr) (1 << CTCR_ARM_TIMER_EN_OFFS) +#define CTCR_ARM_TIMER_EN(cntr) (1 << CTCR_ARM_TIMER_EN_OFFS(cntr)) +#define CTCR_ARM_TIMER_DIS(cntr) (0 << CTCR_ARM_TIMER_EN_OFFS(cntr))
+#define CTCR_ARM_TIMER_AUTO_OFFS(cntr) ((cntr * 2) + 1) +#define CTCR_ARM_TIMER_AUTO_MASK(cntr) (1 << 1) +#define CTCR_ARM_TIMER_AUTO_EN(cntr) (1 << CTCR_ARM_TIMER_AUTO_OFFS(cntr)) +#define CTCR_ARM_TIMER_AUTO_DIS(cntr) (0 << CTCR_ARM_TIMER_AUTO_OFFS(cntr))
+/*
- ARM Timer\Watchdog Reload Register
- CNTMR_RELOAD_REG (TRR)
- */
+#define TRG_ARM_TIMER_REL_OFFS 0 +#define TRG_ARM_TIMER_REL_MASK 0xffffffff
+/*
- ARM Timer\Watchdog Register
- CNTMR_VAL_REG (TVRG)
- */
+#define TVR_ARM_TIMER_OFFS 0 +#define TVR_ARM_TIMER_MASK 0xffffffff +#define TVR_ARM_TIMER_MAX 0xffffffff +#define TIMER_LOAD_VAL 0xffffffff
+static inline ulong read_timer(void) +{
return readl(CNTMR_VAL_REG(UBOOT_CNTR))
/ (CONFIG_SYS_TCLK / 1000);
+}
+static ulong timestamp; +static ulong lastdec;
+void reset_timer_masked(void) +{
/* reset time */
lastdec = read_timer();
timestamp = 0;
+}
+ulong get_timer_masked(void) +{
ulong now = read_timer();
if (lastdec >= now) {
/* normal mode */
timestamp += lastdec - now;
} else {
/* we have an overflow ... */
timestamp += lastdec +
(TIMER_LOAD_VAL / (CONFIG_SYS_TCLK /
1000)) - now;
}
lastdec = now;
return timestamp;
+}
+void reset_timer(void) +{
reset_timer_masked();
+}
+ulong get_timer(ulong base) +{
return get_timer_masked() - base;
+}
+void set_timer(ulong t) +{
timestamp = t;
+}
+static inline ulong uboot_cntr_val(void) +{
return readl(CNTMR_VAL_REG(UBOOT_CNTR));
+}
+void __udelay(unsigned long usec) +{
uint current;
ulong delayticks;
current = uboot_cntr_val();
delayticks = (usec * (CONFIG_SYS_TCLK / 1000000));
if (current < delayticks) {
delayticks -= current;
while (uboot_cntr_val() < current)
;
while ((TIMER_LOAD_VAL - delayticks) < uboot_cntr_val())
;
} else {
while (uboot_cntr_val() > (current - delayticks))
;
}
+}
+/*
- init the counter
- */
+int timer_init(void) +{
unsigned int cntmrctrl;
/* load value into timer */
writel(TIMER_LOAD_VAL, CNTMR_RELOAD_REG(UBOOT_CNTR));
writel(TIMER_LOAD_VAL, CNTMR_VAL_REG(UBOOT_CNTR));
/* enable timer in auto reload mode */
cntmrctrl = readl(CNTMR_CTRL_REG);
cntmrctrl |= CTCR_ARM_TIMER_EN(UBOOT_CNTR);
cntmrctrl |= CTCR_ARM_TIMER_AUTO_EN(UBOOT_CNTR);
writel(cntmrctrl, CNTMR_CTRL_REG);
/* init the timestamp and lastdec value */
reset_timer_masked();
return 0;
+} diff --git a/arch/arm/include/asm/arch-orion5x/cpu.h b/arch/arm/include/asm/arch-orion5x/cpu.h new file mode 100644 index 0000000..22e2dd3 --- /dev/null +++ b/arch/arm/include/asm/arch-orion5x/cpu.h @@ -0,0 +1,203 @@ +/*
- Copyright (C) 2010 Albert ARIBAUD albert.aribaud@free.fr
- Based on original Kirorion5x_ood support which is
- (C) Copyright 2009
- Marvell Semiconductor <www.marvell.com>
- Written-by: Prafulla Wadaskar prafulla@marvell.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., 51 Franklin Street, Fifth Floor, Boston,
- MA 02110-1301 USA
- */
+#ifndef _ORION5X_CPU_H +#define _ORION5X_CPU_H
+#include <asm/system.h>
+#ifndef __ASSEMBLY__
+#define ORION5X_CPU_WIN_CTRL_DATA(size, target, attr, en) (en | (target << 4) \
| (attr << 8) |
(orion5x_winctrl_calcsize(size) << 16))
+#define ORION5XGBE_PORT_SERIAL_CONTROL1_REG(_x) \
((_x ? ORION5X_EGIGA0_BASE :
ORION5X_EGIGA1_BASE) + 0x44c)
+enum memory_bank {
BANK0,
BANK1,
BANK2,
BANK3
+};
+enum orion5x_cpu_winen {
ORION5X_WIN_DISABLE,
ORION5X_WIN_ENABLE
+};
+enum orion5x_cpu_target {
ORION5X_TARGET_DRAM = 0,
ORION5X_TARGET_DEVICE = 1,
ORION5X_TARGET_PCI = 3,
ORION5X_TARGET_PCIE = 4,
ORION5X_TARGET_SASRAM = 9
+};
+enum orion5x_cpu_attrib {
ORION5X_ATTR_DRAM_CS0 = 0x0e,
ORION5X_ATTR_DRAM_CS1 = 0x0d,
ORION5X_ATTR_DRAM_CS2 = 0x0b,
ORION5X_ATTR_DRAM_CS3 = 0x07,
ORION5X_ATTR_PCI_MEM = 0x59,
ORION5X_ATTR_PCI_IO = 0x51,
ORION5X_ATTR_PCIE_MEM = 0x59,
ORION5X_ATTR_PCIE_IO = 0x51,
ORION5X_ATTR_SASRAM = 0x00,
ORION5X_ATTR_DEV_CS0 = 0x1e,
ORION5X_ATTR_DEV_CS1 = 0x1d,
ORION5X_ATTR_DEV_CS2 = 0x1b,
ORION5X_ATTR_BOOTROM = 0x0f
+};
+/*
- Default Device Address MAP BAR values
- */
+#define ORION5X_DEFADR_PCIE_MEM 0x90000000 +#define ORION5X_DEFADR_PCIE_MEM_REMAP_LO 0x90000000 +#define ORION5X_DEFADR_PCIE_MEM_REMAP_HI 0 +#define ORION5X_DEFSZ_PCIE_MEM (128*1024*1024)
+#define ORION5X_DEFADR_PCIE_IO 0xf0000000 +#define ORION5X_DEFADR_PCIE_IO_REMAP_LO 0x90000000 +#define ORION5X_DEFADR_PCIE_IO_REMAP_HI 0 +#define ORION5X_DEFSZ_PCIE_IO (64*1024)
+#define ORION5X_DEFADR_PCI_MEM 0x98000000 +#define ORION5X_DEFSZ_PCI_MEM (128*1024*1024)
+#define ORION5X_DEFADR_PCI_IO 0xf0100000 +#define ORION5X_DEFSZ_PCI_IO (64*1024)
+#define ORION5X_DEFADR_DEV_CS0 0xfa000000 +#define ORION5X_DEFSZ_DEV_CS0 (2*1024*1024)
+#define ORION5X_DEFADR_DEV_CS1 0xf8000000 +#define ORION5X_DEFSZ_DEV_CS1 (32*1024*1024)
+#define ORION5X_DEFADR_DEV_CS2 0xfa800000 +#define ORION5X_DEFSZ_DEV_CS2 (1*1024*1024)
+#define ORION5X_DEFADR_BOOTROM 0xFFF80000 +#define ORION5X_DEFSZ_BOOTROM (512*1024)
+/*
- PCIE registers are used for SoC device ID and revision
- */
+#define PCIE_DEV_ID_OFF (ORION5X_REG_PCIE_BASE + 0x0000) +#define PCIE_DEV_REV_OFF (ORION5X_REG_PCIE_BASE + 0x0008)
+/*
- The following definitions are intended for identifying
- the real device and revision on which u-boot is running
- even if it was compiled only for a specific one. Thus,
- these constants must not be considered chip-specific.
- */
+/* Orion-1 (88F5181) and Orion-VoIP (88F5181L) */ +#define MV88F5181_DEV_ID 0x5181 +#define MV88F5181_REV_B1 3 +#define MV88F5181L_REV_A0 8 +#define MV88F5181L_REV_A1 9 +/* Orion-NAS (88F5182) */ +#define MV88F5182_DEV_ID 0x5182 +#define MV88F5182_REV_A2 2 +/* Orion-2 (88F5281) */ +#define MV88F5281_DEV_ID 0x5281 +#define MV88F5281_REV_D0 4 +#define MV88F5281_REV_D1 5 +#define MV88F5281_REV_D2 6 +/* Orion-1-90 (88F6183) */ +#define MV88F6183_DEV_ID 0x6183 +#define MV88F6183_REV_B0 3
+/*
- read feroceon core extra feature register
- using co-proc instruction
- */
+static inline unsigned int readfr_extra_feature_reg(void) +{
unsigned int val;
asm volatile ("mrc p15, 1, %0, c15, c1, 0 @ readfr exfr" : "=r"
(val) : : "cc");
return val;
+}
+/*
- write feroceon core extra feature register
- using co-proc instruction
- */
+static inline void writefr_extra_feature_reg(unsigned int val) +{
asm volatile ("mcr p15, 1, %0, c15, c1, 0 @ writefr
exfr" : : "r"
(val) : "cc");
isb();
+}
+/*
- AHB to Mbus Bridge Registers
- Source: 88F5182 User Manual, Appendix A, section A.4
- Note: only windows 0 and 1 have remap capability.
- */
+struct orion5x_win_registers {
u32 ctrl;
u32 base;
u32 remap_lo;
u32 remap_hi;
+};
+/*
- CPU control and status Registers
- Source: 88F5182 User Manual, Appendix A, section A.4
- */
+struct orion5x_cpu_registers {
u32 config; /*0x20100 */
u32 ctrl_stat; /*0x20104 */
u32 rstoutn_mask; /* 0x20108 */
u32 sys_soft_rst; /* 0x2010C */
u32 ahb_mbus_cause_irq; /* 0x20110 */
u32 ahb_mbus_mask_irq; /* 0x20114 */
+};
+/*
- DDR SDRAM Controller Address Decode Registers
- Source: 88F5182 User Manual, Appendix A, section A.5.1
- */
+struct orion5x_ddr_addr_decode_registers {
u32 base;
u32 size;
+};
+/*
- functions
- */
+void reset_cpu(unsigned long ignored); +u32 orion5x_device_id(void); +u32 orion5x_device_rev(void); +unsigned int orion5x_winctrl_calcsize(unsigned int sizeval); +#endif /* __ASSEMBLY__ */ +#endif /* _ORION5X_CPU_H */ diff --git a/arch/arm/include/asm/arch-orion5x/mv88f5182.h b/arch/arm/include/asm/arch-orion5x/mv88f5182.h new file mode 100644 index 0000000..86ba08d --- /dev/null +++ b/arch/arm/include/asm/arch-orion5x/mv88f5182.h @@ -0,0 +1,40 @@ +/*
- Copyright (C) 2010 Albert ARIBAUD albert.aribaud@free.fr
- Based on original Kirkwood 88F6182 support which is
- (C) Copyright 2009
- Marvell Semiconductor <www.marvell.com>
- Written-by: Prafulla Wadaskar prafulla@marvell.com
- Header file for Feroceon CPU core 88F5182 SOC.
- 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., 51 Franklin Street, Fifth Floor, Boston,
- MA 02110-1301 USA
- */
+#ifndef _CONFIG_88F5182_H +#define _CONFIG_88F5182_H
+/* SOC specific definitions */ +#define F88F5182_REGS_PHYS_BASE 0xf1000000 +#define ORION5X_REGS_PHY_BASE F88F5182_REGS_PHYS_BASE
+/* TCLK Core Clock defination */ +#define CONFIG_SYS_TCLK 166000000 /* 166MHz */
+#endif /* _CONFIG_88F5182_H */ diff --git a/arch/arm/include/asm/arch-orion5x/orion5x.h b/arch/arm/include/asm/arch-orion5x/orion5x.h new file mode 100644 index 0000000..4008c84 --- /dev/null +++ b/arch/arm/include/asm/arch-orion5x/orion5x.h @@ -0,0 +1,69 @@ +/*
- Copyright (C) 2010 Albert ARIBAUD albert.aribaud@free.fr
- Based on original Kirkwood support which is
- (C) Copyright 2009
- Marvell Semiconductor <www.marvell.com>
- Written-by: Prafulla Wadaskar prafulla@marvell.com
- Header file for Marvell's Orion SoC with Feroceon CPU core.
- 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., 51 Franklin Street, Fifth Floor, Boston,
- MA 02110-1301 USA
- */
+#ifndef _ASM_ARCH_ORION5X_H +#define _ASM_ARCH_ORION5X_H
+#ifndef __ASSEMBLY__ +#include <asm/types.h> +#include <asm/io.h> +#endif /* __ASSEMBLY__ */
+#if defined(CONFIG_FEROCEON) +#include <asm/arch/cpu.h>
+/* SOC specific definations */ +#define ORION5X_REGISTER(x) (ORION5X_REGS_PHY_BASE + x)
+/* Documented registers */ +#define ORION5X_TWSI_BASE (ORION5X_REGISTER(0x11000)) +#define ORION5X_UART0_BASE (ORION5X_REGISTER(0x12000)) +#define ORION5X_UART1_BASE (ORION5X_REGISTER(0x12100)) +#define ORION5X_MPP_BASE (ORION5X_REGISTER(0x10000)) +#define ORION5X_GPIO_BASE (ORION5X_REGISTER(0x10100)) +#define ORION5X_CPU_WIN_BASE (ORION5X_REGISTER(0x20000)) +#define ORION5X_CPU_REG_BASE (ORION5X_REGISTER(0x20100)) +#define ORION5X_TIMER_BASE (ORION5X_REGISTER(0x20300)) +#define ORION5X_REG_PCI_BASE (ORION5X_REGISTER(0x30000)) +#define ORION5X_REG_PCIE_BASE (ORION5X_REGISTER(0x40000)) +#define ORION5X_USB20_PORT0_BASE (ORION5X_REGISTER(0x50000)) +#define ORION5X_USB20_PORT1_BASE (ORION5X_REGISTER(0xA0000)) +#define ORION5X_EGIGA_BASE (ORION5X_REGISTER(0x72000))
+#define CONFIG_MAX_RAM_BANK_SIZE (64*1024*1024)
+/* include here SoC variants. 5181, 5281, 6183 should go here when
- adding support for them, and this comment should then be
updated. */ +#if defined(CONFIG_88F5182) +#include <asm/arch/mv88f5182.h> +#else +#error "SOC Name not defined" +#endif +#endif /* CONFIG_FEROCEON */
+#endif /* _ASM_ARCH_ORION5X_H */
1.6.4.4
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
participants (2)
-
Albert Aribaud
-
Prafulla Wadaskar