PDK API Guide for J721E
Enet Integration Guide

Getting Familiar with Enet LLD APIs


The Enet LLD APIs can be broadly divided into two categories: control and data path. The control APIs can be used to configure all Ethernet hardware submodules like FDB, MAC port, host port, MDIO, statistics, as well as PHY drivers and resource management. The data path APIs are exclusive for the DMA-based data transfers between the TI SoC processing cores and the Ethernet peripheral.

The main APIs of the Enet LLD are the following:

It's worth noting that the control path APIs are mainly IOCTL-based, and the data path APIs are direct functions in order to avoid any additional overhead associated with IOCTL calls as DMA data operations occur highly frequently.

IOCTL Interface


IOCTLs are system calls that take an argument specifying the command code and can take none or additional parameters via Enet_IoctlPrms argument. IOCTL are used by all Enet submodules except for DMA.

The Enet_IoctlPrms parameter structure consists of input and output argument pointers and their corresponding size. The following helper macros are provided to help construct the IOCTL params:

where prms in a pointer to Enet_IoctlPrms variable, in is the pointer to IOCTL input argument and out is the pointer to IOCTL output argument.

It's recommended that the application doesn't set the Enet_IoctlPrms members individually, but only through the helper macros listed above.

Please refer to the individual IOCTL command to find out if it requires input and/or output parameters.

Back To Top

Integrating Enet LLD into User's Application


Developers who wish to add network connectivity to the applications running on TI SoCs, will have to integrate Enet LLD by following the below sequence:

  1. Init Sequence. One-time initialization before using any Enet LLD APIs.
  2. Peripheral Open Sequence. Opens an Ethernet peripheral, it's called for each peripheral that the application intends to use, i.e. ICSSG0 and CPSW.
  3. Port Open Sequence. Opens a MAC port. For peripherals that provide multiple MAC port (i.e. CPSW9G that has 8 MAC ports), this sequence must be followed for each MAC port. This section also covers MAC-PHY and MAC-MAC links.
  4. Packet Send/Receive Sequence. DMA TX and RX channel open sequences as well as functions to use to submit and retrieve queue of packets to/from the driver.
  5. Packet Timestamping Sequence. TX and RX packet timestamping sequence to enable timestamping and retrieval mechanism.
  6. Port Close Sequence. Closes a MAC port. Application has to close all MAC ports which were opened in step 3 when no longer needs those ports.
  7. Peripheral Close Sequence. Closes an Ethernet peripheral when the application no longer needs it. This sequence must be followed for each peripheral that was opened in step 2.
  8. Deinit Sequence. One-time deinitialization once application is done using Enet LLD.

Each of these sequences will be covered in detail in the following sections.

Init Sequence

This is a one-time initialization where the application sets the OSAL and utils functions that Enet LLD will use throughout its lifecycle.

At this stage Enet LLD also initializes its SoC layer which contains data about the Ethernet hardware available in the TI device.

The application should follow the next steps:

  1. (Optional) Enet_initOsalCfg() to initialize the OSAL configuration (see EnetOsal_Cfg) with a default implementation. The default implementation of Enet OSAL interface is based on PDK OSAL layer. Typically, applications can directly use the default Enet OSAL implementation, unless Enet is being used on another OS (i.e. QNX) of if OS is not supported by PDK OSAL layer.
  2. (Optional) Enet_initUtilsCfg() to initialize utils configuration (see EnetUtils_Cfg) with a default implementation. The default implementation of Enet Utils interface is UART-based logging and one-to-one address translations (physical-to-virtual and virtual-to-physical). Applications may want to pass their own utils' print function if UART is not available. Similarly, if a MMU is present and used, applications may need to pass their own address translation functions corresponding to the MMU configuration.
     utilsCfg.print = UART_printf;
     utilsCfg.physToVirt = &myPhysToVirtFxn;
     utilsCfg.virtToPhys = &myVirtToPhysFxn;
    
  3. Enet_init() to pass the OSAL and utils configurations setup in the previous two steps. The application can pass NULL to either the OSAL config or utils config if it intends to use the driver's default implementation.

Peripheral Open Sequence

This is an initialization that needs to be done for each peripheral in the system. The configuration parameters described in this section are peripheral specific.

