diff mbox

[U-Boot] Add minimal support for Congatec Conga-QEVAl Evaluation Carrier Board with a conga-Qmx6 module.

Message ID 3465D313FDFB824F9A9C8CD24FA4F6BC0108CCF3@frontmail.adetel.com
State Changes Requested
Delegated to: Stefano Babic
Headers show

Commit Message

SARTRE Leo May 13, 2013, 12:02 p.m. UTC
Signed-off-by: Leo Sartre <lsartre@adeneo-embedded.com>
---
 board/freescale/cgtqmx6/Makefile  |   42 +++
 board/freescale/cgtqmx6/cgtqmx6.c |  627 +++++++++++++++++++++++++++++++++++++
 boards.cfg                        |    1 +
 include/configs/cgtqmx6.h         |  294 +++++++++++++++++
 4 files changed, 964 insertions(+)
 create mode 100644 board/freescale/cgtqmx6/Makefile
 create mode 100644 board/freescale/cgtqmx6/cgtqmx6.c
 create mode 100644 include/configs/cgtqmx6.h

1.7.10.4

Comments

Stefano Babic May 13, 2013, 12:58 p.m. UTC | #1
On 13/05/2013 14:02, SARTRE Leo wrote:
> Signed-off-by: Leo Sartre <lsartre@adeneo-embedded.com>
> ---

Hi Leo,

>  board/freescale/cgtqmx6/Makefile  |   42 +++
>  board/freescale/cgtqmx6/cgtqmx6.c |  627 +++++++++++++++++++++++++++++++++++++
>  boards.cfg                        |    1 +
>  include/configs/cgtqmx6.h         |  294 +++++++++++++++++

You have also to update the MAINTAINERS file.

As I understand from the Website, even if the board can be derived from
the SabreLite, it is a different product from a different vendor.

Why should the board then be put into freescale/ directory ?

Generally we have the schema:

board/<board_name>

or

board/<vendor_name>/<board_name>

> diff --git a/board/freescale/cgtqmx6/Makefile b/board/freescale/cgtqmx6/Makefile
> new file mode 100644
> index 0000000..a17603e
> --- /dev/null
> +++ b/board/freescale/cgtqmx6/Makefile
> @@ -0,0 +1,41 @@
> +#
> +# Copyright (C) 2007, Guennadi Liakhovetski <lg@denx.de>
> +#
> +# (C) Copyright 2013 Adeneo Embedded <www.adeneo-embedded.com>
> +#
> +# This program is free software; you can redistribute it and/or
> +# modify it under the terms of the GNU General Public License as
> +# published by the Free Software Foundation; either version 2 of
> +# the License, or (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program; if not, write to the Free Software
> +# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> +# MA 02111-1307 USA
> +#
> +
> +include $(TOPDIR)/config.mk
> +
> +LIB    = $(obj)lib$(BOARD).o
> +
> +COBJS  := cgtqmx6.o
> +
> +SRCS   := $(COBJS:.o=.c)
> +OBJS   := $(addprefix $(obj),$(COBJS))
> +
> +$(LIB):        $(obj).depend $(OBJS)
> +	$(call cmd_link_o_target, $(OBJS))
> +
> +#########################################################################
> +
> +# defines $(obj).depend target
> +include $(SRCTREE)/rules.mk
> +
> +sinclude $(obj).depend
> +
> +#########################################################################
> diff --git a/board/freescale/cgtqmx6/cgtqmx6.c b/board/freescale/cgtqmx6/cgtqmx6.c
> new file mode 100644
> index 0000000..ed5476a
> --- /dev/null
> +++ b/board/freescale/cgtqmx6/cgtqmx6.c
> @@ -0,0 +1,630 @@
> +/*
> + * Copyright (C) 2013, Adeneo Embedded <www.adeneo-embedded.com>
> + * Leo Sartre, <lsartre@adeneo-embedded.com>
> + * Based on mx6qsabrelite.c file
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + */
> +
> +#include <common.h>
> +#include <asm/io.h>
> +#include <asm/arch/clock.h>
> +#include <asm/arch/imx-regs.h>
> +#include <asm/arch/iomux.h>
> +#include <asm/arch/mx6-pins.h>
> +#include <asm/errno.h>
> +#include <asm/gpio.h>
> +#include <asm/imx-common/iomux-v3.h>
> +#include <asm/imx-common/mxc_i2c.h>
> +#include <asm/imx-common/boot_mode.h>
> +#include <mmc.h>
> +#include <fsl_esdhc.h>
> +#include <malloc.h>
> +#include <linux/fb.h>
> +#include <ipu_pixfmt.h>
> +#include <asm/arch/crm_regs.h>
> +#include <asm/arch/mxc_hdmi.h>
> +#include <i2c.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 SPI_PAD_CTRL (PAD_CTL_HYS |\
> +					  PAD_CTL_PUS_100K_DOWN |\
> +					  PAD_CTL_SPEED_MED     |\
> +					  PAD_CTL_DSE_40ohm     |\
> +					  PAD_CTL_SRE_FAST)
> +
> +#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 I2C_PAD_CTRL	(PAD_CTL_PKE | PAD_CTL_PUE |\
> +						 PAD_CTL_PUS_100K_UP |\
> +						 PAD_CTL_SPEED_MED   |\
> +						 PAD_CTL_DSE_40ohm   |\
> +						 PAD_CTL_HYS         |\
> +						 PAD_CTL_ODE         |\
> +						 PAD_CTL_SRE_FAST)
> +
> +int dram_init(void)
> +{
> +	gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
> +
> +	return 0;
> +}
> +
> +iomux_v3_cfg_t const uart1_pads[] = {
> +	MX6_PAD_CSI0_DAT10__UART1_TXD | MUX_PAD_CTRL(UART_PAD_CTRL),
> +	MX6_PAD_CSI0_DAT11__UART1_RXD | MUX_PAD_CTRL(UART_PAD_CTRL),
> +};
> +
> +iomux_v3_cfg_t const uart2_pads[] = {
> +	MX6_PAD_EIM_D26__UART2_TXD | MUX_PAD_CTRL(UART_PAD_CTRL),
> +	MX6_PAD_EIM_D27__UART2_RXD | MUX_PAD_CTRL(UART_PAD_CTRL),
> +};
> +
> +#define PC MUX_PAD_CTRL(I2C_PAD_CTRL)
> +
> +/* I2C1, SGTL5000 */
> +struct i2c_pads_info i2c_pad_info0 = {
> +	.scl = {
> +		.i2c_mode = MX6_PAD_EIM_D21__I2C1_SCL | PC,
> +		.gpio_mode = MX6_PAD_EIM_D21__GPIO_3_21 | PC,
> +		.gp = IMX_GPIO_NR(3, 21)
> +	},
> +	.sda = {
> +		.i2c_mode = MX6_PAD_EIM_D28__I2C1_SDA | PC,
> +		.gpio_mode = MX6_PAD_EIM_D28__GPIO_3_28 | PC,
> +		.gp = IMX_GPIO_NR(3, 28)
> +	}
> +};
> +
> +/* I2C2 Camera, MIPI */
> +struct i2c_pads_info i2c_pad_info1 = {
> +	.scl = {
> +		.i2c_mode = MX6_PAD_KEY_COL3__I2C2_SCL | PC,
> +		.gpio_mode = MX6_PAD_KEY_COL3__GPIO_4_12 | PC,
> +		.gp = IMX_GPIO_NR(4, 12)
> +	},
> +	.sda = {
> +		.i2c_mode = MX6_PAD_KEY_ROW3__I2C2_SDA | PC,
> +		.gpio_mode = MX6_PAD_KEY_ROW3__GPIO_4_13 | PC,
> +		.gp = IMX_GPIO_NR(4, 13)
> +	}
> +};
> +
> +struct i2c_pads_info i2c_pad_info2 = {
> +	.scl = {
> +		.i2c_mode = MX6_PAD_GPIO_3__I2C3_SCL | PC,
> +		.gpio_mode = MX6_PAD_GPIO_3__GPIO_1_3 | PC,
> +		.gp = IMX_GPIO_NR(1, 3)
> +	},
> +	.sda = {
> +		.i2c_mode = MX6_PAD_GPIO_6__I2C3_SDA | PC,
> +		.gpio_mode = MX6_PAD_GPIO_6__GPIO_1_6 | PC,
> +		.gp = IMX_GPIO_NR(1, 6)
> +	}
> +};
> +
> +
> +iomux_v3_cfg_t const usdhc1_pads[] = {
> +	MX6_PAD_SD1_CLK__USDHC1_CLK   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD1_CMD__USDHC1_CMD   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD1_DAT0__USDHC1_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD1_DAT1__USDHC1_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD1_DAT2__USDHC1_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD1_DAT3__USDHC1_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +};
> +
> +iomux_v3_cfg_t const usdhc2_pads[] = {
> +	MX6_PAD_SD2_CLK__USDHC2_CLK   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD2_CMD__USDHC2_CMD   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD2_DAT0__USDHC2_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD2_DAT1__USDHC2_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD2_DAT2__USDHC2_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD2_DAT3__USDHC2_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_GPIO_4__GPIO_1_4      | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +};
> +
> +iomux_v3_cfg_t const usdhc3_pads[] = {
> +	MX6_PAD_SD3_CLK__USDHC3_CLK   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD3_CMD__USDHC3_CMD   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD3_DAT0__USDHC3_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD3_DAT1__USDHC3_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD3_DAT2__USDHC3_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD3_DAT3__USDHC3_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD3_DAT4__USDHC3_DAT4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD3_DAT5__USDHC3_DAT5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD3_DAT6__USDHC3_DAT6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD3_DAT7__USDHC3_DAT7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD3_DAT5__GPIO_7_0    | MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */
> +};
> +
> +iomux_v3_cfg_t const usdhc4_pads[] = {
> +	MX6_PAD_SD4_CLK__USDHC4_CLK   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD4_CMD__USDHC4_CMD   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD4_DAT0__USDHC4_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD4_DAT1__USDHC4_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD4_DAT2__USDHC4_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD4_DAT3__USDHC4_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD4_DAT4__USDHC4_DAT4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD4_DAT5__USDHC4_DAT5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD4_DAT6__USDHC4_DAT6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD4_DAT7__USDHC4_DAT7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_NANDF_D6__GPIO_2_6    | MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */
> +};
> +
> +iomux_v3_cfg_t const usb_pads[] = {
> +	MX6_PAD_GPIO_17__GPIO_7_12 | MUX_PAD_CTRL(NO_PAD_CTRL),
> +};
> +
> +/* Button assignments*/
> +static iomux_v3_cfg_t const button_pads[] = {
> +	/* Recovery button */
> +	MX6_PAD_GPIO_19__GPIO_4_5	| MUX_PAD_CTRL(BUTTON_PAD_CTRL),
> +};
> +
> +
> +static void setup_iomux_uart(void)
> +{
> +	imx_iomux_v3_setup_multiple_pads(uart1_pads, ARRAY_SIZE(uart1_pads));
> +	imx_iomux_v3_setup_multiple_pads(uart2_pads, ARRAY_SIZE(uart2_pads));
> +}
> +
> +#ifdef CONFIG_USB_EHCI_MX6
> +int board_ehci_hcd_init(int port)
> +{
> +	imx_iomux_v3_setup_multiple_pads(usb_pads, ARRAY_SIZE(usb_pads));
> +
> +	/* Reset USB hub */
> +	gpio_direction_output(IMX_GPIO_NR(7, 12), 0);
> +	mdelay(2);
> +	gpio_set_value(IMX_GPIO_NR(7, 12), 1);
> +
> +	return 0;
> +}
> +#endif
> +
> +#ifdef CONFIG_FSL_ESDHC
> +struct fsl_esdhc_cfg usdhc_cfg[] = {
> +	{USDHC2_BASE_ADDR},
> +	{USDHC4_BASE_ADDR},
> +};
> +
> +int board_mmc_getcd(struct mmc *mmc)
> +{
> +	struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
> +	int ret;
> +
> +	switch (cfg->esdhc_base) {
> +	case USDHC2_BASE_ADDR:
> +		gpio_direction_input(IMX_GPIO_NR(1, 4));
> +		ret = !gpio_get_value(IMX_GPIO_NR(1, 4));
> +		break;
> +	case USDHC3_BASE_ADDR:
> +		gpio_direction_input(IMX_GPIO_NR(7, 0));
> +		ret = !gpio_get_value(IMX_GPIO_NR(7, 0));
> +		break;
> +	case USDHC4_BASE_ADDR:
> +		gpio_direction_input(IMX_GPIO_NR(2, 6));
> +		ret = !gpio_get_value(IMX_GPIO_NR(2, 6));
> +		break;
> +	default:
> +		printf("Bad USDHC interface\n");
> +	}
> +
> +	return ret;
> +}
> +
> +int board_mmc_init(bd_t *bis)
> +{
> +	s32 status = 0;
> +	u32 index = 0;
> +
> +	usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
> +	usdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC4_CLK);
> +
> +	for (index = 0; index < CONFIG_SYS_FSL_USDHC_NUM; ++index) {
> +		switch (index) {
> +		case 0:
> +			imx_iomux_v3_setup_multiple_pads(
> +					usdhc2_pads, ARRAY_SIZE(usdhc2_pads));
> +			break;
> +		case 1:
> +			imx_iomux_v3_setup_multiple_pads(
> +					usdhc4_pads, ARRAY_SIZE(usdhc4_pads));
> +			break;
> +		default:
> +			printf("Warning: you configured more USDHC controllers
> +				   (%d) then supported by the board (%d)\n",
> +				   index + 1, CONFIG_SYS_FSL_USDHC_NUM);
> +			return status;
> +		}
> +
> +		status |= fsl_esdhc_initialize(bis, &usdhc_cfg[index]);
> +	}
> +
> +	return status;
> +}
> +#endif
> +
> +u32 get_board_rev(void)
> +{
> +	unsigned int fsl_system_rev;
> +	u32 cpu_type = readl(ANATOP_BASE_ADDR + 0x260);

Why don't you use get_cpu_rev() ?

> +
> +	/* Chip Silicon ID */
> +	fsl_system_rev = ((cpu_type >> 16) & 0xFF) << 12;
> +	/* Chip silicon major revision */
> +	fsl_system_rev |= ((cpu_type >> 8) & 0xFF) << 4;
> +	fsl_system_rev += 0x10;
> +	/* Chip silicon minor revision */
> +	fsl_system_rev |= cpu_type & 0xFF;
> +
> +	return fsl_system_rev;

If you use only cpu revision to boot old kernel, you need to set only
CONFIG_REVISION_TAG and a default (weak declared) get_board_rev is
automatically added.

> +}
> +
> +#ifdef CONFIG_MXC_SPI
> +iomux_v3_cfg_t const ecspi1_pads[] = {
> +	/* SS1 */
> +	MX6_PAD_EIM_D19__ECSPI1_SS1  | MUX_PAD_CTRL(SPI_PAD_CTRL),
> +	MX6_PAD_EIM_D17__ECSPI1_MISO | MUX_PAD_CTRL(SPI_PAD_CTRL),
> +	MX6_PAD_EIM_D18__ECSPI1_MOSI | MUX_PAD_CTRL(SPI_PAD_CTRL),
> +	MX6_PAD_EIM_D16__ECSPI1_SCLK | MUX_PAD_CTRL(SPI_PAD_CTRL),
> +};
> +
> +void setup_spi(void)
> +{
> +	gpio_direction_output(CONFIG_SF_DEFAULT_CS, 1);
> +	imx_iomux_v3_setup_multiple_pads(
> +				ecspi1_pads,
> +				ARRAY_SIZE(ecspi1_pads));
> +	printf("Setting up spi...\n");

Use puts for constant data. But why do we need this output at all ? It
seems a debug output, and then debug() should be taken.

> +}
> +#endif
> +
> +static void setup_buttons(void)
> +{
> +	imx_iomux_v3_setup_multiple_pads(
> +				button_pads,
> +				ARRAY_SIZE(button_pads));
> +}
> +
> +#ifdef CONFIG_CMD_SATA
> +
> +int setup_sata(void)
> +{
> +	struct iomuxc_base_regs *const iomuxc_regs
> +		= (struct iomuxc_base_regs *)IOMUXC_BASE_ADDR;
> +	int ret = enable_sata_clock();
> +	if (ret)
> +		return ret;
> +
> +	clrsetbits_le32(
> +		&iomuxc_regs->gpr[13],
> +		IOMUXC_GPR13_SATA_MASK,
> +		IOMUXC_GPR13_SATA_PHY_8_RXEQ_3P0DB
> +		|IOMUXC_GPR13_SATA_PHY_7_SATA2M
> +		|IOMUXC_GPR13_SATA_SPEED_3G
> +		|(3<<IOMUXC_GPR13_SATA_PHY_6_SHIFT)
> +		|IOMUXC_GPR13_SATA_SATA_PHY_5_SS_DISABLED
> +		|IOMUXC_GPR13_SATA_SATA_PHY_4_ATTEN_9_16
> +		|IOMUXC_GPR13_SATA_PHY_3_TXBOOST_0P00_DB
> +		|IOMUXC_GPR13_SATA_PHY_2_TX_1P104V
> +		|IOMUXC_GPR13_SATA_PHY_1_SLOW);
> +
> +	return 0;
> +}
> +#endif
> +
> +#if defined(CONFIG_VIDEO_IPUV3)
> +
> +struct display_info_t {
> +	int	bus;
> +	int	addr;
> +	int	pixfmt;
> +	int	(*detect)(struct display_info_t const *dev);
> +	void	(*enable)(struct display_info_t const *dev);
> +	struct	fb_videomode mode;
> +};
> +
> +
> +static int detect_hdmi(struct display_info_t const *dev)
> +{
> +	struct hdmi_regs *hdmi	= (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
> +	return readb(&hdmi->phy_stat0) & HDMI_PHY_HPD;
> +}
> +
> +static void enable_hdmi(struct display_info_t const *dev)
> +{
> +	struct hdmi_regs *hdmi	= (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
> +	u8 reg;
> +	printf("%s: setup HDMI monitor\n", __func__);
> +	reg = readb(&hdmi->phy_conf0);
> +	reg |= HDMI_PHY_CONF0_PDZ_MASK;
> +	writeb(reg, &hdmi->phy_conf0);
> +
> +	udelay(3000);
> +	reg |= HDMI_PHY_CONF0_ENTMDS_MASK;
> +	writeb(reg, &hdmi->phy_conf0);
> +	udelay(3000);
> +	reg |= HDMI_PHY_CONF0_GEN2_TXPWRON_MASK;
> +	writeb(reg, &hdmi->phy_conf0);
> +	writeb(HDMI_MC_PHYRSTZ_ASSERT, &hdmi->mc_phyrstz);
> +}
> +
> +static struct display_info_t const displays[] = {{
> +		.bus	= -1,
> +		.addr	= 0,
> +		.pixfmt	= IPU_PIX_FMT_RGB24,
> +		.detect	= detect_hdmi,
> +		.enable	= enable_hdmi,
> +		.mode	= {
> +			.name           = "HDMI",
> +			.refresh        = 60,
> +			.xres           = 640,
> +			.yres           = 480,
> +			.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
> +		} } };
> +
> +int board_video_skip(void)
> +{
> +	int i;
> +	int ret;
> +	char const *panel = getenv("panel");
> +	if (!panel) {
> +		for (i = 0; i < ARRAY_SIZE(displays); i++) {
> +			struct display_info_t const *dev = displays+i;
> +			if (dev->detect(dev)) {
> +				panel = dev->mode.name;
> +				printf("auto-detected panel %s\n", panel);
> +				break;
> +			}
> +		}
> +		if (!panel) {
> +			panel = displays[0].mode.name;
> +			printf("No panel detected: default to %s\n", panel);
> +		}
> +	} else {
> +		for (i = 0; i < ARRAY_SIZE(displays); i++) {
> +			if (!strcmp(panel, displays[i].mode.name))
> +				break;
> +		}
> +	}
> +	if (i < ARRAY_SIZE(displays)) {
> +		ret = ipuv3_fb_init(&displays[i].mode, 0,
> +							displays[i].pixfmt);
> +		if (!ret) {
> +			displays[i].enable(displays+i);
> +			printf(
> +				   "Display: %s (%ux%u)\n",
> +				   displays[i].mode.name,
> +				   displays[i].mode.xres,
> +				   displays[i].mode.yres);
> +		} else
> +			printf(
> +				   "LCD %s cannot be configured: %d\n",
> +				   displays[i].mode.name, ret);
> +	} else {
> +		printf("unsupported panel %s\n", panel);
> +		ret = -EINVAL;
> +	}
> +	return (0 != ret);
> +}
> +
> +static void setup_display(void)
> +{
> +	struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
> +	struct hdmi_regs *hdmi	= (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
> +
> +	int reg;
> +
> +	/* Turn on LDB0,IPU,IPU DI0 clocks */
> +	reg = __raw_readl(&mxc_ccm->CCGR3);
> +	reg |=   MXC_CCM_CCGR3_IPU1_IPU_DI0_OFFSET
> +		|MXC_CCM_CCGR3_LDB_DI0_MASK;
> +	writel(reg, &mxc_ccm->CCGR3);
> +
> +	/* Turn on HDMI PHY clock */
> +	reg = __raw_readl(&mxc_ccm->CCGR2);
> +	reg |=  MXC_CCM_CCGR2_HDMI_TX_IAHBCLK_MASK
> +		|MXC_CCM_CCGR2_HDMI_TX_ISFRCLK_MASK;
> +	writel(reg, &mxc_ccm->CCGR2);
> +
> +	/* clear HDMI PHY reset */
> +	writeb(HDMI_MC_PHYRSTZ_DEASSERT, &hdmi->mc_phyrstz);
> +}
> +#endif
> +
> +int board_early_init_f(void)
> +{
> +	setup_iomux_uart();
> +	setup_buttons();
> +
> +#if defined(CONFIG_VIDEO_IPUV3)
> +	setup_display();
> +#endif
> +	return 0;
> +}
> +
> +/*
> + * Do not overwrite the console
> + * Use always serial for U-Boot console
> + */
> +int overwrite_console(void)
> +{
> +	return 1;
> +}
> +
> +int board_init(void)
> +{
> +	u32 reg;
> +	writel(0x41736166, SNVS_BASE_ADDR + 0x64);/*set LPPGDR*/
> +	udelay(10);
> +	reg = readl(SNVS_BASE_ADDR + 0x4c);
> +	reg |= (1 << 3);
> +	writel(reg, SNVS_BASE_ADDR + 0x4c);/*clear LPSR*/
> +
> +	/* address of boot parameters */
> +	gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
> +
> +#ifdef CONFIG_MXC_SPI
> +	setup_spi();
> +#endif
> +	setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info0);
> +	setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1);
> +	setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info2);
> +
> +#ifdef CONFIG_CMD_SATA
> +	setup_sata();
> +#endif
> +
> +	return 0;
> +}
> +
> +int checkboard(void)
> +{
> +#ifdef CONFIG_MX6
> +	puts("Board: Congatec QMX6 Quad\n");
> +#endif
> +#ifdef CONFIG_MX6_DL
> +	puts("Board: Congatec QMX6 Dual\n");
> +#endif
> +	return 0;
> +}
> +
> +struct button_key {
> +	char const	*name;
> +	unsigned	gpnum;
> +	char		ident;
> +};
> +
> +static struct button_key const buttons[] = {
> +	{"recovery",	IMX_GPIO_NR(4, 5),	'r'},
> +};
> +
> +/*
> + * generate a null-terminated string containing the buttons pressed
> + * returns number of keys pressed
> + */
> +static int read_keys(char *buf)
> +{
> +	int i, numpressed = 0;
> +	for (i = 0; i < ARRAY_SIZE(buttons); i++) {
> +		if (!gpio_get_value(buttons[i].gpnum))
> +			buf[numpressed++] = buttons[i].ident;
> +	}
> +	buf[numpressed] = '\0';
> +	return numpressed;
> +}
> +
> +static int do_kbd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
> +{
> +	char envvalue[ARRAY_SIZE(buttons)+1];
> +	int numpressed = read_keys(envvalue);
> +	setenv("keybd", envvalue);
> +	return numpressed == 0;
> +}
> +
> +U_BOOT_CMD(
> +		   kbd, 1, 1, do_kbd,
> +		   "Tests for keypresses, sets 'keybd' environment variable",
> +		   "Returns 0 (true) to shell if key is pressed."
> +		   );
> +
> +#ifdef CONFIG_PREBOOT
> +static char const kbd_magic_prefix[] = "key_magic";
> +static char const kbd_command_prefix[] = "key_cmd";
> +
> +static void preboot_keys(void)
> +{
> +	int numpressed;
> +	char keypress[ARRAY_SIZE(buttons)+1];
> +	numpressed = read_keys(keypress);
> +	if (numpressed) {
> +		char *kbd_magic_keys = getenv("magic_keys");
> +		char *suffix;
> +		/*
> +		 * loop over all magic keys
> +		 */
> +		for (suffix = kbd_magic_keys; *suffix; ++suffix) {
> +			char *keys;
> +			char magic[sizeof(kbd_magic_prefix) + 1];
> +			sprintf(magic, "%s%c", kbd_magic_prefix, *suffix);
> +			keys = getenv(magic);
> +			if (keys) {
> +				if (!strcmp(keys, keypress))
> +					break;
> +			}
> +		}
> +		if (*suffix) {
> +			char cmd_name[sizeof(kbd_command_prefix) + 1];
> +			char *cmd;
> +			sprintf(cmd_name, "%s%c", kbd_command_prefix, *suffix);
> +			cmd = getenv(cmd_name);
> +			if (cmd) {
> +				setenv("preboot", cmd);
> +				return;
> +			}
> +		}
> +	}
> +}
> +#endif
> +

