From mboxrd@z Thu Jan 1 00:00:00 1970 From: Eric =?UTF-8?B?QsOpbmFyZA==?= Date: Mon, 13 May 2013 17:03:48 +0200 Subject: [U-Boot] [PATCH] Add minimal support for Congatec Conga-QEVAl Evaluation Carrier Board with a conga-Qmx6 module. In-Reply-To: <3465D313FDFB824F9A9C8CD24FA4F6BC0108CCF3@frontmail.adetel.com> References: <1368446578-13390-1-git-send-email-lsartre@adeneo-embedded.com> <3465D313FDFB824F9A9C8CD24FA4F6BC0108CCF3@frontmail.adetel.com> Message-ID: <20130513170348.21df6959@e6520eb> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de Hi Leo, Le Mon, 13 May 2013 14:02:57 +0200, "SARTRE Leo" 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 > + * Leo Sartre, > + * 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 > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +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_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