Application should follow the next steps:

  1. Initialize the peripheral configuration parameters with default values using Enet_initCfg(). Although the application can fill all parameters manually, it's recommended to first get the driver's default values for all parameters and only overwrite the parameters of interest.
    • CPSW peripheral configuration - Cpsw_Cfg structure has the configuration parameters for CPSW Enet Peripheral, such as:
    • ICSSG peripheral configuration - Similarly, ICSSG has its own dedicated configuration structure called Icssg_Cfg where the application passes ICSSG specific configuration parameters, such as:
      • Configuration of the MDIO submodule: Mdio_Cfg.
      • Configuration of TimeSync: IcssgTimeSync_Cfg.
      • Configuration of DMA Resource Partition: EnetRm_ResCfg.
      • Configuration of host port's default: EnetPort_VlanCfg. This is applicable only to ICSSG Switch peripherals which start by default in VLAN aware mode.
  2. Once done with the configuration of the parameters, the UDMA driver has to be opened. Enet utils library provides a helper function called EnetAppUtils_udmaOpen() to open the UDMA driver, and returns a handle that can be passed to the peripheral configuration parameters, i.e. Cpsw_Cfg::dmaCfg.
  3. Enet_open() to open a peripheral, passing the configuration parameters previously initialized. Enet_open() function takes the following arguments:
    • Peripheral type - This specifies the type or class of the peripheral, i.e. CPSW, ICSSG or other.
    • Instance number - This argument specifies the instance number of the peripheral. Refer to Enet Peripherals section for further information about specific peripheral types and instance numbers.
    • Configuration structure - A pointer to the peripheral-specific configuration structure, i.e. Cpsw_Cfg or Icssg_Cfg.
    • Size of the configuration structure.
  4. If the module is opened successfully, the API will return a valid handle pointer to the Enet driver. It's worth noting that there will be a unique Enet handle (Enet_Handle) for each peripheral opened.
  5. Attach the core with the Resource Manager (RM) using ENET_PER_IOCTL_ATTACH_CORE. IOCTL. To use IOCTLs, the application must have the following:
    • Valid handle to the driver.
    • Core ID, which can be obtained using EnetSoc_getCoreId().
    • Valid IOCTL command.
    • Valid pointer to the IOCTL parameters.
  6. Once the application attaches the core with Resource Manager (RM), the IOCTL call will return core key which has to be used in all further RM-related calls.
  7. A MAC address for the host port is to be obtained using Enet utils helper function EnetAppUtils_allocMac() and the corresponding entry in the ALE table can be added using EnetAppUtils_addHostPortEntry().
  8. Allocate memory for Ring Accelerators, Ethernet packets, etc. Enet LLD examples use EnetAppMemUtils to take care of all memory allocation and freeing operations. The developer can take this as reference or can implement their own memory allocation functions.
  9. ICSSG Switch runs in VLAN aware mode, so it requires the following IOCTLs to setup the VLAN:

    Refer to Enet Multiport example for a reference implementation.

Port Open Sequence

The MAC ports can be opened in MAC-to-PHY or MAC-to-MAC mode. In MAC-to-PHY mode, Enet LLD's PHY driver state machine will be used to configure the Ethernet PHY. In MAC-to-MAC mode, the PHY driver will be bypassed entirely.

The link speed and duplexity in MAC-to-PHY can be fixed or auto-negotiated, while in MAC-to-MAC, both link speed and duplexity can be fixed only and must be provided by application.

The steps to open and configure ports in either MAC-to-PHY or MAC-to-MAC modes are shown below.

MAC-PHY link

  1. Set the port number in EnetPer_PortLinkCfg structure.
  2. Set the MAC port interface (RMII, RGMII, SGMII, etc) through the layer, sublayer and variant fields of EnetPer_PortLinkCfg::mii.
  3. The MAC port configuration parameters is peripheral dependent.
    • CPSW MAC Port configuration:
      • Use CpswMacPort_initCfg() to initialize the CPSW MAC port configuration parameters to their default values. Overwrite any parameters as needed.
      • If loopback is to be enabled, set enableLoopback flag in MAC configuration to true. For loopback to be functional the secure flag in host port ALE entry must be set to false. The host port entry update can be done using the CPSW_ALE_IOCTL_ADD_UCAST command.
    • ICSSG MAC Port configuration:
      • Use IcssgMacPort_initCfg() to fill MAC port configuration parameters with default values provided by the ICSSG driver. The application can then overwrite any configuration parameter as needed, i.e. unicast flooding, multicast flooding, etc.
      • ICSSG Switch runs in VLAN aware mode, so the MAC port's default VLAN (EnetPort_VlanCfg) must be passed via IcssgMacPort_Cfg::vlanCfg.
      • ICSSG Dual-MAC runs in VLAN unaware mode, so no default VLAN configuration is required.
  4. Set PHY configuration parameters: generic and model specific.
    1. Use EnetPhy_initCfg() to initialize the PHY generic parameters to their default values, such as auto-negotiation capabilities, strap enable/disable, loopback, etc.
    2. Use PHY specific init config functions to initialize model specific parameters. This init config function is provided by the Ethernet PHYs supported in Enet LLD. For example, Dp83867_initCfg() is used to initialize config params for DP83867 PHYs.
    3. Application can also use the Enet helper function EnetBoard_getPhyCfg() to get PHY configuration information for PHYs in TI EVMs.
  5. Set the link speed and duplexity configuration in EnetPer_PortLinkCfg::linkCfg.
  6. Once all the MAC and PHY configurations are done, the ports can be opened by calling the ENET_PER_IOCTL_OPEN_PORT_LINK command.
  7. CPSW Note: To enable RMII on CPSW9G, external 50 MHz RMII clock from PHY is used on SOC RMII_REF_CLOCK pin. On GESI board, this clock is connected as resistor R225 is not populated. To get RMII_50MHZ_CLK, resistor R225 needs to be populated. We need to move R226 to R225 on GESI board to get this clock.
  8. If all the above steps succeeded without any errors, then the Enet driver, the Ethernet peripheral and a MAC port have been opened successfully.
  9. After opening the port, the driver will run its PHY state machine to configure the PHY and eventually get link up status. Application can query the port link using ENET_PER_IOCTL_IS_PORT_LINK_UP.
    • Application can check the PHY alive status (i.e. whether PHY is present on the MDIO bus) using the ENET_MDIO_IOCTL_IS_ALIVE command.
  10. Once link up is detected, application should do the following steps:

