From 104a956ffeede0836c5a6619aefde0f6da8693b4 Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Fri, 27 Jun 2025 11:25:43 +0800 Subject: [PATCH 01/27] drivers: intc_gicv3: enable dma-noncoherent support GIC redistributor on Some platform are connected to a non-coherent downstream interconnect, it need to use Non-cahable and Non-shareable access atttributes to access external memory. And also flush the data cache after CPU update related memory. Signed-off-by: Jiafei Pan --- drivers/interrupt_controller/Kconfig.gic | 9 +++++ drivers/interrupt_controller/intc_gicv3.c | 40 ++++++++++++++++++++--- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/drivers/interrupt_controller/Kconfig.gic b/drivers/interrupt_controller/Kconfig.gic index b482bf3336b1..c3175c74ff2f 100644 --- a/drivers/interrupt_controller/Kconfig.gic +++ b/drivers/interrupt_controller/Kconfig.gic @@ -73,4 +73,13 @@ config GIC_SAFE_CONFIG crash the OS has already been started. With this enabled, it will bypass GIC distributor configuration if it has been configured by other OS. +config GIC_V3_RDIST_DMA_NONCOHERENT + bool "GIC redistributor is DMA noncoherent" + depends on GIC_V3 + default n + help + GIC redistributor on Some platform are connected to a non-coherent + downstream interconnect, it need to use Non-cahable and Non-shareable + access atttributes to access external memory. + endif # CPU_CORTEX diff --git a/drivers/interrupt_controller/intc_gicv3.c b/drivers/interrupt_controller/intc_gicv3.c index cc22eaedb17f..afc5c6d4377b 100644 --- a/drivers/interrupt_controller/intc_gicv3.c +++ b/drivers/interrupt_controller/intc_gicv3.c @@ -1,11 +1,12 @@ /* * Copyright 2020 Broadcom - * Copyright 2024 NXP + * Copyright 2024-2025 NXP * Copyright 2025 Arm Limited and/or its affiliates * * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include #include @@ -111,7 +112,11 @@ static void arm_gic_lpi_setup(unsigned int intid, bool enable) *cfg &= ~BIT(0); } +#ifdef CONFIG_GIC_V3_RDIST_DMA_NONCOHERENT + arch_dcache_flush_and_invd_range(cfg, sizeof(*cfg)); +#else barrier_dsync_fence_full(); +#endif its_rdist_invall(); } @@ -123,7 +128,11 @@ static void arm_gic_lpi_set_priority(unsigned int intid, unsigned int prio) *cfg &= 0xfc; *cfg |= prio & 0xfc; +#ifdef CONFIG_GIC_V3_RDIST_DMA_NONCOHERENT + arch_dcache_flush_and_invd_range(cfg, sizeof(*cfg)); +#else barrier_dsync_fence_full(); +#endif its_rdist_invall(); } @@ -406,7 +415,7 @@ static void gicv3_rdist_setup_lpis(mem_addr_t rdist) unsigned int lpi_id_bits = MIN(GICD_TYPER_IDBITS(sys_read32(GICD_TYPER)), ITS_MAX_LPI_NRBITS); uintptr_t lpi_pend_table; - uint64_t reg; + uint64_t reg, tmp; uint32_t ctlr; /* If not, alloc a common prop table for all redistributors */ @@ -418,6 +427,11 @@ static void gicv3_rdist_setup_lpis(mem_addr_t rdist) lpi_pend_table = (uintptr_t)k_aligned_alloc(64 * 1024, LPI_PENDBASE_SZ(lpi_id_bits)); memset((void *)lpi_pend_table, 0, LPI_PENDBASE_SZ(lpi_id_bits)); +#ifdef CONFIG_GIC_V3_RDIST_DMA_NONCOHERENT + arch_dcache_flush_and_invd_range((void *)lpi_prop_table, LPI_PROPBASE_SZ(lpi_id_bits)); + arch_dcache_flush_and_invd_range((void *)lpi_pend_table, LPI_PENDBASE_SZ(lpi_id_bits)); +#endif + ctlr = sys_read32(rdist + GICR_CTLR); ctlr &= ~GICR_CTLR_ENABLE_LPIS; sys_write32(ctlr, rdist + GICR_CTLR); @@ -429,7 +443,16 @@ static void gicv3_rdist_setup_lpis(mem_addr_t rdist) (GIC_BASER_CACHE_INNERLIKE << GITR_PROPBASER_OUTER_CACHE_SHIFT) | ((lpi_id_bits - 1) & GITR_PROPBASER_ID_BITS_MASK); sys_write64(reg, rdist + GICR_PROPBASER); - /* TOFIX: check SHAREABILITY validity */ + /* Check SHAREABILITY validity */ + tmp = sys_read64(rdist + GICR_PROPBASER); +#ifdef CONFIG_GIC_V3_RDIST_DMA_NONCOHERENT + tmp &= ~MASK(GITR_PROPBASER_SHAREABILITY); +#endif + if (!(tmp & MASK(GITR_PROPBASER_SHAREABILITY))) { + reg &= ~(MASK(GITR_PROPBASER_SHAREABILITY) | MASK(GITR_PROPBASER_INNER_CACHE)); + reg |= GIC_BASER_CACHE_NCACHEABLE << GITR_PROPBASER_INNER_CACHE_SHIFT; + sys_write64(reg, rdist + GICR_PROPBASER); + } /* PENDBASE */ reg = (GIC_BASER_SHARE_INNER << GITR_PENDBASER_SHAREABILITY_SHIFT) | @@ -437,7 +460,16 @@ static void gicv3_rdist_setup_lpis(mem_addr_t rdist) (lpi_pend_table & (GITR_PENDBASER_ADDR_MASK << GITR_PENDBASER_ADDR_SHIFT)) | (GIC_BASER_CACHE_INNERLIKE << GITR_PENDBASER_OUTER_CACHE_SHIFT) | GITR_PENDBASER_PTZ; sys_write64(reg, rdist + GICR_PENDBASER); - /* TOFIX: check SHAREABILITY validity */ + /* Check SHAREABILITY validity */ + tmp = sys_read64(rdist + GICR_PENDBASER); +#ifdef CONFIG_GIC_V3_RDIST_DMA_NONCOHERENT + tmp &= ~MASK(GITR_PENDBASER_SHAREABILITY); +#endif + if (!(tmp & MASK(GITR_PENDBASER_SHAREABILITY))) { + reg &= ~(MASK(GITR_PENDBASER_SHAREABILITY) | MASK(GITR_PENDBASER_INNER_CACHE)); + reg |= GIC_BASER_CACHE_NCACHEABLE << GITR_PENDBASER_INNER_CACHE_SHIFT; + sys_write64(reg, rdist + GICR_PENDBASER); + } ctlr = sys_read32(rdist + GICR_CTLR); ctlr |= GICR_CTLR_ENABLE_LPIS; From 8f425d2842abbc9833b9ee58376abae0801cc79f Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Thu, 12 Jun 2025 18:44:21 +0800 Subject: [PATCH 02/27] drivers: gicv3_its: enable dma noncoherent support Add DMA noncoherent support on GICv3 ITS driver. Signed-off-by: Jiafei Pan --- drivers/interrupt_controller/intc_gicv3_its.c | 50 +++++++++++++++++-- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/drivers/interrupt_controller/intc_gicv3_its.c b/drivers/interrupt_controller/intc_gicv3_its.c index 6316e686c755..d3864bbab32a 100644 --- a/drivers/interrupt_controller/intc_gicv3_its.c +++ b/drivers/interrupt_controller/intc_gicv3_its.c @@ -1,5 +1,6 @@ /* * Copyright 2021 BayLibre, SAS + * Copyright 2025 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,6 +8,7 @@ #include LOG_MODULE_REGISTER(intc_gicv3_its, LOG_LEVEL_ERR); +#include #include #include #include @@ -39,6 +41,9 @@ struct its_cmd_block { #define ITS_CMD_QUEUE_SIZE SIZE_64K #define ITS_CMD_QUEUE_NR_ENTRIES (ITS_CMD_QUEUE_SIZE / sizeof(struct its_cmd_block)) +/* The level 1 entry size is a 64bit pointer */ +#define GITS_LVL1_ENTRY_SIZE (8UL) + struct gicv3_its_data { mm_reg_t base; struct its_cmd_block *cmd_base; @@ -190,8 +195,7 @@ static int its_alloc_tables(struct gicv3_its_data *data) lvl2_width = fls_z(page_size / entry_size) - 1; device_ids -= lvl2_width + 1; - /* The level 1 entry size is a 64bit pointer */ - entry_size = sizeof(uint64_t); + entry_size = GITS_LVL1_ENTRY_SIZE; indirect = true; } @@ -229,13 +233,22 @@ static int its_alloc_tables(struct gicv3_its_data *data) } reg |= MASK_SET(page_cnt - 1, GITS_BASER_SIZE); - reg |= MASK_SET(GIC_BASER_SHARE_INNER, GITS_BASER_SHAREABILITY); reg |= MASK_SET((uintptr_t)alloc_addr >> GITS_BASER_ADDR_SHIFT, GITS_BASER_ADDR); reg |= MASK_SET(GIC_BASER_CACHE_INNERLIKE, GITS_BASER_OUTER_CACHE); +#ifdef CONFIG_GIC_V3_RDIST_DMA_NONCOHERENT + reg |= MASK_SET(GIC_BASER_SHARE_NO, GITS_BASER_SHAREABILITY); + reg |= MASK_SET(GIC_BASER_CACHE_NCACHEABLE, GITS_BASER_INNER_CACHE); +#else + reg |= MASK_SET(GIC_BASER_SHARE_INNER, GITS_BASER_SHAREABILITY); reg |= MASK_SET(GIC_BASER_CACHE_RAWAWB, GITS_BASER_INNER_CACHE); +#endif reg |= MASK_SET(indirect ? 1 : 0, GITS_BASER_INDIRECT); reg |= MASK_SET(1, GITS_BASER_VALID); +#ifdef CONFIG_GIC_V3_RDIST_DMA_NONCOHERENT + arch_dcache_flush_and_invd_range(alloc_addr, page_size * page_cnt); +#endif + sys_write64(reg, data->base + GITS_BASER(i)); /* TOFIX: check page size & SHAREABILITY validity after write */ @@ -300,6 +313,10 @@ static int its_post_command(struct gicv3_its_data *data, struct its_cmd_block *c uint64_t wr_idx, rd_idx, idx; unsigned int count = 1000000; /* 1s! */ +#ifdef CONFIG_GIC_V3_RDIST_DMA_NONCOHERENT + arch_dcache_flush_and_invd_range(cmd, sizeof(*cmd)); +#endif + wr_idx = (data->cmd_write - data->cmd_base) * sizeof(*cmd); rd_idx = sys_read32(data->base + GITS_CREADR); @@ -426,7 +443,6 @@ static int its_send_invall_cmd(struct gicv3_its_data *data, uint32_t icid) static int gicv3_its_send_int(const struct device *dev, uint32_t device_id, uint32_t event_id) { struct gicv3_its_data *data = dev->data; - /* TOFIX check device_id & event_id bounds */ return its_send_int_cmd(data, device_id, event_id); @@ -436,7 +452,7 @@ static void its_setup_cmd_queue(const struct device *dev) { const struct gicv3_its_config *cfg = dev->config; struct gicv3_its_data *data = dev->data; - uint64_t reg = 0; + uint64_t reg = 0, tmp; /* Zero out cmd table */ memset(cfg->cmd_queue, 0, cfg->cmd_queue_size); @@ -450,6 +466,17 @@ static void its_setup_cmd_queue(const struct device *dev) sys_write64(reg, data->base + GITS_CBASER); +#ifdef CONFIG_GIC_V3_RDIST_DMA_NONCOHERENT + reg &= ~(MASK(GITS_BASER_SHAREABILITY)); +#endif + /* Check whether hardware supports sharable */ + tmp = sys_read64(data->base + GITS_CBASER); + if (!(tmp & MASK(GITS_BASER_SHAREABILITY))) { + reg &= ~(MASK(GITS_BASER_SHAREABILITY) | MASK(GITS_BASER_INNER_CACHE)); + reg |= MASK_SET(GIC_BASER_CACHE_NCACHEABLE, GITS_CBASER_INNER_CACHE); + sys_write64(reg, data->base + GITS_CBASER); + } + data->cmd_base = (struct its_cmd_block *)cfg->cmd_queue; data->cmd_write = data->cmd_base; @@ -529,9 +556,18 @@ static int gicv3_its_init_device_id(const struct device *dev, uint32_t device_id memset(alloc_addr, 0, data->indirect_dev_page_size); +#ifdef CONFIG_GIC_V3_RDIST_DMA_NONCOHERENT + arch_dcache_flush_and_invd_range(alloc_addr, data->indirect_dev_page_size); +#endif + data->indirect_dev_lvl1_table[offset] = (uintptr_t)alloc_addr | MASK_SET(1, GITS_BASER_VALID); +#ifdef CONFIG_GIC_V3_RDIST_DMA_NONCOHERENT + arch_dcache_flush_and_invd_range(data->indirect_dev_lvl1_table + offset, + GITS_LVL1_ENTRY_SIZE); +#endif + barrier_dsync_fence_full(); } } @@ -547,6 +583,10 @@ static int gicv3_its_init_device_id(const struct device *dev, uint32_t device_id if (!itt) { return -ENOMEM; } + memset(itt, 0, alloc_size); +#ifdef CONFIG_GIC_V3_RDIST_DMA_NONCOHERENT + arch_dcache_flush_and_invd_range(itt, alloc_size); +#endif /* size is log2(ites) - 1, equivalent to (fls(ites) - 1) - 1 */ ret = its_send_mapd_cmd(data, device_id, fls_z(nr_ites) - 2, (uintptr_t)itt, true); From c69025743e36f753374047adcdcf9303803c90eb Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Fri, 27 Jun 2025 21:22:27 +0800 Subject: [PATCH 03/27] drivers: intc_gicv3_its: fix incorrect RDbase when PE number is used For RDbase used by its command, When GITS_TYPER.PTA = 1, physicall address is used, the RDbase field consist of bits[51:16] of the address, so need to left shift the address by 16 bits. But when GITS_TYPER.PTA = 0, PE number is used, no need to shit anymore. Signed-off-by: Jiafei Pan --- drivers/interrupt_controller/intc_gicv3_its.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/interrupt_controller/intc_gicv3_its.c b/drivers/interrupt_controller/intc_gicv3_its.c index d3864bbab32a..a9a6018cdd89 100644 --- a/drivers/interrupt_controller/intc_gicv3_its.c +++ b/drivers/interrupt_controller/intc_gicv3_its.c @@ -352,7 +352,7 @@ static int its_send_sync_cmd(struct gicv3_its_data *data, uintptr_t rd_addr) } cmd->raw_cmd[0] = MASK_SET(GITS_CMD_ID_SYNC, GITS_CMD_ID); - cmd->raw_cmd[2] = MASK_SET(rd_addr >> GITS_CMD_RDBASE_ALIGN, GITS_CMD_RDBASE); + cmd->raw_cmd[2] = MASK_SET(rd_addr, GITS_CMD_RDBASE); return its_post_command(data, cmd); } @@ -367,8 +367,7 @@ static int its_send_mapc_cmd(struct gicv3_its_data *data, uint32_t icid, } cmd->raw_cmd[0] = MASK_SET(GITS_CMD_ID_MAPC, GITS_CMD_ID); - cmd->raw_cmd[2] = MASK_SET(icid, GITS_CMD_ICID) | - MASK_SET(rd_addr >> GITS_CMD_RDBASE_ALIGN, GITS_CMD_RDBASE) | + cmd->raw_cmd[2] = MASK_SET(icid, GITS_CMD_ICID) | MASK_SET(rd_addr, GITS_CMD_RDBASE) | MASK_SET(valid ? 1 : 0, GITS_CMD_VALID); return its_post_command(data, cmd); @@ -489,12 +488,18 @@ static uintptr_t gicv3_rdist_get_rdbase(const struct device *dev, unsigned int c { struct gicv3_its_data *data = dev->data; uint64_t typer = sys_read64(data->base + GITS_TYPER); + uintptr_t rdbase; if (GITS_TYPER_PTA_GET(typer)) { - return gic_rdists[cpuid]; + rdbase = gic_rdists[cpuid]; + /* RDbase must be 64KB aligned, only return bits[51:16] of the address */ + rdbase = rdbase >> GITS_CMD_RDBASE_ALIGN; } else { - return GICR_TYPER_PROCESSOR_NUMBER_GET(sys_read64(gic_rdists[cpuid] + GICR_TYPER)); + rdbase = + GICR_TYPER_PROCESSOR_NUMBER_GET(sys_read64(gic_rdists[cpuid] + GICR_TYPER)); } + + return rdbase; } static int gicv3_its_map_intid(const struct device *dev, uint32_t device_id, uint32_t event_id, From 5ec58c9919d127ab21ee74abf00b829317eb65aa Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Fri, 27 Jun 2025 17:31:59 +0800 Subject: [PATCH 04/27] drivers: intc_gicv3_its: fix sleep issue in pre-kernel GIC v3 ITS is initialized in pre-kernel stage in which sleep function can't work yet, so use busy delay in pre-kernel stage and use sleep delay in post-kernel stage. Signed-off-by: Jiafei Pan --- drivers/interrupt_controller/intc_gicv3_its.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/interrupt_controller/intc_gicv3_its.c b/drivers/interrupt_controller/intc_gicv3_its.c index a9a6018cdd89..544158685e1d 100644 --- a/drivers/interrupt_controller/intc_gicv3_its.c +++ b/drivers/interrupt_controller/intc_gicv3_its.c @@ -337,7 +337,11 @@ static int its_post_command(struct gicv3_its_data *data, struct its_cmd_block *c rd_idx, idx, wr_idx); return -ETIMEDOUT; } - k_usleep(1); + if (k_is_pre_kernel()) { + k_busy_wait(1); + } else { + k_usleep(1); + } } return 0; From a4bd88f14af4c787c217f952a5f64b5aea1633fb Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Fri, 30 May 2025 18:12:25 +0800 Subject: [PATCH 05/27] boards: imx95_evk: a55: enlarge memory size Enlarge the memory size to 10M bytes as it is not enough if run some networking application. Signed-off-by: Jiafei Pan --- boards/nxp/imx95_evk/imx95_evk_mimx9596_a55.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boards/nxp/imx95_evk/imx95_evk_mimx9596_a55.dts b/boards/nxp/imx95_evk/imx95_evk_mimx9596_a55.dts index d4aff0f100de..4d4866c1a858 100644 --- a/boards/nxp/imx95_evk/imx95_evk_mimx9596_a55.dts +++ b/boards/nxp/imx95_evk/imx95_evk_mimx9596_a55.dts @@ -43,7 +43,7 @@ }; dram: memory@d0000000 { - reg = <0xd0000000 DT_SIZE_M(1)>; + reg = <0xd0000000 DT_SIZE_M(10)>; }; }; From 85367f2e1de6d11776c73cd57ec8408ef6264c52 Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Fri, 27 Jun 2025 12:21:11 +0800 Subject: [PATCH 06/27] dts: arm64: imx95_a55: add gic v3 its dts node Added dts node for GIC v3 ITS. Signed-off-by: Jiafei Pan --- dts/arm64/nxp/nxp_mimx95_a55.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/dts/arm64/nxp/nxp_mimx95_a55.dtsi b/dts/arm64/nxp/nxp_mimx95_a55.dtsi index 37df069d3dd0..cc52bd1d2b23 100644 --- a/dts/arm64/nxp/nxp_mimx95_a55.dtsi +++ b/dts/arm64/nxp/nxp_mimx95_a55.dtsi @@ -76,7 +76,15 @@ <0x48060000 0xc0000>; /* GICR (RD_base + SGI_base) */ interrupt-controller; #interrupt-cells = <4>; + #address-cells = <1>; + #size-cells = <1>; status = "okay"; + + its: msi-controller@48040000 { + compatible = "arm,gic-v3-its"; + reg = <0x48040000 0x20000>; + status = "okay"; + }; }; reserved-memory { From 1eee2af6ba81741831ddb84de64ab558e6ff7930 Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Fri, 13 Jun 2025 12:12:18 +0800 Subject: [PATCH 07/27] soc: imx95: a55: include LPI in irq number In case of ITS is enabled, need to include LPI in the total number of irq. Signed-off-by: Jiafei Pan --- soc/nxp/imx/imx9/imx95/Kconfig.defconfig.mimx95.a55 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/soc/nxp/imx/imx9/imx95/Kconfig.defconfig.mimx95.a55 b/soc/nxp/imx/imx9/imx95/Kconfig.defconfig.mimx95.a55 index 0fc9f23d6888..9047517a1001 100644 --- a/soc/nxp/imx/imx9/imx95/Kconfig.defconfig.mimx95.a55 +++ b/soc/nxp/imx/imx9/imx95/Kconfig.defconfig.mimx95.a55 @@ -22,8 +22,10 @@ config ARM64_DCACHE_ALL_OPS config ARM64_BOOT_DISABLE_DCACHE default y +# Reserve 8192 LPI interrupt ID starts from 8192 when ITS is enabled config NUM_IRQS - default 320 + default 16384 if GIC_V3_ITS + default 407 if !GIC_V3_ITS config SYS_CLOCK_HW_CYCLES_PER_SEC default 24000000 From 5b3c7328dcf3314730264707b38490b9726f9b59 Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Fri, 27 Jun 2025 11:27:04 +0800 Subject: [PATCH 08/27] soc: imx95: a55: enable GIC redistribute noncoherent GIC redistribute on i.MX 95 is DMA noncoherent, so enable CONFIG_GIC_V3_RDIST_DMA_NONCOHERENT. Signed-off-by: Jiafei Pan --- soc/nxp/imx/imx9/imx95/Kconfig.defconfig.mimx95.a55 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/soc/nxp/imx/imx9/imx95/Kconfig.defconfig.mimx95.a55 b/soc/nxp/imx/imx9/imx95/Kconfig.defconfig.mimx95.a55 index 9047517a1001..0d7fef5ac1fd 100644 --- a/soc/nxp/imx/imx9/imx95/Kconfig.defconfig.mimx95.a55 +++ b/soc/nxp/imx/imx9/imx95/Kconfig.defconfig.mimx95.a55 @@ -16,6 +16,9 @@ config FLASH_BASE_ADDRESS config GIC_SAFE_CONFIG default y +config GIC_V3_RDIST_DMA_NONCOHERENT + default y + # Disable data cache until MMU is enabled when booting from EL2 config ARM64_DCACHE_ALL_OPS default y From bffe8d5700b1ef6a8971641247d0afaf6f98959e Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Fri, 27 Jun 2025 16:35:36 +0800 Subject: [PATCH 09/27] boards: imx95_evk: refine GIC and SCMI objects init priority GIC ITS depends on kernel heap, so move GIC initialize to be behind of heap which initialization priority is CONFIG_KERNEL_INIT_PRIORITY_OBJECTS (it is 30 by default). MU mailbox and SCMI objects depend on GIC, so set their init priority to be same with GIC, the initialization sequence decided by the dts dependency although they use the same init priority. Signed-off-by: Jiafei Pan --- boards/nxp/imx95_evk/Kconfig.defconfig | 24 +++++++++++++++++++ .../imx95_evk_mimx9596_a55_defconfig | 2 -- 2 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 boards/nxp/imx95_evk/Kconfig.defconfig diff --git a/boards/nxp/imx95_evk/Kconfig.defconfig b/boards/nxp/imx95_evk/Kconfig.defconfig new file mode 100644 index 000000000000..a32ec5b99bbd --- /dev/null +++ b/boards/nxp/imx95_evk/Kconfig.defconfig @@ -0,0 +1,24 @@ +# Copyright 2024-2025 NXP +# SPDX-License-Identifier: Apache-2.0 + +if SOC_MIMX9596_A55 + +# GIC ITS depends on kernel heap which init priority is 30, so set +# GIC to be 31, mailbox and SCMI will be initialized by the order +# according to dts dependency although they use the same init priority. +config INTC_INIT_PRIORITY + default 31 + +config MBOX_INIT_PRIORITY + default 31 + +config ARM_SCMI_SHMEM_INIT_PRIORITY + default 31 + +config ARM_SCMI_TRANSPORT_INIT_PRIORITY + default 31 + +config CLOCK_CONTROL_INIT_PRIORITY + default 31 + +endif diff --git a/boards/nxp/imx95_evk/imx95_evk_mimx9596_a55_defconfig b/boards/nxp/imx95_evk/imx95_evk_mimx9596_a55_defconfig index 23e5dd52c5a4..88a5148a54ed 100644 --- a/boards/nxp/imx95_evk/imx95_evk_mimx9596_a55_defconfig +++ b/boards/nxp/imx95_evk/imx95_evk_mimx9596_a55_defconfig @@ -31,5 +31,3 @@ CONFIG_CLOCK_CONTROL=y CONFIG_MBOX=y CONFIG_ARM_SCMI=y -CONFIG_INTC_INIT_PRIORITY=2 -CONFIG_MBOX_INIT_PRIORITY=3 From 4e606a425b409a97e2f182f54590dfd6c7e5d18e Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Fri, 27 Jun 2025 11:27:48 +0800 Subject: [PATCH 10/27] tests: arm64_gicv3_its: add imx95_evk support Add imx95_evk support, as hardware limication, it only has 832 LPIs. Signed-off-by: Jiafei Pan --- .../boards/imx95_evk_mimx9596_a55.conf | 15 +++++++++++++++ tests/arch/arm64/arm64_gicv3_its/src/main.c | 9 ++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 tests/arch/arm64/arm64_gicv3_its/boards/imx95_evk_mimx9596_a55.conf diff --git a/tests/arch/arm64/arm64_gicv3_its/boards/imx95_evk_mimx9596_a55.conf b/tests/arch/arm64/arm64_gicv3_its/boards/imx95_evk_mimx9596_a55.conf new file mode 100644 index 000000000000..70a699068df6 --- /dev/null +++ b/tests/arch/arm64/arm64_gicv3_its/boards/imx95_evk_mimx9596_a55.conf @@ -0,0 +1,15 @@ +# The GICv3 & ITS drivers allocation needs are: +# - LPI prop table: global 1x64K aligned on 64K +# - LPI pend table: for each redistributor/cpu 1x64K aligned on 64K +# - Devices table: 128x4K aligned on 4K +# - Interrupt Collections table: 1x4K aligned on 4K +# +# This makes 11x64K to permit all allocations to success. +# +# Note, will need 64K HEAP_MEM per CPUs added. +# +# This doesn't necessarily include the Interrupt Translation Table, which are +# 256bytes aligned tables, for reference a 32 ITEs table needs 256bytes. +# +# To permit allocating 256 ITT tables of 32 ITEs, 13x64K HEAP_MEM is needed +CONFIG_HEAP_MEM_POOL_SIZE=851968 diff --git a/tests/arch/arm64/arm64_gicv3_its/src/main.c b/tests/arch/arm64/arm64_gicv3_its/src/main.c index 42f18067b33f..940e4f504f0d 100644 --- a/tests/arch/arm64/arm64_gicv3_its/src/main.c +++ b/tests/arch/arm64/arm64_gicv3_its/src/main.c @@ -19,12 +19,19 @@ static void lpi_irq_handle(const void *parameter) last_lpi_irq_num = i; } +#ifdef CONFIG_SOC_MIMX9596_A55 +/* DeviceID is 8bits */ +#define ITS_TEST_DEV(id) (id & 0xff) +/* Cover up to 832 LPIs over 26 DevicesIDs and 32 EventIDs per DeviceID */ +#define ITS_TEST_NUM_DEVS 26 +#define ITS_TEST_NUM_ITES 32 +#else /* Generate a DeviceID over the whole 16bits */ #define ITS_TEST_DEV(id) ((((id + 256) % 16) << 12) | (((id + 256) % 24) << 8) | (id & 0xff)) - /* Cover up to 8192 LPIs over 256 DevicesIDs and 32 EventIDs per DeviceID */ #define ITS_TEST_NUM_DEVS 256 #define ITS_TEST_NUM_ITES 32 +#endif /* Do not test all 8192 irqs, iterate with a prime offset to cover most of the possible event_ids */ #define ITS_TEST_NEXT 13 From 1d98712cffe69248de72726049b4492067e7b1de Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Thu, 3 Jul 2025 18:08:23 +0800 Subject: [PATCH 11/27] west.yml: depend on hal_nxp PR Tmp patch to depend on hal_nxp PR 571. Signed-off-by: Jiafei Pan --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index fe8253bfa2f2..cbc16958256a 100644 --- a/west.yml +++ b/west.yml @@ -210,7 +210,7 @@ manifest: groups: - hal - name: hal_nxp - revision: 7a52cbb7cb56db3a276cbd617db3ea7cc3435d12 + revision: refs/pull/571/head path: modules/hal/nxp groups: - hal From 3308b74968403ceeacaf36ab369cfadceb14bc54 Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Thu, 22 May 2025 17:13:15 +0800 Subject: [PATCH 12/27] drivers: ethernet: imx_netc: add GIC MSI support It could use GIC ITS as MSI controller on Cortex-A Core, so added GIC ITS MSI support for NETC drivers. Signed-off-by: Jiafei Pan --- drivers/ethernet/nxp_imx_netc/Kconfig | 14 ++++ .../ethernet/nxp_imx_netc/eth_nxp_imx_netc.c | 73 +++++++++++++++++++ .../nxp_imx_netc/eth_nxp_imx_netc_priv.h | 13 ++++ .../nxp_imx_netc/eth_nxp_imx_netc_psi.c | 10 ++- dts/bindings/ethernet/nxp,imx-netc-psi.yaml | 4 + dts/bindings/ethernet/nxp,imx-netc.yaml | 16 ++++ 6 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 dts/bindings/ethernet/nxp,imx-netc.yaml diff --git a/drivers/ethernet/nxp_imx_netc/Kconfig b/drivers/ethernet/nxp_imx_netc/Kconfig index 5c6af4f5c0cb..21636cb438ac 100644 --- a/drivers/ethernet/nxp_imx_netc/Kconfig +++ b/drivers/ethernet/nxp_imx_netc/Kconfig @@ -12,11 +12,25 @@ menuconfig ETH_NXP_IMX_NETC if ETH_NXP_IMX_NETC +DT_GIC_ITS_COMPAT := arm,gic-v3-its +DT_NETC_PATH := $(dt_nodelabel_path,netc) +DT_NETC_INT_PARENT_PATH := $(dt_node_ph_prop_path,$(DT_NETC_PATH),msi-parent) +DT_NETC_INT_IS_GIC := $(dt_node_has_compat,$(DT_NETC_INT_PARENT_PATH),$(DT_GIC_ITS_COMPAT)) + +config ETH_NXP_IMX_NETC_MSI_GIC + bool + default y if ($(DT_NETC_INT_IS_GIC) && DT_HAS_ARM_GIC_V3_ITS_ENABLED) + depends on GIC_V3_ITS + help + Use GIC ITS controller as MSI module for NXP NETC + +if !ETH_NXP_IMX_NETC_MSI_GIC config ETH_NXP_IMX_MSGINTR int "Message Interrupt module select" default 1 help Message Interrupt module select. +endif config ETH_NXP_IMX_RX_THREAD_PRIO int "RX thread priority" diff --git a/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc.c b/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc.c index 32762582dce7..ec82fafb653b 100644 --- a/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc.c +++ b/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc.c @@ -21,6 +21,9 @@ LOG_MODULE_REGISTER(nxp_imx_eth); #include #include #include +#ifdef CONFIG_GIC_V3_ITS +#include +#endif #include "../eth.h" #include "eth_nxp_imx_netc_priv.h" @@ -173,6 +176,28 @@ static void netc_eth_rx_thread(void *arg1, void *unused1, void *unused2) } } +#ifdef CONFIG_ETH_NXP_IMX_NETC_MSI_GIC + +static void netc_tx_isr_handler(const void *arg) +{ + const struct device *dev = (const struct device *)arg; + struct netc_eth_data *data = dev->data; + + EP_CleanTxIntrFlags(&data->handle, 1, 0); + data->tx_done = true; +} + +static void netc_rx_isr_handler(const void *arg) +{ + const struct device *dev = (const struct device *)arg; + struct netc_eth_data *data = dev->data; + + EP_CleanRxIntrFlags(&data->handle, 1); + k_sem_give(&data->rx_sem); +} + +#else /* CONFIG_ETH_NXP_IMX_NETC_MSI_GIC */ + static void msgintr_isr(void) { uint32_t irqs = NETC_MSGINTR->MSI[NETC_MSGINTR_CHANNEL].MSIR; @@ -203,6 +228,8 @@ static void msgintr_isr(void) SDK_ISR_EXIT_BARRIER; } +#endif + int netc_eth_init_common(const struct device *dev) { const struct netc_eth_config *config = dev->config; @@ -222,6 +249,51 @@ int netc_eth_init_common(const struct device *dev) #endif /* MSIX entry configuration */ +#ifdef CONFIG_ETH_NXP_IMX_NETC_MSI_GIC + int ret; + + if (config->msi_dev == NULL) { + LOG_ERR("MSI device is not configured"); + return -ENODEV; + } + ret = its_setup_deviceid(config->msi_dev, config->msi_device_id, NETC_MSIX_ENTRY_NUM); + if (ret != 0) { + LOG_ERR("Failed to setup device ID for MSI: %d", ret); + return ret; + } + data->tx_intid = its_alloc_intid(config->msi_dev); + data->rx_intid = its_alloc_intid(config->msi_dev); + + msg_addr = its_get_msi_addr(config->msi_dev); + msix_entry[NETC_TX_MSIX_ENTRY_IDX].control = kNETC_MsixIntrMaskBit; + msix_entry[NETC_TX_MSIX_ENTRY_IDX].msgAddr = msg_addr; + msix_entry[NETC_TX_MSIX_ENTRY_IDX].msgData = NETC_TX_MSIX_ENTRY_IDX; + ret = its_map_intid(config->msi_dev, config->msi_device_id, NETC_TX_MSIX_ENTRY_IDX, + data->tx_intid); + if (ret != 0) { + LOG_ERR("Failed to map TX MSI interrupt: %d", ret); + return ret; + } + + msix_entry[NETC_RX_MSIX_ENTRY_IDX].control = kNETC_MsixIntrMaskBit; + msix_entry[NETC_RX_MSIX_ENTRY_IDX].msgAddr = msg_addr; + msix_entry[NETC_RX_MSIX_ENTRY_IDX].msgData = NETC_RX_MSIX_ENTRY_IDX; + ret = its_map_intid(config->msi_dev, config->msi_device_id, NETC_RX_MSIX_ENTRY_IDX, + data->rx_intid); + if (ret != 0) { + LOG_ERR("Failed to map RX MSI interrupt: %d", ret); + return ret; + } + + if (!irq_is_enabled(data->tx_intid)) { + irq_connect_dynamic(data->tx_intid, 0, netc_tx_isr_handler, dev, 0); + irq_enable(data->tx_intid); + } + if (!irq_is_enabled(data->rx_intid)) { + irq_connect_dynamic(data->rx_intid, 0, netc_rx_isr_handler, dev, 0); + irq_enable(data->rx_intid); + } +#else msg_addr = MSGINTR_GetIntrSelectAddr(NETC_MSGINTR, NETC_MSGINTR_CHANNEL); msix_entry[NETC_TX_MSIX_ENTRY_IDX].control = kNETC_MsixIntrMaskBit; msix_entry[NETC_TX_MSIX_ENTRY_IDX].msgAddr = msg_addr; @@ -235,6 +307,7 @@ int netc_eth_init_common(const struct device *dev) IRQ_CONNECT(NETC_MSGINTR_IRQ, 0, msgintr_isr, 0, 0); irq_enable(NETC_MSGINTR_IRQ); } +#endif /* Endpoint configuration. */ EP_GetDefaultConfig(&ep_config); diff --git a/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc_priv.h b/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc_priv.h index 157f7e61bae4..1aba309246fd 100644 --- a/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc_priv.h +++ b/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc_priv.h @@ -9,7 +9,9 @@ #include "nxp_imx_netc.h" #include "fsl_netc_endpoint.h" +#ifndef CONFIG_ETH_NXP_IMX_NETC_MSI_GIC #include "fsl_msgintr.h" +#endif /* Buffer and descriptor alignment */ #define NETC_BUFF_ALIGN 64 @@ -33,6 +35,7 @@ #define NETC_MSGINTR_IRQ DT_IRQN_BY_IDX(DT_NODELABEL(netc), 0) #endif +#ifndef CONFIG_ETH_NXP_IMX_NETC_MSI_GIC #if (CONFIG_ETH_NXP_IMX_MSGINTR == 1) #define NETC_MSGINTR MSGINTR1 #ifndef NETC_MSGINTR_IRQ @@ -46,6 +49,7 @@ #else #error "Current CONFIG_ETH_NXP_IMX_MSGINTR not support" #endif +#endif /* CONFIG_ETH_NXP_IMX_NETC_MSI_GIC */ /* Timeout for various operations */ #define NETC_TIMEOUT K_MSEC(20) @@ -90,8 +94,13 @@ struct netc_eth_config { void (*bdr_init)(netc_bdr_config_t *bdr_config, netc_rx_bdr_config_t *rx_bdr_config, netc_tx_bdr_config_t *tx_bdr_config); const struct pinctrl_dev_config *pincfg; +#ifdef CONFIG_ETH_NXP_IMX_NETC_MSI_GIC + const struct device *msi_dev; + uint8_t msi_device_id; /* MSI device ID */ +#else uint8_t tx_intr_msg_data; uint8_t rx_intr_msg_data; +#endif #ifdef CONFIG_PTP_CLOCK_NXP_NETC const struct device *ptp_clock; #endif @@ -113,6 +122,10 @@ struct netc_eth_data { K_KERNEL_STACK_MEMBER(rx_thread_stack, CONFIG_ETH_NXP_IMX_RX_THREAD_STACK_SIZE); uint8_t *rx_frame; +#ifdef CONFIG_ETH_NXP_IMX_NETC_MSI_GIC + unsigned int tx_intid; + unsigned int rx_intid; +#endif }; int netc_eth_init_common(const struct device *dev); diff --git a/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc_psi.c b/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc_psi.c index 3dc10ae87246..10f0def52e85 100644 --- a/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc_psi.c +++ b/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc_psi.c @@ -200,8 +200,14 @@ static const struct ethernet_api netc_eth_api = {.iface_api.init = netc_eth_ifac .pseudo_mac = DT_ENUM_HAS_VALUE(DT_DRV_INST(n), phy_connection_type, internal), \ .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ .si_idx = (DT_INST_PROP(n, mac_index) << 8) | DT_INST_PROP(n, si_index), \ - .tx_intr_msg_data = NETC_TX_INTR_MSG_DATA_START + n, \ - .rx_intr_msg_data = NETC_RX_INTR_MSG_DATA_START + n, \ + IF_ENABLED(CONFIG_ETH_NXP_IMX_NETC_MSI_GIC, \ + (.msi_device_id = DT_INST_PROP_OR(n, msi_device_id, 0), \ + .msi_dev = (COND_CODE_1(DT_NODE_HAS_PROP(DT_INST_PARENT(n), msi_parent), \ + (DEVICE_DT_GET(DT_PHANDLE(DT_INST_PARENT(n), msi_parent))), NULL)), \ + )) \ + IF_DISABLED(CONFIG_ETH_NXP_IMX_NETC_MSI_GIC, \ + (.tx_intr_msg_data = NETC_TX_INTR_MSG_DATA_START + n, \ + .rx_intr_msg_data = NETC_RX_INTR_MSG_DATA_START + n,)) \ IF_ENABLED(CONFIG_PTP_CLOCK_NXP_NETC, \ (.ptp_clock = DEVICE_DT_GET(DT_INST_PHANDLE(n, ptp_clock)),)) \ }; \ diff --git a/dts/bindings/ethernet/nxp,imx-netc-psi.yaml b/dts/bindings/ethernet/nxp,imx-netc-psi.yaml index 7aba10df1e35..128a385af07a 100644 --- a/dts/bindings/ethernet/nxp,imx-netc-psi.yaml +++ b/dts/bindings/ethernet/nxp,imx-netc-psi.yaml @@ -20,3 +20,7 @@ properties: required: true type: int description: The SI index of this PSI. + + msi-device-id: + type: int + description: The device ID passed to MSI controller. diff --git a/dts/bindings/ethernet/nxp,imx-netc.yaml b/dts/bindings/ethernet/nxp,imx-netc.yaml new file mode 100644 index 000000000000..bf1d53254a24 --- /dev/null +++ b/dts/bindings/ethernet/nxp,imx-netc.yaml @@ -0,0 +1,16 @@ +# Copyright 2025 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: NXP i.MX NETC Controller + +compatible: "nxp,imx-netc" + +include: [base.yaml] + +properties: + reg: + required: true + + msi-parent: + type: phandle + description: MSI controller From 338fc79e6e58f2462d8ddc9673d94e52daf7de69 Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Sun, 29 Jun 2025 18:34:41 +0800 Subject: [PATCH 13/27] drivers: ethernet: imx_netc: add netc block driver Add NETC block driver, it could do some block memory region MMIO mapping and also so dome block initialization, moved some netc related configuration form board_init() to block driver so that it could be reused between different platforms, although some configuration is different for different platform, but put all NETC related code in the same driver to make it easier to be maintained. Signed-off-by: Jiafei Pan --- boards/nxp/imx95_evk/board.c | 17 +- drivers/ethernet/nxp_imx_netc/CMakeLists.txt | 1 + .../nxp_imx_netc/eth_nxp_imx_netc_blk.c | 210 ++++++++++++++++++ .../ethernet/nxp,imx-netc-blk-ctrl.yaml | 12 + 4 files changed, 224 insertions(+), 16 deletions(-) create mode 100644 drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc_blk.c create mode 100644 dts/bindings/ethernet/nxp,imx-netc-blk-ctrl.yaml diff --git a/boards/nxp/imx95_evk/board.c b/boards/nxp/imx95_evk/board.c index 477bcc38f6ae..2b43501bfec0 100644 --- a/boards/nxp/imx95_evk/board.c +++ b/boards/nxp/imx95_evk/board.c @@ -1,5 +1,5 @@ /* - * Copyright 2024 NXP + * Copyright 2024-2025 NXP * SPDX-License-Identifier: Apache-2.0 */ @@ -10,21 +10,6 @@ static int board_init(void) { -#if defined(CONFIG_ETH_NXP_IMX_NETC) && (DT_CHILD_NUM_STATUS_OKAY(DT_NODELABEL(netc)) != 0) - /* Port 0 to 2 protocol configure: RGMII, RGMII, XGMII */ - BLK_CTRL_NETCMIX->CFG_LINK_MII_PROT = 0x00000522; - BLK_CTRL_NETCMIX->CFG_LINK_PCS_PROT_2 = 0x00000040; - - /* Unlock the IERB. It will warm reset whole NETC. */ - NETC_PRIV->NETCRR &= ~NETC_PRIV_NETCRR_LOCK_MASK; - while ((NETC_PRIV->NETCRR & NETC_PRIV_NETCRR_LOCK_MASK) != 0U) { - } - - /* Lock the IERB. */ - NETC_PRIV->NETCRR |= NETC_PRIV_NETCRR_LOCK_MASK; - while ((NETC_PRIV->NETCSR & NETC_PRIV_NETCSR_STATE_MASK) != 0U) { - } -#endif return 0; } diff --git a/drivers/ethernet/nxp_imx_netc/CMakeLists.txt b/drivers/ethernet/nxp_imx_netc/CMakeLists.txt index 91fbf4d4f1ee..28631f49ba31 100644 --- a/drivers/ethernet/nxp_imx_netc/CMakeLists.txt +++ b/drivers/ethernet/nxp_imx_netc/CMakeLists.txt @@ -4,6 +4,7 @@ if(CONFIG_ETH_NXP_IMX_NETC) zephyr_library_sources(eth_nxp_imx_netc.c) zephyr_library_sources(eth_nxp_imx_netc_psi.c) + zephyr_library_sources_ifdef(CONFIG_DT_HAS_NXP_IMX_NETC_BLK_CTRL_ENABLED eth_nxp_imx_netc_blk.c) endif() zephyr_library_sources_ifdef(CONFIG_DSA_NXP_IMX_NETC dsa_nxp_imx_netc.c) diff --git a/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc_blk.c b/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc_blk.c new file mode 100644 index 000000000000..5e6aaa9e8797 --- /dev/null +++ b/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc_blk.c @@ -0,0 +1,210 @@ +/* NXP NETC Block Controller Driver + * + * Copyright 2025 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ +#define DT_DRV_COMPAT nxp_imx_netc_blk_ctrl + +#define LOG_LEVEL CONFIG_ETHERNET_LOG_LEVEL +#include +LOG_MODULE_REGISTER(nxp_imx_netc_blk); + +#include +#include + +/* NETC integrated endpoint register block register */ +#define IERB_EMDIOFAUXR 0x344 +#define IERB_T0FAUXR 0x444 +#define IERB_ETBCR(a) (0x300c + 0x100 * (a)) +#define IERB_EFAUXR(a) (0x3044 + 0x100 * (a)) +#define IERB_VFAUXR(a) (0x4004 + 0x40 * (a)) + +/* NETC privileged register block register */ +#define PRB_NETCRR 0x100 +#define NETCRR_SR BIT(0) +#define NETCRR_LOCK BIT(1) + +#define PRB_NETCSR 0x104 +#define NETCSR_ERROR BIT(0) +#define NETCSR_STATE BIT(1) + +/* NETCMIX CFG Link register */ +#define CFG_LINK_MII_PROT 0x10 +enum { + MII, + RMII, + RGMII, + reserved, + SGMII, + XGMII, +}; +#define CFG_LINK_MII_PROT_0_SHIFT 0 +#define CFG_LINK_MII_PROT_1_SHIFT 4 +#define CFG_LINK_MII_PROT_2_SHIFT 8 +#define MII_PROT_N(prot, n) ((prot) << CFG_LINK_MII_PROT_##n##_SHIFT) + +/* NETCMIX PCS protocol register */ +#define CFG_LINK_PCS_PROT_0 0x14 +#define CFG_LINK_PCS_PROT_1 0x18 +#define CFG_LINK_PCS_PROT_2 0x1c +/* PCS Protocols */ +#define CFG_LINK_PCS_PROT_1G_SGMII BIT(0) +#define CFG_LINK_PCS_PROT_2500M_SGMII BIT(1) +#define CFG_LINK_PCS_PROT_XFI BIT(3) +#define CFG_LINK_PCS_PROT_10G_SXGMII BIT(6) + +struct eth_nxp_imx_netc_blk_config { + DEVICE_MMIO_NAMED_ROM(ierb); + DEVICE_MMIO_NAMED_ROM(prb); + DEVICE_MMIO_NAMED_ROM(netcmix); +}; + +struct eth_nxp_imx_netc_blk_data { + DEVICE_MMIO_NAMED_RAM(ierb); + DEVICE_MMIO_NAMED_RAM(prb); + DEVICE_MMIO_NAMED_RAM(netcmix); +}; + +#define DEV_CFG(_dev) ((const struct eth_nxp_imx_netc_blk_config *)(_dev)->config) +#define DEV_DATA(_dev) ((struct eth_nxp_imx_netc_blk_data *)(_dev)->data) + +#define read_and_poll_timeout(reg, val, cond) \ + ({ \ + unsigned int count = 1000000; /* 1s! */ \ + while (1) { \ + (val) = sys_read32(reg); \ + if (cond) { \ + break; \ + } \ + count--; \ + if (!count) { \ + break; \ + } \ + k_usleep(1); \ + } \ + (cond) ? 0 : -ETIMEDOUT; \ + }) + +static bool ierb_is_locked(const struct device *dev) +{ + uintptr_t base = DEVICE_MMIO_NAMED_GET(dev, prb); + + return sys_read32(base + PRB_NETCRR) & NETCRR_LOCK; +} + +static int ierb_lock(const struct device *dev) +{ + uintptr_t base = DEVICE_MMIO_NAMED_GET(dev, prb); + uint32_t val; + + sys_write32(NETCRR_LOCK, base + PRB_NETCRR); + + return read_and_poll_timeout(base + PRB_NETCSR, val, !(val & NETCSR_STATE)); +} + +static int ierb_unlock(const struct device *dev) +{ + uintptr_t base = DEVICE_MMIO_NAMED_GET(dev, prb); + uint32_t val; + + sys_write32(1, base + PRB_NETCRR); + + return read_and_poll_timeout(base + PRB_NETCRR, val, !(val & NETCRR_LOCK)); +} + +#ifdef CONFIG_SOC_MIMX9596 +/* Set LDID */ +static int ierb_init(const struct device *dev) +{ + uintptr_t base = DEVICE_MMIO_NAMED_GET(dev, ierb); + + /* EMDIO : No MSI-X interrupt */ + sys_write32(0, base + IERB_EMDIOFAUXR); + /* ENETC0 PF */ + sys_write32(0, base + IERB_EFAUXR(0)); + /* ENETC0 VF0 */ + sys_write32(1, base + IERB_VFAUXR(0)); + /* ENETC0 VF1 */ + sys_write32(2, base + IERB_VFAUXR(1)); + /* ENETC1 PF */ + sys_write32(3, base + IERB_EFAUXR(1)); + /* ENETC1 VF0 : Disabled on 19x19 board dts */ + sys_write32(5, base + IERB_VFAUXR(2)); + /* ENETC1 VF1 : Disabled on 19x19 board dts */ + sys_write32(6, base + IERB_VFAUXR(3)); + /* ENETC2 PF */ + sys_write32(4, base + IERB_EFAUXR(2)); + /* ENETC2 VF0 : Disabled on 15x15 board dts */ + sys_write32(5, base + IERB_VFAUXR(4)); + /* ENETC2 VF1 : Disabled on 15x15 board dts */ + sys_write32(6, base + IERB_VFAUXR(5)); + /* NETC TIMER */ + sys_write32(7, base + IERB_T0FAUXR); + + return 0; +} + +static int netcmix_init(const struct device *dev) +{ + uintptr_t base = DEVICE_MMIO_NAMED_GET(dev, netcmix); + uint32_t reg_val; + + /* ToDo: configure PSC protocol and MII protocol according to PHY mode */ + reg_val = MII_PROT_N(RGMII, 0) | MII_PROT_N(RGMII, 1) | MII_PROT_N(XGMII, 2); + sys_write32(reg_val, base + CFG_LINK_MII_PROT); + sys_write32(CFG_LINK_PCS_PROT_10G_SXGMII, base + CFG_LINK_PCS_PROT_2); + + return 0; +} +#endif + +static int eth_nxp_imx_netc_blk_init(const struct device *dev) +{ + int ret; + + DEVICE_MMIO_NAMED_MAP(dev, ierb, K_MEM_CACHE_NONE | K_MEM_DIRECT_MAP); + DEVICE_MMIO_NAMED_MAP(dev, prb, K_MEM_CACHE_NONE | K_MEM_DIRECT_MAP); + DEVICE_MMIO_NAMED_MAP(dev, netcmix, K_MEM_CACHE_NONE | K_MEM_DIRECT_MAP); + + if (ierb_is_locked(dev)) { + ret = ierb_unlock(dev); + if (ret) { + LOG_ERR("Unlock IERB failed."); + return ret; + } + } + + if (ierb_init(dev) != 0) { + LOG_ERR("Failed to initialize IERB"); + return -EIO; + } + + ret = ierb_lock(dev); + if (ret) { + LOG_ERR("Lock IERB failed."); + return ret; + } + + ret = netcmix_init(dev); + if (ret) { + LOG_ERR("NETCMIX init failed."); + return ret; + } + + return 0; +} + +#define ETH_NXP_IMX_NETC_BLK_INIT(inst) \ + static struct eth_nxp_imx_netc_blk_data eth_nxp_imx_netc_blk_data_##inst; \ + static const struct eth_nxp_imx_netc_blk_config eth_nxp_imx_netc_blk_config_##inst = { \ + DEVICE_MMIO_NAMED_ROM_INIT_BY_NAME(ierb, DT_DRV_INST(inst)), \ + DEVICE_MMIO_NAMED_ROM_INIT_BY_NAME(prb, DT_DRV_INST(inst)), \ + DEVICE_MMIO_NAMED_ROM_INIT_BY_NAME(netcmix, DT_DRV_INST(inst)), \ + }; \ + DEVICE_DT_INST_DEFINE(inst, eth_nxp_imx_netc_blk_init, NULL, \ + ð_nxp_imx_netc_blk_data_##inst, \ + ð_nxp_imx_netc_blk_config_##inst, POST_KERNEL, \ + CONFIG_MDIO_INIT_PRIORITY, NULL); + +DT_INST_FOREACH_STATUS_OKAY(ETH_NXP_IMX_NETC_BLK_INIT) diff --git a/dts/bindings/ethernet/nxp,imx-netc-blk-ctrl.yaml b/dts/bindings/ethernet/nxp,imx-netc-blk-ctrl.yaml new file mode 100644 index 000000000000..7ad70ebaf5e3 --- /dev/null +++ b/dts/bindings/ethernet/nxp,imx-netc-blk-ctrl.yaml @@ -0,0 +1,12 @@ +# Copyright 2025 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: NXP i.MX NETC Block Controller + +compatible: "nxp,imx-netc-blk-ctrl" + +include: [base.yaml] + +properties: + reg: + required: true From db5d41a4494926257c6286cfe6d653516badfa09 Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Mon, 23 Jun 2025 16:38:28 +0800 Subject: [PATCH 14/27] drivers: mdio: imx_netc: add mmio mapping support Added MMIO memory mapping for NETC MDIO driver. Signed-off-by: Jiafei Pan --- drivers/mdio/mdio_nxp_imx_netc.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/mdio/mdio_nxp_imx_netc.c b/drivers/mdio/mdio_nxp_imx_netc.c index 4882f16b08d9..c9afc4a4c405 100644 --- a/drivers/mdio/mdio_nxp_imx_netc.c +++ b/drivers/mdio/mdio_nxp_imx_netc.c @@ -1,5 +1,5 @@ /* - * Copyright 2024 NXP + * Copyright 2024-2025 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -15,13 +15,20 @@ #include "fsl_netc_mdio.h" LOG_MODULE_REGISTER(nxp_imx_netc_emdio, CONFIG_MDIO_LOG_LEVEL); +#define DEV_CFG(_dev) ((const struct nxp_imx_netc_mdio_config *)(_dev)->config) +#define DEV_DATA(_dev) ((struct nxp_imx_netc_mdio_data *)(_dev)->data) + struct nxp_imx_netc_mdio_config { + DEVICE_MMIO_NAMED_ROM(basic); + DEVICE_MMIO_NAMED_ROM(pfconfig); const struct pinctrl_dev_config *pincfg; const struct device *clock_dev; clock_control_subsys_t clock_subsys; }; struct nxp_imx_netc_mdio_data { + DEVICE_MMIO_NAMED_RAM(basic); + DEVICE_MMIO_NAMED_RAM(pfconfig); struct k_mutex rw_mutex; netc_mdio_handle_t handle; }; @@ -60,6 +67,9 @@ static int nxp_imx_netc_mdio_initialize(const struct device *dev) status_t result; int err; + DEVICE_MMIO_NAMED_MAP(dev, basic, K_MEM_CACHE_NONE | K_MEM_DIRECT_MAP); + DEVICE_MMIO_NAMED_MAP(dev, pfconfig, K_MEM_CACHE_NONE | K_MEM_DIRECT_MAP); + err = pinctrl_apply_state(cfg->pincfg, PINCTRL_STATE_DEFAULT); if (err) { return err; @@ -89,6 +99,8 @@ static DEVICE_API(mdio, nxp_imx_netc_mdio_api) = { PINCTRL_DT_INST_DEFINE(n); \ static struct nxp_imx_netc_mdio_data nxp_imx_netc_mdio##n##_data; \ static const struct nxp_imx_netc_mdio_config nxp_imx_netc_mdio##n##_cfg = { \ + DEVICE_MMIO_NAMED_ROM_INIT_BY_NAME(basic, DT_DRV_INST(n)), \ + DEVICE_MMIO_NAMED_ROM_INIT_BY_NAME(pfconfig, DT_DRV_INST(n)), \ .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ .clock_subsys = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(n, name), \ From d2f26cb2cd0a23fec442af64e0fd7b3b662656d5 Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Wed, 2 Jul 2025 11:58:33 +0800 Subject: [PATCH 15/27] drivers: ethernet: imx_netc: add MMIO memory mapping Added MMIO memory mapping support in nxim_imx_netc driver as need to do MMU mapping for Cortex-A Core, but the update is also feasible for Cortex-M Core. Signed-off-by: Jiafei Pan --- .../ethernet/nxp_imx_netc/eth_nxp_imx_netc.c | 31 +++++++++++++++++++ .../nxp_imx_netc/eth_nxp_imx_netc_priv.h | 2 ++ 2 files changed, 33 insertions(+) diff --git a/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc.c b/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc.c index ec82fafb653b..518461e8fdb5 100644 --- a/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc.c +++ b/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc.c @@ -3,6 +3,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ +#define DT_DRV_COMPAT nxp_imx_netc #define LOG_LEVEL CONFIG_ETHERNET_LOG_LEVEL #include @@ -32,6 +33,17 @@ LOG_MODULE_REGISTER(nxp_imx_eth); #define NETC_HAS_NO_SWITCH_TAG_SUPPORT 1 #endif +#define DEV_CFG(_dev) ((const struct eth_nxp_imx_netc_ecam_config *)(_dev)->config) +#define DEV_DATA(_dev) ((struct eth_nxp_imx_netc_ecam_data *)(_dev)->data) + +struct eth_nxp_imx_netc_ecam_config { + DEVICE_MMIO_NAMED_ROM(base); +}; + +struct eth_nxp_imx_netc_ecam_data { + DEVICE_MMIO_NAMED_RAM(base); +}; + const struct device *netc_dev_list[NETC_DRV_MAX_INST_SUPPORT]; #ifdef CONFIG_PTP_CLOCK_NXP_NETC @@ -529,3 +541,22 @@ int netc_eth_set_config(const struct device *dev, enum ethernet_config_type type return ret; } + +static int eth_nxp_imx_netc_ecam_init(const struct device *dev) +{ + DEVICE_MMIO_NAMED_MAP(dev, base, K_MEM_CACHE_NONE | K_MEM_DIRECT_MAP); + + return 0; +} + +#define ETH_NXP_IMX_NETC_ECAM_INIT(inst) \ + static struct eth_nxp_imx_netc_ecam_data eth_nxp_imx_netc_ecam_data_##inst; \ + static const struct eth_nxp_imx_netc_ecam_config eth_nxp_imx_netc_ecam_config_##inst = { \ + DEVICE_MMIO_NAMED_ROM_INIT(base, DT_DRV_INST(inst)), \ + }; \ + DEVICE_DT_INST_DEFINE(inst, eth_nxp_imx_netc_ecam_init, NULL, \ + ð_nxp_imx_netc_ecam_data_##inst, \ + ð_nxp_imx_netc_ecam_config_##inst, POST_KERNEL, \ + CONFIG_ETH_INIT_PRIORITY, NULL); + +DT_INST_FOREACH_STATUS_OKAY(ETH_NXP_IMX_NETC_ECAM_INIT) diff --git a/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc_priv.h b/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc_priv.h index 1aba309246fd..008a95ac3e4c 100644 --- a/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc_priv.h +++ b/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc_priv.h @@ -86,6 +86,7 @@ } struct netc_eth_config { + DEVICE_MMIO_NAMED_ROM(base); uint16_t si_idx; const struct device *phy_dev; netc_hw_mii_mode_t phy_mode; @@ -109,6 +110,7 @@ struct netc_eth_config { typedef uint8_t rx_buffer_t[NETC_RX_RING_BUF_SIZE_ALIGN]; struct netc_eth_data { + DEVICE_MMIO_NAMED_RAM(base); ep_handle_t handle; struct net_if *iface; uint8_t mac_addr[6]; From e43fc0c8234d751f5544d244432b23fd630147e0 Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Wed, 2 Jul 2025 12:10:50 +0800 Subject: [PATCH 16/27] drivers: ethernet: netc_psi: add MMIPO mapping support In order to support MMU mapping on Cortex-A core, added MMIO mapping support in imx_netc_psi driver. Signed-off-by: Jiafei Pan --- drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc_psi.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc_psi.c b/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc_psi.c index 10f0def52e85..8c79c59a56db 100644 --- a/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc_psi.c +++ b/drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc_psi.c @@ -22,6 +22,9 @@ LOG_MODULE_REGISTER(nxp_imx_eth_psi); #include "../eth.h" #include "eth_nxp_imx_netc_priv.h" +#define DEV_CFG(_dev) ((const struct netc_eth_config *)(_dev)->config) +#define DEV_DATA(_dev) ((struct netc_eth_data *)(_dev)->data) + static void netc_eth_phylink_callback(const struct device *pdev, struct phy_link_state *state, void *user_data) { @@ -104,6 +107,8 @@ static int netc_eth_init(const struct device *dev) const struct netc_eth_config *cfg = dev->config; int err; + DEVICE_MMIO_NAMED_MAP(dev, base, K_MEM_CACHE_NONE | K_MEM_DIRECT_MAP); + if (cfg->pseudo_mac) { goto init_common; } @@ -192,6 +197,7 @@ static const struct ethernet_api netc_eth_api = {.iface_api.init = netc_eth_ifac .rx_frame = eth##n##_rx_frame, \ }; \ static const struct netc_eth_config netc_eth##n##_config = { \ + DEVICE_MMIO_NAMED_ROM_INIT(base, DT_DRV_INST(n)), \ .generate_mac = netc_eth##n##_generate_mac, \ .bdr_init = netc_eth##n##_bdr_init, \ .phy_dev = (COND_CODE_1(DT_INST_NODE_HAS_PROP(n, phy_handle), \ From fb48e3605422e7bd4274b0a3ec395be9d6dd218c Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Mon, 30 Jun 2025 10:55:58 +0800 Subject: [PATCH 17/27] modules: hal_nxp: disable netc switch on imx95 i.MX 95 has no NETC switch, so disable it on this platform. Signed-off-by: Jiafei Pan --- modules/hal_nxp/mcux/mcux-sdk-ng/drivers/drivers.cmake | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/hal_nxp/mcux/mcux-sdk-ng/drivers/drivers.cmake b/modules/hal_nxp/mcux/mcux-sdk-ng/drivers/drivers.cmake index b794013ca972..d7fa09bed855 100644 --- a/modules/hal_nxp/mcux/mcux-sdk-ng/drivers/drivers.cmake +++ b/modules/hal_nxp/mcux/mcux-sdk-ng/drivers/drivers.cmake @@ -142,7 +142,9 @@ set_variable_ifdef(CONFIG_MIPI_DBI_NXP_DCNANO_LCDIF CONFIG_MCUX_COMPONENT_driver set_variable_ifdef(CONFIG_MIPI_DBI_NXP_FLEXIO_LCDIF CONFIG_MCUX_COMPONENT_driver.flexio_mculcd) set_variable_ifdef(CONFIG_VIDEO_MCUX_MIPI_CSI2RX CONFIG_MCUX_COMPONENT_driver.mipi_csi2rx) set_variable_ifdef(CONFIG_ETH_NXP_IMX_NETC CONFIG_MCUX_COMPONENT_driver.netc) -set_variable_ifdef(CONFIG_ETH_NXP_IMX_NETC CONFIG_MCUX_COMPONENT_driver.netc_switch) +if(NOT CONFIG_SOC_MIMX9596) + set_variable_ifdef(CONFIG_ETH_NXP_IMX_NETC CONFIG_MCUX_COMPONENT_driver.netc_switch) +endif() set_variable_ifdef(CONFIG_SOC_SERIES_IMXRT10XX CONFIG_MCUX_COMPONENT_driver.ocotp) set_variable_ifdef(CONFIG_SOC_SERIES_IMXRT11XX CONFIG_MCUX_COMPONENT_driver.ocotp) From a3a8fce7db999ff29c4b36cdc3baac13ad990162 Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Thu, 3 Jul 2025 11:23:07 +0800 Subject: [PATCH 18/27] dts: arm: imx95_m7: update netc device nodes Update NETC device nodes according to NETC driver update: 1. Added NETC block control device node to handle block control initialization in netc block driver. 2. Added "nxp,imx-netc" compatible for netc driver to handle MMIO mapping in the driver. 3. Added all memory region in MMIO reg propertiy to let driver to handle MMIO mapping for all memory region. 4. Move MMIO device node out of netc device node to decouple the device initialization priority, so that MMIO could be initialized before netc driver initialization. Signed-off-by: Jiafei Pan --- dts/arm/nxp/nxp_imx95_m7.dtsi | 73 +++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 29 deletions(-) diff --git a/dts/arm/nxp/nxp_imx95_m7.dtsi b/dts/arm/nxp/nxp_imx95_m7.dtsi index 1751f15014eb..1c3dc9c7ab8d 100644 --- a/dts/arm/nxp/nxp_imx95_m7.dtsi +++ b/dts/arm/nxp/nxp_imx95_m7.dtsi @@ -526,44 +526,59 @@ }; }; - netc: ethernet@4ca00000 { - reg = <0x4ca00000 0x1000000>; - interrupt-parent = <&irqsteer_master0>; - interrupts = <13 0 0>; + netc_blk_ctrl: netc-blk-ctrl@4cde0000 { + compatible = "nxp,imx-netc-blk-ctrl"; + reg = <0x4cde0000 0x10000>, + <0x4cdf0000 0x10000>, + <0x4c810000 0x18>; + reg-names = "ierb", "prb", "netcmix"; #address-cells = <1>; #size-cells = <1>; ranges; - emdio: mdio@4cce0000 { - compatible = "nxp,imx-netc-emdio"; - reg = <0x4cce0000 0x1c44>; - clocks = <&scmi_clk IMX95_CLK_ENET>; + netc: ethernet@4ca00000 { + compatible = "nxp,imx-netc"; + reg = <0x4ca00000 0x100000>; + interrupt-parent = <&irqsteer_master0>; + interrupts = <13 0 0>; #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; + #size-cells = <1>; + ranges; + + enetc_psi0: ethernet@4cc00000 { + compatible = "nxp,imx-netc-psi"; + reg = <0x4cc00000 0x10000>; + mac-index = <0>; + si-index = <0>; + status = "disabled"; + }; - enetc_psi0: ethernet@4cc00000 { - compatible = "nxp,imx-netc-psi"; - reg = <0x4cc00000 0x10000>; - mac-index = <0>; - si-index = <0>; - status = "disabled"; - }; + enetc_psi1: ethernet@4cc40000 { + compatible = "nxp,imx-netc-psi"; + reg = <0x4cc40000 0x10000>; + mac-index = <1>; + si-index = <1>; + status = "disabled"; + }; + + enetc_psi2: ethernet@4cc80000 { + compatible = "nxp,imx-netc-psi"; + reg = <0x4cc80000 0x10000>; + mac-index = <2>; + si-index = <2>; + status = "disabled"; + }; - enetc_psi1: ethernet@4cc40000 { - compatible = "nxp,imx-netc-psi"; - reg = <0x4cc40000 0x10000>; - mac-index = <1>; - si-index = <1>; - status = "disabled"; }; - enetc_psi2: ethernet@4cc80000 { - compatible = "nxp,imx-netc-psi"; - reg = <0x4cc80000 0x10000>; - mac-index = <2>; - si-index = <2>; + emdio: mdio@4cb00000 { + compatible = "nxp,imx-netc-emdio"; + reg = <0x4cce0000 0x2000>, + <0x4cb00000 0x100000>; + reg-names = "basic", "pfconfig"; + clocks = <&scmi_clk IMX95_CLK_ENET>; + #address-cells = <1>; + #size-cells = <0>; status = "disabled"; }; From 44925f27e6874c95accc56b15b84196b343520a5 Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Wed, 9 Jul 2025 15:10:18 +0800 Subject: [PATCH 19/27] dts: arm: rt118x: update netc device nodes Update NETC device nodes according to NETC driver update: 1. Added "nxp,imx-netc" compatible for netc driver to handle MMIO mapping in the driver. 2. Added all memory region in MMIO reg propertiy to let driver to handle MMIO mapping for all memory region. 3. Move MMIO device node out of netc device node to decouple the device initialization priority, so that MMIO could be initialized before netc driver initialization. Signed-off-by: Jiafei Pan --- dts/arm/nxp/nxp_rt118x.dtsi | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/dts/arm/nxp/nxp_rt118x.dtsi b/dts/arm/nxp/nxp_rt118x.dtsi index dc25cfb24ecb..33f4429edce6 100644 --- a/dts/arm/nxp/nxp_rt118x.dtsi +++ b/dts/arm/nxp/nxp_rt118x.dtsi @@ -619,6 +619,7 @@ }; netc: ethernet@60000000 { + compatible = "nxp,imx-netc"; reg = <0x60000000 0x1000000>; #address-cells = <1>; #size-cells = <1>; @@ -641,15 +642,6 @@ status = "disabled"; }; - emdio: mdio@60ba0000 { - compatible = "nxp,imx-netc-emdio"; - reg = <0x60ba0000 0x1c44>; - clocks = <&ccm IMX_CCM_NETC_CLK 0x0 0>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - switch: dsa { compatible = "nxp,netc-switch"; status = "disabled"; @@ -686,6 +678,17 @@ }; }; + emdio: mdio@60ba0000 { + compatible = "nxp,imx-netc-emdio"; + reg = <0x60ba0000 0x1c44>, + <0x60001000 0x1000>; + reg-names = "basic", "pfconfig"; + clocks = <&ccm IMX_CCM_NETC_CLK 0x0 0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + flexcan1: can@43a0000 { compatible = "nxp,flexcan-fd", "nxp,flexcan"; reg = <0x43a0000 0x1000>; From 855dcf11fac7e55531a222e1693d90528dd216af Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Wed, 9 Jul 2025 16:00:13 +0800 Subject: [PATCH 20/27] dts: arm: imx943_m33: update netc device nodes Update NETC device nodes according to NETC driver update: 1. Added "nxp,imx-netc" compatible for netc driver to handle MMIO mapping in the driver. 2. Added all memory region in MMIO reg propertiy to let driver to handle MMIO mapping for all memory region. 3. Move MMIO device node out of netc device node to decouple the device initialization priority, so that MMIO could be initialized before netc driver initialization. Signed-off-by: Jiafei Pan --- dts/arm/nxp/nxp_imx943_m33.dtsi | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/dts/arm/nxp/nxp_imx943_m33.dtsi b/dts/arm/nxp/nxp_imx943_m33.dtsi index 787fbcfd2974..86366ae4805b 100644 --- a/dts/arm/nxp/nxp_imx943_m33.dtsi +++ b/dts/arm/nxp/nxp_imx943_m33.dtsi @@ -264,21 +264,13 @@ }; netc: ethernet@4ca00000 { + compatible = "nxp,imx-netc"; reg = <0x4ca00000 0x500000>; interrupts = <294 0>; #address-cells = <1>; #size-cells = <1>; ranges; - emdio: mdio@4cde0000 { - compatible = "nxp,imx-netc-emdio"; - reg = <0x4cde0000 0x10000>; - clocks = <&scmi_clk IMX943_CLK_ENET>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - enetc_psi0: ethernet@4cc80000 { compatible = "nxp,imx-netc-psi"; reg = <0x4cc80000 0x10000>; @@ -324,6 +316,17 @@ status = "disabled"; }; }; + + emdio: mdio@4cde0000 { + compatible = "nxp,imx-netc-emdio"; + reg = <0x4cde0000 0x10000>, + <0x4cbc0000 0x40000>; + reg-names = "basic", "pfconfig"; + clocks = <&scmi_clk IMX943_CLK_ENET>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; }; }; From 5aeeddad2c672ac551846a9dd4b47b634202ef23 Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Sun, 29 Jun 2025 18:35:44 +0800 Subject: [PATCH 21/27] dts: arm64: imx95_evk: add netc dts nodes Added NETC dts nodes in imx95_evk A55 platform. Signed-off-by: Jiafei Pan --- dts/arm64/nxp/nxp_mimx95_a55.dtsi | 65 +++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/dts/arm64/nxp/nxp_mimx95_a55.dtsi b/dts/arm64/nxp/nxp_mimx95_a55.dtsi index cc52bd1d2b23..1baa24c1d6b3 100644 --- a/dts/arm64/nxp/nxp_mimx95_a55.dtsi +++ b/dts/arm64/nxp/nxp_mimx95_a55.dtsi @@ -476,6 +476,71 @@ ngpios = <16>; status = "disabled"; }; + + netc_blk_ctrl: netc-blk-ctrl@4cde0000 { + compatible = "nxp,imx-netc-blk-ctrl"; + reg = <0x4cde0000 0x10000>, + <0x4cdf0000 0x10000>, + <0x4c810000 0x18>; + reg-names = "ierb", "prb", "netcmix"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + netc: ethernet@4ca00000 { + compatible = "nxp,imx-netc"; + reg = <0x4ca00000 0x100000>; + msi-parent = <&its>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + enetc_psi0: ethernet@4cc00000 { + compatible = "nxp,imx-netc-psi"; + reg = <0x4cc00000 0x40000>; + msi-device-id = <0x60>; + mac-index = <0>; + si-index = <0>; + status = "disabled"; + }; + + enetc_psi1: ethernet@4cc40000 { + compatible = "nxp,imx-netc-psi"; + reg = <0x4cc40000 0x40000>; + msi-device-id = <0x63>; + mac-index = <1>; + si-index = <1>; + status = "disabled"; + }; + + enetc_psi2: ethernet@4cc80000 { + compatible = "nxp,imx-netc-psi"; + reg = <0x4cc80000 0x40000>; + msi-device-id = <0x64>; + mac-index = <2>; + si-index = <2>; + status = "disabled"; + }; + }; + + emdio: mdio@4cb00000 { + compatible = "nxp,imx-netc-emdio"; + reg = <0x4cce0000 0x2000>, + <0x4cb00000 0x100000>; + reg-names = "basic", "pfconfig"; + clocks = <&scmi_clk IMX95_CLK_ENET>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + enetc_ptp_clock: ptp_clock@4ccc0000 { + compatible = "nxp,netc-ptp-clock"; + reg = <0x4ccc0000 0x10000>; + clocks = <&scmi_clk IMX95_CLK_ENET>; + status = "disabled"; + }; + }; }; /* From 646098a8d8fe65bab83a740a7eabfeb0bd3c740f Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Tue, 24 Jun 2025 11:33:04 +0800 Subject: [PATCH 22/27] dts: arm64: imx95_a55: add SCMI power device node Added SCMI power dts node. Signed-off-by: Jiafei Pan --- dts/arm64/nxp/nxp_mimx95_a55.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/dts/arm64/nxp/nxp_mimx95_a55.dtsi b/dts/arm64/nxp/nxp_mimx95_a55.dtsi index 1baa24c1d6b3..359b2aa4e239 100644 --- a/dts/arm64/nxp/nxp_mimx95_a55.dtsi +++ b/dts/arm64/nxp/nxp_mimx95_a55.dtsi @@ -107,6 +107,12 @@ #address-cells = <1>; #size-cells = <0>; + scmi_devpd: protocol@11 { + compatible = "arm,scmi-power"; + reg = <0x11>; + #power-domain-cells = <1>; + }; + scmi_clk: protocol@14 { compatible = "arm,scmi-clock"; reg = <0x14>; From a74b07954b1978944ddf415e6222662aa27ca375 Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Tue, 24 Jun 2025 11:31:58 +0800 Subject: [PATCH 23/27] soc: imx95: a55: add netc power and clock init in soc.c Power up NETCMIX and configure netc clock in soc_init(). Signed-off-by: Jiafei Pan --- soc/nxp/imx/imx9/imx95/a55/soc.c | 66 +++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/soc/nxp/imx/imx9/imx95/a55/soc.c b/soc/nxp/imx/imx9/imx95/a55/soc.c index 29d2c963578d..91aeb788e671 100644 --- a/soc/nxp/imx/imx9/imx95/a55/soc.c +++ b/soc/nxp/imx/imx9/imx95/a55/soc.c @@ -9,12 +9,18 @@ #include #include #include +#include #include +#include #include #define FREQ_24M_HZ 24000000 /* 24 MHz */ -static int soc_clk_init(void) +/* SCMI power domain states */ +#define POWER_DOMAIN_STATE_ON 0x00000000 +#define POWER_DOMAIN_STATE_OFF 0x40000000 + +static int lpuart_clk_init(void) { #if DT_NODE_HAS_STATUS(DT_NODELABEL(lpuart1), okay) || \ DT_NODE_HAS_STATUS(DT_NODELABEL(lpuart3), okay) @@ -57,9 +63,65 @@ static int soc_clk_init(void) return 0; } +static int netc_init(void) +{ +#if defined(CONFIG_ETH_NXP_IMX_NETC) && (DT_CHILD_NUM_STATUS_OKAY(DT_NODELABEL(netc)) != 0) + const struct device *clk_dev = DEVICE_DT_GET(DT_NODELABEL(scmi_clk)); + struct scmi_protocol *proto = clk_dev->data; + struct scmi_clock_rate_config clk_cfg = {0}; + struct scmi_power_state_config pwr_cfg = {0}; + uint32_t power_state = POWER_DOMAIN_STATE_OFF; + uint64_t enetref_clk = 250000000; /* 250 MHz*/ + int ret; + + /* Power up NETCMIX */ + pwr_cfg.domain_id = IMX95_PD_NETC; + pwr_cfg.power_state = POWER_DOMAIN_STATE_ON; + + ret = scmi_power_state_set(&pwr_cfg); + if (ret) { + return ret; + } + + while (power_state != POWER_DOMAIN_STATE_ON) { + ret = scmi_power_state_get(IMX95_PD_NETC, &power_state); + if (ret) { + return ret; + } + } + + /* ENETREF clock init */ + ret = scmi_clock_parent_set(proto, IMX95_CLK_ENETREF, IMX95_CLK_SYSPLL1_PFD0); + if (ret) { + return ret; + } + + clk_cfg.flags = SCMI_CLK_RATE_SET_FLAGS_ROUNDS_AUTO; + clk_cfg.clk_id = IMX95_CLK_ENETREF; + clk_cfg.rate[0] = enetref_clk & 0xffffffff; + clk_cfg.rate[1] = (enetref_clk >> 32) & 0xffffffff; + + ret = scmi_clock_rate_set(proto, &clk_cfg); + if (ret) { + return ret; + } +#endif + + return 0; +} + static int soc_init(void) { - return soc_clk_init(); + int ret; + + ret = lpuart_clk_init(); + if (ret) { + return ret; + } + + ret = netc_init(); + + return ret; } /* * Because platform is using ARM SCMI, drivers like scmi, mbox etc are From f51c63e5f45dde57ce803790c69f2fdb0fd379f0 Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Fri, 4 Jul 2025 10:55:58 +0800 Subject: [PATCH 24/27] board: imx95_evk: m7: refine NETC dts Removed overlay and enabled these nodes in board dts directly as it is not be valid unless CONFIG_NETWORKING is enabled. Signed-off-by: Jiafei Pan --- boards/nxp/imx95_evk/doc/index.rst | 3 +-- boards/nxp/imx95_evk/dts/enetc_psi0.overlay | 21 ------------------- .../nxp/imx95_evk/imx95_evk_mimx9596_m7.dts | 12 +++++++---- 3 files changed, 9 insertions(+), 27 deletions(-) delete mode 100644 boards/nxp/imx95_evk/dts/enetc_psi0.overlay diff --git a/boards/nxp/imx95_evk/doc/index.rst b/boards/nxp/imx95_evk/doc/index.rst index 4b52b0563c8e..4a186e430071 100644 --- a/boards/nxp/imx95_evk/doc/index.rst +++ b/boards/nxp/imx95_evk/doc/index.rst @@ -106,8 +106,7 @@ Ethernet -------- NETC driver supports to manage the Physical Station Interface (PSI). -The first ENET1 port could be enabled for M7 by west build option -``-DEXTRA_DTC_OVERLAY_FILE=enetc_psi0.overlay``. +The first ENET1 port could be enabled on M7 DDR platform. Programming and Debugging (A55) diff --git a/boards/nxp/imx95_evk/dts/enetc_psi0.overlay b/boards/nxp/imx95_evk/dts/enetc_psi0.overlay deleted file mode 100644 index a14003810f06..000000000000 --- a/boards/nxp/imx95_evk/dts/enetc_psi0.overlay +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2025 NXP - * - * SPDX-License-Identifier: Apache-2.0 - */ - -&emdio { - status = "okay"; - - phy0: phy@1 { - status = "okay"; - }; -}; - -&enetc_psi0 { - status = "okay"; -}; - -&enetc_ptp_clock { - status = "okay"; -}; diff --git a/boards/nxp/imx95_evk/imx95_evk_mimx9596_m7.dts b/boards/nxp/imx95_evk/imx95_evk_mimx9596_m7.dts index 8b661db7a8af..6c5167634d25 100644 --- a/boards/nxp/imx95_evk/imx95_evk_mimx9596_m7.dts +++ b/boards/nxp/imx95_evk/imx95_evk_mimx9596_m7.dts @@ -1,5 +1,5 @@ /* - * Copyright 2024 NXP + * Copyright 2024-2025 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -26,12 +26,12 @@ &emdio { pinctrl-0 = <&emdio_default>; pinctrl-names = "default"; - status = "disabled"; + status = "okay"; phy0: phy@1 { compatible = "realtek,rtl8211f"; reg = <0x1>; - status = "disabled"; + status = "okay"; }; }; @@ -41,7 +41,11 @@ pinctrl-names = "default"; phy-handle = <&phy0>; phy-connection-type = "rgmii"; - status = "disabled"; + status = "okay"; +}; + +&enetc_ptp_clock { + status = "okay"; }; &flexspi { From d37b0675ab1c264461739a0fab59ffc8b551280f Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Sun, 29 Jun 2025 18:37:34 +0800 Subject: [PATCH 25/27] boards: imx95_evk: a55: add NETC support Added NETC PSI0 support on the i.MX 95 EVK board for A55 platform. Signed-off-by: Jiafei Pan --- boards/nxp/imx95_evk/Kconfig.defconfig | 9 ++++++- boards/nxp/imx95_evk/doc/index.rst | 4 ++- .../nxp/imx95_evk/imx95_evk_mimx9596_a55.dts | 25 +++++++++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/boards/nxp/imx95_evk/Kconfig.defconfig b/boards/nxp/imx95_evk/Kconfig.defconfig index a32ec5b99bbd..9e5b8db0d693 100644 --- a/boards/nxp/imx95_evk/Kconfig.defconfig +++ b/boards/nxp/imx95_evk/Kconfig.defconfig @@ -3,6 +3,13 @@ if SOC_MIMX9596_A55 +if ETH_NXP_IMX_NETC + +config GIC_V3_ITS + default y + +endif # ETH_NXP_IMX_NETC + # GIC ITS depends on kernel heap which init priority is 30, so set # GIC to be 31, mailbox and SCMI will be initialized by the order # according to dts dependency although they use the same init priority. @@ -21,4 +28,4 @@ config ARM_SCMI_TRANSPORT_INIT_PRIORITY config CLOCK_CONTROL_INIT_PRIORITY default 31 -endif +endif # SOC_MIMX9596_A55 diff --git a/boards/nxp/imx95_evk/doc/index.rst b/boards/nxp/imx95_evk/doc/index.rst index 4a186e430071..aba0d3f51209 100644 --- a/boards/nxp/imx95_evk/doc/index.rst +++ b/boards/nxp/imx95_evk/doc/index.rst @@ -106,8 +106,10 @@ Ethernet -------- NETC driver supports to manage the Physical Station Interface (PSI). -The first ENET1 port could be enabled on M7 DDR platform. +The first ENET1 port could be enabled on M7 DDR and A55 platforms. +For A55 Core, NETC depends on GIC ITS, so need to make sure to allocate heap memory to +be larger than 851968 byes by setting CONFIG_HEAP_MEM_POOL_SIZE. Programming and Debugging (A55) ******************************* diff --git a/boards/nxp/imx95_evk/imx95_evk_mimx9596_a55.dts b/boards/nxp/imx95_evk/imx95_evk_mimx9596_a55.dts index 4d4866c1a858..51b3d7f704eb 100644 --- a/boards/nxp/imx95_evk/imx95_evk_mimx9596_a55.dts +++ b/boards/nxp/imx95_evk/imx95_evk_mimx9596_a55.dts @@ -47,6 +47,31 @@ }; }; +&emdio { + pinctrl-0 = <&emdio_default>; + pinctrl-names = "default"; + status = "okay"; + + phy0: phy@1 { + compatible = "realtek,rtl8211f"; + reg = <0x1>; + status = "okay"; + }; +}; + +&enetc_psi0 { + local-mac-address = [00 00 00 01 02 00]; + pinctrl-0 = <ð0_default>; + pinctrl-names = "default"; + phy-handle = <&phy0>; + phy-connection-type = "rgmii"; + status = "okay"; +}; + +&enetc_ptp_clock { + status = "okay"; +}; + &lpi2c5 { pinctrl-0 = <&lpi2c5_default>; pinctrl-names = "default"; From 784e7a531ffa915050b97ab3e2f07f4c1fc01af8 Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Wed, 9 Jul 2025 17:14:53 +0800 Subject: [PATCH 26/27] boards: imx95_evk: a55: enlarge networking stack size The issue is caused by default stack size 1500 bytes of NET_RX_STACK_SIZE is to small for ARM64 platform, then the stack of net_rx thread is overflow and break the net_mgmt thread's stack, as a result net_mgmt thread is crashed. So this patch will enlarge all the stack size of net stack threads. Signed-off-by: Jiafei Pan --- boards/nxp/imx95_evk/Kconfig.defconfig | 35 ++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/boards/nxp/imx95_evk/Kconfig.defconfig b/boards/nxp/imx95_evk/Kconfig.defconfig index 9e5b8db0d693..9635d0008939 100644 --- a/boards/nxp/imx95_evk/Kconfig.defconfig +++ b/boards/nxp/imx95_evk/Kconfig.defconfig @@ -28,4 +28,39 @@ config ARM_SCMI_TRANSPORT_INIT_PRIORITY config CLOCK_CONTROL_INIT_PRIORITY default 31 +# Enlarge default networking stack +if NETWORKING + +config NET_L2_ETHERNET + default y + +config NET_TX_STACK_SIZE + default 8192 + +config NET_RX_STACK_SIZE + default 8192 + +if NET_TCP + +config NET_TCP_WORKQ_STACK_SIZE + default 8192 + +endif # NET_TCP + +if NET_MGMT_EVENT + +config NET_MGMT_EVENT_STACK_SIZE + default 8192 + +endif # NET_MGMT_EVENT + +if NET_SOCKETS_SERVICE + +config NET_SOCKETS_SERVICE_STACK_SIZE + default 8192 + +endif # NET_SOCKETS_SERVICE + +endif # NETWORKING + endif # SOC_MIMX9596_A55 From d6c9cda1bac235507a7b94aabe1684f77bc2e876 Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Wed, 9 Jul 2025 15:16:47 +0800 Subject: [PATCH 27/27] samples: net: zperf: add imx95 evk a55 suppport Add i.MX 95 EVK A55 support for zperf sample. Signed-off-by: Jiafei Pan --- .../net/zperf/boards/imx95_evk_mimx9596_a55.conf | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 samples/net/zperf/boards/imx95_evk_mimx9596_a55.conf diff --git a/samples/net/zperf/boards/imx95_evk_mimx9596_a55.conf b/samples/net/zperf/boards/imx95_evk_mimx9596_a55.conf new file mode 100644 index 000000000000..70a699068df6 --- /dev/null +++ b/samples/net/zperf/boards/imx95_evk_mimx9596_a55.conf @@ -0,0 +1,15 @@ +# The GICv3 & ITS drivers allocation needs are: +# - LPI prop table: global 1x64K aligned on 64K +# - LPI pend table: for each redistributor/cpu 1x64K aligned on 64K +# - Devices table: 128x4K aligned on 4K +# - Interrupt Collections table: 1x4K aligned on 4K +# +# This makes 11x64K to permit all allocations to success. +# +# Note, will need 64K HEAP_MEM per CPUs added. +# +# This doesn't necessarily include the Interrupt Translation Table, which are +# 256bytes aligned tables, for reference a 32 ITEs table needs 256bytes. +# +# To permit allocating 256 ITT tables of 32 ITEs, 13x64K HEAP_MEM is needed +CONFIG_HEAP_MEM_POOL_SIZE=851968