1 /* 2 * Marvell NFC driver: major functions 3 * 4 * Copyright (C) 2014, Marvell International Ltd. 5 * 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. 12 * 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. 17 */ 18 19 #include <linux/module.h> 20 #include <linux/nfc.h> 21 #include <net/nfc/nci.h> 22 #include <net/nfc/nci_core.h> 23 #include "nfcmrvl.h" 24 25 #define VERSION "1.0" 26 27 static int nfcmrvl_nci_open(struct nci_dev *ndev) 28 { 29 struct nfcmrvl_private *priv = nci_get_drvdata(ndev); 30 int err; 31 32 if (test_and_set_bit(NFCMRVL_NCI_RUNNING, &priv->flags)) 33 return 0; 34 35 err = priv->if_ops->nci_open(priv); 36 37 if (err) 38 clear_bit(NFCMRVL_NCI_RUNNING, &priv->flags); 39 40 return err; 41 } 42 43 static int nfcmrvl_nci_close(struct nci_dev *ndev) 44 { 45 struct nfcmrvl_private *priv = nci_get_drvdata(ndev); 46 47 if (!test_and_clear_bit(NFCMRVL_NCI_RUNNING, &priv->flags)) 48 return 0; 49 50 priv->if_ops->nci_close(priv); 51 52 return 0; 53 } 54 55 static int nfcmrvl_nci_send(struct nci_dev *ndev, struct sk_buff *skb) 56 { 57 struct nfcmrvl_private *priv = nci_get_drvdata(ndev); 58 59 nfc_info(priv->dev, "send entry, len %d\n", skb->len); 60 61 skb->dev = (void *)ndev; 62 63 if (!test_bit(NFCMRVL_NCI_RUNNING, &priv->flags)) 64 return -EBUSY; 65 66 return priv->if_ops->nci_send(priv, skb); 67 } 68 69 static int nfcmrvl_nci_setup(struct nci_dev *ndev) 70 { 71 __u8 val; 72 73 val = NFCMRVL_GPIO_PIN_NFC_NOT_ALLOWED; 74 nci_set_config(ndev, NFCMRVL_NOT_ALLOWED_ID, 1, &val); 75 val = NFCMRVL_GPIO_PIN_NFC_ACTIVE; 76 nci_set_config(ndev, NFCMRVL_ACTIVE_ID, 1, &val); 77 val = NFCMRVL_EXT_COEX_ENABLE; 78 nci_set_config(ndev, NFCMRVL_EXT_COEX_ID, 1, &val); 79 80 return 0; 81 } 82 83 static struct nci_ops nfcmrvl_nci_ops = { 84 .open = nfcmrvl_nci_open, 85 .close = nfcmrvl_nci_close, 86 .send = nfcmrvl_nci_send, 87 .setup = nfcmrvl_nci_setup, 88 }; 89 90 struct nfcmrvl_private *nfcmrvl_nci_register_dev(void *drv_data, 91 struct nfcmrvl_if_ops *ops, 92 struct device *dev) 93 { 94 struct nfcmrvl_private *priv; 95 int rc; 96 u32 protocols; 97 98 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 99 if (!priv) 100 return ERR_PTR(-ENOMEM); 101 102 priv->drv_data = drv_data; 103 priv->if_ops = ops; 104 priv->dev = dev; 105 106 protocols = NFC_PROTO_JEWEL_MASK 107 | NFC_PROTO_MIFARE_MASK | NFC_PROTO_FELICA_MASK 108 | NFC_PROTO_ISO14443_MASK 109 | NFC_PROTO_ISO14443_B_MASK 110 | NFC_PROTO_NFC_DEP_MASK; 111 112 priv->ndev = nci_allocate_device(&nfcmrvl_nci_ops, protocols, 0, 0); 113 if (!priv->ndev) { 114 nfc_err(dev, "nci_allocate_device failed\n"); 115 rc = -ENOMEM; 116 goto error; 117 } 118 119 nci_set_drvdata(priv->ndev, priv); 120 121 rc = nci_register_device(priv->ndev); 122 if (rc) { 123 nfc_err(dev, "nci_register_device failed %d\n", rc); 124 nci_free_device(priv->ndev); 125 goto error; 126 } 127 128 nfc_info(dev, "registered with nci successfully\n"); 129 return priv; 130 131 error: 132 kfree(priv); 133 return ERR_PTR(rc); 134 } 135 EXPORT_SYMBOL_GPL(nfcmrvl_nci_register_dev); 136 137 void nfcmrvl_nci_unregister_dev(struct nfcmrvl_private *priv) 138 { 139 struct nci_dev *ndev = priv->ndev; 140 141 nci_unregister_device(ndev); 142 nci_free_device(ndev); 143 kfree(priv); 144 } 145 EXPORT_SYMBOL_GPL(nfcmrvl_nci_unregister_dev); 146 147 int nfcmrvl_nci_recv_frame(struct nfcmrvl_private *priv, void *data, int count) 148 { 149 struct sk_buff *skb; 150 151 skb = nci_skb_alloc(priv->ndev, count, GFP_ATOMIC); 152 if (!skb) 153 return -ENOMEM; 154 155 memcpy(skb_put(skb, count), data, count); 156 nci_recv_frame(priv->ndev, skb); 157 158 return count; 159 } 160 EXPORT_SYMBOL_GPL(nfcmrvl_nci_recv_frame); 161 162 MODULE_AUTHOR("Marvell International Ltd."); 163 MODULE_DESCRIPTION("Marvell NFC driver ver " VERSION); 164 MODULE_VERSION(VERSION); 165 MODULE_LICENSE("GPL v2"); 166