Skip to content
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
9 changes: 9 additions & 0 deletions drivers/ethernet/dsa/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,12 @@ config DSA_NXP_IMX_NETC
Add support for NXP i.MX NETC DSA device driver.

endif # DSA_DRIVERS

config DSA_NXP_NETC_GCL_LEN
int "Gate control list length for i.MX NETC DSA"
default 64
range 1 256
depends on DSA_NXP_IMX_NETC && NET_QBV
help
Amount of Gate control list to use, reduce to save RAM.
The Max of the value can be 64,128,256.
196 changes: 196 additions & 0 deletions drivers/ethernet/dsa/dsa_nxp_imx_netc.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ LOG_MODULE_REGISTER(dsa_netc, CONFIG_ETHERNET_LOG_LEVEL);
#include <zephyr/drivers/pinctrl.h>
#include <zephyr/drivers/ethernet/nxp_imx_netc.h>
#include <zephyr/dt-bindings/ethernet/dsa_tag_proto.h>
#include <zephyr/sys/util_macro.h>

#include "../eth.h"
#include "fsl_netc_switch.h"
Expand All @@ -32,6 +33,13 @@ struct dsa_netc_config {
DEVICE_MMIO_NAMED_ROM(pfconfig);
};

#ifdef CONFIG_NET_QBV
struct netc_qbv_config {
netc_tb_tgs_gcl_t tgs_config;
netc_tgs_gate_entry_t gcList[CONFIG_DSA_NXP_NETC_GCL_LEN];
};
#endif

struct dsa_netc_data {
DEVICE_MMIO_NAMED_RAM(base);
DEVICE_MMIO_NAMED_RAM(pfconfig);
Expand All @@ -42,6 +50,10 @@ struct dsa_netc_data {
uint8_t cpu_port_idx;
struct k_fifo tx_ts_queue;
#endif
#ifdef CONFIG_NET_QBV
struct netc_qbv_config qbv_config[DSA_PORT_MAX_COUNT];
#endif

};

static int dsa_netc_port_init(const struct device *dev)
Expand Down Expand Up @@ -86,6 +98,14 @@ static int dsa_netc_port_init(const struct device *dev)
}
#endif

#ifdef CONFIG_NET_QBV
memset(&(prv->qbv_config[cfg->port_idx].tgs_config), 0, sizeof(netc_tb_tgs_gcl_t));
memset(prv->qbv_config[cfg->port_idx].gcList, 0,
sizeof(netc_tgs_gate_entry_t) * CONFIG_DSA_NXP_NETC_GCL_LEN);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about replace these two memset with the suggested code at: line 476

prv->qbv_config[cfg->port_idx].tgs_config.entryID = cfg->port_idx;
prv->qbv_config[cfg->port_idx].tgs_config.gcList = prv->qbv_config[cfg->port_idx].gcList;
#endif

return 0;
}

Expand Down Expand Up @@ -235,6 +255,179 @@ static int dsa_netc_switch_init(const struct device *dev)
return 0;
}

#ifdef CONFIG_NET_QBV
static int dsa_netc_set_qbv(const struct device *dev, const struct ethernet_config *config)
{
struct dsa_switch_context *dsa_switch_ctx = dev->data;
struct dsa_netc_data *prv = PRV_DATA(dsa_switch_ctx);
struct dsa_port_config *cfg = (struct dsa_port_config *)dev->config;
status_t result;
uint32_t gate_num;
int i;
uint16_t row;
int ret = 0;

switch (config->qbv_param.type) {
case ETHERNET_QBV_PARAM_TYPE_STATUS:
result = SWT_TxPortTGSEnable(&prv->swt_handle, cfg->port_idx,
config->qbv_param.enabled);
if (result != kStatus_Success) {
LOG_ERR("Couldn't enable/disable QBV");
ret = -ENOTSUP;
}
break;
case ETHERNET_QBV_PARAM_TYPE_TIME:
prv->qbv_config[cfg->port_idx].tgs_config.baseTime =
config->qbv_param.base_time.second * NSEC_PER_SEC
+ (config->qbv_param.base_time.fract_nsecond >> 16);
prv->qbv_config[cfg->port_idx].tgs_config.cycleTime =
(uint32_t)(config->qbv_param.cycle_time.second * NSEC_PER_SEC
+ config->qbv_param.cycle_time.nanosecond);
prv->qbv_config[cfg->port_idx].tgs_config.extTime =
config->qbv_param.extension_time;
break;
case ETHERNET_QBV_PARAM_TYPE_GATE_CONTROL_LIST:
row = config->qbv_param.gate_control.row;
gate_num = ((CONFIG_NET_TC_TX_COUNT) < 8 ? (CONFIG_NET_TC_TX_COUNT) : 8);
if (row > CONFIG_DSA_NXP_NETC_GCL_LEN) {
LOG_ERR("The gate control list length exceeds the limit");
ret = -ENOTSUP;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
}
break;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will fix next version

prv->qbv_config[cfg->port_idx].gcList[row].interval =
config->qbv_param.gate_control.time_interval;
prv->qbv_config[cfg->port_idx].gcList[row].tcGateState = 0;
for (i = 0; i < gate_num; i++) {
prv->qbv_config[cfg->port_idx].gcList[row].tcGateState
|= config->qbv_param.gate_control.gate_status[i] << i;
}
if (prv->qbv_config[cfg->port_idx].tgs_config.numEntries > 0 &&
(row + 1) == prv->qbv_config[cfg->port_idx].tgs_config.numEntries) {
result = SWT_TxTGSConfigAdminGcl(&prv->swt_handle,
&(prv->qbv_config[cfg->port_idx].tgs_config));
if (result != kStatus_Success) {
LOG_ERR("Fail to set gate control list, err code: 0x%x", result);
ret = -ENOTSUP;
}
}
break;
case ETHERNET_QBV_PARAM_TYPE_GATE_CONTROL_LIST_LEN:
prv->qbv_config[cfg->port_idx].tgs_config.numEntries =
config->qbv_param.gate_control_list_len;
break;
default:
/* No validation needed */
break;
}

return ret;
}

