Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable NETC support for i.MX95 EKV M7 #81113

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 34 additions & 4 deletions arch/arm/core/cortex_a_r/irq_manage.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,24 +33,32 @@ extern void z_arm_reserved(void);
* Generic Interrupt Controller (GIC) and therefore the architecture interrupt
* control functions are mapped to the GIC driver interface.
*
* When GIC is used together with other interrupt controller for
* multi-level interrupts support (i.e. CONFIG_MULTI_LEVEL_INTERRUPTS
* is enabled), the architecture interrupt control functions are mapped
* to the SoC layer in `include/arch/arm/irq.h`.
* The exported arm interrupt control functions which are wrappers of
* GIC control could be used for SoC to do level 1 irq control to implement SoC
* layer interrupt control functions.
*
* When a custom interrupt controller is used (i.e.
* CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER is enabled), the architecture
* interrupt control functions are mapped to the SoC layer in
* `include/arch/arm/irq.h`.
*/

#if !defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER)
void arch_irq_enable(unsigned int irq)
void arm_irq_enable(unsigned int irq)
{
arm_gic_irq_enable(irq);
}

void arch_irq_disable(unsigned int irq)
void arm_irq_disable(unsigned int irq)
{
arm_gic_irq_disable(irq);
}

int arch_irq_is_enabled(unsigned int irq)
int arm_irq_is_enabled(unsigned int irq)
{
return arm_gic_irq_is_enabled(irq);
}
Expand All @@ -65,10 +73,32 @@ int arch_irq_is_enabled(unsigned int irq)
* priority levels which are reserved: three for various types of exceptions,
* and possibly one additional to support zero latency interrupts.
*/
void z_arm_irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flags)
void arm_irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flags)
{
arm_gic_irq_set_priority(irq, prio, flags);
}

#if !defined(CONFIG_MULTI_LEVEL_INTERRUPTS)
void arch_irq_enable(unsigned int irq)
{
arm_irq_enable(irq);
}

void arch_irq_disable(unsigned int irq)
{
arm_irq_disable(irq);
}

int arch_irq_is_enabled(unsigned int irq)
{
return arm_irq_is_enabled(irq);
}

void z_arm_irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flags)
{
arm_irq_priority_set(irq, prio, flags);
}
#endif
#endif /* !CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */

void z_arm_fatal_error(unsigned int reason, const struct arch_esf *esf);
Expand Down
5 changes: 5 additions & 0 deletions arch/arm/core/cortex_m/irq_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,12 @@ void z_arm_interrupt_init(void)
{
int irq = 0;

/* CONFIG_2ND_LVL_ISR_TBL_OFFSET could be treated as total number of level1 interrupts */
#if defined(CONFIG_MULTI_LEVEL_INTERRUPTS) && defined(CONFIG_2ND_LVL_ISR_TBL_OFFSET)
for (; irq < CONFIG_2ND_LVL_ISR_TBL_OFFSET; irq++) {
#else
for (; irq < CONFIG_NUM_IRQS; irq++) {
#endif
NVIC_SetPriority((IRQn_Type)irq, _IRQ_PRIO_OFFSET);
}
}
48 changes: 44 additions & 4 deletions arch/arm/core/cortex_m/irq_manage.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,38 @@ extern void z_arm_reserved(void);
#define REG_FROM_IRQ(irq) (irq / NUM_IRQS_PER_REG)
#define BIT_FROM_IRQ(irq) (irq % NUM_IRQS_PER_REG)

/*
* For Cortex-M core, the default interrupt controller is the ARM
* NVIC and therefore the architecture interrupt control functions
* are mapped to the NVIC driver interface.
*
* When NVIC is used together with other interrupt controller for
* multi-level interrupts support (i.e. CONFIG_MULTI_LEVEL_INTERRUPTS
* is enabled), the architecture interrupt control functions are mapped
* to the SoC layer in `include/arch/arm/irq.h`.
* The exported arm interrupt control functions which are wrappers of
* NVIC control could be used for SoC to do level 1 irq control to implement SoC
* layer interrupt control functions.
*
* When a custom interrupt controller is used (i.e.
* CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER is enabled), the architecture
* interrupt control functions are mapped to the SoC layer in
* `include/arch/arm/irq.h`.
*/

#if !defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER)

void arch_irq_enable(unsigned int irq)
void arm_irq_enable(unsigned int irq)
{
NVIC_EnableIRQ((IRQn_Type)irq);
}

void arch_irq_disable(unsigned int irq)
void arm_irq_disable(unsigned int irq)
{
NVIC_DisableIRQ((IRQn_Type)irq);
}

int arch_irq_is_enabled(unsigned int irq)
int arm_irq_is_enabled(unsigned int irq)
{
return NVIC->ISER[REG_FROM_IRQ(irq)] & BIT(BIT_FROM_IRQ(irq));
}
Expand All @@ -58,7 +77,7 @@ int arch_irq_is_enabled(unsigned int irq)
* of priority levels is a little complex, as there are some hardware
* priority levels which are reserved.
*/
void z_arm_irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flags)
void arm_irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flags)
{
/* The kernel may reserve some of the highest priority levels.
* So we offset the requested priority level with the number
Expand Down Expand Up @@ -91,6 +110,27 @@ void z_arm_irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flags)
NVIC_SetPriority((IRQn_Type)irq, prio);
}

#if !defined(CONFIG_MULTI_LEVEL_INTERRUPTS)
void arch_irq_enable(unsigned int irq)
{
arm_irq_enable(irq);
}

void arch_irq_disable(unsigned int irq)
{
arm_irq_disable(irq);
}

int arch_irq_is_enabled(unsigned int irq)
{
return arm_irq_is_enabled(irq);
}

void z_arm_irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flags)
{
arm_irq_priority_set(irq, prio, flags);
}
#endif
#endif /* !defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER) */

void z_arm_fatal_error(unsigned int reason, const struct arch_esf *esf);
Expand Down
3 changes: 3 additions & 0 deletions boards/nxp/imx95_evk/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ if (CONFIG_SOF AND CONFIG_BOARD_IMX95_EVK_MIMX9596_M7_DDR)
DEPENDS ${CMAKE_BINARY_DIR}/zephyr/${KERNEL_ELF_NAME}
)
endif()

zephyr_library()
zephyr_library_sources(board.c)
36 changes: 36 additions & 0 deletions boards/nxp/imx95_evk/board.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright 2024 NXP
* SPDX-License-Identifier: Apache-2.0
*/

#include <zephyr/devicetree.h>
#include <zephyr/init.h>
#include <zephyr/kernel.h>
#include <soc.h>

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;
}

/*
* Because platform is using ARM SCMI, drivers like scmi, mbox etc. are
* initialized during PRE_KERNEL_1. Common init hooks is not able to use.
* SoC early init and board early init could be run during PRE_KERNEL_2 instead.
*/
SYS_INIT(board_init, PRE_KERNEL_2, 10);
8 changes: 8 additions & 0 deletions boards/nxp/imx95_evk/doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ The Zephyr ``imx95_evk/mimx9596/m7`` board target supports the following hardwar
+-----------+------------+-------------------------------------+
| SPI | on-chip | spi |
+-----------+------------+-------------------------------------+
| NETC | on-chip | ethernet, mdio |
+-----------+------------+-------------------------------------+

The Zephyr ``imx95_evk/mimx9596/a55`` and ``imx95_evk/mimx9596/a55/smp`` board targets support
the following hardware features:
Expand Down Expand Up @@ -141,6 +143,12 @@ SPI
The EVK board need to be reworked to solder R1217/R1218/R1219/R1220 with 0R resistances.
SPI1 on J35 is enabled for M7.

Ethernet
--------

NETC driver supports to manage the Physical Station Interface (PSI).
The first ENET1 port is enabled for M7.


Programming and Debugging (A55)
*******************************
Expand Down
36 changes: 36 additions & 0 deletions boards/nxp/imx95_evk/imx95_evk-pinctrl.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,42 @@
#include <nxp/nxp_imx/mimx9596avzxn-pinctrl.dtsi>