Really this file is very very similar to sabrelite. Then maybe the
decision to put it into Freescale directory is not so odd, but do we
have some way to factorize code ? I dislike that we duplicate so much
code only to change a few lines.

> +++ b/include/configs/cgtqmx6.h
> @@ -0,1 +1,294 @@
> +/*
> + * cgtqmx6.h
> + *
> + * Congatec Conga-QEVAl board configuration file.
> + *
> + * Copyright (C) 2013, Adeneo Embedded <www.adeneo-embedded.com>
> + * Leo Sartre, <lsartre@adeneo-embedded.com>
> + * Based on Freescale i.MX6Q Sabre Lite board configuration file.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.		See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + */
> +
> +#ifndef __CONFIG_H
> +#define __CONFIG_H
> +
> +#define CONFIG_MX6
> +/* MX6Q Quad */

comment is not very useful..

> +#define CONFIG_MX6Q
> +/* MX6Q Dual */
> +/* #define CONFIG_MX6DL */

This is dead code - drop it

I guess also that you took the sabrelite as reference, but you did it
sometimes ago. I have the feeling that it is based on an older status,
and it is worth you check also last changes for the sabrelite to get
them in your board.

> +/* I2C Configs */
> +#define CONFIG_CMD_I2C
> +#define CONFIG_I2C_MULTI_BUS
> +#define CONFIG_I2C_MXC
> +#define CONFIG_SYS_I2C_SPEED		100000
> +
> +/* MMC Configs */
> +#define CONFIG_FSL_ESDHC
> +#define CONFIG_FSL_USDHC
> +#define CONFIG_SYS_FSL_ESDHC_ADDR      0
> +#define CONFIG_SYS_FSL_USDHC_NUM       2

I need some explanation - this does not match with your board file,
where I have seen 3 SDHC controller. Am I wrong ?


> +/* Physical Memory Map */
> +#define CONFIG_NR_DRAM_BANKS	       1
> +#define PHYS_SDRAM		       MMDC0_ARB_BASE_ADDR
> +#ifdef CONFIG_MX6

CONFIG_MX6 is always set for i.MX6, and then which CPU is on board is
selected with CONFIG_MX6Q/CONFIG_MX6DL/CONFIG_MX6SL

> +#define PHYS_SDRAM_SIZE			       (1u * 1024 * 1024 * 1024)
> +#endif
> +#ifdef CONFIG_MX6_DL

This is not set and the usage seems wrong.  And there is CONFIG_MX6DL
and not CONFIG_MX6_DL

Best regards,
Stefano Babic
Eric Benard May 13, 2013, 3:03 p.m. UTC | #2
Hi Leo,

