ARMv8/ls2085a_emu: Add LS2085A emulator and simulator board support
LS2085A is an ARMv8 implementation. This adds board support for emulator
and simulator:
Two DDR controllers
UART2 is used as the console
IFC timing is tightened for speedy booting
Support DDR3 and DDR4 as separated targets
Management Complex (MC) is enabled
Support for GIC 500 (based on GICv3 arch)
Signed-off-by: York Sun <yorksun@freescale.com>
Signed-off-by: Arnab Basu <arnab.basu@freescale.com>
Signed-off-by: J. German Rivera <German.Rivera@freescale.com>
Signed-off-by: Bhupesh Sharma <bhupesh.sharma@freescale.com>
diff --git a/board/freescale/ls2085a/Makefile b/board/freescale/ls2085a/Makefile
new file mode 100644
index 0000000..701b35c
--- /dev/null
+++ b/board/freescale/ls2085a/Makefile
@@ -0,0 +1,8 @@
+#
+# Copyright 2014 Freescale Semiconductor
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-y += ls2085a.o
+obj-y += ddr.o
diff --git a/board/freescale/ls2085a/README b/board/freescale/ls2085a/README
new file mode 100644
index 0000000..b7023e1
--- /dev/null
+++ b/board/freescale/ls2085a/README
@@ -0,0 +1,16 @@
+Freescale ls2085a_emu
+
+This is a emulator target with limited peripherals.
+
+Memory map from core's view
+
+0x00_0000_0000 .. 0x00_000F_FFFF Boot Rom
+0x00_0100_0000 .. 0x00_0FFF_FFFF CCSR
+0x00_1800_0000 .. 0x00_181F_FFFF OCRAM
+0x00_3000_0000 .. 0x00_3FFF_FFFF IFC region #1
+0x00_8000_0000 .. 0x00_FFFF_FFFF DDR region #1
+0x05_1000_0000 .. 0x05_FFFF_FFFF IFC region #2
+0x80_8000_0000 .. 0xFF_FFFF_FFFF DDR region #2
+
+Other addresses are either reserved, or not used directly by u-boot.
+This list should be updated when more addresses are used.
diff --git a/board/freescale/ls2085a/ddr.c b/board/freescale/ls2085a/ddr.c
new file mode 100644
index 0000000..257bc16
--- /dev/null
+++ b/board/freescale/ls2085a/ddr.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <fsl_ddr_sdram.h>
+#include <fsl_ddr_dimm_params.h>
+#include "ddr.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void fsl_ddr_board_options(memctl_options_t *popts,
+ dimm_params_t *pdimm,
+ unsigned int ctrl_num)
+{
+ const struct board_specific_parameters *pbsp, *pbsp_highest = NULL;
+ ulong ddr_freq;
+
+ if (ctrl_num > 3) {
+ printf("Not supported controller number %d\n", ctrl_num);
+ return;
+ }
+ if (!pdimm->n_ranks)
+ return;
+
+ /*
+ * we use identical timing for all slots. If needed, change the code
+ * to pbsp = rdimms[ctrl_num] or pbsp = udimms[ctrl_num];
+ */
+ if (popts->registered_dimm_en)
+ pbsp = rdimms[0];
+ else
+ pbsp = udimms[0];
+
+
+ /* Get clk_adjust, wrlvl_start, wrlvl_ctl, according to the board ddr
+ * freqency and n_banks specified in board_specific_parameters table.
+ */
+ ddr_freq = get_ddr_freq(0) / 1000000;
+ while (pbsp->datarate_mhz_high) {
+ if (pbsp->n_ranks == pdimm->n_ranks &&
+ (pdimm->rank_density >> 30) >= pbsp->rank_gb) {
+ if (ddr_freq <= pbsp->datarate_mhz_high) {
+ popts->clk_adjust = pbsp->clk_adjust;
+ popts->wrlvl_start = pbsp->wrlvl_start;
+ popts->wrlvl_ctl_2 = pbsp->wrlvl_ctl_2;
+ popts->wrlvl_ctl_3 = pbsp->wrlvl_ctl_3;
+ goto found;
+ }
+ pbsp_highest = pbsp;
+ }
+ pbsp++;
+ }
+
+ if (pbsp_highest) {
+ printf("Error: board specific timing not found for data rate %lu MT/s\n"
+ "Trying to use the highest speed (%u) parameters\n",
+ ddr_freq, pbsp_highest->datarate_mhz_high);
+ popts->clk_adjust = pbsp_highest->clk_adjust;
+ popts->wrlvl_start = pbsp_highest->wrlvl_start;
+ popts->wrlvl_ctl_2 = pbsp->wrlvl_ctl_2;
+ popts->wrlvl_ctl_3 = pbsp->wrlvl_ctl_3;
+ } else {
+ panic("DIMM is not supported by this board");
+ }
+found:
+ debug("Found timing match: n_ranks %d, data rate %d, rank_gb %d\n"
+ "\tclk_adjust %d, wrlvl_start %d, wrlvl_ctrl_2 0x%x, wrlvl_ctrl_3 0x%x\n",
+ pbsp->n_ranks, pbsp->datarate_mhz_high, pbsp->rank_gb,
+ pbsp->clk_adjust, pbsp->wrlvl_start, pbsp->wrlvl_ctl_2,
+ pbsp->wrlvl_ctl_3);
+
+ /*
+ * Factors to consider for half-strength driver enable:
+ * - number of DIMMs installed
+ */
+ popts->half_strength_driver_enable = 1;
+ /*
+ * Write leveling override
+ */
+ popts->wrlvl_override = 1;
+ popts->wrlvl_sample = 0xf;
+
+ /*
+ * Rtt and Rtt_WR override
+ */
+ popts->rtt_override = 0;
+
+ /* Enable ZQ calibration */
+ popts->zq_en = 1;
+
+#ifdef CONFIG_SYS_FSL_DDR4
+ popts->ddr_cdr1 = DDR_CDR1_DHC_EN | DDR_CDR1_ODT(DDR_CDR_ODT_80ohm);
+ popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_80ohm) |
+ DDR_CDR2_VREF_OVRD(70); /* Vref = 70% */
+#else
+ /* DHC_EN =1, ODT = 75 Ohm */
+ popts->ddr_cdr1 = DDR_CDR1_DHC_EN | DDR_CDR1_ODT(DDR_CDR_ODT_75ohm);
+ popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_75ohm);
+#endif
+}
+
+#ifdef CONFIG_SYS_DDR_RAW_TIMING
+dimm_params_t ddr_raw_timing = {
+ .n_ranks = 2,
+ .rank_density = 1073741824u,
+ .capacity = 2147483648,
+ .primary_sdram_width = 64,
+ .ec_sdram_width = 0,
+ .registered_dimm = 0,
+ .mirrored_dimm = 0,
+ .n_row_addr = 14,
+ .n_col_addr = 10,
+ .n_banks_per_sdram_device = 8,
+ .edc_config = 0,
+ .burst_lengths_bitmask = 0x0c,
+
+ .tckmin_x_ps = 937,
+ .caslat_x = 0x6FC << 4, /* 14,13,11,10,9,8,7,6 */
+ .taa_ps = 13090,
+ .twr_ps = 15000,
+ .trcd_ps = 13090,
+ .trrd_ps = 5000,
+ .trp_ps = 13090,
+ .tras_ps = 33000,
+ .trc_ps = 46090,
+ .trfc_ps = 160000,
+ .twtr_ps = 7500,
+ .trtp_ps = 7500,
+ .refresh_rate_ps = 7800000,
+ .tfaw_ps = 25000,
+};
+
+int fsl_ddr_get_dimm_params(dimm_params_t *pdimm,
+ unsigned int controller_number,
+ unsigned int dimm_number)
+{
+ const char dimm_model[] = "Fixed DDR on board";
+
+ if (((controller_number == 0) && (dimm_number == 0)) ||
+ ((controller_number == 1) && (dimm_number == 0))) {
+ memcpy(pdimm, &ddr_raw_timing, sizeof(dimm_params_t));
+ memset(pdimm->mpart, 0, sizeof(pdimm->mpart));
+ memcpy(pdimm->mpart, dimm_model, sizeof(dimm_model) - 1);
+ }
+
+ return 0;
+}
+#endif
+phys_size_t initdram(int board_type)
+{
+ phys_size_t dram_size;
+
+ puts("Initializing DDR....");
+
+ puts("using SPD\n");
+ dram_size = fsl_ddr_sdram();
+
+ return dram_size;
+}
+
+void dram_init_banksize(void)
+{
+ gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
+ if (gd->ram_size > CONFIG_SYS_LS2_DDR_BLOCK1_SIZE) {
+ gd->bd->bi_dram[0].size = CONFIG_SYS_LS2_DDR_BLOCK1_SIZE;
+ gd->bd->bi_dram[1].start = CONFIG_SYS_DDR_BLOCK2_BASE;
+ gd->bd->bi_dram[1].size = gd->ram_size -
+ CONFIG_SYS_LS2_DDR_BLOCK1_SIZE;
+ } else {
+ gd->bd->bi_dram[0].size = gd->ram_size;
+ }
+}
diff --git a/board/freescale/ls2085a/ddr.h b/board/freescale/ls2085a/ddr.h
new file mode 100644
index 0000000..77f6aaf
--- /dev/null
+++ b/board/freescale/ls2085a/ddr.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __DDR_H__
+#define __DDR_H__
+struct board_specific_parameters {
+ u32 n_ranks;
+ u32 datarate_mhz_high;
+ u32 rank_gb;
+ u32 clk_adjust;
+ u32 wrlvl_start;
+ u32 wrlvl_ctl_2;
+ u32 wrlvl_ctl_3;
+};
+
+/*
+ * These tables contain all valid speeds we want to override with board
+ * specific parameters. datarate_mhz_high values need to be in ascending order
+ * for each n_ranks group.
+ */
+
+static const struct board_specific_parameters udimm0[] = {
+ /*
+ * memory controller 0
+ * num| hi| rank| clk| wrlvl | wrlvl | wrlvl
+ * ranks| mhz| GB |adjst| start | ctl2 | ctl3
+ */
+ {2, 2140, 0, 4, 4, 0x0, 0x0},
+ {1, 2140, 0, 4, 4, 0x0, 0x0},
+ {}
+};
+
+static const struct board_specific_parameters rdimm0[] = {
+ /*
+ * memory controller 0
+ * num| hi| rank| clk| wrlvl | wrlvl | wrlvl
+ * ranks| mhz| GB |adjst| start | ctl2 | ctl3
+ */
+ {4, 2140, 0, 5, 4, 0x0, 0x0},
+ {2, 2140, 0, 5, 4, 0x0, 0x0},
+ {1, 2140, 0, 4, 4, 0x0, 0x0},
+ {}
+};
+
+static const struct board_specific_parameters *udimms[] = {
+ udimm0,
+};
+
+static const struct board_specific_parameters *rdimms[] = {
+ rdimm0,
+};
+
+
+#endif
diff --git a/board/freescale/ls2085a/ls2085a.c b/board/freescale/ls2085a/ls2085a.c
new file mode 100644
index 0000000..a18db1d
--- /dev/null
+++ b/board/freescale/ls2085a/ls2085a.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2014 Freescale Semiconductor
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+#include <common.h>
+#include <malloc.h>
+#include <errno.h>
+#include <netdev.h>
+#include <fsl_ifc.h>
+#include <fsl_ddr.h>
+#include <asm/io.h>
+#include <fdt_support.h>
+#include <libfdt.h>
+#include <fsl_mc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int board_init(void)
+{
+ init_final_memctl_regs();
+ return 0;
+}
+
+int board_early_init_f(void)
+{
+ init_early_memctl_regs(); /* tighten IFC timing */
+
+ return 0;
+}
+
+int dram_init(void)
+{
+ printf("DRAM: ");
+ gd->ram_size = initdram(0);
+
+ return 0;
+}
+
+int timer_init(void)
+{
+ u32 __iomem *cntcr = (u32 *)CONFIG_SYS_FSL_TIMER_ADDR;
+ u32 __iomem *cltbenr = (u32 *)CONFIG_SYS_FSL_PMU_CLTBENR;
+
+ out_le32(cltbenr, 0x1); /* enable cluster0 timebase */
+ out_le32(cntcr, 0x1); /* enable clock for timer */
+
+ return 0;
+}
+
+/*
+ * Board specific reset that is system reset.
+ */
+void reset_cpu(ulong addr)
+{
+}
+
+int board_eth_init(bd_t *bis)
+{
+ int error = 0;
+
+#ifdef CONFIG_SMC91111
+ error = smc91111_initialize(0, CONFIG_SMC91111_BASE);
+#endif
+
+#ifdef CONFIG_FSL_MC_ENET
+ error = cpu_eth_init(bis);
+#endif
+ return error;
+}
+
+#ifdef CONFIG_FSL_MC_ENET
+void fdt_fixup_board_enet(void *fdt)
+{
+ int offset;
+
+ offset = fdt_path_offset(fdt, "/fsl,dprc@0");
+ if (get_mc_boot_status() == 0)
+ fdt_status_okay(fdt, offset);
+ else
+ fdt_status_fail(fdt, offset);
+}
+#endif
+
+#ifdef CONFIG_OF_BOARD_SETUP
+void ft_board_setup(void *blob, bd_t *bd)
+{
+ phys_addr_t base;
+ phys_size_t size;
+
+ /* limit the memory size to bank 1 until Linux can handle 40-bit PA */
+ base = getenv_bootm_low();
+ size = getenv_bootm_size();
+ fdt_fixup_memory(blob, (u64)base, (u64)size);
+
+#ifdef CONFIG_FSL_MC_ENET
+ fdt_fixup_board_enet(blob);
+#endif
+}
+#endif