diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2022-08-11 13:43:00 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2022-08-11 13:43:00 +0200 |
commit | 3fcf4400a7b051bdbe9fc175b88336519099ff22 (patch) | |
tree | 59e47312f23697970b3defc010a15f367b8e5082 | |
parent | b33c2913d747d3c55019a1d310427ca2697de6fc (diff) | |
parent | 22a073e3a9cdbc8034d5c58a6840e2567e5b3ddd (diff) | |
download | barebox-3fcf4400a7b051bdbe9fc175b88336519099ff22.tar.gz barebox-3fcf4400a7b051bdbe9fc175b88336519099ff22.tar.xz |
Merge branch 'for-next/imx'
52 files changed, 1079 insertions, 570 deletions
diff --git a/Documentation/boards/imx/meerkat96.rst b/Documentation/boards/imx/meerkat96.rst new file mode 100644 index 0000000000..7456aa857b --- /dev/null +++ b/Documentation/boards/imx/meerkat96.rst @@ -0,0 +1,43 @@ +Meerkat 96 +========== + +The Meerkat96 is a single board computer based on an i.MX7D SoC by NXP, +featuring a dual core ARM Cortex-A7 at 1 GHz and a Cortex-M4 at 266MHz +and 512 MB DRAM. For further details on the board's features check the +manufacturers page at https://www.96boards.org/product/imx7-96 + +Serial console +-------------- + +UART6 of the i.MX7D is broken out to Pinheader J3, on the Silkscreen +the Pins are labeled with B (Ground), W (UART 6 TX) and G (UART 6 RX). +If you use the UART-To-USB-Converter provided with the board, you can +just connect the Black jumper to B, the White to W and the Green to G. + +The UART uses 3.3V levels. + +Building Barebox +---------------- + +To build Barebox for the meerkat96 board do the following: + +.. code-block:: sh + + make ARCH=arm CROSS_COMPILE=<ARM toolchain prefix> mrproper + make ARCH=arm CROSS_COMPILE=<ARM toolchain prefix> imx_v7_defconfig + make ARCH=arm CROSS_COMPILE=<ARM toolchain prefix> + +Bringup +------- + +flash the resulting barebox-meerkat96.img to an sdcard at address 0. + +Make sure the pmic is set to power-on state by setting the dipswitch +SW3 on the boards bottom side to 1-1 (i.e. all switches on, which is +the factory default). + +Schematics +---------- + +Schematics are available at https://github.com/96boards/documentation/blob/master/consumer/imx7-96/hardware-docs/files/iMX7-96-schematics.pdf + diff --git a/Documentation/boards/imx/nxp-imx8mp-evk.rst b/Documentation/boards/imx/nxp-imx8mp-evk.rst index 366c1de500..1074992f2f 100644 --- a/Documentation/boards/imx/nxp-imx8mp-evk.rst +++ b/Documentation/boards/imx/nxp-imx8mp-evk.rst @@ -40,15 +40,18 @@ As a last step of this process those files need to be placed in firmware/${f}; \ done -Get and Build the ARM Trusted firmware --------------------------------------- +Get and Build the Trusted Firmware A +------------------------------------ -Get ATF from https://source.codeaurora.org/external/imx/imx-atf, branch -imx_5.4.3_2.0.0:: +Get TF-A from https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/ and +checkout version v2.7:: make PLAT=imx8mp bl31 cp build/imx8mp/release/bl31.bin ${barebox_srctree}/imx8mp-bl31.bin +.. warning:: It is important to use a version >= v2.7 else your system + might not boot. + Build Barebox ------------- diff --git a/arch/arm/boards/Makefile b/arch/arm/boards/Makefile index 3ccde26f1b..96f81a32d6 100644 --- a/arch/arm/boards/Makefile +++ b/arch/arm/boards/Makefile @@ -52,6 +52,7 @@ obj-$(CONFIG_MACH_FREESCALE_MX53_LOCO) += freescale-mx53-qsb/ obj-$(CONFIG_MACH_FREESCALE_MX53_SMD) += freescale-mx53-smd/ obj-$(CONFIG_MACH_FREESCALE_MX53_VMX53) += freescale-mx53-vmx53/ obj-$(CONFIG_MACH_FREESCALE_MX7_SABRESD) += freescale-mx7-sabresd/ +obj-$(CONFIG_MACH_MEERKAT96) += meerkat96/ obj-$(CONFIG_MACH_GE863) += telit-evk-pro3/ obj-$(CONFIG_MACH_GK802) += gk802/ obj-$(CONFIG_MACH_GLOBALSCALE_GURUPLUG) += globalscale-guruplug/ diff --git a/arch/arm/boards/ls1046ardb/lowlevel.c b/arch/arm/boards/ls1046ardb/lowlevel.c index 0a30f05aa2..055e5f4c99 100644 --- a/arch/arm/boards/ls1046ardb/lowlevel.c +++ b/arch/arm/boards/ls1046ardb/lowlevel.c @@ -5,7 +5,7 @@ #include <ddr_spd.h> #include <image-metadata.h> #include <platform_data/mmc-esdhc-imx.h> -#include <i2c/i2c-early.h> +#include <pbl/i2c.h> #include <soc/fsl/fsl_ddr_sdram.h> #include <soc/fsl/immap_lsch2.h> #include <asm/barebox-arm-head.h> @@ -187,7 +187,7 @@ static struct fsl_ddr_info ls1046a_info = { static noinline __noreturn void ls1046ardb_r_entry(unsigned long memsize) { unsigned long membase = LS1046A_DDR_SDRAM_BASE; - struct fsl_i2c *i2c; + struct pbl_i2c *i2c; int ret; if (get_pc() >= membase) { @@ -205,7 +205,7 @@ static noinline __noreturn void ls1046ardb_r_entry(unsigned long memsize) IMD_USED_OF(fsl_ls1046a_rdb); i2c = ls1046_i2c_init(IOMEM(LSCH2_I2C1_BASE_ADDR)); - ret = spd_read_eeprom(i2c, i2c_fsl_xfer, 0x51, &spd_eeprom); + ret = spd_read_eeprom(i2c, 0x51, &spd_eeprom); if (ret) { pr_err("Cannot read SPD EEPROM: %d\n", ret); goto err; diff --git a/arch/arm/boards/meerkat96/Makefile b/arch/arm/boards/meerkat96/Makefile new file mode 100644 index 0000000000..5678718188 --- /dev/null +++ b/arch/arm/boards/meerkat96/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only + +lwl-y += lowlevel.o +obj-y += board.o diff --git a/arch/arm/boards/meerkat96/board.c b/arch/arm/boards/meerkat96/board.c new file mode 100644 index 0000000000..49e9c06f78 --- /dev/null +++ b/arch/arm/boards/meerkat96/board.c @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include <of.h> +#include <deep-probe.h> + +static const struct of_device_id meerkat96_match[] = { + { .compatible = "novtech,imx7d-meerkat96" }, + { /* Sentinel */ }, +}; +BAREBOX_DEEP_PROBE_ENABLE(meerkat96_match); diff --git a/arch/arm/boards/meerkat96/flash-header-mx7-meerkat96.imxcfg b/arch/arm/boards/meerkat96/flash-header-mx7-meerkat96.imxcfg new file mode 100644 index 0000000000..a49b816178 --- /dev/null +++ b/arch/arm/boards/meerkat96/flash-header-mx7-meerkat96.imxcfg @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2014 Freescale Semiconductor, Inc. + */ + +soc imx7 +loadaddr 0x80000000 +ivtofs 0x400 + +/* + * Device Configuration Data (DCD) + * + * Each entry must have the format: + * Addr-type Address Value + * + * where: + * Addr-type register length (1,2 or 4 bytes) + * Address absolute address of the register + * value value to be stored in the register + */ + +/* Enable OCRAM EPDC */ +wm 32 0x30340004 0x4F400005 + +/* ============================================================================= + * DDR Controller Registers + * ============================================================================= + * Memory type: DDR3 + * Manufacturer: ISSI + * Device Part Number: IS43TR16256AL-125KBL + * Clock Freq.: 533MHz + * Density per CS in Gb: 4 + * Chip Selects used: 1 + * Number of Banks: 8 + * Row address: 15 + * Column address: 10 + * Data bus width: 16 + * ROW-BANK interleave: ENABLED + * ============================================================================= + */ + +wm 32 0x30391000 0x00000002 // deassert presetn +wm 32 0x307A0000 0x01041001 // DDRC_MSTR +wm 32 0x307A0064 0x00400046 // DDRC_RFSHTMG +wm 32 0x307a0490 0x00000001 // DDRC_PCTRL_0 +wm 32 0x307A00D4 0x00690000 // DDRC_INIT1 +wm 32 0x307A00D0 0x00020083 // DDRC_INIT0 +wm 32 0x307A00DC 0x09300004 // DDRC_INIT3 +wm 32 0x307A00E0 0x04080000 // DDRC_INIT4 +wm 32 0x307A00E4 0x00100004 // DDRC_INIT5 +wm 32 0x307A00F4 0x0000033F // DDRC_RANKCTL +wm 32 0x307A0100 0x090B1109 // DDRC_DRAMTMG0 +wm 32 0x307A0104 0x0007020D // DDRC_DRAMTMG1 +wm 32 0x307A0108 0x03040407 // DDRC_DRAMTMG2 +wm 32 0x307A010C 0x00002006 // DDRC_DRAMTMG3 +wm 32 0x307A0110 0x04020205 // DDRC_DRAMTMG4 +wm 32 0x307A0114 0x03030202 // DDRC_DRAMTMG5 +wm 32 0x307A0120 0x00000803 // DDRC_DRAMTMG8 +wm 32 0x307A0180 0x00800020 // DDRC_ZQCTL0 +wm 32 0x307A0190 0x02098204 // DDRC_DFITMG0 +wm 32 0x307A0194 0x00030303 // DDRC_DFITMG1 +wm 32 0x307A01A0 0x80400003 // DDRC_DFIUPD0 +wm 32 0x307A01A4 0x00100020 // DDRC_DFIUPD1 +wm 32 0x307A01A8 0x80100004 // DDRC_DFIUPD2 +wm 32 0x307A0200 0x00000015 // DDRC_ADDRMAP0 +wm 32 0x307A0204 0x00070707 // DDRC_ADDRMAP1 +wm 32 0x307A0210 0x00000F0F // DDRC_ADDRMAP4 +wm 32 0x307A0214 0x06060606 // DDRC_ADDRMAP5 +wm 32 0x307A0218 0x0F060606 // DDRC_ADDRMAP6 +wm 32 0x307A0240 0x06000604 // DDRC_ODTCFG +wm 32 0x307A0244 0x00000001 // DDRC_ODTMAP + + +/* ============================================================================= + * PHY Control Register + * ============================================================================= + */ + +wm 32 0x30391000 0x00000000 // deassert presetn +wm 32 0x30790000 0x17420F40 // DDR_PHY_PHY_CON0 +wm 32 0x30790004 0x10210100 // DDR_PHY_PHY_CON1 +wm 32 0x30790010 0x00060807 // DDR_PHY_PHY_CON4 +wm 32 0x307900B0 0x1010007E // DDR_PHY_MDLL_CON0 +wm 32 0x3079009C 0x00000D6E // DDR_PHY_DRVDS_CON0 +wm 32 0x30790030 0x08080808 // DDR_PHY_OFFSET_WR_CON0 +wm 32 0x30790020 0x08080808 // DDR_PHY_OFFSET_RD_CON0 +wm 32 0x30790050 0x01000010 // DDR_PHY_OFFSETD_CON0 +wm 32 0x30790050 0x00000010 // DDR_PHY_OFFSETD_CON0 +wm 32 0x30790018 0x0000000F // DDR_PHY_LP_CON0 +wm 32 0x307900C0 0x0E407304 // DDR_PHY_ZQ_CON0 - Start Manual ZQ +wm 32 0x307900C0 0x0E447304 +wm 32 0x307900C0 0x0E447306 +wm 32 0x307900C0 0x0E447304 // <= NOTE: Depending on JTAG device used, may need ~ 7 us pause at this point. +wm 32 0x307900C0 0x0E407304 // DDR_PHY_ZQ_CON0 - End Manual ZQ + + +/* ============================================================================= + * Final Initialization start sequence + * ============================================================================= + */ + +wm 32 0x30384130 0x00000000 // Disable Clock +wm 32 0x30340020 0x00000178 // IOMUX_GRP_GRP8 - Start input to PHY +wm 32 0x30384130 0x00000002 // Enable Clock +/* <= NOTE: Depending on JTAG device used, may need ~ 250 us pause at this point. */ diff --git a/arch/arm/boards/meerkat96/lowlevel.c b/arch/arm/boards/meerkat96/lowlevel.c new file mode 100644 index 0000000000..1c9baeacfb --- /dev/null +++ b/arch/arm/boards/meerkat96/lowlevel.c @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include <debug_ll.h> +#include <io.h> +#include <linux/sizes.h> +#include <mach/debug_ll.h> +#include <mach/iomux-mx7.h> +#include <mach/imx7-ccm-regs.h> +#include <mach/generic.h> +#include <asm/barebox-arm-head.h> +#include <asm/barebox-arm.h> +#include <asm/cache.h> +extern char __dtb_z_imx7d_meerkat96_start[]; + +static void setup_uart(void) +{ + imx7_early_setup_uart_clock(); + imx7_setup_pad(MX7D_PAD_SD1_WP__UART6_DCE_TX); + imx7_uart_setup_ll(); + putc_ll('>'); +} + +ENTRY_FUNCTION_WITHSTACK(start_imx7d_meerkat96, 0, r0, r1, r2) +{ + void *fdt; + + imx7_cpu_lowlevel_init(); + + setup_uart(); + + fdt = __dtb_z_imx7d_meerkat96_start + get_runtime_offset(); + + barebox_arm_entry(0x80000000, SZ_512M, fdt); +} diff --git a/arch/arm/boards/mnt-reform/lowlevel.c b/arch/arm/boards/mnt-reform/lowlevel.c index 268dfb611a..d22c8b8a74 100644 --- a/arch/arm/boards/mnt-reform/lowlevel.c +++ b/arch/arm/boards/mnt-reform/lowlevel.c @@ -7,7 +7,8 @@ #include <common.h> #include <debug_ll.h> #include <firmware.h> -#include <i2c/i2c-early.h> +#include <pbl/i2c.h> +#include <pbl/pmic.h> #include <mach/atf.h> #include <mach/esdctl.h> #include <mach/generic.h> @@ -18,7 +19,7 @@ #include <mach/xload.h> #include <soc/imx8m/ddr.h> -extern char __dtb_imx8mq_mnt_reform2_start[]; +extern char __dtb_z_imx8mq_mnt_reform2_start[]; #define UART_PAD_CTRL MUX_PAD_CTRL(MX8MQ_PAD_CTL_DSE_65R) @@ -36,7 +37,7 @@ static void mnt_reform_setup_uart(void) putc_ll('>'); } -static void i2c_mux_set(void *i2c, u8 channel) +static void i2c_mux_set(struct pbl_i2c *i2c, u8 channel) { int ret; u8 buf[1]; @@ -50,29 +51,14 @@ static void i2c_mux_set(void *i2c, u8 channel) buf[0] = 1 << channel; - ret = i2c_fsl_xfer(i2c, msgs, ARRAY_SIZE(msgs)); + ret = pbl_i2c_xfer(i2c, msgs, ARRAY_SIZE(msgs)); if (ret != 1) pr_err("failed to set i2c mux\n"); } -static void i2c_regulator_set_voltage(void *i2c, u8 reg, u8 voffs) +static void i2c_regulator_set_voltage(struct pbl_i2c *i2c, u8 reg, u8 voffs) { - int ret; - u8 buf[2]; - struct i2c_msg msgs[] = { - { - .addr = 0x60, - .buf = buf, - .len = 2, - }, - }; - - buf[0] = reg; - buf[1] = 0x80 + voffs; - - ret = i2c_fsl_xfer(i2c, msgs, ARRAY_SIZE(msgs)); - if (ret != 1) - pr_err("failed to set voltage\n"); + pmic_reg_write(i2c, 0x60, reg, 0x80 + voffs); } #define I2C_PAD_CTRL MUX_PAD_CTRL(MX8MQ_PAD_CTL_DSE_45R | \ @@ -81,7 +67,7 @@ static void i2c_regulator_set_voltage(void *i2c, u8 reg, u8 voffs) static void mnt_reform_init_power(void) { - void *i2c; + struct pbl_i2c *i2c; imx8mq_setup_pad(IMX8MQ_PAD_I2C1_SCL__I2C1_SCL | I2C_PAD_CTRL); imx8mq_setup_pad(IMX8MQ_PAD_I2C1_SDA__I2C1_SDA | I2C_PAD_CTRL); @@ -139,7 +125,7 @@ static __noreturn noinline void mnt_reform_start(void) mnt_reform_init_power(); - imx8mq_ddr_init(&mnt_reform_dram_timing); + imx8mq_ddr_init(&mnt_reform_dram_timing, DRAM_TYPE_LPDDR4); imx8mq_get_boot_source(&src, &instance); switch (src) { @@ -173,7 +159,7 @@ static __noreturn noinline void mnt_reform_start(void) /* * Standard entry we hit once we initialized both DDR and ATF */ - imx8mq_barebox_entry(__dtb_imx8mq_mnt_reform2_start); + imx8mq_barebox_entry(__dtb_z_imx8mq_mnt_reform2_start); } ENTRY_FUNCTION(start_mnt_reform, r0, r1, r2) diff --git a/arch/arm/boards/mnt-reform/lpddr4-timing.c b/arch/arm/boards/mnt-reform/lpddr4-timing.c index 0e962890fd..0b5853000d 100644 --- a/arch/arm/boards/mnt-reform/lpddr4-timing.c +++ b/arch/arm/boards/mnt-reform/lpddr4-timing.c @@ -1000,7 +1000,6 @@ static struct dram_fsp_msg mnt_reform_lpddr4_dram_fsp_msg[] = { /* ddr timing config params */ struct dram_timing_info mnt_reform_dram_timing = { - .dram_type = DRAM_TYPE_LPDDR4, .ddrc_cfg = mnt_reform_lpddr4_ddrc_cfg, .ddrc_cfg_num = ARRAY_SIZE(mnt_reform_lpddr4_ddrc_cfg), .ddrphy_cfg = mnt_reform_lpddr4_ddrphy_cfg, diff --git a/arch/arm/boards/nxp-imx8mm-evk/lowlevel.c b/arch/arm/boards/nxp-imx8mm-evk/lowlevel.c index c2f6206cfd..6132df53ec 100644 --- a/arch/arm/boards/nxp-imx8mm-evk/lowlevel.c +++ b/arch/arm/boards/nxp-imx8mm-evk/lowlevel.c @@ -3,27 +3,24 @@ #include <io.h> #include <common.h> #include <debug_ll.h> -#include <firmware.h> #include <asm/mmu.h> #include <asm/cache.h> -#include <asm/sections.h> #include <asm/barebox-arm.h> #include <asm/barebox-arm-head.h> -#include <i2c/i2c-early.h> +#include <pbl/i2c.h> +#include <pbl/pmic.h> #include <linux/sizes.h> -#include <mach/atf.h> -#include <mach/xload.h> #include <mach/esdctl.h> #include <mach/generic.h> #include <mach/imx8mm-regs.h> #include <mach/iomux-mx8mm.h> #include <mach/imx8m-ccm-regs.h> #include <mfd/bd71837.h> +#include <mach/xload.h> #include <soc/imx8m/ddr.h> -#include <soc/fsl/fsl_udc.h> #include <image-metadata.h> -extern char __dtb_imx8mm_evk_start[]; +extern char __dtb_z_imx8mm_evk_start[]; #define UART_PAD_CTRL MUX_PAD_CTRL(PAD_CTL_DSE_3P3V_45_OHM) @@ -41,30 +38,22 @@ static void setup_uart(void) putc_ll('>'); } -static void pmic_reg_write(void *i2c, int reg, uint8_t val) -{ - int ret; - u8 buf[32]; - struct i2c_msg msgs[] = { - { - .addr = 0x4b, - .buf = buf, - }, - }; - - buf[0] = reg; - buf[1] = val; - - msgs[0].len = 2; - - ret = i2c_fsl_xfer(i2c, msgs, ARRAY_SIZE(msgs)); - if (ret != 1) - pr_err("Failed to write to pmic\n"); -} +static struct pmic_config bd71837_cfg[] = { + /* decrease RESET key long push time from the default 10s to 10ms */ + { BD718XX_PWRONCONFIG1, 0x0 }, + /* unlock the PMIC regs */ + { BD718XX_REGLOCK, 0x1 }, + /* increase VDD_SOC to typical value 0.85v before first DRAM access */ + { BD718XX_BUCK1_VOLT_RUN, 0x0f }, + /* increase VDD_DRAM to 0.975v for 3Ghz DDR */ + { BD718XX_1ST_NODVS_BUCK_VOLT, 0x83 }, + /* lock the PMIC regs */ + { BD718XX_REGLOCK, 0x11 }, +}; -static int power_init_board(void) +static void power_init_board(void) { - void *i2c; + struct pbl_i2c *i2c; imx8mm_setup_pad(IMX8MM_PAD_I2C1_SCL_I2C1_SCL); imx8mm_setup_pad(IMX8MM_PAD_I2C1_SDA_I2C1_SDA); @@ -74,33 +63,13 @@ static int power_init_board(void) i2c = imx8m_i2c_early_init(IOMEM(MX8MQ_I2C1_BASE_ADDR)); - /* decrease RESET key long push time from the default 10s to 10ms */ - pmic_reg_write(i2c, BD718XX_PWRONCONFIG1, 0x0); - - /* unlock the PMIC regs */ - pmic_reg_write(i2c, BD718XX_REGLOCK, 0x1); - - /* increase VDD_SOC to typical value 0.85v before first DRAM access */ - pmic_reg_write(i2c, BD718XX_BUCK1_VOLT_RUN, 0x0f); - - /* increase VDD_DRAM to 0.975v for 3Ghz DDR */ - pmic_reg_write(i2c, BD718XX_1ST_NODVS_BUCK_VOLT, 0x83); - - /* lock the PMIC regs */ - pmic_reg_write(i2c, BD718XX_REGLOCK, 0x11); - - return 0; + pmic_configure(i2c, 0x4b, bd71837_cfg, ARRAY_SIZE(bd71837_cfg)); } extern struct dram_timing_info imx8mm_evk_dram_timing; static void start_atf(void) { - size_t bl31_size; - const u8 *bl31; - enum bootsource src; - int instance; - /* * If we are in EL3 we are running for the first time and need to * initialize the DRAM and run TF-A (BL31). The TF-A will then jump @@ -110,37 +79,9 @@ static void start_atf(void) return; power_init_board(); - imx8mm_ddr_init(&imx8mm_evk_dram_timing); - - imx8mm_get_boot_source(&src, &instance); - switch (src) { - case BOOTSOURCE_MMC: - imx8m_esdhc_load_image(instance, false); - break; - case BOOTSOURCE_SERIAL: - imx8mm_barebox_load_usb((void *)MX8M_ATF_BL33_BASE_ADDR); - break; - default: - printf("Unhandled bootsource BOOTSOURCE_%d\n", src); - hang(); - } - - /* - * On completion the TF-A will jump to MX8M_ATF_BL33_BASE_ADDR - * in EL2. Copy the image there, but replace the PBL part of - * that image with ourselves. On a high assurance boot only the - * currently running code is validated and contains the checksum - * for the piggy data, so we need to ensure that we are running - * the same code in DRAM. - */ - memcpy((void *)MX8M_ATF_BL33_BASE_ADDR, - __image_start, barebox_pbl_size); - - get_builtin_firmware(imx8mm_bl31_bin, &bl31, &bl31_size); - - imx8mm_atf_load_bl31(bl31, bl31_size); + imx8mm_ddr_init(&imx8mm_evk_dram_timing, DRAM_TYPE_LPDDR4); - /* not reached */ + imx8mm_load_and_start_image_via_tfa(); } /* @@ -168,7 +109,7 @@ static __noreturn noinline void nxp_imx8mm_evk_start(void) /* * Standard entry we hit once we initialized both DDR and ATF */ - imx8mm_barebox_entry(__dtb_imx8mm_evk_start); + imx8mm_barebox_entry(__dtb_z_imx8mm_evk_start); } ENTRY_FUNCTION(start_nxp_imx8mm_evk, r0, r1, r2) diff --git a/arch/arm/boards/nxp-imx8mm-evk/lpddr4-timing.c b/arch/arm/boards/nxp-imx8mm-evk/lpddr4-timing.c index 68efbbdf91..e7c01f9cc9 100644 --- a/arch/arm/boards/nxp-imx8mm-evk/lpddr4-timing.c +++ b/arch/arm/boards/nxp-imx8mm-evk/lpddr4-timing.c @@ -1965,7 +1965,6 @@ static struct dram_fsp_msg lpddr4_dram_fsp_msg[] = { /* lpddr4 timing config params on EVK board */ struct dram_timing_info imx8mm_evk_dram_timing = { - .dram_type = DRAM_TYPE_LPDDR4, .ddrc_cfg = lpddr4_ddrc_cfg, .ddrc_cfg_num = ARRAY_SIZE(lpddr4_ddrc_cfg), .ddrphy_cfg = lpddr4_ddrphy_cfg, diff --git a/arch/arm/boards/nxp-imx8mn-evk/board.c b/arch/arm/boards/nxp-imx8mn-evk/board.c index 3c478d5f70..3606dabe9d 100644 --- a/arch/arm/boards/nxp-imx8mn-evk/board.c +++ b/arch/arm/boards/nxp-imx8mn-evk/board.c @@ -5,6 +5,7 @@ #include <bootsource.h> #include <common.h> +#include <deep-probe.h> #include <init.h> #include <linux/phy.h> #include <linux/sizes.h> @@ -30,14 +31,11 @@ static int ar8031_phy_fixup(struct phy_device *phydev) return 0; } -static int nxp_imx8mn_evk_init(void) +static int imx8mn_evk_probe(struct device_d *dev) { int emmc_bbu_flag = 0; int sd_bbu_flag = 0; - if (!of_machine_is_compatible("fsl,imx8mn-evk")) - return 0; - if (bootsource_get() == BOOTSOURCE_MMC) { if (bootsource_get_instance() == 2) { of_device_enable_path("/chosen/environment-emmc"); @@ -59,4 +57,17 @@ static int nxp_imx8mn_evk_init(void) return 0; } -coredevice_initcall(nxp_imx8mn_evk_init); + +static const struct of_device_id imx8mn_evk_of_match[] = { + { .compatible = "fsl,imx8mn-evk" }, + { .compatible = "fsl,imx8mn-ddr4-evk" }, + { /* sentinel */ }, +}; +BAREBOX_DEEP_PROBE_ENABLE(imx8mn_evk_of_match); + +static struct driver_d imx8mn_evkboard_driver = { + .name = "board-imx8mn-evk", + .probe = imx8mn_evk_probe, + .of_compatible = DRV_OF_COMPAT(imx8mn_evk_of_match), +}; +coredevice_platform_driver(imx8mn_evkboard_driver); diff --git a/arch/arm/boards/nxp-imx8mn-evk/ddr4-timing.c b/arch/arm/boards/nxp-imx8mn-evk/ddr4-timing.c index 7ce371384e..131a63156e 100644 --- a/arch/arm/boards/nxp-imx8mn-evk/ddr4-timing.c +++ b/arch/arm/boards/nxp-imx8mn-evk/ddr4-timing.c @@ -1040,7 +1040,6 @@ static struct dram_fsp_msg ddr_dram_fsp_msg[] = { /* ddr timing config params */ struct dram_timing_info imx8mn_evk_ddr4_timing = { - .dram_type = DRAM_TYPE_DDR4, .ddrc_cfg = ddr_ddrc_cfg, .ddrc_cfg_num = ARRAY_SIZE(ddr_ddrc_cfg), .ddrphy_cfg = ddr_ddrphy_cfg, diff --git a/arch/arm/boards/nxp-imx8mn-evk/lowlevel.c b/arch/arm/boards/nxp-imx8mn-evk/lowlevel.c index de53213ebc..7da9c33565 100644 --- a/arch/arm/boards/nxp-imx8mn-evk/lowlevel.c +++ b/arch/arm/boards/nxp-imx8mn-evk/lowlevel.c @@ -9,7 +9,8 @@ #include <asm/sections.h> #include <asm/barebox-arm.h> #include <asm/barebox-arm-head.h> -#include <i2c/i2c-early.h> +#include <pbl/i2c.h> +#include <pbl/pmic.h> #include <linux/sizes.h> #include <mach/atf.h> #include <mach/xload.h> @@ -22,8 +23,6 @@ #include <mfd/bd71837.h> #include <soc/imx8m/ddr.h> -extern char __dtb_z_imx8mn_evk_start[]; - static void setup_uart(void) { void __iomem *uart = IOMEM(MX8M_UART2_BASE_ADDR); @@ -38,108 +37,50 @@ static void setup_uart(void) putc_ll('>'); } -static void pmic_reg_write(void *i2c, int addr, int reg, uint8_t val) -{ - int ret; - u8 buf[32]; - struct i2c_msg msgs[] = { - { - .addr = addr, - .buf = buf, - }, - }; - - buf[0] = reg; - buf[1] = val; - - msgs[0].len = 2; - - ret = i2c_fsl_xfer(i2c, msgs, ARRAY_SIZE(msgs)); - if (ret != 1) - pr_err("Failed to write to pmic@%x: %d\n", addr, ret); -} - -static int power_init_board_pca9450(void *i2c, int addr) -{ - u8 buf[1]; - struct i2c_msg msgs[] = { - { - .addr = addr, - .buf = buf, - .flags = I2C_M_RD, - .len = 1, - }, - }; - - if (i2c_fsl_xfer(i2c, msgs, 1) != 1) - return -ENODEV; - +static struct pmic_config pca9450_cfg[] = { /* BUCKxOUT_DVS0/1 control BUCK123 output */ - pmic_reg_write(i2c, addr, PCA9450_BUCK123_DVS, 0x29); - + { PCA9450_BUCK123_DVS, 0x29 }, /* * increase VDD_SOC to typical value 0.95V before first * DRAM access, set DVS1 to 0.85v for suspend. * Enable DVS control through PMIC_STBY_REQ and * set B1_ENMODE=1 (ON by PMIC_ON_REQ=H) */ - pmic_reg_write(i2c, addr, PCA9450_BUCK1OUT_DVS0, 0x1C); - + { PCA9450_BUCK1OUT_DVS0, 0x1C }, /* Set DVS1 to 0.85v for suspend */ /* Enable DVS control through PMIC_STBY_REQ and set B1_ENMODE=1 (ON by PMIC_ON_REQ=H) */ - pmic_reg_write(i2c, addr, PCA9450_BUCK1OUT_DVS1, 0x14); - pmic_reg_write(i2c, addr, PCA9450_BUCK1CTRL, 0x59); - + { PCA9450_BUCK1OUT_DVS1, 0x14 }, + { PCA9450_BUCK1CTRL, 0x59 }, /* set VDD_SNVS_0V8 from default 0.85V */ - pmic_reg_write(i2c, addr, PCA9450_LDO2CTRL, 0xC0); - + { PCA9450_LDO2CTRL, 0xC0 }, /* enable LDO4 to 1.2v */ - pmic_reg_write(i2c, addr, PCA9450_LDO4CTRL, 0x44); - + { PCA9450_LDO4CTRL, 0x44 }, /* set WDOG_B_CFG to cold reset */ - pmic_reg_write(i2c, addr, PCA9450_RESET_CTRL, 0xA1); - - return 0; -} + { PCA9450_RESET_CTRL, 0xA1 }, +}; -static int power_init_board_bd71837(void *i2c, int addr) -{ +static struct pmic_config bd71837_cfg[] = { /* decrease RESET key long push time from the default 10s to 10ms */ - pmic_reg_write(i2c, addr, BD718XX_PWRONCONFIG1, 0x0); - + { BD718XX_PWRONCONFIG1, 0x0 }, /* unlock the PMIC regs */ - pmic_reg_write(i2c, addr, BD718XX_REGLOCK, 0x1); - + { BD718XX_REGLOCK, 0x1 }, /* Set VDD_ARM to typical value 0.85v for 1.2Ghz */ - pmic_reg_write(i2c, addr, BD718XX_BUCK2_VOLT_RUN, 0xf); - + { BD718XX_BUCK2_VOLT_RUN, 0xf }, /* Set VDD_SOC/VDD_DRAM to typical value 0.85v for nominal mode */ - pmic_reg_write(i2c, addr, BD718XX_BUCK1_VOLT_RUN, 0xf); - + { BD718XX_BUCK1_VOLT_RUN, 0xf }, /* Set VDD_SOC 0.85v for suspend */ - pmic_reg_write(i2c, addr, BD718XX_BUCK1_VOLT_SUSP, 0xf); - - /* increase NVCC_DRAM_1V2 to 1.2v for DDR4 - * */ - pmic_reg_write(i2c, addr, BD718XX_4TH_NODVS_BUCK_CTRL, 0x28); - + { BD718XX_BUCK1_VOLT_SUSP, 0xf }, + /* increase NVCC_DRAM_1V2 to 1.2v for DDR4 */ + { BD718XX_4TH_NODVS_BUCK_CTRL, 0x28 }, /* lock the PMIC regs */ - pmic_reg_write(i2c, addr, BD718XX_REGLOCK, 0x11); - - return 0; -} + { BD718XX_REGLOCK, 0x11 }, +}; extern struct dram_timing_info imx8mn_evk_ddr4_timing, imx8mn_evk_lpddr4_timing; static void start_atf(void) { - struct dram_timing_info *dram_timing = &imx8mn_evk_lpddr4_timing; - size_t bl31_size; - const u8 *bl31; - enum bootsource src; - void *i2c; - int instance; - int ret; + struct pbl_i2c *i2c; /* * If we are in EL3 we are running for the first time and need to @@ -157,40 +98,15 @@ static void start_atf(void) i2c = imx8m_i2c_early_init(IOMEM(MX8MN_I2C1_BASE_ADDR)); - ret = power_init_board_pca9450(i2c, 0x25); - if (ret) { - power_init_board_bd71837(i2c, 0x4b); - dram_timing = &imx8mn_evk_ddr4_timing; - } - - imx8mn_ddr_init(dram_timing); - - imx8mn_get_boot_source(&src, &instance); - switch (src) { - case BOOTSOURCE_MMC: - imx8mn_esdhc_load_image(instance, false); - break; - default: - printf("Unhandled bootsource BOOTSOURCE_%d\n", src); - hang(); + if (i2c_dev_probe(i2c, 0x25, true) == 0) { + pmic_configure(i2c, 0x25, pca9450_cfg, ARRAY_SIZE(pca9450_cfg)); + imx8mn_ddr_init(&imx8mn_evk_lpddr4_timing, DRAM_TYPE_LPDDR4); + } else { + pmic_configure(i2c, 0x4b, bd71837_cfg, ARRAY_SIZE(bd71837_cfg)); + imx8mn_ddr_init(&imx8mn_evk_ddr4_timing, DRAM_TYPE_DDR4); } - /* - * On completion the TF-A will jump to MX8M_ATF_BL33_BASE_ADDR - * in EL2. Copy the image there, but replace the PBL part of - * that image with ourselves. On a high assurance boot only the - * currently running code is validated and contains the checksum - * for the piggy data, so we need to ensure that we are running - * the same code in DRAM. - */ - memcpy((void *)MX8M_ATF_BL33_BASE_ADDR, - __image_start, barebox_pbl_size); - - get_builtin_firmware(imx8mn_bl31_bin, &bl31, &bl31_size); - - imx8mn_atf_load_bl31(bl31, bl31_size); - - /* not reached */ + imx8mn_load_and_start_image_via_tfa(); } /* @@ -211,14 +127,23 @@ static void start_atf(void) */ static __noreturn noinline void nxp_imx8mn_evk_start(void) { + extern char __dtb_z_imx8mn_evk_start[], __dtb_z_imx8mn_ddr4_evk_start[]; + void *fdt; + setup_uart(); start_atf(); + /* Check if we configured DDR4 in EL3 */ + if (readl(MX8M_DDRC_CTL_BASE_ADDR) & BIT(4)) + fdt = __dtb_z_imx8mn_ddr4_evk_start; + else + fdt = __dtb_z_imx8mn_evk_start; + /* * Standard entry we hit once we initialized both DDR and ATF */ - imx8mn_barebox_entry(__dtb_z_imx8mn_evk_start); + imx8mn_barebox_entry(fdt); } ENTRY_FUNCTION(start_nxp_imx8mn_evk, r0, r1, r2) diff --git a/arch/arm/boards/nxp-imx8mn-evk/lpddr4-timing.c b/arch/arm/boards/nxp-imx8mn-evk/lpddr4-timing.c index c53bcc705d..940b21cedb 100644 --- a/arch/arm/boards/nxp-imx8mn-evk/lpddr4-timing.c +++ b/arch/arm/boards/nxp-imx8mn-evk/lpddr4-timing.c @@ -1576,7 +1576,6 @@ static struct dram_fsp_msg ddr_dram_fsp_msg[] = { /* ddr timing config params */ struct dram_timing_info imx8mn_evk_lpddr4_timing = { - .dram_type = DRAM_TYPE_LPDDR4, .ddrc_cfg = ddr_ddrc_cfg, .ddrc_cfg_num = ARRAY_SIZE(ddr_ddrc_cfg), .ddrphy_cfg = ddr_ddrphy_cfg, diff --git a/arch/arm/boards/nxp-imx8mp-evk/lowlevel.c b/arch/arm/boards/nxp-imx8mp-evk/lowlevel.c index c7916e4962..4f24dd4cd4 100644 --- a/arch/arm/boards/nxp-imx8mp-evk/lowlevel.c +++ b/arch/arm/boards/nxp-imx8mp-evk/lowlevel.c @@ -10,7 +10,8 @@ #include <asm/sections.h> #include <asm/barebox-arm.h> #include <asm/barebox-arm-head.h> -#include <i2c/i2c-early.h> +#include <pbl/i2c.h> +#include <pbl/pmic.h> #include <linux/sizes.h> #include <mach/atf.h> #include <mach/xload.h> @@ -23,7 +24,7 @@ #include <soc/imx8m/ddr.h> #include <soc/fsl/fsl_udc.h> -extern char __dtb_imx8mp_evk_start[]; +extern char __dtb_z_imx8mp_evk_start[]; #define UART_PAD_CTRL MUX_PAD_CTRL(MX8MP_PAD_CTL_DSE6 | \ MX8MP_PAD_CTL_FSEL) @@ -48,30 +49,25 @@ static void setup_uart(void) putc_ll('>'); } -static void pmic_reg_write(void *i2c, int reg, uint8_t val) -{ - int ret; - u8 buf[32]; - struct i2c_msg msgs[] = { - { - .addr = 0x25, - .buf = buf, - }, - }; - - buf[0] = reg; - buf[1] = val; - - msgs[0].len = 2; - - ret = i2c_fsl_xfer(i2c, msgs, ARRAY_SIZE(msgs)); - if (ret != 1) - pr_err("Failed to write to pmic\n"); -} +static struct pmic_config pca9450_cfg[] = { + /* BUCKxOUT_DVS0/1 control BUCK123 output */ + { PCA9450_BUCK123_DVS, 0x29 }, + /* + * increase VDD_SOC to typical value 0.95V before first + * DRAM access, set DVS1 to 0.85v for suspend. + * Enable DVS control through PMIC_STBY_REQ and + * set B1_ENMODE=1 (ON by PMIC_ON_REQ=H) + */ + { PCA9450_BUCK1OUT_DVS0, 0x1C }, + { PCA9450_BUCK1OUT_DVS1, 0x14 }, + { PCA9450_BUCK1CTRL, 0x59 }, + /* set WDOG_B_CFG to cold reset */ + { PCA9450_RESET_CTRL, 0xA1 }, +}; -static int power_init_board(void) +static void power_init_board(void) { - void *i2c; + struct pbl_i2c *i2c; imx8mp_setup_pad(MX8MP_PAD_I2C1_SCL__I2C1_SCL | I2C_PAD_CTRL); imx8mp_setup_pad(MX8MP_PAD_I2C1_SDA__I2C1_SDA | I2C_PAD_CTRL); @@ -81,34 +77,13 @@ static int power_init_board(void) i2c = imx8m_i2c_early_init(IOMEM(MX8MP_I2C1_BASE_ADDR)); - /* BUCKxOUT_DVS0/1 control BUCK123 output */ - pmic_reg_write(i2c, PCA9450_BUCK123_DVS, 0x29); - - /* - * increase VDD_SOC to typical value 0.95V before first - * DRAM access, set DVS1 to 0.85v for suspend. - * Enable DVS control through PMIC_STBY_REQ and - * set B1_ENMODE=1 (ON by PMIC_ON_REQ=H) - */ - pmic_reg_write(i2c, PCA9450_BUCK1OUT_DVS0, 0x1C); - pmic_reg_write(i2c, PCA9450_BUCK1OUT_DVS1, 0x14); - pmic_reg_write(i2c, PCA9450_BUCK1CTRL, 0x59); - - /* set WDOG_B_CFG to cold reset */ - pmic_reg_write(i2c, PCA9450_RESET_CTRL, 0xA1); - - return 0; + pmic_configure(i2c, 0x25, pca9450_cfg, ARRAY_SIZE(pca9450_cfg)); } extern struct dram_timing_info imx8mp_evk_dram_timing; static void start_atf(void) { - size_t bl31_size; - const u8 *bl31; - enum bootsource src; - int instance; - /* * If we are in EL3 we are running for the first time and need to * initialize the DRAM and run TF-A (BL31). The TF-A will then jump @@ -119,35 +94,9 @@ static void start_atf(void) power_init_board(); - imx8mp_ddr_init(&imx8mp_evk_dram_timing); - - imx8mp_get_boot_source(&src, &instance); - switch (src) { - case BOOTSOURCE_MMC: - imx8mp_esdhc_load_image(instance, false); - break; - default: - printf("Unhandled bootsource BOOTSOURCE_%d\n", src); - hang(); - } - - - /* - * On completion the TF-A will jump to MX8M_ATF_BL33_BASE_ADDR - * in EL2. Copy the image there, but replace the PBL part of - * that image with ourselves. On a high assurance boot only the - * currently running code is validated and contains the checksum - * for the piggy data, so we need to ensure that we are running - * the same code in DRAM. - */ - memcpy((void *)MX8M_ATF_BL33_BASE_ADDR, - __image_start, barebox_pbl_size); - - get_builtin_firmware(imx8mp_bl31_bin, &bl31, &bl31_size); - - imx8mp_atf_load_bl31(bl31, bl31_size); + imx8mp_ddr_init(&imx8mp_evk_dram_timing, DRAM_TYPE_LPDDR4); - /* not reached */ + imx8mp_load_and_start_image_via_tfa(); } /* @@ -175,7 +124,7 @@ static __noreturn noinline void nxp_imx8mp_evk_start(void) /* * Standard entry we hit once we initialized both DDR and ATF */ - imx8mp_barebox_entry(__dtb_imx8mp_evk_start); + imx8mp_barebox_entry(__dtb_z_imx8mp_evk_start); } ENTRY_FUNCTION(start_nxp_imx8mp_evk, r0, r1, r2) diff --git a/arch/arm/boards/nxp-imx8mp-evk/lpddr4-timing.c b/arch/arm/boards/nxp-imx8mp-evk/lpddr4-timing.c index 681e70d060..3028bc084c 100644 --- a/arch/arm/boards/nxp-imx8mp-evk/lpddr4-timing.c +++ b/arch/arm/boards/nxp-imx8mp-evk/lpddr4-timing.c @@ -1834,7 +1834,6 @@ static struct dram_fsp_msg ddr_dram_fsp_msg[] = { /* ddr timing config params */ struct dram_timing_info imx8mp_evk_dram_timing = { - .dram_type = DRAM_TYPE_LPDDR4, .ddrc_cfg = ddr_ddrc_cfg, .ddrc_cfg_num = ARRAY_SIZE(ddr_ddrc_cfg), .ddrphy_cfg = ddr_ddrphy_cfg, diff --git a/arch/arm/boards/nxp-imx8mq-evk/lowlevel.c b/arch/arm/boards/nxp-imx8mq-evk/lowlevel.c index 92cc22e022..0c9f6345ff 100644 --- a/arch/arm/boards/nxp-imx8mq-evk/lowlevel.c +++ b/arch/arm/boards/nxp-imx8mq-evk/lowlevel.c @@ -21,7 +21,7 @@ #include "ddr.h" -extern char __dtb_imx8mq_evk_start[]; +extern char __dtb_z_imx8mq_evk_start[]; #define UART_PAD_CTRL MUX_PAD_CTRL(PAD_CTL_DSE_3P3V_45_OHM) @@ -97,7 +97,7 @@ static __noreturn noinline void nxp_imx8mq_evk_start(void) /* * Standard entry we hit once we initialized both DDR and ATF */ - imx8mq_barebox_entry(__dtb_imx8mq_evk_start); + imx8mq_barebox_entry(__dtb_z_imx8mq_evk_start); } ENTRY_FUNCTION(start_nxp_imx8mq_evk, r0, r1, r2) diff --git a/arch/arm/boards/phytec-som-imx8mq/lowlevel.c b/arch/arm/boards/phytec-som-imx8mq/lowlevel.c index 05226866f8..d35f9b0d39 100644 --- a/arch/arm/boards/phytec-som-imx8mq/lowlevel.c +++ b/arch/arm/boards/phytec-som-imx8mq/lowlevel.c @@ -23,7 +23,7 @@ #include "ddr.h" -extern char __dtb_imx8mq_phytec_phycore_som_start[]; +extern char __dtb_z_imx8mq_phytec_phycore_som_start[]; #define UART_PAD_CTRL MUX_PAD_CTRL(PAD_CTL_DSE_3P3V_45_OHM) @@ -90,7 +90,7 @@ static __noreturn noinline void phytec_phycore_imx8mq_start(void) /* * Standard entry we hit once we initialized both DDR and ATF */ - imx8mq_barebox_entry(__dtb_imx8mq_phytec_phycore_som_start); + imx8mq_barebox_entry(__dtb_z_imx8mq_phytec_phycore_som_start); } /* diff --git a/arch/arm/boards/protonic-imx8m/lowlevel-prt8mm.c b/arch/arm/boards/protonic-imx8m/lowlevel-prt8mm.c index 24d98fe6c9..bfae39ea52 100644 --- a/arch/arm/boards/protonic-imx8m/lowlevel-prt8mm.c +++ b/arch/arm/boards/protonic-imx8m/lowlevel-prt8mm.c @@ -15,7 +15,7 @@ #include <soc/fsl/fsl_udc.h> #include <soc/imx8m/ddr.h> -extern char __dtb_imx8mm_prt8mm_start[]; +extern char __dtb_z_imx8mm_prt8mm_start[]; #define UART_PAD_CTRL MUX_PAD_CTRL(PAD_CTL_DSE_3P3V_45_OHM) @@ -37,11 +37,6 @@ extern struct dram_timing_info prt8mm_dram_timing; static void start_atf(void) { - size_t bl31_size; - const u8 *bl31; - enum bootsource src; - int instance; - /* * If we are in EL3 we are running for the first time and need to * initialize the DRAM and run TF-A (BL31). The TF-A will then jump @@ -52,36 +47,9 @@ static void start_atf(void) imx8mm_early_clock_init(); - imx8mm_ddr_init(&prt8mm_dram_timing); - - imx8mm_get_boot_source(&src, &instance); - switch (src) { - case BOOTSOURCE_MMC: - imx8m_esdhc_load_image(instance, false); - break; - case BOOTSOURCE_SERIAL: - imx8mm_barebox_load_usb((void *)MX8M_ATF_BL33_BASE_ADDR); - break; - default: - printf("Unhandled bootsource BOOTSOURCE_%d\n", src); - hang(); - } - - /* - * On completion the TF-A will jump to MX8M_ATF_BL33_BASE_ADDR - * in EL2. Copy the image there, but replace the PBL part of - * that image with ourselves. On a high assurance boot only the - * currently running code is validated and contains the checksum - * for the piggy data, so we need to ensure that we are running - * the same code in DRAM. - */ - memcpy((void *)MX8MM_ATF_BL33_BASE_ADDR, - __image_start, barebox_pbl_size); - - get_builtin_firmware(imx8mm_bl31_bin, &bl31, &bl31_size); - imx8mm_atf_load_bl31(bl31, bl31_size); + imx8mm_ddr_init(&prt8mm_dram_timing, DRAM_TYPE_LPDDR4); - /* not reached */ + imx8mm_load_and_start_image_via_tfa(); } /* @@ -109,7 +77,7 @@ static __noreturn noinline void prt_prt8mm_start(void) /* * Standard entry we hit once we initialized both DDR and ATF */ - imx8mm_barebox_entry(__dtb_imx8mm_prt8mm_start); + imx8mm_barebox_entry(__dtb_z_imx8mm_prt8mm_start); } ENTRY_FUNCTION(start_prt_prt8mm, r0, r1, r2) diff --git a/arch/arm/boards/protonic-imx8m/lpddr4-timing-prt8mm.c b/arch/arm/boards/protonic-imx8m/lpddr4-timing-prt8mm.c index ea5c0b9154..2c55e7d451 100644 --- a/arch/arm/boards/protonic-imx8m/lpddr4-timing-prt8mm.c +++ b/arch/arm/boards/protonic-imx8m/lpddr4-timing-prt8mm.c @@ -1981,7 +1981,6 @@ static struct dram_fsp_msg lpddr4_dram_fsp_msg[] = { /* lpddr4 timing config params on EVK board */ struct dram_timing_info prt8mm_dram_timing = { - .dram_type = DRAM_TYPE_LPDDR4, .ddrc_cfg = lpddr4_ddrc_cfg, .ddrc_cfg_num = ARRAY_SIZE(lpddr4_ddrc_cfg), .ddrphy_cfg = lpddr4_ddrphy_cfg, diff --git a/arch/arm/configs/imx_v7_defconfig b/arch/arm/configs/imx_v7_defconfig index 8e707b9602..df2304eae9 100644 --- a/arch/arm/configs/imx_v7_defconfig +++ b/arch/arm/configs/imx_v7_defconfig @@ -13,7 +13,6 @@ CONFIG_MACH_FREESCALE_MX53_VMX53=y CONFIG_MACH_TX53=y CONFIG_MACH_PHYTEC_SOM_IMX6=y CONFIG_MACH_PROTONIC_IMX6=y -CONFIG_MACH_KAMSTRUP_MX7_CONCENTRATOR=y CONFIG_MACH_KONTRON_SAMX6I=y CONFIG_MACH_DFI_FS700_M60=y CONFIG_MACH_GUF_SANTARO=y @@ -38,7 +37,8 @@ CONFIG_MACH_GW_VENTANA=y CONFIG_MACH_CM_FX6=y CONFIG_MACH_ADVANTECH_ROM_742X=y CONFIG_MACH_WARP7=y -CONFIG_MACH_WEBASTO_CCBV2=y +CONFIG_MACH_AC_SXB=y +CONFIG_MACH_MEERKAT96=y CONFIG_MACH_VF610_TWR=y CONFIG_MACH_ZII_RDU1=y CONFIG_MACH_ZII_RDU2=y @@ -46,9 +46,12 @@ CONFIG_MACH_ZII_VF610_DEV=y CONFIG_MACH_ZII_IMX7D_DEV=y CONFIG_MACH_PHYTEC_PHYCORE_IMX7=y CONFIG_MACH_FREESCALE_MX7_SABRESD=y +CONFIG_MACH_KAMSTRUP_MX7_CONCENTRATOR=y CONFIG_MACH_NXP_IMX6ULL_EVK=y CONFIG_MACH_GRINN_LITEBOARD=y CONFIG_MACH_DIGI_CCIMX6ULSBCPRO=y +CONFIG_MACH_WEBASTO_CCBV2=y +CONFIG_MACH_SKOV_IMX6=y CONFIG_IMX_IIM_FUSE_BLOW=y CONFIG_THUMB2_BAREBOX=y CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y @@ -87,6 +90,7 @@ CONFIG_CMD_MMC_EXTCSD=y CONFIG_CMD_GO=y CONFIG_CMD_RESET=y CONFIG_CMD_UIMAGE=y +CONFIG_CMD_BOOTCHOOSER=y CONFIG_CMD_PARTITION=y CONFIG_CMD_UBIFORMAT=y CONFIG_CMD_EXPORT=y @@ -139,7 +143,6 @@ CONFIG_CMD_OF_OVERLAY=y CONFIG_CMD_OFTREE=y CONFIG_CMD_TIME=y CONFIG_CMD_STATE=y -CONFIG_CMD_BOOTCHOOSER=y CONFIG_NET=y CONFIG_NET_NETCONSOLE=y CONFIG_OF_BAREBOX_DRIVERS=y @@ -198,9 +201,9 @@ CONFIG_WATCHDOG=y CONFIG_WATCHDOG_IMX=y CONFIG_PWM=y CONFIG_PWM_IMX=y -CONFIG_IMX_OCOTP_WRITE=y CONFIG_MXS_APBH_DMA=y CONFIG_GPIO_STMPE=y +CONFIG_IMX_OCOTP_WRITE=y CONFIG_REGULATOR=y CONFIG_REGULATOR_FIXED=y CONFIG_GENERIC_PHY=y diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 980a2487a0..4e935a7632 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -26,6 +26,7 @@ lwl-$(CONFIG_MACH_CCMX53) += imx53-ccxmx53.dtb.o lwl-$(CONFIG_MACH_DIGI_CCIMX6ULSBCPRO) += imx6ul-ccimx6ulsbcpro.dtb.o lwl-$(CONFIG_MACH_FREESCALE_MX53_VMX53) += imx53-voipac-bsb.dtb.o lwl-$(CONFIG_MACH_FREESCALE_MX7_SABRESD) += imx7d-sdb.dtb.o +lwl-$(CONFIG_MACH_MEERKAT96) += imx7d-meerkat96.dtb.o lwl-$(CONFIG_MACH_GK802) += imx6q-gk802.dtb.o lwl-$(CONFIG_MACH_GLOBALSCALE_GURUPLUG) += kirkwood-guruplug-server-plus-bb.dtb.o lwl-$(CONFIG_MACH_GLOBALSCALE_MIRABOX) += armada-370-mirabox-bb.dtb.o @@ -140,7 +141,7 @@ lwl-$(CONFIG_MACH_TECHNEXION_WANDBOARD) += imx6q-wandboard.dtb.o imx6dl-wandboar lwl-$(CONFIG_MACH_TECHNEXION_PICO_HOBBIT) += imx6ul-pico-hobbit.dtb.o lwl-$(CONFIG_MACH_NXP_IMX6ULL_EVK) += imx6ull-14x14-evk.dtb.o lwl-$(CONFIG_MACH_NXP_IMX8MM_EVK) += imx8mm-evk.dtb.o -lwl-$(CONFIG_MACH_NXP_IMX8MN_EVK) += imx8mn-evk.dtb.o +lwl-$(CONFIG_MACH_NXP_IMX8MN_EVK) += imx8mn-evk.dtb.o imx8mn-ddr4-evk.dtb.o lwl-$(CONFIG_MACH_NXP_IMX8MP_EVK) += imx8mp-evk.dtb.o lwl-$(CONFIG_MACH_NXP_IMX8MQ_EVK) += imx8mq-evk.dtb.o lwl-$(CONFIG_MACH_TORADEX_COLIBRI_T20) += tegra20-colibri-iris.dtb.o diff --git a/arch/arm/dts/imx7d-meerkat96.dts b/arch/arm/dts/imx7d-meerkat96.dts new file mode 100644 index 0000000000..f9d18f355b --- /dev/null +++ b/arch/arm/dts/imx7d-meerkat96.dts @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0+ OR MIT +#include <arm/imx7d-meerkat96.dts> + +/ { + chosen { + environment { + compatible = "barebox,environment"; + device-path = &bareboxenv; + }; + }; +}; + +&usdhc1 { + #address-cells = <1>; + #size-cells = <1>; + + barebox@0 { + label = "barebox"; + reg = <0x0 0x180000>; + }; + + bareboxenv: bareboxenv@180000 { + label = "bareboxenv"; + reg = <0x180000 0x80000>; + }; +}; + +/* FIXME: barebox serial is broken when barebox applies requested reparenting */ +&uart1 { + /delete-property/ assigned-clocks; + /delete-property/ assigned-clock-parents; +}; + +&uart3 { + /delete-property/ assigned-clocks; + /delete-property/ assigned-clock-parents; +}; + +&uart6 { + /delete-property/ assigned-clocks; + /delete-property/ assigned-clock-parents; +}; diff --git a/arch/arm/dts/imx8mn-ddr4-evk.dts b/arch/arm/dts/imx8mn-ddr4-evk.dts new file mode 100644 index 0000000000..6ebb4d15e4 --- /dev/null +++ b/arch/arm/dts/imx8mn-ddr4-evk.dts @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) + +/dts-v1/; + +#include <arm64/freescale/imx8mn-ddr4-evk.dts> +#include "imx8mn-evk.dtsi" diff --git a/arch/arm/dts/imx8mn-evk.dts b/arch/arm/dts/imx8mn-evk.dts index 23f80f8686..cbb8b8874c 100644 --- a/arch/arm/dts/imx8mn-evk.dts +++ b/arch/arm/dts/imx8mn-evk.dts @@ -1,12 +1,9 @@ // SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright 2017 NXP - * Copyright (C) 2017 Pengutronix, Lucas Stach <kernel@pengutronix.de> - */ /dts-v1/; #include <arm64/freescale/imx8mn-evk.dts> +#include "imx8mn-evk.dtsi" #include "imx8mn.dtsi" / { @@ -90,4 +87,3 @@ #size-cells = <1>; }; }; - diff --git a/arch/arm/dts/imx8mn-evk.dtsi b/arch/arm/dts/imx8mn-evk.dtsi new file mode 100644 index 0000000000..ceeb5f8b93 --- /dev/null +++ b/arch/arm/dts/imx8mn-evk.dtsi @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright 2017 NXP + * Copyright (C) 2017 Pengutronix, Lucas Stach <kernel@pengutronix.de> + */ + +/ { + chosen { + environment-sd { + compatible = "barebox,environment"; + device-path = &usdhc2, "partname:barebox-environment"; + status = "disabled"; + }; + environment-emmc { + compatible = "barebox,environment"; + device-path = &usdhc3, "partname:barebox-environment"; + status = "disabled"; + }; + }; +}; + +&usdhc2 { + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "barebox"; + reg = <0x0 0xe0000>; + }; + + partition@e0000 { + label = "barebox-environment"; + reg = <0xe0000 0x20000>; + }; +}; + +&usdhc3 { + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "barebox"; + reg = <0x0 0xe0000>; + }; + + partition@e0000 { + label = "barebox-environment"; + reg = <0xe0000 0x20000>; + }; +}; + +&ocotp { + barebox,provide-mac-address = <&fec1 0x640>; +}; + +&iomuxc { + pinctrl_flexspi0: flexspi0grp { + fsl,pins = < + MX8MN_IOMUXC_NAND_ALE_QSPI_A_SCLK 0x1c4 + MX8MN_IOMUXC_NAND_CE0_B_QSPI_A_SS0_B 0x84 + MX8MN_IOMUXC_NAND_DATA00_QSPI_A_DATA0 0x84 + MX8MN_IOMUXC_NAND_DATA01_QSPI_A_DATA1 0x84 + MX8MN_IOMUXC_NAND_DATA02_QSPI_A_DATA2 0x84 + MX8MN_IOMUXC_NAND_DATA03_QSPI_A_DATA3 0x84 + >; + }; +}; + +&flexspi { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexspi0>; + + system_flash: flash@0 { + reg = <0>; + compatible = "jedec,spi-nor"; + spi-max-frequency = <80000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + #address-cells = <1>; + #size-cells = <1>; + }; +}; diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 9ff549ac83..ca60f85c28 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -183,6 +183,7 @@ config ARCH_IMX8M select HW_HAS_PCI select IMX8M_DRAM select PBL_VERIFY_PIGGY if HABV4 + select ARM_USE_COMPRESSED_DTB config ARCH_IMX8MM select ARCH_IMX8M @@ -485,6 +486,11 @@ config MACH_AC_SXB select MCI_IMX_ESDHC_PBL select ARM_USE_COMPRESSED_DTB +config MACH_MEERKAT96 + bool "96Boards: i.MX7 Meerkat96" + select ARCH_IMX7 + select ARM_USE_COMPRESSED_DTB + config MACH_VF610_TWR bool "Freescale VF610 Tower Board" select ARCH_VF610 @@ -515,7 +521,6 @@ config MACH_ZII_IMX8MQ_DEV select ARM_SMCCC select MCI_IMX_ESDHC_PBL select MACH_ZII_COMMON - select ARM_USE_COMPRESSED_DTB config MACH_ZII_VF610_DEV bool "ZII VF610 Dev Family" @@ -575,7 +580,6 @@ config MACH_NXP_IMX8MN_EVK select MCI_IMX_ESDHC_PBL select IMX8M_DRAM select I2C_IMX_EARLY - select ARM_USE_COMPRESSED_DTB config MACH_NXP_IMX8MP_EVK bool "NXP i.MX8MP EVK Board" @@ -586,7 +590,6 @@ config MACH_NXP_IMX8MP_EVK select MCI_IMX_ESDHC_PBL select IMX8M_DRAM select I2C_IMX_EARLY - select USB_GADGET_DRIVER_ARC_PBL config MACH_NXP_IMX8MQ_EVK bool "NXP i.MX8MQ EVK Board" diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index 2cafcd77e0..fa5133a229 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -18,7 +18,7 @@ lwl-$(CONFIG_ARCH_IMX6) += imx6-mmdc.o obj-$(CONFIG_ARCH_IMX7) += imx7.o obj-$(CONFIG_ARCH_VF610) += vf610.o obj-pbl-$(CONFIG_ARCH_IMX8M) += imx8m.o -lwl-$(CONFIG_ARCH_IMX8M) += atf.o +lwl-$(CONFIG_ARCH_IMX8M) += atf.o romapi.o obj-$(CONFIG_IMX_IIM) += iim.o obj-$(CONFIG_NAND_IMX) += nand.o lwl-$(CONFIG_ARCH_IMX_EXTERNAL_BOOT_NAND) += external-nand-boot.o diff --git a/arch/arm/mach-imx/atf.c b/arch/arm/mach-imx/atf.c index 9ab9ddd203..a4c6582830 100644 --- a/arch/arm/mach-imx/atf.c +++ b/arch/arm/mach-imx/atf.c @@ -1,7 +1,13 @@ // SPDX-License-Identifier: GPL-2.0-only +#include <asm/sections.h> #include <common.h> +#include <firmware.h> #include <mach/atf.h> +#include <mach/generic.h> +#include <mach/xload.h> +#include <mach/romapi.h> +#include <soc/fsl/fsl_udc.h> /** * imx8m_atf_load_bl31 - Load ATF BL31 blob and transfer control to it @@ -63,3 +69,141 @@ void imx8mq_atf_load_bl31(const void *fw, size_t fw_size) { imx8m_atf_load_bl31(fw, fw_size, (void *)MX8MQ_ATF_BL31_BASE_ADDR); } + +void imx8mm_load_and_start_image_via_tfa(void) +{ + size_t bl31_size; + const u8 *bl31; + enum bootsource src; + int instance; + void *bl33 = (void *)MX8M_ATF_BL33_BASE_ADDR; + + imx8mm_get_boot_source(&src, &instance); + switch (src) { + case BOOTSOURCE_MMC: + imx8m_esdhc_load_image(instance, false); + break; + case BOOTSOURCE_SERIAL: + /* + * Traditionally imx-usb-loader sends the PBL twice. The first + * PBL is loaded to OCRAM and executed. Then the full barebox + * image including the PBL is sent again and received here. We + * might change that in the future in imx-usb-loader so that the + * PBL is sent only once and we only receive the rest of the + * image here. To prepare that step we check if we get a full + * barebox image or piggydata only. When it's piggydata only move + * it to the place where it would be if it would have been a + * full image. + */ + imx8mm_barebox_load_usb(bl33); + + if (!strcmp("barebox", bl33 + 0x20)) { + /* Found the barebox marker, so this is a PBL + piggydata */ + pr_debug("received PBL + piggydata\n"); + } else { + /* no barebox marker, so this is piggydata only */ + pr_debug("received piggydata\n"); + memmove(bl33 + barebox_pbl_size, bl33, + barebox_image_size - barebox_pbl_size); + } + + break; + default: + printf("Unhandled bootsource BOOTSOURCE_%d\n", src); + hang(); + } + + /* + * On completion the TF-A will jump to MX8M_ATF_BL33_BASE_ADDR + * in EL2. Copy the image there, but replace the PBL part of + * that image with ourselves. On a high assurance boot only the + * currently running code is validated and contains the checksum + * for the piggy data, so we need to ensure that we are running + * the same code in DRAM. + */ + memcpy(bl33, __image_start, barebox_pbl_size); + + get_builtin_firmware(imx8mm_bl31_bin, &bl31, &bl31_size); + + imx8mm_atf_load_bl31(bl31, bl31_size); + + /* not reached */ +} + +void imx8mp_load_and_start_image_via_tfa(void) +{ + size_t bl31_size; + const u8 *bl31; + enum bootsource src; + int instance; + + imx8mp_get_boot_source(&src, &instance); + switch (src) { + case BOOTSOURCE_MMC: + imx8mp_esdhc_load_image(instance, false); + break; + case BOOTSOURCE_SERIAL: + imx8mp_bootrom_load_image(); + break; + default: + printf("Unhandled bootsource BOOTSOURCE_%d\n", src); + hang(); + } + + + /* + * On completion the TF-A will jump to MX8M_ATF_BL33_BASE_ADDR + * in EL2. Copy the image there, but replace the PBL part of + * that image with ourselves. On a high assurance boot only the + * currently running code is validated and contains the checksum + * for the piggy data, so we need to ensure that we are running + * the same code in DRAM. + */ + memcpy((void *)MX8M_ATF_BL33_BASE_ADDR, + __image_start, barebox_pbl_size); + + get_builtin_firmware(imx8mp_bl31_bin, &bl31, &bl31_size); + + imx8mp_atf_load_bl31(bl31, bl31_size); + + /* not reached */ +} + +void imx8mn_load_and_start_image_via_tfa(void) +{ + size_t bl31_size; + const u8 *bl31; + enum bootsource src; + int instance; + + imx8mn_get_boot_source(&src, &instance); + switch (src) { + case BOOTSOURCE_MMC: + imx8mn_esdhc_load_image(instance, false); + break; + case BOOTSOURCE_SERIAL: + imx8mn_bootrom_load_image(); + break; + default: + printf("Unhandled bootsource BOOTSOURCE_%d\n", src); + hang(); + } + + + /* + * On completion the TF-A will jump to MX8M_ATF_BL33_BASE_ADDR + * in EL2. Copy the image there, but replace the PBL part of + * that image with ourselves. On a high assurance boot only the + * currently running code is validated and contains the checksum + * for the piggy data, so we need to ensure that we are running + * the same code in DRAM. + */ + memcpy((void *)MX8M_ATF_BL33_BASE_ADDR, + __image_start, barebox_pbl_size); + + get_builtin_firmware(imx8mn_bl31_bin, &bl31, &bl31_size); + + imx8mn_atf_load_bl31(bl31, bl31_size); + + /* not reached */ +} diff --git a/arch/arm/mach-imx/include/mach/atf.h b/arch/arm/mach-imx/include/mach/atf.h index 09396f4646..bc400ddbad 100644 --- a/arch/arm/mach-imx/include/mach/atf.h +++ b/arch/arm/mach-imx/include/mach/atf.h @@ -10,7 +10,7 @@ #define MX8MM_ATF_BL31_BASE_ADDR 0x00920000 #define MX8MN_ATF_BL31_BASE_ADDR 0x00960000 -#define MX8MP_ATF_BL31_BASE_ADDR 0x00960000 +#define MX8MP_ATF_BL31_BASE_ADDR 0x00970000 #define MX8MQ_ATF_BL31_BASE_ADDR 0x00910000 #define MX8M_ATF_BL33_BASE_ADDR 0x40200000 #define MX8MM_ATF_BL33_BASE_ADDR MX8M_ATF_BL33_BASE_ADDR diff --git a/arch/arm/mach-imx/include/mach/romapi.h b/arch/arm/mach-imx/include/mach/romapi.h new file mode 100644 index 0000000000..8022fc411e --- /dev/null +++ b/arch/arm/mach-imx/include/mach/romapi.h @@ -0,0 +1,37 @@ +#ifndef __MACH_IMX_ROMAPI_H +#define __MACH_IMX_ROMAPI_H + +struct rom_api { + u16 ver; + u16 tag; + u32 reserved1; + u32 (*download_image)(u8 *dest, u32 offset, u32 size, u32 xor); + u32 (*query_boot_infor)(u32 info_type, u32 *info, u32 xor); +}; + +enum boot_dev_type_e { + BT_DEV_TYPE_SD = 1, + BT_DEV_TYPE_MMC = 2, + BT_DEV_TYPE_NAND = 3, + BT_DEV_TYPE_FLEXSPINOR = 4, + BT_DEV_TYPE_SPI_NOR = 6, + + BT_DEV_TYPE_USB = 0xE, + BT_DEV_TYPE_MEM_DEV = 0xF, + + BT_DEV_TYPE_INVALID = 0xFF +}; + +#define QUERY_ROM_VER 1 +#define QUERY_BT_DEV 2 +#define QUERY_PAGE_SZ 3 +#define QUERY_IVT_OFF 4 +#define QUERY_BT_STAGE 5 +#define QUERY_IMG_OFF 6 + +#define ROM_API_OKAY 0xF0 + +int imx8mp_bootrom_load_image(void); +int imx8mn_bootrom_load_image(void); + +#endif /* __MACH_IMX_ROMAPI_H */ diff --git a/arch/arm/mach-imx/include/mach/xload.h b/arch/arm/mach-imx/include/mach/xload.h index 03ec23ebbd..3090c9c83b 100644 --- a/arch/arm/mach-imx/include/mach/xload.h +++ b/arch/arm/mach-imx/include/mach/xload.h @@ -13,6 +13,10 @@ int imx8m_esdhc_load_image(int instance, bool start); int imx8mn_esdhc_load_image(int instance, bool start); int imx8mp_esdhc_load_image(int instance, bool start); +void imx8mm_load_and_start_image_via_tfa(void); +void imx8mn_load_and_start_image_via_tfa(void); +void imx8mp_load_and_start_image_via_tfa(void); + int imx_image_size(void); int piggydata_size(void); diff --git a/arch/arm/mach-imx/romapi.c b/arch/arm/mach-imx/romapi.c new file mode 100644 index 0000000000..f7d421d737 --- /dev/null +++ b/arch/arm/mach-imx/romapi.c @@ -0,0 +1,44 @@ +#include <common.h> +#include <asm/sections.h> +#include <mach/romapi.h> +#include <mach/atf.h> + +static int imx8m_bootrom_load(struct rom_api *rom_api, void *adr, size_t size) +{ + while (size) { + size_t chunksize = min(size, (size_t)1024); + int ret; + + ret = rom_api->download_image(adr, 0, chunksize, + (uintptr_t)adr ^ chunksize); + if (ret != ROM_API_OKAY) { + pr_err("Failed to load piggy data (ret = %x)\n", ret); + return -EIO; + } + + adr += chunksize; + size -= chunksize; + } + + return 0; +} + +/* read piggydata via a bootrom callback and place it behind our copy in SDRAM */ +static int imx8m_bootrom_load_image(struct rom_api *rom_api) +{ + return imx8m_bootrom_load(rom_api, + (void *)MX8M_ATF_BL33_BASE_ADDR + barebox_pbl_size, + __piggydata_end - __piggydata_start); +} + +int imx8mp_bootrom_load_image(void) +{ + struct rom_api *rom_api = (void *)0x980; + + return imx8m_bootrom_load_image(rom_api); +} + +int imx8mn_bootrom_load_image(void) +{ + return imx8mp_bootrom_load_image(); +} diff --git a/common/ddr_spd.c b/common/ddr_spd.c index 7089923afb..52773178e7 100644 --- a/common/ddr_spd.c +++ b/common/ddr_spd.c @@ -6,6 +6,7 @@ #include <common.h> #include <crc.h> #include <ddr_spd.h> +#include <pbl/i2c.h> /* used for ddr1 and ddr2 spd */ static int spd_check(const u8 *buf, u8 spd_rev, u8 spd_cksum) @@ -430,9 +431,7 @@ void ddr_spd_print(uint8_t *record) #define SPD_SPA0_ADDRESS 0x36 #define SPD_SPA1_ADDRESS 0x37 -static int select_page(void *ctx, - int (*xfer)(void *ctx, struct i2c_msg *msgs, int num), - uint8_t addr) +static int select_page(struct pbl_i2c *i2c, uint8_t addr) { struct i2c_msg msg = { .addr = addr, @@ -440,15 +439,14 @@ static int select_page(void *ctx, }; int ret; - ret = xfer(ctx, &msg, 1); + ret = pbl_i2c_xfer(i2c, &msg, 1); if (ret < 0) return ret; return 0; } -static int read_buf(void *ctx, - int (*xfer)(void *ctx, struct i2c_msg *msgs, int num), +static int read_buf(struct pbl_i2c *i2c, uint8_t addr, int page, void *buf) { uint8_t pos = 0; @@ -466,11 +464,11 @@ static int read_buf(void *ctx, } }; - ret = select_page(ctx, xfer, page); + ret = select_page(i2c, page); if (ret < 0) return ret; - ret = xfer(ctx, msg, 2); + ret = pbl_i2c_xfer(i2c, msg, 2); if (ret < 0) return ret; @@ -479,8 +477,7 @@ static int read_buf(void *ctx, /** * spd_read_eeprom - Read contents of a SPD EEPROM - * @ctx: Context pointer for the xfer function - * @xfer: I2C message transfer function + * @i2c: I2C controller handle * @addr: I2C bus address for the EEPROM * @buf: buffer to read the SPD data to * @@ -489,19 +486,18 @@ static int read_buf(void *ctx, * have a size of 512 bytes. Returns 0 for success or a negative error code * otherwise. */ -int spd_read_eeprom(void *ctx, - int (*xfer)(void *ctx, struct i2c_msg *msgs, int num), +int spd_read_eeprom(struct pbl_i2c *i2c, uint8_t addr, void *buf) { unsigned char *buf8 = buf; int ret; - ret = read_buf(ctx, xfer, addr, SPD_SPA0_ADDRESS, buf); + ret = read_buf(i2c, addr, SPD_SPA0_ADDRESS, buf); if (ret < 0) return ret; if (buf8[2] == SPD_MEMTYPE_DDR4) { - ret = read_buf(ctx, xfer, addr, SPD_SPA1_ADDRESS, buf + 256); + ret = read_buf(i2c, addr, SPD_SPA1_ADDRESS, buf + 256); if (ret < 0) return ret; } diff --git a/drivers/ddr/imx8m/ddr_init.c b/drivers/ddr/imx8m/ddr_init.c index 9a4b4e2ca8..18969ddb53 100644 --- a/drivers/ddr/imx8m/ddr_init.c +++ b/drivers/ddr/imx8m/ddr_init.c @@ -49,17 +49,18 @@ static void ddr_cfg_umctl2(struct dram_cfg_param *ddrc_cfg, int num) */ #define IMX8M_SAVED_DRAM_TIMING_BASE 0x180000 -static int imx8m_ddr_init(struct dram_timing_info *dram_timing, - enum ddrc_type type) +int imx8m_ddr_init(struct dram_timing_info *dram_timing, + unsigned type) { unsigned long src_ddrc_rcr = MX8M_SRC_DDRC_RCR_ADDR; unsigned int tmp, initial_drate, target_freq; + enum ddrc_type ddrc_type = get_ddrc_type(type); int ret; pr_debug("start DRAM init\n"); /* Step1: Follow the power up procedure */ - switch (type) { + switch (ddrc_type) { case DDRC_TYPE_MQ: reg32_write(src_ddrc_rcr + 0x04, 0x8f00000f); reg32_write(src_ddrc_rcr, 0x8f00000f); @@ -81,7 +82,7 @@ static int imx8m_ddr_init(struct dram_timing_info *dram_timing, initial_drate = dram_timing->fsp_msg[0].drate; /* default to the frequency point 0 clock */ - ddrphy_init_set_dfi_clk(initial_drate, type); + ddrphy_init_set_dfi_clk(initial_drate, ddrc_type); /* D-aasert the presetn */ reg32_write(src_ddrc_rcr, 0x8F000006); @@ -107,7 +108,7 @@ static int imx8m_ddr_init(struct dram_timing_info *dram_timing, /* if ddr type is LPDDR4, do it */ tmp = reg32_read(DDRC_MSTR(0)); - if (tmp & (0x1 << 5) && type != DDRC_TYPE_MN) + if (tmp & (0x1 << 5) && ddrc_type != DDRC_TYPE_MN) reg32_write(DDRC_DDR_SS_GPR0, 0x01); /* LPDDR4 mode */ /* determine the initial boot frequency */ @@ -154,7 +155,7 @@ static int imx8m_ddr_init(struct dram_timing_info *dram_timing, reg32_write(DDRC_SWCTL(0), 0x00000000); /* Apply rank-to-rank workaround */ - update_umctl2_rank_space_setting(dram_timing->fsp_msg_num - 1, type); + update_umctl2_rank_space_setting(dram_timing->fsp_msg_num - 1, ddrc_type); /* Step16: Set DFIMISC.dfi_init_start to 1 */ setbits_le32(DDRC_DFIMISC(0), (0x1 << 5)); @@ -210,23 +211,3 @@ static int imx8m_ddr_init(struct dram_timing_info *dram_timing, return 0; } - -int imx8mm_ddr_init(struct dram_timing_info *dram_timing) -{ - return imx8m_ddr_init(dram_timing, DDRC_TYPE_MM); -} - -int imx8mn_ddr_init(struct dram_timing_info *dram_timing) -{ - return imx8m_ddr_init(dram_timing, DDRC_TYPE_MN); -} - -int imx8mq_ddr_init(struct dram_timing_info *dram_timing) -{ - return imx8m_ddr_init(dram_timing, DDRC_TYPE_MQ); -} - -int imx8mp_ddr_init(struct dram_timing_info *dram_timing) -{ - return imx8m_ddr_init(dram_timing, DDRC_TYPE_MP); -} diff --git a/drivers/ddr/imx8m/ddrphy_train.c b/drivers/ddr/imx8m/ddrphy_train.c index 9dc20a4762..e9d35afdfb 100644 --- a/drivers/ddr/imx8m/ddrphy_train.c +++ b/drivers/ddr/imx8m/ddrphy_train.c @@ -11,6 +11,48 @@ #include <firmware.h> #include <mach/imx8m-regs.h> +static const u16 *lpddr4_imem_1d; +static size_t lpddr4_imem_1d_size; +static const u16 *lpddr4_dmem_1d; +static size_t lpddr4_dmem_1d_size; +static const u16 *lpddr4_imem_2d; +static size_t lpddr4_imem_2d_size; +static const u16 *lpddr4_dmem_2d; +static size_t lpddr4_dmem_2d_size; + +void ddr_get_firmware_lpddr4(void) +{ + get_builtin_firmware(lpddr4_pmu_train_1d_imem_bin, &lpddr4_imem_1d, + &lpddr4_imem_1d_size); + get_builtin_firmware(lpddr4_pmu_train_1d_dmem_bin, &lpddr4_dmem_1d, + &lpddr4_dmem_1d_size); + get_builtin_firmware(lpddr4_pmu_train_2d_imem_bin, &lpddr4_imem_2d, + &lpddr4_imem_2d_size); + get_builtin_firmware(lpddr4_pmu_train_2d_dmem_bin, &lpddr4_dmem_2d, + &lpddr4_dmem_2d_size); +} + +static const u16 *ddr4_imem_1d; +static size_t ddr4_imem_1d_size; +static const u16 *ddr4_dmem_1d; +static size_t ddr4_dmem_1d_size; +static const u16 *ddr4_imem_2d; +static size_t ddr4_imem_2d_size; +static const u16 *ddr4_dmem_2d; +static size_t ddr4_dmem_2d_size; + +void ddr_get_firmware_ddr(void) +{ + get_builtin_firmware(ddr4_imem_1d_bin, &ddr4_imem_1d, + &ddr4_imem_1d_size); + get_builtin_firmware(ddr4_dmem_1d_bin, &ddr4_dmem_1d, + &ddr4_dmem_1d_size); + get_builtin_firmware(ddr4_imem_2d_bin, &ddr4_imem_2d, + &ddr4_imem_2d_size); + get_builtin_firmware(ddr4_dmem_2d_bin, &ddr4_dmem_2d, + &ddr4_dmem_2d_size); +} + void ddr_load_train_code(enum dram_type dram_type, enum fw_type fw_type) { const u16 *imem, *dmem; @@ -18,19 +60,27 @@ void ddr_load_train_code(enum dram_type dram_type, enum fw_type fw_type) if (dram_is_lpddr4(dram_type)) { if (fw_type == FW_1D_IMAGE) { - get_builtin_firmware(lpddr4_pmu_train_1d_imem_bin, &imem, &isize); - get_builtin_firmware(lpddr4_pmu_train_1d_dmem_bin, &dmem, &dsize); + imem = lpddr4_imem_1d; + isize = lpddr4_imem_1d_size; + dmem = lpddr4_dmem_1d; + dsize = lpddr4_dmem_1d_size; } else { - get_builtin_firmware(lpddr4_pmu_train_2d_imem_bin, &imem, &isize); - get_builtin_firmware(lpddr4_pmu_train_2d_dmem_bin, &dmem, &dsize); + imem = lpddr4_imem_2d; + isize = lpddr4_imem_2d_size; + dmem = lpddr4_dmem_2d; + dsize = lpddr4_dmem_2d_size; } } else if (dram_is_ddr4(dram_type)) { if (fw_type == FW_1D_IMAGE) { - get_builtin_firmware(ddr4_imem_1d_bin, &imem, &isize); - get_builtin_firmware(ddr4_dmem_1d_bin, &dmem, &dsize); + imem = ddr4_imem_1d; + isize = ddr4_imem_1d_size; + dmem = ddr4_dmem_1d; + dsize = ddr4_dmem_1d_size; } else { - get_builtin_firmware(ddr4_imem_2d_bin, &imem, &isize); - get_builtin_firmware(ddr4_dmem_2d_bin, &dmem, &dsize); + imem = ddr4_imem_2d; + isize = ddr4_imem_2d_size; + dmem = ddr4_dmem_2d; + dsize = ddr4_dmem_2d_size; } } else { panic("No matching DDR PHY firmware found"); @@ -43,8 +93,10 @@ void ddr_load_train_code(enum dram_type dram_type, enum fw_type fw_type) DDRC_PHY_DMEM, dmem, dsize); } -int ddr_cfg_phy(struct dram_timing_info *dram_timing, enum ddrc_type type) +int ddr_cfg_phy(struct dram_timing_info *dram_timing, unsigned type) { + enum ddrc_type ddrc_type = get_ddrc_type(type); + enum dram_type dram_type = get_dram_type(type); struct dram_cfg_param *dram_cfg; struct dram_fsp_msg *fsp_msg; unsigned int num; @@ -66,11 +118,11 @@ int ddr_cfg_phy(struct dram_timing_info *dram_timing, enum ddrc_type type) for (i = 0; i < dram_timing->fsp_msg_num; i++) { pr_debug("DRAM PHY training for %dMTS\n", fsp_msg->drate); /* set dram PHY input clocks to desired frequency */ - ddrphy_init_set_dfi_clk(fsp_msg->drate, type); + ddrphy_init_set_dfi_clk(fsp_msg->drate, ddrc_type); /* load the dram training firmware image */ dwc_ddrphy_apb_wr(0xd0000, 0x0); - ddr_load_train_code(dram_timing->dram_type, fsp_msg->fw_type); + ddr_load_train_code(dram_type, fsp_msg->fw_type); /* load the frequency set point message block parameter */ dram_cfg = fsp_msg->fsp_cfg; diff --git a/drivers/i2c/busses/i2c-imx-early.c b/drivers/i2c/busses/i2c-imx-early.c index a79d7bd88c..4e0f7e517d 100644 --- a/drivers/i2c/busses/i2c-imx-early.c +++ b/drivers/i2c/busses/i2c-imx-early.c @@ -9,11 +9,12 @@ */ #include <common.h> #include <i2c/i2c.h> -#include <i2c/i2c-early.h> +#include <pbl/i2c.h> #include "i2c-imx.h" struct fsl_i2c { + struct pbl_i2c i2c; void __iomem *regs; unsigned int i2cr_ien_opcode; unsigned int i2sr_clr_opcode; @@ -170,7 +171,7 @@ static int i2c_fsl_write(struct fsl_i2c *fsl_i2c, struct i2c_msg *msg) /* write data */ for (i = 0; i < msg->len; i++) { ret = i2c_fsl_send(fsl_i2c, msg->buf[i]); - if (ret) + if (ret) return ret; } @@ -229,9 +230,9 @@ static int i2c_fsl_read(struct fsl_i2c *fsl_i2c, struct i2c_msg *msg) * If successful returns the number of messages transferred, otherwise a negative * error code is returned. */ -int i2c_fsl_xfer(void *ctx, struct i2c_msg *msgs, int num) +static int i2c_fsl_xfer(struct pbl_i2c *i2c, struct i2c_msg *msgs, int num) { - struct fsl_i2c *fsl_i2c = ctx; + struct fsl_i2c *fsl_i2c = container_of(i2c, struct fsl_i2c, i2c); unsigned int i, temp; int ret; @@ -288,7 +289,7 @@ static struct fsl_i2c fsl_i2c; * This function returns a context pointer suitable to transfer I2C messages * using i2c_fsl_xfer. */ -void *ls1046_i2c_init(void __iomem *regs) +struct pbl_i2c *ls1046_i2c_init(void __iomem *regs) { fsl_i2c.regs = regs; fsl_i2c.regshift = 0; @@ -297,10 +298,12 @@ void *ls1046_i2c_init(void __iomem *regs) /* Divider for ~100kHz when coming from the ROM */ fsl_i2c.ifdr = 0x3e; - return &fsl_i2c; + fsl_i2c.i2c.xfer = i2c_fsl_xfer; + + return &fsl_i2c.i2c; } -void *imx8m_i2c_early_init(void __iomem *regs) +struct pbl_i2c *imx8m_i2c_early_init(void __iomem *regs) { fsl_i2c.regs = regs; fsl_i2c.regshift = 2; @@ -309,5 +312,7 @@ void *imx8m_i2c_early_init(void __iomem *regs) /* Divider for ~100kHz when coming from the ROM */ fsl_i2c.ifdr = 0x0f; - return &fsl_i2c; + fsl_i2c.i2c.xfer = i2c_fsl_xfer; + + return &fsl_i2c.i2c; } diff --git a/drivers/mci/imx-esdhc-pbl.c b/drivers/mci/imx-esdhc-pbl.c index 5a76e7a663..c81eba5b9d 100644 --- a/drivers/mci/imx-esdhc-pbl.c +++ b/drivers/mci/imx-esdhc-pbl.c @@ -44,7 +44,7 @@ static int esdhc_send_ext_csd(struct fsl_esdhc_host *host) return esdhc_send_cmd(host, &cmd, &data); } -static bool esdhc_bootpart_active(struct fsl_esdhc_host *host) +static bool __maybe_unused esdhc_bootpart_active(struct fsl_esdhc_host *host) { unsigned bootpart; diff --git a/drivers/net/fec_imx.c b/drivers/net/fec_imx.c index 0c2d600d12..673555a48a 100644 --- a/drivers/net/fec_imx.c +++ b/drivers/net/fec_imx.c @@ -320,6 +320,10 @@ static int fec_init(struct eth_device *dev) /* size of each buffer */ writel(FEC_MAX_PKT_SIZE, fec->regs + FEC_EMRBR); + /* set rx and tx buffer descriptor base address */ + writel(virt_to_phys(fec->tbd_base), fec->regs + FEC_ETDSR); + writel(virt_to_phys(fec->rbd_base), fec->regs + FEC_ERDSR); + return 0; } @@ -359,6 +363,8 @@ static int fec_open(struct eth_device *edev) if (fec->phy_init) fec->phy_init(edev->phydev); + fec_init(edev); + /* * Initialize RxBD/TxBD rings */ @@ -839,9 +845,6 @@ static int fec_probe(struct device_d *dev) base += FEC_RBD_NUM * sizeof(struct buffer_descriptor); fec->tbd_base = base; - writel(virt_to_phys(fec->tbd_base), fec->regs + FEC_ETDSR); - writel(virt_to_phys(fec->rbd_base), fec->regs + FEC_ERDSR); - ret = fec_alloc_receive_packets(fec, FEC_RBD_NUM, FEC_MAX_PKT_SIZE); if (ret < 0) goto free_xbd; @@ -861,8 +864,6 @@ static int fec_probe(struct device_d *dev) if (ret) goto free_receive_packets; - fec_init(edev); - fec->miibus.read = fec_miibus_read; fec->miibus.write = fec_miibus_write; diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index b298da0000..8a57bd1aa9 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c @@ -220,6 +220,11 @@ static struct phy_provider *of_phy_provider_lookup(struct device_node *node) { struct phy_provider *phy_provider; struct device_node *child; + int ret; + + ret = of_device_ensure_probed(node); + if (ret) + return ERR_PTR(ret); list_for_each_entry(phy_provider, &phy_provider_list, list) { if (phy_provider->dev->device_node == node) @@ -255,10 +260,6 @@ static struct phy *_of_phy_get(struct device_node *np, int index) if (ret) return ERR_PTR(-ENODEV); - ret = of_device_ensure_probed(args.np); - if (ret) - return ERR_PTR(ret); - phy_provider = of_phy_provider_lookup(args.np); if (IS_ERR(phy_provider)) { return ERR_CAST(phy_provider); @@ -316,7 +317,7 @@ struct phy *of_phy_get_by_phandle(struct device_d *dev, const char *phandle, phy_provider = of_phy_provider_lookup(np); if (IS_ERR(phy_provider)) { - return ERR_PTR(-ENODEV); + return ERR_CAST(phy_provider); } return phy_provider->of_xlate(phy_provider->dev, NULL); diff --git a/drivers/usb/imx/chipidea-imx.c b/drivers/usb/imx/chipidea-imx.c index bf8b6f1eb8..f71cf80b7d 100644 --- a/drivers/usb/imx/chipidea-imx.c +++ b/drivers/usb/imx/chipidea-imx.c @@ -260,8 +260,6 @@ static int imx_chipidea_probe(struct device_d *dev) * devices which have only one. */ ci->clk = clk_get(dev, NULL); - if (!IS_ERR(ci->clk)) - clk_enable(ci->clk); /* Device trees are using both "phys" and "fsl,usbphy". Prefer the * more modern former one but fall back to the old one. @@ -302,6 +300,14 @@ static int imx_chipidea_probe(struct device_d *dev) ci->data.drvdata = ci; ci->data.usbphy = ci->usbphy; + /* + * Enable the clock after we ensured that all resources are available. + * This is crucial since the phy can be missing which and so the + * usb-controller <-> usb-phy communication is only partly initialized. + * This can trigger strange system hangs at least on i.MX8M SoCs. + */ + clk_enable(ci->clk); + if ((ci->flags & MXC_EHCI_PORTSC_MASK) == MXC_EHCI_MODE_HSIC) imx_chipidea_port_init(ci); diff --git a/drivers/watchdog/imxwd.c b/drivers/watchdog/imxwd.c index 31ea388c2c..dba92cb46a 100644 --- a/drivers/watchdog/imxwd.c +++ b/drivers/watchdog/imxwd.c @@ -239,18 +239,17 @@ static int imx_wd_probe(struct device_d *dev) priv = xzalloc(sizeof(struct imx_wd)); iores = dev_request_mem_resource(dev, 0); - if (IS_ERR(iores)) { - dev_err(dev, "could not get memory region\n"); - return PTR_ERR(iores); - } + if (IS_ERR(iores)) + return dev_err_probe(dev, PTR_ERR(iores), + "could not get memory region\n"); clk = clk_get(dev, NULL); if (IS_ERR(clk)) - return PTR_ERR(clk); + return dev_err_probe(dev, PTR_ERR(clk), "Failed to get clk\n"); ret = clk_enable(clk); if (ret) - return ret; + return dev_err_probe(dev, ret, "Failed to enable clk\n"); priv->base = IOMEM(iores->start); priv->ops = ops; @@ -272,14 +271,17 @@ static int imx_wd_probe(struct device_d *dev) } ret = watchdog_register(&priv->wd); - if (ret) + if (ret) { + dev_err_probe(dev, ret, "Failed to register watchdog device\n"); goto on_error; + } } if (priv->ops->init) { ret = priv->ops->init(priv); if (ret) { - dev_err(dev, "Failed to init watchdog device %d\n", ret); + dev_err_probe(dev, ret, + "Failed to init watchdog device\n"); goto error_unregister; } } diff --git a/images/Makefile.imx b/images/Makefile.imx index 62549ab758..a19e0ff1c7 100644 --- a/images/Makefile.imx +++ b/images/Makefile.imx @@ -418,6 +418,11 @@ CFG_start_zii_imx7d_dev.pblb.imximg = $(board)/zii-imx7d-dev/flash-header-zii-im FILE_barebox-zii-imx7d-dev.img = start_zii_imx7d_dev.pblb.imximg image-$(CONFIG_MACH_ZII_IMX7D_DEV) += barebox-zii-imx7d-dev.img +pblb-$(CONFIG_MACH_MEERKAT96) += start_imx7d_meerkat96 +CFG_start_imx7d_meerkat96.pblb.imximg = $(board)/meerkat96/flash-header-mx7-meerkat96.imxcfg +FILE_barebox-meerkat96.img = start_imx7d_meerkat96.pblb.imximg +image-$(CONFIG_MACH_MEERKAT96) += barebox-meerkat96.img + pblb-$(CONFIG_MACH_KAMSTRUP_MX7_CONCENTRATOR) += start_kamstrup_mx7_concentrator CFG_start_kamstrup_mx7_concentrator.pblb.imximg = $(board)/kamstrup-mx7-concentrator/flash-header-tqma7d.imxcfg FILE_barebox-kamstrup-mx7-concentrator.img = start_kamstrup_mx7_concentrator.pblb.imximg diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h index 0b2ed5615b..e54123de0e 100644 --- a/include/asm-generic/sections.h +++ b/include/asm-generic/sections.h @@ -11,6 +11,7 @@ extern char _end[]; extern char __image_start[]; extern char __image_end[]; extern char __piggydata_start[]; +extern char __piggydata_end[]; extern void *_barebox_image_size; extern void *_barebox_bare_init_size; extern void *_barebox_pbl_size; diff --git a/include/ddr_spd.h b/include/ddr_spd.h index 6e63d90e5e..bcc2171d2a 100644 --- a/include/ddr_spd.h +++ b/include/ddr_spd.h @@ -6,7 +6,7 @@ #ifndef _DDR_SPD_H_ #define _DDR_SPD_H_ -#include <i2c/i2c.h> +#include <pbl/i2c.h> /* * Format from "JEDEC Standard No. 21-C, @@ -574,8 +574,7 @@ void ddr2_spd_dump(const struct ddr2_spd_eeprom *spd); int ddr3_spd_check(const struct ddr3_spd_eeprom *spd); int ddr4_spd_check(const struct ddr4_spd_eeprom *spd); -int spd_read_eeprom(void *ctx, - int (*xfer)(void *ctx, struct i2c_msg *msgs, int num), +int spd_read_eeprom(struct pbl_i2c *i2c, uint8_t addr, void *buf); #endif /* _DDR_SPD_H_ */ diff --git a/include/i2c/i2c-early.h b/include/i2c/i2c-early.h deleted file mode 100644 index fa93656e28..0000000000 --- a/include/i2c/i2c-early.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ - -#ifndef __I2C_EARLY_H -#define __I2C_EARLY_H - -#include <i2c/i2c.h> - -int i2c_fsl_xfer(void *ctx, struct i2c_msg *msgs, int num); - -void *imx8m_i2c_early_init(void __iomem *regs); -void *ls1046_i2c_init(void __iomem *regs); - -#endif /* __I2C_EARLY_H */ diff --git a/include/pbl/i2c.h b/include/pbl/i2c.h new file mode 100644 index 0000000000..d9910f531f --- /dev/null +++ b/include/pbl/i2c.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __PBL_I2C_H +#define __PBL_I2C_H + +#include <i2c/i2c.h> + +struct pbl_i2c { + int (*xfer)(struct pbl_i2c *, struct i2c_msg *msgs, int num); +}; + +static inline int pbl_i2c_xfer(struct pbl_i2c *i2c, + struct i2c_msg *msgs, int num) +{ + return i2c->xfer(i2c, msgs, num); +} + +struct pbl_i2c *imx8m_i2c_early_init(void __iomem *regs); +struct pbl_i2c *ls1046_i2c_init(void __iomem *regs); + +static inline int i2c_dev_probe(struct pbl_i2c *i2c, int addr, bool onebyte) +{ + u8 buf[1]; + struct i2c_msg msgs[] = { + { + .addr = addr, + .buf = buf, + .flags = I2C_M_RD, + .len = onebyte, + }, + }; + + return pbl_i2c_xfer(i2c, msgs, 1) == 1 ? 0 : -ENODEV; +} + + +#endif /* __I2C_EARLY_H */ diff --git a/include/pbl/pmic.h b/include/pbl/pmic.h new file mode 100644 index 0000000000..0f882c5649 --- /dev/null +++ b/include/pbl/pmic.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __PBL_PMIC_H_ +#define __PBL_PMIC_H_ + +#include <pbl/i2c.h> + +struct pmic_config { + u8 reg; + u8 val; +}; + +static void pmic_reg_write(struct pbl_i2c *i2c, int addr, u8 reg, u8 val) +{ + int ret; + u8 buf[32]; + struct i2c_msg msgs[] = { + { + .addr = addr, + .buf = buf, + }, + }; + + buf[0] = reg; + buf[1] = val; + + msgs[0].len = 2; + + ret = pbl_i2c_xfer(i2c, msgs, ARRAY_SIZE(msgs)); + if (ret != 1) + pr_err("Failed to write to pmic@%x: %d\n", addr, ret); +} + +static inline void pmic_configure(struct pbl_i2c *i2c, u8 addr, + const struct pmic_config *config, + size_t config_len) +{ + for (; config_len--; config++) + pmic_reg_write(i2c, addr, config->reg, config->val); +} + +#endif diff --git a/include/soc/imx8m/ddr.h b/include/soc/imx8m/ddr.h index c81c4d82c5..2149ae4325 100644 --- a/include/soc/imx8m/ddr.h +++ b/include/soc/imx8m/ddr.h @@ -329,10 +329,29 @@ enum fw_type { }; enum dram_type { - DRAM_TYPE_LPDDR4, - DRAM_TYPE_DDR4, +#define DRAM_TYPE_MASK 0x00ff + DRAM_TYPE_LPDDR4 = 0 << 0, + DRAM_TYPE_DDR4 = 1 << 0, }; +static inline enum dram_type get_dram_type(unsigned type) +{ + return type & DRAM_TYPE_MASK; +} + +enum ddrc_type { +#define DDRC_TYPE_MASK 0xff00 + DDRC_TYPE_MM = 0 << 8, + DDRC_TYPE_MN = 1 << 8, + DDRC_TYPE_MQ = 2 << 8, + DDRC_TYPE_MP = 3 << 8, +}; + +static inline enum ddrc_type get_ddrc_type(unsigned type) +{ + return type & DDRC_TYPE_MASK; +} + struct dram_cfg_param { unsigned int reg; unsigned int val; @@ -346,7 +365,6 @@ struct dram_fsp_msg { }; struct dram_timing_info { - enum dram_type dram_type; /* umctl2 config */ struct dram_cfg_param *ddrc_cfg; unsigned int ddrc_cfg_num; @@ -368,29 +386,64 @@ struct dram_timing_info { extern struct dram_timing_info dram_timing; -enum ddrc_type { - DDRC_TYPE_MM, - DDRC_TYPE_MN, - DDRC_TYPE_MQ, - DDRC_TYPE_MP, -}; +void ddr_get_firmware_lpddr4(void); +void ddr_get_firmware_ddr(void); + +static void ddr_get_firmware(enum dram_type dram_type) +{ + if (dram_type == DRAM_TYPE_LPDDR4) + ddr_get_firmware_lpddr4(); + else + ddr_get_firmware_ddr(); +} + +int imx8m_ddr_init(struct dram_timing_info *dram_timing, + unsigned type); + +static inline int imx8mm_ddr_init(struct dram_timing_info *dram_timing, + enum dram_type dram_type) +{ + ddr_get_firmware(dram_type); + + return imx8m_ddr_init(dram_timing, DDRC_TYPE_MM | dram_type); +} + +static inline int imx8mn_ddr_init(struct dram_timing_info *dram_timing, + enum dram_type dram_type) +{ + ddr_get_firmware(dram_type); + + return imx8m_ddr_init(dram_timing, DDRC_TYPE_MN | dram_type); +} + +static inline int imx8mq_ddr_init(struct dram_timing_info *dram_timing, + enum dram_type dram_type) +{ + ddr_get_firmware(dram_type); + + return imx8m_ddr_init(dram_timing, DDRC_TYPE_MQ | dram_type); +} + +static inline int imx8mp_ddr_init(struct dram_timing_info *dram_timing, + enum dram_type dram_type) +{ + ddr_get_firmware(dram_type); + + return imx8m_ddr_init(dram_timing, DDRC_TYPE_MP | dram_type); +} -int imx8mm_ddr_init(struct dram_timing_info *timing_info); -int imx8mn_ddr_init(struct dram_timing_info *timing_info); -int imx8mq_ddr_init(struct dram_timing_info *timing_info); -int imx8mp_ddr_init(struct dram_timing_info *timing_info); -int ddr_cfg_phy(struct dram_timing_info *timing_info, enum ddrc_type type); +int ddr_cfg_phy(struct dram_timing_info *timing_info, enum ddrc_type ddrc_type); void load_lpddr4_phy_pie(void); void ddrphy_trained_csr_save(struct dram_cfg_param *param, unsigned int num); void dram_config_save(struct dram_timing_info *info, unsigned long base); /* utils function for ddr phy training */ int wait_ddrphy_training_complete(void); -void ddrphy_init_set_dfi_clk(unsigned int drate, enum ddrc_type type); -void ddrphy_init_read_msg_block(enum fw_type type); +void ddrphy_init_set_dfi_clk(unsigned int drate, enum ddrc_type ddrc_type); +void ddrphy_init_read_msg_block(enum fw_type fw_type); void update_umctl2_rank_space_setting(unsigned int pstat_num, - enum ddrc_type type); + enum ddrc_type ddrc_type); void get_trained_CDD(unsigned int fsp); #define reg32_write(a, v) writel(v, a) @@ -415,22 +468,22 @@ enum ddrc_phy_firmware_offset { DDRC_PHY_DMEM = 0x00054000U, }; -void ddr_load_train_code(enum dram_type dram_type, enum fw_type type); +void ddr_load_train_code(enum dram_type dram_type, enum fw_type fw_type); void ddrc_phy_load_firmware(void __iomem *, enum ddrc_phy_firmware_offset, const u16 *, size_t); -static inline bool dram_is_lpddr4(enum dram_type type) +static inline bool dram_is_lpddr4(enum dram_type dram_type) { return IS_ENABLED(CONFIG_FIRMWARE_IMX_LPDDR4_PMU_TRAIN) && - type == DRAM_TYPE_LPDDR4; + dram_type == DRAM_TYPE_LPDDR4; } -static inline bool dram_is_ddr4(enum dram_type type) +static inline bool dram_is_ddr4(enum dram_type dram_type) { return IS_ENABLED(CONFIG_FIRMWARE_IMX_DDR4_PMU_TRAIN) && - type == DRAM_TYPE_DDR4; + dram_type == DRAM_TYPE_DDR4; } #define DDRC_PHY_REG(x) ((x) * 4) diff --git a/scripts/imx/imx-usb-loader.c b/scripts/imx/imx-usb-loader.c index 69df9bbe92..1242f2dedd 100644 --- a/scripts/imx/imx-usb-loader.c +++ b/scripts/imx/imx-usb-loader.c @@ -74,6 +74,7 @@ struct mach_id { #define DEV_IMX 0 #define DEV_MXS 1 unsigned char dev_type; + unsigned char hid_endpoint; }; struct usb_work { @@ -182,6 +183,22 @@ static const struct mach_id imx_ids[] = { .max_transfer = 1024, }, { .vid = 0x1fc9, + .pid = 0x0146, + .name = "i.MX8MP", + .header_type = HDR_MX53, + .max_transfer = 1020, + .mode = MODE_HID, + .hid_endpoint = 1, + }, { + .vid = 0x1fc9, + .pid = 0x013e, + .name = "i.MX8MN", + .header_type = HDR_MX53, + .max_transfer = 1020, + .dev_type = MODE_HID, + .hid_endpoint = 1, + }, { + .vid = 0x1fc9, .pid = 0x012b, .name = "i.MX8MQ", .header_type = HDR_MX53, @@ -447,7 +464,7 @@ static void dump_bytes(const void *src, unsigned cnt, unsigned addr) * EP2IN - bulk in * (max packet size of 512 bytes) */ -static int transfer(int report, unsigned char *p, unsigned cnt, int *last_trans) +static int transfer(int report, void *p, unsigned cnt, int *last_trans) { int err; if (cnt > mach_id->max_transfer) @@ -470,15 +487,22 @@ static int transfer(int report, unsigned char *p, unsigned cnt, int *last_trans) if (report < 3) { memcpy(&tmp[1], p, cnt); - err = libusb_control_transfer(usb_dev_handle, - CTRL_OUT, - HID_SET_REPORT, - (HID_REPORT_TYPE_OUTPUT << 8) | report, - 0, - tmp, cnt + 1, 1000); - *last_trans = (err > 0) ? err - 1 : 0; - if (err > 0) - err = 0; + if (mach_id->hid_endpoint) { + int trans; + err = libusb_interrupt_transfer(usb_dev_handle, + mach_id->hid_endpoint, tmp, cnt + 1, &trans, 1000); + *last_trans = trans - 1; + } else { + err = libusb_control_transfer(usb_dev_handle, + CTRL_OUT, + HID_SET_REPORT, + (HID_REPORT_TYPE_OUTPUT << 8) | report, + 0, + tmp, cnt + 1, 1000); + *last_trans = (err > 0) ? err - 1 : 0; + if (err > 0) + err = 0; + } } else { *last_trans = 0; memset(&tmp[1], 0, cnt); @@ -511,7 +535,7 @@ static int do_status(void) unsigned char tmp[64]; int retry = 0; int err; - static const struct sdp_command status_command = { + static struct sdp_command status_command = { .cmd = SDP_ERROR_STATUS, .addr = 0, .format = 0, @@ -521,8 +545,7 @@ static int do_status(void) }; for (;;) { - err = transfer(1, (unsigned char *) &status_command, 16, - &last_trans); + err = transfer(1, &status_command, 16, &last_trans); if (verbose > 2) printf("report 1, wrote %i bytes, err=%i\n", last_trans, err); @@ -575,8 +598,7 @@ static int read_memory(unsigned addr, void *dest, unsigned cnt) read_reg_command.cnt = htonl(cnt); for (;;) { - err = transfer(1, (unsigned char *) &read_reg_command, 16, - &last_trans); + err = transfer(1, &read_reg_command, 16, &last_trans); if (!err) break; printf("read_reg_command err=%i, last_trans=%i\n", err, last_trans); @@ -603,17 +625,10 @@ static int read_memory(unsigned addr, void *dest, unsigned cnt) err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3], cnt, rem); break; } - if ((last_trans > rem) || (last_trans > 64)) { - if ((last_trans == 64) && (rem < 64)) { - /* Last transfer is expected to be too large for HID */ - } else { - printf("err: %02x %02x %02x %02x cnt=%u rem=%d last_trans=%i\n", - tmp[0], tmp[1], tmp[2], tmp[3], cnt, rem, last_trans); - } + + if (last_trans > rem) last_trans = rem; - if (last_trans > 64) - last_trans = 64; - } + memcpy(dest, tmp, last_trans); dest += last_trans; rem -= last_trans; @@ -659,8 +674,7 @@ static int write_memory(unsigned addr, unsigned val, int width) write_reg_command.data = htonl(val); for (;;) { - err = transfer(1, (unsigned char *) &write_reg_command, 16, - &last_trans); + err = transfer(1, &write_reg_command, 16, &last_trans); if (!err) break; printf("write_reg_command err=%i, last_trans=%i\n", err, last_trans); @@ -713,6 +727,31 @@ static int modify_memory(unsigned addr, unsigned val, int width, int set_bits, i return write_memory(addr, val, 4); } +static int send_buf(void *buf, unsigned len) +{ + void *p = buf; + int cnt = len; + int err; + + while (1) { + int now = get_min(cnt, mach_id->max_transfer); + + if (!now) + break; + + err = transfer(2, p, now, &now); + if (err) { + printf("dl_command err=%i, last_trans=%i\n", err, now); + return err; + } + + p += now; + cnt -= now; + } + + return 0; +} + static int load_file(void *buf, unsigned len, unsigned dladdr, unsigned char type, bool mode_barebox) { @@ -729,8 +768,6 @@ static int load_file(void *buf, unsigned len, unsigned dladdr, int retry = 0; unsigned transfer_size = 0; unsigned char tmp[64]; - void *p; - int cnt; len = ALIGN(len, 4); @@ -739,8 +776,7 @@ static int load_file(void *buf, unsigned len, unsigned dladdr, dl_command.rsvd = type; for (;;) { - err = transfer(1, (unsigned char *) &dl_command, 16, - &last_trans); + err = transfer(1, &dl_command, 16, &last_trans); if (!err) break; @@ -760,24 +796,9 @@ static int load_file(void *buf, unsigned len, unsigned dladdr, err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3]); } - p = buf; - cnt = len; - - while (1) { - int now = get_min(cnt, mach_id->max_transfer); - - if (!now) - break; - - err = transfer(2, p, now, &now); - if (err) { - printf("dl_command err=%i, last_trans=%i\n", err, last_trans); - return err; - } - - p += now; - cnt -= now; - } + err = send_buf(buf, len); + if (err) + return err; if (mode_barebox) return transfer_size; @@ -815,8 +836,7 @@ static int sdp_jump_address(unsigned addr) jump_command.addr = htonl(addr); for (;;) { - err = transfer(1, (unsigned char *) &jump_command, 16, - &last_trans); + err = transfer(1, &jump_command, 16, &last_trans); if (!err) break; @@ -1234,19 +1254,22 @@ static int get_dl_start(const unsigned char *p, const unsigned char *file_start, } case HDR_MX53: { - unsigned char *bd; + unsigned char *_bd; struct imx_flash_header_v2 *hdr = (struct imx_flash_header_v2 *)p; + struct imx_boot_data *bd; *header_addr = hdr->self; - bd = hdr->boot_data_ptr + cvt_dest_to_src; - if ((bd < file_start) || ((bd + 4) > file_end)) { + _bd = hdr->boot_data_ptr + cvt_dest_to_src; + if ((_bd < file_start) || ((_bd + 4) > file_end)) { printf("bad boot_data_ptr %08x\n", hdr->boot_data_ptr); return -1; } - *firststage_len = ((struct imx_boot_data *)bd)->size; - *plugin = ((struct imx_boot_data *)bd)->plugin; - ((struct imx_boot_data *)bd)->plugin = 0; + bd = (void *)_bd; + + *firststage_len = bd->size - (hdr->self - bd->start); + *plugin = bd->plugin; + bd->plugin = 0; break; } @@ -1345,6 +1368,9 @@ static int do_irom_download(struct usb_work *curr, int verify) header_offset = ret; + if (mach_id->hid_endpoint) + return send_buf(buf + header_offset, fsize - header_offset); + if (plugin && (!curr->plug)) { printf("Only plugin header found\n"); ret = -1; @@ -1386,7 +1412,7 @@ static int do_irom_download(struct usb_work *curr, int verify) if (verify) { printf("verifying file...\n"); - ret = verify_memory(image, fsize, header_addr); + ret = verify_memory(image, firststage_len, header_addr); if (ret < 0) { printf("verifying failed\n"); goto cleanup; @@ -1442,13 +1468,10 @@ static int write_mem(const struct config_data *data, uint32_t addr, return modify_memory(addr, val, width, set_bits, clear_bits); } -/* MXS section */ -static int mxs_load_file(libusb_device_handle *dev, uint8_t *data, int size) +static int mxs_load_buf(uint8_t *data, int size) { static struct mxs_command dl_command; int last_trans, err; - void *p; - int cnt; dl_command.sign = htonl(0x424c5443); /* Signature: BLTC */ dl_command.tag = htonl(0x1); @@ -1459,36 +1482,19 @@ static int mxs_load_file(libusb_device_handle *dev, uint8_t *data, int size) dl_command.cmd = MXS_CMD_FW_DOWNLOAD; dl_command.dw_size = htonl(size); - err = transfer(1, (unsigned char *) &dl_command, 20, &last_trans); + err = transfer(1, &dl_command, 20, &last_trans); if (err) { printf("transfer error at init step: err=%i, last_trans=%i\n", err, last_trans); return err; } - p = data; - cnt = size; - - while (1) { - int now = get_min(cnt, mach_id->max_transfer); - - if (!now) - break; - - err = transfer(2, p, now, &now); - if (err) { - printf("dl_command err=%i, last_trans=%i\n", err, now); - return err; - } - - p += now; - cnt -= now; - } + err = send_buf(data, size); return err; } -static int mxs_work(struct usb_work *curr) +static int mxs_load_file(struct usb_work *curr) { size_t fsize = 0; unsigned char *buf = NULL; @@ -1497,9 +1503,8 @@ static int mxs_work(struct usb_work *curr) if (!buf) return -errno; - return mxs_load_file(usb_dev_handle, buf, fsize); + return mxs_load_buf(buf, fsize); } -/* end of mxs section */ static int parse_initfile(const char *filename) { @@ -1619,7 +1624,7 @@ int main(int argc, char *argv[]) } if (mach_id->dev_type == DEV_MXS) { - ret = mxs_work(&w); + ret = mxs_load_file(&w); goto out; } |