Le Mon, 13 May 2013 14:02:57 +0200,
"SARTRE Leo" <lsartre@adeneo-embedded.com> a écrit :
> diff --git a/board/freescale/cgtqmx6/cgtqmx6.c b/board/freescale/cgtqmx6/cgtqmx6.c
> new file mode 100644
> index 0000000..ed5476a
> --- /dev/null
> +++ b/board/freescale/cgtqmx6/cgtqmx6.c
> @@ -0,0 +1,630 @@
> +/*
> + * Copyright (C) 2013, Adeneo Embedded <www.adeneo-embedded.com>
> + * Leo Sartre, <lsartre@adeneo-embedded.com>
> + * Based on mx6qsabrelite.c file
> + *
cgtqmx6.c is a direct copy of mx6qsabrelite.c adapted to your board but
you remove the copyright to add your own, that's not a good practice.

> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + */
> +
> +#include <common.h>
> +#include <asm/io.h>
> +#include <asm/arch/clock.h>
> +#include <asm/arch/imx-regs.h>
> +#include <asm/arch/iomux.h>
> +#include <asm/arch/mx6-pins.h>
> +#include <asm/errno.h>
> +#include <asm/gpio.h>
> +#include <asm/imx-common/iomux-v3.h>
> +#include <asm/imx-common/mxc_i2c.h>
> +#include <asm/imx-common/boot_mode.h>
> +#include <mmc.h>
> +#include <fsl_esdhc.h>
> +#include <malloc.h>
> +#include <linux/fb.h>
> +#include <ipu_pixfmt.h>
> +#include <asm/arch/crm_regs.h>
> +#include <asm/arch/mxc_hdmi.h>
> +#include <i2c.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 SPI_PAD_CTRL (PAD_CTL_HYS |\
> +					  PAD_CTL_PUS_100K_DOWN |\
> +					  PAD_CTL_SPEED_MED     |\
> +					  PAD_CTL_DSE_40ohm     |\
> +					  PAD_CTL_SRE_FAST)
> +
> +#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 I2C_PAD_CTRL	(PAD_CTL_PKE | PAD_CTL_PUE |\
> +						 PAD_CTL_PUS_100K_UP |\
> +						 PAD_CTL_SPEED_MED   |\
> +						 PAD_CTL_DSE_40ohm   |\
> +						 PAD_CTL_HYS         |\
> +						 PAD_CTL_ODE         |\
> +						 PAD_CTL_SRE_FAST)
> +
> +int dram_init(void)
> +{
> +	gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
> +
> +	return 0;
> +}
> +
> +iomux_v3_cfg_t const uart1_pads[] = {
> +	MX6_PAD_CSI0_DAT10__UART1_TXD | MUX_PAD_CTRL(UART_PAD_CTRL),
> +	MX6_PAD_CSI0_DAT11__UART1_RXD | MUX_PAD_CTRL(UART_PAD_CTRL),
> +};
> +
> +iomux_v3_cfg_t const uart2_pads[] = {
> +	MX6_PAD_EIM_D26__UART2_TXD | MUX_PAD_CTRL(UART_PAD_CTRL),
> +	MX6_PAD_EIM_D27__UART2_RXD | MUX_PAD_CTRL(UART_PAD_CTRL),
> +};
> +
> +#define PC MUX_PAD_CTRL(I2C_PAD_CTRL)
> +
> +/* I2C1, SGTL5000 */
> +struct i2c_pads_info i2c_pad_info0 = {
> +	.scl = {
> +		.i2c_mode = MX6_PAD_EIM_D21__I2C1_SCL | PC,
> +		.gpio_mode = MX6_PAD_EIM_D21__GPIO_3_21 | PC,
> +		.gp = IMX_GPIO_NR(3, 21)
> +	},
> +	.sda = {
> +		.i2c_mode = MX6_PAD_EIM_D28__I2C1_SDA | PC,
> +		.gpio_mode = MX6_PAD_EIM_D28__GPIO_3_28 | PC,
> +		.gp = IMX_GPIO_NR(3, 28)
> +	}
> +};
> +
> +/* I2C2 Camera, MIPI */
> +struct i2c_pads_info i2c_pad_info1 = {
> +	.scl = {
> +		.i2c_mode = MX6_PAD_KEY_COL3__I2C2_SCL | PC,
> +		.gpio_mode = MX6_PAD_KEY_COL3__GPIO_4_12 | PC,
> +		.gp = IMX_GPIO_NR(4, 12)
> +	},
> +	.sda = {
> +		.i2c_mode = MX6_PAD_KEY_ROW3__I2C2_SDA | PC,
> +		.gpio_mode = MX6_PAD_KEY_ROW3__GPIO_4_13 | PC,
> +		.gp = IMX_GPIO_NR(4, 13)
> +	}
> +};
> +
> +struct i2c_pads_info i2c_pad_info2 = {
> +	.scl = {
> +		.i2c_mode = MX6_PAD_GPIO_3__I2C3_SCL | PC,
> +		.gpio_mode = MX6_PAD_GPIO_3__GPIO_1_3 | PC,
> +		.gp = IMX_GPIO_NR(1, 3)
> +	},
> +	.sda = {
> +		.i2c_mode = MX6_PAD_GPIO_6__I2C3_SDA | PC,
> +		.gpio_mode = MX6_PAD_GPIO_6__GPIO_1_6 | PC,
> +		.gp = IMX_GPIO_NR(1, 6)
> +	}
> +};
> +
> +
> +iomux_v3_cfg_t const usdhc1_pads[] = {
> +	MX6_PAD_SD1_CLK__USDHC1_CLK   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD1_CMD__USDHC1_CMD   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD1_DAT0__USDHC1_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD1_DAT1__USDHC1_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD1_DAT2__USDHC1_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD1_DAT3__USDHC1_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +};
> +
> +iomux_v3_cfg_t const usdhc2_pads[] = {
> +	MX6_PAD_SD2_CLK__USDHC2_CLK   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD2_CMD__USDHC2_CMD   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD2_DAT0__USDHC2_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD2_DAT1__USDHC2_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD2_DAT2__USDHC2_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD2_DAT3__USDHC2_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_GPIO_4__GPIO_1_4      | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +};
> +
> +iomux_v3_cfg_t const usdhc3_pads[] = {
> +	MX6_PAD_SD3_CLK__USDHC3_CLK   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD3_CMD__USDHC3_CMD   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD3_DAT0__USDHC3_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD3_DAT1__USDHC3_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD3_DAT2__USDHC3_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD3_DAT3__USDHC3_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD3_DAT4__USDHC3_DAT4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD3_DAT5__USDHC3_DAT5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD3_DAT6__USDHC3_DAT6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD3_DAT7__USDHC3_DAT7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD3_DAT5__GPIO_7_0    | MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */
> +};
> +
> +iomux_v3_cfg_t const usdhc4_pads[] = {
> +	MX6_PAD_SD4_CLK__USDHC4_CLK   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD4_CMD__USDHC4_CMD   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD4_DAT0__USDHC4_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD4_DAT1__USDHC4_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD4_DAT2__USDHC4_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD4_DAT3__USDHC4_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD4_DAT4__USDHC4_DAT4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD4_DAT5__USDHC4_DAT5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD4_DAT6__USDHC4_DAT6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_SD4_DAT7__USDHC4_DAT7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> +	MX6_PAD_NANDF_D6__GPIO_2_6    | MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */
> +};
> +
> +iomux_v3_cfg_t const usb_pads[] = {
> +	MX6_PAD_GPIO_17__GPIO_7_12 | MUX_PAD_CTRL(NO_PAD_CTRL),
> +};
> +
> +/* Button assignments*/
> +static iomux_v3_cfg_t const button_pads[] = {
> +	/* Recovery button */
> +	MX6_PAD_GPIO_19__GPIO_4_5	| MUX_PAD_CTRL(BUTTON_PAD_CTRL),
> +};
> +
> +
> +static void setup_iomux_uart(void)
> +{
> +	imx_iomux_v3_setup_multiple_pads(uart1_pads, ARRAY_SIZE(uart1_pads));
> +	imx_iomux_v3_setup_multiple_pads(uart2_pads, ARRAY_SIZE(uart2_pads));
> +}
> +
> +#ifdef CONFIG_USB_EHCI_MX6
> +int board_ehci_hcd_init(int port)
> +{
> +	imx_iomux_v3_setup_multiple_pads(usb_pads, ARRAY_SIZE(usb_pads));
> +
> +	/* Reset USB hub */
> +	gpio_direction_output(IMX_GPIO_NR(7, 12), 0);
> +	mdelay(2);
> +	gpio_set_value(IMX_GPIO_NR(7, 12), 1);
> +
> +	return 0;
> +}
> +#endif
> +
> +#ifdef CONFIG_FSL_ESDHC
> +struct fsl_esdhc_cfg usdhc_cfg[] = {
> +	{USDHC2_BASE_ADDR},
> +	{USDHC4_BASE_ADDR},
> +};
> +
here 2 & 4 base addresses.

> +int board_mmc_getcd(struct mmc *mmc)
> +{
> +	struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
> +	int ret;
> +
> +	switch (cfg->esdhc_base) {
> +	case USDHC2_BASE_ADDR:
> +		gpio_direction_input(IMX_GPIO_NR(1, 4));
> +		ret = !gpio_get_value(IMX_GPIO_NR(1, 4));
> +		break;
> +	case USDHC3_BASE_ADDR:
> +		gpio_direction_input(IMX_GPIO_NR(7, 0));
> +		ret = !gpio_get_value(IMX_GPIO_NR(7, 0));
> +		break;

here USDHC3 appears.

> +	case USDHC4_BASE_ADDR:
> +		gpio_direction_input(IMX_GPIO_NR(2, 6));
> +		ret = !gpio_get_value(IMX_GPIO_NR(2, 6));
> +		break;
> +	default:
> +		printf("Bad USDHC interface\n");
> +	}
> +
> +	return ret;
> +}
> +
> +int board_mmc_init(bd_t *bis)
> +{
> +	s32 status = 0;
> +	u32 index = 0;
> +
> +	usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
> +	usdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC4_CLK);
> +
but it's not handled here.

