root/drivers/net/ethernet/ti/netcp.h
/* 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__ */