root/include/linux/soc/airoha/airoha_offload.h
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2025 AIROHA Inc
 * Author: Lorenzo Bianconi <lorenzo@kernel.org>
 */
#ifndef AIROHA_OFFLOAD_H
#define AIROHA_OFFLOAD_H

#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>

enum {
        PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED = 0x0f,
};

struct airoha_ppe_dev {
        struct {
                int (*setup_tc_block_cb)(struct airoha_ppe_dev *dev,
                                         void *type_data);
                void (*check_skb)(struct airoha_ppe_dev *dev,
                                  struct sk_buff *skb, u16 hash,
                                  bool rx_wlan);
        } ops;

        void *priv;
};

#if (IS_BUILTIN(CONFIG_NET_AIROHA) || IS_MODULE(CONFIG_NET_AIROHA))
struct airoha_ppe_dev *airoha_ppe_get_dev(struct device *dev);
void airoha_ppe_put_dev(struct airoha_ppe_dev *dev);

static inline int airoha_ppe_dev_setup_tc_block_cb(struct airoha_ppe_dev *dev,
                                                   void *type_data)
{
        return dev->ops.setup_tc_block_cb(dev, type_data);
}

static inline void airoha_ppe_dev_check_skb(struct airoha_ppe_dev *dev,
                                            struct sk_buff *skb,
                                            u16 hash, bool rx_wlan)
{
        dev->ops.check_skb(dev, skb, hash, rx_wlan);
}
#else
static inline struct airoha_ppe_dev *airoha_ppe_get_dev(struct device *dev)
{
        return NULL;
}

static inline void airoha_ppe_put_dev(struct airoha_ppe_dev *dev)
{
}

static inline int airoha_ppe_dev_setup_tc_block_cb(struct airoha_ppe_dev *dev,
                                                   void *type_data)
{
        return -EOPNOTSUPP;
}

static inline void airoha_ppe_dev_check_skb(struct airoha_ppe_dev *dev,
                                            struct sk_buff *skb, u16 hash,
                                            bool rx_wlan)
{
}
#endif

#define NPU_NUM_CORES           8
#define NPU_NUM_IRQ             6
#define NPU_RX0_DESC_NUM        512
#define NPU_RX1_DESC_NUM        512

/* CTRL */
#define NPU_RX_DMA_DESC_LAST_MASK       BIT(27)
#define NPU_RX_DMA_DESC_LEN_MASK        GENMASK(26, 14)
#define NPU_RX_DMA_DESC_CUR_LEN_MASK    GENMASK(13, 1)
#define NPU_RX_DMA_DESC_DONE_MASK       BIT(0)
/* INFO */
#define NPU_RX_DMA_PKT_COUNT_MASK       GENMASK(31, 29)
#define NPU_RX_DMA_PKT_ID_MASK          GENMASK(28, 26)
#define NPU_RX_DMA_SRC_PORT_MASK        GENMASK(25, 21)
#define NPU_RX_DMA_CRSN_MASK            GENMASK(20, 16)
#define NPU_RX_DMA_FOE_ID_MASK          GENMASK(15, 0)
/* DATA */
#define NPU_RX_DMA_SID_MASK             GENMASK(31, 16)
#define NPU_RX_DMA_FRAG_TYPE_MASK       GENMASK(15, 14)
#define NPU_RX_DMA_PRIORITY_MASK        GENMASK(13, 10)
#define NPU_RX_DMA_RADIO_ID_MASK        GENMASK(9, 6)
#define NPU_RX_DMA_VAP_ID_MASK          GENMASK(5, 2)
#define NPU_RX_DMA_FRAME_TYPE_MASK      GENMASK(1, 0)

struct airoha_npu_rx_dma_desc {
        u32 ctrl;
        u32 info;
        u32 data;
        u32 addr;
        u64 rsv;
} __packed;

/* CTRL */
#define NPU_TX_DMA_DESC_SCHED_MASK      BIT(31)
#define NPU_TX_DMA_DESC_LEN_MASK        GENMASK(30, 18)
#define NPU_TX_DMA_DESC_VEND_LEN_MASK   GENMASK(17, 1)
#define NPU_TX_DMA_DESC_DONE_MASK       BIT(0)

#define NPU_TXWI_LEN    192

struct airoha_npu_tx_dma_desc {
        u32 ctrl;
        u32 addr;
        u64 rsv;
        u8 txwi[NPU_TXWI_LEN];
} __packed;