The following code snippet shows how a MAC-PHY link is opened (step 1-6 above). CPSW MAC port 1 connected to a DP83867 RGMII PHY has been chosen for this example.

EnetPer_PortLinkCfg portLinkCfg;
EnetMacPort_LinkCfg *linkCfg = &portLinkCfg.linkCfg;
EnetMacPort_Interface *mii = &portLinkCfg.mii;
CpswMacPort_Cfg cpswMacCfg;
EnetPhy_Cfg *phyCfg = &portLinkCfg.phyCfg;
Dp83867_Cfg dp83867Cfg;
/* Step 1 - MAC port 1 */
portLinkCfg->macPort = ENET_MAC_PORT_1;
/* Step 2 - Set port type to RGMII */
/* Step 3 - Initialize MAC port configuration parameters */
CpswMacPort_initCfg(&cpswMacCfg);
portLinkCfg.macCfg = &cpswMacCfg;
/* Step 4a - Set PHY generic configuration parameters */
phyCfg->phyAddr = 0U;
/* Step 4b - DP83867 PHY specific configuration */
Dp83867_initCfg(&dp83867Cfg);
dp83867Cfg.ledMode[2] = DP83867_LED_RXTXACT;
EnetPhy_setExtendedCfg(phyCfg, &dp83867Cfg, sizeof(dp83867Cfg));
/* Step 5 - Set link speed/duplexity to auto-negotiation */
/* Step 6 - Open port link */
ENET_IOCTL_SET_IN_ARGS(&prms, &portLinkCfg);
status = Enet_ioctl(hEnet, coreId, ENET_PER_IOCTL_OPEN_PORT_LINK, &prms);

MAC-to-MAC link

  1. Set the port number in EnetPer_PortLinkCfg::macPort.
  2. Set the MAC port interface (RMII, RGMII, SGMII, etc) through the layer, sublayer and variant fields of EnetPer_PortLinkCfg::mii.
  3. Initialize the MAC configuration parameters using CpswMacPort_initCfg() and manually overwrite any parameters that differ from defaults.
  4. Set PHY address to ENETPHY_INVALID_PHYADDR to indicate that this is a PHY-less connection.
  5. Set the link speed and duplexity configuration in EnetPer_PortLinkCfg::linkCfg to match those of the partner MAC port. The speed and duplexity must be fixed values, they can't be ENET_SPEED_AUTO or ENET_DUPLEX_AUTO as they are used for auto-negotiation which is not relevant in MAC-to-MAC mode.
  6. Once all the MAC and PHY configurations are done, the ports can be opened by calling the ENET_PER_IOCTL_OPEN_PORT_LINK command.
  7. If all the above steps succeeded without any errors, then the Enet driver, the Ethernet peripheral and a MAC port have been opened successfully.
  8. Once link up is detected, application should do the following steps:

The following code snippet shows how a MAC-to-MAC link is opened (steps 1-6 above). CPSW MAC port 1 connected to partner MAC using RGMII interface at 1 Gbps.

EnetPer_PortLinkCfg portLinkCfg;
EnetMacPort_LinkCfg *linkCfg = &portLinkCfg.linkCfg;
EnetMacPort_Interface *mii = &portLinkCfg.mii;
CpswMacPort_Cfg cpswMacCfg;
EnetPhy_Cfg *phyCfg = &portLinkCfg.phyCfg;
/* Step 1 - MAC port 1 */
portLinkCfg->macPort = ENET_MAC_PORT_1;
/* Step 2 - Set port type to RGMII */
/* Step 3 - Initialize MAC port configuration parameters */
CpswMacPort_initCfg(&cpswMacCfg);
portLinkCfg.macCfg = &cpswMacCfg;
/* Step 4 - Indicate that this is a PHY-less MAC-to-MAC connection */
/* Step 5 - Link speed/duplexity must be explicit set, cannot be set to auto */
/* Step 6 - Open port link */
ENET_IOCTL_SET_IN_ARGS(&prms, &portLinkCfg);
status = Enet_ioctl(hEnet, coreId, ENET_PER_IOCTL_OPEN_PORT_LINK, &prms);

Packet Send/Receive Sequence

  1. The DMA channels to enable data transfer are to be opened. It can be done using the below steps:
  2. Now that the Ethernet peripheral (CPSW or ICSSG) and UDMA are configured, the application can start the data transfer.
    • To transmit data from application:
    • To receive packets that are queued up in the CPSW or ICSSG hardware which are ready to be received by the application:
    • ICSSG Switch requires two different UDMA RX flows, hence the application must retrieve and submit packets via two different queues. Conversely, the ICSSG Dual-MAC only uses a single RX flow, hence packet submit/retrieve happens on a single queue.

