2 * Marvell NFC driver: Firmware downloader
4 * Copyright (C) 2015, Marvell International Ltd.
6 * This software file (the "File") is distributed by Marvell International
7 * Ltd. under the terms of the GNU General Public License Version 2, June 1991
8 * (the "License"). You may use, redistribute and/or modify this File in
9 * accordance with the terms and conditions of the License, a copy of which
10 * is available on the worldwide web at
11 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
13 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
14 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
15 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
16 * this warranty disclaimer.
19 #include <linux/module.h>
20 #include <linux/unaligned/access_ok.h>
21 #include <linux/firmware.h>
22 #include <linux/nfc.h>
23 #include <net/nfc/nci.h>
24 #include <net/nfc/nci_core.h>
27 #define FW_DNLD_TIMEOUT 15000
29 #define NCI_OP_PROPRIETARY_BOOT_CMD nci_opcode_pack(NCI_GID_PROPRIETARY, \
32 /* FW download states */
46 SUBSTATE_WAIT_COMMAND
= 0,
47 SUBSTATE_WAIT_ACK_CREDIT
,
48 SUBSTATE_WAIT_NACK_CREDIT
,
49 SUBSTATE_WAIT_DATA_CREDIT
,
53 ** Patterns for responses
56 static const uint8_t nci_pattern_core_reset_ntf
[] = {
57 0x60, 0x00, 0x02, 0xA0, 0x01
60 static const uint8_t nci_pattern_core_init_rsp
[] = {
64 static const uint8_t nci_pattern_core_set_config_rsp
[] = {
65 0x40, 0x02, 0x02, 0x00, 0x00
68 static const uint8_t nci_pattern_core_conn_create_rsp
[] = {
69 0x40, 0x04, 0x04, 0x00
72 static const uint8_t nci_pattern_core_conn_close_rsp
[] = {
73 0x40, 0x05, 0x01, 0x00
76 static const uint8_t nci_pattern_core_conn_credits_ntf
[] = {
77 0x60, 0x06, 0x03, 0x01, NCI_CORE_LC_CONNID_PROP_FW_DL
, 0x01
80 static const uint8_t nci_pattern_proprietary_boot_rsp
[] = {
81 0x4F, 0x3A, 0x01, 0x00
84 static struct sk_buff
*alloc_lc_skb(struct nfcmrvl_private
*priv
, uint8_t plen
)
87 struct nci_data_hdr
*hdr
;
89 skb
= nci_skb_alloc(priv
->ndev
, (NCI_DATA_HDR_SIZE
+ plen
), GFP_KERNEL
);
91 pr_err("no memory for data\n");
95 hdr
= (struct nci_data_hdr
*) skb_put(skb
, NCI_DATA_HDR_SIZE
);
96 hdr
->conn_id
= NCI_CORE_LC_CONNID_PROP_FW_DL
;
100 nci_mt_set((__u8
*)hdr
, NCI_MT_DATA_PKT
);
101 nci_pbf_set((__u8
*)hdr
, NCI_PBF_LAST
);
106 static void fw_dnld_over(struct nfcmrvl_private
*priv
, u32 error
)
108 if (priv
->fw_dnld
.fw
) {
109 release_firmware(priv
->fw_dnld
.fw
);
110 priv
->fw_dnld
.fw
= NULL
;
111 priv
->fw_dnld
.header
= NULL
;
112 priv
->fw_dnld
.binary_config
= NULL
;
115 atomic_set(&priv
->ndev
->cmd_cnt
, 0);
117 if (timer_pending(&priv
->ndev
->cmd_timer
))
118 del_timer_sync(&priv
->ndev
->cmd_timer
);
120 if (timer_pending(&priv
->fw_dnld
.timer
))
121 del_timer_sync(&priv
->fw_dnld
.timer
);
123 nfc_info(priv
->dev
, "FW loading over (%d)]\n", error
);
126 /* failed, halt the chip to avoid power consumption */
127 nfcmrvl_chip_halt(priv
);
130 nfc_fw_download_done(priv
->ndev
->nfc_dev
, priv
->fw_dnld
.name
, error
);
133 static void fw_dnld_timeout(unsigned long arg
)
135 struct nfcmrvl_private
*priv
= (struct nfcmrvl_private
*) arg
;
137 nfc_err(priv
->dev
, "FW loading timeout");
138 priv
->fw_dnld
.state
= STATE_RESET
;
139 fw_dnld_over(priv
, -ETIMEDOUT
);
142 static int process_state_reset(struct nfcmrvl_private
*priv
,
145 if (sizeof(nci_pattern_core_reset_ntf
) != skb
->len
||
146 memcmp(skb
->data
, nci_pattern_core_reset_ntf
,
147 sizeof(nci_pattern_core_reset_ntf
)))
150 nfc_info(priv
->dev
, "BootROM reset, start fw download\n");
152 /* Start FW download state machine */
153 priv
->fw_dnld
.state
= STATE_INIT
;
154 nci_send_cmd(priv
->ndev
, NCI_OP_CORE_INIT_CMD
, 0, NULL
);
159 static int process_state_init(struct nfcmrvl_private
*priv
, struct sk_buff
*skb
)
161 struct nci_core_set_config_cmd cmd
;
163 if (sizeof(nci_pattern_core_init_rsp
) >= skb
->len
||
164 memcmp(skb
->data
, nci_pattern_core_init_rsp
,
165 sizeof(nci_pattern_core_init_rsp
)))
169 cmd
.param
.id
= NFCMRVL_PROP_REF_CLOCK
;
171 memcpy(cmd
.param
.val
, &priv
->fw_dnld
.header
->ref_clock
, 4);
173 nci_send_cmd(priv
->ndev
, NCI_OP_CORE_SET_CONFIG_CMD
, 3 + cmd
.param
.len
,
176 priv
->fw_dnld
.state
= STATE_SET_REF_CLOCK
;
180 static void create_lc(struct nfcmrvl_private
*priv
)
182 uint8_t param
[2] = { NCI_CORE_LC_PROP_FW_DL
, 0x0 };
184 priv
->fw_dnld
.state
= STATE_OPEN_LC
;
185 nci_send_cmd(priv
->ndev
, NCI_OP_CORE_CONN_CREATE_CMD
, 2, param
);
188 static int process_state_set_ref_clock(struct nfcmrvl_private
*priv
,
191 struct nci_core_set_config_cmd cmd
;
193 if (sizeof(nci_pattern_core_set_config_rsp
) != skb
->len
||
194 memcmp(skb
->data
, nci_pattern_core_set_config_rsp
, skb
->len
))
198 cmd
.param
.id
= NFCMRVL_PROP_SET_HI_CONFIG
;
201 case NFCMRVL_PHY_UART
:
203 memcpy(cmd
.param
.val
,
204 &priv
->fw_dnld
.binary_config
->uart
.baudrate
,
207 priv
->fw_dnld
.binary_config
->uart
.flow_control
;
209 case NFCMRVL_PHY_I2C
:
211 memcpy(cmd
.param
.val
,
212 &priv
->fw_dnld
.binary_config
->i2c
.clk
,
214 cmd
.param
.val
[4] = 0;
216 case NFCMRVL_PHY_SPI
:
218 memcpy(cmd
.param
.val
,
219 &priv
->fw_dnld
.binary_config
->spi
.clk
,
221 cmd
.param
.val
[4] = 0;
228 priv
->fw_dnld
.state
= STATE_SET_HI_CONFIG
;
229 nci_send_cmd(priv
->ndev
, NCI_OP_CORE_SET_CONFIG_CMD
, 3 + cmd
.param
.len
,
234 static int process_state_set_hi_config(struct nfcmrvl_private
*priv
,
237 if (sizeof(nci_pattern_core_set_config_rsp
) != skb
->len
||
238 memcmp(skb
->data
, nci_pattern_core_set_config_rsp
, skb
->len
))
245 static int process_state_open_lc(struct nfcmrvl_private
*priv
,
248 if (sizeof(nci_pattern_core_conn_create_rsp
) >= skb
->len
||
249 memcmp(skb
->data
, nci_pattern_core_conn_create_rsp
,
250 sizeof(nci_pattern_core_conn_create_rsp
)))
253 priv
->fw_dnld
.state
= STATE_FW_DNLD
;
254 priv
->fw_dnld
.substate
= SUBSTATE_WAIT_COMMAND
;
255 priv
->fw_dnld
.offset
= priv
->fw_dnld
.binary_config
->offset
;
259 static int process_state_fw_dnld(struct nfcmrvl_private
*priv
,
264 struct sk_buff
*out_skb
;
266 switch (priv
->fw_dnld
.substate
) {
267 case SUBSTATE_WAIT_COMMAND
:
271 * B3 : Helper command (0xA5)
272 * B4..5: le16 data size
273 * B6..7: le16 data size complement (~)
279 if (skb
->data
[0] != HELPER_CMD_PACKET_FORMAT
|| skb
->len
!= 5) {
280 nfc_err(priv
->dev
, "bad command");
284 memcpy(&len
, skb
->data
, 2);
286 memcpy(&comp_len
, skb
->data
, 2);
288 len
= get_unaligned_le16(&len
);
289 comp_len
= get_unaligned_le16(&comp_len
);
290 if (((~len
) & 0xFFFF) != comp_len
) {
291 nfc_err(priv
->dev
, "bad len complement: %x %x %x",
292 len
, comp_len
, (~len
& 0xFFFF));
293 out_skb
= alloc_lc_skb(priv
, 1);
296 *skb_put(out_skb
, 1) = 0xBF;
297 nci_send_frame(priv
->ndev
, out_skb
);
298 priv
->fw_dnld
.substate
= SUBSTATE_WAIT_NACK_CREDIT
;
301 priv
->fw_dnld
.chunk_len
= len
;
302 out_skb
= alloc_lc_skb(priv
, 1);
305 *skb_put(out_skb
, 1) = HELPER_ACK_PACKET_FORMAT
;
306 nci_send_frame(priv
->ndev
, out_skb
);
307 priv
->fw_dnld
.substate
= SUBSTATE_WAIT_ACK_CREDIT
;
310 case SUBSTATE_WAIT_ACK_CREDIT
:
311 if (sizeof(nci_pattern_core_conn_credits_ntf
) != skb
->len
||
312 memcmp(nci_pattern_core_conn_credits_ntf
, skb
->data
,
314 nfc_err(priv
->dev
, "bad packet: waiting for credit");
317 if (priv
->fw_dnld
.chunk_len
== 0) {
318 /* FW Loading is done */
319 uint8_t conn_id
= NCI_CORE_LC_CONNID_PROP_FW_DL
;
321 priv
->fw_dnld
.state
= STATE_CLOSE_LC
;
322 nci_send_cmd(priv
->ndev
, NCI_OP_CORE_CONN_CLOSE_CMD
,
325 out_skb
= alloc_lc_skb(priv
, priv
->fw_dnld
.chunk_len
);
328 memcpy(skb_put(out_skb
, priv
->fw_dnld
.chunk_len
),
329 ((uint8_t *)priv
->fw_dnld
.fw
->data
) +
330 priv
->fw_dnld
.offset
,
331 priv
->fw_dnld
.chunk_len
);
332 nci_send_frame(priv
->ndev
, out_skb
);
333 priv
->fw_dnld
.substate
= SUBSTATE_WAIT_DATA_CREDIT
;
337 case SUBSTATE_WAIT_DATA_CREDIT
:
338 if (sizeof(nci_pattern_core_conn_credits_ntf
) != skb
->len
||
339 memcmp(nci_pattern_core_conn_credits_ntf
, skb
->data
,
341 nfc_err(priv
->dev
, "bad packet: waiting for credit");
344 priv
->fw_dnld
.offset
+= priv
->fw_dnld
.chunk_len
;
345 priv
->fw_dnld
.chunk_len
= 0;
346 priv
->fw_dnld
.substate
= SUBSTATE_WAIT_COMMAND
;
349 case SUBSTATE_WAIT_NACK_CREDIT
:
350 if (sizeof(nci_pattern_core_conn_credits_ntf
) != skb
->len
||
351 memcmp(nci_pattern_core_conn_credits_ntf
, skb
->data
,
353 nfc_err(priv
->dev
, "bad packet: waiting for credit");
356 priv
->fw_dnld
.substate
= SUBSTATE_WAIT_COMMAND
;
362 static int process_state_close_lc(struct nfcmrvl_private
*priv
,
365 if (sizeof(nci_pattern_core_conn_close_rsp
) != skb
->len
||
366 memcmp(skb
->data
, nci_pattern_core_conn_close_rsp
, skb
->len
))
369 priv
->fw_dnld
.state
= STATE_BOOT
;
370 nci_send_cmd(priv
->ndev
, NCI_OP_PROPRIETARY_BOOT_CMD
, 0, NULL
);
374 static int process_state_boot(struct nfcmrvl_private
*priv
, struct sk_buff
*skb
)
376 if (sizeof(nci_pattern_proprietary_boot_rsp
) != skb
->len
||
377 memcmp(skb
->data
, nci_pattern_proprietary_boot_rsp
, skb
->len
))
381 * Update HI config to use the right configuration for the next
384 priv
->if_ops
->nci_update_config(priv
,
385 &priv
->fw_dnld
.binary_config
->config
);
387 if (priv
->fw_dnld
.binary_config
== &priv
->fw_dnld
.header
->helper
) {
389 * This is the case where an helper was needed and we have
390 * uploaded it. Now we have to wait the next RESET NTF to start
393 priv
->fw_dnld
.state
= STATE_RESET
;
394 priv
->fw_dnld
.binary_config
= &priv
->fw_dnld
.header
->firmware
;
395 nfc_info(priv
->dev
, "FW loading: helper loaded");
397 nfc_info(priv
->dev
, "FW loading: firmware loaded");
398 fw_dnld_over(priv
, 0);
403 static void fw_dnld_rx_work(struct work_struct
*work
)
407 struct nfcmrvl_fw_dnld
*fw_dnld
= container_of(work
,
408 struct nfcmrvl_fw_dnld
,
410 struct nfcmrvl_private
*priv
= container_of(fw_dnld
,
411 struct nfcmrvl_private
,
414 while ((skb
= skb_dequeue(&fw_dnld
->rx_q
))) {
415 nfc_send_to_raw_sock(priv
->ndev
->nfc_dev
, skb
,
416 RAW_PAYLOAD_NCI
, NFC_DIRECTION_RX
);
417 switch (fw_dnld
->state
) {
419 ret
= process_state_reset(priv
, skb
);
422 ret
= process_state_init(priv
, skb
);
424 case STATE_SET_REF_CLOCK
:
425 ret
= process_state_set_ref_clock(priv
, skb
);
427 case STATE_SET_HI_CONFIG
:
428 ret
= process_state_set_hi_config(priv
, skb
);
431 ret
= process_state_open_lc(priv
, skb
);
434 ret
= process_state_fw_dnld(priv
, skb
);
437 ret
= process_state_close_lc(priv
, skb
);
440 ret
= process_state_boot(priv
, skb
);
449 nfc_err(priv
->dev
, "FW loading error");
450 fw_dnld_over(priv
, ret
);
456 int nfcmrvl_fw_dnld_init(struct nfcmrvl_private
*priv
)
460 INIT_WORK(&priv
->fw_dnld
.rx_work
, fw_dnld_rx_work
);
461 snprintf(name
, sizeof(name
), "%s_nfcmrvl_fw_dnld_rx_wq",
462 dev_name(priv
->dev
));
463 priv
->fw_dnld
.rx_wq
= create_singlethread_workqueue(name
);
464 if (!priv
->fw_dnld
.rx_wq
)
466 skb_queue_head_init(&priv
->fw_dnld
.rx_q
);
470 void nfcmrvl_fw_dnld_deinit(struct nfcmrvl_private
*priv
)
472 destroy_workqueue(priv
->fw_dnld
.rx_wq
);
475 void nfcmrvl_fw_dnld_recv_frame(struct nfcmrvl_private
*priv
,
478 /* Discard command timer */
479 if (timer_pending(&priv
->ndev
->cmd_timer
))
480 del_timer_sync(&priv
->ndev
->cmd_timer
);
482 /* Allow next command */
483 atomic_set(&priv
->ndev
->cmd_cnt
, 1);
485 /* Queue and trigger rx work */
486 skb_queue_tail(&priv
->fw_dnld
.rx_q
, skb
);
487 queue_work(priv
->fw_dnld
.rx_wq
, &priv
->fw_dnld
.rx_work
);
490 void nfcmrvl_fw_dnld_abort(struct nfcmrvl_private
*priv
)
492 fw_dnld_over(priv
, -EHOSTDOWN
);
495 int nfcmrvl_fw_dnld_start(struct nci_dev
*ndev
, const char *firmware_name
)
497 struct nfcmrvl_private
*priv
= nci_get_drvdata(ndev
);
498 struct nfcmrvl_fw_dnld
*fw_dnld
= &priv
->fw_dnld
;
500 if (!priv
->support_fw_dnld
)
503 if (!firmware_name
|| !firmware_name
[0])
506 strcpy(fw_dnld
->name
, firmware_name
);
509 * Retrieve FW binary file and parse it to initialize FW download
513 /* Retrieve FW binary */
514 if (request_firmware(&fw_dnld
->fw
, firmware_name
, priv
->dev
) < 0) {
515 nfc_err(priv
->dev
, "failed to retrieve FW %s", firmware_name
);
519 fw_dnld
->header
= (const struct nfcmrvl_fw
*) priv
->fw_dnld
.fw
->data
;
521 if (fw_dnld
->header
->magic
!= NFCMRVL_FW_MAGIC
||
522 fw_dnld
->header
->phy
!= priv
->phy
) {
523 nfc_err(priv
->dev
, "bad firmware binary %s magic=0x%x phy=%d",
524 firmware_name
, fw_dnld
->header
->magic
,
525 fw_dnld
->header
->phy
);
526 release_firmware(fw_dnld
->fw
);
527 fw_dnld
->header
= NULL
;
531 if (fw_dnld
->header
->helper
.offset
!= 0) {
532 nfc_info(priv
->dev
, "loading helper");
533 fw_dnld
->binary_config
= &fw_dnld
->header
->helper
;
535 nfc_info(priv
->dev
, "loading firmware");
536 fw_dnld
->binary_config
= &fw_dnld
->header
->firmware
;
539 /* Configure a timer for timeout */
540 setup_timer(&priv
->fw_dnld
.timer
, fw_dnld_timeout
,
541 (unsigned long) priv
);
542 mod_timer(&priv
->fw_dnld
.timer
,
543 jiffies
+ msecs_to_jiffies(FW_DNLD_TIMEOUT
));
545 /* Ronfigure HI to be sure that it is the bootrom values */
546 priv
->if_ops
->nci_update_config(priv
,
547 &fw_dnld
->header
->bootrom
.config
);
549 /* Allow first command */
550 atomic_set(&priv
->ndev
->cmd_cnt
, 1);
552 /* First, reset the chip */
553 priv
->fw_dnld
.state
= STATE_RESET
;
554 nfcmrvl_chip_reset(priv
);
556 /* Now wait for CORE_RESET_NTF or timeout */