/* * 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> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation version 2. * * This program is distributed "as is" WITHOUT ANY WARRANTY of any * kind, whether express or implied; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #ifndef __NETCP_H__ #define __NETCP_H__ #include <linux/netdevice.h> #include <linux/soc/ti/knav_dma.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 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_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]; u32 rx_buffer_sizes[KNAV_DMA_FDQ_PER_CHAN]; struct napi_struct rx_napi; struct napi_struct tx_napi; 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; u32 *epib; u32 *psdata; unsigned int psdata_len; struct netcp_intf *netcp; struct netcp_tx_pipe *tx_pipe; bool rxtstamp_complete; void *ts_context; int (*txtstamp_complete)(void *ctx, struct netcp_packet *pkt); }; 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); /* 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); void *netcp_device_find_module(struct netcp_device *netcp_device, const char *name); /* SGMII functions */ int netcp_sgmii_reset(void __iomem *sgmii_ofs, int port); 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__ */