Packet Timestamping Sequence

  1. RX packet timestamping doesn't require any enable sequence. The timestamps in nanoseconds will be returned to the application along with the DMA packet info data, that is, in the EnetUdma_PktTsInfo::rxPktTs field of EnetUdma_PktInfo::tsInfo after retrieving RX packets using EnetDma_retrieveRxPktQ().
  2. Application must register a callback function in advance for TX timestamp event (ENET_EVT_TIMESTAMP_TX) via Enet_registerEventCb() function. The callback registration can be done at any time before enabling TX timestamping.
  3. TX packet timestamping requires to be enabled per packet via DMA packet info EnetUdma_PktInfo::tsInfo structure:
  4. After the packet is submitted for transmission using EnetDma_submitTxPktQ(), the timestamp can be retrieved using Enet_poll() function.
    • Application calls Enet_poll() with event type ENET_EVT_TIMESTAMP_TX periodically until the register callback is called.
    • The MAC port where timestamp is being polled is specified via Enet_poll() arg parameter.
    • The returned timestamp is a value in clock cycles for CPSW peripheral and a value in nanoseconds for ICSSG peripheral.
    • The sequence id set to before sending packet for transmission in field EnetUdma_PktTsInfo::txPktSeqId will be passed to the registered callback. Application can use this value to correlate the packet it comes from.

IOCTL Sequence

  1. Some common IOCTLs have already been mentioned in this document so far. But the application can run any other IOCTL supported by the peripheral. There are two kinds of IOCTLs: synchronous and asynchronous. Asynchronous IOCTLs require an additional completion poll step which is explained in Synchronous and Asynchronous IOCTLs section of the Enet LLD IOCTL interface document.

Port Close Sequence

  1. MAC ports that were opened earlier can be closed using ENET_PER_IOCTL_CLOSE_PORT_LINK IOCTL command. This will close the PHY state machine associated with this MAC port, if the port was not open in MAC-to-MAC mode. Application can choose to reopen the port at any time in the future by following the steps listed in Port Open Sequence section.

Peripheral Close Sequence

  1. Disable the host port using the ENET_HOSTPORT_IOCTL_DISABLE command
  2. Close the opened Tx Channel and Rx flow:
    • Close the Rx flow using EnetAppUtils_closeRxFlow().
    • Close the Tx Channel using EnetAppUtils_closeTxCh().
  3. Detach the core from Resource Manager using the ENET_PER_IOCTL_DETACH_CORE command.
  4. Enet driver can now be closed and de-initialized using Enet_close() and Enet_deinit().

Deinit Sequence

This is one-time deinitialization sequence that must be followed when the application no longer wants to use the Enet LLD.

  1. Enet_deinit() should be called to deinitialize the driver. No further Enet LLD APIs should be called from this point.
  2. Finally, close the UDMA driver using EnetAppUtils_udmaclose()

Back To Top

Peripheral-specific


ICSSG Dual-MAC

The following sections discuss lower level details on how the ICSSG Dual-MAC and its buffer pool configuration parameters are passed. This is relevant for readers who are looking to replace the default Dual-MAC firmware or have packet buffer requirements not met with the default buffer pool configuration.

Firmware

Enet LLD provides default firmware for ICSSG Dual-MAC, which is available at <enet>/src/per/firmware/icssg/dualmac. This firmware is tightly coupled with a corresponding firmware initialization done internally in Enet LLD.

The firmware information is populated into the ICSSG internal objects (see Icssg_Obj::fw) by Enet LLD in the corresponding Enet SoC file, i.e. <enet>/soc/j7x/am65xx/enet_soc.c for AM65xx devices.

There are three firmware blobs that must be loaded, one per core in the ICSSG slice: PRU, RTU and TX PRU. It's done as follows:

Peripheral PRU RTU TX PRU
ICSSG0 MAC port 1
(enetType: ENET_ICSSG_DUALMAC, instId: 0)
RX_PRU_SLICE0_b00_DMac RTU0_SLICE0_b00_DMac TX_PRU_SLICE0_b00_DMac
ICSSG0 MAC port 2
(enetType: ENET_ICSSG_DUALMAC, instId: 1)
RX_PRU_SLICE1_b00_DMac RTU0_SLICE1_b00_DMac TX_PRU_SLICE1_b00_DMac
ICSSG1 MAC port 1
(enetType: ENET_ICSSG_DUALMAC, instId: 2)
RX_PRU_SLICE0_b00_DMac RTU0_SLICE0_b00_DMac TX_PRU_SLICE0_b00_DMac
ICSSG1 MAC port 2
(enetType: ENET_ICSSG_DUALMAC, instId: 3)
RX_PRU_SLICE1_b00_DMac RTU0_SLICE1_b00_DMac TX_PRU_SLICE1_b00_DMac
ICSSG2 MAC port 1
(enetType: ENET_ICSSG_DUALMAC, instId: 4)
RX_PRU_SLICE0_b00_DMac RTU0_SLICE0_b00_DMac TX_PRU_SLICE0_b00_DMac
ICSSG2 MAC port 2
(enetType: ENET_ICSSG_DUALMAC, instId: 5)
RX_PRU_SLICE1_b00_DMac RTU0_SLICE1_b00_DMac TX_PRU_SLICE1_b00_DMac

