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 <Jiafei.Pan@nxp.com>
This commit is contained in:
parent
bd432c2727
commit
30b6adf42d
@ -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"
|
||||
|
||||
@ -21,6 +21,9 @@ LOG_MODULE_REGISTER(nxp_imx_eth);
|
||||
#include <zephyr/net/phy.h>
|
||||
#include <ethernet/eth_stats.h>
|
||||
#include <zephyr/net/dsa_core.h>
|
||||
#ifdef CONFIG_GIC_V3_ITS
|
||||
#include <zephyr/drivers/interrupt_controller/gicv3_its.h>
|
||||
#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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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)),)) \
|
||||
}; \
|
||||
|
||||
@ -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.
|
||||
|
||||
16
dts/bindings/ethernet/nxp,imx-netc.yaml
Normal file
16
dts/bindings/ethernet/nxp,imx-netc.yaml
Normal file
@ -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
|
||||
Loading…
Reference in New Issue
Block a user