> +	for (index = 0; index < CONFIG_SYS_FSL_USDHC_NUM; ++index) {
> +		switch (index) {
> +		case 0:
> +			imx_iomux_v3_setup_multiple_pads(
> +					usdhc2_pads, ARRAY_SIZE(usdhc2_pads));
> +			break;
> +		case 1:
> +			imx_iomux_v3_setup_multiple_pads(
> +					usdhc4_pads, ARRAY_SIZE(usdhc4_pads));
> +			break;
> +		default:
> +			printf("Warning: you configured more USDHC controllers
> +				   (%d) then supported by the board (%d)\n",
> +				   index + 1, CONFIG_SYS_FSL_USDHC_NUM);
> +			return status;
> +		}
> +
> +		status |= fsl_esdhc_initialize(bis, &usdhc_cfg[index]);
> +	}
> +
> +	return status;
> +}
> +#endif
> +
> +u32 get_board_rev(void)
> +{
> +	unsigned int fsl_system_rev;
> +	u32 cpu_type = readl(ANATOP_BASE_ADDR + 0x260);
> +
> +	/* Chip Silicon ID */
> +	fsl_system_rev = ((cpu_type >> 16) & 0xFF) << 12;
> +	/* Chip silicon major revision */
> +	fsl_system_rev |= ((cpu_type >> 8) & 0xFF) << 4;
> +	fsl_system_rev += 0x10;
> +	/* Chip silicon minor revision */
> +	fsl_system_rev |= cpu_type & 0xFF;
> +
> +	return fsl_system_rev;
> +}
> +
> +#ifdef CONFIG_MXC_SPI
> +iomux_v3_cfg_t const ecspi1_pads[] = {
> +	/* SS1 */
> +	MX6_PAD_EIM_D19__ECSPI1_SS1  | MUX_PAD_CTRL(SPI_PAD_CTRL),
> +	MX6_PAD_EIM_D17__ECSPI1_MISO | MUX_PAD_CTRL(SPI_PAD_CTRL),
> +	MX6_PAD_EIM_D18__ECSPI1_MOSI | MUX_PAD_CTRL(SPI_PAD_CTRL),
> +	MX6_PAD_EIM_D16__ECSPI1_SCLK | MUX_PAD_CTRL(SPI_PAD_CTRL),
> +};
> +
> +void setup_spi(void)
> +{
> +	gpio_direction_output(CONFIG_SF_DEFAULT_CS, 1);
> +	imx_iomux_v3_setup_multiple_pads(
> +				ecspi1_pads,
> +				ARRAY_SIZE(ecspi1_pads));
> +	printf("Setting up spi...\n");
> +}
> +#endif
> +
> +static void setup_buttons(void)
> +{
> +	imx_iomux_v3_setup_multiple_pads(
> +				button_pads,
> +				ARRAY_SIZE(button_pads));
> +}
> +
> +#ifdef CONFIG_CMD_SATA
> +
> +int setup_sata(void)
> +{
> +	struct iomuxc_base_regs *const iomuxc_regs
> +		= (struct iomuxc_base_regs *)IOMUXC_BASE_ADDR;
> +	int ret = enable_sata_clock();
> +	if (ret)
> +		return ret;
> +
> +	clrsetbits_le32(
> +		&iomuxc_regs->gpr[13],
> +		IOMUXC_GPR13_SATA_MASK,
> +		IOMUXC_GPR13_SATA_PHY_8_RXEQ_3P0DB
> +		|IOMUXC_GPR13_SATA_PHY_7_SATA2M
> +		|IOMUXC_GPR13_SATA_SPEED_3G
> +		|(3<<IOMUXC_GPR13_SATA_PHY_6_SHIFT)
> +		|IOMUXC_GPR13_SATA_SATA_PHY_5_SS_DISABLED
> +		|IOMUXC_GPR13_SATA_SATA_PHY_4_ATTEN_9_16
> +		|IOMUXC_GPR13_SATA_PHY_3_TXBOOST_0P00_DB
> +		|IOMUXC_GPR13_SATA_PHY_2_TX_1P104V
> +		|IOMUXC_GPR13_SATA_PHY_1_SLOW);
> +
> +	return 0;
> +}
> +#endif
> +
> +#if defined(CONFIG_VIDEO_IPUV3)
> +
> +struct display_info_t {
> +	int	bus;
> +	int	addr;
> +	int	pixfmt;
> +	int	(*detect)(struct display_info_t const *dev);
> +	void	(*enable)(struct display_info_t const *dev);
> +	struct	fb_videomode mode;
> +};
> +
> +
> +static int detect_hdmi(struct display_info_t const *dev)
> +{
> +	struct hdmi_regs *hdmi	= (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
> +	return readb(&hdmi->phy_stat0) & HDMI_PHY_HPD;
> +}
> +
> +static void enable_hdmi(struct display_info_t const *dev)
> +{
> +	struct hdmi_regs *hdmi	= (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
> +	u8 reg;
> +	printf("%s: setup HDMI monitor\n", __func__);
> +	reg = readb(&hdmi->phy_conf0);
> +	reg |= HDMI_PHY_CONF0_PDZ_MASK;
> +	writeb(reg, &hdmi->phy_conf0);
> +
> +	udelay(3000);
> +	reg |= HDMI_PHY_CONF0_ENTMDS_MASK;
> +	writeb(reg, &hdmi->phy_conf0);
> +	udelay(3000);
> +	reg |= HDMI_PHY_CONF0_GEN2_TXPWRON_MASK;
> +	writeb(reg, &hdmi->phy_conf0);
> +	writeb(HDMI_MC_PHYRSTZ_ASSERT, &hdmi->mc_phyrstz);
> +}
> +
> +static struct display_info_t const displays[] = {{
> +		.bus	= -1,
> +		.addr	= 0,
> +		.pixfmt	= IPU_PIX_FMT_RGB24,
> +		.detect	= detect_hdmi,
> +		.enable	= enable_hdmi,
> +		.mode	= {
> +			.name           = "HDMI",
> +			.refresh        = 60,
> +			.xres           = 640,
> +			.yres           = 480,
> +			.pixclock       = 15385,
here you change the resolution from 1024x768 to 640x480 but keep the
same pixelclock margin & co : strange ?

> +			.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
> +		} } };
> +
> +int board_video_skip(void)
> +{
> +	int i;
> +	int ret;
> +	char const *panel = getenv("panel");
> +	if (!panel) {
> +		for (i = 0; i < ARRAY_SIZE(displays); i++) {
> +			struct display_info_t const *dev = displays+i;
> +			if (dev->detect(dev)) {
> +				panel = dev->mode.name;
> +				printf("auto-detected panel %s\n", panel);
> +				break;
> +			}
> +		}
> +		if (!panel) {
> +			panel = displays[0].mode.name;
> +			printf("No panel detected: default to %s\n", panel);
> +		}
> +	} else {
> +		for (i = 0; i < ARRAY_SIZE(displays); i++) {
> +			if (!strcmp(panel, displays[i].mode.name))
> +				break;
> +		}
> +	}
> +	if (i < ARRAY_SIZE(displays)) {
> +		ret = ipuv3_fb_init(&displays[i].mode, 0,
> +							displays[i].pixfmt);
> +		if (!ret) {
> +			displays[i].enable(displays+i);
> +			printf(
> +				   "Display: %s (%ux%u)\n",
> +				   displays[i].mode.name,
> +				   displays[i].mode.xres,
> +				   displays[i].mode.yres);
> +		} else
> +			printf(
> +				   "LCD %s cannot be configured: %d\n",
> +				   displays[i].mode.name, ret);
> +	} else {
> +		printf("unsupported panel %s\n", panel);
> +		ret = -EINVAL;
> +	}
> +	return (0 != ret);
> +}
> +
here you copied the function which handles several displays but only
have one HDMI output.

> +static void setup_display(void)
> +{
> +	struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
> +	struct hdmi_regs *hdmi	= (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
> +
> +	int reg;
> +
> +	/* Turn on LDB0,IPU,IPU DI0 clocks */
> +	reg = __raw_readl(&mxc_ccm->CCGR3);
> +	reg |=   MXC_CCM_CCGR3_IPU1_IPU_DI0_OFFSET
> +		|MXC_CCM_CCGR3_LDB_DI0_MASK;
> +	writel(reg, &mxc_ccm->CCGR3);
> +
> +	/* Turn on HDMI PHY clock */
> +	reg = __raw_readl(&mxc_ccm->CCGR2);
> +	reg |=  MXC_CCM_CCGR2_HDMI_TX_IAHBCLK_MASK
> +		|MXC_CCM_CCGR2_HDMI_TX_ISFRCLK_MASK;
> +	writel(reg, &mxc_ccm->CCGR2);
> +
> +	/* clear HDMI PHY reset */
> +	writeb(HDMI_MC_PHYRSTZ_DEASSERT, &hdmi->mc_phyrstz);
> +}
> +#endif
> +
> +int board_early_init_f(void)
> +{
> +	setup_iomux_uart();
> +	setup_buttons();
> +
> +#if defined(CONFIG_VIDEO_IPUV3)
> +	setup_display();
> +#endif
> +	return 0;
> +}
> +
> +/*
> + * Do not overwrite the console
> + * Use always serial for U-Boot console
> + */
> +int overwrite_console(void)
> +{
> +	return 1;
> +}
> +
> +int board_init(void)
> +{
> +	u32 reg;
> +	writel(0x41736166, SNVS_BASE_ADDR + 0x64);/*set LPPGDR*/
> +	udelay(10);
> +	reg = readl(SNVS_BASE_ADDR + 0x4c);
> +	reg |= (1 << 3);
> +	writel(reg, SNVS_BASE_ADDR + 0x4c);/*clear LPSR*/
> +
> +	/* address of boot parameters */
> +	gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
> +
> +#ifdef CONFIG_MXC_SPI
> +	setup_spi();
> +#endif
> +	setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info0);
> +	setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1);
> +	setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info2);
> +
> +#ifdef CONFIG_CMD_SATA
> +	setup_sata();
> +#endif
> +
> +	return 0;
> +}
> +
> +int checkboard(void)
> +{
> +#ifdef CONFIG_MX6
> +	puts("Board: Congatec QMX6 Quad\n");
> +#endif
> +#ifdef CONFIG_MX6_DL
> +	puts("Board: Congatec QMX6 Dual\n");
> +#endif
> +	return 0;
> +}
> +
> +struct button_key {
> +	char const	*name;
> +	unsigned	gpnum;
> +	char		ident;
> +};
> +
> +static struct button_key const buttons[] = {
> +	{"recovery",	IMX_GPIO_NR(4, 5),	'r'},
> +};
> +
> +/*
> + * generate a null-terminated string containing the buttons pressed
> + * returns number of keys pressed
> + */
> +static int read_keys(char *buf)
> +{
> +	int i, numpressed = 0;
> +	for (i = 0; i < ARRAY_SIZE(buttons); i++) {
> +		if (!gpio_get_value(buttons[i].gpnum))
> +			buf[numpressed++] = buttons[i].ident;
> +	}
> +	buf[numpressed] = '\0';
> +	return numpressed;
> +}
> +
> +static int do_kbd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
> +{
> +	char envvalue[ARRAY_SIZE(buttons)+1];
> +	int numpressed = read_keys(envvalue);
> +	setenv("keybd", envvalue);
> +	return numpressed == 0;
> +}
> +
> +U_BOOT_CMD(
> +		   kbd, 1, 1, do_kbd,
> +		   "Tests for keypresses, sets 'keybd' environment variable",
> +		   "Returns 0 (true) to shell if key is pressed."
> +		   );
> +
> +#ifdef CONFIG_PREBOOT
> +static char const kbd_magic_prefix[] = "key_magic";
> +static char const kbd_command_prefix[] = "key_cmd";
> +
> +static void preboot_keys(void)
> +{
> +	int numpressed;
> +	char keypress[ARRAY_SIZE(buttons)+1];
> +	numpressed = read_keys(keypress);
> +	if (numpressed) {
> +		char *kbd_magic_keys = getenv("magic_keys");
> +		char *suffix;
> +		/*
> +		 * loop over all magic keys
> +		 */
> +		for (suffix = kbd_magic_keys; *suffix; ++suffix) {
> +			char *keys;
> +			char magic[sizeof(kbd_magic_prefix) + 1];
> +			sprintf(magic, "%s%c", kbd_magic_prefix, *suffix);
> +			keys = getenv(magic);
> +			if (keys) {
> +				if (!strcmp(keys, keypress))
> +					break;
> +			}
> +		}
> +		if (*suffix) {
> +			char cmd_name[sizeof(kbd_command_prefix) + 1];
> +			char *cmd;
> +			sprintf(cmd_name, "%s%c", kbd_command_prefix, *suffix);
> +			cmd = getenv(cmd_name);
> +			if (cmd) {
> +				setenv("preboot", cmd);
> +				return;
> +			}
> +		}
> +	}
> +}
> +#endif
> +
you copy some code used to handled several buttons but only have one,
maybe you can simplify the code to your use case.

