1 // SPDX-License-Identifier: GPL-2.0-only
3 * Marvell NFC driver: Firmware downloader
5 * Copyright (C) 2015, Marvell International Ltd.
8 #include <linux/module.h>
9 #include <linux/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>
16 #define FW_DNLD_TIMEOUT 15000
18 #define NCI_OP_PROPRIETARY_BOOT_CMD nci_opcode_pack(NCI_GID_PROPRIETARY, \
21 /* FW download states */
35 SUBSTATE_WAIT_COMMAND
= 0,
36 SUBSTATE_WAIT_ACK_CREDIT
,
37 SUBSTATE_WAIT_NACK_CREDIT
,
38 SUBSTATE_WAIT_DATA_CREDIT
,
42 * Patterns for responses
45 static const uint8_t nci_pattern_core_reset_ntf
[] = {
46 0x60, 0x00, 0x02, 0xA0, 0x01
49 static const uint8_t nci_pattern_core_init_rsp
[] = {
53 static const uint8_t nci_pattern_core_set_config_rsp
[] = {
54 0x40, 0x02, 0x02, 0x00, 0x00
57 static const uint8_t nci_pattern_core_conn_create_rsp
[] = {
58 0x40, 0x04, 0x04, 0x00
61 static const uint8_t nci_pattern_core_conn_close_rsp
[] = {
62 0x40, 0x05, 0x01, 0x00
65 static const uint8_t nci_pattern_core_conn_credits_ntf
[] = {
66 0x60, 0x06, 0x03, 0x01, NCI_CORE_LC_CONNID_PROP_FW_DL
, 0x01
69 static const uint8_t nci_pattern_proprietary_boot_rsp
[] = {
70 0x4F, 0x3A, 0x01, 0x00
73 static struct sk_buff
*alloc_lc_skb(struct nfcmrvl_private
*priv
, uint8_t plen
)
76 struct nci_data_hdr
*hdr
;
78 skb
= nci_skb_alloc(priv
->ndev
, (NCI_DATA_HDR_SIZE
+ plen
), GFP_KERNEL
);
82 hdr
= skb_put(skb
, NCI_DATA_HDR_SIZE
);
83 hdr
->conn_id
= NCI_CORE_LC_CONNID_PROP_FW_DL
;
87 nci_mt_set((__u8
*)hdr
, NCI_MT_DATA_PKT
);
88 nci_pbf_set((__u8
*)hdr
, NCI_PBF_LAST
);
93 static void fw_dnld_over(struct nfcmrvl_private
*priv
, u32 error
)
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
;
102 atomic_set(&priv
->ndev
->cmd_cnt
, 0);
104 if (timer_pending(&priv
->ndev
->cmd_timer
))
105 del_timer_sync(&priv
->ndev
->cmd_timer
);
107 if (timer_pending(&priv
->fw_dnld
.timer
))
108 del_timer_sync(&priv
->fw_dnld
.timer
);
110 nfc_info(priv
->dev
, "FW loading over (%d)]\n", error
);
113 /* failed, halt the chip to avoid power consumption */
114 nfcmrvl_chip_halt(priv
);
117 nfc_fw_download_done(priv
->ndev
->nfc_dev
, priv
->fw_dnld
.name
, error
);
120 static void fw_dnld_timeout(struct timer_list
*t
)
122 struct nfcmrvl_private
*priv
= from_timer(priv
, t
, fw_dnld
.timer
);
124 nfc_err(priv
->dev
, "FW loading timeout");
125 priv
->fw_dnld
.state
= STATE_RESET
;
126 fw_dnld_over(priv
, -ETIMEDOUT
);
129 static int process_state_reset(struct nfcmrvl_private
*priv
,
130 const struct sk_buff
*skb
)
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
)))
137 nfc_info(priv
->dev
, "BootROM reset, start fw download\n");
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
);
146 static int process_state_init(struct nfcmrvl_private
*priv
,
147 const struct sk_buff
*skb
)
149 struct nci_core_set_config_cmd cmd
;
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
)))
157 cmd
.param
.id
= NFCMRVL_PROP_REF_CLOCK
;
159 memcpy(cmd
.param
.val
, &priv
->fw_dnld
.header
->ref_clock
, 4);
161 nci_send_cmd(priv
->ndev
, NCI_OP_CORE_SET_CONFIG_CMD
, 3 + cmd
.param
.len
,
164 priv
->fw_dnld
.state
= STATE_SET_REF_CLOCK
;
168 static void create_lc(struct nfcmrvl_private
*priv
)
170 uint8_t param
[2] = { NCI_CORE_LC_PROP_FW_DL
, 0x0 };
172 priv
->fw_dnld
.state
= STATE_OPEN_LC
;
173 nci_send_cmd(priv
->ndev
, NCI_OP_CORE_CONN_CREATE_CMD
, 2, param
);
176 static int process_state_set_ref_clock(struct nfcmrvl_private
*priv
,
177 const struct sk_buff
*skb
)
179 struct nci_core_set_config_cmd cmd
;
181 if (sizeof(nci_pattern_core_set_config_rsp
) != skb
->len
||
182 memcmp(skb
->data
, nci_pattern_core_set_config_rsp
, skb
->len
))
186 cmd
.param
.id
= NFCMRVL_PROP_SET_HI_CONFIG
;
189 case NFCMRVL_PHY_UART
:
191 memcpy(cmd
.param
.val
,
192 &priv
->fw_dnld
.binary_config
->uart
.baudrate
,
195 priv
->fw_dnld
.binary_config
->uart
.flow_control
;
197 case NFCMRVL_PHY_I2C
:
199 memcpy(cmd
.param
.val
,
200 &priv
->fw_dnld
.binary_config
->i2c
.clk
,
202 cmd
.param
.val
[4] = 0;
204 case NFCMRVL_PHY_SPI
:
206 memcpy(cmd
.param
.val
,
207 &priv
->fw_dnld
.binary_config
->spi
.clk
,
209 cmd
.param
.val
[4] = 0;
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
,
222 static int process_state_set_hi_config(struct nfcmrvl_private
*priv
,
223 const struct sk_buff
*skb
)
225 if (sizeof(nci_pattern_core_set_config_rsp
) != skb
->len
||
226 memcmp(skb
->data
, nci_pattern_core_set_config_rsp
, skb
->len
))
233 static int process_state_open_lc(struct nfcmrvl_private
*priv
,
234 const struct sk_buff
*skb
)
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
)))
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
;
247 static int process_state_fw_dnld(struct nfcmrvl_private
*priv
,
252 struct sk_buff
*out_skb
;
254 switch (priv
->fw_dnld
.substate
) {
255 case SUBSTATE_WAIT_COMMAND
:
259 * B3 : Helper command (0xA5)
260 * B4..5: le16 data size
261 * B6..7: le16 data size complement (~)
267 if (skb
->data
[0] != HELPER_CMD_PACKET_FORMAT
|| skb
->len
!= 5) {
268 nfc_err(priv
->dev
, "bad command");
272 len
= get_unaligned_le16(skb
->data
);
274 comp_len
= get_unaligned_le16(skb
->data
);
275 memcpy(&comp_len
, skb
->data
, 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);
283 skb_put_u8(out_skb
, 0xBF);
284 nci_send_frame(priv
->ndev
, out_skb
);
285 priv
->fw_dnld
.substate
= SUBSTATE_WAIT_NACK_CREDIT
;
288 priv
->fw_dnld
.chunk_len
= len
;
289 out_skb
= alloc_lc_skb(priv
, 1);
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
;
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
,
301 nfc_err(priv
->dev
, "bad packet: waiting for credit");
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
;
308 priv
->fw_dnld
.state
= STATE_CLOSE_LC
;
309 nci_send_cmd(priv
->ndev
, NCI_OP_CORE_CONN_CLOSE_CMD
,
312 out_skb
= alloc_lc_skb(priv
, priv
->fw_dnld
.chunk_len
);
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
;
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
,
327 nfc_err(priv
->dev
, "bad packet: waiting for credit");
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
;
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
,
339 nfc_err(priv
->dev
, "bad packet: waiting for credit");
342 priv
->fw_dnld
.substate
= SUBSTATE_WAIT_COMMAND
;
348 static int process_state_close_lc(struct nfcmrvl_private
*priv
,
349 const struct sk_buff
*skb
)
351 if (sizeof(nci_pattern_core_conn_close_rsp
) != skb
->len
||
352 memcmp(skb
->data
, nci_pattern_core_conn_close_rsp
, skb
->len
))
355 priv
->fw_dnld
.state
= STATE_BOOT
;
356 nci_send_cmd(priv
->ndev
, NCI_OP_PROPRIETARY_BOOT_CMD
, 0, NULL
);
360 static int process_state_boot(struct nfcmrvl_private
*priv
,
361 const struct sk_buff
*skb
)
363 if (sizeof(nci_pattern_proprietary_boot_rsp
) != skb
->len
||
364 memcmp(skb
->data
, nci_pattern_proprietary_boot_rsp
, skb
->len
))
368 * Update HI config to use the right configuration for the next
371 priv
->if_ops
->nci_update_config(priv
,
372 &priv
->fw_dnld
.binary_config
->config
);
374 if (priv
->fw_dnld
.binary_config
== &priv
->fw_dnld
.header
->helper
) {
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
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");
384 nfc_info(priv
->dev
, "FW loading: firmware loaded");
385 fw_dnld_over(priv
, 0);
390 static void fw_dnld_rx_work(struct work_struct
*work
)
394 struct nfcmrvl_fw_dnld
*fw_dnld
= container_of(work
,
395 struct nfcmrvl_fw_dnld
,
397 struct nfcmrvl_private
*priv
= container_of(fw_dnld
,
398 struct nfcmrvl_private
,
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
) {
406 ret
= process_state_reset(priv
, skb
);
409 ret
= process_state_init(priv
, skb
);
411 case STATE_SET_REF_CLOCK
:
412 ret
= process_state_set_ref_clock(priv
, skb
);
414 case STATE_SET_HI_CONFIG
:
415 ret
= process_state_set_hi_config(priv
, skb
);
418 ret
= process_state_open_lc(priv
, skb
);
421 ret
= process_state_fw_dnld(priv
, skb
);
424 ret
= process_state_close_lc(priv
, skb
);
427 ret
= process_state_boot(priv
, skb
);
436 nfc_err(priv
->dev
, "FW loading error");
437 fw_dnld_over(priv
, ret
);
443 int nfcmrvl_fw_dnld_init(struct nfcmrvl_private
*priv
)
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
)
453 skb_queue_head_init(&priv
->fw_dnld
.rx_q
);
457 void nfcmrvl_fw_dnld_deinit(struct nfcmrvl_private
*priv
)
459 destroy_workqueue(priv
->fw_dnld
.rx_wq
);
462 void nfcmrvl_fw_dnld_recv_frame(struct nfcmrvl_private
*priv
,
465 /* Discard command timer */
466 if (timer_pending(&priv
->ndev
->cmd_timer
))
467 del_timer_sync(&priv
->ndev
->cmd_timer
);
469 /* Allow next command */
470 atomic_set(&priv
->ndev
->cmd_cnt
, 1);
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
);
477 void nfcmrvl_fw_dnld_abort(struct nfcmrvl_private
*priv
)
479 fw_dnld_over(priv
, -EHOSTDOWN
);
482 int nfcmrvl_fw_dnld_start(struct nci_dev
*ndev
, const char *firmware_name
)
484 struct nfcmrvl_private
*priv
= nci_get_drvdata(ndev
);
485 struct nfcmrvl_fw_dnld
*fw_dnld
= &priv
->fw_dnld
;
488 if (!priv
->support_fw_dnld
)
491 if (!firmware_name
|| !firmware_name
[0])
494 strcpy(fw_dnld
->name
, firmware_name
);
497 * Retrieve FW binary file and parse it to initialize FW download
501 /* Retrieve FW binary */
502 res
= request_firmware(&fw_dnld
->fw
, firmware_name
,
503 &ndev
->nfc_dev
->dev
);
505 nfc_err(priv
->dev
, "failed to retrieve FW %s", firmware_name
);
509 fw_dnld
->header
= (const struct nfcmrvl_fw
*) priv
->fw_dnld
.fw
->data
;
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
;
521 if (fw_dnld
->header
->helper
.offset
!= 0) {
522 nfc_info(priv
->dev
, "loading helper");
523 fw_dnld
->binary_config
= &fw_dnld
->header
->helper
;
525 nfc_info(priv
->dev
, "loading firmware");
526 fw_dnld
->binary_config
= &fw_dnld
->header
->firmware
;
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
));
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
);
538 /* Allow first command */
539 atomic_set(&priv
->ndev
->cmd_cnt
, 1);
541 /* First, reset the chip */
542 priv
->fw_dnld
.state
= STATE_RESET
;
543 nfcmrvl_chip_reset(priv
);
545 /* Now wait for CORE_RESET_NTF or timeout */