2 * Marvell NFC driver: major functions
4 * Copyright (C) 2014-2015 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/gpio.h>
21 #include <linux/delay.h>
22 #include <linux/of_gpio.h>
23 #include <linux/nfc.h>
24 #include <net/nfc/nci.h>
25 #include <net/nfc/nci_core.h>
28 static int nfcmrvl_nci_open(struct nci_dev
*ndev
)
30 struct nfcmrvl_private
*priv
= nci_get_drvdata(ndev
);
33 if (test_and_set_bit(NFCMRVL_NCI_RUNNING
, &priv
->flags
))
36 /* Reset possible fault of previous session */
37 clear_bit(NFCMRVL_PHY_ERROR
, &priv
->flags
);
39 err
= priv
->if_ops
->nci_open(priv
);
42 clear_bit(NFCMRVL_NCI_RUNNING
, &priv
->flags
);
47 static int nfcmrvl_nci_close(struct nci_dev
*ndev
)
49 struct nfcmrvl_private
*priv
= nci_get_drvdata(ndev
);
51 if (!test_and_clear_bit(NFCMRVL_NCI_RUNNING
, &priv
->flags
))
54 priv
->if_ops
->nci_close(priv
);
59 static int nfcmrvl_nci_send(struct nci_dev
*ndev
, struct sk_buff
*skb
)
61 struct nfcmrvl_private
*priv
= nci_get_drvdata(ndev
);
63 nfc_info(priv
->dev
, "send entry, len %d\n", skb
->len
);
65 skb
->dev
= (void *)ndev
;
67 if (priv
->config
.hci_muxed
) {
69 unsigned char len
= skb
->len
;
71 hdr
= (char *) skb_push(skb
, NFCMRVL_HCI_EVENT_HEADER_SIZE
);
72 hdr
[0] = NFCMRVL_HCI_COMMAND_CODE
;
73 hdr
[1] = NFCMRVL_HCI_OGF
;
74 hdr
[2] = NFCMRVL_HCI_OCF
;
78 return priv
->if_ops
->nci_send(priv
, skb
);
81 static int nfcmrvl_nci_setup(struct nci_dev
*ndev
)
85 nci_set_config(ndev
, NFCMRVL_PB_BAIL_OUT
, 1, &val
);
89 static int nfcmrvl_nci_fw_download(struct nci_dev
*ndev
,
90 const char *firmware_name
)
92 return nfcmrvl_fw_dnld_start(ndev
, firmware_name
);
95 static struct nci_ops nfcmrvl_nci_ops
= {
96 .open
= nfcmrvl_nci_open
,
97 .close
= nfcmrvl_nci_close
,
98 .send
= nfcmrvl_nci_send
,
99 .setup
= nfcmrvl_nci_setup
,
100 .fw_download
= nfcmrvl_nci_fw_download
,
103 struct nfcmrvl_private
*nfcmrvl_nci_register_dev(enum nfcmrvl_phy phy
,
105 struct nfcmrvl_if_ops
*ops
,
107 struct nfcmrvl_platform_data
*pdata
)
109 struct nfcmrvl_private
*priv
;
115 priv
= kzalloc(sizeof(*priv
), GFP_KERNEL
);
117 return ERR_PTR(-ENOMEM
);
119 priv
->drv_data
= drv_data
;
124 memcpy(&priv
->config
, pdata
, sizeof(*pdata
));
126 if (priv
->config
.reset_n_io
) {
127 rc
= devm_gpio_request_one(dev
,
128 priv
->config
.reset_n_io
,
132 nfc_err(dev
, "failed to request reset_n io\n");
135 if (phy
== NFCMRVL_PHY_SPI
) {
136 headroom
= NCI_SPI_HDR_LEN
;
139 headroom
= tailroom
= 0;
141 if (priv
->config
.hci_muxed
)
142 headroom
+= NFCMRVL_HCI_EVENT_HEADER_SIZE
;
144 protocols
= NFC_PROTO_JEWEL_MASK
145 | NFC_PROTO_MIFARE_MASK
146 | NFC_PROTO_FELICA_MASK
147 | NFC_PROTO_ISO14443_MASK
148 | NFC_PROTO_ISO14443_B_MASK
149 | NFC_PROTO_ISO15693_MASK
150 | NFC_PROTO_NFC_DEP_MASK
;
152 priv
->ndev
= nci_allocate_device(&nfcmrvl_nci_ops
, protocols
,
155 nfc_err(dev
, "nci_allocate_device failed\n");
160 nci_set_drvdata(priv
->ndev
, priv
);
162 rc
= nci_register_device(priv
->ndev
);
164 nfc_err(dev
, "nci_register_device failed %d\n", rc
);
168 /* Ensure that controller is powered off */
169 nfcmrvl_chip_halt(priv
);
171 rc
= nfcmrvl_fw_dnld_init(priv
);
173 nfc_err(dev
, "failed to initialize FW download %d\n", rc
);
177 nfc_info(dev
, "registered with nci successfully\n");
181 nci_free_device(priv
->ndev
);
186 EXPORT_SYMBOL_GPL(nfcmrvl_nci_register_dev
);
188 void nfcmrvl_nci_unregister_dev(struct nfcmrvl_private
*priv
)
190 struct nci_dev
*ndev
= priv
->ndev
;
192 if (priv
->ndev
->nfc_dev
->fw_download_in_progress
)
193 nfcmrvl_fw_dnld_abort(priv
);
195 nfcmrvl_fw_dnld_deinit(priv
);
197 if (priv
->config
.reset_n_io
)
198 devm_gpio_free(priv
->dev
, priv
->config
.reset_n_io
);
200 nci_unregister_device(ndev
);
201 nci_free_device(ndev
);
204 EXPORT_SYMBOL_GPL(nfcmrvl_nci_unregister_dev
);
206 int nfcmrvl_nci_recv_frame(struct nfcmrvl_private
*priv
, struct sk_buff
*skb
)
208 if (priv
->config
.hci_muxed
) {
209 if (skb
->data
[0] == NFCMRVL_HCI_EVENT_CODE
&&
210 skb
->data
[1] == NFCMRVL_HCI_NFC_EVENT_CODE
) {
211 /* Data packet, let's extract NCI payload */
212 skb_pull(skb
, NFCMRVL_HCI_EVENT_HEADER_SIZE
);
214 /* Skip this packet */
220 if (priv
->ndev
->nfc_dev
->fw_download_in_progress
) {
221 nfcmrvl_fw_dnld_recv_frame(priv
, skb
);
225 if (test_bit(NFCMRVL_NCI_RUNNING
, &priv
->flags
))
226 nci_recv_frame(priv
->ndev
, skb
);
228 /* Drop this packet since nobody wants it */
235 EXPORT_SYMBOL_GPL(nfcmrvl_nci_recv_frame
);
237 void nfcmrvl_chip_reset(struct nfcmrvl_private
*priv
)
239 /* Reset possible fault of previous session */
240 clear_bit(NFCMRVL_PHY_ERROR
, &priv
->flags
);
242 if (priv
->config
.reset_n_io
) {
243 nfc_info(priv
->dev
, "reset the chip\n");
244 gpio_set_value(priv
->config
.reset_n_io
, 0);
245 usleep_range(5000, 10000);
246 gpio_set_value(priv
->config
.reset_n_io
, 1);
248 nfc_info(priv
->dev
, "no reset available on this interface\n");
251 void nfcmrvl_chip_halt(struct nfcmrvl_private
*priv
)
253 if (priv
->config
.reset_n_io
)
254 gpio_set_value(priv
->config
.reset_n_io
, 0);
257 int nfcmrvl_parse_dt(struct device_node
*node
,
258 struct nfcmrvl_platform_data
*pdata
)
262 reset_n_io
= of_get_named_gpio(node
, "reset-n-io", 0);
263 if (reset_n_io
< 0) {
264 pr_info("no reset-n-io config\n");
266 } else if (!gpio_is_valid(reset_n_io
)) {
267 pr_err("invalid reset-n-io GPIO\n");
270 pdata
->reset_n_io
= reset_n_io
;
272 if (of_find_property(node
, "hci-muxed", NULL
))
273 pdata
->hci_muxed
= 1;
275 pdata
->hci_muxed
= 0;
279 EXPORT_SYMBOL_GPL(nfcmrvl_parse_dt
);
281 MODULE_AUTHOR("Marvell International Ltd.");
282 MODULE_DESCRIPTION("Marvell NFC driver");
283 MODULE_LICENSE("GPL v2");