diff mbox

[U-Boot,V7] ARM: mx6: Add support for Kosagi Novena

Message ID 1412990082-8628-1-git-send-email-marex@denx.de
State Changes Requested
Delegated to: Stefano Babic
Headers show

Commit Message

Marek Vasut Oct. 11, 2014, 1:14 a.m. UTC
Add support for the Kosagi Novena board. Currently supported are:
- I2C busses
- FEC Ethernet
- MMC0, MMC1, Booting from MMC
- SATA
- USB ports
- USB Ethernet

Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Sean Cross <xobs@kosagi.com>
Cc: Nikolay Dimitrov <picmaster@mail.bg>
---
 arch/arm/Kconfig                 |   4 +
 board/kosagi/novena/Kconfig      |  18 ++
 board/kosagi/novena/Makefile     |  11 +
 board/kosagi/novena/novena.c     | 343 ++++++++++++++++++++++++
 board/kosagi/novena/novena_spl.c | 556 +++++++++++++++++++++++++++++++++++++++
 board/kosagi/novena/setup.cfg    |  47 ++++
 configs/novena_defconfig         |   4 +
 include/configs/imx6_spl.h       |   2 +-
 include/configs/novena.h         | 302 +++++++++++++++++++++
 9 files changed, 1286 insertions(+), 1 deletion(-)
 create mode 100644 board/kosagi/novena/Kconfig
 create mode 100644 board/kosagi/novena/Makefile
 create mode 100644 board/kosagi/novena/novena.c
 create mode 100644 board/kosagi/novena/novena_spl.c
 create mode 100644 board/kosagi/novena/setup.cfg
 create mode 100644 configs/novena_defconfig
 create mode 100644 include/configs/novena.h

V2: - Drop the tegra_keyboard_init() comment altogether
    - Immediatelly return from the SD controller probe function on failure
    - Rename PFUZE100_PMIC to just PFUZE100
    - Fix the IMX OTP support with CMD_FUSE
    - Enabling LVDS clock is still in place, since this is coming soon.
V3: - Zap rootpath builtin env
V4: - Zap the checkpatch issues
    - Update comments
V5: - Don't configure VGEN1
    - Set FPGA into reset in SPL
    - Drop ECSPI1 and add ECSPI3 mux
    - Drop UART1 and add UART3, UART4 muxes
    - Add separate mux option for the RGMII pins which doesn't set SPEED field
    - Move the configuration of RGMII after they were configured in GPIO mode
V6: - Drop 'string' prop from Kconfig
    - Zap uSD card detect
    - Add bigSD write-protect detection
    - Zap USB hub reset GPIO
V7: - Zap USB hub reset GPIO configuration
    - Remove unnecessary zeroing of GD in SPL

Comments

Fabio Estevam Oct. 11, 2014, 1:39 a.m. UTC | #1
Hi Marek,

On Fri, Oct 10, 2014 at 10:14 PM, Marek Vasut <marex@denx.de> wrote:

