Skip to content

Commit

Permalink
Merge tag 'nfc-next-4.3-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.3 pull request

This is the NFC pull request for 4.3.
With this one we have:

- A new driver for Samsung's S3FWRN5 NFC chipset. In order to
  properly support this driver, a few NCI core routines needed
  to be exported. Future drivers like Intel's Fields Peak will
  benefit from this.

- SPI support as a physical transport for STM st21nfcb.

- An additional netlink API for sending replies back to userspace
  from vendor commands.

- 2 small fixes for TI's trf7970a

- A few st-nci fixes.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Aug 24, 2015
2 parents 751a587 + 29e7692 commit d9893d1
Show file tree
Hide file tree
Showing 29 changed files with 2,180 additions and 61 deletions.
27 changes: 27 additions & 0 deletions Documentation/devicetree/bindings/net/nfc/s3fwrn5.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
* Samsung S3FWRN5 NCI NFC Controller

Required properties:
- compatible: Should be "samsung,s3fwrn5-i2c".
- reg: address on the bus
- interrupt-parent: phandle for the interrupt gpio controller
- interrupts: GPIO interrupt to which the chip is connected
- s3fwrn5,en-gpios: Output GPIO pin used for enabling/disabling the chip
- s3fwrn5,fw-gpios: Output GPIO pin used to enter firmware mode and
sleep/wakeup control

Example:

&hsi2c_4 {
status = "okay";
s3fwrn5@27 {
compatible = "samsung,s3fwrn5-i2c";

reg = <0x27>;

interrupt-parent = <&gpa1>;
interrupts = <3 0 0>;

s3fwrn5,en-gpios = <&gpf1 4 0>;
s3fwrn5,fw-gpios = <&gpj0 2 0>;
};
};
31 changes: 31 additions & 0 deletions Documentation/devicetree/bindings/net/nfc/st-nci-spi.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
* STMicroelectronics SAS. ST NCI NFC Controller

Required properties:
- compatible: Should be "st,st21nfcb-spi"
- spi-max-frequency: Maximum SPI frequency (<= 10000000).
- interrupt-parent: phandle for the interrupt gpio controller
- interrupts: GPIO interrupt to which the chip is connected
- reset-gpios: Output GPIO pin used to reset the ST21NFCB

Optional SoC Specific Properties:
- pinctrl-names: Contains only one value - "default".
- pintctrl-0: Specifies the pin control groups used for this controller.

Example (for ARM-based BeagleBoard xM with ST21NFCB on SPI4):

&mcspi4 {

status = "okay";

st21nfcb: st21nfcb@0 {

compatible = "st,st21nfcb-spi";

clock-frequency = <4000000>;

interrupt-parent = <&gpio5>;
interrupts = <2 IRQ_TYPE_EDGE_RISING>;

reset-gpios = <&gpio5 29 GPIO_ACTIVE_HIGH>;
};
};
6 changes: 6 additions & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -8881,6 +8881,12 @@ L: linux-media@vger.kernel.org
S: Supported
F: drivers/media/i2c/s5k5baf.c

SAMSUNG S3FWRN5 NFC DRIVER
M: Robert Baldyga <r.baldyga@samsung.com>
L: linux-nfc@lists.01.org (moderated for non-subscribers)
S: Supported
F: drivers/nfc/s3fwrn5

SAMSUNG SOC CLOCK DRIVERS
M: Sylwester Nawrocki <s.nawrocki@samsung.com>
M: Tomasz Figa <tomasz.figa@gmail.com>
Expand Down
1 change: 1 addition & 0 deletions drivers/nfc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,5 @@ source "drivers/nfc/nfcmrvl/Kconfig"
source "drivers/nfc/st21nfca/Kconfig"
source "drivers/nfc/st-nci/Kconfig"
source "drivers/nfc/nxp-nci/Kconfig"
source "drivers/nfc/s3fwrn5/Kconfig"
endmenu
1 change: 1 addition & 0 deletions drivers/nfc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ obj-$(CONFIG_NFC_TRF7970A) += trf7970a.o
obj-$(CONFIG_NFC_ST21NFCA) += st21nfca/
obj-$(CONFIG_NFC_ST_NCI) += st-nci/
obj-$(CONFIG_NFC_NXP_NCI) += nxp-nci/
obj-$(CONFIG_NFC_S3FWRN5) += s3fwrn5/
19 changes: 19 additions & 0 deletions drivers/nfc/s3fwrn5/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
config NFC_S3FWRN5
tristate
---help---
Core driver for Samsung S3FWRN5 NFC chip. Contains core utilities
of chip. It's intended to be used by PHYs to avoid duplicating lots
of common code.