It's worth noting that from application perspective, the ICSSG firmware blobs to be loaded and the firmware configuration is completely transparent as it doesn't require any application intervention.

Firmware Memory Pools

ICSSG firmware requires internal memory for buffer pools and queues to be specified at firmware configuration time. This firmware memory is passed into the ICSSG internal objects (see Icssg_Obj::fwPoolMem) by Enet LLD in the corresponding Enet SoC file, i.e. <enet>/soc/j7x/am65xx/enet_soc.c for AM65xx devices.

There are certain memory requirements for each buffer type for Dual-MAC as shown below:

Buffer Type Number of pools per slice Size per buffer pool (bytes) Config parameters
Port buffer pools 0 0 Icssg_FwPoolMem::portBufferPoolMem
Icssg_FwPoolMem::portBufferPoolSize
Icssg_FwPoolMem::portBufferPoolNum
Host buffer pools ICSSG_DUALMAC_HOST_BUFFER_POOL_NUM Configurable Icssg_FwPoolMem::hostBufferPoolMem
Icssg_FwPoolMem::hostBufferPoolSize
Icssg_FwPoolMem::hostBufferPoolNum
Host egress queues ICSSG_DUALMAC_HOST_EGRESS_QUEUE_NUM Configurable. It must include fixed padding size
of ICSSG_HOST_EGRESS_BUFFER_PADDING
Icssg_FwPoolMem::hostEgressQueueMem
Icssg_FwPoolMem::hostEgressQueueSize
Icssg_FwPoolMem::hostEgressQueueNum
Scratch buffer 1 ICSSG_SCRATCH_BUFFER_SIZE Icssg_FwPoolMem::scratchBufferMem
Icssg_FwPoolMem::scratchBufferSize

Enet LLD provides a default firmware memory configuration in order to reduce the configuration burden on applications. The selection of firmware buffer sizes is a trade-off between the desired amount of packet buffering, the available memory and ICSSG MAC concurrency.

The buffer sizes provided by default in Enet LLD enable simultaneous use of all ICSSGs MACs in the SoC. The table below shows the default buffer sizes per ICSSG MAC.

Buffer Type Number of pools Buffer pool size Slices Total size
Port buffer pools 0 0 1 0
Host buffer pools 8 8 kB 1 64 kB
Host egress queues 2 8 kB 1 16 kB
Scratch buffer 1 2 kB 1 2 kB

If these firmware memory sizes don't meet the requirements of the application, they must be changed in the corresponding Enet SoC file, i.e. <enet>/soc/j7x/am65xx/enet_soc.c for AM65xx devices.

ICSSG Switch

The following sections discuss lower level details on how the ICSSG Switch and its buffer pool configuration parameters are passed. This is relevant for readers who are looking to replace the default Switch firmware or have packet buffer requirements not met with the default buffer pool configuration.

Firmware

Enet LLD provides default firmware for ICSSG Switch which is available at <enet>/src/per/firmware/icssg/switch. This firmware is tightly coupled with a corresponding firmware initialization done internally in Enet LLD.

The firmware information is populated into the ICSSG internal objects (see Icssg_Obj::fw) by Enet LLD in the corresponding Enet SoC file, i.e. <enet>/soc/j7x/am65xx/enet_soc.c for AM65xx devices.

There are six firmware blobs that must be supplied by the application, one for each core of the two ICSSG slices: PRU, RTU and TX PRU.

Peripheral PRU RTU TX PRU
ICSSG0
(enetType: ENET_ICSSG_SWITCH, instId: 0)
RX_PRU_SLICE0_b00_Swt
RX_PRU_SLICE1_b00_Swt
RTU0_SLICE0_b00_Swt
RTU0_SLICE1_b00_Swt
TX_PRU_SLICE0_b00_Swt
TX_PRU_SLICE1_b00_Swt
ICSSG1
(enetType: ENET_ICSSG_SWITCH, instId: 1)
RX_PRU_SLICE0_b00_Swt
RX_PRU_SLICE1_b00_Swt
RTU0_SLICE0_b00_Swt
RTU0_SLICE1_b00_Swt
TX_PRU_SLICE0_b00_Swt
TX_PRU_SLICE1_b00_Swt
ICSSG2
(enetType: ENET_ICSSG_SWITCH, instId: 2)
RX_PRU_SLICE0_b00_Swt
RX_PRU_SLICE1_b00_Swt
RTU0_SLICE0_b00_Swt
RTU0_SLICE1_b00_Swt
TX_PRU_SLICE0_b00_Swt
TX_PRU_SLICE1_b00_Swt

Firmware Memory Pools

ICSSG firmware requires internal memory for buffer pools and queues to be specified at firmware configuration time. This firmware memory is passed into the ICSSG internal objects (see Icssg_Obj::fwPoolMem) by Enet LLD in the corresponding Enet SoC file, i.e. <enet>/soc/j7x/am65xx/enet_soc.c for AM65xx devices.

There are certain memory requirements for each buffer type for Switch as shown below:

