Message ID | 20160331135356.GA56795@ubuntu |
---|---|
State | Changes Requested |
Delegated to: | Stefano Babic |
Headers | show |
Hi Eran, On 31/03/2016 15:53, Eran Matityahu wrote: > Add support for Variscite VAR-SOM-MX6 / DART-MX6 / VAR-SOM-SOLO/DUAL boards with features: > PMIC, NAND flash, SD/MMC, USB, Ethernet, I2C, LVDS, HDMI. > > Signed-off-by: Eran Matityahu <eran.m@variscite.com> > --- > arch/arm/cpu/armv7/mx6/Kconfig | 7 + > board/variscite/mx6var_som/Kconfig | 12 + > board/variscite/mx6var_som/MAINTAINERS | 8 + > board/variscite/mx6var_som/Makefile | 9 + > board/variscite/mx6var_som/addresses.inc | 38 + > board/variscite/mx6var_som/imximage.cfg | 13 + > board/variscite/mx6var_som/mx6var_eeprom.c | 320 +++++ > board/variscite/mx6var_som/mx6var_eeprom.h | 88 ++ > board/variscite/mx6var_som/mx6var_eeprom_v2.c | 231 ++++ > board/variscite/mx6var_som/mx6var_eeprom_v2.h | 55 + > board/variscite/mx6var_som/mx6var_som.c | 1587 +++++++++++++++++++++++++ > board/variscite/mx6var_som/u-boot-spl.lds | 59 + > board/variscite/mx6var_som/values.inc | 39 + > configs/mx6var_som_nand_defconfig | 7 + > configs/mx6var_som_sd_defconfig | 7 + > include/configs/mx6var_som.h | 419 +++++++ > include/configs/mx6var_spl.h | 81 ++ > tools/logos/variscite.bmp | Bin 0 -> 15414 bytes This is a very big patch, just not easy to review. Is there any possibility to split it ? I have my difficulties to review such a monstruous patch. Some general notes: - SPL is automatically set. Which is the reason to have an own imximage.cfg ? All boards use the same. You do not need to set "booting from nand" or BOOT FROM SD", because they share the same start offset in the storage. - can you better explain the reason under the ddr configuration in EEPROM ? > 18 files changed, 2980 insertions(+) > create mode 100644 board/variscite/mx6var_som/Kconfig > create mode 100644 board/variscite/mx6var_som/MAINTAINERS > create mode 100644 board/variscite/mx6var_som/Makefile > create mode 100644 board/variscite/mx6var_som/addresses.inc > create mode 100644 board/variscite/mx6var_som/imximage.cfg > create mode 100644 board/variscite/mx6var_som/mx6var_eeprom.c > create mode 100644 board/variscite/mx6var_som/mx6var_eeprom.h > create mode 100644 board/variscite/mx6var_som/mx6var_eeprom_v2.c > create mode 100644 board/variscite/mx6var_som/mx6var_eeprom_v2.h > create mode 100644 board/variscite/mx6var_som/mx6var_som.c > create mode 100644 board/variscite/mx6var_som/u-boot-spl.lds > create mode 100644 board/variscite/mx6var_som/values.inc > create mode 100644 configs/mx6var_som_nand_defconfig > create mode 100644 configs/mx6var_som_sd_defconfig > create mode 100644 include/configs/mx6var_som.h > create mode 100644 include/configs/mx6var_spl.h > create mode 100644 tools/logos/variscite.bmp > > diff --git a/arch/arm/cpu/armv7/mx6/Kconfig b/arch/arm/cpu/armv7/mx6/Kconfig > index c72a150..146c152 100644 > --- a/arch/arm/cpu/armv7/mx6/Kconfig > +++ b/arch/arm/cpu/armv7/mx6/Kconfig > @@ -115,6 +115,12 @@ config TARGET_MX6UL_14X14_EVK > select DM_THERMAL > select SUPPORT_SPL > > +config TARGET_MX6VAR_SOM > + bool "mx6var_som" > + select SUPPORT_SPL > + select DM > + select DM_THERMAL > + > config TARGET_NITROGEN6X > bool "nitrogen6x" > > @@ -180,6 +186,7 @@ source "board/solidrun/mx6cuboxi/Kconfig" > source "board/tbs/tbs2910/Kconfig" > source "board/tqc/tqma6/Kconfig" > source "board/udoo/Kconfig" > +source "board/variscite/mx6var_som/Kconfig" > source "board/wandboard/Kconfig" > source "board/warp/Kconfig" > > diff --git a/board/variscite/mx6var_som/Kconfig b/board/variscite/mx6var_som/Kconfig > new file mode 100644 > index 0000000..0b82df7 > --- /dev/null > +++ b/board/variscite/mx6var_som/Kconfig > @@ -0,0 +1,12 @@ > +if TARGET_MX6VAR_SOM > + > +config SYS_BOARD > + default "mx6var_som" > + > +config SYS_VENDOR > + default "variscite" > + > +config SYS_CONFIG_NAME > + default "mx6var_som" > + > +endif > diff --git a/board/variscite/mx6var_som/MAINTAINERS b/board/variscite/mx6var_som/MAINTAINERS > new file mode 100644 > index 0000000..f3f81dd > --- /dev/null > +++ b/board/variscite/mx6var_som/MAINTAINERS > @@ -0,0 +1,8 @@ > +MX6VAR_SOM BOARD > +M: Eran Matityahu <eran.m@variscite.com> > +S: Maintained > +F: board/variscite/mx6var_som/ > +F: include/configs/mx6var_som.h > +F: include/configs/mx6var_spl.h > +F: configs/mx6var_som_nand_defconfig > +F: configs/mx6var_som_sd_defconfig The list must match the files you want must be added to the projects. Just a few of them are listed here. > diff --git a/board/variscite/mx6var_som/Makefile b/board/variscite/mx6var_som/Makefile > new file mode 100644 > index 0000000..efa90e2 > --- /dev/null > +++ b/board/variscite/mx6var_som/Makefile > @@ -0,0 +1,9 @@ > +# > +# Copyright (C) 2007, Guennadi Liakhovetski <lg@denx.de> > +# > +# (C) Copyright 2011 Freescale Semiconductor, Inc. > +# > +# SPDX-License-Identifier: GPL-2.0+ > +# > + > +obj-y := mx6var_som.o mx6var_eeprom.o mx6var_eeprom_v2.o > diff --git a/board/variscite/mx6var_som/addresses.inc b/board/variscite/mx6var_som/addresses.inc > new file mode 100644 > index 0000000..3aaea54 > --- /dev/null > +++ b/board/variscite/mx6var_som/addresses.inc > @@ -0,0 +1,38 @@ > +0x00000000, 0x020C4068, 0x020C406C, 0x020C4070, > +0x020C4074, 0x020C4078, 0x020C407C, 0x020C4080, > +0x020C4084, 0x020E0464, 0x020E0470, 0x020E0474, > +0x020E0478, 0x020E047C, 0x020E0480, 0x020E0484, > +0x020E0488, 0x020E048C, 0x020E0490, 0x020E0494, > +0x020E04A0, 0x020E04AC, 0x020E04B0, 0x020E04B4, > +0x020E04B8, 0x020E04BC, 0x020E04C0, 0x020E04C4, > +0x020E04C8, 0x020E04CC, 0x020E04D0, 0x020E04D4, > +0x020E04D8, 0x020E050C, 0x020E0510, 0x020E0514, > +0x020E0518, 0x020E051C, 0x020E0520, 0x020E0524, > +0x020E0528, 0x020E056C, 0x020E0578, 0x020E057C, > +0x020E0588, 0x020E058C, 0x020E0594, 0x020E059C, > +0x020E05A0, 0x020E05A8, 0x020E05AC, 0x020E05B0, > +0x020E05B4, 0x020E05B8, 0x020E05BC, 0x020E05C0, > +0x020E05C4, 0x020E0748, 0x020E074C, 0x020E0750, > +0x020E0754, 0x020E0758, 0x020E0760, 0x020E0764, > +0x020E076C, 0x020E0770, 0x020E0774, 0x020E0778, > +0x020E077C, 0x020E0780, 0x020E0784, 0x020E0788, > +0x020E078C, 0x020E0794, 0x020E0798, 0x020E079C, > +0x020E07A0, 0x020E07A4, 0x020E07A8, 0x021B0000, > +0x021B0004, 0x021B0008, 0x021B000C, 0x021B0010, > +0x021B0014, 0x021B0018, 0x021B001C, 0x021B0020, > +0x021B002C, 0x021B0030, 0x021B0038, 0x021B0040, > +0x021B0400, 0x021B0404, 0x021B0800, 0x021B080C, > +0x021B0810, 0x021B0818, 0x021B081C, 0x021B0820, > +0x021B0824, 0x021B0828, 0x021B082C, 0x021B0830, > +0x021B0834, 0x021B0838, 0x021B083C, 0x021B0840, > +0x021B0848, 0x021B0850, 0x021B085C, 0x021B0890, > +0x021B08B8, 0x021B08C0, 0x021B4000, 0x021B4004, > +0x021B4008, 0x021B400C, 0x021B4010, 0x021B4014, > +0x021B4018, 0x021B401C, 0x021B4020, 0x021B402C, > +0x021B4030, 0x021B4038, 0x021B4040, 0x021B4400, > +0x021B4404, 0x021B4800, 0x021B480C, 0x021B4810, > +0x021B4818, 0x021B481C, 0x021B4820, 0x021B4824, > +0x021B4828, 0x021B482C, 0x021B4830, 0x021B4834, > +0x021B4838, 0x021B483C, 0x021B4840, 0x021B4848, > +0x021B4850, 0x021B485C, 0x021B4890, 0x021B48B8, > +0x021B48BC, 0x021B48C0 I miss why it shhoul be necessary this. Indeed, they are addresses that are saved as structures into imx6-regs.h. Why do you need your custom way ? > diff --git a/board/variscite/mx6var_som/imximage.cfg b/board/variscite/mx6var_som/imximage.cfg > new file mode 100644 > index 0000000..54dc449 > --- /dev/null > +++ b/board/variscite/mx6var_som/imximage.cfg > @@ -0,0 +1,13 @@ > +/* > + * Copyright (C) 2016 Variscite Ltd. All Rights Reserved. > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +IMAGE_VERSION 2 > + > +#ifdef CONFIG_SYS_BOOT_NAND > +BOOT_FROM nand > +#else > +BOOT_FROM sd > +#endif I think the file is not needed at all and you can use the general rch/arm/imx-common/spl_sd.cfg. > diff --git a/board/variscite/mx6var_som/mx6var_eeprom.c b/board/variscite/mx6var_som/mx6var_eeprom.c > new file mode 100644 > index 0000000..02fedd0 > --- /dev/null > +++ b/board/variscite/mx6var_som/mx6var_eeprom.c > @@ -0,0 +1,320 @@ > +/* > + * Copyright (C) 2016 Variscite Ltd. All Rights Reserved. > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + I start telling you that I do not understand the meaning for mx6var_eeprom.c and mx6var_eepromV2.c > +#include <common.h> > +#include <command.h> > +#include <i2c.h> > +#include "mx6var_eeprom.h" > +#ifdef CONFIG_SPL_BUILD > +#include <asm/arch/mx6-ddr.h> > + > +#ifdef EEPROM_DEBUG > +#define eeprom_debug(M, ...) printf("EEPROM DEBUG: " M, ##__VA_ARGS__) > +#else > +#define eeprom_debug(M, ...) > +#endif > + > +bool var_eeprom_is_valid(struct var_eeprom_cfg *p_var_eeprom_cfg) > +{ > + return (VARISCITE_MAGIC == p_var_eeprom_cfg->header.variscite_magic); > +} > + > +void var_eeprom_mx6dlsl_dram_setup_iomux_from_struct(struct var_pinmux_group_regs *pinmux_group) > +{ > + volatile struct mx6sdl_iomux_ddr_regs *mx6dl_ddr_iomux; > + volatile struct mx6sdl_iomux_grp_regs *mx6dl_grp_iomux; > + > + mx6dl_ddr_iomux = (struct mx6sdl_iomux_ddr_regs *) MX6SDL_IOM_DDR_BASE; > + mx6dl_grp_iomux = (struct mx6sdl_iomux_grp_regs *) MX6SDL_IOM_GRP_BASE; > + > + mx6dl_grp_iomux->grp_ddr_type = (u32)pinmux_group->IOMUXC_SW_PAD_CTL_GRP_DDR_TYPE; > + mx6dl_grp_iomux->grp_ddrpke = (u32)pinmux_group->IOMUXC_SW_PAD_CTL_GRP_DDRPKE; > + mx6dl_ddr_iomux->dram_sdclk_0 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_ddr_iomux->dram_sdclk_1 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_ddr_iomux->dram_cas = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_ddr_iomux->dram_ras = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_grp_iomux->grp_addds = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_ddr_iomux->dram_reset = (u32)pinmux_group->dram_reset; > + mx6dl_ddr_iomux->dram_sdcke0 = (u32)pinmux_group->dram_sdcke0; > + mx6dl_ddr_iomux->dram_sdcke1 = (u32)pinmux_group->dram_sdcke1; > + mx6dl_ddr_iomux->dram_sdba2 = (u32)pinmux_group->IOMUXC_SW_PAD_CTL_PAD_DRAM_SDBA2; > + mx6dl_ddr_iomux->dram_sdodt0 = (u32)pinmux_group->dram_sdodt0; > + mx6dl_ddr_iomux->dram_sdodt1 = (u32)pinmux_group->dram_sdodt1; > + mx6dl_grp_iomux->grp_ctlds = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_grp_iomux->grp_ddrmode_ctl = (u32)pinmux_group->IOMUXC_SW_PAD_CTL_GRP_DDRMODE_CTL; > + mx6dl_ddr_iomux->dram_sdqs0 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_ddr_iomux->dram_sdqs1 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_ddr_iomux->dram_sdqs2 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_ddr_iomux->dram_sdqs3 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_ddr_iomux->dram_sdqs4 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_ddr_iomux->dram_sdqs5 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_ddr_iomux->dram_sdqs6 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_ddr_iomux->dram_sdqs7 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_grp_iomux->grp_ddrmode = (u32)pinmux_group->IOMUXC_SW_PAD_CTL_GRP_DDRMODE; > + mx6dl_grp_iomux->grp_b0ds = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_grp_iomux->grp_b1ds = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_grp_iomux->grp_b2ds = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_grp_iomux->grp_b3ds = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_grp_iomux->grp_b4ds = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_grp_iomux->grp_b5ds = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_grp_iomux->grp_b6ds = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_grp_iomux->grp_b7ds = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_ddr_iomux->dram_dqm0 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_ddr_iomux->dram_dqm1 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_ddr_iomux->dram_dqm2 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_ddr_iomux->dram_dqm3 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_ddr_iomux->dram_dqm4 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_ddr_iomux->dram_dqm5 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_ddr_iomux->dram_dqm6 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_ddr_iomux->dram_dqm7 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > +} I am really missing the goal for this. > + > +void var_eeprom_mx6qd_dram_setup_iomux_from_struct(struct var_pinmux_group_regs *pinmux_group) > +{ > + volatile struct mx6dq_iomux_ddr_regs *mx6q_ddr_iomux; > + volatile struct mx6dq_iomux_grp_regs *mx6q_grp_iomux; > + > + mx6q_ddr_iomux = (struct mx6dq_iomux_ddr_regs *) MX6DQ_IOM_DDR_BASE; > + mx6q_grp_iomux = (struct mx6dq_iomux_grp_regs *) MX6DQ_IOM_GRP_BASE; > + > + mx6q_grp_iomux->grp_ddr_type = (u32)pinmux_group->IOMUXC_SW_PAD_CTL_GRP_DDR_TYPE; > + mx6q_grp_iomux->grp_ddrpke = (u32)pinmux_group->IOMUXC_SW_PAD_CTL_GRP_DDRPKE; > + mx6q_ddr_iomux->dram_sdclk_0 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_ddr_iomux->dram_sdclk_1 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_ddr_iomux->dram_cas = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_ddr_iomux->dram_ras = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_grp_iomux->grp_addds = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_ddr_iomux->dram_reset = (u32)pinmux_group->dram_reset; > + mx6q_ddr_iomux->dram_sdcke0 = (u32)pinmux_group->dram_sdcke0; > + mx6q_ddr_iomux->dram_sdcke1 = (u32)pinmux_group->dram_sdcke1; > + mx6q_ddr_iomux->dram_sdba2 = (u32)pinmux_group->IOMUXC_SW_PAD_CTL_PAD_DRAM_SDBA2; > + mx6q_ddr_iomux->dram_sdodt0 = (u32)pinmux_group->dram_sdodt0; > + mx6q_ddr_iomux->dram_sdodt1 = (u32)pinmux_group->dram_sdodt1; > + mx6q_grp_iomux->grp_ctlds = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_grp_iomux->grp_ddrmode_ctl = (u32)pinmux_group->IOMUXC_SW_PAD_CTL_GRP_DDRMODE_CTL; > + mx6q_ddr_iomux->dram_sdqs0 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_ddr_iomux->dram_sdqs1 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_ddr_iomux->dram_sdqs2 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_ddr_iomux->dram_sdqs3 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_ddr_iomux->dram_sdqs4 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_ddr_iomux->dram_sdqs5 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_ddr_iomux->dram_sdqs6 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_ddr_iomux->dram_sdqs7 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_grp_iomux->grp_ddrmode = (u32)pinmux_group->IOMUXC_SW_PAD_CTL_GRP_DDRMODE; > + mx6q_grp_iomux->grp_b0ds = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_grp_iomux->grp_b1ds = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_grp_iomux->grp_b2ds = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_grp_iomux->grp_b3ds = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_grp_iomux->grp_b4ds = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_grp_iomux->grp_b5ds = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_grp_iomux->grp_b6ds = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_grp_iomux->grp_b7ds = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_ddr_iomux->dram_dqm0 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_ddr_iomux->dram_dqm1 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_ddr_iomux->dram_dqm2 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_ddr_iomux->dram_dqm3 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_ddr_iomux->dram_dqm4 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_ddr_iomux->dram_dqm5 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_ddr_iomux->dram_dqm6 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_ddr_iomux->dram_dqm7 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > +} Ditto. > + > +void var_eeprom_dram_init_from_struct(struct var_eeprom_cfg *p_var_eeprom_cfg) > +{ > + volatile struct mmdc_p_regs *mmdc_p0 = (struct mmdc_p_regs *) MMDC_P0_BASE_ADDR; > + u32 i; > + u32 last; > + u32 opcode; > + > + /* Go through all register initializations and apply to correct registers... */ > + i = 0; > + last = sizeof(p_var_eeprom_cfg->write_opcodes) / sizeof(u32); > + while ( (0 != p_var_eeprom_cfg->write_opcodes[i].address) && (i < last) ) { > + opcode = p_var_eeprom_cfg->write_opcodes[i].address & 0xF0000000; > + switch (opcode) { > + case VAR_DDR_INIT_OPCODE_WRITE_VAL_TO_ADDRESS: > + /* ZQ calibration? ==> Need to wait? */ > + if (mmdc_p0->mpzqhwctrl == p_var_eeprom_cfg->write_opcodes[i].address) { > + if (p_var_eeprom_cfg->write_opcodes[i].value & 0x3) { > + while (mmdc_p0->mpzqhwctrl & 0x00010000); > + } > + } > + else { > + /* write value to reg */ > + volatile u32 *reg_ptr = (volatile u32 *)p_var_eeprom_cfg->write_opcodes[i].address; > + > + *reg_ptr = p_var_eeprom_cfg->write_opcodes[i].value; > + } > + break; > + case VAR_DDR_INIT_OPCODE_WAIT_MASK_RISING: { > + volatile u32 *reg_ptr = (volatile u32 *)p_var_eeprom_cfg->write_opcodes[i].address; > + > + while ( (p_var_eeprom_cfg->write_opcodes[i].value & *reg_ptr) != \ > + p_var_eeprom_cfg->write_opcodes[i].value ); > + break; > + } > + case VAR_DDR_INIT_OPCODE_WAIT_MASK_FALLING: { > + volatile u32 *reg_ptr = (volatile u32 *)p_var_eeprom_cfg->write_opcodes[i].address; > + > + while ( (p_var_eeprom_cfg->write_opcodes[i].value & (~(*reg_ptr)) ) != \ > + p_var_eeprom_cfg->write_opcodes[i].value ); > + break; > + } > + case VAR_DDR_INIT_OPCODE_DELAY_USEC: > + udelay(p_var_eeprom_cfg->write_opcodes[i].value); > + break; > + default: > + break; > + } > + > + i++; > + } It is not that common code is not flexible: mx6<SOC>_dram_iocfg() let set the pinmux with own setup. You replace common code with this one, and I do not understand why. > + > + /* Short delay */ > + udelay(500); > +} > + > +#ifdef EEPROM_DEBUG > +static void var_eeprom_printf_array_dwords(u32 *ptr, u32 address_mem, u32 size) > +{ > + u32 idx; > + u32 *p_end = ptr + (size/4); > + idx = 0; > + while (ptr < p_end) { > + if ((idx & 0x3) == 0) { > + printf("\n0x%08x:", address_mem); > + address_mem += 0x10; > + } > + printf(" 0x%08x", *ptr); > + idx++; > + ptr++; > + } > + printf("\n"); > +} > +#endif > + > +int var_eeprom_read_struct(struct var_eeprom_cfg *p_var_eeprom_cfg) > +{ > + int eeprom_found; > + int ret = 0; > + i2c_set_bus_num(1); > + eeprom_found = i2c_probe(VAR_MX6_EEPROM_CHIP); > + eeprom_debug("eeprom_found(0x%x)=%d\n", VAR_MX6_EEPROM_CHIP, eeprom_found); > + if (0 == eeprom_found) { > + eeprom_debug("EEPROM device detected, address=0x%x\n", VAR_MX6_EEPROM_CHIP); > + > + if (i2c_read(VAR_MX6_EEPROM_CHIP, VAR_MX6_EEPROM_STRUCT_OFFSET, \ > + 1, (uchar *)p_var_eeprom_cfg, sizeof(struct var_eeprom_cfg))) { > + eeprom_debug("Read device ID error!\n"); > + return -1; > + } else { > + /* Success */ > +#ifdef EEPROM_DEBUG > + var_eeprom_printf_array_dwords((u32 *) p_var_eeprom_cfg, (u32) 0, \ > + sizeof(struct var_eeprom_cfg)); > +#endif > + } > + } else { > + eeprom_debug("Error! Couldn't find EEPROM device\n"); > + } > + > + return ret; > +} > +#endif /* CONFIG_SPL_BUILD */ > + > +void var_eeprom_strings_print(struct var_eeprom_cfg *p_var_eeprom_cfg) > +{ > + p_var_eeprom_cfg->header.part_number[sizeof(p_var_eeprom_cfg->header.part_number)-1] = (u8)0x00; > + p_var_eeprom_cfg->header.Assembly[sizeof(p_var_eeprom_cfg->header.Assembly)-1] = (u8)0x00; > + p_var_eeprom_cfg->header.date[sizeof(p_var_eeprom_cfg->header.date)-1] = (u8)0x00; > + > + printf("Part number: %s\n", (char *)p_var_eeprom_cfg->header.part_number); > + printf("Assembly: %s\n", (char *)p_var_eeprom_cfg->header.Assembly); > + printf("Date of production: %s\n", (char *)p_var_eeprom_cfg->header.date); > +} > + > +static int var_eeprom_write(uchar *ptr, u32 size, u32 offset) > +{ > + int ret = 0; > + u32 size_written; > + u32 size_to_write; > + u32 P0_select_page_EEPROM; > + u32 chip; > + u32 addr; > + > + /* Write to EEPROM device */ > + size_written = 0; > + size_to_write = size; > + while ((0 == ret) && (size_written < size_to_write)) { > + P0_select_page_EEPROM = (offset > 0xFF); > + chip = VAR_MX6_EEPROM_CHIP + P0_select_page_EEPROM; > + addr = (offset & 0xFF); > + ret = i2c_write(chip, addr, 1, ptr, VAR_MX6_EEPROM_WRITE_MAX_SIZE); > + > + /* Wait for EEPROM write operation to complete (No ACK) */ > + mdelay(11); > + > + size_written += VAR_MX6_EEPROM_WRITE_MAX_SIZE; > + offset += VAR_MX6_EEPROM_WRITE_MAX_SIZE; > + ptr += VAR_MX6_EEPROM_WRITE_MAX_SIZE; > + } > + > + return ret; > +} There is eprom_read() and eprom_write() from cmd/eeprom.c. Does it not work in your case ? > + > +/* > + * vareeprom command intepreter. > + */ > +static int do_var_eeprom_params(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) > +{ > + struct var_eeprom_cfg var_eeprom_cfg; > + int offset; > + > + if (argc != 4) > + return -1; > + > + memset(&var_eeprom_cfg, 0x00, sizeof(var_eeprom_cfg)); > + > + memcpy(&var_eeprom_cfg.header.part_number[0], argv[1], sizeof(var_eeprom_cfg.header.part_number)); > + memcpy(&var_eeprom_cfg.header.Assembly[0], argv[2], sizeof(var_eeprom_cfg.header.Assembly)); > + memcpy(&var_eeprom_cfg.header.date[0], argv[3], sizeof(var_eeprom_cfg.header.date)); > + > + var_eeprom_strings_print(&var_eeprom_cfg); > + > + offset = (uchar *)&var_eeprom_cfg.header.part_number[0] - (uchar *)&var_eeprom_cfg.header; > + if (var_eeprom_write((uchar *)&var_eeprom_cfg.header.part_number[0], \ > + sizeof(var_eeprom_cfg.header.part_number), \ > + VAR_MX6_EEPROM_STRUCT_OFFSET + offset) ) { > + printf("Error writing to EEPROM!\n"); > + return -1; > + } > + > + offset = (uchar *)&var_eeprom_cfg.header.Assembly[0] - (uchar *)&var_eeprom_cfg; > + if (var_eeprom_write((uchar *)&var_eeprom_cfg.header.Assembly[0], \ > + sizeof(var_eeprom_cfg.header.Assembly), \ > + VAR_MX6_EEPROM_STRUCT_OFFSET + offset) ) { > + printf("Error writing to EEPROM!\n"); > + return -1; > + } > + > + offset = (uchar *)&var_eeprom_cfg.header.date[0] - (uchar *)&var_eeprom_cfg; > + if (var_eeprom_write((uchar *)&var_eeprom_cfg.header.date[0], \ > + sizeof(var_eeprom_cfg.header.date), \ > + VAR_MX6_EEPROM_STRUCT_OFFSET + offset) ) { > + printf("Error writing to EEPROM!\n"); > + return -1; > + } > + > + printf("EEPROM updated successfully\n"); > + > + return 0; > +} > + > +U_BOOT_CMD( > + vareeprom, 5, 1, do_var_eeprom_params, > + "For internal use only", > + "- Do not use" > +); > diff --git a/board/variscite/mx6var_som/mx6var_eeprom.h b/board/variscite/mx6var_som/mx6var_eeprom.h > new file mode 100644 > index 0000000..5c70a27 > --- /dev/null > +++ b/board/variscite/mx6var_som/mx6var_eeprom.h > @@ -0,0 +1,88 @@ > +/* > + * Copyright (C) 2016 Variscite Ltd. All Rights Reserved. > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#ifndef _MX6VAR_EEPROM_H_ > +#define _MX6VAR_EEPROM_H_ > + > +#define VARISCITE_MAGIC 0x49524157 /* == HEX("VARI")*/ > + > +#define VAR_MX6_EEPROM_CHIP 0x56 > +#define VAR_DART_EEPROM_CHIP 0x52 > + > +#define VAR_MX6_EEPROM_STRUCT_OFFSET 0x00000000 > + > +#define VAR_MX6_EEPROM_WRITE_MAX_SIZE 0x4 > + > +#define EEPROM_SIZE_BYTES 512 > + > +#define VAR_DDR_INIT_OPCODE_WRITE_VAL_TO_ADDRESS 0x00000000 > +#define VAR_DDR_INIT_OPCODE_WAIT_MASK_RISING 0x10000000 > +#define VAR_DDR_INIT_OPCODE_WAIT_MASK_FALLING 0x20000000 > +#define VAR_DDR_INIT_OPCODE_DELAY_USEC 0x30000000 > + > +#define SPL_DRAM_INIT_STATUS_OK 0 > +#define SPL_DRAM_INIT_STATUS_ERROR_NO_EEPROM 1 > +#define SPL_DRAM_INIT_STATUS_ERROR_NO_EEPROM_STRUCT_DETECTED 2 > + > +struct var_eeprom_cfg_header > +{ > + u32 variscite_magic; /* == HEX("VARI")?*/ > + u8 part_number[16]; > + u8 Assembly[16]; > + u8 date[16]; > + u8 version; > + u8 reserved[7]; > + u32 ddr_size; > +}; > + > +struct var_pinmux_group_regs > +{ > + u32 IOMUXC_SW_PAD_CTL_GRP_DDR_TYPE; > + u32 IOMUXC_SW_PAD_CTL_GRP_DDRPKE; > + u32 IOMUXC_SW_PAD_CTL_GRP_DDRMODE_CTL; > + u32 IOMUXC_SW_PAD_CTL_GRP_DDRMODE; > + u32 IOMUXC_SW_PAD_CTL_PAD_DRAM_SDBA2; > + u32 dram_reset; > + u32 dram_sdcke0; > + u32 dram_sdcke1; > + u32 dram_sdodt0; > + u32 dram_sdodt1; > + u32 reserved; > + u32 pinmux_ctrlpad_all_value; > +}; > + > +struct reg_write_opcode > +{ > + u32 address; /* address encoded with opcode */ > + u32 value; > +}; > + > +struct var_eeprom_cfg > +{ > + struct var_eeprom_cfg_header header; > + struct var_pinmux_group_regs pinmux_group; > + struct reg_write_opcode write_opcodes[ \ > + (EEPROM_SIZE_BYTES \ > + - sizeof(struct var_eeprom_cfg_header) \ > + - sizeof(struct var_pinmux_group_regs)) \ > + / sizeof(struct reg_write_opcode) ]; > +}; > + > +bool var_eeprom_is_valid(struct var_eeprom_cfg *p_var_eeprom_cfg); > + > +/* init ddr iomux from struct */ > +void var_eeprom_mx6dlsl_dram_setup_iomux_from_struct(struct var_pinmux_group_regs *pinmux_group); > + > +void var_eeprom_mx6qd_dram_setup_iomux_from_struct(struct var_pinmux_group_regs *pinmux_group); > + > +/* init ddr from struct */ > +void var_eeprom_dram_init_from_struct(struct var_eeprom_cfg *p_var_eeprom_cfg); > + > +int var_eeprom_read_struct(struct var_eeprom_cfg *p_var_eeprom_cfg); > + > +void var_eeprom_strings_print(struct var_eeprom_cfg *p_var_eeprom_cfg); > + > +#endif /* _MX6VAR_EEPROM_H_ */ > diff --git a/board/variscite/mx6var_som/mx6var_eeprom_v2.c b/board/variscite/mx6var_som/mx6var_eeprom_v2.c > new file mode 100644 > index 0000000..490b470 > --- /dev/null > +++ b/board/variscite/mx6var_som/mx6var_eeprom_v2.c > @@ -0,0 +1,231 @@ > +/* > + * Copyright (C) 2016 Variscite Ltd. All Rights Reserved. > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#ifdef CONFIG_SPL_BUILD > +#include <common.h> > +#include <i2c.h> > +#include "mx6var_eeprom_v2.h" > + > +#ifdef EEPROM_V2_DEBUG > +#define eeprom_v2_debug(M, ...) printf("EEPROM_V2 DEBUG: " M, ##__VA_ARGS__) > +#else > +#define eeprom_v2_debug(M, ...) > +#endif > + > +static u32 get_address_by_index(unsigned char index, u32 *ram_addresses); > +static u32 get_value_by_index(unsigned char index, u32 *ram_values); > +static int handle_one_command(struct eeprom_command *eeprom_commands,int command_num, \ > + u32 *ram_addresses, u32 *ram_values); > + > + > +bool var_eeprom_v2_is_valid(struct var_eeprom_v2_cfg *p_var_eeprom_v2_cfg) > +{ > + return (VARISCITE_MAGIC_V2 == p_var_eeprom_v2_cfg->variscite_magic); > +} > + > + > +void var_eeprom_v2_strings_print(struct var_eeprom_v2_cfg *p_var_eeprom_v2_cfg) > +{ > + p_var_eeprom_v2_cfg->part_number[sizeof(p_var_eeprom_v2_cfg->part_number)-1] = (u8)0x00; > + p_var_eeprom_v2_cfg->Assembly[sizeof(p_var_eeprom_v2_cfg->Assembly)-1] = (u8)0x00; > + p_var_eeprom_v2_cfg->date[sizeof(p_var_eeprom_v2_cfg->date)-1] = (u8)0x00; > + > + printf("Part number: %s\n", (char *)p_var_eeprom_v2_cfg->part_number); > + printf("Assembly: %s\n", (char *)p_var_eeprom_v2_cfg->Assembly); > + printf("Date of production: %s\n", (char *)p_var_eeprom_v2_cfg->date); > +} > + > + > +void load_custom_data(u32 *custom_addresses_values, u32 *ram_addresses, u32 *ram_values) > +{ > + int i, j=0; > + > + for (i=0; i<MAXIMUM_RAM_ADDRESSES; i++) { > + ram_addresses[i]=0; > + } > + for (i=0; i<MAXIMUM_RAM_VALUES; i++) { > + ram_values[i]=0; > + } > + > + for (i=0; i<MAXIMUM_RAM_ADDRESSES; i++) { > + if (custom_addresses_values[i]==0) > + break; > + ram_addresses[j]=custom_addresses_values[i]; > + j++; > + } > + > + i++; > + if (i > MAXIMUM_RAM_ADDRESSES) > + return; > + > + j=0; > + for (; i<MAXIMUM_RAM_VALUES; i++) { > + if (custom_addresses_values[i]==0) > + break; > + ram_values[j]=custom_addresses_values[i]; > + j++; > + } > +} > + > + > +int handle_eeprom_data(struct var_eeprom_v2_cfg *var_eeprom_v2_cfg, \ > + u32 *ram_addresses, u32 *ram_values) > +{ > + load_custom_data(var_eeprom_v2_cfg->custom_addresses_values, ram_addresses, ram_values); > + return setup_ddr_parameters(var_eeprom_v2_cfg->eeprom_commands, \ > + ram_addresses, ram_values); > +} > + > + > +int setup_ddr_parameters(struct eeprom_command *eeprom_commands, \ > + u32 *ram_addresses, u32 *ram_values) > +{ > + int i=0; > + > + while (i < MAXIMUM_COMMANDS_NUMBER) { > + i = handle_one_command(eeprom_commands, i, ram_addresses, ram_values); > + if (i < 0) > + return -1; > + if (i == 0) > + return 0; > + } > + return 0; > +} > + > + > +static int handle_one_command(struct eeprom_command *eeprom_commands, int command_num, \ > + u32 *ram_addresses, u32 *ram_values) > +{ > + volatile u32 *data; > + u32 address; > + u32 value; > + > + eeprom_v2_debug("Executing command %03d: %03d, %03d\n", > + command_num, > + eeprom_commands[command_num].address_index, > + eeprom_commands[command_num].value_index); > + > + switch(eeprom_commands[command_num].address_index) { > + case WHILE_NOT_EQUAL_INDEX: > + command_num++; > + address=get_address_by_index(eeprom_commands[command_num].address_index, ram_addresses); > + value=get_value_by_index(eeprom_commands[command_num].value_index, ram_values); > + data=(u32*)address; > + eeprom_v2_debug("Waiting while data at address %08x is not equal %08x\n", address, value); > + > + while(data[0]!=value); > + > + command_num++; > + break; > + case WHILE_EQUAL_INDEX: > + command_num++; > + address=get_address_by_index(eeprom_commands[command_num].address_index, ram_addresses); > + value=get_value_by_index(eeprom_commands[command_num].value_index, ram_values); > + data=(u32*)address; > + eeprom_v2_debug("Waiting while data at address %08x is equal %08x\n", address, value); > + > + while(data[0]==value); > + > + command_num++; > + break; > + case WHILE_AND_INDEX: > + command_num++; > + address=get_address_by_index(eeprom_commands[command_num].address_index, ram_addresses); > + value=get_value_by_index(eeprom_commands[command_num].value_index, ram_values); > + data=(u32*)address; > + eeprom_v2_debug("Waiting while data at address %08x and %08x is not zero\n", address, value); > + > + while(data[0]&value); > + > + command_num++; > + break; > + case WHILE_NOT_AND_INDEX: > + command_num++; > + address=get_address_by_index(eeprom_commands[command_num].address_index, ram_addresses); > + value=get_value_by_index(eeprom_commands[command_num].value_index, ram_values); > + data=(u32*)address; > + eeprom_v2_debug("Waiting while data at address %08x and %08x is zero\n", address, value); > + > + while(!(data[0]&value)); Code is quite confusing - it does quite the same thing, and can be rewritten factorizing most part. > + > + command_num++; > + break; > + case DELAY_10USEC_INDEX: > + /* Delay for Value * 10 uSeconds */ > + eeprom_v2_debug("Delaying for %d microseconds\n", eeprom_commands[command_num].value_index*10); > + udelay((int)(eeprom_commands[command_num].value_index*10)); > + command_num++; > + break; > + case LAST_COMMAND_INDEX: > + command_num=0; > + break; > + default: > + address=get_address_by_index(eeprom_commands[command_num].address_index, ram_addresses); > + value=get_value_by_index(eeprom_commands[command_num].value_index, ram_values); > + data=(u32*)address; > + eeprom_v2_debug("Setting data at address %08x to %08x\n", address, value); > + data[0]=value; > + command_num++; > + break; > + } > + > + return command_num; > +} > + > + > +static u32 get_address_by_index(unsigned char index, u32 *ram_addresses) > +{ > + /* > + * DDR Register struct > + * The eeprom contains a structure of: > + * 1 byte index in this addresses table, and > + * 1 byte index to common values in the next table - to write to this address. > + * If there are new addresses from the calibration program, > + * they should be added to the end of the array. > + * The maximum array size is 256 addresses. > + */ > + const u32 rom_addresses[]= > + { > + #include "addresses.inc" > + }; > + > + if (index >= MAXIMUM_ROM_ADDR_INDEX) > + return ram_addresses[index-MAXIMUM_ROM_ADDR_INDEX]; > + > + return rom_addresses[index]; > +} > + > + > +static u32 get_value_by_index(unsigned char index, u32 *ram_values) > +{ > + const u32 rom_values[] = > + { > + #include "values.inc" > + }; > + > + if (index >= MAXIMUM_ROM_VALUE_INDEX) > + return ram_values[index-MAXIMUM_ROM_VALUE_INDEX]; > + > + return rom_values[index]; > +} > + > + > +int var_eeprom_v2_read_struct(struct var_eeprom_v2_cfg *var_eeprom_v2_cfg, \ > + unsigned char address) > +{ > + int eeprom_found = i2c_probe(address); > + if (0 == eeprom_found) { > + if (i2c_read(address, 0, 1, (void*) var_eeprom_v2_cfg, \ > + sizeof(struct var_eeprom_v2_cfg))) { > + printf("Read device ID error!\n"); > + return -1; > + } > + } else { > + printf("Error! Couldn't find EEPROM device\n"); > + } > + return 0; > +} As I said, I have not understood at all the reason for that. > +#endif > diff --git a/board/variscite/mx6var_som/mx6var_eeprom_v2.h b/board/variscite/mx6var_som/mx6var_eeprom_v2.h > new file mode 100644 > index 0000000..cebf46d > --- /dev/null > +++ b/board/variscite/mx6var_som/mx6var_eeprom_v2.h > @@ -0,0 +1,55 @@ > +/* > + * Copyright (C) 2016 Variscite Ltd. All Rights Reserved. > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#ifndef _MX6VAR_V2_EEPROM_H_ > +#define _MX6VAR_V2_EEPROM_H_ > + > +#define VARISCITE_MAGIC_V2 0x32524156 /* == HEX("VAR2") */ > + > +#define MAXIMUM_ROM_ADDR_INDEX 200 > +#define MAXIMUM_ROM_VALUE_INDEX 200 > +#define WHILE_NOT_EQUAL_INDEX 241 > +#define WHILE_EQUAL_INDEX 242 > +#define WHILE_AND_INDEX 243 > +#define WHILE_NOT_AND_INDEX 244 > +#define DELAY_10USEC_INDEX 245 > +#define LAST_COMMAND_INDEX 255 > + > +#define MAXIMUM_RAM_ADDRESSES 32 > +#define MAXIMUM_RAM_VALUES 32 > + > +#define MAXIMUM_COMMANDS_NUMBER 150 > + > +struct __attribute__((packed)) eeprom_command > +{ > + unsigned char address_index; > + unsigned char value_index; > +}; > + > +struct __attribute__((packed)) var_eeprom_v2_cfg > +{ > + u32 variscite_magic; /* == HEX("VAR2")? */ > + u8 part_number[16]; > + u8 Assembly[16]; > + u8 date[12]; > + u32 custom_addresses_values[32]; > + struct eeprom_command eeprom_commands[MAXIMUM_COMMANDS_NUMBER]; > + u8 reserved[34]; > + u8 ddr_size; > + u8 crc; > +}; > + > +bool var_eeprom_v2_is_valid(struct var_eeprom_v2_cfg *p_var_eeprom_v2_cfg); > +void var_eeprom_v2_strings_print(struct var_eeprom_v2_cfg *p_var_eeprom_v2_cfg); > +int handle_eeprom_data(struct var_eeprom_v2_cfg *var_eeprom_v2_cfg, \ > + u32 *ram_addresses, u32 *ram_values); > +int setup_ddr_parameters(struct eeprom_command *eeprom_commands, \ > + u32 *ram_addresses, u32 *ram_values); > +void load_custom_data(u32 *custom_addresses_values, u32 *ram_addresses, u32 *ram_values); > +int var_eeprom_v2_read_struct(struct var_eeprom_v2_cfg *var_eeprom_v2_cfg, \ > + unsigned char address); > + > +#endif /* _MX6VAR_V2_EEPROM_H_ */ > diff --git a/board/variscite/mx6var_som/mx6var_som.c b/board/variscite/mx6var_som/mx6var_som.c > new file mode 100644 > index 0000000..e99690b > --- /dev/null > +++ b/board/variscite/mx6var_som/mx6var_som.c > @@ -0,0 +1,1587 @@ > +/* > + * Copyright (C) 2012 Freescale Semiconductor, Inc. > + * Author: Fabio Estevam <fabio.estevam@freescale.com> > + * > + * Copyright (C) 2016 Variscite Ltd. All Rights Reserved. > + * > + * Author: Eran Matityahu <eran.m@variscite.com> > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#include <asm/arch/clock.h> > +#include <asm/arch/imx-regs.h> > +#include <asm/arch/iomux.h> > +#include <malloc.h> > +#include <asm/arch/mx6-pins.h> > +#include <asm/errno.h> > +#include <asm/gpio.h> > +#include <asm/imx-common/mxc_i2c.h> > +#include <asm/imx-common/iomux-v3.h> > +#include <asm/imx-common/boot_mode.h> > +#include <asm/imx-common/video.h> > +#include <mmc.h> > +#include <fsl_esdhc.h> > +#include <micrel.h> > +#include <miiphy.h> > +#include <netdev.h> > +#include <asm/arch/mxc_hdmi.h> > +#include <asm/arch/crm_regs.h> > +#include <asm/io.h> > +#include <asm/arch/sys_proto.h> > +#include <i2c.h> > +#include <power/pmic.h> > +#include <power/pfuze100_pmic.h> > +#include <usb.h> > +#include <usb/ehci-fsl.h> > + > +DECLARE_GLOBAL_DATA_PTR; > + > +#define UART_PAD_CTRL (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_PUS_47K_UP | \ > + PAD_CTL_SPEED_LOW | PAD_CTL_DSE_80ohm | \ > + PAD_CTL_SRE_FAST | PAD_CTL_HYS) > + > +#define ENET_PAD_CTRL (PAD_CTL_PUS_100K_UP | \ > + PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS) > + > +#define GPMI_PAD_CTRL0 (PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_PUS_100K_UP) > +#define GPMI_PAD_CTRL1 (PAD_CTL_DSE_40ohm | PAD_CTL_SPEED_MED | \ > + PAD_CTL_SRE_FAST) > +#define GPMI_PAD_CTRL2 (GPMI_PAD_CTRL0 | GPMI_PAD_CTRL1) > + > +#define PER_VCC_EN_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_PUS_100K_UP | \ > + PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS | \ > + PAD_CTL_ODE | PAD_CTL_SRE_FAST) > + > +#define OTG_ID_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 VAR_SOM_BACKLIGHT_EN IMX_GPIO_NR(4, 30) > + > +bool lvds_enabled=false; > + > +#ifdef CONFIG_SYS_USE_NAND > +static int var_load_file_from_nand(u32 addr, char *filename) > +{ > + extern int ubi_part(char *part_name, const char *vid_header_offset); > + extern int ubifs_init(void); > + extern int uboot_ubifs_mount(char *vol_name); > + extern int ubifs_load(char *filename, u32 addr, u32 size); > + extern void cmd_ubifs_umount(void); > + > + char *ubi_part_name = "rootfs"; > + char *ubifs_vol_name = "ubi0:rootfs"; > + > + if (ubi_part(ubi_part_name, NULL)) > + return -1; > + if (ubifs_init()) > + return -1; > + if (uboot_ubifs_mount(ubifs_vol_name)) > + return -1; > + > + /* Load the file to memory */ > + if (ubifs_load(filename, addr, 0)) { > + printf("Error: splash file not found %s\n", filename); > + cmd_ubifs_umount(); > + return -1; > + } > + cmd_ubifs_umount(); Why ? All this stuff can be done in a much more flexible way scripts in the environment. It should be not hard-coded. > + return 0; > +} > +#endif > + > +static int var_load_file_from_mmc(u32 addr, char *filename) > +{ > +#define FS_TYPE_EXT 2 > + extern int fs_set_blk_dev(const char *ifname, const char *dev_part_str, int fstype); > + extern int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len, > + loff_t *actread); > + > + loff_t len_read; > + > +#ifdef CONFIG_SYS_USE_NAND > + if (fs_set_blk_dev("mmc", "1:1", FS_TYPE_EXT)) > + return -1; > +#else > + if (fs_set_blk_dev("mmc", "0:2", FS_TYPE_EXT)) > + return -1; > +#endif > + > + if (fs_read(filename, addr, 0, 0, &len_read)) { > + printf("Error: splash file not found %s\n", filename); > + return -1; > + } > + > + printf("%llu bytes read\n", len_read); > + return 0; > +#undef FS_TYPE_EXT > +} I disagree - the logic should be not bound with the code. There is not such a way in U-Boot. Boards rely on the environment, and the hush shell does the rest, without hardcoding this into the board. This behavior is also wrong for another reason: this drives crazy anyone working with the shell. In fact, he can assume to define the behaviour using the environment, but this is overwritten by your code. > + > +#ifdef CONFIG_SPLASH_SCREEN > +int splash_screen_prepare(void) > +{ > + char *filename; > + const char *addr_str; > + u32 addr = 0; > +#ifdef CONFIG_SYS_USE_NAND > + char *s; > +#endif > + > + /* Get filename and load address from env */ > + addr_str = getenv("splashimage"); > + if (!addr_str) { > + return -1; > + } > + addr = simple_strtoul(addr_str, 0, 16); > + if (addr == 0) { > + printf("Error: bad splashimage value %s\n", addr_str); > + return -1; > + } > + filename = getenv("splash_filename"); > + if (!filename) { > + printf("Error: splashimage defined, but splash_filename isn't\n"); > + return -1; > + } > + > +#ifdef CONFIG_SYS_USE_NAND > + s = getenv("chosen_rootfs"); > + if ((s != NULL) && (!strcmp(s, "emmc"))) { > + if (var_load_file_from_mmc(addr, filename)) > + return -1; > + } else { > + if (var_load_file_from_nand(addr, filename)) > + return -1; > + } Ditto. All this logic must be not part of code. > +#else /* MMC */ > + if (var_load_file_from_mmc(addr, filename)) > + return -1; > +#endif > + > + /* Turn on backlight */ > + if (lvds_enabled) > + gpio_set_value(VAR_SOM_BACKLIGHT_EN, 1); And hardware-related part, as this one for backlight, are mixed with behaviour parts (setting rootfs, for example). > + > + return 0; > +} > +#endif > + > +static bool is_som_solo(void) > +{ > + bool ret; > + int oldbus = i2c_get_bus_num(); > + > + i2c_set_bus_num(PMIC_I2C_BUS); > + /* Probing for PMIC which is not preset only on som solo */ > + ret = (0 != i2c_probe(CONFIG_POWER_PFUZE100_I2C_ADDR)); > + > + i2c_set_bus_num(oldbus); > + return ret; If I understand from the title, you want to check if the CPU is a Solo or DL. But then, instead of reading the CPU-ID, as we expect, you check if you have a PMIC. It looks not straightforward. > +} > + > +static bool is_solo_custom_board(void) > +{ > + bool ret; > + int oldbus = i2c_get_bus_num(); > + > + i2c_set_bus_num(1); > + /* Probing for extra EEPROM present only on solo custom board */ > + ret = (0 == i2c_probe(0x51)); > + > + i2c_set_bus_num(oldbus); > + return ret; > +} > + > +static bool is_cpu_pop_package(void) > +{ > + uint soc_sbmr = readl(SRC_BASE_ADDR + 0x4); > + struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR; > + u32 reg; > + u32 type; > + > + reg = readl(&anatop->digprog); > + type = ((reg >> 16) & 0xff); > + if (type != MXC_CPU_MX6DL) > + return ((soc_sbmr & 0x200000) != 0); There are a lot of is_cpu_type() to check for SOC type. > + return false; > +} > + > +static inline bool is_dart_board(void) > +{ > + return is_cpu_pop_package(); > +} > + > +static inline bool is_mx6_custom_board(void) > +{ > + return (!is_dart_board() && !is_solo_custom_board()); > +} I do not know your board, but the way to select if this is the evaluation board or a custom board seems to me arguable. > + > +enum mmc_boot_device { > + SD_BOOT, > + MMC_BOOT, > + OTHER_BOOT, > +}; > + > +static unsigned get_mmc_boot_device(void) > +{ > + struct src *psrc = (struct src *)SRC_BASE_ADDR; > + unsigned reg = (readl(&psrc->sbmr1) >> 5) & 0x7; > + > + switch(reg) { > + case 0x2: > + return SD_BOOT; > + case 0x3: > + return MMC_BOOT; > + default: > + return OTHER_BOOT; > + } > +} > + > +static bool is_mmc_present(struct mmc *mmc) > +{ > + int err; > + struct mmc_cmd cmd; > + > + if (mmc->has_init) > + return true; > + > + mdelay(1); > + cmd.cmdidx = MMC_CMD_GO_IDLE_STATE; > + cmd.cmdarg = 0; > + cmd.resp_type = MMC_RSP_NONE; > + > + err = mmc->cfg->ops->send_cmd(mmc, &cmd, NULL); > + if (err) > + return false; > + > + mdelay(2); > + > + cmd.cmdidx = MMC_CMD_SEND_OP_COND; > + cmd.resp_type = MMC_RSP_R3; > + cmd.cmdarg = 0; > + > + err = mmc->cfg->ops->send_cmd(mmc, &cmd, NULL); > + return (!err); > +} No idea for that, this is already managed, including error branches, by common code in the MMC subsystem. > + > +static void print_emmc_size(void) > +{ > + struct mmc *mmc; > + int device; > + > + if (is_dart_board() && (MMC_BOOT == get_mmc_boot_device())) > + device=0; > + else > + device=1; This is another place where mmc order is set, leading to further confusion. > + > + mmc = find_mmc_device(device); > + if (!mmc || !is_mmc_present(mmc) || mmc_init(mmc) || IS_SD(mmc)) { > + puts("No eMMC\n"); > + return; > + } > + puts("eMMC: "); > + print_size(mmc->capacity, "\n"); > +} > + > +static u32 var_ram_size(void) > +{ > + u32 *p_ram_size = (u32 *)RAM_SIZE_ADDR; > + return *p_ram_size; > +} > + > +int dram_init(void) > +{ > + gd->ram_size = var_ram_size() * 1024 * 1024; > + return 0; > +} This is not the correct way to do it. U-Boot can detect the RAM on board using get_ram_size(). You have a var_rime_size() function, but this does not detect anything a returns a value defined at compiled time. Use get_ram_size() instead. > + > +static iomux_v3_cfg_t const uart1_pads[] = { > + IOMUX_PADS(PAD_CSI0_DAT10__UART1_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)), > + IOMUX_PADS(PAD_CSI0_DAT11__UART1_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)), > +}; > + > +static iomux_v3_cfg_t const enet_pads1[] = { > + IOMUX_PADS(PAD_ENET_MDIO__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL)), > + IOMUX_PADS(PAD_ENET_MDC__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL)), > + IOMUX_PADS(PAD_RGMII_TXC__RGMII_TXC | MUX_PAD_CTRL(ENET_PAD_CTRL)), > + IOMUX_PADS(PAD_RGMII_TD0__RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL)), > + IOMUX_PADS(PAD_RGMII_TD1__RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL)), > + IOMUX_PADS(PAD_RGMII_TD2__RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL)), > + IOMUX_PADS(PAD_RGMII_TD3__RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL)), > + IOMUX_PADS(PAD_RGMII_TX_CTL__RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL)), > + IOMUX_PADS(PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL)), > + /* pin 35 - 1 (PHY_AD2) on reset */ > + IOMUX_PADS(PAD_RGMII_RXC__GPIO6_IO30 | MUX_PAD_CTRL(NO_PAD_CTRL)), > + /* pin 32 - 1 - (MODE0) all */ > + IOMUX_PADS(PAD_RGMII_RD0__GPIO6_IO25 | MUX_PAD_CTRL(NO_PAD_CTRL)), > + /* pin 31 - 1 - (MODE1) all */ > + IOMUX_PADS(PAD_RGMII_RD1__GPIO6_IO27 | MUX_PAD_CTRL(NO_PAD_CTRL)), > + /* pin 28 - 1 - (MODE2) all */ > + IOMUX_PADS(PAD_RGMII_RD2__GPIO6_IO28 | MUX_PAD_CTRL(NO_PAD_CTRL)), > + /* pin 27 - 1 - (MODE3) all */ > + IOMUX_PADS(PAD_RGMII_RD3__GPIO6_IO29 | MUX_PAD_CTRL(NO_PAD_CTRL)), > + /* pin 33 - 1 - (CLK125_EN) 125Mhz clockout enabled */ > + IOMUX_PADS(PAD_RGMII_RX_CTL__GPIO6_IO24 | MUX_PAD_CTRL(NO_PAD_CTRL)), > + /* AR8031 PHY Reset */ > + IOMUX_PADS(PAD_ENET_CRS_DV__GPIO1_IO25 | MUX_PAD_CTRL(NO_PAD_CTRL)), > +}; > + > +static iomux_v3_cfg_t const enet_pads2[] = { > + IOMUX_PADS(PAD_RGMII_RXC__RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL)), > + IOMUX_PADS(PAD_RGMII_RD0__RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL)), > + IOMUX_PADS(PAD_RGMII_RD1__RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL)), > + IOMUX_PADS(PAD_RGMII_RD2__RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL)), > + IOMUX_PADS(PAD_RGMII_RD3__RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL)), > + IOMUX_PADS(PAD_RGMII_RX_CTL__RGMII_RX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL)), > +}; > + > +static void setup_iomux_enet(void) > +{ > + gpio_direction_output(IMX_GPIO_NR(1, 25), 0); /* Variscite SOM PHY reset */ > + gpio_direction_output(IMX_GPIO_NR(6, 30), 1); > + gpio_direction_output(IMX_GPIO_NR(6, 25), 1); > + gpio_direction_output(IMX_GPIO_NR(6, 27), 1); > + gpio_direction_output(IMX_GPIO_NR(6, 28), 1); > + gpio_direction_output(IMX_GPIO_NR(6, 29), 1); > + > + SETUP_IOMUX_PADS(enet_pads1); > + > + gpio_direction_output(IMX_GPIO_NR(6, 24), 1); > + > + /* Need delay 10ms according to KSZ9021 spec */ > + mdelay(10); > + gpio_set_value(IMX_GPIO_NR(1, 25), 1); > + > + SETUP_IOMUX_PADS(enet_pads2); > +} > + > +static iomux_v3_cfg_t const usdhc1_pads[] = { > + IOMUX_PADS(PAD_SD1_CLK__SD1_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > + IOMUX_PADS(PAD_SD1_CMD__SD1_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > + IOMUX_PADS(PAD_SD1_DAT0__SD1_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > + IOMUX_PADS(PAD_SD1_DAT1__SD1_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > + IOMUX_PADS(PAD_SD1_DAT2__SD1_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > + IOMUX_PADS(PAD_SD1_DAT3__SD1_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > +}; > + > + > +static iomux_v3_cfg_t const usdhc2_pads[] = { > + IOMUX_PADS(PAD_SD2_CLK__SD2_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > + IOMUX_PADS(PAD_SD2_CMD__SD2_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > + IOMUX_PADS(PAD_SD2_DAT0__SD2_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > + IOMUX_PADS(PAD_SD2_DAT1__SD2_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > + IOMUX_PADS(PAD_SD2_DAT2__SD2_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > + IOMUX_PADS(PAD_SD2_DAT3__SD2_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > +}; > + > +static iomux_v3_cfg_t const usdhc3_pads[] = { > + IOMUX_PADS(PAD_SD3_CLK__SD3_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > + IOMUX_PADS(PAD_SD3_CMD__SD3_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > + IOMUX_PADS(PAD_SD3_DAT0__SD3_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > + IOMUX_PADS(PAD_SD3_DAT1__SD3_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > + IOMUX_PADS(PAD_SD3_DAT2__SD3_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > + IOMUX_PADS(PAD_SD3_DAT3__SD3_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > +}; > + > +#ifdef CONFIG_SYS_I2C_MXC > +I2C_PADS(i2c_pad_info1, > + PAD_CSI0_DAT9__I2C1_SCL | MUX_PAD_CTRL(I2C_PAD_CTRL), > + PAD_CSI0_DAT9__GPIO5_IO27 | MUX_PAD_CTRL(I2C_PAD_CTRL), > + IMX_GPIO_NR(5, 27), > + PAD_CSI0_DAT8__I2C1_SDA | MUX_PAD_CTRL(I2C_PAD_CTRL), > + PAD_CSI0_DAT8__GPIO5_IO26 | MUX_PAD_CTRL(I2C_PAD_CTRL), > + IMX_GPIO_NR(5, 26)); > + > +I2C_PADS(i2c_pad_info2, > + PAD_KEY_COL3__I2C2_SCL | MUX_PAD_CTRL(I2C_PAD_CTRL), > + PAD_KEY_COL3__GPIO4_IO12 | MUX_PAD_CTRL(I2C_PAD_CTRL), > + IMX_GPIO_NR(4, 12), > + PAD_KEY_ROW3__I2C2_SDA | MUX_PAD_CTRL(I2C_PAD_CTRL), > + PAD_KEY_ROW3__GPIO4_IO13 | MUX_PAD_CTRL(I2C_PAD_CTRL), > + IMX_GPIO_NR(4, 13)); > + > +I2C_PADS(i2c_pad_info3, > + PAD_GPIO_5__I2C3_SCL | MUX_PAD_CTRL(I2C_PAD_CTRL), > + PAD_GPIO_5__GPIO1_IO05 | MUX_PAD_CTRL(I2C_PAD_CTRL), > + IMX_GPIO_NR(1, 5), > + PAD_GPIO_16__I2C3_SDA | MUX_PAD_CTRL(I2C_PAD_CTRL), > + PAD_GPIO_16__GPIO7_IO11 | MUX_PAD_CTRL(I2C_PAD_CTRL), > + IMX_GPIO_NR(7, 11)); > +#endif > + > +void setup_local_i2c(void) { > + setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, I2C_PADS_INFO(i2c_pad_info1)); > + setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, I2C_PADS_INFO(i2c_pad_info2)); > + setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, I2C_PADS_INFO(i2c_pad_info3)); > +} > + > +iomux_v3_cfg_t const di0_pads[] = { > + IOMUX_PADS(PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK), /* DISP0_CLK */ > + IOMUX_PADS(PAD_DI0_PIN2__IPU1_DI0_PIN02), /* DISP0_HSYNC */ > + IOMUX_PADS(PAD_DI0_PIN3__IPU1_DI0_PIN03), /* DISP0_VSYNC */ > +}; > + Just these three pins for display ? Where are set the other ones ? > +static void var_setup_iomux_per_vcc_en(void) > +{ > + SETUP_IOMUX_PAD(PAD_EIM_D31__GPIO3_IO31 | MUX_PAD_CTRL(PER_VCC_EN_PAD_CTRL)); > + gpio_direction_output(IMX_GPIO_NR(3, 31), 1); > +} > + > +static void setup_iomux_uart(void) > +{ > + SETUP_IOMUX_PADS(uart1_pads); > +} > + > +#ifdef CONFIG_FSL_ESDHC > +struct fsl_esdhc_cfg usdhc_cfg[2] = { > + /* > + * This is incorrect for DART board but it's overwritten > + * in board_mmc_init() according to board setup > + */ > + {USDHC2_BASE_ADDR}, > + {USDHC1_BASE_ADDR}, > +}; > + > +int board_mmc_getcd(struct mmc *mmc) > +{ > + return 1; > +} I do not understand is_mmc_present() at all. U-Boot mmc subsystem sends already the commands to get if a mmc is present. You fix board_mmc_getcd(), but you have your own method instead of rely on common code. > + > +int board_mmc_init(bd_t *bis) > +{ > +#ifndef CONFIG_SPL_BUILD > + int ret; > + int i; > + > + /* > + * According to the board_mmc_init() the following map is done: > + * (U-Boot device node) (Physical Port) > + * On non DART boards: > + * mmc0 SD2 (SD) > + * mmc1 SD1 (eMMC) > + * > + * On DART board when booting from SD: > + * mmc0 SD2 (SD) > + * mmc1 SD3 (eMMC) > + * > + * On DART board when booting from eMMC: > + * mmc0 SD3 (eMMC) > + * mmc1 SD2 (SD) > + */ Why do you need to redefine the order depending from the boot device ? This makes things complicated and very confusing. Is it not much better to maintain the same enumeration ? > + for (i = 0; i < CONFIG_SYS_FSL_USDHC_NUM; i++) { > + switch (i) { > + case 0: > + if (is_dart_board() && (MMC_BOOT == get_mmc_boot_device())) { > + SETUP_IOMUX_PADS(usdhc3_pads); > + usdhc_cfg[0].esdhc_base = USDHC3_BASE_ADDR; > + usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK); > + } else { > + SETUP_IOMUX_PADS(usdhc2_pads); > + usdhc_cfg[0].esdhc_base = USDHC2_BASE_ADDR; > + usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK); > + } > + gd->arch.sdhc_clk = usdhc_cfg[0].sdhc_clk; > + usdhc_cfg[0].max_bus_width = 4; > + break; > + case 1: > + if (is_dart_board() && (MMC_BOOT == get_mmc_boot_device())) { > + SETUP_IOMUX_PADS(usdhc2_pads); > + usdhc_cfg[1].esdhc_base = USDHC2_BASE_ADDR; > + usdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK); > + } else if (is_dart_board()) { > + SETUP_IOMUX_PADS(usdhc3_pads); > + usdhc_cfg[1].esdhc_base = USDHC3_BASE_ADDR; > + usdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK); > + } else { > + SETUP_IOMUX_PADS(usdhc1_pads); > + usdhc_cfg[1].esdhc_base = USDHC1_BASE_ADDR; > + usdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK); > + } > + gd->arch.sdhc_clk = usdhc_cfg[1].sdhc_clk; > + usdhc_cfg[1].max_bus_width = 4; > + break; > + default: > + printf("Warning: you configured more USDHC controllers" > + "(%d) then supported by the board (%d)\n", > + i + 1, CONFIG_SYS_FSL_USDHC_NUM); > + return -EINVAL; > + } > + > + ret = fsl_esdhc_initialize(bis, &usdhc_cfg[i]); > + if (ret) > + return ret; > + } > + return 0; > +#else > + struct src *psrc = (struct src *)SRC_BASE_ADDR; > + unsigned reg = readl(&psrc->sbmr1) >> 11; > + /* > + * Upon reading BOOT_CFG register the following map is done: > + * Bit 11 and 12 of BOOT_CFG register can determine the current > + * mmc port > + * 0x1 SD2 (SD) > + * 0x2 SD3 (DART eMMC) > + */ > + > + switch (reg & 0x3) { > + case 0x1: > + SETUP_IOMUX_PADS(usdhc2_pads); > + usdhc_cfg[0].esdhc_base = USDHC2_BASE_ADDR; > + usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK); > + gd->arch.sdhc_clk = usdhc_cfg[0].sdhc_clk; > + usdhc_cfg[0].max_bus_width = 4; > + break; > + case 0x2: > + SETUP_IOMUX_PADS(usdhc3_pads); > + usdhc_cfg[0].esdhc_base = USDHC3_BASE_ADDR; > + usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK); > + gd->arch.sdhc_clk = usdhc_cfg[0].sdhc_clk; > + usdhc_cfg[0].max_bus_width = 4; > + break; > + } > + > + return fsl_esdhc_initialize(bis, &usdhc_cfg[0]); > +#endif > +} > +#endif > + > +#ifdef CONFIG_SYS_USE_NAND > +static iomux_v3_cfg_t const gpmi_pads[] = { > + IOMUX_PADS(PAD_NANDF_CLE__NAND_CLE | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), > + IOMUX_PADS(PAD_NANDF_ALE__NAND_ALE | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), > + IOMUX_PADS(PAD_NANDF_WP_B__NAND_WP_B | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), > + IOMUX_PADS(PAD_NANDF_RB0__NAND_READY_B | MUX_PAD_CTRL(GPMI_PAD_CTRL0)), > + IOMUX_PADS(PAD_NANDF_CS0__NAND_CE0_B | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), > + IOMUX_PADS(PAD_SD4_CMD__NAND_RE_B | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), > + IOMUX_PADS(PAD_SD4_CLK__NAND_WE_B | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), > + IOMUX_PADS(PAD_NANDF_D0__NAND_DATA00 | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), > + IOMUX_PADS(PAD_NANDF_D1__NAND_DATA01 | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), > + IOMUX_PADS(PAD_NANDF_D2__NAND_DATA02 | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), > + IOMUX_PADS(PAD_NANDF_D3__NAND_DATA03 | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), > + IOMUX_PADS(PAD_NANDF_D4__NAND_DATA04 | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), > + IOMUX_PADS(PAD_NANDF_D5__NAND_DATA05 | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), > + IOMUX_PADS(PAD_NANDF_D6__NAND_DATA06 | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), > + IOMUX_PADS(PAD_NANDF_D7__NAND_DATA07 | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), > + IOMUX_PADS(PAD_SD4_DAT0__NAND_DQS | MUX_PAD_CTRL(GPMI_PAD_CTRL1)), > +}; > + > +static void setup_gpmi_nand(void) > +{ > + struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; > + > + SETUP_IOMUX_PADS(gpmi_pads); > + > + /* gate ENFC_CLK_ROOT clock first,before clk source switch */ > + clrbits_le32(&mxc_ccm->CCGR2, MXC_CCM_CCGR2_IOMUX_IPT_CLK_IO_MASK); > + > + /* config gpmi and bch clock to 100 MHz */ > + clrsetbits_le32(&mxc_ccm->cs2cdr, > + MXC_CCM_CS2CDR_ENFC_CLK_PODF_MASK | > + MXC_CCM_CS2CDR_ENFC_CLK_PRED_MASK | > + MXC_CCM_CS2CDR_ENFC_CLK_SEL_MASK, > + MXC_CCM_CS2CDR_ENFC_CLK_PODF(0) | > + MXC_CCM_CS2CDR_ENFC_CLK_PRED(3) | > + MXC_CCM_CS2CDR_ENFC_CLK_SEL(3)); > + > + /* enable ENFC_CLK_ROOT clock */ > + setbits_le32(&mxc_ccm->CCGR2, MXC_CCM_CCGR2_IOMUX_IPT_CLK_IO_MASK); > + > + /* enable gpmi and bch clock gating */ > + setbits_le32(&mxc_ccm->CCGR4, > + MXC_CCM_CCGR4_RAWNAND_U_BCH_INPUT_APB_MASK | > + MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_BCH_MASK | > + MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_MASK | > + MXC_CCM_CCGR4_RAWNAND_U_GPMI_INPUT_APB_MASK | > + MXC_CCM_CCGR4_PL301_MX6QPER1_BCH_OFFSET); > + > + /* enable apbh clock gating */ > + setbits_le32(&mxc_ccm->CCGR0, MXC_CCM_CCGR0_APBHDMA_MASK); > +} > +#endif > + > +int board_phy_config(struct phy_device *phydev) > +{ > + /* min rx data delay */ > + ksz9021_phy_extended_write(phydev, > + MII_KSZ9021_EXT_RGMII_RX_DATA_SKEW, 0x0); > + /* min tx data delay */ > + ksz9021_phy_extended_write(phydev, > + MII_KSZ9021_EXT_RGMII_TX_DATA_SKEW, 0x0); > + /* max rx/tx clock delay, min rx/tx control */ > + ksz9021_phy_extended_write(phydev, > + MII_KSZ9021_EXT_RGMII_CLOCK_SKEW, 0xf0f0); > + > + if (phydev->drv->config) > + phydev->drv->config(phydev); > + > + return 0; > +} > + > +#if defined(CONFIG_VIDEO_IPUV3) > +static void disable_lvds(struct display_info_t const *dev) > +{ > + struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; > + > + int reg = readl(&iomux->gpr[2]); > + > + reg &= ~(IOMUXC_GPR2_LVDS_CH0_MODE_MASK | > + IOMUXC_GPR2_LVDS_CH1_MODE_MASK); > + > + writel(reg, &iomux->gpr[2]); > +} > + > +static void do_enable_hdmi(struct display_info_t const *dev) > +{ > + disable_lvds(dev); > + /* > + * imx_enable_hdmi_phy(); should be called here. > + * It is ommitted to avoid a current known bug where > + * the boot sometimes hangs if an HDMI cable is attached > + * - at least on some DART SOMs. > + */ > +} > + > +static void enable_lvds(struct display_info_t const *dev) > +{ > + struct iomuxc *iomux = (struct iomuxc *) > + IOMUXC_BASE_ADDR; > + u32 reg = readl(&iomux->gpr[2]); > + reg |= IOMUXC_GPR2_DATA_WIDTH_CH0_24BIT | > + IOMUXC_GPR2_DATA_WIDTH_CH1_18BIT; > + writel(reg, &iomux->gpr[2]); > + > + lvds_enabled=true; > +} > + > +static void lvds_enable_disable(struct display_info_t const *dev) > +{ > + if (getenv("splashimage") != NULL) > + enable_lvds(dev); > + else > + disable_lvds(dev); > +} > + > +static int detect_dart_vsc_display(struct display_info_t const *dev) > +{ > + return (!is_mx6_custom_board()); > +} > + > +static int detect_mx6cb_cdisplay(struct display_info_t const *dev) > +{ > + if (!is_mx6_custom_board()) > + return 0; > + > + i2c_set_bus_num(dev->bus); > + return (0 == i2c_probe(dev->addr)); > +} > + > +static int detect_mx6cb_rdisplay(struct display_info_t const *dev) > +{ > + if (!is_mx6_custom_board()) > + return 0; > + > + /* i2c probe the *c*display */ > + i2c_set_bus_num(MX6CB_CDISPLAY_I2C_BUS); > + return (0 != i2c_probe(MX6CB_CDISPLAY_I2C_ADDR)); > +} > + > +#define MHZ2PS(f) (1000000/(f)) > + > +struct display_info_t const displays[] = {{ > + .bus = -1, > + .addr = 0, > + .pixfmt = IPU_PIX_FMT_RGB24, > + .detect = detect_hdmi, > + .enable = do_enable_hdmi, > + .mode = { > + .name = "HDMI", > + .refresh = 60, > + .xres = 800, > + .yres = 480, > + .pixclock = 31777, > + .left_margin = 48, > + .right_margin = 16, > + .upper_margin = 33, > + .lower_margin = 10, > + .hsync_len = 96, > + .vsync_len = 2, > + .sync = 0, > + .vmode = FB_VMODE_NONINTERLACED > +} }, { > + .bus = -1, > + .addr = 0, > + .pixfmt = IPU_PIX_FMT_RGB666, > + .detect = detect_dart_vsc_display, > + .enable = lvds_enable_disable, > + .mode = { > + .name = "VAR-WVGA", > + .refresh = 60, /* optional */ > + .xres = 800, > + .yres = 480, > + .pixclock = MHZ2PS(50), > + .left_margin = 40, > + .right_margin = 40, > + .upper_margin = 29, > + .lower_margin = 13, > + .hsync_len = 48, > + .vsync_len = 3, > + .sync = FB_SYNC_EXT, > + .vmode = FB_VMODE_NONINTERLACED > +} }, { > + .bus = MX6CB_CDISPLAY_I2C_BUS, > + .addr = MX6CB_CDISPLAY_I2C_ADDR, > + .pixfmt = IPU_PIX_FMT_RGB24, > + .detect = detect_mx6cb_cdisplay, > + .enable = lvds_enable_disable, > + .mode = { > + .name = "VAR-WVGA MX6CB-C", > + .refresh = 60, /* optional */ > + .xres = 800, > + .yres = 480, > + .pixclock = MHZ2PS(50), > + .left_margin = 39, > + .right_margin = 39, > + .upper_margin = 29, > + .lower_margin = 13, > + .hsync_len = 128, > + .vsync_len = 2, > + .sync = FB_SYNC_EXT, > + .vmode = FB_VMODE_NONINTERLACED > +} }, { > + .bus = -1, > + .addr = 0, > + .pixfmt = IPU_PIX_FMT_RGB24, > + .detect = detect_mx6cb_rdisplay, > + .enable = lvds_enable_disable, > + .mode = { > + .name = "VAR-WVGA MX6CB-R", > + .refresh = 60, /* optional */ > + .xres = 800, > + .yres = 480, > + .pixclock = MHZ2PS(50), > + .left_margin = 0, > + .right_margin = 40, > + .upper_margin = 20, > + .lower_margin = 13, > + .hsync_len = 48, > + .vsync_len = 3, > + .sync = FB_SYNC_EXT, > + .vmode = FB_VMODE_NONINTERLACED > +} } }; > + > +size_t display_count = ARRAY_SIZE(displays); > + > +static void setup_display(void) > +{ > + struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; > + struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; > + int reg; > + > + /* Setup backlight */ > + SETUP_IOMUX_PAD(PAD_DISP0_DAT9__GPIO4_IO30 | MUX_PAD_CTRL(ENET_PAD_CTRL)); > + > + /* Turn off backlight until display is ready */ > + gpio_direction_output(VAR_SOM_BACKLIGHT_EN , 0); > + > + /* Setup HSYNC, VSYNC, DISP_CLK for debugging purposes */ > + SETUP_IOMUX_PADS(di0_pads); > + > + enable_ipu_clock(); > + imx_setup_hdmi(); > + > + /* Turn on LDB0, LDB1, IPU,IPU DI0 clocks */ > + reg = readl(&mxc_ccm->CCGR3); > + reg |= MXC_CCM_CCGR3_LDB_DI0_MASK | MXC_CCM_CCGR3_LDB_DI1_MASK; > + writel(reg, &mxc_ccm->CCGR3); > + > + /* set LDB0, LDB1 clk select to 011/011 */ > + reg = readl(&mxc_ccm->cs2cdr); > + reg &= ~(MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK > + | MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_MASK); > + /* 1 -> ~50MHz , 2 -> ~56MHz, 3 -> ~75MHz, 4 -> ~68MHz */ > + reg |= (1 << MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET) > + | (1 << MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_OFFSET); > + writel(reg, &mxc_ccm->cs2cdr); > + > + reg = readl(&mxc_ccm->cscmr2); > + reg |= MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV | MXC_CCM_CSCMR2_LDB_DI1_IPU_DIV; > + writel(reg, &mxc_ccm->cscmr2); > + > + reg = readl(&mxc_ccm->chsccdr); > + reg |= (CHSCCDR_CLK_SEL_LDB_DI0 > + << MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET); > + reg |= (CHSCCDR_CLK_SEL_LDB_DI0 > + << MXC_CCM_CHSCCDR_IPU1_DI1_CLK_SEL_OFFSET); > + writel(reg, &mxc_ccm->chsccdr); > + > + reg = IOMUXC_GPR2_BGREF_RRMODE_EXTERNAL_RES > + | IOMUXC_GPR2_DI1_VS_POLARITY_ACTIVE_LOW > + | IOMUXC_GPR2_DI0_VS_POLARITY_ACTIVE_LOW > + | IOMUXC_GPR2_BIT_MAPPING_CH1_SPWG > + | IOMUXC_GPR2_DATA_WIDTH_CH1_18BIT > + | IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG > + | IOMUXC_GPR2_DATA_WIDTH_CH0_24BIT > + | IOMUXC_GPR2_LVDS_CH0_MODE_ENABLED_DI0 > + | IOMUXC_GPR2_LVDS_CH1_MODE_ENABLED_DI0; > + writel(reg, &iomux->gpr[2]); > + > + reg = readl(&iomux->gpr[3]); > + reg = (reg & ~(IOMUXC_GPR3_LVDS1_MUX_CTL_MASK > + | IOMUXC_GPR3_HDMI_MUX_CTL_MASK)) > + | (IOMUXC_GPR3_MUX_SRC_IPU1_DI0 > + << IOMUXC_GPR3_LVDS1_MUX_CTL_OFFSET); > + writel(reg, &iomux->gpr[3]); > +} > +#endif /* CONFIG_VIDEO_IPUV3 */ > + > +/* > + * Do not overwrite the console > + * Use always serial for U-Boot console > + */ > +int overwrite_console(void) > +{ > + return 1; > +} > + > +int board_eth_init(bd_t *bis) > +{ > + uint32_t base = IMX_FEC_BASE; > + struct mii_dev *bus = NULL; > + struct phy_device *phydev = NULL; > + int ret; > + > + setup_iomux_enet(); > + > +#ifdef CONFIG_FEC_MXC > + bus = fec_get_miibus(base, -1); > + > + if (!bus) { > + printf("FEC MXC bus: %s:failed\n", __func__); > + return 0; > + } > + /* "scan" phy 7 */ > + phydev = phy_find_by_mask(bus, (0x1 << 7), << CONFIG_FEC_MXC_PHYADDR PHY_INTERFACE_MODE_RGMII); > + if (!phydev) { > + printf("FEC MXC phy find: %s:failed\n", __func__); > + free(bus); > + return 0; > + } > + printf("using phy at %d\n", phydev->addr); > + > + ret = fec_probe(bis, -1, base, bus, phydev); > + if (ret) { > + printf("FEC MXC probe: %s:failed\n", __func__); > + free(phydev); > + free(bus); > + } > +#endif > + > +#ifdef CONFIG_USB_ETHER > + /* OTG - Ethernet Gadget */ Is it not CONFIG_CI_UDC ? If it runs as gadget.. > + usb_eth_initialize(bis); > +#endif > + > + return 0; > +} > + > +#ifdef CONFIG_USB_EHCI_MX6 > +#define VSC_USB_H1_PWR_EN IMX_GPIO_NR(4, 15) > +#define VSC_USB_OTG_PWR_EN IMX_GPIO_NR(3, 22) > +#define DART_USB_H1_PWR_EN IMX_GPIO_NR(1, 28) > +#define DART_USB_OTG_PWR_EN IMX_GPIO_NR(4, 15) > + > +static void setup_usb(void) > +{ > + if (is_dart_board()) { > + /* config OTG ID iomux */ > + SETUP_IOMUX_PAD(PAD_ENET_RX_ER__USB_OTG_ID | MUX_PAD_CTRL(OTG_ID_PAD_CTRL)); > + imx_iomux_set_gpr_register(1, 13, 1, 0); > + > + SETUP_IOMUX_PAD(PAD_KEY_ROW4__GPIO4_IO15 | MUX_PAD_CTRL(NO_PAD_CTRL)); > + gpio_direction_output(DART_USB_OTG_PWR_EN, 0); > + > + SETUP_IOMUX_PAD(PAD_ENET_TX_EN__GPIO1_IO28 | MUX_PAD_CTRL(NO_PAD_CTRL)); > + gpio_direction_output(DART_USB_H1_PWR_EN, 0); > + } else if (is_solo_custom_board()) { > + /* config OTG ID iomux */ > + SETUP_IOMUX_PAD(PAD_GPIO_1__USB_OTG_ID | MUX_PAD_CTRL(OTG_ID_PAD_CTRL)); > + imx_iomux_set_gpr_register(1, 13, 1, 1); > + > + SETUP_IOMUX_PAD(PAD_EIM_D22__GPIO3_IO22 | MUX_PAD_CTRL(NO_PAD_CTRL)); > + gpio_direction_output(VSC_USB_OTG_PWR_EN, 0); > + > + SETUP_IOMUX_PAD(PAD_KEY_ROW4__GPIO4_IO15 | MUX_PAD_CTRL(NO_PAD_CTRL)); > + gpio_direction_output(VSC_USB_H1_PWR_EN, 0); You set multiple pins here, and this can be written in a much more readable way. If you see in all code (as well as you use later), there is like a template: - array with pin configuration for a function - calling iomux_setup.. to make the configuration active. This can be done as: board = is_dart_board() .....; pin_config = usb_pin_cfg[board]; /* Multiple array, one for board*/ imx_iomux_v3_setup_multiple_pads(pin_config,...) most code here is duplicated > + } > +} > + > +int board_usb_phy_mode(int port) > +{ > + char *s; > + if (is_mx6_custom_board() && port==0) { > + s = getenv("usbmode"); > + if ((s != NULL) && (!strcmp(s, "host"))) > + return USB_INIT_HOST; > + else > + return USB_INIT_DEVICE; > + } > + return usb_phy_mode(port); > +} > + > +/* > + * int board_ehci_hcd_init(int port) > + * { > + * if (is_dart_board() || is_solo_custom_board()) { > + * no hub to reset > + * } else if (is_mx6_custom_board()) { > + * hub present but pulled up > + * } > + * > + * return 0; > + * } > + */ Drop all dead code, it cannot be mainlined. > + > +int board_ehci_power(int port, int on) > +{ > + if (is_mx6_custom_board()) > + return 0; /* no power enable needed */ > + > + if (port > 1) > + return -EINVAL; > + > + if (port) { > + if (is_dart_board()) > + gpio_set_value(DART_USB_H1_PWR_EN, on); > + else if (is_solo_custom_board()) > + gpio_set_value(VSC_USB_H1_PWR_EN, on); > + } else { > + if (is_dart_board()) > + gpio_set_value(DART_USB_OTG_PWR_EN, on); > + else if (is_solo_custom_board()) > + gpio_set_value(VSC_USB_OTG_PWR_EN, on); > + } > + > + return 0; > +} > +#endif /* CONFIG_USB_EHCI_MX6 */ > + > +int board_early_init_f(void) > +{ > + var_setup_iomux_per_vcc_en(); > + > + setup_iomux_uart(); > +#if defined(CONFIG_VIDEO_IPUV3) > + setup_display(); > +#endif > +#ifdef CONFIG_SYS_I2C_MXC > + setup_local_i2c(); > +#endif > +#ifdef CONFIG_SYS_USE_NAND > + setup_gpmi_nand(); > +#endif > + > + return 0; > +} > + > +int board_init(void) > +{ > + int ret = 0; > + > + /* address of boot parameters */ > + gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100; > + gd->bd->bi_arch_number = CONFIG_MACH_VAR_SOM_MX6; Still needed ? > + > +#ifdef CONFIG_USB_EHCI_MX6 > + setup_usb(); > +#endif > + return ret; > +} > + > +static struct pmic *pfuze; > + > +static void set_anatop_bypass(void) > +{ > + struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR; > + u32 reg = readl(&anatop->reg_core); > + > + /* bypass VDDARM/VDDSOC */ > + reg |= (0x1F << 18) | 0x1F; Use constants instead of hex values - this must be fixed in all code. > + writel(reg, &anatop->reg_core); > +} > + > +static void ldo_mode_set(void) > +{ > + if (!is_som_solo()) { > + unsigned int reg; > + struct pmic *p = pfuze; > + int retval = 0; > + > + if (!p) { > + printf("No PMIC found!\n"); > + return; > + } > + > + /* Set SW1AB to 1.325V */ > + retval += pmic_reg_read(p, PFUZE100_SW1ABVOL, ®); > + reg &= ~SW1x_NORMAL_MASK; > + reg |= SW1x_1_325V; > + retval += pmic_reg_write(p, PFUZE100_SW1ABVOL, reg); > + > + /* Set SW1C to 1.325V */ > + retval += pmic_reg_read(p, PFUZE100_SW1CVOL, ®); > + reg &= ~SW1x_NORMAL_MASK; > + reg |= SW1x_1_325V; > + retval += pmic_reg_write(p, PFUZE100_SW1CVOL, reg); > + > + if (retval) { > + printf("PMIC write voltages error!\n"); > + return; > + } > + > + set_anatop_bypass(); > + printf("switch to ldo_bypass mode!\n"); > + } > +} > + > +int power_init_board(void) > +{ > + if (!is_som_solo()) { > + unsigned int reg; > + int retval; > + > + retval = power_pfuze100_init(PMIC_I2C_BUS); > + if (retval) > + return -ENODEV; > + pfuze = pmic_get("PFUZE100"); > + retval = pmic_probe(pfuze); > + if (retval) > + return -ENODEV; > + pmic_reg_read(pfuze, PFUZE100_DEVICEID, ®); > + printf("PMIC: PFUZE100 ID=0x%02x\n", reg); > + > + if (!is_dart_board()) { > + > + /* Set Gigbit Ethernet voltage (SOM v1.1/1.0) */ > + retval += pmic_reg_read(pfuze, PFUZE100_SW4VOL, ®); > + reg &= ~0x7f; > + reg |= 0x60; /* 2.4V */ > + retval += pmic_reg_write(pfuze, PFUZE100_SW4VOL, reg); > + > + /* Increase VGEN5 from 2.8 to 3V */ > + retval += pmic_reg_read(pfuze, PFUZE100_VGEN5VOL, ®); > + reg &= ~LDO_VOL_MASK; > + reg |= LDOB_3_00V; > + retval += pmic_reg_write(pfuze, PFUZE100_VGEN5VOL, reg); > + > + /* Set SW1AB standby volage to 0.975V */ > + retval += pmic_reg_read(pfuze, PFUZE100_SW1ABSTBY, ®); > + reg &= ~SW1x_STBY_MASK; > + reg |= SW1x_0_975V; > + retval += pmic_reg_write(pfuze, PFUZE100_SW1ABSTBY, reg); > + > + /* Set SW1AB/VDDARM step ramp up time from 16us to 4us/25mV */ > + retval += pmic_reg_read(pfuze, PFUZE100_SW1ABCONF, ®); > + reg &= ~SW1xCONF_DVSSPEED_MASK; > + reg |= SW1xCONF_DVSSPEED_4US; > + retval += pmic_reg_write(pfuze, PFUZE100_SW1ABCONF, reg); > + > + /* Set SW1C standby voltage to 0.975V */ > + retval += pmic_reg_read(pfuze, PFUZE100_SW1CSTBY, ®); > + reg &= ~SW1x_STBY_MASK; > + reg |= SW1x_0_975V; > + retval += pmic_reg_write(pfuze, PFUZE100_SW1CSTBY, reg); > + > +#ifdef LOW_POWER_MODE_ENABLE > + /* Set low power mode voltages to disable */ > + > + /* Set SW3A standby voltage to 1.275V */ > + retval += pmic_reg_read(pfuze, PFUZE100_SW3ASTBY, ®); > + reg &= ~0x7f; /* SW3x STBY MASK */ > + reg = 0x23; /* SW3x 1.275V */ > + retval += pmic_reg_write(pfuze, PFUZE100_SW3ASTBY, reg); > + > + /* Set SW3A off voltage to 1.275V */ > + retval += pmic_reg_read(pfuze, PFUZE100_SW3AOFF, ®); > + reg &= ~0x7f; /* SW3x OFF MASK */ > + reg = 0x23; /* SW3x 1.275V */ > + retval += pmic_reg_write(pfuze, PFUZE100_SW3AOFF, reg); > + > + /* Set SW2 to 3.2V */ > + retval += pmic_reg_read(pfuze, PFUZE100_SW2VOL, ®); > + reg &= ~0x7f; > + reg |= 0x70; /* SW2x 3.2V */ > + retval += pmic_reg_write(pfuze, PFUZE100_SW2VOL, reg); > + > + /* SW4MODE = OFF in standby */ > + reg = PWM_OFF; > + retval += pmic_reg_write(pfuze, PFUZE100_SW4MODE, reg); > + > + /* Set VGEN3 to 2.5V, VGEN3CTL = OFF in standby */ > + retval += pmic_reg_read(pfuze, PFUZE100_VGEN3VOL, ®); > + reg &= ~0x7f; > + reg |= 0x30; /* VGEN3EN, VGEN3STBY, ~VGEN3LPWR */ > + reg |= LDOB_2_50V; > + retval += pmic_reg_write(pfuze, PFUZE100_VGEN3VOL, reg); > +#else > + /* Set VGEN3 to 2.5V, VGEN3CTL = low power in standby */ > + retval += pmic_reg_read(pfuze, PFUZE100_VGEN3VOL, ®); > + reg &= ~0x7f; > + reg |= 0x70; /* VGEN3EN, VGEN3STBY, VGEN3LPWR */ > + reg |= LDOB_2_50V; > + retval += pmic_reg_write(pfuze, PFUZE100_VGEN3VOL, reg); > +#endif > + } else { > + > + /* Set SW1AB standby volage to 0.9V */ > + retval += pmic_reg_read(pfuze, PFUZE100_SW1ABSTBY, ®); > + reg &= ~SW1x_STBY_MASK; > + reg |= SW1x_0_900V; > + retval += pmic_reg_write(pfuze, PFUZE100_SW1ABSTBY, reg); > + > + /* Set SW1AB off volage to 0.9V */ > + retval += pmic_reg_read(pfuze, PFUZE100_SW1ABOFF, ®); > + reg &= ~SW1x_OFF_MASK; > + reg |= SW1x_0_900V; > + retval += pmic_reg_write(pfuze, PFUZE100_SW1ABOFF, reg); > + > + /* Set SW1C standby voltage to 0.9V */ > + retval += pmic_reg_read(pfuze, PFUZE100_SW1CSTBY, ®); > + reg &= ~SW1x_STBY_MASK; > + reg |= SW1x_0_900V; > + retval += pmic_reg_write(pfuze, PFUZE100_SW1CSTBY, reg); > + > + /* Set SW1C off volage to 0.9V */ > + retval += pmic_reg_read(pfuze, PFUZE100_SW1COFF, ®); > + reg &= ~SW1x_OFF_MASK; > + reg |= SW1x_0_900V; > + retval += pmic_reg_write(pfuze, PFUZE100_SW1COFF, reg); > + > + /* Set SW2 to 3.3V */ > + retval += pmic_reg_read(pfuze, PFUZE100_SW2VOL, ®); > + reg &= ~0x7f; /* SW2x NORMAL MASK */ > + reg |= 0x72; /* SW2x 3.3V */ > + retval += pmic_reg_write(pfuze, PFUZE100_SW2VOL, reg); > + > + /* Set SW2 standby voltage to 3.2V */ > + retval += pmic_reg_read(pfuze, PFUZE100_SW2STBY, ®); > + reg &= ~0x7f; /* SW2x STBY MASK */ > + reg |= 0x70; /* SW2x 3.2V */ > + retval += pmic_reg_write(pfuze, PFUZE100_SW2STBY, reg); > + > + /* Set SW2 off voltage to 3.2V */ > + retval += pmic_reg_read(pfuze, PFUZE100_SW2OFF, ®); > + reg &= ~0x7f; /* SW2x OFF MASK */ > + reg |= 0x70; /* SW2x 3.2V */ > + retval += pmic_reg_write(pfuze, PFUZE100_SW2OFF, reg); > + > + reg = PWM_PFM; > + retval += pmic_reg_write(pfuze, PFUZE100_SW1ABMODE, reg); > + > + /* Set SW1AB/VDDARM step ramp up time 2us */ > + retval += pmic_reg_read(pfuze, PFUZE100_SW1ABCONF, ®); > + reg &= ~SW1xCONF_DVSSPEED_MASK; > + reg |= SW1xCONF_DVSSPEED_2US; > + retval += pmic_reg_write(pfuze, PFUZE100_SW1ABCONF, reg); > + > + reg = PWM_PFM; > + retval += pmic_reg_write(pfuze, PFUZE100_SW1CMODE, reg); > + > + reg = PWM_PFM; > + retval += pmic_reg_write(pfuze, PFUZE100_SW2MODE, reg); > + > + reg = LDOB_3_30V; > + retval += pmic_reg_write(pfuze, PFUZE100_VGEN6VOL, reg); > + } > + You have to factoritze the common code and handle in case just the differences, instead of copying the all code twice. > + /* Set SW1C/VDDSOC step ramp up time from 16us to 4us/25mV */ > + retval += pmic_reg_read(pfuze, PFUZE100_SW1CCONF, ®); > + reg &= ~SW1xCONF_DVSSPEED_MASK; > + reg |= SW1xCONF_DVSSPEED_4US; > + retval += pmic_reg_write(pfuze, PFUZE100_SW1CCONF, reg); > + > + if (retval) { > + printf("PMIC write voltages error!\n"); > + return -1; > + } > + > + ldo_mode_set(); > + } > + > + return 0; > +} > + > +static void update_env(void) > +{ > + setenv("mmcroot" , "/dev/mmcblk0p2 rootwait rw"); > + if (is_cpu_type(MXC_CPU_MX6Q)) { > + if (is_dart_board()) { > + setenv("fdt_file", "imx6q-var-dart.dtb"); > + if (MMC_BOOT == get_mmc_boot_device()) > + setenv("mmcroot" , "/dev/mmcblk2p2 rootwait rw"); > + else > + setenv("mmcroot" , "/dev/mmcblk1p2 rootwait rw"); > + } else { > + if (is_solo_custom_board()) > + setenv("fdt_file", "imx6q-var-som-vsc.dtb"); > + else > + setenv("fdt_file", "imx6q-var-som.dtb"); > + } > + } else if (is_cpu_type(MXC_CPU_MX6D)) { > + if (is_dart_board()) { > + setenv("fdt_file", "imx6q-var-dart.dtb"); > + if (MMC_BOOT == get_mmc_boot_device()) > + setenv("mmcroot" , "/dev/mmcblk2p2 rootwait rw"); > + else > + setenv("mmcroot" , "/dev/mmcblk1p2 rootwait rw"); > + } else { > + setenv("fdt_file", "imx6q-var-som.dtb"); > + } > + } else if (is_cpu_type(MXC_CPU_MX6DL)) { > + if (is_som_solo()) { > + if (is_solo_custom_board()) > + setenv("fdt_file", "imx6dl-var-som-solo-vsc.dtb"); > + else > + setenv("fdt_file", "imx6dl-var-som-solo.dtb"); > + } else { > + setenv("fdt_file", "imx6dl-var-som.dtb"); > + } > + } else if (is_cpu_type(MXC_CPU_MX6SOLO)) { > + if (is_som_solo()) { > + if (is_solo_custom_board()) > + setenv("fdt_file", "imx6dl-var-som-solo-vsc.dtb"); > + else > + setenv("fdt_file", "imx6dl-var-som-solo.dtb"); > + } else { > + setenv("fdt_file", "imx6dl-var-som.dtb"); > + } > + } > +} > + This function is against the way U-Boot handle this, and it will be rejected - take a look at the script capabilities in U-Boot, it seems you do not like them at all ! > +static void imx6_pcie_assert_core_reset(void) > +{ > + struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR; > + > + if (is_mx6dqp()) > + setbits_le32(&iomuxc_regs->gpr[1], IOMUXC_GPR1_PCIE_SW_RST); > + > + setbits_le32(&iomuxc_regs->gpr[1], IOMUXC_GPR1_TEST_POWERDOWN); > + clrbits_le32(&iomuxc_regs->gpr[1], IOMUXC_GPR1_REF_SSP_EN); > +} > + > +static void imx6_pcie_init_phy(void) > +{ > + struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR; > + > + clrbits_le32(&iomuxc_regs->gpr[12], IOMUXC_GPR12_APPS_LTSSM_ENABLE); > + > + clrsetbits_le32(&iomuxc_regs->gpr[12], > + IOMUXC_GPR12_DEVICE_TYPE_MASK, > + IOMUXC_GPR12_DEVICE_TYPE_RC); > + clrsetbits_le32(&iomuxc_regs->gpr[12], > + IOMUXC_GPR12_LOS_LEVEL_MASK, > + IOMUXC_GPR12_LOS_LEVEL_9); > + > + writel((0x0 << IOMUXC_GPR8_PCS_TX_DEEMPH_GEN1_OFFSET) | > + (0x0 << IOMUXC_GPR8_PCS_TX_DEEMPH_GEN2_3P5DB_OFFSET) | > + (20 << IOMUXC_GPR8_PCS_TX_DEEMPH_GEN2_6DB_OFFSET) | > + (127 << IOMUXC_GPR8_PCS_TX_SWING_FULL_OFFSET) | > + (127 << IOMUXC_GPR8_PCS_TX_SWING_LOW_OFFSET), > + &iomuxc_regs->gpr[8]); > +} > + > +static void imx6_pcie_deassert_core_reset(void) > +{ > + struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR; > + > + if (is_mx6dqp()) > + clrbits_le32(&iomuxc_regs->gpr[1], IOMUXC_GPR1_PCIE_SW_RST); > + > + /* > + * Wait for the clock to settle a bit, when the clock are sourced > + * from the CPU, we need about 30 ms to settle. > + */ > + mdelay(50); > + > + /* Enable PCIe */ > + clrbits_le32(&iomuxc_regs->gpr[1], IOMUXC_GPR1_TEST_POWERDOWN); > + setbits_le32(&iomuxc_regs->gpr[1], IOMUXC_GPR1_REF_SSP_EN); > +} > + > +/* > + * Resets the PCIe controller in order to prevent a soft reboot hang > + */ > +static void imx_pcie_reset(void) > +{ > + imx6_pcie_assert_core_reset(); > + imx6_pcie_init_phy(); > + imx6_pcie_deassert_core_reset(); > +} > + > +int board_late_init(void) > +{ > + char *s; > + > + print_emmc_size(); > + > + s = getenv("var_auto_env"); > + if (s[0] == 'Y') > + update_env(); > + > + imx_pcie_reset(); > + > + return 0; > +} > + > +int checkboard(void) > +{ > + puts("Board: Variscite VAR-SOM-MX6 "); > + > + if (is_cpu_type(MXC_CPU_MX6Q)) { > + puts("Quad"); > + if (is_cpu_pop_package()) > + puts("-POP"); > + > + } else if (is_cpu_type(MXC_CPU_MX6D)) { > + puts("Dual"); > + if (is_cpu_pop_package()) > + puts("-POP"); > + > + } else if (is_cpu_type(MXC_CPU_MX6DL)) { > + if (is_som_solo()) > + puts("SOM-Dual"); > + else > + puts("Dual Lite"); > + > + } else if (is_cpu_type(MXC_CPU_MX6SOLO)) { > + if (is_som_solo()) > + puts("SOM-Solo"); > + else > + puts("Solo"); > + } else > + puts("????"); > + > + puts("\n"); > + return 0; > +} > + > +#ifdef CONFIG_SPL_BUILD > +#include <spl.h> > +#include <libfdt.h> > +#include <asm/arch/mx6-ddr.h> > +#include "mx6var_eeprom.h" > +#include "mx6var_eeprom_v2.h" > + > +/* > + * Writes RAM size to RAM_SIZE_ADDR so U-Boot can read it > + */ > +static void var_set_ram_size(u32 ram_size) > +{ > + u32 *p_ram_size = (u32 *)RAM_SIZE_ADDR; > + if (ram_size > 3840) > + ram_size=3840; > + *p_ram_size = ram_size; > +} > + > +static void print_board_info(int eeprom_rev, void* var_eeprom, u32 ram_size) > +{ > + u32 boot_device; > + u32 max_freq; > + > + printf("\ni.MX%s SOC P-%s\n", get_imx_type(get_cpu_type()), \ > + is_cpu_pop_package() ? "POP" : "STD"); > + > + max_freq = get_cpu_speed_grade_hz(); > + if (!max_freq) > + printf("CPU running at %dMHz\n", mxc_get_clock(MXC_ARM_CLK) / 1000000); > + else > + printf("%d MHz CPU (running at %d MHz)\n", max_freq / 1000000, > + mxc_get_clock(MXC_ARM_CLK) / 1000000); > + > + if (eeprom_rev==1) > + var_eeprom_strings_print((struct var_eeprom_cfg *) var_eeprom); > + else if (eeprom_rev==2) > + var_eeprom_v2_strings_print((struct var_eeprom_v2_cfg *) var_eeprom); > + else > + return; > + > + printf("RAM: "); > + print_size(ram_size * 1024 * 1024, "\n"); > + > + printf("Boot Device: "); > + boot_device = spl_boot_device(); > + switch (boot_device) { > + case BOOT_DEVICE_MMC1: > + switch (get_mmc_boot_device()) { > + case SD_BOOT: > + printf("MMC0 (SD)\n"); > + break; > + case MMC_BOOT: > + printf("MMC1 (DART eMMC)\n"); > + break; > + default: > + printf("MMC?\n"); > + break; > + } > + break; > + > + case BOOT_DEVICE_NAND: > + printf("NAND\n"); > + break; > + > + default: > + printf("UNKNOWN (%d)\n", boot_device); > + break; > + } > +} > + > +static int spl_dram_init_by_eeprom(void) > +{ > + struct var_eeprom_cfg var_eeprom_cfg = {{0}}; > + int ret; > + > + ret = var_eeprom_read_struct(&var_eeprom_cfg); > + if (ret) > + return SPL_DRAM_INIT_STATUS_ERROR_NO_EEPROM; > + > + /* is valid Variscite EEPROM? */ > + if (!var_eeprom_is_valid(&var_eeprom_cfg)) > + return SPL_DRAM_INIT_STATUS_ERROR_NO_EEPROM_STRUCT_DETECTED; > + > + switch (get_cpu_type()) { > + case MXC_CPU_MX6DL: > + case MXC_CPU_MX6SOLO: > + var_eeprom_mx6dlsl_dram_setup_iomux_from_struct(&var_eeprom_cfg.pinmux_group); > + break; > + case MXC_CPU_MX6Q: > + case MXC_CPU_MX6D: > + default: > + var_eeprom_mx6qd_dram_setup_iomux_from_struct(&var_eeprom_cfg.pinmux_group); > + break; > + } > + > + var_eeprom_dram_init_from_struct(&var_eeprom_cfg); > + > + var_set_ram_size(var_eeprom_cfg.header.ddr_size); > + print_board_info(1, (void*) &var_eeprom_cfg, var_eeprom_cfg.header.ddr_size); > + > + return SPL_DRAM_INIT_STATUS_OK; > +} > + > +/* > + * Bugfix: Fix Freescale wrong processor documentation. > + */ > +static void spl_mx6qd_dram_setup_iomux_check_reset(void) > +{ > + volatile struct mx6dq_iomux_ddr_regs *mx6q_ddr_iomux; > + u32 cputype = get_cpu_type(); > + > + if ((cputype == MXC_CPU_MX6D) || (cputype == MXC_CPU_MX6Q)) { > + mx6q_ddr_iomux = (struct mx6dq_iomux_ddr_regs *) MX6DQ_IOM_DDR_BASE; > + > + if (mx6q_ddr_iomux->dram_reset == (u32)0x000C0030) > + mx6q_ddr_iomux->dram_reset = (u32)0x00000030; > + } > +} > + > +static void ccgr_init(void) > +{ > + struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; > + > + writel(0x00C03F3F, &ccm->CCGR0); > + writel(0x0030FC03, &ccm->CCGR1); > + writel(0x0FFFC000, &ccm->CCGR2); > + writel(0x3FF00000, &ccm->CCGR3); > + writel(0x00FFF300, &ccm->CCGR4); > + writel(0x0F0000C3, &ccm->CCGR5); > + writel(0x000003FF, &ccm->CCGR6); > +} > + > +static void gpr_init(void) > +{ > + struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; > + > + /* enable AXI cache for VDOA/VPU/IPU */ > + writel(0xF00000CF, &iomux->gpr[4]); > + /* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */ > + writel(0x007F007F, &iomux->gpr[6]); > + writel(0x007F007F, &iomux->gpr[7]); > +} > + > +static int spl_dram_init_by_eeprom_v2(void) > +{ > + u32 ram_addresses[MAXIMUM_RAM_ADDRESSES]; > + u32 ram_values[MAXIMUM_RAM_VALUES]; > + struct var_eeprom_v2_cfg var_eeprom_v2_cfg = {0}; > + int ret, ram_size; > + > + ret = var_eeprom_v2_read_struct(&var_eeprom_v2_cfg, \ > + is_dart_board() ? VAR_DART_EEPROM_CHIP : VAR_MX6_EEPROM_CHIP); > + > + if (ret) > + return SPL_DRAM_INIT_STATUS_ERROR_NO_EEPROM; > + > + if (!var_eeprom_v2_is_valid(&var_eeprom_v2_cfg)) > + return SPL_DRAM_INIT_STATUS_ERROR_NO_EEPROM_STRUCT_DETECTED; > + > + handle_eeprom_data(&var_eeprom_v2_cfg, ram_addresses, ram_values); > + > + ram_size = var_eeprom_v2_cfg.ddr_size * 128; > + var_set_ram_size(ram_size); > + print_board_info(2, (void*) &var_eeprom_v2_cfg, ram_size); > + return SPL_DRAM_INIT_STATUS_OK; > +} > + > +static void spl_dram_init(void) > +{ > + int status; > + > + status = spl_dram_init_by_eeprom(); > + if (status != SPL_DRAM_INIT_STATUS_OK) { > + status = spl_dram_init_by_eeprom_v2(); > + if (status != SPL_DRAM_INIT_STATUS_OK) { > + printf("Error initializing RAM using EEPROM\n"); > + hang(); > + } > + } > + spl_mx6qd_dram_setup_iomux_check_reset(); > +} > + > +void board_init_f(ulong dummy) > +{ > + /* setup AIPS and disable watchdog */ > + arch_cpu_init(); > + > + ccgr_init(); > + gpr_init(); > + > + /* iomux and setup of i2c */ > + board_early_init_f(); > + > + /* setup GP timer */ > + timer_init(); > + > + /* Wait 330ms before starting to print to console */ > + mdelay(330); > + > + /* UART clocks enabled and gd valid - init serial console */ > + preloader_console_init(); > + > + /* DDR initialization */ > + spl_dram_init(); > + > + /* Clear the BSS. */ > + memset(__bss_start, 0, __bss_end - __bss_start); > + > + /* load/boot image from boot device */ > + board_init_r(NULL, 0); > +} > +#endif > diff --git a/board/variscite/mx6var_som/u-boot-spl.lds b/board/variscite/mx6var_som/u-boot-spl.lds > new file mode 100644 > index 0000000..33d8406 > --- /dev/null > +++ b/board/variscite/mx6var_som/u-boot-spl.lds > @@ -0,0 +1,59 @@ > +/* > + * (C) Copyright 2002 > + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> > + * > + * (C) Copyright 2010 > + * Texas Instruments, <www.ti.com> > + * Aneesh V <aneesh@ti.com> > + * > + * Copyright (C) 2016 Variscite Ltd. All Rights Reserved. > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE,\ > + LENGTH = CONFIG_SPL_MAX_SIZE } > +MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \ > + LENGTH = CONFIG_SPL_BSS_MAX_SIZE } > + > +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") > +OUTPUT_ARCH(arm) > +ENTRY(_start) > +SECTIONS > +{ > + .text : > + { > + __start = .; > + *(.vectors) > + arch/arm/cpu/armv7/start.o (.text*) > + *(.text*) > + } >.sram > + > + . = ALIGN(4); > + .rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.sram > + > + . = ALIGN(4); > + .data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram > + > + . = ALIGN(4); > + .u_boot_list : { > + KEEP(*(SORT(.u_boot_list*_i2c_*))); > + } >.sram > + > + . = ALIGN(4); > + __image_copy_end = .; > + > + .end : > + { > + *(.__end) > + } > + > + .bss : > + { > + . = ALIGN(4); > + __bss_start = .; > + *(.bss*) > + . = ALIGN(4); > + __bss_end = .; > + } >.sram > +} Any reason for that ? There is a global .lds file, and you should use it. > diff --git a/board/variscite/mx6var_som/values.inc b/board/variscite/mx6var_som/values.inc > new file mode 100644 > index 0000000..aafc088 > --- /dev/null > +++ b/board/variscite/mx6var_som/values.inc > @@ -0,0 +1,39 @@ > +0x00000000,0x00000010,0x00000013,0x00000017, > +0x00000027,0x00000028,0x00000030,0x00000038, > +0x00000047,0x00000053,0x00000080,0x000000DD, > +0x0000020E,0x00000800,0x00001740,0x0000174C, > +0x00001800,0x000026D2,0x00003000,0x00003030, > +0x00005800,0x00007800,0x00008000,0x00008033, > +0x0000803B,0x00011006,0x00011117,0x00011740, > +0x00020000,0x00020025,0x0002002D,0x00020036, > +0x00022227,0x00025565,0x0002556D,0x00025576, > +0x00048031,0x00048039,0x00080000,0x00081740, > +0x000C0000,0x000C0030,0x00130029,0x00160E83, > +0x0019002E,0x001C0019,0x001D002C,0x001F0019, > +0x001F001F,0x001F002B,0x00220AAC,0x0024001F, > +0x00260026,0x00333030,0x00333040,0x003F1023, > +0x003F8030,0x003F8038,0x00400000,0x00431023, > +0x00450000,0x005A1023,0x006B1023,0x008E1023, > +0x008F1023,0x017B017A,0x01FF00DB,0x02008032, > +0x0200803A,0x02038030,0x02088032,0x0208803A, > +0x0214021C,0x021B08B8,0x02280228,0x02300238, > +0x02580258,0x03038038,0x03200314,0x032C0278, > +0x033C0350,0x04008032,0x0400803A,0x04008040, > +0x04008048,0x04088032,0x0408803A,0x05208030, > +0x05208038,0x052C0470,0x052C0520,0x06028030, > +0x06028038,0x07208030,0x09408030,0x09444040, > +0x0F9F26D2,0x11420000,0x15208030,0x15208038, > +0x19408030,0x19408038,0x1B5F01FF,0x20000000, > +0x24911492,0x24921492,0x2B35382B,0x3234342C, > +0x33333333,0x38362E32,0x38363236,0x38383E3A, > +0x3A363446,0x3A38443C,0x3A3F7975,0x3E363A40, > +0x3E373A3C,0x3E463E40,0x3F435313,0x4036363A, > +0x403C3246,0x40404040,0x421C0216,0x421C0228, > +0x423D3843,0x42440244,0x43240334,0x432C0340, > +0x4528053C,0x45300544,0x454A61A5,0x46344840, > +0x48364A3E,0x484A4C4A,0x4B2B4842,0x4B4A4E4C, > +0x555A7974,0x676B5313,0x821A0000,0x83110000, > +0x831A0000,0x84190000,0x841A0000,0x8A8F7955, > +0xA1390003,0xB66D8B63,0xB66E8B63,0xC2018030, > +0xC2018038,0xC41A0000,0xDB538F64,0xF3333333, > +0xFF0A8030,0xFF0A8038,0xFF328F64,0xFFFFFFFF I do not like this way for generating a DCD-like table. > diff --git a/configs/mx6var_som_nand_defconfig b/configs/mx6var_som_nand_defconfig > new file mode 100644 > index 0000000..59c3747 > --- /dev/null > +++ b/configs/mx6var_som_nand_defconfig > @@ -0,0 +1,7 @@ > +CONFIG_ARM=y > +CONFIG_ARCH_MX6=y > +CONFIG_TARGET_MX6VAR_SOM=y > +CONFIG_SPL=y > +CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/variscite/mx6var_som/imximage.cfg,SPL,MX6QDL,SYS_BOOT_NAND" > +# CONFIG_CMD_IMLS is not set > +# CONFIG_CMD_FLASH is not set > diff --git a/configs/mx6var_som_sd_defconfig b/configs/mx6var_som_sd_defconfig > new file mode 100644 > index 0000000..875234e > --- /dev/null > +++ b/configs/mx6var_som_sd_defconfig > @@ -0,0 +1,7 @@ > +CONFIG_ARM=y > +CONFIG_ARCH_MX6=y > +CONFIG_TARGET_MX6VAR_SOM=y > +CONFIG_SPL=y > +CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/variscite/mx6var_som/imximage.cfg,SPL,MX6QDL" > +# CONFIG_CMD_IMLS is not set > +# CONFIG_CMD_FLASH is not set > diff --git a/include/configs/mx6var_som.h b/include/configs/mx6var_som.h > new file mode 100644 > index 0000000..6771a2d > --- /dev/null > +++ b/include/configs/mx6var_som.h > @@ -0,0 +1,419 @@ > +/* > + * Copyright (C) 2012 Freescale Semiconductor, Inc. > + * Copyright (C) 2016 Variscite Ltd. All Rights Reserved. > + * > + * Author: Eran Matityahu <eran.m@variscite.com> > + * > + * Configuration settings for the Variscite VAR-SOM-MX6 board. > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#ifndef __MX6VAR_SOM_CONFIG_H > +#define __MX6VAR_SOM_CONFIG_H > + > +#ifdef CONFIG_SPL > +#define CONFIG_SPL_LIBCOMMON_SUPPORT > +#ifdef CONFIG_SYS_BOOT_NAND > +#define CONFIG_SPL_NAND_SUPPORT > +#else > +#define CONFIG_SPL_MMC_SUPPORT > +#endif > +#include "mx6var_spl.h" > +#endif > +#include "mx6_common.h" > + > +/* Address of reserved 4Bytes in OCRAM for sending RAM size from SPL to U-Boot */ > +#define RAM_SIZE_ADDR ((CONFIG_SPL_TEXT_BASE) + (CONFIG_SPL_MAX_SIZE)) > + > +#define CONFIG_MACH_VAR_SOM_MX6 4419 > +#define CONFIG_MACH_TYPE CONFIG_MACH_VAR_SOM_MX6 > + > +#define CONFIG_MXC_UART_BASE UART1_BASE > +#define CONFIG_CONSOLE_DEV "ttymxc0" > +#define CONFIG_MMCROOT "/dev/mmcblk0p2" > + > +#define CONFIG_IMX_THERMAL > + > +/* Size of malloc() pool */ > +#define CONFIG_SYS_MALLOC_LEN (10 * SZ_1M) > + > +#define CONFIG_BOARD_EARLY_INIT_F > +#define CONFIG_BOARD_LATE_INIT > + > +#define CONFIG_CMD_GPIO > + > +#define CONFIG_MXC_UART > + > +#define LOW_POWER_MODE_ENABLE > + > +/* MMC Configs */ > +#define CONFIG_SYS_FSL_ESDHC_ADDR 0 > +#define CONFIG_SYS_FSL_USDHC_NUM 2 > +#define CONFIG_SYS_MMC_ENV_DEV 0 > +#define CONFIG_SYS_MMC_ENV_PART 0 > +#define CONFIG_SYS_MMC_IMG_LOAD_PART 1 > + > +#define CONFIG_CMD_PING > +#define CONFIG_CMD_DHCP > +#define CONFIG_CMD_MII > +#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 7 > + > +#define CONFIG_PHYLIB > +#define CONFIG_PHY_MICREL > +#define CONFIG_PHY_MICREL_KSZ9021 > + > +#ifdef CONFIG_BOOTDELAY > +#undef CONFIG_BOOTDELAY > +#endif > +#define CONFIG_BOOTDELAY 1 > + > +#ifdef CONFIG_SYS_BOOT_NAND > +#define MFG_NAND_PARTITION "mtdparts=gpmi-nand:16m(boot),16m(kernel),16m(dtb),-(rootfs) " > +#else > +#define MFG_NAND_PARTITION "" > +#endif > + > +#ifdef CONFIG_SYS_BOOT_NAND > +#define MMC_DEV_SET " " > +#else > +#define MMC_DEV_SET "mmcdev=" __stringify(CONFIG_SYS_MMC_ENV_DEV) > +#endif > + > +#define MFG_ENV_SETTINGS \ > + "mfgtool_args=setenv bootargs console=${console},${baudrate} " \ > + "rdinit=/linuxrc " \ > + "g_mass_storage.stall=0 g_mass_storage.removable=1 " \ > + "g_mass_storage.idVendor=0x066F g_mass_storage.idProduct=0x37FF "\ > + "g_mass_storage.iSerialNumber=\"\" "\ > + "enable_wait_mode=off "\ > + MFG_NAND_PARTITION \ > + "\0" \ > + "initrd_addr=0x12C00000\0" \ > + "initrd_high=0xffffffff\0" \ > + "bootcmd_mfg=run mfgtool_args;bootm ${loadaddr} ${initrd_addr} ${fdt_addr};\0" \ > + > + > +#define MMC_BOOT_ENV_SETTINGS \ > + "uimage=uImage\0" \ > + "fdt_file=" CONFIG_DEFAULT_FDT_FILE "\0" \ > + "boot_fdt=try\0" \ > + "ip_dyn=yes\0" \ > + MMC_DEV_SET \ > + "\0" \ > + "mmcpart=" __stringify(CONFIG_SYS_MMC_IMG_LOAD_PART) "\0" \ > + "mmcroot=" CONFIG_MMCROOT " rootwait rw\0" \ > + "mmcargs=setenv bootargs console=${console},${baudrate} root=${mmcroot}; " \ > + "run videoargs\0" \ > + "loadbootscript=" \ > + "fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};\0" \ > + "bootscript=echo Running bootscript from mmc ...; " \ > + "source\0" \ > + "loaduimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${uimage}\0" \ > + "loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${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" \ > + > + > +#define NAND_BOOT_ENV_SETTINGS \ > + "bootargs_ubifs=setenv bootargs console=${console},${baudrate} ubi.mtd=3 " \ > + "root=ubi0:rootfs rootfstype=ubifs; " \ > + "run videoargs\0" \ > + "bootargs_emmc=setenv bootargs console=${console},${baudrate} " \ > + "root=/dev/mmcblk1p1 rootwait rw; " \ > + "run videoargs\0" \ > + "bootcmd=" \ > + "if test ${chosen_rootfs} != emmc; then " \ > + "run bootargs_ubifs; " \ > + "else " \ > + "run bootargs_emmc; " \ > + "fi; " \ > + "nand read ${loadaddr} 0x400000 0x600000;" \ > + "nand read ${fdt_addr} 0x3e0000 0x20000;" \ > + "bootm ${loadaddr} - ${fdt_addr}\0" \ > + "mtdids=" MTDIDS_DEFAULT "\0" \ > + "mtdparts=" MTDPARTS_DEFAULT "\0" \ > + > + > +#ifdef CONFIG_SYS_BOOT_NAND > +#define BOOT_ENV_SETTINGS NAND_BOOT_ENV_SETTINGS > +#else > +#define BOOT_ENV_SETTINGS MMC_BOOT_ENV_SETTINGS > +#define CONFIG_BOOTCOMMAND \ > + "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" > +#endif > + > + > +#define CONFIG_EXTRA_ENV_SETTINGS \ > + MFG_ENV_SETTINGS \ > + BOOT_ENV_SETTINGS \ > + "var_auto_env=Y\0" \ > + "fdt_addr=0x18000000\0" \ > + "fdt_high=0xffffffff\0" \ > + "splash_filename=/boot/splash.bmp\0" \ > + "splashimage=0x18100000\0" \ > + "enable_splash=setenv splash_filename /boot/splash.bmp; " \ > + "setenv splashimage 0x18100000\0" \ > + "disable_splash=setenv splash_filename; setenv splashimage\0" \ > + "console=" CONFIG_CONSOLE_DEV "\0" \ > + "netargs=setenv bootargs console=${console},${baudrate} " \ > + "root=/dev/nfs rw " \ > + "ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp; " \ > + "run videoargs\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" \ > + "videoargs=" \ > + "if hdmidet; then " \ > + "setenv bootargs ${bootargs} " \ > + "video=mxcfb0:dev=hdmi,1920x1080M@60,if=RGB24; " \ > + "fi; " \ > + "setenv bootargs ${bootargs} " \ > + "video=mxcfb1:off; " \ > + "i2c dev 2; " \ > + "if i2c probe 0x38; then " \ > + "setenv bootargs ${bootargs} " \ > + "screen_alternate=yes;" \ > + "fi;\0" > + > + You could even think about to use the "distro" environment. > +#define CONFIG_ARP_TIMEOUT 200UL > + > +#undef CONFIG_SYS_PROMPT > +#ifdef CONFIG_SYS_BOOT_NAND > +#define CONFIG_SYS_PROMPT "VAR-SOM-MX6 (NAND) => " > +#else > +#define CONFIG_SYS_PROMPT "VAR-SOM-MX6 (MMC) => " > +#endif We mostly decide to not use a custom prompt for the board - see commit to remove them, letting the same prompt for all boards. > + > +#define CONFIG_SYS_MEMTEST_START 0x10000000 > +#define CONFIG_SYS_MEMTEST_END 0x10010000 > +#define CONFIG_SYS_MEMTEST_SCRATCH 0x10800000 > + > +#define CONFIG_STACKSIZE (128 * 1024) > + > +/* Physical Memory Map */ > +#define CONFIG_NR_DRAM_BANKS 1 > +#define PHYS_SDRAM MMDC0_ARB_BASE_ADDR > + > +#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_ENV_SIZE (8 * 1024) > + > +#ifdef CONFIG_SYS_BOOT_NAND > +#define CONFIG_SYS_USE_NAND > +#define CONFIG_ENV_IS_IN_NAND > +/* NAND boot config */ > +#define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE > +#define CONFIG_SYS_NAND_U_BOOT_OFFS 0x200000 > +#define CONFIG_SYS_NAND_PAGE_SIZE 2048 > +#else > +#define CONFIG_ENV_IS_IN_MMC > +#endif > + > +#if defined(CONFIG_MX6DL) > +#define CONFIG_DEFAULT_FDT_FILE "imx6dl-var-som.dtb" > +#elif defined(CONFIG_MX6S) > +#define CONFIG_DEFAULT_FDT_FILE "imx6dl-var-som.dtb" > +#elif defined(CONFIG_MX6Q) > +#define CONFIG_DEFAULT_FDT_FILE "imx6q-var-som.dtb" > +#else > +#define CONFIG_DEFAULT_FDT_FILE "imx6q-var-som.dtb" > +#endif > + > +#ifdef CONFIG_SYS_USE_NAND > +#define CONFIG_CMD_NAND > +#define CONFIG_CMD_NAND_TRIMFFS > + > +/* UBI/UBIFS support */ > +#define CONFIG_CMD_UBI > +#define CONFIG_CMD_UBIFS > +#define CONFIG_RBTREE > +#define CONFIG_MTD_DEVICE > +#define CONFIG_MTD_PARTITIONS > +#define CONFIG_CMD_MTDPARTS > +#define CONFIG_LZO > + > +#define MTDIDS_DEFAULT "nand0=nandflash-0" > + > +/* > + * Partions' layout for NAND is: > + * mtd0: 2M (spl) First boot loader > + * mtd1: 2M (u-boot, dtb) > + * mtd2: 6M (kernel) > + * mtd4: left (rootfs) > + */ > +/* Default mtd partition table */ > +#define MTDPARTS_DEFAULT "mtdparts=nandflash-0:"\ > + "2m(spl),"\ > + "2m(u-boot),"\ > + "6m(kernel),"\ > + "-(rootfs)" /* ubifs */ > + > +/* NAND stuff */ > +#define CONFIG_NAND_MXS > +#define CONFIG_SYS_MAX_NAND_DEVICE 1 > +#define CONFIG_SYS_NAND_BASE 0x40000000 > +#define CONFIG_SYS_NAND_5_ADDR_CYCLE > +#define CONFIG_SYS_NAND_ONFI_DETECTION > + > +/* DMA stuff, needed for GPMI/MXS NAND support */ > +#define CONFIG_APBH_DMA > +#define CONFIG_APBH_DMA_BURST > +#define CONFIG_APBH_DMA_BURST8 > +#endif > + > +#if defined(CONFIG_ENV_IS_IN_MMC) > +#define CONFIG_ENV_OFFSET (0x3E0000) > +#elif defined(CONFIG_ENV_IS_IN_NAND) > +#undef CONFIG_ENV_SIZE > +#define CONFIG_ENV_OFFSET (0x180000) > +#define CONFIG_ENV_SECT_SIZE (128 << 10) > +#define CONFIG_ENV_SIZE CONFIG_ENV_SECT_SIZE > +#endif > + > +#define CONFIG_OF_LIBFDT > + > +/* Framebuffer */ > +#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_SPLASH_SCREEN > +#define CONFIG_SPLASH_SCREEN_ALIGN > +#define CONFIG_BMP_16BPP > +#define CONFIG_VIDEO_LOGO > +#define CONFIG_VIDEO_BMP_LOGO > +#ifdef CONFIG_MX6DL > +#define CONFIG_IPUV3_CLK 198000000 > +#else > +#define CONFIG_IPUV3_CLK 264000000 > +#endif > +#define CONFIG_IMX_HDMI > +#define CONFIG_CMD_HDMIDETECT > +#define CONFIG_IMX_VIDEO_SKIP > +#define CONFIG_CMD_BMP > + > +#define PMIC_I2C_BUS 1 > +#define MX6CB_CDISPLAY_I2C_BUS 2 > +#define MX6CB_CDISPLAY_I2C_ADDR 0x38 > + > +/* I2C Configs */ > +#define CONFIG_CMD_I2C > +#define CONFIG_SYS_I2C > +#define CONFIG_SYS_I2C_MXC > +#define CONFIG_SYS_I2C_MXC_I2C1 /* enable I2C bus 1 */ > +#define CONFIG_SYS_I2C_MXC_I2C2 /* enable I2C bus 2 */ > +#define CONFIG_SYS_I2C_MXC_I2C3 /* enable I2C bus 3 */ > +#define CONFIG_SYS_I2C_SPEED 100000 > + > +/* PMIC */ > +#define CONFIG_POWER > +#define CONFIG_POWER_I2C > +#define CONFIG_POWER_PFUZE100 > +#define CONFIG_POWER_PFUZE100_I2C_ADDR 0x08 > + > +/* USB Configs */ > +#define CONFIG_CMD_USB > +#ifdef CONFIG_CMD_USB > +#define CONFIG_USB_EHCI > +#define CONFIG_USB_EHCI_MX6 > +#define CONFIG_USB_STORAGE > +#define CONFIG_EHCI_HCD_INIT_AFTER_RESET > +#define CONFIG_USB_HOST_ETHER > +#define CONFIG_USB_ETHER_ASIX > +#define CONFIG_MXC_USB_PORTSC (PORT_PTS_UTMI | PORT_PTS_PTW) > +#define CONFIG_MXC_USB_FLAGS 0 > +#define CONFIG_USB_MAX_CONTROLLER_COUNT 2 /* Enabled USB controller number */ > +#endif > + > +#define CONFIG_CI_UDC > +#define CONFIG_USBD_HS > +#define CONFIG_USB_GADGET_DUALSPEED > + > +/* Uncomment for USB Ethernet Gadget support */ > +/* > + * #define CONFIG_USB_ETHER > + * #define CONFIG_USB_ETH_CDC > + */ > +#define CONFIG_NETCONSOLE > + > +#define CONFIG_USB_GADGET > +#define CONFIG_CMD_USB_MASS_STORAGE > +#define CONFIG_USB_FUNCTION_MASS_STORAGE > +#define CONFIG_USB_GADGET_DOWNLOAD > +#define CONFIG_USB_GADGET_VBUS_DRAW 2 > + > +#define CONFIG_G_DNL_VENDOR_NUM 0x0525 > +#define CONFIG_G_DNL_PRODUCT_NUM 0xa4a5 > +#define CONFIG_G_DNL_MANUFACTURER "Variscite" > + > +/* USB Device Firmware Update support */ > +#define CONFIG_CMD_DFU > +#define CONFIG_USB_FUNCTION_DFU > +#define CONFIG_DFU_MMC > +#define CONFIG_DFU_RAM > +#ifdef CONFIG_SYS_USE_NAND > +#define CONFIG_SYS_MAX_NAND_DEVICE 1 > +#define CONFIG_DFU_NAND > +#endif > + > +#endif /* __MX6VAR_SOM_CONFIG_H */ > diff --git a/include/configs/mx6var_spl.h b/include/configs/mx6var_spl.h > new file mode 100644 > index 0000000..54cf4f1 > --- /dev/null > +++ b/include/configs/mx6var_spl.h > @@ -0,0 +1,81 @@ > +/* > + * Copyright (C) 2014 Gateworks Corporation > + * Author: Tim Harvey <tharvey@gateworks.com> > + * > + * Copyright (C) 2016 Variscite Ltd. All Rights Reserved. > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > +#ifndef __IMX6_SPL_CONFIG_H > +#define __IMX6_SPL_CONFIG_H > + > +#ifdef CONFIG_SPL > + > +#define CONFIG_SPL_FRAMEWORK > + > +/* > + * see Figure 8-3 in IMX6DQ/IMX6SDL Reference manuals: > + * - IMX6SDL OCRAM (IRAM) is from 0x00907000 to 0x0091FFFF > + * - IMX6DQ has 2x IRAM of IMX6SDL but we intend to support IMX6SDL as well > + * - BOOT ROM stack is at 0x0091FFB8 > + * - if icache/dcache is enabled (eFuse/strapping controlled) then the > + * IMX BOOT ROM will setup MMU table at 0x00918000, therefore we need to > + * fit between 0x00907000 and 0x00918000. > + * - Additionally the BOOT ROM loads what they consider the firmware image > + * which consists of a 4K header in front of us that contains the IVT, DCD > + * and some padding thus 'our' max size is really 0x00908000 - 0x00918000 > + * or 64KB > + */ > +#define CONFIG_SYS_THUMB_BUILD > +#define CONFIG_SPL_LDSCRIPT "board/variscite/mx6var_som/u-boot-spl.lds" > +#define CONFIG_SPL_TEXT_BASE 0x00908000 > +#define CONFIG_SPL_MAX_SIZE 0xFFFC /* ==0x10000-0x4, reserve 4Bytes for sending RAM size from SPL to U-Boot */ This is a hack - if we need an interface between SPL and u-boot, it must be solved globally nad not for a single function. And is it not set in the bdinfo structure ? > +#define CONFIG_SPL_STACK 0x0091FFB8 > +#define CONFIG_SPL_LIBCOMMON_SUPPORT > +#define CONFIG_SPL_LIBGENERIC_SUPPORT > +#define CONFIG_SPL_SERIAL_SUPPORT > +#define CONFIG_SPL_I2C_SUPPORT > +#define CONFIG_SPL_GPIO_SUPPORT > + You set again a lot of stuff instead of using mx6_spl.h. You should include this file, undefined the constants that are conflicting with your setup without duplicating all stuff. > +/* NAND support */ > +#if defined(CONFIG_SPL_NAND_SUPPORT) > +#define CONFIG_SPL_NAND_MXS > +#define CONFIG_SPL_DMA_SUPPORT > +#endif > + > +/* MMC support */ > +#if defined(CONFIG_SPL_MMC_SUPPORT) > +#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR 138 /* offset 69KB */ > +#define CONFIG_SYS_U_BOOT_MAX_SIZE_SECTORS 800 /* 400 KB */ > +#define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION 1 > +#define CONFIG_SYS_MONITOR_LEN (CONFIG_SYS_U_BOOT_MAX_SIZE_SECTORS/2*1024) > +#endif > + > +/* SATA support */ > +#if defined(CONFIG_SPL_SATA_SUPPORT) > +#define CONFIG_SPL_SATA_BOOT_DEVICE 0 > +#define CONFIG_SYS_SATA_FAT_BOOT_PARTITION 1 > +#endif > + > +/* Define the payload for FAT/EXT support */ > +#if defined(CONFIG_SPL_FAT_SUPPORT) || defined(CONFIG_SPL_EXT_SUPPORT) > +#define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME "u-boot.img" > +#define CONFIG_SPL_LIBDISK_SUPPORT > +#endif > + > +#if defined(CONFIG_MX6SX) > +#define CONFIG_SPL_BSS_START_ADDR 0x88200000 > +#define CONFIG_SPL_BSS_MAX_SIZE 0x100000 /* 1 MB */ > +#define CONFIG_SYS_SPL_MALLOC_START 0x88300000 > +#define CONFIG_SYS_SPL_MALLOC_SIZE 0x3200000 /* 50 MB */ > +#define CONFIG_SYS_TEXT_BASE 0x87800000 > +#else > +#define CONFIG_SPL_BSS_START_ADDR 0x18200000 > +#define CONFIG_SPL_BSS_MAX_SIZE 0x100000 /* 1 MB */ > +#define CONFIG_SYS_SPL_MALLOC_START 0x18300000 > +#define CONFIG_SYS_SPL_MALLOC_SIZE 0x3200000 /* 50 MB */ > +#define CONFIG_SYS_TEXT_BASE 0x17800000 > +#endif > +#endif > + > +#endif > diff --git a/tools/logos/variscite.bmp b/tools/logos/variscite.bmp I tend to reject this. You have already implemented a splashscreen and you can load an image to the display. Is it not enough ? > new file mode 100644 > index 0000000000000000000000000000000000000000..f3ca27ceb169cd5d174fa919248968877cb0e3d3 > GIT binary patch > literal 15414 > zcmeHO34B!LwU2kgL_-?_NHAh*x%YW*oFT>rL2W@1H!9Ey5zD@apnzf#MH;{mV~o*= > z6n&VdJdo9}8iv3iVKoq03NnF<0ok<4kPu*!FqZ;F&pYRQ_s(MTMEYxgCYA$t`Id9; > z`G05m&Nuw%+OuP)2&Rsa5fO>_b{wxRcwG~5E#3ufjfse$3p>RX5dj^4l?)wIQsAyT > z+QYB!>IlEN^DgLo_uX*cJ)NOzmwVy<d%M5`UAscJ2Oos)-5!SS4|ju}k30gse%BNF > z^zIFP`#c5%`}KpNg9pQtLx;fdAw%KGVZ&h5$dNGm>8IeCQKMnp*s<{9`0?<k2@_yS > zS{lsxLnO@ZE5V${uY>uiHkkLg1Pkz*pV|aIO0{D<65ElGkA3-%H-ULLcR}B4@EHjU > z@ye%n<jp7kzSqKne%ImkGnn5m78dny4)X>#hlPXiIiM9R=pP632DXMpgIYoUpcb&C > z|MjqVa2zZeasw<JoB&G(-vEn;;`p$eVezmVVZm@27C+GzmJgF*=|~xtjc5z`Puv1a > zM%;q$x4??gDtt5|5ta;3gym1&3d=@2VdW?XEFY5sE1yY$g3))t%4hF@6@Tmit`|DN > z$1ijN*MzRHYU2H{>ZM0uO<GSVO6vw|UhWNRCqD}7r}Tn#>3v}8lqs+_<M*&GBNf)Y > zIsn$aIS@9!IRrMnJ`^_PJPliNhQa1(!=d=?r{L4vF|c*Uv#@=}bFgLRc-S^`99}O% > zao+Q=<AVwC*?VbF^8O^)H7gBv%}s}_%uLA1&W7AK-hk=Troo@zo(}KMm;re+XTq!x > z-iHro&xZMP=Ry9$MX-G7QYcul0#><Puy)NFSYK2GJ7-UY-E%VGFLSeC_kuTIPkt`! > z&3_d<OWp$g<F{e=lIhr<0sEIuhtd`Afxhw`yk^3F*DNS2oCEt-&xJ3F7D3tCxo~j( > zA~>>fF&y5s3^s4v2#2>Uh9jGo!;w!{!k1fJ@MZC8IQp3zj+U&4V>>>9uS!<K*E?3j > z@sf4;TnB&Mvk@wGZ-OnGHpAB9V%T0%0=stZguS1C4*U1*gR%n$;NTZ!aOmJ6DBrUM > zyrm^jrEdf8{#{UcU<Y2i;l#n+P<e0{RF&<9ibH$h#9<vy9^4D34te0zky3o>P<41e > zoIY{@jvqS))kn(U)NviEj~|3HUmpVB*N5SB#Zjm$KMEBU6;SE*!imZgP=!}@bv4v@ > zzk;)sUqNkUIT$A^z<<gMwI?gVUtI}xr%!@$<|Ndd@quyr6r4YE8qU?62477L)Zk^* > z)`DReaN%q%T=3Vy`Ev$bI(H5(o<9edF8mG7|Lr`SyLb^UT(|(2@cH*|F2W_ezWMtl > zxcJRC@a?zX0!H@_y+mU8sorrRf5H?I@e>Az(5~WZ-1fa{zpM6Z$SZKwKO3@jF0b2v > zp#AEO?^^O+ZtlBtH<$S?zd#Lq#y{Ba%UL5H?4ZetBFoA5^q=;Z2Co0*)C<Sw|6<&I > zn&xb)%1BCEr`oQ=6YFX(C!-;chvD<hxLa}j;x;w!qoqh6z2DZU-K?o&ju`$h2)<RB > z>1i3+Zt`9q(rMww^y&-u=ws#O<;Ti{%)V7w8IvYuWVxz>ee`zLlbw+^<&_*g*zMDa > zHKfBZbhpdp4(ZWzUYR^8BYTI*6t1M%8N}!JmkmgCXtJz5Qq5ESXHzw&;=E0Hcx@PK > zPBTf8Y<R_H)wt|YNNq@%n_lg4p_+T_Hl%0^pgSQ7xtO97Jf;Hl$Z1L9knHh=R<~PX > z-oSe4X-#R8&F&U6d@JMZ%p=)iU#sE1v%WArxi5&%*xX%FHK(RHo-^%Lo2w~KS#c;G > z-meRCX7GpU<2ETSof^`sBx()!HxDR;U8RvU>$+q7C0{0^r5+?HDvNvZ=7|eRwAm+{ > z0^HZov}jA5C&rv);`?g?4Vxsz?L#?rRii(%WCor=eCzMmn3B{L)@V_Rf`q;8^8zmF > zVwr3|d}9E%mBg@`2g2}qxGPH7FO!!7k(r7{W{c0bV|bQzliCPK-?86K)*1+W<=0#D > z`6)HmQJ6pP*Y8x)QwZjJ0N<W&m@^ecb|^hgS`(^zDNZN#sws0Uo*P(TWZcUcFUMKm > zSWOH9Ukhu&X})Pc##bm5X__!~>P^uMHCm@RdaRIQZyGILq;%>w!tCewMwx?>js5c` > zA<Z7$)Xu=gsvPa1^({ttbu58z7QV{9!g`uR85>-Hmk2WsIJNse6+GqaWKtHv@O@}{ > z9DnjM_G`nK5_A&dX~~TYdY{bt*`|1OeRUhwx(SO5x8HsNFE%|rT}P%I=C@CA>&Nu$ > zSR1tpNZ2@8>yS$(43LFyqN+Fvp{#131O|-_Ns2Rxfh&)nWY`{7C&si=mQYS74ijH! > ze$hqzk^Q{al7`LA(N)YBkNqBD7!i!V1nQS2lejSZ8J;G@9;MR=E^ITJX6LX#4`@we > zaWt^@c3IO>i!A@c9uwd8WML>xbMy#t;S;?S4LLN-GynA#2{252=AJ05*+i!i(?8G9 > zyGay(l8xh!`Gn>;SjhNdag{Jz;d@Jqfzk5nh1+i*L9jJ5r@43;63iARs8+4w;wX!i > zb;5)%-=13)KxpC{K~csek7YK$(DQk8PwZBm4oBxBG*HE{BZ2^%w2(HNP9ydBC&iy+ > zyN>MV^AK?)8a1UNaxqqG;)!3fa;dL1r5`)(9pUy9_^jk5vNn4peK|;#y<|mGWu@=7 > zvt}pbt1C%H+!Sb9lDdpXb`|lX=vN$nj9eH{M0QMpm&aR>dZG5SRN&DN`*E9YK0W(J > zGg+Vkyg#QE2rQT3E+8V=_1Vu7&dX!hNt{XkTDI8P{+J;#C8~E!Gb2IRZ#-Lx@TtFL > zGa1vKXNHO%9F+uJ?#(PBU?f{i{NyZmIpYhpUs(POi9gokwCA;i=C~`<q97F-Mma;Z > zi^Z~(<>&X|6FW*=>kx`>{VK5yapHDODPQfok;O2+$_E(*;nT)&w{L(zW4xepFW%(j > z^*mJ2ROm-)#x^BAL+uw^&6C6}Z2vR7SuN~jEJ2cu(q}p44JkT=$9k>TKgFQW+(|4^ > z^pvFGG&oYh9SuDZ|Mp{ZFuo#9QP~9%_hPo&flkT7LD%sXPlFC6SBNi7kBua7LDFeJ > z#GlyI#Kf@u&+xPe@?c>Vn?sX?{Q^~r$w!axvmdW&@blu0vTofVnbHMr1?`{znuRgG > zncA%m(@YN><?g&&Zk|Xl{;KYrKXFu1hFbfk*OQZ();d;ft>O0L+`uC67HU6Vb4wxV > z8e8n-0udixR#nn1j^HyKUnw(N@n@C<qWm<MS|WF-=_|5`ocf8mgE78Q>TTqPGVbFe > zd6%nsQqg+R48QRbAtUgL+B0nD#N^;ID@UEw681Bz59+|3DY*X`*}{5~y~Wf5ok!{B > z<5VF9QlZX7F7!SAY4A2_FXWVrx2fdyEaUhCnCdl0@{56hW_$xNs}i9R=h9dGU)?J^ > zlS>%tdX+7Xc}ebim^5MyM4~su@`uKsEt-<MNul<eB+Qp#4%gsf)2t~Bn_~xC<+R_} > zqe}7h`|S5RGqHn{j24JbvXe@?+ba&u@o1ocHuv{bVIj@o>{y1g>Wszc!pfV(Yn=KW > zx-@~86FVKiHrgSwi7k!C3`01bPA$`Zwq}K<YoLFI*bmnn|A^Ysc)ev@%a*MODwd_F > ztaa!S#d{1Puh)KNfaqKo#+gPEl`R!RMxH}cwP%lV3Zb^ZSM!)Gb~#lUj9va(;~5o? > zN~vN`nJ8?F4%&&<bv3V@d8QK|3bP+78=sz)kx9aJwwX9Th&?%*KaF0ASfi-o@Z!-A > zXT`EvJtDBu*gwU0%(W8nM+FZPTU|<HFEW|P#j6K7v>prCFU*OeKI@|<Qv4yPJnpZ0 > zh%hB@V`VnTW@Rd~{rp0Q>kG@h<?eVs?L_fH3j5*afqx{aC8-i>zYkg8*urBK<?aN^ > z2~um;*2R^jEjleb3s102->t7d%*>oh15!*T66HnqW1B5zGBWXIA;tSJnznaHdG3&f > zOgzo_6EP;Y|AKqh@^)|T2Q|GEG_RtxbBf$rz&c1xn#MFWj}JF76XTQ8%+s8}$5Vy< > ze6a*jvLTy5WR=I}c^M(|3fQDqSX|IQ{anMbC|o&lx^RgSNO0g#4BEfWH>TGj%fbSk > z8GmE()J`F$3>4kZvAe3NqV*Q;jcnasoYT){n2LxmV%4kjJU6waDK2q<VtgWhn&;a> > zvnr!mG*!Sr)(mQygecR6iXr($9GhqcGMb_45_Pa(lYUl6slIspacc(?n&X}A_dkll > zryxbRXEnPgZU{Sh+D`R00`F`$!sNmqU`%!BldW~p&1V8UA-K4{X<3WCB7a)HzZ9|s > zO^u>nGlk)!ASh32MsY+Gw4V`={%*42X3O4-vTqD1A+_Ewc<Q+`zT#xw-jmuN<QYY( > zu%<FYF#LhwVaYSy;`ipXiJ>2NBBPq6xvWkd&z|Y&s9t$S4E{1hR?riO(yYzM_c5}e > zi`k>&vUH1$p5C1JXzY)SzA?v|Yj}utcp8bxPEViA_?prebmBnr6%LQVIw~@{O+W=P > z5O!yLRS!`~swn-%(2H1$5ha@Kw`FdoYzX1>>pR?T^Sl$%O|O1D42AxT7dq_I-EMbj > z07P)e>p^kf4W8hzI3ES_r#V2<Jg0-R>Um>)#sn_H<UDp?OehW!aCh!yj;$$VKP5G^ > zbgoC#zq8A%&#wFvjL*OQmx+q3bfV4OFgE`Ze}us*9Lt$m)b>}UI`P*F<sEALNF*ZJ > zsz0wl31Ppwr!_~Sqd%L^pX<=tX>`g^<RQ2N`u)bAR6H_v5ta89$o>~j6_vt2i?7aq > zpaX7sd47x?qq>ixa{S4fe2=hbaSB=&M}Isr?RVu02>ThvbXmPifZ2Jw?9}j(@078a > zo6Wx^R;D_&{{MgQU-?(Bn4{EA6!zo550hcxs~)Tls3DfxcPW{eq>L0lmQK{}quTmM > zBrj5VJ$d(XDp~l9&wu;J%^NmsE?VDT>;}9gC=aaNRE)hJbk674yqvU#Hy*%eY<Z}i > znv|s7Do((b1vM;elC;hrG(63Jm_|W-#<t#6XR4xjG4VO^bSpc$%%feqQBnv#qwFcf > z$F(%0<3mKEoFqRMTDUYal%e>HQwtxJ#bJS>kD$t`+WrkXaWz&7#fRIU_rJR<?FgG7 > zS-W%Gfv|sXYHT<|@v-hz%SQb^g?__V)ui7H``_b@4bXS={RezFUcKj&`S1OC_VSX7 > zMw(PYFxH2!(I(3fT-Iy-_^i>!|GbK?aog~!{jS=tA+Nwy|7^(Cxx8*y?RWV#YREHw > Ls{bo4fb0JN2LML% > Best regards, Stefano Babic
Hi Eran, On 31/03/2016 15:53, Eran Matityahu wrote: > Add support for Variscite VAR-SOM-MX6 / DART-MX6 / VAR-SOM-SOLO/DUAL boards with features: > PMIC, NAND flash, SD/MMC, USB, Ethernet, I2C, LVDS, HDMI. > > Signed-off-by: Eran Matityahu <eran.m@variscite.com> > --- > arch/arm/cpu/armv7/mx6/Kconfig | 7 + > board/variscite/mx6var_som/Kconfig | 12 + > board/variscite/mx6var_som/MAINTAINERS | 8 + > board/variscite/mx6var_som/Makefile | 9 + > board/variscite/mx6var_som/addresses.inc | 38 + > board/variscite/mx6var_som/imximage.cfg | 13 + > board/variscite/mx6var_som/mx6var_eeprom.c | 320 +++++ > board/variscite/mx6var_som/mx6var_eeprom.h | 88 ++ > board/variscite/mx6var_som/mx6var_eeprom_v2.c | 231 ++++ > board/variscite/mx6var_som/mx6var_eeprom_v2.h | 55 + > board/variscite/mx6var_som/mx6var_som.c | 1587 +++++++++++++++++++++++++ > board/variscite/mx6var_som/u-boot-spl.lds | 59 + > board/variscite/mx6var_som/values.inc | 39 + > configs/mx6var_som_nand_defconfig | 7 + > configs/mx6var_som_sd_defconfig | 7 + > include/configs/mx6var_som.h | 419 +++++++ > include/configs/mx6var_spl.h | 81 ++ > tools/logos/variscite.bmp | Bin 0 -> 15414 bytes This is a very big patch, just not easy to review. Is there any possibility to split it ? I have my difficulties to review such a monstruous patch. It is so big that my answer was blocked by the ML due to the size (it exceeds 100K). I have to drop some parts to avoid the block. Some general notes: - SPL is automatically set. Which is the reason to have an own imximage.cfg ? All boards use the same. You do not need to set "booting from nand" or BOOT FROM SD", because they share the same start offset in the storage. - can you better explain the reason under the ddr configuration in EEPROM ? > +endif > diff --git a/board/variscite/mx6var_som/MAINTAINERS b/board/variscite/mx6var_som/MAINTAINERS > new file mode 100644 > index 0000000..f3f81dd > --- /dev/null > +++ b/board/variscite/mx6var_som/MAINTAINERS > @@ -0,0 +1,8 @@ > +MX6VAR_SOM BOARD > +M: Eran Matityahu <eran.m@variscite.com> > +S: Maintained > +F: board/variscite/mx6var_som/ > +F: include/configs/mx6var_som.h > +F: include/configs/mx6var_spl.h > +F: configs/mx6var_som_nand_defconfig > +F: configs/mx6var_som_sd_defconfig The list must match the files you want must be added to the projects. Just a few of them are listed here. > diff --git a/board/variscite/mx6var_som/Makefile b/board/variscite/mx6var_som/Makefile > new file mode 100644 > index 0000000..efa90e2 > --- /dev/null > +++ b/board/variscite/mx6var_som/Makefile > @@ -0,0 +1,9 @@ > +# > +# Copyright (C) 2007, Guennadi Liakhovetski <lg@denx.de> > +# > +# (C) Copyright 2011 Freescale Semiconductor, Inc. > +# > +# SPDX-License-Identifier: GPL-2.0+ > +# > + > +obj-y := mx6var_som.o mx6var_eeprom.o mx6var_eeprom_v2.o > diff --git a/board/variscite/mx6var_som/addresses.inc b/board/variscite/mx6var_som/addresses.inc > new file mode 100644 > index 0000000..3aaea54 > --- /dev/null > +++ b/board/variscite/mx6var_som/addresses.inc > @@ -0,0 +1,38 @@ > +0x00000000, 0x020C4068, 0x020C406C, 0x020C4070, > +0x021B4818, 0x021B481C, 0x021B4820, 0x021B4824, > +0x021B4828, 0x021B482C, 0x021B4830, 0x021B4834, > +0x021B4838, 0x021B483C, 0x021B4840, 0x021B4848, > +0x021B4850, 0x021B485C, 0x021B4890, 0x021B48B8, > +0x021B48BC, 0x021B48C0 I miss why it shhoul be necessary this. Indeed, they are addresses that are saved as structures into imx6-regs.h. Why do you need your custom way ? > diff --git a/board/variscite/mx6var_som/imximage.cfg b/board/variscite/mx6var_som/imximage.cfg > new file mode 100644 > index 0000000..54dc449 > --- /dev/null > +++ b/board/variscite/mx6var_som/imximage.cfg > @@ -0,0 +1,13 @@ > +/* > + * Copyright (C) 2016 Variscite Ltd. All Rights Reserved. > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +IMAGE_VERSION 2 > + > +#ifdef CONFIG_SYS_BOOT_NAND > +BOOT_FROM nand > +#else > +BOOT_FROM sd > +#endif I think the file is not needed at all and you can use the general rch/arm/imx-common/spl_sd.cfg. > diff --git a/board/variscite/mx6var_som/mx6var_eeprom.c b/board/variscite/mx6var_som/mx6var_eeprom.c > new file mode 100644 > index 0000000..02fedd0 > --- /dev/null > +++ b/board/variscite/mx6var_som/mx6var_eeprom.c > @@ -0,0 +1,320 @@ > +/* > + * Copyright (C) 2016 Variscite Ltd. All Rights Reserved. > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + I start telling you that I do not understand the meaning for mx6var_eeprom.c and mx6var_eepromV2.c > +#include <common.h> > +#include <command.h> > +#include <i2c.h> > +#include "mx6var_eeprom.h" > +#ifdef CONFIG_SPL_BUILD > +#include <asm/arch/mx6-ddr.h> > + > +#ifdef EEPROM_DEBUG > +#define eeprom_debug(M, ...) printf("EEPROM DEBUG: " M, ##__VA_ARGS__) > +#else > +#define eeprom_debug(M, ...) > +#endif > + > +bool var_eeprom_is_valid(struct var_eeprom_cfg *p_var_eeprom_cfg) > +{ > + return (VARISCITE_MAGIC == p_var_eeprom_cfg->header.variscite_magic); > +} > + > +void var_eeprom_mx6dlsl_dram_setup_iomux_from_struct(struct var_pinmux_group_regs *pinmux_group) > +{ > + volatile struct mx6sdl_iomux_ddr_regs *mx6dl_ddr_iomux; > + volatile struct mx6sdl_iomux_grp_regs *mx6dl_grp_iomux; > + > + mx6dl_ddr_iomux = (struct mx6sdl_iomux_ddr_regs *) MX6SDL_IOM_DDR_BASE; > + mx6dl_grp_iomux = (struct mx6sdl_iomux_grp_regs *) MX6SDL_IOM_GRP_BASE; > + > + mx6dl_grp_iomux->grp_ddr_type = (u32)pinmux_group->IOMUXC_SW_PAD_CTL_GRP_DDR_TYPE; > + mx6dl_grp_iomux->grp_ddrpke = (u32)pinmux_group->IOMUXC_SW_PAD_CTL_GRP_DDRPKE; > + mx6dl_ddr_iomux->dram_sdclk_0 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_ddr_iomux->dram_sdclk_1 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_ddr_iomux->dram_cas = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_ddr_iomux->dram_ras = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_grp_iomux->grp_addds = (u32)pinmux_group->pinmux_ctrlpad_all_value; [snip} > + mx6dl_ddr_iomux->dram_dqm1 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_ddr_iomux->dram_dqm2 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_ddr_iomux->dram_dqm3 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_ddr_iomux->dram_dqm4 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_ddr_iomux->dram_dqm5 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_ddr_iomux->dram_dqm6 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6dl_ddr_iomux->dram_dqm7 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > +} I am really missing the goal for this. > + > +void var_eeprom_mx6qd_dram_setup_iomux_from_struct(struct var_pinmux_group_regs *pinmux_group) > +{ > + volatile struct mx6dq_iomux_ddr_regs *mx6q_ddr_iomux; > + volatile struct mx6dq_iomux_grp_regs *mx6q_grp_iomux; > + > + mx6q_ddr_iomux = (struct mx6dq_iomux_ddr_regs *) MX6DQ_IOM_DDR_BASE; > + mx6q_grp_iomux = (struct mx6dq_iomux_grp_regs *) MX6DQ_IOM_GRP_BASE; > + > + mx6q_grp_iomux->grp_ddr_type = (u32)pinmux_group->IOMUXC_SW_PAD_CTL_GRP_DDR_TYPE; > + mx6q_grp_iomux->grp_ddrpke = (u32)pinmux_group->IOMUXC_SW_PAD_CTL_GRP_DDRPKE; > + mx6q_ddr_iomux->dram_sdclk_0 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_ddr_iomux->dram_sdclk_1 = (u32)pinmux_group->pinmux_ctrlpad_all_value; [snip} > + mx6q_grp_iomux->grp_b5ds = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_grp_iomux->grp_b6ds = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_grp_iomux->grp_b7ds = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_ddr_iomux->dram_dqm0 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_ddr_iomux->dram_dqm1 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_ddr_iomux->dram_dqm2 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_ddr_iomux->dram_dqm3 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_ddr_iomux->dram_dqm4 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_ddr_iomux->dram_dqm5 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_ddr_iomux->dram_dqm6 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > + mx6q_ddr_iomux->dram_dqm7 = (u32)pinmux_group->pinmux_ctrlpad_all_value; > +} Ditto. > + > +void var_eeprom_dram_init_from_struct(struct var_eeprom_cfg *p_var_eeprom_cfg) > +{ > + volatile struct mmdc_p_regs *mmdc_p0 = (struct mmdc_p_regs *) MMDC_P0_BASE_ADDR; > + u32 i; > + u32 last; > + u32 opcode; > + > + /* Go through all register initializations and apply to correct registers... */ > + i = 0; > + last = sizeof(p_var_eeprom_cfg->write_opcodes) / sizeof(u32); > + while ( (0 != p_var_eeprom_cfg->write_opcodes[i].address) && (i < last) ) { > + opcode = p_var_eeprom_cfg->write_opcodes[i].address & 0xF0000000; > + switch (opcode) { > + case VAR_DDR_INIT_OPCODE_WRITE_VAL_TO_ADDRESS: > + /* ZQ calibration? ==> Need to wait? */ > + if (mmdc_p0->mpzqhwctrl == p_var_eeprom_cfg->write_opcodes[i].address) { > + if (p_var_eeprom_cfg->write_opcodes[i].value & 0x3) { > + while (mmdc_p0->mpzqhwctrl & 0x00010000); > + } > + } > + else { > + /* write value to reg */ > + volatile u32 *reg_ptr = (volatile u32 *)p_var_eeprom_cfg->write_opcodes[i].address; > + > + *reg_ptr = p_var_eeprom_cfg->write_opcodes[i].value; > + } > + break; > + case VAR_DDR_INIT_OPCODE_WAIT_MASK_RISING: { > + volatile u32 *reg_ptr = (volatile u32 *)p_var_eeprom_cfg->write_opcodes[i].address; > + > + while ( (p_var_eeprom_cfg->write_opcodes[i].value & *reg_ptr) != \ > + p_var_eeprom_cfg->write_opcodes[i].value ); > + break; > + } > + case VAR_DDR_INIT_OPCODE_WAIT_MASK_FALLING: { > + volatile u32 *reg_ptr = (volatile u32 *)p_var_eeprom_cfg->write_opcodes[i].address; > + > + while ( (p_var_eeprom_cfg->write_opcodes[i].value & (~(*reg_ptr)) ) != \ > + p_var_eeprom_cfg->write_opcodes[i].value ); > + break; > + } > + case VAR_DDR_INIT_OPCODE_DELAY_USEC: > + udelay(p_var_eeprom_cfg->write_opcodes[i].value); > + break; > + default: > + break; > + } > + > + i++; > + } It is not that common code is not flexible: mx6<SOC>_dram_iocfg() let set the pinmux with own setup. You replace common code with this one, and I do not understand why. > + > + /* Short delay */ > + udelay(500); > +} > + > +#ifdef EEPROM_DEBUG > +static void var_eeprom_printf_array_dwords(u32 *ptr, u32 address_mem, u32 size) > +{ > + u32 idx; > + u32 *p_end = ptr + (size/4); > + idx = 0; > + while (ptr < p_end) { > + if ((idx & 0x3) == 0) { > + printf("\n0x%08x:", address_mem); > + address_mem += 0x10; > + } > + printf(" 0x%08x", *ptr); > + idx++; > + ptr++; > + } > + printf("\n"); > +} > +#endif > + > +int var_eeprom_read_struct(struct var_eeprom_cfg *p_var_eeprom_cfg) > +{ > + int eeprom_found; > + int ret = 0; > + i2c_set_bus_num(1); > + eeprom_found = i2c_probe(VAR_MX6_EEPROM_CHIP); > + eeprom_debug("eeprom_found(0x%x)=%d\n", VAR_MX6_EEPROM_CHIP, eeprom_found); > + if (0 == eeprom_found) { > + eeprom_debug("EEPROM device detected, address=0x%x\n", VAR_MX6_EEPROM_CHIP); > + > + if (i2c_read(VAR_MX6_EEPROM_CHIP, VAR_MX6_EEPROM_STRUCT_OFFSET, \ > + 1, (uchar *)p_var_eeprom_cfg, sizeof(struct var_eeprom_cfg))) { > + eeprom_debug("Read device ID error!\n"); > + return -1; > + } else { > + /* Success */ > +#ifdef EEPROM_DEBUG > + var_eeprom_printf_array_dwords((u32 *) p_var_eeprom_cfg, (u32) 0, \ > + sizeof(struct var_eeprom_cfg)); > +#endif > + } > + } else { > + eeprom_debug("Error! Couldn't find EEPROM device\n"); > + } > + > + return ret; > +} > +#endif /* CONFIG_SPL_BUILD */ > + > +void var_eeprom_strings_print(struct var_eeprom_cfg *p_var_eeprom_cfg) > +{ > + p_var_eeprom_cfg->header.part_number[sizeof(p_var_eeprom_cfg->header.part_number)-1] = (u8)0x00; > + p_var_eeprom_cfg->header.Assembly[sizeof(p_var_eeprom_cfg->header.Assembly)-1] = (u8)0x00; > + p_var_eeprom_cfg->header.date[sizeof(p_var_eeprom_cfg->header.date)-1] = (u8)0x00; > + > + printf("Part number: %s\n", (char *)p_var_eeprom_cfg->header.part_number); > + printf("Assembly: %s\n", (char *)p_var_eeprom_cfg->header.Assembly); > + printf("Date of production: %s\n", (char *)p_var_eeprom_cfg->header.date); > +} > + > +static int var_eeprom_write(uchar *ptr, u32 size, u32 offset) > +{ > + int ret = 0; > + u32 size_written; > + u32 size_to_write; > + u32 P0_select_page_EEPROM; > + u32 chip; > + u32 addr; > + > + /* Write to EEPROM device */ > + size_written = 0; > + size_to_write = size; > + while ((0 == ret) && (size_written < size_to_write)) { > + P0_select_page_EEPROM = (offset > 0xFF); > + chip = VAR_MX6_EEPROM_CHIP + P0_select_page_EEPROM; > + addr = (offset & 0xFF); > + ret = i2c_write(chip, addr, 1, ptr, VAR_MX6_EEPROM_WRITE_MAX_SIZE); > + > + /* Wait for EEPROM write operation to complete (No ACK) */ > + mdelay(11); > + > + size_written += VAR_MX6_EEPROM_WRITE_MAX_SIZE; > + offset += VAR_MX6_EEPROM_WRITE_MAX_SIZE; > + ptr += VAR_MX6_EEPROM_WRITE_MAX_SIZE; > + } > + > + return ret; > +} There is eprom_read() and eprom_write() from cmd/eeprom.c. Does it not work in your case ? > + > +/* > + * vareeprom command intepreter. > + */ > +static int do_var_eeprom_params(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) > +{ > + struct var_eeprom_cfg var_eeprom_cfg; > + int offset; > + > + if (argc != 4) > + return -1; > + > + memset(&var_eeprom_cfg, 0x00, sizeof(var_eeprom_cfg)); > + > + memcpy(&var_eeprom_cfg.header.part_number[0], argv[1], sizeof(var_eeprom_cfg.header.part_number)); > + memcpy(&var_eeprom_cfg.header.Assembly[0], argv[2], sizeof(var_eeprom_cfg.header.Assembly)); > + memcpy(&var_eeprom_cfg.header.date[0], argv[3], sizeof(var_eeprom_cfg.header.date)); > + > + var_eeprom_strings_print(&var_eeprom_cfg); > + > + offset = (uchar *)&var_eeprom_cfg.header.part_number[0] - (uchar *)&var_eeprom_cfg.header; > + if (var_eeprom_write((uchar *)&var_eeprom_cfg.header.part_number[0], \ > + sizeof(var_eeprom_cfg.header.part_number), \ > + VAR_MX6_EEPROM_STRUCT_OFFSET + offset) ) { > + printf("Error writing to EEPROM!\n"); > + return -1; > + } > + > + offset = (uchar *)&var_eeprom_cfg.header.Assembly[0] - (uchar *)&var_eeprom_cfg; > + if (var_eeprom_write((uchar *)&var_eeprom_cfg.header.Assembly[0], \ > + sizeof(var_eeprom_cfg.header.Assembly), \ > + VAR_MX6_EEPROM_STRUCT_OFFSET + offset) ) { > + printf("Error writing to EEPROM!\n"); > + return -1; > + } > + > + offset = (uchar *)&var_eeprom_cfg.header.date[0] - (uchar *)&var_eeprom_cfg; > + if (var_eeprom_write((uchar *)&var_eeprom_cfg.header.date[0], \ > + sizeof(var_eeprom_cfg.header.date), \ > + VAR_MX6_EEPROM_STRUCT_OFFSET + offset) ) { > + printf("Error writing to EEPROM!\n"); > + return -1; > + } > + > + printf("EEPROM updated successfully\n"); > + > + return 0; > +} > + > +U_BOOT_CMD( > + vareeprom, 5, 1, do_var_eeprom_params, > + "For internal use only", > + "- Do not use" > +); > diff --git a/board/variscite/mx6var_som/mx6var_eeprom.h b/board/variscite/mx6var_som/mx6var_eeprom.h > new file mode 100644 > index 0000000..5c70a27 > --- /dev/null > +++ b/board/variscite/mx6var_som/mx6var_eeprom.h > @@ -0,0 +1,88 @@ > +/* > + * Copyright (C) 2016 Variscite Ltd. All Rights Reserved. > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#ifndef _MX6VAR_EEPROM_H_ > +#define _MX6VAR_EEPROM_H_ > + > +#define VARISCITE_MAGIC 0x49524157 /* == HEX("VARI")*/ > + > +#define VAR_MX6_EEPROM_CHIP 0x56 > +#define VAR_DART_EEPROM_CHIP 0x52 > + > +#define VAR_MX6_EEPROM_STRUCT_OFFSET 0x00000000 > + > +#define VAR_MX6_EEPROM_WRITE_MAX_SIZE 0x4 > + > +#define EEPROM_SIZE_BYTES 512 > + > +#define VAR_DDR_INIT_OPCODE_WRITE_VAL_TO_ADDRESS 0x00000000 > +#define VAR_DDR_INIT_OPCODE_WAIT_MASK_RISING 0x10000000 > +#define VAR_DDR_INIT_OPCODE_WAIT_MASK_FALLING 0x20000000 > +#define VAR_DDR_INIT_OPCODE_DELAY_USEC 0x30000000 > + > +#define SPL_DRAM_INIT_STATUS_OK 0 > +#define SPL_DRAM_INIT_STATUS_ERROR_NO_EEPROM 1 > +#define SPL_DRAM_INIT_STATUS_ERROR_NO_EEPROM_STRUCT_DETECTED 2 > + > +struct var_eeprom_cfg_header > +{ > + u32 variscite_magic; /* == HEX("VARI")?*/ > + u8 part_number[16]; > + u8 Assembly[16]; > + u8 date[16]; > + u8 version; > + u8 reserved[7]; > + u32 ddr_size; > +}; > + > +struct var_pinmux_group_regs > +{ > + u32 IOMUXC_SW_PAD_CTL_GRP_DDR_TYPE; > + u32 IOMUXC_SW_PAD_CTL_GRP_DDRPKE; > + u32 IOMUXC_SW_PAD_CTL_GRP_DDRMODE_CTL; > + u32 IOMUXC_SW_PAD_CTL_GRP_DDRMODE; > + u32 IOMUXC_SW_PAD_CTL_PAD_DRAM_SDBA2; > + u32 dram_reset; > + u32 dram_sdcke0; > + u32 dram_sdcke1; > + u32 dram_sdodt0; > + u32 dram_sdodt1; > + u32 reserved; > + u32 pinmux_ctrlpad_all_value; > +}; > + > +struct reg_write_opcode > +{ > + u32 address; /* address encoded with opcode */ > + u32 value; > +}; > + > +struct var_eeprom_cfg > +{ > + struct var_eeprom_cfg_header header; > + struct var_pinmux_group_regs pinmux_group; > + struct reg_write_opcode write_opcodes[ \ > + (EEPROM_SIZE_BYTES \ > + - sizeof(struct var_eeprom_cfg_header) \ > + - sizeof(struct var_pinmux_group_regs)) \ > + / sizeof(struct reg_write_opcode) ]; > +}; > + > +bool var_eeprom_is_valid(struct var_eeprom_cfg *p_var_eeprom_cfg); > + > +/* init ddr iomux from struct */ > +void var_eeprom_mx6dlsl_dram_setup_iomux_from_struct(struct var_pinmux_group_regs *pinmux_group); > + > +void var_eeprom_mx6qd_dram_setup_iomux_from_struct(struct var_pinmux_group_regs *pinmux_group); > + > +/* init ddr from struct */ > +void var_eeprom_dram_init_from_struct(struct var_eeprom_cfg *p_var_eeprom_cfg); > + > +int var_eeprom_read_struct(struct var_eeprom_cfg *p_var_eeprom_cfg); > + > +void var_eeprom_strings_print(struct var_eeprom_cfg *p_var_eeprom_cfg); > + > +#endif /* _MX6VAR_EEPROM_H_ */ > diff --git a/board/variscite/mx6var_som/mx6var_eeprom_v2.c b/board/variscite/mx6var_som/mx6var_eeprom_v2.c > new file mode 100644 > index 0000000..490b470 > --- /dev/null > +++ b/board/variscite/mx6var_som/mx6var_eeprom_v2.c > @@ -0,0 +1,231 @@ > +/* > + * Copyright (C) 2016 Variscite Ltd. All Rights Reserved. > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#ifdef CONFIG_SPL_BUILD > +#include <common.h> > +#include <i2c.h> > +#include "mx6var_eeprom_v2.h" > + > +#ifdef EEPROM_V2_DEBUG > +#define eeprom_v2_debug(M, ...) printf("EEPROM_V2 DEBUG: " M, ##__VA_ARGS__) > +#else > +#define eeprom_v2_debug(M, ...) > +#endif > + > +static u32 get_address_by_index(unsigned char index, u32 *ram_addresses); > +static u32 get_value_by_index(unsigned char index, u32 *ram_values); > +static int handle_one_command(struct eeprom_command *eeprom_commands,int command_num, \ > + u32 *ram_addresses, u32 *ram_values); > + > + > +bool var_eeprom_v2_is_valid(struct var_eeprom_v2_cfg *p_var_eeprom_v2_cfg) > +{ > + return (VARISCITE_MAGIC_V2 == p_var_eeprom_v2_cfg->variscite_magic); > +} > + > + > +void var_eeprom_v2_strings_print(struct var_eeprom_v2_cfg *p_var_eeprom_v2_cfg) [snip] > +} > + > + > +static int handle_one_command(struct eeprom_command *eeprom_commands, int command_num, \ > + u32 *ram_addresses, u32 *ram_values) > +{ > + volatile u32 *data; > + u32 address; > + u32 value; > + > + eeprom_v2_debug("Executing command %03d: %03d, %03d\n", > + command_num, > + eeprom_commands[command_num].address_index, > + eeprom_commands[command_num].value_index); > + > + switch(eeprom_commands[command_num].address_index) { > + case WHILE_NOT_EQUAL_INDEX: > + command_num++; > + address=get_address_by_index(eeprom_commands[command_num].address_index, ram_addresses); > + value=get_value_by_index(eeprom_commands[command_num].value_index, ram_values); > + data=(u32*)address; > + eeprom_v2_debug("Waiting while data at address %08x is not equal %08x\n", address, value); > + > + while(data[0]!=value); > + > + command_num++; > + break; > + case WHILE_EQUAL_INDEX: > + command_num++; > + address=get_address_by_index(eeprom_commands[command_num].address_index, ram_addresses); > + value=get_value_by_index(eeprom_commands[command_num].value_index, ram_values); > + data=(u32*)address; > + eeprom_v2_debug("Waiting while data at address %08x is equal %08x\n", address, value); > + > + while(data[0]==value); > + > + command_num++; > + break; > + case WHILE_AND_INDEX: > + command_num++; > + address=get_address_by_index(eeprom_commands[command_num].address_index, ram_addresses); > + value=get_value_by_index(eeprom_commands[command_num].value_index, ram_values); > + data=(u32*)address; > + eeprom_v2_debug("Waiting while data at address %08x and %08x is not zero\n", address, value); > + > + while(data[0]&value); > + > + command_num++; > + break; > + case WHILE_NOT_AND_INDEX: > + command_num++; > + address=get_address_by_index(eeprom_commands[command_num].address_index, ram_addresses); > + value=get_value_by_index(eeprom_commands[command_num].value_index, ram_values); > + data=(u32*)address; > + eeprom_v2_debug("Waiting while data at address %08x and %08x is zero\n", address, value); > + > + while(!(data[0]&value)); Code is quite confusing - it does quite the same thing, and can be rewritten factorizing most part. > + > + command_num++; > + break; > + case DELAY_10USEC_INDEX: > + /* Delay for Value * 10 uSeconds */ > + eeprom_v2_debug("Delaying for %d microseconds\n", eeprom_commands[command_num].value_index*10); > + udelay((int)(eeprom_commands[command_num].value_index*10)); > + command_num++; > + break; > + case LAST_COMMAND_INDEX: > + command_num=0; > + break; > + default: > + address=get_address_by_index(eeprom_commands[command_num].address_index, ram_addresses); > + value=get_value_by_index(eeprom_commands[command_num].value_index, ram_values); > + data=(u32*)address; > + eeprom_v2_debug("Setting data at address %08x to %08x\n", address, value); > + data[0]=value; > + command_num++; > + break; > + } > + > + return command_num; > +} > + > + > +static u32 get_address_by_index(unsigned char index, u32 *ram_addresses) > +{ > + /* > + * DDR Register struct > + * The eeprom contains a structure of: > + * 1 byte index in this addresses table, and > + * 1 byte index to common values in the next table - to write to this address. > + * If there are new addresses from the calibration program, > + * they should be added to the end of the array. > + * The maximum array size is 256 addresses. > + */ > + const u32 rom_addresses[]= > + { > + #include "addresses.inc" > + }; > + > + if (index >= MAXIMUM_ROM_ADDR_INDEX) > + return ram_addresses[index-MAXIMUM_ROM_ADDR_INDEX]; > + > + return rom_addresses[index]; > +} > + > + > +static u32 get_value_by_index(unsigned char index, u32 *ram_values) > +{ > + const u32 rom_values[] = > + { > + #include "values.inc" > + }; > + > + if (index >= MAXIMUM_ROM_VALUE_INDEX) > + return ram_values[index-MAXIMUM_ROM_VALUE_INDEX]; > + > + return rom_values[index]; > +} > + > + > +int var_eeprom_v2_read_struct(struct var_eeprom_v2_cfg *var_eeprom_v2_cfg, \ > + unsigned char address) > +{ > + int eeprom_found = i2c_probe(address); > + if (0 == eeprom_found) { > + if (i2c_read(address, 0, 1, (void*) var_eeprom_v2_cfg, \ > + sizeof(struct var_eeprom_v2_cfg))) { > + printf("Read device ID error!\n"); > + return -1; > + } > + } else { > + printf("Error! Couldn't find EEPROM device\n"); > + } > + return 0; > +} As I said, I have not understood at all the reason for that. > +#endif > diff --git a/board/variscite/mx6var_som/mx6var_eeprom_v2.h b/board/variscite/mx6var_som/mx6var_eeprom_v2.h > new file mode 100644 > index 0000000..cebf46d > --- /dev/null > +++ b/board/variscite/mx6var_som/mx6var_eeprom_v2.h > @@ -0,0 +1,55 @@ > +/* > + * Copyright (C) 2016 Variscite Ltd. All Rights Reserved. > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#ifndef _MX6VAR_V2_EEPROM_H_ > +#define _MX6VAR_V2_EEPROM_H_ > + > +#define VARISCITE_MAGIC_V2 0x32524156 /* == HEX("VAR2") */ > + > +#define MAXIMUM_ROM_ADDR_INDEX 200 > +#define MAXIMUM_ROM_VALUE_INDEX 200 > +#define WHILE_NOT_EQUAL_INDEX 241 > +#define WHILE_EQUAL_INDEX 242 > +#define WHILE_AND_INDEX 243 > +#define WHILE_NOT_AND_INDEX 244 > +#define DELAY_10USEC_INDEX 245 > +#define LAST_COMMAND_INDEX 255 > + > +#define MAXIMUM_RAM_ADDRESSES 32 > +#define MAXIMUM_RAM_VALUES 32 > + > +#define MAXIMUM_COMMANDS_NUMBER 150 > + > +struct __attribute__((packed)) eeprom_command > +{ > + unsigned char address_index; > + unsigned char value_index; > +}; > + > +struct __attribute__((packed)) var_eeprom_v2_cfg > +{ > + u32 variscite_magic; /* == HEX("VAR2")? */ > + u8 part_number[16]; > + u8 Assembly[16]; > + u8 date[12]; > + u32 custom_addresses_values[32]; > + struct eeprom_command eeprom_commands[MAXIMUM_COMMANDS_NUMBER]; > + u8 reserved[34]; > + u8 ddr_size; > + u8 crc; > +}; > + > +bool var_eeprom_v2_is_valid(struct var_eeprom_v2_cfg *p_var_eeprom_v2_cfg); > +void var_eeprom_v2_strings_print(struct var_eeprom_v2_cfg *p_var_eeprom_v2_cfg); > +int handle_eeprom_data(struct var_eeprom_v2_cfg *var_eeprom_v2_cfg, \ > + u32 *ram_addresses, u32 *ram_values); > +int setup_ddr_parameters(struct eeprom_command *eeprom_commands, \ > + u32 *ram_addresses, u32 *ram_values); > +void load_custom_data(u32 *custom_addresses_values, u32 *ram_addresses, u32 *ram_values); > +int var_eeprom_v2_read_struct(struct var_eeprom_v2_cfg *var_eeprom_v2_cfg, \ > + unsigned char address); > + > +#endif /* _MX6VAR_V2_EEPROM_H_ */ > diff --git a/board/variscite/mx6var_som/mx6var_som.c b/board/variscite/mx6var_som/mx6var_som.c > new file mode 100644 > index 0000000..e99690b > --- /dev/null > +++ b/board/variscite/mx6var_som/mx6var_som.c > @@ -0,0 +1,1587 @@ > +/* > + * Copyright (C) 2012 Freescale Semiconductor, Inc. > + * Author: Fabio Estevam <fabio.estevam@freescale.com> > + * > + * Copyright (C) 2016 Variscite Ltd. All Rights Reserved. > + * > + * Author: Eran Matityahu <eran.m@variscite.com> > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#include <asm/arch/clock.h> > +#include <asm/arch/imx-regs.h> > +#include <asm/arch/iomux.h> > +#include <malloc.h> > +#include <asm/arch/mx6-pins.h> > +#include <asm/errno.h> > +#include <asm/gpio.h> > +#include <asm/imx-common/mxc_i2c.h> > +#include <asm/imx-common/iomux-v3.h> > +#include <asm/imx-common/boot_mode.h> > +#include <asm/imx-common/video.h> > +#include <mmc.h> > +#include <fsl_esdhc.h> > +#include <micrel.h> > +#include <miiphy.h> > +#include <netdev.h> > +#include <asm/arch/mxc_hdmi.h> > +#include <asm/arch/crm_regs.h> > +#include <asm/io.h> > +#include <asm/arch/sys_proto.h> > +#include <i2c.h> > +#include <power/pmic.h> > +#include <power/pfuze100_pmic.h> > +#include <usb.h> > +#include <usb/ehci-fsl.h> > + > +DECLARE_GLOBAL_DATA_PTR; > + > +#define UART_PAD_CTRL (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_PUS_47K_UP | \ > + PAD_CTL_SPEED_LOW | PAD_CTL_DSE_80ohm | \ > + PAD_CTL_SRE_FAST | PAD_CTL_HYS) > + > +#define ENET_PAD_CTRL (PAD_CTL_PUS_100K_UP | \ > + PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS) > + > +#define GPMI_PAD_CTRL0 (PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_PUS_100K_UP) > +#define GPMI_PAD_CTRL1 (PAD_CTL_DSE_40ohm | PAD_CTL_SPEED_MED | \ > + PAD_CTL_SRE_FAST) > +#define GPMI_PAD_CTRL2 (GPMI_PAD_CTRL0 | GPMI_PAD_CTRL1) > + > +#define PER_VCC_EN_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_PUS_100K_UP | \ > + PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS | \ > + PAD_CTL_ODE | PAD_CTL_SRE_FAST) > + > +#define OTG_ID_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 VAR_SOM_BACKLIGHT_EN IMX_GPIO_NR(4, 30) > + > +bool lvds_enabled=false; > + > +#ifdef CONFIG_SYS_USE_NAND > +static int var_load_file_from_nand(u32 addr, char *filename) > +{ > + extern int ubi_part(char *part_name, const char *vid_header_offset); > + extern int ubifs_init(void); > + extern int uboot_ubifs_mount(char *vol_name); > + extern int ubifs_load(char *filename, u32 addr, u32 size); > + extern void cmd_ubifs_umount(void); > + > + char *ubi_part_name = "rootfs"; > + char *ubifs_vol_name = "ubi0:rootfs"; > + > + if (ubi_part(ubi_part_name, NULL)) > + return -1; > + if (ubifs_init()) > + return -1; > + if (uboot_ubifs_mount(ubifs_vol_name)) > + return -1; > + > + /* Load the file to memory */ > + if (ubifs_load(filename, addr, 0)) { > + printf("Error: splash file not found %s\n", filename); > + cmd_ubifs_umount(); > + return -1; > + } > + cmd_ubifs_umount(); Why ? All this stuff can be done in a much more flexible way scripts in the environment. It should be not hard-coded. > + return 0; > +} > +#endif > + > +static int var_load_file_from_mmc(u32 addr, char *filename) > +{ > +#define FS_TYPE_EXT 2 > + extern int fs_set_blk_dev(const char *ifname, const char *dev_part_str, int fstype); > + extern int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len, > + loff_t *actread); > + > + loff_t len_read; > + > +#ifdef CONFIG_SYS_USE_NAND > + if (fs_set_blk_dev("mmc", "1:1", FS_TYPE_EXT)) > + return -1; > +#else > + if (fs_set_blk_dev("mmc", "0:2", FS_TYPE_EXT)) > + return -1; > +#endif > + > + if (fs_read(filename, addr, 0, 0, &len_read)) { > + printf("Error: splash file not found %s\n", filename); > + return -1; > + } > + > + printf("%llu bytes read\n", len_read); > + return 0; > +#undef FS_TYPE_EXT > +} I disagree - the logic should be not bound with the code. There is not such a way in U-Boot. Boards rely on the environment, and the hush shell does the rest, without hardcoding this into the board. This behavior is also wrong for another reason: this drives crazy anyone working with the shell. In fact, he can assume to define the behaviour using the environment, but this is overwritten by your code. > + > +#ifdef CONFIG_SPLASH_SCREEN > +int splash_screen_prepare(void) > +{ > + char *filename; > + const char *addr_str; > + u32 addr = 0; > +#ifdef CONFIG_SYS_USE_NAND > + char *s; > +#endif > + > + /* Get filename and load address from env */ > + addr_str = getenv("splashimage"); > + if (!addr_str) { > + return -1; > + } > + addr = simple_strtoul(addr_str, 0, 16); > + if (addr == 0) { > + printf("Error: bad splashimage value %s\n", addr_str); > + return -1; > + } > + filename = getenv("splash_filename"); > + if (!filename) { > + printf("Error: splashimage defined, but splash_filename isn't\n"); > + return -1; > + } > + > +#ifdef CONFIG_SYS_USE_NAND > + s = getenv("chosen_rootfs"); > + if ((s != NULL) && (!strcmp(s, "emmc"))) { > + if (var_load_file_from_mmc(addr, filename)) > + return -1; > + } else { > + if (var_load_file_from_nand(addr, filename)) > + return -1; > + } Ditto. All this logic must be not part of code. > +#else /* MMC */ > + if (var_load_file_from_mmc(addr, filename)) > + return -1; > +#endif > + > + /* Turn on backlight */ > + if (lvds_enabled) > + gpio_set_value(VAR_SOM_BACKLIGHT_EN, 1); And hardware-related part, as this one for backlight, are mixed with behaviour parts (setting rootfs, for example). > + > + return 0; > +} > +#endif > + > +static bool is_som_solo(void) > +{ > + bool ret; > + int oldbus = i2c_get_bus_num(); > + > + i2c_set_bus_num(PMIC_I2C_BUS); > + /* Probing for PMIC which is not preset only on som solo */ > + ret = (0 != i2c_probe(CONFIG_POWER_PFUZE100_I2C_ADDR)); > + > + i2c_set_bus_num(oldbus); > + return ret; If I understand from the title, you want to check if the CPU is a Solo or DL. But then, instead of reading the CPU-ID, as we expect, you check if you have a PMIC. It looks not straightforward. > +} > + > +static bool is_solo_custom_board(void) > +{ > + bool ret; > + int oldbus = i2c_get_bus_num(); > + > + i2c_set_bus_num(1); > + /* Probing for extra EEPROM present only on solo custom board */ > + ret = (0 == i2c_probe(0x51)); > + > + i2c_set_bus_num(oldbus); > + return ret; > +} > + > +static bool is_cpu_pop_package(void) > +{ > + uint soc_sbmr = readl(SRC_BASE_ADDR + 0x4); > + struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR; > + u32 reg; > + u32 type; > + > + reg = readl(&anatop->digprog); > + type = ((reg >> 16) & 0xff); > + if (type != MXC_CPU_MX6DL) > + return ((soc_sbmr & 0x200000) != 0); There are a lot of is_cpu_type() to check for SOC type. > + return false; > +} > + > +static inline bool is_dart_board(void) > +{ > + return is_cpu_pop_package(); > +} > + > +static inline bool is_mx6_custom_board(void) > +{ > + return (!is_dart_board() && !is_solo_custom_board()); > +} I do not know your board, but the way to select if this is the evaluation board or a custom board seems to me arguable. > + > +enum mmc_boot_device { > + SD_BOOT, > + MMC_BOOT, > + OTHER_BOOT, > +}; > + > +static unsigned get_mmc_boot_device(void) > +{ > + struct src *psrc = (struct src *)SRC_BASE_ADDR; > + unsigned reg = (readl(&psrc->sbmr1) >> 5) & 0x7; > + > + switch(reg) { > + case 0x2: > + return SD_BOOT; > + case 0x3: > + return MMC_BOOT; > + default: > + return OTHER_BOOT; > + } > +} > + > +static bool is_mmc_present(struct mmc *mmc) > +{ > + int err; > + struct mmc_cmd cmd; > + > + if (mmc->has_init) > + return true; > + > + mdelay(1); > + cmd.cmdidx = MMC_CMD_GO_IDLE_STATE; > + cmd.cmdarg = 0; > + cmd.resp_type = MMC_RSP_NONE; > + > + err = mmc->cfg->ops->send_cmd(mmc, &cmd, NULL); > + if (err) > + return false; > + > + mdelay(2); > + > + cmd.cmdidx = MMC_CMD_SEND_OP_COND; > + cmd.resp_type = MMC_RSP_R3; > + cmd.cmdarg = 0; > + > + err = mmc->cfg->ops->send_cmd(mmc, &cmd, NULL); > + return (!err); > +} No idea for that, this is already managed, including error branches, by common code in the MMC subsystem. > + > +static void print_emmc_size(void) > +{ > + struct mmc *mmc; > + int device; > + > + if (is_dart_board() && (MMC_BOOT == get_mmc_boot_device())) > + device=0; > + else > + device=1; This is another place where mmc order is set, leading to further confusion. > + > + mmc = find_mmc_device(device); > + if (!mmc || !is_mmc_present(mmc) || mmc_init(mmc) || IS_SD(mmc)) { > + puts("No eMMC\n"); > + return; > + } > + puts("eMMC: "); > + print_size(mmc->capacity, "\n"); > +} > + > +static u32 var_ram_size(void) > +{ > + u32 *p_ram_size = (u32 *)RAM_SIZE_ADDR; > + return *p_ram_size; > +} > + > +int dram_init(void) > +{ > + gd->ram_size = var_ram_size() * 1024 * 1024; > + return 0; > +} This is not the correct way to do it. U-Boot can detect the RAM on board using get_ram_size(). You have a var_rime_size() function, but this does not detect anything a returns a value defined at compiled time. Use get_ram_size() instead. > + > +static iomux_v3_cfg_t const uart1_pads[] = { > + IOMUX_PADS(PAD_CSI0_DAT10__UART1_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)), > + IOMUX_PADS(PAD_CSI0_DAT11__UART1_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)), > +}; > + > +static iomux_v3_cfg_t const enet_pads1[] = { > + IOMUX_PADS(PAD_ENET_MDIO__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL)), > + IOMUX_PADS(PAD_ENET_MDC__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL)), > + IOMUX_PADS(PAD_RGMII_TXC__RGMII_TXC | MUX_PAD_CTRL(ENET_PAD_CTRL)), > + IOMUX_PADS(PAD_RGMII_TD0__RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL)), > + IOMUX_PADS(PAD_RGMII_TD1__RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL)), > + IOMUX_PADS(PAD_RGMII_TD2__RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL)), > + IOMUX_PADS(PAD_RGMII_TD3__RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL)), > + IOMUX_PADS(PAD_RGMII_TX_CTL__RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL)), > + IOMUX_PADS(PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL)), > + /* pin 35 - 1 (PHY_AD2) on reset */ > + IOMUX_PADS(PAD_RGMII_RXC__GPIO6_IO30 | MUX_PAD_CTRL(NO_PAD_CTRL)), > + /* pin 32 - 1 - (MODE0) all */ > + IOMUX_PADS(PAD_RGMII_RD0__GPIO6_IO25 | MUX_PAD_CTRL(NO_PAD_CTRL)), > + /* pin 31 - 1 - (MODE1) all */ > + IOMUX_PADS(PAD_RGMII_RD1__GPIO6_IO27 | MUX_PAD_CTRL(NO_PAD_CTRL)), > + /* pin 28 - 1 - (MODE2) all */ > + IOMUX_PADS(PAD_RGMII_RD2__GPIO6_IO28 | MUX_PAD_CTRL(NO_PAD_CTRL)), > + /* pin 27 - 1 - (MODE3) all */ > + IOMUX_PADS(PAD_RGMII_RD3__GPIO6_IO29 | MUX_PAD_CTRL(NO_PAD_CTRL)), > + /* pin 33 - 1 - (CLK125_EN) 125Mhz clockout enabled */ > + IOMUX_PADS(PAD_RGMII_RX_CTL__GPIO6_IO24 | MUX_PAD_CTRL(NO_PAD_CTRL)), > + /* AR8031 PHY Reset */ > + IOMUX_PADS(PAD_ENET_CRS_DV__GPIO1_IO25 | MUX_PAD_CTRL(NO_PAD_CTRL)), > +}; > + > +static iomux_v3_cfg_t const enet_pads2[] = { > + IOMUX_PADS(PAD_RGMII_RXC__RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL)), > + IOMUX_PADS(PAD_RGMII_RD0__RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL)), > + IOMUX_PADS(PAD_RGMII_RD1__RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL)), > + IOMUX_PADS(PAD_RGMII_RD2__RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL)), > + IOMUX_PADS(PAD_RGMII_RD3__RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL)), > + IOMUX_PADS(PAD_RGMII_RX_CTL__RGMII_RX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL)), > +}; > + > +static void setup_iomux_enet(void) > +{ > + gpio_direction_output(IMX_GPIO_NR(1, 25), 0); /* Variscite SOM PHY reset */ > + gpio_direction_output(IMX_GPIO_NR(6, 30), 1); > + gpio_direction_output(IMX_GPIO_NR(6, 25), 1); > + gpio_direction_output(IMX_GPIO_NR(6, 27), 1); > + gpio_direction_output(IMX_GPIO_NR(6, 28), 1); > + gpio_direction_output(IMX_GPIO_NR(6, 29), 1); > + > + SETUP_IOMUX_PADS(enet_pads1); > + > + gpio_direction_output(IMX_GPIO_NR(6, 24), 1); > + > + /* Need delay 10ms according to KSZ9021 spec */ > + mdelay(10); > + gpio_set_value(IMX_GPIO_NR(1, 25), 1); > + > + SETUP_IOMUX_PADS(enet_pads2); > +} > + > +static iomux_v3_cfg_t const usdhc1_pads[] = { > + IOMUX_PADS(PAD_SD1_CLK__SD1_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > + IOMUX_PADS(PAD_SD1_CMD__SD1_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > + IOMUX_PADS(PAD_SD1_DAT0__SD1_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > + IOMUX_PADS(PAD_SD1_DAT1__SD1_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > + IOMUX_PADS(PAD_SD1_DAT2__SD1_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > + IOMUX_PADS(PAD_SD1_DAT3__SD1_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > +}; > + > + > +static iomux_v3_cfg_t const usdhc2_pads[] = { > + IOMUX_PADS(PAD_SD2_CLK__SD2_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > + IOMUX_PADS(PAD_SD2_CMD__SD2_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > + IOMUX_PADS(PAD_SD2_DAT0__SD2_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > + IOMUX_PADS(PAD_SD2_DAT1__SD2_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > + IOMUX_PADS(PAD_SD2_DAT2__SD2_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > + IOMUX_PADS(PAD_SD2_DAT3__SD2_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > +}; > + > +static iomux_v3_cfg_t const usdhc3_pads[] = { > + IOMUX_PADS(PAD_SD3_CLK__SD3_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > + IOMUX_PADS(PAD_SD3_CMD__SD3_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > + IOMUX_PADS(PAD_SD3_DAT0__SD3_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > + IOMUX_PADS(PAD_SD3_DAT1__SD3_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > + IOMUX_PADS(PAD_SD3_DAT2__SD3_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > + IOMUX_PADS(PAD_SD3_DAT3__SD3_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), > +}; > + > +#ifdef CONFIG_SYS_I2C_MXC > +I2C_PADS(i2c_pad_info1, > + PAD_CSI0_DAT9__I2C1_SCL | MUX_PAD_CTRL(I2C_PAD_CTRL), > + PAD_CSI0_DAT9__GPIO5_IO27 | MUX_PAD_CTRL(I2C_PAD_CTRL), > + IMX_GPIO_NR(5, 27), > + PAD_CSI0_DAT8__I2C1_SDA | MUX_PAD_CTRL(I2C_PAD_CTRL), > + PAD_CSI0_DAT8__GPIO5_IO26 | MUX_PAD_CTRL(I2C_PAD_CTRL), > + IMX_GPIO_NR(5, 26)); > + > +I2C_PADS(i2c_pad_info2, > + PAD_KEY_COL3__I2C2_SCL | MUX_PAD_CTRL(I2C_PAD_CTRL), > + PAD_KEY_COL3__GPIO4_IO12 | MUX_PAD_CTRL(I2C_PAD_CTRL), > + IMX_GPIO_NR(4, 12), > + PAD_KEY_ROW3__I2C2_SDA | MUX_PAD_CTRL(I2C_PAD_CTRL), > + PAD_KEY_ROW3__GPIO4_IO13 | MUX_PAD_CTRL(I2C_PAD_CTRL), > + IMX_GPIO_NR(4, 13)); > + > +I2C_PADS(i2c_pad_info3, > + PAD_GPIO_5__I2C3_SCL | MUX_PAD_CTRL(I2C_PAD_CTRL), > + PAD_GPIO_5__GPIO1_IO05 | MUX_PAD_CTRL(I2C_PAD_CTRL), > + IMX_GPIO_NR(1, 5), > + PAD_GPIO_16__I2C3_SDA | MUX_PAD_CTRL(I2C_PAD_CTRL), > + PAD_GPIO_16__GPIO7_IO11 | MUX_PAD_CTRL(I2C_PAD_CTRL), > + IMX_GPIO_NR(7, 11)); > +#endif > + > +void setup_local_i2c(void) { > + setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, I2C_PADS_INFO(i2c_pad_info1)); > + setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, I2C_PADS_INFO(i2c_pad_info2)); > + setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, I2C_PADS_INFO(i2c_pad_info3)); > +} > + > +iomux_v3_cfg_t const di0_pads[] = { > + IOMUX_PADS(PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK), /* DISP0_CLK */ > + IOMUX_PADS(PAD_DI0_PIN2__IPU1_DI0_PIN02), /* DISP0_HSYNC */ > + IOMUX_PADS(PAD_DI0_PIN3__IPU1_DI0_PIN03), /* DISP0_VSYNC */ > +}; > + Just these three pins for display ? Where are set the other ones ? > +static void var_setup_iomux_per_vcc_en(void) > +{ > + SETUP_IOMUX_PAD(PAD_EIM_D31__GPIO3_IO31 | MUX_PAD_CTRL(PER_VCC_EN_PAD_CTRL)); > + gpio_direction_output(IMX_GPIO_NR(3, 31), 1); > +} > + > +static void setup_iomux_uart(void) > +{ > + SETUP_IOMUX_PADS(uart1_pads); > +} > + > +#ifdef CONFIG_FSL_ESDHC > +struct fsl_esdhc_cfg usdhc_cfg[2] = { > + /* > + * This is incorrect for DART board but it's overwritten > + * in board_mmc_init() according to board setup > + */ > + {USDHC2_BASE_ADDR}, > + {USDHC1_BASE_ADDR}, > +}; > + > +int board_mmc_getcd(struct mmc *mmc) > +{ > + return 1; > +} I do not understand is_mmc_present() at all. U-Boot mmc subsystem sends already the commands to get if a mmc is present. You fix board_mmc_getcd(), but you have your own method instead of rely on common code. > + > +int board_mmc_init(bd_t *bis) > +{ > +#ifndef CONFIG_SPL_BUILD > + int ret; > + int i; > + > + /* > + * According to the board_mmc_init() the following map is done: > + * (U-Boot device node) (Physical Port) > + * On non DART boards: > + * mmc0 SD2 (SD) > + * mmc1 SD1 (eMMC) > + * > + * On DART board when booting from SD: > + * mmc0 SD2 (SD) > + * mmc1 SD3 (eMMC) > + * > + * On DART board when booting from eMMC: > + * mmc0 SD3 (eMMC) > + * mmc1 SD2 (SD) > + */ Why do you need to redefine the order depending from the boot device ? This makes things complicated and very confusing. Is it not much better to maintain the same enumeration ? > + for (i = 0; i < CONFIG_SYS_FSL_USDHC_NUM; i++) { > + switch (i) { > + case 0: > + if (is_dart_board() && (MMC_BOOT == get_mmc_boot_device())) { > + SETUP_IOMUX_PADS(usdhc3_pads); > + usdhc_cfg[0].esdhc_base = USDHC3_BASE_ADDR; > + usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK); > + } else { > + SETUP_IOMUX_PADS(usdhc2_pads); > + usdhc_cfg[0].esdhc_base = USDHC2_BASE_ADDR; > + usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK); > + } > + gd->arch.sdhc_clk = usdhc_cfg[0].sdhc_clk; > + usdhc_cfg[0].max_bus_width = 4; > + break; > + case 1: > + if (is_dart_board() && (MMC_BOOT == get_mmc_boot_device())) { > + SETUP_IOMUX_PADS(usdhc2_pads); > + usdhc_cfg[1].esdhc_base = USDHC2_BASE_ADDR; > + usdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK); > + } else if (is_dart_board()) { > + SETUP_IOMUX_PADS(usdhc3_pads); > + usdhc_cfg[1].esdhc_base = USDHC3_BASE_ADDR; > + usdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK); > + } else { > + SETUP_IOMUX_PADS(usdhc1_pads); > + usdhc_cfg[1].esdhc_base = USDHC1_BASE_ADDR; > + usdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK); > + } > + gd->arch.sdhc_clk = usdhc_cfg[1].sdhc_clk; > + usdhc_cfg[1].max_bus_width = 4; > + break; > + default: > + printf("Warning: you configured more USDHC controllers" > + "(%d) then supported by the board (%d)\n", > + i + 1, CONFIG_SYS_FSL_USDHC_NUM); > + return -EINVAL; > + } > + > + ret = fsl_esdhc_initialize(bis, &usdhc_cfg[i]); > + if (ret) > + return ret; > + } > + return 0; > +#else > + struct src *psrc = (struct src *)SRC_BASE_ADDR; > + unsigned reg = readl(&psrc->sbmr1) >> 11; > + /* > + * Upon reading BOOT_CFG register the following map is done: > + * Bit 11 and 12 of BOOT_CFG register can determine the current > + * mmc port > + * 0x1 SD2 (SD) > + * 0x2 SD3 (DART eMMC) > + */ > + > + switch (reg & 0x3) { > + case 0x1: > + SETUP_IOMUX_PADS(usdhc2_pads); > + usdhc_cfg[0].esdhc_base = USDHC2_BASE_ADDR; > + usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK); > + gd->arch.sdhc_clk = usdhc_cfg[0].sdhc_clk; > + usdhc_cfg[0].max_bus_width = 4; > + break; > + case 0x2: > + SETUP_IOMUX_PADS(usdhc3_pads); > + usdhc_cfg[0].esdhc_base = USDHC3_BASE_ADDR; > + usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK); > + gd->arch.sdhc_clk = usdhc_cfg[0].sdhc_clk; > + usdhc_cfg[0].max_bus_width = 4; > + break; > + } > + > + return fsl_esdhc_initialize(bis, &usdhc_cfg[0]); > +#endif > +} > +#endif > + > +#ifdef CONFIG_SYS_USE_NAND > +static iomux_v3_cfg_t const gpmi_pads[] = { > + IOMUX_PADS(PAD_NANDF_CLE__NAND_CLE | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), > + IOMUX_PADS(PAD_NANDF_ALE__NAND_ALE | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), > + IOMUX_PADS(PAD_NANDF_WP_B__NAND_WP_B | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), > + IOMUX_PADS(PAD_NANDF_RB0__NAND_READY_B | MUX_PAD_CTRL(GPMI_PAD_CTRL0)), > + IOMUX_PADS(PAD_NANDF_CS0__NAND_CE0_B | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), > + IOMUX_PADS(PAD_SD4_CMD__NAND_RE_B | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), > + IOMUX_PADS(PAD_SD4_CLK__NAND_WE_B | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), > + IOMUX_PADS(PAD_NANDF_D0__NAND_DATA00 | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), > + IOMUX_PADS(PAD_NANDF_D1__NAND_DATA01 | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), > + IOMUX_PADS(PAD_NANDF_D2__NAND_DATA02 | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), > + IOMUX_PADS(PAD_NANDF_D3__NAND_DATA03 | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), > + IOMUX_PADS(PAD_NANDF_D4__NAND_DATA04 | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), > + IOMUX_PADS(PAD_NANDF_D5__NAND_DATA05 | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), > + IOMUX_PADS(PAD_NANDF_D6__NAND_DATA06 | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), > + IOMUX_PADS(PAD_NANDF_D7__NAND_DATA07 | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), > + IOMUX_PADS(PAD_SD4_DAT0__NAND_DQS | MUX_PAD_CTRL(GPMI_PAD_CTRL1)), > +}; > + > +static void setup_gpmi_nand(void) > +{ > + struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; > + > + SETUP_IOMUX_PADS(gpmi_pads); > + > + /* gate ENFC_CLK_ROOT clock first,before clk source switch */ > + clrbits_le32(&mxc_ccm->CCGR2, MXC_CCM_CCGR2_IOMUX_IPT_CLK_IO_MASK); > + > + /* config gpmi and bch clock to 100 MHz */ > + clrsetbits_le32(&mxc_ccm->cs2cdr, > + MXC_CCM_CS2CDR_ENFC_CLK_PODF_MASK | > + MXC_CCM_CS2CDR_ENFC_CLK_PRED_MASK | > + MXC_CCM_CS2CDR_ENFC_CLK_SEL_MASK, > + MXC_CCM_CS2CDR_ENFC_CLK_PODF(0) | > + MXC_CCM_CS2CDR_ENFC_CLK_PRED(3) | > + MXC_CCM_CS2CDR_ENFC_CLK_SEL(3)); > + > + /* enable ENFC_CLK_ROOT clock */ > + setbits_le32(&mxc_ccm->CCGR2, MXC_CCM_CCGR2_IOMUX_IPT_CLK_IO_MASK); > + > + /* enable gpmi and bch clock gating */ > + setbits_le32(&mxc_ccm->CCGR4, > + MXC_CCM_CCGR4_RAWNAND_U_BCH_INPUT_APB_MASK | > + MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_BCH_MASK | > + MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_MASK | > + MXC_CCM_CCGR4_RAWNAND_U_GPMI_INPUT_APB_MASK | > + MXC_CCM_CCGR4_PL301_MX6QPER1_BCH_OFFSET); > + > + /* enable apbh clock gating */ > + setbits_le32(&mxc_ccm->CCGR0, MXC_CCM_CCGR0_APBHDMA_MASK); > +} > +#endif > + > +int board_phy_config(struct phy_device *phydev) > +{ > + /* min rx data delay */ > + ksz9021_phy_extended_write(phydev, > + MII_KSZ9021_EXT_RGMII_RX_DATA_SKEW, 0x0); > + /* min tx data delay */ > + ksz9021_phy_extended_write(phydev, > + MII_KSZ9021_EXT_RGMII_TX_DATA_SKEW, 0x0); > + /* max rx/tx clock delay, min rx/tx control */ > + ksz9021_phy_extended_write(phydev, > + MII_KSZ9021_EXT_RGMII_CLOCK_SKEW, 0xf0f0); > + > + if (phydev->drv->config) > + phydev->drv->config(phydev); > + > + return 0; > +} > + > +#if defined(CONFIG_VIDEO_IPUV3) > +static void disable_lvds(struct display_info_t const *dev) > +{ > + struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; > + > + int reg = readl(&iomux->gpr[2]); > + > + reg &= ~(IOMUXC_GPR2_LVDS_CH0_MODE_MASK | > + IOMUXC_GPR2_LVDS_CH1_MODE_MASK); > + > + writel(reg, &iomux->gpr[2]); > +} > + > +static void do_enable_hdmi(struct display_info_t const *dev) > +{ > + disable_lvds(dev); > + /* > + * imx_enable_hdmi_phy(); should be called here. > + * It is ommitted to avoid a current known bug where > + * the boot sometimes hangs if an HDMI cable is attached > + * - at least on some DART SOMs. > + */ > +} > + > +static void enable_lvds(struct display_info_t const *dev) > +{ > + struct iomuxc *iomux = (struct iomuxc *) > + IOMUXC_BASE_ADDR; > + u32 reg = readl(&iomux->gpr[2]); > + reg |= IOMUXC_GPR2_DATA_WIDTH_CH0_24BIT | > + IOMUXC_GPR2_DATA_WIDTH_CH1_18BIT; > + writel(reg, &iomux->gpr[2]); > + > + lvds_enabled=true; > +} > + > +static void lvds_enable_disable(struct display_info_t const *dev) > +{ > + if (getenv("splashimage") != NULL) > + enable_lvds(dev); > + else > + disable_lvds(dev); > +} > + > +static int detect_dart_vsc_display(struct display_info_t const *dev) > +{ > + return (!is_mx6_custom_board()); > +} > + > +static int detect_mx6cb_cdisplay(struct display_info_t const *dev) > +{ > + if (!is_mx6_custom_board()) > + return 0; > + > + i2c_set_bus_num(dev->bus); > + return (0 == i2c_probe(dev->addr)); > +} > + > +static int detect_mx6cb_rdisplay(struct display_info_t const *dev) > +{ > + if (!is_mx6_custom_board()) > + return 0; > + > + /* i2c probe the *c*display */ > + i2c_set_bus_num(MX6CB_CDISPLAY_I2C_BUS); > + return (0 != i2c_probe(MX6CB_CDISPLAY_I2C_ADDR)); > +} > + > +#define MHZ2PS(f) (1000000/(f)) > + > +struct display_info_t const displays[] = {{ > + .bus = -1, > + .addr = 0, > + .pixfmt = IPU_PIX_FMT_RGB24, > + .detect = detect_hdmi, > + .enable = do_enable_hdmi, > + .mode = { > + .name = "HDMI", > + .refresh = 60, > + .xres = 800, > + .yres = 480, > + .pixclock = 31777, > + .left_margin = 48, > + .right_margin = 16, > + .upper_margin = 33, > + .lower_margin = 10, > + .hsync_len = 96, > + .vsync_len = 2, > + .sync = 0, > + .vmode = FB_VMODE_NONINTERLACED > +} }, { > + .bus = -1, > + .addr = 0, > + .pixfmt = IPU_PIX_FMT_RGB666, > + .detect = detect_dart_vsc_display, > + .enable = lvds_enable_disable, > + .mode = { > + .name = "VAR-WVGA", > + .refresh = 60, /* optional */ > + .xres = 800, > + .yres = 480, > + .pixclock = MHZ2PS(50), > + .left_margin = 40, > + .right_margin = 40, > + .upper_margin = 29, > + .lower_margin = 13, > + .hsync_len = 48, > + .vsync_len = 3, > + .sync = FB_SYNC_EXT, > + .vmode = FB_VMODE_NONINTERLACED > +} }, { > + .bus = MX6CB_CDISPLAY_I2C_BUS, > + .addr = MX6CB_CDISPLAY_I2C_ADDR, > + .pixfmt = IPU_PIX_FMT_RGB24, > + .detect = detect_mx6cb_cdisplay, > + .enable = lvds_enable_disable, > + .mode = { > + .name = "VAR-WVGA MX6CB-C", > + .refresh = 60, /* optional */ > + .xres = 800, > + .yres = 480, > + .pixclock = MHZ2PS(50), > + .left_margin = 39, > + .right_margin = 39, > + .upper_margin = 29, > + .lower_margin = 13, > + .hsync_len = 128, > + .vsync_len = 2, > + .sync = FB_SYNC_EXT, > + .vmode = FB_VMODE_NONINTERLACED > +} }, { > + .bus = -1, > + .addr = 0, > + .pixfmt = IPU_PIX_FMT_RGB24, > + .detect = detect_mx6cb_rdisplay, > + .enable = lvds_enable_disable, > + .mode = { > + .name = "VAR-WVGA MX6CB-R", > + .refresh = 60, /* optional */ > + .xres = 800, > + .yres = 480, > + .pixclock = MHZ2PS(50), > + .left_margin = 0, > + .right_margin = 40, > + .upper_margin = 20, > + .lower_margin = 13, > + .hsync_len = 48, > + .vsync_len = 3, > + .sync = FB_SYNC_EXT, > + .vmode = FB_VMODE_NONINTERLACED > +} } }; > + > +size_t display_count = ARRAY_SIZE(displays); > + > +static void setup_display(void) > +{ > + struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; > + struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; > + int reg; > + > + /* Setup backlight */ > + SETUP_IOMUX_PAD(PAD_DISP0_DAT9__GPIO4_IO30 | MUX_PAD_CTRL(ENET_PAD_CTRL)); > + > + /* Turn off backlight until display is ready */ > + gpio_direction_output(VAR_SOM_BACKLIGHT_EN , 0); > + > + /* Setup HSYNC, VSYNC, DISP_CLK for debugging purposes */ > + SETUP_IOMUX_PADS(di0_pads); > + > + enable_ipu_clock(); > + imx_setup_hdmi(); > + > + /* Turn on LDB0, LDB1, IPU,IPU DI0 clocks */ > + reg = readl(&mxc_ccm->CCGR3); > + reg |= MXC_CCM_CCGR3_LDB_DI0_MASK | MXC_CCM_CCGR3_LDB_DI1_MASK; > + writel(reg, &mxc_ccm->CCGR3); > + > + /* set LDB0, LDB1 clk select to 011/011 */ > + reg = readl(&mxc_ccm->cs2cdr); > + reg &= ~(MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK > + | MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_MASK); > + /* 1 -> ~50MHz , 2 -> ~56MHz, 3 -> ~75MHz, 4 -> ~68MHz */ > + reg |= (1 << MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET) > + | (1 << MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_OFFSET); > + writel(reg, &mxc_ccm->cs2cdr); > + > + reg = readl(&mxc_ccm->cscmr2); > + reg |= MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV | MXC_CCM_CSCMR2_LDB_DI1_IPU_DIV; > + writel(reg, &mxc_ccm->cscmr2); > + > + reg = readl(&mxc_ccm->chsccdr); > + reg |= (CHSCCDR_CLK_SEL_LDB_DI0 > + << MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET); > + reg |= (CHSCCDR_CLK_SEL_LDB_DI0 > + << MXC_CCM_CHSCCDR_IPU1_DI1_CLK_SEL_OFFSET); > + writel(reg, &mxc_ccm->chsccdr); > + > + reg = IOMUXC_GPR2_BGREF_RRMODE_EXTERNAL_RES > + | IOMUXC_GPR2_DI1_VS_POLARITY_ACTIVE_LOW > + | IOMUXC_GPR2_DI0_VS_POLARITY_ACTIVE_LOW > + | IOMUXC_GPR2_BIT_MAPPING_CH1_SPWG > + | IOMUXC_GPR2_DATA_WIDTH_CH1_18BIT > + | IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG > + | IOMUXC_GPR2_DATA_WIDTH_CH0_24BIT > + | IOMUXC_GPR2_LVDS_CH0_MODE_ENABLED_DI0 > + | IOMUXC_GPR2_LVDS_CH1_MODE_ENABLED_DI0; > + writel(reg, &iomux->gpr[2]); > + > + reg = readl(&iomux->gpr[3]); > + reg = (reg & ~(IOMUXC_GPR3_LVDS1_MUX_CTL_MASK > + | IOMUXC_GPR3_HDMI_MUX_CTL_MASK)) > + | (IOMUXC_GPR3_MUX_SRC_IPU1_DI0 > + << IOMUXC_GPR3_LVDS1_MUX_CTL_OFFSET); > + writel(reg, &iomux->gpr[3]); > +} > +#endif /* CONFIG_VIDEO_IPUV3 */ > + > +/* > + * Do not overwrite the console > + * Use always serial for U-Boot console > + */ > +int overwrite_console(void) > +{ > + return 1; > +} > + > +int board_eth_init(bd_t *bis) > +{ > + uint32_t base = IMX_FEC_BASE; > + struct mii_dev *bus = NULL; > + struct phy_device *phydev = NULL; > + int ret; > + > + setup_iomux_enet(); > + > +#ifdef CONFIG_FEC_MXC > + bus = fec_get_miibus(base, -1); > + > + if (!bus) { > + printf("FEC MXC bus: %s:failed\n", __func__); > + return 0; > + } > + /* "scan" phy 7 */ > + phydev = phy_find_by_mask(bus, (0x1 << 7), << CONFIG_FEC_MXC_PHYADDR PHY_INTERFACE_MODE_RGMII); > + if (!phydev) { > + printf("FEC MXC phy find: %s:failed\n", __func__); > + free(bus); > + return 0; > + } > + printf("using phy at %d\n", phydev->addr); > + > + ret = fec_probe(bis, -1, base, bus, phydev); > + if (ret) { > + printf("FEC MXC probe: %s:failed\n", __func__); > + free(phydev); > + free(bus); > + } > +#endif > + > +#ifdef CONFIG_USB_ETHER > + /* OTG - Ethernet Gadget */ Is it not CONFIG_CI_UDC ? If it runs as gadget.. > + usb_eth_initialize(bis); > +#endif > + > + return 0; > +} > + > +#ifdef CONFIG_USB_EHCI_MX6 > +#define VSC_USB_H1_PWR_EN IMX_GPIO_NR(4, 15) > +#define VSC_USB_OTG_PWR_EN IMX_GPIO_NR(3, 22) > +#define DART_USB_H1_PWR_EN IMX_GPIO_NR(1, 28) > +#define DART_USB_OTG_PWR_EN IMX_GPIO_NR(4, 15) > + > +static void setup_usb(void) > +{ > + if (is_dart_board()) { > + /* config OTG ID iomux */ > + SETUP_IOMUX_PAD(PAD_ENET_RX_ER__USB_OTG_ID | MUX_PAD_CTRL(OTG_ID_PAD_CTRL)); > + imx_iomux_set_gpr_register(1, 13, 1, 0); > + > + SETUP_IOMUX_PAD(PAD_KEY_ROW4__GPIO4_IO15 | MUX_PAD_CTRL(NO_PAD_CTRL)); > + gpio_direction_output(DART_USB_OTG_PWR_EN, 0); > + > + SETUP_IOMUX_PAD(PAD_ENET_TX_EN__GPIO1_IO28 | MUX_PAD_CTRL(NO_PAD_CTRL)); > + gpio_direction_output(DART_USB_H1_PWR_EN, 0); > + } else if (is_solo_custom_board()) { > + /* config OTG ID iomux */ > + SETUP_IOMUX_PAD(PAD_GPIO_1__USB_OTG_ID | MUX_PAD_CTRL(OTG_ID_PAD_CTRL)); > + imx_iomux_set_gpr_register(1, 13, 1, 1); > + > + SETUP_IOMUX_PAD(PAD_EIM_D22__GPIO3_IO22 | MUX_PAD_CTRL(NO_PAD_CTRL)); > + gpio_direction_output(VSC_USB_OTG_PWR_EN, 0); > + > + SETUP_IOMUX_PAD(PAD_KEY_ROW4__GPIO4_IO15 | MUX_PAD_CTRL(NO_PAD_CTRL)); > + gpio_direction_output(VSC_USB_H1_PWR_EN, 0); You set multiple pins here, and this can be written in a much more readable way. If you see in all code (as well as you use later), there is like a template: - array with pin configuration for a function - calling iomux_setup.. to make the configuration active. This can be done as: board = is_dart_board() .....; pin_config = usb_pin_cfg[board]; /* Multiple array, one for board*/ imx_iomux_v3_setup_multiple_pads(pin_config,...) most code here is duplicated > + } > +} > + > +int board_usb_phy_mode(int port) > +{ > + char *s; > + if (is_mx6_custom_board() && port==0) { > + s = getenv("usbmode"); > + if ((s != NULL) && (!strcmp(s, "host"))) > + return USB_INIT_HOST; > + else > + return USB_INIT_DEVICE; > + } > + return usb_phy_mode(port); > +} > + > +/* > + * int board_ehci_hcd_init(int port) > + * { > + * if (is_dart_board() || is_solo_custom_board()) { > + * no hub to reset > + * } else if (is_mx6_custom_board()) { > + * hub present but pulled up > + * } > + * > + * return 0; > + * } > + */ Drop all dead code, it cannot be mainlined. > + > +int board_ehci_power(int port, int on) > +{ > + if (is_mx6_custom_board()) > + return 0; /* no power enable needed */ > + > + if (port > 1) > + return -EINVAL; > + > + if (port) { > + if (is_dart_board()) > + gpio_set_value(DART_USB_H1_PWR_EN, on); > + else if (is_solo_custom_board()) > + gpio_set_value(VSC_USB_H1_PWR_EN, on); > + } else { > + if (is_dart_board()) > + gpio_set_value(DART_USB_OTG_PWR_EN, on); > + else if (is_solo_custom_board()) > + gpio_set_value(VSC_USB_OTG_PWR_EN, on); > + } > + > + return 0; > +} > +#endif /* CONFIG_USB_EHCI_MX6 */ > + > +int board_early_init_f(void) > +{ > + var_setup_iomux_per_vcc_en(); > + > + setup_iomux_uart(); > +#if defined(CONFIG_VIDEO_IPUV3) > + setup_display(); > +#endif > +#ifdef CONFIG_SYS_I2C_MXC > + setup_local_i2c(); > +#endif > +#ifdef CONFIG_SYS_USE_NAND > + setup_gpmi_nand(); > +#endif > + > + return 0; > +} > + > +int board_init(void) > +{ > + int ret = 0; > + > + /* address of boot parameters */ > + gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100; > + gd->bd->bi_arch_number = CONFIG_MACH_VAR_SOM_MX6; Still needed ? > + > +#ifdef CONFIG_USB_EHCI_MX6 > + setup_usb(); > +#endif > + return ret; > +} > + > +static struct pmic *pfuze; > + > +static void set_anatop_bypass(void) > +{ > + struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR; > + u32 reg = readl(&anatop->reg_core); > + > + /* bypass VDDARM/VDDSOC */ > + reg |= (0x1F << 18) | 0x1F; Use constants instead of hex values - this must be fixed in all code. > + writel(reg, &anatop->reg_core); > +} > + > +static void ldo_mode_set(void) > +{ > + if (!is_som_solo()) { > + unsigned int reg; > + struct pmic *p = pfuze; > + int retval = 0; > + > + if (!p) { > + printf("No PMIC found!\n"); > + return; > + } > + > + /* Set SW1AB to 1.325V */ > + retval += pmic_reg_read(p, PFUZE100_SW1ABVOL, ®); > + reg &= ~SW1x_NORMAL_MASK; > + reg |= SW1x_1_325V; > + retval += pmic_reg_write(p, PFUZE100_SW1ABVOL, reg); > + > + /* Set SW1C to 1.325V */ > + retval += pmic_reg_read(p, PFUZE100_SW1CVOL, ®); > + reg &= ~SW1x_NORMAL_MASK; > + reg |= SW1x_1_325V; > + retval += pmic_reg_write(p, PFUZE100_SW1CVOL, reg); > + > + if (retval) { > + printf("PMIC write voltages error!\n"); > + return; > + } > + > + set_anatop_bypass(); > + printf("switch to ldo_bypass mode!\n"); > + } > +} > + > +int power_init_board(void) > +{ > + if (!is_som_solo()) { > + unsigned int reg; > + int retval; > + > + retval = power_pfuze100_init(PMIC_I2C_BUS); > + if (retval) > + return -ENODEV; > + pfuze = pmic_get("PFUZE100"); > + retval = pmic_probe(pfuze); > + if (retval) > + return -ENODEV; > + pmic_reg_read(pfuze, PFUZE100_DEVICEID, ®); > + printf("PMIC: PFUZE100 ID=0x%02x\n", reg); > + > + if (!is_dart_board()) { > + > + /* Set Gigbit Ethernet voltage (SOM v1.1/1.0) */ > + retval += pmic_reg_read(pfuze, PFUZE100_SW4VOL, ®); > + reg &= ~0x7f; > + reg |= 0x60; /* 2.4V */ > + retval += pmic_reg_write(pfuze, PFUZE100_SW4VOL, reg); > + > + /* Increase VGEN5 from 2.8 to 3V */ > + retval += pmic_reg_read(pfuze, PFUZE100_VGEN5VOL, ®); > + reg &= ~LDO_VOL_MASK; > + reg |= LDOB_3_00V; > + retval += pmic_reg_write(pfuze, PFUZE100_VGEN5VOL, reg); > + > + /* Set SW1AB standby volage to 0.975V */ > + retval += pmic_reg_read(pfuze, PFUZE100_SW1ABSTBY, ®); > + reg &= ~SW1x_STBY_MASK; > + reg |= SW1x_0_975V; > + retval += pmic_reg_write(pfuze, PFUZE100_SW1ABSTBY, reg); > + > + /* Set SW1AB/VDDARM step ramp up time from 16us to 4us/25mV */ > + retval += pmic_reg_read(pfuze, PFUZE100_SW1ABCONF, ®); > + reg &= ~SW1xCONF_DVSSPEED_MASK; > + reg |= SW1xCONF_DVSSPEED_4US; > + retval += pmic_reg_write(pfuze, PFUZE100_SW1ABCONF, reg); > + > + /* Set SW1C standby voltage to 0.975V */ > + retval += pmic_reg_read(pfuze, PFUZE100_SW1CSTBY, ®); > + reg &= ~SW1x_STBY_MASK; > + reg |= SW1x_0_975V; > + retval += pmic_reg_write(pfuze, PFUZE100_SW1CSTBY, reg); > + > +#ifdef LOW_POWER_MODE_ENABLE > + /* Set low power mode voltages to disable */ > + > + /* Set SW3A standby voltage to 1.275V */ > + retval += pmic_reg_read(pfuze, PFUZE100_SW3ASTBY, ®); > + reg &= ~0x7f; /* SW3x STBY MASK */ > + reg = 0x23; /* SW3x 1.275V */ > + retval += pmic_reg_write(pfuze, PFUZE100_SW3ASTBY, reg); > + > + /* Set SW3A off voltage to 1.275V */ > + retval += pmic_reg_read(pfuze, PFUZE100_SW3AOFF, ®); > + reg &= ~0x7f; /* SW3x OFF MASK */ > + reg = 0x23; /* SW3x 1.275V */ > + retval += pmic_reg_write(pfuze, PFUZE100_SW3AOFF, reg); > + > + /* Set SW2 to 3.2V */ > + retval += pmic_reg_read(pfuze, PFUZE100_SW2VOL, ®); > + reg &= ~0x7f; > + reg |= 0x70; /* SW2x 3.2V */ > + retval += pmic_reg_write(pfuze, PFUZE100_SW2VOL, reg); > + > + /* SW4MODE = OFF in standby */ > + reg = PWM_OFF; > + retval += pmic_reg_write(pfuze, PFUZE100_SW4MODE, reg); > + > + /* Set VGEN3 to 2.5V, VGEN3CTL = OFF in standby */ > + retval += pmic_reg_read(pfuze, PFUZE100_VGEN3VOL, ®); > + reg &= ~0x7f; > + reg |= 0x30; /* VGEN3EN, VGEN3STBY, ~VGEN3LPWR */ > + reg |= LDOB_2_50V; > + retval += pmic_reg_write(pfuze, PFUZE100_VGEN3VOL, reg); > +#else > + /* Set VGEN3 to 2.5V, VGEN3CTL = low power in standby */ > + retval += pmic_reg_read(pfuze, PFUZE100_VGEN3VOL, ®); > + reg &= ~0x7f; > + reg |= 0x70; /* VGEN3EN, VGEN3STBY, VGEN3LPWR */ > + reg |= LDOB_2_50V; > + retval += pmic_reg_write(pfuze, PFUZE100_VGEN3VOL, reg); > +#endif > + } else { > + > + /* Set SW1AB standby volage to 0.9V */ > + retval += pmic_reg_read(pfuze, PFUZE100_SW1ABSTBY, ®); > + reg &= ~SW1x_STBY_MASK; > + reg |= SW1x_0_900V; > + retval += pmic_reg_write(pfuze, PFUZE100_SW1ABSTBY, reg); > + > + /* Set SW1AB off volage to 0.9V */ > + retval += pmic_reg_read(pfuze, PFUZE100_SW1ABOFF, ®); > + reg &= ~SW1x_OFF_MASK; > + reg |= SW1x_0_900V; > + retval += pmic_reg_write(pfuze, PFUZE100_SW1ABOFF, reg); > + > + /* Set SW1C standby voltage to 0.9V */ > + retval += pmic_reg_read(pfuze, PFUZE100_SW1CSTBY, ®); > + reg &= ~SW1x_STBY_MASK; > + reg |= SW1x_0_900V; > + retval += pmic_reg_write(pfuze, PFUZE100_SW1CSTBY, reg); > + > + /* Set SW1C off volage to 0.9V */ > + retval += pmic_reg_read(pfuze, PFUZE100_SW1COFF, ®); > + reg &= ~SW1x_OFF_MASK; > + reg |= SW1x_0_900V; > + retval += pmic_reg_write(pfuze, PFUZE100_SW1COFF, reg); > + > + /* Set SW2 to 3.3V */ > + retval += pmic_reg_read(pfuze, PFUZE100_SW2VOL, ®); > + reg &= ~0x7f; /* SW2x NORMAL MASK */ > + reg |= 0x72; /* SW2x 3.3V */ > + retval += pmic_reg_write(pfuze, PFUZE100_SW2VOL, reg); > + > + /* Set SW2 standby voltage to 3.2V */ > + retval += pmic_reg_read(pfuze, PFUZE100_SW2STBY, ®); > + reg &= ~0x7f; /* SW2x STBY MASK */ > + reg |= 0x70; /* SW2x 3.2V */ > + retval += pmic_reg_write(pfuze, PFUZE100_SW2STBY, reg); > + > + /* Set SW2 off voltage to 3.2V */ > + retval += pmic_reg_read(pfuze, PFUZE100_SW2OFF, ®); > + reg &= ~0x7f; /* SW2x OFF MASK */ > + reg |= 0x70; /* SW2x 3.2V */ > + retval += pmic_reg_write(pfuze, PFUZE100_SW2OFF, reg); > + > + reg = PWM_PFM; > + retval += pmic_reg_write(pfuze, PFUZE100_SW1ABMODE, reg); > + > + /* Set SW1AB/VDDARM step ramp up time 2us */ > + retval += pmic_reg_read(pfuze, PFUZE100_SW1ABCONF, ®); > + reg &= ~SW1xCONF_DVSSPEED_MASK; > + reg |= SW1xCONF_DVSSPEED_2US; > + retval += pmic_reg_write(pfuze, PFUZE100_SW1ABCONF, reg); > + > + reg = PWM_PFM; > + retval += pmic_reg_write(pfuze, PFUZE100_SW1CMODE, reg); > + > + reg = PWM_PFM; > + retval += pmic_reg_write(pfuze, PFUZE100_SW2MODE, reg); > + > + reg = LDOB_3_30V; > + retval += pmic_reg_write(pfuze, PFUZE100_VGEN6VOL, reg); > + } > + You have to factoritze the common code and handle in case just the differences, instead of copying the all code twice. > + /* Set SW1C/VDDSOC step ramp up time from 16us to 4us/25mV */ > + retval += pmic_reg_read(pfuze, PFUZE100_SW1CCONF, ®); > + reg &= ~SW1xCONF_DVSSPEED_MASK; > + reg |= SW1xCONF_DVSSPEED_4US; > + retval += pmic_reg_write(pfuze, PFUZE100_SW1CCONF, reg); > + > + if (retval) { > + printf("PMIC write voltages error!\n"); > + return -1; > + } > + > + ldo_mode_set(); > + } > + > + return 0; > +} > + > +static void update_env(void) > +{ > + setenv("mmcroot" , "/dev/mmcblk0p2 rootwait rw"); > + if (is_cpu_type(MXC_CPU_MX6Q)) { > + if (is_dart_board()) { > + setenv("fdt_file", "imx6q-var-dart.dtb"); > + if (MMC_BOOT == get_mmc_boot_device()) > + setenv("mmcroot" , "/dev/mmcblk2p2 rootwait rw"); > + else > + setenv("mmcroot" , "/dev/mmcblk1p2 rootwait rw"); > + } else { > + if (is_solo_custom_board()) > + setenv("fdt_file", "imx6q-var-som-vsc.dtb"); > + else > + setenv("fdt_file", "imx6q-var-som.dtb"); > + } > + } else if (is_cpu_type(MXC_CPU_MX6D)) { > + if (is_dart_board()) { > + setenv("fdt_file", "imx6q-var-dart.dtb"); > + if (MMC_BOOT == get_mmc_boot_device()) > + setenv("mmcroot" , "/dev/mmcblk2p2 rootwait rw"); > + else > + setenv("mmcroot" , "/dev/mmcblk1p2 rootwait rw"); > + } else { > + setenv("fdt_file", "imx6q-var-som.dtb"); > + } > + } else if (is_cpu_type(MXC_CPU_MX6DL)) { > + if (is_som_solo()) { > + if (is_solo_custom_board()) > + setenv("fdt_file", "imx6dl-var-som-solo-vsc.dtb"); > + else > + setenv("fdt_file", "imx6dl-var-som-solo.dtb"); > + } else { > + setenv("fdt_file", "imx6dl-var-som.dtb"); > + } > + } else if (is_cpu_type(MXC_CPU_MX6SOLO)) { > + if (is_som_solo()) { > + if (is_solo_custom_board()) > + setenv("fdt_file", "imx6dl-var-som-solo-vsc.dtb"); > + else > + setenv("fdt_file", "imx6dl-var-som-solo.dtb"); > + } else { > + setenv("fdt_file", "imx6dl-var-som.dtb"); > + } > + } > +} > + This function is against the way U-Boot handle this, and it will be rejected - take a look at the script capabilities in U-Boot, it seems you do not like them at all ! > +static void imx6_pcie_assert_core_reset(void) > +{ > + struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR; > + > + if (is_mx6dqp()) > + setbits_le32(&iomuxc_regs->gpr[1], IOMUXC_GPR1_PCIE_SW_RST); > + > + setbits_le32(&iomuxc_regs->gpr[1], IOMUXC_GPR1_TEST_POWERDOWN); > + clrbits_le32(&iomuxc_regs->gpr[1], IOMUXC_GPR1_REF_SSP_EN); > +} > + > +static void imx6_pcie_init_phy(void) > +{ > + struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR; > + > + clrbits_le32(&iomuxc_regs->gpr[12], IOMUXC_GPR12_APPS_LTSSM_ENABLE); > + > + clrsetbits_le32(&iomuxc_regs->gpr[12], > + IOMUXC_GPR12_DEVICE_TYPE_MASK, > + IOMUXC_GPR12_DEVICE_TYPE_RC); > + clrsetbits_le32(&iomuxc_regs->gpr[12], > + IOMUXC_GPR12_LOS_LEVEL_MASK, > + IOMUXC_GPR12_LOS_LEVEL_9); > + > + writel((0x0 << IOMUXC_GPR8_PCS_TX_DEEMPH_GEN1_OFFSET) | > + (0x0 << IOMUXC_GPR8_PCS_TX_DEEMPH_GEN2_3P5DB_OFFSET) | > + (20 << IOMUXC_GPR8_PCS_TX_DEEMPH_GEN2_6DB_OFFSET) | > + (127 << IOMUXC_GPR8_PCS_TX_SWING_FULL_OFFSET) | > + (127 << IOMUXC_GPR8_PCS_TX_SWING_LOW_OFFSET), > + &iomuxc_regs->gpr[8]); > +} > + > +static void imx6_pcie_deassert_core_reset(void) > +{ > + struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR; > + > + if (is_mx6dqp()) > + clrbits_le32(&iomuxc_regs->gpr[1], IOMUXC_GPR1_PCIE_SW_RST); > + > + /* > + * Wait for the clock to settle a bit, when the clock are sourced > + * from the CPU, we need about 30 ms to settle. > + */ > + mdelay(50); > + > + /* Enable PCIe */ > + clrbits_le32(&iomuxc_regs->gpr[1], IOMUXC_GPR1_TEST_POWERDOWN); > + setbits_le32(&iomuxc_regs->gpr[1], IOMUXC_GPR1_REF_SSP_EN); > +} > + > +/* > + * Resets the PCIe controller in order to prevent a soft reboot hang > + */ > +static void imx_pcie_reset(void) > +{ > + imx6_pcie_assert_core_reset(); > + imx6_pcie_init_phy(); > + imx6_pcie_deassert_core_reset(); > +} > + > +int board_late_init(void) > +{ > + char *s; > + > + print_emmc_size(); > + > + s = getenv("var_auto_env"); > + if (s[0] == 'Y') > + update_env(); > + > + imx_pcie_reset(); > + > + return 0; > +} > + > +int checkboard(void) > +{ > + puts("Board: Variscite VAR-SOM-MX6 "); > + > + if (is_cpu_type(MXC_CPU_MX6Q)) { > + puts("Quad"); > + if (is_cpu_pop_package()) > + puts("-POP"); > + > + } else if (is_cpu_type(MXC_CPU_MX6D)) { > + puts("Dual"); > + if (is_cpu_pop_package()) > + puts("-POP"); > + > + } else if (is_cpu_type(MXC_CPU_MX6DL)) { > + if (is_som_solo()) > + puts("SOM-Dual"); > + else > + puts("Dual Lite"); > + > + } else if (is_cpu_type(MXC_CPU_MX6SOLO)) { > + if (is_som_solo()) > + puts("SOM-Solo"); > + else > + puts("Solo"); > + } else > + puts("????"); > + > + puts("\n"); > + return 0; > +} > + > +#ifdef CONFIG_SPL_BUILD > +#include <spl.h> > +#include <libfdt.h> > +#include <asm/arch/mx6-ddr.h> > +#include "mx6var_eeprom.h" > +#include "mx6var_eeprom_v2.h" > + > +/* > + * Writes RAM size to RAM_SIZE_ADDR so U-Boot can read it > + */ > +static void var_set_ram_size(u32 ram_size) > +{ > + u32 *p_ram_size = (u32 *)RAM_SIZE_ADDR; > + if (ram_size > 3840) > + ram_size=3840; > + *p_ram_size = ram_size; > +} > + > +static void print_board_info(int eeprom_rev, void* var_eeprom, u32 ram_size) > +{ > + u32 boot_device; > + u32 max_freq; > + > + printf("\ni.MX%s SOC P-%s\n", get_imx_type(get_cpu_type()), \ > + is_cpu_pop_package() ? "POP" : "STD"); > + > + max_freq = get_cpu_speed_grade_hz(); > + if (!max_freq) > + printf("CPU running at %dMHz\n", mxc_get_clock(MXC_ARM_CLK) / 1000000); > + else > + printf("%d MHz CPU (running at %d MHz)\n", max_freq / 1000000, > + mxc_get_clock(MXC_ARM_CLK) / 1000000); > + > + if (eeprom_rev==1) > + var_eeprom_strings_print((struct var_eeprom_cfg *) var_eeprom); > + else if (eeprom_rev==2) > + var_eeprom_v2_strings_print((struct var_eeprom_v2_cfg *) var_eeprom); > + else > + return; > + > + printf("RAM: "); > + print_size(ram_size * 1024 * 1024, "\n"); > + > + printf("Boot Device: "); > + boot_device = spl_boot_device(); > + switch (boot_device) { > + case BOOT_DEVICE_MMC1: > + switch (get_mmc_boot_device()) { > + case SD_BOOT: > + printf("MMC0 (SD)\n"); > + break; > + case MMC_BOOT: > + printf("MMC1 (DART eMMC)\n"); > + break; > + default: > + printf("MMC?\n"); > + break; > + } > + break; > + > + case BOOT_DEVICE_NAND: > + printf("NAND\n"); > + break; > + > + default: > + printf("UNKNOWN (%d)\n", boot_device); > + break; > + } > +} > + > +static int spl_dram_init_by_eeprom(void) > +{ > + struct var_eeprom_cfg var_eeprom_cfg = {{0}}; > + int ret; > + > + ret = var_eeprom_read_struct(&var_eeprom_cfg); > + if (ret) > + return SPL_DRAM_INIT_STATUS_ERROR_NO_EEPROM; > + > + /* is valid Variscite EEPROM? */ > + if (!var_eeprom_is_valid(&var_eeprom_cfg)) > + return SPL_DRAM_INIT_STATUS_ERROR_NO_EEPROM_STRUCT_DETECTED; > + > + switch (get_cpu_type()) { > + case MXC_CPU_MX6DL: > + case MXC_CPU_MX6SOLO: > + var_eeprom_mx6dlsl_dram_setup_iomux_from_struct(&var_eeprom_cfg.pinmux_group); > + break; > + case MXC_CPU_MX6Q: > + case MXC_CPU_MX6D: > + default: > + var_eeprom_mx6qd_dram_setup_iomux_from_struct(&var_eeprom_cfg.pinmux_group); > + break; > + } > + > + var_eeprom_dram_init_from_struct(&var_eeprom_cfg); > + > + var_set_ram_size(var_eeprom_cfg.header.ddr_size); > + print_board_info(1, (void*) &var_eeprom_cfg, var_eeprom_cfg.header.ddr_size); > + > + return SPL_DRAM_INIT_STATUS_OK; > +} > + > +/* > + * Bugfix: Fix Freescale wrong processor documentation. > + */ > +static void spl_mx6qd_dram_setup_iomux_check_reset(void) > +{ > + volatile struct mx6dq_iomux_ddr_regs *mx6q_ddr_iomux; > + u32 cputype = get_cpu_type(); > + > + if ((cputype == MXC_CPU_MX6D) || (cputype == MXC_CPU_MX6Q)) { > + mx6q_ddr_iomux = (struct mx6dq_iomux_ddr_regs *) MX6DQ_IOM_DDR_BASE; > + > + if (mx6q_ddr_iomux->dram_reset == (u32)0x000C0030) > + mx6q_ddr_iomux->dram_reset = (u32)0x00000030; > + } > +} > + > +static void ccgr_init(void) > +{ > + struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; > + > + writel(0x00C03F3F, &ccm->CCGR0); > + writel(0x0030FC03, &ccm->CCGR1); > + writel(0x0FFFC000, &ccm->CCGR2); > + writel(0x3FF00000, &ccm->CCGR3); > + writel(0x00FFF300, &ccm->CCGR4); > + writel(0x0F0000C3, &ccm->CCGR5); > + writel(0x000003FF, &ccm->CCGR6); > +} > + > +static void gpr_init(void) > +{ > + struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; > + > + /* enable AXI cache for VDOA/VPU/IPU */ > + writel(0xF00000CF, &iomux->gpr[4]); > + /* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */ > + writel(0x007F007F, &iomux->gpr[6]); > + writel(0x007F007F, &iomux->gpr[7]); > +} > + > +static int spl_dram_init_by_eeprom_v2(void) > +{ > + u32 ram_addresses[MAXIMUM_RAM_ADDRESSES]; > + u32 ram_values[MAXIMUM_RAM_VALUES]; > + struct var_eeprom_v2_cfg var_eeprom_v2_cfg = {0}; > + int ret, ram_size; > + > + ret = var_eeprom_v2_read_struct(&var_eeprom_v2_cfg, \ > + is_dart_board() ? VAR_DART_EEPROM_CHIP : VAR_MX6_EEPROM_CHIP); > + > + if (ret) > + return SPL_DRAM_INIT_STATUS_ERROR_NO_EEPROM; > + > + if (!var_eeprom_v2_is_valid(&var_eeprom_v2_cfg)) > + return SPL_DRAM_INIT_STATUS_ERROR_NO_EEPROM_STRUCT_DETECTED; > + > + handle_eeprom_data(&var_eeprom_v2_cfg, ram_addresses, ram_values); > + > + ram_size = var_eeprom_v2_cfg.ddr_size * 128; > + var_set_ram_size(ram_size); > + print_board_info(2, (void*) &var_eeprom_v2_cfg, ram_size); > + return SPL_DRAM_INIT_STATUS_OK; > +} > + > +static void spl_dram_init(void) > +{ > + int status; > + > + status = spl_dram_init_by_eeprom(); > + if (status != SPL_DRAM_INIT_STATUS_OK) { > + status = spl_dram_init_by_eeprom_v2(); > + if (status != SPL_DRAM_INIT_STATUS_OK) { > + printf("Error initializing RAM using EEPROM\n"); > + hang(); > + } > + } > + spl_mx6qd_dram_setup_iomux_check_reset(); > +} > + > +void board_init_f(ulong dummy) > +{ > + /* setup AIPS and disable watchdog */ > + arch_cpu_init(); > + > + ccgr_init(); > + gpr_init(); > + > + /* iomux and setup of i2c */ > + board_early_init_f(); > + > + /* setup GP timer */ > + timer_init(); > + > + /* Wait 330ms before starting to print to console */ > + mdelay(330); > + > + /* UART clocks enabled and gd valid - init serial console */ > + preloader_console_init(); > + > + /* DDR initialization */ > + spl_dram_init(); > + > + /* Clear the BSS. */ > + memset(__bss_start, 0, __bss_end - __bss_start); > + > + /* load/boot image from boot device */ > + board_init_r(NULL, 0); > +} > +#endif > diff --git a/board/variscite/mx6var_som/u-boot-spl.lds b/board/variscite/mx6var_som/u-boot-spl.lds > new file mode 100644 > index 0000000..33d8406 > --- /dev/null > +++ b/board/variscite/mx6var_som/u-boot-spl.lds > @@ -0,0 +1,59 @@ > +/* > + * (C) Copyright 2002 > + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> > + * > + * (C) Copyright 2010 > + * Texas Instruments, <www.ti.com> > + * Aneesh V <aneesh@ti.com> > + * > + * Copyright (C) 2016 Variscite Ltd. All Rights Reserved. > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE,\ > + LENGTH = CONFIG_SPL_MAX_SIZE } > +MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \ > + LENGTH = CONFIG_SPL_BSS_MAX_SIZE } > + > +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") > +OUTPUT_ARCH(arm) > +ENTRY(_start) > +SECTIONS > +{ > + .text : > + { > + __start = .; > + *(.vectors) > + arch/arm/cpu/armv7/start.o (.text*) > + *(.text*) > + } >.sram > + > + . = ALIGN(4); > + .rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.sram > + > + . = ALIGN(4); > + .data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram > + > + . = ALIGN(4); > + .u_boot_list : { > + KEEP(*(SORT(.u_boot_list*_i2c_*))); > + } >.sram > + > + . = ALIGN(4); > + __image_copy_end = .; > + > + .end : > + { > + *(.__end) > + } > + > + .bss : > + { > + . = ALIGN(4); > + __bss_start = .; > + *(.bss*) > + . = ALIGN(4); > + __bss_end = .; > + } >.sram > +} Any reason for that ? There is a global .lds file, and you should use it. > diff --git a/board/variscite/mx6var_som/values.inc b/board/variscite/mx6var_som/values.inc > new file mode 100644 > index 0000000..aafc088 > --- /dev/null > +++ b/board/variscite/mx6var_som/values.inc > @@ -0,0 +1,39 @@ > +0x00000000,0x00000010,0x00000013,0x00000017, > +0x00000027,0x00000028,0x00000030,0x00000038, > +0x00000047,0x00000053,0x00000080,0x000000DD, > +0x0000020E,0x00000800,0x00001740,0x0000174C, > +0x00001800,0x000026D2,0x00003000,0x00003030, > +0x00005800,0x00007800,0x00008000,0x00008033, > +0x0000803B,0x00011006,0x00011117,0x00011740, > +0x00020000,0x00020025,0x0002002D,0x00020036, > +0x00022227,0x00025565,0x0002556D,0x00025576, > +0x00048031,0x00048039,0x00080000,0x00081740, > +0x000C0000,0x000C0030,0x00130029,0x00160E83, > +0x0019002E,0x001C0019,0x001D002C,0x001F0019, > +0x001F001F,0x001F002B,0x00220AAC,0x0024001F, > +0x423D3843,0x42440244,0x43240334,0x432C0340, > +0x4528053C,0x45300544,0x454A61A5,0x46344840, > +0x48364A3E,0x484A4C4A,0x4B2B4842,0x4B4A4E4C, > +0x555A7974,0x676B5313,0x821A0000,0x83110000, > +0x831A0000,0x84190000,0x841A0000,0x8A8F7955, > +0xA1390003,0xB66D8B63,0xB66E8B63,0xC2018030, > +0xC2018038,0xC41A0000,0xDB538F64,0xF3333333, > +0xFF0A8030,0xFF0A8038,0xFF328F64,0xFFFFFFFF I do not like this way for generating a DCD-like table. > diff --git a/configs/mx6var_som_nand_defconfig b/configs/mx6var_som_nand_defconfig > new file mode 100644 > index 0000000..59c3747 > --- /dev/null > +++ b/configs/mx6var_som_nand_defconfig > @@ -0,0 +1,7 @@ > +CONFIG_ARM=y > +CONFIG_ARCH_MX6=y > +CONFIG_TARGET_MX6VAR_SOM=y > +CONFIG_SPL=y > +CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/variscite/mx6var_som/imximage.cfg,SPL,MX6QDL,SYS_BOOT_NAND" > +# CONFIG_CMD_IMLS is not set > +# CONFIG_CMD_FLASH is not set > diff --git a/configs/mx6var_som_sd_defconfig b/configs/mx6var_som_sd_defconfig > new file mode 100644 > index 0000000..875234e > --- /dev/null > +++ b/configs/mx6var_som_sd_defconfig > @@ -0,0 +1,7 @@ > +CONFIG_ARM=y > +CONFIG_ARCH_MX6=y > +CONFIG_TARGET_MX6VAR_SOM=y > +CONFIG_SPL=y > +CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/variscite/mx6var_som/imximage.cfg,SPL,MX6QDL" > +# CONFIG_CMD_IMLS is not set > +# CONFIG_CMD_FLASH is not set > diff --git a/include/configs/mx6var_som.h b/include/configs/mx6var_som.h > new file mode 100644 > index 0000000..6771a2d > --- /dev/null > +++ b/include/configs/mx6var_som.h > @@ -0,0 +1,419 @@ > +/* > + * Copyright (C) 2012 Freescale Semiconductor, Inc. > + * Copyright (C) 2016 Variscite Ltd. All Rights Reserved. > + * > + * Author: Eran Matityahu <eran.m@variscite.com> > + * > + * Configuration settings for the Variscite VAR-SOM-MX6 board. > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#ifndef __MX6VAR_SOM_CONFIG_H > +#define __MX6VAR_SOM_CONFIG_H > + > +#ifdef CONFIG_SPL > +#define CONFIG_SPL_LIBCOMMON_SUPPORT > +#ifdef CONFIG_SYS_BOOT_NAND > +#define CONFIG_SPL_NAND_SUPPORT > +#else > +#define CONFIG_SPL_MMC_SUPPORT > +#endif > +#include "mx6var_spl.h" > +#endif > +#include "mx6_common.h" > + > +/* Address of reserved 4Bytes in OCRAM for sending RAM size from SPL to U-Boot */ > +#define RAM_SIZE_ADDR ((CONFIG_SPL_TEXT_BASE) + (CONFIG_SPL_MAX_SIZE)) > + > +#define CONFIG_MACH_VAR_SOM_MX6 4419 > +#define CONFIG_MACH_TYPE CONFIG_MACH_VAR_SOM_MX6 > + > +#define CONFIG_MXC_UART_BASE UART1_BASE > +#define CONFIG_CONSOLE_DEV "ttymxc0" > +#define CONFIG_MMCROOT "/dev/mmcblk0p2" > + > +#define CONFIG_IMX_THERMAL > + > +/* Size of malloc() pool */ > +#define CONFIG_SYS_MALLOC_LEN (10 * SZ_1M) > + > +#define CONFIG_BOARD_EARLY_INIT_F > +#define CONFIG_BOARD_LATE_INIT > + > +#define CONFIG_CMD_GPIO > + > +#define CONFIG_MXC_UART > + > +#define LOW_POWER_MODE_ENABLE > + > +/* MMC Configs */ > +#define CONFIG_SYS_FSL_ESDHC_ADDR 0 > +#define CONFIG_SYS_FSL_USDHC_NUM 2 > +#define CONFIG_SYS_MMC_ENV_DEV 0 > +#define CONFIG_SYS_MMC_ENV_PART 0 > +#define CONFIG_SYS_MMC_IMG_LOAD_PART 1 > + > +#define CONFIG_CMD_PING > +#define CONFIG_CMD_DHCP > +#define CONFIG_CMD_MII > +#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 7 > + > +#define CONFIG_PHYLIB > +#define CONFIG_PHY_MICREL > +#define CONFIG_PHY_MICREL_KSZ9021 > + > +#ifdef CONFIG_BOOTDELAY > +#undef CONFIG_BOOTDELAY > +#endif > +#define CONFIG_BOOTDELAY 1 > + > +#ifdef CONFIG_SYS_BOOT_NAND > +#define MFG_NAND_PARTITION "mtdparts=gpmi-nand:16m(boot),16m(kernel),16m(dtb),-(rootfs) " > +#else > +#define MFG_NAND_PARTITION "" > +#endif > + > +#ifdef CONFIG_SYS_BOOT_NAND > +#define MMC_DEV_SET " " > +#else > +#define MMC_DEV_SET "mmcdev=" __stringify(CONFIG_SYS_MMC_ENV_DEV) > +#endif > + > +#define MFG_ENV_SETTINGS \ > + "mfgtool_args=setenv bootargs console=${console},${baudrate} " \ > + "rdinit=/linuxrc " \ > + "g_mass_storage.stall=0 g_mass_storage.removable=1 " \ > + "g_mass_storage.idVendor=0x066F g_mass_storage.idProduct=0x37FF "\ > + "g_mass_storage.iSerialNumber=\"\" "\ > + "enable_wait_mode=off "\ > + MFG_NAND_PARTITION \ > + "\0" \ > + "initrd_addr=0x12C00000\0" \ > + "initrd_high=0xffffffff\0" \ > + "bootcmd_mfg=run mfgtool_args;bootm ${loadaddr} ${initrd_addr} ${fdt_addr};\0" \ > + > + > +#define MMC_BOOT_ENV_SETTINGS \ > + "uimage=uImage\0" \ > + "fdt_file=" CONFIG_DEFAULT_FDT_FILE "\0" \ > + "boot_fdt=try\0" \ > + "ip_dyn=yes\0" \ > + MMC_DEV_SET \ > + "\0" \ > + "mmcpart=" __stringify(CONFIG_SYS_MMC_IMG_LOAD_PART) "\0" \ > + "mmcroot=" CONFIG_MMCROOT " rootwait rw\0" \ > + "mmcargs=setenv bootargs console=${console},${baudrate} root=${mmcroot}; " \ > + "run videoargs\0" \ > + "loadbootscript=" \ > + "fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};\0" \ > + "bootscript=echo Running bootscript from mmc ...; " \ > + "source\0" \ > + "loaduimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${uimage}\0" \ > + "loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${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" \ > + > + > +#define NAND_BOOT_ENV_SETTINGS \ > + "bootargs_ubifs=setenv bootargs console=${console},${baudrate} ubi.mtd=3 " \ > + "root=ubi0:rootfs rootfstype=ubifs; " \ > + "run videoargs\0" \ > + "bootargs_emmc=setenv bootargs console=${console},${baudrate} " \ > + "root=/dev/mmcblk1p1 rootwait rw; " \ > + "run videoargs\0" \ > + "bootcmd=" \ > + "if test ${chosen_rootfs} != emmc; then " \ > + "run bootargs_ubifs; " \ > + "else " \ > + "run bootargs_emmc; " \ > + "fi; " \ > + "nand read ${loadaddr} 0x400000 0x600000;" \ > + "nand read ${fdt_addr} 0x3e0000 0x20000;" \ > + "bootm ${loadaddr} - ${fdt_addr}\0" \ > + "mtdids=" MTDIDS_DEFAULT "\0" \ > + "mtdparts=" MTDPARTS_DEFAULT "\0" \ > + > + > +#ifdef CONFIG_SYS_BOOT_NAND > +#define BOOT_ENV_SETTINGS NAND_BOOT_ENV_SETTINGS > +#else > +#define BOOT_ENV_SETTINGS MMC_BOOT_ENV_SETTINGS > +#define CONFIG_BOOTCOMMAND \ > + "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" > +#endif > + > + > +#define CONFIG_EXTRA_ENV_SETTINGS \ > + MFG_ENV_SETTINGS \ > + BOOT_ENV_SETTINGS \ > + "var_auto_env=Y\0" \ > + "fdt_addr=0x18000000\0" \ > + "fdt_high=0xffffffff\0" \ > + "splash_filename=/boot/splash.bmp\0" \ > + "splashimage=0x18100000\0" \ > + "enable_splash=setenv splash_filename /boot/splash.bmp; " \ > + "setenv splashimage 0x18100000\0" \ > + "disable_splash=setenv splash_filename; setenv splashimage\0" \ > + "console=" CONFIG_CONSOLE_DEV "\0" \ > + "netargs=setenv bootargs console=${console},${baudrate} " \ > + "root=/dev/nfs rw " \ > + "ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp; " \ > + "run videoargs\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" \ > + "videoargs=" \ > + "if hdmidet; then " \ > + "setenv bootargs ${bootargs} " \ > + "video=mxcfb0:dev=hdmi,1920x1080M@60,if=RGB24; " \ > + "fi; " \ > + "setenv bootargs ${bootargs} " \ > + "video=mxcfb1:off; " \ > + "i2c dev 2; " \ > + "if i2c probe 0x38; then " \ > + "setenv bootargs ${bootargs} " \ > + "screen_alternate=yes;" \ > + "fi;\0" > + > + You could even think about to use the "distro" environment. > +#define CONFIG_ARP_TIMEOUT 200UL > + > +#undef CONFIG_SYS_PROMPT > +#ifdef CONFIG_SYS_BOOT_NAND > +#define CONFIG_SYS_PROMPT "VAR-SOM-MX6 (NAND) => " > +#else > +#define CONFIG_SYS_PROMPT "VAR-SOM-MX6 (MMC) => " > +#endif We mostly decide to not use a custom prompt for the board - see commit to remove them, letting the same prompt for all boards. > + > +#define CONFIG_SYS_MEMTEST_START 0x10000000 > +#define CONFIG_SYS_MEMTEST_END 0x10010000 > +#define CONFIG_SYS_MEMTEST_SCRATCH 0x10800000 > + > +#define CONFIG_STACKSIZE (128 * 1024) > + > +/* Physical Memory Map */ > +#define CONFIG_NR_DRAM_BANKS 1 > +#define PHYS_SDRAM MMDC0_ARB_BASE_ADDR > + > +#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_ENV_SIZE (8 * 1024) > + > +#ifdef CONFIG_SYS_BOOT_NAND > +#define CONFIG_SYS_USE_NAND > +#define CONFIG_ENV_IS_IN_NAND > +/* NAND boot config */ > +#define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE > +#define CONFIG_SYS_NAND_U_BOOT_OFFS 0x200000 > +#define CONFIG_SYS_NAND_PAGE_SIZE 2048 > +#else > +#define CONFIG_ENV_IS_IN_MMC > +#endif > + > +#if defined(CONFIG_MX6DL) > +#define CONFIG_DEFAULT_FDT_FILE "imx6dl-var-som.dtb" > +#elif defined(CONFIG_MX6S) > +#define CONFIG_DEFAULT_FDT_FILE "imx6dl-var-som.dtb" > +#elif defined(CONFIG_MX6Q) > +#define CONFIG_DEFAULT_FDT_FILE "imx6q-var-som.dtb" > +#else > +#define CONFIG_DEFAULT_FDT_FILE "imx6q-var-som.dtb" > +#endif > + > +#ifdef CONFIG_SYS_USE_NAND > +#define CONFIG_CMD_NAND > +#define CONFIG_CMD_NAND_TRIMFFS > + > +/* UBI/UBIFS support */ > +#define CONFIG_CMD_UBI > +#define CONFIG_CMD_UBIFS > +#define CONFIG_RBTREE > +#define CONFIG_MTD_DEVICE > +#define CONFIG_MTD_PARTITIONS > +#define CONFIG_CMD_MTDPARTS > +#define CONFIG_LZO > + > +#define MTDIDS_DEFAULT "nand0=nandflash-0" > + > +/* > + * Partions' layout for NAND is: > + * mtd0: 2M (spl) First boot loader > + * mtd1: 2M (u-boot, dtb) > + * mtd2: 6M (kernel) > + * mtd4: left (rootfs) > + */ > +/* Default mtd partition table */ > +#define MTDPARTS_DEFAULT "mtdparts=nandflash-0:"\ > + "2m(spl),"\ > + "2m(u-boot),"\ > + "6m(kernel),"\ > + "-(rootfs)" /* ubifs */ > + > +/* NAND stuff */ > +#define CONFIG_NAND_MXS > +#define CONFIG_SYS_MAX_NAND_DEVICE 1 > +#define CONFIG_SYS_NAND_BASE 0x40000000 > +#define CONFIG_SYS_NAND_5_ADDR_CYCLE > +#define CONFIG_SYS_NAND_ONFI_DETECTION > + > +/* DMA stuff, needed for GPMI/MXS NAND support */ > +#define CONFIG_APBH_DMA > +#define CONFIG_APBH_DMA_BURST > +#define CONFIG_APBH_DMA_BURST8 > +#endif > + > +#if defined(CONFIG_ENV_IS_IN_MMC) > +#define CONFIG_ENV_OFFSET (0x3E0000) > +#elif defined(CONFIG_ENV_IS_IN_NAND) > +#undef CONFIG_ENV_SIZE > +#define CONFIG_ENV_OFFSET (0x180000) > +#define CONFIG_ENV_SECT_SIZE (128 << 10) > +#define CONFIG_ENV_SIZE CONFIG_ENV_SECT_SIZE > +#endif > + > +#define CONFIG_OF_LIBFDT > + > +/* Framebuffer */ > +#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_SPLASH_SCREEN > +#define CONFIG_SPLASH_SCREEN_ALIGN > +#define CONFIG_BMP_16BPP > +#define CONFIG_VIDEO_LOGO > +#define CONFIG_VIDEO_BMP_LOGO > +#ifdef CONFIG_MX6DL > +#define CONFIG_IPUV3_CLK 198000000 > +#else > +#define CONFIG_IPUV3_CLK 264000000 > +#endif > +#define CONFIG_IMX_HDMI > +#define CONFIG_CMD_HDMIDETECT > +#define CONFIG_IMX_VIDEO_SKIP > +#define CONFIG_CMD_BMP > + > +#define PMIC_I2C_BUS 1 > +#define MX6CB_CDISPLAY_I2C_BUS 2 > +#define MX6CB_CDISPLAY_I2C_ADDR 0x38 > + > +/* I2C Configs */ > +#define CONFIG_CMD_I2C > +#define CONFIG_SYS_I2C > +#define CONFIG_SYS_I2C_MXC > +#define CONFIG_SYS_I2C_MXC_I2C1 /* enable I2C bus 1 */ > +#define CONFIG_SYS_I2C_MXC_I2C2 /* enable I2C bus 2 */ > +#define CONFIG_SYS_I2C_MXC_I2C3 /* enable I2C bus 3 */ > +#define CONFIG_SYS_I2C_SPEED 100000 > + > +/* PMIC */ > +#define CONFIG_POWER > +#define CONFIG_POWER_I2C > +#define CONFIG_POWER_PFUZE100 > +#define CONFIG_POWER_PFUZE100_I2C_ADDR 0x08 > + > +/* USB Configs */ > +#define CONFIG_CMD_USB > +#ifdef CONFIG_CMD_USB > +#define CONFIG_USB_EHCI > +#define CONFIG_USB_EHCI_MX6 > +#define CONFIG_USB_STORAGE > +#define CONFIG_EHCI_HCD_INIT_AFTER_RESET > +#define CONFIG_USB_HOST_ETHER > +#define CONFIG_USB_ETHER_ASIX > +#define CONFIG_MXC_USB_PORTSC (PORT_PTS_UTMI | PORT_PTS_PTW) > +#define CONFIG_MXC_USB_FLAGS 0 > +#define CONFIG_USB_MAX_CONTROLLER_COUNT 2 /* Enabled USB controller number */ > +#endif > + > +#define CONFIG_CI_UDC > +#define CONFIG_USBD_HS > +#define CONFIG_USB_GADGET_DUALSPEED > + > +/* Uncomment for USB Ethernet Gadget support */ > +/* > + * #define CONFIG_USB_ETHER > + * #define CONFIG_USB_ETH_CDC > + */ > +#define CONFIG_NETCONSOLE > + > +#define CONFIG_USB_GADGET > +#define CONFIG_CMD_USB_MASS_STORAGE > +#define CONFIG_USB_FUNCTION_MASS_STORAGE > +#define CONFIG_USB_GADGET_DOWNLOAD > +#define CONFIG_USB_GADGET_VBUS_DRAW 2 > + > +#define CONFIG_G_DNL_VENDOR_NUM 0x0525 > +#define CONFIG_G_DNL_PRODUCT_NUM 0xa4a5 > +#define CONFIG_G_DNL_MANUFACTURER "Variscite" > + > +/* USB Device Firmware Update support */ > +#define CONFIG_CMD_DFU > +#define CONFIG_USB_FUNCTION_DFU > +#define CONFIG_DFU_MMC > +#define CONFIG_DFU_RAM > +#ifdef CONFIG_SYS_USE_NAND > +#define CONFIG_SYS_MAX_NAND_DEVICE 1 > +#define CONFIG_DFU_NAND > +#endif > + > +#endif /* __MX6VAR_SOM_CONFIG_H */ > diff --git a/include/configs/mx6var_spl.h b/include/configs/mx6var_spl.h > new file mode 100644 > index 0000000..54cf4f1 > --- /dev/null > +++ b/include/configs/mx6var_spl.h > @@ -0,0 +1,81 @@ > +/* > + * Copyright (C) 2014 Gateworks Corporation > + * Author: Tim Harvey <tharvey@gateworks.com> > + * > + * Copyright (C) 2016 Variscite Ltd. All Rights Reserved. > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > +#ifndef __IMX6_SPL_CONFIG_H > +#define __IMX6_SPL_CONFIG_H > + > +#ifdef CONFIG_SPL > + > +#define CONFIG_SPL_FRAMEWORK > + > +/* > + * see Figure 8-3 in IMX6DQ/IMX6SDL Reference manuals: > + * - IMX6SDL OCRAM (IRAM) is from 0x00907000 to 0x0091FFFF > + * - IMX6DQ has 2x IRAM of IMX6SDL but we intend to support IMX6SDL as well > + * - BOOT ROM stack is at 0x0091FFB8 > + * - if icache/dcache is enabled (eFuse/strapping controlled) then the > + * IMX BOOT ROM will setup MMU table at 0x00918000, therefore we need to > + * fit between 0x00907000 and 0x00918000. > + * - Additionally the BOOT ROM loads what they consider the firmware image > + * which consists of a 4K header in front of us that contains the IVT, DCD > + * and some padding thus 'our' max size is really 0x00908000 - 0x00918000 > + * or 64KB > + */ > +#define CONFIG_SYS_THUMB_BUILD > +#define CONFIG_SPL_LDSCRIPT "board/variscite/mx6var_som/u-boot-spl.lds" > +#define CONFIG_SPL_TEXT_BASE 0x00908000 > +#define CONFIG_SPL_MAX_SIZE 0xFFFC /* ==0x10000-0x4, reserve 4Bytes for sending RAM size from SPL to U-Boot */ This is a hack - if we need an interface between SPL and u-boot, it must be solved globally nad not for a single function. And is it not set in the bdinfo structure ? > +#define CONFIG_SPL_STACK 0x0091FFB8 > +#define CONFIG_SPL_LIBCOMMON_SUPPORT > +#define CONFIG_SPL_LIBGENERIC_SUPPORT > +#define CONFIG_SPL_SERIAL_SUPPORT > +#define CONFIG_SPL_I2C_SUPPORT > +#define CONFIG_SPL_GPIO_SUPPORT > + You set again a lot of stuff instead of using mx6_spl.h. You should include this file, undefined the constants that are conflicting with your setup without duplicating all stuff. > +/* NAND support */ > +#if defined(CONFIG_SPL_NAND_SUPPORT) > +#define CONFIG_SPL_NAND_MXS > +#define CONFIG_SPL_DMA_SUPPORT > +#endif > + > +/* MMC support */ > +#if defined(CONFIG_SPL_MMC_SUPPORT) > +#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR 138 /* offset 69KB */ > +#define CONFIG_SYS_U_BOOT_MAX_SIZE_SECTORS 800 /* 400 KB */ > +#define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION 1 > +#define CONFIG_SYS_MONITOR_LEN (CONFIG_SYS_U_BOOT_MAX_SIZE_SECTORS/2*1024) > +#endif > + > +/* SATA support */ > +#if defined(CONFIG_SPL_SATA_SUPPORT) > +#define CONFIG_SPL_SATA_BOOT_DEVICE 0 > +#define CONFIG_SYS_SATA_FAT_BOOT_PARTITION 1 > +#endif > + > +/* Define the payload for FAT/EXT support */ > +#if defined(CONFIG_SPL_FAT_SUPPORT) || defined(CONFIG_SPL_EXT_SUPPORT) > +#define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME "u-boot.img" > +#define CONFIG_SPL_LIBDISK_SUPPORT > +#endif > + > +#if defined(CONFIG_MX6SX) > +#define CONFIG_SPL_BSS_START_ADDR 0x88200000 > +#define CONFIG_SPL_BSS_MAX_SIZE 0x100000 /* 1 MB */ > +#define CONFIG_SYS_SPL_MALLOC_START 0x88300000 > +#define CONFIG_SYS_SPL_MALLOC_SIZE 0x3200000 /* 50 MB */ > +#define CONFIG_SYS_TEXT_BASE 0x87800000 > +#else > +#define CONFIG_SPL_BSS_START_ADDR 0x18200000 > +#define CONFIG_SPL_BSS_MAX_SIZE 0x100000 /* 1 MB */ > +#define CONFIG_SYS_SPL_MALLOC_START 0x18300000 > +#define CONFIG_SYS_SPL_MALLOC_SIZE 0x3200000 /* 50 MB */ > +#define CONFIG_SYS_TEXT_BASE 0x17800000 > +#endif > +#endif > + > +#endif > diff --git a/tools/logos/variscite.bmp b/tools/logos/variscite.bmp I tend to reject this. You have already implemented a splashscreen and you can load an image to the display. Is it not enough ? > new file mode 100644 > index 0000000000000000000000000000000000000000..f3ca27ceb169cd5d174fa919248968877cb0e3d3 > GIT binary patch > literal 15414 > zcmeHO34B!LwU2kgL_-?_NHAh*x%YW*oFT>rL2W@1H!9Ey5zD@apnzf#MH;{mV~o*= > z6n&VdJdo9}8iv3iVKoq03NnF<0ok<4kPu*!FqZ;F&pYRQ_s(MTMEYxgCYA$t`Id9; > z`G05m&Nuw%+OuP)2&Rsa5fO>_b{wxRcwG~5E#3ufjfse$3p>RX5dj^4l?)wIQsAyT Best regards, Stefano Babic
diff --git a/arch/arm/cpu/armv7/mx6/Kconfig b/arch/arm/cpu/armv7/mx6/Kconfig index c72a150..146c152 100644 --- a/arch/arm/cpu/armv7/mx6/Kconfig +++ b/arch/arm/cpu/armv7/mx6/Kconfig @@ -115,6 +115,12 @@ config TARGET_MX6UL_14X14_EVK select DM_THERMAL select SUPPORT_SPL +config TARGET_MX6VAR_SOM + bool "mx6var_som" + select SUPPORT_SPL + select DM + select DM_THERMAL + config TARGET_NITROGEN6X bool "nitrogen6x" @@ -180,6 +186,7 @@ source "board/solidrun/mx6cuboxi/Kconfig" source "board/tbs/tbs2910/Kconfig" source "board/tqc/tqma6/Kconfig" source "board/udoo/Kconfig" +source "board/variscite/mx6var_som/Kconfig" source "board/wandboard/Kconfig" source "board/warp/Kconfig" diff --git a/board/variscite/mx6var_som/Kconfig b/board/variscite/mx6var_som/Kconfig new file mode 100644 index 0000000..0b82df7 --- /dev/null +++ b/board/variscite/mx6var_som/Kconfig @@ -0,0 +1,12 @@ +if TARGET_MX6VAR_SOM + +config SYS_BOARD + default "mx6var_som" + +config SYS_VENDOR + default "variscite" + +config SYS_CONFIG_NAME + default "mx6var_som" + +endif diff --git a/board/variscite/mx6var_som/MAINTAINERS b/board/variscite/mx6var_som/MAINTAINERS new file mode 100644 index 0000000..f3f81dd --- /dev/null +++ b/board/variscite/mx6var_som/MAINTAINERS @@ -0,0 +1,8 @@ +MX6VAR_SOM BOARD +M: Eran Matityahu <eran.m@variscite.com> +S: Maintained +F: board/variscite/mx6var_som/ +F: include/configs/mx6var_som.h +F: include/configs/mx6var_spl.h +F: configs/mx6var_som_nand_defconfig +F: configs/mx6var_som_sd_defconfig diff --git a/board/variscite/mx6var_som/Makefile b/board/variscite/mx6var_som/Makefile new file mode 100644 index 0000000..efa90e2 --- /dev/null +++ b/board/variscite/mx6var_som/Makefile @@ -0,0 +1,9 @@ +# +# Copyright (C) 2007, Guennadi Liakhovetski <lg@denx.de> +# +# (C) Copyright 2011 Freescale Semiconductor, Inc. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y := mx6var_som.o mx6var_eeprom.o mx6var_eeprom_v2.o diff --git a/board/variscite/mx6var_som/addresses.inc b/board/variscite/mx6var_som/addresses.inc new file mode 100644 index 0000000..3aaea54 --- /dev/null +++ b/board/variscite/mx6var_som/addresses.inc @@ -0,0 +1,38 @@ +0x00000000, 0x020C4068, 0x020C406C, 0x020C4070, +0x020C4074, 0x020C4078, 0x020C407C, 0x020C4080, +0x020C4084, 0x020E0464, 0x020E0470, 0x020E0474, +0x020E0478, 0x020E047C, 0x020E0480, 0x020E0484, +0x020E0488, 0x020E048C, 0x020E0490, 0x020E0494, +0x020E04A0, 0x020E04AC, 0x020E04B0, 0x020E04B4, +0x020E04B8, 0x020E04BC, 0x020E04C0, 0x020E04C4, +0x020E04C8, 0x020E04CC, 0x020E04D0, 0x020E04D4, +0x020E04D8, 0x020E050C, 0x020E0510, 0x020E0514, +0x020E0518, 0x020E051C, 0x020E0520, 0x020E0524, +0x020E0528, 0x020E056C, 0x020E0578, 0x020E057C, +0x020E0588, 0x020E058C, 0x020E0594, 0x020E059C, +0x020E05A0, 0x020E05A8, 0x020E05AC, 0x020E05B0, +0x020E05B4, 0x020E05B8, 0x020E05BC, 0x020E05C0, +0x020E05C4, 0x020E0748, 0x020E074C, 0x020E0750, +0x020E0754, 0x020E0758, 0x020E0760, 0x020E0764, +0x020E076C, 0x020E0770, 0x020E0774, 0x020E0778, +0x020E077C, 0x020E0780, 0x020E0784, 0x020E0788, +0x020E078C, 0x020E0794, 0x020E0798, 0x020E079C, +0x020E07A0, 0x020E07A4, 0x020E07A8, 0x021B0000, +0x021B0004, 0x021B0008, 0x021B000C, 0x021B0010, +0x021B0014, 0x021B0018, 0x021B001C, 0x021B0020, +0x021B002C, 0x021B0030, 0x021B0038, 0x021B0040, +0x021B0400, 0x021B0404, 0x021B0800, 0x021B080C, +0x021B0810, 0x021B0818, 0x021B081C, 0x021B0820, +0x021B0824, 0x021B0828, 0x021B082C, 0x021B0830, +0x021B0834, 0x021B0838, 0x021B083C, 0x021B0840, +0x021B0848, 0x021B0850, 0x021B085C, 0x021B0890, +0x021B08B8, 0x021B08C0, 0x021B4000, 0x021B4004, +0x021B4008, 0x021B400C, 0x021B4010, 0x021B4014, +0x021B4018, 0x021B401C, 0x021B4020, 0x021B402C, +0x021B4030, 0x021B4038, 0x021B4040, 0x021B4400, +0x021B4404, 0x021B4800, 0x021B480C, 0x021B4810, +0x021B4818, 0x021B481C, 0x021B4820, 0x021B4824, +0x021B4828, 0x021B482C, 0x021B4830, 0x021B4834, +0x021B4838, 0x021B483C, 0x021B4840, 0x021B4848, +0x021B4850, 0x021B485C, 0x021B4890, 0x021B48B8, +0x021B48BC, 0x021B48C0 diff --git a/board/variscite/mx6var_som/imximage.cfg b/board/variscite/mx6var_som/imximage.cfg new file mode 100644 index 0000000..54dc449 --- /dev/null +++ b/board/variscite/mx6var_som/imximage.cfg @@ -0,0 +1,13 @@ +/* + * Copyright (C) 2016 Variscite Ltd. All Rights Reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +IMAGE_VERSION 2 + +#ifdef CONFIG_SYS_BOOT_NAND +BOOT_FROM nand +#else +BOOT_FROM sd +#endif diff --git a/board/variscite/mx6var_som/mx6var_eeprom.c b/board/variscite/mx6var_som/mx6var_eeprom.c new file mode 100644 index 0000000..02fedd0 --- /dev/null +++ b/board/variscite/mx6var_som/mx6var_eeprom.c @@ -0,0 +1,320 @@ +/* + * Copyright (C) 2016 Variscite Ltd. All Rights Reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <command.h> +#include <i2c.h> +#include "mx6var_eeprom.h" +#ifdef CONFIG_SPL_BUILD +#include <asm/arch/mx6-ddr.h> + +#ifdef EEPROM_DEBUG +#define eeprom_debug(M, ...) printf("EEPROM DEBUG: " M, ##__VA_ARGS__) +#else +#define eeprom_debug(M, ...) +#endif + +bool var_eeprom_is_valid(struct var_eeprom_cfg *p_var_eeprom_cfg) +{ + return (VARISCITE_MAGIC == p_var_eeprom_cfg->header.variscite_magic); +} + +void var_eeprom_mx6dlsl_dram_setup_iomux_from_struct(struct var_pinmux_group_regs *pinmux_group) +{ + volatile struct mx6sdl_iomux_ddr_regs *mx6dl_ddr_iomux; + volatile struct mx6sdl_iomux_grp_regs *mx6dl_grp_iomux; + + mx6dl_ddr_iomux = (struct mx6sdl_iomux_ddr_regs *) MX6SDL_IOM_DDR_BASE; + mx6dl_grp_iomux = (struct mx6sdl_iomux_grp_regs *) MX6SDL_IOM_GRP_BASE; + + mx6dl_grp_iomux->grp_ddr_type = (u32)pinmux_group->IOMUXC_SW_PAD_CTL_GRP_DDR_TYPE; + mx6dl_grp_iomux->grp_ddrpke = (u32)pinmux_group->IOMUXC_SW_PAD_CTL_GRP_DDRPKE; + mx6dl_ddr_iomux->dram_sdclk_0 = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6dl_ddr_iomux->dram_sdclk_1 = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6dl_ddr_iomux->dram_cas = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6dl_ddr_iomux->dram_ras = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6dl_grp_iomux->grp_addds = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6dl_ddr_iomux->dram_reset = (u32)pinmux_group->dram_reset; + mx6dl_ddr_iomux->dram_sdcke0 = (u32)pinmux_group->dram_sdcke0; + mx6dl_ddr_iomux->dram_sdcke1 = (u32)pinmux_group->dram_sdcke1; + mx6dl_ddr_iomux->dram_sdba2 = (u32)pinmux_group->IOMUXC_SW_PAD_CTL_PAD_DRAM_SDBA2; + mx6dl_ddr_iomux->dram_sdodt0 = (u32)pinmux_group->dram_sdodt0; + mx6dl_ddr_iomux->dram_sdodt1 = (u32)pinmux_group->dram_sdodt1; + mx6dl_grp_iomux->grp_ctlds = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6dl_grp_iomux->grp_ddrmode_ctl = (u32)pinmux_group->IOMUXC_SW_PAD_CTL_GRP_DDRMODE_CTL; + mx6dl_ddr_iomux->dram_sdqs0 = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6dl_ddr_iomux->dram_sdqs1 = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6dl_ddr_iomux->dram_sdqs2 = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6dl_ddr_iomux->dram_sdqs3 = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6dl_ddr_iomux->dram_sdqs4 = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6dl_ddr_iomux->dram_sdqs5 = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6dl_ddr_iomux->dram_sdqs6 = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6dl_ddr_iomux->dram_sdqs7 = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6dl_grp_iomux->grp_ddrmode = (u32)pinmux_group->IOMUXC_SW_PAD_CTL_GRP_DDRMODE; + mx6dl_grp_iomux->grp_b0ds = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6dl_grp_iomux->grp_b1ds = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6dl_grp_iomux->grp_b2ds = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6dl_grp_iomux->grp_b3ds = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6dl_grp_iomux->grp_b4ds = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6dl_grp_iomux->grp_b5ds = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6dl_grp_iomux->grp_b6ds = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6dl_grp_iomux->grp_b7ds = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6dl_ddr_iomux->dram_dqm0 = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6dl_ddr_iomux->dram_dqm1 = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6dl_ddr_iomux->dram_dqm2 = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6dl_ddr_iomux->dram_dqm3 = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6dl_ddr_iomux->dram_dqm4 = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6dl_ddr_iomux->dram_dqm5 = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6dl_ddr_iomux->dram_dqm6 = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6dl_ddr_iomux->dram_dqm7 = (u32)pinmux_group->pinmux_ctrlpad_all_value; +} + +void var_eeprom_mx6qd_dram_setup_iomux_from_struct(struct var_pinmux_group_regs *pinmux_group) +{ + volatile struct mx6dq_iomux_ddr_regs *mx6q_ddr_iomux; + volatile struct mx6dq_iomux_grp_regs *mx6q_grp_iomux; + + mx6q_ddr_iomux = (struct mx6dq_iomux_ddr_regs *) MX6DQ_IOM_DDR_BASE; + mx6q_grp_iomux = (struct mx6dq_iomux_grp_regs *) MX6DQ_IOM_GRP_BASE; + + mx6q_grp_iomux->grp_ddr_type = (u32)pinmux_group->IOMUXC_SW_PAD_CTL_GRP_DDR_TYPE; + mx6q_grp_iomux->grp_ddrpke = (u32)pinmux_group->IOMUXC_SW_PAD_CTL_GRP_DDRPKE; + mx6q_ddr_iomux->dram_sdclk_0 = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6q_ddr_iomux->dram_sdclk_1 = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6q_ddr_iomux->dram_cas = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6q_ddr_iomux->dram_ras = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6q_grp_iomux->grp_addds = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6q_ddr_iomux->dram_reset = (u32)pinmux_group->dram_reset; + mx6q_ddr_iomux->dram_sdcke0 = (u32)pinmux_group->dram_sdcke0; + mx6q_ddr_iomux->dram_sdcke1 = (u32)pinmux_group->dram_sdcke1; + mx6q_ddr_iomux->dram_sdba2 = (u32)pinmux_group->IOMUXC_SW_PAD_CTL_PAD_DRAM_SDBA2; + mx6q_ddr_iomux->dram_sdodt0 = (u32)pinmux_group->dram_sdodt0; + mx6q_ddr_iomux->dram_sdodt1 = (u32)pinmux_group->dram_sdodt1; + mx6q_grp_iomux->grp_ctlds = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6q_grp_iomux->grp_ddrmode_ctl = (u32)pinmux_group->IOMUXC_SW_PAD_CTL_GRP_DDRMODE_CTL; + mx6q_ddr_iomux->dram_sdqs0 = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6q_ddr_iomux->dram_sdqs1 = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6q_ddr_iomux->dram_sdqs2 = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6q_ddr_iomux->dram_sdqs3 = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6q_ddr_iomux->dram_sdqs4 = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6q_ddr_iomux->dram_sdqs5 = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6q_ddr_iomux->dram_sdqs6 = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6q_ddr_iomux->dram_sdqs7 = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6q_grp_iomux->grp_ddrmode = (u32)pinmux_group->IOMUXC_SW_PAD_CTL_GRP_DDRMODE; + mx6q_grp_iomux->grp_b0ds = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6q_grp_iomux->grp_b1ds = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6q_grp_iomux->grp_b2ds = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6q_grp_iomux->grp_b3ds = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6q_grp_iomux->grp_b4ds = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6q_grp_iomux->grp_b5ds = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6q_grp_iomux->grp_b6ds = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6q_grp_iomux->grp_b7ds = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6q_ddr_iomux->dram_dqm0 = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6q_ddr_iomux->dram_dqm1 = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6q_ddr_iomux->dram_dqm2 = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6q_ddr_iomux->dram_dqm3 = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6q_ddr_iomux->dram_dqm4 = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6q_ddr_iomux->dram_dqm5 = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6q_ddr_iomux->dram_dqm6 = (u32)pinmux_group->pinmux_ctrlpad_all_value; + mx6q_ddr_iomux->dram_dqm7 = (u32)pinmux_group->pinmux_ctrlpad_all_value; +} + +void var_eeprom_dram_init_from_struct(struct var_eeprom_cfg *p_var_eeprom_cfg) +{ + volatile struct mmdc_p_regs *mmdc_p0 = (struct mmdc_p_regs *) MMDC_P0_BASE_ADDR; + u32 i; + u32 last; + u32 opcode; + + /* Go through all register initializations and apply to correct registers... */ + i = 0; + last = sizeof(p_var_eeprom_cfg->write_opcodes) / sizeof(u32); + while ( (0 != p_var_eeprom_cfg->write_opcodes[i].address) && (i < last) ) { + opcode = p_var_eeprom_cfg->write_opcodes[i].address & 0xF0000000; + switch (opcode) { + case VAR_DDR_INIT_OPCODE_WRITE_VAL_TO_ADDRESS: + /* ZQ calibration? ==> Need to wait? */ + if (mmdc_p0->mpzqhwctrl == p_var_eeprom_cfg->write_opcodes[i].address) { + if (p_var_eeprom_cfg->write_opcodes[i].value & 0x3) { + while (mmdc_p0->mpzqhwctrl & 0x00010000); + } + } + else { + /* write value to reg */ + volatile u32 *reg_ptr = (volatile u32 *)p_var_eeprom_cfg->write_opcodes[i].address; + + *reg_ptr = p_var_eeprom_cfg->write_opcodes[i].value; + } + break; + case VAR_DDR_INIT_OPCODE_WAIT_MASK_RISING: { + volatile u32 *reg_ptr = (volatile u32 *)p_var_eeprom_cfg->write_opcodes[i].address; + + while ( (p_var_eeprom_cfg->write_opcodes[i].value & *reg_ptr) != \ + p_var_eeprom_cfg->write_opcodes[i].value ); + break; + } + case VAR_DDR_INIT_OPCODE_WAIT_MASK_FALLING: { + volatile u32 *reg_ptr = (volatile u32 *)p_var_eeprom_cfg->write_opcodes[i].address; + + while ( (p_var_eeprom_cfg->write_opcodes[i].value & (~(*reg_ptr)) ) != \ + p_var_eeprom_cfg->write_opcodes[i].value ); + break; + } + case VAR_DDR_INIT_OPCODE_DELAY_USEC: + udelay(p_var_eeprom_cfg->write_opcodes[i].value); + break; + default: + break; + } + + i++; + } + + /* Short delay */ + udelay(500); +} + +#ifdef EEPROM_DEBUG +static void var_eeprom_printf_array_dwords(u32 *ptr, u32 address_mem, u32 size) +{ + u32 idx; + u32 *p_end = ptr + (size/4); + idx = 0; + while (ptr < p_end) { + if ((idx & 0x3) == 0) { + printf("\n0x%08x:", address_mem); + address_mem += 0x10; + } + printf(" 0x%08x", *ptr); + idx++; + ptr++; + } + printf("\n"); +} +#endif + +int var_eeprom_read_struct(struct var_eeprom_cfg *p_var_eeprom_cfg) +{ + int eeprom_found; + int ret = 0; + i2c_set_bus_num(1); + eeprom_found = i2c_probe(VAR_MX6_EEPROM_CHIP); + eeprom_debug("eeprom_found(0x%x)=%d\n", VAR_MX6_EEPROM_CHIP, eeprom_found); + if (0 == eeprom_found) { + eeprom_debug("EEPROM device detected, address=0x%x\n", VAR_MX6_EEPROM_CHIP); + + if (i2c_read(VAR_MX6_EEPROM_CHIP, VAR_MX6_EEPROM_STRUCT_OFFSET, \ + 1, (uchar *)p_var_eeprom_cfg, sizeof(struct var_eeprom_cfg))) { + eeprom_debug("Read device ID error!\n"); + return -1; + } else { + /* Success */ +#ifdef EEPROM_DEBUG + var_eeprom_printf_array_dwords((u32 *) p_var_eeprom_cfg, (u32) 0, \ + sizeof(struct var_eeprom_cfg)); +#endif + } + } else { + eeprom_debug("Error! Couldn't find EEPROM device\n"); + } + + return ret; +} +#endif /* CONFIG_SPL_BUILD */ + +void var_eeprom_strings_print(struct var_eeprom_cfg *p_var_eeprom_cfg) +{ + p_var_eeprom_cfg->header.part_number[sizeof(p_var_eeprom_cfg->header.part_number)-1] = (u8)0x00; + p_var_eeprom_cfg->header.Assembly[sizeof(p_var_eeprom_cfg->header.Assembly)-1] = (u8)0x00; + p_var_eeprom_cfg->header.date[sizeof(p_var_eeprom_cfg->header.date)-1] = (u8)0x00; + + printf("Part number: %s\n", (char *)p_var_eeprom_cfg->header.part_number); + printf("Assembly: %s\n", (char *)p_var_eeprom_cfg->header.Assembly); + printf("Date of production: %s\n", (char *)p_var_eeprom_cfg->header.date); +} + +static int var_eeprom_write(uchar *ptr, u32 size, u32 offset) +{ + int ret = 0; + u32 size_written; + u32 size_to_write; + u32 P0_select_page_EEPROM; + u32 chip; + u32 addr; + + /* Write to EEPROM device */ + size_written = 0; + size_to_write = size; + while ((0 == ret) && (size_written < size_to_write)) { + P0_select_page_EEPROM = (offset > 0xFF); + chip = VAR_MX6_EEPROM_CHIP + P0_select_page_EEPROM; + addr = (offset & 0xFF); + ret = i2c_write(chip, addr, 1, ptr, VAR_MX6_EEPROM_WRITE_MAX_SIZE); + + /* Wait for EEPROM write operation to complete (No ACK) */ + mdelay(11); + + size_written += VAR_MX6_EEPROM_WRITE_MAX_SIZE; + offset += VAR_MX6_EEPROM_WRITE_MAX_SIZE; + ptr += VAR_MX6_EEPROM_WRITE_MAX_SIZE; + } + + return ret; +} + +/* + * vareeprom command intepreter. + */ +static int do_var_eeprom_params(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct var_eeprom_cfg var_eeprom_cfg; + int offset; + + if (argc != 4) + return -1; + + memset(&var_eeprom_cfg, 0x00, sizeof(var_eeprom_cfg)); + + memcpy(&var_eeprom_cfg.header.part_number[0], argv[1], sizeof(var_eeprom_cfg.header.part_number)); + memcpy(&var_eeprom_cfg.header.Assembly[0], argv[2], sizeof(var_eeprom_cfg.header.Assembly)); + memcpy(&var_eeprom_cfg.header.date[0], argv[3], sizeof(var_eeprom_cfg.header.date)); + + var_eeprom_strings_print(&var_eeprom_cfg); + + offset = (uchar *)&var_eeprom_cfg.header.part_number[0] - (uchar *)&var_eeprom_cfg.header; + if (var_eeprom_write((uchar *)&var_eeprom_cfg.header.part_number[0], \ + sizeof(var_eeprom_cfg.header.part_number), \ + VAR_MX6_EEPROM_STRUCT_OFFSET + offset) ) { + printf("Error writing to EEPROM!\n"); + return -1; + } + + offset = (uchar *)&var_eeprom_cfg.header.Assembly[0] - (uchar *)&var_eeprom_cfg; + if (var_eeprom_write((uchar *)&var_eeprom_cfg.header.Assembly[0], \ + sizeof(var_eeprom_cfg.header.Assembly), \ + VAR_MX6_EEPROM_STRUCT_OFFSET + offset) ) { + printf("Error writing to EEPROM!\n"); + return -1; + } + + offset = (uchar *)&var_eeprom_cfg.header.date[0] - (uchar *)&var_eeprom_cfg; + if (var_eeprom_write((uchar *)&var_eeprom_cfg.header.date[0], \ + sizeof(var_eeprom_cfg.header.date), \ + VAR_MX6_EEPROM_STRUCT_OFFSET + offset) ) { + printf("Error writing to EEPROM!\n"); + return -1; + } + + printf("EEPROM updated successfully\n"); + + return 0; +} + +U_BOOT_CMD( + vareeprom, 5, 1, do_var_eeprom_params, + "For internal use only", + "- Do not use" +); diff --git a/board/variscite/mx6var_som/mx6var_eeprom.h b/board/variscite/mx6var_som/mx6var_eeprom.h new file mode 100644 index 0000000..5c70a27 --- /dev/null +++ b/board/variscite/mx6var_som/mx6var_eeprom.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2016 Variscite Ltd. All Rights Reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _MX6VAR_EEPROM_H_ +#define _MX6VAR_EEPROM_H_ + +#define VARISCITE_MAGIC 0x49524157 /* == HEX("VARI")*/ + +#define VAR_MX6_EEPROM_CHIP 0x56 +#define VAR_DART_EEPROM_CHIP 0x52 + +#define VAR_MX6_EEPROM_STRUCT_OFFSET 0x00000000 + +#define VAR_MX6_EEPROM_WRITE_MAX_SIZE 0x4 + +#define EEPROM_SIZE_BYTES 512 + +#define VAR_DDR_INIT_OPCODE_WRITE_VAL_TO_ADDRESS 0x00000000 +#define VAR_DDR_INIT_OPCODE_WAIT_MASK_RISING 0x10000000 +#define VAR_DDR_INIT_OPCODE_WAIT_MASK_FALLING 0x20000000 +#define VAR_DDR_INIT_OPCODE_DELAY_USEC 0x30000000 + +#define SPL_DRAM_INIT_STATUS_OK 0 +#define SPL_DRAM_INIT_STATUS_ERROR_NO_EEPROM 1 +#define SPL_DRAM_INIT_STATUS_ERROR_NO_EEPROM_STRUCT_DETECTED 2 + +struct var_eeprom_cfg_header +{ + u32 variscite_magic; /* == HEX("VARI")?*/ + u8 part_number[16]; + u8 Assembly[16]; + u8 date[16]; + u8 version; + u8 reserved[7]; + u32 ddr_size; +}; + +struct var_pinmux_group_regs +{ + u32 IOMUXC_SW_PAD_CTL_GRP_DDR_TYPE; + u32 IOMUXC_SW_PAD_CTL_GRP_DDRPKE; + u32 IOMUXC_SW_PAD_CTL_GRP_DDRMODE_CTL; + u32 IOMUXC_SW_PAD_CTL_GRP_DDRMODE; + u32 IOMUXC_SW_PAD_CTL_PAD_DRAM_SDBA2; + u32 dram_reset; + u32 dram_sdcke0; + u32 dram_sdcke1; + u32 dram_sdodt0; + u32 dram_sdodt1; + u32 reserved; + u32 pinmux_ctrlpad_all_value; +}; + +struct reg_write_opcode +{ + u32 address; /* address encoded with opcode */ + u32 value; +}; + +struct var_eeprom_cfg +{ + struct var_eeprom_cfg_header header; + struct var_pinmux_group_regs pinmux_group; + struct reg_write_opcode write_opcodes[ \ + (EEPROM_SIZE_BYTES \ + - sizeof(struct var_eeprom_cfg_header) \ + - sizeof(struct var_pinmux_group_regs)) \ + / sizeof(struct reg_write_opcode) ]; +}; + +bool var_eeprom_is_valid(struct var_eeprom_cfg *p_var_eeprom_cfg); + +/* init ddr iomux from struct */ +void var_eeprom_mx6dlsl_dram_setup_iomux_from_struct(struct var_pinmux_group_regs *pinmux_group); + +void var_eeprom_mx6qd_dram_setup_iomux_from_struct(struct var_pinmux_group_regs *pinmux_group); + +/* init ddr from struct */ +void var_eeprom_dram_init_from_struct(struct var_eeprom_cfg *p_var_eeprom_cfg); + +int var_eeprom_read_struct(struct var_eeprom_cfg *p_var_eeprom_cfg); + +void var_eeprom_strings_print(struct var_eeprom_cfg *p_var_eeprom_cfg); + +#endif /* _MX6VAR_EEPROM_H_ */ diff --git a/board/variscite/mx6var_som/mx6var_eeprom_v2.c b/board/variscite/mx6var_som/mx6var_eeprom_v2.c new file mode 100644 index 0000000..490b470 --- /dev/null +++ b/board/variscite/mx6var_som/mx6var_eeprom_v2.c @@ -0,0 +1,231 @@ +/* + * Copyright (C) 2016 Variscite Ltd. All Rights Reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifdef CONFIG_SPL_BUILD +#include <common.h> +#include <i2c.h> +#include "mx6var_eeprom_v2.h" + +#ifdef EEPROM_V2_DEBUG +#define eeprom_v2_debug(M, ...) printf("EEPROM_V2 DEBUG: " M, ##__VA_ARGS__) +#else +#define eeprom_v2_debug(M, ...) +#endif + +static u32 get_address_by_index(unsigned char index, u32 *ram_addresses); +static u32 get_value_by_index(unsigned char index, u32 *ram_values); +static int handle_one_command(struct eeprom_command *eeprom_commands,int command_num, \ + u32 *ram_addresses, u32 *ram_values); + + +bool var_eeprom_v2_is_valid(struct var_eeprom_v2_cfg *p_var_eeprom_v2_cfg) +{ + return (VARISCITE_MAGIC_V2 == p_var_eeprom_v2_cfg->variscite_magic); +} + + +void var_eeprom_v2_strings_print(struct var_eeprom_v2_cfg *p_var_eeprom_v2_cfg) +{ + p_var_eeprom_v2_cfg->part_number[sizeof(p_var_eeprom_v2_cfg->part_number)-1] = (u8)0x00; + p_var_eeprom_v2_cfg->Assembly[sizeof(p_var_eeprom_v2_cfg->Assembly)-1] = (u8)0x00; + p_var_eeprom_v2_cfg->date[sizeof(p_var_eeprom_v2_cfg->date)-1] = (u8)0x00; + + printf("Part number: %s\n", (char *)p_var_eeprom_v2_cfg->part_number); + printf("Assembly: %s\n", (char *)p_var_eeprom_v2_cfg->Assembly); + printf("Date of production: %s\n", (char *)p_var_eeprom_v2_cfg->date); +} + + +void load_custom_data(u32 *custom_addresses_values, u32 *ram_addresses, u32 *ram_values) +{ + int i, j=0; + + for (i=0; i<MAXIMUM_RAM_ADDRESSES; i++) { + ram_addresses[i]=0; + } + for (i=0; i<MAXIMUM_RAM_VALUES; i++) { + ram_values[i]=0; + } + + for (i=0; i<MAXIMUM_RAM_ADDRESSES; i++) { + if (custom_addresses_values[i]==0) + break; + ram_addresses[j]=custom_addresses_values[i]; + j++; + } + + i++; + if (i > MAXIMUM_RAM_ADDRESSES) + return; + + j=0; + for (; i<MAXIMUM_RAM_VALUES; i++) { + if (custom_addresses_values[i]==0) + break; + ram_values[j]=custom_addresses_values[i]; + j++; + } +} + + +int handle_eeprom_data(struct var_eeprom_v2_cfg *var_eeprom_v2_cfg, \ + u32 *ram_addresses, u32 *ram_values) +{ + load_custom_data(var_eeprom_v2_cfg->custom_addresses_values, ram_addresses, ram_values); + return setup_ddr_parameters(var_eeprom_v2_cfg->eeprom_commands, \ + ram_addresses, ram_values); +} + + +int setup_ddr_parameters(struct eeprom_command *eeprom_commands, \ + u32 *ram_addresses, u32 *ram_values) +{ + int i=0; + + while (i < MAXIMUM_COMMANDS_NUMBER) { + i = handle_one_command(eeprom_commands, i, ram_addresses, ram_values); + if (i < 0) + return -1; + if (i == 0) + return 0; + } + return 0; +} + + +static int handle_one_command(struct eeprom_command *eeprom_commands, int command_num, \ + u32 *ram_addresses, u32 *ram_values) +{ + volatile u32 *data; + u32 address; + u32 value; + + eeprom_v2_debug("Executing command %03d: %03d, %03d\n", + command_num, + eeprom_commands[command_num].address_index, + eeprom_commands[command_num].value_index); + + switch(eeprom_commands[command_num].address_index) { + case WHILE_NOT_EQUAL_INDEX: + command_num++; + address=get_address_by_index(eeprom_commands[command_num].address_index, ram_addresses); + value=get_value_by_index(eeprom_commands[command_num].value_index, ram_values); + data=(u32*)address; + eeprom_v2_debug("Waiting while data at address %08x is not equal %08x\n", address, value); + + while(data[0]!=value); + + command_num++; + break; + case WHILE_EQUAL_INDEX: + command_num++; + address=get_address_by_index(eeprom_commands[command_num].address_index, ram_addresses); + value=get_value_by_index(eeprom_commands[command_num].value_index, ram_values); + data=(u32*)address; + eeprom_v2_debug("Waiting while data at address %08x is equal %08x\n", address, value); + + while(data[0]==value); + + command_num++; + break; + case WHILE_AND_INDEX: + command_num++; + address=get_address_by_index(eeprom_commands[command_num].address_index, ram_addresses); + value=get_value_by_index(eeprom_commands[command_num].value_index, ram_values); + data=(u32*)address; + eeprom_v2_debug("Waiting while data at address %08x and %08x is not zero\n", address, value); + + while(data[0]&value); + + command_num++; + break; + case WHILE_NOT_AND_INDEX: + command_num++; + address=get_address_by_index(eeprom_commands[command_num].address_index, ram_addresses); + value=get_value_by_index(eeprom_commands[command_num].value_index, ram_values); + data=(u32*)address; + eeprom_v2_debug("Waiting while data at address %08x and %08x is zero\n", address, value); + + while(!(data[0]&value)); + + command_num++; + break; + case DELAY_10USEC_INDEX: + /* Delay for Value * 10 uSeconds */ + eeprom_v2_debug("Delaying for %d microseconds\n", eeprom_commands[command_num].value_index*10); + udelay((int)(eeprom_commands[command_num].value_index*10)); + command_num++; + break; + case LAST_COMMAND_INDEX: + command_num=0; + break; + default: + address=get_address_by_index(eeprom_commands[command_num].address_index, ram_addresses); + value=get_value_by_index(eeprom_commands[command_num].value_index, ram_values); + data=(u32*)address; + eeprom_v2_debug("Setting data at address %08x to %08x\n", address, value); + data[0]=value; + command_num++; + break; + } + + return command_num; +} + + +static u32 get_address_by_index(unsigned char index, u32 *ram_addresses) +{ + /* + * DDR Register struct + * The eeprom contains a structure of: + * 1 byte index in this addresses table, and + * 1 byte index to common values in the next table - to write to this address. + * If there are new addresses from the calibration program, + * they should be added to the end of the array. + * The maximum array size is 256 addresses. + */ + const u32 rom_addresses[]= + { + #include "addresses.inc" + }; + + if (index >= MAXIMUM_ROM_ADDR_INDEX) + return ram_addresses[index-MAXIMUM_ROM_ADDR_INDEX]; + + return rom_addresses[index]; +} + + +static u32 get_value_by_index(unsigned char index, u32 *ram_values) +{ + const u32 rom_values[] = + { + #include "values.inc" + }; + + if (index >= MAXIMUM_ROM_VALUE_INDEX) + return ram_values[index-MAXIMUM_ROM_VALUE_INDEX]; + + return rom_values[index]; +} + + +int var_eeprom_v2_read_struct(struct var_eeprom_v2_cfg *var_eeprom_v2_cfg, \ + unsigned char address) +{ + int eeprom_found = i2c_probe(address); + if (0 == eeprom_found) { + if (i2c_read(address, 0, 1, (void*) var_eeprom_v2_cfg, \ + sizeof(struct var_eeprom_v2_cfg))) { + printf("Read device ID error!\n"); + return -1; + } + } else { + printf("Error! Couldn't find EEPROM device\n"); + } + return 0; +} +#endif diff --git a/board/variscite/mx6var_som/mx6var_eeprom_v2.h b/board/variscite/mx6var_som/mx6var_eeprom_v2.h new file mode 100644 index 0000000..cebf46d --- /dev/null +++ b/board/variscite/mx6var_som/mx6var_eeprom_v2.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2016 Variscite Ltd. All Rights Reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _MX6VAR_V2_EEPROM_H_ +#define _MX6VAR_V2_EEPROM_H_ + +#define VARISCITE_MAGIC_V2 0x32524156 /* == HEX("VAR2") */ + +#define MAXIMUM_ROM_ADDR_INDEX 200 +#define MAXIMUM_ROM_VALUE_INDEX 200 +#define WHILE_NOT_EQUAL_INDEX 241 +#define WHILE_EQUAL_INDEX 242 +#define WHILE_AND_INDEX 243 +#define WHILE_NOT_AND_INDEX 244 +#define DELAY_10USEC_INDEX 245 +#define LAST_COMMAND_INDEX 255 + +#define MAXIMUM_RAM_ADDRESSES 32 +#define MAXIMUM_RAM_VALUES 32 + +#define MAXIMUM_COMMANDS_NUMBER 150 + +struct __attribute__((packed)) eeprom_command +{ + unsigned char address_index; + unsigned char value_index; +}; + +struct __attribute__((packed)) var_eeprom_v2_cfg +{ + u32 variscite_magic; /* == HEX("VAR2")? */ + u8 part_number[16]; + u8 Assembly[16]; + u8 date[12]; + u32 custom_addresses_values[32]; + struct eeprom_command eeprom_commands[MAXIMUM_COMMANDS_NUMBER]; + u8 reserved[34]; + u8 ddr_size; + u8 crc; +}; + +bool var_eeprom_v2_is_valid(struct var_eeprom_v2_cfg *p_var_eeprom_v2_cfg); +void var_eeprom_v2_strings_print(struct var_eeprom_v2_cfg *p_var_eeprom_v2_cfg); +int handle_eeprom_data(struct var_eeprom_v2_cfg *var_eeprom_v2_cfg, \ + u32 *ram_addresses, u32 *ram_values); +int setup_ddr_parameters(struct eeprom_command *eeprom_commands, \ + u32 *ram_addresses, u32 *ram_values); +void load_custom_data(u32 *custom_addresses_values, u32 *ram_addresses, u32 *ram_values); +int var_eeprom_v2_read_struct(struct var_eeprom_v2_cfg *var_eeprom_v2_cfg, \ + unsigned char address); + +#endif /* _MX6VAR_V2_EEPROM_H_ */ diff --git a/board/variscite/mx6var_som/mx6var_som.c b/board/variscite/mx6var_som/mx6var_som.c new file mode 100644 index 0000000..e99690b --- /dev/null +++ b/board/variscite/mx6var_som/mx6var_som.c @@ -0,0 +1,1587 @@ +/* + * Copyright (C) 2012 Freescale Semiconductor, Inc. + * Author: Fabio Estevam <fabio.estevam@freescale.com> + * + * Copyright (C) 2016 Variscite Ltd. All Rights Reserved. + * + * Author: Eran Matityahu <eran.m@variscite.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm/arch/clock.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/iomux.h> +#include <malloc.h> +#include <asm/arch/mx6-pins.h> +#include <asm/errno.h> +#include <asm/gpio.h> +#include <asm/imx-common/mxc_i2c.h> +#include <asm/imx-common/iomux-v3.h> +#include <asm/imx-common/boot_mode.h> +#include <asm/imx-common/video.h> +#include <mmc.h> +#include <fsl_esdhc.h> +#include <micrel.h> +#include <miiphy.h> +#include <netdev.h> +#include <asm/arch/mxc_hdmi.h> +#include <asm/arch/crm_regs.h> +#include <asm/io.h> +#include <asm/arch/sys_proto.h> +#include <i2c.h> +#include <power/pmic.h> +#include <power/pfuze100_pmic.h> +#include <usb.h> +#include <usb/ehci-fsl.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define UART_PAD_CTRL (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_PUS_47K_UP | \ + PAD_CTL_SPEED_LOW | PAD_CTL_DSE_80ohm | \ + PAD_CTL_SRE_FAST | PAD_CTL_HYS) + +#define ENET_PAD_CTRL (PAD_CTL_PUS_100K_UP | \ + PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS) + +#define GPMI_PAD_CTRL0 (PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_PUS_100K_UP) +#define GPMI_PAD_CTRL1 (PAD_CTL_DSE_40ohm | PAD_CTL_SPEED_MED | \ + PAD_CTL_SRE_FAST) +#define GPMI_PAD_CTRL2 (GPMI_PAD_CTRL0 | GPMI_PAD_CTRL1) + +#define PER_VCC_EN_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_PUS_100K_UP | \ + PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS | \ + PAD_CTL_ODE | PAD_CTL_SRE_FAST) + +#define OTG_ID_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 VAR_SOM_BACKLIGHT_EN IMX_GPIO_NR(4, 30) + +bool lvds_enabled=false; + +#ifdef CONFIG_SYS_USE_NAND +static int var_load_file_from_nand(u32 addr, char *filename) +{ + extern int ubi_part(char *part_name, const char *vid_header_offset); + extern int ubifs_init(void); + extern int uboot_ubifs_mount(char *vol_name); + extern int ubifs_load(char *filename, u32 addr, u32 size); + extern void cmd_ubifs_umount(void); + + char *ubi_part_name = "rootfs"; + char *ubifs_vol_name = "ubi0:rootfs"; + + if (ubi_part(ubi_part_name, NULL)) + return -1; + if (ubifs_init()) + return -1; + if (uboot_ubifs_mount(ubifs_vol_name)) + return -1; + + /* Load the file to memory */ + if (ubifs_load(filename, addr, 0)) { + printf("Error: splash file not found %s\n", filename); + cmd_ubifs_umount(); + return -1; + } + cmd_ubifs_umount(); + return 0; +} +#endif + +static int var_load_file_from_mmc(u32 addr, char *filename) +{ +#define FS_TYPE_EXT 2 + extern int fs_set_blk_dev(const char *ifname, const char *dev_part_str, int fstype); + extern int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len, + loff_t *actread); + + loff_t len_read; + +#ifdef CONFIG_SYS_USE_NAND + if (fs_set_blk_dev("mmc", "1:1", FS_TYPE_EXT)) + return -1; +#else + if (fs_set_blk_dev("mmc", "0:2", FS_TYPE_EXT)) + return -1; +#endif + + if (fs_read(filename, addr, 0, 0, &len_read)) { + printf("Error: splash file not found %s\n", filename); + return -1; + } + + printf("%llu bytes read\n", len_read); + return 0; +#undef FS_TYPE_EXT +} + +#ifdef CONFIG_SPLASH_SCREEN +int splash_screen_prepare(void) +{ + char *filename; + const char *addr_str; + u32 addr = 0; +#ifdef CONFIG_SYS_USE_NAND + char *s; +#endif + + /* Get filename and load address from env */ + addr_str = getenv("splashimage"); + if (!addr_str) { + return -1; + } + addr = simple_strtoul(addr_str, 0, 16); + if (addr == 0) { + printf("Error: bad splashimage value %s\n", addr_str); + return -1; + } + filename = getenv("splash_filename"); + if (!filename) { + printf("Error: splashimage defined, but splash_filename isn't\n"); + return -1; + } + +#ifdef CONFIG_SYS_USE_NAND + s = getenv("chosen_rootfs"); + if ((s != NULL) && (!strcmp(s, "emmc"))) { + if (var_load_file_from_mmc(addr, filename)) + return -1; + } else { + if (var_load_file_from_nand(addr, filename)) + return -1; + } +#else /* MMC */ + if (var_load_file_from_mmc(addr, filename)) + return -1; +#endif + + /* Turn on backlight */ + if (lvds_enabled) + gpio_set_value(VAR_SOM_BACKLIGHT_EN, 1); + + return 0; +} +#endif + +static bool is_som_solo(void) +{ + bool ret; + int oldbus = i2c_get_bus_num(); + + i2c_set_bus_num(PMIC_I2C_BUS); + /* Probing for PMIC which is not preset only on som solo */ + ret = (0 != i2c_probe(CONFIG_POWER_PFUZE100_I2C_ADDR)); + + i2c_set_bus_num(oldbus); + return ret; +} + +static bool is_solo_custom_board(void) +{ + bool ret; + int oldbus = i2c_get_bus_num(); + + i2c_set_bus_num(1); + /* Probing for extra EEPROM present only on solo custom board */ + ret = (0 == i2c_probe(0x51)); + + i2c_set_bus_num(oldbus); + return ret; +} + +static bool is_cpu_pop_package(void) +{ + uint soc_sbmr = readl(SRC_BASE_ADDR + 0x4); + struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR; + u32 reg; + u32 type; + + reg = readl(&anatop->digprog); + type = ((reg >> 16) & 0xff); + if (type != MXC_CPU_MX6DL) + return ((soc_sbmr & 0x200000) != 0); + return false; +} + +static inline bool is_dart_board(void) +{ + return is_cpu_pop_package(); +} + +static inline bool is_mx6_custom_board(void) +{ + return (!is_dart_board() && !is_solo_custom_board()); +} + +enum mmc_boot_device { + SD_BOOT, + MMC_BOOT, + OTHER_BOOT, +}; + +static unsigned get_mmc_boot_device(void) +{ + struct src *psrc = (struct src *)SRC_BASE_ADDR; + unsigned reg = (readl(&psrc->sbmr1) >> 5) & 0x7; + + switch(reg) { + case 0x2: + return SD_BOOT; + case 0x3: + return MMC_BOOT; + default: + return OTHER_BOOT; + } +} + +static bool is_mmc_present(struct mmc *mmc) +{ + int err; + struct mmc_cmd cmd; + + if (mmc->has_init) + return true; + + mdelay(1); + cmd.cmdidx = MMC_CMD_GO_IDLE_STATE; + cmd.cmdarg = 0; + cmd.resp_type = MMC_RSP_NONE; + + err = mmc->cfg->ops->send_cmd(mmc, &cmd, NULL); + if (err) + return false; + + mdelay(2); + + cmd.cmdidx = MMC_CMD_SEND_OP_COND; + cmd.resp_type = MMC_RSP_R3; + cmd.cmdarg = 0; + + err = mmc->cfg->ops->send_cmd(mmc, &cmd, NULL); + return (!err); +} + +static void print_emmc_size(void) +{ + struct mmc *mmc; + int device; + + if (is_dart_board() && (MMC_BOOT == get_mmc_boot_device())) + device=0; + else + device=1; + + mmc = find_mmc_device(device); + if (!mmc || !is_mmc_present(mmc) || mmc_init(mmc) || IS_SD(mmc)) { + puts("No eMMC\n"); + return; + } + puts("eMMC: "); + print_size(mmc->capacity, "\n"); +} + +static u32 var_ram_size(void) +{ + u32 *p_ram_size = (u32 *)RAM_SIZE_ADDR; + return *p_ram_size; +} + +int dram_init(void) +{ + gd->ram_size = var_ram_size() * 1024 * 1024; + return 0; +} + +static iomux_v3_cfg_t const uart1_pads[] = { + IOMUX_PADS(PAD_CSI0_DAT10__UART1_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)), + IOMUX_PADS(PAD_CSI0_DAT11__UART1_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)), +}; + +static iomux_v3_cfg_t const enet_pads1[] = { + IOMUX_PADS(PAD_ENET_MDIO__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL)), + IOMUX_PADS(PAD_ENET_MDC__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL)), + IOMUX_PADS(PAD_RGMII_TXC__RGMII_TXC | MUX_PAD_CTRL(ENET_PAD_CTRL)), + IOMUX_PADS(PAD_RGMII_TD0__RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL)), + IOMUX_PADS(PAD_RGMII_TD1__RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL)), + IOMUX_PADS(PAD_RGMII_TD2__RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL)), + IOMUX_PADS(PAD_RGMII_TD3__RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL)), + IOMUX_PADS(PAD_RGMII_TX_CTL__RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL)), + IOMUX_PADS(PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL)), + /* pin 35 - 1 (PHY_AD2) on reset */ + IOMUX_PADS(PAD_RGMII_RXC__GPIO6_IO30 | MUX_PAD_CTRL(NO_PAD_CTRL)), + /* pin 32 - 1 - (MODE0) all */ + IOMUX_PADS(PAD_RGMII_RD0__GPIO6_IO25 | MUX_PAD_CTRL(NO_PAD_CTRL)), + /* pin 31 - 1 - (MODE1) all */ + IOMUX_PADS(PAD_RGMII_RD1__GPIO6_IO27 | MUX_PAD_CTRL(NO_PAD_CTRL)), + /* pin 28 - 1 - (MODE2) all */ + IOMUX_PADS(PAD_RGMII_RD2__GPIO6_IO28 | MUX_PAD_CTRL(NO_PAD_CTRL)), + /* pin 27 - 1 - (MODE3) all */ + IOMUX_PADS(PAD_RGMII_RD3__GPIO6_IO29 | MUX_PAD_CTRL(NO_PAD_CTRL)), + /* pin 33 - 1 - (CLK125_EN) 125Mhz clockout enabled */ + IOMUX_PADS(PAD_RGMII_RX_CTL__GPIO6_IO24 | MUX_PAD_CTRL(NO_PAD_CTRL)), + /* AR8031 PHY Reset */ + IOMUX_PADS(PAD_ENET_CRS_DV__GPIO1_IO25 | MUX_PAD_CTRL(NO_PAD_CTRL)), +}; + +static iomux_v3_cfg_t const enet_pads2[] = { + IOMUX_PADS(PAD_RGMII_RXC__RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL)), + IOMUX_PADS(PAD_RGMII_RD0__RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL)), + IOMUX_PADS(PAD_RGMII_RD1__RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL)), + IOMUX_PADS(PAD_RGMII_RD2__RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL)), + IOMUX_PADS(PAD_RGMII_RD3__RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL)), + IOMUX_PADS(PAD_RGMII_RX_CTL__RGMII_RX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL)), +}; + +static void setup_iomux_enet(void) +{ + gpio_direction_output(IMX_GPIO_NR(1, 25), 0); /* Variscite SOM PHY reset */ + gpio_direction_output(IMX_GPIO_NR(6, 30), 1); + gpio_direction_output(IMX_GPIO_NR(6, 25), 1); + gpio_direction_output(IMX_GPIO_NR(6, 27), 1); + gpio_direction_output(IMX_GPIO_NR(6, 28), 1); + gpio_direction_output(IMX_GPIO_NR(6, 29), 1); + + SETUP_IOMUX_PADS(enet_pads1); + + gpio_direction_output(IMX_GPIO_NR(6, 24), 1); + + /* Need delay 10ms according to KSZ9021 spec */ + mdelay(10); + gpio_set_value(IMX_GPIO_NR(1, 25), 1); + + SETUP_IOMUX_PADS(enet_pads2); +} + +static iomux_v3_cfg_t const usdhc1_pads[] = { + IOMUX_PADS(PAD_SD1_CLK__SD1_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL)), + IOMUX_PADS(PAD_SD1_CMD__SD1_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL)), + IOMUX_PADS(PAD_SD1_DAT0__SD1_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), + IOMUX_PADS(PAD_SD1_DAT1__SD1_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), + IOMUX_PADS(PAD_SD1_DAT2__SD1_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), + IOMUX_PADS(PAD_SD1_DAT3__SD1_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), +}; + + +static iomux_v3_cfg_t const usdhc2_pads[] = { + IOMUX_PADS(PAD_SD2_CLK__SD2_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL)), + IOMUX_PADS(PAD_SD2_CMD__SD2_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL)), + IOMUX_PADS(PAD_SD2_DAT0__SD2_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), + IOMUX_PADS(PAD_SD2_DAT1__SD2_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), + IOMUX_PADS(PAD_SD2_DAT2__SD2_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), + IOMUX_PADS(PAD_SD2_DAT3__SD2_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), +}; + +static iomux_v3_cfg_t const usdhc3_pads[] = { + IOMUX_PADS(PAD_SD3_CLK__SD3_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL)), + IOMUX_PADS(PAD_SD3_CMD__SD3_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL)), + IOMUX_PADS(PAD_SD3_DAT0__SD3_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), + IOMUX_PADS(PAD_SD3_DAT1__SD3_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), + IOMUX_PADS(PAD_SD3_DAT2__SD3_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), + IOMUX_PADS(PAD_SD3_DAT3__SD3_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), +}; + +#ifdef CONFIG_SYS_I2C_MXC +I2C_PADS(i2c_pad_info1, + PAD_CSI0_DAT9__I2C1_SCL | MUX_PAD_CTRL(I2C_PAD_CTRL), + PAD_CSI0_DAT9__GPIO5_IO27 | MUX_PAD_CTRL(I2C_PAD_CTRL), + IMX_GPIO_NR(5, 27), + PAD_CSI0_DAT8__I2C1_SDA | MUX_PAD_CTRL(I2C_PAD_CTRL), + PAD_CSI0_DAT8__GPIO5_IO26 | MUX_PAD_CTRL(I2C_PAD_CTRL), + IMX_GPIO_NR(5, 26)); + +I2C_PADS(i2c_pad_info2, + PAD_KEY_COL3__I2C2_SCL | MUX_PAD_CTRL(I2C_PAD_CTRL), + PAD_KEY_COL3__GPIO4_IO12 | MUX_PAD_CTRL(I2C_PAD_CTRL), + IMX_GPIO_NR(4, 12), + PAD_KEY_ROW3__I2C2_SDA | MUX_PAD_CTRL(I2C_PAD_CTRL), + PAD_KEY_ROW3__GPIO4_IO13 | MUX_PAD_CTRL(I2C_PAD_CTRL), + IMX_GPIO_NR(4, 13)); + +I2C_PADS(i2c_pad_info3, + PAD_GPIO_5__I2C3_SCL | MUX_PAD_CTRL(I2C_PAD_CTRL), + PAD_GPIO_5__GPIO1_IO05 | MUX_PAD_CTRL(I2C_PAD_CTRL), + IMX_GPIO_NR(1, 5), + PAD_GPIO_16__I2C3_SDA | MUX_PAD_CTRL(I2C_PAD_CTRL), + PAD_GPIO_16__GPIO7_IO11 | MUX_PAD_CTRL(I2C_PAD_CTRL), + IMX_GPIO_NR(7, 11)); +#endif + +void setup_local_i2c(void) { + setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, I2C_PADS_INFO(i2c_pad_info1)); + setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, I2C_PADS_INFO(i2c_pad_info2)); + setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, I2C_PADS_INFO(i2c_pad_info3)); +} + +iomux_v3_cfg_t const di0_pads[] = { + IOMUX_PADS(PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK), /* DISP0_CLK */ + IOMUX_PADS(PAD_DI0_PIN2__IPU1_DI0_PIN02), /* DISP0_HSYNC */ + IOMUX_PADS(PAD_DI0_PIN3__IPU1_DI0_PIN03), /* DISP0_VSYNC */ +}; + +static void var_setup_iomux_per_vcc_en(void) +{ + SETUP_IOMUX_PAD(PAD_EIM_D31__GPIO3_IO31 | MUX_PAD_CTRL(PER_VCC_EN_PAD_CTRL)); + gpio_direction_output(IMX_GPIO_NR(3, 31), 1); +} + +static void setup_iomux_uart(void) +{ + SETUP_IOMUX_PADS(uart1_pads); +} + +#ifdef CONFIG_FSL_ESDHC +struct fsl_esdhc_cfg usdhc_cfg[2] = { + /* + * This is incorrect for DART board but it's overwritten + * in board_mmc_init() according to board setup + */ + {USDHC2_BASE_ADDR}, + {USDHC1_BASE_ADDR}, +}; + +int board_mmc_getcd(struct mmc *mmc) +{ + return 1; +} + +int board_mmc_init(bd_t *bis) +{ +#ifndef CONFIG_SPL_BUILD + int ret; + int i; + + /* + * According to the board_mmc_init() the following map is done: + * (U-Boot device node) (Physical Port) + * On non DART boards: + * mmc0 SD2 (SD) + * mmc1 SD1 (eMMC) + * + * On DART board when booting from SD: + * mmc0 SD2 (SD) + * mmc1 SD3 (eMMC) + * + * On DART board when booting from eMMC: + * mmc0 SD3 (eMMC) + * mmc1 SD2 (SD) + */ + for (i = 0; i < CONFIG_SYS_FSL_USDHC_NUM; i++) { + switch (i) { + case 0: + if (is_dart_board() && (MMC_BOOT == get_mmc_boot_device())) { + SETUP_IOMUX_PADS(usdhc3_pads); + usdhc_cfg[0].esdhc_base = USDHC3_BASE_ADDR; + usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK); + } else { + SETUP_IOMUX_PADS(usdhc2_pads); + usdhc_cfg[0].esdhc_base = USDHC2_BASE_ADDR; + usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK); + } + gd->arch.sdhc_clk = usdhc_cfg[0].sdhc_clk; + usdhc_cfg[0].max_bus_width = 4; + break; + case 1: + if (is_dart_board() && (MMC_BOOT == get_mmc_boot_device())) { + SETUP_IOMUX_PADS(usdhc2_pads); + usdhc_cfg[1].esdhc_base = USDHC2_BASE_ADDR; + usdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK); + } else if (is_dart_board()) { + SETUP_IOMUX_PADS(usdhc3_pads); + usdhc_cfg[1].esdhc_base = USDHC3_BASE_ADDR; + usdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK); + } else { + SETUP_IOMUX_PADS(usdhc1_pads); + usdhc_cfg[1].esdhc_base = USDHC1_BASE_ADDR; + usdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK); + } + gd->arch.sdhc_clk = usdhc_cfg[1].sdhc_clk; + usdhc_cfg[1].max_bus_width = 4; + break; + default: + printf("Warning: you configured more USDHC controllers" + "(%d) then supported by the board (%d)\n", + i + 1, CONFIG_SYS_FSL_USDHC_NUM); + return -EINVAL; + } + + ret = fsl_esdhc_initialize(bis, &usdhc_cfg[i]); + if (ret) + return ret; + } + return 0; +#else + struct src *psrc = (struct src *)SRC_BASE_ADDR; + unsigned reg = readl(&psrc->sbmr1) >> 11; + /* + * Upon reading BOOT_CFG register the following map is done: + * Bit 11 and 12 of BOOT_CFG register can determine the current + * mmc port + * 0x1 SD2 (SD) + * 0x2 SD3 (DART eMMC) + */ + + switch (reg & 0x3) { + case 0x1: + SETUP_IOMUX_PADS(usdhc2_pads); + usdhc_cfg[0].esdhc_base = USDHC2_BASE_ADDR; + usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK); + gd->arch.sdhc_clk = usdhc_cfg[0].sdhc_clk; + usdhc_cfg[0].max_bus_width = 4; + break; + case 0x2: + SETUP_IOMUX_PADS(usdhc3_pads); + usdhc_cfg[0].esdhc_base = USDHC3_BASE_ADDR; + usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK); + gd->arch.sdhc_clk = usdhc_cfg[0].sdhc_clk; + usdhc_cfg[0].max_bus_width = 4; + break; + } + + return fsl_esdhc_initialize(bis, &usdhc_cfg[0]); +#endif +} +#endif + +#ifdef CONFIG_SYS_USE_NAND +static iomux_v3_cfg_t const gpmi_pads[] = { + IOMUX_PADS(PAD_NANDF_CLE__NAND_CLE | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), + IOMUX_PADS(PAD_NANDF_ALE__NAND_ALE | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), + IOMUX_PADS(PAD_NANDF_WP_B__NAND_WP_B | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), + IOMUX_PADS(PAD_NANDF_RB0__NAND_READY_B | MUX_PAD_CTRL(GPMI_PAD_CTRL0)), + IOMUX_PADS(PAD_NANDF_CS0__NAND_CE0_B | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), + IOMUX_PADS(PAD_SD4_CMD__NAND_RE_B | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), + IOMUX_PADS(PAD_SD4_CLK__NAND_WE_B | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), + IOMUX_PADS(PAD_NANDF_D0__NAND_DATA00 | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), + IOMUX_PADS(PAD_NANDF_D1__NAND_DATA01 | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), + IOMUX_PADS(PAD_NANDF_D2__NAND_DATA02 | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), + IOMUX_PADS(PAD_NANDF_D3__NAND_DATA03 | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), + IOMUX_PADS(PAD_NANDF_D4__NAND_DATA04 | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), + IOMUX_PADS(PAD_NANDF_D5__NAND_DATA05 | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), + IOMUX_PADS(PAD_NANDF_D6__NAND_DATA06 | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), + IOMUX_PADS(PAD_NANDF_D7__NAND_DATA07 | MUX_PAD_CTRL(GPMI_PAD_CTRL2)), + IOMUX_PADS(PAD_SD4_DAT0__NAND_DQS | MUX_PAD_CTRL(GPMI_PAD_CTRL1)), +}; + +static void setup_gpmi_nand(void) +{ + struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; + + SETUP_IOMUX_PADS(gpmi_pads); + + /* gate ENFC_CLK_ROOT clock first,before clk source switch */ + clrbits_le32(&mxc_ccm->CCGR2, MXC_CCM_CCGR2_IOMUX_IPT_CLK_IO_MASK); + + /* config gpmi and bch clock to 100 MHz */ + clrsetbits_le32(&mxc_ccm->cs2cdr, + MXC_CCM_CS2CDR_ENFC_CLK_PODF_MASK | + MXC_CCM_CS2CDR_ENFC_CLK_PRED_MASK | + MXC_CCM_CS2CDR_ENFC_CLK_SEL_MASK, + MXC_CCM_CS2CDR_ENFC_CLK_PODF(0) | + MXC_CCM_CS2CDR_ENFC_CLK_PRED(3) | + MXC_CCM_CS2CDR_ENFC_CLK_SEL(3)); + + /* enable ENFC_CLK_ROOT clock */ + setbits_le32(&mxc_ccm->CCGR2, MXC_CCM_CCGR2_IOMUX_IPT_CLK_IO_MASK); + + /* enable gpmi and bch clock gating */ + setbits_le32(&mxc_ccm->CCGR4, + MXC_CCM_CCGR4_RAWNAND_U_BCH_INPUT_APB_MASK | + MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_BCH_MASK | + MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_MASK | + MXC_CCM_CCGR4_RAWNAND_U_GPMI_INPUT_APB_MASK | + MXC_CCM_CCGR4_PL301_MX6QPER1_BCH_OFFSET); + + /* enable apbh clock gating */ + setbits_le32(&mxc_ccm->CCGR0, MXC_CCM_CCGR0_APBHDMA_MASK); +} +#endif + +int board_phy_config(struct phy_device *phydev) +{ + /* min rx data delay */ + ksz9021_phy_extended_write(phydev, + MII_KSZ9021_EXT_RGMII_RX_DATA_SKEW, 0x0); + /* min tx data delay */ + ksz9021_phy_extended_write(phydev, + MII_KSZ9021_EXT_RGMII_TX_DATA_SKEW, 0x0); + /* max rx/tx clock delay, min rx/tx control */ + ksz9021_phy_extended_write(phydev, + MII_KSZ9021_EXT_RGMII_CLOCK_SKEW, 0xf0f0); + + if (phydev->drv->config) + phydev->drv->config(phydev); + + return 0; +} + +#if defined(CONFIG_VIDEO_IPUV3) +static void disable_lvds(struct display_info_t const *dev) +{ + struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; + + int reg = readl(&iomux->gpr[2]); + + reg &= ~(IOMUXC_GPR2_LVDS_CH0_MODE_MASK | + IOMUXC_GPR2_LVDS_CH1_MODE_MASK); + + writel(reg, &iomux->gpr[2]); +} + +static void do_enable_hdmi(struct display_info_t const *dev) +{ + disable_lvds(dev); + /* + * imx_enable_hdmi_phy(); should be called here. + * It is ommitted to avoid a current known bug where + * the boot sometimes hangs if an HDMI cable is attached + * - at least on some DART SOMs. + */ +} + +static void enable_lvds(struct display_info_t const *dev) +{ + struct iomuxc *iomux = (struct iomuxc *) + IOMUXC_BASE_ADDR; + u32 reg = readl(&iomux->gpr[2]); + reg |= IOMUXC_GPR2_DATA_WIDTH_CH0_24BIT | + IOMUXC_GPR2_DATA_WIDTH_CH1_18BIT; + writel(reg, &iomux->gpr[2]); + + lvds_enabled=true; +} + +static void lvds_enable_disable(struct display_info_t const *dev) +{ + if (getenv("splashimage") != NULL) + enable_lvds(dev); + else + disable_lvds(dev); +} + +static int detect_dart_vsc_display(struct display_info_t const *dev) +{ + return (!is_mx6_custom_board()); +} + +static int detect_mx6cb_cdisplay(struct display_info_t const *dev) +{ + if (!is_mx6_custom_board()) + return 0; + + i2c_set_bus_num(dev->bus); + return (0 == i2c_probe(dev->addr)); +} + +static int detect_mx6cb_rdisplay(struct display_info_t const *dev) +{ + if (!is_mx6_custom_board()) + return 0; + + /* i2c probe the *c*display */ + i2c_set_bus_num(MX6CB_CDISPLAY_I2C_BUS); + return (0 != i2c_probe(MX6CB_CDISPLAY_I2C_ADDR)); +} + +#define MHZ2PS(f) (1000000/(f)) + +struct display_info_t const displays[] = {{ + .bus = -1, + .addr = 0, + .pixfmt = IPU_PIX_FMT_RGB24, + .detect = detect_hdmi, + .enable = do_enable_hdmi, + .mode = { + .name = "HDMI", + .refresh = 60, + .xres = 800, + .yres = 480, + .pixclock = 31777, + .left_margin = 48, + .right_margin = 16, + .upper_margin = 33, + .lower_margin = 10, + .hsync_len = 96, + .vsync_len = 2, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED +} }, { + .bus = -1, + .addr = 0, + .pixfmt = IPU_PIX_FMT_RGB666, + .detect = detect_dart_vsc_display, + .enable = lvds_enable_disable, + .mode = { + .name = "VAR-WVGA", + .refresh = 60, /* optional */ + .xres = 800, + .yres = 480, + .pixclock = MHZ2PS(50), + .left_margin = 40, + .right_margin = 40, + .upper_margin = 29, + .lower_margin = 13, + .hsync_len = 48, + .vsync_len = 3, + .sync = FB_SYNC_EXT, + .vmode = FB_VMODE_NONINTERLACED +} }, { + .bus = MX6CB_CDISPLAY_I2C_BUS, + .addr = MX6CB_CDISPLAY_I2C_ADDR, + .pixfmt = IPU_PIX_FMT_RGB24, + .detect = detect_mx6cb_cdisplay, + .enable = lvds_enable_disable, + .mode = { + .name = "VAR-WVGA MX6CB-C", + .refresh = 60, /* optional */ + .xres = 800, + .yres = 480, + .pixclock = MHZ2PS(50), + .left_margin = 39, + .right_margin = 39, + .upper_margin = 29, + .lower_margin = 13, + .hsync_len = 128, + .vsync_len = 2, + .sync = FB_SYNC_EXT, + .vmode = FB_VMODE_NONINTERLACED +} }, { + .bus = -1, + .addr = 0, + .pixfmt = IPU_PIX_FMT_RGB24, + .detect = detect_mx6cb_rdisplay, + .enable = lvds_enable_disable, + .mode = { + .name = "VAR-WVGA MX6CB-R", + .refresh = 60, /* optional */ + .xres = 800, + .yres = 480, + .pixclock = MHZ2PS(50), + .left_margin = 0, + .right_margin = 40, + .upper_margin = 20, + .lower_margin = 13, + .hsync_len = 48, + .vsync_len = 3, + .sync = FB_SYNC_EXT, + .vmode = FB_VMODE_NONINTERLACED +} } }; + +size_t display_count = ARRAY_SIZE(displays); + +static void setup_display(void) +{ + struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; + struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; + int reg; + + /* Setup backlight */ + SETUP_IOMUX_PAD(PAD_DISP0_DAT9__GPIO4_IO30 | MUX_PAD_CTRL(ENET_PAD_CTRL)); + + /* Turn off backlight until display is ready */ + gpio_direction_output(VAR_SOM_BACKLIGHT_EN , 0); + + /* Setup HSYNC, VSYNC, DISP_CLK for debugging purposes */ + SETUP_IOMUX_PADS(di0_pads); + + enable_ipu_clock(); + imx_setup_hdmi(); + + /* Turn on LDB0, LDB1, IPU,IPU DI0 clocks */ + reg = readl(&mxc_ccm->CCGR3); + reg |= MXC_CCM_CCGR3_LDB_DI0_MASK | MXC_CCM_CCGR3_LDB_DI1_MASK; + writel(reg, &mxc_ccm->CCGR3); + + /* set LDB0, LDB1 clk select to 011/011 */ + reg = readl(&mxc_ccm->cs2cdr); + reg &= ~(MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK + | MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_MASK); + /* 1 -> ~50MHz , 2 -> ~56MHz, 3 -> ~75MHz, 4 -> ~68MHz */ + reg |= (1 << MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET) + | (1 << MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_OFFSET); + writel(reg, &mxc_ccm->cs2cdr); + + reg = readl(&mxc_ccm->cscmr2); + reg |= MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV | MXC_CCM_CSCMR2_LDB_DI1_IPU_DIV; + writel(reg, &mxc_ccm->cscmr2); + + reg = readl(&mxc_ccm->chsccdr); + reg |= (CHSCCDR_CLK_SEL_LDB_DI0 + << MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET); + reg |= (CHSCCDR_CLK_SEL_LDB_DI0 + << MXC_CCM_CHSCCDR_IPU1_DI1_CLK_SEL_OFFSET); + writel(reg, &mxc_ccm->chsccdr); + + reg = IOMUXC_GPR2_BGREF_RRMODE_EXTERNAL_RES + | IOMUXC_GPR2_DI1_VS_POLARITY_ACTIVE_LOW + | IOMUXC_GPR2_DI0_VS_POLARITY_ACTIVE_LOW + | IOMUXC_GPR2_BIT_MAPPING_CH1_SPWG + | IOMUXC_GPR2_DATA_WIDTH_CH1_18BIT + | IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG + | IOMUXC_GPR2_DATA_WIDTH_CH0_24BIT + | IOMUXC_GPR2_LVDS_CH0_MODE_ENABLED_DI0 + | IOMUXC_GPR2_LVDS_CH1_MODE_ENABLED_DI0; + writel(reg, &iomux->gpr[2]); + + reg = readl(&iomux->gpr[3]); + reg = (reg & ~(IOMUXC_GPR3_LVDS1_MUX_CTL_MASK + | IOMUXC_GPR3_HDMI_MUX_CTL_MASK)) + | (IOMUXC_GPR3_MUX_SRC_IPU1_DI0 + << IOMUXC_GPR3_LVDS1_MUX_CTL_OFFSET); + writel(reg, &iomux->gpr[3]); +} +#endif /* CONFIG_VIDEO_IPUV3 */ + +/* + * Do not overwrite the console + * Use always serial for U-Boot console + */ +int overwrite_console(void) +{ + return 1; +} + +int board_eth_init(bd_t *bis) +{ + uint32_t base = IMX_FEC_BASE; + struct mii_dev *bus = NULL; + struct phy_device *phydev = NULL; + int ret; + + setup_iomux_enet(); + +#ifdef CONFIG_FEC_MXC + bus = fec_get_miibus(base, -1); + + if (!bus) { + printf("FEC MXC bus: %s:failed\n", __func__); + return 0; + } + /* "scan" phy 7 */ + phydev = phy_find_by_mask(bus, (0x1 << 7), PHY_INTERFACE_MODE_RGMII); + if (!phydev) { + printf("FEC MXC phy find: %s:failed\n", __func__); + free(bus); + return 0; + } + printf("using phy at %d\n", phydev->addr); + + ret = fec_probe(bis, -1, base, bus, phydev); + if (ret) { + printf("FEC MXC probe: %s:failed\n", __func__); + free(phydev); + free(bus); + } +#endif + +#ifdef CONFIG_USB_ETHER + /* OTG - Ethernet Gadget */ + usb_eth_initialize(bis); +#endif + + return 0; +} + +#ifdef CONFIG_USB_EHCI_MX6 +#define VSC_USB_H1_PWR_EN IMX_GPIO_NR(4, 15) +#define VSC_USB_OTG_PWR_EN IMX_GPIO_NR(3, 22) +#define DART_USB_H1_PWR_EN IMX_GPIO_NR(1, 28) +#define DART_USB_OTG_PWR_EN IMX_GPIO_NR(4, 15) + +static void setup_usb(void) +{ + if (is_dart_board()) { + /* config OTG ID iomux */ + SETUP_IOMUX_PAD(PAD_ENET_RX_ER__USB_OTG_ID | MUX_PAD_CTRL(OTG_ID_PAD_CTRL)); + imx_iomux_set_gpr_register(1, 13, 1, 0); + + SETUP_IOMUX_PAD(PAD_KEY_ROW4__GPIO4_IO15 | MUX_PAD_CTRL(NO_PAD_CTRL)); + gpio_direction_output(DART_USB_OTG_PWR_EN, 0); + + SETUP_IOMUX_PAD(PAD_ENET_TX_EN__GPIO1_IO28 | MUX_PAD_CTRL(NO_PAD_CTRL)); + gpio_direction_output(DART_USB_H1_PWR_EN, 0); + } else if (is_solo_custom_board()) { + /* config OTG ID iomux */ + SETUP_IOMUX_PAD(PAD_GPIO_1__USB_OTG_ID | MUX_PAD_CTRL(OTG_ID_PAD_CTRL)); + imx_iomux_set_gpr_register(1, 13, 1, 1); + + SETUP_IOMUX_PAD(PAD_EIM_D22__GPIO3_IO22 | MUX_PAD_CTRL(NO_PAD_CTRL)); + gpio_direction_output(VSC_USB_OTG_PWR_EN, 0); + + SETUP_IOMUX_PAD(PAD_KEY_ROW4__GPIO4_IO15 | MUX_PAD_CTRL(NO_PAD_CTRL)); + gpio_direction_output(VSC_USB_H1_PWR_EN, 0); + } +} + +int board_usb_phy_mode(int port) +{ + char *s; + if (is_mx6_custom_board() && port==0) { + s = getenv("usbmode"); + if ((s != NULL) && (!strcmp(s, "host"))) + return USB_INIT_HOST; + else + return USB_INIT_DEVICE; + } + return usb_phy_mode(port); +} + +/* + * int board_ehci_hcd_init(int port) + * { + * if (is_dart_board() || is_solo_custom_board()) { + * no hub to reset + * } else if (is_mx6_custom_board()) { + * hub present but pulled up + * } + * + * return 0; + * } + */ + +int board_ehci_power(int port, int on) +{ + if (is_mx6_custom_board()) + return 0; /* no power enable needed */ + + if (port > 1) + return -EINVAL; + + if (port) { + if (is_dart_board()) + gpio_set_value(DART_USB_H1_PWR_EN, on); + else if (is_solo_custom_board()) + gpio_set_value(VSC_USB_H1_PWR_EN, on); + } else { + if (is_dart_board()) + gpio_set_value(DART_USB_OTG_PWR_EN, on); + else if (is_solo_custom_board()) + gpio_set_value(VSC_USB_OTG_PWR_EN, on); + } + + return 0; +} +#endif /* CONFIG_USB_EHCI_MX6 */ + +int board_early_init_f(void) +{ + var_setup_iomux_per_vcc_en(); + + setup_iomux_uart(); +#if defined(CONFIG_VIDEO_IPUV3) + setup_display(); +#endif +#ifdef CONFIG_SYS_I2C_MXC + setup_local_i2c(); +#endif +#ifdef CONFIG_SYS_USE_NAND + setup_gpmi_nand(); +#endif + + return 0; +} + +int board_init(void) +{ + int ret = 0; + + /* address of boot parameters */ + gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100; + gd->bd->bi_arch_number = CONFIG_MACH_VAR_SOM_MX6; + +#ifdef CONFIG_USB_EHCI_MX6 + setup_usb(); +#endif + return ret; +} + +static struct pmic *pfuze; + +static void set_anatop_bypass(void) +{ + struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR; + u32 reg = readl(&anatop->reg_core); + + /* bypass VDDARM/VDDSOC */ + reg |= (0x1F << 18) | 0x1F; + writel(reg, &anatop->reg_core); +} + +static void ldo_mode_set(void) +{ + if (!is_som_solo()) { + unsigned int reg; + struct pmic *p = pfuze; + int retval = 0; + + if (!p) { + printf("No PMIC found!\n"); + return; + } + + /* Set SW1AB to 1.325V */ + retval += pmic_reg_read(p, PFUZE100_SW1ABVOL, ®); + reg &= ~SW1x_NORMAL_MASK; + reg |= SW1x_1_325V; + retval += pmic_reg_write(p, PFUZE100_SW1ABVOL, reg); + + /* Set SW1C to 1.325V */ + retval += pmic_reg_read(p, PFUZE100_SW1CVOL, ®); + reg &= ~SW1x_NORMAL_MASK; + reg |= SW1x_1_325V; + retval += pmic_reg_write(p, PFUZE100_SW1CVOL, reg); + + if (retval) { + printf("PMIC write voltages error!\n"); + return; + } + + set_anatop_bypass(); + printf("switch to ldo_bypass mode!\n"); + } +} + +int power_init_board(void) +{ + if (!is_som_solo()) { + unsigned int reg; + int retval; + + retval = power_pfuze100_init(PMIC_I2C_BUS); + if (retval) + return -ENODEV; + pfuze = pmic_get("PFUZE100"); + retval = pmic_probe(pfuze); + if (retval) + return -ENODEV; + pmic_reg_read(pfuze, PFUZE100_DEVICEID, ®); + printf("PMIC: PFUZE100 ID=0x%02x\n", reg); + + if (!is_dart_board()) { + + /* Set Gigbit Ethernet voltage (SOM v1.1/1.0) */ + retval += pmic_reg_read(pfuze, PFUZE100_SW4VOL, ®); + reg &= ~0x7f; + reg |= 0x60; /* 2.4V */ + retval += pmic_reg_write(pfuze, PFUZE100_SW4VOL, reg); + + /* Increase VGEN5 from 2.8 to 3V */ + retval += pmic_reg_read(pfuze, PFUZE100_VGEN5VOL, ®); + reg &= ~LDO_VOL_MASK; + reg |= LDOB_3_00V; + retval += pmic_reg_write(pfuze, PFUZE100_VGEN5VOL, reg); + + /* Set SW1AB standby volage to 0.975V */ + retval += pmic_reg_read(pfuze, PFUZE100_SW1ABSTBY, ®); + reg &= ~SW1x_STBY_MASK; + reg |= SW1x_0_975V; + retval += pmic_reg_write(pfuze, PFUZE100_SW1ABSTBY, reg); + + /* Set SW1AB/VDDARM step ramp up time from 16us to 4us/25mV */ + retval += pmic_reg_read(pfuze, PFUZE100_SW1ABCONF, ®); + reg &= ~SW1xCONF_DVSSPEED_MASK; + reg |= SW1xCONF_DVSSPEED_4US; + retval += pmic_reg_write(pfuze, PFUZE100_SW1ABCONF, reg); + + /* Set SW1C standby voltage to 0.975V */ + retval += pmic_reg_read(pfuze, PFUZE100_SW1CSTBY, ®); + reg &= ~SW1x_STBY_MASK; + reg |= SW1x_0_975V; + retval += pmic_reg_write(pfuze, PFUZE100_SW1CSTBY, reg); + +#ifdef LOW_POWER_MODE_ENABLE + /* Set low power mode voltages to disable */ + + /* Set SW3A standby voltage to 1.275V */ + retval += pmic_reg_read(pfuze, PFUZE100_SW3ASTBY, ®); + reg &= ~0x7f; /* SW3x STBY MASK */ + reg = 0x23; /* SW3x 1.275V */ + retval += pmic_reg_write(pfuze, PFUZE100_SW3ASTBY, reg); + + /* Set SW3A off voltage to 1.275V */ + retval += pmic_reg_read(pfuze, PFUZE100_SW3AOFF, ®); + reg &= ~0x7f; /* SW3x OFF MASK */ + reg = 0x23; /* SW3x 1.275V */ + retval += pmic_reg_write(pfuze, PFUZE100_SW3AOFF, reg); + + /* Set SW2 to 3.2V */ + retval += pmic_reg_read(pfuze, PFUZE100_SW2VOL, ®); + reg &= ~0x7f; + reg |= 0x70; /* SW2x 3.2V */ + retval += pmic_reg_write(pfuze, PFUZE100_SW2VOL, reg); + + /* SW4MODE = OFF in standby */ + reg = PWM_OFF; + retval += pmic_reg_write(pfuze, PFUZE100_SW4MODE, reg); + + /* Set VGEN3 to 2.5V, VGEN3CTL = OFF in standby */ + retval += pmic_reg_read(pfuze, PFUZE100_VGEN3VOL, ®); + reg &= ~0x7f; + reg |= 0x30; /* VGEN3EN, VGEN3STBY, ~VGEN3LPWR */ + reg |= LDOB_2_50V; + retval += pmic_reg_write(pfuze, PFUZE100_VGEN3VOL, reg); +#else + /* Set VGEN3 to 2.5V, VGEN3CTL = low power in standby */ + retval += pmic_reg_read(pfuze, PFUZE100_VGEN3VOL, ®); + reg &= ~0x7f; + reg |= 0x70; /* VGEN3EN, VGEN3STBY, VGEN3LPWR */ + reg |= LDOB_2_50V; + retval += pmic_reg_write(pfuze, PFUZE100_VGEN3VOL, reg); +#endif + } else { + + /* Set SW1AB standby volage to 0.9V */ + retval += pmic_reg_read(pfuze, PFUZE100_SW1ABSTBY, ®); + reg &= ~SW1x_STBY_MASK; + reg |= SW1x_0_900V; + retval += pmic_reg_write(pfuze, PFUZE100_SW1ABSTBY, reg); + + /* Set SW1AB off volage to 0.9V */ + retval += pmic_reg_read(pfuze, PFUZE100_SW1ABOFF, ®); + reg &= ~SW1x_OFF_MASK; + reg |= SW1x_0_900V; + retval += pmic_reg_write(pfuze, PFUZE100_SW1ABOFF, reg); + + /* Set SW1C standby voltage to 0.9V */ + retval += pmic_reg_read(pfuze, PFUZE100_SW1CSTBY, ®); + reg &= ~SW1x_STBY_MASK; + reg |= SW1x_0_900V; + retval += pmic_reg_write(pfuze, PFUZE100_SW1CSTBY, reg); + + /* Set SW1C off volage to 0.9V */ + retval += pmic_reg_read(pfuze, PFUZE100_SW1COFF, ®); + reg &= ~SW1x_OFF_MASK; + reg |= SW1x_0_900V; + retval += pmic_reg_write(pfuze, PFUZE100_SW1COFF, reg); + + /* Set SW2 to 3.3V */ + retval += pmic_reg_read(pfuze, PFUZE100_SW2VOL, ®); + reg &= ~0x7f; /* SW2x NORMAL MASK */ + reg |= 0x72; /* SW2x 3.3V */ + retval += pmic_reg_write(pfuze, PFUZE100_SW2VOL, reg); + + /* Set SW2 standby voltage to 3.2V */ + retval += pmic_reg_read(pfuze, PFUZE100_SW2STBY, ®); + reg &= ~0x7f; /* SW2x STBY MASK */ + reg |= 0x70; /* SW2x 3.2V */ + retval += pmic_reg_write(pfuze, PFUZE100_SW2STBY, reg); + + /* Set SW2 off voltage to 3.2V */ + retval += pmic_reg_read(pfuze, PFUZE100_SW2OFF, ®); + reg &= ~0x7f; /* SW2x OFF MASK */ + reg |= 0x70; /* SW2x 3.2V */ + retval += pmic_reg_write(pfuze, PFUZE100_SW2OFF, reg); + + reg = PWM_PFM; + retval += pmic_reg_write(pfuze, PFUZE100_SW1ABMODE, reg); + + /* Set SW1AB/VDDARM step ramp up time 2us */ + retval += pmic_reg_read(pfuze, PFUZE100_SW1ABCONF, ®); + reg &= ~SW1xCONF_DVSSPEED_MASK; + reg |= SW1xCONF_DVSSPEED_2US; + retval += pmic_reg_write(pfuze, PFUZE100_SW1ABCONF, reg); + + reg = PWM_PFM; + retval += pmic_reg_write(pfuze, PFUZE100_SW1CMODE, reg); + + reg = PWM_PFM; + retval += pmic_reg_write(pfuze, PFUZE100_SW2MODE, reg); + + reg = LDOB_3_30V; + retval += pmic_reg_write(pfuze, PFUZE100_VGEN6VOL, reg); + } + + /* Set SW1C/VDDSOC step ramp up time from 16us to 4us/25mV */ + retval += pmic_reg_read(pfuze, PFUZE100_SW1CCONF, ®); + reg &= ~SW1xCONF_DVSSPEED_MASK; + reg |= SW1xCONF_DVSSPEED_4US; + retval += pmic_reg_write(pfuze, PFUZE100_SW1CCONF, reg); + + if (retval) { + printf("PMIC write voltages error!\n"); + return -1; + } + + ldo_mode_set(); + } + + return 0; +} + +static void update_env(void) +{ + setenv("mmcroot" , "/dev/mmcblk0p2 rootwait rw"); + if (is_cpu_type(MXC_CPU_MX6Q)) { + if (is_dart_board()) { + setenv("fdt_file", "imx6q-var-dart.dtb"); + if (MMC_BOOT == get_mmc_boot_device()) + setenv("mmcroot" , "/dev/mmcblk2p2 rootwait rw"); + else + setenv("mmcroot" , "/dev/mmcblk1p2 rootwait rw"); + } else { + if (is_solo_custom_board()) + setenv("fdt_file", "imx6q-var-som-vsc.dtb"); + else + setenv("fdt_file", "imx6q-var-som.dtb"); + } + } else if (is_cpu_type(MXC_CPU_MX6D)) { + if (is_dart_board()) { + setenv("fdt_file", "imx6q-var-dart.dtb"); + if (MMC_BOOT == get_mmc_boot_device()) + setenv("mmcroot" , "/dev/mmcblk2p2 rootwait rw"); + else + setenv("mmcroot" , "/dev/mmcblk1p2 rootwait rw"); + } else { + setenv("fdt_file", "imx6q-var-som.dtb"); + } + } else if (is_cpu_type(MXC_CPU_MX6DL)) { + if (is_som_solo()) { + if (is_solo_custom_board()) + setenv("fdt_file", "imx6dl-var-som-solo-vsc.dtb"); + else + setenv("fdt_file", "imx6dl-var-som-solo.dtb"); + } else { + setenv("fdt_file", "imx6dl-var-som.dtb"); + } + } else if (is_cpu_type(MXC_CPU_MX6SOLO)) { + if (is_som_solo()) { + if (is_solo_custom_board()) + setenv("fdt_file", "imx6dl-var-som-solo-vsc.dtb"); + else + setenv("fdt_file", "imx6dl-var-som-solo.dtb"); + } else { + setenv("fdt_file", "imx6dl-var-som.dtb"); + } + } +} + +static void imx6_pcie_assert_core_reset(void) +{ + struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR; + + if (is_mx6dqp()) + setbits_le32(&iomuxc_regs->gpr[1], IOMUXC_GPR1_PCIE_SW_RST); + + setbits_le32(&iomuxc_regs->gpr[1], IOMUXC_GPR1_TEST_POWERDOWN); + clrbits_le32(&iomuxc_regs->gpr[1], IOMUXC_GPR1_REF_SSP_EN); +} + +static void imx6_pcie_init_phy(void) +{ + struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR; + + clrbits_le32(&iomuxc_regs->gpr[12], IOMUXC_GPR12_APPS_LTSSM_ENABLE); + + clrsetbits_le32(&iomuxc_regs->gpr[12], + IOMUXC_GPR12_DEVICE_TYPE_MASK, + IOMUXC_GPR12_DEVICE_TYPE_RC); + clrsetbits_le32(&iomuxc_regs->gpr[12], + IOMUXC_GPR12_LOS_LEVEL_MASK, + IOMUXC_GPR12_LOS_LEVEL_9); + + writel((0x0 << IOMUXC_GPR8_PCS_TX_DEEMPH_GEN1_OFFSET) | + (0x0 << IOMUXC_GPR8_PCS_TX_DEEMPH_GEN2_3P5DB_OFFSET) | + (20 << IOMUXC_GPR8_PCS_TX_DEEMPH_GEN2_6DB_OFFSET) | + (127 << IOMUXC_GPR8_PCS_TX_SWING_FULL_OFFSET) | + (127 << IOMUXC_GPR8_PCS_TX_SWING_LOW_OFFSET), + &iomuxc_regs->gpr[8]); +} + +static void imx6_pcie_deassert_core_reset(void) +{ + struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR; + + if (is_mx6dqp()) + clrbits_le32(&iomuxc_regs->gpr[1], IOMUXC_GPR1_PCIE_SW_RST); + + /* + * Wait for the clock to settle a bit, when the clock are sourced + * from the CPU, we need about 30 ms to settle. + */ + mdelay(50); + + /* Enable PCIe */ + clrbits_le32(&iomuxc_regs->gpr[1], IOMUXC_GPR1_TEST_POWERDOWN); + setbits_le32(&iomuxc_regs->gpr[1], IOMUXC_GPR1_REF_SSP_EN); +} + +/* + * Resets the PCIe controller in order to prevent a soft reboot hang + */ +static void imx_pcie_reset(void) +{ + imx6_pcie_assert_core_reset(); + imx6_pcie_init_phy(); + imx6_pcie_deassert_core_reset(); +} + +int board_late_init(void) +{ + char *s; + + print_emmc_size(); + + s = getenv("var_auto_env"); + if (s[0] == 'Y') + update_env(); + + imx_pcie_reset(); + + return 0; +} + +int checkboard(void) +{ + puts("Board: Variscite VAR-SOM-MX6 "); + + if (is_cpu_type(MXC_CPU_MX6Q)) { + puts("Quad"); + if (is_cpu_pop_package()) + puts("-POP"); + + } else if (is_cpu_type(MXC_CPU_MX6D)) { + puts("Dual"); + if (is_cpu_pop_package()) + puts("-POP"); + + } else if (is_cpu_type(MXC_CPU_MX6DL)) { + if (is_som_solo()) + puts("SOM-Dual"); + else + puts("Dual Lite"); + + } else if (is_cpu_type(MXC_CPU_MX6SOLO)) { + if (is_som_solo()) + puts("SOM-Solo"); + else + puts("Solo"); + } else + puts("????"); + + puts("\n"); + return 0; +} + +#ifdef CONFIG_SPL_BUILD +#include <spl.h> +#include <libfdt.h> +#include <asm/arch/mx6-ddr.h> +#include "mx6var_eeprom.h" +#include "mx6var_eeprom_v2.h" + +/* + * Writes RAM size to RAM_SIZE_ADDR so U-Boot can read it + */ +static void var_set_ram_size(u32 ram_size) +{ + u32 *p_ram_size = (u32 *)RAM_SIZE_ADDR; + if (ram_size > 3840) + ram_size=3840; + *p_ram_size = ram_size; +} + +static void print_board_info(int eeprom_rev, void* var_eeprom, u32 ram_size) +{ + u32 boot_device; + u32 max_freq; + + printf("\ni.MX%s SOC P-%s\n", get_imx_type(get_cpu_type()), \ + is_cpu_pop_package() ? "POP" : "STD"); + + max_freq = get_cpu_speed_grade_hz(); + if (!max_freq) + printf("CPU running at %dMHz\n", mxc_get_clock(MXC_ARM_CLK) / 1000000); + else + printf("%d MHz CPU (running at %d MHz)\n", max_freq / 1000000, + mxc_get_clock(MXC_ARM_CLK) / 1000000); + + if (eeprom_rev==1) + var_eeprom_strings_print((struct var_eeprom_cfg *) var_eeprom); + else if (eeprom_rev==2) + var_eeprom_v2_strings_print((struct var_eeprom_v2_cfg *) var_eeprom); + else + return; + + printf("RAM: "); + print_size(ram_size * 1024 * 1024, "\n"); + + printf("Boot Device: "); + boot_device = spl_boot_device(); + switch (boot_device) { + case BOOT_DEVICE_MMC1: + switch (get_mmc_boot_device()) { + case SD_BOOT: + printf("MMC0 (SD)\n"); + break; + case MMC_BOOT: + printf("MMC1 (DART eMMC)\n"); + break; + default: + printf("MMC?\n"); + break; + } + break; + + case BOOT_DEVICE_NAND: + printf("NAND\n"); + break; + + default: + printf("UNKNOWN (%d)\n", boot_device); + break; + } +} + +static int spl_dram_init_by_eeprom(void) +{ + struct var_eeprom_cfg var_eeprom_cfg = {{0}}; + int ret; + + ret = var_eeprom_read_struct(&var_eeprom_cfg); + if (ret) + return SPL_DRAM_INIT_STATUS_ERROR_NO_EEPROM; + + /* is valid Variscite EEPROM? */ + if (!var_eeprom_is_valid(&var_eeprom_cfg)) + return SPL_DRAM_INIT_STATUS_ERROR_NO_EEPROM_STRUCT_DETECTED; + + switch (get_cpu_type()) { + case MXC_CPU_MX6DL: + case MXC_CPU_MX6SOLO: + var_eeprom_mx6dlsl_dram_setup_iomux_from_struct(&var_eeprom_cfg.pinmux_group); + break; + case MXC_CPU_MX6Q: + case MXC_CPU_MX6D: + default: + var_eeprom_mx6qd_dram_setup_iomux_from_struct(&var_eeprom_cfg.pinmux_group); + break; + } + + var_eeprom_dram_init_from_struct(&var_eeprom_cfg); + + var_set_ram_size(var_eeprom_cfg.header.ddr_size); + print_board_info(1, (void*) &var_eeprom_cfg, var_eeprom_cfg.header.ddr_size); + + return SPL_DRAM_INIT_STATUS_OK; +} + +/* + * Bugfix: Fix Freescale wrong processor documentation. + */ +static void spl_mx6qd_dram_setup_iomux_check_reset(void) +{ + volatile struct mx6dq_iomux_ddr_regs *mx6q_ddr_iomux; + u32 cputype = get_cpu_type(); + + if ((cputype == MXC_CPU_MX6D) || (cputype == MXC_CPU_MX6Q)) { + mx6q_ddr_iomux = (struct mx6dq_iomux_ddr_regs *) MX6DQ_IOM_DDR_BASE; + + if (mx6q_ddr_iomux->dram_reset == (u32)0x000C0030) + mx6q_ddr_iomux->dram_reset = (u32)0x00000030; + } +} + +static void ccgr_init(void) +{ + struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; + + writel(0x00C03F3F, &ccm->CCGR0); + writel(0x0030FC03, &ccm->CCGR1); + writel(0x0FFFC000, &ccm->CCGR2); + writel(0x3FF00000, &ccm->CCGR3); + writel(0x00FFF300, &ccm->CCGR4); + writel(0x0F0000C3, &ccm->CCGR5); + writel(0x000003FF, &ccm->CCGR6); +} + +static void gpr_init(void) +{ + struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; + + /* enable AXI cache for VDOA/VPU/IPU */ + writel(0xF00000CF, &iomux->gpr[4]); + /* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */ + writel(0x007F007F, &iomux->gpr[6]); + writel(0x007F007F, &iomux->gpr[7]); +} + +static int spl_dram_init_by_eeprom_v2(void) +{ + u32 ram_addresses[MAXIMUM_RAM_ADDRESSES]; + u32 ram_values[MAXIMUM_RAM_VALUES]; + struct var_eeprom_v2_cfg var_eeprom_v2_cfg = {0}; + int ret, ram_size; + + ret = var_eeprom_v2_read_struct(&var_eeprom_v2_cfg, \ + is_dart_board() ? VAR_DART_EEPROM_CHIP : VAR_MX6_EEPROM_CHIP); + + if (ret) + return SPL_DRAM_INIT_STATUS_ERROR_NO_EEPROM; + + if (!var_eeprom_v2_is_valid(&var_eeprom_v2_cfg)) + return SPL_DRAM_INIT_STATUS_ERROR_NO_EEPROM_STRUCT_DETECTED; + + handle_eeprom_data(&var_eeprom_v2_cfg, ram_addresses, ram_values); + + ram_size = var_eeprom_v2_cfg.ddr_size * 128; + var_set_ram_size(ram_size); + print_board_info(2, (void*) &var_eeprom_v2_cfg, ram_size); + return SPL_DRAM_INIT_STATUS_OK; +} + +static void spl_dram_init(void) +{ + int status; + + status = spl_dram_init_by_eeprom(); + if (status != SPL_DRAM_INIT_STATUS_OK) { + status = spl_dram_init_by_eeprom_v2(); + if (status != SPL_DRAM_INIT_STATUS_OK) { + printf("Error initializing RAM using EEPROM\n"); + hang(); + } + } + spl_mx6qd_dram_setup_iomux_check_reset(); +} + +void board_init_f(ulong dummy) +{ + /* setup AIPS and disable watchdog */ + arch_cpu_init(); + + ccgr_init(); + gpr_init(); + + /* iomux and setup of i2c */ + board_early_init_f(); + + /* setup GP timer */ + timer_init(); + + /* Wait 330ms before starting to print to console */ + mdelay(330); + + /* UART clocks enabled and gd valid - init serial console */ + preloader_console_init(); + + /* DDR initialization */ + spl_dram_init(); + + /* Clear the BSS. */ + memset(__bss_start, 0, __bss_end - __bss_start); + + /* load/boot image from boot device */ + board_init_r(NULL, 0); +} +#endif diff --git a/board/variscite/mx6var_som/u-boot-spl.lds b/board/variscite/mx6var_som/u-boot-spl.lds new file mode 100644 index 0000000..33d8406 --- /dev/null +++ b/board/variscite/mx6var_som/u-boot-spl.lds @@ -0,0 +1,59 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * (C) Copyright 2010 + * Texas Instruments, <www.ti.com> + * Aneesh V <aneesh@ti.com> + * + * Copyright (C) 2016 Variscite Ltd. All Rights Reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE,\ + LENGTH = CONFIG_SPL_MAX_SIZE } +MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \ + LENGTH = CONFIG_SPL_BSS_MAX_SIZE } + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + .text : + { + __start = .; + *(.vectors) + arch/arm/cpu/armv7/start.o (.text*) + *(.text*) + } >.sram + + . = ALIGN(4); + .rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.sram + + . = ALIGN(4); + .data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram + + . = ALIGN(4); + .u_boot_list : { + KEEP(*(SORT(.u_boot_list*_i2c_*))); + } >.sram + + . = ALIGN(4); + __image_copy_end = .; + + .end : + { + *(.__end) + } + + .bss : + { + . = ALIGN(4); + __bss_start = .; + *(.bss*) + . = ALIGN(4); + __bss_end = .; + } >.sram +} diff --git a/board/variscite/mx6var_som/values.inc b/board/variscite/mx6var_som/values.inc new file mode 100644 index 0000000..aafc088 --- /dev/null +++ b/board/variscite/mx6var_som/values.inc @@ -0,0 +1,39 @@ +0x00000000,0x00000010,0x00000013,0x00000017, +0x00000027,0x00000028,0x00000030,0x00000038, +0x00000047,0x00000053,0x00000080,0x000000DD, +0x0000020E,0x00000800,0x00001740,0x0000174C, +0x00001800,0x000026D2,0x00003000,0x00003030, +0x00005800,0x00007800,0x00008000,0x00008033, +0x0000803B,0x00011006,0x00011117,0x00011740, +0x00020000,0x00020025,0x0002002D,0x00020036, +0x00022227,0x00025565,0x0002556D,0x00025576, +0x00048031,0x00048039,0x00080000,0x00081740, +0x000C0000,0x000C0030,0x00130029,0x00160E83, +0x0019002E,0x001C0019,0x001D002C,0x001F0019, +0x001F001F,0x001F002B,0x00220AAC,0x0024001F, +0x00260026,0x00333030,0x00333040,0x003F1023, +0x003F8030,0x003F8038,0x00400000,0x00431023, +0x00450000,0x005A1023,0x006B1023,0x008E1023, +0x008F1023,0x017B017A,0x01FF00DB,0x02008032, +0x0200803A,0x02038030,0x02088032,0x0208803A, +0x0214021C,0x021B08B8,0x02280228,0x02300238, +0x02580258,0x03038038,0x03200314,0x032C0278, +0x033C0350,0x04008032,0x0400803A,0x04008040, +0x04008048,0x04088032,0x0408803A,0x05208030, +0x05208038,0x052C0470,0x052C0520,0x06028030, +0x06028038,0x07208030,0x09408030,0x09444040, +0x0F9F26D2,0x11420000,0x15208030,0x15208038, +0x19408030,0x19408038,0x1B5F01FF,0x20000000, +0x24911492,0x24921492,0x2B35382B,0x3234342C, +0x33333333,0x38362E32,0x38363236,0x38383E3A, +0x3A363446,0x3A38443C,0x3A3F7975,0x3E363A40, +0x3E373A3C,0x3E463E40,0x3F435313,0x4036363A, +0x403C3246,0x40404040,0x421C0216,0x421C0228, +0x423D3843,0x42440244,0x43240334,0x432C0340, +0x4528053C,0x45300544,0x454A61A5,0x46344840, +0x48364A3E,0x484A4C4A,0x4B2B4842,0x4B4A4E4C, +0x555A7974,0x676B5313,0x821A0000,0x83110000, +0x831A0000,0x84190000,0x841A0000,0x8A8F7955, +0xA1390003,0xB66D8B63,0xB66E8B63,0xC2018030, +0xC2018038,0xC41A0000,0xDB538F64,0xF3333333, +0xFF0A8030,0xFF0A8038,0xFF328F64,0xFFFFFFFF diff --git a/configs/mx6var_som_nand_defconfig b/configs/mx6var_som_nand_defconfig new file mode 100644 index 0000000..59c3747 --- /dev/null +++ b/configs/mx6var_som_nand_defconfig @@ -0,0 +1,7 @@ +CONFIG_ARM=y +CONFIG_ARCH_MX6=y +CONFIG_TARGET_MX6VAR_SOM=y +CONFIG_SPL=y +CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/variscite/mx6var_som/imximage.cfg,SPL,MX6QDL,SYS_BOOT_NAND" +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_FLASH is not set diff --git a/configs/mx6var_som_sd_defconfig b/configs/mx6var_som_sd_defconfig new file mode 100644 index 0000000..875234e --- /dev/null +++ b/configs/mx6var_som_sd_defconfig @@ -0,0 +1,7 @@ +CONFIG_ARM=y +CONFIG_ARCH_MX6=y +CONFIG_TARGET_MX6VAR_SOM=y +CONFIG_SPL=y +CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/variscite/mx6var_som/imximage.cfg,SPL,MX6QDL" +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_FLASH is not set diff --git a/include/configs/mx6var_som.h b/include/configs/mx6var_som.h new file mode 100644 index 0000000..6771a2d --- /dev/null +++ b/include/configs/mx6var_som.h @@ -0,0 +1,419 @@ +/* + * Copyright (C) 2012 Freescale Semiconductor, Inc. + * Copyright (C) 2016 Variscite Ltd. All Rights Reserved. + * + * Author: Eran Matityahu <eran.m@variscite.com> + * + * Configuration settings for the Variscite VAR-SOM-MX6 board. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __MX6VAR_SOM_CONFIG_H +#define __MX6VAR_SOM_CONFIG_H + +#ifdef CONFIG_SPL +#define CONFIG_SPL_LIBCOMMON_SUPPORT +#ifdef CONFIG_SYS_BOOT_NAND +#define CONFIG_SPL_NAND_SUPPORT +#else +#define CONFIG_SPL_MMC_SUPPORT +#endif +#include "mx6var_spl.h" +#endif +#include "mx6_common.h" + +/* Address of reserved 4Bytes in OCRAM for sending RAM size from SPL to U-Boot */ +#define RAM_SIZE_ADDR ((CONFIG_SPL_TEXT_BASE) + (CONFIG_SPL_MAX_SIZE)) + +#define CONFIG_MACH_VAR_SOM_MX6 4419 +#define CONFIG_MACH_TYPE CONFIG_MACH_VAR_SOM_MX6 + +#define CONFIG_MXC_UART_BASE UART1_BASE +#define CONFIG_CONSOLE_DEV "ttymxc0" +#define CONFIG_MMCROOT "/dev/mmcblk0p2" + +#define CONFIG_IMX_THERMAL + +/* Size of malloc() pool */ +#define CONFIG_SYS_MALLOC_LEN (10 * SZ_1M) + +#define CONFIG_BOARD_EARLY_INIT_F +#define CONFIG_BOARD_LATE_INIT + +#define CONFIG_CMD_GPIO + +#define CONFIG_MXC_UART + +#define LOW_POWER_MODE_ENABLE + +/* MMC Configs */ +#define CONFIG_SYS_FSL_ESDHC_ADDR 0 +#define CONFIG_SYS_FSL_USDHC_NUM 2 +#define CONFIG_SYS_MMC_ENV_DEV 0 +#define CONFIG_SYS_MMC_ENV_PART 0 +#define CONFIG_SYS_MMC_IMG_LOAD_PART 1 + +#define CONFIG_CMD_PING +#define CONFIG_CMD_DHCP +#define CONFIG_CMD_MII +#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 7 + +#define CONFIG_PHYLIB +#define CONFIG_PHY_MICREL +#define CONFIG_PHY_MICREL_KSZ9021 + +#ifdef CONFIG_BOOTDELAY +#undef CONFIG_BOOTDELAY +#endif +#define CONFIG_BOOTDELAY 1 + +#ifdef CONFIG_SYS_BOOT_NAND +#define MFG_NAND_PARTITION "mtdparts=gpmi-nand:16m(boot),16m(kernel),16m(dtb),-(rootfs) " +#else +#define MFG_NAND_PARTITION "" +#endif + +#ifdef CONFIG_SYS_BOOT_NAND +#define MMC_DEV_SET " " +#else +#define MMC_DEV_SET "mmcdev=" __stringify(CONFIG_SYS_MMC_ENV_DEV) +#endif + +#define MFG_ENV_SETTINGS \ + "mfgtool_args=setenv bootargs console=${console},${baudrate} " \ + "rdinit=/linuxrc " \ + "g_mass_storage.stall=0 g_mass_storage.removable=1 " \ + "g_mass_storage.idVendor=0x066F g_mass_storage.idProduct=0x37FF "\ + "g_mass_storage.iSerialNumber=\"\" "\ + "enable_wait_mode=off "\ + MFG_NAND_PARTITION \ + "\0" \ + "initrd_addr=0x12C00000\0" \ + "initrd_high=0xffffffff\0" \ + "bootcmd_mfg=run mfgtool_args;bootm ${loadaddr} ${initrd_addr} ${fdt_addr};\0" \ + + +#define MMC_BOOT_ENV_SETTINGS \ + "uimage=uImage\0" \ + "fdt_file=" CONFIG_DEFAULT_FDT_FILE "\0" \ + "boot_fdt=try\0" \ + "ip_dyn=yes\0" \ + MMC_DEV_SET \ + "\0" \ + "mmcpart=" __stringify(CONFIG_SYS_MMC_IMG_LOAD_PART) "\0" \ + "mmcroot=" CONFIG_MMCROOT " rootwait rw\0" \ + "mmcargs=setenv bootargs console=${console},${baudrate} root=${mmcroot}; " \ + "run videoargs\0" \ + "loadbootscript=" \ + "fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};\0" \ + "bootscript=echo Running bootscript from mmc ...; " \ + "source\0" \ + "loaduimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${uimage}\0" \ + "loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${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" \ + + +#define NAND_BOOT_ENV_SETTINGS \ + "bootargs_ubifs=setenv bootargs console=${console},${baudrate} ubi.mtd=3 " \ + "root=ubi0:rootfs rootfstype=ubifs; " \ + "run videoargs\0" \ + "bootargs_emmc=setenv bootargs console=${console},${baudrate} " \ + "root=/dev/mmcblk1p1 rootwait rw; " \ + "run videoargs\0" \ + "bootcmd=" \ + "if test ${chosen_rootfs} != emmc; then " \ + "run bootargs_ubifs; " \ + "else " \ + "run bootargs_emmc; " \ + "fi; " \ + "nand read ${loadaddr} 0x400000 0x600000;" \ + "nand read ${fdt_addr} 0x3e0000 0x20000;" \ + "bootm ${loadaddr} - ${fdt_addr}\0" \ + "mtdids=" MTDIDS_DEFAULT "\0" \ + "mtdparts=" MTDPARTS_DEFAULT "\0" \ + + +#ifdef CONFIG_SYS_BOOT_NAND +#define BOOT_ENV_SETTINGS NAND_BOOT_ENV_SETTINGS +#else +#define BOOT_ENV_SETTINGS MMC_BOOT_ENV_SETTINGS +#define CONFIG_BOOTCOMMAND \ + "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" +#endif + + +#define CONFIG_EXTRA_ENV_SETTINGS \ + MFG_ENV_SETTINGS \ + BOOT_ENV_SETTINGS \ + "var_auto_env=Y\0" \ + "fdt_addr=0x18000000\0" \ + "fdt_high=0xffffffff\0" \ + "splash_filename=/boot/splash.bmp\0" \ + "splashimage=0x18100000\0" \ + "enable_splash=setenv splash_filename /boot/splash.bmp; " \ + "setenv splashimage 0x18100000\0" \ + "disable_splash=setenv splash_filename; setenv splashimage\0" \ + "console=" CONFIG_CONSOLE_DEV "\0" \ + "netargs=setenv bootargs console=${console},${baudrate} " \ + "root=/dev/nfs rw " \ + "ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp; " \ + "run videoargs\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" \ + "videoargs=" \ + "if hdmidet; then " \ + "setenv bootargs ${bootargs} " \ + "video=mxcfb0:dev=hdmi,1920x1080M@60,if=RGB24; " \ + "fi; " \ + "setenv bootargs ${bootargs} " \ + "video=mxcfb1:off; " \ + "i2c dev 2; " \ + "if i2c probe 0x38; then " \ + "setenv bootargs ${bootargs} " \ + "screen_alternate=yes;" \ + "fi;\0" + + +#define CONFIG_ARP_TIMEOUT 200UL + +#undef CONFIG_SYS_PROMPT +#ifdef CONFIG_SYS_BOOT_NAND +#define CONFIG_SYS_PROMPT "VAR-SOM-MX6 (NAND) => " +#else +#define CONFIG_SYS_PROMPT "VAR-SOM-MX6 (MMC) => " +#endif + +#define CONFIG_SYS_MEMTEST_START 0x10000000 +#define CONFIG_SYS_MEMTEST_END 0x10010000 +#define CONFIG_SYS_MEMTEST_SCRATCH 0x10800000 + +#define CONFIG_STACKSIZE (128 * 1024) + +/* Physical Memory Map */ +#define CONFIG_NR_DRAM_BANKS 1 +#define PHYS_SDRAM MMDC0_ARB_BASE_ADDR + +#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_ENV_SIZE (8 * 1024) + +#ifdef CONFIG_SYS_BOOT_NAND +#define CONFIG_SYS_USE_NAND +#define CONFIG_ENV_IS_IN_NAND +/* NAND boot config */ +#define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE +#define CONFIG_SYS_NAND_U_BOOT_OFFS 0x200000 +#define CONFIG_SYS_NAND_PAGE_SIZE 2048 +#else +#define CONFIG_ENV_IS_IN_MMC +#endif + +#if defined(CONFIG_MX6DL) +#define CONFIG_DEFAULT_FDT_FILE "imx6dl-var-som.dtb" +#elif defined(CONFIG_MX6S) +#define CONFIG_DEFAULT_FDT_FILE "imx6dl-var-som.dtb" +#elif defined(CONFIG_MX6Q) +#define CONFIG_DEFAULT_FDT_FILE "imx6q-var-som.dtb" +#else +#define CONFIG_DEFAULT_FDT_FILE "imx6q-var-som.dtb" +#endif + +#ifdef CONFIG_SYS_USE_NAND +#define CONFIG_CMD_NAND +#define CONFIG_CMD_NAND_TRIMFFS + +/* UBI/UBIFS support */ +#define CONFIG_CMD_UBI +#define CONFIG_CMD_UBIFS +#define CONFIG_RBTREE +#define CONFIG_MTD_DEVICE +#define CONFIG_MTD_PARTITIONS +#define CONFIG_CMD_MTDPARTS +#define CONFIG_LZO + +#define MTDIDS_DEFAULT "nand0=nandflash-0" + +/* + * Partions' layout for NAND is: + * mtd0: 2M (spl) First boot loader + * mtd1: 2M (u-boot, dtb) + * mtd2: 6M (kernel) + * mtd4: left (rootfs) + */ +/* Default mtd partition table */ +#define MTDPARTS_DEFAULT "mtdparts=nandflash-0:"\ + "2m(spl),"\ + "2m(u-boot),"\ + "6m(kernel),"\ + "-(rootfs)" /* ubifs */ + +/* NAND stuff */ +#define CONFIG_NAND_MXS +#define CONFIG_SYS_MAX_NAND_DEVICE 1 +#define CONFIG_SYS_NAND_BASE 0x40000000 +#define CONFIG_SYS_NAND_5_ADDR_CYCLE +#define CONFIG_SYS_NAND_ONFI_DETECTION + +/* DMA stuff, needed for GPMI/MXS NAND support */ +#define CONFIG_APBH_DMA +#define CONFIG_APBH_DMA_BURST +#define CONFIG_APBH_DMA_BURST8 +#endif + +#if defined(CONFIG_ENV_IS_IN_MMC) +#define CONFIG_ENV_OFFSET (0x3E0000) +#elif defined(CONFIG_ENV_IS_IN_NAND) +#undef CONFIG_ENV_SIZE +#define CONFIG_ENV_OFFSET (0x180000) +#define CONFIG_ENV_SECT_SIZE (128 << 10) +#define CONFIG_ENV_SIZE CONFIG_ENV_SECT_SIZE +#endif + +#define CONFIG_OF_LIBFDT + +/* Framebuffer */ +#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_SPLASH_SCREEN +#define CONFIG_SPLASH_SCREEN_ALIGN +#define CONFIG_BMP_16BPP +#define CONFIG_VIDEO_LOGO +#define CONFIG_VIDEO_BMP_LOGO +#ifdef CONFIG_MX6DL +#define CONFIG_IPUV3_CLK 198000000 +#else +#define CONFIG_IPUV3_CLK 264000000 +#endif +#define CONFIG_IMX_HDMI +#define CONFIG_CMD_HDMIDETECT +#define CONFIG_IMX_VIDEO_SKIP +#define CONFIG_CMD_BMP + +#define PMIC_I2C_BUS 1 +#define MX6CB_CDISPLAY_I2C_BUS 2 +#define MX6CB_CDISPLAY_I2C_ADDR 0x38 + +/* I2C Configs */ +#define CONFIG_CMD_I2C +#define CONFIG_SYS_I2C +#define CONFIG_SYS_I2C_MXC +#define CONFIG_SYS_I2C_MXC_I2C1 /* enable I2C bus 1 */ +#define CONFIG_SYS_I2C_MXC_I2C2 /* enable I2C bus 2 */ +#define CONFIG_SYS_I2C_MXC_I2C3 /* enable I2C bus 3 */ +#define CONFIG_SYS_I2C_SPEED 100000 + +/* PMIC */ +#define CONFIG_POWER +#define CONFIG_POWER_I2C +#define CONFIG_POWER_PFUZE100 +#define CONFIG_POWER_PFUZE100_I2C_ADDR 0x08 + +/* USB Configs */ +#define CONFIG_CMD_USB +#ifdef CONFIG_CMD_USB +#define CONFIG_USB_EHCI +#define CONFIG_USB_EHCI_MX6 +#define CONFIG_USB_STORAGE +#define CONFIG_EHCI_HCD_INIT_AFTER_RESET +#define CONFIG_USB_HOST_ETHER +#define CONFIG_USB_ETHER_ASIX +#define CONFIG_MXC_USB_PORTSC (PORT_PTS_UTMI | PORT_PTS_PTW) +#define CONFIG_MXC_USB_FLAGS 0 +#define CONFIG_USB_MAX_CONTROLLER_COUNT 2 /* Enabled USB controller number */ +#endif + +#define CONFIG_CI_UDC +#define CONFIG_USBD_HS +#define CONFIG_USB_GADGET_DUALSPEED + +/* Uncomment for USB Ethernet Gadget support */ +/* + * #define CONFIG_USB_ETHER + * #define CONFIG_USB_ETH_CDC + */ +#define CONFIG_NETCONSOLE + +#define CONFIG_USB_GADGET +#define CONFIG_CMD_USB_MASS_STORAGE +#define CONFIG_USB_FUNCTION_MASS_STORAGE +#define CONFIG_USB_GADGET_DOWNLOAD +#define CONFIG_USB_GADGET_VBUS_DRAW 2 + +#define CONFIG_G_DNL_VENDOR_NUM 0x0525 +#define CONFIG_G_DNL_PRODUCT_NUM 0xa4a5 +#define CONFIG_G_DNL_MANUFACTURER "Variscite" + +/* USB Device Firmware Update support */ +#define CONFIG_CMD_DFU +#define CONFIG_USB_FUNCTION_DFU +#define CONFIG_DFU_MMC +#define CONFIG_DFU_RAM +#ifdef CONFIG_SYS_USE_NAND +#define CONFIG_SYS_MAX_NAND_DEVICE 1 +#define CONFIG_DFU_NAND +#endif + +#endif /* __MX6VAR_SOM_CONFIG_H */ diff --git a/include/configs/mx6var_spl.h b/include/configs/mx6var_spl.h new file mode 100644 index 0000000..54cf4f1 --- /dev/null +++ b/include/configs/mx6var_spl.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2014 Gateworks Corporation + * Author: Tim Harvey <tharvey@gateworks.com> + * + * Copyright (C) 2016 Variscite Ltd. All Rights Reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#ifndef __IMX6_SPL_CONFIG_H +#define __IMX6_SPL_CONFIG_H + +#ifdef CONFIG_SPL + +#define CONFIG_SPL_FRAMEWORK + +/* + * see Figure 8-3 in IMX6DQ/IMX6SDL Reference manuals: + * - IMX6SDL OCRAM (IRAM) is from 0x00907000 to 0x0091FFFF + * - IMX6DQ has 2x IRAM of IMX6SDL but we intend to support IMX6SDL as well + * - BOOT ROM stack is at 0x0091FFB8 + * - if icache/dcache is enabled (eFuse/strapping controlled) then the + * IMX BOOT ROM will setup MMU table at 0x00918000, therefore we need to + * fit between 0x00907000 and 0x00918000. + * - Additionally the BOOT ROM loads what they consider the firmware image + * which consists of a 4K header in front of us that contains the IVT, DCD + * and some padding thus 'our' max size is really 0x00908000 - 0x00918000 + * or 64KB + */ +#define CONFIG_SYS_THUMB_BUILD +#define CONFIG_SPL_LDSCRIPT "board/variscite/mx6var_som/u-boot-spl.lds" +#define CONFIG_SPL_TEXT_BASE 0x00908000 +#define CONFIG_SPL_MAX_SIZE 0xFFFC /* ==0x10000-0x4, reserve 4Bytes for sending RAM size from SPL to U-Boot */ +#define CONFIG_SPL_STACK 0x0091FFB8 +#define CONFIG_SPL_LIBCOMMON_SUPPORT +#define CONFIG_SPL_LIBGENERIC_SUPPORT +#define CONFIG_SPL_SERIAL_SUPPORT +#define CONFIG_SPL_I2C_SUPPORT +#define CONFIG_SPL_GPIO_SUPPORT + +/* NAND support */ +#if defined(CONFIG_SPL_NAND_SUPPORT) +#define CONFIG_SPL_NAND_MXS +#define CONFIG_SPL_DMA_SUPPORT +#endif + +/* MMC support */ +#if defined(CONFIG_SPL_MMC_SUPPORT) +#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR 138 /* offset 69KB */ +#define CONFIG_SYS_U_BOOT_MAX_SIZE_SECTORS 800 /* 400 KB */ +#define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION 1 +#define CONFIG_SYS_MONITOR_LEN (CONFIG_SYS_U_BOOT_MAX_SIZE_SECTORS/2*1024) +#endif + +/* SATA support */ +#if defined(CONFIG_SPL_SATA_SUPPORT) +#define CONFIG_SPL_SATA_BOOT_DEVICE 0 +#define CONFIG_SYS_SATA_FAT_BOOT_PARTITION 1 +#endif + +/* Define the payload for FAT/EXT support */ +#if defined(CONFIG_SPL_FAT_SUPPORT) || defined(CONFIG_SPL_EXT_SUPPORT) +#define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME "u-boot.img" +#define CONFIG_SPL_LIBDISK_SUPPORT +#endif + +#if defined(CONFIG_MX6SX) +#define CONFIG_SPL_BSS_START_ADDR 0x88200000 +#define CONFIG_SPL_BSS_MAX_SIZE 0x100000 /* 1 MB */ +#define CONFIG_SYS_SPL_MALLOC_START 0x88300000 +#define CONFIG_SYS_SPL_MALLOC_SIZE 0x3200000 /* 50 MB */ +#define CONFIG_SYS_TEXT_BASE 0x87800000 +#else +#define CONFIG_SPL_BSS_START_ADDR 0x18200000 +#define CONFIG_SPL_BSS_MAX_SIZE 0x100000 /* 1 MB */ +#define CONFIG_SYS_SPL_MALLOC_START 0x18300000 +#define CONFIG_SYS_SPL_MALLOC_SIZE 0x3200000 /* 50 MB */ +#define CONFIG_SYS_TEXT_BASE 0x17800000 +#endif +#endif + +#endif
Add support for Variscite VAR-SOM-MX6 / DART-MX6 / VAR-SOM-SOLO/DUAL boards with features: PMIC, NAND flash, SD/MMC, USB, Ethernet, I2C, LVDS, HDMI. Signed-off-by: Eran Matityahu <eran.m@variscite.com> --- arch/arm/cpu/armv7/mx6/Kconfig | 7 + board/variscite/mx6var_som/Kconfig | 12 + board/variscite/mx6var_som/MAINTAINERS | 8 + board/variscite/mx6var_som/Makefile | 9 + board/variscite/mx6var_som/addresses.inc | 38 + board/variscite/mx6var_som/imximage.cfg | 13 + board/variscite/mx6var_som/mx6var_eeprom.c | 320 +++++ board/variscite/mx6var_som/mx6var_eeprom.h | 88 ++ board/variscite/mx6var_som/mx6var_eeprom_v2.c | 231 ++++ board/variscite/mx6var_som/mx6var_eeprom_v2.h | 55 + board/variscite/mx6var_som/mx6var_som.c | 1587 +++++++++++++++++++++++++ board/variscite/mx6var_som/u-boot-spl.lds | 59 + board/variscite/mx6var_som/values.inc | 39 + configs/mx6var_som_nand_defconfig | 7 + configs/mx6var_som_sd_defconfig | 7 + include/configs/mx6var_som.h | 419 +++++++ include/configs/mx6var_spl.h | 81 ++ tools/logos/variscite.bmp | Bin 0 -> 15414 bytes 18 files changed, 2980 insertions(+) create mode 100644 board/variscite/mx6var_som/Kconfig create mode 100644 board/variscite/mx6var_som/MAINTAINERS create mode 100644 board/variscite/mx6var_som/Makefile create mode 100644 board/variscite/mx6var_som/addresses.inc create mode 100644 board/variscite/mx6var_som/imximage.cfg create mode 100644 board/variscite/mx6var_som/mx6var_eeprom.c create mode 100644 board/variscite/mx6var_som/mx6var_eeprom.h create mode 100644 board/variscite/mx6var_som/mx6var_eeprom_v2.c create mode 100644 board/variscite/mx6var_som/mx6var_eeprom_v2.h create mode 100644 board/variscite/mx6var_som/mx6var_som.c create mode 100644 board/variscite/mx6var_som/u-boot-spl.lds create mode 100644 board/variscite/mx6var_som/values.inc create mode 100644 configs/mx6var_som_nand_defconfig create mode 100644 configs/mx6var_som_sd_defconfig create mode 100644 include/configs/mx6var_som.h create mode 100644 include/configs/mx6var_spl.h create mode 100644 tools/logos/variscite.bmp diff --git a/tools/logos/variscite.bmp b/tools/logos/variscite.bmp new file mode 100644 index 0000000000000000000000000000000000000000..f3ca27ceb169cd5d174fa919248968877cb0e3d3 GIT binary patch literal 15414 zcmeHO34B!LwU2kgL_-?_NHAh*x%YW*oFT>rL2W@1H!9Ey5zD@apnzf#MH;{mV~o*= z6n&VdJdo9}8iv3iVKoq03NnF<0ok<4kPu*!FqZ;F&pYRQ_s(MTMEYxgCYA$t`Id9; z`G05m&Nuw%+OuP)2&Rsa5fO>_b{wxRcwG~5E#3ufjfse$3p>RX5dj^4l?)wIQsAyT z+QYB!>IlEN^DgLo_uX*cJ)NOzmwVy<d%M5`UAscJ2Oos)-5!SS4|ju}k30gse%BNF z^zIFP`#c5%`}KpNg9pQtLx;fdAw%KGVZ&h5$dNGm>8IeCQKMnp*s<{9`0?<k2@_yS zS{lsxLnO@ZE5V${uY>uiHkkLg1Pkz*pV|aIO0{D<65ElGkA3-%H-ULLcR}B4@EHjU z@ye%n<jp7kzSqKne%ImkGnn5m78dny4)X>#hlPXiIiM9R=pP632DXMpgIYoUpcb&C z|MjqVa2zZeasw<JoB&G(-vEn;;`p$eVezmVVZm@27C+GzmJgF*=|~xtjc5z`Puv1a zM%;q$x4??gDtt5|5ta;3gym1&3d=@2VdW?XEFY5sE1yY$g3))t%4hF@6@Tmit`|DN z$1ijN*MzRHYU2H{>ZM0uO<GSVO6vw|UhWNRCqD}7r}Tn#>3v}8lqs+_<M*&GBNf)Y zIsn$aIS@9!IRrMnJ`^_PJPliNhQa1(!=d=?r{L4vF|c*Uv#@=}bFgLRc-S^`99}O% zao+Q=<AVwC*?VbF^8O^)H7gBv%}s}_%uLA1&W7AK-hk=Troo@zo(}KMm;re+XTq!x z-iHro&xZMP=Ry9$MX-G7QYcul0#><Puy)NFSYK2GJ7-UY-E%VGFLSeC_kuTIPkt`! z&3_d<OWp$g<F{e=lIhr<0sEIuhtd`Afxhw`yk^3F*DNS2oCEt-&xJ3F7D3tCxo~j( zA~>>fF&y5s3^s4v2#2>Uh9jGo!;w!{!k1fJ@MZC8IQp3zj+U&4V>>>9uS!<K*E?3j z@sf4;TnB&Mvk@wGZ-OnGHpAB9V%T0%0=stZguS1C4*U1*gR%n$;NTZ!aOmJ6DBrUM zyrm^jrEdf8{#{UcU<Y2i;l#n+P<e0{RF&<9ibH$h#9<vy9^4D34te0zky3o>P<41e zoIY{@jvqS))kn(U)NviEj~|3HUmpVB*N5SB#Zjm$KMEBU6;SE*!imZgP=!}@bv4v@ zzk;)sUqNkUIT$A^z<<gMwI?gVUtI}xr%!@$<|Ndd@quyr6r4YE8qU?62477L)Zk^* z)`DReaN%q%T=3Vy`Ev$bI(H5(o<9edF8mG7|Lr`SyLb^UT(|(2@cH*|F2W_ezWMtl zxcJRC@a?zX0!H@_y+mU8sorrRf5H?I@e>Az(5~WZ-1fa{zpM6Z$SZKwKO3@jF0b2v zp#AEO?^^O+ZtlBtH<$S?zd#Lq#y{Ba%UL5H?4ZetBFoA5^q=;Z2Co0*)C<Sw|6<&I zn&xb)%1BCEr`oQ=6YFX(C!-;chvD<hxLa}j;x;w!qoqh6z2DZU-K?o&ju`$h2)<RB z>1i3+Zt`9q(rMww^y&-u=ws#O<;Ti{%)V7w8IvYuWVxz>ee`zLlbw+^<&_*g*zMDa zHKfBZbhpdp4(ZWzUYR^8BYTI*6t1M%8N}!JmkmgCXtJz5Qq5ESXHzw&;=E0Hcx@PK zPBTf8Y<R_H)wt|YNNq@%n_lg4p_+T_Hl%0^pgSQ7xtO97Jf;Hl$Z1L9knHh=R<~PX z-oSe4X-#R8&F&U6d@JMZ%p=)iU#sE1v%WArxi5&%*xX%FHK(RHo-^%Lo2w~KS#c;G z-meRCX7GpU<2ETSof^`sBx()!HxDR;U8RvU>$+q7C0{0^r5+?HDvNvZ=7|eRwAm+{ z0^HZov}jA5C&rv);`?g?4Vxsz?L#?rRii(%WCor=eCzMmn3B{L)@V_Rf`q;8^8zmF zVwr3|d}9E%mBg@`2g2}qxGPH7FO!!7k(r7{W{c0bV|bQzliCPK-?86K)*1+W<=0#D z`6)HmQJ6pP*Y8x)QwZjJ0N<W&m@^ecb|^hgS`(^zDNZN#sws0Uo*P(TWZcUcFUMKm zSWOH9Ukhu&X})Pc##bm5X__!~>P^uMHCm@RdaRIQZyGILq;%>w!tCewMwx?>js5c` zA<Z7$)Xu=gsvPa1^({ttbu58z7QV{9!g`uR85>-Hmk2WsIJNse6+GqaWKtHv@O@}{ z9DnjM_G`nK5_A&dX~~TYdY{bt*`|1OeRUhwx(SO5x8HsNFE%|rT}P%I=C@CA>&Nu$ zSR1tpNZ2@8>yS$(43LFyqN+Fvp{#131O|-_Ns2Rxfh&)nWY`{7C&si=mQYS74ijH! ze$hqzk^Q{al7`LA(N)YBkNqBD7!i!V1nQS2lejSZ8J;G@9;MR=E^ITJX6LX#4`@we zaWt^@c3IO>i!A@c9uwd8WML>xbMy#t;S;?S4LLN-GynA#2{252=AJ05*+i!i(?8G9 zyGay(l8xh!`Gn>;SjhNdag{Jz;d@Jqfzk5nh1+i*L9jJ5r@43;63iARs8+4w;wX!i zb;5)%-=13)KxpC{K~csek7YK$(DQk8PwZBm4oBxBG*HE{BZ2^%w2(HNP9ydBC&iy+ zyN>MV^AK?)8a1UNaxqqG;)!3fa;dL1r5`)(9pUy9_^jk5vNn4peK|;#y<|mGWu@=7 zvt}pbt1C%H+!Sb9lDdpXb`|lX=vN$nj9eH{M0QMpm&aR>dZG5SRN&DN`*E9YK0W(J zGg+Vkyg#QE2rQT3E+8V=_1Vu7&dX!hNt{XkTDI8P{+J;#C8~E!Gb2IRZ#-Lx@TtFL zGa1vKXNHO%9F+uJ?#(PBU?f{i{NyZmIpYhpUs(POi9gokwCA;i=C~`<q97F-Mma;Z zi^Z~(<>&X|6FW*=>kx`>{VK5yapHDODPQfok;O2+$_E(*;nT)&w{L(zW4xepFW%(j z^*mJ2ROm-)#x^BAL+uw^&6C6}Z2vR7SuN~jEJ2cu(q}p44JkT=$9k>TKgFQW+(|4^ z^pvFGG&oYh9SuDZ|Mp{ZFuo#9QP~9%_hPo&flkT7LD%sXPlFC6SBNi7kBua7LDFeJ z#GlyI#Kf@u&+xPe@?c>Vn?sX?{Q^~r$w!axvmdW&@blu0vTofVnbHMr1?`{znuRgG zncA%m(@YN><?g&&Zk|Xl{;KYrKXFu1hFbfk*OQZ();d;ft>O0L+`uC67HU6Vb4wxV z8e8n-0udixR#nn1j^HyKUnw(N@n@C<qWm<MS|WF-=_|5`ocf8mgE78Q>TTqPGVbFe zd6%nsQqg+R48QRbAtUgL+B0nD#N^;ID@UEw681Bz59+|3DY*X`*}{5~y~Wf5ok!{B z<5VF9QlZX7F7!SAY4A2_FXWVrx2fdyEaUhCnCdl0@{56hW_$xNs}i9R=h9dGU)?J^ zlS>%tdX+7Xc}ebim^5MyM4~su@`uKsEt-<MNul<eB+Qp#4%gsf)2t~Bn_~xC<+R_} zqe}7h`|S5RGqHn{j24JbvXe@?+ba&u@o1ocHuv{bVIj@o>{y1g>Wszc!pfV(Yn=KW zx-@~86FVKiHrgSwi7k!C3`01bPA$`Zwq}K<YoLFI*bmnn|A^Ysc)ev@%a*MODwd_F ztaa!S#d{1Puh)KNfaqKo#+gPEl`R!RMxH}cwP%lV3Zb^ZSM!)Gb~#lUj9va(;~5o? zN~vN`nJ8?F4%&&<bv3V@d8QK|3bP+78=sz)kx9aJwwX9Th&?%*KaF0ASfi-o@Z!-A zXT`EvJtDBu*gwU0%(W8nM+FZPTU|<HFEW|P#j6K7v>prCFU*OeKI@|<Qv4yPJnpZ0 zh%hB@V`VnTW@Rd~{rp0Q>kG@h<?eVs?L_fH3j5*afqx{aC8-i>zYkg8*urBK<?aN^ z2~um;*2R^jEjleb3s102->t7d%*>oh15!*T66HnqW1B5zGBWXIA;tSJnznaHdG3&f zOgzo_6EP;Y|AKqh@^)|T2Q|GEG_RtxbBf$rz&c1xn#MFWj}JF76XTQ8%+s8}$5Vy< ze6a*jvLTy5WR=I}c^M(|3fQDqSX|IQ{anMbC|o&lx^RgSNO0g#4BEfWH>TGj%fbSk z8GmE()J`F$3>4kZvAe3NqV*Q;jcnasoYT){n2LxmV%4kjJU6waDK2q<VtgWhn&;a> zvnr!mG*!Sr)(mQygecR6iXr($9GhqcGMb_45_Pa(lYUl6slIspacc(?n&X}A_dkll zryxbRXEnPgZU{Sh+D`R00`F`$!sNmqU`%!BldW~p&1V8UA-K4{X<3WCB7a)HzZ9|s zO^u>nGlk)!ASh32MsY+Gw4V`={%*42X3O4-vTqD1A+_Ewc<Q+`zT#xw-jmuN<QYY( zu%<FYF#LhwVaYSy;`ipXiJ>2NBBPq6xvWkd&z|Y&s9t$S4E{1hR?riO(yYzM_c5}e zi`k>&vUH1$p5C1JXzY)SzA?v|Yj}utcp8bxPEViA_?prebmBnr6%LQVIw~@{O+W=P z5O!yLRS!`~swn-%(2H1$5ha@Kw`FdoYzX1>>pR?T^Sl$%O|O1D42AxT7dq_I-EMbj z07P)e>p^kf4W8hzI3ES_r#V2<Jg0-R>Um>)#sn_H<UDp?OehW!aCh!yj;$$VKP5G^ zbgoC#zq8A%&#wFvjL*OQmx+q3bfV4OFgE`Ze}us*9Lt$m)b>}UI`P*F<sEALNF*ZJ zsz0wl31Ppwr!_~Sqd%L^pX<=tX>`g^<RQ2N`u)bAR6H_v5ta89$o>~j6_vt2i?7aq zpaX7sd47x?qq>ixa{S4fe2=hbaSB=&M}Isr?RVu02>ThvbXmPifZ2Jw?9}j(@078a zo6Wx^R;D_&{{MgQU-?(Bn4{EA6!zo550hcxs~)Tls3DfxcPW{eq>L0lmQK{}quTmM zBrj5VJ$d(XDp~l9&wu;J%^NmsE?VDT>;}9gC=aaNRE)hJbk674yqvU#Hy*%eY<Z}i znv|s7Do((b1vM;elC;hrG(63Jm_|W-#<t#6XR4xjG4VO^bSpc$%%feqQBnv#qwFcf z$F(%0<3mKEoFqRMTDUYal%e>HQwtxJ#bJS>kD$t`+WrkXaWz&7#fRIU_rJR<?FgG7 zS-W%Gfv|sXYHT<|@v-hz%SQb^g?__V)ui7H``_b@4bXS={RezFUcKj&`S1OC_VSX7 zMw(PYFxH2!(I(3fT-Iy-_^i>!|GbK?aog~!{jS=tA+Nwy|7^(Cxx8*y?RWV#YREHw Ls{bo4fb0JN2LML% literal 0 HcmV?d00001