PM / sleep: Asynchronous threads for suspend_noirq
[linux/fpc-iii.git] / drivers / nfc / nfcmrvl / main.c
blob85e8bcf986936123bdab959e5b01fb8738d80e79
1 /*
2 * Marvell NFC driver: major functions
4 * Copyright (C) 2014, Marvell International Ltd.
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.
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.
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"
25 #define VERSION "1.0"
27 static int nfcmrvl_nci_open(struct nci_dev *ndev)
29 struct nfcmrvl_private *priv = nci_get_drvdata(ndev);
30 int err;
32 if (test_and_set_bit(NFCMRVL_NCI_RUNNING, &priv->flags))
33 return 0;
35 err = priv->if_ops->nci_open(priv);
37 if (err)
38 clear_bit(NFCMRVL_NCI_RUNNING, &priv->flags);
40 return err;
43 static int nfcmrvl_nci_close(struct nci_dev *ndev)
45 struct nfcmrvl_private *priv = nci_get_drvdata(ndev);
47 if (!test_and_clear_bit(NFCMRVL_NCI_RUNNING, &priv->flags))
48 return 0;
50 priv->if_ops->nci_close(priv);
52 return 0;
55 static int nfcmrvl_nci_send(struct nci_dev *ndev, struct sk_buff *skb)
57 struct nfcmrvl_private *priv = nci_get_drvdata(ndev);
59 nfc_info(priv->dev, "send entry, len %d\n", skb->len);
61 skb->dev = (void *)ndev;
63 if (!test_bit(NFCMRVL_NCI_RUNNING, &priv->flags))
64 return -EBUSY;
66 return priv->if_ops->nci_send(priv, skb);
69 static int nfcmrvl_nci_setup(struct nci_dev *ndev)
71 __u8 val;
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);
80 return 0;
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,
90 struct nfcmrvl_private *nfcmrvl_nci_register_dev(void *drv_data,
91 struct nfcmrvl_if_ops *ops,
92 struct device *dev)
94 struct nfcmrvl_private *priv;
95 int rc;
96 u32 protocols;
98 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
99 if (!priv)
100 return ERR_PTR(-ENOMEM);
102 priv->drv_data = drv_data;
103 priv->if_ops = ops;
104 priv->dev = dev;
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;
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;
119 nci_set_drvdata(priv->ndev, priv);
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;
128 nfc_info(dev, "registered with nci successfully\n");
129 return priv;
131 error:
132 kfree(priv);
133 return ERR_PTR(rc);
135 EXPORT_SYMBOL_GPL(nfcmrvl_nci_register_dev);
137 void nfcmrvl_nci_unregister_dev(struct nfcmrvl_private *priv)
139 struct nci_dev *ndev = priv->ndev;
141 nci_unregister_device(ndev);
142 nci_free_device(ndev);
143 kfree(priv);
145 EXPORT_SYMBOL_GPL(nfcmrvl_nci_unregister_dev);
147 int nfcmrvl_nci_recv_frame(struct nfcmrvl_private *priv, void *data, int count)
149 struct sk_buff *skb;
151 skb = nci_skb_alloc(priv->ndev, count, GFP_ATOMIC);
152 if (!skb)
153 return -ENOMEM;
155 memcpy(skb_put(skb, count), data, count);
156 nci_recv_frame(priv->ndev, skb);
158 return count;
160 EXPORT_SYMBOL_GPL(nfcmrvl_nci_recv_frame);
162 MODULE_AUTHOR("Marvell International Ltd.");
163 MODULE_DESCRIPTION("Marvell NFC driver ver " VERSION);
164 MODULE_VERSION(VERSION);
165 MODULE_LICENSE("GPL v2");