xref: /openbmc/linux/drivers/nfc/nfcmrvl/main.c (revision c819e2cf)
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");
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", 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