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 b482bf3336b1e..c3175c74ff2f8 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 cc22eaedb17f8..afc5c6d4377b4 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 6316e686c7557..d3864bbab32a8 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 d3864bbab32a8..a9a6018cdd89d 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 a9a6018cdd89d..544158685e1d0 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 d4aff0f100de9..4d4866c1a858f 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 37df069d3dd0c..cc52bd1d2b23d 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 0fc9f23d68880..9047517a1001c 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 9047517a1001c..0d7fef5ac1fd2 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 0000000000000..a32ec5b99bbde --- /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 23e5dd52c5a41..88a5148a54ed7 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 0000000000000..70a699068df66 --- /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 42f18067b33f0..940e4f504f0d7 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 fe8253bfa2f22..cbc16958256ad 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 5c6af4f5c0cb6..21636cb438aca 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 32762582dce7d..ec82fafb653b8 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 157f7e61bae47..1aba309246fd7 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 3dc10ae872469..10f0def52e852 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 7aba10df1e35d..128a385af07a9 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 0000000000000..bf1d53254a245 --- /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 477bcc38f6ae9..2b43501bfec0e 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 91fbf4d4f1eef..28631f49ba316 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 0000000000000..5e6aaa9e87978 --- /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 0000000000000..7ad70ebaf5e3a --- /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 4882f16b08d98..c9afc4a4c4055 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 d413ad122541a0dca0acdfbb807a8d9f98a15ac3 Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Wed, 2 Jul 2025 12:10:50 +0800 Subject: [PATCH 15/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_priv.h | 4 ++++ drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc_psi.c | 8 ++++++++ 2 files changed, 12 insertions(+) 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 1aba309246fd7..3dce788f1a24c 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,8 @@ } struct netc_eth_config { + DEVICE_MMIO_NAMED_ROM(port); + DEVICE_MMIO_NAMED_ROM(pfconfig); uint16_t si_idx; const struct device *phy_dev; netc_hw_mii_mode_t phy_mode; @@ -109,6 +111,8 @@ struct netc_eth_config { typedef uint8_t rx_buffer_t[NETC_RX_RING_BUF_SIZE_ALIGN]; struct netc_eth_data { + DEVICE_MMIO_NAMED_RAM(port); + DEVICE_MMIO_NAMED_RAM(pfconfig); ep_handle_t handle; struct net_if *iface; uint8_t mac_addr[6]; 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 10f0def52e852..1f2eda5094971 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,9 @@ static int netc_eth_init(const struct device *dev) const struct netc_eth_config *cfg = dev->config; int err; + DEVICE_MMIO_NAMED_MAP(dev, port, K_MEM_CACHE_NONE | K_MEM_DIRECT_MAP); + DEVICE_MMIO_NAMED_MAP(dev, pfconfig, K_MEM_CACHE_NONE | K_MEM_DIRECT_MAP); + if (cfg->pseudo_mac) { goto init_common; } @@ -192,6 +198,8 @@ 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_BY_NAME(port, DT_DRV_INST(n)), \ + DEVICE_MMIO_NAMED_ROM_INIT_BY_NAME(pfconfig, 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 51a237be742e948e965b756317d06a2edabbb8a4 Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Mon, 30 Jun 2025 10:55:58 +0800 Subject: [PATCH 16/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 b794013ca972c..d7fa09bed8551 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 554428c662588b29b36b6c6945ccb9f7f31963c9 Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Thu, 17 Jul 2025 17:00:46 +0800 Subject: [PATCH 17/27] dts: bindling: imx-netc: remove unused reg property As reg property is not used by the driver and there is no proper address could be assigned to it, so remove it. Signed-off-by: Jiafei Pan --- dts/bindings/ethernet/nxp,imx-netc.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/dts/bindings/ethernet/nxp,imx-netc.yaml b/dts/bindings/ethernet/nxp,imx-netc.yaml index bf1d53254a245..badfc134a7e3c 100644 --- a/dts/bindings/ethernet/nxp,imx-netc.yaml +++ b/dts/bindings/ethernet/nxp,imx-netc.yaml @@ -8,9 +8,6 @@ compatible: "nxp,imx-netc" include: [base.yaml] properties: - reg: - required: true - msi-parent: type: phandle description: MSI controller From 7257445d007955d1db39e5578eb47137bce18aef 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. 3. Added all memory region in MMIO reg propertiy to let driver to handle MMIO mapping for all memory region. Signed-off-by: Jiafei Pan --- dts/arm/nxp/nxp_imx95_m7.dtsi | 93 +++++++++++++++++++++-------------- 1 file changed, 56 insertions(+), 37 deletions(-) diff --git a/dts/arm/nxp/nxp_imx95_m7.dtsi b/dts/arm/nxp/nxp_imx95_m7.dtsi index 1751f15014eb3..b80830aa264c5 100644 --- a/dts/arm/nxp/nxp_imx95_m7.dtsi +++ b/dts/arm/nxp/nxp_imx95_m7.dtsi @@ -526,52 +526,71 @@ }; }; - 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 { + compatible = "nxp,imx-netc"; + 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>, + <0x4ca00000 0x1000>; + reg-names = "port", "pfconfig"; + 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>, + <0x4ca40000 0x1000>; + reg-names = "port", "pfconfig"; + mac-index = <1>; + si-index = <1>; + 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>, + <0x4ca80000 0x1000>; + reg-names = "port", "pfconfig"; + mac-index = <2>; + si-index = <2>; + status = "disabled"; + }; - enetc_psi2: ethernet@4cc80000 { - compatible = "nxp,imx-netc-psi"; - reg = <0x4cc80000 0x10000>; - 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"; + enetc_ptp_clock: ptp_clock@4ccc0000 { + compatible = "nxp,netc-ptp-clock"; + reg = <0x4ccc0000 0x10000>; + clocks = <&scmi_clk IMX95_CLK_ENET>; + status = "disabled"; + }; }; }; }; From 43f6f5e4702f4e95bb5a6cdefbc81be573798666 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. 2. Added all memory region in MMIO reg propertiy to let driver to handle MMIO mapping for all memory region. Signed-off-by: Jiafei Pan --- dts/arm/nxp/nxp_rt118x.dtsi | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/dts/arm/nxp/nxp_rt118x.dtsi b/dts/arm/nxp/nxp_rt118x.dtsi index dc25cfb24ecb4..8556d002605a3 100644 --- a/dts/arm/nxp/nxp_rt118x.dtsi +++ b/dts/arm/nxp/nxp_rt118x.dtsi @@ -618,15 +618,17 @@ }; }; - netc: ethernet@60000000 { - reg = <0x60000000 0x1000000>; + netc: ethernet { + compatible = "nxp,imx-netc"; #address-cells = <1>; #size-cells = <1>; ranges; enetc_psi0: ethernet@60b00000 { compatible = "nxp,imx-netc-psi"; - reg = <0x60b00000 0x10000>; + reg = <0x60b00000 0x10000>, + <0x60003000 0x1000>; + reg-names = "port", "pfconfig"; mac-index = <0>; si-index = <0>; status = "disabled"; @@ -634,22 +636,15 @@ enetc_psi1: ethernet@60b40000 { compatible = "nxp,imx-netc-psi"; - reg = <0x60b40000 0x10000>; + reg = <0x60b40000 0x10000>, + <0x60004000 0x1000>; + reg-names = "port", "pfconfig"; mac-index = <1>; si-index = <1>; phy-connection-type = "internal"; 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 +681,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 edbdc1dbcc08745795a90e3cb14babeec7e8ecdf 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. 2. Added all memory region in MMIO reg propertiy to let driver to handle MMIO mapping for all memory region. Signed-off-by: Jiafei Pan --- dts/arm/nxp/nxp_imx943_m33.dtsi | 36 ++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/dts/arm/nxp/nxp_imx943_m33.dtsi b/dts/arm/nxp/nxp_imx943_m33.dtsi index 787fbcfd29744..41637e6a96638 100644 --- a/dts/arm/nxp/nxp_imx943_m33.dtsi +++ b/dts/arm/nxp/nxp_imx943_m33.dtsi @@ -263,25 +263,18 @@ status = "disabled"; }; - netc: ethernet@4ca00000 { - reg = <0x4ca00000 0x500000>; + netc: ethernet { + compatible = "nxp,imx-netc"; 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>; + reg = <0x4cc80000 0x10000>, + <0x4cb00000 0x1000>; + reg-names = "port", "pfconfig"; mac-index = <0>; si-index = <0>; status = "disabled"; @@ -289,7 +282,9 @@ enetc_psi1: ethernet@4ccc0000 { compatible = "nxp,imx-netc-psi"; - reg = <0x4ccc0000 0x10000>; + reg = <0x4ccc0000 0x10000>, + <0x4cb40000 0x1000>; + reg-names = "port", "pfconfig"; mac-index = <1>; si-index = <1>; status = "disabled"; @@ -297,7 +292,9 @@ enetc_psi2: ethernet@4cd00000 { compatible = "nxp,imx-netc-psi"; - reg = <0x4cd00000 0x10000>; + reg = <0x4cd00000 0x10000>, + <0x4cb80000 0x1000>; + reg-names = "port", "pfconfig"; mac-index = <2>; si-index = <2>; status = "disabled"; @@ -323,6 +320,17 @@ clocks = <&scmi_clk IMX943_CLK_ENET>; 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 d7cfef160bdaaaa555b2379bfd9fb5d2f466f1b5 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 | 70 +++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/dts/arm64/nxp/nxp_mimx95_a55.dtsi b/dts/arm64/nxp/nxp_mimx95_a55.dtsi index cc52bd1d2b23d..bf0fbd5858ee9 100644 --- a/dts/arm64/nxp/nxp_mimx95_a55.dtsi +++ b/dts/arm64/nxp/nxp_mimx95_a55.dtsi @@ -476,6 +476,76 @@ 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 { + compatible = "nxp,imx-netc"; + msi-parent = <&its>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + enetc_psi0: ethernet@4cc00000 { + compatible = "nxp,imx-netc-psi"; + reg = <0x4cc00000 0x40000>, + <0x4ca00000 0x1000>; + reg-names = "port", "pfconfig"; + msi-device-id = <0x60>; + mac-index = <0>; + si-index = <0>; + status = "disabled"; + }; + + enetc_psi1: ethernet@4cc40000 { + compatible = "nxp,imx-netc-psi"; + reg = <0x4cc40000 0x40000>, + <0x4ca40000 0x1000>; + reg-names = "port", "pfconfig"; + msi-device-id = <0x63>; + mac-index = <1>; + si-index = <1>; + status = "disabled"; + }; + + enetc_psi2: ethernet@4cc80000 { + compatible = "nxp,imx-netc-psi"; + reg = <0x4cc80000 0x40000>, + <0x4ca80000 0x1000>; + reg-names = "port", "pfconfig"; + 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 f04dbecfb2b3fe1f4973f1827274db0c33753a8a 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 bf0fbd5858ee9..ae13c72d2716f 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 5524d9df9a044aa1fa1c03fb0e7a5e6a5de4f261 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 29d2c963578d5..91aeb788e6715 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 c2e18fa47c6a0be394a1e7c7a93c086c98a02983 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 4b52b0563c8ec..4a186e4300719 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 a14003810f063..0000000000000 --- 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 8b661db7a8aff..6c5167634d257 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 685a06bbc35a16b97fdf99a3ab53ab0a2b833db6 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 a32ec5b99bbde..9e5b8db0d6931 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 4a186e4300719..aba0d3f51209d 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 4d4866c1a858f..51b3d7f704eb6 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 085689ef9d14371172abad810e865e0b50057a7d 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 9e5b8db0d6931..9635d00089396 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 0dec6e883d6fa9bd4a15ffb8aff1a790ba975cd5 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 0000000000000..70a699068df66 --- /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