config NFC_S3FWRN5_I2C
tristate "Samsung S3FWRN5 I2C support"
depends on NFC_NCI && I2C
select NFC_S3FWRN5
default n
---help---
This module adds support for an I2C interface to the S3FWRN5 chip.
Select this if your platform is using the I2C bus.

To compile this driver as a module, choose m here. The module will
be called s3fwrn5_i2c.ko.
Say N if unsure.
11 changes: 11 additions & 0 deletions drivers/nfc/s3fwrn5/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#
# Makefile for Samsung S3FWRN5 NFC driver
#

s3fwrn5-objs = core.o firmware.o nci.o
s3fwrn5_i2c-objs = i2c.o

obj-$(CONFIG_NFC_S3FWRN5) += s3fwrn5.o
obj-$(CONFIG_NFC_S3FWRN5_I2C) += s3fwrn5_i2c.o

ccflags-$(CONFIG_NFC_DEBUG) := -DDEBUG
219 changes: 219 additions & 0 deletions drivers/nfc/s3fwrn5/core.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
/*
* NCI based driver for Samsung S3FWRN5 NFC chip
*
* Copyright (C) 2015 Samsung Electrnoics
* Robert Baldyga <r.baldyga@samsung.com>
*
* 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 or later, 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 <net/nfc/nci_core.h>

#include "s3fwrn5.h"
#include "firmware.h"
#include "nci.h"

#define S3FWRN5_NFC_PROTOCOLS (NFC_PROTO_JEWEL_MASK | \
NFC_PROTO_MIFARE_MASK | \
NFC_PROTO_FELICA_MASK | \
NFC_PROTO_ISO14443_MASK | \
NFC_PROTO_ISO14443_B_MASK | \
NFC_PROTO_ISO15693_MASK)

static int s3fwrn5_firmware_update(struct s3fwrn5_info *info)
{
bool need_update;
int ret;

s3fwrn5_fw_init(&info->fw_info, "sec_s3fwrn5_firmware.bin");

/* Update firmware */

s3fwrn5_set_wake(info, false);
s3fwrn5_set_mode(info, S3FWRN5_MODE_FW);

ret = s3fwrn5_fw_setup(&info->fw_info);
if (ret < 0)
return ret;

need_update = s3fwrn5_fw_check_version(&info->fw_info,
info->ndev->manufact_specific_info);
if (!need_update)
goto out;

dev_info(&info->ndev->nfc_dev->dev, "Detected new firmware version\n");

ret = s3fwrn5_fw_download(&info->fw_info);
if (ret < 0)
goto out;

/* Update RF configuration */

s3fwrn5_set_mode(info, S3FWRN5_MODE_NCI);

s3fwrn5_set_wake(info, true);
ret = s3fwrn5_nci_rf_configure(info, "sec_s3fwrn5_rfreg.bin");
s3fwrn5_set_wake(info, false);

out:
s3fwrn5_set_mode(info, S3FWRN5_MODE_COLD);
s3fwrn5_fw_cleanup(&info->fw_info);
return ret;
}

static int s3fwrn5_nci_open(struct nci_dev *ndev)
{
struct s3fwrn5_info *info = nci_get_drvdata(ndev);

if (s3fwrn5_get_mode(info) != S3FWRN5_MODE_COLD)
return -EBUSY;

s3fwrn5_set_mode(info, S3FWRN5_MODE_NCI);
s3fwrn5_set_wake(info, true);

return 0;
}