enum airoha_npu_wlan_set_cmd {
        WLAN_FUNC_SET_WAIT_PCIE_ADDR,
        WLAN_FUNC_SET_WAIT_DESC,
        WLAN_FUNC_SET_WAIT_NPU_INIT_DONE,
        WLAN_FUNC_SET_WAIT_TRAN_TO_CPU,
        WLAN_FUNC_SET_WAIT_BA_WIN_SIZE,
        WLAN_FUNC_SET_WAIT_DRIVER_MODEL,
        WLAN_FUNC_SET_WAIT_DEL_STA,
        WLAN_FUNC_SET_WAIT_DRAM_BA_NODE_ADDR,
        WLAN_FUNC_SET_WAIT_PKT_BUF_ADDR,
        WLAN_FUNC_SET_WAIT_IS_TEST_NOBA,
        WLAN_FUNC_SET_WAIT_FLUSHONE_TIMEOUT,
        WLAN_FUNC_SET_WAIT_FLUSHALL_TIMEOUT,
        WLAN_FUNC_SET_WAIT_IS_FORCE_TO_CPU,
        WLAN_FUNC_SET_WAIT_PCIE_STATE,
        WLAN_FUNC_SET_WAIT_PCIE_PORT_TYPE,
        WLAN_FUNC_SET_WAIT_ERROR_RETRY_TIMES,
        WLAN_FUNC_SET_WAIT_BAR_INFO,
        WLAN_FUNC_SET_WAIT_FAST_FLAG,
        WLAN_FUNC_SET_WAIT_NPU_BAND0_ONCPU,
        WLAN_FUNC_SET_WAIT_TX_RING_PCIE_ADDR,
        WLAN_FUNC_SET_WAIT_TX_DESC_HW_BASE,
        WLAN_FUNC_SET_WAIT_TX_BUF_SPACE_HW_BASE,
        WLAN_FUNC_SET_WAIT_RX_RING_FOR_TXDONE_HW_BASE,
        WLAN_FUNC_SET_WAIT_TX_PKT_BUF_ADDR,
        WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR,
        WLAN_FUNC_SET_WAIT_INODE_DEBUG_FLAG,
        WLAN_FUNC_SET_WAIT_INODE_HW_CFG_INFO,
        WLAN_FUNC_SET_WAIT_INODE_STOP_ACTION,
        WLAN_FUNC_SET_WAIT_INODE_PCIE_SWAP,
        WLAN_FUNC_SET_WAIT_RATELIMIT_CTRL,
        WLAN_FUNC_SET_WAIT_HWNAT_INIT,
        WLAN_FUNC_SET_WAIT_ARHT_CHIP_INFO,
        WLAN_FUNC_SET_WAIT_TX_BUF_CHECK_ADDR,
        WLAN_FUNC_SET_WAIT_TOKEN_ID_SIZE,
};

enum airoha_npu_wlan_get_cmd {
        WLAN_FUNC_GET_WAIT_NPU_INFO,
        WLAN_FUNC_GET_WAIT_LAST_RATE,
        WLAN_FUNC_GET_WAIT_COUNTER,
        WLAN_FUNC_GET_WAIT_DBG_COUNTER,
        WLAN_FUNC_GET_WAIT_RXDESC_BASE,
        WLAN_FUNC_GET_WAIT_WCID_DBG_COUNTER,
        WLAN_FUNC_GET_WAIT_DMA_ADDR,
        WLAN_FUNC_GET_WAIT_RING_SIZE,
        WLAN_FUNC_GET_WAIT_NPU_SUPPORT_MAP,
        WLAN_FUNC_GET_WAIT_MDC_LOCK_ADDRESS,
        WLAN_FUNC_GET_WAIT_NPU_VERSION,
};

struct airoha_npu {
#if (IS_BUILTIN(CONFIG_NET_AIROHA_NPU) || IS_MODULE(CONFIG_NET_AIROHA_NPU))
        struct device *dev;
        struct regmap *regmap;

        struct airoha_npu_core {
                struct airoha_npu *npu;
                /* protect concurrent npu memory accesses */
                spinlock_t lock;
                struct work_struct wdt_work;
        } cores[NPU_NUM_CORES];

        int irqs[NPU_NUM_IRQ];

        struct airoha_foe_stats __iomem *stats;

