From 7d289d6239b29171bf9503869f1a92c084cf1c35 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Wed, 13 Sep 2017 14:29:44 -0700 Subject: imx: add macro to detect whether USB PHY is active This macro allows to detect whether the USB PHY is active. This is helpful to detect if the boot ROM has previously started the USB serial downloader. The idea is taken from the mfgtool support in the NXP U-Boot: http://git.freescale.com/git/cgit.cgi/imx/uboot-imx.git/commit/?h=imx_v2016.03_4.1.15_2.0.0_ga&id=a352ed3c5184b95c4c9f7468f5fbb5f43de5e412 Signed-off-by: Stefan Agner Acked-by: Marcel Ziswiler Tested-by: Fabio Estevam Reviewed-by: Eric Nelson --- arch/arm/include/asm/arch-mx6/sys_proto.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/include/asm/arch-mx6/sys_proto.h b/arch/arm/include/asm/arch-mx6/sys_proto.h index 14f5d94..ba73943 100644 --- a/arch/arm/include/asm/arch-mx6/sys_proto.h +++ b/arch/arm/include/asm/arch-mx6/sys_proto.h @@ -6,3 +6,10 @@ */ #include + +#define USBPHY_PWD 0x00000000 + +#define USBPHY_PWD_RXPWDRX (1 << 20) /* receiver block power down */ + +#define is_usbotg_phy_active(void) (!(readl(USB_PHY0_BASE_ADDR + USBPHY_PWD) & \ + USBPHY_PWD_RXPWDRX)) -- cgit v1.1 From e203dcf23e9eabc2e4f3d0b079457cd1516f2081 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Wed, 13 Sep 2017 14:29:45 -0700 Subject: imx_common: detect USB serial downloader reliably The current mechanism using SCR/GPR registers work well when the serial downloader boot mode has been selected explicitly (either via boot mode pins or using bmode command). However, in case the system entered boot ROM due to unbootable primary boot devices (e.g. empty eMMC), the SPL fails to detect that it has been downloaded through serial loader and tries to continue booting from eMMC: Trying to boot from MMC1 mmc_load_image_raw_sector: mmc block read error SPL: failed to boot from all boot devices ### ERROR ### Please RESET the board ### The only known way to reliably detect USB serial downloader is by checking the USB PHY receiver block power state... Signed-off-by: Stefan Agner Acked-by: Marcel Ziswiler Tested-by: Fabio Estevam Reviewed-by: Eric Nelson --- arch/arm/mach-imx/spl.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/mach-imx/spl.c b/arch/arm/mach-imx/spl.c index 258578a..82ea6b8 100644 --- a/arch/arm/mach-imx/spl.c +++ b/arch/arm/mach-imx/spl.c @@ -31,6 +31,18 @@ u32 spl_boot_device(void) if (((bmode >> 24) & 0x03) == 0x01) /* Serial Downloader */ return BOOT_DEVICE_BOARD; + /* + * The above method does not detect that the boot ROM used + * serial downloader in case the boot ROM decided to use the + * serial downloader as a fall back (primary boot source failed). + * + * Infer that the boot ROM used the USB serial downloader by + * checking whether the USB PHY is currently active... This + * assumes that SPL did not (yet) initialize the USB PHY... + */ + if (is_usbotg_phy_active()) + return BOOT_DEVICE_BOARD; + /* BOOT_CFG1[7:4] - see IMX6DQRM Table 8-8 */ switch ((reg & IMX6_BMODE_MASK) >> IMX6_BMODE_SHIFT) { /* EIM: See 8.5.1, Table 8-9 */ -- cgit v1.1 From 8590786acfc3d2afb46f739c2e72b98ef3d9e172 Mon Sep 17 00:00:00 2001 From: Eric Nelson Date: Thu, 31 Aug 2017 08:34:23 -0700 Subject: imx: imx7d: remove CamelCase from ENET_xMHz macros Update these macros to use all upper-case to avoid checkpatch warnings: ENET_25MHz, ENET_50MHz, ENET_125MHz, Signed-off-by: Eric Nelson Reviewed-by: Stefano Babic --- arch/arm/include/asm/arch-mx7/clock.h | 6 +++--- arch/arm/mach-imx/mx7/clock.c | 6 +++--- board/freescale/mx7dsabresd/mx7dsabresd.c | 2 +- board/technexion/pico-imx7d/pico-imx7d.c | 2 +- board/toradex/colibri_imx7/colibri_imx7.c | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/arm/include/asm/arch-mx7/clock.h b/arch/arm/include/asm/arch-mx7/clock.h index 688d236..3b115ad 100644 --- a/arch/arm/include/asm/arch-mx7/clock.h +++ b/arch/arm/include/asm/arch-mx7/clock.h @@ -318,9 +318,9 @@ struct clk_root_map { }; enum enet_freq { - ENET_25MHz, - ENET_50MHz, - ENET_125MHz, + ENET_25MHZ, + ENET_50MHZ, + ENET_125MHZ, }; u32 get_root_clk(enum clk_root_index clock_id); diff --git a/arch/arm/mach-imx/mx7/clock.c b/arch/arm/mach-imx/mx7/clock.c index 2cfde46..8150faa 100644 --- a/arch/arm/mach-imx/mx7/clock.c +++ b/arch/arm/mach-imx/mx7/clock.c @@ -966,15 +966,15 @@ int set_clk_enet(enum enet_freq type) clock_enable(CCGR_ENET2, 0); switch (type) { - case ENET_125MHz: + case ENET_125MHZ: enet1_ref = ENET1_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_125M_CLK; enet2_ref = ENET2_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_125M_CLK; break; - case ENET_50MHz: + case ENET_50MHZ: enet1_ref = ENET1_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_50M_CLK; enet2_ref = ENET2_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_50M_CLK; break; - case ENET_25MHz: + case ENET_25MHZ: enet1_ref = ENET1_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_25M_CLK; enet2_ref = ENET2_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_25M_CLK; break; diff --git a/board/freescale/mx7dsabresd/mx7dsabresd.c b/board/freescale/mx7dsabresd/mx7dsabresd.c index a681ece..5819b18 100644 --- a/board/freescale/mx7dsabresd/mx7dsabresd.c +++ b/board/freescale/mx7dsabresd/mx7dsabresd.c @@ -260,7 +260,7 @@ static int setup_fec(void) (IOMUXC_GPR_GPR1_GPR_ENET1_TX_CLK_SEL_MASK | IOMUXC_GPR_GPR1_GPR_ENET1_CLK_DIR_MASK), 0); - return set_clk_enet(ENET_125MHz); + return set_clk_enet(ENET_125MHZ); } diff --git a/board/technexion/pico-imx7d/pico-imx7d.c b/board/technexion/pico-imx7d/pico-imx7d.c index b4c9be7..67bab51 100644 --- a/board/technexion/pico-imx7d/pico-imx7d.c +++ b/board/technexion/pico-imx7d/pico-imx7d.c @@ -182,7 +182,7 @@ static int setup_fec(void) (IOMUXC_GPR_GPR1_GPR_ENET1_TX_CLK_SEL_MASK | IOMUXC_GPR_GPR1_GPR_ENET1_CLK_DIR_MASK), 0); - return set_clk_enet(ENET_125MHz); + return set_clk_enet(ENET_125MHZ); } int board_phy_config(struct phy_device *phydev) diff --git a/board/toradex/colibri_imx7/colibri_imx7.c b/board/toradex/colibri_imx7/colibri_imx7.c index 5cb14b4..13b2b57 100644 --- a/board/toradex/colibri_imx7/colibri_imx7.c +++ b/board/toradex/colibri_imx7/colibri_imx7.c @@ -280,7 +280,7 @@ static int setup_fec(void) IOMUXC_GPR_GPR1_GPR_ENET1_TX_CLK_SEL_MASK); #endif - return set_clk_enet(ENET_50MHz); + return set_clk_enet(ENET_50MHZ); } int board_phy_config(struct phy_device *phydev) -- cgit v1.1 From 0bfd4f81ae3d28e951111481e9af66ba1f7be671 Mon Sep 17 00:00:00 2001 From: Vanessa Maegima Date: Tue, 29 Aug 2017 13:53:18 -0300 Subject: pico-imx7d: Add "how to boot with NXP 4.1 Kernel" The NXP 4.1 kernel needs to boot with secure boot. Add information on how to enable secure boot mode. Signed-off-by: Vanessa Maegima --- board/technexion/pico-imx7d/README | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/board/technexion/pico-imx7d/README b/board/technexion/pico-imx7d/README index a2805ee..8af4eff 100644 --- a/board/technexion/pico-imx7d/README +++ b/board/technexion/pico-imx7d/README @@ -47,3 +47,20 @@ Remove power from the pico board. Put pico board into normal boot mode. Power up the board and the new updated U-Boot should boot from eMMC. + +Building U-Boot to boot with NXP 4.1 kernel: + +The NXP 4.1 kernel boots only in secure boot mode on mx7. + +Follow the next steps to enable secure boot: + +$ make mrproper +$ make pico-imx7d_defconfig +$ make menuconfig + -> ARM architecture + -> [*] Enable support for booting in non-secure mode + -> [*] Boot in secure mode by default + -> Exit +$ make + +Flash u-boot.imx using the imx_usb_loader tool. -- cgit v1.1 From 30df9f770b22f3c89d61947950da362117c43c63 Mon Sep 17 00:00:00 2001 From: Anatolij Gustschin Date: Mon, 28 Aug 2017 20:58:38 +0200 Subject: imx6: drop duplicated bss memset and board_init_r() call bss section is cleared in crt0.S. board_init_r() is also entered from crt0 code. Signed-off-by: Anatolij Gustschin Cc: Christian Gmeiner Cc: Nikita Kiryanov Cc: Jagan Teki Cc: Tim Harvey Cc: Marek Vasut Cc: Lukasz Majewski Cc: Fabio Estevam Reviewed-by: Lukasz Majewski Reviewed-by: Christian Gmeiner Reviewed-by: Fabio Estevam --- board/bachmann/ot1200/ot1200_spl.c | 6 ------ board/compulab/cm_fx6/spl.c | 3 --- board/engicam/common/spl.c | 6 ------ board/gateworks/gw_ventana/gw_ventana_spl.c | 3 --- board/kosagi/novena/novena_spl.c | 6 ------ board/liebherr/mccmon6/spl.c | 6 ------ board/udoo/udoo_spl.c | 6 ------ board/wandboard/spl.c | 6 ------ 8 files changed, 42 deletions(-) diff --git a/board/bachmann/ot1200/ot1200_spl.c b/board/bachmann/ot1200/ot1200_spl.c index 9d28da4..f3dff95 100644 --- a/board/bachmann/ot1200/ot1200_spl.c +++ b/board/bachmann/ot1200/ot1200_spl.c @@ -151,10 +151,4 @@ void board_init_f(ulong dummy) /* configure MMDC for SDRAM width/size and per-model calibration */ ot1200_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); } diff --git a/board/compulab/cm_fx6/spl.c b/board/compulab/cm_fx6/spl.c index bba977f..56aac60 100644 --- a/board/compulab/cm_fx6/spl.c +++ b/board/compulab/cm_fx6/spl.c @@ -336,9 +336,6 @@ void board_init_f(ulong dummy) puts("!!!ERROR!!! DRAM detection failed!!!\n"); hang(); } - - memset(__bss_start, 0, __bss_end - __bss_start); - board_init_r(NULL, 0); } void board_boot_order(u32 *spl_boot_list) diff --git a/board/engicam/common/spl.c b/board/engicam/common/spl.c index 6964c13..8711418 100644 --- a/board/engicam/common/spl.c +++ b/board/engicam/common/spl.c @@ -384,10 +384,4 @@ void board_init_f(ulong dummy) /* 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); } diff --git a/board/gateworks/gw_ventana/gw_ventana_spl.c b/board/gateworks/gw_ventana/gw_ventana_spl.c index c2e370b..bdbe5e7 100644 --- a/board/gateworks/gw_ventana/gw_ventana_spl.c +++ b/board/gateworks/gw_ventana/gw_ventana_spl.c @@ -626,9 +626,6 @@ void board_init_f(ulong dummy) spl_dram_init(8 << ventana_info.sdram_width, 16 << ventana_info.sdram_size, board_model); - - /* Clear the BSS. */ - memset(__bss_start, 0, __bss_end - __bss_start); } void board_boot_order(u32 *spl_boot_list) diff --git a/board/kosagi/novena/novena_spl.c b/board/kosagi/novena/novena_spl.c index 512f06d..b4a68da 100644 --- a/board/kosagi/novena/novena_spl.c +++ b/board/kosagi/novena/novena_spl.c @@ -596,10 +596,4 @@ void board_init_f(ulong dummy) udelay(100); mmdc_do_write_level_calibration(&novena_ddr_info); mmdc_do_dqs_calibration(&novena_ddr_info); - - /* Clear the BSS. */ - memset(__bss_start, 0, __bss_end - __bss_start); - - /* load/boot image from boot device */ - board_init_r(NULL, 0); } diff --git a/board/liebherr/mccmon6/spl.c b/board/liebherr/mccmon6/spl.c index a2f804d..196da46 100644 --- a/board/liebherr/mccmon6/spl.c +++ b/board/liebherr/mccmon6/spl.c @@ -296,11 +296,5 @@ void board_init_f(ulong dummy) /* 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/udoo/udoo_spl.c b/board/udoo/udoo_spl.c index 3645969..694055b 100644 --- a/board/udoo/udoo_spl.c +++ b/board/udoo/udoo_spl.c @@ -252,11 +252,5 @@ void board_init_f(ulong dummy) /* 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/wandboard/spl.c b/board/wandboard/spl.c index 99a0286..00c75d0 100644 --- a/board/wandboard/spl.c +++ b/board/wandboard/spl.c @@ -300,11 +300,5 @@ void board_init_f(ulong dummy) /* 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 -- cgit v1.1 From b1e8512e9dbe1771da9c3ad3ddfaf7681318fe0e Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Thu, 24 Aug 2017 10:49:43 -0500 Subject: detect and setup solidrun hummingboard2 The hummingboard2 is slightly different to the cubox i and to the hummingboard. The GPIO pin info to probe came from solidruns for of u-boot on github. https://github.com/SolidRun/u-boot-imx6/blob/imx6/board/solidrun/mx6_cubox-i/mx6_cubox-i.c#L569-L589 I have tested on a hummingboard-edge witha imx6 solo and 512mb of ram. Signed-off-by: Dennis Gilmore --- board/solidrun/mx6cuboxi/mx6cuboxi.c | 35 +++++++++++++++++++++++++++++++++-- include/configs/mx6cuboxi.h | 4 ++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/board/solidrun/mx6cuboxi/mx6cuboxi.c b/board/solidrun/mx6cuboxi/mx6cuboxi.c index 986abc5..1e4da4a 100644 --- a/board/solidrun/mx6cuboxi/mx6cuboxi.c +++ b/board/solidrun/mx6cuboxi/mx6cuboxi.c @@ -349,6 +349,7 @@ static bool is_hummingboard(void) * Machine selection - * Machine val1, val2 * ------------------------- + * HB2 x x * HB rev 3.x x 0 * CBi 0 1 * HB 1 1 @@ -362,9 +363,37 @@ static bool is_hummingboard(void) return true; } +static bool is_hummingboard2(void) +{ + int val1; + + SETUP_IOMUX_PADS(hb_cbi_sense); + + gpio_direction_input(IMX_GPIO_NR(2, 8)); + + val1 = gpio_get_value(IMX_GPIO_NR(2, 8)); + + /* + * Machine selection - + * Machine val1 + * ------------------- + * HB2 0 + * HB rev 3.x x + * CBi x + * HB x + */ + + if (val1 == 0) + return true; + else + return false; +} + int checkboard(void) { - if (is_hummingboard()) + if (is_hummingboard2()) + puts("Board: MX6 Hummingboard2\n"); + else if (is_hummingboard()) puts("Board: MX6 Hummingboard\n"); else puts("Board: MX6 Cubox-i\n"); @@ -375,7 +404,9 @@ int checkboard(void) int board_late_init(void) { #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG - if (is_hummingboard()) + if (is_hummingboard2()) + env_set("board_name", "HUMMINGBOARD2"); + else if (is_hummingboard()) env_set("board_name", "HUMMINGBOARD"); else env_set("board_name", "CUBOXI"); diff --git a/include/configs/mx6cuboxi.h b/include/configs/mx6cuboxi.h index 4e12de1..7fefe8e 100644 --- a/include/configs/mx6cuboxi.h +++ b/include/configs/mx6cuboxi.h @@ -106,6 +106,10 @@ "fi; " \ "fi\0" \ "findfdt="\ + "if test $board_name = HUMMINGBOARD2 && test $board_rev = MX6Q ; then " \ + "setenv fdtfile imx6q-hummingboard2.dtb; fi; " \ + "if test $board_name = HUMMINGBOARD2 && test $board_rev = MX6DL ; then " \ + "setenv fdtfile imx6dl-hummingboard2.dtb; fi; " \ "if test $board_name = HUMMINGBOARD && test $board_rev = MX6Q ; then " \ "setenv fdtfile imx6q-hummingboard.dtb; fi; " \ "if test $board_name = HUMMINGBOARD && test $board_rev = MX6DL ; then " \ -- cgit v1.1 From be2808c3b0671751827b39753e7abe7278d33c62 Mon Sep 17 00:00:00 2001 From: Ian Ray Date: Tue, 22 Aug 2017 09:03:54 +0300 Subject: board: ge: bx50v3: set eth0 MAC address Define i2c mux configuration. Add new vpd_reader which is used to read vital product data. Read VPD from EEPROM and set eth0 MAC address. Signed-off-by: Ian Ray Signed-off-by: Jose Alarcon --- board/ge/bx50v3/Makefile | 2 +- board/ge/bx50v3/bx50v3.c | 109 +++++++++++++++++++++ board/ge/bx50v3/vpd_reader.c | 228 +++++++++++++++++++++++++++++++++++++++++++ board/ge/bx50v3/vpd_reader.h | 25 +++++ include/configs/ge_bx50v3.h | 15 +++ 5 files changed, 378 insertions(+), 1 deletion(-) create mode 100644 board/ge/bx50v3/vpd_reader.c create mode 100644 board/ge/bx50v3/vpd_reader.h diff --git a/board/ge/bx50v3/Makefile b/board/ge/bx50v3/Makefile index bcd149f..2fff27b 100644 --- a/board/ge/bx50v3/Makefile +++ b/board/ge/bx50v3/Makefile @@ -5,4 +5,4 @@ # SPDX-License-Identifier: GPL-2.0+ # -obj-y := bx50v3.o +obj-y := bx50v3.o vpd_reader.o diff --git a/board/ge/bx50v3/bx50v3.c b/board/ge/bx50v3/bx50v3.c index b25c634..c7df4ce 100644 --- a/board/ge/bx50v3/bx50v3.c +++ b/board/ge/bx50v3/bx50v3.c @@ -26,8 +26,19 @@ #include #include #include +#include +#include "vpd_reader.h" DECLARE_GLOBAL_DATA_PTR; +#ifndef CONFIG_SYS_I2C_EEPROM_ADDR +# define CONFIG_SYS_I2C_EEPROM_ADDR 0x50 +# define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1 +#endif + +#ifndef CONFIG_SYS_I2C_EEPROM_BUS +#define CONFIG_SYS_I2C_EEPROM_BUS 2 +#endif + #define NC_PAD_CTRL (PAD_CTL_PUS_100K_UP | \ PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \ PAD_CTL_HYS) @@ -528,6 +539,102 @@ int overwrite_console(void) return 1; } +#define VPD_TYPE_INVALID 0x00 +#define VPD_BLOCK_NETWORK 0x20 +#define VPD_BLOCK_HWID 0x44 +#define VPD_PRODUCT_B850 1 +#define VPD_PRODUCT_B650 2 +#define VPD_PRODUCT_B450 3 + +struct vpd_cache { + uint8_t product_id; + uint8_t macbits; + unsigned char mac1[6]; +}; + +/* + * Extracts MAC and product information from the VPD. + */ +static int vpd_callback( + void *userdata, + uint8_t id, + uint8_t version, + uint8_t type, + size_t size, + uint8_t const *data) +{ + struct vpd_cache *vpd = (struct vpd_cache *)userdata; + + if ( id == VPD_BLOCK_HWID + && version == 1 + && type != VPD_TYPE_INVALID + && size >= 1) { + vpd->product_id = data[0]; + + } else if ( id == VPD_BLOCK_NETWORK + && version == 1 + && type != VPD_TYPE_INVALID + && size >= 6) { + vpd->macbits |= 1; + memcpy(vpd->mac1, data, 6); + } + + return 0; +} + +static void set_eth0_mac_address(unsigned char * mac) +{ + uint32_t *ENET_TCR = (uint32_t*)0x21880c4; + uint32_t *ENET_PALR = (uint32_t*)0x21880e4; + uint32_t *ENET_PAUR = (uint32_t*)0x21880e8; + + *ENET_TCR |= 0x100; /* ADDINS */ + *ENET_PALR |= (mac[0] << 24) | (mac[1] << 16) | (mac[2] << 8) | mac[3]; + *ENET_PAUR |= (mac[4] << 24) | (mac[5] << 16); +} + +static void process_vpd(struct vpd_cache *vpd) +{ + if ( vpd->product_id == VPD_PRODUCT_B850 + || vpd->product_id == VPD_PRODUCT_B650 + || vpd->product_id == VPD_PRODUCT_B450) { + if (vpd->macbits & 1) { + set_eth0_mac_address(vpd->mac1); + } + } +} + +static int read_vpd(uint eeprom_bus) +{ + struct vpd_cache vpd; + int res; + int size = 1024; + uint8_t *data; + unsigned int current_i2c_bus = i2c_get_bus_num(); + + res = i2c_set_bus_num(eeprom_bus); + if (res < 0) + return res; + + data = (uint8_t *)malloc(size); + if (!data) + return -ENOMEM; + + res = i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0, + CONFIG_SYS_I2C_EEPROM_ADDR_LEN, data, size); + + if (res == 0) { + memset(&vpd, 0, sizeof(vpd)); + vpd_reader(size, data, &vpd, vpd_callback); + process_vpd(&vpd); + } + + free(data); + + i2c_set_bus_num(current_i2c_bus); + return res; +} + int board_eth_init(bd_t *bis) { setup_iomux_enet(); @@ -586,6 +693,8 @@ int board_init(void) setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info2); setup_i2c(3, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info3); + read_vpd(CONFIG_SYS_I2C_EEPROM_BUS); + return 0; } diff --git a/board/ge/bx50v3/vpd_reader.c b/board/ge/bx50v3/vpd_reader.c new file mode 100644 index 0000000..98da893 --- /dev/null +++ b/board/ge/bx50v3/vpd_reader.c @@ -0,0 +1,228 @@ +/* + * Copyright 2016 General Electric Company + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include "vpd_reader.h" + +#include +#include + + +/* BCH configuration */ + +const struct { + int header_ecc_capability_bits; + int data_ecc_capability_bits; + unsigned int prim_poly; + struct { + int min; + int max; + } galois_field_order; +} bch_configuration = { + .header_ecc_capability_bits = 4, + .data_ecc_capability_bits = 16, + .prim_poly = 0, + .galois_field_order = { + .min = 5, + .max = 15, + }, +}; + +static int calculate_galois_field_order(size_t source_length) +{ + int gfo = bch_configuration.galois_field_order.min; + + for (; gfo < bch_configuration.galois_field_order.max && + ((((1 << gfo) - 1) - ((int)source_length * 8)) < 0); + gfo++) { + } + + if (gfo == bch_configuration.galois_field_order.max) { + return -1; + } + + return gfo + 1; +} + +static int verify_bch(int ecc_bits, unsigned int prim_poly, + uint8_t * data, size_t data_length, + const uint8_t * ecc, size_t ecc_length) +{ + int gfo = calculate_galois_field_order(data_length); + if (gfo < 0) { + return -1; + } + + struct bch_control * bch = init_bch(gfo, ecc_bits, prim_poly); + if (!bch) { + return -1; + } + + if (bch->ecc_bytes != ecc_length) { + free_bch(bch); + return -1; + } + + unsigned * errloc = (unsigned *)calloc(data_length, sizeof(unsigned)); + int errors = decode_bch( + bch, data, data_length, ecc, NULL, NULL, errloc); + free_bch(bch); + if (errors < 0) { + free(errloc); + return -1; + } + + if (errors > 0) { + for (int n = 0; n < errors; n++) { + if (errloc[n] >= 8 * data_length) { + /* n-th error located in ecc (no need for data correction) */ + } else { + /* n-th error located in data */ + data[errloc[n] / 8] ^= 1 << (errloc[n] % 8); + } + } + } + + free(errloc); + return 0; +} + + +static const int ID = 0; +static const int LEN = 1; +static const int VER = 2; +static const int TYP = 3; +static const int BLOCK_SIZE = 4; + +static const uint8_t HEADER_BLOCK_ID = 0x00; +static const uint8_t HEADER_BLOCK_LEN = 18; +static const uint32_t HEADER_BLOCK_MAGIC = 0xca53ca53; +static const size_t HEADER_BLOCK_VERIFY_LEN = 14; +static const size_t HEADER_BLOCK_ECC_OFF = 14; +static const size_t HEADER_BLOCK_ECC_LEN = 4; + +static const uint8_t ECC_BLOCK_ID = 0xFF; + +int vpd_reader( + size_t size, + uint8_t * data, + void * userdata, + int (*fn)( + void * userdata, + uint8_t id, + uint8_t version, + uint8_t type, + size_t size, + uint8_t const * data)) +{ + if ( size < HEADER_BLOCK_LEN + || data == NULL + || fn == NULL) { + return -EINVAL; + } + + /* + * +--------------------+--------------------+--//--+--------------------+ + * | header block | data block | ... | ecc block | + * +--------------------+--------------------+--//--+--------------------+ + * : : : + * +------+-------+-----+ +------+-------------+ + * | id | magic | ecc | | ... | ecc | + * | len | off | | +------+-------------+ + * | ver | size | | : + * | type | | | : + * +------+-------+-----+ : + * : : : : + * <----- [1] ----> <----------- [2] -----------> + * + * Repair (if necessary) the contents of header block [1] by using a + * 4 byte ECC located at the end of the header block. A successful + * return value means that we can trust the header. + */ + int ret = verify_bch( + bch_configuration.header_ecc_capability_bits, + bch_configuration.prim_poly, + data, + HEADER_BLOCK_VERIFY_LEN, + &data[HEADER_BLOCK_ECC_OFF], + HEADER_BLOCK_ECC_LEN); + if (ret < 0) { + return ret; + } + + /* Validate header block { id, length, version, type }. */ + if ( data[ID] != HEADER_BLOCK_ID + || data[LEN] != HEADER_BLOCK_LEN + || data[VER] != 0 + || data[TYP] != 0 + || ntohl(*(uint32_t *)(&data[4])) != HEADER_BLOCK_MAGIC) { + return -EINVAL; + } + + uint32_t offset = ntohl(*(uint32_t *)(&data[8])); + uint16_t size_bits = ntohs(*(uint16_t *)(&data[12])); + + /* Check that ECC header fits. */ + if (offset + 3 >= size) { + return -EINVAL; + } + + /* Validate ECC block. */ + uint8_t * ecc = &data[offset]; + if ( ecc[ID] != ECC_BLOCK_ID + || ecc[LEN] < BLOCK_SIZE + || ecc[LEN] + offset > size + || ecc[LEN] - BLOCK_SIZE != size_bits / 8 + || ecc[VER] != 1 + || ecc[TYP] != 1) { + return -EINVAL; + } + + /* + * Use the header block to locate the ECC block and verify the data + * blocks [2] against the ecc block ECC. + */ + ret = verify_bch( + bch_configuration.data_ecc_capability_bits, + bch_configuration.prim_poly, + &data[data[LEN]], + offset - data[LEN], + &data[offset + BLOCK_SIZE], + ecc[LEN] - BLOCK_SIZE); + if (ret < 0) { + return ret; + } + + /* Stop after ECC. Ignore possible zero padding. */ + size = offset; + + for (;;) { + /* Move to next block. */ + size -= data[LEN]; + data += data[LEN]; + + if (size == 0) { + /* Finished iterating through blocks. */ + return 0; + } + + if ( size < BLOCK_SIZE + || data[LEN] < BLOCK_SIZE) { + /* Not enough data for a header, or short header. */ + return -EINVAL; + } + + ret = fn( + userdata, + data[ID], + data[VER], + data[TYP], + data[LEN] - BLOCK_SIZE, + &data[BLOCK_SIZE]); + if (ret) { + return ret; + } + } +} diff --git a/board/ge/bx50v3/vpd_reader.h b/board/ge/bx50v3/vpd_reader.h new file mode 100644 index 0000000..efa172a --- /dev/null +++ b/board/ge/bx50v3/vpd_reader.h @@ -0,0 +1,25 @@ +/* + * Copyright 2016 General Electric Company + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include "common.h" + +/* + * Read VPD from given data, verify content, and call callback + * for each vital product data block. + * + * Returns Non-zero on error. Negative numbers encode errno. + */ +int vpd_reader( + size_t size, + uint8_t * data, + void * userdata, + int (*fn)( + void * userdata, + uint8_t id, + uint8_t version, + uint8_t type, + size_t size, + uint8_t const * data)); diff --git a/include/configs/ge_bx50v3.h b/include/configs/ge_bx50v3.h index a0468d2..33f5101 100644 --- a/include/configs/ge_bx50v3.h +++ b/include/configs/ge_bx50v3.h @@ -299,4 +299,19 @@ #define CONFIG_SYS_I2C_MXC_I2C2 #define CONFIG_SYS_I2C_MXC_I2C3 +#define CONFIG_SYS_NUM_I2C_BUSES 9 +#define CONFIG_SYS_I2C_MAX_HOPS 1 +#define CONFIG_SYS_I2C_BUSES { {0, {I2C_NULL_HOP} }, \ + {0, {{I2C_MUX_PCA9547, 0x70, 0} } }, \ + {0, {{I2C_MUX_PCA9547, 0x70, 1} } }, \ + {0, {{I2C_MUX_PCA9547, 0x70, 2} } }, \ + {0, {{I2C_MUX_PCA9547, 0x70, 3} } }, \ + {0, {{I2C_MUX_PCA9547, 0x70, 4} } }, \ + {0, {{I2C_MUX_PCA9547, 0x70, 5} } }, \ + {0, {{I2C_MUX_PCA9547, 0x70, 6} } }, \ + {0, {{I2C_MUX_PCA9547, 0x70, 7} } }, \ + } + +#define CONFIG_BCH + #endif /* __GE_BX50V3_CONFIG_H */ -- cgit v1.1 From 511db3bf5a27a2f7eca0f60b6adb1eff74bd6df6 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 5 Sep 2017 20:46:39 -0300 Subject: toradex: imx6: Move g_dnl_bind_fixup() into common SPL code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of having every board file to add its own g_dnl_bind_fixup() implementation, move it to the common imx6 SPL code. Signed-off-by: Fabio Estevam Reviewed-by: Ɓukasz Majewski --- arch/arm/mach-imx/spl.c | 10 ++++++++++ board/toradex/apalis_imx6/apalis_imx6.c | 13 ------------- board/toradex/colibri_imx6/colibri_imx6.c | 13 ------------- 3 files changed, 10 insertions(+), 26 deletions(-) diff --git a/arch/arm/mach-imx/spl.c b/arch/arm/mach-imx/spl.c index 82ea6b8..5944f99 100644 --- a/arch/arm/mach-imx/spl.c +++ b/arch/arm/mach-imx/spl.c @@ -14,6 +14,7 @@ #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -94,6 +95,15 @@ u32 spl_boot_device(void) } return BOOT_DEVICE_NONE; } + +#ifdef CONFIG_SPL_USB_GADGET_SUPPORT +int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name) +{ + put_unaligned(CONFIG_G_DNL_PRODUCT_NUM + 0xfff, &dev->idProduct); + + return 0; +} +#endif #endif #if defined(CONFIG_SPL_MMC_SUPPORT) diff --git a/board/toradex/apalis_imx6/apalis_imx6.c b/board/toradex/apalis_imx6/apalis_imx6.c index ebc6c12..628a61d 100644 --- a/board/toradex/apalis_imx6/apalis_imx6.c +++ b/board/toradex/apalis_imx6/apalis_imx6.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -1224,18 +1223,6 @@ void reset_cpu(ulong addr) { } -#ifdef CONFIG_SPL_USB_GADGET_SUPPORT -int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name) -{ - unsigned short usb_pid; - - usb_pid = TORADEX_USB_PRODUCT_NUM_OFFSET + 0xfff; - put_unaligned(usb_pid, &dev->idProduct); - - return 0; -} -#endif - #endif static struct mxc_serial_platdata mxc_serial_plat = { diff --git a/board/toradex/colibri_imx6/colibri_imx6.c b/board/toradex/colibri_imx6/colibri_imx6.c index 669d912..756e3f3 100644 --- a/board/toradex/colibri_imx6/colibri_imx6.c +++ b/board/toradex/colibri_imx6/colibri_imx6.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -1108,18 +1107,6 @@ void reset_cpu(ulong addr) { } -#ifdef CONFIG_SPL_USB_GADGET_SUPPORT -int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name) -{ - unsigned short usb_pid; - - usb_pid = TORADEX_USB_PRODUCT_NUM_OFFSET + 0xfff; - put_unaligned(usb_pid, &dev->idProduct); - - return 0; -} -#endif - #endif static struct mxc_serial_platdata mxc_serial_plat = { -- cgit v1.1 From 031426a7af63d3c939fc963311e6dc8e904a0440 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 5 Sep 2017 20:46:40 -0300 Subject: mx6sabresd: Add Serial Download Protocol support Add Serial Download Protocol support (SDP), which allows loading SPL and u-boot.img via imx_usb_loader tool as explained in doc/README.sdp. Signed-off-by: Fabio Estevam --- configs/mx6sabresd_defconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/configs/mx6sabresd_defconfig b/configs/mx6sabresd_defconfig index 0e49e69..ad5d448 100644 --- a/configs/mx6sabresd_defconfig +++ b/configs/mx6sabresd_defconfig @@ -18,6 +18,9 @@ CONFIG_SPL=y CONFIG_SPL_EXT_SUPPORT=y CONFIG_SPL_I2C_SUPPORT=y CONFIG_SPL_OS_BOOT=y +CONFIG_SPL_USB_HOST_SUPPORT=y +CONFIG_SPL_USB_GADGET_SUPPORT=y +CONFIG_SPL_USB_SDP_SUPPORT=y CONFIG_HUSH_PARSER=y CONFIG_CMD_BOOTZ=y # CONFIG_CMD_IMLS is not set @@ -31,6 +34,7 @@ CONFIG_CMD_PART=y CONFIG_CMD_PCI=y CONFIG_CMD_SF=y CONFIG_CMD_USB=y +CONFIG_CMD_USB_SDP=y CONFIG_CMD_DHCP=y CONFIG_CMD_MII=y CONFIG_CMD_PING=y -- cgit v1.1