Forum | Documentation | Website | Blog

Skip to content
Snippets Groups Projects
Commit a9b8608a authored by Murali Karicheri's avatar Murali Karicheri
Browse files

net: ti: prueth_core: add HSR/PRP driver


HSR/PRP is a industrial Ethernet protocol defined by IEC 62439
standard. Both use 6 bytes of protocol bytes to implement redundancy.
This consists of 2 bytes of sequence number, 1 byte of Ethernet
type identifying the protocol and LSDU length and pathid/network id
bits. Link Redundancy Entity (LRE) implements 1) duplication of Ethernet
frames at Egress and 2) discard of duplicates at the ingress and 3)
processing of Supervision frames to build the Node Table information.
Node table contains the health status of remote nodes in the network.

HSR/PRP driver offload part of LRE function. In the current version of
the firmware 2 & 3 are offloaded to PRU firmware. 1) is still performed
by upper HSR/PRP driver under net/hsr. This patch initialize the firmware
based on the Ethernet type. HSR/PRP firmware uses same memory map as
Switch firmware. So all places in the driver that initializes the basic
Switch firmware is re-used for HSR/PRP as well using the
!PRUETH_IS_EMAC() macro. Any HSR/PRP specific function is initialized
under PRUETH_IS_LRE() macro.

This update support both v1.0 and v2.1 of the ICSS firmware by using fw
offsets that are assigned at probe based on platform. A list of firmware
names are also picked at probe and then based on ethtype appropriate
firmware is picked to load on the PRUs. For Packet handling, NAPI is used
at at Ingress. There are two pair of Queues at the Ingress for each port.
Low priority and High priority. A NAPI instance is added for each of the
priority queue. An interrupt is raised by firmware when packets are
en-queued to one of the priority queue. red_emac_rx_packets() ensures that
packets are scanned from both queues at a specific priority and sends
them to network stack based on timestamp associated with the packet. At
the egress, packets are en-queued based on pcp bits. There are 2 queues
per port and other queues are for port to port traffic.

