1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Generic driver for NXP NCI NFC chips 4 * 5 * Copyright (C) 2014 NXP Semiconductors All rights reserved. 6 * 7 * Authors: Clément Perrochaud <clement.perrochaud@nxp.com> 8 * 9 * Derived from PN544 device driver: 10 * Copyright (C) 2012 Intel Corporation. All rights reserved. 11 */ 12 13 #include <linux/delay.h> 14 #include <linux/module.h> 15 #include <linux/nfc.h> 16 17 #include <net/nfc/nci_core.h> 18 19 #include "nxp-nci.h" 20 21 #define NXP_NCI_HDR_LEN 4 22 23 #define NXP_NCI_NFC_PROTOCOLS (NFC_PROTO_JEWEL_MASK | \ 24 NFC_PROTO_MIFARE_MASK | \ 25 NFC_PROTO_FELICA_MASK | \ 26 NFC_PROTO_ISO14443_MASK | \ 27 NFC_PROTO_ISO14443_B_MASK | \ 28 NFC_PROTO_NFC_DEP_MASK) 29 30 #define NXP_NCI_RF_PLL_UNLOCKED_NTF nci_opcode_pack(NCI_GID_RF_MGMT, 0x21) 31 #define NXP_NCI_RF_TXLDO_ERROR_NTF nci_opcode_pack(NCI_GID_RF_MGMT, 0x23) 32 33 static int nxp_nci_open(struct nci_dev *ndev) 34 { 35 struct nxp_nci_info *info = nci_get_drvdata(ndev); 36 int r = 0; 37 38 mutex_lock(&info->info_lock); 39 40 if (info->mode != NXP_NCI_MODE_COLD) { 41 r = -EBUSY; 42 goto open_exit; 43 } 44 45 if (info->phy_ops->set_mode) 46 r = info->phy_ops->set_mode(info->phy_id, NXP_NCI_MODE_NCI); 47 48 info->mode = NXP_NCI_MODE_NCI; 49 50 open_exit: 51 mutex_unlock(&info->info_lock); 52 return r; 53 } 54 55 static int nxp_nci_close(struct nci_dev *ndev) 56 { 57 struct nxp_nci_info *info = nci_get_drvdata(ndev); 58 int r = 0; 59 60 mutex_lock(&info->info_lock); 61 62 if (info->phy_ops->set_mode) 63 r = info->phy_ops->set_mode(info->phy_id, NXP_NCI_MODE_COLD); 64 65 info->mode = NXP_NCI_MODE_COLD; 66 67 mutex_unlock(&info->info_lock); 68 return r; 69 } 70 71 static int nxp_nci_send(struct nci_dev *ndev, struct sk_buff *skb) 72 { 73 struct nxp_nci_info *info = nci_get_drvdata(ndev); 74 int r; 75 76 if (!info->phy_ops->write) 77 return -EOPNOTSUPP; 78 79 if (info->mode != NXP_NCI_MODE_NCI) 80 return -EINVAL; 81 82 r = info->phy_ops->write(info->phy_id, skb); 83 if (r < 0) 84 kfree_skb(skb); 85 86 return r; 87 } 88 89 static int nxp_nci_rf_pll_unlocked_ntf(struct nci_dev *ndev, 90 struct sk_buff *skb) 91 { 92 nfc_err(&ndev->nfc_dev->dev, 93 "PLL didn't lock. Missing or unstable clock?\n"); 94 95 return 0; 96 } 97 98 static int nxp_nci_rf_txldo_error_ntf(struct nci_dev *ndev, 99 struct sk_buff *skb) 100 { 101 nfc_err(&ndev->nfc_dev->dev, 102 "RF transmitter couldn't start. Bad power and/or configuration?\n"); 103 104 return 0; 105 } 106 107 static const struct nci_driver_ops nxp_nci_core_ops[] = { 108 { 109 .opcode = NXP_NCI_RF_PLL_UNLOCKED_NTF, 110 .ntf = nxp_nci_rf_pll_unlocked_ntf, 111 }, 112 { 113 .opcode = NXP_NCI_RF_TXLDO_ERROR_NTF, 114 .ntf = nxp_nci_rf_txldo_error_ntf, 115 }, 116 }; 117 118 static const struct nci_ops nxp_nci_ops = { 119 .open = nxp_nci_open, 120 .close = nxp_nci_close, 121 .send = nxp_nci_send, 122 .fw_download = nxp_nci_fw_download, 123 .core_ops = nxp_nci_core_ops, 124 .n_core_ops = ARRAY_SIZE(nxp_nci_core_ops), 125 }; 126 127 int nxp_nci_probe(void *phy_id, struct device *pdev, 128 const struct nxp_nci_phy_ops *phy_ops, 129 unsigned int max_payload, 130 struct nci_dev **ndev) 131 { 132 struct nxp_nci_info *info; 133 int r; 134 135 info = devm_kzalloc(pdev, sizeof(struct nxp_nci_info), GFP_KERNEL); 136 if (!info) 137 return -ENOMEM; 138 139 info->phy_id = phy_id; 140 info->pdev = pdev; 141 info->phy_ops = phy_ops; 142 info->max_payload = max_payload; 143 INIT_WORK(&info->fw_info.work, nxp_nci_fw_work); 144 init_completion(&info->fw_info.cmd_completion); 145 mutex_init(&info->info_lock); 146 147 if (info->phy_ops->set_mode) { 148 r = info->phy_ops->set_mode(info->phy_id, NXP_NCI_MODE_COLD); 149 if (r < 0) 150 return r; 151 } 152 153 info->mode = NXP_NCI_MODE_COLD; 154 155 info->ndev = nci_allocate_device(&nxp_nci_ops, NXP_NCI_NFC_PROTOCOLS, 156 NXP_NCI_HDR_LEN, 0); 157 if (!info->ndev) 158 return -ENOMEM; 159 160 nci_set_parent_dev(info->ndev, pdev); 161 nci_set_drvdata(info->ndev, info); 162 r = nci_register_device(info->ndev); 163 if (r < 0) { 164 nci_free_device(info->ndev); 165 return r; 166 } 167 168 *ndev = info->ndev; 169 return r; 170 } 171 EXPORT_SYMBOL(nxp_nci_probe); 172 173 void nxp_nci_remove(struct nci_dev *ndev) 174 { 175 struct nxp_nci_info *info = nci_get_drvdata(ndev); 176 177 if (info->mode == NXP_NCI_MODE_FW) 178 nxp_nci_fw_work_complete(info, -ESHUTDOWN); 179 cancel_work_sync(&info->fw_info.work); 180 181 mutex_lock(&info->info_lock); 182 183 if (info->phy_ops->set_mode) 184 info->phy_ops->set_mode(info->phy_id, NXP_NCI_MODE_COLD); 185 186 nci_unregister_device(ndev); 187 nci_free_device(ndev); 188 189 mutex_unlock(&info->info_lock); 190 } 191 EXPORT_SYMBOL(nxp_nci_remove); 192 193 MODULE_LICENSE("GPL"); 194 MODULE_DESCRIPTION("NXP NCI NFC driver"); 195 MODULE_AUTHOR("Clément Perrochaud <clement.perrochaud@nxp.com>"); 196