1 // SPDX-License-Identifier: GPL-2.0-only
3 * Marvell NFC driver: major functions
5 * Copyright (C) 2014-2015 Marvell International Ltd.
8 #include <linux/module.h>
9 #include <linux/gpio.h>
10 #include <linux/delay.h>
11 #include <linux/of_gpio.h>
12 #include <linux/nfc.h>
13 #include <net/nfc/nci.h>
14 #include <net/nfc/nci_core.h>
17 static int nfcmrvl_nci_open(struct nci_dev
*ndev
)
19 struct nfcmrvl_private
*priv
= nci_get_drvdata(ndev
);
22 if (test_and_set_bit(NFCMRVL_NCI_RUNNING
, &priv
->flags
))
25 /* Reset possible fault of previous session */
26 clear_bit(NFCMRVL_PHY_ERROR
, &priv
->flags
);
28 err
= priv
->if_ops
->nci_open(priv
);
31 clear_bit(NFCMRVL_NCI_RUNNING
, &priv
->flags
);
36 static int nfcmrvl_nci_close(struct nci_dev
*ndev
)
38 struct nfcmrvl_private
*priv
= nci_get_drvdata(ndev
);
40 if (!test_and_clear_bit(NFCMRVL_NCI_RUNNING
, &priv
->flags
))
43 priv
->if_ops
->nci_close(priv
);
48 static int nfcmrvl_nci_send(struct nci_dev
*ndev
, struct sk_buff
*skb
)
50 struct nfcmrvl_private
*priv
= nci_get_drvdata(ndev
);
52 nfc_info(priv
->dev
, "send entry, len %d\n", skb
->len
);
54 skb
->dev
= (void *)ndev
;
56 if (priv
->config
.hci_muxed
) {
58 unsigned char len
= skb
->len
;
60 hdr
= skb_push(skb
, NFCMRVL_HCI_EVENT_HEADER_SIZE
);
61 hdr
[0] = NFCMRVL_HCI_COMMAND_CODE
;
62 hdr
[1] = NFCMRVL_HCI_OGF
;
63 hdr
[2] = NFCMRVL_HCI_OCF
;
67 return priv
->if_ops
->nci_send(priv
, skb
);
70 static int nfcmrvl_nci_setup(struct nci_dev
*ndev
)
74 nci_set_config(ndev
, NFCMRVL_PB_BAIL_OUT
, 1, &val
);
78 static int nfcmrvl_nci_fw_download(struct nci_dev
*ndev
,
79 const char *firmware_name
)
81 return nfcmrvl_fw_dnld_start(ndev
, firmware_name
);
84 static const struct nci_ops nfcmrvl_nci_ops
= {
85 .open
= nfcmrvl_nci_open
,
86 .close
= nfcmrvl_nci_close
,
87 .send
= nfcmrvl_nci_send
,
88 .setup
= nfcmrvl_nci_setup
,
89 .fw_download
= nfcmrvl_nci_fw_download
,
92 struct nfcmrvl_private
*nfcmrvl_nci_register_dev(enum nfcmrvl_phy phy
,
94 const struct nfcmrvl_if_ops
*ops
,
96 const struct nfcmrvl_platform_data
*pdata
)
98 struct nfcmrvl_private
*priv
;
104 priv
= kzalloc(sizeof(*priv
), GFP_KERNEL
);
106 return ERR_PTR(-ENOMEM
);
108 priv
->drv_data
= drv_data
;
113 memcpy(&priv
->config
, pdata
, sizeof(*pdata
));
115 if (gpio_is_valid(priv
->config
.reset_n_io
)) {
116 rc
= gpio_request_one(priv
->config
.reset_n_io
,
120 priv
->config
.reset_n_io
= -EINVAL
;
121 nfc_err(dev
, "failed to request reset_n io\n");
125 if (phy
== NFCMRVL_PHY_SPI
) {
126 headroom
= NCI_SPI_HDR_LEN
;
129 headroom
= tailroom
= 0;
131 if (priv
->config
.hci_muxed
)
132 headroom
+= NFCMRVL_HCI_EVENT_HEADER_SIZE
;
134 protocols
= NFC_PROTO_JEWEL_MASK
135 | NFC_PROTO_MIFARE_MASK
136 | NFC_PROTO_FELICA_MASK
137 | NFC_PROTO_ISO14443_MASK
138 | NFC_PROTO_ISO14443_B_MASK
139 | NFC_PROTO_ISO15693_MASK
140 | NFC_PROTO_NFC_DEP_MASK
;
142 priv
->ndev
= nci_allocate_device(&nfcmrvl_nci_ops
, protocols
,
145 nfc_err(dev
, "nci_allocate_device failed\n");
147 goto error_free_gpio
;
150 rc
= nfcmrvl_fw_dnld_init(priv
);
152 nfc_err(dev
, "failed to initialize FW download %d\n", rc
);
156 nci_set_drvdata(priv
->ndev
, priv
);
158 rc
= nci_register_device(priv
->ndev
);
160 nfc_err(dev
, "nci_register_device failed %d\n", rc
);
161 goto error_fw_dnld_deinit
;
164 /* Ensure that controller is powered off */
165 nfcmrvl_chip_halt(priv
);
167 nfc_info(dev
, "registered with nci successfully\n");
170 error_fw_dnld_deinit
:
171 nfcmrvl_fw_dnld_deinit(priv
);
173 nci_free_device(priv
->ndev
);
175 if (gpio_is_valid(priv
->config
.reset_n_io
))
176 gpio_free(priv
->config
.reset_n_io
);
180 EXPORT_SYMBOL_GPL(nfcmrvl_nci_register_dev
);
182 void nfcmrvl_nci_unregister_dev(struct nfcmrvl_private
*priv
)
184 struct nci_dev
*ndev
= priv
->ndev
;
186 nci_unregister_device(ndev
);
187 if (priv
->ndev
->nfc_dev
->fw_download_in_progress
)
188 nfcmrvl_fw_dnld_abort(priv
);
190 nfcmrvl_fw_dnld_deinit(priv
);
192 if (gpio_is_valid(priv
->config
.reset_n_io
))
193 gpio_free(priv
->config
.reset_n_io
);
195 nci_free_device(ndev
);
198 EXPORT_SYMBOL_GPL(nfcmrvl_nci_unregister_dev
);
200 int nfcmrvl_nci_recv_frame(struct nfcmrvl_private
*priv
, struct sk_buff
*skb
)
202 if (priv
->config
.hci_muxed
) {
203 if (skb
->data
[0] == NFCMRVL_HCI_EVENT_CODE
&&
204 skb
->data
[1] == NFCMRVL_HCI_NFC_EVENT_CODE
) {
205 /* Data packet, let's extract NCI payload */
206 skb_pull(skb
, NFCMRVL_HCI_EVENT_HEADER_SIZE
);
208 /* Skip this packet */
214 if (priv
->ndev
->nfc_dev
->fw_download_in_progress
) {
215 nfcmrvl_fw_dnld_recv_frame(priv
, skb
);
219 if (test_bit(NFCMRVL_NCI_RUNNING
, &priv
->flags
))
220 nci_recv_frame(priv
->ndev
, skb
);
222 /* Drop this packet since nobody wants it */
229 EXPORT_SYMBOL_GPL(nfcmrvl_nci_recv_frame
);
231 void nfcmrvl_chip_reset(struct nfcmrvl_private
*priv
)
233 /* Reset possible fault of previous session */
234 clear_bit(NFCMRVL_PHY_ERROR
, &priv
->flags
);
236 if (gpio_is_valid(priv
->config
.reset_n_io
)) {
237 nfc_info(priv
->dev
, "reset the chip\n");
238 gpio_set_value(priv
->config
.reset_n_io
, 0);
239 usleep_range(5000, 10000);
240 gpio_set_value(priv
->config
.reset_n_io
, 1);
242 nfc_info(priv
->dev
, "no reset available on this interface\n");
245 void nfcmrvl_chip_halt(struct nfcmrvl_private
*priv
)
247 if (gpio_is_valid(priv
->config
.reset_n_io
))
248 gpio_set_value(priv
->config
.reset_n_io
, 0);
251 int nfcmrvl_parse_dt(struct device_node
*node
,
252 struct nfcmrvl_platform_data
*pdata
)
256 reset_n_io
= of_get_named_gpio(node
, "reset-n-io", 0);
257 if (reset_n_io
< 0) {
258 pr_info("no reset-n-io config\n");
259 } else if (!gpio_is_valid(reset_n_io
)) {
260 pr_err("invalid reset-n-io GPIO\n");
263 pdata
->reset_n_io
= reset_n_io
;
264 pdata
->hci_muxed
= of_property_read_bool(node
, "hci-muxed");
268 EXPORT_SYMBOL_GPL(nfcmrvl_parse_dt
);
270 MODULE_AUTHOR("Marvell International Ltd.");
271 MODULE_DESCRIPTION("Marvell NFC driver");
272 MODULE_LICENSE("GPL v2");