Skip to content

Commit

Permalink
Merge tag 'nfc-next-4.2-1' of git://git.kernel.org/pub/scm/linux/kern…
Browse files Browse the repository at this point in the history
…el/git/sameo/nfc-next

Samuel Ortiz says:

====================
NFC 4.2 pull request

This is the NFC pull request for 4.2.

- NCI drivers can now define their own handlers for processing
  proprietary NCI responses and notifications.

- NFC vendors can use a dedicated netlink API to send their own
  proprietary commands, like e.g. all commands needed to implement
  vendor specific manufacturing tools.

- A new generic NCI over UART driver against which any NCI chipset
  running on top of a serial interface can register.

- The st21nfcb driver is renamed to st-nci as it can and will support
  most of ST Microelectronics NCI chipsets.

- The st21nfcb driver can put its CLF in hibernate mode and save
  significant amount of power.

- A few st21nfcb minor fixes.

- The NXP NCI driver now supports ACPI enumeration.

- The Marvell NCI driver now supports both USB and serial
  physical interfaces.

- The Marvell NCI drivers also supports NCI frames being muxed
  over HCI. This is a setting that can be defined by a DT property.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Jun 15, 2015
2 parents cadfaf4 + d0dcad8 commit 023033b
Show file tree
Hide file tree
Showing 47 changed files with 1,988 additions and 625 deletions.
29 changes: 29 additions & 0 deletions Documentation/devicetree/bindings/net/nfc/nfcmrvl.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
* Marvell International Ltd. NCI NFC Controller

Required properties:
- compatible: Should be "mrvl,nfc-uart".

Optional SoC specific properties:
- pinctrl-names: Contains only one value - "default".
- pintctrl-0: Specifies the pin control groups used for this controller.
- reset-n-io: Output GPIO pin used to reset the chip (active low).
- hci-muxed: Specifies that the chip is muxing NCI over HCI frames.

Optional UART-based chip specific properties:
- flow-control: Specifies that the chip is using RTS/CTS.
- break-control: Specifies that the chip needs specific break management.

Example (for ARM-based BeagleBoard Black with 88W8887 on UART5):

&uart5 {
status = "okay";

nfcmrvluart: nfcmrvluart@5 {
compatible = "mrvl,nfc-uart";

reset-n-io = <&gpio3 16 0>;

hci-muxed;
flow-control;
}
};
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
* STMicroelectronics SAS. ST21NFCB NFC Controller
* STMicroelectronics SAS. ST NCI NFC Controller

Required properties:
- compatible: Should be "st,st21nfcb-i2c".
- compatible: Should be "st,st21nfcb-i2c" or "st,st21nfcc-i2c".
- clock-frequency: I²C work frequency.
- reg: address on the bus
- interrupt-parent: phandle for the interrupt gpio controller
Expand Down
4 changes: 4 additions & 0 deletions Documentation/devicetree/bindings/net/nfc/trf7970a.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ Optional SoC Specific Properties:
"IRQ Status Read" erratum.
- en2-rf-quirk: Specify that the trf7970a being used has the "EN2 RF"
erratum.
- t5t-rmb-extra-byte-quirk: Specify that the trf7970a has the erratum
where an extra byte is returned by Read Multiple Block commands issued
to Type 5 tags.

Example (for ARM-based BeagleBone with TRF7970A on SPI1):

Expand All @@ -39,6 +42,7 @@ Example (for ARM-based BeagleBone with TRF7970A on SPI1):
autosuspend-delay = <30000>;
irq-status-read-quirk;
en2-rf-quirk;
t5t-rmb-extra-byte-quirk;
status = "okay";
};
};
2 changes: 1 addition & 1 deletion Documentation/nfc/nfc-hci.txt
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ This must be done from a context that can sleep.
PHY Management
--------------

The physical link (i2c, ...) management is defined by the following struture:
The physical link (i2c, ...) management is defined by the following structure:

