+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2014 Gateworks Corporation
* Author: Tim Harvey <tharvey@gateworks.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
-#include <i2c.h>
#include <asm/io.h>
#include <asm/arch/crm_regs.h>
-#include <asm/arch/iomux.h>
#include <asm/arch/mx6-ddr.h>
#include <asm/arch/mx6-pins.h>
#include <asm/arch/sys_proto.h>
-#include <asm/imx-common/boot_mode.h>
-#include <asm/imx-common/iomux-v3.h>
-#include <asm/imx-common/mxc_i2c.h>
+#include <asm/mach-imx/boot_mode.h>
+#include <asm/mach-imx/iomux-v3.h>
+#include <asm/mach-imx/mxc_i2c.h>
+#include <environment.h>
+#include <i2c.h>
#include <spl.h>
-#include "ventana_eeprom.h"
-
-DECLARE_GLOBAL_DATA_PTR;
+#include "gsc.h"
+#include "common.h"
#define RTT_NOM_120OHM /* use 120ohm Rtt_nom vs 60ohm (lower power) */
-#define I2C_GSC 0
-#define GSC_EEPROM_ADDR 0x51
#define GSC_EEPROM_DDR_SIZE 0x2B /* enum (512,1024,2048) MB */
#define GSC_EEPROM_DDR_WIDTH 0x2D /* enum (32,64) bit */
-#define I2C_PAD_CTRL (PAD_CTL_PUS_100K_UP | \
- PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS | \
- PAD_CTL_ODE | PAD_CTL_SRE_FAST)
-#define PC MUX_PAD_CTRL(I2C_PAD_CTRL)
-#define CONFIG_SYS_I2C_SPEED 100000
-
-/* I2C1: GSC */
-static struct i2c_pads_info mx6q_i2c_pad_info0 = {
- .scl = {
- .i2c_mode = MX6Q_PAD_EIM_D21__I2C1_SCL | PC,
- .gpio_mode = MX6Q_PAD_EIM_D21__GPIO3_IO21 | PC,
- .gp = IMX_GPIO_NR(3, 21)
- },
- .sda = {
- .i2c_mode = MX6Q_PAD_EIM_D28__I2C1_SDA | PC,
- .gpio_mode = MX6Q_PAD_EIM_D28__GPIO3_IO28 | PC,
- .gp = IMX_GPIO_NR(3, 28)
- }
-};
-static struct i2c_pads_info mx6dl_i2c_pad_info0 = {
- .scl = {
- .i2c_mode = MX6DL_PAD_EIM_D21__I2C1_SCL | PC,
- .gpio_mode = MX6DL_PAD_EIM_D21__GPIO3_IO21 | PC,
- .gp = IMX_GPIO_NR(3, 21)
- },
- .sda = {
- .i2c_mode = MX6DL_PAD_EIM_D28__I2C1_SDA | PC,
- .gpio_mode = MX6DL_PAD_EIM_D28__GPIO3_IO28 | PC,
- .gp = IMX_GPIO_NR(3, 28)
- }
-};
-
-static void i2c_setup_iomux(void)
-{
- if (is_cpu_type(MXC_CPU_MX6Q))
- setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &mx6q_i2c_pad_info0);
- else
- setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &mx6dl_i2c_pad_info0);
-}
/* configure MX6Q/DUAL mmdc DDR io registers */
struct mx6dq_iomux_ddr_regs mx6dq_ddr_ioregs = {
.trasmin = 3500,
};
+/* MT41K512M16HA-125 (8Gb density) */
+static struct mx6_ddr3_cfg mt41k512m16ha_125 = {
+ .mem_speed = 1600,
+ .density = 8,
+ .width = 16,
+ .banks = 8,
+ .rowaddr = 16,
+ .coladdr = 10,
+ .pagesz = 2,
+ .trcd = 1375,
+ .trcmin = 4875,
+ .trasmin = 3500,
+};
+
/*
* calibration - these are the various CPU/DDR3 combinations we support
*/
.p1_mpwrdlctl = 0X40304239,
};
+static struct mx6_mmdc_calibration mx6sdl_256x64_mmdc_calib = {
+ /* write leveling calibration determine */
+ .p0_mpwldectrl0 = 0x0048004A,
+ .p0_mpwldectrl1 = 0x003F004A,
+ .p1_mpwldectrl0 = 0x001E0028,
+ .p1_mpwldectrl1 = 0x002C0043,
+ /* Read DQS Gating calibration */
+ .p0_mpdgctrl0 = 0x02250219,
+ .p0_mpdgctrl1 = 0x01790202,
+ .p1_mpdgctrl0 = 0x02080208,
+ .p1_mpdgctrl1 = 0x016C0175,
+ /* Read Calibration: DQS delay relative to DQ read access */
+ .p0_mprddlctl = 0x4A4C4D4C,
+ .p1_mprddlctl = 0x494C4A48,
+ /* Write Calibration: DQ/DM delay relative to DQS write access */
+ .p0_mpwrdlctl = 0x403F3437,
+ .p1_mpwrdlctl = 0x383A3930,
+};
+
+static struct mx6_mmdc_calibration mx6sdl_256x64x2_mmdc_calib = {
+ /* write leveling calibration determine */
+ .p0_mpwldectrl0 = 0x001F003F,
+ .p0_mpwldectrl1 = 0x001F001F,
+ .p1_mpwldectrl0 = 0x001F004E,
+ .p1_mpwldectrl1 = 0x0059001F,
+ /* Read DQS Gating calibration */
+ .p0_mpdgctrl0 = 0x42220225,
+ .p0_mpdgctrl1 = 0x0213021F,
+ .p1_mpdgctrl0 = 0x022C0242,
+ .p1_mpdgctrl1 = 0x022C0244,
+ /* Read Calibration: DQS delay relative to DQ read access */
+ .p0_mprddlctl = 0x474A4C4A,
+ .p1_mprddlctl = 0x48494C45,
+ /* Write Calibration: DQ/DM delay relative to DQS write access */
+ .p0_mpwrdlctl = 0x3F3F3F36,
+ .p1_mpwrdlctl = 0x3F36363F,
+};
+
+static struct mx6_mmdc_calibration mx6dq_512x32_mmdc_calib = {
+ /* write leveling calibration determine */
+ .p0_mpwldectrl0 = 0x002A0025,
+ .p0_mpwldectrl1 = 0x003A002A,
+ /* Read DQS Gating calibration */
+ .p0_mpdgctrl0 = 0x43430356,
+ .p0_mpdgctrl1 = 0x033C0335,
+ /* Read Calibration: DQS delay relative to DQ read access */
+ .p0_mprddlctl = 0x4B373F42,
+ /* Write Calibration: DQ/DM delay relative to DQS write access */
+ .p0_mpwrdlctl = 0x303E3C36,
+};
+
+static struct mx6_mmdc_calibration mx6dq_512x64_mmdc_calib = {
+ /* write leveling calibration determine */
+ .p0_mpwldectrl0 = 0x00230020,
+ .p0_mpwldectrl1 = 0x002F002A,
+ .p1_mpwldectrl0 = 0x001D0027,
+ .p1_mpwldectrl1 = 0x00100023,
+ /* Read DQS Gating calibration */
+ .p0_mpdgctrl0 = 0x03250339,
+ .p0_mpdgctrl1 = 0x031C0316,
+ .p1_mpdgctrl0 = 0x03210331,
+ .p1_mpdgctrl1 = 0x031C025A,
+ /* Read Calibration: DQS delay relative to DQ read access */
+ .p0_mprddlctl = 0x40373C40,
+ .p1_mprddlctl = 0x3A373646,
+ /* Write Calibration: DQ/DM delay relative to DQS write access */
+ .p0_mpwrdlctl = 0x2E353933,
+ .p1_mpwrdlctl = 0x3C2F3F35,
+};
+
static void spl_dram_init(int width, int size_mb, int board_model)
{
struct mx6_ddr3_cfg *mem = NULL;
.sde_to_rst = 0x10, /* 14 cycles, 200us (JEDEC default) */
.rst_to_cke = 0x23, /* 33 cycles, 500us (JEDEC default) */
.pd_fast_exit = 1, /* enable precharge power-down fast exit */
+ .ddr_type = DDR_TYPE_DDR3,
+ .refsel = 1, /* Refresh cycles at 32KHz */
+ .refr = 7, /* 8 refresh commands per refresh cycle */
};
/*
else
calib = &mx6sdl_256x32_mmdc_calib;
debug("4gB density\n");
+ } else if (width == 32 && size_mb == 2048) {
+ mem = &mt41k512m16ha_125;
+ if (is_cpu_type(MXC_CPU_MX6Q))
+ calib = &mx6dq_512x32_mmdc_calib;
+ debug("8gB density\n");
} else if (width == 64 && size_mb == 512) {
mem = &mt41k64m16jt_125;
debug("1gB density\n");
mem = &mt41k256m16ha_125;
if (is_cpu_type(MXC_CPU_MX6Q))
calib = &mx6dq_256x64_mmdc_calib;
+ else
+ calib = &mx6sdl_256x64_mmdc_calib;
debug("4gB density\n");
+ } else if (width == 64 && size_mb == 4096) {
+ switch(board_model) {
+ case GW5903:
+ /* 8xMT41K256M16 (4GiB) fly-by mirrored 2-chipsels */
+ mem = &mt41k256m16ha_125;
+ debug("4gB density\n");
+ if (!is_cpu_type(MXC_CPU_MX6Q)) {
+ calib = &mx6sdl_256x64x2_mmdc_calib;
+ sysinfo.ncs = 2;
+ sysinfo.cs_density = 18; /* CS0_END=71 */
+ sysinfo.cs1_mirror = 1; /* mirror enabled */
+ }
+ break;
+ default:
+ mem = &mt41k512m16ha_125;
+ if (is_cpu_type(MXC_CPU_MX6Q))
+ calib = &mx6dq_512x64_mmdc_calib;
+ debug("8gB density\n");
+ break;
+ }
}
- if (!mem) {
- puts("Error: Invalid Memory Configuration\n");
- hang();
- }
- if (!calib) {
- puts("Error: Invalid Board Calibration Configuration\n");
+ if (!(mem && calib)) {
+ puts("Error: Invalid Calibration/Board Configuration\n");
+ printf("MEM : %s\n", mem ? "OKAY" : "NULL");
+ printf("CALIB : %s\n", calib ? "OKAY" : "NULL");
+ printf("CPUTYPE: %s\n",
+ is_cpu_type(MXC_CPU_MX6Q) ? "IMX6Q" : "IMX6DL");
+ printf("SIZE_MB: %d\n", size_mb);
+ printf("WIDTH : %d\n", width);
hang();
}
writel(0x000003FF, &ccm->CCGR6);
}
-static void gpr_init(void)
-{
- struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
-
- /* enable AXI cache for VDOA/VPU/IPU */
- writel(0xF00000CF, &iomux->gpr[4]);
- /* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */
- writel(0x007F007F, &iomux->gpr[6]);
- writel(0x007F007F, &iomux->gpr[7]);
-}
-
/*
* called from C runtime startup code (arch/arm/lib/crt0.S:_main)
* - we have a stack and a place to store GD, both in SRAM
struct ventana_board_info ventana_info;
int board_model;
+ /* setup clock gating */
+ ccgr_init();
+
/* setup AIPS and disable watchdog */
arch_cpu_init();
- ccgr_init();
+ /* setup AXI */
gpr_init();
/* iomux and setup of i2c */
- board_early_init_f();
- i2c_setup_iomux();
+ setup_iomux_uart();
+ setup_ventana_i2c();
/* setup GP timer */
timer_init();
preloader_console_init();
/* read/validate EEPROM info to determine board model and SDRAM cfg */
- board_model = read_eeprom(I2C_GSC, &ventana_info);
+ board_model = read_eeprom(CONFIG_I2C_GSC, &ventana_info);
+
+ /* configure model-specific gpio */
+ setup_iomux_gpio(board_model, &ventana_info);
/* provide some some default: 32bit 128MB */
- if (GW_UNKNOWN == board_model) {
- ventana_info.sdram_width = 2;
- ventana_info.sdram_size = 3;
- }
+ if (GW_UNKNOWN == board_model)
+ hang();
/* configure MMDC for SDRAM width/size and per-model calibration */
spl_dram_init(8 << ventana_info.sdram_width,
16 << ventana_info.sdram_size,
board_model);
+}
- /* Clear the BSS. */
- memset(__bss_start, 0, __bss_end - __bss_start);
+void board_boot_order(u32 *spl_boot_list)
+{
+ spl_boot_list[0] = spl_boot_device();
+ switch (spl_boot_list[0]) {
+ case BOOT_DEVICE_NAND:
+ spl_boot_list[1] = BOOT_DEVICE_MMC1;
+ spl_boot_list[2] = BOOT_DEVICE_UART;
+ break;
+ case BOOT_DEVICE_MMC1:
+ spl_boot_list[1] = BOOT_DEVICE_UART;
+ break;
+ }
+}
+
+/* called from board_init_r after gd setup if CONFIG_SPL_BOARD_INIT defined */
+/* its our chance to print info about boot device */
+void spl_board_init(void)
+{
+ /* determine boot device from SRC_SBMR1 (BOOT_CFG[4:1]) or SRC_GPR9 */
+ u32 boot_device = spl_boot_device();
+
+ switch (boot_device) {
+ case BOOT_DEVICE_MMC1:
+ puts("Booting from MMC\n");
+ break;
+ case BOOT_DEVICE_NAND:
+ puts("Booting from NAND\n");
+ break;
+ case BOOT_DEVICE_SATA:
+ puts("Booting from SATA\n");
+ break;
+ default:
+ puts("Unknown boot device\n");
+ }
- /* load/boot image from boot device */
- board_init_r(NULL, 0);
+ /* PMIC init */
+ setup_pmic();
}
-void reset_cpu(ulong addr)
+#ifdef CONFIG_SPL_OS_BOOT
+/* return 1 if we wish to boot to uboot vs os (falcon mode) */
+int spl_start_uboot(void)
{
+ unsigned char ret = 1;
+
+ debug("%s\n", __func__);
+#ifdef CONFIG_SPL_ENV_SUPPORT
+ env_init();
+ env_load();
+ debug("boot_os=%s\n", env_get("boot_os"));
+ if (env_get_yesno("boot_os") == 1)
+ ret = 0;
+#else
+ /* use i2c-0:0x50:0x00 for falcon boot mode (0=linux, else uboot) */
+ i2c_set_bus_num(0);
+ gsc_i2c_read(0x50, 0x0, 1, &ret, 1);
+#endif
+ if (!ret)
+ gsc_boot_wd_disable();
+
+ debug("%s booting %s\n", __func__, ret ? "uboot" : "linux");
+ return ret;
}
+#endif