1/* SPDX-License-Identifier: GPL-2.0-only */
2/* Copyright (C) 2022 Lorenzo Bianconi <lorenzo@kernel.org>  */
3
4#ifndef __MTK_WED_WO_H
5#define __MTK_WED_WO_H
6
7#include <linux/skbuff.h>
8#include <linux/netdevice.h>
9
10struct mtk_wed_hw;
11
12struct mtk_wed_mcu_hdr {
13	/* DW0 */
14	u8 version;
15	u8 cmd;
16	__le16 length;
17
18	/* DW1 */
19	__le16 seq;
20	__le16 flag;
21
22	/* DW2 */
23	__le32 status;
24
25	/* DW3 */
26	u8 rsv[20];
27};
28
29struct mtk_wed_wo_log_info {
30	__le32 sn;
31	__le32 total;
32	__le32 rro;
33	__le32 mod;
34};
35
36enum mtk_wed_wo_event {
37	MTK_WED_WO_EVT_LOG_DUMP		= 0x1,
38	MTK_WED_WO_EVT_PROFILING	= 0x2,
39	MTK_WED_WO_EVT_RXCNT_INFO	= 0x3,
40};
41
42#define MTK_WED_MODULE_ID_WO		1
43#define MTK_FW_DL_TIMEOUT		4000000 /* us */
44#define MTK_WOCPU_TIMEOUT		2000000 /* us */
45
46enum {
47	MTK_WED_WARP_CMD_FLAG_RSP		= BIT(0),
48	MTK_WED_WARP_CMD_FLAG_NEED_RSP		= BIT(1),
49	MTK_WED_WARP_CMD_FLAG_FROM_TO_WO	= BIT(2),
50};
51
52#define MTK_WED_WO_CPU_MCUSYS_RESET_ADDR	0x15194050
53#define MTK_WED_WO_CPU_WO0_MCUSYS_RESET_MASK	0x20
54#define MTK_WED_WO_CPU_WO1_MCUSYS_RESET_MASK	0x1
55
56enum {
57	MTK_WED_WO_REGION_EMI,
58	MTK_WED_WO_REGION_ILM,
59	MTK_WED_WO_REGION_DATA,
60	MTK_WED_WO_REGION_BOOT,
61	__MTK_WED_WO_REGION_MAX,
62};
63
64enum mtk_wed_wo_state {
65	MTK_WED_WO_STATE_UNDEFINED,
66	MTK_WED_WO_STATE_INIT,
67	MTK_WED_WO_STATE_ENABLE,
68	MTK_WED_WO_STATE_DISABLE,
69	MTK_WED_WO_STATE_HALT,
70	MTK_WED_WO_STATE_GATING,
71	MTK_WED_WO_STATE_SER_RESET,
72	MTK_WED_WO_STATE_WF_RESET,
73};
74
75enum mtk_wed_wo_done_state {
76	MTK_WED_WOIF_UNDEFINED,
77	MTK_WED_WOIF_DISABLE_DONE,
78	MTK_WED_WOIF_TRIGGER_ENABLE,
79	MTK_WED_WOIF_ENABLE_DONE,
80	MTK_WED_WOIF_TRIGGER_GATING,
81	MTK_WED_WOIF_GATING_DONE,
82	MTK_WED_WOIF_TRIGGER_HALT,
83	MTK_WED_WOIF_HALT_DONE,
84};
85
86enum mtk_wed_dummy_cr_idx {
87	MTK_WED_DUMMY_CR_FWDL,
88	MTK_WED_DUMMY_CR_WO_STATUS,
89};
90
91#define MT7981_FIRMWARE_WO	"mediatek/mt7981_wo.bin"
92#define MT7986_FIRMWARE_WO0	"mediatek/mt7986_wo_0.bin"
93#define MT7986_FIRMWARE_WO1	"mediatek/mt7986_wo_1.bin"
94
95#define MTK_WO_MCU_CFG_LS_BASE				0
96#define MTK_WO_MCU_CFG_LS_HW_VER_ADDR			(MTK_WO_MCU_CFG_LS_BASE + 0x000)
97#define MTK_WO_MCU_CFG_LS_FW_VER_ADDR			(MTK_WO_MCU_CFG_LS_BASE + 0x004)
98#define MTK_WO_MCU_CFG_LS_CFG_DBG1_ADDR			(MTK_WO_MCU_CFG_LS_BASE + 0x00c)
99#define MTK_WO_MCU_CFG_LS_CFG_DBG2_ADDR			(MTK_WO_MCU_CFG_LS_BASE + 0x010)
100#define MTK_WO_MCU_CFG_LS_WF_MCCR_ADDR			(MTK_WO_MCU_CFG_LS_BASE + 0x014)
101#define MTK_WO_MCU_CFG_LS_WF_MCCR_SET_ADDR		(MTK_WO_MCU_CFG_LS_BASE + 0x018)
102#define MTK_WO_MCU_CFG_LS_WF_MCCR_CLR_ADDR		(MTK_WO_MCU_CFG_LS_BASE + 0x01c)
103#define MTK_WO_MCU_CFG_LS_WF_MCU_CFG_WM_WA_ADDR		(MTK_WO_MCU_CFG_LS_BASE + 0x050)
104#define MTK_WO_MCU_CFG_LS_WM_BOOT_ADDR_ADDR		(MTK_WO_MCU_CFG_LS_BASE + 0x060)
105#define MTK_WO_MCU_CFG_LS_WA_BOOT_ADDR_ADDR		(MTK_WO_MCU_CFG_LS_BASE + 0x064)
106
107#define MTK_WO_MCU_CFG_LS_WF_WM_WA_WM_CPU_RSTB_MASK	BIT(5)
108#define MTK_WO_MCU_CFG_LS_WF_WM_WA_WA_CPU_RSTB_MASK	BIT(0)
109
110#define MTK_WED_WO_RING_SIZE	256
111#define MTK_WED_WO_CMD_LEN	1504
112
113#define MTK_WED_WO_TXCH_NUM		0
114#define MTK_WED_WO_RXCH_NUM		1
115#define MTK_WED_WO_RXCH_WO_EXCEPTION	7
116
117#define MTK_WED_WO_TXCH_INT_MASK	BIT(0)
118#define MTK_WED_WO_RXCH_INT_MASK	BIT(1)
119#define MTK_WED_WO_EXCEPTION_INT_MASK	BIT(7)
120#define MTK_WED_WO_ALL_INT_MASK		(MTK_WED_WO_RXCH_INT_MASK | \
121					 MTK_WED_WO_EXCEPTION_INT_MASK)
122
123#define MTK_WED_WO_CCIF_BUSY		0x004
124#define MTK_WED_WO_CCIF_START		0x008
125#define MTK_WED_WO_CCIF_TCHNUM		0x00c
126#define MTK_WED_WO_CCIF_RCHNUM		0x010
127#define MTK_WED_WO_CCIF_RCHNUM_MASK	GENMASK(7, 0)
128
129#define MTK_WED_WO_CCIF_ACK		0x014
130#define MTK_WED_WO_CCIF_IRQ0_MASK	0x018
131#define MTK_WED_WO_CCIF_IRQ1_MASK	0x01c
132#define MTK_WED_WO_CCIF_DUMMY1		0x020
133#define MTK_WED_WO_CCIF_DUMMY2		0x024
134#define MTK_WED_WO_CCIF_DUMMY3		0x028
135#define MTK_WED_WO_CCIF_DUMMY4		0x02c
136#define MTK_WED_WO_CCIF_SHADOW1		0x030
137#define MTK_WED_WO_CCIF_SHADOW2		0x034
138#define MTK_WED_WO_CCIF_SHADOW3		0x038
139#define MTK_WED_WO_CCIF_SHADOW4		0x03c
140#define MTK_WED_WO_CCIF_DUMMY5		0x050
141#define MTK_WED_WO_CCIF_DUMMY6		0x054
142#define MTK_WED_WO_CCIF_DUMMY7		0x058
143#define MTK_WED_WO_CCIF_DUMMY8		0x05c
144#define MTK_WED_WO_CCIF_SHADOW5		0x060
145#define MTK_WED_WO_CCIF_SHADOW6		0x064
146#define MTK_WED_WO_CCIF_SHADOW7		0x068
147#define MTK_WED_WO_CCIF_SHADOW8		0x06c
148
149#define MTK_WED_WO_CTL_SD_LEN1		GENMASK(13, 0)
150#define MTK_WED_WO_CTL_LAST_SEC1	BIT(14)
151#define MTK_WED_WO_CTL_BURST		BIT(15)
152#define MTK_WED_WO_CTL_SD_LEN0_SHIFT	16
153#define MTK_WED_WO_CTL_SD_LEN0		GENMASK(29, 16)
154#define MTK_WED_WO_CTL_LAST_SEC0	BIT(30)
155#define MTK_WED_WO_CTL_DMA_DONE		BIT(31)
156#define MTK_WED_WO_INFO_WINFO		GENMASK(15, 0)
157
158struct mtk_wed_wo_memory_region {
159	const char *name;
160	void __iomem *addr;
161	phys_addr_t phy_addr;
162	u32 size;
163	bool shared:1;
164	bool consumed:1;
165};
166
167struct mtk_wed_fw_region {
168	__le32 decomp_crc;
169	__le32 decomp_len;
170	__le32 decomp_blk_sz;
171	u8 rsv0[4];
172	__le32 addr;
173	__le32 len;
174	u8 feature_set;
175	u8 rsv1[15];
176} __packed;
177
178struct mtk_wed_fw_trailer {
179	u8 chip_id;
180	u8 eco_code;
181	u8 num_region;
182	u8 format_ver;
183	u8 format_flag;
184	u8 rsv[2];
185	char fw_ver[10];
186	char build_date[15];
187	u32 crc;
188};
189
190struct mtk_wed_wo_queue_regs {
191	u32 desc_base;
192	u32 ring_size;
193	u32 cpu_idx;
194	u32 dma_idx;
195};
196
197struct mtk_wed_wo_queue_desc {
198	__le32 buf0;
199	__le32 ctrl;
200	__le32 buf1;
201	__le32 info;
202	__le32 reserved[4];
203} __packed __aligned(32);
204
205struct mtk_wed_wo_queue_entry {
206	dma_addr_t addr;
207	void *buf;
208	u32 len;
209};
210
211struct mtk_wed_wo_queue {
212	struct mtk_wed_wo_queue_regs regs;
213
214	struct page_frag_cache cache;
215
216	struct mtk_wed_wo_queue_desc *desc;
217	dma_addr_t desc_dma;
218
219	struct mtk_wed_wo_queue_entry *entry;
220
221	u16 head;
222	u16 tail;
223	int n_desc;
224	int queued;
225	int buf_size;
226
227};
228
229struct mtk_wed_wo {
230	struct mtk_wed_hw *hw;
231	struct mtk_wed_wo_memory_region boot;
232
233	struct mtk_wed_wo_queue q_tx;
234	struct mtk_wed_wo_queue q_rx;
235
236	struct {
237		struct mutex mutex;
238		int timeout;
239		u16 seq;
240
241		struct sk_buff_head res_q;
242		wait_queue_head_t wait;
243	} mcu;
244
245	struct {
246		struct regmap *regs;
247
248		spinlock_t lock;
249		struct tasklet_struct irq_tasklet;
250		int irq;
251		u32 irq_mask;
252	} mmio;
253};
254
255static inline int
256mtk_wed_mcu_check_msg(struct mtk_wed_wo *wo, struct sk_buff *skb)
257{
258	struct mtk_wed_mcu_hdr *hdr = (struct mtk_wed_mcu_hdr *)skb->data;
259
260	if (hdr->version)
261		return -EINVAL;
262
263	if (skb->len < sizeof(*hdr) || skb->len != le16_to_cpu(hdr->length))
264		return -EINVAL;
265
266	return 0;
267}
268
269void mtk_wed_mcu_rx_event(struct mtk_wed_wo *wo, struct sk_buff *skb);
270void mtk_wed_mcu_rx_unsolicited_event(struct mtk_wed_wo *wo,
271				      struct sk_buff *skb);
272int mtk_wed_mcu_send_msg(struct mtk_wed_wo *wo, int id, int cmd,
273			 const void *data, int len, bool wait_resp);
274int mtk_wed_mcu_msg_update(struct mtk_wed_device *dev, int id, void *data,
275			   int len);
276int mtk_wed_mcu_init(struct mtk_wed_wo *wo);
277int mtk_wed_wo_init(struct mtk_wed_hw *hw);
278void mtk_wed_wo_deinit(struct mtk_wed_hw *hw);
279int mtk_wed_wo_queue_tx_skb(struct mtk_wed_wo *dev, struct mtk_wed_wo_queue *q,
280			    struct sk_buff *skb);
281
282#endif /* __MTK_WED_WO_H */
283