root/drivers/net/ethernet/tehuti/tn40.h
/* SPDX-License-Identifier: GPL-2.0+ */
/* Copyright (c) Tehuti Networks Ltd. */

#ifndef _TN40_H_
#define _TN40_H_

#include <linux/property.h>
#include "tn40_regs.h"

#define TN40_DRV_NAME "tn40xx"

#define PCI_DEVICE_ID_TEHUTI_TN9510     0x4025

#define TN40_MDIO_SPEED_1MHZ (1)
#define TN40_MDIO_SPEED_6MHZ (6)

/* netdev tx queue len for Luxor. The default value is 1000.
 * ifconfig eth1 txqueuelen 3000 - to change it at runtime.
 */
#define TN40_NDEV_TXQ_LEN 1000

#define TN40_FIFO_SIZE 4096
#define TN40_FIFO_EXTRA_SPACE 1024

#define TN40_TXF_DESC_SZ 16
#define TN40_MAX_TX_LEVEL (priv->txd_fifo0.m.memsz - 16)
#define TN40_MIN_TX_LEVEL 256
#define TN40_NO_UPD_PACKETS 40
#define TN40_MAX_MTU BIT(14)

#define TN40_PCK_TH_MULT 128
#define TN40_INT_COAL_MULT 2

#define TN40_INT_REG_VAL(coal, coal_rc, rxf_th, pck_th) (       \
        FIELD_PREP(GENMASK(14, 0), (coal)) |            \
        FIELD_PREP(BIT(15), (coal_rc)) |                \
        FIELD_PREP(GENMASK(19, 16), (rxf_th)) |         \
        FIELD_PREP(GENMASK(31, 20), (pck_th))           \
        )

struct tn40_fifo {
        dma_addr_t da; /* Physical address of fifo (used by HW) */
        char *va; /* Virtual address of fifo (used by SW) */
        u32 rptr, wptr;
         /* Cached values of RPTR and WPTR registers,
          * they're 32 bits on both 32 and 64 archs.
          */
        u16 reg_cfg0;
        u16 reg_cfg1;
        u16 reg_rptr;
        u16 reg_wptr;
        u16 memsz; /* Memory size allocated for fifo */
        u16 size_mask;
        u16 pktsz; /* Skb packet size to allocate */
        u16 rcvno; /* Number of buffers that come from this RXF */
};

struct tn40_txf_fifo {
        struct tn40_fifo m; /* The minimal set of variables used by all fifos */
};

struct tn40_txd_fifo {
        struct tn40_fifo m; /* The minimal set of variables used by all fifos */
};

struct tn40_rxf_fifo {
        struct tn40_fifo m; /* The minimal set of variables used by all fifos */
};

struct tn40_rxd_fifo {
        struct tn40_fifo m; /* The minimal set of variables used by all fifos */
};

struct tn40_rx_map {
        struct page *page;
};

struct tn40_rxdb {
        unsigned int *stack;
        struct tn40_rx_map *elems;
        unsigned int nelem;
        unsigned int top;
};

union tn40_tx_dma_addr {
        dma_addr_t dma;
        struct sk_buff *skb;
};

/* Entry in the db.
 * if len == 0 addr is dma
 * if len != 0 addr is skb
 */
struct tn40_tx_map {
        union tn40_tx_dma_addr addr;
        int len;
};

/* tx database - implemented as circular fifo buffer */
struct tn40_txdb {
        struct tn40_tx_map *start; /* Points to the first element */
        struct tn40_tx_map *end; /* Points just AFTER the last element */
        struct tn40_tx_map *rptr; /* Points to the next element to read */
        struct tn40_tx_map *wptr; /* Points to the next element to write */
        int size; /* Number of elements in the db */
};

#define NODE_PROP(_NAME, _PROP) (               \
        (const struct software_node) {          \
                .name = _NAME,                  \
                .properties = _PROP,            \
        })

#define NODE_PAR_PROP(_NAME, _PAR, _PROP)       (       \
        (const struct software_node) {          \
                .name = _NAME,                  \
                .parent = _PAR,                 \
                .properties = _PROP,            \
        })

enum tn40_swnodes {
        SWNODE_MDIO,
        SWNODE_PHY,
        SWNODE_MAX
};

struct tn40_nodes {
        char phy_name[32];
        char mdio_name[32];
        struct property_entry phy_props[3];
        struct software_node swnodes[SWNODE_MAX];
        const struct software_node *group[SWNODE_MAX + 1];
};

struct tn40_priv {
        struct net_device *ndev;
        struct pci_dev *pdev;

        struct tn40_nodes nodes;

