1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Marvell NFC driver: Firmware downloader
4 *
5 * Copyright (C) 2015, Marvell International Ltd.
6 */
7
8#include <linux/module.h>
9#include <asm/unaligned.h>
10#include <linux/firmware.h>
11#include <linux/nfc.h>
12#include <net/nfc/nci.h>
13#include <net/nfc/nci_core.h>
14#include "nfcmrvl.h"
15
16#define FW_DNLD_TIMEOUT			15000
17
18#define NCI_OP_PROPRIETARY_BOOT_CMD	nci_opcode_pack(NCI_GID_PROPRIETARY, \
19							NCI_OP_PROP_BOOT_CMD)
20
21/* FW download states */
22
23enum {
24	STATE_RESET = 0,
25	STATE_INIT,
26	STATE_SET_REF_CLOCK,
27	STATE_SET_HI_CONFIG,
28	STATE_OPEN_LC,
29	STATE_FW_DNLD,
30	STATE_CLOSE_LC,
31	STATE_BOOT
32};
33
34enum {
35	SUBSTATE_WAIT_COMMAND = 0,
36	SUBSTATE_WAIT_ACK_CREDIT,
37	SUBSTATE_WAIT_NACK_CREDIT,
38	SUBSTATE_WAIT_DATA_CREDIT,
39};
40
41/*
42 * Patterns for responses
43 */
44
45static const uint8_t nci_pattern_core_reset_ntf[] = {
46	0x60, 0x00, 0x02, 0xA0, 0x01
47};
48
49static const uint8_t nci_pattern_core_init_rsp[] = {
50	0x40, 0x01, 0x11
51};
52
53static const uint8_t nci_pattern_core_set_config_rsp[] = {
54	0x40, 0x02, 0x02, 0x00, 0x00
55};
56
57static const uint8_t nci_pattern_core_conn_create_rsp[] = {
58	0x40, 0x04, 0x04, 0x00
59};
60
61static const uint8_t nci_pattern_core_conn_close_rsp[] = {
62	0x40, 0x05, 0x01, 0x00
63};
64
65static const uint8_t nci_pattern_core_conn_credits_ntf[] = {
66	0x60, 0x06, 0x03, 0x01, NCI_CORE_LC_CONNID_PROP_FW_DL, 0x01
67};
68
69static const uint8_t nci_pattern_proprietary_boot_rsp[] = {
70	0x4F, 0x3A, 0x01, 0x00
71};
72
73static struct sk_buff *alloc_lc_skb(struct nfcmrvl_private *priv, uint8_t plen)
74{
75	struct sk_buff *skb;
76	struct nci_data_hdr *hdr;
77
78	skb = nci_skb_alloc(priv->ndev, (NCI_DATA_HDR_SIZE + plen), GFP_KERNEL);
79	if (!skb)
80		return NULL;
81
82	hdr = skb_put(skb, NCI_DATA_HDR_SIZE);
83	hdr->conn_id = NCI_CORE_LC_CONNID_PROP_FW_DL;
84	hdr->rfu = 0;
85	hdr->plen = plen;
86
87	nci_mt_set((__u8 *)hdr, NCI_MT_DATA_PKT);
88	nci_pbf_set((__u8 *)hdr, NCI_PBF_LAST);
89
90	return skb;
91}
92
93static void fw_dnld_over(struct nfcmrvl_private *priv, u32 error)
94{
95	if (priv->fw_dnld.fw) {
96		release_firmware(priv->fw_dnld.fw);
97		priv->fw_dnld.fw = NULL;
98		priv->fw_dnld.header = NULL;
99		priv->fw_dnld.binary_config = NULL;
100	}
101
102	atomic_set(&priv->ndev->cmd_cnt, 0);
103
104	if (timer_pending(&priv->ndev->cmd_timer))
105		del_timer_sync(&priv->ndev->cmd_timer);
106
107	if (timer_pending(&priv->fw_dnld.timer))
108		del_timer_sync(&priv->fw_dnld.timer);
109
110	nfc_info(priv->dev, "FW loading over (%d)]\n", error);
111
112	if (error != 0) {
113		/* failed, halt the chip to avoid power consumption */
114		nfcmrvl_chip_halt(priv);
115	}
116
117	nfc_fw_download_done(priv->ndev->nfc_dev, priv->fw_dnld.name, error);
118}
119
120static void fw_dnld_timeout(struct timer_list *t)
121{
122	struct nfcmrvl_private *priv = from_timer(priv, t, fw_dnld.timer);
123
124	nfc_err(priv->dev, "FW loading timeout");
125	priv->fw_dnld.state = STATE_RESET;
126	fw_dnld_over(priv, -ETIMEDOUT);
127}
128
129static int process_state_reset(struct nfcmrvl_private *priv,
130			       const struct sk_buff *skb)
131{
132	if (sizeof(nci_pattern_core_reset_ntf) != skb->len ||
133	    memcmp(skb->data, nci_pattern_core_reset_ntf,
134		   sizeof(nci_pattern_core_reset_ntf)))
135		return -EINVAL;
136
137	nfc_info(priv->dev, "BootROM reset, start fw download\n");
138
139	/* Start FW download state machine */
140	priv->fw_dnld.state = STATE_INIT;
141	nci_send_cmd(priv->ndev, NCI_OP_CORE_INIT_CMD, 0, NULL);
142
143	return 0;
144}
145
146static int process_state_init(struct nfcmrvl_private *priv,
147			      const struct sk_buff *skb)
148{
149	struct nci_core_set_config_cmd cmd;
150
151	if (sizeof(nci_pattern_core_init_rsp) >= skb->len ||
152	    memcmp(skb->data, nci_pattern_core_init_rsp,
153		   sizeof(nci_pattern_core_init_rsp)))
154		return -EINVAL;
155
156	cmd.num_params = 1;
157	cmd.param.id = NFCMRVL_PROP_REF_CLOCK;
158	cmd.param.len = 4;
159	memcpy(cmd.param.val, &priv->fw_dnld.header->ref_clock, 4);
160
161	nci_send_cmd(priv->ndev, NCI_OP_CORE_SET_CONFIG_CMD, 3 + cmd.param.len,
162		     &cmd);
163
164	priv->fw_dnld.state = STATE_SET_REF_CLOCK;
165	return 0;
166}
167
168static void create_lc(struct nfcmrvl_private *priv)
169{
170	uint8_t param[2] = { NCI_CORE_LC_PROP_FW_DL, 0x0 };
171
172	priv->fw_dnld.state = STATE_OPEN_LC;
173	nci_send_cmd(priv->ndev, NCI_OP_CORE_CONN_CREATE_CMD, 2, param);
174}
175
176static int process_state_set_ref_clock(struct nfcmrvl_private *priv,
177				       const struct sk_buff *skb)
178{
179	struct nci_core_set_config_cmd cmd;
180
181	if (sizeof(nci_pattern_core_set_config_rsp) != skb->len ||
182	    memcmp(skb->data, nci_pattern_core_set_config_rsp, skb->len))
183		return -EINVAL;
184
185	cmd.num_params = 1;
186	cmd.param.id = NFCMRVL_PROP_SET_HI_CONFIG;
187
188	switch (priv->phy) {
189	case NFCMRVL_PHY_UART:
190		cmd.param.len = 5;
191		memcpy(cmd.param.val,
192		       &priv->fw_dnld.binary_config->uart.baudrate,
193		       4);
194		cmd.param.val[4] =
195			priv->fw_dnld.binary_config->uart.flow_control;
196		break;
197	case NFCMRVL_PHY_I2C:
198		cmd.param.len = 5;
199		memcpy(cmd.param.val,
200		       &priv->fw_dnld.binary_config->i2c.clk,
201		       4);
202		cmd.param.val[4] = 0;
203		break;
204	case NFCMRVL_PHY_SPI:
205		cmd.param.len = 5;
206		memcpy(cmd.param.val,
207		       &priv->fw_dnld.binary_config->spi.clk,
208		       4);
209		cmd.param.val[4] = 0;
210		break;
211	default:
212		create_lc(priv);
213		return 0;
214	}
215
216	priv->fw_dnld.state = STATE_SET_HI_CONFIG;
217	nci_send_cmd(priv->ndev, NCI_OP_CORE_SET_CONFIG_CMD, 3 + cmd.param.len,
218		     &cmd);
219	return 0;
220}
221
222static int process_state_set_hi_config(struct nfcmrvl_private *priv,
223				       const struct sk_buff *skb)
224{
225	if (sizeof(nci_pattern_core_set_config_rsp) != skb->len ||
226	    memcmp(skb->data, nci_pattern_core_set_config_rsp, skb->len))
227		return -EINVAL;
228
229	create_lc(priv);
230	return 0;
231}
232
233static int process_state_open_lc(struct nfcmrvl_private *priv,
234				 const struct sk_buff *skb)
235{
236	if (sizeof(nci_pattern_core_conn_create_rsp) >= skb->len ||
237	    memcmp(skb->data, nci_pattern_core_conn_create_rsp,
238		   sizeof(nci_pattern_core_conn_create_rsp)))
239		return -EINVAL;
240
241	priv->fw_dnld.state = STATE_FW_DNLD;
242	priv->fw_dnld.substate = SUBSTATE_WAIT_COMMAND;
243	priv->fw_dnld.offset = priv->fw_dnld.binary_config->offset;
244	return 0;
245}
246
247static int process_state_fw_dnld(struct nfcmrvl_private *priv,
248				 struct sk_buff *skb)
249{
250	uint16_t len;
251	uint16_t comp_len;
252	struct sk_buff *out_skb;
253
254	switch (priv->fw_dnld.substate) {
255	case SUBSTATE_WAIT_COMMAND:
256		/*
257		 * Command format:
258		 * B0..2: NCI header
259		 * B3   : Helper command (0xA5)
260		 * B4..5: le16 data size
261		 * B6..7: le16 data size complement (~)
262		 * B8..N: payload
263		 */
264
265		/* Remove NCI HDR */
266		skb_pull(skb, 3);
267		if (skb->data[0] != HELPER_CMD_PACKET_FORMAT || skb->len != 5) {
268			nfc_err(priv->dev, "bad command");
269			return -EINVAL;
270		}
271		skb_pull(skb, 1);
272		len = get_unaligned_le16(skb->data);
273		skb_pull(skb, 2);
274		comp_len = get_unaligned_le16(skb->data);
275		memcpy(&comp_len, skb->data, 2);
276		skb_pull(skb, 2);
277		if (((~len) & 0xFFFF) != comp_len) {
278			nfc_err(priv->dev, "bad len complement: %x %x %x",
279				len, comp_len, (~len & 0xFFFF));
280			out_skb = alloc_lc_skb(priv, 1);
281			if (!out_skb)
282				return -ENOMEM;
283			skb_put_u8(out_skb, 0xBF);
284			nci_send_frame(priv->ndev, out_skb);
285			priv->fw_dnld.substate = SUBSTATE_WAIT_NACK_CREDIT;
286			return 0;
287		}
288		priv->fw_dnld.chunk_len = len;
289		out_skb = alloc_lc_skb(priv, 1);
290		if (!out_skb)
291			return -ENOMEM;
292		skb_put_u8(out_skb, HELPER_ACK_PACKET_FORMAT);
293		nci_send_frame(priv->ndev, out_skb);
294		priv->fw_dnld.substate = SUBSTATE_WAIT_ACK_CREDIT;
295		break;
296
297	case SUBSTATE_WAIT_ACK_CREDIT:
298		if (sizeof(nci_pattern_core_conn_credits_ntf) != skb->len ||
299		    memcmp(nci_pattern_core_conn_credits_ntf, skb->data,
300			   skb->len)) {
301			nfc_err(priv->dev, "bad packet: waiting for credit");
302			return -EINVAL;
303		}
304		if (priv->fw_dnld.chunk_len == 0) {
305			/* FW Loading is done */
306			uint8_t conn_id = NCI_CORE_LC_CONNID_PROP_FW_DL;
307
308			priv->fw_dnld.state = STATE_CLOSE_LC;
309			nci_send_cmd(priv->ndev, NCI_OP_CORE_CONN_CLOSE_CMD,
310				     1, &conn_id);
311		} else {
312			out_skb = alloc_lc_skb(priv, priv->fw_dnld.chunk_len);
313			if (!out_skb)
314				return -ENOMEM;
315			skb_put_data(out_skb,
316				     ((uint8_t *)priv->fw_dnld.fw->data) + priv->fw_dnld.offset,
317				     priv->fw_dnld.chunk_len);
318			nci_send_frame(priv->ndev, out_skb);
319			priv->fw_dnld.substate = SUBSTATE_WAIT_DATA_CREDIT;
320		}
321		break;
322
323	case SUBSTATE_WAIT_DATA_CREDIT:
324		if (sizeof(nci_pattern_core_conn_credits_ntf) != skb->len ||
325		    memcmp(nci_pattern_core_conn_credits_ntf, skb->data,
326			    skb->len)) {
327			nfc_err(priv->dev, "bad packet: waiting for credit");
328			return -EINVAL;
329		}
330		priv->fw_dnld.offset += priv->fw_dnld.chunk_len;
331		priv->fw_dnld.chunk_len = 0;
332		priv->fw_dnld.substate = SUBSTATE_WAIT_COMMAND;
333		break;
334
335	case SUBSTATE_WAIT_NACK_CREDIT:
336		if (sizeof(nci_pattern_core_conn_credits_ntf) != skb->len ||
337		    memcmp(nci_pattern_core_conn_credits_ntf, skb->data,
338			    skb->len)) {
339			nfc_err(priv->dev, "bad packet: waiting for credit");
340			return -EINVAL;
341		}
342		priv->fw_dnld.substate = SUBSTATE_WAIT_COMMAND;
343		break;
344	}
345	return 0;
346}
347
348static int process_state_close_lc(struct nfcmrvl_private *priv,
349				  const struct sk_buff *skb)
350{
351	if (sizeof(nci_pattern_core_conn_close_rsp) != skb->len ||
352	    memcmp(skb->data, nci_pattern_core_conn_close_rsp, skb->len))
353		return -EINVAL;
354
355	priv->fw_dnld.state = STATE_BOOT;
356	nci_send_cmd(priv->ndev, NCI_OP_PROPRIETARY_BOOT_CMD, 0, NULL);
357	return 0;
358}
359
360static int process_state_boot(struct nfcmrvl_private *priv,
361			      const struct sk_buff *skb)
362{
363	if (sizeof(nci_pattern_proprietary_boot_rsp) != skb->len ||
364	    memcmp(skb->data, nci_pattern_proprietary_boot_rsp, skb->len))
365		return -EINVAL;
366
367	/*
368	 * Update HI config to use the right configuration for the next
369	 * data exchanges.
370	 */
371	priv->if_ops->nci_update_config(priv,
372					&priv->fw_dnld.binary_config->config);
373
374	if (priv->fw_dnld.binary_config == &priv->fw_dnld.header->helper) {
375		/*
376		 * This is the case where an helper was needed and we have
377		 * uploaded it. Now we have to wait the next RESET NTF to start
378		 * FW download.
379		 */
380		priv->fw_dnld.state = STATE_RESET;
381		priv->fw_dnld.binary_config = &priv->fw_dnld.header->firmware;
382		nfc_info(priv->dev, "FW loading: helper loaded");
383	} else {
384		nfc_info(priv->dev, "FW loading: firmware loaded");
385		fw_dnld_over(priv, 0);
386	}
387	return 0;
388}
389
390static void fw_dnld_rx_work(struct work_struct *work)
391{
392	int ret;
393	struct sk_buff *skb;
394	struct nfcmrvl_fw_dnld *fw_dnld = container_of(work,
395						       struct nfcmrvl_fw_dnld,
396						       rx_work);
397	struct nfcmrvl_private *priv = container_of(fw_dnld,
398						    struct nfcmrvl_private,
399						    fw_dnld);
400
401	while ((skb = skb_dequeue(&fw_dnld->rx_q))) {
402		nfc_send_to_raw_sock(priv->ndev->nfc_dev, skb,
403				     RAW_PAYLOAD_NCI, NFC_DIRECTION_RX);
404		switch (fw_dnld->state) {
405		case STATE_RESET:
406			ret = process_state_reset(priv, skb);
407			break;
408		case STATE_INIT:
409			ret = process_state_init(priv, skb);
410			break;
411		case STATE_SET_REF_CLOCK:
412			ret = process_state_set_ref_clock(priv, skb);
413			break;
414		case STATE_SET_HI_CONFIG:
415			ret = process_state_set_hi_config(priv, skb);
416			break;
417		case STATE_OPEN_LC:
418			ret = process_state_open_lc(priv, skb);
419			break;
420		case STATE_FW_DNLD:
421			ret = process_state_fw_dnld(priv, skb);
422			break;
423		case STATE_CLOSE_LC:
424			ret = process_state_close_lc(priv, skb);
425			break;
426		case STATE_BOOT:
427			ret = process_state_boot(priv, skb);
428			break;
429		default:
430			ret = -EFAULT;
431		}
432
433		kfree_skb(skb);
434
435		if (ret != 0) {
436			nfc_err(priv->dev, "FW loading error");
437			fw_dnld_over(priv, ret);
438			break;
439		}
440	}
441}
442
443int nfcmrvl_fw_dnld_init(struct nfcmrvl_private *priv)
444{
445	char name[32];
446
447	INIT_WORK(&priv->fw_dnld.rx_work, fw_dnld_rx_work);
448	snprintf(name, sizeof(name), "%s_nfcmrvl_fw_dnld_rx_wq",
449		 dev_name(&priv->ndev->nfc_dev->dev));
450	priv->fw_dnld.rx_wq = create_singlethread_workqueue(name);
451	if (!priv->fw_dnld.rx_wq)
452		return -ENOMEM;
453	skb_queue_head_init(&priv->fw_dnld.rx_q);
454	return 0;
455}
456
457void nfcmrvl_fw_dnld_deinit(struct nfcmrvl_private *priv)
458{
459	destroy_workqueue(priv->fw_dnld.rx_wq);
460}
461
462void nfcmrvl_fw_dnld_recv_frame(struct nfcmrvl_private *priv,
463				struct sk_buff *skb)
464{
465	/* Discard command timer */
466	if (timer_pending(&priv->ndev->cmd_timer))
467		del_timer_sync(&priv->ndev->cmd_timer);
468
469	/* Allow next command */
470	atomic_set(&priv->ndev->cmd_cnt, 1);
471
472	/* Queue and trigger rx work */
473	skb_queue_tail(&priv->fw_dnld.rx_q, skb);
474	queue_work(priv->fw_dnld.rx_wq, &priv->fw_dnld.rx_work);
475}
476
477void nfcmrvl_fw_dnld_abort(struct nfcmrvl_private *priv)
478{
479	fw_dnld_over(priv, -EHOSTDOWN);
480}
481
482int nfcmrvl_fw_dnld_start(struct nci_dev *ndev, const char *firmware_name)
483{
484	struct nfcmrvl_private *priv = nci_get_drvdata(ndev);
485	struct nfcmrvl_fw_dnld *fw_dnld = &priv->fw_dnld;
486	int res;
487
488	if (!priv->support_fw_dnld)
489		return -ENOTSUPP;
490
491	if (!firmware_name || !firmware_name[0])
492		return -EINVAL;
493
494	strcpy(fw_dnld->name, firmware_name);
495
496	/*
497	 * Retrieve FW binary file and parse it to initialize FW download
498	 * state machine.
499	 */
500
501	/* Retrieve FW binary */
502	res = request_firmware(&fw_dnld->fw, firmware_name,
503			       &ndev->nfc_dev->dev);
504	if (res < 0) {
505		nfc_err(priv->dev, "failed to retrieve FW %s", firmware_name);
506		return -ENOENT;
507	}
508
509	fw_dnld->header = (const struct nfcmrvl_fw *) priv->fw_dnld.fw->data;
510
511	if (fw_dnld->header->magic != NFCMRVL_FW_MAGIC ||
512	    fw_dnld->header->phy != priv->phy) {
513		nfc_err(priv->dev, "bad firmware binary %s magic=0x%x phy=%d",
514			firmware_name, fw_dnld->header->magic,
515			fw_dnld->header->phy);
516		release_firmware(fw_dnld->fw);
517		fw_dnld->header = NULL;
518		return -EINVAL;
519	}
520
521	if (fw_dnld->header->helper.offset != 0) {
522		nfc_info(priv->dev, "loading helper");
523		fw_dnld->binary_config = &fw_dnld->header->helper;
524	} else {
525		nfc_info(priv->dev, "loading firmware");
526		fw_dnld->binary_config = &fw_dnld->header->firmware;
527	}
528
529	/* Configure a timer for timeout */
530	timer_setup(&priv->fw_dnld.timer, fw_dnld_timeout, 0);
531	mod_timer(&priv->fw_dnld.timer,
532		  jiffies + msecs_to_jiffies(FW_DNLD_TIMEOUT));
533
534	/* Ronfigure HI to be sure that it is the bootrom values */
535	priv->if_ops->nci_update_config(priv,
536					&fw_dnld->header->bootrom.config);
537
538	/* Allow first command */
539	atomic_set(&priv->ndev->cmd_cnt, 1);
540
541	/* First, reset the chip */
542	priv->fw_dnld.state = STATE_RESET;
543	nfcmrvl_chip_reset(priv);
544
545	/* Now wait for CORE_RESET_NTF or timeout */
546
547	return 0;
548}
549