static int dsa_netc_get_qbv(const struct device *dev, struct ethernet_config *config)
{
struct dsa_switch_context *dsa_switch_ctx = dev->data;
struct dsa_netc_data *prv = PRV_DATA(dsa_switch_ctx);
struct dsa_port_config *cfg = (struct dsa_port_config *)dev->config;
uint32_t gate_num;
int i;
uint16_t row;
int ret = 0;

switch (config->qbv_param.type) {
case ETHERNET_QBV_PARAM_TYPE_STATUS:
config->qbv_param.enabled = ((prv->swt_handle.hw.ports[cfg->port_idx].port->PTGSCR
& NETC_PORT_PTGSCR_TGE_MASK) != 0);
break;
case ETHERNET_QBV_PARAM_TYPE_TIME:
config->qbv_param.base_time.second =
prv->qbv_config[cfg->port_idx].tgs_config.baseTime / NSEC_PER_SEC;
config->qbv_param.base_time.fract_nsecond =
prv->qbv_config[cfg->port_idx].tgs_config.baseTime % NSEC_PER_SEC << 16;
config->qbv_param.cycle_time.second = (uint64_t)
(prv->qbv_config[cfg->port_idx].tgs_config.cycleTime / NSEC_PER_SEC);
config->qbv_param.cycle_time.nanosecond =
prv->qbv_config[cfg->port_idx].tgs_config.cycleTime % NSEC_PER_SEC;
config->qbv_param.extension_time =
prv->qbv_config[cfg->port_idx].tgs_config.extTime;
break;
case ETHERNET_QBV_PARAM_TYPE_GATE_CONTROL_LIST:
row = config->qbv_param.gate_control.row;
gate_num = ((CONFIG_NET_TC_TX_COUNT) < 8 ? (CONFIG_NET_TC_TX_COUNT) : 8);
if (row > CONFIG_DSA_NXP_NETC_GCL_LEN) {
LOG_ERR("The gate control list length exceeds the limit");
ret = -ENOTSUP;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
}
break;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will fix next version

config->qbv_param.gate_control.time_interval =
prv->qbv_config[cfg->port_idx].gcList[row].interval;
for (i = 0; i < gate_num; i++) {
config->qbv_param.gate_control.gate_status[i] =
((prv->qbv_config[cfg->port_idx].gcList[row].tcGateState
& BIT(i)) != 0);
}
break;
case ETHERNET_QBV_PARAM_TYPE_GATE_CONTROL_LIST_LEN:
config->qbv_param.gate_control_list_len =
prv->qbv_config[cfg->port_idx].tgs_config.numEntries;
break;
default:
/* No validation needed */
break;
}

return ret;
}
#endif

static int dsa_netc_set_config(const struct device *dev, enum ethernet_config_type type,
const struct ethernet_config *config)
{
int ret = 0;

switch (type) {
#ifdef CONFIG_NET_QBV
case ETHERNET_CONFIG_TYPE_QBV_PARAM:
ret = dsa_netc_set_qbv(dev, config);
break;
#endif
default:
ret = -ENOTSUP;
break;
}

return ret;
}

static int dsa_netc_get_config(const struct device *dev, enum ethernet_config_type type,
struct ethernet_config *config)
{
int ret = 0;

switch (type) {
#ifdef CONFIG_NET_QBV
case ETHERNET_CONFIG_TYPE_QBV_PARAM:
ret = dsa_netc_get_qbv(dev, config);
break;
#endif
default:
ret = -ENOTSUP;
break;
}

return ret;
}

static enum ethernet_hw_caps dsa_port_get_capabilities(const struct device *dev)
{
uint32_t caps = 0;

ARG_UNUSED(dev);

#ifdef CONFIG_NET_QBV
caps |= ETHERNET_QBV;
#endif

return caps;
}

