linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [[linux-nfc][PATCH v1] 0/6] Support of ST NFC Transceiver
@ 2017-05-02  6:03 Shikha Singh
  2017-05-02  6:03 ` [[linux-nfc][PATCH v1] 1/6] NFC: add generic UART support Shikha Singh
                   ` (6 more replies)
  0 siblings, 7 replies; 11+ messages in thread
From: Shikha Singh @ 2017-05-02  6:03 UTC (permalink / raw)
  To: sameo, linux-wireless, linux-nfc
  Cc: raunaque.quaiser, manoj.kumar, sylvain.fidelis, raphael.collado,
	shikha.singh, MMS_MMY_Applications_SW

*** V1.0 ***
This patch series is generated on top of latest
code available on nfc-next.

This patch series introduces the following features:

(a) A generic Digital NFC UART framework.
The framework itself is an LDISC registered
with the tty core. Any NFC transciever implementing
the digital specs and connected on an UART
(or on an emulated tty, such as /dev/ttyUSBx, /dev/ttyACMx)
interface with the host, will require this support.

(b) An ST NFC Transciever core framework. This implements the
required digital ops and exposes an interface for the
underlying phy drivers (UART/ SPI). The services of the phy drivers
are required when the core wants to transmit/receive frames.
Also it provides helper functions for the phy drivers, for
example phy drivers registers with the core when it detects
a Transciever connected on the corresponding interface.
The framework currently supports NFC Type 2, Type 4A, Type 4B,
Type 5 tag read/write.

(c) An ST NFC UART LDisc driver that registers with the
Digital NFC UART framework, and with the ST NFC Transciever
core framework as the UART Phy driver.

(d) An ST NFC SPI driver that register with ST NFC Transceiver
core framework as SPI phy driver.

(e) Binding doc was renamed from st95hf.txt to stnfc.txt.

(f) This patch series also removes all the references of old ST
NFC transceiver driver "st95hf".

Shikha Singh (6):
  NFC: add generic UART support
  NFC: nfcst: Add ST NFC Transceiver core framework
  NFC: nfcst: Add UART LDisc Driver
  NFC: nfcst: Add ST NFC SPI Driver
  DT: bindings: net: nfc: stnfc binding doc
  DRIVERS: NFC: Remove st95hf name reference

 .../devicetree/bindings/net/nfc/st95hf.txt         |   50 -
 .../devicetree/bindings/net/nfc/stnfc.txt          |   50 +
 drivers/nfc/Kconfig                                |    2 +-
 drivers/nfc/Makefile                               |    2 +-
 drivers/nfc/nfcst/Kconfig                          |   49 +
 drivers/nfc/nfcst/Makefile                         |   12 +
 drivers/nfc/nfcst/core.c                           | 1122 +++++++++++++++++
 drivers/nfc/nfcst/spi.c                            |  493 ++++++++
 drivers/nfc/nfcst/stnfcdev.h                       |   70 ++
 drivers/nfc/nfcst/uart.c                           |  164 +++
 drivers/nfc/st95hf/Kconfig                         |   10 -
 drivers/nfc/st95hf/Makefile                        |    6 -
 drivers/nfc/st95hf/core.c                          | 1273 --------------------
 drivers/nfc/st95hf/spi.c                           |  167 ---
 drivers/nfc/st95hf/spi.h                           |   64 -
 include/net/nfc/digital_uart.h                     |  105 ++
 include/uapi/linux/tty.h                           |    1 +
 net/nfc/Kconfig                                    |   12 +
 net/nfc/Makefile                                   |    3 +
 net/nfc/digital_uart.c                             |  523 ++++++++
 20 files changed, 2606 insertions(+), 1572 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/net/nfc/st95hf.txt
 create mode 100644 Documentation/devicetree/bindings/net/nfc/stnfc.txt
 create mode 100644 drivers/nfc/nfcst/Kconfig
 create mode 100644 drivers/nfc/nfcst/Makefile
 create mode 100644 drivers/nfc/nfcst/core.c
 create mode 100644 drivers/nfc/nfcst/spi.c
 create mode 100644 drivers/nfc/nfcst/stnfcdev.h
 create mode 100644 drivers/nfc/nfcst/uart.c
 delete mode 100644 drivers/nfc/st95hf/Kconfig
 delete mode 100644 drivers/nfc/st95hf/Makefile
 delete mode 100644 drivers/nfc/st95hf/core.c
 delete mode 100644 drivers/nfc/st95hf/spi.c
 delete mode 100644 drivers/nfc/st95hf/spi.h
 create mode 100644 include/net/nfc/digital_uart.h
 create mode 100644 net/nfc/digital_uart.c

-- 
1.8.2.1

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

* [[linux-nfc][PATCH v1] 1/6] NFC: add generic UART support
  2017-05-02  6:03 [[linux-nfc][PATCH v1] 0/6] Support of ST NFC Transceiver Shikha Singh
@ 2017-05-02  6:03 ` Shikha Singh
  2017-05-02  6:03 ` [[linux-nfc][PATCH v1] 2/6] NFC: nfcst: Add ST NFC Transceiver core framework Shikha Singh
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 11+ messages in thread
From: Shikha Singh @ 2017-05-02  6:03 UTC (permalink / raw)
  To: sameo, linux-wireless, linux-nfc
  Cc: raunaque.quaiser, manoj.kumar, sylvain.fidelis, raphael.collado,
	shikha.singh, MMS_MMY_Applications_SW

Some NFC controller supports UART as host interface.
Such controllers which are direct implementation of
digital protocol can use this framework.
This patch add the generic support of UART and
provides some extension API for vendor specific needs.

This code is strongly inspired by the nci ldisc
implementation.
Digital UART drivers will have to register themselves
to this layer via digital_uart_register.

Underlying tty will have to be configured from user land
thanks to ioctl support.

Signed-off-by: Shikha Singh <shikha.singh@st.com>
---
 include/net/nfc/digital_uart.h | 105 +++++++++
 include/uapi/linux/tty.h       |   1 +
 net/nfc/Kconfig                |  12 +
 net/nfc/Makefile               |   3 +
 net/nfc/digital_uart.c         | 523 +++++++++++++++++++++++++++++++++++++++++
 5 files changed, 644 insertions(+)
 create mode 100644 include/net/nfc/digital_uart.h
 create mode 100644 net/nfc/digital_uart.c

diff --git a/include/net/nfc/digital_uart.h b/include/net/nfc/digital_uart.h
new file mode 100644
index 0000000..5d64e2d
--- /dev/null
+++ b/include/net/nfc/digital_uart.h
@@ -0,0 +1,105 @@
+/*
+ * NFC Digital UART Line Discipline Framework API
+ *
+ * Copyright (c) 2016, STMicroelectronics Pvt. Ltd.
+ * 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 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.
+ *
+ */
+
+#ifndef __NFC_DIGITAL_UART_H
+#define __NFC_DIGITAL_UART_H
+
+#include <linux/tty.h>
+#include <linux/skbuff.h>
+
+/**
+ * Drivers that can register with DIGITAL UART LDISC Framework
+ */
+enum digital_uart_driver {
+	DIGITAL_UART_DRIVER_ST = 0,
+	DIGITAL_UART_DRIVER_MAX,
+};
+
+enum digital_uart_stop_bits {
+	DIGITAL_UART_STOP_BIT_1 = 0,
+	DIGITAL_UART_STOP_BIT_2,
+};
+
+struct digital_uart;
+
+#define DIGITALUARTSETDRIVER	_IOW('V', 0, char *)
+
+/*
+ * DIGITAL UART LDISC Framework ops
+ */
+struct digital_uart_ops {
+	/* called when SETDRIVER IOCTL called on tty */
+	int (*open)(struct digital_uart *du);
+	/* called when ldisc of tty changed to other than N_DIGITAL */
+	void (*close)(struct digital_uart *du);
+	/* called after a frame is received */
+	int (*recv)(struct digital_uart *du, struct sk_buff *skb);
+	/* called by low level uart driver's tty layer when the data is
+	 * received at UART port.
+	 */
+	int (*recv_buff)(struct digital_uart *du, const u8 *data, char *flags,
+			 int count);
+	/* called for sending a frame through UART */
+	int (*send)(struct digital_uart *du, struct sk_buff *skb);
+	/* if required to do some special handling before starting the
+	 * transmission
+	 */
+	void (*tx_start)(struct digital_uart *du);
+	/* if required to do some special handling before ending the
+	 * transmission
+	 */
+	void (*tx_done)(struct digital_uart *du);
+	/* returns the received frame header for valid frames*/
+	/* called at the time of received frame processing */
+	int (*recv_fr_hdr_sz)(struct digital_uart *du,
+			      const u8 *data, int count);
+	/* returns the max size of frame that can be received*/
+	int (*recv_fr_max_sz)(struct digital_uart *du);
+	/* return payload size */
+	int (*recv_pl_sz)(struct digital_uart *du, const u8 *data, int count);
+};
+
+struct digital_uart {
+	struct module *owner;
+	struct digital_uart_ops ops;
+	const char *name;
+	enum digital_uart_driver driver;
+	/* Pointer of corresponding TTY */
+	struct tty_struct *tty;
+	/* worker for writing the frame */
+	struct work_struct write_work;
+	/* lock to serialize the frame read operation */
+	spinlock_t rx_lock;
+	unsigned long tx_state;
+	/* queue of frames to be written */
+	struct sk_buff_head tx_q;
+	/* current write frame */
+	struct sk_buff *tx_skb;
+	/* current read frame */
+	struct sk_buff *rx_skb;
+	/* store received pkt length in ldisc context */
+	int rx_packet_len;
+	/* store drive specific data */
+	void *drv_data;
+};
+
+/* exported helper functions */
+int digital_uart_register(struct digital_uart *du);
+void digital_uart_unregister(struct digital_uart *du);
+void digital_uart_set_config(struct digital_uart *du, int baudrate,
+			     int flow_ctrl,
+			     enum digital_uart_stop_bits stop_bits);
+
+#endif /* __NFC_DIGITAL_UART_H */
diff --git a/include/uapi/linux/tty.h b/include/uapi/linux/tty.h
index 01c4410..7c1fb70 100644
--- a/include/uapi/linux/tty.h
+++ b/include/uapi/linux/tty.h
@@ -35,5 +35,6 @@
 #define N_TRACESINK	23	/* Trace data routing for MIPI P1149.7 */
 #define N_TRACEROUTER	24	/* Trace data routing for MIPI P1149.7 */
 #define N_NCI		25	/* NFC NCI UART */
+#define N_DIGITAL	26	/* NFC DIGITAL UART */
 
 #endif /* _UAPI_LINUX_TTY_H */
diff --git a/net/nfc/Kconfig b/net/nfc/Kconfig
index 6e0fa0c..80cffcd 100644
--- a/net/nfc/Kconfig
+++ b/net/nfc/Kconfig
@@ -28,6 +28,18 @@ config NFC_DIGITAL
 	  To compile this support as a module, choose M here: the module will
 	  be called nfc_digital.
 
+config NFC_DIGITAL_UART
+	depends on NFC_DIGITAL && TTY
+	tristate "Digital over UART protocol support"
+	default n
+	help
+	  This implements an UART LDisc framework for digital core based
+	  drivers.
+
+	  Say Y if you use a digital driver that requires UART link layer.
+	  Choose M to build this support as a module.
+	  The module will be called nfc_digital_uart.
+
 source "net/nfc/nci/Kconfig"
 source "net/nfc/hci/Kconfig"
 
diff --git a/net/nfc/Makefile b/net/nfc/Makefile
index 2555ff8..c6bb8f9 100644
--- a/net/nfc/Makefile
+++ b/net/nfc/Makefile
@@ -6,8 +6,11 @@ obj-$(CONFIG_NFC) += nfc.o
 obj-$(CONFIG_NFC_NCI) += nci/
 obj-$(CONFIG_NFC_HCI) += hci/
 obj-$(CONFIG_NFC_DIGITAL) += nfc_digital.o
+obj-$(CONFIG_NFC_DIGITAL_UART) += nfc_digital_uart.o
 
 nfc-objs := core.o netlink.o af_nfc.o rawsock.o llcp_core.o llcp_commands.o \
 		llcp_sock.o
 
 nfc_digital-objs := digital_core.o digital_technology.o digital_dep.o
