Merge tag 'u-boot-imx-master-20250503' of https://gitlab.denx.de/u-boot/custodians/u-boot-imx
CI: https://source.denx.de/u-boot/custodians/u-boot-imx/-/pipelines/26064 - Add i.MX95 support. - Enable BOOTAUX on the i.MX8M Beacon boards.
This commit is contained in:
@@ -2231,7 +2231,8 @@ CLEAN_FILES += include/autoconf.mk* include/bmp_logo.h include/bmp_logo_data.h \
|
||||
itb.fit.fit itb.fit.itb itb.map spl.map mkimage-out.rom.mkimage \
|
||||
mkimage.rom.mkimage mkimage-in-simple-bin* rom.map simple-bin* \
|
||||
idbloader-spi.img lib/efi_loader/helloworld_efi.S *.itb \
|
||||
Test* capsule*.*.efi-capsule capsule*.map
|
||||
Test* capsule*.*.efi-capsule capsule*.map mkimage.imx-boot.spl \
|
||||
mkimage.imx-boot.u-boot mkimage-out.imx-boot.spl mkimage-out.imx-boot.u-boot
|
||||
|
||||
# Directories & files removed with 'make mrproper'
|
||||
MRPROPER_DIRS += include/config include/generated spl tpl vpl \
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2025 NXP
|
||||
*/
|
||||
|
||||
#include "imx95-u-boot.dtsi"
|
||||
|
||||
&lpuart1 {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
|
||||
®_usdhc2_vmmc {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
|
||||
&usdhc1 {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
|
||||
&usdhc2 {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
|
||||
&wdog3 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&pinctrl_uart1 {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
|
||||
&pinctrl_usdhc1 {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
|
||||
&pinctrl_usdhc1_100mhz {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
|
||||
&pinctrl_usdhc1_200mhz {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
|
||||
&pinctrl_usdhc2 {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
|
||||
&pinctrl_usdhc2_100mhz {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
|
||||
&pinctrl_usdhc2_200mhz {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
|
||||
&pinctrl_usdhc2_gpio {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
|
||||
&pinctrl_reg_usdhc2_vmmc {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
@@ -0,0 +1,188 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2025 NXP
|
||||
*/
|
||||
|
||||
/ {
|
||||
binman {
|
||||
multiple-images;
|
||||
|
||||
m33-oei-ddrfw {
|
||||
pad-byte = <0x00>;
|
||||
align-size = <0x8>;
|
||||
filename = "m33-oei-ddrfw.bin";
|
||||
|
||||
oei-m33-ddr {
|
||||
align-size = <0x4>;
|
||||
filename = "oei-m33-ddr.bin";
|
||||
type = "blob-ext";
|
||||
};
|
||||
|
||||
imx-lpddr {
|
||||
type = "nxp-header-ddrfw";
|
||||
|
||||
imx-lpddr-imem {
|
||||
filename = "lpddr5_imem_v202311.bin";
|
||||
type = "blob-ext";
|
||||
};
|
||||
|
||||
imx-lpddr-dmem {
|
||||
filename = "lpddr5_dmem_v202311.bin";
|
||||
type = "blob-ext";
|
||||
};
|
||||
};
|
||||
|
||||
imx-lpddr-qb {
|
||||
type = "nxp-header-ddrfw";
|
||||
|
||||
imx-lpddr-imem-qb {
|
||||
filename = "lpddr5_imem_qb_v202311.bin";
|
||||
type = "blob-ext";
|
||||
};
|
||||
|
||||
imx-lpddr-dmem-qb {
|
||||
filename = "lpddr5_dmem_qb_v202311.bin";
|
||||
type = "blob-ext";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
imx-boot {
|
||||
filename = "flash.bin";
|
||||
pad-byte = <0x00>;
|
||||
|
||||
spl {
|
||||
align = <0x400>;
|
||||
align-size = <0x400>;
|
||||
type = "mkimage";
|
||||
args = "-n spl/u-boot-spl.cfgout -T imx8image";
|
||||
};
|
||||
|
||||
u-boot {
|
||||
type = "mkimage";
|
||||
args = "-n u-boot-container.cfgout -T imx8image";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&A55_0 {
|
||||
clocks = <&scmi_clk IMX95_CLK_ARMPLL_PFD0>;
|
||||
/delete-property/ power-domains;
|
||||
};
|
||||
|
||||
&A55_1 {
|
||||
clocks = <&scmi_clk IMX95_CLK_ARMPLL_PFD0>;
|
||||
/delete-property/ power-domains;
|
||||
};
|
||||
|
||||
&A55_2 {
|
||||
clocks = <&scmi_clk IMX95_CLK_ARMPLL_PFD0>;
|
||||
/delete-property/ power-domains;
|
||||
};
|
||||
|
||||
&A55_3 {
|
||||
clocks = <&scmi_clk IMX95_CLK_ARMPLL_PFD0>;
|
||||
/delete-property/ power-domains;
|
||||
};
|
||||
|
||||
&A55_4 {
|
||||
clocks = <&scmi_clk IMX95_CLK_ARMPLL_PFD0>;
|
||||
/delete-property/ power-domains;
|
||||
};
|
||||
|
||||
&A55_5 {
|
||||
clocks = <&scmi_clk IMX95_CLK_ARMPLL_PFD0>;
|
||||
/delete-property/ power-domains;
|
||||
};
|
||||
|
||||
&aips1 {
|
||||
bootph-all;
|
||||
};
|
||||
|
||||
&aips2 {
|
||||
bootph-all;
|
||||
};
|
||||
|
||||
&aips3 {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
|
||||
&clk_ext1 {
|
||||
bootph-all;
|
||||
};
|
||||
|
||||
&elemu1 {
|
||||
bootph-all;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&elemu3 {
|
||||
bootph-all;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&{/firmware} {
|
||||
bootph-all;
|
||||
};
|
||||
|
||||
&{/firmware/scmi} {
|
||||
bootph-all;
|
||||
};
|
||||
|
||||
&{/firmware/scmi/protocol@11} {
|
||||
bootph-all;
|
||||
};
|
||||
|
||||
&{/firmware/scmi/protocol@13} {
|
||||
bootph-all;
|
||||
};
|
||||
|
||||
&{/firmware/scmi/protocol@14} {
|
||||
bootph-all;
|
||||
};
|
||||
|
||||
&{/firmware/scmi/protocol@19} {
|
||||
bootph-all;
|
||||
};
|
||||
|
||||
&gpio2 {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
|
||||
&gpio3 {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
|
||||
&gpio4 {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
|
||||
&gpio5 {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
|
||||
&mu2 {
|
||||
bootph-all;
|
||||
};
|
||||
|
||||
&osc_24m {
|
||||
bootph-all;
|
||||
};
|
||||
|
||||
&{/soc} {
|
||||
bootph-all;
|
||||
};
|
||||
|
||||
&sram0 {
|
||||
bootph-all;
|
||||
};
|
||||
|
||||
&scmi_buf0 {
|
||||
reg = <0x0 0x400>;
|
||||
bootph-all;
|
||||
};
|
||||
|
||||
&scmi_buf1 {
|
||||
bootph-all;
|
||||
};
|
||||
@@ -76,6 +76,8 @@
|
||||
#define MXC_CPU_IMX9111 0xCD /* dummy ID */
|
||||
#define MXC_CPU_IMX9101 0xCE /* dummy ID */
|
||||
|
||||
#define MXC_CPU_IMX95 0x1C1 /* dummy ID */
|
||||
|
||||
#define MXC_SOC_MX6 0x60
|
||||
#define MXC_SOC_MX7 0x70
|
||||
#define MXC_SOC_IMX8M 0x80
|
||||
|
||||
@@ -255,5 +255,15 @@ int ccm_shared_gpr_tz_access(u32 gpr, bool non_secure, bool user_mode, bool lock
|
||||
void enable_usboh3_clk(unsigned char enable);
|
||||
int set_clk_enet(enum enet_freq type);
|
||||
int set_clk_eqos(enum enet_freq type);
|
||||
|
||||
int imx_clk_scmi_enable(u32 clock_id, bool enable);
|
||||
ulong imx_clk_scmi_set_rate(u32 clock_id, ulong rate);
|
||||
ulong imx_clk_scmi_get_rate(u32 clock_id);
|
||||
int imx_clk_scmi_set_parent(u32 clock_id, u32 parent_id);
|
||||
void set_arm_clk(ulong freq);
|
||||
|
||||
int imx_clk_scmi_enable(u32 clock_id, bool enable);
|
||||
ulong imx_clk_scmi_set_rate(u32 clock_id, ulong rate);
|
||||
ulong imx_clk_scmi_get_rate(u32 clock_id);
|
||||
int imx_clk_scmi_set_parent(u32 clock_id, u32 parent_id);
|
||||
#endif
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#define CCM_BASE_ADDR 0x44450000UL
|
||||
#define CCM_CCGR_BASE_ADDR 0x44458000UL
|
||||
#define SYSCNT_CTRL_BASE_ADDR 0x44290000
|
||||
#define SYSCNT_CMP_BASE_ADDR (SYSCNT_CTRL_BASE_ADDR + 0x10000)
|
||||
|
||||
#define ANATOP_BASE_ADDR 0x44480000UL
|
||||
|
||||
@@ -20,6 +21,11 @@
|
||||
#define WDG4_BASE_ADDR 0x424a0000UL
|
||||
#define WDG5_BASE_ADDR 0x424b0000UL
|
||||
|
||||
#define GPIO2_BASE_ADDR 0x43810000UL
|
||||
#define GPIO3_BASE_ADDR 0x43820000UL
|
||||
#define GPIO4_BASE_ADDR 0x43840000UL
|
||||
#define GPIO5_BASE_ADDR 0x43850000UL
|
||||
|
||||
#define FSB_BASE_ADDR 0x47510000UL
|
||||
|
||||
#define ANATOP_BASE_ADDR 0x44480000UL
|
||||
|
||||
@@ -12,6 +12,7 @@ enum imx9_soc_voltage_mode {
|
||||
VOLT_LOW_DRIVE = 0,
|
||||
VOLT_NOMINAL_DRIVE,
|
||||
VOLT_OVER_DRIVE,
|
||||
VOLT_SUPER_OVER_DRIVE,
|
||||
};
|
||||
|
||||
void soc_power_init(void);
|
||||
|
||||
@@ -97,6 +97,8 @@ struct bd_info;
|
||||
#define is_imx9302() (is_cpu_type(MXC_CPU_IMX9302))
|
||||
#define is_imx9301() (is_cpu_type(MXC_CPU_IMX9301))
|
||||
|
||||
#define is_imx95() (is_cpu_type(MXC_CPU_IMX95))
|
||||
|
||||
#define is_imx9121() (is_cpu_type(MXC_CPU_IMX9121))
|
||||
#define is_imx9111() (is_cpu_type(MXC_CPU_IMX9111))
|
||||
#define is_imx9101() (is_cpu_type(MXC_CPU_IMX9101))
|
||||
@@ -216,6 +218,43 @@ ulong spl_romapi_get_uboot_base(u32 image_offset, u32 rom_bt_dev);
|
||||
u32 rom_api_download_image(u8 *dest, u32 offset, u32 size);
|
||||
u32 rom_api_query_boot_infor(u32 info_type, u32 *info);
|
||||
|
||||
#if IS_ENABLED(CONFIG_SCMI_FIRMWARE)
|
||||
typedef struct rom_passover {
|
||||
u16 tag; // Tag
|
||||
u8 len; // Fixed value of 0x80
|
||||
u8 ver; // Version
|
||||
u32 boot_mode; // Boot mode
|
||||
u32 card_addr_mode; // SD card address mode
|
||||
u32 bad_blks_of_img_set0; // NAND bad block count skipped 1
|
||||
u32 ap_mu_id; // AP MU ID
|
||||
u32 bad_blks_of_img_set1; // NAND bad block count skipped 1
|
||||
u8 boot_stage; // Boot stage
|
||||
u8 img_set_sel; // Image set booted from
|
||||
u8 rsv0[2]; // Reserved
|
||||
u32 img_set_end; // Offset of Image End
|
||||
u32 rom_version; // ROM version
|
||||
u8 boot_dev_state; // Boot device state
|
||||
u8 boot_dev_inst; // Boot device type
|
||||
u8 boot_dev_type; // Boot device instance
|
||||
u8 rsv1; // Reserved
|
||||
u32 dev_page_size; // Boot device page size
|
||||
u32 cnt_header_ofs; // Container header offset
|
||||
u32 img_ofs; // Image offset
|
||||
} __packed rom_passover_t;
|
||||
|
||||
/**
|
||||
* struct scmi_rom_passover_out - Response payload for ROM_PASSOVER_GET command
|
||||
* @status: SCMI clock ID
|
||||
* @attributes: Attributes of the targets clock state
|
||||
*/
|
||||
struct scmi_rom_passover_get_out {
|
||||
u32 status;
|
||||
u32 numPassover;
|
||||
u32 passover[(sizeof(rom_passover_t) + 8) / 4];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* For i.MX ULP */
|
||||
#define BT0CFG_LPBOOT_MASK 0x1
|
||||
#define BT0CFG_DUALBOOT_MASK 0x2
|
||||
|
||||
@@ -180,7 +180,7 @@ config DDRMC_VF610_CALIBRATION
|
||||
|
||||
config IMX8_ROMAPI
|
||||
def_bool y
|
||||
depends on IMX8MN || IMX8MP || IMX8ULP || IMX9
|
||||
depends on IMX8MN || IMX8MP || IMX8ULP || IMX91 || IMX93
|
||||
|
||||
config SPL_IMX_ROMAPI_LOADADDR
|
||||
hex "Default load address to load image through ROM API"
|
||||
|
||||
@@ -41,6 +41,52 @@
|
||||
#define FUSE_IMG_SET_OFF_WORD 720
|
||||
#endif
|
||||
|
||||
#define MAX_V2X_CTNR_IMG_NUM (4)
|
||||
#define MIN_V2X_CTNR_IMG_NUM (2)
|
||||
|
||||
#define IMG_FLAGS_IMG_TYPE_SHIFT (0u)
|
||||
#define IMG_FLAGS_IMG_TYPE_MASK (0xfU)
|
||||
#define IMG_FLAGS_IMG_TYPE(x) (((x) & IMG_FLAGS_IMG_TYPE_MASK) >> \
|
||||
IMG_FLAGS_IMG_TYPE_SHIFT)
|
||||
|
||||
#define IMG_FLAGS_CORE_ID_SHIFT (4u)
|
||||
#define IMG_FLAGS_CORE_ID_MASK (0xf0U)
|
||||
#define IMG_FLAGS_CORE_ID(x) (((x) & IMG_FLAGS_CORE_ID_MASK) >> \
|
||||
IMG_FLAGS_CORE_ID_SHIFT)
|
||||
|
||||
#define IMG_TYPE_V2X_PRI_FW (0x0Bu) /* Primary V2X FW */
|
||||
#define IMG_TYPE_V2X_SND_FW (0x0Cu) /* Secondary V2X FW */
|
||||
|
||||
#define CORE_V2X_PRI 9
|
||||
#define CORE_V2X_SND 10
|
||||
|
||||
static bool is_v2x_fw_container(ulong addr)
|
||||
{
|
||||
struct container_hdr *phdr;
|
||||
struct boot_img_t *img_entry;
|
||||
|
||||
phdr = (struct container_hdr *)addr;
|
||||
if (phdr->tag != 0x87 || phdr->version != 0x0) {
|
||||
debug("Wrong container header\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (phdr->num_images >= MIN_V2X_CTNR_IMG_NUM && phdr->num_images <= MAX_V2X_CTNR_IMG_NUM) {
|
||||
img_entry = (struct boot_img_t *)(addr + sizeof(struct container_hdr));
|
||||
|
||||
if (IMG_FLAGS_IMG_TYPE(img_entry->hab_flags) == IMG_TYPE_V2X_PRI_FW &&
|
||||
IMG_FLAGS_CORE_ID(img_entry->hab_flags) == CORE_V2X_PRI) {
|
||||
img_entry++;
|
||||
|
||||
if (IMG_FLAGS_IMG_TYPE(img_entry->hab_flags) == IMG_TYPE_V2X_SND_FW &&
|
||||
IMG_FLAGS_CORE_ID(img_entry->hab_flags) == CORE_V2X_SND)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int get_container_size(ulong addr, u16 *header_length)
|
||||
{
|
||||
struct container_hdr *phdr;
|
||||
@@ -83,7 +129,7 @@ int get_container_size(ulong addr, u16 *header_length)
|
||||
return max_offset;
|
||||
}
|
||||
|
||||
static int get_dev_container_size(void *dev, int dev_type, unsigned long offset, u16 *header_length)
|
||||
static int get_dev_container_size(void *dev, int dev_type, unsigned long offset, u16 *header_length, bool *v2x_cntr)
|
||||
{
|
||||
u8 *buf = malloc(CONTAINER_HDR_ALIGNMENT);
|
||||
int ret = 0;
|
||||
@@ -150,6 +196,9 @@ static int get_dev_container_size(void *dev, int dev_type, unsigned long offset,
|
||||
|
||||
ret = get_container_size((ulong)buf, header_length);
|
||||
|
||||
if (v2x_cntr)
|
||||
*v2x_cntr = is_v2x_fw_container((ulong)buf);
|
||||
|
||||
free(buf);
|
||||
|
||||
return ret;
|
||||
@@ -231,45 +280,67 @@ static unsigned long get_boot_device_offset(void *dev, int dev_type)
|
||||
return offset;
|
||||
}
|
||||
|
||||
static int get_imageset_end(void *dev, int dev_type)
|
||||
static ulong get_imageset_end(void *dev, int dev_type)
|
||||
{
|
||||
unsigned long offset1 = 0, offset2 = 0;
|
||||
int value_container[2];
|
||||
unsigned long offset[3] = {};
|
||||
int value_container[3] = {};
|
||||
u16 hdr_length;
|
||||
bool v2x_fw = false;
|
||||
|
||||
offset1 = get_boot_device_offset(dev, dev_type);
|
||||
offset2 = CONTAINER_HDR_ALIGNMENT + offset1;
|
||||
offset[0] = get_boot_device_offset(dev, dev_type);
|
||||
|
||||
value_container[0] = get_dev_container_size(dev, dev_type, offset1, &hdr_length);
|
||||
value_container[0] = get_dev_container_size(dev, dev_type, offset[0], &hdr_length, NULL);
|
||||
if (value_container[0] < 0) {
|
||||
printf("Parse seco container failed %d\n", value_container[0]);
|
||||
return value_container[0];
|
||||
return 0;
|
||||
}
|
||||
|
||||
debug("seco container size 0x%x\n", value_container[0]);
|
||||
|
||||
value_container[1] = get_dev_container_size(dev, dev_type, offset2, &hdr_length);
|
||||
if (value_container[1] < 0) {
|
||||
debug("Parse scu container failed %d, only seco container\n",
|
||||
value_container[1]);
|
||||
/* return seco container total size */
|
||||
return value_container[0] + offset1;
|
||||
if (is_imx95()) {
|
||||
offset[1] = ALIGN(hdr_length, CONTAINER_HDR_ALIGNMENT) + offset[0];
|
||||
|
||||
value_container[1] = get_dev_container_size(dev, dev_type, offset[1], &hdr_length, &v2x_fw);
|
||||
if (value_container[1] < 0) {
|
||||
printf("Parse v2x container failed %d\n", value_container[1]);
|
||||
return value_container[0] + offset[0]; /* return seco container total size */
|
||||
}
|
||||
|
||||
if (v2x_fw) {
|
||||
debug("v2x container size 0x%x\n", value_container[1]);
|
||||
offset[2] = ALIGN(hdr_length, CONTAINER_HDR_ALIGNMENT) + offset[1];
|
||||
} else {
|
||||
printf("no v2x container included\n");
|
||||
offset[2] = offset[1];
|
||||
}
|
||||
} else {
|
||||
/* Skip offset[1] */
|
||||
offset[2] = ALIGN(hdr_length, CONTAINER_HDR_ALIGNMENT) + offset[0];
|
||||
}
|
||||
|
||||
debug("scu container size 0x%x\n", value_container[1]);
|
||||
value_container[2] = get_dev_container_size(dev, dev_type, offset[2], &hdr_length, NULL);
|
||||
if (value_container[2] < 0) {
|
||||
debug("Parse scu container image failed %d, only seco container\n", value_container[2]);
|
||||
if (is_imx95())
|
||||
return value_container[1] + offset[1]; /* return seco + v2x container total size */
|
||||
else
|
||||
return value_container[0] + offset[0]; /* return seco container total size */
|
||||
}
|
||||
|
||||
return value_container[1] + offset2;
|
||||
debug("scu container size 0x%x\n", value_container[2]);
|
||||
|
||||
return value_container[2] + offset[2];
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SPL_SPI_LOAD
|
||||
unsigned int spl_spi_get_uboot_offs(struct spi_flash *flash)
|
||||
{
|
||||
int end;
|
||||
ulong end;
|
||||
|
||||
end = get_imageset_end(flash, QSPI_DEV);
|
||||
end = ROUND(end, SZ_1K);
|
||||
|
||||
printf("Load image from QSPI 0x%x\n", end);
|
||||
printf("Load image from QSPI 0x%lx\n", end);
|
||||
|
||||
return end;
|
||||
}
|
||||
@@ -279,12 +350,12 @@ unsigned int spl_spi_get_uboot_offs(struct spi_flash *flash)
|
||||
unsigned long arch_spl_mmc_get_uboot_raw_sector(struct mmc *mmc,
|
||||
unsigned long raw_sect)
|
||||
{
|
||||
int end;
|
||||
ulong end;
|
||||
|
||||
end = get_imageset_end(mmc, MMC_DEV);
|
||||
end = ROUND(end, SZ_1K);
|
||||
|
||||
printf("Load image from MMC/SD 0x%x\n", end);
|
||||
printf("Load image from MMC/SD 0x%lx\n", end);
|
||||
|
||||
return end / mmc->read_bl_len;
|
||||
}
|
||||
@@ -312,12 +383,12 @@ int spl_mmc_emmc_boot_partition(struct mmc *mmc)
|
||||
#ifdef CONFIG_SPL_NAND_SUPPORT
|
||||
uint32_t spl_nand_get_uboot_raw_page(void)
|
||||
{
|
||||
int end;
|
||||
ulong end;
|
||||
|
||||
end = get_imageset_end((void *)NULL, NAND_DEV);
|
||||
end = ROUND(end, SZ_16K);
|
||||
|
||||
printf("Load image from NAND 0x%x\n", end);
|
||||
printf("Load image from NAND 0x%lx\n", end);
|
||||
|
||||
return end;
|
||||
}
|
||||
@@ -326,7 +397,7 @@ uint32_t spl_nand_get_uboot_raw_page(void)
|
||||
#ifdef CONFIG_SPL_NOR_SUPPORT
|
||||
unsigned long spl_nor_get_uboot_base(void)
|
||||
{
|
||||
int end;
|
||||
ulong end;
|
||||
|
||||
/* Calculate the image set end,
|
||||
* if it is less than CFG_SYS_UBOOT_BASE(0x8281000),
|
||||
@@ -339,7 +410,7 @@ unsigned long spl_nor_get_uboot_base(void)
|
||||
else
|
||||
end = ROUND(end, SZ_1K);
|
||||
|
||||
printf("Load image from NOR 0x%x\n", end);
|
||||
printf("Load image from NOR 0x%lx\n", end);
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,13 @@ config IMX91
|
||||
select IMX9
|
||||
select ARMV8_SPL_EXCEPTION_VECTORS
|
||||
|
||||
config IMX95
|
||||
bool
|
||||
select ARMV8_SPL_EXCEPTION_VECTORS
|
||||
select IMX9
|
||||
select DM_MAILBOX
|
||||
select SCMI_FIRMWARE
|
||||
select SPL_IMX_CONTAINER_USE_TRAMPOLINE
|
||||
|
||||
config SYS_SOC
|
||||
default "imx9"
|
||||
@@ -69,6 +76,13 @@ config TARGET_PHYCORE_IMX93
|
||||
select OF_BOARD_FIXUP
|
||||
select OF_BOARD_SETUP
|
||||
|
||||
config TARGET_IMX95_19X19_EVK
|
||||
bool "imx95_19x19_evk"
|
||||
select IMX95
|
||||
imply BOOTSTD_BOOTCOMMAND
|
||||
imply BOOTSTD_FULL
|
||||
imply OF_UPSTREAM
|
||||
|
||||
endchoice
|
||||
|
||||
source "board/freescale/imx91_evk/Kconfig"
|
||||
@@ -76,6 +90,7 @@ source "board/freescale/imx93_evk/Kconfig"
|
||||
source "board/freescale/imx93_qsb/Kconfig"
|
||||
source "board/phytec/phycore_imx93/Kconfig"
|
||||
source "board/variscite/imx93_var_som/Kconfig"
|
||||
source "board/freescale/imx95_evk/Kconfig"
|
||||
|
||||
endif
|
||||
|
||||
|
||||
@@ -3,8 +3,13 @@
|
||||
# Copyright 2022 NXP
|
||||
|
||||
obj-y += lowlevel_init.o
|
||||
obj-y += soc.o clock.o clock_root.o trdc.o
|
||||
|
||||
#ifndef CONFIG_XPL_BUILD
|
||||
ifeq ($(CONFIG_SCMI_FIRMWARE),y)
|
||||
obj-y += scmi/
|
||||
else
|
||||
obj-y += soc.o clock.o clock_root.o trdc.o
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_SPL_BUILD),y)
|
||||
obj-y += imx_bootaux.o
|
||||
#endif
|
||||
endif
|
||||
@@ -0,0 +1,6 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
# Copyright 2025 NXP
|
||||
|
||||
obj-y += soc.o
|
||||
obj-y += clock_scmi.o clock.o
|
||||
@@ -0,0 +1,70 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2025 NXP
|
||||
*/
|
||||
|
||||
#include <asm/arch/clock.h>
|
||||
#include <dm/uclass.h>
|
||||
#include <scmi_agent.h>
|
||||
#include "../../../../../dts/upstream/src/arm64/freescale/imx95-clock.h"
|
||||
|
||||
u32 get_arm_core_clk(void)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = imx_clk_scmi_get_rate(IMX95_CLK_SEL_A55C0);
|
||||
if (val)
|
||||
return val;
|
||||
return imx_clk_scmi_get_rate(IMX95_CLK_A55);
|
||||
}
|
||||
|
||||
void init_uart_clk(u32 index)
|
||||
{
|
||||
u32 clock_id;
|
||||
|
||||
switch (index) {
|
||||
case 0:
|
||||
clock_id = IMX95_CLK_LPUART1;
|
||||
break;
|
||||
case 1:
|
||||
clock_id = IMX95_CLK_LPUART2;
|
||||
break;
|
||||
case 2:
|
||||
clock_id = IMX95_CLK_LPUART3;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
/* 24MHz */
|
||||
imx_clk_scmi_enable(clock_id, false);
|
||||
imx_clk_scmi_set_parent(clock_id, IMX95_CLK_24M);
|
||||
imx_clk_scmi_set_rate(clock_id, 24000000);
|
||||
imx_clk_scmi_enable(clock_id, true);
|
||||
}
|
||||
|
||||
unsigned int mxc_get_clock(enum mxc_clock clk)
|
||||
{
|
||||
switch (clk) {
|
||||
case MXC_ARM_CLK:
|
||||
return get_arm_core_clk();
|
||||
case MXC_IPG_CLK:
|
||||
return imx_clk_scmi_get_rate(IMX95_CLK_BUSWAKEUP);
|
||||
case MXC_CSPI_CLK:
|
||||
return imx_clk_scmi_get_rate(IMX95_CLK_LPSPI1);
|
||||
case MXC_ESDHC_CLK:
|
||||
return imx_clk_scmi_get_rate(IMX95_CLK_USDHC1);
|
||||
case MXC_ESDHC2_CLK:
|
||||
return imx_clk_scmi_get_rate(IMX95_CLK_USDHC2);
|
||||
case MXC_ESDHC3_CLK:
|
||||
return imx_clk_scmi_get_rate(IMX95_CLK_USDHC3);
|
||||
case MXC_UART_CLK:
|
||||
return imx_clk_scmi_get_rate(IMX95_CLK_LPUART1);
|
||||
case MXC_FLEXSPI_CLK:
|
||||
return imx_clk_scmi_get_rate(IMX95_CLK_FLEXSPI1);
|
||||
default:
|
||||
return -1;
|
||||
};
|
||||
|
||||
return -1;
|
||||
};
|
||||
@@ -0,0 +1,133 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2025 NXP
|
||||
*
|
||||
* Peng Fan <peng.fan@nxp.com>
|
||||
*/
|
||||
|
||||
#include <dm/uclass.h>
|
||||
#include <scmi_agent.h>
|
||||
|
||||
int imx_clk_scmi_enable(u32 clock_id, bool enable)
|
||||
{
|
||||
struct scmi_clk_state_in in = {
|
||||
.clock_id = clock_id,
|
||||
.attributes = (enable) ? 1 : 0,
|
||||
};
|
||||
struct scmi_clk_state_out out;
|
||||
struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_CLOCK,
|
||||
SCMI_CLOCK_CONFIG_SET,
|
||||
in, out);
|
||||
int ret;
|
||||
struct udevice *dev;
|
||||
|
||||
ret = uclass_get_device_by_name(UCLASS_CLK, "protocol@14", &dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_scmi_process_msg(dev, &msg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return scmi_to_linux_errno(out.status);
|
||||
}
|
||||
|
||||
ulong imx_clk_scmi_set_rate(u32 clock_id, ulong rate)
|
||||
{
|
||||
struct scmi_clk_rate_set_in in = {
|
||||
.clock_id = clock_id,
|
||||
.flags = SCMI_CLK_RATE_ROUND_CLOSEST,
|
||||
.rate_lsb = (u32)rate,
|
||||
.rate_msb = (u32)((u64)rate >> 32),
|
||||
};
|
||||
struct scmi_clk_rate_set_out out;
|
||||
struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_CLOCK,
|
||||
SCMI_CLOCK_RATE_SET,
|
||||
in, out);
|
||||
int ret;
|
||||
struct udevice *dev;
|
||||
|
||||
ret = uclass_get_device_by_name(UCLASS_CLK, "protocol@14", &dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_scmi_process_msg(dev, &msg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = scmi_to_linux_errno(out.status);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
struct scmi_clk_rate_get_in in_rate = {
|
||||
.clock_id = clock_id,
|
||||
};
|
||||
struct scmi_clk_rate_get_out out_rate;
|
||||
|
||||
msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_CLOCK, SCMI_CLOCK_RATE_GET, in_rate, out_rate);
|
||||
|
||||
ret = devm_scmi_process_msg(dev, &msg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = scmi_to_linux_errno(out_rate.status);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return (ulong)(((u64)out_rate.rate_msb << 32) | out_rate.rate_lsb);
|
||||
}
|
||||
|
||||
ulong imx_clk_scmi_get_rate(u32 clock_id)
|
||||
{
|
||||
struct scmi_clk_rate_get_in in = {
|
||||
.clock_id = clock_id,
|
||||
};
|
||||
struct scmi_clk_rate_get_out out;
|
||||
struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_CLOCK,
|
||||
SCMI_CLOCK_RATE_GET,
|
||||
in, out);
|
||||
int ret;
|
||||
struct udevice *dev;
|
||||
|
||||
ret = uclass_get_device_by_name(UCLASS_CLK, "protocol@14", &dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_scmi_process_msg(dev, &msg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = scmi_to_linux_errno(out.status);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return (ulong)(((u64)out.rate_msb << 32) | out.rate_lsb);
|
||||
}
|
||||
|
||||
int imx_clk_scmi_set_parent(u32 clock_id, u32 parent_id)
|
||||
{
|
||||
struct scmi_clk_parent_set_in in = {
|
||||
.clock_id = clock_id,
|
||||
.parent_clk = parent_id,
|
||||
};
|
||||
struct scmi_clk_parent_set_out out;
|
||||
struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_CLOCK,
|
||||
SCMI_CLOCK_PARENT_SET,
|
||||
in, out);
|
||||
int ret;
|
||||
struct udevice *dev;
|
||||
|
||||
ret = uclass_get_device_by_name(UCLASS_CLK, "protocol@14", &dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_scmi_process_msg(dev, &msg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = scmi_to_linux_errno(out.status);
|
||||
if (ret < 0 && ret != -EACCES)
|
||||
printf("%s: %d, clock_id %u\n", __func__, ret, clock_id);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright 2025 NXP
|
||||
*/
|
||||
|
||||
BOOT_FROM SD
|
||||
SOC_TYPE IMX9
|
||||
CONTAINER
|
||||
IMAGE A55 bl31.bin 0x8a200000
|
||||
IMAGE A55 u-boot.bin CONFIG_TEXT_BASE
|
||||
@@ -0,0 +1,15 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright 2025 NXP
|
||||
*/
|
||||
|
||||
BOOT_FROM SD
|
||||
SOC_TYPE IMX9
|
||||
APPEND mx95a0-ahab-container.img
|
||||
CONTAINER
|
||||
IMAGE OEI m33-oei-ddrfw.bin 0x1ffc0000
|
||||
HOLD 0x10000
|
||||
IMAGE OEI oei-m33-tcm.bin 0x1ffc0000
|
||||
IMAGE M33 m33_image.bin 0x1ffc0000
|
||||
IMAGE A55 spl/u-boot-spl.bin 0x20480000
|
||||
DUMMY_V2X 0x8b000000
|
||||
@@ -0,0 +1,749 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2025 NXP
|
||||
*
|
||||
* Peng Fan <peng.fan@nxp.com>
|
||||
*/
|
||||
|
||||
#include <asm/arch/clock.h>
|
||||
#include <asm/arch/ddr.h>
|
||||
#include <asm/arch/sys_proto.h>
|
||||
#include <asm/armv8/mmu.h>
|
||||
#include <asm/mach-imx/boot_mode.h>
|
||||
#include <asm/mach-imx/ele_api.h>
|
||||
#include <asm/setup.h>
|
||||
#include <dm/uclass.h>
|
||||
#include <dm/device.h>
|
||||
#include <env_internal.h>
|
||||
#include <fuse.h>
|
||||
#include <imx_thermal.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <scmi_agent.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static rom_passover_t rom_passover_data = {0};
|
||||
|
||||
uint32_t scmi_get_rom_data(rom_passover_t *rom_data)
|
||||
{
|
||||
/* Read ROM passover data */
|
||||
struct scmi_rom_passover_get_out out;
|
||||
struct scmi_msg msg = {
|
||||
.protocol_id = SCMI_PROTOCOL_ID_IMX_MISC,
|
||||
.message_id = SCMI_MISC_ROM_PASSOVER_GET,
|
||||
.in_msg = (u8 *)NULL,
|
||||
.in_msg_sz = 0,
|
||||
.out_msg = (u8 *)&out,
|
||||
.out_msg_sz = sizeof(out),
|
||||
};
|
||||
int ret;
|
||||
struct udevice *dev;
|
||||
|
||||
ret = uclass_get_device_by_name(UCLASS_CLK, "protocol@14", &dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_scmi_process_msg(dev, &msg);
|
||||
if (ret == 0 && out.status == 0) {
|
||||
memcpy(rom_data, (struct rom_passover_t *)out.passover, sizeof(rom_passover_t));
|
||||
} else {
|
||||
printf("Failed to get ROM passover data, scmi_err = %d, size_of(out) = %ld\n",
|
||||
out.status, sizeof(out));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_ENV_IS_IN_MMC)
|
||||
__weak int board_mmc_get_env_dev(int devno)
|
||||
{
|
||||
return devno;
|
||||
}
|
||||
|
||||
int mmc_get_env_dev(void)
|
||||
{
|
||||
int ret;
|
||||
u16 boot_type;
|
||||
u8 boot_instance;
|
||||
|
||||
volatile gd_t *pgd = gd;
|
||||
rom_passover_t *rdata;
|
||||
|
||||
#if IS_ENABLED(CONFIG_XPL_BUILD)
|
||||
rdata = &rom_passover_data;
|
||||
#else
|
||||
rom_passover_t rom_data = {0};
|
||||
|
||||
if (!pgd->reloc_off)
|
||||
rdata = &rom_data;
|
||||
else
|
||||
rdata = &rom_passover_data;
|
||||
#endif
|
||||
if (rdata->tag == 0) {
|
||||
ret = scmi_get_rom_data(rdata);
|
||||
if (ret != 0) {
|
||||
puts("SCMI: failure at rom_boot_info\n");
|
||||
return CONFIG_SYS_MMC_ENV_DEV;
|
||||
}
|
||||
}
|
||||
boot_type = rdata->boot_dev_type;
|
||||
boot_instance = rdata->boot_dev_inst;
|
||||
set_gd(pgd);
|
||||
|
||||
debug("boot_type %d, instance %d\n", boot_type, boot_instance);
|
||||
|
||||
/* If not boot from sd/mmc, use default value */
|
||||
if (boot_type != BOOT_TYPE_SD && boot_type != BOOT_TYPE_MMC)
|
||||
return env_get_ulong("mmcdev", 10, CONFIG_SYS_MMC_ENV_DEV);
|
||||
|
||||
return board_mmc_get_env_dev(boot_instance);
|
||||
}
|
||||
#endif
|
||||
|
||||
u32 get_cpu_speed_grade_hz(void)
|
||||
{
|
||||
u32 speed, max_speed;
|
||||
int ret;
|
||||
u32 val, word, offset;
|
||||
|
||||
word = 17;
|
||||
offset = 14;
|
||||
|
||||
ret = fuse_read(word / 8, word % 8, &val);
|
||||
if (ret)
|
||||
val = 0; /* If read fuse failed, return as blank fuse */
|
||||
|
||||
val >>= offset;
|
||||
val &= 0xf;
|
||||
|
||||
max_speed = 2300000000;
|
||||
speed = max_speed - val * 100000000;
|
||||
|
||||
if (is_imx95())
|
||||
max_speed = 2000000000;
|
||||
|
||||
/* In case the fuse of speed grade not programmed */
|
||||
if (speed > max_speed)
|
||||
speed = max_speed;
|
||||
|
||||
return speed;
|
||||
}
|
||||
|
||||
u32 get_cpu_temp_grade(int *minc, int *maxc)
|
||||
{
|
||||
int ret;
|
||||
u32 val, word, offset;
|
||||
|
||||
word = 17;
|
||||
offset = 12;
|
||||
|
||||
ret = fuse_read(word / 8, word % 8, &val);
|
||||
if (ret)
|
||||
val = 0; /* If read fuse failed, return as blank fuse */
|
||||
|
||||
val >>= offset;
|
||||
val &= 0x3;
|
||||
|
||||
if (minc && maxc) {
|
||||
if (val == TEMP_AUTOMOTIVE) {
|
||||
*minc = -40;
|
||||
*maxc = 125;
|
||||
} else if (val == TEMP_INDUSTRIAL) {
|
||||
*minc = -40;
|
||||
*maxc = 105;
|
||||
} else if (val == TEMP_EXTCOMMERCIAL) {
|
||||
*minc = -20;
|
||||
*maxc = 105;
|
||||
} else {
|
||||
*minc = 0;
|
||||
*maxc = 95;
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static void set_cpu_info(struct ele_get_info_data *info)
|
||||
{
|
||||
gd->arch.soc_rev = info->soc;
|
||||
gd->arch.lifecycle = info->lc;
|
||||
memcpy((void *)&gd->arch.uid, &info->uid, 4 * sizeof(u32));
|
||||
}
|
||||
|
||||
u32 get_cpu_rev(void)
|
||||
{
|
||||
u32 rev = (gd->arch.soc_rev >> 24) - 0xa0;
|
||||
|
||||
return (MXC_CPU_IMX95 << 12) | (CHIP_REV_1_0 + rev);
|
||||
}
|
||||
|
||||
#define UNLOCK_WORD 0xD928C520
|
||||
#define REFRESH_WORD 0xB480A602
|
||||
|
||||
static void disable_wdog(void __iomem *wdog_base)
|
||||
{
|
||||
u32 val_cs = readl(wdog_base + 0x00);
|
||||
int ret = 0;
|
||||
|
||||
if (!(val_cs & 0x80))
|
||||
return;
|
||||
|
||||
/* default is 32bits cmd */
|
||||
writel(REFRESH_WORD, (wdog_base + 0x04)); /* Refresh the CNT */
|
||||
|
||||
if (!(val_cs & 0x800)) {
|
||||
writel(UNLOCK_WORD, (wdog_base + 0x04));
|
||||
while (!(readl(wdog_base + 0x00) & 0x800))
|
||||
;
|
||||
}
|
||||
writel(0x0, (wdog_base + 0x0C)); /* Set WIN to 0 */
|
||||
writel(0x400, (wdog_base + 0x08)); /* Set timeout to default 0x400 */
|
||||
writel(0x2120, (wdog_base + 0x00)); /* Disable it and set update */
|
||||
|
||||
ret = readl_poll_timeout(wdog_base, val_cs, val_cs & 0x400, 100000);
|
||||
if (ret < 0)
|
||||
debug("%s timeout\n", __func__);
|
||||
}
|
||||
|
||||
static struct mm_region imx9_mem_map[] = {
|
||||
{
|
||||
/* M7 TCM */
|
||||
.virt = 0x203c0000UL,
|
||||
.phys = 0x203c0000UL,
|
||||
.size = 0x80000UL,
|
||||
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
|
||||
PTE_BLOCK_NON_SHARE |
|
||||
PTE_BLOCK_PXN | PTE_BLOCK_UXN
|
||||
}, {
|
||||
/* OCRAM */
|
||||
.virt = 0x20480000UL,
|
||||
.phys = 0x20480000UL,
|
||||
.size = 0xA0000UL,
|
||||
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
|
||||
PTE_BLOCK_OUTER_SHARE
|
||||
}, {
|
||||
/* AIPS */
|
||||
.virt = 0x40000000UL,
|
||||
.phys = 0x40000000UL,
|
||||
.size = 0x40000000UL,
|
||||
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
|
||||
PTE_BLOCK_NON_SHARE |
|
||||
PTE_BLOCK_PXN | PTE_BLOCK_UXN
|
||||
}, {
|
||||
/* Flexible Serial Peripheral Interface */
|
||||
.virt = 0x28000000UL,
|
||||
.phys = 0x28000000UL,
|
||||
.size = 0x8000000UL,
|
||||
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
|
||||
PTE_BLOCK_NON_SHARE |
|
||||
PTE_BLOCK_PXN | PTE_BLOCK_UXN
|
||||
}, {
|
||||
/* DRAM1 */
|
||||
.virt = PHYS_SDRAM,
|
||||
.phys = PHYS_SDRAM,
|
||||
.size = PHYS_SDRAM_SIZE,
|
||||
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
|
||||
PTE_BLOCK_OUTER_SHARE
|
||||
}, {
|
||||
#ifdef PHYS_SDRAM_2_SIZE
|
||||
/* DRAM2 */
|
||||
.virt = 0x100000000UL,
|
||||
.phys = 0x100000000UL,
|
||||
.size = PHYS_SDRAM_2_SIZE,
|
||||
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
|
||||
PTE_BLOCK_OUTER_SHARE
|
||||
}, {
|
||||
#endif
|
||||
/* empty entry to split table entry 5 if needed when TEEs are used */
|
||||
0,
|
||||
}, {
|
||||
/* List terminator */
|
||||
0,
|
||||
}
|
||||
};
|
||||
|
||||
struct mm_region *mem_map = imx9_mem_map;
|
||||
|
||||
static unsigned int imx9_find_dram_entry_in_mem_map(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(imx9_mem_map); i++)
|
||||
if (imx9_mem_map[i].phys == CFG_SYS_SDRAM_BASE)
|
||||
return i;
|
||||
|
||||
hang(); /* Entry not found, this must never happen. */
|
||||
}
|
||||
|
||||
void enable_caches(void)
|
||||
{
|
||||
/* If OPTEE runs, remove OPTEE memory from MMU table to avoid speculative prefetch
|
||||
* If OPTEE does not run, still update the MMU table according to dram banks structure
|
||||
* to set correct dram size from board_phys_sdram_size
|
||||
*/
|
||||
int i = 0;
|
||||
/*
|
||||
* please make sure that entry initial value matches
|
||||
* imx9_mem_map for DRAM1
|
||||
*/
|
||||
int entry = imx9_find_dram_entry_in_mem_map();
|
||||
u64 attrs = imx9_mem_map[entry].attrs;
|
||||
|
||||
while (i < CONFIG_NR_DRAM_BANKS &&
|
||||
entry < ARRAY_SIZE(imx9_mem_map)) {
|
||||
if (gd->bd->bi_dram[i].start == 0)
|
||||
break;
|
||||
imx9_mem_map[entry].phys = gd->bd->bi_dram[i].start;
|
||||
imx9_mem_map[entry].virt = gd->bd->bi_dram[i].start;
|
||||
imx9_mem_map[entry].size = gd->bd->bi_dram[i].size;
|
||||
imx9_mem_map[entry].attrs = attrs;
|
||||
debug("Added memory mapping (%d): %llx %llx\n", entry,
|
||||
imx9_mem_map[entry].phys, imx9_mem_map[entry].size);
|
||||
i++; entry++;
|
||||
}
|
||||
|
||||
icache_enable();
|
||||
dcache_enable();
|
||||
}
|
||||
|
||||
__weak int board_phys_sdram_size(phys_size_t *size)
|
||||
{
|
||||
phys_size_t start, end;
|
||||
phys_size_t val;
|
||||
|
||||
if (!size)
|
||||
return -EINVAL;
|
||||
|
||||
val = readl(REG_DDR_CS0_BNDS);
|
||||
start = (val >> 16) << 24;
|
||||
end = (val & 0xFFFF);
|
||||
end = end ? end + 1 : 0;
|
||||
end = end << 24;
|
||||
*size = end - start;
|
||||
|
||||
val = readl(REG_DDR_CS1_BNDS);
|
||||
start = (val >> 16) << 24;
|
||||
end = (val & 0xFFFF);
|
||||
end = end ? end + 1 : 0;
|
||||
end = end << 24;
|
||||
*size += end - start;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dram_init(void)
|
||||
{
|
||||
phys_size_t sdram_size;
|
||||
int ret;
|
||||
|
||||
ret = board_phys_sdram_size(&sdram_size);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* rom_pointer[1] contains the size of TEE occupies */
|
||||
if (rom_pointer[1] && PHYS_SDRAM < (phys_addr_t)rom_pointer[0])
|
||||
gd->ram_size = sdram_size - rom_pointer[1];
|
||||
else
|
||||
gd->ram_size = sdram_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dram_init_banksize(void)
|
||||
{
|
||||
int bank = 0;
|
||||
int ret;
|
||||
phys_size_t sdram_size;
|
||||
phys_size_t sdram_b1_size, sdram_b2_size;
|
||||
|
||||
ret = board_phys_sdram_size(&sdram_size);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Bank 1 can't cross over 4GB space */
|
||||
if (sdram_size > 0x80000000) {
|
||||
sdram_b1_size = 0x100000000UL - PHYS_SDRAM;
|
||||
sdram_b2_size = sdram_size - sdram_b1_size;
|
||||
} else {
|
||||
sdram_b1_size = sdram_size;
|
||||
sdram_b2_size = 0;
|
||||
}
|
||||
|
||||
gd->bd->bi_dram[bank].start = PHYS_SDRAM;
|
||||
if (rom_pointer[1] && PHYS_SDRAM < (phys_addr_t)rom_pointer[0]) {
|
||||
phys_addr_t optee_start = (phys_addr_t)rom_pointer[0];
|
||||
phys_size_t optee_size = (size_t)rom_pointer[1];
|
||||
|
||||
gd->bd->bi_dram[bank].size = optee_start - gd->bd->bi_dram[bank].start;
|
||||
if ((optee_start + optee_size) < (PHYS_SDRAM + sdram_b1_size)) {
|
||||
if (++bank >= CONFIG_NR_DRAM_BANKS) {
|
||||
puts("CONFIG_NR_DRAM_BANKS is not enough\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
gd->bd->bi_dram[bank].start = optee_start + optee_size;
|
||||
gd->bd->bi_dram[bank].size = PHYS_SDRAM +
|
||||
sdram_b1_size - gd->bd->bi_dram[bank].start;
|
||||
}
|
||||
} else {
|
||||
gd->bd->bi_dram[bank].size = sdram_b1_size;
|
||||
}
|
||||
|
||||
if (sdram_b2_size) {
|
||||
if (++bank >= CONFIG_NR_DRAM_BANKS) {
|
||||
puts("CONFIG_NR_DRAM_BANKS is not enough for SDRAM_2\n");
|
||||
return -1;
|
||||
}
|
||||
gd->bd->bi_dram[bank].start = 0x100000000UL;
|
||||
gd->bd->bi_dram[bank].size = sdram_b2_size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
phys_size_t get_effective_memsize(void)
|
||||
{
|
||||
int ret;
|
||||
phys_size_t sdram_size;
|
||||
phys_size_t sdram_b1_size;
|
||||
|
||||
ret = board_phys_sdram_size(&sdram_size);
|
||||
if (!ret) {
|
||||
/* Bank 1 can't cross over 4GB space */
|
||||
if (sdram_size > 0x80000000)
|
||||
sdram_b1_size = 0x100000000UL - PHYS_SDRAM;
|
||||
else
|
||||
sdram_b1_size = sdram_size;
|
||||
|
||||
if (rom_pointer[1]) {
|
||||
/* We will relocate u-boot to Top of dram1. Tee position has three cases:
|
||||
* 1. At the top of dram1, Then return the size removed optee size.
|
||||
* 2. In the middle of dram1, return the size of dram1.
|
||||
* 3. Not in the scope of dram1, return the size of dram1.
|
||||
*/
|
||||
if ((rom_pointer[0] + rom_pointer[1]) == (PHYS_SDRAM + sdram_b1_size))
|
||||
return ((phys_addr_t)rom_pointer[0] - PHYS_SDRAM);
|
||||
}
|
||||
|
||||
return sdram_b1_size;
|
||||
} else {
|
||||
return PHYS_SDRAM_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
|
||||
{
|
||||
u32 val[2] = {};
|
||||
int ret, num_of_macs;
|
||||
|
||||
ret = fuse_read(40, 5, &val[0]);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = fuse_read(40, 6, &val[1]);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
num_of_macs = (val[1] >> 24) & 0xff;
|
||||
if (num_of_macs <= (dev_id * 3)) {
|
||||
printf("WARNING: no MAC address assigned for MAC%d\n", dev_id);
|
||||
goto err;
|
||||
}
|
||||
|
||||
mac[0] = val[0] & 0xff;
|
||||
mac[1] = (val[0] >> 8) & 0xff;
|
||||
mac[2] = (val[0] >> 16) & 0xff;
|
||||
mac[3] = (val[0] >> 24) & 0xff;
|
||||
mac[4] = val[1] & 0xff;
|
||||
mac[5] = (val[1] >> 8) & 0xff;
|
||||
if (dev_id == 1)
|
||||
mac[5] = mac[5] + 3;
|
||||
if (dev_id == 2)
|
||||
mac[5] = mac[5] + 6;
|
||||
|
||||
debug("%s: MAC%d: %pM\n", __func__, dev_id, mac);
|
||||
return;
|
||||
err:
|
||||
memset(mac, 0, 6);
|
||||
printf("%s: fuse read err: %d\n", __func__, ret);
|
||||
}
|
||||
|
||||
const char *get_imx_type(u32 imxtype)
|
||||
{
|
||||
switch (imxtype) {
|
||||
case MXC_CPU_IMX95:
|
||||
return "95";/* iMX95 FULL */
|
||||
default:
|
||||
return "??";
|
||||
}
|
||||
}
|
||||
|
||||
void build_info(void)
|
||||
{
|
||||
u32 fw_version, sha1, res = 0, status;
|
||||
int ret;
|
||||
|
||||
printf("\nBuildInfo:\n");
|
||||
|
||||
ret = ele_get_fw_status(&status, &res);
|
||||
if (ret) {
|
||||
printf(" - ELE firmware status failed %d, 0x%x\n", ret, res);
|
||||
} else if ((status & 0xff) == 1) {
|
||||
ret = ele_get_fw_version(&fw_version, &sha1, &res);
|
||||
if (ret) {
|
||||
printf(" - ELE firmware version failed %d, 0x%x\n", ret, res);
|
||||
} else {
|
||||
printf(" - ELE firmware version %u.%u.%u-%x",
|
||||
(fw_version & (0x00ff0000)) >> 16,
|
||||
(fw_version & (0x0000fff0)) >> 4,
|
||||
(fw_version & (0x0000000f)), sha1);
|
||||
((fw_version & (0x80000000)) >> 31) == 1 ? puts("-dirty\n") : puts("\n");
|
||||
}
|
||||
} else {
|
||||
printf(" - ELE firmware not included\n");
|
||||
}
|
||||
puts("\n");
|
||||
}
|
||||
|
||||
int arch_misc_init(void)
|
||||
{
|
||||
build_info();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_OF_BOARD_FIXUP) && !defined(CONFIG_SPL_BUILD)
|
||||
int board_fix_fdt(void *fdt)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int ft_system_setup(void *blob, struct bd_info *bd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG)
|
||||
void get_board_serial(struct tag_serialnr *serialnr)
|
||||
{
|
||||
printf("UID: %08x%08x%08x%08x\n", __be32_to_cpu(gd->arch.uid[0]),
|
||||
__be32_to_cpu(gd->arch.uid[1]), __be32_to_cpu(gd->arch.uid[2]),
|
||||
__be32_to_cpu(gd->arch.uid[3]));
|
||||
|
||||
serialnr->low = __be32_to_cpu(gd->arch.uid[1]);
|
||||
serialnr->high = __be32_to_cpu(gd->arch.uid[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void gpio_reset(ulong gpio_base)
|
||||
{
|
||||
writel(0, gpio_base + 0x10);
|
||||
writel(0, gpio_base + 0x14);
|
||||
writel(0, gpio_base + 0x18);
|
||||
writel(0, gpio_base + 0x1c);
|
||||
}
|
||||
|
||||
int arch_cpu_init(void)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_SPL_BUILD)) {
|
||||
disable_wdog((void __iomem *)WDG3_BASE_ADDR);
|
||||
disable_wdog((void __iomem *)WDG4_BASE_ADDR);
|
||||
|
||||
gpio_reset(GPIO2_BASE_ADDR);
|
||||
gpio_reset(GPIO3_BASE_ADDR);
|
||||
gpio_reset(GPIO4_BASE_ADDR);
|
||||
gpio_reset(GPIO5_BASE_ADDR);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int imx9_probe_mu(void)
|
||||
{
|
||||
struct udevice *dev;
|
||||
int ret;
|
||||
u32 res;
|
||||
struct ele_get_info_data info;
|
||||
|
||||
ret = uclass_get_device_by_driver(UCLASS_SCMI_AGENT, DM_DRIVER_GET(scmi_mbox), &dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = uclass_get_device_by_name(UCLASS_CLK, "protocol@14", &dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_scmi_of_get_channel(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = uclass_get_device_by_name(UCLASS_PINCTRL, "protocol@19", &dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
#if defined(CONFIG_SPL_BUILD)
|
||||
ret = uclass_get_device_by_name(UCLASS_MISC, "mailbox@47530000", &dev);
|
||||
#else
|
||||
ret = uclass_get_device_by_name(UCLASS_MISC, "mailbox@47550000", &dev);
|
||||
#endif
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (gd->flags & GD_FLG_RELOC)
|
||||
return 0;
|
||||
|
||||
ret = ele_get_info(&info, &res);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
set_cpu_info(&info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EVENT_SPY_SIMPLE(EVT_DM_POST_INIT_F, imx9_probe_mu);
|
||||
EVENT_SPY_SIMPLE(EVT_DM_POST_INIT_R, imx9_probe_mu);
|
||||
|
||||
int timer_init(void)
|
||||
{
|
||||
gd->arch.tbl = 0;
|
||||
gd->arch.tbu = 0;
|
||||
|
||||
if (IS_ENABLED(CONFIG_SPL_BUILD)) {
|
||||
unsigned long freq = 24000000;
|
||||
|
||||
asm volatile("msr cntfrq_el0, %0" : : "r" (freq) : "memory");
|
||||
|
||||
/* Clear the compare frame interrupt */
|
||||
unsigned long sctr_cmpcr_addr = SYSCNT_CMP_BASE_ADDR + 0x2c;
|
||||
unsigned long sctr_cmpcr = readl(sctr_cmpcr_addr);
|
||||
|
||||
sctr_cmpcr &= ~0x1;
|
||||
writel(sctr_cmpcr, sctr_cmpcr_addr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum env_location env_get_location(enum env_operation op, int prio)
|
||||
{
|
||||
enum boot_device dev = get_boot_device();
|
||||
enum env_location env_loc = ENVL_UNKNOWN;
|
||||
|
||||
if (prio)
|
||||
return env_loc;
|
||||
|
||||
switch (dev) {
|
||||
case QSPI_BOOT:
|
||||
env_loc = ENVL_SPI_FLASH;
|
||||
break;
|
||||
case SD1_BOOT:
|
||||
case SD2_BOOT:
|
||||
case SD3_BOOT:
|
||||
case MMC1_BOOT:
|
||||
case MMC2_BOOT:
|
||||
case MMC3_BOOT:
|
||||
env_loc = ENVL_MMC;
|
||||
break;
|
||||
default:
|
||||
env_loc = ENVL_NOWHERE;
|
||||
break;
|
||||
}
|
||||
|
||||
return env_loc;
|
||||
}
|
||||
|
||||
enum imx9_soc_voltage_mode soc_target_voltage_mode(void)
|
||||
{
|
||||
u32 speed = get_cpu_speed_grade_hz();
|
||||
enum imx9_soc_voltage_mode voltage = VOLT_OVER_DRIVE;
|
||||
|
||||
if (is_imx95()) {
|
||||
if (speed == 2000000000)
|
||||
voltage = VOLT_SUPER_OVER_DRIVE;
|
||||
else if (speed == 1800000000)
|
||||
voltage = VOLT_OVER_DRIVE;
|
||||
else if (speed == 1400000000)
|
||||
voltage = VOLT_NOMINAL_DRIVE;
|
||||
else /* boot not support low drive mode according to AS */
|
||||
printf("Unexpected A55 freq %u, default to OD\n", speed);
|
||||
}
|
||||
|
||||
return voltage;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_SCMI_FIRMWARE)
|
||||
enum boot_device get_boot_device(void)
|
||||
{
|
||||
volatile gd_t *pgd = gd;
|
||||
int ret;
|
||||
u16 boot_type;
|
||||
u8 boot_instance;
|
||||
enum boot_device boot_dev = 0;
|
||||
rom_passover_t *rdata;
|
||||
|
||||
#if IS_ENABLED(CONFIG_SPL_BUILD)
|
||||
rdata = &rom_passover_data;
|
||||
#else
|
||||
rom_passover_t rom_data = {0};
|
||||
|
||||
if (pgd->reloc_off == 0)
|
||||
rdata = &rom_data;
|
||||
else
|
||||
rdata = &rom_passover_data;
|
||||
#endif
|
||||
if (rdata->tag == 0) {
|
||||
ret = scmi_get_rom_data(rdata);
|
||||
if (ret != 0) {
|
||||
puts("SCMI: failure at rom_boot_info\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
boot_type = rdata->boot_dev_type;
|
||||
boot_instance = rdata->boot_dev_inst;
|
||||
|
||||
set_gd(pgd);
|
||||
|
||||
switch (boot_type) {
|
||||
case BT_DEV_TYPE_SD:
|
||||
boot_dev = boot_instance + SD1_BOOT;
|
||||
break;
|
||||
case BT_DEV_TYPE_MMC:
|
||||
boot_dev = boot_instance + MMC1_BOOT;
|
||||
break;
|
||||
case BT_DEV_TYPE_NAND:
|
||||
boot_dev = NAND_BOOT;
|
||||
break;
|
||||
case BT_DEV_TYPE_FLEXSPINOR:
|
||||
boot_dev = QSPI_BOOT;
|
||||
break;
|
||||
case BT_DEV_TYPE_USB:
|
||||
boot_dev = boot_instance + USB_BOOT;
|
||||
if (IS_ENABLED(CONFIG_IMX95))
|
||||
boot_dev -= 3; //iMX95 usb instance start at 3
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return boot_dev;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool arch_check_dst_in_secure(void *start, ulong size)
|
||||
{
|
||||
ulong ns_end = CFG_SYS_SDRAM_BASE + PHYS_SDRAM_SIZE;
|
||||
#ifdef PHYS_SDRAM_2_SIZE
|
||||
ns_end += PHYS_SDRAM_2_SIZE;
|
||||
#endif
|
||||
|
||||
if ((ulong)start < CFG_SYS_SDRAM_BASE || (ulong)start + size > ns_end)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void *arch_get_container_trampoline(void)
|
||||
{
|
||||
return (void *)((ulong)CFG_SYS_SDRAM_BASE + PHYS_SDRAM_SIZE - SZ_16M);
|
||||
}
|
||||
@@ -27,10 +27,12 @@ struct sandbox_scmi_pwd {
|
||||
* @id: Identifier of the clock used in the SCMI protocol
|
||||
* @enabled: Clock state: true if enabled, false if disabled
|
||||
* @rate: Clock rate in Hertz
|
||||
* @perm: Indicating state/parent/rate permission
|
||||
*/
|
||||
struct sandbox_scmi_clk {
|
||||
bool enabled;
|
||||
ulong rate;
|
||||
u32 perm;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -108,7 +110,7 @@ struct sandbox_scmi_devices {
|
||||
size_t regul_count;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SCMI_FIRMWARE
|
||||
#if IS_ENABLED(CONFIG_SCMI_FIRMWARE)
|
||||
/**
|
||||
* sandbox_scmi_channel_id - Get the channel id
|
||||
* @dev: Reference to the SCMI protocol device
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
if TARGET_IMX95_19X19_EVK
|
||||
|
||||
config SYS_BOARD
|
||||
default "imx95_evk"
|
||||
|
||||
config SYS_VENDOR
|
||||
default "freescale"
|
||||
|
||||
config SYS_CONFIG_NAME
|
||||
default "imx95_evk"
|
||||
|
||||
endif
|
||||
@@ -0,0 +1,6 @@
|
||||
i.MX95 EVK BOARD
|
||||
M: Alice Guo <alice.guo@nxp.com>
|
||||
S: Maintained
|
||||
F: board/freescale/imx95_evk/
|
||||
F: include/configs/imx95_evk.h
|
||||
F: configs/imx95_19x19_evk_defconfig
|
||||
@@ -0,0 +1,11 @@
|
||||
#
|
||||
# Copyright 2025 NXP
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
obj-y += imx95_evk.o
|
||||
|
||||
ifdef CONFIG_SPL_BUILD
|
||||
obj-y += spl.o
|
||||
endif
|
||||
@@ -0,0 +1,91 @@
|
||||
sec_boot=no
|
||||
initrd_addr=0x93800000
|
||||
emmc_dev=0
|
||||
sd_dev=1
|
||||
scriptaddr=0x93500000
|
||||
kernel_addr_r=CONFIG_SYS_LOAD_ADDR
|
||||
image=Image
|
||||
splashimage=0xA0000000
|
||||
console=ttyLP0,115200 earlycon
|
||||
fdt_addr_r=0x93000000
|
||||
fdt_addr=0x93000000
|
||||
cntr_addr=0xA8000000
|
||||
cntr_file=os_cntr_signed.bin
|
||||
boot_fit=no
|
||||
fdtfile=CONFIG_DEFAULT_FDT_FILE
|
||||
bootm_size=0x10000000
|
||||
mmcdev=CONFIG_SYS_MMC_ENV_DEV
|
||||
mmcautodetect=yes
|
||||
mmcargs=setenv bootargs console=${console} root=${mmcroot}
|
||||
loadbootscript=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};
|
||||
bootscript=echo Running bootscript from mmc ...; source
|
||||
loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}
|
||||
loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr_r} ${fdtfile}
|
||||
loadcntr=fatload mmc ${mmcdev}:${mmcpart} ${cntr_addr} ${cntr_file}
|
||||
auth_os=auth_cntr ${cntr_addr}
|
||||
boot_os=booti ${loadaddr} - ${fdt_addr_r};
|
||||
mmcboot=echo Booting from mmc ...;
|
||||
run mmcargs;
|
||||
if test ${sec_boot} = yes; then
|
||||
if run auth_os; then
|
||||
run boot_os;
|
||||
else
|
||||
echo ERR: failed to authenticate;
|
||||
fi;
|
||||
else
|
||||
if test ${boot_fit} = yes || test ${boot_fit} = try; then
|
||||
bootm ${loadaddr};
|
||||
else
|
||||
if run loadfdt; then
|
||||
run boot_os;
|
||||
else
|
||||
echo WARN: Cannot load the DT;
|
||||
fi;
|
||||
fi;
|
||||
fi;
|
||||
netargs=setenv bootargs console=${console} root=/dev/nfs
|
||||
ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp
|
||||
netboot=echo Booting from net ...;
|
||||
run netargs;
|
||||
if test ${ip_dyn} = yes; then
|
||||
setenv get_cmd dhcp;
|
||||
else
|
||||
setenv get_cmd tftp;
|
||||
fi;
|
||||
if test ${sec_boot} = yes; then
|
||||
${get_cmd} ${cntr_addr} ${cntr_file};
|
||||
if run auth_os; then
|
||||
run boot_os;
|
||||
else
|
||||
echo ERR: failed to authenticate;
|
||||
fi;
|
||||
else
|
||||
${get_cmd} ${loadaddr} ${image};
|
||||
if test ${boot_fit} = yes || test ${boot_fit} = try; then
|
||||
bootm ${loadaddr};
|
||||
else
|
||||
if ${get_cmd} ${fdt_addr_r} ${fdtfile}; then
|
||||
run boot_os;
|
||||
else
|
||||
echo WARN: Cannot load the DT;
|
||||
fi;
|
||||
fi;
|
||||
fi;
|
||||
bsp_bootcmd=echo Running BSP bootcmd ...;
|
||||
mmc dev ${mmcdev}; if mmc rescan; then
|
||||
if run loadbootscript; then
|
||||
run bootscript;
|
||||
else
|
||||
if test ${sec_boot} = yes; then
|
||||
if run loadcntr; then
|
||||
run mmcboot;
|
||||
else run netboot;
|
||||
fi;
|
||||
else
|
||||
if run loadimage; then
|
||||
run mmcboot;
|
||||
else run netboot;
|
||||
fi;
|
||||
fi;
|
||||
fi;
|
||||
fi;
|
||||
@@ -0,0 +1,36 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2025 NXP
|
||||
*/
|
||||
|
||||
#include <asm/arch/clock.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/mach-imx/sys_proto.h>
|
||||
|
||||
int board_early_init_f(void)
|
||||
{
|
||||
/* UART1: A55, UART2: M33, UART3: M7 */
|
||||
init_uart_clk(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int board_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int board_late_init(void)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_ENV_IS_IN_MMC))
|
||||
board_late_mmc_env_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int board_phys_sdram_size(phys_size_t *size)
|
||||
{
|
||||
*size = PHYS_SDRAM_SIZE + PHYS_SDRAM_2_SIZE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2025 NXP
|
||||
*/
|
||||
|
||||
#include <asm/arch/clock.h>
|
||||
#include <asm/arch/mu.h>
|
||||
#include <asm/mach-imx/boot_mode.h>
|
||||
#include <asm/sections.h>
|
||||
#include <hang.h>
|
||||
#include <init.h>
|
||||
#include <spl.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
int spl_board_boot_device(enum boot_device boot_dev_spl)
|
||||
{
|
||||
switch (boot_dev_spl) {
|
||||
case SD1_BOOT:
|
||||
case MMC1_BOOT:
|
||||
return BOOT_DEVICE_MMC1;
|
||||
case SD2_BOOT:
|
||||
case MMC2_BOOT:
|
||||
return BOOT_DEVICE_MMC2;
|
||||
case USB_BOOT:
|
||||
return BOOT_DEVICE_BOARD;
|
||||
default:
|
||||
return BOOT_DEVICE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
void spl_board_init(void)
|
||||
{
|
||||
puts("Normal Boot\n");
|
||||
}
|
||||
|
||||
void board_init_f(ulong dummy)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Clear the BSS. */
|
||||
memset(__bss_start, 0, __bss_end - __bss_start);
|
||||
|
||||
#ifdef CONFIG_SPL_RECOVER_DATA_SECTION
|
||||
if (IS_ENABLED(CONFIG_SPL_BUILD))
|
||||
spl_save_restore_data();
|
||||
#endif
|
||||
|
||||
timer_init();
|
||||
|
||||
/* Need dm_init() to run before any SCMI calls can be made. */
|
||||
spl_early_init();
|
||||
|
||||
/* Need enable SCMI drivers and ELE driver before enabling console */
|
||||
ret = imx9_probe_mu();
|
||||
if (ret)
|
||||
hang(); /* if MU not probed, nothing can output, just hang here */
|
||||
|
||||
arch_cpu_init();
|
||||
|
||||
board_early_init_f();
|
||||
|
||||
preloader_console_init();
|
||||
|
||||
debug("SOC: 0x%x\n", gd->arch.soc_rev);
|
||||
debug("LC: 0x%x\n", gd->arch.lifecycle);
|
||||
|
||||
board_init_r(NULL, 0);
|
||||
}
|
||||
@@ -363,6 +363,12 @@ config SPL_LOAD_IMX_CONTAINER
|
||||
Support booting U-Boot from an i.MX8 container image. If you are not
|
||||
using i.MX8, say 'n'.
|
||||
|
||||
config SPL_IMX_CONTAINER_USE_TRAMPOLINE
|
||||
bool
|
||||
depends on SPL
|
||||
help
|
||||
Enable SPL load reader to load data to a trampoline buffer.
|
||||
|
||||
config IMX_CONTAINER_CFG
|
||||
string "i.MX8 Container config file"
|
||||
depends on SPL && SPL_LOAD_IMX_CONTAINER
|
||||
|
||||
@@ -14,6 +14,16 @@
|
||||
#include <asm/mach-imx/ahab.h>
|
||||
#endif
|
||||
|
||||
__weak bool arch_check_dst_in_secure(void *start, ulong size)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
__weak void *arch_get_container_trampoline(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct boot_img_t *read_auth_image(struct spl_image_info *spl_image,
|
||||
struct spl_load_info *info,
|
||||
struct container_hdr *container,
|
||||
@@ -22,6 +32,7 @@ static struct boot_img_t *read_auth_image(struct spl_image_info *spl_image,
|
||||
{
|
||||
struct boot_img_t *images;
|
||||
ulong offset, overhead, size;
|
||||
void *buf, *trampoline;
|
||||
|
||||
if (image_index > container->num_images) {
|
||||
debug("Invalid image number\n");
|
||||
@@ -42,12 +53,27 @@ static struct boot_img_t *read_auth_image(struct spl_image_info *spl_image,
|
||||
|
||||
debug("%s: container: %p offset: %lu size: %lu\n", __func__,
|
||||
container, offset, size);
|
||||
if (info->read(info, offset, size,
|
||||
map_sysmem(images[image_index].dst - overhead,
|
||||
images[image_index].size)) <
|
||||
images[image_index].size) {
|
||||
printf("%s wrong\n", __func__);
|
||||
return NULL;
|
||||
|
||||
buf = map_sysmem(images[image_index].dst - overhead, images[image_index].size);
|
||||
if (IS_ENABLED(CONFIG_SPL_IMX_CONTAINER_USE_TRAMPOLINE) &&
|
||||
arch_check_dst_in_secure(buf, size)) {
|
||||
trampoline = arch_get_container_trampoline();
|
||||
if (!trampoline) {
|
||||
printf("%s: trampoline size is zero\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (info->read(info, offset, size, trampoline) < images[image_index].size) {
|
||||
printf("%s: failed to load image to a trampoline buffer\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(buf, trampoline, images[image_index].size);
|
||||
} else {
|
||||
if (info->read(info, offset, size, buf) < images[image_index].size) {
|
||||
printf("%s: failed to load image to a non-secure region\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_AHAB_BOOT
|
||||
|
||||
@@ -24,6 +24,7 @@ CONFIG_SPL_BSS_MAX_SIZE=0x2000
|
||||
CONFIG_SYS_BOOTM_LEN=0x800000
|
||||
CONFIG_SYS_LOAD_ADDR=0x40480000
|
||||
CONFIG_SPL=y
|
||||
CONFIG_IMX_BOOTAUX=y
|
||||
CONFIG_FIT=y
|
||||
CONFIG_FIT_EXTERNAL_OFFSET=0x3000
|
||||
CONFIG_SPL_LOAD_FIT=y
|
||||
|
||||
@@ -29,6 +29,7 @@ CONFIG_SPL=y
|
||||
CONFIG_SPL_IMX_ROMAPI_LOADADDR=0x48000000
|
||||
CONFIG_SYS_MEMTEST_START=0x40000000
|
||||
CONFIG_SYS_MEMTEST_END=0x44000000
|
||||
CONFIG_IMX_BOOTAUX=y
|
||||
CONFIG_REMAKE_ELF=y
|
||||
CONFIG_FIT=y
|
||||
CONFIG_FIT_EXTERNAL_OFFSET=0x3000
|
||||
|
||||
@@ -33,6 +33,7 @@ CONFIG_ARMV8_SET_SMPEN=y
|
||||
CONFIG_ARMV8_EA_EL3_FIRST=y
|
||||
CONFIG_SPL_IMX_ROMAPI_LOADADDR=0x48000000
|
||||
CONFIG_PCI=y
|
||||
CONFIG_IMX_BOOTAUX=y
|
||||
# CONFIG_ANDROID_BOOT_IMAGE is not set
|
||||
CONFIG_FIT=y
|
||||
CONFIG_FIT_EXTERNAL_OFFSET=0x3000
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
CONFIG_ARM=y
|
||||
CONFIG_ARCH_IMX9=y
|
||||
CONFIG_TEXT_BASE=0x90200000
|
||||
CONFIG_SYS_MALLOC_LEN=0x2000000
|
||||
CONFIG_SYS_MALLOC_F_LEN=0x10000
|
||||
CONFIG_SPL_GPIO=y
|
||||
CONFIG_SPL_LIBCOMMON_SUPPORT=y
|
||||
CONFIG_SPL_LIBGENERIC_SUPPORT=y
|
||||
CONFIG_NR_DRAM_BANKS=3
|
||||
CONFIG_ENV_SOURCE_FILE="imx95_19x19_evk"
|
||||
CONFIG_SF_DEFAULT_SPEED=40000000
|
||||
CONFIG_ENV_SIZE=0x4000
|
||||
CONFIG_ENV_OFFSET=0x700000
|
||||
CONFIG_IMX_CONFIG="arch/arm/mach-imx/imx9/scmi/imximage.cfg"
|
||||
CONFIG_DM_GPIO=y
|
||||
CONFIG_DEFAULT_DEVICE_TREE="freescale/imx95-19x19-evk"
|
||||
CONFIG_TARGET_IMX95_19X19_EVK=y
|
||||
CONFIG_OF_LIBFDT_OVERLAY=y
|
||||
CONFIG_SYS_MONITOR_LEN=524288
|
||||
CONFIG_SPL_MMC=y
|
||||
CONFIG_SPL_SERIAL=y
|
||||
CONFIG_SPL_DRIVERS_MISC=y
|
||||
CONFIG_SPL_STACK=0x204d6000
|
||||
CONFIG_SPL_TEXT_BASE=0x20480000
|
||||
CONFIG_SPL_HAS_BSS_LINKER_SECTION=y
|
||||
CONFIG_SPL_BSS_START_ADDR=0x204d6000
|
||||
CONFIG_SPL_BSS_MAX_SIZE=0x2000
|
||||
CONFIG_SYS_LOAD_ADDR=0x90400000
|
||||
CONFIG_SPL=y
|
||||
CONFIG_SPL_RECOVER_DATA_SECTION=y
|
||||
CONFIG_PCI=y
|
||||
CONFIG_SYS_MEMTEST_START=0x90000000
|
||||
CONFIG_SYS_MEMTEST_END=0xA0000000
|
||||
CONFIG_REMAKE_ELF=y
|
||||
CONFIG_FIT=y
|
||||
CONFIG_FIT_VERBOSE=y
|
||||
CONFIG_OF_SYSTEM_SETUP=y
|
||||
CONFIG_BOOTCOMMAND="bootflow scan -l; run bsp_bootcmd"
|
||||
CONFIG_DEFAULT_FDT_FILE="imx95-19x19-evk.dtb"
|
||||
CONFIG_SYS_CBSIZE=2048
|
||||
CONFIG_SYS_PBSIZE=2074
|
||||
CONFIG_ARCH_MISC_INIT=y
|
||||
CONFIG_BOARD_EARLY_INIT_F=y
|
||||
CONFIG_BOARD_LATE_INIT=y
|
||||
CONFIG_SPL_MAX_SIZE=0x20000
|
||||
CONFIG_SPL_BOARD_INIT=y
|
||||
CONFIG_SPL_LOAD_IMX_CONTAINER=y
|
||||
CONFIG_IMX_CONTAINER_CFG="arch/arm/mach-imx/imx9/scmi/container.cfg"
|
||||
# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set
|
||||
CONFIG_SPL_SYS_MALLOC=y
|
||||
CONFIG_SPL_HAS_CUSTOM_MALLOC_START=y
|
||||
CONFIG_SPL_CUSTOM_SYS_MALLOC_ADDR=0x93200000
|
||||
CONFIG_SPL_SYS_MALLOC_SIZE=0x80000
|
||||
CONFIG_SPL_SYS_MMCSD_RAW_MODE=y
|
||||
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x1040
|
||||
CONFIG_SPL_I2C=y
|
||||
CONFIG_SPL_DM_MAILBOX=y
|
||||
CONFIG_SPL_POWER=y
|
||||
CONFIG_SPL_WATCHDOG=y
|
||||
CONFIG_SYS_PROMPT="u-boot=> "
|
||||
CONFIG_CMD_ERASEENV=y
|
||||
CONFIG_CMD_NVEDIT_EFI=y
|
||||
CONFIG_CRC32_VERIFY=y
|
||||
CONFIG_CMD_MEMTEST=y
|
||||
CONFIG_CMD_CLK=y
|
||||
CONFIG_CMD_DFU=y
|
||||
CONFIG_CMD_FUSE=y
|
||||
CONFIG_CMD_GPIO=y
|
||||
CONFIG_CMD_GPT=y
|
||||
CONFIG_CMD_I2C=y
|
||||
CONFIG_CMD_MMC=y
|
||||
CONFIG_CMD_PCI=y
|
||||
CONFIG_CMD_POWEROFF=y
|
||||
CONFIG_CMD_SNTP=y
|
||||
CONFIG_CMD_CACHE=y
|
||||
CONFIG_CMD_EFIDEBUG=y
|
||||
CONFIG_CMD_RTC=y
|
||||
CONFIG_CMD_TIME=y
|
||||
CONFIG_CMD_GETTIME=y
|
||||
CONFIG_CMD_TIMER=y
|
||||
CONFIG_CMD_REGULATOR=y
|
||||
CONFIG_CMD_HASH=y
|
||||
CONFIG_CMD_EXT4_WRITE=y
|
||||
CONFIG_OF_CONTROL=y
|
||||
CONFIG_SPL_OF_CONTROL=y
|
||||
CONFIG_ENV_OVERWRITE=y
|
||||
CONFIG_ENV_IS_NOWHERE=y
|
||||
CONFIG_ENV_IS_IN_MMC=y
|
||||
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
|
||||
CONFIG_SYS_MMC_ENV_DEV=1
|
||||
CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
|
||||
CONFIG_USE_ETHPRIME=y
|
||||
CONFIG_ETHPRIME="eth0"
|
||||
CONFIG_NET_RANDOM_ETHADDR=y
|
||||
CONFIG_SYS_RX_ETH_BUFFER=8
|
||||
CONFIG_SPL_DM=y
|
||||
CONFIG_REGMAP=y
|
||||
CONFIG_SYSCON=y
|
||||
CONFIG_SPL_OF_TRANSLATE=y
|
||||
CONFIG_CLK=y
|
||||
CONFIG_SPL_CLK=y
|
||||
CONFIG_SPL_CLK_CCF=y
|
||||
CONFIG_CLK_CCF=y
|
||||
CONFIG_CLK_SCMI=y
|
||||
CONFIG_SPL_CLK_SCMI=y
|
||||
CONFIG_DFU_MMC=y
|
||||
CONFIG_DFU_RAM=y
|
||||
CONFIG_SPL_FIRMWARE=y
|
||||
# CONFIG_SCMI_AGENT_SMCCC is not set
|
||||
CONFIG_IMX_RGPIO2P=y
|
||||
CONFIG_DM_PCA953X=y
|
||||
CONFIG_ADP5585_GPIO=y
|
||||
CONFIG_DM_I2C=y
|
||||
CONFIG_SYS_I2C_IMX_LPI2C=y
|
||||
CONFIG_IMX_MU_MBOX=y
|
||||
CONFIG_SUPPORT_EMMC_BOOT=y
|
||||
CONFIG_MMC_IO_VOLTAGE=y
|
||||
CONFIG_MMC_UHS_SUPPORT=y
|
||||
CONFIG_MMC_HS400_ES_SUPPORT=y
|
||||
CONFIG_MMC_HS400_SUPPORT=y
|
||||
CONFIG_FSL_USDHC=y
|
||||
CONFIG_MTD=y
|
||||
CONFIG_DM_SPI_FLASH=y
|
||||
CONFIG_SPI_FLASH_STMICRO=y
|
||||
CONFIG_SPI_FLASH_MT35XU=y
|
||||
CONFIG_PHYLIB=y
|
||||
CONFIG_PHY_AQUANTIA=y
|
||||
CONFIG_PHY_REALTEK=y
|
||||
CONFIG_DM_MDIO=y
|
||||
CONFIG_MII=y
|
||||
CONFIG_FSL_ENETC=y
|
||||
CONFIG_PCIE_ECAM_GENERIC=y
|
||||
CONFIG_PHY=y
|
||||
CONFIG_PINCTRL=y
|
||||
CONFIG_SPL_PINCTRL=y
|
||||
CONFIG_PINCTRL_IMX_SCMI=y
|
||||
CONFIG_POWER_DOMAIN=y
|
||||
CONFIG_SCMI_POWER_DOMAIN=y
|
||||
CONFIG_DM_REGULATOR=y
|
||||
CONFIG_SPL_DM_REGULATOR=y
|
||||
CONFIG_DM_REGULATOR_FIXED=y
|
||||
CONFIG_SPL_DM_REGULATOR_FIXED=y
|
||||
CONFIG_DM_REGULATOR_GPIO=y
|
||||
CONFIG_DM_RTC=y
|
||||
CONFIG_DM_SERIAL=y
|
||||
CONFIG_FSL_LPUART=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_DM_SPI=y
|
||||
CONFIG_NXP_FSPI=y
|
||||
CONFIG_ULP_WATCHDOG=y
|
||||
CONFIG_LZO=y
|
||||
CONFIG_BZIP2=y
|
||||
@@ -0,0 +1,114 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
imx95_evk
|
||||
=======================
|
||||
|
||||
U-Boot for the NXP i.MX95 19x19 EVK board
|
||||
|
||||
Quick Start
|
||||
-----------
|
||||
|
||||
- Get ahab-container.img
|
||||
- Get DDR PHY Firmware Images
|
||||
- Get and Build OEI Images
|
||||
- Get and Build System Manager Image
|
||||
- Get and Build the ARM Trusted Firmware
|
||||
- Build the Bootloader Image
|
||||
- Boot
|
||||
|
||||
Get ahab-container.img
|
||||
--------------------------------------
|
||||
|
||||
Note: srctree is U-Boot source directory
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-ele-imx-1.3.0-17945fc.bin
|
||||
$ sh firmware-ele-imx-1.3.0-17945fc.bin --auto-accept
|
||||
$ cp firmware-ele-imx-1.3.0-17945fc/mx95a0-ahab-container.img $(srctree)
|
||||
|
||||
Get DDR PHY Firmware Images
|
||||
--------------------------------------
|
||||
|
||||
Note: srctree is U-Boot source directory
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-imx-8.26-d4c33ab.bin
|
||||
$ sh firmware-imx-8.26-d4c33ab.bin --auto-accept
|
||||
$ cp firmware-imx-8.26-d4c33ab/firmware/ddr/synopsys/lpddr5*v202311.bin $(srctree)
|
||||
|
||||
Get and Build OEI Images
|
||||
--------------------------------------
|
||||
|
||||
Note: srctree is U-Boot source directory
|
||||
Get OEI from: https://github.com/nxp-imx/imx-oei
|
||||
branch: master
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ sudo apt -y install make gcc g++-multilib srecord
|
||||
$ wget https://developer.arm.com/-/media/Files/downloads/gnu/13.3.rel1/binrel/arm-gnu-toolchain-13.3.rel1-x86_64-arm-none-eabi.tar.xz
|
||||
$ tar xvf arm-gnu-toolchain-13.3.rel1-x86_64-arm-none-eabi.tar.xz
|
||||
$ export TOOLS=$PWD
|
||||
$ git clone -b master https://github.com/nxp-imx/imx-oei.git
|
||||
$ cd imx-oei
|
||||
$ make board=mx95lp5 oei=ddr DEBUG=1
|
||||
$ cp build/mx95lp5/ddr/oei-m33-ddr.bin $(srctree)
|
||||
|
||||
$ make board=mx95lp5 oei=tcm DEBUG=1
|
||||
$ cp build/mx95lp5/tcm/oei-m33-tcm.bin $(srctree)
|
||||
|
||||
Get and Build System Manager Image
|
||||
--------------------------------------
|
||||
|
||||
Note: srctree is U-Boot source directory
|
||||
Get System Manager from: https://github.com/nxp-imx/imx-sm
|
||||
branch: master
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ sudo apt -y install make gcc g++-multilib srecord
|
||||
$ wget https://developer.arm.com/-/media/Files/downloads/gnu/13.3.rel1/binrel/arm-gnu-toolchain-13.3.rel1-x86_64-arm-none-eabi.tar.xz
|
||||
$ tar xvf arm-gnu-toolchain-13.3.rel1-x86_64-arm-none-eabi.tar.xz
|
||||
$ export TOOLS=$PWD
|
||||
$ git clone -b master https://github.com/nxp-imx/imx-sm.git
|
||||
$ cd imx-sm
|
||||
$ make config=mx95evk all
|
||||
$ cp build/mx95evk/m33_image.bin $(srctree)
|
||||
|
||||
Get and Build the ARM Trusted Firmware
|
||||
--------------------------------------
|
||||
|
||||
Note: srctree is U-Boot source directory
|
||||
Get ATF from: https://github.com/nxp-imx/imx-atf/
|
||||
branch: lf_v2.10
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ export CROSS_COMPILE=aarch64-poky-linux-
|
||||
$ unset LDFLAGS
|
||||
$ git clone -b lf_v2.10 https://github.com/nxp-imx/imx-atf.git
|
||||
$ cd imx-atf
|
||||
$ make PLAT=imx95 bl31
|
||||
$ cp build/imx95/release/bl31.bin $(srctree)
|
||||
|
||||
Build the Bootloader Image
|
||||
--------------------------
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ export CROSS_COMPILE=aarch64-poky-linux-
|
||||
$ make imx95_19x19_evk_defconfig
|
||||
$ make
|
||||
|
||||
Copy imx-boot-imx95.bin to the MicroSD card:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ sudo dd if=flash.bin of=/dev/sd[x] bs=1k seek=32 conv=fsync
|
||||
|
||||
Boot
|
||||
----
|
||||
|
||||
Set i.MX95 boot device to MicroSD card
|
||||
@@ -15,6 +15,7 @@ NXP Semiconductors
|
||||
imx91_11x11_evk
|
||||
imx93_9x9_qsb
|
||||
imx93_11x11_evk
|
||||
imx95_evk
|
||||
imxrt1020-evk
|
||||
imxrt1050-evk
|
||||
imxrt1170-evk
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
i.MX95 Image Container Format
|
||||
-----------------------------
|
||||
|
||||
The image container set consists of some image containers, and image container
|
||||
contains boot images. Each image container has its own container header which is
|
||||
defined in Figure 1. All container headers are placed together in a continuous
|
||||
8KB space at the beginning of the image container set - image container set header.
|
||||
|
||||
ROM code addresses image containers in image container set one by one based on
|
||||
their headers’ order in image container set header.
|
||||
|
||||
If ELE container exists, its container header must be the 1st one in the image
|
||||
container set header.
|
||||
|
||||
If V2X container exists, its container header must be the 2nd one in the image
|
||||
container set header. V2X must be combined with ELE container.
|
||||
|
||||
The information of boot images are recorded in image container header. System
|
||||
ROM code needs to retrieve the information from the image container header, like
|
||||
the offset on boot source, the target address in RAM, the length of boot image.
|
||||
The order of ROM code handling these boot images is based on the order of each
|
||||
boot image information present in image container header.
|
||||
|
||||
Figure 1:
|
||||
------------------- +--------------+--------------+--------------+--------------+
|
||||
^ |Tag |Length |Length |Version |
|
||||
| +--------------+--------------+--------------+--------------+
|
||||
| | Flags |
|
||||
| +--------------+--------------+--------------+--------------+
|
||||
| |# of Images |Fuse version |SW version |
|
||||
Image | +--------------+--------------+--------------+--------------+
|
||||
Container | |Reserved |Signature Block Offset |
|
||||
Header | ------- +--------------+--------------+--------------+--------------+
|
||||
| ^ |Image0: Offset, Size, LoadAddr, EntryPoint, Flags, Hash, IV|
|
||||
| | +--------------+--------------+--------------+--------------+
|
||||
| Image | |Image1: Offset, Size, LoadAddr, EntryPoint, Flags, Hash, IV|
|
||||
| Array | +--------------+--------------+--------------+--------------+
|
||||
| | | ... |
|
||||
| | +--------------+--------------+--------------+--------------+
|
||||
v v |ImageN: Offset, Size, LoadAddr, EntryPoint, Flags, Hash, IV|
|
||||
------------------- +--------------+--------------+--------------+--------------+
|
||||
| ... |
|
||||
----------- +--------------+--------------+--------------+--------------+ <-- SignOffset
|
||||
^ |Tag |Length |Length |Version |
|
||||
| +--------------+--------------+--------------+--------------+
|
||||
| |SRK table offset |Certificate Offset |
|
||||
| +--------------+--------------+--------------+--------------+
|
||||
| |Blob Offset |Signature Offset |
|
||||
| +--------------+--------------+--------------+--------------+
|
||||
Signature | | SRK Table |
|
||||
Block | +--------------+--------------+--------------+--------------+
|
||||
| | Signature |
|
||||
| +--------------+--------------+--------------+--------------+
|
||||
| | Certificate (optional) |
|
||||
| +--------------+--------------+--------------+--------------+
|
||||
v | Blob (optional) |
|
||||
----------- +--------------+--------------+--------------+--------------+
|
||||
| ... |
|
||||
+--------------+--------------+--------------+--------------+ <-- Image0Offset
|
||||
| Image0 |
|
||||
+--------------+--------------+--------------+--------------+
|
||||
| ... |
|
||||
+--------------+--------------+--------------+--------------+ <-- ImageNOffset
|
||||
| ImageN |
|
||||
+--------------+--------------+--------------+--------------+
|
||||
| ... |
|
||||
+--------------+--------------+--------------+--------------+
|
||||
|
||||
i.MX95 Low Power Boot Image Sets Layout
|
||||
---------------------------------------
|
||||
|
||||
Image container sets are handled by M33 ROM.
|
||||
|
||||
--------------- +--------------+--------------+--------------+--------------+
|
||||
^ | 1st Container Header |
|
||||
| +--------------+--------------+--------------+--------------+
|
||||
ELE + | | Padding for 1KB alignment |
|
||||
OEM | +--------------+--------------+--------------+--------------+
|
||||
Container | | 2nd Container Header |
|
||||
Set | +--------------+--------------+--------------+--------------+
|
||||
Header | | Padding for 1KB alignment |
|
||||
| +--------------+--------------+--------------+--------------+
|
||||
| | 3rd Container Header |
|
||||
| +--------------+--------------+--------------+--------------+
|
||||
v | Padding for 1KB alignment |
|
||||
--------------- +--------------+--------------+--------------+--------------+
|
||||
| ... |
|
||||
+--------------+--------------+--------------+--------------+
|
||||
| mx95a0-ahab-container.img |
|
||||
+--------------+--------------+--------------+--------------+
|
||||
| ... |
|
||||
------------------- +--------------+--------------+--------------+--------------+
|
||||
^ | oei-m33-ddr.bin |
|
||||
| +--------------+--------------+--------------+--------------+
|
||||
| | ddrfw-header.bin |
|
||||
| +--------------+--------------+--------------+--------------+
|
||||
| | lpddr5_imem_v202311.bin |
|
||||
| +--------------+--------------+--------------+--------------+
|
||||
m33-oei-ddrfw.bin | | lpddr5_dmem_v202311.bin |
|
||||
| +--------------+--------------+--------------+--------------+
|
||||
| | ddrfw-qb-header.bin |
|
||||
| +--------------+--------------+--------------+--------------+
|
||||
| | lpddr5_imem_qb_v202311.bin |
|
||||
| +--------------+--------------+--------------+--------------+
|
||||
v | lpddr5_dmem_qb_v202311.bin |
|
||||
------------------- +--------------+--------------+--------------+--------------+
|
||||
| ... |
|
||||
+--------------+--------------+--------------+--------------+
|
||||
| oei-m33-tcm.bin |
|
||||
+--------------+--------------+--------------+--------------+
|
||||
| ... |
|
||||
+--------------+--------------+--------------+--------------+
|
||||
| m33_image.bin |
|
||||
+--------------+--------------+--------------+--------------+
|
||||
| ... |
|
||||
+--------------+--------------+--------------+--------------+
|
||||
| u-boot-spl.bin |
|
||||
+--------------+--------------+--------------+--------------+
|
||||
| ... |
|
||||
+--------------+--------------+--------------+--------------+
|
||||
|
||||
--------------- +--------------+--------------+--------------+--------------+
|
||||
u-boot-atf ^ | 1st Container Header |
|
||||
Container | +--------------+--------------+--------------+--------------+
|
||||
Header v | Padding for 1KB alignment |
|
||||
--------------- +--------------+--------------+--------------+--------------+
|
||||
| ... |
|
||||
+--------------+--------------+--------------+--------------+
|
||||
| bl31.bin |
|
||||
+--------------+--------------+--------------+--------------+
|
||||
| ... |
|
||||
+--------------+--------------+--------------+--------------+
|
||||
| u-boot.bin |
|
||||
+--------------+--------------+--------------+--------------+
|
||||
| ... |
|
||||
+--------------+--------------+--------------+--------------+
|
||||
+193
-11
@@ -8,10 +8,59 @@
|
||||
#include <clk-uclass.h>
|
||||
#include <dm.h>
|
||||
#include <scmi_agent.h>
|
||||
#include <scmi_agent-uclass.h>
|
||||
#include <scmi_protocols.h>
|
||||
#include <asm/types.h>
|
||||
#include <linux/clk-provider.h>
|
||||
|
||||
struct clk_scmi {
|
||||
struct clk clk;
|
||||
u32 ctrl_flags;
|
||||
};
|
||||
|
||||
struct scmi_clock_priv {
|
||||
u32 version;
|
||||
};
|
||||
|
||||
static int scmi_clk_get_permissions(struct udevice *dev, int clkid, u32 *perm)
|
||||
{
|
||||
struct scmi_clock_priv *priv = dev_get_priv(dev);
|
||||
int ret;
|
||||
|
||||
struct scmi_clk_get_permissions_in in = {
|
||||
.clock_id = clkid,
|
||||
};
|
||||
struct scmi_clk_get_permissions_out out;
|
||||
struct scmi_msg msg = {
|
||||
.protocol_id = SCMI_PROTOCOL_ID_CLOCK,
|
||||
.message_id = SCMI_CLOCK_GET_PERMISSIONS,
|
||||
.in_msg = (u8 *)&in,
|
||||
.in_msg_sz = sizeof(in),
|
||||
.out_msg = (u8 *)&out,
|
||||
.out_msg_sz = sizeof(out),
|
||||
};
|
||||
|
||||
if (priv->version < CLOCK_PROTOCOL_VERSION_3_0) {
|
||||
log_debug("%s: SCMI clock management protocol version is less than 3.0.\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = devm_scmi_process_msg(dev, &msg);
|
||||
if (ret) {
|
||||
log_debug("%s: get SCMI clock management protocol permissions failed\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = scmi_to_linux_errno(out.status);
|
||||
if (ret < 0) {
|
||||
log_debug("%s: the status code of getting permissions: %d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
*perm = out.permissions;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int scmi_clk_get_num_clock(struct udevice *dev, size_t *num_clocks)
|
||||
{
|
||||
struct scmi_clk_protocol_attr_out out;
|
||||
@@ -32,7 +81,8 @@ static int scmi_clk_get_num_clock(struct udevice *dev, size_t *num_clocks)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name)
|
||||
static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name,
|
||||
u32 *attr)
|
||||
{
|
||||
struct scmi_clk_attribute_in in = {
|
||||
.clock_id = clkid,
|
||||
@@ -53,6 +103,7 @@ static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name)
|
||||
return ret;
|
||||
|
||||
*name = strdup(out.clock_name);
|
||||
*attr = out.attributes;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -78,12 +129,48 @@ static int scmi_clk_gate(struct clk *clk, int enable)
|
||||
|
||||
static int scmi_clk_enable(struct clk *clk)
|
||||
{
|
||||
return scmi_clk_gate(clk, 1);
|
||||
struct clk_scmi *clkscmi;
|
||||
struct clk *c;
|
||||
int ret;
|
||||
|
||||
if (!CONFIG_IS_ENABLED(CLK_CCF))
|
||||
return scmi_clk_gate(clk, 1);
|
||||
|
||||
ret = clk_get_by_id(clk->id, &c);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
clkscmi = container_of(c, struct clk_scmi, clk);
|
||||
|
||||
if (clkscmi->ctrl_flags & SUPPORT_CLK_STAT_CONTROL)
|
||||
return scmi_clk_gate(clk, 1);
|
||||
|
||||
/* Following Linux drivers/clk/clk-scmi.c, directly return 0 if agent has no permission. */
|
||||
log_debug("%s: SCMI CLOCK: the clock cannot be enabled by the agent.\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int scmi_clk_disable(struct clk *clk)
|
||||
{
|
||||
return scmi_clk_gate(clk, 0);
|
||||
struct clk_scmi *clkscmi;
|
||||
struct clk *c;
|
||||
int ret;
|
||||
|
||||
if (!CONFIG_IS_ENABLED(CLK_CCF))
|
||||
return scmi_clk_gate(clk, 0);
|
||||
|
||||
ret = clk_get_by_id(clk->id, &c);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
clkscmi = container_of(c, struct clk_scmi, clk);
|
||||
|
||||
if (clkscmi->ctrl_flags & SUPPORT_CLK_STAT_CONTROL)
|
||||
return scmi_clk_gate(clk, 0);
|
||||
|
||||
/* Following Linux drivers/clk/clk-scmi.c, directly return 0 if agent has no permission. */
|
||||
log_debug("%s: SCMI CLOCK: the clock cannot be disabled by the agent.\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ulong scmi_clk_get_rate(struct clk *clk)
|
||||
@@ -108,7 +195,7 @@ static ulong scmi_clk_get_rate(struct clk *clk)
|
||||
return (ulong)(((u64)out.rate_msb << 32) | out.rate_lsb);
|
||||
}
|
||||
|
||||
static ulong scmi_clk_set_rate(struct clk *clk, ulong rate)
|
||||
static ulong __scmi_clk_set_rate(struct clk *clk, ulong rate)
|
||||
{
|
||||
struct scmi_clk_rate_set_in in = {
|
||||
.clock_id = clk->id,
|
||||
@@ -133,9 +220,33 @@ static ulong scmi_clk_set_rate(struct clk *clk, ulong rate)
|
||||
return scmi_clk_get_rate(clk);
|
||||
}
|
||||
|
||||
static ulong scmi_clk_set_rate(struct clk *clk, ulong rate)
|
||||
{
|
||||
struct clk_scmi *clkscmi;
|
||||
struct clk *c;
|
||||
int ret;
|
||||
|
||||
if (!CONFIG_IS_ENABLED(CLK_CCF))
|
||||
return __scmi_clk_set_rate(clk, rate);
|
||||
|
||||
ret = clk_get_by_id(clk->id, &c);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
clkscmi = container_of(c, struct clk_scmi, clk);
|
||||
|
||||
if (clkscmi->ctrl_flags & SUPPORT_CLK_RATE_CONTROL)
|
||||
return __scmi_clk_set_rate(clk, rate);
|
||||
|
||||
/* Following Linux drivers/clk/clk-scmi.c, directly return 0 if agent has no permission. */
|
||||
log_debug("%s: SCMI CLOCK: the clock rate cannot be changed by the agent.\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int scmi_clk_probe(struct udevice *dev)
|
||||
{
|
||||
struct clk *clk;
|
||||
struct clk_scmi *clk_scmi;
|
||||
struct scmi_clock_priv *priv = dev_get_priv(dev);
|
||||
size_t num_clocks, i;
|
||||
int ret;
|
||||
|
||||
@@ -154,35 +265,98 @@ static int scmi_clk_probe(struct udevice *dev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = scmi_generic_protocol_version(dev, SCMI_PROTOCOL_ID_CLOCK, &priv->version);
|
||||
if (ret) {
|
||||
log_debug("%s: get SCMI clock management protocol version failed\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_clocks; i++) {
|
||||
char *clock_name;
|
||||
u32 attributes;
|
||||
|
||||
if (!scmi_clk_get_attibute(dev, i, &clock_name)) {
|
||||
clk = kzalloc(sizeof(*clk), GFP_KERNEL);
|
||||
if (!clk || !clock_name)
|
||||
if (!scmi_clk_get_attibute(dev, i, &clock_name, &attributes)) {
|
||||
clk_scmi = kzalloc(sizeof(*clk_scmi), GFP_KERNEL);
|
||||
if (!clk_scmi || !clock_name)
|
||||
ret = -ENOMEM;
|
||||
else
|
||||
ret = clk_register(clk, dev->driver->name,
|
||||
ret = clk_register(&clk_scmi->clk, dev->driver->name,
|
||||
clock_name, dev->name);
|
||||
|
||||
if (ret) {
|
||||
free(clk);
|
||||
free(clk_scmi);
|
||||
free(clock_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
clk_dm(i, clk);
|
||||
clk_dm(i, &clk_scmi->clk);
|
||||
|
||||
if (CLK_HAS_RESTRICTIONS(attributes)) {
|
||||
u32 perm;
|
||||
|
||||
ret = scmi_clk_get_permissions(dev, i, &perm);
|
||||
if (ret < 0)
|
||||
clk_scmi->ctrl_flags = 0;
|
||||
else
|
||||
clk_scmi->ctrl_flags = perm;
|
||||
} else {
|
||||
clk_scmi->ctrl_flags = SUPPORT_CLK_STAT_CONTROL | SUPPORT_CLK_PARENT_CONTROL |
|
||||
SUPPORT_CLK_RATE_CONTROL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __scmi_clk_set_parent(struct clk *clk, struct clk *parent)
|
||||
{
|
||||
struct scmi_clk_parent_set_in in = {
|
||||
.clock_id = clk->id,
|
||||
.parent_clk = parent->id,
|
||||
};
|
||||
struct scmi_clk_parent_set_out out;
|
||||
struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_CLOCK,
|
||||
SCMI_CLOCK_PARENT_SET,
|
||||
in, out);
|
||||
int ret;
|
||||
|
||||
ret = devm_scmi_process_msg(clk->dev, &msg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return scmi_to_linux_errno(out.status);
|
||||
}
|
||||
|
||||
static int scmi_clk_set_parent(struct clk *clk, struct clk *parent)
|
||||
{
|
||||
struct clk_scmi *clkscmi;
|
||||
struct clk *c;
|
||||
int ret;
|
||||
|
||||
if (!CONFIG_IS_ENABLED(CLK_CCF))
|
||||
return -ENOTSUPP;
|
||||
|
||||
ret = clk_get_by_id(clk->id, &c);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
clkscmi = container_of(c, struct clk_scmi, clk);
|
||||
|
||||
if (clkscmi->ctrl_flags & SUPPORT_CLK_PARENT_CONTROL)
|
||||
return __scmi_clk_set_parent(clk, parent);
|
||||
|
||||
/* Following Linux drivers/clk/clk-scmi.c, directly return 0 if agent has no permission. */
|
||||
log_debug("%s: SCMI CLOCK: the clock's parent cannot be changed by the agent.\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops scmi_clk_ops = {
|
||||
.enable = scmi_clk_enable,
|
||||
.disable = scmi_clk_disable,
|
||||
.get_rate = scmi_clk_get_rate,
|
||||
.set_rate = scmi_clk_set_rate,
|
||||
.set_parent = scmi_clk_set_parent,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(scmi_clock) = {
|
||||
@@ -190,4 +364,12 @@ U_BOOT_DRIVER(scmi_clock) = {
|
||||
.id = UCLASS_CLK,
|
||||
.ops = &scmi_clk_ops,
|
||||
.probe = scmi_clk_probe,
|
||||
.priv_auto = sizeof(struct scmi_clock_priv),
|
||||
};
|
||||
|
||||
static struct scmi_proto_match match[] = {
|
||||
{ .proto_id = SCMI_PROTOCOL_ID_CLOCK },
|
||||
{ /* Sentinel */ }
|
||||
};
|
||||
|
||||
U_BOOT_SCMI_PROTO_DRIVER(scmi_clock, match);
|
||||
|
||||
@@ -111,6 +111,8 @@ static const char *get_imx_type_str(u32 imxtype)
|
||||
return "91(11)";/* iMX91 9x9 Reduced feature */
|
||||
case MXC_CPU_IMX9101:
|
||||
return "91(01)";/* iMX91 9x9 Specific feature */
|
||||
case MXC_CPU_IMX95:
|
||||
return "95";
|
||||
default:
|
||||
return "??";
|
||||
}
|
||||
|
||||
@@ -258,7 +258,7 @@ static int scmi_base_discover_impl_version_int(struct udevice *dev,
|
||||
static int scmi_base_discover_list_protocols_int(struct udevice *dev,
|
||||
u8 **protocols)
|
||||
{
|
||||
struct scmi_base_discover_list_protocols_out out;
|
||||
struct scmi_base_discover_list_protocols_out *out;
|
||||
int cur;
|
||||
struct scmi_msg msg = {
|
||||
.protocol_id = SCMI_PROTOCOL_ID_BASE,
|
||||
@@ -268,7 +268,7 @@ static int scmi_base_discover_list_protocols_int(struct udevice *dev,
|
||||
.out_msg = (u8 *)&out,
|
||||
.out_msg_sz = sizeof(out),
|
||||
};
|
||||
u32 num_agents, num_protocols;
|
||||
u32 num_agents, num_protocols, out_size;
|
||||
u8 *buf;
|
||||
int i, ret;
|
||||
|
||||
@@ -276,22 +276,31 @@ static int scmi_base_discover_list_protocols_int(struct udevice *dev,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
buf = calloc(sizeof(u8), num_protocols);
|
||||
if (!buf)
|
||||
out_size = sizeof(*out) + sizeof(u32) * (1 + num_protocols / 4);
|
||||
out = calloc(1, out_size);
|
||||
if (!out)
|
||||
return -ENOMEM;
|
||||
msg.out_msg = (u8 *)out;
|
||||
msg.out_msg_sz = out_size;
|
||||
|
||||
buf = calloc(sizeof(u8), num_protocols);
|
||||
if (!buf) {
|
||||
free(out);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cur = 0;
|
||||
do {
|
||||
ret = devm_scmi_process_msg(dev, &msg);
|
||||
if (ret)
|
||||
goto err;
|
||||
if (out.status) {
|
||||
ret = scmi_to_linux_errno(out.status);
|
||||
if (out->status) {
|
||||
ret = scmi_to_linux_errno(out->status);
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (i = 0; i < out.num_protocols; i++, cur++)
|
||||
buf[cur] = out.protocols[i / 4] >> ((i % 4) * 8);
|
||||
for (i = 0; i < out->num_protocols; i++, cur++)
|
||||
buf[cur] = out->protocols[i / 4] >> ((i % 4) * 8);
|
||||
} while (cur < num_protocols);
|
||||
|
||||
*protocols = buf;
|
||||
@@ -299,6 +308,7 @@ static int scmi_base_discover_list_protocols_int(struct udevice *dev,
|
||||
return num_protocols;
|
||||
err:
|
||||
free(buf);
|
||||
free(out);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -80,9 +80,9 @@ static struct sandbox_scmi_pwd scmi_pwdom[] = {
|
||||
};
|
||||
|
||||
static struct sandbox_scmi_clk scmi_clk[] = {
|
||||
{ .rate = 333 },
|
||||
{ .rate = 200 },
|
||||
{ .rate = 1000 },
|
||||
{ .rate = 333, .perm = 0xE0000000 },
|
||||
{ .rate = 200, .perm = 0xE0000000 },
|
||||
{ .rate = 1000, .perm = 0xE0000000 },
|
||||
};
|
||||
|
||||
static struct sandbox_scmi_reset scmi_reset[] = {
|
||||
@@ -700,6 +700,21 @@ static int sandbox_scmi_pwd_name_get(struct udevice *dev, struct scmi_msg *msg)
|
||||
|
||||
/* Clock Protocol */
|
||||
|
||||
static int sandbox_scmi_clock_protocol_version(struct udevice *dev,
|
||||
struct scmi_msg *msg)
|
||||
{
|
||||
struct scmi_protocol_version_out *out = NULL;
|
||||
|
||||
if (!msg->out_msg || msg->out_msg_sz < sizeof(*out))
|
||||
return -EINVAL;
|
||||
|
||||
out = (struct scmi_protocol_version_out *)msg->out_msg;
|
||||
out->version = 0x30000;
|
||||
out->status = SCMI_SUCCESS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sandbox_scmi_clock_protocol_attribs(struct udevice *dev,
|
||||
struct scmi_msg *msg)
|
||||
{
|
||||
@@ -740,6 +755,9 @@ static int sandbox_scmi_clock_attribs(struct udevice *dev, struct scmi_msg *msg)
|
||||
if (clk_state->enabled)
|
||||
out->attributes = 1;
|
||||
|
||||
/* Restricted clock */
|
||||
out->attributes |= BIT(1);
|
||||
|
||||
ret = snprintf(out->clock_name, sizeof(out->clock_name),
|
||||
"clk%u", in->clock_id);
|
||||
assert(ret > 0 && ret < sizeof(out->clock_name));
|
||||
@@ -837,6 +855,34 @@ static int sandbox_scmi_clock_gate(struct udevice *dev, struct scmi_msg *msg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sandbox_scmi_clock_permissions_get(struct udevice *dev,
|
||||
struct scmi_msg *msg)
|
||||
{
|
||||
struct scmi_clk_get_permissions_in *in = NULL;
|
||||
struct scmi_clk_get_permissions_out *out = NULL;
|
||||
struct sandbox_scmi_clk *clk_state = NULL;
|
||||
|
||||
if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
|
||||
!msg->out_msg || msg->out_msg_sz < sizeof(*out))
|
||||
return -EINVAL;
|
||||
|
||||
in = (struct scmi_clk_get_permissions_in *)msg->in_msg;
|
||||
out = (struct scmi_clk_get_permissions_out *)msg->out_msg;
|
||||
|
||||
clk_state = get_scmi_clk_state(in->clock_id);
|
||||
if (!clk_state) {
|
||||
dev_err(dev, "Unexpected clock ID %u\n", in->clock_id);
|
||||
|
||||
out->status = SCMI_NOT_FOUND;
|
||||
} else {
|
||||
out->permissions = clk_state->perm;
|
||||
|
||||
out->status = SCMI_SUCCESS;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sandbox_scmi_rd_attribs(struct udevice *dev, struct scmi_msg *msg)
|
||||
{
|
||||
struct scmi_rd_attr_in *in = NULL;
|
||||
@@ -1193,6 +1239,8 @@ static int sandbox_scmi_test_process_msg(struct udevice *dev,
|
||||
return sandbox_proto_not_supported(msg);
|
||||
|
||||
switch (msg->message_id) {
|
||||
case SCMI_PROTOCOL_VERSION:
|
||||
return sandbox_scmi_clock_protocol_version(dev, msg);
|
||||
case SCMI_PROTOCOL_ATTRIBUTES:
|
||||
return sandbox_scmi_clock_protocol_attribs(dev, msg);
|
||||
case SCMI_CLOCK_ATTRIBUTES:
|
||||
@@ -1203,6 +1251,8 @@ static int sandbox_scmi_test_process_msg(struct udevice *dev,
|
||||
return sandbox_scmi_clock_rate_get(dev, msg);
|
||||
case SCMI_CLOCK_CONFIG_SET:
|
||||
return sandbox_scmi_clock_gate(dev, msg);
|
||||
case SCMI_CLOCK_GET_PERMISSIONS:
|
||||
return sandbox_scmi_clock_permissions_get(dev, msg);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -97,6 +97,9 @@ struct udevice *scmi_get_protocol(struct udevice *dev,
|
||||
case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN:
|
||||
proto = priv->voltagedom_dev;
|
||||
break;
|
||||
case SCMI_PROTOCOL_ID_PINCTRL:
|
||||
proto = priv->pinctrl_dev;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "Protocol not supported\n");
|
||||
proto = NULL;
|
||||
@@ -147,6 +150,9 @@ static int scmi_add_protocol(struct udevice *dev,
|
||||
case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN:
|
||||
priv->voltagedom_dev = proto;
|
||||
break;
|
||||
case SCMI_PROTOCOL_ID_PINCTRL:
|
||||
priv->pinctrl_dev = proto;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "Protocol not supported\n");
|
||||
return -EPROTO;
|
||||
@@ -352,6 +358,22 @@ static int scmi_fill_base_info(struct udevice *agent, struct udevice *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct driver *scmi_proto_driver_get(unsigned int proto_id)
|
||||
{
|
||||
struct scmi_proto_driver *start, *entry;
|
||||
int n_ents;
|
||||
|
||||
start = ll_entry_start(struct scmi_proto_driver, scmi_proto_driver);
|
||||
n_ents = ll_entry_count(struct scmi_proto_driver, scmi_proto_driver);
|
||||
|
||||
for (entry = start; entry != start + n_ents; entry++) {
|
||||
if (entry->match->proto_id == proto_id)
|
||||
return entry->driver;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* SCMI agent devices binds devices of various uclasses depending on
|
||||
* the FDT description. scmi_bind_protocol() is a generic bind sequence
|
||||
@@ -409,31 +431,11 @@ static int scmi_bind_protocols(struct udevice *dev)
|
||||
|
||||
drv = NULL;
|
||||
name = ofnode_get_name(node);
|
||||
switch (protocol_id) {
|
||||
case SCMI_PROTOCOL_ID_POWER_DOMAIN:
|
||||
if (CONFIG_IS_ENABLED(SCMI_POWER_DOMAIN) &&
|
||||
scmi_protocol_is_supported(dev, protocol_id))
|
||||
drv = DM_DRIVER_GET(scmi_power_domain);
|
||||
break;
|
||||
case SCMI_PROTOCOL_ID_CLOCK:
|
||||
if (CONFIG_IS_ENABLED(CLK_SCMI) &&
|
||||
scmi_protocol_is_supported(dev, protocol_id))
|
||||
drv = DM_DRIVER_GET(scmi_clock);
|
||||
break;
|
||||
case SCMI_PROTOCOL_ID_RESET_DOMAIN:
|
||||
if (IS_ENABLED(CONFIG_RESET_SCMI) &&
|
||||
scmi_protocol_is_supported(dev, protocol_id))
|
||||
drv = DM_DRIVER_GET(scmi_reset_domain);
|
||||
break;
|
||||
case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN:
|
||||
if (IS_ENABLED(CONFIG_DM_REGULATOR_SCMI) &&
|
||||
scmi_protocol_is_supported(dev, protocol_id))
|
||||
drv = DM_DRIVER_GET(scmi_voltage_domain);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!scmi_protocol_is_supported(dev, protocol_id))
|
||||
continue;
|
||||
|
||||
drv = scmi_proto_driver_get(protocol_id);
|
||||
if (!drv) {
|
||||
dev_dbg(dev, "Ignore unsupported SCMI protocol %#x\n",
|
||||
protocol_id);
|
||||
|
||||
@@ -139,6 +139,19 @@ config PINCTRL_IMXRT
|
||||
only parses the 'fsl,pins' property and configure related
|
||||
registers.
|
||||
|
||||
config PINCTRL_IMX_SCMI
|
||||
bool "IMX pinctrl SCMI driver"
|
||||
depends on ARCH_IMX9 && PINCTRL_FULL
|
||||
select PINCTRL_IMX
|
||||
help
|
||||
This provides a simple pinctrl driver for i.MX SoC which supports
|
||||
SCMI. This feature depends on device tree configuration. This driver
|
||||
is different from the linux one, this is a simple implementation,
|
||||
only parses the 'fsl,pins' property and configure related
|
||||
registers.
|
||||
|
||||
Say Y here to enable the imx pinctrl SCMI driver
|
||||
|
||||
config PINCTRL_VYBRID
|
||||
bool "Vybrid (vf610) pinctrl driver"
|
||||
depends on ARCH_VF610 && PINCTRL_FULL
|
||||
|
||||
@@ -11,3 +11,4 @@ obj-$(CONFIG_PINCTRL_IMX93) += pinctrl-imx93.o
|
||||
obj-$(CONFIG_PINCTRL_MXS) += pinctrl-mxs.o
|
||||
obj-$(CONFIG_PINCTRL_VYBRID) += pinctrl-vf610.o
|
||||
obj-$(CONFIG_PINCTRL_IMXRT) += pinctrl-imxrt.o
|
||||
obj-$(CONFIG_PINCTRL_IMX_SCMI) += pinctrl-imx-scmi.o
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2025 NXP
|
||||
*/
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/mach-imx/sys_proto.h>
|
||||
#include <dm.h>
|
||||
#include <dm/device_compat.h>
|
||||
#include <dm/devres.h>
|
||||
#include <dm/pinctrl.h>
|
||||
#include <scmi_agent.h>
|
||||
#include <scmi_agent-uclass.h>
|
||||
#include <scmi_protocols.h>
|
||||
|
||||
#include "pinctrl-imx.h"
|
||||
|
||||
#define DAISY_OFFSET_IMX95 0x408
|
||||
|
||||
/* SCMI pin control types */
|
||||
#define PINCTRL_TYPE_MUX 192
|
||||
#define PINCTRL_TYPE_CONFIG 193
|
||||
#define PINCTRL_TYPE_DAISY_ID 194
|
||||
#define PINCTRL_TYPE_DAISY_CFG 195
|
||||
#define PINCTRL_NUM_CFGS_SHIFT 2
|
||||
|
||||
struct imx_scmi_pinctrl_priv {
|
||||
u16 daisy_offset;
|
||||
};
|
||||
|
||||
static int imx_pinconf_scmi_set(struct udevice *dev, u32 mux_ofs, u32 mux, u32 config_val,
|
||||
u32 input_ofs, u32 input_val)
|
||||
{
|
||||
struct imx_scmi_pinctrl_priv *priv = dev_get_priv(dev);
|
||||
int ret, num_cfgs = 0;
|
||||
struct scmi_msg msg;
|
||||
|
||||
/* Call SCMI API to set the pin mux and configuration. */
|
||||
struct scmi_pinctrl_config_set_out out;
|
||||
struct scmi_pinctrl_config_set_in in = {
|
||||
.identifier = mux_ofs / 4,
|
||||
.function_id = 0xFFFFFFFF,
|
||||
.attributes = 0,
|
||||
};
|
||||
|
||||
if (mux_ofs) {
|
||||
in.configs[num_cfgs].type = PINCTRL_TYPE_MUX;
|
||||
in.configs[num_cfgs].val = mux;
|
||||
num_cfgs++;
|
||||
}
|
||||
|
||||
if (config_val) {
|
||||
in.configs[num_cfgs].type = PINCTRL_TYPE_CONFIG;
|
||||
in.configs[num_cfgs].val = config_val;
|
||||
num_cfgs++;
|
||||
}
|
||||
|
||||
if (input_ofs) {
|
||||
in.configs[num_cfgs].type = PINCTRL_TYPE_DAISY_ID;
|
||||
in.configs[num_cfgs].val = (input_ofs - priv->daisy_offset) / 4;
|
||||
num_cfgs++;
|
||||
in.configs[num_cfgs].type = PINCTRL_TYPE_DAISY_CFG;
|
||||
in.configs[num_cfgs].val = input_val;
|
||||
num_cfgs++;
|
||||
}
|
||||
|
||||
/* Update the number of configs sent in this call. */
|
||||
in.attributes = num_cfgs << PINCTRL_NUM_CFGS_SHIFT;
|
||||
|
||||
msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_PINCTRL,
|
||||
SCMI_MSG_PINCTRL_CONFIG_SET, in, out);
|
||||
|
||||
ret = devm_scmi_process_msg(dev, &msg);
|
||||
if (ret || out.status) {
|
||||
dev_err(dev, "Failed to set PAD = %d, daisy = %d, scmi_err = %d, ret = %d\n",
|
||||
mux_ofs / 4, input_ofs / 4, out.status, ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int imx_pinctrl_set_state_scmi(struct udevice *dev, struct udevice *config)
|
||||
{
|
||||
int mux_ofs, mux, config_val, input_reg, input_val;
|
||||
u32 *pin_data;
|
||||
int i, j = 0;
|
||||
int npins;
|
||||
int ret;
|
||||
|
||||
ret = imx_pinctrl_set_state_common(dev, config, FSL_PIN_SIZE,
|
||||
&pin_data, &npins);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Refer to linux documentation for details:
|
||||
* Documentation/devicetree/bindings/pinctrl/fsl,imx-pinctrl.txt
|
||||
*/
|
||||
for (i = 0; i < npins; i++) {
|
||||
mux_ofs = pin_data[j++];
|
||||
/* Skip config_reg */
|
||||
j++;
|
||||
input_reg = pin_data[j++];
|
||||
|
||||
mux = pin_data[j++];
|
||||
input_val = pin_data[j++];
|
||||
config_val = pin_data[j++];
|
||||
|
||||
if (config_val & IMX_PAD_SION)
|
||||
mux |= IOMUXC_CONFIG_SION;
|
||||
|
||||
config_val &= ~IMX_PAD_SION;
|
||||
|
||||
ret = imx_pinconf_scmi_set(dev, mux_ofs, mux, config_val, input_reg, input_val);
|
||||
if (ret && ret != -EPERM) {
|
||||
dev_err(dev, "Set pin %d, mux %d, val %d, error\n",
|
||||
mux_ofs, mux, config_val);
|
||||
}
|
||||
}
|
||||
|
||||
devm_kfree(dev, pin_data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct pinctrl_ops imx_scmi_pinctrl_ops = {
|
||||
.set_state = imx_pinctrl_set_state_scmi,
|
||||
};
|
||||
|
||||
static int imx_scmi_pinctrl_probe(struct udevice *dev)
|
||||
{
|
||||
struct imx_scmi_pinctrl_priv *priv = dev_get_priv(dev);
|
||||
|
||||
if (IS_ENABLED(CONFIG_IMX95))
|
||||
priv->daisy_offset = DAISY_OFFSET_IMX95;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
return devm_scmi_of_get_channel(dev);
|
||||
}
|
||||
|
||||
static int imx_scmi_pinctrl_bind(struct udevice *dev)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_IMX95))
|
||||
return 0;
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
U_BOOT_DRIVER(scmi_pinctrl_imx) = {
|
||||
.name = "scmi_pinctrl_imx",
|
||||
.id = UCLASS_PINCTRL,
|
||||
.bind = imx_scmi_pinctrl_bind,
|
||||
.probe = imx_scmi_pinctrl_probe,
|
||||
.priv_auto = sizeof(struct imx_scmi_pinctrl_priv),
|
||||
.ops = &imx_scmi_pinctrl_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
||||
static struct scmi_proto_match match[] = {
|
||||
{ .proto_id = SCMI_PROTOCOL_ID_PINCTRL },
|
||||
{ /* Sentinel */ }
|
||||
};
|
||||
|
||||
U_BOOT_SCMI_PROTO_DRIVER(scmi_pinctrl_imx, match);
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <power-domain.h>
|
||||
#include <power-domain-uclass.h>
|
||||
#include <scmi_agent.h>
|
||||
#include <scmi_agent-uclass.h>
|
||||
#include <scmi_protocols.h>
|
||||
#include <dm/device_compat.h>
|
||||
|
||||
@@ -190,3 +191,10 @@ U_BOOT_DRIVER(scmi_power_domain) = {
|
||||
.probe = scmi_power_domain_probe,
|
||||
.priv_auto = sizeof(struct scmi_power_domain_priv),
|
||||
};
|
||||
|
||||
static struct scmi_proto_match match[] = {
|
||||
{ .proto_id = SCMI_PROTOCOL_ID_POWER_DOMAIN },
|
||||
{ /* Sentinel */ }
|
||||
};
|
||||
|
||||
U_BOOT_SCMI_PROTO_DRIVER(scmi_power_domain, match);
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <scmi_agent.h>
|
||||
#include <scmi_agent-uclass.h>
|
||||
#include <scmi_protocols.h>
|
||||
#include <asm/types.h>
|
||||
#include <dm/device.h>
|
||||
@@ -202,3 +203,10 @@ U_BOOT_DRIVER(scmi_voltage_domain) = {
|
||||
.id = UCLASS_NOP,
|
||||
.bind = scmi_regulator_bind,
|
||||
};
|
||||
|
||||
static struct scmi_proto_match match[] = {
|
||||
{ .proto_id = SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN },
|
||||
{ /* Sentinel */ }
|
||||
};
|
||||
|
||||
U_BOOT_SCMI_PROTO_DRIVER(scmi_voltage_domain, match);
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <errno.h>
|
||||
#include <reset-uclass.h>
|
||||
#include <scmi_agent.h>
|
||||
#include <scmi_agent-uclass.h>
|
||||
#include <scmi_protocols.h>
|
||||
#include <asm/types.h>
|
||||
|
||||
@@ -81,3 +82,10 @@ U_BOOT_DRIVER(scmi_reset_domain) = {
|
||||
.ops = &scmi_reset_domain_ops,
|
||||
.probe = scmi_reset_probe,
|
||||
};
|
||||
|
||||
static struct scmi_proto_match match[] = {
|
||||
{ .proto_id = SCMI_PROTOCOL_ID_RESET_DOMAIN },
|
||||
{ /* Sentinel */ }
|
||||
};
|
||||
|
||||
U_BOOT_SCMI_PROTO_DRIVER(scmi_reset_domain, match);
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright 2025 NXP
|
||||
*/
|
||||
|
||||
#ifndef __IMX95_EVK_H
|
||||
#define __IMX95_EVK_H
|
||||
|
||||
#include <linux/sizes.h>
|
||||
#include <linux/stringify.h>
|
||||
#include <asm/arch/imx-regs.h>
|
||||
|
||||
#define CFG_SYS_INIT_RAM_ADDR 0x90000000
|
||||
#define CFG_SYS_INIT_RAM_SIZE 0x200000
|
||||
|
||||
#define CFG_SYS_SDRAM_BASE 0x90000000
|
||||
#define PHYS_SDRAM 0x90000000
|
||||
/* Totally 16GB */
|
||||
#define PHYS_SDRAM_SIZE 0x70000000 /* 2GB - 256MB DDR */
|
||||
#define PHYS_SDRAM_2_SIZE 0x380000000 /* 14GB */
|
||||
|
||||
#define WDOG_BASE_ADDR WDG3_BASE_ADDR
|
||||
|
||||
#endif
|
||||
+16
-3
@@ -157,7 +157,9 @@ enum imx8image_cmd {
|
||||
CMD_SOC_TYPE,
|
||||
CMD_CONTAINER,
|
||||
CMD_IMAGE,
|
||||
CMD_DATA
|
||||
CMD_DATA,
|
||||
CMD_DUMMY_V2X,
|
||||
CMD_HOLD,
|
||||
};
|
||||
|
||||
enum imx8image_core_type {
|
||||
@@ -169,7 +171,9 @@ enum imx8image_core_type {
|
||||
CFG_A35,
|
||||
CFG_A55,
|
||||
CFG_A53,
|
||||
CFG_A72
|
||||
CFG_A72,
|
||||
CFG_M33,
|
||||
CFG_OEI,
|
||||
};
|
||||
|
||||
enum imx8image_fld_types {
|
||||
@@ -208,7 +212,10 @@ typedef enum option_type {
|
||||
FILEOFF,
|
||||
MSG_BLOCK,
|
||||
SENTINEL,
|
||||
UPOWER
|
||||
UPOWER,
|
||||
OEI,
|
||||
DUMMY_V2X,
|
||||
HOLD,
|
||||
} option_type_t;
|
||||
|
||||
typedef struct {
|
||||
@@ -227,12 +234,16 @@ typedef struct {
|
||||
#define CORE_CA35 4
|
||||
#define CORE_CA72 5
|
||||
#define CORE_SECO 6
|
||||
#define CORE_M33 7
|
||||
|
||||
#define CORE_ULP_CM33 0x1
|
||||
#define CORE_ULP_CA35 0x2
|
||||
#define CORE_ULP_UPOWER 0x4
|
||||
#define CORE_ULP_SENTINEL 0x6
|
||||
|
||||
#define CORE_IMX95_M33P 0
|
||||
#define CORE_IMX95_A55C0 2
|
||||
|
||||
#define SC_R_OTP 357U
|
||||
#define SC_R_DEBUG 354U
|
||||
#define SC_R_ROM_0 236U
|
||||
@@ -246,10 +257,12 @@ typedef struct {
|
||||
#define IMG_TYPE_EXEC 0x03 /* Executable image type */
|
||||
#define IMG_TYPE_DATA 0x04 /* Data image type */
|
||||
#define IMG_TYPE_DCD_DDR 0x05 /* DCD/DDR image type */
|
||||
#define IMG_TYPE_OEI 0x05 /* Optional Executable image type */
|
||||
#define IMG_TYPE_SECO 0x06 /* SECO image type */
|
||||
#define IMG_TYPE_SENTINEL 0x06 /* SENTINEL image type */
|
||||
#define IMG_TYPE_PROV 0x07 /* Provisioning image type */
|
||||
#define IMG_TYPE_DEK 0x08 /* DEK validation type */
|
||||
#define IMG_TYPE_V2X_DUMMY 0x0E /* V2X Dummy image */
|
||||
|
||||
#define IMG_TYPE_SHIFT 0
|
||||
#define IMG_TYPE_MASK 0x1f
|
||||
|
||||
@@ -27,6 +27,7 @@ struct scmi_channel;
|
||||
* @clock_dev: SCMI clock protocol device
|
||||
* @resetdom_dev: SCMI reset domain protocol device
|
||||
* @voltagedom_dev: SCMI voltage domain protocol device
|
||||
* @pinctrl_dev: SCMI pin control protocol device
|
||||
*/
|
||||
struct scmi_agent_priv {
|
||||
u32 version;
|
||||
@@ -43,6 +44,7 @@ struct scmi_agent_priv {
|
||||
struct udevice *clock_dev;
|
||||
struct udevice *resetdom_dev;
|
||||
struct udevice *voltagedom_dev;
|
||||
struct udevice *pinctrl_dev;
|
||||
};
|
||||
|
||||
static inline u32 scmi_version(struct udevice *dev)
|
||||
@@ -115,4 +117,19 @@ struct scmi_agent_ops {
|
||||
struct scmi_msg *msg);
|
||||
};
|
||||
|
||||
struct scmi_proto_match {
|
||||
unsigned int proto_id;
|
||||
};
|
||||
|
||||
struct scmi_proto_driver {
|
||||
struct driver *driver;
|
||||
const struct scmi_proto_match *match;
|
||||
};
|
||||
|
||||
#define U_BOOT_SCMI_PROTO_DRIVER(__name, __match) \
|
||||
ll_entry_declare(struct scmi_proto_driver, __name, scmi_proto_driver) = { \
|
||||
.driver = llsym(struct driver, __name, driver), \
|
||||
.match = __match, \
|
||||
}
|
||||
|
||||
#endif /* _SCMI_TRANSPORT_UCLASS_H */
|
||||
|
||||
+103
-1
@@ -24,6 +24,8 @@ enum scmi_std_protocol {
|
||||
SCMI_PROTOCOL_ID_SENSOR = 0x15,
|
||||
SCMI_PROTOCOL_ID_RESET_DOMAIN = 0x16,
|
||||
SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN = 0x17,
|
||||
SCMI_PROTOCOL_ID_PINCTRL = 0x19,
|
||||
SCMI_PROTOCOL_ID_IMX_MISC = 0x84,
|
||||
};
|
||||
|
||||
enum scmi_status_code {
|
||||
@@ -49,6 +51,10 @@ enum scmi_discovery_id {
|
||||
SCMI_PROTOCOL_MESSAGE_ATTRIBUTES = 0x2,
|
||||
};
|
||||
|
||||
enum scmi_imx_misc_message_id {
|
||||
SCMI_MISC_ROM_PASSOVER_GET = 0x7
|
||||
};
|
||||
|
||||
/*
|
||||
* SCMI Base Protocol
|
||||
*/
|
||||
@@ -139,7 +145,7 @@ struct scmi_base_discover_impl_version_out {
|
||||
struct scmi_base_discover_list_protocols_out {
|
||||
s32 status;
|
||||
u32 num_protocols;
|
||||
u32 protocols[3];
|
||||
u32 protocols[];
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -725,12 +731,15 @@ int scmi_pwd_name_get(struct udevice *dev, u32 domain_id, u8 **name);
|
||||
/*
|
||||
* SCMI Clock Protocol
|
||||
*/
|
||||
#define CLOCK_PROTOCOL_VERSION_3_0 0x30000
|
||||
|
||||
enum scmi_clock_message_id {
|
||||
SCMI_CLOCK_ATTRIBUTES = 0x3,
|
||||
SCMI_CLOCK_RATE_SET = 0x5,
|
||||
SCMI_CLOCK_RATE_GET = 0x6,
|
||||
SCMI_CLOCK_CONFIG_SET = 0x7,
|
||||
SCMI_CLOCK_PARENT_SET = 0xD,
|
||||
SCMI_CLOCK_GET_PERMISSIONS = 0xF,
|
||||
};
|
||||
|
||||
#define SCMI_CLK_PROTO_ATTR_COUNT_MASK GENMASK(15, 0)
|
||||
@@ -769,6 +778,7 @@ struct scmi_clk_attribute_in {
|
||||
struct scmi_clk_attribute_out {
|
||||
s32 status;
|
||||
u32 attributes;
|
||||
#define CLK_HAS_RESTRICTIONS(x) ((x) & BIT(1))
|
||||
char clock_name[SCMI_CLOCK_NAME_LENGTH_MAX];
|
||||
};
|
||||
|
||||
@@ -833,6 +843,45 @@ struct scmi_clk_rate_set_out {
|
||||
s32 status;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct scmi_clk_parent_state_in - Message payload for CLOCK_PARENT_SET command
|
||||
* @clock_id: SCMI clock ID
|
||||
* @parent_clk: SCMI clock ID
|
||||
*/
|
||||
struct scmi_clk_parent_set_in {
|
||||
u32 clock_id;
|
||||
u32 parent_clk;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct scmi_clk_parent_set_out - Response payload for CLOCK_PARENT_SET command
|
||||
* @status: SCMI command status
|
||||
*/
|
||||
struct scmi_clk_parent_set_out {
|
||||
s32 status;
|
||||
};
|
||||
|
||||
/**
|
||||
* @clock_id: Identifier for the clock device.
|
||||
*/
|
||||
struct scmi_clk_get_permissions_in {
|
||||
u32 clock_id;
|
||||
};
|
||||
|
||||
/**
|
||||
* @status: Negative 32-bit integers are used to return error status codes.
|
||||
* @permissions: Bit[31] Clock state control, Bit[30] Clock parent control,
|
||||
* Bit[29] Clock rate control, Bits[28:0] Reserved, must be zero.
|
||||
*/
|
||||
struct scmi_clk_get_permissions_out {
|
||||
s32 status;
|
||||
u32 permissions;
|
||||
};
|
||||
|
||||
#define SUPPORT_CLK_STAT_CONTROL BIT(31)
|
||||
#define SUPPORT_CLK_PARENT_CONTROL BIT(30)
|
||||
#define SUPPORT_CLK_RATE_CONTROL BIT(29)
|
||||
|
||||
/*
|
||||
* SCMI Reset Domain Protocol
|
||||
*/
|
||||
@@ -1005,4 +1054,57 @@ struct scmi_voltd_level_get_out {
|
||||
s32 voltage_level;
|
||||
};
|
||||
|
||||
/* SCMI Pinctrl Protocol */
|
||||
enum scmi_pinctrl_message_id {
|
||||
SCMI_MSG_PINCTRL_CONFIG_SET = 0x6
|
||||
};
|
||||
|
||||
struct scmi_pin_config {
|
||||
u32 type;
|
||||
u32 val;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct scmi_pad_config_set_in - Message payload for PAD_CONFIG_SET command
|
||||
* @identifier: Identifier for the pin or group.
|
||||
* @function_id: Identifier for the function selected to be enabled
|
||||
* for the selected pin or group. This field is set to
|
||||
* 0xFFFFFFFF if no function should be enabled by the
|
||||
* pin or group.
|
||||
* @attributes: Bits[31:11] Reserved, must be zero.
|
||||
* Bit[10] Function valid.
|
||||
* Bits[9:2] Number of configurations to set.
|
||||
* Bits[1:0] Selector: Whether the identifier field
|
||||
* refers to a pin or a group.
|
||||
* @configs: Array of configurations.
|
||||
*/
|
||||
struct scmi_pinctrl_config_set_in {
|
||||
u32 identifier;
|
||||
u32 function_id;
|
||||
u32 attributes;
|
||||
struct scmi_pin_config configs[4];
|
||||
};
|
||||
|
||||
struct scmi_pinctrl_config_set_out {
|
||||
s32 status;
|
||||
};
|
||||
|
||||
/* SCMI Perf Protocol */
|
||||
enum scmi_perf_message_id {
|
||||
SCMI_PERF_DOMAIN_ATTRIBUTES = 0x3,
|
||||
SCMI_PERF_DESCRIBE_LEVELS = 0x4,
|
||||
SCMI_PERF_LIMITS_SET = 0x5,
|
||||
SCMI_PERF_LIMITS_GET = 0x6,
|
||||
SCMI_PERF_LEVEL_SET = 0x7,
|
||||
SCMI_PERF_LEVEL_GET = 0x8
|
||||
};
|
||||
|
||||
struct scmi_perf_in {
|
||||
u32 domain_id;
|
||||
u32 perf_level;
|
||||
};
|
||||
|
||||
struct scmi_perf_out {
|
||||
s32 status;
|
||||
};
|
||||
#endif /* _SCMI_PROTOCOLS_H */
|
||||
|
||||
@@ -1663,6 +1663,16 @@ Properties / Entry arguments:
|
||||
|
||||
|
||||
|
||||
.. _etype_nxp_header_ddrfw:
|
||||
|
||||
Entry: nxp-header-ddrfw: add a header to DDR PHY firmware images
|
||||
----------------------------------------------------------------
|
||||
|
||||
This entry is used to combine DDR PHY firmware images and their byte counts
|
||||
together. See imx95_evk.rst for how to get DDR PHY Firmware Images.
|
||||
|
||||
|
||||
|
||||
.. _etype_opensbi:
|
||||
|
||||
Entry: opensbi: RISC-V OpenSBI fw_dynamic blob
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
# Copyright 2025 NXP
|
||||
|
||||
from binman.etype.section import Entry_section
|
||||
|
||||
class Entry_nxp_header_ddrfw(Entry_section):
|
||||
"""Add a header to DDR PHY firmware images
|
||||
|
||||
This entry is used for i.MX95 to combine DDR PHY firmware images and their
|
||||
byte counts together.
|
||||
|
||||
See imx95_evk.rst for how to get DDR PHY Firmware Images.
|
||||
"""
|
||||
|
||||
def __init__(self, section, etype, node):
|
||||
super().__init__(section, etype, node)
|
||||
|
||||
def BuildSectionData(self, required):
|
||||
section_data = bytearray()
|
||||
header_data = bytearray()
|
||||
|
||||
for entry in self._entries.values():
|
||||
entry_data = entry.GetData(required)
|
||||
|
||||
section_data += entry_data
|
||||
header_data += entry.contents_size.to_bytes(4, 'little')
|
||||
|
||||
return header_data + section_data
|
||||
@@ -104,6 +104,8 @@ PRE_LOAD_VERSION = 0x11223344.to_bytes(4, 'big')
|
||||
PRE_LOAD_HDR_SIZE = 0x00001000.to_bytes(4, 'big')
|
||||
TI_BOARD_CONFIG_DATA = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||
TI_UNSECURE_DATA = b'unsecuredata'
|
||||
IMX_LPDDR_IMEM_DATA = b'qwertyuiop1234567890'
|
||||
IMX_LPDDR_DMEM_DATA = b'asdfghjklzxcvbnm'
|
||||
|
||||
# Subdirectory of the input dir to use to put test FDTs
|
||||
TEST_FDT_SUBDIR = 'fdts'
|
||||
@@ -202,6 +204,8 @@ class TestFunctional(unittest.TestCase):
|
||||
TestFunctional._MakeInputFile('fsp_m.bin', FSP_M_DATA)
|
||||
TestFunctional._MakeInputFile('fsp_s.bin', FSP_S_DATA)
|
||||
TestFunctional._MakeInputFile('fsp_t.bin', FSP_T_DATA)
|
||||
TestFunctional._MakeInputFile('lpddr5_imem.bin', IMX_LPDDR_IMEM_DATA)
|
||||
TestFunctional._MakeInputFile('lpddr5_dmem.bin', IMX_LPDDR_DMEM_DATA)
|
||||
|
||||
cls._elf_testdir = os.path.join(cls._indir, 'elftest')
|
||||
elf_test.BuildElfTestFiles(cls._elf_testdir)
|
||||
@@ -7848,6 +7852,13 @@ fdt fdtmap Extract the devicetree blob from the fdtmap
|
||||
"""Test that binman can produce an iMX8 image"""
|
||||
self._DoTestFile('339_nxp_imx8.dts')
|
||||
|
||||
def testNxpHeaderDdrfw(self):
|
||||
"""Test that binman can add a header to DDR PHY firmware images"""
|
||||
data = self._DoReadFile('346_nxp_ddrfw_imx95.dts')
|
||||
self.assertEqual(len(IMX_LPDDR_IMEM_DATA).to_bytes(4, 'little') +
|
||||
len(IMX_LPDDR_DMEM_DATA).to_bytes(4, 'little') +
|
||||
IMX_LPDDR_IMEM_DATA + IMX_LPDDR_DMEM_DATA, data)
|
||||
|
||||
def testFitSignSimple(self):
|
||||
"""Test that image with FIT and signature nodes can be signed"""
|
||||
if not elf.ELF_TOOLS:
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
binman {
|
||||
imx-lpddr {
|
||||
type = "nxp-header-ddrfw";
|
||||
|
||||
imx-lpddr-imem {
|
||||
filename = "lpddr5_imem.bin";
|
||||
type = "blob-ext";
|
||||
};
|
||||
|
||||
imx-lpddr-dmem {
|
||||
filename = "lpddr5_dmem.bin";
|
||||
type = "blob-ext";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
+131
-16
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "imx8image.h"
|
||||
#include <image.h>
|
||||
#include <linux/sizes.h>
|
||||
|
||||
static int p_idx;
|
||||
static int sector_size;
|
||||
@@ -54,7 +55,9 @@ static table_entry_t imx8image_cmds[] = {
|
||||
{CMD_CONTAINER, "CONTAINER", "new container", },
|
||||
{CMD_IMAGE, "IMAGE", "new image", },
|
||||
{CMD_DATA, "DATA", "new data", },
|
||||
{-1, "", "", },
|
||||
{CMD_DUMMY_V2X, "DUMMY_V2X", "v2x", },
|
||||
{CMD_HOLD, "HOLD", "hold", },
|
||||
{-1, "", "", }
|
||||
};
|
||||
|
||||
static table_entry_t imx8image_core_entries[] = {
|
||||
@@ -66,7 +69,9 @@ static table_entry_t imx8image_core_entries[] = {
|
||||
{CFG_A55, "A55", "A55 core", },
|
||||
{CFG_A53, "A53", "A53 core", },
|
||||
{CFG_A72, "A72", "A72 core", },
|
||||
{-1, "", "", },
|
||||
{CFG_OEI, "OEI", "OEI", },
|
||||
{CFG_M33, "M33", "M33 core", },
|
||||
{-1, "", "", }
|
||||
};
|
||||
|
||||
static table_entry_t imx8image_sector_size[] = {
|
||||
@@ -144,6 +149,14 @@ static void parse_cfg_cmd(image_t *param_stack, int32_t cmd, char *token,
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
case CMD_DUMMY_V2X:
|
||||
param_stack[p_idx].option = DUMMY_V2X;
|
||||
param_stack[p_idx++].entry = (uint32_t)strtoll(token, NULL, 0);
|
||||
break;
|
||||
case CMD_HOLD:
|
||||
param_stack[p_idx].option = HOLD;
|
||||
param_stack[p_idx].entry = (uint32_t)strtoll(token, NULL, 0);
|
||||
param_stack[p_idx++].filename = NULL;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -221,6 +234,16 @@ static void parse_cfg_fld(image_t *param_stack, int32_t *cmd, char *token,
|
||||
(*cmd == CMD_DATA) ? DATA : AP;
|
||||
param_stack[p_idx].filename = token;
|
||||
break;
|
||||
case CFG_OEI:
|
||||
param_stack[p_idx].option = OEI;
|
||||
param_stack[p_idx].filename = token;
|
||||
param_stack[p_idx].ext = CORE_CM4_0;
|
||||
break;
|
||||
case CFG_M33:
|
||||
param_stack[p_idx].option = M40;
|
||||
param_stack[p_idx].ext = 0;
|
||||
param_stack[p_idx].filename = token;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case CFG_LOAD_ADDR:
|
||||
@@ -238,9 +261,15 @@ static void parse_cfg_fld(image_t *param_stack, int32_t *cmd, char *token,
|
||||
case CFG_A53:
|
||||
case CFG_A55:
|
||||
case CFG_A72:
|
||||
case CFG_M33:
|
||||
param_stack[p_idx++].entry =
|
||||
(uint32_t)strtoll(token, NULL, 0);
|
||||
break;
|
||||
case CFG_OEI:
|
||||
param_stack[p_idx].dst = (uint32_t)strtoll(token, NULL, 0);
|
||||
param_stack[p_idx].entry = param_stack[p_idx].dst + 1;
|
||||
p_idx++;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
@@ -549,6 +578,7 @@ static void set_image_array_entry(flash_header_v3_t *container,
|
||||
char *tmp_filename, bool dcd_skip)
|
||||
{
|
||||
uint64_t entry = image_stack->entry;
|
||||
uint64_t dst = image_stack->dst;
|
||||
uint64_t core = image_stack->ext;
|
||||
uint32_t meta;
|
||||
char *tmp_name = "";
|
||||
@@ -558,7 +588,9 @@ static void set_image_array_entry(flash_header_v3_t *container,
|
||||
img->offset = offset; /* Is re-adjusted later */
|
||||
img->size = size;
|
||||
|
||||
set_image_hash(img, tmp_filename, IMAGE_HASH_ALGO_DEFAULT);
|
||||
if (type != DUMMY_V2X) {
|
||||
set_image_hash(img, tmp_filename, IMAGE_HASH_ALGO_DEFAULT);
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case SECO:
|
||||
@@ -580,6 +612,27 @@ static void set_image_array_entry(flash_header_v3_t *container,
|
||||
img->dst = 0xe4000000; /* S400 IRAM base */
|
||||
img->entry = 0xe4000000;
|
||||
break;
|
||||
case OEI:
|
||||
if (soc != IMX9) {
|
||||
fprintf(stderr, "Error: invalid core id: %" PRIi64 "\n", core);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
img->hab_flags |= IMG_TYPE_OEI;
|
||||
if (core == CORE_CM4_0) {
|
||||
img->hab_flags |= CORE_ULP_CM33 << BOOT_IMG_FLAGS_CORE_SHIFT;
|
||||
meta = CORE_IMX95_M33P;
|
||||
|
||||
} else {
|
||||
img->hab_flags |= CORE_ULP_CA35 << BOOT_IMG_FLAGS_CORE_SHIFT;
|
||||
meta = CORE_IMX95_A55C0;
|
||||
}
|
||||
tmp_name = "OEI";
|
||||
img->dst = (dst ? dst : entry);
|
||||
img->entry = entry;
|
||||
img->meta = meta;
|
||||
custom_partition = 0;
|
||||
break;
|
||||
case AP:
|
||||
if (soc == QX && core == CORE_CA35) {
|
||||
meta = IMAGE_A35_DEFAULT_META(custom_partition);
|
||||
@@ -587,8 +640,10 @@ static void set_image_array_entry(flash_header_v3_t *container,
|
||||
meta = IMAGE_A53_DEFAULT_META(custom_partition);
|
||||
} else if (soc == QM && core == CORE_CA72) {
|
||||
meta = IMAGE_A72_DEFAULT_META(custom_partition);
|
||||
} else if (((soc == ULP) || (soc == IMX9)) && core == CORE_CA35) {
|
||||
} else if ((soc == ULP) && core == CORE_CA35) {
|
||||
meta = 0;
|
||||
} else if ((soc == IMX9) && core == CORE_CA35) {
|
||||
meta = CORE_IMX95_A55C0;
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"Error: invalid AP core id: %" PRIu64 "\n",
|
||||
@@ -687,6 +742,15 @@ static void set_image_array_entry(flash_header_v3_t *container,
|
||||
img->entry = 0x28300200;
|
||||
}
|
||||
break;
|
||||
case DUMMY_V2X:
|
||||
img->hab_flags |= IMG_TYPE_V2X_DUMMY;
|
||||
img->hab_flags |= CORE_SC << BOOT_IMG_FLAGS_CORE_SHIFT;
|
||||
tmp_name = "V2X Dummy";
|
||||
set_image_hash(img, "/dev/null", IMAGE_HASH_ALGO_DEFAULT);
|
||||
img->dst = entry;
|
||||
img->entry = entry;
|
||||
img->size = 0; /* dummy image has no size */
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "unrecognized image type (%d)\n", type);
|
||||
exit(EXIT_FAILURE);
|
||||
@@ -709,15 +773,26 @@ void set_container(flash_header_v3_t *container, uint16_t sw_version,
|
||||
fprintf(stdout, "container flags: 0x%x\n", container->flags);
|
||||
}
|
||||
|
||||
static int get_container_image_start_pos(image_t *image_stack, uint32_t align)
|
||||
static int get_container_image_start_pos(image_t *image_stack, uint32_t align, uint32_t *v2x)
|
||||
{
|
||||
image_t *img_sp = image_stack;
|
||||
/*8K total container header*/
|
||||
int file_off = CONTAINER_IMAGE_ARRAY_START_OFFSET;
|
||||
FILE *fd = NULL;
|
||||
flash_header_v3_t header;
|
||||
flash_header_v3_t *header;
|
||||
flash_header_v3_t *header2;
|
||||
void *p;
|
||||
int ret;
|
||||
|
||||
p = calloc(1, SZ_4K);
|
||||
if (!p) {
|
||||
fprintf(stderr, "Fail to alloc 4K memory\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
header = p;
|
||||
header2 = p + FIRST_CONTAINER_HEADER_LENGTH;
|
||||
|
||||
while (img_sp->option != NO_IMG) {
|
||||
if (img_sp->option == APPEND) {
|
||||
fd = fopen(img_sp->filename, "r");
|
||||
@@ -726,7 +801,7 @@ static int get_container_image_start_pos(image_t *image_stack, uint32_t align)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = fread(&header, sizeof(header), 1, fd);
|
||||
ret = fread(header, SZ_4K, 1, fd);
|
||||
if (ret != 1) {
|
||||
printf("Failure Read header %d\n", ret);
|
||||
exit(EXIT_FAILURE);
|
||||
@@ -734,19 +809,27 @@ static int get_container_image_start_pos(image_t *image_stack, uint32_t align)
|
||||
|
||||
fclose(fd);
|
||||
|
||||
if (header.tag != IVT_HEADER_TAG_B0) {
|
||||
fprintf(stderr, "header tag mismatched file %s\n", img_sp->filename);
|
||||
if (header->tag != IVT_HEADER_TAG_B0) {
|
||||
fprintf(stderr, "header tag mismatched \n");
|
||||
exit(EXIT_FAILURE);
|
||||
} else {
|
||||
file_off +=
|
||||
header.img[header.num_images - 1].size;
|
||||
file_off = ALIGN(file_off, align);
|
||||
if (header2->tag != IVT_HEADER_TAG_B0) {
|
||||
file_off += header->img[header->num_images - 1].size;
|
||||
file_off = ALIGN(file_off, align);
|
||||
} else {
|
||||
file_off = header2->img[header2->num_images - 1].offset + FIRST_CONTAINER_HEADER_LENGTH;
|
||||
file_off += header2->img[header2->num_images - 1].size;
|
||||
file_off = ALIGN(file_off, align);
|
||||
fprintf(stderr, "Has 2nd container %x\n", file_off);
|
||||
*v2x = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
img_sp++;
|
||||
}
|
||||
|
||||
free(p);
|
||||
return file_off;
|
||||
}
|
||||
|
||||
@@ -838,6 +921,7 @@ static int build_container(soc_type_t soc, uint32_t sector_size,
|
||||
char *tmp_filename = NULL;
|
||||
uint32_t size = 0;
|
||||
uint32_t file_padding = 0;
|
||||
uint32_t v2x = false;
|
||||
int ret;
|
||||
|
||||
int container = -1;
|
||||
@@ -861,7 +945,7 @@ static int build_container(soc_type_t soc, uint32_t sector_size,
|
||||
set_imx_hdr_v3(&imx_header, 0);
|
||||
set_imx_hdr_v3(&imx_header, 1);
|
||||
|
||||
file_off = get_container_image_start_pos(image_stack, sector_size);
|
||||
file_off = get_container_image_start_pos(image_stack, sector_size, &v2x);
|
||||
fprintf(stdout, "container image offset (aligned):%x\n", file_off);
|
||||
|
||||
/* step through image stack and generate the header */
|
||||
@@ -870,6 +954,7 @@ static int build_container(soc_type_t soc, uint32_t sector_size,
|
||||
/* stop once we reach null terminator */
|
||||
while (img_sp->option != NO_IMG) {
|
||||
switch (img_sp->option) {
|
||||
case OEI:
|
||||
case AP:
|
||||
case M40:
|
||||
case M41:
|
||||
@@ -892,6 +977,30 @@ static int build_container(soc_type_t soc, uint32_t sector_size,
|
||||
file_off += ALIGN(sbuf.st_size, sector_size);
|
||||
break;
|
||||
|
||||
case DUMMY_V2X:
|
||||
if (container < 0) {
|
||||
fprintf(stderr, "No container found\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
tmp_filename = "dummy";
|
||||
set_image_array_entry(&imx_header.fhdr[container],
|
||||
soc,
|
||||
img_sp,
|
||||
file_off,
|
||||
0,
|
||||
tmp_filename,
|
||||
dcd_skip);
|
||||
img_sp->src = file_off;
|
||||
break;
|
||||
|
||||
case HOLD:
|
||||
if (container < 0) {
|
||||
fprintf(stderr, "No container found\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
file_off += ALIGN(img_sp->entry, sector_size);
|
||||
break;
|
||||
|
||||
case SECO:
|
||||
case SENTINEL:
|
||||
if (container < 0) {
|
||||
@@ -963,11 +1072,15 @@ static int build_container(soc_type_t soc, uint32_t sector_size,
|
||||
do {
|
||||
if (img_sp->option == APPEND) {
|
||||
copy_file(ofd, img_sp->filename, 0, 0);
|
||||
file_padding += FIRST_CONTAINER_HEADER_LENGTH;
|
||||
if (v2x)
|
||||
file_padding += FIRST_CONTAINER_HEADER_LENGTH * 2;
|
||||
else
|
||||
file_padding += FIRST_CONTAINER_HEADER_LENGTH;
|
||||
}
|
||||
img_sp++;
|
||||
} while (img_sp->option != NO_IMG);
|
||||
|
||||
fprintf(stderr, "%s: %x %d\n", __func__, file_padding, v2x);
|
||||
/* Add padding or skip appended container */
|
||||
ret = lseek(ofd, file_padding, SEEK_SET);
|
||||
if (ret < 0) {
|
||||
@@ -980,6 +1093,7 @@ static int build_container(soc_type_t soc, uint32_t sector_size,
|
||||
/* Note: Image offset are not contained in the image */
|
||||
tmp = flatten_container_header(&imx_header, container + 1,
|
||||
&size, file_padding);
|
||||
fprintf(stderr, "error writing image hdr %x\n", size);
|
||||
/* Write image header */
|
||||
if (write(ofd, tmp, size) != size) {
|
||||
fprintf(stderr, "error writing image hdr\n");
|
||||
@@ -1000,7 +1114,8 @@ static int build_container(soc_type_t soc, uint32_t sector_size,
|
||||
img_sp->option == AP || img_sp->option == DATA ||
|
||||
img_sp->option == SCD || img_sp->option == SCFW ||
|
||||
img_sp->option == SECO || img_sp->option == MSG_BLOCK ||
|
||||
img_sp->option == UPOWER || img_sp->option == SENTINEL) {
|
||||
img_sp->option == UPOWER || img_sp->option == SENTINEL ||
|
||||
img_sp->option == OEI) {
|
||||
copy_file_aligned(ofd, img_sp->filename, img_sp->src,
|
||||
sector_size);
|
||||
}
|
||||
@@ -1031,7 +1146,7 @@ int imx8image_copy_image(int outfd, struct image_tool_params *mparams)
|
||||
fprintf(stdout, "CONTAINER SW VERSION:\t0x%04x\n", sw_version);
|
||||
|
||||
build_container(soc, sector_size, emmc_fastboot,
|
||||
img_sp, dcd_skip, fuse_version, sw_version, outfd);
|
||||
img_sp, false, fuse_version, sw_version, outfd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,14 @@ for f in $blobs; do
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ $f = "m33-oei-ddrfw.bin" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ $f = "u-boot.bin" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ ! -f $tmp ]; then
|
||||
echo "WARNING '$tmp' not found, resulting binary may be not-functional" >&2
|
||||
|
||||
|
||||
Reference in New Issue
Block a user