root/drivers/net/ethernet/marvell/mvneta_bm.h
/*
 * Driver for Marvell NETA network controller Buffer Manager.
 *
 * Copyright (C) 2015 Marvell
 *
 * Marcin Wojtas <mw@semihalf.com>
 *
 * This file is licensed under the terms of the GNU General Public
 * License version 2. This program is licensed "as is" without any
 * warranty of any kind, whether express or implied.
 */

#ifndef _MVNETA_BM_H_
#define _MVNETA_BM_H_

/* BM Configuration Register */
#define MVNETA_BM_CONFIG_REG                    0x0
#define    MVNETA_BM_STATUS_MASK                0x30
#define    MVNETA_BM_ACTIVE_MASK                BIT(4)
#define    MVNETA_BM_MAX_IN_BURST_SIZE_MASK     0x60000
#define    MVNETA_BM_MAX_IN_BURST_SIZE_16BP     BIT(18)
#define    MVNETA_BM_EMPTY_LIMIT_MASK           BIT(19)

/* BM Activation Register */
#define MVNETA_BM_COMMAND_REG                   0x4
#define    MVNETA_BM_START_MASK                 BIT(0)
#define    MVNETA_BM_STOP_MASK                  BIT(1)
#define    MVNETA_BM_PAUSE_MASK                 BIT(2)

/* BM Xbar interface Register */
#define MVNETA_BM_XBAR_01_REG                   0x8
#define MVNETA_BM_XBAR_23_REG                   0xc
#define MVNETA_BM_XBAR_POOL_REG(pool)           \
                (((pool) < 2) ? MVNETA_BM_XBAR_01_REG : MVNETA_BM_XBAR_23_REG)
#define     MVNETA_BM_TARGET_ID_OFFS(pool)      (((pool) & 1) ? 16 : 0)
#define     MVNETA_BM_TARGET_ID_MASK(pool)      \
                (0xf << MVNETA_BM_TARGET_ID_OFFS(pool))
#define     MVNETA_BM_TARGET_ID_VAL(pool, id)   \
                ((id) << MVNETA_BM_TARGET_ID_OFFS(pool))
#define     MVNETA_BM_XBAR_ATTR_OFFS(pool)      (((pool) & 1) ? 20 : 4)
#define     MVNETA_BM_XBAR_ATTR_MASK(pool)      \
                (0xff << MVNETA_BM_XBAR_ATTR_OFFS(pool))
#define     MVNETA_BM_XBAR_ATTR_VAL(pool, attr) \
                ((attr) << MVNETA_BM_XBAR_ATTR_OFFS(pool))

/* Address of External Buffer Pointers Pool Register */
#define MVNETA_BM_POOL_BASE_REG(pool)           (0x10 + ((pool) << 4))
#define     MVNETA_BM_POOL_ENABLE_MASK          BIT(0)

/* External Buffer Pointers Pool RD pointer Register */
#define MVNETA_BM_POOL_READ_PTR_REG(pool)       (0x14 + ((pool) << 4))
#define     MVNETA_BM_POOL_SET_READ_PTR_MASK    0xfffc
#define     MVNETA_BM_POOL_GET_READ_PTR_OFFS    16
#define     MVNETA_BM_POOL_GET_READ_PTR_MASK    0xfffc0000

/* External Buffer Pointers Pool WR pointer */
#define MVNETA_BM_POOL_WRITE_PTR_REG(pool)      (0x18 + ((pool) << 4))
#define     MVNETA_BM_POOL_SET_WRITE_PTR_OFFS   0
#define     MVNETA_BM_POOL_SET_WRITE_PTR_MASK   0xfffc
#define     MVNETA_BM_POOL_GET_WRITE_PTR_OFFS   16
#define     MVNETA_BM_POOL_GET_WRITE_PTR_MASK   0xfffc0000

/* External Buffer Pointers Pool Size Register */
#define MVNETA_BM_POOL_SIZE_REG(pool)           (0x1c + ((pool) << 4))
#define     MVNETA_BM_POOL_SIZE_MASK            0x3fff

/* BM Interrupt Cause Register */
#define MVNETA_BM_INTR_CAUSE_REG                (0x50)

/* BM interrupt Mask Register */
#define MVNETA_BM_INTR_MASK_REG                 (0x54)

/* Other definitions */
#define MVNETA_BM_SHORT_PKT_SIZE                256
#define MVNETA_BM_POOLS_NUM                     4
#define MVNETA_BM_POOL_CAP_MIN                  128
#define MVNETA_BM_POOL_CAP_DEF                  2048
#define MVNETA_BM_POOL_CAP_MAX                  \
                (16 * 1024 - MVNETA_BM_POOL_CAP_ALIGN)
