Skip to content

Commit dece458

Browse files
Clément PerrochaudSamuel Ortiz
authored andcommitted
NFC: nxp-nci: Add support for NXP NCI chips
Add support for NXP NCI NFC controllers such as the NPC100 or PN7150 families. Signed-off-by: Clément Perrochaud <clement.perrochaud@effinnov.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
1 parent 25af01e commit dece458

File tree

9 files changed

+657
-0
lines changed

9 files changed

+657
-0
lines changed

MAINTAINERS

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6937,6 +6937,13 @@ S: Supported
69376937
F: drivers/block/nvme*
69386938
F: include/linux/nvme.h
69396939

6940+
NXP-NCI NFC DRIVER
6941+
M: Clément Perrochaud <clement.perrochaud@effinnov.com>
6942+
R: Charles Gorand <charles.gorand@effinnov.com>
6943+
L: linux-nfc@lists.01.org (moderated for non-subscribers)
6944+
S: Supported
6945+
F: drivers/nfc/nxp-nci
6946+
69406947
NXP TDA998X DRM DRIVER
69416948
M: Russell King <rmk+kernel@arm.linux.org.uk>
69426949
S: Supported

drivers/nfc/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,5 @@ source "drivers/nfc/microread/Kconfig"
7373
source "drivers/nfc/nfcmrvl/Kconfig"
7474
source "drivers/nfc/st21nfca/Kconfig"
7575
source "drivers/nfc/st21nfcb/Kconfig"
76+
source "drivers/nfc/nxp-nci/Kconfig"
7677
endmenu

drivers/nfc/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@ obj-$(CONFIG_NFC_MRVL) += nfcmrvl/
1313
obj-$(CONFIG_NFC_TRF7970A) += trf7970a.o
1414
obj-$(CONFIG_NFC_ST21NFCA) += st21nfca/
1515
obj-$(CONFIG_NFC_ST21NFCB) += st21nfcb/
16+
obj-$(CONFIG_NFC_NXP_NCI) += nxp-nci/
1617

1718
ccflags-$(CONFIG_NFC_DEBUG) := -DDEBUG

drivers/nfc/nxp-nci/Kconfig

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
config NFC_NXP_NCI
2+
tristate "NXP-NCI NFC driver"
3+
depends on NFC_NCI
4+
default n
5+
---help---
6+
Generic core driver for NXP NCI chips such as the NPC100
7+
or PN7150 families.
8+
This is a driver based on the NCI NFC kernel layers and
9+
will thus not work with NXP libnfc library.
10+
11+
To compile this driver as a module, choose m here. The module will
12+
be called nxp_nci.
13+
Say N if unsure.

drivers/nfc/nxp-nci/Makefile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#
2+
# Makefile for NXP-NCI NFC driver
3+
#
4+
5+
nxp-nci-objs = core.o firmware.o
6+
7+
obj-$(CONFIG_NFC_NXP_NCI) += nxp-nci.o
8+
9+
ccflags-$(CONFIG_NFC_DEBUG) := -DDEBUG