> +int board_early_init_f(void)
> +{
> +#if defined(CONFIG_VIDEO_IPUV3)
> +       setup_display();
> +#endif
> +
> +       /* Bring Ethernet PHY out of reset. */
> +       gpio_set_value(IMX_GPIO_NR(3, 23), 1);

No delay needed here prior to setting it to 1?

> +/* System configurations */
> +#define CONFIG_MX6
> +#define CONFIG_SYS_MX6_HCLK            24000000
> +#define CONFIG_SYS_MX6_CLK32           32768

These are the default values from
arch/arm/include/asm/arch-mx6/clock.h. You could just drop them.

> +/* Extra U-Boot environment. */
> +#define CONFIG_EXTRA_ENV_SETTINGS                                      \
> +       "fdt_high=0xffffffff\0"                                         \
> +       "initrd_high=0xffffffff\0"                                      \
> +       "consdev=ttymxc1\0"                                             \
> +       "baudrate=115200\0"                                             \
> +       "bootdev=/dev/mmcblk0p1\0"                                      \
> +       "rootdev=/dev/mmcblk0p2\0"                                      \
> +       "netdev=eth0\0"                                                 \
> +       "rootpath=/opt/eldk-5.5/armv7a-hf/rootfs-qte-sdk\0"             \

Hardcoded root path again? I thought we already discussed this in
previous versions of this patch.
Fabio Estevam Oct. 11, 2014, 1:44 a.m. UTC | #2
On Fri, Oct 10, 2014 at 10:14 PM, Marek Vasut <marex@denx.de> wrote:

> +/* PCI express */
> +#undef CONFIG_CMD_PCI  /* Disable to prevent Linux from hanging on MX6 */

This has been fixed recently by this commit:

https://git.kernel.org/cgit/linux/kernel/git/next/linux-next.git/commit/drivers/pci/host/pci-imx6.c?id=3e3e406e3807235906ee0b7c697664ea6dfd88de
Nikolay Dimitrov Oct. 11, 2014, 5:01 a.m. UTC | #3
Hi Fabio,

On 10/11/2014 04:39 AM, Fabio Estevam wrote:
> Hi Marek,
>
> On Fri, Oct 10, 2014 at 10:14 PM, Marek Vasut <marex@denx.de> wrote:
>
>> +int board_early_init_f(void)
>> +{
>> +#if defined(CONFIG_VIDEO_IPUV3)
>> +       setup_display();
>> +#endif
>> +
>> +       /* Bring Ethernet PHY out of reset. */
>> +       gpio_set_value(IMX_GPIO_NR(3, 23), 1);
>
> No delay needed here prior to setting it to 1?

We had some discussions about the PHY reset sequence and timing, but 
still not a common opinion, so I suggested to leave this fix for a 
consequent patch.

Regards,
Nikolay
Nikolay Dimitrov Oct. 11, 2014, 5:10 a.m. UTC | #4
Hi Marek,

On 10/11/2014 04:14 AM, Marek Vasut wrote:
> Add support for the Kosagi Novena board. Currently supported are:
> - I2C busses
> - FEC Ethernet
> - MMC0, MMC1, Booting from MMC
> - SATA
> - USB ports
> - USB Ethernet
>
> Signed-off-by: Marek Vasut <marex@denx.de>
> Cc: Stefano Babic <sbabic@denx.de>
> Cc: Sean Cross <xobs@kosagi.com>
> Cc: Nikolay Dimitrov <picmaster@mail.bg>
> ---
>   arch/arm/Kconfig                 |   4 +
>   board/kosagi/novena/Kconfig      |  18 ++
>   board/kosagi/novena/Makefile     |  11 +
>   board/kosagi/novena/novena.c     | 343 ++++++++++++++++++++++++
>   board/kosagi/novena/novena_spl.c | 556 +++++++++++++++++++++++++++++++++++++++
>   board/kosagi/novena/setup.cfg    |  47 ++++
>   configs/novena_defconfig         |   4 +
>   include/configs/imx6_spl.h       |   2 +-
>   include/configs/novena.h         | 302 +++++++++++++++++++++
>   9 files changed, 1286 insertions(+), 1 deletion(-)
>   create mode 100644 board/kosagi/novena/Kconfig
>   create mode 100644 board/kosagi/novena/Makefile
>   create mode 100644 board/kosagi/novena/novena.c
>   create mode 100644 board/kosagi/novena/novena_spl.c
>   create mode 100644 board/kosagi/novena/setup.cfg
>   create mode 100644 configs/novena_defconfig
>   create mode 100644 include/configs/novena.h
>
> V2: - Drop the tegra_keyboard_init() comment altogether
>      - Immediatelly return from the SD controller probe function on failure
>      - Rename PFUZE100_PMIC to just PFUZE100
>      - Fix the IMX OTP support with CMD_FUSE
>      - Enabling LVDS clock is still in place, since this is coming soon.
> V3: - Zap rootpath builtin env
> V4: - Zap the checkpatch issues
>      - Update comments
> V5: - Don't configure VGEN1
>      - Set FPGA into reset in SPL
>      - Drop ECSPI1 and add ECSPI3 mux
>      - Drop UART1 and add UART3, UART4 muxes
>      - Add separate mux option for the RGMII pins which doesn't set SPEED field
>      - Move the configuration of RGMII after they were configured in GPIO mode
> V6: - Drop 'string' prop from Kconfig
>      - Zap uSD card detect
>      - Add bigSD write-protect detection
>      - Zap USB hub reset GPIO
> V7: - Zap USB hub reset GPIO configuration
>      - Remove unnecessary zeroing of GD in SPL
>
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 106aed9..4da1923 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -411,6 +411,9 @@ config TARGET_GW_VENTANA
>   config TARGET_HUMMINGBOARD
>   	bool "Support hummingboard"
>
> +config TARGET_KOSAGI_NOVENA
> +	bool "Support Kosagi Novena"
> +
>   config TARGET_TQMA6
>   	bool "TQ Systems TQMa6 board"
>
> @@ -637,6 +640,7 @@ source "board/imx31_phycore/Kconfig"
>   source "board/isee/igep0033/Kconfig"
>   source "board/jornada/Kconfig"
>   source "board/karo/tx25/Kconfig"
> +source "board/kosagi/novena/Kconfig"
>   source "board/logicpd/imx27lite/Kconfig"
>   source "board/logicpd/imx31_litekit/Kconfig"
>   source "board/mpl/vcma9/Kconfig"
> diff --git a/board/kosagi/novena/Kconfig b/board/kosagi/novena/Kconfig
> new file mode 100644
> index 0000000..4ba6399
> --- /dev/null
> +++ b/board/kosagi/novena/Kconfig
> @@ -0,0 +1,18 @@
> +if TARGET_KOSAGI_NOVENA
> +
> +config SYS_CPU
> +	default "armv7"
> +
> +config SYS_BOARD
> +	default "novena"
> +
> +config SYS_VENDOR
> +	default "kosagi"
> +
> +config SYS_SOC
> +	default "mx6"
> +
> +config SYS_CONFIG_NAME
> +	default "novena"
> +
> +endif
> diff --git a/board/kosagi/novena/Makefile b/board/kosagi/novena/Makefile
> new file mode 100644
> index 0000000..6fba177
> --- /dev/null
> +++ b/board/kosagi/novena/Makefile
> @@ -0,0 +1,11 @@
> +#
> +# Copyright (C) 2014 Marek Vasut <marex@denx.de>
> +#
> +# SPDX-License-Identifier:	GPL-2.0+
> +#
> +
> +ifdef CONFIG_SPL_BUILD
> +obj-y	:= novena_spl.o
> +else
> +obj-y	:= novena.o
> +endif
> diff --git a/board/kosagi/novena/novena.c b/board/kosagi/novena/novena.c
> new file mode 100644
> index 0000000..2361a3c
> --- /dev/null
> +++ b/board/kosagi/novena/novena.c
> @@ -0,0 +1,343 @@
> +/*
> + * Novena board support
> + *
> + * Copyright (C) 2014 Marek Vasut <marex@denx.de>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <asm/errno.h>
> +#include <asm/gpio.h>
> +#include <asm/io.h>
> +#include <asm/arch/clock.h>
> +#include <asm/arch/crm_regs.h>
> +#include <asm/arch/imx-regs.h>
> +#include <asm/arch/iomux.h>
> +#include <asm/arch/mxc_hdmi.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/imx-common/sata.h>
> +#include <asm/imx-common/video.h>
> +#include <fsl_esdhc.h>
> +#include <i2c.h>
> +#include <input.h>
> +#include <ipu_pixfmt.h>
> +#include <linux/fb.h>
> +#include <linux/input.h>
> +#include <malloc.h>
> +#include <micrel.h>
> +#include <miiphy.h>
> +#include <mmc.h>
> +#include <netdev.h>
> +#include <power/pmic.h>
> +#include <power/pfuze100_pmic.h>
> +#include <stdio_dev.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +#define NOVENA_BUTTON_GPIO	IMX_GPIO_NR(4, 14)
> +#define NOVENA_SD_WP		IMX_GPIO_NR(1, 2)
> +#define NOVENA_SD_CD		IMX_GPIO_NR(1, 4)
> +
> +/*
> + * GPIO button
> + */
> +#ifdef CONFIG_KEYBOARD
> +static struct input_config button_input;
> +
> +static int novena_gpio_button_read_keys(struct input_config *input)
> +{
> +	int key = KEY_ENTER;
> +	if (gpio_get_value(NOVENA_BUTTON_GPIO))
> +		return 0;
> +	input_send_keycodes(&button_input, &key, 1);
> +	return 1;
> +}
> +
> +static int novena_gpio_button_getc(struct stdio_dev *dev)
> +{
> +	return input_getc(&button_input);
> +}
> +
> +static int novena_gpio_button_tstc(struct stdio_dev *dev)
> +{
> +	return input_tstc(&button_input);
> +}
> +
> +static int novena_gpio_button_init(struct stdio_dev *dev)
> +{
> +	gpio_direction_input(NOVENA_BUTTON_GPIO);
> +	input_set_delays(&button_input, 250, 250);
> +	return 0;
> +}
> +
> +int drv_keyboard_init(void)
> +{
> +	int error;
> +	struct stdio_dev dev = {
> +		.name	= "button",
> +		.flags	= DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM,
> +		.start	= novena_gpio_button_init,
> +		.getc	= novena_gpio_button_getc,
> +		.tstc	= novena_gpio_button_tstc,
> +	};
> +
> +	error = input_init(&button_input, 0);
> +	if (error) {
> +		debug("%s: Cannot set up input\n", __func__);
> +		return -1;
> +	}
> +	button_input.read_keys = novena_gpio_button_read_keys;
> +
> +	error = input_stdio_register(&dev);
> +	if (error)
> +		return error;
> +
> +	return 0;
> +}
> +#endif
> +
> +/*
> + * SDHC
> + */
> +#ifdef CONFIG_FSL_ESDHC
> +static struct fsl_esdhc_cfg usdhc_cfg[] = {
> +	{ USDHC3_BASE_ADDR, 0, 4 },	/* Micro SD */
> +	{ USDHC2_BASE_ADDR, 0, 4 },	/* Big SD */
> +};
> +
> +int board_mmc_getcd(struct mmc *mmc)
> +{
> +	struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
> +
> +	/* There is no CD for a microSD card, assume always present. */
> +	if (cfg->esdhc_base == USDHC3_BASE_ADDR)
> +		return 1;
> +	else
> +		return !gpio_get_value(NOVENA_SD_CD);
> +}
> +
> +int board_mmc_getwp(struct mmc *mmc)
> +{
> +	struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
> +
> +	/* There is no WP for a microSD card, assume always read-write. */
> +	if (cfg->esdhc_base == USDHC3_BASE_ADDR)
> +		return 0;
> +	else
> +		return gpio_get_value(NOVENA_SD_WP);
> +}
> +
> +
> +int board_mmc_init(bd_t *bis)
> +{
> +	s32 status = 0;
> +	int index;
> +
> +	usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
> +	usdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
> +
> +	/* Big SD write-protect and card-detect */
> +	gpio_direction_input(NOVENA_SD_WP);
> +	gpio_direction_input(NOVENA_SD_CD);
> +
> +	for (index = 0; index < ARRAY_SIZE(usdhc_cfg); index++) {
> +		status = fsl_esdhc_initialize(bis, &usdhc_cfg[index]);
> +		if (status)
> +			return status;
> +	}
> +
> +	return status;
> +}
> +#endif
> +
> +/*
> + * Video over HDMI
> + */
> +#if defined(CONFIG_VIDEO_IPUV3)
> +static void enable_hdmi(struct display_info_t const *dev)
> +{
> +	imx_enable_hdmi_phy();
> +}
> +
> +struct display_info_t const displays[] = {
> +	{
> +		/* HDMI Output */
> +		.bus	= -1,
> +		.addr	= 0,
> +		.pixfmt	= IPU_PIX_FMT_RGB24,
> +		.detect	= detect_hdmi,
> +		.enable	= enable_hdmi,
> +		.mode	= {
> +			.name           = "HDMI",
> +			.refresh        = 60,
> +			.xres           = 1024,
> +			.yres           = 768,
> +			.pixclock       = 15385,
> +			.left_margin    = 220,
> +			.right_margin   = 40,
> +			.upper_margin   = 21,
> +			.lower_margin   = 7,
> +			.hsync_len      = 60,
> +			.vsync_len      = 10,
> +			.sync           = FB_SYNC_EXT,
> +			.vmode          = FB_VMODE_NONINTERLACED
> +		}
> +	}
> +};
> +
> +size_t display_count = ARRAY_SIZE(displays);
> +
> +static void setup_display(void)
> +{
> +	struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
> +	struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
> +
> +	enable_ipu_clock();
> +	imx_setup_hdmi();
> +
> +	/* Turn on LDB0,IPU,IPU DI0 clocks */
> +	setbits_le32(&mxc_ccm->CCGR3, MXC_CCM_CCGR3_LDB_DI0_MASK);
> +
> +	/* set LDB0, LDB1 clk select to 011/011 */
> +	clrsetbits_le32(&mxc_ccm->cs2cdr,
> +			MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK |
> +			MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_MASK,
> +			(3 << MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET) |
> +			(3 << MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_OFFSET));
> +
> +	setbits_le32(&mxc_ccm->cscmr2, MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV);
> +
> +	setbits_le32(&mxc_ccm->chsccdr, CHSCCDR_CLK_SEL_LDB_DI0 <<
> +		     MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET);
> +
> +	writel(IOMUXC_GPR2_BGREF_RRMODE_EXTERNAL_RES |
> +	       IOMUXC_GPR2_DI1_VS_POLARITY_ACTIVE_HIGH |
> +	       IOMUXC_GPR2_DI0_VS_POLARITY_ACTIVE_LOW |
> +	       IOMUXC_GPR2_BIT_MAPPING_CH1_SPWG |
> +	       IOMUXC_GPR2_DATA_WIDTH_CH1_18BIT |
> +	       IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG |
> +	       IOMUXC_GPR2_DATA_WIDTH_CH0_18BIT |
> +	       IOMUXC_GPR2_LVDS_CH1_MODE_DISABLED |
> +	       IOMUXC_GPR2_LVDS_CH0_MODE_ENABLED_DI0,
> +	       &iomux->gpr[2]);
> +
> +	clrsetbits_le32(&iomux->gpr[3], IOMUXC_GPR3_LVDS0_MUX_CTL_MASK,
> +			IOMUXC_GPR3_MUX_SRC_IPU1_DI0 <<
> +			IOMUXC_GPR3_LVDS0_MUX_CTL_OFFSET);
> +}
> +#endif
> +
> +int board_early_init_f(void)
> +{
> +#if defined(CONFIG_VIDEO_IPUV3)
> +	setup_display();
> +#endif
> +
> +	/* Bring Ethernet PHY out of reset. */
> +	gpio_set_value(IMX_GPIO_NR(3, 23), 1);
> +
> +	return 0;
> +}
> +
> +int board_init(void)
> +{
> +	/* address of boot parameters */
> +	gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
> +
> +#ifdef CONFIG_CMD_SATA
> +	setup_sata();
> +#endif
> +
> +	return 0;
> +}
> +
> +int checkboard(void)
> +{
> +	puts("Board: Novena 4x\n");
> +	return 0;
> +}
> +
> +int dram_init(void)
> +{
> +	gd->ram_size = imx_ddr_size();
> +	return 0;
> +}
> +
> +/* setup board specific PMIC */
> +int power_init_board(void)
> +{
> +	struct pmic *p;
> +	u32 reg;
> +	int ret;
> +
> +	power_pfuze100_init(1);
> +	p = pmic_get("PFUZE100");
> +	if (!p)
> +		return -EINVAL;
> +
> +	ret = pmic_probe(p);
> +	if (ret)
> +		return ret;
> +
> +	pmic_reg_read(p, PFUZE100_DEVICEID, &reg);
> +	printf("PMIC:  PFUZE100 ID=0x%02x\n", reg);
> +
> +	/* Set SWBST to 5.0V and enable (for USB) */
> +	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);
> +
> +	return 0;
> +}
> +
> +/* EEPROM configuration data */
> +struct novena_eeprom_data {
> +	uint8_t		signature[6];
> +	uint8_t		version;
> +	uint8_t		reserved;
> +	uint32_t	serial;
> +	uint8_t		mac[6];
> +	uint16_t	features;
> +};
> +
> +int misc_init_r(void)
> +{
> +	struct novena_eeprom_data data;
> +	uchar *datap = (uchar *)&data;
> +	const char *signature = "Novena";
> +	int ret;
> +
> +	/* If 'ethaddr' is already set, do nothing. */
> +	if (getenv("ethaddr"))
> +		return 0;
> +
> +	/* EEPROM is at bus 2. */
> +	ret = i2c_set_bus_num(2);
> +	if (ret) {
> +		puts("Cannot select EEPROM I2C bus.\n");
> +		return 0;
> +	}
> +
> +	/* EEPROM is at address 0x56. */
> +	ret = eeprom_read(0x56, 0, datap, sizeof(data));
> +	if (ret) {
> +		puts("Cannot read I2C EEPROM.\n");
> +		return 0;
> +	}
> +
> +	/* Check EEPROM signature. */
> +	if (memcmp(data.signature, signature, 6)) {
> +		puts("Invalid I2C EEPROM signature.\n");
> +		return 0;
> +	}
> +
> +	/* Set ethernet address from EEPROM. */
> +	eth_setenv_enetaddr("ethaddr", data.mac);
> +
> +	return ret;
> +}
> diff --git a/board/kosagi/novena/novena_spl.c b/board/kosagi/novena/novena_spl.c
> new file mode 100644
> index 0000000..a8389d9
> --- /dev/null
> +++ b/board/kosagi/novena/novena_spl.c
> @@ -0,0 +1,556 @@
> +/*
> + * Novena SPL
> + *
> + * Copyright (C) 2014 Marek Vasut <marex@denx.de>
> + *
> + * SPDX-License-Identifier:     GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <asm/io.h>
> +#include <asm/arch/clock.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/gpio.h>
> +#include <asm/imx-common/boot_mode.h>
> +#include <asm/imx-common/iomux-v3.h>
> +#include <asm/imx-common/mxc_i2c.h>
> +#include <i2c.h>
> +#include <mmc.h>
> +#include <fsl_esdhc.h>
> +#include <spl.h>
> +
> +#include <asm/arch/mx6-ddr.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +#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 RGMII_PAD_CTRL						\
> +	(PAD_CTL_PKE | PAD_CTL_PUE |				\
> +	PAD_CTL_PUS_100K_UP | 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 I2C_PAD_CTRL						\
> +	(PAD_CTL_PKE | PAD_CTL_PUE |				\
> +	PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_LOW |		\
> +	PAD_CTL_DSE_240ohm  | PAD_CTL_HYS |			\
> +	PAD_CTL_ODE)
> +
> +#define BUTTON_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 PC MUX_PAD_CTRL(I2C_PAD_CTRL)
> +
> +#define NOVENA_AUDIO_PWRON		IMX_GPIO_NR(5, 17)
> +#define NOVENA_FPGA_RESET_N_GPIO	IMX_GPIO_NR(5, 7)
> +#define NOVENA_HDMI_GHOST_HPD		IMX_GPIO_NR(5, 4)
> +#define NOVENA_PCIE_RESET_GPIO		IMX_GPIO_NR(3, 29)
> +#define NOVENA_PCIE_POWER_ON_GPIO	IMX_GPIO_NR(7, 12)
> +#define NOVENA_PCIE_WAKE_UP_GPIO	IMX_GPIO_NR(3, 22)
> +#define NOVENA_PCIE_DISABLE_GPIO	IMX_GPIO_NR(2, 16)
> +
> +/*
> + * Audio
> + */
> +static iomux_v3_cfg_t audio_pads[] = {
> +	/* AUD_PWRON */
> +	MX6_PAD_DISP0_DAT23__GPIO5_IO17 | MUX_PAD_CTRL(NO_PAD_CTRL),
> +};
> +
> +static void novena_spl_setup_iomux_audio(void)
> +{
> +	imx_iomux_v3_setup_multiple_pads(audio_pads, ARRAY_SIZE(audio_pads));
> +	gpio_direction_output(NOVENA_AUDIO_PWRON, 1);
> +}
> +
> +/*
> + * ENET
> + */
> +static iomux_v3_cfg_t enet_pads1[] = {
> +	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(RGMII_PAD_CTRL),
> +	MX6_PAD_RGMII_TD0__RGMII_TD0		| MUX_PAD_CTRL(RGMII_PAD_CTRL),
> +	MX6_PAD_RGMII_TD1__RGMII_TD1		| MUX_PAD_CTRL(RGMII_PAD_CTRL),
> +	MX6_PAD_RGMII_TD2__RGMII_TD2		| MUX_PAD_CTRL(RGMII_PAD_CTRL),
> +	MX6_PAD_RGMII_TD3__RGMII_TD3		| MUX_PAD_CTRL(RGMII_PAD_CTRL),
> +	MX6_PAD_RGMII_TX_CTL__RGMII_TX_CTL	| MUX_PAD_CTRL(RGMII_PAD_CTRL),
> +	MX6_PAD_ENET_REF_CLK__ENET_TX_CLK	| MUX_PAD_CTRL(ENET_PAD_CTRL),
> +	/* pin 35 - 1 (PHY_AD2) on reset */
> +	MX6_PAD_RGMII_RXC__GPIO6_IO30		| MUX_PAD_CTRL(NO_PAD_CTRL),
> +	/* pin 32 - 1 - (MODE0) all */
> +	MX6_PAD_RGMII_RD0__GPIO6_IO25		| MUX_PAD_CTRL(NO_PAD_CTRL),
> +	/* pin 31 - 1 - (MODE1) all */
> +	MX6_PAD_RGMII_RD1__GPIO6_IO27		| MUX_PAD_CTRL(NO_PAD_CTRL),
> +	/* pin 28 - 1 - (MODE2) all */
> +	MX6_PAD_RGMII_RD2__GPIO6_IO28		| MUX_PAD_CTRL(NO_PAD_CTRL),
> +	/* pin 27 - 1 - (MODE3) all */
> +	MX6_PAD_RGMII_RD3__GPIO6_IO29		| MUX_PAD_CTRL(NO_PAD_CTRL),
> +	/* pin 33 - 1 - (CLK125_EN) 125Mhz clockout enabled */
> +	MX6_PAD_RGMII_RX_CTL__GPIO6_IO24	| MUX_PAD_CTRL(NO_PAD_CTRL),
> +	/* pin 42 PHY nRST */
> +	MX6_PAD_EIM_D23__GPIO3_IO23		| MUX_PAD_CTRL(NO_PAD_CTRL),
> +};
> +
> +static iomux_v3_cfg_t enet_pads2[] = {
> +	MX6_PAD_RGMII_RXC__RGMII_RXC		| MUX_PAD_CTRL(RGMII_PAD_CTRL),
> +	MX6_PAD_RGMII_RD0__RGMII_RD0		| MUX_PAD_CTRL(RGMII_PAD_CTRL),
> +	MX6_PAD_RGMII_RD1__RGMII_RD1		| MUX_PAD_CTRL(RGMII_PAD_CTRL),
> +	MX6_PAD_RGMII_RD2__RGMII_RD2		| MUX_PAD_CTRL(RGMII_PAD_CTRL),
> +	MX6_PAD_RGMII_RD3__RGMII_RD3		| MUX_PAD_CTRL(RGMII_PAD_CTRL),
> +	MX6_PAD_RGMII_RX_CTL__RGMII_RX_CTL	| MUX_PAD_CTRL(RGMII_PAD_CTRL),
> +};
> +
> +static void novena_spl_setup_iomux_enet(void)
> +{
> +	imx_iomux_v3_setup_multiple_pads(enet_pads1, ARRAY_SIZE(enet_pads1));
> +
> +	gpio_direction_output(IMX_GPIO_NR(3, 23), 0);
> +	gpio_direction_output(IMX_GPIO_NR(6, 30), 1);
> +	gpio_direction_output(IMX_GPIO_NR(6, 25), 1);
> +	gpio_direction_output(IMX_GPIO_NR(6, 27), 1);
> +	gpio_direction_output(IMX_GPIO_NR(6, 28), 1);
> +	gpio_direction_output(IMX_GPIO_NR(6, 29), 1);
> +	gpio_direction_output(IMX_GPIO_NR(6, 24), 1);
> +
> +	imx_iomux_v3_setup_multiple_pads(enet_pads2, ARRAY_SIZE(enet_pads2));
> +}
> +
> +/*
> + * FPGA
> + */
> +static iomux_v3_cfg_t fpga_pads[] = {
> +	/* FPGA_RESET_N */
> +	MX6_PAD_DISP0_DAT13__GPIO5_IO07 | MUX_PAD_CTRL(NO_PAD_CTRL),
> +};
> +
> +static void novena_spl_setup_iomux_fpga(void)
> +{
> +	imx_iomux_v3_setup_multiple_pads(fpga_pads, ARRAY_SIZE(fpga_pads));
> +	gpio_direction_output(NOVENA_FPGA_RESET_N_GPIO, 0);
> +}
> +
> +/*
> + * GPIO Button
> + */
> +static iomux_v3_cfg_t button_pads[] = {
> +	/* Debug */
> +	MX6_PAD_KEY_COL4__GPIO4_IO14 | MUX_PAD_CTRL(BUTTON_PAD_CTRL),
> +};
> +
> +static void novena_spl_setup_iomux_buttons(void)
> +{
> +	imx_iomux_v3_setup_multiple_pads(button_pads, ARRAY_SIZE(button_pads));
> +}
> +
> +/*
> + * I2C
> + */
> +/*
> + * I2C1:
> + *  0x1d ... MMA7455L
> + *  0x30 ... SO-DIMM temp sensor
> + *  0x44 ... STMPE610
> + *  0x50 ... SO-DIMM ID
> + */
> +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:
> + *  0x08 ... PMIC
> + *  0x3a ... HDMI DCC
> + *  0x50 ... HDMI DCC
> + */
> +static struct i2c_pads_info i2c_pad_info1 = {
> +	.scl = {
> +		.i2c_mode	= MX6_PAD_EIM_EB2__I2C2_SCL | PC,
> +		.gpio_mode	= MX6_PAD_EIM_EB2__GPIO2_IO30 | PC,
> +		.gp		= IMX_GPIO_NR(2, 30)
> +	},
> +	.sda = {
> +		.i2c_mode	= MX6_PAD_EIM_D16__I2C2_SDA | PC,
> +		.gpio_mode	= MX6_PAD_EIM_D16__GPIO3_IO16 | PC,
> +		.gp		= IMX_GPIO_NR(3, 16)
> +	}
> +};
> +
> +/*
> + * I2C3:
> + *  0x11 ... ES8283
> + *  0x50 ... LCD EDID
> + *  0x56 ... EEPROM
> + */
> +static struct i2c_pads_info i2c_pad_info2 = {
> +	.scl = {
> +		.i2c_mode	= MX6_PAD_EIM_D17__I2C3_SCL | PC,
> +		.gpio_mode	= MX6_PAD_EIM_D17__GPIO3_IO17 | PC,
> +		.gp		= IMX_GPIO_NR(3, 17)
> +	},
> +	.sda = {
> +		.i2c_mode	= MX6_PAD_EIM_D18__I2C3_SDA | PC,
> +		.gpio_mode	= MX6_PAD_EIM_D18__GPIO3_IO18 | PC,
> +		.gp		= IMX_GPIO_NR(3, 18)
> +	}
> +};
> +
> +static void novena_spl_setup_iomux_i2c(void)
> +{
> +	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);
> +}
> +
> +/*
> + * PCI express
> + */
> +#ifdef CONFIG_CMD_PCI
> +static iomux_v3_cfg_t pcie_pads[] = {
> +	/* "Reset" pin */
> +	MX6_PAD_EIM_D29__GPIO3_IO29 | MUX_PAD_CTRL(NO_PAD_CTRL),
> +	/* "Power on" pin */
> +	MX6_PAD_GPIO_17__GPIO7_IO12 | MUX_PAD_CTRL(NO_PAD_CTRL),
> +	/* "Wake up" pin (input) */
> +	MX6_PAD_EIM_D22__GPIO3_IO22 | MUX_PAD_CTRL(NO_PAD_CTRL),
> +	/* "Disable endpoint" (rfkill) pin */
> +	MX6_PAD_EIM_A22__GPIO2_IO16 | MUX_PAD_CTRL(NO_PAD_CTRL),
> +};
> +
> +static void novena_spl_setup_iomux_pcie(void)
> +{
> +	imx_iomux_v3_setup_multiple_pads(pcie_pads, ARRAY_SIZE(pcie_pads));
> +
> +	/* Ensure PCIe is powered down */
> +	gpio_direction_output(NOVENA_PCIE_POWER_ON_GPIO, 0);
> +
> +	/* Put the card into reset */
> +	gpio_direction_output(NOVENA_PCIE_RESET_GPIO, 0);
> +
> +	/* Input signal to wake system from mPCIe card */
> +	gpio_direction_input(NOVENA_PCIE_WAKE_UP_GPIO);
> +
> +	/* Drive RFKILL high, to ensure the radio is turned on */
> +	gpio_direction_output(NOVENA_PCIE_DISABLE_GPIO, 1);
> +}
> +#else
> +static inline void novena_spl_setup_iomux_pcie(void) {}
> +#endif
> +
> +/*
> + * SDHC
> + */
> +static iomux_v3_cfg_t usdhc2_pads[] = {
> +	MX6_PAD_SD2_CLK__SD2_CLK    | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD2_CMD__SD2_CMD    | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD2_DAT0__SD2_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD2_DAT1__SD2_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD2_DAT2__SD2_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD2_DAT3__SD2_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_GPIO_2__GPIO1_IO02  | MUX_PAD_CTRL(NO_PAD_CTRL), /* WP */
> +	MX6_PAD_GPIO_4__GPIO1_IO04  | MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */
> +};
> +
> +static iomux_v3_cfg_t 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),
> +};
> +
> +static void novena_spl_setup_iomux_sdhc(void)
> +{
> +	imx_iomux_v3_setup_multiple_pads(usdhc2_pads, ARRAY_SIZE(usdhc2_pads));
> +	imx_iomux_v3_setup_multiple_pads(usdhc3_pads, ARRAY_SIZE(usdhc3_pads));
> +
> +	/* Big SD write-protect and card-detect */
> +	gpio_direction_input(IMX_GPIO_NR(1, 2));
> +	gpio_direction_input(IMX_GPIO_NR(1, 4));
> +}
> +
> +/*
> + * SPI
> + */
> +#ifdef CONFIG_MXC_SPI
> +static iomux_v3_cfg_t ecspi3_pads[] = {
> +	/* SS1 */
> +	MX6_PAD_DISP0_DAT1__ECSPI3_MOSI | MUX_PAD_CTRL(SPI_PAD_CTRL),
> +	MX6_PAD_DISP0_DAT2__ECSPI3_MISO | MUX_PAD_CTRL(SPI_PAD_CTRL),
> +	MX6_PAD_DISP0_DAT0__ECSPI3_SCLK | MUX_PAD_CTRL(SPI_PAD_CTRL),
> +	MX6_PAD_DISP0_DAT3__GPIO4_IO24 | MUX_PAD_CTRL(SPI_PAD_CTRL),
> +	MX6_PAD_DISP0_DAT4__GPIO4_IO25 | MUX_PAD_CTRL(SPI_PAD_CTRL),
> +	MX6_PAD_DISP0_DAT5__GPIO4_IO26 | MUX_PAD_CTRL(SPI_PAD_CTRL),
> +	MX6_PAD_DISP0_DAT7__ECSPI3_RDY | MUX_PAD_CTRL(SPI_PAD_CTRL),
> +};
> +
> +static void novena_spl_setup_iomux_spi(void)
> +{
> +	imx_iomux_v3_setup_multiple_pads(ecspi3_pads, ARRAY_SIZE(ecspi3_pads));
> +	/* De-assert the nCS */
> +	gpio_direction_output(MX6_PAD_DISP0_DAT3__GPIO4_IO24, 1);
> +	gpio_direction_output(MX6_PAD_DISP0_DAT4__GPIO4_IO25, 1);
> +	gpio_direction_output(MX6_PAD_DISP0_DAT5__GPIO4_IO26, 1);
> +}
> +#else
> +static void novena_spl_setup_iomux_spi(void) {}
> +#endif
> +
> +/*
> + * UART
> + */
> +static iomux_v3_cfg_t const uart2_pads[] = {
> +	MX6_PAD_EIM_D26__UART2_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
> +	MX6_PAD_EIM_D27__UART2_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
> +};
> +
> +static iomux_v3_cfg_t const uart3_pads[] = {
> +	MX6_PAD_EIM_D24__UART3_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
> +	MX6_PAD_EIM_D25__UART3_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
> +};
> +
> +static iomux_v3_cfg_t const uart4_pads[] = {
> +	MX6_PAD_KEY_COL0__UART4_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
> +	MX6_PAD_KEY_ROW0__UART4_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
> +	MX6_PAD_CSI0_DAT16__UART4_CTS_B | MUX_PAD_CTRL(UART_PAD_CTRL),
> +	MX6_PAD_CSI0_DAT17__UART4_RTS_B | MUX_PAD_CTRL(UART_PAD_CTRL),
> +
> +};
> +
> +static void novena_spl_setup_iomux_uart(void)
> +{
> +	imx_iomux_v3_setup_multiple_pads(uart2_pads, ARRAY_SIZE(uart2_pads));
> +	imx_iomux_v3_setup_multiple_pads(uart3_pads, ARRAY_SIZE(uart3_pads));
> +	imx_iomux_v3_setup_multiple_pads(uart4_pads, ARRAY_SIZE(uart4_pads));
> +}
> +
> +/*
> + * Video
> + */
> +#ifdef CONFIG_VIDEO
> +static iomux_v3_cfg_t hdmi_pads[] = {
> +	/* "Ghost HPD" pin */
> +	MX6_PAD_EIM_A24__GPIO5_IO04 | MUX_PAD_CTRL(NO_PAD_CTRL),
> +};
> +
> +static void novena_spl_setup_iomux_video(void)
> +{
> +	imx_iomux_v3_setup_multiple_pads(hdmi_pads, ARRAY_SIZE(hdmi_pads));
> +	gpio_direction_input(NOVENA_HDMI_GHOST_HPD);
> +}
> +#else
> +static inline void novena_spl_setup_iomux_video(void) {}
> +#endif
> +
> +/*
> + * SPL boots from uSDHC card
> + */
> +#ifdef CONFIG_FSL_ESDHC
> +static struct fsl_esdhc_cfg usdhc_cfg = {
> +	USDHC3_BASE_ADDR, 0, 4
> +};
> +
> +int board_mmc_getcd(struct mmc *mmc)
> +{
> +	/* There is no CD for a microSD card, assume always present. */
> +	return 1;
> +}
> +
> +int board_mmc_init(bd_t *bis)
> +{
> +	usdhc_cfg.sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
> +	return fsl_esdhc_initialize(bis, &usdhc_cfg);
> +}
> +#endif
> +
> +/* Configure MX6Q/DUAL mmdc DDR io registers */
> +static struct mx6dq_iomux_ddr_regs novena_ddr_ioregs = {
> +	/* SDCLK[0:1], CAS, RAS, Reset: Differential input, 40ohm */
> +	.dram_sdclk_0		= 0x00020038,
> +	.dram_sdclk_1		= 0x00020038,
> +	.dram_cas		= 0x00000038,
> +	.dram_ras		= 0x00000038,
> +	.dram_reset		= 0x00000038,
> +	/* SDCKE[0:1]: 100k pull-up */
> +	.dram_sdcke0		= 0x00003000,
> +	.dram_sdcke1		= 0x00003000,
> +	/* SDBA2: pull-up disabled */
> +	.dram_sdba2		= 0x00000000,
> +	/* SDODT[0:1]: 100k pull-up, 40 ohm */
> +	.dram_sdodt0		= 0x00000038,
> +	.dram_sdodt1		= 0x00000038,
> +	/* SDQS[0:7]: Differential input, 40 ohm */
> +	.dram_sdqs0		= 0x00000038,
> +	.dram_sdqs1		= 0x00000038,
> +	.dram_sdqs2		= 0x00000038,
> +	.dram_sdqs3		= 0x00000038,
> +	.dram_sdqs4		= 0x00000038,
> +	.dram_sdqs5		= 0x00000038,
> +	.dram_sdqs6		= 0x00000038,
> +	.dram_sdqs7		= 0x00000038,
> +
> +	/* DQM[0:7]: Differential input, 40 ohm */
> +	.dram_dqm0		= 0x00000038,
> +	.dram_dqm1		= 0x00000038,
> +	.dram_dqm2		= 0x00000038,
> +	.dram_dqm3		= 0x00000038,
> +	.dram_dqm4		= 0x00000038,
> +	.dram_dqm5		= 0x00000038,
> +	.dram_dqm6		= 0x00000038,
> +	.dram_dqm7		= 0x00000038,
> +};
> +
> +/* Configure MX6Q/DUAL mmdc GRP io registers */
> +static struct mx6dq_iomux_grp_regs novena_grp_ioregs = {
> +	/* DDR3 */
> +	.grp_ddr_type		= 0x000c0000,
> +	.grp_ddrmode_ctl	= 0x00020000,
> +	/* Disable DDR pullups */
> +	.grp_ddrpke		= 0x00000000,
> +	/* ADDR[00:16], SDBA[0:1]: 40 ohm */
> +	.grp_addds		= 0x00000038,
> +	/* CS0/CS1/SDBA2/CKE0/CKE1/SDWE: 40 ohm */
> +	.grp_ctlds		= 0x00000038,
> +	/* DATA[00:63]: Differential input, 40 ohm */
> +	.grp_ddrmode		= 0x00020000,
> +	.grp_b0ds		= 0x00000038,
> +	.grp_b1ds		= 0x00000038,
> +	.grp_b2ds		= 0x00000038,
> +	.grp_b3ds		= 0x00000038,
> +	.grp_b4ds		= 0x00000038,
> +	.grp_b5ds		= 0x00000038,
> +	.grp_b6ds		= 0x00000038,
> +	.grp_b7ds		= 0x00000038,
> +};
> +
> +static struct mx6_mmdc_calibration novena_mmdc_calib = {
> +	/* write leveling calibration determine */
> +	.p0_mpwldectrl0		= 0x00420048,
> +	.p0_mpwldectrl1		= 0x006f0059,
> +	.p1_mpwldectrl0		= 0x005a0104,
> +	.p1_mpwldectrl1		= 0x01070113,
> +	/* Read DQS Gating calibration */
> +	.p0_mpdgctrl0		= 0x437c040b,
> +	.p0_mpdgctrl1		= 0x0413040e,
> +	.p1_mpdgctrl0		= 0x444f0446,
> +	.p1_mpdgctrl1		= 0x044d0422,
> +	/* Read Calibration: DQS delay relative to DQ read access */
> +	.p0_mprddlctl		= 0x4c424249,
> +	.p1_mprddlctl		= 0x4e48414f,
> +	/* Write Calibration: DQ/DM delay relative to DQS write access */
> +	.p0_mpwrdlctl		= 0x42414641,
> +	.p1_mpwrdlctl		= 0x46374b43,
> +};
> +
> +static struct mx6_ddr_sysinfo novena_ddr_info = {
> +	/* Width of data bus: 0=16, 1=32, 2=64 */
> +	.dsize		= 2,
> +	/* Config for full 4GB range so that get_mem_size() works */
> +	.cs_density	= 32,	/* 32Gb per CS */
> +	/* Single chip select */
> +	.ncs		= 1,
> +	.cs1_mirror	= 0,
> +	.rtt_wr		= 1,	/* RTT_Wr = RZQ/4 */
> +	.rtt_nom	= 2,	/* RTT_Nom = RZQ/2 */
> +	.walat		= 3,	/* Write additional latency */
> +	.ralat		= 7,	/* 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) */
> +};
> +
> +static struct mx6_ddr3_cfg elpida_4gib_1600 = {
> +	.mem_speed	= 1600,
> +	.density	= 4,
> +	.width		= 64,
> +	.banks		= 8,
> +	.rowaddr	= 16,
> +	.coladdr	= 10,
> +	.pagesz		= 2,
> +	.trcd		= 1300,
> +	.trcmin		= 4900,
> +	.trasmin	= 3590,
> +};
> +
> +/*
> + * 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
> + * - no variable global data is available
> + */
> +void board_init_f(ulong dummy)
> +{
> +	/* setup AIPS and disable watchdog */
> +	arch_cpu_init();
> +
> +	/* setup GP timer */
> +	timer_init();
> +
> +#ifdef CONFIG_BOARD_POSTCLK_INIT
> +	board_postclk_init();
> +#endif
> +#ifdef CONFIG_FSL_ESDHC
> +	get_clocks();
> +#endif
> +
> +	/* Setup IOMUX and configure basics. */
> +	novena_spl_setup_iomux_audio();
> +	novena_spl_setup_iomux_buttons();
> +	novena_spl_setup_iomux_enet();
> +	novena_spl_setup_iomux_fpga();
> +	novena_spl_setup_iomux_i2c();
> +	novena_spl_setup_iomux_pcie();
> +	novena_spl_setup_iomux_sdhc();
> +	novena_spl_setup_iomux_spi();
> +	novena_spl_setup_iomux_uart();
> +	novena_spl_setup_iomux_video();
> +
> +	/* UART clocks enabled and gd valid - init serial console */
> +	preloader_console_init();
> +
> +	/* Start the DDR DRAM */
> +	mx6dq_dram_iocfg(64, &novena_ddr_ioregs, &novena_grp_ioregs);
> +	mx6_dram_cfg(&novena_ddr_info, &novena_mmdc_calib, &elpida_4gib_1600);
> +
> +	/* Clear the BSS. */
> +	memset(__bss_start, 0, __bss_end - __bss_start);
> +
> +	/* load/boot image from boot device */
> +	board_init_r(NULL, 0);
> +}
> +
> +void reset_cpu(ulong addr)
> +{
> +}
> diff --git a/board/kosagi/novena/setup.cfg b/board/kosagi/novena/setup.cfg
> new file mode 100644
> index 0000000..18d139c
> --- /dev/null
> +++ b/board/kosagi/novena/setup.cfg
> @@ -0,0 +1,47 @@
> +/*
> + * Copyright (C) 2014 Marek Vasut <marex@denx.de>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + *
> + * Refer docs/README.imxmage 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 : sd */
> +BOOT_FROM sd
> +
> +#define __ASSEMBLY__
> +#include <config.h>
> +#include "asm/arch/iomux.h"
> +#include "asm/arch/crm_regs.h"
> +
> +/* 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/configs/novena_defconfig b/configs/novena_defconfig
> new file mode 100644
> index 0000000..a560afb
> --- /dev/null
> +++ b/configs/novena_defconfig
> @@ -0,0 +1,4 @@
> +CONFIG_SPL=y
> +CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/kosagi/novena/setup.cfg,MX6Q,SPL"
> ++S:CONFIG_ARM=y
> ++S:CONFIG_TARGET_KOSAGI_NOVENA=y
> diff --git a/include/configs/imx6_spl.h b/include/configs/imx6_spl.h
> index 970460d..52fe9cf 100644
> --- a/include/configs/imx6_spl.h
> +++ b/include/configs/imx6_spl.h
> @@ -27,7 +27,7 @@
>   #define CONFIG_SYS_THUMB_BUILD
>   #define CONFIG_SPL_LDSCRIPT	"arch/arm/cpu/armv7/omap-common/u-boot-spl.lds"
>   #define CONFIG_SPL_TEXT_BASE		0x00908000
> -#define CONFIG_SPL_MAX_SIZE		(64 * 1024)
> +#define CONFIG_SPL_MAX_SIZE		0x10000
>   #define CONFIG_SPL_START_S_PATH		"arch/arm/cpu/armv7"
>   #define CONFIG_SPL_STACK		0x0091FFB8
>   #define CONFIG_SPL_LIBCOMMON_SUPPORT
> diff --git a/include/configs/novena.h b/include/configs/novena.h
> new file mode 100644
> index 0000000..6b120f7
> --- /dev/null
> +++ b/include/configs/novena.h
> @@ -0,0 +1,302 @@
> +/*
> + * Configuration settings for the Novena U-boot.
> + *
> + * Copyright (C) 2014 Marek Vasut <marex@denx.de>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#ifndef __CONFIG_H
> +#define __CONFIG_H
> +
> +/* System configurations */
> +#define CONFIG_MX6
> +#define CONFIG_SYS_MX6_HCLK		24000000
> +#define CONFIG_SYS_MX6_CLK32		32768
> +#define CONFIG_BOARD_EARLY_INIT_F
> +#define CONFIG_MISC_INIT_R
> +#define CONFIG_DISPLAY_BOARDINFO
> +#define CONFIG_DISPLAY_CPUINFO
> +#define CONFIG_DOS_PARTITION
> +#define CONFIG_FAT_WRITE
> +#define CONFIG_FIT
> +#define CONFIG_KEYBOARD
> +#define CONFIG_MXC_GPIO
> +#define CONFIG_OF_LIBFDT
> +#define CONFIG_REGEX
> +#define CONFIG_SYS_GENERIC_BOARD
> +#define CONFIG_SYS_NO_FLASH
> +
> +#include "configs/mx6_common.h"
> +#include <asm/arch/imx-regs.h>
> +#include <asm/imx-common/gpio.h>
> +#include <config_cmd_default.h>
> +
> +/* U-Boot Commands */
> +#define CONFIG_CMD_ASKENV
> +#define CONFIG_CMD_BMODE
> +#define CONFIG_CMD_BOOTZ
> +#define CONFIG_CMD_CACHE
> +#define CONFIG_CMD_DHCP
> +#define CONFIG_CMD_EEPROM
> +#define CONFIG_CMD_EXT4
> +#define CONFIG_CMD_EXT4_WRITE
> +#define CONFIG_CMD_FAT
> +#define CONFIG_CMD_FS_GENERIC
> +#define CONFIG_CMD_I2C
> +#define CONFIG_CMD_FUSE
> +#define CONFIG_CMD_MII
> +#define CONFIG_CMD_MMC
> +#define CONFIG_CMD_NET
> +#define CONFIG_CMD_PCI
> +#define CONFIG_CMD_PING
> +#define CONFIG_CMD_SATA
> +#define CONFIG_CMD_SETEXPR
> +#define CONFIG_CMD_TIME
> +#define CONFIG_CMD_USB
> +#define CONFIG_VIDEO
> +
> +/* U-Boot general configurations */
> +#define CONFIG_SYS_LONGHELP
> +#define CONFIG_SYS_CBSIZE	1024		/* Console I/O buffer size */
> +#define CONFIG_SYS_PBSIZE	\
> +	(CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
> +						/* Print buffer size */
> +#define CONFIG_SYS_MAXARGS	32		/* Max number of command args */
> +#define CONFIG_SYS_BARGSIZE	CONFIG_SYS_CBSIZE
> +						/* Boot argument buffer size */
> +#define CONFIG_VERSION_VARIABLE			/* U-BOOT version */
> +#define CONFIG_AUTO_COMPLETE			/* Command auto complete */
> +#define CONFIG_CMDLINE_EDITING			/* Command history etc */
> +#define CONFIG_SYS_HUSH_PARSER
> +
> +/* U-Boot environment */
> +#define CONFIG_ENV_OVERWRITE
> +#define CONFIG_ENV_SIZE			(16 * 1024)
> +/*
> + * Environment is on MMC, starting at offset 512KiB from start of the card.
> + * Please place first partition at offset 1MiB from the start of the card
> + * as recommended by GNU/fdisk. See below for details:
> + * http://homepage.ntlworld.com./jonathan.deboynepollard/FGA/disc-partition-alignment.html
> + */
> +#ifdef CONFIG_CMD_MMC
> +#define CONFIG_ENV_IS_IN_MMC
> +#define CONFIG_SYS_MMC_ENV_DEV		0
> +#define CONFIG_ENV_OFFSET		(512 * 1024)
> +#define CONFIG_ENV_SIZE_REDUND		CONFIG_ENV_SIZE
> +#define CONFIG_ENV_OFFSET_REDUND	\
> +		(CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE)
> +#else
> +#define CONFIG_ENV_IS_NOWHERE
> +#endif
> +
> +/* Booting Linux */
> +#define CONFIG_BOOTDELAY		5
> +#define CONFIG_BOOTFILE			"fitImage"
> +#define CONFIG_BOOTARGS			"console=ttymxc1,115200 "
> +#define CONFIG_BOOTCOMMAND		"run net_nfs"
> +#define CONFIG_LOADADDR			0x18000000
> +#define CONFIG_SYS_LOAD_ADDR		CONFIG_LOADADDR
> +#define CONFIG_HOSTNAME			novena
> +
> +/* Physical Memory Map */
> +#define CONFIG_NR_DRAM_BANKS		1
> +#define PHYS_SDRAM			MMDC0_ARB_BASE_ADDR
> +#define PHYS_SDRAM_SIZE			0xF0000000
> +
> +#define CONFIG_SYS_SDRAM_BASE		PHYS_SDRAM
> +#define CONFIG_SYS_INIT_RAM_ADDR	IRAM_BASE_ADDR
> +#define CONFIG_SYS_INIT_RAM_SIZE	IRAM_SIZE
> +
> +#define CONFIG_SYS_INIT_SP_OFFSET \
> +	(CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
> +#define CONFIG_SYS_INIT_SP_ADDR \
> +	(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)
> +
> +#define CONFIG_SYS_MEMTEST_START	0x10000000
> +#define CONFIG_SYS_MEMTEST_END		0x20000000
> +
> +#define CONFIG_SYS_MALLOC_LEN		(64 * 1024 * 1024)
> +
> +/* SPL */
> +#define CONFIG_SPL_FAT_SUPPORT
> +#define CONFIG_SPL_MMC_SUPPORT
> +#include "imx6_spl.h"			/* common IMX6 SPL configuration */
> +
> +#define CONFIG_CMDLINE_TAG
> +#define CONFIG_SETUP_MEMORY_TAGS
> +#define CONFIG_INITRD_TAG
> +#define CONFIG_REVISION_TAG
> +
> +/* Ethernet Configuration */
> +#ifdef CONFIG_CMD_NET
> +#define CONFIG_FEC_MXC
> +#define CONFIG_MII
> +#define IMX_FEC_BASE			ENET_BASE_ADDR
> +#define CONFIG_FEC_XCV_TYPE		RGMII
> +#define CONFIG_ETHPRIME			"FEC"
> +#define CONFIG_FEC_MXC_PHYADDR		0x7
> +#define CONFIG_PHYLIB
> +#define CONFIG_PHY_MICREL
> +#define CONFIG_PHY_MICREL_KSZ9021
> +#define CONFIG_ARP_TIMEOUT		200UL
> +#endif
> +
> +/* I2C */
> +#define CONFIG_SYS_I2C
> +#define CONFIG_SYS_I2C_MXC
> +#define CONFIG_I2C_MULTI_BUS
> +#define CONFIG_I2C_MXC
> +#define CONFIG_SYS_I2C_SPEED		100000
> +
> +/* I2C EEPROM */
> +#ifdef CONFIG_CMD_EEPROM
> +#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN	2
> +#define CONFIG_SYS_SPD_BUS_NUM		2
> +#endif
> +
> +/* MMC Configs */
> +#ifdef CONFIG_CMD_MMC
> +#define CONFIG_MMC
> +#define CONFIG_GENERIC_MMC
> +#define CONFIG_BOUNCE_BUFFER
> +#define CONFIG_FSL_ESDHC
> +#define CONFIG_FSL_USDHC
> +#define CONFIG_SYS_FSL_ESDHC_ADDR	0
> +#define CONFIG_SYS_FSL_USDHC_NUM	2
> +#endif
> +
> +/* OCOTP Configs */
> +#ifdef CONFIG_CMD_FUSE
> +#define CONFIG_MXC_OCOTP
> +#endif
> +
> +/* PCI express */
> +#undef CONFIG_CMD_PCI	/* Disable to prevent Linux from hanging on MX6 */
> +#ifdef CONFIG_CMD_PCI
> +#define CONFIG_PCI
> +#define CONFIG_PCI_PNP
> +#define CONFIG_PCI_SCAN_SHOW
> +#define CONFIG_PCIE_IMX
> +#define CONFIG_PCIE_IMX_PERST_GPIO	IMX_GPIO_NR(3, 29)
> +#define CONFIG_PCIE_IMX_POWER_GPIO	IMX_GPIO_NR(7, 12)
> +#endif
> +
> +/* PMIC */
> +#define CONFIG_POWER
> +#define CONFIG_POWER_I2C
> +#define CONFIG_POWER_PFUZE100
> +#define CONFIG_POWER_PFUZE100_I2C_ADDR	0x08
> +
> +/* SATA Configs */
> +#ifdef CONFIG_CMD_SATA
> +#define CONFIG_DWC_AHSATA
> +#define CONFIG_SYS_SATA_MAX_DEVICE	1
> +#define CONFIG_DWC_AHSATA_PORT_ID	0
> +#define CONFIG_DWC_AHSATA_BASE_ADDR	SATA_ARB_BASE_ADDR
> +#define CONFIG_LBA48
> +#define CONFIG_LIBATA
> +#endif
> +
> +/* UART */
> +#define CONFIG_MXC_UART
> +#define CONFIG_MXC_UART_BASE		UART2_BASE
> +#define CONFIG_BAUDRATE			115200
> +#define CONFIG_CONS_INDEX		1
> +
> +/* USB Configs */
> +#ifdef CONFIG_CMD_USB
> +#define CONFIG_USB_EHCI
> +#define CONFIG_USB_EHCI_MX6
> +#define CONFIG_USB_STORAGE
> +#define CONFIG_USB_KEYBOARD
> +#define CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP
> +#define CONFIG_USB_HOST_ETHER
> +#define CONFIG_USB_ETHER_ASIX
> +#define CONFIG_USB_ETHER_SMSC95XX
> +#define CONFIG_USB_MAX_CONTROLLER_COUNT 2
> +#define CONFIG_MXC_USB_PORTSC		(PORT_PTS_UTMI | PORT_PTS_PTW)
> +#define CONFIG_MXC_USB_FLAGS		0
> +/* Gadget part */
> +#define CONFIG_CI_UDC
> +#define CONFIG_USBD_HS
> +#define CONFIG_USB_GADGET_DUALSPEED
> +#define CONFIG_USB_ETHER
> +#define CONFIG_USB_ETH_CDC
> +#define CONFIG_NETCONSOLE
> +#endif
> +
> +/* Video output */
> +#ifdef CONFIG_VIDEO
> +#define CONFIG_VIDEO
> +#define CONFIG_VIDEO_IPUV3
> +#define CONFIG_CFB_CONSOLE
> +#define CONFIG_VGA_AS_SINGLE_DEVICE
> +#define CONFIG_SYS_CONSOLE_IS_IN_ENV
> +#define CONFIG_VIDEO_BMP_RLE8
> +#define CONFIG_SPLASH_SCREEN
> +#define CONFIG_BMP_16BPP
> +#define CONFIG_VIDEO_LOGO
> +#define CONFIG_IPUV3_CLK		260000000
> +#define CONFIG_CMD_HDMIDETECT
> +#define CONFIG_CONSOLE_MUX
> +#define CONFIG_IMX_HDMI
> +#define CONFIG_IMX_VIDEO_SKIP
> +#endif
> +
> +/* Extra U-Boot environment. */
> +#define CONFIG_EXTRA_ENV_SETTINGS					\
> +	"fdt_high=0xffffffff\0"						\
> +	"initrd_high=0xffffffff\0"					\
> +	"consdev=ttymxc1\0"						\
> +	"baudrate=115200\0"						\
> +	"bootdev=/dev/mmcblk0p1\0"					\
> +	"rootdev=/dev/mmcblk0p2\0"					\
> +	"netdev=eth0\0"							\
> +	"rootpath=/opt/eldk-5.5/armv7a-hf/rootfs-qte-sdk\0"		\
> +	"kernel_addr_r=0x18000000\0"					\
> +	"addcons="							\
> +		"setenv bootargs ${bootargs} "				\
> +		"console=${consdev},${baudrate}\0"			\
> +	"addip="							\
> +		"setenv bootargs ${bootargs} "				\
> +		"ip=${ipaddr}:${serverip}:${gatewayip}:"		\
> +			"${netmask}:${hostname}:${netdev}:off\0"	\
> +	"addmisc="							\
> +		"setenv bootargs ${bootargs} ${miscargs}\0"		\
> +	"addargs=run addcons addmisc\0"					\
> +	"mmcload="							\
> +		"mmc rescan ; "						\
> +		"ext4load mmc 0:1 ${kernel_addr_r} ${bootfile}\0"	\
> +	"netload="							\
> +		"tftp ${kernel_addr_r} ${hostname}/${bootfile}\0"	\
> +	"miscargs=nohlt panic=1\0"					\
> +	"mmcargs=setenv bootargs root=${rootdev} rw rootwait\0"		\
> +	"nfsargs="							\
> +		"setenv bootargs root=/dev/nfs rw "			\
> +			"nfsroot=${serverip}:${rootpath},v3,tcp\0"	\
> +	"mmc_mmc="							\
> +		"run mmcload mmcargs addargs ; "			\
> +		"bootm ${kernel_addr_r}\0"				\
> +	"mmc_nfs="							\
> +		"run mmcload nfsargs addip addargs ; "			\
> +		"bootm ${kernel_addr_r}\0"				\
> +	"net_mmc="							\
> +		"run netload mmcargs addargs ; "			\
> +		"bootm ${kernel_addr_r}\0"				\
> +	"net_nfs="							\
> +		"run netload nfsargs addip addargs ; "			\
> +		"bootm ${kernel_addr_r}\0"				\
> +	"update_sd_spl_filename=SPL\0"					\
> +	"update_sd_uboot_filename=u-boot.img\0"				\
> +	"update_sd_firmware="	/* Update the SD firmware partition */	\
> +		"if mmc rescan ; then "					\
> +		"if dhcp ${update_sd_spl_filename} ; then "		\
> +		"mmc write ${loadaddr} 2 0x200 ; "			\
> +		"fi ; "							\
> +		"if dhcp ${update_sd_uboot_filename} ; then "		\
> +		"fatwrite mmc 0:1 ${loadaddr} u-boot.img ${filesize} ; "\
> +		"fi ; "							\
> +		"fi\0"							\
> +
> +#endif				/* __CONFIG_H */
>

Reviewed-by: Nikolay Dimitrov <picmaster@mail.bg>

No more comments from my side. Thanks for the hard work!

Regards,
Nikolay
Fabio Estevam Oct. 11, 2014, 1:56 p.m. UTC | #5
Hi Nikolay,

On Sat, Oct 11, 2014 at 2:01 AM, Nikolay Dimitrov <picmaster@mail.bg> wrote:

> We had some discussions about the PHY reset sequence and timing, but still
> not a common opinion, so I suggested to leave this fix for a consequent
> patch.

Ok, understood. Just curious: which Ethernet PHY is used on the novena board?
Sean Cross Oct. 11, 2014, 2:21 p.m. UTC | #6
On 11/10/2014 21:56, Fabio Estevam wrote:
> Hi Nikolay,
>
> On Sat, Oct 11, 2014 at 2:01 AM, Nikolay Dimitrov <picmaster@mail.bg> wrote:
>
>> We had some discussions about the PHY reset sequence and timing, but still
>> not a common opinion, so I suggested to leave this fix for a consequent
>> patch.
> Ok, understood. Just curious: which Ethernet PHY is used on the novena board?
It's the same Micrel PHY used on the Sabrelite, the KSZ9021.


Sean
Marek Vasut Oct. 11, 2014, 6:43 p.m. UTC | #7
On Saturday, October 11, 2014 at 03:44:06 AM, Fabio Estevam wrote:
> On Fri, Oct 10, 2014 at 10:14 PM, Marek Vasut <marex@denx.de> wrote:
> > +/* PCI express */
> > +#undef CONFIG_CMD_PCI  /* Disable to prevent Linux from hanging on MX6
> > */
> 
> This has been fixed recently by this commit:
> 
> https://git.kernel.org/cgit/linux/kernel/git/next/linux-next.git/commit/dri
> vers/pci/host/pci-imx6.c?id=3e3e406e3807235906ee0b7c697664ea6dfd88de

Are you positive it is possible to completely fix the PCI on MX6 ? What is the
latest official statement from FSL on the PCI in MX6 please?

Best regards,
Marek Vasut
Fabio Estevam Oct. 11, 2014, 8:56 p.m. UTC | #8
On Sat, Oct 11, 2014 at 3:43 PM, Marek Vasut <marex@denx.de> wrote:

> Are you positive it is possible to completely fix the PCI on MX6 ? What is the

I don't see the hang with that patch applied. Do you?

Regards,

Fabio Estevam
Fabio Estevam Oct. 11, 2014, 9:04 p.m. UTC | #9
On Sat, Oct 11, 2014 at 11:21 AM, Sean Cross <xobs@kosagi.com> wrote:

>> Ok, understood. Just curious: which Ethernet PHY is used on the novena board?
> It's the same Micrel PHY used on the Sabrelite, the KSZ9021.

nitrogen/sabrelite holds Ethernet PHY reset low for 10ms, which is in
accordance with ksz9021 datasheet.

Shouldn't we wait 10ms here as well?
Sean Cross Oct. 12, 2014, 6:33 a.m. UTC | #10
On 12/10/2014 05:04, Fabio Estevam wrote:
> On Sat, Oct 11, 2014 at 11:21 AM, Sean Cross <xobs@kosagi.com> wrote:
>
>>> Ok, understood. Just curious: which Ethernet PHY is used on the novena board?
>> It's the same Micrel PHY used on the Sabrelite, the KSZ9021.
> nitrogen/sabrelite holds Ethernet PHY reset low for 10ms, which is in
> accordance with ksz9021 datasheet.
>
> Shouldn't we wait 10ms here as well?
The reference manual for the PHY indicates that you should hold reset
low for 10ms after the supply voltage stabilizes.  So long as it takes
at least 10msto get from the point at which the CPU starts executing its
ROM code  to the point at which the reset line is toggled, we will be fine.


Sean
Marek Vasut Oct. 14, 2014, 9:38 p.m. UTC | #11
On Sunday, October 12, 2014 at 08:33:21 AM, Sean Cross wrote:
> On 12/10/2014 05:04, Fabio Estevam wrote:
> > On Sat, Oct 11, 2014 at 11:21 AM, Sean Cross <xobs@kosagi.com> wrote:
> >>> Ok, understood. Just curious: which Ethernet PHY is used on the novena
> >>> board?
> >> 
> >> It's the same Micrel PHY used on the Sabrelite, the KSZ9021.
> > 
> > nitrogen/sabrelite holds Ethernet PHY reset low for 10ms, which is in
> > accordance with ksz9021 datasheet.
> > 
> > Shouldn't we wait 10ms here as well?
> 
> The reference manual for the PHY indicates that you should hold reset
> low for 10ms after the supply voltage stabilizes.  So long as it takes
> at least 10msto get from the point at which the CPU starts executing its
> ROM code  to the point at which the reset line is toggled, we will be fine.

This definitelly is the case, so I presume we don't need the delay ?

Best regards,
Marek Vasut
Marek Vasut Oct. 14, 2014, 9:40 p.m. UTC | #12
On Saturday, October 11, 2014 at 03:39:36 AM, Fabio Estevam wrote:
> Hi Marek,

Fixed all, I dunno where my git-foo got wrong :/ Thanks!

Best regards,
Marek Vasut
Nikolay Dimitrov Oct. 15, 2014, 4:47 a.m. UTC | #13
Hi Marek,

On 10/15/2014 12:38 AM, Marek Vasut wrote:
> On Sunday, October 12, 2014 at 08:33:21 AM, Sean Cross wrote:
>> On 12/10/2014 05:04, Fabio Estevam wrote:
>>> On Sat, Oct 11, 2014 at 11:21 AM, Sean Cross <xobs@kosagi.com> wrote:
>>>>> Ok, understood. Just curious: which Ethernet PHY is used on the novena
>>>>> board?
>>>>
>>>> It's the same Micrel PHY used on the Sabrelite, the KSZ9021.
>>>
>>> nitrogen/sabrelite holds Ethernet PHY reset low for 10ms, which is in
>>> accordance with ksz9021 datasheet.
>>>
>>> Shouldn't we wait 10ms here as well?
>>
>> The reference manual for the PHY indicates that you should hold reset
>> low for 10ms after the supply voltage stabilizes.  So long as it takes
>> at least 10msto get from the point at which the CPU starts executing its
>> ROM code  to the point at which the reset line is toggled, we will be fine.
>
> This definitelly is the case, so I presume we don't need the delay ?

Well, here's how I see the case.

After power on, the PHY unfortunately is out of reset (R20G is DNP, imx6 
pin pulled high internally after reset). At some unknown point in time 
the CPU reaches novena_spl_setup_iomux_enet(). During all this time the 
PHY is still out of reset. Neither this complies with the recommended 
sequence, and even more doesn't comply if we remove the delay.

If we leave the delay as it is currently implemented, the actual reset 
sequence is just delayed (by the time it takes the CPU to reach the PHY 
reset code). At this later point we enforce the proper reset sequence: 
supply rail is obviously now stable, and we keep the PHY reset low for 
the minimum specified time: 10ms.

My understanding is that this is simple and efficient way to guarantee 
that for all different cases (different temperatures, different CPU 
silicon revisions, differently configured drivers/subsystems), the PHY 
reset timing is generated properly, and will be generated properly in 
the future when the code evolves.

Please tell me if I'm missing something.

Kind regards,
Nikolay
Sean Cross Oct. 15, 2014, 7:47 a.m. UTC | #14
On 15/10/2014 12:47, Nikolay Dimitrov wrote:
> Hi Marek,
>
> On 10/15/2014 12:38 AM, Marek Vasut wrote:
>> On Sunday, October 12, 2014 at 08:33:21 AM, Sean Cross wrote:
>>> On 12/10/2014 05:04, Fabio Estevam wrote:
>>>> On Sat, Oct 11, 2014 at 11:21 AM, Sean Cross <xobs@kosagi.com> wrote:
>>>>>> Ok, understood. Just curious: which Ethernet PHY is used on the
>>>>>> novena
>>>>>> board?
>>>>>
>>>>> It's the same Micrel PHY used on the Sabrelite, the KSZ9021.
>>>>
>>>> nitrogen/sabrelite holds Ethernet PHY reset low for 10ms, which is in
>>>> accordance with ksz9021 datasheet.
>>>>
>>>> Shouldn't we wait 10ms here as well?
>>>
>>> The reference manual for the PHY indicates that you should hold reset
>>> low for 10ms after the supply voltage stabilizes.  So long as it takes
>>> at least 10msto get from the point at which the CPU starts executing
>>> its
>>> ROM code  to the point at which the reset line is toggled, we will
>>> be fine.
>>
>> This definitelly is the case, so I presume we don't need the delay ?
>
> Well, here's how I see the case.
>
> After power on, the PHY unfortunately is out of reset (R20G is DNP,
> imx6 pin pulled high internally after reset). At some unknown point in
> time the CPU reaches novena_spl_setup_iomux_enet(). During all this
> time the PHY is still out of reset. Neither this complies with the
> recommended sequence, and even more doesn't comply if we remove the
> delay.
>
> If we leave the delay as it is currently implemented, the actual reset
> sequence is just delayed (by the time it takes the CPU to reach the
> PHY reset code). At this later point we enforce the proper reset
> sequence: supply rail is obviously now stable, and we keep the PHY
> reset low for the minimum specified time: 10ms.
>
> My understanding is that this is simple and efficient way to guarantee
> that for all different cases (different temperatures, different CPU
> silicon revisions, differently configured drivers/subsystems), the PHY
> reset timing is generated properly, and will be generated properly in
> the future when the code evolves.
>
> Please tell me if I'm missing something.
I generally think we'd be fine without the delay, putting it into reset
in the SPL and pulling it out of reset in U-Boot, but I can understand
the need for future-proofing and clarity.  If someone were to copy the
code from Novena to a new board, they may find the PHY behaving unreliably

If 10ms is the difference between "we ought to be fine" and "we'll
definitely be fine and not surprise anyone", then we should leave the
delay in.


Sean
Nikolay Dimitrov Oct. 15, 2014, 7:16 p.m. UTC | #15
Hi Sean, guys,

On 10/15/2014 10:47 AM, Sean Cross wrote:
> On 15/10/2014 12:47, Nikolay Dimitrov wrote:
>> Hi Marek,
>>
>> On 10/15/2014 12:38 AM, Marek Vasut wrote:
>>> On Sunday, October 12, 2014 at 08:33:21 AM, Sean Cross wrote:
>>>> On 12/10/2014 05:04, Fabio Estevam wrote:
>>>>> On Sat, Oct 11, 2014 at 11:21 AM, Sean Cross <xobs@kosagi.com> wrote:
>>>>>>> Ok, understood. Just curious: which Ethernet PHY is used on the
>>>>>>> novena
>>>>>>> board?
>>>>>>
>>>>>> It's the same Micrel PHY used on the Sabrelite, the KSZ9021.
>>>>>
>>>>> nitrogen/sabrelite holds Ethernet PHY reset low for 10ms, which is in
>>>>> accordance with ksz9021 datasheet.
>>>>>
>>>>> Shouldn't we wait 10ms here as well?
>>>>
>>>> The reference manual for the PHY indicates that you should hold reset
>>>> low for 10ms after the supply voltage stabilizes.  So long as it takes
>>>> at least 10msto get from the point at which the CPU starts executing
>>>> its
>>>> ROM code  to the point at which the reset line is toggled, we will
>>>> be fine.
>>>
>>> This definitelly is the case, so I presume we don't need the delay ?
>>
>> Well, here's how I see the case.
>>
>> After power on, the PHY unfortunately is out of reset (R20G is DNP,
>> imx6 pin pulled high internally after reset). At some unknown point in
>> time the CPU reaches novena_spl_setup_iomux_enet(). During all this
>> time the PHY is still out of reset. Neither this complies with the
>> recommended sequence, and even more doesn't comply if we remove the
>> delay.
>>
>> If we leave the delay as it is currently implemented, the actual reset
>> sequence is just delayed (by the time it takes the CPU to reach the
>> PHY reset code). At this later point we enforce the proper reset
>> sequence: supply rail is obviously now stable, and we keep the PHY
>> reset low for the minimum specified time: 10ms.
>>
>> My understanding is that this is simple and efficient way to guarantee
>> that for all different cases (different temperatures, different CPU
>> silicon revisions, differently configured drivers/subsystems), the PHY
>> reset timing is generated properly, and will be generated properly in
>> the future when the code evolves.
>>
>> Please tell me if I'm missing something.
> I generally think we'd be fine without the delay, putting it into reset
> in the SPL and pulling it out of reset in U-Boot, but I can understand
> the need for future-proofing and clarity.  If someone were to copy the
> code from Novena to a new board, they may find the PHY behaving unreliably
>
> If 10ms is the difference between "we ought to be fine" and "we'll
> definitely be fine and not surprise anyone", then we should leave the
> delay in.

Oops, I think my position on this topic seems to be "too hard headed". I 
just wanted to justify why I wrote the patch this way, and I didn't 
wanted to look like an opposition.

Sean, you're in the position of the "oem", so I definitely appreciate 
your opinion, together with Marek's and Fabio's imx6 expertise.

So guys, please advice - what should be the final value of this delay, 
and I'll re-send the patch if needed.

Kind regards,
Nikolay
Sean Cross Oct. 16, 2014, 2:38 a.m. UTC | #16
On 16/10/2014 03:16, Nikolay Dimitrov wrote:
> Hi Sean, guys,
>
> On 10/15/2014 10:47 AM, Sean Cross wrote:
>> On 15/10/2014 12:47, Nikolay Dimitrov wrote:
>>> Hi Marek,
>>>
>>> On 10/15/2014 12:38 AM, Marek Vasut wrote:
>>>> On Sunday, October 12, 2014 at 08:33:21 AM, Sean Cross wrote:
>>>>> On 12/10/2014 05:04, Fabio Estevam wrote:
>>>>>> On Sat, Oct 11, 2014 at 11:21 AM, Sean Cross <xobs@kosagi.com>
>>>>>> wrote:
>>>>>>>> Ok, understood. Just curious: which Ethernet PHY is used on the
>>>>>>>> novena
>>>>>>>> board?
>>>>>>>
>>>>>>> It's the same Micrel PHY used on the Sabrelite, the KSZ9021.
>>>>>>
>>>>>> nitrogen/sabrelite holds Ethernet PHY reset low for 10ms, which
>>>>>> is in
>>>>>> accordance with ksz9021 datasheet.
>>>>>>
>>>>>> Shouldn't we wait 10ms here as well?
>>>>>
>>>>> The reference manual for the PHY indicates that you should hold reset
>>>>> low for 10ms after the supply voltage stabilizes.  So long as it
>>>>> takes
>>>>> at least 10msto get from the point at which the CPU starts executing
>>>>> its
>>>>> ROM code  to the point at which the reset line is toggled, we will
>>>>> be fine.
>>>>
>>>> This definitelly is the case, so I presume we don't need the delay ?
>>>
>>> Well, here's how I see the case.
>>>
>>> After power on, the PHY unfortunately is out of reset (R20G is DNP,
>>> imx6 pin pulled high internally after reset). At some unknown point in
>>> time the CPU reaches novena_spl_setup_iomux_enet(). During all this
>>> time the PHY is still out of reset. Neither this complies with the
>>> recommended sequence, and even more doesn't comply if we remove the
>>> delay.
>>>
>>> If we leave the delay as it is currently implemented, the actual reset
>>> sequence is just delayed (by the time it takes the CPU to reach the
>>> PHY reset code). At this later point we enforce the proper reset
>>> sequence: supply rail is obviously now stable, and we keep the PHY
>>> reset low for the minimum specified time: 10ms.
>>>
>>> My understanding is that this is simple and efficient way to guarantee
>>> that for all different cases (different temperatures, different CPU
>>> silicon revisions, differently configured drivers/subsystems), the PHY
>>> reset timing is generated properly, and will be generated properly in
>>> the future when the code evolves.
>>>
>>> Please tell me if I'm missing something.
>> I generally think we'd be fine without the delay, putting it into reset
>> in the SPL and pulling it out of reset in U-Boot, but I can understand
>> the need for future-proofing and clarity.  If someone were to copy the
>> code from Novena to a new board, they may find the PHY behaving
>> unreliably
>>
>> If 10ms is the difference between "we ought to be fine" and "we'll
>> definitely be fine and not surprise anyone", then we should leave the
>> delay in.
>
> Oops, I think my position on this topic seems to be "too hard headed".
> I just wanted to justify why I wrote the patch this way, and I didn't
> wanted to look like an opposition.
>
> Sean, you're in the position of the "oem", so I definitely appreciate
> your opinion, together with Marek's and Fabio's imx6 expertise.
>
> So guys, please advice - what should be the final value of this delay,
> and I'll re-send the patch if needed.

My opinion is that, following the principle of least surprise, we should
leave the delay in.  If, sometime in the future, someone were to
micro-optimize the boot sequence, they can strip it out then, but in
that case it'd make more sense to load Linux directly from SPL.

I say leave it in.


Sean
Marek Vasut Oct. 16, 2014, 10:21 a.m. UTC | #17
On Saturday, October 11, 2014 at 11:04:58 PM, Fabio Estevam wrote:
> On Sat, Oct 11, 2014 at 11:21 AM, Sean Cross <xobs@kosagi.com> wrote:
> >> Ok, understood. Just curious: which Ethernet PHY is used on the novena
> >> board?
> > 
> > It's the same Micrel PHY used on the Sabrelite, the KSZ9021.
> 
> nitrogen/sabrelite holds Ethernet PHY reset low for 10ms, which is in
> accordance with ksz9021 datasheet.
> 
> Shouldn't we wait 10ms here as well?

I checked the novena_spl.c and we do wait in novena_spl_setup_iomux_enet().
Is this what you have in mind ?

Best regards,
Marek Vasut
Fabio Estevam Oct. 16, 2014, 5:17 p.m. UTC | #18
On Thu, Oct 16, 2014 at 7:21 AM, Marek Vasut <marex@denx.de> wrote:

> I checked the novena_spl.c and we do wait in novena_spl_setup_iomux_enet().
> Is this what you have in mind ?

Nikolay added the delay in this patch:
https://patchwork.ozlabs.org/patch/398920/
Marek Vasut Oct. 16, 2014, 11:02 p.m. UTC | #19
On Thursday, October 16, 2014 at 07:17:36 PM, Fabio Estevam wrote:
> On Thu, Oct 16, 2014 at 7:21 AM, Marek Vasut <marex@denx.de> wrote:
> > I checked the novena_spl.c and we do wait in
> > novena_spl_setup_iomux_enet(). Is this what you have in mind ?
> 
> Nikolay added the delay in this patch:
> https://patchwork.ozlabs.org/patch/398920/

So this discussion is related to a different thread ? I see ...

Best regards,
Marek Vasut
Fabio Estevam Oct. 16, 2014, 11:27 p.m. UTC | #20
On Thu, Oct 16, 2014 at 8:02 PM, Marek Vasut <marex@denx.de> wrote:

> So this discussion is related to a different thread ? I see ...

We are talking about the need for the delay in the Ethernet PHY.

Nikolay sent a patch adding such delay as a standard patch.
Fabio Estevam Oct. 16, 2014, 11:32 p.m. UTC | #21
On Wed, Oct 15, 2014 at 11:38 PM, Sean Cross <xobs@kosagi.com> wrote:

> My opinion is that, following the principle of least surprise, we should
> leave the delay in.  If, sometime in the future, someone were to
> micro-optimize the boot sequence, they can strip it out then, but in
> that case it'd make more sense to load Linux directly from SPL.
>
> I say leave it in.

Yes, I agree.
Marek Vasut Oct. 17, 2014, 1:55 p.m. UTC | #22
On Friday, October 17, 2014 at 01:27:10 AM, Fabio Estevam wrote:
> On Thu, Oct 16, 2014 at 8:02 PM, Marek Vasut <marex@denx.de> wrote:
> > So this discussion is related to a different thread ? I see ...
> 
> We are talking about the need for the delay in the Ethernet PHY.
> 
> Nikolay sent a patch adding such delay as a standard patch.

OK, so we're discussing different patch here, thanks for clarifying.

Best regards,
Marek Vasut
diff mbox

Patch

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 106aed9..4da1923 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -411,6 +411,9 @@  config TARGET_GW_VENTANA
 config TARGET_HUMMINGBOARD
 	bool "Support hummingboard"
 
+config TARGET_KOSAGI_NOVENA
+	bool "Support Kosagi Novena"
+
 config TARGET_TQMA6
 	bool "TQ Systems TQMa6 board"
 
@@ -637,6 +640,7 @@  source "board/imx31_phycore/Kconfig"
 source "board/isee/igep0033/Kconfig"
 source "board/jornada/Kconfig"
 source "board/karo/tx25/Kconfig"
+source "board/kosagi/novena/Kconfig"
 source "board/logicpd/imx27lite/Kconfig"
 source "board/logicpd/imx31_litekit/Kconfig"
 source "board/mpl/vcma9/Kconfig"
diff --git a/board/kosagi/novena/Kconfig b/board/kosagi/novena/Kconfig
new file mode 100644
index 0000000..4ba6399
--- /dev/null
+++ b/board/kosagi/novena/Kconfig
@@ -0,0 +1,18 @@ 
+if TARGET_KOSAGI_NOVENA
+
+config SYS_CPU
+	default "armv7"
+
+config SYS_BOARD
+	default "novena"
+
+config SYS_VENDOR
+	default "kosagi"
+
+config SYS_SOC
+	default "mx6"
+
+config SYS_CONFIG_NAME
+	default "novena"
+
+endif
diff --git a/board/kosagi/novena/Makefile b/board/kosagi/novena/Makefile
new file mode 100644
index 0000000..6fba177
--- /dev/null
+++ b/board/kosagi/novena/Makefile
@@ -0,0 +1,11 @@ 
+#
+# Copyright (C) 2014 Marek Vasut <marex@denx.de>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+ifdef CONFIG_SPL_BUILD
+obj-y	:= novena_spl.o
+else
+obj-y	:= novena.o
+endif
diff --git a/board/kosagi/novena/novena.c b/board/kosagi/novena/novena.c
new file mode 100644
index 0000000..2361a3c
--- /dev/null
+++ b/board/kosagi/novena/novena.c
@@ -0,0 +1,343 @@ 
+/*
+ * Novena board support
+ *
+ * Copyright (C) 2014 Marek Vasut <marex@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/errno.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/crm_regs.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/iomux.h>
+#include <asm/arch/mxc_hdmi.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/imx-common/sata.h>
+#include <asm/imx-common/video.h>
+#include <fsl_esdhc.h>
+#include <i2c.h>
+#include <input.h>
+#include <ipu_pixfmt.h>
+#include <linux/fb.h>
+#include <linux/input.h>
+#include <malloc.h>
+#include <micrel.h>
+#include <miiphy.h>
+#include <mmc.h>
+#include <netdev.h>
+#include <power/pmic.h>
+#include <power/pfuze100_pmic.h>
+#include <stdio_dev.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define NOVENA_BUTTON_GPIO	IMX_GPIO_NR(4, 14)
+#define NOVENA_SD_WP		IMX_GPIO_NR(1, 2)
+#define NOVENA_SD_CD		IMX_GPIO_NR(1, 4)
+
+/*
+ * GPIO button
+ */
+#ifdef CONFIG_KEYBOARD
+static struct input_config button_input;
+
+static int novena_gpio_button_read_keys(struct input_config *input)
+{
+	int key = KEY_ENTER;
+	if (gpio_get_value(NOVENA_BUTTON_GPIO))
+		return 0;
+	input_send_keycodes(&button_input, &key, 1);
+	return 1;
+}
+
+static int novena_gpio_button_getc(struct stdio_dev *dev)
+{
+	return input_getc(&button_input);
+}
+
+static int novena_gpio_button_tstc(struct stdio_dev *dev)
+{
+	return input_tstc(&button_input);
+}
+
+static int novena_gpio_button_init(struct stdio_dev *dev)
+{
+	gpio_direction_input(NOVENA_BUTTON_GPIO);
+	input_set_delays(&button_input, 250, 250);
+	return 0;
+}
+
+int drv_keyboard_init(void)
+{
+	int error;
+	struct stdio_dev dev = {
+		.name	= "button",
+		.flags	= DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM,
+		.start	= novena_gpio_button_init,
+		.getc	= novena_gpio_button_getc,
+		.tstc	= novena_gpio_button_tstc,
+	};
+
+	error = input_init(&button_input, 0);
+	if (error) {
+		debug("%s: Cannot set up input\n", __func__);
+		return -1;
+	}
+	button_input.read_keys = novena_gpio_button_read_keys;
+
+	error = input_stdio_register(&dev);
+	if (error)
+		return error;
+
+	return 0;
+}
+#endif
+
+/*
+ * SDHC
+ */
+#ifdef CONFIG_FSL_ESDHC
+static struct fsl_esdhc_cfg usdhc_cfg[] = {
+	{ USDHC3_BASE_ADDR, 0, 4 },	/* Micro SD */
+	{ USDHC2_BASE_ADDR, 0, 4 },	/* Big SD */
+};
+
+int board_mmc_getcd(struct mmc *mmc)
+{
+	struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
+
+	/* There is no CD for a microSD card, assume always present. */
+	if (cfg->esdhc_base == USDHC3_BASE_ADDR)
+		return 1;
+	else
+		return !gpio_get_value(NOVENA_SD_CD);
+}
+
+int board_mmc_getwp(struct mmc *mmc)
+{
+	struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
+
+	/* There is no WP for a microSD card, assume always read-write. */
+	if (cfg->esdhc_base == USDHC3_BASE_ADDR)
+		return 0;
+	else
+		return gpio_get_value(NOVENA_SD_WP);
+}
+
+
+int board_mmc_init(bd_t *bis)
+{
+	s32 status = 0;
+	int index;
+
+	usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
+	usdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
+
+	/* Big SD write-protect and card-detect */
+	gpio_direction_input(NOVENA_SD_WP);
+	gpio_direction_input(NOVENA_SD_CD);
+
+	for (index = 0; index < ARRAY_SIZE(usdhc_cfg); index++) {
+		status = fsl_esdhc_initialize(bis, &usdhc_cfg[index]);
+		if (status)
+			return status;
+	}
+
+	return status;
+}
+#endif
+
+/*
+ * Video over HDMI
+ */
+#if defined(CONFIG_VIDEO_IPUV3)
+static void enable_hdmi(struct display_info_t const *dev)
+{
+	imx_enable_hdmi_phy();
+}
+
+struct display_info_t const displays[] = {
+	{
+		/* HDMI Output */
+		.bus	= -1,
+		.addr	= 0,
+		.pixfmt	= IPU_PIX_FMT_RGB24,
+		.detect	= detect_hdmi,
+		.enable	= enable_hdmi,
+		.mode	= {
+			.name           = "HDMI",
+			.refresh        = 60,
+			.xres           = 1024,
+			.yres           = 768,
+			.pixclock       = 15385,
+			.left_margin    = 220,
+			.right_margin   = 40,
+			.upper_margin   = 21,
+			.lower_margin   = 7,
+			.hsync_len      = 60,
+			.vsync_len      = 10,
+			.sync           = FB_SYNC_EXT,
+			.vmode          = FB_VMODE_NONINTERLACED
+		}
+	}
+};
+
+size_t display_count = ARRAY_SIZE(displays);
+
+static void setup_display(void)
+{
+	struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+	struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
+
+	enable_ipu_clock();
+	imx_setup_hdmi();
+
+	/* Turn on LDB0,IPU,IPU DI0 clocks */
+	setbits_le32(&mxc_ccm->CCGR3, MXC_CCM_CCGR3_LDB_DI0_MASK);
+
+	/* set LDB0, LDB1 clk select to 011/011 */
+	clrsetbits_le32(&mxc_ccm->cs2cdr,
+			MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK |
+			MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_MASK,
+			(3 << MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET) |
+			(3 << MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_OFFSET));
+
+	setbits_le32(&mxc_ccm->cscmr2, MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV);
+
+	setbits_le32(&mxc_ccm->chsccdr, CHSCCDR_CLK_SEL_LDB_DI0 <<
+		     MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET);
+
+	writel(IOMUXC_GPR2_BGREF_RRMODE_EXTERNAL_RES |
+	       IOMUXC_GPR2_DI1_VS_POLARITY_ACTIVE_HIGH |
+	       IOMUXC_GPR2_DI0_VS_POLARITY_ACTIVE_LOW |
+	       IOMUXC_GPR2_BIT_MAPPING_CH1_SPWG |
+	       IOMUXC_GPR2_DATA_WIDTH_CH1_18BIT |
+	       IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG |
+	       IOMUXC_GPR2_DATA_WIDTH_CH0_18BIT |
+	       IOMUXC_GPR2_LVDS_CH1_MODE_DISABLED |
+	       IOMUXC_GPR2_LVDS_CH0_MODE_ENABLED_DI0,
+	       &iomux->gpr[2]);
+
+	clrsetbits_le32(&iomux->gpr[3], IOMUXC_GPR3_LVDS0_MUX_CTL_MASK,
+			IOMUXC_GPR3_MUX_SRC_IPU1_DI0 <<
+			IOMUXC_GPR3_LVDS0_MUX_CTL_OFFSET);
+}
+#endif
+
+int board_early_init_f(void)
+{
+#if defined(CONFIG_VIDEO_IPUV3)
+	setup_display();
+#endif
+
+	/* Bring Ethernet PHY out of reset. */
+	gpio_set_value(IMX_GPIO_NR(3, 23), 1);
+
+	return 0;
+}
+
+int board_init(void)
+{
+	/* address of boot parameters */
+	gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
+
+#ifdef CONFIG_CMD_SATA
+	setup_sata();
+#endif
+
+	return 0;
+}
+
+int checkboard(void)
+{
+	puts("Board: Novena 4x\n");
+	return 0;
+}
+
+int dram_init(void)
+{
+	gd->ram_size = imx_ddr_size();
+	return 0;
+}
+
+/* setup board specific PMIC */
+int power_init_board(void)
+{
+	struct pmic *p;
+	u32 reg;
+	int ret;
+
+	power_pfuze100_init(1);
+	p = pmic_get("PFUZE100");
+	if (!p)
+		return -EINVAL;
+
+	ret = pmic_probe(p);
+	if (ret)
+		return ret;
+
+	pmic_reg_read(p, PFUZE100_DEVICEID, &reg);
+	printf("PMIC:  PFUZE100 ID=0x%02x\n", reg);
+
+	/* Set SWBST to 5.0V and enable (for USB) */
+	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);
+
+	return 0;
+}
+
+/* EEPROM configuration data */
+struct novena_eeprom_data {
+	uint8_t		signature[6];
+	uint8_t		version;
+	uint8_t		reserved;
+	uint32_t	serial;
+	uint8_t		mac[6];
+	uint16_t	features;
+};
+
+int misc_init_r(void)
+{
+	struct novena_eeprom_data data;
+	uchar *datap = (uchar *)&data;
+	const char *signature = "Novena";
+	int ret;
+
+	/* If 'ethaddr' is already set, do nothing. */
+	if (getenv("ethaddr"))
+		return 0;
+
+	/* EEPROM is at bus 2. */
+	ret = i2c_set_bus_num(2);
+	if (ret) {
+		puts("Cannot select EEPROM I2C bus.\n");
+		return 0;
+	}
+
+	/* EEPROM is at address 0x56. */
+	ret = eeprom_read(0x56, 0, datap, sizeof(data));
+	if (ret) {
+		puts("Cannot read I2C EEPROM.\n");
+		return 0;
+	}
+
+	/* Check EEPROM signature. */
+	if (memcmp(data.signature, signature, 6)) {
+		puts("Invalid I2C EEPROM signature.\n");
+		return 0;
+	}
+
+	/* Set ethernet address from EEPROM. */
+	eth_setenv_enetaddr("ethaddr", data.mac);
+
+	return ret;
+}
diff --git a/board/kosagi/novena/novena_spl.c b/board/kosagi/novena/novena_spl.c
new file mode 100644
index 0000000..a8389d9
--- /dev/null
+++ b/board/kosagi/novena/novena_spl.c
@@ -0,0 +1,556 @@ 
+/*
+ * Novena SPL
+ *
+ * Copyright (C) 2014 Marek Vasut <marex@denx.de>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/clock.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/gpio.h>
+#include <asm/imx-common/boot_mode.h>
+#include <asm/imx-common/iomux-v3.h>
+#include <asm/imx-common/mxc_i2c.h>
+#include <i2c.h>
+#include <mmc.h>
+#include <fsl_esdhc.h>
+#include <spl.h>
+
+#include <asm/arch/mx6-ddr.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#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 RGMII_PAD_CTRL						\
+	(PAD_CTL_PKE | PAD_CTL_PUE |				\
+	PAD_CTL_PUS_100K_UP | 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 I2C_PAD_CTRL						\
+	(PAD_CTL_PKE | PAD_CTL_PUE |				\
+	PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_LOW |		\
+	PAD_CTL_DSE_240ohm  | PAD_CTL_HYS |			\
+	PAD_CTL_ODE)
+
+#define BUTTON_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 PC MUX_PAD_CTRL(I2C_PAD_CTRL)
+
+#define NOVENA_AUDIO_PWRON		IMX_GPIO_NR(5, 17)
+#define NOVENA_FPGA_RESET_N_GPIO	IMX_GPIO_NR(5, 7)
+#define NOVENA_HDMI_GHOST_HPD		IMX_GPIO_NR(5, 4)
+#define NOVENA_PCIE_RESET_GPIO		IMX_GPIO_NR(3, 29)
+#define NOVENA_PCIE_POWER_ON_GPIO	IMX_GPIO_NR(7, 12)
+#define NOVENA_PCIE_WAKE_UP_GPIO	IMX_GPIO_NR(3, 22)
+#define NOVENA_PCIE_DISABLE_GPIO	IMX_GPIO_NR(2, 16)
+
+/*
+ * Audio
+ */
+static iomux_v3_cfg_t audio_pads[] = {
+	/* AUD_PWRON */
+	MX6_PAD_DISP0_DAT23__GPIO5_IO17 | MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
+static void novena_spl_setup_iomux_audio(void)
+{
+	imx_iomux_v3_setup_multiple_pads(audio_pads, ARRAY_SIZE(audio_pads));
+	gpio_direction_output(NOVENA_AUDIO_PWRON, 1);
+}
+
+/*
+ * ENET
+ */
+static iomux_v3_cfg_t enet_pads1[] = {
+	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(RGMII_PAD_CTRL),
+	MX6_PAD_RGMII_TD0__RGMII_TD0		| MUX_PAD_CTRL(RGMII_PAD_CTRL),
+	MX6_PAD_RGMII_TD1__RGMII_TD1		| MUX_PAD_CTRL(RGMII_PAD_CTRL),
+	MX6_PAD_RGMII_TD2__RGMII_TD2		| MUX_PAD_CTRL(RGMII_PAD_CTRL),
+	MX6_PAD_RGMII_TD3__RGMII_TD3		| MUX_PAD_CTRL(RGMII_PAD_CTRL),
+	MX6_PAD_RGMII_TX_CTL__RGMII_TX_CTL	| MUX_PAD_CTRL(RGMII_PAD_CTRL),
+	MX6_PAD_ENET_REF_CLK__ENET_TX_CLK	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	/* pin 35 - 1 (PHY_AD2) on reset */
+	MX6_PAD_RGMII_RXC__GPIO6_IO30		| MUX_PAD_CTRL(NO_PAD_CTRL),
+	/* pin 32 - 1 - (MODE0) all */
+	MX6_PAD_RGMII_RD0__GPIO6_IO25		| MUX_PAD_CTRL(NO_PAD_CTRL),
+	/* pin 31 - 1 - (MODE1) all */
+	MX6_PAD_RGMII_RD1__GPIO6_IO27		| MUX_PAD_CTRL(NO_PAD_CTRL),
+	/* pin 28 - 1 - (MODE2) all */
+	MX6_PAD_RGMII_RD2__GPIO6_IO28		| MUX_PAD_CTRL(NO_PAD_CTRL),
+	/* pin 27 - 1 - (MODE3) all */
+	MX6_PAD_RGMII_RD3__GPIO6_IO29		| MUX_PAD_CTRL(NO_PAD_CTRL),
+	/* pin 33 - 1 - (CLK125_EN) 125Mhz clockout enabled */
+	MX6_PAD_RGMII_RX_CTL__GPIO6_IO24	| MUX_PAD_CTRL(NO_PAD_CTRL),
+	/* pin 42 PHY nRST */
+	MX6_PAD_EIM_D23__GPIO3_IO23		| MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
+static iomux_v3_cfg_t enet_pads2[] = {
+	MX6_PAD_RGMII_RXC__RGMII_RXC		| MUX_PAD_CTRL(RGMII_PAD_CTRL),
+	MX6_PAD_RGMII_RD0__RGMII_RD0		| MUX_PAD_CTRL(RGMII_PAD_CTRL),
+	MX6_PAD_RGMII_RD1__RGMII_RD1		| MUX_PAD_CTRL(RGMII_PAD_CTRL),
+	MX6_PAD_RGMII_RD2__RGMII_RD2		| MUX_PAD_CTRL(RGMII_PAD_CTRL),
+	MX6_PAD_RGMII_RD3__RGMII_RD3		| MUX_PAD_CTRL(RGMII_PAD_CTRL),
+	MX6_PAD_RGMII_RX_CTL__RGMII_RX_CTL	| MUX_PAD_CTRL(RGMII_PAD_CTRL),
+};
+
+static void novena_spl_setup_iomux_enet(void)
+{
+	imx_iomux_v3_setup_multiple_pads(enet_pads1, ARRAY_SIZE(enet_pads1));
+
+	gpio_direction_output(IMX_GPIO_NR(3, 23), 0);
+	gpio_direction_output(IMX_GPIO_NR(6, 30), 1);
+	gpio_direction_output(IMX_GPIO_NR(6, 25), 1);
+	gpio_direction_output(IMX_GPIO_NR(6, 27), 1);
+	gpio_direction_output(IMX_GPIO_NR(6, 28), 1);
+	gpio_direction_output(IMX_GPIO_NR(6, 29), 1);
+	gpio_direction_output(IMX_GPIO_NR(6, 24), 1);
+
+	imx_iomux_v3_setup_multiple_pads(enet_pads2, ARRAY_SIZE(enet_pads2));
+}
+
+/*
+ * FPGA
+ */
+static iomux_v3_cfg_t fpga_pads[] = {
+	/* FPGA_RESET_N */
+	MX6_PAD_DISP0_DAT13__GPIO5_IO07 | MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
+static void novena_spl_setup_iomux_fpga(void)
+{
+	imx_iomux_v3_setup_multiple_pads(fpga_pads, ARRAY_SIZE(fpga_pads));
+	gpio_direction_output(NOVENA_FPGA_RESET_N_GPIO, 0);
+}
+
+/*
+ * GPIO Button
+ */
+static iomux_v3_cfg_t button_pads[] = {
+	/* Debug */
+	MX6_PAD_KEY_COL4__GPIO4_IO14 | MUX_PAD_CTRL(BUTTON_PAD_CTRL),
+};
+
+static void novena_spl_setup_iomux_buttons(void)
+{
+	imx_iomux_v3_setup_multiple_pads(button_pads, ARRAY_SIZE(button_pads));
+}
+
+/*
+ * I2C
+ */
+/*
+ * I2C1:
+ *  0x1d ... MMA7455L
+ *  0x30 ... SO-DIMM temp sensor
+ *  0x44 ... STMPE610
+ *  0x50 ... SO-DIMM ID
+ */
+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:
+ *  0x08 ... PMIC
+ *  0x3a ... HDMI DCC
+ *  0x50 ... HDMI DCC
+ */
+static struct i2c_pads_info i2c_pad_info1 = {
+	.scl = {
+		.i2c_mode	= MX6_PAD_EIM_EB2__I2C2_SCL | PC,
+		.gpio_mode	= MX6_PAD_EIM_EB2__GPIO2_IO30 | PC,
+		.gp		= IMX_GPIO_NR(2, 30)
+	},
+	.sda = {
+		.i2c_mode	= MX6_PAD_EIM_D16__I2C2_SDA | PC,
+		.gpio_mode	= MX6_PAD_EIM_D16__GPIO3_IO16 | PC,
+		.gp		= IMX_GPIO_NR(3, 16)
+	}
+};
+
+/*
+ * I2C3:
+ *  0x11 ... ES8283
+ *  0x50 ... LCD EDID
+ *  0x56 ... EEPROM
+ */
+static struct i2c_pads_info i2c_pad_info2 = {
+	.scl = {
+		.i2c_mode	= MX6_PAD_EIM_D17__I2C3_SCL | PC,
+		.gpio_mode	= MX6_PAD_EIM_D17__GPIO3_IO17 | PC,
+		.gp		= IMX_GPIO_NR(3, 17)
+	},
+	.sda = {
+		.i2c_mode	= MX6_PAD_EIM_D18__I2C3_SDA | PC,
+		.gpio_mode	= MX6_PAD_EIM_D18__GPIO3_IO18 | PC,
+		.gp		= IMX_GPIO_NR(3, 18)
+	}
+};
+
+static void novena_spl_setup_iomux_i2c(void)
+{
+	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);
+}
+
+/*
+ * PCI express
+ */
+#ifdef CONFIG_CMD_PCI
+static iomux_v3_cfg_t pcie_pads[] = {
+	/* "Reset" pin */
+	MX6_PAD_EIM_D29__GPIO3_IO29 | MUX_PAD_CTRL(NO_PAD_CTRL),
+	/* "Power on" pin */
+	MX6_PAD_GPIO_17__GPIO7_IO12 | MUX_PAD_CTRL(NO_PAD_CTRL),
+	/* "Wake up" pin (input) */
+	MX6_PAD_EIM_D22__GPIO3_IO22 | MUX_PAD_CTRL(NO_PAD_CTRL),
+	/* "Disable endpoint" (rfkill) pin */
+	MX6_PAD_EIM_A22__GPIO2_IO16 | MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
+static void novena_spl_setup_iomux_pcie(void)
+{
+	imx_iomux_v3_setup_multiple_pads(pcie_pads, ARRAY_SIZE(pcie_pads));
+
+	/* Ensure PCIe is powered down */
+	gpio_direction_output(NOVENA_PCIE_POWER_ON_GPIO, 0);
+
+	/* Put the card into reset */
+	gpio_direction_output(NOVENA_PCIE_RESET_GPIO, 0);
+
+	/* Input signal to wake system from mPCIe card */
+	gpio_direction_input(NOVENA_PCIE_WAKE_UP_GPIO);
+
+	/* Drive RFKILL high, to ensure the radio is turned on */
+	gpio_direction_output(NOVENA_PCIE_DISABLE_GPIO, 1);
+}
+#else
+static inline void novena_spl_setup_iomux_pcie(void) {}
+#endif
+
+/*
+ * SDHC
+ */
+static iomux_v3_cfg_t usdhc2_pads[] = {
+	MX6_PAD_SD2_CLK__SD2_CLK    | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD2_CMD__SD2_CMD    | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD2_DAT0__SD2_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD2_DAT1__SD2_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD2_DAT2__SD2_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD2_DAT3__SD2_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_GPIO_2__GPIO1_IO02  | MUX_PAD_CTRL(NO_PAD_CTRL), /* WP */
+	MX6_PAD_GPIO_4__GPIO1_IO04  | MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */
+};
+
+static iomux_v3_cfg_t 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),
+};
+
+static void novena_spl_setup_iomux_sdhc(void)
+{
+	imx_iomux_v3_setup_multiple_pads(usdhc2_pads, ARRAY_SIZE(usdhc2_pads));
+	imx_iomux_v3_setup_multiple_pads(usdhc3_pads, ARRAY_SIZE(usdhc3_pads));
+
+	/* Big SD write-protect and card-detect */
+	gpio_direction_input(IMX_GPIO_NR(1, 2));
+	gpio_direction_input(IMX_GPIO_NR(1, 4));
+}
+
+/*
+ * SPI
+ */
+#ifdef CONFIG_MXC_SPI
+static iomux_v3_cfg_t ecspi3_pads[] = {
+	/* SS1 */
+	MX6_PAD_DISP0_DAT1__ECSPI3_MOSI | MUX_PAD_CTRL(SPI_PAD_CTRL),
+	MX6_PAD_DISP0_DAT2__ECSPI3_MISO | MUX_PAD_CTRL(SPI_PAD_CTRL),
+	MX6_PAD_DISP0_DAT0__ECSPI3_SCLK | MUX_PAD_CTRL(SPI_PAD_CTRL),
+	MX6_PAD_DISP0_DAT3__GPIO4_IO24 | MUX_PAD_CTRL(SPI_PAD_CTRL),
+	MX6_PAD_DISP0_DAT4__GPIO4_IO25 | MUX_PAD_CTRL(SPI_PAD_CTRL),
+	MX6_PAD_DISP0_DAT5__GPIO4_IO26 | MUX_PAD_CTRL(SPI_PAD_CTRL),
+	MX6_PAD_DISP0_DAT7__ECSPI3_RDY | MUX_PAD_CTRL(SPI_PAD_CTRL),
+};
+
+static void novena_spl_setup_iomux_spi(void)
+{
+	imx_iomux_v3_setup_multiple_pads(ecspi3_pads, ARRAY_SIZE(ecspi3_pads));
+	/* De-assert the nCS */
+	gpio_direction_output(MX6_PAD_DISP0_DAT3__GPIO4_IO24, 1);
+	gpio_direction_output(MX6_PAD_DISP0_DAT4__GPIO4_IO25, 1);
+	gpio_direction_output(MX6_PAD_DISP0_DAT5__GPIO4_IO26, 1);
+}
+#else
+static void novena_spl_setup_iomux_spi(void) {}
+#endif
+
+/*
+ * UART
+ */
+static iomux_v3_cfg_t const uart2_pads[] = {
+	MX6_PAD_EIM_D26__UART2_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+	MX6_PAD_EIM_D27__UART2_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+};
+
+static iomux_v3_cfg_t const uart3_pads[] = {
+	MX6_PAD_EIM_D24__UART3_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+	MX6_PAD_EIM_D25__UART3_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+};
+
+static iomux_v3_cfg_t const uart4_pads[] = {
+	MX6_PAD_KEY_COL0__UART4_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+	MX6_PAD_KEY_ROW0__UART4_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+	MX6_PAD_CSI0_DAT16__UART4_CTS_B | MUX_PAD_CTRL(UART_PAD_CTRL),
+	MX6_PAD_CSI0_DAT17__UART4_RTS_B | MUX_PAD_CTRL(UART_PAD_CTRL),
+
+};
+
+static void novena_spl_setup_iomux_uart(void)
+{
+	imx_iomux_v3_setup_multiple_pads(uart2_pads, ARRAY_SIZE(uart2_pads));
+	imx_iomux_v3_setup_multiple_pads(uart3_pads, ARRAY_SIZE(uart3_pads));
+	imx_iomux_v3_setup_multiple_pads(uart4_pads, ARRAY_SIZE(uart4_pads));
+}
+
+/*
+ * Video
+ */
+#ifdef CONFIG_VIDEO
+static iomux_v3_cfg_t hdmi_pads[] = {
+	/* "Ghost HPD" pin */
+	MX6_PAD_EIM_A24__GPIO5_IO04 | MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
+static void novena_spl_setup_iomux_video(void)
+{
+	imx_iomux_v3_setup_multiple_pads(hdmi_pads, ARRAY_SIZE(hdmi_pads));
+	gpio_direction_input(NOVENA_HDMI_GHOST_HPD);
+}
+#else
+static inline void novena_spl_setup_iomux_video(void) {}
+#endif
+
+/*
+ * SPL boots from uSDHC card
+ */
+#ifdef CONFIG_FSL_ESDHC
+static struct fsl_esdhc_cfg usdhc_cfg = {
+	USDHC3_BASE_ADDR, 0, 4
+};
+
+int board_mmc_getcd(struct mmc *mmc)
+{
+	/* There is no CD for a microSD card, assume always present. */
+	return 1;
+}
+
+int board_mmc_init(bd_t *bis)
+{
+	usdhc_cfg.sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
+	return fsl_esdhc_initialize(bis, &usdhc_cfg);
+}
+#endif
+
+/* Configure MX6Q/DUAL mmdc DDR io registers */
+static struct mx6dq_iomux_ddr_regs novena_ddr_ioregs = {
+	/* SDCLK[0:1], CAS, RAS, Reset: Differential input, 40ohm */
+	.dram_sdclk_0		= 0x00020038,
+	.dram_sdclk_1		= 0x00020038,
+	.dram_cas		= 0x00000038,
+	.dram_ras		= 0x00000038,
+	.dram_reset		= 0x00000038,
+	/* SDCKE[0:1]: 100k pull-up */
+	.dram_sdcke0		= 0x00003000,
+	.dram_sdcke1		= 0x00003000,
+	/* SDBA2: pull-up disabled */
+	.dram_sdba2		= 0x00000000,
+	/* SDODT[0:1]: 100k pull-up, 40 ohm */
+	.dram_sdodt0		= 0x00000038,
+	.dram_sdodt1		= 0x00000038,
+	/* SDQS[0:7]: Differential input, 40 ohm */
+	.dram_sdqs0		= 0x00000038,
+	.dram_sdqs1		= 0x00000038,
+	.dram_sdqs2		= 0x00000038,
+	.dram_sdqs3		= 0x00000038,
+	.dram_sdqs4		= 0x00000038,
+	.dram_sdqs5		= 0x00000038,
+	.dram_sdqs6		= 0x00000038,
+	.dram_sdqs7		= 0x00000038,
+
+	/* DQM[0:7]: Differential input, 40 ohm */
+	.dram_dqm0		= 0x00000038,
+	.dram_dqm1		= 0x00000038,
+	.dram_dqm2		= 0x00000038,
+	.dram_dqm3		= 0x00000038,
+	.dram_dqm4		= 0x00000038,
+	.dram_dqm5		= 0x00000038,
+	.dram_dqm6		= 0x00000038,
+	.dram_dqm7		= 0x00000038,
+};
+
+/* Configure MX6Q/DUAL mmdc GRP io registers */
+static struct mx6dq_iomux_grp_regs novena_grp_ioregs = {
+	/* DDR3 */
+	.grp_ddr_type		= 0x000c0000,
+	.grp_ddrmode_ctl	= 0x00020000,
+	/* Disable DDR pullups */
+	.grp_ddrpke		= 0x00000000,
+	/* ADDR[00:16], SDBA[0:1]: 40 ohm */
+	.grp_addds		= 0x00000038,
+	/* CS0/CS1/SDBA2/CKE0/CKE1/SDWE: 40 ohm */
+	.grp_ctlds		= 0x00000038,
+	/* DATA[00:63]: Differential input, 40 ohm */
+	.grp_ddrmode		= 0x00020000,
+	.grp_b0ds		= 0x00000038,
+	.grp_b1ds		= 0x00000038,
+	.grp_b2ds		= 0x00000038,
+	.grp_b3ds		= 0x00000038,
+	.grp_b4ds		= 0x00000038,
+	.grp_b5ds		= 0x00000038,
+	.grp_b6ds		= 0x00000038,
+	.grp_b7ds		= 0x00000038,
+};
+
+static struct mx6_mmdc_calibration novena_mmdc_calib = {
+	/* write leveling calibration determine */
+	.p0_mpwldectrl0		= 0x00420048,
+	.p0_mpwldectrl1		= 0x006f0059,
+	.p1_mpwldectrl0		= 0x005a0104,
+	.p1_mpwldectrl1		= 0x01070113,
+	/* Read DQS Gating calibration */
+	.p0_mpdgctrl0		= 0x437c040b,
+	.p0_mpdgctrl1		= 0x0413040e,
+	.p1_mpdgctrl0		= 0x444f0446,
+	.p1_mpdgctrl1		= 0x044d0422,
+	/* Read Calibration: DQS delay relative to DQ read access */
+	.p0_mprddlctl		= 0x4c424249,
+	.p1_mprddlctl		= 0x4e48414f,
+	/* Write Calibration: DQ/DM delay relative to DQS write access */
+	.p0_mpwrdlctl		= 0x42414641,
+	.p1_mpwrdlctl		= 0x46374b43,
+};
+
+static struct mx6_ddr_sysinfo novena_ddr_info = {
+	/* Width of data bus: 0=16, 1=32, 2=64 */
+	.dsize		= 2,
+	/* Config for full 4GB range so that get_mem_size() works */
+	.cs_density	= 32,	/* 32Gb per CS */
+	/* Single chip select */
+	.ncs		= 1,
+	.cs1_mirror	= 0,
+	.rtt_wr		= 1,	/* RTT_Wr = RZQ/4 */
+	.rtt_nom	= 2,	/* RTT_Nom = RZQ/2 */
+	.walat		= 3,	/* Write additional latency */
+	.ralat		= 7,	/* 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) */
+};
+
+static struct mx6_ddr3_cfg elpida_4gib_1600 = {
+	.mem_speed	= 1600,
+	.density	= 4,
+	.width		= 64,
+	.banks		= 8,
+	.rowaddr	= 16,
+	.coladdr	= 10,
+	.pagesz		= 2,
+	.trcd		= 1300,
+	.trcmin		= 4900,
+	.trasmin	= 3590,
+};
+
+/*
+ * 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
+ * - no variable global data is available
+ */
+void board_init_f(ulong dummy)
+{
+	/* setup AIPS and disable watchdog */
+	arch_cpu_init();
+
+	/* setup GP timer */
+	timer_init();
+
+#ifdef CONFIG_BOARD_POSTCLK_INIT
+	board_postclk_init();
+#endif
+#ifdef CONFIG_FSL_ESDHC
+	get_clocks();
+#endif
+
+	/* Setup IOMUX and configure basics. */
+	novena_spl_setup_iomux_audio();
+	novena_spl_setup_iomux_buttons();
+	novena_spl_setup_iomux_enet();
+	novena_spl_setup_iomux_fpga();
+	novena_spl_setup_iomux_i2c();
+	novena_spl_setup_iomux_pcie();
+	novena_spl_setup_iomux_sdhc();
+	novena_spl_setup_iomux_spi();
+	novena_spl_setup_iomux_uart();
+	novena_spl_setup_iomux_video();
+
+	/* UART clocks enabled and gd valid - init serial console */
+	preloader_console_init();
+
+	/* Start the DDR DRAM */
+	mx6dq_dram_iocfg(64, &novena_ddr_ioregs, &novena_grp_ioregs);
+	mx6_dram_cfg(&novena_ddr_info, &novena_mmdc_calib, &elpida_4gib_1600);
+
+	/* Clear the BSS. */
+	memset(__bss_start, 0, __bss_end - __bss_start);
+
+	/* load/boot image from boot device */
+	board_init_r(NULL, 0);
+}
+
+void reset_cpu(ulong addr)
+{
+}
diff --git a/board/kosagi/novena/setup.cfg b/board/kosagi/novena/setup.cfg
new file mode 100644
index 0000000..18d139c
--- /dev/null
+++ b/board/kosagi/novena/setup.cfg
@@ -0,0 +1,47 @@ 
+/*
+ * Copyright (C) 2014 Marek Vasut <marex@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ * Refer docs/README.imxmage 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 : sd */
+BOOT_FROM sd
+
+#define __ASSEMBLY__
+#include <config.h>
+#include "asm/arch/iomux.h"
+#include "asm/arch/crm_regs.h"
+
+/* 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/configs/novena_defconfig b/configs/novena_defconfig
new file mode 100644
index 0000000..a560afb
--- /dev/null
+++ b/configs/novena_defconfig
@@ -0,0 +1,4 @@ 
+CONFIG_SPL=y
+CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/kosagi/novena/setup.cfg,MX6Q,SPL"
++S:CONFIG_ARM=y
++S:CONFIG_TARGET_KOSAGI_NOVENA=y
diff --git a/include/configs/imx6_spl.h b/include/configs/imx6_spl.h
index 970460d..52fe9cf 100644
--- a/include/configs/imx6_spl.h
+++ b/include/configs/imx6_spl.h
@@ -27,7 +27,7 @@ 
 #define CONFIG_SYS_THUMB_BUILD
 #define CONFIG_SPL_LDSCRIPT	"arch/arm/cpu/armv7/omap-common/u-boot-spl.lds"
 #define CONFIG_SPL_TEXT_BASE		0x00908000
-#define CONFIG_SPL_MAX_SIZE		(64 * 1024)
+#define CONFIG_SPL_MAX_SIZE		0x10000
 #define CONFIG_SPL_START_S_PATH		"arch/arm/cpu/armv7"
 #define CONFIG_SPL_STACK		0x0091FFB8
 #define CONFIG_SPL_LIBCOMMON_SUPPORT
diff --git a/include/configs/novena.h b/include/configs/novena.h
new file mode 100644
index 0000000..6b120f7
--- /dev/null
+++ b/include/configs/novena.h
@@ -0,0 +1,302 @@ 
+/*
+ * Configuration settings for the Novena U-boot.
+ *
+ * Copyright (C) 2014 Marek Vasut <marex@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/* System configurations */
+#define CONFIG_MX6
+#define CONFIG_SYS_MX6_HCLK		24000000
+#define CONFIG_SYS_MX6_CLK32		32768
+#define CONFIG_BOARD_EARLY_INIT_F
+#define CONFIG_MISC_INIT_R
+#define CONFIG_DISPLAY_BOARDINFO
+#define CONFIG_DISPLAY_CPUINFO
+#define CONFIG_DOS_PARTITION
+#define CONFIG_FAT_WRITE
+#define CONFIG_FIT
+#define CONFIG_KEYBOARD
+#define CONFIG_MXC_GPIO
+#define CONFIG_OF_LIBFDT
+#define CONFIG_REGEX
+#define CONFIG_SYS_GENERIC_BOARD
+#define CONFIG_SYS_NO_FLASH
+
+#include "configs/mx6_common.h"
+#include <asm/arch/imx-regs.h>
+#include <asm/imx-common/gpio.h>
+#include <config_cmd_default.h>
+
+/* U-Boot Commands */
+#define CONFIG_CMD_ASKENV
+#define CONFIG_CMD_BMODE
+#define CONFIG_CMD_BOOTZ
+#define CONFIG_CMD_CACHE
+#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_EEPROM
+#define CONFIG_CMD_EXT4
+#define CONFIG_CMD_EXT4_WRITE
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_FS_GENERIC
+#define CONFIG_CMD_I2C
+#define CONFIG_CMD_FUSE
+#define CONFIG_CMD_MII
+#define CONFIG_CMD_MMC
+#define CONFIG_CMD_NET
+#define CONFIG_CMD_PCI
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_SATA
+#define CONFIG_CMD_SETEXPR
+#define CONFIG_CMD_TIME
+#define CONFIG_CMD_USB
+#define CONFIG_VIDEO
+
+/* U-Boot general configurations */
+#define CONFIG_SYS_LONGHELP
+#define CONFIG_SYS_CBSIZE	1024		/* Console I/O buffer size */
+#define CONFIG_SYS_PBSIZE	\
+	(CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
+						/* Print buffer size */
+#define CONFIG_SYS_MAXARGS	32		/* Max number of command args */
+#define CONFIG_SYS_BARGSIZE	CONFIG_SYS_CBSIZE
+						/* Boot argument buffer size */
+#define CONFIG_VERSION_VARIABLE			/* U-BOOT version */
+#define CONFIG_AUTO_COMPLETE			/* Command auto complete */
+#define CONFIG_CMDLINE_EDITING			/* Command history etc */
+#define CONFIG_SYS_HUSH_PARSER
+
+/* U-Boot environment */
+#define CONFIG_ENV_OVERWRITE
+#define CONFIG_ENV_SIZE			(16 * 1024)
+/*
+ * Environment is on MMC, starting at offset 512KiB from start of the card.
+ * Please place first partition at offset 1MiB from the start of the card
+ * as recommended by GNU/fdisk. See below for details:
+ * http://homepage.ntlworld.com./jonathan.deboynepollard/FGA/disc-partition-alignment.html
+ */
+#ifdef CONFIG_CMD_MMC
+#define CONFIG_ENV_IS_IN_MMC
+#define CONFIG_SYS_MMC_ENV_DEV		0
+#define CONFIG_ENV_OFFSET		(512 * 1024)
+#define CONFIG_ENV_SIZE_REDUND		CONFIG_ENV_SIZE
+#define CONFIG_ENV_OFFSET_REDUND	\
+		(CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE)
+#else
+#define CONFIG_ENV_IS_NOWHERE
+#endif
+
+/* Booting Linux */
+#define CONFIG_BOOTDELAY		5
+#define CONFIG_BOOTFILE			"fitImage"
+#define CONFIG_BOOTARGS			"console=ttymxc1,115200 "
+#define CONFIG_BOOTCOMMAND		"run net_nfs"
+#define CONFIG_LOADADDR			0x18000000
+#define CONFIG_SYS_LOAD_ADDR		CONFIG_LOADADDR
+#define CONFIG_HOSTNAME			novena
+
+/* Physical Memory Map */
+#define CONFIG_NR_DRAM_BANKS		1
+#define PHYS_SDRAM			MMDC0_ARB_BASE_ADDR
+#define PHYS_SDRAM_SIZE			0xF0000000
+
+#define CONFIG_SYS_SDRAM_BASE		PHYS_SDRAM
+#define CONFIG_SYS_INIT_RAM_ADDR	IRAM_BASE_ADDR
+#define CONFIG_SYS_INIT_RAM_SIZE	IRAM_SIZE
+
+#define CONFIG_SYS_INIT_SP_OFFSET \
+	(CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
+#define CONFIG_SYS_INIT_SP_ADDR \
+	(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)
+
+#define CONFIG_SYS_MEMTEST_START	0x10000000
+#define CONFIG_SYS_MEMTEST_END		0x20000000
+
+#define CONFIG_SYS_MALLOC_LEN		(64 * 1024 * 1024)
+
+/* SPL */
+#define CONFIG_SPL_FAT_SUPPORT
+#define CONFIG_SPL_MMC_SUPPORT
+#include "imx6_spl.h"			/* common IMX6 SPL configuration */
+
+#define CONFIG_CMDLINE_TAG
+#define CONFIG_SETUP_MEMORY_TAGS
+#define CONFIG_INITRD_TAG
+#define CONFIG_REVISION_TAG
+
+/* Ethernet Configuration */
+#ifdef CONFIG_CMD_NET
+#define CONFIG_FEC_MXC
+#define CONFIG_MII
+#define IMX_FEC_BASE			ENET_BASE_ADDR
+#define CONFIG_FEC_XCV_TYPE		RGMII
+#define CONFIG_ETHPRIME			"FEC"
+#define CONFIG_FEC_MXC_PHYADDR		0x7
+#define CONFIG_PHYLIB
+#define CONFIG_PHY_MICREL
+#define CONFIG_PHY_MICREL_KSZ9021
+#define CONFIG_ARP_TIMEOUT		200UL
+#endif
+
+/* I2C */
+#define CONFIG_SYS_I2C
+#define CONFIG_SYS_I2C_MXC
+#define CONFIG_I2C_MULTI_BUS
+#define CONFIG_I2C_MXC
+#define CONFIG_SYS_I2C_SPEED		100000
+
+/* I2C EEPROM */
+#ifdef CONFIG_CMD_EEPROM
+#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN	2
+#define CONFIG_SYS_SPD_BUS_NUM		2
+#endif
+
+/* MMC Configs */
+#ifdef CONFIG_CMD_MMC
+#define CONFIG_MMC
+#define CONFIG_GENERIC_MMC
+#define CONFIG_BOUNCE_BUFFER
+#define CONFIG_FSL_ESDHC
+#define CONFIG_FSL_USDHC
+#define CONFIG_SYS_FSL_ESDHC_ADDR	0
+#define CONFIG_SYS_FSL_USDHC_NUM	2
+#endif
+
+/* OCOTP Configs */
+#ifdef CONFIG_CMD_FUSE
+#define CONFIG_MXC_OCOTP
+#endif
+
+/* PCI express */
+#undef CONFIG_CMD_PCI	/* Disable to prevent Linux from hanging on MX6 */
+#ifdef CONFIG_CMD_PCI
+#define CONFIG_PCI
+#define CONFIG_PCI_PNP
+#define CONFIG_PCI_SCAN_SHOW
+#define CONFIG_PCIE_IMX
+#define CONFIG_PCIE_IMX_PERST_GPIO	IMX_GPIO_NR(3, 29)
+#define CONFIG_PCIE_IMX_POWER_GPIO	IMX_GPIO_NR(7, 12)
+#endif
+
+/* PMIC */
+#define CONFIG_POWER
+#define CONFIG_POWER_I2C
+#define CONFIG_POWER_PFUZE100
+#define CONFIG_POWER_PFUZE100_I2C_ADDR	0x08
+
+/* SATA Configs */
+#ifdef CONFIG_CMD_SATA
+#define CONFIG_DWC_AHSATA
+#define CONFIG_SYS_SATA_MAX_DEVICE	1
+#define CONFIG_DWC_AHSATA_PORT_ID	0
+#define CONFIG_DWC_AHSATA_BASE_ADDR	SATA_ARB_BASE_ADDR
+#define CONFIG_LBA48
+#define CONFIG_LIBATA
+#endif
+
+/* UART */
+#define CONFIG_MXC_UART
+#define CONFIG_MXC_UART_BASE		UART2_BASE
+#define CONFIG_BAUDRATE			115200
+#define CONFIG_CONS_INDEX		1
+
+/* USB Configs */
+#ifdef CONFIG_CMD_USB
+#define CONFIG_USB_EHCI
+#define CONFIG_USB_EHCI_MX6
+#define CONFIG_USB_STORAGE
+#define CONFIG_USB_KEYBOARD
+#define CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP
+#define CONFIG_USB_HOST_ETHER
+#define CONFIG_USB_ETHER_ASIX
+#define CONFIG_USB_ETHER_SMSC95XX
+#define CONFIG_USB_MAX_CONTROLLER_COUNT 2
+#define CONFIG_MXC_USB_PORTSC		(PORT_PTS_UTMI | PORT_PTS_PTW)
+#define CONFIG_MXC_USB_FLAGS		0
+/* Gadget part */
+#define CONFIG_CI_UDC
+#define CONFIG_USBD_HS
+#define CONFIG_USB_GADGET_DUALSPEED
+#define CONFIG_USB_ETHER
+#define CONFIG_USB_ETH_CDC
+#define CONFIG_NETCONSOLE
+#endif
+
+/* Video output */
+#ifdef CONFIG_VIDEO
+#define CONFIG_VIDEO
+#define CONFIG_VIDEO_IPUV3
+#define CONFIG_CFB_CONSOLE
+#define CONFIG_VGA_AS_SINGLE_DEVICE
+#define CONFIG_SYS_CONSOLE_IS_IN_ENV
+#define CONFIG_VIDEO_BMP_RLE8
+#define CONFIG_SPLASH_SCREEN
+#define CONFIG_BMP_16BPP
+#define CONFIG_VIDEO_LOGO
+#define CONFIG_IPUV3_CLK		260000000
+#define CONFIG_CMD_HDMIDETECT
+#define CONFIG_CONSOLE_MUX
+#define CONFIG_IMX_HDMI
+#define CONFIG_IMX_VIDEO_SKIP
+#endif
+
+/* Extra U-Boot environment. */
+#define CONFIG_EXTRA_ENV_SETTINGS					\
+	"fdt_high=0xffffffff\0"						\
+	"initrd_high=0xffffffff\0"					\
+	"consdev=ttymxc1\0"						\
+	"baudrate=115200\0"						\
+	"bootdev=/dev/mmcblk0p1\0"					\
+	"rootdev=/dev/mmcblk0p2\0"					\
+	"netdev=eth0\0"							\
+	"rootpath=/opt/eldk-5.5/armv7a-hf/rootfs-qte-sdk\0"		\
+	"kernel_addr_r=0x18000000\0"					\
+	"addcons="							\
+		"setenv bootargs ${bootargs} "				\
+		"console=${consdev},${baudrate}\0"			\
+	"addip="							\
+		"setenv bootargs ${bootargs} "				\
+		"ip=${ipaddr}:${serverip}:${gatewayip}:"		\
+			"${netmask}:${hostname}:${netdev}:off\0"	\
+	"addmisc="							\
+		"setenv bootargs ${bootargs} ${miscargs}\0"		\
+	"addargs=run addcons addmisc\0"					\
+	"mmcload="							\
+		"mmc rescan ; "						\
+		"ext4load mmc 0:1 ${kernel_addr_r} ${bootfile}\0"	\
+	"netload="							\
+		"tftp ${kernel_addr_r} ${hostname}/${bootfile}\0"	\
+	"miscargs=nohlt panic=1\0"					\
+	"mmcargs=setenv bootargs root=${rootdev} rw rootwait\0"		\
+	"nfsargs="							\
+		"setenv bootargs root=/dev/nfs rw "			\
+			"nfsroot=${serverip}:${rootpath},v3,tcp\0"	\
+	"mmc_mmc="							\
+		"run mmcload mmcargs addargs ; "			\
+		"bootm ${kernel_addr_r}\0"				\
+	"mmc_nfs="							\
+		"run mmcload nfsargs addip addargs ; "			\
+		"bootm ${kernel_addr_r}\0"				\
+	"net_mmc="							\
+		"run netload mmcargs addargs ; "			\
+		"bootm ${kernel_addr_r}\0"				\
+	"net_nfs="							\
+		"run netload nfsargs addip addargs ; "			\
+		"bootm ${kernel_addr_r}\0"				\
+	"update_sd_spl_filename=SPL\0"					\
+	"update_sd_uboot_filename=u-boot.img\0"				\
+	"update_sd_firmware="	/* Update the SD firmware partition */	\
+		"if mmc rescan ; then "					\
+		"if dhcp ${update_sd_spl_filename} ; then "		\
+		"mmc write ${loadaddr} 2 0x200 ; "			\
+		"fi ; "							\
+		"if dhcp ${update_sd_uboot_filename} ; then "		\
+		"fatwrite mmc 0:1 ${loadaddr} u-boot.img ${filesize} ; "\
+		"fi ; "							\
+		"fi\0"							\
+
+#endif				/* __CONFIG_H */