aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/nfc/pn544/i2c.c180
1 files changed, 174 insertions, 6 deletions
diff --git a/drivers/nfc/pn544/i2c.c b/drivers/nfc/pn544/i2c.c
index c7e277cddb48..f2acd85be86e 100644
--- a/drivers/nfc/pn544/i2c.c
+++ b/drivers/nfc/pn544/i2c.c
@@ -66,8 +66,11 @@ MODULE_DEVICE_TABLE(i2c, pn544_hci_i2c_id_table);
66#define PN544_HW_VARIANT_C2 0xa 66#define PN544_HW_VARIANT_C2 0xa
67#define PN544_HW_VARIANT_C3 0xb 67#define PN544_HW_VARIANT_C3 0xb
68 68
69#define PN544_FW_CMD_RESET 0x01
69#define PN544_FW_CMD_WRITE 0x08 70#define PN544_FW_CMD_WRITE 0x08
70#define PN544_FW_CMD_CHECK 0x06 71#define PN544_FW_CMD_CHECK 0x06
72#define PN544_FW_CMD_SECURE_WRITE 0x0C
73#define PN544_FW_CMD_SECURE_CHUNK_WRITE 0x0D
71 74
72struct pn544_i2c_fw_frame_write { 75struct pn544_i2c_fw_frame_write {
73 u8 cmd; 76 u8 cmd;
@@ -96,13 +99,31 @@ struct pn544_i2c_fw_blob {
96 u8 data[]; 99 u8 data[];
97}; 100};
98 101
102struct pn544_i2c_fw_secure_frame {
103 u8 cmd;
104 u16 be_datalen;
105 u8 data[];
106} __packed;
107
108struct pn544_i2c_fw_secure_blob {
109 u64 header;
110 u8 data[];
111};
112
99#define PN544_FW_CMD_RESULT_TIMEOUT 0x01 113#define PN544_FW_CMD_RESULT_TIMEOUT 0x01
100#define PN544_FW_CMD_RESULT_BAD_CRC 0x02 114#define PN544_FW_CMD_RESULT_BAD_CRC 0x02
101#define PN544_FW_CMD_RESULT_ACCESS_DENIED 0x08 115#define PN544_FW_CMD_RESULT_ACCESS_DENIED 0x08
102#define PN544_FW_CMD_RESULT_PROTOCOL_ERROR 0x0B 116#define PN544_FW_CMD_RESULT_PROTOCOL_ERROR 0x0B
103#define PN544_FW_CMD_RESULT_INVALID_PARAMETER 0x11 117#define PN544_FW_CMD_RESULT_INVALID_PARAMETER 0x11
118#define PN544_FW_CMD_RESULT_UNSUPPORTED_COMMAND 0x13
104#define PN544_FW_CMD_RESULT_INVALID_LENGTH 0x18 119#define PN544_FW_CMD_RESULT_INVALID_LENGTH 0x18
120#define PN544_FW_CMD_RESULT_CRYPTOGRAPHIC_ERROR 0x19
121#define PN544_FW_CMD_RESULT_VERSION_CONDITIONS_ERROR 0x1D
122#define PN544_FW_CMD_RESULT_MEMORY_ERROR 0x20
123#define PN544_FW_CMD_RESULT_CHUNK_OK 0x21
105#define PN544_FW_CMD_RESULT_WRITE_FAILED 0x74 124#define PN544_FW_CMD_RESULT_WRITE_FAILED 0x74
125#define PN544_FW_CMD_RESULT_COMMAND_REJECTED 0xE0
126#define PN544_FW_CMD_RESULT_CHUNK_ERROR 0xE6
106 127
107#define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) 128#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
108 129
@@ -112,11 +133,17 @@ struct pn544_i2c_fw_blob {
112#define PN544_FW_I2C_WRITE_DATA_MAX_LEN MIN((PN544_FW_I2C_MAX_PAYLOAD -\ 133#define PN544_FW_I2C_WRITE_DATA_MAX_LEN MIN((PN544_FW_I2C_MAX_PAYLOAD -\
113 PN544_FW_I2C_WRITE_FRAME_HEADER_LEN),\ 134 PN544_FW_I2C_WRITE_FRAME_HEADER_LEN),\
114 PN544_FW_WRITE_BUFFER_MAX_LEN) 135 PN544_FW_WRITE_BUFFER_MAX_LEN)
136#define PN544_FW_SECURE_CHUNK_WRITE_HEADER_LEN 3
137#define PN544_FW_SECURE_CHUNK_WRITE_DATA_MAX_LEN (PN544_FW_I2C_MAX_PAYLOAD -\
138 PN544_FW_SECURE_CHUNK_WRITE_HEADER_LEN)
139#define PN544_FW_SECURE_FRAME_HEADER_LEN 3
140#define PN544_FW_SECURE_BLOB_HEADER_LEN 8
115 141
116#define FW_WORK_STATE_IDLE 1 142#define FW_WORK_STATE_IDLE 1
117#define FW_WORK_STATE_START 2 143#define FW_WORK_STATE_START 2
118#define FW_WORK_STATE_WAIT_WRITE_ANSWER 3 144#define FW_WORK_STATE_WAIT_WRITE_ANSWER 3
119#define FW_WORK_STATE_WAIT_CHECK_ANSWER 4 145#define FW_WORK_STATE_WAIT_CHECK_ANSWER 4
146#define FW_WORK_STATE_WAIT_SECURE_WRITE_ANSWER 5
120 147
121struct pn544_i2c_phy { 148struct pn544_i2c_phy {
122 struct i2c_client *i2c_dev; 149 struct i2c_client *i2c_dev;
@@ -137,6 +164,8 @@ struct pn544_i2c_phy {
137 size_t fw_blob_size; 164 size_t fw_blob_size;
138 const u8 *fw_blob_data; 165 const u8 *fw_blob_data;
139 size_t fw_written; 166 size_t fw_written;
167 size_t fw_size;
168
140 int fw_cmd_result; 169 int fw_cmd_result;
141 170
142 int powered; 171 int powered;
@@ -400,6 +429,8 @@ static int pn544_hci_i2c_fw_read_status(struct pn544_i2c_phy *phy)
400 switch (response.status) { 429 switch (response.status) {
401 case 0: 430 case 0:
402 return 0; 431 return 0;
432 case PN544_FW_CMD_RESULT_CHUNK_OK:
433 return response.status;
403 case PN544_FW_CMD_RESULT_TIMEOUT: 434 case PN544_FW_CMD_RESULT_TIMEOUT:
404 return -ETIMEDOUT; 435 return -ETIMEDOUT;
405 case PN544_FW_CMD_RESULT_BAD_CRC: 436 case PN544_FW_CMD_RESULT_BAD_CRC:
@@ -410,9 +441,20 @@ static int pn544_hci_i2c_fw_read_status(struct pn544_i2c_phy *phy)
410 return -EPROTO; 441 return -EPROTO;
411 case PN544_FW_CMD_RESULT_INVALID_PARAMETER: 442 case PN544_FW_CMD_RESULT_INVALID_PARAMETER:
412 return -EINVAL; 443 return -EINVAL;
444 case PN544_FW_CMD_RESULT_UNSUPPORTED_COMMAND:
445 return -ENOTSUPP;
413 case PN544_FW_CMD_RESULT_INVALID_LENGTH: 446 case PN544_FW_CMD_RESULT_INVALID_LENGTH:
414 return -EBADMSG; 447 return -EBADMSG;
448 case PN544_FW_CMD_RESULT_CRYPTOGRAPHIC_ERROR:
449 return -ENOKEY;
450 case PN544_FW_CMD_RESULT_VERSION_CONDITIONS_ERROR:
451 return -EINVAL;
452 case PN544_FW_CMD_RESULT_MEMORY_ERROR:
453 return -ENOMEM;
454 case PN544_FW_CMD_RESULT_COMMAND_REJECTED:
455 return -EACCES;
415 case PN544_FW_CMD_RESULT_WRITE_FAILED: 456 case PN544_FW_CMD_RESULT_WRITE_FAILED:
457 case PN544_FW_CMD_RESULT_CHUNK_ERROR:
416 return -EIO; 458 return -EIO;
417 default: 459 default:
418 return -EIO; 460 return -EIO;
@@ -610,12 +652,93 @@ static int pn544_hci_i2c_fw_write_chunk(struct pn544_i2c_phy *phy)
610 return 0; 652 return 0;
611} 653}
612 654
655static int pn544_hci_i2c_fw_secure_write_frame_cmd(struct pn544_i2c_phy *phy,
656 const u8 *data, u16 datalen)
657{
658 u8 buf[PN544_FW_I2C_MAX_PAYLOAD];
659 struct pn544_i2c_fw_secure_frame *chunk;
660 int chunklen;
661 int r;
662
663 if (datalen > PN544_FW_SECURE_CHUNK_WRITE_DATA_MAX_LEN)
664 datalen = PN544_FW_SECURE_CHUNK_WRITE_DATA_MAX_LEN;
665
666 chunk = (struct pn544_i2c_fw_secure_frame *) buf;
667
668 chunk->cmd = PN544_FW_CMD_SECURE_CHUNK_WRITE;
669
670 put_unaligned_be16(datalen, &chunk->be_datalen);
671
672 memcpy(chunk->data, data, datalen);
673
674 chunklen = sizeof(chunk->cmd) + sizeof(chunk->be_datalen) + datalen;
675
676 r = i2c_master_send(phy->i2c_dev, buf, chunklen);
677
678 if (r == chunklen)
679 return datalen;
680 else if (r < 0)
681 return r;
682 else
683 return -EIO;
684
685}
686
687static int pn544_hci_i2c_fw_secure_write_frame(struct pn544_i2c_phy *phy)
688{
689 struct pn544_i2c_fw_secure_frame *framep;
690 int r;
691
692 framep = (struct pn544_i2c_fw_secure_frame *) phy->fw_blob_data;
693 if (phy->fw_written == 0)
694 phy->fw_blob_size = get_unaligned_be16(&framep->be_datalen)
695 + PN544_FW_SECURE_FRAME_HEADER_LEN;
696
697 /* Only secure write command can be chunked*/
698 if (phy->fw_blob_size > PN544_FW_I2C_MAX_PAYLOAD &&
699 framep->cmd != PN544_FW_CMD_SECURE_WRITE)
700 return -EINVAL;
701
702 /* The firmware also have other commands, we just send them directly */
703 if (phy->fw_blob_size < PN544_FW_I2C_MAX_PAYLOAD) {
704 r = i2c_master_send(phy->i2c_dev,
705 (const char *) phy->fw_blob_data, phy->fw_blob_size);
706
707 if (r == phy->fw_blob_size)
708 goto exit;
709 else if (r < 0)
710 return r;
711 else
712 return -EIO;
713 }
714
715 r = pn544_hci_i2c_fw_secure_write_frame_cmd(phy,
716 phy->fw_blob_data + phy->fw_written,
717 phy->fw_blob_size - phy->fw_written);
718 if (r < 0)
719 return r;
720
721exit:
722 phy->fw_written += r;
723 phy->fw_work_state = FW_WORK_STATE_WAIT_SECURE_WRITE_ANSWER;
724
725 /* SW reset command will not trig any response from PN544 */
726 if (framep->cmd == PN544_FW_CMD_RESET) {
727 pn544_hci_i2c_enable_mode(phy, PN544_FW_MODE);
728 phy->fw_cmd_result = 0;
729 schedule_work(&phy->fw_work);
730 }
731
732 return 0;
733}
734
613static void pn544_hci_i2c_fw_work(struct work_struct *work) 735static void pn544_hci_i2c_fw_work(struct work_struct *work)
614{ 736{
615 struct pn544_i2c_phy *phy = container_of(work, struct pn544_i2c_phy, 737 struct pn544_i2c_phy *phy = container_of(work, struct pn544_i2c_phy,
616 fw_work); 738 fw_work);
617 int r; 739 int r;
618 struct pn544_i2c_fw_blob *blob; 740 struct pn544_i2c_fw_blob *blob;
741 struct pn544_i2c_fw_secure_blob *secure_blob;
619 742
620 switch (phy->fw_work_state) { 743 switch (phy->fw_work_state) {
621 case FW_WORK_STATE_START: 744 case FW_WORK_STATE_START:
@@ -626,13 +749,29 @@ static void pn544_hci_i2c_fw_work(struct work_struct *work)
626 if (r < 0) 749 if (r < 0)
627 goto exit_state_start; 750 goto exit_state_start;
628 751
629 blob = (struct pn544_i2c_fw_blob *) phy->fw->data;
630 phy->fw_blob_size = get_unaligned_be32(&blob->be_size);
631 phy->fw_blob_dest_addr = get_unaligned_be32(&blob->be_destaddr);
632 phy->fw_blob_data = blob->data;
633
634 phy->fw_written = 0; 752 phy->fw_written = 0;
635 r = pn544_hci_i2c_fw_write_chunk(phy); 753
754 switch (phy->hw_variant) {
755 case PN544_HW_VARIANT_C2:
756 blob = (struct pn544_i2c_fw_blob *) phy->fw->data;
757 phy->fw_blob_size = get_unaligned_be32(&blob->be_size);
758 phy->fw_blob_dest_addr = get_unaligned_be32(
759 &blob->be_destaddr);
760 phy->fw_blob_data = blob->data;
761
762 r = pn544_hci_i2c_fw_write_chunk(phy);
763 break;
764 case PN544_HW_VARIANT_C3:
765 secure_blob = (struct pn544_i2c_fw_secure_blob *)
766 phy->fw->data;
767 phy->fw_blob_data = secure_blob->data;
768 phy->fw_size = phy->fw->size;
769 r = pn544_hci_i2c_fw_secure_write_frame(phy);
770 break;
771 default:
772 r = -ENOTSUPP;
773 break;
774 }
636 775
637exit_state_start: 776exit_state_start:
638 if (r < 0) 777 if (r < 0)
@@ -684,6 +823,35 @@ exit_state_wait_check_answer:
684 pn544_hci_i2c_fw_work_complete(phy, r); 823 pn544_hci_i2c_fw_work_complete(phy, r);
685 break; 824 break;
686 825
826 case FW_WORK_STATE_WAIT_SECURE_WRITE_ANSWER:
827 r = phy->fw_cmd_result;
828 if (r < 0)
829 goto exit_state_wait_secure_write_answer;
830
831 if (r == PN544_FW_CMD_RESULT_CHUNK_OK) {
832 r = pn544_hci_i2c_fw_secure_write_frame(phy);
833 goto exit_state_wait_secure_write_answer;
834 }
835
836 if (phy->fw_written == phy->fw_blob_size) {
837 secure_blob = (struct pn544_i2c_fw_secure_blob *)
838 (phy->fw_blob_data + phy->fw_blob_size);
839 phy->fw_size -= phy->fw_blob_size +
840 PN544_FW_SECURE_BLOB_HEADER_LEN;
841 if (phy->fw_size >= PN544_FW_SECURE_BLOB_HEADER_LEN
842 + PN544_FW_SECURE_FRAME_HEADER_LEN) {
843 phy->fw_blob_data = secure_blob->data;
844
845 phy->fw_written = 0;
846 r = pn544_hci_i2c_fw_secure_write_frame(phy);
847 }
848 }
849
850exit_state_wait_secure_write_answer:
851 if (r < 0 || phy->fw_size == 0)
852 pn544_hci_i2c_fw_work_complete(phy, r);
853 break;
854
687 default: 855 default:
688 break; 856 break;
689 } 857 }