All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 00/35] Few fixes and st21nfca/st-nci vendor_cmds support
@ 2015-10-26  6:49 Christophe Ricard
  2015-10-26  6:49 ` [PATCH v3 04/35] nfc: st-nci: Fix incorrect spi buffer size Christophe Ricard
                   ` (15 more replies)
  0 siblings, 16 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:49 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe-h.ricard-qxv4g6HH51o,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Hi Samuel,

Please find in the following patchset severals fixes as well as vendor_cmds support
for st21nfca and st-nci.
vendor_cmds includes production test, trimmings & firmware update commands.

v3:
- Fix st21nfca vendor_cmds by exporting nfc_llc_start/stop
- Remove #include "st21nfca_vendor_cmds.h" in vendor_cmds as this one does not exist.

v2:
- Propose a more elegant way to switch between NFC target mode (SLEEP, IDLE).
- Remove st21nfca_ and st-nci_ file name prefix.
- Merge st21nfca_xxx.h headers into st21nfca.h. Same for st-nci_xxx.h

Best Regards
Christophe

Christophe Ricard (35):
  nfc: st-nci: Align st-nci driver with other nfc driver
  nfc: st-nci: include st-nci.h instead of ndlc.h
  nfc: st21nfca: Align st21nfca driver with other nfc driver
  nfc: st-nci: Fix incorrect spi buffer size
  nfc: nci: Fix incorrect data chaining when sending data
  nfc: nci: Fix improper management of HCI return code
  nfc: nci: extract pipe value using NCI_HCP_MSG_GET_PIPE
  nfc: nci: add nci_hci_clear_all_pipes functions
  nfc: nci: Add a call to nci_hci_clear_all_pipes at HCI initial
    activation.
  nfc: nci: add capability to create pipe on specific gate in
    nci_hci_connect_gate
  nfc: st-nci: Remove ndev->hci_dev->init_data.gates initialization in
    load_session
  nfc: st21nfca: Remove hdev->init_data.gates initialization in
    load_session
  nfc: st-nci: Open NCI_HCI_LINK_MGMT_PIPE
  nfc: st21nfca: Open NFC_HCI_LINK_MGMT_PIPE
  nfc: st-nci: Keep st_nci_gates unchanged in load_session
  nfc: st21nfca: Keep st21nfca_gates unchanged in load_session
  nfc: st-nci: initialize gate_count in st_nci_hci_network_init
  nfc: st-nci: Add support for NCI_HCI_IDENTITY_MGMT_GATE
  nfc: st-nci: Change st_nci_gates offset when looking for a pipe in the
    table
  nfc: st21nfca: Change st21nfca_gates offset when looking for a pipe in
    the table
  nfc: st-nci: Add support for proprietary commands for factory tests
  nfc: st-nci: Add error messages when an unexpected HCI event occurs
  nfc: netlink: Add missing NFC_ATTR comments
  nfc: st-nci: Add ese-present/uicc-present dts properties
  nfc: st-nci: Increase waiting time between 2 secure element activation
  nfc: st-nci: Fix host_list verification after secure element
    activation
  nfc: st21nfca: Fix host_list verification after secure element
    activation
  nfc: netlink: Add mode parameter to deactivate_target functions
  nfc: st-nci: Add few code style fixes
  nfc: st21nfca: Add few code style fixes
  nfc: st21nfca: Add support for proprietary commands for factory tests
  nfc: st21nfca: Add error messages when an unexpected HCI event occurs
  nfc: st-nci: Make sure irq is not already active when powering the
    device
  nfc: st-nci: remove duplicated skb dump
  nfc: st-nci: Replace st21nfcb by st_nci in makefile

 .../devicetree/bindings/net/nfc/st-nci-i2c.txt     |    7 +
 .../devicetree/bindings/net/nfc/st-nci-spi.txt     |    9 +-
 drivers/nfc/st-nci/Makefile                        |    4 +-
 drivers/nfc/st-nci/core.c                          |   18 +-
 drivers/nfc/st-nci/i2c.c                           |   35 +-
 drivers/nfc/st-nci/ndlc.c                          |    7 +-
 drivers/nfc/st-nci/ndlc.h                          |    5 +-
 drivers/nfc/st-nci/se.c                            |  166 ++-
 drivers/nfc/st-nci/se.h                            |   61 --
 drivers/nfc/st-nci/spi.c                           |   37 +-
 drivers/nfc/st-nci/st-nci.h                        |  117 ++-
 drivers/nfc/st-nci/vendor_cmds.c                   |  516 ++++++++++
 drivers/nfc/st21nfca/Makefile                      |    2 +-
 drivers/nfc/st21nfca/core.c                        | 1056 +++++++++++++++++++
 drivers/nfc/st21nfca/dep.c                         |  689 +++++++++++++
 drivers/nfc/st21nfca/i2c.c                         |    1 +
 drivers/nfc/st21nfca/se.c                          |  428 ++++++++
 drivers/nfc/st21nfca/st21nfca.c                    | 1064 --------------------
 drivers/nfc/st21nfca/st21nfca.h                    |  148 ++-
 drivers/nfc/st21nfca/st21nfca_dep.c                |  689 -------------
 drivers/nfc/st21nfca/st21nfca_dep.h                |   43 -
 drivers/nfc/st21nfca/st21nfca_se.c                 |  420 --------
 drivers/nfc/st21nfca/st21nfca_se.h                 |   63 --
 drivers/nfc/st21nfca/vendor_cmds.c                 |  369 +++++++
 include/linux/platform_data/st-nci.h               |    2 +
 include/net/nfc/nci_core.h                         |    3 +
 include/net/nfc/nfc.h                              |    2 +-
 include/uapi/linux/nfc.h                           |    2 +
 net/nfc/core.c                                     |    4 +-
 net/nfc/digital_core.c                             |    3 +-
 net/nfc/hci/core.c                                 |    3 +-
 net/nfc/hci/llc.c                                  |    2 +
 net/nfc/nci/core.c                                 |   15 +-
 net/nfc/nci/hci.c                                  |  159 ++-
 net/nfc/netlink.c                                  |    2 +-
 net/nfc/nfc.h                                      |    5 +-
 net/nfc/rawsock.c                                  |    3 +-
 37 files changed, 3664 insertions(+), 2495 deletions(-)
 delete mode 100644 drivers/nfc/st-nci/se.h
 create mode 100644 drivers/nfc/st-nci/vendor_cmds.c
 create mode 100644 drivers/nfc/st21nfca/core.c
 create mode 100644 drivers/nfc/st21nfca/dep.c
 create mode 100644 drivers/nfc/st21nfca/se.c
 delete mode 100644 drivers/nfc/st21nfca/st21nfca.c
 delete mode 100644 drivers/nfc/st21nfca/st21nfca_dep.c
 delete mode 100644 drivers/nfc/st21nfca/st21nfca_dep.h
 delete mode 100644 drivers/nfc/st21nfca/st21nfca_se.c
 delete mode 100644 drivers/nfc/st21nfca/st21nfca_se.h
 create mode 100644 drivers/nfc/st21nfca/vendor_cmds.c

-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 38+ messages in thread

* [PATCH v3 01/35] nfc: st-nci: Align st-nci driver with other nfc driver
       [not found] ` <1445842215-28403-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
@ 2015-10-26  6:49   ` Christophe Ricard
  2015-10-26  6:49   ` [PATCH v3 02/35] nfc: st-nci: include st-nci.h instead of ndlc.h Christophe Ricard
                     ` (18 subsequent siblings)
  19 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:49 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe-h.ricard-qxv4g6HH51o,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Align st-nci driver with or nfc driver:
- Remove st-nci_ prefix
- Merge se.h in st-nci.h

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 drivers/nfc/st-nci/core.c   |  1 -
 drivers/nfc/st-nci/se.c     |  1 -
 drivers/nfc/st-nci/se.h     | 61 ---------------------------------------------
 drivers/nfc/st-nci/st-nci.h | 40 ++++++++++++++++++++++++++++-
 4 files changed, 39 insertions(+), 64 deletions(-)
 delete mode 100644 drivers/nfc/st-nci/se.h

diff --git a/drivers/nfc/st-nci/core.c b/drivers/nfc/st-nci/core.c
index c419d39..96997e6 100644
--- a/drivers/nfc/st-nci/core.c
+++ b/drivers/nfc/st-nci/core.c
@@ -24,7 +24,6 @@
 #include <linux/delay.h>
 
 #include "st-nci.h"
-#include "st-nci_se.h"
 
 #define DRIVER_DESC "NCI NFC driver for ST_NCI"
 
diff --git a/drivers/nfc/st-nci/se.c b/drivers/nfc/st-nci/se.c
index c742ef6..4acb945 100644
--- a/drivers/nfc/st-nci/se.c
+++ b/drivers/nfc/st-nci/se.c
@@ -23,7 +23,6 @@
 #include <net/nfc/nci_core.h>
 
 #include "st-nci.h"
-#include "st-nci_se.h"
 
 struct st_nci_pipe_info {
 	u8 pipe_state;
diff --git a/drivers/nfc/st-nci/se.h b/drivers/nfc/st-nci/se.h
deleted file mode 100644
index ea66e87..0000000
--- a/drivers/nfc/st-nci/se.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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/st-nci/st-nci.h b/drivers/nfc/st-nci/st-nci.h
index 850a239..5d3f4d9 100644
--- a/drivers/nfc/st-nci/st-nci.h
+++ b/drivers/nfc/st-nci/st-nci.h
@@ -19,7 +19,6 @@
 #ifndef __LOCAL_ST_NCI_H_
 #define __LOCAL_ST_NCI_H_
 
-#include "st-nci_se.h"
 #include "ndlc.h"
 
 /* Define private flags: */
@@ -28,6 +27,13 @@
 #define ST_NCI_CORE_PROP                0x01
 #define ST_NCI_SET_NFC_MODE             0x02
 
+/*
+ * 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 nci_mode_set_cmd {
 	u8 cmd_type;
 	u8 mode;
@@ -37,6 +43,23 @@ struct nci_mode_set_rsp {
 	u8 status;
 } __packed;
 
+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;
+};
+
 struct st_nci_info {
 	struct llt_ndlc *ndlc;
 	unsigned long flags;
@@ -47,4 +70,19 @@ void st_nci_remove(struct nci_dev *ndev);
 int st_nci_probe(struct llt_ndlc *ndlc, int phy_headroom,
 		int phy_tailroom);
 
+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_H_ */
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 02/35] nfc: st-nci: include st-nci.h instead of ndlc.h
       [not found] ` <1445842215-28403-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
  2015-10-26  6:49   ` [PATCH v3 01/35] nfc: st-nci: Align st-nci driver with other nfc driver Christophe Ricard
@ 2015-10-26  6:49   ` Christophe Ricard
  2015-10-26  6:49   ` [PATCH v3 03/35] nfc: st21nfca: Align st21nfca driver with other nfc driver Christophe Ricard
                     ` (17 subsequent siblings)
  19 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:49 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe-h.ricard-qxv4g6HH51o,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	devicetree-u79uwXL29TY76Z2rM5mHXA

st-nci.h already include ndlc.h.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 drivers/nfc/st-nci/i2c.c  | 2 +-
 drivers/nfc/st-nci/ndlc.c | 1 -
 drivers/nfc/st-nci/spi.c  | 2 +-
 3 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/nfc/st-nci/i2c.c b/drivers/nfc/st-nci/i2c.c
index 707ed2e..02e585f 100644
--- a/drivers/nfc/st-nci/i2c.c
+++ b/drivers/nfc/st-nci/i2c.c
@@ -27,7 +27,7 @@
 #include <linux/nfc.h>
 #include <linux/platform_data/st-nci.h>
 
-#include "ndlc.h"
+#include "st-nci.h"
 
 #define DRIVER_DESC "NCI NFC driver for ST_NCI"
 
diff --git a/drivers/nfc/st-nci/ndlc.c b/drivers/nfc/st-nci/ndlc.c
index d2cf84e..fb50007 100644
--- a/drivers/nfc/st-nci/ndlc.c
+++ b/drivers/nfc/st-nci/ndlc.c
@@ -19,7 +19,6 @@
 #include <linux/sched.h>
 #include <net/nfc/nci_core.h>
 
-#include "ndlc.h"
 #include "st-nci.h"
 
 #define NDLC_TIMER_T1		100
diff --git a/drivers/nfc/st-nci/spi.c b/drivers/nfc/st-nci/spi.c
index 598a58c..9a39871 100644
--- a/drivers/nfc/st-nci/spi.c
+++ b/drivers/nfc/st-nci/spi.c
@@ -27,7 +27,7 @@
 #include <linux/nfc.h>
 #include <linux/platform_data/st-nci.h>
 
-#include "ndlc.h"
+#include "st-nci.h"
 
 #define DRIVER_DESC "NCI NFC driver for ST_NCI"
 
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 03/35] nfc: st21nfca: Align st21nfca driver with other nfc driver
       [not found] ` <1445842215-28403-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
  2015-10-26  6:49   ` [PATCH v3 01/35] nfc: st-nci: Align st-nci driver with other nfc driver Christophe Ricard
  2015-10-26  6:49   ` [PATCH v3 02/35] nfc: st-nci: include st-nci.h instead of ndlc.h Christophe Ricard
@ 2015-10-26  6:49   ` Christophe Ricard
  2015-10-26  6:49   ` [PATCH v3 08/35] nfc: nci: add nci_hci_clear_all_pipes functions Christophe Ricard
                     ` (16 subsequent siblings)
  19 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:49 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe-h.ricard-qxv4g6HH51o,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Align st21nfca driver with or nfc driver:
- Remove st21nfca_ prefix
- Merge st21nfca_se.h, st21nfca_dep.h in st21nfca.h

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 drivers/nfc/st21nfca/Makefile       |    2 +-
 drivers/nfc/st21nfca/core.c         | 1062 ++++++++++++++++++++++++++++++++++
 drivers/nfc/st21nfca/dep.c          |  688 ++++++++++++++++++++++
 drivers/nfc/st21nfca/se.c           |  419 ++++++++++++++
 drivers/nfc/st21nfca/st21nfca.c     | 1064 -----------------------------------
 drivers/nfc/st21nfca/st21nfca.h     |   98 +++-
 drivers/nfc/st21nfca/st21nfca_dep.c |  689 -----------------------
 drivers/nfc/st21nfca/st21nfca_dep.h |   43 --
 drivers/nfc/st21nfca/st21nfca_se.c  |  420 --------------
 drivers/nfc/st21nfca/st21nfca_se.h  |   63 ---
 10 files changed, 2249 insertions(+), 2299 deletions(-)
 create mode 100644 drivers/nfc/st21nfca/core.c
 create mode 100644 drivers/nfc/st21nfca/dep.c
 create mode 100644 drivers/nfc/st21nfca/se.c
 delete mode 100644 drivers/nfc/st21nfca/st21nfca.c
 delete mode 100644 drivers/nfc/st21nfca/st21nfca_dep.c
 delete mode 100644 drivers/nfc/st21nfca/st21nfca_dep.h
 delete mode 100644 drivers/nfc/st21nfca/st21nfca_se.c
 delete mode 100644 drivers/nfc/st21nfca/st21nfca_se.h

diff --git a/drivers/nfc/st21nfca/Makefile b/drivers/nfc/st21nfca/Makefile
index 97edab4..82434c3 100644
--- a/drivers/nfc/st21nfca/Makefile
+++ b/drivers/nfc/st21nfca/Makefile
@@ -2,7 +2,7 @@
 # Makefile for ST21NFCA HCI based NFC driver
 #
 
-st21nfca_hci-objs = st21nfca.o st21nfca_dep.o st21nfca_se.o
+st21nfca_hci-objs = core.o dep.o se.o
 obj-$(CONFIG_NFC_ST21NFCA)     += st21nfca_hci.o
 
 st21nfca_i2c-objs  = i2c.o
diff --git a/drivers/nfc/st21nfca/core.c b/drivers/nfc/st21nfca/core.c
new file mode 100644
index 0000000..42f1974
--- /dev/null
+++ b/drivers/nfc/st21nfca/core.c
@@ -0,0 +1,1062 @@
+/*
+ * HCI 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/hci.h>
+#include <net/nfc/llc.h>
+
+#include "st21nfca.h"
+
+#define DRIVER_DESC "HCI NFC driver for ST21NFCA"
+
+#define FULL_VERSION_LEN 3
+
+/* Proprietary gates, events, commands and registers */
+
+/* Commands that apply to all RF readers */
+#define ST21NFCA_RF_READER_CMD_PRESENCE_CHECK	0x30
+
+#define ST21NFCA_RF_READER_ISO15693_GATE	0x12
+#define ST21NFCA_RF_READER_ISO15693_INVENTORY	0x01
+
+/*
+ * Reader gate for communication with contact-less cards using Type A
+ * protocol ISO14443-3 but not compliant with ISO14443-4
+ */
+#define ST21NFCA_RF_READER_14443_3_A_GATE	0x15
+#define ST21NFCA_RF_READER_14443_3_A_UID	0x02
+#define ST21NFCA_RF_READER_14443_3_A_ATQA	0x03
+#define ST21NFCA_RF_READER_14443_3_A_SAK	0x04
+
+#define ST21NFCA_RF_READER_F_DATARATE		0x01
+#define ST21NFCA_RF_READER_F_DATARATE_106	0x01
+#define ST21NFCA_RF_READER_F_DATARATE_212	0x02
+#define ST21NFCA_RF_READER_F_DATARATE_424	0x04
+#define ST21NFCA_RF_READER_F_POL_REQ		0x02
+#define ST21NFCA_RF_READER_F_POL_REQ_DEFAULT	0xffff0000
+#define ST21NFCA_RF_READER_F_NFCID2		0x03
+#define ST21NFCA_RF_READER_F_NFCID1		0x04
+
+#define ST21NFCA_RF_CARD_F_MODE			0x01
+#define ST21NFCA_RF_CARD_F_NFCID2_LIST		0x04
+#define ST21NFCA_RF_CARD_F_NFCID1		0x05
+#define ST21NFCA_RF_CARD_F_SENS_RES		0x06
+#define ST21NFCA_RF_CARD_F_SEL_RES		0x07
+#define ST21NFCA_RF_CARD_F_DATARATE		0x08
+#define ST21NFCA_RF_CARD_F_DATARATE_212_424	0x01
+
+#define ST21NFCA_DEVICE_MGNT_PIPE		0x02
+
+#define ST21NFCA_DM_GETINFO			0x13
+#define ST21NFCA_DM_GETINFO_PIPE_LIST		0x02
+#define ST21NFCA_DM_GETINFO_PIPE_INFO		0x01
+#define ST21NFCA_DM_PIPE_CREATED		0x02
+#define ST21NFCA_DM_PIPE_OPEN			0x04
+#define ST21NFCA_DM_RF_ACTIVE			0x80
+#define ST21NFCA_DM_DISCONNECT			0x30
+
+#define ST21NFCA_DM_IS_PIPE_OPEN(p) \
+	((p & 0x0f) == (ST21NFCA_DM_PIPE_CREATED | ST21NFCA_DM_PIPE_OPEN))
+
+#define ST21NFCA_NFC_MODE			0x03	/* NFC_MODE parameter*/
+
+#define ST21NFCA_EVT_HOT_PLUG			0x03
+#define ST21NFCA_EVT_HOT_PLUG_IS_INHIBITED(x) (x->data[0] & 0x80)
+
+#define ST21NFCA_SE_TO_PIPES			2000
+
+static DECLARE_BITMAP(dev_mask, ST21NFCA_NUM_DEVICES);
+
+static struct nfc_hci_gate st21nfca_gates[] = {
+	{NFC_HCI_ADMIN_GATE, NFC_HCI_ADMIN_PIPE},
+	{NFC_HCI_LOOPBACK_GATE, NFC_HCI_INVALID_PIPE},
+	{NFC_HCI_ID_MGMT_GATE, NFC_HCI_INVALID_PIPE},
+	{NFC_HCI_LINK_MGMT_GATE, NFC_HCI_LINK_MGMT_PIPE},
+	{NFC_HCI_RF_READER_B_GATE, NFC_HCI_INVALID_PIPE},
+	{NFC_HCI_RF_READER_A_GATE, NFC_HCI_INVALID_PIPE},
+	{ST21NFCA_DEVICE_MGNT_GATE, ST21NFCA_DEVICE_MGNT_PIPE},
+	{ST21NFCA_RF_READER_F_GATE, NFC_HCI_INVALID_PIPE},
+	{ST21NFCA_RF_READER_14443_3_A_GATE, NFC_HCI_INVALID_PIPE},
+	{ST21NFCA_RF_READER_ISO15693_GATE, NFC_HCI_INVALID_PIPE},
+	{ST21NFCA_RF_CARD_F_GATE, NFC_HCI_INVALID_PIPE},
+
+	/* Secure element pipes are created by secure element host */
+	{ST21NFCA_CONNECTIVITY_GATE, NFC_HCI_DO_NOT_CREATE_PIPE},
+	{ST21NFCA_APDU_READER_GATE, NFC_HCI_DO_NOT_CREATE_PIPE},
+};
+
+struct st21nfca_pipe_info {
+	u8 pipe_state;
+	u8 src_host_id;
+	u8 src_gate_id;
+	u8 dst_host_id;
+	u8 dst_gate_id;
+} __packed;
+
+/* Largest headroom needed for outgoing custom commands */
+#define ST21NFCA_CMDS_HEADROOM  7
+
+static int st21nfca_hci_load_session(struct nfc_hci_dev *hdev)
+{
+	int i, j, r;
+	struct sk_buff *skb_pipe_list, *skb_pipe_info;
+	struct st21nfca_pipe_info *info;
+
+	u8 pipe_list[] = { ST21NFCA_DM_GETINFO_PIPE_LIST,
+		NFC_HCI_TERMINAL_HOST_ID
+	};
+	u8 pipe_info[] = { ST21NFCA_DM_GETINFO_PIPE_INFO,
+		NFC_HCI_TERMINAL_HOST_ID, 0
+	};
+
+	/* On ST21NFCA device pipes number are dynamics
+	 * A maximum of 16 pipes can be created at the same time
+	 * 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 ST21NFCA is to:
+	 * - get a pipe list for each host.
+	 * (eg: NFC_HCI_HOST_CONTROLLER_ID for now).
+	 * (TODO Later on UICC HOST and eSE HOST)
+	 * - get pipe information
+	 * - match retrieved pipe list in st21nfca_gates
+	 * ST21NFCA_DEVICE_MGNT_GATE is a proprietary gate
+	 * with ST21NFCA_DEVICE_MGNT_PIPE.
+	 * Pipe can be closed and need to be open.
+	 */
+	r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID,
+				ST21NFCA_DEVICE_MGNT_GATE,
+				ST21NFCA_DEVICE_MGNT_PIPE);
+	if (r < 0)
+		return r;
+
+	/* Get pipe list */
+	r = nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE,
+			ST21NFCA_DM_GETINFO, pipe_list, sizeof(pipe_list),
+			&skb_pipe_list);
+	if (r < 0)
+		return r;
+
+	/* Complete the existing gate_pipe table */
+	for (i = 0; i < skb_pipe_list->len; i++) {
+		pipe_info[2] = skb_pipe_list->data[i];
+		r = nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE,
+					ST21NFCA_DM_GETINFO, pipe_info,
+					sizeof(pipe_info), &skb_pipe_info);
+
+		if (r)
+			continue;
+
+		/*
+		 * Match pipe ID and gate ID
+		 * Output format from ST21NFC_DM_GETINFO is:
+		 * - pipe state (1byte)
+		 * - source hid (1byte)
+		 * - source gid (1byte)
+		 * - destination hid (1byte)
+		 * - destination gid (1byte)
+		 */
+		info = (struct st21nfca_pipe_info *) skb_pipe_info->data;
+		if (info->dst_gate_id == ST21NFCA_APDU_READER_GATE &&
+			info->src_host_id != ST21NFCA_ESE_HOST_ID) {
+			pr_err("Unexpected apdu_reader pipe on host %x\n",
+				info->src_host_id);
+			kfree_skb(skb_pipe_info);
+			continue;
+		}
+
+		for (j = 0; (j < ARRAY_SIZE(st21nfca_gates)) &&
+			(st21nfca_gates[j].gate != info->dst_gate_id) ; j++)
+			;
+
+		if (j < ARRAY_SIZE(st21nfca_gates) &&
+			st21nfca_gates[j].gate == info->dst_gate_id &&
+			ST21NFCA_DM_IS_PIPE_OPEN(info->pipe_state)) {
+			st21nfca_gates[j].pipe = pipe_info[2];
+
+			hdev->gate2pipe[st21nfca_gates[j].gate] =
+							st21nfca_gates[j].pipe;
+			hdev->pipes[st21nfca_gates[j].pipe].gate =
+							st21nfca_gates[j].gate;
+			hdev->pipes[st21nfca_gates[j].pipe].dest_host =
+							info->src_host_id;
+		}
+		kfree_skb(skb_pipe_info);
+	}
+
+	/*
+	 * 3 gates have a well known pipe ID.
+	 * They will never appear in the pipe list
+	 */
+	if (skb_pipe_list->len + 3 < ARRAY_SIZE(st21nfca_gates)) {
+		for (i = skb_pipe_list->len + 3;
+				i < ARRAY_SIZE(st21nfca_gates) - 2; i++) {
+			r = nfc_hci_connect_gate(hdev,
+					NFC_HCI_HOST_CONTROLLER_ID,
+					st21nfca_gates[i].gate,
+					st21nfca_gates[i].pipe);
+			if (r < 0)
+				goto free_list;
+		}
+	}
+
+	memcpy(hdev->init_data.gates, st21nfca_gates, sizeof(st21nfca_gates));
+free_list:
+	kfree_skb(skb_pipe_list);
+	return r;
+}
+
+static int st21nfca_hci_open(struct nfc_hci_dev *hdev)
+{
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+	int r;
+
+	mutex_lock(&info->info_lock);
+
+	if (info->state != ST21NFCA_ST_COLD) {
+		r = -EBUSY;
+		goto out;
+	}
+
+	r = info->phy_ops->enable(info->phy_id);
+
+	if (r == 0)
+		info->state = ST21NFCA_ST_READY;
+
+out:
+	mutex_unlock(&info->info_lock);
+	return r;
+}
+
+static void st21nfca_hci_close(struct nfc_hci_dev *hdev)
+{
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	mutex_lock(&info->info_lock);
+
+	if (info->state == ST21NFCA_ST_COLD)
+		goto out;
+
+	info->phy_ops->disable(info->phy_id);
+	info->state = ST21NFCA_ST_COLD;
+
+out:
+	mutex_unlock(&info->info_lock);
+}
+
+static int st21nfca_hci_ready(struct nfc_hci_dev *hdev)
+{
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+	struct sk_buff *skb;
+
+	u8 param;
+	u8 white_list[2];
+	int wl_size = 0;
+	int r;
+
+	if (info->se_status->is_ese_present &&
+		info->se_status->is_uicc_present) {
+		white_list[wl_size++] = NFC_HCI_UICC_HOST_ID;
+		white_list[wl_size++] = ST21NFCA_ESE_HOST_ID;
+	} else if (!info->se_status->is_ese_present &&
+			 info->se_status->is_uicc_present) {
+		white_list[wl_size++] = NFC_HCI_UICC_HOST_ID;
+	} else if (info->se_status->is_ese_present &&
+			!info->se_status->is_uicc_present) {
+		white_list[wl_size++] = ST21NFCA_ESE_HOST_ID;
+	}
+
+	if (wl_size) {
+		r = nfc_hci_set_param(hdev, NFC_HCI_ADMIN_GATE,
+					NFC_HCI_ADMIN_WHITELIST,
+					(u8 *) &white_list, wl_size);
+		if (r < 0)
+			return r;
+	}
+
+	/* Set NFC_MODE in device management gate to enable */
+	r = nfc_hci_get_param(hdev, ST21NFCA_DEVICE_MGNT_GATE,
+			      ST21NFCA_NFC_MODE, &skb);
+	if (r < 0)
+		return r;
+
+	param = skb->data[0];
+	kfree_skb(skb);
+	if (param == 0) {
+		param = 1;
+
+		r = nfc_hci_set_param(hdev, ST21NFCA_DEVICE_MGNT_GATE,
+					ST21NFCA_NFC_MODE, &param, 1);
+		if (r < 0)
+			return r;
+	}
+
+	r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,
+			       NFC_HCI_EVT_END_OPERATION, NULL, 0);
+	if (r < 0)
+		return r;
+
+	r = nfc_hci_get_param(hdev, NFC_HCI_ID_MGMT_GATE,
+			      NFC_HCI_ID_MGMT_VERSION_SW, &skb);
+	if (r < 0)
+		return r;
+
+	if (skb->len != FULL_VERSION_LEN) {
+		kfree_skb(skb);
+		return -EINVAL;
+	}
+
+	print_hex_dump(KERN_DEBUG, "FULL VERSION SOFTWARE INFO: ",
+		       DUMP_PREFIX_NONE, 16, 1,
+		       skb->data, FULL_VERSION_LEN, false);
+
+	kfree_skb(skb);
+
+	return 0;
+}
+
+static int st21nfca_hci_xmit(struct nfc_hci_dev *hdev, struct sk_buff *skb)
+{
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	return info->phy_ops->write(info->phy_id, skb);
+}
+
+static int st21nfca_hci_start_poll(struct nfc_hci_dev *hdev,
+				   u32 im_protocols, u32 tm_protocols)
+{
+	int r;
+	u32 pol_req;
+	u8 param[19];
+	struct sk_buff *datarate_skb;
+
+	pr_info(DRIVER_DESC ": %s protocols 0x%x 0x%x\n",
+		__func__, im_protocols, tm_protocols);
+
+	r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,
+			       NFC_HCI_EVT_END_OPERATION, NULL, 0);
+	if (r < 0)
+		return r;
+	if (im_protocols) {
+		/*
+		 * enable polling according to im_protocols & tm_protocols
+		 * - CLOSE pipe according to im_protocols & tm_protocols
+		 */
+		if ((NFC_HCI_RF_READER_B_GATE & im_protocols) == 0) {
+			r = nfc_hci_disconnect_gate(hdev,
+					NFC_HCI_RF_READER_B_GATE);
+			if (r < 0)
+				return r;
+		}
+
+		if ((NFC_HCI_RF_READER_A_GATE & im_protocols) == 0) {
+			r = nfc_hci_disconnect_gate(hdev,
+					NFC_HCI_RF_READER_A_GATE);
+			if (r < 0)
+				return r;
+		}
+
+		if ((ST21NFCA_RF_READER_F_GATE & im_protocols) == 0) {
+			r = nfc_hci_disconnect_gate(hdev,
+					ST21NFCA_RF_READER_F_GATE);
+			if (r < 0)
+				return r;
+		} else {
+			hdev->gb = nfc_get_local_general_bytes(hdev->ndev,
+							       &hdev->gb_len);
+
+			if (hdev->gb == NULL || hdev->gb_len == 0) {
+				im_protocols &= ~NFC_PROTO_NFC_DEP_MASK;
+				tm_protocols &= ~NFC_PROTO_NFC_DEP_MASK;
+			}
+
+			param[0] = ST21NFCA_RF_READER_F_DATARATE_106 |
+			    ST21NFCA_RF_READER_F_DATARATE_212 |
+			    ST21NFCA_RF_READER_F_DATARATE_424;
+			r = nfc_hci_set_param(hdev, ST21NFCA_RF_READER_F_GATE,
+					      ST21NFCA_RF_READER_F_DATARATE,
+					      param, 1);
+			if (r < 0)
+				return r;
+
+			pol_req = be32_to_cpu((__force __be32)
+					ST21NFCA_RF_READER_F_POL_REQ_DEFAULT);
+			r = nfc_hci_set_param(hdev, ST21NFCA_RF_READER_F_GATE,
+					      ST21NFCA_RF_READER_F_POL_REQ,
+					      (u8 *) &pol_req, 4);
+			if (r < 0)
+				return r;
+		}
+
+		if ((ST21NFCA_RF_READER_14443_3_A_GATE & im_protocols) == 0) {
+			r = nfc_hci_disconnect_gate(hdev,
+					ST21NFCA_RF_READER_14443_3_A_GATE);
+			if (r < 0)
+				return r;
+		}
+
+		if ((ST21NFCA_RF_READER_ISO15693_GATE & im_protocols) == 0) {
+			r = nfc_hci_disconnect_gate(hdev,
+					ST21NFCA_RF_READER_ISO15693_GATE);
+			if (r < 0)
+				return r;
+		}
+
+		r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,
+				       NFC_HCI_EVT_READER_REQUESTED, NULL, 0);
+		if (r < 0)
+			nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,
+					   NFC_HCI_EVT_END_OPERATION, NULL, 0);
+	}
+
+	if (tm_protocols & NFC_PROTO_NFC_DEP_MASK) {
+		r = nfc_hci_get_param(hdev, ST21NFCA_RF_CARD_F_GATE,
+				      ST21NFCA_RF_CARD_F_DATARATE,
+				      &datarate_skb);
+		if (r < 0)
+			return r;
+
+		/* Configure the maximum supported datarate to 424Kbps */
+		if (datarate_skb->len > 0 &&
+		    datarate_skb->data[0] !=
+		    ST21NFCA_RF_CARD_F_DATARATE_212_424) {
+			param[0] = ST21NFCA_RF_CARD_F_DATARATE_212_424;
+			r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE,
+					      ST21NFCA_RF_CARD_F_DATARATE,
+					      param, 1);
+			if (r < 0) {
+				kfree_skb(datarate_skb);
+				return r;
+			}
+		}
+		kfree_skb(datarate_skb);
+
+		/*
+		 * Configure sens_res
+		 *
+		 * NFC Forum Digital Spec Table 7:
+		 * NFCID1 size: triple (10 bytes)
+		 */
+		param[0] = 0x00;
+		param[1] = 0x08;
+		r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE,
+				      ST21NFCA_RF_CARD_F_SENS_RES, param, 2);
+		if (r < 0)
+			return r;
+
+		/*
+		 * Configure sel_res
+		 *
+		 * NFC Forum Digistal Spec Table 17:
+		 * b3 set to 0b (value b7-b6):
+		 * - 10b: Configured for NFC-DEP Protocol
+		 */
+		param[0] = 0x40;
+		r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE,
+				      ST21NFCA_RF_CARD_F_SEL_RES, param, 1);
+		if (r < 0)
+			return r;
+
+		/* Configure NFCID1 Random uid */
+		r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE,
+				      ST21NFCA_RF_CARD_F_NFCID1, NULL, 0);
+		if (r < 0)
+			return r;
+
+		/* Configure NFCID2_LIST */
+		/* System Code */
+		param[0] = 0x00;
+		param[1] = 0x00;
+		/* NFCID2 */
+		param[2] = 0x01;
+		param[3] = 0xfe;
+		param[4] = 'S';
+		param[5] = 'T';
+		param[6] = 'M';
+		param[7] = 'i';
+		param[8] = 'c';
+		param[9] = 'r';
+		/* 8 byte Pad bytes used for polling respone frame */
+
+		/*
+		 * Configuration byte:
+		 * - bit 0: define the default NFCID2 entry used when the
+		 * system code is equal to 'FFFF'
+		 * - bit 1: use a random value for lowest 6 bytes of
+		 * NFCID2 value
+		 * - bit 2: ignore polling request frame if request code
+		 * is equal to '01'
+		 * - Other bits are RFU
+		 */
+		param[18] = 0x01;
+		r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE,
+				      ST21NFCA_RF_CARD_F_NFCID2_LIST, param,
+				      19);
+		if (r < 0)
+			return r;
+
+		param[0] = 0x02;
+		r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE,
+				      ST21NFCA_RF_CARD_F_MODE, param, 1);
+	}
+
+	return r;
+}
+
+static void st21nfca_hci_stop_poll(struct nfc_hci_dev *hdev)
+{
+	nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE,
+			ST21NFCA_DM_DISCONNECT, NULL, 0, NULL);
+}
+
+static int st21nfca_get_iso14443_3_atqa(struct nfc_hci_dev *hdev, u16 *atqa)
+{
+	int r;
+	struct sk_buff *atqa_skb = NULL;
+
+	r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_14443_3_A_GATE,
+			      ST21NFCA_RF_READER_14443_3_A_ATQA, &atqa_skb);
+	if (r < 0)
+		goto exit;
+
+	if (atqa_skb->len != 2) {
+		r = -EPROTO;
+		goto exit;
+	}
+
+	*atqa = be16_to_cpu(*(__be16 *) atqa_skb->data);
+
+exit:
+	kfree_skb(atqa_skb);
+	return r;
+}
+
+static int st21nfca_get_iso14443_3_sak(struct nfc_hci_dev *hdev, u8 *sak)
+{
+	int r;
+	struct sk_buff *sak_skb = NULL;
+
+	r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_14443_3_A_GATE,
+			      ST21NFCA_RF_READER_14443_3_A_SAK, &sak_skb);
+	if (r < 0)
+		goto exit;
+
+	if (sak_skb->len != 1) {
+		r = -EPROTO;
+		goto exit;
+	}
+
+	*sak = sak_skb->data[0];
+
+exit:
+	kfree_skb(sak_skb);
+	return r;
+}
+
+static int st21nfca_get_iso14443_3_uid(struct nfc_hci_dev *hdev, u8 *uid,
+				       int *len)
+{
+	int r;
+	struct sk_buff *uid_skb = NULL;
+
+	r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_14443_3_A_GATE,
+			      ST21NFCA_RF_READER_14443_3_A_UID, &uid_skb);
+	if (r < 0)
+		goto exit;
+
+	if (uid_skb->len == 0 || uid_skb->len > NFC_NFCID1_MAXSIZE) {
+		r = -EPROTO;
+		goto exit;
+	}
+
+	memcpy(uid, uid_skb->data, uid_skb->len);
+	*len = uid_skb->len;
+exit:
+	kfree_skb(uid_skb);
+	return r;
+}
+
+static int st21nfca_get_iso15693_inventory(struct nfc_hci_dev *hdev,
+					   struct nfc_target *target)
+{
+	int r;
+	struct sk_buff *inventory_skb = NULL;
+
+	r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_ISO15693_GATE,
+			      ST21NFCA_RF_READER_ISO15693_INVENTORY,
+			      &inventory_skb);
+	if (r < 0)
+		goto exit;
+
+	skb_pull(inventory_skb, 2);
+
+	if (inventory_skb->len == 0 ||
+	    inventory_skb->len > NFC_ISO15693_UID_MAXSIZE) {
+		r = -EPROTO;
+		goto exit;
+	}
+
+	memcpy(target->iso15693_uid, inventory_skb->data, inventory_skb->len);
+	target->iso15693_dsfid	= inventory_skb->data[1];
+	target->is_iso15693 = 1;
+exit:
+	kfree_skb(inventory_skb);
+	return r;
+}
+
+static int st21nfca_hci_dep_link_up(struct nfc_hci_dev *hdev,
+				    struct nfc_target *target, u8 comm_mode,
+				    u8 *gb, size_t gb_len)
+{
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	info->dep_info.idx = target->idx;
+	return st21nfca_im_send_atr_req(hdev, gb, gb_len);
+}
+
+static int st21nfca_hci_dep_link_down(struct nfc_hci_dev *hdev)
+{
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	info->state = ST21NFCA_ST_READY;
+
+	return nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE,
+				ST21NFCA_DM_DISCONNECT, NULL, 0, NULL);
+}
+
+static int st21nfca_hci_target_from_gate(struct nfc_hci_dev *hdev, u8 gate,
+					 struct nfc_target *target)
+{
+	int r, len;
+	u16 atqa;
+	u8 sak;
+	u8 uid[NFC_NFCID1_MAXSIZE];
+
+	switch (gate) {
+	case ST21NFCA_RF_READER_F_GATE:
+		target->supported_protocols = NFC_PROTO_FELICA_MASK;
+		break;
+	case ST21NFCA_RF_READER_14443_3_A_GATE:
+		/* ISO14443-3 type 1 or 2 tags */
+		r = st21nfca_get_iso14443_3_atqa(hdev, &atqa);
+		if (r < 0)
+			return r;
+		if (atqa == 0x000c) {
+			target->supported_protocols = NFC_PROTO_JEWEL_MASK;
+			target->sens_res = 0x0c00;
+		} else {
+			r = st21nfca_get_iso14443_3_sak(hdev, &sak);
+			if (r < 0)
+				return r;
+
+			r = st21nfca_get_iso14443_3_uid(hdev, uid, &len);
+			if (r < 0)
+				return r;
+
+			target->supported_protocols =
+			    nfc_hci_sak_to_protocol(sak);
+			if (target->supported_protocols == 0xffffffff)
+				return -EPROTO;
+
+			target->sens_res = atqa;
+			target->sel_res = sak;
+			memcpy(target->nfcid1, uid, len);
+			target->nfcid1_len = len;
+		}
+
+		break;
+	case ST21NFCA_RF_READER_ISO15693_GATE:
+		target->supported_protocols = NFC_PROTO_ISO15693_MASK;
+		r = st21nfca_get_iso15693_inventory(hdev, target);
+		if (r < 0)
+			return r;
+		break;
+	default:
+		return -EPROTO;
+	}
+
+	return 0;
+}
+
+static int st21nfca_hci_complete_target_discovered(struct nfc_hci_dev *hdev,
+						u8 gate,
+						struct nfc_target *target)
+{
+	int r;
+	struct sk_buff *nfcid_skb = NULL;
+
+	if (gate == ST21NFCA_RF_READER_F_GATE) {
+		r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_F_GATE,
+				ST21NFCA_RF_READER_F_NFCID2, &nfcid_skb);
+		if (r < 0)
+			goto exit;
+
+		if (nfcid_skb->len > NFC_SENSF_RES_MAXSIZE) {
+			r = -EPROTO;
+			goto exit;
+		}
+
+		/*
+		 * - After the recepton of polling response for type F frame
+		 * at 212 or 424 Kbit/s, NFCID2 registry parameters will be
+		 * updated.
+		 * - After the reception of SEL_RES with NFCIP-1 compliant bit
+		 * set for type A frame NFCID1 will be updated
+		 */
+		if (nfcid_skb->len > 0) {
+			/* P2P in type F */
+			memcpy(target->sensf_res, nfcid_skb->data,
+				nfcid_skb->len);
+			target->sensf_res_len = nfcid_skb->len;
+			/* NFC Forum Digital Protocol Table 44 */
+			if (target->sensf_res[0] == 0x01 &&
+			    target->sensf_res[1] == 0xfe)
+				target->supported_protocols =
+							NFC_PROTO_NFC_DEP_MASK;
+			else
+				target->supported_protocols =
+							NFC_PROTO_FELICA_MASK;
+		} else {
+			kfree_skb(nfcid_skb);
+			/* P2P in type A */
+			r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_F_GATE,
+					ST21NFCA_RF_READER_F_NFCID1,
+					&nfcid_skb);
+			if (r < 0)
+				goto exit;
+
+			if (nfcid_skb->len > NFC_NFCID1_MAXSIZE) {
+				r = -EPROTO;
+				goto exit;
+			}
+			memcpy(target->sensf_res, nfcid_skb->data,
+				nfcid_skb->len);
+			target->sensf_res_len = nfcid_skb->len;
+			target->supported_protocols = NFC_PROTO_NFC_DEP_MASK;
+		}
+		target->hci_reader_gate = ST21NFCA_RF_READER_F_GATE;
+	}
+	r = 1;
+exit:
+	kfree_skb(nfcid_skb);
+	return r;
+}
+
+#define ST21NFCA_CB_TYPE_READER_ISO15693 1
+static void st21nfca_hci_data_exchange_cb(void *context, struct sk_buff *skb,
+					  int err)
+{
+	struct st21nfca_hci_info *info = context;
+
+	switch (info->async_cb_type) {
+	case ST21NFCA_CB_TYPE_READER_ISO15693:
+		if (err == 0)
+			skb_trim(skb, skb->len - 1);
+		info->async_cb(info->async_cb_context, skb, err);
+		break;
+	default:
+		if (err == 0)
+			kfree_skb(skb);
+		break;
+	}
+}
+
+/*
+ * Returns:
+ * <= 0: driver handled the data exchange
+ *    1: driver doesn't especially handle, please do standard processing
+ */
+static int st21nfca_hci_im_transceive(struct nfc_hci_dev *hdev,
+				      struct nfc_target *target,
+				      struct sk_buff *skb,
+				      data_exchange_cb_t cb, void *cb_context)
+{
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	pr_info(DRIVER_DESC ": %s for gate=%d len=%d\n", __func__,
+		target->hci_reader_gate, skb->len);
+
+	switch (target->hci_reader_gate) {
+	case ST21NFCA_RF_READER_F_GATE:
+		if (target->supported_protocols == NFC_PROTO_NFC_DEP_MASK)
+			return st21nfca_im_send_dep_req(hdev, skb);
+
+		*skb_push(skb, 1) = 0x1a;
+		return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate,
+					      ST21NFCA_WR_XCHG_DATA, skb->data,
+					      skb->len, cb, cb_context);
+	case ST21NFCA_RF_READER_14443_3_A_GATE:
+		*skb_push(skb, 1) = 0x1a;	/* CTR, see spec:10.2.2.1 */
+
+		return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate,
+					      ST21NFCA_WR_XCHG_DATA, skb->data,
+					      skb->len, cb, cb_context);
+	case ST21NFCA_RF_READER_ISO15693_GATE:
+		info->async_cb_type = ST21NFCA_CB_TYPE_READER_ISO15693;
+		info->async_cb = cb;
+		info->async_cb_context = cb_context;
+
+		*skb_push(skb, 1) = 0x17;
+
+		return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate,
+					      ST21NFCA_WR_XCHG_DATA, skb->data,
+					      skb->len,
+					      st21nfca_hci_data_exchange_cb,
+					      info);
+		break;
+	default:
+		return 1;
+	}
+}
+
+static int st21nfca_hci_tm_send(struct nfc_hci_dev *hdev, struct sk_buff *skb)
+{
+	return st21nfca_tm_send_dep_res(hdev, skb);
+}
+
+static int st21nfca_hci_check_presence(struct nfc_hci_dev *hdev,
+				       struct nfc_target *target)
+{
+	u8 fwi = 0x11;
+
+	switch (target->hci_reader_gate) {
+	case NFC_HCI_RF_READER_A_GATE:
+	case NFC_HCI_RF_READER_B_GATE:
+		/*
+		 * PRESENCE_CHECK on those gates is available
+		 * However, the answer to this command is taking 3 * fwi
+		 * if the card is no present.
+		 * Instead, we send an empty I-Frame with a very short
+		 * configurable fwi ~604µs.
+		 */
+		return nfc_hci_send_cmd(hdev, target->hci_reader_gate,
+					ST21NFCA_WR_XCHG_DATA, &fwi, 1, NULL);
+	case ST21NFCA_RF_READER_14443_3_A_GATE:
+		return nfc_hci_send_cmd(hdev, target->hci_reader_gate,
+					ST21NFCA_RF_READER_CMD_PRESENCE_CHECK,
+					NULL, 0, NULL);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static void st21nfca_hci_cmd_received(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd,
+				struct sk_buff *skb)
+{
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+	u8 gate = hdev->pipes[pipe].gate;
+
+	pr_debug("cmd: %x\n", cmd);
+
+	switch (cmd) {
+	case NFC_HCI_ANY_OPEN_PIPE:
+		if (gate != ST21NFCA_APDU_READER_GATE &&
+			hdev->pipes[pipe].dest_host != NFC_HCI_UICC_HOST_ID)
+			info->se_info.count_pipes++;
+
+		if (info->se_info.count_pipes == info->se_info.expected_pipes) {
+			del_timer_sync(&info->se_info.se_active_timer);
+			info->se_info.se_active = false;
+			info->se_info.count_pipes = 0;
+			complete(&info->se_info.req_completion);
+		}
+	break;
+	}
+}
+
+static int st21nfca_admin_event_received(struct nfc_hci_dev *hdev, u8 event,
+					struct sk_buff *skb)
+{
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	pr_debug("admin event: %x\n", event);
+
+	switch (event) {
+	case ST21NFCA_EVT_HOT_PLUG:
+		if (info->se_info.se_active) {
+			if (!ST21NFCA_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(ST21NFCA_SE_TO_PIPES));
+			}
+		}
+	break;
+	}
+	kfree_skb(skb);
+	return 0;
+}
+
+/*
+ * Returns:
+ * <= 0: driver handled the event, skb consumed
+ *    1: driver does not handle the event, please do standard processing
+ */
+static int st21nfca_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe,
+				       u8 event, struct sk_buff *skb)
+{
+	u8 gate = hdev->pipes[pipe].gate;
+	u8 host = hdev->pipes[pipe].dest_host;
+
+	pr_debug("hci event: %d gate: %x\n", event, gate);
+
+	switch (gate) {
+	case NFC_HCI_ADMIN_GATE:
+		return st21nfca_admin_event_received(hdev, event, skb);
+	case ST21NFCA_RF_CARD_F_GATE:
+		return st21nfca_dep_event_received(hdev, event, skb);
+	case ST21NFCA_CONNECTIVITY_GATE:
+		return st21nfca_connectivity_event_received(hdev, host,
+							event, skb);
+	case ST21NFCA_APDU_READER_GATE:
+		return st21nfca_apdu_reader_event_received(hdev, event, skb);
+	default:
+		return 1;
+	}
+}
+
+static struct nfc_hci_ops st21nfca_hci_ops = {
+	.open = st21nfca_hci_open,
+	.close = st21nfca_hci_close,
+	.load_session = st21nfca_hci_load_session,
+	.hci_ready = st21nfca_hci_ready,
+	.xmit = st21nfca_hci_xmit,
+	.start_poll = st21nfca_hci_start_poll,
+	.stop_poll = st21nfca_hci_stop_poll,
+	.dep_link_up = st21nfca_hci_dep_link_up,
+	.dep_link_down = st21nfca_hci_dep_link_down,
+	.target_from_gate = st21nfca_hci_target_from_gate,
+	.complete_target_discovered = st21nfca_hci_complete_target_discovered,
+	.im_transceive = st21nfca_hci_im_transceive,
+	.tm_send = st21nfca_hci_tm_send,
+	.check_presence = st21nfca_hci_check_presence,
+	.event_received = st21nfca_hci_event_received,
+	.cmd_received = st21nfca_hci_cmd_received,
+	.discover_se = st21nfca_hci_discover_se,
+	.enable_se = st21nfca_hci_enable_se,
+	.disable_se = st21nfca_hci_disable_se,
+	.se_io = st21nfca_hci_se_io,
+};
+
+int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops,
+		       char *llc_name, int phy_headroom, int phy_tailroom,
+		       int phy_payload, struct nfc_hci_dev **hdev,
+			   struct st21nfca_se_status *se_status)
+{
+	struct st21nfca_hci_info *info;
+	int r = 0;
+	int dev_num;
+	u32 protocols;
+	struct nfc_hci_init_data init_data;
+	unsigned long quirks = 0;
+
+	info = kzalloc(sizeof(struct st21nfca_hci_info), GFP_KERNEL);
+	if (!info) {
+		r = -ENOMEM;
+		goto err_alloc_hdev;
+	}
+
+	info->phy_ops = phy_ops;
+	info->phy_id = phy_id;
+	info->state = ST21NFCA_ST_COLD;
+	mutex_init(&info->info_lock);
+
+	init_data.gate_count = ARRAY_SIZE(st21nfca_gates);
+
+	memcpy(init_data.gates, st21nfca_gates, sizeof(st21nfca_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, ST21NFCA_NUM_DEVICES);
+
+	if (dev_num >= ST21NFCA_NUM_DEVICES)
+		return -ENODEV;
+
+	set_bit(dev_num, dev_mask);
+
+	scnprintf(init_data.session_id, sizeof(init_data.session_id), "%s%2x",
+		  "ST21AH", dev_num);
+
+	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;
+
+	set_bit(NFC_HCI_QUIRK_SHORT_CLEAR, &quirks);
+
+	info->hdev =
+	    nfc_hci_allocate_device(&st21nfca_hci_ops, &init_data, quirks,
+				    protocols, llc_name,
+				    phy_headroom + ST21NFCA_CMDS_HEADROOM,
+				    phy_tailroom, phy_payload);
+
+	if (!info->hdev) {
+		pr_err("Cannot allocate nfc hdev.\n");
+		r = -ENOMEM;
+		goto err_alloc_hdev;
+	}
+
+	info->se_status = se_status;
+
+	nfc_hci_set_clientdata(info->hdev, info);
+
+	r = nfc_hci_register_device(info->hdev);
+	if (r)
+		goto err_regdev;
+
+	*hdev = info->hdev;
+	st21nfca_dep_init(info->hdev);
+	st21nfca_se_init(info->hdev);
+
+	return 0;
+
+err_regdev:
+	nfc_hci_free_device(info->hdev);
+
+err_alloc_hdev:
+	kfree(info);
+
+	return r;
+}
+EXPORT_SYMBOL(st21nfca_hci_probe);
+
+void st21nfca_hci_remove(struct nfc_hci_dev *hdev)
+{
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	st21nfca_dep_deinit(hdev);
+	st21nfca_se_deinit(hdev);
+	nfc_hci_unregister_device(hdev);
+	nfc_hci_free_device(hdev);
+	kfree(info);
+}
+EXPORT_SYMBOL(st21nfca_hci_remove);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/nfc/st21nfca/dep.c b/drivers/nfc/st21nfca/dep.c
new file mode 100644
index 0000000..c011712
--- /dev/null
+++ b/drivers/nfc/st21nfca/dep.c
@@ -0,0 +1,688 @@
+/*
+ * 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 <net/nfc/hci.h>
+
+#include "st21nfca.h"
+
+#define ST21NFCA_NFCIP1_INITIATOR 0x00
+#define ST21NFCA_NFCIP1_REQ 0xd4
+#define ST21NFCA_NFCIP1_RES 0xd5
+#define ST21NFCA_NFCIP1_ATR_REQ 0x00
+#define ST21NFCA_NFCIP1_ATR_RES 0x01
+#define ST21NFCA_NFCIP1_PSL_REQ 0x04
+#define ST21NFCA_NFCIP1_PSL_RES 0x05
+#define ST21NFCA_NFCIP1_DEP_REQ 0x06
+#define ST21NFCA_NFCIP1_DEP_RES 0x07
+
+#define ST21NFCA_NFC_DEP_PFB_PNI(pfb)     ((pfb) & 0x03)
+#define ST21NFCA_NFC_DEP_PFB_TYPE(pfb) ((pfb) & 0xE0)
+#define ST21NFCA_NFC_DEP_PFB_IS_TIMEOUT(pfb) \
+				((pfb) & ST21NFCA_NFC_DEP_PFB_TIMEOUT_BIT)
+#define ST21NFCA_NFC_DEP_DID_BIT_SET(pfb) ((pfb) & 0x04)
+#define ST21NFCA_NFC_DEP_NAD_BIT_SET(pfb) ((pfb) & 0x08)
+#define ST21NFCA_NFC_DEP_PFB_TIMEOUT_BIT 0x10
+
+#define ST21NFCA_NFC_DEP_PFB_IS_TIMEOUT(pfb) \
+				((pfb) & ST21NFCA_NFC_DEP_PFB_TIMEOUT_BIT)
+
+#define ST21NFCA_NFC_DEP_PFB_I_PDU          0x00
+#define ST21NFCA_NFC_DEP_PFB_ACK_NACK_PDU   0x40
+#define ST21NFCA_NFC_DEP_PFB_SUPERVISOR_PDU 0x80
+
+#define ST21NFCA_ATR_REQ_MIN_SIZE 17
+#define ST21NFCA_ATR_REQ_MAX_SIZE 65
+#define ST21NFCA_LR_BITS_PAYLOAD_SIZE_254B 0x30
+#define ST21NFCA_GB_BIT  0x02
+
+#define ST21NFCA_EVT_SEND_DATA		0x10
+#define ST21NFCA_EVT_FIELD_ON           0x11
+#define ST21NFCA_EVT_CARD_DEACTIVATED   0x12
+#define ST21NFCA_EVT_CARD_ACTIVATED     0x13
+#define ST21NFCA_EVT_FIELD_OFF          0x14
+
+#define ST21NFCA_EVT_CARD_F_BITRATE 0x16
+#define ST21NFCA_EVT_READER_F_BITRATE 0x13
+#define	ST21NFCA_PSL_REQ_SEND_SPEED(brs) (brs & 0x38)
+#define ST21NFCA_PSL_REQ_RECV_SPEED(brs) (brs & 0x07)
+#define ST21NFCA_PP2LRI(pp) ((pp & 0x30) >> 4)
+#define ST21NFCA_CARD_BITRATE_212 0x01
+#define ST21NFCA_CARD_BITRATE_424 0x02
+
+#define ST21NFCA_DEFAULT_TIMEOUT 0x0a
+
+
+#define PROTOCOL_ERR(req) pr_err("%d: ST21NFCA Protocol error: %s\n", \
+				 __LINE__, req)
+
+struct st21nfca_atr_req {
+	u8 length;
+	u8 cmd0;
+	u8 cmd1;
+	u8 nfcid3[NFC_NFCID3_MAXSIZE];
+	u8 did;
+	u8 bsi;
+	u8 bri;
+	u8 ppi;
+	u8 gbi[0];
+} __packed;
+
+struct st21nfca_atr_res {
+	u8 length;
+	u8 cmd0;
+	u8 cmd1;
+	u8 nfcid3[NFC_NFCID3_MAXSIZE];
+	u8 did;
+	u8 bsi;
+	u8 bri;
+	u8 to;
+	u8 ppi;
+	u8 gbi[0];
+} __packed;
+
+struct st21nfca_psl_req {
+	u8 length;
+	u8 cmd0;
+	u8 cmd1;
+	u8 did;
+	u8 brs;
+	u8 fsl;
+} __packed;
+
+struct st21nfca_psl_res {
+	u8 length;
+	u8 cmd0;
+	u8 cmd1;
+	u8 did;
+} __packed;
+
+struct st21nfca_dep_req_res {
+	u8 length;
+	u8 cmd0;
+	u8 cmd1;
+	u8 pfb;
+	u8 did;
+	u8 nad;
+} __packed;
+
+static void st21nfca_tx_work(struct work_struct *work)
+{
+	struct st21nfca_hci_info *info = container_of(work,
+						struct st21nfca_hci_info,
+						dep_info.tx_work);
+
+	struct nfc_dev *dev;
+	struct sk_buff *skb;
+
+	if (info) {
+		dev = info->hdev->ndev;
+		skb = info->dep_info.tx_pending;
+
+		device_lock(&dev->dev);
+
+		nfc_hci_send_cmd_async(info->hdev, ST21NFCA_RF_READER_F_GATE,
+				ST21NFCA_WR_XCHG_DATA, skb->data, skb->len,
+				info->async_cb, info);
+		device_unlock(&dev->dev);
+		kfree_skb(skb);
+	}
+}
+
+static void st21nfca_im_send_pdu(struct st21nfca_hci_info *info,
+						struct sk_buff *skb)
+{
+	info->dep_info.tx_pending = skb;
+	schedule_work(&info->dep_info.tx_work);
+}
+
+static int st21nfca_tm_send_atr_res(struct nfc_hci_dev *hdev,
+				    struct st21nfca_atr_req *atr_req)
+{
+	struct st21nfca_atr_res *atr_res;
+	struct sk_buff *skb;
+	size_t gb_len;
+	int r;
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	gb_len = atr_req->length - sizeof(struct st21nfca_atr_req);
+	skb = alloc_skb(atr_req->length + 1, GFP_KERNEL);
+	if (!skb)
+		return -ENOMEM;
+
+	skb_put(skb, sizeof(struct st21nfca_atr_res));
+
+	atr_res = (struct st21nfca_atr_res *)skb->data;
+	memset(atr_res, 0, sizeof(struct st21nfca_atr_res));
+
+	atr_res->length = atr_req->length + 1;
+	atr_res->cmd0 = ST21NFCA_NFCIP1_RES;
+	atr_res->cmd1 = ST21NFCA_NFCIP1_ATR_RES;
+
+	memcpy(atr_res->nfcid3, atr_req->nfcid3, 6);
+	atr_res->bsi = 0x00;
+	atr_res->bri = 0x00;
+	atr_res->to = ST21NFCA_DEFAULT_TIMEOUT;
+	atr_res->ppi = ST21NFCA_LR_BITS_PAYLOAD_SIZE_254B;
+
+	if (gb_len) {
+		skb_put(skb, gb_len);
+
+		atr_res->ppi |= ST21NFCA_GB_BIT;
+		memcpy(atr_res->gbi, atr_req->gbi, gb_len);
+		r = nfc_set_remote_general_bytes(hdev->ndev, atr_res->gbi,
+						  gb_len);
+		if (r < 0)
+			return r;
+	}
+
+	info->dep_info.curr_nfc_dep_pni = 0;
+
+	r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE,
+				ST21NFCA_EVT_SEND_DATA, skb->data, skb->len);
+	kfree_skb(skb);
+	return r;
+}
+
+static int st21nfca_tm_recv_atr_req(struct nfc_hci_dev *hdev,
+				    struct sk_buff *skb)
+{
+	struct st21nfca_atr_req *atr_req;
+	size_t gb_len;
+	int r;
+
+	skb_trim(skb, skb->len - 1);
+
+	if (!skb->len) {
+		r = -EIO;
+		goto exit;
+	}
+
+	if (skb->len < ST21NFCA_ATR_REQ_MIN_SIZE) {
+		r = -EPROTO;
+		goto exit;
+	}
+
+	atr_req = (struct st21nfca_atr_req *)skb->data;
+
+	if (atr_req->length < sizeof(struct st21nfca_atr_req)) {
+		r = -EPROTO;
+		goto exit;
+	}
+
+	r = st21nfca_tm_send_atr_res(hdev, atr_req);
+	if (r)
+		goto exit;
+
+	gb_len = skb->len - sizeof(struct st21nfca_atr_req);
+
+	r = nfc_tm_activated(hdev->ndev, NFC_PROTO_NFC_DEP_MASK,
+			      NFC_COMM_PASSIVE, atr_req->gbi, gb_len);
+	if (r)
+		goto exit;
+
+	r = 0;
+
+exit:
+	return r;
+}
+
+static int st21nfca_tm_send_psl_res(struct nfc_hci_dev *hdev,
+				    struct st21nfca_psl_req *psl_req)
+{
+	struct st21nfca_psl_res *psl_res;
+	struct sk_buff *skb;
+	u8 bitrate[2] = {0, 0};
+	int r;
+
+	skb = alloc_skb(sizeof(struct st21nfca_psl_res), GFP_KERNEL);
+	if (!skb)
+		return -ENOMEM;
+	skb_put(skb, sizeof(struct st21nfca_psl_res));
+
+	psl_res = (struct st21nfca_psl_res *)skb->data;
+
+	psl_res->length = sizeof(struct st21nfca_psl_res);
+	psl_res->cmd0 = ST21NFCA_NFCIP1_RES;
+	psl_res->cmd1 = ST21NFCA_NFCIP1_PSL_RES;
+	psl_res->did = psl_req->did;
+
+	r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE,
+				ST21NFCA_EVT_SEND_DATA, skb->data, skb->len);
+	if (r < 0)
+		goto error;
+
+	/*
+	 * ST21NFCA only support P2P passive.
+	 * PSL_REQ BRS value != 0 has only a meaning to
+	 * change technology to type F.
+	 * We change to BITRATE 424Kbits.
+	 * In other case switch to BITRATE 106Kbits.
+	 */
+	if (ST21NFCA_PSL_REQ_SEND_SPEED(psl_req->brs) &&
+	    ST21NFCA_PSL_REQ_RECV_SPEED(psl_req->brs)) {
+		bitrate[0] = ST21NFCA_CARD_BITRATE_424;
+		bitrate[1] = ST21NFCA_CARD_BITRATE_424;
+	}
+
+	/* Send an event to change bitrate change event to card f */
+	r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE,
+			ST21NFCA_EVT_CARD_F_BITRATE, bitrate, 2);
+error:
+	kfree_skb(skb);
+	return r;
+}
+
+static int st21nfca_tm_recv_psl_req(struct nfc_hci_dev *hdev,
+				    struct sk_buff *skb)
+{
+	struct st21nfca_psl_req *psl_req;
+	int r;
+
+	skb_trim(skb, skb->len - 1);
+
+	if (!skb->len) {
+		r = -EIO;
+		goto exit;
+	}
+
+	psl_req = (struct st21nfca_psl_req *)skb->data;
+
+	if (skb->len < sizeof(struct st21nfca_psl_req)) {
+		r = -EIO;
+		goto exit;
+	}
+
+	r = st21nfca_tm_send_psl_res(hdev, psl_req);
+exit:
+	return r;
+}
+
+int st21nfca_tm_send_dep_res(struct nfc_hci_dev *hdev, struct sk_buff *skb)
+{
+	int r;
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	*skb_push(skb, 1) = info->dep_info.curr_nfc_dep_pni;
+	*skb_push(skb, 1) = ST21NFCA_NFCIP1_DEP_RES;
+	*skb_push(skb, 1) = ST21NFCA_NFCIP1_RES;
+	*skb_push(skb, 1) = skb->len;
+
+	r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE,
+			ST21NFCA_EVT_SEND_DATA, skb->data, skb->len);
+	kfree_skb(skb);
+
+	return r;
+}
+EXPORT_SYMBOL(st21nfca_tm_send_dep_res);
+
+static int st21nfca_tm_recv_dep_req(struct nfc_hci_dev *hdev,
+				    struct sk_buff *skb)
+{
+	struct st21nfca_dep_req_res *dep_req;
+	u8 size;
+	int r;
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	skb_trim(skb, skb->len - 1);
+
+	size = 4;
+
+	dep_req = (struct st21nfca_dep_req_res *)skb->data;
+	if (skb->len < size) {
+		r = -EIO;
+		goto exit;
+	}
+
+	if (ST21NFCA_NFC_DEP_DID_BIT_SET(dep_req->pfb))
+		size++;
+	if (ST21NFCA_NFC_DEP_NAD_BIT_SET(dep_req->pfb))
+		size++;
+
+	if (skb->len < size) {
+		r = -EIO;
+		goto exit;
+	}
+
+	/* Receiving DEP_REQ - Decoding */
+	switch (ST21NFCA_NFC_DEP_PFB_TYPE(dep_req->pfb)) {
+	case ST21NFCA_NFC_DEP_PFB_I_PDU:
+		info->dep_info.curr_nfc_dep_pni =
+				ST21NFCA_NFC_DEP_PFB_PNI(dep_req->pfb);
+		break;
+	case ST21NFCA_NFC_DEP_PFB_ACK_NACK_PDU:
+		pr_err("Received a ACK/NACK PDU\n");
+		break;
+	case ST21NFCA_NFC_DEP_PFB_SUPERVISOR_PDU:
+		pr_err("Received a SUPERVISOR PDU\n");
+		break;
+	}
+
+	skb_pull(skb, size);
+
+	return nfc_tm_data_received(hdev->ndev, skb);
+exit:
+	return r;
+}
+
+static int st21nfca_tm_event_send_data(struct nfc_hci_dev *hdev,
+				struct sk_buff *skb)
+{
+	u8 cmd0, cmd1;
+	int r;
+
+	cmd0 = skb->data[1];
+	switch (cmd0) {
+	case ST21NFCA_NFCIP1_REQ:
+		cmd1 = skb->data[2];
+		switch (cmd1) {
+		case ST21NFCA_NFCIP1_ATR_REQ:
+			r = st21nfca_tm_recv_atr_req(hdev, skb);
+			break;
+		case ST21NFCA_NFCIP1_PSL_REQ:
+			r = st21nfca_tm_recv_psl_req(hdev, skb);
+			break;
+		case ST21NFCA_NFCIP1_DEP_REQ:
+			r = st21nfca_tm_recv_dep_req(hdev, skb);
+			break;
+		default:
+			return 1;
+		}
+	default:
+		return 1;
+	}
+	return r;
+}
+
+/*
+ * Returns:
+ * <= 0: driver handled the event, skb consumed
+ *    1: driver does not handle the event, please do standard processing
+ */
+int st21nfca_dep_event_received(struct nfc_hci_dev *hdev,
+				u8 event, struct sk_buff *skb)
+{
+	int r = 0;
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	pr_debug("dep event: %d\n", event);
+
+	switch (event) {
+	case ST21NFCA_EVT_CARD_ACTIVATED:
+		info->dep_info.curr_nfc_dep_pni = 0;
+		break;
+	case ST21NFCA_EVT_CARD_DEACTIVATED:
+		break;
+	case ST21NFCA_EVT_FIELD_ON:
+		break;
+	case ST21NFCA_EVT_FIELD_OFF:
+		break;
+	case ST21NFCA_EVT_SEND_DATA:
+		r = st21nfca_tm_event_send_data(hdev, skb);
+		if (r < 0)
+			return r;
+		return 0;
+	default:
+		return 1;
+	}
+	kfree_skb(skb);
+	return r;
+}
+EXPORT_SYMBOL(st21nfca_dep_event_received);
+
+static void st21nfca_im_send_psl_req(struct nfc_hci_dev *hdev, u8 did, u8 bsi,
+				     u8 bri, u8 lri)
+{
+	struct sk_buff *skb;
+	struct st21nfca_psl_req *psl_req;
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	skb =
+	    alloc_skb(sizeof(struct st21nfca_psl_req) + 1, GFP_KERNEL);
+	if (!skb)
+		return;
+	skb_reserve(skb, 1);
+
+	skb_put(skb, sizeof(struct st21nfca_psl_req));
+	psl_req = (struct st21nfca_psl_req *) skb->data;
+
+	psl_req->length = sizeof(struct st21nfca_psl_req);
+	psl_req->cmd0 = ST21NFCA_NFCIP1_REQ;
+	psl_req->cmd1 = ST21NFCA_NFCIP1_PSL_REQ;
+	psl_req->did = did;
+	psl_req->brs = (0x30 & bsi << 4) | (bri & 0x03);
+	psl_req->fsl = lri;
+
+	*skb_push(skb, 1) = info->dep_info.to | 0x10;
+
+	st21nfca_im_send_pdu(info, skb);
+}
+
+#define ST21NFCA_CB_TYPE_READER_F 1
+static void st21nfca_im_recv_atr_res_cb(void *context, struct sk_buff *skb,
+					int err)
+{
+	struct st21nfca_hci_info *info = context;
+	struct st21nfca_atr_res *atr_res;
+	int r;
+
+	if (err != 0)
+		return;
+
+	if (!skb)
+		return;
+
+	switch (info->async_cb_type) {
+	case ST21NFCA_CB_TYPE_READER_F:
+		skb_trim(skb, skb->len - 1);
+		atr_res = (struct st21nfca_atr_res *)skb->data;
+		r = nfc_set_remote_general_bytes(info->hdev->ndev,
+				atr_res->gbi,
+				skb->len - sizeof(struct st21nfca_atr_res));
+		if (r < 0)
+			return;
+
+		if (atr_res->to >= 0x0e)
+			info->dep_info.to = 0x0e;
+		else
+			info->dep_info.to = atr_res->to + 1;
+
+		info->dep_info.to |= 0x10;
+
+		r = nfc_dep_link_is_up(info->hdev->ndev, info->dep_info.idx,
+					NFC_COMM_PASSIVE, NFC_RF_INITIATOR);
+		if (r < 0)
+			return;
+
+		info->dep_info.curr_nfc_dep_pni = 0;
+		if (ST21NFCA_PP2LRI(atr_res->ppi) != info->dep_info.lri)
+			st21nfca_im_send_psl_req(info->hdev, atr_res->did,
+						atr_res->bsi, atr_res->bri,
+						ST21NFCA_PP2LRI(atr_res->ppi));
+		break;
+	default:
+		kfree_skb(skb);
+		break;
+	}
+}
+
+int st21nfca_im_send_atr_req(struct nfc_hci_dev *hdev, u8 *gb, size_t gb_len)
+{
+	struct sk_buff *skb;
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+	struct st21nfca_atr_req *atr_req;
+	struct nfc_target *target;
+	uint size;
+
+	info->dep_info.to = ST21NFCA_DEFAULT_TIMEOUT;
+	size = ST21NFCA_ATR_REQ_MIN_SIZE + gb_len;
+	if (size > ST21NFCA_ATR_REQ_MAX_SIZE) {
+		PROTOCOL_ERR("14.6.1.1");
+		return -EINVAL;
+	}
+
+	skb =
+	    alloc_skb(sizeof(struct st21nfca_atr_req) + gb_len + 1, GFP_KERNEL);
+	if (!skb)
+		return -ENOMEM;
+
+	skb_reserve(skb, 1);
+
+	skb_put(skb, sizeof(struct st21nfca_atr_req));
+
+	atr_req = (struct st21nfca_atr_req *)skb->data;
+	memset(atr_req, 0, sizeof(struct st21nfca_atr_req));
+
+	atr_req->cmd0 = ST21NFCA_NFCIP1_REQ;
+	atr_req->cmd1 = ST21NFCA_NFCIP1_ATR_REQ;
+	memset(atr_req->nfcid3, 0, NFC_NFCID3_MAXSIZE);
+	target = hdev->ndev->targets;
+
+	if (target->sensf_res_len > 0)
+		memcpy(atr_req->nfcid3, target->sensf_res,
+				target->sensf_res_len);
+	else
+		get_random_bytes(atr_req->nfcid3, NFC_NFCID3_MAXSIZE);
+
+	atr_req->did = 0x0;
+
+	atr_req->bsi = 0x00;
+	atr_req->bri = 0x00;
+	atr_req->ppi = ST21NFCA_LR_BITS_PAYLOAD_SIZE_254B;
+	if (gb_len) {
+		atr_req->ppi |= ST21NFCA_GB_BIT;
+		memcpy(skb_put(skb, gb_len), gb, gb_len);
+	}
+	atr_req->length = sizeof(struct st21nfca_atr_req) + hdev->gb_len;
+
+	*skb_push(skb, 1) = info->dep_info.to | 0x10; /* timeout */
+
+	info->async_cb_type = ST21NFCA_CB_TYPE_READER_F;
+	info->async_cb_context = info;
+	info->async_cb = st21nfca_im_recv_atr_res_cb;
+	info->dep_info.bri = atr_req->bri;
+	info->dep_info.bsi = atr_req->bsi;
+	info->dep_info.lri = ST21NFCA_PP2LRI(atr_req->ppi);
+
+	return nfc_hci_send_cmd_async(hdev, ST21NFCA_RF_READER_F_GATE,
+				ST21NFCA_WR_XCHG_DATA, skb->data,
+				skb->len, info->async_cb, info);
+}
+EXPORT_SYMBOL(st21nfca_im_send_atr_req);
+
+static void st21nfca_im_recv_dep_res_cb(void *context, struct sk_buff *skb,
+					int err)
+{
+	struct st21nfca_hci_info *info = context;
+	struct st21nfca_dep_req_res *dep_res;
+
+	int size;
+
+	if (err != 0)
+		return;
+
+	if (!skb)
+		return;
+
+	switch (info->async_cb_type) {
+	case ST21NFCA_CB_TYPE_READER_F:
+		dep_res = (struct st21nfca_dep_req_res *)skb->data;
+
+		size = 3;
+		if (skb->len < size)
+			goto exit;
+
+		if (ST21NFCA_NFC_DEP_DID_BIT_SET(dep_res->pfb))
+			size++;
+		if (ST21NFCA_NFC_DEP_NAD_BIT_SET(dep_res->pfb))
+			size++;
+
+		if (skb->len < size)
+			goto exit;
+
+		skb_trim(skb, skb->len - 1);
+
+		/* Receiving DEP_REQ - Decoding */
+		switch (ST21NFCA_NFC_DEP_PFB_TYPE(dep_res->pfb)) {
+		case ST21NFCA_NFC_DEP_PFB_ACK_NACK_PDU:
+			pr_err("Received a ACK/NACK PDU\n");
+		case ST21NFCA_NFC_DEP_PFB_I_PDU:
+			info->dep_info.curr_nfc_dep_pni =
+			    ST21NFCA_NFC_DEP_PFB_PNI(dep_res->pfb + 1);
+			size++;
+			skb_pull(skb, size);
+			nfc_tm_data_received(info->hdev->ndev, skb);
+			break;
+		case ST21NFCA_NFC_DEP_PFB_SUPERVISOR_PDU:
+			pr_err("Received a SUPERVISOR PDU\n");
+			skb_pull(skb, size);
+			*skb_push(skb, 1) = ST21NFCA_NFCIP1_DEP_REQ;
+			*skb_push(skb, 1) = ST21NFCA_NFCIP1_REQ;
+			*skb_push(skb, 1) = skb->len;
+			*skb_push(skb, 1) = info->dep_info.to | 0x10;
+
+			st21nfca_im_send_pdu(info, skb);
+			break;
+		}
+
+		return;
+	default:
+		break;
+	}
+
+exit:
+	kfree_skb(skb);
+}
+
+int st21nfca_im_send_dep_req(struct nfc_hci_dev *hdev, struct sk_buff *skb)
+{
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	info->async_cb_type = ST21NFCA_CB_TYPE_READER_F;
+	info->async_cb_context = info;
+	info->async_cb = st21nfca_im_recv_dep_res_cb;
+
+	*skb_push(skb, 1) = info->dep_info.curr_nfc_dep_pni;
+	*skb_push(skb, 1) = ST21NFCA_NFCIP1_DEP_REQ;
+	*skb_push(skb, 1) = ST21NFCA_NFCIP1_REQ;
+	*skb_push(skb, 1) = skb->len;
+
+	*skb_push(skb, 1) = info->dep_info.to | 0x10;
+
+	return nfc_hci_send_cmd_async(hdev, ST21NFCA_RF_READER_F_GATE,
+				      ST21NFCA_WR_XCHG_DATA,
+				      skb->data, skb->len,
+				      info->async_cb, info);
+}
+EXPORT_SYMBOL(st21nfca_im_send_dep_req);
+
+void st21nfca_dep_init(struct nfc_hci_dev *hdev)
+{
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	INIT_WORK(&info->dep_info.tx_work, st21nfca_tx_work);
+	info->dep_info.curr_nfc_dep_pni = 0;
+	info->dep_info.idx = 0;
+	info->dep_info.to = ST21NFCA_DEFAULT_TIMEOUT;
+}
+EXPORT_SYMBOL(st21nfca_dep_init);
+
+void st21nfca_dep_deinit(struct nfc_hci_dev *hdev)
+{
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	cancel_work_sync(&info->dep_info.tx_work);
+}
+EXPORT_SYMBOL(st21nfca_dep_deinit);
diff --git a/drivers/nfc/st21nfca/se.c b/drivers/nfc/st21nfca/se.c
new file mode 100644
index 0000000..6aa4e34
--- /dev/null
+++ b/drivers/nfc/st21nfca/se.c
@@ -0,0 +1,419 @@
+/*
+ * 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 <net/nfc/hci.h>
+
+#include "st21nfca.h"
+
+#define ST21NFCA_EVT_UICC_ACTIVATE		0x10
+#define ST21NFCA_EVT_UICC_DEACTIVATE	0x13
+#define ST21NFCA_EVT_SE_HARD_RESET		0x20
+#define ST21NFCA_EVT_SE_SOFT_RESET		0x11
+#define ST21NFCA_EVT_SE_END_OF_APDU_TRANSFER	0x21
+#define ST21NFCA_EVT_SE_ACTIVATE		0x22
+#define ST21NFCA_EVT_SE_DEACTIVATE		0x23
+
+#define ST21NFCA_EVT_TRANSMIT_DATA		0x10
+#define ST21NFCA_EVT_WTX_REQUEST		0x11
+
+#define ST21NFCA_EVT_CONNECTIVITY		0x10
+#define ST21NFCA_EVT_TRANSACTION		0x12
+
+#define ST21NFCA_ESE_HOST_ID			0xc0
+
+#define ST21NFCA_SE_TO_HOT_PLUG			1000
+/* Connectivity pipe only */
+#define ST21NFCA_SE_COUNT_PIPE_UICC		0x01
+/* Connectivity + APDU Reader pipe */
+#define ST21NFCA_SE_COUNT_PIPE_EMBEDDED	0x02
+
+#define ST21NFCA_SE_MODE_OFF			0x00
+#define ST21NFCA_SE_MODE_ON				0x01
+
+#define ST21NFCA_PARAM_ATR				0x01
+#define ST21NFCA_ATR_DEFAULT_BWI		0x04
+
+/*
+ * WT = 2^BWI/10[s], convert into msecs and add a secure
+ * room by increasing by 2 this timeout
+ */
+#define ST21NFCA_BWI_TO_TIMEOUT(x)		((1 << x) * 200)
+#define ST21NFCA_ATR_GET_Y_FROM_TD(x)	(x >> 4)
+
+/* If TA is present bit 0 is set */
+#define ST21NFCA_ATR_TA_PRESENT(x) (x & 0x01)
+/* If TB is present bit 1 is set */
+#define ST21NFCA_ATR_TB_PRESENT(x) (x & 0x02)
+
+static u8 st21nfca_se_get_bwi(struct nfc_hci_dev *hdev)
+{
+	int i;
+	u8 td;
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	/* Bits 8 to 5 of the first TB for T=1 encode BWI from zero to nine */
+	for (i = 1; i < ST21NFCA_ESE_MAX_LENGTH; i++) {
+		td = ST21NFCA_ATR_GET_Y_FROM_TD(info->se_info.atr[i]);
+		if (ST21NFCA_ATR_TA_PRESENT(td))
+			i++;
+		if (ST21NFCA_ATR_TB_PRESENT(td)) {
+			i++;
+			return info->se_info.atr[i] >> 4;
+		}
+	}
+	return ST21NFCA_ATR_DEFAULT_BWI;
+}
+
+static void st21nfca_se_get_atr(struct nfc_hci_dev *hdev)
+{
+	int r;
+	struct sk_buff *skb;
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	r = nfc_hci_get_param(hdev, ST21NFCA_APDU_READER_GATE,
+			ST21NFCA_PARAM_ATR, &skb);
+	if (r < 0)
+		return;
+
+	if (skb->len <= ST21NFCA_ESE_MAX_LENGTH) {
+		memcpy(info->se_info.atr, skb->data, skb->len);
+		info->se_info.wt_timeout =
+			ST21NFCA_BWI_TO_TIMEOUT(st21nfca_se_get_bwi(hdev));
+	}
+	kfree_skb(skb);
+}
+
+static int st21nfca_hci_control_se(struct nfc_hci_dev *hdev, u32 se_idx,
+				u8 state)
+{
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+	int r;
+	struct sk_buff *sk_host_list;
+	u8 se_event, host_id;
+
+	switch (se_idx) {
+	case NFC_HCI_UICC_HOST_ID:
+		se_event = (state == ST21NFCA_SE_MODE_ON ?
+					ST21NFCA_EVT_UICC_ACTIVATE :
+					ST21NFCA_EVT_UICC_DEACTIVATE);
+
+		info->se_info.count_pipes = 0;
+		info->se_info.expected_pipes = ST21NFCA_SE_COUNT_PIPE_UICC;
+		break;
+	case ST21NFCA_ESE_HOST_ID:
+		se_event = (state == ST21NFCA_SE_MODE_ON ?
+					ST21NFCA_EVT_SE_ACTIVATE :
+					ST21NFCA_EVT_SE_DEACTIVATE);
+
+		info->se_info.count_pipes = 0;
+		info->se_info.expected_pipes = ST21NFCA_SE_COUNT_PIPE_EMBEDDED;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/*
+	 * Wait for an EVT_HOT_PLUG in order to
+	 * retrieve a relevant host list.
+	 */
+	reinit_completion(&info->se_info.req_completion);
+	r = nfc_hci_send_event(hdev, ST21NFCA_DEVICE_MGNT_GATE, se_event,
+			       NULL, 0);
+	if (r < 0)
+		return r;
+
+	mod_timer(&info->se_info.se_active_timer, jiffies +
+		msecs_to_jiffies(ST21NFCA_SE_TO_HOT_PLUG));
+	info->se_info.se_active = true;
+
+	/* Ignore return value and check in any case the host_list */
+	wait_for_completion_interruptible(&info->se_info.req_completion);
+
+	r = nfc_hci_get_param(hdev, NFC_HCI_ADMIN_GATE,
+			NFC_HCI_ADMIN_HOST_LIST,
+			&sk_host_list);
+	if (r < 0)
+		return r;
+
+	host_id = sk_host_list->data[sk_host_list->len - 1];
+	kfree_skb(sk_host_list);
+
+	if (state == ST21NFCA_SE_MODE_ON && host_id == se_idx)
+		return se_idx;
+	else if (state == ST21NFCA_SE_MODE_OFF && host_id != se_idx)
+		return se_idx;
+
+	return -1;
+}
+
+int st21nfca_hci_discover_se(struct nfc_hci_dev *hdev)
+{
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+	int se_count = 0;
+
+	if (info->se_status->is_uicc_present) {
+		nfc_add_se(hdev->ndev, NFC_HCI_UICC_HOST_ID, NFC_SE_UICC);
+		se_count++;
+	}
+
+	if (info->se_status->is_ese_present) {
+		nfc_add_se(hdev->ndev, ST21NFCA_ESE_HOST_ID, NFC_SE_EMBEDDED);
+		se_count++;
+	}
+
+	return !se_count;
+}
+EXPORT_SYMBOL(st21nfca_hci_discover_se);
+
+int st21nfca_hci_enable_se(struct nfc_hci_dev *hdev, u32 se_idx)
+{
+	int r;
+
+	/*
+	 * According to upper layer, se_idx == NFC_SE_UICC when
+	 * info->se_status->is_uicc_enable is true should never happen.
+	 * Same for eSE.
+	 */
+	r = st21nfca_hci_control_se(hdev, se_idx, ST21NFCA_SE_MODE_ON);
+
+	if (r == ST21NFCA_ESE_HOST_ID) {
+		st21nfca_se_get_atr(hdev);
+		r = nfc_hci_send_event(hdev, ST21NFCA_APDU_READER_GATE,
+				ST21NFCA_EVT_SE_SOFT_RESET, NULL, 0);
+		if (r < 0)
+			return r;
+	} else if (r < 0) {
+		/*
+		 * The activation tentative failed, the secure element
+		 * is not connected. Remove from the list.
+		 */
+		nfc_remove_se(hdev->ndev, se_idx);
+		return r;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(st21nfca_hci_enable_se);
+
+int st21nfca_hci_disable_se(struct nfc_hci_dev *hdev, u32 se_idx)
+{
+	int r;
+
+	/*
+	 * According to upper layer, se_idx == NFC_SE_UICC when
+	 * info->se_status->is_uicc_enable is true should never happen
+	 * Same for eSE.
+	 */
+	r = st21nfca_hci_control_se(hdev, se_idx, ST21NFCA_SE_MODE_OFF);
+	if (r < 0)
+		return r;
+
+	return 0;
+}
+EXPORT_SYMBOL(st21nfca_hci_disable_se);
+
+int st21nfca_hci_se_io(struct nfc_hci_dev *hdev, u32 se_idx,
+			u8 *apdu, size_t apdu_length,
+			se_io_cb_t cb, void *cb_context)
+{
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	pr_debug("se_io %x\n", se_idx);
+
+	switch (se_idx) {
+	case ST21NFCA_ESE_HOST_ID:
+		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 nfc_hci_send_event(hdev, ST21NFCA_APDU_READER_GATE,
+					ST21NFCA_EVT_TRANSMIT_DATA,
+					apdu, apdu_length);
+	default:
+		return -ENODEV;
+	}
+}
+EXPORT_SYMBOL(st21nfca_hci_se_io);
+
+static void st21nfca_se_wt_timeout(unsigned long data)
+{
+	/*
+	 * No answer from the secure element
+	 * within the defined timeout.
+	 * Let's send a reset request as recovery procedure.
+	 * According to the situation, we first try to send a software reset
+	 * to the secure element. If the next command is still not
+	 * answering in time, we send to the CLF a secure element hardware
+	 * reset request.
+	 */
+	/* hardware reset managed through VCC_UICC_OUT power supply */
+	u8 param = 0x01;
+	struct st21nfca_hci_info *info = (struct st21nfca_hci_info *) data;
+
+	pr_debug("\n");
+
+	info->se_info.bwi_active = false;
+
+	if (!info->se_info.xch_error) {
+		info->se_info.xch_error = true;
+		nfc_hci_send_event(info->hdev, ST21NFCA_APDU_READER_GATE,
+				ST21NFCA_EVT_SE_SOFT_RESET, NULL, 0);
+	} else {
+		info->se_info.xch_error = false;
+		nfc_hci_send_event(info->hdev, ST21NFCA_DEVICE_MGNT_GATE,
+				ST21NFCA_EVT_SE_HARD_RESET, &param, 1);
+	}
+	info->se_info.cb(info->se_info.cb_context, NULL, 0, -ETIME);
+}
+
+static void st21nfca_se_activation_timeout(unsigned long data)
+{
+	struct st21nfca_hci_info *info = (struct st21nfca_hci_info *) data;
+
+	pr_debug("\n");
+
+	info->se_info.se_active = false;
+
+	complete(&info->se_info.req_completion);
+}
+
+/*
+ * Returns:
+ * <= 0: driver handled the event, skb consumed
+ *    1: driver does not handle the event, please do standard processing
+ */
+int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host,
+				u8 event, struct sk_buff *skb)
+{
+	int r = 0;
+	struct device *dev = &hdev->ndev->dev;
+	struct nfc_evt_transaction *transaction;
+
+	pr_debug("connectivity gate event: %x\n", event);
+
+	switch (event) {
+	case ST21NFCA_EVT_CONNECTIVITY:
+		break;
+	case ST21NFCA_EVT_TRANSACTION:
+		/*
+		 * According to specification etsi 102 622
+		 * 11.2.2.4 EVT_TRANSACTION Table 52
+		 * Description	Tag	Length
+		 * AID		81	5 to 16
+		 * PARAMETERS	82	0 to 255
+		 */
+		if (skb->len < NFC_MIN_AID_LENGTH + 2 &&
+		    skb->data[0] != NFC_EVT_TRANSACTION_AID_TAG)
+			return -EPROTO;
+
+		transaction = (struct nfc_evt_transaction *)devm_kzalloc(dev,
+						   skb->len - 2, GFP_KERNEL);
+
+		transaction->aid_len = skb->data[1];
+		memcpy(transaction->aid, &skb->data[2],
+		       transaction->aid_len);
+
+		/* Check next byte is PARAMETERS tag (82) */
+		if (skb->data[transaction->aid_len + 2] !=
+		    NFC_EVT_TRANSACTION_PARAMS_TAG)
+			return -EPROTO;
+
+		transaction->params_len = skb->data[transaction->aid_len + 3];
+		memcpy(transaction->params, skb->data +
+		       transaction->aid_len + 4, transaction->params_len);
+
+		r = nfc_se_transaction(hdev->ndev, host, transaction);
+		break;
+	default:
+		return 1;
+	}
+	kfree_skb(skb);
+	return r;
+}
+EXPORT_SYMBOL(st21nfca_connectivity_event_received);
+
+int st21nfca_apdu_reader_event_received(struct nfc_hci_dev *hdev,
+					u8 event, struct sk_buff *skb)
+{
+	int r = 0;
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	pr_debug("apdu reader gate event: %x\n", event);
+
+	switch (event) {
+	case ST21NFCA_EVT_TRANSMIT_DATA:
+		del_timer_sync(&info->se_info.bwi_timer);
+		info->se_info.bwi_active = false;
+		r = nfc_hci_send_event(hdev, ST21NFCA_DEVICE_MGNT_GATE,
+				ST21NFCA_EVT_SE_END_OF_APDU_TRANSFER, NULL, 0);
+		if (r < 0)
+			goto exit;
+
+		info->se_info.cb(info->se_info.cb_context,
+			skb->data, skb->len, 0);
+		break;
+	case ST21NFCA_EVT_WTX_REQUEST:
+		mod_timer(&info->se_info.bwi_timer, jiffies +
+				msecs_to_jiffies(info->se_info.wt_timeout));
+		break;
+	}
+
+exit:
+	kfree_skb(skb);
+	return r;
+}
+EXPORT_SYMBOL(st21nfca_apdu_reader_event_received);
+
+void st21nfca_se_init(struct nfc_hci_dev *hdev)
+{
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	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 = st21nfca_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 = st21nfca_se_activation_timeout;
+	info->se_info.se_active = false;
+
+	info->se_info.count_pipes = 0;
+	info->se_info.expected_pipes = 0;
+
+	info->se_info.xch_error = false;
+
+	info->se_info.wt_timeout =
+			ST21NFCA_BWI_TO_TIMEOUT(ST21NFCA_ATR_DEFAULT_BWI);
+}
+EXPORT_SYMBOL(st21nfca_se_init);
+
+void st21nfca_se_deinit(struct nfc_hci_dev *hdev)
+{
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	if (info->se_info.bwi_active)
+		del_timer_sync(&info->se_info.bwi_timer);
+	if (info->se_info.se_active)
+		del_timer_sync(&info->se_info.se_active_timer);
+
+	info->se_info.bwi_active = false;
+	info->se_info.se_active = false;
+}
+EXPORT_SYMBOL(st21nfca_se_deinit);
diff --git a/drivers/nfc/st21nfca/st21nfca.c b/drivers/nfc/st21nfca/st21nfca.c
deleted file mode 100644
index 0512865..0000000
--- a/drivers/nfc/st21nfca/st21nfca.c
+++ /dev/null
@@ -1,1064 +0,0 @@
-/*
- * HCI 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/hci.h>
-#include <net/nfc/llc.h>
-
-#include "st21nfca.h"
-#include "st21nfca_dep.h"
-#include "st21nfca_se.h"
-
-#define DRIVER_DESC "HCI NFC driver for ST21NFCA"
-
-#define FULL_VERSION_LEN 3
-
-/* Proprietary gates, events, commands and registers */
-
-/* Commands that apply to all RF readers */
-#define ST21NFCA_RF_READER_CMD_PRESENCE_CHECK	0x30
-
-#define ST21NFCA_RF_READER_ISO15693_GATE	0x12
-#define ST21NFCA_RF_READER_ISO15693_INVENTORY	0x01
-
-/*
- * Reader gate for communication with contact-less cards using Type A
- * protocol ISO14443-3 but not compliant with ISO14443-4
- */
-#define ST21NFCA_RF_READER_14443_3_A_GATE	0x15
-#define ST21NFCA_RF_READER_14443_3_A_UID	0x02
-#define ST21NFCA_RF_READER_14443_3_A_ATQA	0x03
-#define ST21NFCA_RF_READER_14443_3_A_SAK	0x04
-
-#define ST21NFCA_RF_READER_F_DATARATE		0x01
-#define ST21NFCA_RF_READER_F_DATARATE_106	0x01
-#define ST21NFCA_RF_READER_F_DATARATE_212	0x02
-#define ST21NFCA_RF_READER_F_DATARATE_424	0x04
-#define ST21NFCA_RF_READER_F_POL_REQ		0x02
-#define ST21NFCA_RF_READER_F_POL_REQ_DEFAULT	0xffff0000
-#define ST21NFCA_RF_READER_F_NFCID2		0x03
-#define ST21NFCA_RF_READER_F_NFCID1		0x04
-
-#define ST21NFCA_RF_CARD_F_MODE			0x01
-#define ST21NFCA_RF_CARD_F_NFCID2_LIST		0x04
-#define ST21NFCA_RF_CARD_F_NFCID1		0x05
-#define ST21NFCA_RF_CARD_F_SENS_RES		0x06
-#define ST21NFCA_RF_CARD_F_SEL_RES		0x07
-#define ST21NFCA_RF_CARD_F_DATARATE		0x08
-#define ST21NFCA_RF_CARD_F_DATARATE_212_424	0x01
-
-#define ST21NFCA_DEVICE_MGNT_PIPE		0x02
-
-#define ST21NFCA_DM_GETINFO			0x13
-#define ST21NFCA_DM_GETINFO_PIPE_LIST		0x02
-#define ST21NFCA_DM_GETINFO_PIPE_INFO		0x01
-#define ST21NFCA_DM_PIPE_CREATED		0x02
-#define ST21NFCA_DM_PIPE_OPEN			0x04
-#define ST21NFCA_DM_RF_ACTIVE			0x80
-#define ST21NFCA_DM_DISCONNECT			0x30
-
-#define ST21NFCA_DM_IS_PIPE_OPEN(p) \
-	((p & 0x0f) == (ST21NFCA_DM_PIPE_CREATED | ST21NFCA_DM_PIPE_OPEN))
-
-#define ST21NFCA_NFC_MODE			0x03	/* NFC_MODE parameter*/
-
-#define ST21NFCA_EVT_HOT_PLUG			0x03
-#define ST21NFCA_EVT_HOT_PLUG_IS_INHIBITED(x) (x->data[0] & 0x80)
-
-#define ST21NFCA_SE_TO_PIPES			2000
-
-static DECLARE_BITMAP(dev_mask, ST21NFCA_NUM_DEVICES);
-
-static struct nfc_hci_gate st21nfca_gates[] = {
-	{NFC_HCI_ADMIN_GATE, NFC_HCI_ADMIN_PIPE},
-	{NFC_HCI_LOOPBACK_GATE, NFC_HCI_INVALID_PIPE},
-	{NFC_HCI_ID_MGMT_GATE, NFC_HCI_INVALID_PIPE},
-	{NFC_HCI_LINK_MGMT_GATE, NFC_HCI_LINK_MGMT_PIPE},
-	{NFC_HCI_RF_READER_B_GATE, NFC_HCI_INVALID_PIPE},
-	{NFC_HCI_RF_READER_A_GATE, NFC_HCI_INVALID_PIPE},
-	{ST21NFCA_DEVICE_MGNT_GATE, ST21NFCA_DEVICE_MGNT_PIPE},
-	{ST21NFCA_RF_READER_F_GATE, NFC_HCI_INVALID_PIPE},
-	{ST21NFCA_RF_READER_14443_3_A_GATE, NFC_HCI_INVALID_PIPE},
-	{ST21NFCA_RF_READER_ISO15693_GATE, NFC_HCI_INVALID_PIPE},
-	{ST21NFCA_RF_CARD_F_GATE, NFC_HCI_INVALID_PIPE},
-
-	/* Secure element pipes are created by secure element host */
-	{ST21NFCA_CONNECTIVITY_GATE, NFC_HCI_DO_NOT_CREATE_PIPE},
-	{ST21NFCA_APDU_READER_GATE, NFC_HCI_DO_NOT_CREATE_PIPE},
-};
-
-struct st21nfca_pipe_info {
-	u8 pipe_state;
-	u8 src_host_id;
-	u8 src_gate_id;
-	u8 dst_host_id;
-	u8 dst_gate_id;
-} __packed;
-
-/* Largest headroom needed for outgoing custom commands */
-#define ST21NFCA_CMDS_HEADROOM  7
-
-static int st21nfca_hci_load_session(struct nfc_hci_dev *hdev)
-{
-	int i, j, r;
-	struct sk_buff *skb_pipe_list, *skb_pipe_info;
-	struct st21nfca_pipe_info *info;
-
-	u8 pipe_list[] = { ST21NFCA_DM_GETINFO_PIPE_LIST,
-		NFC_HCI_TERMINAL_HOST_ID
-	};
-	u8 pipe_info[] = { ST21NFCA_DM_GETINFO_PIPE_INFO,
-		NFC_HCI_TERMINAL_HOST_ID, 0
-	};
-
-	/* On ST21NFCA device pipes number are dynamics
-	 * A maximum of 16 pipes can be created at the same time
-	 * 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 ST21NFCA is to:
-	 * - get a pipe list for each host.
-	 * (eg: NFC_HCI_HOST_CONTROLLER_ID for now).
-	 * (TODO Later on UICC HOST and eSE HOST)
-	 * - get pipe information
-	 * - match retrieved pipe list in st21nfca_gates
-	 * ST21NFCA_DEVICE_MGNT_GATE is a proprietary gate
-	 * with ST21NFCA_DEVICE_MGNT_PIPE.
-	 * Pipe can be closed and need to be open.
-	 */
-	r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID,
-				ST21NFCA_DEVICE_MGNT_GATE,
-				ST21NFCA_DEVICE_MGNT_PIPE);
-	if (r < 0)
-		return r;
-
-	/* Get pipe list */
-	r = nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE,
-			ST21NFCA_DM_GETINFO, pipe_list, sizeof(pipe_list),
-			&skb_pipe_list);
-	if (r < 0)
-		return r;
-
-	/* Complete the existing gate_pipe table */
-	for (i = 0; i < skb_pipe_list->len; i++) {
-		pipe_info[2] = skb_pipe_list->data[i];
-		r = nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE,
-					ST21NFCA_DM_GETINFO, pipe_info,
-					sizeof(pipe_info), &skb_pipe_info);
-
-		if (r)
-			continue;
-
-		/*
-		 * Match pipe ID and gate ID
-		 * Output format from ST21NFC_DM_GETINFO is:
-		 * - pipe state (1byte)
-		 * - source hid (1byte)
-		 * - source gid (1byte)
-		 * - destination hid (1byte)
-		 * - destination gid (1byte)
-		 */
-		info = (struct st21nfca_pipe_info *) skb_pipe_info->data;
-		if (info->dst_gate_id == ST21NFCA_APDU_READER_GATE &&
-			info->src_host_id != ST21NFCA_ESE_HOST_ID) {
-			pr_err("Unexpected apdu_reader pipe on host %x\n",
-				info->src_host_id);
-			kfree_skb(skb_pipe_info);
-			continue;
-		}
-
-		for (j = 0; (j < ARRAY_SIZE(st21nfca_gates)) &&
-			(st21nfca_gates[j].gate != info->dst_gate_id) ; j++)
-			;
-
-		if (j < ARRAY_SIZE(st21nfca_gates) &&
-			st21nfca_gates[j].gate == info->dst_gate_id &&
-			ST21NFCA_DM_IS_PIPE_OPEN(info->pipe_state)) {
-			st21nfca_gates[j].pipe = pipe_info[2];
-
-			hdev->gate2pipe[st21nfca_gates[j].gate] =
-							st21nfca_gates[j].pipe;
-			hdev->pipes[st21nfca_gates[j].pipe].gate =
-							st21nfca_gates[j].gate;
-			hdev->pipes[st21nfca_gates[j].pipe].dest_host =
-							info->src_host_id;
-		}
-		kfree_skb(skb_pipe_info);
-	}
-
-	/*
-	 * 3 gates have a well known pipe ID.
-	 * They will never appear in the pipe list
-	 */
-	if (skb_pipe_list->len + 3 < ARRAY_SIZE(st21nfca_gates)) {
-		for (i = skb_pipe_list->len + 3;
-				i < ARRAY_SIZE(st21nfca_gates) - 2; i++) {
-			r = nfc_hci_connect_gate(hdev,
-					NFC_HCI_HOST_CONTROLLER_ID,
-					st21nfca_gates[i].gate,
-					st21nfca_gates[i].pipe);
-			if (r < 0)
-				goto free_list;
-		}
-	}
-
-	memcpy(hdev->init_data.gates, st21nfca_gates, sizeof(st21nfca_gates));
-free_list:
-	kfree_skb(skb_pipe_list);
-	return r;
-}
-
-static int st21nfca_hci_open(struct nfc_hci_dev *hdev)
-{
-	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
-	int r;
-
-	mutex_lock(&info->info_lock);
-
-	if (info->state != ST21NFCA_ST_COLD) {
-		r = -EBUSY;
-		goto out;
-	}
-
-	r = info->phy_ops->enable(info->phy_id);
-
-	if (r == 0)
-		info->state = ST21NFCA_ST_READY;
-
-out:
-	mutex_unlock(&info->info_lock);
-	return r;
-}
-
-static void st21nfca_hci_close(struct nfc_hci_dev *hdev)
-{
-	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
-
-	mutex_lock(&info->info_lock);
-
-	if (info->state == ST21NFCA_ST_COLD)
-		goto out;
-
-	info->phy_ops->disable(info->phy_id);
-	info->state = ST21NFCA_ST_COLD;
-
-out:
-	mutex_unlock(&info->info_lock);
-}
-
-static int st21nfca_hci_ready(struct nfc_hci_dev *hdev)
-{
-	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
-	struct sk_buff *skb;
-
-	u8 param;
-	u8 white_list[2];
-	int wl_size = 0;
-	int r;
-
-	if (info->se_status->is_ese_present &&
-		info->se_status->is_uicc_present) {
-		white_list[wl_size++] = NFC_HCI_UICC_HOST_ID;
-		white_list[wl_size++] = ST21NFCA_ESE_HOST_ID;
-	} else if (!info->se_status->is_ese_present &&
-			 info->se_status->is_uicc_present) {
-		white_list[wl_size++] = NFC_HCI_UICC_HOST_ID;
-	} else if (info->se_status->is_ese_present &&
-			!info->se_status->is_uicc_present) {
-		white_list[wl_size++] = ST21NFCA_ESE_HOST_ID;
-	}
-
-	if (wl_size) {
-		r = nfc_hci_set_param(hdev, NFC_HCI_ADMIN_GATE,
-					NFC_HCI_ADMIN_WHITELIST,
-					(u8 *) &white_list, wl_size);
-		if (r < 0)
-			return r;
-	}
-
-	/* Set NFC_MODE in device management gate to enable */
-	r = nfc_hci_get_param(hdev, ST21NFCA_DEVICE_MGNT_GATE,
-			      ST21NFCA_NFC_MODE, &skb);
-	if (r < 0)
-		return r;
-
-	param = skb->data[0];
-	kfree_skb(skb);
-	if (param == 0) {
-		param = 1;
-
-		r = nfc_hci_set_param(hdev, ST21NFCA_DEVICE_MGNT_GATE,
-					ST21NFCA_NFC_MODE, &param, 1);
-		if (r < 0)
-			return r;
-	}
-
-	r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,
-			       NFC_HCI_EVT_END_OPERATION, NULL, 0);
-	if (r < 0)
-		return r;
-
-	r = nfc_hci_get_param(hdev, NFC_HCI_ID_MGMT_GATE,
-			      NFC_HCI_ID_MGMT_VERSION_SW, &skb);
-	if (r < 0)
-		return r;
-
-	if (skb->len != FULL_VERSION_LEN) {
-		kfree_skb(skb);
-		return -EINVAL;
-	}
-
-	print_hex_dump(KERN_DEBUG, "FULL VERSION SOFTWARE INFO: ",
-		       DUMP_PREFIX_NONE, 16, 1,
-		       skb->data, FULL_VERSION_LEN, false);
-
-	kfree_skb(skb);
-
-	return 0;
-}
-
-static int st21nfca_hci_xmit(struct nfc_hci_dev *hdev, struct sk_buff *skb)
-{
-	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
-
-	return info->phy_ops->write(info->phy_id, skb);
-}
-
-static int st21nfca_hci_start_poll(struct nfc_hci_dev *hdev,
-				   u32 im_protocols, u32 tm_protocols)
-{
-	int r;
-	u32 pol_req;
-	u8 param[19];
-	struct sk_buff *datarate_skb;
-
-	pr_info(DRIVER_DESC ": %s protocols 0x%x 0x%x\n",
-		__func__, im_protocols, tm_protocols);
-
-	r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,
-			       NFC_HCI_EVT_END_OPERATION, NULL, 0);
-	if (r < 0)
-		return r;
-	if (im_protocols) {
-		/*
-		 * enable polling according to im_protocols & tm_protocols
-		 * - CLOSE pipe according to im_protocols & tm_protocols
-		 */
-		if ((NFC_HCI_RF_READER_B_GATE & im_protocols) == 0) {
-			r = nfc_hci_disconnect_gate(hdev,
-					NFC_HCI_RF_READER_B_GATE);
-			if (r < 0)
-				return r;
-		}
-
-		if ((NFC_HCI_RF_READER_A_GATE & im_protocols) == 0) {
-			r = nfc_hci_disconnect_gate(hdev,
-					NFC_HCI_RF_READER_A_GATE);
-			if (r < 0)
-				return r;
-		}
-
-		if ((ST21NFCA_RF_READER_F_GATE & im_protocols) == 0) {
-			r = nfc_hci_disconnect_gate(hdev,
-					ST21NFCA_RF_READER_F_GATE);
-			if (r < 0)
-				return r;
-		} else {
-			hdev->gb = nfc_get_local_general_bytes(hdev->ndev,
-							       &hdev->gb_len);
-
-			if (hdev->gb == NULL || hdev->gb_len == 0) {
-				im_protocols &= ~NFC_PROTO_NFC_DEP_MASK;
-				tm_protocols &= ~NFC_PROTO_NFC_DEP_MASK;
-			}
-
-			param[0] = ST21NFCA_RF_READER_F_DATARATE_106 |
-			    ST21NFCA_RF_READER_F_DATARATE_212 |
-			    ST21NFCA_RF_READER_F_DATARATE_424;
-			r = nfc_hci_set_param(hdev, ST21NFCA_RF_READER_F_GATE,
-					      ST21NFCA_RF_READER_F_DATARATE,
-					      param, 1);
-			if (r < 0)
-				return r;
-
-			pol_req = be32_to_cpu((__force __be32)
-					ST21NFCA_RF_READER_F_POL_REQ_DEFAULT);
-			r = nfc_hci_set_param(hdev, ST21NFCA_RF_READER_F_GATE,
-					      ST21NFCA_RF_READER_F_POL_REQ,
-					      (u8 *) &pol_req, 4);
-			if (r < 0)
-				return r;
-		}
-
-		if ((ST21NFCA_RF_READER_14443_3_A_GATE & im_protocols) == 0) {
-			r = nfc_hci_disconnect_gate(hdev,
-					ST21NFCA_RF_READER_14443_3_A_GATE);
-			if (r < 0)
-				return r;
-		}
-
-		if ((ST21NFCA_RF_READER_ISO15693_GATE & im_protocols) == 0) {
-			r = nfc_hci_disconnect_gate(hdev,
-					ST21NFCA_RF_READER_ISO15693_GATE);
-			if (r < 0)
-				return r;
-		}
-
-		r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,
-				       NFC_HCI_EVT_READER_REQUESTED, NULL, 0);
-		if (r < 0)
-			nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,
-					   NFC_HCI_EVT_END_OPERATION, NULL, 0);
-	}
-
-	if (tm_protocols & NFC_PROTO_NFC_DEP_MASK) {
-		r = nfc_hci_get_param(hdev, ST21NFCA_RF_CARD_F_GATE,
-				      ST21NFCA_RF_CARD_F_DATARATE,
-				      &datarate_skb);
-		if (r < 0)
-			return r;
-
-		/* Configure the maximum supported datarate to 424Kbps */
-		if (datarate_skb->len > 0 &&
-		    datarate_skb->data[0] !=
-		    ST21NFCA_RF_CARD_F_DATARATE_212_424) {
-			param[0] = ST21NFCA_RF_CARD_F_DATARATE_212_424;
-			r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE,
-					      ST21NFCA_RF_CARD_F_DATARATE,
-					      param, 1);
-			if (r < 0) {
-				kfree_skb(datarate_skb);
-				return r;
-			}
-		}
-		kfree_skb(datarate_skb);
-
-		/*
-		 * Configure sens_res
-		 *
-		 * NFC Forum Digital Spec Table 7:
-		 * NFCID1 size: triple (10 bytes)
-		 */
-		param[0] = 0x00;
-		param[1] = 0x08;
-		r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE,
-				      ST21NFCA_RF_CARD_F_SENS_RES, param, 2);
-		if (r < 0)
-			return r;
-
-		/*
-		 * Configure sel_res
-		 *
-		 * NFC Forum Digistal Spec Table 17:
-		 * b3 set to 0b (value b7-b6):
-		 * - 10b: Configured for NFC-DEP Protocol
-		 */
-		param[0] = 0x40;
-		r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE,
-				      ST21NFCA_RF_CARD_F_SEL_RES, param, 1);
-		if (r < 0)
-			return r;
-
-		/* Configure NFCID1 Random uid */
-		r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE,
-				      ST21NFCA_RF_CARD_F_NFCID1, NULL, 0);
-		if (r < 0)
-			return r;
-
-		/* Configure NFCID2_LIST */
-		/* System Code */
-		param[0] = 0x00;
-		param[1] = 0x00;
-		/* NFCID2 */
-		param[2] = 0x01;
-		param[3] = 0xfe;
-		param[4] = 'S';
-		param[5] = 'T';
-		param[6] = 'M';
-		param[7] = 'i';
-		param[8] = 'c';
-		param[9] = 'r';
-		/* 8 byte Pad bytes used for polling respone frame */
-
-		/*
-		 * Configuration byte:
-		 * - bit 0: define the default NFCID2 entry used when the
-		 * system code is equal to 'FFFF'
-		 * - bit 1: use a random value for lowest 6 bytes of
-		 * NFCID2 value
-		 * - bit 2: ignore polling request frame if request code
-		 * is equal to '01'
-		 * - Other bits are RFU
-		 */
-		param[18] = 0x01;
-		r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE,
-				      ST21NFCA_RF_CARD_F_NFCID2_LIST, param,
-				      19);
-		if (r < 0)
-			return r;
-
-		param[0] = 0x02;
-		r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE,
-				      ST21NFCA_RF_CARD_F_MODE, param, 1);
-	}
-
-	return r;
-}
-
-static void st21nfca_hci_stop_poll(struct nfc_hci_dev *hdev)
-{
-	nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE,
-			ST21NFCA_DM_DISCONNECT, NULL, 0, NULL);
-}
-
-static int st21nfca_get_iso14443_3_atqa(struct nfc_hci_dev *hdev, u16 *atqa)
-{
-	int r;
-	struct sk_buff *atqa_skb = NULL;
-
-	r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_14443_3_A_GATE,
-			      ST21NFCA_RF_READER_14443_3_A_ATQA, &atqa_skb);
-	if (r < 0)
-		goto exit;
-
-	if (atqa_skb->len != 2) {
-		r = -EPROTO;
-		goto exit;
-	}
-
-	*atqa = be16_to_cpu(*(__be16 *) atqa_skb->data);
-
-exit:
-	kfree_skb(atqa_skb);
-	return r;
-}
-
-static int st21nfca_get_iso14443_3_sak(struct nfc_hci_dev *hdev, u8 *sak)
-{
-	int r;
-	struct sk_buff *sak_skb = NULL;
-
-	r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_14443_3_A_GATE,
-			      ST21NFCA_RF_READER_14443_3_A_SAK, &sak_skb);
-	if (r < 0)
-		goto exit;
-
-	if (sak_skb->len != 1) {
-		r = -EPROTO;
-		goto exit;
-	}
-
-	*sak = sak_skb->data[0];
-
-exit:
-	kfree_skb(sak_skb);
-	return r;
-}
-
-static int st21nfca_get_iso14443_3_uid(struct nfc_hci_dev *hdev, u8 *uid,
-				       int *len)
-{
-	int r;
-	struct sk_buff *uid_skb = NULL;
-
-	r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_14443_3_A_GATE,
-			      ST21NFCA_RF_READER_14443_3_A_UID, &uid_skb);
-	if (r < 0)
-		goto exit;
-
-	if (uid_skb->len == 0 || uid_skb->len > NFC_NFCID1_MAXSIZE) {
-		r = -EPROTO;
-		goto exit;
-	}
-
-	memcpy(uid, uid_skb->data, uid_skb->len);
-	*len = uid_skb->len;
-exit:
-	kfree_skb(uid_skb);
-	return r;
-}
-
-static int st21nfca_get_iso15693_inventory(struct nfc_hci_dev *hdev,
-					   struct nfc_target *target)
-{
-	int r;
-	struct sk_buff *inventory_skb = NULL;
-
-	r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_ISO15693_GATE,
-			      ST21NFCA_RF_READER_ISO15693_INVENTORY,
-			      &inventory_skb);
-	if (r < 0)
-		goto exit;
-
-	skb_pull(inventory_skb, 2);
-
-	if (inventory_skb->len == 0 ||
-	    inventory_skb->len > NFC_ISO15693_UID_MAXSIZE) {
-		r = -EPROTO;
-		goto exit;
-	}
-
-	memcpy(target->iso15693_uid, inventory_skb->data, inventory_skb->len);
-	target->iso15693_dsfid	= inventory_skb->data[1];
-	target->is_iso15693 = 1;
-exit:
-	kfree_skb(inventory_skb);
-	return r;
-}
-
-static int st21nfca_hci_dep_link_up(struct nfc_hci_dev *hdev,
-				    struct nfc_target *target, u8 comm_mode,
-				    u8 *gb, size_t gb_len)
-{
-	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
-
-	info->dep_info.idx = target->idx;
-	return st21nfca_im_send_atr_req(hdev, gb, gb_len);
-}
-
-static int st21nfca_hci_dep_link_down(struct nfc_hci_dev *hdev)
-{
-	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
-
-	info->state = ST21NFCA_ST_READY;
-
-	return nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE,
-				ST21NFCA_DM_DISCONNECT, NULL, 0, NULL);
-}
-
-static int st21nfca_hci_target_from_gate(struct nfc_hci_dev *hdev, u8 gate,
-					 struct nfc_target *target)
-{
-	int r, len;
-	u16 atqa;
-	u8 sak;
-	u8 uid[NFC_NFCID1_MAXSIZE];
-
-	switch (gate) {
-	case ST21NFCA_RF_READER_F_GATE:
-		target->supported_protocols = NFC_PROTO_FELICA_MASK;
-		break;
-	case ST21NFCA_RF_READER_14443_3_A_GATE:
-		/* ISO14443-3 type 1 or 2 tags */
-		r = st21nfca_get_iso14443_3_atqa(hdev, &atqa);
-		if (r < 0)
-			return r;
-		if (atqa == 0x000c) {
-			target->supported_protocols = NFC_PROTO_JEWEL_MASK;
-			target->sens_res = 0x0c00;
-		} else {
-			r = st21nfca_get_iso14443_3_sak(hdev, &sak);
-			if (r < 0)
-				return r;
-
-			r = st21nfca_get_iso14443_3_uid(hdev, uid, &len);
-			if (r < 0)
-				return r;
-
-			target->supported_protocols =
-			    nfc_hci_sak_to_protocol(sak);
-			if (target->supported_protocols == 0xffffffff)
-				return -EPROTO;
-
-			target->sens_res = atqa;
-			target->sel_res = sak;
-			memcpy(target->nfcid1, uid, len);
-			target->nfcid1_len = len;
-		}
-
-		break;
-	case ST21NFCA_RF_READER_ISO15693_GATE:
-		target->supported_protocols = NFC_PROTO_ISO15693_MASK;
-		r = st21nfca_get_iso15693_inventory(hdev, target);
-		if (r < 0)
-			return r;
-		break;
-	default:
-		return -EPROTO;
-	}
-
-	return 0;
-}
-
-static int st21nfca_hci_complete_target_discovered(struct nfc_hci_dev *hdev,
-						u8 gate,
-						struct nfc_target *target)
-{
-	int r;
-	struct sk_buff *nfcid_skb = NULL;
-
-	if (gate == ST21NFCA_RF_READER_F_GATE) {
-		r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_F_GATE,
-				ST21NFCA_RF_READER_F_NFCID2, &nfcid_skb);
-		if (r < 0)
-			goto exit;
-
-		if (nfcid_skb->len > NFC_SENSF_RES_MAXSIZE) {
-			r = -EPROTO;
-			goto exit;
-		}
-
-		/*
-		 * - After the recepton of polling response for type F frame
-		 * at 212 or 424 Kbit/s, NFCID2 registry parameters will be
-		 * updated.
-		 * - After the reception of SEL_RES with NFCIP-1 compliant bit
-		 * set for type A frame NFCID1 will be updated
-		 */
-		if (nfcid_skb->len > 0) {
-			/* P2P in type F */
-			memcpy(target->sensf_res, nfcid_skb->data,
-				nfcid_skb->len);
-			target->sensf_res_len = nfcid_skb->len;
-			/* NFC Forum Digital Protocol Table 44 */
-			if (target->sensf_res[0] == 0x01 &&
-			    target->sensf_res[1] == 0xfe)
-				target->supported_protocols =
-							NFC_PROTO_NFC_DEP_MASK;
-			else
-				target->supported_protocols =
-							NFC_PROTO_FELICA_MASK;
-		} else {
-			kfree_skb(nfcid_skb);
-			/* P2P in type A */
-			r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_F_GATE,
-					ST21NFCA_RF_READER_F_NFCID1,
-					&nfcid_skb);
-			if (r < 0)
-				goto exit;
-
-			if (nfcid_skb->len > NFC_NFCID1_MAXSIZE) {
-				r = -EPROTO;
-				goto exit;
-			}
-			memcpy(target->sensf_res, nfcid_skb->data,
-				nfcid_skb->len);
-			target->sensf_res_len = nfcid_skb->len;
-			target->supported_protocols = NFC_PROTO_NFC_DEP_MASK;
-		}
-		target->hci_reader_gate = ST21NFCA_RF_READER_F_GATE;
-	}
-	r = 1;
-exit:
-	kfree_skb(nfcid_skb);
-	return r;
-}
-
-#define ST21NFCA_CB_TYPE_READER_ISO15693 1
-static void st21nfca_hci_data_exchange_cb(void *context, struct sk_buff *skb,
-					  int err)
-{
-	struct st21nfca_hci_info *info = context;
-
-	switch (info->async_cb_type) {
-	case ST21NFCA_CB_TYPE_READER_ISO15693:
-		if (err == 0)
-			skb_trim(skb, skb->len - 1);
-		info->async_cb(info->async_cb_context, skb, err);
-		break;
-	default:
-		if (err == 0)
-			kfree_skb(skb);
-		break;
-	}
-}
-
-/*
- * Returns:
- * <= 0: driver handled the data exchange
- *    1: driver doesn't especially handle, please do standard processing
- */
-static int st21nfca_hci_im_transceive(struct nfc_hci_dev *hdev,
-				      struct nfc_target *target,
-				      struct sk_buff *skb,
-				      data_exchange_cb_t cb, void *cb_context)
-{
-	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
-
-	pr_info(DRIVER_DESC ": %s for gate=%d len=%d\n", __func__,
-		target->hci_reader_gate, skb->len);
-
-	switch (target->hci_reader_gate) {
-	case ST21NFCA_RF_READER_F_GATE:
-		if (target->supported_protocols == NFC_PROTO_NFC_DEP_MASK)
-			return st21nfca_im_send_dep_req(hdev, skb);
-
-		*skb_push(skb, 1) = 0x1a;
-		return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate,
-					      ST21NFCA_WR_XCHG_DATA, skb->data,
-					      skb->len, cb, cb_context);
-	case ST21NFCA_RF_READER_14443_3_A_GATE:
-		*skb_push(skb, 1) = 0x1a;	/* CTR, see spec:10.2.2.1 */
-
-		return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate,
-					      ST21NFCA_WR_XCHG_DATA, skb->data,
-					      skb->len, cb, cb_context);
-	case ST21NFCA_RF_READER_ISO15693_GATE:
-		info->async_cb_type = ST21NFCA_CB_TYPE_READER_ISO15693;
-		info->async_cb = cb;
-		info->async_cb_context = cb_context;
-
-		*skb_push(skb, 1) = 0x17;
-
-		return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate,
-					      ST21NFCA_WR_XCHG_DATA, skb->data,
-					      skb->len,
-					      st21nfca_hci_data_exchange_cb,
-					      info);
-		break;
-	default:
-		return 1;
-	}
-}
-
-static int st21nfca_hci_tm_send(struct nfc_hci_dev *hdev, struct sk_buff *skb)
-{
-	return st21nfca_tm_send_dep_res(hdev, skb);
-}
-
-static int st21nfca_hci_check_presence(struct nfc_hci_dev *hdev,
-				       struct nfc_target *target)
-{
-	u8 fwi = 0x11;
-
-	switch (target->hci_reader_gate) {
-	case NFC_HCI_RF_READER_A_GATE:
-	case NFC_HCI_RF_READER_B_GATE:
-		/*
-		 * PRESENCE_CHECK on those gates is available
-		 * However, the answer to this command is taking 3 * fwi
-		 * if the card is no present.
-		 * Instead, we send an empty I-Frame with a very short
-		 * configurable fwi ~604µs.
-		 */
-		return nfc_hci_send_cmd(hdev, target->hci_reader_gate,
-					ST21NFCA_WR_XCHG_DATA, &fwi, 1, NULL);
-	case ST21NFCA_RF_READER_14443_3_A_GATE:
-		return nfc_hci_send_cmd(hdev, target->hci_reader_gate,
-					ST21NFCA_RF_READER_CMD_PRESENCE_CHECK,
-					NULL, 0, NULL);
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-static void st21nfca_hci_cmd_received(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd,
-				struct sk_buff *skb)
-{
-	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
-	u8 gate = hdev->pipes[pipe].gate;
-
-	pr_debug("cmd: %x\n", cmd);
-
-	switch (cmd) {
-	case NFC_HCI_ANY_OPEN_PIPE:
-		if (gate != ST21NFCA_APDU_READER_GATE &&
-			hdev->pipes[pipe].dest_host != NFC_HCI_UICC_HOST_ID)
-			info->se_info.count_pipes++;
-
-		if (info->se_info.count_pipes == info->se_info.expected_pipes) {
-			del_timer_sync(&info->se_info.se_active_timer);
-			info->se_info.se_active = false;
-			info->se_info.count_pipes = 0;
-			complete(&info->se_info.req_completion);
-		}
-	break;
-	}
-}
-
-static int st21nfca_admin_event_received(struct nfc_hci_dev *hdev, u8 event,
-					struct sk_buff *skb)
-{
-	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
-
-	pr_debug("admin event: %x\n", event);
-
-	switch (event) {
-	case ST21NFCA_EVT_HOT_PLUG:
-		if (info->se_info.se_active) {
-			if (!ST21NFCA_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(ST21NFCA_SE_TO_PIPES));
-			}
-		}
-	break;
-	}
-	kfree_skb(skb);
-	return 0;
-}
-
-/*
- * Returns:
- * <= 0: driver handled the event, skb consumed
- *    1: driver does not handle the event, please do standard processing
- */
-static int st21nfca_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe,
-				       u8 event, struct sk_buff *skb)
-{
-	u8 gate = hdev->pipes[pipe].gate;
-	u8 host = hdev->pipes[pipe].dest_host;
-
-	pr_debug("hci event: %d gate: %x\n", event, gate);
-
-	switch (gate) {
-	case NFC_HCI_ADMIN_GATE:
-		return st21nfca_admin_event_received(hdev, event, skb);
-	case ST21NFCA_RF_CARD_F_GATE:
-		return st21nfca_dep_event_received(hdev, event, skb);
-	case ST21NFCA_CONNECTIVITY_GATE:
-		return st21nfca_connectivity_event_received(hdev, host,
-							event, skb);
-	case ST21NFCA_APDU_READER_GATE:
-		return st21nfca_apdu_reader_event_received(hdev, event, skb);
-	default:
-		return 1;
-	}
-}
-
-static struct nfc_hci_ops st21nfca_hci_ops = {
-	.open = st21nfca_hci_open,
-	.close = st21nfca_hci_close,
-	.load_session = st21nfca_hci_load_session,
-	.hci_ready = st21nfca_hci_ready,
-	.xmit = st21nfca_hci_xmit,
-	.start_poll = st21nfca_hci_start_poll,
-	.stop_poll = st21nfca_hci_stop_poll,
-	.dep_link_up = st21nfca_hci_dep_link_up,
-	.dep_link_down = st21nfca_hci_dep_link_down,
-	.target_from_gate = st21nfca_hci_target_from_gate,
-	.complete_target_discovered = st21nfca_hci_complete_target_discovered,
-	.im_transceive = st21nfca_hci_im_transceive,
-	.tm_send = st21nfca_hci_tm_send,
-	.check_presence = st21nfca_hci_check_presence,
-	.event_received = st21nfca_hci_event_received,
-	.cmd_received = st21nfca_hci_cmd_received,
-	.discover_se = st21nfca_hci_discover_se,
-	.enable_se = st21nfca_hci_enable_se,
-	.disable_se = st21nfca_hci_disable_se,
-	.se_io = st21nfca_hci_se_io,
-};
-
-int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops,
-		       char *llc_name, int phy_headroom, int phy_tailroom,
-		       int phy_payload, struct nfc_hci_dev **hdev,
-			   struct st21nfca_se_status *se_status)
-{
-	struct st21nfca_hci_info *info;
-	int r = 0;
-	int dev_num;
-	u32 protocols;
-	struct nfc_hci_init_data init_data;
-	unsigned long quirks = 0;
-
-	info = kzalloc(sizeof(struct st21nfca_hci_info), GFP_KERNEL);
-	if (!info) {
-		r = -ENOMEM;
-		goto err_alloc_hdev;
-	}
-
-	info->phy_ops = phy_ops;
-	info->phy_id = phy_id;
-	info->state = ST21NFCA_ST_COLD;
-	mutex_init(&info->info_lock);
-
-	init_data.gate_count = ARRAY_SIZE(st21nfca_gates);
-
-	memcpy(init_data.gates, st21nfca_gates, sizeof(st21nfca_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, ST21NFCA_NUM_DEVICES);
-
-	if (dev_num >= ST21NFCA_NUM_DEVICES)
-		return -ENODEV;
-
-	set_bit(dev_num, dev_mask);
-
-	scnprintf(init_data.session_id, sizeof(init_data.session_id), "%s%2x",
-		  "ST21AH", dev_num);
-
-	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;
-
-	set_bit(NFC_HCI_QUIRK_SHORT_CLEAR, &quirks);
-
-	info->hdev =
-	    nfc_hci_allocate_device(&st21nfca_hci_ops, &init_data, quirks,
-				    protocols, llc_name,
-				    phy_headroom + ST21NFCA_CMDS_HEADROOM,
-				    phy_tailroom, phy_payload);
-
-	if (!info->hdev) {
-		pr_err("Cannot allocate nfc hdev.\n");
-		r = -ENOMEM;
-		goto err_alloc_hdev;
-	}
-
-	info->se_status = se_status;
-
-	nfc_hci_set_clientdata(info->hdev, info);
-
-	r = nfc_hci_register_device(info->hdev);
-	if (r)
-		goto err_regdev;
-
-	*hdev = info->hdev;
-	st21nfca_dep_init(info->hdev);
-	st21nfca_se_init(info->hdev);
-
-	return 0;
-
-err_regdev:
-	nfc_hci_free_device(info->hdev);
-
-err_alloc_hdev:
-	kfree(info);
-
-	return r;
-}
-EXPORT_SYMBOL(st21nfca_hci_probe);
-
-void st21nfca_hci_remove(struct nfc_hci_dev *hdev)
-{
-	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
-
-	st21nfca_dep_deinit(hdev);
-	st21nfca_se_deinit(hdev);
-	nfc_hci_unregister_device(hdev);
-	nfc_hci_free_device(hdev);
-	kfree(info);
-}
-EXPORT_SYMBOL(st21nfca_hci_remove);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/nfc/st21nfca/st21nfca.h b/drivers/nfc/st21nfca/st21nfca.h
index 15a78d3..70e2d43 100644
--- a/drivers/nfc/st21nfca/st21nfca.h
+++ b/drivers/nfc/st21nfca/st21nfca.h
@@ -18,9 +18,8 @@
 #define __LOCAL_ST21NFCA_H_
 
 #include <net/nfc/hci.h>
-
-#include "st21nfca_dep.h"
-#include "st21nfca_se.h"
+#include <linux/skbuff.h>
+#include <linux/workqueue.h>
 
 #define HCI_MODE 0
 
@@ -46,28 +45,68 @@
 #define ST21NFCA_HCI_LLC_MAX_SIZE       (ST21NFCA_HCI_LLC_LEN_CRC + 1 + \
 					ST21NFCA_HCI_LLC_MAX_PAYLOAD)
 
-#define DRIVER_DESC "HCI NFC driver for ST21NFCA"
+/* Reader RF commands */
+#define ST21NFCA_WR_XCHG_DATA           0x10
+
+#define ST21NFCA_DEVICE_MGNT_GATE       0x01
+#define ST21NFCA_RF_READER_F_GATE       0x14
+#define ST21NFCA_RF_CARD_F_GATE		0x24
+#define ST21NFCA_APDU_READER_GATE	0xf0
+#define ST21NFCA_CONNECTIVITY_GATE	0x41
 
-#define ST21NFCA_HCI_MODE 0
+/*
+ * ref ISO7816-3 chap 8.1. the initial character TS is followed by a
+ * sequence of at most 32 characters.
+ */
+#define ST21NFCA_ESE_MAX_LENGTH		33
+#define ST21NFCA_ESE_HOST_ID		0xc0
+
+#define DRIVER_DESC "HCI NFC driver for ST21NFCA"
 
-#define ST21NFCA_NUM_DEVICES 256
+#define ST21NFCA_HCI_MODE		0
+#define ST21NFCA_NUM_DEVICES		256
 
 struct st21nfca_se_status {
 	bool is_ese_present;
 	bool is_uicc_present;
 };
 
-int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops,
-		       char *llc_name, int phy_headroom, int phy_tailroom,
-		       int phy_payload, struct nfc_hci_dev **hdev,
-			   struct st21nfca_se_status *se_status);
-void st21nfca_hci_remove(struct nfc_hci_dev *hdev);
-
 enum st21nfca_state {
 	ST21NFCA_ST_COLD,
 	ST21NFCA_ST_READY,
 };
 
+struct st21nfca_dep_info {
+	struct sk_buff *tx_pending;
+	struct work_struct tx_work;
+	u8 curr_nfc_dep_pni;
+	u32 idx;
+	u8 to;
+	u8 did;
+	u8 bsi;
+	u8 bri;
+	u8 lri;
+} __packed;
+
+struct st21nfca_se_info {
+	u8 atr[ST21NFCA_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;
+	int expected_pipes;
+	int count_pipes;
+
+	bool xch_error;
+
+	se_io_cb_t cb;
+	void *cb_context;
+};
+
 struct st21nfca_hci_info {
 	struct nfc_phy_ops *phy_ops;
 	void *phy_id;
@@ -87,13 +126,34 @@ struct st21nfca_hci_info {
 	struct st21nfca_se_info se_info;
 };
 
-/* Reader RF commands */
-#define ST21NFCA_WR_XCHG_DATA           0x10
+int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops,
+		       char *llc_name, int phy_headroom, int phy_tailroom,
+		       int phy_payload, struct nfc_hci_dev **hdev,
+			   struct st21nfca_se_status *se_status);
+void st21nfca_hci_remove(struct nfc_hci_dev *hdev);
 
-#define ST21NFCA_DEVICE_MGNT_GATE       0x01
-#define ST21NFCA_RF_READER_F_GATE       0x14
-#define ST21NFCA_RF_CARD_F_GATE			0x24
-#define ST21NFCA_APDU_READER_GATE		0xf0
-#define ST21NFCA_CONNECTIVITY_GATE		0x41
+int st21nfca_dep_event_received(struct nfc_hci_dev *hdev,
+				u8 event, struct sk_buff *skb);
+int st21nfca_tm_send_dep_res(struct nfc_hci_dev *hdev, struct sk_buff *skb);
+
+int st21nfca_im_send_atr_req(struct nfc_hci_dev *hdev, u8 *gb, size_t gb_len);
+int st21nfca_im_send_dep_req(struct nfc_hci_dev *hdev, struct sk_buff *skb);
+void st21nfca_dep_init(struct nfc_hci_dev *hdev);
+void st21nfca_dep_deinit(struct nfc_hci_dev *hdev);
+
+int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host,
+					u8 event, struct sk_buff *skb);
+int st21nfca_apdu_reader_event_received(struct nfc_hci_dev *hdev,
+					u8 event, struct sk_buff *skb);
+
+int st21nfca_hci_discover_se(struct nfc_hci_dev *hdev);
+int st21nfca_hci_enable_se(struct nfc_hci_dev *hdev, u32 se_idx);
+int st21nfca_hci_disable_se(struct nfc_hci_dev *hdev, u32 se_idx);
+int st21nfca_hci_se_io(struct nfc_hci_dev *hdev, u32 se_idx,
+		u8 *apdu, size_t apdu_length,
+		se_io_cb_t cb, void *cb_context);
+
+void st21nfca_se_init(struct nfc_hci_dev *hdev);
+void st21nfca_se_deinit(struct nfc_hci_dev *hdev);
 
 #endif /* __LOCAL_ST21NFCA_H_ */
diff --git a/drivers/nfc/st21nfca/st21nfca_dep.c b/drivers/nfc/st21nfca/st21nfca_dep.c
deleted file mode 100644
index 8882181..0000000
--- a/drivers/nfc/st21nfca/st21nfca_dep.c
+++ /dev/null
@@ -1,689 +0,0 @@
-/*
- * 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 <net/nfc/hci.h>
-
-#include "st21nfca.h"
-#include "st21nfca_dep.h"
-
-#define ST21NFCA_NFCIP1_INITIATOR 0x00
-#define ST21NFCA_NFCIP1_REQ 0xd4
-#define ST21NFCA_NFCIP1_RES 0xd5
-#define ST21NFCA_NFCIP1_ATR_REQ 0x00
-#define ST21NFCA_NFCIP1_ATR_RES 0x01
-#define ST21NFCA_NFCIP1_PSL_REQ 0x04
-#define ST21NFCA_NFCIP1_PSL_RES 0x05
-#define ST21NFCA_NFCIP1_DEP_REQ 0x06
-#define ST21NFCA_NFCIP1_DEP_RES 0x07
-
-#define ST21NFCA_NFC_DEP_PFB_PNI(pfb)     ((pfb) & 0x03)
-#define ST21NFCA_NFC_DEP_PFB_TYPE(pfb) ((pfb) & 0xE0)
-#define ST21NFCA_NFC_DEP_PFB_IS_TIMEOUT(pfb) \
-				((pfb) & ST21NFCA_NFC_DEP_PFB_TIMEOUT_BIT)
-#define ST21NFCA_NFC_DEP_DID_BIT_SET(pfb) ((pfb) & 0x04)
-#define ST21NFCA_NFC_DEP_NAD_BIT_SET(pfb) ((pfb) & 0x08)
-#define ST21NFCA_NFC_DEP_PFB_TIMEOUT_BIT 0x10
-
-#define ST21NFCA_NFC_DEP_PFB_IS_TIMEOUT(pfb) \
-				((pfb) & ST21NFCA_NFC_DEP_PFB_TIMEOUT_BIT)
-
-#define ST21NFCA_NFC_DEP_PFB_I_PDU          0x00
-#define ST21NFCA_NFC_DEP_PFB_ACK_NACK_PDU   0x40
-#define ST21NFCA_NFC_DEP_PFB_SUPERVISOR_PDU 0x80
-
-#define ST21NFCA_ATR_REQ_MIN_SIZE 17
-#define ST21NFCA_ATR_REQ_MAX_SIZE 65
-#define ST21NFCA_LR_BITS_PAYLOAD_SIZE_254B 0x30
-#define ST21NFCA_GB_BIT  0x02
-
-#define ST21NFCA_EVT_SEND_DATA		0x10
-#define ST21NFCA_EVT_FIELD_ON           0x11
-#define ST21NFCA_EVT_CARD_DEACTIVATED   0x12
-#define ST21NFCA_EVT_CARD_ACTIVATED     0x13
-#define ST21NFCA_EVT_FIELD_OFF          0x14
-
-#define ST21NFCA_EVT_CARD_F_BITRATE 0x16
-#define ST21NFCA_EVT_READER_F_BITRATE 0x13
-#define	ST21NFCA_PSL_REQ_SEND_SPEED(brs) (brs & 0x38)
-#define ST21NFCA_PSL_REQ_RECV_SPEED(brs) (brs & 0x07)
-#define ST21NFCA_PP2LRI(pp) ((pp & 0x30) >> 4)
-#define ST21NFCA_CARD_BITRATE_212 0x01
-#define ST21NFCA_CARD_BITRATE_424 0x02
-
-#define ST21NFCA_DEFAULT_TIMEOUT 0x0a
-
-
-#define PROTOCOL_ERR(req) pr_err("%d: ST21NFCA Protocol error: %s\n", \
-				 __LINE__, req)
-
-struct st21nfca_atr_req {
-	u8 length;
-	u8 cmd0;
-	u8 cmd1;
-	u8 nfcid3[NFC_NFCID3_MAXSIZE];
-	u8 did;
-	u8 bsi;
-	u8 bri;
-	u8 ppi;
-	u8 gbi[0];
-} __packed;
-
-struct st21nfca_atr_res {
-	u8 length;
-	u8 cmd0;
-	u8 cmd1;
-	u8 nfcid3[NFC_NFCID3_MAXSIZE];
-	u8 did;
-	u8 bsi;
-	u8 bri;
-	u8 to;
-	u8 ppi;
-	u8 gbi[0];
-} __packed;
-
-struct st21nfca_psl_req {
-	u8 length;
-	u8 cmd0;
-	u8 cmd1;
-	u8 did;
-	u8 brs;
-	u8 fsl;
-} __packed;
-
-struct st21nfca_psl_res {
-	u8 length;
-	u8 cmd0;
-	u8 cmd1;
-	u8 did;
-} __packed;
-
-struct st21nfca_dep_req_res {
-	u8 length;
-	u8 cmd0;
-	u8 cmd1;
-	u8 pfb;
-	u8 did;
-	u8 nad;
-} __packed;
-
-static void st21nfca_tx_work(struct work_struct *work)
-{
-	struct st21nfca_hci_info *info = container_of(work,
-						struct st21nfca_hci_info,
-						dep_info.tx_work);
-
-	struct nfc_dev *dev;
-	struct sk_buff *skb;
-
-	if (info) {
-		dev = info->hdev->ndev;
-		skb = info->dep_info.tx_pending;
-
-		device_lock(&dev->dev);
-
-		nfc_hci_send_cmd_async(info->hdev, ST21NFCA_RF_READER_F_GATE,
-				ST21NFCA_WR_XCHG_DATA, skb->data, skb->len,
-				info->async_cb, info);
-		device_unlock(&dev->dev);
-		kfree_skb(skb);
-	}
-}
-
-static void st21nfca_im_send_pdu(struct st21nfca_hci_info *info,
-						struct sk_buff *skb)
-{
-	info->dep_info.tx_pending = skb;
-	schedule_work(&info->dep_info.tx_work);
-}
-
-static int st21nfca_tm_send_atr_res(struct nfc_hci_dev *hdev,
-				    struct st21nfca_atr_req *atr_req)
-{
-	struct st21nfca_atr_res *atr_res;
-	struct sk_buff *skb;
-	size_t gb_len;
-	int r;
-	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
-
-	gb_len = atr_req->length - sizeof(struct st21nfca_atr_req);
-	skb = alloc_skb(atr_req->length + 1, GFP_KERNEL);
-	if (!skb)
-		return -ENOMEM;
-
-	skb_put(skb, sizeof(struct st21nfca_atr_res));
-
-	atr_res = (struct st21nfca_atr_res *)skb->data;
-	memset(atr_res, 0, sizeof(struct st21nfca_atr_res));
-
-	atr_res->length = atr_req->length + 1;
-	atr_res->cmd0 = ST21NFCA_NFCIP1_RES;
-	atr_res->cmd1 = ST21NFCA_NFCIP1_ATR_RES;
-
-	memcpy(atr_res->nfcid3, atr_req->nfcid3, 6);
-	atr_res->bsi = 0x00;
-	atr_res->bri = 0x00;
-	atr_res->to = ST21NFCA_DEFAULT_TIMEOUT;
-	atr_res->ppi = ST21NFCA_LR_BITS_PAYLOAD_SIZE_254B;
-
-	if (gb_len) {
-		skb_put(skb, gb_len);
-
-		atr_res->ppi |= ST21NFCA_GB_BIT;
-		memcpy(atr_res->gbi, atr_req->gbi, gb_len);
-		r = nfc_set_remote_general_bytes(hdev->ndev, atr_res->gbi,
-						  gb_len);
-		if (r < 0)
-			return r;
-	}
-
-	info->dep_info.curr_nfc_dep_pni = 0;
-
-	r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE,
-				ST21NFCA_EVT_SEND_DATA, skb->data, skb->len);
-	kfree_skb(skb);
-	return r;
-}
-
-static int st21nfca_tm_recv_atr_req(struct nfc_hci_dev *hdev,
-				    struct sk_buff *skb)
-{
-	struct st21nfca_atr_req *atr_req;
-	size_t gb_len;
-	int r;
-
-	skb_trim(skb, skb->len - 1);
-
-	if (!skb->len) {
-		r = -EIO;
-		goto exit;
-	}
-
-	if (skb->len < ST21NFCA_ATR_REQ_MIN_SIZE) {
-		r = -EPROTO;
-		goto exit;
-	}
-
-	atr_req = (struct st21nfca_atr_req *)skb->data;
-
-	if (atr_req->length < sizeof(struct st21nfca_atr_req)) {
-		r = -EPROTO;
-		goto exit;
-	}
-
-	r = st21nfca_tm_send_atr_res(hdev, atr_req);
-	if (r)
-		goto exit;
-
-	gb_len = skb->len - sizeof(struct st21nfca_atr_req);
-
-	r = nfc_tm_activated(hdev->ndev, NFC_PROTO_NFC_DEP_MASK,
-			      NFC_COMM_PASSIVE, atr_req->gbi, gb_len);
-	if (r)
-		goto exit;
-
-	r = 0;
-
-exit:
-	return r;
-}
-
-static int st21nfca_tm_send_psl_res(struct nfc_hci_dev *hdev,
-				    struct st21nfca_psl_req *psl_req)
-{
-	struct st21nfca_psl_res *psl_res;
-	struct sk_buff *skb;
-	u8 bitrate[2] = {0, 0};
-	int r;
-
-	skb = alloc_skb(sizeof(struct st21nfca_psl_res), GFP_KERNEL);
-	if (!skb)
-		return -ENOMEM;
-	skb_put(skb, sizeof(struct st21nfca_psl_res));
-
-	psl_res = (struct st21nfca_psl_res *)skb->data;
-
-	psl_res->length = sizeof(struct st21nfca_psl_res);
-	psl_res->cmd0 = ST21NFCA_NFCIP1_RES;
-	psl_res->cmd1 = ST21NFCA_NFCIP1_PSL_RES;
-	psl_res->did = psl_req->did;
-
-	r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE,
-				ST21NFCA_EVT_SEND_DATA, skb->data, skb->len);
-	if (r < 0)
-		goto error;
-
-	/*
-	 * ST21NFCA only support P2P passive.
-	 * PSL_REQ BRS value != 0 has only a meaning to
-	 * change technology to type F.
-	 * We change to BITRATE 424Kbits.
-	 * In other case switch to BITRATE 106Kbits.
-	 */
-	if (ST21NFCA_PSL_REQ_SEND_SPEED(psl_req->brs) &&
-	    ST21NFCA_PSL_REQ_RECV_SPEED(psl_req->brs)) {
-		bitrate[0] = ST21NFCA_CARD_BITRATE_424;
-		bitrate[1] = ST21NFCA_CARD_BITRATE_424;
-	}
-
-	/* Send an event to change bitrate change event to card f */
-	r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE,
-			ST21NFCA_EVT_CARD_F_BITRATE, bitrate, 2);
-error:
-	kfree_skb(skb);
-	return r;
-}
-
-static int st21nfca_tm_recv_psl_req(struct nfc_hci_dev *hdev,
-				    struct sk_buff *skb)
-{
-	struct st21nfca_psl_req *psl_req;
-	int r;
-
-	skb_trim(skb, skb->len - 1);
-
-	if (!skb->len) {
-		r = -EIO;
-		goto exit;
-	}
-
-	psl_req = (struct st21nfca_psl_req *)skb->data;
-
-	if (skb->len < sizeof(struct st21nfca_psl_req)) {
-		r = -EIO;
-		goto exit;
-	}
-
-	r = st21nfca_tm_send_psl_res(hdev, psl_req);
-exit:
-	return r;
-}
-
-int st21nfca_tm_send_dep_res(struct nfc_hci_dev *hdev, struct sk_buff *skb)
-{
-	int r;
-	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
-
-	*skb_push(skb, 1) = info->dep_info.curr_nfc_dep_pni;
-	*skb_push(skb, 1) = ST21NFCA_NFCIP1_DEP_RES;
-	*skb_push(skb, 1) = ST21NFCA_NFCIP1_RES;
-	*skb_push(skb, 1) = skb->len;
-
-	r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE,
-			ST21NFCA_EVT_SEND_DATA, skb->data, skb->len);
-	kfree_skb(skb);
-
-	return r;
-}
-EXPORT_SYMBOL(st21nfca_tm_send_dep_res);
-
-static int st21nfca_tm_recv_dep_req(struct nfc_hci_dev *hdev,
-				    struct sk_buff *skb)
-{
-	struct st21nfca_dep_req_res *dep_req;
-	u8 size;
-	int r;
-	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
-
-	skb_trim(skb, skb->len - 1);
-
-	size = 4;
-
-	dep_req = (struct st21nfca_dep_req_res *)skb->data;
-	if (skb->len < size) {
-		r = -EIO;
-		goto exit;
-	}
-
-	if (ST21NFCA_NFC_DEP_DID_BIT_SET(dep_req->pfb))
-		size++;
-	if (ST21NFCA_NFC_DEP_NAD_BIT_SET(dep_req->pfb))
-		size++;
-
-	if (skb->len < size) {
-		r = -EIO;
-		goto exit;
-	}
-
-	/* Receiving DEP_REQ - Decoding */
-	switch (ST21NFCA_NFC_DEP_PFB_TYPE(dep_req->pfb)) {
-	case ST21NFCA_NFC_DEP_PFB_I_PDU:
-		info->dep_info.curr_nfc_dep_pni =
-				ST21NFCA_NFC_DEP_PFB_PNI(dep_req->pfb);
-		break;
-	case ST21NFCA_NFC_DEP_PFB_ACK_NACK_PDU:
-		pr_err("Received a ACK/NACK PDU\n");
-		break;
-	case ST21NFCA_NFC_DEP_PFB_SUPERVISOR_PDU:
-		pr_err("Received a SUPERVISOR PDU\n");
-		break;
-	}
-
-	skb_pull(skb, size);
-
-	return nfc_tm_data_received(hdev->ndev, skb);
-exit:
-	return r;
-}
-
-static int st21nfca_tm_event_send_data(struct nfc_hci_dev *hdev,
-				struct sk_buff *skb)
-{
-	u8 cmd0, cmd1;
-	int r;
-
-	cmd0 = skb->data[1];
-	switch (cmd0) {
-	case ST21NFCA_NFCIP1_REQ:
-		cmd1 = skb->data[2];
-		switch (cmd1) {
-		case ST21NFCA_NFCIP1_ATR_REQ:
-			r = st21nfca_tm_recv_atr_req(hdev, skb);
-			break;
-		case ST21NFCA_NFCIP1_PSL_REQ:
-			r = st21nfca_tm_recv_psl_req(hdev, skb);
-			break;
-		case ST21NFCA_NFCIP1_DEP_REQ:
-			r = st21nfca_tm_recv_dep_req(hdev, skb);
-			break;
-		default:
-			return 1;
-		}
-	default:
-		return 1;
-	}
-	return r;
-}
-
-/*
- * Returns:
- * <= 0: driver handled the event, skb consumed
- *    1: driver does not handle the event, please do standard processing
- */
-int st21nfca_dep_event_received(struct nfc_hci_dev *hdev,
-				u8 event, struct sk_buff *skb)
-{
-	int r = 0;
-	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
-
-	pr_debug("dep event: %d\n", event);
-
-	switch (event) {
-	case ST21NFCA_EVT_CARD_ACTIVATED:
-		info->dep_info.curr_nfc_dep_pni = 0;
-		break;
-	case ST21NFCA_EVT_CARD_DEACTIVATED:
-		break;
-	case ST21NFCA_EVT_FIELD_ON:
-		break;
-	case ST21NFCA_EVT_FIELD_OFF:
-		break;
-	case ST21NFCA_EVT_SEND_DATA:
-		r = st21nfca_tm_event_send_data(hdev, skb);
-		if (r < 0)
-			return r;
-		return 0;
-	default:
-		return 1;
-	}
-	kfree_skb(skb);
-	return r;
-}
-EXPORT_SYMBOL(st21nfca_dep_event_received);
-
-static void st21nfca_im_send_psl_req(struct nfc_hci_dev *hdev, u8 did, u8 bsi,
-				     u8 bri, u8 lri)
-{
-	struct sk_buff *skb;
-	struct st21nfca_psl_req *psl_req;
-	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
-
-	skb =
-	    alloc_skb(sizeof(struct st21nfca_psl_req) + 1, GFP_KERNEL);
-	if (!skb)
-		return;
-	skb_reserve(skb, 1);
-
-	skb_put(skb, sizeof(struct st21nfca_psl_req));
-	psl_req = (struct st21nfca_psl_req *) skb->data;
-
-	psl_req->length = sizeof(struct st21nfca_psl_req);
-	psl_req->cmd0 = ST21NFCA_NFCIP1_REQ;
-	psl_req->cmd1 = ST21NFCA_NFCIP1_PSL_REQ;
-	psl_req->did = did;
-	psl_req->brs = (0x30 & bsi << 4) | (bri & 0x03);
-	psl_req->fsl = lri;
-
-	*skb_push(skb, 1) = info->dep_info.to | 0x10;
-
-	st21nfca_im_send_pdu(info, skb);
-}
-
-#define ST21NFCA_CB_TYPE_READER_F 1
-static void st21nfca_im_recv_atr_res_cb(void *context, struct sk_buff *skb,
-					int err)
-{
-	struct st21nfca_hci_info *info = context;
-	struct st21nfca_atr_res *atr_res;
-	int r;
-
-	if (err != 0)
-		return;
-
-	if (!skb)
-		return;
-
-	switch (info->async_cb_type) {
-	case ST21NFCA_CB_TYPE_READER_F:
-		skb_trim(skb, skb->len - 1);
-		atr_res = (struct st21nfca_atr_res *)skb->data;
-		r = nfc_set_remote_general_bytes(info->hdev->ndev,
-				atr_res->gbi,
-				skb->len - sizeof(struct st21nfca_atr_res));
-		if (r < 0)
-			return;
-
-		if (atr_res->to >= 0x0e)
-			info->dep_info.to = 0x0e;
-		else
-			info->dep_info.to = atr_res->to + 1;
-
-		info->dep_info.to |= 0x10;
-
-		r = nfc_dep_link_is_up(info->hdev->ndev, info->dep_info.idx,
-					NFC_COMM_PASSIVE, NFC_RF_INITIATOR);
-		if (r < 0)
-			return;
-
-		info->dep_info.curr_nfc_dep_pni = 0;
-		if (ST21NFCA_PP2LRI(atr_res->ppi) != info->dep_info.lri)
-			st21nfca_im_send_psl_req(info->hdev, atr_res->did,
-						atr_res->bsi, atr_res->bri,
-						ST21NFCA_PP2LRI(atr_res->ppi));
-		break;
-	default:
-		kfree_skb(skb);
-		break;
-	}
-}
-
-int st21nfca_im_send_atr_req(struct nfc_hci_dev *hdev, u8 *gb, size_t gb_len)
-{
-	struct sk_buff *skb;
-	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
-	struct st21nfca_atr_req *atr_req;
-	struct nfc_target *target;
-	uint size;
-
-	info->dep_info.to = ST21NFCA_DEFAULT_TIMEOUT;
-	size = ST21NFCA_ATR_REQ_MIN_SIZE + gb_len;
-	if (size > ST21NFCA_ATR_REQ_MAX_SIZE) {
-		PROTOCOL_ERR("14.6.1.1");
-		return -EINVAL;
-	}
-
-	skb =
-	    alloc_skb(sizeof(struct st21nfca_atr_req) + gb_len + 1, GFP_KERNEL);
-	if (!skb)
-		return -ENOMEM;
-
-	skb_reserve(skb, 1);
-
-	skb_put(skb, sizeof(struct st21nfca_atr_req));
-
-	atr_req = (struct st21nfca_atr_req *)skb->data;
-	memset(atr_req, 0, sizeof(struct st21nfca_atr_req));
-
-	atr_req->cmd0 = ST21NFCA_NFCIP1_REQ;
-	atr_req->cmd1 = ST21NFCA_NFCIP1_ATR_REQ;
-	memset(atr_req->nfcid3, 0, NFC_NFCID3_MAXSIZE);
-	target = hdev->ndev->targets;
-
-	if (target->sensf_res_len > 0)
-		memcpy(atr_req->nfcid3, target->sensf_res,
-				target->sensf_res_len);
-	else
-		get_random_bytes(atr_req->nfcid3, NFC_NFCID3_MAXSIZE);
-
-	atr_req->did = 0x0;
-
-	atr_req->bsi = 0x00;
-	atr_req->bri = 0x00;
-	atr_req->ppi = ST21NFCA_LR_BITS_PAYLOAD_SIZE_254B;
-	if (gb_len) {
-		atr_req->ppi |= ST21NFCA_GB_BIT;
-		memcpy(skb_put(skb, gb_len), gb, gb_len);
-	}
-	atr_req->length = sizeof(struct st21nfca_atr_req) + hdev->gb_len;
-
-	*skb_push(skb, 1) = info->dep_info.to | 0x10; /* timeout */
-
-	info->async_cb_type = ST21NFCA_CB_TYPE_READER_F;
-	info->async_cb_context = info;
-	info->async_cb = st21nfca_im_recv_atr_res_cb;
-	info->dep_info.bri = atr_req->bri;
-	info->dep_info.bsi = atr_req->bsi;
-	info->dep_info.lri = ST21NFCA_PP2LRI(atr_req->ppi);
-
-	return nfc_hci_send_cmd_async(hdev, ST21NFCA_RF_READER_F_GATE,
-				ST21NFCA_WR_XCHG_DATA, skb->data,
-				skb->len, info->async_cb, info);
-}
-EXPORT_SYMBOL(st21nfca_im_send_atr_req);
-
-static void st21nfca_im_recv_dep_res_cb(void *context, struct sk_buff *skb,
-					int err)
-{
-	struct st21nfca_hci_info *info = context;
-	struct st21nfca_dep_req_res *dep_res;
-
-	int size;
-
-	if (err != 0)
-		return;
-
-	if (!skb)
-		return;
-
-	switch (info->async_cb_type) {
-	case ST21NFCA_CB_TYPE_READER_F:
-		dep_res = (struct st21nfca_dep_req_res *)skb->data;
-
-		size = 3;
-		if (skb->len < size)
-			goto exit;
-
-		if (ST21NFCA_NFC_DEP_DID_BIT_SET(dep_res->pfb))
-			size++;
-		if (ST21NFCA_NFC_DEP_NAD_BIT_SET(dep_res->pfb))
-			size++;
-
-		if (skb->len < size)
-			goto exit;
-
-		skb_trim(skb, skb->len - 1);
-
-		/* Receiving DEP_REQ - Decoding */
-		switch (ST21NFCA_NFC_DEP_PFB_TYPE(dep_res->pfb)) {
-		case ST21NFCA_NFC_DEP_PFB_ACK_NACK_PDU:
-			pr_err("Received a ACK/NACK PDU\n");
-		case ST21NFCA_NFC_DEP_PFB_I_PDU:
-			info->dep_info.curr_nfc_dep_pni =
-			    ST21NFCA_NFC_DEP_PFB_PNI(dep_res->pfb + 1);
-			size++;
-			skb_pull(skb, size);
-			nfc_tm_data_received(info->hdev->ndev, skb);
-			break;
-		case ST21NFCA_NFC_DEP_PFB_SUPERVISOR_PDU:
-			pr_err("Received a SUPERVISOR PDU\n");
-			skb_pull(skb, size);
-			*skb_push(skb, 1) = ST21NFCA_NFCIP1_DEP_REQ;
-			*skb_push(skb, 1) = ST21NFCA_NFCIP1_REQ;
-			*skb_push(skb, 1) = skb->len;
-			*skb_push(skb, 1) = info->dep_info.to | 0x10;
-
-			st21nfca_im_send_pdu(info, skb);
-			break;
-		}
-
-		return;
-	default:
-		break;
-	}
-
-exit:
-	kfree_skb(skb);
-}
-
-int st21nfca_im_send_dep_req(struct nfc_hci_dev *hdev, struct sk_buff *skb)
-{
-	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
-
-	info->async_cb_type = ST21NFCA_CB_TYPE_READER_F;
-	info->async_cb_context = info;
-	info->async_cb = st21nfca_im_recv_dep_res_cb;
-
-	*skb_push(skb, 1) = info->dep_info.curr_nfc_dep_pni;
-	*skb_push(skb, 1) = ST21NFCA_NFCIP1_DEP_REQ;
-	*skb_push(skb, 1) = ST21NFCA_NFCIP1_REQ;
-	*skb_push(skb, 1) = skb->len;
-
-	*skb_push(skb, 1) = info->dep_info.to | 0x10;
-
-	return nfc_hci_send_cmd_async(hdev, ST21NFCA_RF_READER_F_GATE,
-				      ST21NFCA_WR_XCHG_DATA,
-				      skb->data, skb->len,
-				      info->async_cb, info);
-}
-EXPORT_SYMBOL(st21nfca_im_send_dep_req);
-
-void st21nfca_dep_init(struct nfc_hci_dev *hdev)
-{
-	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
-
-	INIT_WORK(&info->dep_info.tx_work, st21nfca_tx_work);
-	info->dep_info.curr_nfc_dep_pni = 0;
-	info->dep_info.idx = 0;
-	info->dep_info.to = ST21NFCA_DEFAULT_TIMEOUT;
-}
-EXPORT_SYMBOL(st21nfca_dep_init);
-
-void st21nfca_dep_deinit(struct nfc_hci_dev *hdev)
-{
-	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
-
-	cancel_work_sync(&info->dep_info.tx_work);
-}
-EXPORT_SYMBOL(st21nfca_dep_deinit);
diff --git a/drivers/nfc/st21nfca/st21nfca_dep.h b/drivers/nfc/st21nfca/st21nfca_dep.h
deleted file mode 100644
index baf4664..0000000
--- a/drivers/nfc/st21nfca/st21nfca_dep.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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 __ST21NFCA_DEP_H
-#define __ST21NFCA_DEP_H
-
-#include <linux/skbuff.h>
-#include <linux/workqueue.h>
-
-struct st21nfca_dep_info {
-	struct sk_buff *tx_pending;
-	struct work_struct tx_work;
-	u8 curr_nfc_dep_pni;
-	u32 idx;
-	u8 to;
-	u8 did;
-	u8 bsi;
-	u8 bri;
-	u8 lri;
-} __packed;
-
-int st21nfca_dep_event_received(struct nfc_hci_dev *hdev,
-				u8 event, struct sk_buff *skb);
-int st21nfca_tm_send_dep_res(struct nfc_hci_dev *hdev, struct sk_buff *skb);
-
-int st21nfca_im_send_atr_req(struct nfc_hci_dev *hdev, u8 *gb, size_t gb_len);
-int st21nfca_im_send_dep_req(struct nfc_hci_dev *hdev, struct sk_buff *skb);
-void st21nfca_dep_init(struct nfc_hci_dev *hdev);
-void st21nfca_dep_deinit(struct nfc_hci_dev *hdev);
-#endif /* __ST21NFCA_DEP_H */
diff --git a/drivers/nfc/st21nfca/st21nfca_se.c b/drivers/nfc/st21nfca/st21nfca_se.c
deleted file mode 100644
index 3197e9b..0000000
--- a/drivers/nfc/st21nfca/st21nfca_se.c
+++ /dev/null
@@ -1,420 +0,0 @@
-/*
- * 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 <net/nfc/hci.h>
-
-#include "st21nfca.h"
-#include "st21nfca_se.h"
-
-#define ST21NFCA_EVT_UICC_ACTIVATE		0x10
-#define ST21NFCA_EVT_UICC_DEACTIVATE	0x13
-#define ST21NFCA_EVT_SE_HARD_RESET		0x20
-#define ST21NFCA_EVT_SE_SOFT_RESET		0x11
-#define ST21NFCA_EVT_SE_END_OF_APDU_TRANSFER	0x21
-#define ST21NFCA_EVT_SE_ACTIVATE		0x22
-#define ST21NFCA_EVT_SE_DEACTIVATE		0x23
-
-#define ST21NFCA_EVT_TRANSMIT_DATA		0x10
-#define ST21NFCA_EVT_WTX_REQUEST		0x11
-
-#define ST21NFCA_EVT_CONNECTIVITY		0x10
-#define ST21NFCA_EVT_TRANSACTION		0x12
-
-#define ST21NFCA_ESE_HOST_ID			0xc0
-
-#define ST21NFCA_SE_TO_HOT_PLUG			1000
-/* Connectivity pipe only */
-#define ST21NFCA_SE_COUNT_PIPE_UICC		0x01
-/* Connectivity + APDU Reader pipe */
-#define ST21NFCA_SE_COUNT_PIPE_EMBEDDED	0x02
-
-#define ST21NFCA_SE_MODE_OFF			0x00
-#define ST21NFCA_SE_MODE_ON				0x01
-
-#define ST21NFCA_PARAM_ATR				0x01
-#define ST21NFCA_ATR_DEFAULT_BWI		0x04
-
-/*
- * WT = 2^BWI/10[s], convert into msecs and add a secure
- * room by increasing by 2 this timeout
- */
-#define ST21NFCA_BWI_TO_TIMEOUT(x)		((1 << x) * 200)
-#define ST21NFCA_ATR_GET_Y_FROM_TD(x)	(x >> 4)
-
-/* If TA is present bit 0 is set */
-#define ST21NFCA_ATR_TA_PRESENT(x) (x & 0x01)
-/* If TB is present bit 1 is set */
-#define ST21NFCA_ATR_TB_PRESENT(x) (x & 0x02)
-
-static u8 st21nfca_se_get_bwi(struct nfc_hci_dev *hdev)
-{
-	int i;
-	u8 td;
-	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
-
-	/* Bits 8 to 5 of the first TB for T=1 encode BWI from zero to nine */
-	for (i = 1; i < ST21NFCA_ESE_MAX_LENGTH; i++) {
-		td = ST21NFCA_ATR_GET_Y_FROM_TD(info->se_info.atr[i]);
-		if (ST21NFCA_ATR_TA_PRESENT(td))
-			i++;
-		if (ST21NFCA_ATR_TB_PRESENT(td)) {
-			i++;
-			return info->se_info.atr[i] >> 4;
-		}
-	}
-	return ST21NFCA_ATR_DEFAULT_BWI;
-}
-
-static void st21nfca_se_get_atr(struct nfc_hci_dev *hdev)
-{
-	int r;
-	struct sk_buff *skb;
-	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
-
-	r = nfc_hci_get_param(hdev, ST21NFCA_APDU_READER_GATE,
-			ST21NFCA_PARAM_ATR, &skb);
-	if (r < 0)
-		return;
-
-	if (skb->len <= ST21NFCA_ESE_MAX_LENGTH) {
-		memcpy(info->se_info.atr, skb->data, skb->len);
-		info->se_info.wt_timeout =
-			ST21NFCA_BWI_TO_TIMEOUT(st21nfca_se_get_bwi(hdev));
-	}
-	kfree_skb(skb);
-}
-
-static int st21nfca_hci_control_se(struct nfc_hci_dev *hdev, u32 se_idx,
-				u8 state)
-{
-	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
-	int r;
-	struct sk_buff *sk_host_list;
-	u8 se_event, host_id;
-
-	switch (se_idx) {
-	case NFC_HCI_UICC_HOST_ID:
-		se_event = (state == ST21NFCA_SE_MODE_ON ?
-					ST21NFCA_EVT_UICC_ACTIVATE :
-					ST21NFCA_EVT_UICC_DEACTIVATE);
-
-		info->se_info.count_pipes = 0;
-		info->se_info.expected_pipes = ST21NFCA_SE_COUNT_PIPE_UICC;
-		break;
-	case ST21NFCA_ESE_HOST_ID:
-		se_event = (state == ST21NFCA_SE_MODE_ON ?
-					ST21NFCA_EVT_SE_ACTIVATE :
-					ST21NFCA_EVT_SE_DEACTIVATE);
-
-		info->se_info.count_pipes = 0;
-		info->se_info.expected_pipes = ST21NFCA_SE_COUNT_PIPE_EMBEDDED;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	/*
-	 * Wait for an EVT_HOT_PLUG in order to
-	 * retrieve a relevant host list.
-	 */
-	reinit_completion(&info->se_info.req_completion);
-	r = nfc_hci_send_event(hdev, ST21NFCA_DEVICE_MGNT_GATE, se_event,
-			       NULL, 0);
-	if (r < 0)
-		return r;
-
-	mod_timer(&info->se_info.se_active_timer, jiffies +
-		msecs_to_jiffies(ST21NFCA_SE_TO_HOT_PLUG));
-	info->se_info.se_active = true;
-
-	/* Ignore return value and check in any case the host_list */
-	wait_for_completion_interruptible(&info->se_info.req_completion);
-
-	r = nfc_hci_get_param(hdev, NFC_HCI_ADMIN_GATE,
-			NFC_HCI_ADMIN_HOST_LIST,
-			&sk_host_list);
-	if (r < 0)
-		return r;
-
-	host_id = sk_host_list->data[sk_host_list->len - 1];
-	kfree_skb(sk_host_list);
-
-	if (state == ST21NFCA_SE_MODE_ON && host_id == se_idx)
-		return se_idx;
-	else if (state == ST21NFCA_SE_MODE_OFF && host_id != se_idx)
-		return se_idx;
-
-	return -1;
-}
-
-int st21nfca_hci_discover_se(struct nfc_hci_dev *hdev)
-{
-	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
-	int se_count = 0;
-
-	if (info->se_status->is_uicc_present) {
-		nfc_add_se(hdev->ndev, NFC_HCI_UICC_HOST_ID, NFC_SE_UICC);
-		se_count++;
-	}
-
-	if (info->se_status->is_ese_present) {
-		nfc_add_se(hdev->ndev, ST21NFCA_ESE_HOST_ID, NFC_SE_EMBEDDED);
-		se_count++;
-	}
-
-	return !se_count;
-}
-EXPORT_SYMBOL(st21nfca_hci_discover_se);
-
-int st21nfca_hci_enable_se(struct nfc_hci_dev *hdev, u32 se_idx)
-{
-	int r;
-
-	/*
-	 * According to upper layer, se_idx == NFC_SE_UICC when
-	 * info->se_status->is_uicc_enable is true should never happen.
-	 * Same for eSE.
-	 */
-	r = st21nfca_hci_control_se(hdev, se_idx, ST21NFCA_SE_MODE_ON);
-
-	if (r == ST21NFCA_ESE_HOST_ID) {
-		st21nfca_se_get_atr(hdev);
-		r = nfc_hci_send_event(hdev, ST21NFCA_APDU_READER_GATE,
-				ST21NFCA_EVT_SE_SOFT_RESET, NULL, 0);
-		if (r < 0)
-			return r;
-	} else if (r < 0) {
-		/*
-		 * The activation tentative failed, the secure element
-		 * is not connected. Remove from the list.
-		 */
-		nfc_remove_se(hdev->ndev, se_idx);
-		return r;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(st21nfca_hci_enable_se);
-
-int st21nfca_hci_disable_se(struct nfc_hci_dev *hdev, u32 se_idx)
-{
-	int r;
-
-	/*
-	 * According to upper layer, se_idx == NFC_SE_UICC when
-	 * info->se_status->is_uicc_enable is true should never happen
-	 * Same for eSE.
-	 */
-	r = st21nfca_hci_control_se(hdev, se_idx, ST21NFCA_SE_MODE_OFF);
-	if (r < 0)
-		return r;
-
-	return 0;
-}
-EXPORT_SYMBOL(st21nfca_hci_disable_se);
-
-int st21nfca_hci_se_io(struct nfc_hci_dev *hdev, u32 se_idx,
-			u8 *apdu, size_t apdu_length,
-			se_io_cb_t cb, void *cb_context)
-{
-	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
-
-	pr_debug("se_io %x\n", se_idx);
-
-	switch (se_idx) {
-	case ST21NFCA_ESE_HOST_ID:
-		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 nfc_hci_send_event(hdev, ST21NFCA_APDU_READER_GATE,
-					ST21NFCA_EVT_TRANSMIT_DATA,
-					apdu, apdu_length);
-	default:
-		return -ENODEV;
-	}
-}
-EXPORT_SYMBOL(st21nfca_hci_se_io);
-
-static void st21nfca_se_wt_timeout(unsigned long data)
-{
-	/*
-	 * No answer from the secure element
-	 * within the defined timeout.
-	 * Let's send a reset request as recovery procedure.
-	 * According to the situation, we first try to send a software reset
-	 * to the secure element. If the next command is still not
-	 * answering in time, we send to the CLF a secure element hardware
-	 * reset request.
-	 */
-	/* hardware reset managed through VCC_UICC_OUT power supply */
-	u8 param = 0x01;
-	struct st21nfca_hci_info *info = (struct st21nfca_hci_info *) data;
-
-	pr_debug("\n");
-
-	info->se_info.bwi_active = false;
-
-	if (!info->se_info.xch_error) {
-		info->se_info.xch_error = true;
-		nfc_hci_send_event(info->hdev, ST21NFCA_APDU_READER_GATE,
-				ST21NFCA_EVT_SE_SOFT_RESET, NULL, 0);
-	} else {
-		info->se_info.xch_error = false;
-		nfc_hci_send_event(info->hdev, ST21NFCA_DEVICE_MGNT_GATE,
-				ST21NFCA_EVT_SE_HARD_RESET, &param, 1);
-	}
-	info->se_info.cb(info->se_info.cb_context, NULL, 0, -ETIME);
-}
-
-static void st21nfca_se_activation_timeout(unsigned long data)
-{
-	struct st21nfca_hci_info *info = (struct st21nfca_hci_info *) data;
-
-	pr_debug("\n");
-
-	info->se_info.se_active = false;
-
-	complete(&info->se_info.req_completion);
-}
-
-/*
- * Returns:
- * <= 0: driver handled the event, skb consumed
- *    1: driver does not handle the event, please do standard processing
- */
-int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host,
-				u8 event, struct sk_buff *skb)
-{
-	int r = 0;
-	struct device *dev = &hdev->ndev->dev;
-	struct nfc_evt_transaction *transaction;
-
-	pr_debug("connectivity gate event: %x\n", event);
-
-	switch (event) {
-	case ST21NFCA_EVT_CONNECTIVITY:
-		break;
-	case ST21NFCA_EVT_TRANSACTION:
-		/*
-		 * According to specification etsi 102 622
-		 * 11.2.2.4 EVT_TRANSACTION Table 52
-		 * Description	Tag	Length
-		 * AID		81	5 to 16
-		 * PARAMETERS	82	0 to 255
-		 */
-		if (skb->len < NFC_MIN_AID_LENGTH + 2 &&
-		    skb->data[0] != NFC_EVT_TRANSACTION_AID_TAG)
-			return -EPROTO;
-
-		transaction = (struct nfc_evt_transaction *)devm_kzalloc(dev,
-						   skb->len - 2, GFP_KERNEL);
-
-		transaction->aid_len = skb->data[1];
-		memcpy(transaction->aid, &skb->data[2],
-		       transaction->aid_len);
-
-		/* Check next byte is PARAMETERS tag (82) */
-		if (skb->data[transaction->aid_len + 2] !=
-		    NFC_EVT_TRANSACTION_PARAMS_TAG)
-			return -EPROTO;
-
-		transaction->params_len = skb->data[transaction->aid_len + 3];
-		memcpy(transaction->params, skb->data +
-		       transaction->aid_len + 4, transaction->params_len);
-
-		r = nfc_se_transaction(hdev->ndev, host, transaction);
-		break;
-	default:
-		return 1;
-	}
-	kfree_skb(skb);
-	return r;
-}
-EXPORT_SYMBOL(st21nfca_connectivity_event_received);
-
-int st21nfca_apdu_reader_event_received(struct nfc_hci_dev *hdev,
-					u8 event, struct sk_buff *skb)
-{
-	int r = 0;
-	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
-
-	pr_debug("apdu reader gate event: %x\n", event);
-
-	switch (event) {
-	case ST21NFCA_EVT_TRANSMIT_DATA:
-		del_timer_sync(&info->se_info.bwi_timer);
-		info->se_info.bwi_active = false;
-		r = nfc_hci_send_event(hdev, ST21NFCA_DEVICE_MGNT_GATE,
-				ST21NFCA_EVT_SE_END_OF_APDU_TRANSFER, NULL, 0);
-		if (r < 0)
-			goto exit;
-
-		info->se_info.cb(info->se_info.cb_context,
-			skb->data, skb->len, 0);
-		break;
-	case ST21NFCA_EVT_WTX_REQUEST:
-		mod_timer(&info->se_info.bwi_timer, jiffies +
-				msecs_to_jiffies(info->se_info.wt_timeout));
-		break;
-	}
-
-exit:
-	kfree_skb(skb);
-	return r;
-}
-EXPORT_SYMBOL(st21nfca_apdu_reader_event_received);
-
-void st21nfca_se_init(struct nfc_hci_dev *hdev)
-{
-	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
-
-	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 = st21nfca_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 = st21nfca_se_activation_timeout;
-	info->se_info.se_active = false;
-
-	info->se_info.count_pipes = 0;
-	info->se_info.expected_pipes = 0;
-
-	info->se_info.xch_error = false;
-
-	info->se_info.wt_timeout =
-			ST21NFCA_BWI_TO_TIMEOUT(ST21NFCA_ATR_DEFAULT_BWI);
-}
-EXPORT_SYMBOL(st21nfca_se_init);
-
-void st21nfca_se_deinit(struct nfc_hci_dev *hdev)
-{
-	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
-
-	if (info->se_info.bwi_active)
-		del_timer_sync(&info->se_info.bwi_timer);
-	if (info->se_info.se_active)
-		del_timer_sync(&info->se_info.se_active_timer);
-
-	info->se_info.bwi_active = false;
-	info->se_info.se_active = false;
-}
-EXPORT_SYMBOL(st21nfca_se_deinit);
diff --git a/drivers/nfc/st21nfca/st21nfca_se.h b/drivers/nfc/st21nfca/st21nfca_se.h
deleted file mode 100644
index b172cfc..0000000
--- a/drivers/nfc/st21nfca/st21nfca_se.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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 __ST21NFCA_SE_H
-#define __ST21NFCA_SE_H
-
-#include <linux/skbuff.h>
-#include <linux/workqueue.h>
-
-/*
- * ref ISO7816-3 chap 8.1. the initial character TS is followed by a
- * sequence of at most 32 characters.
- */
-#define ST21NFCA_ESE_MAX_LENGTH			33
-#define ST21NFCA_ESE_HOST_ID			0xc0
-
-struct st21nfca_se_info {
-	u8 atr[ST21NFCA_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;
-	int expected_pipes;
-	int count_pipes;
-
-	bool xch_error;
-
-	se_io_cb_t cb;
-	void *cb_context;
-};
-
-int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host,
-					u8 event, struct sk_buff *skb);
-int st21nfca_apdu_reader_event_received(struct nfc_hci_dev *hdev,
-					u8 event, struct sk_buff *skb);
-
-int st21nfca_hci_discover_se(struct nfc_hci_dev *hdev);
-int st21nfca_hci_enable_se(struct nfc_hci_dev *hdev, u32 se_idx);
-int st21nfca_hci_disable_se(struct nfc_hci_dev *hdev, u32 se_idx);
-int st21nfca_hci_se_io(struct nfc_hci_dev *hdev, u32 se_idx,
-		u8 *apdu, size_t apdu_length,
-		se_io_cb_t cb, void *cb_context);
-
-void st21nfca_se_init(struct nfc_hci_dev *hdev);
-void st21nfca_se_deinit(struct nfc_hci_dev *hdev);
-#endif /* __ST21NFCA_SE_H */
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 04/35] nfc: st-nci: Fix incorrect spi buffer size
  2015-10-26  6:49 [PATCH v3 00/35] Few fixes and st21nfca/st-nci vendor_cmds support Christophe Ricard
@ 2015-10-26  6:49 ` Christophe Ricard
  2015-10-26  6:49 ` [PATCH v3 05/35] nfc: nci: Fix incorrect data chaining when sending data Christophe Ricard
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:49 UTC (permalink / raw)
  To: sameo
  Cc: linux-nfc, christophe-h.ricard, christophe.ricard, devicetree, stable

When sending data over SPI, the maximum expected length is the maximum
nci packet payload + data header size + the frame head room (1 for the
ndlc header) + the frame trail room (0).

Cc: stable@vger.kernel.org
Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com>
---
 drivers/nfc/st-nci/spi.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/nfc/st-nci/spi.c b/drivers/nfc/st-nci/spi.c
index 9a39871..b43f448 100644
--- a/drivers/nfc/st-nci/spi.c
+++ b/drivers/nfc/st-nci/spi.c
@@ -25,6 +25,7 @@
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/nfc.h>
+#include <net/nfc/nci.h>
 #include <linux/platform_data/st-nci.h>
 
 #include "st-nci.h"
@@ -94,7 +95,8 @@ static int st_nci_spi_write(void *phy_id, struct sk_buff *skb)
 	struct st_nci_spi_phy *phy = phy_id;
 	struct spi_device *dev = phy->spi_dev;
 	struct sk_buff *skb_rx;
-	u8 buf[ST_NCI_SPI_MAX_SIZE];
+	u8 buf[ST_NCI_SPI_MAX_SIZE + NCI_DATA_HDR_SIZE +
+	       ST_NCI_FRAME_HEADROOM + ST_NCI_FRAME_TAILROOM];
 	struct spi_transfer spi_xfer = {
 		.tx_buf = skb->data,
 		.rx_buf = buf,
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 05/35] nfc: nci: Fix incorrect data chaining when sending data
  2015-10-26  6:49 [PATCH v3 00/35] Few fixes and st21nfca/st-nci vendor_cmds support Christophe Ricard
  2015-10-26  6:49 ` [PATCH v3 04/35] nfc: st-nci: Fix incorrect spi buffer size Christophe Ricard
@ 2015-10-26  6:49 ` Christophe Ricard
  2015-10-26  6:49 ` [PATCH v3 06/35] nfc: nci: Fix improper management of HCI return code Christophe Ricard
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:49 UTC (permalink / raw)
  To: sameo
  Cc: linux-nfc, christophe-h.ricard, christophe.ricard, devicetree, stable

When sending HCI data over NCI, cmd information should be present only on
the first packet. Each packet shall be specifically allocated and sent to
the NCI layer.

Cc: stable@vger.kernel.org
Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com>
---
 net/nfc/nci/hci.c | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/net/nfc/nci/hci.c b/net/nfc/nci/hci.c
index 609f922..bc6b9d5 100644
--- a/net/nfc/nci/hci.c
+++ b/net/nfc/nci/hci.c
@@ -146,18 +146,18 @@ static int nci_hci_send_data(struct nci_dev *ndev, u8 pipe,
 	if (!conn_info)
 		return -EPROTO;
 
-	skb = nci_skb_alloc(ndev, 2 + conn_info->max_pkt_payload_len +
+	i = 0;
+	skb = nci_skb_alloc(ndev, conn_info->max_pkt_payload_len +
 			    NCI_DATA_HDR_SIZE, GFP_KERNEL);
 	if (!skb)
 		return -ENOMEM;
 
-	skb_reserve(skb, 2 + NCI_DATA_HDR_SIZE);
+	skb_reserve(skb, NCI_DATA_HDR_SIZE + 2);
 	*skb_push(skb, 1) = data_type;
 
-	i = 0;
-	len = conn_info->max_pkt_payload_len;
-
 	do {
+		len = conn_info->max_pkt_payload_len;
+
 		/* If last packet add NCI_HFP_NO_CHAINING */
 		if (i + conn_info->max_pkt_payload_len -
 		    (skb->len + 1) >= data_len) {
@@ -177,9 +177,14 @@ static int nci_hci_send_data(struct nci_dev *ndev, u8 pipe,
 			return r;
 
 		i += len;
+
 		if (i < data_len) {
-			skb_trim(skb, 0);
-			skb_pull(skb, len);
+			skb = nci_skb_alloc(ndev, conn_info->max_pkt_payload_len +
+					    NCI_DATA_HDR_SIZE, GFP_KERNEL);
+			if (!skb)
+				return -ENOMEM;
+
+			skb_reserve(skb, NCI_DATA_HDR_SIZE + 1);
 		}
 	} while (i < data_len);
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 06/35] nfc: nci: Fix improper management of HCI return code
  2015-10-26  6:49 [PATCH v3 00/35] Few fixes and st21nfca/st-nci vendor_cmds support Christophe Ricard
  2015-10-26  6:49 ` [PATCH v3 04/35] nfc: st-nci: Fix incorrect spi buffer size Christophe Ricard
  2015-10-26  6:49 ` [PATCH v3 05/35] nfc: nci: Fix incorrect data chaining when sending data Christophe Ricard
@ 2015-10-26  6:49 ` Christophe Ricard
  2015-10-26  6:49 ` [PATCH v3 07/35] nfc: nci: extract pipe value using NCI_HCP_MSG_GET_PIPE Christophe Ricard
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:49 UTC (permalink / raw)
  To: sameo
  Cc: linux-nfc, christophe-h.ricard, christophe.ricard, devicetree, stable

When sending HCI data over NCI, HCI return code is part of the NCI data.
In order to get correctly the HCI return code, we assume the NCI
communication is successful and extract the return code for the nci_hci
functions return code.

This is done because nci_to_errno does not match hci return code value.

Cc: stable@vger.kernel.org
Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com>
---
 net/nfc/nci/hci.c | 60 ++++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 44 insertions(+), 16 deletions(-)

diff --git a/net/nfc/nci/hci.c b/net/nfc/nci/hci.c
index bc6b9d5..73afb47 100644
--- a/net/nfc/nci/hci.c
+++ b/net/nfc/nci/hci.c
@@ -101,6 +101,20 @@ struct nci_hcp_packet {
 #define NCI_HCP_MSG_GET_CMD(header)  (header & 0x3f)
 #define NCI_HCP_MSG_GET_PIPE(header) (header & 0x7f)
 
+static int nci_hci_result_to_errno(u8 result)
+{
+	switch (result) {
+	case NCI_HCI_ANY_OK:
+		return 0;
+	case NCI_HCI_ANY_E_REG_PAR_UNKNOWN:
+		return -EOPNOTSUPP;
+	case NCI_HCI_ANY_E_TIMEOUT:
+		return -ETIME;
+	default:
+		return -1;
+	}
+}
+
 /* HCI core */
 static void nci_hci_reset_pipes(struct nci_hci_dev *hdev)
 {
@@ -217,7 +231,8 @@ int nci_hci_send_cmd(struct nci_dev *ndev, u8 gate, u8 cmd,
 		     const u8 *param, size_t param_len,
 		     struct sk_buff **skb)
 {
-	struct nci_conn_info    *conn_info;
+	struct nci_hcp_message *message;
+	struct nci_conn_info   *conn_info;
 	struct nci_data data;
 	int r;
 	u8 pipe = ndev->hci_dev->gate2pipe[gate];
@@ -237,9 +252,14 @@ int nci_hci_send_cmd(struct nci_dev *ndev, u8 gate, u8 cmd,
 
 	r = nci_request(ndev, nci_hci_send_data_req, (unsigned long)&data,
 			msecs_to_jiffies(NCI_DATA_TIMEOUT));
+	if (r == NCI_STATUS_OK) {
+		message = (struct nci_hcp_message *)conn_info->rx_skb->data;
+		r = nci_hci_result_to_errno(NCI_HCP_MSG_GET_CMD(message->header));
+		skb_pull(conn_info->rx_skb, NCI_HCI_HCP_MESSAGE_HEADER_LEN);
 
-	if (r == NCI_STATUS_OK && skb)
-		*skb = conn_info->rx_skb;
+		if (!r && skb)
+			*skb = conn_info->rx_skb;
+	}
 
 	return r;
 }
@@ -333,9 +353,6 @@ static void nci_hci_resp_received(struct nci_dev *ndev, u8 pipe,
 	struct nci_conn_info    *conn_info;
 	u8 status = result;
 
-	if (result != NCI_HCI_ANY_OK)
-		goto exit;
-
 	conn_info = ndev->hci_dev->conn_info;
 	if (!conn_info) {
 		status = NCI_STATUS_REJECTED;
@@ -345,7 +362,7 @@ static void nci_hci_resp_received(struct nci_dev *ndev, u8 pipe,
 	conn_info->rx_skb = skb;
 
 exit:
-	nci_req_complete(ndev, status);
+	nci_req_complete(ndev, NCI_STATUS_OK);
 }
 
 /* Receive hcp message for pipe, with type and cmd.
@@ -400,7 +417,7 @@ void nci_hci_data_received_cb(void *context,
 {
 	struct nci_dev *ndev = (struct nci_dev *)context;
 	struct nci_hcp_packet *packet;
-	u8 pipe, type, instruction;
+	u8 pipe, type;
 	struct sk_buff *hcp_skb;
 	struct sk_buff *frag_skb;
 	int msg_len;
@@ -439,7 +456,7 @@ void nci_hci_data_received_cb(void *context,
 		*skb_put(hcp_skb, NCI_HCI_HCP_PACKET_HEADER_LEN) = pipe;
 
 		skb_queue_walk(&ndev->hci_dev->rx_hcp_frags, frag_skb) {
-		       msg_len = frag_skb->len - NCI_HCI_HCP_PACKET_HEADER_LEN;
+			msg_len = frag_skb->len - NCI_HCI_HCP_PACKET_HEADER_LEN;
 			memcpy(skb_put(hcp_skb, msg_len), frag_skb->data +
 			       NCI_HCI_HCP_PACKET_HEADER_LEN, msg_len);
 		}
@@ -457,11 +474,9 @@ void nci_hci_data_received_cb(void *context,
 	packet = (struct nci_hcp_packet *)hcp_skb->data;
 	type = NCI_HCP_MSG_GET_TYPE(packet->message.header);
 	if (type == NCI_HCI_HCP_RESPONSE) {
-		pipe = packet->header;
-		instruction = NCI_HCP_MSG_GET_CMD(packet->message.header);
-		skb_pull(hcp_skb, NCI_HCI_HCP_PACKET_HEADER_LEN +
-			 NCI_HCI_HCP_MESSAGE_HEADER_LEN);
-		nci_hci_hcp_message_rx(ndev, pipe, type, instruction, hcp_skb);
+		pipe = NCI_HCP_MSG_GET_PIPE(packet->header);
+		skb_pull(hcp_skb, NCI_HCI_HCP_PACKET_HEADER_LEN);
+		nci_hci_hcp_message_rx(ndev, pipe, type, NCI_STATUS_OK, hcp_skb);
 	} else {
 		skb_queue_tail(&ndev->hci_dev->msg_rx_queue, hcp_skb);
 		schedule_work(&ndev->hci_dev->msg_rx_work);
@@ -493,6 +508,7 @@ EXPORT_SYMBOL(nci_hci_open_pipe);
 int nci_hci_set_param(struct nci_dev *ndev, u8 gate, u8 idx,
 		      const u8 *param, size_t param_len)
 {
+	struct nci_hcp_message *message;
 	struct nci_conn_info *conn_info;
 	struct nci_data data;
 	int r;
@@ -525,6 +541,11 @@ int nci_hci_set_param(struct nci_dev *ndev, u8 gate, u8 idx,
 	r = nci_request(ndev, nci_hci_send_data_req,
 			(unsigned long)&data,
 			msecs_to_jiffies(NCI_DATA_TIMEOUT));
+	if (r == NCI_STATUS_OK) {
+		message = (struct nci_hcp_message *)conn_info->rx_skb->data;
+		r = nci_hci_result_to_errno(NCI_HCP_MSG_GET_CMD(message->header));
+		skb_pull(conn_info->rx_skb, NCI_HCI_HCP_MESSAGE_HEADER_LEN);
+	}
 
 	kfree(tmp);
 	return r;
@@ -534,6 +555,7 @@ EXPORT_SYMBOL(nci_hci_set_param);
 int nci_hci_get_param(struct nci_dev *ndev, u8 gate, u8 idx,
 		      struct sk_buff **skb)
 {
+	struct nci_hcp_message *message;
 	struct nci_conn_info    *conn_info;
 	struct nci_data data;
 	int r;
@@ -558,8 +580,14 @@ int nci_hci_get_param(struct nci_dev *ndev, u8 gate, u8 idx,
 	r = nci_request(ndev, nci_hci_send_data_req, (unsigned long)&data,
 			msecs_to_jiffies(NCI_DATA_TIMEOUT));
 
-	if (r == NCI_STATUS_OK)
-		*skb = conn_info->rx_skb;
+	if (r == NCI_STATUS_OK) {
+		message = (struct nci_hcp_message *)conn_info->rx_skb->data;
+		r = nci_hci_result_to_errno(NCI_HCP_MSG_GET_CMD(message->header));
+		skb_pull(conn_info->rx_skb, NCI_HCI_HCP_MESSAGE_HEADER_LEN);
+
+		if (!r && skb)
+			*skb = conn_info->rx_skb;
+	}
 
 	return r;
 }
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 07/35] nfc: nci: extract pipe value using NCI_HCP_MSG_GET_PIPE
  2015-10-26  6:49 [PATCH v3 00/35] Few fixes and st21nfca/st-nci vendor_cmds support Christophe Ricard
                   ` (2 preceding siblings ...)
  2015-10-26  6:49 ` [PATCH v3 06/35] nfc: nci: Fix improper management of HCI return code Christophe Ricard
@ 2015-10-26  6:49 ` Christophe Ricard
       [not found] ` <1445842215-28403-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:49 UTC (permalink / raw)
  To: sameo
  Cc: linux-nfc, christophe-h.ricard, christophe.ricard, devicetree, stable

When receiving data in nci_hci_msg_rx_work, extract pipe value using
NCI_HCP_MSG_GET_PIPE macro.

Cc: stable@vger.kernel.org
Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com>
---
 net/nfc/nci/hci.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/nfc/nci/hci.c b/net/nfc/nci/hci.c
index 73afb47..abe0200 100644
--- a/net/nfc/nci/hci.c
+++ b/net/nfc/nci/hci.c
@@ -400,7 +400,7 @@ static void nci_hci_msg_rx_work(struct work_struct *work)
 	u8 pipe, type, instruction;
 
 	while ((skb = skb_dequeue(&hdev->msg_rx_queue)) != NULL) {
-		pipe = skb->data[0];
+		pipe = NCI_HCP_MSG_GET_PIPE(skb->data[0]);
 		skb_pull(skb, NCI_HCI_HCP_PACKET_HEADER_LEN);
 		message = (struct nci_hcp_message *)skb->data;
 		type = NCI_HCP_MSG_GET_TYPE(message->header);
@@ -437,7 +437,7 @@ void nci_hci_data_received_cb(void *context,
 
 	/* it's the last fragment. Does it need re-aggregation? */
 	if (skb_queue_len(&ndev->hci_dev->rx_hcp_frags)) {
-		pipe = packet->header & NCI_HCI_FRAGMENT;
+		pipe = NCI_HCP_MSG_GET_PIPE(packet->header);
 		skb_queue_tail(&ndev->hci_dev->rx_hcp_frags, skb);
 
 		msg_len = 0;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 08/35] nfc: nci: add nci_hci_clear_all_pipes functions
       [not found] ` <1445842215-28403-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (2 preceding siblings ...)
  2015-10-26  6:49   ` [PATCH v3 03/35] nfc: st21nfca: Align st21nfca driver with other nfc driver Christophe Ricard
@ 2015-10-26  6:49   ` Christophe Ricard
  2015-10-26  6:49   ` [PATCH v3 09/35] nfc: nci: Add a call to nci_hci_clear_all_pipes at HCI initial activation Christophe Ricard
                     ` (15 subsequent siblings)
  19 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:49 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe-h.ricard-qxv4g6HH51o,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	devicetree-u79uwXL29TY76Z2rM5mHXA

nci_hci_clear_all_pipes might be use full in some cases for example after
a firmware update.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 include/net/nfc/nci_core.h |  1 +
 net/nfc/nci/hci.c          | 15 +++++++++++++++
 2 files changed, 16 insertions(+)

diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h
index d0d0f1e..b2f2e04 100644
--- a/include/net/nfc/nci_core.h
+++ b/include/net/nfc/nci_core.h
@@ -305,6 +305,7 @@ int nci_hci_set_param(struct nci_dev *ndev, u8 gate, u8 idx,
 		      const u8 *param, size_t param_len);
 int nci_hci_get_param(struct nci_dev *ndev, u8 gate, u8 idx,
 		      struct sk_buff **skb);
+int nci_hci_clear_all_pipes(struct nci_dev *ndev);
 int nci_hci_dev_session_init(struct nci_dev *ndev);
 
 static inline struct sk_buff *nci_skb_alloc(struct nci_dev *ndev,
diff --git a/net/nfc/nci/hci.c b/net/nfc/nci/hci.c
index abe0200..43d7931 100644
--- a/net/nfc/nci/hci.c
+++ b/net/nfc/nci/hci.c
@@ -70,6 +70,7 @@ struct nci_hcp_packet {
 #define NCI_HCI_ANY_SET_PARAMETER  0x01
 #define NCI_HCI_ANY_GET_PARAMETER  0x02
 #define NCI_HCI_ANY_CLOSE_PIPE     0x04
+#define NCI_HCI_ADM_CLEAR_ALL_PIPE 0x14
 
 #define NCI_HFP_NO_CHAINING        0x80
 
@@ -265,6 +266,20 @@ int nci_hci_send_cmd(struct nci_dev *ndev, u8 gate, u8 cmd,
 }
 EXPORT_SYMBOL(nci_hci_send_cmd);
 
+int nci_hci_clear_all_pipes(struct nci_dev *ndev)
+{
+	int r;
+
+	r = nci_hci_send_cmd(ndev, NCI_HCI_ADMIN_GATE,
+			     NCI_HCI_ADM_CLEAR_ALL_PIPE, NULL, 0, NULL);
+	if (r < 0)
+		return r;
+
+	nci_hci_reset_pipes(ndev->hci_dev);
+	return r;
+}
+EXPORT_SYMBOL(nci_hci_clear_all_pipes);
+
 static void nci_hci_event_received(struct nci_dev *ndev, u8 pipe,
 				   u8 event, struct sk_buff *skb)
 {
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 09/35] nfc: nci: Add a call to nci_hci_clear_all_pipes at HCI initial activation.
       [not found] ` <1445842215-28403-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (3 preceding siblings ...)
  2015-10-26  6:49   ` [PATCH v3 08/35] nfc: nci: add nci_hci_clear_all_pipes functions Christophe Ricard
@ 2015-10-26  6:49   ` Christophe Ricard
  2015-10-26  6:49   ` [PATCH v3 10/35] nfc: nci: add capability to create pipe on specific gate in nci_hci_connect_gate Christophe Ricard
                     ` (14 subsequent siblings)
  19 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:49 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe-h.ricard-qxv4g6HH51o,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	devicetree-u79uwXL29TY76Z2rM5mHXA

When session_id is filled to ff, the pipe configuration is probably
incorrect.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 net/nfc/nci/hci.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/net/nfc/nci/hci.c b/net/nfc/nci/hci.c
index 43d7931..a937bc6 100644
--- a/net/nfc/nci/hci.c
+++ b/net/nfc/nci/hci.c
@@ -701,6 +701,10 @@ int nci_hci_dev_session_init(struct nci_dev *ndev)
 		/* Restore gate<->pipe table from some proprietary location. */
 		r = ndev->ops->hci_load_session(ndev);
 	} else {
+		r = nci_hci_clear_all_pipes(ndev);
+		if (r < 0)
+			goto exit;
+
 		r = nci_hci_dev_connect_gates(ndev,
 					      ndev->hci_dev->init_data.gate_count,
 					      ndev->hci_dev->init_data.gates);
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 10/35] nfc: nci: add capability to create pipe on specific gate in nci_hci_connect_gate
       [not found] ` <1445842215-28403-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (4 preceding siblings ...)
  2015-10-26  6:49   ` [PATCH v3 09/35] nfc: nci: Add a call to nci_hci_clear_all_pipes at HCI initial activation Christophe Ricard
@ 2015-10-26  6:49   ` Christophe Ricard
  2015-10-26  6:49   ` [PATCH v3 13/35] nfc: st-nci: Open NCI_HCI_LINK_MGMT_PIPE Christophe Ricard
                     ` (13 subsequent siblings)
  19 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:49 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe-h.ricard-qxv4g6HH51o,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Some gates might be interesting to have their pipes created.
Add in nci_hci_connect_gate a call to nci_hci_create_pipe for every gate
different than NCI_HCI_LINK_MGMT_GATE or NCI_HCI_ADMIN_GATE.

In case of an error when opening a pipe, like in hci layer, delete the pipe
if it was created.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 net/nfc/nci/hci.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 54 insertions(+), 1 deletion(-)

diff --git a/net/nfc/nci/hci.c b/net/nfc/nci/hci.c
index a937bc6..1d6aa5d 100644
--- a/net/nfc/nci/hci.c
+++ b/net/nfc/nci/hci.c
@@ -79,6 +79,8 @@ struct nci_hcp_packet {
 #define NCI_EVT_HOT_PLUG           0x03
 
 #define NCI_HCI_ADMIN_PARAM_SESSION_IDENTITY       0x01
+#define NCI_HCI_ADM_CREATE_PIPE			0x10
+#define NCI_HCI_ADM_DELETE_PIPE			0x11
 
 /* HCP headers */
 #define NCI_HCI_HCP_PACKET_HEADER_LEN      1
@@ -520,6 +522,42 @@ int nci_hci_open_pipe(struct nci_dev *ndev, u8 pipe)
 }
 EXPORT_SYMBOL(nci_hci_open_pipe);
 
+static u8 nci_hci_create_pipe(struct nci_dev *ndev, u8 dest_host,
+			      u8 dest_gate, int *result)
+{
+	u8 pipe;
+	struct sk_buff *skb;
+	struct nci_hci_create_pipe_params params;
+	struct nci_hci_create_pipe_resp *resp;
+
+	pr_debug("gate=%d\n", dest_gate);
+
+	params.src_gate = NCI_HCI_ADMIN_GATE;
+	params.dest_host = dest_host;
+	params.dest_gate = dest_gate;
+
+	*result = nci_hci_send_cmd(ndev, NCI_HCI_ADMIN_GATE, NCI_HCI_ADM_CREATE_PIPE,
+				   (u8 *)&params, sizeof(params), &skb);
+	if (*result < 0)
+		return NCI_HCI_INVALID_PIPE;
+
+	resp = (struct nci_hci_create_pipe_resp *)skb->data;
+	pipe = resp->pipe;
+	kfree_skb(skb);
+
+	pr_debug("pipe created=%d\n", pipe);
+
+	return pipe;
+}
+
+static int nci_hci_delete_pipe(struct nci_dev *ndev, u8 pipe)
+{
+	pr_debug("\n");
+
+	return nci_hci_send_cmd(ndev, NCI_HCI_ADMIN_GATE,
+				NCI_HCI_ADM_DELETE_PIPE, &pipe, 1, NULL);
+}
+
 int nci_hci_set_param(struct nci_dev *ndev, u8 gate, u8 idx,
 		      const u8 *param, size_t param_len)
 {
@@ -611,6 +649,7 @@ EXPORT_SYMBOL(nci_hci_get_param);
 int nci_hci_connect_gate(struct nci_dev *ndev,
 			 u8 dest_host, u8 dest_gate, u8 pipe)
 {
+	bool pipe_created = false;
 	int r;
 
 	if (pipe == NCI_HCI_DO_NOT_OPEN_PIPE)
@@ -629,12 +668,26 @@ int nci_hci_connect_gate(struct nci_dev *ndev,
 	case NCI_HCI_ADMIN_GATE:
 		pipe = NCI_HCI_ADMIN_PIPE;
 	break;
+	default:
+		pipe = nci_hci_create_pipe(ndev, dest_host, dest_gate, &r);
+		if (pipe < 0)
+			return r;
+		pipe_created = true;
+		break;
 	}
 
 open_pipe:
 	r = nci_hci_open_pipe(ndev, pipe);
-	if (r < 0)
+	if (r < 0) {
+		if (pipe_created) {
+			if (nci_hci_delete_pipe(ndev, pipe) < 0) {
+				/* TODO: Cannot clean by deleting pipe...
+				 * -> inconsistent state
+				 */
+			}
+		}
 		return r;
+	}
 
 	ndev->hci_dev->pipes[pipe].gate = dest_gate;
 	ndev->hci_dev->pipes[pipe].host = dest_host;
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 11/35] nfc: st-nci: Remove ndev->hci_dev->init_data.gates initialization in load_session
  2015-10-26  6:49 [PATCH v3 00/35] Few fixes and st21nfca/st-nci vendor_cmds support Christophe Ricard
                   ` (4 preceding siblings ...)
       [not found] ` <1445842215-28403-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
@ 2015-10-26  6:49 ` Christophe Ricard
  2015-10-26  6:49 ` [PATCH v3 12/35] nfc: st21nfca: Remove hdev->init_data.gates " Christophe Ricard
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:49 UTC (permalink / raw)
  To: sameo
  Cc: linux-nfc, christophe-h.ricard, christophe.ricard, devicetree, stable

ndev->hci_dev->init_data.gates is already initialized in st_nci_hci_network.

Cc: stable@vger.kernel.org
Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com>
---
 drivers/nfc/st-nci/se.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/nfc/st-nci/se.c b/drivers/nfc/st-nci/se.c
index 4acb945..3ffac0e 100644
--- a/drivers/nfc/st-nci/se.c
+++ b/drivers/nfc/st-nci/se.c
@@ -244,9 +244,6 @@ int st_nci_hci_load_session(struct nci_dev *ndev)
 		kfree_skb(skb_pipe_info);
 	}
 
-	memcpy(ndev->hci_dev->init_data.gates, st_nci_gates,
-	       sizeof(st_nci_gates));
-
 	kfree_skb(skb_pipe_list);
 	return r;
 }
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 12/35] nfc: st21nfca: Remove hdev->init_data.gates initialization in load_session
  2015-10-26  6:49 [PATCH v3 00/35] Few fixes and st21nfca/st-nci vendor_cmds support Christophe Ricard
                   ` (5 preceding siblings ...)
  2015-10-26  6:49 ` [PATCH v3 11/35] nfc: st-nci: Remove ndev->hci_dev->init_data.gates initialization in load_session Christophe Ricard
@ 2015-10-26  6:49 ` Christophe Ricard
  2015-10-26  6:49 ` [PATCH v3 14/35] nfc: st21nfca: Open NFC_HCI_LINK_MGMT_PIPE Christophe Ricard
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:49 UTC (permalink / raw)
  To: sameo
  Cc: linux-nfc, christophe-h.ricard, christophe.ricard, devicetree, stable

hdev->init_data.gates is already initialized in st21nfca_hci_probe.

Cc: stable@vger.kernel.org
Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com>
---
 drivers/nfc/st21nfca/core.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/nfc/st21nfca/core.c b/drivers/nfc/st21nfca/core.c
index 42f1974..67d1c27 100644
--- a/drivers/nfc/st21nfca/core.c
+++ b/drivers/nfc/st21nfca/core.c
@@ -218,7 +218,6 @@ static int st21nfca_hci_load_session(struct nfc_hci_dev *hdev)
 		}
 	}
 
-	memcpy(hdev->init_data.gates, st21nfca_gates, sizeof(st21nfca_gates));
 free_list:
 	kfree_skb(skb_pipe_list);
 	return r;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 13/35] nfc: st-nci: Open NCI_HCI_LINK_MGMT_PIPE
       [not found] ` <1445842215-28403-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (5 preceding siblings ...)
  2015-10-26  6:49   ` [PATCH v3 10/35] nfc: nci: add capability to create pipe on specific gate in nci_hci_connect_gate Christophe Ricard
@ 2015-10-26  6:49   ` Christophe Ricard
  2015-10-26  6:49   ` [PATCH v3 18/35] nfc: st-nci: Add support for NCI_HCI_IDENTITY_MGMT_GATE Christophe Ricard
                     ` (12 subsequent siblings)
  19 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:49 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe-h.ricard-qxv4g6HH51o,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	devicetree-u79uwXL29TY76Z2rM5mHXA

NCI_HCI_LINK_MGMT_PIPE was never open in st_nci_hci_load_session.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 drivers/nfc/st-nci/se.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/nfc/st-nci/se.c b/drivers/nfc/st-nci/se.c
index 3ffac0e..3522165 100644
--- a/drivers/nfc/st-nci/se.c
+++ b/drivers/nfc/st-nci/se.c
@@ -244,6 +244,14 @@ int st_nci_hci_load_session(struct nci_dev *ndev)
 		kfree_skb(skb_pipe_info);
 	}
 
+	/*
+	 * 3 gates have a well known pipe ID. Only NCI_HCI_LINK_MGMT_GATE
+	 * is not yet open at this stage.
+	 */
+	r = nci_hci_connect_gate(ndev, ST_NCI_HOST_CONTROLLER_ID,
+				 NCI_HCI_LINK_MGMT_GATE,
+				 NCI_HCI_LINK_MGMT_PIPE);
+
 	kfree_skb(skb_pipe_list);
 	return r;
 }
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 14/35] nfc: st21nfca: Open NFC_HCI_LINK_MGMT_PIPE
  2015-10-26  6:49 [PATCH v3 00/35] Few fixes and st21nfca/st-nci vendor_cmds support Christophe Ricard
                   ` (6 preceding siblings ...)
  2015-10-26  6:49 ` [PATCH v3 12/35] nfc: st21nfca: Remove hdev->init_data.gates " Christophe Ricard
@ 2015-10-26  6:49 ` Christophe Ricard
  2015-10-26  6:49 ` [PATCH v3 15/35] nfc: st-nci: Keep st_nci_gates unchanged in load_session Christophe Ricard
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:49 UTC (permalink / raw)
  To: sameo
  Cc: linux-nfc, christophe-h.ricard, christophe.ricard, devicetree, stable

NFC_HCI_LINK_MGMT_PIPE was never open in nfc_hci_load_session.

Cc: stable@vger.kernel.org
Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com>
---
 drivers/nfc/st21nfca/core.c | 19 +++++--------------
 1 file changed, 5 insertions(+), 14 deletions(-)

diff --git a/drivers/nfc/st21nfca/core.c b/drivers/nfc/st21nfca/core.c
index 67d1c27..819a94a 100644
--- a/drivers/nfc/st21nfca/core.c
+++ b/drivers/nfc/st21nfca/core.c
@@ -203,22 +203,13 @@ static int st21nfca_hci_load_session(struct nfc_hci_dev *hdev)
 	}
 
 	/*
-	 * 3 gates have a well known pipe ID.
-	 * They will never appear in the pipe list
+	 * 3 gates have a well known pipe ID. Only NFC_HCI_LINK_MGMT_GATE
+	 * is not yet open at this stage.
 	 */
-	if (skb_pipe_list->len + 3 < ARRAY_SIZE(st21nfca_gates)) {
-		for (i = skb_pipe_list->len + 3;
-				i < ARRAY_SIZE(st21nfca_gates) - 2; i++) {
-			r = nfc_hci_connect_gate(hdev,
-					NFC_HCI_HOST_CONTROLLER_ID,
-					st21nfca_gates[i].gate,
-					st21nfca_gates[i].pipe);
-			if (r < 0)
-				goto free_list;
-		}
-	}
+	r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID,
+				 NFC_HCI_LINK_MGMT_GATE,
+				 NFC_HCI_LINK_MGMT_PIPE);
 
-free_list:
 	kfree_skb(skb_pipe_list);
 	return r;
 }
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 15/35] nfc: st-nci: Keep st_nci_gates unchanged in load_session
  2015-10-26  6:49 [PATCH v3 00/35] Few fixes and st21nfca/st-nci vendor_cmds support Christophe Ricard
                   ` (7 preceding siblings ...)
  2015-10-26  6:49 ` [PATCH v3 14/35] nfc: st21nfca: Open NFC_HCI_LINK_MGMT_PIPE Christophe Ricard
@ 2015-10-26  6:49 ` Christophe Ricard
  2015-10-26  6:49 ` [PATCH v3 16/35] nfc: st21nfca: Keep st21nfca_gates " Christophe Ricard
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:49 UTC (permalink / raw)
  To: sameo
  Cc: linux-nfc, christophe-h.ricard, christophe.ricard, devicetree, stable

We need to keep initial st_nci_gates values in order for
nci_hci_dev_connect_gates to create and open pipe when necessary.

For example after a firmware update CLF pipes are cleared. Changing pipe
values in st_nci_gates was causing nci_hci_dev_connect_gates not using
accurate pipes value.

Cc: stable@vger.kernel.org
Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com>
---
 drivers/nfc/st-nci/se.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/nfc/st-nci/se.c b/drivers/nfc/st-nci/se.c
index 3522165..df2dc54 100644
--- a/drivers/nfc/st-nci/se.c
+++ b/drivers/nfc/st-nci/se.c
@@ -232,13 +232,13 @@ int st_nci_hci_load_session(struct nci_dev *ndev)
 		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->init_data.gates[j].pipe = pipe_info[2];
 
 			ndev->hci_dev->gate2pipe[st_nci_gates[j].gate] =
-						st_nci_gates[j].pipe;
-			ndev->hci_dev->pipes[st_nci_gates[j].pipe].gate =
+						pipe_info[2];
+			ndev->hci_dev->pipes[pipe_info[2]].gate =
 						st_nci_gates[j].gate;
-			ndev->hci_dev->pipes[st_nci_gates[j].pipe].host =
+			ndev->hci_dev->pipes[pipe_info[2]].host =
 						dm_pipe_info->src_host_id;
 		}
 		kfree_skb(skb_pipe_info);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 16/35] nfc: st21nfca: Keep st21nfca_gates unchanged in load_session
  2015-10-26  6:49 [PATCH v3 00/35] Few fixes and st21nfca/st-nci vendor_cmds support Christophe Ricard
                   ` (8 preceding siblings ...)
  2015-10-26  6:49 ` [PATCH v3 15/35] nfc: st-nci: Keep st_nci_gates unchanged in load_session Christophe Ricard
@ 2015-10-26  6:49 ` Christophe Ricard
  2015-10-26  6:49 ` [PATCH v3 17/35] nfc: st-nci: initialize gate_count in st_nci_hci_network_init Christophe Ricard
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:49 UTC (permalink / raw)
  To: sameo
  Cc: linux-nfc, christophe-h.ricard, christophe.ricard, devicetree, stable

We need to keep initial st_nci_gates values in order for
nfc_hci_dev_connect_gates to create and open pipe when necessary.

For example after a firmware update CLF pipes are cleared. Changing pipe
values in st21nfca_gates was causing nfc_hci_dev_connect_gates not using
accurate pipes value.

Cc: stable@vger.kernel.org
Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com>
---
 drivers/nfc/st21nfca/core.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/nfc/st21nfca/core.c b/drivers/nfc/st21nfca/core.c
index 819a94a..b4451f8 100644
--- a/drivers/nfc/st21nfca/core.c
+++ b/drivers/nfc/st21nfca/core.c
@@ -190,14 +190,14 @@ static int st21nfca_hci_load_session(struct nfc_hci_dev *hdev)
 		if (j < ARRAY_SIZE(st21nfca_gates) &&
 			st21nfca_gates[j].gate == info->dst_gate_id &&
 			ST21NFCA_DM_IS_PIPE_OPEN(info->pipe_state)) {
-			st21nfca_gates[j].pipe = pipe_info[2];
+			hdev->init_data.gates[j].pipe = pipe_info[2];
 
 			hdev->gate2pipe[st21nfca_gates[j].gate] =
-							st21nfca_gates[j].pipe;
-			hdev->pipes[st21nfca_gates[j].pipe].gate =
-							st21nfca_gates[j].gate;
-			hdev->pipes[st21nfca_gates[j].pipe].dest_host =
-							info->src_host_id;
+						pipe_info[2];
+			hdev->pipes[pipe_info[2]].gate =
+						st21nfca_gates[j].gate;
+			hdev->pipes[pipe_info[2]].dest_host =
+						info->src_host_id;
 		}
 		kfree_skb(skb_pipe_info);
 	}
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 17/35] nfc: st-nci: initialize gate_count in st_nci_hci_network_init
  2015-10-26  6:49 [PATCH v3 00/35] Few fixes and st21nfca/st-nci vendor_cmds support Christophe Ricard
                   ` (9 preceding siblings ...)
  2015-10-26  6:49 ` [PATCH v3 16/35] nfc: st21nfca: Keep st21nfca_gates " Christophe Ricard
@ 2015-10-26  6:49 ` Christophe Ricard
  2015-10-26  6:49 ` [PATCH v3 19/35] nfc: st-nci: Change st_nci_gates offset when looking for a pipe in the table Christophe Ricard
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:49 UTC (permalink / raw)
  To: sameo
  Cc: linux-nfc, christophe-h.ricard, christophe.ricard, devicetree, stable

When initializing ndev->hci_dev->init_data, only gates field was set.
gate_count needs to be initialized as well.

Cc: stable@vger.kernel.org
Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com>
---
 drivers/nfc/st-nci/se.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/nfc/st-nci/se.c b/drivers/nfc/st-nci/se.c
index df2dc54..11e49a5 100644
--- a/drivers/nfc/st-nci/se.c
+++ b/drivers/nfc/st-nci/se.c
@@ -536,6 +536,7 @@ static int st_nci_hci_network_init(struct nci_dev *ndev)
 	if (!conn_info)
 		goto free_dest_params;
 
+	ndev->hci_dev->init_data.gate_count = ARRAY_SIZE(st_nci_gates);
 	memcpy(ndev->hci_dev->init_data.gates, st_nci_gates,
 	       sizeof(st_nci_gates));
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 18/35] nfc: st-nci: Add support for NCI_HCI_IDENTITY_MGMT_GATE
       [not found] ` <1445842215-28403-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (6 preceding siblings ...)
  2015-10-26  6:49   ` [PATCH v3 13/35] nfc: st-nci: Open NCI_HCI_LINK_MGMT_PIPE Christophe Ricard
@ 2015-10-26  6:49   ` Christophe Ricard
  2015-10-26  6:50     ` Christophe Ricard
                     ` (11 subsequent siblings)
  19 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:49 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe-h.ricard-qxv4g6HH51o,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	devicetree-u79uwXL29TY76Z2rM5mHXA

NCI_HCI_IDENTITY_MGMT_GATE might be useful to get information for example
about hardware or firmware version.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 drivers/nfc/st-nci/se.c    | 3 +++
 include/net/nfc/nci_core.h | 1 +
 2 files changed, 4 insertions(+)

diff --git a/drivers/nfc/st-nci/se.c b/drivers/nfc/st-nci/se.c
index 11e49a5..5d1747d 100644
--- a/drivers/nfc/st-nci/se.c
+++ b/drivers/nfc/st-nci/se.c
@@ -112,6 +112,9 @@ static struct nci_hci_gate st_nci_gates[] = {
 	{ST_NCI_DEVICE_MGNT_GATE, ST_NCI_DEVICE_MGNT_PIPE,
 					ST_NCI_HOST_CONTROLLER_ID},
 
+	{NCI_HCI_IDENTITY_MGMT_GATE, NCI_HCI_INVALID_PIPE,
+					ST_NCI_HOST_CONTROLLER_ID},
+
 	/* Secure element pipes are created by secure element host */
 	{ST_NCI_CONNECTIVITY_GATE, NCI_HCI_DO_NOT_OPEN_PIPE,
 					ST_NCI_HOST_CONTROLLER_ID},
diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h
index b2f2e04..377f3de 100644
--- a/include/net/nfc/nci_core.h
+++ b/include/net/nfc/nci_core.h
@@ -125,6 +125,7 @@ struct nci_conn_info {
 
 /* Gates */
 #define NCI_HCI_ADMIN_GATE         0x00
+#define NCI_HCI_IDENTITY_MGMT_GATE 0x05
 #define NCI_HCI_LINK_MGMT_GATE     0x06
 
 /* Pipes */
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 19/35] nfc: st-nci: Change st_nci_gates offset when looking for a pipe in the table
  2015-10-26  6:49 [PATCH v3 00/35] Few fixes and st21nfca/st-nci vendor_cmds support Christophe Ricard
                   ` (10 preceding siblings ...)
  2015-10-26  6:49 ` [PATCH v3 17/35] nfc: st-nci: initialize gate_count in st_nci_hci_network_init Christophe Ricard
@ 2015-10-26  6:49 ` Christophe Ricard
  2015-10-26  6:50 ` [PATCH v3 26/35] nfc: st-nci: Fix host_list verification after secure element activation Christophe Ricard
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:49 UTC (permalink / raw)
  To: sameo
  Cc: linux-nfc, christophe-h.ricard, christophe.ricard, devicetree, stable

It is useless to start from index 0 when looking for a gate because only
dynamic pipes are retrieved with ST_NCI_DM_GETINFO(ST_NCI_DM_GETINFO_PIPE_LIST).

The first dynamic pipe is present at index 3.

Cc: stable@vger.kernel.org
Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com>
---
 drivers/nfc/st-nci/se.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/nfc/st-nci/se.c b/drivers/nfc/st-nci/se.c
index 5d1747d..4c98346 100644
--- a/drivers/nfc/st-nci/se.c
+++ b/drivers/nfc/st-nci/se.c
@@ -228,7 +228,7 @@ int st_nci_hci_load_session(struct nci_dev *ndev)
 			continue;
 		}
 
-		for (j = 0; (j < ARRAY_SIZE(st_nci_gates)) &&
+		for (j = 3; (j < ARRAY_SIZE(st_nci_gates)) &&
 		     (st_nci_gates[j].gate != dm_pipe_info->dst_gate_id); j++)
 			;
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 20/35] nfc: st21nfca: Change st21nfca_gates offset when looking for a pipe in the table
  2015-10-26  6:49 [PATCH v3 00/35] Few fixes and st21nfca/st-nci vendor_cmds support Christophe Ricard
@ 2015-10-26  6:50     ` Christophe Ricard
  2015-10-26  6:49 ` [PATCH v3 05/35] nfc: nci: Fix incorrect data chaining when sending data Christophe Ricard
                       ` (14 subsequent siblings)
  15 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:50 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe-h.ricard-qxv4g6HH51o,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	devicetree-u79uwXL29TY76Z2rM5mHXA, stable-u79uwXL29TY76Z2rM5mHXA

It is useless to start from index 0 when looking for a gate because only
dynamic pipes are retrieved with ST21NFCA_DM_GETINFO(ST21NFCA_DM_GETINFO_PIPE_LIST).

The first dynamic pipe is present at index 3.

Cc: stable-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 drivers/nfc/st21nfca/core.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/nfc/st21nfca/core.c b/drivers/nfc/st21nfca/core.c
index b4451f8..814d8ff4 100644
--- a/drivers/nfc/st21nfca/core.c
+++ b/drivers/nfc/st21nfca/core.c
@@ -85,12 +85,13 @@ static DECLARE_BITMAP(dev_mask, ST21NFCA_NUM_DEVICES);
 
 static struct nfc_hci_gate st21nfca_gates[] = {
 	{NFC_HCI_ADMIN_GATE, NFC_HCI_ADMIN_PIPE},
+	{NFC_HCI_LINK_MGMT_GATE, NFC_HCI_LINK_MGMT_PIPE},
+	{ST21NFCA_DEVICE_MGNT_GATE, ST21NFCA_DEVICE_MGNT_PIPE},
+
 	{NFC_HCI_LOOPBACK_GATE, NFC_HCI_INVALID_PIPE},
 	{NFC_HCI_ID_MGMT_GATE, NFC_HCI_INVALID_PIPE},
-	{NFC_HCI_LINK_MGMT_GATE, NFC_HCI_LINK_MGMT_PIPE},
 	{NFC_HCI_RF_READER_B_GATE, NFC_HCI_INVALID_PIPE},
 	{NFC_HCI_RF_READER_A_GATE, NFC_HCI_INVALID_PIPE},
-	{ST21NFCA_DEVICE_MGNT_GATE, ST21NFCA_DEVICE_MGNT_PIPE},
 	{ST21NFCA_RF_READER_F_GATE, NFC_HCI_INVALID_PIPE},
 	{ST21NFCA_RF_READER_14443_3_A_GATE, NFC_HCI_INVALID_PIPE},
 	{ST21NFCA_RF_READER_ISO15693_GATE, NFC_HCI_INVALID_PIPE},
@@ -183,7 +184,7 @@ static int st21nfca_hci_load_session(struct nfc_hci_dev *hdev)
 			continue;
 		}
 
-		for (j = 0; (j < ARRAY_SIZE(st21nfca_gates)) &&
+		for (j = 3; (j < ARRAY_SIZE(st21nfca_gates)) &&
 			(st21nfca_gates[j].gate != info->dst_gate_id) ; j++)
 			;
 
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 20/35] nfc: st21nfca: Change st21nfca_gates offset when looking for a pipe in the table
@ 2015-10-26  6:50     ` Christophe Ricard
  0 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:50 UTC (permalink / raw)
  To: sameo
  Cc: linux-nfc, christophe-h.ricard, christophe.ricard, devicetree, stable

It is useless to start from index 0 when looking for a gate because only
dynamic pipes are retrieved with ST21NFCA_DM_GETINFO(ST21NFCA_DM_GETINFO_PIPE_LIST).

The first dynamic pipe is present at index 3.

Cc: stable@vger.kernel.org
Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com>
---
 drivers/nfc/st21nfca/core.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/nfc/st21nfca/core.c b/drivers/nfc/st21nfca/core.c
index b4451f8..814d8ff4 100644
--- a/drivers/nfc/st21nfca/core.c
+++ b/drivers/nfc/st21nfca/core.c
@@ -85,12 +85,13 @@ static DECLARE_BITMAP(dev_mask, ST21NFCA_NUM_DEVICES);
 
 static struct nfc_hci_gate st21nfca_gates[] = {
 	{NFC_HCI_ADMIN_GATE, NFC_HCI_ADMIN_PIPE},
+	{NFC_HCI_LINK_MGMT_GATE, NFC_HCI_LINK_MGMT_PIPE},
+	{ST21NFCA_DEVICE_MGNT_GATE, ST21NFCA_DEVICE_MGNT_PIPE},
+
 	{NFC_HCI_LOOPBACK_GATE, NFC_HCI_INVALID_PIPE},
 	{NFC_HCI_ID_MGMT_GATE, NFC_HCI_INVALID_PIPE},
-	{NFC_HCI_LINK_MGMT_GATE, NFC_HCI_LINK_MGMT_PIPE},
 	{NFC_HCI_RF_READER_B_GATE, NFC_HCI_INVALID_PIPE},
 	{NFC_HCI_RF_READER_A_GATE, NFC_HCI_INVALID_PIPE},
-	{ST21NFCA_DEVICE_MGNT_GATE, ST21NFCA_DEVICE_MGNT_PIPE},
 	{ST21NFCA_RF_READER_F_GATE, NFC_HCI_INVALID_PIPE},
 	{ST21NFCA_RF_READER_14443_3_A_GATE, NFC_HCI_INVALID_PIPE},
 	{ST21NFCA_RF_READER_ISO15693_GATE, NFC_HCI_INVALID_PIPE},
@@ -183,7 +184,7 @@ static int st21nfca_hci_load_session(struct nfc_hci_dev *hdev)
 			continue;
 		}
 
-		for (j = 0; (j < ARRAY_SIZE(st21nfca_gates)) &&
+		for (j = 3; (j < ARRAY_SIZE(st21nfca_gates)) &&
 			(st21nfca_gates[j].gate != info->dst_gate_id) ; j++)
 			;
 
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 21/35] nfc: st-nci: Add support for proprietary commands for factory tests
       [not found] ` <1445842215-28403-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (8 preceding siblings ...)
  2015-10-26  6:50     ` Christophe Ricard
@ 2015-10-26  6:50   ` Christophe Ricard
  2015-10-26  6:50   ` [PATCH v3 22/35] nfc: st-nci: Add error messages when an unexpected HCI event occurs Christophe Ricard
                     ` (9 subsequent siblings)
  19 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:50 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe-h.ricard-qxv4g6HH51o,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Add support for proprietary commands useful mainly for factory testings.
Here is a list:
- FACTORY_MODE: Allow to set the driver into a mode where no secure element
are activated. It does not consider any NFC_ATTR_VENDOR_DATA.
- HCI_CLEAR_ALL_PIPES: Allow to execute a HCI clear all pipes command.
It does not consider any NFC_ATTR_VENDOR_DATA.
- HCI_DM_PUT_DATA: Allow to configure specific CLF registry as for example
RF trimmings or low level drivers configurations (I2C, SPI, SWP).
- HCI_DM_UPDATE_AID: Allow to configure an AID routing into the CLF routing
table following RF technology, CLF mode or protocol.
- HCI_DM_GET_INFO: Allow to retrieve CLF information.
- HCI_DM_GET_DATA: Allow to retrieve CLF configurable data such as low
level drivers configurations or RF trimmings.
- HCI_DM_DIRECT_LOAD: Allow to load a firmware into the CLF. A complete
packet can be more than 8KB.
- HCI_DM_RESET: Allow to run a CLF reset in order to "commit" CLF
configuration changes without CLF power off.
-  HCI_GET_PARAM: Allow to retrieve an HCI CLF parameter (for example the
white list).
- HCI_DM_FIELD_GENERATOR: Allow to generate different kind of RF
technology. When using this command to anti-collision is done.
- HCI_LOOPBACK: Allow to echo a command and test the Dh to CLF
connectivity.
- HCI_DM_VDC_MEASUREMENT_VALUE: Allow to measure the field applied on the
CLF antenna. A value between 0 and 0x0f is returned. 0 is maximum.
- HCI_DM_FWUPD_START: Allow to put CLF into firmware update mode. It is a
specific CLF command as there is no GPIO for this.
- HCI_DM_FWUPD_END:  Allow to complete firmware update.
- HCI_DM_VDC_VALUE_COMPARISON: Allow to compare the field applied on the
CLF antenna to a reference value.
- MANUFACTURER_SPECIFIC: Allow to retrieve manufacturer specific data
received during a NCI_CORE_INIT_CMD.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 drivers/nfc/st-nci/Makefile      |   2 +-
 drivers/nfc/st-nci/core.c        |  13 +-
 drivers/nfc/st-nci/se.c          |  29 ++-
 drivers/nfc/st-nci/st-nci.h      |  68 ++++++
 drivers/nfc/st-nci/vendor_cmds.c | 516 +++++++++++++++++++++++++++++++++++++++
 include/net/nfc/nci_core.h       |   1 +
 6 files changed, 619 insertions(+), 10 deletions(-)
 create mode 100644 drivers/nfc/st-nci/vendor_cmds.c

diff --git a/drivers/nfc/st-nci/Makefile b/drivers/nfc/st-nci/Makefile
index 594c63d..ea40ace 100644
--- a/drivers/nfc/st-nci/Makefile
+++ b/drivers/nfc/st-nci/Makefile
@@ -2,7 +2,7 @@
 # Makefile for ST21NFCB NCI based NFC driver
 #
 
-st-nci-objs = ndlc.o core.o se.o
+st-nci-objs = ndlc.o core.o se.o vendor_cmds.o
 obj-$(CONFIG_NFC_ST_NCI)     += st-nci.o
 
 st-nci_i2c-objs = i2c.o
diff --git a/drivers/nfc/st-nci/core.c b/drivers/nfc/st-nci/core.c
index 96997e6..6b083ed 100644
--- a/drivers/nfc/st-nci/core.c
+++ b/drivers/nfc/st-nci/core.c
@@ -152,14 +152,23 @@ int st_nci_probe(struct llt_ndlc *ndlc, int phy_headroom,
 
 	nci_set_drvdata(ndlc->ndev, info);
 
+	r = st_nci_vendor_cmds_init(ndlc->ndev);
+	if (r) {
+		pr_err("Cannot register proprietary vendor cmds\n");
+		goto err_reg_dev;
+	}
+
 	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;
+		goto err_reg_dev;
 	}
 
 	return st_nci_se_init(ndlc->ndev);
+
+err_reg_dev:
+	nci_free_device(ndlc->ndev);
+	return r;
 }
 EXPORT_SYMBOL_GPL(st_nci_probe);
 
diff --git a/drivers/nfc/st-nci/se.c b/drivers/nfc/st-nci/se.c
index 4c98346..7ec4dba 100644
--- a/drivers/nfc/st-nci/se.c
+++ b/drivers/nfc/st-nci/se.c
@@ -39,7 +39,6 @@ struct st_nci_pipe_info {
 #define ST_NCI_ESE_HOST_ID            0xc0
 
 /* Gates */
-#define ST_NCI_DEVICE_MGNT_GATE       0x01
 #define ST_NCI_APDU_READER_GATE       0xf0
 #define ST_NCI_CONNECTIVITY_GATE      0x41
 
@@ -114,6 +113,8 @@ static struct nci_hci_gate st_nci_gates[] = {
 
 	{NCI_HCI_IDENTITY_MGMT_GATE, NCI_HCI_INVALID_PIPE,
 					ST_NCI_HOST_CONTROLLER_ID},
+	{NCI_HCI_LOOPBACK_GATE, NCI_HCI_INVALID_PIPE,
+					ST_NCI_HOST_CONTROLLER_ID},
 
 	/* Secure element pipes are created by secure element host */
 	{ST_NCI_CONNECTIVITY_GATE, NCI_HCI_DO_NOT_OPEN_PIPE,
@@ -376,8 +377,10 @@ void st_nci_hci_event_received(struct nci_dev *ndev, u8 pipe,
 		st_nci_hci_apdu_reader_event_received(ndev, event, skb);
 	break;
 	case ST_NCI_CONNECTIVITY_GATE:
-		st_nci_hci_connectivity_event_received(ndev, host, event,
-							 skb);
+		st_nci_hci_connectivity_event_received(ndev, host, event, skb);
+	break;
+	case NCI_HCI_LOOPBACK_GATE:
+		st_nci_hci_loopback_event_received(ndev, event, skb);
 	break;
 	}
 }
@@ -509,6 +512,7 @@ EXPORT_SYMBOL_GPL(st_nci_enable_se);
 
 static int st_nci_hci_network_init(struct nci_dev *ndev)
 {
+	struct st_nci_info *info = nci_get_drvdata(ndev);
 	struct core_conn_create_dest_spec_params *dest_params;
 	struct dest_spec_params spec_params;
 	struct nci_conn_info    *conn_info;
@@ -561,10 +565,17 @@ static int st_nci_hci_network_init(struct nci_dev *ndev)
 	if (r != NCI_HCI_ANY_OK)
 		goto free_dest_params;
 
-	r = nci_nfcee_mode_set(ndev, ndev->hci_dev->conn_info->id,
-			       NCI_NFCEE_ENABLE);
-	if (r != NCI_STATUS_OK)
-		goto free_dest_params;
+	/*
+	 * In factory mode, we prevent secure elements activation
+	 * by disabling nfcee on the current HCI connection id.
+	 * HCI will be used here only for proprietary commands.
+	 */
+	if (test_bit(ST_NCI_FACTORY_MODE, &info->flags))
+		r = nci_nfcee_mode_set(ndev, ndev->hci_dev->conn_info->id,
+				       NCI_NFCEE_DISABLE);
+	else
+		r = nci_nfcee_mode_set(ndev, ndev->hci_dev->conn_info->id,
+				       NCI_NFCEE_ENABLE);
 
 free_dest_params:
 	kfree(dest_params);
@@ -578,6 +589,7 @@ int st_nci_discover_se(struct nci_dev *ndev)
 	u8 param[2];
 	int r;
 	int se_count = 0;
+	struct st_nci_info *info = nci_get_drvdata(ndev);
 
 	pr_debug("st_nci_discover_se\n");
 
@@ -585,6 +597,9 @@ int st_nci_discover_se(struct nci_dev *ndev)
 	if (r != 0)
 		return r;
 
+	if (test_bit(ST_NCI_FACTORY_MODE, &info->flags))
+		return 0;
+
 	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,
diff --git a/drivers/nfc/st-nci/st-nci.h b/drivers/nfc/st-nci/st-nci.h
index 5d3f4d9..c68d538 100644
--- a/drivers/nfc/st-nci/st-nci.h
+++ b/drivers/nfc/st-nci/st-nci.h
@@ -34,6 +34,11 @@
 #define ST_NCI_ESE_MAX_LENGTH	33
 #define ST_NCI_HCI_HOST_ID_ESE	0xc0
 
+#define ST_NCI_DEVICE_MGNT_GATE		0x01
+
+#define ST_NCI_VENDOR_OUI 0x0080E1 /* STMicroelectronics */
+#define ST_NCI_FACTORY_MODE 2
+
 struct nci_mode_set_cmd {
 	u8 cmd_type;
 	u8 mode;
@@ -60,10 +65,69 @@ struct st_nci_se_info {
 	void *cb_context;
 };
 
+/**
+ * enum nfc_vendor_cmds - supported nfc vendor commands
+ *
+ * @FACTORY_MODE: Allow to set the driver into a mode where no secure element
+ *	are activated. It does not consider any NFC_ATTR_VENDOR_DATA.
+ * @HCI_CLEAR_ALL_PIPES: Allow to execute a HCI clear all pipes command.
+ *	It does not consider any NFC_ATTR_VENDOR_DATA.
+ * @HCI_DM_PUT_DATA: Allow to configure specific CLF registry as for example
+ *	RF trimmings or low level drivers configurations (I2C, SPI, SWP).
+ * @HCI_DM_UPDATE_AID: Allow to configure an AID routing into the CLF routing
+ *	table following RF technology, CLF mode or protocol.
+ * @HCI_DM_GET_INFO: Allow to retrieve CLF information.
+ * @HCI_DM_GET_DATA: Allow to retrieve CLF configurable data such as low
+ *	level drivers configurations or RF trimmings.
+ * @HCI_DM_DIRECT_LOAD: Allow to load a firmware into the CLF. A complete
+ *	packet can be more than 8KB.
+ * @HCI_DM_RESET: Allow to run a CLF reset in order to "commit" CLF
+ *	configuration changes without CLF power off.
+ * @HCI_GET_PARAM: Allow to retrieve an HCI CLF parameter (for example the
+ *	white list).
+ * @HCI_DM_FIELD_GENERATOR: Allow to generate different kind of RF
+ *	technology. When using this command to anti-collision is done.
+ * @HCI_LOOPBACK: Allow to echo a command and test the Dh to CLF
+ *	connectivity.
+ * @HCI_DM_VDC_MEASUREMENT_VALUE: Allow to measure the field applied on the
+ *	CLF antenna. A value between 0 and 0x0f is returned. 0 is maximum.
+ * @HCI_DM_FWUPD_START: Allow to put CLF into firmware update mode. It is a
+ *	specific CLF command as there is no GPIO for this.
+ * @HCI_DM_FWUPD_END:  Allow to complete firmware update.
+ * @HCI_DM_VDC_VALUE_COMPARISON: Allow to compare the field applied on the
+ *	CLF antenna to a reference value.
+ * @MANUFACTURER_SPECIFIC: Allow to retrieve manufacturer specific data
+ *	received during a NCI_CORE_INIT_CMD.
+ */
+enum nfc_vendor_cmds {
+	FACTORY_MODE,
+	HCI_CLEAR_ALL_PIPES,
+	HCI_DM_PUT_DATA,
+	HCI_DM_UPDATE_AID,
+	HCI_DM_GET_INFO,
+	HCI_DM_GET_DATA,
+	HCI_DM_DIRECT_LOAD,
+	HCI_DM_RESET,
+	HCI_GET_PARAM,
+	HCI_DM_FIELD_GENERATOR,
+	HCI_LOOPBACK,
+	HCI_DM_FWUPD_START,
+	HCI_DM_FWUPD_END,
+	HCI_DM_VDC_MEASUREMENT_VALUE,
+	HCI_DM_VDC_VALUE_COMPARISON,
+	MANUFACTURER_SPECIFIC,
+};
+
+struct st_nci_vendor_info {
+	struct completion req_completion;
+	struct sk_buff *rx_skb;
+};
+
 struct st_nci_info {
 	struct llt_ndlc *ndlc;
 	unsigned long flags;
 	struct st_nci_se_info se_info;
+	struct st_nci_vendor_info vendor_info;
 };
 
 void st_nci_remove(struct nci_dev *ndev);
@@ -85,4 +149,8 @@ void st_nci_hci_event_received(struct nci_dev *ndev, u8 pipe,
 void st_nci_hci_cmd_received(struct nci_dev *ndev, u8 pipe, u8 cmd,
 			struct sk_buff *skb);
 
+void st_nci_hci_loopback_event_received(struct nci_dev *ndev, u8 event,
+					 struct sk_buff *skb);
+int st_nci_vendor_cmds_init(struct nci_dev *ndev);
+
 #endif /* __LOCAL_ST_NCI_H_ */
diff --git a/drivers/nfc/st-nci/vendor_cmds.c b/drivers/nfc/st-nci/vendor_cmds.c
new file mode 100644
index 0000000..b5debce
--- /dev/null
+++ b/drivers/nfc/st-nci/vendor_cmds.c
@@ -0,0 +1,516 @@
+/*
+ * Proprietary commands extension 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/>.
+ */
+
+#include <net/genetlink.h>
+#include <linux/module.h>
+#include <linux/nfc.h>
+#include <linux/delay.h>
+#include <net/nfc/nci_core.h>
+
+#include "st-nci.h"
+
+#define ST_NCI_HCI_DM_GETDATA			0x10
+#define ST_NCI_HCI_DM_PUTDATA			0x11
+#define ST_NCI_HCI_DM_LOAD			0x12
+#define ST_NCI_HCI_DM_GETINFO			0x13
+#define ST_NCI_HCI_DM_FWUPD_START		0x14
+#define ST_NCI_HCI_DM_FWUPD_STOP		0x15
+#define ST_NCI_HCI_DM_UPDATE_AID		0x20
+#define ST_NCI_HCI_DM_RESET			0x3e
+
+#define ST_NCI_HCI_DM_FIELD_GENERATOR		0x32
+#define ST_NCI_HCI_DM_VDC_MEASUREMENT_VALUE	0x33
+#define ST_NCI_HCI_DM_VDC_VALUE_COMPARISON	0x34
+
+#define ST_NCI_FACTORY_MODE_ON			1
+#define ST_NCI_FACTORY_MODE_OFF			0
+
+#define ST_NCI_EVT_POST_DATA			0x02
+
+struct get_param_data {
+	u8 gate;
+	u8 data;
+} __packed;
+
+static int st_nci_factory_mode(struct nfc_dev *dev, void *data,
+			       size_t data_len)
+{
+	struct nci_dev *ndev = nfc_get_drvdata(dev);
+	struct st_nci_info *info = nci_get_drvdata(ndev);
+
+	if (data_len != 1)
+		return -EINVAL;
+
+	pr_debug("factory mode: %x\n", ((u8 *)data)[0]);
+
+	switch (((u8 *)data)[0]) {
+	case ST_NCI_FACTORY_MODE_ON:
+		test_and_set_bit(ST_NCI_FACTORY_MODE, &info->flags);
+	break;
+	case ST_NCI_FACTORY_MODE_OFF:
+		clear_bit(ST_NCI_FACTORY_MODE, &info->flags);
+	break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int st_nci_hci_clear_all_pipes(struct nfc_dev *dev, void *data,
+				      size_t data_len)
+{
+	struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+	return nci_hci_clear_all_pipes(ndev);
+}
+
+static int st_nci_hci_dm_put_data(struct nfc_dev *dev, void *data,
+				  size_t data_len)
+{
+	struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+	return nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
+				ST_NCI_HCI_DM_PUTDATA, data,
+				data_len, NULL);
+}
+
+static int st_nci_hci_dm_update_aid(struct nfc_dev *dev, void *data,
+				    size_t data_len)
+{
+	struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+	return nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
+			ST_NCI_HCI_DM_UPDATE_AID, data, data_len, NULL);
+}
+
+static int st_nci_hci_dm_get_info(struct nfc_dev *dev, void *data,
+				  size_t data_len)
+{
+	int r;
+	struct sk_buff *msg, *skb;
+	struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+	r = nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE, ST_NCI_HCI_DM_GETINFO,
+			     data, data_len, &skb);
+	if (r)
+		goto exit;
+
+	msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST_NCI_VENDOR_OUI,
+					     HCI_DM_GET_INFO, skb->len);
+	if (!msg) {
+		r = -ENOMEM;
+		goto free_skb;
+	}
+
+	if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) {
+		kfree_skb(msg);
+		r = -ENOBUFS;
+		goto free_skb;
+	}
+
+	r = nfc_vendor_cmd_reply(msg);
+
+free_skb:
+	kfree_skb(skb);
+exit:
+	return r;
+}
+
+static int st_nci_hci_dm_get_data(struct nfc_dev *dev, void *data,
+				  size_t data_len)
+{
+	int r;
+	struct sk_buff *msg, *skb;
+	struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+	r = nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE, ST_NCI_HCI_DM_GETDATA,
+			     data, data_len, &skb);
+	if (r)
+		goto exit;
+
+	msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST_NCI_VENDOR_OUI,
+					     HCI_DM_GET_DATA, skb->len);
+	if (!msg) {
+		r = -ENOMEM;
+		goto free_skb;
+	}
+
+	if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) {
+		kfree_skb(msg);
+		r = -ENOBUFS;
+		goto free_skb;
+	}
+
+	r = nfc_vendor_cmd_reply(msg);
+
+free_skb:
+	kfree_skb(skb);
+exit:
+	return r;
+}
+
+static int st_nci_hci_dm_fwupd_start(struct nfc_dev *dev, void *data,
+				     size_t data_len)
+{
+	int r;
+	struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+	dev->fw_download_in_progress = true;
+	r = nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
+			ST_NCI_HCI_DM_FWUPD_START, data, data_len, NULL);
+	if (r)
+		dev->fw_download_in_progress = false;
+
+	return r;
+}
+
+static int st_nci_hci_dm_fwupd_end(struct nfc_dev *dev, void *data,
+				   size_t data_len)
+{
+	struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+	return nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
+			ST_NCI_HCI_DM_FWUPD_STOP, data, data_len, NULL);
+}
+
+static int st_nci_hci_dm_direct_load(struct nfc_dev *dev, void *data,
+				     size_t data_len)
+{
+	struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+	if (dev->fw_download_in_progress) {
+		dev->fw_download_in_progress = false;
+		return nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
+				ST_NCI_HCI_DM_LOAD, data, data_len, NULL);
+	}
+	return -EPROTO;
+}
+
+static int st_nci_hci_dm_reset(struct nfc_dev *dev, void *data,
+			       size_t data_len)
+{
+	struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+	nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
+			ST_NCI_HCI_DM_RESET, data, data_len, NULL);
+	msleep(200);
+
+	return 0;
+}
+
+static int st_nci_hci_get_param(struct nfc_dev *dev, void *data,
+				size_t data_len)
+{
+	int r;
+	struct sk_buff *msg, *skb;
+	struct nci_dev *ndev = nfc_get_drvdata(dev);
+	struct get_param_data *param = (struct get_param_data *)data;
+
+	if (data_len < sizeof(struct get_param_data))
+		return -EPROTO;
+
+	r = nci_hci_get_param(ndev, param->gate, param->data, &skb);
+	if (r)
+		goto exit;
+
+	msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST_NCI_VENDOR_OUI,
+					     HCI_GET_PARAM, skb->len);
+	if (!msg) {
+		r = -ENOMEM;
+		goto free_skb;
+	}
+
+	if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) {
+		kfree_skb(msg);
+		r = -ENOBUFS;
+		goto free_skb;
+	}
+
+	r = nfc_vendor_cmd_reply(msg);
+
+free_skb:
+	kfree_skb(skb);
+exit:
+	return r;
+}
+
+static int st_nci_hci_dm_field_generator(struct nfc_dev *dev, void *data,
+					 size_t data_len)
+{
+	struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+	return nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
+				ST_NCI_HCI_DM_FIELD_GENERATOR, data, data_len, NULL);
+}
+
+static int st_nci_hci_dm_vdc_measurement_value(struct nfc_dev *dev, void *data,
+					       size_t data_len)
+{
+	int r;
+	struct sk_buff *msg, *skb;
+	struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+	if (data_len != 4)
+		return -EPROTO;
+
+	r = nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
+			     ST_NCI_HCI_DM_VDC_MEASUREMENT_VALUE,
+			     data, data_len, &skb);
+	if (r)
+		goto exit;
+
+	msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST_NCI_VENDOR_OUI,
+				HCI_DM_VDC_MEASUREMENT_VALUE, skb->len);
+	if (!msg) {
+		r = -ENOMEM;
+		goto free_skb;
+	}
+
+	if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) {
+		kfree_skb(msg);
+		r = -ENOBUFS;
+		goto free_skb;
+	}
+
+	r = nfc_vendor_cmd_reply(msg);
+
+free_skb:
+	kfree_skb(skb);
+exit:
+	return r;
+}
+
+static int st_nci_hci_dm_vdc_value_comparison(struct nfc_dev *dev, void *data,
+					      size_t data_len)
+{
+	int r;
+	struct sk_buff *msg, *skb;
+	struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+	if (data_len != 2)
+		return -EPROTO;
+
+	r = nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
+			     ST_NCI_HCI_DM_VDC_VALUE_COMPARISON,
+			     data, data_len, &skb);
+	if (r)
+		goto exit;
+
+	msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST_NCI_VENDOR_OUI,
+					HCI_DM_VDC_VALUE_COMPARISON, skb->len);
+	if (!msg) {
+		r = -ENOMEM;
+		goto free_skb;
+	}
+
+	if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) {
+		kfree_skb(msg);
+		r = -ENOBUFS;
+		goto free_skb;
+	}
+
+	r = nfc_vendor_cmd_reply(msg);
+
+free_skb:
+	kfree_skb(skb);
+exit:
+	return r;
+}
+
+void st_nci_hci_loopback_event_received(struct nci_dev *ndev, u8 event,
+					struct sk_buff *skb)
+{
+	struct st_nci_info *info = nci_get_drvdata(ndev);
+
+	switch (event) {
+	case ST_NCI_EVT_POST_DATA:
+		info->vendor_info.rx_skb = skb;
+	break;
+	default:
+		nfc_err(&ndev->nfc_dev->dev, "Unexpected event on loopback gate\n");
+	}
+	complete(&info->vendor_info.req_completion);
+}
+EXPORT_SYMBOL(st_nci_hci_loopback_event_received);
+
+static int st_nci_hci_loopback(struct nfc_dev *dev, void *data,
+			       size_t data_len)
+{
+	int r;
+	struct sk_buff *msg;
+	struct nci_dev *ndev = nfc_get_drvdata(dev);
+	struct st_nci_info *info = nci_get_drvdata(ndev);
+
+	if (data_len <= 0)
+		return -EPROTO;
+
+	reinit_completion(&info->vendor_info.req_completion);
+	info->vendor_info.rx_skb = NULL;
+
+	r = nci_hci_send_event(ndev, NCI_HCI_LOOPBACK_GATE,
+			       ST_NCI_EVT_POST_DATA, data, data_len);
+	if (r != data_len) {
+		r = -EPROTO;
+		goto exit;
+	}
+
+	wait_for_completion_interruptible(&info->vendor_info.req_completion);
+
+	if (!info->vendor_info.rx_skb ||
+	    info->vendor_info.rx_skb->len != data_len) {
+		r = -EPROTO;
+		goto exit;
+	}
+
+	msg = nfc_vendor_cmd_alloc_reply_skb(ndev->nfc_dev,
+					ST_NCI_VENDOR_OUI,
+					HCI_LOOPBACK,
+					info->vendor_info.rx_skb->len);
+	if (!msg) {
+		r = -ENOMEM;
+		goto free_skb;
+	}
+
+	if (nla_put(msg, NFC_ATTR_VENDOR_DATA, info->vendor_info.rx_skb->len,
+		    info->vendor_info.rx_skb->data)) {
+		kfree_skb(msg);
+		r = -ENOBUFS;
+		goto free_skb;
+	}
+
+	r = nfc_vendor_cmd_reply(msg);
+free_skb:
+	kfree_skb(info->vendor_info.rx_skb);
+exit:
+	return r;
+}
+
+static int st_nci_manufacturer_specific(struct nfc_dev *dev, void *data,
+					size_t data_len)
+{
+	struct sk_buff *msg;
+	struct nci_dev *ndev = nfc_get_drvdata(dev);
+
+	msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST_NCI_VENDOR_OUI,
+					MANUFACTURER_SPECIFIC,
+					sizeof(ndev->manufact_specific_info));
+	if (!msg)
+		return -ENOMEM;
+
+	if (nla_put(msg, NFC_ATTR_VENDOR_DATA, sizeof(ndev->manufact_specific_info),
+		    &ndev->manufact_specific_info)) {
+		kfree_skb(msg);
+		return -ENOBUFS;
+	}
+
+	return nfc_vendor_cmd_reply(msg);
+}
+
+static struct nfc_vendor_cmd st_nci_vendor_cmds[] = {
+	{
+		.vendor_id = ST_NCI_VENDOR_OUI,
+		.subcmd = FACTORY_MODE,
+		.doit = st_nci_factory_mode,
+	},
+	{
+		.vendor_id = ST_NCI_VENDOR_OUI,
+		.subcmd = HCI_CLEAR_ALL_PIPES,
+		.doit = st_nci_hci_clear_all_pipes,
+	},
+	{
+		.vendor_id = ST_NCI_VENDOR_OUI,
+		.subcmd = HCI_DM_PUT_DATA,
+		.doit = st_nci_hci_dm_put_data,
+	},
+	{
+		.vendor_id = ST_NCI_VENDOR_OUI,
+		.subcmd = HCI_DM_UPDATE_AID,
+		.doit = st_nci_hci_dm_update_aid,
+	},
+	{
+		.vendor_id = ST_NCI_VENDOR_OUI,
+		.subcmd = HCI_DM_GET_INFO,
+		.doit = st_nci_hci_dm_get_info,
+	},
+	{
+		.vendor_id = ST_NCI_VENDOR_OUI,
+		.subcmd = HCI_DM_GET_DATA,
+		.doit = st_nci_hci_dm_get_data,
+	},
+	{
+		.vendor_id = ST_NCI_VENDOR_OUI,
+		.subcmd = HCI_DM_DIRECT_LOAD,
+		.doit = st_nci_hci_dm_direct_load,
+	},
+	{
+		.vendor_id = ST_NCI_VENDOR_OUI,
+		.subcmd = HCI_DM_RESET,
+		.doit = st_nci_hci_dm_reset,
+	},
+	{
+		.vendor_id = ST_NCI_VENDOR_OUI,
+		.subcmd = HCI_GET_PARAM,
+		.doit = st_nci_hci_get_param,
+	},
+	{
+		.vendor_id = ST_NCI_VENDOR_OUI,
+		.subcmd = HCI_DM_FIELD_GENERATOR,
+		.doit = st_nci_hci_dm_field_generator,
+	},
+	{
+		.vendor_id = ST_NCI_VENDOR_OUI,
+		.subcmd = HCI_DM_FWUPD_START,
+		.doit = st_nci_hci_dm_fwupd_start,
+	},
+	{
+		.vendor_id = ST_NCI_VENDOR_OUI,
+		.subcmd = HCI_DM_FWUPD_END,
+		.doit = st_nci_hci_dm_fwupd_end,
+	},
+	{
+		.vendor_id = ST_NCI_VENDOR_OUI,
+		.subcmd = HCI_LOOPBACK,
+		.doit = st_nci_hci_loopback,
+	},
+	{
+		.vendor_id = ST_NCI_VENDOR_OUI,
+		.subcmd = HCI_DM_VDC_MEASUREMENT_VALUE,
+		.doit = st_nci_hci_dm_vdc_measurement_value,
+	},
+	{
+		.vendor_id = ST_NCI_VENDOR_OUI,
+		.subcmd = HCI_DM_VDC_VALUE_COMPARISON,
+		.doit = st_nci_hci_dm_vdc_value_comparison,
+	},
+	{
+		.vendor_id = ST_NCI_VENDOR_OUI,
+		.subcmd = MANUFACTURER_SPECIFIC,
+		.doit = st_nci_manufacturer_specific,
+	},
+};
+
+int st_nci_vendor_cmds_init(struct nci_dev *ndev)
+{
+	struct st_nci_info *info = nci_get_drvdata(ndev);
+
+	init_completion(&info->vendor_info.req_completion);
+	return nfc_set_vendor_cmds(ndev->nfc_dev, st_nci_vendor_cmds,
+				   sizeof(st_nci_vendor_cmds));
+}
+EXPORT_SYMBOL(st_nci_vendor_cmds_init);
diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h
index 377f3de..591338f 100644
--- a/include/net/nfc/nci_core.h
+++ b/include/net/nfc/nci_core.h
@@ -125,6 +125,7 @@ struct nci_conn_info {
 
 /* Gates */
 #define NCI_HCI_ADMIN_GATE         0x00
+#define NCI_HCI_LOOPBACK_GATE	   0x04
 #define NCI_HCI_IDENTITY_MGMT_GATE 0x05
 #define NCI_HCI_LINK_MGMT_GATE     0x06
 
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 22/35] nfc: st-nci: Add error messages when an unexpected HCI event occurs
       [not found] ` <1445842215-28403-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (9 preceding siblings ...)
  2015-10-26  6:50   ` [PATCH v3 21/35] nfc: st-nci: Add support for proprietary commands for factory tests Christophe Ricard
@ 2015-10-26  6:50   ` Christophe Ricard
  2015-10-26  6:50   ` [PATCH v3 23/35] nfc: netlink: Add missing NFC_ATTR comments Christophe Ricard
                     ` (8 subsequent siblings)
  19 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:50 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe-h.ricard-qxv4g6HH51o,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Potentially an unexpected HCI event may occur because of a firmware bug.
It could be transparent for the user but at least log this.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 drivers/nfc/st-nci/se.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/nfc/st-nci/se.c b/drivers/nfc/st-nci/se.c
index 7ec4dba..2812884 100644
--- a/drivers/nfc/st-nci/se.c
+++ b/drivers/nfc/st-nci/se.c
@@ -280,6 +280,8 @@ static void st_nci_hci_admin_event_received(struct nci_dev *ndev,
 			}
 		}
 	break;
+	default:
+		nfc_err(&ndev->nfc_dev->dev, "Unexpected event on admin gate\n");
 	}
 }
 
@@ -303,6 +305,9 @@ static int st_nci_hci_apdu_reader_event_received(struct nci_dev *ndev,
 		mod_timer(&info->se_info.bwi_timer, jiffies +
 			  msecs_to_jiffies(info->se_info.wt_timeout));
 	break;
+	default:
+		nfc_err(&ndev->nfc_dev->dev, "Unexpected event on apdu reader gate\n");
+		return 1;
 	}
 
 	kfree_skb(skb);
@@ -357,6 +362,7 @@ static int st_nci_hci_connectivity_event_received(struct nci_dev *ndev,
 		r = nfc_se_transaction(ndev->nfc_dev, host, transaction);
 		break;
 	default:
+		nfc_err(&ndev->nfc_dev->dev, "Unexpected event on connectivity gate\n");
 		return 1;
 	}
 	kfree_skb(skb);
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 23/35] nfc: netlink: Add missing NFC_ATTR comments
       [not found] ` <1445842215-28403-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (10 preceding siblings ...)
  2015-10-26  6:50   ` [PATCH v3 22/35] nfc: st-nci: Add error messages when an unexpected HCI event occurs Christophe Ricard
@ 2015-10-26  6:50   ` Christophe Ricard
  2015-10-26  6:50   ` [PATCH v3 24/35] nfc: st-nci: Add ese-present/uicc-present dts properties Christophe Ricard
                     ` (7 subsequent siblings)
  19 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:50 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe-h.ricard-qxv4g6HH51o,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	devicetree-u79uwXL29TY76Z2rM5mHXA

NFC_CMD_ACTIVATE_TARGET and NFC_ATTR_SE_PARAMS comments are missing.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 include/uapi/linux/nfc.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/uapi/linux/nfc.h b/include/uapi/linux/nfc.h
index dd3f753..399f39f 100644
--- a/include/uapi/linux/nfc.h
+++ b/include/uapi/linux/nfc.h
@@ -86,6 +86,7 @@
  *	for this event is the application ID (AID).
  * @NFC_CMD_GET_SE: Dump all discovered secure elements from an NFC controller.
  * @NFC_CMD_SE_IO: Send/Receive APDUs to/from the selected secure element.
+ * @NFC_CMD_ACTIVATE_TARGET: Request NFC controller to reactivate target.
  * @NFC_CMD_VENDOR: Vendor specific command, to be implemented directly
  *	from the driver in order to support hardware specific operations.
  */
@@ -156,6 +157,7 @@ enum nfc_commands {
  * @NFC_ATTR_APDU: Secure element APDU
  * @NFC_ATTR_TARGET_ISO15693_DSFID: ISO 15693 Data Storage Format Identifier
  * @NFC_ATTR_TARGET_ISO15693_UID: ISO 15693 Unique Identifier
+ * @NFC_ATTR_SE_PARAMS: Parameters data from an evt_transaction
  * @NFC_ATTR_VENDOR_ID: NFC manufacturer unique ID, typically an OUI
  * @NFC_ATTR_VENDOR_SUBCMD: Vendor specific sub command
  * @NFC_ATTR_VENDOR_DATA: Vendor specific data, to be optionally passed
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 24/35] nfc: st-nci: Add ese-present/uicc-present dts properties
       [not found] ` <1445842215-28403-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (11 preceding siblings ...)
  2015-10-26  6:50   ` [PATCH v3 23/35] nfc: netlink: Add missing NFC_ATTR comments Christophe Ricard
@ 2015-10-26  6:50   ` Christophe Ricard
  2015-10-26  6:50   ` [PATCH v3 25/35] nfc: st-nci: Increase waiting time between 2 secure element activation Christophe Ricard
                     ` (6 subsequent siblings)
  19 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:50 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe-h.ricard-qxv4g6HH51o,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	devicetree-u79uwXL29TY76Z2rM5mHXA

In order to align with st21nfca, dts configuration properties ese_present
and uicc_present are made available in st-nci driver.

So far, in early development firmware, because nci_nfcee_mode_set(DISABLE)
was not supported pushed us to try to enable during the secure element
discovery phase.

After several trials on commercial and qualified firmware it appears that
nci_nfcee_mode_set(ENABLE) and nci_nfcee_mode_set(DISABLE) are properly
supported.

Such feature also help us to eventually save some time (~5ms) if only
one secure element is connected.

Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 .../devicetree/bindings/net/nfc/st-nci-i2c.txt     |  7 ++
 .../devicetree/bindings/net/nfc/st-nci-spi.txt     |  9 +-
 drivers/nfc/st-nci/core.c                          |  4 +-
 drivers/nfc/st-nci/i2c.c                           | 12 ++-
 drivers/nfc/st-nci/ndlc.c                          |  6 +-
 drivers/nfc/st-nci/ndlc.h                          |  5 +-
 drivers/nfc/st-nci/se.c                            | 98 ++++++++++++++--------
 drivers/nfc/st-nci/spi.c                           | 12 ++-
 drivers/nfc/st-nci/st-nci.h                        | 13 ++-
 include/linux/platform_data/st-nci.h               |  2 +
 10 files changed, 122 insertions(+), 46 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/nfc/st-nci-i2c.txt b/Documentation/devicetree/bindings/net/nfc/st-nci-i2c.txt
index d707588..263732e 100644
--- a/Documentation/devicetree/bindings/net/nfc/st-nci-i2c.txt
+++ b/Documentation/devicetree/bindings/net/nfc/st-nci-i2c.txt
@@ -11,6 +11,10 @@ Required properties:
 Optional SoC Specific Properties:
 - pinctrl-names: Contains only one value - "default".
 - pintctrl-0: Specifies the pin control groups used for this controller.
+- ese-present: Specifies that an ese is physically connected to the nfc
+controller.
+- uicc-present: Specifies that the uicc swp signal can be physically
+connected to the nfc controller.
 
 Example (for ARM-based BeagleBoard xM with ST21NFCB on I2C2):
 
@@ -29,5 +33,8 @@ Example (for ARM-based BeagleBoard xM with ST21NFCB on I2C2):
 		interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
 
 		reset-gpios = <&gpio5 29 GPIO_ACTIVE_HIGH>;
+
+		ese-present;
+		uicc-present;
 	};
 };
diff --git a/Documentation/devicetree/bindings/net/nfc/st-nci-spi.txt b/Documentation/devicetree/bindings/net/nfc/st-nci-spi.txt
index 525681b..711ca85 100644
--- a/Documentation/devicetree/bindings/net/nfc/st-nci-spi.txt
+++ b/Documentation/devicetree/bindings/net/nfc/st-nci-spi.txt
@@ -2,7 +2,7 @@
 
 Required properties:
 - compatible: Should be "st,st21nfcb-spi"
-- spi-max-frequency: Maximum SPI frequency (<= 10000000).
+- spi-max-frequency: Maximum SPI frequency (<= 4000000).
 - interrupt-parent: phandle for the interrupt gpio controller
 - interrupts: GPIO interrupt to which the chip is connected
 - reset-gpios: Output GPIO pin used to reset the ST21NFCB
@@ -10,6 +10,10 @@ Required properties:
 Optional SoC Specific Properties:
 - pinctrl-names: Contains only one value - "default".
 - pintctrl-0: Specifies the pin control groups used for this controller.
+- ese-present: Specifies that an ese is physically connected to the nfc
+controller.
+- uicc-present: Specifies that the uicc swp signal can be physically
+connected to the nfc controller.
 
 Example (for ARM-based BeagleBoard xM with ST21NFCB on SPI4):
 
@@ -27,5 +31,8 @@ Example (for ARM-based BeagleBoard xM with ST21NFCB on SPI4):
 		interrupts = <2 IRQ_TYPE_EDGE_RISING>;
 
 		reset-gpios = <&gpio5 29 GPIO_ACTIVE_HIGH>;
+
+		ese-present;
+		uicc-present;
 	};
 };
diff --git a/drivers/nfc/st-nci/core.c b/drivers/nfc/st-nci/core.c
index 6b083ed..ccf7237 100644
--- a/drivers/nfc/st-nci/core.c
+++ b/drivers/nfc/st-nci/core.c
@@ -123,7 +123,7 @@ static struct nci_ops st_nci_ops = {
 };
 
 int st_nci_probe(struct llt_ndlc *ndlc, int phy_headroom,
-		       int phy_tailroom)
+		 int phy_tailroom, struct st_nci_se_status *se_status)
 {
 	struct st_nci_info *info;
 	int r;
@@ -164,7 +164,7 @@ int st_nci_probe(struct llt_ndlc *ndlc, int phy_headroom,
 		goto err_reg_dev;
 	}
 
-	return st_nci_se_init(ndlc->ndev);
+	return st_nci_se_init(ndlc->ndev, se_status);
 
 err_reg_dev:
 	nci_free_device(ndlc->ndev);
diff --git a/drivers/nfc/st-nci/i2c.c b/drivers/nfc/st-nci/i2c.c
index 02e585f..172cbc3 100644
--- a/drivers/nfc/st-nci/i2c.c
+++ b/drivers/nfc/st-nci/i2c.c
@@ -52,6 +52,8 @@ struct st_nci_i2c_phy {
 
 	unsigned int gpio_reset;
 	unsigned int irq_polarity;
+
+	struct st_nci_se_status se_status;
 };
 
 #define I2C_DUMP_SKB(info, skb)					\
@@ -245,6 +247,11 @@ static int st_nci_i2c_of_request_resources(struct i2c_client *client)
 
 	phy->irq_polarity = irq_get_trigger_type(client->irq);
 
+	phy->se_status.is_ese_present =
+				of_property_read_bool(pp, "ese-present");
+	phy->se_status.is_uicc_present =
+				of_property_read_bool(pp, "uicc-present");
+
 	return 0;
 }
 #else
@@ -277,6 +284,9 @@ static int st_nci_i2c_request_resources(struct i2c_client *client)
 		return r;
 	}
 
+	phy->se_status.is_ese_present = pdata->is_ese_present;
+	phy->se_status.is_uicc_present = pdata->is_uicc_present;
+
 	return 0;
 }
 
@@ -326,7 +336,7 @@ static int st_nci_i2c_probe(struct i2c_client *client,
 
 	r = ndlc_probe(phy, &i2c_phy_ops, &client->dev,
 			ST_NCI_FRAME_HEADROOM, ST_NCI_FRAME_TAILROOM,
-			&phy->ndlc);
+			&phy->ndlc, &phy->se_status);
 	if (r < 0) {
 		nfc_err(&client->dev, "Unable to register ndlc layer\n");
 		return r;
diff --git a/drivers/nfc/st-nci/ndlc.c b/drivers/nfc/st-nci/ndlc.c
index fb50007..0884b11 100644
--- a/drivers/nfc/st-nci/ndlc.c
+++ b/drivers/nfc/st-nci/ndlc.c
@@ -20,6 +20,7 @@
 #include <net/nfc/nci_core.h>
 
 #include "st-nci.h"
+#include "ndlc.h"
 
 #define NDLC_TIMER_T1		100
 #define NDLC_TIMER_T1_WAIT	400
@@ -265,7 +266,8 @@ static void ndlc_t2_timeout(unsigned long data)
 }
 
 int ndlc_probe(void *phy_id, struct nfc_phy_ops *phy_ops, struct device *dev,
-	       int phy_headroom, int phy_tailroom, struct llt_ndlc **ndlc_id)
+	       int phy_headroom, int phy_tailroom, struct llt_ndlc **ndlc_id,
+	       struct st_nci_se_status *se_status)
 {
 	struct llt_ndlc *ndlc;
 
@@ -295,7 +297,7 @@ 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 st_nci_probe(ndlc, phy_headroom, phy_tailroom);
+	return st_nci_probe(ndlc, phy_headroom, phy_tailroom, se_status);
 }
 EXPORT_SYMBOL(ndlc_probe);
 
diff --git a/drivers/nfc/st-nci/ndlc.h b/drivers/nfc/st-nci/ndlc.h
index 6361005..bdf78ff 100644
--- a/drivers/nfc/st-nci/ndlc.h
+++ b/drivers/nfc/st-nci/ndlc.h
@@ -22,6 +22,8 @@
 #include <linux/skbuff.h>
 #include <net/nfc/nfc.h>
 
+struct st_nci_se_status;
+
 /* Low Level Transport description */
 struct llt_ndlc {
 	struct nci_dev *ndev;
@@ -55,6 +57,7 @@ void ndlc_close(struct llt_ndlc *ndlc);
 int ndlc_send(struct llt_ndlc *ndlc, struct sk_buff *skb);
 void ndlc_recv(struct llt_ndlc *ndlc, struct sk_buff *skb);
 int ndlc_probe(void *phy_id, struct nfc_phy_ops *phy_ops, struct device *dev,
-	int phy_headroom, int phy_tailroom, struct llt_ndlc **ndlc_id);
+	       int phy_headroom, int phy_tailroom, struct llt_ndlc **ndlc_id,
+	       struct st_nci_se_status *se_status);
 void ndlc_remove(struct llt_ndlc *ndlc);
 #endif /* __LOCAL_NDLC_H__ */
diff --git a/drivers/nfc/st-nci/se.c b/drivers/nfc/st-nci/se.c
index 2812884..147e2d9 100644
--- a/drivers/nfc/st-nci/se.c
+++ b/drivers/nfc/st-nci/se.c
@@ -419,12 +419,8 @@ void st_nci_hci_cmd_received(struct nci_dev *ndev, u8 pipe, u8 cmd,
 }
 EXPORT_SYMBOL_GPL(st_nci_hci_cmd_received);
 
-/*
- * Remarks: On some early st_nci firmware, nci_nfcee_mode_set(0)
- * is rejected
- */
 static int st_nci_control_se(struct nci_dev *ndev, u8 se_idx,
-				   u8 state)
+			     u8 state)
 {
 	struct st_nci_info *info = nci_get_drvdata(ndev);
 	int r;
@@ -449,7 +445,7 @@ static int st_nci_control_se(struct nci_dev *ndev, u8 se_idx,
 	 * retrieve a relevant host list.
 	 */
 	reinit_completion(&info->se_info.req_completion);
-	r = nci_nfcee_mode_set(ndev, se_idx, NCI_NFCEE_ENABLE);
+	r = nci_nfcee_mode_set(ndev, se_idx, state);
 	if (r != NCI_STATUS_OK)
 		return r;
 
@@ -465,7 +461,9 @@ static int st_nci_control_se(struct nci_dev *ndev, u8 se_idx,
 	 * There is no possible synchronization to prevent this.
 	 * Adding a small delay is the only way to solve the issue.
 	 */
-	usleep_range(3000, 5000);
+	if (info->se_info.se_status->is_ese_present &&
+	    info->se_info.se_status->is_uicc_present)
+		usleep_range(3000, 5000);
 
 	r = nci_hci_get_param(ndev, NCI_HCI_ADMIN_GATE,
 			NCI_HCI_ADMIN_PARAM_HOST_LIST, &sk_host_list);
@@ -488,11 +486,20 @@ int st_nci_disable_se(struct nci_dev *ndev, u32 se_idx)
 
 	pr_debug("st_nci_disable_se\n");
 
-	if (se_idx == NFC_SE_EMBEDDED) {
-		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;
+	/*
+	 * According to upper layer, se_idx == NFC_SE_UICC when
+	 * info->se_info.se_status->is_uicc_enable is true should never happen
+	 * Same for eSE.
+	 */
+	r = st_nci_control_se(ndev, se_idx, ST_NCI_SE_MODE_OFF);
+	if (r < 0) {
+		/* Do best effort to release SWP */
+		if (se_idx == NFC_SE_EMBEDDED) {
+			r = nci_hci_send_event(ndev, ST_NCI_APDU_READER_GATE,
+					ST_NCI_EVT_SE_END_OF_APDU_TRANSFER,
+					NULL, 0);
+		}
+		return r;
 	}
 
 	return 0;
@@ -505,11 +512,25 @@ int st_nci_enable_se(struct nci_dev *ndev, u32 se_idx)
 
 	pr_debug("st_nci_enable_se\n");
 
-	if (se_idx == ST_NCI_HCI_HOST_ID_ESE) {
+	/*
+	 * According to upper layer, se_idx == NFC_SE_UICC when
+	 * info->se_info.se_status->is_uicc_enable is true should never happen.
+	 * Same for eSE.
+	 */
+	r = st_nci_control_se(ndev, se_idx, ST_NCI_SE_MODE_ON);
+	if (r == ST_NCI_HCI_HOST_ID_ESE) {
+		st_nci_se_get_atr(ndev);
 		r = nci_hci_send_event(ndev, ST_NCI_APDU_READER_GATE,
 				ST_NCI_EVT_SE_SOFT_RESET, NULL, 0);
-		if (r < 0)
-			return r;
+	}
+
+	if (r < 0) {
+		/*
+		 * The activation procedure failed, the secure element
+		 * is not connected. Remove from the list.
+		 */
+		nfc_remove_se(ndev->nfc_dev, se_idx);
+		return r;
 	}
 
 	return 0;
@@ -592,8 +613,8 @@ exit:
 
 int st_nci_discover_se(struct nci_dev *ndev)
 {
-	u8 param[2];
-	int r;
+	u8 white_list[2];
+	int r, wl_size = 0;
 	int se_count = 0;
 	struct st_nci_info *info = nci_get_drvdata(ndev);
 
@@ -606,29 +627,34 @@ int st_nci_discover_se(struct nci_dev *ndev)
 	if (test_bit(ST_NCI_FACTORY_MODE, &info->flags))
 		return 0;
 
-	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;
+	if (info->se_info.se_status->is_ese_present &&
+	    info->se_info.se_status->is_uicc_present) {
+		white_list[wl_size++] = ST_NCI_UICC_HOST_ID;
+		white_list[wl_size++] = ST_NCI_ESE_HOST_ID;
+	} else if (!info->se_info.se_status->is_ese_present &&
+		   info->se_info.se_status->is_uicc_present) {
+		white_list[wl_size++] = ST_NCI_UICC_HOST_ID;
+	} else if (info->se_info.se_status->is_ese_present &&
+		   !info->se_info.se_status->is_uicc_present) {
+		white_list[wl_size++] = ST_NCI_ESE_HOST_ID;
+	}
+
+	if (wl_size) {
+		r = nci_hci_set_param(ndev, NCI_HCI_ADMIN_GATE,
+				      NCI_HCI_ADMIN_PARAM_WHITELIST,
+				      white_list, wl_size);
+		if (r != NCI_HCI_ANY_OK)
+			return r;
+	}
 
-	r = st_nci_control_se(ndev, ST_NCI_UICC_HOST_ID,
-				ST_NCI_SE_MODE_ON);
-	if (r == ST_NCI_UICC_HOST_ID) {
+	if (info->se_info.se_status->is_uicc_present) {
 		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 = 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);
+	if (info->se_info.se_status->is_ese_present) {
+		nfc_add_se(ndev->nfc_dev, ST_NCI_ESE_HOST_ID, NFC_SE_EMBEDDED);
 		se_count++;
-		st_nci_se_get_atr(ndev);
 	}
 
 	return !se_count;
@@ -701,7 +727,7 @@ static void st_nci_se_activation_timeout(unsigned long data)
 	complete(&info->se_info.req_completion);
 }
 
-int st_nci_se_init(struct nci_dev *ndev)
+int st_nci_se_init(struct nci_dev *ndev, struct st_nci_se_status *se_status)
 {
 	struct st_nci_info *info = nci_get_drvdata(ndev);
 
@@ -723,6 +749,8 @@ int st_nci_se_init(struct nci_dev *ndev)
 	info->se_info.wt_timeout =
 		ST_NCI_BWI_TO_TIMEOUT(ST_NCI_ATR_DEFAULT_BWI);
 
+	info->se_info.se_status = se_status;
+
 	return 0;
 }
 EXPORT_SYMBOL(st_nci_se_init);
diff --git a/drivers/nfc/st-nci/spi.c b/drivers/nfc/st-nci/spi.c
index b43f448..8897203 100644
--- a/drivers/nfc/st-nci/spi.c
+++ b/drivers/nfc/st-nci/spi.c
@@ -53,6 +53,8 @@ struct st_nci_spi_phy {
 
 	unsigned int gpio_reset;
 	unsigned int irq_polarity;
+
+	struct st_nci_se_status se_status;
 };
 
 #define SPI_DUMP_SKB(info, skb)					\
@@ -260,6 +262,11 @@ static int st_nci_spi_of_request_resources(struct spi_device *dev)
 
 	phy->irq_polarity = irq_get_trigger_type(dev->irq);
 
+	phy->se_status.is_ese_present =
+				of_property_read_bool(pp, "ese-present");
+	phy->se_status.is_uicc_present =
+				of_property_read_bool(pp, "uicc-present");
+
 	return 0;
 }
 #else
@@ -292,6 +299,9 @@ static int st_nci_spi_request_resources(struct spi_device *dev)
 		return r;
 	}
 
+	phy->se_status.is_ese_present = pdata->is_ese_present;
+	phy->se_status.is_uicc_present = pdata->is_uicc_present;
+
 	return 0;
 }
 
@@ -342,7 +352,7 @@ static int st_nci_spi_probe(struct spi_device *dev)
 
 	r = ndlc_probe(phy, &spi_phy_ops, &dev->dev,
 			ST_NCI_FRAME_HEADROOM, ST_NCI_FRAME_TAILROOM,
-			&phy->ndlc);
+			&phy->ndlc, &phy->se_status);
 	if (r < 0) {
 		nfc_err(&dev->dev, "Unable to register ndlc layer\n");
 		return r;
diff --git a/drivers/nfc/st-nci/st-nci.h b/drivers/nfc/st-nci/st-nci.h
index c68d538..b07aded 100644
--- a/drivers/nfc/st-nci/st-nci.h
+++ b/drivers/nfc/st-nci/st-nci.h
@@ -48,7 +48,13 @@ struct nci_mode_set_rsp {
 	u8 status;
 } __packed;
 
+struct st_nci_se_status {
+	bool is_ese_present;
+	bool is_uicc_present;
+};
+
 struct st_nci_se_info {
+	struct st_nci_se_status *se_status;
 	u8 atr[ST_NCI_ESE_MAX_LENGTH];
 	struct completion req_completion;
 
@@ -126,15 +132,16 @@ struct st_nci_vendor_info {
 struct st_nci_info {
 	struct llt_ndlc *ndlc;
 	unsigned long flags;
+
 	struct st_nci_se_info se_info;
 	struct st_nci_vendor_info vendor_info;
 };
 
 void st_nci_remove(struct nci_dev *ndev);
 int st_nci_probe(struct llt_ndlc *ndlc, int phy_headroom,
-		int phy_tailroom);
+		 int phy_tailroom, struct st_nci_se_status *se_status);
 
-int st_nci_se_init(struct nci_dev *ndev);
+int st_nci_se_init(struct nci_dev *ndev, struct st_nci_se_status *se_status);
 void st_nci_se_deinit(struct nci_dev *ndev);
 
 int st_nci_discover_se(struct nci_dev *ndev);
@@ -150,7 +157,7 @@ void st_nci_hci_cmd_received(struct nci_dev *ndev, u8 pipe, u8 cmd,
 			struct sk_buff *skb);
 
 void st_nci_hci_loopback_event_received(struct nci_dev *ndev, u8 event,
-					 struct sk_buff *skb);
+					struct sk_buff *skb);
 int st_nci_vendor_cmds_init(struct nci_dev *ndev);
 
 #endif /* __LOCAL_ST_NCI_H_ */
diff --git a/include/linux/platform_data/st-nci.h b/include/linux/platform_data/st-nci.h
index d9d400a..f6494b3 100644
--- a/include/linux/platform_data/st-nci.h
+++ b/include/linux/platform_data/st-nci.h
@@ -24,6 +24,8 @@
 struct st_nci_nfc_platform_data {
 	unsigned int gpio_reset;
 	unsigned int irq_polarity;
+	bool is_ese_present;
+	bool is_uicc_present;
 };
 
 #endif /* _ST_NCI_H_ */
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 25/35] nfc: st-nci: Increase waiting time between 2 secure element activation
       [not found] ` <1445842215-28403-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (12 preceding siblings ...)
  2015-10-26  6:50   ` [PATCH v3 24/35] nfc: st-nci: Add ese-present/uicc-present dts properties Christophe Ricard
@ 2015-10-26  6:50   ` Christophe Ricard
  2015-10-26  6:50   ` [PATCH v3 28/35] nfc: netlink: Add mode parameter to deactivate_target functions Christophe Ricard
                     ` (5 subsequent siblings)
  19 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:50 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe-h.ricard-qxv4g6HH51o,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	devicetree-u79uwXL29TY76Z2rM5mHXA

After internal discussion, it appears this timing should be increase to
20 ms for interoperability reason.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 drivers/nfc/st-nci/se.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/nfc/st-nci/se.c b/drivers/nfc/st-nci/se.c
index 147e2d9..3059baa 100644
--- a/drivers/nfc/st-nci/se.c
+++ b/drivers/nfc/st-nci/se.c
@@ -463,7 +463,7 @@ static int st_nci_control_se(struct nci_dev *ndev, u8 se_idx,
 	 */
 	if (info->se_info.se_status->is_ese_present &&
 	    info->se_info.se_status->is_uicc_present)
-		usleep_range(3000, 5000);
+		usleep_range(15000, 20000);
 
 	r = nci_hci_get_param(ndev, NCI_HCI_ADMIN_GATE,
 			NCI_HCI_ADMIN_PARAM_HOST_LIST, &sk_host_list);
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 26/35] nfc: st-nci: Fix host_list verification after secure element activation
  2015-10-26  6:49 [PATCH v3 00/35] Few fixes and st21nfca/st-nci vendor_cmds support Christophe Ricard
                   ` (11 preceding siblings ...)
  2015-10-26  6:49 ` [PATCH v3 19/35] nfc: st-nci: Change st_nci_gates offset when looking for a pipe in the table Christophe Ricard
@ 2015-10-26  6:50 ` Christophe Ricard
  2015-10-26  6:50 ` [PATCH v3 27/35] nfc: st21nfca: " Christophe Ricard
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:50 UTC (permalink / raw)
  To: sameo
  Cc: linux-nfc, christophe-h.ricard, christophe.ricard, devicetree, stable

A secure element can be activated in different order. The host_list is
updated keeping a fixed order: <terminal_host_id><uicc_id><ese_id>.

Cc: stable@vger.kernel.org
Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com>
---
 drivers/nfc/st-nci/se.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/nfc/st-nci/se.c b/drivers/nfc/st-nci/se.c
index 3059baa..1cc24b6 100644
--- a/drivers/nfc/st-nci/se.c
+++ b/drivers/nfc/st-nci/se.c
@@ -423,7 +423,7 @@ static int st_nci_control_se(struct nci_dev *ndev, u8 se_idx,
 			     u8 state)
 {
 	struct st_nci_info *info = nci_get_drvdata(ndev);
-	int r;
+	int r, i;
 	struct sk_buff *sk_host_list;
 	u8 host_id;
 
@@ -470,7 +470,10 @@ static int st_nci_control_se(struct nci_dev *ndev, u8 se_idx,
 	if (r != NCI_HCI_ANY_OK)
 		return r;
 
-	host_id = sk_host_list->data[sk_host_list->len - 1];
+	for (i = 0; i < sk_host_list->len &&
+		sk_host_list->data[i] != se_idx; i++)
+		;
+	host_id = sk_host_list->data[i];
 	kfree_skb(sk_host_list);
 	if (state == ST_NCI_SE_MODE_ON && host_id == se_idx)
 		return se_idx;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 27/35] nfc: st21nfca: Fix host_list verification after secure element activation
  2015-10-26  6:49 [PATCH v3 00/35] Few fixes and st21nfca/st-nci vendor_cmds support Christophe Ricard
                   ` (12 preceding siblings ...)
  2015-10-26  6:50 ` [PATCH v3 26/35] nfc: st-nci: Fix host_list verification after secure element activation Christophe Ricard
@ 2015-10-26  6:50 ` Christophe Ricard
  2015-10-26  6:50 ` [PATCH v3 30/35] nfc: st21nfca: Add few code style fixes Christophe Ricard
  2015-10-26  6:50 ` [PATCH v3 34/35] nfc: st-nci: remove duplicated skb dump Christophe Ricard
  15 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:50 UTC (permalink / raw)
  To: sameo
  Cc: linux-nfc, christophe-h.ricard, christophe.ricard, devicetree, stable

A secure element can be activated in different order. The host_list is
updated keeping a fixed order: <terminal_host_id><uicc_id><ese_id>.

Cc: stable@vger.kernel.org
Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com>
---
 drivers/nfc/st21nfca/se.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/nfc/st21nfca/se.c b/drivers/nfc/st21nfca/se.c
index 6aa4e34..8e05d73 100644
--- a/drivers/nfc/st21nfca/se.c
+++ b/drivers/nfc/st21nfca/se.c
@@ -100,7 +100,7 @@ static int st21nfca_hci_control_se(struct nfc_hci_dev *hdev, u32 se_idx,
 				u8 state)
 {
 	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
-	int r;
+	int r, i;
 	struct sk_buff *sk_host_list;
 	u8 se_event, host_id;
 
@@ -148,7 +148,10 @@ static int st21nfca_hci_control_se(struct nfc_hci_dev *hdev, u32 se_idx,
 	if (r < 0)
 		return r;
 
-	host_id = sk_host_list->data[sk_host_list->len - 1];
+	for (i = 0; i < sk_host_list->len &&
+		sk_host_list->data[i] != se_idx; i++)
+		;
+	host_id = sk_host_list->data[i];
 	kfree_skb(sk_host_list);
 
 	if (state == ST21NFCA_SE_MODE_ON && host_id == se_idx)
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 28/35] nfc: netlink: Add mode parameter to deactivate_target functions
       [not found] ` <1445842215-28403-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (13 preceding siblings ...)
  2015-10-26  6:50   ` [PATCH v3 25/35] nfc: st-nci: Increase waiting time between 2 secure element activation Christophe Ricard
@ 2015-10-26  6:50   ` Christophe Ricard
  2015-10-26  6:50     ` Christophe Ricard
                     ` (4 subsequent siblings)
  19 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:50 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe-h.ricard-qxv4g6HH51o,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	devicetree-u79uwXL29TY76Z2rM5mHXA

In order to manage in a better way the nci poll mode state machine, add
mode parameter to deactivate_target functions. This way we can manage
different target state. mode parameter make sense only in nci core.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 include/net/nfc/nfc.h  |  2 +-
 net/nfc/core.c         |  4 ++--
 net/nfc/digital_core.c |  3 ++-
 net/nfc/hci/core.c     |  3 ++-
 net/nfc/nci/core.c     | 15 +++++++++++----
 net/nfc/netlink.c      |  2 +-
 net/nfc/nfc.h          |  5 ++++-
 net/nfc/rawsock.c      |  3 ++-
 8 files changed, 25 insertions(+), 12 deletions(-)

diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h
index 30afc9a..dcfcfc9 100644
--- a/include/net/nfc/nfc.h
+++ b/include/net/nfc/nfc.h
@@ -68,7 +68,7 @@ struct nfc_ops {
 	int (*activate_target)(struct nfc_dev *dev, struct nfc_target *target,
 			       u32 protocol);
 	void (*deactivate_target)(struct nfc_dev *dev,
-				  struct nfc_target *target);
+				  struct nfc_target *target, u8 mode);
 	int (*im_transceive)(struct nfc_dev *dev, struct nfc_target *target,
 			     struct sk_buff *skb, data_exchange_cb_t cb,
 			     void *cb_context);
diff --git a/net/nfc/core.c b/net/nfc/core.c
index cff3f16..1fe3d3b 100644
--- a/net/nfc/core.c
+++ b/net/nfc/core.c
@@ -449,7 +449,7 @@ error:
  * @dev: The nfc device that found the target
  * @target_idx: index of the target that must be deactivated
  */
-int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx)
+int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx, u8 mode)
 {
 	int rc = 0;
 
@@ -476,7 +476,7 @@ int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx)
 	if (dev->ops->check_presence)
 		del_timer_sync(&dev->check_pres_timer);
 
-	dev->ops->deactivate_target(dev, dev->active_target);
+	dev->ops->deactivate_target(dev, dev->active_target, mode);
 	dev->active_target = NULL;
 
 error:
diff --git a/net/nfc/digital_core.c b/net/nfc/digital_core.c
index 009bcf3..23c2a11 100644
--- a/net/nfc/digital_core.c
+++ b/net/nfc/digital_core.c
@@ -631,7 +631,8 @@ static int digital_activate_target(struct nfc_dev *nfc_dev,
 }
 
 static void digital_deactivate_target(struct nfc_dev *nfc_dev,
-				      struct nfc_target *target)
+				      struct nfc_target *target,
+				      u8 mode)
 {
 	struct nfc_digital_dev *ddev = nfc_get_drvdata(nfc_dev);
 
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c
index 6e061da..2b0f0ac 100644
--- a/net/nfc/hci/core.c
+++ b/net/nfc/hci/core.c
@@ -678,7 +678,8 @@ static int hci_activate_target(struct nfc_dev *nfc_dev,
 }
 
 static void hci_deactivate_target(struct nfc_dev *nfc_dev,
-				  struct nfc_target *target)
+				  struct nfc_target *target,
+				  u8 mode)
 {
 }
 
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
index 0909720..b7f548b 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -802,9 +802,11 @@ static int nci_activate_target(struct nfc_dev *nfc_dev,
 }
 
 static void nci_deactivate_target(struct nfc_dev *nfc_dev,
-				  struct nfc_target *target)
+				  struct nfc_target *target,
+				  __u8 mode)
 {
 	struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
+	u8 nci_mode = NCI_DEACTIVATE_TYPE_IDLE_MODE;
 
 	pr_debug("entry\n");
 
@@ -815,9 +817,14 @@ static void nci_deactivate_target(struct nfc_dev *nfc_dev,
 
 	ndev->target_active_prot = 0;
 
+	switch (mode) {
+	case NFC_TARGET_MODE_SLEEP:
+		nci_mode = NCI_DEACTIVATE_TYPE_SLEEP_MODE;
+		break;
+	}
+
 	if (atomic_read(&ndev->state) == NCI_POLL_ACTIVE) {
-		nci_request(ndev, nci_rf_deactivate_req,
-			    NCI_DEACTIVATE_TYPE_IDLE_MODE,
+		nci_request(ndev, nci_rf_deactivate_req, nci_mode,
 			    msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT));
 	}
 }
@@ -851,7 +858,7 @@ static int nci_dep_link_down(struct nfc_dev *nfc_dev)
 	pr_debug("entry\n");
 
 	if (nfc_dev->rf_mode == NFC_RF_INITIATOR) {
-		nci_deactivate_target(nfc_dev, NULL);
+		nci_deactivate_target(nfc_dev, NULL, NCI_DEACTIVATE_TYPE_IDLE_MODE);
 	} else {
 		if (atomic_read(&ndev->state) == NCI_LISTEN_ACTIVE ||
 		    atomic_read(&ndev->state) == NCI_DISCOVERY) {
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
index f040532..f58c1fb 100644
--- a/net/nfc/netlink.c
+++ b/net/nfc/netlink.c
@@ -885,7 +885,7 @@ static int nfc_genl_activate_target(struct sk_buff *skb, struct genl_info *info)
 	target_idx = nla_get_u32(info->attrs[NFC_ATTR_TARGET_INDEX]);
 	protocol = nla_get_u32(info->attrs[NFC_ATTR_PROTOCOLS]);
 
-	nfc_deactivate_target(dev, target_idx);
+	nfc_deactivate_target(dev, target_idx, NFC_TARGET_MODE_SLEEP);
 	rc = nfc_activate_target(dev, target_idx, protocol);
 
 	nfc_put_device(dev);
diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h
index 5c93e84..c20b784 100644
--- a/net/nfc/nfc.h
+++ b/net/nfc/nfc.h
@@ -25,6 +25,9 @@
 #include <net/nfc/nfc.h>
 #include <net/sock.h>
 
+#define NFC_TARGET_MODE_IDLE 0
+#define NFC_TARGET_MODE_SLEEP 1
+
 struct nfc_protocol {
 	int id;
 	struct proto *proto;
@@ -147,7 +150,7 @@ int nfc_dep_link_down(struct nfc_dev *dev);
 
 int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol);
 
-int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx);
+int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx, u8 mode);
 
 int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, struct sk_buff *skb,
 		      data_exchange_cb_t cb, void *cb_context);
diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c
index e9a9148..e386e6c 100644
--- a/net/nfc/rawsock.c
+++ b/net/nfc/rawsock.c
@@ -321,7 +321,8 @@ static void rawsock_destruct(struct sock *sk)
 
 	if (sk->sk_state == TCP_ESTABLISHED) {
 		nfc_deactivate_target(nfc_rawsock(sk)->dev,
-				      nfc_rawsock(sk)->target_idx);
+				      nfc_rawsock(sk)->target_idx,
+				      NFC_TARGET_MODE_IDLE);
 		nfc_put_device(nfc_rawsock(sk)->dev);
 	}
 
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 29/35] nfc: st-nci: Add few code style fixes
  2015-10-26  6:49 [PATCH v3 00/35] Few fixes and st21nfca/st-nci vendor_cmds support Christophe Ricard
@ 2015-10-26  6:50     ` Christophe Ricard
  2015-10-26  6:49 ` [PATCH v3 05/35] nfc: nci: Fix incorrect data chaining when sending data Christophe Ricard
                       ` (14 subsequent siblings)
  15 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:50 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe-h.ricard-qxv4g6HH51o,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	devicetree-u79uwXL29TY76Z2rM5mHXA, stable-u79uwXL29TY76Z2rM5mHXA

Add some few code style fixes.

Cc: stable-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 drivers/nfc/st-nci/i2c.c | 2 +-
 drivers/nfc/st-nci/se.c  | 2 +-
 net/nfc/nci/hci.c        | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/nfc/st-nci/i2c.c b/drivers/nfc/st-nci/i2c.c
index 172cbc3..2a96f1a 100644
--- a/drivers/nfc/st-nci/i2c.c
+++ b/drivers/nfc/st-nci/i2c.c
@@ -32,7 +32,7 @@
 #define DRIVER_DESC "NCI NFC driver for ST_NCI"
 
 /* ndlc header */
-#define ST_NCI_FRAME_HEADROOM	1
+#define ST_NCI_FRAME_HEADROOM 1
 #define ST_NCI_FRAME_TAILROOM 0
 
 #define ST_NCI_I2C_MIN_SIZE 4   /* PCB(1) + NCI Packet header(3) */
diff --git a/drivers/nfc/st-nci/se.c b/drivers/nfc/st-nci/se.c
index 1cc24b6..dbab722 100644
--- a/drivers/nfc/st-nci/se.c
+++ b/drivers/nfc/st-nci/se.c
@@ -62,7 +62,7 @@ struct st_nci_pipe_info {
 
 #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_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
diff --git a/net/nfc/nci/hci.c b/net/nfc/nci/hci.c
index 1d6aa5d..984d451 100644
--- a/net/nfc/nci/hci.c
+++ b/net/nfc/nci/hci.c
@@ -405,7 +405,7 @@ static void nci_hci_hcp_message_rx(struct nci_dev *ndev, u8 pipe,
 		break;
 	}
 
-	nci_req_complete(ndev, 0);
+	nci_req_complete(ndev, NCI_STATUS_OK);
 }
 
 static void nci_hci_msg_rx_work(struct work_struct *work)
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 29/35] nfc: st-nci: Add few code style fixes
@ 2015-10-26  6:50     ` Christophe Ricard
  0 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:50 UTC (permalink / raw)
  To: sameo
  Cc: linux-nfc, christophe-h.ricard, christophe.ricard, devicetree, stable

Add some few code style fixes.

Cc: stable@vger.kernel.org
Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com>
---
 drivers/nfc/st-nci/i2c.c | 2 +-
 drivers/nfc/st-nci/se.c  | 2 +-
 net/nfc/nci/hci.c        | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/nfc/st-nci/i2c.c b/drivers/nfc/st-nci/i2c.c
index 172cbc3..2a96f1a 100644
--- a/drivers/nfc/st-nci/i2c.c
+++ b/drivers/nfc/st-nci/i2c.c
@@ -32,7 +32,7 @@
 #define DRIVER_DESC "NCI NFC driver for ST_NCI"
 
 /* ndlc header */
-#define ST_NCI_FRAME_HEADROOM	1
+#define ST_NCI_FRAME_HEADROOM 1
 #define ST_NCI_FRAME_TAILROOM 0
 
 #define ST_NCI_I2C_MIN_SIZE 4   /* PCB(1) + NCI Packet header(3) */
diff --git a/drivers/nfc/st-nci/se.c b/drivers/nfc/st-nci/se.c
index 1cc24b6..dbab722 100644
--- a/drivers/nfc/st-nci/se.c
+++ b/drivers/nfc/st-nci/se.c
@@ -62,7 +62,7 @@ struct st_nci_pipe_info {
 
 #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_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
diff --git a/net/nfc/nci/hci.c b/net/nfc/nci/hci.c
index 1d6aa5d..984d451 100644
--- a/net/nfc/nci/hci.c
+++ b/net/nfc/nci/hci.c
@@ -405,7 +405,7 @@ static void nci_hci_hcp_message_rx(struct nci_dev *ndev, u8 pipe,
 		break;
 	}
 
-	nci_req_complete(ndev, 0);
+	nci_req_complete(ndev, NCI_STATUS_OK);
 }
 
 static void nci_hci_msg_rx_work(struct work_struct *work)
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 30/35] nfc: st21nfca: Add few code style fixes
  2015-10-26  6:49 [PATCH v3 00/35] Few fixes and st21nfca/st-nci vendor_cmds support Christophe Ricard
                   ` (13 preceding siblings ...)
  2015-10-26  6:50 ` [PATCH v3 27/35] nfc: st21nfca: " Christophe Ricard
@ 2015-10-26  6:50 ` Christophe Ricard
  2015-10-26  6:50 ` [PATCH v3 34/35] nfc: st-nci: remove duplicated skb dump Christophe Ricard
  15 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:50 UTC (permalink / raw)
  To: sameo
  Cc: linux-nfc, christophe-h.ricard, christophe.ricard, devicetree, stable

Add a minor code style fixes

Cc: stable@vger.kernel.org
Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com>
---
 drivers/nfc/st21nfca/core.c | 2 --
 drivers/nfc/st21nfca/i2c.c  | 1 +
 drivers/nfc/st21nfca/se.c   | 2 +-
 3 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/nfc/st21nfca/core.c b/drivers/nfc/st21nfca/core.c
index 814d8ff4..6fc60bb 100644
--- a/drivers/nfc/st21nfca/core.c
+++ b/drivers/nfc/st21nfca/core.c
@@ -162,7 +162,6 @@ static int st21nfca_hci_load_session(struct nfc_hci_dev *hdev)
 		r = nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE,
 					ST21NFCA_DM_GETINFO, pipe_info,
 					sizeof(pipe_info), &skb_pipe_info);
-
 		if (r)
 			continue;
 
@@ -982,7 +981,6 @@ int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops,
 	 * persistent info to discriminate 2 identical chips
 	 */
 	dev_num = find_first_zero_bit(dev_mask, ST21NFCA_NUM_DEVICES);
-
 	if (dev_num >= ST21NFCA_NUM_DEVICES)
 		return -ENODEV;
 
diff --git a/drivers/nfc/st21nfca/i2c.c b/drivers/nfc/st21nfca/i2c.c
index b2c914b..84c2cb0 100644
--- a/drivers/nfc/st21nfca/i2c.c
+++ b/drivers/nfc/st21nfca/i2c.c
@@ -94,6 +94,7 @@ struct st21nfca_i2c_phy {
 	int hard_fault;
 	struct mutex phy_lock;
 };
+
 static u8 len_seq[] = { 16, 24, 12, 29 };
 static u16 wait_tab[] = { 2, 3, 5, 15, 20, 40};
 
diff --git a/drivers/nfc/st21nfca/se.c b/drivers/nfc/st21nfca/se.c
index 8e05d73..d3347c7 100644
--- a/drivers/nfc/st21nfca/se.c
+++ b/drivers/nfc/st21nfca/se.c
@@ -19,7 +19,7 @@
 #include "st21nfca.h"
 
 #define ST21NFCA_EVT_UICC_ACTIVATE		0x10
-#define ST21NFCA_EVT_UICC_DEACTIVATE	0x13
+#define ST21NFCA_EVT_UICC_DEACTIVATE		0x13
 #define ST21NFCA_EVT_SE_HARD_RESET		0x20
 #define ST21NFCA_EVT_SE_SOFT_RESET		0x11
 #define ST21NFCA_EVT_SE_END_OF_APDU_TRANSFER	0x21
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 31/35] nfc: st21nfca: Add support for proprietary commands for factory tests
       [not found] ` <1445842215-28403-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (15 preceding siblings ...)
  2015-10-26  6:50     ` Christophe Ricard
@ 2015-10-26  6:50   ` Christophe Ricard
  2015-10-26  6:50   ` [PATCH v3 32/35] nfc: st21nfca: Add error messages when an unexpected HCI event occurs Christophe Ricard
                     ` (2 subsequent siblings)
  19 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:50 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe-h.ricard-qxv4g6HH51o,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Add support for proprietary commands useful mainly for factory testings.
Here is a list:
- FACTORY_MODE: Allow to set the driver into a mode where no secure element
are activated. It does not consider any NFC_ATTR_VENDOR_DATA.
- HCI_CLEAR_ALL_PIPES: Allow to execute a HCI clear all pipes command.
It does not consider any NFC_ATTR_VENDOR_DATA.
- HCI_DM_PUT_DATA: Allow to configure specific CLF registry as for example
RF trimmings or low level drivers configurations (I2C, SPI, SWP).
- HCI_DM_UPDATE_AID: Allow to configure an AID routing into the CLF routing
table following RF technology, CLF mode or protocol.
- HCI_DM_GET_INFO: Allow to retrieve CLF information.
- HCI_DM_GET_DATA: Allow to retrieve CLF configurable data such as low
level drivers configurations or RF trimmings.
- HCI_DM_LOAD: Allow to load a firmware into the CLF. A complete
packet can be more than 8KB.
- HCI_DM_RESET: Allow to run a CLF reset in order to "commit" CLF
configuration changes without CLF power off.
-  HCI_GET_PARAM: Allow to retrieve an HCI CLF parameter (for example the
white list).
- HCI_DM_FIELD_GENERATOR: Allow to generate different kind of RF
technology. When using this command to anti-collision is done.
- HCI_LOOPBACK: Allow to echo a command and test the Dh to CLF
connectivity.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 drivers/nfc/st21nfca/Makefile      |   2 +-
 drivers/nfc/st21nfca/core.c        |   3 +
 drivers/nfc/st21nfca/se.c          |   4 +-
 drivers/nfc/st21nfca/st21nfca.h    |  54 +++++-
 drivers/nfc/st21nfca/vendor_cmds.c | 369 +++++++++++++++++++++++++++++++++++++
 net/nfc/hci/llc.c                  |   2 +
 6 files changed, 431 insertions(+), 3 deletions(-)
 create mode 100644 drivers/nfc/st21nfca/vendor_cmds.c

diff --git a/drivers/nfc/st21nfca/Makefile b/drivers/nfc/st21nfca/Makefile
index 82434c3..ded6489 100644
--- a/drivers/nfc/st21nfca/Makefile
+++ b/drivers/nfc/st21nfca/Makefile
@@ -2,7 +2,7 @@
 # Makefile for ST21NFCA HCI based NFC driver
 #
 
-st21nfca_hci-objs = core.o dep.o se.o
+st21nfca_hci-objs = core.o dep.o se.o vendor_cmds.o
 obj-$(CONFIG_NFC_ST21NFCA)     += st21nfca_hci.o
 
 st21nfca_i2c-objs  = i2c.o
diff --git a/drivers/nfc/st21nfca/core.c b/drivers/nfc/st21nfca/core.c
index 6fc60bb..d36e290 100644
--- a/drivers/nfc/st21nfca/core.c
+++ b/drivers/nfc/st21nfca/core.c
@@ -921,6 +921,8 @@ static int st21nfca_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe,
 							event, skb);
 	case ST21NFCA_APDU_READER_GATE:
 		return st21nfca_apdu_reader_event_received(hdev, event, skb);
+	case NFC_HCI_LOOPBACK_GATE:
+		return st21nfca_hci_loopback_event_received(hdev, event, skb);
 	default:
 		return 1;
 	}
@@ -1022,6 +1024,7 @@ int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops,
 	*hdev = info->hdev;
 	st21nfca_dep_init(info->hdev);
 	st21nfca_se_init(info->hdev);
+	st21nfca_vendor_cmds_init(info->hdev);
 
 	return 0;
 
diff --git a/drivers/nfc/st21nfca/se.c b/drivers/nfc/st21nfca/se.c
index d3347c7..e04f603 100644
--- a/drivers/nfc/st21nfca/se.c
+++ b/drivers/nfc/st21nfca/se.c
@@ -167,6 +167,9 @@ int st21nfca_hci_discover_se(struct nfc_hci_dev *hdev)
 	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
 	int se_count = 0;
 
+	if (test_bit(ST21NFCA_FACTORY_MODE, &hdev->quirks))
+		return 0;
+
 	if (info->se_status->is_uicc_present) {
 		nfc_add_se(hdev->ndev, NFC_HCI_UICC_HOST_ID, NFC_SE_UICC);
 		se_count++;
@@ -191,7 +194,6 @@ int st21nfca_hci_enable_se(struct nfc_hci_dev *hdev, u32 se_idx)
 	 * Same for eSE.
 	 */
 	r = st21nfca_hci_control_se(hdev, se_idx, ST21NFCA_SE_MODE_ON);
-
 	if (r == ST21NFCA_ESE_HOST_ID) {
 		st21nfca_se_get_atr(hdev);
 		r = nfc_hci_send_event(hdev, ST21NFCA_APDU_READER_GATE,
diff --git a/drivers/nfc/st21nfca/st21nfca.h b/drivers/nfc/st21nfca/st21nfca.h
index 70e2d43..94ffb05 100644
--- a/drivers/nfc/st21nfca/st21nfca.h
+++ b/drivers/nfc/st21nfca/st21nfca.h
@@ -66,6 +66,9 @@
 #define ST21NFCA_HCI_MODE		0
 #define ST21NFCA_NUM_DEVICES		256
 
+#define ST21NFCA_VENDOR_OUI		0x0080E1 /* STMicroelectronics */
+#define ST21NFCA_FACTORY_MODE		2
+
 struct st21nfca_se_status {
 	bool is_ese_present;
 	bool is_uicc_present;
@@ -76,6 +79,50 @@ enum st21nfca_state {
 	ST21NFCA_ST_READY,
 };
 
+/**
+ * enum nfc_vendor_cmds - supported nfc vendor commands
+ *
+ * @FACTORY_MODE: Allow to set the driver into a mode where no secure element
+ *	are activated. It does not consider any NFC_ATTR_VENDOR_DATA.
+ * @HCI_CLEAR_ALL_PIPES: Allow to execute a HCI clear all pipes command.
+ *	It does not consider any NFC_ATTR_VENDOR_DATA.
+ * @HCI_DM_PUT_DATA: Allow to configure specific CLF registry as for example
+ *	RF trimmings or low level drivers configurations (I2C, SPI, SWP).
+ * @HCI_DM_UPDATE_AID: Allow to configure an AID routing into the CLF routing
+ *	table following RF technology, CLF mode or protocol.
+ * @HCI_DM_GET_INFO: Allow to retrieve CLF information.
+ * @HCI_DM_GET_DATA: Allow to retrieve CLF configurable data such as low
+ *	level drivers configurations or RF trimmings.
+ * @HCI_DM_LOAD: Allow to load a firmware into the CLF. A complete
+ *	packet can be more than 8KB.
+ * @HCI_DM_RESET: Allow to run a CLF reset in order to "commit" CLF
+ *	configuration changes without CLF power off.
+ * @HCI_GET_PARAM: Allow to retrieve an HCI CLF parameter (for example the
+ *	white list).
+ * @HCI_DM_FIELD_GENERATOR: Allow to generate different kind of RF
+ *	technology. When using this command to anti-collision is done.
+ * @HCI_LOOPBACK: Allow to echo a command and test the Dh to CLF
+ *	connectivity.
+ */
+enum nfc_vendor_cmds {
+	FACTORY_MODE,
+	HCI_CLEAR_ALL_PIPES,
+	HCI_DM_PUT_DATA,
+	HCI_DM_UPDATE_AID,
+	HCI_DM_GET_INFO,
+	HCI_DM_GET_DATA,
+	HCI_DM_LOAD,
+	HCI_DM_RESET,
+	HCI_GET_PARAM,
+	HCI_DM_FIELD_GENERATOR,
+	HCI_LOOPBACK,
+};
+
+struct st21nfca_vendor_info {
+	struct completion req_completion;
+	struct sk_buff *rx_skb;
+};
+
 struct st21nfca_dep_info {
 	struct sk_buff *tx_pending;
 	struct work_struct tx_work;
@@ -124,12 +171,13 @@ struct st21nfca_hci_info {
 
 	struct st21nfca_dep_info dep_info;
 	struct st21nfca_se_info se_info;
+	struct st21nfca_vendor_info vendor_info;
 };
 
 int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops,
 		       char *llc_name, int phy_headroom, int phy_tailroom,
 		       int phy_payload, struct nfc_hci_dev **hdev,
-			   struct st21nfca_se_status *se_status);
+		       struct st21nfca_se_status *se_status);
 void st21nfca_hci_remove(struct nfc_hci_dev *hdev);
 
 int st21nfca_dep_event_received(struct nfc_hci_dev *hdev,
@@ -156,4 +204,8 @@ int st21nfca_hci_se_io(struct nfc_hci_dev *hdev, u32 se_idx,
 void st21nfca_se_init(struct nfc_hci_dev *hdev);
 void st21nfca_se_deinit(struct nfc_hci_dev *hdev);
 
+int st21nfca_hci_loopback_event_received(struct nfc_hci_dev *ndev, u8 event,
+					 struct sk_buff *skb);
+int st21nfca_vendor_cmds_init(struct nfc_hci_dev *ndev);
+
 #endif /* __LOCAL_ST21NFCA_H_ */
diff --git a/drivers/nfc/st21nfca/vendor_cmds.c b/drivers/nfc/st21nfca/vendor_cmds.c
new file mode 100644
index 0000000..9a3913d
--- /dev/null
+++ b/drivers/nfc/st21nfca/vendor_cmds.c
@@ -0,0 +1,369 @@
+/*
+ * Proprietary commands extension 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 <net/genetlink.h>
+#include <linux/module.h>
+#include <linux/nfc.h>
+#include <net/nfc/hci.h>
+#include <net/nfc/llc.h>
+
+#include "st21nfca.h"
+
+#define ST21NFCA_HCI_DM_GETDATA			0x10
+#define ST21NFCA_HCI_DM_PUTDATA			0x11
+#define ST21NFCA_HCI_DM_LOAD			0x12
+#define ST21NFCA_HCI_DM_GETINFO			0x13
+#define ST21NFCA_HCI_DM_UPDATE_AID		0x20
+#define ST21NFCA_HCI_DM_RESET			0x3e
+
+#define ST21NFCA_HCI_DM_FIELD_GENERATOR		0x32
+
+#define ST21NFCA_FACTORY_MODE_ON		1
+#define ST21NFCA_FACTORY_MODE_OFF		0
+
+#define ST21NFCA_EVT_POST_DATA			0x02
+
+struct get_param_data {
+	u8 gate;
+	u8 data;
+} __packed;
+
+static int st21nfca_factory_mode(struct nfc_dev *dev, void *data,
+			       size_t data_len)
+{
+	struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
+
+	if (data_len != 1)
+		return -EINVAL;
+
+	pr_debug("factory mode: %x\n", ((u8 *)data)[0]);
+
+	switch (((u8 *)data)[0]) {
+	case ST21NFCA_FACTORY_MODE_ON:
+		test_and_set_bit(ST21NFCA_FACTORY_MODE, &hdev->quirks);
+	break;
+	case ST21NFCA_FACTORY_MODE_OFF:
+		clear_bit(ST21NFCA_FACTORY_MODE, &hdev->quirks);
+	break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int st21nfca_hci_clear_all_pipes(struct nfc_dev *dev, void *data,
+				      size_t data_len)
+{
+	struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
+
+	return nfc_hci_disconnect_all_gates(hdev);
+}
+
+static int st21nfca_hci_dm_put_data(struct nfc_dev *dev, void *data,
+				  size_t data_len)
+{
+	struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
+
+	return nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE,
+				ST21NFCA_HCI_DM_PUTDATA, data,
+				data_len, NULL);
+}
+
+static int st21nfca_hci_dm_update_aid(struct nfc_dev *dev, void *data,
+				    size_t data_len)
+{
+	struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
+
+	return nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE,
+			ST21NFCA_HCI_DM_UPDATE_AID, data, data_len, NULL);
+}
+
+static int st21nfca_hci_dm_get_info(struct nfc_dev *dev, void *data,
+				    size_t data_len)
+{
+	int r;
+	struct sk_buff *msg, *skb;
+	struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
+
+	r = nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE, ST21NFCA_HCI_DM_GETINFO,
+			     data, data_len, &skb);
+	if (r)
+		goto exit;
+
+	msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST21NFCA_VENDOR_OUI,
+					     HCI_DM_GET_INFO, skb->len);
+	if (!msg) {
+		r = -ENOMEM;
+		goto free_skb;
+	}
+
+	if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) {
+		kfree_skb(msg);
+		r = -ENOBUFS;
+		goto free_skb;
+	}
+
+	r = nfc_vendor_cmd_reply(msg);
+
+free_skb:
+	kfree_skb(skb);
+exit:
+	return r;
+}
+
+static int st21nfca_hci_dm_get_data(struct nfc_dev *dev, void *data,
+				    size_t data_len)
+{
+	int r;
+	struct sk_buff *msg, *skb;
+	struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
+
+	r = nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE, ST21NFCA_HCI_DM_GETDATA,
+			     data, data_len, &skb);
+	if (r)
+		goto exit;
+
+	msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST21NFCA_VENDOR_OUI,
+					     HCI_DM_GET_DATA, skb->len);
+	if (!msg) {
+		r = -ENOMEM;
+		goto free_skb;
+	}
+
+	if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) {
+		kfree_skb(msg);
+		r = -ENOBUFS;
+		goto free_skb;
+	}
+
+	r = nfc_vendor_cmd_reply(msg);
+
+free_skb:
+	kfree_skb(skb);
+exit:
+	return r;
+}
+
+static int st21nfca_hci_dm_load(struct nfc_dev *dev, void *data,
+				size_t data_len)
+{
+	struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
+
+	return nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE,
+				ST21NFCA_HCI_DM_LOAD, data, data_len, NULL);
+}
+
+static int st21nfca_hci_dm_reset(struct nfc_dev *dev, void *data,
+				 size_t data_len)
+{
+	int r;
+	struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
+
+	r = nfc_hci_send_cmd_async(hdev, ST21NFCA_DEVICE_MGNT_GATE,
+			ST21NFCA_HCI_DM_RESET, data, data_len, NULL, NULL);
+	if (r < 0)
+		return r;
+
+	r = nfc_llc_stop(hdev->llc);
+	if (r < 0)
+		return r;
+
+	return nfc_llc_start(hdev->llc);
+}
+
+static int st21nfca_hci_get_param(struct nfc_dev *dev, void *data,
+				  size_t data_len)
+{
+	int r;
+	struct sk_buff *msg, *skb;
+	struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
+	struct get_param_data *param = (struct get_param_data *)data;
+
+	if (data_len < sizeof(struct get_param_data))
+		return -EPROTO;
+
+	r = nfc_hci_get_param(hdev, param->gate, param->data, &skb);
+	if (r)
+		goto exit;
+
+	msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST21NFCA_VENDOR_OUI,
+					     HCI_GET_PARAM, skb->len);
+	if (!msg) {
+		r = -ENOMEM;
+		goto free_skb;
+	}
+
+	if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) {
+		kfree_skb(msg);
+		r = -ENOBUFS;
+		goto free_skb;
+	}
+
+	r = nfc_vendor_cmd_reply(msg);
+
+free_skb:
+	kfree_skb(skb);
+exit:
+	return r;
+}
+
+static int st21nfca_hci_dm_field_generator(struct nfc_dev *dev, void *data,
+					   size_t data_len)
+{
+	struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
+
+	return nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE,
+				ST21NFCA_HCI_DM_FIELD_GENERATOR, data, data_len, NULL);
+}
+
+int st21nfca_hci_loopback_event_received(struct nfc_hci_dev *hdev, u8 event,
+					 struct sk_buff *skb)
+{
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	switch (event) {
+	case ST21NFCA_EVT_POST_DATA:
+		info->vendor_info.rx_skb = skb;
+	break;
+	default:
+		nfc_err(&hdev->ndev->dev, "Unexpected event on loopback gate\n");
+	}
+	complete(&info->vendor_info.req_completion);
+	return 0;
+}
+EXPORT_SYMBOL(st21nfca_hci_loopback_event_received);
+
+static int st21nfca_hci_loopback(struct nfc_dev *dev, void *data,
+				 size_t data_len)
+{
+	int r;
+	struct sk_buff *msg;
+	struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	if (data_len <= 0)
+		return -EPROTO;
+
+	reinit_completion(&info->vendor_info.req_completion);
+	info->vendor_info.rx_skb = NULL;
+
+	r = nfc_hci_send_event(hdev, NFC_HCI_LOOPBACK_GATE,
+			       ST21NFCA_EVT_POST_DATA, data, data_len);
+	if (r < 0) {
+		r = -EPROTO;
+		goto exit;
+	}
+
+	wait_for_completion_interruptible(&info->vendor_info.req_completion);
+	if (!info->vendor_info.rx_skb ||
+	    info->vendor_info.rx_skb->len != data_len) {
+		r = -EPROTO;
+		goto exit;
+	}
+
+	msg = nfc_vendor_cmd_alloc_reply_skb(hdev->ndev,
+					ST21NFCA_VENDOR_OUI,
+					HCI_LOOPBACK,
+					info->vendor_info.rx_skb->len);
+	if (!msg) {
+		r = -ENOMEM;
+		goto free_skb;
+	}
+
+	if (nla_put(msg, NFC_ATTR_VENDOR_DATA, info->vendor_info.rx_skb->len,
+		    info->vendor_info.rx_skb->data)) {
+		kfree_skb(msg);
+		r = -ENOBUFS;
+		goto free_skb;
+	}
+
+	r = nfc_vendor_cmd_reply(msg);
+free_skb:
+	kfree_skb(info->vendor_info.rx_skb);
+exit:
+	return r;
+}
+
+static struct nfc_vendor_cmd st21nfca_vendor_cmds[] = {
+	{
+		.vendor_id = ST21NFCA_VENDOR_OUI,
+		.subcmd = FACTORY_MODE,
+		.doit = st21nfca_factory_mode,
+	},
+	{
+		.vendor_id = ST21NFCA_VENDOR_OUI,
+		.subcmd = HCI_CLEAR_ALL_PIPES,
+		.doit = st21nfca_hci_clear_all_pipes,
+	},
+	{
+		.vendor_id = ST21NFCA_VENDOR_OUI,
+		.subcmd = HCI_DM_PUT_DATA,
+		.doit = st21nfca_hci_dm_put_data,
+	},
+	{
+		.vendor_id = ST21NFCA_VENDOR_OUI,
+		.subcmd = HCI_DM_UPDATE_AID,
+		.doit = st21nfca_hci_dm_update_aid,
+	},
+	{
+		.vendor_id = ST21NFCA_VENDOR_OUI,
+		.subcmd = HCI_DM_GET_INFO,
+		.doit = st21nfca_hci_dm_get_info,
+	},
+	{
+		.vendor_id = ST21NFCA_VENDOR_OUI,
+		.subcmd = HCI_DM_GET_DATA,
+		.doit = st21nfca_hci_dm_get_data,
+	},
+	{
+		.vendor_id = ST21NFCA_VENDOR_OUI,
+		.subcmd = HCI_DM_LOAD,
+		.doit = st21nfca_hci_dm_load,
+	},
+	{
+		.vendor_id = ST21NFCA_VENDOR_OUI,
+		.subcmd = HCI_DM_RESET,
+		.doit = st21nfca_hci_dm_reset,
+	},
+	{
+		.vendor_id = ST21NFCA_VENDOR_OUI,
+		.subcmd = HCI_GET_PARAM,
+		.doit = st21nfca_hci_get_param,
+	},
+	{
+		.vendor_id = ST21NFCA_VENDOR_OUI,
+		.subcmd = HCI_DM_FIELD_GENERATOR,
+		.doit = st21nfca_hci_dm_field_generator,
+	},
+	{
+		.vendor_id = ST21NFCA_VENDOR_OUI,
+		.subcmd = HCI_LOOPBACK,
+		.doit = st21nfca_hci_loopback,
+	},
+};
+
+int st21nfca_vendor_cmds_init(struct nfc_hci_dev *hdev)
+{
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	init_completion(&info->vendor_info.req_completion);
+	return nfc_set_vendor_cmds(hdev->ndev, st21nfca_vendor_cmds,
+				   sizeof(st21nfca_vendor_cmds));
+}
+EXPORT_SYMBOL(st21nfca_vendor_cmds_init);
diff --git a/net/nfc/hci/llc.c b/net/nfc/hci/llc.c
index 65e6a0e..f40a401 100644
--- a/net/nfc/hci/llc.c
+++ b/net/nfc/hci/llc.c
@@ -148,11 +148,13 @@ inline int nfc_llc_start(struct nfc_llc *llc)
 {
 	return llc->ops->start(llc);
 }
+EXPORT_SYMBOL(nfc_llc_start);
 
 inline int nfc_llc_stop(struct nfc_llc *llc)
 {
 	return llc->ops->stop(llc);
 }
+EXPORT_SYMBOL(nfc_llc_stop);
 
 inline void nfc_llc_rcv_from_drv(struct nfc_llc *llc, struct sk_buff *skb)
 {
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 32/35] nfc: st21nfca: Add error messages when an unexpected HCI event occurs
       [not found] ` <1445842215-28403-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (16 preceding siblings ...)
  2015-10-26  6:50   ` [PATCH v3 31/35] nfc: st21nfca: Add support for proprietary commands for factory tests Christophe Ricard
@ 2015-10-26  6:50   ` Christophe Ricard
  2015-10-26  6:50   ` [PATCH v3 33/35] nfc: st-nci: Make sure irq is not already active when powering the device Christophe Ricard
  2015-10-26  6:50   ` [PATCH v3 35/35] nfc: st-nci: Replace st21nfcb by st_nci in makefile Christophe Ricard
  19 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:50 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe-h.ricard-qxv4g6HH51o,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Potentially an unexpected HCI event may occur because of a firmware bug.
It could be transparent for the user but at least log this.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 drivers/nfc/st21nfca/core.c | 2 ++
 drivers/nfc/st21nfca/dep.c  | 1 +
 drivers/nfc/st21nfca/se.c   | 4 ++++
 3 files changed, 7 insertions(+)

diff --git a/drivers/nfc/st21nfca/core.c b/drivers/nfc/st21nfca/core.c
index d36e290..dd8b150 100644
--- a/drivers/nfc/st21nfca/core.c
+++ b/drivers/nfc/st21nfca/core.c
@@ -893,6 +893,8 @@ static int st21nfca_admin_event_received(struct nfc_hci_dev *hdev, u8 event,
 			}
 		}
 	break;
+	default:
+		nfc_err(&hdev->ndev->dev, "Unexpected event on admin gate\n");
 	}
 	kfree_skb(skb);
 	return 0;
diff --git a/drivers/nfc/st21nfca/dep.c b/drivers/nfc/st21nfca/dep.c
index c011712..798a32b 100644
--- a/drivers/nfc/st21nfca/dep.c
+++ b/drivers/nfc/st21nfca/dep.c
@@ -435,6 +435,7 @@ int st21nfca_dep_event_received(struct nfc_hci_dev *hdev,
 			return r;
 		return 0;
 	default:
+		nfc_err(&hdev->ndev->dev, "Unexpected event on card f gate\n");
 		return 1;
 	}
 	kfree_skb(skb);
diff --git a/drivers/nfc/st21nfca/se.c b/drivers/nfc/st21nfca/se.c
index e04f603..c79d99b 100644
--- a/drivers/nfc/st21nfca/se.c
+++ b/drivers/nfc/st21nfca/se.c
@@ -344,6 +344,7 @@ int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host,
 		r = nfc_se_transaction(hdev->ndev, host, transaction);
 		break;
 	default:
+		nfc_err(&hdev->ndev->dev, "Unexpected event on connectivity gate\n");
 		return 1;
 	}
 	kfree_skb(skb);
@@ -375,6 +376,9 @@ int st21nfca_apdu_reader_event_received(struct nfc_hci_dev *hdev,
 		mod_timer(&info->se_info.bwi_timer, jiffies +
 				msecs_to_jiffies(info->se_info.wt_timeout));
 		break;
+	default:
+		nfc_err(&hdev->ndev->dev, "Unexpected event on apdu reader gate\n");
+		return 1;
 	}
 
 exit:
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 33/35] nfc: st-nci: Make sure irq is not already active when powering the device
       [not found] ` <1445842215-28403-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (17 preceding siblings ...)
  2015-10-26  6:50   ` [PATCH v3 32/35] nfc: st21nfca: Add error messages when an unexpected HCI event occurs Christophe Ricard
@ 2015-10-26  6:50   ` Christophe Ricard
  2015-10-26  6:50   ` [PATCH v3 35/35] nfc: st-nci: Replace st21nfcb by st_nci in makefile Christophe Ricard
  19 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:50 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe-h.ricard-qxv4g6HH51o,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Upon some conditions (timing, CLF errors, platform errors...), the irq might
be already active when powering the device.

Add irq_active variable as a guard to avoid kernel warning message

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 drivers/nfc/st-nci/i2c.c | 8 +++++++-
 drivers/nfc/st-nci/spi.c | 8 +++++++-
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/nfc/st-nci/i2c.c b/drivers/nfc/st-nci/i2c.c
index 2a96f1a..25e5042 100644
--- a/drivers/nfc/st-nci/i2c.c
+++ b/drivers/nfc/st-nci/i2c.c
@@ -50,6 +50,8 @@ struct st_nci_i2c_phy {
 	struct i2c_client *i2c_dev;
 	struct llt_ndlc *ndlc;
 
+	bool irq_active;
+
 	unsigned int gpio_reset;
 	unsigned int irq_polarity;
 
@@ -72,8 +74,10 @@ static int st_nci_i2c_enable(void *phy_id)
 	gpio_set_value(phy->gpio_reset, 1);
 	usleep_range(80000, 85000);
 
-	if (phy->ndlc->powered == 0)
+	if (phy->ndlc->powered == 0 && phy->irq_active == 0) {
 		enable_irq(phy->i2c_dev->irq);
+		phy->irq_active = true;
+	}
 
 	return 0;
 }
@@ -83,6 +87,7 @@ static void st_nci_i2c_disable(void *phy_id)
 	struct st_nci_i2c_phy *phy = phy_id;
 
 	disable_irq_nosync(phy->i2c_dev->irq);
+	phy->irq_active = false;
 }
 
 /*
@@ -342,6 +347,7 @@ static int st_nci_i2c_probe(struct i2c_client *client,
 		return r;
 	}
 
+	phy->irq_active = true;
 	r = devm_request_threaded_irq(&client->dev, client->irq, NULL,
 				st_nci_irq_thread_fn,
 				phy->irq_polarity | IRQF_ONESHOT,
diff --git a/drivers/nfc/st-nci/spi.c b/drivers/nfc/st-nci/spi.c
index 8897203..bf6643c 100644
--- a/drivers/nfc/st-nci/spi.c
+++ b/drivers/nfc/st-nci/spi.c
@@ -51,6 +51,8 @@ struct st_nci_spi_phy {
 	struct spi_device *spi_dev;
 	struct llt_ndlc *ndlc;
 
+	bool irq_active;
+
 	unsigned int gpio_reset;
 	unsigned int irq_polarity;
 
@@ -73,8 +75,10 @@ static int st_nci_spi_enable(void *phy_id)
 	gpio_set_value(phy->gpio_reset, 1);
 	usleep_range(80000, 85000);
 
-	if (phy->ndlc->powered == 0)
+	if (phy->ndlc->powered == 0 && phy->irq_active == 0) {
 		enable_irq(phy->spi_dev->irq);
+		phy->irq_active = true;
+	}
 
 	return 0;
 }
@@ -84,6 +88,7 @@ static void st_nci_spi_disable(void *phy_id)
 	struct st_nci_spi_phy *phy = phy_id;
 
 	disable_irq_nosync(phy->spi_dev->irq);
+	phy->irq_active = false;
 }
 
 /*
@@ -358,6 +363,7 @@ static int st_nci_spi_probe(struct spi_device *dev)
 		return r;
 	}
 
+	phy->irq_active = true;
 	r = devm_request_threaded_irq(&dev->dev, dev->irq, NULL,
 				st_nci_irq_thread_fn,
 				phy->irq_polarity | IRQF_ONESHOT,
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 34/35] nfc: st-nci: remove duplicated skb dump
  2015-10-26  6:49 [PATCH v3 00/35] Few fixes and st21nfca/st-nci vendor_cmds support Christophe Ricard
                   ` (14 preceding siblings ...)
  2015-10-26  6:50 ` [PATCH v3 30/35] nfc: st21nfca: Add few code style fixes Christophe Ricard
@ 2015-10-26  6:50 ` Christophe Ricard
  15 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:50 UTC (permalink / raw)
  To: sameo
  Cc: linux-nfc, christophe-h.ricard, christophe.ricard, devicetree, stable

Remove SPI_DUMP_SKB and I2C_DUMP_SKB as skb is already dumped in ndlc
layer.

Cc: stable@vger.kernel.org
Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com>
---
 drivers/nfc/st-nci/i2c.c | 11 -----------
 drivers/nfc/st-nci/spi.c | 11 -----------
 2 files changed, 22 deletions(-)

diff --git a/drivers/nfc/st-nci/i2c.c b/drivers/nfc/st-nci/i2c.c
index 25e5042..15e3ce2 100644
--- a/drivers/nfc/st-nci/i2c.c
+++ b/drivers/nfc/st-nci/i2c.c
@@ -58,13 +58,6 @@ struct st_nci_i2c_phy {
 	struct st_nci_se_status se_status;
 };
 
-#define I2C_DUMP_SKB(info, skb)					\
-do {								\
-	pr_debug("%s:\n", info);				\
-	print_hex_dump(KERN_DEBUG, "i2c: ", DUMP_PREFIX_OFFSET,	\
-		       16, 1, (skb)->data, (skb)->len, 0);	\
-} while (0)
-
 static int st_nci_i2c_enable(void *phy_id)
 {
 	struct st_nci_i2c_phy *phy = phy_id;
@@ -101,8 +94,6 @@ static int st_nci_i2c_write(void *phy_id, struct sk_buff *skb)
 	struct st_nci_i2c_phy *phy = phy_id;
 	struct i2c_client *client = phy->i2c_dev;
 
-	I2C_DUMP_SKB("st_nci_i2c_write", skb);
-
 	if (phy->ndlc->hard_fault != 0)
 		return phy->ndlc->hard_fault;
 
@@ -173,8 +164,6 @@ static int st_nci_i2c_read(struct st_nci_i2c_phy *phy,
 	skb_put(*skb, len);
 	memcpy((*skb)->data + ST_NCI_I2C_MIN_SIZE, buf, len);
 
-	I2C_DUMP_SKB("i2c frame read", *skb);
-
 	return 0;
 }
 
diff --git a/drivers/nfc/st-nci/spi.c b/drivers/nfc/st-nci/spi.c
index bf6643c..cf7ad81 100644
--- a/drivers/nfc/st-nci/spi.c
+++ b/drivers/nfc/st-nci/spi.c
@@ -59,13 +59,6 @@ struct st_nci_spi_phy {
 	struct st_nci_se_status se_status;
 };
 
-#define SPI_DUMP_SKB(info, skb)					\
-do {								\
-	pr_debug("%s:\n", info);				\
-	print_hex_dump(KERN_DEBUG, "spi: ", DUMP_PREFIX_OFFSET,	\
-		       16, 1, (skb)->data, (skb)->len, 0);	\
-} while (0)
-
 static int st_nci_spi_enable(void *phy_id)
 {
 	struct st_nci_spi_phy *phy = phy_id;
@@ -110,8 +103,6 @@ static int st_nci_spi_write(void *phy_id, struct sk_buff *skb)
 		.len = skb->len,
 	};
 
-	SPI_DUMP_SKB("st_nci_spi_write", skb);
-
 	if (phy->ndlc->hard_fault != 0)
 		return phy->ndlc->hard_fault;
 
@@ -188,8 +179,6 @@ static int st_nci_spi_read(struct st_nci_spi_phy *phy,
 	skb_put(*skb, len);
 	memcpy((*skb)->data + ST_NCI_SPI_MIN_SIZE, buf, len);
 
-	SPI_DUMP_SKB("spi frame read", *skb);
-
 	return 0;
 }
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v3 35/35] nfc: st-nci: Replace st21nfcb by st_nci in makefile
       [not found] ` <1445842215-28403-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (18 preceding siblings ...)
  2015-10-26  6:50   ` [PATCH v3 33/35] nfc: st-nci: Make sure irq is not already active when powering the device Christophe Ricard
@ 2015-10-26  6:50   ` Christophe Ricard
  19 siblings, 0 replies; 38+ messages in thread
From: Christophe Ricard @ 2015-10-26  6:50 UTC (permalink / raw)
  To: sameo-VuQAYsv1563Yd54FQh9/CA
  Cc: linux-nfc-hn68Rpc1hR1g9hUCZPvPmw,
	christophe-h.ricard-qxv4g6HH51o,
	christophe.ricard-Re5JQEeQqe8AvxtiuMwx3w,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Replace 1 missing st21nfcb by st_nci

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 drivers/nfc/st-nci/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/nfc/st-nci/Makefile b/drivers/nfc/st-nci/Makefile
index ea40ace..439b2fa 100644
--- a/drivers/nfc/st-nci/Makefile
+++ b/drivers/nfc/st-nci/Makefile
@@ -1,5 +1,5 @@
 #
-# Makefile for ST21NFCB NCI based NFC driver
+# Makefile for ST_NCI NCI based NFC driver
 #
 
 st-nci-objs = ndlc.o core.o se.o vendor_cmds.o
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 38+ messages in thread

end of thread, other threads:[~2015-10-26  6:51 UTC | newest]

Thread overview: 38+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-10-26  6:49 [PATCH v3 00/35] Few fixes and st21nfca/st-nci vendor_cmds support Christophe Ricard
2015-10-26  6:49 ` [PATCH v3 04/35] nfc: st-nci: Fix incorrect spi buffer size Christophe Ricard
2015-10-26  6:49 ` [PATCH v3 05/35] nfc: nci: Fix incorrect data chaining when sending data Christophe Ricard
2015-10-26  6:49 ` [PATCH v3 06/35] nfc: nci: Fix improper management of HCI return code Christophe Ricard
2015-10-26  6:49 ` [PATCH v3 07/35] nfc: nci: extract pipe value using NCI_HCP_MSG_GET_PIPE Christophe Ricard
     [not found] ` <1445842215-28403-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
2015-10-26  6:49   ` [PATCH v3 01/35] nfc: st-nci: Align st-nci driver with other nfc driver Christophe Ricard
2015-10-26  6:49   ` [PATCH v3 02/35] nfc: st-nci: include st-nci.h instead of ndlc.h Christophe Ricard
2015-10-26  6:49   ` [PATCH v3 03/35] nfc: st21nfca: Align st21nfca driver with other nfc driver Christophe Ricard
2015-10-26  6:49   ` [PATCH v3 08/35] nfc: nci: add nci_hci_clear_all_pipes functions Christophe Ricard
2015-10-26  6:49   ` [PATCH v3 09/35] nfc: nci: Add a call to nci_hci_clear_all_pipes at HCI initial activation Christophe Ricard
2015-10-26  6:49   ` [PATCH v3 10/35] nfc: nci: add capability to create pipe on specific gate in nci_hci_connect_gate Christophe Ricard
2015-10-26  6:49   ` [PATCH v3 13/35] nfc: st-nci: Open NCI_HCI_LINK_MGMT_PIPE Christophe Ricard
2015-10-26  6:49   ` [PATCH v3 18/35] nfc: st-nci: Add support for NCI_HCI_IDENTITY_MGMT_GATE Christophe Ricard
2015-10-26  6:50   ` [PATCH v3 20/35] nfc: st21nfca: Change st21nfca_gates offset when looking for a pipe in the table Christophe Ricard
2015-10-26  6:50     ` Christophe Ricard
2015-10-26  6:50   ` [PATCH v3 21/35] nfc: st-nci: Add support for proprietary commands for factory tests Christophe Ricard
2015-10-26  6:50   ` [PATCH v3 22/35] nfc: st-nci: Add error messages when an unexpected HCI event occurs Christophe Ricard
2015-10-26  6:50   ` [PATCH v3 23/35] nfc: netlink: Add missing NFC_ATTR comments Christophe Ricard
2015-10-26  6:50   ` [PATCH v3 24/35] nfc: st-nci: Add ese-present/uicc-present dts properties Christophe Ricard
2015-10-26  6:50   ` [PATCH v3 25/35] nfc: st-nci: Increase waiting time between 2 secure element activation Christophe Ricard
2015-10-26  6:50   ` [PATCH v3 28/35] nfc: netlink: Add mode parameter to deactivate_target functions Christophe Ricard
2015-10-26  6:50   ` [PATCH v3 29/35] nfc: st-nci: Add few code style fixes Christophe Ricard
2015-10-26  6:50     ` Christophe Ricard
2015-10-26  6:50   ` [PATCH v3 31/35] nfc: st21nfca: Add support for proprietary commands for factory tests Christophe Ricard
2015-10-26  6:50   ` [PATCH v3 32/35] nfc: st21nfca: Add error messages when an unexpected HCI event occurs Christophe Ricard
2015-10-26  6:50   ` [PATCH v3 33/35] nfc: st-nci: Make sure irq is not already active when powering the device Christophe Ricard
2015-10-26  6:50   ` [PATCH v3 35/35] nfc: st-nci: Replace st21nfcb by st_nci in makefile Christophe Ricard
2015-10-26  6:49 ` [PATCH v3 11/35] nfc: st-nci: Remove ndev->hci_dev->init_data.gates initialization in load_session Christophe Ricard
2015-10-26  6:49 ` [PATCH v3 12/35] nfc: st21nfca: Remove hdev->init_data.gates " Christophe Ricard
2015-10-26  6:49 ` [PATCH v3 14/35] nfc: st21nfca: Open NFC_HCI_LINK_MGMT_PIPE Christophe Ricard
2015-10-26  6:49 ` [PATCH v3 15/35] nfc: st-nci: Keep st_nci_gates unchanged in load_session Christophe Ricard
2015-10-26  6:49 ` [PATCH v3 16/35] nfc: st21nfca: Keep st21nfca_gates " Christophe Ricard
2015-10-26  6:49 ` [PATCH v3 17/35] nfc: st-nci: initialize gate_count in st_nci_hci_network_init Christophe Ricard
2015-10-26  6:49 ` [PATCH v3 19/35] nfc: st-nci: Change st_nci_gates offset when looking for a pipe in the table Christophe Ricard
2015-10-26  6:50 ` [PATCH v3 26/35] nfc: st-nci: Fix host_list verification after secure element activation Christophe Ricard
2015-10-26  6:50 ` [PATCH v3 27/35] nfc: st21nfca: " Christophe Ricard
2015-10-26  6:50 ` [PATCH v3 30/35] nfc: st21nfca: Add few code style fixes Christophe Ricard
2015-10-26  6:50 ` [PATCH v3 34/35] nfc: st-nci: remove duplicated skb dump Christophe Ricard

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.