Buffer Type Number of pools per slice Size per buffer pool (bytes) Config parameters
Port buffer pools ICSSG_SWITCH_PORT_BUFFER_POOL_NUM Configurable Icssg_FwPoolMem::portBufferPoolMem
Icssg_FwPoolMem::portBufferPoolSize
Icssg_FwPoolMem::portBufferPoolNum
Host buffer pools ICSSG_SWITCH_HOST_BUFFER_POOL_NUM Configurable Icssg_FwPoolMem::hostBufferPoolMem
Icssg_FwPoolMem::hostBufferPoolSize
Icssg_FwPoolMem::hostBufferPoolNum
Host egress queues ICSSG_SWITCH_HOST_EGRESS_QUEUE_NUM Configurable. It must include fixed padding size
of ICSSG_HOST_EGRESS_BUFFER_PADDING
Icssg_FwPoolMem::hostEgressQueueMem
Icssg_FwPoolMem::hostEgressQueueSize
Icssg_FwPoolMem::hostEgressQueueNum
Scratch buffer 1 ICSSG_SCRATCH_BUFFER_SIZE Icssg_FwPoolMem::scratchBufferMem
Icssg_FwPoolMem::scratchBufferSize

Enet LLD provides a default firmware memory configuration in order to reduce the configuration burden on applications. The selection of firmware buffer sizes is a trade-off between the desired amount of packet buffering, the available memory and ICSSG Switch concurrency.

The buffer sizes provided by default in Enet LLD enable simultaneous use of all ICSSGs Switches in the SoC. The table below shows the default buffer sizes per ICSSG MAC.

Buffer Type Number of pools Buffer pool size Slices Total size
Port buffer pools 8 6 kB 2 96 kB
Host buffer pools 16 6 kB 2 192 kB
Host egress queues 2 8 kB 2 32 kB
Scratch buffer 1 2 kB 2 4 kB

If these firmware memory sizes don't meet the requirements of the application, they must be changed in the corresponding Enet SoC file, i.e. <enet>/soc/j7x/am65xx/enet_soc.c for AM65xx devices.

Migrating from EMAC LLD


ICSSG Migration

Peripheral open

EMAC LLD and Enet LLD differ in the kind of parameters passed at open time. EMAC LLD's emac_open() takes a port number, and Enet LLD's Enet_open() takes a peripheral type and instance id.

Dual-MAC is implemented as separate Enet peripherals of the same type (ENET_ICSSG_DUALMAC). Instance number goes from 0 to 5 for AM65xx device as there are a total of 3 ICSSG instances, each having 2 MAC ports.

The following tables show the equivalent parameters to use in Enet_open() for ICSSG Dual-MAC.

EMAC LLD
Port Number
Enet LLD
Peripheral
EMAC_ICSSG0_PORT0 enetType: ENET_ICSSG_DUALMAC instId: 0
EMAC_ICSSG0_PORT1 enetType: ENET_ICSSG_DUALMAC instId: 1
EMAC_ICSSG1_PORT0 enetType: ENET_ICSSG_DUALMAC instId: 2
EMAC_ICSSG1_PORT1 enetType: ENET_ICSSG_DUALMAC instId: 3
EMAC_ICSSG2_PORT0 enetType: ENET_ICSSG_DUALMAC instId: 4
EMAC_ICSSG2_PORT1 enetType: ENET_ICSSG_DUALMAC instId: 5

ICSSG Switch is implemented as separate Enet peripherals of the same type (ENET_ICSSG_SWITCH). Instance number goes from 0 to 3 for AM65xx device as there are a total of 3 ICSSG instances.

The following tables show the equivalent parameters to use in Enet_open() for ICSSG Switch.

EMAC LLD
Port Number
Enet LLD
Peripheral
EMAC_SWITCH_PORT enetType: ENET_ICSSG_SWITCH instId: 0
EMAC_ICSSG0_SWITCH_PORT enetType: ENET_ICSSG_SWITCH instId: 0
EMAC_ICSSG1_SWITCH_PORT enetType: ENET_ICSSG_SWITCH instId: 1
EMAC_ICSSG2_SWITCH_PORT enetType: ENET_ICSSG_SWITCH instId: 2

Enet LLD Enet_open() returns a handle of Enet_Handle type, this handle is used in all other Enet LLD APIs. This is an important difference with respect to EMAC LLD, as port number is still required in other EMAC LLD APIs, i.e. emac_ioctl.

IOCTLs

EMAC LLD's emac_ioctl() uses a port number as a means to indicate whether the command is to be run on a Dual-MAC or a Switch, and also to convey information about whether the command is MAC port or host port related:

  • Dual-MAC - It's the same port number used at open time in emac_open(). There is no additional port number for host port IOCTL commands.
  • Switch - There are 4 port numbers per instance:
    • EMAC_ICSSGn_SWITCH_PORT used for global settings.
    • EMAC_ICSSGn_SWITCH_PORT0 used for host port related IOCTLs.
    • EMAC_ICSSGn_SWITCH_PORT1 used for MAC port 1 related IOCTLs.
    • EMAC_ICSSGn_SWITCH_PORT2 used for MAC port 2 related IOCTLs.

Note that in the Switch case, the last three port numbers are not used at open time.

In Enet LLD, Enet_ioctl() doesn't take the port number in all cases, but only for MAC port related IOCTL commands.

