Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f26e30cc authored by Amitkumar Karwar's avatar Amitkumar Karwar Committed by Samuel Ortiz
Browse files

NFC: nfcmrvl: Initial commit for Marvell NFC driver



This patch adds NFC support for Marvell 8897 NFC-over-USB chipset.

Signed-off-by: default avatarAmitkumar Karwar <akarwar@marvell.com>
Signed-off-by: default avatarBing Zhao <bzhao@marvell.com>
Signed-off-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
parent 22c15bf3
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -58,5 +58,6 @@ config NFC_PORT100

source "drivers/nfc/pn544/Kconfig"
source "drivers/nfc/microread/Kconfig"
source "drivers/nfc/nfcmrvl/Kconfig"

endmenu
+1 −0
Original line number Diff line number Diff line
@@ -9,5 +9,6 @@ obj-$(CONFIG_NFC_WILINK) += nfcwilink.o
obj-$(CONFIG_NFC_MEI_PHY)	+= mei_phy.o
obj-$(CONFIG_NFC_SIM)		+= nfcsim.o
obj-$(CONFIG_NFC_PORT100)	+= port100.o
obj-$(CONFIG_NFC_MRVL)		+= nfcmrvl/

ccflags-$(CONFIG_NFC_DEBUG) := -DDEBUG
+23 −0
Original line number Diff line number Diff line
config NFC_MRVL
	tristate "Marvell NFC driver support"
	depends on NFC_NCI
	help
	  The core driver to support Marvell NFC devices.

	  This driver is required if you want to support
	  Marvell NFC device 8897.

	  Say Y here to compile Marvell NFC driver into the kernel or
	  say M to compile it as module.

config NFC_MRVL_USB
	tristate "Marvell NFC-over-USB driver"
	depends on NFC_MRVL && USB
	help
	  Marvell NFC-over-USB driver.

	  This driver provides support for Marvell NFC-over-USB devices:
          8897.

	  Say Y here to compile support for Marvell NFC-over-USB driver
	  into the kernel or say M to compile it as module.
+9 −0
Original line number Diff line number Diff line
#
# Makefile for NFCMRVL NCI based NFC driver
#

nfcmrvl-y += main.o
obj-$(CONFIG_NFC_MRVL) += nfcmrvl.o

nfcmrvl_usb-y += usb.o
obj-$(CONFIG_NFC_MRVL_USB) += nfcmrvl_usb.o
+145 −0
Original line number Diff line number Diff line
/*
 * Marvell NFC driver: major functions
 *
 * Copyright (C) 2014, Marvell International Ltd.
 *
 * This software file (the "File") is distributed by Marvell International
 * Ltd. under the terms of the GNU General Public License Version 2, June 1991
 * (the "License").  You may use, redistribute and/or modify this File in
 * accordance with the terms and conditions of the License, a copy of which
 * is available on the worldwide web at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
 *
 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
 * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
 * this warranty disclaimer.
 */

#include <linux/module.h>
#include <linux/nfc.h>
#include <net/nfc/nci.h>
#include <net/nfc/nci_core.h>
#include "nfcmrvl.h"

#define VERSION "1.0"

static int nfcmrvl_nci_open(struct nci_dev *ndev)
{
	struct nfcmrvl_private *priv = nci_get_drvdata(ndev);
	int err;

	if (test_and_set_bit(NFCMRVL_NCI_RUNNING, &priv->flags))
		return 0;

	err = priv->if_ops->nci_open(priv);

	if (err)
		clear_bit(NFCMRVL_NCI_RUNNING, &priv->flags);

	return err;
}

static int nfcmrvl_nci_close(struct nci_dev *ndev)
{
	struct nfcmrvl_private *priv = nci_get_drvdata(ndev);

	if (!test_and_clear_bit(NFCMRVL_NCI_RUNNING, &priv->flags))
		return 0;

	priv->if_ops->nci_close(priv);

	return 0;
}

static int nfcmrvl_nci_send(struct nci_dev *ndev, struct sk_buff *skb)
{
	struct nfcmrvl_private *priv = nci_get_drvdata(ndev);

	nfc_info(priv->dev, "send entry, len %d\n", skb->len);

	skb->dev = (void *)ndev;

	if (!test_bit(NFCMRVL_NCI_RUNNING, &priv->flags))
		return -EBUSY;

	return priv->if_ops->nci_send(priv, skb);
}

static struct nci_ops nfcmrvl_nci_ops = {
	.open = nfcmrvl_nci_open,
	.close = nfcmrvl_nci_close,
	.send = nfcmrvl_nci_send,
};

struct nfcmrvl_private *nfcmrvl_nci_register_dev(void *drv_data,
						 struct nfcmrvl_if_ops *ops,
						 struct device *dev)
{
	struct nfcmrvl_private *priv;
	int rc;
	u32 protocols;

	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
	if (!priv)
		return ERR_PTR(-ENOMEM);

	priv->drv_data = drv_data;
	priv->if_ops = ops;
	priv->dev = dev;

	protocols = NFC_PROTO_JEWEL_MASK
		| NFC_PROTO_MIFARE_MASK | NFC_PROTO_FELICA_MASK
		| NFC_PROTO_ISO14443_MASK
		| NFC_PROTO_ISO14443_B_MASK
		| NFC_PROTO_NFC_DEP_MASK;

	priv->ndev = nci_allocate_device(&nfcmrvl_nci_ops, protocols, 0, 0);
	if (!priv->ndev) {
		nfc_err(dev, "nci_allocate_device failed");
		return ERR_PTR(-ENOMEM);
	}

	nci_set_drvdata(priv->ndev, priv);

	rc = nci_register_device(priv->ndev);
	if (rc) {
		nfc_err(dev, "nci_register_device failed %d", rc);
		nci_free_device(priv->ndev);
		return ERR_PTR(rc);
	}

	nfc_info(dev, "registered with nci successfully\n");
	return priv;
}
EXPORT_SYMBOL_GPL(nfcmrvl_nci_register_dev);

void nfcmrvl_nci_unregister_dev(struct nfcmrvl_private *priv)
{
	struct nci_dev *ndev = priv->ndev;

	nci_unregister_device(ndev);
	nci_free_device(ndev);
	kfree(priv);
}
EXPORT_SYMBOL_GPL(nfcmrvl_nci_unregister_dev);

int nfcmrvl_nci_recv_frame(struct nfcmrvl_private *priv, void *data, int count)
{
	struct sk_buff *skb;

	skb = nci_skb_alloc(priv->ndev, count, GFP_ATOMIC);
	if (!skb)
		return -ENOMEM;

	memcpy(skb_put(skb, count), data, count);
	nci_recv_frame(priv->ndev, skb);

	return count;
}
EXPORT_SYMBOL_GPL(nfcmrvl_nci_recv_frame);

MODULE_AUTHOR("Marvell International Ltd.");
MODULE_DESCRIPTION("Marvell NFC driver ver " VERSION);
MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL v2");
Loading