drivers/nfc/nxp-nci/core.c

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
/*
2+
* Generic driver for NXP NCI NFC chips
3+
*
4+
* Copyright (C) 2014 NXP Semiconductors All rights reserved.
5+
*
6+
* Authors: Clément Perrochaud <clement.perrochaud@nxp.com>
7+
*
8+
* Derived from PN544 device driver:
9+
* Copyright (C) 2012 Intel Corporation. All rights reserved.
10+
*
11+
* This program is free software; you can redistribute it and/or modify it
12+
* under the terms and conditions of the GNU General Public License,
13+
* version 2, as published by the Free Software Foundation.
14+
*
15+
* This program is distributed in the hope that it will be useful,
16+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
* GNU General Public License for more details.
19+
*
20+
* You should have received a copy of the GNU General Public License
21+
* along with this program; if not, see <http://www.gnu.org/licenses/>.
22+
*/
23+
24+
#include <linux/delay.h>
25+
#include <linux/gpio.h>
26+
#include <linux/module.h>
27+
#include <linux/nfc.h>
28+
#include <linux/platform_data/nxp-nci.h>
29+
30+
#include <net/nfc/nci_core.h>
31+
32+
#include "nxp-nci.h"
33+
34+
#define NXP_NCI_HDR_LEN 4
35+
36+
#define NXP_NCI_NFC_PROTOCOLS (NFC_PROTO_JEWEL_MASK | \
37+
NFC_PROTO_MIFARE_MASK | \
38+
NFC_PROTO_FELICA_MASK | \
39+
NFC_PROTO_ISO14443_MASK | \
40+
NFC_PROTO_ISO14443_B_MASK | \
41+
NFC_PROTO_NFC_DEP_MASK)
42+
43+
static int nxp_nci_open(struct nci_dev *ndev)
44+
{
45+
struct nxp_nci_info *info = nci_get_drvdata(ndev);
46+
int r = 0;
47+
48+
mutex_lock(&info->info_lock);
49+
50+
if (info->mode != NXP_NCI_MODE_COLD) {
51+
r = -EBUSY;
52+
goto open_exit;
53+
}
54+
55+
if (info->phy_ops->set_mode)
56+
r = info->phy_ops->set_mode(info->phy_id, NXP_NCI_MODE_NCI);
57+
58+
info->mode = NXP_NCI_MODE_NCI;
59+
60+
open_exit:
61+
mutex_unlock(&info->info_lock);
62+
return r;
63+
}
64+
65+
static int nxp_nci_close(struct nci_dev *ndev)
66+
{
67+
struct nxp_nci_info *info = nci_get_drvdata(ndev);
68+
int r = 0;
69+
70+
mutex_lock(&info->info_lock);
71+
72+
if (info->phy_ops->set_mode)
73+
r = info->phy_ops->set_mode(info->phy_id, NXP_NCI_MODE_COLD);
74+
75+
info->mode = NXP_NCI_MODE_COLD;
76+
77+
mutex_unlock(&info->info_lock);
78+
return r;
79+
}
80+
81+
static int nxp_nci_send(struct nci_dev *ndev, struct sk_buff *skb)
82+
{
83+
struct nxp_nci_info *info = nci_get_drvdata(ndev);
84+
int r;
85+
86+
if (!info->phy_ops->write) {
87+
r = -ENOTSUPP;
88+
goto send_exit;
89+
}
90+
91+
if (info->mode != NXP_NCI_MODE_NCI) {
92+
r = -EINVAL;
93+
goto send_exit;
94+
}
95+
96+
r = info->phy_ops->write(info->phy_id, skb);
97+
if (r < 0)
98+
kfree_skb(skb);
99+
100+
send_exit:
101+
return r;
102+
}
103+
104+
static struct nci_ops nxp_nci_ops = {
105+
.open = nxp_nci_open,
106+
.close = nxp_nci_close,
107+
.send = nxp_nci_send,
108+
.fw_download = nxp_nci_fw_download,
109+
};
110+
111+
int nxp_nci_probe(void *phy_id, struct device *pdev,
112+
struct nxp_nci_phy_ops *phy_ops, unsigned int max_payload,
113+
struct nci_dev **ndev)
114+
{
115+
struct nxp_nci_info *info;
116+
int r;
117+
118+
info = devm_kzalloc(pdev, sizeof(struct nxp_nci_info), GFP_KERNEL);
119+
if (!info) {
120+
r = -ENOMEM;
121+
goto probe_exit;
122+
}
123+
124+
info->phy_id = phy_id;
125+
info->pdev = pdev;
126+
info->phy_ops = phy_ops;
127+
info->max_payload = max_payload;
128+
INIT_WORK(&info->fw_info.work, nxp_nci_fw_work);
129+
init_completion(&info->fw_info.cmd_completion);
130+
mutex_init(&info->info_lock);
131+
132+
if (info->phy_ops->set_mode) {
133+
r = info->phy_ops->set_mode(info->phy_id, NXP_NCI_MODE_COLD);
134+
if (r < 0)
135+
goto probe_exit;
136+
}
137+
138+
info->mode = NXP_NCI_MODE_COLD;
139+
140+
info->ndev = nci_allocate_device(&nxp_nci_ops, NXP_NCI_NFC_PROTOCOLS,
141+
NXP_NCI_HDR_LEN, 0);
142+
if (!info->ndev) {
143+
r = -ENOMEM;
144+
goto probe_exit;
145+
}
146+
147+
nci_set_parent_dev(info->ndev, pdev);
148+
nci_set_drvdata(info->ndev, info);
149+
r = nci_register_device(info->ndev);
150+
if (r < 0)
151+
goto probe_exit_free_nci;
152+
153+
*ndev = info->ndev;
154+
155+
goto probe_exit;
156+
157+
probe_exit_free_nci:
158+
nci_free_device(info->ndev);
159+
probe_exit:
160+
return r;
161+
}
162+
EXPORT_SYMBOL(nxp_nci_probe);
163+
164+
void nxp_nci_remove(struct nci_dev *ndev)
165+
{
166+
struct nxp_nci_info *info = nci_get_drvdata(ndev);
167+
168+
if (info->mode == NXP_NCI_MODE_FW)
169+
nxp_nci_fw_work_complete(info, -ESHUTDOWN);
170+
cancel_work_sync(&info->fw_info.work);
171+
172+
mutex_lock(&info->info_lock);
173+
174+
if (info->phy_ops->set_mode)
175+
info->phy_ops->set_mode(info->phy_id, NXP_NCI_MODE_COLD);
176+
177+
nci_unregister_device(ndev);
178+
nci_free_device(ndev);
179+
180+
mutex_unlock(&info->info_lock);
181+
}
182+
EXPORT_SYMBOL(nxp_nci_remove);
183+
184+
MODULE_LICENSE("GPL");
185+
MODULE_DESCRIPTION("NXP NCI NFC driver");
186+
MODULE_AUTHOR("Clément Perrochaud <clement.perrochaud@nxp.com>");

0 commit comments

Comments
 (0)