IOCTLs that are MAC port related will take the MAC port number (Enet_MacPort) as IOCTL input args. For example, ENET_MACPORT_IOCTL_SET_PRI_REGEN_MAP command is MAC port related and it takes the MAC port number in its input arguments EnetMacPort_SetPriorityRegenMapInArgs::macPort.

IOCTLs that are host port related will not take a port number. For example, ICSSG_PER_IOCTL_VLAN_SET_HOSTPORT_DFLT_VID.

Asynchronous IOCTLs

In EMAC LLD, asynchronous IOCTLs return EMAC_DRV_RESULT_IOCTL_IN_PROGRESS in emac_ioctl() call which is used to indicate that the application must poll for the operation completion. Polling is done via emac_poll_ctrl() function.

Enet LLD implements asynchronous IOCTLs using a similar mechanism. First, the application must register an IOCTL completion callback funcion via Enet_registerEventCb(). When application has called an asynchronous IOCTL, Enet LLD will return ENET_SINPROGRESS and the application must call Enet_poll() with event type ENET_EVT_ASYNC_CMD_RESP until the registered callback is called.

Refer to section Synchronous and Asynchronous IOCTLs of the Enet LLD IOCTL interface document for further details.

IOCTL Command Mappings

The following table shows the mapping between EMAC LLD IOCTL commands/subcommands and Enet LLD IOCTLs.

EMAC LLD
IOCTL cmd
EMAC LLD
IOCTL subcmd
Enet LLD
IOCTL cmd
EMAC_IOCTL_PROMISCOUS_MODE_CTRL ICSSG_MACPORT_IOCTL_ENABLE_PROMISC_MODE
ICSSG_MACPORT_IOCTL_DISABLE_PROMISC_MODE
EMAC_IOCTL_UC_FLOODING_CTRL EMAC_IOCTL_PORT_UC_FLOODING_ENABLE ICSSG_MACPORT_IOCTL_ENABLE_UCAST_FLOOD
EMAC_IOCTL_PORT_UC_FLOODING_DISABLE ICSSG_MACPORT_IOCTL_DISABLE_UCAST_FLOOD
EMAC_IOCTL_MC_FLOODING_CTRL EMAC_IOCTL_PORT_MC_FLOODING_ENABLE ICSSG_MACPORT_IOCTL_ENABLE_MCAST_FLOOD
EMAC_IOCTL_PORT_MC_FLOODING_DISABLE ICSSG_MACPORT_IOCTL_DISABLE_MCAST_FLOOD
EMAC_IOCTL_PORT_STATE_CTRL EMAC_IOCTL_PORT_STATE_DISABLE ICSSG_PER_IOCTL_SET_PORT_STATE
EMAC_IOCTL_PORT_STATE_BLOCKING ICSSG_PER_IOCTL_SET_PORT_STATE
EMAC_IOCTL_PORT_STATE_FORWARD ICSSG_PER_IOCTL_SET_PORT_STATE
EMAC_IOCTL_PORT_STATE_FORWARD_WO_LEARNING ICSSG_PER_IOCTL_SET_PORT_STATE
EMAC_IOCTL_ACCEPTABLE_FRAME_CHECK_CTRL EMAC_IOCTL_ACCEPTABLE_FRAME_CHECK_ONLY_VLAN_TAGGED ICSSG_MACPORT_IOCTL_SET_ACCEPT_FRAME_CHECK
EMAC_IOCTL_ACCEPTABLE_FRAME_CHECK_ONLY_UN_TAGGED_PRIO_TAGGED ICSSG_MACPORT_IOCTL_SET_ACCEPT_FRAME_CHECK
EMAC_IOCTL_ACCEPTABLE_FRAME_CHECK_ALL_FRAMES ICSSG_MACPORT_IOCTL_SET_ACCEPT_FRAME_CHECK
EMAC_IOCTL_VLAN_CTRL EMAC_IOCTL_VLAN_SET_DEFAULT_TBL ICSSG_PER_IOCTL_VLAN_RESET_TABLE
EMAC_IOCTL_VLAN_SET_ENTRY ICSSG_PER_IOCTL_VLAN_SET_ENTRY
EMAC_IOCTL_VLAN_SET_DEFAULT_VLAN_ID ICSSG_PER_IOCTL_VLAN_SET_HOSTPORT_DFLT_VID
ICSSG_PER_IOCTL_VLAN_SET_MACPORT_DFLT_VID
EMAC_IOCTL_VLAN_GET_ENTRY ICSSG_PER_IOCTL_VLAN_GET_ENTRY
EMAC_IOCTL_PORT_PRIO_MAPPING_CTRL ENET_MACPORT_IOCTL_SET_EGRESS_QOS_PRI_MAP
EMAC_IOCTL_PRIO_REGEN_CTRL ENET_MACPORT_IOCTL_SET_PRI_REGEN_MAP
EMAC_IOCTL_SPECIAL_FRAME_PRIO_CONFIG IcssgMacPort_Cfg::specialFramePrio
EMAC_IOCTL_FDB_AGEING_TIMEOUT_CTRL ICSSG_FDB_IOCTL_SET_AGING_PERIOD
EMAC_IOCTL_FDB_ENTRY_CTRL EMAC_IOCTL_FDB_ENTRY_ADD ICSSG_FDB_IOCTL_ADD_ENTRY
EMAC_IOCTL_FDB_ENTRY_DELETE ICSSG_FDB_IOCTL_REMOVE_ENTRY
EMAC_IOCTL_FDB_ENTRY_DELETE_ALL ICSSG_FDB_IOCTL_REMOVE_ALL_ENTRIES
EMAC_IOCTL_FDB_ENTRY_DELETE_ALL_AGEABLE ICSSG_FDB_IOCTL_REMOVE_AGEABLE_ENTRIES
EMAC_IOCTL_INTERFACE_MAC_CONFIG EMAC_IOCTL_INTERFACE_MAC_ADD ICSSG_HOSTPORT_IOCTL_SET_MACADDR
ICSSG_MACPORT_IOCTL_SET_MACADDR
EMAC_IOCTL_INGRESS_RATE_LIMIT_CTRL ICSSG_MACPORT_IOCTL_SET_INGRESS_RATE_LIM
EMAC_IOCTL_FRAME_PREEMPTION_CTRL EMAC_IOCTL_PREEMPT_TX_ENABLE ICSSG_MACPORT_IOCTL_PREEMPT_TX_ENABLE
EMAC_IOCTL_PREEMPT_TX_DISABLE ICSSG_MACPORT_IOCTL_PREEMPT_TX_DISABLE
EMAC_IOCTL_PREEMPT_GET_TX_ENABLE_STATUS ICSSG_MACPORT_IOCTL_PREEMPT_GET_TX_ENABLE_STATUS
EMAC_IOCTL_PREEMPT_GET_TX_ACTIVE_STATUS ICSSG_MACPORT_IOCTL_PREEMPT_GET_TX_ACTIVE_STATUS
EMAC_IOCTL_PREEMPT_VERIFY_ENABLE ICSSG_MACPORT_IOCTL_PREEMPT_VERIFY_ENABLE
EMAC_IOCTL_PREEMPT_VERIFY_DISABLE ICSSG_MACPORT_IOCTL_PREEMPT_VERIFY_DISABLE
EMAC_IOCTL_PREEMPT_GET_VERIFY_STATE ICSSG_MACPORT_IOCTL_PREEMPT_GET_VERIFY_STATE
EMAC_IOCTL_PREEMPT_GET_MIN_FRAG_SIZE_LOCAL ICSSG_MACPORT_IOCTL_PREEMPT_GET_MIN_FRAG_SIZE_LOCAL
EMAC_IOCTL_PREEMPT_SET_MIN_FRAG_SIZE_REMOTE ICSSG_MACPORT_IOCTL_PREEMPT_SET_MIN_FRAG_SIZE_REMOTE
EMAC_IOCTL_CUT_THROUGH_PREEMPT_SELECT IcssgMacPort_Cfg::queuePreemptMode
IcssgMacPort_Cfg::queueForwardMode
EMAC_IOCTL_SPEED_DUPLEXITY_CTRL EMAC_IOCTL_SPEED_DUPLEXITY_10HD No longer available as explicit IOCTLs.
Speed and duplexity are passed as arguments to ENET_PER_IOCTL_OPEN_PORT_LINK in either auto-negotiation or manual modes.
EMAC_IOCTL_SPEED_DUPLEXITY_10FD
EMAC_IOCTL_SPEED_DUPLEXITY_100HD
EMAC_IOCTL_SPEED_DUPLEXITY_100FD
EMAC_IOCTL_SPEED_DUPLEXITY_GIGABIT
EMAC_IOCTL_SPEED_DUPLEXITY_DISABLE