#define MVNETA_BM_POOL_CAP_ALIGN                32
#define MVNETA_BM_POOL_PTR_ALIGN                32

#define MVNETA_BM_POOL_ACCESS_OFFS              8

#define MVNETA_BM_BPPI_SIZE                     0x100000

#define MVNETA_RX_BUF_SIZE(pkt_size)   ((pkt_size) + NET_SKB_PAD)

enum mvneta_bm_type {
        MVNETA_BM_FREE,
        MVNETA_BM_LONG,
        MVNETA_BM_SHORT
};

struct mvneta_bm {
        void __iomem *reg_base;
        struct clk *clk;
        struct platform_device *pdev;

        struct gen_pool *bppi_pool;
        /* BPPI virtual base address */
        void __iomem *bppi_virt_addr;
        /* BPPI physical base address */
        dma_addr_t bppi_phys_addr;

        /* BM pools */
        struct mvneta_bm_pool *bm_pools;
};

struct mvneta_bm_pool {
        struct hwbm_pool hwbm_pool;
        /* Pool number in the range 0-3 */
        u8 id;
        enum mvneta_bm_type type;

        /* Packet size */
        int pkt_size;
        /* Size of the buffer access through DMA */
        u32 buf_size;

        /* BPPE virtual base address */
        u32 *virt_addr;
        /* BPPE physical base address */
        dma_addr_t phys_addr;

        /* Ports using BM pool */
        u8 port_map;

        struct mvneta_bm *priv;
};

/* Declarations and definitions */
#if IS_ENABLED(CONFIG_MVNETA_BM)
struct mvneta_bm *mvneta_bm_get(struct device_node *node);
void mvneta_bm_put(struct mvneta_bm *priv);

void mvneta_bm_pool_destroy(struct mvneta_bm *priv,
                            struct mvneta_bm_pool *bm_pool, u8 port_map);
void mvneta_bm_bufs_free(struct mvneta_bm *priv, struct mvneta_bm_pool *bm_pool,
                         u8 port_map);
int mvneta_bm_construct(struct hwbm_pool *hwbm_pool, void *buf);
int mvneta_bm_pool_refill(struct mvneta_bm *priv,
                          struct mvneta_bm_pool *bm_pool);
struct mvneta_bm_pool *mvneta_bm_pool_use(struct mvneta_bm *priv, u8 pool_id,
                                          enum mvneta_bm_type type, u8 port_id,
                                          int pkt_size);

static inline void mvneta_bm_pool_put_bp(struct mvneta_bm *priv,
                                         struct mvneta_bm_pool *bm_pool,
                                         dma_addr_t buf_phys_addr)
{
        writel_relaxed(buf_phys_addr, priv->bppi_virt_addr +
                       (bm_pool->id << MVNETA_BM_POOL_ACCESS_OFFS));
}

static inline u32 mvneta_bm_pool_get_bp(struct mvneta_bm *priv,
                                        struct mvneta_bm_pool *bm_pool)
{
        return readl_relaxed(priv->bppi_virt_addr +
                             (bm_pool->id << MVNETA_BM_POOL_ACCESS_OFFS));
}
#else
static inline void mvneta_bm_pool_destroy(struct mvneta_bm *priv,
                                          struct mvneta_bm_pool *bm_pool,
                                          u8 port_map) {}
static inline void mvneta_bm_bufs_free(struct mvneta_bm *priv,
                                       struct mvneta_bm_pool *bm_pool,
                                       u8 port_map) {}
static inline int mvneta_bm_construct(struct hwbm_pool *hwbm_pool, void *buf)
{ return 0; }
static inline int mvneta_bm_pool_refill(struct mvneta_bm *priv,
                                        struct mvneta_bm_pool *bm_pool)
{ return 0; }
static inline struct mvneta_bm_pool *mvneta_bm_pool_use(struct mvneta_bm *priv,
                                                        u8 pool_id,
                                                        enum mvneta_bm_type type,
                                                        u8 port_id,
                                                        int pkt_size)
{ return NULL; }

static inline void mvneta_bm_pool_put_bp(struct mvneta_bm *priv,
                                         struct mvneta_bm_pool *bm_pool,
                                         dma_addr_t buf_phys_addr) {}

static inline u32 mvneta_bm_pool_get_bp(struct mvneta_bm *priv,
                                        struct mvneta_bm_pool *bm_pool)
{ return 0; }
static inline struct mvneta_bm *mvneta_bm_get(struct device_node *node)
{ return NULL; }
static inline void mvneta_bm_put(struct mvneta_bm *priv) {}
#endif /* CONFIG_MVNETA_BM */
#endif