summaryrefslogtreecommitdiff
path: root/arch/arm/mvebu-common
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mvebu-common')
-rw-r--r--arch/arm/mvebu-common/Makefile10
-rw-r--r--arch/arm/mvebu-common/dram.c143
-rw-r--r--arch/arm/mvebu-common/timer.c157
3 files changed, 310 insertions, 0 deletions
diff --git a/arch/arm/mvebu-common/Makefile b/arch/arm/mvebu-common/Makefile
new file mode 100644
index 0000000..4d20d2c
--- /dev/null
+++ b/arch/arm/mvebu-common/Makefile
@@ -0,0 +1,10 @@
+#
+# (C) Copyright 2009
+# Marvell Semiconductor <www.marvell.com>
+# Written-by: Prafulla Wadaskar <prafulla@marvell.com>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-y = dram.o
+obj-y += timer.o
diff --git a/arch/arm/mvebu-common/dram.c b/arch/arm/mvebu-common/dram.c
new file mode 100644
index 0000000..bb5989b
--- /dev/null
+++ b/arch/arm/mvebu-common/dram.c
@@ -0,0 +1,143 @@
+/*
+ * (C) Copyright 2009
+ * Marvell Semiconductor <www.marvell.com>
+ * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <config.h>
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/kirkwood.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct kw_sdram_bank {
+ u32 win_bar;
+ u32 win_sz;
+};
+
+struct kw_sdram_addr_dec {
+ struct kw_sdram_bank sdram_bank[4];
+};
+
+#define KW_REG_CPUCS_WIN_ENABLE (1 << 0)
+#define KW_REG_CPUCS_WIN_WR_PROTECT (1 << 1)
+#define KW_REG_CPUCS_WIN_WIN0_CS(x) (((x) & 0x3) << 2)
+#define KW_REG_CPUCS_WIN_SIZE(x) (((x) & 0xff) << 24)
+
+/*
+ * kw_sdram_bar - reads SDRAM Base Address Register
+ */
+u32 kw_sdram_bar(enum memory_bank bank)
+{
+ struct kw_sdram_addr_dec *base =
+ (struct kw_sdram_addr_dec *)KW_REGISTER(0x1500);
+ u32 result = 0;
+ u32 enable = 0x01 & readl(&base->sdram_bank[bank].win_sz);
+
+ if ((!enable) || (bank > BANK3))
+ return 0;
+
+ result = readl(&base->sdram_bank[bank].win_bar);
+ return result;
+}
+
+/*
+ * kw_sdram_bs_set - writes SDRAM Bank size
+ */
+static void kw_sdram_bs_set(enum memory_bank bank, u32 size)
+{
+ struct kw_sdram_addr_dec *base =
+ (struct kw_sdram_addr_dec *)KW_REGISTER(0x1500);
+ /* Read current register value */
+ u32 reg = readl(&base->sdram_bank[bank].win_sz);
+
+ /* Clear window size */
+ reg &= ~KW_REG_CPUCS_WIN_SIZE(0xFF);
+
+ /* Set new window size */
+ reg |= KW_REG_CPUCS_WIN_SIZE((size - 1) >> 24);
+
+ writel(reg, &base->sdram_bank[bank].win_sz);
+}
+
+/*
+ * kw_sdram_bs - reads SDRAM Bank size
+ */
+u32 kw_sdram_bs(enum memory_bank bank)
+{
+ struct kw_sdram_addr_dec *base =
+ (struct kw_sdram_addr_dec *)KW_REGISTER(0x1500);
+ u32 result = 0;
+ u32 enable = 0x01 & readl(&base->sdram_bank[bank].win_sz);
+
+ if ((!enable) || (bank > BANK3))
+ return 0;
+ result = 0xff000000 & readl(&base->sdram_bank[bank].win_sz);
+ result += 0x01000000;
+ return result;
+}
+
+void kw_sdram_size_adjust(enum memory_bank bank)
+{
+ u32 size;
+
+ /* probe currently equipped RAM size */
+ size = get_ram_size((void *)kw_sdram_bar(bank), kw_sdram_bs(bank));
+
+ /* adjust SDRAM window size accordingly */
+ kw_sdram_bs_set(bank, size);
+}
+
+#ifndef CONFIG_SYS_BOARD_DRAM_INIT
+int dram_init(void)
+{
+ int i;
+
+ gd->ram_size = 0;
+ for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+ gd->bd->bi_dram[i].start = kw_sdram_bar(i);
+ gd->bd->bi_dram[i].size = kw_sdram_bs(i);
+ /*
+ * It is assumed that all memory banks are consecutive
+ * and without gaps.
+ * If the gap is found, ram_size will be reported for
+ * consecutive memory only
+ */
+ if (gd->bd->bi_dram[i].start != gd->ram_size)
+ break;
+
+ /*
+ * Don't report more than 3GiB of SDRAM, otherwise there is no
+ * address space left for the internal registers etc.
+ */
+ if ((gd->ram_size + gd->bd->bi_dram[i].size != 0) &&
+ (gd->ram_size + gd->bd->bi_dram[i].size <= (3 << 30)))
+ gd->ram_size += gd->bd->bi_dram[i].size;
+
+ }
+
+ for (; i < CONFIG_NR_DRAM_BANKS; i++) {
+ /* If above loop terminated prematurely, we need to set
+ * remaining banks' start address & size as 0. Otherwise other
+ * u-boot functions and Linux kernel gets wrong values which
+ * could result in crash */
+ gd->bd->bi_dram[i].start = 0;
+ gd->bd->bi_dram[i].size = 0;
+ }
+
+ return 0;
+}
+
+/*
+ * If this function is not defined here,
+ * board.c alters dram bank zero configuration defined above.
+ */
+void dram_init_banksize(void)
+{
+ dram_init();
+}
+#endif /* CONFIG_SYS_BOARD_DRAM_INIT */
diff --git a/arch/arm/mvebu-common/timer.c b/arch/arm/mvebu-common/timer.c
new file mode 100644
index 0000000..a08f4a1
--- /dev/null
+++ b/arch/arm/mvebu-common/timer.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/kirkwood.h>
+
+#define UBOOT_CNTR 0 /* counter to use for uboot timer */
+
+/* Timer reload and current value registers */
+struct kwtmr_val {
+ u32 reload; /* Timer reload reg */
+ u32 val; /* Timer value reg */
+};
+
+/* Timer registers */
+struct kwtmr_registers {
+ u32 ctrl; /* Timer control reg */
+ u32 pad[3];
+ struct kwtmr_val tmr[2];
+ u32 wdt_reload;
+ u32 wdt_val;
+};
+
+struct kwtmr_registers *kwtmr_regs = (struct kwtmr_registers *)KW_TIMER_BASE;
+
+/*
+ * ARM Timers Registers Map
+ */
+#define CNTMR_CTRL_REG &kwtmr_regs->ctrl
+#define CNTMR_RELOAD_REG(tmrnum) &kwtmr_regs->tmr[tmrnum].reload
+#define CNTMR_VAL_REG(tmrnum) &kwtmr_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
+
+#define READ_TIMER (readl(CNTMR_VAL_REG(UBOOT_CNTR)) / \
+ (CONFIG_SYS_TCLK / 1000))
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define timestamp gd->arch.tbl
+#define lastdec gd->arch.lastinc
+
+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;
+}
+
+ulong get_timer(ulong base)
+{
+ return get_timer_masked() - base;
+}
+
+void __udelay(unsigned long usec)
+{
+ uint current;
+ ulong delayticks;
+
+ current = readl(CNTMR_VAL_REG(UBOOT_CNTR));
+ delayticks = (usec * (CONFIG_SYS_TCLK / 1000000));
+
+ if (current < delayticks) {
+ delayticks -= current;
+ while (readl(CNTMR_VAL_REG(UBOOT_CNTR)) < current) ;
+ while ((TIMER_LOAD_VAL - delayticks) <
+ readl(CNTMR_VAL_REG(UBOOT_CNTR))) ;
+ } else {
+ while (readl(CNTMR_VAL_REG(UBOOT_CNTR)) >
+ (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 */
+ lastdec = READ_TIMER;
+ timestamp = 0;
+
+ return 0;
+}
+
+/*
+ * 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)
+{
+ return (ulong)CONFIG_SYS_HZ;
+}