1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * NCI based Driver for STMicroelectronics NFC Chip 4 * 5 * Copyright (C) 2014-2015 STMicroelectronics SAS. All rights reserved. 6 */ 7 8 #include <linux/module.h> 9 #include <linux/nfc.h> 10 #include <net/nfc/nci.h> 11 #include <net/nfc/nci_core.h> 12 #include <linux/gpio.h> 13 #include <linux/delay.h> 14 15 #include "st-nci.h" 16 17 #define DRIVER_DESC "NCI NFC driver for ST_NCI" 18 19 #define ST_NCI1_X_PROPRIETARY_ISO15693 0x83 20 21 static int st_nci_init(struct nci_dev *ndev) 22 { 23 struct nci_mode_set_cmd cmd; 24 25 cmd.cmd_type = ST_NCI_SET_NFC_MODE; 26 cmd.mode = 1; 27 28 return nci_prop_cmd(ndev, ST_NCI_CORE_PROP, 29 sizeof(struct nci_mode_set_cmd), (__u8 *)&cmd); 30 } 31 32 static int st_nci_open(struct nci_dev *ndev) 33 { 34 struct st_nci_info *info = nci_get_drvdata(ndev); 35 int r; 36 37 if (test_and_set_bit(ST_NCI_RUNNING, &info->flags)) 38 return 0; 39 40 r = ndlc_open(info->ndlc); 41 if (r) 42 clear_bit(ST_NCI_RUNNING, &info->flags); 43 44 return r; 45 } 46 47 static int st_nci_close(struct nci_dev *ndev) 48 { 49 struct st_nci_info *info = nci_get_drvdata(ndev); 50 51 if (!test_bit(ST_NCI_RUNNING, &info->flags)) 52 return 0; 53 54 ndlc_close(info->ndlc); 55 56 clear_bit(ST_NCI_RUNNING, &info->flags); 57 58 return 0; 59 } 60 61 static int st_nci_send(struct nci_dev *ndev, struct sk_buff *skb) 62 { 63 struct st_nci_info *info = nci_get_drvdata(ndev); 64 65 skb->dev = (void *)ndev; 66 67 if (!test_bit(ST_NCI_RUNNING, &info->flags)) 68 return -EBUSY; 69 70 return ndlc_send(info->ndlc, skb); 71 } 72 73 static __u32 st_nci_get_rfprotocol(struct nci_dev *ndev, 74 __u8 rf_protocol) 75 { 76 return rf_protocol == ST_NCI1_X_PROPRIETARY_ISO15693 ? 77 NFC_PROTO_ISO15693_MASK : 0; 78 } 79 80 static int st_nci_prop_rsp_packet(struct nci_dev *ndev, 81 struct sk_buff *skb) 82 { 83 __u8 status = skb->data[0]; 84 85 nci_req_complete(ndev, status); 86 return 0; 87 } 88 89 static struct nci_driver_ops st_nci_prop_ops[] = { 90 { 91 .opcode = nci_opcode_pack(NCI_GID_PROPRIETARY, 92 ST_NCI_CORE_PROP), 93 .rsp = st_nci_prop_rsp_packet, 94 }, 95 }; 96 97 static struct nci_ops st_nci_ops = { 98 .init = st_nci_init, 99 .open = st_nci_open, 100 .close = st_nci_close, 101 .send = st_nci_send, 102 .get_rfprotocol = st_nci_get_rfprotocol, 103 .discover_se = st_nci_discover_se, 104 .enable_se = st_nci_enable_se, 105 .disable_se = st_nci_disable_se, 106 .se_io = st_nci_se_io, 107 .hci_load_session = st_nci_hci_load_session, 108 .hci_event_received = st_nci_hci_event_received, 109 .hci_cmd_received = st_nci_hci_cmd_received, 110 .prop_ops = st_nci_prop_ops, 111 .n_prop_ops = ARRAY_SIZE(st_nci_prop_ops), 112 }; 113 114 int st_nci_probe(struct llt_ndlc *ndlc, int phy_headroom, 115 int phy_tailroom, struct st_nci_se_status *se_status) 116 { 117 struct st_nci_info *info; 118 int r; 119 u32 protocols; 120 121 info = devm_kzalloc(ndlc->dev, 122 sizeof(struct st_nci_info), GFP_KERNEL); 123 if (!info) 124 return -ENOMEM; 125 126 protocols = NFC_PROTO_JEWEL_MASK 127 | NFC_PROTO_MIFARE_MASK 128 | NFC_PROTO_FELICA_MASK 129 | NFC_PROTO_ISO14443_MASK 130 | NFC_PROTO_ISO14443_B_MASK 131 | NFC_PROTO_ISO15693_MASK 132 | NFC_PROTO_NFC_DEP_MASK; 133 134 ndlc->ndev = nci_allocate_device(&st_nci_ops, protocols, 135 phy_headroom, phy_tailroom); 136 if (!ndlc->ndev) { 137 pr_err("Cannot allocate nfc ndev\n"); 138 return -ENOMEM; 139 } 140 info->ndlc = ndlc; 141 142 nci_set_drvdata(ndlc->ndev, info); 143 144 r = st_nci_vendor_cmds_init(ndlc->ndev); 145 if (r) { 146 pr_err("Cannot register proprietary vendor cmds\n"); 147 goto err_reg_dev; 148 } 149 150 r = nci_register_device(ndlc->ndev); 151 if (r) { 152 pr_err("Cannot register nfc device to nci core\n"); 153 goto err_reg_dev; 154 } 155 156 return st_nci_se_init(ndlc->ndev, se_status); 157 158 err_reg_dev: 159 nci_free_device(ndlc->ndev); 160 return r; 161 } 162 EXPORT_SYMBOL_GPL(st_nci_probe); 163 164 void st_nci_remove(struct nci_dev *ndev) 165 { 166 struct st_nci_info *info = nci_get_drvdata(ndev); 167 168 ndlc_close(info->ndlc); 169 170 nci_unregister_device(ndev); 171 nci_free_device(ndev); 172 } 173 EXPORT_SYMBOL_GPL(st_nci_remove); 174 175 MODULE_LICENSE("GPL"); 176 MODULE_DESCRIPTION(DRIVER_DESC); 177