| /* SPDX-License-Identifier: GPL-2.0 */ | |
| /* | |
| * NetCP driver local header | |
| * | |
| * Copyright (C) 2014 Texas Instruments Incorporated | |
| * Authors: Sandeep Nair <sandeep_n@ti.com> | |
| * Sandeep Paulraj <s-paulraj@ti.com> | |
| * Cyril Chemparathy <cyril@ti.com> | |
| * Santosh Shilimkar <santosh.shilimkar@ti.com> | |
| * Wingman Kwok <w-kwok2@ti.com> | |
| * Murali Karicheri <m-karicheri2@ti.com> | |
| */ | |
| #ifndef __NETCP_H__ | |
| #define __NETCP_H__ | |
| #include <linux/netdevice.h> | |
| #include <linux/soc/ti/knav_dma.h> | |
| #include <linux/u64_stats_sync.h> | |
| /* Maximum Ethernet frame size supported by Keystone switch */ | |
| #define NETCP_MAX_FRAME_SIZE 9504 | |
| #define SGMII_LINK_MAC_MAC_AUTONEG 0 | |
| #define SGMII_LINK_MAC_PHY 1 | |
| #define SGMII_LINK_MAC_MAC_FORCED 2 | |
| #define SGMII_LINK_MAC_FIBER 3 | |
| #define SGMII_LINK_MAC_PHY_NO_MDIO 4 | |
| #define RGMII_LINK_MAC_PHY 5 | |
| #define RGMII_LINK_MAC_PHY_NO_MDIO 7 | |
| #define XGMII_LINK_MAC_PHY 10 | |
| #define XGMII_LINK_MAC_MAC_FORCED 11 | |
| struct netcp_device; | |
| struct netcp_tx_pipe { | |
| struct netcp_device *netcp_device; | |
| void *dma_queue; | |
| unsigned int dma_queue_id; | |
| /* To port for packet forwarded to switch. Used only by ethss */ | |
| u8 switch_to_port; | |
| #define SWITCH_TO_PORT_IN_TAGINFO BIT(0) | |
| u8 flags; | |
| void *dma_channel; | |
| const char *dma_chan_name; | |
| }; | |
| #define ADDR_NEW BIT(0) | |
| #define ADDR_VALID BIT(1) | |
| enum netcp_addr_type { | |
| ADDR_ANY, | |
| ADDR_DEV, | |
| ADDR_UCAST, | |
| ADDR_MCAST, | |
| ADDR_BCAST | |
| }; | |
| struct netcp_addr { | |
| struct netcp_intf *netcp; | |
| unsigned char addr[ETH_ALEN]; | |
| enum netcp_addr_type type; | |
| unsigned int flags; | |
| struct list_head node; | |
| }; | |
| struct netcp_stats { | |
| struct u64_stats_sync syncp_rx ____cacheline_aligned_in_smp; | |
| u64_stats_t rx_packets; | |
| u64_stats_t rx_bytes; | |
| u32 rx_errors; | |
| u32 rx_dropped; | |
| struct u64_stats_sync syncp_tx ____cacheline_aligned_in_smp; | |
| u64_stats_t tx_packets; | |
| u64_stats_t tx_bytes; | |
| u32 tx_errors; | |
| u32 tx_dropped; | |
| }; | |
| struct netcp_intf { | |
| struct device *dev; | |
| struct device *ndev_dev; | |
| struct net_device *ndev; | |
| bool big_endian; | |
| unsigned int tx_compl_qid; | |
| void *tx_pool; | |
| struct list_head txhook_list_head; | |
| unsigned int tx_pause_threshold; | |
| void *tx_compl_q; | |
| unsigned int tx_resume_threshold; | |
| void *rx_queue; | |
| void *rx_pool; | |
| struct list_head rxhook_list_head; | |
| unsigned int rx_queue_id; | |
| void *rx_fdq[KNAV_DMA_FDQ_PER_CHAN]; | |
| struct napi_struct rx_napi; | |
| struct napi_struct tx_napi; | |
| #define ETH_SW_CAN_REMOVE_ETH_FCS BIT(0) | |
| u32 hw_cap; | |
| /* 64-bit netcp stats */ | |
| struct netcp_stats stats; | |
| void *rx_channel; | |
| const char *dma_chan_name; | |
| u32 rx_pool_size; | |
| u32 rx_pool_region_id; | |
| u32 tx_pool_size; | |
| u32 tx_pool_region_id; | |
| struct list_head module_head; | |
| struct list_head interface_list; | |
| struct list_head addr_list; | |
| bool netdev_registered; | |
| bool primary_module_attached; | |
| /* Lock used for protecting Rx/Tx hook list management */ | |
| spinlock_t lock; | |
| struct netcp_device *netcp_device; | |
| struct device_node *node_interface; | |
| /* DMA configuration data */ | |
| u32 msg_enable; | |
| u32 rx_queue_depths[KNAV_DMA_FDQ_PER_CHAN]; | |
| }; | |
| #define NETCP_PSDATA_LEN KNAV_DMA_NUM_PS_WORDS | |
| struct netcp_packet { | |
| struct sk_buff *skb; | |
| __le32 *epib; | |
| u32 *psdata; | |
| u32 eflags; | |
| unsigned int psdata_len; | |
| struct netcp_intf *netcp; | |
| struct netcp_tx_pipe *tx_pipe; | |
| bool rxtstamp_complete; | |
| void *ts_context; | |
| void (*txtstamp)(void *ctx, struct sk_buff *skb); | |
| }; | |
| static inline u32 *netcp_push_psdata(struct netcp_packet *p_info, | |
| unsigned int bytes) | |
| { | |
| u32 *buf; | |
| unsigned int words; | |
| if ((bytes & 0x03) != 0) | |
| return NULL; | |
| words = bytes >> 2; | |
| if ((p_info->psdata_len + words) > NETCP_PSDATA_LEN) | |
| return NULL; | |
| p_info->psdata_len += words; | |
| buf = &p_info->psdata[NETCP_PSDATA_LEN - p_info->psdata_len]; | |
| return buf; | |
| } | |
| static inline int netcp_align_psdata(struct netcp_packet *p_info, | |
| unsigned int byte_align) | |
| { | |
| int padding; | |
| switch (byte_align) { | |
| case 0: | |
| padding = -EINVAL; | |
| break; | |
| case 1: | |
| case 2: | |
| case 4: | |
| padding = 0; | |
| break; | |
| case 8: | |
| padding = (p_info->psdata_len << 2) % 8; | |
| break; | |
| case 16: | |
| padding = (p_info->psdata_len << 2) % 16; | |
| break; | |
| default: | |
| padding = (p_info->psdata_len << 2) % byte_align; | |
| break; | |
| } | |
| return padding; | |
| } | |
| struct netcp_module { | |
| const char *name; | |
| struct module *owner; | |
| bool primary; | |
| /* probe/remove: called once per NETCP instance */ | |
| int (*probe)(struct netcp_device *netcp_device, | |
| struct device *device, struct device_node *node, | |
| void **inst_priv); | |
| int (*remove)(struct netcp_device *netcp_device, void *inst_priv); | |
| /* attach/release: called once per network interface */ | |
| int (*attach)(void *inst_priv, struct net_device *ndev, | |
| struct device_node *node, void **intf_priv); | |
| int (*release)(void *intf_priv); | |
| int (*open)(void *intf_priv, struct net_device *ndev); | |
| int (*close)(void *intf_priv, struct net_device *ndev); | |
| int (*add_addr)(void *intf_priv, struct netcp_addr *naddr); | |
| int (*del_addr)(void *intf_priv, struct netcp_addr *naddr); | |
| int (*add_vid)(void *intf_priv, int vid); | |
| int (*del_vid)(void *intf_priv, int vid); | |
| int (*ioctl)(void *intf_priv, struct ifreq *req, int cmd); | |
| int (*set_rx_mode)(void *intf_priv, bool promisc); | |
| int (*hwtstamp_get)(void *intf_priv, | |
| struct kernel_hwtstamp_config *cfg); | |
| int (*hwtstamp_set)(void *intf_priv, | |
| struct kernel_hwtstamp_config *cfg, | |
| struct netlink_ext_ack *extack); | |
| /* used internally */ | |
| struct list_head module_list; | |
| struct list_head interface_list; | |
| }; | |
| int netcp_register_module(struct netcp_module *module); | |
| void netcp_unregister_module(struct netcp_module *module); | |
| void *netcp_module_get_intf_data(struct netcp_module *module, | |
| struct netcp_intf *intf); | |
| int netcp_txpipe_init(struct netcp_tx_pipe *tx_pipe, | |
| struct netcp_device *netcp_device, | |
| const char *dma_chan_name, unsigned int dma_queue_id); | |
| int netcp_txpipe_open(struct netcp_tx_pipe *tx_pipe); | |
| int netcp_txpipe_close(struct netcp_tx_pipe *tx_pipe); | |
| typedef int netcp_hook_rtn(int order, void *data, struct netcp_packet *packet); | |
| int netcp_register_txhook(struct netcp_intf *netcp_priv, int order, | |
| netcp_hook_rtn *hook_rtn, void *hook_data); | |
| int netcp_unregister_txhook(struct netcp_intf *netcp_priv, int order, | |
| netcp_hook_rtn *hook_rtn, void *hook_data); | |
| int netcp_register_rxhook(struct netcp_intf *netcp_priv, int order, | |
| netcp_hook_rtn *hook_rtn, void *hook_data); | |
| int netcp_unregister_rxhook(struct netcp_intf *netcp_priv, int order, | |
| netcp_hook_rtn *hook_rtn, void *hook_data); | |
| /* SGMII functions */ | |
| int netcp_sgmii_reset(void __iomem *sgmii_ofs, int port); | |
| bool netcp_sgmii_rtreset(void __iomem *sgmii_ofs, int port, bool set); | |
| int netcp_sgmii_get_port_link(void __iomem *sgmii_ofs, int port); | |
| int netcp_sgmii_config(void __iomem *sgmii_ofs, int port, u32 interface); | |
| /* XGBE SERDES init functions */ | |
| int netcp_xgbe_serdes_init(void __iomem *serdes_regs, void __iomem *xgbe_regs); | |
| #endif /* __NETCP_H__ */ |