162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci *
362306a36Sopenharmony_ci * Copyright (c) 2021, MediaTek Inc.
462306a36Sopenharmony_ci * Copyright (c) 2021-2022, Intel Corporation.
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Authors:
762306a36Sopenharmony_ci *  Haijun Liu <haijun.liu@mediatek.com>
862306a36Sopenharmony_ci *  Moises Veleta <moises.veleta@intel.com>
962306a36Sopenharmony_ci *  Ricardo Martinez <ricardo.martinez@linux.intel.com>
1062306a36Sopenharmony_ci *  Sreehari Kancharla <sreehari.kancharla@intel.com>
1162306a36Sopenharmony_ci *
1262306a36Sopenharmony_ci * Contributors:
1362306a36Sopenharmony_ci *  Amir Hanania <amir.hanania@intel.com>
1462306a36Sopenharmony_ci *  Chiranjeevi Rapolu <chiranjeevi.rapolu@intel.com>
1562306a36Sopenharmony_ci *  Eliot Lee <eliot.lee@intel.com>
1662306a36Sopenharmony_ci */
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#ifndef __T7XX_HIF_CLDMA_H__
1962306a36Sopenharmony_ci#define __T7XX_HIF_CLDMA_H__
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#include <linux/bits.h>
2262306a36Sopenharmony_ci#include <linux/device.h>
2362306a36Sopenharmony_ci#include <linux/dmapool.h>
2462306a36Sopenharmony_ci#include <linux/pci.h>
2562306a36Sopenharmony_ci#include <linux/skbuff.h>
2662306a36Sopenharmony_ci#include <linux/spinlock.h>
2762306a36Sopenharmony_ci#include <linux/wait.h>
2862306a36Sopenharmony_ci#include <linux/workqueue.h>
2962306a36Sopenharmony_ci#include <linux/types.h>
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci#include "t7xx_cldma.h"
3262306a36Sopenharmony_ci#include "t7xx_pci.h"
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci/**
3562306a36Sopenharmony_ci * enum cldma_id - Identifiers for CLDMA HW units.
3662306a36Sopenharmony_ci * @CLDMA_ID_MD: Modem control channel.
3762306a36Sopenharmony_ci * @CLDMA_ID_AP: Application Processor control channel.
3862306a36Sopenharmony_ci * @CLDMA_NUM:   Number of CLDMA HW units available.
3962306a36Sopenharmony_ci */
4062306a36Sopenharmony_cienum cldma_id {
4162306a36Sopenharmony_ci	CLDMA_ID_MD,
4262306a36Sopenharmony_ci	CLDMA_ID_AP,
4362306a36Sopenharmony_ci	CLDMA_NUM
4462306a36Sopenharmony_ci};
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_cistruct cldma_gpd {
4762306a36Sopenharmony_ci	u8 flags;
4862306a36Sopenharmony_ci	u8 not_used1;
4962306a36Sopenharmony_ci	__le16 rx_data_allow_len;
5062306a36Sopenharmony_ci	__le32 next_gpd_ptr_h;
5162306a36Sopenharmony_ci	__le32 next_gpd_ptr_l;
5262306a36Sopenharmony_ci	__le32 data_buff_bd_ptr_h;
5362306a36Sopenharmony_ci	__le32 data_buff_bd_ptr_l;
5462306a36Sopenharmony_ci	__le16 data_buff_len;
5562306a36Sopenharmony_ci	__le16 not_used2;
5662306a36Sopenharmony_ci};
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_cistruct cldma_request {
5962306a36Sopenharmony_ci	struct cldma_gpd *gpd;	/* Virtual address for CPU */
6062306a36Sopenharmony_ci	dma_addr_t gpd_addr;	/* Physical address for DMA */
6162306a36Sopenharmony_ci	struct sk_buff *skb;
6262306a36Sopenharmony_ci	dma_addr_t mapped_buff;
6362306a36Sopenharmony_ci	struct list_head entry;
6462306a36Sopenharmony_ci};
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_cistruct cldma_ring {
6762306a36Sopenharmony_ci	struct list_head gpd_ring;	/* Ring of struct cldma_request */
6862306a36Sopenharmony_ci	unsigned int length;		/* Number of struct cldma_request */
6962306a36Sopenharmony_ci	int pkt_size;
7062306a36Sopenharmony_ci};
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_cistruct cldma_queue {
7362306a36Sopenharmony_ci	struct cldma_ctrl *md_ctrl;
7462306a36Sopenharmony_ci	enum mtk_txrx dir;
7562306a36Sopenharmony_ci	unsigned int index;
7662306a36Sopenharmony_ci	struct cldma_ring *tr_ring;
7762306a36Sopenharmony_ci	struct cldma_request *tr_done;
7862306a36Sopenharmony_ci	struct cldma_request *rx_refill;
7962306a36Sopenharmony_ci	struct cldma_request *tx_next;
8062306a36Sopenharmony_ci	int budget;			/* Same as ring buffer size by default */
8162306a36Sopenharmony_ci	spinlock_t ring_lock;
8262306a36Sopenharmony_ci	wait_queue_head_t req_wq;	/* Only for TX */
8362306a36Sopenharmony_ci	struct workqueue_struct *worker;
8462306a36Sopenharmony_ci	struct work_struct cldma_work;
8562306a36Sopenharmony_ci};
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_cistruct cldma_ctrl {
8862306a36Sopenharmony_ci	enum cldma_id hif_id;
8962306a36Sopenharmony_ci	struct device *dev;
9062306a36Sopenharmony_ci	struct t7xx_pci_dev *t7xx_dev;
9162306a36Sopenharmony_ci	struct cldma_queue txq[CLDMA_TXQ_NUM];
9262306a36Sopenharmony_ci	struct cldma_queue rxq[CLDMA_RXQ_NUM];
9362306a36Sopenharmony_ci	unsigned short txq_active;
9462306a36Sopenharmony_ci	unsigned short rxq_active;
9562306a36Sopenharmony_ci	unsigned short txq_started;
9662306a36Sopenharmony_ci	spinlock_t cldma_lock; /* Protects CLDMA structure */
9762306a36Sopenharmony_ci	/* Assumes T/R GPD/BD/SPD have the same size */
9862306a36Sopenharmony_ci	struct dma_pool *gpd_dmapool;
9962306a36Sopenharmony_ci	struct cldma_ring tx_ring[CLDMA_TXQ_NUM];
10062306a36Sopenharmony_ci	struct cldma_ring rx_ring[CLDMA_RXQ_NUM];
10162306a36Sopenharmony_ci	struct md_pm_entity *pm_entity;
10262306a36Sopenharmony_ci	struct t7xx_cldma_hw hw_info;
10362306a36Sopenharmony_ci	bool is_late_init;
10462306a36Sopenharmony_ci	int (*recv_skb)(struct cldma_queue *queue, struct sk_buff *skb);
10562306a36Sopenharmony_ci};
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci#define GPD_FLAGS_HWO		BIT(0)
10862306a36Sopenharmony_ci#define GPD_FLAGS_IOC		BIT(7)
10962306a36Sopenharmony_ci#define GPD_DMAPOOL_ALIGN	16
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci#define CLDMA_MTU		3584	/* 3.5kB */
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ciint t7xx_cldma_alloc(enum cldma_id hif_id, struct t7xx_pci_dev *t7xx_dev);
11462306a36Sopenharmony_civoid t7xx_cldma_hif_hw_init(struct cldma_ctrl *md_ctrl);
11562306a36Sopenharmony_ciint t7xx_cldma_init(struct cldma_ctrl *md_ctrl);
11662306a36Sopenharmony_civoid t7xx_cldma_exit(struct cldma_ctrl *md_ctrl);
11762306a36Sopenharmony_civoid t7xx_cldma_switch_cfg(struct cldma_ctrl *md_ctrl);
11862306a36Sopenharmony_civoid t7xx_cldma_start(struct cldma_ctrl *md_ctrl);
11962306a36Sopenharmony_ciint t7xx_cldma_stop(struct cldma_ctrl *md_ctrl);
12062306a36Sopenharmony_civoid t7xx_cldma_reset(struct cldma_ctrl *md_ctrl);
12162306a36Sopenharmony_civoid t7xx_cldma_set_recv_skb(struct cldma_ctrl *md_ctrl,
12262306a36Sopenharmony_ci			     int (*recv_skb)(struct cldma_queue *queue, struct sk_buff *skb));
12362306a36Sopenharmony_ciint t7xx_cldma_send_skb(struct cldma_ctrl *md_ctrl, int qno, struct sk_buff *skb);
12462306a36Sopenharmony_civoid t7xx_cldma_stop_all_qs(struct cldma_ctrl *md_ctrl, enum mtk_txrx tx_rx);
12562306a36Sopenharmony_civoid t7xx_cldma_clear_all_qs(struct cldma_ctrl *md_ctrl, enum mtk_txrx tx_rx);
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci#endif /* __T7XX_HIF_CLDMA_H__ */
128