+
+nfc_digital_uart-objs := digital_uart.o
diff --git a/net/nfc/digital_uart.c b/net/nfc/digital_uart.c
new file mode 100644
index 0000000..a759203
--- /dev/null
+++ b/net/nfc/digital_uart.c
@@ -0,0 +1,523 @@
+/*
+ * NFC Digital UART Line Discipline Framework
+ *
+ * Copyright (C) 2016, STMicroelectronics Pvt. Ltd.
+ *
+ * This software file (the "File") is distributed by STMicroelectronics Pvt.
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available on the worldwide web at
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+/* Inspired (hugely) by NCI LDISC implementation in NFC. */
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/poll.h>
+
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/ioctl.h>
+#include <linux/skbuff.h>
+
+#include <net/nfc/digital.h>
+#include <net/nfc/digital_uart.h>
+
+/* TX states  */
+#define DIGITAL_UART_SENDING	1
+#define DIGITAL_UART_TX_WAKEUP	2
+
+static struct digital_uart *digital_uart_drivers[DIGITAL_UART_DRIVER_MAX];
+
+static inline struct sk_buff *digital_uart_dequeue(struct digital_uart *du)
+{
+	struct sk_buff *skb = du->tx_skb;
+
+	if (!skb)
+		skb = skb_dequeue(&du->tx_q);
+	else
+		du->tx_skb = NULL;
+
+	return skb;
+}
+
+static inline int digital_uart_queue_empty(struct digital_uart *du)
+{
+	if (du->tx_skb)
+		return 0;
+
+	return skb_queue_empty(&du->tx_q);
+}
+
+static int digital_uart_tx_wakeup(struct digital_uart *du)
+{
+	if (test_and_set_bit(DIGITAL_UART_SENDING, &du->tx_state)) {
+		set_bit(DIGITAL_UART_TX_WAKEUP, &du->tx_state);
+		return 0;
+	}
+
+	schedule_work(&du->write_work);
+
+	return 0;
+}
+
+static void digital_uart_write_work(struct work_struct *work)
+{
+	struct digital_uart *du = container_of(work,
+					       struct digital_uart,
+					       write_work);
+	struct tty_struct *tty = du->tty;
+	struct sk_buff *skb;
+
+restart:
+	clear_bit(DIGITAL_UART_TX_WAKEUP, &du->tx_state);
+
+	if (du->ops.tx_start)
+		du->ops.tx_start(du);
+
+	while ((skb = digital_uart_dequeue(du))) {
+		int len;
+
+		set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+		len = tty->ops->write(tty, skb->data, skb->len);
+		skb_pull(skb, len);
+		if (skb->len) {
+			du->tx_skb = skb;
+			break;
+		}
+		kfree_skb(skb);
+	}
+
+	if (test_bit(DIGITAL_UART_TX_WAKEUP, &du->tx_state))
+		goto restart;
+
+	if (du->ops.tx_done && digital_uart_queue_empty(du))
+		du->ops.tx_done(du);
+
+	clear_bit(DIGITAL_UART_SENDING, &du->tx_state);
+}
+
+static int digital_uart_set_driver(struct tty_struct *tty, unsigned int driver)
+{
+	struct digital_uart *du = NULL;
+	int ret;
+
+	if (driver >= DIGITAL_UART_DRIVER_MAX)
+		return -EINVAL;
+
+	if (!digital_uart_drivers[driver])
+		return -ENOENT;
+
+	du = kzalloc(sizeof(*du), GFP_KERNEL);
+	if (!du)
+		return -ENOMEM;
+
+	memcpy(du, digital_uart_drivers[driver], sizeof(struct digital_uart));
+	du->tty = tty;
+	tty->disc_data = du;
+	skb_queue_head_init(&du->tx_q);
+	INIT_WORK(&du->write_work, digital_uart_write_work);
+	spin_lock_init(&du->rx_lock);
+
+	ret = du->ops.open(du);
+	if (ret) {
+		tty->disc_data = NULL;
+		kfree(du);
+	} else if (!try_module_get(du->owner)) {
+		du->ops.close(du);
+		tty->disc_data = NULL;
+		kfree(du);
+		return -ENOENT;
+	}
+
+	tty->receive_room = du->ops.recv_fr_max_sz(du);
+
+	return ret;
+}
+
+/* ------ LDISC part ------ */
+
+/* digital_uart_tty_open
+ *
+ *     Called when line discipline changed to DIGITAL_UART.
+ *
+ * Arguments:
+ *     tty pointer to tty info structure
+ * Return Value:
+ *     0 if success, otherwise error code
+ */
+static int digital_uart_tty_open(struct tty_struct *tty)
+{
+	/* Error if the tty has no write op */
+	if (!tty->ops->write)
+		return -EOPNOTSUPP;
+
+	tty->disc_data = NULL;
+
+	/* Flush any pending characters in the driver and line discipline. */
+
+	/* Note don't use ldisc_ref here as the
+	 * open path is before the ldisc is referencable.
+	 */
+
+	if (tty->ldisc->ops->flush_buffer)
+		tty->ldisc->ops->flush_buffer(tty);
+	tty_driver_flush_buffer(tty);
+
+	return 0;
+}
+
+/* digital_uart_tty_close()
+ *
+ *    Called when the line discipline is changed to something
+ *    else, the tty is closed, or the tty detects a hangup.
+ */
+static void digital_uart_tty_close(struct tty_struct *tty)
+{
+	struct digital_uart *du = (void *)tty->disc_data;
+
+	/* Detach from the tty */
+	tty->disc_data = NULL;
+
+	if (!du)
+		return;
+
+	if (du->tx_skb)
+		kfree_skb(du->tx_skb);
+	if (du->rx_skb)
+		kfree_skb(du->rx_skb);
+
+	skb_queue_purge(&du->tx_q);
+
+	du->ops.close(du);
+	du->tty = NULL;
+	module_put(du->owner);
+
+	cancel_work_sync(&du->write_work);
+
+	kfree(du);
+}
+
+/* digital_uart_tty_wakeup()
+ *
+ *    Callback for transmit wakeup. Called when low level
+ *    device driver can accept more send data.
+ *
+ * Arguments:        tty    pointer to associated tty instance data
+ * Return Value:    None
+ */
+static void digital_uart_tty_wakeup(struct tty_struct *tty)
+{
+	struct digital_uart *du = (void *)tty->disc_data;
+
+	if (!du)
+		return;
+
+	clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+
+	if (tty != du->tty)
+		return;
+
+	digital_uart_tx_wakeup(du);
+}
+
+/* digital_uart_tty_receive()
+ *
+ *     Called by tty low level driver when receive data is
+ *     available.
+ *
+ * Arguments:  tty          pointer to tty isntance data
+ *             data         pointer to received data
+ *             flags        pointer to flags for data
+ *             count        count of received data in bytes
+ *
+ * Return Value:    None
+ */
+static void digital_uart_tty_receive(struct tty_struct *tty, const u8 *data,
+				     char *flags, int count)
+{
+	struct digital_uart *du = (void *)tty->disc_data;
+
+	if (!du || tty != du->tty)
+		return;
+
+	spin_lock(&du->rx_lock);
+	du->ops.recv_buff(du, (void *)data, flags, count);
+	spin_unlock(&du->rx_lock);
+
+	tty_unthrottle(tty);
+}
+
+/* digital_uart_tty_ioctl()
+ *
+ *    Process IOCTL system call for the tty device.
+ *
+ * Arguments:
+ *
+ *    tty        pointer to tty instance data
+ *    file       pointer to open file object for device
+ *    cmd        IOCTL command code
+ *    arg        argument for IOCTL call (cmd dependent)
+ *
+ * Return Value:    Command dependent
+ */
+static int digital_uart_tty_ioctl(struct tty_struct *tty, struct file *file,
+				  unsigned int cmd, unsigned long arg)
+{
+	struct digital_uart *du = (void *)tty->disc_data;
+	int err = 0;
+
+	switch (cmd) {
+	case DIGITALUARTSETDRIVER:
+		if (!du)
+			return digital_uart_set_driver(tty, (unsigned int)arg);
+		else
+			return -EBUSY;
+		break;
+	default:
+		err = n_tty_ioctl_helper(tty, file, cmd, arg);
+		break;
+	}
+
+	return err;
+}
+
+/* We don't provide read/write/poll interface for user space. */
+static ssize_t digital_uart_tty_read(struct tty_struct *tty, struct file *file,
+				     unsigned char __user *buf, size_t nr)
+{
+	return 0;
+}
+
+static ssize_t digital_uart_tty_write(struct tty_struct *tty, struct file *file,
+				      const unsigned char *data, size_t count)
+{
+	return 0;
+}
+
+static unsigned int digital_uart_tty_poll(struct tty_struct *tty,
+					  struct file *filp, poll_table *wait)
+{
+	return 0;
+}
+
+static int digital_uart_send(struct digital_uart *du, struct sk_buff *skb)
+{
+	/* Queue TX packet */
+	skb_queue_tail(&du->tx_q, skb);
+
+	/* Try to start TX (if possible) */
+	digital_uart_tx_wakeup(du);
+
+	return 0;
+}
+
+/*  -- Default recv_buf handler --
+ *
+ * This handler receives the data from UART read the header to
+ * retrieve the frame length.
+ * This function can be hit multiple time to receive complete frame.
+ * Once complete frame is received, the frame is passed to the digital layer.
+ */
+static int digital_uart_default_recv_buf(struct digital_uart *du,
+					 const u8 *data,
+					 char *flags,
+					 int count)
+{
+	int chunk_len, err;
+	static int header_len;
+	unsigned int recv_fr_sz;
+
+	/* Decode all incoming data in packets
+	 * and enqueue then for processing.
+	 */
+	while (count > 0) {
+		/* If this is the first data of a packet, allocate a buffer */
+		if (!du->rx_skb) {
+			du->rx_packet_len = -1;
+			recv_fr_sz = du->ops.recv_fr_max_sz(du);
+			du->rx_skb = nfc_alloc_recv_skb(recv_fr_sz, GFP_KERNEL);
+			if (!du->rx_skb)
+				return -ENOMEM;
+			header_len = du->ops.recv_fr_hdr_sz(du, data, count);
+			if (header_len < 0) {
+				kfree_skb(du->rx_skb);
+				du->rx_skb = NULL;
+				return -EIO;
+			}
+		}
+
+		/* Eat byte after byte till full packet header is received */
+		if (du->rx_skb->len < header_len) {
+			*skb_put(du->rx_skb, 1) = *data++;
+			--count;
+			if (count)
+				continue;
+		}
+
+		/* if count is zero and hdr not fully received
+		 * continue, otherwise go ahead to check if
+		 * hdr is enough to complete the frame and
+		 * we will not receive any payload
+		 */
+		if (!count && du->rx_skb->len < header_len)
+			continue;
+
+		/* Header was received but packet len (if any) was not read */
+		if (du->rx_packet_len < 0) {
+			if (!header_len)
+				du->rx_packet_len =
+					du->ops.recv_pl_sz(du,
+							   data,
+							   count);
+			else
+				du->rx_packet_len = header_len +
+					du->ops.recv_pl_sz(du,
+							   du->rx_skb->data,
+							   du->rx_skb->len);
+		}
+
+		/* Compute how many bytes are missing and how many bytes can
+		 * be consumed.
+		 */
+		chunk_len = du->rx_packet_len - du->rx_skb->len;
+		if (count < chunk_len)
+			chunk_len = count;
+		if (chunk_len)
+			memcpy(skb_put(du->rx_skb, chunk_len), data, chunk_len);
+
+		/* if multiple frames are received, adjust data and count for
+		 * next frame, to be ready for next iterate of while (count > 0)
+		 */
+		data += chunk_len;
+		count -= chunk_len;
+
+		/* Check if packet is fully received */
+		if (du->rx_packet_len == du->rx_skb->len) {
+			/* Pass RX packet to driver */
+			err = du->ops.recv(du, du->rx_skb);
+			if (err)
+				nfc_err(du->tty->dev, "corrupted RX packet, err =%d\n",
+					err);
+			/* Next packet will be a new one */
+			du->rx_skb = NULL;
+		}
+	}
+
+	return 0;
+}
+
+int digital_uart_register(struct digital_uart *du)
+{
+	if (!du || !du->ops.open ||
+	    !du->ops.recv || !du->ops.close ||
+	    !du->ops.recv_fr_max_sz || !du->ops.recv_fr_hdr_sz ||
+	    !du->ops.recv_pl_sz)
+		return -EINVAL;
+
+	/* Set the send callback */
+	du->ops.send = digital_uart_send;
+
+	/* Install default handlers if not overridden */
+	if (!du->ops.recv_buff)
+		du->ops.recv_buff = digital_uart_default_recv_buf;
+
+	/* Add this driver in the driver list */
+	if (digital_uart_drivers[du->driver]) {
+		pr_err("driver %d is already registered\n", du->driver);
+		return -EBUSY;
+	}
+	digital_uart_drivers[du->driver] = du;
+
+	pr_info("DIGITAL uart driver '%s [%d]' registered\n",
+		du->name, du->driver);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(digital_uart_register);
+
+void digital_uart_unregister(struct digital_uart *du)
+{
+	pr_info("DIGITAL uart driver '%s [%d]' unregistered\n", du->name,
+		du->driver);
+
+	/* Remove this driver from the driver list */
+	digital_uart_drivers[du->driver] = NULL;
+}
+EXPORT_SYMBOL_GPL(digital_uart_unregister);
+
+void digital_uart_set_config(struct digital_uart *du,
+			     int baudrate,
+			     int flow_ctrl,
+			     enum digital_uart_stop_bits stop_bits)
+{
+	struct ktermios new_termios;
+
+	if (!du->tty)
+		return;
+
+	down_read(&du->tty->termios_rwsem);
+	new_termios = du->tty->termios;
+	up_read(&du->tty->termios_rwsem);
+	tty_termios_encode_baud_rate(&new_termios, baudrate, baudrate);
+
+	if (flow_ctrl)
+		new_termios.c_cflag |= CRTSCTS;
+	else
+		new_termios.c_cflag &= ~CRTSCTS;
+
+	if (stop_bits == DIGITAL_UART_STOP_BIT_2)
+		new_termios.c_cflag |= CSTOPB;
+
+	/* 8 bit data with no parity is default */
+	new_termios.c_cflag |= CS8;
+
+	tty_set_termios(du->tty, &new_termios);
+}
+EXPORT_SYMBOL_GPL(digital_uart_set_config);
+
+static struct tty_ldisc_ops digital_uart_ldisc = {
+	.magic		= TTY_LDISC_MAGIC,
+	.owner		= THIS_MODULE,
+	.name		= "n_digital",
+	.open		= digital_uart_tty_open,
+	.close		= digital_uart_tty_close,
+	.read		= digital_uart_tty_read,
+	.write		= digital_uart_tty_write,
+	.poll		= digital_uart_tty_poll,
+	.receive_buf	= digital_uart_tty_receive,
+	.write_wakeup	= digital_uart_tty_wakeup,
+	.ioctl		= digital_uart_tty_ioctl,
+};
+
+static int __init digital_uart_init(void)
+{
+	return tty_register_ldisc(N_DIGITAL, &digital_uart_ldisc);
+}
+
+static void __exit digital_uart_exit(void)
+{
+	tty_unregister_ldisc(N_DIGITAL);
+}
+
+module_init(digital_uart_init);
+module_exit(digital_uart_exit);
+
+MODULE_AUTHOR("Sudeep Biswas <sudeep.biswas@st.com>");
+MODULE_AUTHOR("Shikha Singh <shikha.singh@st.com>");
+MODULE_DESCRIPTION("NFC Digital UART driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS_LDISC(N_DIGITAL);
-- 
1.8.2.1

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

* [[linux-nfc][PATCH v1] 2/6] NFC: nfcst: Add ST NFC Transceiver core framework
  2017-05-02  6:03 [[linux-nfc][PATCH v1] 0/6] Support of ST NFC Transceiver Shikha Singh
  2017-05-02  6:03 ` [[linux-nfc][PATCH v1] 1/6] NFC: add generic UART support Shikha Singh
@ 2017-05-02  6:03 ` Shikha Singh
  2017-06-25 23:04   ` Samuel Ortiz
  2017-05-02  6:03 ` [[linux-nfc][PATCH v1] 3/6] NFC: nfcst: Add UART LDisc Driver Shikha Singh
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 11+ messages in thread
From: Shikha Singh @ 2017-05-02  6:03 UTC (permalink / raw)
  To: sameo, linux-wireless, linux-nfc
  Cc: raunaque.quaiser, manoj.kumar, sylvain.fidelis, raphael.collado,
	shikha.singh, MMS_MMY_Applications_SW

This patch implements the ST NFC Transceiver
core framework.
This framework implements the digital specifications.
ST NFC Phy drivers supporting SPI or UART interface can
register with this framework when a Transceiver is connected
with host using the respective interface.

Following the modular design approach, the core framework
exports helper functions that groups common features
required by all the phy drivers.
On the other hand it expects phy specific ops to be
implemented by the phy drivers.

Signed-off-by: Shikha Singh <shikha.singh@st.com>
---
 drivers/nfc/Kconfig          |    1 +
 drivers/nfc/Makefile         |    1 +
 drivers/nfc/nfcst/Kconfig    |   17 +
 drivers/nfc/nfcst/Makefile   |    6 +
 drivers/nfc/nfcst/core.c     | 1122 ++++++++++++++++++++++++++++++++++++++++++
 drivers/nfc/nfcst/stnfcdev.h |   70 +++
 6 files changed, 1217 insertions(+)
 create mode 100644 drivers/nfc/nfcst/Kconfig
 create mode 100644 drivers/nfc/nfcst/Makefile
 create mode 100644 drivers/nfc/nfcst/core.c
 create mode 100644 drivers/nfc/nfcst/stnfcdev.h

diff --git a/drivers/nfc/Kconfig b/drivers/nfc/Kconfig
index b065eb6..3ac0aba 100644
--- a/drivers/nfc/Kconfig
+++ b/drivers/nfc/Kconfig
@@ -58,4 +58,5 @@ source "drivers/nfc/st-nci/Kconfig"
 source "drivers/nfc/nxp-nci/Kconfig"
 source "drivers/nfc/s3fwrn5/Kconfig"
 source "drivers/nfc/st95hf/Kconfig"
+source "drivers/nfc/nfcst/Kconfig"
 endmenu
diff --git a/drivers/nfc/Makefile b/drivers/nfc/Makefile
index 640b727..9c1b127 100644
--- a/drivers/nfc/Makefile
+++ b/drivers/nfc/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_NFC_ST_NCI)	+= st-nci/
 obj-$(CONFIG_NFC_NXP_NCI)	+= nxp-nci/
 obj-$(CONFIG_NFC_S3FWRN5)	+= s3fwrn5/
 obj-$(CONFIG_NFC_ST95HF)	+= st95hf/
+obj-$(CONFIG_NFC_ST)		+= nfcst/
diff --git a/drivers/nfc/nfcst/Kconfig b/drivers/nfc/nfcst/Kconfig
new file mode 100644
index 0000000..2c71aa2
--- /dev/null
+++ b/drivers/nfc/nfcst/Kconfig
@@ -0,0 +1,17 @@
+config NFC_ST
+	tristate "ST NFC Transceiver driver"
+	depends on NFC_DIGITAL
+	help
+	  This enables the STMicroelectronics NFC transceiver
+	  core framework. These transceivers implement the
+	  digital specifications.
+	  The core framework registers with the digital core and
+	  implements the digital ops. On the other side, it
+	  exposes a framework for the phy drivers. Phy drivers
+	  implements ops that are required by the core for
+	  communication between the transceiver and the host.
+	  Phy driver can be an UART LDisc driver or an SPI slave
+	  driver.
+
+	  Say Y here to compile support for ST NFC transceiver core
+	  framework into the kernel or say M to compile it as module.
diff --git a/drivers/nfc/nfcst/Makefile b/drivers/nfc/nfcst/Makefile
new file mode 100644
index 0000000..d46acc5
--- /dev/null
+++ b/drivers/nfc/nfcst/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for STMicroelectronics NFC transceiver driver
+#
+
+nfcst-y += core.o
+obj-$(CONFIG_NFC_ST) += nfcst.o
diff --git a/drivers/nfc/nfcst/core.c b/drivers/nfc/nfcst/core.c
new file mode 100644
index 0000000..5a7e2b0
--- /dev/null
+++ b/drivers/nfc/nfcst/core.c
@@ -0,0 +1,1122 @@
+/*
+ * --------------------------------------------------------------------
+ * Core driver framework for ST NFC Transceiver
+ * --------------------------------------------------------------------
+ * Copyright (C) 2016 STMicroelectronics Pvt. Ltd. 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/err.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/nfc.h>
+#include <linux/wait.h>
+#include <net/nfc/digital.h>
+#include <net/nfc/nfc.h>
+#include "stnfcdev.h"
+
+/* supported protocols */
+#define DEVICE_SUPPORTED_PROT		(NFC_PROTO_ISO14443_MASK | \
+					NFC_PROTO_ISO14443_B_MASK | \
+					NFC_PROTO_ISO15693_MASK | \
+					NFC_PROTO_MIFARE_MASK)
+/* driver capabilities */
+#define DEVICE_CAPABILITIES		NFC_DIGITAL_DRV_CAPS_IN_CRC
+
+/* Command Send Interface */
+/* DEVICE_COMMAND_SEND CMD Ids */
+#define ECHO_CMD			0x55
+#define WRITE_REGISTER_CMD		0x9
+#define PROTOCOL_SELECT_CMD		0x2
+#define SEND_RECEIVE_CMD		0x4
+
+/* Select protocol codes */
+#define ISO15693_PROTOCOL_CODE		0x1
+#define ISO14443A_PROTOCOL_CODE		0x2
+#define ISO14443B_PROTOCOL_CODE		0x3
+
+/*
+ * head room len is 2
+ * 1 byte for cmd
+ * 1 byte for size
+ */
+#define DEVICE_HEADROOM_LEN		2
+
+/*
+ * tailroom is 1 for ISO14443A
+ * and 0 for ISO14443B/ISO15693,
+ * hence the max value 1 should be
+ * taken.
+ */
+#define DEVICE_TAILROOM_LEN		1
+
+/* Command Response interface */
+#define MAX_RESPONSE_BUFFER_SIZE	280
+#define ECHORESPONSE			0x55
+#define DEVICE_ERR_MASK			0xF
+#define DEVICE_TIMEOUT_ERROR		0x87
+#define DEVICE_NFCA_CRC_ERR_MASK	0x20
+#define DEVICE_NFCB_CRC_ERR_MASK	0x01
+#define TYPE2_RESP_ACK_NACK		0x90
+
+/* device transmission flag values */
+#define TRFLAG_NFCA_SHORT_FRAME		0x07
+#define TRFLAG_NFCA_STD_FRAME		0x08
+#define TRFLAG_NFCA_STD_FRAME_CRC	0x28
+
+/* Misc defs */
+#define HIGH				1
+#define LOW				0
+#define ISO14443A_RATS_REQ		0xE0
+#define RATS_TB1_PRESENT_MASK		0x20
+#define RATS_TA1_PRESENT_MASK		0x10
+#define TB1_FWI_MASK			0xF0
+#define WTX_REQ_FROM_TAG		0xF2
+#define VALID_RESP_MASK			0x90
+#define VALID_RESP_VALUE		0x80
+
+#define MAX_CMD_LEN			0x6
+
+#define MAX_CMD_PARAMS			4
+
+/* flag to differentiate synchronous & asynchronous request */
+enum req_type {
+	SYNC,
+	ASYNC,
+};
+
+struct cmd {
+	int cmd_len;
+	unsigned char cmd_id;
+	unsigned char no_cmd_params;
+	unsigned char cmd_params[MAX_CMD_PARAMS];
+	enum req_type req;
+};
+
+struct param_list {
+	int param_offset;
+	int new_param_val;
+};
+
+/*
+ * List of top-level cmds to be used internally by the driver.
+ * All these commands are build on top of basic commands
+ * such as SEND_RECEIVE_CMD, PROTOCOL_SELECT_CMD, etc.
+ * These top level cmds are used internally while implementing various ops of
+ * digital layer/driver probe or extending the digital framework layer for
+ * features that are not yet implemented there, for example, WTX cmd handling.
+ */
+enum nfcst_cmd_list {
+	CMD_ECHO,
+	CMD_NFCA_CONFIG,
+	CMD_NFCA_DEMOGAIN,
+	CMD_ISO14443B_DEMOGAIN,
+	CMD_NFCA_PROTOCOL_SELECT,
+	CMD_ISO14443B_PROTOCOL_SELECT,
+	CMD_WTX_RESPONSE,
+	CMD_FIELD_OFF,
+	CMD_ISO15693_PROTOCOL_SELECT,
+};
+
+static const struct cmd cmd_array[] = {
+	[CMD_ECHO] = {
+		.cmd_len = 0x1,
+		.cmd_id = ECHO_CMD,
+		.no_cmd_params = 0,
+		.req = SYNC,
+	},
+	[CMD_NFCA_CONFIG] = {
+		.cmd_len = 0x6,
+		.cmd_id = WRITE_REGISTER_CMD,
+		.no_cmd_params = 0x4,
+		.cmd_params = {0x3A, 0x00, 0x5A, 0x04},
+		.req = SYNC,
+	},
+	[CMD_NFCA_DEMOGAIN] = {
+		.cmd_len = 0x6,
+		.cmd_id = WRITE_REGISTER_CMD,
+		.no_cmd_params = 0x4,
+		.cmd_params = {0x68, 0x01, 0x01, 0xDF},
+		.req = SYNC,
+	},
+	[CMD_ISO14443B_DEMOGAIN] = {
+		.cmd_len = 0x6,
+		.cmd_id = WRITE_REGISTER_CMD,
+		.no_cmd_params = 0x4,
+		.cmd_params = {0x68, 0x01, 0x01, 0x51},
+		.req = SYNC,
+	},
+	[CMD_NFCA_PROTOCOL_SELECT] = {
+		.cmd_len = 0x6,
+		.cmd_id = PROTOCOL_SELECT_CMD,
+		.no_cmd_params = 0x4,
+		.cmd_params = {ISO14443A_PROTOCOL_CODE, 0x00, 0x01, 0xA0},
+		.req = SYNC,
+	},
+	[CMD_ISO14443B_PROTOCOL_SELECT] = {
+		.cmd_len = 0x6,
+		.cmd_id = PROTOCOL_SELECT_CMD,
+		.no_cmd_params = 0x4,
+		.cmd_params = {ISO14443B_PROTOCOL_CODE, 0x01, 0x03, 0xFF},
+		.req = SYNC,
+	},
+	[CMD_WTX_RESPONSE] = {
+		.cmd_len = 0x5,
+		.cmd_id = SEND_RECEIVE_CMD,
+		.no_cmd_params = 0x3,
+		.cmd_params = {0xF2, 0x00, TRFLAG_NFCA_STD_FRAME_CRC},
+		.req = ASYNC,
+	},
+	[CMD_FIELD_OFF] = {
+		.cmd_len = 0x4,
+		.cmd_id = PROTOCOL_SELECT_CMD,
+		.no_cmd_params = 0x2,
+		.cmd_params = {0x0, 0x0},
+		.req = SYNC,
+	},
+	[CMD_ISO15693_PROTOCOL_SELECT] = {
+		.cmd_len = 0x4,
+		.cmd_id = PROTOCOL_SELECT_CMD,
+		.no_cmd_params = 0x2,
+		.cmd_params = {ISO15693_PROTOCOL_CODE, 0x0D},
+		.req = SYNC,
+	},
+};
+
+/* nfcst_digital_cmd_complete_arg stores client context */
+struct nfcst_digital_cmd_complete_arg {
+	nfc_digital_cmd_complete_t complete_cb;
+	void *cb_usrarg;
+	bool rats;
+};
+
+struct nfcst_context {
+	struct nfc_digital_dev *ddev;
+	struct nfc_dev *nfcdev;
+	struct nfcst_digital_cmd_complete_arg complete_cb_arg;
+	unsigned char sendrcv_trflag;
+	struct semaphore exchange_lock;
+	u8 current_protocol;
+	u8 current_rf_tech;
+	int fwi;
+	struct work_struct write_work;
+	int wtx_mm;
+	struct device *dev;
+	void *phy_ctx;
+	enum nfcst_phy phy;
+	struct nfcst_if_ops *if_ops;
+	struct nfcst_pltf_data cfg;
+	bool req_is_sync;
+	struct completion done;
+	bool nfcst_power;
+	bool trig_config;
+	struct sk_buff *recv_buff;
+};
+
+static struct sk_buff *nfcst_send_recv_fr(struct nfcst_context *ctx,
+					  struct sk_buff *send_buf,
+					  enum req_type req)
+{
+	int err;
+
+	if (!send_buf || !ctx || !ctx->if_ops->phy_send || !ctx->dev ||
+	    !ctx->phy_ctx)
+		return NULL;
+
+	reinit_completion(&ctx->done);
+
+	ctx->recv_buff = NULL;
+	ctx->req_is_sync = req;
+
+	err = ctx->if_ops->phy_send(ctx->phy_ctx, send_buf);
+	if (err) {
+		dev_err(ctx->dev, "phy_send error %d\n", err);
+		return ERR_PTR(err);
+	}
+
+	if (req == ASYNC)
+		return NULL;
+
+	err = wait_for_completion_timeout(&ctx->done, msecs_to_jiffies(1000));
+	if (!err) {
+		dev_err(ctx->dev, "phy timeout error\n");
+		return ERR_PTR(-ETIMEDOUT);
+	}
+
+	return ctx->recv_buff;
+}
+
+/*
+ * nfcst_send_recv_cmd() is for sending commands to device
+ * that are described in the cmd_array[]. It can optionally
+ * receive the response if the cmd request is of type
+ * SYNC.
+ */
+static int nfcst_send_recv_cmd(struct nfcst_context *context,
+			       enum nfcst_cmd_list cmd,
+			       int no_modif,
+			       struct param_list *list_array)
+{
+	int i, ret = 0;
+	struct sk_buff *skb_send, *skb_recv;
+
+	if (cmd_array[cmd].cmd_len > MAX_CMD_LEN)
+		return -EINVAL;
+	if (cmd_array[cmd].no_cmd_params < no_modif)
+		return -EINVAL;
+	if (no_modif && !list_array)
+		return -EINVAL;
+
+	skb_send = alloc_skb(MAX_CMD_LEN, GFP_KERNEL);
+	if (!skb_send)
+		return -ENOMEM;
+
+	skb_reserve(skb_send, cmd_array[cmd].cmd_len);
+	skb_push(skb_send, cmd_array[cmd].cmd_len);
+
+	skb_send->data[0] = cmd_array[cmd].cmd_id;
+	if (cmd_array[cmd].no_cmd_params > 0) {
+		skb_send->data[1] = cmd_array[cmd].no_cmd_params;
+		memcpy(&skb_send->data[2], cmd_array[cmd].cmd_params,
+		       cmd_array[cmd].no_cmd_params);
+	}
+
+	for (i = 0; i < no_modif; i++) {
+		if (list_array[i].param_offset >= cmd_array[cmd].no_cmd_params)
+			return -EINVAL;
+
+		skb_send->data[2 + list_array[i].param_offset] =
+						list_array[i].new_param_val;
+	}
+
+	skb_recv = nfcst_send_recv_fr(context, skb_send, cmd_array[cmd].req);
+	if (IS_ERR(skb_recv)) {
+		dev_err(context->dev, "send receive of frame fail with %ld\n",
+			PTR_ERR(skb_recv));
+		return PTR_ERR(skb_recv);
+	}
+
+	if (cmd_array[cmd].req == SYNC) {
+		ret = -EIO;
+		if (!skb_recv)
+			return ret;
+
+		if (cmd_array[cmd].cmd_id == ECHO_CMD) {
+			if (skb_recv->data[0] != ECHORESPONSE)
+				dev_err(context->dev, "echo failed, recv 0x%x\n",
+					skb_recv->data[0]);
+			else
+				ret = 0;
+		} else if (skb_recv->data[0]) {
+			dev_err(context->dev, "send recv frame, err = 0x%x\n",
+				skb_recv->data[0]);
+		} else {
+			ret = 0;
+		}
+
+		kfree_skb(skb_recv);
+	}
+
+	return ret;
+}
+
+static int secondary_configuration_type4a(struct nfcst_context *context)
+{
+	int result = 0;
+	struct device *dev = &context->nfcdev->dev;
+
+	/* 14443A config setting after select protocol */
+	result = nfcst_send_recv_cmd(context,
+				     CMD_NFCA_CONFIG,
+				     0,
+				     NULL);
+	if (result) {
+		dev_err(dev, "type a config cmd, err = 0x%x\n", result);
+		return result;
+	}
+
+	/* 14443A demo gain setting */
+	result = nfcst_send_recv_cmd(context,
+				     CMD_NFCA_DEMOGAIN,
+				     0,
+				     NULL);
+	if (result)
+		dev_err(dev, "type a demogain cmd, err = 0x%x\n", result);
+
+	return result;
+}
+
+static int secondary_configuration_type4b(struct nfcst_context *context)
+{
+	int result = 0;
+	struct device *dev = &context->nfcdev->dev;
+
+	result = nfcst_send_recv_cmd(context,
+				     CMD_ISO14443B_DEMOGAIN,
+				     0,
+				     NULL);
+	if (result)
+		dev_err(dev, "type b demogain cmd, err = 0x%x\n", result);
+
+	return result;
+}
+
+static int nfcst_select_protocol(struct nfcst_context *context, int type)
+{
+	int result = 0;
+	struct device *dev;
+
+	dev = &context->nfcdev->dev;
+
+	switch (type) {
+	case NFC_DIGITAL_RF_TECH_106A:
+		context->current_rf_tech = NFC_DIGITAL_RF_TECH_106A;
+		result = nfcst_send_recv_cmd(context,
+					     CMD_NFCA_PROTOCOL_SELECT,
+					     0,
+					     NULL);
+		if (result) {
+			dev_err(dev, "protocol sel, err = 0x%x\n",
+				result);
+			return result;
+		}
+
+		/* secondary config. for 14443Type 4A after protocol select */
+		result = secondary_configuration_type4a(context);
+		if (result) {
+			dev_err(dev, "type a secondary config, err = 0x%x\n",
+				result);
+			return result;
+		}
+		break;
+	case NFC_DIGITAL_RF_TECH_106B:
+		context->current_rf_tech = NFC_DIGITAL_RF_TECH_106B;
+		result = nfcst_send_recv_cmd(context,
+					     CMD_ISO14443B_PROTOCOL_SELECT,
+					     0,
+					     NULL);
+		if (result) {
+			dev_err(dev, "protocol sel send, err = 0x%x\n",
+				result);
+			return result;
+		}
+
+		/*
+		 * delay of 5-6 ms is required after select protocol
+		 * command in case of ISO14443 Type B
+		 */
+		usleep_range(50000, 60000);
+
+		/* secondary config. for 14443Type 4B after protocol select */
+		result = secondary_configuration_type4b(context);
+		if (result) {
+			dev_err(dev, "type b secondary config, err = 0x%x\n",
+				result);
+			return result;
+		}
+		break;
+	case NFC_DIGITAL_RF_TECH_ISO15693:
+		context->current_rf_tech = NFC_DIGITAL_RF_TECH_ISO15693;
+		result = nfcst_send_recv_cmd(context,
+					     CMD_ISO15693_PROTOCOL_SELECT,
+					     0,
+					     NULL);
+		if (result) {
+			dev_err(dev, "protocol sel send, err = 0x%x\n",
+				result);
+			return result;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int iso14443_config_fdt(struct nfcst_context *context, int wtxm)
+{
+	int result = 0;
+	struct nfc_digital_dev *nfcddev = context->ddev;
+	unsigned char pp_typeb;
+	struct param_list new_params[2];
+
+	struct device *dev = &context->nfcdev->dev;
+
+	pp_typeb = cmd_array[CMD_ISO14443B_PROTOCOL_SELECT].cmd_params[2];
+
+	if (nfcddev->curr_protocol == NFC_PROTO_ISO14443 && context->fwi < 4)
+		context->fwi = 4;
+
+	new_params[0].param_offset = 2;
+	if (nfcddev->curr_protocol == NFC_PROTO_ISO14443)
+		new_params[0].new_param_val = context->fwi;
+	else if (nfcddev->curr_protocol == NFC_PROTO_ISO14443_B)
+		new_params[0].new_param_val = pp_typeb;
+
+	new_params[1].param_offset = 3;
+	new_params[1].new_param_val = wtxm;
+
+	switch (nfcddev->curr_protocol) {
+	case NFC_PROTO_ISO14443:
+		result = nfcst_send_recv_cmd(context,
+					     CMD_NFCA_PROTOCOL_SELECT,
+					     2,
+					     new_params);
+		if (result) {
+			dev_err(dev, "iso14443_config_fdt: nfcst_send_recv_cmd fails, err = %d\n",
+				result);
+			return result;
+		}
+
+		/* secondary config. for 14443Type 4A after protocol select */
+		result = secondary_configuration_type4a(context);
+		if (result) {
+			dev_err(dev, "iso14443_config_fdt: secondary_configuration_type4a, err = %d\n",
+				result);
+			return result;
+		}
+		break;
+	case NFC_PROTO_ISO14443_B:
+		result = nfcst_send_recv_cmd(context,
+					     CMD_ISO14443B_PROTOCOL_SELECT,
+					     2,
+					     new_params);
+		if (result) {
+			dev_err(dev, "WTX type b sel proto,err = %d\n", result);
+			return result;
+		}
+
+		/* secondary config. for 14443Type 4B after protocol select */
+		result = secondary_configuration_type4b(context);
+		if (result) {
+			dev_err(dev, "WTX type b second. config, err = 0x%x\n",
+				result);
+			return result;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int nfcst_handle_config_fdt(struct nfcst_context *context,
+				   bool new_wtx)
+{
+	int result = 0;
+	unsigned char val_mm = 0;
+	struct param_list new_params[1];
+	struct nfc_digital_dev *nfcddev = context->ddev;
+	struct device *dev = &context->nfcdev->dev;
+	int wtx_val;
+
+	if (new_wtx) {
+		wtx_val = context->wtx_mm;
+		result = iso14443_config_fdt(context, wtx_val & 0x3f);
+		if (result) {
+			dev_err(dev, "Config. setting error on WTX req, err = %d\n",
+				result);
+			return result;
+		}
+
+		/* Send response of wtx with ASYNC as no response expected */
+		new_params[0].param_offset = 1;
+		new_params[0].new_param_val = wtx_val;
+
+		result = nfcst_send_recv_cmd(context,
+					     CMD_WTX_RESPONSE,
+					     1,
+					     new_params);
+		if (result)
+			dev_err(dev, "WTX response send, err = %d\n", result);
+		return result;
+	}
+
+	/* if no new wtx, cofigure with default values */
+	if (nfcddev->curr_protocol == NFC_PROTO_ISO14443)
+		val_mm = cmd_array[CMD_NFCA_PROTOCOL_SELECT].cmd_params[3];
+	else if (nfcddev->curr_protocol == NFC_PROTO_ISO14443_B)
+		val_mm = cmd_array[CMD_ISO14443B_PROTOCOL_SELECT].cmd_params[3];
+	result = iso14443_config_fdt(context, val_mm);
+	if (result)
+		dev_err(dev, "Default config. setting error, err = %d\n",
+			result);
+
+	return result;
+}
+
+static void nfcst_handle_wtx(struct work_struct *work)
+{
+	int ret;
+	struct nfcst_context *ctx = container_of(work,
+						 struct nfcst_context,
+						 write_work);
+
+	struct device *dev = &ctx->nfcdev->dev;
+
+	ret = nfcst_handle_config_fdt(ctx, true);
+	if (ret)
+		dev_err(dev, "nfcst_handle_wtx:: nfcst_handle_config_fdt, err = %d\n",
+			ret);
+
+	ctx->trig_config = true;
+}
+
+static int nfcst_error_handling(struct nfcst_context *context,
+				struct sk_buff *skb_resp,
+				int res_len)
+{
+	int result = 0;
+	unsigned char error_byte;
+	struct device *dev = &context->nfcdev->dev;
+
+	/* First check device specific error */
+	if (skb_resp->data[0] & DEVICE_ERR_MASK) {
+		if (skb_resp->data[0] == DEVICE_TIMEOUT_ERROR)
+			result = -ETIMEDOUT;
+		else
+			result = -EIO;
+		dev_dbg(dev, "Error frame[0]: 0x%x and result %d\n",
+			skb_resp->data[0], result);
+		return  result;
+	}
+
+	/* Check for CRC err only if CRC is present in the tag response */
+	switch (context->current_rf_tech) {
+	case NFC_DIGITAL_RF_TECH_106A:
+		/* In case of Type2 ACK and NACK response, no CRC check*/
+		if (context->ddev->curr_protocol == NFC_PROTO_MIFARE) {
+			if (skb_resp->data[0] == TYPE2_RESP_ACK_NACK)
+				break;
+		}
+		if (context->sendrcv_trflag == TRFLAG_NFCA_STD_FRAME_CRC) {
+			error_byte = skb_resp->data[res_len - 3];
+			if (error_byte & DEVICE_NFCA_CRC_ERR_MASK) {
+				/* CRC error occurred */
+				dev_err(dev, "CRC error, byte received = 0x%x\n",
+					error_byte);
+				result = -EIO;
+			}
+		}
+		break;
+	case NFC_DIGITAL_RF_TECH_106B:
+	case NFC_DIGITAL_RF_TECH_ISO15693:
+		error_byte = skb_resp->data[res_len - 1];
+		if (error_byte & DEVICE_NFCB_CRC_ERR_MASK) {
+			/* CRC error occurred */
+			dev_err(dev, "CRC error, byte received = 0x%x\n",
+				error_byte);
+			result = -EIO;
+		}
+		break;
+	}
+
+	return result;
+}
+
+static void nfcst_response_handler(struct nfcst_context *context,
+				   struct sk_buff *skb_resp)
+{
+	int skb_len;
+	struct nfcst_digital_cmd_complete_arg *cb_arg;
+
+	cb_arg = &context->complete_cb_arg;
+
+	/* Remove device specific header */
+	skb_pull(skb_resp, 2);
+
+	skb_len = skb_resp->len;
+
+	/* check if it is case of RATS request reply & FWI is present */
+	if (context->current_rf_tech == NFC_DIGITAL_RF_TECH_106A &&
+	    cb_arg->rats && (skb_resp->data[1] & RATS_TB1_PRESENT_MASK)) {
+		if (skb_resp->data[1] & RATS_TA1_PRESENT_MASK)
+			context->fwi =
+				(skb_resp->data[3] & TB1_FWI_MASK) >> 4;
+		else
+			context->fwi =
+				(skb_resp->data[2] & TB1_FWI_MASK) >> 4;
+
+		context->trig_config = true;
+	}
+	cb_arg->rats = false;
+
+	/** CRC handling **/
+	/* For MIFARE Type2, CRC handling will be done by digital framework */
+	if (context->current_rf_tech == NFC_DIGITAL_RF_TECH_106A &&
+	    context->ddev->curr_protocol == NFC_PROTO_MIFARE) {
+		/* Removing Transceiver specific data */
+		skb_trim(skb_resp, (skb_len - 3));
+		return;
+	}
+	/* Remove CRC bytes only if received frames data has an eod (CRC) */
+	switch (context->current_rf_tech) {
+	case NFC_DIGITAL_RF_TECH_106A:
+		if (context->sendrcv_trflag == TRFLAG_NFCA_STD_FRAME_CRC)
+			skb_trim(skb_resp, (skb_len - 5));
+		else
+			skb_trim(skb_resp, (skb_len - 3));
+		break;
+	case NFC_DIGITAL_RF_TECH_106B:
+	case NFC_DIGITAL_RF_TECH_ISO15693:
+		skb_trim(skb_resp, (skb_len - 3));
+		break;
+	}
+}
+
+static int nfcst_wake(void *context)
+{
+	int nth_attempt = 1;
+	int result;
+	struct nfcst_context *ctx = (struct nfcst_context *)context;
+
+	if (ctx->phy == PHY_UART || ctx->phy == PHY_SPI) {
+		do {
+			result = nfcst_send_recv_cmd(ctx,
+						     CMD_ECHO,
+						     0,
+						     NULL);
+			if (!result) {
+				ctx->nfcst_power = true;
+
+				/*
+				 * TBD: If baud rate is set different than
+				 * the default, (i.e. nfcst_pltf_data contains
+				 * a baudrate different than default), then
+				 * we need to set the baudrate of our device.
+				 * This is done by sending the 0xA command.
+				 * The response of the command should be ignored
+				 * because the response is received on the
+				 * new baudrate and we have not yet
+				 * re-configured our tty device on the new
+				 * baudrate. So the received response of 0xA,
+				 * which should be 0x55 (only one byte) could be
+				 * some other value (so ignore it).
+				 * Once the response of 1 byte is received, we
+				 * must re-configure our tty device to the new
+				 * baudrate.
+				 * This must be done using the UART phy driver.
+				 * For that we need to introduce a new ops
+				 * (such as setconfig) and pass the
+				 * nfcst_pltf_data struct saved in nfcst_context
+				 * to it. SPI based phy driver could also need
+				 * to implement this new ops for example to set
+				 * some parameters specific to spi such as clk
+				 * frequency (to be stored in nfcst_pltf_data)
+				 */
+				return 0;
+			}
+		} while (nth_attempt++ < 4);
+	} else { /* TBD: Support for SPI interface */
+		return -EINVAL;
+	}
+
+	return -ETIMEDOUT;
+}
+
+/* NFC ops functions definition */
+static int nfcst_in_configure_hw(struct nfc_digital_dev *ddev, int type,
+				 int param)
+{
+	struct nfcst_context *context = nfc_digital_get_drvdata(ddev);
+
+	if (!context->nfcst_power)
+		return -EIO;
+
+	if (type == NFC_DIGITAL_CONFIG_RF_TECH)
+		return nfcst_select_protocol(context, param);
+
+	if (type == NFC_DIGITAL_CONFIG_FRAMING) {
+		switch (param) {
+		case NFC_DIGITAL_FRAMING_NFCA_SHORT:
+			context->sendrcv_trflag = TRFLAG_NFCA_SHORT_FRAME;
+			break;
+		case NFC_DIGITAL_FRAMING_NFCA_STANDARD:
+			context->sendrcv_trflag = TRFLAG_NFCA_STD_FRAME;
+			break;
+		case NFC_DIGITAL_FRAMING_NFCA_T4T:
+		case NFC_DIGITAL_FRAMING_NFCA_T2T:
+		case NFC_DIGITAL_FRAMING_NFCA_NFC_DEP:
+		case NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A:
+			context->sendrcv_trflag = TRFLAG_NFCA_STD_FRAME_CRC;
+			break;
+		case NFC_DIGITAL_FRAMING_NFCB:
+		case NFC_DIGITAL_FRAMING_ISO15693_INVENTORY:
+		case NFC_DIGITAL_FRAMING_ISO15693_T5T:
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static int rf_off(struct nfcst_context *context)
+{
+	int rc;
+	struct device *dev;
+
+	dev = &context->nfcdev->dev;
+
+	/*
+	 * TBD: Currently basic pwr mgmt. is implemented !
+	 * (switching off the field)
+	 * In a better approach, we can send the idle command
+	 * after switching off the field. This will save
+	 * more power.
+	 * In fact even better is to switch off the device
+	 * assuming the power to device is coming from a
+	 * regulator which can be turned off/on.
+	 */
+	rc = nfcst_send_recv_cmd(context, CMD_FIELD_OFF, 0, NULL);
+	if (rc)
+		dev_err(dev, "protocol sel send field off, err = %d\n", rc);
+
+	return rc;
+}
+
+static int nfcst_in_send_cmd(struct nfc_digital_dev *ddev,
+			     struct sk_buff *skb,
+			     u16 timeout,
+			     nfc_digital_cmd_complete_t cb,
+			     void *arg)
+{
+	struct nfcst_context *context = nfc_digital_get_drvdata(ddev);
+	int rc;
+	int len_data_to_tag = 0;
+
+	if (!context->nfcst_power)
+		return -EIO;
+
+	/*
+	 * down the semaphore to indicate that last nfcst_in_send_cmd()
+	 * call is pending, If interrupted, WARN and return !
+	 */
+	rc = down_killable(&context->exchange_lock);
+	if (rc) {
+		WARN(1, "Semaphore wait is interrupted in nfcst_in_send_cmd\n");
+		return rc;
+	}
+
+	if (context->trig_config) {
+		context->trig_config = false;
+		rc = nfcst_handle_config_fdt(context, false);
+		if (rc) {
+			dev_err(&context->nfcdev->dev, "config fdt failed from nfcst_in_send_cmd %d\n",
+				rc);
+			return rc;
+		}
+	}
+
+	switch (context->current_rf_tech) {
+	case NFC_DIGITAL_RF_TECH_106A:
+		len_data_to_tag = skb->len + 1;
+		*skb_put(skb, 1) = context->sendrcv_trflag;
+		break;
+	case NFC_DIGITAL_RF_TECH_106B:
+	case NFC_DIGITAL_RF_TECH_ISO15693:
+		len_data_to_tag = skb->len;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	skb_push(skb, 2);
+	skb->data[0] = SEND_RECEIVE_CMD;
+	skb->data[1] = len_data_to_tag;
+
+	context->complete_cb_arg.cb_usrarg = arg;
+	context->complete_cb_arg.complete_cb = cb;
+
+	if ((skb->data[2] == ISO14443A_RATS_REQ) &&
+	    context->current_rf_tech == NFC_DIGITAL_RF_TECH_106A)
+		context->complete_cb_arg.rats = true;
+
+	rc = PTR_ERR(nfcst_send_recv_fr(context, skb, ASYNC));
+	if (rc) {
+		dev_err(&context->nfcdev->dev,
+			"Error %d trying to perform data_exchange", rc);
+		up(&context->exchange_lock);
+	}
+
+	return rc;
+}
+
+/* p2p will be supported in a later release ! */
+static int nfcst_tg_configure_hw(struct nfc_digital_dev *ddev,
+				 int type,
+				 int param)
+{
+	return 0;
+}
+
+static int nfcst_tg_send_cmd(struct nfc_digital_dev *ddev,
+			     struct sk_buff *skb,
+			     u16 timeout,
+			     nfc_digital_cmd_complete_t cb,
+			     void *arg)
+{
+	return 0;
+}
+
+static int nfcst_tg_listen(struct nfc_digital_dev *ddev,
+			   u16 timeout,
+			   nfc_digital_cmd_complete_t cb,
+			   void *arg)
+{
+	return 0;
+}
+
+static int nfcst_tg_get_rf_tech(struct nfc_digital_dev *ddev, u8 *rf_tech)
+{
+	return 0;
+}
+
+static int nfcst_switch_rf(struct nfc_digital_dev *ddev, bool on)
+{
+	u8 rf_tech;
+	int rc;
+
+	struct nfcst_context *context = nfc_digital_get_drvdata(ddev);
+
+	if (!context->nfcst_power) {
+		if (on) {
+			rc = nfcst_wake(context);
+			if (rc)
+				return rc;
+		} else {
+			return 0;
+		}
+	}
+
+	rf_tech = ddev->curr_rf_tech;
+
+	if (on)
+		/* switch on RF field */
+		return nfcst_select_protocol(context, rf_tech);
+
+	/* switch OFF RF field */
+	return rf_off(context);
+}
+
+/* TODO nfcst_abort_cmd */
+static void nfcst_abort_cmd(struct nfc_digital_dev *ddev)
+{
+}
+
+static struct nfc_digital_ops nfcst_nfc_digital_ops = {
+	.in_configure_hw = nfcst_in_configure_hw,
+	.in_send_cmd = nfcst_in_send_cmd,
+
+	.tg_listen = nfcst_tg_listen,
+	.tg_configure_hw = nfcst_tg_configure_hw,
+	.tg_send_cmd = nfcst_tg_send_cmd,
+	.tg_get_rf_tech = nfcst_tg_get_rf_tech,
+
+	.switch_rf = nfcst_switch_rf,
+	.abort_cmd = nfcst_abort_cmd,
+};
+
+/*
+ * phy drivers can register with the framework,
+ * this will return the new (attached) nfcst_context object
+ */
+void *nfcst_register_phy(enum nfcst_phy phy,
+			 void *phy_ctx,
+			 struct nfcst_if_ops *ops,
+			 struct device *dev,
+			 struct nfcst_pltf_data *pdata)
+{
+	int ret;
+	struct nfcst_context *ctx;
+
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return ERR_PTR(-ENOMEM);
+
+	ctx->phy_ctx = phy_ctx;
+	ctx->if_ops = ops;
+	ctx->dev = dev;
+	ctx->phy = phy;
+
+	memcpy(&ctx->cfg, pdata, sizeof(*pdata));
+
+	ctx->fwi = cmd_array[CMD_NFCA_PROTOCOL_SELECT].cmd_params[2];
+
+	init_completion(&ctx->done);
+
+	/* create NFC dev object and register with NFC Subsystem */
+	ctx->ddev = nfc_digital_allocate_device(&nfcst_nfc_digital_ops,
+						DEVICE_SUPPORTED_PROT,
+						DEVICE_CAPABILITIES,
+						DEVICE_HEADROOM_LEN,
+						DEVICE_TAILROOM_LEN);
+	if (!ctx->ddev) {
+		ret = -ENOMEM;
+		goto error;
+	}
+
+	ctx->nfcdev = ctx->ddev->nfc_dev;
+	nfc_digital_set_parent_dev(ctx->ddev, dev);
+
+	ret = nfc_digital_register_device(ctx->ddev);
+	if (ret) {
+		dev_err(&ctx->nfcdev->dev, "st nfc device registration failed\n");
+		goto err_free_digital_device;
+	}
+
+	nfc_digital_set_drvdata(ctx->ddev, ctx);
+
+	sema_init(&ctx->exchange_lock, 1);
+	INIT_WORK(&ctx->write_work, nfcst_handle_wtx);
+
+	return (void *)ctx;
+
+err_free_digital_device:
+	nfc_digital_free_device(ctx->ddev);
+
+error:
+	kfree(ctx);
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(nfcst_register_phy);
+
+void nfcst_unregister_phy(void *context)
+{
+	struct nfcst_context *ctx = (struct nfcst_context *)context;
+
+	up(&ctx->exchange_lock);
+	nfc_digital_unregister_device(ctx->ddev);
+	nfc_digital_free_device(ctx->ddev);
+	kfree(ctx);
+}
+EXPORT_SYMBOL_GPL(nfcst_unregister_phy);
+
+int nfcst_recv_frame(void *context, struct sk_buff *skb_res)
+{
+	int result;
+	struct nfcst_digital_cmd_complete_arg *cb_arg;
+
+	struct nfcst_context *ctx = (struct nfcst_context *)context;
+
+	/* first check the sync request */
+	if (ctx->req_is_sync == SYNC) {
+		ctx->recv_buff = skb_res;
+		complete(&ctx->done);
+		return 0;
+	}
+
+	/* now check for async request */
+	cb_arg = &ctx->complete_cb_arg;
+
+	/* check error skb */
+	if (IS_ERR(skb_res)) {
+		result = PTR_ERR(skb_res);
+		skb_res = NULL;
+		goto end;
+	}
+
+	/* check for excahange semaphore state */
+	if (!down_trylock(&ctx->exchange_lock)) {
+		WARN(1, "nfcst response in unknown context\n");
+		result = -EINVAL;
+		goto end;
+	}
+
+	result = nfcst_error_handling(ctx, skb_res, skb_res->len);
+	if (result)
+		goto end;
+
+	if (skb_res->len > 2 && skb_res->data[2] == WTX_REQ_FROM_TAG) {
+		ctx->wtx_mm = skb_res->data[3];
+		kfree_skb(skb_res);
+		schedule_work(&ctx->write_work);
+		return 0;
+	}
+
+	nfcst_response_handler(ctx, skb_res);
+
+	/* call digital layer callback */
+	cb_arg->complete_cb(ctx->ddev, cb_arg->cb_usrarg, skb_res);
+
+	/* up the semaphore before returning */
+	up(&ctx->exchange_lock);
+
+	return 0;
+
+end:
+	kfree_skb(skb_res);
+	cb_arg->rats = false;
+	skb_res = ERR_PTR(result);
+	/* callback with error */
+	cb_arg->complete_cb(ctx->ddev, cb_arg->cb_usrarg, skb_res);
+	/* up the semaphore before returning */
+	up(&ctx->exchange_lock);
+
+	/*
+	 * frame is received with success, though frame itself can
+	 * contain error or new error generated. In later case we
+	 * already inform the digital layer about the error, but
+	 * the underlying phy layer must be reported as no error
+	 */
+	return 0;
+}
+EXPORT_SYMBOL_GPL(nfcst_recv_frame);
+
+int nfcst_recv_fr_len(void *context, const u8 *hdr, int count)
+{
+	/* if echo response, nothing to read after */
+	if (hdr[0] == ECHORESPONSE)
+		return 1;
+
+	if (hdr[0] & 0x60)
+		return (((hdr[0] & 0x60) >> 5) << 8) | hdr[1];
+	else
+		return hdr[1];
+}
+EXPORT_SYMBOL_GPL(nfcst_recv_fr_len);
+
+int nfcst_recv_hdr_len(void *context, const u8 *data, int count)
+{
+	if (data[0] == ECHORESPONSE)
+		return 0;
+
+	/* check if invalid frame is received */
+	if (data[0] && ((data[0] & VALID_RESP_MASK) != VALID_RESP_VALUE))
+		return -EIO;
+
+	return DEVICE_HEADROOM_LEN;
+}
+EXPORT_SYMBOL_GPL(nfcst_recv_hdr_len);
+
+int nfcst_recv_max_fr_sz(void *context)
+{
+	return MAX_RESPONSE_BUFFER_SIZE;
+}
+EXPORT_SYMBOL_GPL(nfcst_recv_max_fr_sz);
+
+struct nfcst_pltf_data *nfcst_pltf_data(void *context)
+{
+	struct nfcst_context *ctx = (struct nfcst_context *)context;
+
+	return &ctx->cfg;
+}
+EXPORT_SYMBOL_GPL(nfcst_pltf_data);
+
+MODULE_AUTHOR("Shikha Singh <shikha.singh@st.com>");
+MODULE_AUTHOR("Sudeep Biswas <sudeep.biswas@st.com>");
+MODULE_DESCRIPTION("ST NFC Transceiver device driver core");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/nfc/nfcst/stnfcdev.h b/drivers/nfc/nfcst/stnfcdev.h
new file mode 100644
index 0000000..245069d
--- /dev/null
+++ b/drivers/nfc/nfcst/stnfcdev.h
@@ -0,0 +1,70 @@
+/*
+ * --------------------------------------------------------------------
+ * API defination provided by ST NFC Transceiver core framework
+ * --------------------------------------------------------------------
+ * Copyright (C) 2015 STMicroelectronics Pvt. Ltd. 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 _STNFCDEV_H_
+#define _STNFCDEV_H_
+
+#include <linux/regulator/consumer.h>
+
+/* phy type */
+enum nfcst_phy {
+	PHY_SPI = 0,
+	PHY_UART,
+};
+
+/* nfcst platform data */
+struct nfcst_pltf_data {
+	/* UART specific */
+	unsigned int baudrate;
+
+	/* SPI specific */
+	unsigned int enable_gpio;
+
+	/*
+	 * Generic stuff that can be required for any interface
+	 * such as regulator (device can receive power from a
+	 * regulator which needs to be enabled in the device
+	 * wake-up. Also it can help power mgmt., for example
+	 * switching off the regulator when the device is
+	 * disabled (off) and then switching it on when the
+	 * device is again enabled (on))
+	 */
+	struct regulator *nfcst_supply;
+};
+
+/* interface ops */
+struct nfcst_if_ops {
+	int (*phy_send)(void *phy_ctx, struct sk_buff *skb);
+};
+
+/* helper functions, can be called by interface layer */
+void *nfcst_register_phy(enum nfcst_phy phy,
+			 void *phy_ctx,
+			   struct nfcst_if_ops *ops,
+			   struct device *dev,
+			   struct nfcst_pltf_data *pdata);
+
+void nfcst_unregister_phy(void *context);
+int nfcst_recv_frame(void *context, struct sk_buff *skb_res);
+int nfcst_recv_fr_len(void *context, const u8 *data, int count);
+int nfcst_recv_hdr_len(void *context, const u8 *data, int count);
+int nfcst_recv_max_fr_sz(void *context);
+struct nfcst_pltf_data *nfcst_pltf_data(void *context);
+
+#endif
-- 
1.8.2.1

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

* [[linux-nfc][PATCH v1] 3/6] NFC: nfcst: Add UART LDisc Driver
  2017-05-02  6:03 [[linux-nfc][PATCH v1] 0/6] Support of ST NFC Transceiver Shikha Singh
  2017-05-02  6:03 ` [[linux-nfc][PATCH v1] 1/6] NFC: add generic UART support Shikha Singh
  2017-05-02  6:03 ` [[linux-nfc][PATCH v1] 2/6] NFC: nfcst: Add ST NFC Transceiver core framework Shikha Singh
@ 2017-05-02  6:03 ` Shikha Singh
  2017-05-02  6:03 ` [[linux-nfc][PATCH v1] 4/6] NFC: nfcst: Add ST NFC SPI Driver Shikha Singh
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 11+ messages in thread
From: Shikha Singh @ 2017-05-02  6:03 UTC (permalink / raw)
  To: sameo, linux-wireless, linux-nfc
  Cc: raunaque.quaiser, manoj.kumar, sylvain.fidelis, raphael.collado,
	shikha.singh, MMS_MMY_Applications_SW

Add support of ST NFC transceiver controlled over UART.

This driver registers with the digital LDisc UART
framework as an UART LDisc driver, and as a phy driver
with the ST NFC transceiver core framework.

Signed-off-by: Shikha Singh <shikha.singh@st.com>
---
 drivers/nfc/nfcst/Kconfig  |  17 +++++
 drivers/nfc/nfcst/Makefile |   3 +
 drivers/nfc/nfcst/uart.c   | 164 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 184 insertions(+)
 create mode 100644 drivers/nfc/nfcst/uart.c

diff --git a/drivers/nfc/nfcst/Kconfig b/drivers/nfc/nfcst/Kconfig
index 2c71aa2..70fec4f 100644
--- a/drivers/nfc/nfcst/Kconfig
+++ b/drivers/nfc/nfcst/Kconfig
@@ -15,3 +15,20 @@ config NFC_ST
 
 	  Say Y here to compile support for ST NFC transceiver core
 	  framework into the kernel or say M to compile it as module.
+
+config NFC_ST_UART
+       tristate "ST NFC-over-UART driver"
+       depends on NFC_DIGITAL && NFC_DIGITAL_UART
+       select NFC_ST
+       help
+         ST NFC-over-UART driver.
+
+         This driver is an UART LDisc driver that helps
+         ST NFC transceiver core framework communicate with
+         the transceiver device over the UART interface.
+         The driver registers as a phy driver with the core,
+         and as an LDisc driver with the digital UART LDisc
+         framework.
+
+         Say Y here to compile support for ST NFC-over-UART driver
+         into the kernel or say M to compile it as module.
diff --git a/drivers/nfc/nfcst/Makefile b/drivers/nfc/nfcst/Makefile
index d46acc5..a90055a 100644
--- a/drivers/nfc/nfcst/Makefile
+++ b/drivers/nfc/nfcst/Makefile
@@ -4,3 +4,6 @@
 
 nfcst-y += core.o
 obj-$(CONFIG_NFC_ST) += nfcst.o
+
+nfcst_uart-y += uart.o
+obj-$(CONFIG_NFC_ST_UART) += nfcst_uart.o
diff --git a/drivers/nfc/nfcst/uart.c b/drivers/nfc/nfcst/uart.c
new file mode 100644
index 0000000..953281d
--- /dev/null
+++ b/drivers/nfc/nfcst/uart.c
@@ -0,0 +1,164 @@
+/*
+ * --------------------------------------------------------------------
+ * LDisc UART Driver for ST NFC Transceiver
+ * --------------------------------------------------------------------
+ * Copyright (C) 2016 STMicroelectronics Pvt. Ltd. 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/of.h>
+#include <net/nfc/digital_uart.h>
+#include "stnfcdev.h"
+
+#define DEVICE_DEFAULT_BAUD 57600
+
+static unsigned int baud = DEVICE_DEFAULT_BAUD;
+
+static int nfcst_uart_digital_send(void *phy_ctx, struct sk_buff *skb)
+{
+	struct digital_uart *du = (struct digital_uart *)phy_ctx;
+
+	return du->ops.send(du, skb);
+}
+
+static struct nfcst_if_ops uart_ops = {
+	.phy_send = nfcst_uart_digital_send,
+};
+
+static int nfcst_uart_parse_dt(struct device_node *node,
+			       struct nfcst_pltf_data *pdata)
+{
+	struct device_node *matched_node;
+	const void *ptr;
+
+	matched_node = of_find_compatible_node(node, NULL, "st,nfc-uart");
+	if (!matched_node)
+		return -ENODEV;
+
+	ptr = of_get_property(matched_node, "st,baudrate", NULL);
+	if (!ptr)
+		return -ENODEV;
+
+	pdata->baudrate = be32_to_cpup(ptr);
+
+	return 0;
+}
+
+/*
+ * DIGITAL UART OPS
+ */
+static int nfcst_digital_uart_open(struct digital_uart *du)
+{
+	void *priv;
+	int err;
+	struct nfcst_pltf_data config;
+	struct nfcst_pltf_data *pdata = NULL;
+
+	if (du->tty->dev->parent && du->tty->dev->parent->of_node) {
+		err = nfcst_uart_parse_dt(du->tty->dev->parent->of_node,
+					  &config);
+		if (err)
+			dev_err(du->tty->dev, "No st nfc uart platform data found in DT\n");
+		else
+			pdata = &config;
+	}
+
+	if (!pdata) {
+		dev_info(du->tty->dev, "No platform data / DT -> fallback to module params\n");
+		config.baudrate = baud;
+		pdata = &config;
+	}
+	priv = nfcst_register_phy(PHY_UART, (void *)du, &uart_ops,
+				  du->tty->dev, pdata);
+	if (IS_ERR(priv))
+		return PTR_ERR(priv);
+
+	du->drv_data = priv;
+
+	/* set the default configuration */
+	digital_uart_set_config(du,
+				DEVICE_DEFAULT_BAUD,
+				0,
+				DIGITAL_UART_STOP_BIT_2);
+
+	return 0;
+}
+
+static void nfcst_digital_uart_close(struct digital_uart *du)
+{
+	nfcst_unregister_phy(du->drv_data);
+}
+
+static int nfcst_digital_uart_recv(struct digital_uart *du, struct sk_buff *skb)
+{
+	return nfcst_recv_frame(du->drv_data, skb);
+}
+
+static int nfcst_digital_uart_recv_hdr_len(struct digital_uart *du,
+					   const u8 *data,
+					   int count)
+{
+	return nfcst_recv_hdr_len(du->drv_data, data, count);
+}
+
+static int nfcst_digital_uart_fr_len(struct digital_uart *du,
+				     const u8 *data,
+				     int count)
+{
+	return nfcst_recv_fr_len(du->drv_data, data, count);
+}
+
+static int nfcst_digital_uart_max_fr_sz(struct digital_uart *du)
+{
+	return nfcst_recv_max_fr_sz(du->drv_data);
+}
+
+static struct digital_uart nfcst_uart = {
+	.owner  = THIS_MODULE,
+	.name   = "nfcst_uart",
+	.driver = DIGITAL_UART_DRIVER_ST,
+	.ops	= {
+		.open		= nfcst_digital_uart_open,
+		.close		= nfcst_digital_uart_close,
+		.recv		= nfcst_digital_uart_recv,
+		.recv_fr_hdr_sz	= nfcst_digital_uart_recv_hdr_len,
+		.recv_pl_sz	= nfcst_digital_uart_fr_len,
+		.recv_fr_max_sz	= nfcst_digital_uart_max_fr_sz,
+	}
+};
+
+/*
+ * Module init
+ */
+static int nfcst_uart_init_module(void)
+{
+	return digital_uart_register(&nfcst_uart);
+}
+
+static void nfcst_uart_exit_module(void)
+{
+	digital_uart_unregister(&nfcst_uart);
+}
+
+module_init(nfcst_uart_init_module);
+module_exit(nfcst_uart_exit_module);
+
+MODULE_AUTHOR("Sudeep Biswas <sudeep.biswas@st.com>");
+MODULE_AUTHOR("Shikha Singh <shikha.singh@st.com>");
+MODULE_DESCRIPTION("ST NFC-over-UART");
+MODULE_LICENSE("GPL v2");
+
+module_param(baud, uint, 0000);
+MODULE_PARM_DESC(baud, "Tell the UART baudrate for communication");
-- 
1.8.2.1

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

* [[linux-nfc][PATCH v1] 4/6] NFC: nfcst: Add ST NFC SPI Driver
  2017-05-02  6:03 [[linux-nfc][PATCH v1] 0/6] Support of ST NFC Transceiver Shikha Singh
                   ` (2 preceding siblings ...)
  2017-05-02  6:03 ` [[linux-nfc][PATCH v1] 3/6] NFC: nfcst: Add UART LDisc Driver Shikha Singh
@ 2017-05-02  6:03 ` Shikha Singh
  2017-05-02  6:03 ` [[linux-nfc][PATCH v1] 5/6] DT: bindings: net: nfc: stnfc binding doc Shikha Singh
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 11+ messages in thread
From: Shikha Singh @ 2017-05-02  6:03 UTC (permalink / raw)
  To: sameo, linux-wireless, linux-nfc
  Cc: raunaque.quaiser, manoj.kumar, sylvain.fidelis, raphael.collado,
	shikha.singh, MMS_MMY_Applications_SW

Add support of ST NFC transceiver controlled over SPI.

This driver enables ST NFC transceiver to communicate
with host over SPI interface and as a phy driver it
registers with ST NFC transceiver core framework.

Signed-off-by: Shikha Singh <shikha.singh@st.com>
---
 drivers/nfc/nfcst/Kconfig  |  15 ++
 drivers/nfc/nfcst/Makefile |   3 +
 drivers/nfc/nfcst/spi.c    | 493 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 511 insertions(+)
 create mode 100644 drivers/nfc/nfcst/spi.c

diff --git a/drivers/nfc/nfcst/Kconfig b/drivers/nfc/nfcst/Kconfig
index 70fec4f..73549cd 100644
--- a/drivers/nfc/nfcst/Kconfig
+++ b/drivers/nfc/nfcst/Kconfig
@@ -32,3 +32,18 @@ config NFC_ST_UART
 
          Say Y here to compile support for ST NFC-over-UART driver
          into the kernel or say M to compile it as module.
+
+config NFC_ST_SPI
+       tristate "ST NFC-over-SPI driver"
+       depends on SPI && NFC_DIGITAL
+       select NFC_ST
+       help
+         ST NFC-over-SPI driver.
+
+         This SPI slave driver is an ST NFC transceiver driver that
+         communicates with host processor over SPI interface.
+
+         Say Y here to compile support for ST NFC-over-SPI driver
+         into the kernel or say M to compile it as module.
+
+
diff --git a/drivers/nfc/nfcst/Makefile b/drivers/nfc/nfcst/Makefile
index a90055a..adefcec 100644
--- a/drivers/nfc/nfcst/Makefile
+++ b/drivers/nfc/nfcst/Makefile
@@ -7,3 +7,6 @@ obj-$(CONFIG_NFC_ST) += nfcst.o
 
 nfcst_uart-y += uart.o
 obj-$(CONFIG_NFC_ST_UART) += nfcst_uart.o
+
+nfcst_spi-y += spi.o
+obj-$(CONFIG_NFC_ST_SPI) += nfcst_spi.o
diff --git a/drivers/nfc/nfcst/spi.c b/drivers/nfc/nfcst/spi.c
new file mode 100644
index 0000000..68317db
--- /dev/null
+++ b/drivers/nfc/nfcst/spi.c
@@ -0,0 +1,493 @@
+/*
+ * --------------------------------------------------------------------
+ * SPI Driver for ST NFC Transceiver
+ * --------------------------------------------------------------------
+ * Copyright (C) 2016 STMicroelectronics Pvt. Ltd. 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/of.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/of_gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/netdevice.h>
+#include <linux/module.h>
+#include <net/nfc/nfc.h>
+#include "stnfcdev.h"
+
+#define HIGH	1
+#define LOW	0
+
+#define NFCST_SPI_SEND_CTRLBYTE	0x0
+#define NFCST_SPI_RESET_CMD	0x1
+#define NFCST_SPI_RECV_CTRLBYTE	0x2
+
+#define NFCST_RESET_CMD_LEN	0x1
+
+/*
+ * structure to contain ST NFC spi communication specific information.
+ * @spidev: ST NFC spi device object.
+ * @spi_lock: mutex to allow only one spi transfer at a time.
+ * @nfc_ctx: nfcst core context.
+ * @nfcdev_free: flag to check if driver remove is called.
+ * @rm_lock: mutex for ensuring safe access of nfc digital object
+ *	from threaded ISR. Usage of this mutex avoids any race between
+ *	deletion of the object from nfcst_spi_remove() and its access from
+ *	the threaded ISR.
+ * @nfcdev_free: flag to have the state of nfc device object.
+ *	[alive | died]
+
+ */
+struct nfcst_spi_context {
+	struct spi_device *spidev;
+	struct mutex spi_lock;
+	void *nfc_ctx;
+	struct mutex rm_lock;
+	bool nfcdev_free;
+};
+
+/* Function to send user provided buffer to NFC transceiver through SPI */
+static int nfcst_spi_send(void *phy_ctx, struct sk_buff *skb)
+{
+	int result = 0;
+	struct spi_message m;
+
+	struct nfcst_spi_context *spictx = (struct nfcst_spi_context *)phy_ctx;
+	unsigned char ctrl_byte = NFCST_SPI_SEND_CTRLBYTE;
+	struct spi_device *spidev = spictx->spidev;
+	struct spi_transfer tx_spictrl;
+	struct spi_transfer tx_buffer;
+
+	memset(&tx_spictrl, 0x0, sizeof(struct spi_transfer));
+	memset(&tx_buffer, 0x0, sizeof(struct spi_transfer));
+
+	tx_spictrl.len = 1;
+	tx_spictrl.tx_buf = &ctrl_byte;
+	tx_spictrl.cs_change = 1;
+
+	tx_buffer.len = skb->len;
+	tx_buffer.tx_buf = skb->data;
+
+	spi_message_init(&m);
+	spi_message_add_tail(&tx_spictrl, &m);
+
+	mutex_lock(&spictx->spi_lock);
+	result = spi_sync(spidev, &m);
+	if (result) {
+		dev_err(&spidev->dev, "spi_send ctrl err = %d\n", result);
+		goto end;
+	}
+
+	spi_message_init(&m);
+	spi_message_add_tail(&tx_buffer, &m);
+	result = spi_sync(spidev, &m);
+	if (result)
+		dev_err(&spidev->dev, "SPI sending data err = %d\n", result);
+
+end:
+	mutex_unlock(&spictx->spi_lock);
+	kfree_skb(skb);
+	return result;
+}
+
+static int nfcst_spi_reset_send(struct nfcst_spi_context *spictx)
+{
+	int result = 0;
+	struct spi_message m;
+	struct spi_device *spidev = spictx->spidev;
+	unsigned char reset_cmd = NFCST_SPI_RESET_CMD;
+	struct spi_transfer reset_transfer;
+
+	memset(&reset_transfer, 0x0, sizeof(struct spi_transfer));
+	reset_transfer.tx_buf = &reset_cmd;
+	reset_transfer.len = NFCST_RESET_CMD_LEN;
+
+	spi_message_init(&m);
+	spi_message_add_tail(&reset_transfer, &m);
+
+	mutex_lock(&spictx->spi_lock);
+	result = spi_sync(spidev, &m);
+	if (result)
+		dev_err(&spidev->dev,
+			"error: spi reset send error = 0x%x\n", result);
+
+	mutex_unlock(&spictx->spi_lock);
+	return result;
+}
+
+/* Function to Receive Response from taransceiver
+ * On success, this function will return length of data read.
+ * In case of error it returns -EIO.
+ */
+static int nfcst_spi_recv_resp(void *phy_ctx,
+			       struct sk_buff *receivebuff)
+{
+	int ret = 0;
+	int header_len;
+	int payload_len;
+	int already_read = 0;
+	int total_expected_len = 0;
+	struct spi_transfer tx_takedata;
+	struct spi_transfer tx_takehdr;
+	struct spi_transfer tx_dummy;
+	struct spi_message m;
+	unsigned char readdata_cmd = NFCST_SPI_RECV_CTRLBYTE;
+	struct nfcst_spi_context *spictx = (struct nfcst_spi_context *)phy_ctx;
+	struct spi_device *spidev = spictx->spidev;
+	struct spi_transfer t[2];
+
+	memset(&tx_takedata, 0x0, sizeof(struct spi_transfer));
+	memset(&tx_takehdr, 0x0, sizeof(struct spi_transfer));
+	memset(&tx_dummy, 0x0, sizeof(struct spi_transfer));
+	memset(&t[0], 0x0, sizeof(struct spi_transfer));
+	memset(&t[1], 0x0, sizeof(struct spi_transfer));
+
+	t[0].tx_buf = &readdata_cmd;
+	t[0].len = 1;
+	t[1].rx_buf = receivebuff->data;
+	t[1].len = 1;
+	t[1].cs_change = 1;
+
+	/* First spi transfer to receive first byte */
+	spi_message_init(&m);
+	spi_message_add_tail(&t[0], &m);
+	spi_message_add_tail(&t[1], &m);
+
+	mutex_lock(&spictx->spi_lock);
+	ret = spi_sync(spidev, &m);
+	if (ret) {
+		dev_err(&spidev->dev, "spi_recv_resp, spi recv err = %d\n",
+			ret);
+		goto end;
+	}
+	already_read = 1;
+
+	/* Determine the header length with help of first byte */
+	header_len = nfcst_recv_hdr_len(spictx, receivebuff->data,
+					already_read);
+	if (header_len < 0) {
+		dev_err(&spidev->dev, "spi_recv_resp, invalid recv frame\n");
+		goto end;
+	}
+	/* Read header */
+	if (header_len > already_read) {
+		tx_takehdr.rx_buf = &receivebuff->data[already_read];
+		tx_takehdr.len = header_len - already_read;
+		tx_takehdr.cs_change = 1;
+		spi_message_init(&m);
+		spi_message_add_tail(&tx_takehdr, &m);
+		ret = spi_sync(spidev, &m);
+		if (ret) {
+			dev_err(&spidev->dev,
+				"spi_recv_resp, header read error = %d\n", ret);
+			goto end;
+		}
+		already_read = header_len;
+	}
+
+	payload_len = nfcst_recv_fr_len(spictx, receivebuff->data,
+					already_read);
+	total_expected_len = header_len + payload_len;
+	if (already_read == total_expected_len) {
+		/* transfer for cs_change */
+		spi_message_init(&m);
+		spi_message_add_tail(&tx_dummy, &m);
+		ret = spi_sync(spidev, &m);
+		if (ret) {
+			dev_err(&spidev->dev, "spi dummy transfer error\n");
+			goto end;
+		}
+	}
+
+	/* Now make transfer to read complete data */
+	if (total_expected_len > already_read) {
+		tx_takedata.rx_buf = &receivebuff->data[already_read];
+		tx_takedata.len = payload_len;
+		spi_message_init(&m);
+		spi_message_add_tail(&tx_takedata, &m);
+		ret = spi_sync(spidev, &m);
+		if (ret) {
+			dev_err(&spidev->dev, "spi_recv_resp, data read error = %d\n",
+				ret);
+			goto end;
+		}
+		already_read = total_expected_len;
+	}
+
+	skb_put(receivebuff, already_read);
+	mutex_unlock(&spictx->spi_lock);
+
+	return already_read;
+
+end:
+	mutex_unlock(&spictx->spi_lock);
+	return -EIO;
+}
+
+static irqreturn_t nfcst_spi_irq_thread_handler(int irq, void *phyctx)
+{
+	int result = 0;
+	int max_frame_sz;
+	struct sk_buff *skb_resp;
+	struct nfcst_spi_context *spictx = (struct nfcst_spi_context *)phyctx;
+
+	mutex_lock(&spictx->rm_lock);
+	if (spictx->nfcdev_free) {
+		dev_err(&spictx->spidev->dev,
+			"nfcst_spi_remove is already called\n");
+		mutex_unlock(&spictx->rm_lock);
+		return IRQ_HANDLED;
+	}
+
+	max_frame_sz = nfcst_recv_max_fr_sz(spictx->nfc_ctx);
+	skb_resp = nfc_alloc_recv_skb(max_frame_sz, GFP_KERNEL);
+	if (skb_resp) {
+		result = nfcst_spi_recv_resp(spictx, skb_resp);
+		if (result < 0)
+			kfree_skb(skb_resp);
+	} else {
+		result = -ENOMEM;
+	}
+	if (result < 0)
+		skb_resp = ERR_PTR(result);
+
+	/* nfcst_recv_frame will never return error */
+	nfcst_recv_frame(spictx->nfc_ctx, skb_resp);
+	mutex_unlock(&spictx->rm_lock);
+	return IRQ_HANDLED;
+}
+
+static struct nfcst_if_ops spi_ops = {
+	.phy_send = nfcst_spi_send,
+};
+
+static int nfcst_spi_parse_dt(struct spi_device *nfc_spi_dev,
+			      struct nfcst_pltf_data *pdata)
+{
+	int ret = 0;
+
+	if (device_property_present(&nfc_spi_dev->dev, "nfcstvin")) {
+		pdata->nfcst_supply =
+			devm_regulator_get(&nfc_spi_dev->dev,
+					   "nfcstvin");
+		if (IS_ERR(pdata->nfcst_supply)) {
+			dev_err(&nfc_spi_dev->dev, "failed to acquire regulator\n");
+			return PTR_ERR(pdata->nfcst_supply);
+		}
+
+		ret = regulator_enable(pdata->nfcst_supply);
+		if (ret) {
+			dev_err(&nfc_spi_dev->dev, "failed to enable regulator\n");
+			return ret;
+		}
+	}
+
+	pdata->enable_gpio =
+		of_get_named_gpio(nfc_spi_dev->dev.of_node,
+				  "enable-gpio",
+				  0);
+	if (!gpio_is_valid(pdata->enable_gpio)) {
+		dev_err(&nfc_spi_dev->dev, "No valid enable gpio\n");
+		ret = pdata->enable_gpio;
+		goto err_disable_regulator;
+	}
+
+	ret = devm_gpio_request_one(&nfc_spi_dev->dev, pdata->enable_gpio,
+				    GPIOF_DIR_OUT | GPIOF_INIT_HIGH,
+				    "enable_gpio");
+	if (ret)
+		goto err_disable_regulator;
+
+	return 0;
+
+err_disable_regulator:
+	if (pdata->nfcst_supply)
+		regulator_disable(pdata->nfcst_supply);
+	return ret;
+}
+
+static void nfcst_spi_enable_negativepulse(struct nfcst_spi_context *spictx)
+{
+	struct nfcst_pltf_data *pdata;
+
+	pdata = nfcst_pltf_data(spictx->nfc_ctx);
+
+	/* First make irq_in pin high */
+	gpio_set_value(pdata->enable_gpio, HIGH);
+
+	/* wait for 1 milisecond */
+	usleep_range(1000, 2000);
+
+	/* Make irq_in pin low */
+	gpio_set_value(pdata->enable_gpio, LOW);
+
+	/* wait for minimum interrupt pulse to make ST transceiver active */
+	usleep_range(1000, 2000);
+
+	/* At end make it high */
+	gpio_set_value(pdata->enable_gpio, HIGH);
+}
+
+/*
+ * Send a reset sequence over SPI bus (Reset command + wait 3ms +
+ * negative pulse on Transceiver's gpio)
+ */
+static int nfcst_spi_reset_sequence(struct nfcst_spi_context *spictx)
+{
+	int result = 0;
+
+	result = nfcst_spi_reset_send(spictx);
+	if (result) {
+		dev_err(&spictx->spidev->dev,
+			"spi reset sequence error\n");
+		return result;
+	}
+	/* wait for 3 milisecond to complete the controller reset process */
+	usleep_range(3000, 4000);
+
+	/* send negative pulse to make ST NFC transceiver active */
+	nfcst_spi_enable_negativepulse(spictx);
+
+	/* wait for 10 milisecond : HFO setup time */
+	usleep_range(10000, 20000);
+
+	return result;
+}
+
+static const struct spi_device_id nfc_st_spi_id[] = {
+	{ "stnfc", 0 },
+	{}
+};
+MODULE_DEVICE_TABLE(spi, nfc_st_spi_id);
+
+static int nfcst_spi_probe(struct spi_device *nfc_spi_dev)
+{
+	int ret;
+	void *priv;
+	struct nfcst_spi_context *spictx;
+	struct nfcst_pltf_data config;
+	struct nfcst_pltf_data *pdata = NULL;
+
+	nfc_info(&nfc_spi_dev->dev, "nfc_st_spi driver probe called\n");
+
+	spictx = devm_kzalloc(&nfc_spi_dev->dev,
+			      sizeof(struct nfcst_spi_context),
+			      GFP_KERNEL);
+	if (!spictx)
+		ret = -ENOMEM;
+
+	spictx->spidev = nfc_spi_dev;
+	mutex_init(&spictx->spi_lock);
+	mutex_init(&spictx->rm_lock);
+
+	dev_set_drvdata(&nfc_spi_dev->dev, spictx);
+
+	ret = nfcst_spi_parse_dt(nfc_spi_dev, &config);
+	if (ret) {
+		dev_err(&nfc_spi_dev->dev, "Error in getting st nfc spi platform data from DT\n");
+		return ret;
+	}
+	pdata = &config;
+
+	priv = nfcst_register_phy(PHY_SPI, (void *)spictx, &spi_ops,
+				  &nfc_spi_dev->dev, pdata);
+	if (IS_ERR(priv)) {
+		ret = PTR_ERR(priv);
+		goto error;
+	}
+	spictx->nfc_ctx = priv;
+
+	if (nfc_spi_dev->irq > 0) {
+		if (devm_request_threaded_irq(&nfc_spi_dev->dev,
+					      nfc_spi_dev->irq,
+					      NULL,
+					      nfcst_spi_irq_thread_handler,
+					      IRQF_TRIGGER_FALLING |
+					      IRQF_ONESHOT,
+					      "nfcst",
+					      (void *)spictx) < 0) {
+			dev_err(&nfc_spi_dev->dev, "err: irq request for nfc_st_spi is failed\n");
+			ret =  -EINVAL;
+			goto error;
+		}
+	} else {
+		dev_err(&nfc_spi_dev->dev, "not a valid IRQ associated with ST NFC\n");
+		ret = -EINVAL;
+		goto error;
+	}
+
+	/* Enable transceiver and do SPI reset to initialize HW */
+	nfcst_spi_enable_negativepulse(spictx);
+	usleep_range(5000, 6000);
+	ret = nfcst_spi_reset_sequence(spictx);
+	usleep_range(50000, 51000);
+	if (ret)
+		goto error;
+
+	return 0;
+error:
+	if (pdata->nfcst_supply)
+		regulator_disable(pdata->nfcst_supply);
+	return ret;
+}
+
+static int nfcst_spi_remove(struct spi_device *nfc_spi_dev)
+{
+	int result = 0;
+	struct nfcst_spi_context *spictx = dev_get_drvdata(&nfc_spi_dev->dev);
+	struct nfcst_pltf_data *pdata;
+
+	mutex_lock(&spictx->rm_lock);
+	nfcst_unregister_phy(spictx->nfc_ctx);
+	spictx->nfcdev_free = true;
+	mutex_unlock(&spictx->rm_lock);
+
+	/* wait for completion of currently running interrupt handler
+	 * and disable upcoming interrupts
+	 */
+	disable_irq(nfc_spi_dev->irq);
+
+	/* Reset the ST NFC controller */
+	result = nfcst_spi_reset_send(spictx);
+	if (result) {
+		dev_err(&spictx->spidev->dev,
+			"stnfc reset failed from remove() err = %d\n", result);
+		return result;
+	}
+
+	/* disable regulator */
+	pdata = nfcst_pltf_data(spictx->nfc_ctx);
+	if (pdata->nfcst_supply)
+		regulator_disable(spictx->nfc_ctx);
+	return result;
+}
+
+/* Register as SPI protocol driver */
+static struct spi_driver stnfc_spi_driver = {
+	.driver = {
+		.name = "stnfc",
+		.owner = THIS_MODULE,
+	},
+	.id_table = nfc_st_spi_id,
+	.probe = nfcst_spi_probe,
+	.remove = nfcst_spi_remove,
+};
+
+module_spi_driver(stnfc_spi_driver);
+
+MODULE_AUTHOR("Shikha Singh <shikha.singh@st.com>");
+MODULE_DESCRIPTION("ST NFC-over-SPI");
+MODULE_LICENSE("GPL v2");
-- 
1.8.2.1

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

* [[linux-nfc][PATCH v1] 5/6] DT: bindings: net: nfc: stnfc binding doc
  2017-05-02  6:03 [[linux-nfc][PATCH v1] 0/6] Support of ST NFC Transceiver Shikha Singh
                   ` (3 preceding siblings ...)
  2017-05-02  6:03 ` [[linux-nfc][PATCH v1] 4/6] NFC: nfcst: Add ST NFC SPI Driver Shikha Singh
@ 2017-05-02  6:03 ` Shikha Singh
  2017-05-02  6:03 ` [[linux-nfc][PATCH v1] 6/6] DRIVERS: NFC: Remove st95hf name reference Shikha Singh
  2017-05-02  6:58 ` [linux-nfc] [[PATCH v1] 0/6] Support of ST NFC Transceiver Marcel Holtmann
  6 siblings, 0 replies; 11+ messages in thread
From: Shikha Singh @ 2017-05-02  6:03 UTC (permalink / raw)
  To: sameo, linux-wireless, linux-nfc
  Cc: raunaque.quaiser, manoj.kumar, sylvain.fidelis, raphael.collado,
	shikha.singh, MMS_MMY_Applications_SW

This patch adds ST NFC binding doc that guides
how to make SPI slave node entry of ST NFC transceiver
in DT file of any platform.

Signed-off-by: Shikha Singh <shikha.singh@st.com>
---
 .../devicetree/bindings/net/nfc/stnfc.txt          | 50 ++++++++++++++++++++++
 1 file changed, 50 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/nfc/stnfc.txt

diff --git a/Documentation/devicetree/bindings/net/nfc/stnfc.txt b/Documentation/devicetree/bindings/net/nfc/stnfc.txt
new file mode 100644
index 0000000..b050b3e
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/nfc/stnfc.txt
@@ -0,0 +1,50 @@
+* STMicroelectronics : NFC Transceiver
+
+ST NFC Transceiver can be attached with SPI bus.
+ST NFC node should be defined in DT as SPI slave device of SPI
+master with which  transceiver is physically connected.
+The properties defined below are required to be the part of DT
+to include ST NFC transceiver over SPI into the platform.
+
+Required properties:
+===================
+- reg: Address of SPI slave "ST NFC transceiver" on SPI master bus.
+
+- compatible: should be "st,stnfc" for ST NFC transceiver
+
+- spi-max-frequency: Max. operating SPI frequency for ST NFC
+	transceiver.
+
+- enable-gpio: GPIO line to enable ST NFC transceiver.
+
+- interrupt-parent : Standard way to specify the controller to which
+	transceiver's interrupt is routed.
+
+- interrupts : Standard way to define ST NFC transceiver's out
+	interrupt.
+
+Optional property:
+=================
+- nfcstvin : This is an optional property. It contains a
+	phandle to ST NFC transceiver's regulator supply node in DT.
+
+Example:
+=======
+spi@9840000 {
+	reg = <0x9840000 0x110>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+	cs-gpios = <&pio0 4>;
+	status = "okay";
+
+	stnfc@0{
+		reg = <0>;
+		compatible = "st,stnfc";
+		status = "okay";
+		spi-max-frequency = <1000000>;
+		enable-gpio = <&pio4 0>;
+		interrupt-parent = <&pio0>;
+		interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
+	};
+
+};
-- 
1.8.2.1

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

* [[linux-nfc][PATCH v1] 6/6] DRIVERS: NFC: Remove st95hf name reference
  2017-05-02  6:03 [[linux-nfc][PATCH v1] 0/6] Support of ST NFC Transceiver Shikha Singh
                   ` (4 preceding siblings ...)
  2017-05-02  6:03 ` [[linux-nfc][PATCH v1] 5/6] DT: bindings: net: nfc: stnfc binding doc Shikha Singh
@ 2017-05-02  6:03 ` Shikha Singh
  2017-05-02  6:58 ` [linux-nfc] [[PATCH v1] 0/6] Support of ST NFC Transceiver Marcel Holtmann
  6 siblings, 0 replies; 11+ messages in thread
From: Shikha Singh @ 2017-05-02  6:03 UTC (permalink / raw)
  To: sameo, linux-wireless, linux-nfc
  Cc: raunaque.quaiser, manoj.kumar, sylvain.fidelis, raphael.collado,
	shikha.singh, MMS_MMY_Applications_SW

This patch removes all references to old st95hf driver.

A new ST NFC driver is added under drivers/nfc/nfcst.
The new driver design is based on modular
approach to have ST NFC core framework which is
independent of PHY and Two ST NFC PHY drivers to support
SPI and UART interfaces.

Signed-off-by: Shikha Singh <shikha.singh@st.com>
---
 .../devicetree/bindings/net/nfc/st95hf.txt         |   50 -
 drivers/nfc/Kconfig                                |    1 -
 drivers/nfc/Makefile                               |    1 -
 drivers/nfc/st95hf/Kconfig                         |   10 -
 drivers/nfc/st95hf/Makefile                        |    6 -
 drivers/nfc/st95hf/core.c                          | 1273 --------------------
 drivers/nfc/st95hf/spi.c                           |  167 ---
 drivers/nfc/st95hf/spi.h                           |   64 -
 8 files changed, 1572 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/net/nfc/st95hf.txt
 delete mode 100644 drivers/nfc/st95hf/Kconfig
 delete mode 100644 drivers/nfc/st95hf/Makefile
 delete mode 100644 drivers/nfc/st95hf/core.c
 delete mode 100644 drivers/nfc/st95hf/spi.c
 delete mode 100644 drivers/nfc/st95hf/spi.h

diff --git a/Documentation/devicetree/bindings/net/nfc/st95hf.txt b/Documentation/devicetree/bindings/net/nfc/st95hf.txt
deleted file mode 100644
index ea3178b..0000000
--- a/Documentation/devicetree/bindings/net/nfc/st95hf.txt
+++ /dev/null
@@ -1,50 +0,0 @@
-* STMicroelectronics : NFC Transceiver ST95HF
-
-ST NFC Transceiver is required to attach with SPI bus.
-ST95HF node should be defined in DT as SPI slave device of SPI
-master with which ST95HF transceiver is physically connected.
-The properties defined below are required to be the part of DT
-to include ST95HF transceiver into the platform.
-
-Required properties:
-===================
-- reg: Address of SPI slave "ST95HF transceiver" on SPI master bus.
-
-- compatible: should be "st,st95hf" for ST95HF NFC transceiver
-
-- spi-max-frequency: Max. operating SPI frequency for ST95HF
-	transceiver.
-
-- enable-gpio: GPIO line to enable ST95HF transceiver.
-
-- interrupt-parent : Standard way to specify the controller to which
-	ST95HF transceiver's interrupt is routed.
-
-- interrupts : Standard way to define ST95HF transceiver's out
-	interrupt.
-
-Optional property:
-=================
-- st95hfvin-supply : This is an optional property. It contains a
-	phandle to ST95HF transceiver's regulator supply node in DT.
-
-Example:
-=======
-spi@9840000 {
-	reg = <0x9840000 0x110>;
-	#address-cells = <1>;
-	#size-cells = <0>;
-	cs-gpios = <&pio0 4>;
-	status = "okay";
-
-	st95hf@0{
-		reg = <0>;
-		compatible = "st,st95hf";
-		status = "okay";
-		spi-max-frequency = <1000000>;
-		enable-gpio = <&pio4 0>;
-		interrupt-parent = <&pio0>;
-		interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
-	};
-
-};
diff --git a/drivers/nfc/Kconfig b/drivers/nfc/Kconfig
index 3ac0aba..f4f0b66 100644
--- a/drivers/nfc/Kconfig
+++ b/drivers/nfc/Kconfig
@@ -57,6 +57,5 @@ source "drivers/nfc/st21nfca/Kconfig"
 source "drivers/nfc/st-nci/Kconfig"
 source "drivers/nfc/nxp-nci/Kconfig"
 source "drivers/nfc/s3fwrn5/Kconfig"
-source "drivers/nfc/st95hf/Kconfig"
 source "drivers/nfc/nfcst/Kconfig"
 endmenu
diff --git a/drivers/nfc/Makefile b/drivers/nfc/Makefile
index 9c1b127..be22efe 100644
--- a/drivers/nfc/Makefile
+++ b/drivers/nfc/Makefile
@@ -15,5 +15,4 @@ obj-$(CONFIG_NFC_ST21NFCA)  	+= st21nfca/
 obj-$(CONFIG_NFC_ST_NCI)	+= st-nci/
 obj-$(CONFIG_NFC_NXP_NCI)	+= nxp-nci/
 obj-$(CONFIG_NFC_S3FWRN5)	+= s3fwrn5/
-obj-$(CONFIG_NFC_ST95HF)	+= st95hf/
 obj-$(CONFIG_NFC_ST)		+= nfcst/
diff --git a/drivers/nfc/st95hf/Kconfig b/drivers/nfc/st95hf/Kconfig
deleted file mode 100644
index 224f266..0000000
--- a/drivers/nfc/st95hf/Kconfig
+++ /dev/null
@@ -1,10 +0,0 @@
-config NFC_ST95HF
-	tristate "ST95HF NFC Transceiver driver"
-	depends on SPI && NFC_DIGITAL
-	help
-	This enables the ST NFC driver for ST95HF NFC transceiver.
-	This makes use of SPI framework to communicate with transceiver
-	and registered with NFC digital core to support Linux NFC framework.
-
-	Say Y here to compile support for ST NFC transceiver ST95HF
-	linux driver into the kernel or say M to compile it as module.
diff --git a/drivers/nfc/st95hf/Makefile b/drivers/nfc/st95hf/Makefile
deleted file mode 100644
index 00760b3..0000000
--- a/drivers/nfc/st95hf/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# Makefile for STMicroelectronics NFC transceiver ST95HF
-#
-
-obj-$(CONFIG_NFC_ST95HF)	+= st95hf.o
-st95hf-objs			:= spi.o core.o
diff --git a/drivers/nfc/st95hf/core.c b/drivers/nfc/st95hf/core.c
deleted file mode 100644
index c2840e4..0000000
--- a/drivers/nfc/st95hf/core.c
+++ /dev/null
@@ -1,1273 +0,0 @@
-/*
- * --------------------------------------------------------------------
- * Driver for ST NFC Transceiver ST95HF
- * --------------------------------------------------------------------
- * Copyright (C) 2015 STMicroelectronics Pvt. Ltd. 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/err.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/nfc.h>
-#include <linux/of_gpio.h>
-#include <linux/of.h>
-#include <linux/of_irq.h>
-#include <linux/property.h>
-#include <linux/regulator/consumer.h>
-#include <linux/wait.h>
-#include <net/nfc/digital.h>
-#include <net/nfc/nfc.h>
-
-#include "spi.h"
-
-/* supported protocols */
-#define ST95HF_SUPPORTED_PROT		(NFC_PROTO_ISO14443_MASK | \
-					NFC_PROTO_ISO14443_B_MASK | \
-					NFC_PROTO_ISO15693_MASK)
-/* driver capabilities */
-#define ST95HF_CAPABILITIES		NFC_DIGITAL_DRV_CAPS_IN_CRC
-
-/* Command Send Interface */
-/* ST95HF_COMMAND_SEND CMD Ids */
-#define ECHO_CMD			0x55
-#define WRITE_REGISTER_CMD		0x9
-#define PROTOCOL_SELECT_CMD		0x2
-#define SEND_RECEIVE_CMD		0x4
-
-/* Select protocol codes */
-#define ISO15693_PROTOCOL_CODE		0x1
-#define ISO14443A_PROTOCOL_CODE		0x2
-#define ISO14443B_PROTOCOL_CODE		0x3
-
-/*
- * head room len is 3
- * 1 byte for control byte
- * 1 byte for cmd
- * 1 byte for size
- */
-#define ST95HF_HEADROOM_LEN		3
-
-/*
- * tailroom is 1 for ISO14443A
- * and 0 for ISO14443B/ISO15693,
- * hence the max value 1 should be
- * taken.
- */
-#define ST95HF_TAILROOM_LEN		1
-
-/* Command Response interface */
-#define MAX_RESPONSE_BUFFER_SIZE	280
-#define ECHORESPONSE			0x55
-#define ST95HF_ERR_MASK			0xF
-#define ST95HF_TIMEOUT_ERROR		0x87
-#define ST95HF_NFCA_CRC_ERR_MASK	0x20
-#define ST95HF_NFCB_CRC_ERR_MASK	0x01
-
-/* ST95HF transmission flag values */
-#define TRFLAG_NFCA_SHORT_FRAME		0x07
-#define TRFLAG_NFCA_STD_FRAME		0x08
-#define TRFLAG_NFCA_STD_FRAME_CRC	0x28
-
-/* Misc defs */
-#define HIGH				1
-#define LOW				0
-#define ISO14443A_RATS_REQ		0xE0
-#define RATS_TB1_PRESENT_MASK		0x20
-#define RATS_TA1_PRESENT_MASK		0x10
-#define TB1_FWI_MASK			0xF0
-#define WTX_REQ_FROM_TAG		0xF2
-
-#define MAX_CMD_LEN			0x7
-
-#define MAX_CMD_PARAMS			4
-struct cmd {
-	int cmd_len;
-	unsigned char cmd_id;
-	unsigned char no_cmd_params;
-	unsigned char cmd_params[MAX_CMD_PARAMS];
-	enum req_type req;
-};
-
-struct param_list {
-	int param_offset;
-	int new_param_val;
-};
-
-/*
- * List of top-level cmds to be used internally by the driver.
- * All these commands are build on top of ST95HF basic commands
- * such as SEND_RECEIVE_CMD, PROTOCOL_SELECT_CMD, etc.
- * These top level cmds are used internally while implementing various ops of
- * digital layer/driver probe or extending the digital framework layer for
- * features that are not yet implemented there, for example, WTX cmd handling.
- */
-enum st95hf_cmd_list {
-	CMD_ECHO,
-	CMD_ISO14443A_CONFIG,
-	CMD_ISO14443A_DEMOGAIN,
-	CMD_ISO14443B_DEMOGAIN,
-	CMD_ISO14443A_PROTOCOL_SELECT,
-	CMD_ISO14443B_PROTOCOL_SELECT,
-	CMD_WTX_RESPONSE,
-	CMD_FIELD_OFF,
-	CMD_ISO15693_PROTOCOL_SELECT,
-};
-
-static const struct cmd cmd_array[] = {
-	[CMD_ECHO] = {
-		.cmd_len = 0x2,
-		.cmd_id = ECHO_CMD,
-		.no_cmd_params = 0,
-		.req = SYNC,
-	},
-	[CMD_ISO14443A_CONFIG] = {
-		.cmd_len = 0x7,
-		.cmd_id = WRITE_REGISTER_CMD,
-		.no_cmd_params = 0x4,
-		.cmd_params = {0x3A, 0x00, 0x5A, 0x04},
-		.req = SYNC,
-	},
-	[CMD_ISO14443A_DEMOGAIN] = {
-		.cmd_len = 0x7,
-		.cmd_id = WRITE_REGISTER_CMD,
-		.no_cmd_params = 0x4,
-		.cmd_params = {0x68, 0x01, 0x01, 0xDF},
-		.req = SYNC,
-	},
-	[CMD_ISO14443B_DEMOGAIN] = {
-		.cmd_len = 0x7,
-		.cmd_id = WRITE_REGISTER_CMD,
-		.no_cmd_params = 0x4,
-		.cmd_params = {0x68, 0x01, 0x01, 0x51},
-		.req = SYNC,
-	},
-	[CMD_ISO14443A_PROTOCOL_SELECT] = {
-		.cmd_len = 0x7,
-		.cmd_id = PROTOCOL_SELECT_CMD,
-		.no_cmd_params = 0x4,
-		.cmd_params = {ISO14443A_PROTOCOL_CODE, 0x00, 0x01, 0xA0},
-		.req = SYNC,
-	},
-	[CMD_ISO14443B_PROTOCOL_SELECT] = {
-		.cmd_len = 0x7,
-		.cmd_id = PROTOCOL_SELECT_CMD,
-		.no_cmd_params = 0x4,
-		.cmd_params = {ISO14443B_PROTOCOL_CODE, 0x01, 0x03, 0xFF},
-		.req = SYNC,
-	},
-	[CMD_WTX_RESPONSE] = {
-		.cmd_len = 0x6,
-		.cmd_id = SEND_RECEIVE_CMD,
-		.no_cmd_params = 0x3,
-		.cmd_params = {0xF2, 0x00, TRFLAG_NFCA_STD_FRAME_CRC},
-		.req = ASYNC,
-	},
-	[CMD_FIELD_OFF] = {
-		.cmd_len = 0x5,
-		.cmd_id = PROTOCOL_SELECT_CMD,
-		.no_cmd_params = 0x2,
-		.cmd_params = {0x0, 0x0},
-		.req = SYNC,
-	},
-	[CMD_ISO15693_PROTOCOL_SELECT] = {
-		.cmd_len = 0x5,
-		.cmd_id = PROTOCOL_SELECT_CMD,
-		.no_cmd_params = 0x2,
-		.cmd_params = {ISO15693_PROTOCOL_CODE, 0x0D},
-		.req = SYNC,
-	},
-};
-
-/* st95_digital_cmd_complete_arg stores client context */
-struct st95_digital_cmd_complete_arg {
-	struct sk_buff *skb_resp;
-	nfc_digital_cmd_complete_t complete_cb;
-	void *cb_usrarg;
-	bool rats;
-};
-
-/*
- * structure containing ST95HF driver specific data.
- * @spicontext: structure containing information required
- *	for spi communication between st95hf and host.
- * @ddev: nfc digital device object.
- * @nfcdev: nfc device object.
- * @enable_gpio: gpio used to enable st95hf transceiver.
- * @complete_cb_arg: structure to store various context information
- *	that is passed from nfc requesting thread to the threaded ISR.
- * @st95hf_supply: regulator "consumer" for NFC device.
- * @sendrcv_trflag: last byte of frame send by sendrecv command
- *	of st95hf. This byte contains transmission flag info.
- * @exchange_lock: semaphore used for signaling the st95hf_remove
- *	function that the last outstanding async nfc request is finished.
- * @rm_lock: mutex for ensuring safe access of nfc digital object
- *	from threaded ISR. Usage of this mutex avoids any race between
- *	deletion of the object from st95hf_remove() and its access from
- *	the threaded ISR.
- * @nfcdev_free: flag to have the state of nfc device object.
- *	[alive | died]
- * @current_protocol: current nfc protocol.
- * @current_rf_tech: current rf technology.
- * @fwi: frame waiting index, received in reply of RATS according to
- *	digital protocol.
- */
-struct st95hf_context {
-	struct st95hf_spi_context spicontext;
-	struct nfc_digital_dev *ddev;
-	struct nfc_dev *nfcdev;
-	unsigned int enable_gpio;
-	struct st95_digital_cmd_complete_arg complete_cb_arg;
-	struct regulator *st95hf_supply;
-	unsigned char sendrcv_trflag;
-	struct semaphore exchange_lock;
-	struct mutex rm_lock;
-	bool nfcdev_free;
-	u8 current_protocol;
-	u8 current_rf_tech;
-	int fwi;
-};
-
-/*
- * st95hf_send_recv_cmd() is for sending commands to ST95HF
- * that are described in the cmd_array[]. It can optionally
- * receive the response if the cmd request is of type
- * SYNC. For that to happen caller must pass true to recv_res.
- * For ASYNC request, recv_res is ignored and the
- * function will never try to receive the response on behalf
- * of the caller.
- */
-static int st95hf_send_recv_cmd(struct st95hf_context *st95context,
-				enum st95hf_cmd_list cmd,
-				int no_modif,
-				struct param_list *list_array,
-				bool recv_res)
-{
-	unsigned char spi_cmd_buffer[MAX_CMD_LEN];
-	int i, ret;
-	struct device *dev = &st95context->spicontext.spidev->dev;
-
-	if (cmd_array[cmd].cmd_len > MAX_CMD_LEN)
-		return -EINVAL;
-	if (cmd_array[cmd].no_cmd_params < no_modif)
-		return -EINVAL;
-	if (no_modif && !list_array)
-		return -EINVAL;
-
-	spi_cmd_buffer[0] = ST95HF_COMMAND_SEND;
-	spi_cmd_buffer[1] = cmd_array[cmd].cmd_id;
-	spi_cmd_buffer[2] = cmd_array[cmd].no_cmd_params;
-
-	memcpy(&spi_cmd_buffer[3], cmd_array[cmd].cmd_params,
-	       spi_cmd_buffer[2]);
-
-	for (i = 0; i < no_modif; i++) {
-		if (list_array[i].param_offset >= cmd_array[cmd].no_cmd_params)
-			return -EINVAL;
-		spi_cmd_buffer[3 + list_array[i].param_offset] =
-						list_array[i].new_param_val;
-	}
-
-	ret = st95hf_spi_send(&st95context->spicontext,
-			      spi_cmd_buffer,
-			      cmd_array[cmd].cmd_len,
-			      cmd_array[cmd].req);
-	if (ret) {
-		dev_err(dev, "st95hf_spi_send failed with error %d\n", ret);
-		return ret;
-	}
-
-	if (cmd_array[cmd].req == SYNC && recv_res) {
-		unsigned char st95hf_response_arr[2];
-
-		ret = st95hf_spi_recv_response(&st95context->spicontext,
-					       st95hf_response_arr);
-		if (ret < 0) {
-			dev_err(dev, "spi error from st95hf_spi_recv_response(), err = 0x%x\n",
-				ret);
-			return ret;
-		}
-
-		if (st95hf_response_arr[0]) {
-			dev_err(dev, "st95hf error from st95hf_spi_recv_response(), err = 0x%x\n",
-				st95hf_response_arr[0]);
-			return -EIO;
-		}
-	}
-
-	return 0;
-}
-
-static int st95hf_echo_command(struct st95hf_context *st95context)
-{
-	int result = 0;
-	unsigned char echo_response;
-
-	result = st95hf_send_recv_cmd(st95context, CMD_ECHO, 0, NULL, false);
-	if (result)
-		return result;
-
-	/* If control reached here, response can be taken */
-	result = st95hf_spi_recv_echo_res(&st95context->spicontext,
-					  &echo_response);
-	if (result) {
-		dev_err(&st95context->spicontext.spidev->dev,
-			"err: echo response receieve error = 0x%x\n", result);
-		return result;
-	}
-
-	if (echo_response == ECHORESPONSE)
-		return 0;
-
-	dev_err(&st95context->spicontext.spidev->dev, "err: echo res is 0x%x\n",
-		echo_response);
-
-	return -EIO;
-}
-
-static int secondary_configuration_type4a(struct st95hf_context *stcontext)
-{
-	int result = 0;
-	struct device *dev = &stcontext->nfcdev->dev;
-
-	/* 14443A config setting after select protocol */
-	result = st95hf_send_recv_cmd(stcontext,
-				      CMD_ISO14443A_CONFIG,
-				      0,
-				      NULL,
-				      true);
-	if (result) {
-		dev_err(dev, "type a config cmd, err = 0x%x\n", result);
-		return result;
-	}
-
-	/* 14443A demo gain setting */
-	result = st95hf_send_recv_cmd(stcontext,
-				      CMD_ISO14443A_DEMOGAIN,
-				      0,
-				      NULL,
-				      true);
-	if (result)
-		dev_err(dev, "type a demogain cmd, err = 0x%x\n", result);
-
-	return result;
-}
-
-static int secondary_configuration_type4b(struct st95hf_context *stcontext)
-{
-	int result = 0;
-	struct device *dev = &stcontext->nfcdev->dev;
-
-	result = st95hf_send_recv_cmd(stcontext,
-				      CMD_ISO14443B_DEMOGAIN,
-				      0,
-				      NULL,
-				      true);
-	if (result)
-		dev_err(dev, "type b demogain cmd, err = 0x%x\n", result);
-
-	return result;
-}
-
-static int st95hf_select_protocol(struct st95hf_context *stcontext, int type)
-{
-	int result = 0;
-	struct device *dev;
-
-	dev = &stcontext->nfcdev->dev;
-
-	switch (type) {
-	case NFC_DIGITAL_RF_TECH_106A:
-		stcontext->current_rf_tech = NFC_DIGITAL_RF_TECH_106A;
-		result = st95hf_send_recv_cmd(stcontext,
-					      CMD_ISO14443A_PROTOCOL_SELECT,
-					      0,
-					      NULL,
-					      true);
-		if (result) {
-			dev_err(dev, "protocol sel, err = 0x%x\n",
-				result);
-			return result;
-		}
-
-		/* secondary config. for 14443Type 4A after protocol select */
-		result = secondary_configuration_type4a(stcontext);
-		if (result) {
-			dev_err(dev, "type a secondary config, err = 0x%x\n",
-				result);
-			return result;
-		}
-		break;
-	case NFC_DIGITAL_RF_TECH_106B:
-		stcontext->current_rf_tech = NFC_DIGITAL_RF_TECH_106B;
-		result = st95hf_send_recv_cmd(stcontext,
-					      CMD_ISO14443B_PROTOCOL_SELECT,
-					      0,
-					      NULL,
-					      true);
-		if (result) {
-			dev_err(dev, "protocol sel send, err = 0x%x\n",
-				result);
-			return result;
-		}
-
-		/*
-		 * delay of 5-6 ms is required after select protocol
-		 * command in case of ISO14443 Type B
-		 */
-		usleep_range(50000, 60000);
-
-		/* secondary config. for 14443Type 4B after protocol select */
-		result = secondary_configuration_type4b(stcontext);
-		if (result) {
-			dev_err(dev, "type b secondary config, err = 0x%x\n",
-				result);
-			return result;
-		}
-		break;
-	case NFC_DIGITAL_RF_TECH_ISO15693:
-		stcontext->current_rf_tech = NFC_DIGITAL_RF_TECH_ISO15693;
-		result = st95hf_send_recv_cmd(stcontext,
-					      CMD_ISO15693_PROTOCOL_SELECT,
-					      0,
-					      NULL,
-					      true);
-		if (result) {
-			dev_err(dev, "protocol sel send, err = 0x%x\n",
-				result);
-			return result;
-		}
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static void st95hf_send_st95enable_negativepulse(struct st95hf_context *st95con)
-{
-	/* First make irq_in pin high */
-	gpio_set_value(st95con->enable_gpio, HIGH);
-
-	/* wait for 1 milisecond */
-	usleep_range(1000, 2000);
-
-	/* Make irq_in pin low */
-	gpio_set_value(st95con->enable_gpio, LOW);
-
-	/* wait for minimum interrupt pulse to make st95 active */
-	usleep_range(1000, 2000);
-
-	/* At end make it high */
-	gpio_set_value(st95con->enable_gpio, HIGH);
-}
-
-/*
- * Send a reset sequence over SPI bus (Reset command + wait 3ms +
- * negative pulse on st95hf enable gpio
- */
-static int st95hf_send_spi_reset_sequence(struct st95hf_context *st95context)
-{
-	int result = 0;
-	unsigned char reset_cmd = ST95HF_COMMAND_RESET;
-
-	result = st95hf_spi_send(&st95context->spicontext,
-				 &reset_cmd,
-				 ST95HF_RESET_CMD_LEN,
-				 ASYNC);
-	if (result) {
-		dev_err(&st95context->spicontext.spidev->dev,
-			"spi reset sequence cmd error = %d", result);
-		return result;
-	}
-
-	/* wait for 3 milisecond to complete the controller reset process */
-	usleep_range(3000, 4000);
-
-	/* send negative pulse to make st95hf active */
-	st95hf_send_st95enable_negativepulse(st95context);
-
-	/* wait for 10 milisecond : HFO setup time */
-	usleep_range(10000, 20000);
-
-	return result;
-}
-
-static int st95hf_por_sequence(struct st95hf_context *st95context)
-{
-	int nth_attempt = 1;
-	int result;
-
-	st95hf_send_st95enable_negativepulse(st95context);
-
-	usleep_range(5000, 6000);
-	do {
-		/* send an ECHO command and checks ST95HF response */
-		result = st95hf_echo_command(st95context);
-
-		dev_dbg(&st95context->spicontext.spidev->dev,
-			"response from echo function = 0x%x, attempt = %d\n",
-			result, nth_attempt);
-
-		if (!result)
-			return 0;
-
-		/* send an pulse on IRQ in case of the chip is on sleep state */
-		if (nth_attempt == 2)
-			st95hf_send_st95enable_negativepulse(st95context);
-		else
-			st95hf_send_spi_reset_sequence(st95context);
-
-		/* delay of 50 milisecond */
-		usleep_range(50000, 51000);
-	} while (nth_attempt++ < 3);
-
-	return -ETIMEDOUT;
-}
-
-static int iso14443_config_fdt(struct st95hf_context *st95context, int wtxm)
-{
-	int result = 0;
-	struct device *dev = &st95context->spicontext.spidev->dev;
-	struct nfc_digital_dev *nfcddev = st95context->ddev;
-	unsigned char pp_typeb;
-	struct param_list new_params[2];
-
-	pp_typeb = cmd_array[CMD_ISO14443B_PROTOCOL_SELECT].cmd_params[2];
-
-	if (nfcddev->curr_protocol == NFC_PROTO_ISO14443 &&
-	    st95context->fwi < 4)
-		st95context->fwi = 4;
-
-	new_params[0].param_offset = 2;
-	if (nfcddev->curr_protocol == NFC_PROTO_ISO14443)
-		new_params[0].new_param_val = st95context->fwi;
-	else if (nfcddev->curr_protocol == NFC_PROTO_ISO14443_B)
-		new_params[0].new_param_val = pp_typeb;
-
-	new_params[1].param_offset = 3;
-	new_params[1].new_param_val = wtxm;
-
-	switch (nfcddev->curr_protocol) {
-	case NFC_PROTO_ISO14443:
-		result = st95hf_send_recv_cmd(st95context,
-					      CMD_ISO14443A_PROTOCOL_SELECT,
-					      2,
-					      new_params,
-					      true);
-		if (result) {
-			dev_err(dev, "WTX type a sel proto, err = 0x%x\n",
-				result);
-			return result;
-		}
-
-		/* secondary config. for 14443Type 4A after protocol select */
-		result = secondary_configuration_type4a(st95context);
-		if (result) {
-			dev_err(dev, "WTX type a second. config, err = 0x%x\n",
-				result);
-			return result;
-		}
-		break;
-	case NFC_PROTO_ISO14443_B:
-		result = st95hf_send_recv_cmd(st95context,
-					      CMD_ISO14443B_PROTOCOL_SELECT,
-					      2,
-					      new_params,
-					      true);
-		if (result) {
-			dev_err(dev, "WTX type b sel proto, err = 0x%x\n",
-				result);
-			return result;
-		}
-
-		/* secondary config. for 14443Type 4B after protocol select */
-		result = secondary_configuration_type4b(st95context);
-		if (result) {
-			dev_err(dev, "WTX type b second. config, err = 0x%x\n",
-				result);
-			return result;
-		}
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int st95hf_handle_wtx(struct st95hf_context *stcontext,
-			     bool new_wtx,
-			     int wtx_val)
-{
-	int result = 0;
-	unsigned char val_mm = 0;
-	struct param_list new_params[1];
-	struct nfc_digital_dev *nfcddev = stcontext->ddev;
-	struct device *dev = &stcontext->nfcdev->dev;
-
-	if (new_wtx) {
-		result = iso14443_config_fdt(stcontext, wtx_val & 0x3f);
-		if (result) {
-			dev_err(dev, "Config. setting error on WTX req, err = 0x%x\n",
-				result);
-			return result;
-		}
-
-		/* Send response of wtx with ASYNC as no response expected */
-		new_params[0].param_offset = 1;
-		new_params[0].new_param_val = wtx_val;
-
-		result = st95hf_send_recv_cmd(stcontext,
-					      CMD_WTX_RESPONSE,
-					      1,
-					      new_params,
-					      false);
-		if (result)
-			dev_err(dev, "WTX response send, err = 0x%x\n", result);
-		return result;
-	}
-
-	/* if no new wtx, cofigure with default values */
-	if (nfcddev->curr_protocol == NFC_PROTO_ISO14443)
-		val_mm = cmd_array[CMD_ISO14443A_PROTOCOL_SELECT].cmd_params[3];
-	else if (nfcddev->curr_protocol == NFC_PROTO_ISO14443_B)
-		val_mm = cmd_array[CMD_ISO14443B_PROTOCOL_SELECT].cmd_params[3];
-
-	result = iso14443_config_fdt(stcontext, val_mm);
-	if (result)
-		dev_err(dev, "Default config. setting error after WTX processing, err = 0x%x\n",
-			result);
-
-	return result;
-}
-
-static int st95hf_error_handling(struct st95hf_context *stcontext,
-				 struct sk_buff *skb_resp,
-				 int res_len)
-{
-	int result = 0;
-	unsigned char error_byte;
-	struct device *dev = &stcontext->nfcdev->dev;
-
-	/* First check ST95HF specific error */
-	if (skb_resp->data[0] & ST95HF_ERR_MASK) {
-		if (skb_resp->data[0] == ST95HF_TIMEOUT_ERROR)
-			result = -ETIMEDOUT;
-		else
-			result = -EIO;
-	return  result;
-	}
-
-	/* Check for CRC err only if CRC is present in the tag response */
-	switch (stcontext->current_rf_tech) {
-	case NFC_DIGITAL_RF_TECH_106A:
-		if (stcontext->sendrcv_trflag == TRFLAG_NFCA_STD_FRAME_CRC) {
-			error_byte = skb_resp->data[res_len - 3];
-			if (error_byte & ST95HF_NFCA_CRC_ERR_MASK) {
-				/* CRC error occurred */
-				dev_err(dev, "CRC error, byte received = 0x%x\n",
-					error_byte);
-				result = -EIO;
-			}
-		}
-		break;
-	case NFC_DIGITAL_RF_TECH_106B:
-	case NFC_DIGITAL_RF_TECH_ISO15693:
-		error_byte = skb_resp->data[res_len - 1];
-		if (error_byte & ST95HF_NFCB_CRC_ERR_MASK) {
-			/* CRC error occurred */
-			dev_err(dev, "CRC error, byte received = 0x%x\n",
-				error_byte);
-			result = -EIO;
-		}
-		break;
-	}
-
-	return result;
-}
-
-static int st95hf_response_handler(struct st95hf_context *stcontext,
-				   struct sk_buff *skb_resp,
-				   int res_len)
-{
-	int result = 0;
-	int skb_len;
-	unsigned char val_mm;
-	struct nfc_digital_dev *nfcddev = stcontext->ddev;
-	struct device *dev = &stcontext->nfcdev->dev;
-	struct st95_digital_cmd_complete_arg *cb_arg;
-
-	cb_arg = &stcontext->complete_cb_arg;
-
-	/* Process the response */
-	skb_put(skb_resp, res_len);
-
-	/* Remove st95 header */
-	skb_pull(skb_resp, 2);
-
-	skb_len = skb_resp->len;
-
-	/* check if it is case of RATS request reply & FWI is present */
-	if (nfcddev->curr_protocol == NFC_PROTO_ISO14443 && cb_arg->rats &&
-	    (skb_resp->data[1] & RATS_TB1_PRESENT_MASK)) {
-		if (skb_resp->data[1] & RATS_TA1_PRESENT_MASK)
-			stcontext->fwi =
-				(skb_resp->data[3] & TB1_FWI_MASK) >> 4;
-		else
-			stcontext->fwi =
-				(skb_resp->data[2] & TB1_FWI_MASK) >> 4;
-
-		val_mm = cmd_array[CMD_ISO14443A_PROTOCOL_SELECT].cmd_params[3];
-
-		result = iso14443_config_fdt(stcontext, val_mm);
-		if (result) {
-			dev_err(dev, "error in config_fdt to handle fwi of ATS, error=%d\n",
-				result);
-			return result;
-		}
-	}
-	cb_arg->rats = false;
-
-	/* Remove CRC bytes only if received frames data has an eod (CRC) */
-	switch (stcontext->current_rf_tech) {
-	case NFC_DIGITAL_RF_TECH_106A:
-		if (stcontext->sendrcv_trflag == TRFLAG_NFCA_STD_FRAME_CRC)
-			skb_trim(skb_resp, (skb_len - 5));
-		else
-			skb_trim(skb_resp, (skb_len - 3));
-		break;
-	case NFC_DIGITAL_RF_TECH_106B:
-	case NFC_DIGITAL_RF_TECH_ISO15693:
-		skb_trim(skb_resp, (skb_len - 3));
-		break;
-	}
-
-	return result;
-}
-
-static irqreturn_t st95hf_irq_handler(int irq, void  *st95hfcontext)
-{
-	struct st95hf_context *stcontext  =
-		(struct st95hf_context *)st95hfcontext;
-
-	if (stcontext->spicontext.req_issync) {
-		complete(&stcontext->spicontext.done);
-		stcontext->spicontext.req_issync = false;
-		return IRQ_HANDLED;
-	}
-
-	return IRQ_WAKE_THREAD;
-}
-
-static irqreturn_t st95hf_irq_thread_handler(int irq, void  *st95hfcontext)
-{
-	int result = 0;
-	int res_len;
-	static bool wtx;
-	struct device *dev;
-	struct device *spidevice;
-	struct nfc_digital_dev *nfcddev;
-	struct sk_buff *skb_resp;
-	struct st95hf_context *stcontext  =
-		(struct st95hf_context *)st95hfcontext;
-	struct st95_digital_cmd_complete_arg *cb_arg;
-
-	spidevice = &stcontext->spicontext.spidev->dev;
-
-	/*
-	 * check semaphore, if not down() already, then we don't
-	 * know in which context the ISR is called and surely it
-	 * will be a bug. Note that down() of the semaphore is done
-	 * in the corresponding st95hf_in_send_cmd() and then
-	 * only this ISR should be called. ISR will up() the
-	 * semaphore before leaving. Hence when the ISR is called
-	 * the correct behaviour is down_trylock() should always
-	 * return 1 (indicating semaphore cant be taken and hence no
-	 * change in semaphore count).
-	 * If not, then we up() the semaphore and crash on
-	 * a BUG() !
-	 */
-	if (!down_trylock(&stcontext->exchange_lock)) {
-		up(&stcontext->exchange_lock);
-		WARN(1, "unknown context in ST95HF ISR");
-		return IRQ_NONE;
-	}
-
-	cb_arg = &stcontext->complete_cb_arg;
-	skb_resp = cb_arg->skb_resp;
-
-	mutex_lock(&stcontext->rm_lock);
-	res_len = st95hf_spi_recv_response(&stcontext->spicontext,
-					   skb_resp->data);
-	if (res_len < 0) {
-		dev_err(spidevice, "TISR spi response err = 0x%x\n", res_len);
-		result = res_len;
-		goto end;
-	}
-
-	/* if stcontext->nfcdev_free is true, it means remove already ran */
-	if (stcontext->nfcdev_free) {
-		result = -ENODEV;
-		goto end;
-	}
-
-	dev = &stcontext->nfcdev->dev;
-	nfcddev = stcontext->ddev;
-	if (skb_resp->data[2] == WTX_REQ_FROM_TAG) {
-		/* Request for new FWT from tag */
-		result = st95hf_handle_wtx(stcontext, true, skb_resp->data[3]);
-		if (result)
-			goto end;
-
-		wtx = true;
-		mutex_unlock(&stcontext->rm_lock);
-		return IRQ_HANDLED;
-	}
-
-	result = st95hf_error_handling(stcontext, skb_resp, res_len);
-	if (result)
-		goto end;
-
-	result = st95hf_response_handler(stcontext, skb_resp, res_len);
-	if (result)
-		goto end;
-
-	/*
-	 * If select protocol is done on wtx req. do select protocol
-	 * again with default values
-	 */
-	if (wtx) {
-		wtx = false;
-		result = st95hf_handle_wtx(stcontext, false, 0);
-		if (result)
-			goto end;
-	}
-
-	/* call digital layer callback */
-	cb_arg->complete_cb(stcontext->ddev, cb_arg->cb_usrarg, skb_resp);
-
-	/* up the semaphore before returning */
-	up(&stcontext->exchange_lock);
-	mutex_unlock(&stcontext->rm_lock);
-
-	return IRQ_HANDLED;
-
-end:
-	kfree_skb(skb_resp);
-	wtx = false;
-	cb_arg->rats = false;
-	skb_resp = ERR_PTR(result);
-	/* call of callback with error */
-	cb_arg->complete_cb(stcontext->ddev, cb_arg->cb_usrarg, skb_resp);
-	/* up the semaphore before returning */
-	up(&stcontext->exchange_lock);
-	mutex_unlock(&stcontext->rm_lock);
-	return IRQ_HANDLED;
-}
-
-/* NFC ops functions definition */
-static int st95hf_in_configure_hw(struct nfc_digital_dev *ddev,
-				  int type,
-				  int param)
-{
-	struct st95hf_context *stcontext = nfc_digital_get_drvdata(ddev);
-
-	if (type == NFC_DIGITAL_CONFIG_RF_TECH)
-		return st95hf_select_protocol(stcontext, param);
-
-	if (type == NFC_DIGITAL_CONFIG_FRAMING) {
-		switch (param) {
-		case NFC_DIGITAL_FRAMING_NFCA_SHORT:
-			stcontext->sendrcv_trflag = TRFLAG_NFCA_SHORT_FRAME;
-			break;
-		case NFC_DIGITAL_FRAMING_NFCA_STANDARD:
-			stcontext->sendrcv_trflag = TRFLAG_NFCA_STD_FRAME;
-			break;
-		case NFC_DIGITAL_FRAMING_NFCA_T4T:
-		case NFC_DIGITAL_FRAMING_NFCA_NFC_DEP:
-		case NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A:
-			stcontext->sendrcv_trflag = TRFLAG_NFCA_STD_FRAME_CRC;
-			break;
-		case NFC_DIGITAL_FRAMING_NFCB:
-		case NFC_DIGITAL_FRAMING_ISO15693_INVENTORY:
-		case NFC_DIGITAL_FRAMING_ISO15693_T5T:
-			break;
-		}
-	}
-
-	return 0;
-}
-
-static int rf_off(struct st95hf_context *stcontext)
-{
-	int rc;
-	struct device *dev;
-
-	dev = &stcontext->nfcdev->dev;
-
-	rc = st95hf_send_recv_cmd(stcontext, CMD_FIELD_OFF, 0, NULL, true);
-	if (rc)
-		dev_err(dev, "protocol sel send field off, err = 0x%x\n", rc);
-
-	return rc;
-}
-
-static int st95hf_in_send_cmd(struct nfc_digital_dev *ddev,
-			      struct sk_buff *skb,
-			      u16 timeout,
-			      nfc_digital_cmd_complete_t cb,
-			      void *arg)
-{
-	struct st95hf_context *stcontext = nfc_digital_get_drvdata(ddev);
-	int rc;
-	struct sk_buff *skb_resp;
-	int len_data_to_tag = 0;
-
-	skb_resp = nfc_alloc_recv_skb(MAX_RESPONSE_BUFFER_SIZE, GFP_KERNEL);
-	if (!skb_resp) {
-		rc = -ENOMEM;
-		goto error;
-	}
-
-	switch (stcontext->current_rf_tech) {
-	case NFC_DIGITAL_RF_TECH_106A:
-		len_data_to_tag = skb->len + 1;
-		*skb_put(skb, 1) = stcontext->sendrcv_trflag;
-		break;
-	case NFC_DIGITAL_RF_TECH_106B:
-	case NFC_DIGITAL_RF_TECH_ISO15693:
-		len_data_to_tag = skb->len;
-		break;
-	default:
-		rc = -EINVAL;
-		goto free_skb_resp;
-	}
-
-	skb_push(skb, 3);
-	skb->data[0] = ST95HF_COMMAND_SEND;
-	skb->data[1] = SEND_RECEIVE_CMD;
-	skb->data[2] = len_data_to_tag;
-
-	stcontext->complete_cb_arg.skb_resp = skb_resp;
-	stcontext->complete_cb_arg.cb_usrarg = arg;
-	stcontext->complete_cb_arg.complete_cb = cb;
-
-	if ((skb->data[3] == ISO14443A_RATS_REQ) &&
-	    ddev->curr_protocol == NFC_PROTO_ISO14443)
-		stcontext->complete_cb_arg.rats = true;
-
-	/*
-	 * down the semaphore to indicate to remove func that an
-	 * ISR is pending, note that it will not block here in any case.
-	 * If found blocked, it is a BUG!
-	 */
-	rc = down_killable(&stcontext->exchange_lock);
-	if (rc) {
-		WARN(1, "Semaphore is not found up in st95hf_in_send_cmd\n");
-		return rc;
-	}
-
-	rc = st95hf_spi_send(&stcontext->spicontext, skb->data,
-			     skb->len,
-			     ASYNC);
-	if (rc) {
-		dev_err(&stcontext->nfcdev->dev,
-			"Error %d trying to perform data_exchange", rc);
-		/* up the semaphore since ISR will never come in this case */
-		up(&stcontext->exchange_lock);
-		goto free_skb_resp;
-	}
-
-	kfree_skb(skb);
-
-	return rc;
-
-free_skb_resp:
-	kfree_skb(skb_resp);
-error:
-	return rc;
-}
-
-/* p2p will be supported in a later release ! */
-static int st95hf_tg_configure_hw(struct nfc_digital_dev *ddev,
-				  int type,
-				  int param)
-{
-	return 0;
-}
-
-static int st95hf_tg_send_cmd(struct nfc_digital_dev *ddev,
-			      struct sk_buff *skb,
-			      u16 timeout,
-			      nfc_digital_cmd_complete_t cb,
-			      void *arg)
-{
-	return 0;
-}
-
-static int st95hf_tg_listen(struct nfc_digital_dev *ddev,
-			    u16 timeout,
-			    nfc_digital_cmd_complete_t cb,
-			    void *arg)
-{
-	return 0;
-}
-
-static int st95hf_tg_get_rf_tech(struct nfc_digital_dev *ddev, u8 *rf_tech)
-{
-	return 0;
-}
-
-static int st95hf_switch_rf(struct nfc_digital_dev *ddev, bool on)
-{
-	u8 rf_tech;
-	struct st95hf_context *stcontext = nfc_digital_get_drvdata(ddev);
-
-	rf_tech = ddev->curr_rf_tech;
-
-	if (on)
-		/* switch on RF field */
-		return st95hf_select_protocol(stcontext, rf_tech);
-
-	/* switch OFF RF field */
-	return rf_off(stcontext);
-}
-
-/* TODO st95hf_abort_cmd */
-static void st95hf_abort_cmd(struct nfc_digital_dev *ddev)
-{
-}
-
-static struct nfc_digital_ops st95hf_nfc_digital_ops = {
-	.in_configure_hw = st95hf_in_configure_hw,
-	.in_send_cmd = st95hf_in_send_cmd,
-
-	.tg_listen = st95hf_tg_listen,
-	.tg_configure_hw = st95hf_tg_configure_hw,
-	.tg_send_cmd = st95hf_tg_send_cmd,
-	.tg_get_rf_tech = st95hf_tg_get_rf_tech,
-
-	.switch_rf = st95hf_switch_rf,
-	.abort_cmd = st95hf_abort_cmd,
-};
-
-static const struct spi_device_id st95hf_id[] = {
-	{ "st95hf", 0 },
-	{}
-};
-MODULE_DEVICE_TABLE(spi, st95hf_id);
-
-static int st95hf_probe(struct spi_device *nfc_spi_dev)
-{
-	int ret;
-
-	struct st95hf_context *st95context;
-	struct st95hf_spi_context *spicontext;
-
-	nfc_info(&nfc_spi_dev->dev, "ST95HF driver probe called.\n");
-
-	st95context = devm_kzalloc(&nfc_spi_dev->dev,
-				   sizeof(struct st95hf_context),
-				   GFP_KERNEL);
-	if (!st95context)
-		return -ENOMEM;
-
-	spicontext = &st95context->spicontext;
-
-	spicontext->spidev = nfc_spi_dev;
-
-	st95context->fwi =
-		cmd_array[CMD_ISO14443A_PROTOCOL_SELECT].cmd_params[2];
-
-	if (device_property_present(&nfc_spi_dev->dev, "st95hfvin")) {
-		st95context->st95hf_supply =
-			devm_regulator_get(&nfc_spi_dev->dev,
-					   "st95hfvin");
-		if (IS_ERR(st95context->st95hf_supply)) {
-			dev_err(&nfc_spi_dev->dev, "failed to acquire regulator\n");
-			return PTR_ERR(st95context->st95hf_supply);
-		}
-
-		ret = regulator_enable(st95context->st95hf_supply);
-		if (ret) {
-			dev_err(&nfc_spi_dev->dev, "failed to enable regulator\n");
-			return ret;
-		}
-	}
-
-	init_completion(&spicontext->done);
-	mutex_init(&spicontext->spi_lock);
-
-	/*
-	 * Store spicontext in spi device object for using it in
-	 * remove function
-	 */
-	dev_set_drvdata(&nfc_spi_dev->dev, spicontext);
-
-	st95context->enable_gpio =
-		of_get_named_gpio(nfc_spi_dev->dev.of_node,
-				  "enable-gpio",
-				  0);
-	if (!gpio_is_valid(st95context->enable_gpio)) {
-		dev_err(&nfc_spi_dev->dev, "No valid enable gpio\n");
-		ret = st95context->enable_gpio;
-		goto err_disable_regulator;
-	}
-
-	ret = devm_gpio_request_one(&nfc_spi_dev->dev, st95context->enable_gpio,
-				    GPIOF_DIR_OUT | GPIOF_INIT_HIGH,
-				    "enable_gpio");
-	if (ret)
-		goto err_disable_regulator;
-
-	if (nfc_spi_dev->irq > 0) {
-		if (devm_request_threaded_irq(&nfc_spi_dev->dev,
-					      nfc_spi_dev->irq,
-					      st95hf_irq_handler,
-					      st95hf_irq_thread_handler,
-					      IRQF_TRIGGER_FALLING,
-					      "st95hf",
-					      (void *)st95context) < 0) {
-			dev_err(&nfc_spi_dev->dev, "err: irq request for st95hf is failed\n");
-			ret =  -EINVAL;
-			goto err_disable_regulator;
-		}
-	} else {
-		dev_err(&nfc_spi_dev->dev, "not a valid IRQ associated with ST95HF\n");
-		ret = -EINVAL;
-		goto err_disable_regulator;
-	}
-
-	/*
-	 * First reset SPI to handle warm reset of the system.
-	 * It will put the ST95HF device in Power ON state
-	 * which make the state of device identical to state
-	 * at the time of cold reset of the system.
-	 */
-	ret = st95hf_send_spi_reset_sequence(st95context);
-	if (ret) {
-		dev_err(&nfc_spi_dev->dev, "err: spi_reset_sequence failed\n");
-		goto err_disable_regulator;
-	}
-
-	/* call PowerOnReset sequence of ST95hf to activate it */
-	ret = st95hf_por_sequence(st95context);
-	if (ret) {
-		dev_err(&nfc_spi_dev->dev, "err: por seq failed for st95hf\n");
-		goto err_disable_regulator;
-	}
-
-	/* create NFC dev object and register with NFC Subsystem */
-	st95context->ddev = nfc_digital_allocate_device(&st95hf_nfc_digital_ops,
-							ST95HF_SUPPORTED_PROT,
-							ST95HF_CAPABILITIES,
-							ST95HF_HEADROOM_LEN,
-							ST95HF_TAILROOM_LEN);
-	if (!st95context->ddev) {
-		ret = -ENOMEM;
-		goto err_disable_regulator;
-	}
-
-	st95context->nfcdev = st95context->ddev->nfc_dev;
-	nfc_digital_set_parent_dev(st95context->ddev, &nfc_spi_dev->dev);
-
-	ret =  nfc_digital_register_device(st95context->ddev);
-	if (ret) {
-		dev_err(&st95context->nfcdev->dev, "st95hf registration failed\n");
-		goto err_free_digital_device;
-	}
-
-	/* store st95context in nfc device object */
-	nfc_digital_set_drvdata(st95context->ddev, st95context);
-
-	sema_init(&st95context->exchange_lock, 1);
-	mutex_init(&st95context->rm_lock);
-
-	return ret;
-
-err_free_digital_device:
-	nfc_digital_free_device(st95context->ddev);
-err_disable_regulator:
-	if (st95context->st95hf_supply)
-		regulator_disable(st95context->st95hf_supply);
-
-	return ret;
-}
-
-static int st95hf_remove(struct spi_device *nfc_spi_dev)
-{
-	int result = 0;
-	unsigned char reset_cmd = ST95HF_COMMAND_RESET;
-	struct st95hf_spi_context *spictx = dev_get_drvdata(&nfc_spi_dev->dev);
-
-	struct st95hf_context *stcontext = container_of(spictx,
-							struct st95hf_context,
-							spicontext);
-
-	mutex_lock(&stcontext->rm_lock);
-
-	nfc_digital_unregister_device(stcontext->ddev);
-	nfc_digital_free_device(stcontext->ddev);
-	stcontext->nfcdev_free = true;
-
-	mutex_unlock(&stcontext->rm_lock);
-
-	/* if last in_send_cmd's ISR is pending, wait for it to finish */
-	result = down_killable(&stcontext->exchange_lock);
-	if (result == -EINTR)
-		dev_err(&spictx->spidev->dev, "sleep for semaphore interrupted by signal\n");
-
-	/* next reset the ST95HF controller */
-	result = st95hf_spi_send(&stcontext->spicontext,
-				 &reset_cmd,
-				 ST95HF_RESET_CMD_LEN,
-				 ASYNC);
-	if (result) {
-		dev_err(&spictx->spidev->dev,
-			"ST95HF reset failed in remove() err = %d\n", result);
-		return result;
-	}
-
-	/* wait for 3 ms to complete the controller reset process */
-	usleep_range(3000, 4000);
-
-	/* disable regulator */
-	if (stcontext->st95hf_supply)
-		regulator_disable(stcontext->st95hf_supply);
-
-	return result;
-}
-
-/* Register as SPI protocol driver */
-static struct spi_driver st95hf_driver = {
-	.driver = {
-		.name = "st95hf",
-		.owner = THIS_MODULE,
-	},
-	.id_table = st95hf_id,
-	.probe = st95hf_probe,
-	.remove = st95hf_remove,
-};
-
-module_spi_driver(st95hf_driver);
-
-MODULE_AUTHOR("Shikha Singh <shikha.singh@st.com>");
-MODULE_DESCRIPTION("ST NFC Transceiver ST95HF driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/nfc/st95hf/spi.c b/drivers/nfc/st95hf/spi.c
deleted file mode 100644
index e2d3bbc..0000000
--- a/drivers/nfc/st95hf/spi.c
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * ----------------------------------------------------------------------------
- * drivers/nfc/st95hf/spi.c function definitions for SPI communication
- * ----------------------------------------------------------------------------
- * Copyright (C) 2015 STMicroelectronics Pvt. Ltd. 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 "spi.h"
-
-/* Function to send user provided buffer to ST95HF through SPI */
-int st95hf_spi_send(struct st95hf_spi_context *spicontext,
-		    unsigned char *buffertx,
-		    int datalen,
-		    enum req_type reqtype)
-{
-	struct spi_message m;
-	int result = 0;
-	struct spi_device *spidev = spicontext->spidev;
-	struct spi_transfer tx_transfer = {
-		.tx_buf = buffertx,
-		.len = datalen,
-	};
-
-	mutex_lock(&spicontext->spi_lock);
-
-	if (reqtype == SYNC) {
-		spicontext->req_issync = true;
-		reinit_completion(&spicontext->done);
-	} else {
-		spicontext->req_issync = false;
-	}
-
-	spi_message_init(&m);
-	spi_message_add_tail(&tx_transfer, &m);
-
-	result = spi_sync(spidev, &m);
-	if (result) {
-		dev_err(&spidev->dev, "error: sending cmd to st95hf using SPI = %d\n",
-			result);
-		mutex_unlock(&spicontext->spi_lock);
-		return result;
-	}
-
-	/* return for asynchronous or no-wait case */
-	if (reqtype == ASYNC) {
-		mutex_unlock(&spicontext->spi_lock);
-		return 0;
-	}
-
-	result = wait_for_completion_timeout(&spicontext->done,
-					     msecs_to_jiffies(1000));
-	/* check for timeout or success */
-	if (!result) {
-		dev_err(&spidev->dev, "error: response not ready timeout\n");
-		result = -ETIMEDOUT;
-	} else {
-		result = 0;
-	}
-
-	mutex_unlock(&spicontext->spi_lock);
-
-	return result;
-}
-EXPORT_SYMBOL_GPL(st95hf_spi_send);
-
-/* Function to Receive command Response */
-int st95hf_spi_recv_response(struct st95hf_spi_context *spicontext,
-			     unsigned char *receivebuff)
-{
-	int len = 0;
-	struct spi_transfer tx_takedata;
-	struct spi_message m;
-	struct spi_device *spidev = spicontext->spidev;
-	unsigned char readdata_cmd = ST95HF_COMMAND_RECEIVE;
-	struct spi_transfer t[2] = {
-		{.tx_buf = &readdata_cmd, .len = 1,},
-		{.rx_buf = receivebuff, .len = 2, .cs_change = 1,},
-	};
-
-	int ret = 0;
-
-	memset(&tx_takedata, 0x0, sizeof(struct spi_transfer));
-
-	mutex_lock(&spicontext->spi_lock);
-
-	/* First spi transfer to know the length of valid data */
-	spi_message_init(&m);
-	spi_message_add_tail(&t[0], &m);
-	spi_message_add_tail(&t[1], &m);
-
-	ret = spi_sync(spidev, &m);
-	if (ret) {
-		dev_err(&spidev->dev, "spi_recv_resp, data length error = %d\n",
-			ret);
-		mutex_unlock(&spicontext->spi_lock);
-		return ret;
-	}
-
-	/* As 2 bytes are already read */
-	len = 2;
-
-	/* Support of long frame */
-	if (receivebuff[0] & 0x60)
-		len += (((receivebuff[0] & 0x60) >> 5) << 8) | receivebuff[1];
-	else
-		len += receivebuff[1];
-
-	/* Now make a transfer to read only relevant bytes */
-	tx_takedata.rx_buf = &receivebuff[2];
-	tx_takedata.len = len - 2;
-
-	spi_message_init(&m);
-	spi_message_add_tail(&tx_takedata, &m);
-
-	ret = spi_sync(spidev, &m);
-
-	mutex_unlock(&spicontext->spi_lock);
-	if (ret) {
-		dev_err(&spidev->dev, "spi_recv_resp, data read error = %d\n",
-			ret);
-		return ret;
-	}
-
-	return len;
-}
-EXPORT_SYMBOL_GPL(st95hf_spi_recv_response);
-
-int st95hf_spi_recv_echo_res(struct st95hf_spi_context *spicontext,
-			     unsigned char *receivebuff)
-{
-	unsigned char readdata_cmd = ST95HF_COMMAND_RECEIVE;
-	struct spi_transfer t[2] = {
-		{.tx_buf = &readdata_cmd, .len = 1,},
-		{.rx_buf = receivebuff, .len = 1,},
-	};
-	struct spi_message m;
-	struct spi_device *spidev = spicontext->spidev;
-	int ret = 0;
-
-	mutex_lock(&spicontext->spi_lock);
-
-	spi_message_init(&m);
-	spi_message_add_tail(&t[0], &m);
-	spi_message_add_tail(&t[1], &m);
-	ret = spi_sync(spidev, &m);
-
-	mutex_unlock(&spicontext->spi_lock);
-
-	if (ret)
-		dev_err(&spidev->dev, "recv_echo_res, data read error = %d\n",
-			ret);
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(st95hf_spi_recv_echo_res);
diff --git a/drivers/nfc/st95hf/spi.h b/drivers/nfc/st95hf/spi.h
deleted file mode 100644
index 552d220..0000000
--- a/drivers/nfc/st95hf/spi.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * ---------------------------------------------------------------------------
- * drivers/nfc/st95hf/spi.h functions declarations for SPI communication
- * ---------------------------------------------------------------------------
- * Copyright (C) 2015 STMicroelectronics – 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 __LINUX_ST95HF_SPI_H
-#define __LINUX_ST95HF_SPI_H
-
-#include <linux/spi/spi.h>
-
-/* Basic ST95HF SPI CMDs */
-#define ST95HF_COMMAND_SEND	0x0
-#define ST95HF_COMMAND_RESET	0x1
-#define ST95HF_COMMAND_RECEIVE	0x2
-
-#define ST95HF_RESET_CMD_LEN	0x1
-
-/*
- * structure to contain st95hf spi communication specific information.
- * @req_issync: true for synchronous calls.
- * @spidev: st95hf spi device object.
- * @done: completion structure to wait for st95hf response
- *	for synchronous calls.
- * @spi_lock: mutex to allow only one spi transfer at a time.
- */
-struct st95hf_spi_context {
-	bool req_issync;
-	struct spi_device *spidev;
-	struct completion done;
-	struct mutex spi_lock;
-};
-
-/* flag to differentiate synchronous & asynchronous spi request */
-enum req_type {
-	SYNC,
-	ASYNC,
-};
-
-int st95hf_spi_send(struct st95hf_spi_context *spicontext,
-		    unsigned char *buffertx,
-		    int datalen,
-		    enum req_type reqtype);
-
-int st95hf_spi_recv_response(struct st95hf_spi_context *spicontext,
-			     unsigned char *receivebuff);
-
-int st95hf_spi_recv_echo_res(struct st95hf_spi_context *spicontext,
-			     unsigned char *receivebuff);
-
-#endif
-- 
1.8.2.1

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

* Re: [linux-nfc] [[PATCH v1] 0/6] Support of ST NFC Transceiver
  2017-05-02  6:03 [[linux-nfc][PATCH v1] 0/6] Support of ST NFC Transceiver Shikha Singh
                   ` (5 preceding siblings ...)
  2017-05-02  6:03 ` [[linux-nfc][PATCH v1] 6/6] DRIVERS: NFC: Remove st95hf name reference Shikha Singh
@ 2017-05-02  6:58 ` Marcel Holtmann
  2017-05-02 11:56   ` Shikha SINGH
  6 siblings, 1 reply; 11+ messages in thread
From: Marcel Holtmann @ 2017-05-02  6:58 UTC (permalink / raw)
  To: Shikha Singh
  Cc: Samuel Ortiz, linux-wireless, linux-nfc, manoj.kumar,
	sylvain.fidelis, raphael.collado, MMS_MMY_Applications_SW,
	Rob Herring

Hi Shikha,

> *** V1.0 ***
> This patch series is generated on top of latest
> code available on nfc-next.
> 
> This patch series introduces the following features:
> 
> (a) A generic Digital NFC UART framework.
> The framework itself is an LDISC registered
> with the tty core. Any NFC transciever implementing
> the digital specs and connected on an UART
> (or on an emulated tty, such as /dev/ttyUSBx, /dev/ttyACMx)
> interface with the host, will require this support.
> 
> (b) An ST NFC Transciever core framework. This implements the
> required digital ops and exposes an interface for the
> underlying phy drivers (UART/ SPI). The services of the phy drivers
> are required when the core wants to transmit/receive frames.
> Also it provides helper functions for the phy drivers, for
> example phy drivers registers with the core when it detects
> a Transciever connected on the corresponding interface.
> The framework currently supports NFC Type 2, Type 4A, Type 4B,
> Type 5 tag read/write.
> 
> (c) An ST NFC UART LDisc driver that registers with the
> Digital NFC UART framework, and with the ST NFC Transciever
> core framework as the UART Phy driver.

lets stop this please and move towards serdev support. We really do not need more line disciplines for this.

Regards

Marcel

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

* RE: [linux-nfc] [[PATCH v1] 0/6] Support of ST NFC Transceiver
  2017-05-02  6:58 ` [linux-nfc] [[PATCH v1] 0/6] Support of ST NFC Transceiver Marcel Holtmann
@ 2017-05-02 11:56   ` Shikha SINGH
  0 siblings, 0 replies; 11+ messages in thread
From: Shikha SINGH @ 2017-05-02 11:56 UTC (permalink / raw)
  To: Marcel Holtmann, Samuel Ortiz
  Cc: linux-wireless, linux-nfc, Manoj KUMAR, Sylvain FIDELIS,
	Raphael COLLADO, MMS_MMY_Applications_SW, Rob Herring

Hello Marcel,
          Thanks for making me aware of this new concept of serdev.

Samuel,
	You can pick my release selectively only for SPI interface.

You can skip below 2 patches which were only for UART support -
Patch#1 : A generic Digital NFC UART framework.
Patch#3 : An ST NFC UART LDisc driver ...

 I will make new release for UART support based on serdev.

Thanks & Regards,
Shikha

>-----Original Message-----
>From: Marcel Holtmann [mailto:marcel@holtmann.org]
>Sent: Tuesday, May 02, 2017 12:29 PM
>To: Shikha SINGH <shikha.singh@st.com>
>Cc: Samuel Ortiz <sameo@linux.intel.com>; linux-wireless <linux-
>wireless@vger.kernel.org>; linux-nfc@lists.01.org; Manoj KUMAR
><manoj.kumar@st.com>; Sylvain FIDELIS <sylvain.fidelis@st.com>; Raphael
>COLLADO <Raphael.COLLADO@st.com>; MMS_MMY_Applications_SW
><MMS_MMY_Applications_SW@list.st.com>; Rob Herring
><robh@kernel.org>
>Subject: Re: [linux-nfc] [[PATCH v1] 0/6] Support of ST NFC Transceiver
>
>Hi Shikha,
>
>> *** V1.0 ***
>> This patch series is generated on top of latest code available on
>> nfc-next.
>>
>> This patch series introduces the following features:
>>
>> (a) A generic Digital NFC UART framework.
>> The framework itself is an LDISC registered with the tty core. Any NFC
>> transciever implementing the digital specs and connected on an UART
>> (or on an emulated tty, such as /dev/ttyUSBx, /dev/ttyACMx) interface
>> with the host, will require this support.
>>
>> (b) An ST NFC Transciever core framework. This implements the required
>> digital ops and exposes an interface for the underlying phy drivers
>> (UART/ SPI). The services of the phy drivers are required when the
>> core wants to transmit/receive frames.
>> Also it provides helper functions for the phy drivers, for example phy
>> drivers registers with the core when it detects a Transciever
>> connected on the corresponding interface.
>> The framework currently supports NFC Type 2, Type 4A, Type 4B, Type 5
>> tag read/write.
>>
>> (c) An ST NFC UART LDisc driver that registers with the Digital NFC
>> UART framework, and with the ST NFC Transciever core framework as the
>> UART Phy driver.
>
>lets stop this please and move towards serdev support. We really do not need
>more line disciplines for this.
>
>Regards
>
>Marcel

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

* Re: [[linux-nfc][PATCH v1] 2/6] NFC: nfcst: Add ST NFC Transceiver core framework
  2017-05-02  6:03 ` [[linux-nfc][PATCH v1] 2/6] NFC: nfcst: Add ST NFC Transceiver core framework Shikha Singh
@ 2017-06-25 23:04   ` Samuel Ortiz
  2017-06-30  4:46     ` Shikha SINGH
  0 siblings, 1 reply; 11+ messages in thread
From: Samuel Ortiz @ 2017-06-25 23:04 UTC (permalink / raw)
  To: Shikha Singh
  Cc: linux-wireless, linux-nfc, raunaque.quaiser, manoj.kumar,
	sylvain.fidelis, raphael.collado

Hi Shikha,

On Tue, May 02, 2017 at 02:03:39AM -0400, Shikha Singh wrote:
> +static int nfcst_in_send_cmd(struct nfc_digital_dev *ddev,
> +			     struct sk_buff *skb,
> +			     u16 timeout,
> +			     nfc_digital_cmd_complete_t cb,
> +			     void *arg)
> +{
> +	struct nfcst_context *context = nfc_digital_get_drvdata(ddev);
> +	int rc;
> +	int len_data_to_tag = 0;
> +
> +	if (!context->nfcst_power)
> +		return -EIO;
> +
> +	/*
> +	 * down the semaphore to indicate that last nfcst_in_send_cmd()
> +	 * call is pending, If interrupted, WARN and return !
> +	 */
> +	rc = down_killable(&context->exchange_lock);
> +	if (rc) {
> +		WARN(1, "Semaphore wait is interrupted in nfcst_in_send_cmd\n");
> +		return rc;
> +	}
> +
> +	if (context->trig_config) {
> +		context->trig_config = false;
> +		rc = nfcst_handle_config_fdt(context, false);
> +		if (rc) {
> +			dev_err(&context->nfcdev->dev, "config fdt failed from nfcst_in_send_cmd %d\n",
> +				rc);
> +			return rc;
> +		}
> +	}
> +
> +	switch (context->current_rf_tech) {
> +	case NFC_DIGITAL_RF_TECH_106A:
> +		len_data_to_tag = skb->len + 1;
> +		*skb_put(skb, 1) = context->sendrcv_trflag;
You can't dereference a void pointer. Please fix that as it will most
likely break the build.

Cheers,
Samuel.

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

* RE: [[linux-nfc][PATCH v1] 2/6] NFC: nfcst: Add ST NFC Transceiver core framework
  2017-06-25 23:04   ` Samuel Ortiz
@ 2017-06-30  4:46     ` Shikha SINGH
  0 siblings, 0 replies; 11+ messages in thread
From: Shikha SINGH @ 2017-06-30  4:46 UTC (permalink / raw)
  To: Samuel Ortiz
  Cc: linux-wireless, linux-nfc, Raunaque Mujeeb QUAISER, Manoj KUMAR,
	Sylvain FIDELIS, Raphael COLLADO

Hello Samuel,
            Skb_put()  returns pointer of type unsigned char  (unsigned char *).
 So here we are dereferencing unsigned char pointer not a void pointer. It should not create any issue.

Let me know your view.
Thanks & Regards,
Shikha
 

>-----Original Message-----
>From: Samuel Ortiz [mailto:sameo@linux.intel.com]
>Sent: Monday, June 26, 2017 4:35 AM
>To: Shikha SINGH <shikha.singh@st.com>
>Cc: linux-wireless@vger.kernel.org; linux-nfc@lists.01.org; Raunaque Mujeeb
>QUAISER <raunaque.quaiser@st.com>; Manoj KUMAR
><manoj.kumar@st.com>; Sylvain FIDELIS <sylvain.fidelis@st.com>; Raphael
>COLLADO <Raphael.COLLADO@st.com>
>Subject: Re: [[linux-nfc][PATCH v1] 2/6] NFC: nfcst: Add ST NFC Transceiver
>core framework
>
>Hi Shikha,
>
>On Tue, May 02, 2017 at 02:03:39AM -0400, Shikha Singh wrote:
>> +static int nfcst_in_send_cmd(struct nfc_digital_dev *ddev,
>> +			     struct sk_buff *skb,
>> +			     u16 timeout,
>> +			     nfc_digital_cmd_complete_t cb,
>> +			     void *arg)
>> +{
>> +	struct nfcst_context *context = nfc_digital_get_drvdata(ddev);
>> +	int rc;
>> +	int len_data_to_tag = 0;
>> +
>> +	if (!context->nfcst_power)
>> +		return -EIO;
>> +
>> +	/*
>> +	 * down the semaphore to indicate that last nfcst_in_send_cmd()
>> +	 * call is pending, If interrupted, WARN and return !
>> +	 */
>> +	rc = down_killable(&context->exchange_lock);
>> +	if (rc) {
>> +		WARN(1, "Semaphore wait is interrupted in
>nfcst_in_send_cmd\n");
>> +		return rc;
>> +	}
>> +
>> +	if (context->trig_config) {
>> +		context->trig_config = false;
>> +		rc = nfcst_handle_config_fdt(context, false);
>> +		if (rc) {
>> +			dev_err(&context->nfcdev->dev, "config fdt failed
>from nfcst_in_send_cmd %d\n",
>> +				rc);
>> +			return rc;
>> +		}
>> +	}
>> +
>> +	switch (context->current_rf_tech) {
>> +	case NFC_DIGITAL_RF_TECH_106A:
>> +		len_data_to_tag = skb->len + 1;
>> +		*skb_put(skb, 1) = context->sendrcv_trflag;
>You can't dereference a void pointer. Please fix that as it will most likely break
>the build.
>
>Cheers,
>Samuel.

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

end of thread, other threads:[~2017-06-30  4:48 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-02  6:03 [[linux-nfc][PATCH v1] 0/6] Support of ST NFC Transceiver Shikha Singh
2017-05-02  6:03 ` [[linux-nfc][PATCH v1] 1/6] NFC: add generic UART support Shikha Singh
2017-05-02  6:03 ` [[linux-nfc][PATCH v1] 2/6] NFC: nfcst: Add ST NFC Transceiver core framework Shikha Singh
2017-06-25 23:04   ` Samuel Ortiz
2017-06-30  4:46     ` Shikha SINGH
2017-05-02  6:03 ` [[linux-nfc][PATCH v1] 3/6] NFC: nfcst: Add UART LDisc Driver Shikha Singh
2017-05-02  6:03 ` [[linux-nfc][PATCH v1] 4/6] NFC: nfcst: Add ST NFC SPI Driver Shikha Singh
2017-05-02  6:03 ` [[linux-nfc][PATCH v1] 5/6] DT: bindings: net: nfc: stnfc binding doc Shikha Singh
2017-05-02  6:03 ` [[linux-nfc][PATCH v1] 6/6] DRIVERS: NFC: Remove st95hf name reference Shikha Singh
2017-05-02  6:58 ` [linux-nfc] [[PATCH v1] 0/6] Support of ST NFC Transceiver Marcel Holtmann
2017-05-02 11:56   ` Shikha SINGH

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).