aboutsummaryrefslogtreecommitdiff
path: root/board/gateworks
diff options
context:
space:
mode:
authorTim Harvey2014-03-06 07:46:30 -0800
committerStefano Babic2014-03-12 10:23:03 +0100
commit59189a8b26793ace1b7d0eee9496875ac8713299 (patch)
tree1ef0c4d4ba8a38443900ff20b22ed4bb4dc44ab7 /board/gateworks
parent1ad6364eeb4f578e423081d1748e8a3fdf1ab01d (diff)
ventana: Add Gateworks Ventana family support
Gateworks Ventana is a product family based on the i.MX6. This patch adds support for all boards in the Ventana family. Where possible, data from the boards EEPROM is used to determine various details about the board at runtime. Signed-off-by: Tim Harvey <tharvey@gateworks.com>
Diffstat (limited to 'board/gateworks')
-rw-r--r--board/gateworks/gw_ventana/Makefile10
-rw-r--r--board/gateworks/gw_ventana/README55
-rw-r--r--board/gateworks/gw_ventana/clocks.cfg42
-rw-r--r--board/gateworks/gw_ventana/gsc.c129
-rw-r--r--board/gateworks/gw_ventana/gsc.h64
-rw-r--r--board/gateworks/gw_ventana/gw_ventana.c1263
-rw-r--r--board/gateworks/gw_ventana/gw_ventana.cfg44
-rw-r--r--board/gateworks/gw_ventana/ventana_eeprom.h106
8 files changed, 1713 insertions, 0 deletions
diff --git a/board/gateworks/gw_ventana/Makefile b/board/gateworks/gw_ventana/Makefile
new file mode 100644
index 00000000000..e8dab89c656
--- /dev/null
+++ b/board/gateworks/gw_ventana/Makefile
@@ -0,0 +1,10 @@
+#
+# Copyright (C) 2012-2013, Guennadi Liakhovetski <lg@denx.de>
+# (C) Copyright 2012-2013 Freescale Semiconductor, Inc.
+# Copyright (C) 2013, Gateworks Corporation
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-y := gw_ventana.o gsc.o
+
diff --git a/board/gateworks/gw_ventana/README b/board/gateworks/gw_ventana/README
new file mode 100644
index 00000000000..9e697d6199d
--- /dev/null
+++ b/board/gateworks/gw_ventana/README
@@ -0,0 +1,55 @@
+U-Boot for the Gateworks Ventana Product Family boards
+
+This file contains information for the port of U-Boot to the Gateworks
+Ventana Product family boards.
+
+1. Boot source, boot from NAND
+------------------------------
+
+The i.MX6 BOOT ROM expects some structures that provide details of NAND layout
+and bad block information (referred to as 'bootstreams') which are replicated
+multiple times in NAND. The number of replications is configurable through
+board strapping options and eFUSE settings. The Freescale 'kobs-ng'
+application from the Freescale LTIB BSP, which runs under Linux, must be used
+to program the bootstream in order to setup the replicated headers correctly.
+
+The Gateworks Ventana boards with NAND flash have been factory programmed
+such that their eFUSE settings expect 2 copies of the boostream (this is
+specified by providing kobs-ng with the --search_exponent=1 argument). Once in
+Linux with MTD support for the NAND on /dev/mtd0 you can program the boostream
+with:
+
+kobs-ng init -v -x --search_exponent=1 u-boot.imx
+
+The kobs-ng application uses an imximage (u-boot.imx) which contains the
+Image Vector Table (IVT) and Device Configuration Data (DCD) structures that
+the i.MX6 BOOT ROM requires to boot. The kobs-ng adds the Firmware
+Configuration Block (FCB) and Discovered Bad Block Table (DBBT).
+
+This information is taken from:
+ http://trac.gateworks.com/wiki/ventana/bootloader#NANDFLASH
+
+More details about the i.MX6 BOOT ROM can be found in the IMX6 reference manual.
+
+2. Build
+--------
+
+There are several Gateworks Ventana boards that share a simliar design but
+vary based on CPU, Memory configuration, and subloaded devices. Although
+the subloaded devices are handled dynamically in the bootloader using
+factory configured EEPROM data to modify the device-tree, the CPU choice
+(IMX6Q vs IMX6DL) and memory configurations are currently compile-time
+options.
+
+The following Gateworks Ventana configurations exist:
+ gwventanaq1gspi: MX6Q,1GB,SPI FLASH
+ gwventanaq : MX6Q,512MB,NAND FLASH
+ gwventanaq1g : MX6Q,1GB,NAND FLASH
+ gwventanadl : MX6DL,512MB,NAND FLASH
+ gwventanadl1g : MX6DL,1GB,NAND FLASH
+
+To build U-Boot for the MX6Q,1GB,NAND FLASH for example:
+
+ make gwventanaq1g_config
+ make
+
diff --git a/board/gateworks/gw_ventana/clocks.cfg b/board/gateworks/gw_ventana/clocks.cfg
new file mode 100644
index 00000000000..a8118a258e8
--- /dev/null
+++ b/board/gateworks/gw_ventana/clocks.cfg
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2013 Boundary Devices
+ * Copyright (C) 2013 Gateworks Corporation
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * Device Configuration Data (DCD)
+ *
+ * Each entry must have the format:
+ * Addr-type Address Value
+ *
+ * where:
+ * Addr-type register length (1,2 or 4 bytes)
+ * Address absolute address of the register
+ * value value to be stored in the register
+ */
+
+/* set the default clock gate to save power */
+DATA 4, CCM_CCGR0, 0x00C03F3F
+DATA 4, CCM_CCGR1, 0x0030FC03
+DATA 4, CCM_CCGR2, 0x0FFFC000
+DATA 4, CCM_CCGR3, 0x3FF00000
+DATA 4, CCM_CCGR4, 0xFFFFF300 /* enable NAND/GPMI/BCH clocks */
+DATA 4, CCM_CCGR5, 0x0F0000C3
+DATA 4, CCM_CCGR6, 0x000003FF
+
+/* enable AXI cache for VDOA/VPU/IPU */
+DATA 4, MX6_IOMUXC_GPR4, 0xF00000CF
+/* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */
+DATA 4, MX6_IOMUXC_GPR6, 0x007F007F
+DATA 4, MX6_IOMUXC_GPR7, 0x007F007F
+
+/*
+ * Setup CCM_CCOSR register as follows:
+ *
+ * cko1_en = 1 --> CKO1 enabled
+ * cko1_div = 111 --> divide by 8
+ * cko1_sel = 1011 --> ahb_clk_root
+ *
+ * This sets CKO1 at ahb_clk_root/8 = 132/8 = 16.5 MHz
+ */
+DATA 4, CCM_CCOSR, 0x000000fb
diff --git a/board/gateworks/gw_ventana/gsc.c b/board/gateworks/gw_ventana/gsc.c
new file mode 100644
index 00000000000..37966abba99
--- /dev/null
+++ b/board/gateworks/gw_ventana/gsc.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2013 Gateworks Corporation
+ *
+ * Author: Tim Harvey <tharvey@gateworks.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <asm/errno.h>
+#include <common.h>
+#include <i2c.h>
+#include <linux/ctype.h>
+
+#include "gsc.h"
+
+#define MINMAX(n, percent) ((n)*(100-percent)/100), ((n)*(100+percent)/100)
+
+/*
+ * The Gateworks System Controller will fail to ACK a master transaction if
+ * it is busy, which can occur during its 1HZ timer tick while reading ADC's.
+ * When this does occur, it will never be busy long enough to fail more than
+ * 2 back-to-back transfers. Thus we wrap i2c_read and i2c_write with
+ * 3 retries.
+ */
+int gsc_i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len)
+{
+ int retry = 3;
+ int n = 0;
+ int ret;
+
+ while (n++ < retry) {
+ ret = i2c_read(chip, addr, alen, buf, len);
+ if (!ret)
+ break;
+ debug("%s: 0x%02x 0x%02x retry%d: %d\n", __func__, chip, addr,
+ n, ret);
+ if (ret != -ENODEV)
+ break;
+ mdelay(10);
+ }
+ return ret;
+}
+
+int gsc_i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len)
+{
+ int retry = 3;
+ int n = 0;
+ int ret;
+
+ while (n++ < retry) {
+ ret = i2c_write(chip, addr, alen, buf, len);
+ if (!ret)
+ break;
+ debug("%s: 0x%02x 0x%02x retry%d: %d\n", __func__, chip, addr,
+ n, ret);
+ if (ret != -ENODEV)
+ break;
+ mdelay(10);
+ }
+ mdelay(1);
+ return ret;
+}
+
+#ifdef CONFIG_CMD_GSC
+static void read_hwmon(const char *name, uint reg, uint size, uint low,
+ uint high)
+{
+ unsigned char buf[3];
+ uint ui;
+
+ printf("%-8s:", name);
+ memset(buf, 0, sizeof(buf));
+ if (gsc_i2c_read(GSC_HWMON_ADDR, reg, 1, buf, size)) {
+ puts("fRD\n");
+ } else {
+ ui = buf[0] | (buf[1]<<8) | (buf[2]<<16);
+ if (ui == 0xffffff)
+ printf("invalid");
+ else if (ui < low)
+ printf("%d Failed - Low", ui);
+ else if (ui > high)
+ printf("%d Failed - High", ui);
+ else
+ printf("%d", ui);
+ }
+ puts("\n");
+}
+
+int do_gsc(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ const char *model = getenv("model");
+
+ i2c_set_bus_num(0);
+ read_hwmon("Temp", GSC_HWMON_TEMP, 2, 0, 9000);
+ read_hwmon("VIN", GSC_HWMON_VIN, 3, 8000, 60000);
+ read_hwmon("VBATT", GSC_HWMON_VBATT, 3, 1800, 3500);
+ read_hwmon("VDD_3P3", GSC_HWMON_VDD_3P3, 3, MINMAX(3300, 10));
+ read_hwmon("VDD_HIGH", GSC_HWMON_VDD_HIGH, 3, MINMAX(3000, 10));
+ read_hwmon("VDD_DDR", GSC_HWMON_VDD_DDR, 3, MINMAX(1500, 10));
+ read_hwmon("VDD_5P0", GSC_HWMON_VDD_5P0, 3, MINMAX(5000, 10));
+ read_hwmon("VDD_2P5", GSC_HWMON_VDD_2P5, 3, MINMAX(2500, 10));
+ read_hwmon("VDD_1P8", GSC_HWMON_VDD_1P8, 3, MINMAX(1800, 10));
+
+ switch (model[3]) {
+ case '1': /* GW51xx */
+ read_hwmon("VDD_CORE", GSC_HWMON_VDD_CORE, 3, MINMAX(1175, 10));
+ read_hwmon("VDD_SOC", GSC_HWMON_VDD_SOC, 3, MINMAX(1175, 10));
+ break;
+ case '2': /* GW52xx */
+ case '3': /* GW53xx */
+ read_hwmon("VDD_CORE", GSC_HWMON_VDD_CORE, 3, MINMAX(1175, 10));
+ read_hwmon("VDD_SOC", GSC_HWMON_VDD_SOC, 3, MINMAX(1175, 10));
+ read_hwmon("VDD_1P0", GSC_HWMON_VDD_1P0, 3, MINMAX(1000, 10));
+ break;
+ case '4': /* GW54xx */
+ read_hwmon("VDD_CORE", GSC_HWMON_VDD_CORE, 3, MINMAX(1375, 10));
+ read_hwmon("VDD_SOC", GSC_HWMON_VDD_SOC, 3, MINMAX(1375, 10));
+ read_hwmon("VDD_1P0", GSC_HWMON_VDD_1P0, 3, MINMAX(1000, 10));
+ break;
+ }
+ return 0;
+}
+
+U_BOOT_CMD(gsc, 1, 1, do_gsc,
+ "GSC test",
+ ""
+);
+
+#endif /* CONFIG_CMD_GSC */
diff --git a/board/gateworks/gw_ventana/gsc.h b/board/gateworks/gw_ventana/gsc.h
new file mode 100644
index 00000000000..da970c39d6a
--- /dev/null
+++ b/board/gateworks/gw_ventana/gsc.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2013 Gateworks Corporation
+ *
+ * Author: Tim Harvey <tharvey@gateworks.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __ASSEMBLY__
+
+/* i2c slave addresses */
+#define GSC_SC_ADDR 0x20
+#define GSC_RTC_ADDR 0x68
+#define GSC_HWMON_ADDR 0x29
+#define GSC_EEPROM_ADDR 0x51
+
+/* System Controller registers */
+enum {
+ GSC_SC_CTRL0 = 0x00,
+ GSC_SC_CTRL1 = 0x01,
+ GSC_SC_STATUS = 0x0a,
+ GSC_SC_FWVER = 0x0e,
+};
+
+/* System Controller Control1 bits */
+enum {
+ GSC_SC_CTRL1_WDDIS = 7, /* 1 = disable watchdog */
+};
+
+/* System Controller Interrupt bits */
+enum {
+ GSC_SC_IRQ_PB = 0, /* Pushbutton switch */
+ GSC_SC_IRQ_SECURE = 1, /* Secure Key erase operation complete */
+ GSC_SC_IRQ_EEPROM_WP = 2, /* EEPROM write violation */
+ GSC_SC_IRQ_GPIO = 4, /* GPIO change */
+ GSC_SC_IRQ_TAMPER = 5, /* Tamper detect */
+ GSC_SC_IRQ_WATCHDOG = 6, /* Watchdog trip */
+ GSC_SC_IRQ_PBLONG = 7, /* Pushbutton long hold */
+};
+
+/* Hardware Monitor registers */
+enum {
+ GSC_HWMON_TEMP = 0x00,
+ GSC_HWMON_VIN = 0x02,
+ GSC_HWMON_VDD_3P3 = 0x05,
+ GSC_HWMON_VBATT = 0x08,
+ GSC_HWMON_VDD_5P0 = 0x0b,
+ GSC_HWMON_VDD_CORE = 0x0e,
+ GSC_HWMON_VDD_HIGH = 0x14,
+ GSC_HWMON_VDD_DDR = 0x17,
+ GSC_HWMON_VDD_SOC = 0x11,
+ GSC_HWMON_VDD_1P8 = 0x1d,
+ GSC_HWMON_VDD_2P5 = 0x23,
+ GSC_HWMON_VDD_1P0 = 0x20,
+};
+
+/*
+ * I2C transactions to the GSC are done via these functions which
+ * perform retries in the case of a busy GSC NAK'ing the transaction
+ */
+int gsc_i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len);
+int gsc_i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len);
+#endif
+
diff --git a/board/gateworks/gw_ventana/gw_ventana.c b/board/gateworks/gw_ventana/gw_ventana.c
new file mode 100644
index 00000000000..c130e2c1ed6
--- /dev/null
+++ b/board/gateworks/gw_ventana/gw_ventana.c
@@ -0,0 +1,1263 @@
+/*
+ * Copyright (C) 2013 Gateworks Corporation
+ *
+ * Author: Tim Harvey <tharvey@gateworks.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.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/crm_regs.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/gpio.h>
+#include <asm/imx-common/iomux-v3.h>
+#include <asm/imx-common/mxc_i2c.h>
+#include <asm/imx-common/boot_mode.h>
+#include <asm/imx-common/sata.h>
+#include <jffs2/load_kernel.h>
+#include <hwconfig.h>
+#include <i2c.h>
+#include <linux/ctype.h>
+#include <fdt_support.h>
+#include <fsl_esdhc.h>
+#include <miiphy.h>
+#include <mmc.h>
+#include <mtd_node.h>
+#include <netdev.h>
+#include <power/pmic.h>
+#include <power/pfuze100_pmic.h>
+#include <i2c.h>
+#include <fdt_support.h>
+#include <jffs2/load_kernel.h>
+#include <spi_flash.h>
+
+#include "gsc.h"
+#include "ventana_eeprom.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* GPIO's common to all baseboards */
+#define GP_PHY_RST IMX_GPIO_NR(1, 30)
+#define GP_USB_OTG_PWR IMX_GPIO_NR(3, 22)
+#define GP_SD3_CD IMX_GPIO_NR(7, 0)
+#define GP_RS232_EN IMX_GPIO_NR(2, 11)
+#define GP_MSATA_SEL IMX_GPIO_NR(2, 8)
+
+/* I2C bus numbers */
+#define I2C_GSC 0
+#define I2C_PMIC 1
+
+#define UART_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \
+ 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_PKE | PAD_CTL_PUE | \
+ PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_LOW | \
+ PAD_CTL_DSE_80ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS)
+
+#define ENET_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \
+ PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \
+ PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
+
+#define SPI_PAD_CTRL (PAD_CTL_HYS | \
+ PAD_CTL_PUS_100K_DOWN | PAD_CTL_SPEED_MED | \
+ PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST)
+
+#define DIO_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \
+ PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \
+ PAD_CTL_DSE_34ohm | PAD_CTL_HYS | PAD_CTL_SRE_FAST)
+
+#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)
+
+/*
+ * EEPROM board info struct populated by read_eeprom so that we only have to
+ * read it once.
+ */
+static struct ventana_board_info ventana_info;
+
+enum {
+ GW54proto, /* original GW5400-A prototype */
+ GW51xx,
+ GW52xx,
+ GW53xx,
+ GW54xx,
+ GW_UNKNOWN,
+};
+
+int board_type;
+
+/* UART1: Function varies per baseboard */
+iomux_v3_cfg_t const uart1_pads[] = {
+ MX6_PAD_SD3_DAT6__UART1_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+ MX6_PAD_SD3_DAT7__UART1_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+};
+
+/* UART2: Serial Console */
+iomux_v3_cfg_t const uart2_pads[] = {
+ MX6_PAD_SD4_DAT7__UART2_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+ MX6_PAD_SD4_DAT4__UART2_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+};
+
+#define PC MUX_PAD_CTRL(I2C_PAD_CTRL)
+
+/* I2C1: GSC */
+struct i2c_pads_info i2c_pad_info0 = {
+ .scl = {
+ .i2c_mode = MX6_PAD_EIM_D21__I2C1_SCL | PC,
+ .gpio_mode = MX6_PAD_EIM_D21__GPIO3_IO21 | PC,
+ .gp = IMX_GPIO_NR(3, 21)
+ },
+ .sda = {
+ .i2c_mode = MX6_PAD_EIM_D28__I2C1_SDA | PC,
+ .gpio_mode = MX6_PAD_EIM_D28__GPIO3_IO28 | PC,
+ .gp = IMX_GPIO_NR(3, 28)
+ }
+};
+
+/* I2C2: PMIC/PCIe Switch/PCIe Clock/Mezz */
+struct i2c_pads_info i2c_pad_info1 = {
+ .scl = {
+ .i2c_mode = MX6_PAD_KEY_COL3__I2C2_SCL | PC,
+ .gpio_mode = MX6_PAD_KEY_COL3__GPIO4_IO12 | PC,
+ .gp = IMX_GPIO_NR(4, 12)
+ },
+ .sda = {
+ .i2c_mode = MX6_PAD_KEY_ROW3__I2C2_SDA | PC,
+ .gpio_mode = MX6_PAD_KEY_ROW3__GPIO4_IO13 | PC,
+ .gp = IMX_GPIO_NR(4, 13)
+ }
+};
+
+/* I2C3: Misc/Expansion */
+struct i2c_pads_info i2c_pad_info2 = {
+ .scl = {
+ .i2c_mode = MX6_PAD_GPIO_3__I2C3_SCL | PC,
+ .gpio_mode = MX6_PAD_GPIO_3__GPIO1_IO03 | PC,
+ .gp = IMX_GPIO_NR(1, 3)
+ },
+ .sda = {
+ .i2c_mode = MX6_PAD_GPIO_6__I2C3_SDA | PC,
+ .gpio_mode = MX6_PAD_GPIO_6__GPIO1_IO06 | PC,
+ .gp = IMX_GPIO_NR(1, 6)
+ }
+};
+
+/* MMC */
+iomux_v3_cfg_t const usdhc3_pads[] = {
+ MX6_PAD_SD3_CLK__SD3_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_CMD__SD3_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT0__SD3_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT1__SD3_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT2__SD3_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT3__SD3_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+ MX6_PAD_SD3_DAT5__GPIO7_IO00 | MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */
+};
+
+/* ENET */
+iomux_v3_cfg_t const enet_pads[] = {
+ MX6_PAD_ENET_MDIO__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_ENET_MDC__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TXC__RGMII_TXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TD0__RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TD1__RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TD2__RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TD3__RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_TX_CTL__RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_RXC__RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_RD0__RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_RD1__RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_RD2__RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_RD3__RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ MX6_PAD_RGMII_RX_CTL__RGMII_RX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL),
+ /* PHY nRST */
+ MX6_PAD_ENET_TXD0__GPIO1_IO30 | MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
+/* NAND */
+iomux_v3_cfg_t const nfc_pads[] = {
+ MX6_PAD_NANDF_CLE__NAND_CLE | MUX_PAD_CTRL(NO_PAD_CTRL),
+ MX6_PAD_NANDF_ALE__NAND_ALE | MUX_PAD_CTRL(NO_PAD_CTRL),
+ MX6_PAD_NANDF_WP_B__NAND_WP_B | MUX_PAD_CTRL(NO_PAD_CTRL),
+ MX6_PAD_NANDF_RB0__NAND_READY_B | MUX_PAD_CTRL(NO_PAD_CTRL),
+ MX6_PAD_NANDF_CS0__NAND_CE0_B | MUX_PAD_CTRL(NO_PAD_CTRL),
+ MX6_PAD_SD4_CMD__NAND_RE_B | MUX_PAD_CTRL(NO_PAD_CTRL),
+ MX6_PAD_SD4_CLK__NAND_WE_B | MUX_PAD_CTRL(NO_PAD_CTRL),
+ MX6_PAD_NANDF_D0__NAND_DATA00 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ MX6_PAD_NANDF_D1__NAND_DATA01 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ MX6_PAD_NANDF_D2__NAND_DATA02 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ MX6_PAD_NANDF_D3__NAND_DATA03 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ MX6_PAD_NANDF_D4__NAND_DATA04 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ MX6_PAD_NANDF_D5__NAND_DATA05 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ MX6_PAD_NANDF_D6__NAND_DATA06 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ MX6_PAD_NANDF_D7__NAND_DATA07 | MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
+#ifdef CONFIG_CMD_NAND
+static void setup_gpmi_nand(void)
+{
+ struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+
+ /* config gpmi nand iomux */
+ imx_iomux_v3_setup_multiple_pads(nfc_pads, ARRAY_SIZE(nfc_pads));
+
+ /* config gpmi and bch clock to 100 MHz */
+ clrsetbits_le32(&mxc_ccm->cs2cdr,
+ MXC_CCM_CS2CDR_ENFC_CLK_PODF_MASK |
+ MXC_CCM_CS2CDR_ENFC_CLK_PRED_MASK |
+ MXC_CCM_CS2CDR_ENFC_CLK_SEL_MASK,
+ MXC_CCM_CS2CDR_ENFC_CLK_PODF(0) |
+ MXC_CCM_CS2CDR_ENFC_CLK_PRED(3) |
+ MXC_CCM_CS2CDR_ENFC_CLK_SEL(3));
+
+ /* enable gpmi and bch clock gating */
+ setbits_le32(&mxc_ccm->CCGR4,
+ MXC_CCM_CCGR4_RAWNAND_U_BCH_INPUT_APB_MASK |
+ MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_BCH_MASK |
+ MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_MASK |
+ MXC_CCM_CCGR4_RAWNAND_U_GPMI_INPUT_APB_MASK |
+ MXC_CCM_CCGR4_PL301_MX6QPER1_BCH_OFFSET);
+
+ /* enable apbh clock gating */
+ setbits_le32(&mxc_ccm->CCGR0, MXC_CCM_CCGR0_APBHDMA_MASK);
+}
+#endif
+
+static void setup_iomux_enet(void)
+{
+ imx_iomux_v3_setup_multiple_pads(enet_pads, ARRAY_SIZE(enet_pads));
+
+ /* toggle PHY_RST# */
+ gpio_direction_output(GP_PHY_RST, 0);
+ mdelay(2);
+ gpio_set_value(GP_PHY_RST, 1);
+}
+
+static void setup_iomux_uart(void)
+{
+ imx_iomux_v3_setup_multiple_pads(uart1_pads, ARRAY_SIZE(uart1_pads));
+ imx_iomux_v3_setup_multiple_pads(uart2_pads, ARRAY_SIZE(uart2_pads));
+}
+
+#ifdef CONFIG_USB_EHCI_MX6
+iomux_v3_cfg_t const usb_pads[] = {
+ MX6_PAD_GPIO_1__USB_OTG_ID | MUX_PAD_CTRL(DIO_PAD_CTRL),
+ MX6_PAD_KEY_COL4__USB_OTG_OC | MUX_PAD_CTRL(DIO_PAD_CTRL),
+ MX6_PAD_EIM_D22__GPIO3_IO22 | MUX_PAD_CTRL(DIO_PAD_CTRL), /* OTG PWR */
+};
+
+int board_ehci_hcd_init(int port)
+{
+ struct ventana_board_info *info = &ventana_info;
+
+ imx_iomux_v3_setup_multiple_pads(usb_pads, ARRAY_SIZE(usb_pads));
+
+ /* Reset USB HUB (present on GW54xx/GW53xx) */
+ switch (info->model[3]) {
+ case '3': /* GW53xx */
+ imx_iomux_v3_setup_pad(MX6_PAD_GPIO_9__GPIO1_IO09|
+ MUX_PAD_CTRL(NO_PAD_CTRL));
+ gpio_direction_output(IMX_GPIO_NR(1, 9), 0);
+ mdelay(2);
+ gpio_set_value(IMX_GPIO_NR(1, 9), 1);
+ break;
+ case '4': /* GW54xx */
+ imx_iomux_v3_setup_pad(MX6_PAD_SD1_DAT0__GPIO1_IO16 |
+ MUX_PAD_CTRL(NO_PAD_CTRL));
+ gpio_direction_output(IMX_GPIO_NR(1, 16), 0);
+ mdelay(2);
+ gpio_set_value(IMX_GPIO_NR(1, 16), 1);
+ break;
+ }
+
+ return 0;
+}
+
+int board_ehci_power(int port, int on)
+{
+ if (port)
+ return 0;
+ gpio_set_value(GP_USB_OTG_PWR, on);
+ return 0;
+}
+#endif /* CONFIG_USB_EHCI_MX6 */
+
+#ifdef CONFIG_FSL_ESDHC
+struct fsl_esdhc_cfg usdhc_cfg = { USDHC3_BASE_ADDR };
+
+int board_mmc_getcd(struct mmc *mmc)
+{
+ /* Card Detect */
+ gpio_direction_input(GP_SD3_CD);
+ return !gpio_get_value(GP_SD3_CD);
+}
+
+int board_mmc_init(bd_t *bis)
+{
+ /* Only one USDHC controller on Ventana */
+ imx_iomux_v3_setup_multiple_pads(usdhc3_pads, ARRAY_SIZE(usdhc3_pads));
+ usdhc_cfg.sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
+ usdhc_cfg.max_bus_width = 4;
+
+ return fsl_esdhc_initialize(bis, &usdhc_cfg);
+}
+#endif /* CONFIG_FSL_ESDHC */
+
+#ifdef CONFIG_MXC_SPI
+iomux_v3_cfg_t const ecspi1_pads[] = {
+ /* SS1 */
+ MX6_PAD_EIM_D19__GPIO3_IO19 | MUX_PAD_CTRL(SPI_PAD_CTRL),
+ MX6_PAD_EIM_D17__ECSPI1_MISO | MUX_PAD_CTRL(SPI_PAD_CTRL),
+ MX6_PAD_EIM_D18__ECSPI1_MOSI | MUX_PAD_CTRL(SPI_PAD_CTRL),
+ MX6_PAD_EIM_D16__ECSPI1_SCLK | MUX_PAD_CTRL(SPI_PAD_CTRL),
+};
+
+static void setup_spi(void)
+{
+ gpio_direction_output(CONFIG_SF_DEFAULT_CS, 1);
+ imx_iomux_v3_setup_multiple_pads(ecspi1_pads,
+ ARRAY_SIZE(ecspi1_pads));
+}
+#endif
+
+/* configure eth0 PHY board-specific LED behavior */
+int board_phy_config(struct phy_device *phydev)
+{
+ unsigned short val;
+
+ /* Marvel 88E1510 */
+ if (phydev->phy_id == 0x1410dd1) {
+ /*
+ * Page 3, Register 16: LED[2:0] Function Control Register
+ * LED[0] (SPD:Amber) R16_3.3:0 to 0111: on-GbE link
+ * LED[1] (LNK:Green) R16_3.7:4 to 0001: on-link, blink-activity
+ */
+ phy_write(phydev, MDIO_DEVAD_NONE, 22, 3);
+ val = phy_read(phydev, MDIO_DEVAD_NONE, 16);
+ val &= 0xff00;
+ val |= 0x0017;
+ phy_write(phydev, MDIO_DEVAD_NONE, 16, val);
+ phy_write(phydev, MDIO_DEVAD_NONE, 22, 0);
+ }
+
+ if (phydev->drv->config)
+ phydev->drv->config(phydev);
+
+ return 0;
+}
+
+int board_eth_init(bd_t *bis)
+{
+ setup_iomux_enet();
+
+#ifdef CONFIG_FEC_MXC
+ cpu_eth_init(bis);
+#endif
+
+#ifdef CONFIG_CI_UDC
+ /* For otg ethernet*/
+ usb_eth_initialize(bis);
+#endif
+
+ return 0;
+}
+
+/* read ventana EEPROM, check for validity, and return baseboard type */
+static int
+read_eeprom(void)
+{
+ int i;
+ int chksum;
+ char baseboard;
+ int type;
+ struct ventana_board_info *info = &ventana_info;
+ unsigned char *buf = (unsigned char *)&ventana_info;
+
+ memset(info, 0, sizeof(ventana_info));
+
+ /*
+ * On a board with a missing/depleted backup battery for GSC, the
+ * board may be ready to probe the GSC before its firmware is
+ * running. We will wait here indefinately for the GSC/EEPROM.
+ */
+ while (1) {
+ if (0 == i2c_set_bus_num(I2C_GSC) &&
+ 0 == i2c_probe(GSC_EEPROM_ADDR))
+ break;
+ mdelay(1);
+ }
+
+ /* read eeprom config section */
+ if (gsc_i2c_read(GSC_EEPROM_ADDR, 0x00, 1, buf, sizeof(ventana_info))) {
+ puts("EEPROM: Failed to read EEPROM\n");
+ info->model[0] = 0;
+ return GW_UNKNOWN;
+ }
+
+ /* sanity checks */
+ if (info->model[0] != 'G' || info->model[1] != 'W') {
+ puts("EEPROM: Invalid Model in EEPROM\n");
+ info->model[0] = 0;
+ return GW_UNKNOWN;
+ }
+
+ /* validate checksum */
+ for (chksum = 0, i = 0; i < sizeof(*info)-2; i++)
+ chksum += buf[i];
+ if ((info->chksum[0] != chksum>>8) ||
+ (info->chksum[1] != (chksum&0xff))) {
+ puts("EEPROM: Failed EEPROM checksum\n");
+ info->model[0] = 0;
+ return GW_UNKNOWN;
+ }
+
+ /* original GW5400-A prototype */
+ baseboard = info->model[3];
+ if (strncasecmp((const char *)info->model, "GW5400-A", 8) == 0)
+ baseboard = '0';
+
+ switch (baseboard) {
+ case '0': /* original GW5400-A prototype */
+ type = GW54proto;
+ break;
+ case '1':
+ type = GW51xx;
+ break;
+ case '2':
+ type = GW52xx;
+ break;
+ case '3':
+ type = GW53xx;
+ break;
+ case '4':
+ type = GW54xx;
+ break;
+ default:
+ printf("EEPROM: Unknown model in EEPROM: %s\n", info->model);
+ type = GW_UNKNOWN;
+ break;
+ }
+ return type;
+}
+
+/*
+ * Baseboard specific GPIO
+ */
+
+/* common to add baseboards */
+static iomux_v3_cfg_t const gw_gpio_pads[] = {
+ /* MSATA_EN */
+ MX6_PAD_SD4_DAT0__GPIO2_IO08 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* RS232_EN# */
+ MX6_PAD_SD4_DAT3__GPIO2_IO11 | MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
+/* prototype */
+static iomux_v3_cfg_t const gwproto_gpio_pads[] = {
+ /* PANLEDG# */
+ MX6_PAD_KEY_COL0__GPIO4_IO06 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* PANLEDR# */
+ MX6_PAD_KEY_ROW0__GPIO4_IO07 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* LOCLED# */
+ MX6_PAD_KEY_ROW4__GPIO4_IO15 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* RS485_EN */
+ MX6_PAD_SD3_DAT4__GPIO7_IO01 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* IOEXP_PWREN# */
+ MX6_PAD_EIM_A19__GPIO2_IO19 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* IOEXP_IRQ# */
+ MX6_PAD_EIM_A20__GPIO2_IO18 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* VID_EN */
+ MX6_PAD_EIM_D31__GPIO3_IO31 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* DIOI2C_DIS# */
+ MX6_PAD_GPIO_19__GPIO4_IO05 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* PCICK_SSON */
+ MX6_PAD_SD1_CLK__GPIO1_IO20 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* PCI_RST# */
+ MX6_PAD_ENET_TXD1__GPIO1_IO29 | MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
+static iomux_v3_cfg_t const gw51xx_gpio_pads[] = {
+ /* PANLEDG# */
+ MX6_PAD_KEY_COL0__GPIO4_IO06 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* PANLEDR# */
+ MX6_PAD_KEY_ROW0__GPIO4_IO07 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* IOEXP_PWREN# */
+ MX6_PAD_EIM_A19__GPIO2_IO19 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* IOEXP_IRQ# */
+ MX6_PAD_EIM_A20__GPIO2_IO18 | MUX_PAD_CTRL(NO_PAD_CTRL),
+
+ /* GPS_SHDN */
+ MX6_PAD_GPIO_2__GPIO1_IO02 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* VID_PWR */
+ MX6_PAD_CSI0_DATA_EN__GPIO5_IO20 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* PCI_RST# */
+ MX6_PAD_GPIO_0__GPIO1_IO00 | MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
+static iomux_v3_cfg_t const gw52xx_gpio_pads[] = {
+ /* PANLEDG# */
+ MX6_PAD_KEY_COL0__GPIO4_IO06 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* PANLEDR# */
+ MX6_PAD_KEY_ROW0__GPIO4_IO07 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* IOEXP_PWREN# */
+ MX6_PAD_EIM_A19__GPIO2_IO19 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* IOEXP_IRQ# */
+ MX6_PAD_EIM_A20__GPIO2_IO18 | MUX_PAD_CTRL(NO_PAD_CTRL),
+
+ /* MX6_LOCLED# */
+ MX6_PAD_KEY_ROW4__GPIO4_IO15 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* GPS_SHDN */
+ MX6_PAD_ENET_RXD0__GPIO1_IO27 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* USBOTG_SEL */
+ MX6_PAD_GPIO_2__GPIO1_IO02 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* VID_PWR */
+ MX6_PAD_EIM_D31__GPIO3_IO31 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* PCI_RST# */
+ MX6_PAD_ENET_TXD1__GPIO1_IO29 | MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
+static iomux_v3_cfg_t const gw53xx_gpio_pads[] = {
+ /* PANLEDG# */
+ MX6_PAD_KEY_COL0__GPIO4_IO06 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* PANLEDR# */
+ MX6_PAD_KEY_ROW0__GPIO4_IO07 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* IOEXP_PWREN# */
+ MX6_PAD_EIM_A19__GPIO2_IO19 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* IOEXP_IRQ# */
+ MX6_PAD_EIM_A20__GPIO2_IO18 | MUX_PAD_CTRL(NO_PAD_CTRL),
+
+ /* MX6_LOCLED# */
+ MX6_PAD_KEY_ROW4__GPIO4_IO15 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* GPS_SHDN */
+ MX6_PAD_ENET_RXD0__GPIO1_IO27 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* VID_EN */
+ MX6_PAD_EIM_D31__GPIO3_IO31 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* PCI_RST# */
+ MX6_PAD_ENET_TXD1__GPIO1_IO29 | MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
+static iomux_v3_cfg_t const gw54xx_gpio_pads[] = {
+ /* PANLEDG# */
+ MX6_PAD_KEY_COL0__GPIO4_IO06 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* PANLEDR# */
+ MX6_PAD_KEY_COL2__GPIO4_IO10 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* MX6_LOCLED# */
+ MX6_PAD_KEY_ROW4__GPIO4_IO15 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* MIPI_DIO */
+ MX6_PAD_SD1_DAT3__GPIO1_IO21 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* RS485_EN */
+ MX6_PAD_EIM_D24__GPIO3_IO24 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* IOEXP_PWREN# */
+ MX6_PAD_KEY_ROW0__GPIO4_IO07 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* IOEXP_IRQ# */
+ MX6_PAD_KEY_ROW1__GPIO4_IO09 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* DIOI2C_DIS# */
+ MX6_PAD_GPIO_19__GPIO4_IO05 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* DIOI2C_DIS# */
+ MX6_PAD_GPIO_19__GPIO4_IO05 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* PCICK_SSON */
+ MX6_PAD_SD1_CLK__GPIO1_IO20 | MUX_PAD_CTRL(NO_PAD_CTRL),
+ /* PCI_RST# */
+ MX6_PAD_ENET_TXD1__GPIO1_IO29 | MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
+/*
+ * each baseboard has 4 user configurable Digital IO lines which can
+ * be pinmuxed as a GPIO or in some cases a PWM
+ */
+struct dio_cfg {
+ iomux_v3_cfg_t gpio_padmux;
+ unsigned gpio_param;
+ iomux_v3_cfg_t pwm_padmux;
+ unsigned pwm_param;
+};
+
+struct ventana {
+ /* pinmux */
+ iomux_v3_cfg_t const *gpio_pads;
+ int num_pads;
+ /* DIO pinmux/val */
+ struct dio_cfg dio_cfg[4];
+ /* various gpios (0 if non-existent) */
+ int leds[3];
+ int pcie_rst;
+ int mezz_pwren;
+ int mezz_irq;
+ int rs485en;
+ int gps_shdn;
+ int vidin_en;
+ int dioi2c_en;
+ int pcie_sson;
+ int usb_sel;
+};
+
+struct ventana gpio_cfg[] = {
+ /* GW5400proto */
+ {
+ .gpio_pads = gw54xx_gpio_pads,
+ .num_pads = ARRAY_SIZE(gw54xx_gpio_pads),
+ .dio_cfg = {
+ { MX6_PAD_GPIO_9__GPIO1_IO09, IMX_GPIO_NR(1, 9),
+ MX6_PAD_GPIO_9__PWM1_OUT, 1 },
+ { MX6_PAD_SD1_DAT2__GPIO1_IO19, IMX_GPIO_NR(1, 19),
+ MX6_PAD_SD1_DAT2__PWM2_OUT, 2 },
+ { MX6_PAD_SD4_DAT1__GPIO2_IO09, IMX_GPIO_NR(2, 9),
+ MX6_PAD_SD4_DAT1__PWM3_OUT, 3 },
+ { MX6_PAD_SD4_DAT2__GPIO2_IO10, IMX_GPIO_NR(2, 10),
+ MX6_PAD_SD4_DAT2__PWM4_OUT, 4 },
+ },
+ .leds = {
+ IMX_GPIO_NR(4, 6),
+ IMX_GPIO_NR(4, 10),
+ IMX_GPIO_NR(4, 15),
+ },
+ .pcie_rst = IMX_GPIO_NR(1, 29),
+ .mezz_pwren = IMX_GPIO_NR(4, 7),
+ .mezz_irq = IMX_GPIO_NR(4, 9),
+ .rs485en = IMX_GPIO_NR(3, 24),
+ .dioi2c_en = IMX_GPIO_NR(4, 5),
+ .pcie_sson = IMX_GPIO_NR(1, 20),
+ },
+
+ /* GW51xx */
+ {
+ .gpio_pads = gw51xx_gpio_pads,
+ .num_pads = ARRAY_SIZE(gw51xx_gpio_pads),
+ .dio_cfg = {
+ { MX6_PAD_SD1_DAT0__GPIO1_IO16, IMX_GPIO_NR(1, 16),
+ 0, 0 },
+ { MX6_PAD_SD1_DAT2__GPIO1_IO19, IMX_GPIO_NR(1, 19),
+ MX6_PAD_SD1_DAT2__PWM2_OUT, 2 },
+ { MX6_PAD_SD1_DAT1__GPIO1_IO17, IMX_GPIO_NR(1, 17),
+ MX6_PAD_SD1_DAT1__PWM3_OUT, 3 },
+ { MX6_PAD_SD1_CMD__GPIO1_IO18, IMX_GPIO_NR(1, 18),
+ MX6_PAD_SD1_CMD__PWM4_OUT, 4 },
+ },
+ .leds = {
+ IMX_GPIO_NR(4, 6),
+ IMX_GPIO_NR(4, 10),
+ },
+ .pcie_rst = IMX_GPIO_NR(1, 0),
+ .mezz_pwren = IMX_GPIO_NR(2, 19),
+ .mezz_irq = IMX_GPIO_NR(2, 18),
+ .gps_shdn = IMX_GPIO_NR(1, 2),
+ .vidin_en = IMX_GPIO_NR(5, 20),
+ },
+
+ /* GW52xx */
+ {
+ .gpio_pads = gw52xx_gpio_pads,
+ .num_pads = ARRAY_SIZE(gw52xx_gpio_pads),
+ .dio_cfg = {
+ { MX6_PAD_SD1_DAT0__GPIO1_IO16, IMX_GPIO_NR(1, 16),
+ 0, 0 },
+ { MX6_PAD_SD1_DAT2__GPIO1_IO19, IMX_GPIO_NR(1, 19),
+ MX6_PAD_SD1_DAT2__PWM2_OUT, 2 },
+ { MX6_PAD_SD1_DAT1__GPIO1_IO17, IMX_GPIO_NR(1, 17),
+ MX6_PAD_SD1_DAT1__PWM3_OUT, 3 },
+ { MX6_PAD_SD1_CLK__GPIO1_IO20, IMX_GPIO_NR(1, 20),
+ 0, 0 },
+ },
+ .leds = {
+ IMX_GPIO_NR(4, 6),
+ IMX_GPIO_NR(4, 7),
+ IMX_GPIO_NR(4, 15),
+ },
+ .pcie_rst = IMX_GPIO_NR(1, 29),
+ .mezz_pwren = IMX_GPIO_NR(2, 19),
+ .mezz_irq = IMX_GPIO_NR(2, 18),
+ .gps_shdn = IMX_GPIO_NR(1, 27),
+ .vidin_en = IMX_GPIO_NR(3, 31),
+ .usb_sel = IMX_GPIO_NR(1, 2),
+ },
+
+ /* GW53xx */
+ {
+ .gpio_pads = gw53xx_gpio_pads,
+ .num_pads = ARRAY_SIZE(gw53xx_gpio_pads),
+ .dio_cfg = {
+ { MX6_PAD_SD1_DAT0__GPIO1_IO16, IMX_GPIO_NR(1, 16),
+ 0, 0 },
+ { MX6_PAD_SD1_DAT2__GPIO1_IO19, IMX_GPIO_NR(1, 19),
+ MX6_PAD_SD1_DAT2__PWM2_OUT, 2 },
+ { MX6_PAD_SD1_DAT1__GPIO1_IO17, IMX_GPIO_NR(1, 17),
+ MX6_PAD_SD1_DAT1__PWM3_OUT, 3 },
+ { MX6_PAD_SD1_CLK__GPIO1_IO20, IMX_GPIO_NR(1, 20),
+ 0, 0 },
+ },
+ .leds = {
+ IMX_GPIO_NR(4, 6),
+ IMX_GPIO_NR(4, 7),
+ IMX_GPIO_NR(4, 15),
+ },
+ .pcie_rst = IMX_GPIO_NR(1, 29),
+ .mezz_pwren = IMX_GPIO_NR(2, 19),
+ .mezz_irq = IMX_GPIO_NR(2, 18),
+ .gps_shdn = IMX_GPIO_NR(1, 27),
+ .vidin_en = IMX_GPIO_NR(3, 31),
+ },
+
+ /* GW54xx */
+ {
+ .gpio_pads = gw54xx_gpio_pads,
+ .num_pads = ARRAY_SIZE(gw54xx_gpio_pads),
+ .dio_cfg = {
+ { MX6_PAD_GPIO_9__GPIO1_IO09, IMX_GPIO_NR(1, 9),
+ MX6_PAD_GPIO_9__PWM1_OUT, 1 },
+ { MX6_PAD_SD1_DAT2__GPIO1_IO19, IMX_GPIO_NR(1, 19),
+ MX6_PAD_SD1_DAT2__PWM2_OUT, 2 },
+ { MX6_PAD_SD4_DAT1__GPIO2_IO09, IMX_GPIO_NR(2, 9),
+ MX6_PAD_SD4_DAT1__PWM3_OUT, 3 },
+ { MX6_PAD_SD4_DAT2__GPIO2_IO10, IMX_GPIO_NR(2, 10),
+ MX6_PAD_SD4_DAT2__PWM4_OUT, 4 },
+ },
+ .leds = {
+ IMX_GPIO_NR(4, 6),
+ IMX_GPIO_NR(4, 7),
+ IMX_GPIO_NR(4, 15),
+ },
+ .pcie_rst = IMX_GPIO_NR(1, 29),
+ .mezz_pwren = IMX_GPIO_NR(2, 19),
+ .mezz_irq = IMX_GPIO_NR(2, 18),
+ .rs485en = IMX_GPIO_NR(7, 1),
+ .vidin_en = IMX_GPIO_NR(3, 31),
+ .dioi2c_en = IMX_GPIO_NR(4, 5),
+ .pcie_sson = IMX_GPIO_NR(1, 20),
+ },
+};
+
+/* setup GPIO pinmux and default configuration per baseboard */
+static void setup_board_gpio(int board)
+{
+ struct ventana_board_info *info = &ventana_info;
+ const char *s;
+ char arg[10];
+ size_t len;
+ int i;
+ int quiet = simple_strtol(getenv("quiet"), NULL, 10);
+
+ if (board >= GW_UNKNOWN)
+ return;
+
+ /* RS232_EN# */
+ gpio_direction_output(GP_RS232_EN, (hwconfig("rs232")) ? 0 : 1);
+
+ /* MSATA Enable */
+ if (is_cpu_type(MXC_CPU_MX6Q) &&
+ test_bit(EECONFIG_SATA, info->config)) {
+ gpio_direction_output(GP_MSATA_SEL,
+ (hwconfig("msata")) ? 1 : 0);
+ } else {
+ gpio_direction_output(GP_MSATA_SEL, 0);
+ }
+
+ /*
+ * assert PCI_RST# (released by OS when clock is valid)
+ * TODO: figure out why leaving this de-asserted from PCI scan on boot
+ * causes linux pcie driver to hang during enumeration
+ */
+ gpio_direction_output(gpio_cfg[board].pcie_rst, 0);
+
+ /* turn off (active-high) user LED's */
+ for (i = 0; i < 4; i++) {
+ if (gpio_cfg[board].leds[i])
+ gpio_direction_output(gpio_cfg[board].leds[i], 1);
+ }
+
+ /* Expansion Mezzanine IO */
+ gpio_direction_output(gpio_cfg[board].mezz_pwren, 0);
+ gpio_direction_input(gpio_cfg[board].mezz_irq);
+
+ /* RS485 Transmit Enable */
+ if (gpio_cfg[board].rs485en)
+ gpio_direction_output(gpio_cfg[board].rs485en, 0);
+
+ /* GPS_SHDN */
+ if (gpio_cfg[board].gps_shdn)
+ gpio_direction_output(gpio_cfg[board].gps_shdn, 1);
+
+ /* Analog video codec power enable */
+ if (gpio_cfg[board].vidin_en)
+ gpio_direction_output(gpio_cfg[board].vidin_en, 1);
+
+ /* DIOI2C_DIS# */
+ if (gpio_cfg[board].dioi2c_en)
+ gpio_direction_output(gpio_cfg[board].dioi2c_en, 0);
+
+ /* PCICK_SSON: disable spread-spectrum clock */
+ if (gpio_cfg[board].pcie_sson)
+ gpio_direction_output(gpio_cfg[board].pcie_sson, 0);
+
+ /* USBOTG Select (PCISKT or FrontPanel) */
+ if (gpio_cfg[board].usb_sel)
+ gpio_direction_output(gpio_cfg[board].usb_sel, 0);
+
+ /*
+ * Configure DIO pinmux/padctl registers
+ * see IMX6DQRM/IMX6SDLRM IOMUXC_SW_PAD_CTL_PAD_* register definitions
+ */
+ for (i = 0; i < 4; i++) {
+ struct dio_cfg *cfg = &gpio_cfg[board].dio_cfg[i];
+ unsigned ctrl = DIO_PAD_CTRL;
+
+ sprintf(arg, "dio%d", i);
+ if (!hwconfig(arg))
+ continue;
+ s = hwconfig_subarg(arg, "padctrl", &len);
+ if (s)
+ ctrl = simple_strtoul(s, NULL, 16) & 0x3ffff;
+ if (hwconfig_subarg_cmp(arg, "mode", "gpio")) {
+ if (!quiet) {
+ printf("DIO%d: GPIO%d_IO%02d (gpio-%d)\n", i,
+ (cfg->gpio_param/32)+1,
+ cfg->gpio_param%32,
+ cfg->gpio_param);
+ }
+ imx_iomux_v3_setup_pad(cfg->gpio_padmux |
+ MUX_PAD_CTRL(ctrl));
+ gpio_direction_input(cfg->gpio_param);
+ } else if (hwconfig_subarg_cmp("dio2", "mode", "pwm") &&
+ cfg->pwm_padmux) {
+ if (!quiet)
+ printf("DIO%d: pwm%d\n", i, cfg->pwm_param);
+ imx_iomux_v3_setup_pad(cfg->pwm_padmux |
+ MUX_PAD_CTRL(ctrl));
+ }
+ }
+
+ if (!quiet) {
+ if (is_cpu_type(MXC_CPU_MX6Q) &&
+ (test_bit(EECONFIG_SATA, info->config))) {
+ printf("MSATA: %s\n", (hwconfig("msata") ?
+ "enabled" : "disabled"));
+ }
+ printf("RS232: %s\n", (hwconfig("rs232")) ?
+ "enabled" : "disabled");
+ }
+}
+
+#if defined(CONFIG_CMD_PCI)
+int imx6_pcie_toggle_reset(void)
+{
+ if (board_type < GW_UNKNOWN) {
+ gpio_direction_output(gpio_cfg[board_type].pcie_rst, 0);
+ mdelay(50);
+ gpio_direction_output(gpio_cfg[board_type].pcie_rst, 1);
+ }
+ return 0;
+}
+#endif /* CONFIG_CMD_PCI */
+
+#ifdef CONFIG_SERIAL_TAG
+/*
+ * called when setting up ATAGS before booting kernel
+ * populate serialnum from the following (in order of priority):
+ * serial# env var
+ * eeprom
+ */
+void get_board_serial(struct tag_serialnr *serialnr)
+{
+ char *serial = getenv("serial#");
+
+ if (serial) {
+ serialnr->high = 0;
+ serialnr->low = simple_strtoul(serial, NULL, 10);
+ } else if (ventana_info.model[0]) {
+ serialnr->high = 0;
+ serialnr->low = ventana_info.serial;
+ } else {
+ serialnr->high = 0;
+ serialnr->low = 0;
+ }
+}
+#endif
+
+/*
+ * Board Support
+ */
+
+int board_early_init_f(void)
+{
+ setup_iomux_uart();
+ gpio_direction_output(GP_USB_OTG_PWR, 0); /* OTG power off */
+
+ return 0;
+}
+
+int dram_init(void)
+{
+ gd->ram_size = get_ram_size((void *)PHYS_SDRAM,
+ CONFIG_DDR_MB*1024*1024);
+
+ return 0;
+}
+
+int board_init(void)
+{
+ struct iomuxc_base_regs *const iomuxc_regs
+ = (struct iomuxc_base_regs *)IOMUXC_BASE_ADDR;
+
+ clrsetbits_le32(&iomuxc_regs->gpr[1],
+ IOMUXC_GPR1_OTG_ID_MASK,
+ IOMUXC_GPR1_OTG_ID_GPIO1);
+
+ /* address of linux boot parameters */
+ gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
+
+#ifdef CONFIG_CMD_NAND
+ setup_gpmi_nand();
+#endif
+#ifdef CONFIG_MXC_SPI
+ setup_spi();
+#endif
+ setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info0);
+ setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1);
+ setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info2);
+
+#ifdef CONFIG_CMD_SATA
+ setup_sata();
+#endif
+ /* read Gateworks EEPROM into global struct (used later) */
+ board_type = read_eeprom();
+
+ /* board-specifc GPIO iomux */
+ if (board_type < GW_UNKNOWN) {
+ imx_iomux_v3_setup_multiple_pads(gw_gpio_pads,
+ ARRAY_SIZE(gw_gpio_pads));
+ imx_iomux_v3_setup_multiple_pads(gpio_cfg[board_type].gpio_pads,
+ gpio_cfg[board_type].num_pads);
+ }
+
+ return 0;
+}
+
+#if defined(CONFIG_DISPLAY_BOARDINFO_LATE)
+/*
+ * called during late init (after relocation and after board_init())
+ * by virtue of CONFIG_DISPLAY_BOARDINFO_LATE as we needed i2c initialized and
+ * EEPROM read.
+ */
+int checkboard(void)
+{
+ struct ventana_board_info *info = &ventana_info;
+ unsigned char buf[4];
+ const char *p;
+ int quiet; /* Quiet or minimal output mode */
+
+ quiet = 0;
+ p = getenv("quiet");
+ if (p)
+ quiet = simple_strtol(p, NULL, 10);
+ else
+ setenv("quiet", "0");
+
+ puts("\nGateworks Corporation Copyright 2014\n");
+ if (info->model[0]) {
+ printf("Model: %s\n", info->model);
+ printf("MFGDate: %02x-%02x-%02x%02x\n",
+ info->mfgdate[0], info->mfgdate[1],
+ info->mfgdate[2], info->mfgdate[3]);
+ printf("Serial:%d\n", info->serial);
+ } else {
+ puts("Invalid EEPROM - board will not function fully\n");
+ }
+ if (quiet)
+ return 0;
+
+ /* Display GSC firmware revision/CRC/status */
+ i2c_set_bus_num(I2C_GSC);
+ if (!gsc_i2c_read(GSC_SC_ADDR, GSC_SC_FWVER, 1, buf, 1)) {
+ printf("GSC: v%d", buf[0]);
+ if (!gsc_i2c_read(GSC_SC_ADDR, GSC_SC_STATUS, 1, buf, 4)) {
+ printf(" 0x%04x", buf[2] | buf[3]<<8); /* CRC */
+ printf(" 0x%02x", buf[0]); /* irq status */
+ }
+ puts("\n");
+ }
+ /* Display RTC */
+ if (!gsc_i2c_read(GSC_RTC_ADDR, 0x00, 1, buf, 4)) {
+ printf("RTC: %d\n",
+ buf[0] | buf[1]<<8 | buf[2]<<16 | buf[3]<<24);
+ }
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_CMD_BMODE
+/*
+ * BOOT_CFG1, BOOT_CFG2, BOOT_CFG3, BOOT_CFG4
+ * see Table 8-11 and Table 5-9
+ * BOOT_CFG1[7] = 1 (boot from NAND)
+ * BOOT_CFG1[5] = 0 - raw NAND
+ * BOOT_CFG1[4] = 0 - default pad settings
+ * BOOT_CFG1[3:2] = 00 - devices = 1
+ * BOOT_CFG1[1:0] = 00 - Row Address Cycles = 3
+ * BOOT_CFG2[4:3] = 00 - Boot Search Count = 2
+ * BOOT_CFG2[2:1] = 01 - Pages In Block = 64
+ * BOOT_CFG2[0] = 0 - Reset time 12ms
+ */
+static const struct boot_mode board_boot_modes[] = {
+ /* NAND: 64pages per block, 3 row addr cycles, 2 copies of FCB/DBBT */
+ { "nand", MAKE_CFGVAL(0x80, 0x02, 0x00, 0x00) },
+ { NULL, 0 },
+};
+#endif
+
+/* late init */
+int misc_init_r(void)
+{
+ struct ventana_board_info *info = &ventana_info;
+ unsigned char reg;
+
+ /* set env vars based on EEPROM data */
+ if (ventana_info.model[0]) {
+ char str[16], fdt[36];
+ char *p;
+ const char *cputype = "";
+ int i;
+
+ /*
+ * FDT name will be prefixed with CPU type. Three versions
+ * will be created each increasingly generic and bootloader
+ * env scripts will try loading each from most specific to
+ * least.
+ */
+ if (is_cpu_type(MXC_CPU_MX6Q))
+ cputype = "imx6q";
+ else if (is_cpu_type(MXC_CPU_MX6DL))
+ cputype = "imx6dl";
+ memset(str, 0, sizeof(str));
+ for (i = 0; i < (sizeof(str)-1) && info->model[i]; i++)
+ str[i] = tolower(info->model[i]);
+ if (!getenv("model"))
+ setenv("model", str);
+ if (!getenv("fdt_file")) {
+ sprintf(fdt, "%s-%s.dtb", cputype, str);
+ setenv("fdt_file", fdt);
+ }
+ p = strchr(str, '-');
+ if (p) {
+ *p++ = 0;
+
+ setenv("model_base", str);
+ if (!getenv("fdt_file1")) {
+ sprintf(fdt, "%s-%s.dtb", cputype, str);
+ setenv("fdt_file1", fdt);
+ }
+ str[4] = 'x';
+ str[5] = 'x';
+ str[6] = 0;
+ if (!getenv("fdt_file2")) {
+ sprintf(fdt, "%s-%s.dtb", cputype, str);
+ setenv("fdt_file2", fdt);
+ }
+ }
+
+ /* initialize env from EEPROM */
+ if (test_bit(EECONFIG_ETH0, info->config) &&
+ !getenv("ethaddr")) {
+ eth_setenv_enetaddr("ethaddr", info->mac0);
+ }
+ if (test_bit(EECONFIG_ETH1, info->config) &&
+ !getenv("eth1addr")) {
+ eth_setenv_enetaddr("eth1addr", info->mac1);
+ }
+
+ /* board serial-number */
+ sprintf(str, "%6d", info->serial);
+ setenv("serial#", str);
+ }
+
+ /* configure PFUZE100 PMIC (not used on all Ventana baseboards) */
+ if ((board_type == GW54xx || board_type == GW54proto) &&
+ !pmic_init(I2C_PMIC)) {
+ struct pmic *p = pmic_get("PFUZE100_PMIC");
+ u32 reg;
+ if (p && !pmic_probe(p)) {
+ pmic_reg_read(p, PFUZE100_DEVICEID, &reg);
+ printf("PMIC: PFUZE100 ID=0x%02x\n", reg);
+
+ /* Set VGEN1 to 1.5V and enable */
+ pmic_reg_read(p, PFUZE100_VGEN1VOL, &reg);
+ reg &= ~(LDO_VOL_MASK);
+ reg |= (LDOA_1_50V | LDO_EN);
+ pmic_reg_write(p, PFUZE100_VGEN1VOL, reg);
+
+ /* Set SWBST to 5.0V and enable */
+ pmic_reg_read(p, PFUZE100_SWBSTCON1, &reg);
+ reg &= ~(SWBST_MODE_MASK | SWBST_VOL_MASK);
+ reg |= (SWBST_5_00V | SWBST_MODE_AUTO);
+ pmic_reg_write(p, PFUZE100_SWBSTCON1, reg);
+ }
+ }
+
+ /* setup baseboard specific GPIO pinmux and config */
+ setup_board_gpio(board_type);
+
+#ifdef CONFIG_CMD_BMODE
+ add_board_boot_modes(board_boot_modes);
+#endif
+
+ /*
+ * The Gateworks System Controller implements a boot
+ * watchdog (always enabled) as a workaround for IMX6 boot related
+ * errata such as:
+ * ERR005768 - no fix
+ * ERR006282 - fixed in silicon r1.3
+ * ERR007117 - fixed in silicon r1.3
+ * ERR007220 - fixed in silicon r1.3
+ * see http://cache.freescale.com/files/32bit/doc/errata/IMX6DQCE.pdf
+ *
+ * Disable the boot watchdog and display/clear the timeout flag if set
+ */
+ i2c_set_bus_num(I2C_GSC);
+ if (!gsc_i2c_read(GSC_SC_ADDR, GSC_SC_CTRL1, 1, &reg, 1)) {
+ reg |= (1 << GSC_SC_CTRL1_WDDIS);
+ if (gsc_i2c_write(GSC_SC_ADDR, GSC_SC_CTRL1, 1, &reg, 1))
+ puts("Error: could not disable GSC Watchdog\n");
+ } else {
+ puts("Error: could not disable GSC Watchdog\n");
+ }
+ if (!gsc_i2c_read(GSC_SC_ADDR, GSC_SC_STATUS, 1, &reg, 1)) {
+ if (reg & (1 << GSC_SC_IRQ_WATCHDOG)) { /* watchdog timeout */
+ puts("GSC boot watchdog timeout detected");
+ reg &= ~(1 << GSC_SC_IRQ_WATCHDOG); /* clear flag */
+ gsc_i2c_write(GSC_SC_ADDR, GSC_SC_STATUS, 1, &reg, 1);
+ }
+ }
+
+ return 0;
+}
+
+#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
+
+/* FDT aliases associated with EEPROM config bits */
+const char *fdt_aliases[] = {
+ "ethernet0",
+ "ethernet1",
+ "hdmi_out",
+ "ahci0",
+ "pcie",
+ "ssi0",
+ "ssi1",
+ "lcd0",
+ "lvds0",
+ "lvds1",
+ "usb0",
+ "usb1",
+ "mmc0",
+ "mmc1",
+ "mmc2",
+ "mmc3",
+ "uart0",
+ "uart1",
+ "uart2",
+ "uart3",
+ "uart4",
+ "ipu0",
+ "ipu1",
+ "can0",
+ "mipi_dsi",
+ "mipi_csi",
+ "tzasc0",
+ "tzasc1",
+ "i2c0",
+ "i2c1",
+ "i2c2",
+ "vpu",
+ "csi0",
+ "csi1",
+ "caam",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "spi0",
+ "spi1",
+ "spi2",
+ "spi3",
+ "spi4",
+ "spi5",
+ NULL,
+ NULL,
+ "pps",
+ NULL,
+ NULL,
+ NULL,
+ "hdmi_in",
+ "cvbs_out",
+ "cvbs_in",
+ "nand",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+};
+
+/*
+ * called prior to booting kernel or by 'fdt boardsetup' command
+ *
+ * unless 'fdt_noauto' env var is set we will update the following in the DTB:
+ * - mtd partitions based on mtdparts/mtdids env
+ * - system-serial (board serial num from EEPROM)
+ * - board (full model from EEPROM)
+ * - peripherals removed from DTB if not loaded on board (per EEPROM config)
+ */
+void ft_board_setup(void *blob, bd_t *bd)
+{
+ int bit;
+ struct ventana_board_info *info = &ventana_info;
+ struct node_info nodes[] = {
+ { "sst,w25q256", MTD_DEV_TYPE_NOR, }, /* SPI flash */
+ { "fsl,imx6q-gpmi-nand", MTD_DEV_TYPE_NAND, }, /* NAND flash */
+ };
+ const char *model = getenv("model");
+
+ if (getenv("fdt_noauto")) {
+ puts(" Skiping ft_board_setup (fdt_noauto defined)\n");
+ return;
+ }
+
+ /* Update partition nodes using info from mtdparts env var */
+ puts(" Updating MTD partitions...\n");
+ fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
+
+ if (!model) {
+ puts("invalid board info: Leaving FDT fully enabled\n");
+ return;
+ }
+ printf(" Adjusting FDT per EEPROM for %s...\n", model);
+
+ /* board serial number */
+ fdt_setprop(blob, 0, "system-serial", getenv("serial#"),
+ strlen(getenv("serial#") + 1));
+
+ /* board (model contains model from device-tree) */
+ fdt_setprop(blob, 0, "board", info->model,
+ strlen((const char *)info->model) + 1);
+
+ /*
+ * Peripheral Config:
+ * remove nodes by alias path if EEPROM config tells us the
+ * peripheral is not loaded on the board.
+ */
+ for (bit = 0; bit < 64; bit++) {
+ if (!test_bit(bit, info->config))
+ fdt_del_node_and_alias(blob, fdt_aliases[bit]);
+ }
+}
+#endif /* defined(CONFIG_OF_FLAT_TREE) && defined(CONFIG_OF_BOARD_SETUP) */
+
diff --git a/board/gateworks/gw_ventana/gw_ventana.cfg b/board/gateworks/gw_ventana/gw_ventana.cfg
new file mode 100644
index 00000000000..27f09745c1b
--- /dev/null
+++ b/board/gateworks/gw_ventana/gw_ventana.cfg
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2013 Gateworks Corporation
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * Refer doc/README.imximage for more details about how-to configure
+ * and create imximage boot image
+ *
+ * The syntax is taken as close as possible with the kwbimage
+ */
+
+/* image version */
+IMAGE_VERSION 2
+
+/*
+ * Boot Device : one of
+ * spi, sd, nand, sata
+ */
+#ifdef CONFIG_SPI_FLASH
+BOOT_FROM spi
+#else
+BOOT_FROM nand
+#endif
+
+#define __ASSEMBLY__
+#include <config.h>
+#include "asm/arch/mx6-ddr.h"
+#include "asm/arch/iomux.h"
+#include "asm/arch/crm_regs.h"
+
+/* Memory configuration (size is overridden via eeprom config) */
+#include "../../boundary/nitrogen6x/ddr-setup.cfg"
+#if defined(CONFIG_MX6Q) && CONFIG_DDR_MB == 1024
+ #include "../../boundary/nitrogen6x/1066mhz_4x128mx16.cfg"
+#elif defined(CONFIG_MX6DL) && CONFIG_DDR_MB == 1024
+ #include "../../boundary/nitrogen6x/800mhz_4x128mx16.cfg"
+#elif defined(CONFIG_MX6DL) && CONFIG_DDR_MB == 512
+ #include "../../boundary/nitrogen6x/800mhz_2x128mx16.cfg"
+#elif defined(CONFIG_MX6Q) && CONFIG_DDR_MB == 512
+ #include "../../boundary/nitrogen6x/800mhz_2x128mx16.cfg"
+#else
+ #error "Unsupported CPU/Memory configuration"
+#endif
+#include "clocks.cfg"
diff --git a/board/gateworks/gw_ventana/ventana_eeprom.h b/board/gateworks/gw_ventana/ventana_eeprom.h
new file mode 100644
index 00000000000..d310bfd9942
--- /dev/null
+++ b/board/gateworks/gw_ventana/ventana_eeprom.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2013 Gateworks Corporation
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _VENTANA_EEPROM_
+#define _VENTANA_EEPROM_
+
+struct ventana_board_info {
+ u8 mac0[6]; /* 0x00: MAC1 */
+ u8 mac1[6]; /* 0x06: MAC2 */
+ u8 res0[12]; /* 0x0C: reserved */
+ u32 serial; /* 0x18: Serial Number (read only) */
+ u8 res1[4]; /* 0x1C: reserved */
+ u8 mfgdate[4]; /* 0x20: MFG date (read only) */
+ u8 res2[7]; /* 0x24 */
+ /* sdram config */
+ u8 sdram_size; /* 0x2B: enum (512,1024,2048) MB */
+ u8 sdram_speed; /* 0x2C: enum (100,133,166,200,267,333,400) MHz */
+ u8 sdram_width; /* 0x2D: enum (32,64) bit */
+ /* cpu config */
+ u8 cpu_speed; /* 0x2E: enum (800,1000,1200) MHz */
+ u8 cpu_type; /* 0x2F: enum (imx6q,imx6d,imx6dl,imx6s) */
+ u8 model[16]; /* 0x30: model string */
+ /* FLASH config */
+ u8 nand_flash_size; /* 0x40: enum (4,8,16,32,64,128) MB */
+ u8 spi_flash_size; /* 0x41: enum (4,8,16,32,64,128) MB */
+
+ /* Config1: SoC Peripherals */
+ u8 config[8]; /* 0x42: loading options */
+
+ u8 res3[4]; /* 0x4A */
+
+ u8 chksum[2]; /* 0x4E */
+};
+
+/* config bits */
+enum {
+ EECONFIG_ETH0,
+ EECONFIG_ETH1,
+ EECONFIG_HDMI_OUT,
+ EECONFIG_SATA,
+ EECONFIG_PCIE,
+ EECONFIG_SSI0,
+ EECONFIG_SSI1,
+ EECONFIG_LCD,
+ EECONFIG_LVDS0,
+ EECONFIG_LVDS1,
+ EECONFIG_USB0,
+ EECONFIG_USB1,
+ EECONFIG_SD0,
+ EECONFIG_SD1,
+ EECONFIG_SD2,
+ EECONFIG_SD3,
+ EECONFIG_UART0,
+ EECONFIG_UART1,
+ EECONFIG_UART2,
+ EECONFIG_UART3,
+ EECONFIG_UART4,
+ EECONFIG_IPU0,
+ EECONFIG_IPU1,
+ EECONFIG_FLEXCAN,
+ EECONFIG_MIPI_DSI,
+ EECONFIG_MIPI_CSI,
+ EECONFIG_TZASC0,
+ EECONFIG_TZASC1,
+ EECONFIG_I2C0,
+ EECONFIG_I2C1,
+ EECONFIG_I2C2,
+ EECONFIG_VPU,
+ EECONFIG_CSI0,
+ EECONFIG_CSI1,
+ EECONFIG_CAAM,
+ EECONFIG_MEZZ,
+ EECONFIG_RES1,
+ EECONFIG_RES2,
+ EECONFIG_RES3,
+ EECONFIG_RES4,
+ EECONFIG_ESPCI0,
+ EECONFIG_ESPCI1,
+ EECONFIG_ESPCI2,
+ EECONFIG_ESPCI3,
+ EECONFIG_ESPCI4,
+ EECONFIG_ESPCI5,
+ EECONFIG_RES5,
+ EECONFIG_RES6,
+ EECONFIG_GPS,
+ EECONFIG_SPIFL0,
+ EECONFIG_SPIFL1,
+ EECONFIG_GSPBATT,
+ EECONFIG_HDMI_IN,
+ EECONFIG_VID_OUT,
+ EECONFIG_VID_IN,
+ EECONFIG_NAND,
+ EECONFIG_RES8,
+ EECONFIG_RES9,
+ EECONFIG_RES10,
+ EECONFIG_RES11,
+ EECONFIG_RES12,
+ EECONFIG_RES13,
+ EECONFIG_RES14,
+ EECONFIG_RES15,
+};
+
+#endif