        struct napi_struct napi;
        /* RX FIFOs: 1 for data (full) descs, and 2 for free descs */
        struct tn40_rxd_fifo rxd_fifo0;
        struct tn40_rxf_fifo rxf_fifo0;
        struct tn40_rxdb *rxdb0; /* Rx dbs to store skb pointers */
        struct page_pool *page_pool;

        /* Tx FIFOs: 1 for data desc, 1 for empty (acks) desc */
        struct tn40_txd_fifo txd_fifo0;
        struct tn40_txf_fifo txf_fifo0;
        struct tn40_txdb txdb;
        int tx_level;
        int tx_update_mark;
        int tx_noupd;

        int stats_flag;
        struct rtnl_link_stats64 stats;
        u64 alloc_fail;
        struct u64_stats_sync syncp;

        u8 txd_size;
        u8 txf_size;
        u8 rxd_size;
        u8 rxf_size;
        u32 rdintcm;
        u32 tdintcm;

        u32 isr_mask;

        void __iomem *regs;

        /* SHORT_PKT_FIX */
        u32 b0_len;
        dma_addr_t b0_dma; /* Physical address of buffer */
        char *b0_va; /* Virtual address of buffer */

        struct mii_bus *mdio;
        struct phy_device *phydev;
        struct phylink *phylink;
        struct phylink_config phylink_config;
};

/* RX FREE descriptor - 64bit */
struct tn40_rxf_desc {
        __le32 info; /* Buffer Count + Info - described below */
        __le32 va_lo; /* VAdr[31:0] */
        __le32 va_hi; /* VAdr[63:32] */
        __le32 pa_lo; /* PAdr[31:0] */
        __le32 pa_hi; /* PAdr[63:32] */
        __le32 len; /* Buffer Length */
};

#define TN40_GET_RXD_BC(x) FIELD_GET(GENMASK(4, 0), (x))
#define TN40_GET_RXD_ERR(x) FIELD_GET(GENMASK(26, 21), (x))
#define TN40_GET_RXD_PKT_ID(x) FIELD_GET(GENMASK(30, 28), (x))
#define TN40_GET_RXD_VTAG(x) FIELD_GET(BIT(31), (x))
#define TN40_GET_RXD_VLAN_TCI(x) FIELD_GET(GENMASK(15, 0), (x))

struct tn40_rxd_desc {
        __le32 rxd_val1;
        __le16 len;
        __le16 rxd_vlan;
        __le32 va_lo;
        __le32 va_hi;
        __le32 rss_lo;
        __le32 rss_hash;
};

#define TN40_MAX_PBL (19)
/* PBL describes each virtual buffer to be transmitted from the host. */
struct tn40_pbl {
        __le32 pa_lo;
        __le32 pa_hi;
        __le32 len;
};

/* First word for TXD descriptor. It means: type = 3 for regular Tx packet,
 * hw_csum = 7 for IP+UDP+TCP HW checksums.
 */
#define TN40_TXD_W1_VAL(bc, checksum, vtag, lgsnd, vlan_id) (           \
        GENMASK(17, 16) |                                               \
        FIELD_PREP(GENMASK(4, 0), (bc)) |                               \
        FIELD_PREP(GENMASK(7, 5), (checksum)) |                         \
        FIELD_PREP(BIT(8), (vtag)) |                                    \
        FIELD_PREP(GENMASK(12, 9), (lgsnd)) |                           \
        FIELD_PREP(GENMASK(15, 13),                                     \
                   FIELD_GET(GENMASK(15, 13), (vlan_id))) |             \
        FIELD_PREP(GENMASK(31, 20),                                     \
                   FIELD_GET(GENMASK(11, 0), (vlan_id)))                \
        )

struct tn40_txd_desc {
        __le32 txd_val1;
        __le16 mss;
        __le16 length;
        __le32 va_lo;
        __le32 va_hi;
        struct tn40_pbl pbl[]; /* Fragments */
};

struct tn40_txf_desc {
        u32 status;
        u32 va_lo; /* VAdr[31:0] */
        u32 va_hi; /* VAdr[63:32] */
        u32 pad;
};

static inline u32 tn40_read_reg(struct tn40_priv *priv, u32 reg)
{
        return readl(priv->regs + reg);
}

static inline void tn40_write_reg(struct tn40_priv *priv, u32 reg, u32 val)
{
        writel(val, priv->regs + reg);
}

int tn40_set_link_speed(struct tn40_priv *priv, u32 speed);

void tn40_swnodes_cleanup(struct tn40_priv *priv);
int tn40_mdiobus_init(struct tn40_priv *priv);

int tn40_phy_register(struct tn40_priv *priv);
void tn40_phy_unregister(struct tn40_priv *priv);

#endif /* _TN40XX_H */