struct nfc_phy_ops {
int (*write)(void *dev_id, struct sk_buff *skb);
Expand Down
2 changes: 1 addition & 1 deletion drivers/nfc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,6 @@ source "drivers/nfc/pn544/Kconfig"
source "drivers/nfc/microread/Kconfig"
source "drivers/nfc/nfcmrvl/Kconfig"
source "drivers/nfc/st21nfca/Kconfig"
source "drivers/nfc/st21nfcb/Kconfig"
source "drivers/nfc/st-nci/Kconfig"
source "drivers/nfc/nxp-nci/Kconfig"
endmenu
4 changes: 1 addition & 3 deletions drivers/nfc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,5 @@ obj-$(CONFIG_NFC_PORT100) += port100.o
obj-$(CONFIG_NFC_MRVL) += nfcmrvl/
obj-$(CONFIG_NFC_TRF7970A) += trf7970a.o
obj-$(CONFIG_NFC_ST21NFCA) += st21nfca/
obj-$(CONFIG_NFC_ST21NFCB) += st21nfcb/
obj-$(CONFIG_NFC_ST_NCI) += st-nci/
obj-$(CONFIG_NFC_NXP_NCI) += nxp-nci/

ccflags-$(CONFIG_NFC_DEBUG) := -DDEBUG
3 changes: 0 additions & 3 deletions drivers/nfc/microread/i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,6 @@ static int microread_i2c_read(struct microread_i2c_phy *phy,
static irqreturn_t microread_i2c_irq_thread_fn(int irq, void *phy_id)
{
struct microread_i2c_phy *phy = phy_id;
struct i2c_client *client;
struct sk_buff *skb = NULL;
int r;

Expand All @@ -220,8 +219,6 @@ static irqreturn_t microread_i2c_irq_thread_fn(int irq, void *phy_id)
return IRQ_NONE;
}

client = phy->i2c_dev;

if (phy->hard_fault != 0)
return IRQ_HANDLED;

Expand Down
11 changes: 11 additions & 0 deletions drivers/nfc/nfcmrvl/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,14 @@ config NFC_MRVL_USB

Say Y here to compile support for Marvell NFC-over-USB driver
into the kernel or say M to compile it as module.

config NFC_MRVL_UART
tristate "Marvell NFC-over-UART driver"
depends on NFC_MRVL && NFC_NCI_UART
help
Marvell NFC-over-UART driver.

This driver provides support for Marvell NFC-over-UART devices

Say Y here to compile support for Marvell NFC-over-UART driver
into the kernel or say M to compile it as module.
3 changes: 3 additions & 0 deletions drivers/nfc/nfcmrvl/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@ obj-$(CONFIG_NFC_MRVL) += nfcmrvl.o

nfcmrvl_usb-y += usb.o
obj-$(CONFIG_NFC_MRVL_USB) += nfcmrvl_usb.o

nfcmrvl_uart-y += uart.o
obj-$(CONFIG_NFC_MRVL_UART) += nfcmrvl_uart.o
134 changes: 113 additions & 21 deletions drivers/nfc/nfcmrvl/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
*/

#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/of_gpio.h>
#include <linux/nfc.h>
#include <net/nfc/nci.h>
#include <net/nfc/nci_core.h>
Expand Down Expand Up @@ -63,20 +66,25 @@ static int nfcmrvl_nci_send(struct nci_dev *ndev, struct sk_buff *skb)
if (!test_bit(NFCMRVL_NCI_RUNNING, &priv->flags))
return -EBUSY;

if (priv->config.hci_muxed) {
unsigned char *hdr;
unsigned char len = skb->len;

hdr = (char *) skb_push(skb, NFCMRVL_HCI_EVENT_HEADER_SIZE);
hdr[0] = NFCMRVL_HCI_COMMAND_CODE;
hdr[1] = NFCMRVL_HCI_OGF;
hdr[2] = NFCMRVL_HCI_OCF;
hdr[3] = len;
}

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

static int nfcmrvl_nci_setup(struct nci_dev *ndev)
{
__u8 val;

val = NFCMRVL_GPIO_PIN_NFC_NOT_ALLOWED;
nci_set_config(ndev, NFCMRVL_NOT_ALLOWED_ID, 1, &val);
val = NFCMRVL_GPIO_PIN_NFC_ACTIVE;
nci_set_config(ndev, NFCMRVL_ACTIVE_ID, 1, &val);
val = NFCMRVL_EXT_COEX_ENABLE;
nci_set_config(ndev, NFCMRVL_EXT_COEX_ID, 1, &val);
__u8 val = 1;

nci_set_config(ndev, NFCMRVL_PB_BAIL_OUT, 1, &val);
return 0;
}

Expand All @@ -88,11 +96,13 @@ static struct nci_ops nfcmrvl_nci_ops = {
};

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

priv = kzalloc(sizeof(*priv), GFP_KERNEL);
Expand All @@ -103,13 +113,30 @@ struct nfcmrvl_private *nfcmrvl_nci_register_dev(void *drv_data,
priv->if_ops = ops;
priv->dev = dev;

memcpy(&priv->config, pdata, sizeof(*pdata));

if (priv->config.reset_n_io) {
rc = devm_gpio_request_one(dev,
priv->config.reset_n_io,
GPIOF_OUT_INIT_LOW,
"nfcmrvl_reset_n");
if (rc < 0)
nfc_err(dev, "failed to request reset_n io\n");
}

if (priv->config.hci_muxed)
headroom = NFCMRVL_HCI_EVENT_HEADER_SIZE;

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

priv->ndev = nci_allocate_device(&nfcmrvl_nci_ops, protocols, 0, 0);
priv->ndev = nci_allocate_device(&nfcmrvl_nci_ops, protocols,
headroom, 0);
if (!priv->ndev) {
nfc_err(dev, "nci_allocate_device failed\n");
rc = -ENOMEM;
Expand All @@ -118,6 +145,8 @@ struct nfcmrvl_private *nfcmrvl_nci_register_dev(void *drv_data,

nci_set_drvdata(priv->ndev, priv);

nfcmrvl_chip_reset(priv);

rc = nci_register_device(priv->ndev);
if (rc) {
nfc_err(dev, "nci_register_device failed %d\n", rc);
Expand All @@ -144,21 +173,84 @@ void nfcmrvl_nci_unregister_dev(struct nfcmrvl_private *priv)
}
EXPORT_SYMBOL_GPL(nfcmrvl_nci_unregister_dev);

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

skb = nci_skb_alloc(priv->ndev, count, GFP_ATOMIC);
if (!skb)
return -ENOMEM;
if (priv->config.hci_muxed) {
if (skb->data[0] == NFCMRVL_HCI_EVENT_CODE &&
skb->data[1] == NFCMRVL_HCI_NFC_EVENT_CODE) {
/* Data packet, let's extract NCI payload */
skb_pull(skb, NFCMRVL_HCI_EVENT_HEADER_SIZE);
} else {
/* Skip this packet */
kfree_skb(skb);
return 0;
}
}

memcpy(skb_put(skb, count), data, count);
nci_recv_frame(priv->ndev, skb);
if (test_bit(NFCMRVL_NCI_RUNNING, &priv->flags))
nci_recv_frame(priv->ndev, skb);
else {
/* Drop this packet since nobody wants it */
kfree_skb(skb);
return 0;
}

return count;
return 0;
}
EXPORT_SYMBOL_GPL(nfcmrvl_nci_recv_frame);

void nfcmrvl_chip_reset(struct nfcmrvl_private *priv)
{
/*
* This function does not take care if someone is using the device.
* To be improved.
*/

if (priv->config.reset_n_io) {
nfc_info(priv->dev, "reset the chip\n");
gpio_set_value(priv->config.reset_n_io, 0);
usleep_range(5000, 10000);
gpio_set_value(priv->config.reset_n_io, 1);
} else
nfc_info(priv->dev, "no reset available on this interface\n");
}

#ifdef CONFIG_OF

int nfcmrvl_parse_dt(struct device_node *node,
struct nfcmrvl_platform_data *pdata)
{
int reset_n_io;

reset_n_io = of_get_named_gpio(node, "reset-n-io", 0);
if (reset_n_io < 0) {
pr_info("no reset-n-io config\n");
reset_n_io = 0;
} else if (!gpio_is_valid(reset_n_io)) {
pr_err("invalid reset-n-io GPIO\n");
return reset_n_io;
}
pdata->reset_n_io = reset_n_io;

if (of_find_property(node, "hci-muxed", NULL))
pdata->hci_muxed = 1;
else
pdata->hci_muxed = 0;

return 0;
}

#else

int nfcmrvl_parse_dt(struct device_node *node,
struct nfcmrvl_platform_data *pdata)
{
return -ENODEV;
}

#endif
EXPORT_SYMBOL_GPL(nfcmrvl_parse_dt);

MODULE_AUTHOR("Marvell International Ltd.");
MODULE_DESCRIPTION("Marvell NFC driver ver " VERSION);
MODULE_VERSION(VERSION);
Expand Down
Loading

0 comments on commit 023033b

Please sign in to comment.