        struct {
                int (*ppe_init)(struct airoha_npu *npu);
                int (*ppe_deinit)(struct airoha_npu *npu);
                int (*ppe_init_stats)(struct airoha_npu *npu,
                                      dma_addr_t addr, u32 num_stats_entries);
                int (*ppe_flush_sram_entries)(struct airoha_npu *npu,
                                              dma_addr_t foe_addr,
                                              int sram_num_entries);
                int (*ppe_foe_commit_entry)(struct airoha_npu *npu,
                                            dma_addr_t foe_addr,
                                            u32 entry_size, u32 hash,
                                            bool ppe2);
                int (*wlan_init_reserved_memory)(struct airoha_npu *npu);
                int (*wlan_send_msg)(struct airoha_npu *npu, int ifindex,
                                     enum airoha_npu_wlan_set_cmd func_id,
                                     void *data, int data_len, gfp_t gfp);
                int (*wlan_get_msg)(struct airoha_npu *npu, int ifindex,
                                    enum airoha_npu_wlan_get_cmd func_id,
                                    void *data, int data_len, gfp_t gfp);
                u32 (*wlan_get_queue_addr)(struct airoha_npu *npu, int qid,
                                           bool xmit);
                void (*wlan_set_irq_status)(struct airoha_npu *npu, u32 val);
                u32 (*wlan_get_irq_status)(struct airoha_npu *npu, int q);
                void (*wlan_enable_irq)(struct airoha_npu *npu, int q);
                void (*wlan_disable_irq)(struct airoha_npu *npu, int q);
        } ops;
#endif
};

#if (IS_BUILTIN(CONFIG_NET_AIROHA_NPU) || IS_MODULE(CONFIG_NET_AIROHA_NPU))
struct airoha_npu *airoha_npu_get(struct device *dev);
void airoha_npu_put(struct airoha_npu *npu);

static inline int airoha_npu_wlan_init_reserved_memory(struct airoha_npu *npu)
{
        return npu->ops.wlan_init_reserved_memory(npu);
}

static inline int airoha_npu_wlan_send_msg(struct airoha_npu *npu,
                                           int ifindex,
                                           enum airoha_npu_wlan_set_cmd cmd,
                                           void *data, int data_len, gfp_t gfp)
{
        return npu->ops.wlan_send_msg(npu, ifindex, cmd, data, data_len, gfp);
}

static inline int airoha_npu_wlan_get_msg(struct airoha_npu *npu, int ifindex,
                                          enum airoha_npu_wlan_get_cmd cmd,
                                          void *data, int data_len, gfp_t gfp)
{
        return npu->ops.wlan_get_msg(npu, ifindex, cmd, data, data_len, gfp);
}

static inline u32 airoha_npu_wlan_get_queue_addr(struct airoha_npu *npu,
                                                 int qid, bool xmit)
{
        return npu->ops.wlan_get_queue_addr(npu, qid, xmit);
}

static inline void airoha_npu_wlan_set_irq_status(struct airoha_npu *npu,
                                                  u32 val)
{
        npu->ops.wlan_set_irq_status(npu, val);
}

static inline u32 airoha_npu_wlan_get_irq_status(struct airoha_npu *npu, int q)
{
        return npu->ops.wlan_get_irq_status(npu, q);
}

static inline void airoha_npu_wlan_enable_irq(struct airoha_npu *npu, int q)
{
        npu->ops.wlan_enable_irq(npu, q);
}

static inline void airoha_npu_wlan_disable_irq(struct airoha_npu *npu, int q)
{
        npu->ops.wlan_disable_irq(npu, q);
}
#else
static inline struct airoha_npu *airoha_npu_get(struct device *dev)
{
        return NULL;
}

static inline void airoha_npu_put(struct airoha_npu *npu)
{
}

static inline int airoha_npu_wlan_init_reserved_memory(struct airoha_npu *npu)
{
        return -EOPNOTSUPP;
}

static inline int airoha_npu_wlan_send_msg(struct airoha_npu *npu,
                                           int ifindex,
                                           enum airoha_npu_wlan_set_cmd cmd,
                                           void *data, int data_len, gfp_t gfp)
{
        return -EOPNOTSUPP;
}

static inline int airoha_npu_wlan_get_msg(struct airoha_npu *npu, int ifindex,
                                          enum airoha_npu_wlan_get_cmd cmd,
                                          void *data, int data_len, gfp_t gfp)
{
        return -EOPNOTSUPP;
}

static inline u32 airoha_npu_wlan_get_queue_addr(struct airoha_npu *npu,
                                                 int qid, bool xmit)
{
        return 0;
}

static inline void airoha_npu_wlan_set_irq_status(struct airoha_npu *npu,
                                                  u32 val)
{
}

static inline u32 airoha_npu_wlan_get_irq_status(struct airoha_npu *npu,
                                                 int q)
{
        return 0;
}

static inline void airoha_npu_wlan_enable_irq(struct airoha_npu *npu, int q)
{
}

static inline void airoha_npu_wlan_disable_irq(struct airoha_npu *npu, int q)
{
}
#endif

#endif /* AIROHA_OFFLOAD_H */