> +#ifdef CONFIG_CMD_BMODE
> +static const struct boot_mode board_boot_modes[] = {
> +	/* 4 bit bus width */
> +	{"mmc0",	MAKE_CFGVAL(0x50, 0x30, 0x00, 0x00)},
> +	{"mmc1",	MAKE_CFGVAL(0x50, 0x38, 0x00, 0x00)},

same values as sabrelite but you don't seem to use the same USDHC
peripherals : isn't that wrong ?

Eric
SARTRE Leo May 13, 2013, 3:09 p.m. UTC | #3
On Monday 13 May 2013 14:58:32, Stefano Babic wrote :
> On 13/05/2013 14:02, SARTRE Leo wrote:
> > Signed-off-by: Leo Sartre <lsartre@adeneo-embedded.com>
> > ---
> 
> Hi Leo,

Hi Stefano,

I will rework my patch taking all your remarks, and those from Wolfgang, into 
acount, I just like to talk a bit about the problem of duplicated code that 
you spooted. 
This patch is just a first commit for this board, there will come other commits 
to add missing functionnalities provided by the board, so I think that it will 
be more convenient to have a separate file even if for now, it is very similar 
to the sabrelite file. 
Anyway I will rework my patch and post again a cleaner version.

Best regards,
> 
> >  board/freescale/cgtqmx6/Makefile  |   42 +++
> >  board/freescale/cgtqmx6/cgtqmx6.c |  627
> >  +++++++++++++++++++++++++++++++++++++ boards.cfg                       
> >  |    1 +
> >  include/configs/cgtqmx6.h         |  294 +++++++++++++++++
> 
> You have also to update the MAINTAINERS file.
> 
> As I understand from the Website, even if the board can be derived from
> the SabreLite, it is a different product from a different vendor.
> 
> Why should the board then be put into freescale/ directory ?
> 
> Generally we have the schema:
> 
> board/<board_name>
> 
> or
> 
> board/<vendor_name>/<board_name>
> 
> > diff --git a/board/freescale/cgtqmx6/Makefile
> > b/board/freescale/cgtqmx6/Makefile new file mode 100644
> > index 0000000..a17603e
> > --- /dev/null
> > +++ b/board/freescale/cgtqmx6/Makefile
> > @@ -0,0 +1,41 @@
> > +#
> > +# Copyright (C) 2007, Guennadi Liakhovetski <lg@denx.de>
> > +#
> > +# (C) Copyright 2013 Adeneo Embedded <www.adeneo-embedded.com>
> > +#
> > +# This program is free software; you can redistribute it and/or
> > +# modify it under the terms of the GNU General Public License as
> > +# published by the Free Software Foundation; either version 2 of
> > +# the License, or (at your option) any later version.
> > +#
> > +# This program is distributed in the hope that it will be useful,
> > +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > +# GNU General Public License for more details.
> > +#
> > +# You should have received a copy of the GNU General Public License
> > +# along with this program; if not, write to the Free Software
> > +# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> > +# MA 02111-1307 USA
> > +#
> > +
> > +include $(TOPDIR)/config.mk
> > +
> > +LIB    = $(obj)lib$(BOARD).o
> > +
> > +COBJS  := cgtqmx6.o
> > +
> > +SRCS   := $(COBJS:.o=.c)
> > +OBJS   := $(addprefix $(obj),$(COBJS))
> > +
> > +$(LIB):        $(obj).depend $(OBJS)
> > +	$(call cmd_link_o_target, $(OBJS))
> > +
> > +########################################################################
> > # +
> > +# defines $(obj).depend target
> > +include $(SRCTREE)/rules.mk
> > +
> > +sinclude $(obj).depend
> > +
> > +########################################################################
> > # diff --git a/board/freescale/cgtqmx6/cgtqmx6.c
> > b/board/freescale/cgtqmx6/cgtqmx6.c new file mode 100644
> > index 0000000..ed5476a
> > --- /dev/null
> > +++ b/board/freescale/cgtqmx6/cgtqmx6.c
> > @@ -0,0 +1,630 @@
> > +/*
> > + * Copyright (C) 2013, Adeneo Embedded <www.adeneo-embedded.com>
> > + * Leo Sartre, <lsartre@adeneo-embedded.com>
> > + * Based on mx6qsabrelite.c file
> > + *
> > + * This program is free software; you can redistribute it and/or
> > + * modify it under the terms of the GNU General Public License as
> > + * published by the Free Software Foundation; either version 2 of
> > + * the License, or (at your option) any later version.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
> > + * GNU General Public License for more details.
> > + *
> > + * You should have received a copy of the GNU General Public License
> > + * along with this program; if not, write to the Free Software
> > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> > + * MA 02111-1307 USA
> > + */
> > +
> > +#include <common.h>
> > +#include <asm/io.h>
> > +#include <asm/arch/clock.h>
> > +#include <asm/arch/imx-regs.h>
> > +#include <asm/arch/iomux.h>
> > +#include <asm/arch/mx6-pins.h>
> > +#include <asm/errno.h>
> > +#include <asm/gpio.h>
> > +#include <asm/imx-common/iomux-v3.h>
> > +#include <asm/imx-common/mxc_i2c.h>
> > +#include <asm/imx-common/boot_mode.h>
> > +#include <mmc.h>
> > +#include <fsl_esdhc.h>
> > +#include <malloc.h>
> > +#include <linux/fb.h>
> > +#include <ipu_pixfmt.h>
> > +#include <asm/arch/crm_regs.h>
> > +#include <asm/arch/mxc_hdmi.h>
> > +#include <i2c.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 SPI_PAD_CTRL (PAD_CTL_HYS |\
> > +					  PAD_CTL_PUS_100K_DOWN |\
> > +					  PAD_CTL_SPEED_MED     |\
> > +					  PAD_CTL_DSE_40ohm     |\
> > +					  PAD_CTL_SRE_FAST)
> > +
> > +#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 I2C_PAD_CTRL	(PAD_CTL_PKE | PAD_CTL_PUE |\
> > +						 PAD_CTL_PUS_100K_UP |\
> > +						 PAD_CTL_SPEED_MED   |\
> > +						 PAD_CTL_DSE_40ohm   |\
> > +						 PAD_CTL_HYS         |\
> > +						 PAD_CTL_ODE         |\
> > +						 PAD_CTL_SRE_FAST)
> > +
> > +int dram_init(void)
> > +{
> > +	gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
> > +
> > +	return 0;
> > +}
> > +
> > +iomux_v3_cfg_t const uart1_pads[] = {
> > +	MX6_PAD_CSI0_DAT10__UART1_TXD | MUX_PAD_CTRL(UART_PAD_CTRL),
> > +	MX6_PAD_CSI0_DAT11__UART1_RXD | MUX_PAD_CTRL(UART_PAD_CTRL),
> > +};
> > +
> > +iomux_v3_cfg_t const uart2_pads[] = {
> > +	MX6_PAD_EIM_D26__UART2_TXD | MUX_PAD_CTRL(UART_PAD_CTRL),
> > +	MX6_PAD_EIM_D27__UART2_RXD | MUX_PAD_CTRL(UART_PAD_CTRL),
> > +};
> > +
> > +#define PC MUX_PAD_CTRL(I2C_PAD_CTRL)
> > +
> > +/* I2C1, SGTL5000 */
> > +struct i2c_pads_info i2c_pad_info0 = {
> > +	.scl = {
> > +		.i2c_mode = MX6_PAD_EIM_D21__I2C1_SCL | PC,
> > +		.gpio_mode = MX6_PAD_EIM_D21__GPIO_3_21 | PC,
> > +		.gp = IMX_GPIO_NR(3, 21)
> > +	},
> > +	.sda = {
> > +		.i2c_mode = MX6_PAD_EIM_D28__I2C1_SDA | PC,
> > +		.gpio_mode = MX6_PAD_EIM_D28__GPIO_3_28 | PC,
> > +		.gp = IMX_GPIO_NR(3, 28)
> > +	}
> > +};
> > +
> > +/* I2C2 Camera, MIPI */
> > +struct i2c_pads_info i2c_pad_info1 = {
> > +	.scl = {
> > +		.i2c_mode = MX6_PAD_KEY_COL3__I2C2_SCL | PC,
> > +		.gpio_mode = MX6_PAD_KEY_COL3__GPIO_4_12 | PC,
> > +		.gp = IMX_GPIO_NR(4, 12)
> > +	},
> > +	.sda = {
> > +		.i2c_mode = MX6_PAD_KEY_ROW3__I2C2_SDA | PC,
> > +		.gpio_mode = MX6_PAD_KEY_ROW3__GPIO_4_13 | PC,
> > +		.gp = IMX_GPIO_NR(4, 13)
> > +	}
> > +};
> > +
> > +struct i2c_pads_info i2c_pad_info2 = {
> > +	.scl = {
> > +		.i2c_mode = MX6_PAD_GPIO_3__I2C3_SCL | PC,
> > +		.gpio_mode = MX6_PAD_GPIO_3__GPIO_1_3 | PC,
> > +		.gp = IMX_GPIO_NR(1, 3)
> > +	},
> > +	.sda = {
> > +		.i2c_mode = MX6_PAD_GPIO_6__I2C3_SDA | PC,
> > +		.gpio_mode = MX6_PAD_GPIO_6__GPIO_1_6 | PC,
> > +		.gp = IMX_GPIO_NR(1, 6)
> > +	}
> > +};
> > +
> > +
> > +iomux_v3_cfg_t const usdhc1_pads[] = {
> > +	MX6_PAD_SD1_CLK__USDHC1_CLK   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> > +	MX6_PAD_SD1_CMD__USDHC1_CMD   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> > +	MX6_PAD_SD1_DAT0__USDHC1_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> > +	MX6_PAD_SD1_DAT1__USDHC1_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> > +	MX6_PAD_SD1_DAT2__USDHC1_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> > +	MX6_PAD_SD1_DAT3__USDHC1_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> > +};
> > +
> > +iomux_v3_cfg_t const usdhc2_pads[] = {
> > +	MX6_PAD_SD2_CLK__USDHC2_CLK   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> > +	MX6_PAD_SD2_CMD__USDHC2_CMD   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> > +	MX6_PAD_SD2_DAT0__USDHC2_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> > +	MX6_PAD_SD2_DAT1__USDHC2_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> > +	MX6_PAD_SD2_DAT2__USDHC2_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> > +	MX6_PAD_SD2_DAT3__USDHC2_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> > +	MX6_PAD_GPIO_4__GPIO_1_4      | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> > +};
> > +
> > +iomux_v3_cfg_t const usdhc3_pads[] = {
> > +	MX6_PAD_SD3_CLK__USDHC3_CLK   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> > +	MX6_PAD_SD3_CMD__USDHC3_CMD   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> > +	MX6_PAD_SD3_DAT0__USDHC3_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> > +	MX6_PAD_SD3_DAT1__USDHC3_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> > +	MX6_PAD_SD3_DAT2__USDHC3_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> > +	MX6_PAD_SD3_DAT3__USDHC3_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> > +	MX6_PAD_SD3_DAT4__USDHC3_DAT4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> > +	MX6_PAD_SD3_DAT5__USDHC3_DAT5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> > +	MX6_PAD_SD3_DAT6__USDHC3_DAT6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> > +	MX6_PAD_SD3_DAT7__USDHC3_DAT7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> > +	MX6_PAD_SD3_DAT5__GPIO_7_0    | MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */
> > +};
> > +
> > +iomux_v3_cfg_t const usdhc4_pads[] = {
> > +	MX6_PAD_SD4_CLK__USDHC4_CLK   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> > +	MX6_PAD_SD4_CMD__USDHC4_CMD   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> > +	MX6_PAD_SD4_DAT0__USDHC4_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> > +	MX6_PAD_SD4_DAT1__USDHC4_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> > +	MX6_PAD_SD4_DAT2__USDHC4_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> > +	MX6_PAD_SD4_DAT3__USDHC4_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> > +	MX6_PAD_SD4_DAT4__USDHC4_DAT4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> > +	MX6_PAD_SD4_DAT5__USDHC4_DAT5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> > +	MX6_PAD_SD4_DAT6__USDHC4_DAT6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> > +	MX6_PAD_SD4_DAT7__USDHC4_DAT7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
> > +	MX6_PAD_NANDF_D6__GPIO_2_6    | MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */
> > +};
> > +
> > +iomux_v3_cfg_t const usb_pads[] = {
> > +	MX6_PAD_GPIO_17__GPIO_7_12 | MUX_PAD_CTRL(NO_PAD_CTRL),
> > +};
> > +
> > +/* Button assignments*/
> > +static iomux_v3_cfg_t const button_pads[] = {
> > +	/* Recovery button */
> > +	MX6_PAD_GPIO_19__GPIO_4_5	| MUX_PAD_CTRL(BUTTON_PAD_CTRL),
> > +};
> > +
> > +
> > +static void setup_iomux_uart(void)
> > +{
> > +	imx_iomux_v3_setup_multiple_pads(uart1_pads, ARRAY_SIZE(uart1_pads));
> > +	imx_iomux_v3_setup_multiple_pads(uart2_pads, ARRAY_SIZE(uart2_pads));
> > +}
> > +
> > +#ifdef CONFIG_USB_EHCI_MX6
> > +int board_ehci_hcd_init(int port)
> > +{
> > +	imx_iomux_v3_setup_multiple_pads(usb_pads, ARRAY_SIZE(usb_pads));
> > +
> > +	/* Reset USB hub */
> > +	gpio_direction_output(IMX_GPIO_NR(7, 12), 0);
> > +	mdelay(2);
> > +	gpio_set_value(IMX_GPIO_NR(7, 12), 1);
> > +
> > +	return 0;
> > +}
> > +#endif
> > +
> > +#ifdef CONFIG_FSL_ESDHC
> > +struct fsl_esdhc_cfg usdhc_cfg[] = {
> > +	{USDHC2_BASE_ADDR},
> > +	{USDHC4_BASE_ADDR},
> > +};
> > +
> > +int board_mmc_getcd(struct mmc *mmc)
> > +{
> > +	struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
> > +	int ret;
> > +
> > +	switch (cfg->esdhc_base) {
> > +	case USDHC2_BASE_ADDR:
> > +		gpio_direction_input(IMX_GPIO_NR(1, 4));
> > +		ret = !gpio_get_value(IMX_GPIO_NR(1, 4));
> > +		break;
> > +	case USDHC3_BASE_ADDR:
> > +		gpio_direction_input(IMX_GPIO_NR(7, 0));
> > +		ret = !gpio_get_value(IMX_GPIO_NR(7, 0));
> > +		break;
> > +	case USDHC4_BASE_ADDR:
> > +		gpio_direction_input(IMX_GPIO_NR(2, 6));
> > +		ret = !gpio_get_value(IMX_GPIO_NR(2, 6));
> > +		break;
> > +	default:
> > +		printf("Bad USDHC interface\n");
> > +	}
> > +
> > +	return ret;
> > +}
> > +
> > +int board_mmc_init(bd_t *bis)
> > +{
> > +	s32 status = 0;
> > +	u32 index = 0;
> > +
> > +	usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
> > +	usdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC4_CLK);
> > +
> > +	for (index = 0; index < CONFIG_SYS_FSL_USDHC_NUM; ++index) {
> > +		switch (index) {
> > +		case 0:
> > +			imx_iomux_v3_setup_multiple_pads(
> > +					usdhc2_pads, ARRAY_SIZE(usdhc2_pads));
> > +			break;
> > +		case 1:
> > +			imx_iomux_v3_setup_multiple_pads(
> > +					usdhc4_pads, ARRAY_SIZE(usdhc4_pads));
> > +			break;
> > +		default:
> > +			printf("Warning: you configured more USDHC controllers
> > +				   (%d) then supported by the board (%d)\n",
> > +				   index + 1, CONFIG_SYS_FSL_USDHC_NUM);
> > +			return status;
> > +		}
> > +
> > +		status |= fsl_esdhc_initialize(bis, &usdhc_cfg[index]);
> > +	}
> > +
> > +	return status;
> > +}
> > +#endif
> > +
> > +u32 get_board_rev(void)
> > +{
> > +	unsigned int fsl_system_rev;
> > +	u32 cpu_type = readl(ANATOP_BASE_ADDR + 0x260);
> 
> Why don't you use get_cpu_rev() ?
> 
> > +
> > +	/* Chip Silicon ID */
> > +	fsl_system_rev = ((cpu_type >> 16) & 0xFF) << 12;
> > +	/* Chip silicon major revision */
> > +	fsl_system_rev |= ((cpu_type >> 8) & 0xFF) << 4;
> > +	fsl_system_rev += 0x10;
> > +	/* Chip silicon minor revision */
> > +	fsl_system_rev |= cpu_type & 0xFF;
> > +
> > +	return fsl_system_rev;
> 
> If you use only cpu revision to boot old kernel, you need to set only
> CONFIG_REVISION_TAG and a default (weak declared) get_board_rev is
> automatically added.
> 
> > +}
> > +
> > +#ifdef CONFIG_MXC_SPI
> > +iomux_v3_cfg_t const ecspi1_pads[] = {
> > +	/* SS1 */
> > +	MX6_PAD_EIM_D19__ECSPI1_SS1  | MUX_PAD_CTRL(SPI_PAD_CTRL),
> > +	MX6_PAD_EIM_D17__ECSPI1_MISO | MUX_PAD_CTRL(SPI_PAD_CTRL),
> > +	MX6_PAD_EIM_D18__ECSPI1_MOSI | MUX_PAD_CTRL(SPI_PAD_CTRL),
> > +	MX6_PAD_EIM_D16__ECSPI1_SCLK | MUX_PAD_CTRL(SPI_PAD_CTRL),
> > +};
> > +
> > +void setup_spi(void)
> > +{
> > +	gpio_direction_output(CONFIG_SF_DEFAULT_CS, 1);
> > +	imx_iomux_v3_setup_multiple_pads(
> > +				ecspi1_pads,
> > +				ARRAY_SIZE(ecspi1_pads));
> > +	printf("Setting up spi...\n");
> 
> Use puts for constant data. But why do we need this output at all ? It
> seems a debug output, and then debug() should be taken.
> 
> > +}
> > +#endif
> > +
> > +static void setup_buttons(void)
> > +{
> > +	imx_iomux_v3_setup_multiple_pads(
> > +				button_pads,
> > +				ARRAY_SIZE(button_pads));
> > +}
> > +
> > +#ifdef CONFIG_CMD_SATA
> > +
> > +int setup_sata(void)
> > +{
> > +	struct iomuxc_base_regs *const iomuxc_regs
> > +		= (struct iomuxc_base_regs *)IOMUXC_BASE_ADDR;
> > +	int ret = enable_sata_clock();
> > +	if (ret)
> > +		return ret;
> > +
> > +	clrsetbits_le32(
> > +		&iomuxc_regs->gpr[13],
> > +		IOMUXC_GPR13_SATA_MASK,
> > +		IOMUXC_GPR13_SATA_PHY_8_RXEQ_3P0DB
> > +		|IOMUXC_GPR13_SATA_PHY_7_SATA2M
> > +		|IOMUXC_GPR13_SATA_SPEED_3G
> > +		|(3<<IOMUXC_GPR13_SATA_PHY_6_SHIFT)
> > +		|IOMUXC_GPR13_SATA_SATA_PHY_5_SS_DISABLED
> > +		|IOMUXC_GPR13_SATA_SATA_PHY_4_ATTEN_9_16
> > +		|IOMUXC_GPR13_SATA_PHY_3_TXBOOST_0P00_DB
> > +		|IOMUXC_GPR13_SATA_PHY_2_TX_1P104V
> > +		|IOMUXC_GPR13_SATA_PHY_1_SLOW);
> > +
> > +	return 0;
> > +}
> > +#endif
> > +
> > +#if defined(CONFIG_VIDEO_IPUV3)
> > +
> > +struct display_info_t {
> > +	int	bus;
> > +	int	addr;
> > +	int	pixfmt;
> > +	int	(*detect)(struct display_info_t const *dev);
> > +	void	(*enable)(struct display_info_t const *dev);
> > +	struct	fb_videomode mode;
> > +};
> > +
> > +
> > +static int detect_hdmi(struct display_info_t const *dev)
> > +{
> > +	struct hdmi_regs *hdmi	= (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
> > +	return readb(&hdmi->phy_stat0) & HDMI_PHY_HPD;
> > +}
> > +
> > +static void enable_hdmi(struct display_info_t const *dev)
> > +{
> > +	struct hdmi_regs *hdmi	= (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
> > +	u8 reg;
> > +	printf("%s: setup HDMI monitor\n", __func__);
> > +	reg = readb(&hdmi->phy_conf0);
> > +	reg |= HDMI_PHY_CONF0_PDZ_MASK;
> > +	writeb(reg, &hdmi->phy_conf0);
> > +
> > +	udelay(3000);
> > +	reg |= HDMI_PHY_CONF0_ENTMDS_MASK;
> > +	writeb(reg, &hdmi->phy_conf0);
> > +	udelay(3000);
> > +	reg |= HDMI_PHY_CONF0_GEN2_TXPWRON_MASK;
> > +	writeb(reg, &hdmi->phy_conf0);
> > +	writeb(HDMI_MC_PHYRSTZ_ASSERT, &hdmi->mc_phyrstz);
> > +}
> > +
> > +static struct display_info_t const displays[] = {{
> > +		.bus	= -1,
> > +		.addr	= 0,
> > +		.pixfmt	= IPU_PIX_FMT_RGB24,
> > +		.detect	= detect_hdmi,
> > +		.enable	= enable_hdmi,
> > +		.mode	= {
> > +			.name           = "HDMI",
> > +			.refresh        = 60,
> > +			.xres           = 640,
> > +			.yres           = 480,
> > +			.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
> > +		} } };
> > +
> > +int board_video_skip(void)
> > +{
> > +	int i;
> > +	int ret;
> > +	char const *panel = getenv("panel");
> > +	if (!panel) {
> > +		for (i = 0; i < ARRAY_SIZE(displays); i++) {
> > +			struct display_info_t const *dev = displays+i;
> > +			if (dev->detect(dev)) {
> > +				panel = dev->mode.name;
> > +				printf("auto-detected panel %s\n", panel);
> > +				break;
> > +			}
> > +		}
> > +		if (!panel) {
> > +			panel = displays[0].mode.name;
> > +			printf("No panel detected: default to %s\n", panel);
> > +		}
> > +	} else {
> > +		for (i = 0; i < ARRAY_SIZE(displays); i++) {
> > +			if (!strcmp(panel, displays[i].mode.name))
> > +				break;
> > +		}
> > +	}
> > +	if (i < ARRAY_SIZE(displays)) {
> > +		ret = ipuv3_fb_init(&displays[i].mode, 0,
> > +							displays[i].pixfmt);
> > +		if (!ret) {
> > +			displays[i].enable(displays+i);
> > +			printf(
> > +				   "Display: %s (%ux%u)\n",
> > +				   displays[i].mode.name,
> > +				   displays[i].mode.xres,
> > +				   displays[i].mode.yres);
> > +		} else
> > +			printf(
> > +				   "LCD %s cannot be configured: %d\n",
> > +				   displays[i].mode.name, ret);
> > +	} else {
> > +		printf("unsupported panel %s\n", panel);
> > +		ret = -EINVAL;
> > +	}
> > +	return (0 != ret);
> > +}
> > +
> > +static void setup_display(void)
> > +{
> > +	struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
> > +	struct hdmi_regs *hdmi	= (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
> > +
> > +	int reg;
> > +
> > +	/* Turn on LDB0,IPU,IPU DI0 clocks */
> > +	reg = __raw_readl(&mxc_ccm->CCGR3);
> > +	reg |=   MXC_CCM_CCGR3_IPU1_IPU_DI0_OFFSET
> > +		|MXC_CCM_CCGR3_LDB_DI0_MASK;
> > +	writel(reg, &mxc_ccm->CCGR3);
> > +
> > +	/* Turn on HDMI PHY clock */
> > +	reg = __raw_readl(&mxc_ccm->CCGR2);
> > +	reg |=  MXC_CCM_CCGR2_HDMI_TX_IAHBCLK_MASK
> > +		|MXC_CCM_CCGR2_HDMI_TX_ISFRCLK_MASK;
> > +	writel(reg, &mxc_ccm->CCGR2);
> > +
> > +	/* clear HDMI PHY reset */
> > +	writeb(HDMI_MC_PHYRSTZ_DEASSERT, &hdmi->mc_phyrstz);
> > +}
> > +#endif
> > +
> > +int board_early_init_f(void)
> > +{
> > +	setup_iomux_uart();
> > +	setup_buttons();
> > +
> > +#if defined(CONFIG_VIDEO_IPUV3)
> > +	setup_display();
> > +#endif
> > +	return 0;
> > +}
> > +
> > +/*
> > + * Do not overwrite the console
> > + * Use always serial for U-Boot console
> > + */
> > +int overwrite_console(void)
> > +{
> > +	return 1;
> > +}
> > +
> > +int board_init(void)
> > +{
> > +	u32 reg;
> > +	writel(0x41736166, SNVS_BASE_ADDR + 0x64);/*set LPPGDR*/
> > +	udelay(10);
> > +	reg = readl(SNVS_BASE_ADDR + 0x4c);
> > +	reg |= (1 << 3);
> > +	writel(reg, SNVS_BASE_ADDR + 0x4c);/*clear LPSR*/
> > +
> > +	/* address of boot parameters */
> > +	gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
> > +
> > +#ifdef CONFIG_MXC_SPI
> > +	setup_spi();
> > +#endif
> > +	setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info0);
> > +	setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1);
> > +	setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info2);
> > +
> > +#ifdef CONFIG_CMD_SATA
> > +	setup_sata();
> > +#endif
> > +
> > +	return 0;
> > +}
> > +
> > +int checkboard(void)
> > +{
> > +#ifdef CONFIG_MX6
> > +	puts("Board: Congatec QMX6 Quad\n");
> > +#endif
> > +#ifdef CONFIG_MX6_DL
> > +	puts("Board: Congatec QMX6 Dual\n");
> > +#endif
> > +	return 0;
> > +}
> > +
> > +struct button_key {
> > +	char const	*name;
> > +	unsigned	gpnum;
> > +	char		ident;
> > +};
> > +
> > +static struct button_key const buttons[] = {
> > +	{"recovery",	IMX_GPIO_NR(4, 5),	'r'},
> > +};
> > +
> > +/*
> > + * generate a null-terminated string containing the buttons pressed
> > + * returns number of keys pressed
> > + */
> > +static int read_keys(char *buf)
> > +{
> > +	int i, numpressed = 0;
> > +	for (i = 0; i < ARRAY_SIZE(buttons); i++) {
> > +		if (!gpio_get_value(buttons[i].gpnum))
> > +			buf[numpressed++] = buttons[i].ident;
> > +	}
> > +	buf[numpressed] = '\0';
> > +	return numpressed;
> > +}
> > +
> > +static int do_kbd(cmd_tbl_t *cmdtp, int flag, int argc, char * const
> > argv[]) +{
> > +	char envvalue[ARRAY_SIZE(buttons)+1];
> > +	int numpressed = read_keys(envvalue);
> > +	setenv("keybd", envvalue);
> > +	return numpressed == 0;
> > +}
> > +
> > +U_BOOT_CMD(
> > +		   kbd, 1, 1, do_kbd,
> > +		   "Tests for keypresses, sets 'keybd' environment variable",
> > +		   "Returns 0 (true) to shell if key is pressed."
> > +		   );
> > +
> > +#ifdef CONFIG_PREBOOT
> > +static char const kbd_magic_prefix[] = "key_magic";
> > +static char const kbd_command_prefix[] = "key_cmd";
> > +
> > +static void preboot_keys(void)
> > +{
> > +	int numpressed;
> > +	char keypress[ARRAY_SIZE(buttons)+1];
> > +	numpressed = read_keys(keypress);
> > +	if (numpressed) {
> > +		char *kbd_magic_keys = getenv("magic_keys");
> > +		char *suffix;
> > +		/*
> > +		 * loop over all magic keys
> > +		 */
> > +		for (suffix = kbd_magic_keys; *suffix; ++suffix) {
> > +			char *keys;
> > +			char magic[sizeof(kbd_magic_prefix) + 1];
> > +			sprintf(magic, "%s%c", kbd_magic_prefix, *suffix);
> > +			keys = getenv(magic);
> > +			if (keys) {
> > +				if (!strcmp(keys, keypress))
> > +					break;
> > +			}
> > +		}
> > +		if (*suffix) {
> > +			char cmd_name[sizeof(kbd_command_prefix) + 1];
> > +			char *cmd;
> > +			sprintf(cmd_name, "%s%c", kbd_command_prefix, *suffix);
> > +			cmd = getenv(cmd_name);
> > +			if (cmd) {
> > +				setenv("preboot", cmd);
> > +				return;
> > +			}
> > +		}
> > +	}
> > +}
> > +#endif
> > +
> 
> Really this file is very very similar to sabrelite. Then maybe the
> decision to put it into Freescale directory is not so odd, but do we
> have some way to factorize code ? I dislike that we duplicate so much
> code only to change a few lines.
> 
> > +++ b/include/configs/cgtqmx6.h
> > @@ -0,1 +1,294 @@
> > +/*
> > + * cgtqmx6.h
> > + *
> > + * Congatec Conga-QEVAl board configuration file.
> > + *
> > + * Copyright (C) 2013, Adeneo Embedded <www.adeneo-embedded.com>
> > + * Leo Sartre, <lsartre@adeneo-embedded.com>
> > + * Based on Freescale i.MX6Q Sabre Lite board configuration file.
> > + *
> > + * This program is free software; you can redistribute it and/or
> > + * modify it under the terms of the GNU General Public License as
> > + * published by the Free Software Foundation; either version 2 of
> > + * the License, or (at your option) any later version.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.		See the
> > + * GNU General Public License for more details.
> > + *
> > + * You should have received a copy of the GNU General Public License
> > + * along with this program; if not, write to the Free Software
> > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> > + * MA 02111-1307 USA
> > + */
> > +
> > +#ifndef __CONFIG_H
> > +#define __CONFIG_H
> > +
> > +#define CONFIG_MX6
> > +/* MX6Q Quad */
> 
> comment is not very useful..
> 
> > +#define CONFIG_MX6Q
> > +/* MX6Q Dual */
> > +/* #define CONFIG_MX6DL */
> 
> This is dead code - drop it
> 
> I guess also that you took the sabrelite as reference, but you did it
> sometimes ago. I have the feeling that it is based on an older status,
> and it is worth you check also last changes for the sabrelite to get
> them in your board.
> 
> > +/* I2C Configs */
> > +#define CONFIG_CMD_I2C
> > +#define CONFIG_I2C_MULTI_BUS
> > +#define CONFIG_I2C_MXC
> > +#define CONFIG_SYS_I2C_SPEED		100000
> > +
> > +/* MMC Configs */
> > +#define CONFIG_FSL_ESDHC
> > +#define CONFIG_FSL_USDHC
> > +#define CONFIG_SYS_FSL_ESDHC_ADDR      0
> > +#define CONFIG_SYS_FSL_USDHC_NUM       2
> 
> I need some explanation - this does not match with your board file,
> where I have seen 3 SDHC controller. Am I wrong ?
> 
> > +/* Physical Memory Map */
> > +#define CONFIG_NR_DRAM_BANKS	       1
> > +#define PHYS_SDRAM		       MMDC0_ARB_BASE_ADDR
> > +#ifdef CONFIG_MX6
> 
> CONFIG_MX6 is always set for i.MX6, and then which CPU is on board is
> selected with CONFIG_MX6Q/CONFIG_MX6DL/CONFIG_MX6SL
> 
> > +#define PHYS_SDRAM_SIZE			       (1u * 1024 * 1024 * 1024)
> > +#endif
> > +#ifdef CONFIG_MX6_DL
> 
> This is not set and the usage seems wrong.  And there is CONFIG_MX6DL
> and not CONFIG_MX6_DL
> 
> Best regards,
> Stefano Babic
Wolfgang Denk May 13, 2013, 10:32 p.m. UTC | #4
Dear "SARTRE Leo",

