summaryrefslogtreecommitdiff
path: root/drivers/nfc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-06-25 02:49:49 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2015-06-25 02:49:49 +0300
commite0456717e483bb8a9431b80a5bdc99a928b9b003 (patch)
tree5eb5add2bafd1f20326d70f5cb3b711d00a40b10 /drivers/nfc
parent98ec21a01896751b673b6c731ca8881daa8b2c6d (diff)
parent1ea2d020ba477cb7011a7174e8501a9e04a325d4 (diff)
downloadlinux-e0456717e483bb8a9431b80a5bdc99a928b9b003.tar.xz
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking updates from David Miller: 1) Add TX fast path in mac80211, from Johannes Berg. 2) Add TSO/GRO support to ibmveth, from Thomas Falcon 3) Move away from cached routes in ipv6, just like ipv4, from Martin KaFai Lau. 4) Lots of new rhashtable tests, from Thomas Graf. 5) Run ingress qdisc lockless, from Alexei Starovoitov. 6) Allow servers to fetch TCP packet headers for SYN packets of new connections, for fingerprinting. From Eric Dumazet. 7) Add mode parameter to pktgen, for testing receive. From Alexei Starovoitov. 8) Cache access optimizations via simplifications of build_skb(), from Alexander Duyck. 9) Move page frag allocator under mm/, also from Alexander. 10) Add xmit_more support to hv_netvsc, from KY Srinivasan. 11) Add a counter guard in case we try to perform endless reclassify loops in the packet scheduler. 12) Extern flow dissector to be programmable and use it in new "Flower" classifier. From Jiri Pirko. 13) AF_PACKET fanout rollover fixes, performance improvements, and new statistics. From Willem de Bruijn. 14) Add netdev driver for GENEVE tunnels, from John W Linville. 15) Add ingress netfilter hooks and filtering, from Pablo Neira Ayuso. 16) Fix handling of epoll edge triggers in TCP, from Eric Dumazet. 17) Add an ECN retry fallback for the initial TCP handshake, from Daniel Borkmann. 18) Add tail call support to BPF, from Alexei Starovoitov. 19) Add several pktgen helper scripts, from Jesper Dangaard Brouer. 20) Add zerocopy support to AF_UNIX, from Hannes Frederic Sowa. 21) Favor even port numbers for allocation to connect() requests, and odd port numbers for bind(0), in an effort to help avoid ip_local_port_range exhaustion. From Eric Dumazet. 22) Add Cavium ThunderX driver, from Sunil Goutham. 23) Allow bpf programs to access skb_iif and dev->ifindex SKB metadata, from Alexei Starovoitov. 24) Add support for T6 chips in cxgb4vf driver, from Hariprasad Shenai. 25) Double TCP Small Queues default to 256K to accomodate situations like the XEN driver and wireless aggregation. From Wei Liu. 26) Add more entropy inputs to flow dissector, from Tom Herbert. 27) Add CDG congestion control algorithm to TCP, from Kenneth Klette Jonassen. 28) Convert ipset over to RCU locking, from Jozsef Kadlecsik. 29) Track and act upon link status of ipv4 route nexthops, from Andy Gospodarek. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1670 commits) bridge: vlan: flush the dynamically learned entries on port vlan delete bridge: multicast: add a comment to br_port_state_selection about blocking state net: inet_diag: export IPV6_V6ONLY sockopt stmmac: troubleshoot unexpected bits in des0 & des1 net: ipv4 sysctl option to ignore routes when nexthop link is down net: track link-status of ipv4 nexthops net: switchdev: ignore unsupported bridge flags net: Cavium: Fix MAC address setting in shutdown state drivers: net: xgene: fix for ACPI support without ACPI ip: report the original address of ICMP messages net/mlx5e: Prefetch skb data on RX net/mlx5e: Pop cq outside mlx5e_get_cqe net/mlx5e: Remove mlx5e_cq.sqrq back-pointer net/mlx5e: Remove extra spaces net/mlx5e: Avoid TX CQE generation if more xmit packets expected net/mlx5e: Avoid redundant dev_kfree_skb() upon NOP completion net/mlx5e: Remove re-assignment of wq type in mlx5e_enable_rq() net/mlx5e: Use skb_shinfo(skb)->gso_segs rather than counting them net/mlx5e: Static mapping of netdev priv resources to/from netdev TX queues net/mlx4_en: Use HW counters for rx/tx bytes/packets in PF device ...
Diffstat (limited to 'drivers/nfc')
-rw-r--r--drivers/nfc/Kconfig2
-rw-r--r--drivers/nfc/Makefile4
-rw-r--r--drivers/nfc/microread/i2c.c3
-rw-r--r--drivers/nfc/nfcmrvl/Kconfig11
-rw-r--r--drivers/nfc/nfcmrvl/Makefile3
-rw-r--r--drivers/nfc/nfcmrvl/main.c134
-rw-r--r--drivers/nfc/nfcmrvl/nfcmrvl.h60
-rw-r--r--drivers/nfc/nfcmrvl/uart.c225
-rw-r--r--drivers/nfc/nfcmrvl/usb.c27
-rw-r--r--drivers/nfc/nxp-nci/Makefile2
-rw-r--r--drivers/nfc/nxp-nci/i2c.c52
-rw-r--r--drivers/nfc/pn544/i2c.c43
-rw-r--r--drivers/nfc/st-nci/Kconfig23
-rw-r--r--drivers/nfc/st-nci/Makefile9
-rw-r--r--drivers/nfc/st-nci/core.c179
-rw-r--r--drivers/nfc/st-nci/i2c.c (renamed from drivers/nfc/st21nfcb/i2c.c)147
-rw-r--r--drivers/nfc/st-nci/ndlc.c (renamed from drivers/nfc/st21nfcb/ndlc.c)23
-rw-r--r--drivers/nfc/st-nci/ndlc.h (renamed from drivers/nfc/st21nfcb/ndlc.h)5
-rw-r--r--drivers/nfc/st-nci/st-nci.h (renamed from drivers/nfc/st21nfcb/st21nfcb.h)30
-rw-r--r--drivers/nfc/st-nci/st-nci_se.c (renamed from drivers/nfc/st21nfcb/st21nfcb_se.c)383
-rw-r--r--drivers/nfc/st-nci/st-nci_se.h61
-rw-r--r--drivers/nfc/st21nfcb/Kconfig22
-rw-r--r--drivers/nfc/st21nfcb/Makefile9
-rw-r--r--drivers/nfc/st21nfcb/st21nfcb.c143
-rw-r--r--drivers/nfc/st21nfcb/st21nfcb_se.h61
-rw-r--r--drivers/nfc/trf7970a.c23
26 files changed, 1086 insertions, 598 deletions
diff --git a/drivers/nfc/Kconfig b/drivers/nfc/Kconfig
index 107714e4405f..722673cb785b 100644
--- a/drivers/nfc/Kconfig
+++ b/drivers/nfc/Kconfig
@@ -72,6 +72,6 @@ source "drivers/nfc/pn544/Kconfig"
source "drivers/nfc/microread/Kconfig"
source "drivers/nfc/nfcmrvl/Kconfig"
source "drivers/nfc/st21nfca/Kconfig"
-source "drivers/nfc/st21nfcb/Kconfig"
+source "drivers/nfc/st-nci/Kconfig"
source "drivers/nfc/nxp-nci/Kconfig"
endmenu
diff --git a/drivers/nfc/Makefile b/drivers/nfc/Makefile
index a4292d790f9b..368b6dfe71b3 100644
--- a/drivers/nfc/Makefile
+++ b/drivers/nfc/Makefile
@@ -12,7 +12,5 @@ obj-$(CONFIG_NFC_PORT100) += port100.o
obj-$(CONFIG_NFC_MRVL) += nfcmrvl/
obj-$(CONFIG_NFC_TRF7970A) += trf7970a.o
obj-$(CONFIG_NFC_ST21NFCA) += st21nfca/
-obj-$(CONFIG_NFC_ST21NFCB) += st21nfcb/
+obj-$(CONFIG_NFC_ST_NCI) += st-nci/
obj-$(CONFIG_NFC_NXP_NCI) += nxp-nci/
-
-ccflags-$(CONFIG_NFC_DEBUG) := -DDEBUG
diff --git a/drivers/nfc/microread/i2c.c b/drivers/nfc/microread/i2c.c
index 661e2c8143c4..daf352597ef8 100644
--- a/drivers/nfc/microread/i2c.c
+++ b/drivers/nfc/microread/i2c.c
@@ -211,7 +211,6 @@ flush:
static irqreturn_t microread_i2c_irq_thread_fn(int irq, void *phy_id)
{
struct microread_i2c_phy *phy = phy_id;
- struct i2c_client *client;
struct sk_buff *skb = NULL;
int r;
@@ -220,8 +219,6 @@ static irqreturn_t microread_i2c_irq_thread_fn(int irq, void *phy_id)
return IRQ_NONE;
}
- client = phy->i2c_dev;
-
if (phy->hard_fault != 0)
return IRQ_HANDLED;
diff --git a/drivers/nfc/nfcmrvl/Kconfig b/drivers/nfc/nfcmrvl/Kconfig
index 5e18afd9abe2..796be2411440 100644
--- a/drivers/nfc/nfcmrvl/Kconfig
+++ b/drivers/nfc/nfcmrvl/Kconfig
@@ -21,3 +21,14 @@ config NFC_MRVL_USB
Say Y here to compile support for Marvell NFC-over-USB driver
into the kernel or say M to compile it as module.
+
+config NFC_MRVL_UART
+ tristate "Marvell NFC-over-UART driver"
+ depends on NFC_MRVL && NFC_NCI_UART
+ help
+ Marvell NFC-over-UART driver.
+
+ This driver provides support for Marvell NFC-over-UART devices
+
+ Say Y here to compile support for Marvell NFC-over-UART driver
+ into the kernel or say M to compile it as module.
diff --git a/drivers/nfc/nfcmrvl/Makefile b/drivers/nfc/nfcmrvl/Makefile
index 97a0de72dc01..775196274d1f 100644
--- a/drivers/nfc/nfcmrvl/Makefile
+++ b/drivers/nfc/nfcmrvl/Makefile
@@ -7,3 +7,6 @@ obj-$(CONFIG_NFC_MRVL) += nfcmrvl.o
nfcmrvl_usb-y += usb.o
obj-$(CONFIG_NFC_MRVL_USB) += nfcmrvl_usb.o
+
+nfcmrvl_uart-y += uart.o
+obj-$(CONFIG_NFC_MRVL_UART) += nfcmrvl_uart.o
diff --git a/drivers/nfc/nfcmrvl/main.c b/drivers/nfc/nfcmrvl/main.c
index ad4933cefbd1..4a8866d62941 100644
--- a/drivers/nfc/nfcmrvl/main.c
+++ b/drivers/nfc/nfcmrvl/main.c
@@ -17,6 +17,9 @@
*/
#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/of_gpio.h>
#include <linux/nfc.h>
#include <net/nfc/nci.h>
#include <net/nfc/nci_core.h>
@@ -63,20 +66,25 @@ static int nfcmrvl_nci_send(struct nci_dev *ndev, struct sk_buff *skb)
if (!test_bit(NFCMRVL_NCI_RUNNING, &priv->flags))
return -EBUSY;
+ if (priv->config.hci_muxed) {
+ unsigned char *hdr;
+ unsigned char len = skb->len;
+
+ hdr = (char *) skb_push(skb, NFCMRVL_HCI_EVENT_HEADER_SIZE);
+ hdr[0] = NFCMRVL_HCI_COMMAND_CODE;
+ hdr[1] = NFCMRVL_HCI_OGF;
+ hdr[2] = NFCMRVL_HCI_OCF;
+ hdr[3] = len;
+ }
+
return priv->if_ops->nci_send(priv, skb);
}
static int nfcmrvl_nci_setup(struct nci_dev *ndev)
{
- __u8 val;
-
- val = NFCMRVL_GPIO_PIN_NFC_NOT_ALLOWED;
- nci_set_config(ndev, NFCMRVL_NOT_ALLOWED_ID, 1, &val);
- val = NFCMRVL_GPIO_PIN_NFC_ACTIVE;
- nci_set_config(ndev, NFCMRVL_ACTIVE_ID, 1, &val);
- val = NFCMRVL_EXT_COEX_ENABLE;
- nci_set_config(ndev, NFCMRVL_EXT_COEX_ID, 1, &val);
+ __u8 val = 1;
+ nci_set_config(ndev, NFCMRVL_PB_BAIL_OUT, 1, &val);
return 0;
}
@@ -88,11 +96,13 @@ static struct nci_ops nfcmrvl_nci_ops = {
};
struct nfcmrvl_private *nfcmrvl_nci_register_dev(void *drv_data,
- struct nfcmrvl_if_ops *ops,
- struct device *dev)
+ struct nfcmrvl_if_ops *ops,
+ struct device *dev,
+ struct nfcmrvl_platform_data *pdata)
{
struct nfcmrvl_private *priv;
int rc;
+ int headroom = 0;
u32 protocols;
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
@@ -103,13 +113,30 @@ struct nfcmrvl_private *nfcmrvl_nci_register_dev(void *drv_data,
priv->if_ops = ops;
priv->dev = dev;
+ memcpy(&priv->config, pdata, sizeof(*pdata));
+
+ if (priv->config.reset_n_io) {
+ rc = devm_gpio_request_one(dev,
+ priv->config.reset_n_io,
+ GPIOF_OUT_INIT_LOW,
+ "nfcmrvl_reset_n");
+ if (rc < 0)
+ nfc_err(dev, "failed to request reset_n io\n");
+ }
+
+ if (priv->config.hci_muxed)
+ headroom = NFCMRVL_HCI_EVENT_HEADER_SIZE;
+
protocols = NFC_PROTO_JEWEL_MASK
- | NFC_PROTO_MIFARE_MASK | NFC_PROTO_FELICA_MASK
+ | NFC_PROTO_MIFARE_MASK
+ | NFC_PROTO_FELICA_MASK
| NFC_PROTO_ISO14443_MASK
| NFC_PROTO_ISO14443_B_MASK
+ | NFC_PROTO_ISO15693_MASK
| NFC_PROTO_NFC_DEP_MASK;
- priv->ndev = nci_allocate_device(&nfcmrvl_nci_ops, protocols, 0, 0);
+ priv->ndev = nci_allocate_device(&nfcmrvl_nci_ops, protocols,
+ headroom, 0);
if (!priv->ndev) {
nfc_err(dev, "nci_allocate_device failed\n");
rc = -ENOMEM;
@@ -118,6 +145,8 @@ struct nfcmrvl_private *nfcmrvl_nci_register_dev(void *drv_data,
nci_set_drvdata(priv->ndev, priv);
+ nfcmrvl_chip_reset(priv);
+
rc = nci_register_device(priv->ndev);
if (rc) {
nfc_err(dev, "nci_register_device failed %d\n", rc);
@@ -144,21 +173,84 @@ void nfcmrvl_nci_unregister_dev(struct nfcmrvl_private *priv)
}
EXPORT_SYMBOL_GPL(nfcmrvl_nci_unregister_dev);
-int nfcmrvl_nci_recv_frame(struct nfcmrvl_private *priv, void *data, int count)
+int nfcmrvl_nci_recv_frame(struct nfcmrvl_private *priv, struct sk_buff *skb)
{
- struct sk_buff *skb;
-
- skb = nci_skb_alloc(priv->ndev, count, GFP_ATOMIC);
- if (!skb)
- return -ENOMEM;
+ if (priv->config.hci_muxed) {
+ if (skb->data[0] == NFCMRVL_HCI_EVENT_CODE &&
+ skb->data[1] == NFCMRVL_HCI_NFC_EVENT_CODE) {
+ /* Data packet, let's extract NCI payload */
+ skb_pull(skb, NFCMRVL_HCI_EVENT_HEADER_SIZE);
+ } else {
+ /* Skip this packet */
+ kfree_skb(skb);
+ return 0;
+ }
+ }
- memcpy(skb_put(skb, count), data, count);
- nci_recv_frame(priv->ndev, skb);
+ if (test_bit(NFCMRVL_NCI_RUNNING, &priv->flags))
+ nci_recv_frame(priv->ndev, skb);
+ else {
+ /* Drop this packet since nobody wants it */
+ kfree_skb(skb);
+ return 0;
+ }
- return count;
+ return 0;
}
EXPORT_SYMBOL_GPL(nfcmrvl_nci_recv_frame);
+void nfcmrvl_chip_reset(struct nfcmrvl_private *priv)
+{
+ /*
+ * This function does not take care if someone is using the device.
+ * To be improved.
+ */
+
+ if (priv->config.reset_n_io) {
+ nfc_info(priv->dev, "reset the chip\n");
+ gpio_set_value(priv->config.reset_n_io, 0);
+ usleep_range(5000, 10000);
+ gpio_set_value(priv->config.reset_n_io, 1);
+ } else
+ nfc_info(priv->dev, "no reset available on this interface\n");
+}
+
+#ifdef CONFIG_OF
+
+int nfcmrvl_parse_dt(struct device_node *node,
+ struct nfcmrvl_platform_data *pdata)
+{
+ int reset_n_io;
+
+ reset_n_io = of_get_named_gpio(node, "reset-n-io", 0);
+ if (reset_n_io < 0) {
+ pr_info("no reset-n-io config\n");
+ reset_n_io = 0;
+ } else if (!gpio_is_valid(reset_n_io)) {
+ pr_err("invalid reset-n-io GPIO\n");
+ return reset_n_io;
+ }
+ pdata->reset_n_io = reset_n_io;
+
+ if (of_find_property(node, "hci-muxed", NULL))
+ pdata->hci_muxed = 1;
+ else
+ pdata->hci_muxed = 0;
+
+ return 0;
+}
+
+#else
+
+int nfcmrvl_parse_dt(struct device_node *node,
+ struct nfcmrvl_platform_data *pdata)
+{
+ return -ENODEV;
+}
+
+#endif
+EXPORT_SYMBOL_GPL(nfcmrvl_parse_dt);
+
MODULE_AUTHOR("Marvell International Ltd.");
MODULE_DESCRIPTION("Marvell NFC driver ver " VERSION);
MODULE_VERSION(VERSION);
diff --git a/drivers/nfc/nfcmrvl/nfcmrvl.h b/drivers/nfc/nfcmrvl/nfcmrvl.h
index 54c4a956bd45..e5a7e5464f2e 100644
--- a/drivers/nfc/nfcmrvl/nfcmrvl.h
+++ b/drivers/nfc/nfcmrvl/nfcmrvl.h
@@ -16,6 +16,11 @@
* this warranty disclaimer.
**/
+#ifndef _NFCMRVL_H_
+#define _NFCMRVL_H_
+
+#include <linux/platform_data/nfcmrvl.h>
+
/* Define private flags: */
#define NFCMRVL_NCI_RUNNING 1
@@ -27,11 +32,49 @@
#define NFCMRVL_GPIO_PIN_NFC_ACTIVE 0xB
#define NFCMRVL_NCI_MAX_EVENT_SIZE 260
+/*
+** NCI FW Parmaters
+*/
+
+#define NFCMRVL_PB_BAIL_OUT 0x11
+
+/*
+** HCI defines
+*/
+
+#define NFCMRVL_HCI_EVENT_HEADER_SIZE 0x04
+#define NFCMRVL_HCI_EVENT_CODE 0x04
+#define NFCMRVL_HCI_NFC_EVENT_CODE 0xFF
+#define NFCMRVL_HCI_COMMAND_CODE 0x01
+#define NFCMRVL_HCI_OGF 0x81
+#define NFCMRVL_HCI_OCF 0xFE
+
+enum nfcmrvl_phy {
+ NFCMRVL_PHY_USB = 0,
+ NFCMRVL_PHY_UART = 1,
+};
+
+
struct nfcmrvl_private {
- struct nci_dev *ndev;
+
unsigned long flags;
+
+ /* Platform configuration */
+ struct nfcmrvl_platform_data config;
+
+ struct nci_dev *ndev;
+
+ /*
+ ** PHY related information
+ */
+
+ /* PHY driver context */
void *drv_data;
+ /* PHY device */
struct device *dev;
+ /* PHY type */
+ enum nfcmrvl_phy phy;
+ /* Low level driver ops */
struct nfcmrvl_if_ops *if_ops;
};
@@ -42,7 +85,16 @@ struct nfcmrvl_if_ops {
};
void nfcmrvl_nci_unregister_dev(struct nfcmrvl_private *priv);
-int nfcmrvl_nci_recv_frame(struct nfcmrvl_private *priv, void *data, int count);
+int nfcmrvl_nci_recv_frame(struct nfcmrvl_private *priv, struct sk_buff *skb);
struct nfcmrvl_private *nfcmrvl_nci_register_dev(void *drv_data,
- struct nfcmrvl_if_ops *ops,
- struct device *dev);
+ struct nfcmrvl_if_ops *ops,
+ struct device *dev,
+ struct nfcmrvl_platform_data *pdata);
+
+
+void nfcmrvl_chip_reset(struct nfcmrvl_private *priv);
+
+int nfcmrvl_parse_dt(struct device_node *node,
+ struct nfcmrvl_platform_data *pdata);
+
+#endif
diff --git a/drivers/nfc/nfcmrvl/uart.c b/drivers/nfc/nfcmrvl/uart.c
new file mode 100644
index 000000000000..61442d6528a6
--- /dev/null
+++ b/drivers/nfc/nfcmrvl/uart.c
@@ -0,0 +1,225 @@
+/**
+ * Marvell NFC-over-UART driver
+ *
+ * Copyright (C) 2015, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available on the worldwide web at
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/of_gpio.h>
+#include <net/nfc/nci.h>
+#include <net/nfc/nci_core.h>
+#include "nfcmrvl.h"
+
+static unsigned int hci_muxed;
+static unsigned int flow_control;
+static unsigned int break_control;
+static unsigned int reset_n_io;
+
+/*
+** NFCMRVL NCI OPS
+*/
+
+static int nfcmrvl_uart_nci_open(struct nfcmrvl_private *priv)
+{
+ return 0;
+}
+
+static int nfcmrvl_uart_nci_close(struct nfcmrvl_private *priv)
+{
+ return 0;
+}
+
+static int nfcmrvl_uart_nci_send(struct nfcmrvl_private *priv,
+ struct sk_buff *skb)
+{
+ struct nci_uart *nu = priv->drv_data;
+
+ return nu->ops.send(nu, skb);
+}
+
+static struct nfcmrvl_if_ops uart_ops = {
+ .nci_open = nfcmrvl_uart_nci_open,
+ .nci_close = nfcmrvl_uart_nci_close,
+ .nci_send = nfcmrvl_uart_nci_send,
+};
+
+#ifdef CONFIG_OF
+
+static int nfcmrvl_uart_parse_dt(struct device_node *node,
+ struct nfcmrvl_platform_data *pdata)
+{
+ struct device_node *matched_node;
+ int ret;
+
+ matched_node = of_find_compatible_node(node, NULL, "mrvl,nfc-uart");
+ if (!matched_node)
+ return -ENODEV;
+
+ ret = nfcmrvl_parse_dt(matched_node, pdata);
+ if (ret < 0) {
+ pr_err("Failed to get generic entries\n");
+ return ret;
+ }
+
+ if (of_find_property(matched_node, "flow-control", NULL))
+ pdata->flow_control = 1;
+ else
+ pdata->flow_control = 0;
+
+ if (of_find_property(matched_node, "break-control", NULL))
+ pdata->break_control = 1;
+ else
+ pdata->break_control = 0;
+
+ return 0;
+}
+
+#else
+
+static int nfcmrvl_uart_parse_dt(struct device_node *node,
+ struct nfcmrvl_platform_data *pdata)
+{
+ return -ENODEV;
+}
+
+#endif
+
+/*
+** NCI UART OPS
+*/
+
+static int nfcmrvl_nci_uart_open(struct nci_uart *nu)
+{
+ struct nfcmrvl_private *priv;
+ struct nfcmrvl_platform_data *pdata = NULL;
+ struct nfcmrvl_platform_data config;
+
+ /*
+ * Platform data cannot be used here since usually it is already used
+ * by low level serial driver. We can try to retrieve serial device
+ * and check if DT entries were added.
+ */
+
+ if (nu->tty->dev->parent && nu->tty->dev->parent->of_node)
+ if (nfcmrvl_uart_parse_dt(nu->tty->dev->parent->of_node,
+ &config) == 0)
+ pdata = &config;
+
+ if (!pdata) {
+ pr_info("No platform data / DT -> fallback to module params\n");
+ config.hci_muxed = hci_muxed;
+ config.reset_n_io = reset_n_io;
+ config.flow_control = flow_control;
+ config.break_control = break_control;
+ pdata = &config;
+ }
+
+ priv = nfcmrvl_nci_register_dev(nu, &uart_ops, nu->tty->dev, pdata);
+ if (IS_ERR(priv))
+ return PTR_ERR(priv);
+
+ priv->phy = NFCMRVL_PHY_UART;
+
+ nu->drv_data = priv;
+ nu->ndev = priv->ndev;
+
+ /* Set BREAK */
+ if (priv->config.break_control && nu->tty->ops->break_ctl)
+ nu->tty->ops->break_ctl(nu->tty, -1);
+
+ return 0;
+}
+
+static void nfcmrvl_nci_uart_close(struct nci_uart *nu)
+{
+ nfcmrvl_nci_unregister_dev((struct nfcmrvl_private *)nu->drv_data);
+}
+
+static int nfcmrvl_nci_uart_recv(struct nci_uart *nu, struct sk_buff *skb)
+{
+ return nfcmrvl_nci_recv_frame((struct nfcmrvl_private *)nu->drv_data,
+ skb);
+}
+
+static void nfcmrvl_nci_uart_tx_start(struct nci_uart *nu)
+{
+ struct nfcmrvl_private *priv = (struct nfcmrvl_private *)nu->drv_data;
+
+ /* Remove BREAK to wake up the NFCC */
+ if (priv->config.break_control && nu->tty->ops->break_ctl) {
+ nu->tty->ops->break_ctl(nu->tty, 0);
+ usleep_range(3000, 5000);
+ }
+}
+
+static void nfcmrvl_nci_uart_tx_done(struct nci_uart *nu)
+{
+ struct nfcmrvl_private *priv = (struct nfcmrvl_private *)nu->drv_data;
+
+ /*
+ ** To ensure that if the NFCC goes in DEEP SLEEP sate we can wake him
+ ** up. we set BREAK. Once we will be ready to send again we will remove
+ ** it.
+ */
+ if (priv->config.break_control && nu->tty->ops->break_ctl)
+ nu->tty->ops->break_ctl(nu->tty, -1);
+}
+
+static struct nci_uart nfcmrvl_nci_uart = {
+ .owner = THIS_MODULE,
+ .name = "nfcmrvl_uart",
+ .driver = NCI_UART_DRIVER_MARVELL,
+ .ops = {
+ .open = nfcmrvl_nci_uart_open,
+ .close = nfcmrvl_nci_uart_close,
+ .recv = nfcmrvl_nci_uart_recv,
+ .tx_start = nfcmrvl_nci_uart_tx_start,
+ .tx_done = nfcmrvl_nci_uart_tx_done,
+ }
+};
+
+/*
+** Module init
+*/
+
+static int nfcmrvl_uart_init_module(void)
+{
+ return nci_uart_register(&nfcmrvl_nci_uart);
+}
+
+static void nfcmrvl_uart_exit_module(void)
+{
+ nci_uart_unregister(&nfcmrvl_nci_uart);
+}
+
+module_init(nfcmrvl_uart_init_module);
+module_exit(nfcmrvl_uart_exit_module);
+
+MODULE_AUTHOR("Marvell International Ltd.");
+MODULE_DESCRIPTION("Marvell NFC-over-UART");
+MODULE_LICENSE("GPL v2");
+
+module_param(flow_control, uint, 0);
+MODULE_PARM_DESC(flow_control, "Tell if UART needs flow control at init.");
+
+module_param(break_control, uint, 0);
+MODULE_PARM_DESC(break_control, "Tell if UART driver must drive break signal.");
+
+module_param(hci_muxed, uint, 0);
+MODULE_PARM_DESC(hci_muxed, "Tell if transport is muxed in HCI one.");
+
+module_param(reset_n_io, uint, 0);
+MODULE_PARM_DESC(reset_n_io, "GPIO that is wired to RESET_N signal.");
diff --git a/drivers/nfc/nfcmrvl/usb.c b/drivers/nfc/nfcmrvl/usb.c
index 6cf15c1a2618..7d1fe436c9f6 100644
--- a/drivers/nfc/nfcmrvl/usb.c
+++ b/drivers/nfc/nfcmrvl/usb.c
@@ -26,7 +26,8 @@
#define VERSION "1.0"
static struct usb_device_id nfcmrvl_table[] = {
- { USB_DEVICE_INTERFACE_CLASS(0x1286, 0x2046, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x1286, 0x2046,
+ USB_CLASS_VENDOR_SPEC, 4, 1) },
{ } /* Terminating entry */
};
@@ -69,18 +70,27 @@ static int nfcmrvl_inc_tx(struct nfcmrvl_usb_drv_data *drv_data)
static void nfcmrvl_bulk_complete(struct urb *urb)
{
struct nfcmrvl_usb_drv_data *drv_data = urb->context;
+ struct sk_buff *skb;
int err;
- dev_dbg(&drv_data->udev->dev, "urb %p status %d count %d",
+ dev_dbg(&drv_data->udev->dev, "urb %p status %d count %d\n",
urb, urb->status, urb->actual_length);
if (!test_bit(NFCMRVL_NCI_RUNNING, &drv_data->flags))
return;
if (!urb->status) {
- if (nfcmrvl_nci_recv_frame(drv_data->priv, urb->transfer_buffer,
- urb->actual_length) < 0)
- nfc_err(&drv_data->udev->dev, "corrupted Rx packet\n");
+ skb = nci_skb_alloc(drv_data->priv->ndev, urb->actual_length,
+ GFP_ATOMIC);
+ if (!skb) {
+ nfc_err(&drv_data->udev->dev, "failed to alloc mem\n");
+ } else {
+ memcpy(skb_put(skb, urb->actual_length),
+ urb->transfer_buffer, urb->actual_length);
+ if (nfcmrvl_nci_recv_frame(drv_data->priv, skb) < 0)
+ nfc_err(&drv_data->udev->dev,
+ "corrupted Rx packet\n");
+ }
}
if (!test_bit(NFCMRVL_USB_BULK_RUNNING, &drv_data->flags))
@@ -292,6 +302,10 @@ static int nfcmrvl_probe(struct usb_interface *intf,
struct nfcmrvl_private *priv;
int i;
struct usb_device *udev = interface_to_usbdev(intf);
+ struct nfcmrvl_platform_data config;
+
+ /* No configuration for USB */
+ memset(&config, 0, sizeof(config));
nfc_info(&udev->dev, "intf %p id %p\n", intf, id);
@@ -329,11 +343,12 @@ static int nfcmrvl_probe(struct usb_interface *intf,
init_usb_anchor(&drv_data->deferred);
priv = nfcmrvl_nci_register_dev(drv_data, &usb_ops,
- &drv_data->udev->dev);
+ &drv_data->udev->dev, &config);
if (IS_ERR(priv))
return PTR_ERR(priv);
drv_data->priv = priv;
+ drv_data->priv->phy = NFCMRVL_PHY_USB;
priv->dev = &drv_data->udev->dev;
usb_set_intfdata(intf, drv_data);
diff --git a/drivers/nfc/nxp-nci/Makefile b/drivers/nfc/nxp-nci/Makefile
index c008be30bb18..c9ec7869dbd2 100644
--- a/drivers/nfc/nxp-nci/Makefile
+++ b/drivers/nfc/nxp-nci/Makefile
@@ -7,5 +7,3 @@ nxp-nci_i2c-objs = i2c.o
obj-$(CONFIG_NFC_NXP_NCI) += nxp-nci.o
obj-$(CONFIG_NFC_NXP_NCI_I2C) += nxp-nci_i2c.o
-
-ccflags-$(CONFIG_NFC_DEBUG) := -DDEBUG
diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c
index 17bd67dbebf0..2f77f1d03638 100644
--- a/drivers/nfc/nxp-nci/i2c.c
+++ b/drivers/nfc/nxp-nci/i2c.c
@@ -2,8 +2,10 @@
* I2C link layer for the NXP NCI driver
*
* Copyright (C) 2014 NXP Semiconductors All rights reserved.
+ * Copyright (C) 2012-2015 Intel Corporation. All rights reserved.
*
* Authors: Clément Perrochaud <clement.perrochaud@nxp.com>
+ * Authors: Oleg Zhurakivskyy <oleg.zhurakivskyy@intel.com>
*
* Derived from PN544 device driver:
* Copyright (C) 2012 Intel Corporation. All rights reserved.
@@ -23,12 +25,14 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/acpi.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/nfc.h>
+#include <linux/gpio/consumer.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/platform_data/nxp-nci.h>
@@ -48,6 +52,7 @@ struct nxp_nci_i2c_phy {
unsigned int gpio_en;
unsigned int gpio_fw;
+ unsigned int gpio_irq;
int hard_fault; /*
* < 0 if hardware error occurred (e.g. i2c err)
@@ -308,6 +313,37 @@ static int nxp_nci_i2c_parse_devtree(struct i2c_client *client)
#endif
+static int nxp_nci_i2c_acpi_config(struct nxp_nci_i2c_phy *phy)
+{
+ struct i2c_client *client = phy->i2c_dev;
+ struct gpio_desc *gpiod_en, *gpiod_fw, *gpiod_irq;
+
+ gpiod_en = devm_gpiod_get_index(&client->dev, NULL, 2);
+ gpiod_fw = devm_gpiod_get_index(&client->dev, NULL, 1);
+ gpiod_irq = devm_gpiod_get_index(&client->dev, NULL, 0);
+
+ if (IS_ERR(gpiod_en) || IS_ERR(gpiod_fw) || IS_ERR(gpiod_irq)) {
+ nfc_err(&client->dev, "No GPIOs\n");
+ return -EINVAL;
+ }
+
+ gpiod_direction_output(gpiod_en, 0);
+ gpiod_direction_output(gpiod_fw, 0);
+ gpiod_direction_input(gpiod_irq);
+
+ client->irq = gpiod_to_irq(gpiod_irq);
+ if (client->irq < 0) {
+ nfc_err(&client->dev, "No IRQ\n");
+ return -EINVAL;
+ }
+
+ phy->gpio_en = desc_to_gpio(gpiod_en);
+ phy->gpio_fw = desc_to_gpio(gpiod_fw);
+ phy->gpio_irq = desc_to_gpio(gpiod_irq);
+
+ return 0;
+}
+
static int nxp_nci_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -343,6 +379,11 @@ static int nxp_nci_i2c_probe(struct i2c_client *client,
phy->gpio_en = pdata->gpio_en;
phy->gpio_fw = pdata->gpio_fw;
client->irq = pdata->irq;
+ } else if (ACPI_HANDLE(&client->dev)) {
+ r = nxp_nci_i2c_acpi_config(phy);
+ if (r < 0)
+ goto probe_exit;
+ goto nci_probe;
} else {
nfc_err(&client->dev, "No platform data\n");
r = -EINVAL;
@@ -359,6 +400,7 @@ static int nxp_nci_i2c_probe(struct i2c_client *client,
if (r < 0)
goto probe_exit;
+nci_probe:
r = nxp_nci_probe(phy, &client->dev, &i2c_phy_ops,
NXP_NCI_I2C_MAX_PAYLOAD, &phy->ndev);
if (r < 0)
@@ -397,10 +439,19 @@ static const struct of_device_id of_nxp_nci_i2c_match[] = {
};
MODULE_DEVICE_TABLE(of, of_nxp_nci_i2c_match);
+#ifdef CONFIG_ACPI
+static struct acpi_device_id acpi_id[] = {
+ { "NXP7471" },
+ { },
+};
+MODULE_DEVICE_TABLE(acpi, acpi_id);
+#endif
+
static struct i2c_driver nxp_nci_i2c_driver = {
.driver = {
.name = NXP_NCI_I2C_DRIVER_NAME,
.owner = THIS_MODULE,
+ .acpi_match_table = ACPI_PTR(acpi_id),
.of_match_table = of_match_ptr(of_nxp_nci_i2c_match),
},
.probe = nxp_nci_i2c_probe,
@@ -413,3 +464,4 @@ module_i2c_driver(nxp_nci_i2c_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("I2C driver for NXP NCI NFC controllers");
MODULE_AUTHOR("Clément Perrochaud <clement.perrochaud@nxp.com>");
+MODULE_AUTHOR("Oleg Zhurakivskyy <oleg.zhurakivskyy@intel.com>");
diff --git a/drivers/nfc/pn544/i2c.c b/drivers/nfc/pn544/i2c.c
index 6fd986f5ac3e..fa75c53f3fa5 100644
--- a/drivers/nfc/pn544/i2c.c
+++ b/drivers/nfc/pn544/i2c.c
@@ -895,56 +895,35 @@ static int pn544_hci_i2c_acpi_request_resources(struct i2c_client *client)
return -ENODEV;
/* Get EN GPIO from ACPI */
- gpiod_en = devm_gpiod_get_index(dev, PN544_GPIO_NAME_EN, 1);
+ gpiod_en = devm_gpiod_get_index(dev, PN544_GPIO_NAME_EN, 1,
+ GPIOD_OUT_LOW);
if (IS_ERR(gpiod_en)) {
- nfc_err(dev,
- "Unable to get EN GPIO\n");
+ nfc_err(dev, "Unable to get EN GPIO\n");
return -ENODEV;
}
- phy->gpio_en = desc_to_gpio(gpiod_en);
-
- /* Configuration EN GPIO */
- ret = gpiod_direction_output(gpiod_en, 0);
- if (ret) {
- nfc_err(dev, "Fail EN pin direction\n");
- return ret;
- }
+ phy->gpio_en = desc_to_gpio(gpiod_en);
/* Get FW GPIO from ACPI */
- gpiod_fw = devm_gpiod_get_index(dev, PN544_GPIO_NAME_FW, 2);
+ gpiod_fw = devm_gpiod_get_index(dev, PN544_GPIO_NAME_FW, 2,
+ GPIOD_OUT_LOW);
if (IS_ERR(gpiod_fw)) {
- nfc_err(dev,
- "Unable to get FW GPIO\n");
+ nfc_err(dev, "Unable to get FW GPIO\n");
return -ENODEV;
}
- phy->gpio_fw = desc_to_gpio(gpiod_fw);
-
- /* Configuration FW GPIO */
- ret = gpiod_direction_output(gpiod_fw, 0);
- if (ret) {
- nfc_err(dev, "Fail FW pin direction\n");
- return ret;
- }
+ phy->gpio_fw = desc_to_gpio(gpiod_fw);
/* Get IRQ GPIO */
- gpiod_irq = devm_gpiod_get_index(dev, PN544_GPIO_NAME_IRQ, 0);
+ gpiod_irq = devm_gpiod_get_index(dev, PN544_GPIO_NAME_IRQ, 0,
+ GPIOD_IN);
if (IS_ERR(gpiod_irq)) {
- nfc_err(dev,
- "Unable to get IRQ GPIO\n");
+ nfc_err(dev, "Unable to get IRQ GPIO\n");
return -ENODEV;
}
phy->gpio_irq = desc_to_gpio(gpiod_irq);
- /* Configure IRQ GPIO */
- ret = gpiod_direction_input(gpiod_irq);
- if (ret) {
- nfc_err(dev, "Fail IRQ pin direction\n");
- return ret;
- }
-
/* Map the pin to an IRQ */
ret = gpiod_to_irq(gpiod_irq);
if (ret < 0) {
diff --git a/drivers/nfc/st-nci/Kconfig b/drivers/nfc/st-nci/Kconfig
new file mode 100644
index 000000000000..fc3904c946ee
--- /dev/null
+++ b/drivers/nfc/st-nci/Kconfig
@@ -0,0 +1,23 @@
+config NFC_ST_NCI
+ tristate "STMicroelectronics ST NCI NFC driver"
+ depends on NFC_NCI
+ default n
+ ---help---
+ STMicroelectronics NFC NCI chips core driver. It implements the chipset
+ NCI logic and hooks into the NFC kernel APIs. Physical layers will
+ register against it.
+
+ To compile this driver as a module, choose m here. The module will
+ be called st-nci.
+ Say N if unsure.
+
+config NFC_ST_NCI_I2C
+ tristate "NFC ST NCI i2c support"
+ depends on NFC_ST_NCI && I2C
+ ---help---
+ This module adds support for an I2C interface to the
+ STMicroelectronics NFC NCI chips familly.
+ Select this if your platform is using the i2c bus.
+
+ If you choose to build a module, it'll be called st-nci_i2c.
+ Say N if unsure.
diff --git a/drivers/nfc/st-nci/Makefile b/drivers/nfc/st-nci/Makefile
new file mode 100644
index 000000000000..0df157df3a94
--- /dev/null
+++ b/drivers/nfc/st-nci/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for ST21NFCB NCI based NFC driver
+#
+
+st-nci-objs = ndlc.o core.o st-nci_se.o
+obj-$(CONFIG_NFC_ST_NCI) += st-nci.o
+
+st-nci_i2c-objs = i2c.o
+obj-$(CONFIG_NFC_ST_NCI_I2C) += st-nci_i2c.o
diff --git a/drivers/nfc/st-nci/core.c b/drivers/nfc/st-nci/core.c
new file mode 100644
index 000000000000..c419d3943973
--- /dev/null
+++ b/drivers/nfc/st-nci/core.c
@@ -0,0 +1,179 @@
+/*
+ * NCI based Driver for STMicroelectronics NFC Chip
+ *
+ * Copyright (C) 2014-2015 STMicroelectronics SAS. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/nfc.h>
+#include <net/nfc/nci.h>
+#include <net/nfc/nci_core.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+
+#include "st-nci.h"
+#include "st-nci_se.h"
+
+#define DRIVER_DESC "NCI NFC driver for ST_NCI"
+
+#define ST_NCI1_X_PROPRIETARY_ISO15693 0x83
+
+static int st_nci_init(struct nci_dev *ndev)
+{
+ struct nci_mode_set_cmd cmd;
+
+ cmd.cmd_type = ST_NCI_SET_NFC_MODE;
+ cmd.mode = 1;
+
+ return nci_prop_cmd(ndev, ST_NCI_CORE_PROP,
+ sizeof(struct nci_mode_set_cmd), (__u8 *)&cmd);
+}
+
+static int st_nci_open(struct nci_dev *ndev)
+{
+ struct st_nci_info *info = nci_get_drvdata(ndev);
+ int r;
+
+ if (test_and_set_bit(ST_NCI_RUNNING, &info->flags))
+ return 0;
+
+ r = ndlc_open(info->ndlc);
+ if (r)
+ clear_bit(ST_NCI_RUNNING, &info->flags);
+
+ return r;
+}
+
+static int st_nci_close(struct nci_dev *ndev)
+{
+ struct st_nci_info *info = nci_get_drvdata(ndev);
+
+ if (!test_bit(ST_NCI_RUNNING, &info->flags))
+ return 0;
+
+ ndlc_close(info->ndlc);
+
+ clear_bit(ST_NCI_RUNNING, &info->flags);
+
+ return 0;
+}
+
+static int st_nci_send(struct nci_dev *ndev, struct sk_buff *skb)
+{
+ struct st_nci_info *info = nci_get_drvdata(ndev);
+
+ skb->dev = (void *)ndev;
+
+ if (!test_bit(ST_NCI_RUNNING, &info->flags))
+ return -EBUSY;
+
+ return ndlc_send(info->ndlc, skb);
+}
+
+static __u32 st_nci_get_rfprotocol(struct nci_dev *ndev,
+ __u8 rf_protocol)
+{
+ return rf_protocol == ST_NCI1_X_PROPRIETARY_ISO15693 ?
+ NFC_PROTO_ISO15693_MASK : 0;
+}
+
+static int st_nci_prop_rsp_packet(struct nci_dev *ndev,
+ struct sk_buff *skb)
+{
+ __u8 status = skb->data[0];
+
+ nci_req_complete(ndev, status);
+ return 0;
+}
+
+static struct nci_prop_ops st_nci_prop_ops[] = {
+ {
+ .opcode = nci_opcode_pack(NCI_GID_PROPRIETARY,
+ ST_NCI_CORE_PROP),
+ .rsp = st_nci_prop_rsp_packet,
+ },
+};
+
+static struct nci_ops st_nci_ops = {
+ .init = st_nci_init,
+ .open = st_nci_open,
+ .close = st_nci_close,
+ .send = st_nci_send,
+ .get_rfprotocol = st_nci_get_rfprotocol,
+ .discover_se = st_nci_discover_se,
+ .enable_se = st_nci_enable_se,
+ .disable_se = st_nci_disable_se,
+ .se_io = st_nci_se_io,
+ .hci_load_session = st_nci_hci_load_session,
+ .hci_event_received = st_nci_hci_event_received,
+ .hci_cmd_received = st_nci_hci_cmd_received,
+ .prop_ops = st_nci_prop_ops,
+ .n_prop_ops = ARRAY_SIZE(st_nci_prop_ops),
+};
+
+int st_nci_probe(struct llt_ndlc *ndlc, int phy_headroom,
+ int phy_tailroom)
+{
+ struct st_nci_info *info;
+ int r;
+ u32 protocols;
+
+ info = devm_kzalloc(ndlc->dev,
+ sizeof(struct st_nci_info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ protocols = NFC_PROTO_JEWEL_MASK
+ | NFC_PROTO_MIFARE_MASK
+ | NFC_PROTO_FELICA_MASK
+ | NFC_PROTO_ISO14443_MASK
+ | NFC_PROTO_ISO14443_B_MASK
+ | NFC_PROTO_ISO15693_MASK
+ | NFC_PROTO_NFC_DEP_MASK;
+
+ ndlc->ndev = nci_allocate_device(&st_nci_ops, protocols,
+ phy_headroom, phy_tailroom);
+ if (!ndlc->ndev) {
+ pr_err("Cannot allocate nfc ndev\n");
+ return -ENOMEM;
+ }
+ info->ndlc = ndlc;
+
+ nci_set_drvdata(ndlc->ndev, info);
+
+ r = nci_register_device(ndlc->ndev);
+ if (r) {
+ pr_err("Cannot register nfc device to nci core\n");
+ nci_free_device(ndlc->ndev);
+ return r;
+ }
+
+ return st_nci_se_init(ndlc->ndev);
+}
+EXPORT_SYMBOL_GPL(st_nci_probe);
+
+void st_nci_remove(struct nci_dev *ndev)
+{
+ struct st_nci_info *info = nci_get_drvdata(ndev);
+
+ ndlc_close(info->ndlc);
+
+ nci_unregister_device(ndev);
+ nci_free_device(ndev);
+}
+EXPORT_SYMBOL_GPL(st_nci_remove);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/nfc/st21nfcb/i2c.c b/drivers/nfc/st-nci/i2c.c
index 76a4cad41cec..06175ce769bb 100644
--- a/drivers/nfc/st21nfcb/i2c.c
+++ b/drivers/nfc/st-nci/i2c.c
@@ -1,6 +1,6 @@
/*
- * I2C Link Layer for ST21NFCB NCI based Driver
- * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved.
+ * I2C Link Layer for ST NCI NFC controller familly based Driver
+ * Copyright (C) 2014-2015 STMicroelectronics SAS. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -25,7 +25,7 @@
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/nfc.h>
-#include <linux/platform_data/st21nfcb.h>
+#include <linux/platform_data/st_nci.h>
#include "ndlc.h"
@@ -35,25 +35,23 @@
#define ST21NFCB_FRAME_HEADROOM 1
#define ST21NFCB_FRAME_TAILROOM 0
-#define ST21NFCB_NCI_I2C_MIN_SIZE 4 /* PCB(1) + NCI Packet header(3) */
-#define ST21NFCB_NCI_I2C_MAX_SIZE 250 /* req 4.2.1 */
+#define ST_NCI_I2C_MIN_SIZE 4 /* PCB(1) + NCI Packet header(3) */
+#define ST_NCI_I2C_MAX_SIZE 250 /* req 4.2.1 */
-#define ST21NFCB_NCI_I2C_DRIVER_NAME "st21nfcb_nci_i2c"
+#define ST_NCI_I2C_DRIVER_NAME "st_nci_i2c"
-static struct i2c_device_id st21nfcb_nci_i2c_id_table[] = {
- {ST21NFCB_NCI_DRIVER_NAME, 0},
+static struct i2c_device_id st_nci_i2c_id_table[] = {
+ {ST_NCI_DRIVER_NAME, 0},
{}
};
-MODULE_DEVICE_TABLE(i2c, st21nfcb_nci_i2c_id_table);
+MODULE_DEVICE_TABLE(i2c, st_nci_i2c_id_table);
-struct st21nfcb_i2c_phy {
+struct st_nci_i2c_phy {
struct i2c_client *i2c_dev;
struct llt_ndlc *ndlc;
unsigned int gpio_reset;
unsigned int irq_polarity;
-
- int powered;
};
#define I2C_DUMP_SKB(info, skb) \
@@ -63,33 +61,26 @@ do { \
16, 1, (skb)->data, (skb)->len, 0); \
} while (0)
-static int st21nfcb_nci_i2c_enable(void *phy_id)
+static int st_nci_i2c_enable(void *phy_id)
{
- struct st21nfcb_i2c_phy *phy = phy_id;
+ struct st_nci_i2c_phy *phy = phy_id;
gpio_set_value(phy->gpio_reset, 0);
usleep_range(10000, 15000);
gpio_set_value(phy->gpio_reset, 1);
- phy->powered = 1;
usleep_range(80000, 85000);
+ if (phy->ndlc->powered == 0)
+ enable_irq(phy->i2c_dev->irq);
+
return 0;
}
-static void st21nfcb_nci_i2c_disable(void *phy_id)
+static void st_nci_i2c_disable(void *phy_id)
{
- struct st21nfcb_i2c_phy *phy = phy_id;
-
- phy->powered = 0;
- /* reset chip in order to flush clf */
- gpio_set_value(phy->gpio_reset, 0);
- usleep_range(10000, 15000);
- gpio_set_value(phy->gpio_reset, 1);
-}
+ struct st_nci_i2c_phy *phy = phy_id;
-static void st21nfcb_nci_remove_header(struct sk_buff *skb)
-{
- skb_pull(skb, ST21NFCB_FRAME_HEADROOM);
+ disable_irq_nosync(phy->i2c_dev->irq);
}
/*
@@ -97,13 +88,13 @@ static void st21nfcb_nci_remove_header(struct sk_buff *skb)
* It must return either zero for success, or <0 for error.
* In addition, it must not alter the skb
*/
-static int st21nfcb_nci_i2c_write(void *phy_id, struct sk_buff *skb)
+static int st_nci_i2c_write(void *phy_id, struct sk_buff *skb)
{
int r = -1;
- struct st21nfcb_i2c_phy *phy = phy_id;
+ struct st_nci_i2c_phy *phy = phy_id;
struct i2c_client *client = phy->i2c_dev;
- I2C_DUMP_SKB("st21nfcb_nci_i2c_write", skb);
+ I2C_DUMP_SKB("st_nci_i2c_write", skb);
if (phy->ndlc->hard_fault != 0)
return phy->ndlc->hard_fault;
@@ -121,8 +112,6 @@ static int st21nfcb_nci_i2c_write(void *phy_id, struct sk_buff *skb)
r = 0;
}
- st21nfcb_nci_remove_header(skb);
-
return r;
}
@@ -135,40 +124,40 @@ static int st21nfcb_nci_i2c_write(void *phy_id, struct sk_buff *skb)
* at end of read)
* -EREMOTEIO : i2c read error (fatal)
* -EBADMSG : frame was incorrect and discarded
- * (value returned from st21nfcb_nci_i2c_repack)
+ * (value returned from st_nci_i2c_repack)
* -EIO : if no ST21NFCB_SOF_EOF is found after reaching
* the read length end sequence
*/
-static int st21nfcb_nci_i2c_read(struct st21nfcb_i2c_phy *phy,
+static int st_nci_i2c_read(struct st_nci_i2c_phy *phy,
struct sk_buff **skb)
{
int r;
u8 len;
- u8 buf[ST21NFCB_NCI_I2C_MAX_SIZE];
+ u8 buf[ST_NCI_I2C_MAX_SIZE];
struct i2c_client *client = phy->i2c_dev;
- r = i2c_master_recv(client, buf, ST21NFCB_NCI_I2C_MIN_SIZE);
+ r = i2c_master_recv(client, buf, ST_NCI_I2C_MIN_SIZE);
if (r < 0) { /* Retry, chip was in standby */
usleep_range(1000, 4000);
- r = i2c_master_recv(client, buf, ST21NFCB_NCI_I2C_MIN_SIZE);
+ r = i2c_master_recv(client, buf, ST_NCI_I2C_MIN_SIZE);
}
- if (r != ST21NFCB_NCI_I2C_MIN_SIZE)
+ if (r != ST_NCI_I2C_MIN_SIZE)
return -EREMOTEIO;
len = be16_to_cpu(*(__be16 *) (buf + 2));
- if (len > ST21NFCB_NCI_I2C_MAX_SIZE) {
+ if (len > ST_NCI_I2C_MAX_SIZE) {
nfc_err(&client->dev, "invalid frame len\n");
return -EBADMSG;
}
- *skb = alloc_skb(ST21NFCB_NCI_I2C_MIN_SIZE + len, GFP_KERNEL);
+ *skb = alloc_skb(ST_NCI_I2C_MIN_SIZE + len, GFP_KERNEL);
if (*skb == NULL)
return -ENOMEM;
- skb_reserve(*skb, ST21NFCB_NCI_I2C_MIN_SIZE);
- skb_put(*skb, ST21NFCB_NCI_I2C_MIN_SIZE);
- memcpy((*skb)->data, buf, ST21NFCB_NCI_I2C_MIN_SIZE);
+ skb_reserve(*skb, ST_NCI_I2C_MIN_SIZE);
+ skb_put(*skb, ST_NCI_I2C_MIN_SIZE);
+ memcpy((*skb)->data, buf, ST_NCI_I2C_MIN_SIZE);
if (!len)
return 0;
@@ -180,7 +169,7 @@ static int st21nfcb_nci_i2c_read(struct st21nfcb_i2c_phy *phy,
}
skb_put(*skb, len);
- memcpy((*skb)->data + ST21NFCB_NCI_I2C_MIN_SIZE, buf, len);
+ memcpy((*skb)->data + ST_NCI_I2C_MIN_SIZE, buf, len);
I2C_DUMP_SKB("i2c frame read", *skb);
@@ -192,9 +181,9 @@ static int st21nfcb_nci_i2c_read(struct st21nfcb_i2c_phy *phy,
*
* On ST21NFCB, IRQ goes in idle state when read starts.
*/
-static irqreturn_t st21nfcb_nci_irq_thread_fn(int irq, void *phy_id)
+static irqreturn_t st_nci_irq_thread_fn(int irq, void *phy_id)
{
- struct st21nfcb_i2c_phy *phy = phy_id;
+ struct st_nci_i2c_phy *phy = phy_id;
struct i2c_client *client;
struct sk_buff *skb = NULL;
int r;
@@ -210,12 +199,12 @@ static irqreturn_t st21nfcb_nci_irq_thread_fn(int irq, void *phy_id)
if (phy->ndlc->hard_fault)
return IRQ_HANDLED;
- if (!phy->powered) {
- st21nfcb_nci_i2c_disable(phy);
+ if (!phy->ndlc->powered) {
+ st_nci_i2c_disable(phy);
return IRQ_HANDLED;
}
- r = st21nfcb_nci_i2c_read(phy, &skb);
+ r = st_nci_i2c_read(phy, &skb);
if (r == -EREMOTEIO || r == -ENOMEM || r == -EBADMSG)
return IRQ_HANDLED;
@@ -225,15 +214,15 @@ static irqreturn_t st21nfcb_nci_irq_thread_fn(int irq, void *phy_id)
}
static struct nfc_phy_ops i2c_phy_ops = {
- .write = st21nfcb_nci_i2c_write,
- .enable = st21nfcb_nci_i2c_enable,
- .disable = st21nfcb_nci_i2c_disable,
+ .write = st_nci_i2c_write,
+ .enable = st_nci_i2c_enable,
+ .disable = st_nci_i2c_disable,
};
#ifdef CONFIG_OF
-static int st21nfcb_nci_i2c_of_request_resources(struct i2c_client *client)
+static int st_nci_i2c_of_request_resources(struct i2c_client *client)
{
- struct st21nfcb_i2c_phy *phy = i2c_get_clientdata(client);
+ struct st_nci_i2c_phy *phy = i2c_get_clientdata(client);
struct device_node *pp;
int gpio;
int r;
@@ -264,16 +253,16 @@ static int st21nfcb_nci_i2c_of_request_resources(struct i2c_client *client)
return 0;
}
#else
-static int st21nfcb_nci_i2c_of_request_resources(struct i2c_client *client)
+static int st_nci_i2c_of_request_resources(struct i2c_client *client)
{
return -ENODEV;
}
#endif
-static int st21nfcb_nci_i2c_request_resources(struct i2c_client *client)
+static int st_nci_i2c_request_resources(struct i2c_client *client)
{
- struct st21nfcb_nfc_platform_data *pdata;
- struct st21nfcb_i2c_phy *phy = i2c_get_clientdata(client);
+ struct st_nci_nfc_platform_data *pdata;
+ struct st_nci_i2c_phy *phy = i2c_get_clientdata(client);
int r;
pdata = client->dev.platform_data;
@@ -296,11 +285,11 @@ static int st21nfcb_nci_i2c_request_resources(struct i2c_client *client)
return 0;
}
-static int st21nfcb_nci_i2c_probe(struct i2c_client *client,
+static int st_nci_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- struct st21nfcb_i2c_phy *phy;
- struct st21nfcb_nfc_platform_data *pdata;
+ struct st_nci_i2c_phy *phy;
+ struct st_nci_nfc_platform_data *pdata;
int r;
dev_dbg(&client->dev, "%s\n", __func__);
@@ -311,7 +300,7 @@ static int st21nfcb_nci_i2c_probe(struct i2c_client *client,
return -ENODEV;
}
- phy = devm_kzalloc(&client->dev, sizeof(struct st21nfcb_i2c_phy),
+ phy = devm_kzalloc(&client->dev, sizeof(struct st_nci_i2c_phy),
GFP_KERNEL);
if (!phy)
return -ENOMEM;
@@ -322,13 +311,13 @@ static int st21nfcb_nci_i2c_probe(struct i2c_client *client,
pdata = client->dev.platform_data;
if (!pdata && client->dev.of_node) {
- r = st21nfcb_nci_i2c_of_request_resources(client);
+ r = st_nci_i2c_of_request_resources(client);
if (r) {
nfc_err(&client->dev, "No platform data\n");
return r;
}
} else if (pdata) {
- r = st21nfcb_nci_i2c_request_resources(client);
+ r = st_nci_i2c_request_resources(client);
if (r) {
nfc_err(&client->dev,
"Cannot get platform resources\n");
@@ -349,50 +338,48 @@ static int st21nfcb_nci_i2c_probe(struct i2c_client *client,
}
r = devm_request_threaded_irq(&client->dev, client->irq, NULL,
- st21nfcb_nci_irq_thread_fn,
+ st_nci_irq_thread_fn,
phy->irq_polarity | IRQF_ONESHOT,
- ST21NFCB_NCI_DRIVER_NAME, phy);
+ ST_NCI_DRIVER_NAME, phy);
if (r < 0)
nfc_err(&client->dev, "Unable to register IRQ handler\n");
return r;
}
-static int st21nfcb_nci_i2c_remove(struct i2c_client *client)
+static int st_nci_i2c_remove(struct i2c_client *client)
{
- struct st21nfcb_i2c_phy *phy = i2c_get_clientdata(client);
+ struct st_nci_i2c_phy *phy = i2c_get_clientdata(client);
dev_dbg(&client->dev, "%s\n", __func__);
ndlc_remove(phy->ndlc);
- if (phy->powered)
- st21nfcb_nci_i2c_disable(phy);
-
return 0;
}
#ifdef CONFIG_OF
-static const struct of_device_id of_st21nfcb_i2c_match[] = {
+static const struct of_device_id of_st_nci_i2c_match[] = {
{ .compatible = "st,st21nfcb-i2c", },
{ .compatible = "st,st21nfcb_i2c", },
+ { .compatible = "st,st21nfcc-i2c", },
{}
};
-MODULE_DEVICE_TABLE(of, of_st21nfcb_i2c_match);
+MODULE_DEVICE_TABLE(of, of_st_nci_i2c_match);
#endif
-static struct i2c_driver st21nfcb_nci_i2c_driver = {
+static struct i2c_driver st_nci_i2c_driver = {
.driver = {
.owner = THIS_MODULE,
- .name = ST21NFCB_NCI_I2C_DRIVER_NAME,
- .of_match_table = of_match_ptr(of_st21nfcb_i2c_match),
+ .name = ST_NCI_I2C_DRIVER_NAME,
+ .of_match_table = of_match_ptr(of_st_nci_i2c_match),
},
- .probe = st21nfcb_nci_i2c_probe,
- .id_table = st21nfcb_nci_i2c_id_table,
- .remove = st21nfcb_nci_i2c_remove,
+ .probe = st_nci_i2c_probe,
+ .id_table = st_nci_i2c_id_table,
+ .remove = st_nci_i2c_remove,
};
-module_i2c_driver(st21nfcb_nci_i2c_driver);
+module_i2c_driver(st_nci_i2c_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/nfc/st21nfcb/ndlc.c b/drivers/nfc/st-nci/ndlc.c
index 6014b5859465..56c6a4cb4c96 100644
--- a/drivers/nfc/st21nfcb/ndlc.c
+++ b/drivers/nfc/st-nci/ndlc.c
@@ -1,7 +1,7 @@
/*
* Low Level Transport (NDLC) Driver for STMicroelectronics NFC Chip
*
- * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved.
+ * Copyright (C) 2014-2015 STMicroelectronics SAS. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -20,7 +20,7 @@
#include <net/nfc/nci_core.h>
#include "ndlc.h"
-#include "st21nfcb.h"
+#include "st-nci.h"
#define NDLC_TIMER_T1 100
#define NDLC_TIMER_T1_WAIT 400
@@ -59,13 +59,25 @@ int ndlc_open(struct llt_ndlc *ndlc)
{
/* toggle reset pin */
ndlc->ops->enable(ndlc->phy_id);
+ ndlc->powered = 1;
return 0;
}
EXPORT_SYMBOL(ndlc_open);
void ndlc_close(struct llt_ndlc *ndlc)
{
+ struct nci_mode_set_cmd cmd;
+
+ cmd.cmd_type = ST_NCI_SET_NFC_MODE;
+ cmd.mode = 0;
+
/* toggle reset pin */
+ ndlc->ops->enable(ndlc->phy_id);
+
+ nci_prop_cmd(ndlc->ndev, ST_NCI_CORE_PROP,
+ sizeof(struct nci_mode_set_cmd), (__u8 *)&cmd);
+
+ ndlc->powered = 0;
ndlc->ops->disable(ndlc->phy_id);
}
EXPORT_SYMBOL(ndlc_close);
@@ -262,6 +274,7 @@ int ndlc_probe(void *phy_id, struct nfc_phy_ops *phy_ops, struct device *dev,
ndlc->ops = phy_ops;
ndlc->phy_id = phy_id;
ndlc->dev = dev;
+ ndlc->powered = 0;
*ndlc_id = ndlc;
@@ -280,12 +293,14 @@ int ndlc_probe(void *phy_id, struct nfc_phy_ops *phy_ops, struct device *dev,
INIT_WORK(&ndlc->sm_work, llt_ndlc_sm_work);
- return st21nfcb_nci_probe(ndlc, phy_headroom, phy_tailroom);
+ return st_nci_probe(ndlc, phy_headroom, phy_tailroom);
}
EXPORT_SYMBOL(ndlc_probe);
void ndlc_remove(struct llt_ndlc *ndlc)
{
+ st_nci_remove(ndlc->ndev);
+
/* cancel timers */
del_timer_sync(&ndlc->t1_timer);
del_timer_sync(&ndlc->t2_timer);
@@ -294,7 +309,5 @@ void ndlc_remove(struct llt_ndlc *ndlc)
skb_queue_purge(&ndlc->rcv_q);
skb_queue_purge(&ndlc->send_q);
-
- st21nfcb_nci_remove(ndlc->ndev);
}
EXPORT_SYMBOL(ndlc_remove);
diff --git a/drivers/nfc/st21nfcb/ndlc.h b/drivers/nfc/st-nci/ndlc.h
index b28140e0cd78..6361005ef003 100644
--- a/drivers/nfc/st21nfcb/ndlc.h
+++ b/drivers/nfc/st-nci/ndlc.h
@@ -1,7 +1,7 @@
/*
* NCI based Driver for STMicroelectronics NFC Chip
*
- * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved.
+ * Copyright (C) 2014-2015 STMicroelectronics SAS. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -43,10 +43,11 @@ struct llt_ndlc {
struct device *dev;
/*
- * < 0 if hardware error occured
+ * < 0 if hardware error occurred
* and prevents normal operation.
*/
int hard_fault;
+ int powered;
};
int ndlc_open(struct llt_ndlc *ndlc);
diff --git a/drivers/nfc/st21nfcb/st21nfcb.h b/drivers/nfc/st-nci/st-nci.h
index 5ef8a58c9839..850a2395deb7 100644
--- a/drivers/nfc/st21nfcb/st21nfcb.h
+++ b/drivers/nfc/st-nci/st-nci.h
@@ -16,23 +16,35 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef __LOCAL_ST21NFCB_H_
-#define __LOCAL_ST21NFCB_H_
+#ifndef __LOCAL_ST_NCI_H_
+#define __LOCAL_ST_NCI_H_
-#include "st21nfcb_se.h"
+#include "st-nci_se.h"
#include "ndlc.h"
/* Define private flags: */
-#define ST21NFCB_NCI_RUNNING 1
+#define ST_NCI_RUNNING 1
-struct st21nfcb_nci_info {
+#define ST_NCI_CORE_PROP 0x01
+#define ST_NCI_SET_NFC_MODE 0x02
+
+struct nci_mode_set_cmd {
+ u8 cmd_type;
+ u8 mode;
+} __packed;
+
+struct nci_mode_set_rsp {
+ u8 status;
+} __packed;
+
+struct st_nci_info {
struct llt_ndlc *ndlc;
unsigned long flags;
- struct st21nfcb_se_info se_info;
+ struct st_nci_se_info se_info;
};
-void st21nfcb_nci_remove(struct nci_dev *ndev);
-int st21nfcb_nci_probe(struct llt_ndlc *ndlc, int phy_headroom,
+void st_nci_remove(struct nci_dev *ndev);
+int st_nci_probe(struct llt_ndlc *ndlc, int phy_headroom,
int phy_tailroom);
-#endif /* __LOCAL_ST21NFCB_H_ */
+#endif /* __LOCAL_ST_NCI_H_ */
diff --git a/drivers/nfc/st21nfcb/st21nfcb_se.c b/drivers/nfc/st-nci/st-nci_se.c
index 24862a525fb5..97addfa96c6f 100644
--- a/drivers/nfc/st21nfcb/st21nfcb_se.c
+++ b/drivers/nfc/st-nci/st-nci_se.c
@@ -1,7 +1,7 @@
/*
- * NCI based Driver for STMicroelectronics NFC Chip
+ * Secure Element driver for STMicroelectronics NFC NCI chip
*
- * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved.
+ * Copyright (C) 2014-2015 STMicroelectronics SAS. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -22,10 +22,10 @@
#include <net/nfc/nci.h>
#include <net/nfc/nci_core.h>
-#include "st21nfcb.h"
-#include "st21nfcb_se.h"
+#include "st-nci.h"
+#include "st-nci_se.h"
-struct st21nfcb_pipe_info {
+struct st_nci_pipe_info {
u8 pipe_state;
u8 src_host_id;
u8 src_gate_id;
@@ -34,166 +34,166 @@ struct st21nfcb_pipe_info {
} __packed;
/* Hosts */
-#define ST21NFCB_HOST_CONTROLLER_ID 0x00
-#define ST21NFCB_TERMINAL_HOST_ID 0x01
-#define ST21NFCB_UICC_HOST_ID 0x02
-#define ST21NFCB_ESE_HOST_ID 0xc0
+#define ST_NCI_HOST_CONTROLLER_ID 0x00
+#define ST_NCI_TERMINAL_HOST_ID 0x01
+#define ST_NCI_UICC_HOST_ID 0x02
+#define ST_NCI_ESE_HOST_ID 0xc0
/* Gates */
-#define ST21NFCB_DEVICE_MGNT_GATE 0x01
-#define ST21NFCB_APDU_READER_GATE 0xf0
-#define ST21NFCB_CONNECTIVITY_GATE 0x41
+#define ST_NCI_DEVICE_MGNT_GATE 0x01
+#define ST_NCI_APDU_READER_GATE 0xf0
+#define ST_NCI_CONNECTIVITY_GATE 0x41
/* Pipes */
-#define ST21NFCB_DEVICE_MGNT_PIPE 0x02
+#define ST_NCI_DEVICE_MGNT_PIPE 0x02
/* Connectivity pipe only */
-#define ST21NFCB_SE_COUNT_PIPE_UICC 0x01
+#define ST_NCI_SE_COUNT_PIPE_UICC 0x01
/* Connectivity + APDU Reader pipe */
-#define ST21NFCB_SE_COUNT_PIPE_EMBEDDED 0x02
+#define ST_NCI_SE_COUNT_PIPE_EMBEDDED 0x02
-#define ST21NFCB_SE_TO_HOT_PLUG 1000 /* msecs */
-#define ST21NFCB_SE_TO_PIPES 2000
+#define ST_NCI_SE_TO_HOT_PLUG 1000 /* msecs */
+#define ST_NCI_SE_TO_PIPES 2000
-#define ST21NFCB_EVT_HOT_PLUG_IS_INHIBITED(x) (x->data[0] & 0x80)
+#define ST_NCI_EVT_HOT_PLUG_IS_INHIBITED(x) (x->data[0] & 0x80)
#define NCI_HCI_APDU_PARAM_ATR 0x01
#define NCI_HCI_ADMIN_PARAM_SESSION_IDENTITY 0x01
#define NCI_HCI_ADMIN_PARAM_WHITELIST 0x03
#define NCI_HCI_ADMIN_PARAM_HOST_LIST 0x04
-#define ST21NFCB_EVT_SE_HARD_RESET 0x20
-#define ST21NFCB_EVT_TRANSMIT_DATA 0x10
-#define ST21NFCB_EVT_WTX_REQUEST 0x11
-#define ST21NFCB_EVT_SE_SOFT_RESET 0x11
-#define ST21NFCB_EVT_SE_END_OF_APDU_TRANSFER 0x21
-#define ST21NFCB_EVT_HOT_PLUG 0x03
+#define ST_NCI_EVT_SE_HARD_RESET 0x20
+#define ST_NCI_EVT_TRANSMIT_DATA 0x10
+#define ST_NCI_EVT_WTX_REQUEST 0x11
+#define ST_NCI_EVT_SE_SOFT_RESET 0x11
+#define ST_NCI_EVT_SE_END_OF_APDU_TRANSFER 0x21
+#define ST_NCI_EVT_HOT_PLUG 0x03
-#define ST21NFCB_SE_MODE_OFF 0x00
-#define ST21NFCB_SE_MODE_ON 0x01
+#define ST_NCI_SE_MODE_OFF 0x00
+#define ST_NCI_SE_MODE_ON 0x01
-#define ST21NFCB_EVT_CONNECTIVITY 0x10
-#define ST21NFCB_EVT_TRANSACTION 0x12
+#define ST_NCI_EVT_CONNECTIVITY 0x10
+#define ST_NCI_EVT_TRANSACTION 0x12
-#define ST21NFCB_DM_GETINFO 0x13
-#define ST21NFCB_DM_GETINFO_PIPE_LIST 0x02
-#define ST21NFCB_DM_GETINFO_PIPE_INFO 0x01
-#define ST21NFCB_DM_PIPE_CREATED 0x02
-#define ST21NFCB_DM_PIPE_OPEN 0x04
-#define ST21NFCB_DM_RF_ACTIVE 0x80
-#define ST21NFCB_DM_DISCONNECT 0x30
+#define ST_NCI_DM_GETINFO 0x13
+#define ST_NCI_DM_GETINFO_PIPE_LIST 0x02
+#define ST_NCI_DM_GETINFO_PIPE_INFO 0x01
+#define ST_NCI_DM_PIPE_CREATED 0x02
+#define ST_NCI_DM_PIPE_OPEN 0x04
+#define ST_NCI_DM_RF_ACTIVE 0x80
+#define ST_NCI_DM_DISCONNECT 0x30
-#define ST21NFCB_DM_IS_PIPE_OPEN(p) \
- ((p & 0x0f) == (ST21NFCB_DM_PIPE_CREATED | ST21NFCB_DM_PIPE_OPEN))
+#define ST_NCI_DM_IS_PIPE_OPEN(p) \
+ ((p & 0x0f) == (ST_NCI_DM_PIPE_CREATED | ST_NCI_DM_PIPE_OPEN))
-#define ST21NFCB_ATR_DEFAULT_BWI 0x04
+#define ST_NCI_ATR_DEFAULT_BWI 0x04
/*
* WT = 2^BWI/10[s], convert into msecs and add a secure
* room by increasing by 2 this timeout
*/
-#define ST21NFCB_BWI_TO_TIMEOUT(x) ((1 << x) * 200)
-#define ST21NFCB_ATR_GET_Y_FROM_TD(x) (x >> 4)
+#define ST_NCI_BWI_TO_TIMEOUT(x) ((1 << x) * 200)
+#define ST_NCI_ATR_GET_Y_FROM_TD(x) (x >> 4)
/* If TA is present bit 0 is set */
-#define ST21NFCB_ATR_TA_PRESENT(x) (x & 0x01)
+#define ST_NCI_ATR_TA_PRESENT(x) (x & 0x01)
/* If TB is present bit 1 is set */
-#define ST21NFCB_ATR_TB_PRESENT(x) (x & 0x02)
+#define ST_NCI_ATR_TB_PRESENT(x) (x & 0x02)
-#define ST21NFCB_NUM_DEVICES 256
+#define ST_NCI_NUM_DEVICES 256
-static DECLARE_BITMAP(dev_mask, ST21NFCB_NUM_DEVICES);
+static DECLARE_BITMAP(dev_mask, ST_NCI_NUM_DEVICES);
-/* Here are the mandatory pipe for st21nfcb */
-static struct nci_hci_gate st21nfcb_gates[] = {
+/* Here are the mandatory pipe for st_nci */
+static struct nci_hci_gate st_nci_gates[] = {
{NCI_HCI_ADMIN_GATE, NCI_HCI_ADMIN_PIPE,
- ST21NFCB_HOST_CONTROLLER_ID},
+ ST_NCI_HOST_CONTROLLER_ID},
{NCI_HCI_LINK_MGMT_GATE, NCI_HCI_LINK_MGMT_PIPE,
- ST21NFCB_HOST_CONTROLLER_ID},
- {ST21NFCB_DEVICE_MGNT_GATE, ST21NFCB_DEVICE_MGNT_PIPE,
- ST21NFCB_HOST_CONTROLLER_ID},
+ ST_NCI_HOST_CONTROLLER_ID},
+ {ST_NCI_DEVICE_MGNT_GATE, ST_NCI_DEVICE_MGNT_PIPE,
+ ST_NCI_HOST_CONTROLLER_ID},
/* Secure element pipes are created by secure element host */
- {ST21NFCB_CONNECTIVITY_GATE, NCI_HCI_DO_NOT_OPEN_PIPE,
- ST21NFCB_HOST_CONTROLLER_ID},
- {ST21NFCB_APDU_READER_GATE, NCI_HCI_DO_NOT_OPEN_PIPE,
- ST21NFCB_HOST_CONTROLLER_ID},
+ {ST_NCI_CONNECTIVITY_GATE, NCI_HCI_DO_NOT_OPEN_PIPE,
+ ST_NCI_HOST_CONTROLLER_ID},
+ {ST_NCI_APDU_READER_GATE, NCI_HCI_DO_NOT_OPEN_PIPE,
+ ST_NCI_HOST_CONTROLLER_ID},
};
-static u8 st21nfcb_se_get_bwi(struct nci_dev *ndev)
+static u8 st_nci_se_get_bwi(struct nci_dev *ndev)
{
int i;
u8 td;
- struct st21nfcb_nci_info *info = nci_get_drvdata(ndev);
+ struct st_nci_info *info = nci_get_drvdata(ndev);
/* Bits 8 to 5 of the first TB for T=1 encode BWI from zero to nine */
- for (i = 1; i < ST21NFCB_ESE_MAX_LENGTH; i++) {
- td = ST21NFCB_ATR_GET_Y_FROM_TD(info->se_info.atr[i]);
- if (ST21NFCB_ATR_TA_PRESENT(td))
+ for (i = 1; i < ST_NCI_ESE_MAX_LENGTH; i++) {
+ td = ST_NCI_ATR_GET_Y_FROM_TD(info->se_info.atr[i]);
+ if (ST_NCI_ATR_TA_PRESENT(td))
i++;
- if (ST21NFCB_ATR_TB_PRESENT(td)) {
+ if (ST_NCI_ATR_TB_PRESENT(td)) {
i++;
return info->se_info.atr[i] >> 4;
}
}
- return ST21NFCB_ATR_DEFAULT_BWI;
+ return ST_NCI_ATR_DEFAULT_BWI;
}
-static void st21nfcb_se_get_atr(struct nci_dev *ndev)
+static void st_nci_se_get_atr(struct nci_dev *ndev)
{
- struct st21nfcb_nci_info *info = nci_get_drvdata(ndev);
+ struct st_nci_info *info = nci_get_drvdata(ndev);
int r;
struct sk_buff *skb;
- r = nci_hci_get_param(ndev, ST21NFCB_APDU_READER_GATE,
+ r = nci_hci_get_param(ndev, ST_NCI_APDU_READER_GATE,
NCI_HCI_APDU_PARAM_ATR, &skb);
if (r < 0)
return;
- if (skb->len <= ST21NFCB_ESE_MAX_LENGTH) {
+ if (skb->len <= ST_NCI_ESE_MAX_LENGTH) {
memcpy(info->se_info.atr, skb->data, skb->len);
info->se_info.wt_timeout =
- ST21NFCB_BWI_TO_TIMEOUT(st21nfcb_se_get_bwi(ndev));
+ ST_NCI_BWI_TO_TIMEOUT(st_nci_se_get_bwi(ndev));
}
kfree_skb(skb);
}
-int st21nfcb_hci_load_session(struct nci_dev *ndev)
+int st_nci_hci_load_session(struct nci_dev *ndev)
{
int i, j, r;
struct sk_buff *skb_pipe_list, *skb_pipe_info;
- struct st21nfcb_pipe_info *dm_pipe_info;
- u8 pipe_list[] = { ST21NFCB_DM_GETINFO_PIPE_LIST,
- ST21NFCB_TERMINAL_HOST_ID};
- u8 pipe_info[] = { ST21NFCB_DM_GETINFO_PIPE_INFO,
- ST21NFCB_TERMINAL_HOST_ID, 0};
+ struct st_nci_pipe_info *dm_pipe_info;
+ u8 pipe_list[] = { ST_NCI_DM_GETINFO_PIPE_LIST,
+ ST_NCI_TERMINAL_HOST_ID};
+ u8 pipe_info[] = { ST_NCI_DM_GETINFO_PIPE_INFO,
+ ST_NCI_TERMINAL_HOST_ID, 0};
- /* On ST21NFCB device pipes number are dynamics
+ /* On ST_NCI device pipes number are dynamics
* If pipes are already created, hci_dev_up will fail.
* Doing a clear all pipe is a bad idea because:
* - It does useless EEPROM cycling
* - It might cause issue for secure elements support
* (such as removing connectivity or APDU reader pipe)
- * A better approach on ST21NFCB is to:
+ * A better approach on ST_NCI is to:
* - get a pipe list for each host.
- * (eg: ST21NFCB_HOST_CONTROLLER_ID for now).
+ * (eg: ST_NCI_HOST_CONTROLLER_ID for now).
* (TODO Later on UICC HOST and eSE HOST)
* - get pipe information
- * - match retrieved pipe list in st21nfcb_gates
- * ST21NFCB_DEVICE_MGNT_GATE is a proprietary gate
- * with ST21NFCB_DEVICE_MGNT_PIPE.
+ * - match retrieved pipe list in st_nci_gates
+ * ST_NCI_DEVICE_MGNT_GATE is a proprietary gate
+ * with ST_NCI_DEVICE_MGNT_PIPE.
* Pipe can be closed and need to be open.
*/
- r = nci_hci_connect_gate(ndev, ST21NFCB_HOST_CONTROLLER_ID,
- ST21NFCB_DEVICE_MGNT_GATE,
- ST21NFCB_DEVICE_MGNT_PIPE);
+ r = nci_hci_connect_gate(ndev, ST_NCI_HOST_CONTROLLER_ID,
+ ST_NCI_DEVICE_MGNT_GATE,
+ ST_NCI_DEVICE_MGNT_PIPE);
if (r < 0)
goto free_info;
/* Get pipe list */
- r = nci_hci_send_cmd(ndev, ST21NFCB_DEVICE_MGNT_GATE,
- ST21NFCB_DM_GETINFO, pipe_list, sizeof(pipe_list),
+ r = nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
+ ST_NCI_DM_GETINFO, pipe_list, sizeof(pipe_list),
&skb_pipe_list);
if (r < 0)
goto free_info;
@@ -201,8 +201,8 @@ int st21nfcb_hci_load_session(struct nci_dev *ndev)
/* Complete the existing gate_pipe table */
for (i = 0; i < skb_pipe_list->len; i++) {
pipe_info[2] = skb_pipe_list->data[i];
- r = nci_hci_send_cmd(ndev, ST21NFCB_DEVICE_MGNT_GATE,
- ST21NFCB_DM_GETINFO, pipe_info,
+ r = nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
+ ST_NCI_DM_GETINFO, pipe_info,
sizeof(pipe_info), &skb_pipe_info);
if (r)
@@ -217,81 +217,81 @@ int st21nfcb_hci_load_session(struct nci_dev *ndev)
* - destination hid (1byte)
* - destination gid (1byte)
*/
- dm_pipe_info = (struct st21nfcb_pipe_info *)skb_pipe_info->data;
- if (dm_pipe_info->dst_gate_id == ST21NFCB_APDU_READER_GATE &&
- dm_pipe_info->src_host_id != ST21NFCB_ESE_HOST_ID) {
+ dm_pipe_info = (struct st_nci_pipe_info *)skb_pipe_info->data;
+ if (dm_pipe_info->dst_gate_id == ST_NCI_APDU_READER_GATE &&
+ dm_pipe_info->src_host_id != ST_NCI_ESE_HOST_ID) {
pr_err("Unexpected apdu_reader pipe on host %x\n",
dm_pipe_info->src_host_id);
continue;
}
- for (j = 0; (j < ARRAY_SIZE(st21nfcb_gates)) &&
- (st21nfcb_gates[j].gate != dm_pipe_info->dst_gate_id); j++)
+ for (j = 0; (j < ARRAY_SIZE(st_nci_gates)) &&
+ (st_nci_gates[j].gate != dm_pipe_info->dst_gate_id); j++)
;
- if (j < ARRAY_SIZE(st21nfcb_gates) &&
- st21nfcb_gates[j].gate == dm_pipe_info->dst_gate_id &&
- ST21NFCB_DM_IS_PIPE_OPEN(dm_pipe_info->pipe_state)) {
- st21nfcb_gates[j].pipe = pipe_info[2];
+ if (j < ARRAY_SIZE(st_nci_gates) &&
+ st_nci_gates[j].gate == dm_pipe_info->dst_gate_id &&
+ ST_NCI_DM_IS_PIPE_OPEN(dm_pipe_info->pipe_state)) {
+ st_nci_gates[j].pipe = pipe_info[2];
- ndev->hci_dev->gate2pipe[st21nfcb_gates[j].gate] =
- st21nfcb_gates[j].pipe;
- ndev->hci_dev->pipes[st21nfcb_gates[j].pipe].gate =
- st21nfcb_gates[j].gate;
- ndev->hci_dev->pipes[st21nfcb_gates[j].pipe].host =
+ ndev->hci_dev->gate2pipe[st_nci_gates[j].gate] =
+ st_nci_gates[j].pipe;
+ ndev->hci_dev->pipes[st_nci_gates[j].pipe].gate =
+ st_nci_gates[j].gate;
+ ndev->hci_dev->pipes[st_nci_gates[j].pipe].host =
dm_pipe_info->src_host_id;
}
}
- memcpy(ndev->hci_dev->init_data.gates, st21nfcb_gates,
- sizeof(st21nfcb_gates));
+ memcpy(ndev->hci_dev->init_data.gates, st_nci_gates,
+ sizeof(st_nci_gates));
free_info:
kfree_skb(skb_pipe_info);
kfree_skb(skb_pipe_list);
return r;
}
-EXPORT_SYMBOL_GPL(st21nfcb_hci_load_session);
+EXPORT_SYMBOL_GPL(st_nci_hci_load_session);
-static void st21nfcb_hci_admin_event_received(struct nci_dev *ndev,
+static void st_nci_hci_admin_event_received(struct nci_dev *ndev,
u8 event, struct sk_buff *skb)
{
- struct st21nfcb_nci_info *info = nci_get_drvdata(ndev);
+ struct st_nci_info *info = nci_get_drvdata(ndev);
switch (event) {
- case ST21NFCB_EVT_HOT_PLUG:
+ case ST_NCI_EVT_HOT_PLUG:
if (info->se_info.se_active) {
- if (!ST21NFCB_EVT_HOT_PLUG_IS_INHIBITED(skb)) {
+ if (!ST_NCI_EVT_HOT_PLUG_IS_INHIBITED(skb)) {
del_timer_sync(&info->se_info.se_active_timer);
info->se_info.se_active = false;
complete(&info->se_info.req_completion);
} else {
mod_timer(&info->se_info.se_active_timer,
jiffies +
- msecs_to_jiffies(ST21NFCB_SE_TO_PIPES));
+ msecs_to_jiffies(ST_NCI_SE_TO_PIPES));
}
}
break;
}
}
-static int st21nfcb_hci_apdu_reader_event_received(struct nci_dev *ndev,
+static int st_nci_hci_apdu_reader_event_received(struct nci_dev *ndev,
u8 event,
struct sk_buff *skb)
{
int r = 0;
- struct st21nfcb_nci_info *info = nci_get_drvdata(ndev);
+ struct st_nci_info *info = nci_get_drvdata(ndev);
pr_debug("apdu reader gate event: %x\n", event);
switch (event) {
- case ST21NFCB_EVT_TRANSMIT_DATA:
+ case ST_NCI_EVT_TRANSMIT_DATA:
del_timer_sync(&info->se_info.bwi_timer);
info->se_info.bwi_active = false;
info->se_info.cb(info->se_info.cb_context,
skb->data, skb->len, 0);
break;
- case ST21NFCB_EVT_WTX_REQUEST:
+ case ST_NCI_EVT_WTX_REQUEST:
mod_timer(&info->se_info.bwi_timer, jiffies +
msecs_to_jiffies(info->se_info.wt_timeout));
break;
@@ -306,7 +306,7 @@ static int st21nfcb_hci_apdu_reader_event_received(struct nci_dev *ndev,
* <= 0: driver handled the event, skb consumed
* 1: driver does not handle the event, please do standard processing
*/
-static int st21nfcb_hci_connectivity_event_received(struct nci_dev *ndev,
+static int st_nci_hci_connectivity_event_received(struct nci_dev *ndev,
u8 host, u8 event,
struct sk_buff *skb)
{
@@ -317,10 +317,10 @@ static int st21nfcb_hci_connectivity_event_received(struct nci_dev *ndev,
pr_debug("connectivity gate event: %x\n", event);
switch (event) {
- case ST21NFCB_EVT_CONNECTIVITY:
+ case ST_NCI_EVT_CONNECTIVITY:
break;
- case ST21NFCB_EVT_TRANSACTION:
+ case ST_NCI_EVT_TRANSACTION:
/* According to specification etsi 102 622
* 11.2.2.4 EVT_TRANSACTION Table 52
* Description Tag Length
@@ -355,7 +355,7 @@ static int st21nfcb_hci_connectivity_event_received(struct nci_dev *ndev,
return r;
}
-void st21nfcb_hci_event_received(struct nci_dev *ndev, u8 pipe,
+void st_nci_hci_event_received(struct nci_dev *ndev, u8 pipe,
u8 event, struct sk_buff *skb)
{
u8 gate = ndev->hci_dev->pipes[pipe].gate;
@@ -363,32 +363,32 @@ void st21nfcb_hci_event_received(struct nci_dev *ndev, u8 pipe,
switch (gate) {
case NCI_HCI_ADMIN_GATE:
- st21nfcb_hci_admin_event_received(ndev, event, skb);
+ st_nci_hci_admin_event_received(ndev, event, skb);
break;
- case ST21NFCB_APDU_READER_GATE:
- st21nfcb_hci_apdu_reader_event_received(ndev, event, skb);
+ case ST_NCI_APDU_READER_GATE:
+ st_nci_hci_apdu_reader_event_received(ndev, event, skb);
break;
- case ST21NFCB_CONNECTIVITY_GATE:
- st21nfcb_hci_connectivity_event_received(ndev, host, event,
+ case ST_NCI_CONNECTIVITY_GATE:
+ st_nci_hci_connectivity_event_received(ndev, host, event,
skb);
break;
}
}
-EXPORT_SYMBOL_GPL(st21nfcb_hci_event_received);
+EXPORT_SYMBOL_GPL(st_nci_hci_event_received);
-void st21nfcb_hci_cmd_received(struct nci_dev *ndev, u8 pipe, u8 cmd,
+void st_nci_hci_cmd_received(struct nci_dev *ndev, u8 pipe, u8 cmd,
struct sk_buff *skb)
{
- struct st21nfcb_nci_info *info = nci_get_drvdata(ndev);
+ struct st_nci_info *info = nci_get_drvdata(ndev);
u8 gate = ndev->hci_dev->pipes[pipe].gate;
pr_debug("cmd: %x\n", cmd);
switch (cmd) {
case NCI_HCI_ANY_OPEN_PIPE:
- if (gate != ST21NFCB_APDU_READER_GATE &&
- ndev->hci_dev->pipes[pipe].host != ST21NFCB_UICC_HOST_ID)
+ if (gate != ST_NCI_APDU_READER_GATE &&
+ ndev->hci_dev->pipes[pipe].host != ST_NCI_UICC_HOST_ID)
ndev->hci_dev->count_pipes++;
if (ndev->hci_dev->count_pipes ==
@@ -401,28 +401,28 @@ void st21nfcb_hci_cmd_received(struct nci_dev *ndev, u8 pipe, u8 cmd,
break;
}
}
-EXPORT_SYMBOL_GPL(st21nfcb_hci_cmd_received);
+EXPORT_SYMBOL_GPL(st_nci_hci_cmd_received);
/*
- * Remarks: On some early st21nfcb firmware, nci_nfcee_mode_set(0)
+ * Remarks: On some early st_nci firmware, nci_nfcee_mode_set(0)
* is rejected
*/
-static int st21nfcb_nci_control_se(struct nci_dev *ndev, u8 se_idx,
+static int st_nci_control_se(struct nci_dev *ndev, u8 se_idx,
u8 state)
{
- struct st21nfcb_nci_info *info = nci_get_drvdata(ndev);
+ struct st_nci_info *info = nci_get_drvdata(ndev);
int r;
struct sk_buff *sk_host_list;
u8 host_id;
switch (se_idx) {
- case ST21NFCB_UICC_HOST_ID:
+ case ST_NCI_UICC_HOST_ID:
ndev->hci_dev->count_pipes = 0;
- ndev->hci_dev->expected_pipes = ST21NFCB_SE_COUNT_PIPE_UICC;
+ ndev->hci_dev->expected_pipes = ST_NCI_SE_COUNT_PIPE_UICC;
break;
- case ST21NFCB_ESE_HOST_ID:
+ case ST_NCI_ESE_HOST_ID:
ndev->hci_dev->count_pipes = 0;
- ndev->hci_dev->expected_pipes = ST21NFCB_SE_COUNT_PIPE_EMBEDDED;
+ ndev->hci_dev->expected_pipes = ST_NCI_SE_COUNT_PIPE_EMBEDDED;
break;
default:
return -EINVAL;
@@ -438,7 +438,7 @@ static int st21nfcb_nci_control_se(struct nci_dev *ndev, u8 se_idx,
return r;
mod_timer(&info->se_info.se_active_timer, jiffies +
- msecs_to_jiffies(ST21NFCB_SE_TO_HOT_PLUG));
+ msecs_to_jiffies(ST_NCI_SE_TO_HOT_PLUG));
info->se_info.se_active = true;
/* Ignore return value and check in any case the host_list */
@@ -458,49 +458,49 @@ static int st21nfcb_nci_control_se(struct nci_dev *ndev, u8 se_idx,
host_id = sk_host_list->data[sk_host_list->len - 1];
kfree_skb(sk_host_list);
- if (state == ST21NFCB_SE_MODE_ON && host_id == se_idx)
+ if (state == ST_NCI_SE_MODE_ON && host_id == se_idx)
return se_idx;
- else if (state == ST21NFCB_SE_MODE_OFF && host_id != se_idx)
+ else if (state == ST_NCI_SE_MODE_OFF && host_id != se_idx)
return se_idx;
return -1;
}
-int st21nfcb_nci_disable_se(struct nci_dev *ndev, u32 se_idx)
+int st_nci_disable_se(struct nci_dev *ndev, u32 se_idx)
{
int r;
- pr_debug("st21nfcb_nci_disable_se\n");
+ pr_debug("st_nci_disable_se\n");
if (se_idx == NFC_SE_EMBEDDED) {
- r = nci_hci_send_event(ndev, ST21NFCB_APDU_READER_GATE,
- ST21NFCB_EVT_SE_END_OF_APDU_TRANSFER, NULL, 0);
+ r = nci_hci_send_event(ndev, ST_NCI_APDU_READER_GATE,
+ ST_NCI_EVT_SE_END_OF_APDU_TRANSFER, NULL, 0);
if (r < 0)
return r;
}
return 0;
}
-EXPORT_SYMBOL_GPL(st21nfcb_nci_disable_se);
+EXPORT_SYMBOL_GPL(st_nci_disable_se);
-int st21nfcb_nci_enable_se(struct nci_dev *ndev, u32 se_idx)
+int st_nci_enable_se(struct nci_dev *ndev, u32 se_idx)
{
int r;
- pr_debug("st21nfcb_nci_enable_se\n");
+ pr_debug("st_nci_enable_se\n");
- if (se_idx == ST21NFCB_HCI_HOST_ID_ESE) {
- r = nci_hci_send_event(ndev, ST21NFCB_APDU_READER_GATE,
- ST21NFCB_EVT_SE_SOFT_RESET, NULL, 0);
+ if (se_idx == ST_NCI_HCI_HOST_ID_ESE) {
+ r = nci_hci_send_event(ndev, ST_NCI_APDU_READER_GATE,
+ ST_NCI_EVT_SE_SOFT_RESET, NULL, 0);
if (r < 0)
return r;
}
return 0;
}
-EXPORT_SYMBOL_GPL(st21nfcb_nci_enable_se);
+EXPORT_SYMBOL_GPL(st_nci_enable_se);
-static int st21nfcb_hci_network_init(struct nci_dev *ndev)
+static int st_nci_hci_network_init(struct nci_dev *ndev)
{
struct core_conn_create_dest_spec_params *dest_params;
struct dest_spec_params spec_params;
@@ -519,7 +519,8 @@ static int st21nfcb_hci_network_init(struct nci_dev *ndev)
dest_params->length = sizeof(struct dest_spec_params);
spec_params.id = ndev->hci_dev->nfcee_id;
spec_params.protocol = NCI_NFCEE_INTERFACE_HCI_ACCESS;
- memcpy(dest_params->value, &spec_params, sizeof(struct dest_spec_params));
+ memcpy(dest_params->value, &spec_params,
+ sizeof(struct dest_spec_params));
r = nci_core_conn_create(ndev, NCI_DESTINATION_NFCEE, 1,
sizeof(struct core_conn_create_dest_spec_params) +
sizeof(struct dest_spec_params),
@@ -531,15 +532,15 @@ static int st21nfcb_hci_network_init(struct nci_dev *ndev)
if (!conn_info)
goto free_dest_params;
- memcpy(ndev->hci_dev->init_data.gates, st21nfcb_gates,
- sizeof(st21nfcb_gates));
+ memcpy(ndev->hci_dev->init_data.gates, st_nci_gates,
+ sizeof(st_nci_gates));
/*
* Session id must include the driver name + i2c bus addr
* persistent info to discriminate 2 identical chips
*/
- dev_num = find_first_zero_bit(dev_mask, ST21NFCB_NUM_DEVICES);
- if (dev_num >= ST21NFCB_NUM_DEVICES) {
+ dev_num = find_first_zero_bit(dev_mask, ST_NCI_NUM_DEVICES);
+ if (dev_num >= ST_NCI_NUM_DEVICES) {
r = -ENODEV;
goto free_dest_params;
}
@@ -564,72 +565,72 @@ exit:
return r;
}
-int st21nfcb_nci_discover_se(struct nci_dev *ndev)
+int st_nci_discover_se(struct nci_dev *ndev)
{
u8 param[2];
int r;
int se_count = 0;
- pr_debug("st21nfcb_nci_discover_se\n");
+ pr_debug("st_nci_discover_se\n");
- r = st21nfcb_hci_network_init(ndev);
+ r = st_nci_hci_network_init(ndev);
if (r != 0)
return r;
- param[0] = ST21NFCB_UICC_HOST_ID;
- param[1] = ST21NFCB_HCI_HOST_ID_ESE;
+ param[0] = ST_NCI_UICC_HOST_ID;
+ param[1] = ST_NCI_HCI_HOST_ID_ESE;
r = nci_hci_set_param(ndev, NCI_HCI_ADMIN_GATE,
NCI_HCI_ADMIN_PARAM_WHITELIST,
param, sizeof(param));
if (r != NCI_HCI_ANY_OK)
return r;
- r = st21nfcb_nci_control_se(ndev, ST21NFCB_UICC_HOST_ID,
- ST21NFCB_SE_MODE_ON);
- if (r == ST21NFCB_UICC_HOST_ID) {
- nfc_add_se(ndev->nfc_dev, ST21NFCB_UICC_HOST_ID, NFC_SE_UICC);
+ r = st_nci_control_se(ndev, ST_NCI_UICC_HOST_ID,
+ ST_NCI_SE_MODE_ON);
+ if (r == ST_NCI_UICC_HOST_ID) {
+ nfc_add_se(ndev->nfc_dev, ST_NCI_UICC_HOST_ID, NFC_SE_UICC);
se_count++;
}
/* Try to enable eSE in order to check availability */
- r = st21nfcb_nci_control_se(ndev, ST21NFCB_HCI_HOST_ID_ESE,
- ST21NFCB_SE_MODE_ON);
- if (r == ST21NFCB_HCI_HOST_ID_ESE) {
- nfc_add_se(ndev->nfc_dev, ST21NFCB_HCI_HOST_ID_ESE,
+ r = st_nci_control_se(ndev, ST_NCI_HCI_HOST_ID_ESE,
+ ST_NCI_SE_MODE_ON);
+ if (r == ST_NCI_HCI_HOST_ID_ESE) {
+ nfc_add_se(ndev->nfc_dev, ST_NCI_HCI_HOST_ID_ESE,
NFC_SE_EMBEDDED);
se_count++;
- st21nfcb_se_get_atr(ndev);
+ st_nci_se_get_atr(ndev);
}
return !se_count;
}
-EXPORT_SYMBOL_GPL(st21nfcb_nci_discover_se);
+EXPORT_SYMBOL_GPL(st_nci_discover_se);
-int st21nfcb_nci_se_io(struct nci_dev *ndev, u32 se_idx,
+int st_nci_se_io(struct nci_dev *ndev, u32 se_idx,
u8 *apdu, size_t apdu_length,
se_io_cb_t cb, void *cb_context)
{
- struct st21nfcb_nci_info *info = nci_get_drvdata(ndev);
+ struct st_nci_info *info = nci_get_drvdata(ndev);
pr_debug("\n");
switch (se_idx) {
- case ST21NFCB_HCI_HOST_ID_ESE:
+ case ST_NCI_HCI_HOST_ID_ESE:
info->se_info.cb = cb;
info->se_info.cb_context = cb_context;
mod_timer(&info->se_info.bwi_timer, jiffies +
msecs_to_jiffies(info->se_info.wt_timeout));
info->se_info.bwi_active = true;
- return nci_hci_send_event(ndev, ST21NFCB_APDU_READER_GATE,
- ST21NFCB_EVT_TRANSMIT_DATA, apdu,
+ return nci_hci_send_event(ndev, ST_NCI_APDU_READER_GATE,
+ ST_NCI_EVT_TRANSMIT_DATA, apdu,
apdu_length);
default:
return -ENODEV;
}
}
-EXPORT_SYMBOL(st21nfcb_nci_se_io);
+EXPORT_SYMBOL(st_nci_se_io);
-static void st21nfcb_se_wt_timeout(unsigned long data)
+static void st_nci_se_wt_timeout(unsigned long data)
{
/*
* No answer from the secure element
@@ -642,7 +643,7 @@ static void st21nfcb_se_wt_timeout(unsigned long data)
*/
/* hardware reset managed through VCC_UICC_OUT power supply */
u8 param = 0x01;
- struct st21nfcb_nci_info *info = (struct st21nfcb_nci_info *) data;
+ struct st_nci_info *info = (struct st_nci_info *) data;
pr_debug("\n");
@@ -650,19 +651,19 @@ static void st21nfcb_se_wt_timeout(unsigned long data)
if (!info->se_info.xch_error) {
info->se_info.xch_error = true;
- nci_hci_send_event(info->ndlc->ndev, ST21NFCB_APDU_READER_GATE,
- ST21NFCB_EVT_SE_SOFT_RESET, NULL, 0);
+ nci_hci_send_event(info->ndlc->ndev, ST_NCI_APDU_READER_GATE,
+ ST_NCI_EVT_SE_SOFT_RESET, NULL, 0);
} else {
info->se_info.xch_error = false;
- nci_hci_send_event(info->ndlc->ndev, ST21NFCB_DEVICE_MGNT_GATE,
- ST21NFCB_EVT_SE_HARD_RESET, &param, 1);
+ nci_hci_send_event(info->ndlc->ndev, ST_NCI_DEVICE_MGNT_GATE,
+ ST_NCI_EVT_SE_HARD_RESET, &param, 1);
}
info->se_info.cb(info->se_info.cb_context, NULL, 0, -ETIME);
}
-static void st21nfcb_se_activation_timeout(unsigned long data)
+static void st_nci_se_activation_timeout(unsigned long data)
{
- struct st21nfcb_nci_info *info = (struct st21nfcb_nci_info *) data;
+ struct st_nci_info *info = (struct st_nci_info *) data;
pr_debug("\n");
@@ -671,35 +672,35 @@ static void st21nfcb_se_activation_timeout(unsigned long data)
complete(&info->se_info.req_completion);
}
-int st21nfcb_se_init(struct nci_dev *ndev)
+int st_nci_se_init(struct nci_dev *ndev)
{
- struct st21nfcb_nci_info *info = nci_get_drvdata(ndev);
+ struct st_nci_info *info = nci_get_drvdata(ndev);
init_completion(&info->se_info.req_completion);
/* initialize timers */
init_timer(&info->se_info.bwi_timer);
info->se_info.bwi_timer.data = (unsigned long)info;
- info->se_info.bwi_timer.function = st21nfcb_se_wt_timeout;
+ info->se_info.bwi_timer.function = st_nci_se_wt_timeout;
info->se_info.bwi_active = false;
init_timer(&info->se_info.se_active_timer);
info->se_info.se_active_timer.data = (unsigned long)info;
info->se_info.se_active_timer.function =
- st21nfcb_se_activation_timeout;
+ st_nci_se_activation_timeout;
info->se_info.se_active = false;
info->se_info.xch_error = false;
info->se_info.wt_timeout =
- ST21NFCB_BWI_TO_TIMEOUT(ST21NFCB_ATR_DEFAULT_BWI);
+ ST_NCI_BWI_TO_TIMEOUT(ST_NCI_ATR_DEFAULT_BWI);
return 0;
}
-EXPORT_SYMBOL(st21nfcb_se_init);
+EXPORT_SYMBOL(st_nci_se_init);
-void st21nfcb_se_deinit(struct nci_dev *ndev)
+void st_nci_se_deinit(struct nci_dev *ndev)
{
- struct st21nfcb_nci_info *info = nci_get_drvdata(ndev);
+ struct st_nci_info *info = nci_get_drvdata(ndev);
if (info->se_info.bwi_active)
del_timer_sync(&info->se_info.bwi_timer);
@@ -709,5 +710,5 @@ void st21nfcb_se_deinit(struct nci_dev *ndev)
info->se_info.se_active = false;
info->se_info.bwi_active = false;
}
-EXPORT_SYMBOL(st21nfcb_se_deinit);
+EXPORT_SYMBOL(st_nci_se_deinit);
diff --git a/drivers/nfc/st-nci/st-nci_se.h b/drivers/nfc/st-nci/st-nci_se.h
new file mode 100644
index 000000000000..ea66e879d67f
--- /dev/null
+++ b/drivers/nfc/st-nci/st-nci_se.h
@@ -0,0 +1,61 @@
+/*
+ * Secure Element Driver for STMicroelectronics NFC NCI Chip
+ *
+ * Copyright (C) 2014-2015 STMicroelectronics SAS. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __LOCAL_ST_NCI_SE_H_
+#define __LOCAL_ST_NCI_SE_H_
+
+/*
+ * ref ISO7816-3 chap 8.1. the initial character TS is followed by a
+ * sequence of at most 32 characters.
+ */
+#define ST_NCI_ESE_MAX_LENGTH 33
+#define ST_NCI_HCI_HOST_ID_ESE 0xc0
+
+struct st_nci_se_info {
+ u8 atr[ST_NCI_ESE_MAX_LENGTH];
+ struct completion req_completion;
+
+ struct timer_list bwi_timer;
+ int wt_timeout; /* in msecs */
+ bool bwi_active;
+
+ struct timer_list se_active_timer;
+ bool se_active;
+
+ bool xch_error;
+
+ se_io_cb_t cb;
+ void *cb_context;
+};
+
+int st_nci_se_init(struct nci_dev *ndev);
+void st_nci_se_deinit(struct nci_dev *ndev);
+
+int st_nci_discover_se(struct nci_dev *ndev);
+int st_nci_enable_se(struct nci_dev *ndev, u32 se_idx);
+int st_nci_disable_se(struct nci_dev *ndev, u32 se_idx);
+int st_nci_se_io(struct nci_dev *ndev, u32 se_idx,
+ u8 *apdu, size_t apdu_length,
+ se_io_cb_t cb, void *cb_context);
+int st_nci_hci_load_session(struct nci_dev *ndev);
+void st_nci_hci_event_received(struct nci_dev *ndev, u8 pipe,
+ u8 event, struct sk_buff *skb);
+void st_nci_hci_cmd_received(struct nci_dev *ndev, u8 pipe, u8 cmd,
+ struct sk_buff *skb);
+
+
+#endif /* __LOCAL_ST_NCI_SE_H_ */
diff --git a/drivers/nfc/st21nfcb/Kconfig b/drivers/nfc/st21nfcb/Kconfig
deleted file mode 100644
index e0322dd03a70..000000000000
--- a/drivers/nfc/st21nfcb/Kconfig
+++ /dev/null
@@ -1,22 +0,0 @@
-config NFC_ST21NFCB
- tristate "STMicroelectronics ST21NFCB NFC driver"
- depends on NFC_NCI
- default n
- ---help---
- STMicroelectronics ST21NFCB core driver. It implements the chipset
- NCI logic and hooks into the NFC kernel APIs. Physical layers will
- register against it.
-
- To compile this driver as a module, choose m here. The module will
- be called st21nfcb.
- Say N if unsure.
-
-config NFC_ST21NFCB_I2C
- tristate "NFC ST21NFCB i2c support"
- depends on NFC_ST21NFCB && I2C
- ---help---
- This module adds support for the STMicroelectronics st21nfcb i2c interface.
- Select this if your platform is using the i2c bus.
-
- If you choose to build a module, it'll be called st21nfcb_i2c.
- Say N if unsure.
diff --git a/drivers/nfc/st21nfcb/Makefile b/drivers/nfc/st21nfcb/Makefile
deleted file mode 100644
index ce659a9e5a1a..000000000000
--- a/drivers/nfc/st21nfcb/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# Makefile for ST21NFCB NCI based NFC driver
-#
-
-st21nfcb_nci-objs = ndlc.o st21nfcb.o st21nfcb_se.o
-obj-$(CONFIG_NFC_ST21NFCB) += st21nfcb_nci.o
-
-st21nfcb_i2c-objs = i2c.o
-obj-$(CONFIG_NFC_ST21NFCB_I2C) += st21nfcb_i2c.o
diff --git a/drivers/nfc/st21nfcb/st21nfcb.c b/drivers/nfc/st21nfcb/st21nfcb.c
deleted file mode 100644
index ca9871ab3fb3..000000000000
--- a/drivers/nfc/st21nfcb/st21nfcb.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * NCI based Driver for STMicroelectronics NFC Chip
- *
- * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/module.h>
-#include <linux/nfc.h>
-#include <net/nfc/nci.h>
-#include <net/nfc/nci_core.h>
-
-#include "st21nfcb.h"
-#include "st21nfcb_se.h"
-
-#define DRIVER_DESC "NCI NFC driver for ST21NFCB"
-
-#define ST21NFCB_NCI1_X_PROPRIETARY_ISO15693 0x83
-
-static int st21nfcb_nci_open(struct nci_dev *ndev)
-{
- struct st21nfcb_nci_info *info = nci_get_drvdata(ndev);
- int r;
-
- if (test_and_set_bit(ST21NFCB_NCI_RUNNING, &info->flags))
- return 0;
-
- r = ndlc_open(info->ndlc);
- if (r)
- clear_bit(ST21NFCB_NCI_RUNNING, &info->flags);
-
- return r;
-}
-
-static int st21nfcb_nci_close(struct nci_dev *ndev)
-{
- struct st21nfcb_nci_info *info = nci_get_drvdata(ndev);
-
- if (!test_and_clear_bit(ST21NFCB_NCI_RUNNING, &info->flags))
- return 0;
-
- ndlc_close(info->ndlc);
-
- return 0;
-}
-
-static int st21nfcb_nci_send(struct nci_dev *ndev, struct sk_buff *skb)
-{
- struct st21nfcb_nci_info *info = nci_get_drvdata(ndev);
-
- skb->dev = (void *)ndev;
-
- if (!test_bit(ST21NFCB_NCI_RUNNING, &info->flags))
- return -EBUSY;
-
- return ndlc_send(info->ndlc, skb);
-}
-
-static __u32 st21nfcb_nci_get_rfprotocol(struct nci_dev *ndev,
- __u8 rf_protocol)
-{
- return rf_protocol == ST21NFCB_NCI1_X_PROPRIETARY_ISO15693 ?
- NFC_PROTO_ISO15693_MASK : 0;
-}
-
-static struct nci_ops st21nfcb_nci_ops = {
- .open = st21nfcb_nci_open,
- .close = st21nfcb_nci_close,
- .send = st21nfcb_nci_send,
- .get_rfprotocol = st21nfcb_nci_get_rfprotocol,
- .discover_se = st21nfcb_nci_discover_se,
- .enable_se = st21nfcb_nci_enable_se,
- .disable_se = st21nfcb_nci_disable_se,
- .se_io = st21nfcb_nci_se_io,
- .hci_load_session = st21nfcb_hci_load_session,
- .hci_event_received = st21nfcb_hci_event_received,
- .hci_cmd_received = st21nfcb_hci_cmd_received,
-};
-
-int st21nfcb_nci_probe(struct llt_ndlc *ndlc, int phy_headroom,
- int phy_tailroom)
-{
- struct st21nfcb_nci_info *info;
- int r;
- u32 protocols;
-
- info = devm_kzalloc(ndlc->dev,
- sizeof(struct st21nfcb_nci_info), GFP_KERNEL);
- if (!info)
- return -ENOMEM;
-
- protocols = NFC_PROTO_JEWEL_MASK
- | NFC_PROTO_MIFARE_MASK
- | NFC_PROTO_FELICA_MASK
- | NFC_PROTO_ISO14443_MASK
- | NFC_PROTO_ISO14443_B_MASK
- | NFC_PROTO_ISO15693_MASK
- | NFC_PROTO_NFC_DEP_MASK;
-
- ndlc->ndev = nci_allocate_device(&st21nfcb_nci_ops, protocols,
- phy_headroom, phy_tailroom);
- if (!ndlc->ndev) {
- pr_err("Cannot allocate nfc ndev\n");
- return -ENOMEM;
- }
- info->ndlc = ndlc;
-
- nci_set_drvdata(ndlc->ndev, info);
-
- r = nci_register_device(ndlc->ndev);
- if (r) {
- pr_err("Cannot register nfc device to nci core\n");
- nci_free_device(ndlc->ndev);
- return r;
- }
-
- return st21nfcb_se_init(ndlc->ndev);
-}
-EXPORT_SYMBOL_GPL(st21nfcb_nci_probe);
-
-void st21nfcb_nci_remove(struct nci_dev *ndev)
-{
- struct st21nfcb_nci_info *info = nci_get_drvdata(ndev);
-
- nci_unregister_device(ndev);
- nci_free_device(ndev);
- kfree(info);
-}
-EXPORT_SYMBOL_GPL(st21nfcb_nci_remove);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/nfc/st21nfcb/st21nfcb_se.h b/drivers/nfc/st21nfcb/st21nfcb_se.h
deleted file mode 100644
index 52a323872bea..000000000000
--- a/drivers/nfc/st21nfcb/st21nfcb_se.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * NCI based Driver for STMicroelectronics NFC Chip
- *
- * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef __LOCAL_ST21NFCB_SE_H_
-#define __LOCAL_ST21NFCB_SE_H_
-
-/*
- * ref ISO7816-3 chap 8.1. the initial character TS is followed by a
- * sequence of at most 32 characters.
- */
-#define ST21NFCB_ESE_MAX_LENGTH 33
-#define ST21NFCB_HCI_HOST_ID_ESE 0xc0
-
-struct st21nfcb_se_info {
- u8 atr[ST21NFCB_ESE_MAX_LENGTH];
- struct completion req_completion;
-
- struct timer_list bwi_timer;
- int wt_timeout; /* in msecs */
- bool bwi_active;
-
- struct timer_list se_active_timer;
- bool se_active;
-
- bool xch_error;
-
- se_io_cb_t cb;
- void *cb_context;
-};
-
-int st21nfcb_se_init(struct nci_dev *ndev);
-void st21nfcb_se_deinit(struct nci_dev *ndev);
-
-int st21nfcb_nci_discover_se(struct nci_dev *ndev);
-int st21nfcb_nci_enable_se(struct nci_dev *ndev, u32 se_idx);
-int st21nfcb_nci_disable_se(struct nci_dev *ndev, u32 se_idx);
-int st21nfcb_nci_se_io(struct nci_dev *ndev, u32 se_idx,
- u8 *apdu, size_t apdu_length,
- se_io_cb_t cb, void *cb_context);
-int st21nfcb_hci_load_session(struct nci_dev *ndev);
-void st21nfcb_hci_event_received(struct nci_dev *ndev, u8 pipe,
- u8 event, struct sk_buff *skb);
-void st21nfcb_hci_cmd_received(struct nci_dev *ndev, u8 pipe, u8 cmd,
- struct sk_buff *skb);
-
-
-#endif /* __LOCAL_ST21NFCB_NCI_H_ */
diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c
index aa6a333b2ead..85b4d86772d8 100644
--- a/drivers/nfc/trf7970a.c
+++ b/drivers/nfc/trf7970a.c
@@ -149,6 +149,7 @@
*/
#define TRF7970A_QUIRK_IRQ_STATUS_READ BIT(0)
#define TRF7970A_QUIRK_EN2_MUST_STAY_LOW BIT(1)
+#define TRF7970A_QUIRK_T5T_RMB_EXTRA_BYTE BIT(2)
/* Direct commands */
#define TRF7970A_CMD_IDLE 0x00
@@ -446,6 +447,7 @@ struct trf7970a {
u8 md_rf_tech;
u8 tx_cmd;
bool issue_eof;
+ bool adjust_resp_len;
int en2_gpio;
int en_gpio;
struct mutex lock;
@@ -626,6 +628,11 @@ static void trf7970a_send_upstream(struct trf7970a *trf)
trf->aborting = false;
}
+ if (trf->adjust_resp_len) {
+ skb_trim(trf->rx_skb, trf->rx_skb->len - 1);
+ trf->adjust_resp_len = false;
+ }
+
trf->cb(trf->ddev, trf->cb_arg, trf->rx_skb);
trf->rx_skb = NULL;
@@ -1429,10 +1436,15 @@ static int trf7970a_per_cmd_config(struct trf7970a *trf, struct sk_buff *skb)
trf->iso_ctrl = iso_ctrl;
}
- if ((trf->framing == NFC_DIGITAL_FRAMING_ISO15693_T5T) &&
- trf7970a_is_iso15693_write_or_lock(req[1]) &&
- (req[0] & ISO15693_REQ_FLAG_OPTION))
- trf->issue_eof = true;
+ if (trf->framing == NFC_DIGITAL_FRAMING_ISO15693_T5T) {
+ if (trf7970a_is_iso15693_write_or_lock(req[1]) &&
+ (req[0] & ISO15693_REQ_FLAG_OPTION))
+ trf->issue_eof = true;
+ else if ((trf->quirks &
+ TRF7970A_QUIRK_T5T_RMB_EXTRA_BYTE) &&
+ (req[1] == ISO15693_CMD_READ_MULTIPLE_BLOCK))
+ trf->adjust_resp_len = true;
+ }
}
return 0;
@@ -1992,6 +2004,9 @@ static int trf7970a_probe(struct spi_device *spi)
return ret;
}
+ if (of_property_read_bool(np, "t5t-rmb-extra-byte-quirk"))
+ trf->quirks |= TRF7970A_QUIRK_T5T_RMB_EXTRA_BYTE;
+
if (of_property_read_bool(np, "irq-status-read-quirk"))
trf->quirks |= TRF7970A_QUIRK_IRQ_STATUS_READ;