static int s3fwrn5_nci_close(struct nci_dev *ndev)
{
struct s3fwrn5_info *info = nci_get_drvdata(ndev);

s3fwrn5_set_wake(info, false);
s3fwrn5_set_mode(info, S3FWRN5_MODE_COLD);

return 0;
}

static int s3fwrn5_nci_send(struct nci_dev *ndev, struct sk_buff *skb)
{
struct s3fwrn5_info *info = nci_get_drvdata(ndev);
int ret;

mutex_lock(&info->mutex);

if (s3fwrn5_get_mode(info) != S3FWRN5_MODE_NCI) {
mutex_unlock(&info->mutex);
return -EINVAL;
}

ret = s3fwrn5_write(info, skb);
if (ret < 0)
kfree_skb(skb);

mutex_unlock(&info->mutex);
return ret;
}

static int s3fwrn5_nci_post_setup(struct nci_dev *ndev)
{
struct s3fwrn5_info *info = nci_get_drvdata(ndev);
int ret;

ret = s3fwrn5_firmware_update(info);
if (ret < 0)
goto out;

/* NCI core reset */

s3fwrn5_set_mode(info, S3FWRN5_MODE_NCI);
s3fwrn5_set_wake(info, true);

ret = nci_core_reset(info->ndev);
if (ret < 0)
goto out;

ret = nci_core_init(info->ndev);

out:
return ret;
}

static struct nci_ops s3fwrn5_nci_ops = {
.open = s3fwrn5_nci_open,
.close = s3fwrn5_nci_close,
.send = s3fwrn5_nci_send,
.post_setup = s3fwrn5_nci_post_setup,
};

int s3fwrn5_probe(struct nci_dev **ndev, void *phy_id, struct device *pdev,
struct s3fwrn5_phy_ops *phy_ops, unsigned int max_payload)
{
struct s3fwrn5_info *info;
int ret;

info = devm_kzalloc(pdev, sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;

info->phy_id = phy_id;
info->pdev = pdev;
info->phy_ops = phy_ops;
info->max_payload = max_payload;
mutex_init(&info->mutex);

s3fwrn5_set_mode(info, S3FWRN5_MODE_COLD);

s3fwrn5_nci_get_prop_ops(&s3fwrn5_nci_ops.prop_ops,
&s3fwrn5_nci_ops.n_prop_ops);

info->ndev = nci_allocate_device(&s3fwrn5_nci_ops,
S3FWRN5_NFC_PROTOCOLS, 0, 0);
if (!info->ndev)
return -ENOMEM;

nci_set_parent_dev(info->ndev, pdev);
nci_set_drvdata(info->ndev, info);

ret = nci_register_device(info->ndev);
if (ret < 0) {
nci_free_device(info->ndev);
return ret;
}

info->fw_info.ndev = info->ndev;

*ndev = info->ndev;

return ret;
}
EXPORT_SYMBOL(s3fwrn5_probe);

void s3fwrn5_remove(struct nci_dev *ndev)
{
struct s3fwrn5_info *info = nci_get_drvdata(ndev);

s3fwrn5_set_mode(info, S3FWRN5_MODE_COLD);

nci_unregister_device(ndev);
nci_free_device(ndev);
}
EXPORT_SYMBOL(s3fwrn5_remove);

int s3fwrn5_recv_frame(struct nci_dev *ndev, struct sk_buff *skb,
enum s3fwrn5_mode mode)
{
switch (mode) {
case S3FWRN5_MODE_NCI:
return nci_recv_frame(ndev, skb);
case S3FWRN5_MODE_FW:
return s3fwrn5_fw_recv_frame(ndev, skb);
default:
return -ENODEV;
}
}
EXPORT_SYMBOL(s3fwrn5_recv_frame);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Samsung S3FWRN5 NFC driver");
MODULE_AUTHOR("Robert Baldyga <r.baldyga@samsung.com>");
Loading

0 comments on commit d9893d1

Please sign in to comment.