| /* |
| * 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; |
| u8 dma_psflags; |
| 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__ */ |