aboutsummaryrefslogtreecommitdiffstats
path: root/roms/u-boot/board/solidrun
diff options
context:
space:
mode:
Diffstat (limited to 'roms/u-boot/board/solidrun')
-rw-r--r--roms/u-boot/board/solidrun/clearfog/Kconfig62
-rw-r--r--roms/u-boot/board/solidrun/clearfog/MAINTAINERS7
-rw-r--r--roms/u-boot/board/solidrun/clearfog/Makefile5
-rw-r--r--roms/u-boot/board/solidrun/clearfog/README74
-rw-r--r--roms/u-boot/board/solidrun/clearfog/clearfog.c262
-rw-r--r--roms/u-boot/board/solidrun/common/Makefile5
-rw-r--r--roms/u-boot/board/solidrun/common/tlv_data.c103
-rw-r--r--roms/u-boot/board/solidrun/common/tlv_data.h18
-rw-r--r--roms/u-boot/board/solidrun/mx6cuboxi/Kconfig12
-rw-r--r--roms/u-boot/board/solidrun/mx6cuboxi/MAINTAINERS7
-rw-r--r--roms/u-boot/board/solidrun/mx6cuboxi/Makefile7
-rw-r--r--roms/u-boot/board/solidrun/mx6cuboxi/README21
-rw-r--r--roms/u-boot/board/solidrun/mx6cuboxi/mx6cuboxi.c773
13 files changed, 1356 insertions, 0 deletions
diff --git a/roms/u-boot/board/solidrun/clearfog/Kconfig b/roms/u-boot/board/solidrun/clearfog/Kconfig
new file mode 100644
index 000000000..cf9525809
--- /dev/null
+++ b/roms/u-boot/board/solidrun/clearfog/Kconfig
@@ -0,0 +1,62 @@
+menu "ClearFog configuration"
+ depends on TARGET_CLEARFOG
+
+config TARGET_CLEARFOG_BASE
+ bool "Use ClearFog Base static configuration"
+ help
+ Use the ClearFog Base as the static configuration instead of the
+ default which uses the ClearFog Pro.
+
+ Runtime board detection is always attempted and used if available. The
+ static configuration is used as a fallback in cases where runtime
+ detection is disabled, is not available in hardware, or otherwise fails.
+
+ Only newer revisions of the ClearFog product line support runtime
+ detection via additional EEPROM hardware. This option enables selecting
+ the Base variant for older hardware revisions.
+
+config CLEARFOG_CON3_SATA
+ bool "Use CON3 slot in SATA mode"
+ help
+ Use the CON3 port with SATA protocol instead of the default PCIe.
+ The ClearFog port allows usage of either mSATA or miniPCIe
+ modules, but the desired protocol must be configured at build
+ time since it affects the SerDes topology layout.
+
+config CLEARFOG_CON2_SATA
+ bool "Use CON2 slot in SATA mode"
+ depends on !TARGET_CLEARFOG_BASE
+ help
+ Use the CON2 port with SATA protocol instead of the default PCIe.
+ The ClearFog port allows usage of either mSATA or miniPCIe
+ modules, but the desired protocol must be configured at build
+ time since it affects the SerDes topology layout.
+
+config CLEARFOG_SFP_25GB
+ bool "Enable 2.5 Gbps mode for SFP"
+ help
+ Set the SFP module connection to support 2.5 Gbps transfer speed for the
+ SGMII connection (requires a supporting SFP). By default, transfer speed
+ of 1.25 Gbps is used, suitable for a more common 1 Gbps SFP module.
+
+config ENV_SIZE
+ hex "Environment Size"
+ default 0x10000
+
+config ENV_OFFSET
+ hex "Environment offset"
+ default 0xF0000
+
+config ENV_SECT_SIZE
+ hex "Environment Sector-Size"
+ # Use SPI flash erase block size of 4 KiB
+ default 0x1000 if MVEBU_SPL_BOOT_DEVICE_SPI || MVEBU_SPL_BOOT_DEVICE_SATA
+ # Use optimistic 64 KiB erase block, will vary between actual media
+ default 0x10000 if MVEBU_SPL_BOOT_DEVICE_MMC || MVEBU_SPL_BOOT_DEVICE_UART
+
+config SYS_SPI_U_BOOT_OFFS
+ hex "address of u-boot payload in SPI flash"
+ default 0x20000
+ depends on MVEBU_SPL_BOOT_DEVICE_SPI
+
+endmenu
diff --git a/roms/u-boot/board/solidrun/clearfog/MAINTAINERS b/roms/u-boot/board/solidrun/clearfog/MAINTAINERS
new file mode 100644
index 000000000..6646d9620
--- /dev/null
+++ b/roms/u-boot/board/solidrun/clearfog/MAINTAINERS
@@ -0,0 +1,7 @@
+CLEARFOG BOARD
+M: Stefan Roese <sr@denx.de>
+S: Maintained
+F: board/soldrun/clearfog/
+F: include/configs/clearfog.h
+F: configs/clearfog_defconfig
+F: configs/clearfog_gt_8k_defconfig
diff --git a/roms/u-boot/board/solidrun/clearfog/Makefile b/roms/u-boot/board/solidrun/clearfog/Makefile
new file mode 100644
index 000000000..5cfda3283
--- /dev/null
+++ b/roms/u-boot/board/solidrun/clearfog/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2015 Stefan Roese <sr@denx.de>
+
+obj-y := clearfog.o
diff --git a/roms/u-boot/board/solidrun/clearfog/README b/roms/u-boot/board/solidrun/clearfog/README
new file mode 100644
index 000000000..9375be849
--- /dev/null
+++ b/roms/u-boot/board/solidrun/clearfog/README
@@ -0,0 +1,74 @@
+Update from original Marvell U-Boot to mainline U-Boot:
+-------------------------------------------------------
+
+Generate the U-Boot image with these commands:
+
+$ make clearfog_defconfig
+$ make
+
+The resulting image including the SPL binary with the
+full DDR setup is "u-boot-spl.kwb".
+
+Now all you need to do is copy this image on a SD card.
+For example with this command:
+
+$ sudo dd if=u-boot-spl.kwb of=/dev/sdX bs=512 seek=1
+
+Please use the correct device node for your setup instead
+of "/dev/sdX" here!
+
+Install U-Boot on eMMC:
+-----------------------
+
+To make SPL load the main U-Boot image from the eMMC boot partition enable
+eMMC boot acknowledgement and boot partition with the following U-Boot
+command:
+
+ mmc partconf 0 1 1 0
+
+Install U-Boot on eMMC boot partition from Linux running on Clearfog:
+
+ echo 0 > /sys/block/mmcblk0boot0/force_ro
+ dd if=u-boot-spl.kwb of=/dev/mmcblk0boot0
+
+Note that the SD card is not accessible when the Clearfog SOM has eMMC.
+Consider initial boot from UART (see below).
+
+Install U-Boot on SATA:
+-----------------------
+
+When loading the main U-Boot image from raw SATA sector, set
+CONFIG_SPL_SATA_RAW_U_BOOT_SECTOR to 0x141.
+
+Boot selection:
+---------------
+
+Before powering up the board, boot selection should be done via the SW1 dip
+switch (0: OFF, 1: ON):
+
+ - SPI: 00010
+ - SD/eMMC: 00111
+ - M.2 SSD: 11100
+ - UART: 01001 [1]
+
+[1]: According to SolidRun's manual, 11110 should be used for UART booting on
+ the ClearFog 'Pro' variant.
+ However, this doesn't work (anymore) at least on Rev. 2.1 (but '01001' as
+ mentionend for the 'Base' variant does).
+
+Boot from UART:
+---------------
+
+Connect the on-board micro-USB (CF Pro: CON11, CF Base: CON5)
+to your host.
+
+Set the SW1 DIP switches to UART boot (see above).
+
+Run the following command to initiate U-Boot download:
+
+ ./tools/kwboot -b u-boot-spl.kwb /dev/ttyUSBX
+
+Use the correct UART device node for /dev/ttyUSBX.
+
+When download finishes start your favorite terminal emulator
+on /dev/ttyUSBX.
diff --git a/roms/u-boot/board/solidrun/clearfog/clearfog.c b/roms/u-boot/board/solidrun/clearfog/clearfog.c
new file mode 100644
index 000000000..c920cf8d6
--- /dev/null
+++ b/roms/u-boot/board/solidrun/clearfog/clearfog.c
@@ -0,0 +1,262 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015 Stefan Roese <sr@denx.de>
+ */
+
+#include <common.h>
+#include <env.h>
+#include <i2c.h>
+#include <init.h>
+#include <miiphy.h>
+#include <net.h>
+#include <netdev.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include "../common/tlv_data.h"
+
+#include "../drivers/ddr/marvell/a38x/ddr3_init.h"
+#include <../serdes/a38x/high_speed_env_spec.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Those values and defines are taken from the Marvell U-Boot version
+ * "u-boot-2013.01-15t1-clearfog"
+ */
+#define BOARD_GPP_OUT_ENA_LOW 0xffffffff
+#define BOARD_GPP_OUT_ENA_MID 0xffffffff
+
+#define BOARD_GPP_OUT_VAL_LOW 0x0
+#define BOARD_GPP_OUT_VAL_MID 0x0
+#define BOARD_GPP_POL_LOW 0x0
+#define BOARD_GPP_POL_MID 0x0
+
+static struct tlv_data cf_tlv_data;
+
+static void cf_read_tlv_data(void)
+{
+ static bool read_once;
+
+ if (read_once)
+ return;
+ read_once = true;
+
+ read_tlv_data(&cf_tlv_data);
+}
+
+/* The starting board_serdes_map reflects original Clearfog Pro usage */
+static struct serdes_map board_serdes_map[] = {
+ {SATA0, SERDES_SPEED_3_GBPS, SERDES_DEFAULT_MODE, 0, 0},
+ {SGMII1, SERDES_SPEED_1_25_GBPS, SERDES_DEFAULT_MODE, 0, 0},
+ {PEX1, SERDES_SPEED_5_GBPS, PEX_ROOT_COMPLEX_X1, 0, 0},
+ {USB3_HOST1, SERDES_SPEED_5_GBPS, SERDES_DEFAULT_MODE, 0, 0},
+ {PEX2, SERDES_SPEED_5_GBPS, PEX_ROOT_COMPLEX_X1, 0, 0},
+ {SGMII2, SERDES_SPEED_1_25_GBPS, SERDES_DEFAULT_MODE, 0, 0},
+};
+
+void config_cfbase_serdes_map(void)
+{
+ board_serdes_map[4].serdes_type = USB3_HOST0;
+ board_serdes_map[4].serdes_speed = SERDES_SPEED_5_GBPS;
+ board_serdes_map[4].serdes_mode = SERDES_DEFAULT_MODE;
+}
+
+int hws_board_topology_load(struct serdes_map **serdes_map_array, u8 *count)
+{
+ cf_read_tlv_data();
+
+ /* Apply build configuration options before runtime configuration */
+ if (IS_ENABLED(CONFIG_CLEARFOG_SFP_25GB))
+ board_serdes_map[5].serdes_speed = SERDES_SPEED_3_125_GBPS;
+
+ if (IS_ENABLED(CONFIG_CLEARFOG_CON2_SATA)) {
+ board_serdes_map[4].serdes_type = SATA2;
+ board_serdes_map[4].serdes_speed = SERDES_SPEED_3_GBPS;
+ board_serdes_map[4].serdes_mode = SERDES_DEFAULT_MODE;
+ board_serdes_map[4].swap_rx = 1;
+ }
+
+ if (IS_ENABLED(CONFIG_CLEARFOG_CON3_SATA)) {
+ board_serdes_map[2].serdes_type = SATA1;
+ board_serdes_map[2].serdes_speed = SERDES_SPEED_3_GBPS;
+ board_serdes_map[2].serdes_mode = SERDES_DEFAULT_MODE;
+ board_serdes_map[2].swap_rx = 1;
+ }
+
+ /* Apply runtime detection changes */
+ if (sr_product_is(&cf_tlv_data, "Clearfog GTR")) {
+ board_serdes_map[0].serdes_type = PEX0;
+ board_serdes_map[0].serdes_speed = SERDES_SPEED_5_GBPS;
+ board_serdes_map[0].serdes_mode = PEX_ROOT_COMPLEX_X1;
+ } else if (sr_product_is(&cf_tlv_data, "Clearfog Pro")) {
+ /* handle recognized product as noop, no adjustment required */
+ } else if (sr_product_is(&cf_tlv_data, "Clearfog Base")) {
+ config_cfbase_serdes_map();
+ } else {
+ /*
+ * Fallback to static default. EEPROM TLV support is not
+ * enabled, runtime detection failed, hardware support is not
+ * present, EEPROM is corrupt, or an unrecognized product name
+ * is present.
+ */
+ if (IS_ENABLED(CONFIG_SPL_CMD_TLV_EEPROM))
+ puts("EEPROM TLV detection failed: ");
+ puts("Using static config for ");
+ if (IS_ENABLED(CONFIG_TARGET_CLEARFOG_BASE)) {
+ puts("Clearfog Base.\n");
+ config_cfbase_serdes_map();
+ } else {
+ puts("Clearfog Pro.\n");
+ }
+ }
+
+ *serdes_map_array = board_serdes_map;
+ *count = ARRAY_SIZE(board_serdes_map);
+ return 0;
+}
+
+/*
+ * Define the DDR layout / topology here in the board file. This will
+ * be used by the DDR3 init code in the SPL U-Boot version to configure
+ * the DDR3 controller.
+ */
+static struct mv_ddr_topology_map board_topology_map = {
+ DEBUG_LEVEL_ERROR,
+ 0x1, /* active interfaces */
+ /* cs_mask, mirror, dqs_swap, ck_swap X PUPs */
+ { { { {0x1, 0, 0, 0},
+ {0x1, 0, 0, 0},
+ {0x1, 0, 0, 0},
+ {0x1, 0, 0, 0},
+ {0x1, 0, 0, 0} },
+ SPEED_BIN_DDR_1600K, /* speed_bin */
+ MV_DDR_DEV_WIDTH_16BIT, /* memory_width */
+ MV_DDR_DIE_CAP_4GBIT, /* mem_size */
+ MV_DDR_FREQ_800, /* frequency */
+ 0, 0, /* cas_wl cas_l */
+ MV_DDR_TEMP_LOW, /* temperature */
+ MV_DDR_TIM_DEFAULT} }, /* timing */
+ BUS_MASK_32BIT, /* Busses mask */
+ MV_DDR_CFG_DEFAULT, /* ddr configuration data source */
+ NOT_COMBINED, /* ddr twin-die combined */
+ { {0} }, /* raw spd data */
+ {0}, /* timing parameters */
+ { {0} }, /* electrical configuration */
+ {0,}, /* electrical parameters */
+ 0x3, /* clock enable mask */
+};
+
+struct mv_ddr_topology_map *mv_ddr_topology_map_get(void)
+{
+ struct if_params *ifp = &board_topology_map.interface_params[0];
+
+ cf_read_tlv_data();
+
+ switch (cf_tlv_data.ram_size) {
+ case 4:
+ default:
+ ifp->memory_size = MV_DDR_DIE_CAP_4GBIT;
+ break;
+ case 8:
+ ifp->memory_size = MV_DDR_DIE_CAP_8GBIT;
+ break;
+ }
+
+ /* Return the board topology as defined in the board code */
+ return &board_topology_map;
+}
+
+int board_early_init_f(void)
+{
+ /* Configure MPP */
+ writel(0x11111111, MVEBU_MPP_BASE + 0x00);
+ writel(0x11111111, MVEBU_MPP_BASE + 0x04);
+ writel(0x10400011, MVEBU_MPP_BASE + 0x08);
+ writel(0x22043333, MVEBU_MPP_BASE + 0x0c);
+ writel(0x44400002, MVEBU_MPP_BASE + 0x10);
+ writel(0x41144004, MVEBU_MPP_BASE + 0x14);
+ writel(0x40333333, MVEBU_MPP_BASE + 0x18);
+ writel(0x00004444, MVEBU_MPP_BASE + 0x1c);
+
+ /* Set GPP Out value */
+ writel(BOARD_GPP_OUT_VAL_LOW, MVEBU_GPIO0_BASE + 0x00);
+ writel(BOARD_GPP_OUT_VAL_MID, MVEBU_GPIO1_BASE + 0x00);
+
+ /* Set GPP Polarity */
+ writel(BOARD_GPP_POL_LOW, MVEBU_GPIO0_BASE + 0x0c);
+ writel(BOARD_GPP_POL_MID, MVEBU_GPIO1_BASE + 0x0c);
+
+ /* Set GPP Out Enable */
+ writel(BOARD_GPP_OUT_ENA_LOW, MVEBU_GPIO0_BASE + 0x04);
+ writel(BOARD_GPP_OUT_ENA_MID, MVEBU_GPIO1_BASE + 0x04);
+
+ return 0;
+}
+
+int board_init(void)
+{
+ /* Address of boot parameters */
+ gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
+
+ /* Toggle GPIO41 to reset onboard switch and phy */
+ clrbits_le32(MVEBU_GPIO1_BASE + 0x0, BIT(9));
+ clrbits_le32(MVEBU_GPIO1_BASE + 0x4, BIT(9));
+ /* GPIO 19 on ClearFog rev 2.1 controls the uSOM onboard phy reset */
+ clrbits_le32(MVEBU_GPIO0_BASE + 0x0, BIT(19));
+ clrbits_le32(MVEBU_GPIO0_BASE + 0x4, BIT(19));
+ mdelay(1);
+ setbits_le32(MVEBU_GPIO1_BASE + 0x0, BIT(9));
+ setbits_le32(MVEBU_GPIO0_BASE + 0x0, BIT(19));
+ mdelay(10);
+
+ return 0;
+}
+
+int checkboard(void)
+{
+ char *board = "Clearfog Pro";
+ if (IS_ENABLED(CONFIG_TARGET_CLEARFOG_BASE))
+ board = "Clearfog Base";
+
+ cf_read_tlv_data();
+ if (strlen(cf_tlv_data.tlv_product_name[0]) > 0)
+ board = cf_tlv_data.tlv_product_name[0];
+
+ printf("Board: SolidRun %s", board);
+ if (strlen(cf_tlv_data.tlv_product_name[1]) > 0)
+ printf(", %s", cf_tlv_data.tlv_product_name[1]);
+ puts("\n");
+
+ return 0;
+}
+
+int board_eth_init(struct bd_info *bis)
+{
+ cpu_eth_init(bis); /* Built in controller(s) come first */
+ return pci_eth_init(bis);
+}
+
+int board_late_init(void)
+{
+ if (env_get("fdtfile"))
+ return 0;
+
+ cf_read_tlv_data();
+
+ if (sr_product_is(&cf_tlv_data, "Clearfog Base"))
+ env_set("fdtfile", "armada-388-clearfog-base.dtb");
+ else if (sr_product_is(&cf_tlv_data, "Clearfog GTR S4"))
+ env_set("fdtfile", "armada-385-clearfog-gtr-s4.dtb");
+ else if (sr_product_is(&cf_tlv_data, "Clearfog GTR L8"))
+ env_set("fdtfile", "armada-385-clearfog-gtr-l8.dtb");
+ else if (IS_ENABLED(CONFIG_TARGET_CLEARFOG_BASE))
+ env_set("fdtfile", "armada-388-clearfog-base.dtb");
+ else
+ env_set("fdtfile", "armada-388-clearfog-pro.dtb");
+
+ return 0;
+}
diff --git a/roms/u-boot/board/solidrun/common/Makefile b/roms/u-boot/board/solidrun/common/Makefile
new file mode 100644
index 000000000..a72ac1b7b
--- /dev/null
+++ b/roms/u-boot/board/solidrun/common/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) SolidRun
+
+obj-$(CONFIG_TARGET_CLEARFOG) += tlv_data.o
diff --git a/roms/u-boot/board/solidrun/common/tlv_data.c b/roms/u-boot/board/solidrun/common/tlv_data.c
new file mode 100644
index 000000000..11d6e4a13
--- /dev/null
+++ b/roms/u-boot/board/solidrun/common/tlv_data.c
@@ -0,0 +1,103 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2020 SolidRun
+ */
+
+#include <common.h>
+#include <compiler.h>
+#include <tlv_eeprom.h>
+#include "tlv_data.h"
+
+#define SR_TLV_CODE_RAM_SIZE 0x81
+
+static void store_product_name(struct tlvinfo_tlv *tlv_entry,
+ struct tlv_data *td)
+{
+ int len;
+ char *dest;
+
+ if (strlen(td->tlv_product_name[0]) == 0)
+ dest = td->tlv_product_name[0];
+ else if (strlen(td->tlv_product_name[1]) == 0)
+ dest = td->tlv_product_name[1];
+ else
+ return;
+
+ len = min_t(unsigned int, tlv_entry->length,
+ sizeof(td->tlv_product_name[0]) - 1);
+ memcpy(dest, tlv_entry->value, len);
+}
+
+static void parse_tlv_vendor_ext(struct tlvinfo_tlv *tlv_entry,
+ struct tlv_data *td)
+{
+ u8 *val = tlv_entry->value;
+ u32 pen; /* IANA Private Enterprise Numbers */
+
+ if (tlv_entry->length < 5) /* 4 bytes PEN + at least 1 byte type */
+ return;
+
+ /* PEN is big endian */
+ pen = (val[0] << 24) | (val[1] << 16) | (val[2] << 8) | val[3];
+ /* Not a real PEN */
+ if (pen != 0xffffffff)
+ return;
+
+ if (val[4] != SR_TLV_CODE_RAM_SIZE)
+ return;
+ if (tlv_entry->length != 6)
+ return;
+ td->ram_size = val[5];
+}
+
+static void parse_tlv_data(u8 *eeprom, struct tlvinfo_header *hdr,
+ struct tlvinfo_tlv *entry, struct tlv_data *td)
+{
+ unsigned int tlv_offset, tlv_len;
+
+ tlv_offset = sizeof(struct tlvinfo_header);
+ tlv_len = sizeof(struct tlvinfo_header) + be16_to_cpu(hdr->totallen);
+ while (tlv_offset < tlv_len) {
+ entry = (struct tlvinfo_tlv *)&eeprom[tlv_offset];
+
+ switch (entry->type) {
+ case TLV_CODE_PRODUCT_NAME:
+ store_product_name(entry, td);
+ break;
+ case TLV_CODE_VENDOR_EXT:
+ parse_tlv_vendor_ext(entry, td);
+ break;
+ default:
+ break;
+ }
+
+ tlv_offset += sizeof(struct tlvinfo_tlv) + entry->length;
+ }
+}
+
+void read_tlv_data(struct tlv_data *td)
+{
+ u8 eeprom_data[TLV_TOTAL_LEN_MAX];
+ struct tlvinfo_header *tlv_hdr;
+ struct tlvinfo_tlv *tlv_entry;
+ int ret, i;
+
+ for (i = 0; i < 2; i++) {
+ ret = read_tlvinfo_tlv_eeprom(eeprom_data, &tlv_hdr,
+ &tlv_entry, i);
+ if (ret < 0)
+ continue;
+ parse_tlv_data(eeprom_data, tlv_hdr, tlv_entry, td);
+ }
+}
+
+bool sr_product_is(const struct tlv_data *td, const char *product)
+{
+ /* Allow prefix sub-string match */
+ if (strncmp(td->tlv_product_name[0], product, strlen(product)) == 0)
+ return true;
+ if (strncmp(td->tlv_product_name[1], product, strlen(product)) == 0)
+ return true;
+
+ return false;
+}
diff --git a/roms/u-boot/board/solidrun/common/tlv_data.h b/roms/u-boot/board/solidrun/common/tlv_data.h
new file mode 100644
index 000000000..a1432e4b8
--- /dev/null
+++ b/roms/u-boot/board/solidrun/common/tlv_data.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2020 SolidRun
+ */
+
+#ifndef __BOARD_SR_COMMON_H_
+#define __BOARD_SR_COMMON_H_
+
+struct tlv_data {
+ /* Store product name of both SOM and carrier */
+ char tlv_product_name[2][32];
+ unsigned int ram_size;
+};
+
+void read_tlv_data(struct tlv_data *td);
+bool sr_product_is(const struct tlv_data *td, const char *product);
+
+#endif /* __BOARD_SR_COMMON_H_ */
diff --git a/roms/u-boot/board/solidrun/mx6cuboxi/Kconfig b/roms/u-boot/board/solidrun/mx6cuboxi/Kconfig
new file mode 100644
index 000000000..741c1754f
--- /dev/null
+++ b/roms/u-boot/board/solidrun/mx6cuboxi/Kconfig
@@ -0,0 +1,12 @@
+if TARGET_MX6CUBOXI
+
+config SYS_BOARD
+ default "mx6cuboxi"
+
+config SYS_VENDOR
+ default "solidrun"
+
+config SYS_CONFIG_NAME
+ default "mx6cuboxi"
+
+endif
diff --git a/roms/u-boot/board/solidrun/mx6cuboxi/MAINTAINERS b/roms/u-boot/board/solidrun/mx6cuboxi/MAINTAINERS
new file mode 100644
index 000000000..055852166
--- /dev/null
+++ b/roms/u-boot/board/solidrun/mx6cuboxi/MAINTAINERS
@@ -0,0 +1,7 @@
+MX6CUBOXI BOARD
+M: Baruch Siach <baruch@tkos.co.il>
+M: Fabio Estevam <festevam@gmail.com>
+S: Maintained
+F: board/solidrun/mx6cuboxi/
+F: include/configs/mx6cuboxi.h
+F: configs/mx6cuboxi_defconfig
diff --git a/roms/u-boot/board/solidrun/mx6cuboxi/Makefile b/roms/u-boot/board/solidrun/mx6cuboxi/Makefile
new file mode 100644
index 000000000..6e5becbd2
--- /dev/null
+++ b/roms/u-boot/board/solidrun/mx6cuboxi/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2007, Guennadi Liakhovetski <lg@denx.de>
+#
+# (C) Copyright 2011 Freescale Semiconductor, Inc.
+
+obj-y := mx6cuboxi.o
diff --git a/roms/u-boot/board/solidrun/mx6cuboxi/README b/roms/u-boot/board/solidrun/mx6cuboxi/README
new file mode 100644
index 000000000..5d0a45d92
--- /dev/null
+++ b/roms/u-boot/board/solidrun/mx6cuboxi/README
@@ -0,0 +1,21 @@
+How to use U-Boot on Solid-run mx6 Hummingboard and Cubox-i
+-----------------------------------------------------------
+
+- Build U-Boot for Hummingboard/Cubox-i:
+
+$ make mrproper
+$ make mx6cuboxi_defconfig
+$ make
+
+This will generate the SPL image called SPL and the u-boot.img.
+
+- Flash the SPL image into the SD card:
+
+sudo dd if=SPL of=/dev/mmcblk0 bs=1k seek=1; sync
+
+- Flash the u-boot.img image into the SD card:
+
+sudo dd if=u-boot.img of=/dev/mmcblk0 bs=1k seek=69; sync
+
+- Insert the SD card in the board, power it up and U-Boot messages should
+come up.
diff --git a/roms/u-boot/board/solidrun/mx6cuboxi/mx6cuboxi.c b/roms/u-boot/board/solidrun/mx6cuboxi/mx6cuboxi.c
new file mode 100644
index 000000000..3eadc38f6
--- /dev/null
+++ b/roms/u-boot/board/solidrun/mx6cuboxi/mx6cuboxi.c
@@ -0,0 +1,773 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * Author: Fabio Estevam <fabio.estevam@freescale.com>
+ *
+ * Copyright (C) 2013 Jon Nettleton <jon.nettleton@gmail.com>
+ *
+ * Based on SPL code from Solidrun tree, which is:
+ * Author: Tungyi Lin <tungyilin1127@gmail.com>
+ *
+ * Derived from EDM_CF_IMX6 code by TechNexion,Inc
+ * Ported to SolidRun microSOM by Rabeeh Khoury <rabeeh@solid-run.com>
+ */
+
+#include <common.h>
+#include <image.h>
+#include <init.h>
+#include <log.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/iomux.h>
+#include <asm/arch/mx6-pins.h>
+#include <asm/arch/mxc_hdmi.h>
+#include <env.h>
+#include <asm/global_data.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <asm/gpio.h>
+#include <asm/mach-imx/iomux-v3.h>
+#include <asm/mach-imx/sata.h>
+#include <asm/mach-imx/video.h>
+#include <mmc.h>
+#include <fsl_esdhc_imx.h>
+#include <malloc.h>
+#include <asm/arch/crm_regs.h>
+#include <asm/io.h>
+#include <asm/arch/sys_proto.h>
+#include <spl.h>
+#include <usb.h>
+#include <usb/ehci-ci.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define UART_PAD_CTRL (PAD_CTL_PUS_100K_UP | \
+ PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \
+ PAD_CTL_SRE_FAST | PAD_CTL_HYS)
+
+#define USDHC_PAD_CTRL (PAD_CTL_PUS_47K_UP | \
+ PAD_CTL_SPEED_LOW | PAD_CTL_DSE_80ohm | \
+ PAD_CTL_SRE_FAST | PAD_CTL_HYS)
+
+#define USB_H1_VBUS IMX_GPIO_NR(1, 0)
+
+enum board_type {
+ CUBOXI = 0x00,
+ HUMMINGBOARD = 0x01,
+ HUMMINGBOARD2 = 0x02,
+ UNKNOWN = 0x03,
+};
+
+static struct gpio_desc board_detect_desc[5];
+
+#define MEM_STRIDE 0x4000000
+static u32 get_ram_size_stride_test(u32 *base, u32 maxsize)
+{
+ volatile u32 *addr;
+ u32 save[64];
+ u32 cnt;
+ u32 size;
+ int i = 0;
+
+ /* First save the data */
+ for (cnt = 0; cnt < maxsize; cnt += MEM_STRIDE) {
+ addr = (volatile u32 *)((u32)base + cnt); /* pointer arith! */
+ sync ();
+ save[i++] = *addr;
+ sync ();
+ }
+
+ /* First write a signature */
+ * (volatile u32 *)base = 0x12345678;
+ for (size = MEM_STRIDE; size < maxsize; size += MEM_STRIDE) {
+ * (volatile u32 *)((u32)base + size) = size;
+ sync ();
+ if (* (volatile u32 *)((u32)base) == size) { /* We reached the overlapping address */
+ break;
+ }
+ }
+
+ /* Restore the data */
+ for (cnt = (maxsize - MEM_STRIDE); i > 0; cnt -= MEM_STRIDE) {
+ addr = (volatile u32 *)((u32)base + cnt); /* pointer arith! */
+ sync ();
+ *addr = save[i--];
+ sync ();
+ }
+
+ return (size);
+}
+
+int dram_init(void)
+{
+ u32 max_size = imx_ddr_size();
+
+ gd->ram_size = get_ram_size_stride_test((u32 *) CONFIG_SYS_SDRAM_BASE,
+ (u32)max_size);
+
+ return 0;
+}
+
+static iomux_v3_cfg_t const uart1_pads[] = {
+ IOMUX_PADS(PAD_CSI0_DAT10__UART1_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)),
+ IOMUX_PADS(PAD_CSI0_DAT11__UART1_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)),
+};
+
+static iomux_v3_cfg_t const usdhc2_pads[] = {
+ IOMUX_PADS(PAD_SD2_CLK__SD2_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
+ IOMUX_PADS(PAD_SD2_CMD__SD2_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
+ IOMUX_PADS(PAD_SD2_DAT0__SD2_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
+ IOMUX_PADS(PAD_SD2_DAT1__SD2_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
+ IOMUX_PADS(PAD_SD2_DAT2__SD2_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
+ IOMUX_PADS(PAD_SD2_DAT3__SD2_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
+};
+
+static iomux_v3_cfg_t const usdhc3_pads[] = {
+ IOMUX_PADS(PAD_SD3_CLK__SD3_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
+ IOMUX_PADS(PAD_SD3_CMD__SD3_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
+ IOMUX_PADS(PAD_SD3_DAT0__SD3_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
+ IOMUX_PADS(PAD_SD3_DAT1__SD3_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
+ IOMUX_PADS(PAD_SD3_DAT2__SD3_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
+ IOMUX_PADS(PAD_SD3_DAT3__SD3_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
+ IOMUX_PADS(PAD_SD3_DAT4__SD3_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
+ IOMUX_PADS(PAD_SD3_DAT5__SD3_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
+ IOMUX_PADS(PAD_SD3_DAT6__SD3_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
+ IOMUX_PADS(PAD_SD3_DAT7__SD3_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
+ IOMUX_PADS(PAD_SD3_RST__SD3_RESET | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
+};
+
+static iomux_v3_cfg_t const board_detect[] = {
+ /* These pins are for sensing if it is a CuBox-i or a HummingBoard */
+ IOMUX_PADS(PAD_KEY_ROW1__GPIO4_IO09 | MUX_PAD_CTRL(UART_PAD_CTRL)),
+ IOMUX_PADS(PAD_EIM_DA4__GPIO3_IO04 | MUX_PAD_CTRL(UART_PAD_CTRL)),
+ IOMUX_PADS(PAD_SD4_DAT0__GPIO2_IO08 | MUX_PAD_CTRL(UART_PAD_CTRL)),
+};
+
+static iomux_v3_cfg_t const som_rev_detect[] = {
+ /* These pins are for sensing if it is a CuBox-i or a HummingBoard */
+ IOMUX_PADS(PAD_CSI0_DAT14__GPIO6_IO00 | MUX_PAD_CTRL(UART_PAD_CTRL)),
+ IOMUX_PADS(PAD_CSI0_DAT18__GPIO6_IO04 | MUX_PAD_CTRL(UART_PAD_CTRL)),
+};
+
+static void setup_iomux_uart(void)
+{
+ SETUP_IOMUX_PADS(uart1_pads);
+}
+
+int board_mmc_get_env_dev(int devno)
+{
+ return devno;
+}
+
+#ifdef CONFIG_VIDEO_IPUV3
+static void do_enable_hdmi(struct display_info_t const *dev)
+{
+ imx_enable_hdmi_phy();
+}
+
+struct display_info_t const displays[] = {
+ {
+ .bus = -1,
+ .addr = 0,
+ .pixfmt = IPU_PIX_FMT_RGB24,
+ .detect = detect_hdmi,
+ .enable = do_enable_hdmi,
+ .mode = {
+ .name = "HDMI",
+ /* 1024x768@60Hz (VESA)*/
+ .refresh = 60,
+ .xres = 1024,
+ .yres = 768,
+ .pixclock = 15384,
+ .left_margin = 160,
+ .right_margin = 24,
+ .upper_margin = 29,
+ .lower_margin = 3,
+ .hsync_len = 136,
+ .vsync_len = 6,
+ .sync = FB_SYNC_EXT,
+ .vmode = FB_VMODE_NONINTERLACED
+ }
+ }
+};
+
+size_t display_count = ARRAY_SIZE(displays);
+
+static int setup_display(void)
+{
+ struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+ int reg;
+ int timeout = 100000;
+
+ enable_ipu_clock();
+ imx_setup_hdmi();
+
+ /* set video pll to 455MHz (24MHz * (37+11/12) / 2) */
+ setbits_le32(&ccm->analog_pll_video, BM_ANADIG_PLL_VIDEO_POWERDOWN);
+
+ reg = readl(&ccm->analog_pll_video);
+ reg &= ~BM_ANADIG_PLL_VIDEO_DIV_SELECT;
+ reg |= BF_ANADIG_PLL_VIDEO_DIV_SELECT(37);
+ reg &= ~BM_ANADIG_PLL_VIDEO_POST_DIV_SELECT;
+ reg |= BF_ANADIG_PLL_VIDEO_POST_DIV_SELECT(1);
+ writel(reg, &ccm->analog_pll_video);
+
+ writel(BF_ANADIG_PLL_VIDEO_NUM_A(11), &ccm->analog_pll_video_num);
+ writel(BF_ANADIG_PLL_VIDEO_DENOM_B(12), &ccm->analog_pll_video_denom);
+
+ reg &= ~BM_ANADIG_PLL_VIDEO_POWERDOWN;
+ writel(reg, &ccm->analog_pll_video);
+
+ while (timeout--)
+ if (readl(&ccm->analog_pll_video) & BM_ANADIG_PLL_VIDEO_LOCK)
+ break;
+ if (timeout < 0) {
+ printf("Warning: video pll lock timeout!\n");
+ return -ETIMEDOUT;
+ }
+
+ reg = readl(&ccm->analog_pll_video);
+ reg |= BM_ANADIG_PLL_VIDEO_ENABLE;
+ reg &= ~BM_ANADIG_PLL_VIDEO_BYPASS;
+ writel(reg, &ccm->analog_pll_video);
+
+ /* gate ipu1_di0_clk */
+ clrbits_le32(&ccm->CCGR3, MXC_CCM_CCGR3_LDB_DI0_MASK);
+
+ /* select video_pll clock / 7 for ipu1_di0_clk -> 65MHz pixclock */
+ reg = readl(&ccm->chsccdr);
+ reg &= ~(MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK |
+ MXC_CCM_CHSCCDR_IPU1_DI0_PODF_MASK |
+ MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK);
+ reg |= (2 << MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_OFFSET) |
+ (6 << MXC_CCM_CHSCCDR_IPU1_DI0_PODF_OFFSET) |
+ (0 << MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET);
+ writel(reg, &ccm->chsccdr);
+
+ /* enable ipu1_di0_clk */
+ setbits_le32(&ccm->CCGR3, MXC_CCM_CCGR3_LDB_DI0_MASK);
+
+ return 0;
+}
+#endif /* CONFIG_VIDEO_IPUV3 */
+
+static int setup_fec(void)
+{
+ struct iomuxc *const iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR;
+ int ret;
+
+ ret = enable_fec_anatop_clock(0, ENET_25MHZ);
+ if (ret)
+ return ret;
+
+ /* set gpr1[ENET_CLK_SEL] */
+ setbits_le32(&iomuxc_regs->gpr[1], IOMUXC_GPR1_ENET_CLK_SEL_MASK);
+
+ return 0;
+}
+
+int board_early_init_f(void)
+{
+ setup_iomux_uart();
+
+#ifdef CONFIG_CMD_SATA
+ setup_sata();
+#endif
+ setup_fec();
+
+ return 0;
+}
+
+int board_init(void)
+{
+ int ret = 0;
+
+ /* address of boot parameters */
+ gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
+
+#ifdef CONFIG_VIDEO_IPUV3
+ ret = setup_display();
+#endif
+
+ return ret;
+}
+
+static int request_detect_gpios(void)
+{
+ int node;
+ int ret;
+
+ node = fdt_node_offset_by_compatible(gd->fdt_blob, 0,
+ "solidrun,hummingboard-detect");
+ if (node < 0)
+ return -ENODEV;
+
+ ret = gpio_request_list_by_name_nodev(offset_to_ofnode(node),
+ "detect-gpios", board_detect_desc,
+ ARRAY_SIZE(board_detect_desc), GPIOD_IS_IN);
+
+ return ret;
+}
+
+static int free_detect_gpios(void)
+{
+ return gpio_free_list_nodev(board_detect_desc,
+ ARRAY_SIZE(board_detect_desc));
+}
+
+static enum board_type board_type(void)
+{
+ int val1, val2, val3;
+
+ SETUP_IOMUX_PADS(board_detect);
+
+ /*
+ * Machine selection -
+ * Machine val1, val2, val3
+ * ----------------------------
+ * HB2 x x 0
+ * HB rev 3.x x 0 x
+ * CBi 0 1 x
+ * HB 1 1 x
+ */
+
+ gpio_direction_input(IMX_GPIO_NR(2, 8));
+ val3 = gpio_get_value(IMX_GPIO_NR(2, 8));
+
+ if (val3 == 0)
+ return HUMMINGBOARD2;
+
+ gpio_direction_input(IMX_GPIO_NR(3, 4));
+ val2 = gpio_get_value(IMX_GPIO_NR(3, 4));
+
+ if (val2 == 0)
+ return HUMMINGBOARD;
+
+ gpio_direction_input(IMX_GPIO_NR(4, 9));
+ val1 = gpio_get_value(IMX_GPIO_NR(4, 9));
+
+ if (val1 == 0) {
+ return CUBOXI;
+ } else {
+ return HUMMINGBOARD;
+ }
+}
+
+static bool is_rev_15_som(void)
+{
+ int val1, val2;
+ SETUP_IOMUX_PADS(som_rev_detect);
+
+ val1 = gpio_get_value(IMX_GPIO_NR(6, 0));
+ val2 = gpio_get_value(IMX_GPIO_NR(6, 4));
+
+ if (val1 == 1 && val2 == 0)
+ return true;
+
+ return false;
+}
+
+static bool has_emmc(void)
+{
+ struct mmc *mmc;
+ mmc = find_mmc_device(2);
+ if (!mmc)
+ return 0;
+ return (mmc_get_op_cond(mmc) < 0) ? 0 : 1;
+}
+
+int checkboard(void)
+{
+ request_detect_gpios();
+
+ switch (board_type()) {
+ case CUBOXI:
+ puts("Board: MX6 Cubox-i");
+ break;
+ case HUMMINGBOARD:
+ puts("Board: MX6 HummingBoard");
+ break;
+ case HUMMINGBOARD2:
+ puts("Board: MX6 HummingBoard2");
+ break;
+ case UNKNOWN:
+ default:
+ puts("Board: Unknown\n");
+ goto out;
+ }
+
+ if (is_rev_15_som())
+ puts(" (som rev 1.5)\n");
+ else
+ puts("\n");
+
+ free_detect_gpios();
+out:
+ return 0;
+}
+
+/* Override the default implementation, DT model is not accurate */
+int show_board_info(void)
+{
+ return checkboard();
+}
+
+int board_late_init(void)
+{
+#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
+ request_detect_gpios();
+
+ switch (board_type()) {
+ case CUBOXI:
+ env_set("board_name", "CUBOXI");
+ break;
+ case HUMMINGBOARD:
+ env_set("board_name", "HUMMINGBOARD");
+ break;
+ case HUMMINGBOARD2:
+ env_set("board_name", "HUMMINGBOARD2");
+ break;
+ case UNKNOWN:
+ default:
+ env_set("board_name", "CUBOXI");
+ }
+
+ if (is_mx6dq())
+ env_set("board_rev", "MX6Q");
+ else
+ env_set("board_rev", "MX6DL");
+
+ if (is_rev_15_som())
+ env_set("som_rev", "V15");
+
+ if (has_emmc())
+ env_set("has_emmc", "yes");
+
+ free_detect_gpios();
+#endif
+
+ return 0;
+}
+
+/*
+ * This is not a perfect match. Avoid dependency on the DM GPIO driver needed
+ * for accurate board detection. Hummingboard2 DT is good enough for U-Boot on
+ * all Hummingboard/Cubox-i platforms.
+ */
+int board_fit_config_name_match(const char *name)
+{
+ char tmp_name[36];
+
+ snprintf(tmp_name, sizeof(tmp_name), "%s-hummingboard2-emmc-som-v15",
+ is_mx6dq() ? "imx6q" : "imx6dl");
+
+ return strcmp(name, tmp_name);
+}
+
+void board_boot_order(u32 *spl_boot_list)
+{
+ struct src *psrc = (struct src *)SRC_BASE_ADDR;
+ unsigned int reg = readl(&psrc->sbmr1) >> 11;
+ u32 boot_mode = imx6_src_get_boot_mode() & IMX6_BMODE_MASK;
+ unsigned int bmode = readl(&src_base->sbmr2);
+
+ /* If bmode is serial or USB phy is active, return serial */
+ if (((bmode >> 24) & 0x03) == 0x01 || is_usbotg_phy_active()) {
+ spl_boot_list[0] = BOOT_DEVICE_BOARD;
+ return;
+ }
+
+ switch (boot_mode >> IMX6_BMODE_SHIFT) {
+ case IMX6_BMODE_SD:
+ case IMX6_BMODE_ESD:
+ case IMX6_BMODE_MMC:
+ case IMX6_BMODE_EMMC:
+ /*
+ * Upon reading BOOT_CFG register the following map is done:
+ * Bit 11 and 12 of BOOT_CFG register can determine the current
+ * mmc port
+ * 0x1 SD2
+ * 0x2 SD3
+ */
+
+ reg &= 0x3; /* Only care about bottom 2 bits */
+ switch (reg) {
+ case 1:
+ SETUP_IOMUX_PADS(usdhc2_pads);
+ spl_boot_list[0] = BOOT_DEVICE_MMC1;
+ break;
+ case 2:
+ SETUP_IOMUX_PADS(usdhc3_pads);
+ spl_boot_list[0] = BOOT_DEVICE_MMC2;
+ break;
+ }
+ break;
+ default:
+ /* By default use USB downloader */
+ spl_boot_list[0] = BOOT_DEVICE_BOARD;
+ break;
+ }
+
+ /* As a last resort, use serial downloader */
+ spl_boot_list[1] = BOOT_DEVICE_BOARD;
+}
+
+#ifdef CONFIG_SPL_BUILD
+#include <asm/arch/mx6-ddr.h>
+static const struct mx6dq_iomux_ddr_regs mx6q_ddr_ioregs = {
+ .dram_sdclk_0 = 0x00020030,
+ .dram_sdclk_1 = 0x00020030,
+ .dram_cas = 0x00020030,
+ .dram_ras = 0x00020030,
+ .dram_reset = 0x000c0030,
+ .dram_sdcke0 = 0x00003000,
+ .dram_sdcke1 = 0x00003000,
+ .dram_sdba2 = 0x00000000,
+ .dram_sdodt0 = 0x00003030,
+ .dram_sdodt1 = 0x00003030,
+ .dram_sdqs0 = 0x00000030,
+ .dram_sdqs1 = 0x00000030,
+ .dram_sdqs2 = 0x00000030,
+ .dram_sdqs3 = 0x00000030,
+ .dram_sdqs4 = 0x00000030,
+ .dram_sdqs5 = 0x00000030,
+ .dram_sdqs6 = 0x00000030,
+ .dram_sdqs7 = 0x00000030,
+ .dram_dqm0 = 0x00020030,
+ .dram_dqm1 = 0x00020030,
+ .dram_dqm2 = 0x00020030,
+ .dram_dqm3 = 0x00020030,
+ .dram_dqm4 = 0x00020030,
+ .dram_dqm5 = 0x00020030,
+ .dram_dqm6 = 0x00020030,
+ .dram_dqm7 = 0x00020030,
+};
+
+static const struct mx6sdl_iomux_ddr_regs mx6dl_ddr_ioregs = {
+ .dram_sdclk_0 = 0x00000028,
+ .dram_sdclk_1 = 0x00000028,
+ .dram_cas = 0x00000028,
+ .dram_ras = 0x00000028,
+ .dram_reset = 0x000c0028,
+ .dram_sdcke0 = 0x00003000,
+ .dram_sdcke1 = 0x00003000,
+ .dram_sdba2 = 0x00000000,
+ .dram_sdodt0 = 0x00003030,
+ .dram_sdodt1 = 0x00003030,
+ .dram_sdqs0 = 0x00000028,
+ .dram_sdqs1 = 0x00000028,
+ .dram_sdqs2 = 0x00000028,
+ .dram_sdqs3 = 0x00000028,
+ .dram_sdqs4 = 0x00000028,
+ .dram_sdqs5 = 0x00000028,
+ .dram_sdqs6 = 0x00000028,
+ .dram_sdqs7 = 0x00000028,
+ .dram_dqm0 = 0x00000028,
+ .dram_dqm1 = 0x00000028,
+ .dram_dqm2 = 0x00000028,
+ .dram_dqm3 = 0x00000028,
+ .dram_dqm4 = 0x00000028,
+ .dram_dqm5 = 0x00000028,
+ .dram_dqm6 = 0x00000028,
+ .dram_dqm7 = 0x00000028,
+};
+
+static const struct mx6dq_iomux_grp_regs mx6q_grp_ioregs = {
+ .grp_ddr_type = 0x000C0000,
+ .grp_ddrmode_ctl = 0x00020000,
+ .grp_ddrpke = 0x00000000,
+ .grp_addds = 0x00000030,
+ .grp_ctlds = 0x00000030,
+ .grp_ddrmode = 0x00020000,
+ .grp_b0ds = 0x00000030,
+ .grp_b1ds = 0x00000030,
+ .grp_b2ds = 0x00000030,
+ .grp_b3ds = 0x00000030,
+ .grp_b4ds = 0x00000030,
+ .grp_b5ds = 0x00000030,
+ .grp_b6ds = 0x00000030,
+ .grp_b7ds = 0x00000030,
+};
+
+static const struct mx6sdl_iomux_grp_regs mx6sdl_grp_ioregs = {
+ .grp_ddr_type = 0x000c0000,
+ .grp_ddrmode_ctl = 0x00020000,
+ .grp_ddrpke = 0x00000000,
+ .grp_addds = 0x00000028,
+ .grp_ctlds = 0x00000028,
+ .grp_ddrmode = 0x00020000,
+ .grp_b0ds = 0x00000028,
+ .grp_b1ds = 0x00000028,
+ .grp_b2ds = 0x00000028,
+ .grp_b3ds = 0x00000028,
+ .grp_b4ds = 0x00000028,
+ .grp_b5ds = 0x00000028,
+ .grp_b6ds = 0x00000028,
+ .grp_b7ds = 0x00000028,
+};
+
+/* microSOM with Dual processor and 1GB memory */
+static const struct mx6_mmdc_calibration mx6q_1g_mmcd_calib = {
+ .p0_mpwldectrl0 = 0x00000000,
+ .p0_mpwldectrl1 = 0x00000000,
+ .p1_mpwldectrl0 = 0x00000000,
+ .p1_mpwldectrl1 = 0x00000000,
+ .p0_mpdgctrl0 = 0x0314031c,
+ .p0_mpdgctrl1 = 0x023e0304,
+ .p1_mpdgctrl0 = 0x03240330,
+ .p1_mpdgctrl1 = 0x03180260,
+ .p0_mprddlctl = 0x3630323c,
+ .p1_mprddlctl = 0x3436283a,
+ .p0_mpwrdlctl = 0x36344038,
+ .p1_mpwrdlctl = 0x422a423c,
+};
+
+/* microSOM with Quad processor and 2GB memory */
+static const struct mx6_mmdc_calibration mx6q_2g_mmcd_calib = {
+ .p0_mpwldectrl0 = 0x00000000,
+ .p0_mpwldectrl1 = 0x00000000,
+ .p1_mpwldectrl0 = 0x00000000,
+ .p1_mpwldectrl1 = 0x00000000,
+ .p0_mpdgctrl0 = 0x0314031c,
+ .p0_mpdgctrl1 = 0x023e0304,
+ .p1_mpdgctrl0 = 0x03240330,
+ .p1_mpdgctrl1 = 0x03180260,
+ .p0_mprddlctl = 0x3630323c,
+ .p1_mprddlctl = 0x3436283a,
+ .p0_mpwrdlctl = 0x36344038,
+ .p1_mpwrdlctl = 0x422a423c,
+};
+
+/* microSOM with Solo processor and 512MB memory */
+static const struct mx6_mmdc_calibration mx6dl_512m_mmcd_calib = {
+ .p0_mpwldectrl0 = 0x0045004D,
+ .p0_mpwldectrl1 = 0x003A0047,
+ .p0_mpdgctrl0 = 0x023C0224,
+ .p0_mpdgctrl1 = 0x02000220,
+ .p0_mprddlctl = 0x44444846,
+ .p0_mpwrdlctl = 0x32343032,
+};
+
+/* microSOM with Dual lite processor and 1GB memory */
+static const struct mx6_mmdc_calibration mx6dl_1g_mmcd_calib = {
+ .p0_mpwldectrl0 = 0x0045004D,
+ .p0_mpwldectrl1 = 0x003A0047,
+ .p1_mpwldectrl0 = 0x001F001F,
+ .p1_mpwldectrl1 = 0x00210035,
+ .p0_mpdgctrl0 = 0x023C0224,
+ .p0_mpdgctrl1 = 0x02000220,
+ .p1_mpdgctrl0 = 0x02200220,
+ .p1_mpdgctrl1 = 0x02040208,
+ .p0_mprddlctl = 0x44444846,
+ .p1_mprddlctl = 0x4042463C,
+ .p0_mpwrdlctl = 0x32343032,
+ .p1_mpwrdlctl = 0x36363430,
+};
+
+static struct mx6_ddr3_cfg mem_ddr_2g = {
+ .mem_speed = 1600,
+ .density = 2,
+ .width = 16,
+ .banks = 8,
+ .rowaddr = 14,
+ .coladdr = 10,
+ .pagesz = 2,
+ .trcd = 1375,
+ .trcmin = 4875,
+ .trasmin = 3500,
+};
+
+static struct mx6_ddr3_cfg mem_ddr_4g = {
+ .mem_speed = 1600,
+ .density = 4,
+ .width = 16,
+ .banks = 8,
+ .rowaddr = 16,
+ .coladdr = 10,
+ .pagesz = 2,
+ .trcd = 1375,
+ .trcmin = 4875,
+ .trasmin = 3500,
+};
+
+static void ccgr_init(void)
+{
+ struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+
+ writel(0x00C03F3F, &ccm->CCGR0);
+ writel(0x0030FC03, &ccm->CCGR1);
+ writel(0x0FFFC000, &ccm->CCGR2);
+ writel(0x3FF00000, &ccm->CCGR3);
+ writel(0x00FFF300, &ccm->CCGR4);
+ writel(0x0F0000C3, &ccm->CCGR5);
+ writel(0x000003FF, &ccm->CCGR6);
+}
+
+static void spl_dram_init(int width)
+{
+ struct mx6_ddr_sysinfo sysinfo = {
+ /* width of data bus: 0=16, 1=32, 2=64 */
+ .dsize = width / 32,
+ /* config for full 4GB range so that get_mem_size() works */
+ .cs_density = 32, /* 32Gb per CS */
+ .ncs = 1, /* single chip select */
+ .cs1_mirror = 0,
+ .rtt_wr = 1 /*DDR3_RTT_60_OHM*/, /* RTT_Wr = RZQ/4 */
+ .rtt_nom = 1 /*DDR3_RTT_60_OHM*/, /* RTT_Nom = RZQ/4 */
+ .walat = 1, /* Write additional latency */
+ .ralat = 5, /* Read additional latency */
+ .mif3_mode = 3, /* Command prediction working mode */
+ .bi_on = 1, /* Bank interleaving enabled */
+ .sde_to_rst = 0x10, /* 14 cycles, 200us (JEDEC default) */
+ .rst_to_cke = 0x23, /* 33 cycles, 500us (JEDEC default) */
+ .ddr_type = DDR_TYPE_DDR3,
+ .refsel = 1, /* Refresh cycles at 32KHz */
+ .refr = 7, /* 8 refresh commands per refresh cycle */
+ };
+
+ if (is_mx6dq())
+ mx6dq_dram_iocfg(width, &mx6q_ddr_ioregs, &mx6q_grp_ioregs);
+ else
+ mx6sdl_dram_iocfg(width, &mx6dl_ddr_ioregs, &mx6sdl_grp_ioregs);
+
+ if (is_cpu_type(MXC_CPU_MX6D))
+ mx6_dram_cfg(&sysinfo, &mx6q_1g_mmcd_calib, &mem_ddr_2g);
+ else if (is_cpu_type(MXC_CPU_MX6Q))
+ mx6_dram_cfg(&sysinfo, &mx6q_2g_mmcd_calib, &mem_ddr_4g);
+ else if (is_cpu_type(MXC_CPU_MX6DL))
+ mx6_dram_cfg(&sysinfo, &mx6dl_1g_mmcd_calib, &mem_ddr_2g);
+ else if (is_cpu_type(MXC_CPU_MX6SOLO))
+ mx6_dram_cfg(&sysinfo, &mx6dl_512m_mmcd_calib, &mem_ddr_2g);
+}
+
+void board_init_f(ulong dummy)
+{
+ /* setup AIPS and disable watchdog */
+ arch_cpu_init();
+
+ ccgr_init();
+ gpr_init();
+
+ /* iomux and setup of i2c */
+ board_early_init_f();
+
+ /* setup GP timer */
+ timer_init();
+
+ /* UART clocks enabled and gd valid - init serial console */
+ preloader_console_init();
+
+ /* DDR initialization */
+ if (is_cpu_type(MXC_CPU_MX6SOLO))
+ spl_dram_init(32);
+ else
+ spl_dram_init(64);
+
+ /* Clear the BSS. */
+ memset(__bss_start, 0, __bss_end - __bss_start);
+
+ /* load/boot image from boot device */
+ board_init_r(NULL, 0);
+}
+#endif