Signed-off-by: default avatarMurali Karicheri <m-karicheri2@ti.com>
parent 685b6369
Branches
Tags
No related merge requests found
......@@ -83,6 +83,7 @@
/* HOST_TIMER_CHECK_FLAGS bits */
#define ICSS_LRE_HOST_TIMER_NODE_TABLE_CHECK_BIT BIT(0)
#define ICSS_LRE_HOST_TIMER_NODE_TABLE_CLEAR_BIT BIT(4)
#define ICSS_LRE_HOST_TIMER_HOST_TABLE_CHECK_BIT BIT(8)
#define ICSS_LRE_HOST_TIMER_P1_TABLE_CHECK_BIT BIT(16)
#define ICSS_LRE_HOST_TIMER_P2_TABLE_CHECK_BIT BIT(24)
......@@ -91,5 +92,32 @@
ICSS_LRE_HOST_TIMER_P2_TABLE_CHECK_BIT)
#define ICSS_LRE_NODE_FREE 0x10
/* PRU1 DMEM */
/* Node table offsets are different for AM3/4 vs AM57/K2G, set by firmware */
#define ICSS_LRE_V1_0_HASH_MASK 0x3F
#define ICSS_LRE_V1_0_INDEX_ARRAY_NT 0x10
#define ICSS_LRE_V1_0_BIN_ARRAY 0x1A00
#define ICSS_LRE_V1_0_NODE_TABLE_NEW 0x1FC0
#define ICSS_LRE_V1_0_INDEX_ARRAY_LOC PRUETH_MEM_DRAM0
#define ICSS_LRE_V1_0_BIN_ARRAY_LOC PRUETH_MEM_DRAM0
#define ICSS_LRE_V1_0_NODE_TABLE_LOC PRUETH_MEM_SHARED_RAM
#define ICSS_LRE_V1_0_INDEX_TBL_MAX_ENTRIES 64
#define ICSS_LRE_V1_0_BIN_TBL_MAX_ENTRIES 128
#define ICSS_LRE_V1_0_NODE_TBL_MAX_ENTRIES 128
#define ICSS_LRE_V2_1_HASH_MASK 0xFF
#define ICSS_LRE_V2_1_INDEX_ARRAY_NT 0x3000
#define ICSS_LRE_V2_1_BIN_ARRAY \
(ICSS_LRE_V2_1_INDEX_ARRAY_NT + \
(ICSS_LRE_V2_1_INDEX_TBL_MAX_ENTRIES * 6))
#define ICSS_LRE_V2_1_NODE_TABLE_NEW \
(ICSS_LRE_V2_1_BIN_ARRAY + \
(ICSS_LRE_V2_1_BIN_TBL_MAX_ENTRIES * 8))
#define ICSS_LRE_V2_1_INDEX_ARRAY_LOC PRUETH_MEM_SHARED_RAM
#define ICSS_LRE_V2_1_BIN_ARRAY_LOC PRUETH_MEM_SHARED_RAM
#define ICSS_LRE_V2_1_NODE_TABLE_LOC PRUETH_MEM_SHARED_RAM
#define ICSS_LRE_V2_1_INDEX_TBL_MAX_ENTRIES 256
#define ICSS_LRE_V2_1_BIN_TBL_MAX_ENTRIES 256
#define ICSS_LRE_V2_1_NODE_TBL_MAX_ENTRIES 256
#endif /* __ICSS_LRE_FIRMWARE_H */
......@@ -77,4 +77,13 @@
#define ICSS_EMAC_FW_VLAN_FILTER_ADD_VLAN_VID_CMD 0x00
#define ICSS_EMAC_FW_VLAN_FILTER_REMOVE_VLAN_VID_CMD 0x01
/* Switch defines for VLAN/MC filtering */
/* SRAM
* VLAN filter defines & offsets
*/
#define ICSS_LRE_FW_VLAN_FLTR_CTRL_BYTE 0x1FE
/* one bit field | 0 : VLAN filter disabled
* | 1 : VLAN filter enabled
*/
#endif /* ICSS_MULTICAST_FILTER_MM_H */
......@@ -10,6 +10,7 @@
#include <linux/types.h>
#include <linux/pruss.h>
#include <linux/types.h>
#include <net/lredev.h>
#include "icss_switch.h"
......@@ -282,6 +283,8 @@ struct prueth_fw_offsets {
u32 index_array_max_entries;
u32 bin_array_max_entries;
u32 nt_array_max_entries;
u32 vlan_ctrl_byte;
u32 vlan_filter_tbl;
/* IEP wrap is used in the rx packet ordering logic and
* is different for ICSSM v1.0 vs 2.1
*/
......@@ -301,7 +304,11 @@ struct prueth_firmware {
* @fw_names: firmware names to be used for PRUSS ethernet usecases
*/
struct prueth_private_data {
struct prueth_firmware fw_pru[PRUSS_NUM_PRUS];
const struct prueth_firmware fw_pru[PRUSS_NUM_PRUS];
/* TODO: need to get this from firmware */
bool rev_2_1;
bool support_lre;
bool support_switch;
};
struct nsp_counter {
......@@ -401,6 +408,7 @@ struct prueth {
struct prueth_fw_offsets *fw_offsets;
/* HSR-PRP */
bool support_lre;
struct prueth_ndev_priority *hp, *lp;
/* NAPI for lp and hp queue scans */
struct napi_struct napi_lpq;
......@@ -411,9 +419,11 @@ struct prueth {
unsigned int tbl_check_mask;
enum iec62439_3_tr_modes prp_tr_mode;
struct node_tbl *nt;
struct device_node *eth_node[PRUETH_NUM_MACS];
struct prueth_emac *emac[PRUETH_NUM_MACS];
struct net_device *registered_netdevs[PRUETH_NUM_MACS];
struct device_node *prueth_np;
struct net_device *hw_bridge_dev;
struct fdb_tbl *fdb_tbl;
......
This diff is collapsed.
......@@ -994,9 +994,9 @@ int prueth_sw_boot_prus(struct prueth *prueth, struct net_device *ndev)
return 0;
pru_firmwares = &prueth->fw_data->fw_pru[PRUSS_PRU0];
fw_name = pru_firmwares->fw_name[PRUSS_ETHTYPE_SWITCH];
fw_name = pru_firmwares->fw_name[prueth->eth_type];
pru_firmwares = &prueth->fw_data->fw_pru[PRUSS_PRU1];
fw_name1 = pru_firmwares->fw_name[PRUSS_ETHTYPE_SWITCH];
fw_name1 = pru_firmwares->fw_name[prueth->eth_type];
ret = rproc_set_firmware(prueth->pru0, fw_name);
if (ret) {
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment