Skip to content

Commit

Permalink
NFC: nfcmrvl: Initial commit for Marvell NFC driver
Browse files Browse the repository at this point in the history
This patch adds NFC support for Marvell 8897 NFC-over-USB chipset.

Signed-off-by: Amitkumar Karwar <[email protected]>
Signed-off-by: Bing Zhao <[email protected]>
Signed-off-by: Samuel Ortiz <[email protected]>
  • Loading branch information
Amitkumar Karwar authored and Samuel Ortiz committed Jan 7, 2014
1 parent 22c15bf commit f26e30c
Show file tree
Hide file tree
Showing 7 changed files with 680 additions and 0 deletions.
1 change: 1 addition & 0 deletions drivers/nfc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,6 @@ config NFC_PORT100

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

endmenu
1 change: 1 addition & 0 deletions drivers/nfc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 23 additions & 0 deletions drivers/nfc/nfcmrvl/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
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 changes: 9 additions & 0 deletions drivers/nfc/nfcmrvl/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#
# 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 changes: 145 additions & 0 deletions drivers/nfc/nfcmrvl/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/*
* 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");
42 changes: 42 additions & 0 deletions drivers/nfc/nfcmrvl/nfcmrvl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/**
* Marvell NFC driver
*
* 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.
**/

/* Define private flags: */
#define NFCMRVL_NCI_RUNNING 1

#define NFCMRVL_NCI_MAX_EVENT_SIZE 260

struct nfcmrvl_private {
struct nci_dev *ndev;
unsigned long flags;
void *drv_data;
struct device *dev;
struct nfcmrvl_if_ops *if_ops;
};

struct nfcmrvl_if_ops {
int (*nci_open) (struct nfcmrvl_private *priv);
int (*nci_close) (struct nfcmrvl_private *priv);
int (*nci_send) (struct nfcmrvl_private *priv, struct sk_buff *skb);
};

void nfcmrvl_nci_unregister_dev(struct nfcmrvl_private *priv);
int nfcmrvl_nci_recv_frame(struct nfcmrvl_private *priv, void *data, int count);
struct nfcmrvl_private *nfcmrvl_nci_register_dev(void *drv_data,
struct nfcmrvl_if_ops *ops,
struct device *dev);
Loading

0 comments on commit f26e30c

Please sign in to comment.