Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

NFC: nxp-nci: Add support for NXP NCI chips

Add support for NXP NCI NFC controllers such as the NPC100 or PN7150
families.

Signed-off-by: Clément Perrochaud <clement.perrochaud@effinnov.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>

authored by

Clément Perrochaud and committed by
Samuel Ortiz
dece4585 25af01ed

+657
+7
MAINTAINERS
··· 6937 6937 F: drivers/block/nvme* 6938 6938 F: include/linux/nvme.h 6939 6939 6940 + NXP-NCI NFC DRIVER 6941 + M: Clément Perrochaud <clement.perrochaud@effinnov.com> 6942 + R: Charles Gorand <charles.gorand@effinnov.com> 6943 + L: linux-nfc@lists.01.org (moderated for non-subscribers) 6944 + S: Supported 6945 + F: drivers/nfc/nxp-nci 6946 + 6940 6947 NXP TDA998X DRM DRIVER 6941 6948 M: Russell King <rmk+kernel@arm.linux.org.uk> 6942 6949 S: Supported
+1
drivers/nfc/Kconfig
··· 73 73 source "drivers/nfc/nfcmrvl/Kconfig" 74 74 source "drivers/nfc/st21nfca/Kconfig" 75 75 source "drivers/nfc/st21nfcb/Kconfig" 76 + source "drivers/nfc/nxp-nci/Kconfig" 76 77 endmenu
+1
drivers/nfc/Makefile
··· 13 13 obj-$(CONFIG_NFC_TRF7970A) += trf7970a.o 14 14 obj-$(CONFIG_NFC_ST21NFCA) += st21nfca/ 15 15 obj-$(CONFIG_NFC_ST21NFCB) += st21nfcb/ 16 + obj-$(CONFIG_NFC_NXP_NCI) += nxp-nci/ 16 17 17 18 ccflags-$(CONFIG_NFC_DEBUG) := -DDEBUG
+13
drivers/nfc/nxp-nci/Kconfig
··· 1 + config NFC_NXP_NCI 2 + tristate "NXP-NCI NFC driver" 3 + depends on NFC_NCI 4 + default n 5 + ---help--- 6 + Generic core driver for NXP NCI chips such as the NPC100 7 + or PN7150 families. 8 + This is a driver based on the NCI NFC kernel layers and 9 + will thus not work with NXP libnfc library. 10 + 11 + To compile this driver as a module, choose m here. The module will 12 + be called nxp_nci. 13 + Say N if unsure.
+9
drivers/nfc/nxp-nci/Makefile
··· 1 + # 2 + # Makefile for NXP-NCI NFC driver 3 + # 4 + 5 + nxp-nci-objs = core.o firmware.o 6 + 7 + obj-$(CONFIG_NFC_NXP_NCI) += nxp-nci.o 8 + 9 + ccflags-$(CONFIG_NFC_DEBUG) := -DDEBUG
+186
drivers/nfc/nxp-nci/core.c
··· 1 + /* 2 + * Generic driver for NXP NCI NFC chips 3 + * 4 + * Copyright (C) 2014 NXP Semiconductors All rights reserved. 5 + * 6 + * Authors: Clément Perrochaud <clement.perrochaud@nxp.com> 7 + * 8 + * Derived from PN544 device driver: 9 + * Copyright (C) 2012 Intel Corporation. All rights reserved. 10 + * 11 + * This program is free software; you can redistribute it and/or modify it 12 + * under the terms and conditions of the GNU General Public License, 13 + * version 2, as published by the Free Software Foundation. 14 + * 15 + * This program is distributed in the hope that it will be useful, 16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 + * GNU General Public License for more details. 19 + * 20 + * You should have received a copy of the GNU General Public License 21 + * along with this program; if not, see <http://www.gnu.org/licenses/>. 22 + */ 23 + 24 + #include <linux/delay.h> 25 + #include <linux/gpio.h> 26 + #include <linux/module.h> 27 + #include <linux/nfc.h> 28 + #include <linux/platform_data/nxp-nci.h> 29 + 30 + #include <net/nfc/nci_core.h> 31 + 32 + #include "nxp-nci.h" 33 + 34 + #define NXP_NCI_HDR_LEN 4 35 + 36 + #define NXP_NCI_NFC_PROTOCOLS (NFC_PROTO_JEWEL_MASK | \ 37 + NFC_PROTO_MIFARE_MASK | \ 38 + NFC_PROTO_FELICA_MASK | \ 39 + NFC_PROTO_ISO14443_MASK | \ 40 + NFC_PROTO_ISO14443_B_MASK | \ 41 + NFC_PROTO_NFC_DEP_MASK) 42 + 43 + static int nxp_nci_open(struct nci_dev *ndev) 44 + { 45 + struct nxp_nci_info *info = nci_get_drvdata(ndev); 46 + int r = 0; 47 + 48 + mutex_lock(&info->info_lock); 49 + 50 + if (info->mode != NXP_NCI_MODE_COLD) { 51 + r = -EBUSY; 52 + goto open_exit; 53 + } 54 + 55 + if (info->phy_ops->set_mode) 56 + r = info->phy_ops->set_mode(info->phy_id, NXP_NCI_MODE_NCI); 57 + 58 + info->mode = NXP_NCI_MODE_NCI; 59 + 60 + open_exit: 61 + mutex_unlock(&info->info_lock); 62 + return r; 63 + } 64 + 65 + static int nxp_nci_close(struct nci_dev *ndev) 66 + { 67 + struct nxp_nci_info *info = nci_get_drvdata(ndev); 68 + int r = 0; 69 + 70 + mutex_lock(&info->info_lock); 71 + 72 + if (info->phy_ops->set_mode) 73 + r = info->phy_ops->set_mode(info->phy_id, NXP_NCI_MODE_COLD); 74 + 75 + info->mode = NXP_NCI_MODE_COLD; 76 + 77 + mutex_unlock(&info->info_lock); 78 + return r; 79 + } 80 + 81 + static int nxp_nci_send(struct nci_dev *ndev, struct sk_buff *skb) 82 + { 83 + struct nxp_nci_info *info = nci_get_drvdata(ndev); 84 + int r; 85 + 86 + if (!info->phy_ops->write) { 87 + r = -ENOTSUPP; 88 + goto send_exit; 89 + } 90 + 91 + if (info->mode != NXP_NCI_MODE_NCI) { 92 + r = -EINVAL; 93 + goto send_exit; 94 + } 95 + 96 + r = info->phy_ops->write(info->phy_id, skb); 97 + if (r < 0) 98 + kfree_skb(skb); 99 + 100 + send_exit: 101 + return r; 102 + } 103 + 104 + static struct nci_ops nxp_nci_ops = { 105 + .open = nxp_nci_open, 106 + .close = nxp_nci_close, 107 + .send = nxp_nci_send, 108 + .fw_download = nxp_nci_fw_download, 109 + }; 110 + 111 + int nxp_nci_probe(void *phy_id, struct device *pdev, 112 + struct nxp_nci_phy_ops *phy_ops, unsigned int max_payload, 113 + struct nci_dev **ndev) 114 + { 115 + struct nxp_nci_info *info; 116 + int r; 117 + 118 + info = devm_kzalloc(pdev, sizeof(struct nxp_nci_info), GFP_KERNEL); 119 + if (!info) { 120 + r = -ENOMEM; 121 + goto probe_exit; 122 + } 123 + 124 + info->phy_id = phy_id; 125 + info->pdev = pdev; 126 + info->phy_ops = phy_ops; 127 + info->max_payload = max_payload; 128 + INIT_WORK(&info->fw_info.work, nxp_nci_fw_work); 129 + init_completion(&info->fw_info.cmd_completion); 130 + mutex_init(&info->info_lock); 131 + 132 + if (info->phy_ops->set_mode) { 133 + r = info->phy_ops->set_mode(info->phy_id, NXP_NCI_MODE_COLD); 134 + if (r < 0) 135 + goto probe_exit; 136 + } 137 + 138 + info->mode = NXP_NCI_MODE_COLD; 139 + 140 + info->ndev = nci_allocate_device(&nxp_nci_ops, NXP_NCI_NFC_PROTOCOLS, 141 + NXP_NCI_HDR_LEN, 0); 142 + if (!info->ndev) { 143 + r = -ENOMEM; 144 + goto probe_exit; 145 + } 146 + 147 + nci_set_parent_dev(info->ndev, pdev); 148 + nci_set_drvdata(info->ndev, info); 149 + r = nci_register_device(info->ndev); 150 + if (r < 0) 151 + goto probe_exit_free_nci; 152 + 153 + *ndev = info->ndev; 154 + 155 + goto probe_exit; 156 + 157 + probe_exit_free_nci: 158 + nci_free_device(info->ndev); 159 + probe_exit: 160 + return r; 161 + } 162 + EXPORT_SYMBOL(nxp_nci_probe); 163 + 164 + void nxp_nci_remove(struct nci_dev *ndev) 165 + { 166 + struct nxp_nci_info *info = nci_get_drvdata(ndev); 167 + 168 + if (info->mode == NXP_NCI_MODE_FW) 169 + nxp_nci_fw_work_complete(info, -ESHUTDOWN); 170 + cancel_work_sync(&info->fw_info.work); 171 + 172 + mutex_lock(&info->info_lock); 173 + 174 + if (info->phy_ops->set_mode) 175 + info->phy_ops->set_mode(info->phy_id, NXP_NCI_MODE_COLD); 176 + 177 + nci_unregister_device(ndev); 178 + nci_free_device(ndev); 179 + 180 + mutex_unlock(&info->info_lock); 181 + } 182 + EXPORT_SYMBOL(nxp_nci_remove); 183 + 184 + MODULE_LICENSE("GPL"); 185 + MODULE_DESCRIPTION("NXP NCI NFC driver"); 186 + MODULE_AUTHOR("Clément Perrochaud <clement.perrochaud@nxp.com>");
+324
drivers/nfc/nxp-nci/firmware.c
··· 1 + /* 2 + * Generic driver for NXP NCI NFC chips 3 + * 4 + * Copyright (C) 2014 NXP Semiconductors All rights reserved. 5 + * 6 + * Author: Clément Perrochaud <clement.perrochaud@nxp.com> 7 + * 8 + * Derived from PN544 device driver: 9 + * Copyright (C) 2012 Intel Corporation. All rights reserved. 10 + * 11 + * This program is free software; you can redistribute it and/or modify it 12 + * under the terms and conditions of the GNU General Public License, 13 + * version 2, as published by the Free Software Foundation. 14 + * 15 + * This program is distributed in the hope that it will be useful, 16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 + * GNU General Public License for more details. 19 + * 20 + * You should have received a copy of the GNU General Public License 21 + * along with this program; if not, see <http://www.gnu.org/licenses/>. 22 + */ 23 + 24 + #include <linux/completion.h> 25 + #include <linux/firmware.h> 26 + #include <linux/nfc.h> 27 + #include <linux/unaligned/access_ok.h> 28 + 29 + #include "nxp-nci.h" 30 + 31 + /* Crypto operations can take up to 30 seconds */ 32 + #define NXP_NCI_FW_ANSWER_TIMEOUT msecs_to_jiffies(30000) 33 + 34 + #define NXP_NCI_FW_CMD_RESET 0xF0 35 + #define NXP_NCI_FW_CMD_GETVERSION 0xF1 36 + #define NXP_NCI_FW_CMD_CHECKINTEGRITY 0xE0 37 + #define NXP_NCI_FW_CMD_WRITE 0xC0 38 + #define NXP_NCI_FW_CMD_READ 0xA2 39 + #define NXP_NCI_FW_CMD_GETSESSIONSTATE 0xF2 40 + #define NXP_NCI_FW_CMD_LOG 0xA7 41 + #define NXP_NCI_FW_CMD_FORCE 0xD0 42 + #define NXP_NCI_FW_CMD_GET_DIE_ID 0xF4 43 + 44 + #define NXP_NCI_FW_CHUNK_FLAG 0x0400 45 + 46 + #define NXP_NCI_FW_RESULT_OK 0x00 47 + #define NXP_NCI_FW_RESULT_INVALID_ADDR 0x01 48 + #define NXP_NCI_FW_RESULT_GENERIC_ERROR 0x02 49 + #define NXP_NCI_FW_RESULT_UNKNOWN_CMD 0x0B 50 + #define NXP_NCI_FW_RESULT_ABORTED_CMD 0x0C 51 + #define NXP_NCI_FW_RESULT_PLL_ERROR 0x0D 52 + #define NXP_NCI_FW_RESULT_ADDR_RANGE_OFL_ERROR 0x1E 53 + #define NXP_NCI_FW_RESULT_BUFFER_OFL_ERROR 0x1F 54 + #define NXP_NCI_FW_RESULT_MEM_BSY 0x20 55 + #define NXP_NCI_FW_RESULT_SIGNATURE_ERROR 0x21 56 + #define NXP_NCI_FW_RESULT_FIRMWARE_VERSION_ERROR 0x24 57 + #define NXP_NCI_FW_RESULT_PROTOCOL_ERROR 0x28 58 + #define NXP_NCI_FW_RESULT_SFWU_DEGRADED 0x2A 59 + #define NXP_NCI_FW_RESULT_PH_STATUS_FIRST_CHUNK 0x2D 60 + #define NXP_NCI_FW_RESULT_PH_STATUS_NEXT_CHUNK 0x2E 61 + #define NXP_NCI_FW_RESULT_PH_STATUS_INTERNAL_ERROR_5 0xC5 62 + 63 + void nxp_nci_fw_work_complete(struct nxp_nci_info *info, int result) 64 + { 65 + struct nxp_nci_fw_info *fw_info = &info->fw_info; 66 + int r; 67 + 68 + if (info->phy_ops->set_mode) { 69 + r = info->phy_ops->set_mode(info->phy_id, NXP_NCI_MODE_COLD); 70 + if (r < 0 && result == 0) 71 + result = -r; 72 + } 73 + 74 + info->mode = NXP_NCI_MODE_COLD; 75 + 76 + if (fw_info->fw) { 77 + release_firmware(fw_info->fw); 78 + fw_info->fw = NULL; 79 + } 80 + 81 + nfc_fw_download_done(info->ndev->nfc_dev, fw_info->name, (u32) -result); 82 + } 83 + 84 + /* crc_ccitt cannot be used since it is computed MSB first and not LSB first */ 85 + static u16 nxp_nci_fw_crc(u8 const *buffer, size_t len) 86 + { 87 + u16 crc = 0xffff; 88 + 89 + while (len--) { 90 + crc = ((crc >> 8) | (crc << 8)) ^ *buffer++; 91 + crc ^= (crc & 0xff) >> 4; 92 + crc ^= (crc & 0xff) << 12; 93 + crc ^= (crc & 0xff) << 5; 94 + } 95 + 96 + return crc; 97 + } 98 + 99 + static int nxp_nci_fw_send_chunk(struct nxp_nci_info *info) 100 + { 101 + struct nxp_nci_fw_info *fw_info = &info->fw_info; 102 + u16 header, crc; 103 + struct sk_buff *skb; 104 + size_t chunk_len; 105 + size_t remaining_len; 106 + int r; 107 + 108 + skb = nci_skb_alloc(info->ndev, info->max_payload, GFP_KERNEL); 109 + if (!skb) { 110 + r = -ENOMEM; 111 + goto chunk_exit; 112 + } 113 + 114 + chunk_len = info->max_payload - NXP_NCI_FW_HDR_LEN - NXP_NCI_FW_CRC_LEN; 115 + remaining_len = fw_info->frame_size - fw_info->written; 116 + 117 + if (remaining_len > chunk_len) { 118 + header = NXP_NCI_FW_CHUNK_FLAG; 119 + } else { 120 + chunk_len = remaining_len; 121 + header = 0x0000; 122 + } 123 + 124 + header |= chunk_len & NXP_NCI_FW_FRAME_LEN_MASK; 125 + put_unaligned_be16(header, skb_put(skb, NXP_NCI_FW_HDR_LEN)); 126 + 127 + memcpy(skb_put(skb, chunk_len), fw_info->data + fw_info->written, 128 + chunk_len); 129 + 130 + crc = nxp_nci_fw_crc(skb->data, chunk_len + NXP_NCI_FW_HDR_LEN); 131 + put_unaligned_be16(crc, skb_put(skb, NXP_NCI_FW_CRC_LEN)); 132 + 133 + r = info->phy_ops->write(info->phy_id, skb); 134 + if (r >= 0) 135 + r = chunk_len; 136 + 137 + kfree_skb(skb); 138 + 139 + chunk_exit: 140 + return r; 141 + } 142 + 143 + static int nxp_nci_fw_send(struct nxp_nci_info *info) 144 + { 145 + struct nxp_nci_fw_info *fw_info = &info->fw_info; 146 + long completion_rc; 147 + int r; 148 + 149 + reinit_completion(&fw_info->cmd_completion); 150 + 151 + if (fw_info->written == 0) { 152 + fw_info->frame_size = get_unaligned_be16(fw_info->data) & 153 + NXP_NCI_FW_FRAME_LEN_MASK; 154 + fw_info->data += NXP_NCI_FW_HDR_LEN; 155 + fw_info->size -= NXP_NCI_FW_HDR_LEN; 156 + } 157 + 158 + if (fw_info->frame_size > fw_info->size) 159 + return -EMSGSIZE; 160 + 161 + r = nxp_nci_fw_send_chunk(info); 162 + if (r < 0) 163 + return r; 164 + 165 + fw_info->written += r; 166 + 167 + if (*fw_info->data == NXP_NCI_FW_CMD_RESET) { 168 + fw_info->cmd_result = 0; 169 + if (fw_info->fw) 170 + schedule_work(&fw_info->work); 171 + } else { 172 + completion_rc = wait_for_completion_interruptible_timeout( 173 + &fw_info->cmd_completion, NXP_NCI_FW_ANSWER_TIMEOUT); 174 + if (completion_rc == 0) 175 + return -ETIMEDOUT; 176 + } 177 + 178 + return 0; 179 + } 180 + 181 + void nxp_nci_fw_work(struct work_struct *work) 182 + { 183 + struct nxp_nci_info *info; 184 + struct nxp_nci_fw_info *fw_info; 185 + int r; 186 + 187 + fw_info = container_of(work, struct nxp_nci_fw_info, work); 188 + info = container_of(fw_info, struct nxp_nci_info, fw_info); 189 + 190 + mutex_lock(&info->info_lock); 191 + 192 + r = fw_info->cmd_result; 193 + if (r < 0) 194 + goto exit_work; 195 + 196 + if (fw_info->written == fw_info->frame_size) { 197 + fw_info->data += fw_info->frame_size; 198 + fw_info->size -= fw_info->frame_size; 199 + fw_info->written = 0; 200 + } 201 + 202 + if (fw_info->size > 0) 203 + r = nxp_nci_fw_send(info); 204 + 205 + exit_work: 206 + if (r < 0 || fw_info->size == 0) 207 + nxp_nci_fw_work_complete(info, r); 208 + mutex_unlock(&info->info_lock); 209 + } 210 + 211 + int nxp_nci_fw_download(struct nci_dev *ndev, const char *firmware_name) 212 + { 213 + struct nxp_nci_info *info = nci_get_drvdata(ndev); 214 + struct nxp_nci_fw_info *fw_info = &info->fw_info; 215 + int r; 216 + 217 + mutex_lock(&info->info_lock); 218 + 219 + if (!info->phy_ops->set_mode || !info->phy_ops->write) { 220 + r = -ENOTSUPP; 221 + goto fw_download_exit; 222 + } 223 + 224 + if (!firmware_name || firmware_name[0] == '\0') { 225 + r = -EINVAL; 226 + goto fw_download_exit; 227 + } 228 + 229 + strcpy(fw_info->name, firmware_name); 230 + 231 + r = request_firmware(&fw_info->fw, firmware_name, 232 + ndev->nfc_dev->dev.parent); 233 + if (r < 0) 234 + goto fw_download_exit; 235 + 236 + r = info->phy_ops->set_mode(info->phy_id, NXP_NCI_MODE_FW); 237 + if (r < 0) 238 + goto fw_download_exit; 239 + 240 + info->mode = NXP_NCI_MODE_FW; 241 + 242 + fw_info->data = fw_info->fw->data; 243 + fw_info->size = fw_info->fw->size; 244 + fw_info->written = 0; 245 + fw_info->frame_size = 0; 246 + fw_info->cmd_result = 0; 247 + 248 + if (fw_info->fw) 249 + schedule_work(&fw_info->work); 250 + 251 + fw_download_exit: 252 + mutex_unlock(&info->info_lock); 253 + return r; 254 + } 255 + 256 + static int nxp_nci_fw_read_status(u8 stat) 257 + { 258 + switch (stat) { 259 + case NXP_NCI_FW_RESULT_OK: 260 + return 0; 261 + case NXP_NCI_FW_RESULT_INVALID_ADDR: 262 + return -EINVAL; 263 + case NXP_NCI_FW_RESULT_UNKNOWN_CMD: 264 + return -EINVAL; 265 + case NXP_NCI_FW_RESULT_ABORTED_CMD: 266 + return -EMSGSIZE; 267 + case NXP_NCI_FW_RESULT_ADDR_RANGE_OFL_ERROR: 268 + return -EADDRNOTAVAIL; 269 + case NXP_NCI_FW_RESULT_BUFFER_OFL_ERROR: 270 + return -ENOBUFS; 271 + case NXP_NCI_FW_RESULT_MEM_BSY: 272 + return -ENOKEY; 273 + case NXP_NCI_FW_RESULT_SIGNATURE_ERROR: 274 + return -EKEYREJECTED; 275 + case NXP_NCI_FW_RESULT_FIRMWARE_VERSION_ERROR: 276 + return -EALREADY; 277 + case NXP_NCI_FW_RESULT_PROTOCOL_ERROR: 278 + return -EPROTO; 279 + case NXP_NCI_FW_RESULT_SFWU_DEGRADED: 280 + return -EHWPOISON; 281 + case NXP_NCI_FW_RESULT_PH_STATUS_FIRST_CHUNK: 282 + return 0; 283 + case NXP_NCI_FW_RESULT_PH_STATUS_NEXT_CHUNK: 284 + return 0; 285 + case NXP_NCI_FW_RESULT_PH_STATUS_INTERNAL_ERROR_5: 286 + return -EINVAL; 287 + default: 288 + return -EIO; 289 + } 290 + } 291 + 292 + static u16 nxp_nci_fw_check_crc(struct sk_buff *skb) 293 + { 294 + u16 crc, frame_crc; 295 + size_t len = skb->len - NXP_NCI_FW_CRC_LEN; 296 + 297 + crc = nxp_nci_fw_crc(skb->data, len); 298 + frame_crc = get_unaligned_be16(skb->data + len); 299 + 300 + return (crc ^ frame_crc); 301 + } 302 + 303 + void nxp_nci_fw_recv_frame(struct nci_dev *ndev, struct sk_buff *skb) 304 + { 305 + struct nxp_nci_info *info = nci_get_drvdata(ndev); 306 + struct nxp_nci_fw_info *fw_info = &info->fw_info; 307 + 308 + complete(&fw_info->cmd_completion); 309 + 310 + if (skb) { 311 + if (nxp_nci_fw_check_crc(skb) != 0x00) 312 + fw_info->cmd_result = -EBADMSG; 313 + else 314 + fw_info->cmd_result = nxp_nci_fw_read_status( 315 + *skb_pull(skb, NXP_NCI_FW_HDR_LEN)); 316 + kfree_skb(skb); 317 + } else { 318 + fw_info->cmd_result = -EIO; 319 + } 320 + 321 + if (fw_info->fw) 322 + schedule_work(&fw_info->work); 323 + } 324 + EXPORT_SYMBOL(nxp_nci_fw_recv_frame);
+89
drivers/nfc/nxp-nci/nxp-nci.h
··· 1 + /* 2 + * Copyright (C) 2014 NXP Semiconductors All rights reserved. 3 + * 4 + * Authors: Clément Perrochaud <clement.perrochaud@nxp.com> 5 + * 6 + * Derived from PN544 device driver: 7 + * Copyright (C) 2012 Intel Corporation. All rights reserved. 8 + * 9 + * This program is free software; you can redistribute it and/or modify it 10 + * under the terms and conditions of the GNU General Public License, 11 + * version 2, as published by the Free Software Foundation. 12 + * 13 + * This program is distributed in the hope that it will be useful, 14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 + * GNU General Public License for more details. 17 + * 18 + * You should have received a copy of the GNU General Public License 19 + * along with this program; if not, see <http://www.gnu.org/licenses/>. 20 + */ 21 + 22 + #ifndef __LOCAL_NXP_NCI_H_ 23 + #define __LOCAL_NXP_NCI_H_ 24 + 25 + #include <linux/completion.h> 26 + #include <linux/firmware.h> 27 + #include <linux/nfc.h> 28 + #include <linux/platform_data/nxp-nci.h> 29 + 30 + #include <net/nfc/nci_core.h> 31 + 32 + #define NXP_NCI_FW_HDR_LEN 2 33 + #define NXP_NCI_FW_CRC_LEN 2 34 + 35 + #define NXP_NCI_FW_FRAME_LEN_MASK 0x03FF 36 + 37 + enum nxp_nci_mode { 38 + NXP_NCI_MODE_COLD, 39 + NXP_NCI_MODE_NCI, 40 + NXP_NCI_MODE_FW 41 + }; 42 + 43 + struct nxp_nci_phy_ops { 44 + int (*set_mode)(void *id, enum nxp_nci_mode mode); 45 + int (*write)(void *id, struct sk_buff *skb); 46 + }; 47 + 48 + struct nxp_nci_fw_info { 49 + char name[NFC_FIRMWARE_NAME_MAXSIZE + 1]; 50 + const struct firmware *fw; 51 + 52 + size_t size; 53 + size_t written; 54 + 55 + const u8 *data; 56 + size_t frame_size; 57 + 58 + struct work_struct work; 59 + struct completion cmd_completion; 60 + 61 + int cmd_result; 62 + }; 63 + 64 + struct nxp_nci_info { 65 + struct nci_dev *ndev; 66 + void *phy_id; 67 + struct device *pdev; 68 + 69 + enum nxp_nci_mode mode; 70 + 71 + struct nxp_nci_phy_ops *phy_ops; 72 + unsigned int max_payload; 73 + 74 + struct mutex info_lock; 75 + 76 + struct nxp_nci_fw_info fw_info; 77 + }; 78 + 79 + int nxp_nci_fw_download(struct nci_dev *ndev, const char *firmware_name); 80 + void nxp_nci_fw_work(struct work_struct *work); 81 + void nxp_nci_fw_recv_frame(struct nci_dev *ndev, struct sk_buff *skb); 82 + void nxp_nci_fw_work_complete(struct nxp_nci_info *info, int result); 83 + 84 + int nxp_nci_probe(void *phy_id, struct device *pdev, 85 + struct nxp_nci_phy_ops *phy_ops, unsigned int max_payload, 86 + struct nci_dev **ndev); 87 + void nxp_nci_remove(struct nci_dev *ndev); 88 + 89 + #endif /* __LOCAL_NXP_NCI_H_ */
+27
include/linux/platform_data/nxp-nci.h
··· 1 + /* 2 + * Generic platform data for the NXP NCI NFC chips. 3 + * 4 + * Copyright (C) 2014 NXP Semiconductors All rights reserved. 5 + * 6 + * Authors: Clément Perrochaud <clement.perrochaud@nxp.com> 7 + * 8 + * This program is free software; you can redistribute it and/or modify it 9 + * under the terms and conditions of the GNU General Public License, 10 + * version 2, as published by the Free Software Foundation. 11 + * 12 + * This program is distributed in the hope that it will be useful, 13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 + * GNU General Public License for more details. 16 + */ 17 + 18 + #ifndef _NXP_NCI_H_ 19 + #define _NXP_NCI_H_ 20 + 21 + struct nxp_nci_nfc_platform_data { 22 + unsigned int gpio_en; 23 + unsigned int gpio_fw; 24 + unsigned int irq; 25 + }; 26 + 27 + #endif /* _NXP_NCI_H_ */