Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
  2/* Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved */
  3
  4#include <linux/bitfield.h>
  5#include <linux/circ_buf.h>
  6#include <linux/device.h>
  7#include <linux/firmware.h>
  8#include <linux/iopoll.h>
  9#include <linux/kernel.h>
 10#include <linux/module.h>
 11#include <linux/pci.h>
 12
 13#include "prestera.h"
 14
 15#define PRESTERA_MSG_MAX_SIZE 1500
 16
 17#define PRESTERA_SUPP_FW_MAJ_VER	4
 18#define PRESTERA_SUPP_FW_MIN_VER	1
 19
 20#define PRESTERA_PREV_FW_MAJ_VER	4
 21#define PRESTERA_PREV_FW_MIN_VER	0
 22
 23#define PRESTERA_FW_PATH_FMT	"mrvl/prestera/mvsw_prestera_fw-v%u.%u.img"
 24#define PRESTERA_FW_ARM64_PATH_FMT "mrvl/prestera/mvsw_prestera_fw_arm64-v%u.%u.img"
 25
 26#define PRESTERA_FW_HDR_MAGIC		0x351D9D06
 27#define PRESTERA_FW_DL_TIMEOUT_MS	50000
 28#define PRESTERA_FW_BLK_SZ		1024
 29
 30#define PRESTERA_FW_VER_MAJ_MUL 1000000
 31#define PRESTERA_FW_VER_MIN_MUL 1000
 32
 33#define PRESTERA_FW_VER_MAJ(v)	((v) / PRESTERA_FW_VER_MAJ_MUL)
 34
 35#define PRESTERA_FW_VER_MIN(v) \
 36	(((v) - (PRESTERA_FW_VER_MAJ(v) * PRESTERA_FW_VER_MAJ_MUL)) / \
 37			PRESTERA_FW_VER_MIN_MUL)
 38
 39#define PRESTERA_FW_VER_PATCH(v) \
 40	((v) - (PRESTERA_FW_VER_MAJ(v) * PRESTERA_FW_VER_MAJ_MUL) - \
 41			(PRESTERA_FW_VER_MIN(v) * PRESTERA_FW_VER_MIN_MUL))
 42
 43enum prestera_pci_bar_t {
 44	PRESTERA_PCI_BAR_FW = 2,
 45	PRESTERA_PCI_BAR_PP = 4,
 46};
 47
 48struct prestera_fw_header {
 49	__be32 magic_number;
 50	__be32 version_value;
 51	u8 reserved[8];
 52};
 53
 54struct prestera_ldr_regs {
 55	u32 ldr_ready;
 56	u32 pad1;
 57
 58	u32 ldr_img_size;
 59	u32 ldr_ctl_flags;
 60
 61	u32 ldr_buf_offs;
 62	u32 ldr_buf_size;
 63
 64	u32 ldr_buf_rd;
 65	u32 pad2;
 66	u32 ldr_buf_wr;
 67
 68	u32 ldr_status;
 69};
 70
 71#define PRESTERA_LDR_REG_OFFSET(f)	offsetof(struct prestera_ldr_regs, f)
 72
 73#define PRESTERA_LDR_READY_MAGIC	0xf00dfeed
 74
 75#define PRESTERA_LDR_STATUS_IMG_DL	BIT(0)
 76#define PRESTERA_LDR_STATUS_START_FW	BIT(1)
 77#define PRESTERA_LDR_STATUS_INVALID_IMG	BIT(2)
 78#define PRESTERA_LDR_STATUS_NOMEM	BIT(3)
 79
 80#define PRESTERA_LDR_REG_BASE(fw)	((fw)->ldr_regs)
 81#define PRESTERA_LDR_REG_ADDR(fw, reg)	(PRESTERA_LDR_REG_BASE(fw) + (reg))
 82
 83/* fw loader registers */
 84#define PRESTERA_LDR_READY_REG		PRESTERA_LDR_REG_OFFSET(ldr_ready)
 85#define PRESTERA_LDR_IMG_SIZE_REG	PRESTERA_LDR_REG_OFFSET(ldr_img_size)
 86#define PRESTERA_LDR_CTL_REG		PRESTERA_LDR_REG_OFFSET(ldr_ctl_flags)
 87#define PRESTERA_LDR_BUF_SIZE_REG	PRESTERA_LDR_REG_OFFSET(ldr_buf_size)
 88#define PRESTERA_LDR_BUF_OFFS_REG	PRESTERA_LDR_REG_OFFSET(ldr_buf_offs)
 89#define PRESTERA_LDR_BUF_RD_REG		PRESTERA_LDR_REG_OFFSET(ldr_buf_rd)
 90#define PRESTERA_LDR_BUF_WR_REG		PRESTERA_LDR_REG_OFFSET(ldr_buf_wr)
 91#define PRESTERA_LDR_STATUS_REG		PRESTERA_LDR_REG_OFFSET(ldr_status)
 92
 93#define PRESTERA_LDR_CTL_DL_START	BIT(0)
 94
 95#define PRESTERA_EVT_QNUM_MAX	4
 96
 97struct prestera_fw_evtq_regs {
 98	u32 rd_idx;
 99	u32 pad1;
100	u32 wr_idx;
101	u32 pad2;
102	u32 offs;
103	u32 len;
104};
105
106#define PRESTERA_CMD_QNUM_MAX	4
107
108struct prestera_fw_cmdq_regs {
109	u32 req_ctl;
110	u32 req_len;
111	u32 rcv_ctl;
112	u32 rcv_len;
113	u32 offs;
114	u32 len;
115};
116
117struct prestera_fw_regs {
118	u32 fw_ready;
119	u32 cmd_offs;
120	u32 cmd_len;
121	u32 cmd_qnum;
122	u32 evt_offs;
123	u32 evt_qnum;
124
125	u32 fw_status;
126	u32 rx_status;
127
128	struct prestera_fw_cmdq_regs cmdq_list[PRESTERA_EVT_QNUM_MAX];
129	struct prestera_fw_evtq_regs evtq_list[PRESTERA_CMD_QNUM_MAX];
130};
131
132#define PRESTERA_FW_REG_OFFSET(f)	offsetof(struct prestera_fw_regs, f)
133
134#define PRESTERA_FW_READY_MAGIC		0xcafebabe
135
136/* fw registers */
137#define PRESTERA_FW_READY_REG		PRESTERA_FW_REG_OFFSET(fw_ready)
138
139#define PRESTERA_CMD_BUF_OFFS_REG	PRESTERA_FW_REG_OFFSET(cmd_offs)
140#define PRESTERA_CMD_BUF_LEN_REG	PRESTERA_FW_REG_OFFSET(cmd_len)
141#define PRESTERA_CMD_QNUM_REG		PRESTERA_FW_REG_OFFSET(cmd_qnum)
142#define PRESTERA_EVT_BUF_OFFS_REG	PRESTERA_FW_REG_OFFSET(evt_offs)
143#define PRESTERA_EVT_QNUM_REG		PRESTERA_FW_REG_OFFSET(evt_qnum)
144
145#define PRESTERA_CMDQ_REG_OFFSET(q, f)			\
146	(PRESTERA_FW_REG_OFFSET(cmdq_list) +		\
147	 (q) * sizeof(struct prestera_fw_cmdq_regs) +	\
148	 offsetof(struct prestera_fw_cmdq_regs, f))
149
150#define PRESTERA_CMDQ_REQ_CTL_REG(q)	PRESTERA_CMDQ_REG_OFFSET(q, req_ctl)
151#define PRESTERA_CMDQ_REQ_LEN_REG(q)	PRESTERA_CMDQ_REG_OFFSET(q, req_len)
152#define PRESTERA_CMDQ_RCV_CTL_REG(q)	PRESTERA_CMDQ_REG_OFFSET(q, rcv_ctl)
153#define PRESTERA_CMDQ_RCV_LEN_REG(q)	PRESTERA_CMDQ_REG_OFFSET(q, rcv_len)
154#define PRESTERA_CMDQ_OFFS_REG(q)	PRESTERA_CMDQ_REG_OFFSET(q, offs)
155#define PRESTERA_CMDQ_LEN_REG(q)	PRESTERA_CMDQ_REG_OFFSET(q, len)
156
157#define PRESTERA_FW_STATUS_REG		PRESTERA_FW_REG_OFFSET(fw_status)
158#define PRESTERA_RX_STATUS_REG		PRESTERA_FW_REG_OFFSET(rx_status)
159
160/* PRESTERA_CMD_REQ_CTL_REG flags */
161#define PRESTERA_CMD_F_REQ_SENT		BIT(0)
162#define PRESTERA_CMD_F_REPL_RCVD	BIT(1)
163
164/* PRESTERA_CMD_RCV_CTL_REG flags */
165#define PRESTERA_CMD_F_REPL_SENT	BIT(0)
166
167#define PRESTERA_FW_EVT_CTL_STATUS_MASK	GENMASK(1, 0)
168
169#define PRESTERA_FW_EVT_CTL_STATUS_ON	0
170#define PRESTERA_FW_EVT_CTL_STATUS_OFF	1
171
172#define PRESTERA_EVTQ_REG_OFFSET(q, f)			\
173	(PRESTERA_FW_REG_OFFSET(evtq_list) +		\
174	 (q) * sizeof(struct prestera_fw_evtq_regs) +	\
175	 offsetof(struct prestera_fw_evtq_regs, f))
176
177#define PRESTERA_EVTQ_RD_IDX_REG(q)	PRESTERA_EVTQ_REG_OFFSET(q, rd_idx)
178#define PRESTERA_EVTQ_WR_IDX_REG(q)	PRESTERA_EVTQ_REG_OFFSET(q, wr_idx)
179#define PRESTERA_EVTQ_OFFS_REG(q)	PRESTERA_EVTQ_REG_OFFSET(q, offs)
180#define PRESTERA_EVTQ_LEN_REG(q)	PRESTERA_EVTQ_REG_OFFSET(q, len)
181
182#define PRESTERA_FW_REG_BASE(fw)	((fw)->dev.ctl_regs)
183#define PRESTERA_FW_REG_ADDR(fw, reg)	PRESTERA_FW_REG_BASE((fw)) + (reg)
184
185#define PRESTERA_FW_CMD_DEFAULT_WAIT_MS	30000
186#define PRESTERA_FW_READY_WAIT_MS	20000
187
188#define PRESTERA_DEV_ID_AC3X_98DX_55	0xC804
189#define PRESTERA_DEV_ID_AC3X_98DX_65	0xC80C
190#define PRESTERA_DEV_ID_ALDRIN2		0xCC1E
191#define PRESTERA_DEV_ID_98DX7312M	0x981F
192#define PRESTERA_DEV_ID_98DX3500	0x9820
193#define PRESTERA_DEV_ID_98DX3501	0x9826
194#define PRESTERA_DEV_ID_98DX3510	0x9821
195#define PRESTERA_DEV_ID_98DX3520	0x9822
196
197struct prestera_fw_evtq {
198	u8 __iomem *addr;
199	size_t len;
200};
201
202struct prestera_fw_cmdq {
203	/* serialize access to dev->send_req */
204	struct mutex cmd_mtx;
205	u8 __iomem *addr;
206	size_t len;
207};
208
209struct prestera_fw {
210	struct prestera_fw_rev rev_supp;
211	const struct firmware *bin;
212	struct workqueue_struct *wq;
213	struct prestera_device dev;
214	struct pci_dev *pci_dev;
215	u8 __iomem *ldr_regs;
216	u8 __iomem *ldr_ring_buf;
217	u32 ldr_buf_len;
218	u32 ldr_wr_idx;
219	size_t cmd_mbox_len;
220	u8 __iomem *cmd_mbox;
221	struct prestera_fw_cmdq cmd_queue[PRESTERA_CMD_QNUM_MAX];
222	u8 cmd_qnum;
223	struct prestera_fw_evtq evt_queue[PRESTERA_EVT_QNUM_MAX];
224	u8 evt_qnum;
225	struct work_struct evt_work;
226	u8 __iomem *evt_buf;
227	u8 *evt_msg;
228};
229
230static int prestera_fw_load(struct prestera_fw *fw);
231
232static void prestera_fw_write(struct prestera_fw *fw, u32 reg, u32 val)
233{
234	writel(val, PRESTERA_FW_REG_ADDR(fw, reg));
235}
236
237static u32 prestera_fw_read(struct prestera_fw *fw, u32 reg)
238{
239	return readl(PRESTERA_FW_REG_ADDR(fw, reg));
240}
241
242static u32 prestera_fw_evtq_len(struct prestera_fw *fw, u8 qid)
243{
244	return fw->evt_queue[qid].len;
245}
246
247static u32 prestera_fw_evtq_avail(struct prestera_fw *fw, u8 qid)
248{
249	u32 wr_idx = prestera_fw_read(fw, PRESTERA_EVTQ_WR_IDX_REG(qid));
250	u32 rd_idx = prestera_fw_read(fw, PRESTERA_EVTQ_RD_IDX_REG(qid));
251
252	return CIRC_CNT(wr_idx, rd_idx, prestera_fw_evtq_len(fw, qid));
253}
254
255static void prestera_fw_evtq_rd_set(struct prestera_fw *fw,
256				    u8 qid, u32 idx)
257{
258	u32 rd_idx = idx & (prestera_fw_evtq_len(fw, qid) - 1);
259
260	prestera_fw_write(fw, PRESTERA_EVTQ_RD_IDX_REG(qid), rd_idx);
261}
262
263static u8 __iomem *prestera_fw_evtq_buf(struct prestera_fw *fw, u8 qid)
264{
265	return fw->evt_queue[qid].addr;
266}
267
268static u32 prestera_fw_evtq_read32(struct prestera_fw *fw, u8 qid)
269{
270	u32 rd_idx = prestera_fw_read(fw, PRESTERA_EVTQ_RD_IDX_REG(qid));
271	u32 val;
272
273	val = readl(prestera_fw_evtq_buf(fw, qid) + rd_idx);
274	prestera_fw_evtq_rd_set(fw, qid, rd_idx + 4);
275	return val;
276}
277
278static ssize_t prestera_fw_evtq_read_buf(struct prestera_fw *fw,
279					 u8 qid, void *buf, size_t len)
280{
281	u32 idx = prestera_fw_read(fw, PRESTERA_EVTQ_RD_IDX_REG(qid));
282	u8 __iomem *evtq_addr = prestera_fw_evtq_buf(fw, qid);
283	u32 *buf32 = buf;
284	int i;
285
286	for (i = 0; i < len / 4; buf32++, i++) {
287		*buf32 = readl_relaxed(evtq_addr + idx);
288		idx = (idx + 4) & (prestera_fw_evtq_len(fw, qid) - 1);
289	}
290
291	prestera_fw_evtq_rd_set(fw, qid, idx);
292
293	return i;
294}
295
296static u8 prestera_fw_evtq_pick(struct prestera_fw *fw)
297{
298	int qid;
299
300	for (qid = 0; qid < fw->evt_qnum; qid++) {
301		if (prestera_fw_evtq_avail(fw, qid) >= 4)
302			return qid;
303	}
304
305	return PRESTERA_EVT_QNUM_MAX;
306}
307
308static void prestera_fw_evt_ctl_status_set(struct prestera_fw *fw, u32 val)
309{
310	u32 status = prestera_fw_read(fw, PRESTERA_FW_STATUS_REG);
311
312	u32p_replace_bits(&status, val, PRESTERA_FW_EVT_CTL_STATUS_MASK);
313
314	prestera_fw_write(fw, PRESTERA_FW_STATUS_REG, status);
315}
316
317static void prestera_fw_evt_work_fn(struct work_struct *work)
318{
319	struct prestera_fw *fw;
320	void *msg;
321	u8 qid;
322
323	fw = container_of(work, struct prestera_fw, evt_work);
324	msg = fw->evt_msg;
325
326	prestera_fw_evt_ctl_status_set(fw, PRESTERA_FW_EVT_CTL_STATUS_OFF);
327
328	while ((qid = prestera_fw_evtq_pick(fw)) < PRESTERA_EVT_QNUM_MAX) {
329		u32 idx;
330		u32 len;
331
332		len = prestera_fw_evtq_read32(fw, qid);
333		idx = prestera_fw_read(fw, PRESTERA_EVTQ_RD_IDX_REG(qid));
334
335		WARN_ON(prestera_fw_evtq_avail(fw, qid) < len);
336
337		if (WARN_ON(len > PRESTERA_MSG_MAX_SIZE)) {
338			prestera_fw_evtq_rd_set(fw, qid, idx + len);
339			continue;
340		}
341
342		prestera_fw_evtq_read_buf(fw, qid, msg, len);
343
344		if (fw->dev.recv_msg)
345			fw->dev.recv_msg(&fw->dev, msg, len);
346	}
347
348	prestera_fw_evt_ctl_status_set(fw, PRESTERA_FW_EVT_CTL_STATUS_ON);
349}
350
351static int prestera_fw_wait_reg32(struct prestera_fw *fw, u32 reg, u32 cmp,
352				  unsigned int waitms)
353{
354	u8 __iomem *addr = PRESTERA_FW_REG_ADDR(fw, reg);
355	u32 val;
356
357	return readl_poll_timeout(addr, val, cmp == val,
358				  1 * USEC_PER_MSEC, waitms * USEC_PER_MSEC);
359}
360
361static void prestera_fw_cmdq_lock(struct prestera_fw *fw, u8 qid)
362{
363	mutex_lock(&fw->cmd_queue[qid].cmd_mtx);
364}
365
366static void prestera_fw_cmdq_unlock(struct prestera_fw *fw, u8 qid)
367{
368	mutex_unlock(&fw->cmd_queue[qid].cmd_mtx);
369}
370
371static u32 prestera_fw_cmdq_len(struct prestera_fw *fw, u8 qid)
372{
373	return fw->cmd_queue[qid].len;
374}
375
376static u8 __iomem *prestera_fw_cmdq_buf(struct prestera_fw *fw, u8 qid)
377{
378	return fw->cmd_queue[qid].addr;
379}
380
381static int prestera_fw_cmd_send(struct prestera_fw *fw, int qid,
382				void *in_msg, size_t in_size,
383				void *out_msg, size_t out_size,
384				unsigned int waitms)
385{
386	u32 ret_size;
387	int err;
388
389	if (!waitms)
390		waitms = PRESTERA_FW_CMD_DEFAULT_WAIT_MS;
391
392	if (ALIGN(in_size, 4) > prestera_fw_cmdq_len(fw, qid))
393		return -EMSGSIZE;
394
395	/* wait for finish previous reply from FW */
396	err = prestera_fw_wait_reg32(fw, PRESTERA_CMDQ_RCV_CTL_REG(qid), 0, 30);
397	if (err) {
398		dev_err(fw->dev.dev, "finish reply from FW is timed out\n");
399		return err;
400	}
401
402	prestera_fw_write(fw, PRESTERA_CMDQ_REQ_LEN_REG(qid), in_size);
403
404	memcpy_toio(prestera_fw_cmdq_buf(fw, qid), in_msg, in_size);
405
406	prestera_fw_write(fw, PRESTERA_CMDQ_REQ_CTL_REG(qid),
407			  PRESTERA_CMD_F_REQ_SENT);
408
409	/* wait for reply from FW */
410	err = prestera_fw_wait_reg32(fw, PRESTERA_CMDQ_RCV_CTL_REG(qid),
411				     PRESTERA_CMD_F_REPL_SENT, waitms);
412	if (err) {
413		dev_err(fw->dev.dev, "reply from FW is timed out\n");
414		goto cmd_exit;
415	}
416
417	ret_size = prestera_fw_read(fw, PRESTERA_CMDQ_RCV_LEN_REG(qid));
418	if (ret_size > out_size) {
419		dev_err(fw->dev.dev, "ret_size (%u) > out_len(%zu)\n",
420			ret_size, out_size);
421		err = -EMSGSIZE;
422		goto cmd_exit;
423	}
424
425	memcpy_fromio(out_msg,
426		      prestera_fw_cmdq_buf(fw, qid) + in_size, ret_size);
427
428cmd_exit:
429	prestera_fw_write(fw, PRESTERA_CMDQ_REQ_CTL_REG(qid),
430			  PRESTERA_CMD_F_REPL_RCVD);
431	return err;
432}
433
434static int prestera_fw_send_req(struct prestera_device *dev, int qid,
435				void *in_msg, size_t in_size, void *out_msg,
436				size_t out_size, unsigned int waitms)
437{
438	struct prestera_fw *fw;
439	ssize_t ret;
440
441	fw = container_of(dev, struct prestera_fw, dev);
442
443	prestera_fw_cmdq_lock(fw, qid);
444	ret = prestera_fw_cmd_send(fw, qid, in_msg, in_size, out_msg, out_size,
445				   waitms);
446	prestera_fw_cmdq_unlock(fw, qid);
447
448	return ret;
449}
450
451static int prestera_fw_init(struct prestera_fw *fw)
452{
453	u8 __iomem *base;
454	int err;
455	u8 qid;
456
457	fw->dev.send_req = prestera_fw_send_req;
458	fw->ldr_regs = fw->dev.ctl_regs;
459
460	err = prestera_fw_load(fw);
461	if (err)
462		return err;
463
464	err = prestera_fw_wait_reg32(fw, PRESTERA_FW_READY_REG,
465				     PRESTERA_FW_READY_MAGIC,
466				     PRESTERA_FW_READY_WAIT_MS);
467	if (err) {
468		dev_err(fw->dev.dev, "FW failed to start\n");
469		return err;
470	}
471
472	base = fw->dev.ctl_regs;
473
474	fw->cmd_mbox = base + prestera_fw_read(fw, PRESTERA_CMD_BUF_OFFS_REG);
475	fw->cmd_mbox_len = prestera_fw_read(fw, PRESTERA_CMD_BUF_LEN_REG);
476	fw->cmd_qnum = prestera_fw_read(fw, PRESTERA_CMD_QNUM_REG);
477
478	for (qid = 0; qid < fw->cmd_qnum; qid++) {
479		u32 offs = prestera_fw_read(fw, PRESTERA_CMDQ_OFFS_REG(qid));
480		struct prestera_fw_cmdq *cmdq = &fw->cmd_queue[qid];
481
482		cmdq->len = prestera_fw_read(fw, PRESTERA_CMDQ_LEN_REG(qid));
483		cmdq->addr = fw->cmd_mbox + offs;
484		mutex_init(&cmdq->cmd_mtx);
485	}
486
487	fw->evt_buf = base + prestera_fw_read(fw, PRESTERA_EVT_BUF_OFFS_REG);
488	fw->evt_qnum = prestera_fw_read(fw, PRESTERA_EVT_QNUM_REG);
489	fw->evt_msg = kmalloc(PRESTERA_MSG_MAX_SIZE, GFP_KERNEL);
490	if (!fw->evt_msg)
491		return -ENOMEM;
492
493	for (qid = 0; qid < fw->evt_qnum; qid++) {
494		u32 offs = prestera_fw_read(fw, PRESTERA_EVTQ_OFFS_REG(qid));
495		struct prestera_fw_evtq *evtq = &fw->evt_queue[qid];
496
497		evtq->len = prestera_fw_read(fw, PRESTERA_EVTQ_LEN_REG(qid));
498		evtq->addr = fw->evt_buf + offs;
499	}
500
501	return 0;
502}
503
504static void prestera_fw_uninit(struct prestera_fw *fw)
505{
506	kfree(fw->evt_msg);
507}
508
509static irqreturn_t prestera_pci_irq_handler(int irq, void *dev_id)
510{
511	struct prestera_fw *fw = dev_id;
512
513	if (prestera_fw_read(fw, PRESTERA_RX_STATUS_REG)) {
514		prestera_fw_write(fw, PRESTERA_RX_STATUS_REG, 0);
515
516		if (fw->dev.recv_pkt)
517			fw->dev.recv_pkt(&fw->dev);
518	}
519
520	queue_work(fw->wq, &fw->evt_work);
521
522	return IRQ_HANDLED;
523}
524
525static void prestera_ldr_write(struct prestera_fw *fw, u32 reg, u32 val)
526{
527	writel(val, PRESTERA_LDR_REG_ADDR(fw, reg));
528}
529
530static u32 prestera_ldr_read(struct prestera_fw *fw, u32 reg)
531{
532	return readl(PRESTERA_LDR_REG_ADDR(fw, reg));
533}
534
535static int prestera_ldr_wait_reg32(struct prestera_fw *fw,
536				   u32 reg, u32 cmp, unsigned int waitms)
537{
538	u8 __iomem *addr = PRESTERA_LDR_REG_ADDR(fw, reg);
539	u32 val;
540
541	return readl_poll_timeout(addr, val, cmp == val,
542				  10 * USEC_PER_MSEC, waitms * USEC_PER_MSEC);
543}
544
545static u32 prestera_ldr_wait_buf(struct prestera_fw *fw, size_t len)
546{
547	u8 __iomem *addr = PRESTERA_LDR_REG_ADDR(fw, PRESTERA_LDR_BUF_RD_REG);
548	u32 buf_len = fw->ldr_buf_len;
549	u32 wr_idx = fw->ldr_wr_idx;
550	u32 rd_idx;
551
552	return readl_poll_timeout(addr, rd_idx,
553				 CIRC_SPACE(wr_idx, rd_idx, buf_len) >= len,
554				 1 * USEC_PER_MSEC, 100 * USEC_PER_MSEC);
555}
556
557static int prestera_ldr_wait_dl_finish(struct prestera_fw *fw)
558{
559	u8 __iomem *addr = PRESTERA_LDR_REG_ADDR(fw, PRESTERA_LDR_STATUS_REG);
560	unsigned long mask = ~(PRESTERA_LDR_STATUS_IMG_DL);
561	u32 val;
562	int err;
563
564	err = readl_poll_timeout(addr, val, val & mask, 10 * USEC_PER_MSEC,
565				 PRESTERA_FW_DL_TIMEOUT_MS * USEC_PER_MSEC);
566	if (err) {
567		dev_err(fw->dev.dev, "Timeout to load FW img [state=%d]",
568			prestera_ldr_read(fw, PRESTERA_LDR_STATUS_REG));
569		return err;
570	}
571
572	return 0;
573}
574
575static void prestera_ldr_wr_idx_move(struct prestera_fw *fw, unsigned int n)
576{
577	fw->ldr_wr_idx = (fw->ldr_wr_idx + (n)) & (fw->ldr_buf_len - 1);
578}
579
580static void prestera_ldr_wr_idx_commit(struct prestera_fw *fw)
581{
582	prestera_ldr_write(fw, PRESTERA_LDR_BUF_WR_REG, fw->ldr_wr_idx);
583}
584
585static u8 __iomem *prestera_ldr_wr_ptr(struct prestera_fw *fw)
586{
587	return fw->ldr_ring_buf + fw->ldr_wr_idx;
588}
589
590static int prestera_ldr_send(struct prestera_fw *fw, const u8 *buf, size_t len)
591{
592	int err;
593	int i;
594
595	err = prestera_ldr_wait_buf(fw, len);
596	if (err) {
597		dev_err(fw->dev.dev, "failed wait for sending firmware\n");
598		return err;
599	}
600
601	for (i = 0; i < len; i += 4) {
602		writel_relaxed(*(u32 *)(buf + i), prestera_ldr_wr_ptr(fw));
603		prestera_ldr_wr_idx_move(fw, 4);
604	}
605
606	prestera_ldr_wr_idx_commit(fw);
607	return 0;
608}
609
610static int prestera_ldr_fw_send(struct prestera_fw *fw,
611				const char *img, u32 fw_size)
612{
613	u32 status;
614	u32 pos;
615	int err;
616
617	err = prestera_ldr_wait_reg32(fw, PRESTERA_LDR_STATUS_REG,
618				      PRESTERA_LDR_STATUS_IMG_DL,
619				      5 * MSEC_PER_SEC);
620	if (err) {
621		dev_err(fw->dev.dev, "Loader is not ready to load image\n");
622		return err;
623	}
624
625	for (pos = 0; pos < fw_size; pos += PRESTERA_FW_BLK_SZ) {
626		if (pos + PRESTERA_FW_BLK_SZ > fw_size)
627			break;
628
629		err = prestera_ldr_send(fw, img + pos, PRESTERA_FW_BLK_SZ);
630		if (err)
631			return err;
632	}
633
634	if (pos < fw_size) {
635		err = prestera_ldr_send(fw, img + pos, fw_size - pos);
636		if (err)
637			return err;
638	}
639
640	err = prestera_ldr_wait_dl_finish(fw);
641	if (err)
642		return err;
643
644	status = prestera_ldr_read(fw, PRESTERA_LDR_STATUS_REG);
645
646	switch (status) {
647	case PRESTERA_LDR_STATUS_INVALID_IMG:
648		dev_err(fw->dev.dev, "FW img has bad CRC\n");
649		return -EINVAL;
650	case PRESTERA_LDR_STATUS_NOMEM:
651		dev_err(fw->dev.dev, "Loader has no enough mem\n");
652		return -ENOMEM;
653	}
654
655	return 0;
656}
657
658static void prestera_fw_rev_parse(const struct prestera_fw_header *hdr,
659				  struct prestera_fw_rev *rev)
660{
661	u32 version = be32_to_cpu(hdr->version_value);
662
663	rev->maj = PRESTERA_FW_VER_MAJ(version);
664	rev->min = PRESTERA_FW_VER_MIN(version);
665	rev->sub = PRESTERA_FW_VER_PATCH(version);
666}
667
668static int prestera_fw_rev_check(struct prestera_fw *fw)
669{
670	struct prestera_fw_rev *rev = &fw->dev.fw_rev;
671
672	if (rev->maj == fw->rev_supp.maj && rev->min >= fw->rev_supp.min)
673		return 0;
674
675	dev_err(fw->dev.dev, "Driver supports FW version only '%u.%u.x'",
676		fw->rev_supp.maj, fw->rev_supp.min);
677
678	return -EINVAL;
679}
680
681static int prestera_fw_hdr_parse(struct prestera_fw *fw)
682{
683	struct prestera_fw_rev *rev = &fw->dev.fw_rev;
684	struct prestera_fw_header *hdr;
685	u32 magic;
686
687	hdr = (struct prestera_fw_header *)fw->bin->data;
688
689	magic = be32_to_cpu(hdr->magic_number);
690	if (magic != PRESTERA_FW_HDR_MAGIC) {
691		dev_err(fw->dev.dev, "FW img hdr magic is invalid");
692		return -EINVAL;
693	}
694
695	prestera_fw_rev_parse(hdr, rev);
696
697	dev_info(fw->dev.dev, "FW version '%u.%u.%u'\n",
698		 rev->maj, rev->min, rev->sub);
699
700	return prestera_fw_rev_check(fw);
701}
702
703static const char *prestera_fw_path_fmt_get(struct prestera_fw *fw)
704{
705	switch (fw->pci_dev->device) {
706	case PRESTERA_DEV_ID_98DX3500:
707	case PRESTERA_DEV_ID_98DX3501:
708	case PRESTERA_DEV_ID_98DX3510:
709	case PRESTERA_DEV_ID_98DX3520:
710		return PRESTERA_FW_ARM64_PATH_FMT;
711
712	default:
713		return PRESTERA_FW_PATH_FMT;
714	}
715}
716
717static int prestera_fw_get(struct prestera_fw *fw)
718{
719	int ver_maj = PRESTERA_SUPP_FW_MAJ_VER;
720	int ver_min = PRESTERA_SUPP_FW_MIN_VER;
721	char fw_path[128];
722	int err;
723
724pick_fw_ver:
725	snprintf(fw_path, sizeof(fw_path), prestera_fw_path_fmt_get(fw),
726		 ver_maj, ver_min);
727
728	err = request_firmware_direct(&fw->bin, fw_path, fw->dev.dev);
729	if (err) {
730		if (ver_maj != PRESTERA_PREV_FW_MAJ_VER ||
731		    ver_min != PRESTERA_PREV_FW_MIN_VER) {
732			ver_maj = PRESTERA_PREV_FW_MAJ_VER;
733			ver_min = PRESTERA_PREV_FW_MIN_VER;
734
735			dev_warn(fw->dev.dev,
736				 "missing latest %s firmware, fall-back to previous %u.%u version\n",
737				 fw_path, ver_maj, ver_min);
738
739			goto pick_fw_ver;
740		} else {
741			dev_err(fw->dev.dev, "failed to request previous firmware: %s\n",
742				fw_path);
743			return err;
744		}
745	}
746
747	dev_info(fw->dev.dev, "Loading %s ...", fw_path);
748
749	fw->rev_supp.maj = ver_maj;
750	fw->rev_supp.min = ver_min;
751	fw->rev_supp.sub = 0;
752
753	return 0;
754}
755
756static void prestera_fw_put(struct prestera_fw *fw)
757{
758	release_firmware(fw->bin);
759}
760
761static int prestera_fw_load(struct prestera_fw *fw)
762{
763	size_t hlen = sizeof(struct prestera_fw_header);
764	int err;
765
766	err = prestera_ldr_wait_reg32(fw, PRESTERA_LDR_READY_REG,
767				      PRESTERA_LDR_READY_MAGIC,
768				      5 * MSEC_PER_SEC);
769	if (err) {
770		dev_err(fw->dev.dev, "waiting for FW loader is timed out");
771		return err;
772	}
773
774	fw->ldr_ring_buf = fw->ldr_regs +
775		prestera_ldr_read(fw, PRESTERA_LDR_BUF_OFFS_REG);
776
777	fw->ldr_buf_len =
778		prestera_ldr_read(fw, PRESTERA_LDR_BUF_SIZE_REG);
779
780	fw->ldr_wr_idx = 0;
781
782	err = prestera_fw_get(fw);
783	if (err)
784		return err;
785
786	err = prestera_fw_hdr_parse(fw);
787	if (err) {
788		dev_err(fw->dev.dev, "FW image header is invalid\n");
789		goto out_release;
790	}
791
792	prestera_ldr_write(fw, PRESTERA_LDR_IMG_SIZE_REG, fw->bin->size - hlen);
793	prestera_ldr_write(fw, PRESTERA_LDR_CTL_REG, PRESTERA_LDR_CTL_DL_START);
794
795	err = prestera_ldr_fw_send(fw, fw->bin->data + hlen,
796				   fw->bin->size - hlen);
797
798out_release:
799	prestera_fw_put(fw);
800	return err;
801}
802
803static bool prestera_pci_pp_use_bar2(struct pci_dev *pdev)
804{
805	switch (pdev->device) {
806	case PRESTERA_DEV_ID_98DX7312M:
807	case PRESTERA_DEV_ID_98DX3500:
808	case PRESTERA_DEV_ID_98DX3501:
809	case PRESTERA_DEV_ID_98DX3510:
810	case PRESTERA_DEV_ID_98DX3520:
811		return true;
812
813	default:
814		return false;
815	}
816}
817
818static u32 prestera_pci_pp_bar2_offs(struct pci_dev *pdev)
819{
820	if (pci_resource_len(pdev, 2) == 0x1000000)
821		return 0x0;
822	else
823		return (pci_resource_len(pdev, 2) / 2);
824}
825
826static u32 prestera_pci_fw_bar2_offs(struct pci_dev *pdev)
827{
828	if (pci_resource_len(pdev, 2) == 0x1000000)
829		return 0x400000;
830	else
831		return 0x0;
832}
833
834static int prestera_pci_probe(struct pci_dev *pdev,
835			      const struct pci_device_id *id)
836{
837	const char *driver_name = dev_driver_string(&pdev->dev);
838	u8 __iomem *mem_addr, *pp_addr = NULL;
839	struct prestera_fw *fw;
840	int err;
841
842	err = pcim_enable_device(pdev);
843	if (err) {
844		dev_err(&pdev->dev, "pci_enable_device failed\n");
845		goto err_pci_enable_device;
846	}
847
848	err = pci_request_regions(pdev, driver_name);
849	if (err) {
850		dev_err(&pdev->dev, "pci_request_regions failed\n");
851		goto err_pci_request_regions;
852	}
853
854	err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(30));
855	if (err) {
856		dev_err(&pdev->dev, "fail to set DMA mask\n");
857		goto err_dma_mask;
858	}
859
860	mem_addr = pcim_iomap(pdev, 2, 0);
861	if (!mem_addr) {
862		dev_err(&pdev->dev, "pci mem ioremap failed\n");
863		err = -EIO;
864		goto err_mem_ioremap;
865	}
866
867	/* AC5X devices use second half of BAR2 */
868	if (prestera_pci_pp_use_bar2(pdev)) {
869		pp_addr = mem_addr + prestera_pci_pp_bar2_offs(pdev);
870		mem_addr = mem_addr + prestera_pci_fw_bar2_offs(pdev);
871	} else {
872		pp_addr = pcim_iomap(pdev, 4, 0);
873		if (!pp_addr) {
874			dev_err(&pdev->dev, "pp regs ioremap failed\n");
875			err = -EIO;
876			goto err_pp_ioremap;
877		}
878	}
879
880	pci_set_master(pdev);
881
882	fw = devm_kzalloc(&pdev->dev, sizeof(*fw), GFP_KERNEL);
883	if (!fw) {
884		err = -ENOMEM;
885		goto err_pci_dev_alloc;
886	}
887
888	fw->pci_dev = pdev;
889	fw->dev.ctl_regs = mem_addr;
890	fw->dev.pp_regs = pp_addr;
891	fw->dev.dev = &pdev->dev;
892
893	pci_set_drvdata(pdev, fw);
894
895	err = prestera_fw_init(fw);
896	if (err)
897		goto err_prestera_fw_init;
898
899	dev_info(fw->dev.dev, "Prestera FW is ready\n");
900
901	fw->wq = alloc_workqueue("prestera_fw_wq", WQ_HIGHPRI, 1);
902	if (!fw->wq) {
903		err = -ENOMEM;
904		goto err_wq_alloc;
905	}
906
907	INIT_WORK(&fw->evt_work, prestera_fw_evt_work_fn);
908
909	err = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI);
910	if (err < 0) {
911		dev_err(&pdev->dev, "MSI IRQ init failed\n");
912		goto err_irq_alloc;
913	}
914
915	err = request_irq(pci_irq_vector(pdev, 0), prestera_pci_irq_handler,
916			  0, driver_name, fw);
917	if (err) {
918		dev_err(&pdev->dev, "fail to request IRQ\n");
919		goto err_request_irq;
920	}
921
922	err = prestera_device_register(&fw->dev);
923	if (err)
924		goto err_prestera_dev_register;
925
926	return 0;
927
928err_prestera_dev_register:
929	free_irq(pci_irq_vector(pdev, 0), fw);
930err_request_irq:
931	pci_free_irq_vectors(pdev);
932err_irq_alloc:
933	destroy_workqueue(fw->wq);
934err_wq_alloc:
935	prestera_fw_uninit(fw);
936err_prestera_fw_init:
937err_pci_dev_alloc:
938err_pp_ioremap:
939err_mem_ioremap:
940err_dma_mask:
941	pci_release_regions(pdev);
942err_pci_request_regions:
943err_pci_enable_device:
944	return err;
945}
946
947static void prestera_pci_remove(struct pci_dev *pdev)
948{
949	struct prestera_fw *fw = pci_get_drvdata(pdev);
950
951	prestera_device_unregister(&fw->dev);
952	free_irq(pci_irq_vector(pdev, 0), fw);
953	pci_free_irq_vectors(pdev);
954	destroy_workqueue(fw->wq);
955	prestera_fw_uninit(fw);
956	pci_release_regions(pdev);
957}
958
959static const struct pci_device_id prestera_pci_devices[] = {
960	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, PRESTERA_DEV_ID_AC3X_98DX_55) },
961	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, PRESTERA_DEV_ID_AC3X_98DX_65) },
962	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, PRESTERA_DEV_ID_ALDRIN2) },
963	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, PRESTERA_DEV_ID_98DX7312M) },
964	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, PRESTERA_DEV_ID_98DX3500) },
965	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, PRESTERA_DEV_ID_98DX3501) },
966	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, PRESTERA_DEV_ID_98DX3510) },
967	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, PRESTERA_DEV_ID_98DX3520) },
968	{ }
969};
970MODULE_DEVICE_TABLE(pci, prestera_pci_devices);
971
972static struct pci_driver prestera_pci_driver = {
973	.name     = "Prestera DX",
974	.id_table = prestera_pci_devices,
975	.probe    = prestera_pci_probe,
976	.remove   = prestera_pci_remove,
977};
978module_pci_driver(prestera_pci_driver);
979
980MODULE_LICENSE("Dual BSD/GPL");
981MODULE_DESCRIPTION("Marvell Prestera switch PCI interface");