root/drivers/net/ethernet/mediatek/mtk_wed.h
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (C) 2021 Felix Fietkau <nbd@nbd.name> */

#ifndef __MTK_WED_PRIV_H
#define __MTK_WED_PRIV_H

#include <linux/soc/mediatek/mtk_wed.h>
#include <linux/debugfs.h>
#include <linux/regmap.h>
#include <linux/netdevice.h>

#include "mtk_wed_regs.h"

struct mtk_eth;
struct mtk_wed_wo;

struct mtk_wed_soc_data {
        struct {
                u32 tx_bm_tkid;
                u32 wpdma_rx_ring[MTK_WED_RX_QUEUES];
                u32 reset_idx_tx_mask;
                u32 reset_idx_rx_mask;
        } regmap;
        u32 tx_ring_desc_size;
        u32 wdma_desc_size;
};

struct mtk_wed_amsdu {
        void *txd;
        dma_addr_t txd_phy;
};

struct mtk_wed_hw {
        const struct mtk_wed_soc_data *soc;
        struct device_node *node;
        struct mtk_eth *eth;
        struct regmap *regs;
        struct regmap *hifsys;
        struct device *dev;
        void __iomem *wdma;
        phys_addr_t wdma_phy;
        struct regmap *mirror;
        struct dentry *debugfs_dir;
        struct mtk_wed_device *wed_dev;
        struct mtk_wed_wo *wed_wo;
        struct mtk_wed_amsdu *wed_amsdu;
        u32 pcie_base;
        u32 debugfs_reg;
        u32 num_flows;
        u8 version;
        char dirname[5];
        int irq;
        int index;
};

struct mtk_wdma_info {
        u8 wdma_idx;
        u8 queue;
        u16 wcid;
        u8 bss;
        u8 amsdu;
};

#ifdef CONFIG_NET_MEDIATEK_SOC_WED
static inline bool mtk_wed_is_v1(struct mtk_wed_hw *hw)
{
        return hw->version == 1;
}

static inline bool mtk_wed_is_v2(struct mtk_wed_hw *hw)
{
        return hw->version == 2;
}

static inline bool mtk_wed_is_v3(struct mtk_wed_hw *hw)
{
        return hw->version == 3;
}

static inline bool mtk_wed_is_v3_or_greater(struct mtk_wed_hw *hw)
{
        return hw->version > 2;
}

static inline void
wed_w32(struct mtk_wed_device *dev, u32 reg, u32 val)
{
        regmap_write(dev->hw->regs, reg, val);
}

static inline u32
wed_r32(struct mtk_wed_device *dev, u32 reg)
{
        unsigned int val;

        regmap_read(dev->hw->regs, reg, &val);

        return val;
}

static inline void
wdma_w32(struct mtk_wed_device *dev, u32 reg, u32 val)
{
        writel(val, dev->hw->wdma + reg);
}

static inline u32
wdma_r32(struct mtk_wed_device *dev, u32 reg)
{
        return readl(dev->hw->wdma + reg);
}

static inline u32
wpdma_tx_r32(struct mtk_wed_device *dev, int ring, u32 reg)
{
        if (!dev->tx_ring[ring].wpdma)
                return 0;

        return readl(dev->tx_ring[ring].wpdma + reg);
}

static inline void
wpdma_tx_w32(struct mtk_wed_device *dev, int ring, u32 reg, u32 val)
{
        if (!dev->tx_ring[ring].wpdma)
                return;

        writel(val, dev->tx_ring[ring].wpdma + reg);
}

static inline u32
wpdma_rx_r32(struct mtk_wed_device *dev, int ring, u32 reg)
{
        if (!dev->rx_ring[ring].wpdma)
                return 0;

        return readl(dev->rx_ring[ring].wpdma + reg);
}

static inline void
wpdma_rx_w32(struct mtk_wed_device *dev, int ring, u32 reg, u32 val)
{
        if (!dev->rx_ring[ring].wpdma)
                return;

        writel(val, dev->rx_ring[ring].wpdma + reg);
}

static inline u32
wpdma_txfree_r32(struct mtk_wed_device *dev, u32 reg)
{
        if (!dev->txfree_ring.wpdma)
                return 0;

        return readl(dev->txfree_ring.wpdma + reg);
}

static inline void
wpdma_txfree_w32(struct mtk_wed_device *dev, u32 reg, u32 val)
{
        if (!dev->txfree_ring.wpdma)
                return;

        writel(val, dev->txfree_ring.wpdma + reg);
}

static inline u32 mtk_wed_get_pcie_base(struct mtk_wed_device *dev)
{
        if (!mtk_wed_is_v3_or_greater(dev->hw))
                return MTK_WED_PCIE_BASE;

        switch (dev->hw->index) {
        case 1:
                return MTK_WED_PCIE_BASE1;
        case 2:
                return MTK_WED_PCIE_BASE2;
        default:
                return MTK_WED_PCIE_BASE0;
        }
}

void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
                    void __iomem *wdma, phys_addr_t wdma_phy,
                    int index);
void mtk_wed_exit(void);
int mtk_wed_flow_add(int index);
void mtk_wed_flow_remove(int index);
void mtk_wed_fe_reset(void);
void mtk_wed_fe_reset_complete(void);
#else
static inline void
mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
               void __iomem *wdma, phys_addr_t wdma_phy,
               int index)
{
}
static inline void
mtk_wed_exit(void)
{
}
static inline int mtk_wed_flow_add(int index)
{
        return -EINVAL;
}
static inline void mtk_wed_flow_remove(int index)
{
}

static inline void mtk_wed_fe_reset(void)
{
}

static inline void mtk_wed_fe_reset_complete(void)
{
}
#endif

#ifdef CONFIG_DEBUG_FS
void mtk_wed_hw_add_debugfs(struct mtk_wed_hw *hw);
#else
static inline void mtk_wed_hw_add_debugfs(struct mtk_wed_hw *hw)
{
}
#endif

#endif