In message <3465D313FDFB824F9A9C8CD24FA4F6BC0108CCF5@frontmail.adetel.com> you wrote:
>
> I will rework my patch taking all your remarks, and those from Wolfgang, into 
> acount, I just like to talk a bit about the problem of duplicated code that 
> you spooted. 
> This patch is just a first commit for this board, there will come other commits 
> to add missing functionnalities provided by the board, so I think that it will 
> be more convenient to have a separate file even if for now, it is very similar 
> to the sabrelite file. 

NAK.  Duplicating code is NEVER a good idea.  Even if you want to add
other / more stuff, then it makes a lot of sense to factor out the
common parts into a common file.

Best regards,

Wolfgang Denk
diff mbox

Patch

diff --git a/board/freescale/cgtqmx6/Makefile b/board/freescale/cgtqmx6/Makefile
new file mode 100644
index 0000000..a17603e
--- /dev/null
+++ b/board/freescale/cgtqmx6/Makefile
@@ -0,0 +1,41 @@ 
+#
+# Copyright (C) 2007, Guennadi Liakhovetski <lg@denx.de>
+#
+# (C) Copyright 2013 Adeneo Embedded <www.adeneo-embedded.com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB    = $(obj)lib$(BOARD).o
+
+COBJS  := cgtqmx6.o
+
+SRCS   := $(COBJS:.o=.c)
+OBJS   := $(addprefix $(obj),$(COBJS))
+
+$(LIB):        $(obj).depend $(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/freescale/cgtqmx6/cgtqmx6.c b/board/freescale/cgtqmx6/cgtqmx6.c
new file mode 100644
index 0000000..ed5476a
--- /dev/null
+++ b/board/freescale/cgtqmx6/cgtqmx6.c
@@ -0,0 +1,630 @@ 
+/*
+ * Copyright (C) 2013, Adeneo Embedded <www.adeneo-embedded.com>
+ * Leo Sartre, <lsartre@adeneo-embedded.com>
+ * Based on mx6qsabrelite.c file
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/iomux.h>
+#include <asm/arch/mx6-pins.h>
+#include <asm/errno.h>
+#include <asm/gpio.h>
+#include <asm/imx-common/iomux-v3.h>
+#include <asm/imx-common/mxc_i2c.h>
+#include <asm/imx-common/boot_mode.h>
+#include <mmc.h>
+#include <fsl_esdhc.h>
+#include <malloc.h>
+#include <linux/fb.h>
+#include <ipu_pixfmt.h>
+#include <asm/arch/crm_regs.h>
+#include <asm/arch/mxc_hdmi.h>
+#include <i2c.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 SPI_PAD_CTRL (PAD_CTL_HYS |\
+					  PAD_CTL_PUS_100K_DOWN |\
+					  PAD_CTL_SPEED_MED     |\
+					  PAD_CTL_DSE_40ohm     |\
+					  PAD_CTL_SRE_FAST)
+
+#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 I2C_PAD_CTRL	(PAD_CTL_PKE | PAD_CTL_PUE |\
+						 PAD_CTL_PUS_100K_UP |\
+						 PAD_CTL_SPEED_MED   |\
+						 PAD_CTL_DSE_40ohm   |\
+						 PAD_CTL_HYS         |\
+						 PAD_CTL_ODE         |\
+						 PAD_CTL_SRE_FAST)
+
+int dram_init(void)
+{
+	gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
+
+	return 0;
+}
+
+iomux_v3_cfg_t const uart1_pads[] = {
+	MX6_PAD_CSI0_DAT10__UART1_TXD | MUX_PAD_CTRL(UART_PAD_CTRL),
+	MX6_PAD_CSI0_DAT11__UART1_RXD | MUX_PAD_CTRL(UART_PAD_CTRL),
+};
+
+iomux_v3_cfg_t const uart2_pads[] = {
+	MX6_PAD_EIM_D26__UART2_TXD | MUX_PAD_CTRL(UART_PAD_CTRL),
+	MX6_PAD_EIM_D27__UART2_RXD | MUX_PAD_CTRL(UART_PAD_CTRL),
+};
+
+#define PC MUX_PAD_CTRL(I2C_PAD_CTRL)
+
+/* I2C1, SGTL5000 */
+struct i2c_pads_info i2c_pad_info0 = {
+	.scl = {
+		.i2c_mode = MX6_PAD_EIM_D21__I2C1_SCL | PC,
+		.gpio_mode = MX6_PAD_EIM_D21__GPIO_3_21 | PC,
+		.gp = IMX_GPIO_NR(3, 21)
+	},
+	.sda = {
+		.i2c_mode = MX6_PAD_EIM_D28__I2C1_SDA | PC,
+		.gpio_mode = MX6_PAD_EIM_D28__GPIO_3_28 | PC,
+		.gp = IMX_GPIO_NR(3, 28)
+	}
+};
+
+/* I2C2 Camera, MIPI */
+struct i2c_pads_info i2c_pad_info1 = {
+	.scl = {
+		.i2c_mode = MX6_PAD_KEY_COL3__I2C2_SCL | PC,
+		.gpio_mode = MX6_PAD_KEY_COL3__GPIO_4_12 | PC,
+		.gp = IMX_GPIO_NR(4, 12)
+	},
+	.sda = {
+		.i2c_mode = MX6_PAD_KEY_ROW3__I2C2_SDA | PC,
+		.gpio_mode = MX6_PAD_KEY_ROW3__GPIO_4_13 | PC,
+		.gp = IMX_GPIO_NR(4, 13)
+	}
+};
+
+struct i2c_pads_info i2c_pad_info2 = {
+	.scl = {
+		.i2c_mode = MX6_PAD_GPIO_3__I2C3_SCL | PC,
+		.gpio_mode = MX6_PAD_GPIO_3__GPIO_1_3 | PC,
+		.gp = IMX_GPIO_NR(1, 3)
+	},
+	.sda = {
+		.i2c_mode = MX6_PAD_GPIO_6__I2C3_SDA | PC,
+		.gpio_mode = MX6_PAD_GPIO_6__GPIO_1_6 | PC,
+		.gp = IMX_GPIO_NR(1, 6)
+	}
+};
+
+
+iomux_v3_cfg_t const usdhc1_pads[] = {
+	MX6_PAD_SD1_CLK__USDHC1_CLK   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD1_CMD__USDHC1_CMD   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD1_DAT0__USDHC1_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD1_DAT1__USDHC1_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD1_DAT2__USDHC1_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD1_DAT3__USDHC1_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+};
+
+iomux_v3_cfg_t const usdhc2_pads[] = {
+	MX6_PAD_SD2_CLK__USDHC2_CLK   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD2_CMD__USDHC2_CMD   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD2_DAT0__USDHC2_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD2_DAT1__USDHC2_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD2_DAT2__USDHC2_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD2_DAT3__USDHC2_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_GPIO_4__GPIO_1_4      | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+};
+
+iomux_v3_cfg_t const usdhc3_pads[] = {
+	MX6_PAD_SD3_CLK__USDHC3_CLK   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD3_CMD__USDHC3_CMD   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD3_DAT0__USDHC3_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD3_DAT1__USDHC3_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD3_DAT2__USDHC3_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD3_DAT3__USDHC3_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD3_DAT4__USDHC3_DAT4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD3_DAT5__USDHC3_DAT5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD3_DAT6__USDHC3_DAT6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD3_DAT7__USDHC3_DAT7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD3_DAT5__GPIO_7_0    | MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */
+};
+
+iomux_v3_cfg_t const usdhc4_pads[] = {
+	MX6_PAD_SD4_CLK__USDHC4_CLK   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD4_CMD__USDHC4_CMD   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD4_DAT0__USDHC4_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD4_DAT1__USDHC4_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD4_DAT2__USDHC4_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD4_DAT3__USDHC4_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD4_DAT4__USDHC4_DAT4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD4_DAT5__USDHC4_DAT5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD4_DAT6__USDHC4_DAT6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD4_DAT7__USDHC4_DAT7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_NANDF_D6__GPIO_2_6    | MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */
+};
+
+iomux_v3_cfg_t const usb_pads[] = {
+	MX6_PAD_GPIO_17__GPIO_7_12 | MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
+/* Button assignments*/
+static iomux_v3_cfg_t const button_pads[] = {
+	/* Recovery button */
+	MX6_PAD_GPIO_19__GPIO_4_5	| MUX_PAD_CTRL(BUTTON_PAD_CTRL),
+};
+
+
+static void setup_iomux_uart(void)
+{
+	imx_iomux_v3_setup_multiple_pads(uart1_pads, ARRAY_SIZE(uart1_pads));
+	imx_iomux_v3_setup_multiple_pads(uart2_pads, ARRAY_SIZE(uart2_pads));
+}
+
+#ifdef CONFIG_USB_EHCI_MX6
+int board_ehci_hcd_init(int port)
+{
+	imx_iomux_v3_setup_multiple_pads(usb_pads, ARRAY_SIZE(usb_pads));
+
+	/* Reset USB hub */
+	gpio_direction_output(IMX_GPIO_NR(7, 12), 0);
+	mdelay(2);
+	gpio_set_value(IMX_GPIO_NR(7, 12), 1);
+
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_FSL_ESDHC
+struct fsl_esdhc_cfg usdhc_cfg[] = {
+	{USDHC2_BASE_ADDR},
+	{USDHC4_BASE_ADDR},
+};
+
+int board_mmc_getcd(struct mmc *mmc)
+{
+	struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
+	int ret;
+
+	switch (cfg->esdhc_base) {
+	case USDHC2_BASE_ADDR:
+		gpio_direction_input(IMX_GPIO_NR(1, 4));
+		ret = !gpio_get_value(IMX_GPIO_NR(1, 4));
+		break;
+	case USDHC3_BASE_ADDR:
+		gpio_direction_input(IMX_GPIO_NR(7, 0));
+		ret = !gpio_get_value(IMX_GPIO_NR(7, 0));
+		break;
+	case USDHC4_BASE_ADDR:
+		gpio_direction_input(IMX_GPIO_NR(2, 6));
+		ret = !gpio_get_value(IMX_GPIO_NR(2, 6));
+		break;
+	default:
+		printf("Bad USDHC interface\n");
+	}
+
+	return ret;
+}
+
+int board_mmc_init(bd_t *bis)
+{
+	s32 status = 0;
+	u32 index = 0;
+
+	usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
+	usdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC4_CLK);
+
+	for (index = 0; index < CONFIG_SYS_FSL_USDHC_NUM; ++index) {
+		switch (index) {
+		case 0:
+			imx_iomux_v3_setup_multiple_pads(
+					usdhc2_pads, ARRAY_SIZE(usdhc2_pads));
+			break;
+		case 1:
+			imx_iomux_v3_setup_multiple_pads(
+					usdhc4_pads, ARRAY_SIZE(usdhc4_pads));
+			break;
+		default:
+			printf("Warning: you configured more USDHC controllers
+				   (%d) then supported by the board (%d)\n",
+				   index + 1, CONFIG_SYS_FSL_USDHC_NUM);
+			return status;
+		}
+
+		status |= fsl_esdhc_initialize(bis, &usdhc_cfg[index]);
+	}
+
+	return status;
+}
+#endif
+
+u32 get_board_rev(void)
+{
+	unsigned int fsl_system_rev;
+	u32 cpu_type = readl(ANATOP_BASE_ADDR + 0x260);
+
+	/* Chip Silicon ID */
+	fsl_system_rev = ((cpu_type >> 16) & 0xFF) << 12;
+	/* Chip silicon major revision */
+	fsl_system_rev |= ((cpu_type >> 8) & 0xFF) << 4;
+	fsl_system_rev += 0x10;
+	/* Chip silicon minor revision */
+	fsl_system_rev |= cpu_type & 0xFF;
+
+	return fsl_system_rev;
+}
+
+#ifdef CONFIG_MXC_SPI
+iomux_v3_cfg_t const ecspi1_pads[] = {
+	/* SS1 */
+	MX6_PAD_EIM_D19__ECSPI1_SS1  | MUX_PAD_CTRL(SPI_PAD_CTRL),
+	MX6_PAD_EIM_D17__ECSPI1_MISO | MUX_PAD_CTRL(SPI_PAD_CTRL),
+	MX6_PAD_EIM_D18__ECSPI1_MOSI | MUX_PAD_CTRL(SPI_PAD_CTRL),
+	MX6_PAD_EIM_D16__ECSPI1_SCLK | MUX_PAD_CTRL(SPI_PAD_CTRL),
+};
+
+void setup_spi(void)
+{
+	gpio_direction_output(CONFIG_SF_DEFAULT_CS, 1);
+	imx_iomux_v3_setup_multiple_pads(
+				ecspi1_pads,
+				ARRAY_SIZE(ecspi1_pads));
+	printf("Setting up spi...\n");
+}
+#endif
+
+static void setup_buttons(void)
+{
+	imx_iomux_v3_setup_multiple_pads(
+				button_pads,
+				ARRAY_SIZE(button_pads));
+}
+
+#ifdef CONFIG_CMD_SATA
+
+int setup_sata(void)
+{
+	struct iomuxc_base_regs *const iomuxc_regs
+		= (struct iomuxc_base_regs *)IOMUXC_BASE_ADDR;
+	int ret = enable_sata_clock();
+	if (ret)
+		return ret;
+
+	clrsetbits_le32(
+		&iomuxc_regs->gpr[13],
+		IOMUXC_GPR13_SATA_MASK,
+		IOMUXC_GPR13_SATA_PHY_8_RXEQ_3P0DB
+		|IOMUXC_GPR13_SATA_PHY_7_SATA2M
+		|IOMUXC_GPR13_SATA_SPEED_3G
+		|(3<<IOMUXC_GPR13_SATA_PHY_6_SHIFT)
+		|IOMUXC_GPR13_SATA_SATA_PHY_5_SS_DISABLED
+		|IOMUXC_GPR13_SATA_SATA_PHY_4_ATTEN_9_16
+		|IOMUXC_GPR13_SATA_PHY_3_TXBOOST_0P00_DB
+		|IOMUXC_GPR13_SATA_PHY_2_TX_1P104V
+		|IOMUXC_GPR13_SATA_PHY_1_SLOW);
+
+	return 0;
+}
+#endif
+
+#if defined(CONFIG_VIDEO_IPUV3)
+
+struct display_info_t {
+	int	bus;
+	int	addr;
+	int	pixfmt;
+	int	(*detect)(struct display_info_t const *dev);
+	void	(*enable)(struct display_info_t const *dev);
+	struct	fb_videomode mode;
+};
+
+
+static int detect_hdmi(struct display_info_t const *dev)
+{
+	struct hdmi_regs *hdmi	= (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
+	return readb(&hdmi->phy_stat0) & HDMI_PHY_HPD;
+}
+
+static void enable_hdmi(struct display_info_t const *dev)
+{
+	struct hdmi_regs *hdmi	= (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
+	u8 reg;
+	printf("%s: setup HDMI monitor\n", __func__);
+	reg = readb(&hdmi->phy_conf0);
+	reg |= HDMI_PHY_CONF0_PDZ_MASK;
+	writeb(reg, &hdmi->phy_conf0);
+
+	udelay(3000);
+	reg |= HDMI_PHY_CONF0_ENTMDS_MASK;
+	writeb(reg, &hdmi->phy_conf0);
+	udelay(3000);
+	reg |= HDMI_PHY_CONF0_GEN2_TXPWRON_MASK;
+	writeb(reg, &hdmi->phy_conf0);
+	writeb(HDMI_MC_PHYRSTZ_ASSERT, &hdmi->mc_phyrstz);
+}
+
+static struct display_info_t const displays[] = {{
+		.bus	= -1,
+		.addr	= 0,
+		.pixfmt	= IPU_PIX_FMT_RGB24,
+		.detect	= detect_hdmi,
+		.enable	= enable_hdmi,
+		.mode	= {
+			.name           = "HDMI",
+			.refresh        = 60,
+			.xres           = 640,
+			.yres           = 480,
+			.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
+		} } };
+
+int board_video_skip(void)
+{
+	int i;
+	int ret;
+	char const *panel = getenv("panel");
+	if (!panel) {
+		for (i = 0; i < ARRAY_SIZE(displays); i++) {
+			struct display_info_t const *dev = displays+i;
+			if (dev->detect(dev)) {
+				panel = dev->mode.name;
+				printf("auto-detected panel %s\n", panel);
+				break;
+			}
+		}
+		if (!panel) {
+			panel = displays[0].mode.name;
+			printf("No panel detected: default to %s\n", panel);
+		}
+	} else {
+		for (i = 0; i < ARRAY_SIZE(displays); i++) {
+			if (!strcmp(panel, displays[i].mode.name))
+				break;
+		}
+	}
+	if (i < ARRAY_SIZE(displays)) {
+		ret = ipuv3_fb_init(&displays[i].mode, 0,
+							displays[i].pixfmt);
+		if (!ret) {
+			displays[i].enable(displays+i);
+			printf(
+				   "Display: %s (%ux%u)\n",
+				   displays[i].mode.name,
+				   displays[i].mode.xres,
+				   displays[i].mode.yres);
+		} else
+			printf(
+				   "LCD %s cannot be configured: %d\n",
+				   displays[i].mode.name, ret);
+	} else {
+		printf("unsupported panel %s\n", panel);
+		ret = -EINVAL;
+	}
+	return (0 != ret);
+}
+
+static void setup_display(void)
+{
+	struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+	struct hdmi_regs *hdmi	= (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
+
+	int reg;
+
+	/* Turn on LDB0,IPU,IPU DI0 clocks */
+	reg = __raw_readl(&mxc_ccm->CCGR3);
+	reg |=   MXC_CCM_CCGR3_IPU1_IPU_DI0_OFFSET
+		|MXC_CCM_CCGR3_LDB_DI0_MASK;
+	writel(reg, &mxc_ccm->CCGR3);
+
+	/* Turn on HDMI PHY clock */
+	reg = __raw_readl(&mxc_ccm->CCGR2);
+	reg |=  MXC_CCM_CCGR2_HDMI_TX_IAHBCLK_MASK
+		|MXC_CCM_CCGR2_HDMI_TX_ISFRCLK_MASK;
+	writel(reg, &mxc_ccm->CCGR2);
+
+	/* clear HDMI PHY reset */
+	writeb(HDMI_MC_PHYRSTZ_DEASSERT, &hdmi->mc_phyrstz);
+}
+#endif
+
+int board_early_init_f(void)
+{
+	setup_iomux_uart();
+	setup_buttons();
+
+#if defined(CONFIG_VIDEO_IPUV3)
+	setup_display();
+#endif
+	return 0;
+}
+
+/*
+ * Do not overwrite the console
+ * Use always serial for U-Boot console
+ */
+int overwrite_console(void)
+{
+	return 1;
+}
+
+int board_init(void)
+{
+	u32 reg;
+	writel(0x41736166, SNVS_BASE_ADDR + 0x64);/*set LPPGDR*/
+	udelay(10);
+	reg = readl(SNVS_BASE_ADDR + 0x4c);
+	reg |= (1 << 3);
+	writel(reg, SNVS_BASE_ADDR + 0x4c);/*clear LPSR*/
+
+	/* address of boot parameters */
+	gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
+
+#ifdef CONFIG_MXC_SPI
+	setup_spi();
+#endif
+	setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info0);
+	setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1);
+	setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info2);
+
+#ifdef CONFIG_CMD_SATA
+	setup_sata();
+#endif
+
+	return 0;
+}
+
+int checkboard(void)
+{
+#ifdef CONFIG_MX6
+	puts("Board: Congatec QMX6 Quad\n");
+#endif
+#ifdef CONFIG_MX6_DL
+	puts("Board: Congatec QMX6 Dual\n");
+#endif
+	return 0;
+}
+
+struct button_key {
+	char const	*name;
+	unsigned	gpnum;
+	char		ident;
+};
+
+static struct button_key const buttons[] = {
+	{"recovery",	IMX_GPIO_NR(4, 5),	'r'},
+};
+
+/*
+ * generate a null-terminated string containing the buttons pressed
+ * returns number of keys pressed
+ */
+static int read_keys(char *buf)
+{
+	int i, numpressed = 0;
+	for (i = 0; i < ARRAY_SIZE(buttons); i++) {
+		if (!gpio_get_value(buttons[i].gpnum))
+			buf[numpressed++] = buttons[i].ident;
+	}
+	buf[numpressed] = '\0';
+	return numpressed;
+}
+
+static int do_kbd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	char envvalue[ARRAY_SIZE(buttons)+1];
+	int numpressed = read_keys(envvalue);
+	setenv("keybd", envvalue);
+	return numpressed == 0;
+}
+
+U_BOOT_CMD(
+		   kbd, 1, 1, do_kbd,
+		   "Tests for keypresses, sets 'keybd' environment variable",
+		   "Returns 0 (true) to shell if key is pressed."
+		   );
+
+#ifdef CONFIG_PREBOOT
+static char const kbd_magic_prefix[] = "key_magic";
+static char const kbd_command_prefix[] = "key_cmd";
+
+static void preboot_keys(void)
+{
+	int numpressed;
+	char keypress[ARRAY_SIZE(buttons)+1];
+	numpressed = read_keys(keypress);
+	if (numpressed) {
+		char *kbd_magic_keys = getenv("magic_keys");
+		char *suffix;
+		/*
+		 * loop over all magic keys
+		 */
+		for (suffix = kbd_magic_keys; *suffix; ++suffix) {
+			char *keys;
+			char magic[sizeof(kbd_magic_prefix) + 1];
+			sprintf(magic, "%s%c", kbd_magic_prefix, *suffix);
+			keys = getenv(magic);
+			if (keys) {
+				if (!strcmp(keys, keypress))
+					break;
+			}
+		}
+		if (*suffix) {
+			char cmd_name[sizeof(kbd_command_prefix) + 1];
+			char *cmd;
+			sprintf(cmd_name, "%s%c", kbd_command_prefix, *suffix);
+			cmd = getenv(cmd_name);
+			if (cmd) {
+				setenv("preboot", cmd);
+				return;
+			}
+		}
+	}
+}
+#endif
+
+#ifdef CONFIG_CMD_BMODE
+static const struct boot_mode board_boot_modes[] = {
+	/* 4 bit bus width */
+	{"mmc0",	MAKE_CFGVAL(0x50, 0x30, 0x00, 0x00)},
+	{"mmc1",	MAKE_CFGVAL(0x50, 0x38, 0x00, 0x00)},
+	{NULL,		0},
+};
+#endif
+
+int misc_init_r(void)
+{
+#ifdef CONFIG_PREBOOT
+	preboot_keys();
+#endif
+
+#ifdef CONFIG_CMD_BMODE
+	add_board_boot_modes(board_boot_modes);
+#endif
+	return 0;
+}
diff --git a/boards.cfg b/boards.cfg
index 5d78064..448e78d 100644
--- a/boards.cfg
+++ b/boards.cfg
@@ -258,6 +258,7 @@  vision2                      arm         armv7       vision2             ttcontr
 mx6qarm2                     arm         armv7       mx6qarm2            freescale      mx6		mx6qarm2:IMX_CONFIG=board/freescale/mx6qarm2/imximage.cfg
 mx6qsabreauto                arm         armv7       mx6qsabreauto       freescale      mx6		mx6qsabreauto:IMX_CONFIG=board/freescale/mx6qsabreauto/imximage.cfg
 mx6qsabrelite                arm         armv7       mx6qsabrelite       freescale      mx6		mx6qsabrelite:IMX_CONFIG=board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg
+cgtqmx6                      arm         armv7       cgtqmx6             freescale      mx6     cgtqmx6:IMX_CONFIG=board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg
 mx6qsabresd                  arm         armv7       mx6qsabresd         freescale      mx6		mx6qsabresd:IMX_CONFIG=board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg
 eco5pk                       arm         armv7       eco5pk              8dtech         omap3
 nitrogen6dl                  arm         armv7       nitrogen6x          boundary       mx6		nitrogen6x:IMX_CONFIG=board/boundary/nitrogen6x/nitrogen6dl.cfg,MX6DL,DDR_MB=1024
diff --git a/include/configs/cgtqmx6.h b/include/configs/cgtqmx6.h
new file mode 100644
index 0000000..93b02be
--- /dev/null
+++ b/include/configs/cgtqmx6.h
@@ -0,1 +1,294 @@ 
+/*
+ * cgtqmx6.h
+ *
+ * Congatec Conga-QEVAl board configuration file.
+ *
+ * Copyright (C) 2013, Adeneo Embedded <www.adeneo-embedded.com>
+ * Leo Sartre, <lsartre@adeneo-embedded.com>
+ * Based on Freescale i.MX6Q Sabre Lite board configuration file.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.		See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#define CONFIG_MX6
+/* MX6Q Quad */
+#define CONFIG_MX6Q
+/* MX6Q Dual */
+/* #define CONFIG_MX6DL */
+#include "mx6_common.h"
+
+#define CONFIG_DISPLAY_CPUINFO
+#define CONFIG_DISPLAY_BOARDINFO
+
+#define CONFIG_MACH_TYPE	4122
+
+#include <asm/arch/imx-regs.h>
+#include <asm/imx-common/gpio.h>
+
+#define CONFIG_CMDLINE_TAG
+#define CONFIG_SETUP_MEMORY_TAGS
+#define CONFIG_INITRD_TAG
+#define CONFIG_REVISION_TAG
+
+/* Size of malloc() pool */
+#define CONFIG_SYS_MALLOC_LEN		(10 * 1024 * 1024)
+
+#define CONFIG_BOARD_EARLY_INIT_F
+#define CONFIG_MISC_INIT_R
+#define CONFIG_MXC_GPIO
+
+#define CONFIG_MXC_UART
+#define CONFIG_MXC_UART_BASE	       UART2_BASE
+
+#define CONFIG_CMD_SF
+#ifdef CONFIG_CMD_SF
+#define CONFIG_SPI_FLASH
+#define CONFIG_SPI_FLASH_SST
+#define CONFIG_MXC_SPI
+#define CONFIG_SF_DEFAULT_BUS  0
+#define CONFIG_SF_DEFAULT_CS   (0|(IMX_GPIO_NR(3, 19)<<8))
+#define CONFIG_SF_DEFAULT_SPEED 25000000
+#define CONFIG_SF_DEFAULT_MODE (SPI_MODE_0)
+#endif
+
+/* I2C Configs */
+#define CONFIG_CMD_I2C
+#define CONFIG_I2C_MULTI_BUS
+#define CONFIG_I2C_MXC
+#define CONFIG_SYS_I2C_SPEED		100000
+
+/* MMC Configs */
+#define CONFIG_FSL_ESDHC
+#define CONFIG_FSL_USDHC
+#define CONFIG_SYS_FSL_ESDHC_ADDR      0
+#define CONFIG_SYS_FSL_USDHC_NUM       2
+
+#define CONFIG_MMC
+#define CONFIG_CMD_MMC
+#define CONFIG_GENERIC_MMC
+#define CONFIG_BOUNCE_BUFFER
+#define CONFIG_CMD_EXT2
+#define CONFIG_CMD_FAT
+#define CONFIG_DOS_PARTITION
+
+#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		6
+#define CONFIG_PHYLIB
+
+/* USB Configs */
+#define CONFIG_CMD_USB
+#define CONFIG_CMD_FAT
+#define CONFIG_USB_EHCI
+#define CONFIG_USB_EHCI_MX6
+#define CONFIG_USB_STORAGE
+#define CONFIG_USB_HOST_ETHER
+#define CONFIG_USB_ETHER_ASIX
+#define CONFIG_USB_ETHER_SMSC95XX
+#define CONFIG_MXC_USB_PORT	1
+#define CONFIG_MXC_USB_PORTSC	(PORT_PTS_UTMI | PORT_PTS_PTW)
+#define CONFIG_MXC_USB_FLAGS	0
+
+/* Miscellaneous commands */
+#define CONFIG_CMD_BMODE
+
+/* Framebuffer and LCD */
+#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_SYS_CONSOLE_OVERWRITE_ROUTINE
+#define CONFIG_VIDEO_BMP_RLE8
+#define CONFIG_IPUV3_CLK 260000000
+
+/* allow to overwrite serial and ethaddr */
+#define CONFIG_ENV_OVERWRITE
+#define CONFIG_CONS_INDEX	       1
+#define CONFIG_BAUDRATE			       115200
+
+/* Command definition */
+#include <config_cmd_default.h>
+
+#undef CONFIG_CMD_IMLS
+
+#define CONFIG_BOOTDELAY	       3
+
+#define CONFIG_PREBOOT                 ""
+
+#define CONFIG_LOADADDR			       0x12000000
+#define CONFIG_SYS_TEXT_BASE	       0x17800000
+
+#define CONFIG_EXTRA_ENV_SETTINGS \
+	"script=boot.scr\0" \
+	"uimage=uImage\0" \
+	"fdt_file=imx6q-congatec.dtb\0" \
+	"boot_dir=/boot\0" \
+	"console=ttymxc1\0" \
+	"fdt_high=0xffffffff\0" \
+	"initrd_high=0xffffffff\0" \
+	"fdt_addr=0x11000000\0" \
+	"boot_fdt=try\0" \
+	"ip_dyn=yes\0" \
+	"mmcdev=1\0" \
+	"mmcpart=1\0" \
+	"mmcroot=/dev/mmcblk0p1 rootwait rw\0" \
+	"mmcargs=setenv bootargs console=${console},${baudrate} " \
+		"root=${mmcroot}\0" \
+	"loadbootscript=" \
+		"ext2load mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};\0" \
+	"bootscript=echo Running bootscript from mmc ...; " \
+		"source\0" \
+	"loaduimage=ext2load mmc ${mmcdev}:${mmcpart} ${loadaddr} ${boot_dir}/${uimage}\0" \
+	"loadfdt=ext2load mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${boot_dir}/${fdt_file}\0" \
+	"mmcboot=echo Booting from mmc ...; " \
+		"run mmcargs; " \
+		"if test ${boot_fdt} = yes || test ${boot_fdt} = try; then " \
+			"if run loadfdt; then " \
+				"bootm ${loadaddr} - ${fdt_addr}; " \
+			"else " \
+				"if test ${boot_fdt} = try; then " \
+					"bootm; " \
+				"else " \
+					"echo WARN: Cannot load the DT; " \
+				"fi; " \
+			"fi; " \
+		"else " \
+			"bootm; " \
+		"fi;\0" \
+	"netargs=setenv bootargs console=${console},${baudrate} " \
+		"root=/dev/nfs " \
+	"ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp\0" \
+		"netboot=echo Booting from net ...; " \
+		"run netargs; " \
+		"if test ${ip_dyn} = yes; then " \
+			"setenv get_cmd dhcp; " \
+		"else " \
+			"setenv get_cmd tftp; " \
+		"fi; " \
+		"${get_cmd} ${uimage}; " \
+		"if test ${boot_fdt} = yes || test ${boot_fdt} = try; then " \
+			"if ${get_cmd} ${fdt_addr} ${fdt_file}; then " \
+				"bootm ${loadaddr} - ${fdt_addr}; " \
+			"else " \
+				"if test ${boot_fdt} = try; then " \
+					"bootm; " \
+				"else " \
+					"echo WARN: Cannot load the DT; " \
+				"fi; " \
+			"fi; " \
+		"else " \
+			"bootm; " \
+		"fi;\0"
+
+#define CONFIG_BOOTCOMMAND \
+	   "mmc dev ${mmcdev};" \
+	   "mmc dev ${mmcdev}; if mmc rescan; then " \
+		   "if run loadbootscript; then " \
+			   "run bootscript; " \
+		   "else " \
+			   "if run loaduimage; then " \
+				   "run mmcboot; " \
+			   "else run netboot; " \
+			   "fi; " \
+		   "fi; " \
+	   "else run netboot; fi"
+
+#define CONFIG_ARP_TIMEOUT     200UL
+
+/* Miscellaneous configurable options */
+#define CONFIG_SYS_LONGHELP
+#define CONFIG_SYS_HUSH_PARSER
+#ifdef CONFIG_MX6
+#define CONFIG_SYS_PROMPT	       "CGT-QMX6-Quad U-Boot > "
+#endif
+#ifdef CONFIG_MX6_DL
+#define CONFIG_SYS_PROMPT	       "CGT-QMX6-Dual U-Boot > "
+#endif
+#define CONFIG_AUTO_COMPLETE
+#define CONFIG_SYS_CBSIZE	       256
+
+/* Print Buffer Size */
+#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
+#define CONFIG_SYS_MAXARGS	       16
+#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE
+
+#define CONFIG_SYS_MEMTEST_START       0x10000000
+#define CONFIG_SYS_MEMTEST_END	       0x10010000
+#define CONFIG_SYS_MEMTEST_SCRATCH     0x10800000
+
+#define CONFIG_SYS_LOAD_ADDR	       CONFIG_LOADADDR
+#define CONFIG_SYS_HZ		       1000
+
+#define CONFIG_CMDLINE_EDITING
+
+/* Physical Memory Map */
+#define CONFIG_NR_DRAM_BANKS	       1
+#define PHYS_SDRAM		       MMDC0_ARB_BASE_ADDR
+#ifdef CONFIG_MX6
+#define PHYS_SDRAM_SIZE			       (1u * 1024 * 1024 * 1024)
+#endif
+#ifdef CONFIG_MX6_DL
+#define PHYS_SDRAM_SIZE			       (1u * 1024 * 1024 * 1024)
+#endif
+
+#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)
+
+/* FLASH and environment organization */
+#define CONFIG_SYS_NO_FLASH
+
+#ifndef CONFIG_SYS_NO_FLASH
+#define CONFIG_SYS_MAX_FLASH_SECT 256
+#define CONFIG_SYS_MAX_FLASH_BANKS  1
+#endif
+
+#define CONFIG_ENV_SIZE			(8 * 1024)
+
+#define CONFIG_ENV_IS_IN_MMC
+
+#if defined(CONFIG_ENV_IS_IN_MMC)
+#define CONFIG_ENV_OFFSET		(6 * 64 * 1024)
+#define CONFIG_SYS_MMC_ENV_DEV		0
+#elif defined(CONFIG_ENV_IS_IN_SPI_FLASH)
+#define CONFIG_ENV_OFFSET		(768 * 1024)
+#define CONFIG_ENV_SECT_SIZE		(8 * 1024)
+#define CONFIG_ENV_SPI_BUS		CONFIG_SF_DEFAULT_BUS
+#define CONFIG_ENV_SPI_CS		CONFIG_SF_DEFAULT_CS
+#define CONFIG_ENV_SPI_MODE		CONFIG_SF_DEFAULT_MODE
+#define CONFIG_ENV_SPI_MAX_HZ		CONFIG_SF_DEFAULT_SPEED
+#endif
+
+#define CONFIG_OF_LIBFDT
+#define CONFIG_CMD_BOOTZ
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+#define CONFIG_CMD_CACHE
+#endif
+
+#endif			       /* __CONFIG_H */
--