&pinctrl {
emdio_default: emdio_default {
group1 {
pinmux = <&iomuxc_enet1_mdc_netc_mdc_netc_mdc>,
<&iomuxc_enet1_mdio_netc_mdio_netc_mdio>;
bias-pull-down;
slew-rate = "slightly_fast";
drive-strength = "x6";
};
};

eth0_default: eth0_default {
group1 {
pinmux = <&iomuxc_enet1_rx_ctl_eth_rgmii_rx_ctl_eth0_rgmii_rx_ctl>,
<&iomuxc_enet1_rd0_eth_rgmii_rd_eth0_rgmii_rd0>,
<&iomuxc_enet1_rd1_eth_rgmii_rd_eth0_rgmii_rd1>,
<&iomuxc_enet1_rd2_eth_rgmii_rd_eth0_rgmii_rd2>,
<&iomuxc_enet1_rd3_eth_rgmii_rd_eth0_rgmii_rd3>,
<&iomuxc_enet1_tx_ctl_eth_rgmii_tx_ctl_eth0_rgmii_tx_ctl>,
<&iomuxc_enet1_td0_eth_rgmii_td_eth0_rgmii_td0>,
<&iomuxc_enet1_td1_eth_rgmii_td_eth0_rgmii_td1>,
<&iomuxc_enet1_td2_eth_rgmii_td_eth0_rgmii_td2>,
<&iomuxc_enet1_td3_eth_rgmii_td_eth0_rgmii_td3>;
bias-pull-down;
slew-rate = "slightly_fast";
drive-strength = "x6";
};
group2 {
pinmux = <&iomuxc_enet1_rxc_eth_rgmii_rx_clk_eth0_rgmii_rx_clk>,
<&iomuxc_enet1_txc_eth_rgmii_tx_clk_eth0_rgmii_tx_clk>;
bias-pull-down;
slew-rate = "fast";
drive-strength = "x6";
};

};

lpi2c5_default: lpi2c5_default {
group0 {
pinmux = <&iomuxc_gpio_io23_lpi2c_scl_lpi2c5_scl>,
Expand Down
21 changes: 21 additions & 0 deletions boards/nxp/imx95_evk/imx95_evk_mimx9596_m7.dts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,27 @@
};
};

&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 = <&eth0_default>;
pinctrl-names = "default";
phy-handle = <&phy0>;
phy-connection-type = "rgmii";
status = "okay";
};

&lpi2c5 {
pinctrl-0 = <&lpi2c5_default>;
pinctrl-names = "default";
Expand Down
1 change: 1 addition & 0 deletions boards/nxp/imx95_evk/imx95_evk_mimx9596_m7.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ supported:
- i2c
- pwm
- spi
- netif:eth
vendor: nxp
12 changes: 10 additions & 2 deletions drivers/ethernet/nxp_imx_netc/eth_nxp_imx_netc_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,20 @@
/* MSGINTR */
#define NETC_MSGINTR_CHANNEL 0

#if DT_IRQ_HAS_IDX(DT_NODELABEL(netc), 0)
#define NETC_MSGINTR_IRQ DT_IRQN_BY_IDX(DT_NODELABEL(netc), 0)
#endif

#if (CONFIG_ETH_NXP_IMX_MSGINTR == 1)
#define NETC_MSGINTR MSGINTR1
#define NETC_MSGINTR MSGINTR1
#ifndef NETC_MSGINTR_IRQ
#define NETC_MSGINTR_IRQ MSGINTR1_IRQn
#endif
#elif (CONFIG_ETH_NXP_IMX_MSGINTR == 2)
#define NETC_MSGINTR MSGINTR2
#define NETC_MSGINTR MSGINTR2
#ifndef NETC_MSGINTR_IRQ
#define NETC_MSGINTR_IRQ MSGINTR2_IRQn
#endif
#else
#error "Current CONFIG_ETH_NXP_IMX_MSGINTR not support"
#endif
Expand Down
1 change: 0 additions & 1 deletion drivers/interrupt_controller/Kconfig.nxp_irqsteer
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ config NXP_IRQSTEER
default y
depends on DT_HAS_NXP_IRQSTEER_INTC_ENABLED
depends on MULTI_LEVEL_INTERRUPTS
depends on XTENSA
help
The IRQSTEER INTC provides support for MUX-ing
multiple interrupts from peripheral to one or
Expand Down
Loading
Loading