Packet send and receive

EMAC LLD relies on emac_send() and emac_poll_pkt() for packet transmission and reception, respectively.

  • For transmission, application populates a descriptor with packet information and passes it to emac_send(). The descriptor provides fields for packet buffer, packet length, traffic class, etc.
  • For reception, application registers a callback (rx_pkt_cb) at open time, which will be called by the driver when application calls emac_poll_pkt() and packets have been received.

Internally, EMAC LLD would open all required TX channels and RX flows.

Enet LLD takes a different approach, provides a queue oriented mechanism for packet submission and retrieval.

Enet LLD API Description
EnetDma_retrieveRxPktQ() Called by application to retrieve ready packets from the driver, that is, new full packets.
EnetDma_submitRxPktQ() Callen by application to return free packets that the application has consumed and is ready to recycle.
EnetDma_submitTxPktQ() Called by application to submit ready packets to the driver for transmission.
EnetDma_retrieveTxPktQ() Called by application to retrieve done packets which the driver has already used for transmission and are ready to be reused for future transmission.

The queues passed to above APIs are created by the application using EnetQueue APIs, such as EnetQueue_initQ(), EnetQueue_enq() and EnetQueue_deq().

The queues are composed of EnetDma_Pkt objects, which is the abstraction provided by Enet LLD for a packet. The native type of the packet object in AM65xx/J721E devices is EnetUdma_PktInfo. Note that this same packet object type is used for transmission and reception.

Back To Top