static struct dsa_api dsa_netc_api = {
.port_init = dsa_netc_port_init,
.port_generate_random_mac = dsa_netc_port_generate_random_mac,
Expand All @@ -244,6 +437,9 @@ static struct dsa_api dsa_netc_api = {
.port_txtstamp = dsa_netc_port_txtstamp,
#endif
.connect_tag_protocol = dsa_netc_connect_tag_protocol,
.get_capabilities = dsa_port_get_capabilities,
.set_config = dsa_netc_set_config,
.get_config = dsa_netc_get_config,
};

#define DSA_NETC_PORT_INST_INIT(port, n) \
Expand Down
13 changes: 13 additions & 0 deletions include/zephyr/net/dsa_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,19 @@ struct dsa_api {

/** Connect the switch to the tag protocol */
int (*connect_tag_protocol)(struct dsa_switch_context *dsa_switch_ctx, int tag_proto);

/** Get the device capabilities */
enum ethernet_hw_caps (*get_capabilities)(const struct device *dev);

/** Set specific hardware configuration */
int (*set_config)(const struct device *dev,
enum ethernet_config_type type,
const struct ethernet_config *config);

/** Get hardware specific configuration */
int (*get_config)(const struct device *dev,
enum ethernet_config_type type,
struct ethernet_config *config);
};

/**
Expand Down
10 changes: 10 additions & 0 deletions subsys/net/l2/ethernet/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -174,4 +174,14 @@ config NET_ETHERNET_FORWARD_UNRECOGNISED_ETHERTYPE
it does not recognize the EtherType in the header. By default, such
frames are dropped at the L2 processing.

config NET_QBV
bool "Qbv support"
depends on PTP_CLOCK
help
Enable Qbv support, Qbv is Enhancements for Scheduled Traffic (EST), one
feature of TSN. It provides time "slots" for specific classes of traffic
in a manner similar to TDM. Host (beyond standard) can select time/time
gate during which a packet will be sent, granular control by software of
packet transmission.

endif # NET_L2_ETHERNET
32 changes: 32 additions & 0 deletions subsys/net/l2/ethernet/dsa/dsa_port.c
Original file line number Diff line number Diff line change
Expand Up @@ -133,16 +133,46 @@ const struct device *dsa_port_get_ptp_clock(const struct device *dev)

enum ethernet_hw_caps dsa_port_get_capabilities(const struct device *dev)
{
struct dsa_switch_context *dsa_switch_ctx = dev->data;
uint32_t caps = 0;

#ifdef CONFIG_NET_L2_PTP
if (dsa_port_get_ptp_clock(dev) != NULL) {
caps |= ETHERNET_PTP;
}
#endif

if (dsa_switch_ctx->dapi->get_capabilities) {
caps |= dsa_switch_ctx->dapi->get_capabilities(dev);
}

return caps;
}

static int dsa_set_config(const struct device *dev, enum ethernet_config_type type,
const struct ethernet_config *config)
{
struct dsa_switch_context *dsa_switch_ctx = dev->data;

if (!dsa_switch_ctx->dapi->set_config) {
return -ENOTSUP;
}

return dsa_switch_ctx->dapi->set_config(dev, type, config);
}

static int dsa_get_config(const struct device *dev, enum ethernet_config_type type,
struct ethernet_config *config)
{
struct dsa_switch_context *dsa_switch_ctx = dev->data;

if (!dsa_switch_ctx->dapi->get_config) {
return -ENOTSUP;
}

return dsa_switch_ctx->dapi->get_config(dev, type, config);
}

const struct ethernet_api dsa_eth_api = {
.iface_api.init = dsa_port_iface_init,
.get_phy = dsa_port_get_phy,
Expand All @@ -151,4 +181,6 @@ const struct ethernet_api dsa_eth_api = {
.get_ptp_clock = dsa_port_get_ptp_clock,
#endif
.get_capabilities = dsa_port_get_capabilities,
.set_config = dsa_set_config,
.get_config = dsa_get_config,
};
1 change: 1 addition & 0 deletions subsys/net/lib/shell/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,4 @@ zephyr_library_sources_ifdef(CONFIG_NET_SHELL_UDP_SUPPORTED udp.c)
zephyr_library_sources_ifdef(CONFIG_NET_SHELL_VIRTUAL_SUPPORTED virtual.c)
zephyr_library_sources_ifdef(CONFIG_NET_SHELL_VLAN_SUPPORTED vlan.c)
zephyr_library_sources_ifdef(CONFIG_NET_SHELL_WEBSOCKET_SUPPORTED websocket.c)
zephyr_library_sources_ifdef(CONFIG_NET_SHELL_QBV_SUPPORTED qbv_shell.c)
8 changes: 8 additions & 0 deletions subsys/net/lib/shell/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,14 @@ config NET_SHELL_WEBSOCKET_SUPPORTED
default y
depends on NET_SHELL_SHOW_DISABLED_COMMANDS || WEBSOCKET_CLIENT

config NET_SHELL_QBV_SUPPORTED
bool "Qbv Shell"
default y
depends on NET_SHELL_SHOW_DISABLED_COMMANDS || (NET_QBV && NET_L2_ETHERNET_MGMT)
help
Enable Qbv Shell.
The Qbv shell currently supports set/enable operations.

config NET_SHELL_DYN_CMD_COMPLETION
bool "Network shell dynamic command completion"
default y
Expand Down
Loading